From bddac278764c4ade6998e3797d91d32d0e1d5d6b Mon Sep 17 00:00:00 2001 From: James Henry Date: Mon, 11 Sep 2023 19:59:28 +0400 Subject: [PATCH 01/13] feat(core): alpha implementation of `nx release` --- docs/generated/cli/release.md | 170 ++ docs/generated/devkit/NxJsonConfiguration.md | 9 + docs/generated/devkit/Workspace.md | 13 + docs/generated/manifests/menus.json | 24 + docs/generated/manifests/packages.json | 29 + docs/generated/packages-metadata.json | 29 + .../js/executors/release-publish.json | 32 + .../js/generators/release-version.json | 50 + .../packages/nx/documents/release.md | 170 ++ docs/map.json | 5 + docs/shared/reference/sitemap.md | 3 + e2e/release/jest.config.ts | 13 + e2e/release/project.json | 10 + .../src/__snapshots__/release.test.ts.snap | 76 + e2e/release/src/release.test.ts | 101 + e2e/release/tsconfig.json | 13 + e2e/release/tsconfig.spec.json | 20 + package.json | 4 + packages/js/executors.json | 6 + packages/js/generators.json | 6 + packages/js/package.json | 4 + .../executors/release-publish/format-bytes.ts | 30 + .../src/executors/release-publish/log-tar.ts | 76 + .../release-publish/release-publish.impl.ts | 110 ++ .../src/executors/release-publish/schema.d.ts | 5 + .../src/executors/release-publish/schema.json | 22 + .../release-version/release-version.spec.ts | 127 ++ .../release-version/release-version.ts | 210 ++ .../generators/release-version/schema.d.ts | 1 + .../generators/release-version/schema.json | 41 + ...ate-workspace-with-package-dependencies.ts | 62 + .../release-version/utils/package.ts | 43 + ...resolve-local-package-dependencies.spec.ts | 410 ++++ .../resolve-local-package-dependencies.ts | 105 + .../utils/resolve-version-spec.spec.ts | 83 + .../utils/resolve-version-spec.ts | 30 + packages/nx/package.json | 1 + .../plugins/package-json-workspaces.spec.ts | 12 + .../nx/src/command-line/affected/affected.ts | 5 +- .../nx/src/command-line/generate/generate.ts | 2 +- packages/nx/src/command-line/nx-commands.ts | 2 + .../nx/src/command-line/release/changelog.ts | 163 ++ .../command-line/release/command-object.ts | 165 ++ .../release/config/config.spec.ts | 48 + .../src/command-line/release/config/config.ts | 12 + .../config/create-release-groups.spec.ts | 249 +++ .../release/config/create-release-groups.ts | 225 +++ .../nx/src/command-line/release/publish.ts | 213 ++ .../nx/src/command-line/release/release.ts | 1 + .../nx/src/command-line/release/utils/git.ts | 158 ++ .../src/command-line/release/utils/github.ts | 391 ++++ .../release/utils/launch-editor.ts | 43 + .../command-line/release/utils/print-diff.ts | 16 + .../utils/resolve-nx-json-error-message.ts | 68 + .../command-line/release/utils/semver.spec.ts | 70 + .../src/command-line/release/utils/semver.ts | 42 + .../nx/src/command-line/release/version.ts | 428 ++++ .../nx/src/command-line/run-many/run-many.ts | 5 +- packages/nx/src/command-line/run/run-one.ts | 5 +- .../yargs-utils/shared-options.ts | 4 +- packages/nx/src/config/nx-json.ts | 34 + packages/nx/src/config/workspaces.spec.ts | 28 +- .../nx/src/generators/utils/deprecated.ts | 1 + .../build-nodes/project-json.spec.ts | 21 +- packages/nx/src/tasks-runner/run-command.ts | 7 +- packages/nx/src/utils/command-line-utils.ts | 35 +- packages/nx/src/utils/package-json.spec.ts | 12 + packages/nx/src/utils/package-json.ts | 9 + pnpm-lock.yaml | 1740 +++++++++-------- 69 files changed, 5489 insertions(+), 868 deletions(-) create mode 100644 docs/generated/cli/release.md create mode 100644 docs/generated/packages/js/executors/release-publish.json create mode 100644 docs/generated/packages/js/generators/release-version.json create mode 100644 docs/generated/packages/nx/documents/release.md create mode 100644 e2e/release/jest.config.ts create mode 100644 e2e/release/project.json create mode 100644 e2e/release/src/__snapshots__/release.test.ts.snap create mode 100644 e2e/release/src/release.test.ts create mode 100644 e2e/release/tsconfig.json create mode 100644 e2e/release/tsconfig.spec.json create mode 100644 packages/js/src/executors/release-publish/format-bytes.ts create mode 100644 packages/js/src/executors/release-publish/log-tar.ts create mode 100644 packages/js/src/executors/release-publish/release-publish.impl.ts create mode 100644 packages/js/src/executors/release-publish/schema.d.ts create mode 100644 packages/js/src/executors/release-publish/schema.json create mode 100644 packages/js/src/generators/release-version/release-version.spec.ts create mode 100644 packages/js/src/generators/release-version/release-version.ts create mode 100644 packages/js/src/generators/release-version/schema.d.ts create mode 100644 packages/js/src/generators/release-version/schema.json create mode 100644 packages/js/src/generators/release-version/test-utils/create-workspace-with-package-dependencies.ts create mode 100644 packages/js/src/generators/release-version/utils/package.ts create mode 100644 packages/js/src/generators/release-version/utils/resolve-local-package-dependencies.spec.ts create mode 100644 packages/js/src/generators/release-version/utils/resolve-local-package-dependencies.ts create mode 100644 packages/js/src/generators/release-version/utils/resolve-version-spec.spec.ts create mode 100644 packages/js/src/generators/release-version/utils/resolve-version-spec.ts create mode 100644 packages/nx/src/command-line/release/changelog.ts create mode 100644 packages/nx/src/command-line/release/command-object.ts create mode 100644 packages/nx/src/command-line/release/config/config.spec.ts create mode 100644 packages/nx/src/command-line/release/config/config.ts create mode 100644 packages/nx/src/command-line/release/config/create-release-groups.spec.ts create mode 100644 packages/nx/src/command-line/release/config/create-release-groups.ts create mode 100644 packages/nx/src/command-line/release/publish.ts create mode 100644 packages/nx/src/command-line/release/release.ts create mode 100644 packages/nx/src/command-line/release/utils/git.ts create mode 100644 packages/nx/src/command-line/release/utils/github.ts create mode 100644 packages/nx/src/command-line/release/utils/launch-editor.ts create mode 100644 packages/nx/src/command-line/release/utils/print-diff.ts create mode 100644 packages/nx/src/command-line/release/utils/resolve-nx-json-error-message.ts create mode 100644 packages/nx/src/command-line/release/utils/semver.spec.ts create mode 100644 packages/nx/src/command-line/release/utils/semver.ts create mode 100644 packages/nx/src/command-line/release/version.ts diff --git a/docs/generated/cli/release.md b/docs/generated/cli/release.md new file mode 100644 index 0000000000000..3c242248c8b0a --- /dev/null +++ b/docs/generated/cli/release.md @@ -0,0 +1,170 @@ +--- +title: 'release - CLI command' +description: '**ALPHA**: Orchestrate versioning and publishing of applications and libraries' +--- + +# release + +**ALPHA**: Orchestrate versioning and publishing of applications and libraries + +## Usage + +```shell +nx release +``` + +Install `nx` globally to invoke the command directly using `nx`, or use `npx nx`, `yarn nx`, or `pnpm nx`. + +## Options + +### dryRun + +Type: `boolean` + +Default: `false` + +Preview the changes without updating files/creating releases + +### groups + +Type: `string` + +One or more release groups to target with the current command. + +### help + +Type: `boolean` + +Show help + +### projects + +Type: `string` + +Projects to run. (comma/space delimited project names and/or patterns) + +### version + +Type: `boolean` + +Show version number + +## Subcommands + +### version + +Create a version and release for one or more applications and libraries + +```shell +nx release version [specifier] +``` + +#### Options + +##### help + +Type: `boolean` + +Show help + +##### specifier + +Type: `string` + +Exact version or semver keyword to apply to the selected release group. + +##### version + +Type: `boolean` + +Show version number + +### changelog + +Generate a changelog for one or more projects, and optionally push to Github + +```shell +nx release changelog [version] +``` + +#### Options + +##### from + +Type: `string` + +The git reference to use as the start of the changelog. If not set it will attempt to resolve the latest tag and use that + +##### gitRemote + +Type: `string` + +Default: `origin` + +Alternate git remote in the form {user}/{repo} on which to create the Github release (useful for testing) + +##### help + +Type: `boolean` + +Show help + +##### interactive + +Type: `boolean` + +##### tagVersionPrefix + +Type: `string` + +Default: `v` + +Prefix to apply to the version when creating the Github release tag + +##### to + +Type: `string` + +Default: `HEAD` + +The git reference to use as the end of the changelog + +##### version + +Type: `string` + +The version to create a Github release and changelog for + +### publish + +Publish a versioned project to a registry + +```shell +nx release publish +``` + +#### Options + +##### help + +Type: `boolean` + +Show help + +##### registry + +Type: `string` + +The registry to publish to + +##### tag + +Type: `string` + +The distribution tag to apply to the published package + +##### version + +Type: `boolean` + +Show version number diff --git a/docs/generated/devkit/NxJsonConfiguration.md b/docs/generated/devkit/NxJsonConfiguration.md index eaa6e3478f0a1..9a47653e6923a 100644 --- a/docs/generated/devkit/NxJsonConfiguration.md +++ b/docs/generated/devkit/NxJsonConfiguration.md @@ -29,6 +29,7 @@ Nx.json configuration - [npmScope](../../devkit/documents/NxJsonConfiguration#npmscope): string - [plugins](../../devkit/documents/NxJsonConfiguration#plugins): string[] - [pluginsConfig](../../devkit/documents/NxJsonConfiguration#pluginsconfig): Record<string, unknown> +- [release](../../devkit/documents/NxJsonConfiguration#release): NxReleaseConfiguration - [targetDefaults](../../devkit/documents/NxJsonConfiguration#targetdefaults): TargetDefaults - [tasksRunnerOptions](../../devkit/documents/NxJsonConfiguration#tasksrunneroptions): Object - [workspaceLayout](../../devkit/documents/NxJsonConfiguration#workspacelayout): Object @@ -163,6 +164,14 @@ Configuration for Nx Plugins --- +### release + +• `Optional` **release**: `NxReleaseConfiguration` + +**ALPHA**: Configuration for `nx release` (versioning and publishing of applications and libraries) + +--- + ### targetDefaults • `Optional` **targetDefaults**: `TargetDefaults` diff --git a/docs/generated/devkit/Workspace.md b/docs/generated/devkit/Workspace.md index 87a5801b57b99..239db1d5767c5 100644 --- a/docs/generated/devkit/Workspace.md +++ b/docs/generated/devkit/Workspace.md @@ -28,6 +28,7 @@ use ProjectsConfigurations or NxJsonConfiguration - [plugins](../../devkit/documents/Workspace#plugins): string[] - [pluginsConfig](../../devkit/documents/Workspace#pluginsconfig): Record<string, unknown> - [projects](../../devkit/documents/Workspace#projects): Record<string, ProjectConfiguration> +- [release](../../devkit/documents/Workspace#release): NxReleaseConfiguration - [targetDefaults](../../devkit/documents/Workspace#targetdefaults): TargetDefaults - [tasksRunnerOptions](../../devkit/documents/Workspace#tasksrunneroptions): Object - [version](../../devkit/documents/Workspace#version): number @@ -219,6 +220,18 @@ Projects' projects --- +### release + +• `Optional` **release**: `NxReleaseConfiguration` + +**ALPHA**: Configuration for `nx release` (versioning and publishing of applications and libraries) + +#### Inherited from + +[NxJsonConfiguration](../../devkit/documents/NxJsonConfiguration).[release](../../devkit/documents/NxJsonConfiguration#release) + +--- + ### targetDefaults • `Optional` **targetDefaults**: `TargetDefaults` diff --git a/docs/generated/manifests/menus.json b/docs/generated/manifests/menus.json index f636171f52f8e..cfe206f2003ba 100644 --- a/docs/generated/manifests/menus.json +++ b/docs/generated/manifests/menus.json @@ -7056,6 +7056,14 @@ "isExternal": false, "disableCollapsible": false }, + { + "id": "release-publish", + "path": "/packages/js/executors/release-publish", + "name": "release-publish", + "children": [], + "isExternal": false, + "disableCollapsible": false + }, { "id": "verdaccio", "path": "/packages/js/executors/verdaccio", @@ -7097,6 +7105,14 @@ "isExternal": false, "disableCollapsible": false }, + { + "id": "release-version", + "path": "/packages/js/generators/release-version", + "name": "release-version", + "children": [], + "isExternal": false, + "disableCollapsible": false + }, { "id": "setup-verdaccio", "path": "/packages/js/generators/setup-verdaccio", @@ -7776,6 +7792,14 @@ "isExternal": false, "children": [], "disableCollapsible": false + }, + { + "name": "release", + "path": "/packages/nx/documents/release", + "id": "release", + "isExternal": false, + "children": [], + "disableCollapsible": false } ], "isExternal": false, diff --git a/docs/generated/manifests/packages.json b/docs/generated/manifests/packages.json index c0a17ec7bc62f..7722b0c0e2a7b 100644 --- a/docs/generated/manifests/packages.json +++ b/docs/generated/manifests/packages.json @@ -1010,6 +1010,15 @@ "path": "/packages/js/executors/node", "type": "executor" }, + "/packages/js/executors/release-publish": { + "description": "DO NOT INVOKE DIRECTLY WITH `nx run`. Use `nx release publish` instead.", + "file": "generated/packages/js/executors/release-publish.json", + "hidden": true, + "name": "release-publish", + "originalFilePath": "/packages/js/src/executors/release-publish/schema.json", + "path": "/packages/js/executors/release-publish", + "type": "executor" + }, "/packages/js/executors/verdaccio": { "description": "Start local registry with verdaccio", "file": "generated/packages/js/executors/verdaccio.json", @@ -1048,6 +1057,15 @@ "path": "/packages/js/generators/convert-to-swc", "type": "generator" }, + "/packages/js/generators/release-version": { + "description": "DO NOT INVOKE DIRECTLY WITH `nx generate`. Use `nx release version` instead.", + "file": "generated/packages/js/generators/release-version.json", + "hidden": true, + "name": "release-version", + "originalFilePath": "/packages/js/src/generators/release-version/schema.json", + "path": "/packages/js/generators/release-version", + "type": "generator" + }, "/packages/js/generators/setup-verdaccio": { "description": "Setup Verdaccio for local package management.", "file": "generated/packages/js/generators/setup-verdaccio.json", @@ -1773,6 +1791,17 @@ "path": "/packages/nx/documents/view-logs", "tags": [], "originalFilePath": "generated/cli/view-logs" + }, + "/packages/nx/documents/release": { + "id": "release", + "name": "release", + "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.", + "file": "generated/packages/nx/documents/release", + "itemList": [], + "isExternal": false, + "path": "/packages/nx/documents/release", + "tags": [], + "originalFilePath": "generated/cli/release" } }, "root": "/packages/nx", diff --git a/docs/generated/packages-metadata.json b/docs/generated/packages-metadata.json index b7fe8d96eaa25..3075e1de3e993 100644 --- a/docs/generated/packages-metadata.json +++ b/docs/generated/packages-metadata.json @@ -994,6 +994,15 @@ "path": "js/executors/node", "type": "executor" }, + { + "description": "DO NOT INVOKE DIRECTLY WITH `nx run`. Use `nx release publish` instead.", + "file": "generated/packages/js/executors/release-publish.json", + "hidden": true, + "name": "release-publish", + "originalFilePath": "/packages/js/src/executors/release-publish/schema.json", + "path": "js/executors/release-publish", + "type": "executor" + }, { "description": "Start local registry with verdaccio", "file": "generated/packages/js/executors/verdaccio.json", @@ -1032,6 +1041,15 @@ "path": "js/generators/convert-to-swc", "type": "generator" }, + { + "description": "DO NOT INVOKE DIRECTLY WITH `nx generate`. Use `nx release version` instead.", + "file": "generated/packages/js/generators/release-version.json", + "hidden": true, + "name": "release-version", + "originalFilePath": "/packages/js/src/generators/release-version/schema.json", + "path": "js/generators/release-version", + "type": "generator" + }, { "description": "Setup Verdaccio for local package management.", "file": "generated/packages/js/generators/setup-verdaccio.json", @@ -1754,6 +1772,17 @@ "path": "nx/documents/view-logs", "tags": [], "originalFilePath": "generated/cli/view-logs" + }, + { + "id": "release", + "name": "release", + "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.", + "file": "generated/packages/nx/documents/release", + "itemList": [], + "isExternal": false, + "path": "nx/documents/release", + "tags": [], + "originalFilePath": "generated/cli/release" } ], "executors": [ diff --git a/docs/generated/packages/js/executors/release-publish.json b/docs/generated/packages/js/executors/release-publish.json new file mode 100644 index 0000000000000..49ec6e4cc38f6 --- /dev/null +++ b/docs/generated/packages/js/executors/release-publish.json @@ -0,0 +1,32 @@ +{ + "name": "release-publish", + "implementation": "/packages/js/src/executors/release-publish/release-publish.impl.ts", + "schema": { + "$schema": "http://json-schema.org/schema", + "version": 2, + "title": "Implementation details of `nx release publish`", + "description": "DO NOT INVOKE DIRECTLY WITH `nx run`. Use `nx release publish` instead.", + "type": "object", + "properties": { + "packageRoot": { + "type": "string", + "description": "The root directory of the directory (containing a manifest file at its root) to publish. Defaults to the project root." + }, + "registry": { + "type": "string", + "description": "The registry to publish the package to." + }, + "tag": { + "type": "string", + "description": "The distribution tag to apply to the published package." + } + }, + "required": [], + "presets": [] + }, + "description": "DO NOT INVOKE DIRECTLY WITH `nx run`. Use `nx release publish` instead.", + "hidden": true, + "aliases": [], + "path": "/packages/js/src/executors/release-publish/schema.json", + "type": "executor" +} diff --git a/docs/generated/packages/js/generators/release-version.json b/docs/generated/packages/js/generators/release-version.json new file mode 100644 index 0000000000000..5d002ed9538ab --- /dev/null +++ b/docs/generated/packages/js/generators/release-version.json @@ -0,0 +1,50 @@ +{ + "name": "release-version", + "factory": "./src/generators/release-version/release-version#releaseVersionGenerator", + "schema": { + "$schema": "http://json-schema.org/schema", + "$id": "NxJSReleaseVersionGenerator", + "cli": "nx", + "title": "Implementation details of `nx release version`", + "description": "DO NOT INVOKE DIRECTLY WITH `nx generate`. Use `nx release version` instead.", + "type": "object", + "properties": { + "projects": { + "type": "array", + "description": "The ProjectGraphProjectNodes being versioned in the current execution.", + "items": { "type": "object" } + }, + "projectGraph": { + "type": "object", + "description": "ProjectGraph instance" + }, + "specifier": { + "type": "string", + "description": "Exact version or semver keyword to apply to the selected release group. NOTE: This should be set on the release group level, not the project level." + }, + "packageRoot": { + "type": "string", + "description": "The root directory of the directory (containing a manifest file at its root) to publish. Defaults to the project root" + }, + "currentVersionResolver": { + "type": "string", + "default": "disk", + "description": "Which approach to use to determine the current version of the project.", + "enum": ["registry", "disk"] + }, + "currentVersionResolverMetadata": { + "type": "object", + "description": "Additional metadata to pass to the current version resolver.", + "default": {} + } + }, + "required": ["projects", "projectGraph", "specifier"], + "presets": [] + }, + "description": "DO NOT INVOKE DIRECTLY WITH `nx generate`. Use `nx release version` instead.", + "hidden": true, + "implementation": "/packages/js/src/generators/release-version/release-version#releaseVersionGenerator.ts", + "aliases": [], + "path": "/packages/js/src/generators/release-version/schema.json", + "type": "generator" +} diff --git a/docs/generated/packages/nx/documents/release.md b/docs/generated/packages/nx/documents/release.md new file mode 100644 index 0000000000000..3c242248c8b0a --- /dev/null +++ b/docs/generated/packages/nx/documents/release.md @@ -0,0 +1,170 @@ +--- +title: 'release - CLI command' +description: '**ALPHA**: Orchestrate versioning and publishing of applications and libraries' +--- + +# release + +**ALPHA**: Orchestrate versioning and publishing of applications and libraries + +## Usage + +```shell +nx release +``` + +Install `nx` globally to invoke the command directly using `nx`, or use `npx nx`, `yarn nx`, or `pnpm nx`. + +## Options + +### dryRun + +Type: `boolean` + +Default: `false` + +Preview the changes without updating files/creating releases + +### groups + +Type: `string` + +One or more release groups to target with the current command. + +### help + +Type: `boolean` + +Show help + +### projects + +Type: `string` + +Projects to run. (comma/space delimited project names and/or patterns) + +### version + +Type: `boolean` + +Show version number + +## Subcommands + +### version + +Create a version and release for one or more applications and libraries + +```shell +nx release version [specifier] +``` + +#### Options + +##### help + +Type: `boolean` + +Show help + +##### specifier + +Type: `string` + +Exact version or semver keyword to apply to the selected release group. + +##### version + +Type: `boolean` + +Show version number + +### changelog + +Generate a changelog for one or more projects, and optionally push to Github + +```shell +nx release changelog [version] +``` + +#### Options + +##### from + +Type: `string` + +The git reference to use as the start of the changelog. If not set it will attempt to resolve the latest tag and use that + +##### gitRemote + +Type: `string` + +Default: `origin` + +Alternate git remote in the form {user}/{repo} on which to create the Github release (useful for testing) + +##### help + +Type: `boolean` + +Show help + +##### interactive + +Type: `boolean` + +##### tagVersionPrefix + +Type: `string` + +Default: `v` + +Prefix to apply to the version when creating the Github release tag + +##### to + +Type: `string` + +Default: `HEAD` + +The git reference to use as the end of the changelog + +##### version + +Type: `string` + +The version to create a Github release and changelog for + +### publish + +Publish a versioned project to a registry + +```shell +nx release publish +``` + +#### Options + +##### help + +Type: `boolean` + +Show help + +##### registry + +Type: `string` + +The registry to publish to + +##### tag + +Type: `string` + +The distribution tag to apply to the published package + +##### version + +Type: `boolean` + +Show version number diff --git a/docs/map.json b/docs/map.json index 934778e187d72..6ff45dff51a61 100644 --- a/docs/map.json +++ b/docs/map.json @@ -1975,6 +1975,11 @@ "name": "view-logs", "id": "view-logs", "file": "generated/cli/view-logs" + }, + { + "name": "release", + "id": "release", + "file": "generated/cli/release" } ] }, diff --git a/docs/shared/reference/sitemap.md b/docs/shared/reference/sitemap.md index c61af4b215ad5..62e3142227c9d 100644 --- a/docs/shared/reference/sitemap.md +++ b/docs/shared/reference/sitemap.md @@ -432,11 +432,13 @@ - [tsc](/packages/js/executors/tsc) - [swc](/packages/js/executors/swc) - [node](/packages/js/executors/node) + - [release-publish](/packages/js/executors/release-publish) - [verdaccio](/packages/js/executors/verdaccio) - [generators](/packages/js/generators) - [library](/packages/js/generators/library) - [init](/packages/js/generators/init) - [convert-to-swc](/packages/js/generators/convert-to-swc) + - [release-version](/packages/js/generators/release-version) - [setup-verdaccio](/packages/js/generators/setup-verdaccio) - [setup-build](/packages/js/generators/setup-build) - [linter](/packages/linter) @@ -520,6 +522,7 @@ - [watch](/packages/nx/documents/watch) - [show](/packages/nx/documents/show) - [view-logs](/packages/nx/documents/view-logs) + - [release](/packages/nx/documents/release) - [executors](/packages/nx/executors) - [noop](/packages/nx/executors/noop) - [run-commands](/packages/nx/executors/run-commands) diff --git a/e2e/release/jest.config.ts b/e2e/release/jest.config.ts new file mode 100644 index 0000000000000..639a0a29676b0 --- /dev/null +++ b/e2e/release/jest.config.ts @@ -0,0 +1,13 @@ +/* eslint-disable */ +export default { + transform: { + '^.+\\.[tj]sx?$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }], + }, + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'], + maxWorkers: 1, + globals: {}, + globalSetup: '../utils/global-setup.ts', + globalTeardown: '../utils/global-teardown.ts', + displayName: 'e2e-release', + preset: '../../jest.preset.js', +}; diff --git a/e2e/release/project.json b/e2e/release/project.json new file mode 100644 index 0000000000000..6003a790233ac --- /dev/null +++ b/e2e/release/project.json @@ -0,0 +1,10 @@ +{ + "name": "e2e-release", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "e2e/release", + "projectType": "application", + "targets": { + "e2e": {} + }, + "implicitDependencies": ["nx", "js"] +} diff --git a/e2e/release/src/__snapshots__/release.test.ts.snap b/e2e/release/src/__snapshots__/release.test.ts.snap new file mode 100644 index 0000000000000..f7cf7c4328aed --- /dev/null +++ b/e2e/release/src/__snapshots__/release.test.ts.snap @@ -0,0 +1,76 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`nx release should version and publish multiple related npm packages with zero config 1`] = ` + +> NX Running target release-publish for 3 projects: + +- {project-name} +- {project-name} +- {project-name} + + + +> nx run {project-name}:release-publish + +{project-name}: 📦 @proj/{project-name}@999.9.9 +{project-name}: === Tarball Contents === +{project-name}: XXB index.js +{project-name}: XXXB package.json +{project-name}: XXB project.json +{project-name}: === Tarball Details === +{project-name}: name: @proj/{project-name} +{project-name}: version: 999.9.9 +{project-name}: filename: proj-{project-name}-999.9.9.tgz +{project-name}: package size: XXXB +{project-name}: unpacked size: XXXB +{project-name}: shasum: {SHASUM} +{project-name}: integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +{project-name}: total files: 3 +{project-name}: +{project-name}: Published to http://localhost:4875 with tag "latest" + +> nx run {project-name}:release-publish + +{project-name}: 📦 @proj/{project-name}@999.9.9 +{project-name}: === Tarball Contents === +{project-name}: XXB index.js +{project-name}: XXXB package.json +{project-name}: XXB project.json +{project-name}: === Tarball Details === +{project-name}: name: @proj/{project-name} +{project-name}: version: 999.9.9 +{project-name}: filename: proj-{project-name}-999.9.9.tgz +{project-name}: package size: XXXB +{project-name}: unpacked size: XXXB +{project-name}: shasum: {SHASUM} +{project-name}: integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +{project-name}: total files: 3 +{project-name}: +{project-name}: Published to http://localhost:4875 with tag "latest" + +> nx run {project-name}:release-publish + +{project-name}: 📦 @proj/{project-name}@999.9.9 +{project-name}: === Tarball Contents === +{project-name}: XXB index.js +{project-name}: XXXB package.json +{project-name}: XXB project.json +{project-name}: === Tarball Details === +{project-name}: name: @proj/{project-name} +{project-name}: version: 999.9.9 +{project-name}: filename: proj-{project-name}-999.9.9.tgz +{project-name}: package size: XXXB +{project-name}: unpacked size: XXXB +{project-name}: shasum: {SHASUM} +{project-name}: integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +{project-name}: total files: 3 +{project-name}: +{project-name}: Published to http://localhost:4875 with tag "latest" + + + +> NX Successfully ran target release-publish for 3 projects + + + +`; diff --git a/e2e/release/src/release.test.ts b/e2e/release/src/release.test.ts new file mode 100644 index 0000000000000..097e0b9e473b7 --- /dev/null +++ b/e2e/release/src/release.test.ts @@ -0,0 +1,101 @@ +import { + cleanupProject, + newProject, + runCLI, + uniq, + updateJson, +} from '@nx/e2e/utils'; + +expect.addSnapshotSerializer({ + serialize(str: string) { + return ( + str + // Remove all output unique to specific projects to ensure deterministic snapshots + .replaceAll(/my-pkg-\d+/g, '{project-name}') + .replaceAll( + /integrity:\s*.*/g, + 'integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' + ) + .replaceAll(/\b[0-9a-f]{40}\b/g, '{SHASUM}') + .replaceAll(/\d*B index\.js/g, 'XXB index.js') + .replaceAll(/\d*B project\.json/g, 'XXB project.json') + .replaceAll(/\d*B package\.json/g, 'XXXB package.json') + .replaceAll(/size:\s*\d*\s?B/g, 'size: XXXB') + .replaceAll(/\d*\.\d*\s?kB/g, 'XXX.XXX kb') + // We trim each line to reduce the chances of snapshot flakiness + .split('\n') + .map((r) => r.trim()) + .join('\n') + ); + }, + test(val: string) { + return val != null && typeof val === 'string'; + }, +}); + +describe('nx release', () => { + let pkg1: string; + let pkg2: string; + let pkg3: string; + + beforeAll(() => { + newProject(); + + pkg1 = uniq('my-pkg-1'); + runCLI(`generate @nx/workspace:npm-package ${pkg1}`); + + pkg2 = uniq('my-pkg-2'); + runCLI(`generate @nx/workspace:npm-package ${pkg2}`); + + pkg3 = uniq('my-pkg-3'); + runCLI(`generate @nx/workspace:npm-package ${pkg3}`); + + // Update pkg2 to depend on pkg1 + updateJson(`libs/${pkg2}/package.json`, (json) => { + json.dependencies ??= {}; + json.dependencies[`@proj/${pkg1}`] = '0.0.0'; + return json; + }); + }); + afterAll(() => cleanupProject()); + + it('should version and publish multiple related npm packages with zero config', async () => { + const versionOutput = runCLI(`release version 999.9.9`); + + /** + * We can't just assert on the whole version output as a snapshot because the order of the projects + * is non-deterministic, and not every project has the same number of log lines (because of the + * dependency relationship) + */ + expect( + versionOutput.match(/Running release version for project: my-pkg-\d*/g) + .length + ).toEqual(3); + expect( + versionOutput.match( + /Reading data for package "@proj\/my-pkg-\d*" from libs\/my-pkg-\d*\/package.json/g + ).length + ).toEqual(3); + expect( + versionOutput.match( + /Resolved the current version as 0.0.0 from libs\/my-pkg-\d*\/package.json/g + ).length + ).toEqual(3); + expect( + versionOutput.match( + /New version 999.9.9 written to libs\/my-pkg-\d*\/package.json/g + ).length + ).toEqual(3); + + // Only one dependency relationship exists, so this log should only match once + expect( + versionOutput.match( + /Applying new version 999.9.9 to 1 package which depends on my-pkg-\d*/g + ).length + ).toEqual(1); + + // Thanks to the custom serializer above, the publish output should be deterministic + const publishOutput = runCLI(`release publish`); + expect(publishOutput).toMatchSnapshot(); + }, 500000); +}); diff --git a/e2e/release/tsconfig.json b/e2e/release/tsconfig.json new file mode 100644 index 0000000000000..6d5abf8483200 --- /dev/null +++ b/e2e/release/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "types": ["node", "jest"] + }, + "include": [], + "files": [], + "references": [ + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/e2e/release/tsconfig.spec.json b/e2e/release/tsconfig.spec.json new file mode 100644 index 0000000000000..1a24bfb0a1353 --- /dev/null +++ b/e2e/release/tsconfig.spec.json @@ -0,0 +1,20 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "**/*.test.ts", + "**/*.spec.ts", + "**/*.spec.tsx", + "**/*.test.tsx", + "**/*.spec.js", + "**/*.test.js", + "**/*.spec.jsx", + "**/*.test.jsx", + "**/*.d.ts", + "jest.config.ts" + ] +} diff --git a/package.json b/package.json index 17ace3d715ea9..e62322660933c 100644 --- a/package.json +++ b/package.json @@ -119,6 +119,7 @@ "@types/js-yaml": "^4.0.5", "@types/marked": "^2.0.0", "@types/node": "18.16.9", + "@types/npm-package-arg": "6.1.1", "@types/prettier": "^2.6.2", "@types/react": "18.2.14", "@types/react-dom": "18.2.6", @@ -144,6 +145,7 @@ "chalk": "^4.1.0", "cli-cursor": "3.1.0", "cli-spinners": "2.6.1", + "columnify": "^1.6.0", "confusing-browser-globals": "^1.0.9", "conventional-changelog-cli": "^2.0.23", "convert-source-map": "^2.0.0", @@ -197,6 +199,7 @@ "jasmine-spec-reporter": "~4.2.1", "jest": "29.4.3", "jest-config": "^29.4.1", + "jest-diff": "^29.4.1", "jest-environment-jsdom": "29.4.3", "jest-environment-node": "^29.4.1", "jest-resolve": "^29.4.1", @@ -225,6 +228,7 @@ "next-sitemap": "^3.1.10", "ng-packagr": "~16.2.0", "node-fetch": "^2.6.7", + "npm-package-arg": "11.0.1", "nx": "16.8.0-rc.0", "nx-cloud": "16.4.0-beta.7", "octokit": "^2.0.14", diff --git a/packages/js/executors.json b/packages/js/executors.json index 4df6f6369d599..ff7d851b68430 100644 --- a/packages/js/executors.json +++ b/packages/js/executors.json @@ -17,6 +17,12 @@ "schema": "./src/executors/node/schema.json", "description": "Execute a Node application." }, + "release-publish": { + "implementation": "./src/executors/release-publish/release-publish.impl", + "schema": "./src/executors/release-publish/schema.json", + "description": "DO NOT INVOKE DIRECTLY WITH `nx run`. Use `nx release publish` instead.", + "hidden": true + }, "verdaccio": { "implementation": "./src/executors/verdaccio/verdaccio.impl", "schema": "./src/executors/verdaccio/schema.json", diff --git a/packages/js/generators.json b/packages/js/generators.json index b5a3791c0f9cc..91a7eed1c5dcf 100644 --- a/packages/js/generators.json +++ b/packages/js/generators.json @@ -59,6 +59,12 @@ "x-type": "library", "description": "Convert a TypeScript library to compile with SWC." }, + "release-version": { + "factory": "./src/generators/release-version/release-version#releaseVersionGenerator", + "schema": "./src/generators/release-version/schema.json", + "description": "DO NOT INVOKE DIRECTLY WITH `nx generate`. Use `nx release version` instead.", + "hidden": true + }, "setup-verdaccio": { "factory": "./src/generators/setup-verdaccio/generator#setupVerdaccio", "schema": "./src/generators/setup-verdaccio/schema.json", diff --git a/packages/js/package.json b/packages/js/package.json index 4556a4b7d1bd5..48163735a4873 100644 --- a/packages/js/package.json +++ b/packages/js/package.json @@ -44,14 +44,18 @@ "babel-plugin-macros": "^2.8.0", "babel-plugin-transform-typescript-metadata": "^0.3.1", "chalk": "^4.1.0", + "columnify": "^1.6.0", "detect-port": "^1.5.1", "fast-glob": "3.2.7", "fs-extra": "^11.1.0", + "npm-package-arg": "11.0.1", + "npm-run-path": "^4.0.1", "ts-node": "10.9.1", "tsconfig-paths": "^4.1.2", "ignore": "^5.0.4", "js-tokens": "^4.0.0", "minimatch": "3.0.5", + "ora": "5.3.0", "semver": "7.5.3", "source-map-support": "0.5.19", "tslib": "^2.3.0", diff --git a/packages/js/src/executors/release-publish/format-bytes.ts b/packages/js/src/executors/release-publish/format-bytes.ts new file mode 100644 index 0000000000000..72015a59c8bfe --- /dev/null +++ b/packages/js/src/executors/release-publish/format-bytes.ts @@ -0,0 +1,30 @@ +// Taken from https://github.com/npm/cli/blob/c736b622b8504b07f5a19f631ade42dd40063269/lib/utils/format-bytes.js + +// Convert bytes to printable output, for file reporting in tarballs +// Only supports up to GB because that's way larger than anything the registry +// supports anyways. + +export const formatBytes = (bytes, space = true) => { + let spacer = ''; + if (space) { + spacer = ' '; + } + + if (bytes < 1000) { + // B + return `${bytes}${spacer}B`; + } + + if (bytes < 1000000) { + // kB + return `${(bytes / 1000).toFixed(1)}${spacer}kB`; + } + + if (bytes < 1000000000) { + // MB + return `${(bytes / 1000000).toFixed(1)}${spacer}MB`; + } + + // GB + return `${(bytes / 1000000000).toFixed(1)}${spacer}GB`; +}; diff --git a/packages/js/src/executors/release-publish/log-tar.ts b/packages/js/src/executors/release-publish/log-tar.ts new file mode 100644 index 0000000000000..d43a3e0105940 --- /dev/null +++ b/packages/js/src/executors/release-publish/log-tar.ts @@ -0,0 +1,76 @@ +// Adapted from https://github.com/npm/cli/blob/c736b622b8504b07f5a19f631ade42dd40063269/lib/utils/tar.js +import * as chalk from 'chalk'; +import * as columnify from 'columnify'; +import { formatBytes } from './format-bytes'; + +export const logTar = (tarball, opts = {}) => { + // @ts-ignore + const { unicode = true } = opts; + console.log(''); + console.log( + `${unicode ? '📦 ' : 'package:'} ${tarball.name}@${tarball.version}` + ); + console.log(chalk.magenta('=== Tarball Contents ===')); + if (tarball.files.length) { + console.log(''); + const columnData = columnify( + tarball.files + .map((f) => { + const bytes = formatBytes(f.size, false); + return /^node_modules\//.test(f.path) + ? null + : { path: f.path, size: `${bytes}` }; + }) + .filter((f) => f), + { + include: ['size', 'path'], + showHeaders: false, + } + ); + columnData.split('\n').forEach((line) => { + console.log(line); + }); + } + if (tarball.bundled.length) { + console.log(chalk.magenta('=== Bundled Dependencies ===')); + tarball.bundled.forEach((name) => console.log('', name)); + } + console.log(chalk.magenta('=== Tarball Details ===')); + console.log( + columnify( + [ + { name: 'name:', value: tarball.name }, + { name: 'version:', value: tarball.version }, + tarball.filename && { name: 'filename:', value: tarball.filename }, + { name: 'package size:', value: formatBytes(tarball.size) }, + { name: 'unpacked size:', value: formatBytes(tarball.unpackedSize) }, + { name: 'shasum:', value: tarball.shasum }, + { + name: 'integrity:', + value: + tarball.integrity.toString().slice(0, 20) + + '[...]' + + tarball.integrity.toString().slice(80), + }, + tarball.bundled.length && { + name: 'bundled deps:', + value: tarball.bundled.length, + }, + tarball.bundled.length && { + name: 'bundled files:', + value: tarball.entryCount - tarball.files.length, + }, + tarball.bundled.length && { + name: 'own files:', + value: tarball.files.length, + }, + { name: 'total files:', value: tarball.entryCount }, + ].filter((x) => x), + { + include: ['name', 'value'], + showHeaders: false, + } + ) + ); + console.log('', ''); +}; diff --git a/packages/js/src/executors/release-publish/release-publish.impl.ts b/packages/js/src/executors/release-publish/release-publish.impl.ts new file mode 100644 index 0000000000000..27f2f3f1d55b2 --- /dev/null +++ b/packages/js/src/executors/release-publish/release-publish.impl.ts @@ -0,0 +1,110 @@ +import { ExecutorContext, joinPathFragments, readJsonFile } from '@nx/devkit'; +import { execSync } from 'child_process'; +import { env as appendLocalEnv } from 'npm-run-path'; +import { logTar } from './log-tar'; +import { PublishExecutorSchema } from './schema'; + +const LARGE_BUFFER = 1024 * 1000000; + +function processEnv(color: boolean) { + const env = { + ...process.env, + ...appendLocalEnv(), + }; + + if (color) { + env.FORCE_COLOR = `${color}`; + } + return env; +} + +export default async function runExecutor( + options: PublishExecutorSchema, + context: ExecutorContext +) { + const projectConfig = + context.projectsConfigurations!.projects[context.projectName!]!; + + const packageRoot = joinPathFragments( + context.root, + options.packageRoot ?? projectConfig.root + ); + + const npmPublishCommandSegments = [`npm publish --json`]; + + if (options.registry) { + npmPublishCommandSegments.push(`--registry=${options.registry}`); + } + + if (options.tag) { + npmPublishCommandSegments.push(`--tag=${options.tag}`); + } + + // Resolve values using the `npm config` command so that things like environment variables and `publishConfig`s are accounted for + const registry = + options.registry ?? execSync(`npm config get registry`).toString().trim(); + const tag = options.tag ?? execSync(`npm config get tag`).toString().trim(); + + try { + const output = execSync(npmPublishCommandSegments.join(' '), { + maxBuffer: LARGE_BUFFER, + env: processEnv(true), + cwd: packageRoot, + stdio: ['ignore', 'pipe', 'pipe'], + }); + + const stdoutData = JSON.parse(output.toString()); + logTar(stdoutData); + + console.log(`Published to ${registry} with tag "${tag}"`); + + return { + success: true, + }; + } catch (err) { + try { + const projectPackageJson = readJsonFile( + joinPathFragments(packageRoot, 'package.json') + ); + const name = projectPackageJson.name; + const currentVersion = projectPackageJson.version; + + const stdoutData = JSON.parse(err.stdout?.toString() || '{}'); + if (stdoutData.error?.code === 'EPUBLISHCONFLICT') { + // If package and project name match, make it terser + let packageTxt = + name === context.projectName + ? `package "${name}"` + : `package "${name}" from project "${context.projectName}"`; + + console.warn( + `Skipping ${packageTxt}, as v${currentVersion} has already been published to ${registry} with tag "${tag}"` + ); + return { + success: true, + }; + } + + console.error('npm publish error:'); + if (stdoutData.error.summary) { + console.error(stdoutData.error.summary); + } + if (stdoutData.error.detail) { + console.error(stdoutData.error.detail); + } + return { + success: false, + }; + } catch (err) { + // npm v9 onwards seems to guarantee stdout will be well formed JSON when --json is used, so maybe we need to + // specify that as minimum supported version? (comes with node 18 and 20 by default) + console.error( + 'Something unexpected went wrong when processing the npm publish output\n', + err + ); + return { + success: false, + }; + } + } +} diff --git a/packages/js/src/executors/release-publish/schema.d.ts b/packages/js/src/executors/release-publish/schema.d.ts new file mode 100644 index 0000000000000..19de5b5518035 --- /dev/null +++ b/packages/js/src/executors/release-publish/schema.d.ts @@ -0,0 +1,5 @@ +export interface PublishExecutorSchema { + packageRoot?: string; + registry?: string; + tag?: string; +} diff --git a/packages/js/src/executors/release-publish/schema.json b/packages/js/src/executors/release-publish/schema.json new file mode 100644 index 0000000000000..149d7b0b6d38c --- /dev/null +++ b/packages/js/src/executors/release-publish/schema.json @@ -0,0 +1,22 @@ +{ + "$schema": "http://json-schema.org/schema", + "version": 2, + "title": "Implementation details of `nx release publish`", + "description": "DO NOT INVOKE DIRECTLY WITH `nx run`. Use `nx release publish` instead.", + "type": "object", + "properties": { + "packageRoot": { + "type": "string", + "description": "The root directory of the directory (containing a manifest file at its root) to publish. Defaults to the project root." + }, + "registry": { + "type": "string", + "description": "The registry to publish the package to." + }, + "tag": { + "type": "string", + "description": "The distribution tag to apply to the published package." + } + }, + "required": [] +} diff --git a/packages/js/src/generators/release-version/release-version.spec.ts b/packages/js/src/generators/release-version/release-version.spec.ts new file mode 100644 index 0000000000000..04f6f869dd805 --- /dev/null +++ b/packages/js/src/generators/release-version/release-version.spec.ts @@ -0,0 +1,127 @@ +import { ProjectGraph, Tree, readJson } from '@nx/devkit'; +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import { releaseVersionGenerator } from './release-version'; +import { createWorkspaceWithPackageDependencies } from './test-utils/create-workspace-with-package-dependencies'; + +// Using the daemon in unit tests would cause jest to never exit +process.env.NX_DAEMON = 'false'; + +describe('release-version', () => { + let tree: Tree; + let projectGraph: ProjectGraph; + + beforeEach(() => { + tree = createTreeWithEmptyWorkspace(); + + projectGraph = createWorkspaceWithPackageDependencies(tree, { + 'my-lib': { + projectRoot: 'libs/my-lib', + packageName: 'my-lib', + version: '0.0.1', + packageJsonPath: 'libs/my-lib/package.json', + localDependencies: [], + }, + 'project-with-dependency-on-my-pkg': { + projectRoot: 'libs/project-with-dependency-on-my-pkg', + packageName: 'project-with-dependency-on-my-pkg', + version: '0.0.1', + packageJsonPath: 'libs/project-with-dependency-on-my-pkg/package.json', + localDependencies: [ + { + projectName: 'my-lib', + dependencyCollection: 'dependencies', + version: '0.0.1', + }, + ], + }, + 'project-with-devDependency-on-my-pkg': { + projectRoot: 'libs/project-with-devDependency-on-my-pkg', + packageName: 'project-with-devDependency-on-my-pkg', + version: '0.0.1', + packageJsonPath: + 'libs/project-with-devDependency-on-my-pkg/package.json', + localDependencies: [ + { + projectName: 'my-lib', + dependencyCollection: 'devDependencies', + version: '0.0.1', + }, + ], + }, + }); + }); + + it(`should work with semver keywords and exact semver versions`, async () => { + expect(readJson(tree, 'libs/my-lib/package.json').version).toEqual('0.0.1'); + await releaseVersionGenerator(tree, { + projects: Object.values(projectGraph.nodes), // version all projects + projectGraph, + specifier: 'major', + currentVersionResolver: 'disk', + }); + expect(readJson(tree, 'libs/my-lib/package.json').version).toEqual('1.0.0'); + + await releaseVersionGenerator(tree, { + projects: Object.values(projectGraph.nodes), // version all projects + projectGraph, + specifier: 'minor', + currentVersionResolver: 'disk', + }); + expect(readJson(tree, 'libs/my-lib/package.json').version).toEqual('1.1.0'); + + await releaseVersionGenerator(tree, { + projects: Object.values(projectGraph.nodes), // version all projects + projectGraph, + specifier: 'patch', + currentVersionResolver: 'disk', + }); + expect(readJson(tree, 'libs/my-lib/package.json').version).toEqual('1.1.1'); + + await releaseVersionGenerator(tree, { + projects: Object.values(projectGraph.nodes), // version all projects + projectGraph, + specifier: '1.2.3', // exact version + currentVersionResolver: 'disk', + }); + expect(readJson(tree, 'libs/my-lib/package.json').version).toEqual('1.2.3'); + }); + + it(`should apply the updated version to the projects, including updating dependents`, async () => { + await releaseVersionGenerator(tree, { + projects: Object.values(projectGraph.nodes), // version all projects + projectGraph, + specifier: 'major', + currentVersionResolver: 'disk', + }); + + expect(readJson(tree, 'libs/my-lib/package.json')).toMatchInlineSnapshot(` + { + "name": "my-lib", + "version": "1.0.0", + } + `); + + expect( + readJson(tree, 'libs/project-with-dependency-on-my-pkg/package.json') + ).toMatchInlineSnapshot(` + { + "dependencies": { + "my-lib": "1.0.0", + }, + "name": "project-with-dependency-on-my-pkg", + "version": "1.0.0", + } + `); + expect( + readJson(tree, 'libs/project-with-devDependency-on-my-pkg/package.json') + ).toMatchInlineSnapshot(` + { + "devDependencies": { + "my-lib": "1.0.0", + }, + "name": "project-with-devDependency-on-my-pkg", + "version": "1.0.0", + } + `); + }); +}); diff --git a/packages/js/src/generators/release-version/release-version.ts b/packages/js/src/generators/release-version/release-version.ts new file mode 100644 index 0000000000000..9e6aa546c4ccf --- /dev/null +++ b/packages/js/src/generators/release-version/release-version.ts @@ -0,0 +1,210 @@ +import { + Tree, + joinPathFragments, + output, + readJson, + updateJson, + workspaceRoot, + writeJson, +} from '@nx/devkit'; +import * as chalk from 'chalk'; +import { exec } from 'child_process'; +import { deriveNewSemverVersion } from 'nx/src/command-line/release/release'; +import { interpolate } from 'nx/src/tasks-runner/utils'; +import * as ora from 'ora'; +import { relative } from 'path'; +import { ReleaseVersionGeneratorSchema } from './schema'; +import { resolveLocalPackageDependencies } from './utils/resolve-local-package-dependencies'; + +export async function releaseVersionGenerator( + tree: Tree, + options: ReleaseVersionGeneratorSchema +) { + const projects = options.projects; + + // Resolve any custom package roots for each project upfront as they will need to be reused during dependency resolution + const projectNameToPackageRootMap = new Map(); + for (const project of projects) { + projectNameToPackageRootMap.set( + project.name, + // Default to the project root if no custom packageRoot + !options.packageRoot + ? project.data.root + : interpolate(options.packageRoot, { + workspaceRoot: '', + projectRoot: project.data.root, + projectName: project.name, + }) + ); + } + + let currentVersion: string; + + for (const project of projects) { + const projectName = project.name; + const packageRoot = projectNameToPackageRootMap.get(projectName); + const packageJsonPath = joinPathFragments(packageRoot, 'package.json'); + const workspaceRelativePackageJsonPath = relative( + workspaceRoot, + packageJsonPath + ); + + const color = getColor(projectName); + const log = (msg: string) => { + console.log(color.instance.bold(projectName) + ' ' + msg); + }; + + output.logSingleLine( + `Running release version for project: ${color.instance.bold( + project.name + )}` + ); + + const projectPackageJson = readJson(tree, packageJsonPath); + log( + `🔍 Reading data for package "${projectPackageJson.name}" from ${workspaceRelativePackageJsonPath}` + ); + + const { name: packageName, version: currentVersionFromDisk } = + projectPackageJson; + + switch (options.currentVersionResolver) { + case 'registry': { + const metadata = options.currentVersionResolverMetadata; + const registry = metadata?.registry ?? 'https://registry.npmjs.org'; + const tag = metadata?.tag ?? 'latest'; + + // If the currentVersionResolver is set to registry, we only want to make the request once for the whole batch of projects + if (!currentVersion) { + const spinner = ora( + `${Array.from(new Array(projectName.length + 3)).join( + ' ' + )}Resolving the current version for tag "${tag}" on ${registry}` + ); + spinner.color = + color.spinnerColor as typeof colors[number]['spinnerColor']; + spinner.start(); + + // Must be non-blocking async to allow spinner to render + currentVersion = await new Promise((resolve, reject) => { + exec( + `npm view ${packageName} version --registry=${registry} --tag=${tag}`, + (error, stdout, stderr) => { + if (error) { + return reject(error); + } + if (stderr) { + return reject(stderr); + } + return resolve(stdout.trim()); + } + ); + }); + + spinner.stop(); + + log( + `📄 Resolved the current version as ${currentVersion} for tag "${tag}" from registry ${registry}` + ); + } else { + log( + `📄 Using the current version ${currentVersion} already resolved from the registry ${registry}` + ); + } + break; + } + case 'disk': + currentVersion = currentVersionFromDisk; + log( + `📄 Resolved the current version as ${currentVersion} from ${packageJsonPath}` + ); + break; + default: + throw new Error( + `Invalid value for options.currentVersionResolver: ${options.currentVersionResolver}` + ); + } + + // Resolve any local package dependencies for this project (before applying the new version) + const localPackageDependencies = resolveLocalPackageDependencies( + tree, + options.projectGraph, + projects, + projectNameToPackageRootMap + ); + + const newVersion = deriveNewSemverVersion( + currentVersion, + options.specifier + ); + + writeJson(tree, packageJsonPath, { + ...readJson(tree, packageJsonPath), + version: newVersion, + }); + + log( + `✍️ New version ${newVersion} written to ${workspaceRelativePackageJsonPath}` + ); + + const dependentProjects = Object.values(localPackageDependencies) + .filter((localPackageDependencies) => { + return localPackageDependencies.some( + (localPackageDependency) => + localPackageDependency.target === project.name + ); + }) + .flat(); + + if (dependentProjects.length > 0) { + log( + `✍️ Applying new version ${newVersion} to ${ + dependentProjects.length + } ${ + dependentProjects.length > 1 + ? 'packages which depend' + : 'package which depends' + } on ${project.name}` + ); + } + + for (const dependentProject of dependentProjects) { + updateJson( + tree, + joinPathFragments( + projectNameToPackageRootMap.get(dependentProject.source), + 'package.json' + ), + (json) => { + json[dependentProject.dependencyCollection][packageName] = newVersion; + return json; + } + ); + } + } +} + +export default releaseVersionGenerator; + +const colors = [ + { instance: chalk.green, spinnerColor: 'green' }, + { instance: chalk.greenBright, spinnerColor: 'green' }, + { instance: chalk.red, spinnerColor: 'red' }, + { instance: chalk.redBright, spinnerColor: 'red' }, + { instance: chalk.cyan, spinnerColor: 'cyan' }, + { instance: chalk.cyanBright, spinnerColor: 'cyan' }, + { instance: chalk.yellow, spinnerColor: 'yellow' }, + { instance: chalk.yellowBright, spinnerColor: 'yellow' }, + { instance: chalk.magenta, spinnerColor: 'magenta' }, + { instance: chalk.magentaBright, spinnerColor: 'magenta' }, +] as const; + +function getColor(projectName: string) { + let code = 0; + for (let i = 0; i < projectName.length; ++i) { + code += projectName.charCodeAt(i); + } + const colorIndex = code % colors.length; + + return colors[colorIndex]; +} diff --git a/packages/js/src/generators/release-version/schema.d.ts b/packages/js/src/generators/release-version/schema.d.ts new file mode 100644 index 0000000000000..0bd430fb7fdba --- /dev/null +++ b/packages/js/src/generators/release-version/schema.d.ts @@ -0,0 +1 @@ +export { ReleaseVersionGeneratorSchema } from 'nx/src/command-line/release/version'; diff --git a/packages/js/src/generators/release-version/schema.json b/packages/js/src/generators/release-version/schema.json new file mode 100644 index 0000000000000..94d7755f2e13d --- /dev/null +++ b/packages/js/src/generators/release-version/schema.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json-schema.org/schema", + "$id": "NxJSReleaseVersionGenerator", + "cli": "nx", + "title": "Implementation details of `nx release version`", + "description": "DO NOT INVOKE DIRECTLY WITH `nx generate`. Use `nx release version` instead.", + "type": "object", + "properties": { + "projects": { + "type": "array", + "description": "The ProjectGraphProjectNodes being versioned in the current execution.", + "items": { + "type": "object" + } + }, + "projectGraph": { + "type": "object", + "description": "ProjectGraph instance" + }, + "specifier": { + "type": "string", + "description": "Exact version or semver keyword to apply to the selected release group. NOTE: This should be set on the release group level, not the project level." + }, + "packageRoot": { + "type": "string", + "description": "The root directory of the directory (containing a manifest file at its root) to publish. Defaults to the project root" + }, + "currentVersionResolver": { + "type": "string", + "default": "disk", + "description": "Which approach to use to determine the current version of the project.", + "enum": ["registry", "disk"] + }, + "currentVersionResolverMetadata": { + "type": "object", + "description": "Additional metadata to pass to the current version resolver.", + "default": {} + } + }, + "required": ["projects", "projectGraph", "specifier"] +} diff --git a/packages/js/src/generators/release-version/test-utils/create-workspace-with-package-dependencies.ts b/packages/js/src/generators/release-version/test-utils/create-workspace-with-package-dependencies.ts new file mode 100644 index 0000000000000..d006a04db897c --- /dev/null +++ b/packages/js/src/generators/release-version/test-utils/create-workspace-with-package-dependencies.ts @@ -0,0 +1,62 @@ +import { ProjectGraph, Tree, writeJson } from '@nx/devkit'; + +interface ProjectAndPackageData { + [projectName: string]: { + projectRoot: string; + packageName: string; + version: string; + packageJsonPath: string; + localDependencies: { + projectName: string; + dependencyCollection: + | 'dependencies' + | 'devDependencies' + | 'optionalDependencies'; + version: string; + }[]; + }; +} + +export function createWorkspaceWithPackageDependencies( + tree: Tree, + projectAndPackageData: ProjectAndPackageData +): ProjectGraph { + const projectGraph: ProjectGraph = { + nodes: {}, + dependencies: {}, + }; + + for (const [projectName, data] of Object.entries(projectAndPackageData)) { + const packageJsonContents = { + name: data.packageName, + version: data.version, + }; + for (const dependency of data.localDependencies) { + const dependencyPackageName = + projectAndPackageData[dependency.projectName].packageName; + packageJsonContents[dependency.dependencyCollection] = { + ...packageJsonContents[dependency.dependencyCollection], + [dependencyPackageName]: dependency.version, + }; + } + // add the project and its nx project level dependencies to the projectGraph + projectGraph.nodes[projectName] = { + name: projectName, + type: 'lib', + data: { + root: data.projectRoot, + }, + }; + projectGraph.dependencies[projectName] = data.localDependencies.map( + (dependency) => ({ + source: projectName, + target: dependency.projectName, + type: 'static', + }) + ); + // create the package.json in the tree + writeJson(tree, data.packageJsonPath, packageJsonContents); + } + + return projectGraph; +} diff --git a/packages/js/src/generators/release-version/utils/package.ts b/packages/js/src/generators/release-version/utils/package.ts new file mode 100644 index 0000000000000..08ad057514b59 --- /dev/null +++ b/packages/js/src/generators/release-version/utils/package.ts @@ -0,0 +1,43 @@ +import { joinPathFragments } from '@nx/devkit'; +import { PackageJson } from 'nx/src/utils/package-json'; + +export class Package { + name: string; + version: string; + location: string; + + constructor( + private packageJson: PackageJson, + workspaceRoot: string, + workspaceRelativeLocation: string + ) { + this.name = packageJson.name; + this.version = packageJson.version; + this.location = joinPathFragments(workspaceRoot, workspaceRelativeLocation); + } + + getLocalDependency(depName: string): { + collection: 'dependencies' | 'devDependencies' | 'optionalDependencies'; + spec: string; + } | null { + if (this.packageJson.dependencies?.[depName]) { + return { + collection: 'dependencies', + spec: this.packageJson.dependencies[depName], + }; + } + if (this.packageJson.devDependencies?.[depName]) { + return { + collection: 'devDependencies', + spec: this.packageJson.devDependencies[depName], + }; + } + if (this.packageJson.optionalDependencies?.[depName]) { + return { + collection: 'optionalDependencies', + spec: this.packageJson.optionalDependencies[depName], + }; + } + return null; + } +} diff --git a/packages/js/src/generators/release-version/utils/resolve-local-package-dependencies.spec.ts b/packages/js/src/generators/release-version/utils/resolve-local-package-dependencies.spec.ts new file mode 100644 index 0000000000000..7f0e73c3b1dac --- /dev/null +++ b/packages/js/src/generators/release-version/utils/resolve-local-package-dependencies.spec.ts @@ -0,0 +1,410 @@ +import { ProjectGraph, Tree, workspaceRoot } from '@nx/devkit'; +import { createTree } from '@nx/devkit/testing'; +import { createWorkspaceWithPackageDependencies } from '../test-utils/create-workspace-with-package-dependencies'; +import { resolveLocalPackageDependencies } from './resolve-local-package-dependencies'; + +expect.addSnapshotSerializer({ + serialize: (str: string) => { + // replace all instances of the workspace root with a placeholder to ensure consistency + return JSON.stringify( + str.replaceAll( + new RegExp(workspaceRoot.replace(/\\/g, '\\\\'), 'g'), + '' + ) + ); + }, + test(val: string) { + return ( + val != null && typeof val === 'string' && val.includes(workspaceRoot) + ); + }, +}); + +describe('resolveLocalPackageDependencies()', () => { + let tree: Tree; + let projectGraph: ProjectGraph; + + describe('fixed versions', () => { + beforeEach(() => { + tree = createTree(); + + projectGraph = createWorkspaceWithPackageDependencies(tree, { + projectA: { + projectRoot: 'packages/projectA', + packageName: 'projectA', + version: '1.0.0', + packageJsonPath: 'packages/projectA/package.json', + localDependencies: [ + { + projectName: 'projectB', + dependencyCollection: 'dependencies', + version: '1.0.0', + }, + { + projectName: 'projectC', + dependencyCollection: 'devDependencies', + version: '1.0.0', + }, + { + projectName: 'projectD', + dependencyCollection: 'optionalDependencies', + version: '1.0.0', + }, + ], + }, + projectB: { + projectRoot: 'packages/projectB', + packageName: 'projectB', + version: '1.0.0', + packageJsonPath: 'packages/projectB/package.json', + localDependencies: [], + }, + projectC: { + projectRoot: 'packages/projectC', + packageName: 'projectC', + version: '1.0.0', + packageJsonPath: 'packages/projectC/package.json', + localDependencies: [], + }, + projectD: { + projectRoot: 'packages/projectD', + packageName: 'projectD', + version: '1.0.0', + packageJsonPath: 'packages/projectD/package.json', + localDependencies: [], + }, + }); + }); + + it('should resolve local dependencies based on fixed semver versions', () => { + const allProjects = Object.values(projectGraph.nodes); + const projectNameToPackageRootMap = new Map(); + for (const project of allProjects) { + projectNameToPackageRootMap.set(project.name, project.data.root); + } + + const result = resolveLocalPackageDependencies( + tree, + projectGraph, + allProjects, + projectNameToPackageRootMap + ); + + expect(result).toMatchInlineSnapshot(` + { + "projectA": [ + { + "dependencyCollection": "dependencies", + "source": "projectA", + "target": "projectB", + "type": "static", + }, + { + "dependencyCollection": "devDependencies", + "source": "projectA", + "target": "projectC", + "type": "static", + }, + { + "dependencyCollection": "optionalDependencies", + "source": "projectA", + "target": "projectD", + "type": "static", + }, + ], + } + `); + }); + }); + + describe(`"file:", "link:" and "workspace:" protocols`, () => { + beforeEach(() => { + tree = createTree(); + + projectGraph = createWorkspaceWithPackageDependencies(tree, { + projectA: { + projectRoot: 'packages/projectA', + packageName: 'projectA', + version: '1.0.0', + packageJsonPath: 'packages/projectA/package.json', + localDependencies: [ + { + projectName: 'projectB', + dependencyCollection: 'dependencies', + version: 'file:../projectB', + }, + { + projectName: 'projectC', + dependencyCollection: 'devDependencies', + version: 'workspace:*', + }, + { + projectName: 'projectD', + dependencyCollection: 'optionalDependencies', + version: 'workspace:../projectD', + }, + { + projectName: 'projectE', + dependencyCollection: 'dependencies', + version: 'link:../projectE', // yarn classic equivalent of `file:` + }, + ], + }, + projectB: { + projectRoot: 'packages/projectB', + packageName: 'projectB', + version: '1.0.0', + packageJsonPath: 'packages/projectB/package.json', + localDependencies: [ + { + projectName: 'projectC', + dependencyCollection: 'dependencies', + version: 'workspace:1.0.0', + }, + { + projectName: 'projectD', + dependencyCollection: 'dependencies', + /** + * Wrong version is specified, shouldn't be resolved as a local package dependency + * (pnpm will likely error on this at install time anyway, so it's unlikely + * to occur in a real-world setup) + */ + version: 'workspace:2.0.0', + }, + ], + }, + projectC: { + projectRoot: 'packages/projectC', + packageName: 'projectC', + version: '1.0.0', + packageJsonPath: 'packages/projectC/package.json', + localDependencies: [], + }, + projectD: { + projectRoot: 'packages/projectD', + packageName: 'projectD', + version: '1.0.0', + packageJsonPath: 'packages/projectD/package.json', + localDependencies: [], + }, + projectE: { + projectRoot: 'packages/projectE', + packageName: 'projectE', + version: '1.0.0', + packageJsonPath: 'packages/projectE/package.json', + localDependencies: [], + }, + }); + }); + + it('should resolve local dependencies based on file, link and workspace protocols', () => { + const allProjects = Object.values(projectGraph.nodes); + const projectNameToPackageRootMap = new Map(); + for (const project of allProjects) { + projectNameToPackageRootMap.set(project.name, project.data.root); + } + + const result = resolveLocalPackageDependencies( + tree, + projectGraph, + allProjects, + projectNameToPackageRootMap + ); + + expect(result).toMatchInlineSnapshot(` + { + "projectA": [ + { + "dependencyCollection": "dependencies", + "source": "projectA", + "target": "projectB", + "type": "static", + }, + { + "dependencyCollection": "devDependencies", + "source": "projectA", + "target": "projectC", + "type": "static", + }, + { + "dependencyCollection": "optionalDependencies", + "source": "projectA", + "target": "projectD", + "type": "static", + }, + { + "dependencyCollection": "dependencies", + "source": "projectA", + "target": "projectE", + "type": "static", + }, + ], + "projectB": [ + { + "dependencyCollection": "dependencies", + "source": "projectB", + "target": "projectC", + "type": "static", + }, + ], + } + `); + }); + }); + + describe('npm scopes', () => { + beforeEach(() => { + tree = createTree(); + + projectGraph = createWorkspaceWithPackageDependencies(tree, { + projectA: { + projectRoot: 'packages/projectA', + packageName: '@acme/projectA', + version: '1.0.0', + packageJsonPath: 'packages/projectA/package.json', + localDependencies: [ + { + projectName: 'projectB', + dependencyCollection: 'dependencies', + version: '1.0.0', + }, + ], + }, + projectB: { + projectRoot: 'packages/projectB', + packageName: '@acme/projectB', + version: '1.0.0', + packageJsonPath: 'packages/projectB/package.json', + localDependencies: [], + }, + }); + }); + + it('should resolve local dependencies which contain npm scopes', () => { + const allProjects = Object.values(projectGraph.nodes); + const projectNameToPackageRootMap = new Map(); + for (const project of allProjects) { + projectNameToPackageRootMap.set(project.name, project.data.root); + } + + const result = resolveLocalPackageDependencies( + tree, + projectGraph, + allProjects, + projectNameToPackageRootMap + ); + + expect(result).toMatchInlineSnapshot(` + { + "projectA": [ + { + "dependencyCollection": "dependencies", + "source": "projectA", + "target": "projectB", + "type": "static", + }, + ], + } + `); + }); + }); + + describe('custom package roots', () => { + beforeEach(() => { + tree = createTree(); + + projectGraph = createWorkspaceWithPackageDependencies(tree, { + projectA: { + projectRoot: 'packages/projectA', + packageName: '@acme/projectA', + version: '1.0.0', + // Custom package.json path coming from a build/dist location, not the project root + packageJsonPath: 'build/packages/projectA/package.json', + localDependencies: [ + { + projectName: 'projectB', + dependencyCollection: 'dependencies', + version: '1.0.0', + }, + { + projectName: 'projectC', + dependencyCollection: 'dependencies', + version: '1.0.0', + }, + { + projectName: 'projectD', + dependencyCollection: 'dependencies', + // relative from projectA's package.json path to projectD's package.json path + version: 'file:../../../packages/projectD', + }, + ], + }, + projectB: { + projectRoot: 'packages/projectB', + packageName: '@acme/projectB', + version: '1.0.0', + // Custom package.json path coming from a build/dist location, not the project root + packageJsonPath: 'build/packages/projectB/package.json', + localDependencies: [], + }, + projectC: { + projectRoot: 'packages/projectC', + packageName: '@acme/projectC', + version: '1.0.0', + // Standard package.json path coming from the project root + packageJsonPath: 'packages/projectC/package.json', + localDependencies: [], + }, + projectD: { + projectRoot: 'packages/projectD', + packageName: 'projectD', + version: '1.0.0', + // Standard package.json path coming from the project root + packageJsonPath: 'packages/projectD/package.json', + localDependencies: [], + }, + }); + }); + + it('should resolve local dependencies using custom package roots', () => { + const allProjects = Object.values(projectGraph.nodes); + const projectNameToPackageRootMap = new Map(); + projectNameToPackageRootMap.set('projectA', 'build/packages/projectA'); + projectNameToPackageRootMap.set('projectB', 'build/packages/projectB'); + projectNameToPackageRootMap.set('projectC', 'packages/projectC'); + projectNameToPackageRootMap.set('projectD', 'packages/projectD'); + + const result = resolveLocalPackageDependencies( + tree, + projectGraph, + allProjects, + projectNameToPackageRootMap + ); + + expect(result).toMatchInlineSnapshot(` + { + "projectA": [ + { + "dependencyCollection": "dependencies", + "source": "projectA", + "target": "projectB", + "type": "static", + }, + { + "dependencyCollection": "dependencies", + "source": "projectA", + "target": "projectC", + "type": "static", + }, + { + "dependencyCollection": "dependencies", + "source": "projectA", + "target": "projectD", + "type": "static", + }, + ], + } + `); + }); + }); +}); diff --git a/packages/js/src/generators/release-version/utils/resolve-local-package-dependencies.ts b/packages/js/src/generators/release-version/utils/resolve-local-package-dependencies.ts new file mode 100644 index 0000000000000..ac2997d0d65d7 --- /dev/null +++ b/packages/js/src/generators/release-version/utils/resolve-local-package-dependencies.ts @@ -0,0 +1,105 @@ +import { + ProjectGraph, + ProjectGraphDependency, + ProjectGraphProjectNode, + Tree, + joinPathFragments, + readJson, + workspaceRoot, +} from '@nx/devkit'; +import { PackageJson } from 'nx/src/utils/package-json'; +import { satisfies } from 'semver'; +import { Package } from './package'; +import { resolveVersionSpec } from './resolve-version-spec'; + +interface LocalPackageDependency extends ProjectGraphDependency { + dependencyCollection: + | 'dependencies' + | 'devDependencies' + | 'optionalDependencies'; + // we don't currently manage peer dependencies +} + +export function resolveLocalPackageDependencies( + tree: Tree, + projectGraph: ProjectGraph, + projects: ProjectGraphProjectNode[], + projectNameToPackageRootMap: Map +): Record { + const localPackageDependencies: Record = {}; + const projectNodeToPackageMap = new Map(); + + // Iterate through the projects being released and resolve any relevant package.json data + for (const projectNode of projects) { + // Resolve the package.json path for the project, taking into account any custom packageRoot settings + const packageRoot = projectNameToPackageRootMap.get(projectNode.name); + if (!packageRoot) { + continue; + } + const packageJson = readJson( + tree, + joinPathFragments(packageRoot, 'package.json') + ) as PackageJson; + const pkg = new Package(packageJson, workspaceRoot, packageRoot); + projectNodeToPackageMap.set(projectNode, pkg); + } + + // populate local npm package dependencies + for (const projectDeps of Object.values(projectGraph.dependencies)) { + const workspaceDeps = projectDeps.filter( + (dep) => + !isExternalNpmDependency(dep.target) && + !isExternalNpmDependency(dep.source) + ); + for (const dep of workspaceDeps) { + const source = projectGraph.nodes[dep.source]; + const target = projectGraph.nodes[dep.target]; + if ( + !source || + !projectNodeToPackageMap.has(source) || + !target || + !projectNodeToPackageMap.has(target) + ) { + // only relevant for dependencies between two workspace projects with Package objects + continue; + } + + const sourcePackage = projectNodeToPackageMap.get(source); + const targetPackage = projectNodeToPackageMap.get(target); + const sourceNpmDependency = sourcePackage.getLocalDependency( + targetPackage.name + ); + if (!sourceNpmDependency) { + continue; + } + + const targetVersionSpec = resolveVersionSpec( + targetPackage.name, + targetPackage.version, + sourceNpmDependency.spec, + sourcePackage.location + ); + const targetMatchesRequirement = + // For file: and workspace: protocols the targetVersionSpec could be a path, so we check if it matches the target's location + targetVersionSpec === targetPackage.location || + satisfies(targetPackage.version, targetVersionSpec); + + if (targetMatchesRequirement) { + // track only local package dependencies that are satisfied by the target's version + localPackageDependencies[dep.source] = [ + ...(localPackageDependencies[dep.source] || []), + { + ...dep, + dependencyCollection: sourceNpmDependency.collection, + }, + ]; + } + } + } + + return localPackageDependencies; +} + +function isExternalNpmDependency(dep: string): boolean { + return dep.startsWith('npm:'); +} diff --git a/packages/js/src/generators/release-version/utils/resolve-version-spec.spec.ts b/packages/js/src/generators/release-version/utils/resolve-version-spec.spec.ts new file mode 100644 index 0000000000000..a767f8e970b06 --- /dev/null +++ b/packages/js/src/generators/release-version/utils/resolve-version-spec.spec.ts @@ -0,0 +1,83 @@ +import { join } from 'path'; +import { resolveVersionSpec } from './resolve-version-spec'; + +describe('resolveVersionSpec()', () => { + it('should work for specific name and spec', () => { + expect( + resolveVersionSpec( + 'projectA', + '1.0.4', + '^1.0.0', + '/test/packages/packageB' + ) + ).toEqual('^1.0.0'); + }); + + it('should work for a workspace spec', () => { + expect( + resolveVersionSpec( + 'projectA', + '1.0.4', + 'workspace:^1.0.0', + '/test/packages/packageB' + ) + ).toEqual('^1.0.0'); + }); + + describe('with a workspace alias', () => { + it('should work for a * workspace alias', () => { + expect( + resolveVersionSpec( + 'projectA', + '1.0.4', + 'workspace:*', + '/test/packages/packageB' + ) + ).toEqual('1.0.4'); + }); + + it('should work for a ^ workspace alias', () => { + expect( + resolveVersionSpec( + 'projectA', + '1.0.4', + 'workspace:^', + '/test/packages/packageB' + ) + ).toEqual('^1.0.4'); + }); + + it('should work for a ~ workspace alias', () => { + expect( + resolveVersionSpec( + 'projectA', + '1.0.4', + 'workspace:~', + '/test/packages/packageB' + ) + ).toEqual('~1.0.4'); + }); + }); + + it('should for a file reference', async () => { + expect( + resolveVersionSpec( + 'projectA', + '1.0.0', + 'file:../projectB', + '/packages/projectB' + ) + ).toEqual(expect.stringContaining(join('/packages/projectB'))); + }); + + it('should work for a yarn classic style link reference', async () => { + expect( + resolveVersionSpec( + 'projectA', + '1.0.0', + 'link:../projectB', + '/packages/fuck' + ) + ).toEqual(expect.stringContaining(join('/packages/projectB'))); + }); +}); diff --git a/packages/js/src/generators/release-version/utils/resolve-version-spec.ts b/packages/js/src/generators/release-version/utils/resolve-version-spec.ts new file mode 100644 index 0000000000000..81a4d87ace2d5 --- /dev/null +++ b/packages/js/src/generators/release-version/utils/resolve-version-spec.ts @@ -0,0 +1,30 @@ +import * as npa from 'npm-package-arg'; + +export function resolveVersionSpec( + name: string, + version: string, + spec: string, + location?: string +): string { + // yarn classic uses link instead of file, normalize to match what npm expects + spec = spec.replace(/^link:/, 'file:'); + + // Support workspace: protocol for pnpm and yarn 2+ (https://pnpm.io/workspaces#workspace-protocol-workspace) + const isWorkspaceSpec = /^workspace:/.test(spec); + if (isWorkspaceSpec) { + spec = spec.replace(/^workspace:/, ''); + // replace aliases (https://pnpm.io/workspaces#referencing-workspace-packages-through-aliases) + if (spec === '*' || spec === '^' || spec === '~') { + if (version) { + const prefix = spec === '*' ? '' : spec; + spec = `${prefix}${version}`; + } else { + spec = '*'; + } + } + } + + const npaResult = npa.resolve(name, spec, location); + + return npaResult.fetchSpec; +} diff --git a/packages/nx/package.json b/packages/nx/package.json index 243f1a569223d..b61459fea83d0 100644 --- a/packages/nx/package.json +++ b/packages/nx/package.json @@ -49,6 +49,7 @@ "fs-extra": "^11.1.0", "glob": "7.1.4", "ignore": "^5.0.4", + "jest-diff": "^29.4.1", "js-yaml": "4.1.0", "jsonc-parser": "3.2.0", "lines-and-columns": "~2.0.3", diff --git a/packages/nx/plugins/package-json-workspaces.spec.ts b/packages/nx/plugins/package-json-workspaces.spec.ts index df30a43d652f7..4499d091cd71f 100644 --- a/packages/nx/plugins/package-json-workspaces.spec.ts +++ b/packages/nx/plugins/package-json-workspaces.spec.ts @@ -52,6 +52,10 @@ describe('nx package.json workspaces plugin', () => { "script": "echo", }, }, + "release-publish": { + "executor": "@nx/js:release-publish", + "options": {}, + }, }, }, }, @@ -67,6 +71,10 @@ describe('nx package.json workspaces plugin', () => { "root": "packages/lib-a", "sourceRoot": "packages/lib-a", "targets": { + "release-publish": { + "executor": "@nx/js:release-publish", + "options": {}, + }, "test": { "executor": "nx:run-script", "options": { @@ -104,6 +112,10 @@ describe('nx package.json workspaces plugin', () => { "{projectRoot}/dist", ], }, + "release-publish": { + "executor": "@nx/js:release-publish", + "options": {}, + }, "test": { "executor": "nx:run-script", "options": { diff --git a/packages/nx/src/command-line/affected/affected.ts b/packages/nx/src/command-line/affected/affected.ts index e7bda358cb508..e62c2e9134759 100644 --- a/packages/nx/src/command-line/affected/affected.ts +++ b/packages/nx/src/command-line/affected/affected.ts @@ -104,7 +104,7 @@ export async function affected( projectNames ); } else { - await runCommand( + const status = await runCommand( projectsWithTarget, projectGraph, { nxJson }, @@ -114,6 +114,9 @@ export async function affected( extraTargetDependencies, { excludeTaskDependencies: false, loadDotEnvFiles: true } ); + // fix for https://github.com/nrwl/nx/issues/1666 + if (process.stdin['unref']) (process.stdin as any).unref(); + process.exit(status); } break; } diff --git a/packages/nx/src/command-line/generate/generate.ts b/packages/nx/src/command-line/generate/generate.ts index d3181c383c01b..d560d98bcb3c2 100644 --- a/packages/nx/src/command-line/generate/generate.ts +++ b/packages/nx/src/command-line/generate/generate.ts @@ -184,7 +184,7 @@ async function promptForCollection( } } -function parseGeneratorString(value: string): { +export function parseGeneratorString(value: string): { collection?: string; generator: string; } { diff --git a/packages/nx/src/command-line/nx-commands.ts b/packages/nx/src/command-line/nx-commands.ts index 769782ee2fb80..beed4e67b4d91 100644 --- a/packages/nx/src/command-line/nx-commands.ts +++ b/packages/nx/src/command-line/nx-commands.ts @@ -40,6 +40,7 @@ import { yargsShowCommand } from './show/command-object'; import { yargsWatchCommand } from './watch/command-object'; import { yargsWorkspaceLintCommand } from './workspace-lint/command-object'; import { yargsResetCommand } from './reset/command-object'; +import { yargsReleaseCommand } from './release/command-object'; // Ensure that the output takes up the available width of the terminal. yargs.wrap(yargs.terminalWidth()); @@ -78,6 +79,7 @@ export const commandsObject = yargs .command(yargsMigrateCommand) .command(yargsNewCommand) .command(yargsPrintAffectedCommand) + .command(yargsReleaseCommand) .command(yargsRepairCommand) .command(yargsReportCommand) .command(yargsResetCommand) diff --git a/packages/nx/src/command-line/release/changelog.ts b/packages/nx/src/command-line/release/changelog.ts new file mode 100644 index 0000000000000..0133c017b64ed --- /dev/null +++ b/packages/nx/src/command-line/release/changelog.ts @@ -0,0 +1,163 @@ +import * as chalk from 'chalk'; +import { readFileSync, writeFileSync } from 'node:fs'; +import { dirSync } from 'tmp'; +import { joinPathFragments, logger, output } from '../../devkit-exports'; +import { ChangelogOptions } from './command-object'; +import { getGitDiff, getLastGitTag, parseCommits } from './utils/git'; +import { + GithubRelease, + GithubRequestConfig, + createOrUpdateGithubRelease, + generateMarkdown, + getGitHubRemote, + getGithubReleaseByTag, + resolveGithubToken, +} from './utils/github'; +import { launchEditor } from './utils/launch-editor'; +import { printDiff } from './utils/print-diff'; + +export async function changelogHandler(args: ChangelogOptions): Promise { + /** + * TODO: allow the prefix and version to be controllable via config as well once we flesh out + * changelog customization, and how it will interact with independently released projects. + */ + const tagVersionPrefix = args.tagVersionPrefix ?? 'v'; + const releaseVersion = `${tagVersionPrefix}${args.version}`; + + const githubRemote = getGitHubRemote(args.gitRemote); + const token = await resolveGithubToken(); + const githubRequestConfig: GithubRequestConfig = { + repo: githubRemote, + token, + }; + + const from = args.from || (await getLastGitTag()); + if (!from) { + throw new Error( + `Could not determine the previous git tag, please provide and explicit reference using --from` + ); + } + const to = args.to; + const rawCommits = await getGitDiff(from, args.to); + + // Parse as conventional commits + const commits = parseCommits(rawCommits).filter((c) => { + const type = c.type; + // Always ignore non user-facing commits for now + // TODO: allow this filter to be configurable via config in a future release + if (type === 'feat' || type === 'fix' || type === 'perf') { + return true; + } + return false; + }); + + const initialMarkdown = await generateMarkdown( + commits, + releaseVersion, + githubRequestConfig + ); + + let finalMarkdown = initialMarkdown; + + /** + * If interactive mode, make the markdown available for the user to modify in their editor of choice, + * in a similar style to git interactive rebases/merges. + */ + if (args.interactive) { + const tmpDir = dirSync().name; + const changelogPath = joinPathFragments(tmpDir, 'c.md'); + writeFileSync(changelogPath, initialMarkdown); + await launchEditor(changelogPath); + finalMarkdown = readFileSync(changelogPath, 'utf-8'); + } + + let existingGithubReleaseForVersion: GithubRelease; + try { + existingGithubReleaseForVersion = await getGithubReleaseByTag( + githubRequestConfig, + releaseVersion + ); + } catch (err) { + if (err.response?.status === 401) { + output.error({ + title: `Unable to resolve data via the Github API. You can use any of the following options to resolve this:`, + bodyLines: [ + '- Set the `GITHUB_TOKEN` or `GH_TOKEN` environment variable to a valid Github token with `repo` scope', + '- Have an active session via the official gh CLI tool (https://cli.github.com) in your current terminal', + ], + }); + process.exit(1); + } + if (err.response?.status === 404) { + // No existing release found, this is fine + } else { + // Rethrow unknown errors for now + throw err; + } + } + + const changesRangeText = + to === 'HEAD' ? `since ${from}` : `between ${from} and ${to}`; + + if (existingGithubReleaseForVersion) { + output.log({ + title: `Found existing Github release for ${chalk.white( + releaseVersion + )}, regenerating with changes ${chalk.cyan(changesRangeText)}`, + }); + } else { + output.log({ + title: `Creating a new Github release for ${chalk.white( + releaseVersion + )}, including changes ${chalk.cyan(changesRangeText)}`, + }); + } + + printReleaseLog( + releaseVersion, + githubRemote, + args.dryRun, + finalMarkdown, + existingGithubReleaseForVersion + ); + + if (args.dryRun) { + logger.warn(`\nNOTE: The "dryRun" flag means no changes were made.`); + } else { + await createOrUpdateGithubRelease( + githubRequestConfig, + { + version: releaseVersion, + body: finalMarkdown, + }, + existingGithubReleaseForVersion + ); + } + + process.exit(0); +} + +function printReleaseLog( + releaseVersion: string, + githubRemote: string, + isDryRun: boolean, + finalMarkdown: string, + existingGithubReleaseForVersion?: GithubRelease +) { + const logTitle = `https://github.com/${githubRemote}/releases/tag/${releaseVersion}`; + if (existingGithubReleaseForVersion) { + console.error( + `${chalk.white('UPDATE')} ${logTitle}${ + isDryRun ? chalk.keyword('orange')(' [dry-run]') : '' + }` + ); + } else { + console.error( + `${chalk.green('CREATE')} ${logTitle}${ + isDryRun ? chalk.keyword('orange')(' [dry-run]') : '' + }` + ); + } + console.log(''); + printDiff('', finalMarkdown); +} diff --git a/packages/nx/src/command-line/release/command-object.ts b/packages/nx/src/command-line/release/command-object.ts new file mode 100644 index 0000000000000..572d9e486ed9f --- /dev/null +++ b/packages/nx/src/command-line/release/command-object.ts @@ -0,0 +1,165 @@ +import { CommandModule, showHelp } from 'yargs'; +import { readNxJson } from '../../project-graph/file-utils'; +import { parseCSV } from '../yargs-utils/shared-options'; + +export interface NxReleaseArgs { + groups?: string[]; + projects?: string[]; + dryRun?: boolean; +} + +export type VersionOptions = NxReleaseArgs & { + specifier?: string; +}; + +export type ChangelogOptions = NxReleaseArgs & { + version: string; + to: string; + from?: string; + interactive?: boolean; + gitRemote?: string; + tagVersionPrefix?: string; +}; + +export type PublishOptions = NxReleaseArgs & { + registry?: string; + tag?: string; +}; + +export const yargsReleaseCommand: CommandModule< + Record, + NxReleaseArgs +> = { + command: 'release', + describe: + '**ALPHA**: Orchestrate versioning and publishing of applications and libraries', + builder: (yargs) => + yargs + .command(versionCommand) + .command(changelogCommand) + .command(publishCommand) + .demandCommand() + .option('groups', { + description: + 'One or more release groups to target with the current command.', + type: 'string', + coerce: parseCSV, + alias: ['group', 'g'], + }) + .option('projects', { + type: 'string', + alias: 'p', + coerce: parseCSV, + describe: + 'Projects to run. (comma/space delimited project names and/or patterns)', + }) + .option('dryRun', { + describe: + 'Preview the changes without updating files/creating releases', + alias: 'd', + type: 'boolean', + default: false, + }) + .check((argv) => { + if (argv.groups && argv.projects) { + throw new Error( + 'The --projects and --groups options are mutually exclusive, please use one or the other.' + ); + } + const nxJson = readNxJson(); + if (argv.groups?.length) { + for (const group of argv.groups) { + if (!nxJson.release?.groups?.[group]) { + throw new Error( + `The specified release group "${group}" was not found in nx.json` + ); + } + } + } + return true; + }) as any, // the type: 'string' and coerce: parseCSV combo isn't enough to produce the string[] type for projects and groups + handler: async () => { + showHelp(); + process.exit(1); + }, +}; + +const versionCommand: CommandModule = { + command: 'version [specifier]', + aliases: ['v'], + describe: + 'Create a version and release for one or more applications and libraries', + builder: (yargs) => + yargs.positional('specifier', { + type: 'string', + describe: + 'Exact version or semver keyword to apply to the selected release group.', + }), + handler: (args) => import('./version').then((m) => m.versionHandler(args)), +}; + +const changelogCommand: CommandModule = { + command: 'changelog [version]', + aliases: ['c'], + describe: + 'Generate a changelog for one or more projects, and optionally push to Github', + builder: (yargs) => + yargs + // Disable default meaning of yargs version for this command + .version(false) + .positional('version', { + type: 'string', + description: 'The version to create a Github release and changelog for', + }) + .option('from', { + type: 'string', + description: + 'The git reference to use as the start of the changelog. If not set it will attempt to resolve the latest tag and use that', + }) + .option('to', { + type: 'string', + description: 'The git reference to use as the end of the changelog', + default: 'HEAD', + }) + .option('interactive', { + alias: 'i', + type: 'boolean', + }) + .option('gitRemote', { + type: 'string', + description: + 'Alternate git remote in the form {user}/{repo} on which to create the Github release (useful for testing)', + default: 'origin', + }) + .option('tagVersionPrefix', { + type: 'string', + description: + 'Prefix to apply to the version when creating the Github release tag', + default: 'v', + }) + .check((argv) => { + if (!argv.version) { + throw new Error('A target version must be specified'); + } + return true; + }), + handler: (args) => + import('./changelog').then((m) => m.changelogHandler(args)), +}; + +const publishCommand: CommandModule = { + command: 'publish', + aliases: ['p'], + describe: 'Publish a versioned project to a registry', + builder: (yargs) => + yargs + .option('registry', { + type: 'string', + description: 'The registry to publish to', + }) + .option('tag', { + type: 'string', + description: 'The distribution tag to apply to the published package', + }), + handler: (args) => import('./publish').then((m) => m.publishHandler(args)), +}; diff --git a/packages/nx/src/command-line/release/config/config.spec.ts b/packages/nx/src/command-line/release/config/config.spec.ts new file mode 100644 index 0000000000000..15ad7bbdb0858 --- /dev/null +++ b/packages/nx/src/command-line/release/config/config.spec.ts @@ -0,0 +1,48 @@ +import { createNxReleaseConfig } from './config'; + +describe('createNxReleaseConfig()', () => { + const testCases = [ + { + input: undefined, + output: { + groups: {}, + }, + }, + { + input: {}, + output: { + groups: {}, + }, + }, + { + input: { + groups: {}, + }, + output: { + groups: {}, + }, + }, + { + input: { + groups: { + foo: { + projects: '*', + }, + }, + }, + output: { + groups: { + foo: { + projects: '*', + }, + }, + }, + }, + ]; + + testCases.forEach((c, i) => { + it(`should create appropriate NxReleaseConfig, CASE: ${i}`, () => { + expect(createNxReleaseConfig(c.input)).toEqual(c.output); + }); + }); +}); diff --git a/packages/nx/src/command-line/release/config/config.ts b/packages/nx/src/command-line/release/config/config.ts new file mode 100644 index 0000000000000..ad79bede01b2b --- /dev/null +++ b/packages/nx/src/command-line/release/config/config.ts @@ -0,0 +1,12 @@ +import { NxJsonConfiguration } from '../../../devkit-exports'; + +// Apply default configuration to any optional user configuration +export function createNxReleaseConfig( + userConfig: NxJsonConfiguration['release'] = {} +): Required { + const nxReleaseConfig: Required = { + ...userConfig, + groups: userConfig.groups || {}, + }; + return nxReleaseConfig; +} diff --git a/packages/nx/src/command-line/release/config/create-release-groups.spec.ts b/packages/nx/src/command-line/release/config/create-release-groups.spec.ts new file mode 100644 index 0000000000000..b02d303e83123 --- /dev/null +++ b/packages/nx/src/command-line/release/config/create-release-groups.spec.ts @@ -0,0 +1,249 @@ +import { ProjectGraph } from '../../../devkit-exports'; +import { createReleaseGroups } from './create-release-groups'; + +describe('create-release-groups', () => { + let projectGraph: ProjectGraph; + + beforeEach(() => { + projectGraph = { + nodes: { + 'lib-a': { + name: 'lib-a', + type: 'lib', + data: { + root: 'libs/lib-a', + targets: { + 'release-publish': {}, + }, + } as any, + }, + 'lib-b': { + name: 'lib-b', + type: 'lib', + data: { + root: 'libs/lib-b', + targets: { + 'release-publish': {}, + }, + } as any, + }, + }, + dependencies: {}, + }; + }); + + describe('no user specified groups', () => { + it('should return a catch all release group containing all projects when no groups are specified', async () => { + const res = await createReleaseGroups(projectGraph, {}); + expect(res).toMatchInlineSnapshot(` + { + "error": null, + "releaseGroups": [ + { + "name": "__default__", + "projects": [ + "lib-a", + "lib-b", + ], + "version": { + "generator": "@nx/js:release-version", + "generatorOptions": {}, + }, + }, + ], + } + `); + }); + }); + + describe('user specified groups', () => { + it('should ignore any projects not matched to user specified groups', async () => { + const res = await createReleaseGroups(projectGraph, { + 'group-1': { + projects: ['lib-a'], // intentionally no lib-b, so it should be ignored + }, + }); + expect(res).toMatchInlineSnapshot(` + { + "error": null, + "releaseGroups": [ + { + "name": "group-1", + "projects": [ + "lib-a", + ], + "version": { + "generator": "@nx/js:release-version", + "generatorOptions": {}, + }, + }, + ], + } + `); + }); + + it('should respect user overrides for "version" config', async () => { + const res = await createReleaseGroups(projectGraph, { + 'group-1': { + projects: ['lib-a'], + version: { + generator: '@custom/generator', + generatorOptions: { + optionsOverride: 'something', + }, + }, + }, + 'group-2': { + projects: ['lib-b'], + version: { + generator: '@custom/generator-alternative', + }, + }, + }); + expect(res).toMatchInlineSnapshot(` + { + "error": null, + "releaseGroups": [ + { + "name": "group-1", + "projects": [ + "lib-a", + ], + "version": { + "generator": "@custom/generator", + "generatorOptions": { + "optionsOverride": "something", + }, + }, + }, + { + "name": "group-2", + "projects": [ + "lib-b", + ], + "version": { + "generator": "@custom/generator-alternative", + "generatorOptions": {}, + }, + }, + ], + } + `); + }); + }); + + describe('release group config errors', () => { + it('should return an error if a project matches multiple groups', async () => { + const res = await createReleaseGroups(projectGraph, { + 'group-1': { + projects: ['lib-a'], + }, + 'group-2': { + projects: ['lib-a'], + }, + }); + expect(res).toMatchInlineSnapshot(` + { + "error": { + "code": "PROJECT_MATCHES_MULTIPLE_GROUPS", + "data": { + "project": "lib-a", + }, + }, + "releaseGroups": [], + } + `); + }); + + it('should return an error if no projects can be resolved for a group', async () => { + const res = await createReleaseGroups(projectGraph, { + 'group-1': { + projects: ['lib-does-not-exist'], + }, + }); + expect(res).toMatchInlineSnapshot(` + { + "error": { + "code": "RELEASE_GROUP_MATCHES_NO_PROJECTS", + "data": { + "releaseGroupName": "group-1", + }, + }, + "releaseGroups": [], + } + `); + }); + + it('should return an error if any matched projects do not have the required target specified', async () => { + const res = await createReleaseGroups( + { + ...projectGraph, + nodes: { + ...projectGraph.nodes, + 'project-without-target': { + name: 'project-without-target', + type: 'lib', + data: { + root: 'libs/project-without-target', + targets: {}, + } as any, + }, + }, + }, + { + 'group-1': { + projects: '*', // using string form to ensure that is supported in addition to array form + }, + }, + 'release-publish' + ); + expect(res).toMatchInlineSnapshot(` + { + "error": { + "code": "PROJECTS_MISSING_TARGET", + "data": { + "projects": [ + "project-without-target", + ], + "targetName": "release-publish", + }, + }, + "releaseGroups": [], + } + `); + + const res2 = await createReleaseGroups( + { + ...projectGraph, + nodes: { + ...projectGraph.nodes, + 'another-project-without-target': { + name: 'another-project-without-target', + type: 'lib', + data: { + root: 'libs/another-project-without-target', + targets: {}, + } as any, + }, + }, + }, + {}, + 'release-publish' + ); + expect(res2).toMatchInlineSnapshot(` + { + "error": { + "code": "PROJECTS_MISSING_TARGET", + "data": { + "projects": [ + "another-project-without-target", + ], + "targetName": "release-publish", + }, + }, + "releaseGroups": [], + } + `); + }); + }); +}); diff --git a/packages/nx/src/command-line/release/config/create-release-groups.ts b/packages/nx/src/command-line/release/config/create-release-groups.ts new file mode 100644 index 0000000000000..9406b535d39ea --- /dev/null +++ b/packages/nx/src/command-line/release/config/create-release-groups.ts @@ -0,0 +1,225 @@ +import type { NxJsonConfiguration } from '../../../config/nx-json'; +import { output, type ProjectGraph } from '../../../devkit-exports'; +import { findMatchingProjects } from '../../../utils/find-matching-projects'; +import { projectHasTarget } from '../../../utils/project-graph-utils'; +import { resolveNxJsonConfigErrorMessage } from '../utils/resolve-nx-json-error-message'; + +export interface ReleaseGroup { + name: string; + projects: string[]; + version: { + generator: string; + generatorOptions: Record; + }; +} + +// We explicitly handle some expected errors in order to provide the best possible DX +interface CreateReleaseGroupsError { + code: + | 'RELEASE_GROUP_MATCHES_NO_PROJECTS' + | 'PROJECT_MATCHES_MULTIPLE_GROUPS' + | 'PROJECTS_MISSING_TARGET'; + data: Record; +} + +export const CATCH_ALL_RELEASE_GROUP = '__default__'; + +/** + * Create a set of release groups based on the relevant user specified config ready + * to be consumed by the release commands. + */ +export async function createReleaseGroups( + projectGraph: ProjectGraph, + userSpecifiedGroups: NxJsonConfiguration['release']['groups'] = {}, + requiredTargetName?: 'release-publish' +): Promise<{ + error: null | CreateReleaseGroupsError; + releaseGroups: ReleaseGroup[]; +}> { + const DEFAULT_VERSION_GENERATOR = '@nx/js:release-version'; + const DEFAULT_VERSION_GENERATOR_OPTIONS = {}; + + const allProjects = findMatchingProjects(['*'], projectGraph.nodes); + + /** + * No user specified release groups, so we treat all projects as being in one release group + * together in which all projects are released in lock step. + */ + if (Object.keys(userSpecifiedGroups).length === 0) { + // Ensure all projects have the relevant target available, if applicable + if (requiredTargetName) { + const error = ensureProjectsHaveTarget( + allProjects, + projectGraph, + requiredTargetName + ); + if (error) { + return { + error, + releaseGroups: [], + }; + } + } + + return { + error: null, + releaseGroups: [ + { + name: CATCH_ALL_RELEASE_GROUP, + projects: allProjects, + version: { + generator: DEFAULT_VERSION_GENERATOR, + generatorOptions: DEFAULT_VERSION_GENERATOR_OPTIONS, + }, + }, + ], + }; + } + + /** + * The user has specified at least one release group. + * + * Resolve all the project names into their release groups, and check + * that individual projects are not found in multiple groups. + */ + const releaseGroups: ReleaseGroup[] = []; + const alreadyMatchedProjects = new Set(); + + for (const [releaseGroupName, userSpecifiedGroup] of Object.entries( + userSpecifiedGroups + )) { + // Ensure that the user config for the release group can resolve at least one project + const matchingProjects = findMatchingProjects( + Array.isArray(userSpecifiedGroup.projects) + ? userSpecifiedGroup.projects + : [userSpecifiedGroup.projects], + projectGraph.nodes + ); + if (!matchingProjects.length) { + return { + error: { + code: 'RELEASE_GROUP_MATCHES_NO_PROJECTS', + data: { + releaseGroupName: releaseGroupName, + }, + }, + releaseGroups: [], + }; + } + + // Ensure all matching projects have the relevant target available, if applicable + if (requiredTargetName) { + const error = ensureProjectsHaveTarget( + matchingProjects, + projectGraph, + requiredTargetName + ); + if (error) { + return { + error, + releaseGroups: [], + }; + } + } + + for (const project of matchingProjects) { + if (alreadyMatchedProjects.has(project)) { + return { + error: { + code: 'PROJECT_MATCHES_MULTIPLE_GROUPS', + data: { + project, + }, + }, + releaseGroups: [], + }; + } + alreadyMatchedProjects.add(project); + } + releaseGroups.push({ + name: releaseGroupName, + projects: matchingProjects, + version: userSpecifiedGroup.version + ? { + generator: + userSpecifiedGroup.version.generator || DEFAULT_VERSION_GENERATOR, + generatorOptions: + userSpecifiedGroup.version.generatorOptions || + DEFAULT_VERSION_GENERATOR_OPTIONS, + } + : { + generator: DEFAULT_VERSION_GENERATOR, + generatorOptions: DEFAULT_VERSION_GENERATOR_OPTIONS, + }, + }); + } + + return { + error: null, + releaseGroups, + }; +} + +export async function handleCreateReleaseGroupsError( + error: CreateReleaseGroupsError +) { + switch (error.code) { + case 'RELEASE_GROUP_MATCHES_NO_PROJECTS': + { + const nxJsonMessage = await resolveNxJsonConfigErrorMessage([ + 'release', + 'groups', + ]); + output.error({ + title: `Release group "${error.data.releaseGroupName}" matches no projects. Please ensure all release groups match at least one project:`, + bodyLines: [nxJsonMessage], + }); + } + break; + case 'PROJECT_MATCHES_MULTIPLE_GROUPS': + { + const nxJsonMessage = await resolveNxJsonConfigErrorMessage([ + 'release', + 'groups', + ]); + output.error({ + title: `Project "${error.data.project}" matches multiple release groups. Please ensure all projects are part of only one release group:`, + bodyLines: [nxJsonMessage], + }); + } + break; + case 'PROJECTS_MISSING_TARGET': + { + output.error({ + title: `Based on your config, the following projects were matched for release but do not have a "${error.data.targetName}" target specified. Please ensure you have an appropriate plugin such as @nx/js installed, or have configured the target manually, or exclude the projects using release groups config in nx.json:`, + bodyLines: Array.from(error.data.projects).map((name) => `- ${name}`), + }); + } + break; + default: + throw new Error(`Unhandled error code: ${error.code}`); + } + + process.exit(1); +} + +function ensureProjectsHaveTarget( + projects: string[], + projectGraph: ProjectGraph, + requiredTargetName: string +): null | CreateReleaseGroupsError { + const missingTargetProjects = projects.filter( + (project) => + !projectHasTarget(projectGraph.nodes[project], requiredTargetName) + ); + if (missingTargetProjects.length) { + return { + code: 'PROJECTS_MISSING_TARGET', + data: { + targetName: requiredTargetName, + projects: missingTargetProjects, + }, + }; + } + return null; +} diff --git a/packages/nx/src/command-line/release/publish.ts b/packages/nx/src/command-line/release/publish.ts new file mode 100644 index 0000000000000..842f7b97f42af --- /dev/null +++ b/packages/nx/src/command-line/release/publish.ts @@ -0,0 +1,213 @@ +import { readNxJson } from '../../config/nx-json'; +import { + ProjectGraph, + ProjectGraphProjectNode, +} from '../../config/project-graph'; +import { NxJsonConfiguration, output } from '../../devkit-exports'; +import { createProjectGraphAsync } from '../../project-graph/project-graph'; +import { runCommand } from '../../tasks-runner/run-command'; +import { + NxArgs, + splitArgsIntoNxArgsAndOverrides, +} from '../../utils/command-line-utils'; +import { findMatchingProjects } from '../../utils/find-matching-projects'; +import { PublishOptions } from './command-object'; +import { createNxReleaseConfig } from './config/config'; +import { + CATCH_ALL_RELEASE_GROUP, + ReleaseGroup, + createReleaseGroups, + handleCreateReleaseGroupsError, +} from './config/create-release-groups'; + +export async function publishHandler(args: PublishOptions): Promise { + const projectGraph = await createProjectGraphAsync({ exitOnError: true }); + const nxJson = readNxJson(); + + const { nxArgs, overrides } = splitArgsIntoNxArgsAndOverrides( + args, + 'release', + { printWarnings: false }, + nxJson + ); + nxArgs.targets = ['release-publish']; + // We are not prioritizing raw speed for publishing execution, we are prioritizing clear useful output + nxArgs.parallel = 1; + nxArgs.outputStyle = 'stream'; + if (nxArgs.verbose) { + process.env.NX_VERBOSE_LOGGING = 'true'; + } + + /** + * TODO: We seem to need to explicitly add the possible CLI flags to the overrides in order for runCommand to work correctly. + * We can't leave this out, otherwise the options will not be set on the executor, nor can we generically spread the args, + * because then a ton of excess properties will be passed to the executor... This makes this code brittle as we could forget + * to update this when we make schema changes and it should be looked into in more detail in a follow up. + */ + if (args.registry) { + overrides.registry = args.registry; + } + if (args.tag) { + overrides.tag = args.tag; + } + + // Apply default configuration to any optional user configuration + const nxReleaseConfig = createNxReleaseConfig(nxJson.release); + const releaseGroupsData = await createReleaseGroups( + projectGraph, + nxReleaseConfig.groups + ); + if (releaseGroupsData.error) { + return await handleCreateReleaseGroupsError(releaseGroupsData.error); + } + + let { releaseGroups } = releaseGroupsData; + + /** + * User is filtering to a subset of projects. We need to make sure that what they have provided can be reconciled + * against their configuration in terms of release groups and the ungroupedProjectsHandling option. + */ + if (args.projects?.length) { + const matchingProjectsForFilter = findMatchingProjects( + args.projects, + projectGraph.nodes + ); + + if (!matchingProjectsForFilter.length) { + output.error({ + title: `Your --projects filter "${args.projects}" did not match any projects in the workspace`, + }); + process.exit(1); + } + + const filteredProjectToReleaseGroup = new Map(); + const releaseGroupToFilteredProjects = new Map>(); + + // Figure out which release groups, if any, that the filtered projects belong to so that we can resolve other config + for (const releaseGroup of releaseGroups) { + const matchingProjectsForReleaseGroup = findMatchingProjects( + releaseGroup.projects, + projectGraph.nodes + ); + for (const matchingProject of matchingProjectsForFilter) { + if (matchingProjectsForReleaseGroup.includes(matchingProject)) { + filteredProjectToReleaseGroup.set(matchingProject, releaseGroup); + if (!releaseGroupToFilteredProjects.has(releaseGroup)) { + releaseGroupToFilteredProjects.set(releaseGroup, new Set()); + } + releaseGroupToFilteredProjects.get(releaseGroup).add(matchingProject); + } + } + } + + /** + * If there are release groups specified, each filtered project must match at least one release + * group, otherwise the command + config combination is invalid. + */ + if (Object.keys(nxReleaseConfig.groups).length) { + const unmatchedProjects = matchingProjectsForFilter.filter( + (p) => !filteredProjectToReleaseGroup.has(p) + ); + if (unmatchedProjects.length) { + output.error({ + title: `The following projects which match your projects filter "${args.projects}" did not match any configured release groups:`, + bodyLines: unmatchedProjects.map((p) => `- ${p}`), + }); + process.exit(1); + } + } + + output.note({ + title: `Your filter "${args.projects}" matched the following projects:`, + bodyLines: matchingProjectsForFilter.map((p) => { + const releaseGroupForProject = filteredProjectToReleaseGroup.get(p); + if (releaseGroupForProject.name === CATCH_ALL_RELEASE_GROUP) { + return `- ${p}`; + } + return `- ${p} (release group "${releaseGroupForProject.name}")`; + }), + }); + + // Filter the releaseGroups collection appropriately + releaseGroups = releaseGroups.filter((rg) => + releaseGroupToFilteredProjects.has(rg) + ); + + /** + * Run publishing for all remaining release groups and filtered projects within them + */ + for (const releaseGroup of releaseGroups) { + await runPublishOnProjects( + projectGraph, + nxJson, + nxArgs, + overrides, + Array.from(releaseGroupToFilteredProjects.get(releaseGroup)) + ); + } + + return process.exit(0); + } + + /** + * The user is filtering by release group + */ + if (args.groups?.length) { + releaseGroups = releaseGroups.filter((g) => args.groups?.includes(g.name)); + } + + // Should be an impossible state, as we should have explicitly handled any errors/invalid config by now + if (!releaseGroups.length) { + output.error({ + title: `No projects could be matched for versioning, please report this case and include your nx.json config`, + }); + process.exit(1); + } + + /** + * Run publishing for all remaining release groups + */ + for (const releaseGroup of releaseGroups) { + await runPublishOnProjects( + projectGraph, + nxJson, + nxArgs, + overrides, + releaseGroup.projects + ); + } + + process.exit(0); +} + +async function runPublishOnProjects( + projectGraph: ProjectGraph, + nxJson: NxJsonConfiguration, + nxArgs: NxArgs, + overrides: Record, + projectNames: string[] +) { + const projectsToRun: ProjectGraphProjectNode[] = projectNames.map( + (projectName) => projectGraph.nodes[projectName] + ); + + /** + * Run the relevant release-publish executor on each of the selected projects. + */ + const status = await runCommand( + projectsToRun, + projectGraph, + { nxJson }, + nxArgs, + overrides, + null, + {}, + { excludeTaskDependencies: false, loadDotEnvFiles: true } + ); + + if (status !== 0) { + // fix for https://github.com/nrwl/nx/issues/1666 + if (process.stdin['unref']) (process.stdin as any).unref(); + process.exit(status); + } +} diff --git a/packages/nx/src/command-line/release/release.ts b/packages/nx/src/command-line/release/release.ts new file mode 100644 index 0000000000000..d3e1d9e167b5c --- /dev/null +++ b/packages/nx/src/command-line/release/release.ts @@ -0,0 +1 @@ +export { deriveNewSemverVersion } from './utils/semver'; diff --git a/packages/nx/src/command-line/release/utils/git.ts b/packages/nx/src/command-line/release/utils/git.ts new file mode 100644 index 0000000000000..2612d381c3e05 --- /dev/null +++ b/packages/nx/src/command-line/release/utils/git.ts @@ -0,0 +1,158 @@ +/** + * Special thanks to changelogen for the original inspiration for many of these utilities: + * https://github.com/unjs/changelogen + */ +import { spawn } from 'node:child_process'; + +export interface GitCommitAuthor { + name: string; + email: string; +} + +export interface RawGitCommit { + message: string; + body: string; + shortHash: string; + author: GitCommitAuthor; +} + +export interface Reference { + type: 'hash' | 'issue' | 'pull-request'; + value: string; +} + +export interface GitCommit extends RawGitCommit { + description: string; + type: string; + scope: string; + references: Reference[]; + authors: GitCommitAuthor[]; + isBreaking: boolean; +} + +export async function getLastGitTag() { + const r = await execCommand('git', ['describe', '--tags', '--abbrev=0']) + .then((r) => r.split('\n').filter(Boolean)) + .catch(() => []); + return r.at(-1); +} + +export async function getGitDiff( + from: string | undefined, + to = 'HEAD' +): Promise { + // https://git-scm.com/docs/pretty-formats + const r = await execCommand('git', [ + '--no-pager', + 'log', + `${from ? `${from}...` : ''}${to}`, + '--pretty="----%n%s|%h|%an|%ae%n%b"', + '--name-status', + ]); + return r + .split('----\n') + .splice(1) + .map((line) => { + const [firstLine, ..._body] = line.split('\n'); + const [message, shortHash, authorName, authorEmail] = + firstLine.split('|'); + const r: RawGitCommit = { + message, + shortHash, + author: { name: authorName, email: authorEmail }, + body: _body.join('\n'), + }; + return r; + }); +} + +export function parseCommits(commits: RawGitCommit[]): GitCommit[] { + return commits.map((commit) => parseGitCommit(commit)).filter(Boolean); +} + +// https://www.conventionalcommits.org/en/v1.0.0/ +// https://regex101.com/r/FSfNvA/1 +const ConventionalCommitRegex = + /(?[a-z]+)(\((?.+)\))?(?!)?: (?.+)/i; +const CoAuthoredByRegex = /co-authored-by:\s*(?.+)(<(?.+)>)/gim; +const PullRequestRE = /\([ a-z]*(#\d+)\s*\)/gm; +const IssueRE = /(#\d+)/gm; + +export function parseGitCommit(commit: RawGitCommit): GitCommit | null { + const match = commit.message.match(ConventionalCommitRegex); + if (!match) { + return null; + } + + const type = match.groups.type; + + const scope = match.groups.scope || ''; + + const isBreaking = Boolean(match.groups.breaking); + let description = match.groups.description; + + // Extract references from message + const references: Reference[] = []; + for (const m of description.matchAll(PullRequestRE)) { + references.push({ type: 'pull-request', value: m[1] }); + } + for (const m of description.matchAll(IssueRE)) { + if (!references.some((i) => i.value === m[1])) { + references.push({ type: 'issue', value: m[1] }); + } + } + references.push({ value: commit.shortHash, type: 'hash' }); + + // Remove references and normalize + description = description.replace(PullRequestRE, '').trim(); + + // Find all authors + const authors: GitCommitAuthor[] = [commit.author]; + for (const match of commit.body.matchAll(CoAuthoredByRegex)) { + authors.push({ + name: (match.groups.name || '').trim(), + email: (match.groups.email || '').trim(), + }); + } + + return { + ...commit, + authors, + description, + type, + scope, + references, + isBreaking, + }; +} + +async function execCommand( + cmd: string, + args: string[], + options?: any +): Promise { + return new Promise((resolve, reject) => { + const child = spawn(cmd, args, { + ...options, + stdio: ['pipe', 'pipe', 'pipe'], // stdin, stdout, stderr + encoding: 'utf-8', + }); + + let stdout = ''; + child.stdout.on('data', (chunk) => { + stdout += chunk; + }); + + child.on('error', (error) => { + reject(error); + }); + + child.on('close', (code) => { + if (code !== 0) { + reject(new Error(`Command failed with exit code ${code}`)); + } else { + resolve(stdout); + } + }); + }); +} diff --git a/packages/nx/src/command-line/release/utils/github.ts b/packages/nx/src/command-line/release/utils/github.ts new file mode 100644 index 0000000000000..e0eaf24518d2b --- /dev/null +++ b/packages/nx/src/command-line/release/utils/github.ts @@ -0,0 +1,391 @@ +/** + * Special thanks to changelogen for the original inspiration for many of these utilities: + * https://github.com/unjs/changelogen + */ +import type { AxiosRequestConfig } from 'axios'; +import * as chalk from 'chalk'; +import { execSync } from 'node:child_process'; +import { existsSync, promises as fsp } from 'node:fs'; +import { homedir } from 'node:os'; +import { joinPathFragments, output } from '../../../devkit-exports'; +import { GitCommit, Reference } from './git'; + +// axios types and values don't seem to match +import _axios = require('axios'); +const axios = _axios as any as typeof _axios['default']; + +export interface GithubRequestConfig { + repo: string; + token: string | null; +} + +export interface GithubRelease { + id?: string; + tag_name: string; + name?: string; + body?: string; + draft?: boolean; + prerelease?: boolean; +} + +export function getGitHubRemote(remoteName = 'origin') { + try { + const remoteUrl = execSync(`git remote get-url ${remoteName}`, { + encoding: 'utf8', + }).trim(); + + // Extract the 'user/repo' part from the URL + const regex = /github\.com[/:]([\w-]+\/[\w-]+)\.git/; + const match = remoteUrl.match(regex); + + if (match && match[1]) { + return match[1]; + } else { + throw new Error( + `Could not extract "user/repo" data from the resolved remote URL: ${remoteUrl}` + ); + } + } catch (error) { + console.error('Error getting GitHub remote:', error.message); + return null; + } +} + +export async function createOrUpdateGithubRelease( + githubRequestConfig: GithubRequestConfig, + release: { version: string; body: string }, + existingGithubReleaseForVersion?: GithubRelease +) { + const result = await syncGithubRelease( + githubRequestConfig, + release, + existingGithubReleaseForVersion + ); + /** + * If something went wrong POSTing to Github we can still pre-populate the web form on github.com + * to allow the user to manually complete the release. + */ + if (result.status === 'manual') { + if (result.error) { + console.error(result.error); + process.exitCode = 1; + } + const open = require('open'); + await open(result.url) + .then(() => { + console.info( + `Follow up in the browser to manually create the release.` + ); + }) + .catch(() => { + console.info( + `Open this link to manually create a release: \n` + + chalk.underline(chalk.cyan(result.url)) + + '\n' + ); + }); + } else { + output.success({ + title: `Successfully ${ + existingGithubReleaseForVersion ? 'updated' : 'created' + } release ${chalk.bold(release.version)} on Github:`, + bodyLines: [result.url], + }); + } +} + +// TODO: allow this to be configurable via config in a future release +export async function generateMarkdown( + commits: GitCommit[], + releaseVersion: string, + githubRequestConfig: GithubRequestConfig +) { + const typeGroups = groupBy(commits, 'type'); + + const markdown: string[] = []; + const breakingChanges = []; + + const commitTypes = { + feat: { title: '🚀 Features' }, + perf: { title: '🔥 Performance' }, + fix: { title: '🩹 Fixes' }, + refactor: { title: '💅 Refactors' }, + docs: { title: '📖 Documentation' }, + build: { title: '📦 Build' }, + types: { title: '🌊 Types' }, + chore: { title: '🏡 Chore' }, + examples: { title: '🏀 Examples' }, + test: { title: '✅ Tests' }, + style: { title: '🎨 Styles' }, + ci: { title: '🤖 CI' }, + }; + + // Version Title + markdown.push('', `## ${releaseVersion}`, ''); + + for (const type of Object.keys(commitTypes)) { + const group = typeGroups[type]; + if (!group || group.length === 0) { + continue; + } + + markdown.push('', '### ' + commitTypes[type].title, ''); + for (const commit of group.reverse()) { + const line = formatCommit(commit, githubRequestConfig); + markdown.push(line); + if (commit.isBreaking) { + breakingChanges.push(line); + } + } + } + + if (breakingChanges.length > 0) { + markdown.push('', '#### ⚠️ Breaking Changes', '', ...breakingChanges); + } + + const _authors = new Map; github?: string }>(); + for (const commit of commits) { + if (!commit.author) { + continue; + } + const name = formatName(commit.author.name); + if (!name || name.includes('[bot]')) { + continue; + } + if (_authors.has(name)) { + const entry = _authors.get(name); + entry.email.add(commit.author.email); + } else { + _authors.set(name, { email: new Set([commit.author.email]) }); + } + } + + // Try to map authors to github usernames + await Promise.all( + [..._authors.keys()].map(async (authorName) => { + const meta = _authors.get(authorName); + for (const email of meta.email) { + // For these pseudo-anonymized emails we can just extract the Github username from before the @ + if (email.endsWith('@users.noreply.github.com')) { + meta.github = email.split('@')[0]; + break; + } + // Look up any other emails against the ungh.cc API + const { data } = await axios + .get( + `https://ungh.cc/users/find/${email}` + ) + .catch(() => ({ data: { user: null } })); + if (data?.user) { + meta.github = data.user.username; + break; + } + } + }) + ); + + const authors = [..._authors.entries()].map((e) => ({ name: e[0], ...e[1] })); + + if (authors.length > 0) { + markdown.push( + '', + '### ' + '❤️ Thank You', + '', + ...authors.map((i) => { + const _email = [...i.email].find( + (e) => !e.includes('noreply.github.com') + ); + const email = _email ? `<${_email}>` : ''; + const github = i.github ? `@${i.github}` : ''; + return `- ${i.name} ${github || email}`; + }) + ); + } + + return markdown.join('\n').trim(); +} + +async function syncGithubRelease( + githubRequestConfig: GithubRequestConfig, + release: { version: string; body: string }, + existingGithubReleaseForVersion?: GithubRelease +) { + const ghRelease: GithubRelease = { + tag_name: release.version, + name: release.version, + body: release.body, + }; + + try { + const newGhRelease = await (existingGithubReleaseForVersion + ? updateGithubRelease( + githubRequestConfig, + existingGithubReleaseForVersion.id, + ghRelease + ) + : createGithubRelease(githubRequestConfig, ghRelease)); + return { + status: existingGithubReleaseForVersion ? 'updated' : 'created', + id: newGhRelease.id, + url: newGhRelease.html_url, + }; + } catch (error) { + return { + status: 'manual', + error, + url: githubNewReleaseURL(githubRequestConfig, release), + }; + } +} + +export async function resolveGithubToken(): Promise { + // Try and resolve from the environment + const tokenFromEnv = process.env.GITHUB_TOKEN || process.env.GH_TOKEN; + if (tokenFromEnv) { + return tokenFromEnv; + } + // Try and resolve from gh CLI installation + const ghCLIPath = joinPathFragments( + process.env.XDG_CONFIG_HOME || joinPathFragments(homedir(), '.config'), + 'gh', + 'hosts.yml' + ); + if (existsSync(ghCLIPath)) { + const yamlContents = await fsp.readFile(ghCLIPath, 'utf8'); + const { load } = require('@zkochan/js-yaml'); + const ghCLIConfig = load(yamlContents); + return ghCLIConfig['github.com'].oauth_token; + } + return null; +} + +export async function getGithubReleaseByTag( + config: GithubRequestConfig, + tag: string +): Promise { + return await makeGithubRequest( + config, + `/repos/${config.repo}/releases/tags/${tag}`, + {} + ); +} + +async function makeGithubRequest( + config: GithubRequestConfig, + url: string, + opts: AxiosRequestConfig = {} +) { + return ( + await axios(url, { + ...opts, + baseURL: 'https://api.github.com', + headers: { + ...(opts.headers as any), + Authorization: config.token ? `Bearer ${config.token}` : undefined, + }, + }) + ).data; +} + +async function createGithubRelease( + config: GithubRequestConfig, + body: GithubRelease +) { + return await makeGithubRequest(config, `/repos/${config.repo}/releases`, { + method: 'POST', + data: body, + }); +} + +async function updateGithubRelease( + config: GithubRequestConfig, + id: string, + body: GithubRelease +) { + return await makeGithubRequest( + config, + `/repos/${config.repo}/releases/${id}`, + { + method: 'PATCH', + data: body, + } + ); +} + +function githubNewReleaseURL( + config: GithubRequestConfig, + release: { version: string; body: string } +) { + return `https://github.com/${config.repo}/releases/new?tag=v${ + release.version + }&title=v${release.version}&body=${encodeURIComponent(release.body)}`; +} + +type RepoProvider = 'github'; + +const providerToRefSpec: Record< + RepoProvider, + Record +> = { + github: { 'pull-request': 'pull', hash: 'commit', issue: 'issues' }, +}; + +function formatReference( + ref: Reference, + githubRequestConfig: GithubRequestConfig +) { + const refSpec = providerToRefSpec['github']; + return `[${ref.value}](https://github.com/${githubRequestConfig.repo}/${ + refSpec[ref.type] + }/${ref.value.replace(/^#/, '')})`; +} + +export function formatCommit( + commit: GitCommit, + githubRequestConfig: GithubRequestConfig +) { + return ( + '- ' + + (commit.scope ? `**${commit.scope.trim()}:** ` : '') + + (commit.isBreaking ? '⚠️ ' : '') + + commit.description + + formatReferences(commit.references, githubRequestConfig) + ); +} + +function formatReferences( + references: Reference[], + githubRequestConfig: GithubRequestConfig +) { + const pr = references.filter((ref) => ref.type === 'pull-request'); + const issue = references.filter((ref) => ref.type === 'issue'); + if (pr.length > 0 || issue.length > 0) { + return ( + ' (' + + [...pr, ...issue] + .map((ref) => formatReference(ref, githubRequestConfig)) + .join(', ') + + ')' + ); + } + if (references.length > 0) { + return ' (' + formatReference(references[0], githubRequestConfig) + ')'; + } + return ''; +} + +function formatName(name = '') { + return name + .split(' ') + .map((p) => p.trim()) + .join(' '); +} + +function groupBy(items: any[], key: string) { + const groups = {}; + for (const item of items) { + groups[item[key]] = groups[item[key]] || []; + groups[item[key]].push(item); + } + return groups; +} diff --git a/packages/nx/src/command-line/release/utils/launch-editor.ts b/packages/nx/src/command-line/release/utils/launch-editor.ts new file mode 100644 index 0000000000000..9ecc90baff863 --- /dev/null +++ b/packages/nx/src/command-line/release/utils/launch-editor.ts @@ -0,0 +1,43 @@ +import { execSync, spawn } from 'node:child_process'; + +export async function launchEditor(filePath: string) { + // Inspired by what git does + const editorCommand = + process.env.GIT_EDITOR || + getGitConfig('core.editor') || + process.env.VISUAL || + process.env.EDITOR || + 'vi'; + + const { cmd, args } = parseCommand(editorCommand); + + return new Promise((resolve, reject) => { + const editorProcess = spawn(cmd, [...args, filePath], { + stdio: 'inherit', // This will ensure the editor uses the current terminal + }); + + editorProcess.on('exit', (code) => { + if (code === 0) { + resolve(undefined); + } else { + reject(new Error(`Editor process exited with code ${code}`)); + } + }); + }); +} + +function getGitConfig(key): string | null { + try { + return execSync(`git config --get ${key}`).toString().trim(); + } catch { + return null; + } +} + +function parseCommand(commandString) { + const parts = commandString.split(/\s+/); + return { + cmd: parts[0], + args: parts.slice(1), + }; +} diff --git a/packages/nx/src/command-line/release/utils/print-diff.ts b/packages/nx/src/command-line/release/utils/print-diff.ts new file mode 100644 index 0000000000000..c2e5947d1de3d --- /dev/null +++ b/packages/nx/src/command-line/release/utils/print-diff.ts @@ -0,0 +1,16 @@ +import * as chalk from 'chalk'; +import { diff } from 'jest-diff'; + +export function printDiff(before: string, after: string) { + console.error( + diff(before, after, { + omitAnnotationLines: true, + contextLines: 1, + expand: false, + aColor: chalk.red, + bColor: chalk.green, + patchColor: (s) => '', + }) + ); + console.log(''); +} diff --git a/packages/nx/src/command-line/release/utils/resolve-nx-json-error-message.ts b/packages/nx/src/command-line/release/utils/resolve-nx-json-error-message.ts new file mode 100644 index 0000000000000..85f8776b4e06d --- /dev/null +++ b/packages/nx/src/command-line/release/utils/resolve-nx-json-error-message.ts @@ -0,0 +1,68 @@ +import { readFileSync } from 'node:fs'; +import { relative } from 'node:path'; +import { joinPathFragments, workspaceRoot } from '../../../devkit-exports'; + +export async function resolveNxJsonConfigErrorMessage( + propPath: string[] +): Promise { + const errorLines = await getJsonConfigLinesForErrorMessage( + readFileSync(joinPathFragments(workspaceRoot, 'nx.json'), 'utf-8'), + propPath + ); + let nxJsonMessage = `The relevant config is defined here: ${relative( + process.cwd(), + joinPathFragments(workspaceRoot, 'nx.json') + )}`; + if (errorLines) { + nxJsonMessage += `, lines ${errorLines.startLine}-${errorLines.endLine}`; + } + return nxJsonMessage; +} + +async function getJsonConfigLinesForErrorMessage( + rawConfig: string, + jsonPath: string[] +): Promise<{ startLine: number; endLine: number } | null> { + try { + const jsonParser = await import('jsonc-parser'); + const rootNode = jsonParser.parseTree(rawConfig); + const node = jsonParser.findNodeAtLocation(rootNode, jsonPath); + return computeJsonLineNumbers(rawConfig, node?.offset, node?.length); + } catch { + return null; + } +} + +function computeJsonLineNumbers( + inputText: string, + startOffset: number, + characterCount: number +) { + let lines = inputText.split('\n'); + let totalChars = 0; + let startLine = 0; + let endLine = 0; + + for (let i = 0; i < lines.length; i++) { + totalChars += lines[i].length + 1; // +1 for '\n' character + + if (!startLine && totalChars >= startOffset) { + startLine = i + 1; // +1 because arrays are 0-based + } + if (totalChars >= startOffset + characterCount) { + endLine = i + 1; // +1 because arrays are 0-based + break; + } + } + + if (!startLine) { + throw new Error('Start offset exceeds the text length'); + } + if (!endLine) { + throw new Error( + 'Character count exceeds the text length after start offset' + ); + } + + return { startLine, endLine }; +} diff --git a/packages/nx/src/command-line/release/utils/semver.spec.ts b/packages/nx/src/command-line/release/utils/semver.spec.ts new file mode 100644 index 0000000000000..c315923e6aef7 --- /dev/null +++ b/packages/nx/src/command-line/release/utils/semver.spec.ts @@ -0,0 +1,70 @@ +import { deriveNewSemverVersion } from './semver'; + +describe('deriveNewSemverVersion()', () => { + const testCases = [ + { + input: { + currentVersion: '1.0.0', + specifier: 'major', + }, + expected: '2.0.0', + }, + { + input: { + currentVersion: '1.0.0', + specifier: 'minor', + }, + expected: '1.1.0', + }, + { + input: { + currentVersion: '1.0.0', + specifier: 'patch', + }, + expected: '1.0.1', + }, + { + input: { + currentVersion: '1.0.0', + specifier: '99.9.9', // exact version + }, + expected: '99.9.9', + }, + { + input: { + currentVersion: '1.0.0', + specifier: '99.9.9', // exact version + }, + expected: '99.9.9', + }, + ]; + + testCases.forEach((c, i) => { + it(`should derive an appropriate semver version, CASE: ${i}`, () => { + expect( + deriveNewSemverVersion(c.input.currentVersion, c.input.specifier) + ).toEqual(c.expected); + }); + }); + + it('should throw if the current version is not a valid semver version', () => { + expect(() => + deriveNewSemverVersion('not-a-valid-semver-version', 'minor') + ).toThrowErrorMatchingInlineSnapshot( + `"Invalid semver version "not-a-valid-semver-version" provided."` + ); + expect(() => + deriveNewSemverVersion('major', 'minor') + ).toThrowErrorMatchingInlineSnapshot( + `"Invalid semver version "major" provided."` + ); + }); + + it('should throw if the new version specifier is not a valid semver version or semver keyword', () => { + expect(() => + deriveNewSemverVersion('1.0.0', 'foo') + ).toThrowErrorMatchingInlineSnapshot( + `"Invalid semver version specifier "foo" provided. Please provide either a valid semver version or a valid semver version keyword."` + ); + }); +}); diff --git a/packages/nx/src/command-line/release/utils/semver.ts b/packages/nx/src/command-line/release/utils/semver.ts new file mode 100644 index 0000000000000..fcd59b13e2f78 --- /dev/null +++ b/packages/nx/src/command-line/release/utils/semver.ts @@ -0,0 +1,42 @@ +import { + // @ts-ignore the RELEASE_TYPES export is missing from @types/semver + RELEASE_TYPES, + ReleaseType, + inc, + valid, +} from 'semver'; + +function isRelativeVersionKeyword(val: string): val is ReleaseType { + return RELEASE_TYPES.includes(val as ReleaseType); +} + +export function deriveNewSemverVersion( + currentSemverVersion: string, + semverSpecifier: string +) { + if (!valid(currentSemverVersion)) { + throw new Error( + `Invalid semver version "${currentSemverVersion}" provided.` + ); + } + + let newVersion = semverSpecifier; + if (isRelativeVersionKeyword(semverSpecifier)) { + // Derive the new version from the current version combined with the new version specifier. + const derivedVersion = inc(currentSemverVersion, semverSpecifier); + if (!derivedVersion) { + throw new Error( + `Unable to derive new version from current version "${currentSemverVersion}" and version specifier "${semverSpecifier}"` + ); + } + newVersion = derivedVersion; + } else { + // Ensure the new version specifier is a valid semver version, given it is not a valid semver keyword + if (!valid(semverSpecifier)) { + throw new Error( + `Invalid semver version specifier "${semverSpecifier}" provided. Please provide either a valid semver version or a valid semver version keyword.` + ); + } + } + return newVersion; +} diff --git a/packages/nx/src/command-line/release/version.ts b/packages/nx/src/command-line/release/version.ts new file mode 100644 index 0000000000000..75b7741fe722b --- /dev/null +++ b/packages/nx/src/command-line/release/version.ts @@ -0,0 +1,428 @@ +import * as chalk from 'chalk'; +import * as enquirer from 'enquirer'; +import { readFileSync } from 'node:fs'; +import { relative } from 'node:path'; +import { + // @ts-ignore missing from @types/semver + RELEASE_TYPES, + valid, +} from 'semver'; +import { Generator } from '../../config/misc-interfaces'; +import { readNxJson } from '../../config/nx-json'; +import { + ProjectGraph, + ProjectGraphProjectNode, +} from '../../config/project-graph'; +import { + NxJsonConfiguration, + joinPathFragments, + logger, + output, + workspaceRoot, +} from '../../devkit-exports'; +import { FsTree, Tree, flushChanges } from '../../generators/tree'; +import { + createProjectGraphAsync, + readProjectsConfigurationFromProjectGraph, +} from '../../project-graph/project-graph'; +import { NxArgs } from '../../utils/command-line-utils'; +import { findMatchingProjects } from '../../utils/find-matching-projects'; +import { combineOptionsForGenerator } from '../../utils/params'; +import { parseGeneratorString } from '../generate/generate'; +import { getGeneratorInformation } from '../generate/generator-utils'; +import { VersionOptions } from './command-object'; +import { createNxReleaseConfig } from './config/config'; +import { + CATCH_ALL_RELEASE_GROUP, + ReleaseGroup, + createReleaseGroups, + handleCreateReleaseGroupsError, +} from './config/create-release-groups'; +import { printDiff } from './utils/print-diff'; + +export interface ReleaseVersionGeneratorSchema { + // The projects being versioned in the current execution + projects: ProjectGraphProjectNode[]; + projectGraph: ProjectGraph; + specifier: string; + packageRoot?: string; + currentVersionResolver?: 'registry' | 'disk'; + currentVersionResolverMetadata?: Record; +} + +export async function versionHandler(args: VersionOptions): Promise { + const projectGraph = await createProjectGraphAsync({ exitOnError: true }); + const nxJson = readNxJson(); + + const nxArgs = args as NxArgs; + if (nxArgs.verbose) { + process.env.NX_VERBOSE_LOGGING = 'true'; + } + + // Apply default configuration to any optional user configuration + const nxReleaseConfig = createNxReleaseConfig(nxJson.release); + const releaseGroupsData = await createReleaseGroups( + projectGraph, + nxReleaseConfig.groups + ); + if (releaseGroupsData.error) { + return await handleCreateReleaseGroupsError(releaseGroupsData.error); + } + + const tree = new FsTree(workspaceRoot, nxArgs.verbose); + + let { releaseGroups } = releaseGroupsData; + + /** + * User is filtering to a subset of projects. We need to make sure that what they have provided can be reconciled + * against their configuration in terms of release groups and the ungroupedProjectsHandling option. + */ + if (args.projects?.length) { + const matchingProjectsForFilter = findMatchingProjects( + args.projects, + projectGraph.nodes + ); + + if (!matchingProjectsForFilter.length) { + output.error({ + title: `Your --projects filter "${args.projects}" did not match any projects in the workspace`, + }); + process.exit(1); + } + + const filteredProjectToReleaseGroup = new Map(); + const releaseGroupToFilteredProjects = new Map>(); + + // Figure out which release groups, if any, that the filtered projects belong to so that we can resolve other config + for (const releaseGroup of releaseGroups) { + const matchingProjectsForReleaseGroup = findMatchingProjects( + releaseGroup.projects, + projectGraph.nodes + ); + for (const matchingProject of matchingProjectsForFilter) { + if (matchingProjectsForReleaseGroup.includes(matchingProject)) { + filteredProjectToReleaseGroup.set(matchingProject, releaseGroup); + if (!releaseGroupToFilteredProjects.has(releaseGroup)) { + releaseGroupToFilteredProjects.set(releaseGroup, new Set()); + } + releaseGroupToFilteredProjects.get(releaseGroup).add(matchingProject); + } + } + } + + /** + * If there are release groups specified, each filtered project must match at least one release + * group, otherwise the command + config combination is invalid. + */ + if (Object.keys(nxReleaseConfig.groups).length) { + const unmatchedProjects = matchingProjectsForFilter.filter( + (p) => !filteredProjectToReleaseGroup.has(p) + ); + if (unmatchedProjects.length) { + output.error({ + title: `The following projects which match your projects filter "${args.projects}" did not match any configured release groups:`, + bodyLines: unmatchedProjects.map((p) => `- ${p}`), + }); + process.exit(1); + } + } + + output.note({ + title: `Your filter "${args.projects}" matched the following projects:`, + bodyLines: matchingProjectsForFilter.map((p) => { + const releaseGroupForProject = filteredProjectToReleaseGroup.get(p); + if (releaseGroupForProject.name === CATCH_ALL_RELEASE_GROUP) { + return `- ${p}`; + } + return `- ${p} (release group "${releaseGroupForProject.name}")`; + }), + }); + + // Filter the releaseGroups collection appropriately + releaseGroups = releaseGroups.filter((rg) => + releaseGroupToFilteredProjects.has(rg) + ); + + /** + * Run semver versioning for all remaining release groups and filtered projects within them + */ + for (const releaseGroup of releaseGroups) { + const releaseGroupName = releaseGroup.name; + + // Resolve the generator data for the current release group + const generatorData = resolveGeneratorData({ + ...extractGeneratorCollectionAndName( + `release-group "${releaseGroupName}"`, + releaseGroup.version.generator + ), + configGeneratorOptions: releaseGroup.version.generatorOptions, + }); + + const semverSpecifier = await resolveSemverSpecifier( + args.specifier, + `What kind of change is this for the ${ + releaseGroupToFilteredProjects.get(releaseGroup).size + } matched project(s) within release group "${releaseGroupName}"?`, + `What is the exact version for the ${ + releaseGroupToFilteredProjects.get(releaseGroup).size + } matched project(s) within release group "${releaseGroupName}"?` + ); + + await runVersionOnProjects( + projectGraph, + nxJson, + nxArgs, + tree, + generatorData, + Array.from(releaseGroupToFilteredProjects.get(releaseGroup)), + semverSpecifier + ); + } + + printChanges(tree, !!args.dryRun); + + return process.exit(0); + } + + /** + * The user is filtering by release group + */ + if (args.groups?.length) { + releaseGroups = releaseGroups.filter((g) => args.groups?.includes(g.name)); + } + + // Should be an impossible state, as we should have explicitly handled any errors/invalid config by now + if (!releaseGroups.length) { + output.error({ + title: `No projects could be matched for versioning, please report this case and include your nx.json config`, + }); + process.exit(1); + } + + /** + * Run semver versioning for all remaining release groups + */ + for (const releaseGroup of releaseGroups) { + const releaseGroupName = releaseGroup.name; + + // Resolve the generator data for the current release group + const generatorData = resolveGeneratorData({ + ...extractGeneratorCollectionAndName( + `release-group "${releaseGroupName}"`, + releaseGroup.version.generator + ), + configGeneratorOptions: releaseGroup.version.generatorOptions, + }); + + const semverSpecifier = await resolveSemverSpecifier( + args.specifier, + releaseGroupName === CATCH_ALL_RELEASE_GROUP + ? `What kind of change is this for all packages?` + : `What kind of change is this for release group "${releaseGroupName}"?`, + releaseGroupName === CATCH_ALL_RELEASE_GROUP + ? `What is the exact version for all packages?` + : `What is the exact version for release group "${releaseGroupName}"?` + ); + + await runVersionOnProjects( + projectGraph, + nxJson, + nxArgs, + tree, + generatorData, + releaseGroup.projects, + semverSpecifier + ); + } + + printChanges(tree, !!args.dryRun); + + process.exit(0); +} + +async function runVersionOnProjects( + projectGraph: ProjectGraph, + nxJson: NxJsonConfiguration, + nxArgs: NxArgs, + tree: Tree, + generatorData: GeneratorData, + projectNames: string[], + newVersionSpecifier: string +) { + // Should be impossible state + if (!newVersionSpecifier) { + output.error({ + title: `No version or semver keyword could be determined`, + }); + process.exit(1); + } + // Specifier could be user provided so we need to validate it + if ( + !valid(newVersionSpecifier) && + !RELEASE_TYPES.includes(newVersionSpecifier) + ) { + output.error({ + title: `The given version specifier "${newVersionSpecifier}" is not valid. You provide an exact version or a valid semver keyword such as "major", "minor", "patch", etc.`, + }); + process.exit(1); + } + + const generatorOptions: ReleaseVersionGeneratorSchema = { + projects: projectNames.map((p) => projectGraph.nodes[p]), + projectGraph, + specifier: newVersionSpecifier, + ...generatorData.configGeneratorOptions, + }; + + // Apply generator defaults from schema.json file etc + const combinedOpts = await combineOptionsForGenerator( + generatorOptions as any, + generatorData.collectionName, + generatorData.normalizedGeneratorName, + readProjectsConfigurationFromProjectGraph(projectGraph), + nxJson, + generatorData.schema, + false, + null, + relative(process.cwd(), workspaceRoot), + nxArgs.verbose + ); + + const releaseVersionGenerator = generatorData.implementationFactory(); + await releaseVersionGenerator(tree, combinedOpts); +} + +function printChanges(tree: Tree, isDryRun: boolean) { + const changes = tree.listChanges(); + + console.log(''); + + // Print the changes + changes.forEach((f) => { + if (f.type === 'CREATE') { + console.error( + `${chalk.green('CREATE')} ${f.path}${ + isDryRun ? chalk.keyword('orange')(' [dry-run]') : '' + }` + ); + printDiff('', f.content?.toString() || ''); + } else if (f.type === 'UPDATE') { + console.error( + `${chalk.white('UPDATE')} ${f.path}${ + isDryRun ? chalk.keyword('orange')(' [dry-run]') : '' + }` + ); + const currentContentsOnDisk = readFileSync( + joinPathFragments(tree.root, f.path) + ).toString(); + printDiff(currentContentsOnDisk, f.content?.toString() || ''); + } else if (f.type === 'DELETE') { + throw new Error( + 'Unexpected DELETE change, please report this as an issue' + ); + } + }); + + if (!isDryRun) { + flushChanges(workspaceRoot, changes); + } + + if (isDryRun) { + logger.warn(`\nNOTE: The "dryRun" flag means no changes were made.`); + } +} + +async function resolveSemverSpecifier( + cliArgSpecifier: string, + selectionMessage: string, + customVersionMessage: string +): Promise { + try { + let newVersionSpecifier = cliArgSpecifier; + // If the user didn't provide a new version specifier directly on the CLI, prompt for one + if (!newVersionSpecifier) { + const reply = await enquirer.prompt<{ specifier: string }>([ + { + name: 'specifier', + message: selectionMessage, + type: 'select', + choices: [ + ...RELEASE_TYPES, + { + name: 'custom', + message: 'Custom exact version', + }, + ], + }, + ]); + if (reply.specifier !== 'custom') { + newVersionSpecifier = reply.specifier; + } else { + const reply = await enquirer.prompt<{ specifier: string }>([ + { + name: 'specifier', + message: customVersionMessage, + type: 'input', + validate: (input) => { + if (valid(input)) { + return true; + } + return 'Please enter a valid semver version'; + }, + }, + ]); + newVersionSpecifier = reply.specifier; + } + } + return newVersionSpecifier; + } catch { + // We need to catch the error from enquirer prompt, otherwise yargs will print its help + process.exit(1); + } +} + +function extractGeneratorCollectionAndName( + description: string, + generatorString: string +) { + let collectionName: string; + let generatorName: string; + const parsedGeneratorString = parseGeneratorString(generatorString); + collectionName = parsedGeneratorString.collection; + generatorName = parsedGeneratorString.generator; + + if (!collectionName || !generatorName) { + throw new Error( + `Invalid generator string: ${generatorString} used for ${description}. Must be in the format of [collectionName]:[generatorName]` + ); + } + + return { collectionName, generatorName }; +} + +interface GeneratorData { + collectionName: string; + generatorName: string; + configGeneratorOptions: NxJsonConfiguration['release']['groups'][number]['version']['generatorOptions']; + normalizedGeneratorName: string; + schema: any; + implementationFactory: () => Generator; +} + +function resolveGeneratorData({ + collectionName, + generatorName, + configGeneratorOptions, +}): GeneratorData { + const { normalizedGeneratorName, schema, implementationFactory } = + getGeneratorInformation(collectionName, generatorName, workspaceRoot); + + return { + collectionName, + generatorName, + configGeneratorOptions, + normalizedGeneratorName, + schema, + implementationFactory, + }; +} diff --git a/packages/nx/src/command-line/run-many/run-many.ts b/packages/nx/src/command-line/run-many/run-many.ts index 9d8ef5b483035..ddbfc34bb0628 100644 --- a/packages/nx/src/command-line/run-many/run-many.ts +++ b/packages/nx/src/command-line/run-many/run-many.ts @@ -65,7 +65,7 @@ export async function runMany( projectNames ); } else { - await runCommand( + const status = await runCommand( projects, projectGraph, { nxJson }, @@ -75,6 +75,9 @@ export async function runMany( extraTargetDependencies, extraOptions ); + // fix for https://github.com/nrwl/nx/issues/1666 + if (process.stdin['unref']) (process.stdin as any).unref(); + process.exit(status); } } diff --git a/packages/nx/src/command-line/run/run-one.ts b/packages/nx/src/command-line/run/run-one.ts index cdb768c6735b0..fbf64fe3c2d80 100644 --- a/packages/nx/src/command-line/run/run-one.ts +++ b/packages/nx/src/command-line/run/run-one.ts @@ -79,7 +79,7 @@ export async function runOne( projectNames ); } else { - await runCommand( + const status = await runCommand( projects, projectGraph, { nxJson }, @@ -89,6 +89,9 @@ export async function runOne( extraTargetDependencies, extraOptions ); + // fix for https://github.com/nrwl/nx/issues/1666 + if (process.stdin['unref']) (process.stdin as any).unref(); + process.exit(status); } } diff --git a/packages/nx/src/command-line/yargs-utils/shared-options.ts b/packages/nx/src/command-line/yargs-utils/shared-options.ts index 9af442d323595..ee79267fe7bb9 100644 --- a/packages/nx/src/command-line/yargs-utils/shared-options.ts +++ b/packages/nx/src/command-line/yargs-utils/shared-options.ts @@ -279,9 +279,9 @@ export function withRunOneOptions(yargs: Argv) { } } -export function parseCSV(args: string[] | string) { +export function parseCSV(args: string[] | string): string[] { if (!args) { - return args; + return []; } if (Array.isArray(args)) { return args; diff --git a/packages/nx/src/config/nx-json.ts b/packages/nx/src/config/nx-json.ts index 5751858accffd..681e3ea3c4af9 100644 --- a/packages/nx/src/config/nx-json.ts +++ b/packages/nx/src/config/nx-json.ts @@ -50,6 +50,35 @@ interface NxInstallationConfiguration { plugins?: Record; } +/** + * **ALPHA** + */ +interface NxReleaseVersionConfiguration { + generator: string; + generatorOptions?: Record; +} + +/** + * **ALPHA** + */ +interface NxReleaseConfiguration { + /** + * @note: When no groups are configured at all (the default), all projects in the workspace are treated as + * if they were in a release group together. + */ + groups?: Record< + string, + { + projects: string[] | string; + /** + * If no version config is provided for the group, we will assume that @nx/js:release-version + * is the desired generator implementation, allowing for terser config for the common case. + */ + version?: NxReleaseVersionConfiguration; + } + >; +} + /** * Nx.json configuration * @@ -158,6 +187,11 @@ export interface NxJsonConfiguration { * useful for workspaces that don't have a root package.json + node_modules. */ installation?: NxInstallationConfiguration; + + /** + * **ALPHA**: Configuration for `nx release` (versioning and publishing of applications and libraries) + */ + release?: NxReleaseConfiguration; } export function readNxJson(root: string = workspaceRoot): NxJsonConfiguration { diff --git a/packages/nx/src/config/workspaces.spec.ts b/packages/nx/src/config/workspaces.spec.ts index 51c4db200e056..6ecc875918705 100644 --- a/packages/nx/src/config/workspaces.spec.ts +++ b/packages/nx/src/config/workspaces.spec.ts @@ -9,7 +9,12 @@ const libConfig = (root, name?: string) => ({ projectType: 'library', root: `libs/${root}`, sourceRoot: `libs/${root}/src`, - targets: {}, + targets: { + 'release-publish': { + executor: '@nx/js:release-publish', + options: {}, + }, + }, }); const packageLibConfig = (root, name?: string) => ({ @@ -17,7 +22,12 @@ const packageLibConfig = (root, name?: string) => ({ root, sourceRoot: root, projectType: 'library', - targets: {}, + targets: { + 'release-publish': { + executor: '@nx/js:release-publish', + options: {}, + }, + }, }); describe('Workspaces', () => { @@ -86,7 +96,12 @@ describe('Workspaces', () => { root: 'libs/lib1', sourceRoot: 'libs/lib1/src', projectType: 'library', - targets: {}, + targets: { + 'release-publish': { + executor: '@nx/js:release-publish', + options: {}, + }, + }, }); expect(projects.lib2).toEqual(lib2Config); expect(projects['domain-lib3']).toEqual(domainPackageConfig); @@ -127,7 +142,12 @@ describe('Workspaces', () => { root: 'packages/my-package', sourceRoot: 'packages/my-package', projectType: 'library', - targets: {}, + targets: { + 'release-publish': { + executor: '@nx/js:release-publish', + options: {}, + }, + }, }); } ); diff --git a/packages/nx/src/generators/utils/deprecated.ts b/packages/nx/src/generators/utils/deprecated.ts index c75a6a561ecd4..ed0afde2841c1 100644 --- a/packages/nx/src/generators/utils/deprecated.ts +++ b/packages/nx/src/generators/utils/deprecated.ts @@ -56,6 +56,7 @@ export function updateWorkspaceConfiguration( defaultProject, extends: ext, installation, + release: {}, }; updateNxJson(tree, nxJson); diff --git a/packages/nx/src/plugins/project-json/build-nodes/project-json.spec.ts b/packages/nx/src/plugins/project-json/build-nodes/project-json.spec.ts index 6631f068edf65..9d3f4bec34ead 100644 --- a/packages/nx/src/plugins/project-json/build-nodes/project-json.spec.ts +++ b/packages/nx/src/plugins/project-json/build-nodes/project-json.spec.ts @@ -11,6 +11,13 @@ import { import { CreateNodesContext } from '../../../utils/nx-plugin'; const { createNodes } = CreateProjectJsonProjectsPlugin; +const defaultReleasePublishTarget = { + 'release-publish': { + executor: '@nx/js:release-publish', + options: {}, + }, +}; + describe('nx project.json plugin', () => { let context: CreateNodesContext; beforeEach(() => { @@ -72,6 +79,10 @@ describe('nx project.json plugin', () => { "executor": "nx:run-commands", "options": {}, }, + "release-publish": { + "executor": "@nx/js:release-publish", + "options": {}, + }, "test": { "executor": "nx:run-script", "options": { @@ -115,7 +126,10 @@ describe('nx project.json plugin', () => { packageJson, projectJsonTargets ); - expect(result).toEqual(projectJsonTargets); + expect(result).toEqual({ + ...projectJsonTargets, + ...defaultReleasePublishTarget, + }); }); it('should provide targets from project.json and package.json', () => { @@ -135,6 +149,7 @@ describe('nx project.json plugin', () => { expect(result).toEqual({ ...projectJsonTargets, build: packageJsonBuildTarget, + ...defaultReleasePublishTarget, }); }); @@ -158,6 +173,7 @@ describe('nx project.json plugin', () => { ); expect(result).toEqual({ build: { ...packageJsonBuildTarget, outputs: ['custom'] }, + ...defaultReleasePublishTarget, }); }); @@ -171,6 +187,7 @@ describe('nx project.json plugin', () => { script: 'build', }, }, + ...defaultReleasePublishTarget, }); }); @@ -200,6 +217,7 @@ describe('nx project.json plugin', () => { executor: 'nx:run-script', options: { script: 'test' }, }, + ...defaultReleasePublishTarget, }); }); @@ -233,6 +251,7 @@ describe('nx project.json plugin', () => { executor: 'nx:run-script', options: { script: 'test' }, }, + ...defaultReleasePublishTarget, }); }); }); diff --git a/packages/nx/src/tasks-runner/run-command.ts b/packages/nx/src/tasks-runner/run-command.ts index 2686b2d562cab..50da0156a29ca 100644 --- a/packages/nx/src/tasks-runner/run-command.ts +++ b/packages/nx/src/tasks-runner/run-command.ts @@ -145,7 +145,7 @@ export async function runCommand( initiatingProject: string | null, extraTargetDependencies: Record, extraOptions: { excludeTaskDependencies: boolean; loadDotEnvFiles: boolean } -) { +): Promise { const status = await handleErrors( process.env.NX_VERBOSE_LOGGING === 'true', async () => { @@ -190,9 +190,8 @@ export async function runCommand( return status; } ); - // fix for https://github.com/nrwl/nx/issues/1666 - if (process.stdin['unref']) (process.stdin as any).unref(); - process.exit(status); + + return status; } function setEnvVarsBasedOnArgs(nxArgs: NxArgs, loadDotEnvFiles: boolean) { diff --git a/packages/nx/src/utils/command-line-utils.ts b/packages/nx/src/utils/command-line-utils.ts index 8517e33287ae2..5ee7aed74c3e1 100644 --- a/packages/nx/src/utils/command-line-utils.ts +++ b/packages/nx/src/utils/command-line-utils.ts @@ -39,7 +39,7 @@ export interface NxArgs { export function splitArgsIntoNxArgsAndOverrides( args: { [k: string]: any }, - mode: 'run-one' | 'run-many' | 'affected' | 'print-affected', + mode: 'run-one' | 'run-many' | 'affected' | 'print-affected' | 'release', options = { printWarnings: true }, nxJson: NxJsonConfiguration ): { @@ -81,6 +81,39 @@ export function splitArgsIntoNxArgsAndOverrides( delete (nxArgs as any).$0; delete (nxArgs as any).__overrides_unparsed__; + if (mode === 'release') { + if (overrides._[0] === 'release') { + overrides._.shift(); + } + if ( + overrides._[0] === 'version' || + overrides._[0] === 'v' || + overrides._[0] === 'changelog' || + overrides._[0] === 'c' || + overrides._[0] === 'publish' || + overrides._[0] === 'p' + ) { + overrides._.shift(); + } + if (overrides.__overrides_unparsed__[0] === 'release') { + overrides.__overrides_unparsed__.shift(); + } + if ( + overrides.__overrides_unparsed__[0] === 'version' || + overrides.__overrides_unparsed__[0] === 'v' || + overrides.__overrides_unparsed__[0] === 'changelog' || + overrides.__overrides_unparsed__[0] === 'c' || + overrides.__overrides_unparsed__[0] === 'publish' || + overrides.__overrides_unparsed__[0] === 'p' + ) { + overrides.__overrides_unparsed__.shift(); + } + if (overrides._.length === 0) { + delete overrides._; + } + return { nxArgs, overrides } as any; + } + if (mode === 'run-many') { const args = nxArgs as any; if (!args.projects) { diff --git a/packages/nx/src/utils/package-json.spec.ts b/packages/nx/src/utils/package-json.spec.ts index 82077bec95934..6c4ec85cd7182 100644 --- a/packages/nx/src/utils/package-json.spec.ts +++ b/packages/nx/src/utils/package-json.spec.ts @@ -70,6 +70,10 @@ describe('readTargetsFromPackageJson', () => { script: 'build', }, }, + 'release-publish': { + executor: '@nx/js:release-publish', + options: {}, + }, }); }); @@ -90,6 +94,10 @@ describe('readTargetsFromPackageJson', () => { }); expect(result).toEqual({ build: { ...packageJsonBuildTarget, outputs: ['custom'] }, + 'release-publish': { + executor: '@nx/js:release-publish', + options: {}, + }, }); }); @@ -111,6 +119,10 @@ describe('readTargetsFromPackageJson', () => { executor: 'nx:run-script', options: { script: 'test' }, }, + 'release-publish': { + executor: '@nx/js:release-publish', + options: {}, + }, }); }); }); diff --git a/packages/nx/src/utils/package-json.ts b/packages/nx/src/utils/package-json.ts index e0d4d58fc0c6c..af608257ed7cf 100644 --- a/packages/nx/src/utils/package-json.ts +++ b/packages/nx/src/utils/package-json.ts @@ -141,6 +141,15 @@ export function readTargetsFromPackageJson({ scripts, nx }: PackageJson) { res[script] = buildTargetFromScript(script, nx); } }); + + // Add implicit release-publish target for all package.json files to allow for lightweight configuration for package based repos + if (!res['release-publish']) { + res['release-publish'] = { + executor: '@nx/js:release-publish', + options: {}, + }; + } + return res; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 49df6c5899171..cf2c8ba1d6690 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,7 +16,7 @@ patchedDependencies: dependencies: '@docsearch/react': specifier: ^3.3.0 - version: 3.3.0(@algolia/client-search@4.14.2)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0) + version: 3.3.0(@algolia/client-search@4.17.2)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0) '@headlessui/react': specifier: ^1.7.3 version: 1.7.3(react-dom@18.2.0)(react@18.2.0) @@ -28,7 +28,7 @@ dependencies: version: 0.2.2(@types/react@18.2.14)(react@18.2.0) '@monaco-editor/react': specifier: ^4.4.6 - version: 4.4.6(monaco-editor@0.41.0)(react-dom@18.2.0)(react@18.2.0) + version: 4.4.6(monaco-editor@0.39.0)(react-dom@18.2.0)(react@18.2.0) '@napi-rs/canvas': specifier: ^0.1.19 version: 0.1.30 @@ -276,10 +276,10 @@ devDependencies: version: 16.2.0(@angular-devkit/build-angular@16.2.0)(@angular/common@16.2.0)(@angular/core@16.2.0)(@types/express@4.17.14)(typescript@5.1.3) '@nx/angular': specifier: 16.8.0-rc.0 - version: 16.8.0-rc.0(@angular-devkit/build-angular@16.2.0)(@angular-devkit/core@16.2.0)(@angular-devkit/schematics@16.2.0)(@nguniversal/builders@16.2.0)(@schematics/angular@16.2.0)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.1.0)(esbuild@0.19.2)(eslint@8.46.0)(html-webpack-plugin@5.5.0)(nx@16.8.0-rc.0)(rxjs@7.8.1)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) + version: 16.8.0-rc.0(@angular-devkit/build-angular@16.2.0)(@angular-devkit/core@16.2.0)(@angular-devkit/schematics@16.2.0)(@nguniversal/builders@16.2.0)(@schematics/angular@16.2.0)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.0.0)(esbuild@0.19.2)(eslint@8.46.0)(html-webpack-plugin@5.5.0)(nx@16.8.0-rc.0)(rxjs@7.8.1)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/cypress': specifier: 16.8.0-rc.0 - version: 16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.1.0)(eslint@8.46.0)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4) + version: 16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.0.0)(eslint@8.46.0)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/devkit': specifier: 16.8.0-rc.0 version: 16.8.0-rc.0(nx@16.8.0-rc.0) @@ -309,7 +309,7 @@ devDependencies: version: 16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.46.0)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0) '@nx/storybook': specifier: 16.8.0-rc.0 - version: 16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.1.0)(eslint@8.46.0)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4) + version: 16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.0.0)(eslint@8.46.0)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/web': specifier: 16.8.0-rc.0 version: 16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4) @@ -436,6 +436,9 @@ devDependencies: '@types/node': specifier: 18.16.9 version: 18.16.9 + '@types/npm-package-arg': + specifier: 6.1.1 + version: 6.1.1 '@types/prettier': specifier: ^2.6.2 version: 2.7.1 @@ -483,7 +486,7 @@ devDependencies: version: 3.0.1(@types/react@18.2.14)(react@18.2.0)(xstate@4.34.0) ai: specifier: ^2.2.10 - version: 2.2.10(react@18.2.0)(solid-js@1.7.11)(svelte@4.2.0)(vue@3.3.4) + version: 2.2.10(react@18.2.0)(solid-js@1.7.11)(svelte@4.1.1)(vue@3.3.4) ajv: specifier: ^8.11.0 version: 8.11.0 @@ -511,6 +514,9 @@ devDependencies: cli-spinners: specifier: 2.6.1 version: 2.6.1 + columnify: + specifier: ^1.6.0 + version: 1.6.0 confusing-browser-globals: specifier: ^1.0.9 version: 1.0.11 @@ -528,7 +534,7 @@ devDependencies: version: 5.0.0(esbuild@0.19.2)(webpack@5.88.0) cypress: specifier: ^13.0.0 - version: 13.1.0 + version: 13.0.0 cytoscape: specifier: ^3.18.2 version: 3.23.0 @@ -670,6 +676,9 @@ devDependencies: jest-config: specifier: ^29.4.1 version: 29.5.0(@types/node@18.16.9)(ts-node@10.9.1) + jest-diff: + specifier: ^29.4.1 + version: 29.5.0 jest-environment-jsdom: specifier: 29.4.3 version: 29.4.3 @@ -747,13 +756,16 @@ devDependencies: version: 3.0.5 next-sitemap: specifier: ^3.1.10 - version: 3.1.29(@next/env@13.3.4)(next@13.3.4) + version: 3.1.29(@next/env@13.4.5)(next@13.3.4) ng-packagr: specifier: ~16.2.0 version: 16.2.0(@angular/compiler-cli@16.2.0)(tailwindcss@3.2.4)(tslib@2.4.0)(typescript@5.1.3) node-fetch: specifier: ^2.6.7 version: 2.6.7 + npm-package-arg: + specifier: 11.0.1 + version: 11.0.1 nx: specifier: 16.8.0-rc.0 version: 16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51) @@ -930,7 +942,7 @@ devDependencies: version: 1.2.0(react@18.2.0) verdaccio: specifier: ^5.0.4 - version: 5.15.4(typanion@3.14.0) + version: 5.15.4(typanion@3.12.1) vite: specifier: ^4.3.4 version: 4.3.4(@types/node@18.16.9)(less@4.1.3)(sass@1.55.0)(stylus@0.59.0) @@ -991,14 +1003,14 @@ packages: '@algolia/autocomplete-shared': 1.7.2 dev: false - /@algolia/autocomplete-preset-algolia@1.7.2(@algolia/client-search@4.14.2)(algoliasearch@4.14.2): + /@algolia/autocomplete-preset-algolia@1.7.2(@algolia/client-search@4.17.2)(algoliasearch@4.14.2): resolution: {integrity: sha512-+RYEG6B0QiGGfRb2G3MtPfyrl0dALF3cQNTWBzBX6p5o01vCCGTTinAm2UKG3tfc2CnOMAtnPLkzNZyJUpnVJw==} peerDependencies: '@algolia/client-search': '>= 4.9.1 < 6' algoliasearch: '>= 4.9.1 < 6' dependencies: '@algolia/autocomplete-shared': 1.7.2 - '@algolia/client-search': 4.14.2 + '@algolia/client-search': 4.17.2 algoliasearch: 4.14.2 dev: false @@ -1016,6 +1028,10 @@ packages: resolution: {integrity: sha512-SbvAlG9VqNanCErr44q6lEKD2qoK4XtFNx9Qn8FK26ePCI8I9yU7pYB+eM/cZdS9SzQCRJBbHUumVr4bsQ4uxg==} dev: false + /@algolia/cache-common@4.17.2: + resolution: {integrity: sha512-fojbhYIS8ovfYs6hwZpy1O4mBfVRxNgAaZRqsdVQd54hU4MxYDYFCxagYX28lOBz7btcDHld6BMoWXvjzkx6iQ==} + dev: false + /@algolia/cache-in-memory@4.14.2: resolution: {integrity: sha512-HrOukWoop9XB/VFojPv1R5SVXowgI56T9pmezd/djh2JnVN/vXswhXV51RKy4nCpqxyHt/aGFSq2qkDvj6KiuQ==} dependencies: @@ -1046,6 +1062,13 @@ packages: '@algolia/transporter': 4.14.2 dev: false + /@algolia/client-common@4.17.2: + resolution: {integrity: sha512-gKBUnjxi0ukJYIJxVREYGt1Dmj1B3RBYbfGWi0dIPp1BC1VvQm+BOuNwsIwmq/x3MPO+sGuK978eKiP3tZDvag==} + dependencies: + '@algolia/requester-common': 4.17.2 + '@algolia/transporter': 4.17.2 + dev: false + /@algolia/client-personalization@4.14.2: resolution: {integrity: sha512-ACCoLi0cL8CBZ1W/2juehSltrw2iqsQBnfiu/Rbl9W2yE6o2ZUb97+sqN/jBqYNQBS+o0ekTMKNkQjHHAcEXNw==} dependencies: @@ -1062,10 +1085,22 @@ packages: '@algolia/transporter': 4.14.2 dev: false + /@algolia/client-search@4.17.2: + resolution: {integrity: sha512-FUjIs+gRe0upJC++uVs4sdxMw15JxfkT86Gr/kqVwi9kcqaZhXntSbW/Fw959bIYXczjmeVQsilYvBWW4YvSZA==} + dependencies: + '@algolia/client-common': 4.17.2 + '@algolia/requester-common': 4.17.2 + '@algolia/transporter': 4.17.2 + dev: false + /@algolia/logger-common@4.14.2: resolution: {integrity: sha512-/JGlYvdV++IcMHBnVFsqEisTiOeEr6cUJtpjz8zc0A9c31JrtLm318Njc72p14Pnkw3A/5lHHh+QxpJ6WFTmsA==} dev: false + /@algolia/logger-common@4.17.2: + resolution: {integrity: sha512-EfXuweUE+1HiSMsQidaDWA5Lv4NnStYIlh7PO5pLkI+sdhbMX0e5AO5nUAMIFM1VkEANes70RA8fzhP6OqCqQQ==} + dev: false + /@algolia/logger-console@4.14.2: resolution: {integrity: sha512-8S2PlpdshbkwlLCSAB5f8c91xyc84VM9Ar9EdfE9UmX+NrKNYnWR1maXXVDQQoto07G1Ol/tYFnFVhUZq0xV/g==} dependencies: @@ -1082,6 +1117,10 @@ packages: resolution: {integrity: sha512-73YQsBOKa5fvVV3My7iZHu1sUqmjjfs9TteFWwPwDmnad7T0VTCopttcsM3OjLxZFtBnX61Xxl2T2gmG2O4ehg==} dev: false + /@algolia/requester-common@4.17.2: + resolution: {integrity: sha512-Rfim23ztAhYpE9qm+KCfCRo+YLJCjiiTG+IpDdzUjMpYPhUtirQT0A35YEd/gKn86YNyydxS9w8iRSjwKh+L0A==} + dev: false + /@algolia/requester-node-http@4.14.2: resolution: {integrity: sha512-oDbb02kd1o5GTEld4pETlPZLY0e+gOSWjWMJHWTgDXbv9rm/o2cF7japO6Vj1ENnrqWvLBmW1OzV9g6FUFhFXg==} dependencies: @@ -1096,6 +1135,14 @@ packages: '@algolia/requester-common': 4.14.2 dev: false + /@algolia/transporter@4.17.2: + resolution: {integrity: sha512-m8pXlz5OnNzjD1rcw+duCN4jG4yEzkJBsvKYMoN22Oq6rQwy1AY5muZ+IQUs4dL+A364CYkRMLRWhvXpCZ1x+g==} + dependencies: + '@algolia/cache-common': 4.17.2 + '@algolia/logger-common': 4.17.2 + '@algolia/requester-common': 4.17.2 + dev: false + /@ampproject/remapping@2.2.1: resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} engines: {node: '>=6.0.0'} @@ -1459,7 +1506,7 @@ packages: dependencies: '@angular/core': 16.2.0(rxjs@7.8.1)(zone.js@0.13.1) rxjs: 7.8.1 - tslib: 2.6.1 + tslib: 2.5.3 dev: true /@angular/compiler-cli@16.2.0(@angular/compiler@16.2.0)(typescript@5.1.3): @@ -1477,7 +1524,7 @@ packages: convert-source-map: 1.9.0 reflect-metadata: 0.1.13 semver: 7.5.3 - tslib: 2.6.1 + tslib: 2.5.3 typescript: 5.1.3 yargs: 17.7.2 transitivePeerDependencies: @@ -1494,7 +1541,7 @@ packages: optional: true dependencies: '@angular/core': 16.2.0(rxjs@7.8.1)(zone.js@0.13.1) - tslib: 2.6.1 + tslib: 2.5.3 dev: true /@angular/core@16.2.0(rxjs@7.8.1)(zone.js@0.13.1): @@ -1505,7 +1552,7 @@ packages: zone.js: ~0.13.0 dependencies: rxjs: 7.8.1 - tslib: 2.6.1 + tslib: 2.5.3 zone.js: 0.13.1 dev: true @@ -1538,7 +1585,7 @@ packages: '@angular/core': 16.2.0(rxjs@7.8.1)(zone.js@0.13.1) '@angular/platform-browser': 16.2.0(@angular/common@16.2.0)(@angular/core@16.2.0) rxjs: 7.8.1 - tslib: 2.6.1 + tslib: 2.5.3 dev: true /@apidevtools/json-schema-ref-parser@9.0.9: @@ -1565,7 +1612,7 @@ packages: resolution: {integrity: sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==} engines: {node: '>=6.9.0'} dependencies: - '@babel/highlight': 7.22.5 + '@babel/highlight': 7.18.6 dev: true /@babel/code-frame@7.22.5: @@ -1574,6 +1621,11 @@ packages: dependencies: '@babel/highlight': 7.22.5 + /@babel/compat-data@7.22.5: + resolution: {integrity: sha512-4Jc/YuIaYqKnDDz892kPIledykKg12Aw1PYX5i/TY28anJtacvM1Rrr8wbieB9GfEJwlzqT0hUEao0CxEebiDA==} + engines: {node: '>=6.9.0'} + dev: true + /@babel/compat-data@7.22.9: resolution: {integrity: sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==} engines: {node: '>=6.9.0'} @@ -1623,6 +1675,16 @@ packages: transitivePeerDependencies: - supports-color + /@babel/generator@7.22.5: + resolution: {integrity: sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.22.5 + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.18 + jsesc: 2.5.2 + dev: true + /@babel/generator@7.22.9: resolution: {integrity: sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==} engines: {node: '>=6.9.0'} @@ -1646,6 +1708,20 @@ packages: '@babel/types': 7.22.5 dev: true + /@babel/helper-compilation-targets@7.22.5(@babel/core@7.22.9): + resolution: {integrity: sha512-Ji+ywpHeuqxB8WDxraCiqR0xfhYjiDE/e6k7FuIaANnoOFxAHskHChz4vA1mJC9Lbm01s1PVAGhQY4FUKSkGZw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/compat-data': 7.22.5 + '@babel/core': 7.22.9 + '@babel/helper-validator-option': 7.22.5 + browserslist: 4.21.9 + lru-cache: 5.1.1 + semver: 6.3.1 + dev: true + /@babel/helper-compilation-targets@7.22.9(@babel/core@7.22.5): resolution: {integrity: sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==} engines: {node: '>=6.9.0'} @@ -1719,10 +1795,26 @@ packages: - supports-color dev: true - /@babel/helper-define-polyfill-provider@0.4.1(@babel/core@7.22.9): - resolution: {integrity: sha512-kX4oXixDxG197yhX+J3Wp+NpL2wuCFjWQAr6yX2jtCnflK9ulMI51ULFGIrWiX1jGfvAxdHp+XQCcP2bZGPs9A==} + /@babel/helper-define-polyfill-provider@0.4.0(@babel/core@7.22.9): + resolution: {integrity: sha512-RnanLx5ETe6aybRi1cO/edaRH+bNYWaryCEmjDDYyNr4wnSzyOp8T0dWipmqVHKEY3AbVKUom50AKSlj1zmKbg==} peerDependencies: '@babel/core': ^7.4.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-compilation-targets': 7.22.9(@babel/core@7.22.9) + '@babel/helper-plugin-utils': 7.22.5 + debug: 4.3.4(supports-color@5.5.0) + lodash.debounce: 4.0.8 + resolve: 1.22.2 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-define-polyfill-provider@0.4.2(@babel/core@7.22.9): + resolution: {integrity: sha512-k0qnnOqHn5dK9pZpfD5XXZ9SojAITdCKRn2Lp6rnDGzIbaP0rHyMPk/4wsSxVBVz4RfN0q6VpXWP2pDGIoQ7hw==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 dependencies: '@babel/core': 7.22.9 '@babel/helper-compilation-targets': 7.22.9(@babel/core@7.22.9) @@ -1745,6 +1837,13 @@ packages: '@babel/template': 7.22.5 '@babel/types': 7.22.5 + /@babel/helper-hoist-variables@7.18.6: + resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.22.5 + dev: true + /@babel/helper-hoist-variables@7.22.5: resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} engines: {node: '>=6.9.0'} @@ -1771,6 +1870,22 @@ packages: dependencies: '@babel/types': 7.22.5 + /@babel/helper-module-transforms@7.22.5: + resolution: {integrity: sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-environment-visitor': 7.22.5 + '@babel/helper-module-imports': 7.22.5 + '@babel/helper-simple-access': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/helper-validator-identifier': 7.22.5 + '@babel/template': 7.22.5 + '@babel/traverse': 7.22.8 + '@babel/types': 7.22.5 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/helper-module-transforms@7.22.9(@babel/core@7.22.5): resolution: {integrity: sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==} engines: {node: '>=6.9.0'} @@ -1890,6 +2005,15 @@ packages: transitivePeerDependencies: - supports-color + /@babel/highlight@7.18.6: + resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.22.5 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: true + /@babel/highlight@7.22.5: resolution: {integrity: sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==} engines: {node: '>=6.9.0'} @@ -1898,6 +2022,22 @@ packages: chalk: 2.4.2 js-tokens: 4.0.0 + /@babel/parser@7.21.4: + resolution: {integrity: sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.22.5 + dev: true + + /@babel/parser@7.22.5: + resolution: {integrity: sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.22.5 + dev: true + /@babel/parser@7.22.7: resolution: {integrity: sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==} engines: {node: '>=6.0.0'} @@ -1966,6 +2106,20 @@ packages: '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.22.9) dev: true + /@babel/plugin-proposal-decorators@7.21.0(@babel/core@7.22.9): + resolution: {integrity: sha512-MfgX49uRrFUTL/HvWtmx3zmpyzMMr4MTj3d527MLlr/4RTT9G/ytFFP7qet2uM2Ve03b+BkpWUpK+lRXnQ+v9w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-create-class-features-plugin': 7.22.9(@babel/core@7.22.9) + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-replace-supers': 7.22.9(@babel/core@7.22.9) + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/plugin-syntax-decorators': 7.22.5(@babel/core@7.22.9) + dev: true + /@babel/plugin-proposal-decorators@7.22.7(@babel/core@7.22.9): resolution: {integrity: sha512-omXqPF7Onq4Bb7wHxXjM3jSMSJvUUbvDvmmds7KI5n9Cq6Ln5I05I1W2nRlRof1rGdiUxJrxwe285WF96XlBXQ==} engines: {node: '>=6.9.0'} @@ -2063,9 +2217,9 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.22.9 + '@babel/compat-data': 7.22.5 '@babel/core': 7.22.9 - '@babel/helper-compilation-targets': 7.22.9(@babel/core@7.22.9) + '@babel/helper-compilation-targets': 7.22.5(@babel/core@7.22.9) '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.22.9) '@babel/plugin-transform-parameters': 7.22.5(@babel/core@7.22.9) @@ -2213,6 +2367,16 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true + /@babel/plugin-syntax-flow@7.18.6(@babel/core@7.22.9): + resolution: {integrity: sha512-LUbR+KNTBWCUAqRG9ex5Gnzu2IOkt8jRJbHHXFT9q+L9zm7M/QQbEqXyw1n1pohYvOyWC8CjeyjrSaIwiYjK7A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + /@babel/plugin-syntax-flow@7.22.5(@babel/core@7.22.9): resolution: {integrity: sha512-9RdCl0i+q0QExayk2nOS7853w08yLucnnPML6EN9S8fgMPVtdLDCdx/cOQ/i44Lb9UeQX9A35yaqBBOMMZxPxQ==} engines: {node: '>=6.9.0'} @@ -2261,6 +2425,16 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true + /@babel/plugin-syntax-jsx@7.21.4(@babel/core@7.22.9): + resolution: {integrity: sha512-5hewiLct5OKyh6PLKEYaFclcqtIgCb6bmELouxjF6up5q3Sov7rOayW4RwhbaBL0dit8rA80GNfY+UuDp2mBbQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + /@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.22.9): resolution: {integrity: sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==} engines: {node: '>=6.9.0'} @@ -2376,6 +2550,21 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true + /@babel/plugin-transform-async-generator-functions@7.22.5(@babel/core@7.22.9): + resolution: {integrity: sha512-gGOEvFzm3fWoyD5uZq7vVTD57pPJ3PczPUD/xCFGjzBpUosnklmXyKnGQbbbGs1NPNPskFex0j93yKbHt0cHyg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-environment-visitor': 7.22.5 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-remap-async-to-generator': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.22.9) + transitivePeerDependencies: + - supports-color + dev: true + /@babel/plugin-transform-async-generator-functions@7.22.7(@babel/core@7.22.9): resolution: {integrity: sha512-7HmE7pk/Fmke45TODvxvkxRMV9RazV+ZZzhOL9AG8G29TLrr3jkjwF7uJfxZ30EoXpO+LJkq4oA8NjO2DTnEDg==} engines: {node: '>=6.9.0'} @@ -2448,6 +2637,24 @@ packages: '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.22.9) dev: true + /@babel/plugin-transform-classes@7.22.5(@babel/core@7.22.9): + resolution: {integrity: sha512-2edQhLfibpWpsVBx2n/GKOz6JdGQvLruZQfGr9l1qes2KQaWswjBzhQF7UDUZMNaMMQeYnQzxwOMPsbYF7wqPQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-compilation-targets': 7.22.5(@babel/core@7.22.9) + '@babel/helper-environment-visitor': 7.22.5 + '@babel/helper-function-name': 7.22.5 + '@babel/helper-optimise-call-expression': 7.22.5 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-replace-supers': 7.22.9(@babel/core@7.22.9) + '@babel/helper-split-export-declaration': 7.22.6 + globals: 11.12.0 + dev: true + /@babel/plugin-transform-classes@7.22.6(@babel/core@7.22.9): resolution: {integrity: sha512-58EgM6nuPNG6Py4Z3zSuu0xWu2VfodiMi72Jt5Kj2FECmaYk1RrTXA45z6KBFsu9tRgwQDwIiY4FXTt+YsSFAQ==} engines: {node: '>=6.9.0'} @@ -2541,6 +2748,17 @@ packages: '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.22.9) dev: true + /@babel/plugin-transform-flow-strip-types@7.21.0(@babel/core@7.22.9): + resolution: {integrity: sha512-FlFA2Mj87a6sDkW4gfGrQQqwY/dLlBAyJa2dJEZ+FHXUVHBflO2wyKvg+OOEzXfrKYIa4HWl0mgmbCzt0cMb7w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-flow': 7.18.6(@babel/core@7.22.9) + dev: true + /@babel/plugin-transform-flow-strip-types@7.22.5(@babel/core@7.22.9): resolution: {integrity: sha512-tujNbZdxdG0/54g/oua8ISToaXTFBf8EnSb5PgQSciIXWOWKX3S4+JR7ZE9ol8FZwf9kxitzkGQ+QWeov/mCiA==} engines: {node: '>=6.9.0'} @@ -2623,8 +2841,10 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.22.9 - '@babel/helper-module-transforms': 7.22.9(@babel/core@7.22.9) + '@babel/helper-module-transforms': 7.22.5 '@babel/helper-plugin-utils': 7.22.5 + transitivePeerDependencies: + - supports-color dev: true /@babel/plugin-transform-modules-commonjs@7.22.5(@babel/core@7.22.9): @@ -2634,9 +2854,11 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.22.9 - '@babel/helper-module-transforms': 7.22.9(@babel/core@7.22.9) + '@babel/helper-module-transforms': 7.22.5 '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-simple-access': 7.22.5 + transitivePeerDependencies: + - supports-color dev: true /@babel/plugin-transform-modules-systemjs@7.22.5(@babel/core@7.22.9): @@ -2647,9 +2869,11 @@ packages: dependencies: '@babel/core': 7.22.9 '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-module-transforms': 7.22.9(@babel/core@7.22.9) + '@babel/helper-module-transforms': 7.22.5 '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-validator-identifier': 7.22.5 + transitivePeerDependencies: + - supports-color dev: true /@babel/plugin-transform-modules-umd@7.22.5(@babel/core@7.22.9): @@ -2659,8 +2883,10 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.22.9 - '@babel/helper-module-transforms': 7.22.9(@babel/core@7.22.9) + '@babel/helper-module-transforms': 7.22.5 '@babel/helper-plugin-utils': 7.22.5 + transitivePeerDependencies: + - supports-color dev: true /@babel/plugin-transform-named-capturing-groups-regex@7.22.5(@babel/core@7.22.9): @@ -2742,6 +2968,18 @@ packages: '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.22.9) dev: true + /@babel/plugin-transform-optional-chaining@7.22.5(@babel/core@7.22.9): + resolution: {integrity: sha512-AconbMKOMkyG+xCng2JogMCDcqW8wedQAqpVIL4cOSescZ7+iW8utC6YDZLMCSUIReEA733gzRSaOSXMAt/4WQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.22.9) + dev: true + /@babel/plugin-transform-optional-chaining@7.22.6(@babel/core@7.22.9): resolution: {integrity: sha512-Vd5HiWml0mDVtcLHIoEU5sw6HOUW/Zk0acLs/SAeuLzkGNOPc9DB4nkUajemhCmTIz3eiaKREZn2hQQqF79YTg==} engines: {node: '>=6.9.0'} @@ -2808,6 +3046,16 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true + /@babel/plugin-transform-react-display-name@7.18.6(@babel/core@7.22.9): + resolution: {integrity: sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + /@babel/plugin-transform-react-display-name@7.22.5(@babel/core@7.22.9): resolution: {integrity: sha512-PVk3WPYudRF5z4GKMEYUrLjPl38fJSKNaEOkFuoprioowGuWN6w2RKznuFNSlJx7pzzXXStPUnNSOEO0jL5EVw==} engines: {node: '>=6.9.0'} @@ -2848,6 +3096,20 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true + /@babel/plugin-transform-react-jsx@7.21.0(@babel/core@7.22.9): + resolution: {integrity: sha512-6OAWljMvQrZjR2DaNhVfRz6dkCAVV+ymcLUmaf8bccGOHn2v5rHJK3tTpij0BuhdYWP4LLaqj5lwcdlpAAPuvg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-module-imports': 7.22.5 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-jsx': 7.21.4(@babel/core@7.22.9) + '@babel/types': 7.22.5 + dev: true + /@babel/plugin-transform-react-jsx@7.22.5(@babel/core@7.22.9): resolution: {integrity: sha512-rog5gZaVbUip5iWDMTYbVM15XQq+RkUKhET/IHR6oizR+JEoN6CAfTTuHcK4vwUyzca30qqHqEpzBOnaRMWYMA==} engines: {node: '>=6.9.0'} @@ -2903,9 +3165,9 @@ packages: '@babel/core': 7.22.9 '@babel/helper-module-imports': 7.22.5 '@babel/helper-plugin-utils': 7.22.5 - babel-plugin-polyfill-corejs2: 0.4.4(@babel/core@7.22.9) - babel-plugin-polyfill-corejs3: 0.8.2(@babel/core@7.22.9) - babel-plugin-polyfill-regenerator: 0.5.1(@babel/core@7.22.9) + babel-plugin-polyfill-corejs2: 0.4.5(@babel/core@7.22.9) + babel-plugin-polyfill-corejs3: 0.8.3(@babel/core@7.22.9) + babel-plugin-polyfill-regenerator: 0.5.2(@babel/core@7.22.9) semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -2962,6 +3224,19 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true + /@babel/plugin-transform-typescript@7.21.3(@babel/core@7.22.9): + resolution: {integrity: sha512-RQxPz6Iqt8T0uw/WsJNReuBpWpBqs/n7mNo18sKLoTbMp+UrEekhH+pKSVC7gWz+DNjo9gryfV8YzCiT45RgMw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-create-class-features-plugin': 7.22.9(@babel/core@7.22.9) + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-typescript': 7.22.5(@babel/core@7.22.9) + dev: true + /@babel/plugin-transform-typescript@7.22.9(@babel/core@7.22.9): resolution: {integrity: sha512-BnVR1CpKiuD0iobHPaM1iLvcwPYN2uVFAqoLVSpEDKWuOikoCv5HbKLxclhKYUXlWkX86DoZGtqI4XhbOsyrMg==} engines: {node: '>=6.9.0'} @@ -3024,9 +3299,9 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.22.9 + '@babel/compat-data': 7.22.5 '@babel/core': 7.22.9 - '@babel/helper-compilation-targets': 7.22.9(@babel/core@7.22.9) + '@babel/helper-compilation-targets': 7.22.5(@babel/core@7.22.9) '@babel/helper-plugin-utils': 7.22.5 '@babel/helper-validator-option': 7.22.5 '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.22.5(@babel/core@7.22.9) @@ -3065,7 +3340,7 @@ packages: '@babel/plugin-transform-async-to-generator': 7.22.5(@babel/core@7.22.9) '@babel/plugin-transform-block-scoped-functions': 7.22.5(@babel/core@7.22.9) '@babel/plugin-transform-block-scoping': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-classes': 7.22.6(@babel/core@7.22.9) + '@babel/plugin-transform-classes': 7.22.5(@babel/core@7.22.9) '@babel/plugin-transform-computed-properties': 7.22.5(@babel/core@7.22.9) '@babel/plugin-transform-destructuring': 7.22.5(@babel/core@7.22.9) '@babel/plugin-transform-dotall-regex': 7.22.5(@babel/core@7.22.9) @@ -3098,7 +3373,98 @@ packages: babel-plugin-polyfill-corejs2: 0.3.3(@babel/core@7.22.9) babel-plugin-polyfill-corejs3: 0.6.0(@babel/core@7.22.9) babel-plugin-polyfill-regenerator: 0.4.1(@babel/core@7.22.9) - core-js-compat: 3.31.1 + core-js-compat: 3.30.2 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/preset-env@7.22.5(@babel/core@7.22.9): + resolution: {integrity: sha512-fj06hw89dpiZzGZtxn+QybifF07nNiZjZ7sazs2aVDcysAZVGjW7+7iFYxg6GLNM47R/thYfLdrXc+2f11Vi9A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/compat-data': 7.22.5 + '@babel/core': 7.22.9 + '@babel/helper-compilation-targets': 7.22.5(@babel/core@7.22.9) + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-validator-option': 7.22.5 + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.22.9) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.22.9) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.22.9) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.22.9) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-import-assertions': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-syntax-import-attributes': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.22.9) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.22.9) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.22.9) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.22.9) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.22.9) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.22.9) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.22.9) + '@babel/plugin-transform-arrow-functions': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-async-generator-functions': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-async-to-generator': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-block-scoped-functions': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-block-scoping': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-class-properties': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-class-static-block': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-classes': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-computed-properties': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-destructuring': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-dotall-regex': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-duplicate-keys': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-dynamic-import': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-exponentiation-operator': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-export-namespace-from': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-for-of': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-function-name': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-json-strings': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-literals': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-logical-assignment-operators': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-member-expression-literals': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-modules-amd': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-modules-commonjs': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-modules-systemjs': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-modules-umd': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-named-capturing-groups-regex': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-new-target': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-nullish-coalescing-operator': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-numeric-separator': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-object-rest-spread': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-object-super': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-optional-catch-binding': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-optional-chaining': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-parameters': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-private-methods': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-private-property-in-object': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-property-literals': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-regenerator': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-reserved-words': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-shorthand-properties': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-spread': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-sticky-regex': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-template-literals': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-typeof-symbol': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-unicode-escapes': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-unicode-property-regex': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-unicode-regex': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-unicode-sets-regex': 7.22.5(@babel/core@7.22.9) + '@babel/preset-modules': 0.1.5(@babel/core@7.22.9) + '@babel/types': 7.22.5 + babel-plugin-polyfill-corejs2: 0.4.3(@babel/core@7.22.9) + babel-plugin-polyfill-corejs3: 0.8.1(@babel/core@7.22.9) + babel-plugin-polyfill-regenerator: 0.5.0(@babel/core@7.22.9) + core-js-compat: 3.30.2 semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -3186,9 +3552,9 @@ packages: '@babel/plugin-transform-unicode-sets-regex': 7.22.5(@babel/core@7.22.9) '@babel/preset-modules': 0.1.5(@babel/core@7.22.9) '@babel/types': 7.22.5 - babel-plugin-polyfill-corejs2: 0.4.4(@babel/core@7.22.9) - babel-plugin-polyfill-corejs3: 0.8.2(@babel/core@7.22.9) - babel-plugin-polyfill-regenerator: 0.5.1(@babel/core@7.22.9) + babel-plugin-polyfill-corejs2: 0.4.5(@babel/core@7.22.9) + babel-plugin-polyfill-corejs3: 0.8.3(@babel/core@7.22.9) + babel-plugin-polyfill-regenerator: 0.5.2(@babel/core@7.22.9) core-js-compat: 3.31.1 semver: 6.3.1 transitivePeerDependencies: @@ -3247,6 +3613,8 @@ packages: '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.22.9) '@babel/plugin-transform-modules-commonjs': 7.22.5(@babel/core@7.22.9) '@babel/plugin-transform-typescript': 7.22.9(@babel/core@7.22.9) + transitivePeerDependencies: + - supports-color dev: true /@babel/regjsgen@0.8.0: @@ -3280,12 +3648,12 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.22.5 - '@babel/generator': 7.22.9 + '@babel/generator': 7.22.5 '@babel/helper-environment-visitor': 7.22.5 '@babel/helper-function-name': 7.22.5 - '@babel/helper-hoist-variables': 7.22.5 + '@babel/helper-hoist-variables': 7.18.6 '@babel/helper-split-export-declaration': 7.22.6 - '@babel/parser': 7.22.7 + '@babel/parser': 7.22.5 '@babel/types': 7.22.5 debug: 4.3.4(supports-color@5.5.0) globals: 11.12.0 @@ -3457,8 +3825,8 @@ packages: postcss-selector-parser: 6.0.11 dev: true - /@cypress/request@3.0.0: - resolution: {integrity: sha512-GKFCqwZwMYmL3IBoNeR2MM1SnxRIGERsQOTWeQKoYBt2JLqcqiy7JXqO894FLrpjZYqGxW92MNwRH2BN56obdQ==} + /@cypress/request@3.0.1: + resolution: {integrity: sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ==} engines: {node: '>= 6'} dependencies: aws-sign2: 0.7.0 @@ -3474,7 +3842,7 @@ packages: json-stringify-safe: 5.0.1 mime-types: 2.1.35 performance-now: 2.1.0 - qs: 6.10.3 + qs: 6.10.4 safe-buffer: 5.2.1 tough-cookie: 4.1.3 tunnel-agent: 0.6.0 @@ -3499,7 +3867,7 @@ packages: resolution: {integrity: sha512-rODCdDtGyudLj+Va8b6w6Y85KE85bXRsps/R4Yjwt5vueXKXZQKYw0aA9knxLBT6a/bI/GMrAcmCR75KYOM6hg==} dev: false - /@docsearch/react@3.3.0(@algolia/client-search@4.14.2)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0): + /@docsearch/react@3.3.0(@algolia/client-search@4.17.2)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-fhS5adZkae2SSdMYEMVg6pxI5a/cE+tW16ki1V0/ur4Fdok3hBRkmN/H8VvlXnxzggkQIIRIVvYPn00JPjen3A==} peerDependencies: '@types/react': '>= 16.8.0 < 19.0.0' @@ -3514,7 +3882,7 @@ packages: optional: true dependencies: '@algolia/autocomplete-core': 1.7.2 - '@algolia/autocomplete-preset-algolia': 1.7.2(@algolia/client-search@4.14.2)(algoliasearch@4.14.2) + '@algolia/autocomplete-preset-algolia': 1.7.2(@algolia/client-search@4.17.2)(algoliasearch@4.14.2) '@docsearch/css': 3.3.0 '@types/react': 18.2.14 algoliasearch: 4.14.2 @@ -3581,15 +3949,6 @@ packages: dev: true optional: true - /@esbuild/android-arm64@0.18.20: - resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/android-arm64@0.19.2: resolution: {integrity: sha512-lsB65vAbe90I/Qe10OjkmrdxSX4UJDjosDgb8sZUKcg3oefEuW2OT2Vozz8ef7wrJbMcmhvCC+hciF8jY/uAkw==} engines: {node: '>=12'} @@ -3616,15 +3975,6 @@ packages: dev: true optional: true - /@esbuild/android-arm@0.18.20: - resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/android-arm@0.19.2: resolution: {integrity: sha512-tM8yLeYVe7pRyAu9VMi/Q7aunpLwD139EY1S99xbQkT4/q2qa6eA4ige/WJQYdJ8GBL1K33pPFhPfPdJ/WzT8Q==} engines: {node: '>=12'} @@ -3651,15 +4001,6 @@ packages: dev: true optional: true - /@esbuild/android-x64@0.18.20: - resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: true - optional: true - /@esbuild/android-x64@0.19.2: resolution: {integrity: sha512-qK/TpmHt2M/Hg82WXHRc/W/2SGo/l1thtDHZWqFq7oi24AjZ4O/CpPSu6ZuYKFkEgmZlFoa7CooAyYmuvnaG8w==} engines: {node: '>=12'} @@ -3686,15 +4027,6 @@ packages: dev: true optional: true - /@esbuild/darwin-arm64@0.18.20: - resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - /@esbuild/darwin-arm64@0.19.2: resolution: {integrity: sha512-Ora8JokrvrzEPEpZO18ZYXkH4asCdc1DLdcVy8TGf5eWtPO1Ie4WroEJzwI52ZGtpODy3+m0a2yEX9l+KUn0tA==} engines: {node: '>=12'} @@ -3721,15 +4053,6 @@ packages: dev: true optional: true - /@esbuild/darwin-x64@0.18.20: - resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - /@esbuild/darwin-x64@0.19.2: resolution: {integrity: sha512-tP+B5UuIbbFMj2hQaUr6EALlHOIOmlLM2FK7jeFBobPy2ERdohI4Ka6ZFjZ1ZYsrHE/hZimGuU90jusRE0pwDw==} engines: {node: '>=12'} @@ -3756,15 +4079,6 @@ packages: dev: true optional: true - /@esbuild/freebsd-arm64@0.18.20: - resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/freebsd-arm64@0.19.2: resolution: {integrity: sha512-YbPY2kc0acfzL1VPVK6EnAlig4f+l8xmq36OZkU0jzBVHcOTyQDhnKQaLzZudNJQyymd9OqQezeaBgkTGdTGeQ==} engines: {node: '>=12'} @@ -3791,15 +4105,6 @@ packages: dev: true optional: true - /@esbuild/freebsd-x64@0.18.20: - resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/freebsd-x64@0.19.2: resolution: {integrity: sha512-nSO5uZT2clM6hosjWHAsS15hLrwCvIWx+b2e3lZ3MwbYSaXwvfO528OF+dLjas1g3bZonciivI8qKR/Hm7IWGw==} engines: {node: '>=12'} @@ -3826,15 +4131,6 @@ packages: dev: true optional: true - /@esbuild/linux-arm64@0.18.20: - resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-arm64@0.19.2: resolution: {integrity: sha512-ig2P7GeG//zWlU0AggA3pV1h5gdix0MA3wgB+NsnBXViwiGgY77fuN9Wr5uoCrs2YzaYfogXgsWZbm+HGr09xg==} engines: {node: '>=12'} @@ -3861,15 +4157,6 @@ packages: dev: true optional: true - /@esbuild/linux-arm@0.18.20: - resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-arm@0.19.2: resolution: {integrity: sha512-Odalh8hICg7SOD7XCj0YLpYCEc+6mkoq63UnExDCiRA2wXEmGlK5JVrW50vZR9Qz4qkvqnHcpH+OFEggO3PgTg==} engines: {node: '>=12'} @@ -3896,15 +4183,6 @@ packages: dev: true optional: true - /@esbuild/linux-ia32@0.18.20: - resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-ia32@0.19.2: resolution: {integrity: sha512-mLfp0ziRPOLSTek0Gd9T5B8AtzKAkoZE70fneiiyPlSnUKKI4lp+mGEnQXcQEHLJAcIYDPSyBvsUbKUG2ri/XQ==} engines: {node: '>=12'} @@ -3931,15 +4209,6 @@ packages: dev: true optional: true - /@esbuild/linux-loong64@0.18.20: - resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-loong64@0.19.2: resolution: {integrity: sha512-hn28+JNDTxxCpnYjdDYVMNTR3SKavyLlCHHkufHV91fkewpIyQchS1d8wSbmXhs1fiYDpNww8KTFlJ1dHsxeSw==} engines: {node: '>=12'} @@ -3966,15 +4235,6 @@ packages: dev: true optional: true - /@esbuild/linux-mips64el@0.18.20: - resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-mips64el@0.19.2: resolution: {integrity: sha512-KbXaC0Sejt7vD2fEgPoIKb6nxkfYW9OmFUK9XQE4//PvGIxNIfPk1NmlHmMg6f25x57rpmEFrn1OotASYIAaTg==} engines: {node: '>=12'} @@ -4001,15 +4261,6 @@ packages: dev: true optional: true - /@esbuild/linux-ppc64@0.18.20: - resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-ppc64@0.19.2: resolution: {integrity: sha512-dJ0kE8KTqbiHtA3Fc/zn7lCd7pqVr4JcT0JqOnbj4LLzYnp+7h8Qi4yjfq42ZlHfhOCM42rBh0EwHYLL6LEzcw==} engines: {node: '>=12'} @@ -4036,15 +4287,6 @@ packages: dev: true optional: true - /@esbuild/linux-riscv64@0.18.20: - resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-riscv64@0.19.2: resolution: {integrity: sha512-7Z/jKNFufZ/bbu4INqqCN6DDlrmOTmdw6D0gH+6Y7auok2r02Ur661qPuXidPOJ+FSgbEeQnnAGgsVynfLuOEw==} engines: {node: '>=12'} @@ -4071,15 +4313,6 @@ packages: dev: true optional: true - /@esbuild/linux-s390x@0.18.20: - resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-s390x@0.19.2: resolution: {integrity: sha512-U+RinR6aXXABFCcAY4gSlv4CL1oOVvSSCdseQmGO66H+XyuQGZIUdhG56SZaDJQcLmrSfRmx5XZOWyCJPRqS7g==} engines: {node: '>=12'} @@ -4106,15 +4339,6 @@ packages: dev: true optional: true - /@esbuild/linux-x64@0.18.20: - resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@esbuild/linux-x64@0.19.2: resolution: {integrity: sha512-oxzHTEv6VPm3XXNaHPyUTTte+3wGv7qVQtqaZCrgstI16gCuhNOtBXLEBkBREP57YTd68P0VgDgG73jSD8bwXQ==} engines: {node: '>=12'} @@ -4141,15 +4365,6 @@ packages: dev: true optional: true - /@esbuild/netbsd-x64@0.18.20: - resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/netbsd-x64@0.19.2: resolution: {integrity: sha512-WNa5zZk1XpTTwMDompZmvQLHszDDDN7lYjEHCUmAGB83Bgs20EMs7ICD+oKeT6xt4phV4NDdSi/8OfjPbSbZfQ==} engines: {node: '>=12'} @@ -4176,15 +4391,6 @@ packages: dev: true optional: true - /@esbuild/openbsd-x64@0.18.20: - resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - dev: true - optional: true - /@esbuild/openbsd-x64@0.19.2: resolution: {integrity: sha512-S6kI1aT3S++Dedb7vxIuUOb3oAxqxk2Rh5rOXOTYnzN8JzW1VzBd+IqPiSpgitu45042SYD3HCoEyhLKQcDFDw==} engines: {node: '>=12'} @@ -4211,15 +4417,6 @@ packages: dev: true optional: true - /@esbuild/sunos-x64@0.18.20: - resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: true - optional: true - /@esbuild/sunos-x64@0.19.2: resolution: {integrity: sha512-VXSSMsmb+Z8LbsQGcBMiM+fYObDNRm8p7tkUDMPG/g4fhFX5DEFmjxIEa3N8Zr96SjsJ1woAhF0DUnS3MF3ARw==} engines: {node: '>=12'} @@ -4246,15 +4443,6 @@ packages: dev: true optional: true - /@esbuild/win32-arm64@0.18.20: - resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - /@esbuild/win32-arm64@0.19.2: resolution: {integrity: sha512-5NayUlSAyb5PQYFAU9x3bHdsqB88RC3aM9lKDAz4X1mo/EchMIT1Q+pSeBXNgkfNmRecLXA0O8xP+x8V+g/LKg==} engines: {node: '>=12'} @@ -4265,24 +4453,15 @@ packages: optional: true /@esbuild/win32-ia32@0.17.19: - resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - optional: true - - /@esbuild/win32-ia32@0.18.17: - resolution: {integrity: sha512-H/XaPtPKli2MhW+3CQueo6Ni3Avggi6hP/YvgkEe1aSaxw+AeO8MFjq8DlgfTd9Iz4Yih3QCZI6YLMoyccnPRg==} + resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==} engines: {node: '>=12'} cpu: [ia32] os: [win32] requiresBuild: true - dev: true optional: true - /@esbuild/win32-ia32@0.18.20: - resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} + /@esbuild/win32-ia32@0.18.17: + resolution: {integrity: sha512-H/XaPtPKli2MhW+3CQueo6Ni3Avggi6hP/YvgkEe1aSaxw+AeO8MFjq8DlgfTd9Iz4Yih3QCZI6YLMoyccnPRg==} engines: {node: '>=12'} cpu: [ia32] os: [win32] @@ -4316,15 +4495,6 @@ packages: dev: true optional: true - /@esbuild/win32-x64@0.18.20: - resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - /@esbuild/win32-x64@0.19.2: resolution: {integrity: sha512-tcuhV7ncXBqbt/Ybf0IyrMcwVOAPDckMK9rXNHtF17UTK18OKLpg08glminN06pt2WCoALhXdLfSPbVvK/6fxw==} engines: {node: '>=12'} @@ -4341,7 +4511,12 @@ packages: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 dependencies: eslint: 8.46.0 - eslint-visitor-keys: 3.4.2 + eslint-visitor-keys: 3.3.0 + dev: true + + /@eslint-community/regexpp@4.5.0: + resolution: {integrity: sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} dev: true /@eslint-community/regexpp@4.6.2: @@ -4356,7 +4531,7 @@ packages: ajv: 6.12.6 debug: 4.3.4(supports-color@5.5.0) espree: 9.6.1 - globals: 13.20.0 + globals: 13.21.0 ignore: 5.2.0 import-fresh: 3.3.0 js-yaml: 4.1.0 @@ -4548,7 +4723,7 @@ packages: '@types/node': 18.16.9 ansi-escapes: 4.3.2 chalk: 4.1.2 - ci-info: 3.8.0 + ci-info: 3.5.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.4.3 @@ -4565,7 +4740,7 @@ packages: jest-validate: 29.5.0 jest-watcher: 29.5.0 micromatch: 4.0.5 - pretty-format: 29.5.0 + pretty-format: 29.4.3 slash: 3.0.0 strip-ansi: 6.0.1 transitivePeerDependencies: @@ -4838,13 +5013,13 @@ packages: - supports-color dev: true - /@lerna/legacy-package-management@6.6.2(nx@15.9.4)(typescript@4.9.5): + /@lerna/legacy-package-management@6.6.2(nx@15.8.0)(typescript@4.9.5): resolution: {integrity: sha512-0hZxUPKnHwehUO2xC4ldtdX9bW0W1UosxebDIQlZL2STnZnA2IFmIk2lJVUyFW+cmTPQzV93jfS0i69T9Z+teg==} engines: {node: ^14.17.0 || >=16.0.0} dependencies: '@npmcli/arborist': 6.2.3 '@npmcli/run-script': 4.1.7 - '@nrwl/devkit': 15.8.0(nx@15.9.4)(typescript@4.9.5) + '@nrwl/devkit': 15.8.0(nx@15.8.0)(typescript@4.9.5) '@octokit/rest': 19.0.3 byte-size: 7.0.0 chalk: 4.1.0 @@ -4958,24 +5133,24 @@ packages: os-filter-obj: 2.0.0 dev: true - /@monaco-editor/loader@1.3.2(monaco-editor@0.41.0): + /@monaco-editor/loader@1.3.2(monaco-editor@0.39.0): resolution: {integrity: sha512-BTDbpHl3e47r3AAtpfVFTlAi7WXv4UQ/xZmz8atKl4q7epQV5e7+JbigFDViWF71VBi4IIBdcWP57Hj+OWuc9g==} peerDependencies: monaco-editor: '>= 0.21.0 < 1' dependencies: - monaco-editor: 0.41.0 + monaco-editor: 0.39.0 state-local: 1.0.7 dev: false - /@monaco-editor/react@4.4.6(monaco-editor@0.41.0)(react-dom@18.2.0)(react@18.2.0): + /@monaco-editor/react@4.4.6(monaco-editor@0.39.0)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-Gr3uz3LYf33wlFE3eRnta4RxP5FSNxiIV9ENn2D2/rN8KgGAD8ecvcITRtsbbyuOuNkwbuHYxfeaz2Vr+CtyFA==} peerDependencies: monaco-editor: '>= 0.25.0 < 1' react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: - '@monaco-editor/loader': 1.3.2(monaco-editor@0.41.0) - monaco-editor: 0.41.0 + '@monaco-editor/loader': 1.3.2(monaco-editor@0.39.0) + monaco-editor: 0.39.0 prop-types: 15.8.1 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -5301,6 +5476,10 @@ packages: /@next/env@13.3.4: resolution: {integrity: sha512-oTK/wRV2qga86m/4VdrR1+/56UA6U1Qv3sIgowB+bZjahniZLEG5BmmQjfoGv7ZuLXBZ8Eec6hkL9BqJcrEL2g==} + /@next/env@13.4.5: + resolution: {integrity: sha512-SG/gKH6eij4vwQy87b/3mbpQ1X3x2vUdnpwq6/qL2IQWjtq58EY/UuNAp9CoEZoC9sI4L9AD1r+73Z9r4d3uug==} + dev: true + /@next/eslint-plugin-next@13.1.1: resolution: {integrity: sha512-SBrOFS8PC3nQ5aeZmawJkjKkWjwK9RoxvBSv/86nZp0ubdoVQoko8r8htALd9ufp16NhacCdqhu9bzZLDWtALQ==} dependencies: @@ -5475,7 +5654,7 @@ packages: '@angular/core': 16.2.0(rxjs@7.8.1)(zone.js@0.13.1) critters: 0.0.20 jsdom: 22.1.0 - tslib: 2.6.1 + tslib: 2.5.3 transitivePeerDependencies: - bufferutil - canvas @@ -5483,11 +5662,6 @@ packages: - utf-8-validate dev: true - /@nicolo-ribaudo/semver-v6@6.3.3: - resolution: {integrity: sha512-3Yc1fUTs69MG/uZbJlLSI3JISMn2UV2rg+1D/vROUqZyh3l6iYHCs7GMp+M40ZD7yOdDbYjJcU1oTJhrc+dGKg==} - hasBin: true - dev: true - /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -5518,17 +5692,17 @@ packages: '@npmcli/metavuln-calculator': 5.0.1 '@npmcli/name-from-folder': 2.0.0 '@npmcli/node-gyp': 3.0.0 - '@npmcli/package-json': 3.0.0 + '@npmcli/package-json': 3.1.1 '@npmcli/query': 3.0.0 - '@npmcli/run-script': 6.0.0 - bin-links: 4.0.1 + '@npmcli/run-script': 6.0.2 + bin-links: 4.0.2 cacache: 17.1.3 common-ancestor-path: 1.0.1 hosted-git-info: 6.1.1 json-parse-even-better-errors: 3.0.0 json-stringify-nice: 1.1.4 minimatch: 6.2.0 - nopt: 7.1.0 + nopt: 7.2.0 npm-install-checks: 6.0.0 npm-package-arg: 10.1.0 npm-pick-manifest: 8.0.1 @@ -5538,7 +5712,7 @@ packages: parse-conflict-json: 3.0.1 proc-log: 3.0.0 promise-all-reject-late: 1.0.1 - promise-call-limit: 1.0.1 + promise-call-limit: 1.0.2 read-package-json-fast: 3.0.2 semver: 7.5.3 ssri: 10.0.4 @@ -5581,6 +5755,22 @@ packages: - bluebird dev: true + /@npmcli/git@4.1.0: + resolution: {integrity: sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + '@npmcli/promise-spawn': 6.0.1 + lru-cache: 7.14.0 + npm-pick-manifest: 8.0.1 + proc-log: 3.0.0 + promise-inflight: 1.0.1 + promise-retry: 2.0.1 + semver: 7.5.3 + which: 3.0.0 + transitivePeerDependencies: + - bluebird + dev: true + /@npmcli/installed-package-contents@2.0.1: resolution: {integrity: sha512-GIykAFdOVK31Q1/zAtT5MbxqQL2vyl9mvFJv+OGu01zxbhL3p0xc8gJjdNGX1mWmUT43aEKVO2L6V/2j4TOsAA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -5637,11 +5827,18 @@ packages: engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dev: true - /@npmcli/package-json@3.0.0: - resolution: {integrity: sha512-NnuPuM97xfiCpbTEJYtEuKz6CFbpUHtaT0+5via5pQeI25omvQDFbp1GcGJ/c4zvL/WX0qbde6YiLgfZbWFgvg==} + /@npmcli/package-json@3.1.1: + resolution: {integrity: sha512-+UW0UWOYFKCkvszLoTwrYGrjNrT8tI5Ckeb/h+Z1y1fsNJEctl7HmerA5j2FgmoqFaLI2gsA1X9KgMFqx/bRmA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: + '@npmcli/git': 4.1.0 + glob: 10.2.2 json-parse-even-better-errors: 3.0.0 + normalize-package-data: 5.0.0 + npm-normalize-package-bin: 3.0.1 + proc-log: 3.0.0 + transitivePeerDependencies: + - bluebird dev: true /@npmcli/promise-spawn@3.0.0: @@ -5693,10 +5890,24 @@ packages: - supports-color dev: true - /@nrwl/angular@16.8.0-rc.0(@angular-devkit/build-angular@16.2.0)(@angular-devkit/core@16.2.0)(@angular-devkit/schematics@16.2.0)(@nguniversal/builders@16.2.0)(@schematics/angular@16.2.0)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.1.0)(esbuild@0.19.2)(eslint@8.46.0)(html-webpack-plugin@5.5.0)(nx@16.8.0-rc.0)(rxjs@7.8.1)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4): + /@npmcli/run-script@6.0.2: + resolution: {integrity: sha512-NCcr1uQo1k5U+SYlnIrbAh3cxy+OQT1VtqiAbxdymSlptbzBb62AjH2xXgjNCoP073hoa1CfCAcwoZ8k96C4nA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + '@npmcli/node-gyp': 3.0.0 + '@npmcli/promise-spawn': 6.0.1 + node-gyp: 9.3.0 + read-package-json-fast: 3.0.2 + which: 3.0.0 + transitivePeerDependencies: + - bluebird + - supports-color + dev: true + + /@nrwl/angular@16.8.0-rc.0(@angular-devkit/build-angular@16.2.0)(@angular-devkit/core@16.2.0)(@angular-devkit/schematics@16.2.0)(@nguniversal/builders@16.2.0)(@schematics/angular@16.2.0)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.0.0)(esbuild@0.19.2)(eslint@8.46.0)(html-webpack-plugin@5.5.0)(nx@16.8.0-rc.0)(rxjs@7.8.1)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4): resolution: {integrity: sha512-/zU0NGzH+k7OHOR0Qa3auPt1ZCwnx9JpakBUDXfY/oLL95MX+PWpz+41d8NZ2GhvfhHxfMTXCbE0PzL/SqI3hQ==} dependencies: - '@nx/angular': 16.8.0-rc.0(@angular-devkit/build-angular@16.2.0)(@angular-devkit/core@16.2.0)(@angular-devkit/schematics@16.2.0)(@nguniversal/builders@16.2.0)(@schematics/angular@16.2.0)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.1.0)(esbuild@0.19.2)(eslint@8.46.0)(html-webpack-plugin@5.5.0)(nx@16.8.0-rc.0)(rxjs@7.8.1)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/angular': 16.8.0-rc.0(@angular-devkit/build-angular@16.2.0)(@angular-devkit/core@16.2.0)(@angular-devkit/schematics@16.2.0)(@nguniversal/builders@16.2.0)(@schematics/angular@16.2.0)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.0.0)(esbuild@0.19.2)(eslint@8.46.0)(html-webpack-plugin@5.5.0)(nx@16.8.0-rc.0)(rxjs@7.8.1)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) tslib: 2.6.1 transitivePeerDependencies: - '@angular-devkit/build-angular' @@ -5746,20 +5957,10 @@ packages: - debug dev: true - /@nrwl/cli@15.9.4(@swc-node/register@1.5.4)(@swc/core@1.3.51): - resolution: {integrity: sha512-FoiGFCLpb/r4HXCM3KYqT0xteP+MRV6bIHjz3bdPHIDLmBNQQnRRaV2K47jtJ6zjh1eOU5UHKyDtDDYf80Idpw==} - dependencies: - nx: 15.9.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) - transitivePeerDependencies: - - '@swc-node/register' - - '@swc/core' - - debug - dev: true - - /@nrwl/cypress@16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.1.0)(eslint@8.46.0)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4): + /@nrwl/cypress@16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.0.0)(eslint@8.46.0)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4): resolution: {integrity: sha512-Nasfcbr0LaS9XAxe2xzfOv5+ghuizjyPA/rOd9W8KSBXd4r9EQpKK5gFTqbqsKYZ8Fyg+xwA8RDj4APlzmEeBA==} dependencies: - '@nx/cypress': 16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.1.0)(eslint@8.46.0)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/cypress': 16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.0.0)(eslint@8.46.0)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -5775,34 +5976,34 @@ packages: - verdaccio dev: true - /@nrwl/devkit@15.8.0(nx@15.8.0)(typescript@5.1.3): + /@nrwl/devkit@15.8.0(nx@15.8.0)(typescript@4.9.5): resolution: {integrity: sha512-qD+asvhTXIibXPXr3r1IDP7ap3Bw5H7tSd+C5mXFhIMMinTqRnQVXe6Odfs34VFP/dpWBIBZdkkwCM/+BsCLNw==} peerDependencies: nx: '>= 14.1 <= 16' dependencies: - '@phenomnomnominal/tsquery': 4.1.1(typescript@5.1.3) + '@phenomnomnominal/tsquery': 4.1.1(typescript@4.9.5) ejs: 3.1.8 ignore: 5.2.0 nx: 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51) semver: 7.3.4 tmp: 0.2.1 - tslib: 2.6.1 + tslib: 2.5.3 transitivePeerDependencies: - typescript dev: true - /@nrwl/devkit@15.8.0(nx@15.9.4)(typescript@4.9.5): + /@nrwl/devkit@15.8.0(nx@15.8.0)(typescript@5.1.3): resolution: {integrity: sha512-qD+asvhTXIibXPXr3r1IDP7ap3Bw5H7tSd+C5mXFhIMMinTqRnQVXe6Odfs34VFP/dpWBIBZdkkwCM/+BsCLNw==} peerDependencies: nx: '>= 14.1 <= 16' dependencies: - '@phenomnomnominal/tsquery': 4.1.1(typescript@4.9.5) + '@phenomnomnominal/tsquery': 4.1.1(typescript@5.1.3) ejs: 3.1.8 ignore: 5.2.0 - nx: 15.9.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) + nx: 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51) semver: 7.3.4 tmp: 0.2.1 - tslib: 2.6.1 + tslib: 2.5.3 transitivePeerDependencies: - typescript dev: true @@ -5818,7 +6019,7 @@ packages: nx: 16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51) semver: 7.3.4 tmp: 0.2.1 - tslib: 2.6.1 + tslib: 2.5.3 transitivePeerDependencies: - typescript dev: true @@ -5893,9 +6094,9 @@ packages: dependencies: '@babel/core': 7.22.9 '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-proposal-decorators': 7.22.7(@babel/core@7.22.9) + '@babel/plugin-proposal-decorators': 7.21.0(@babel/core@7.22.9) '@babel/plugin-transform-runtime': 7.22.9(@babel/core@7.22.9) - '@babel/preset-env': 7.22.9(@babel/core@7.22.9) + '@babel/preset-env': 7.22.5(@babel/core@7.22.9) '@babel/preset-typescript': 7.22.5(@babel/core@7.22.9) '@babel/runtime': 7.22.6 '@nrwl/devkit': 15.8.0(nx@16.8.0-rc.0)(typescript@5.1.3) @@ -5912,7 +6113,7 @@ packages: minimatch: 3.0.5 source-map-support: 0.5.19 tree-kill: 1.2.2 - tslib: 2.6.1 + tslib: 2.5.3 transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -5930,9 +6131,9 @@ packages: dependencies: '@babel/core': 7.22.9 '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-proposal-decorators': 7.22.7(@babel/core@7.22.9) + '@babel/plugin-proposal-decorators': 7.21.0(@babel/core@7.22.9) '@babel/plugin-transform-runtime': 7.22.9(@babel/core@7.22.9) - '@babel/preset-env': 7.22.9(@babel/core@7.22.9) + '@babel/preset-env': 7.22.5(@babel/core@7.22.9) '@babel/preset-typescript': 7.22.5(@babel/core@7.22.9) '@babel/runtime': 7.22.6 '@nrwl/devkit': 15.8.0(nx@15.8.0)(typescript@5.1.3) @@ -5949,7 +6150,7 @@ packages: minimatch: 3.0.5 source-map-support: 0.5.19 tree-kill: 1.2.2 - tslib: 2.6.1 + tslib: 2.5.3 transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -6059,15 +6260,6 @@ packages: dev: true optional: true - /@nrwl/nx-darwin-arm64@15.9.4: - resolution: {integrity: sha512-XnvrnT9BJsgThY/4xUcYtE077ERq/img8CkRj7MOOBNOh0/nVcR4LGbBKDHtwE3HPk0ikyS/SxRyNa9msvi3QQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - /@nrwl/nx-darwin-x64@15.8.0: resolution: {integrity: sha512-jq812R8JXTUDDYhnO1c4BNrek10nan4ViHXjhq/bNvkXqA+I2EI0B7UTjr97urDGW8D0E2Skqu3tm9i1W3LJLg==} engines: {node: '>= 10'} @@ -6077,15 +6269,6 @@ packages: dev: true optional: true - /@nrwl/nx-darwin-x64@15.9.4: - resolution: {integrity: sha512-WKSfSlpVMLchpXkax0geeUNyhvNxwO7qUz/s0/HJWBekt8fizwKDwDj1gP7fOu+YWb/tHiSscbR1km8PtdjhQw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - /@nrwl/nx-linux-arm-gnueabihf@15.8.0: resolution: {integrity: sha512-pKNvu3slRElcPjk4qFblaqL25jJKZ9cYw/NUSfchMlvgEMXPSqFXHRg45U3iXMT61YFUKuK9y2l3AlCELagUUA==} engines: {node: '>= 10'} @@ -6095,15 +6278,6 @@ packages: dev: true optional: true - /@nrwl/nx-linux-arm-gnueabihf@15.9.4: - resolution: {integrity: sha512-a/b4PP7lP/Cgrh0LjC4O2YTt5pyf4DQTGtuE8qlo8o486UiofCtk4QGJX72q80s23L0ejCaKY2ULKx/3zMLjuA==} - engines: {node: '>= 10'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@nrwl/nx-linux-arm64-gnu@15.8.0: resolution: {integrity: sha512-Glkqlb1ln8ERYoDADY1She9wqjVbJuCpJV+lKQOrM7lLblmZIu6w3NtyoTE+bQNDz6yKlxaOftuTUVJKS+zLlw==} engines: {node: '>= 10'} @@ -6113,15 +6287,6 @@ packages: dev: true optional: true - /@nrwl/nx-linux-arm64-gnu@15.9.4: - resolution: {integrity: sha512-ibBV8fMhSfLVd/2WzcDuUm32BoZsattuKkvMmOoyU6Pzoznc3AqyDjJR4xCIoAn5Rf+Nu1oeQONr5FAtb1Ugow==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@nrwl/nx-linux-arm64-musl@15.8.0: resolution: {integrity: sha512-bQ74bGEXtmN0SkT7fIjGnf4Es7wRQ9j8gxSOkzbVVKEZ4rMj5ufaSc+0kBZ1Kpleg5yrj0dUMbH1tIdrbQPYGg==} engines: {node: '>= 10'} @@ -6131,15 +6296,6 @@ packages: dev: true optional: true - /@nrwl/nx-linux-arm64-musl@15.9.4: - resolution: {integrity: sha512-iIjvVYd7+uM4jVD461+PvU5XTALgSvJOODUaMRGOoDl0KlMuTe6pQZlw0eXjl5rcTd6paKaVFWT5j6awr8kj7w==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@nrwl/nx-linux-x64-gnu@15.8.0: resolution: {integrity: sha512-D4LT/06DtKbVmJBsC7J0O/jdbQZ2aGO2husAbwAEXt/gQXr8g+5ubcjMsJm8+pIkoXskPLQ1jOSw0+HA5W80uQ==} engines: {node: '>= 10'} @@ -6149,15 +6305,6 @@ packages: dev: true optional: true - /@nrwl/nx-linux-x64-gnu@15.9.4: - resolution: {integrity: sha512-q4OyH72mdrE4KellBWtwpr5EwfxHKNoFP9//7FAILO68ROh0rpMd7YQMlTB7T04UEUHjKEEsFGTlVXIee3Viwg==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@nrwl/nx-linux-x64-musl@15.8.0: resolution: {integrity: sha512-yRbeWH0tvTIxlZNrxIdnZ3dZ0noYqbPfICjlg1Zrok9VE5J+P3JenEdJV6JAKSCUOmH/lu08j+bA/NGgFX6QCg==} engines: {node: '>= 10'} @@ -6167,15 +6314,6 @@ packages: dev: true optional: true - /@nrwl/nx-linux-x64-musl@15.9.4: - resolution: {integrity: sha512-67+/XNMR1CgLPyeGX8jqSG6l8yYD0iiwUgcu1Vaxq6N05WwnqVisIW8XzLSRUtKt4WyVQgOWk3aspImpMVOG3Q==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - /@nrwl/nx-win32-arm64-msvc@15.8.0: resolution: {integrity: sha512-TX6c8KYg25rlUzCZA86Hy9Bi/7rgFzdEx9v1fj0NezT8RYrupWekhazngBORKxTnM6bEiuKqnRkETIds8RPIZQ==} engines: {node: '>= 10'} @@ -6185,15 +6323,6 @@ packages: dev: true optional: true - /@nrwl/nx-win32-arm64-msvc@15.9.4: - resolution: {integrity: sha512-2rEsq3eOGVCYpYJn2tTJkOGNJm/U8rP/FmqtZXYa6VJv/00XP3Gl00IXFEDaYV6rZo7SWqLxtEPUbjK5LwPzZA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - /@nrwl/nx-win32-x64-msvc@15.8.0: resolution: {integrity: sha512-BsVjhiofd0SF0B2oWgWvYYzoPrxixk/Zb2EEW3RShY5L6jt+B0PpM4LPf/JKAEnmYBgRTzMlXrYMO+clwnKFdw==} engines: {node: '>= 10'} @@ -6203,15 +6332,6 @@ packages: dev: true optional: true - /@nrwl/nx-win32-x64-msvc@15.9.4: - resolution: {integrity: sha512-bogVju4Z/hy1jbppqaTNbmV1R4Kg0R5fKxXAXC2LaL7FL0dup31wPumdV+mXttXBNOBDjV8V/Oz1ZqdmxpOJUw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - /@nrwl/react@16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.46.0)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4)(webpack@5.88.0): resolution: {integrity: sha512-EFkSkRWzUQbBfjHqJvmvu77Igh/Beyb6yf1w6tHjVAxQXK1EOI2TLGaZpbNZpbjb5y83iOTn/zKngEaEiE3Q1A==} dependencies: @@ -6231,10 +6351,10 @@ packages: - webpack dev: true - /@nrwl/storybook@16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.1.0)(eslint@8.46.0)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4): + /@nrwl/storybook@16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.0.0)(eslint@8.46.0)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4): resolution: {integrity: sha512-1pN5LCvO5v/Iyl8v9GZ/Bxw1vU1Yazc3nQsGaitGyoywxqIKngzNidaX7ptcT9VXPTnM5XnzQT1SCk5NoIDxbw==} dependencies: - '@nx/storybook': 16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.1.0)(eslint@8.46.0)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/storybook': 16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.0.0)(eslint@8.46.0)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -6261,17 +6381,6 @@ packages: - debug dev: true - /@nrwl/tao@15.9.4(@swc-node/register@1.5.4)(@swc/core@1.3.51): - resolution: {integrity: sha512-m90iz8UsXx1rgPm1dxsBQjSrCViWYZIrp8bpwjSCW24j3kifyilYSXGuKaRwZwUn7eNmH/kZcI9/8qeGIPF4Sg==} - hasBin: true - dependencies: - nx: 15.9.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) - transitivePeerDependencies: - - '@swc-node/register' - - '@swc/core' - - debug - dev: true - /@nrwl/tao@16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51): resolution: {integrity: sha512-/844WCjnjFkF/u6BsIFn5Wxwwq8Cyx/vwbgH9FaAp1It3vo4cIPEwQ1jmkAc3wfwZv/0Q5NKuX25hj+8zBK2tQ==} hasBin: true @@ -6391,12 +6500,12 @@ packages: dependencies: chalk: 4.1.2 consola: 2.15.3 - node-fetch: 2.6.12 + node-fetch: 2.6.7 transitivePeerDependencies: - encoding dev: true - /@nx/angular@16.8.0-rc.0(@angular-devkit/build-angular@16.2.0)(@angular-devkit/core@16.2.0)(@angular-devkit/schematics@16.2.0)(@nguniversal/builders@16.2.0)(@schematics/angular@16.2.0)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.1.0)(esbuild@0.19.2)(eslint@8.46.0)(html-webpack-plugin@5.5.0)(nx@16.8.0-rc.0)(rxjs@7.8.1)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4): + /@nx/angular@16.8.0-rc.0(@angular-devkit/build-angular@16.2.0)(@angular-devkit/core@16.2.0)(@angular-devkit/schematics@16.2.0)(@nguniversal/builders@16.2.0)(@schematics/angular@16.2.0)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.0.0)(esbuild@0.19.2)(eslint@8.46.0)(html-webpack-plugin@5.5.0)(nx@16.8.0-rc.0)(rxjs@7.8.1)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4): resolution: {integrity: sha512-euqv1wNTmxpYWAlinmyAzXeaAmcFdSRi1HZPCDWqclLHh4+qbCyIIgLw/fUlzvs3x32BKlosJEnEQSZru0MQRg==} peerDependencies: '@angular-devkit/build-angular': '>= 14.0.0 < 17.0.0' @@ -6416,8 +6525,8 @@ packages: '@angular-devkit/core': 16.2.0(chokidar@3.5.3) '@angular-devkit/schematics': 16.2.0 '@nguniversal/builders': 16.2.0(@angular-devkit/build-angular@16.2.0)(@angular/common@16.2.0)(@angular/core@16.2.0)(@types/express@4.17.14)(typescript@5.1.3) - '@nrwl/angular': 16.8.0-rc.0(@angular-devkit/build-angular@16.2.0)(@angular-devkit/core@16.2.0)(@angular-devkit/schematics@16.2.0)(@nguniversal/builders@16.2.0)(@schematics/angular@16.2.0)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.1.0)(esbuild@0.19.2)(eslint@8.46.0)(html-webpack-plugin@5.5.0)(nx@16.8.0-rc.0)(rxjs@7.8.1)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/cypress': 16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.1.0)(eslint@8.46.0)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/angular': 16.8.0-rc.0(@angular-devkit/build-angular@16.2.0)(@angular-devkit/core@16.2.0)(@angular-devkit/schematics@16.2.0)(@nguniversal/builders@16.2.0)(@schematics/angular@16.2.0)(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.0.0)(esbuild@0.19.2)(eslint@8.46.0)(html-webpack-plugin@5.5.0)(nx@16.8.0-rc.0)(rxjs@7.8.1)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/cypress': 16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.0.0)(eslint@8.46.0)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/devkit': 16.8.0-rc.0(nx@16.8.0-rc.0) '@nx/jest': 16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.8.0-rc.0)(ts-node@10.9.1)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/js': 16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4) @@ -6470,7 +6579,7 @@ packages: - webpack-cli dev: true - /@nx/cypress@16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.1.0)(eslint@8.46.0)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4): + /@nx/cypress@16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.0.0)(eslint@8.46.0)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4): resolution: {integrity: sha512-WJ5RSvnj/TJB7KnE8pHi8vdALF3qBLov/LWutBLnZe7QinZFashLUiadff5I/mcmmOOmaXj8QtOemj5Cs+SgCQ==} peerDependencies: cypress: '>= 3 < 14' @@ -6478,12 +6587,12 @@ packages: cypress: optional: true dependencies: - '@nrwl/cypress': 16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.1.0)(eslint@8.46.0)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/cypress': 16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.0.0)(eslint@8.46.0)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/devkit': 16.8.0-rc.0(nx@16.8.0-rc.0) '@nx/js': 16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/linter': 16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.46.0)(nx@16.8.0-rc.0)(verdaccio@5.15.4) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.1.3) - cypress: 13.1.0 + cypress: 13.0.0 detect-port: 1.5.1 semver: 7.5.3 tslib: 2.6.1 @@ -6646,7 +6755,7 @@ packages: ts-node: 10.9.1(@swc/core@1.3.51)(@types/node@18.16.9)(typescript@5.1.3) tsconfig-paths: 4.1.2 tslib: 2.6.1 - verdaccio: 5.15.4(typanion@3.14.0) + verdaccio: 5.15.4(typanion@3.12.1) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -6871,11 +6980,11 @@ packages: - webpack dev: true - /@nx/storybook@16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.1.0)(eslint@8.46.0)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4): + /@nx/storybook@16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.0.0)(eslint@8.46.0)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4): resolution: {integrity: sha512-AYAxTZhDSDzpZhEyzxCLgzaBn14ezZQFz8JuMh5GRxVheZKqc1ASaLzctelnTlcQ0EupZwKYKPOu+vAxdmfHkw==} dependencies: - '@nrwl/storybook': 16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.1.0)(eslint@8.46.0)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4) - '@nx/cypress': 16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.1.0)(eslint@8.46.0)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4) + '@nrwl/storybook': 16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.0.0)(eslint@8.46.0)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4) + '@nx/cypress': 16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(cypress@13.0.0)(eslint@8.46.0)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/devkit': 16.8.0-rc.0(nx@16.8.0-rc.0) '@nx/js': 16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(nx@16.8.0-rc.0)(typescript@5.1.3)(verdaccio@5.15.4) '@nx/linter': 16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51)(@types/node@18.16.9)(eslint@8.46.0)(nx@16.8.0-rc.0)(verdaccio@5.15.4) @@ -7110,6 +7219,21 @@ packages: - encoding dev: true + /@octokit/core@4.2.4: + resolution: {integrity: sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==} + engines: {node: '>= 14'} + dependencies: + '@octokit/auth-token': 3.0.2 + '@octokit/graphql': 5.0.4 + '@octokit/request': 6.2.3 + '@octokit/request-error': 3.0.3 + '@octokit/types': 9.3.2 + before-after-hook: 2.2.3 + universal-user-agent: 6.0.0 + transitivePeerDependencies: + - encoding + dev: true + /@octokit/endpoint@7.0.3: resolution: {integrity: sha512-57gRlb28bwTsdNXq+O3JTQ7ERmBTuik9+LelgcLIVfYwf235VHbN9QNo4kXExtp/h8T423cR5iJThKtFYxC7Lw==} engines: {node: '>= 14'} @@ -7177,17 +7301,21 @@ packages: resolution: {integrity: sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==} dev: true + /@octokit/openapi-types@18.0.0: + resolution: {integrity: sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==} + dev: true + /@octokit/plugin-enterprise-rest@6.0.1: resolution: {integrity: sha512-93uGjlhUD+iNg1iWhUENAtJata6w5nE+V4urXOAlIXdco6xNZtUSfYY8dzp3Udy74aqO/B5UZL80x/YMa5PKRw==} dev: true - /@octokit/plugin-paginate-rest@3.1.0(@octokit/core@4.2.0): + /@octokit/plugin-paginate-rest@3.1.0(@octokit/core@4.2.4): resolution: {integrity: sha512-+cfc40pMzWcLkoDcLb1KXqjX0jTGYXjKuQdFQDc6UAknISJHnZTiBqld6HDwRJvD4DsouDKrWXNbNV0lE/3AXA==} engines: {node: '>= 14'} peerDependencies: '@octokit/core': '>=4' dependencies: - '@octokit/core': 4.2.0 + '@octokit/core': 4.2.4 '@octokit/types': 6.41.0 dev: true @@ -7201,22 +7329,22 @@ packages: '@octokit/types': 9.0.0 dev: true - /@octokit/plugin-request-log@1.0.4(@octokit/core@4.2.0): + /@octokit/plugin-request-log@1.0.4(@octokit/core@4.2.4): resolution: {integrity: sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==} peerDependencies: '@octokit/core': '>=3' dependencies: - '@octokit/core': 4.2.0 + '@octokit/core': 4.2.4 dev: true - /@octokit/plugin-rest-endpoint-methods@6.7.0(@octokit/core@4.2.0): - resolution: {integrity: sha512-orxQ0fAHA7IpYhG2flD2AygztPlGYNAdlzYz8yrD8NDgelPfOYoRPROfEyIe035PlxvbYrgkfUZIhSBKju/Cvw==} + /@octokit/plugin-rest-endpoint-methods@6.8.1(@octokit/core@4.2.4): + resolution: {integrity: sha512-QrlaTm8Lyc/TbU7BL/8bO49vp+RZ6W3McxxmmQTgYxf2sWkO8ZKuj4dLhPNJD6VCUW1hetCmeIM0m6FTVpDiEg==} engines: {node: '>= 14'} peerDependencies: '@octokit/core': '>=3' dependencies: - '@octokit/core': 4.2.0 - '@octokit/types': 8.0.0 + '@octokit/core': 4.2.4 + '@octokit/types': 8.2.1 deprecation: 2.3.1 dev: true @@ -7280,10 +7408,10 @@ packages: resolution: {integrity: sha512-5arkTsnnRT7/sbI4fqgSJ35KiFaN7zQm0uQiQtivNQLI8RQx8EHwJCajcTUwmaCMNDg7tdCvqAnc7uvHHPxrtQ==} engines: {node: '>= 14'} dependencies: - '@octokit/core': 4.2.0 - '@octokit/plugin-paginate-rest': 3.1.0(@octokit/core@4.2.0) - '@octokit/plugin-request-log': 1.0.4(@octokit/core@4.2.0) - '@octokit/plugin-rest-endpoint-methods': 6.7.0(@octokit/core@4.2.0) + '@octokit/core': 4.2.4 + '@octokit/plugin-paginate-rest': 3.1.0(@octokit/core@4.2.4) + '@octokit/plugin-request-log': 1.0.4(@octokit/core@4.2.4) + '@octokit/plugin-rest-endpoint-methods': 6.8.1(@octokit/core@4.2.4) transitivePeerDependencies: - encoding dev: true @@ -7300,12 +7428,24 @@ packages: '@octokit/openapi-types': 14.0.0 dev: true + /@octokit/types@8.2.1: + resolution: {integrity: sha512-8oWMUji8be66q2B9PmEIUyQm00VPDPun07umUWSaCwxmeaquFBro4Hcc3ruVoDo3zkQyZBlRvhIMEYS3pBhanw==} + dependencies: + '@octokit/openapi-types': 14.0.0 + dev: true + /@octokit/types@9.0.0: resolution: {integrity: sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==} dependencies: '@octokit/openapi-types': 16.0.0 dev: true + /@octokit/types@9.3.2: + resolution: {integrity: sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==} + dependencies: + '@octokit/openapi-types': 18.0.0 + dev: true + /@octokit/webhooks-methods@3.0.2: resolution: {integrity: sha512-Vlnv5WBscf07tyAvfDbp7pTkMZUwk7z7VwEF32x6HqI+55QRwBTcT+D7DDjZXtad/1dU9E32x0HmtDlF9VIRaQ==} engines: {node: '>= 14'} @@ -7997,7 +8137,7 @@ packages: rollup: 2.79.0 dev: true - /@rollup/plugin-json@6.0.0(rollup@3.27.2): + /@rollup/plugin-json@6.0.0(rollup@3.21.0): resolution: {integrity: sha512-i/4C5Jrdr1XUarRhVu27EEwjt4GObltD7c+MkCIpO2QIbojw8MUs+CCTqOphQi3Qtg1FLmYt+l+6YeoIf51J7w==} engines: {node: '>=14.0.0'} peerDependencies: @@ -8006,8 +8146,8 @@ packages: rollup: optional: true dependencies: - '@rollup/pluginutils': 5.0.2(rollup@3.27.2) - rollup: 3.27.2 + '@rollup/pluginutils': 5.0.2(rollup@3.21.0) + rollup: 3.21.0 dev: true /@rollup/plugin-node-resolve@13.3.0(rollup@2.79.0): @@ -8025,7 +8165,7 @@ packages: rollup: 2.79.0 dev: true - /@rollup/plugin-node-resolve@15.0.0(rollup@3.27.2): + /@rollup/plugin-node-resolve@15.0.0(rollup@3.21.0): resolution: {integrity: sha512-iwJbzfTzlzDDQcGmkS7EkCKwe2kSkdBrjX87Fy/KrNjr6UNnLpod0t6X66e502LRe5JJCA4FFqrEscWPnZAkig==} engines: {node: '>=14.0.0'} peerDependencies: @@ -8040,7 +8180,7 @@ packages: is-builtin-module: 3.2.0 is-module: 1.0.0 resolve: 1.22.2 - rollup: 3.27.2 + rollup: 3.21.0 dev: true /@rollup/plugin-url@7.0.0(rollup@2.79.0): @@ -8090,7 +8230,7 @@ packages: rollup: 2.79.0 dev: true - /@rollup/pluginutils@5.0.2(rollup@3.27.2): + /@rollup/pluginutils@5.0.2(rollup@3.21.0): resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} engines: {node: '>=14.0.0'} peerDependencies: @@ -8102,7 +8242,7 @@ packages: '@types/estree': 1.0.1 estree-walker: 2.0.2 picomatch: 2.3.1 - rollup: 3.27.2 + rollup: 3.21.0 dev: true /@rushstack/eslint-patch@1.2.0: @@ -8490,7 +8630,7 @@ packages: '@storybook/preview-api': 7.2.2 '@storybook/theming': 7.2.2(react-dom@18.2.0)(react@18.2.0) '@storybook/types': 7.2.2 - '@types/lodash': 4.14.188 + '@types/lodash': 4.14.197 color-convert: 2.0.1 dequal: 2.0.3 lodash: 4.17.21 @@ -8501,7 +8641,7 @@ packages: react-colorful: 5.6.1(react-dom@18.2.0)(react@18.2.0) react-dom: 18.2.0(react@18.2.0) telejson: 7.1.0 - tocbot: 4.21.0 + tocbot: 4.21.1 ts-dedent: 2.2.0 util-deprecate: 1.0.2 transitivePeerDependencies: @@ -8520,10 +8660,10 @@ packages: '@storybook/node-logger': 7.2.2 '@types/ejs': 3.1.2 '@types/find-cache-dir': 3.2.1 - '@yarnpkg/esbuild-plugin-pnp': 3.0.0-rc.15(esbuild@0.18.20) + '@yarnpkg/esbuild-plugin-pnp': 3.0.0-rc.15(esbuild@0.18.17) browser-assert: 1.2.1 ejs: 3.1.8 - esbuild: 0.18.20 + esbuild: 0.18.17 esbuild-plugin-alias: 0.2.1 express: 4.18.2 find-cache-dir: 3.3.2 @@ -8565,7 +8705,7 @@ packages: '@swc/core': 1.3.51(@swc/helpers@0.5.0) '@types/node': 16.18.36 '@types/semver': 7.5.0 - babel-loader: 9.1.3(@babel/core@7.22.9)(webpack@5.88.0) + babel-loader: 9.1.2(@babel/core@7.22.9)(webpack@5.88.0) babel-plugin-named-exports-order: 0.0.2 browser-assert: 1.2.1 case-sensitive-paths-webpack-plugin: 2.4.0 @@ -8621,7 +8761,6 @@ packages: /@storybook/channels@7.1.1: resolution: {integrity: sha512-uhkZFtLIeRnbBhyLlvQAZQmsRbftX/YMGQL+9WRzICrCkwl4xfZPAvMxEgCj1iJzNFcaX5ma9XzHb7q/i+wUCw==} dependencies: - '@storybook/channels': registry.npmjs.org/@storybook/channels@7.1.1 '@storybook/client-logger': 7.1.1 '@storybook/core-events': 7.1.1 '@storybook/global': 5.0.0 @@ -8724,8 +8863,8 @@ packages: '@types/node-fetch': 2.6.4 '@types/pretty-hrtime': 1.0.1 chalk: 4.1.2 - esbuild: 0.18.20 - esbuild-register: 3.4.2(esbuild@0.18.20) + esbuild: 0.18.17 + esbuild-register: 3.4.2(esbuild@0.18.17) file-system-cache: 2.3.0 find-cache-dir: 3.3.2 find-up: 5.0.0 @@ -8818,7 +8957,7 @@ packages: '@storybook/core-common': 7.2.2 '@storybook/node-logger': 7.2.2 '@storybook/types': 7.2.2 - '@types/node': 16.18.47 + '@types/node': 16.18.36 ts-dedent: 2.2.0 transitivePeerDependencies: - encoding @@ -9274,8 +9413,8 @@ packages: - encoding dev: true - /@supabase/gotrue-js@2.39.1: - resolution: {integrity: sha512-qRz9mBleA/QATGKOdMAUjpn+YcbZJrTHyWQCe2hAFqJo15JIe1XziD1ZeFraRpsXwja+vONslGeynGv7H8ZZeQ==} + /@supabase/gotrue-js@2.46.0: + resolution: {integrity: sha512-XRSPjya9wDG2zwsRy1IBKGH8as0NZmGcAmKd2Y6zr97ab6lgvs+/ocJ4Tq8Nw4TxXFTNurMOC++IqsfwxCAi4A==} dependencies: cross-fetch: 3.1.8 transitivePeerDependencies: @@ -9312,7 +9451,7 @@ packages: resolution: {integrity: sha512-RXmTPTobaYAwkSobadHZmEVLmzX3SGrtRZIGfLWnLv92VzBRrjuXn0a+bJqKl50GUzsyqPA+j5pod7EwMkcH5A==} dependencies: '@supabase/functions-js': 2.1.2 - '@supabase/gotrue-js': 2.39.1 + '@supabase/gotrue-js': 2.46.0 '@supabase/postgrest-js': 1.7.2 '@supabase/realtime-js': 2.7.3 '@supabase/storage-js': 2.5.1 @@ -9418,7 +9557,7 @@ packages: '@babel/core': 7.22.9 '@svgr/babel-preset': 8.0.0(@babel/core@7.22.9) camelcase: 6.3.0 - cosmiconfig: 8.2.0 + cosmiconfig: 8.1.3 snake-case: 3.0.4 transitivePeerDependencies: - supports-color @@ -9454,7 +9593,7 @@ packages: '@svgr/core': '*' dependencies: '@svgr/core': 8.0.0 - cosmiconfig: 8.2.0 + cosmiconfig: 8.1.3 deepmerge: 4.3.1 svgo: 3.0.2 dev: true @@ -9798,7 +9937,7 @@ packages: /@types/babel__core@7.1.20: resolution: {integrity: sha512-PVb6Bg2QuscZ30FvOU7z4guG6c926D9YRvOxEaelzndpMsvP+YM74Q/dAFASpg2l6+XLalxSGxcq/lrgYWZtyQ==} dependencies: - '@babel/parser': 7.22.7 + '@babel/parser': 7.22.5 '@babel/types': 7.22.5 '@types/babel__generator': 7.6.4 '@types/babel__template': 7.4.1 @@ -9814,7 +9953,7 @@ packages: /@types/babel__template@7.4.1: resolution: {integrity: sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==} dependencies: - '@babel/parser': 7.22.7 + '@babel/parser': 7.22.5 '@babel/types': 7.22.5 dev: true @@ -9912,15 +10051,8 @@ packages: /@types/eslint-scope@3.7.4: resolution: {integrity: sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==} dependencies: - '@types/eslint': 8.4.1 - '@types/estree': 1.0.1 - dev: true - - /@types/eslint@8.4.1: - resolution: {integrity: sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA==} - dependencies: + '@types/eslint': 8.44.2 '@types/estree': 1.0.1 - '@types/json-schema': 7.0.12 dev: true /@types/eslint@8.44.2: @@ -10012,7 +10144,7 @@ packages: /@types/hast@2.3.4: resolution: {integrity: sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==} dependencies: - '@types/unist': 3.0.0 + '@types/unist': 2.0.6 /@types/hoist-non-react-statics@3.3.1: resolution: {integrity: sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==} @@ -10075,7 +10207,7 @@ packages: resolution: {integrity: sha512-VaywcGQ9tPorCX/Jkkni7RWGFfI11whqzs8dvxF41P17Z+z872thvEvlIbznjPJ02kl1HMX3LmLOonsj2n7HeQ==} dependencies: expect: 29.5.0 - pretty-format: 29.5.0 + pretty-format: 29.4.3 dev: true /@types/js-yaml@4.0.5: @@ -10129,8 +10261,8 @@ packages: dev: false optional: true - /@types/lodash@4.14.188: - resolution: {integrity: sha512-zmEmF5OIM3rb7SbLCFYoQhO4dGt2FRM9AMkxvA3LaADOF1n8in/zGJlWji9fmafLoNyz+FoL6FE0SLtGIArD7w==} + /@types/lodash@4.14.197: + resolution: {integrity: sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g==} /@types/lru-cache@5.1.1: resolution: {integrity: sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==} @@ -10195,8 +10327,8 @@ packages: resolution: {integrity: sha512-8egDX8dE50XyXWH6C6PRCNkTP106DuUrvdrednFouDSmCi7IOvrqr0frznfZaHifHH/3aq/7a7v9N4wdXMqhBQ==} dev: true - /@types/node@16.18.47: - resolution: {integrity: sha512-yBaT6qZKmvaeTuv8kfv2QwIsgi/D4bYSLmHow/IBxjLNRHxYEXgwVRvBmnNLBXi3CkZg0Wdzu3NTUlUjjxconQ==} + /@types/node@16.18.48: + resolution: {integrity: sha512-mlaecDKQ7rIZrYD7iiKNdzFb6e/qD5I9U1rAhq+Fd+DWvYVs+G2kv74UFHmSOlg5+i/vF3XxuR522V4u8BqO+Q==} dev: true /@types/node@18.16.9: @@ -10206,6 +10338,10 @@ packages: resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} dev: true + /@types/npm-package-arg@6.1.1: + resolution: {integrity: sha512-452/1Kp9IdM/oR10AyqAgZOxUt7eLbm+EMJ194L6oarMYdZNiFIFAOJ7IIr0OrZXTySgfHjJezh2oiyk2kc3ag==} + dev: true + /@types/parse-json@4.0.0: resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} dev: true @@ -10319,10 +10455,10 @@ packages: /@types/unist@2.0.6: resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==} - dev: true /@types/unist@3.0.0: resolution: {integrity: sha512-MFETx3tbTjE7Uk6vvnWINA/1iJ7LuMdO4fcq8UfF0pRbj01aGLduVvQcRyswuACJdpnHgg8E3rQLhaRdNEJS0w==} + dev: true /@types/use-sync-external-store@0.0.3: resolution: {integrity: sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==} @@ -10385,7 +10521,7 @@ packages: typescript: optional: true dependencies: - '@eslint-community/regexpp': 4.6.2 + '@eslint-community/regexpp': 4.5.0 '@typescript-eslint/parser': 5.62.0(eslint@8.46.0)(typescript@5.1.3) '@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/type-utils': 5.62.0(eslint@8.46.0)(typescript@5.1.3) @@ -10649,7 +10785,7 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: '@typescript-eslint/types': 5.59.2 - eslint-visitor-keys: 3.4.2 + eslint-visitor-keys: 3.3.0 dev: true /@typescript-eslint/visitor-keys@5.60.1: @@ -10657,7 +10793,7 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: '@typescript-eslint/types': 5.60.1 - eslint-visitor-keys: 3.4.2 + eslint-visitor-keys: 3.3.0 dev: true /@typescript-eslint/visitor-keys@5.62.0: @@ -10665,7 +10801,7 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: '@typescript-eslint/types': 5.62.0 - eslint-visitor-keys: 3.4.2 + eslint-visitor-keys: 3.3.0 dev: true /@verdaccio/commons-api@10.2.0: @@ -11136,13 +11272,13 @@ packages: resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} dev: true - /@yarnpkg/esbuild-plugin-pnp@3.0.0-rc.15(esbuild@0.18.20): + /@yarnpkg/esbuild-plugin-pnp@3.0.0-rc.15(esbuild@0.18.17): resolution: {integrity: sha512-kYzDJO5CA9sy+on/s2aIW0411AklfCi8Ck/4QDivOqsMKpStZA2SsR+X27VTggGwpStWaLrjJcDcdDMowtG8MA==} engines: {node: '>=14.15.0'} peerDependencies: esbuild: '>=0.10.0' dependencies: - esbuild: 0.18.20 + esbuild: 0.18.17 tslib: 2.6.1 dev: true @@ -11207,7 +11343,7 @@ packages: /acorn-globals@7.0.1: resolution: {integrity: sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==} dependencies: - acorn: 8.10.0 + acorn: 8.8.2 acorn-walk: 8.2.0 dev: true @@ -11243,6 +11379,14 @@ packages: acorn: 8.10.0 dev: true + /acorn-jsx@5.3.2(acorn@8.8.2): + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.8.2 + dev: true + /acorn-node@1.8.2: resolution: {integrity: sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==} dependencies: @@ -11323,7 +11467,7 @@ packages: indent-string: 4.0.0 dev: true - /ai@2.2.10(react@18.2.0)(solid-js@1.7.11)(svelte@4.2.0)(vue@3.3.4): + /ai@2.2.10(react@18.2.0)(solid-js@1.7.11)(svelte@4.1.1)(vue@3.3.4): resolution: {integrity: sha512-3FARCB9X57YxpAJeAUvZHTeeQ549B/kTMQk5Qet1rZNm9EjKXeHUiQfaq+L8v9f75HYasZXJIl//owzdjojTTw==} engines: {node: '>=14.6'} peerDependencies: @@ -11347,8 +11491,8 @@ packages: react: 18.2.0 solid-js: 1.7.11 solid-swr-store: 0.10.7(solid-js@1.7.11)(swr-store@0.10.6) - sswr: 2.0.0(svelte@4.2.0) - svelte: 4.2.0 + sswr: 2.0.0(svelte@4.1.1) + svelte: 4.1.1 swr: 2.2.0(react@18.2.0) swr-store: 0.10.6 swrv: 1.0.4(vue@3.3.4) @@ -11544,12 +11688,12 @@ packages: readable-stream: 3.6.0 dev: true - /are-we-there-yet@4.0.0: - resolution: {integrity: sha512-nSXlV+u3vtVjRgihdTzbfWYzxPWGo424zPgQbHD0ZqIla3jqYAewDcvee0Ua2hjS5IfTAmjGlx1Jf0PKwjZDEw==} + /are-we-there-yet@4.0.1: + resolution: {integrity: sha512-2zuA+jpOYBRgoBCfa+fB87Rk0oGJjDX6pxGzqH6f33NzUhG25Xur6R0u0Z9VVAq8Z5JvQpQI6j6rtonuivC8QA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: delegates: 1.0.0 - readable-stream: 4.3.0 + readable-stream: 4.4.2 dev: true /arg@4.1.3: @@ -11585,7 +11729,7 @@ packages: dependencies: '@types/react': 18.2.14 react: 18.2.0 - tslib: 2.6.1 + tslib: 2.5.3 dev: true /aria-query@4.2.2: @@ -12003,7 +12147,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.22.9 + '@babel/compat-data': 7.22.5 '@babel/core': 7.22.9 '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.22.9) semver: 6.3.1 @@ -12011,15 +12155,28 @@ packages: - supports-color dev: true - /babel-plugin-polyfill-corejs2@0.4.4(@babel/core@7.22.9): - resolution: {integrity: sha512-9WeK9snM1BfxB38goUEv2FLnA6ja07UMfazFHzCXUb3NyDZAwfXvQiURQ6guTTMeHcOsdknULm1PDhs4uWtKyA==} + /babel-plugin-polyfill-corejs2@0.4.3(@babel/core@7.22.9): + resolution: {integrity: sha512-bM3gHc337Dta490gg+/AseNB9L4YLHxq1nGKZZSHbhXv4aTYU2MD2cjza1Ru4S6975YLTaL1K8uJf6ukJhhmtw==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/compat-data': 7.22.9 '@babel/core': 7.22.9 - '@babel/helper-define-polyfill-provider': 0.4.1(@babel/core@7.22.9) - '@nicolo-ribaudo/semver-v6': 6.3.3 + '@babel/helper-define-polyfill-provider': 0.4.0(@babel/core@7.22.9) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-polyfill-corejs2@0.4.5(@babel/core@7.22.9): + resolution: {integrity: sha512-19hwUH5FKl49JEsvyTcoHakh6BE0wgXLLptIyKZ3PijHc/Ci521wygORCUCCred+E/twuqRyAkE02BAWPmsHOg==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/compat-data': 7.22.9 + '@babel/core': 7.22.9 + '@babel/helper-define-polyfill-provider': 0.4.2(@babel/core@7.22.9) + semver: 6.3.1 transitivePeerDependencies: - supports-color dev: true @@ -12031,41 +12188,64 @@ packages: dependencies: '@babel/core': 7.22.9 '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.22.9) - core-js-compat: 3.31.1 + core-js-compat: 3.30.2 transitivePeerDependencies: - supports-color dev: true - /babel-plugin-polyfill-corejs3@0.8.2(@babel/core@7.22.9): - resolution: {integrity: sha512-Cid+Jv1BrY9ReW9lIfNlNpsI53N+FN7gE+f73zLAUbr9C52W4gKLWSByx47pfDJsEysojKArqOtOKZSVIIUTuQ==} + /babel-plugin-polyfill-corejs3@0.8.1(@babel/core@7.22.9): + resolution: {integrity: sha512-ikFrZITKg1xH6pLND8zT14UPgjKHiGLqex7rGEZCH2EvhsneJaJPemmpQaIZV5AL03II+lXylw3UmddDK8RU5Q==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.22.9 - '@babel/helper-define-polyfill-provider': 0.4.1(@babel/core@7.22.9) + '@babel/helper-define-polyfill-provider': 0.4.0(@babel/core@7.22.9) + core-js-compat: 3.31.1 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-polyfill-corejs3@0.8.3(@babel/core@7.22.9): + resolution: {integrity: sha512-z41XaniZL26WLrvjy7soabMXrfPWARN25PZoriDEiLMxAp50AUW3t35BGQUMg5xK3UrpVTtagIDklxYa+MhiNA==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-define-polyfill-provider': 0.4.2(@babel/core@7.22.9) core-js-compat: 3.31.1 transitivePeerDependencies: - supports-color dev: true - /babel-plugin-polyfill-regenerator@0.4.1(@babel/core@7.22.9): - resolution: {integrity: sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==} + /babel-plugin-polyfill-regenerator@0.4.1(@babel/core@7.22.9): + resolution: {integrity: sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.22.9 + '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.22.9) + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-polyfill-regenerator@0.5.0(@babel/core@7.22.9): + resolution: {integrity: sha512-hDJtKjMLVa7Z+LwnTCxoDLQj6wdc+B8dun7ayF2fYieI6OzfuvcLMB32ihJZ4UhCBwNYGl5bg/x/P9cMdnkc2g==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.22.9 - '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.22.9) + '@babel/helper-define-polyfill-provider': 0.4.0(@babel/core@7.22.9) transitivePeerDependencies: - supports-color dev: true - /babel-plugin-polyfill-regenerator@0.5.1(@babel/core@7.22.9): - resolution: {integrity: sha512-L8OyySuI6OSQ5hFy9O+7zFjyr4WhAfRjLIOkhQGYl+emwJkd/S4XXT1JpfrgR1jrQ1NcGiOh+yAdGlF8pnC3Jw==} + /babel-plugin-polyfill-regenerator@0.5.2(@babel/core@7.22.9): + resolution: {integrity: sha512-tAlOptU0Xj34V1Y2PNTL4Y0FOJMDB6bZmoW39FeCQIhigGLkqu3Fj6uiXpxIf6Ij274ENdYx64y6Au+ZKlb1IA==} peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 dependencies: '@babel/core': 7.22.9 - '@babel/helper-define-polyfill-provider': 0.4.1(@babel/core@7.22.9) + '@babel/helper-define-polyfill-provider': 0.4.2(@babel/core@7.22.9) transitivePeerDependencies: - supports-color dev: true @@ -12108,7 +12288,7 @@ packages: /babel-plugin-transform-flow-enums@0.0.2(@babel/core@7.22.9): resolution: {integrity: sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==} dependencies: - '@babel/plugin-syntax-flow': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-syntax-flow': 7.18.6(@babel/core@7.22.9) transitivePeerDependencies: - '@babel/core' dev: true @@ -12155,8 +12335,8 @@ packages: '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.22.9) '@babel/plugin-proposal-object-rest-spread': 7.20.7(@babel/core@7.22.9) '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.22.9) - '@babel/plugin-syntax-flow': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-syntax-flow': 7.18.6(@babel/core@7.22.9) + '@babel/plugin-syntax-jsx': 7.21.4(@babel/core@7.22.9) '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.22.9) '@babel/plugin-transform-arrow-functions': 7.22.5(@babel/core@7.22.9) '@babel/plugin-transform-block-scoped-functions': 7.22.5(@babel/core@7.22.9) @@ -12164,7 +12344,7 @@ packages: '@babel/plugin-transform-classes': 7.22.6(@babel/core@7.22.9) '@babel/plugin-transform-computed-properties': 7.22.5(@babel/core@7.22.9) '@babel/plugin-transform-destructuring': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-flow-strip-types': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-flow-strip-types': 7.21.0(@babel/core@7.22.9) '@babel/plugin-transform-for-of': 7.22.5(@babel/core@7.22.9) '@babel/plugin-transform-function-name': 7.22.5(@babel/core@7.22.9) '@babel/plugin-transform-literals': 7.22.5(@babel/core@7.22.9) @@ -12173,12 +12353,14 @@ packages: '@babel/plugin-transform-object-super': 7.22.5(@babel/core@7.22.9) '@babel/plugin-transform-parameters': 7.22.5(@babel/core@7.22.9) '@babel/plugin-transform-property-literals': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-react-display-name': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-react-jsx': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-react-display-name': 7.18.6(@babel/core@7.22.9) + '@babel/plugin-transform-react-jsx': 7.21.0(@babel/core@7.22.9) '@babel/plugin-transform-shorthand-properties': 7.22.5(@babel/core@7.22.9) '@babel/plugin-transform-spread': 7.22.5(@babel/core@7.22.9) '@babel/plugin-transform-template-literals': 7.22.5(@babel/core@7.22.9) babel-plugin-syntax-trailing-function-commas: 7.0.0-beta.0 + transitivePeerDependencies: + - supports-color dev: true /babel-preset-jest@29.5.0(@babel/core@7.22.9): @@ -12261,8 +12443,8 @@ packages: executable: 4.1.1 dev: true - /bin-links@4.0.1: - resolution: {integrity: sha512-bmFEM39CyX336ZGGRsGPlc6jZHriIoHacOQcTt72MktIjpPhZoP4te2jOyUXF3BLILmJ8aNLncoPVeIIFlrDeA==} + /bin-links@4.0.2: + resolution: {integrity: sha512-jxJ0PbXR8eQyPlExCvCs3JFnikvs1Yp4gUJt6nmgathdOwvur+q22KWC3h20gvWl4T/14DXKj2IlkJwwZkZPOw==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: cmd-shim: 6.0.1 @@ -12497,8 +12679,8 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001517 - electron-to-chromium: 1.4.466 + caniuse-lite: 1.0.30001492 + electron-to-chromium: 1.4.417 node-releases: 2.0.12 update-browserslist-db: 1.0.11(browserslist@4.21.5) dev: true @@ -12508,8 +12690,8 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001517 - electron-to-chromium: 1.4.466 + caniuse-lite: 1.0.30001492 + electron-to-chromium: 1.4.417 node-releases: 2.0.12 update-browserslist-db: 1.0.11(browserslist@4.21.7) dev: true @@ -12520,7 +12702,7 @@ packages: hasBin: true dependencies: caniuse-lite: 1.0.30001517 - electron-to-chromium: 1.4.466 + electron-to-chromium: 1.4.470 node-releases: 2.0.12 update-browserslist-db: 1.0.11(browserslist@4.21.9) @@ -12678,7 +12860,7 @@ packages: promise-inflight: 1.0.1 rimraf: 3.0.2 ssri: 9.0.1 - tar: 6.1.13 + tar: 6.1.15 unique-filename: 2.0.1 transitivePeerDependencies: - bluebird @@ -12698,7 +12880,7 @@ packages: minipass-pipeline: 1.2.4 p-map: 4.0.0 ssri: 10.0.4 - tar: 6.1.13 + tar: 6.1.15 unique-filename: 3.0.0 dev: true @@ -12806,6 +12988,10 @@ packages: /caniuse-lite@1.0.30001480: resolution: {integrity: sha512-q7cpoPPvZYgtyC4VaBSN0Bt+PJ4c4EYRf0DrduInOz2SkFpHD5p3LnvEpqBp7UnJn+8x1Ogl1s38saUxe+ihQQ==} + /caniuse-lite@1.0.30001492: + resolution: {integrity: sha512-2efF8SAZwgAX1FJr87KWhvuJxnGJKOnctQa8xLOskAXNXq8oiuqgl6u1kk3fFpsp3GgvzlRjiK1sl63hNtFADw==} + dev: true + /caniuse-lite@1.0.30001517: resolution: {integrity: sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA==} @@ -13032,12 +13218,12 @@ packages: /client-only@0.0.1: resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} - /clipanion@3.1.0(typanion@3.14.0): + /clipanion@3.1.0(typanion@3.12.1): resolution: {integrity: sha512-v025Hz+IDQ15FpOyK8p02h5bFznMu6rLFsJSyOPR+7WrbSnZ1Ek6pblPukV7K5tC/dsWfncQPIrJ4iUy2PXkbw==} peerDependencies: typanion: '*' dependencies: - typanion: 3.14.0 + typanion: 3.12.1 dev: true /cliui@7.0.4: @@ -13093,8 +13279,8 @@ packages: engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} dev: true - /code-red@1.0.4: - resolution: {integrity: sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==} + /code-red@1.0.3: + resolution: {integrity: sha512-kVwJELqiILQyG5aeuyKFbdsI1fmQy1Cmf7dQ8eGmVuJoaRVdwey7WaMknr2ZFeVSYSKT0rExsa8EGw0aoI/1QQ==} dependencies: '@jridgewell/sourcemap-codec': 1.4.15 '@types/estree': 1.0.1 @@ -13609,6 +13795,12 @@ packages: webpack: 5.88.2(@swc/core@1.3.51)(esbuild@0.18.17) dev: true + /core-js-compat@3.30.2: + resolution: {integrity: sha512-nriW1nuJjUgvkEjIot1Spwakz52V9YkYHZAQG6A1eCgC8AA1p0zngrQEP9R0+V6hji5XilWKG1Bd0YRppmGimA==} + dependencies: + browserslist: 4.21.9 + dev: true + /core-js-compat@3.31.1: resolution: {integrity: sha512-wIDWd2s5/5aJSdpOJHfSibxNODxoGoWOBHt8JSPB41NOE94M7kuTPZCYLOlTtuoXTsBPKobpJ6T+y0SSy5L9SA==} dependencies: @@ -13689,6 +13881,16 @@ packages: yaml: 1.10.2 dev: true + /cosmiconfig@8.1.3: + resolution: {integrity: sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==} + engines: {node: '>=14'} + dependencies: + import-fresh: 3.3.0 + js-yaml: 4.1.0 + parse-json: 5.2.0 + path-type: 4.0.0 + dev: true + /cosmiconfig@8.2.0: resolution: {integrity: sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==} engines: {node: '>=14'} @@ -14109,15 +14311,15 @@ packages: resolution: {integrity: sha512-d4ZVpCW31eWwCMe1YT3ur7mUDnTXbgwyzaL320DrcRT45rfjYxkt5QWLrmOJ+/UEAI2+fQgKe/fCjR8l4TpRgw==} dev: true - /cypress@13.1.0: - resolution: {integrity: sha512-LUKxCYlB973QBFls1Up4FAE9QIYobT+2I8NvvAwMfQS2YwsWbr6yx7y9hmsk97iqbHkKwZW3MRjoK1RToBFVdQ==} + /cypress@13.0.0: + resolution: {integrity: sha512-nWHU5dUxP2Wm/zrMd8SWTTl706aJex/l+H4vi/tbu2SWUr17BUcd/sIYeqyxeoSPW1JFV2pT1pf4JEImH/POMg==} engines: {node: ^16.0.0 || ^18.0.0 || >=20.0.0} hasBin: true requiresBuild: true dependencies: - '@cypress/request': 3.0.0 + '@cypress/request': 3.0.1 '@cypress/xvfb': 1.2.4(supports-color@8.1.1) - '@types/node': 16.18.47 + '@types/node': 16.18.48 '@types/sinonjs__fake-timers': 8.1.1 '@types/sizzle': 2.3.3 arch: 2.2.0 @@ -14147,7 +14349,7 @@ packages: listr2: 3.14.0(enquirer@2.3.6) lodash: 4.17.21 log-symbols: 4.1.0 - minimist: 1.2.8 + minimist: 1.2.7 ospath: 1.2.2 pretty-bytes: 5.6.0 process: 0.11.10 @@ -14559,7 +14761,7 @@ packages: dependencies: acorn-node: 1.8.2 defined: 1.0.1 - minimist: 1.2.8 + minimist: 1.2.7 /dev-ip@1.0.1: resolution: {integrity: sha512-LmVkry/oDShEgSZPNgqCIp2/TlqtExeGmymru3uCELnfyjY11IzpAproLYs+1X88fXO6DBoYP3ul2Xo2yz2j6A==} @@ -14802,8 +15004,12 @@ packages: resolution: {integrity: sha512-/xlATgfwkm5uDDwLw5nt/MNEf7c1oazLURMZLy39vOioGYyYzLWIDT8fZMJak6qTiAJ7udFTy7JG7ziyjNutiA==} dev: true - /electron-to-chromium@1.4.466: - resolution: {integrity: sha512-TSkRvbXRXD8BwhcGlZXDsbI2lRoP8dvqR7LQnqQNk9KxXBc4tG8O+rTuXgTyIpEdiqSGKEBSqrxdqEntnjNncA==} + /electron-to-chromium@1.4.417: + resolution: {integrity: sha512-8rY8HdCxuSVY8wku3i/eDac4g1b4cSbruzocenrqBlzqruAZYHjQCHIjC66dLR9DXhEHTojsC4EjhZ8KmzwXqA==} + dev: true + + /electron-to-chromium@1.4.470: + resolution: {integrity: sha512-zZM48Lmy2FKWgqyvsX9XK+J6FfP7aCDUFLmgooLJzA7v1agCs/sxSoBpTIwDLhmbhpx9yJIxj2INig/ncjJRqg==} /emittery@0.13.1: resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} @@ -14981,7 +15187,7 @@ packages: is-shared-array-buffer: 1.0.2 is-string: 1.0.7 is-weakref: 1.0.2 - object-inspect: 1.12.3 + object-inspect: 1.12.2 object-keys: 1.1.1 object.assign: 4.1.4 regexp.prototype.flags: 1.4.3 @@ -15066,13 +15272,13 @@ packages: resolution: {integrity: sha512-jyfL/pwPqaFXyKnj8lP8iLk6Z0m099uXR45aSN8Av1XD4vhvQutxxPzgA2bTcAwQpa1zCXDcWOlhFgyP3GKqhQ==} dev: true - /esbuild-register@3.4.2(esbuild@0.18.20): + /esbuild-register@3.4.2(esbuild@0.18.17): resolution: {integrity: sha512-kG/XyTDyz6+YDuyfB9ZoSIOOmgyFCH+xPRtsCa8W85HLRV5Csp+o3jWVbOSHgSLfyLc5DmP+KFDNwty4mEjC+Q==} peerDependencies: esbuild: '>=0.12 <1' dependencies: debug: 4.3.4(supports-color@5.5.0) - esbuild: 0.18.20 + esbuild: 0.18.17 transitivePeerDependencies: - supports-color dev: true @@ -15083,8 +15289,8 @@ packages: hasBin: true dev: true - /esbuild-wasm@0.19.0: - resolution: {integrity: sha512-RqTcOMscbNJEEbPjEUK/37G8nZyC9Ixobv4M/pRhVjb6/v+WxxivAOjaKQKgOpM8zHjQdHALXx0vnpEVYaxKtw==} + /esbuild-wasm@0.19.2: + resolution: {integrity: sha512-ak2XIIJKby+Uo3Iqh8wtw4pn2uZcnfLgtcmBHIgkShpun5ZIJsFigWXp7uLt7gXk3QAOCMmv0TSsIxD5qdn+Vw==} engines: {node: '>=12'} hasBin: true dev: true @@ -15148,36 +15354,6 @@ packages: '@esbuild/win32-x64': 0.18.17 dev: true - /esbuild@0.18.20: - resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/android-arm': 0.18.20 - '@esbuild/android-arm64': 0.18.20 - '@esbuild/android-x64': 0.18.20 - '@esbuild/darwin-arm64': 0.18.20 - '@esbuild/darwin-x64': 0.18.20 - '@esbuild/freebsd-arm64': 0.18.20 - '@esbuild/freebsd-x64': 0.18.20 - '@esbuild/linux-arm': 0.18.20 - '@esbuild/linux-arm64': 0.18.20 - '@esbuild/linux-ia32': 0.18.20 - '@esbuild/linux-loong64': 0.18.20 - '@esbuild/linux-mips64el': 0.18.20 - '@esbuild/linux-ppc64': 0.18.20 - '@esbuild/linux-riscv64': 0.18.20 - '@esbuild/linux-s390x': 0.18.20 - '@esbuild/linux-x64': 0.18.20 - '@esbuild/netbsd-x64': 0.18.20 - '@esbuild/openbsd-x64': 0.18.20 - '@esbuild/sunos-x64': 0.18.20 - '@esbuild/win32-arm64': 0.18.20 - '@esbuild/win32-ia32': 0.18.20 - '@esbuild/win32-x64': 0.18.20 - dev: true - /esbuild@0.19.2: resolution: {integrity: sha512-G6hPax8UbFakEj3hWO0Vs52LQ8k3lnBhxZWomUJDxfz3rZTLqF5k/FCzuNdLx2RbpBiQQF9H9onlDDH1lZsnjg==} engines: {node: '>=12'} @@ -15355,7 +15531,7 @@ packages: eslint: '>= 3.2.1' dependencies: eslint: 8.46.0 - globals: 13.20.0 + globals: 13.21.0 dev: true /eslint-plugin-import@2.26.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-typescript@3.5.2)(eslint@8.46.0): @@ -15501,8 +15677,8 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /eslint-visitor-keys@3.4.2: - resolution: {integrity: sha512-8drBzUEyZ2llkpCA67iYrgEssKDUu68V8ChqqOfFupIaG/LCVPUT+CoGJpT77zJprs4T/W7p07LP7zAIMuweVw==} + /eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true @@ -15525,7 +15701,7 @@ packages: doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.2 + eslint-visitor-keys: 3.4.3 espree: 9.6.1 esquery: 1.5.0 esutils: 2.0.3 @@ -15533,7 +15709,7 @@ packages: file-entry-cache: 6.0.1 find-up: 5.0.0 glob-parent: 6.0.2 - globals: 13.20.0 + globals: 13.21.0 graphemer: 1.4.0 ignore: 5.2.0 imurmurhash: 0.1.4 @@ -15556,9 +15732,9 @@ packages: resolution: {integrity: sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - acorn: 8.10.0 - acorn-jsx: 5.3.2(acorn@8.10.0) - eslint-visitor-keys: 3.4.2 + acorn: 8.8.2 + acorn-jsx: 5.3.2(acorn@8.8.2) + eslint-visitor-keys: 3.3.0 dev: true /espree@9.6.1: @@ -15567,7 +15743,7 @@ packages: dependencies: acorn: 8.10.0 acorn-jsx: 5.3.2(acorn@8.10.0) - eslint-visitor-keys: 3.4.2 + eslint-visitor-keys: 3.4.3 dev: true /esprima@4.0.1: @@ -16055,7 +16231,7 @@ packages: /filelist@1.0.4: resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} dependencies: - minimatch: 5.1.0 + minimatch: 5.1.6 dev: true /filename-reserved-regex@3.0.0: @@ -16267,7 +16443,7 @@ packages: fs-extra: 10.1.0 memfs: 3.5.0 minimatch: 3.0.5 - node-abort-controller: 3.1.1 + node-abort-controller: 3.0.1 schema-utils: 3.2.0 semver: 7.5.3 tapable: 2.2.1 @@ -16807,8 +16983,8 @@ packages: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} - /globals@13.20.0: - resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==} + /globals@13.21.0: + resolution: {integrity: sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==} engines: {node: '>=8'} dependencies: type-fest: 0.20.2 @@ -16935,7 +17111,7 @@ packages: engines: {node: '>=0.4.7'} hasBin: true dependencies: - minimist: 1.2.8 + minimist: 1.2.7 neo-async: 2.6.2 source-map: 0.6.1 wordwrap: 1.0.0 @@ -17099,8 +17275,8 @@ packages: lru-cache: 6.0.0 dev: true - /hosted-git-info@5.2.0: - resolution: {integrity: sha512-y5aljBDICf0OFQecausUdWGZbLxSaFc012tdP4xe4GcFMeYUrOptSGaTZ21gvIsPUSe1/K9EVKLYwBOSEOPirw==} + /hosted-git-info@5.2.1: + resolution: {integrity: sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} dependencies: lru-cache: 7.14.0 @@ -17113,6 +17289,13 @@ packages: lru-cache: 7.14.0 dev: true + /hosted-git-info@7.0.0: + resolution: {integrity: sha512-ICclEpTLhHj+zCuSb2/usoNXSVkxUSIopre+b1w8NDY9Dntp9LO4vLdHYI336TH8sAqwrRgnSfdkBG2/YpisHA==} + engines: {node: ^16.14.0 || >=18.0.0} + dependencies: + lru-cache: 10.0.1 + dev: true + /hpack.js@2.1.6: resolution: {integrity: sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==} dependencies: @@ -17155,7 +17338,7 @@ packages: he: 1.2.0 param-case: 3.0.4 relateurl: 0.2.7 - terser: 5.19.2 + terser: 5.18.0 dev: true /html-tags@3.2.0: @@ -17445,7 +17628,7 @@ packages: resolution: {integrity: sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} dependencies: - minimatch: 5.1.0 + minimatch: 5.1.6 dev: true /ignore@5.2.0: @@ -17567,7 +17750,7 @@ packages: npm-package-arg: 9.1.2 promzard: 0.3.0 read: 1.0.7 - read-package-json: 5.0.2 + read-package-json: 5.0.1 semver: 7.5.3 validate-npm-package-license: 3.0.4 validate-npm-package-name: 4.0.0 @@ -18105,7 +18288,7 @@ packages: engines: {node: '>=8'} dependencies: '@babel/core': 7.22.9 - '@babel/parser': 7.22.7 + '@babel/parser': 7.21.4 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.0 semver: 6.3.1 @@ -18389,7 +18572,7 @@ packages: resolution: {integrity: sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@babel/code-frame': 7.22.5 + '@babel/code-frame': 7.21.4 '@jest/types': 29.5.0 '@types/stack-utils': 2.0.1 chalk: 4.1.2 @@ -18521,7 +18704,7 @@ packages: dependencies: '@babel/core': 7.22.9 '@babel/generator': 7.22.9 - '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-syntax-jsx': 7.21.4(@babel/core@7.22.9) '@babel/plugin-syntax-typescript': 7.22.5(@babel/core@7.22.9) '@babel/traverse': 7.22.8 '@babel/types': 7.22.5 @@ -18679,7 +18862,7 @@ packages: optional: true dependencies: abab: 2.0.6 - acorn: 8.10.0 + acorn: 8.8.2 acorn-globals: 6.0.0 cssom: 0.4.4 cssstyle: 2.3.0 @@ -18721,7 +18904,7 @@ packages: optional: true dependencies: abab: 2.0.6 - acorn: 8.10.0 + acorn: 8.8.2 acorn-globals: 7.0.1 cssom: 0.5.0 cssstyle: 2.3.0 @@ -18734,7 +18917,7 @@ packages: http-proxy-agent: 5.0.0 https-proxy-agent: 5.0.1 is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.4 + nwsapi: 2.2.2 parse5: 7.1.2 saxes: 6.0.0 symbol-tree: 3.2.4 @@ -18830,7 +19013,7 @@ packages: hasBin: true dependencies: '@types/json-schema': 7.0.11 - '@types/lodash': 4.14.188 + '@types/lodash': 4.14.197 '@types/prettier': 2.7.1 cli-color: 2.0.3 get-stdin: 8.0.0 @@ -18873,7 +19056,7 @@ packages: resolution: {integrity: sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==} hasBin: true dependencies: - minimist: 1.2.8 + minimist: 1.2.7 dev: true /json5@2.2.3: @@ -18978,8 +19161,8 @@ packages: object.assign: 4.1.4 dev: true - /just-diff-apply@5.4.1: - resolution: {integrity: sha512-AAV5Jw7tsniWwih8Ly3fXxEZ06y+6p5TwQMsw0dzZ/wPKilzyDgdAnL0Ug4NNIquPUOh1vfFWEHbmXUqM5+o8g==} + /just-diff-apply@5.5.0: + resolution: {integrity: sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw==} dev: true /just-diff@6.0.2: @@ -19091,10 +19274,10 @@ packages: dependencies: '@lerna/child-process': 6.6.2 '@lerna/create': 6.6.2 - '@lerna/legacy-package-management': 6.6.2(nx@15.9.4)(typescript@4.9.5) + '@lerna/legacy-package-management': 6.6.2(nx@15.8.0)(typescript@4.9.5) '@npmcli/arborist': 6.2.3 '@npmcli/run-script': 4.1.7 - '@nrwl/devkit': 15.8.0(nx@15.9.4)(typescript@4.9.5) + '@nrwl/devkit': 15.8.0(nx@15.8.0)(typescript@4.9.5) '@octokit/plugin-enterprise-rest': 6.0.1 '@octokit/rest': 19.0.3 byte-size: 7.0.0 @@ -19136,7 +19319,7 @@ packages: npm-packlist: 5.1.1 npm-registry-fetch: 14.0.5 npmlog: 6.0.2 - nx: 15.9.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) + nx: 15.8.0(@swc-node/register@1.5.4)(@swc/core@1.3.51) p-map: 4.0.0 p-map-series: 2.1.0 p-pipe: 3.1.0 @@ -19592,6 +19775,11 @@ packages: highlight.js: 10.7.3 dev: false + /lru-cache@10.0.1: + resolution: {integrity: sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==} + engines: {node: 14 || >=16.14} + dev: true + /lru-cache@4.1.5: resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} dependencies: @@ -20061,7 +20249,7 @@ packages: resolution: {integrity: sha512-FQiZGhIxCzhDwK4LxyPMLlq0Tsmla10X7BfNGlYFK0A5IsaVKNJbETyTzhpIwc+YFRT4GkFFwgo0V2N5vxO5HA==} engines: {node: '>=16'} dependencies: - terser: 5.19.2 + terser: 5.18.0 dev: true /metro-minify-uglify@0.76.7: @@ -20088,30 +20276,30 @@ packages: '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.22.9) '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.22.9) '@babel/plugin-syntax-export-default-from': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-syntax-flow': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-syntax-flow': 7.18.6(@babel/core@7.22.9) '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.22.9) '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.22.9) '@babel/plugin-transform-arrow-functions': 7.22.5(@babel/core@7.22.9) '@babel/plugin-transform-async-to-generator': 7.22.5(@babel/core@7.22.9) '@babel/plugin-transform-block-scoping': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-classes': 7.22.6(@babel/core@7.22.9) + '@babel/plugin-transform-classes': 7.22.5(@babel/core@7.22.9) '@babel/plugin-transform-computed-properties': 7.22.5(@babel/core@7.22.9) '@babel/plugin-transform-destructuring': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-flow-strip-types': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-flow-strip-types': 7.21.0(@babel/core@7.22.9) '@babel/plugin-transform-function-name': 7.22.5(@babel/core@7.22.9) '@babel/plugin-transform-literals': 7.22.5(@babel/core@7.22.9) '@babel/plugin-transform-modules-commonjs': 7.22.5(@babel/core@7.22.9) '@babel/plugin-transform-named-capturing-groups-regex': 7.22.5(@babel/core@7.22.9) '@babel/plugin-transform-parameters': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-react-display-name': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-react-jsx': 7.22.5(@babel/core@7.22.9) + '@babel/plugin-transform-react-display-name': 7.18.6(@babel/core@7.22.9) + '@babel/plugin-transform-react-jsx': 7.21.0(@babel/core@7.22.9) '@babel/plugin-transform-react-jsx-self': 7.22.5(@babel/core@7.22.9) '@babel/plugin-transform-react-jsx-source': 7.22.5(@babel/core@7.22.9) '@babel/plugin-transform-runtime': 7.22.9(@babel/core@7.22.9) '@babel/plugin-transform-shorthand-properties': 7.22.5(@babel/core@7.22.9) '@babel/plugin-transform-spread': 7.22.5(@babel/core@7.22.9) '@babel/plugin-transform-sticky-regex': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-typescript': 7.22.9(@babel/core@7.22.9) + '@babel/plugin-transform-typescript': 7.21.3(@babel/core@7.22.9) '@babel/plugin-transform-unicode-regex': 7.22.5(@babel/core@7.22.9) '@babel/template': 7.22.5 babel-plugin-transform-flow-enums: 0.0.2(@babel/core@7.22.9) @@ -20183,7 +20371,7 @@ packages: dependencies: '@babel/core': 7.22.9 '@babel/generator': 7.22.9 - '@babel/parser': 7.22.7 + '@babel/parser': 7.22.5 '@babel/types': 7.22.5 babel-preset-fbjs: 3.4.0(@babel/core@7.22.9) metro: 0.76.7 @@ -20207,8 +20395,8 @@ packages: dependencies: '@babel/code-frame': 7.22.5 '@babel/core': 7.22.9 - '@babel/generator': 7.22.9 - '@babel/parser': 7.22.7 + '@babel/generator': 7.22.5 + '@babel/parser': 7.22.5 '@babel/template': 7.22.5 '@babel/traverse': 7.22.8 '@babel/types': 7.22.5 @@ -20244,7 +20432,7 @@ packages: metro-transform-plugins: 0.76.7 metro-transform-worker: 0.76.7 mime-types: 2.1.35 - node-fetch: 2.6.12 + node-fetch: 2.6.7 nullthrows: 1.1.1 rimraf: 3.0.2 serialize-error: 2.1.0 @@ -20461,7 +20649,6 @@ packages: resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} engines: {node: '>=4'} hasBin: true - requiresBuild: true /mime@2.5.2: resolution: {integrity: sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==} @@ -20600,9 +20787,6 @@ packages: /minimist@1.2.7: resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==} - /minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - /minipass-collect@1.0.2: resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} engines: {node: '>= 8'} @@ -20706,7 +20890,7 @@ packages: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true dependencies: - minimist: 1.2.8 + minimist: 1.2.7 /mkdirp@1.0.4: resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} @@ -20727,8 +20911,8 @@ packages: engines: {node: '>=0.10.0'} dev: true - /monaco-editor@0.41.0: - resolution: {integrity: sha512-1o4olnZJsiLmv5pwLEAmzHTE/5geLKQ07BrGxlF4Ri/AXAc2yyDGZwHjiTqD8D/ROKUZmwMA28A+yEowLNOEcA==} + /monaco-editor@0.39.0: + resolution: {integrity: sha512-zhbZ2Nx93tLR8aJmL2zI1mhJpsl87HMebNBM6R8z4pLfs8pj604pIVIVwyF1TivcfNtIPpMXL+nb3DsBmE/x6Q==} dev: false /mri@1.2.0: @@ -20869,7 +21053,7 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /next-sitemap@3.1.29(@next/env@13.3.4)(next@13.3.4): + /next-sitemap@3.1.29(@next/env@13.4.5)(next@13.3.4): resolution: {integrity: sha512-7UQyfpI7obOdB11aCswWYfqRn5CR0YSmWHo1r/uarrFfZD5PyyAWtQlgP6jNqDW0eX1ZJWERBwmJ2dLjl4nT8Q==} engines: {node: '>=14.18'} hasBin: true @@ -20878,7 +21062,7 @@ packages: next: '*' dependencies: '@corex/deepmerge': 4.0.29 - '@next/env': 13.3.4 + '@next/env': 13.4.5 minimist: 1.2.7 next: 13.3.4(@babel/core@7.22.9)(react-dom@18.2.0)(react@18.2.0)(sass@1.55.0) dev: true @@ -20944,8 +21128,8 @@ packages: optional: true dependencies: '@angular/compiler-cli': 16.2.0(@angular/compiler@16.2.0)(typescript@5.1.3) - '@rollup/plugin-json': 6.0.0(rollup@3.27.2) - '@rollup/plugin-node-resolve': 15.0.0(rollup@3.27.2) + '@rollup/plugin-json': 6.0.0(rollup@3.21.0) + '@rollup/plugin-node-resolve': 15.0.0(rollup@3.21.0) ajv: 8.12.0 ansi-colors: 4.1.3 autoprefixer: 10.4.13(postcss@8.4.19) @@ -20955,8 +21139,8 @@ packages: commander: 11.0.0 convert-source-map: 2.0.0 dependency-graph: 0.11.0 - esbuild-wasm: 0.19.0 - fast-glob: 3.3.1 + esbuild-wasm: 0.19.2 + fast-glob: 3.2.12 find-cache-dir: 3.3.2 injection-js: 2.4.0 jsonc-parser: 3.2.0 @@ -20965,7 +21149,7 @@ packages: piscina: 4.1.0 postcss: 8.4.19 postcss-url: 10.1.3(postcss@8.4.19) - rollup: 3.27.2 + rollup: 3.21.0 rxjs: 7.8.1 sass: 1.55.0 tailwindcss: 3.2.4(postcss@8.4.19)(ts-node@10.9.1) @@ -21069,7 +21253,7 @@ packages: npmlog: 6.0.2 rimraf: 3.0.2 semver: 7.5.3 - tar: 6.1.13 + tar: 6.1.15 which: 2.0.2 transitivePeerDependencies: - bluebird @@ -21106,8 +21290,8 @@ packages: abbrev: 1.1.1 dev: true - /nopt@7.1.0: - resolution: {integrity: sha512-ZFPLe9Iu0tnx7oWhFxAo4s7QTn8+NNDDxYNaKLjE7Dp0tbakQ3M1QhQzsnzXHQBTUO3K9BmwaxnyO8Ayn2I95Q==} + /nopt@7.2.0: + resolution: {integrity: sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} hasBin: true dependencies: @@ -21136,7 +21320,7 @@ packages: resolution: {integrity: sha512-EBk5QKKuocMJhB3BILuKhmaPjI8vNRSpIfO9woLC6NyHVkKKdVEdAO1mrT0ZfxNR1lKwCcTkuZfmGIFdizZ8Pg==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} dependencies: - hosted-git-info: 5.2.0 + hosted-git-info: 5.2.1 is-core-module: 2.11.0 semver: 7.5.3 validate-npm-package-license: 3.0.4 @@ -21189,16 +21373,16 @@ packages: /npm-normalize-package-bin@1.0.1: resolution: {integrity: sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==} - /npm-normalize-package-bin@2.0.0: - resolution: {integrity: sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - dev: true - /npm-normalize-package-bin@3.0.0: resolution: {integrity: sha512-g+DPQSkusnk7HYXr75NtzkIP4+N81i3RPsGFidF3DzHd9MT9wWngmqoeg/fnHFz5MNdtG4w03s+QnhewSLTT2Q==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dev: true + /npm-normalize-package-bin@3.0.1: + resolution: {integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: true + /npm-package-arg@10.1.0: resolution: {integrity: sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -21209,6 +21393,16 @@ packages: validate-npm-package-name: 5.0.0 dev: true + /npm-package-arg@11.0.1: + resolution: {integrity: sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==} + engines: {node: ^16.14.0 || >=18.0.0} + dependencies: + hosted-git-info: 7.0.0 + proc-log: 3.0.0 + semver: 7.5.3 + validate-npm-package-name: 5.0.0 + dev: true + /npm-package-arg@8.1.1: resolution: {integrity: sha512-CsP95FhWQDwNqiYS+Q0mZ7FAEDytDZAkNxQqea6IaAFJTAY9Lhhqyl0irU/6PMc7BGfUmnsbHcqxJD7XuVM/rg==} engines: {node: '>=10'} @@ -21222,7 +21416,7 @@ packages: resolution: {integrity: sha512-pzd9rLEx4TfNJkovvlBSLGhq31gGu2QDexFPWT19yCDh0JgnRhlBLNo5759N0AJmBk+kQ9Y/hXoLnlgFD+ukmg==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} dependencies: - hosted-git-info: 5.2.0 + hosted-git-info: 5.2.1 proc-log: 2.0.1 semver: 7.5.3 validate-npm-package-name: 4.0.0 @@ -21329,7 +21523,7 @@ packages: resolution: {integrity: sha512-uJ0YFk/mCQpLBt+bxN88AKd+gyqZvZDbtiNxk6Waqcj2aPRyfVx8ITawkyQynxUagInjdYT1+qj4NfA5KJJUxg==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: - are-we-there-yet: 4.0.0 + are-we-there-yet: 4.0.1 console-control-strings: 1.1.0 gauge: 5.0.1 set-blocking: 2.0.0 @@ -21345,6 +21539,10 @@ packages: resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==} dev: true + /nwsapi@2.2.2: + resolution: {integrity: sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==} + dev: true + /nwsapi@2.2.4: resolution: {integrity: sha512-NHj4rzRo0tQdijE9ZqAx6kYDcoRwYwSYzCA8MY3JzfxlrvEU0jhnhJT9BhqhJs7I/dKcrDm6TyulaRqZPIhN5g==} dev: true @@ -21431,70 +21629,6 @@ packages: - debug dev: true - /nx@15.9.4(@swc-node/register@1.5.4)(@swc/core@1.3.51): - resolution: {integrity: sha512-P1G4t59UvE/lkHyruLeSOB5ZuNyh01IwU0tTUOi8f9s/NbP7+OQ8MYVwDV74JHTr6mQgjlS+n+4Eox8tVm9itA==} - hasBin: true - requiresBuild: true - peerDependencies: - '@swc-node/register': ^1.4.2 - '@swc/core': ^1.2.173 - peerDependenciesMeta: - '@swc-node/register': - optional: true - '@swc/core': - optional: true - dependencies: - '@nrwl/cli': 15.9.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) - '@nrwl/tao': 15.9.4(@swc-node/register@1.5.4)(@swc/core@1.3.51) - '@parcel/watcher': 2.0.4 - '@swc-node/register': 1.5.4(@swc/core@1.3.51)(typescript@5.1.3) - '@swc/core': 1.3.51(@swc/helpers@0.5.0) - '@yarnpkg/lockfile': 1.1.0 - '@yarnpkg/parsers': 3.0.0-rc.46 - '@zkochan/js-yaml': 0.0.6 - axios: 1.0.0 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-spinners: 2.6.1 - cliui: 7.0.4 - dotenv: 10.0.0 - enquirer: 2.3.6 - fast-glob: 3.2.7 - figures: 3.2.0 - flat: 5.0.2 - fs-extra: 11.1.1 - glob: 7.1.4 - ignore: 5.2.0 - js-yaml: 4.1.0 - jsonc-parser: 3.2.0 - lines-and-columns: 2.0.3 - minimatch: 3.0.5 - npm-run-path: 4.0.1 - open: 8.4.2 - semver: 7.3.4 - string-width: 4.2.3 - strong-log-transformer: 2.1.0 - tar-stream: 2.2.0 - tmp: 0.2.1 - tsconfig-paths: 4.1.2 - tslib: 2.6.1 - v8-compile-cache: 2.3.0 - yargs: 17.7.2 - yargs-parser: 21.1.1 - optionalDependencies: - '@nrwl/nx-darwin-arm64': 15.9.4 - '@nrwl/nx-darwin-x64': 15.9.4 - '@nrwl/nx-linux-arm-gnueabihf': 15.9.4 - '@nrwl/nx-linux-arm64-gnu': 15.9.4 - '@nrwl/nx-linux-arm64-musl': 15.9.4 - '@nrwl/nx-linux-x64-gnu': 15.9.4 - '@nrwl/nx-linux-x64-musl': 15.9.4 - '@nrwl/nx-win32-arm64-msvc': 15.9.4 - '@nrwl/nx-win32-x64-msvc': 15.9.4 - transitivePeerDependencies: - - debug - dev: true - /nx@16.8.0-rc.0(@swc-node/register@1.5.4)(@swc/core@1.3.51): resolution: {integrity: sha512-qDKwHg7XmBKPrkMLZmGtYRf8lqF+4nEIDS8jscdcjkfAWGHLbBrAVopJYcqR0uwrRCoYPlpkBVgdGiaiqfcbxQ==} hasBin: true @@ -21578,8 +21712,8 @@ packages: resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} engines: {node: '>= 6'} - /object-inspect@1.12.3: - resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} + /object-inspect@1.12.2: + resolution: {integrity: sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==} dev: true /object-is@1.1.5: @@ -21998,7 +22132,7 @@ packages: '@npmcli/git': 4.0.3 '@npmcli/installed-package-contents': 2.0.1 '@npmcli/promise-spawn': 6.0.1 - '@npmcli/run-script': 6.0.0 + '@npmcli/run-script': 6.0.2 cacache: 17.1.3 fs-minipass: 3.0.0 minipass: 4.2.8 @@ -22008,11 +22142,11 @@ packages: npm-registry-fetch: 14.0.5 proc-log: 3.0.0 promise-retry: 2.0.1 - read-package-json: 6.0.0 + read-package-json: 6.0.4 read-package-json-fast: 3.0.2 sigstore: 1.4.0 ssri: 10.0.4 - tar: 6.1.13 + tar: 6.1.15 transitivePeerDependencies: - bluebird - supports-color @@ -22040,7 +22174,7 @@ packages: read-package-json-fast: 3.0.2 sigstore: 1.4.0 ssri: 10.0.4 - tar: 6.1.13 + tar: 6.1.15 transitivePeerDependencies: - bluebird - supports-color @@ -22070,7 +22204,7 @@ packages: dependencies: json-parse-even-better-errors: 3.0.0 just-diff: 6.0.2 - just-diff-apply: 5.4.1 + just-diff-apply: 5.5.0 dev: true /parse-entities@2.0.0: @@ -23525,6 +23659,15 @@ packages: picocolors: 1.0.0 source-map-js: 1.0.2 + /postcss@8.4.24: + resolution: {integrity: sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.6 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: false + /postcss@8.4.27: resolution: {integrity: sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==} engines: {node: ^10 || ^12 || >=14} @@ -23532,6 +23675,7 @@ packages: nanoid: 3.3.6 picocolors: 1.0.0 source-map-js: 1.0.2 + dev: true /preact@10.6.4: resolution: {integrity: sha512-WyosM7pxGcndU8hY0OQlLd54tOU+qmG45QXj2dAYrL11HoyU/EzOSTlpJsirbBr1QW7lICxSsVJJmcmUglovHQ==} @@ -23668,8 +23812,8 @@ packages: resolution: {integrity: sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==} dev: true - /promise-call-limit@1.0.1: - resolution: {integrity: sha512-3+hgaa19jzCGLuSCbieeRsu5C2joKfYn8pY6JAuXFRVfF4IO+L7UPpFWNTeWT9pM7uhskvbPPd/oEOktCn317Q==} + /promise-call-limit@1.0.2: + resolution: {integrity: sha512-1vTUnfI2hzui8AEIixbdAJlFY4LFDXqQswy/2eOlThAscXCY4It8FdVuI0fMJGAB2aWGbdQf/gv0skKYXmdrHA==} dev: true /promise-inflight@1.0.1: @@ -23721,8 +23865,8 @@ packages: xtend: 4.0.2 dev: false - /property-information@6.2.0: - resolution: {integrity: sha512-kma4U7AFCTwpqq5twzC1YVIDXSqg6qQK6JN0smOw8fgRy1OkMi0CYSzFmsy6dnqSenamAtj0CyXMUJ1Mf6oROg==} + /property-information@6.3.0: + resolution: {integrity: sha512-gVNZ74nqhRMiIUYWGQdosYetaKc83x8oT41a0LlV3AAFCAZwCpg4vmGkq8t34+cUhp3cnM4XDiU/7xlgK7HGrg==} dev: true /proto-list@1.2.4: @@ -23793,6 +23937,13 @@ packages: side-channel: 1.0.4 dev: true + /qs@6.10.4: + resolution: {integrity: sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.4 + dev: true + /qs@6.11.0: resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} engines: {node: '>=0.6'} @@ -23978,7 +24129,7 @@ packages: comma-separated-tokens: 2.0.3 hast-util-whitespace: 2.0.1 prop-types: 15.8.1 - property-information: 6.2.0 + property-information: 6.3.0 react: 18.2.0 react-is: 18.2.0 remark-parse: 10.0.2 @@ -24212,21 +24363,21 @@ packages: npm-normalize-package-bin: 1.0.1 dev: true - /read-package-json@5.0.2: - resolution: {integrity: sha512-BSzugrt4kQ/Z0krro8zhTwV1Kd79ue25IhNN/VtHFy1mG/6Tluyi+msc0UpwaoQzxSHa28mntAjIZY6kEgfR9Q==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + /read-package-json@6.0.0: + resolution: {integrity: sha512-b/9jxWJ8EwogJPpv99ma+QwtqB7FSl3+V6UXS7Aaay8/5VwMY50oIFooY1UKXMWpfNCM6T/PoGqa5GD1g9xf9w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: glob: 8.1.0 - json-parse-even-better-errors: 2.3.1 - normalize-package-data: 4.0.1 - npm-normalize-package-bin: 2.0.0 + json-parse-even-better-errors: 3.0.0 + normalize-package-data: 5.0.0 + npm-normalize-package-bin: 3.0.0 dev: true - /read-package-json@6.0.0: - resolution: {integrity: sha512-b/9jxWJ8EwogJPpv99ma+QwtqB7FSl3+V6UXS7Aaay8/5VwMY50oIFooY1UKXMWpfNCM6T/PoGqa5GD1g9xf9w==} + /read-package-json@6.0.4: + resolution: {integrity: sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: - glob: 8.1.0 + glob: 10.2.2 json-parse-even-better-errors: 3.0.0 normalize-package-data: 5.0.0 npm-normalize-package-bin: 3.0.0 @@ -24296,14 +24447,15 @@ packages: util-deprecate: 1.0.2 dev: true - /readable-stream@4.3.0: - resolution: {integrity: sha512-MuEnA0lbSi7JS8XM+WNJlWZkHAAdm7gETHdFK//Q/mChGyj2akEFtdLZh32jSdkWGbRwCW9pn6g3LWDdDeZnBQ==} + /readable-stream@4.4.2: + resolution: {integrity: sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: abort-controller: 3.0.0 buffer: 6.0.3 events: 3.3.0 process: 0.11.10 + string_decoder: 1.3.0 dev: true /readable-web-to-node-stream@3.0.2: @@ -24776,8 +24928,8 @@ packages: optionalDependencies: fsevents: 2.3.2 - /rollup@3.27.2: - resolution: {integrity: sha512-YGwmHf7h2oUHkVBT248x0yt6vZkYQ3/rvE5iQuVBh3WO8GcJ6BNeOkpoX1yMHIiBm18EMLjBPIoUDkhgnyxGOQ==} + /rollup@3.28.0: + resolution: {integrity: sha512-d7zhvo1OUY2SXSM6pfNjgD5+d0Nz87CUp4mt8l/GgVP3oBsPwzNvSzyu1me6BSG9JIgWNTVcafIXBIyM8yQ3yw==} engines: {node: '>=14.18.0', npm: '>=8.0.0'} hasBin: true optionalDependencies: @@ -25300,7 +25452,7 @@ packages: dependencies: call-bind: 1.0.2 get-intrinsic: 1.2.0 - object-inspect: 1.12.3 + object-inspect: 1.12.2 dev: true /siginfo@2.0.0: @@ -25681,12 +25833,12 @@ packages: minipass: 3.3.4 dev: true - /sswr@2.0.0(svelte@4.2.0): + /sswr@2.0.0(svelte@4.1.1): resolution: {integrity: sha512-mV0kkeBHcjcb0M5NqKtKVg/uTIYNlIIniyDfSGrSfxpEdM9C365jK0z55pl9K0xAkNTJi2OAOVFQpgMPUk+V0w==} peerDependencies: svelte: ^4.0.0 dependencies: - svelte: 4.2.0 + svelte: 4.1.1 swrev: 4.0.0 dev: true @@ -25915,7 +26067,7 @@ packages: /strip-literal@1.0.1: resolution: {integrity: sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q==} dependencies: - acorn: 8.10.0 + acorn: 8.8.2 dev: false /strip-outer@2.0.0: @@ -26095,8 +26247,8 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - /svelte@4.2.0: - resolution: {integrity: sha512-kVsdPjDbLrv74SmLSUzAsBGquMs4MPgWGkGLpH+PjOYnFOziAvENVzgJmyOCV2gntxE32aNm8/sqNKD6LbIpeQ==} + /svelte@4.1.1: + resolution: {integrity: sha512-Enick5fPFISLoVy0MFK45cG+YlQt6upw8skEK9zzTpJnH1DqEv8xOZwizCGSo3Q6HZ7KrZTM0J18poF7aQg5zw==} engines: {node: '>=16'} dependencies: '@ampproject/remapping': 2.2.1 @@ -26105,7 +26257,7 @@ packages: acorn: 8.10.0 aria-query: 5.3.0 axobject-query: 3.2.1 - code-red: 1.0.4 + code-red: 1.0.3 css-tree: 2.3.1 estree-walker: 3.0.3 is-reference: 3.0.1 @@ -26291,13 +26443,13 @@ packages: yallist: 4.0.0 dev: true - /tar@6.1.13: - resolution: {integrity: sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==} + /tar@6.1.15: + resolution: {integrity: sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==} engines: {node: '>=10'} dependencies: chownr: 2.0.0 fs-minipass: 2.1.0 - minipass: 4.2.8 + minipass: 5.0.0 minizlib: 2.1.2 mkdirp: 1.0.4 yallist: 4.0.0 @@ -26395,7 +26547,7 @@ packages: jest-worker: 27.5.1 schema-utils: 3.2.0 serialize-javascript: 6.0.1 - terser: 5.19.2 + terser: 5.18.0 webpack: 5.88.2(@swc/core@1.3.51)(esbuild@0.18.17) dev: true @@ -26421,7 +26573,7 @@ packages: jest-worker: 27.5.1 schema-utils: 3.2.0 serialize-javascript: 6.0.1 - terser: 5.19.2 + terser: 5.18.0 webpack: 5.75.0(@swc/core@1.3.51)(esbuild@0.19.2) dev: true @@ -26447,7 +26599,7 @@ packages: jest-worker: 27.5.1 schema-utils: 3.2.0 serialize-javascript: 6.0.1 - terser: 5.19.2 + terser: 5.18.0 webpack: 5.88.0(@swc/core@1.3.51)(esbuild@0.19.2) dev: true @@ -26457,7 +26609,18 @@ packages: hasBin: true dependencies: '@jridgewell/source-map': 0.3.3 - acorn: 8.10.0 + acorn: 8.8.2 + commander: 2.20.3 + source-map-support: 0.5.21 + dev: true + + /terser@5.18.0: + resolution: {integrity: sha512-pdL757Ig5a0I+owA42l6tIuEycRuM7FPY4n62h44mRLRfnOxJkkOHd6i89dOpwZlpF6JXBwaAHF6yWzFrt+QyA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + '@jridgewell/source-map': 0.3.3 + acorn: 8.8.2 commander: 2.20.3 source-map-support: 0.5.21 dev: true @@ -26603,8 +26766,8 @@ packages: dependencies: is-number: 7.0.0 - /tocbot@4.21.0: - resolution: {integrity: sha512-vXk8htr8mIl3hc2s2mDkaPTBfqmqZA2o0x7eXbxUibdrpEIPdpM0L9hH/RvEvlgSM+ZTgS34sGipk5+VrLJCLA==} + /tocbot@4.21.1: + resolution: {integrity: sha512-IfajhBTeg0HlMXu1f+VMbPef05QpDTsZ9X2Yn1+8npdaXsXg/+wrm9Ze1WG5OS1UDC3qJ5EQN/XOZ3gfXjPFCw==} dev: true /toggle-selection@1.0.6: @@ -26831,7 +26994,7 @@ packages: dependencies: '@types/json5': 0.0.29 json5: 1.0.1 - minimist: 1.2.8 + minimist: 1.2.7 strip-bom: 3.0.0 dev: true @@ -26840,7 +27003,7 @@ packages: engines: {node: '>=6'} dependencies: json5: 2.2.3 - minimist: 1.2.8 + minimist: 1.2.7 strip-bom: 3.0.0 dev: true @@ -26961,8 +27124,8 @@ packages: resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==} dev: true - /typanion@3.14.0: - resolution: {integrity: sha512-ZW/lVMRabETuYCd9O9ZvMhAh8GslSqaUjxmK/JLPCh6l73CvLBiuXswj/+7LdnWOgYsQ130FqLzFz5aGT4I3Ug==} + /typanion@3.12.1: + resolution: {integrity: sha512-3SJF/czpzqq6G3lprGFLa6ps12yb1uQ1EmitNnep2fDMNh1aO/Zbq9sWY+3lem0zYb2oHJnQWyabTGUZ+L1ScQ==} dev: true /type-check@0.3.2: @@ -27648,7 +27811,7 @@ packages: unix-crypt-td-js: 1.1.4 dev: true - /verdaccio@5.15.4(typanion@3.14.0): + /verdaccio@5.15.4(typanion@3.12.1): resolution: {integrity: sha512-yYMqpEQCv/BfYW5K/Nq57dbx68ICP1GfK7RJ0A3SlhKgl6idT8x4cJyLjH7C4k1Tln3LIQk1/X6ZtSl7xhzwOg==} engines: {node: '>=12', npm: '>=6'} hasBin: true @@ -27661,7 +27824,7 @@ packages: JSONStream: 1.3.5 async: 3.2.4 body-parser: 1.20.0 - clipanion: 3.1.0(typanion@3.14.0) + clipanion: 3.1.0(typanion@3.12.1) compression: 1.7.4 cookies: 0.8.0 cors: 2.8.5 @@ -27813,7 +27976,7 @@ packages: '@types/node': 18.16.9 esbuild: 0.17.19 less: 4.1.3 - postcss: 8.4.27 + postcss: 8.4.24 rollup: 3.21.0 sass: 1.55.0 stylus: 0.59.0 @@ -27850,10 +28013,10 @@ packages: optional: true dependencies: '@types/node': 18.16.9 - esbuild: 0.18.20 + esbuild: 0.18.17 less: 4.1.3 postcss: 8.4.27 - rollup: 3.27.2 + rollup: 3.28.0 sass: 1.64.1 stylus: 0.59.0 terser: 5.19.2 @@ -28894,130 +29057,3 @@ packages: /zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} dev: true - - registry.npmjs.org/@storybook/channels@7.1.1: - resolution: {integrity: sha512-uhkZFtLIeRnbBhyLlvQAZQmsRbftX/YMGQL+9WRzICrCkwl4xfZPAvMxEgCj1iJzNFcaX5ma9XzHb7q/i+wUCw==, registry: https://registry.yarnpkg.com/, tarball: https://registry.npmjs.org/@storybook/channels/-/channels-7.1.1.tgz} - name: '@storybook/channels' - version: 7.1.1 - dependencies: - '@storybook/client-logger': registry.npmjs.org/@storybook/client-logger@7.1.1 - '@storybook/core-events': registry.npmjs.org/@storybook/core-events@7.1.1 - '@storybook/global': registry.npmjs.org/@storybook/global@5.0.0 - qs: registry.npmjs.org/qs@6.11.0 - telejson: registry.npmjs.org/telejson@7.1.0 - tiny-invariant: registry.npmjs.org/tiny-invariant@1.3.1 - dev: true - - registry.npmjs.org/@storybook/client-logger@7.1.1: - resolution: {integrity: sha512-R0bdVjzJ5CwLNAG3XMyMZ0e9XDteBkFkTTIZJ9m+WMh/+oa2PInCpXDxoYb180UI6abrqh1jEaAsrHMC1pTKnA==, registry: https://registry.yarnpkg.com/, tarball: https://registry.npmjs.org/@storybook/client-logger/-/client-logger-7.1.1.tgz} - name: '@storybook/client-logger' - version: 7.1.1 - dependencies: - '@storybook/global': registry.npmjs.org/@storybook/global@5.0.0 - dev: true - - registry.npmjs.org/@storybook/core-events@7.1.1: - resolution: {integrity: sha512-P5iI4zvCJo85de/sghglEHFK/GGkWAQQKzRFrz9kbVBX5LNaosfD7IYHIz/6ZWNPzxWR+RBOKcrRUfcArL4Njg==, registry: https://registry.yarnpkg.com/, tarball: https://registry.npmjs.org/@storybook/core-events/-/core-events-7.1.1.tgz} - name: '@storybook/core-events' - version: 7.1.1 - dev: true - - registry.npmjs.org/@storybook/global@5.0.0: - resolution: {integrity: sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==, registry: https://registry.yarnpkg.com/, tarball: https://registry.npmjs.org/@storybook/global/-/global-5.0.0.tgz} - name: '@storybook/global' - version: 5.0.0 - dev: true - - registry.npmjs.org/call-bind@1.0.2: - resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==, registry: https://registry.yarnpkg.com/, tarball: https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz} - name: call-bind - version: 1.0.2 - dependencies: - function-bind: registry.npmjs.org/function-bind@1.1.1 - get-intrinsic: registry.npmjs.org/get-intrinsic@1.2.0 - dev: true - - registry.npmjs.org/function-bind@1.1.1: - resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==, registry: https://registry.yarnpkg.com/, tarball: https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz} - name: function-bind - version: 1.1.1 - dev: true - - registry.npmjs.org/get-intrinsic@1.2.0: - resolution: {integrity: sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==, registry: https://registry.yarnpkg.com/, tarball: https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz} - name: get-intrinsic - version: 1.2.0 - dependencies: - function-bind: registry.npmjs.org/function-bind@1.1.1 - has: registry.npmjs.org/has@1.0.3 - has-symbols: registry.npmjs.org/has-symbols@1.0.3 - dev: true - - registry.npmjs.org/has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==, registry: https://registry.yarnpkg.com/, tarball: https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz} - name: has-symbols - version: 1.0.3 - engines: {node: '>= 0.4'} - dev: true - - registry.npmjs.org/has@1.0.3: - resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==, registry: https://registry.yarnpkg.com/, tarball: https://registry.npmjs.org/has/-/has-1.0.3.tgz} - name: has - version: 1.0.3 - engines: {node: '>= 0.4.0'} - dependencies: - function-bind: registry.npmjs.org/function-bind@1.1.1 - dev: true - - registry.npmjs.org/map-or-similar@1.5.0: - resolution: {integrity: sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==, registry: https://registry.yarnpkg.com/, tarball: https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz} - name: map-or-similar - version: 1.5.0 - dev: true - - registry.npmjs.org/memoizerific@1.11.3: - resolution: {integrity: sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==, registry: https://registry.yarnpkg.com/, tarball: https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz} - name: memoizerific - version: 1.11.3 - dependencies: - map-or-similar: registry.npmjs.org/map-or-similar@1.5.0 - dev: true - - registry.npmjs.org/object-inspect@1.12.3: - resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==, registry: https://registry.yarnpkg.com/, tarball: https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz} - name: object-inspect - version: 1.12.3 - dev: true - - registry.npmjs.org/qs@6.11.0: - resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==, registry: https://registry.yarnpkg.com/, tarball: https://registry.npmjs.org/qs/-/qs-6.11.0.tgz} - name: qs - version: 6.11.0 - engines: {node: '>=0.6'} - dependencies: - side-channel: registry.npmjs.org/side-channel@1.0.4 - dev: true - - registry.npmjs.org/side-channel@1.0.4: - resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==, registry: https://registry.yarnpkg.com/, tarball: https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz} - name: side-channel - version: 1.0.4 - dependencies: - call-bind: registry.npmjs.org/call-bind@1.0.2 - get-intrinsic: registry.npmjs.org/get-intrinsic@1.2.0 - object-inspect: registry.npmjs.org/object-inspect@1.12.3 - dev: true - - registry.npmjs.org/telejson@7.1.0: - resolution: {integrity: sha512-jFJO4P5gPebZAERPkJsqMAQ0IMA1Hi0AoSfxpnUaV6j6R2SZqlpkbS20U6dEUtA3RUYt2Ak/mTlkQzHH9Rv/hA==, registry: https://registry.yarnpkg.com/, tarball: https://registry.npmjs.org/telejson/-/telejson-7.1.0.tgz} - name: telejson - version: 7.1.0 - dependencies: - memoizerific: registry.npmjs.org/memoizerific@1.11.3 - dev: true - - registry.npmjs.org/tiny-invariant@1.3.1: - resolution: {integrity: sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==, registry: https://registry.yarnpkg.com/, tarball: https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz} - name: tiny-invariant - version: 1.3.1 - dev: true From cd7b7670d5a34ac3a8f2ca78d19da602282bd264 Mon Sep 17 00:00:00 2001 From: James Henry Date: Tue, 12 Sep 2023 16:44:04 +0400 Subject: [PATCH 02/13] chore(core): anonymize localhost port within snapshot --- e2e/release/src/__snapshots__/release.test.ts.snap | 6 +++--- e2e/release/src/release.test.ts | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/e2e/release/src/__snapshots__/release.test.ts.snap b/e2e/release/src/__snapshots__/release.test.ts.snap index f7cf7c4328aed..3d22bb2939510 100644 --- a/e2e/release/src/__snapshots__/release.test.ts.snap +++ b/e2e/release/src/__snapshots__/release.test.ts.snap @@ -27,7 +27,7 @@ exports[`nx release should version and publish multiple related npm packages wit {project-name}: integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX {project-name}: total files: 3 {project-name}: -{project-name}: Published to http://localhost:4875 with tag "latest" +{project-name}: Published to http://localhost:{port-number} with tag "latest" > nx run {project-name}:release-publish @@ -46,7 +46,7 @@ exports[`nx release should version and publish multiple related npm packages wit {project-name}: integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX {project-name}: total files: 3 {project-name}: -{project-name}: Published to http://localhost:4875 with tag "latest" +{project-name}: Published to http://localhost:{port-number} with tag "latest" > nx run {project-name}:release-publish @@ -65,7 +65,7 @@ exports[`nx release should version and publish multiple related npm packages wit {project-name}: integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX {project-name}: total files: 3 {project-name}: -{project-name}: Published to http://localhost:4875 with tag "latest" +{project-name}: Published to http://localhost:{port-number} with tag "latest" diff --git a/e2e/release/src/release.test.ts b/e2e/release/src/release.test.ts index 097e0b9e473b7..fd21ae84ae7cc 100644 --- a/e2e/release/src/release.test.ts +++ b/e2e/release/src/release.test.ts @@ -22,6 +22,8 @@ expect.addSnapshotSerializer({ .replaceAll(/\d*B package\.json/g, 'XXXB package.json') .replaceAll(/size:\s*\d*\s?B/g, 'size: XXXB') .replaceAll(/\d*\.\d*\s?kB/g, 'XXX.XXX kb') + // Anonymize localhost port because it can be different between local and CI + .replaceAll(/http:\/\/localhost:\d+/g, 'http://localhost:{port-number}') // We trim each line to reduce the chances of snapshot flakiness .split('\n') .map((r) => r.trim()) From 81045dcd6da681225fc2f788486a91135f782df7 Mon Sep 17 00:00:00 2001 From: James Henry Date: Tue, 12 Sep 2023 19:30:11 +0400 Subject: [PATCH 03/13] fix(js): only attempt to version projects with package.json files --- .../release-version/release-version.spec.ts | 21 +++++++++++++++++++ .../release-version/release-version.ts | 8 +++++++ .../resolve-local-package-dependencies.ts | 9 ++++---- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/packages/js/src/generators/release-version/release-version.spec.ts b/packages/js/src/generators/release-version/release-version.spec.ts index 04f6f869dd805..e26bb82f1b7c3 100644 --- a/packages/js/src/generators/release-version/release-version.spec.ts +++ b/packages/js/src/generators/release-version/release-version.spec.ts @@ -124,4 +124,25 @@ describe('release-version', () => { } `); }); + + describe('not all given projects have package.json files', () => { + beforeEach(() => { + tree.delete('libs/my-lib/package.json'); + }); + + it(`should error with guidance when not all of the given projects are appropriate for JS versioning`, async () => { + await expect( + releaseVersionGenerator(tree, { + projects: Object.values(projectGraph.nodes), // version all projects + projectGraph, + specifier: 'major', + currentVersionResolver: 'disk', + }) + ).rejects.toThrowErrorMatchingInlineSnapshot(` + "The project "my-lib" does not have a package.json available at libs/my-lib/package.json. + + To fix this you will either need to add a package.json file at that location, or configure "release" within your nx.json to exclude "my-lib" from the current release group, or amend the packageRoot configuration to point to where the package.json should be." + `); + }); + }); }); diff --git a/packages/js/src/generators/release-version/release-version.ts b/packages/js/src/generators/release-version/release-version.ts index 9e6aa546c4ccf..5ff0d2c0d4dea 100644 --- a/packages/js/src/generators/release-version/release-version.ts +++ b/packages/js/src/generators/release-version/release-version.ts @@ -60,6 +60,14 @@ export async function releaseVersionGenerator( )}` ); + if (!tree.read(packageJsonPath)) { + throw new Error( + `The project "${projectName}" does not have a package.json available at ${workspaceRelativePackageJsonPath}. + +To fix this you will either need to add a package.json file at that location, or configure "release" within your nx.json to exclude "${projectName}" from the current release group, or amend the packageRoot configuration to point to where the package.json should be.` + ); + } + const projectPackageJson = readJson(tree, packageJsonPath); log( `🔍 Reading data for package "${projectPackageJson.name}" from ${workspaceRelativePackageJsonPath}` diff --git a/packages/js/src/generators/release-version/utils/resolve-local-package-dependencies.ts b/packages/js/src/generators/release-version/utils/resolve-local-package-dependencies.ts index ac2997d0d65d7..ca83acea7be0d 100644 --- a/packages/js/src/generators/release-version/utils/resolve-local-package-dependencies.ts +++ b/packages/js/src/generators/release-version/utils/resolve-local-package-dependencies.ts @@ -36,10 +36,11 @@ export function resolveLocalPackageDependencies( if (!packageRoot) { continue; } - const packageJson = readJson( - tree, - joinPathFragments(packageRoot, 'package.json') - ) as PackageJson; + const packageJsonPath = joinPathFragments(packageRoot, 'package.json'); + if (!tree.exists(packageJsonPath)) { + continue; + } + const packageJson = readJson(tree, packageJsonPath) as PackageJson; const pkg = new Package(packageJson, workspaceRoot, packageRoot); projectNodeToPackageMap.set(projectNode, pkg); } From 8eaf70538b91b2e5d6413d635c260274a68b0eff Mon Sep 17 00:00:00 2001 From: James Henry Date: Tue, 12 Sep 2023 22:11:48 +0400 Subject: [PATCH 04/13] chore(core): interpolate registry url in snapshot --- .../src/__snapshots__/release.test.ts.snap | 76 ------------------ e2e/release/src/release.test.ts | 80 ++++++++++++++++++- 2 files changed, 77 insertions(+), 79 deletions(-) delete mode 100644 e2e/release/src/__snapshots__/release.test.ts.snap diff --git a/e2e/release/src/__snapshots__/release.test.ts.snap b/e2e/release/src/__snapshots__/release.test.ts.snap deleted file mode 100644 index 3d22bb2939510..0000000000000 --- a/e2e/release/src/__snapshots__/release.test.ts.snap +++ /dev/null @@ -1,76 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`nx release should version and publish multiple related npm packages with zero config 1`] = ` - -> NX Running target release-publish for 3 projects: - -- {project-name} -- {project-name} -- {project-name} - - - -> nx run {project-name}:release-publish - -{project-name}: 📦 @proj/{project-name}@999.9.9 -{project-name}: === Tarball Contents === -{project-name}: XXB index.js -{project-name}: XXXB package.json -{project-name}: XXB project.json -{project-name}: === Tarball Details === -{project-name}: name: @proj/{project-name} -{project-name}: version: 999.9.9 -{project-name}: filename: proj-{project-name}-999.9.9.tgz -{project-name}: package size: XXXB -{project-name}: unpacked size: XXXB -{project-name}: shasum: {SHASUM} -{project-name}: integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -{project-name}: total files: 3 -{project-name}: -{project-name}: Published to http://localhost:{port-number} with tag "latest" - -> nx run {project-name}:release-publish - -{project-name}: 📦 @proj/{project-name}@999.9.9 -{project-name}: === Tarball Contents === -{project-name}: XXB index.js -{project-name}: XXXB package.json -{project-name}: XXB project.json -{project-name}: === Tarball Details === -{project-name}: name: @proj/{project-name} -{project-name}: version: 999.9.9 -{project-name}: filename: proj-{project-name}-999.9.9.tgz -{project-name}: package size: XXXB -{project-name}: unpacked size: XXXB -{project-name}: shasum: {SHASUM} -{project-name}: integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -{project-name}: total files: 3 -{project-name}: -{project-name}: Published to http://localhost:{port-number} with tag "latest" - -> nx run {project-name}:release-publish - -{project-name}: 📦 @proj/{project-name}@999.9.9 -{project-name}: === Tarball Contents === -{project-name}: XXB index.js -{project-name}: XXXB package.json -{project-name}: XXB project.json -{project-name}: === Tarball Details === -{project-name}: name: @proj/{project-name} -{project-name}: version: 999.9.9 -{project-name}: filename: proj-{project-name}-999.9.9.tgz -{project-name}: package size: XXXB -{project-name}: unpacked size: XXXB -{project-name}: shasum: {SHASUM} -{project-name}: integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -{project-name}: total files: 3 -{project-name}: -{project-name}: Published to http://localhost:{port-number} with tag "latest" - - - -> NX Successfully ran target release-publish for 3 projects - - - -`; diff --git a/e2e/release/src/release.test.ts b/e2e/release/src/release.test.ts index fd21ae84ae7cc..6d52f5c1e3c55 100644 --- a/e2e/release/src/release.test.ts +++ b/e2e/release/src/release.test.ts @@ -5,6 +5,7 @@ import { uniq, updateJson, } from '@nx/e2e/utils'; +import { execSync } from 'child_process'; expect.addSnapshotSerializer({ serialize(str: string) { @@ -22,8 +23,6 @@ expect.addSnapshotSerializer({ .replaceAll(/\d*B package\.json/g, 'XXXB package.json') .replaceAll(/size:\s*\d*\s?B/g, 'size: XXXB') .replaceAll(/\d*\.\d*\s?kB/g, 'XXX.XXX kb') - // Anonymize localhost port because it can be different between local and CI - .replaceAll(/http:\/\/localhost:\d+/g, 'http://localhost:{port-number}') // We trim each line to reduce the chances of snapshot flakiness .split('\n') .map((r) => r.trim()) @@ -96,8 +95,83 @@ describe('nx release', () => { ).length ).toEqual(1); + const registryUrl = execSync('npm config get registry').toString().trim(); + // Thanks to the custom serializer above, the publish output should be deterministic const publishOutput = runCLI(`release publish`); - expect(publishOutput).toMatchSnapshot(); + expect(publishOutput).toMatchInlineSnapshot(` + + > NX Running target release-publish for 3 projects: + + - {project-name} + - {project-name} + - {project-name} + + + + > nx run {project-name}:release-publish + + {project-name}: 📦 @proj/{project-name}@999.9.9 + {project-name}: === Tarball Contents === + {project-name}: XXB index.js + {project-name}: XXXB package.json + {project-name}: XXB project.json + {project-name}: === Tarball Details === + {project-name}: name: @proj/{project-name} + {project-name}: version: 999.9.9 + {project-name}: filename: proj-{project-name}-999.9.9.tgz + {project-name}: package size: XXXB + {project-name}: unpacked size: XXXB + {project-name}: shasum: {SHASUM} + {project-name}: integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + {project-name}: total files: 3 + {project-name}: + {project-name}: Published to ${registryUrl} with tag "latest" + + > nx run {project-name}:release-publish + + {project-name}: 📦 @proj/{project-name}@999.9.9 + {project-name}: === Tarball Contents === + {project-name}: XXB index.js + {project-name}: XXXB package.json + {project-name}: XXB project.json + {project-name}: === Tarball Details === + {project-name}: name: @proj/{project-name} + {project-name}: version: 999.9.9 + {project-name}: filename: proj-{project-name}-999.9.9.tgz + {project-name}: package size: XXXB + {project-name}: unpacked size: XXXB + {project-name}: shasum: {SHASUM} + {project-name}: integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + {project-name}: total files: 3 + {project-name}: + {project-name}: Published to ${registryUrl} with tag "latest" + + > nx run {project-name}:release-publish + + {project-name}: 📦 @proj/{project-name}@999.9.9 + {project-name}: === Tarball Contents === + {project-name}: XXB index.js + {project-name}: XXXB package.json + {project-name}: XXB project.json + {project-name}: === Tarball Details === + {project-name}: name: @proj/{project-name} + {project-name}: version: 999.9.9 + {project-name}: filename: proj-{project-name}-999.9.9.tgz + {project-name}: package size: XXXB + {project-name}: unpacked size: XXXB + {project-name}: shasum: {SHASUM} + {project-name}: integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + {project-name}: total files: 3 + {project-name}: + {project-name}: Published to ${registryUrl} with tag "latest" + + + + > NX Successfully ran target release-publish for 3 projects + + + + `); }, 500000); }); From 4361d9cb70d694d5cd267d96602a88f2f5f7ad16 Mon Sep 17 00:00:00 2001 From: James Henry Date: Wed, 13 Sep 2023 22:08:06 +0400 Subject: [PATCH 05/13] chore(core): multiple PR feedback items --- e2e/release/src/release.test.ts | 222 +++++++++++++++++- .../release-publish/release-publish.impl.ts | 13 +- .../release-version/release-version.ts | 18 +- .../src/command-line/release/config/config.ts | 2 +- .../config/create-release-groups.spec.ts | 2 +- .../nx/src/command-line/release/release.ts | 1 - .../nx/src/command-line/release/version.ts | 3 + .../nx/src/generators/utils/deprecated.ts | 3 +- 8 files changed, 240 insertions(+), 24 deletions(-) delete mode 100644 packages/nx/src/command-line/release/release.ts diff --git a/e2e/release/src/release.test.ts b/e2e/release/src/release.test.ts index 6d52f5c1e3c55..e966a19d014cb 100644 --- a/e2e/release/src/release.test.ts +++ b/e2e/release/src/release.test.ts @@ -1,7 +1,10 @@ +import { NxJsonConfiguration } from '@nx/devkit'; import { cleanupProject, + killProcessAndPorts, newProject, runCLI, + runCommandUntil, uniq, updateJson, } from '@nx/e2e/utils'; @@ -40,7 +43,9 @@ describe('nx release', () => { let pkg3: string; beforeAll(() => { - newProject(); + newProject({ + unsetProjectNameAndRootFormat: false, + }); pkg1 = uniq('my-pkg-1'); runCLI(`generate @nx/workspace:npm-package ${pkg1}`); @@ -52,7 +57,7 @@ describe('nx release', () => { runCLI(`generate @nx/workspace:npm-package ${pkg3}`); // Update pkg2 to depend on pkg1 - updateJson(`libs/${pkg2}/package.json`, (json) => { + updateJson(`${pkg2}/package.json`, (json) => { json.dependencies ??= {}; json.dependencies[`@proj/${pkg1}`] = '0.0.0'; return json; @@ -74,17 +79,17 @@ describe('nx release', () => { ).toEqual(3); expect( versionOutput.match( - /Reading data for package "@proj\/my-pkg-\d*" from libs\/my-pkg-\d*\/package.json/g + /Reading data for package "@proj\/my-pkg-\d*" from my-pkg-\d*\/package.json/g ).length ).toEqual(3); expect( versionOutput.match( - /Resolved the current version as 0.0.0 from libs\/my-pkg-\d*\/package.json/g + /Resolved the current version as 0.0.0 from my-pkg-\d*\/package.json/g ).length ).toEqual(3); expect( versionOutput.match( - /New version 999.9.9 written to libs\/my-pkg-\d*\/package.json/g + /New version 999.9.9 written to my-pkg-\d*\/package.json/g ).length ).toEqual(3); @@ -95,7 +100,10 @@ describe('nx release', () => { ).length ).toEqual(1); - const registryUrl = execSync('npm config get registry').toString().trim(); + // This is the verdaccio instance that the e2e tests themselves are working from + const e2eRegistryUrl = execSync('npm config get registry') + .toString() + .trim(); // Thanks to the custom serializer above, the publish output should be deterministic const publishOutput = runCLI(`release publish`); @@ -126,7 +134,7 @@ describe('nx release', () => { {project-name}: integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX {project-name}: total files: 3 {project-name}: - {project-name}: Published to ${registryUrl} with tag "latest" + {project-name}: Published to ${e2eRegistryUrl} with tag "latest" > nx run {project-name}:release-publish @@ -145,7 +153,7 @@ describe('nx release', () => { {project-name}: integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX {project-name}: total files: 3 {project-name}: - {project-name}: Published to ${registryUrl} with tag "latest" + {project-name}: Published to ${e2eRegistryUrl} with tag "latest" > nx run {project-name}:release-publish @@ -164,7 +172,178 @@ describe('nx release', () => { {project-name}: integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX {project-name}: total files: 3 {project-name}: - {project-name}: Published to ${registryUrl} with tag "latest" + {project-name}: Published to ${e2eRegistryUrl} with tag "latest" + + + + > NX Successfully ran target release-publish for 3 projects + + + + `); + + expect( + execSync(`npm view @proj/${pkg1} version`).toString().trim() + ).toEqual('999.9.9'); + expect( + execSync(`npm view @proj/${pkg2} version`).toString().trim() + ).toEqual('999.9.9'); + expect( + execSync(`npm view @proj/${pkg3} version`).toString().trim() + ).toEqual('999.9.9'); + + // Add custom nx release config to control version resolution + updateJson('nx.json', (nxJson) => { + nxJson.release = { + groups: { + default: { + // @proj/source will be added as a project by the verdaccio setup, but we aren't versioning or publishing it, so we exclude it here + projects: ['*', '!@proj/source'], + version: { + generator: '@nx/js:release-version', + generatorOptions: { + // Resolve the latest version from the custom registry instance, therefore finding the previously published versions + currentVersionResolver: 'registry', + currentVersionResolverMetadata: { + registry: e2eRegistryUrl, + tag: 'latest', + }, + }, + }, + }, + }, + }; + return nxJson; + }); + + // Run additional custom verdaccio instance to publish the packages to + runCLI(`generate setup-verdaccio`); + + const verdaccioPort = 7190; + const customRegistryUrl = `http://localhost:${verdaccioPort}`; + const process = await runCommandUntil( + `local-registry @proj/source --port=${verdaccioPort}`, + (output) => output.includes(`warn --- http address`) + ); + + const versionOutput2 = runCLI(`release version major`); // version using semver keyword this time + + expect( + versionOutput2.match(/Running release version for project: my-pkg-\d*/g) + .length + ).toEqual(3); + expect( + versionOutput2.match( + /Reading data for package "@proj\/my-pkg-\d*" from my-pkg-\d*\/package.json/g + ).length + ).toEqual(3); + + // It should resolve the current version from the registry once... + expect( + versionOutput2.match( + new RegExp( + `Resolved the current version as 999.9.9 for tag "latest" from registry ${e2eRegistryUrl}`, + 'g' + ) + ).length + ).toEqual(1); + // ...and then reuse it twice + expect( + versionOutput2.match( + new RegExp( + `Using the current version 999.9.9 already resolved from the registry ${e2eRegistryUrl}`, + 'g' + ) + ).length + ).toEqual(2); + + expect( + versionOutput2.match( + /New version 1000.0.0 written to my-pkg-\d*\/package.json/g + ).length + ).toEqual(3); + + // Only one dependency relationship exists, so this log should only match once + expect( + versionOutput2.match( + /Applying new version 1000.0.0 to 1 package which depends on my-pkg-\d*/g + ).length + ).toEqual(1); + + // publish to custom registry (not e2e registry), and a custom dist tag of "next" + const publishOutput2 = runCLI( + `release publish --registry=${customRegistryUrl} --tag=next` + ); + expect(publishOutput2).toMatchInlineSnapshot(` + + > NX Running target release-publish for 3 projects: + + - {project-name} + - {project-name} + - {project-name} + + With additional flags: + --registry=http://localhost:7190 + --tag=next + + + + > nx run {project-name}:release-publish + + {project-name}: 📦 @proj/{project-name}@1000.0.0 + {project-name}: === Tarball Contents === + {project-name}: XXB index.js + {project-name}: XXXB package.json + {project-name}: XXB project.json + {project-name}: === Tarball Details === + {project-name}: name: @proj/{project-name} + {project-name}: version: 1000.0.0 + {project-name}: filename: proj-{project-name}-1000.0.0.tgz + {project-name}: package size: XXXB + {project-name}: unpacked size: XXXB + {project-name}: shasum: {SHASUM} + {project-name}: integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + {project-name}: total files: 3 + {project-name}: + {project-name}: Published to ${customRegistryUrl} with tag "next" + + > nx run {project-name}:release-publish + + {project-name}: 📦 @proj/{project-name}@1000.0.0 + {project-name}: === Tarball Contents === + {project-name}: XXB index.js + {project-name}: XXXB package.json + {project-name}: XXB project.json + {project-name}: === Tarball Details === + {project-name}: name: @proj/{project-name} + {project-name}: version: 1000.0.0 + {project-name}: filename: proj-{project-name}-1000.0.0.tgz + {project-name}: package size: XXXB + {project-name}: unpacked size: XXXB + {project-name}: shasum: {SHASUM} + {project-name}: integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + {project-name}: total files: 3 + {project-name}: + {project-name}: Published to ${customRegistryUrl} with tag "next" + + > nx run {project-name}:release-publish + + {project-name}: 📦 @proj/{project-name}@1000.0.0 + {project-name}: === Tarball Contents === + {project-name}: XXB index.js + {project-name}: XXXB package.json + {project-name}: XXB project.json + {project-name}: === Tarball Details === + {project-name}: name: @proj/{project-name} + {project-name}: version: 1000.0.0 + {project-name}: filename: proj-{project-name}-1000.0.0.tgz + {project-name}: package size: XXXB + {project-name}: unpacked size: XXXB + {project-name}: shasum: {SHASUM} + {project-name}: integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + {project-name}: total files: 3 + {project-name}: + {project-name}: Published to ${customRegistryUrl} with tag "next" @@ -173,5 +352,30 @@ describe('nx release', () => { `); + + expect( + execSync( + `npm view @proj/${pkg1}@next version --registry=${customRegistryUrl}` + ) + .toString() + .trim() + ).toEqual('1000.0.0'); + expect( + execSync( + `npm view @proj/${pkg2}@next version --registry=${customRegistryUrl}` + ) + .toString() + .trim() + ).toEqual('1000.0.0'); + expect( + execSync( + `npm view @proj/${pkg3}@next version --registry=${customRegistryUrl}` + ) + .toString() + .trim() + ).toEqual('1000.0.0'); + + // port and process cleanup + await killProcessAndPorts(process.pid, verdaccioPort); }, 500000); }); diff --git a/packages/js/src/executors/release-publish/release-publish.impl.ts b/packages/js/src/executors/release-publish/release-publish.impl.ts index 27f2f3f1d55b2..2e0eb2c57a94c 100644 --- a/packages/js/src/executors/release-publish/release-publish.impl.ts +++ b/packages/js/src/executors/release-publish/release-publish.impl.ts @@ -54,7 +54,10 @@ export default async function runExecutor( }); const stdoutData = JSON.parse(output.toString()); - logTar(stdoutData); + + // If npm workspaces are in use, the publish output will nest the data under the package name, so we normalize it first + const normalizedStdoutData = stdoutData[context.projectName!] ?? stdoutData; + logTar(normalizedStdoutData); console.log(`Published to ${registry} with tag "${tag}"`); @@ -70,7 +73,13 @@ export default async function runExecutor( const currentVersion = projectPackageJson.version; const stdoutData = JSON.parse(err.stdout?.toString() || '{}'); - if (stdoutData.error?.code === 'EPUBLISHCONFLICT') { + if ( + stdoutData.error?.code === 'EPUBLISHCONFLICT' || + (stdoutData.error?.code === 'E403' && + stdoutData.error?.body?.error?.includes( + 'You cannot publish over the previously published versions' + )) + ) { // If package and project name match, make it terser let packageTxt = name === context.projectName diff --git a/packages/js/src/generators/release-version/release-version.ts b/packages/js/src/generators/release-version/release-version.ts index 5ff0d2c0d4dea..fe2a185a7b344 100644 --- a/packages/js/src/generators/release-version/release-version.ts +++ b/packages/js/src/generators/release-version/release-version.ts @@ -9,7 +9,7 @@ import { } from '@nx/devkit'; import * as chalk from 'chalk'; import { exec } from 'child_process'; -import { deriveNewSemverVersion } from 'nx/src/command-line/release/release'; +import { deriveNewSemverVersion } from 'nx/src/command-line/release/version'; import { interpolate } from 'nx/src/tasks-runner/utils'; import * as ora from 'ora'; import { relative } from 'path'; @@ -54,13 +54,7 @@ export async function releaseVersionGenerator( console.log(color.instance.bold(projectName) + ' ' + msg); }; - output.logSingleLine( - `Running release version for project: ${color.instance.bold( - project.name - )}` - ); - - if (!tree.read(packageJsonPath)) { + if (!tree.exists(packageJsonPath)) { throw new Error( `The project "${projectName}" does not have a package.json available at ${workspaceRelativePackageJsonPath}. @@ -68,6 +62,12 @@ To fix this you will either need to add a package.json file at that location, or ); } + output.logSingleLine( + `Running release version for project: ${color.instance.bold( + project.name + )}` + ); + const projectPackageJson = readJson(tree, packageJsonPath); log( `🔍 Reading data for package "${projectPackageJson.name}" from ${workspaceRelativePackageJsonPath}` @@ -147,7 +147,7 @@ To fix this you will either need to add a package.json file at that location, or ); writeJson(tree, packageJsonPath, { - ...readJson(tree, packageJsonPath), + ...projectPackageJson, version: newVersion, }); diff --git a/packages/nx/src/command-line/release/config/config.ts b/packages/nx/src/command-line/release/config/config.ts index ad79bede01b2b..2bd7474c7c463 100644 --- a/packages/nx/src/command-line/release/config/config.ts +++ b/packages/nx/src/command-line/release/config/config.ts @@ -1,4 +1,4 @@ -import { NxJsonConfiguration } from '../../../devkit-exports'; +import { NxJsonConfiguration } from '../../../config/nx-json'; // Apply default configuration to any optional user configuration export function createNxReleaseConfig( diff --git a/packages/nx/src/command-line/release/config/create-release-groups.spec.ts b/packages/nx/src/command-line/release/config/create-release-groups.spec.ts index b02d303e83123..d59f9c4221f8d 100644 --- a/packages/nx/src/command-line/release/config/create-release-groups.spec.ts +++ b/packages/nx/src/command-line/release/config/create-release-groups.spec.ts @@ -1,4 +1,4 @@ -import { ProjectGraph } from '../../../devkit-exports'; +import { ProjectGraph } from '../../../config/project-graph'; import { createReleaseGroups } from './create-release-groups'; describe('create-release-groups', () => { diff --git a/packages/nx/src/command-line/release/release.ts b/packages/nx/src/command-line/release/release.ts deleted file mode 100644 index d3e1d9e167b5c..0000000000000 --- a/packages/nx/src/command-line/release/release.ts +++ /dev/null @@ -1 +0,0 @@ -export { deriveNewSemverVersion } from './utils/semver'; diff --git a/packages/nx/src/command-line/release/version.ts b/packages/nx/src/command-line/release/version.ts index 75b7741fe722b..3f3f3789f4602 100644 --- a/packages/nx/src/command-line/release/version.ts +++ b/packages/nx/src/command-line/release/version.ts @@ -40,6 +40,9 @@ import { } from './config/create-release-groups'; import { printDiff } from './utils/print-diff'; +// Reexport for use in plugin release-version generator implementations +export { deriveNewSemverVersion } from './utils/semver'; + export interface ReleaseVersionGeneratorSchema { // The projects being versioned in the current execution projects: ProjectGraphProjectNode[]; diff --git a/packages/nx/src/generators/utils/deprecated.ts b/packages/nx/src/generators/utils/deprecated.ts index ed0afde2841c1..a49cd05057ed5 100644 --- a/packages/nx/src/generators/utils/deprecated.ts +++ b/packages/nx/src/generators/utils/deprecated.ts @@ -39,6 +39,7 @@ export function updateWorkspaceConfiguration( affected, extends: ext, installation, + release, } = workspaceConfig; const nxJson: Required = { @@ -56,7 +57,7 @@ export function updateWorkspaceConfiguration( defaultProject, extends: ext, installation, - release: {}, + release, }; updateNxJson(tree, nxJson); From 1e999fdeee84fa8ec7a2c543a10a31b1a6ed48e3 Mon Sep 17 00:00:00 2001 From: FrozenPandaz Date: Wed, 13 Sep 2023 20:04:52 -0400 Subject: [PATCH 06/13] fix(core): fix release arguments handling --- docs/generated/cli/release.md | 6 ++ .../packages/nx/documents/release.md | 6 ++ .../src/command-line/exec/command-object.ts | 2 +- .../command-line/release/command-object.ts | 11 +++- .../nx/src/command-line/release/publish.ts | 61 +++++++----------- .../yargs-utils/shared-options.ts | 14 +++-- packages/nx/src/utils/command-line-utils.ts | 63 ++++++------------- 7 files changed, 72 insertions(+), 91 deletions(-) diff --git a/docs/generated/cli/release.md b/docs/generated/cli/release.md index 3c242248c8b0a..77a6b410458b4 100644 --- a/docs/generated/cli/release.md +++ b/docs/generated/cli/release.md @@ -43,6 +43,12 @@ Type: `string` Projects to run. (comma/space delimited project names and/or patterns) +### verbose + +Type: `boolean` + +Prints additional information about the commands (e.g., stack traces) + ### version Type: `boolean` diff --git a/docs/generated/packages/nx/documents/release.md b/docs/generated/packages/nx/documents/release.md index 3c242248c8b0a..77a6b410458b4 100644 --- a/docs/generated/packages/nx/documents/release.md +++ b/docs/generated/packages/nx/documents/release.md @@ -43,6 +43,12 @@ Type: `string` Projects to run. (comma/space delimited project names and/or patterns) +### verbose + +Type: `boolean` + +Prints additional information about the commands (e.g., stack traces) + ### version Type: `boolean` diff --git a/packages/nx/src/command-line/exec/command-object.ts b/packages/nx/src/command-line/exec/command-object.ts index ee0e2ace1720d..522ee48b7ce73 100644 --- a/packages/nx/src/command-line/exec/command-object.ts +++ b/packages/nx/src/command-line/exec/command-object.ts @@ -10,7 +10,7 @@ export const yargsExecCommand: CommandModule = { builder: (yargs) => withRunOneOptions(yargs), handler: async (args) => { try { - await (await import('./exec')).nxExecCommand(withOverrides(args)); + await (await import('./exec')).nxExecCommand(withOverrides(args) as any); process.exit(0); } catch (e) { process.exit(1); diff --git a/packages/nx/src/command-line/release/command-object.ts b/packages/nx/src/command-line/release/command-object.ts index 572d9e486ed9f..acd3129c862aa 100644 --- a/packages/nx/src/command-line/release/command-object.ts +++ b/packages/nx/src/command-line/release/command-object.ts @@ -1,11 +1,12 @@ import { CommandModule, showHelp } from 'yargs'; import { readNxJson } from '../../project-graph/file-utils'; -import { parseCSV } from '../yargs-utils/shared-options'; +import { parseCSV, withOverrides } from '../yargs-utils/shared-options'; export interface NxReleaseArgs { groups?: string[]; projects?: string[]; dryRun?: boolean; + verbose?: boolean; } export type VersionOptions = NxReleaseArgs & { @@ -60,6 +61,11 @@ export const yargsReleaseCommand: CommandModule< type: 'boolean', default: false, }) + .option('verbose', { + type: 'boolean', + describe: + 'Prints additional information about the commands (e.g., stack traces)', + }) .check((argv) => { if (argv.groups && argv.projects) { throw new Error( @@ -161,5 +167,6 @@ const publishCommand: CommandModule = { type: 'string', description: 'The distribution tag to apply to the published package', }), - handler: (args) => import('./publish').then((m) => m.publishHandler(args)), + handler: (args) => + import('./publish').then((m) => m.publishHandler(withOverrides(args, 2))), }; diff --git a/packages/nx/src/command-line/release/publish.ts b/packages/nx/src/command-line/release/publish.ts index 842f7b97f42af..c7c0fd87d297c 100644 --- a/packages/nx/src/command-line/release/publish.ts +++ b/packages/nx/src/command-line/release/publish.ts @@ -6,10 +6,7 @@ import { import { NxJsonConfiguration, output } from '../../devkit-exports'; import { createProjectGraphAsync } from '../../project-graph/project-graph'; import { runCommand } from '../../tasks-runner/run-command'; -import { - NxArgs, - splitArgsIntoNxArgsAndOverrides, -} from '../../utils/command-line-utils'; +import { createOverrides } from '../../utils/command-line-utils'; import { findMatchingProjects } from '../../utils/find-matching-projects'; import { PublishOptions } from './command-object'; import { createNxReleaseConfig } from './config/config'; @@ -20,37 +17,12 @@ import { handleCreateReleaseGroupsError, } from './config/create-release-groups'; -export async function publishHandler(args: PublishOptions): Promise { +export async function publishHandler( + args: PublishOptions & { __unparsed_overrides__: string[] } +): Promise { const projectGraph = await createProjectGraphAsync({ exitOnError: true }); const nxJson = readNxJson(); - const { nxArgs, overrides } = splitArgsIntoNxArgsAndOverrides( - args, - 'release', - { printWarnings: false }, - nxJson - ); - nxArgs.targets = ['release-publish']; - // We are not prioritizing raw speed for publishing execution, we are prioritizing clear useful output - nxArgs.parallel = 1; - nxArgs.outputStyle = 'stream'; - if (nxArgs.verbose) { - process.env.NX_VERBOSE_LOGGING = 'true'; - } - - /** - * TODO: We seem to need to explicitly add the possible CLI flags to the overrides in order for runCommand to work correctly. - * We can't leave this out, otherwise the options will not be set on the executor, nor can we generically spread the args, - * because then a ton of excess properties will be passed to the executor... This makes this code brittle as we could forget - * to update this when we make schema changes and it should be looked into in more detail in a follow up. - */ - if (args.registry) { - overrides.registry = args.registry; - } - if (args.tag) { - overrides.tag = args.tag; - } - // Apply default configuration to any optional user configuration const nxReleaseConfig = createNxReleaseConfig(nxJson.release); const releaseGroupsData = await createReleaseGroups( @@ -138,10 +110,9 @@ export async function publishHandler(args: PublishOptions): Promise { */ for (const releaseGroup of releaseGroups) { await runPublishOnProjects( + args, projectGraph, nxJson, - nxArgs, - overrides, Array.from(releaseGroupToFilteredProjects.get(releaseGroup)) ); } @@ -169,10 +140,9 @@ export async function publishHandler(args: PublishOptions): Promise { */ for (const releaseGroup of releaseGroups) { await runPublishOnProjects( + args, projectGraph, nxJson, - nxArgs, - overrides, releaseGroup.projects ); } @@ -181,16 +151,25 @@ export async function publishHandler(args: PublishOptions): Promise { } async function runPublishOnProjects( + args: PublishOptions & { __unparsed_overrides__: string[] }, projectGraph: ProjectGraph, nxJson: NxJsonConfiguration, - nxArgs: NxArgs, - overrides: Record, projectNames: string[] ) { const projectsToRun: ProjectGraphProjectNode[] = projectNames.map( (projectName) => projectGraph.nodes[projectName] ); + const overrides = { + registry: args.registry, + tag: args.tag, + ...createOverrides(args.__unparsed_overrides__), + }; + + if (args.verbose) { + process.env.NX_VERBOSE_LOGGING = 'true'; + } + /** * Run the relevant release-publish executor on each of the selected projects. */ @@ -198,7 +177,11 @@ async function runPublishOnProjects( projectsToRun, projectGraph, { nxJson }, - nxArgs, + { + targets: ['release-publish'], + parallel: 1, + outputStyle: 'stream', + }, overrides, null, {}, diff --git a/packages/nx/src/command-line/yargs-utils/shared-options.ts b/packages/nx/src/command-line/yargs-utils/shared-options.ts index ee79267fe7bb9..28ac8480592e7 100644 --- a/packages/nx/src/command-line/yargs-utils/shared-options.ts +++ b/packages/nx/src/command-line/yargs-utils/shared-options.ts @@ -168,13 +168,19 @@ export function withRunManyOptions(yargs: Argv) { }); } -export function withOverrides(args: any): any { - args.__overrides_unparsed__ = (args['--'] ?? args._.slice(1)).map((v) => - v.toString() +export function withOverrides }>( + args: T, + commandLevel: number = 1 +): T & { __unparsed_overrides__: string[] } { + const unparsedArgs: string[] = (args['--'] ?? args._.slice(commandLevel)).map( + (v) => v.toString() ); delete args['--']; delete args._; - return args; + return { + ...args, + __unparsed_overrides__: unparsedArgs, + }; } export function withOutputStyleOption( diff --git a/packages/nx/src/utils/command-line-utils.ts b/packages/nx/src/utils/command-line-utils.ts index 5ee7aed74c3e1..f800982b73304 100644 --- a/packages/nx/src/utils/command-line-utils.ts +++ b/packages/nx/src/utils/command-line-utils.ts @@ -37,9 +37,25 @@ export interface NxArgs { type?: string; } +export function createOverrides(__overrides_unparsed__: string[]) { + let overrides = yargsParser(__overrides_unparsed__ as string[], { + configuration: { + 'camel-case-expansion': false, + 'dot-notation': true, + }, + }); + + if (!overrides._ || overrides._.length === 0) { + delete overrides._; + } + + overrides.__overrides_unparsed__ = __overrides_unparsed__; + return overrides; +} + export function splitArgsIntoNxArgsAndOverrides( args: { [k: string]: any }, - mode: 'run-one' | 'run-many' | 'affected' | 'print-affected' | 'release', + mode: 'run-one' | 'run-many' | 'affected' | 'print-affected', options = { printWarnings: true }, nxJson: NxJsonConfiguration ): { @@ -66,54 +82,11 @@ export function splitArgsIntoNxArgsAndOverrides( } const nxArgs: RawNxArgs = args; - let overrides = yargsParser(args.__overrides_unparsed__ as string[], { - configuration: { - 'camel-case-expansion': false, - 'dot-notation': true, - }, - }); - - if (!overrides._ || overrides._.length === 0) { - delete overrides._; - } - overrides.__overrides_unparsed__ = args.__overrides_unparsed__; + let overrides = createOverrides(args.__overrides_unparsed__); delete (nxArgs as any).$0; delete (nxArgs as any).__overrides_unparsed__; - if (mode === 'release') { - if (overrides._[0] === 'release') { - overrides._.shift(); - } - if ( - overrides._[0] === 'version' || - overrides._[0] === 'v' || - overrides._[0] === 'changelog' || - overrides._[0] === 'c' || - overrides._[0] === 'publish' || - overrides._[0] === 'p' - ) { - overrides._.shift(); - } - if (overrides.__overrides_unparsed__[0] === 'release') { - overrides.__overrides_unparsed__.shift(); - } - if ( - overrides.__overrides_unparsed__[0] === 'version' || - overrides.__overrides_unparsed__[0] === 'v' || - overrides.__overrides_unparsed__[0] === 'changelog' || - overrides.__overrides_unparsed__[0] === 'c' || - overrides.__overrides_unparsed__[0] === 'publish' || - overrides.__overrides_unparsed__[0] === 'p' - ) { - overrides.__overrides_unparsed__.shift(); - } - if (overrides._.length === 0) { - delete overrides._; - } - return { nxArgs, overrides } as any; - } - if (mode === 'run-many') { const args = nxArgs as any; if (!args.projects) { From 86f20b6aa5085c422f8f50181bfcdc65103f834d Mon Sep 17 00:00:00 2001 From: James Henry Date: Thu, 14 Sep 2023 13:03:24 +0400 Subject: [PATCH 07/13] chore(core): fix e2e regressions, update types --- package.json | 2 +- .../nx/src/command-line/release/publish.ts | 13 +++++++----- .../src/command-line/release/utils/semver.ts | 10 ++-------- .../nx/src/command-line/release/version.ts | 11 ++++------ packages/nx/src/utils/command-line-utils.ts | 15 +++++++------- pnpm-lock.yaml | 20 +++++++++---------- 6 files changed, 33 insertions(+), 38 deletions(-) diff --git a/package.json b/package.json index e62322660933c..be82d365c146b 100644 --- a/package.json +++ b/package.json @@ -123,7 +123,7 @@ "@types/prettier": "^2.6.2", "@types/react": "18.2.14", "@types/react-dom": "18.2.6", - "@types/semver": "^7.5.0", + "@types/semver": "^7.5.2", "@types/tar-stream": "^2.2.2", "@types/tmp": "^0.2.0", "@types/yargs": "^17.0.10", diff --git a/packages/nx/src/command-line/release/publish.ts b/packages/nx/src/command-line/release/publish.ts index c7c0fd87d297c..234efacea2c90 100644 --- a/packages/nx/src/command-line/release/publish.ts +++ b/packages/nx/src/command-line/release/publish.ts @@ -160,11 +160,14 @@ async function runPublishOnProjects( (projectName) => projectGraph.nodes[projectName] ); - const overrides = { - registry: args.registry, - tag: args.tag, - ...createOverrides(args.__unparsed_overrides__), - }; + const overrides = createOverrides(args.__unparsed_overrides__); + + if (args.registry) { + overrides.registry = args.registry; + } + if (args.tag) { + overrides.registry = args.registry; + } if (args.verbose) { process.env.NX_VERBOSE_LOGGING = 'true'; diff --git a/packages/nx/src/command-line/release/utils/semver.ts b/packages/nx/src/command-line/release/utils/semver.ts index fcd59b13e2f78..7157ba0c5e09e 100644 --- a/packages/nx/src/command-line/release/utils/semver.ts +++ b/packages/nx/src/command-line/release/utils/semver.ts @@ -1,12 +1,6 @@ -import { - // @ts-ignore the RELEASE_TYPES export is missing from @types/semver - RELEASE_TYPES, - ReleaseType, - inc, - valid, -} from 'semver'; +import { RELEASE_TYPES, ReleaseType, inc, valid } from 'semver'; -function isRelativeVersionKeyword(val: string): val is ReleaseType { +export function isRelativeVersionKeyword(val: string): val is ReleaseType { return RELEASE_TYPES.includes(val as ReleaseType); } diff --git a/packages/nx/src/command-line/release/version.ts b/packages/nx/src/command-line/release/version.ts index 3f3f3789f4602..346a479107241 100644 --- a/packages/nx/src/command-line/release/version.ts +++ b/packages/nx/src/command-line/release/version.ts @@ -2,11 +2,7 @@ import * as chalk from 'chalk'; import * as enquirer from 'enquirer'; import { readFileSync } from 'node:fs'; import { relative } from 'node:path'; -import { - // @ts-ignore missing from @types/semver - RELEASE_TYPES, - valid, -} from 'semver'; +import { RELEASE_TYPES, valid } from 'semver'; import { Generator } from '../../config/misc-interfaces'; import { readNxJson } from '../../config/nx-json'; import { @@ -39,6 +35,7 @@ import { handleCreateReleaseGroupsError, } from './config/create-release-groups'; import { printDiff } from './utils/print-diff'; +import { isRelativeVersionKeyword } from './utils/semver'; // Reexport for use in plugin release-version generator implementations export { deriveNewSemverVersion } from './utils/semver'; @@ -262,7 +259,7 @@ async function runVersionOnProjects( // Specifier could be user provided so we need to validate it if ( !valid(newVersionSpecifier) && - !RELEASE_TYPES.includes(newVersionSpecifier) + !isRelativeVersionKeyword(newVersionSpecifier) ) { output.error({ title: `The given version specifier "${newVersionSpecifier}" is not valid. You provide an exact version or a valid semver keyword such as "major", "minor", "patch", etc.`, @@ -350,7 +347,7 @@ async function resolveSemverSpecifier( message: selectionMessage, type: 'select', choices: [ - ...RELEASE_TYPES, + ...RELEASE_TYPES.map((t) => ({ name: t, message: t })), { name: 'custom', message: 'Custom exact version', diff --git a/packages/nx/src/utils/command-line-utils.ts b/packages/nx/src/utils/command-line-utils.ts index f800982b73304..53fe4a9c91ff9 100644 --- a/packages/nx/src/utils/command-line-utils.ts +++ b/packages/nx/src/utils/command-line-utils.ts @@ -37,13 +37,14 @@ export interface NxArgs { type?: string; } -export function createOverrides(__overrides_unparsed__: string[]) { - let overrides = yargsParser(__overrides_unparsed__ as string[], { - configuration: { - 'camel-case-expansion': false, - 'dot-notation': true, - }, - }); +export function createOverrides(__overrides_unparsed__: string[] = []) { + let overrides = + yargsParser(__overrides_unparsed__, { + configuration: { + 'camel-case-expansion': false, + 'dot-notation': true, + }, + }) || {}; if (!overrides._ || overrides._.length === 0) { delete overrides._; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cf2c8ba1d6690..ce11769f83463 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -449,8 +449,8 @@ devDependencies: specifier: 18.2.6 version: 18.2.6 '@types/semver': - specifier: ^7.5.0 - version: 7.5.0 + specifier: ^7.5.2 + version: 7.5.2 '@types/tar-stream': specifier: ^2.2.2 version: 2.2.2 @@ -8704,7 +8704,7 @@ packages: '@storybook/theming': 7.2.2(react-dom@18.2.0)(react@18.2.0) '@swc/core': 1.3.51(@swc/helpers@0.5.0) '@types/node': 16.18.36 - '@types/semver': 7.5.0 + '@types/semver': 7.5.2 babel-loader: 9.1.2(@babel/core@7.22.9)(webpack@5.88.0) babel-plugin-named-exports-order: 0.0.2 browser-assert: 1.2.1 @@ -8920,7 +8920,7 @@ packages: '@types/detect-port': 1.3.2 '@types/node': 16.18.36 '@types/pretty-hrtime': 1.0.1 - '@types/semver': 7.5.0 + '@types/semver': 7.5.2 better-opn: 3.0.2 chalk: 4.1.2 cli-table3: 0.6.3 @@ -9124,7 +9124,7 @@ packages: '@storybook/react': 7.2.2(react-dom@18.2.0)(react@18.2.0)(typescript@5.1.3) '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.1.3)(webpack@5.88.0) '@types/node': 16.18.36 - '@types/semver': 7.5.0 + '@types/semver': 7.5.2 babel-plugin-add-react-displayname: 0.0.5 babel-plugin-react-docgen: 4.2.1 fs-extra: 11.1.1 @@ -10404,8 +10404,8 @@ packages: /@types/scheduler@0.16.2: resolution: {integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==} - /@types/semver@7.5.0: - resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==} + /@types/semver@7.5.2: + resolution: {integrity: sha512-7aqorHYgdNO4DM36stTiGO3DvKoex9TQRwsJU6vMaFGyqpBA1MNZkz+PG3gaNUPpTAOYhT1WR7M1JyA3fbS9Cw==} dev: true /@types/serve-index@1.9.1: @@ -10728,7 +10728,7 @@ packages: dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.46.0) '@types/json-schema': 7.0.12 - '@types/semver': 7.5.0 + '@types/semver': 7.5.2 '@typescript-eslint/scope-manager': 5.59.2 '@typescript-eslint/types': 5.59.2 '@typescript-eslint/typescript-estree': 5.59.2(typescript@5.1.3) @@ -10748,7 +10748,7 @@ packages: dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.46.0) '@types/json-schema': 7.0.12 - '@types/semver': 7.5.0 + '@types/semver': 7.5.2 '@typescript-eslint/scope-manager': 5.60.1 '@typescript-eslint/types': 5.60.1 '@typescript-eslint/typescript-estree': 5.60.1(typescript@5.1.3) @@ -10768,7 +10768,7 @@ packages: dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.46.0) '@types/json-schema': 7.0.12 - '@types/semver': 7.5.0 + '@types/semver': 7.5.2 '@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/types': 5.62.0 '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.1.3) From 8b9f60cfaffa2959586f77789529d8dcb76ee2ea Mon Sep 17 00:00:00 2001 From: FrozenPandaz Date: Thu, 14 Sep 2023 09:38:15 -0400 Subject: [PATCH 08/13] fix(core): fix property name --- packages/nx/src/command-line/release/publish.ts | 6 +++--- packages/nx/src/command-line/yargs-utils/shared-options.ts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/nx/src/command-line/release/publish.ts b/packages/nx/src/command-line/release/publish.ts index 234efacea2c90..0b709a86a645a 100644 --- a/packages/nx/src/command-line/release/publish.ts +++ b/packages/nx/src/command-line/release/publish.ts @@ -18,7 +18,7 @@ import { } from './config/create-release-groups'; export async function publishHandler( - args: PublishOptions & { __unparsed_overrides__: string[] } + args: PublishOptions & { __overrides_unparsed__: string[] } ): Promise { const projectGraph = await createProjectGraphAsync({ exitOnError: true }); const nxJson = readNxJson(); @@ -151,7 +151,7 @@ export async function publishHandler( } async function runPublishOnProjects( - args: PublishOptions & { __unparsed_overrides__: string[] }, + args: PublishOptions & { __overrides_unparsed__: string[] }, projectGraph: ProjectGraph, nxJson: NxJsonConfiguration, projectNames: string[] @@ -160,7 +160,7 @@ async function runPublishOnProjects( (projectName) => projectGraph.nodes[projectName] ); - const overrides = createOverrides(args.__unparsed_overrides__); + const overrides = createOverrides(args.__overrides_unparsed__); if (args.registry) { overrides.registry = args.registry; diff --git a/packages/nx/src/command-line/yargs-utils/shared-options.ts b/packages/nx/src/command-line/yargs-utils/shared-options.ts index 28ac8480592e7..dc3bc2e57fc44 100644 --- a/packages/nx/src/command-line/yargs-utils/shared-options.ts +++ b/packages/nx/src/command-line/yargs-utils/shared-options.ts @@ -171,7 +171,7 @@ export function withRunManyOptions(yargs: Argv) { export function withOverrides }>( args: T, commandLevel: number = 1 -): T & { __unparsed_overrides__: string[] } { +): T & { __overrides_unparsed__: string[] } { const unparsedArgs: string[] = (args['--'] ?? args._.slice(commandLevel)).map( (v) => v.toString() ); @@ -179,7 +179,7 @@ export function withOverrides }>( delete args._; return { ...args, - __unparsed_overrides__: unparsedArgs, + __overrides_unparsed__: unparsedArgs, }; } From 99abdbeabd3b4a390eb5fb6f5526f5f275b09a2b Mon Sep 17 00:00:00 2001 From: James Henry Date: Fri, 15 Sep 2023 18:22:34 +0400 Subject: [PATCH 09/13] fix(core): copy paste error --- packages/nx/src/command-line/release/publish.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nx/src/command-line/release/publish.ts b/packages/nx/src/command-line/release/publish.ts index 0b709a86a645a..56efa9518cb8c 100644 --- a/packages/nx/src/command-line/release/publish.ts +++ b/packages/nx/src/command-line/release/publish.ts @@ -166,7 +166,7 @@ async function runPublishOnProjects( overrides.registry = args.registry; } if (args.tag) { - overrides.registry = args.registry; + overrides.tag = args.tag; } if (args.verbose) { From 434016dfd8b1ee657c4c52dc2ece49e4de82ebe7 Mon Sep 17 00:00:00 2001 From: FrozenPandaz Date: Fri, 15 Sep 2023 14:13:54 -0400 Subject: [PATCH 10/13] feat(core): allow all run-many options for publish --- docs/generated/cli/affected.md | 6 +- docs/generated/cli/exec.md | 6 +- docs/generated/cli/release.md | 68 +++++++++++++++++++ docs/generated/cli/run-many.md | 6 +- .../packages/nx/documents/affected.md | 6 +- docs/generated/packages/nx/documents/exec.md | 6 +- .../packages/nx/documents/release.md | 68 +++++++++++++++++++ .../packages/nx/documents/run-many.md | 6 +- .../plugins/package-json-workspaces.spec.ts | 9 +++ .../command-line/release/command-object.ts | 20 ++++-- .../nx/src/command-line/release/publish.ts | 65 ++++++++++++------ .../yargs-utils/shared-options.ts | 47 ++++++++++--- packages/nx/src/config/workspaces.spec.ts | 4 ++ .../build-nodes/project-json.spec.ts | 4 ++ packages/nx/src/utils/command-line-utils.ts | 2 +- packages/nx/src/utils/package-json.spec.ts | 3 + packages/nx/src/utils/package-json.ts | 1 + 17 files changed, 270 insertions(+), 57 deletions(-) diff --git a/docs/generated/cli/affected.md b/docs/generated/cli/affected.md index 3507e64b9a425..b8557f8d10726 100644 --- a/docs/generated/cli/affected.md +++ b/docs/generated/cli/affected.md @@ -115,7 +115,7 @@ Type: `boolean` Show help -### nx-bail +### nxBail Type: `boolean` @@ -123,7 +123,7 @@ Default: `false` Stop command execution after the first failed task -### nx-ignore-cycles +### nxIgnoreCycles Type: `boolean` @@ -151,7 +151,7 @@ Type: `string` This is the name of the tasks runner configured in nx.json -### skip-nx-cache +### skipNxCache Type: `boolean` diff --git a/docs/generated/cli/exec.md b/docs/generated/cli/exec.md index 9c5b2825f940c..a0fa423a92df2 100644 --- a/docs/generated/cli/exec.md +++ b/docs/generated/cli/exec.md @@ -35,7 +35,7 @@ Type: `string` Show the task graph of the command. Pass a file path to save the graph data instead of viewing it in the browser. -### nx-bail +### nxBail Type: `boolean` @@ -43,7 +43,7 @@ Default: `false` Stop command execution after the first failed task -### nx-ignore-cycles +### nxIgnoreCycles Type: `boolean` @@ -77,7 +77,7 @@ Type: `string` This is the name of the tasks runner configured in nx.json -### skip-nx-cache +### skipNxCache Type: `boolean` diff --git a/docs/generated/cli/release.md b/docs/generated/cli/release.md index 77a6b410458b4..0fabd6ec0d58f 100644 --- a/docs/generated/cli/release.md +++ b/docs/generated/cli/release.md @@ -151,24 +151,92 @@ nx release publish #### Options +##### all + +Type: `boolean` + +Default: `true` + +[deprecated] `run-many` runs all targets on all projects in the workspace if no projects are provided. This option is no longer required. + +##### exclude + +Type: `string` + +Exclude certain projects from being processed + +##### graph + +Type: `string` + +Show the task graph of the command. Pass a file path to save the graph data instead of viewing it in the browser. + ##### help Type: `boolean` Show help +##### nxBail + +Type: `boolean` + +Default: `false` + +Stop command execution after the first failed task + +##### nxIgnoreCycles + +Type: `boolean` + +Default: `false` + +Ignore cycles in the task graph + +##### parallel + +Type: `string` + +Max number of parallel processes [default is 3] + +##### projects + +Type: `string` + +Projects to run. (comma/space delimited project names and/or patterns) + ##### registry Type: `string` The registry to publish to +##### runner + +Type: `string` + +This is the name of the tasks runner configured in nx.json + +##### skipNxCache + +Type: `boolean` + +Default: `false` + +Rerun the tasks even when the results are available in the cache + ##### tag Type: `string` The distribution tag to apply to the published package +##### verbose + +Type: `boolean` + +Prints additional information about the commands (e.g., stack traces) + ##### version Type: `boolean` diff --git a/docs/generated/cli/run-many.md b/docs/generated/cli/run-many.md index 291aa6fbabe08..2d80356950d79 100644 --- a/docs/generated/cli/run-many.md +++ b/docs/generated/cli/run-many.md @@ -105,7 +105,7 @@ Type: `boolean` Show help -### nx-bail +### nxBail Type: `boolean` @@ -113,7 +113,7 @@ Default: `false` Stop command execution after the first failed task -### nx-ignore-cycles +### nxIgnoreCycles Type: `boolean` @@ -147,7 +147,7 @@ Type: `string` This is the name of the tasks runner configured in nx.json -### skip-nx-cache +### skipNxCache Type: `boolean` diff --git a/docs/generated/packages/nx/documents/affected.md b/docs/generated/packages/nx/documents/affected.md index 3507e64b9a425..b8557f8d10726 100644 --- a/docs/generated/packages/nx/documents/affected.md +++ b/docs/generated/packages/nx/documents/affected.md @@ -115,7 +115,7 @@ Type: `boolean` Show help -### nx-bail +### nxBail Type: `boolean` @@ -123,7 +123,7 @@ Default: `false` Stop command execution after the first failed task -### nx-ignore-cycles +### nxIgnoreCycles Type: `boolean` @@ -151,7 +151,7 @@ Type: `string` This is the name of the tasks runner configured in nx.json -### skip-nx-cache +### skipNxCache Type: `boolean` diff --git a/docs/generated/packages/nx/documents/exec.md b/docs/generated/packages/nx/documents/exec.md index 9c5b2825f940c..a0fa423a92df2 100644 --- a/docs/generated/packages/nx/documents/exec.md +++ b/docs/generated/packages/nx/documents/exec.md @@ -35,7 +35,7 @@ Type: `string` Show the task graph of the command. Pass a file path to save the graph data instead of viewing it in the browser. -### nx-bail +### nxBail Type: `boolean` @@ -43,7 +43,7 @@ Default: `false` Stop command execution after the first failed task -### nx-ignore-cycles +### nxIgnoreCycles Type: `boolean` @@ -77,7 +77,7 @@ Type: `string` This is the name of the tasks runner configured in nx.json -### skip-nx-cache +### skipNxCache Type: `boolean` diff --git a/docs/generated/packages/nx/documents/release.md b/docs/generated/packages/nx/documents/release.md index 77a6b410458b4..0fabd6ec0d58f 100644 --- a/docs/generated/packages/nx/documents/release.md +++ b/docs/generated/packages/nx/documents/release.md @@ -151,24 +151,92 @@ nx release publish #### Options +##### all + +Type: `boolean` + +Default: `true` + +[deprecated] `run-many` runs all targets on all projects in the workspace if no projects are provided. This option is no longer required. + +##### exclude + +Type: `string` + +Exclude certain projects from being processed + +##### graph + +Type: `string` + +Show the task graph of the command. Pass a file path to save the graph data instead of viewing it in the browser. + ##### help Type: `boolean` Show help +##### nxBail + +Type: `boolean` + +Default: `false` + +Stop command execution after the first failed task + +##### nxIgnoreCycles + +Type: `boolean` + +Default: `false` + +Ignore cycles in the task graph + +##### parallel + +Type: `string` + +Max number of parallel processes [default is 3] + +##### projects + +Type: `string` + +Projects to run. (comma/space delimited project names and/or patterns) + ##### registry Type: `string` The registry to publish to +##### runner + +Type: `string` + +This is the name of the tasks runner configured in nx.json + +##### skipNxCache + +Type: `boolean` + +Default: `false` + +Rerun the tasks even when the results are available in the cache + ##### tag Type: `string` The distribution tag to apply to the published package +##### verbose + +Type: `boolean` + +Prints additional information about the commands (e.g., stack traces) + ##### version Type: `boolean` diff --git a/docs/generated/packages/nx/documents/run-many.md b/docs/generated/packages/nx/documents/run-many.md index 291aa6fbabe08..2d80356950d79 100644 --- a/docs/generated/packages/nx/documents/run-many.md +++ b/docs/generated/packages/nx/documents/run-many.md @@ -105,7 +105,7 @@ Type: `boolean` Show help -### nx-bail +### nxBail Type: `boolean` @@ -113,7 +113,7 @@ Default: `false` Stop command execution after the first failed task -### nx-ignore-cycles +### nxIgnoreCycles Type: `boolean` @@ -147,7 +147,7 @@ Type: `string` This is the name of the tasks runner configured in nx.json -### skip-nx-cache +### skipNxCache Type: `boolean` diff --git a/packages/nx/plugins/package-json-workspaces.spec.ts b/packages/nx/plugins/package-json-workspaces.spec.ts index e9b714369b608..2bc5eb630b58c 100644 --- a/packages/nx/plugins/package-json-workspaces.spec.ts +++ b/packages/nx/plugins/package-json-workspaces.spec.ts @@ -53,6 +53,9 @@ describe('nx package.json workspaces plugin', () => { }, }, "release-publish": { + "dependsOn": [ + "^release-publish", + ], "executor": "@nx/js:release-publish", "options": {}, }, @@ -72,6 +75,9 @@ describe('nx package.json workspaces plugin', () => { "sourceRoot": "packages/lib-a", "targets": { "release-publish": { + "dependsOn": [ + "^release-publish", + ], "executor": "@nx/js:release-publish", "options": {}, }, @@ -113,6 +119,9 @@ describe('nx package.json workspaces plugin', () => { ], }, "release-publish": { + "dependsOn": [ + "^release-publish", + ], "executor": "@nx/js:release-publish", "options": {}, }, diff --git a/packages/nx/src/command-line/release/command-object.ts b/packages/nx/src/command-line/release/command-object.ts index acd3129c862aa..ba39eb0246e96 100644 --- a/packages/nx/src/command-line/release/command-object.ts +++ b/packages/nx/src/command-line/release/command-object.ts @@ -1,6 +1,11 @@ import { CommandModule, showHelp } from 'yargs'; import { readNxJson } from '../../project-graph/file-utils'; -import { parseCSV, withOverrides } from '../yargs-utils/shared-options'; +import { + parseCSV, + RunManyOptions, + withOverrides, + withRunManyOptions, +} from '../yargs-utils/shared-options'; export interface NxReleaseArgs { groups?: string[]; @@ -22,10 +27,11 @@ export type ChangelogOptions = NxReleaseArgs & { tagVersionPrefix?: string; }; -export type PublishOptions = NxReleaseArgs & { - registry?: string; - tag?: string; -}; +export type PublishOptions = NxReleaseArgs & + RunManyOptions & { + registry?: string; + tag?: string; + }; export const yargsReleaseCommand: CommandModule< Record, @@ -153,12 +159,12 @@ const changelogCommand: CommandModule = { import('./changelog').then((m) => m.changelogHandler(args)), }; -const publishCommand: CommandModule = { +const publishCommand: CommandModule = { command: 'publish', aliases: ['p'], describe: 'Publish a versioned project to a registry', builder: (yargs) => - yargs + withRunManyOptions(yargs) .option('registry', { type: 'string', description: 'The registry to publish to', diff --git a/packages/nx/src/command-line/release/publish.ts b/packages/nx/src/command-line/release/publish.ts index 56efa9518cb8c..40de17c5a8aff 100644 --- a/packages/nx/src/command-line/release/publish.ts +++ b/packages/nx/src/command-line/release/publish.ts @@ -6,7 +6,10 @@ import { import { NxJsonConfiguration, output } from '../../devkit-exports'; import { createProjectGraphAsync } from '../../project-graph/project-graph'; import { runCommand } from '../../tasks-runner/run-command'; -import { createOverrides } from '../../utils/command-line-utils'; +import { + createOverrides, + readGraphFileFromGraphArg, +} from '../../utils/command-line-utils'; import { findMatchingProjects } from '../../utils/find-matching-projects'; import { PublishOptions } from './command-object'; import { createNxReleaseConfig } from './config/config'; @@ -16,6 +19,7 @@ import { createReleaseGroups, handleCreateReleaseGroupsError, } from './config/create-release-groups'; +import { generateGraph } from '../graph/graph'; export async function publishHandler( args: PublishOptions & { __overrides_unparsed__: string[] } @@ -173,27 +177,44 @@ async function runPublishOnProjects( process.env.NX_VERBOSE_LOGGING = 'true'; } - /** - * Run the relevant release-publish executor on each of the selected projects. - */ - const status = await runCommand( - projectsToRun, - projectGraph, - { nxJson }, - { - targets: ['release-publish'], - parallel: 1, - outputStyle: 'stream', - }, - overrides, - null, - {}, - { excludeTaskDependencies: false, loadDotEnvFiles: true } - ); + if (args.graph) { + const file = readGraphFileFromGraphArg(args); + const projectNames = projectsToRun.map((t) => t.name); + return await generateGraph( + { + watch: false, + all: false, + open: true, + view: 'tasks', + targets: ['release-publish'], + projects: projectNames, + file, + }, + projectNames + ); + } else { + /** + * Run the relevant release-publish executor on each of the selected projects. + */ + const status = await runCommand( + projectsToRun, + projectGraph, + { nxJson }, + { + targets: ['release-publish'], + outputStyle: 'static', + ...(args as any), + }, + overrides, + null, + {}, + { excludeTaskDependencies: false, loadDotEnvFiles: true } + ); - if (status !== 0) { - // fix for https://github.com/nrwl/nx/issues/1666 - if (process.stdin['unref']) (process.stdin as any).unref(); - process.exit(status); + if (status !== 0) { + // fix for https://github.com/nrwl/nx/issues/1666 + if (process.stdin['unref']) (process.stdin as any).unref(); + process.exit(status); + } } } diff --git a/packages/nx/src/command-line/yargs-utils/shared-options.ts b/packages/nx/src/command-line/yargs-utils/shared-options.ts index dc3bc2e57fc44..9a294df04719f 100644 --- a/packages/nx/src/command-line/yargs-utils/shared-options.ts +++ b/packages/nx/src/command-line/yargs-utils/shared-options.ts @@ -1,14 +1,33 @@ import { Argv } from 'yargs'; -export function withExcludeOption(yargs: Argv) { +interface ExcludeOptions { + exclude: string[]; +} + +export function withExcludeOption(yargs: Argv): Argv { return yargs.option('exclude', { describe: 'Exclude certain projects from being processed', type: 'string', coerce: parseCSV, - }); + }) as any; +} + +export interface RunOptions { + exclude: string; + parallel: string; + maxParallel: number; + runner: string; + prod: boolean; + graph: string; + verbose: boolean; + nxBail: boolean; + nxIgnoreCycles: boolean; + skipNxCache: boolean; + cloud: boolean; + dte: boolean; } -export function withRunOptions(yargs: Argv) { +export function withRunOptions(yargs: Argv): Argv { return withExcludeOption(yargs) .option('parallel', { describe: 'Max number of parallel processes [default is 3]', @@ -47,17 +66,17 @@ export function withRunOptions(yargs: Argv) { describe: 'Prints additional information about the commands (e.g., stack traces)', }) - .option('nx-bail', { + .option('nxBail', { describe: 'Stop command execution after the first failed task', type: 'boolean', default: false, }) - .option('nx-ignore-cycles', { + .option('nxIgnoreCycles', { describe: 'Ignore cycles in the task graph', type: 'boolean', default: false, }) - .options('skip-nx-cache', { + .options('skipNxCache', { describe: 'Rerun the tasks even when the results are available in the cache', type: 'boolean', @@ -70,7 +89,7 @@ export function withRunOptions(yargs: Argv) { .options('dte', { type: 'boolean', hidden: true, - }); + }) as Argv> as any; } export function withTargetAndConfigurationOption( @@ -146,7 +165,17 @@ export function withAffectedOptions(yargs: Argv) { }); } -export function withRunManyOptions(yargs: Argv) { +export interface RunManyOptions extends RunOptions { + projects: string[]; + /** + * @deprecated This is deprecated + */ + all: boolean; +} + +export function withRunManyOptions( + yargs: Argv +): Argv { return withRunOptions(yargs) .parserConfiguration({ 'strip-dashed': true, @@ -165,7 +194,7 @@ export function withRunManyOptions(yargs: Argv) { '[deprecated] `run-many` runs all targets on all projects in the workspace if no projects are provided. This option is no longer required.', type: 'boolean', default: true, - }); + }) as Argv; } export function withOverrides }>( diff --git a/packages/nx/src/config/workspaces.spec.ts b/packages/nx/src/config/workspaces.spec.ts index d6a45ed5d6025..f38f9e1e295cf 100644 --- a/packages/nx/src/config/workspaces.spec.ts +++ b/packages/nx/src/config/workspaces.spec.ts @@ -11,6 +11,7 @@ const libConfig = (root, name?: string) => ({ sourceRoot: `libs/${root}/src`, targets: { 'release-publish': { + dependsOn: ['^release-publish'], executor: '@nx/js:release-publish', options: {}, }, @@ -24,6 +25,7 @@ const packageLibConfig = (root, name?: string) => ({ projectType: 'library', targets: { 'release-publish': { + dependsOn: ['^release-publish'], executor: '@nx/js:release-publish', options: {}, }, @@ -98,6 +100,7 @@ describe('Workspaces', () => { projectType: 'library', targets: { 'release-publish': { + dependsOn: ['^release-publish'], executor: '@nx/js:release-publish', options: {}, }, @@ -144,6 +147,7 @@ describe('Workspaces', () => { projectType: 'library', targets: { 'release-publish': { + dependsOn: ['^release-publish'], executor: '@nx/js:release-publish', options: {}, }, diff --git a/packages/nx/src/plugins/project-json/build-nodes/project-json.spec.ts b/packages/nx/src/plugins/project-json/build-nodes/project-json.spec.ts index 3f871d737eb82..d09fbef6be10a 100644 --- a/packages/nx/src/plugins/project-json/build-nodes/project-json.spec.ts +++ b/packages/nx/src/plugins/project-json/build-nodes/project-json.spec.ts @@ -13,6 +13,7 @@ const { createNodes } = CreateProjectJsonProjectsPlugin; const defaultReleasePublishTarget = { 'release-publish': { + dependsOn: ['^release-publish'], executor: '@nx/js:release-publish', options: {}, }, @@ -80,6 +81,9 @@ describe('nx project.json plugin', () => { "options": {}, }, "release-publish": { + "dependsOn": [ + "^release-publish", + ], "executor": "@nx/js:release-publish", "options": {}, }, diff --git a/packages/nx/src/utils/command-line-utils.ts b/packages/nx/src/utils/command-line-utils.ts index 53fe4a9c91ff9..267b098491380 100644 --- a/packages/nx/src/utils/command-line-utils.ts +++ b/packages/nx/src/utils/command-line-utils.ts @@ -329,7 +329,7 @@ export function getProjectRoots( return projectNames.map((name) => nodes[name].data.root); } -export function readGraphFileFromGraphArg({ graph }: NxArgs) { +export function readGraphFileFromGraphArg({ graph }: Pick) { return typeof graph === 'string' && graph !== 'true' && graph !== '' ? graph : undefined; diff --git a/packages/nx/src/utils/package-json.spec.ts b/packages/nx/src/utils/package-json.spec.ts index 6c4ec85cd7182..57dbd400f6d02 100644 --- a/packages/nx/src/utils/package-json.spec.ts +++ b/packages/nx/src/utils/package-json.spec.ts @@ -71,6 +71,7 @@ describe('readTargetsFromPackageJson', () => { }, }, 'release-publish': { + dependsOn: ['^release-publish'], executor: '@nx/js:release-publish', options: {}, }, @@ -95,6 +96,7 @@ describe('readTargetsFromPackageJson', () => { expect(result).toEqual({ build: { ...packageJsonBuildTarget, outputs: ['custom'] }, 'release-publish': { + dependsOn: ['^release-publish'], executor: '@nx/js:release-publish', options: {}, }, @@ -120,6 +122,7 @@ describe('readTargetsFromPackageJson', () => { options: { script: 'test' }, }, 'release-publish': { + dependsOn: ['^release-publish'], executor: '@nx/js:release-publish', options: {}, }, diff --git a/packages/nx/src/utils/package-json.ts b/packages/nx/src/utils/package-json.ts index af608257ed7cf..09e4c18dd650d 100644 --- a/packages/nx/src/utils/package-json.ts +++ b/packages/nx/src/utils/package-json.ts @@ -145,6 +145,7 @@ export function readTargetsFromPackageJson({ scripts, nx }: PackageJson) { // Add implicit release-publish target for all package.json files to allow for lightweight configuration for package based repos if (!res['release-publish']) { res['release-publish'] = { + dependsOn: ['^release-publish'], executor: '@nx/js:release-publish', options: {}, }; From 7724538396f456f2323898cbcd4855a0ded02cd6 Mon Sep 17 00:00:00 2001 From: FrozenPandaz Date: Fri, 15 Sep 2023 17:54:02 -0400 Subject: [PATCH 11/13] chore(core): fix release snapshots --- e2e/release/src/release.test.ts | 204 +++++++++++++++++--------------- 1 file changed, 108 insertions(+), 96 deletions(-) diff --git a/e2e/release/src/release.test.ts b/e2e/release/src/release.test.ts index e966a19d014cb..0a2a7a41379e5 100644 --- a/e2e/release/src/release.test.ts +++ b/e2e/release/src/release.test.ts @@ -119,60 +119,66 @@ describe('nx release', () => { > nx run {project-name}:release-publish - {project-name}: 📦 @proj/{project-name}@999.9.9 - {project-name}: === Tarball Contents === - {project-name}: XXB index.js - {project-name}: XXXB package.json - {project-name}: XXB project.json - {project-name}: === Tarball Details === - {project-name}: name: @proj/{project-name} - {project-name}: version: 999.9.9 - {project-name}: filename: proj-{project-name}-999.9.9.tgz - {project-name}: package size: XXXB - {project-name}: unpacked size: XXXB - {project-name}: shasum: {SHASUM} - {project-name}: integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - {project-name}: total files: 3 - {project-name}: - {project-name}: Published to ${e2eRegistryUrl} with tag "latest" + + 📦 @proj/{project-name}@999.9.9 + === Tarball Contents === + + XXB index.js + XXXB package.json + XXB project.json + === Tarball Details === + name: @proj/{project-name} + version: 999.9.9 + filename: proj-{project-name}-999.9.9.tgz + package size: XXXB + unpacked size: XXXB + shasum: {SHASUM} + integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + total files: 3 + + Published to http://localhost:4874 with tag "latest" > nx run {project-name}:release-publish - {project-name}: 📦 @proj/{project-name}@999.9.9 - {project-name}: === Tarball Contents === - {project-name}: XXB index.js - {project-name}: XXXB package.json - {project-name}: XXB project.json - {project-name}: === Tarball Details === - {project-name}: name: @proj/{project-name} - {project-name}: version: 999.9.9 - {project-name}: filename: proj-{project-name}-999.9.9.tgz - {project-name}: package size: XXXB - {project-name}: unpacked size: XXXB - {project-name}: shasum: {SHASUM} - {project-name}: integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - {project-name}: total files: 3 - {project-name}: - {project-name}: Published to ${e2eRegistryUrl} with tag "latest" + + 📦 @proj/{project-name}@999.9.9 + === Tarball Contents === + + XXB index.js + XXXB package.json + XXB project.json + === Tarball Details === + name: @proj/{project-name} + version: 999.9.9 + filename: proj-{project-name}-999.9.9.tgz + package size: XXXB + unpacked size: XXXB + shasum: {SHASUM} + integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + total files: 3 + + Published to http://localhost:4874 with tag "latest" > nx run {project-name}:release-publish - {project-name}: 📦 @proj/{project-name}@999.9.9 - {project-name}: === Tarball Contents === - {project-name}: XXB index.js - {project-name}: XXXB package.json - {project-name}: XXB project.json - {project-name}: === Tarball Details === - {project-name}: name: @proj/{project-name} - {project-name}: version: 999.9.9 - {project-name}: filename: proj-{project-name}-999.9.9.tgz - {project-name}: package size: XXXB - {project-name}: unpacked size: XXXB - {project-name}: shasum: {SHASUM} - {project-name}: integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - {project-name}: total files: 3 - {project-name}: - {project-name}: Published to ${e2eRegistryUrl} with tag "latest" + + 📦 @proj/{project-name}@999.9.9 + === Tarball Contents === + + XXB index.js + XXXB package.json + XXB project.json + === Tarball Details === + name: @proj/{project-name} + version: 999.9.9 + filename: proj-{project-name}-999.9.9.tgz + package size: XXXB + unpacked size: XXXB + shasum: {SHASUM} + integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + total files: 3 + + Published to http://localhost:4874 with tag "latest" @@ -290,60 +296,66 @@ describe('nx release', () => { > nx run {project-name}:release-publish - {project-name}: 📦 @proj/{project-name}@1000.0.0 - {project-name}: === Tarball Contents === - {project-name}: XXB index.js - {project-name}: XXXB package.json - {project-name}: XXB project.json - {project-name}: === Tarball Details === - {project-name}: name: @proj/{project-name} - {project-name}: version: 1000.0.0 - {project-name}: filename: proj-{project-name}-1000.0.0.tgz - {project-name}: package size: XXXB - {project-name}: unpacked size: XXXB - {project-name}: shasum: {SHASUM} - {project-name}: integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - {project-name}: total files: 3 - {project-name}: - {project-name}: Published to ${customRegistryUrl} with tag "next" + + 📦 @proj/{project-name}@1000.0.0 + === Tarball Contents === + + XXB index.js + XXXB package.json + XXB project.json + === Tarball Details === + name: @proj/{project-name} + version: 1000.0.0 + filename: proj-{project-name}-1000.0.0.tgz + package size: XXXB + unpacked size: XXXB + shasum: {SHASUM} + integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + total files: 3 + + Published to http://localhost:7190 with tag "next" > nx run {project-name}:release-publish - {project-name}: 📦 @proj/{project-name}@1000.0.0 - {project-name}: === Tarball Contents === - {project-name}: XXB index.js - {project-name}: XXXB package.json - {project-name}: XXB project.json - {project-name}: === Tarball Details === - {project-name}: name: @proj/{project-name} - {project-name}: version: 1000.0.0 - {project-name}: filename: proj-{project-name}-1000.0.0.tgz - {project-name}: package size: XXXB - {project-name}: unpacked size: XXXB - {project-name}: shasum: {SHASUM} - {project-name}: integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - {project-name}: total files: 3 - {project-name}: - {project-name}: Published to ${customRegistryUrl} with tag "next" + + 📦 @proj/{project-name}@1000.0.0 + === Tarball Contents === + + XXB index.js + XXXB package.json + XXB project.json + === Tarball Details === + name: @proj/{project-name} + version: 1000.0.0 + filename: proj-{project-name}-1000.0.0.tgz + package size: XXXB + unpacked size: XXXB + shasum: {SHASUM} + integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + total files: 3 + + Published to http://localhost:7190 with tag "next" > nx run {project-name}:release-publish - {project-name}: 📦 @proj/{project-name}@1000.0.0 - {project-name}: === Tarball Contents === - {project-name}: XXB index.js - {project-name}: XXXB package.json - {project-name}: XXB project.json - {project-name}: === Tarball Details === - {project-name}: name: @proj/{project-name} - {project-name}: version: 1000.0.0 - {project-name}: filename: proj-{project-name}-1000.0.0.tgz - {project-name}: package size: XXXB - {project-name}: unpacked size: XXXB - {project-name}: shasum: {SHASUM} - {project-name}: integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - {project-name}: total files: 3 - {project-name}: - {project-name}: Published to ${customRegistryUrl} with tag "next" + + 📦 @proj/{project-name}@1000.0.0 + === Tarball Contents === + + XXB index.js + XXXB package.json + XXB project.json + === Tarball Details === + name: @proj/{project-name} + version: 1000.0.0 + filename: proj-{project-name}-1000.0.0.tgz + package size: XXXB + unpacked size: XXXB + shasum: {SHASUM} + integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + total files: 3 + + Published to http://localhost:7190 with tag "next" From fb2fcad4ed95d40ed5590c9e9928be3388816667 Mon Sep 17 00:00:00 2001 From: James Henry Date: Sun, 17 Sep 2023 15:44:38 +0400 Subject: [PATCH 12/13] chore(core): fix snapshots --- e2e/release/src/release.test.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/e2e/release/src/release.test.ts b/e2e/release/src/release.test.ts index 0a2a7a41379e5..1fc2d5c20477c 100644 --- a/e2e/release/src/release.test.ts +++ b/e2e/release/src/release.test.ts @@ -136,7 +136,7 @@ describe('nx release', () => { integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX total files: 3 - Published to http://localhost:4874 with tag "latest" + Published to ${e2eRegistryUrl} with tag "latest" > nx run {project-name}:release-publish @@ -157,7 +157,7 @@ describe('nx release', () => { integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX total files: 3 - Published to http://localhost:4874 with tag "latest" + Published to ${e2eRegistryUrl} with tag "latest" > nx run {project-name}:release-publish @@ -178,7 +178,7 @@ describe('nx release', () => { integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX total files: 3 - Published to http://localhost:4874 with tag "latest" + Published to ${e2eRegistryUrl} with tag "latest" @@ -289,7 +289,7 @@ describe('nx release', () => { - {project-name} With additional flags: - --registry=http://localhost:7190 + --registry=${customRegistryUrl} --tag=next @@ -313,7 +313,7 @@ describe('nx release', () => { integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX total files: 3 - Published to http://localhost:7190 with tag "next" + Published to ${customRegistryUrl} with tag "next" > nx run {project-name}:release-publish @@ -334,7 +334,7 @@ describe('nx release', () => { integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX total files: 3 - Published to http://localhost:7190 with tag "next" + Published to ${customRegistryUrl} with tag "next" > nx run {project-name}:release-publish @@ -355,7 +355,7 @@ describe('nx release', () => { integrity: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX total files: 3 - Published to http://localhost:7190 with tag "next" + Published to ${customRegistryUrl} with tag "next" From 50db44270bcc1aae7a7a02c12de647539f5e3ed6 Mon Sep 17 00:00:00 2001 From: James Henry Date: Mon, 18 Sep 2023 20:12:49 +0400 Subject: [PATCH 13/13] chore(core): namespace publish target further, support preid --- docs/generated/cli/release.md | 6 +++ .../js/generators/release-version.json | 4 ++ .../packages/nx/documents/release.md | 6 +++ e2e/release/src/release.test.ts | 50 +++++++++---------- .../release-version/release-version.ts | 3 +- .../generators/release-version/schema.json | 4 ++ .../plugins/package-json-workspaces.spec.ts | 12 ++--- .../command-line/release/command-object.ts | 18 +++++-- .../config/create-release-groups.spec.ts | 12 ++--- .../release/config/create-release-groups.ts | 2 +- .../nx/src/command-line/release/publish.ts | 8 +-- .../src/command-line/release/utils/semver.ts | 5 +- .../nx/src/command-line/release/version.ts | 16 +++--- packages/nx/src/config/workspaces.spec.ts | 16 +++--- .../build-nodes/project-json.spec.ts | 8 +-- packages/nx/src/utils/package-json.spec.ts | 12 ++--- packages/nx/src/utils/package-json.ts | 8 +-- 17 files changed, 111 insertions(+), 79 deletions(-) diff --git a/docs/generated/cli/release.md b/docs/generated/cli/release.md index 0fabd6ec0d58f..3b7471d9cbd3b 100644 --- a/docs/generated/cli/release.md +++ b/docs/generated/cli/release.md @@ -73,6 +73,12 @@ Type: `boolean` Show help +##### preid + +Type: `string` + +The optional prerelease identifier to apply to the version, in the case that specifier has been set to prerelease. + ##### specifier Type: `string` diff --git a/docs/generated/packages/js/generators/release-version.json b/docs/generated/packages/js/generators/release-version.json index 5d002ed9538ab..4068844d0caf2 100644 --- a/docs/generated/packages/js/generators/release-version.json +++ b/docs/generated/packages/js/generators/release-version.json @@ -22,6 +22,10 @@ "type": "string", "description": "Exact version or semver keyword to apply to the selected release group. NOTE: This should be set on the release group level, not the project level." }, + "preid": { + "type": "string", + "description": "The optional prerelease identifier to apply to the version, in the case that specifier has been set to prerelease." + }, "packageRoot": { "type": "string", "description": "The root directory of the directory (containing a manifest file at its root) to publish. Defaults to the project root" diff --git a/docs/generated/packages/nx/documents/release.md b/docs/generated/packages/nx/documents/release.md index 0fabd6ec0d58f..3b7471d9cbd3b 100644 --- a/docs/generated/packages/nx/documents/release.md +++ b/docs/generated/packages/nx/documents/release.md @@ -73,6 +73,12 @@ Type: `boolean` Show help +##### preid + +Type: `string` + +The optional prerelease identifier to apply to the version, in the case that specifier has been set to prerelease. + ##### specifier Type: `string` diff --git a/e2e/release/src/release.test.ts b/e2e/release/src/release.test.ts index 1fc2d5c20477c..a170481b466a7 100644 --- a/e2e/release/src/release.test.ts +++ b/e2e/release/src/release.test.ts @@ -109,7 +109,7 @@ describe('nx release', () => { const publishOutput = runCLI(`release publish`); expect(publishOutput).toMatchInlineSnapshot(` - > NX Running target release-publish for 3 projects: + > NX Running target nx-release-publish for 3 projects: - {project-name} - {project-name} @@ -117,7 +117,7 @@ describe('nx release', () => { - > nx run {project-name}:release-publish + > nx run {project-name}:nx-release-publish 📦 @proj/{project-name}@999.9.9 @@ -138,7 +138,7 @@ describe('nx release', () => { Published to ${e2eRegistryUrl} with tag "latest" - > nx run {project-name}:release-publish + > nx run {project-name}:nx-release-publish 📦 @proj/{project-name}@999.9.9 @@ -159,7 +159,7 @@ describe('nx release', () => { Published to ${e2eRegistryUrl} with tag "latest" - > nx run {project-name}:release-publish + > nx run {project-name}:nx-release-publish 📦 @proj/{project-name}@999.9.9 @@ -182,7 +182,7 @@ describe('nx release', () => { - > NX Successfully ran target release-publish for 3 projects + > NX Successfully ran target nx-release-publish for 3 projects @@ -232,7 +232,7 @@ describe('nx release', () => { (output) => output.includes(`warn --- http address`) ); - const versionOutput2 = runCLI(`release version major`); // version using semver keyword this time + const versionOutput2 = runCLI(`release version premajor --preid next`); // version using semver keyword this time (and custom preid) expect( versionOutput2.match(/Running release version for project: my-pkg-\d*/g) @@ -265,14 +265,14 @@ describe('nx release', () => { expect( versionOutput2.match( - /New version 1000.0.0 written to my-pkg-\d*\/package.json/g + /New version 1000.0.0-next.0 written to my-pkg-\d*\/package.json/g ).length ).toEqual(3); // Only one dependency relationship exists, so this log should only match once expect( versionOutput2.match( - /Applying new version 1000.0.0 to 1 package which depends on my-pkg-\d*/g + /Applying new version 1000.0.0-next.0 to 1 package which depends on my-pkg-\d*/g ).length ).toEqual(1); @@ -282,7 +282,7 @@ describe('nx release', () => { ); expect(publishOutput2).toMatchInlineSnapshot(` - > NX Running target release-publish for 3 projects: + > NX Running target nx-release-publish for 3 projects: - {project-name} - {project-name} @@ -294,10 +294,10 @@ describe('nx release', () => { - > nx run {project-name}:release-publish + > nx run {project-name}:nx-release-publish - 📦 @proj/{project-name}@1000.0.0 + 📦 @proj/{project-name}@1000.0.0-next.0 === Tarball Contents === XXB index.js @@ -305,8 +305,8 @@ describe('nx release', () => { XXB project.json === Tarball Details === name: @proj/{project-name} - version: 1000.0.0 - filename: proj-{project-name}-1000.0.0.tgz + version: 1000.0.0-next.0 + filename: proj-{project-name}-1000.0.0-next.0.tgz package size: XXXB unpacked size: XXXB shasum: {SHASUM} @@ -315,10 +315,10 @@ describe('nx release', () => { Published to ${customRegistryUrl} with tag "next" - > nx run {project-name}:release-publish + > nx run {project-name}:nx-release-publish - 📦 @proj/{project-name}@1000.0.0 + 📦 @proj/{project-name}@1000.0.0-next.0 === Tarball Contents === XXB index.js @@ -326,8 +326,8 @@ describe('nx release', () => { XXB project.json === Tarball Details === name: @proj/{project-name} - version: 1000.0.0 - filename: proj-{project-name}-1000.0.0.tgz + version: 1000.0.0-next.0 + filename: proj-{project-name}-1000.0.0-next.0.tgz package size: XXXB unpacked size: XXXB shasum: {SHASUM} @@ -336,10 +336,10 @@ describe('nx release', () => { Published to ${customRegistryUrl} with tag "next" - > nx run {project-name}:release-publish + > nx run {project-name}:nx-release-publish - 📦 @proj/{project-name}@1000.0.0 + 📦 @proj/{project-name}@1000.0.0-next.0 === Tarball Contents === XXB index.js @@ -347,8 +347,8 @@ describe('nx release', () => { XXB project.json === Tarball Details === name: @proj/{project-name} - version: 1000.0.0 - filename: proj-{project-name}-1000.0.0.tgz + version: 1000.0.0-next.0 + filename: proj-{project-name}-1000.0.0-next.0.tgz package size: XXXB unpacked size: XXXB shasum: {SHASUM} @@ -359,7 +359,7 @@ describe('nx release', () => { - > NX Successfully ran target release-publish for 3 projects + > NX Successfully ran target nx-release-publish for 3 projects @@ -371,21 +371,21 @@ describe('nx release', () => { ) .toString() .trim() - ).toEqual('1000.0.0'); + ).toEqual('1000.0.0-next.0'); expect( execSync( `npm view @proj/${pkg2}@next version --registry=${customRegistryUrl}` ) .toString() .trim() - ).toEqual('1000.0.0'); + ).toEqual('1000.0.0-next.0'); expect( execSync( `npm view @proj/${pkg3}@next version --registry=${customRegistryUrl}` ) .toString() .trim() - ).toEqual('1000.0.0'); + ).toEqual('1000.0.0-next.0'); // port and process cleanup await killProcessAndPorts(process.pid, verdaccioPort); diff --git a/packages/js/src/generators/release-version/release-version.ts b/packages/js/src/generators/release-version/release-version.ts index fe2a185a7b344..df141829f614a 100644 --- a/packages/js/src/generators/release-version/release-version.ts +++ b/packages/js/src/generators/release-version/release-version.ts @@ -143,7 +143,8 @@ To fix this you will either need to add a package.json file at that location, or const newVersion = deriveNewSemverVersion( currentVersion, - options.specifier + options.specifier, + options.preid ); writeJson(tree, packageJsonPath, { diff --git a/packages/js/src/generators/release-version/schema.json b/packages/js/src/generators/release-version/schema.json index 94d7755f2e13d..58989ef57c735 100644 --- a/packages/js/src/generators/release-version/schema.json +++ b/packages/js/src/generators/release-version/schema.json @@ -21,6 +21,10 @@ "type": "string", "description": "Exact version or semver keyword to apply to the selected release group. NOTE: This should be set on the release group level, not the project level." }, + "preid": { + "type": "string", + "description": "The optional prerelease identifier to apply to the version, in the case that specifier has been set to prerelease." + }, "packageRoot": { "type": "string", "description": "The root directory of the directory (containing a manifest file at its root) to publish. Defaults to the project root" diff --git a/packages/nx/plugins/package-json-workspaces.spec.ts b/packages/nx/plugins/package-json-workspaces.spec.ts index 2bc5eb630b58c..99ee379093ca2 100644 --- a/packages/nx/plugins/package-json-workspaces.spec.ts +++ b/packages/nx/plugins/package-json-workspaces.spec.ts @@ -52,9 +52,9 @@ describe('nx package.json workspaces plugin', () => { "script": "echo", }, }, - "release-publish": { + "nx-release-publish": { "dependsOn": [ - "^release-publish", + "^nx-release-publish", ], "executor": "@nx/js:release-publish", "options": {}, @@ -74,9 +74,9 @@ describe('nx package.json workspaces plugin', () => { "root": "packages/lib-a", "sourceRoot": "packages/lib-a", "targets": { - "release-publish": { + "nx-release-publish": { "dependsOn": [ - "^release-publish", + "^nx-release-publish", ], "executor": "@nx/js:release-publish", "options": {}, @@ -118,9 +118,9 @@ describe('nx package.json workspaces plugin', () => { "{projectRoot}/dist", ], }, - "release-publish": { + "nx-release-publish": { "dependsOn": [ - "^release-publish", + "^nx-release-publish", ], "executor": "@nx/js:release-publish", "options": {}, diff --git a/packages/nx/src/command-line/release/command-object.ts b/packages/nx/src/command-line/release/command-object.ts index ba39eb0246e96..309c8b54e2b8f 100644 --- a/packages/nx/src/command-line/release/command-object.ts +++ b/packages/nx/src/command-line/release/command-object.ts @@ -16,6 +16,7 @@ export interface NxReleaseArgs { export type VersionOptions = NxReleaseArgs & { specifier?: string; + preid?: string; }; export type ChangelogOptions = NxReleaseArgs & { @@ -102,11 +103,18 @@ const versionCommand: CommandModule = { describe: 'Create a version and release for one or more applications and libraries', builder: (yargs) => - yargs.positional('specifier', { - type: 'string', - describe: - 'Exact version or semver keyword to apply to the selected release group.', - }), + yargs + .positional('specifier', { + type: 'string', + describe: + 'Exact version or semver keyword to apply to the selected release group.', + }) + .option('preid', { + type: 'string', + describe: + 'The optional prerelease identifier to apply to the version, in the case that specifier has been set to prerelease.', + default: '', + }), handler: (args) => import('./version').then((m) => m.versionHandler(args)), }; diff --git a/packages/nx/src/command-line/release/config/create-release-groups.spec.ts b/packages/nx/src/command-line/release/config/create-release-groups.spec.ts index d59f9c4221f8d..3193e0e90d36a 100644 --- a/packages/nx/src/command-line/release/config/create-release-groups.spec.ts +++ b/packages/nx/src/command-line/release/config/create-release-groups.spec.ts @@ -13,7 +13,7 @@ describe('create-release-groups', () => { data: { root: 'libs/lib-a', targets: { - 'release-publish': {}, + 'nx-release-publish': {}, }, } as any, }, @@ -23,7 +23,7 @@ describe('create-release-groups', () => { data: { root: 'libs/lib-b', targets: { - 'release-publish': {}, + 'nx-release-publish': {}, }, } as any, }, @@ -195,7 +195,7 @@ describe('create-release-groups', () => { projects: '*', // using string form to ensure that is supported in addition to array form }, }, - 'release-publish' + 'nx-release-publish' ); expect(res).toMatchInlineSnapshot(` { @@ -205,7 +205,7 @@ describe('create-release-groups', () => { "projects": [ "project-without-target", ], - "targetName": "release-publish", + "targetName": "nx-release-publish", }, }, "releaseGroups": [], @@ -228,7 +228,7 @@ describe('create-release-groups', () => { }, }, {}, - 'release-publish' + 'nx-release-publish' ); expect(res2).toMatchInlineSnapshot(` { @@ -238,7 +238,7 @@ describe('create-release-groups', () => { "projects": [ "another-project-without-target", ], - "targetName": "release-publish", + "targetName": "nx-release-publish", }, }, "releaseGroups": [], diff --git a/packages/nx/src/command-line/release/config/create-release-groups.ts b/packages/nx/src/command-line/release/config/create-release-groups.ts index 9406b535d39ea..a130abd1ea107 100644 --- a/packages/nx/src/command-line/release/config/create-release-groups.ts +++ b/packages/nx/src/command-line/release/config/create-release-groups.ts @@ -31,7 +31,7 @@ export const CATCH_ALL_RELEASE_GROUP = '__default__'; export async function createReleaseGroups( projectGraph: ProjectGraph, userSpecifiedGroups: NxJsonConfiguration['release']['groups'] = {}, - requiredTargetName?: 'release-publish' + requiredTargetName?: 'nx-release-publish' ): Promise<{ error: null | CreateReleaseGroupsError; releaseGroups: ReleaseGroup[]; diff --git a/packages/nx/src/command-line/release/publish.ts b/packages/nx/src/command-line/release/publish.ts index 40de17c5a8aff..0646c38e888b2 100644 --- a/packages/nx/src/command-line/release/publish.ts +++ b/packages/nx/src/command-line/release/publish.ts @@ -177,6 +177,8 @@ async function runPublishOnProjects( process.env.NX_VERBOSE_LOGGING = 'true'; } + const targets = ['nx-release-publish']; + if (args.graph) { const file = readGraphFileFromGraphArg(args); const projectNames = projectsToRun.map((t) => t.name); @@ -186,7 +188,7 @@ async function runPublishOnProjects( all: false, open: true, view: 'tasks', - targets: ['release-publish'], + targets, projects: projectNames, file, }, @@ -194,14 +196,14 @@ async function runPublishOnProjects( ); } else { /** - * Run the relevant release-publish executor on each of the selected projects. + * Run the relevant nx-release-publish executor on each of the selected projects. */ const status = await runCommand( projectsToRun, projectGraph, { nxJson }, { - targets: ['release-publish'], + targets, outputStyle: 'static', ...(args as any), }, diff --git a/packages/nx/src/command-line/release/utils/semver.ts b/packages/nx/src/command-line/release/utils/semver.ts index 7157ba0c5e09e..7e4a2daf5c066 100644 --- a/packages/nx/src/command-line/release/utils/semver.ts +++ b/packages/nx/src/command-line/release/utils/semver.ts @@ -6,7 +6,8 @@ export function isRelativeVersionKeyword(val: string): val is ReleaseType { export function deriveNewSemverVersion( currentSemverVersion: string, - semverSpecifier: string + semverSpecifier: string, + preid?: string ) { if (!valid(currentSemverVersion)) { throw new Error( @@ -17,7 +18,7 @@ export function deriveNewSemverVersion( let newVersion = semverSpecifier; if (isRelativeVersionKeyword(semverSpecifier)) { // Derive the new version from the current version combined with the new version specifier. - const derivedVersion = inc(currentSemverVersion, semverSpecifier); + const derivedVersion = inc(currentSemverVersion, semverSpecifier, preid); if (!derivedVersion) { throw new Error( `Unable to derive new version from current version "${currentSemverVersion}" and version specifier "${semverSpecifier}"` diff --git a/packages/nx/src/command-line/release/version.ts b/packages/nx/src/command-line/release/version.ts index 346a479107241..005d8debb5353 100644 --- a/packages/nx/src/command-line/release/version.ts +++ b/packages/nx/src/command-line/release/version.ts @@ -21,7 +21,6 @@ import { createProjectGraphAsync, readProjectsConfigurationFromProjectGraph, } from '../../project-graph/project-graph'; -import { NxArgs } from '../../utils/command-line-utils'; import { findMatchingProjects } from '../../utils/find-matching-projects'; import { combineOptionsForGenerator } from '../../utils/params'; import { parseGeneratorString } from '../generate/generate'; @@ -45,6 +44,7 @@ export interface ReleaseVersionGeneratorSchema { projects: ProjectGraphProjectNode[]; projectGraph: ProjectGraph; specifier: string; + preid?: string; packageRoot?: string; currentVersionResolver?: 'registry' | 'disk'; currentVersionResolverMetadata?: Record; @@ -54,8 +54,7 @@ export async function versionHandler(args: VersionOptions): Promise { const projectGraph = await createProjectGraphAsync({ exitOnError: true }); const nxJson = readNxJson(); - const nxArgs = args as NxArgs; - if (nxArgs.verbose) { + if (args.verbose) { process.env.NX_VERBOSE_LOGGING = 'true'; } @@ -69,7 +68,7 @@ export async function versionHandler(args: VersionOptions): Promise { return await handleCreateReleaseGroupsError(releaseGroupsData.error); } - const tree = new FsTree(workspaceRoot, nxArgs.verbose); + const tree = new FsTree(workspaceRoot, args.verbose); let { releaseGroups } = releaseGroupsData; @@ -171,7 +170,7 @@ export async function versionHandler(args: VersionOptions): Promise { await runVersionOnProjects( projectGraph, nxJson, - nxArgs, + args, tree, generatorData, Array.from(releaseGroupToFilteredProjects.get(releaseGroup)), @@ -227,7 +226,7 @@ export async function versionHandler(args: VersionOptions): Promise { await runVersionOnProjects( projectGraph, nxJson, - nxArgs, + args, tree, generatorData, releaseGroup.projects, @@ -243,7 +242,7 @@ export async function versionHandler(args: VersionOptions): Promise { async function runVersionOnProjects( projectGraph: ProjectGraph, nxJson: NxJsonConfiguration, - nxArgs: NxArgs, + args: VersionOptions, tree: Tree, generatorData: GeneratorData, projectNames: string[], @@ -271,6 +270,7 @@ async function runVersionOnProjects( projects: projectNames.map((p) => projectGraph.nodes[p]), projectGraph, specifier: newVersionSpecifier, + preid: args.preid, ...generatorData.configGeneratorOptions, }; @@ -285,7 +285,7 @@ async function runVersionOnProjects( false, null, relative(process.cwd(), workspaceRoot), - nxArgs.verbose + args.verbose ); const releaseVersionGenerator = generatorData.implementationFactory(); diff --git a/packages/nx/src/config/workspaces.spec.ts b/packages/nx/src/config/workspaces.spec.ts index f38f9e1e295cf..16c8511ac86fc 100644 --- a/packages/nx/src/config/workspaces.spec.ts +++ b/packages/nx/src/config/workspaces.spec.ts @@ -10,8 +10,8 @@ const libConfig = (root, name?: string) => ({ root: `libs/${root}`, sourceRoot: `libs/${root}/src`, targets: { - 'release-publish': { - dependsOn: ['^release-publish'], + 'nx-release-publish': { + dependsOn: ['^nx-release-publish'], executor: '@nx/js:release-publish', options: {}, }, @@ -24,8 +24,8 @@ const packageLibConfig = (root, name?: string) => ({ sourceRoot: root, projectType: 'library', targets: { - 'release-publish': { - dependsOn: ['^release-publish'], + 'nx-release-publish': { + dependsOn: ['^nx-release-publish'], executor: '@nx/js:release-publish', options: {}, }, @@ -99,8 +99,8 @@ describe('Workspaces', () => { sourceRoot: 'libs/lib1/src', projectType: 'library', targets: { - 'release-publish': { - dependsOn: ['^release-publish'], + 'nx-release-publish': { + dependsOn: ['^nx-release-publish'], executor: '@nx/js:release-publish', options: {}, }, @@ -146,8 +146,8 @@ describe('Workspaces', () => { sourceRoot: 'packages/my-package', projectType: 'library', targets: { - 'release-publish': { - dependsOn: ['^release-publish'], + 'nx-release-publish': { + dependsOn: ['^nx-release-publish'], executor: '@nx/js:release-publish', options: {}, }, diff --git a/packages/nx/src/plugins/project-json/build-nodes/project-json.spec.ts b/packages/nx/src/plugins/project-json/build-nodes/project-json.spec.ts index d09fbef6be10a..51b8922858b98 100644 --- a/packages/nx/src/plugins/project-json/build-nodes/project-json.spec.ts +++ b/packages/nx/src/plugins/project-json/build-nodes/project-json.spec.ts @@ -12,8 +12,8 @@ import { CreateNodesContext } from '../../../utils/nx-plugin'; const { createNodes } = CreateProjectJsonProjectsPlugin; const defaultReleasePublishTarget = { - 'release-publish': { - dependsOn: ['^release-publish'], + 'nx-release-publish': { + dependsOn: ['^nx-release-publish'], executor: '@nx/js:release-publish', options: {}, }, @@ -80,9 +80,9 @@ describe('nx project.json plugin', () => { "executor": "nx:run-commands", "options": {}, }, - "release-publish": { + "nx-release-publish": { "dependsOn": [ - "^release-publish", + "^nx-release-publish", ], "executor": "@nx/js:release-publish", "options": {}, diff --git a/packages/nx/src/utils/package-json.spec.ts b/packages/nx/src/utils/package-json.spec.ts index 57dbd400f6d02..b4ea5a0e6db06 100644 --- a/packages/nx/src/utils/package-json.spec.ts +++ b/packages/nx/src/utils/package-json.spec.ts @@ -70,8 +70,8 @@ describe('readTargetsFromPackageJson', () => { script: 'build', }, }, - 'release-publish': { - dependsOn: ['^release-publish'], + 'nx-release-publish': { + dependsOn: ['^nx-release-publish'], executor: '@nx/js:release-publish', options: {}, }, @@ -95,8 +95,8 @@ describe('readTargetsFromPackageJson', () => { }); expect(result).toEqual({ build: { ...packageJsonBuildTarget, outputs: ['custom'] }, - 'release-publish': { - dependsOn: ['^release-publish'], + 'nx-release-publish': { + dependsOn: ['^nx-release-publish'], executor: '@nx/js:release-publish', options: {}, }, @@ -121,8 +121,8 @@ describe('readTargetsFromPackageJson', () => { executor: 'nx:run-script', options: { script: 'test' }, }, - 'release-publish': { - dependsOn: ['^release-publish'], + 'nx-release-publish': { + dependsOn: ['^nx-release-publish'], executor: '@nx/js:release-publish', options: {}, }, diff --git a/packages/nx/src/utils/package-json.ts b/packages/nx/src/utils/package-json.ts index 09e4c18dd650d..a3b93bf1767cf 100644 --- a/packages/nx/src/utils/package-json.ts +++ b/packages/nx/src/utils/package-json.ts @@ -142,10 +142,10 @@ export function readTargetsFromPackageJson({ scripts, nx }: PackageJson) { } }); - // Add implicit release-publish target for all package.json files to allow for lightweight configuration for package based repos - if (!res['release-publish']) { - res['release-publish'] = { - dependsOn: ['^release-publish'], + // Add implicit nx-release-publish target for all package.json files to allow for lightweight configuration for package based repos + if (!res['nx-release-publish']) { + res['nx-release-publish'] = { + dependsOn: ['^nx-release-publish'], executor: '@nx/js:release-publish', options: {}, };