diff --git a/packages/cli/cli/versions.yml b/packages/cli/cli/versions.yml index 49c4168f527..66af38f0c63 100644 --- a/packages/cli/cli/versions.yml +++ b/packages/cli/cli/versions.yml @@ -1,13 +1,18 @@ +- changelogEntry: + - summary: Support parsing alpha and beta version numbers of Fern generators + type: internal + irVersion: 53 + version: 0.45.0-rc37 - changelogEntry: - summary: | - The OpenAPI importer now supports importing deep object query parameters. To do this, you will + The OpenAPI importer now supports importing deep object query parameters. To do this, you will need to configure a setting in your `generators.yml` ```yml - api: - specs: + api: + specs: - openapi: ./path/to/openapi.yml - settings: + settings: object-query-paramaters: true ``` type: fix @@ -26,11 +31,11 @@ The Fern CLI now supports roles and viewers in your docs configuration, if you are on the enteprise plan for docs: ```yml docs.ym - roles: + roles: - internal - beta-users - enterprise-users - + navigation: - section: Internal Section viewers: @@ -80,21 +85,21 @@ - changelogEntry: - summary: | - The Conjure importer now brings in endpoint level descriptions. + The Conjure importer now brings in endpoint level descriptions. type: feat irVersion: 53 version: 0.45.0-rc27 - changelogEntry: - summary: | - `fern check` handles validating unions that contain base properties. + `fern check` handles validating unions that contain base properties. type: feat irVersion: 53 version: 0.45.0-rc26 - changelogEntry: - summary: | - The Fern CLI temporarily does not support RBAC/Audiences (they will be added in again shortly). + The Fern CLI temporarily does not support RBAC/Audiences (they will be added in again shortly). type: internal irVersion: 53 version: 0.45.0-rc25 @@ -126,14 +131,14 @@ type: feat - summary: | The RBAC config model is now renamed to `roles` and `viewers`: - + ```yml docs.yml roles: - internal - + navigation: - section: Internal Section - viewers: + viewers: - internal contents: - page: Internal Page @@ -152,7 +157,7 @@ # all audiences must be declared at the top level audiences: - internal - + navigation: - section: Internal Section audience: internal # audience is optional @@ -179,7 +184,7 @@ version: 0.45.0-rc18 - changelogEntry: - - summary: | + - summary: | - Improved union example generation by increasing depth for better handling of recursive structures. - Updated Conjure importer to represent binary types as bytes for requests and file for responses in Fern. - Added detailed error messages when 'fern docs dev' fails, accessible with --log-level debug. @@ -189,7 +194,7 @@ - changelogEntry: - summary: | - The Conjure importer now correctly keys the union subvariant by the property of the discriminant. + The Conjure importer now correctly keys the union subvariant by the property of the discriminant. ```conjure union: @@ -205,10 +210,10 @@ union: discriminant: type types: - square: + square: type: Square key: square - circle: + circle: type: Circle key: circle ``` @@ -262,8 +267,8 @@ irVersion: 53 version: 0.45.0-rc10 -- changelogEntry: - - summary: | +- changelogEntry: + - summary: | Improved JSON Schema generation for object extensions and const values: - Object extensions are now properly represented using `allOf` in the JSON Schema - Literal values (string and boolean) are now correctly represented using `const` in the JSON Schema @@ -271,29 +276,29 @@ irVersion: 53 version: 0.45.0-rc9 -- changelogEntry: - - summary: | +- changelogEntry: + - summary: | Add `#!/usr/bin/env node` to the CLI to prevent runtime errors. type: internal irVersion: 53 version: 0.45.0-rc8 -- changelogEntry: - - summary: | +- changelogEntry: + - summary: | Stop minifying the CLI to prevent javascript runtime errors. type: internal irVersion: 53 version: 0.45.0-rc7 -- changelogEntry: - - summary: | +- changelogEntry: + - summary: | Update the CLI package.json to include the correct files. type: fix irVersion: 53 version: 0.45.0-rc6 -- changelogEntry: - - summary: | +- changelogEntry: + - summary: | Introduce a new command `fern jsonschema --type ` that outputs the JSON Schema for a given type in your Fern Definition. @@ -304,43 +309,43 @@ irVersion: 53 version: 0.45.0-rc5 -- changelogEntry: - - summary: | - SCIM has been added as a common initialism. +- changelogEntry: + - summary: | + SCIM has been added as a common initialism. type: chore irVersion: 53 version: 0.45.0-rc4 - changelogEntry: - - summary: | - Numerous fixes to the Conjure API Importer such as reading in request bodies and query parameters. + - summary: | + Numerous fixes to the Conjure API Importer such as reading in request bodies and query parameters. type: fix irVersion: 53 version: 0.45.0-rc3 - changelogEntry: - - summary: | - The CLI now generates endpoint examples for undiscriminated unions that are recusive. + - summary: | + The CLI now generates endpoint examples for undiscriminated unions that are recusive. type: fix irVersion: 53 version: 0.45.0-rc2 - changelogEntry: - - summary: | - The OpenAPI importer now generates streaming examples based on OpenAPI examples. + - summary: | + The OpenAPI importer now generates streaming examples based on OpenAPI examples. type: fix irVersion: 53 version: 0.45.0-rc1 - changelogEntry: - - summary: | - The Docs now support rendering `additionalProperties` in the API Playground so that users can send out arbitrary key,value pairs. + - summary: | + The Docs now support rendering `additionalProperties` in the API Playground so that users can send out arbitrary key,value pairs. type: fix irVersion: 53 version: 0.45.0-rc0 - changelogEntry: - - summary: Several improvements to the conjure importer. + - summary: Several improvements to the conjure importer. type: fix irVersion: 53 version: 0.44.11 diff --git a/packages/cli/semver-utils/src/__test__/isVersionAhead.test.ts b/packages/cli/semver-utils/src/__test__/isVersionAhead.test.ts index 99be8f5e050..fc55b1bc76e 100644 --- a/packages/cli/semver-utils/src/__test__/isVersionAhead.test.ts +++ b/packages/cli/semver-utils/src/__test__/isVersionAhead.test.ts @@ -2,29 +2,47 @@ import { isVersionAhead } from "../isVersionAhead"; describe("isVersionAhead", () => { it.each` - a | b | expected - ${"0.0.191"} | ${"0.0.190"} | ${true} - ${"0.0.191"} | ${"0.0.191"} | ${false} - ${"0.0.191"} | ${"0.0.192"} | ${false} - ${"0.0.191"} | ${"0.0.191-4-abc"} | ${false} - ${"0.0.191-4-abc"} | ${"0.0.191"} | ${true} - ${"0.0.191-2-abc"} | ${"0.0.191-1-abc"} | ${true} - ${"0.0.191-11-abc"} | ${"0.0.191-2-abc"} | ${true} - ${"0.0.191-rc0"} | ${"0.0.190"} | ${true} - ${"0.0.191-rc0"} | ${"0.0.191"} | ${false} - ${"0.0.191-rc0"} | ${"0.0.192"} | ${false} - ${"0.0.191-rc0"} | ${"0.0.191-4-abc"} | ${false} - ${"0.0.191-rc2"} | ${"0.0.191-rc1"} | ${true} - ${"0.0.191-rc2"} | ${"0.0.191-rc11"} | ${false} - ${"0.1.3-rc9-2-g23dc3c70"} | ${"0.1.3-rc8-1-g23dc3c70"} | ${true} - ${"0.1.3-rc9-2-g23dc3c70"} | ${"0.1.3-rc8-3-g23dc3c70"} | ${true} - ${"0.1.3-rc9-2-g23dc3c70"} | ${"0.1.3-rc9-1-g23dc3c70"} | ${true} - ${"0.1.3-rc9-2-g23dc3c70"} | ${"0.1.3-rc9-3-g23dc3c70"} | ${false} - ${"0.1.3-rc9-1-g23dc3c70"} | ${"0.1.3-rc8"} | ${true} - ${"0.1.3-rc9-1-g23dc3c70"} | ${"0.1.3-rc9"} | ${true} - ${"0.1.3-rc9-1-g23dc3c70"} | ${"0.1.3-rc10"} | ${false} - ${"0.1.3-rc9-1-g23dc3c70"} | ${"0.1.2"} | ${true} - ${"0.1.3-rc9-1-g23dc3c70"} | ${"0.1.3"} | ${false} + a | b | expected + ${"0.0.191"} | ${"0.0.190"} | ${true} + ${"0.0.191"} | ${"0.0.191"} | ${false} + ${"0.0.191"} | ${"0.0.192"} | ${false} + ${"0.0.191"} | ${"0.0.191-4-abc"} | ${false} + ${"0.0.191"} | ${"0.0.191-beta0"} | ${true} + ${"0.0.191"} | ${"0.0.191-alpha0"} | ${true} + ${"0.0.191"} | ${"0.0.191-beta.0"} | ${true} + ${"0.0.191"} | ${"0.0.191-alpha.0"} | ${true} + ${"0.0.191-4-abc"} | ${"0.0.191"} | ${true} + ${"0.0.191-2-abc"} | ${"0.0.191-1-abc"} | ${true} + ${"0.0.191-11-abc"} | ${"0.0.191-2-abc"} | ${true} + ${"0.0.191-rc0"} | ${"0.0.190"} | ${true} + ${"0.0.191-rc0"} | ${"0.0.191"} | ${false} + ${"0.0.191-rc0"} | ${"0.0.192"} | ${false} + ${"0.0.191-rc0"} | ${"0.0.191-4-abc"} | ${false} + ${"0.0.191-rc2"} | ${"0.0.191-rc1"} | ${true} + ${"0.0.191-rc2"} | ${"0.0.191-rc11"} | ${false} + ${"0.0.191-rc.2"} | ${"0.0.191-rc.1"} | ${true} + ${"0.0.191-rc.2"} | ${"0.0.191-rc.11"} | ${false} + ${"0.0.191-rc-2"} | ${"0.0.191-rc-1"} | ${true} + ${"0.0.191-rc-2"} | ${"0.0.191-rc-11"} | ${false} + ${"0.1.3-rc9-2-g23dc3c70"} | ${"0.1.3-rc8-1-g23dc3c70"} | ${true} + ${"0.1.3-rc9-2-g23dc3c70"} | ${"0.1.3-rc8-3-g23dc3c70"} | ${true} + ${"0.1.3-rc9-2-g23dc3c70"} | ${"0.1.3-rc9-1-g23dc3c70"} | ${true} + ${"0.1.3-rc9-2-g23dc3c70"} | ${"0.1.3-rc9-3-g23dc3c70"} | ${false} + ${"0.1.3-rc.9-2-g23dc3c70"} | ${"0.1.3-rc.9-1-g23dc3c70"} | ${true} + ${"0.1.3-rc.9-2-g23dc3c70"} | ${"0.1.3-rc.9-3-g23dc3c70"} | ${false} + ${"0.1.3-rc9-1-g23dc3c70"} | ${"0.1.3-rc8"} | ${true} + ${"0.1.3-rc9-1-g23dc3c70"} | ${"0.1.3-rc9"} | ${true} + ${"0.1.3-rc9-1-g23dc3c70"} | ${"0.1.3-rc10"} | ${false} + ${"0.1.3-rc9-1-g23dc3c70"} | ${"0.1.2"} | ${true} + ${"0.1.3-rc9-1-g23dc3c70"} | ${"0.1.3"} | ${false} + ${"0.0.191-rc0"} | ${"0.0.190-beta.0"} | ${true} + ${"0.0.191-rc0"} | ${"0.0.190-alpha.0"} | ${true} + ${"0.1.3-rc9-2-g23dc3c70"} | ${"0.0.190-beta.0"} | ${true} + ${"0.1.3-rc9-2-g23dc3c70"} | ${"0.0.190-alpha.0"} | ${true} + ${"0.0.190-beta.0"} | ${"0.0.190-beta.1"} | ${false} + ${"0.0.190-beta.1"} | ${"0.0.190-beta.0"} | ${true} + ${"0.0.190-beta.0"} | ${"0.0.190-alpha.0"} | ${true} + ${"0.0.190-alpha.0"} | ${"0.0.190-beta.0"} | ${false} `("$a vs. $b", ({ a, b, expected }) => { expect(isVersionAhead(a, b)).toBe(expected); }); diff --git a/packages/cli/semver-utils/src/isVersionAhead.ts b/packages/cli/semver-utils/src/isVersionAhead.ts index d394ac2922b..7eb53e3fb31 100644 --- a/packages/cli/semver-utils/src/isVersionAhead.ts +++ b/packages/cli/semver-utils/src/isVersionAhead.ts @@ -30,6 +30,9 @@ export function isVersionAhead(a: string, b: string): boolean { case "release": case "post-release-commit": return false; + case "alpha": + case "beta": + return true; } return ( @@ -38,11 +41,48 @@ export function isVersionAhead(a: string, b: string): boolean { ); } - if (bVersion.type === "post-rc-commit") { - if (aVersion.releaseCandidateIndex !== bVersion.releaseCandidateIndex) { - return aVersion.releaseCandidateIndex > bVersion.releaseCandidateIndex; + if (aVersion.type === "post-rc-commit") { + switch (bVersion.type) { + case "release": + case "post-release-commit": + return false; + case "alpha": + case "beta": + return true; + } + + if (bVersion.type === "post-rc-commit") { + if (aVersion.releaseCandidateIndex !== bVersion.releaseCandidateIndex) { + return aVersion.releaseCandidateIndex > bVersion.releaseCandidateIndex; + } + return aVersion.commitIndex > bVersion.commitIndex; + } + } + + if (aVersion.type === "beta") { + switch (bVersion.type) { + case "release": + case "post-release-commit": + case "rc": + case "post-rc-commit": + return false; + case "alpha": + return true; } - return aVersion.commitIndex > bVersion.commitIndex; + + return aVersion.index > bVersion.index; + } + + if (aVersion.type === "alpha") { + switch (bVersion.type) { + case "release": + case "post-release-commit": + case "rc": + case "post-rc-commit": + return false; + } + + return aVersion.index > bVersion.index; } // if here, 'a' is a post-rc-commit and 'b' is not, so just recursively run diff --git a/packages/cli/semver-utils/src/parseVersion.ts b/packages/cli/semver-utils/src/parseVersion.ts index 94e981febed..48df024c1b0 100644 --- a/packages/cli/semver-utils/src/parseVersion.ts +++ b/packages/cli/semver-utils/src/parseVersion.ts @@ -1,9 +1,23 @@ const POST_RELEASE_COMMIT_VERSION_REGEX = /^([0-9]+)\.([0-9]+)\.([0-9]+)-([0-9]+)-([a-z0-9])+$/; -const POST_RC_COMMIT_VERSION_REGEX = /^([0-9]+)\.([0-9]+)\.([0-9]+)-rc([0-9]+)-([0-9]+)-([a-z0-9])+$/; -const RC_VERSION_REGEX = /^([0-9]+)\.([0-9]+)\.([0-9]+)-rc([0-9]+)$/; +const POST_RC_COMMIT_VERSION_REGEX = /^([0-9]+)\.([0-9]+)\.([0-9]+)-rc[.-]?([0-9]+)-([0-9]+)-([a-z0-9])+$/; +const RC_VERSION_REGEX = /^([0-9]+)\.([0-9]+)\.([0-9]+)-rc[.-]?([0-9]+)$/; const RELEASE_REGEX = /^([0-9]+)\.([0-9]+)\.([0-9]+)$/; +const ALPHA_VERSION_REGEX = /^([0-9]+)\.([0-9]+)\.([0-9]+)-alpha[.-]?([0-9]+)$/; +const BETA_VERSION_REGEX = /^([0-9]+)\.([0-9]+)\.([0-9]+)-beta[.-]?([0-9]+)$/; -export type ParsedVersion = Release | PostReleaseCommit | ReleaseCandidate | PostReleaseCandidateCommit; +export interface BaseVersion { + major: number; + minor: number; + patch: number; +} + +export type ParsedVersion = + | Release + | PostReleaseCommit + | ReleaseCandidate + | PostReleaseCandidateCommit + | AlphaRelease + | BetaRelease; export interface ReleaseCandidate extends BaseVersion { type: "rc"; @@ -25,13 +39,54 @@ export interface PostReleaseCommit extends BaseVersion { commitIndex: number; } -export interface BaseVersion { - major: number; - minor: number; - patch: number; +export interface AlphaRelease extends BaseVersion { + type: "alpha"; + index: number; +} +export interface BetaRelease extends BaseVersion { + type: "beta"; + index: number; } export function parseVersion(versionString: string): ParsedVersion { + const alphaMatch = versionString.match(ALPHA_VERSION_REGEX); + if (alphaMatch != null) { + const [_, major, minor, patch, index] = alphaMatch; + const parsedMajor = parseNumber(major); + const parsedMinor = parseNumber(minor); + const parsedPatch = parseNumber(patch); + const parsedIndex = parseNumber(index); + if (parsedMajor == null || parsedMinor == null || parsedPatch == null || parsedIndex == null) { + throw new Error("Cannot parse alpha version: " + versionString); + } + return { + type: "alpha", + major: parsedMajor, + minor: parsedMinor, + patch: parsedPatch, + index: parsedIndex + }; + } + + const betaMatch = versionString.match(BETA_VERSION_REGEX); + if (betaMatch != null) { + const [_, major, minor, patch, index] = betaMatch; + const parsedMajor = parseNumber(major); + const parsedMinor = parseNumber(minor); + const parsedPatch = parseNumber(patch); + const parsedIndex = parseNumber(index); + if (parsedMajor == null || parsedMinor == null || parsedPatch == null || parsedIndex == null) { + throw new Error("Cannot parse beta version: " + versionString); + } + return { + type: "beta", + major: parsedMajor, + minor: parsedMinor, + patch: parsedPatch, + index: parsedIndex + }; + } + const postReleaseCommitMatch = versionString.match(POST_RELEASE_COMMIT_VERSION_REGEX); if (postReleaseCommitMatch != null) { const [_, major, minor, patch, commitIndex] = postReleaseCommitMatch;