@angular/cli 22.2.1 → 22.3.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/ng.js +7 -10
- package/bin/version.js +98 -0
- package/index.d.ts +19 -0
- package/lib/chunk-5AASRQKS.js +85 -0
- package/lib/chunk-A2VIYA2E.js +165 -0
- package/lib/chunk-CAZUOCTC.js +225 -0
- package/lib/chunk-DHWVZMLH.js +206 -0
- package/lib/chunk-FZ5GFCWU.js +483 -0
- package/lib/chunk-G7TRU43D.js +42 -0
- package/lib/chunk-GHUUJYOY.js +40 -0
- package/lib/chunk-JBLF2TH3.js +267 -0
- package/lib/chunk-Q67GOPL7.js +380 -0
- package/lib/chunk-SN4KY4Z3.js +24 -0
- package/lib/chunk-XFL2J3CJ.js +24 -0
- package/lib/chunk-XG3HVNIL.js +59 -0
- package/lib/chunk-YM7ILCS5.js +2573 -0
- package/lib/cli/index.js +353 -105
- package/lib/cli-4CMZ6KMR.js +48 -0
- package/lib/cli-4Q7DGTBA.js +33 -0
- package/lib/cli-6AHY7ADW.js +96 -0
- package/lib/cli-A5UAJDO6.js +135 -0
- package/lib/cli-ACLGUIBI.js +2531 -0
- package/lib/cli-BQRFWIMG.js +35 -0
- package/lib/cli-CWICUPZW.js +42 -0
- package/lib/cli-DWQUM3M2.js +29 -0
- package/lib/cli-L4TM4JH3.js +88 -0
- package/lib/cli-LYBZEMDR.js +96 -0
- package/lib/cli-PDCEX7HQ.js +605 -0
- package/lib/cli-PJVTDBQM.js +51 -0
- package/lib/cli-PRIRL3WP.js +185 -0
- package/lib/cli-PU5VH7JB.js +189 -0
- package/lib/cli-QUH44NUB.js +68 -0
- package/lib/cli-VVITNTBC.js +50 -0
- package/lib/cli-XM4L4PP4.js +1651 -0
- package/lib/cli-Y2ECUR33.js +33 -0
- package/lib/cli-YDSMJOSO.js +182 -0
- package/lib/color-SJPGXZVA.js +8 -0
- package/lib/config/schema.json +204 -0
- package/lib/config-QXK7SSVG.js +22 -0
- package/lib/init.js +91 -180
- package/package.json +20 -15
- package/lib/cli/index.d.ts +0 -11
- package/lib/cli/index.js.map +0 -1
- package/lib/config/workspace-schema.d.ts +0 -1025
- package/lib/config/workspace-schema.js +0 -131
- package/lib/config/workspace-schema.js.map +0 -1
- package/lib/init.d.ts +0 -8
- package/lib/init.js.map +0 -1
- package/src/analytics/analytics-collector.d.ts +0 -35
- package/src/analytics/analytics-collector.js +0 -195
- package/src/analytics/analytics-collector.js.map +0 -1
- package/src/analytics/analytics-parameters.d.ts +0 -101
- package/src/analytics/analytics-parameters.js +0 -107
- package/src/analytics/analytics-parameters.js.map +0 -1
- package/src/analytics/analytics.d.ts +0 -27
- package/src/analytics/analytics.js +0 -183
- package/src/analytics/analytics.js.map +0 -1
- package/src/command-builder/architect-base-command-module.d.ts +0 -30
- package/src/command-builder/architect-base-command-module.js +0 -244
- package/src/command-builder/architect-base-command-module.js.map +0 -1
- package/src/command-builder/architect-command-module.d.ts +0 -28
- package/src/command-builder/architect-command-module.js +0 -218
- package/src/command-builder/architect-command-module.js.map +0 -1
- package/src/command-builder/command-module.d.ts +0 -73
- package/src/command-builder/command-module.js +0 -260
- package/src/command-builder/command-module.js.map +0 -1
- package/src/command-builder/command-runner.d.ts +0 -9
- package/src/command-builder/command-runner.js +0 -202
- package/src/command-builder/command-runner.js.map +0 -1
- package/src/command-builder/definitions.d.ts +0 -41
- package/src/command-builder/definitions.js +0 -20
- package/src/command-builder/definitions.js.map +0 -1
- package/src/command-builder/schematics-command-module.d.ts +0 -41
- package/src/command-builder/schematics-command-module.js +0 -408
- package/src/command-builder/schematics-command-module.js.map +0 -1
- package/src/command-builder/utilities/command.d.ts +0 -13
- package/src/command-builder/utilities/command.js +0 -39
- package/src/command-builder/utilities/command.js.map +0 -1
- package/src/command-builder/utilities/json-help.d.ts +0 -37
- package/src/command-builder/utilities/json-help.js +0 -92
- package/src/command-builder/utilities/json-help.js.map +0 -1
- package/src/command-builder/utilities/json-schema.d.ts +0 -64
- package/src/command-builder/utilities/json-schema.js +0 -349
- package/src/command-builder/utilities/json-schema.js.map +0 -1
- package/src/command-builder/utilities/normalize-options-middleware.d.ts +0 -18
- package/src/command-builder/utilities/normalize-options-middleware.js +0 -37
- package/src/command-builder/utilities/normalize-options-middleware.js.map +0 -1
- package/src/command-builder/utilities/schematic-engine-host.d.ts +0 -15
- package/src/command-builder/utilities/schematic-engine-host.js +0 -179
- package/src/command-builder/utilities/schematic-engine-host.js.map +0 -1
- package/src/command-builder/utilities/schematic-workflow.d.ts +0 -14
- package/src/command-builder/utilities/schematic-workflow.js +0 -70
- package/src/command-builder/utilities/schematic-workflow.js.map +0 -1
- package/src/commands/add/cli.d.ts +0 -41
- package/src/commands/add/cli.js +0 -705
- package/src/commands/add/cli.js.map +0 -1
- package/src/commands/add/long-description.md +0 -7
- package/src/commands/analytics/cli.d.ts +0 -16
- package/src/commands/analytics/cli.js +0 -34
- package/src/commands/analytics/cli.js.map +0 -1
- package/src/commands/analytics/info/cli.d.ts +0 -16
- package/src/commands/analytics/info/cli.js +0 -25
- package/src/commands/analytics/info/cli.js.map +0 -1
- package/src/commands/analytics/long-description.md +0 -20
- package/src/commands/analytics/settings/cli.d.ts +0 -35
- package/src/commands/analytics/settings/cli.js +0 -54
- package/src/commands/analytics/settings/cli.js.map +0 -1
- package/src/commands/build/cli.d.ts +0 -16
- package/src/commands/build/cli.js +0 -21
- package/src/commands/build/cli.js.map +0 -1
- package/src/commands/build/long-description.md +0 -18
- package/src/commands/cache/clean/cli.d.ts +0 -17
- package/src/commands/cache/clean/cli.js +0 -32
- package/src/commands/cache/clean/cli.js.map +0 -1
- package/src/commands/cache/cli.d.ts +0 -17
- package/src/commands/cache/cli.js +0 -36
- package/src/commands/cache/cli.js.map +0 -1
- package/src/commands/cache/info/cli.d.ts +0 -20
- package/src/commands/cache/info/cli.js +0 -139
- package/src/commands/cache/info/cli.js.map +0 -1
- package/src/commands/cache/long-description.md +0 -53
- package/src/commands/cache/settings/cli.d.ts +0 -27
- package/src/commands/cache/settings/cli.js +0 -41
- package/src/commands/cache/settings/cli.js.map +0 -1
- package/src/commands/cache/utilities.d.ts +0 -11
- package/src/commands/cache/utilities.js +0 -90
- package/src/commands/cache/utilities.js.map +0 -1
- package/src/commands/command-config.d.ts +0 -17
- package/src/commands/command-config.js +0 -116
- package/src/commands/command-config.js.map +0 -1
- package/src/commands/completion/cli.d.ts +0 -16
- package/src/commands/completion/cli.js +0 -61
- package/src/commands/completion/cli.js.map +0 -1
- package/src/commands/completion/long-description.md +0 -67
- package/src/commands/config/cli.d.ts +0 -24
- package/src/commands/config/cli.js +0 -150
- package/src/commands/config/cli.js.map +0 -1
- package/src/commands/config/long-description.md +0 -13
- package/src/commands/deploy/cli.d.ts +0 -17
- package/src/commands/deploy/cli.js +0 -38
- package/src/commands/deploy/cli.js.map +0 -1
- package/src/commands/deploy/long-description.md +0 -22
- package/src/commands/e2e/cli.d.ts +0 -18
- package/src/commands/e2e/cli.js +0 -42
- package/src/commands/e2e/cli.js.map +0 -1
- package/src/commands/extract-i18n/cli.d.ts +0 -17
- package/src/commands/extract-i18n/cli.js +0 -48
- package/src/commands/extract-i18n/cli.js.map +0 -1
- package/src/commands/generate/cli.d.ts +0 -47
- package/src/commands/generate/cli.js +0 -189
- package/src/commands/generate/cli.js.map +0 -1
- package/src/commands/lint/cli.d.ts +0 -17
- package/src/commands/lint/cli.js +0 -25
- package/src/commands/lint/cli.js.map +0 -1
- package/src/commands/lint/long-description.md +0 -20
- package/src/commands/make-this-awesome/cli.d.ts +0 -17
- package/src/commands/make-this-awesome/cli.js +0 -36
- package/src/commands/make-this-awesome/cli.js.map +0 -1
- package/src/commands/mcp/cli.d.ts +0 -21
- package/src/commands/mcp/cli.js +0 -74
- package/src/commands/mcp/cli.js.map +0 -1
- package/src/commands/mcp/constants.d.ts +0 -10
- package/src/commands/mcp/constants.js +0 -16
- package/src/commands/mcp/constants.js.map +0 -1
- package/src/commands/mcp/devserver.d.ts +0 -85
- package/src/commands/mcp/devserver.js +0 -109
- package/src/commands/mcp/devserver.js.map +0 -1
- package/src/commands/mcp/host.d.ts +0 -103
- package/src/commands/mcp/host.js +0 -270
- package/src/commands/mcp/host.js.map +0 -1
- package/src/commands/mcp/mcp-server.d.ts +0 -38
- package/src/commands/mcp/mcp-server.js +0 -176
- package/src/commands/mcp/mcp-server.js.map +0 -1
- package/src/commands/mcp/resources/ai-tutor.md +0 -822
- package/src/commands/mcp/resources/best-practices.md +0 -59
- package/src/commands/mcp/resources/instructions.d.ts +0 -9
- package/src/commands/mcp/resources/instructions.js +0 -26
- package/src/commands/mcp/resources/instructions.js.map +0 -1
- package/src/commands/mcp/shared-options.d.ts +0 -12
- package/src/commands/mcp/shared-options.js +0 -22
- package/src/commands/mcp/shared-options.js.map +0 -1
- package/src/commands/mcp/tools/ai-tutor.d.ts +0 -12
- package/src/commands/mcp/tools/ai-tutor.js +0 -59
- package/src/commands/mcp/tools/ai-tutor.js.map +0 -1
- package/src/commands/mcp/tools/best-practices.d.ts +0 -13
- package/src/commands/mcp/tools/best-practices.js +0 -196
- package/src/commands/mcp/tools/best-practices.js.map +0 -1
- package/src/commands/mcp/tools/devserver/devserver-start.d.ts +0 -32
- package/src/commands/mcp/tools/devserver/devserver-start.js +0 -110
- package/src/commands/mcp/tools/devserver/devserver-start.js.map +0 -1
- package/src/commands/mcp/tools/devserver/devserver-stop.d.ts +0 -31
- package/src/commands/mcp/tools/devserver/devserver-stop.js +0 -69
- package/src/commands/mcp/tools/devserver/devserver-stop.js.map +0 -1
- package/src/commands/mcp/tools/devserver/devserver-wait-for-build.d.ts +0 -41
- package/src/commands/mcp/tools/devserver/devserver-wait-for-build.js +0 -105
- package/src/commands/mcp/tools/devserver/devserver-wait-for-build.js.map +0 -1
- package/src/commands/mcp/tools/doc-search.d.ts +0 -21
- package/src/commands/mcp/tools/doc-search.js +0 -307
- package/src/commands/mcp/tools/doc-search.js.map +0 -1
- package/src/commands/mcp/tools/onpush-zoneless-migration/analyze-for-unsupported-zone-uses.d.ts +0 -17
- package/src/commands/mcp/tools/onpush-zoneless-migration/analyze-for-unsupported-zone-uses.js +0 -62
- package/src/commands/mcp/tools/onpush-zoneless-migration/analyze-for-unsupported-zone-uses.js.map +0 -1
- package/src/commands/mcp/tools/onpush-zoneless-migration/migrate-single-file.d.ts +0 -12
- package/src/commands/mcp/tools/onpush-zoneless-migration/migrate-single-file.js +0 -70
- package/src/commands/mcp/tools/onpush-zoneless-migration/migrate-single-file.js.map +0 -1
- package/src/commands/mcp/tools/onpush-zoneless-migration/migrate-test-file.d.ts +0 -12
- package/src/commands/mcp/tools/onpush-zoneless-migration/migrate-test-file.js +0 -60
- package/src/commands/mcp/tools/onpush-zoneless-migration/migrate-test-file.js.map +0 -1
- package/src/commands/mcp/tools/onpush-zoneless-migration/prompts.d.ts +0 -15
- package/src/commands/mcp/tools/onpush-zoneless-migration/prompts.js +0 -238
- package/src/commands/mcp/tools/onpush-zoneless-migration/prompts.js.map +0 -1
- package/src/commands/mcp/tools/onpush-zoneless-migration/send-debug-message.d.ts +0 -9
- package/src/commands/mcp/tools/onpush-zoneless-migration/send-debug-message.js +0 -14
- package/src/commands/mcp/tools/onpush-zoneless-migration/send-debug-message.js.map +0 -1
- package/src/commands/mcp/tools/onpush-zoneless-migration/ts-utils.d.ts +0 -36
- package/src/commands/mcp/tools/onpush-zoneless-migration/ts-utils.js +0 -135
- package/src/commands/mcp/tools/onpush-zoneless-migration/ts-utils.js.map +0 -1
- package/src/commands/mcp/tools/onpush-zoneless-migration/types.d.ts +0 -13
- package/src/commands/mcp/tools/onpush-zoneless-migration/types.js +0 -10
- package/src/commands/mcp/tools/onpush-zoneless-migration/types.js.map +0 -1
- package/src/commands/mcp/tools/onpush-zoneless-migration/zoneless-migration.d.ts +0 -16
- package/src/commands/mcp/tools/onpush-zoneless-migration/zoneless-migration.js +0 -215
- package/src/commands/mcp/tools/onpush-zoneless-migration/zoneless-migration.js.map +0 -1
- package/src/commands/mcp/tools/projects.d.ts +0 -48
- package/src/commands/mcp/tools/projects.js +0 -541
- package/src/commands/mcp/tools/projects.js.map +0 -1
- package/src/commands/mcp/tools/run-target/build-target-strategy.d.ts +0 -14
- package/src/commands/mcp/tools/run-target/build-target-strategy.js +0 -53
- package/src/commands/mcp/tools/run-target/build-target-strategy.js.map +0 -1
- package/src/commands/mcp/tools/run-target/generic-target-strategy.d.ts +0 -14
- package/src/commands/mcp/tools/run-target/generic-target-strategy.js +0 -63
- package/src/commands/mcp/tools/run-target/generic-target-strategy.js.map +0 -1
- package/src/commands/mcp/tools/run-target/options-serializer.d.ts +0 -13
- package/src/commands/mcp/tools/run-target/options-serializer.js +0 -41
- package/src/commands/mcp/tools/run-target/options-serializer.js.map +0 -1
- package/src/commands/mcp/tools/run-target/run-target.d.ts +0 -34
- package/src/commands/mcp/tools/run-target/run-target.js +0 -69
- package/src/commands/mcp/tools/run-target/run-target.js.map +0 -1
- package/src/commands/mcp/tools/run-target/strategy.d.ts +0 -15
- package/src/commands/mcp/tools/run-target/strategy.js +0 -10
- package/src/commands/mcp/tools/run-target/strategy.js.map +0 -1
- package/src/commands/mcp/tools/run-target/types.d.ts +0 -39
- package/src/commands/mcp/tools/run-target/types.js +0 -41
- package/src/commands/mcp/tools/run-target/types.js.map +0 -1
- package/src/commands/mcp/tools/run-target/unit-test-strategy.d.ts +0 -14
- package/src/commands/mcp/tools/run-target/unit-test-strategy.js +0 -56
- package/src/commands/mcp/tools/run-target/unit-test-strategy.js.map +0 -1
- package/src/commands/mcp/tools/tool-registry.d.ts +0 -40
- package/src/commands/mcp/tools/tool-registry.js +0 -40
- package/src/commands/mcp/tools/tool-registry.js.map +0 -1
- package/src/commands/mcp/utils.d.ts +0 -25
- package/src/commands/mcp/utils.js +0 -44
- package/src/commands/mcp/utils.js.map +0 -1
- package/src/commands/mcp/workspace-utils.d.ts +0 -55
- package/src/commands/mcp/workspace-utils.js +0 -181
- package/src/commands/mcp/workspace-utils.js.map +0 -1
- package/src/commands/new/cli.d.ts +0 -27
- package/src/commands/new/cli.js +0 -76
- package/src/commands/new/cli.js.map +0 -1
- package/src/commands/new/long-description.md +0 -15
- package/src/commands/run/cli.d.ts +0 -25
- package/src/commands/run/cli.js +0 -89
- package/src/commands/run/cli.js.map +0 -1
- package/src/commands/run/long-description.md +0 -10
- package/src/commands/serve/cli.d.ts +0 -16
- package/src/commands/serve/cli.js +0 -20
- package/src/commands/serve/cli.js.map +0 -1
- package/src/commands/test/cli.d.ts +0 -16
- package/src/commands/test/cli.js +0 -21
- package/src/commands/test/cli.js.map +0 -1
- package/src/commands/test/long-description.md +0 -2
- package/src/commands/update/cli.d.ts +0 -50
- package/src/commands/update/cli.js +0 -586
- package/src/commands/update/cli.js.map +0 -1
- package/src/commands/update/long-description.md +0 -22
- package/src/commands/update/update-resolver.d.ts +0 -75
- package/src/commands/update/update-resolver.js +0 -918
- package/src/commands/update/update-resolver.js.map +0 -1
- package/src/commands/update/utilities/cli-version.d.ts +0 -48
- package/src/commands/update/utilities/cli-version.js +0 -196
- package/src/commands/update/utilities/cli-version.js.map +0 -1
- package/src/commands/update/utilities/constants.d.ts +0 -12
- package/src/commands/update/utilities/constants.js +0 -16
- package/src/commands/update/utilities/constants.js.map +0 -1
- package/src/commands/update/utilities/git.d.ts +0 -36
- package/src/commands/update/utilities/git.js +0 -148
- package/src/commands/update/utilities/git.js.map +0 -1
- package/src/commands/update/utilities/migration.d.ts +0 -32
- package/src/commands/update/utilities/migration.js +0 -271
- package/src/commands/update/utilities/migration.js.map +0 -1
- package/src/commands/version/cli.d.ts +0 -36
- package/src/commands/version/cli.js +0 -117
- package/src/commands/version/cli.js.map +0 -1
- package/src/commands/version/version-info.d.ts +0 -46
- package/src/commands/version/version-info.js +0 -101
- package/src/commands/version/version-info.js.map +0 -1
- package/src/package-managers/discovery.d.ts +0 -23
- package/src/package-managers/discovery.js +0 -104
- package/src/package-managers/discovery.js.map +0 -1
- package/src/package-managers/error.d.ts +0 -43
- package/src/package-managers/error.js +0 -41
- package/src/package-managers/error.js.map +0 -1
- package/src/package-managers/factory.d.ts +0 -30
- package/src/package-managers/factory.js +0 -137
- package/src/package-managers/factory.js.map +0 -1
- package/src/package-managers/host.d.ts +0 -86
- package/src/package-managers/host.js +0 -91
- package/src/package-managers/host.js.map +0 -1
- package/src/package-managers/index.d.ts +0 -13
- package/src/package-managers/index.js +0 -17
- package/src/package-managers/index.js.map +0 -1
- package/src/package-managers/logger.d.ts +0 -27
- package/src/package-managers/logger.js +0 -10
- package/src/package-managers/logger.js.map +0 -1
- package/src/package-managers/package-manager-descriptor.d.ts +0 -269
- package/src/package-managers/package-manager-descriptor.js +0 -210
- package/src/package-managers/package-manager-descriptor.js.map +0 -1
- package/src/package-managers/package-manager.d.ts +0 -200
- package/src/package-managers/package-manager.js +0 -720
- package/src/package-managers/package-manager.js.map +0 -1
- package/src/package-managers/package-metadata.d.ts +0 -91
- package/src/package-managers/package-metadata.js +0 -10
- package/src/package-managers/package-metadata.js.map +0 -1
- package/src/package-managers/package-tree.d.ts +0 -23
- package/src/package-managers/package-tree.js +0 -10
- package/src/package-managers/package-tree.js.map +0 -1
- package/src/package-managers/parsers.d.ts +0 -167
- package/src/package-managers/parsers.js +0 -674
- package/src/package-managers/parsers.js.map +0 -1
- package/src/utilities/color.d.ts +0 -23
- package/src/utilities/color.js +0 -41
- package/src/utilities/color.js.map +0 -1
- package/src/utilities/completion.d.ts +0 -30
- package/src/utilities/completion.js +0 -270
- package/src/utilities/completion.js.map +0 -1
- package/src/utilities/config.d.ts +0 -38
- package/src/utilities/config.js +0 -368
- package/src/utilities/config.js.map +0 -1
- package/src/utilities/environment-options.d.ts +0 -25
- package/src/utilities/environment-options.js +0 -60
- package/src/utilities/environment-options.js.map +0 -1
- package/src/utilities/eol.d.ts +0 -20
- package/src/utilities/eol.js +0 -35
- package/src/utilities/eol.js.map +0 -1
- package/src/utilities/error.d.ts +0 -18
- package/src/utilities/error.js +0 -41
- package/src/utilities/error.js.map +0 -1
- package/src/utilities/find-up.d.ts +0 -21
- package/src/utilities/find-up.js +0 -67
- package/src/utilities/find-up.js.map +0 -1
- package/src/utilities/json-file.d.ts +0 -24
- package/src/utilities/json-file.js +0 -179
- package/src/utilities/json-file.js.map +0 -1
- package/src/utilities/log-file.d.ts +0 -13
- package/src/utilities/log-file.js +0 -28
- package/src/utilities/log-file.js.map +0 -1
- package/src/utilities/memoize.d.ts +0 -15
- package/src/utilities/memoize.js +0 -64
- package/src/utilities/memoize.js.map +0 -1
- package/src/utilities/node-version.d.ts +0 -21
- package/src/utilities/node-version.js +0 -65
- package/src/utilities/node-version.js.map +0 -1
- package/src/utilities/prettier.d.ts +0 -19
- package/src/utilities/prettier.js +0 -105
- package/src/utilities/prettier.js.map +0 -1
- package/src/utilities/project.d.ts +0 -8
- package/src/utilities/project.js +0 -81
- package/src/utilities/project.js.map +0 -1
- package/src/utilities/prompt.d.ts +0 -17
- package/src/utilities/prompt.js +0 -90
- package/src/utilities/prompt.js.map +0 -1
- package/src/utilities/tty.d.ts +0 -16
- package/src/utilities/tty.js +0 -23
- package/src/utilities/tty.js.map +0 -1
- package/src/utilities/version.d.ts +0 -16
- package/src/utilities/version.js +0 -26
- package/src/utilities/version.js.map +0 -1
|
@@ -0,0 +1,2573 @@
|
|
|
1
|
+
import {
|
|
2
|
+
VERSION,
|
|
3
|
+
analyticsDisabled,
|
|
4
|
+
forceAutocomplete,
|
|
5
|
+
forceTty,
|
|
6
|
+
isCI,
|
|
7
|
+
ngDebug
|
|
8
|
+
} from "./chunk-XG3HVNIL.js";
|
|
9
|
+
import {
|
|
10
|
+
colors
|
|
11
|
+
} from "./chunk-GHUUJYOY.js";
|
|
12
|
+
import {
|
|
13
|
+
assertIsError,
|
|
14
|
+
getWorkspace
|
|
15
|
+
} from "./chunk-FZ5GFCWU.js";
|
|
16
|
+
|
|
17
|
+
// packages/angular/cli/src/utilities/tty.js
|
|
18
|
+
function isTTY(stream = process.stdout) {
|
|
19
|
+
return forceTty ?? (!!stream.isTTY && !isCI);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// packages/angular/cli/src/utilities/completion.js
|
|
23
|
+
import { json } from "@angular-devkit/core";
|
|
24
|
+
import { execFile } from "node:child_process";
|
|
25
|
+
import * as fs from "node:fs/promises";
|
|
26
|
+
import * as path from "node:path";
|
|
27
|
+
import { env } from "node:process";
|
|
28
|
+
|
|
29
|
+
// packages/angular/cli/src/utilities/prompt.js
|
|
30
|
+
async function askConfirmation(message, defaultResponse, noTTYResponse) {
|
|
31
|
+
if (!isTTY()) {
|
|
32
|
+
return noTTYResponse ?? defaultResponse;
|
|
33
|
+
}
|
|
34
|
+
const { confirm } = await import("@inquirer/prompts");
|
|
35
|
+
const answer = await confirm({
|
|
36
|
+
message,
|
|
37
|
+
default: defaultResponse,
|
|
38
|
+
theme: {
|
|
39
|
+
prefix: ""
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
return answer;
|
|
43
|
+
}
|
|
44
|
+
async function askQuestion(message, choices, defaultResponseIndex, noTTYResponse) {
|
|
45
|
+
if (!isTTY()) {
|
|
46
|
+
return noTTYResponse;
|
|
47
|
+
}
|
|
48
|
+
const { select } = await import("@inquirer/prompts");
|
|
49
|
+
const answer = await select({
|
|
50
|
+
message,
|
|
51
|
+
choices,
|
|
52
|
+
default: choices[defaultResponseIndex].value,
|
|
53
|
+
theme: {
|
|
54
|
+
prefix: ""
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
return answer;
|
|
58
|
+
}
|
|
59
|
+
async function askChoices(message, choices, noTTYResponse) {
|
|
60
|
+
if (!isTTY()) {
|
|
61
|
+
return noTTYResponse;
|
|
62
|
+
}
|
|
63
|
+
const { checkbox } = await import("@inquirer/prompts");
|
|
64
|
+
const answers = await checkbox({
|
|
65
|
+
message,
|
|
66
|
+
choices,
|
|
67
|
+
theme: {
|
|
68
|
+
prefix: ""
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
return answers;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// packages/angular/cli/src/utilities/completion.js
|
|
75
|
+
async function considerSettingUpAutocompletion(command, logger) {
|
|
76
|
+
const completionConfig = await getCompletionConfig();
|
|
77
|
+
if (!await shouldPromptForAutocompletionSetup(command, completionConfig)) {
|
|
78
|
+
return void 0;
|
|
79
|
+
}
|
|
80
|
+
const shouldSetupAutocompletion = await promptForAutocompletion();
|
|
81
|
+
if (!shouldSetupAutocompletion) {
|
|
82
|
+
logger.info(`
|
|
83
|
+
Ok, you won't be prompted again. Should you change your mind, the following command will set up autocompletion for you:
|
|
84
|
+
|
|
85
|
+
${colors.yellow(`ng completion`)}
|
|
86
|
+
`.trim());
|
|
87
|
+
await setCompletionConfig({ ...completionConfig, prompted: true });
|
|
88
|
+
return void 0;
|
|
89
|
+
}
|
|
90
|
+
let rcFile;
|
|
91
|
+
try {
|
|
92
|
+
rcFile = await initializeAutocomplete();
|
|
93
|
+
} catch (err) {
|
|
94
|
+
assertIsError(err);
|
|
95
|
+
logger.error(err.message);
|
|
96
|
+
return 1;
|
|
97
|
+
}
|
|
98
|
+
logger.info(`
|
|
99
|
+
Appended \`source <(ng completion script)\` to \`${rcFile}\`. Restart your terminal or run the following to autocomplete \`ng\` commands:
|
|
100
|
+
|
|
101
|
+
${colors.yellow(`source <(ng completion script)`)}
|
|
102
|
+
`.trim());
|
|
103
|
+
if (!await hasGlobalCliInstall()) {
|
|
104
|
+
logger.warn("Setup completed successfully, but there does not seem to be a global install of the Angular CLI. For autocompletion to work, the CLI will need to be on your `$PATH`, which is typically done with the `-g` flag in `npm install -g @angular/cli`.\n\nFor more information, see https://angular.dev/cli/completion#global-install");
|
|
105
|
+
}
|
|
106
|
+
await setCompletionConfig({ ...completionConfig, prompted: true });
|
|
107
|
+
return void 0;
|
|
108
|
+
}
|
|
109
|
+
async function getCompletionConfig() {
|
|
110
|
+
const wksp = await getWorkspace("global");
|
|
111
|
+
return wksp?.getCli()?.["completion"];
|
|
112
|
+
}
|
|
113
|
+
async function setCompletionConfig(config) {
|
|
114
|
+
const wksp = await getWorkspace("global");
|
|
115
|
+
if (!wksp) {
|
|
116
|
+
throw new Error(`Could not find global workspace`);
|
|
117
|
+
}
|
|
118
|
+
wksp.extensions["cli"] ??= {};
|
|
119
|
+
const cli = wksp.extensions["cli"];
|
|
120
|
+
if (!json.isJsonObject(cli)) {
|
|
121
|
+
throw new Error(`Invalid config found at ${wksp.filePath}. \`extensions.cli\` should be an object.`);
|
|
122
|
+
}
|
|
123
|
+
cli.completion = config;
|
|
124
|
+
await wksp.save();
|
|
125
|
+
}
|
|
126
|
+
async function shouldPromptForAutocompletionSetup(command, config) {
|
|
127
|
+
if (forceAutocomplete !== void 0) {
|
|
128
|
+
return forceAutocomplete;
|
|
129
|
+
}
|
|
130
|
+
if (["version", "update", "completion"].includes(command)) {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
if (!isTTY()) {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
if (config?.prompted) {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
const home = env["HOME"];
|
|
140
|
+
if (!home) {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
const shell = env["SHELL"];
|
|
144
|
+
if (!shell) {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
const rcFiles = getShellRunCommandCandidates(shell, home);
|
|
148
|
+
if (!rcFiles) {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
if (await hasGlobalCliInstall() === false) {
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
for (const rcFile of rcFiles) {
|
|
155
|
+
const contents = await fs.readFile(rcFile, "utf-8").catch(() => void 0);
|
|
156
|
+
if (contents?.includes("ng completion script")) {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
async function promptForAutocompletion() {
|
|
163
|
+
const autocomplete = await askConfirmation(`
|
|
164
|
+
Would you like to enable autocompletion? This will set up your terminal so pressing TAB while typing
|
|
165
|
+
Angular CLI commands will show possible options and autocomplete arguments. (Enabling autocompletion
|
|
166
|
+
will modify configuration files in your home directory.)
|
|
167
|
+
`.split("\n").join(" ").trim(), true);
|
|
168
|
+
return autocomplete;
|
|
169
|
+
}
|
|
170
|
+
async function initializeAutocomplete() {
|
|
171
|
+
const shell = env["SHELL"];
|
|
172
|
+
if (!shell) {
|
|
173
|
+
throw new Error("`$SHELL` environment variable not set. Angular CLI autocompletion only supports Bash or Zsh. If you're on Windows, Cmd and Powershell don't support command autocompletion, but Git Bash or Windows Subsystem for Linux should work, so please try again in one of those environments.");
|
|
174
|
+
}
|
|
175
|
+
const home = env["HOME"];
|
|
176
|
+
if (!home) {
|
|
177
|
+
throw new Error("`$HOME` environment variable not set. Setting up autocompletion modifies configuration files in the home directory and must be set.");
|
|
178
|
+
}
|
|
179
|
+
const runCommandCandidates = getShellRunCommandCandidates(shell, home);
|
|
180
|
+
if (!runCommandCandidates) {
|
|
181
|
+
throw new Error(`Unknown \`$SHELL\` environment variable value (${shell}). Angular CLI autocompletion only supports Bash or Zsh.`);
|
|
182
|
+
}
|
|
183
|
+
const candidates = await Promise.allSettled(runCommandCandidates.map((rcFile2) => fs.access(rcFile2).then(() => rcFile2)));
|
|
184
|
+
const rcFile = candidates.find((result) => result.status === "fulfilled")?.value ?? runCommandCandidates[0];
|
|
185
|
+
try {
|
|
186
|
+
await fs.appendFile(rcFile, "\n\n# Load Angular CLI autocompletion.\nsource <(ng completion script)\n");
|
|
187
|
+
} catch (err) {
|
|
188
|
+
assertIsError(err);
|
|
189
|
+
throw new Error(`Failed to append autocompletion setup to \`${rcFile}\`.`, { cause: err });
|
|
190
|
+
}
|
|
191
|
+
return rcFile;
|
|
192
|
+
}
|
|
193
|
+
function getShellRunCommandCandidates(shell, home) {
|
|
194
|
+
if (shell.toLowerCase().includes("bash")) {
|
|
195
|
+
return [".bashrc", ".bash_profile", ".profile"].map((file) => path.join(home, file));
|
|
196
|
+
} else if (shell.toLowerCase().includes("zsh")) {
|
|
197
|
+
return [".zshrc", ".zsh_profile", ".profile"].map((file) => path.join(home, file));
|
|
198
|
+
} else {
|
|
199
|
+
return void 0;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function hasGlobalCliInstall() {
|
|
203
|
+
return new Promise((resolve2) => {
|
|
204
|
+
execFile("which", ["-a", "ng"], (error, stdout) => {
|
|
205
|
+
if (error) {
|
|
206
|
+
resolve2(false);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const lines = stdout.split("\n").filter((line) => line !== "");
|
|
210
|
+
const hasGlobalInstall = lines.some((line) => {
|
|
211
|
+
const parent = path.parse(path.parse(line).dir);
|
|
212
|
+
const grandparent = path.parse(parent.dir);
|
|
213
|
+
const localInstall = grandparent.base === "node_modules" && parent.base === ".bin";
|
|
214
|
+
return !localInstall;
|
|
215
|
+
});
|
|
216
|
+
return resolve2(hasGlobalInstall);
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// packages/angular/cli/src/command-builder/definitions.js
|
|
222
|
+
var CommandScope;
|
|
223
|
+
(function(CommandScope2) {
|
|
224
|
+
CommandScope2[CommandScope2["In"] = 0] = "In";
|
|
225
|
+
CommandScope2[CommandScope2["Out"] = 1] = "Out";
|
|
226
|
+
CommandScope2[CommandScope2["Both"] = 2] = "Both";
|
|
227
|
+
})(CommandScope || (CommandScope = {}));
|
|
228
|
+
|
|
229
|
+
// packages/angular/cli/src/command-builder/command-module.js
|
|
230
|
+
import { schema } from "@angular-devkit/core";
|
|
231
|
+
import { Parser as yargsParser } from "yargs/helpers";
|
|
232
|
+
|
|
233
|
+
// packages/angular/cli/src/analytics/analytics.js
|
|
234
|
+
import { json as json2, tags } from "@angular-devkit/core";
|
|
235
|
+
import { randomUUID } from "node:crypto";
|
|
236
|
+
var analyticsPackageSafelist = [
|
|
237
|
+
/^@angular\//,
|
|
238
|
+
/^@angular-devkit\//,
|
|
239
|
+
/^@nguniversal\//,
|
|
240
|
+
"@schematics/angular"
|
|
241
|
+
];
|
|
242
|
+
function isPackageNameSafeForAnalytics(name) {
|
|
243
|
+
return analyticsPackageSafelist.some((pattern) => {
|
|
244
|
+
if (typeof pattern == "string") {
|
|
245
|
+
return pattern === name;
|
|
246
|
+
} else {
|
|
247
|
+
return pattern.test(name);
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
async function setAnalyticsConfig(global, value) {
|
|
252
|
+
const level = global ? "global" : "local";
|
|
253
|
+
const workspace = await getWorkspace(level);
|
|
254
|
+
if (!workspace) {
|
|
255
|
+
throw new Error(`Could not find ${level} workspace.`);
|
|
256
|
+
}
|
|
257
|
+
const cli = workspace.extensions["cli"] ??= {};
|
|
258
|
+
if (!workspace || !json2.isJsonObject(cli)) {
|
|
259
|
+
throw new Error(`Invalid config found at ${workspace.filePath}. CLI should be an object.`);
|
|
260
|
+
}
|
|
261
|
+
cli.analytics = value === true ? randomUUID() : value;
|
|
262
|
+
await workspace.save();
|
|
263
|
+
}
|
|
264
|
+
async function promptAnalytics(context, global, force = false) {
|
|
265
|
+
const level = global ? "global" : "local";
|
|
266
|
+
const workspace = await getWorkspace(level);
|
|
267
|
+
if (!workspace) {
|
|
268
|
+
throw new Error(`Could not find a ${level} workspace. Are you in a project?`);
|
|
269
|
+
}
|
|
270
|
+
if (force || isTTY()) {
|
|
271
|
+
const answer = await askConfirmation(`
|
|
272
|
+
Would you like to share pseudonymous usage data about this project with the Angular Team
|
|
273
|
+
at Google under Google's Privacy Policy at https://policies.google.com/privacy. For more
|
|
274
|
+
details and how to change this setting, see https://angular.dev/cli/analytics.
|
|
275
|
+
|
|
276
|
+
`, false);
|
|
277
|
+
await setAnalyticsConfig(global, answer);
|
|
278
|
+
if (answer) {
|
|
279
|
+
console.log("");
|
|
280
|
+
console.log(tags.stripIndent`
|
|
281
|
+
Thank you for sharing pseudonymous usage data. Should you change your mind, the following
|
|
282
|
+
command will disable this feature entirely:
|
|
283
|
+
|
|
284
|
+
${colors.yellow(`ng analytics disable${global ? " --global" : ""}`)}
|
|
285
|
+
`);
|
|
286
|
+
console.log("");
|
|
287
|
+
}
|
|
288
|
+
process.stderr.write(await getAnalyticsInfoString(context));
|
|
289
|
+
return true;
|
|
290
|
+
}
|
|
291
|
+
return false;
|
|
292
|
+
}
|
|
293
|
+
async function getAnalyticsUserIdForLevel(level) {
|
|
294
|
+
if (analyticsDisabled) {
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
const workspace = await getWorkspace(level);
|
|
298
|
+
const analyticsConfig = workspace?.getCli()?.["analytics"];
|
|
299
|
+
if (analyticsConfig === false) {
|
|
300
|
+
return false;
|
|
301
|
+
} else if (analyticsConfig === void 0 || analyticsConfig === null) {
|
|
302
|
+
return void 0;
|
|
303
|
+
} else {
|
|
304
|
+
if (typeof analyticsConfig == "string") {
|
|
305
|
+
return analyticsConfig;
|
|
306
|
+
} else if (typeof analyticsConfig == "object" && typeof analyticsConfig["uid"] == "string") {
|
|
307
|
+
return analyticsConfig["uid"];
|
|
308
|
+
}
|
|
309
|
+
return void 0;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
async function getAnalyticsUserId(context, skipPrompt = false) {
|
|
313
|
+
const { workspace } = context;
|
|
314
|
+
const globalConfig = await getAnalyticsUserIdForLevel("global");
|
|
315
|
+
if (globalConfig === false) {
|
|
316
|
+
return void 0;
|
|
317
|
+
}
|
|
318
|
+
if (workspace || globalConfig === void 0) {
|
|
319
|
+
const level = workspace ? "local" : "global";
|
|
320
|
+
let localOrGlobalConfig = await getAnalyticsUserIdForLevel(level);
|
|
321
|
+
if (localOrGlobalConfig === void 0) {
|
|
322
|
+
if (!skipPrompt) {
|
|
323
|
+
await promptAnalytics(
|
|
324
|
+
context,
|
|
325
|
+
!workspace
|
|
326
|
+
/** global */
|
|
327
|
+
);
|
|
328
|
+
localOrGlobalConfig = await getAnalyticsUserIdForLevel(level);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
if (localOrGlobalConfig === false) {
|
|
332
|
+
return void 0;
|
|
333
|
+
} else if (typeof localOrGlobalConfig === "string") {
|
|
334
|
+
return localOrGlobalConfig;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
return globalConfig;
|
|
338
|
+
}
|
|
339
|
+
function analyticsConfigValueToHumanFormat(value) {
|
|
340
|
+
if (value === false) {
|
|
341
|
+
return "disabled";
|
|
342
|
+
} else if (typeof value === "string" || value === true) {
|
|
343
|
+
return "enabled";
|
|
344
|
+
} else {
|
|
345
|
+
return "not set";
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
async function getAnalyticsInfoString(context) {
|
|
349
|
+
const analyticsInstance = await getAnalyticsUserId(
|
|
350
|
+
context,
|
|
351
|
+
true
|
|
352
|
+
/** skipPrompt */
|
|
353
|
+
);
|
|
354
|
+
const { globalConfiguration, workspace: localWorkspace } = context;
|
|
355
|
+
const globalSetting = globalConfiguration?.getCli()?.["analytics"];
|
|
356
|
+
const localSetting = localWorkspace?.getCli()?.["analytics"];
|
|
357
|
+
return tags.stripIndents`
|
|
358
|
+
Global setting: ${analyticsConfigValueToHumanFormat(globalSetting)}
|
|
359
|
+
Local setting: ${localWorkspace ? analyticsConfigValueToHumanFormat(localSetting) : "No local workspace configuration file."}
|
|
360
|
+
Effective status: ${analyticsInstance ? "enabled" : "disabled"}
|
|
361
|
+
` + "\n";
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// packages/angular/cli/src/analytics/analytics-collector.js
|
|
365
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
366
|
+
import * as https from "node:https";
|
|
367
|
+
import * as os from "node:os";
|
|
368
|
+
import * as querystring from "node:querystring";
|
|
369
|
+
import * as semver from "semver";
|
|
370
|
+
|
|
371
|
+
// packages/angular/cli/src/analytics/analytics-parameters.js
|
|
372
|
+
var RequestParameter;
|
|
373
|
+
(function(RequestParameter2) {
|
|
374
|
+
RequestParameter2["ClientId"] = "cid";
|
|
375
|
+
RequestParameter2["DebugView"] = "_dbg";
|
|
376
|
+
RequestParameter2["GtmVersion"] = "gtm";
|
|
377
|
+
RequestParameter2["Language"] = "ul";
|
|
378
|
+
RequestParameter2["NewToSite"] = "_nsi";
|
|
379
|
+
RequestParameter2["NonInteraction"] = "ni";
|
|
380
|
+
RequestParameter2["PageLocation"] = "dl";
|
|
381
|
+
RequestParameter2["PageTitle"] = "dt";
|
|
382
|
+
RequestParameter2["ProtocolVersion"] = "v";
|
|
383
|
+
RequestParameter2["SessionEngaged"] = "seg";
|
|
384
|
+
RequestParameter2["SessionId"] = "sid";
|
|
385
|
+
RequestParameter2["SessionNumber"] = "sct";
|
|
386
|
+
RequestParameter2["SessionStart"] = "_ss";
|
|
387
|
+
RequestParameter2["TrackingId"] = "tid";
|
|
388
|
+
RequestParameter2["TrafficType"] = "tt";
|
|
389
|
+
RequestParameter2["UserAgentArchitecture"] = "uaa";
|
|
390
|
+
RequestParameter2["UserAgentBitness"] = "uab";
|
|
391
|
+
RequestParameter2["UserAgentFullVersionList"] = "uafvl";
|
|
392
|
+
RequestParameter2["UserAgentMobile"] = "uamb";
|
|
393
|
+
RequestParameter2["UserAgentModel"] = "uam";
|
|
394
|
+
RequestParameter2["UserAgentPlatform"] = "uap";
|
|
395
|
+
RequestParameter2["UserAgentPlatformVersion"] = "uapv";
|
|
396
|
+
RequestParameter2["UserId"] = "uid";
|
|
397
|
+
})(RequestParameter || (RequestParameter = {}));
|
|
398
|
+
var UserCustomDimension;
|
|
399
|
+
(function(UserCustomDimension2) {
|
|
400
|
+
UserCustomDimension2["UserId"] = "up.ng_user_id";
|
|
401
|
+
UserCustomDimension2["OsArchitecture"] = "up.ng_os_architecture";
|
|
402
|
+
UserCustomDimension2["NodeVersion"] = "up.ng_node_version";
|
|
403
|
+
UserCustomDimension2["NodeMajorVersion"] = "upn.ng_node_major_version";
|
|
404
|
+
UserCustomDimension2["AngularCLIVersion"] = "up.ng_cli_version";
|
|
405
|
+
UserCustomDimension2["AngularCLIMajorVersion"] = "upn.ng_cli_major_version";
|
|
406
|
+
UserCustomDimension2["PackageManager"] = "up.ng_package_manager";
|
|
407
|
+
UserCustomDimension2["PackageManagerVersion"] = "up.ng_pkg_manager_version";
|
|
408
|
+
UserCustomDimension2["PackageManagerMajorVersion"] = "upn.ng_pkg_manager_major_v";
|
|
409
|
+
})(UserCustomDimension || (UserCustomDimension = {}));
|
|
410
|
+
var EventCustomDimension;
|
|
411
|
+
(function(EventCustomDimension2) {
|
|
412
|
+
EventCustomDimension2["Command"] = "ep.ng_command";
|
|
413
|
+
EventCustomDimension2["SchematicCollectionName"] = "ep.ng_schematic_collection_name";
|
|
414
|
+
EventCustomDimension2["SchematicName"] = "ep.ng_schematic_name";
|
|
415
|
+
EventCustomDimension2["Standalone"] = "ep.ng_standalone";
|
|
416
|
+
EventCustomDimension2["SSR"] = "ep.ng_ssr";
|
|
417
|
+
EventCustomDimension2["Style"] = "ep.ng_style";
|
|
418
|
+
EventCustomDimension2["Routing"] = "ep.ng_routing";
|
|
419
|
+
EventCustomDimension2["InlineTemplate"] = "ep.ng_inline_template";
|
|
420
|
+
EventCustomDimension2["InlineStyle"] = "ep.ng_inline_style";
|
|
421
|
+
EventCustomDimension2["BuilderTarget"] = "ep.ng_builder_target";
|
|
422
|
+
EventCustomDimension2["Aot"] = "ep.ng_aot";
|
|
423
|
+
EventCustomDimension2["Optimization"] = "ep.ng_optimization";
|
|
424
|
+
})(EventCustomDimension || (EventCustomDimension = {}));
|
|
425
|
+
var EventCustomMetric;
|
|
426
|
+
(function(EventCustomMetric2) {
|
|
427
|
+
EventCustomMetric2["AllChunksCount"] = "epn.ng_all_chunks_count";
|
|
428
|
+
EventCustomMetric2["LazyChunksCount"] = "epn.ng_lazy_chunks_count";
|
|
429
|
+
EventCustomMetric2["InitialChunksCount"] = "epn.ng_initial_chunks_count";
|
|
430
|
+
EventCustomMetric2["ChangedChunksCount"] = "epn.ng_changed_chunks_count";
|
|
431
|
+
EventCustomMetric2["DurationInMs"] = "epn.ng_duration_ms";
|
|
432
|
+
EventCustomMetric2["CssSizeInBytes"] = "epn.ng_css_size_bytes";
|
|
433
|
+
EventCustomMetric2["JsSizeInBytes"] = "epn.ng_js_size_bytes";
|
|
434
|
+
EventCustomMetric2["NgComponentCount"] = "epn.ng_component_count";
|
|
435
|
+
EventCustomMetric2["AllProjectsCount"] = "epn.all_projects_count";
|
|
436
|
+
EventCustomMetric2["LibraryProjectsCount"] = "epn.libs_projects_count";
|
|
437
|
+
EventCustomMetric2["ApplicationProjectsCount"] = "epn.apps_projects_count";
|
|
438
|
+
})(EventCustomMetric || (EventCustomMetric = {}));
|
|
439
|
+
|
|
440
|
+
// packages/angular/cli/src/analytics/analytics-collector.js
|
|
441
|
+
var TRACKING_ID_PROD = "G-VETNJBW8L4";
|
|
442
|
+
var TRACKING_ID_STAGING = "G-TBMPRL1BTM";
|
|
443
|
+
var AnalyticsCollector = class {
|
|
444
|
+
logger;
|
|
445
|
+
trackingEventsQueue;
|
|
446
|
+
requestParameterStringified;
|
|
447
|
+
userParameters;
|
|
448
|
+
constructor(logger, userId, packageManagerInfo) {
|
|
449
|
+
this.logger = logger;
|
|
450
|
+
const requestParameters = {
|
|
451
|
+
[RequestParameter.ProtocolVersion]: 2,
|
|
452
|
+
[RequestParameter.ClientId]: userId,
|
|
453
|
+
[RequestParameter.UserId]: userId,
|
|
454
|
+
[RequestParameter.TrackingId]: /^\d+\.\d+\.\d+$/.test(VERSION.full) && VERSION.full !== "0.0.0" ? TRACKING_ID_PROD : TRACKING_ID_STAGING,
|
|
455
|
+
// Built-in user properties
|
|
456
|
+
[RequestParameter.SessionId]: randomUUID2(),
|
|
457
|
+
[RequestParameter.UserAgentArchitecture]: os.arch(),
|
|
458
|
+
[RequestParameter.UserAgentPlatform]: os.platform(),
|
|
459
|
+
[RequestParameter.UserAgentPlatformVersion]: os.release(),
|
|
460
|
+
[RequestParameter.UserAgentMobile]: 0,
|
|
461
|
+
[RequestParameter.SessionEngaged]: 1,
|
|
462
|
+
// The below is needed for tech details to be collected.
|
|
463
|
+
[RequestParameter.UserAgentFullVersionList]: "Google%20Chrome;111.0.5563.64|Not(A%3ABrand;8.0.0.0|Chromium;111.0.5563.64"
|
|
464
|
+
};
|
|
465
|
+
if (ngDebug) {
|
|
466
|
+
requestParameters[RequestParameter.DebugView] = 1;
|
|
467
|
+
}
|
|
468
|
+
this.requestParameterStringified = querystring.stringify(requestParameters);
|
|
469
|
+
const parsedVersion = semver.parse(process.version);
|
|
470
|
+
const packageManagerVersion = packageManagerInfo.version;
|
|
471
|
+
this.userParameters = {
|
|
472
|
+
// While architecture is being collect by GA as UserAgentArchitecture.
|
|
473
|
+
// It doesn't look like there is a way to query this. Therefore we collect this as a custom user dimension too.
|
|
474
|
+
[UserCustomDimension.OsArchitecture]: os.arch(),
|
|
475
|
+
// While User ID is being collected by GA, this is not visible in reports/for filtering.
|
|
476
|
+
[UserCustomDimension.UserId]: userId,
|
|
477
|
+
[UserCustomDimension.NodeVersion]: parsedVersion ? `${parsedVersion.major}.${parsedVersion.minor}.${parsedVersion.patch}` : "other",
|
|
478
|
+
[UserCustomDimension.NodeMajorVersion]: parsedVersion?.major,
|
|
479
|
+
[UserCustomDimension.PackageManager]: packageManagerInfo.name,
|
|
480
|
+
[UserCustomDimension.PackageManagerVersion]: packageManagerVersion,
|
|
481
|
+
[UserCustomDimension.PackageManagerMajorVersion]: packageManagerVersion ? +packageManagerVersion.split(".", 1)[0] : void 0,
|
|
482
|
+
[UserCustomDimension.AngularCLIVersion]: VERSION.full,
|
|
483
|
+
[UserCustomDimension.AngularCLIMajorVersion]: VERSION.major
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
reportWorkspaceInfoEvent(parameters) {
|
|
487
|
+
this.event("workspace_info", parameters);
|
|
488
|
+
}
|
|
489
|
+
reportRebuildRunEvent(parameters) {
|
|
490
|
+
this.event("run_rebuild", parameters);
|
|
491
|
+
}
|
|
492
|
+
reportBuildRunEvent(parameters) {
|
|
493
|
+
this.event("run_build", parameters);
|
|
494
|
+
}
|
|
495
|
+
reportArchitectRunEvent(parameters) {
|
|
496
|
+
this.event("run_architect", parameters);
|
|
497
|
+
}
|
|
498
|
+
reportSchematicRunEvent(parameters) {
|
|
499
|
+
this.event("run_schematic", parameters);
|
|
500
|
+
}
|
|
501
|
+
reportCommandRunEvent(command) {
|
|
502
|
+
this.event("run_command", { [EventCustomDimension.Command]: command });
|
|
503
|
+
}
|
|
504
|
+
event(eventName, parameters) {
|
|
505
|
+
this.trackingEventsQueue ??= [];
|
|
506
|
+
this.trackingEventsQueue.push({
|
|
507
|
+
...this.userParameters,
|
|
508
|
+
...parameters,
|
|
509
|
+
"en": eventName
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* Flush on an interval (if the event loop is waiting).
|
|
514
|
+
*
|
|
515
|
+
* @returns a method that when called will terminate the periodic
|
|
516
|
+
* flush and call flush one last time.
|
|
517
|
+
*/
|
|
518
|
+
periodFlush() {
|
|
519
|
+
let analyticsFlushPromise = Promise.resolve();
|
|
520
|
+
const analyticsFlushInterval = setInterval(() => {
|
|
521
|
+
if (this.trackingEventsQueue?.length) {
|
|
522
|
+
analyticsFlushPromise = analyticsFlushPromise.then(() => this.flush());
|
|
523
|
+
}
|
|
524
|
+
}, 4e3);
|
|
525
|
+
return () => {
|
|
526
|
+
clearInterval(analyticsFlushInterval);
|
|
527
|
+
return analyticsFlushPromise.then(() => this.flush());
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
async flush() {
|
|
531
|
+
const pendingTrackingEvents = this.trackingEventsQueue;
|
|
532
|
+
this.logger.debug(`Analytics flush size. ${pendingTrackingEvents?.length}.`);
|
|
533
|
+
if (!pendingTrackingEvents?.length) {
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
this.trackingEventsQueue = void 0;
|
|
537
|
+
try {
|
|
538
|
+
await this.send(pendingTrackingEvents);
|
|
539
|
+
} catch (error) {
|
|
540
|
+
assertIsError(error);
|
|
541
|
+
this.logger.debug(`Send analytics error. ${error.message}.`);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
async send(data) {
|
|
545
|
+
return new Promise((resolve2, reject) => {
|
|
546
|
+
const request2 = https.request({
|
|
547
|
+
host: "www.google-analytics.com",
|
|
548
|
+
method: "POST",
|
|
549
|
+
path: "/g/collect?" + this.requestParameterStringified,
|
|
550
|
+
headers: {
|
|
551
|
+
// The below is needed for tech details to be collected even though we provide our own information from the OS Node.js module
|
|
552
|
+
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36"
|
|
553
|
+
}
|
|
554
|
+
}, (response) => {
|
|
555
|
+
response.on("data", () => {
|
|
556
|
+
});
|
|
557
|
+
if (response.statusCode !== 200 && response.statusCode !== 204) {
|
|
558
|
+
reject(new Error(`Analytics reporting failed with status code: ${response.statusCode}.`));
|
|
559
|
+
} else {
|
|
560
|
+
resolve2();
|
|
561
|
+
}
|
|
562
|
+
});
|
|
563
|
+
request2.on("error", reject);
|
|
564
|
+
const queryParameters = data.map((p) => querystring.stringify(p)).join("\n");
|
|
565
|
+
request2.write(queryParameters);
|
|
566
|
+
request2.end();
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
};
|
|
570
|
+
|
|
571
|
+
// packages/angular/cli/src/package-managers/factory.js
|
|
572
|
+
import assert from "node:assert/strict";
|
|
573
|
+
import { major } from "semver";
|
|
574
|
+
|
|
575
|
+
// packages/angular/cli/src/package-managers/discovery.js
|
|
576
|
+
import { dirname, join as join2 } from "node:path";
|
|
577
|
+
|
|
578
|
+
// packages/angular/cli/src/package-managers/parsers.js
|
|
579
|
+
import { compare, valid } from "semver";
|
|
580
|
+
var MAX_LOG_LENGTH = 1024;
|
|
581
|
+
function logStdout(stdout, logger) {
|
|
582
|
+
if (!logger) {
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
let output = stdout;
|
|
586
|
+
if (output.length > MAX_LOG_LENGTH) {
|
|
587
|
+
output = `${output.slice(0, MAX_LOG_LENGTH)}... (truncated)`;
|
|
588
|
+
}
|
|
589
|
+
logger.debug(` stdout:
|
|
590
|
+
${output}`);
|
|
591
|
+
}
|
|
592
|
+
function* parseJsonLines(output, logger) {
|
|
593
|
+
for (const line of output.split("\n")) {
|
|
594
|
+
if (!line.trim()) {
|
|
595
|
+
continue;
|
|
596
|
+
}
|
|
597
|
+
try {
|
|
598
|
+
yield JSON.parse(line);
|
|
599
|
+
} catch (e) {
|
|
600
|
+
logger?.debug(` Ignoring non-JSON line: ${e}`);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
function parseNpmLikeDependencies(stdout, logger, options) {
|
|
605
|
+
logger?.debug(`Parsing npm-like dependency list...`);
|
|
606
|
+
logStdout(stdout, logger);
|
|
607
|
+
const dependencies = /* @__PURE__ */ new Map();
|
|
608
|
+
if (!stdout) {
|
|
609
|
+
logger?.debug(" stdout is empty. No dependencies found.");
|
|
610
|
+
return dependencies;
|
|
611
|
+
}
|
|
612
|
+
const data = JSON.parse(stdout);
|
|
613
|
+
const workspacePackageName = options?.workspacePackageName;
|
|
614
|
+
let rootProject;
|
|
615
|
+
let subProject;
|
|
616
|
+
if (Array.isArray(data)) {
|
|
617
|
+
rootProject = data[0];
|
|
618
|
+
if (workspacePackageName) {
|
|
619
|
+
subProject = data.find((project) => project?.name === workspacePackageName);
|
|
620
|
+
}
|
|
621
|
+
} else {
|
|
622
|
+
rootProject = data;
|
|
623
|
+
}
|
|
624
|
+
if (!rootProject || typeof rootProject !== "object") {
|
|
625
|
+
return dependencies;
|
|
626
|
+
}
|
|
627
|
+
if (subProject) {
|
|
628
|
+
const subprojectMaps = [
|
|
629
|
+
subProject.dependencies,
|
|
630
|
+
subProject.devDependencies,
|
|
631
|
+
subProject.unsavedDependencies
|
|
632
|
+
].filter((d) => !!d);
|
|
633
|
+
for (const subprojectMap of subprojectMaps) {
|
|
634
|
+
for (const [name, info] of Object.entries(subprojectMap)) {
|
|
635
|
+
if (info && typeof info === "object" && info.version) {
|
|
636
|
+
dependencies.set(name, {
|
|
637
|
+
name,
|
|
638
|
+
version: info.version,
|
|
639
|
+
path: info.path
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
} else if (workspacePackageName) {
|
|
645
|
+
const rootDependencyMaps2 = [
|
|
646
|
+
rootProject.dependencies,
|
|
647
|
+
rootProject.devDependencies,
|
|
648
|
+
rootProject.unsavedDependencies
|
|
649
|
+
].filter((d) => !!d);
|
|
650
|
+
for (const dependencyMap of rootDependencyMaps2) {
|
|
651
|
+
const info = dependencyMap[workspacePackageName];
|
|
652
|
+
if (info && typeof info === "object") {
|
|
653
|
+
const nestedMaps = [
|
|
654
|
+
info.dependencies,
|
|
655
|
+
info.devDependencies,
|
|
656
|
+
info.unsavedDependencies
|
|
657
|
+
].filter((d) => !!d);
|
|
658
|
+
for (const nestedMap of nestedMaps) {
|
|
659
|
+
for (const [name, nestedInfo] of Object.entries(nestedMap)) {
|
|
660
|
+
if (nestedInfo && typeof nestedInfo === "object" && nestedInfo.version) {
|
|
661
|
+
dependencies.set(name, {
|
|
662
|
+
name,
|
|
663
|
+
version: nestedInfo.version,
|
|
664
|
+
path: nestedInfo.path
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
const rootDependencyMaps = [
|
|
673
|
+
rootProject.dependencies,
|
|
674
|
+
rootProject.devDependencies,
|
|
675
|
+
rootProject.unsavedDependencies
|
|
676
|
+
].filter((d) => !!d);
|
|
677
|
+
for (const dependencyMap of rootDependencyMaps) {
|
|
678
|
+
for (const [name, info] of Object.entries(dependencyMap)) {
|
|
679
|
+
if (!info || typeof info !== "object") {
|
|
680
|
+
continue;
|
|
681
|
+
}
|
|
682
|
+
const isWorkspacePackage = info.resolved?.startsWith("file:") && (!!info.dependencies || !!info.devDependencies || !!info.unsavedDependencies);
|
|
683
|
+
if (info.version && !dependencies.has(name) && !isWorkspacePackage) {
|
|
684
|
+
dependencies.set(name, {
|
|
685
|
+
name,
|
|
686
|
+
version: info.version,
|
|
687
|
+
path: info.path
|
|
688
|
+
});
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
logger?.debug(` Found ${dependencies.size} dependencies.`);
|
|
693
|
+
return dependencies;
|
|
694
|
+
}
|
|
695
|
+
function parseYarnClassicDependencies(stdout, logger) {
|
|
696
|
+
logger?.debug(`Parsing yarn classic dependency list...`);
|
|
697
|
+
logStdout(stdout, logger);
|
|
698
|
+
const dependencies = /* @__PURE__ */ new Map();
|
|
699
|
+
if (!stdout) {
|
|
700
|
+
logger?.debug(" stdout is empty. No dependencies found.");
|
|
701
|
+
return dependencies;
|
|
702
|
+
}
|
|
703
|
+
for (const json4 of parseJsonLines(stdout, logger)) {
|
|
704
|
+
if (json4.type === "tree" && json4.data?.trees) {
|
|
705
|
+
for (const info of json4.data.trees) {
|
|
706
|
+
const lastAtIndex = info.name.lastIndexOf("@");
|
|
707
|
+
const name = info.name.slice(0, lastAtIndex);
|
|
708
|
+
const version = info.name.slice(lastAtIndex + 1);
|
|
709
|
+
dependencies.set(name, {
|
|
710
|
+
name,
|
|
711
|
+
version
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
logger?.debug(` Found ${dependencies.size} dependencies.`);
|
|
717
|
+
return dependencies;
|
|
718
|
+
}
|
|
719
|
+
function isValidManifest(obj) {
|
|
720
|
+
if (typeof obj !== "object" || obj === null) {
|
|
721
|
+
return false;
|
|
722
|
+
}
|
|
723
|
+
const { name, version } = obj;
|
|
724
|
+
return typeof name === "string" && typeof version === "string" && valid(version) !== null;
|
|
725
|
+
}
|
|
726
|
+
function isValidMetadata(obj) {
|
|
727
|
+
if (typeof obj !== "object" || obj === null) {
|
|
728
|
+
return false;
|
|
729
|
+
}
|
|
730
|
+
const { name, versions, "dist-tags": distTags } = obj;
|
|
731
|
+
return typeof name === "string" && Array.isArray(versions) && typeof distTags === "object" && distTags !== null;
|
|
732
|
+
}
|
|
733
|
+
function parseNpmLikeManifest(stdout, logger) {
|
|
734
|
+
logger?.debug(`Parsing npm-like manifest...`);
|
|
735
|
+
logStdout(stdout, logger);
|
|
736
|
+
if (!stdout) {
|
|
737
|
+
logger?.debug(" stdout is empty. No manifest found.");
|
|
738
|
+
return null;
|
|
739
|
+
}
|
|
740
|
+
const result = JSON.parse(stdout);
|
|
741
|
+
if (Array.isArray(result)) {
|
|
742
|
+
let maxManifest = null;
|
|
743
|
+
for (const manifest of result) {
|
|
744
|
+
if (!isValidManifest(manifest)) {
|
|
745
|
+
logger?.debug(" Skipping invalid manifest in array (missing name, version, or invalid SemVer).");
|
|
746
|
+
continue;
|
|
747
|
+
}
|
|
748
|
+
if (!maxManifest || compare(manifest.version, maxManifest.version) > 0) {
|
|
749
|
+
maxManifest = manifest;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
if (!maxManifest) {
|
|
753
|
+
logger?.debug(" No valid manifests found in the array.");
|
|
754
|
+
}
|
|
755
|
+
return maxManifest;
|
|
756
|
+
}
|
|
757
|
+
if (!isValidManifest(result)) {
|
|
758
|
+
logger?.debug(" Parsed JSON is not a valid manifest (missing name, version, or invalid SemVer).");
|
|
759
|
+
return null;
|
|
760
|
+
}
|
|
761
|
+
return result;
|
|
762
|
+
}
|
|
763
|
+
function parseNpmLikeMetadata(stdout, logger) {
|
|
764
|
+
logger?.debug(`Parsing npm-like metadata...`);
|
|
765
|
+
logStdout(stdout, logger);
|
|
766
|
+
if (!stdout) {
|
|
767
|
+
logger?.debug(" stdout is empty. No metadata found.");
|
|
768
|
+
return null;
|
|
769
|
+
}
|
|
770
|
+
const result = JSON.parse(stdout);
|
|
771
|
+
if (Array.isArray(result)) {
|
|
772
|
+
for (const item of result) {
|
|
773
|
+
if (isValidMetadata(item)) {
|
|
774
|
+
return item;
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
logger?.debug(" No valid metadata found in the array.");
|
|
778
|
+
return null;
|
|
779
|
+
}
|
|
780
|
+
if (!isValidMetadata(result)) {
|
|
781
|
+
logger?.debug(" Parsed JSON is not valid metadata (missing name, versions, or dist-tags).");
|
|
782
|
+
return null;
|
|
783
|
+
}
|
|
784
|
+
return result;
|
|
785
|
+
}
|
|
786
|
+
function parseYarnClassicManifest(stdout, logger) {
|
|
787
|
+
logger?.debug(`Parsing yarn classic manifest...`);
|
|
788
|
+
logStdout(stdout, logger);
|
|
789
|
+
if (!stdout) {
|
|
790
|
+
logger?.debug(" stdout is empty. No manifest found.");
|
|
791
|
+
return null;
|
|
792
|
+
}
|
|
793
|
+
let manifest;
|
|
794
|
+
for (const json4 of parseJsonLines(stdout, logger)) {
|
|
795
|
+
if (json4.type === "inspect" && json4.data) {
|
|
796
|
+
manifest = json4.data;
|
|
797
|
+
break;
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
if (!manifest) {
|
|
801
|
+
logger?.debug(" Failed to find manifest in yarn classic output.");
|
|
802
|
+
return null;
|
|
803
|
+
}
|
|
804
|
+
if (manifest["ng-add"] && typeof manifest["ng-add"] === "object" && Object.keys(manifest["ng-add"]).length === 0) {
|
|
805
|
+
manifest["ng-add"].save ??= false;
|
|
806
|
+
}
|
|
807
|
+
if (!isValidManifest(manifest)) {
|
|
808
|
+
logger?.debug(" Parsed JSON is not a valid manifest (missing name, version, or invalid SemVer).");
|
|
809
|
+
return null;
|
|
810
|
+
}
|
|
811
|
+
return manifest;
|
|
812
|
+
}
|
|
813
|
+
function parseYarnClassicMetadata(stdout, logger) {
|
|
814
|
+
logger?.debug(`Parsing yarn classic metadata...`);
|
|
815
|
+
logStdout(stdout, logger);
|
|
816
|
+
if (!stdout) {
|
|
817
|
+
logger?.debug(" stdout is empty. No metadata found.");
|
|
818
|
+
return null;
|
|
819
|
+
}
|
|
820
|
+
let metadata;
|
|
821
|
+
for (const json4 of parseJsonLines(stdout, logger)) {
|
|
822
|
+
if (json4.type === "inspect" && json4.data) {
|
|
823
|
+
metadata = json4.data;
|
|
824
|
+
break;
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
if (!metadata) {
|
|
828
|
+
logger?.debug(" Failed to find metadata in yarn classic output.");
|
|
829
|
+
return null;
|
|
830
|
+
}
|
|
831
|
+
return metadata;
|
|
832
|
+
}
|
|
833
|
+
function parseNpmLikeError(output, logger) {
|
|
834
|
+
logger?.debug(`Parsing npm-like error output...`);
|
|
835
|
+
logStdout(output, logger);
|
|
836
|
+
if (!output) {
|
|
837
|
+
logger?.debug(" output is empty. No error found.");
|
|
838
|
+
return null;
|
|
839
|
+
}
|
|
840
|
+
try {
|
|
841
|
+
let jsonError = JSON.parse(output);
|
|
842
|
+
if (Array.isArray(jsonError)) {
|
|
843
|
+
jsonError = jsonError[0];
|
|
844
|
+
}
|
|
845
|
+
if (jsonError && typeof jsonError === "object" && "error" in jsonError) {
|
|
846
|
+
jsonError = jsonError.error;
|
|
847
|
+
}
|
|
848
|
+
if (jsonError && typeof jsonError.code === "string" && (typeof jsonError.summary === "string" || typeof jsonError.message === "string")) {
|
|
849
|
+
const summary = jsonError.summary || jsonError.message;
|
|
850
|
+
logger?.debug(` Successfully parsed JSON error with code '${jsonError.code}'.`);
|
|
851
|
+
return {
|
|
852
|
+
code: jsonError.code,
|
|
853
|
+
summary,
|
|
854
|
+
detail: jsonError.detail
|
|
855
|
+
};
|
|
856
|
+
}
|
|
857
|
+
} catch (e) {
|
|
858
|
+
logger?.debug(` Failed to parse output as JSON: ${e}. Attempting regex fallback.`);
|
|
859
|
+
}
|
|
860
|
+
const errorCodeMatch = output.match(/npm (ERR!|error) code (E\d{3}|[A-Z_]+)/);
|
|
861
|
+
if (errorCodeMatch) {
|
|
862
|
+
const code = errorCodeMatch[2];
|
|
863
|
+
let summary;
|
|
864
|
+
for (const line of output.split("\n")) {
|
|
865
|
+
if (line.startsWith("npm ERR!") && !line.includes(" code ")) {
|
|
866
|
+
summary = line.replace("npm ERR! ", "").trim();
|
|
867
|
+
break;
|
|
868
|
+
} else if (line.startsWith("npm error") && !line.includes(" code ")) {
|
|
869
|
+
summary = line.replace("npm error ", "").trim();
|
|
870
|
+
break;
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
logger?.debug(` Successfully parsed text error with code '${code}'.`);
|
|
874
|
+
return {
|
|
875
|
+
code,
|
|
876
|
+
summary: summary || `Package manager error: ${code}`
|
|
877
|
+
};
|
|
878
|
+
}
|
|
879
|
+
logger?.debug(" Failed to parse npm-like error. No structured error found.");
|
|
880
|
+
return null;
|
|
881
|
+
}
|
|
882
|
+
function parseYarnClassicError(output, logger) {
|
|
883
|
+
logger?.debug(`Parsing yarn classic error output...`);
|
|
884
|
+
logStdout(output, logger);
|
|
885
|
+
if (!output) {
|
|
886
|
+
logger?.debug(" output is empty. No error found.");
|
|
887
|
+
return null;
|
|
888
|
+
}
|
|
889
|
+
const statusCodeMatch = output.match(/finished with status code (\d{3})/);
|
|
890
|
+
if (statusCodeMatch) {
|
|
891
|
+
const statusCode = Number(statusCodeMatch[1]);
|
|
892
|
+
if (statusCode < 200 || statusCode >= 300) {
|
|
893
|
+
logger?.debug(` Detected HTTP error status code '${statusCode}' in verbose output.`);
|
|
894
|
+
return {
|
|
895
|
+
code: `E${statusCode}`,
|
|
896
|
+
summary: `Request failed with status code ${statusCode}.`
|
|
897
|
+
};
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
for (const json4 of parseJsonLines(output, logger)) {
|
|
901
|
+
if (json4.type === "error" && typeof json4.data === "string") {
|
|
902
|
+
const summary = json4.data;
|
|
903
|
+
logger?.debug(` Successfully parsed generic yarn classic error.`);
|
|
904
|
+
return {
|
|
905
|
+
code: "UNKNOWN_ERROR",
|
|
906
|
+
summary
|
|
907
|
+
};
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
logger?.debug(" Failed to parse yarn classic error. No structured error found.");
|
|
911
|
+
return null;
|
|
912
|
+
}
|
|
913
|
+
function parseBunDependencies(stdout, logger) {
|
|
914
|
+
logger?.debug("Parsing Bun dependency list...");
|
|
915
|
+
logStdout(stdout, logger);
|
|
916
|
+
const dependencies = /* @__PURE__ */ new Map();
|
|
917
|
+
if (!stdout) {
|
|
918
|
+
return dependencies;
|
|
919
|
+
}
|
|
920
|
+
const lines = stdout.split("\n");
|
|
921
|
+
for (let i = 1; i < lines.length; i++) {
|
|
922
|
+
const line = lines[i].trim();
|
|
923
|
+
if (!line) {
|
|
924
|
+
continue;
|
|
925
|
+
}
|
|
926
|
+
const cleanLine = line.replace(/^[└├]──\s*/, "");
|
|
927
|
+
const match = cleanLine.match(/^(.+?)\s?@([^@\s]+)$/);
|
|
928
|
+
if (match) {
|
|
929
|
+
const name = match[1];
|
|
930
|
+
const version = match[2];
|
|
931
|
+
dependencies.set(name, { name, version });
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
logger?.debug(` Found ${dependencies.size} dependencies.`);
|
|
935
|
+
return dependencies;
|
|
936
|
+
}
|
|
937
|
+
function parseYarnModernDependencies(stdout, logger) {
|
|
938
|
+
logger?.debug("Parsing Yarn Berry dependency list...");
|
|
939
|
+
logStdout(stdout, logger);
|
|
940
|
+
const dependencies = /* @__PURE__ */ new Map();
|
|
941
|
+
if (!stdout) {
|
|
942
|
+
return dependencies;
|
|
943
|
+
}
|
|
944
|
+
for (const json4 of parseJsonLines(stdout, logger)) {
|
|
945
|
+
if (typeof json4 === "string") {
|
|
946
|
+
const match = json4.match(/^(@?[^@]+)@(.+)$/);
|
|
947
|
+
if (match) {
|
|
948
|
+
const name = match[1];
|
|
949
|
+
let version = match[2];
|
|
950
|
+
if (version.startsWith("npm:")) {
|
|
951
|
+
version = version.slice(4);
|
|
952
|
+
}
|
|
953
|
+
const versionParamMatch = version.match(/::version=([^&]+)/);
|
|
954
|
+
if (versionParamMatch) {
|
|
955
|
+
version = versionParamMatch[1];
|
|
956
|
+
}
|
|
957
|
+
dependencies.set(name, { name, version });
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
logger?.debug(` Found ${dependencies.size} dependencies.`);
|
|
962
|
+
return dependencies;
|
|
963
|
+
}
|
|
964
|
+
function parsePnpmReleaseAge(output, version) {
|
|
965
|
+
const value = output.trim();
|
|
966
|
+
if (!value || value === "undefined" || value === "null") {
|
|
967
|
+
const major2 = parseInt(version.split(".")[0], 10);
|
|
968
|
+
if (major2 >= 11) {
|
|
969
|
+
return 1440 * 6e4;
|
|
970
|
+
}
|
|
971
|
+
return 0;
|
|
972
|
+
}
|
|
973
|
+
const minutes = parseInt(value, 10);
|
|
974
|
+
return isNaN(minutes) ? 0 : minutes * 6e4;
|
|
975
|
+
}
|
|
976
|
+
function parseYarnReleaseAge(output, version) {
|
|
977
|
+
const value = output.trim();
|
|
978
|
+
if (!value || value === "undefined" || value === "null") {
|
|
979
|
+
const major2 = parseInt(version.split(".")[0], 10);
|
|
980
|
+
if (major2 >= 4) {
|
|
981
|
+
return 1440 * 6e4;
|
|
982
|
+
}
|
|
983
|
+
return 0;
|
|
984
|
+
}
|
|
985
|
+
const match = value.match(/^(\d+)(ms|s|m|h|d|w)?$/);
|
|
986
|
+
if (!match) {
|
|
987
|
+
return 0;
|
|
988
|
+
}
|
|
989
|
+
const amount = parseInt(match[1], 10);
|
|
990
|
+
const unit = match[2];
|
|
991
|
+
if (unit) {
|
|
992
|
+
switch (unit) {
|
|
993
|
+
case "ms":
|
|
994
|
+
return amount;
|
|
995
|
+
case "s":
|
|
996
|
+
return amount * 1e3;
|
|
997
|
+
case "m":
|
|
998
|
+
return amount * 6e4;
|
|
999
|
+
case "h":
|
|
1000
|
+
return amount * 36e5;
|
|
1001
|
+
case "d":
|
|
1002
|
+
return amount * 864e5;
|
|
1003
|
+
case "w":
|
|
1004
|
+
return amount * 6048e5;
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
return amount * 6e4;
|
|
1008
|
+
}
|
|
1009
|
+
function parseNpmBeforeDate(output) {
|
|
1010
|
+
const trimmed = output.trim();
|
|
1011
|
+
if (!trimmed || trimmed === "null" || trimmed === "undefined") {
|
|
1012
|
+
return 0;
|
|
1013
|
+
}
|
|
1014
|
+
const parsedDate = Date.parse(trimmed);
|
|
1015
|
+
if (isNaN(parsedDate)) {
|
|
1016
|
+
return 0;
|
|
1017
|
+
}
|
|
1018
|
+
const age = Date.now() - parsedDate;
|
|
1019
|
+
return age > 0 ? age : 0;
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
// packages/angular/cli/src/package-managers/package-manager-descriptor.js
|
|
1023
|
+
var NOT_FOUND_ERROR_CODES = /* @__PURE__ */ new Set(["E404"]);
|
|
1024
|
+
function isKnownNotFound(error) {
|
|
1025
|
+
return NOT_FOUND_ERROR_CODES.has(error.code);
|
|
1026
|
+
}
|
|
1027
|
+
var SUPPORTED_PACKAGE_MANAGERS = {
|
|
1028
|
+
npm: {
|
|
1029
|
+
binary: "npm",
|
|
1030
|
+
lockfiles: ["package-lock.json", "npm-shrinkwrap.json"],
|
|
1031
|
+
addCommand: "install",
|
|
1032
|
+
installCommand: ["install"],
|
|
1033
|
+
forceFlag: "--force",
|
|
1034
|
+
saveExactFlag: "--save-exact",
|
|
1035
|
+
saveTildeFlag: "--save-tilde",
|
|
1036
|
+
saveDevFlag: "--save-dev",
|
|
1037
|
+
noLockfileFlag: "--no-package-lock",
|
|
1038
|
+
ignoreScriptsFlag: "--ignore-scripts",
|
|
1039
|
+
ignorePeerDependenciesFlag: "--force",
|
|
1040
|
+
configFiles: [".npmrc"],
|
|
1041
|
+
getRegistryOptions: (registry) => ({ args: ["--registry", registry] }),
|
|
1042
|
+
versionCommand: ["--version"],
|
|
1043
|
+
listDependenciesCommand: ["list", "--depth=0", "--json=true", "--all=true"],
|
|
1044
|
+
getReleaseAgeConfigCommand: ["config", "get", "before"],
|
|
1045
|
+
getPackageNameCommand: ["pkg", "get", "name"],
|
|
1046
|
+
getManifestCommand: ["view", "--json"],
|
|
1047
|
+
viewCommandFieldArgFormatter: (fields) => [...fields],
|
|
1048
|
+
outputParsers: {
|
|
1049
|
+
listDependencies: parseNpmLikeDependencies,
|
|
1050
|
+
getRegistryManifest: parseNpmLikeManifest,
|
|
1051
|
+
getRegistryMetadata: parseNpmLikeMetadata,
|
|
1052
|
+
getError: parseNpmLikeError,
|
|
1053
|
+
getReleaseAge: parseNpmBeforeDate
|
|
1054
|
+
},
|
|
1055
|
+
isNotFound: isKnownNotFound
|
|
1056
|
+
},
|
|
1057
|
+
yarn: {
|
|
1058
|
+
binary: "yarn",
|
|
1059
|
+
lockfiles: ["yarn.lock"],
|
|
1060
|
+
addCommand: "add",
|
|
1061
|
+
installCommand: ["install"],
|
|
1062
|
+
forceFlag: "--force",
|
|
1063
|
+
saveExactFlag: "--exact",
|
|
1064
|
+
saveTildeFlag: "--tilde",
|
|
1065
|
+
saveDevFlag: "--dev",
|
|
1066
|
+
noLockfileFlag: "",
|
|
1067
|
+
ignoreScriptsFlag: "--mode=skip-build",
|
|
1068
|
+
configFiles: [".yarnrc.yml", ".yarnrc.yaml"],
|
|
1069
|
+
copyConfigFromProject: true,
|
|
1070
|
+
getRegistryOptions: (registry) => ({ env: { YARN_NPM_REGISTRY_SERVER: registry } }),
|
|
1071
|
+
versionCommand: ["--version"],
|
|
1072
|
+
listDependenciesCommand: ["info", "--name-only", "--json"],
|
|
1073
|
+
getReleaseAgeConfigCommand: ["config", "get", "npmMinimalAgeGate"],
|
|
1074
|
+
getManifestCommand: ["npm", "info", "--json"],
|
|
1075
|
+
viewCommandFieldArgFormatter: (fields) => ["--fields", fields.join(",")],
|
|
1076
|
+
outputParsers: {
|
|
1077
|
+
listDependencies: parseYarnModernDependencies,
|
|
1078
|
+
getRegistryManifest: parseNpmLikeManifest,
|
|
1079
|
+
getRegistryMetadata: parseNpmLikeMetadata,
|
|
1080
|
+
getError: parseNpmLikeError,
|
|
1081
|
+
getReleaseAge: parseYarnReleaseAge
|
|
1082
|
+
},
|
|
1083
|
+
isNotFound: isKnownNotFound
|
|
1084
|
+
},
|
|
1085
|
+
"yarn-classic": {
|
|
1086
|
+
binary: "yarn",
|
|
1087
|
+
// This is intentionally empty. `yarn-classic` is not a discoverable package manager.
|
|
1088
|
+
// The discovery process finds `yarn` via `yarn.lock`, and the factory logic
|
|
1089
|
+
// determines whether it is classic or modern by checking the installed version.
|
|
1090
|
+
lockfiles: [],
|
|
1091
|
+
addCommand: "add",
|
|
1092
|
+
installCommand: ["install"],
|
|
1093
|
+
forceFlag: "--force",
|
|
1094
|
+
saveExactFlag: "--exact",
|
|
1095
|
+
saveTildeFlag: "--tilde",
|
|
1096
|
+
saveDevFlag: "--dev",
|
|
1097
|
+
noLockfileFlag: "--no-lockfile",
|
|
1098
|
+
ignoreScriptsFlag: "--ignore-scripts",
|
|
1099
|
+
configFiles: [".yarnrc", ".npmrc"],
|
|
1100
|
+
getRegistryOptions: (registry) => ({ args: ["--registry", registry] }),
|
|
1101
|
+
versionCommand: ["--version"],
|
|
1102
|
+
listDependenciesCommand: ["list", "--depth=0", "--json"],
|
|
1103
|
+
getManifestCommand: ["info", "--json", "--verbose"],
|
|
1104
|
+
requiresManifestVersionLookup: true,
|
|
1105
|
+
outputParsers: {
|
|
1106
|
+
listDependencies: parseYarnClassicDependencies,
|
|
1107
|
+
getRegistryManifest: parseYarnClassicManifest,
|
|
1108
|
+
getRegistryMetadata: parseYarnClassicMetadata,
|
|
1109
|
+
getError: parseYarnClassicError
|
|
1110
|
+
},
|
|
1111
|
+
isNotFound: isKnownNotFound
|
|
1112
|
+
},
|
|
1113
|
+
pnpm: {
|
|
1114
|
+
binary: "pnpm",
|
|
1115
|
+
lockfiles: ["pnpm-lock.yaml"],
|
|
1116
|
+
addCommand: "add",
|
|
1117
|
+
installCommand: ["install"],
|
|
1118
|
+
forceFlag: "--force",
|
|
1119
|
+
saveExactFlag: "--save-exact",
|
|
1120
|
+
saveTildeFlag: "--save-tilde",
|
|
1121
|
+
saveDevFlag: "--save-dev",
|
|
1122
|
+
noLockfileFlag: "--no-lockfile",
|
|
1123
|
+
ignoreScriptsFlag: "--ignore-scripts",
|
|
1124
|
+
ignorePeerDependenciesFlag: "--strict-peer-dependencies=false",
|
|
1125
|
+
configFiles: [".npmrc", "pnpm-workspace.yaml"],
|
|
1126
|
+
getRegistryOptions: (registry) => ({ args: ["--registry", registry] }),
|
|
1127
|
+
versionCommand: ["--version"],
|
|
1128
|
+
listDependenciesCommand: ["list", "--depth=0", "--json"],
|
|
1129
|
+
getReleaseAgeConfigCommand: ["config", "get", "minimum-release-age"],
|
|
1130
|
+
getPackageNameCommand: ["pkg", "get", "name"],
|
|
1131
|
+
getManifestCommand: ["view", "--json"],
|
|
1132
|
+
viewCommandFieldArgFormatter: (fields) => [...fields],
|
|
1133
|
+
outputParsers: {
|
|
1134
|
+
listDependencies: parseNpmLikeDependencies,
|
|
1135
|
+
getRegistryManifest: parseNpmLikeManifest,
|
|
1136
|
+
getRegistryMetadata: parseNpmLikeMetadata,
|
|
1137
|
+
getError: parseNpmLikeError,
|
|
1138
|
+
getReleaseAge: parsePnpmReleaseAge
|
|
1139
|
+
},
|
|
1140
|
+
isNotFound: isKnownNotFound
|
|
1141
|
+
},
|
|
1142
|
+
bun: {
|
|
1143
|
+
binary: "bun",
|
|
1144
|
+
lockfiles: ["bun.lockb", "bun.lock"],
|
|
1145
|
+
addCommand: "add",
|
|
1146
|
+
installCommand: ["install"],
|
|
1147
|
+
forceFlag: "--force",
|
|
1148
|
+
saveExactFlag: "--exact",
|
|
1149
|
+
saveTildeFlag: "",
|
|
1150
|
+
// Bun does not have a flag for tilde, it defaults to caret.
|
|
1151
|
+
saveDevFlag: "--development",
|
|
1152
|
+
noLockfileFlag: "",
|
|
1153
|
+
// Bun does not have a flag for this.
|
|
1154
|
+
ignoreScriptsFlag: "--ignore-scripts",
|
|
1155
|
+
configFiles: ["bunfig.toml", ".npmrc"],
|
|
1156
|
+
copyConfigFromProject: true,
|
|
1157
|
+
getRegistryOptions: (registry) => ({ args: ["--registry", registry] }),
|
|
1158
|
+
versionCommand: ["--version"],
|
|
1159
|
+
listDependenciesCommand: ["pm", "ls"],
|
|
1160
|
+
getManifestCommand: ["pm", "view", "--json"],
|
|
1161
|
+
getRegistryMetadata: async (packageName, fetchAndParse) => {
|
|
1162
|
+
const [distTags, versions] = await Promise.all([
|
|
1163
|
+
fetchAndParse(["pm", "view", "--json", packageName, "dist-tags"], (stdout) => {
|
|
1164
|
+
if (!stdout) {
|
|
1165
|
+
return {};
|
|
1166
|
+
}
|
|
1167
|
+
const parsed = JSON.parse(stdout);
|
|
1168
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
1169
|
+
}),
|
|
1170
|
+
fetchAndParse(["pm", "view", "--json", packageName, "versions"], (stdout) => {
|
|
1171
|
+
if (!stdout) {
|
|
1172
|
+
return null;
|
|
1173
|
+
}
|
|
1174
|
+
const parsed = JSON.parse(stdout);
|
|
1175
|
+
return Array.isArray(parsed) ? parsed : [parsed];
|
|
1176
|
+
})
|
|
1177
|
+
]);
|
|
1178
|
+
if (!versions || versions.length === 0) {
|
|
1179
|
+
return null;
|
|
1180
|
+
}
|
|
1181
|
+
return {
|
|
1182
|
+
name: packageName,
|
|
1183
|
+
"dist-tags": distTags || {},
|
|
1184
|
+
versions
|
|
1185
|
+
};
|
|
1186
|
+
},
|
|
1187
|
+
outputParsers: {
|
|
1188
|
+
listDependencies: parseBunDependencies,
|
|
1189
|
+
getRegistryManifest: parseNpmLikeManifest,
|
|
1190
|
+
getRegistryMetadata: parseNpmLikeMetadata,
|
|
1191
|
+
getError: parseNpmLikeError
|
|
1192
|
+
},
|
|
1193
|
+
isNotFound: isKnownNotFound
|
|
1194
|
+
}
|
|
1195
|
+
};
|
|
1196
|
+
var PACKAGE_MANAGER_PRECEDENCE = [
|
|
1197
|
+
"pnpm",
|
|
1198
|
+
"yarn",
|
|
1199
|
+
"bun",
|
|
1200
|
+
"npm"
|
|
1201
|
+
];
|
|
1202
|
+
|
|
1203
|
+
// packages/angular/cli/src/package-managers/discovery.js
|
|
1204
|
+
async function findLockfiles(host, directory, logger) {
|
|
1205
|
+
logger?.debug(`Searching for lockfiles in '${directory}'...`);
|
|
1206
|
+
const foundPackageManagers = /* @__PURE__ */ new Set();
|
|
1207
|
+
const checks = [];
|
|
1208
|
+
for (const [name, descriptor] of Object.entries(SUPPORTED_PACKAGE_MANAGERS)) {
|
|
1209
|
+
const manager = name;
|
|
1210
|
+
for (const lockfile of descriptor.lockfiles) {
|
|
1211
|
+
checks.push((async () => {
|
|
1212
|
+
try {
|
|
1213
|
+
const path2 = join2(directory, lockfile);
|
|
1214
|
+
const stats = await host.stat(path2);
|
|
1215
|
+
if (stats.isFile()) {
|
|
1216
|
+
logger?.debug(` Found '${lockfile}'.`);
|
|
1217
|
+
foundPackageManagers.add(manager);
|
|
1218
|
+
}
|
|
1219
|
+
} catch {
|
|
1220
|
+
}
|
|
1221
|
+
})());
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
await Promise.all(checks);
|
|
1225
|
+
return foundPackageManagers;
|
|
1226
|
+
}
|
|
1227
|
+
async function isDirectory(host, path2) {
|
|
1228
|
+
try {
|
|
1229
|
+
return (await host.stat(path2)).isDirectory();
|
|
1230
|
+
} catch {
|
|
1231
|
+
return false;
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
async function discover(host, startDir, logger) {
|
|
1235
|
+
logger?.debug(`Starting package manager discovery in '${startDir}'...`);
|
|
1236
|
+
let currentDir = startDir;
|
|
1237
|
+
while (true) {
|
|
1238
|
+
const found = await findLockfiles(host, currentDir, logger);
|
|
1239
|
+
if (found.size > 0) {
|
|
1240
|
+
logger?.debug(`Found lockfile(s): [${[...found].join(", ")}]. Applying precedence...`);
|
|
1241
|
+
for (const packageManager of PACKAGE_MANAGER_PRECEDENCE) {
|
|
1242
|
+
if (found.has(packageManager)) {
|
|
1243
|
+
logger?.debug(`Selected '${packageManager}' based on precedence.`);
|
|
1244
|
+
return packageManager;
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
if (await isDirectory(host, join2(currentDir, ".git"))) {
|
|
1249
|
+
logger?.debug(`Reached repository root at '${currentDir}'. Stopping search.`);
|
|
1250
|
+
return null;
|
|
1251
|
+
}
|
|
1252
|
+
const parentDir = dirname(currentDir);
|
|
1253
|
+
if (parentDir === currentDir) {
|
|
1254
|
+
logger?.debug("Reached filesystem root. No lockfile found.");
|
|
1255
|
+
return null;
|
|
1256
|
+
}
|
|
1257
|
+
currentDir = parentDir;
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
// packages/angular/cli/src/package-managers/host.js
|
|
1262
|
+
import { spawn } from "node:child_process";
|
|
1263
|
+
import { constants } from "node:fs";
|
|
1264
|
+
import { copyFile, mkdir, mkdtemp, readFile as readFile2, rm, stat, writeFile } from "node:fs/promises";
|
|
1265
|
+
import { platform as platform2, tmpdir } from "node:os";
|
|
1266
|
+
import { join as join3 } from "node:path";
|
|
1267
|
+
|
|
1268
|
+
// packages/angular/cli/src/package-managers/error.js
|
|
1269
|
+
var PackageManagerError = class extends Error {
|
|
1270
|
+
stdout;
|
|
1271
|
+
stderr;
|
|
1272
|
+
exitCode;
|
|
1273
|
+
/**
|
|
1274
|
+
* Creates a new `PackageManagerError` instance.
|
|
1275
|
+
* @param message The error message.
|
|
1276
|
+
* @param stdout The standard output of the failed process.
|
|
1277
|
+
* @param stderr The standard error of the failed process.
|
|
1278
|
+
* @param exitCode The exit code of the failed process.
|
|
1279
|
+
*/
|
|
1280
|
+
constructor(message, stdout, stderr, exitCode) {
|
|
1281
|
+
super(message);
|
|
1282
|
+
this.stdout = stdout;
|
|
1283
|
+
this.stderr = stderr;
|
|
1284
|
+
this.exitCode = exitCode;
|
|
1285
|
+
}
|
|
1286
|
+
};
|
|
1287
|
+
|
|
1288
|
+
// packages/angular/cli/src/package-managers/host.js
|
|
1289
|
+
var NodeJS_HOST = {
|
|
1290
|
+
stat,
|
|
1291
|
+
requiresQuoting: platform2() === "win32",
|
|
1292
|
+
mkdir,
|
|
1293
|
+
readFile: (path2) => readFile2(path2, { encoding: "utf8" }),
|
|
1294
|
+
copyFile: (src, dest) => copyFile(src, dest, constants.COPYFILE_FICLONE),
|
|
1295
|
+
writeFile,
|
|
1296
|
+
createTempDirectory: (baseDir) => mkdtemp(join3(baseDir ?? tmpdir(), "angular-cli-tmp-packages-")),
|
|
1297
|
+
deleteDirectory: (path2) => rm(path2, { recursive: true, force: true }),
|
|
1298
|
+
runCommand: async (command, args, options = {}) => {
|
|
1299
|
+
const signal = options.timeout ? AbortSignal.timeout(options.timeout) : void 0;
|
|
1300
|
+
const isWin32 = platform2() === "win32";
|
|
1301
|
+
return new Promise((resolve2, reject) => {
|
|
1302
|
+
const env2 = {
|
|
1303
|
+
...process.env,
|
|
1304
|
+
...options.env,
|
|
1305
|
+
// NPM updater notifier will prevents the child process from closing until it timeout after 3 minutes.
|
|
1306
|
+
NO_UPDATE_NOTIFIER: "1",
|
|
1307
|
+
NPM_CONFIG_UPDATE_NOTIFIER: "false"
|
|
1308
|
+
};
|
|
1309
|
+
if ((env2["npm_config_registry"] === "https://registry.yarnpkg.com" || env2["NPM_CONFIG_REGISTRY"] === "https://registry.yarnpkg.com") && (env2["npm_config_user_agent"]?.includes("yarn") || env2["NPM_CONFIG_USER_AGENT"]?.includes("yarn"))) {
|
|
1310
|
+
delete env2["npm_config_registry"];
|
|
1311
|
+
delete env2["NPM_CONFIG_REGISTRY"];
|
|
1312
|
+
}
|
|
1313
|
+
const spawnOptions = {
|
|
1314
|
+
shell: isWin32,
|
|
1315
|
+
stdio: options.stdio ?? "pipe",
|
|
1316
|
+
signal,
|
|
1317
|
+
cwd: options.cwd,
|
|
1318
|
+
env: env2
|
|
1319
|
+
};
|
|
1320
|
+
const childProcess = isWin32 ? spawn(`${command} ${args.join(" ")}`, spawnOptions) : spawn(command, args, spawnOptions);
|
|
1321
|
+
let stdout = "";
|
|
1322
|
+
childProcess.stdout?.on("data", (data) => stdout += data.toString());
|
|
1323
|
+
let stderr = "";
|
|
1324
|
+
childProcess.stderr?.on("data", (data) => stderr += data.toString());
|
|
1325
|
+
childProcess.on("close", (code) => {
|
|
1326
|
+
if (code === 0) {
|
|
1327
|
+
resolve2({ stdout, stderr });
|
|
1328
|
+
} else {
|
|
1329
|
+
const message = `Process exited with code ${code}.`;
|
|
1330
|
+
reject(new PackageManagerError(message, stdout, stderr, code));
|
|
1331
|
+
}
|
|
1332
|
+
});
|
|
1333
|
+
childProcess.on("error", (err) => {
|
|
1334
|
+
if (err.name === "AbortError") {
|
|
1335
|
+
const message2 = `Process timed out.`;
|
|
1336
|
+
reject(new PackageManagerError(message2, stdout, stderr, null));
|
|
1337
|
+
return;
|
|
1338
|
+
}
|
|
1339
|
+
const message = `Process failed with error: ${err.message}`;
|
|
1340
|
+
reject(new PackageManagerError(message, stdout, stderr, null));
|
|
1341
|
+
});
|
|
1342
|
+
});
|
|
1343
|
+
}
|
|
1344
|
+
};
|
|
1345
|
+
|
|
1346
|
+
// packages/angular/cli/src/package-managers/package-manager.js
|
|
1347
|
+
import { join as join4, relative, resolve } from "node:path";
|
|
1348
|
+
import npa from "npm-package-arg";
|
|
1349
|
+
import { maxSatisfying, valid as valid2 } from "semver";
|
|
1350
|
+
var METADATA_FIELDS = ["name", "dist-tags", "versions", "time"];
|
|
1351
|
+
var MANIFEST_FIELDS = [
|
|
1352
|
+
"name",
|
|
1353
|
+
"version",
|
|
1354
|
+
"deprecated",
|
|
1355
|
+
"dependencies",
|
|
1356
|
+
"peerDependencies",
|
|
1357
|
+
"devDependencies",
|
|
1358
|
+
"homepage",
|
|
1359
|
+
"schematics",
|
|
1360
|
+
"ng-add",
|
|
1361
|
+
"ng-update"
|
|
1362
|
+
];
|
|
1363
|
+
var PackageManager = class {
|
|
1364
|
+
host;
|
|
1365
|
+
cwd;
|
|
1366
|
+
descriptor;
|
|
1367
|
+
options;
|
|
1368
|
+
#manifestCache = /* @__PURE__ */ new Map();
|
|
1369
|
+
#metadataCache = /* @__PURE__ */ new Map();
|
|
1370
|
+
#initializationError;
|
|
1371
|
+
#dependencyCache = null;
|
|
1372
|
+
#version;
|
|
1373
|
+
#minimumReleaseAge;
|
|
1374
|
+
#activeTasks = 0;
|
|
1375
|
+
#pendingTasks = [];
|
|
1376
|
+
#maxConcurrent = 5;
|
|
1377
|
+
/**
|
|
1378
|
+
* Creates a new `PackageManager` instance.
|
|
1379
|
+
* @param host A `Host` instance for interacting with the file system and running commands.
|
|
1380
|
+
* @param cwd The absolute path to the project's working directory.
|
|
1381
|
+
* @param descriptor A `PackageManagerDescriptor` that defines the commands for a specific package manager.
|
|
1382
|
+
* @param options An options object to configure the instance.
|
|
1383
|
+
*/
|
|
1384
|
+
constructor(host, cwd, descriptor, options = {}) {
|
|
1385
|
+
this.host = host;
|
|
1386
|
+
this.cwd = cwd;
|
|
1387
|
+
this.descriptor = descriptor;
|
|
1388
|
+
this.options = options;
|
|
1389
|
+
if (this.options.dryRun && !this.options.logger) {
|
|
1390
|
+
throw new Error("A logger must be provided when dryRun is enabled.");
|
|
1391
|
+
}
|
|
1392
|
+
this.#version = options.version;
|
|
1393
|
+
this.#initializationError = options.initializationError;
|
|
1394
|
+
}
|
|
1395
|
+
/**
|
|
1396
|
+
* The name of the package manager's binary.
|
|
1397
|
+
*/
|
|
1398
|
+
get name() {
|
|
1399
|
+
return this.descriptor.binary;
|
|
1400
|
+
}
|
|
1401
|
+
/**
|
|
1402
|
+
* Ensures that the package manager is installed and available in the PATH.
|
|
1403
|
+
* If it is not, this method will throw an error with instructions on how to install it.
|
|
1404
|
+
*
|
|
1405
|
+
* @throws {Error} If the package manager is not installed.
|
|
1406
|
+
*/
|
|
1407
|
+
ensureInstalled() {
|
|
1408
|
+
if (this.#initializationError) {
|
|
1409
|
+
throw this.#initializationError;
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
/**
|
|
1413
|
+
* A private method to lazily populate the dependency cache.
|
|
1414
|
+
* This is a performance optimization to avoid running `npm list` multiple times.
|
|
1415
|
+
* @returns A promise that resolves to the dependency cache map.
|
|
1416
|
+
*/
|
|
1417
|
+
async #populateDependencyCache() {
|
|
1418
|
+
if (this.#dependencyCache !== null) {
|
|
1419
|
+
return this.#dependencyCache;
|
|
1420
|
+
}
|
|
1421
|
+
const args = this.descriptor.listDependenciesCommand;
|
|
1422
|
+
const workspacePackageName = await this.getCurrentPackageName();
|
|
1423
|
+
const dependencies = await this.#fetchAndParse(args, (stdout, logger) => this.descriptor.outputParsers.listDependencies(stdout, logger, { workspacePackageName }));
|
|
1424
|
+
return this.#dependencyCache = dependencies ?? /* @__PURE__ */ new Map();
|
|
1425
|
+
}
|
|
1426
|
+
/**
|
|
1427
|
+
* A private method to run a command using the package manager's binary.
|
|
1428
|
+
* @param args The arguments to pass to the command.
|
|
1429
|
+
* @param options Options for the child process.
|
|
1430
|
+
* @returns A promise that resolves with the standard output and standard error of the command.
|
|
1431
|
+
*/
|
|
1432
|
+
async #runWithThrottle(action) {
|
|
1433
|
+
if (this.#activeTasks >= this.#maxConcurrent) {
|
|
1434
|
+
await new Promise((resolve2) => {
|
|
1435
|
+
this.#pendingTasks.push(resolve2);
|
|
1436
|
+
});
|
|
1437
|
+
} else {
|
|
1438
|
+
this.#activeTasks++;
|
|
1439
|
+
}
|
|
1440
|
+
try {
|
|
1441
|
+
return await action();
|
|
1442
|
+
} finally {
|
|
1443
|
+
const next = this.#pendingTasks.shift();
|
|
1444
|
+
if (next) {
|
|
1445
|
+
next();
|
|
1446
|
+
} else {
|
|
1447
|
+
this.#activeTasks--;
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
async #run(args, options = {}) {
|
|
1452
|
+
return this.#runWithThrottle(async () => {
|
|
1453
|
+
this.ensureInstalled();
|
|
1454
|
+
const { registry, cwd, ...runOptions } = options;
|
|
1455
|
+
const finalArgs = [...args];
|
|
1456
|
+
let finalEnv;
|
|
1457
|
+
if (registry) {
|
|
1458
|
+
const registryOptions = this.descriptor.getRegistryOptions?.(registry);
|
|
1459
|
+
if (!registryOptions) {
|
|
1460
|
+
throw new Error(`The configured package manager, '${this.descriptor.binary}', does not support a custom registry.`);
|
|
1461
|
+
}
|
|
1462
|
+
if (registryOptions.args) {
|
|
1463
|
+
finalArgs.push(...registryOptions.args);
|
|
1464
|
+
}
|
|
1465
|
+
if (registryOptions.env) {
|
|
1466
|
+
finalEnv = registryOptions.env;
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
const executionDirectory = cwd ?? this.cwd;
|
|
1470
|
+
if (this.options.dryRun) {
|
|
1471
|
+
this.options.logger?.info(`[DRY RUN] Would execute in [${executionDirectory}]: ${this.descriptor.binary} ${finalArgs.join(" ")}`);
|
|
1472
|
+
return { stdout: "", stderr: "" };
|
|
1473
|
+
}
|
|
1474
|
+
const commandResult = await this.host.runCommand(this.descriptor.binary, finalArgs, {
|
|
1475
|
+
...runOptions,
|
|
1476
|
+
cwd: executionDirectory,
|
|
1477
|
+
stdio: "pipe",
|
|
1478
|
+
env: finalEnv
|
|
1479
|
+
});
|
|
1480
|
+
return { stdout: commandResult.stdout.trim(), stderr: commandResult.stderr.trim() };
|
|
1481
|
+
});
|
|
1482
|
+
}
|
|
1483
|
+
/**
|
|
1484
|
+
* A private, generic method to encapsulate the common logic of running a command,
|
|
1485
|
+
* handling errors, and parsing the output.
|
|
1486
|
+
* @param args The arguments to pass to the command.
|
|
1487
|
+
* @param parser A function that parses the command's stdout.
|
|
1488
|
+
* @param options Options for the command, including caching.
|
|
1489
|
+
* @returns A promise that resolves to the parsed data, or null if not found.
|
|
1490
|
+
*/
|
|
1491
|
+
async #fetchAndParse(args, parser, options = {}) {
|
|
1492
|
+
const { cache, cacheKey, bypassCache, ...runOptions } = options;
|
|
1493
|
+
if (!bypassCache && cache && cacheKey && cache.has(cacheKey)) {
|
|
1494
|
+
return cache.get(cacheKey);
|
|
1495
|
+
}
|
|
1496
|
+
let stdout;
|
|
1497
|
+
let stderr;
|
|
1498
|
+
let exitCode;
|
|
1499
|
+
let thrownError;
|
|
1500
|
+
try {
|
|
1501
|
+
({ stdout, stderr } = await this.#run(args, runOptions));
|
|
1502
|
+
exitCode = 0;
|
|
1503
|
+
} catch (e) {
|
|
1504
|
+
thrownError = e;
|
|
1505
|
+
if (e instanceof PackageManagerError) {
|
|
1506
|
+
stdout = e.stdout;
|
|
1507
|
+
stderr = e.stderr;
|
|
1508
|
+
exitCode = e.exitCode;
|
|
1509
|
+
} else {
|
|
1510
|
+
throw e;
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
const getError = this.descriptor.outputParsers.getError;
|
|
1514
|
+
const parsedError = getError?.(stdout, this.options.logger) ?? getError?.(stderr, this.options.logger) ?? null;
|
|
1515
|
+
if (parsedError) {
|
|
1516
|
+
this.options.logger?.debug(`[${this.descriptor.binary}] Structured error (code: ${parsedError.code}): ${parsedError.summary}`);
|
|
1517
|
+
if (this.descriptor.isNotFound(parsedError)) {
|
|
1518
|
+
if (cache && cacheKey) {
|
|
1519
|
+
cache.set(cacheKey, null);
|
|
1520
|
+
}
|
|
1521
|
+
return null;
|
|
1522
|
+
} else {
|
|
1523
|
+
throw new PackageManagerError(parsedError.summary, stdout, stderr, exitCode);
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
if (thrownError) {
|
|
1527
|
+
throw thrownError;
|
|
1528
|
+
}
|
|
1529
|
+
try {
|
|
1530
|
+
const result = parser(stdout, this.options.logger);
|
|
1531
|
+
if (cache && cacheKey) {
|
|
1532
|
+
cache.set(cacheKey, result);
|
|
1533
|
+
}
|
|
1534
|
+
return result;
|
|
1535
|
+
} catch (e) {
|
|
1536
|
+
const message = `Failed to parse package manager output: ${e instanceof Error ? e.message : ""}`;
|
|
1537
|
+
throw new PackageManagerError(message, stdout, stderr, exitCode);
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
/**
|
|
1541
|
+
* Adds a package to the project's dependencies.
|
|
1542
|
+
* @param packageName The name of the package to add.
|
|
1543
|
+
* @param save The save strategy to use.
|
|
1544
|
+
* - `exact`: The package will be saved with an exact version.
|
|
1545
|
+
* - `tilde`: The package will be saved with a tilde version range (`~`).
|
|
1546
|
+
* - `none`: The package will be saved with the default version range (`^`).
|
|
1547
|
+
* @param asDevDependency Whether to install the package as a dev dependency.
|
|
1548
|
+
* @param noLockfile Whether to skip updating the lockfile.
|
|
1549
|
+
* @param options Extra options for the command.
|
|
1550
|
+
* @returns A promise that resolves when the command is complete.
|
|
1551
|
+
*/
|
|
1552
|
+
async add(packageName, save, asDevDependency, noLockfile, ignoreScripts, options = {}) {
|
|
1553
|
+
const flags = [
|
|
1554
|
+
asDevDependency ? this.descriptor.saveDevFlag : "",
|
|
1555
|
+
save === "exact" ? this.descriptor.saveExactFlag : "",
|
|
1556
|
+
save === "tilde" ? this.descriptor.saveTildeFlag : "",
|
|
1557
|
+
noLockfile ? this.descriptor.noLockfileFlag : "",
|
|
1558
|
+
ignoreScripts ? this.descriptor.ignoreScriptsFlag : ""
|
|
1559
|
+
].filter((flag) => flag);
|
|
1560
|
+
const specifier = this.host.requiresQuoting ? `"${packageName}"` : packageName;
|
|
1561
|
+
const args = [this.descriptor.addCommand, specifier, ...flags];
|
|
1562
|
+
await this.#run(args, options);
|
|
1563
|
+
this.#dependencyCache = null;
|
|
1564
|
+
}
|
|
1565
|
+
/**
|
|
1566
|
+
* Installs all dependencies in the project.
|
|
1567
|
+
* @param options Options for the installation.
|
|
1568
|
+
* @param options.timeout The maximum time in milliseconds to wait for the command to complete.
|
|
1569
|
+
* @param options.force If true, forces a clean install, potentially overwriting existing modules.
|
|
1570
|
+
* @param options.registry The registry to use for the installation.
|
|
1571
|
+
* @param options.ignoreScripts If true, prevents lifecycle scripts from being executed.
|
|
1572
|
+
* @returns A promise that resolves when the command is complete.
|
|
1573
|
+
*/
|
|
1574
|
+
async install(options = { ignoreScripts: true }) {
|
|
1575
|
+
const flags = [
|
|
1576
|
+
options.force ? this.descriptor.forceFlag : "",
|
|
1577
|
+
options.ignoreScripts ? this.descriptor.ignoreScriptsFlag : "",
|
|
1578
|
+
options.ignorePeerDependencies ? this.descriptor.ignorePeerDependenciesFlag ?? "" : ""
|
|
1579
|
+
].filter((flag) => flag);
|
|
1580
|
+
const args = [...this.descriptor.installCommand, ...flags];
|
|
1581
|
+
await this.#run(args, options);
|
|
1582
|
+
this.#dependencyCache = null;
|
|
1583
|
+
}
|
|
1584
|
+
/**
|
|
1585
|
+
* Gets the name of the package in the current project.
|
|
1586
|
+
*/
|
|
1587
|
+
async getCurrentPackageName() {
|
|
1588
|
+
if (this.descriptor.getPackageNameCommand) {
|
|
1589
|
+
try {
|
|
1590
|
+
const { stdout } = await this.#run(this.descriptor.getPackageNameCommand);
|
|
1591
|
+
if (stdout) {
|
|
1592
|
+
return JSON.parse(stdout);
|
|
1593
|
+
}
|
|
1594
|
+
} catch {
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
try {
|
|
1598
|
+
const content = await this.host.readFile(join4(this.cwd, "package.json"));
|
|
1599
|
+
const pkgJson = JSON.parse(content);
|
|
1600
|
+
return pkgJson.name;
|
|
1601
|
+
} catch {
|
|
1602
|
+
return void 0;
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
/**
|
|
1606
|
+
* Gets the version of the package manager binary.
|
|
1607
|
+
*/
|
|
1608
|
+
async getVersion() {
|
|
1609
|
+
if (this.#version) {
|
|
1610
|
+
return this.#version;
|
|
1611
|
+
}
|
|
1612
|
+
const { stdout } = await this.#run(this.descriptor.versionCommand);
|
|
1613
|
+
this.#version = stdout.trim();
|
|
1614
|
+
if (!valid2(this.#version)) {
|
|
1615
|
+
throw new Error(`Invalid semver version for ${this.name}: "${this.#version}"`);
|
|
1616
|
+
}
|
|
1617
|
+
return this.#version;
|
|
1618
|
+
}
|
|
1619
|
+
/**
|
|
1620
|
+
* Gets the installed details of a package from the project's dependencies.
|
|
1621
|
+
* @param packageName The name of the package to check.
|
|
1622
|
+
* @returns A promise that resolves to the installed package details, or `null` if the package is not installed.
|
|
1623
|
+
*/
|
|
1624
|
+
async getInstalledPackage(packageName) {
|
|
1625
|
+
const cache = await this.#populateDependencyCache();
|
|
1626
|
+
return cache.get(packageName) ?? null;
|
|
1627
|
+
}
|
|
1628
|
+
/**
|
|
1629
|
+
* Gets a map of all top-level dependencies installed in the project.
|
|
1630
|
+
* @returns A promise that resolves to a map of package names to their installed package details.
|
|
1631
|
+
*/
|
|
1632
|
+
async getProjectDependencies() {
|
|
1633
|
+
const cache = await this.#populateDependencyCache();
|
|
1634
|
+
return new Map(cache);
|
|
1635
|
+
}
|
|
1636
|
+
/**
|
|
1637
|
+
* Fetches the registry metadata for a package. This is the full metadata,
|
|
1638
|
+
* including all versions and distribution tags.
|
|
1639
|
+
* @param packageName The name of the package to fetch the metadata for.
|
|
1640
|
+
* @param options Options for the fetch.
|
|
1641
|
+
* @param options.timeout The maximum time in milliseconds to wait for the command to complete.
|
|
1642
|
+
* @param options.registry The registry to use for the fetch.
|
|
1643
|
+
* @param options.bypassCache If true, ignores the in-memory cache and fetches fresh data.
|
|
1644
|
+
* @returns A promise that resolves to the `PackageMetadata` object, or `null` if the package is not found.
|
|
1645
|
+
*/
|
|
1646
|
+
async getRegistryMetadata(packageName, options = {}) {
|
|
1647
|
+
const cacheKey = options.registry ? `${packageName}|${options.registry}` : packageName;
|
|
1648
|
+
if (!options.bypassCache) {
|
|
1649
|
+
const cached = this.#metadataCache.get(cacheKey);
|
|
1650
|
+
if (cached !== void 0) {
|
|
1651
|
+
return cached;
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
let metadata;
|
|
1655
|
+
if (this.descriptor.getRegistryMetadata) {
|
|
1656
|
+
metadata = await this.descriptor.getRegistryMetadata(packageName, (args, parser) => this.#fetchAndParse(args, parser, options));
|
|
1657
|
+
} else {
|
|
1658
|
+
const commandArgs = [...this.descriptor.getManifestCommand, packageName];
|
|
1659
|
+
const formatter = this.descriptor.viewCommandFieldArgFormatter;
|
|
1660
|
+
if (formatter) {
|
|
1661
|
+
commandArgs.push(...formatter(METADATA_FIELDS));
|
|
1662
|
+
}
|
|
1663
|
+
metadata = await this.#fetchAndParse(commandArgs, (stdout, logger) => this.descriptor.outputParsers.getRegistryMetadata(stdout, logger), options);
|
|
1664
|
+
}
|
|
1665
|
+
this.#metadataCache.set(cacheKey, metadata);
|
|
1666
|
+
return metadata;
|
|
1667
|
+
}
|
|
1668
|
+
/**
|
|
1669
|
+
* Fetches the registry manifest for a specific version of a package.
|
|
1670
|
+
* The manifest is similar to the package's `package.json` file.
|
|
1671
|
+
* @param packageName The name of the package to fetch the manifest for.
|
|
1672
|
+
* @param version The version of the package to fetch the manifest for.
|
|
1673
|
+
* @param options Options for the fetch.
|
|
1674
|
+
* @param options.timeout The maximum time in milliseconds to wait for the command to complete.
|
|
1675
|
+
* @param options.registry The registry to use for the fetch.
|
|
1676
|
+
* @param options.bypassCache If true, ignores the in-memory cache and fetches fresh data.
|
|
1677
|
+
* @returns A promise that resolves to the `PackageManifest` object, or `null` if the package is not found.
|
|
1678
|
+
*/
|
|
1679
|
+
async getRegistryManifest(packageName, version, options = {}) {
|
|
1680
|
+
const specifier = this.host.requiresQuoting ? `"${packageName}@${version}"` : `${packageName}@${version}`;
|
|
1681
|
+
const commandArgs = [...this.descriptor.getManifestCommand, specifier];
|
|
1682
|
+
const formatter = this.descriptor.viewCommandFieldArgFormatter;
|
|
1683
|
+
if (formatter) {
|
|
1684
|
+
commandArgs.push(...formatter(MANIFEST_FIELDS));
|
|
1685
|
+
}
|
|
1686
|
+
const cacheKey = options.registry ? `${specifier}|${options.registry}` : specifier;
|
|
1687
|
+
const manifest = await this.#fetchAndParse(commandArgs, (stdout, logger) => this.descriptor.outputParsers.getRegistryManifest(stdout, logger), { ...options, cache: this.#manifestCache, cacheKey });
|
|
1688
|
+
if (manifest && manifest.version !== version) {
|
|
1689
|
+
const manifestSpecifier = `${manifest.name}@${manifest.version}`;
|
|
1690
|
+
const manifestCacheKey = options.registry ? `${manifestSpecifier}|${options.registry}` : manifestSpecifier;
|
|
1691
|
+
this.#manifestCache.set(manifestCacheKey, manifest);
|
|
1692
|
+
}
|
|
1693
|
+
return manifest;
|
|
1694
|
+
}
|
|
1695
|
+
/**
|
|
1696
|
+
* Fetches the manifest for a package.
|
|
1697
|
+
*
|
|
1698
|
+
* This method can resolve manifests for packages from the registry, as well
|
|
1699
|
+
* as those specified by file paths, directory paths, and remote tarballs.
|
|
1700
|
+
* Caching is only supported for registry packages.
|
|
1701
|
+
*
|
|
1702
|
+
* @param specifier The package specifier to resolve the manifest for.
|
|
1703
|
+
* @param options Options for the fetch.
|
|
1704
|
+
* @returns A promise that resolves to the `PackageManifest` object, or `null` if the package is not found.
|
|
1705
|
+
*/
|
|
1706
|
+
async getManifest(specifier, options = {}) {
|
|
1707
|
+
const { name, type, fetchSpec } = typeof specifier === "string" ? npa(specifier) : specifier;
|
|
1708
|
+
switch (type) {
|
|
1709
|
+
case "range":
|
|
1710
|
+
case "version":
|
|
1711
|
+
case "tag": {
|
|
1712
|
+
if (!name) {
|
|
1713
|
+
throw new Error(`Could not parse package name from specifier: ${specifier}`);
|
|
1714
|
+
}
|
|
1715
|
+
let versionSpec = fetchSpec ?? "latest";
|
|
1716
|
+
if (this.descriptor.requiresManifestVersionLookup) {
|
|
1717
|
+
if (type === "tag" || !fetchSpec) {
|
|
1718
|
+
const metadata = await this.getRegistryMetadata(name, options);
|
|
1719
|
+
if (!metadata) {
|
|
1720
|
+
return null;
|
|
1721
|
+
}
|
|
1722
|
+
versionSpec = metadata["dist-tags"][versionSpec];
|
|
1723
|
+
} else if (type === "range") {
|
|
1724
|
+
const metadata = await this.getRegistryMetadata(name, options);
|
|
1725
|
+
if (!metadata) {
|
|
1726
|
+
return null;
|
|
1727
|
+
}
|
|
1728
|
+
versionSpec = maxSatisfying(metadata.versions, fetchSpec) ?? "";
|
|
1729
|
+
}
|
|
1730
|
+
if (!versionSpec) {
|
|
1731
|
+
return null;
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
return this.getRegistryManifest(name, versionSpec, options);
|
|
1735
|
+
}
|
|
1736
|
+
case "directory": {
|
|
1737
|
+
if (!fetchSpec) {
|
|
1738
|
+
throw new Error(`Could not parse directory path from specifier: ${specifier}`);
|
|
1739
|
+
}
|
|
1740
|
+
const manifestPath = join4(fetchSpec, "package.json");
|
|
1741
|
+
const manifest = await this.host.readFile(manifestPath);
|
|
1742
|
+
return JSON.parse(manifest);
|
|
1743
|
+
}
|
|
1744
|
+
case "file":
|
|
1745
|
+
case "remote":
|
|
1746
|
+
case "git": {
|
|
1747
|
+
if (!fetchSpec) {
|
|
1748
|
+
throw new Error(`Could not parse location from specifier: ${specifier}`);
|
|
1749
|
+
}
|
|
1750
|
+
const { workingDirectory, cleanup } = await this.acquireTempPackage(fetchSpec, {
|
|
1751
|
+
...options,
|
|
1752
|
+
ignoreScripts: true
|
|
1753
|
+
});
|
|
1754
|
+
try {
|
|
1755
|
+
const tempManifest = await this.host.readFile(join4(workingDirectory, "package.json"));
|
|
1756
|
+
const { dependencies } = JSON.parse(tempManifest);
|
|
1757
|
+
const packageName = dependencies && Object.keys(dependencies)[0];
|
|
1758
|
+
if (!packageName) {
|
|
1759
|
+
throw new Error(`Could not determine package name for specifier: ${specifier}`);
|
|
1760
|
+
}
|
|
1761
|
+
const packagePath = join4(workingDirectory, "node_modules", packageName);
|
|
1762
|
+
const manifestPath = join4(packagePath, "package.json");
|
|
1763
|
+
const manifest = await this.host.readFile(manifestPath);
|
|
1764
|
+
return JSON.parse(manifest);
|
|
1765
|
+
} finally {
|
|
1766
|
+
await cleanup();
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
default:
|
|
1770
|
+
throw new Error(`Unsupported package specifier type: ${type}`);
|
|
1771
|
+
}
|
|
1772
|
+
}
|
|
1773
|
+
async getTemporaryDirectory() {
|
|
1774
|
+
const { tempDirectory } = this.options;
|
|
1775
|
+
if (tempDirectory && !relative(this.cwd, tempDirectory).startsWith("..")) {
|
|
1776
|
+
try {
|
|
1777
|
+
await this.host.stat(tempDirectory);
|
|
1778
|
+
} catch {
|
|
1779
|
+
await this.host.mkdir(tempDirectory, { recursive: true });
|
|
1780
|
+
}
|
|
1781
|
+
return tempDirectory;
|
|
1782
|
+
}
|
|
1783
|
+
const tempOptions = ["node_modules"];
|
|
1784
|
+
for (const tempOption of tempOptions) {
|
|
1785
|
+
try {
|
|
1786
|
+
const directory = resolve(this.cwd, tempOption);
|
|
1787
|
+
if ((await this.host.stat(directory)).isDirectory()) {
|
|
1788
|
+
return directory;
|
|
1789
|
+
}
|
|
1790
|
+
} catch {
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1794
|
+
/**
|
|
1795
|
+
* Acquires a package by installing it into a temporary directory. The caller is
|
|
1796
|
+
* responsible for managing the lifecycle of the temporary directory by calling
|
|
1797
|
+
* the returned `cleanup` function.
|
|
1798
|
+
*
|
|
1799
|
+
* @param specifier The specifier of the package to install.
|
|
1800
|
+
* @param options Options for the installation.
|
|
1801
|
+
* @returns A promise that resolves to an object containing the temporary path
|
|
1802
|
+
* and a cleanup function.
|
|
1803
|
+
*/
|
|
1804
|
+
async acquireTempPackage(specifier, options = {}) {
|
|
1805
|
+
const workingDirectory = await this.host.createTempDirectory(await this.getTemporaryDirectory());
|
|
1806
|
+
const cleanup = () => this.host.deleteDirectory(workingDirectory);
|
|
1807
|
+
let packageManagerVersion;
|
|
1808
|
+
try {
|
|
1809
|
+
packageManagerVersion = await this.getVersion();
|
|
1810
|
+
} catch {
|
|
1811
|
+
}
|
|
1812
|
+
const tempPackageJson = packageManagerVersion ? { packageManager: `${this.name}@${packageManagerVersion}` } : {};
|
|
1813
|
+
await this.host.writeFile(join4(workingDirectory, "package.json"), JSON.stringify(tempPackageJson, null, 2));
|
|
1814
|
+
if (this.name === "pnpm") {
|
|
1815
|
+
try {
|
|
1816
|
+
const workspaceConfigPath = join4(this.cwd, "pnpm-workspace.yaml");
|
|
1817
|
+
const content = await this.host.readFile(workspaceConfigPath);
|
|
1818
|
+
await this.host.writeFile(join4(workingDirectory, "pnpm-workspace.yaml"), sanitizePnpmWorkspace(content));
|
|
1819
|
+
} catch {
|
|
1820
|
+
await this.host.writeFile(join4(workingDirectory, "pnpm-workspace.yaml"), "packages:\n - '.'\n");
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1823
|
+
if (this.name === "yarn") {
|
|
1824
|
+
await this.host.writeFile(join4(workingDirectory, "yarn.lock"), "");
|
|
1825
|
+
}
|
|
1826
|
+
if (this.descriptor.copyConfigFromProject) {
|
|
1827
|
+
let copiedYarnConfig = false;
|
|
1828
|
+
for (const configFile of this.descriptor.configFiles) {
|
|
1829
|
+
try {
|
|
1830
|
+
const configPath = join4(this.cwd, configFile);
|
|
1831
|
+
let content = await this.host.readFile(configPath);
|
|
1832
|
+
if (this.name === "yarn") {
|
|
1833
|
+
content = sanitizeYarnRc(content);
|
|
1834
|
+
}
|
|
1835
|
+
await this.host.writeFile(join4(workingDirectory, configFile), content);
|
|
1836
|
+
if (this.name === "yarn") {
|
|
1837
|
+
copiedYarnConfig = true;
|
|
1838
|
+
}
|
|
1839
|
+
} catch {
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1842
|
+
if (this.name === "yarn" && !copiedYarnConfig) {
|
|
1843
|
+
await this.host.writeFile(join4(workingDirectory, ".yarnrc.yml"), "nodeLinker: node-modules\n");
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1846
|
+
const flags = [options.ignoreScripts ? this.descriptor.ignoreScriptsFlag : ""].filter((flag) => flag);
|
|
1847
|
+
const args = [this.descriptor.addCommand, specifier, ...flags];
|
|
1848
|
+
try {
|
|
1849
|
+
await this.#run(args, { ...options, cwd: workingDirectory });
|
|
1850
|
+
} catch (e) {
|
|
1851
|
+
await cleanup();
|
|
1852
|
+
throw e;
|
|
1853
|
+
}
|
|
1854
|
+
return { workingDirectory, cleanup };
|
|
1855
|
+
}
|
|
1856
|
+
/**
|
|
1857
|
+
* Gets the active release age gate limit in milliseconds.
|
|
1858
|
+
* @returns A promise that resolves to the limit in milliseconds, or `0` if not set.
|
|
1859
|
+
*/
|
|
1860
|
+
async getMinimumReleaseAge() {
|
|
1861
|
+
if (this.#minimumReleaseAge === void 0) {
|
|
1862
|
+
this.#minimumReleaseAge = this.#resolveMinimumReleaseAge();
|
|
1863
|
+
}
|
|
1864
|
+
return this.#minimumReleaseAge;
|
|
1865
|
+
}
|
|
1866
|
+
/**
|
|
1867
|
+
* Resolves the active minimum release age by querying the package manager configuration
|
|
1868
|
+
* and parsing the resulting setting.
|
|
1869
|
+
* @returns A promise that resolves to the limit in milliseconds, or `0` if not set.
|
|
1870
|
+
*/
|
|
1871
|
+
async #resolveMinimumReleaseAge() {
|
|
1872
|
+
if (this.descriptor.getReleaseAgeConfigCommand && this.descriptor.outputParsers.getReleaseAge) {
|
|
1873
|
+
try {
|
|
1874
|
+
const { stdout } = await this.#run(this.descriptor.getReleaseAgeConfigCommand);
|
|
1875
|
+
const version = await this.getVersion();
|
|
1876
|
+
return this.descriptor.outputParsers.getReleaseAge(stdout, version);
|
|
1877
|
+
} catch {
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
1880
|
+
return 0;
|
|
1881
|
+
}
|
|
1882
|
+
};
|
|
1883
|
+
function sanitizePnpmWorkspace(content) {
|
|
1884
|
+
const lines = content.split(/\r?\n/);
|
|
1885
|
+
const result = [];
|
|
1886
|
+
let inBlockToRemove = false;
|
|
1887
|
+
let blockIndent = 0;
|
|
1888
|
+
for (const line of lines) {
|
|
1889
|
+
const trimmed = line.trim();
|
|
1890
|
+
if (!trimmed) {
|
|
1891
|
+
result.push(line);
|
|
1892
|
+
continue;
|
|
1893
|
+
}
|
|
1894
|
+
const indent = line.length - line.trimStart().length;
|
|
1895
|
+
if (inBlockToRemove) {
|
|
1896
|
+
if (indent > blockIndent) {
|
|
1897
|
+
continue;
|
|
1898
|
+
}
|
|
1899
|
+
inBlockToRemove = false;
|
|
1900
|
+
}
|
|
1901
|
+
if (trimmed.startsWith("overrides:") || trimmed.startsWith("packages:")) {
|
|
1902
|
+
inBlockToRemove = true;
|
|
1903
|
+
blockIndent = indent;
|
|
1904
|
+
if (trimmed.startsWith("packages:")) {
|
|
1905
|
+
result.push(line.replace(/packages:.*/, "packages:\n - '.'"));
|
|
1906
|
+
}
|
|
1907
|
+
continue;
|
|
1908
|
+
}
|
|
1909
|
+
result.push(line);
|
|
1910
|
+
}
|
|
1911
|
+
return result.join("\n");
|
|
1912
|
+
}
|
|
1913
|
+
function sanitizeYarnRc(content) {
|
|
1914
|
+
const lines = content.split(/\r?\n/);
|
|
1915
|
+
const result = [];
|
|
1916
|
+
let inBlockToRemove = false;
|
|
1917
|
+
let blockIndent = 0;
|
|
1918
|
+
for (const line of lines) {
|
|
1919
|
+
const trimmed = line.trim();
|
|
1920
|
+
if (!trimmed) {
|
|
1921
|
+
result.push(line);
|
|
1922
|
+
continue;
|
|
1923
|
+
}
|
|
1924
|
+
const indent = line.length - line.trimStart().length;
|
|
1925
|
+
if (inBlockToRemove) {
|
|
1926
|
+
if (indent > blockIndent) {
|
|
1927
|
+
continue;
|
|
1928
|
+
}
|
|
1929
|
+
inBlockToRemove = false;
|
|
1930
|
+
}
|
|
1931
|
+
if (indent === 0 && (trimmed.startsWith("yarnPath:") || trimmed.startsWith("nodeLinker:") || trimmed.startsWith("plugins:"))) {
|
|
1932
|
+
inBlockToRemove = true;
|
|
1933
|
+
blockIndent = indent;
|
|
1934
|
+
continue;
|
|
1935
|
+
}
|
|
1936
|
+
result.push(line);
|
|
1937
|
+
}
|
|
1938
|
+
result.push("nodeLinker: node-modules");
|
|
1939
|
+
return result.join("\n");
|
|
1940
|
+
}
|
|
1941
|
+
|
|
1942
|
+
// packages/angular/cli/src/package-managers/factory.js
|
|
1943
|
+
var DEFAULT_PACKAGE_MANAGER = "npm";
|
|
1944
|
+
async function getPackageManagerVersion(host, cwd, name, logger) {
|
|
1945
|
+
const descriptor = SUPPORTED_PACKAGE_MANAGERS[name];
|
|
1946
|
+
logger?.debug(`Getting ${name} version...`);
|
|
1947
|
+
const { stdout } = await host.runCommand(descriptor.binary, descriptor.versionCommand, { cwd });
|
|
1948
|
+
const version = stdout.trim();
|
|
1949
|
+
logger?.debug(`${name} version is '${version}'.`);
|
|
1950
|
+
return version;
|
|
1951
|
+
}
|
|
1952
|
+
async function determinePackageManager(host, cwd, configured = [], logger, dryRun) {
|
|
1953
|
+
let [name, version] = configured;
|
|
1954
|
+
let source;
|
|
1955
|
+
if (name) {
|
|
1956
|
+
source = "configured";
|
|
1957
|
+
logger?.debug(`Using configured package manager: '${name}'.`);
|
|
1958
|
+
} else {
|
|
1959
|
+
const discovered = await discover(host, cwd, logger);
|
|
1960
|
+
if (discovered) {
|
|
1961
|
+
name = discovered;
|
|
1962
|
+
source = "discovered";
|
|
1963
|
+
logger?.debug(`Discovered package manager: '${name}'.`);
|
|
1964
|
+
} else {
|
|
1965
|
+
name = DEFAULT_PACKAGE_MANAGER;
|
|
1966
|
+
source = "default";
|
|
1967
|
+
logger?.debug(`No lockfile found. Using default package manager: '${DEFAULT_PACKAGE_MANAGER}'.`);
|
|
1968
|
+
}
|
|
1969
|
+
}
|
|
1970
|
+
if (name === "yarn" && !dryRun) {
|
|
1971
|
+
assert.deepStrictEqual(SUPPORTED_PACKAGE_MANAGERS.yarn.versionCommand, SUPPORTED_PACKAGE_MANAGERS["yarn-classic"].versionCommand, "Yarn and Yarn Classic version commands must match for detection logic to be valid.");
|
|
1972
|
+
try {
|
|
1973
|
+
version ??= await getPackageManagerVersion(host, cwd, name, logger);
|
|
1974
|
+
if (version && major(version) < 2) {
|
|
1975
|
+
name = "yarn-classic";
|
|
1976
|
+
logger?.debug(`Detected yarn classic. Using 'yarn-classic'.`);
|
|
1977
|
+
}
|
|
1978
|
+
} catch {
|
|
1979
|
+
logger?.debug("Failed to get yarn version.");
|
|
1980
|
+
}
|
|
1981
|
+
} else if (name === "yarn") {
|
|
1982
|
+
logger?.debug("Skipping yarn version check due to dry run. Assuming modern yarn.");
|
|
1983
|
+
}
|
|
1984
|
+
return { name, source, version };
|
|
1985
|
+
}
|
|
1986
|
+
async function createPackageManager(options) {
|
|
1987
|
+
const { cwd, configuredPackageManager, logger, dryRun, tempDirectory } = options;
|
|
1988
|
+
const host = NodeJS_HOST;
|
|
1989
|
+
const result = await determinePackageManager(host, cwd, configuredPackageManager, logger, dryRun);
|
|
1990
|
+
const { name, source } = result;
|
|
1991
|
+
let { version } = result;
|
|
1992
|
+
const descriptor = SUPPORTED_PACKAGE_MANAGERS[name];
|
|
1993
|
+
if (!descriptor) {
|
|
1994
|
+
throw new Error(`Unsupported package manager: "${name}"`);
|
|
1995
|
+
}
|
|
1996
|
+
let initializationError;
|
|
1997
|
+
if (!dryRun && !version) {
|
|
1998
|
+
try {
|
|
1999
|
+
version = await getPackageManagerVersion(host, cwd, name, logger);
|
|
2000
|
+
} catch {
|
|
2001
|
+
if (source === "default") {
|
|
2002
|
+
initializationError = new Error(`'${DEFAULT_PACKAGE_MANAGER}' was selected as the default package manager, but it is not installed or cannot be found in the PATH. Please install '${DEFAULT_PACKAGE_MANAGER}' to continue.`);
|
|
2003
|
+
} else {
|
|
2004
|
+
initializationError = new Error(`The project is configured to use '${name}', but it is not installed or cannot be found in the PATH. Please install '${name}' to continue.`);
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
const packageManager = new PackageManager(host, cwd, descriptor, {
|
|
2009
|
+
dryRun,
|
|
2010
|
+
logger,
|
|
2011
|
+
tempDirectory,
|
|
2012
|
+
version,
|
|
2013
|
+
initializationError
|
|
2014
|
+
});
|
|
2015
|
+
logger?.debug(`Successfully created PackageManager for '${name}'.`);
|
|
2016
|
+
return packageManager;
|
|
2017
|
+
}
|
|
2018
|
+
|
|
2019
|
+
// packages/angular/cli/src/utilities/memoize.js
|
|
2020
|
+
function memoize(target, context) {
|
|
2021
|
+
if (context.kind !== "method" && context.kind !== "getter") {
|
|
2022
|
+
throw new Error("Memoize decorator can only be used on methods or get accessors.");
|
|
2023
|
+
}
|
|
2024
|
+
const cache = /* @__PURE__ */ new Map();
|
|
2025
|
+
return function(...args) {
|
|
2026
|
+
for (const arg of args) {
|
|
2027
|
+
if (!isJSONSerializable(arg)) {
|
|
2028
|
+
throw new Error(`Argument ${isNonPrimitive(arg) ? arg.toString() : arg} is JSON serializable.`);
|
|
2029
|
+
}
|
|
2030
|
+
}
|
|
2031
|
+
const key = JSON.stringify(args);
|
|
2032
|
+
if (cache.has(key)) {
|
|
2033
|
+
return cache.get(key);
|
|
2034
|
+
}
|
|
2035
|
+
const result = target.apply(this, args);
|
|
2036
|
+
cache.set(key, result);
|
|
2037
|
+
return result;
|
|
2038
|
+
};
|
|
2039
|
+
}
|
|
2040
|
+
function isNonPrimitive(value) {
|
|
2041
|
+
return value !== null && typeof value === "object" || typeof value === "function" || typeof value === "symbol";
|
|
2042
|
+
}
|
|
2043
|
+
function isJSONSerializable(value) {
|
|
2044
|
+
if (!isNonPrimitive(value)) {
|
|
2045
|
+
return true;
|
|
2046
|
+
}
|
|
2047
|
+
let nestedValues;
|
|
2048
|
+
if (Array.isArray(value)) {
|
|
2049
|
+
nestedValues = value;
|
|
2050
|
+
} else if (Object.prototype.toString.call(value) === "[object Object]") {
|
|
2051
|
+
nestedValues = Object.values(value);
|
|
2052
|
+
}
|
|
2053
|
+
if (!nestedValues || nestedValues.some((v) => !isJSONSerializable(v))) {
|
|
2054
|
+
return false;
|
|
2055
|
+
}
|
|
2056
|
+
return true;
|
|
2057
|
+
}
|
|
2058
|
+
|
|
2059
|
+
// packages/angular/cli/src/command-builder/utilities/json-schema.js
|
|
2060
|
+
import { isJsonObject, json as json3, strings } from "@angular-devkit/core";
|
|
2061
|
+
function checkStringMap(keyValuePairOptions, args) {
|
|
2062
|
+
for (const key of keyValuePairOptions) {
|
|
2063
|
+
const value = args[key];
|
|
2064
|
+
if (!Array.isArray(value)) {
|
|
2065
|
+
continue;
|
|
2066
|
+
}
|
|
2067
|
+
for (const pair of value) {
|
|
2068
|
+
if (pair === void 0) {
|
|
2069
|
+
continue;
|
|
2070
|
+
}
|
|
2071
|
+
if (!pair.includes("=")) {
|
|
2072
|
+
throw new Error(`Invalid value for argument: ${key}, Given: '${pair}', Expected key=value pair`);
|
|
2073
|
+
}
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
2076
|
+
return true;
|
|
2077
|
+
}
|
|
2078
|
+
function coerceToStringMap(value) {
|
|
2079
|
+
const stringMap = {};
|
|
2080
|
+
for (const pair of value) {
|
|
2081
|
+
if (pair === void 0) {
|
|
2082
|
+
continue;
|
|
2083
|
+
}
|
|
2084
|
+
const eqIdx = pair.indexOf("=");
|
|
2085
|
+
if (eqIdx === -1) {
|
|
2086
|
+
return value;
|
|
2087
|
+
}
|
|
2088
|
+
const key = pair.slice(0, eqIdx);
|
|
2089
|
+
stringMap[key] = pair.slice(eqIdx + 1);
|
|
2090
|
+
}
|
|
2091
|
+
return stringMap;
|
|
2092
|
+
}
|
|
2093
|
+
function isStringMap(node) {
|
|
2094
|
+
if (node.properties || node.patternProperties) {
|
|
2095
|
+
return false;
|
|
2096
|
+
}
|
|
2097
|
+
return json3.isJsonObject(node.additionalProperties) && !node.additionalProperties.enum && node.additionalProperties.type === "string";
|
|
2098
|
+
}
|
|
2099
|
+
var SUPPORTED_PRIMITIVE_TYPES = /* @__PURE__ */ new Set(["boolean", "number", "string"]);
|
|
2100
|
+
function isSupportedPrimitiveType(value) {
|
|
2101
|
+
return SUPPORTED_PRIMITIVE_TYPES.has(value);
|
|
2102
|
+
}
|
|
2103
|
+
function isSupportedArrayItemSchema(schema2) {
|
|
2104
|
+
if (typeof schema2.type === "string" && isSupportedPrimitiveType(schema2.type)) {
|
|
2105
|
+
return true;
|
|
2106
|
+
}
|
|
2107
|
+
if (json3.isJsonArray(schema2.enum)) {
|
|
2108
|
+
return true;
|
|
2109
|
+
}
|
|
2110
|
+
if (json3.isJsonArray(schema2.items)) {
|
|
2111
|
+
return schema2.items.some((item) => isJsonObject(item) && isSupportedArrayItemSchema(item));
|
|
2112
|
+
}
|
|
2113
|
+
if (json3.isJsonArray(schema2.oneOf) && schema2.oneOf.some((item) => isJsonObject(item) && isSupportedArrayItemSchema(item))) {
|
|
2114
|
+
return true;
|
|
2115
|
+
}
|
|
2116
|
+
if (json3.isJsonArray(schema2.anyOf) && schema2.anyOf.some((item) => isJsonObject(item) && isSupportedArrayItemSchema(item))) {
|
|
2117
|
+
return true;
|
|
2118
|
+
}
|
|
2119
|
+
return false;
|
|
2120
|
+
}
|
|
2121
|
+
function getSupportedTypes(current) {
|
|
2122
|
+
const typeSet = json3.schema.getTypesOfSchema(current);
|
|
2123
|
+
if (typeSet.size === 0) {
|
|
2124
|
+
return [];
|
|
2125
|
+
}
|
|
2126
|
+
return [...typeSet].filter((type) => {
|
|
2127
|
+
switch (type) {
|
|
2128
|
+
case "boolean":
|
|
2129
|
+
case "number":
|
|
2130
|
+
case "string":
|
|
2131
|
+
return true;
|
|
2132
|
+
case "array":
|
|
2133
|
+
return isJsonObject(current.items) && isSupportedArrayItemSchema(current.items);
|
|
2134
|
+
case "object":
|
|
2135
|
+
return isStringMap(current);
|
|
2136
|
+
default:
|
|
2137
|
+
return false;
|
|
2138
|
+
}
|
|
2139
|
+
});
|
|
2140
|
+
}
|
|
2141
|
+
function getEnumValues(current) {
|
|
2142
|
+
if (json3.isJsonArray(current.enum)) {
|
|
2143
|
+
return current.enum.sort();
|
|
2144
|
+
}
|
|
2145
|
+
if (isJsonObject(current.items)) {
|
|
2146
|
+
const enumValues = getEnumValues(current.items);
|
|
2147
|
+
if (enumValues?.length) {
|
|
2148
|
+
return enumValues;
|
|
2149
|
+
}
|
|
2150
|
+
}
|
|
2151
|
+
if (typeof current.type === "string" && isSupportedPrimitiveType(current.type)) {
|
|
2152
|
+
return [];
|
|
2153
|
+
}
|
|
2154
|
+
const subSchemas = json3.isJsonArray(current.oneOf) && current.oneOf || json3.isJsonArray(current.anyOf) && current.anyOf;
|
|
2155
|
+
if (subSchemas) {
|
|
2156
|
+
for (const subSchema of subSchemas) {
|
|
2157
|
+
if (isJsonObject(subSchema)) {
|
|
2158
|
+
const enumValues = getEnumValues(subSchema);
|
|
2159
|
+
if (enumValues) {
|
|
2160
|
+
return enumValues;
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
2164
|
+
}
|
|
2165
|
+
return [];
|
|
2166
|
+
}
|
|
2167
|
+
function getDefaultValue(current, type) {
|
|
2168
|
+
const defaultValue = current.default;
|
|
2169
|
+
if (defaultValue === void 0) {
|
|
2170
|
+
return void 0;
|
|
2171
|
+
}
|
|
2172
|
+
if (type === "array") {
|
|
2173
|
+
return Array.isArray(defaultValue) && defaultValue.length > 0 ? defaultValue : void 0;
|
|
2174
|
+
}
|
|
2175
|
+
if (typeof defaultValue === type) {
|
|
2176
|
+
return defaultValue;
|
|
2177
|
+
}
|
|
2178
|
+
return void 0;
|
|
2179
|
+
}
|
|
2180
|
+
function getAliases(current) {
|
|
2181
|
+
if (json3.isJsonArray(current.aliases)) {
|
|
2182
|
+
return [...current.aliases].map(String);
|
|
2183
|
+
}
|
|
2184
|
+
if (current.alias) {
|
|
2185
|
+
return [String(current.alias)];
|
|
2186
|
+
}
|
|
2187
|
+
return [];
|
|
2188
|
+
}
|
|
2189
|
+
async function parseJsonSchemaToOptions(registry, schema2, interactive = true) {
|
|
2190
|
+
const options = [];
|
|
2191
|
+
function visitor(current, pointer, parentSchema) {
|
|
2192
|
+
if (!parentSchema || json3.isJsonArray(current) || pointer.split(/\/(?:properties|items|definitions)\//g).length > 2) {
|
|
2193
|
+
return;
|
|
2194
|
+
}
|
|
2195
|
+
if (pointer.includes("/not/")) {
|
|
2196
|
+
throw new Error('The "not" keyword is not supported in JSON Schema.');
|
|
2197
|
+
}
|
|
2198
|
+
const ptr = json3.schema.parseJsonPointer(pointer);
|
|
2199
|
+
if (ptr[ptr.length - 2] !== "properties") {
|
|
2200
|
+
return;
|
|
2201
|
+
}
|
|
2202
|
+
const name = ptr.at(-1);
|
|
2203
|
+
const types = getSupportedTypes(current);
|
|
2204
|
+
if (types.length === 0) {
|
|
2205
|
+
return;
|
|
2206
|
+
}
|
|
2207
|
+
const [type] = types;
|
|
2208
|
+
const $default = current.$default;
|
|
2209
|
+
const $defaultIndex = isJsonObject($default) && $default["$source"] === "argv" ? $default["index"] : void 0;
|
|
2210
|
+
const positional = typeof $defaultIndex === "number" ? $defaultIndex : void 0;
|
|
2211
|
+
let required = json3.isJsonArray(schema2.required) && schema2.required.includes(name);
|
|
2212
|
+
if (required && interactive && current["x-prompt"]) {
|
|
2213
|
+
required = false;
|
|
2214
|
+
}
|
|
2215
|
+
const visible = current.visible !== false;
|
|
2216
|
+
const xDeprecated = current["x-deprecated"];
|
|
2217
|
+
const enumValues = getEnumValues(current);
|
|
2218
|
+
const option = {
|
|
2219
|
+
name,
|
|
2220
|
+
description: String(current.description ?? ""),
|
|
2221
|
+
default: getDefaultValue(current, type),
|
|
2222
|
+
choices: enumValues?.length ? enumValues : void 0,
|
|
2223
|
+
required,
|
|
2224
|
+
alias: getAliases(current),
|
|
2225
|
+
format: typeof current.format === "string" ? current.format : void 0,
|
|
2226
|
+
hidden: !!current.hidden || !visible,
|
|
2227
|
+
userAnalytics: typeof current["x-user-analytics"] === "string" ? current["x-user-analytics"] : void 0,
|
|
2228
|
+
deprecated: xDeprecated === true || typeof xDeprecated === "string" ? xDeprecated : void 0,
|
|
2229
|
+
positional,
|
|
2230
|
+
...type === "object" ? {
|
|
2231
|
+
type: "array",
|
|
2232
|
+
itemValueType: "string"
|
|
2233
|
+
} : {
|
|
2234
|
+
type
|
|
2235
|
+
}
|
|
2236
|
+
};
|
|
2237
|
+
options.push(option);
|
|
2238
|
+
}
|
|
2239
|
+
const flattenedSchema = await registry.\u0275flatten(schema2);
|
|
2240
|
+
json3.schema.visitJsonSchema(flattenedSchema, visitor);
|
|
2241
|
+
return options.sort((a, b) => {
|
|
2242
|
+
if (a.positional) {
|
|
2243
|
+
return b.positional ? a.positional - b.positional : a.name.localeCompare(b.name);
|
|
2244
|
+
} else if (b.positional) {
|
|
2245
|
+
return -1;
|
|
2246
|
+
}
|
|
2247
|
+
return a.name.localeCompare(b.name);
|
|
2248
|
+
});
|
|
2249
|
+
}
|
|
2250
|
+
function addSchemaOptionsToCommand(localYargs, options, includeDefaultValues) {
|
|
2251
|
+
const booleanOptionsWithNoPrefix = /* @__PURE__ */ new Set();
|
|
2252
|
+
const keyValuePairOptions = /* @__PURE__ */ new Set();
|
|
2253
|
+
const optionsWithAnalytics = /* @__PURE__ */ new Map();
|
|
2254
|
+
for (const option of options) {
|
|
2255
|
+
const { default: defaultVal, positional, deprecated, description, alias, userAnalytics, type, itemValueType, hidden, name, choices } = option;
|
|
2256
|
+
let dashedName = strings.dasherize(name);
|
|
2257
|
+
if (type === "boolean" && dashedName.startsWith("no-")) {
|
|
2258
|
+
dashedName = dashedName.slice(3);
|
|
2259
|
+
booleanOptionsWithNoPrefix.add(dashedName);
|
|
2260
|
+
}
|
|
2261
|
+
if (itemValueType) {
|
|
2262
|
+
keyValuePairOptions.add(dashedName);
|
|
2263
|
+
}
|
|
2264
|
+
const sharedOptions = {
|
|
2265
|
+
alias,
|
|
2266
|
+
hidden,
|
|
2267
|
+
description,
|
|
2268
|
+
deprecated,
|
|
2269
|
+
choices,
|
|
2270
|
+
coerce: itemValueType ? coerceToStringMap : void 0,
|
|
2271
|
+
// This should only be done when `--help` is used otherwise default will override options set in angular.json.
|
|
2272
|
+
...includeDefaultValues ? { default: defaultVal } : {}
|
|
2273
|
+
};
|
|
2274
|
+
if (positional === void 0) {
|
|
2275
|
+
localYargs = localYargs.option(dashedName, {
|
|
2276
|
+
array: itemValueType ? true : void 0,
|
|
2277
|
+
type: itemValueType ?? type,
|
|
2278
|
+
...sharedOptions
|
|
2279
|
+
});
|
|
2280
|
+
} else {
|
|
2281
|
+
localYargs = localYargs.positional(dashedName, {
|
|
2282
|
+
type: type === "array" || type === "count" ? "string" : type,
|
|
2283
|
+
...sharedOptions
|
|
2284
|
+
});
|
|
2285
|
+
}
|
|
2286
|
+
if (userAnalytics !== void 0) {
|
|
2287
|
+
optionsWithAnalytics.set(name, userAnalytics);
|
|
2288
|
+
}
|
|
2289
|
+
}
|
|
2290
|
+
if (keyValuePairOptions.size) {
|
|
2291
|
+
localYargs.check(checkStringMap.bind(null, keyValuePairOptions), false);
|
|
2292
|
+
}
|
|
2293
|
+
if (booleanOptionsWithNoPrefix.size) {
|
|
2294
|
+
localYargs.middleware((options2) => {
|
|
2295
|
+
for (const key of booleanOptionsWithNoPrefix) {
|
|
2296
|
+
if (key in options2) {
|
|
2297
|
+
options2[`no-${key}`] = !options2[key];
|
|
2298
|
+
delete options2[key];
|
|
2299
|
+
}
|
|
2300
|
+
}
|
|
2301
|
+
}, false);
|
|
2302
|
+
}
|
|
2303
|
+
return optionsWithAnalytics;
|
|
2304
|
+
}
|
|
2305
|
+
|
|
2306
|
+
// packages/angular/cli/src/command-builder/command-module.js
|
|
2307
|
+
var __runInitializers = function(thisArg, initializers, value) {
|
|
2308
|
+
var useValue = arguments.length > 2;
|
|
2309
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
2310
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
2311
|
+
}
|
|
2312
|
+
return useValue ? value : void 0;
|
|
2313
|
+
};
|
|
2314
|
+
var __esDecorate = function(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
2315
|
+
function accept(f) {
|
|
2316
|
+
if (f !== void 0 && typeof f !== "function")
|
|
2317
|
+
throw new TypeError("Function expected");
|
|
2318
|
+
return f;
|
|
2319
|
+
}
|
|
2320
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
2321
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
2322
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
2323
|
+
var _, done = false;
|
|
2324
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
2325
|
+
var context = {};
|
|
2326
|
+
for (var p in contextIn)
|
|
2327
|
+
context[p] = p === "access" ? {} : contextIn[p];
|
|
2328
|
+
for (var p in contextIn.access)
|
|
2329
|
+
context.access[p] = contextIn.access[p];
|
|
2330
|
+
context.addInitializer = function(f) {
|
|
2331
|
+
if (done)
|
|
2332
|
+
throw new TypeError("Cannot add initializers after decoration has completed");
|
|
2333
|
+
extraInitializers.push(accept(f || null));
|
|
2334
|
+
};
|
|
2335
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
2336
|
+
if (kind === "accessor") {
|
|
2337
|
+
if (result === void 0)
|
|
2338
|
+
continue;
|
|
2339
|
+
if (result === null || typeof result !== "object")
|
|
2340
|
+
throw new TypeError("Object expected");
|
|
2341
|
+
if (_ = accept(result.get))
|
|
2342
|
+
descriptor.get = _;
|
|
2343
|
+
if (_ = accept(result.set))
|
|
2344
|
+
descriptor.set = _;
|
|
2345
|
+
if (_ = accept(result.init))
|
|
2346
|
+
initializers.unshift(_);
|
|
2347
|
+
} else if (_ = accept(result)) {
|
|
2348
|
+
if (kind === "field")
|
|
2349
|
+
initializers.unshift(_);
|
|
2350
|
+
else
|
|
2351
|
+
descriptor[key] = _;
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
if (target)
|
|
2355
|
+
Object.defineProperty(target, contextIn.name, descriptor);
|
|
2356
|
+
done = true;
|
|
2357
|
+
};
|
|
2358
|
+
var CommandModule = (() => {
|
|
2359
|
+
let _instanceExtraInitializers = [];
|
|
2360
|
+
let _getAnalytics_decorators;
|
|
2361
|
+
return class CommandModule {
|
|
2362
|
+
static {
|
|
2363
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? /* @__PURE__ */ Object.create(null) : void 0;
|
|
2364
|
+
_getAnalytics_decorators = [memoize];
|
|
2365
|
+
__esDecorate(this, null, _getAnalytics_decorators, { kind: "method", name: "getAnalytics", static: false, private: false, access: { has: (obj) => "getAnalytics" in obj, get: (obj) => obj.getAnalytics }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
2366
|
+
if (_metadata)
|
|
2367
|
+
Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
2368
|
+
}
|
|
2369
|
+
context = __runInitializers(this, _instanceExtraInitializers);
|
|
2370
|
+
longDescription;
|
|
2371
|
+
longDescriptionRelativePath;
|
|
2372
|
+
shouldReportAnalytics = true;
|
|
2373
|
+
scope = CommandScope.Both;
|
|
2374
|
+
optionsWithAnalytics = /* @__PURE__ */ new Map();
|
|
2375
|
+
constructor(context) {
|
|
2376
|
+
this.context = context;
|
|
2377
|
+
}
|
|
2378
|
+
/**
|
|
2379
|
+
* Description object which contains the long command descroption.
|
|
2380
|
+
* This is used to generate JSON help wich is used in AIO.
|
|
2381
|
+
*
|
|
2382
|
+
* `false` will result in a hidden command.
|
|
2383
|
+
*/
|
|
2384
|
+
get fullDescribe() {
|
|
2385
|
+
if (this.describe === false) {
|
|
2386
|
+
return false;
|
|
2387
|
+
}
|
|
2388
|
+
const description = {
|
|
2389
|
+
describe: this.describe
|
|
2390
|
+
};
|
|
2391
|
+
if (this.longDescription) {
|
|
2392
|
+
description.longDescription = this.longDescription.replace(/\r\n/g, "\n");
|
|
2393
|
+
description.longDescriptionRelativePath = this.longDescriptionRelativePath ?? `@angular/cli/src/commands/${this.commandName}/long-description.md`;
|
|
2394
|
+
}
|
|
2395
|
+
return description;
|
|
2396
|
+
}
|
|
2397
|
+
get commandName() {
|
|
2398
|
+
return this.command.split(" ", 1)[0];
|
|
2399
|
+
}
|
|
2400
|
+
async handler(args) {
|
|
2401
|
+
const { _, $0, ...options } = args;
|
|
2402
|
+
const { logger } = this.context;
|
|
2403
|
+
const camelCasedOptions = {};
|
|
2404
|
+
for (const [key, value] of Object.entries(options)) {
|
|
2405
|
+
camelCasedOptions[yargsParser.camelCase(key)] = value;
|
|
2406
|
+
}
|
|
2407
|
+
const autocompletionExitCode = await considerSettingUpAutocompletion(this.commandName, logger);
|
|
2408
|
+
if (autocompletionExitCode !== void 0) {
|
|
2409
|
+
process.exitCode = autocompletionExitCode;
|
|
2410
|
+
return;
|
|
2411
|
+
}
|
|
2412
|
+
const analytics = await this.getAnalytics();
|
|
2413
|
+
const stopPeriodicFlushes = analytics && analytics.periodFlush();
|
|
2414
|
+
let exitCode;
|
|
2415
|
+
try {
|
|
2416
|
+
if (analytics) {
|
|
2417
|
+
this.reportCommandRunAnalytics(analytics);
|
|
2418
|
+
this.reportWorkspaceInfoAnalytics(analytics);
|
|
2419
|
+
}
|
|
2420
|
+
exitCode = await this.run(camelCasedOptions);
|
|
2421
|
+
} catch (e) {
|
|
2422
|
+
if (e instanceof schema.SchemaValidationException) {
|
|
2423
|
+
logger.fatal(`Error: ${e.message}`);
|
|
2424
|
+
exitCode = 1;
|
|
2425
|
+
} else if (e instanceof PackageManagerError) {
|
|
2426
|
+
const output = e.stderr || e.stdout;
|
|
2427
|
+
logger.fatal(`Error: Package installation failed: ${e.message}${output ? `
|
|
2428
|
+
Output: ${output}` : ""}`);
|
|
2429
|
+
exitCode = 1;
|
|
2430
|
+
} else {
|
|
2431
|
+
throw e;
|
|
2432
|
+
}
|
|
2433
|
+
} finally {
|
|
2434
|
+
await stopPeriodicFlushes?.();
|
|
2435
|
+
if (typeof exitCode === "number" && exitCode > 0) {
|
|
2436
|
+
process.exitCode = exitCode;
|
|
2437
|
+
}
|
|
2438
|
+
}
|
|
2439
|
+
}
|
|
2440
|
+
async getAnalytics() {
|
|
2441
|
+
if (!this.shouldReportAnalytics) {
|
|
2442
|
+
return void 0;
|
|
2443
|
+
}
|
|
2444
|
+
const userId = await getAnalyticsUserId(
|
|
2445
|
+
this.context,
|
|
2446
|
+
// Don't prompt on `ng update`, 'ng version' or `ng analytics`.
|
|
2447
|
+
["version", "update", "analytics"].includes(this.commandName)
|
|
2448
|
+
);
|
|
2449
|
+
if (!userId) {
|
|
2450
|
+
return void 0;
|
|
2451
|
+
}
|
|
2452
|
+
let version;
|
|
2453
|
+
try {
|
|
2454
|
+
version = await this.context.packageManager.getVersion();
|
|
2455
|
+
} catch {
|
|
2456
|
+
}
|
|
2457
|
+
return new AnalyticsCollector(this.context.logger, userId, {
|
|
2458
|
+
name: this.context.packageManager.name,
|
|
2459
|
+
version
|
|
2460
|
+
});
|
|
2461
|
+
}
|
|
2462
|
+
/**
|
|
2463
|
+
* Adds schema options to a command also this keeps track of options that are required for analytics.
|
|
2464
|
+
* **Note:** This method should be called from the command bundler method.
|
|
2465
|
+
*/
|
|
2466
|
+
addSchemaOptionsToCommand(localYargs, options) {
|
|
2467
|
+
const optionsWithAnalytics = addSchemaOptionsToCommand(
|
|
2468
|
+
localYargs,
|
|
2469
|
+
options,
|
|
2470
|
+
// This should only be done when `--help` is used otherwise default will override options set in angular.json.
|
|
2471
|
+
/* includeDefaultValues= */
|
|
2472
|
+
this.context.args.options.help
|
|
2473
|
+
);
|
|
2474
|
+
for (const [name, userAnalytics] of optionsWithAnalytics) {
|
|
2475
|
+
this.optionsWithAnalytics.set(name, userAnalytics);
|
|
2476
|
+
}
|
|
2477
|
+
return localYargs;
|
|
2478
|
+
}
|
|
2479
|
+
getWorkspaceOrThrow() {
|
|
2480
|
+
const { workspace } = this.context;
|
|
2481
|
+
if (!workspace) {
|
|
2482
|
+
throw new CommandModuleError("A workspace is required for this command.");
|
|
2483
|
+
}
|
|
2484
|
+
return workspace;
|
|
2485
|
+
}
|
|
2486
|
+
/**
|
|
2487
|
+
* Flush on an interval (if the event loop is waiting).
|
|
2488
|
+
*
|
|
2489
|
+
* @returns a method that when called will terminate the periodic
|
|
2490
|
+
* flush and call flush one last time.
|
|
2491
|
+
*/
|
|
2492
|
+
getAnalyticsParameters(options) {
|
|
2493
|
+
const parameters = {};
|
|
2494
|
+
const validEventCustomDimensionAndMetrics = /* @__PURE__ */ new Set([
|
|
2495
|
+
...Object.values(EventCustomDimension),
|
|
2496
|
+
...Object.values(EventCustomMetric)
|
|
2497
|
+
]);
|
|
2498
|
+
for (const [name, ua] of this.optionsWithAnalytics) {
|
|
2499
|
+
if (!validEventCustomDimensionAndMetrics.has(ua)) {
|
|
2500
|
+
continue;
|
|
2501
|
+
}
|
|
2502
|
+
const value = options[name];
|
|
2503
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
2504
|
+
parameters[ua] = value;
|
|
2505
|
+
} else if (Array.isArray(value)) {
|
|
2506
|
+
parameters[ua] = value.sort().join(", ");
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2509
|
+
return parameters;
|
|
2510
|
+
}
|
|
2511
|
+
reportCommandRunAnalytics(analytics) {
|
|
2512
|
+
const internalMethods = this.context.yargsInstance.getInternalMethods();
|
|
2513
|
+
const fullCommand = internalMethods.getUsageInstance().getUsage()[0][0].split(" ").filter((x) => {
|
|
2514
|
+
const code = x.charCodeAt(0);
|
|
2515
|
+
return code >= 97 && code <= 122;
|
|
2516
|
+
}).join("_");
|
|
2517
|
+
analytics.reportCommandRunEvent(fullCommand);
|
|
2518
|
+
}
|
|
2519
|
+
reportWorkspaceInfoAnalytics(analytics) {
|
|
2520
|
+
const { workspace } = this.context;
|
|
2521
|
+
if (!workspace) {
|
|
2522
|
+
return;
|
|
2523
|
+
}
|
|
2524
|
+
let applicationProjectsCount = 0;
|
|
2525
|
+
let librariesProjectsCount = 0;
|
|
2526
|
+
for (const project of workspace.projects.values()) {
|
|
2527
|
+
switch (project.extensions["projectType"]) {
|
|
2528
|
+
case "application":
|
|
2529
|
+
applicationProjectsCount++;
|
|
2530
|
+
break;
|
|
2531
|
+
case "library":
|
|
2532
|
+
librariesProjectsCount++;
|
|
2533
|
+
break;
|
|
2534
|
+
}
|
|
2535
|
+
}
|
|
2536
|
+
analytics.reportWorkspaceInfoEvent({
|
|
2537
|
+
[EventCustomMetric.AllProjectsCount]: librariesProjectsCount + applicationProjectsCount,
|
|
2538
|
+
[EventCustomMetric.ApplicationProjectsCount]: applicationProjectsCount,
|
|
2539
|
+
[EventCustomMetric.LibraryProjectsCount]: librariesProjectsCount
|
|
2540
|
+
});
|
|
2541
|
+
}
|
|
2542
|
+
};
|
|
2543
|
+
})();
|
|
2544
|
+
var CommandModuleError = class extends Error {
|
|
2545
|
+
};
|
|
2546
|
+
|
|
2547
|
+
export {
|
|
2548
|
+
isTTY,
|
|
2549
|
+
askConfirmation,
|
|
2550
|
+
askQuestion,
|
|
2551
|
+
askChoices,
|
|
2552
|
+
isPackageNameSafeForAnalytics,
|
|
2553
|
+
setAnalyticsConfig,
|
|
2554
|
+
promptAnalytics,
|
|
2555
|
+
getAnalyticsInfoString,
|
|
2556
|
+
EventCustomDimension,
|
|
2557
|
+
EventCustomMetric,
|
|
2558
|
+
createPackageManager,
|
|
2559
|
+
initializeAutocomplete,
|
|
2560
|
+
hasGlobalCliInstall,
|
|
2561
|
+
memoize,
|
|
2562
|
+
CommandScope,
|
|
2563
|
+
parseJsonSchemaToOptions,
|
|
2564
|
+
CommandModule,
|
|
2565
|
+
CommandModuleError
|
|
2566
|
+
};
|
|
2567
|
+
/**
|
|
2568
|
+
* @license
|
|
2569
|
+
* Copyright Google LLC All Rights Reserved.
|
|
2570
|
+
*
|
|
2571
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
2572
|
+
* found in the LICENSE file at https://angular.dev/license
|
|
2573
|
+
*/
|