Primeiro commit do projeto Angular

This commit is contained in:
2026-03-14 20:41:55 +00:00
parent 9bebe1de72
commit 94f4f46395
22413 changed files with 3221690 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
The MIT License
Copyright (c) 2010-2026 Google LLC. https://angular.dev/license
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+5
View File
@@ -0,0 +1,5 @@
# Angular CLI - The CLI tool for Angular.
The sources for this package are in the [Angular CLI](https://github.com/angular/angular-cli) repository. Please file issues and pull requests against that repository.
Usage information and reference details can be found in repository [README](https://github.com/angular/angular-cli/blob/main/README.md) file.
+33
View File
@@ -0,0 +1,33 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
/**
* @fileoverview
*
* This file is used to bootstrap the CLI process by dynamically importing the main initialization code.
* This is done to allow the main bin file (`ng`) to remain CommonJS so that older versions of Node.js
* can be checked and validated prior to the execution of the CLI. This separate bootstrap file is
* needed to allow the use of a dynamic import expression without crashing older versions of Node.js that
* do not support dynamic import expressions and would otherwise throw a syntax error. This bootstrap file
* is required from the main bin file only after the Node.js version is determined to be in the supported
* range.
*/
// Enable on-disk code caching if available (Node.js 22.8+)
// Skip if running inside Bazel via a RUNFILES environment variable check and no explicit cache
// location defined. The default cache location does not work well with Bazel's hermeticity requirements.
if (!process.env['RUNFILES'] || process.env['NODE_COMPILE_CACHE']) {
try {
const { enableCompileCache } = require('node:module');
enableCompileCache?.();
} catch {}
}
// Initialize the Angular CLI
void import('../lib/init.js');
+71
View File
@@ -0,0 +1,71 @@
#!/usr/bin/env node
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
/* eslint-disable no-console */
/* eslint-disable import/no-unassigned-import */
'use strict';
const path = require('path');
// Error if the external CLI appears to be used inside a google3 context.
if (process.cwd().split(path.sep).includes('google3')) {
console.error(
'This is the external Angular CLI, but you appear to be running in google3. There is a separate, internal version of the CLI which should be used instead. See http://go/angular/cli.',
);
process.exit();
}
// Provide a title to the process in `ps`.
// Due to an obscure Mac bug, do not start this title with any symbol.
try {
process.title = 'ng ' + Array.from(process.argv).slice(2).join(' ');
} catch (_) {
// If an error happened above, use the most basic title.
process.title = 'ng';
}
const rawCommandName = process.argv[2];
if (rawCommandName === '--get-yargs-completions' || rawCommandName === 'completion') {
// Skip Node.js supported checks when running ng completion.
// A warning at this stage could cause a broken source action (`source <(ng completion script)`) when in the shell init script.
require('./bootstrap');
return;
}
// This node version check ensures that extremely old versions of node are not used.
// These may not support ES2015 features such as const/let/async/await/etc.
// These would then crash with a hard to diagnose error message.
const [major, minor] = process.versions.node.split('.', 2).map((part) => Number(part));
if (major % 2 === 1) {
// Allow new odd numbered releases with a warning (currently v17+)
console.warn(
'Node.js version ' +
process.version +
' detected.\n' +
'Odd numbered Node.js versions will not enter LTS status and should not be used for production.' +
' For more information, please see https://nodejs.org/en/about/previous-releases/.',
);
require('./bootstrap');
} else if (major < 20 || (major === 20 && minor < 19) || (major === 22 && minor < 12)) {
// Error and exit if less than 20.19 or 22.12
console.error(
'Node.js version ' +
process.version +
' detected.\n' +
'The Angular CLI requires a minimum Node.js version of v20.19 or v22.12.\n\n' +
'Please update your Node.js version or visit https://nodejs.org/ for additional instructions.\n',
);
process.exitCode = 3;
} else {
require('./bootstrap');
}
+3
View File
@@ -0,0 +1,3 @@
{
"type": "commonjs"
}
+11
View File
@@ -0,0 +1,11 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
export { VERSION } from '../../src/utilities/version';
export default function (options: {
cliArgs: string[];
}): Promise<number>;
+109
View File
@@ -0,0 +1,109 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.VERSION = void 0;
exports.default = default_1;
const core_1 = require("@angular-devkit/core");
const node_util_1 = require("node:util");
const command_module_1 = require("../../src/command-builder/command-module");
const command_runner_1 = require("../../src/command-builder/command-runner");
const color_1 = require("../../src/utilities/color");
const environment_options_1 = require("../../src/utilities/environment-options");
const log_file_1 = require("../../src/utilities/log-file");
var version_1 = require("../../src/utilities/version");
Object.defineProperty(exports, "VERSION", { enumerable: true, get: function () { return version_1.VERSION; } });
const MIN_NODEJS_VERSION = [20, 19];
/* eslint-disable no-console */
async function default_1(options) {
// This node version check ensures that the requirements of the project instance of the CLI are met
const [major, minor] = process.versions.node.split('.').map((part) => Number(part));
if (major < MIN_NODEJS_VERSION[0] ||
(major === MIN_NODEJS_VERSION[0] && minor < MIN_NODEJS_VERSION[1])) {
process.stderr.write(`Node.js version ${process.version} detected.\n` +
`The Angular CLI requires a minimum of v${MIN_NODEJS_VERSION[0]}.${MIN_NODEJS_VERSION[1]}.\n\n` +
'Please update your Node.js version or visit https://nodejs.org/ for additional instructions.\n');
return 3;
}
const colorLevels = {
info: (s) => s,
debug: (s) => s,
warn: (s) => color_1.colors.bold(color_1.colors.yellow(s)),
error: (s) => color_1.colors.bold(color_1.colors.red(s)),
fatal: (s) => color_1.colors.bold(color_1.colors.red(s)),
};
const logger = new core_1.logging.IndentLogger('cli-main-logger');
const logInfo = console.log;
const logError = console.error;
const useColor = (0, color_1.supportColor)();
const loggerFinished = logger.forEach((entry) => {
if (!environment_options_1.ngDebug && entry.level === 'debug') {
return;
}
const color = useColor ? colorLevels[entry.level] : node_util_1.stripVTControlCharacters;
const message = color(entry.message);
switch (entry.level) {
case 'warn':
case 'fatal':
case 'error':
logError(message);
break;
default:
logInfo(message);
break;
}
});
// Redirect console to logger
console.info = console.log = function (...args) {
logger.info((0, node_util_1.format)(...args));
};
console.warn = function (...args) {
logger.warn((0, node_util_1.format)(...args));
};
console.error = function (...args) {
logger.error((0, node_util_1.format)(...args));
};
try {
return await (0, command_runner_1.runCommand)(options.cliArgs, logger);
}
catch (err) {
if (err instanceof command_module_1.CommandModuleError) {
logger.fatal(`Error: ${err.message}`);
}
else if (err instanceof Error) {
try {
const logPath = (0, log_file_1.writeErrorToLogFile)(err);
logger.fatal(`An unhandled exception occurred: ${err.message}\n` +
`See "${logPath}" for further details.`);
}
catch (e) {
logger.fatal(`An unhandled exception occurred: ${err.message}\n` +
`Fatal error writing debug log file: ${e}`);
if (err.stack) {
logger.fatal(err.stack);
}
}
return 127;
}
else if (typeof err === 'string') {
logger.fatal(err);
}
else if (typeof err === 'number') {
// Log nothing.
}
else {
logger.fatal(`An unexpected error occurred: ${err}`);
}
return 1;
}
finally {
logger.complete();
await loggerFinished;
}
}
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"}
BIN
View File
Binary file not shown.
+6150
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+133
View File
@@ -0,0 +1,133 @@
"use strict";
// THIS FILE IS AUTOMATICALLY GENERATED. TO UPDATE THIS FILE YOU NEED TO CHANGE THE
// CORRESPONDING JSON SCHEMA FILE, THEN RUN devkit-admin build (or bazel build ...).
Object.defineProperty(exports, "__esModule", { value: true });
exports.AiConfig = exports.TypeSeparator = exports.Implement = exports.SchematicsAngularComponentStyle = exports.ChangeDetection = exports.ViewEncapsulation = exports.TestRunner = exports.SchematicsAngularApplicationStyle = exports.FileNameStyleGuide = exports.PackageManager = exports.Environment = void 0;
/**
* Configure in which environment disk cache is enabled.
*/
var Environment;
(function (Environment) {
Environment["All"] = "all";
Environment["Ci"] = "ci";
Environment["Local"] = "local";
})(Environment || (exports.Environment = Environment = {}));
/**
* Specify which package manager tool to use.
*
* The package manager used to install dependencies.
*/
var PackageManager;
(function (PackageManager) {
PackageManager["Bun"] = "bun";
PackageManager["Npm"] = "npm";
PackageManager["Pnpm"] = "pnpm";
PackageManager["Yarn"] = "yarn";
})(PackageManager || (exports.PackageManager = PackageManager = {}));
/**
* The file naming convention to use for generated files. The '2025' style guide (default)
* uses a concise format (e.g., `app.ts` for the root component), while the '2016' style
* guide includes the type in the file name (e.g., `app.component.ts`). For more
* information, see the Angular Style Guide (https://angular.dev/style-guide).
*/
var FileNameStyleGuide;
(function (FileNameStyleGuide) {
FileNameStyleGuide["The2016"] = "2016";
FileNameStyleGuide["The2025"] = "2025";
})(FileNameStyleGuide || (exports.FileNameStyleGuide = FileNameStyleGuide = {}));
/**
* The type of stylesheet files to be created for components in the application.
*
* The type of stylesheet files to be created for components in the initial project.
*/
var SchematicsAngularApplicationStyle;
(function (SchematicsAngularApplicationStyle) {
SchematicsAngularApplicationStyle["Css"] = "css";
SchematicsAngularApplicationStyle["Less"] = "less";
SchematicsAngularApplicationStyle["Sass"] = "sass";
SchematicsAngularApplicationStyle["Scss"] = "scss";
SchematicsAngularApplicationStyle["Tailwind"] = "tailwind";
})(SchematicsAngularApplicationStyle || (exports.SchematicsAngularApplicationStyle = SchematicsAngularApplicationStyle = {}));
/**
* The unit testing runner to use.
*/
var TestRunner;
(function (TestRunner) {
TestRunner["Karma"] = "karma";
TestRunner["Vitest"] = "vitest";
})(TestRunner || (exports.TestRunner = TestRunner = {}));
/**
* Sets the view encapsulation mode for the application's components. This determines how
* component styles are scoped and applied.
*
* Sets the view encapsulation mode for the component. This determines how the component's
* styles are scoped and applied.
*
* Sets the view encapsulation mode for components in the initial project. This determines
* how component styles are scoped and applied. Options include: `Emulated` (default, styles
* are scoped to the component), `None` (styles are global), and `ShadowDom` (styles are
* encapsulated using Shadow DOM).
*/
var ViewEncapsulation;
(function (ViewEncapsulation) {
ViewEncapsulation["Emulated"] = "Emulated";
ViewEncapsulation["None"] = "None";
ViewEncapsulation["ShadowDom"] = "ShadowDom";
})(ViewEncapsulation || (exports.ViewEncapsulation = ViewEncapsulation = {}));
/**
* Configures the change detection strategy for the component.
*/
var ChangeDetection;
(function (ChangeDetection) {
ChangeDetection["Default"] = "Default";
ChangeDetection["OnPush"] = "OnPush";
})(ChangeDetection || (exports.ChangeDetection = ChangeDetection = {}));
/**
* Specify the type of stylesheet to be created for the component, or `none` to skip
* creating a stylesheet.
*/
var SchematicsAngularComponentStyle;
(function (SchematicsAngularComponentStyle) {
SchematicsAngularComponentStyle["Css"] = "css";
SchematicsAngularComponentStyle["Less"] = "less";
SchematicsAngularComponentStyle["None"] = "none";
SchematicsAngularComponentStyle["Sass"] = "sass";
SchematicsAngularComponentStyle["Scss"] = "scss";
})(SchematicsAngularComponentStyle || (exports.SchematicsAngularComponentStyle = SchematicsAngularComponentStyle = {}));
var Implement;
(function (Implement) {
Implement["CanActivate"] = "CanActivate";
Implement["CanActivateChild"] = "CanActivateChild";
Implement["CanDeactivate"] = "CanDeactivate";
Implement["CanMatch"] = "CanMatch";
})(Implement || (exports.Implement = Implement = {}));
/**
* The separator character to use before the type within the generated file's name. For
* example, if you set the option to `.`, the file will be named `example.guard.ts`.
*
* The separator character to use before the type within the generated file's name. For
* example, if you set the option to `.`, the file will be named `example.interceptor.ts`.
*
* The separator character to use before the type within the generated file's name. For
* example, if you set the option to `.`, the file will be named `example.pipe.ts`.
*
* The separator character to use before the type within the generated file's name. For
* example, if you set the option to `.`, the file will be named `example.resolver.ts`.
*/
var TypeSeparator;
(function (TypeSeparator) {
TypeSeparator["Empty"] = "-";
TypeSeparator["TypeSeparator"] = ".";
})(TypeSeparator || (exports.TypeSeparator = TypeSeparator = {}));
var AiConfig;
(function (AiConfig) {
AiConfig["Agents"] = "agents";
AiConfig["Claude"] = "claude";
AiConfig["Copilot"] = "copilot";
AiConfig["Cursor"] = "cursor";
AiConfig["Gemini"] = "gemini";
AiConfig["Jetbrains"] = "jetbrains";
AiConfig["None"] = "none";
AiConfig["Windsurf"] = "windsurf";
})(AiConfig || (exports.AiConfig = AiConfig = {}));
//# sourceMappingURL=workspace-schema.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"workspace-schema.js","sourceRoot":"","sources":["workspace-schema.ts"],"names":[],"mappings":";AACA,mFAAmF;AACnF,oFAAoF;;;AA4DpF;;GAEG;AACH,IAAY,WAIX;AAJD,WAAY,WAAW;IACnB,0BAAW,CAAA;IACX,wBAAS,CAAA;IACT,8BAAe,CAAA;AACnB,CAAC,EAJW,WAAW,2BAAX,WAAW,QAItB;AAED;;;;GAIG;AACH,IAAY,cAKX;AALD,WAAY,cAAc;IACtB,6BAAW,CAAA;IACX,6BAAW,CAAA;IACX,+BAAa,CAAA;IACb,+BAAa,CAAA;AACjB,CAAC,EALW,cAAc,8BAAd,cAAc,QAKzB;AAqID;;;;;GAKG;AACH,IAAY,kBAGX;AAHD,WAAY,kBAAkB;IAC1B,sCAAgB,CAAA;IAChB,sCAAgB,CAAA;AACpB,CAAC,EAHW,kBAAkB,kCAAlB,kBAAkB,QAG7B;AAED;;;;GAIG;AACH,IAAY,iCAMX;AAND,WAAY,iCAAiC;IACzC,gDAAW,CAAA;IACX,kDAAa,CAAA;IACb,kDAAa,CAAA;IACb,kDAAa,CAAA;IACb,0DAAqB,CAAA;AACzB,CAAC,EANW,iCAAiC,iDAAjC,iCAAiC,QAM5C;AAED;;GAEG;AACH,IAAY,UAGX;AAHD,WAAY,UAAU;IAClB,6BAAe,CAAA;IACf,+BAAiB,CAAA;AACrB,CAAC,EAHW,UAAU,0BAAV,UAAU,QAGrB;AAED;;;;;;;;;;;GAWG;AACH,IAAY,iBAIX;AAJD,WAAY,iBAAiB;IACzB,0CAAqB,CAAA;IACrB,kCAAa,CAAA;IACb,4CAAuB,CAAA;AAC3B,CAAC,EAJW,iBAAiB,iCAAjB,iBAAiB,QAI5B;AAsJD;;GAEG;AACH,IAAY,eAGX;AAHD,WAAY,eAAe;IACvB,sCAAmB,CAAA;IACnB,oCAAiB,CAAA;AACrB,CAAC,EAHW,eAAe,+BAAf,eAAe,QAG1B;AAED;;;GAGG;AACH,IAAY,+BAMX;AAND,WAAY,+BAA+B;IACvC,8CAAW,CAAA;IACX,gDAAa,CAAA;IACb,gDAAa,CAAA;IACb,gDAAa,CAAA;IACb,gDAAa,CAAA;AACjB,CAAC,EANW,+BAA+B,+CAA/B,+BAA+B,QAM1C;AAwJD,IAAY,SAKX;AALD,WAAY,SAAS;IACjB,wCAA2B,CAAA;IAC3B,kDAAqC,CAAA;IACrC,4CAA+B,CAAA;IAC/B,kCAAqB,CAAA;AACzB,CAAC,EALW,SAAS,yBAAT,SAAS,QAKpB;AAED;;;;;;;;;;;;GAYG;AACH,IAAY,aAGX;AAHD,WAAY,aAAa;IACrB,4BAAW,CAAA;IACX,oCAAmB,CAAA;AACvB,CAAC,EAHW,aAAa,6BAAb,aAAa,QAGxB;AAyQD,IAAY,QASX;AATD,WAAY,QAAQ;IAChB,6BAAiB,CAAA;IACjB,6BAAiB,CAAA;IACjB,+BAAmB,CAAA;IACnB,6BAAiB,CAAA;IACjB,6BAAiB,CAAA;IACjB,mCAAuB,CAAA;IACvB,yBAAa,CAAA;IACb,iCAAqB,CAAA;AACzB,CAAC,EATW,QAAQ,wBAAR,QAAQ,QASnB"}
+8
View File
@@ -0,0 +1,8 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
export {};
+162
View File
@@ -0,0 +1,162 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
const promises_1 = require("node:fs/promises");
const node_module_1 = require("node:module");
const path = __importStar(require("node:path"));
const semver_1 = require("semver");
const color_1 = require("../src/utilities/color");
const config_1 = require("../src/utilities/config");
const environment_options_1 = require("../src/utilities/environment-options");
const version_1 = require("../src/utilities/version");
/**
* Angular CLI versions prior to v14 may not exit correctly if not forcibly exited
* via `process.exit()`. When bootstrapping, `forceExit` will be set to `true`
* if the local CLI version is less than v14 to prevent the CLI from hanging on
* exit in those cases.
*/
let forceExit = false;
(async () => {
/**
* Disable Browserslist old data warning as otherwise with every release we'd need to update this dependency
* which is cumbersome considering we pin versions and the warning is not user actionable.
* `Browserslist: caniuse-lite is outdated. Please run next command `npm update`
* See: https://github.com/browserslist/browserslist/blob/819c4337456996d19db6ba953014579329e9c6e1/node.js#L324
*/
process.env.BROWSERSLIST_IGNORE_OLD_DATA = '1';
const rawCommandName = process.argv[2];
/**
* Disable CLI version mismatch checks and forces usage of the invoked CLI
* instead of invoking the local installed version.
*
* When running `ng new` always favor the global version. As in some
* cases orphan `node_modules` would cause the non global CLI to be used.
* @see: https://github.com/angular/angular-cli/issues/14603
*/
if (environment_options_1.disableVersionCheck || rawCommandName === 'new') {
return (await Promise.resolve().then(() => __importStar(require('./cli')))).default;
}
let cli;
try {
// No error implies a projectLocalCli, which will load whatever
// version of ng-cli you have installed in a local package.json
const cwdRequire = (0, node_module_1.createRequire)(process.cwd() + '/');
const projectLocalCli = cwdRequire.resolve('@angular/cli');
cli = await Promise.resolve(`${projectLocalCli}`).then(s => __importStar(require(s)));
const globalVersion = new semver_1.SemVer(version_1.VERSION.full);
// Older versions might not have the VERSION export
let localVersion = cli.VERSION?.full;
if (!localVersion) {
try {
const localPackageJson = await (0, promises_1.readFile)(path.join(path.dirname(projectLocalCli), '../../package.json'), 'utf-8');
localVersion = JSON.parse(localPackageJson).version;
}
catch (error) {
// eslint-disable-next-line no-console
console.error('Version mismatch check skipped. Unable to retrieve local version: ' + error);
}
}
// Ensure older versions of the CLI fully exit
const localMajorVersion = (0, semver_1.major)(localVersion);
if (localMajorVersion > 0 && localMajorVersion < 14) {
forceExit = true;
// Versions prior to 14 didn't implement completion command.
if (rawCommandName === 'completion') {
return null;
}
}
let isGlobalGreater = false;
try {
isGlobalGreater = localVersion > 0 && globalVersion.compare(localVersion) > 0;
}
catch (error) {
// eslint-disable-next-line no-console
console.error('Version mismatch check skipped. Unable to compare local version: ' + error);
}
// When using the completion command, don't show the warning as otherwise this will break completion.
if (isGlobalGreater &&
rawCommandName !== '--get-yargs-completions' &&
rawCommandName !== 'completion') {
// If using the update command and the global version is greater, use the newer update command
// This allows improvements in update to be used in older versions that do not have bootstrapping
if (rawCommandName === 'update' &&
cli.VERSION &&
cli.VERSION.major - globalVersion.major <= 1) {
cli = await Promise.resolve().then(() => __importStar(require('./cli')));
}
else if (await (0, config_1.isWarningEnabled)('versionMismatch')) {
// Otherwise, use local version and warn if global is newer than local
const warning = `Your global Angular CLI version (${globalVersion}) is greater than your local ` +
`version (${localVersion}). The local Angular CLI version is used.\n\n` +
'To disable this warning use "ng config -g cli.warnings.versionMismatch false".';
// eslint-disable-next-line no-console
console.error(color_1.colors.yellow(warning));
}
}
}
catch {
// If there is an error, resolve could not find the ng-cli
// library from a package.json. Instead, include it from a relative
// path to this script file (which is likely a globally installed
// npm package). Most common cause for hitting this is `ng new`
cli = await Promise.resolve().then(() => __importStar(require('./cli')));
}
if ('default' in cli) {
cli = cli['default'];
}
return cli;
})()
.then((cli) => cli?.({
cliArgs: process.argv.slice(2),
}))
.then((exitCode = 0) => {
if (forceExit) {
process.exit(exitCode);
}
process.exitCode = exitCode;
})
.catch((err) => {
// eslint-disable-next-line no-console
console.error('Unknown error: ' + err.toString());
process.exit(127);
});
//# sourceMappingURL=init.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"init.js","sourceRoot":"","sources":["init.ts"],"names":[],"mappings":"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"}
+66
View File
@@ -0,0 +1,66 @@
{
"name": "@angular/cli",
"version": "21.2.1",
"description": "CLI tool for Angular",
"main": "lib/cli/index.js",
"bin": {
"ng": "./bin/ng.js"
},
"keywords": [
"Angular CLI",
"Angular DevKit",
"angular",
"angular-cli",
"devkit",
"sdk"
],
"repository": {
"type": "git",
"url": "https://github.com/angular/angular-cli.git"
},
"author": "Angular Authors",
"license": "MIT",
"bugs": {
"url": "https://github.com/angular/angular-cli/issues"
},
"homepage": "https://github.com/angular/angular-cli",
"dependencies": {
"@angular-devkit/architect": "0.2102.1",
"@angular-devkit/core": "21.2.1",
"@angular-devkit/schematics": "21.2.1",
"@inquirer/prompts": "7.10.1",
"@listr2/prompt-adapter-inquirer": "3.0.5",
"@modelcontextprotocol/sdk": "1.26.0",
"@schematics/angular": "21.2.1",
"@yarnpkg/lockfile": "1.1.0",
"algoliasearch": "5.48.1",
"ini": "6.0.0",
"jsonc-parser": "3.3.1",
"listr2": "9.0.5",
"npm-package-arg": "13.0.2",
"pacote": "21.3.1",
"parse5-html-rewriting-stream": "8.0.0",
"semver": "7.7.4",
"yargs": "18.0.0",
"zod": "4.3.6"
},
"ng-update": {
"migrations": "@schematics/angular/migrations/migration-collection.json",
"packageGroup": {
"@angular/cli": "21.2.1",
"@angular/build": "21.2.1",
"@angular/ssr": "21.2.1",
"@angular-devkit/architect": "0.2102.1",
"@angular-devkit/build-angular": "21.2.1",
"@angular-devkit/build-webpack": "0.2102.1",
"@angular-devkit/core": "21.2.1",
"@angular-devkit/schematics": "21.2.1"
}
},
"packageManager": "pnpm@10.30.3",
"engines": {
"node": "^20.19.0 || ^22.12.0 || >=24.0.0",
"npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
"yarn": ">= 1.13.0"
}
}
+35
View File
@@ -0,0 +1,35 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { logging } from '@angular-devkit/core';
import { EventCustomDimension, EventCustomMetric, PrimitiveTypes } from './analytics-parameters';
export declare class AnalyticsCollector {
private logger;
private trackingEventsQueue;
private readonly requestParameterStringified;
private readonly userParameters;
constructor(logger: logging.Logger, userId: string, packageManagerInfo: {
name: string;
version: string | undefined;
});
reportWorkspaceInfoEvent(parameters: Partial<Record<EventCustomMetric, string | boolean | number | undefined>>): void;
reportRebuildRunEvent(parameters: Partial<Record<EventCustomMetric & EventCustomDimension, string | boolean | number | undefined>>): void;
reportBuildRunEvent(parameters: Partial<Record<EventCustomMetric & EventCustomDimension, string | boolean | number | undefined>>): void;
reportArchitectRunEvent(parameters: Partial<Record<EventCustomDimension, PrimitiveTypes>>): void;
reportSchematicRunEvent(parameters: Partial<Record<EventCustomDimension, PrimitiveTypes>>): void;
reportCommandRunEvent(command: string): void;
private event;
/**
* Flush on an interval (if the event loop is waiting).
*
* @returns a method that when called will terminate the periodic
* flush and call flush one last time.
*/
periodFlush(): () => Promise<void>;
flush(): Promise<void>;
private send;
}
+195
View File
@@ -0,0 +1,195 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.AnalyticsCollector = void 0;
const node_crypto_1 = require("node:crypto");
const https = __importStar(require("node:https"));
const os = __importStar(require("node:os"));
const querystring = __importStar(require("node:querystring"));
const semver = __importStar(require("semver"));
const environment_options_1 = require("../utilities/environment-options");
const error_1 = require("../utilities/error");
const version_1 = require("../utilities/version");
const analytics_parameters_1 = require("./analytics-parameters");
const TRACKING_ID_PROD = 'G-VETNJBW8L4';
const TRACKING_ID_STAGING = 'G-TBMPRL1BTM';
class AnalyticsCollector {
logger;
trackingEventsQueue;
requestParameterStringified;
userParameters;
constructor(logger, userId, packageManagerInfo) {
this.logger = logger;
const requestParameters = {
[analytics_parameters_1.RequestParameter.ProtocolVersion]: 2,
[analytics_parameters_1.RequestParameter.ClientId]: userId,
[analytics_parameters_1.RequestParameter.UserId]: userId,
[analytics_parameters_1.RequestParameter.TrackingId]: /^\d+\.\d+\.\d+$/.test(version_1.VERSION.full) && version_1.VERSION.full !== '0.0.0'
? TRACKING_ID_PROD
: TRACKING_ID_STAGING,
// Built-in user properties
[analytics_parameters_1.RequestParameter.SessionId]: (0, node_crypto_1.randomUUID)(),
[analytics_parameters_1.RequestParameter.UserAgentArchitecture]: os.arch(),
[analytics_parameters_1.RequestParameter.UserAgentPlatform]: os.platform(),
[analytics_parameters_1.RequestParameter.UserAgentPlatformVersion]: os.release(),
[analytics_parameters_1.RequestParameter.UserAgentMobile]: 0,
[analytics_parameters_1.RequestParameter.SessionEngaged]: 1,
// The below is needed for tech details to be collected.
[analytics_parameters_1.RequestParameter.UserAgentFullVersionList]: 'Google%20Chrome;111.0.5563.64|Not(A%3ABrand;8.0.0.0|Chromium;111.0.5563.64',
};
if (environment_options_1.ngDebug) {
requestParameters[analytics_parameters_1.RequestParameter.DebugView] = 1;
}
this.requestParameterStringified = querystring.stringify(requestParameters);
const parsedVersion = semver.parse(process.version);
const packageManagerVersion = packageManagerInfo.version;
this.userParameters = {
// While architecture is being collect by GA as UserAgentArchitecture.
// It doesn't look like there is a way to query this. Therefore we collect this as a custom user dimension too.
[analytics_parameters_1.UserCustomDimension.OsArchitecture]: os.arch(),
// While User ID is being collected by GA, this is not visible in reports/for filtering.
[analytics_parameters_1.UserCustomDimension.UserId]: userId,
[analytics_parameters_1.UserCustomDimension.NodeVersion]: parsedVersion
? `${parsedVersion.major}.${parsedVersion.minor}.${parsedVersion.patch}`
: 'other',
[analytics_parameters_1.UserCustomDimension.NodeMajorVersion]: parsedVersion?.major,
[analytics_parameters_1.UserCustomDimension.PackageManager]: packageManagerInfo.name,
[analytics_parameters_1.UserCustomDimension.PackageManagerVersion]: packageManagerVersion,
[analytics_parameters_1.UserCustomDimension.PackageManagerMajorVersion]: packageManagerVersion
? +packageManagerVersion.split('.', 1)[0]
: undefined,
[analytics_parameters_1.UserCustomDimension.AngularCLIVersion]: version_1.VERSION.full,
[analytics_parameters_1.UserCustomDimension.AngularCLIMajorVersion]: version_1.VERSION.major,
};
}
reportWorkspaceInfoEvent(parameters) {
this.event('workspace_info', parameters);
}
reportRebuildRunEvent(parameters) {
this.event('run_rebuild', parameters);
}
reportBuildRunEvent(parameters) {
this.event('run_build', parameters);
}
reportArchitectRunEvent(parameters) {
this.event('run_architect', parameters);
}
reportSchematicRunEvent(parameters) {
this.event('run_schematic', parameters);
}
reportCommandRunEvent(command) {
this.event('run_command', { [analytics_parameters_1.EventCustomDimension.Command]: command });
}
event(eventName, parameters) {
this.trackingEventsQueue ??= [];
this.trackingEventsQueue.push({
...this.userParameters,
...parameters,
'en': eventName,
});
}
/**
* Flush on an interval (if the event loop is waiting).
*
* @returns a method that when called will terminate the periodic
* flush and call flush one last time.
*/
periodFlush() {
let analyticsFlushPromise = Promise.resolve();
const analyticsFlushInterval = setInterval(() => {
if (this.trackingEventsQueue?.length) {
analyticsFlushPromise = analyticsFlushPromise.then(() => this.flush());
}
}, 4000);
return () => {
clearInterval(analyticsFlushInterval);
// Flush one last time.
return analyticsFlushPromise.then(() => this.flush());
};
}
async flush() {
const pendingTrackingEvents = this.trackingEventsQueue;
this.logger.debug(`Analytics flush size. ${pendingTrackingEvents?.length}.`);
if (!pendingTrackingEvents?.length) {
return;
}
// The below is needed so that if flush is called multiple times,
// we don't report the same event multiple times.
this.trackingEventsQueue = undefined;
try {
await this.send(pendingTrackingEvents);
}
catch (error) {
// Failure to report analytics shouldn't crash the CLI.
(0, error_1.assertIsError)(error);
this.logger.debug(`Send analytics error. ${error.message}.`);
}
}
async send(data) {
return new Promise((resolve, reject) => {
const request = https.request({
host: 'www.google-analytics.com',
method: 'POST',
path: '/g/collect?' + this.requestParameterStringified,
headers: {
// The below is needed for tech details to be collected even though we provide our own information from the OS Node.js module
'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',
},
}, (response) => {
// The below is needed as otherwise the response will never close which will cause the CLI not to terminate.
response.on('data', () => { });
if (response.statusCode !== 200 && response.statusCode !== 204) {
reject(new Error(`Analytics reporting failed with status code: ${response.statusCode}.`));
}
else {
resolve();
}
});
request.on('error', reject);
const queryParameters = data.map((p) => querystring.stringify(p)).join('\n');
request.write(queryParameters);
request.end();
});
}
}
exports.AnalyticsCollector = AnalyticsCollector;
//# sourceMappingURL=analytics-collector.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"analytics-collector.js","sourceRoot":"","sources":["analytics-collector.ts"],"names":[],"mappings":"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"}
+101
View File
@@ -0,0 +1,101 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
/** Any changes in this file needs to be done in the mts version. */
export type PrimitiveTypes = string | number | boolean;
/**
* GA built-in request parameters
* @see https://www.thyngster.com/ga4-measurement-protocol-cheatsheet
* @see http://go/depot/google3/analytics/container_tag/templates/common/gold/mpv2_schema.js
*/
export declare enum RequestParameter {
ClientId = "cid",
DebugView = "_dbg",
GtmVersion = "gtm",
Language = "ul",
NewToSite = "_nsi",
NonInteraction = "ni",
PageLocation = "dl",
PageTitle = "dt",
ProtocolVersion = "v",
SessionEngaged = "seg",
SessionId = "sid",
SessionNumber = "sct",
SessionStart = "_ss",
TrackingId = "tid",
TrafficType = "tt",
UserAgentArchitecture = "uaa",
UserAgentBitness = "uab",
UserAgentFullVersionList = "uafvl",
UserAgentMobile = "uamb",
UserAgentModel = "uam",
UserAgentPlatform = "uap",
UserAgentPlatformVersion = "uapv",
UserId = "uid"
}
/**
* User scoped custom dimensions.
* @remarks
* - User custom dimensions limit is 25.
* - `up.*` string type.
* - `upn.*` number type.
* @see https://support.google.com/analytics/answer/10075209?hl=en
*/
export declare enum UserCustomDimension {
UserId = "up.ng_user_id",
OsArchitecture = "up.ng_os_architecture",
NodeVersion = "up.ng_node_version",
NodeMajorVersion = "upn.ng_node_major_version",
AngularCLIVersion = "up.ng_cli_version",
AngularCLIMajorVersion = "upn.ng_cli_major_version",
PackageManager = "up.ng_package_manager",
PackageManagerVersion = "up.ng_pkg_manager_version",
PackageManagerMajorVersion = "upn.ng_pkg_manager_major_v"
}
/**
* Event scoped custom dimensions.
* @remarks
* - Event custom dimensions limit is 50.
* - `ep.*` string type.
* - `epn.*` number type.
* @see https://support.google.com/analytics/answer/10075209?hl=en
*/
export declare enum EventCustomDimension {
Command = "ep.ng_command",
SchematicCollectionName = "ep.ng_schematic_collection_name",
SchematicName = "ep.ng_schematic_name",
Standalone = "ep.ng_standalone",
SSR = "ep.ng_ssr",
Style = "ep.ng_style",
Routing = "ep.ng_routing",
InlineTemplate = "ep.ng_inline_template",
InlineStyle = "ep.ng_inline_style",
BuilderTarget = "ep.ng_builder_target",
Aot = "ep.ng_aot",
Optimization = "ep.ng_optimization"
}
/**
* Event scoped custom mertics.
* @remarks
* - Event scoped custom mertics limit is 50.
* - `ep.*` string type.
* - `epn.*` number type.
* @see https://support.google.com/analytics/answer/10075209?hl=en
*/
export declare enum EventCustomMetric {
AllChunksCount = "epn.ng_all_chunks_count",
LazyChunksCount = "epn.ng_lazy_chunks_count",
InitialChunksCount = "epn.ng_initial_chunks_count",
ChangedChunksCount = "epn.ng_changed_chunks_count",
DurationInMs = "epn.ng_duration_ms",
CssSizeInBytes = "epn.ng_css_size_bytes",
JsSizeInBytes = "epn.ng_js_size_bytes",
NgComponentCount = "epn.ng_component_count",
AllProjectsCount = "epn.all_projects_count",
LibraryProjectsCount = "epn.libs_projects_count",
ApplicationProjectsCount = "epn.apps_projects_count"
}
+107
View File
@@ -0,0 +1,107 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.EventCustomMetric = exports.EventCustomDimension = exports.UserCustomDimension = exports.RequestParameter = void 0;
/**
* GA built-in request parameters
* @see https://www.thyngster.com/ga4-measurement-protocol-cheatsheet
* @see http://go/depot/google3/analytics/container_tag/templates/common/gold/mpv2_schema.js
*/
var RequestParameter;
(function (RequestParameter) {
RequestParameter["ClientId"] = "cid";
RequestParameter["DebugView"] = "_dbg";
RequestParameter["GtmVersion"] = "gtm";
RequestParameter["Language"] = "ul";
RequestParameter["NewToSite"] = "_nsi";
RequestParameter["NonInteraction"] = "ni";
RequestParameter["PageLocation"] = "dl";
RequestParameter["PageTitle"] = "dt";
RequestParameter["ProtocolVersion"] = "v";
RequestParameter["SessionEngaged"] = "seg";
RequestParameter["SessionId"] = "sid";
RequestParameter["SessionNumber"] = "sct";
RequestParameter["SessionStart"] = "_ss";
RequestParameter["TrackingId"] = "tid";
RequestParameter["TrafficType"] = "tt";
RequestParameter["UserAgentArchitecture"] = "uaa";
RequestParameter["UserAgentBitness"] = "uab";
RequestParameter["UserAgentFullVersionList"] = "uafvl";
RequestParameter["UserAgentMobile"] = "uamb";
RequestParameter["UserAgentModel"] = "uam";
RequestParameter["UserAgentPlatform"] = "uap";
RequestParameter["UserAgentPlatformVersion"] = "uapv";
RequestParameter["UserId"] = "uid";
})(RequestParameter || (exports.RequestParameter = RequestParameter = {}));
/**
* User scoped custom dimensions.
* @remarks
* - User custom dimensions limit is 25.
* - `up.*` string type.
* - `upn.*` number type.
* @see https://support.google.com/analytics/answer/10075209?hl=en
*/
var UserCustomDimension;
(function (UserCustomDimension) {
UserCustomDimension["UserId"] = "up.ng_user_id";
UserCustomDimension["OsArchitecture"] = "up.ng_os_architecture";
UserCustomDimension["NodeVersion"] = "up.ng_node_version";
UserCustomDimension["NodeMajorVersion"] = "upn.ng_node_major_version";
UserCustomDimension["AngularCLIVersion"] = "up.ng_cli_version";
UserCustomDimension["AngularCLIMajorVersion"] = "upn.ng_cli_major_version";
UserCustomDimension["PackageManager"] = "up.ng_package_manager";
UserCustomDimension["PackageManagerVersion"] = "up.ng_pkg_manager_version";
UserCustomDimension["PackageManagerMajorVersion"] = "upn.ng_pkg_manager_major_v";
})(UserCustomDimension || (exports.UserCustomDimension = UserCustomDimension = {}));
/**
* Event scoped custom dimensions.
* @remarks
* - Event custom dimensions limit is 50.
* - `ep.*` string type.
* - `epn.*` number type.
* @see https://support.google.com/analytics/answer/10075209?hl=en
*/
var EventCustomDimension;
(function (EventCustomDimension) {
EventCustomDimension["Command"] = "ep.ng_command";
EventCustomDimension["SchematicCollectionName"] = "ep.ng_schematic_collection_name";
EventCustomDimension["SchematicName"] = "ep.ng_schematic_name";
EventCustomDimension["Standalone"] = "ep.ng_standalone";
EventCustomDimension["SSR"] = "ep.ng_ssr";
EventCustomDimension["Style"] = "ep.ng_style";
EventCustomDimension["Routing"] = "ep.ng_routing";
EventCustomDimension["InlineTemplate"] = "ep.ng_inline_template";
EventCustomDimension["InlineStyle"] = "ep.ng_inline_style";
EventCustomDimension["BuilderTarget"] = "ep.ng_builder_target";
EventCustomDimension["Aot"] = "ep.ng_aot";
EventCustomDimension["Optimization"] = "ep.ng_optimization";
})(EventCustomDimension || (exports.EventCustomDimension = EventCustomDimension = {}));
/**
* Event scoped custom mertics.
* @remarks
* - Event scoped custom mertics limit is 50.
* - `ep.*` string type.
* - `epn.*` number type.
* @see https://support.google.com/analytics/answer/10075209?hl=en
*/
var EventCustomMetric;
(function (EventCustomMetric) {
EventCustomMetric["AllChunksCount"] = "epn.ng_all_chunks_count";
EventCustomMetric["LazyChunksCount"] = "epn.ng_lazy_chunks_count";
EventCustomMetric["InitialChunksCount"] = "epn.ng_initial_chunks_count";
EventCustomMetric["ChangedChunksCount"] = "epn.ng_changed_chunks_count";
EventCustomMetric["DurationInMs"] = "epn.ng_duration_ms";
EventCustomMetric["CssSizeInBytes"] = "epn.ng_css_size_bytes";
EventCustomMetric["JsSizeInBytes"] = "epn.ng_js_size_bytes";
EventCustomMetric["NgComponentCount"] = "epn.ng_component_count";
EventCustomMetric["AllProjectsCount"] = "epn.all_projects_count";
EventCustomMetric["LibraryProjectsCount"] = "epn.libs_projects_count";
EventCustomMetric["ApplicationProjectsCount"] = "epn.apps_projects_count";
})(EventCustomMetric || (exports.EventCustomMetric = EventCustomMetric = {}));
//# sourceMappingURL=analytics-parameters.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"analytics-parameters.js","sourceRoot":"","sources":["analytics-parameters.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAMH;;;;GAIG;AACH,IAAY,gBAwBX;AAxBD,WAAY,gBAAgB;IAC1B,oCAAgB,CAAA;IAChB,sCAAkB,CAAA;IAClB,sCAAkB,CAAA;IAClB,mCAAe,CAAA;IACf,sCAAkB,CAAA;IAClB,yCAAqB,CAAA;IACrB,uCAAmB,CAAA;IACnB,oCAAgB,CAAA;IAChB,yCAAqB,CAAA;IACrB,0CAAsB,CAAA;IACtB,qCAAiB,CAAA;IACjB,yCAAqB,CAAA;IACrB,wCAAoB,CAAA;IACpB,sCAAkB,CAAA;IAClB,sCAAkB,CAAA;IAClB,iDAA6B,CAAA;IAC7B,4CAAwB,CAAA;IACxB,sDAAkC,CAAA;IAClC,4CAAwB,CAAA;IACxB,0CAAsB,CAAA;IACtB,6CAAyB,CAAA;IACzB,qDAAiC,CAAA;IACjC,kCAAc,CAAA;AAChB,CAAC,EAxBW,gBAAgB,gCAAhB,gBAAgB,QAwB3B;AAED;;;;;;;GAOG;AACH,IAAY,mBAUX;AAVD,WAAY,mBAAmB;IAC7B,+CAAwB,CAAA;IACxB,+DAAwC,CAAA;IACxC,yDAAkC,CAAA;IAClC,qEAA8C,CAAA;IAC9C,8DAAuC,CAAA;IACvC,0EAAmD,CAAA;IACnD,+DAAwC,CAAA;IACxC,0EAAmD,CAAA;IACnD,gFAAyD,CAAA;AAC3D,CAAC,EAVW,mBAAmB,mCAAnB,mBAAmB,QAU9B;AAED;;;;;;;GAOG;AACH,IAAY,oBAaX;AAbD,WAAY,oBAAoB;IAC9B,iDAAyB,CAAA;IACzB,mFAA2D,CAAA;IAC3D,8DAAsC,CAAA;IACtC,uDAA+B,CAAA;IAC/B,yCAAiB,CAAA;IACjB,6CAAqB,CAAA;IACrB,iDAAyB,CAAA;IACzB,gEAAwC,CAAA;IACxC,0DAAkC,CAAA;IAClC,8DAAsC,CAAA;IACtC,yCAAiB,CAAA;IACjB,2DAAmC,CAAA;AACrC,CAAC,EAbW,oBAAoB,oCAApB,oBAAoB,QAa/B;AAED;;;;;;;GAOG;AACH,IAAY,iBAYX;AAZD,WAAY,iBAAiB;IAC3B,+DAA0C,CAAA;IAC1C,iEAA4C,CAAA;IAC5C,uEAAkD,CAAA;IAClD,uEAAkD,CAAA;IAClD,wDAAmC,CAAA;IACnC,6DAAwC,CAAA;IACxC,2DAAsC,CAAA;IACtC,gEAA2C,CAAA;IAC3C,gEAA2C,CAAA;IAC3C,qEAAgD,CAAA;IAChD,yEAAoD,CAAA;AACtD,CAAC,EAZW,iBAAiB,iCAAjB,iBAAiB,QAY5B"}
+27
View File
@@ -0,0 +1,27 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import type { CommandContext } from '../command-builder/definitions';
/**
* This is the ultimate safelist for checking if a package name is safe to report to analytics.
*/
export declare const analyticsPackageSafelist: (string | RegExp)[];
export declare function isPackageNameSafeForAnalytics(name: string): boolean;
/**
* Set analytics settings. This does not work if the user is not inside a project.
* @param global Which config to use. "global" for user-level, and "local" for project-level.
* @param value Either a user ID, true to generate a new User ID, or false to disable analytics.
*/
export declare function setAnalyticsConfig(global: boolean, value: string | boolean): Promise<void>;
/**
* Prompt the user for usage gathering permission.
* @param force Whether to ask regardless of whether or not the user is using an interactive shell.
* @return Whether or not the user was shown a prompt.
*/
export declare function promptAnalytics(context: CommandContext, global: boolean, force?: boolean): Promise<boolean>;
export declare function getAnalyticsUserId(context: CommandContext, skipPrompt?: boolean): Promise<string | undefined>;
export declare function getAnalyticsInfoString(context: CommandContext): Promise<string>;
+183
View File
@@ -0,0 +1,183 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.analyticsPackageSafelist = void 0;
exports.isPackageNameSafeForAnalytics = isPackageNameSafeForAnalytics;
exports.setAnalyticsConfig = setAnalyticsConfig;
exports.promptAnalytics = promptAnalytics;
exports.getAnalyticsUserId = getAnalyticsUserId;
exports.getAnalyticsInfoString = getAnalyticsInfoString;
const core_1 = require("@angular-devkit/core");
const node_crypto_1 = require("node:crypto");
const color_1 = require("../utilities/color");
const config_1 = require("../utilities/config");
const environment_options_1 = require("../utilities/environment-options");
const prompt_1 = require("../utilities/prompt");
const tty_1 = require("../utilities/tty");
/* eslint-disable no-console */
/**
* This is the ultimate safelist for checking if a package name is safe to report to analytics.
*/
exports.analyticsPackageSafelist = [
/^@angular\//,
/^@angular-devkit\//,
/^@nguniversal\//,
'@schematics/angular',
];
function isPackageNameSafeForAnalytics(name) {
return exports.analyticsPackageSafelist.some((pattern) => {
if (typeof pattern == 'string') {
return pattern === name;
}
else {
return pattern.test(name);
}
});
}
/**
* Set analytics settings. This does not work if the user is not inside a project.
* @param global Which config to use. "global" for user-level, and "local" for project-level.
* @param value Either a user ID, true to generate a new User ID, or false to disable analytics.
*/
async function setAnalyticsConfig(global, value) {
const level = global ? 'global' : 'local';
const workspace = await (0, config_1.getWorkspace)(level);
if (!workspace) {
throw new Error(`Could not find ${level} workspace.`);
}
const cli = (workspace.extensions['cli'] ??= {});
if (!workspace || !core_1.json.isJsonObject(cli)) {
throw new Error(`Invalid config found at ${workspace.filePath}. CLI should be an object.`);
}
cli.analytics = value === true ? (0, node_crypto_1.randomUUID)() : value;
await workspace.save();
}
/**
* Prompt the user for usage gathering permission.
* @param force Whether to ask regardless of whether or not the user is using an interactive shell.
* @return Whether or not the user was shown a prompt.
*/
async function promptAnalytics(context, global, force = false) {
const level = global ? 'global' : 'local';
const workspace = await (0, config_1.getWorkspace)(level);
if (!workspace) {
throw new Error(`Could not find a ${level} workspace. Are you in a project?`);
}
if (force || (0, tty_1.isTTY)()) {
const answer = await (0, prompt_1.askConfirmation)(`
Would you like to share pseudonymous usage data about this project with the Angular Team
at Google under Google's Privacy Policy at https://policies.google.com/privacy. For more
details and how to change this setting, see https://angular.dev/cli/analytics.
`, false);
await setAnalyticsConfig(global, answer);
if (answer) {
console.log('');
console.log(core_1.tags.stripIndent `
Thank you for sharing pseudonymous usage data. Should you change your mind, the following
command will disable this feature entirely:
${color_1.colors.yellow(`ng analytics disable${global ? ' --global' : ''}`)}
`);
console.log('');
}
process.stderr.write(await getAnalyticsInfoString(context));
return true;
}
return false;
}
/**
* Get the analytics user id.
*
* @returns
* - `string` user id.
* - `false` when disabled.
* - `undefined` when not configured.
*/
async function getAnalyticsUserIdForLevel(level) {
if (environment_options_1.analyticsDisabled) {
return false;
}
const workspace = await (0, config_1.getWorkspace)(level);
const analyticsConfig = workspace?.getCli()?.['analytics'];
if (analyticsConfig === false) {
return false;
}
else if (analyticsConfig === undefined || analyticsConfig === null) {
return undefined;
}
else {
if (typeof analyticsConfig == 'string') {
return analyticsConfig;
}
else if (typeof analyticsConfig == 'object' && typeof analyticsConfig['uid'] == 'string') {
return analyticsConfig['uid'];
}
return undefined;
}
}
async function getAnalyticsUserId(context, skipPrompt = false) {
const { workspace } = context;
// Global config takes precedence over local config only for the disabled check.
// IE:
// global: disabled & local: enabled = disabled
// global: id: 123 & local: id: 456 = 456
// check global
const globalConfig = await getAnalyticsUserIdForLevel('global');
if (globalConfig === false) {
return undefined;
}
// Not disabled globally, check locally or not set globally and command is run outside of workspace example: `ng new`
if (workspace || globalConfig === undefined) {
const level = workspace ? 'local' : 'global';
let localOrGlobalConfig = await getAnalyticsUserIdForLevel(level);
if (localOrGlobalConfig === undefined) {
if (!skipPrompt) {
// config is unset, prompt user.
// TODO: This should honor the `no-interactive` option.
// It is currently not an `ng` option but rather only an option for specific commands.
// The concept of `ng`-wide options are needed to cleanly handle this.
await promptAnalytics(context, !workspace /** global */);
localOrGlobalConfig = await getAnalyticsUserIdForLevel(level);
}
}
if (localOrGlobalConfig === false) {
return undefined;
}
else if (typeof localOrGlobalConfig === 'string') {
return localOrGlobalConfig;
}
}
return globalConfig;
}
function analyticsConfigValueToHumanFormat(value) {
if (value === false) {
return 'disabled';
}
else if (typeof value === 'string' || value === true) {
return 'enabled';
}
else {
return 'not set';
}
}
async function getAnalyticsInfoString(context) {
const analyticsInstance = await getAnalyticsUserId(context, true /** skipPrompt */);
const { globalConfiguration, workspace: localWorkspace } = context;
const globalSetting = globalConfiguration?.getCli()?.['analytics'];
const localSetting = localWorkspace?.getCli()?.['analytics'];
return (core_1.tags.stripIndents `
Global setting: ${analyticsConfigValueToHumanFormat(globalSetting)}
Local setting: ${localWorkspace
? analyticsConfigValueToHumanFormat(localSetting)
: 'No local workspace configuration file.'}
Effective status: ${analyticsInstance ? 'enabled' : 'disabled'}
` + '\n');
}
//# sourceMappingURL=analytics.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"analytics.js","sourceRoot":"","sources":["analytics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { Architect, Target } from '@angular-devkit/architect';
import { WorkspaceNodeModulesArchitectHost } from '@angular-devkit/architect/node';
import { CommandModule, CommandModuleImplementation, CommandScope, OtherOptions } from './command-module';
import { Option } from './utilities/json-schema';
export interface MissingTargetChoice {
name: string;
value: string;
}
export declare abstract class ArchitectBaseCommandModule<T extends object> extends CommandModule<T> implements CommandModuleImplementation<T> {
scope: CommandScope;
protected readonly missingTargetChoices: MissingTargetChoice[] | undefined;
protected runSingleTarget(target: Target, options: OtherOptions): Promise<number>;
private builderStatsToAnalyticsParameters;
private _architectHost;
protected getArchitectHost(): WorkspaceNodeModulesArchitectHost;
private _architect;
protected getArchitect(skipUndefinedArrayTransform: boolean): Architect;
protected getArchitectTargetOptions(target: Target): Promise<Option[]>;
private warnOnMissingNodeModules;
protected getArchitectTarget(): string;
protected onMissingTarget(defaultMessage: string): Promise<1>;
private getMissingTargetPackageToInstall;
}
@@ -0,0 +1,244 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.ArchitectBaseCommandModule = void 0;
const architect_1 = require("@angular-devkit/architect");
const node_1 = require("@angular-devkit/architect/node");
const core_1 = require("@angular-devkit/core");
const node_module_1 = require("node:module");
const analytics_1 = require("../analytics/analytics");
const analytics_parameters_1 = require("../analytics/analytics-parameters");
const error_1 = require("../utilities/error");
const prompt_1 = require("../utilities/prompt");
const tty_1 = require("../utilities/tty");
const command_module_1 = require("./command-module");
const json_schema_1 = require("./utilities/json-schema");
class ArchitectBaseCommandModule extends command_module_1.CommandModule {
scope = command_module_1.CommandScope.In;
missingTargetChoices;
async runSingleTarget(target, options) {
const architectHost = this.getArchitectHost();
let builderName;
try {
builderName = await architectHost.getBuilderNameForTarget(target);
}
catch (e) {
(0, error_1.assertIsError)(e);
return this.onMissingTarget(e.message);
}
const isAngularBuild = builderName.startsWith('@angular/build:');
const { logger } = this.context;
const run = await this.getArchitect(isAngularBuild).scheduleTarget(target, options, {
logger,
});
const analytics = (0, analytics_1.isPackageNameSafeForAnalytics)(builderName)
? await this.getAnalytics()
: undefined;
let outputSubscription;
if (analytics) {
analytics.reportArchitectRunEvent({
[analytics_parameters_1.EventCustomDimension.BuilderTarget]: builderName,
});
let firstRun = true;
outputSubscription = run.output.subscribe(({ stats }) => {
const parameters = this.builderStatsToAnalyticsParameters(stats, builderName);
if (!parameters) {
return;
}
if (firstRun) {
firstRun = false;
analytics.reportBuildRunEvent(parameters);
}
else {
analytics.reportRebuildRunEvent(parameters);
}
});
}
try {
const { error, success } = await run.lastOutput;
if (error) {
logger.error(error);
}
return success ? 0 : 1;
}
finally {
await run.stop();
outputSubscription?.unsubscribe();
}
}
builderStatsToAnalyticsParameters(stats, builderName) {
if (!stats || typeof stats !== 'object' || !('durationInMs' in stats)) {
return undefined;
}
const { optimization, allChunksCount, aot, lazyChunksCount, initialChunksCount, durationInMs, changedChunksCount, cssSizeInBytes, jsSizeInBytes, ngComponentCount, } = stats;
return {
[analytics_parameters_1.EventCustomDimension.BuilderTarget]: builderName,
[analytics_parameters_1.EventCustomDimension.Aot]: aot,
[analytics_parameters_1.EventCustomDimension.Optimization]: optimization,
[analytics_parameters_1.EventCustomMetric.AllChunksCount]: allChunksCount,
[analytics_parameters_1.EventCustomMetric.LazyChunksCount]: lazyChunksCount,
[analytics_parameters_1.EventCustomMetric.InitialChunksCount]: initialChunksCount,
[analytics_parameters_1.EventCustomMetric.ChangedChunksCount]: changedChunksCount,
[analytics_parameters_1.EventCustomMetric.DurationInMs]: durationInMs,
[analytics_parameters_1.EventCustomMetric.JsSizeInBytes]: jsSizeInBytes,
[analytics_parameters_1.EventCustomMetric.CssSizeInBytes]: cssSizeInBytes,
[analytics_parameters_1.EventCustomMetric.NgComponentCount]: ngComponentCount,
};
}
_architectHost;
getArchitectHost() {
if (this._architectHost) {
return this._architectHost;
}
const workspace = this.getWorkspaceOrThrow();
return (this._architectHost = new node_1.WorkspaceNodeModulesArchitectHost(workspace, workspace.basePath));
}
_architect;
getArchitect(skipUndefinedArrayTransform) {
if (this._architect) {
return this._architect;
}
const registry = new core_1.json.schema.CoreSchemaRegistry();
if (skipUndefinedArrayTransform) {
registry.addPostTransform(core_1.json.schema.transforms.addUndefinedObjectDefaults);
}
else {
registry.addPostTransform(core_1.json.schema.transforms.addUndefinedDefaults);
}
registry.useXDeprecatedProvider((msg) => this.context.logger.warn(msg));
const architectHost = this.getArchitectHost();
return (this._architect = new architect_1.Architect(architectHost, registry));
}
async getArchitectTargetOptions(target) {
const architectHost = this.getArchitectHost();
let builderConf;
try {
builderConf = await architectHost.getBuilderNameForTarget(target);
}
catch {
return [];
}
let builderDesc;
try {
builderDesc = await architectHost.resolveBuilder(builderConf);
}
catch (e) {
(0, error_1.assertIsError)(e);
if (e.code === 'MODULE_NOT_FOUND') {
this.warnOnMissingNodeModules();
throw new command_module_1.CommandModuleError(`Could not find the '${builderConf}' builder's node package.`);
}
throw e;
}
return (0, json_schema_1.parseJsonSchemaToOptions)(new core_1.json.schema.CoreSchemaRegistry(), builderDesc.optionSchema, true);
}
warnOnMissingNodeModules() {
const basePath = this.context.workspace?.basePath;
if (!basePath) {
return;
}
const workspaceResolve = (0, node_module_1.createRequire)(basePath + '/').resolve;
try {
workspaceResolve('@angular/core');
return;
}
catch { }
this.context.logger.warn(`Node packages may not be installed. Try installing with '${this.context.packageManager.name} install'.`);
}
getArchitectTarget() {
return this.commandName;
}
async onMissingTarget(defaultMessage) {
const { logger } = this.context;
const choices = this.missingTargetChoices;
if (!choices?.length) {
logger.error(defaultMessage);
return 1;
}
const missingTargetMessage = `Cannot find "${this.getArchitectTarget()}" target for the specified project.\n` +
`You can add a package that implements these capabilities.\n\n` +
`For example:\n` +
choices.map(({ name, value }) => ` ${name}: ng add ${value}`).join('\n') +
'\n';
if ((0, tty_1.isTTY)()) {
// Use prompts to ask the user if they'd like to install a package.
logger.warn(missingTargetMessage);
const packageToInstall = await this.getMissingTargetPackageToInstall(choices);
if (packageToInstall) {
// Example run: `ng add angular-eslint`.
const AddCommandModule = (await Promise.resolve().then(() => __importStar(require('../commands/add/cli')))).default;
await new AddCommandModule(this.context).run({
interactive: true,
force: false,
dryRun: false,
defaults: false,
collection: packageToInstall,
});
}
}
else {
// Non TTY display error message.
logger.error(missingTargetMessage);
}
return 1;
}
async getMissingTargetPackageToInstall(choices) {
if (choices.length === 1) {
// Single choice
const { name, value } = choices[0];
if (await (0, prompt_1.askConfirmation)(`Would you like to add ${name} now?`, true, false)) {
return value;
}
return null;
}
// Multiple choice
return (0, prompt_1.askQuestion)(`Would you like to add a package with "${this.getArchitectTarget()}" capabilities now?`, [
{
name: 'No',
value: null,
},
...choices,
], 0, null);
}
}
exports.ArchitectBaseCommandModule = ArchitectBaseCommandModule;
//# sourceMappingURL=architect-base-command-module.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,28 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { Target } from '@angular-devkit/architect';
import { workspaces } from '@angular-devkit/core';
import { Argv } from 'yargs';
import { ArchitectBaseCommandModule } from './architect-base-command-module';
import { CommandModuleImplementation, Options, OtherOptions } from './command-module';
export interface ArchitectCommandArgs {
configuration?: string;
project?: string;
}
export declare abstract class ArchitectCommandModule extends ArchitectBaseCommandModule<ArchitectCommandArgs> implements CommandModuleImplementation<ArchitectCommandArgs> {
abstract readonly multiTarget: boolean;
findDefaultBuilderName?(project: workspaces.ProjectDefinition, target: Target): Promise<string | undefined>;
builder(argv: Argv): Promise<Argv<ArchitectCommandArgs>>;
run(options: Options<ArchitectCommandArgs> & OtherOptions): Promise<number | void>;
private getArchitectProject;
private getProjectNamesByTarget;
/** @returns a sorted list of project names to be used for auto completion. */
private getProjectChoices;
/** @returns a sorted list of configuration names to be used for auto completion. */
private getConfigurationChoices;
}
@@ -0,0 +1,218 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
var useValue = arguments.length > 2;
for (var i = 0; i < initializers.length; i++) {
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
}
return useValue ? value : void 0;
};
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
var _, done = false;
for (var i = decorators.length - 1; i >= 0; i--) {
var context = {};
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
if (kind === "accessor") {
if (result === void 0) continue;
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
if (_ = accept(result.get)) descriptor.get = _;
if (_ = accept(result.set)) descriptor.set = _;
if (_ = accept(result.init)) initializers.unshift(_);
}
else if (_ = accept(result)) {
if (kind === "field") initializers.unshift(_);
else descriptor[key] = _;
}
}
if (target) Object.defineProperty(target, contextIn.name, descriptor);
done = true;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ArchitectCommandModule = void 0;
const config_1 = require("../utilities/config");
const memoize_1 = require("../utilities/memoize");
const architect_base_command_module_1 = require("./architect-base-command-module");
const command_module_1 = require("./command-module");
let ArchitectCommandModule = (() => {
let _classSuper = architect_base_command_module_1.ArchitectBaseCommandModule;
let _instanceExtraInitializers = [];
let _getProjectNamesByTarget_decorators;
return class ArchitectCommandModule extends _classSuper {
static {
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
_getProjectNamesByTarget_decorators = [memoize_1.memoize];
__esDecorate(this, null, _getProjectNamesByTarget_decorators, { kind: "method", name: "getProjectNamesByTarget", static: false, private: false, access: { has: obj => "getProjectNamesByTarget" in obj, get: obj => obj.getProjectNamesByTarget }, metadata: _metadata }, null, _instanceExtraInitializers);
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
}
async builder(argv) {
const target = this.getArchitectTarget();
// Add default builder if target is not in project and a command default is provided
if (this.findDefaultBuilderName && this.context.workspace) {
for (const [project, projectDefinition] of this.context.workspace.projects) {
const targetDefinition = projectDefinition.targets.get(target);
if (targetDefinition?.builder) {
continue;
}
const defaultBuilder = await this.findDefaultBuilderName(projectDefinition, {
project,
target,
});
if (!defaultBuilder) {
continue;
}
if (targetDefinition) {
targetDefinition.builder = defaultBuilder;
}
else {
projectDefinition.targets.set(target, {
builder: defaultBuilder,
});
}
}
}
const project = this.getArchitectProject();
const { jsonHelp, getYargsCompletions, help } = this.context.args.options;
const localYargs = argv
.positional('project', {
describe: 'The name of the project to build. Can be an application or a library.',
type: 'string',
// Hide choices from JSON help so that we don't display them in AIO.
choices: jsonHelp ? undefined : this.getProjectChoices(),
})
.option('configuration', {
describe: `One or more named builder configurations as a comma-separated ` +
`list as specified in the "configurations" section in angular.json.\n` +
`The builder uses the named configurations to run the given target.\n` +
`For more information, see https://angular.dev/reference/configs/workspace-config#alternate-build-configurations.`,
alias: 'c',
type: 'string',
// Show only in when using --help and auto completion because otherwise comma seperated configuration values will be invalid.
// Also, hide choices from JSON help so that we don't display them in AIO.
choices: (getYargsCompletions || help) && !jsonHelp && project
? this.getConfigurationChoices(project)
: undefined,
})
.strict();
if (!project) {
return localYargs;
}
const schemaOptions = await this.getArchitectTargetOptions({
project,
target,
});
return this.addSchemaOptionsToCommand(localYargs, schemaOptions);
}
async run(options) {
const originalProcessTitle = process.title;
try {
const target = this.getArchitectTarget();
const { configuration = '', project, ...architectOptions } = options;
if (project) {
process.title = `${originalProcessTitle} (${project})`;
return await this.runSingleTarget({ configuration, target, project }, architectOptions);
}
// This runs each target sequentially.
// Running them in parallel would jumble the log messages.
let result = 0;
const projectNames = this.getProjectNamesByTarget(target);
if (!projectNames) {
return this.onMissingTarget('Cannot determine project or target for command.');
}
for (const project of projectNames) {
process.title = `${originalProcessTitle} (${project})`;
result |= await this.runSingleTarget({ configuration, target, project }, architectOptions);
}
return result;
}
finally {
process.title = originalProcessTitle;
}
}
getArchitectProject() {
const { options, positional } = this.context.args;
const [, projectName] = positional;
if (projectName) {
return projectName;
}
// Yargs allows positional args to be used as flags.
if (typeof options['project'] === 'string') {
return options['project'];
}
const target = this.getArchitectTarget();
const projectFromTarget = this.getProjectNamesByTarget(target);
return projectFromTarget?.length ? projectFromTarget[0] : undefined;
}
getProjectNamesByTarget(target) {
const workspace = this.getWorkspaceOrThrow();
const allProjectsForTargetName = [];
for (const [name, project] of workspace.projects) {
if (project.targets.has(target)) {
allProjectsForTargetName.push(name);
}
}
if (allProjectsForTargetName.length === 0) {
return undefined;
}
if (this.multiTarget) {
// For multi target commands, we always list all projects that have the target.
return allProjectsForTargetName;
}
else {
if (allProjectsForTargetName.length === 1) {
return allProjectsForTargetName;
}
const maybeProject = (0, config_1.getProjectByCwd)(workspace);
if (maybeProject) {
return allProjectsForTargetName.includes(maybeProject) ? [maybeProject] : undefined;
}
const { getYargsCompletions, help } = this.context.args.options;
if (!getYargsCompletions && !help) {
// Only issue the below error when not in help / completion mode.
throw new command_module_1.CommandModuleError('Cannot determine project for command.\n' +
'This is a multi-project workspace and more than one project supports this command. ' +
`Run "ng ${this.command}" to execute the command for a specific project or change the current ` +
'working directory to a project directory.\n\n' +
`Available projects are:\n${allProjectsForTargetName
.sort()
.map((p) => `- ${p}`)
.join('\n')}`);
}
}
return undefined;
}
/** @returns a sorted list of project names to be used for auto completion. */
getProjectChoices() {
const { workspace } = this.context;
return workspace ? [...workspace.projects.keys()].sort() : undefined;
}
/** @returns a sorted list of configuration names to be used for auto completion. */
getConfigurationChoices(project) {
const projectDefinition = this.context.workspace?.projects.get(project);
if (!projectDefinition) {
return undefined;
}
const target = this.getArchitectTarget();
const configurations = projectDefinition.targets.get(target)?.configurations;
return configurations ? Object.keys(configurations).sort() : undefined;
}
constructor() {
super(...arguments);
__runInitializers(this, _instanceExtraInitializers);
}
};
})();
exports.ArchitectCommandModule = ArchitectCommandModule;
//# sourceMappingURL=architect-command-module.js.map
File diff suppressed because one or more lines are too long
+73
View File
@@ -0,0 +1,73 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import type { ArgumentsCamelCase, Argv, CommandModule as YargsCommandModule } from 'yargs';
import { AnalyticsCollector } from '../analytics/analytics-collector';
import { EventCustomDimension, EventCustomMetric } from '../analytics/analytics-parameters';
import { AngularWorkspace } from '../utilities/config';
import { CommandContext, CommandScope, Options, OtherOptions } from './definitions';
import { Option } from './utilities/json-schema';
export { CommandScope };
export type { CommandContext, Options, OtherOptions };
export interface CommandModuleImplementation<T extends {} = {}> extends Omit<YargsCommandModule<{}, T>, 'builder' | 'handler'> {
/** Scope in which the command can be executed in. */
scope: CommandScope;
/** Path used to load the long description for the command in JSON help text. */
longDescriptionPath?: string;
/** Object declaring the options the command accepts, or a function accepting and returning a yargs instance. */
builder(argv: Argv): Promise<Argv<T>> | Argv<T>;
/** A function which will be passed the parsed argv. */
run(options: Options<T> & OtherOptions): Promise<number | void> | number | void;
}
export interface FullDescribe {
describe?: string;
longDescription?: string;
longDescriptionRelativePath?: string;
}
export declare abstract class CommandModule<T extends {} = {}> implements CommandModuleImplementation<T> {
protected readonly context: CommandContext;
abstract readonly command: string;
abstract readonly describe: string | false;
abstract readonly longDescriptionPath?: string;
protected readonly shouldReportAnalytics: boolean;
readonly scope: CommandScope;
private readonly optionsWithAnalytics;
constructor(context: CommandContext);
/**
* Description object which contains the long command descroption.
* This is used to generate JSON help wich is used in AIO.
*
* `false` will result in a hidden command.
*/
get fullDescribe(): FullDescribe | false;
protected get commandName(): string;
abstract builder(argv: Argv): Promise<Argv<T>> | Argv<T>;
abstract run(options: Options<T> & OtherOptions): Promise<number | void> | number | void;
handler(args: ArgumentsCamelCase<T> & OtherOptions): Promise<void>;
protected getAnalytics(): Promise<AnalyticsCollector | undefined>;
/**
* Adds schema options to a command also this keeps track of options that are required for analytics.
* **Note:** This method should be called from the command bundler method.
*/
protected addSchemaOptionsToCommand<T>(localYargs: Argv<T>, options: Option[]): Argv<T>;
protected getWorkspaceOrThrow(): AngularWorkspace;
/**
* Flush on an interval (if the event loop is waiting).
*
* @returns a method that when called will terminate the periodic
* flush and call flush one last time.
*/
protected getAnalyticsParameters(options: (Options<T> & OtherOptions) | OtherOptions): Partial<Record<EventCustomDimension | EventCustomMetric, string | boolean | number>>;
private reportCommandRunAnalytics;
private reportWorkspaceInfoAnalytics;
}
/**
* Creates an known command module error.
* This is used so during executation we can filter between known validation error and real non handled errors.
*/
export declare class CommandModuleError extends Error {
}
+245
View File
@@ -0,0 +1,245 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
var useValue = arguments.length > 2;
for (var i = 0; i < initializers.length; i++) {
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
}
return useValue ? value : void 0;
};
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
var _, done = false;
for (var i = decorators.length - 1; i >= 0; i--) {
var context = {};
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
if (kind === "accessor") {
if (result === void 0) continue;
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
if (_ = accept(result.get)) descriptor.get = _;
if (_ = accept(result.set)) descriptor.set = _;
if (_ = accept(result.init)) initializers.unshift(_);
}
else if (_ = accept(result)) {
if (kind === "field") initializers.unshift(_);
else descriptor[key] = _;
}
}
if (target) Object.defineProperty(target, contextIn.name, descriptor);
done = true;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CommandModuleError = exports.CommandModule = exports.CommandScope = void 0;
const core_1 = require("@angular-devkit/core");
const node_fs_1 = require("node:fs");
const node_path_1 = require("node:path");
const helpers_1 = require("yargs/helpers");
const analytics_1 = require("../analytics/analytics");
const analytics_collector_1 = require("../analytics/analytics-collector");
const analytics_parameters_1 = require("../analytics/analytics-parameters");
const completion_1 = require("../utilities/completion");
const memoize_1 = require("../utilities/memoize");
const definitions_1 = require("./definitions");
Object.defineProperty(exports, "CommandScope", { enumerable: true, get: function () { return definitions_1.CommandScope; } });
const json_schema_1 = require("./utilities/json-schema");
let CommandModule = (() => {
let _instanceExtraInitializers = [];
let _getAnalytics_decorators;
return class CommandModule {
static {
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
_getAnalytics_decorators = [memoize_1.memoize];
__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);
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
}
context = __runInitializers(this, _instanceExtraInitializers);
shouldReportAnalytics = true;
scope = definitions_1.CommandScope.Both;
optionsWithAnalytics = new Map();
constructor(context) {
this.context = context;
}
/**
* Description object which contains the long command descroption.
* This is used to generate JSON help wich is used in AIO.
*
* `false` will result in a hidden command.
*/
get fullDescribe() {
return this.describe === false
? false
: {
describe: this.describe,
...(this.longDescriptionPath
? {
longDescriptionRelativePath: (0, node_path_1.relative)((0, node_path_1.join)(__dirname, '../../../../'), this.longDescriptionPath).replace(/\\/g, node_path_1.posix.sep),
longDescription: (0, node_fs_1.readFileSync)(this.longDescriptionPath, 'utf8').replace(/\r\n/g, '\n'),
}
: {}),
};
}
get commandName() {
return this.command.split(' ', 1)[0];
}
async handler(args) {
const { _, $0, ...options } = args;
// Camelize options as yargs will return the object in kebab-case when camel casing is disabled.
const camelCasedOptions = {};
for (const [key, value] of Object.entries(options)) {
camelCasedOptions[helpers_1.Parser.camelCase(key)] = value;
}
// Set up autocompletion if appropriate.
const autocompletionExitCode = await (0, completion_1.considerSettingUpAutocompletion)(this.commandName, this.context.logger);
if (autocompletionExitCode !== undefined) {
process.exitCode = autocompletionExitCode;
return;
}
// Gather and report analytics.
const analytics = await this.getAnalytics();
const stopPeriodicFlushes = analytics && analytics.periodFlush();
let exitCode;
try {
if (analytics) {
this.reportCommandRunAnalytics(analytics);
this.reportWorkspaceInfoAnalytics(analytics);
}
exitCode = await this.run(camelCasedOptions);
}
catch (e) {
if (e instanceof core_1.schema.SchemaValidationException) {
this.context.logger.fatal(`Error: ${e.message}`);
exitCode = 1;
}
else {
throw e;
}
}
finally {
await stopPeriodicFlushes?.();
if (typeof exitCode === 'number' && exitCode > 0) {
process.exitCode = exitCode;
}
}
}
async getAnalytics() {
if (!this.shouldReportAnalytics) {
return undefined;
}
const userId = await (0, analytics_1.getAnalyticsUserId)(this.context,
// Don't prompt on `ng update`, 'ng version' or `ng analytics`.
['version', 'update', 'analytics'].includes(this.commandName));
return userId
? new analytics_collector_1.AnalyticsCollector(this.context.logger, userId, {
name: this.context.packageManager.name,
version: await this.context.packageManager.getVersion(),
})
: undefined;
}
/**
* Adds schema options to a command also this keeps track of options that are required for analytics.
* **Note:** This method should be called from the command bundler method.
*/
addSchemaOptionsToCommand(localYargs, options) {
const optionsWithAnalytics = (0, json_schema_1.addSchemaOptionsToCommand)(localYargs, options,
// This should only be done when `--help` is used otherwise default will override options set in angular.json.
/* includeDefaultValues= */ this.context.args.options.help);
// Record option of analytics.
for (const [name, userAnalytics] of optionsWithAnalytics) {
this.optionsWithAnalytics.set(name, userAnalytics);
}
return localYargs;
}
getWorkspaceOrThrow() {
const { workspace } = this.context;
if (!workspace) {
throw new CommandModuleError('A workspace is required for this command.');
}
return workspace;
}
/**
* Flush on an interval (if the event loop is waiting).
*
* @returns a method that when called will terminate the periodic
* flush and call flush one last time.
*/
getAnalyticsParameters(options) {
const parameters = {};
const validEventCustomDimensionAndMetrics = new Set([
...Object.values(analytics_parameters_1.EventCustomDimension),
...Object.values(analytics_parameters_1.EventCustomMetric),
]);
for (const [name, ua] of this.optionsWithAnalytics) {
if (!validEventCustomDimensionAndMetrics.has(ua)) {
continue;
}
const value = options[name];
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
parameters[ua] = value;
}
else if (Array.isArray(value)) {
// GA doesn't allow array as values.
parameters[ua] = value.sort().join(', ');
}
}
return parameters;
}
reportCommandRunAnalytics(analytics) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const internalMethods = this.context.yargsInstance.getInternalMethods();
// $0 generate component [name] -> generate_component
// $0 add <collection> -> add
const fullCommand = internalMethods.getUsageInstance().getUsage()[0][0]
.split(' ')
.filter((x) => {
const code = x.charCodeAt(0);
return code >= 97 && code <= 122;
})
.join('_');
analytics.reportCommandRunEvent(fullCommand);
}
reportWorkspaceInfoAnalytics(analytics) {
const { workspace } = this.context;
if (!workspace) {
return;
}
let applicationProjectsCount = 0;
let librariesProjectsCount = 0;
for (const project of workspace.projects.values()) {
switch (project.extensions['projectType']) {
case 'application':
applicationProjectsCount++;
break;
case 'library':
librariesProjectsCount++;
break;
}
}
analytics.reportWorkspaceInfoEvent({
[analytics_parameters_1.EventCustomMetric.AllProjectsCount]: librariesProjectsCount + applicationProjectsCount,
[analytics_parameters_1.EventCustomMetric.ApplicationProjectsCount]: applicationProjectsCount,
[analytics_parameters_1.EventCustomMetric.LibraryProjectsCount]: librariesProjectsCount,
});
}
};
})();
exports.CommandModule = CommandModule;
/**
* Creates an known command module error.
* This is used so during executation we can filter between known validation error and real non handled errors.
*/
class CommandModuleError extends Error {
}
exports.CommandModuleError = CommandModuleError;
//# sourceMappingURL=command-module.js.map
File diff suppressed because one or more lines are too long
+9
View File
@@ -0,0 +1,9 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { logging } from '@angular-devkit/core';
export declare function runCommand(args: string[], logger: logging.Logger): Promise<number>;
+195
View File
@@ -0,0 +1,195 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.runCommand = runCommand;
const core_1 = require("@angular-devkit/core");
const promises_1 = require("node:fs/promises");
const node_path_1 = require("node:path");
const yargs_1 = __importDefault(require("yargs"));
const helpers_1 = require("yargs/helpers");
const utilities_1 = require("../commands/cache/utilities");
const command_config_1 = require("../commands/command-config");
const package_managers_1 = require("../package-managers");
const color_1 = require("../utilities/color");
const config_1 = require("../utilities/config");
const error_1 = require("../utilities/error");
const version_1 = require("../utilities/version");
const command_module_1 = require("./command-module");
const command_1 = require("./utilities/command");
const json_help_1 = require("./utilities/json-help");
const normalize_options_middleware_1 = require("./utilities/normalize-options-middleware");
async function runCommand(args, logger) {
const { $0, _, help = false, dryRun = false, jsonHelp = false, getYargsCompletions = false, ...rest } = (0, helpers_1.Parser)(args, {
boolean: ['help', 'json-help', 'get-yargs-completions', 'dry-run'],
alias: { 'collection': 'c' },
});
// When `getYargsCompletions` is true the scriptName 'ng' at index 0 is not removed.
const positional = getYargsCompletions ? _.slice(1) : _;
let workspace;
let globalConfiguration;
try {
[workspace, globalConfiguration] = await Promise.all([
(0, config_1.getWorkspace)('local'),
(0, config_1.getWorkspace)('global'),
]);
}
catch (e) {
(0, error_1.assertIsError)(e);
logger.fatal(e.message);
return 1;
}
const root = workspace?.basePath ?? process.cwd();
const cacheConfig = workspace && (0, utilities_1.getCacheConfig)(workspace);
const packageManager = await (0, package_managers_1.createPackageManager)({
cwd: root,
logger,
dryRun: dryRun || help || jsonHelp || getYargsCompletions,
tempDirectory: cacheConfig?.enabled ? cacheConfig.path : undefined,
configuredPackageManager: await getConfiguredPackageManager(root, workspace, globalConfiguration),
});
const localYargs = (0, yargs_1.default)(args);
const context = {
globalConfiguration,
workspace,
logger,
currentDirectory: process.cwd(),
yargsInstance: localYargs,
root,
packageManager,
args: {
positional: positional.map((v) => v.toString()),
options: {
help,
jsonHelp,
getYargsCompletions,
...rest,
},
},
};
for (const CommandModule of await getCommandsToRegister(positional[0])) {
(0, command_1.addCommandModuleToYargs)(CommandModule, context);
}
if (jsonHelp) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const usageInstance = localYargs.getInternalMethods().getUsageInstance();
usageInstance.help = () => (0, json_help_1.jsonHelpUsage)(localYargs);
}
// Add default command to support version option when no subcommand is specified
localYargs.command('*', false, (builder) => builder.version('version', 'Show Angular CLI version.', version_1.VERSION.full));
await localYargs
.scriptName('ng')
// https://github.com/yargs/yargs/blob/main/docs/advanced.md#customizing-yargs-parser
.parserConfiguration({
'populate--': true,
'unknown-options-as-args': false,
'dot-notation': false,
'boolean-negation': true,
'strip-aliased': true,
'strip-dashed': true,
'camel-case-expansion': false,
})
.option('json-help', {
describe: 'Show help in JSON format.',
implies: ['help'],
hidden: true,
type: 'boolean',
})
.help('help', 'Shows a help message for this command in the console.')
// A complete list of strings can be found: https://github.com/yargs/yargs/blob/main/locales/en.json
.updateStrings({
'Commands:': color_1.colors.cyan('Commands:'),
'Options:': color_1.colors.cyan('Options:'),
'Positionals:': color_1.colors.cyan('Arguments:'),
'deprecated': color_1.colors.yellow('deprecated'),
'deprecated: %s': color_1.colors.yellow('deprecated:') + ' %s',
'Did you mean %s?': 'Unknown command. Did you mean %s?',
})
.epilogue('For more information, see https://angular.dev/cli/.\n')
.demandCommand(1, command_1.demandCommandFailureMessage)
.recommendCommands()
.middleware((0, normalize_options_middleware_1.createNormalizeOptionsMiddleware)(localYargs))
.version(false)
.showHelpOnFail(false)
.strict()
.fail((msg, err) => {
throw msg
? // Validation failed example: `Unknown argument:`
new command_module_1.CommandModuleError(msg)
: // Unknown exception, re-throw.
err;
})
.wrap(localYargs.terminalWidth())
.parseAsync();
return +(process.exitCode ?? 0);
}
/**
* Get the commands that need to be registered.
* @returns One or more command factories that needs to be registered.
*/
async function getCommandsToRegister(commandName) {
const commands = [];
if (commandName in command_config_1.RootCommands) {
commands.push(command_config_1.RootCommands[commandName]);
}
else if (commandName in command_config_1.RootCommandsAliases) {
commands.push(command_config_1.RootCommandsAliases[commandName]);
}
else {
// Unknown command, register every possible command.
Object.values(command_config_1.RootCommands).forEach((c) => commands.push(c));
}
return Promise.all(commands.map((command) => command.factory().then((m) => m.default)));
}
/**
* Gets the configured package manager by checking package.json, or the local and global angular.json files.
*
* @param root The root directory of the workspace.
* @param localWorkspace The local workspace.
* @param globalWorkspace The global workspace.
* @returns The package manager name and version.
*/
async function getConfiguredPackageManager(root, localWorkspace, globalWorkspace) {
let result;
try {
const packageJsonPath = (0, node_path_1.join)(root, 'package.json');
const pkgJson = JSON.parse(await (0, promises_1.readFile)(packageJsonPath, 'utf-8'));
result = getPackageManager(pkgJson);
}
catch { }
if (result) {
return result;
}
if (localWorkspace) {
const project = (0, config_1.getProjectByCwd)(localWorkspace);
if (project) {
result = getPackageManager(localWorkspace.projects.get(project)?.extensions['cli']);
}
result ??= getPackageManager(localWorkspace.extensions['cli']);
}
result ??= getPackageManager(globalWorkspace.extensions['cli']);
return result;
}
/**
* Get the package manager name from a JSON value.
* @param source The JSON value to get the package manager name from.
* @returns The package manager name and version.
*/
function getPackageManager(source) {
if (source && (0, core_1.isJsonObject)(source)) {
const value = source['packageManager'];
if (typeof value === 'string') {
return value.split('@', 2);
}
}
return undefined;
}
//# sourceMappingURL=command-runner.js.map
File diff suppressed because one or more lines are too long
+41
View File
@@ -0,0 +1,41 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { logging } from '@angular-devkit/core';
import type { Argv, CamelCaseKey } from 'yargs';
import type { PackageManager } from '../package-managers/package-manager';
import { AngularWorkspace } from '../utilities/config';
export declare enum CommandScope {
/** Command can only run inside an Angular workspace. */
In = 0,
/** Command can only run outside an Angular workspace. */
Out = 1,
/** Command can run inside and outside an Angular workspace. */
Both = 2
}
export interface CommandContext {
currentDirectory: string;
root: string;
workspace?: AngularWorkspace;
globalConfiguration: AngularWorkspace;
logger: logging.Logger;
packageManager: PackageManager;
yargsInstance: Argv<{}>;
/** Arguments parsed in free-from without parser configuration. */
args: {
positional: string[];
options: {
help: boolean;
jsonHelp: boolean;
getYargsCompletions: boolean;
} & Record<string, unknown>;
};
}
export type Options<T> = {
[key in keyof T as CamelCaseKey<key>]: T[key];
};
export type OtherOptions = Record<string, unknown>;
+20
View File
@@ -0,0 +1,20 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.CommandScope = void 0;
var CommandScope;
(function (CommandScope) {
/** Command can only run inside an Angular workspace. */
CommandScope[CommandScope["In"] = 0] = "In";
/** Command can only run outside an Angular workspace. */
CommandScope[CommandScope["Out"] = 1] = "Out";
/** Command can run inside and outside an Angular workspace. */
CommandScope[CommandScope["Both"] = 2] = "Both";
})(CommandScope || (exports.CommandScope = CommandScope = {}));
//# sourceMappingURL=definitions.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["definitions.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAOH,IAAY,YASX;AATD,WAAY,YAAY;IACtB,wDAAwD;IACxD,2CAAE,CAAA;IAEF,yDAAyD;IACzD,6CAAG,CAAA;IAEH,+DAA+D;IAC/D,+CAAI,CAAA;AACN,CAAC,EATW,YAAY,4BAAZ,YAAY,QASvB"}
@@ -0,0 +1,41 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { Collection } from '@angular-devkit/schematics';
import { FileSystemCollectionDescription, FileSystemSchematicDescription, NodeWorkflow } from '@angular-devkit/schematics/tools';
import { Argv } from 'yargs';
import { CommandModule, CommandModuleImplementation, CommandScope, Options, OtherOptions } from './command-module';
import { Option } from './utilities/json-schema';
export declare const DEFAULT_SCHEMATICS_COLLECTION = "@schematics/angular";
export interface SchematicsCommandArgs {
interactive: boolean;
force: boolean;
'dry-run': boolean;
defaults: boolean;
}
export interface SchematicsExecutionOptions extends Options<SchematicsCommandArgs> {
packageRegistry?: string;
}
export declare abstract class SchematicsCommandModule extends CommandModule<SchematicsCommandArgs> implements CommandModuleImplementation<SchematicsCommandArgs> {
scope: CommandScope;
protected readonly allowPrivateSchematics: boolean;
builder(argv: Argv): Promise<Argv<SchematicsCommandArgs>>;
/** Get schematic schema options.*/
protected getSchematicOptions(collection: Collection<FileSystemCollectionDescription, FileSystemSchematicDescription>, schematicName: string, workflow: NodeWorkflow): Promise<Option[]>;
protected getOrCreateWorkflowForBuilder(collectionName: string): NodeWorkflow;
protected getOrCreateWorkflowForExecution(collectionName: string, options: SchematicsExecutionOptions): Promise<NodeWorkflow>;
protected getSchematicCollections(): Promise<Set<string>>;
protected parseSchematicInfo(schematic: string | undefined): [collectionName: string | undefined, schematicName: string | undefined];
protected runSchematic(options: {
executionOptions: SchematicsExecutionOptions;
schematicOptions: OtherOptions;
collectionName: string;
schematicName: string;
}): Promise<number>;
private getProjectName;
private getResolvePaths;
}
@@ -0,0 +1,408 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
var useValue = arguments.length > 2;
for (var i = 0; i < initializers.length; i++) {
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
}
return useValue ? value : void 0;
};
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
var _, done = false;
for (var i = decorators.length - 1; i >= 0; i--) {
var context = {};
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
if (kind === "accessor") {
if (result === void 0) continue;
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
if (_ = accept(result.get)) descriptor.get = _;
if (_ = accept(result.set)) descriptor.set = _;
if (_ = accept(result.init)) initializers.unshift(_);
}
else if (_ = accept(result)) {
if (kind === "field") initializers.unshift(_);
else descriptor[key] = _;
}
}
if (target) Object.defineProperty(target, contextIn.name, descriptor);
done = true;
};
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.SchematicsCommandModule = exports.DEFAULT_SCHEMATICS_COLLECTION = void 0;
const core_1 = require("@angular-devkit/core");
const schematics_1 = require("@angular-devkit/schematics");
const tools_1 = require("@angular-devkit/schematics/tools");
const node_path_1 = require("node:path");
const analytics_1 = require("../analytics/analytics");
const analytics_parameters_1 = require("../analytics/analytics-parameters");
const config_1 = require("../utilities/config");
const error_1 = require("../utilities/error");
const memoize_1 = require("../utilities/memoize");
const prettier_1 = require("../utilities/prettier");
const tty_1 = require("../utilities/tty");
const command_module_1 = require("./command-module");
const json_schema_1 = require("./utilities/json-schema");
const schematic_engine_host_1 = require("./utilities/schematic-engine-host");
const schematic_workflow_1 = require("./utilities/schematic-workflow");
exports.DEFAULT_SCHEMATICS_COLLECTION = '@schematics/angular';
let SchematicsCommandModule = (() => {
let _classSuper = command_module_1.CommandModule;
let _instanceExtraInitializers = [];
let _getOrCreateWorkflowForBuilder_decorators;
let _getOrCreateWorkflowForExecution_decorators;
let _getSchematicCollections_decorators;
return class SchematicsCommandModule extends _classSuper {
static {
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
_getOrCreateWorkflowForBuilder_decorators = [memoize_1.memoize];
_getOrCreateWorkflowForExecution_decorators = [memoize_1.memoize];
_getSchematicCollections_decorators = [memoize_1.memoize];
__esDecorate(this, null, _getOrCreateWorkflowForBuilder_decorators, { kind: "method", name: "getOrCreateWorkflowForBuilder", static: false, private: false, access: { has: obj => "getOrCreateWorkflowForBuilder" in obj, get: obj => obj.getOrCreateWorkflowForBuilder }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(this, null, _getOrCreateWorkflowForExecution_decorators, { kind: "method", name: "getOrCreateWorkflowForExecution", static: false, private: false, access: { has: obj => "getOrCreateWorkflowForExecution" in obj, get: obj => obj.getOrCreateWorkflowForExecution }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(this, null, _getSchematicCollections_decorators, { kind: "method", name: "getSchematicCollections", static: false, private: false, access: { has: obj => "getSchematicCollections" in obj, get: obj => obj.getSchematicCollections }, metadata: _metadata }, null, _instanceExtraInitializers);
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
}
scope = (__runInitializers(this, _instanceExtraInitializers), command_module_1.CommandScope.In);
allowPrivateSchematics = false;
async builder(argv) {
return argv
.option('interactive', {
describe: 'Enable interactive input prompts.',
type: 'boolean',
default: true,
})
.option('dry-run', {
describe: 'Run through and reports activity without writing out results.',
type: 'boolean',
alias: ['d'],
default: false,
})
.option('defaults', {
describe: 'Disable interactive input prompts for options with a default.',
type: 'boolean',
default: false,
})
.option('force', {
describe: 'Force overwriting of existing files.',
type: 'boolean',
default: false,
})
.strict();
}
/** Get schematic schema options.*/
async getSchematicOptions(collection, schematicName, workflow) {
const schematic = collection.createSchematic(schematicName, true);
const { schemaJson } = schematic.description;
if (!schemaJson) {
return [];
}
return (0, json_schema_1.parseJsonSchemaToOptions)(workflow.registry, schemaJson);
}
getOrCreateWorkflowForBuilder(collectionName) {
return new tools_1.NodeWorkflow(this.context.root, {
resolvePaths: this.getResolvePaths(collectionName),
engineHostCreator: (options) => new schematic_engine_host_1.SchematicEngineHost(options.resolvePaths),
});
}
async getOrCreateWorkflowForExecution(collectionName, options) {
const { logger, root, packageManager } = this.context;
const { force, dryRun, packageRegistry } = options;
const workflow = new tools_1.NodeWorkflow(root, {
force,
dryRun,
packageManager: packageManager.name,
// A schema registry is required to allow customizing addUndefinedDefaults
registry: new core_1.schema.CoreSchemaRegistry(schematics_1.formats.standardFormats),
packageRegistry,
resolvePaths: this.getResolvePaths(collectionName),
schemaValidation: true,
optionTransforms: [
// Add configuration file defaults
async (schematic, current) => {
const projectName = typeof current?.project === 'string' ? current.project : this.getProjectName();
return {
...(await (0, config_1.getSchematicDefaults)(schematic.collection.name, schematic.name, projectName)),
...current,
};
},
],
engineHostCreator: (options) => new schematic_engine_host_1.SchematicEngineHost(options.resolvePaths),
});
workflow.registry.addPostTransform(core_1.schema.transforms.addUndefinedDefaults);
workflow.registry.useXDeprecatedProvider((msg) => logger.warn(msg));
workflow.registry.addSmartDefaultProvider('projectName', () => this.getProjectName());
const workingDir = (0, core_1.normalize)((0, node_path_1.relative)(this.context.root, process.cwd()));
workflow.registry.addSmartDefaultProvider('workingDirectory', () => workingDir === '' ? undefined : workingDir);
workflow.engineHost.registerOptionsTransform(async (schematic, options) => {
const { collection: { name: collectionName }, name: schematicName, } = schematic;
const analytics = (0, analytics_1.isPackageNameSafeForAnalytics)(collectionName)
? await this.getAnalytics()
: undefined;
analytics?.reportSchematicRunEvent({
[analytics_parameters_1.EventCustomDimension.SchematicCollectionName]: collectionName,
[analytics_parameters_1.EventCustomDimension.SchematicName]: schematicName,
...this.getAnalyticsParameters(options),
});
return options;
});
if (options.interactive !== false && (0, tty_1.isTTY)()) {
workflow.registry.usePromptProvider(async (definitions) => {
let prompts;
const answers = {};
for (const definition of definitions) {
if (options.defaults && definition.default !== undefined) {
continue;
}
// Only load prompt package if needed
prompts ??= await Promise.resolve().then(() => __importStar(require('@inquirer/prompts')));
switch (definition.type) {
case 'confirmation':
answers[definition.id] = await prompts.confirm({
message: definition.message,
default: definition.default,
});
break;
case 'list':
if (!definition.items?.length) {
continue;
}
answers[definition.id] = await (definition.multiselect ? prompts.checkbox : prompts.select)({
message: definition.message,
validate: (values) => {
if (!definition.validator) {
return true;
}
return definition.validator(Object.values(values).map(({ value }) => value));
},
default: definition.multiselect ? undefined : definition.default,
choices: definition.items?.map((item) => typeof item == 'string'
? {
name: item,
value: item,
checked: definition.multiselect && Array.isArray(definition.default)
? definition.default?.includes(item)
: item === definition.default,
}
: {
...item,
name: item.label,
value: item.value,
checked: definition.multiselect && Array.isArray(definition.default)
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
definition.default?.includes(item.value)
: item.value === definition.default,
}),
});
break;
case 'input': {
let finalValue;
answers[definition.id] = await prompts.input({
message: definition.message,
default: definition.default,
async validate(value) {
if (definition.validator === undefined) {
return true;
}
let lastValidation = false;
for (const type of definition.propertyTypes) {
let potential;
switch (type) {
case 'string':
potential = String(value);
break;
case 'integer':
case 'number':
potential = Number(value);
break;
default:
potential = value;
break;
}
lastValidation = await definition.validator(potential);
// Can be a string if validation fails
if (lastValidation === true) {
finalValue = potential;
return true;
}
}
return lastValidation;
},
});
// Use validated value if present.
// This ensures the correct type is inserted into the final schema options.
if (finalValue !== undefined) {
answers[definition.id] = finalValue;
}
break;
}
}
}
return answers;
});
}
return workflow;
}
async getSchematicCollections() {
const getSchematicCollections = (configSection) => {
if (!configSection) {
return undefined;
}
const { schematicCollections } = configSection;
if (Array.isArray(schematicCollections)) {
return new Set(schematicCollections);
}
return undefined;
};
const { workspace, globalConfiguration } = this.context;
if (workspace) {
const project = (0, config_1.getProjectByCwd)(workspace);
if (project) {
const value = getSchematicCollections(workspace.getProjectCli(project));
if (value) {
return value;
}
}
}
const value = getSchematicCollections(workspace?.getCli()) ??
getSchematicCollections(globalConfiguration.getCli());
if (value) {
return value;
}
return new Set([exports.DEFAULT_SCHEMATICS_COLLECTION]);
}
parseSchematicInfo(schematic) {
if (schematic?.includes(':')) {
const [collectionName, schematicName] = schematic.split(':', 2);
return [collectionName, schematicName];
}
return [undefined, schematic];
}
async runSchematic(options) {
const { logger } = this.context;
const { schematicOptions, executionOptions, collectionName, schematicName } = options;
const workflow = await this.getOrCreateWorkflowForExecution(collectionName, executionOptions);
if (!schematicName) {
throw new Error('schematicName cannot be undefined.');
}
const { unsubscribe, files } = (0, schematic_workflow_1.subscribeToWorkflow)(workflow, logger);
try {
await workflow
.execute({
collection: collectionName,
schematic: schematicName,
options: schematicOptions,
logger,
allowPrivate: this.allowPrivateSchematics,
})
.toPromise();
if (!files.size) {
logger.info('Nothing to be done.');
}
if (executionOptions.dryRun) {
logger.warn(`\nNOTE: The "--dry-run" option means no changes were made.`);
return 0;
}
if (files.size) {
// Note: we could use a task executor to format the files but this is simpler.
try {
await (0, prettier_1.formatFiles)(this.context.root, files);
}
catch (error) {
(0, error_1.assertIsError)(error);
logger.warn(`WARNING: Formatting of files failed with the following error: ${error.message}`);
}
}
return 0;
}
catch (err) {
// In case the workflow was not successful, show an appropriate error message.
if (err instanceof schematics_1.UnsuccessfulWorkflowExecution) {
// "See above" because we already printed the error.
logger.fatal('The Schematic workflow failed. See above.');
}
else {
(0, error_1.assertIsError)(err);
logger.fatal(err.message);
}
return 1;
}
finally {
unsubscribe();
}
}
getProjectName() {
const { workspace } = this.context;
if (!workspace) {
return undefined;
}
const projectName = (0, config_1.getProjectByCwd)(workspace);
if (projectName) {
return projectName;
}
return undefined;
}
getResolvePaths(collectionName) {
const { workspace, root } = this.context;
if (collectionName[0] === '.') {
// Resolve relative collections from the location of `angular.json`
return [root];
}
return workspace
? // Workspace
collectionName === exports.DEFAULT_SCHEMATICS_COLLECTION
? // Favor __dirname for @schematics/angular to use the build-in version
[__dirname, process.cwd(), root]
: [process.cwd(), root, __dirname]
: // Global
[__dirname, process.cwd()];
}
};
})();
exports.SchematicsCommandModule = SchematicsCommandModule;
//# sourceMappingURL=schematics-command-module.js.map
File diff suppressed because one or more lines are too long
+13
View File
@@ -0,0 +1,13 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { CommandContext, CommandModule, CommandModuleImplementation } from '../command-module';
export declare const demandCommandFailureMessage = "You need to specify a command before moving on. Use '--help' to view the available commands.";
export type CommandModuleConstructor = Partial<CommandModuleImplementation> & {
new (context: CommandContext): Partial<CommandModuleImplementation> & CommandModule;
};
export declare function addCommandModuleToYargs<U extends CommandModuleConstructor>(commandModule: U, context: CommandContext): void;
+39
View File
@@ -0,0 +1,39 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.demandCommandFailureMessage = void 0;
exports.addCommandModuleToYargs = addCommandModuleToYargs;
const command_module_1 = require("../command-module");
exports.demandCommandFailureMessage = `You need to specify a command before moving on. Use '--help' to view the available commands.`;
function addCommandModuleToYargs(commandModule, context) {
const cmd = new commandModule(context);
const { args: { options: { jsonHelp }, }, workspace, } = context;
const describe = jsonHelp ? cmd.fullDescribe : cmd.describe;
context.yargsInstance.command({
command: cmd.command,
aliases: cmd.aliases,
describe:
// We cannot add custom fields in help, such as long command description which is used in AIO.
// Therefore, we get around this by adding a complex object as a string which we later parse when generating the help files.
typeof describe === 'object' ? JSON.stringify(describe) : describe,
deprecated: cmd.deprecated,
builder: (argv) => {
// Skip scope validation when running with '--json-help' since it's easier to generate the output for all commands this way.
const isInvalidScope = !jsonHelp &&
((cmd.scope === command_module_1.CommandScope.In && !workspace) ||
(cmd.scope === command_module_1.CommandScope.Out && workspace));
if (isInvalidScope) {
throw new command_module_1.CommandModuleError(`This command is not available when running the Angular CLI ${workspace ? 'inside' : 'outside'} a workspace.`);
}
return cmd.builder(argv);
},
handler: (args) => cmd.handler(args),
});
}
//# sourceMappingURL=command.js.map
@@ -0,0 +1 @@
{"version":3,"file":"command.js","sourceRoot":"","sources":["command.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAgBH,0DAyCC;AAtDD,sDAM2B;AAEd,QAAA,2BAA2B,GAAG,8FAA8F,CAAC;AAK1I,SAAgB,uBAAuB,CACrC,aAAgB,EAChB,OAAuB;IAEvB,MAAM,GAAG,GAAG,IAAI,aAAa,CAAC,OAAO,CAAC,CAAC;IACvC,MAAM,EACJ,IAAI,EAAE,EACJ,OAAO,EAAE,EAAE,QAAQ,EAAE,GACtB,EACD,SAAS,GACV,GAAG,OAAO,CAAC;IAEZ,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC;IAE5D,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC;QAC5B,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,QAAQ;QACN,8FAA8F;QAC9F,4HAA4H;QAC5H,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ;QACpE,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAChB,4HAA4H;YAC5H,MAAM,cAAc,GAClB,CAAC,QAAQ;gBACT,CAAC,CAAC,GAAG,CAAC,KAAK,KAAK,6BAAY,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC;oBAC5C,CAAC,GAAG,CAAC,KAAK,KAAK,6BAAY,CAAC,GAAG,IAAI,SAAS,CAAC,CAAC,CAAC;YAEnD,IAAI,cAAc,EAAE,CAAC;gBACnB,MAAM,IAAI,mCAAkB,CAC1B,8DACE,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SACzB,eAAe,CAChB,CAAC;YACJ,CAAC;YAED,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,CAAS,CAAC;QACnC,CAAC;QACD,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;KACrC,CAAC,CAAC;AACL,CAAC"}
+37
View File
@@ -0,0 +1,37 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { Argv } from 'yargs';
interface JsonHelpOption {
name: string;
type?: string;
deprecated: boolean | string;
aliases?: string[];
default?: string;
required?: boolean;
positional?: number;
enum?: string[];
description?: string;
}
interface JsonHelpDescription {
shortDescription?: string;
longDescription?: string;
longDescriptionRelativePath?: string;
}
interface JsonHelpSubcommand extends JsonHelpDescription {
name: string;
aliases: string[];
deprecated: string | boolean;
}
export interface JsonHelp extends JsonHelpDescription {
name: string;
command: string;
options: JsonHelpOption[];
subcommands?: JsonHelpSubcommand[];
}
export declare function jsonHelpUsage(localYargs: Argv): string;
export {};
+92
View File
@@ -0,0 +1,92 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.jsonHelpUsage = jsonHelpUsage;
const yargsDefaultCommandRegExp = /^\$0|\*/;
function jsonHelpUsage(localYargs) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const localYargsInstance = localYargs;
const { deprecatedOptions, alias: aliases, array, string, boolean, number, choices, demandedOptions, default: defaultVal, hiddenOptions = [], } = localYargsInstance.getOptions();
const internalMethods = localYargsInstance.getInternalMethods();
const usageInstance = internalMethods.getUsageInstance();
const context = internalMethods.getContext();
const descriptions = usageInstance.getDescriptions();
const groups = localYargsInstance.getGroups();
const positional = groups[usageInstance.getPositionalGroupName()];
const seen = new Set();
const hidden = new Set(hiddenOptions);
const normalizeOptions = [];
const allAliases = new Set([...Object.values(aliases).flat()]);
// Reverted order of https://github.com/yargs/yargs/blob/971e351705f0fbc5566c6ed1dfd707fa65e11c0d/lib/usage.ts#L419-L424
for (const [names, type] of [
[number, 'number'],
[array, 'array'],
[string, 'string'],
[boolean, 'boolean'],
]) {
for (const name of names) {
if (allAliases.has(name) || hidden.has(name) || seen.has(name)) {
// Ignore hidden, aliases and already visited option.
continue;
}
seen.add(name);
const positionalIndex = positional?.indexOf(name) ?? -1;
const alias = aliases[name];
normalizeOptions.push({
name,
type,
deprecated: deprecatedOptions[name],
aliases: alias?.length > 0 ? alias : undefined,
default: defaultVal[name],
required: demandedOptions[name],
enum: choices[name],
description: descriptions[name]?.replace('__yargsString__:', ''),
positional: positionalIndex >= 0 ? positionalIndex : undefined,
});
}
}
// https://github.com/yargs/yargs/blob/00e4ebbe3acd438e73fdb101e75b4f879eb6d345/lib/usage.ts#L124
const subcommands = usageInstance.getCommands()
.map(([name, rawDescription, isDefault, aliases, deprecated]) => ({
name: name.split(' ', 1)[0].replace(yargsDefaultCommandRegExp, ''),
command: name.replace(yargsDefaultCommandRegExp, ''),
default: isDefault || undefined,
...parseDescription(rawDescription),
aliases,
deprecated,
}))
.sort((a, b) => a.name.localeCompare(b.name));
const [command, rawDescription] = usageInstance.getUsage()[0] ?? [];
const defaultSubCommand = subcommands.find((x) => x.default)?.command ?? '';
const otherSubcommands = subcommands.filter((s) => !s.default);
const output = {
name: [...context.commands].pop(),
command: `${command?.replace(yargsDefaultCommandRegExp, localYargsInstance['$0'])}${defaultSubCommand}`,
...parseDescription(rawDescription),
options: normalizeOptions.sort((a, b) => a.name.localeCompare(b.name)),
subcommands: otherSubcommands.length ? otherSubcommands : undefined,
};
return JSON.stringify(output, undefined, 2);
}
function parseDescription(rawDescription) {
try {
const { longDescription, describe: shortDescription, longDescriptionRelativePath, } = JSON.parse(rawDescription);
return {
shortDescription,
longDescriptionRelativePath,
longDescription,
};
}
catch {
return {
shortDescription: rawDescription,
};
}
}
//# sourceMappingURL=json-help.js.map
@@ -0,0 +1 @@
{"version":3,"file":"json-help.js","sourceRoot":"","sources":["json-help.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { json } from '@angular-devkit/core';
import type { Argv, Options as YargsOptions } from 'yargs';
import { EventCustomDimension } from '../../analytics/analytics-parameters';
/**
* An option description that can be used by yargs to create a command.
* See: https://github.com/yargs/yargs/blob/main/docs/options.mjs
*/
export interface Option extends YargsOptions {
/**
* The name of the option.
*/
name: string;
/**
* Whether this option is required or not.
*/
required?: boolean;
/**
* Format field of this option.
*/
format?: string;
/**
* Whether this option should be hidden from the help output. It will still show up in JSON help.
*/
hidden?: boolean;
/**
* If this option can be used as an argument, the position of the argument. Otherwise omitted.
*/
positional?: number;
/**
* Whether or not to report this option to the Angular Team, and which custom field to use.
* If this is falsey, do not report this option.
*/
userAnalytics?: string;
/**
* Type of the values in a key/value pair field.
*/
itemValueType?: 'string';
}
/**
* Parses a JSON schema to a list of options that can be used by yargs.
*
* @param registry A schema registry to use for flattening the schema.
* @param schema The JSON schema to parse.
* @param interactive Whether to prompt the user for missing options.
* @returns A list of options.
*
* @note The schema definition are not resolved at this stage. This means that `$ref` will not be resolved,
* and custom keywords like `x-prompt` will not be processed.
*/
export declare function parseJsonSchemaToOptions(registry: json.schema.SchemaRegistry, schema: json.JsonObject, interactive?: boolean): Promise<Option[]>;
/**
* Adds schema options to a command also this keeps track of options that are required for analytics.
* **Note:** This method should be called from the command bundler method.
*
* @returns A map from option name to analytics configuration.
*/
export declare function addSchemaOptionsToCommand<T>(localYargs: Argv<T>, options: Option[], includeDefaultValues: boolean): Map<string, EventCustomDimension>;
+349
View File
@@ -0,0 +1,349 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseJsonSchemaToOptions = parseJsonSchemaToOptions;
exports.addSchemaOptionsToCommand = addSchemaOptionsToCommand;
const core_1 = require("@angular-devkit/core");
/**
* A Yargs check function that validates that the given options are in the form of `key=value`.
* @param keyValuePairOptions A set of options that should be in the form of `key=value`.
* @param args The parsed arguments.
* @returns `true` if the options are valid, otherwise an error is thrown.
*/
function checkStringMap(keyValuePairOptions, args) {
for (const key of keyValuePairOptions) {
const value = args[key];
if (!Array.isArray(value)) {
// Value has been parsed.
continue;
}
for (const pair of value) {
if (pair === undefined) {
continue;
}
if (!pair.includes('=')) {
throw new Error(`Invalid value for argument: ${key}, Given: '${pair}', Expected key=value pair`);
}
}
}
return true;
}
/**
* A Yargs coerce function that converts an array of `key=value` strings to an object.
* @param value An array of `key=value` strings.
* @returns An object with the keys and values from the input array.
*/
function coerceToStringMap(value) {
const stringMap = {};
for (const pair of value) {
// This happens when the flag isn't passed at all.
if (pair === undefined) {
continue;
}
const eqIdx = pair.indexOf('=');
if (eqIdx === -1) {
// In the case it is not valid skip processing this option and handle the error in `checkStringMap`
return value;
}
const key = pair.slice(0, eqIdx);
stringMap[key] = pair.slice(eqIdx + 1);
}
return stringMap;
}
/**
* Checks if a JSON schema node represents a string map.
* A string map is an object with `additionalProperties` of type `string`.
* @param node The JSON schema node to check.
* @returns `true` if the node represents a string map, otherwise `false`.
*/
function isStringMap(node) {
// Exclude fields with more specific kinds of properties.
if (node.properties || node.patternProperties) {
return false;
}
// Restrict to additionalProperties with string values.
return (core_1.json.isJsonObject(node.additionalProperties) &&
!node.additionalProperties.enum &&
node.additionalProperties.type === 'string');
}
const SUPPORTED_PRIMITIVE_TYPES = new Set(['boolean', 'number', 'string']);
/**
* Checks if a string is a supported primitive type.
* @param value The string to check.
* @returns `true` if the string is a supported primitive type, otherwise `false`.
*/
function isSupportedPrimitiveType(value) {
return SUPPORTED_PRIMITIVE_TYPES.has(value);
}
/**
* Recursively checks if a JSON schema for an array's items is a supported primitive type.
* It supports `oneOf` and `anyOf` keywords.
* @param schema The JSON schema for the array's items.
* @returns `true` if the schema is a supported primitive type, otherwise `false`.
*/
function isSupportedArrayItemSchema(schema) {
if (typeof schema.type === 'string' && isSupportedPrimitiveType(schema.type)) {
return true;
}
if (core_1.json.isJsonArray(schema.enum)) {
return true;
}
if (core_1.json.isJsonArray(schema.items)) {
return schema.items.some((item) => (0, core_1.isJsonObject)(item) && isSupportedArrayItemSchema(item));
}
if (core_1.json.isJsonArray(schema.oneOf) &&
schema.oneOf.some((item) => (0, core_1.isJsonObject)(item) && isSupportedArrayItemSchema(item))) {
return true;
}
if (core_1.json.isJsonArray(schema.anyOf) &&
schema.anyOf.some((item) => (0, core_1.isJsonObject)(item) && isSupportedArrayItemSchema(item))) {
return true;
}
return false;
}
/**
* Gets the supported types for a JSON schema node.
* @param current The JSON schema node to get the supported types for.
* @returns An array of supported types.
*/
function getSupportedTypes(current) {
const typeSet = core_1.json.schema.getTypesOfSchema(current);
if (typeSet.size === 0) {
return [];
}
return [...typeSet].filter((type) => {
switch (type) {
case 'boolean':
case 'number':
case 'string':
return true;
case 'array':
return (0, core_1.isJsonObject)(current.items) && isSupportedArrayItemSchema(current.items);
case 'object':
return isStringMap(current);
default:
return false;
}
});
}
/**
* Gets the enum values for a JSON schema node.
* @param current The JSON schema node to get the enum values for.
* @returns An array of enum values.
*/
function getEnumValues(current) {
if (core_1.json.isJsonArray(current.enum)) {
return current.enum.sort();
}
if ((0, core_1.isJsonObject)(current.items)) {
const enumValues = getEnumValues(current.items);
if (enumValues?.length) {
return enumValues;
}
}
if (typeof current.type === 'string' && isSupportedPrimitiveType(current.type)) {
return [];
}
const subSchemas = (core_1.json.isJsonArray(current.oneOf) && current.oneOf) ||
(core_1.json.isJsonArray(current.anyOf) && current.anyOf);
if (subSchemas) {
// Find the first enum.
for (const subSchema of subSchemas) {
if ((0, core_1.isJsonObject)(subSchema)) {
const enumValues = getEnumValues(subSchema);
if (enumValues) {
return enumValues;
}
}
}
}
return [];
}
/**
* Gets the default value for a JSON schema node.
* @param current The JSON schema node to get the default value for.
* @param type The type of the JSON schema node.
* @returns The default value, or `undefined` if there is no default value.
*/
function getDefaultValue(current, type) {
const defaultValue = current.default;
if (defaultValue === undefined) {
return undefined;
}
if (type === 'array') {
return Array.isArray(defaultValue) && defaultValue.length > 0 ? defaultValue : undefined;
}
if (typeof defaultValue === type) {
return defaultValue;
}
return undefined;
}
/**
* Gets the aliases for a JSON schema node.
* @param current The JSON schema node to get the aliases for.
* @returns An array of aliases.
*/
function getAliases(current) {
if (core_1.json.isJsonArray(current.aliases)) {
return [...current.aliases].map(String);
}
if (current.alias) {
return [String(current.alias)];
}
return [];
}
/**
* Parses a JSON schema to a list of options that can be used by yargs.
*
* @param registry A schema registry to use for flattening the schema.
* @param schema The JSON schema to parse.
* @param interactive Whether to prompt the user for missing options.
* @returns A list of options.
*
* @note The schema definition are not resolved at this stage. This means that `$ref` will not be resolved,
* and custom keywords like `x-prompt` will not be processed.
*/
async function parseJsonSchemaToOptions(registry, schema, interactive = true) {
const options = [];
function visitor(current, pointer, parentSchema) {
if (!parentSchema ||
core_1.json.isJsonArray(current) ||
pointer.split(/\/(?:properties|items|definitions)\//g).length > 2) {
// Ignore root, arrays, and subitems.
return;
}
if (pointer.includes('/not/')) {
// We don't support anyOf/not.
throw new Error('The "not" keyword is not supported in JSON Schema.');
}
const ptr = core_1.json.schema.parseJsonPointer(pointer);
if (ptr[ptr.length - 2] !== 'properties') {
// Skip any non-property items.
return;
}
const name = ptr.at(-1);
const types = getSupportedTypes(current);
if (types.length === 0) {
// This means it's not usable on the command line. e.g. an Object.
return;
}
const [type] = types;
const $default = current.$default;
const $defaultIndex = (0, core_1.isJsonObject)($default) && $default['$source'] === 'argv' ? $default['index'] : undefined;
const positional = typeof $defaultIndex === 'number' ? $defaultIndex : undefined;
let required = core_1.json.isJsonArray(schema.required) && schema.required.includes(name);
if (required && interactive && current['x-prompt']) {
required = false;
}
const visible = current.visible !== false;
const xDeprecated = current['x-deprecated'];
const enumValues = getEnumValues(current);
const option = {
name,
description: String(current.description ?? ''),
default: getDefaultValue(current, type),
choices: enumValues?.length ? enumValues : undefined,
required,
alias: getAliases(current),
format: typeof current.format === 'string' ? current.format : undefined,
hidden: !!current.hidden || !visible,
userAnalytics: typeof current['x-user-analytics'] === 'string' ? current['x-user-analytics'] : undefined,
deprecated: xDeprecated === true || typeof xDeprecated === 'string' ? xDeprecated : undefined,
positional,
...(type === 'object'
? {
type: 'array',
itemValueType: 'string',
}
: {
type,
}),
};
options.push(option);
}
const flattenedSchema = await registry.ɵflatten(schema);
core_1.json.schema.visitJsonSchema(flattenedSchema, visitor);
// Sort by positional and name.
return options.sort((a, b) => {
if (a.positional) {
return b.positional ? a.positional - b.positional : a.name.localeCompare(b.name);
}
else if (b.positional) {
return -1;
}
return a.name.localeCompare(b.name);
});
}
/**
* Adds schema options to a command also this keeps track of options that are required for analytics.
* **Note:** This method should be called from the command bundler method.
*
* @returns A map from option name to analytics configuration.
*/
function addSchemaOptionsToCommand(localYargs, options, includeDefaultValues) {
const booleanOptionsWithNoPrefix = new Set();
const keyValuePairOptions = new Set();
const optionsWithAnalytics = new Map();
for (const option of options) {
const { default: defaultVal, positional, deprecated, description, alias, userAnalytics, type, itemValueType, hidden, name, choices, } = option;
let dashedName = core_1.strings.dasherize(name);
// Handle options which have been defined in the schema with `no` prefix.
if (type === 'boolean' && dashedName.startsWith('no-')) {
dashedName = dashedName.slice(3);
booleanOptionsWithNoPrefix.add(dashedName);
}
if (itemValueType) {
keyValuePairOptions.add(dashedName);
}
const sharedOptions = {
alias,
hidden,
description,
deprecated,
choices,
coerce: itemValueType ? coerceToStringMap : undefined,
// This should only be done when `--help` is used otherwise default will override options set in angular.json.
...(includeDefaultValues ? { default: defaultVal } : {}),
};
if (positional === undefined) {
localYargs = localYargs.option(dashedName, {
array: itemValueType ? true : undefined,
type: itemValueType ?? type,
...sharedOptions,
});
}
else {
localYargs = localYargs.positional(dashedName, {
type: type === 'array' || type === 'count' ? 'string' : type,
...sharedOptions,
});
}
// Record option of analytics.
if (userAnalytics !== undefined) {
optionsWithAnalytics.set(name, userAnalytics);
}
}
// Valid key/value options
if (keyValuePairOptions.size) {
localYargs.check(checkStringMap.bind(null, keyValuePairOptions), false);
}
// Handle options which have been defined in the schema with `no` prefix.
if (booleanOptionsWithNoPrefix.size) {
localYargs.middleware((options) => {
for (const key of booleanOptionsWithNoPrefix) {
if (key in options) {
options[`no-${key}`] = !options[key];
delete options[key];
}
}
}, false);
}
return optionsWithAnalytics;
}
//# sourceMappingURL=json-schema.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,18 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import type { Arguments, Argv } from 'yargs';
/**
* A Yargs middleware that normalizes non Array options when the argument has been provided multiple times.
*
* By default, when an option is non array and it is provided multiple times in the command line, yargs
* will not override it's value but instead it will be changed to an array unless `duplicate-arguments-array` is disabled.
* But this option also have an effect on real array options which isn't desired.
*
* See: https://github.com/yargs/yargs-parser/pull/163#issuecomment-516566614
*/
export declare function createNormalizeOptionsMiddleware(localeYargs: Argv): (args: Arguments) => void;
@@ -0,0 +1,37 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.createNormalizeOptionsMiddleware = createNormalizeOptionsMiddleware;
/**
* A Yargs middleware that normalizes non Array options when the argument has been provided multiple times.
*
* By default, when an option is non array and it is provided multiple times in the command line, yargs
* will not override it's value but instead it will be changed to an array unless `duplicate-arguments-array` is disabled.
* But this option also have an effect on real array options which isn't desired.
*
* See: https://github.com/yargs/yargs-parser/pull/163#issuecomment-516566614
*/
function createNormalizeOptionsMiddleware(localeYargs) {
return (args) => {
// `getOptions` is not included in the types even though it's public API.
// https://github.com/yargs/yargs/issues/2098
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const { array } = localeYargs.getOptions();
const arrayOptions = new Set(array);
for (const [key, value] of Object.entries(args)) {
if (key !== '_' && Array.isArray(value) && !arrayOptions.has(key)) {
const newValue = value.pop();
// eslint-disable-next-line no-console
console.warn(`Option '${key}' has been specified multiple times. The value '${newValue}' will be used.`);
args[key] = newValue;
}
}
};
}
//# sourceMappingURL=normalize-options-middleware.js.map
@@ -0,0 +1 @@
{"version":3,"file":"normalize-options-middleware.js","sourceRoot":"","sources":["normalize-options-middleware.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAaH,4EAmBC;AA5BD;;;;;;;;GAQG;AACH,SAAgB,gCAAgC,CAAC,WAAiB;IAChE,OAAO,CAAC,IAAe,EAAE,EAAE;QACzB,yEAAyE;QACzE,6CAA6C;QAC7C,8DAA8D;QAC9D,MAAM,EAAE,KAAK,EAAE,GAAI,WAAmB,CAAC,UAAU,EAAE,CAAC;QACpD,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;QAEpC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAChD,IAAI,GAAG,KAAK,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBAClE,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;gBAC7B,sCAAsC;gBACtC,OAAO,CAAC,IAAI,CACV,WAAW,GAAG,mDAAmD,QAAQ,iBAAiB,CAC3F,CAAC;gBACF,IAAI,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { RuleFactory } from '@angular-devkit/schematics';
import { FileSystemCollectionDesc, NodeModulesEngineHost } from '@angular-devkit/schematics/tools';
export declare class SchematicEngineHost extends NodeModulesEngineHost {
protected _resolveReferenceString(refString: string, parentPath: string, collectionDescription?: FileSystemCollectionDesc): {
ref: RuleFactory<{}>;
path: string;
} | null;
}
@@ -0,0 +1,179 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.SchematicEngineHost = void 0;
const schematics_1 = require("@angular-devkit/schematics");
const tools_1 = require("@angular-devkit/schematics/tools");
const jsonc_parser_1 = require("jsonc-parser");
const node_fs_1 = require("node:fs");
const node_module_1 = require("node:module");
const node_path_1 = require("node:path");
const node_vm_1 = require("node:vm");
const error_1 = require("../../utilities/error");
/**
* Environment variable to control schematic package redirection
*/
const schematicRedirectVariable = process.env['NG_SCHEMATIC_REDIRECT']?.toLowerCase();
function shouldWrapSchematic(schematicFile, schematicEncapsulation) {
// Check environment variable if present
switch (schematicRedirectVariable) {
case '0':
case 'false':
case 'off':
case 'none':
return false;
case 'all':
return true;
}
const normalizedSchematicFile = schematicFile.replace(/\\/g, '/');
// Never wrap the internal update schematic when executed directly
// It communicates with the update command via `global`
// But we still want to redirect schematics located in `@angular/cli/node_modules`.
if (normalizedSchematicFile.includes('node_modules/@angular/cli/') &&
!normalizedSchematicFile.includes('node_modules/@angular/cli/node_modules/')) {
return false;
}
// @angular/pwa uses dynamic imports which causes `[1] 2468039 segmentation fault` when wrapped.
// We should remove this when make `importModuleDynamically` work.
// See: https://nodejs.org/docs/latest-v14.x/api/vm.html
if (normalizedSchematicFile.includes('@angular/pwa')) {
return false;
}
// Check for first-party Angular schematic packages
// Angular schematics are safe to use in the wrapped VM context
const isFirstParty = /\/node_modules\/@(?:angular|schematics|nguniversal)\//.test(normalizedSchematicFile);
// Use value of defined option if present, otherwise default to first-party usage.
return schematicEncapsulation ?? isFirstParty;
}
class SchematicEngineHost extends tools_1.NodeModulesEngineHost {
_resolveReferenceString(refString, parentPath, collectionDescription) {
const [path, name] = refString.split('#', 2);
// Mimic behavior of ExportStringRef class used in default behavior
const fullPath = path[0] === '.' ? (0, node_path_1.resolve)(parentPath ?? process.cwd(), path) : path;
const referenceRequire = (0, node_module_1.createRequire)(__filename);
const schematicFile = referenceRequire.resolve(fullPath, { paths: [parentPath] });
if (shouldWrapSchematic(schematicFile, collectionDescription?.encapsulation)) {
const schematicPath = (0, node_path_1.dirname)(schematicFile);
const moduleCache = new Map();
const factoryInitializer = wrap(schematicFile, schematicPath, moduleCache, name || 'default');
const factory = factoryInitializer();
if (!factory || typeof factory !== 'function') {
return null;
}
return { ref: factory, path: schematicPath };
}
// All other schematics use default behavior
return super._resolveReferenceString(refString, parentPath, collectionDescription);
}
}
exports.SchematicEngineHost = SchematicEngineHost;
/**
* Minimal shim modules for legacy deep imports of `@schematics/angular`
*/
const legacyModules = {
'@schematics/angular/utility/config': {
getWorkspace(host) {
const path = '/.angular.json';
const data = host.read(path);
if (!data) {
throw new schematics_1.SchematicsException(`Could not find (${path})`);
}
return (0, jsonc_parser_1.parse)(data.toString(), [], { allowTrailingComma: true });
},
},
'@schematics/angular/utility/project': {
buildDefaultPath(project) {
const root = project.sourceRoot ? `/${project.sourceRoot}/` : `/${project.root}/src/`;
return `${root}${project.projectType === 'application' ? 'app' : 'lib'}`;
},
},
};
/**
* Wrap a JavaScript file in a VM context to allow specific Angular dependencies to be redirected.
* This VM setup is ONLY intended to redirect dependencies.
*
* @param schematicFile A JavaScript schematic file path that should be wrapped.
* @param schematicDirectory A directory that will be used as the location of the JavaScript file.
* @param moduleCache A map to use for caching repeat module usage and proper `instanceof` support.
* @param exportName An optional name of a specific export to return. Otherwise, return all exports.
*/
function wrap(schematicFile, schematicDirectory, moduleCache, exportName) {
const hostRequire = (0, node_module_1.createRequire)(__filename);
const schematicRequire = (0, node_module_1.createRequire)(schematicFile);
const customRequire = function (id) {
if (legacyModules[id]) {
// Provide compatibility modules for older versions of @angular/cdk
return legacyModules[id];
}
else if (id.startsWith('schematics:')) {
// Schematics built-in modules use the `schematics` scheme (similar to the Node.js `node` scheme)
const builtinId = id.slice(11);
const builtinModule = loadBuiltinModule(builtinId);
if (!builtinModule) {
throw new Error(`Unknown schematics built-in module '${id}' requested from schematic '${schematicFile}'`);
}
return builtinModule;
}
else if (id.startsWith('@angular-devkit/') || id.startsWith('@schematics/')) {
// Files should not redirect `@angular/core` and instead use the direct
// dependency if available. This allows old major version migrations to continue to function
// even though the latest major version may have breaking changes in `@angular/core`.
if (id.startsWith('@angular-devkit/core')) {
try {
return schematicRequire(id);
}
catch (e) {
(0, error_1.assertIsError)(e);
if (e.code !== 'MODULE_NOT_FOUND') {
throw e;
}
}
}
// Resolve from inside the `@angular/cli` project
return hostRequire(id);
}
else if (id.startsWith('.') || id.startsWith('@angular/cdk')) {
// Wrap relative files inside the schematic collection
// Also wrap `@angular/cdk`, it contains helper utilities that import core schematic packages
// Resolve from the original file
const modulePath = schematicRequire.resolve(id);
// Use cached module if available
const cachedModule = moduleCache.get(modulePath);
if (cachedModule) {
return cachedModule;
}
// Do not wrap vendored third-party packages or JSON files
if (!/[/\\]node_modules[/\\]@schematics[/\\]angular[/\\]third_party[/\\]/.test(modulePath) &&
!modulePath.endsWith('.json')) {
// Wrap module and save in cache
const wrappedModule = wrap(modulePath, (0, node_path_1.dirname)(modulePath), moduleCache)();
moduleCache.set(modulePath, wrappedModule);
return wrappedModule;
}
}
// All others are required directly from the original file
return schematicRequire(id);
};
// Setup a wrapper function to capture the module's exports
const schematicCode = (0, node_fs_1.readFileSync)(schematicFile, 'utf8');
const script = new node_vm_1.Script(node_module_1.Module.wrap(schematicCode), {
filename: schematicFile,
lineOffset: 1,
});
const schematicModule = new node_module_1.Module(schematicFile);
const moduleFactory = script.runInThisContext();
return () => {
moduleFactory(schematicModule.exports, customRequire, schematicModule, schematicFile, schematicDirectory);
return exportName ? schematicModule.exports[exportName] : schematicModule.exports;
};
}
function loadBuiltinModule(id) {
return undefined;
}
//# sourceMappingURL=schematic-engine-host.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,14 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { logging } from '@angular-devkit/core';
import { NodeWorkflow } from '@angular-devkit/schematics/tools';
export declare function subscribeToWorkflow(workflow: NodeWorkflow, logger: logging.LoggerApi): {
files: Set<string>;
error: boolean;
unsubscribe: () => void;
};
@@ -0,0 +1,70 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.subscribeToWorkflow = subscribeToWorkflow;
const color_1 = require("../../utilities/color");
function removeLeadingSlash(value) {
return value[0] === '/' ? value.slice(1) : value;
}
function subscribeToWorkflow(workflow, logger) {
const files = new Set();
let error = false;
let logs = [];
const reporterSubscription = workflow.reporter.subscribe((event) => {
// Strip leading slash to prevent confusion.
const eventPath = removeLeadingSlash(event.path);
switch (event.kind) {
case 'error':
error = true;
logger.error(`ERROR! ${eventPath} ${event.description == 'alreadyExist' ? 'already exists' : 'does not exist'}.`);
break;
case 'update':
logs.push(
// TODO: `as unknown` was necessary during TS 5.9 update. Figure out a long-term solution.
`${color_1.colors.cyan('UPDATE')} ${eventPath} (${event.content.length} bytes)`);
files.add(eventPath);
break;
case 'create':
logs.push(
// TODO: `as unknown` was necessary during TS 5.9 update. Figure out a long-term solution.
`${color_1.colors.green('CREATE')} ${eventPath} (${event.content.length} bytes)`);
files.add(eventPath);
break;
case 'delete':
logs.push(`${color_1.colors.yellow('DELETE')} ${eventPath}`);
files.add(eventPath);
break;
case 'rename': {
const newFilename = removeLeadingSlash(event.to);
logs.push(`${color_1.colors.blue('RENAME')} ${eventPath} => ${newFilename}`);
files.add(newFilename);
break;
}
}
});
const lifecycleSubscription = workflow.lifeCycle.subscribe((event) => {
if (event.kind == 'end' || event.kind == 'post-tasks-start') {
if (!error) {
// Output the logging queue, no error happened.
logs.forEach((log) => logger.info(log));
}
logs = [];
error = false;
}
});
return {
files,
error,
unsubscribe: () => {
reporterSubscription.unsubscribe();
lifecycleSubscription.unsubscribe();
},
};
}
//# sourceMappingURL=schematic-workflow.js.map
@@ -0,0 +1 @@
{"version":3,"file":"schematic-workflow.js","sourceRoot":"","sources":["schematic-workflow.ts"],"names":[],"mappings":"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"}
+38
View File
@@ -0,0 +1,38 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { Argv } from 'yargs';
import { CommandModuleImplementation, Options, OtherOptions } from '../../command-builder/command-module';
import { SchematicsCommandArgs, SchematicsCommandModule } from '../../command-builder/schematics-command-module';
interface AddCommandArgs extends SchematicsCommandArgs {
collection: string;
verbose?: boolean;
registry?: string;
'skip-confirmation'?: boolean;
}
export default class AddCommandModule extends SchematicsCommandModule implements CommandModuleImplementation<AddCommandArgs> {
#private;
command: string;
describe: string;
longDescriptionPath: string;
protected allowPrivateSchematics: boolean;
private readonly schematicName;
private rootRequire;
builder(argv: Argv): Promise<Argv<AddCommandArgs>>;
run(options: Options<AddCommandArgs> & OtherOptions): Promise<number | void>;
private findCompatiblePackageVersionTask;
private loadPackageInfoTask;
private confirmInstallationTask;
private installPackageTask;
private isProjectVersionValid;
private getCollectionName;
private isPackageInstalled;
private executeSchematic;
private findProjectVersion;
private getPeerDependencyConflicts;
}
export {};
+623
View File
@@ -0,0 +1,623 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const listr2_1 = require("listr2");
const node_assert_1 = __importDefault(require("node:assert"));
const promises_1 = __importDefault(require("node:fs/promises"));
const node_module_1 = require("node:module");
const node_path_1 = require("node:path");
const npm_package_arg_1 = __importDefault(require("npm-package-arg"));
const semver_1 = __importStar(require("semver"));
const schematics_command_module_1 = require("../../command-builder/schematics-command-module");
const package_managers_1 = require("../../package-managers");
const error_1 = require("../../utilities/error");
const tty_1 = require("../../utilities/tty");
const version_1 = require("../../utilities/version");
class CommandError extends Error {
}
/**
* The set of packages that should have certain versions excluded from consideration
* when attempting to find a compatible version for a package.
* The key is a package name and the value is a SemVer range of versions to exclude.
*/
const packageVersionExclusions = {
// @angular/localize@9.x and earlier versions as well as @angular/localize@10.0 prereleases do not have peer dependencies setup.
'@angular/localize': '<10.0.0',
// @angular/material@7.x versions have unbounded peer dependency ranges (>=7.0.0).
'@angular/material': '7.x',
};
const DEFAULT_CONFLICT_DISPLAY_LIMIT = 5;
/**
* A map of packages to built-in schematics.
* This is used for packages that do not have a native `ng-add` schematic.
*/
const BUILT_IN_SCHEMATICS = {
tailwindcss: {
collection: '@schematics/angular',
name: 'tailwind',
},
'@vitest/browser-playwright': {
collection: '@schematics/angular',
name: 'vitest-browser',
},
'@vitest/browser-webdriverio': {
collection: '@schematics/angular',
name: 'vitest-browser',
},
'@vitest/browser-preview': {
collection: '@schematics/angular',
name: 'vitest-browser',
},
};
class AddCommandModule extends schematics_command_module_1.SchematicsCommandModule {
command = 'add <collection>';
describe = 'Adds support for an external library to your project.';
longDescriptionPath = (0, node_path_1.join)(__dirname, 'long-description.md');
allowPrivateSchematics = true;
schematicName = 'ng-add';
rootRequire = (0, node_module_1.createRequire)(this.context.root + '/');
#projectVersionCache = new Map();
async builder(argv) {
const localYargs = (await super.builder(argv))
.positional('collection', {
description: 'The package to be added.',
type: 'string',
demandOption: true,
})
.option('registry', { description: 'The NPM registry to use.', type: 'string' })
.option('verbose', {
description: 'Display additional details about internal operations during execution.',
type: 'boolean',
default: false,
})
.option('skip-confirmation', {
description: 'Skip asking a confirmation prompt before installing and executing the package. ' +
'Ensure package name is correct prior to using this option.',
type: 'boolean',
default: false,
})
// Prior to downloading we don't know the full schema and therefore we cannot be strict on the options.
// Possibly in the future update the logic to use the following syntax:
// `ng add @angular/localize -- --package-options`.
.strict(false);
const collectionName = this.getCollectionName();
if (!collectionName) {
return localYargs;
}
const workflow = this.getOrCreateWorkflowForBuilder(collectionName);
try {
const collection = workflow.engine.createCollection(collectionName);
const options = await this.getSchematicOptions(collection, this.schematicName, workflow);
return this.addSchemaOptionsToCommand(localYargs, options);
}
catch (error) {
// During `ng add` prior to the downloading of the package
// we are not able to resolve and create a collection.
// Or when the collection value is a path to a tarball.
}
return localYargs;
}
async run(options) {
this.#projectVersionCache.clear();
const { logger } = this.context;
const { collection, skipConfirmation } = options;
let packageIdentifier;
try {
packageIdentifier = (0, npm_package_arg_1.default)(collection);
}
catch (e) {
(0, error_1.assertIsError)(e);
logger.error(e.message);
return 1;
}
if (packageIdentifier.name &&
packageIdentifier.registry &&
this.isPackageInstalled(packageIdentifier.name)) {
const validVersion = await this.isProjectVersionValid(packageIdentifier);
if (validVersion) {
// Already installed so just run schematic
logger.info('Skipping installation: Package already installed');
return this.executeSchematic({ ...options, collection: packageIdentifier.name });
}
}
const taskContext = {
packageIdentifier,
executeSchematic: this.executeSchematic.bind(this),
getPeerDependencyConflicts: this.getPeerDependencyConflicts.bind(this),
dryRun: options.dryRun,
};
const tasks = new listr2_1.Listr([
{
title: 'Determining Package Manager',
task: (_context, task) => (task.output = `Using package manager: ${listr2_1.color.dim(this.context.packageManager.name)}`),
rendererOptions: { persistentOutput: true },
},
{
title: 'Searching for compatible package version',
enabled: packageIdentifier.type === 'range' && packageIdentifier.rawSpec === '*',
task: (context, task) => this.findCompatiblePackageVersionTask(context, task, options),
rendererOptions: { persistentOutput: true },
},
{
title: 'Loading package information',
task: (context, task) => this.loadPackageInfoTask(context, task, options),
rendererOptions: { persistentOutput: true },
},
{
title: 'Confirming installation',
enabled: !skipConfirmation && !options.dryRun,
task: (context, task) => this.confirmInstallationTask(context, task),
rendererOptions: { persistentOutput: true },
},
{
title: 'Installing package',
skip: (context) => {
if (context.dryRun) {
return `Skipping package installation. Would install package ${listr2_1.color.blue(context.packageIdentifier.toString())}.`;
}
return false;
},
task: (context, task) => this.installPackageTask(context, task, options),
rendererOptions: { bottomBar: Infinity },
},
// TODO: Rework schematic execution as a task and insert here
], {
/* options */
});
try {
const result = await tasks.run(taskContext);
(0, node_assert_1.default)(result.collectionName, 'Collection name should always be available');
// Check if the installed package has actual add actions and not just schematic support
if (result.hasSchematics && !options.dryRun) {
const workflow = this.getOrCreateWorkflowForBuilder(result.collectionName);
const collection = workflow.engine.createCollection(result.collectionName);
// listSchematicNames cannot be used here since it does not list private schematics.
// Most `ng-add` schematics are marked as private.
// TODO: Consider adding a `hasSchematic` helper to the schematic collection object.
try {
collection.createSchematic(this.schematicName, true);
}
catch {
result.hasSchematics = false;
}
}
if (!result.hasSchematics) {
// Fallback to a built-in schematic if the package does not have an `ng-add` schematic
const packageName = result.packageIdentifier.name;
if (packageName) {
const builtInSchematic = BUILT_IN_SCHEMATICS[packageName];
if (builtInSchematic) {
logger.info(`The ${listr2_1.color.blue(packageName)} package does not provide \`ng add\` actions.`);
logger.info('The Angular CLI will use built-in actions to add it to your project.');
return this.executeSchematic({
...options,
collection: builtInSchematic.collection,
schematicName: builtInSchematic.name,
package: packageName,
});
}
}
let message = options.dryRun
? 'The package does not provide any `ng add` actions, so no further actions would be taken.'
: 'Package installed successfully. The package does not provide any `ng add` actions, so no further actions were taken.';
if (result.homepage) {
message += `\nFor more information about this package, visit its homepage at ${result.homepage}`;
}
logger.info(message);
return;
}
if (options.dryRun) {
logger.info("The package's `ng add` actions would be executed next.");
return;
}
return this.executeSchematic({ ...options, collection: result.collectionName });
}
catch (e) {
if (e instanceof CommandError) {
logger.error(e.message);
return 1;
}
throw e;
}
}
async findCompatiblePackageVersionTask(context, task, options) {
const { registry, verbose } = options;
const { packageIdentifier } = context;
const { packageManager } = this.context;
const packageName = packageIdentifier.name;
(0, node_assert_1.default)(packageName, 'Registry package identifiers should always have a name.');
const rejectionReasons = [];
// Attempt to use the 'latest' tag from the registry.
try {
const latestManifest = await packageManager.getManifest(`${packageName}@latest`, {
registry,
});
if (latestManifest) {
const conflicts = await this.getPeerDependencyConflicts(latestManifest);
if (!conflicts) {
context.packageIdentifier = npm_package_arg_1.default.resolve(latestManifest.name, latestManifest.version);
task.output = `Found compatible package version: ${listr2_1.color.blue(latestManifest.version)}.`;
return;
}
rejectionReasons.push(...conflicts);
}
}
catch (e) {
(0, error_1.assertIsError)(e);
throw new CommandError(`Unable to load package information from registry: ${e.message}`);
}
// 'latest' is invalid or not found, search for most recent matching package.
task.output =
'Could not find a compatible version with `latest`. Searching for a compatible version.';
let packageMetadata;
try {
packageMetadata = await packageManager.getRegistryMetadata(packageName, {
registry,
});
}
catch (e) {
(0, error_1.assertIsError)(e);
throw new CommandError(`Unable to load package information from registry: ${e.message}`);
}
if (!packageMetadata) {
throw new CommandError('Unable to load package information from registry.');
}
// Allow prelease versions if the CLI itself is a prerelease or locally built.
const allowPrereleases = !!(0, semver_1.prerelease)(version_1.VERSION.full) || version_1.VERSION.full === '0.0.0';
const potentialVersions = this.#getPotentialVersions(packageMetadata, allowPrereleases);
// Heuristic-based search: Check the latest release of each major version first.
const majorVersions = this.#getMajorVersions(potentialVersions);
let found = await this.#findCompatibleVersion(context, majorVersions, {
registry,
verbose,
rejectionReasons,
});
// Exhaustive search: If no compatible major version is found, fall back to checking all versions.
if (!found) {
const checkedVersions = new Set(majorVersions);
const remainingVersions = potentialVersions.filter((v) => !checkedVersions.has(v));
found = await this.#findCompatibleVersion(context, remainingVersions, {
registry,
verbose,
rejectionReasons,
});
}
if (!found) {
let message = `Unable to find compatible package.`;
if (rejectionReasons.length > 0) {
message +=
'\nThis is often because of incompatible peer dependencies.\n' +
'These versions were rejected due to the following conflicts:\n' +
rejectionReasons
.slice(0, verbose ? undefined : DEFAULT_CONFLICT_DISPLAY_LIMIT)
.map((r) => ` - ${r}`)
.join('\n');
}
task.output = message;
}
else {
task.output = `Found compatible package version: ${listr2_1.color.blue(context.packageIdentifier.toString())}.`;
}
}
async #findCompatibleVersion(context, versions, options) {
const { packageIdentifier } = context;
const { packageManager } = this.context;
const { registry, verbose, rejectionReasons } = options;
const packageName = packageIdentifier.name;
(0, node_assert_1.default)(packageName, 'Package name must be defined.');
for (const version of versions) {
const manifest = await packageManager.getManifest(`${packageName}@${version}`, {
registry,
});
if (!manifest) {
continue;
}
const conflicts = await this.getPeerDependencyConflicts(manifest);
if (conflicts) {
if (verbose || rejectionReasons.length < DEFAULT_CONFLICT_DISPLAY_LIMIT) {
rejectionReasons.push(...conflicts);
}
continue;
}
context.packageIdentifier = npm_package_arg_1.default.resolve(manifest.name, manifest.version);
return manifest;
}
return null;
}
#getPotentialVersions(packageMetadata, allowPrereleases) {
const versionExclusions = packageVersionExclusions[packageMetadata.name];
const latestVersion = packageMetadata['dist-tags']['latest'];
const versions = Object.values(packageMetadata.versions).filter((version) => {
// Latest tag has already been checked
if (latestVersion && version === latestVersion) {
return false;
}
// Prerelease versions are not stable and should not be considered by default
if (!allowPrereleases && (0, semver_1.prerelease)(version)) {
return false;
}
// Excluded package versions should not be considered
if (versionExclusions && (0, semver_1.satisfies)(version, versionExclusions, { includePrerelease: true })) {
return false;
}
return true;
});
// Sort in reverse SemVer order so that the newest compatible version is chosen
return versions.sort((a, b) => (0, semver_1.compare)(b, a, true));
}
#getMajorVersions(versions) {
const majorVersions = new Map();
for (const version of versions) {
const major = semver_1.default.major(version);
const existing = majorVersions.get(major);
if (!existing || semver_1.default.gt(version, existing)) {
majorVersions.set(major, version);
}
}
return [...majorVersions.values()].sort((a, b) => (0, semver_1.compare)(b, a, true));
}
async loadPackageInfoTask(context, task, options) {
const { registry } = options;
let manifest;
try {
manifest = await this.context.packageManager.getManifest(context.packageIdentifier.toString(), {
registry,
});
}
catch (e) {
(0, error_1.assertIsError)(e);
throw new CommandError(`Unable to fetch package information for '${context.packageIdentifier}': ${e.message}`);
}
if (!manifest) {
throw new CommandError(`Unable to fetch package information for '${context.packageIdentifier}'.`);
}
context.hasSchematics = !!manifest.schematics;
context.savePackage = manifest['ng-add']?.save;
context.collectionName = manifest.name;
context.homepage = manifest.homepage;
if (await this.getPeerDependencyConflicts(manifest)) {
task.output = listr2_1.color.yellow(listr2_1.figures.warning +
' Package has unmet peer dependencies. Adding the package may not succeed.');
}
}
async confirmInstallationTask(context, task) {
if (!(0, tty_1.isTTY)()) {
task.output =
`'--skip-confirmation' can be used to bypass installation confirmation. ` +
`Ensure package name is correct prior to '--skip-confirmation' option usage.`;
throw new CommandError('No terminal detected');
}
const { ListrInquirerPromptAdapter } = await Promise.resolve().then(() => __importStar(require('@listr2/prompt-adapter-inquirer')));
const { confirm } = await Promise.resolve().then(() => __importStar(require('@inquirer/prompts')));
const shouldProceed = await task.prompt(ListrInquirerPromptAdapter).run(confirm, {
message: `The package ${listr2_1.color.blue(context.packageIdentifier.toString())} will be installed and executed.\n` +
'Would you like to proceed?',
default: true,
theme: { prefix: '' },
});
if (!shouldProceed) {
throw new CommandError('Command aborted');
}
}
async installPackageTask(context, task, options) {
const { registry } = options;
const { packageIdentifier, savePackage } = context;
const { packageManager } = this.context;
// Only show if installation will actually occur
task.title = 'Installing package';
try {
if (context.savePackage === false) {
task.title += ' in temporary location';
// Temporary packages are located in a different directory
// Hence we need to resolve them using the temp path
const { workingDirectory } = await packageManager.acquireTempPackage(packageIdentifier.toString(), {
registry,
});
const tempRequire = (0, node_module_1.createRequire)(workingDirectory + '/');
(0, node_assert_1.default)(context.collectionName, 'Collection name should always be available');
const resolvedCollectionPath = tempRequire.resolve((0, node_path_1.join)(context.collectionName, 'package.json'));
context.collectionName = (0, node_path_1.dirname)(resolvedCollectionPath);
}
else {
await packageManager.add(packageIdentifier.toString(), 'none', savePackage === 'devDependencies', false, true, {
registry,
});
}
}
catch (e) {
if (e instanceof package_managers_1.PackageManagerError) {
const output = e.stderr || e.stdout;
if (output) {
throw new CommandError(`Package installation failed: ${e.message}\nOutput: ${output}`);
}
}
throw e;
}
}
async isProjectVersionValid(packageIdentifier) {
if (!packageIdentifier.name) {
return false;
}
const installedVersion = await this.findProjectVersion(packageIdentifier.name);
if (!installedVersion) {
return false;
}
if (packageIdentifier.rawSpec === '*') {
return true;
}
if (packageIdentifier.type === 'range' &&
packageIdentifier.fetchSpec &&
packageIdentifier.fetchSpec !== '*') {
return (0, semver_1.satisfies)(installedVersion, packageIdentifier.fetchSpec);
}
if (packageIdentifier.type === 'version') {
const v1 = (0, semver_1.valid)(packageIdentifier.fetchSpec);
const v2 = (0, semver_1.valid)(installedVersion);
return v1 !== null && v1 === v2;
}
return false;
}
getCollectionName() {
const [, collectionName] = this.context.args.positional;
if (!collectionName) {
return undefined;
}
// The CLI argument may specify also a version, like `ng add @my/lib@13.0.0`,
// but here we need only the name of the package, like `@my/lib`.
try {
const packageName = (0, npm_package_arg_1.default)(collectionName).name;
if (packageName) {
return packageName;
}
}
catch (e) {
(0, error_1.assertIsError)(e);
this.context.logger.error(e.message);
}
return collectionName;
}
isPackageInstalled(name) {
try {
this.rootRequire.resolve((0, node_path_1.join)(name, 'package.json'));
return true;
}
catch (e) {
(0, error_1.assertIsError)(e);
if (e.code !== 'MODULE_NOT_FOUND') {
throw e;
}
}
return false;
}
executeSchematic(options) {
const { verbose, skipConfirmation, interactive, force, dryRun, registry, defaults, collection: collectionName, schematicName, ...schematicOptions } = options;
return this.runSchematic({
schematicOptions,
schematicName: schematicName ?? this.schematicName,
collectionName,
executionOptions: {
interactive,
force,
dryRun,
defaults,
packageRegistry: registry,
},
});
}
async findProjectVersion(name) {
const cachedVersion = this.#projectVersionCache.get(name);
if (cachedVersion !== undefined) {
return cachedVersion;
}
const { root } = this.context;
let installedPackagePath;
try {
installedPackagePath = this.rootRequire.resolve((0, node_path_1.join)(name, 'package.json'));
}
catch { }
if (installedPackagePath) {
try {
const installedPackage = JSON.parse(await promises_1.default.readFile(installedPackagePath, 'utf-8'));
this.#projectVersionCache.set(name, installedPackage.version);
return installedPackage.version;
}
catch { }
}
let projectManifest;
try {
projectManifest = JSON.parse(await promises_1.default.readFile((0, node_path_1.join)(root, 'package.json'), 'utf-8'));
}
catch { }
if (projectManifest) {
const version = projectManifest.dependencies?.[name] || projectManifest.devDependencies?.[name];
if (version) {
this.#projectVersionCache.set(name, version);
return version;
}
}
this.#projectVersionCache.set(name, null);
return null;
}
async getPeerDependencyConflicts(manifest) {
if (!manifest.peerDependencies) {
return false;
}
const checks = Object.entries(manifest.peerDependencies).map(async ([peer, range]) => {
let peerIdentifier;
try {
peerIdentifier = npm_package_arg_1.default.resolve(peer, range);
}
catch {
this.context.logger.warn(`Invalid peer dependency ${peer} found in package.`);
return null;
}
if (peerIdentifier.type !== 'version' && peerIdentifier.type !== 'range') {
// type === 'tag' | 'file' | 'directory' | 'remote' | 'git'
// Cannot accurately compare these as the tag/location may have changed since install.
return null;
}
try {
const version = await this.findProjectVersion(peer);
if (!version) {
return null;
}
const options = { includePrerelease: true };
if (!(0, semver_1.intersects)(version, peerIdentifier.rawSpec, options) &&
!(0, semver_1.satisfies)(version, peerIdentifier.rawSpec, options)) {
return (`Package "${manifest.name}@${manifest.version}" has an incompatible peer dependency to "` +
`${peer}@${peerIdentifier.rawSpec}" (requires "${version}" in project).`);
}
}
catch {
// Not found or invalid so ignore
}
return null;
});
const conflicts = (await Promise.all(checks)).filter((result) => !!result);
return conflicts.length > 0 && conflicts;
}
}
exports.default = AddCommandModule;
//# sourceMappingURL=cli.js.map
File diff suppressed because one or more lines are too long
+7
View File
@@ -0,0 +1,7 @@
Adds the npm package for a published library to your workspace, and configures
the project in the current working directory to use that library, as specified by the library's schematic.
For example, adding `@angular/pwa` configures your project for PWA support:
```bash
ng add @angular/pwa
```
+16
View File
@@ -0,0 +1,16 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { Argv } from 'yargs';
import { CommandModule, CommandModuleImplementation, Options } from '../../command-builder/command-module';
export default class AnalyticsCommandModule extends CommandModule implements CommandModuleImplementation {
command: string;
describe: string;
longDescriptionPath: string;
builder(localYargs: Argv): Argv;
run(_options: Options<{}>): void;
}
+34
View File
@@ -0,0 +1,34 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
Object.defineProperty(exports, "__esModule", { value: true });
const node_path_1 = require("node:path");
const command_module_1 = require("../../command-builder/command-module");
const command_1 = require("../../command-builder/utilities/command");
const cli_1 = require("./info/cli");
const cli_2 = require("./settings/cli");
class AnalyticsCommandModule extends command_module_1.CommandModule {
command = 'analytics';
describe = 'Configures the gathering of Angular CLI usage metrics.';
longDescriptionPath = (0, node_path_1.join)(__dirname, 'long-description.md');
builder(localYargs) {
const subcommands = [
cli_1.AnalyticsInfoCommandModule,
cli_2.AnalyticsDisableModule,
cli_2.AnalyticsEnableModule,
cli_2.AnalyticsPromptModule,
].sort(); // sort by class name.
for (const module of subcommands) {
(0, command_1.addCommandModuleToYargs)(module, this.context);
}
return localYargs.demandCommand(1, command_1.demandCommandFailureMessage).strict();
}
run(_options) { }
}
exports.default = AnalyticsCommandModule;
//# sourceMappingURL=cli.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"cli.js","sourceRoot":"","sources":["cli.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAEH,yCAAiC;AAEjC,yEAI8C;AAC9C,qEAGiD;AACjD,oCAAwD;AACxD,wCAIwB;AAExB,MAAqB,sBACnB,SAAQ,8BAAa;IAGrB,OAAO,GAAG,WAAW,CAAC;IACtB,QAAQ,GAAG,wDAAwD,CAAC;IACpE,mBAAmB,GAAG,IAAA,gBAAI,EAAC,SAAS,EAAE,qBAAqB,CAAC,CAAC;IAE7D,OAAO,CAAC,UAAgB;QACtB,MAAM,WAAW,GAAG;YAClB,gCAA0B;YAC1B,4BAAsB;YACtB,2BAAqB;YACrB,2BAAqB;SACtB,CAAC,IAAI,EAAE,CAAC,CAAC,sBAAsB;QAEhC,KAAK,MAAM,MAAM,IAAI,WAAW,EAAE,CAAC;YACjC,IAAA,iCAAuB,EAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAChD,CAAC;QAED,OAAO,UAAU,CAAC,aAAa,CAAC,CAAC,EAAE,qCAA2B,CAAC,CAAC,MAAM,EAAE,CAAC;IAC3E,CAAC;IAED,GAAG,CAAC,QAAqB,IAAS,CAAC;CACpC;AAxBD,yCAwBC"}
+16
View File
@@ -0,0 +1,16 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { Argv } from 'yargs';
import { CommandModule, CommandModuleImplementation, Options } from '../../../command-builder/command-module';
export declare class AnalyticsInfoCommandModule extends CommandModule implements CommandModuleImplementation {
command: string;
describe: string;
longDescriptionPath?: string;
builder(localYargs: Argv): Argv;
run(_options: Options<{}>): Promise<void>;
}
+25
View File
@@ -0,0 +1,25 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.AnalyticsInfoCommandModule = void 0;
const analytics_1 = require("../../../analytics/analytics");
const command_module_1 = require("../../../command-builder/command-module");
class AnalyticsInfoCommandModule extends command_module_1.CommandModule {
command = 'info';
describe = 'Prints analytics gathering and reporting configuration in the console.';
longDescriptionPath;
builder(localYargs) {
return localYargs.strict();
}
async run(_options) {
this.context.logger.info(await (0, analytics_1.getAnalyticsInfoString)(this.context));
}
}
exports.AnalyticsInfoCommandModule = AnalyticsInfoCommandModule;
//# sourceMappingURL=cli.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"cli.js","sourceRoot":"","sources":["cli.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAGH,4DAAsE;AACtE,4EAIiD;AAEjD,MAAa,0BACX,SAAQ,8BAAa;IAGrB,OAAO,GAAG,MAAM,CAAC;IACjB,QAAQ,GAAG,wEAAwE,CAAC;IACpF,mBAAmB,CAAU;IAE7B,OAAO,CAAC,UAAgB;QACtB,OAAO,UAAU,CAAC,MAAM,EAAE,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,QAAqB;QAC7B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,IAAA,kCAAsB,EAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IACvE,CAAC;CACF;AAfD,gEAeC"}
+20
View File
@@ -0,0 +1,20 @@
You can help the Angular Team to prioritize features and improvements by permitting the Angular team to send command-line command usage statistics to Google.
The Angular Team does not collect usage statistics unless you explicitly opt in. When installing the Angular CLI you are prompted to allow global collection of usage statistics.
If you say no or skip the prompt, no data is collected.
### What is collected?
Usage analytics include the commands and selected flags for each execution.
Usage analytics may include the following information:
- Your operating system \(macOS, Linux distribution, Windows\) and its version.
- Package manager name and version \(local version only\).
- Node.js version \(local version only\).
- Angular CLI version \(local version only\).
- Command name that was run.
- Workspace information, the number of application and library projects.
- For schematics commands \(add, generate and new\), the schematic collection and name and a list of selected flags.
- For build commands \(build, serve\), the builder name, the number and size of bundles \(initial and lazy\), compilation units, the time it took to build and rebuild, and basic Angular-specific API usage.
Only Angular owned and developed schematics and builders are reported.
Third-party schematics and builders do not send data to the Angular Team.
+35
View File
@@ -0,0 +1,35 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { Argv } from 'yargs';
import { CommandModule, CommandModuleImplementation, Options } from '../../../command-builder/command-module';
interface AnalyticsCommandArgs {
global: boolean;
}
declare abstract class AnalyticsSettingModule extends CommandModule<AnalyticsCommandArgs> implements CommandModuleImplementation<AnalyticsCommandArgs> {
longDescriptionPath?: string;
builder(localYargs: Argv): Argv<AnalyticsCommandArgs>;
abstract run({ global }: Options<AnalyticsCommandArgs>): Promise<void>;
}
export declare class AnalyticsDisableModule extends AnalyticsSettingModule implements CommandModuleImplementation<AnalyticsCommandArgs> {
command: string;
aliases: string;
describe: string;
run({ global }: Options<AnalyticsCommandArgs>): Promise<void>;
}
export declare class AnalyticsEnableModule extends AnalyticsSettingModule implements CommandModuleImplementation<AnalyticsCommandArgs> {
command: string;
aliases: string;
describe: string;
run({ global }: Options<AnalyticsCommandArgs>): Promise<void>;
}
export declare class AnalyticsPromptModule extends AnalyticsSettingModule implements CommandModuleImplementation<AnalyticsCommandArgs> {
command: string;
describe: string;
run({ global }: Options<AnalyticsCommandArgs>): Promise<void>;
}
export {};
+54
View File
@@ -0,0 +1,54 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.AnalyticsPromptModule = exports.AnalyticsEnableModule = exports.AnalyticsDisableModule = void 0;
const analytics_1 = require("../../../analytics/analytics");
const command_module_1 = require("../../../command-builder/command-module");
class AnalyticsSettingModule extends command_module_1.CommandModule {
longDescriptionPath;
builder(localYargs) {
return localYargs
.option('global', {
description: `Configure analytics gathering and reporting globally in the caller's home directory.`,
alias: ['g'],
type: 'boolean',
default: false,
})
.strict();
}
}
class AnalyticsDisableModule extends AnalyticsSettingModule {
command = 'disable';
aliases = 'off';
describe = 'Disables analytics gathering and reporting for the user.';
async run({ global }) {
await (0, analytics_1.setAnalyticsConfig)(global, false);
process.stderr.write(await (0, analytics_1.getAnalyticsInfoString)(this.context));
}
}
exports.AnalyticsDisableModule = AnalyticsDisableModule;
class AnalyticsEnableModule extends AnalyticsSettingModule {
command = 'enable';
aliases = 'on';
describe = 'Enables analytics gathering and reporting for the user.';
async run({ global }) {
await (0, analytics_1.setAnalyticsConfig)(global, true);
process.stderr.write(await (0, analytics_1.getAnalyticsInfoString)(this.context));
}
}
exports.AnalyticsEnableModule = AnalyticsEnableModule;
class AnalyticsPromptModule extends AnalyticsSettingModule {
command = 'prompt';
describe = 'Prompts the user to set the analytics gathering status interactively.';
async run({ global }) {
await (0, analytics_1.promptAnalytics)(this.context, global, true);
}
}
exports.AnalyticsPromptModule = AnalyticsPromptModule;
//# sourceMappingURL=cli.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"cli.js","sourceRoot":"","sources":["cli.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAGH,4DAIsC;AACtC,4EAIiD;AAMjD,MAAe,sBACb,SAAQ,8BAAmC;IAG3C,mBAAmB,CAAU;IAE7B,OAAO,CAAC,UAAgB;QACtB,OAAO,UAAU;aACd,MAAM,CAAC,QAAQ,EAAE;YAChB,WAAW,EAAE,sFAAsF;YACnG,KAAK,EAAE,CAAC,GAAG,CAAC;YACZ,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,KAAK;SACf,CAAC;aACD,MAAM,EAAE,CAAC;IACd,CAAC;CAGF;AAED,MAAa,sBACX,SAAQ,sBAAsB;IAG9B,OAAO,GAAG,SAAS,CAAC;IACpB,OAAO,GAAG,KAAK,CAAC;IAChB,QAAQ,GAAG,0DAA0D,CAAC;IAEtE,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,EAAiC;QACjD,MAAM,IAAA,8BAAkB,EAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACxC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,IAAA,kCAAsB,EAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IACnE,CAAC;CACF;AAZD,wDAYC;AAED,MAAa,qBACX,SAAQ,sBAAsB;IAG9B,OAAO,GAAG,QAAQ,CAAC;IACnB,OAAO,GAAG,IAAI,CAAC;IACf,QAAQ,GAAG,yDAAyD,CAAC;IACrE,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,EAAiC;QACjD,MAAM,IAAA,8BAAkB,EAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACvC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,IAAA,kCAAsB,EAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IACnE,CAAC;CACF;AAXD,sDAWC;AAED,MAAa,qBACX,SAAQ,sBAAsB;IAG9B,OAAO,GAAG,QAAQ,CAAC;IACnB,QAAQ,GAAG,uEAAuE,CAAC;IAEnF,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,EAAiC;QACjD,MAAM,IAAA,2BAAe,EAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IACpD,CAAC;CACF;AAVD,sDAUC"}
+16
View File
@@ -0,0 +1,16 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { ArchitectCommandModule } from '../../command-builder/architect-command-module';
import { CommandModuleImplementation } from '../../command-builder/command-module';
export default class BuildCommandModule extends ArchitectCommandModule implements CommandModuleImplementation {
multiTarget: boolean;
command: string;
aliases: string[] | undefined;
describe: string;
longDescriptionPath: string;
}
+21
View File
@@ -0,0 +1,21 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
Object.defineProperty(exports, "__esModule", { value: true });
const node_path_1 = require("node:path");
const architect_command_module_1 = require("../../command-builder/architect-command-module");
const command_config_1 = require("../command-config");
class BuildCommandModule extends architect_command_module_1.ArchitectCommandModule {
multiTarget = false;
command = 'build [project]';
aliases = command_config_1.RootCommands['build'].aliases;
describe = 'Compiles an Angular application or library into an output directory named dist/ at the given output path.';
longDescriptionPath = (0, node_path_1.join)(__dirname, 'long-description.md');
}
exports.default = BuildCommandModule;
//# sourceMappingURL=cli.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"cli.js","sourceRoot":"","sources":["cli.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAEH,yCAAiC;AACjC,6FAAwF;AAExF,sDAAiD;AAEjD,MAAqB,kBACnB,SAAQ,iDAAsB;IAG9B,WAAW,GAAG,KAAK,CAAC;IACpB,OAAO,GAAG,iBAAiB,CAAC;IAC5B,OAAO,GAAG,6BAAY,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC;IACxC,QAAQ,GACN,2GAA2G,CAAC;IAC9G,mBAAmB,GAAG,IAAA,gBAAI,EAAC,SAAS,EAAE,qBAAqB,CAAC,CAAC;CAC9D;AAVD,qCAUC"}
+18
View File
@@ -0,0 +1,18 @@
The command can be used to build a project of type "application" or "library".
When used to build a library, a different builder is invoked, and only the `ts-config`, `configuration`, `poll` and `watch` options are applied.
All other options apply only to building applications.
The application builder uses the [esbuild](https://esbuild.github.io/) build tool, with default configuration options specified in the workspace configuration file (`angular.json`) or with a named alternative configuration.
A "development" configuration is created by default when you use the CLI to create the project, and you can use that configuration by specifying the `--configuration development`.
The configuration options generally correspond to the command options.
You can override individual configuration defaults by specifying the corresponding options on the command line.
The command can accept option names given in dash-case.
Note that in the configuration file, you must specify names in camelCase.
Some additional options can only be set through the configuration file,
either by direct editing or with the `ng config` command.
These include `assets`, `styles`, and `scripts` objects that provide runtime-global resources to include in the project.
Resources in CSS, such as images and fonts, are automatically written and fingerprinted at the root of the output folder.
For further details, see [Workspace Configuration](reference/configs/workspace-config).
+17
View File
@@ -0,0 +1,17 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { Argv } from 'yargs';
import { CommandModule, CommandModuleImplementation, CommandScope } from '../../../command-builder/command-module';
export declare class CacheCleanModule extends CommandModule implements CommandModuleImplementation {
command: string;
describe: string;
longDescriptionPath: string | undefined;
scope: CommandScope;
builder(localYargs: Argv): Argv;
run(): Promise<void>;
}
+32
View File
@@ -0,0 +1,32 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.CacheCleanModule = void 0;
const promises_1 = require("node:fs/promises");
const command_module_1 = require("../../../command-builder/command-module");
const utilities_1 = require("../utilities");
class CacheCleanModule extends command_module_1.CommandModule {
command = 'clean';
describe = 'Deletes persistent disk cache from disk.';
longDescriptionPath;
scope = command_module_1.CommandScope.In;
builder(localYargs) {
return localYargs.strict();
}
run() {
const { path } = (0, utilities_1.getCacheConfig)(this.context.workspace);
return (0, promises_1.rm)(path, {
force: true,
recursive: true,
maxRetries: 3,
});
}
}
exports.CacheCleanModule = CacheCleanModule;
//# sourceMappingURL=cli.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"cli.js","sourceRoot":"","sources":["cli.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAEH,+CAAsC;AAEtC,4EAIiD;AACjD,4CAA8C;AAE9C,MAAa,gBAAiB,SAAQ,8BAAa;IACjD,OAAO,GAAG,OAAO,CAAC;IAClB,QAAQ,GAAG,0CAA0C,CAAC;IACtD,mBAAmB,CAAqB;IAC/B,KAAK,GAAG,6BAAY,CAAC,EAAE,CAAC;IAEjC,OAAO,CAAC,UAAgB;QACtB,OAAO,UAAU,CAAC,MAAM,EAAE,CAAC;IAC7B,CAAC;IAED,GAAG;QACD,MAAM,EAAE,IAAI,EAAE,GAAG,IAAA,0BAAc,EAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAExD,OAAO,IAAA,aAAE,EAAC,IAAI,EAAE;YACd,KAAK,EAAE,IAAI;YACX,SAAS,EAAE,IAAI;YACf,UAAU,EAAE,CAAC;SACd,CAAC,CAAC;IACL,CAAC;CACF;AAnBD,4CAmBC"}
+17
View File
@@ -0,0 +1,17 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { Argv } from 'yargs';
import { CommandModule, CommandModuleImplementation, CommandScope, Options } from '../../command-builder/command-module';
export default class CacheCommandModule extends CommandModule implements CommandModuleImplementation {
command: string;
describe: string;
longDescriptionPath: string;
scope: CommandScope;
builder(localYargs: Argv): Argv;
run(_options: Options<{}>): void;
}
+36
View File
@@ -0,0 +1,36 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
Object.defineProperty(exports, "__esModule", { value: true });
const node_path_1 = require("node:path");
const command_module_1 = require("../../command-builder/command-module");
const command_1 = require("../../command-builder/utilities/command");
const cli_1 = require("./clean/cli");
const cli_2 = require("./info/cli");
const cli_3 = require("./settings/cli");
class CacheCommandModule extends command_module_1.CommandModule {
command = 'cache';
describe = 'Configure persistent disk cache and retrieve cache statistics.';
longDescriptionPath = (0, node_path_1.join)(__dirname, 'long-description.md');
scope = command_module_1.CommandScope.In;
builder(localYargs) {
const subcommands = [
cli_3.CacheEnableModule,
cli_3.CacheDisableModule,
cli_1.CacheCleanModule,
cli_2.CacheInfoCommandModule,
].sort();
for (const module of subcommands) {
(0, command_1.addCommandModuleToYargs)(module, this.context);
}
return localYargs.demandCommand(1, command_1.demandCommandFailureMessage).strict();
}
run(_options) { }
}
exports.default = CacheCommandModule;
//# sourceMappingURL=cli.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"cli.js","sourceRoot":"","sources":["cli.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAEH,yCAAiC;AAEjC,yEAK8C;AAC9C,qEAGiD;AACjD,qCAA+C;AAC/C,oCAAoD;AACpD,wCAAuE;AAEvE,MAAqB,kBACnB,SAAQ,8BAAa;IAGrB,OAAO,GAAG,OAAO,CAAC;IAClB,QAAQ,GAAG,gEAAgE,CAAC;IAC5E,mBAAmB,GAAG,IAAA,gBAAI,EAAC,SAAS,EAAE,qBAAqB,CAAC,CAAC;IACpD,KAAK,GAAG,6BAAY,CAAC,EAAE,CAAC;IAEjC,OAAO,CAAC,UAAgB;QACtB,MAAM,WAAW,GAAG;YAClB,uBAAiB;YACjB,wBAAkB;YAClB,sBAAgB;YAChB,4BAAsB;SACvB,CAAC,IAAI,EAAE,CAAC;QAET,KAAK,MAAM,MAAM,IAAI,WAAW,EAAE,CAAC;YACjC,IAAA,iCAAuB,EAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAChD,CAAC;QAED,OAAO,UAAU,CAAC,aAAa,CAAC,CAAC,EAAE,qCAA2B,CAAC,CAAC,MAAM,EAAE,CAAC;IAC3E,CAAC;IAED,GAAG,CAAC,QAAqB,IAAS,CAAC;CACpC;AAzBD,qCAyBC"}
+20
View File
@@ -0,0 +1,20 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { Argv } from 'yargs';
import { CommandModule, CommandModuleImplementation, CommandScope } from '../../../command-builder/command-module';
export declare class CacheInfoCommandModule extends CommandModule implements CommandModuleImplementation {
command: string;
describe: string;
longDescriptionPath?: string | undefined;
scope: CommandScope;
builder(localYargs: Argv): Argv;
run(): Promise<void>;
private getSizeOfDirectory;
private formatSize;
private effectiveEnabledStatus;
}
+139
View File
@@ -0,0 +1,139 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.CacheInfoCommandModule = void 0;
const fs = __importStar(require("node:fs/promises"));
const node_path_1 = require("node:path");
const command_module_1 = require("../../../command-builder/command-module");
const color_1 = require("../../../utilities/color");
const environment_options_1 = require("../../../utilities/environment-options");
const utilities_1 = require("../utilities");
class CacheInfoCommandModule extends command_module_1.CommandModule {
command = 'info';
describe = 'Prints persistent disk cache configuration and statistics in the console.';
longDescriptionPath;
scope = command_module_1.CommandScope.In;
builder(localYargs) {
return localYargs.strict();
}
async run() {
const cacheConfig = (0, utilities_1.getCacheConfig)(this.context.workspace);
const { path, environment, enabled } = cacheConfig;
const effectiveStatus = this.effectiveEnabledStatus(cacheConfig);
const sizeOnDisk = await this.getSizeOfDirectory(path);
const info = [
{
label: 'Enabled',
value: enabled ? color_1.colors.green('Yes') : color_1.colors.red('No'),
},
{
label: 'Environment',
value: color_1.colors.cyan(environment),
},
{
label: 'Path',
value: color_1.colors.cyan(path),
},
{
label: 'Size on disk',
value: color_1.colors.cyan(sizeOnDisk),
},
{
label: 'Effective Status',
value: (effectiveStatus ? color_1.colors.green('Enabled') : color_1.colors.red('Disabled')) +
' (current machine)',
},
];
const maxLabelLength = Math.max(...info.map((l) => l.label.length));
const output = info
.map(({ label, value }) => color_1.colors.bold(label.padEnd(maxLabelLength + 2)) + `: ${value}`)
.join('\n');
this.context.logger.info(`\n${color_1.colors.bold('Cache Information')}\n\n${output}\n`);
}
async getSizeOfDirectory(path) {
const directoriesStack = [path];
let size = 0;
while (directoriesStack.length) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const dirPath = directoriesStack.pop();
let entries = [];
try {
entries = await fs.readdir(dirPath);
}
catch { }
for (const entry of entries) {
const entryPath = (0, node_path_1.join)(dirPath, entry);
const stats = await fs.stat(entryPath);
if (stats.isDirectory()) {
directoriesStack.push(entryPath);
}
size += stats.size;
}
}
return this.formatSize(size);
}
formatSize(size) {
if (size <= 0) {
return '0 bytes';
}
const abbreviations = ['bytes', 'kB', 'MB', 'GB'];
const index = Math.floor(Math.log(size) / Math.log(1024));
const roundedSize = size / Math.pow(1024, index);
// bytes don't have a fraction
const fractionDigits = index === 0 ? 0 : 2;
return `${roundedSize.toFixed(fractionDigits)} ${abbreviations[index]}`;
}
effectiveEnabledStatus(cacheConfig) {
const { enabled, environment } = cacheConfig;
if (enabled) {
switch (environment) {
case 'ci':
return environment_options_1.isCI;
case 'local':
return !environment_options_1.isCI;
}
}
return enabled;
}
}
exports.CacheInfoCommandModule = CacheInfoCommandModule;
//# sourceMappingURL=cli.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"cli.js","sourceRoot":"","sources":["cli.ts"],"names":[],"mappings":"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"}
+53
View File
@@ -0,0 +1,53 @@
Angular CLI saves a number of cachable operations on disk by default.
When you re-run the same build, the build system restores the state of the previous build and re-uses previously performed operations, which decreases the time taken to build and test your applications and libraries.
To amend the default cache settings, add the `cli.cache` object to your [Workspace Configuration](reference/configs/workspace-config).
The object goes under `cli.cache` at the top level of the file, outside the `projects` sections.
```jsonc
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"cli": {
"cache": {
// ...
},
},
"projects": {},
}
```
For more information, see [cache options](reference/configs/workspace-config#cache-options).
### Cache environments
By default, disk cache is only enabled for local environments. The value of environment can be one of the following:
- `all` - allows disk cache on all machines.
- `local` - allows disk cache only on development machines.
- `ci` - allows disk cache only on continuous integration (CI) systems.
To change the environment setting to `all`, run the following command:
```bash
ng config cli.cache.environment all
```
For more information, see `environment` in [cache options](reference/configs/workspace-config#cache-options).
<div class="alert is-helpful">
The Angular CLI checks for the presence and value of the `CI` environment variable to determine in which environment it is running.
</div>
### Cache path
By default, `.angular/cache` is used as a base directory to store cache results.
To change this path to `.cache/ng`, run the following command:
```bash
ng config cli.cache.path ".cache/ng"
```
+27
View File
@@ -0,0 +1,27 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { Argv } from 'yargs';
import { CommandModule, CommandModuleImplementation, CommandScope } from '../../../command-builder/command-module';
export declare class CacheDisableModule extends CommandModule implements CommandModuleImplementation {
command: string;
aliases: string;
describe: string;
longDescriptionPath: string | undefined;
scope: CommandScope;
builder(localYargs: Argv): Argv;
run(): Promise<void>;
}
export declare class CacheEnableModule extends CommandModule implements CommandModuleImplementation {
command: string;
aliases: string;
describe: string;
longDescriptionPath: string | undefined;
scope: CommandScope;
builder(localYargs: Argv): Argv;
run(): Promise<void>;
}
+41
View File
@@ -0,0 +1,41 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.CacheEnableModule = exports.CacheDisableModule = void 0;
const command_module_1 = require("../../../command-builder/command-module");
const utilities_1 = require("../utilities");
class CacheDisableModule extends command_module_1.CommandModule {
command = 'disable';
aliases = 'off';
describe = 'Disables persistent disk cache for all projects in the workspace.';
longDescriptionPath;
scope = command_module_1.CommandScope.In;
builder(localYargs) {
return localYargs;
}
run() {
return (0, utilities_1.updateCacheConfig)(this.getWorkspaceOrThrow(), 'enabled', false);
}
}
exports.CacheDisableModule = CacheDisableModule;
class CacheEnableModule extends command_module_1.CommandModule {
command = 'enable';
aliases = 'on';
describe = 'Enables disk cache for all projects in the workspace.';
longDescriptionPath;
scope = command_module_1.CommandScope.In;
builder(localYargs) {
return localYargs;
}
run() {
return (0, utilities_1.updateCacheConfig)(this.getWorkspaceOrThrow(), 'enabled', true);
}
}
exports.CacheEnableModule = CacheEnableModule;
//# sourceMappingURL=cli.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"cli.js","sourceRoot":"","sources":["cli.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAGH,4EAIiD;AACjD,4CAAiD;AAEjD,MAAa,kBAAmB,SAAQ,8BAAa;IACnD,OAAO,GAAG,SAAS,CAAC;IACpB,OAAO,GAAG,KAAK,CAAC;IAChB,QAAQ,GAAG,mEAAmE,CAAC;IAC/E,mBAAmB,CAAqB;IAC/B,KAAK,GAAG,6BAAY,CAAC,EAAE,CAAC;IAEjC,OAAO,CAAC,UAAgB;QACtB,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,GAAG;QACD,OAAO,IAAA,6BAAiB,EAAC,IAAI,CAAC,mBAAmB,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;IACzE,CAAC;CACF;AAdD,gDAcC;AAED,MAAa,iBAAkB,SAAQ,8BAAa;IAClD,OAAO,GAAG,QAAQ,CAAC;IACnB,OAAO,GAAG,IAAI,CAAC;IACf,QAAQ,GAAG,uDAAuD,CAAC;IACnE,mBAAmB,CAAqB;IAC/B,KAAK,GAAG,6BAAY,CAAC,EAAE,CAAC;IAEjC,OAAO,CAAC,UAAgB;QACtB,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,GAAG;QACD,OAAO,IAAA,6BAAiB,EAAC,IAAI,CAAC,mBAAmB,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;IACxE,CAAC;CACF;AAdD,8CAcC"}
+11
View File
@@ -0,0 +1,11 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { Cache } from '../../../lib/config/workspace-schema';
import { AngularWorkspace } from '../../utilities/config';
export declare function updateCacheConfig<K extends keyof Cache>(workspace: AngularWorkspace, key: K, value: Cache[K]): Promise<void>;
export declare function getCacheConfig(workspace: AngularWorkspace | undefined): Required<Cache>;
+47
View File
@@ -0,0 +1,47 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.updateCacheConfig = updateCacheConfig;
exports.getCacheConfig = getCacheConfig;
const core_1 = require("@angular-devkit/core");
const node_path_1 = require("node:path");
const workspace_schema_1 = require("../../../lib/config/workspace-schema");
function updateCacheConfig(workspace, key, value) {
const cli = (workspace.extensions['cli'] ??= {});
const cache = (cli['cache'] ??= {});
cache[key] = value;
return workspace.save();
}
function getCacheConfig(workspace) {
if (!workspace) {
throw new Error(`Cannot retrieve cache configuration as workspace is not defined.`);
}
const defaultSettings = {
path: (0, node_path_1.resolve)(workspace.basePath, '.angular/cache'),
environment: workspace_schema_1.Environment.Local,
enabled: true,
};
const cliSetting = workspace.extensions['cli'];
if (!cliSetting || !(0, core_1.isJsonObject)(cliSetting)) {
return defaultSettings;
}
const cacheSettings = cliSetting['cache'];
if (!(0, core_1.isJsonObject)(cacheSettings)) {
return defaultSettings;
}
const { path = defaultSettings.path, environment = defaultSettings.environment, enabled = defaultSettings.enabled,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} = cacheSettings;
return {
path: (0, node_path_1.resolve)(workspace.basePath, path),
environment,
enabled,
};
}
//# sourceMappingURL=utilities.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"utilities.js","sourceRoot":"","sources":["utilities.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAOH,8CAUC;AAED,wCAiCC;AAlDD,+CAAoD;AACpD,yCAAoC;AACpC,2EAA0E;AAG1E,SAAgB,iBAAiB,CAC/B,SAA2B,EAC3B,GAAM,EACN,KAAe;IAEf,MAAM,GAAG,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,EAAE,CAA4C,CAAC;IAC5F,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;IACpC,KAAK,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IAEnB,OAAO,SAAS,CAAC,IAAI,EAAE,CAAC;AAC1B,CAAC;AAED,SAAgB,cAAc,CAAC,SAAuC;IACpE,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAC;IACtF,CAAC;IAED,MAAM,eAAe,GAAoB;QACvC,IAAI,EAAE,IAAA,mBAAO,EAAC,SAAS,CAAC,QAAQ,EAAE,gBAAgB,CAAC;QACnD,WAAW,EAAE,8BAAW,CAAC,KAAK;QAC9B,OAAO,EAAE,IAAI;KACd,CAAC;IAEF,MAAM,UAAU,GAAG,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IAC/C,IAAI,CAAC,UAAU,IAAI,CAAC,IAAA,mBAAY,EAAC,UAAU,CAAC,EAAE,CAAC;QAC7C,OAAO,eAAe,CAAC;IACzB,CAAC;IAED,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;IAC1C,IAAI,CAAC,IAAA,mBAAY,EAAC,aAAa,CAAC,EAAE,CAAC;QACjC,OAAO,eAAe,CAAC;IACzB,CAAC;IAED,MAAM,EACJ,IAAI,GAAG,eAAe,CAAC,IAAI,EAC3B,WAAW,GAAG,eAAe,CAAC,WAAW,EACzC,OAAO,GAAG,eAAe,CAAC,OAAO;IACjC,8DAA8D;MAC/D,GAAG,aAAoC,CAAC;IAEzC,OAAO;QACL,IAAI,EAAE,IAAA,mBAAO,EAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC;QACvC,WAAW;QACX,OAAO;KACR,CAAC;AACJ,CAAC"}
+17
View File
@@ -0,0 +1,17 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { CommandModuleConstructor } from '../command-builder/utilities/command';
export type CommandNames = 'add' | 'analytics' | 'build' | 'cache' | 'completion' | 'config' | 'deploy' | 'e2e' | 'extract-i18n' | 'generate' | 'lint' | 'make-this-awesome' | 'mcp' | 'new' | 'run' | 'serve' | 'test' | 'update' | 'version';
export interface CommandConfig {
aliases?: string[];
factory: () => Promise<{
default: CommandModuleConstructor;
}>;
}
export declare const RootCommands: Record<CommandNames & string, CommandConfig>;
export declare const RootCommandsAliases: Record<string, CommandConfig>;
+116
View File
@@ -0,0 +1,116 @@
"use strict";
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.RootCommandsAliases = exports.RootCommands = void 0;
exports.RootCommands = {
'add': {
factory: () => Promise.resolve().then(() => __importStar(require('./add/cli'))),
},
'analytics': {
factory: () => Promise.resolve().then(() => __importStar(require('./analytics/cli'))),
},
'build': {
factory: () => Promise.resolve().then(() => __importStar(require('./build/cli'))),
aliases: ['b'],
},
'cache': {
factory: () => Promise.resolve().then(() => __importStar(require('./cache/cli'))),
},
'completion': {
factory: () => Promise.resolve().then(() => __importStar(require('./completion/cli'))),
},
'config': {
factory: () => Promise.resolve().then(() => __importStar(require('./config/cli'))),
},
'deploy': {
factory: () => Promise.resolve().then(() => __importStar(require('./deploy/cli'))),
},
'e2e': {
factory: () => Promise.resolve().then(() => __importStar(require('./e2e/cli'))),
aliases: ['e'],
},
'extract-i18n': {
factory: () => Promise.resolve().then(() => __importStar(require('./extract-i18n/cli'))),
},
'generate': {
factory: () => Promise.resolve().then(() => __importStar(require('./generate/cli'))),
aliases: ['g'],
},
'lint': {
factory: () => Promise.resolve().then(() => __importStar(require('./lint/cli'))),
},
'make-this-awesome': {
factory: () => Promise.resolve().then(() => __importStar(require('./make-this-awesome/cli'))),
},
'mcp': {
factory: () => Promise.resolve().then(() => __importStar(require('./mcp/cli'))),
},
'new': {
factory: () => Promise.resolve().then(() => __importStar(require('./new/cli'))),
aliases: ['n'],
},
'run': {
factory: () => Promise.resolve().then(() => __importStar(require('./run/cli'))),
},
'serve': {
factory: () => Promise.resolve().then(() => __importStar(require('./serve/cli'))),
aliases: ['dev', 's'],
},
'test': {
factory: () => Promise.resolve().then(() => __importStar(require('./test/cli'))),
aliases: ['t'],
},
'update': {
factory: () => Promise.resolve().then(() => __importStar(require('./update/cli'))),
},
'version': {
factory: () => Promise.resolve().then(() => __importStar(require('./version/cli'))),
aliases: ['v'],
},
};
exports.RootCommandsAliases = Object.values(exports.RootCommands).reduce((prev, current) => {
current.aliases?.forEach((alias) => {
prev[alias] = current;
});
return prev;
}, {});
//# sourceMappingURL=command-config.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"command-config.js","sourceRoot":"","sources":["command-config.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BU,QAAA,YAAY,GAGrB;IACF,KAAK,EAAE;QACL,OAAO,EAAE,GAAG,EAAE,mDAAQ,WAAW,GAAC;KACnC;IACD,WAAW,EAAE;QACX,OAAO,EAAE,GAAG,EAAE,mDAAQ,iBAAiB,GAAC;KACzC;IACD,OAAO,EAAE;QACP,OAAO,EAAE,GAAG,EAAE,mDAAQ,aAAa,GAAC;QACpC,OAAO,EAAE,CAAC,GAAG,CAAC;KACf;IACD,OAAO,EAAE;QACP,OAAO,EAAE,GAAG,EAAE,mDAAQ,aAAa,GAAC;KACrC;IACD,YAAY,EAAE;QACZ,OAAO,EAAE,GAAG,EAAE,mDAAQ,kBAAkB,GAAC;KAC1C;IACD,QAAQ,EAAE;QACR,OAAO,EAAE,GAAG,EAAE,mDAAQ,cAAc,GAAC;KACtC;IACD,QAAQ,EAAE;QACR,OAAO,EAAE,GAAG,EAAE,mDAAQ,cAAc,GAAC;KACtC;IAED,KAAK,EAAE;QACL,OAAO,EAAE,GAAG,EAAE,mDAAQ,WAAW,GAAC;QAClC,OAAO,EAAE,CAAC,GAAG,CAAC;KACf;IACD,cAAc,EAAE;QACd,OAAO,EAAE,GAAG,EAAE,mDAAQ,oBAAoB,GAAC;KAC5C;IACD,UAAU,EAAE;QACV,OAAO,EAAE,GAAG,EAAE,mDAAQ,gBAAgB,GAAC;QACvC,OAAO,EAAE,CAAC,GAAG,CAAC;KACf;IACD,MAAM,EAAE;QACN,OAAO,EAAE,GAAG,EAAE,mDAAQ,YAAY,GAAC;KACpC;IACD,mBAAmB,EAAE;QACnB,OAAO,EAAE,GAAG,EAAE,mDAAQ,yBAAyB,GAAC;KACjD;IACD,KAAK,EAAE;QACL,OAAO,EAAE,GAAG,EAAE,mDAAQ,WAAW,GAAC;KACnC;IACD,KAAK,EAAE;QACL,OAAO,EAAE,GAAG,EAAE,mDAAQ,WAAW,GAAC;QAClC,OAAO,EAAE,CAAC,GAAG,CAAC;KACf;IACD,KAAK,EAAE;QACL,OAAO,EAAE,GAAG,EAAE,mDAAQ,WAAW,GAAC;KACnC;IACD,OAAO,EAAE;QACP,OAAO,EAAE,GAAG,EAAE,mDAAQ,aAAa,GAAC;QACpC,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,CAAC;KACtB;IACD,MAAM,EAAE;QACN,OAAO,EAAE,GAAG,EAAE,mDAAQ,YAAY,GAAC;QACnC,OAAO,EAAE,CAAC,GAAG,CAAC;KACf;IACD,QAAQ,EAAE;QACR,OAAO,EAAE,GAAG,EAAE,mDAAQ,cAAc,GAAC;KACtC;IACD,SAAS,EAAE;QACT,OAAO,EAAE,GAAG,EAAE,mDAAQ,eAAe,GAAC;QACtC,OAAO,EAAE,CAAC,GAAG,CAAC;KACf;CACF,CAAC;AAEW,QAAA,mBAAmB,GAAG,MAAM,CAAC,MAAM,CAAC,oBAAY,CAAC,CAAC,MAAM,CACnE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE;IAChB,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;QACjC,IAAI,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,OAAO,IAAI,CAAC;AACd,CAAC,EACD,EAAmC,CACpC,CAAC"}
+16
View File
@@ -0,0 +1,16 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
import { Argv } from 'yargs';
import { CommandModule, CommandModuleImplementation } from '../../command-builder/command-module';
export default class CompletionCommandModule extends CommandModule implements CommandModuleImplementation {
command: string;
describe: string;
longDescriptionPath: string;
builder(localYargs: Argv): Argv;
run(): Promise<number>;
}

Some files were not shown because too many files have changed in this diff Show More