@schematics/angular 21.0.0-next.5 → 21.0.0-next.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,6 +11,10 @@ exports.default = default_1;
11
11
  const schematics_1 = require("@angular-devkit/schematics");
12
12
  const schema_1 = require("./schema");
13
13
  const AI_TOOLS = {
14
+ agents: {
15
+ rulesName: 'AGENTS.md',
16
+ directory: '.',
17
+ },
14
18
  gemini: {
15
19
  rulesName: 'GEMINI.md',
16
20
  directory: '.gemini',
@@ -39,19 +43,32 @@ const AI_TOOLS = {
39
43
  },
40
44
  };
41
45
  function default_1({ tool }) {
42
- if (!tool) {
43
- return (0, schematics_1.noop)();
44
- }
45
- const rules = tool
46
- .filter((tool) => tool !== schema_1.Tool.None)
47
- .map((selectedTool) => AI_TOOLS[selectedTool])
48
- .map(({ rulesName, directory, frontmatter }) => (0, schematics_1.mergeWith)((0, schematics_1.apply)((0, schematics_1.url)('./files'), [
49
- (0, schematics_1.applyTemplates)({
50
- ...schematics_1.strings,
51
- rulesName,
52
- frontmatter,
53
- }),
54
- (0, schematics_1.move)(directory),
55
- ])));
56
- return (0, schematics_1.chain)(rules);
46
+ return (tree, context) => {
47
+ if (!tool) {
48
+ return (0, schematics_1.noop)();
49
+ }
50
+ const rules = tool
51
+ .filter((tool) => tool !== schema_1.Tool.None)
52
+ .map((selectedTool) => {
53
+ const { rulesName, directory, frontmatter } = AI_TOOLS[selectedTool];
54
+ const path = `${directory}/${rulesName}`;
55
+ if (tree.exists(path)) {
56
+ const toolName = schematics_1.strings.classify(selectedTool);
57
+ context.logger.warn(`Skipping configuration file for '${toolName}' at '${path}' because it already exists.\n` +
58
+ 'This is to prevent overwriting a potentially customized file. ' +
59
+ 'If you want to regenerate it with Angular recommended defaults, please delete the existing file and re-run the command.\n' +
60
+ 'You can review the latest recommendations at https://angular.dev/ai/develop-with-ai.');
61
+ return (0, schematics_1.noop)();
62
+ }
63
+ return (0, schematics_1.mergeWith)((0, schematics_1.apply)((0, schematics_1.url)('./files'), [
64
+ (0, schematics_1.applyTemplates)({
65
+ ...schematics_1.strings,
66
+ rulesName,
67
+ frontmatter,
68
+ }),
69
+ (0, schematics_1.move)(directory),
70
+ ]));
71
+ });
72
+ return (0, schematics_1.chain)(rules);
73
+ };
57
74
  }
@@ -11,6 +11,7 @@ export type Schema = {
11
11
  tool?: Tool[];
12
12
  };
13
13
  export declare enum Tool {
14
+ Agents = "agents",
14
15
  Claude = "claude",
15
16
  Copilot = "copilot",
16
17
  Cursor = "cursor",
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.Tool = void 0;
6
6
  var Tool;
7
7
  (function (Tool) {
8
+ Tool["Agents"] = "agents";
8
9
  Tool["Claude"] = "claude";
9
10
  Tool["Copilot"] = "copilot";
10
11
  Tool["Cursor"] = "cursor";
@@ -18,6 +18,10 @@
18
18
  "value": "none",
19
19
  "label": "None"
20
20
  },
21
+ {
22
+ "value": "agents",
23
+ "label": "Agents.md [ https://agents.md/ ]"
24
+ },
21
25
  {
22
26
  "value": "claude",
23
27
  "label": "Claude [ https://docs.anthropic.com/en/docs/claude-code/memory ]"
@@ -47,7 +51,7 @@
47
51
  "description": "Specifies which AI tools to generate configuration files for. These file are used to improve the outputs of AI tools by following the best practices.",
48
52
  "items": {
49
53
  "type": "string",
50
- "enum": ["none", "gemini", "copilot", "claude", "cursor", "jetbrains", "windsurf"]
54
+ "enum": ["none", "gemini", "copilot", "claude", "cursor", "jetbrains", "windsurf", "agents"]
51
55
  }
52
56
  }
53
57
  }
@@ -20,9 +20,9 @@ describe('App', () => {
20
20
  expect(app).toBeTruthy();
21
21
  });
22
22
 
23
- it('should render title', () => {
23
+ it('should render title', <% if(zoneless) { %> async <% } %>() => {
24
24
  const fixture = TestBed.createComponent(App);
25
- fixture.detectChanges();
25
+ <%= zoneless ? 'await fixture.whenStable();' : 'fixture.detectChanges();' %>
26
26
  const compiled = fixture.nativeElement as HTMLElement;
27
27
  expect(compiled.querySelector('h1')?.textContent).toContain('Hello, <%= name %>');
28
28
  });
@@ -14,9 +14,9 @@ describe('App', () => {
14
14
  expect(app).toBeTruthy();
15
15
  });
16
16
 
17
- it('should render title', () => {
17
+ it('should render title', <% if(zoneless) { %> async <% } %>() => {
18
18
  const fixture = TestBed.createComponent(App);
19
- fixture.detectChanges();
19
+ <%= zoneless ? 'await fixture.whenStable();' : 'fixture.detectChanges();' %>
20
20
  const compiled = fixture.nativeElement as HTMLElement;
21
21
  expect(compiled.querySelector('h1')?.textContent).toContain('Hello, <%= name %>');
22
22
  });
@@ -14,7 +14,7 @@ describe('<%= classifiedName %>', () => {
14
14
 
15
15
  fixture = TestBed.createComponent(<%= classifiedName %>);
16
16
  component = fixture.componentInstance;
17
- fixture.detectChanges();
17
+ <%= zoneless ? 'await fixture.whenStable();' : 'fixture.detectChanges();' %>
18
18
  });
19
19
 
20
20
  it('should create', () => {
@@ -12,6 +12,7 @@ const add_declaration_to_ng_module_1 = require("../utility/add-declaration-to-ng
12
12
  const find_module_1 = require("../utility/find-module");
13
13
  const parse_name_1 = require("../utility/parse-name");
14
14
  const project_1 = require("../utility/project");
15
+ const project_targets_1 = require("../utility/project-targets");
15
16
  const validation_1 = require("../utility/validation");
16
17
  const workspace_1 = require("../utility/workspace");
17
18
  const schema_1 = require("./schema");
@@ -40,6 +41,7 @@ exports.default = (0, project_1.createProjectSchematic)((options, { project, tre
40
41
  const classifiedName = schematics_1.strings.classify(options.name) +
41
42
  (options.addTypeToClassName && options.type ? schematics_1.strings.classify(options.type) : '');
42
43
  (0, validation_1.validateClassName)(classifiedName);
44
+ const zoneless = (0, project_targets_1.isZonelessApp)(project);
43
45
  const skipStyleFile = options.inlineStyle || options.style === schema_1.Style.None;
44
46
  const templateSource = (0, schematics_1.apply)((0, schematics_1.url)('./files'), [
45
47
  options.skipTests ? (0, schematics_1.filter)((path) => !path.endsWith('.spec.ts.template')) : (0, schematics_1.noop)(),
@@ -52,6 +54,7 @@ exports.default = (0, project_1.createProjectSchematic)((options, { project, tre
52
54
  ...options,
53
55
  // Add a new variable for the classified name, conditionally including the type
54
56
  classifiedName,
57
+ zoneless,
55
58
  }),
56
59
  !options.type
57
60
  ? (0, schematics_1.forEach)(((file) => {
@@ -270,6 +270,7 @@ function default_1() {
270
270
  rootJson.modify(['compilerOptions', 'esModuleInterop'], true);
271
271
  rootJson.modify(['compilerOptions', 'downlevelIteration'], undefined);
272
272
  rootJson.modify(['compilerOptions', 'allowSyntheticDefaultImports'], undefined);
273
+ rootJson.modify(['compilerOptions', 'moduleResolution'], 'bundler');
273
274
  }),
274
275
  ]);
275
276
  }
@@ -124,6 +124,7 @@ export type Schema = {
124
124
  zoneless?: boolean;
125
125
  };
126
126
  export declare enum AiConfig {
127
+ Agents = "agents",
127
128
  Claude = "claude",
128
129
  Copilot = "copilot",
129
130
  Cursor = "cursor",
package/ng-new/schema.js CHANGED
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.ViewEncapsulation = exports.Style = exports.PackageManager = exports.FileNameStyleGuide = exports.AiConfig = void 0;
6
6
  var AiConfig;
7
7
  (function (AiConfig) {
8
+ AiConfig["Agents"] = "agents";
8
9
  AiConfig["Claude"] = "claude";
9
10
  AiConfig["Copilot"] = "copilot";
10
11
  AiConfig["Cursor"] = "cursor";
@@ -149,7 +149,7 @@
149
149
  "description": "Specifies which AI tools to generate configuration files for. These file are used to improve the outputs of AI tools by following the best practices.",
150
150
  "items": {
151
151
  "type": "string",
152
- "enum": ["none", "gemini", "copilot", "claude", "cursor", "jetbrains", "windsurf"]
152
+ "enum": ["none", "gemini", "copilot", "claude", "cursor", "jetbrains", "windsurf", "agents"]
153
153
  }
154
154
  },
155
155
  "fileNameStyleGuide": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schematics/angular",
3
- "version": "21.0.0-next.5",
3
+ "version": "21.0.0-next.6",
4
4
  "description": "Schematics specific to Angular",
5
5
  "homepage": "https://github.com/angular/angular-cli",
6
6
  "keywords": [
@@ -22,8 +22,8 @@
22
22
  },
23
23
  "schematics": "./collection.json",
24
24
  "dependencies": {
25
- "@angular-devkit/core": "21.0.0-next.5",
26
- "@angular-devkit/schematics": "21.0.0-next.5",
25
+ "@angular-devkit/core": "21.0.0-next.6",
26
+ "@angular-devkit/schematics": "21.0.0-next.6",
27
27
  "jsonc-parser": "3.3.1"
28
28
  },
29
29
  "repository": {
@@ -48,10 +48,10 @@ app.use((req, res, next) => {
48
48
  });
49
49
 
50
50
  /**
51
- * Start the server if this module is the main entry point.
51
+ * Start the server if this module is the main entry point, or it is ran via PM2.
52
52
  * The server listens on the port defined by the `PORT` environment variable, or defaults to 4000.
53
53
  */
54
- if (isMainModule(import.meta.url)) {
54
+ if (isMainModule(import.meta.url) || process.env['pm_id']) {
55
55
  const port = process.env['PORT'] || 4000;
56
56
  app.listen(port, (error) => {
57
57
  if (error) {
@@ -8,7 +8,7 @@
8
8
  "@types/node": "^20.17.19",
9
9
  "browser-sync": "^3.0.0",
10
10
  "express": "^5.1.0",
11
- "jasmine-core": "~5.10.0",
11
+ "jasmine-core": "~5.11.0",
12
12
  "jasmine-spec-reporter": "~7.0.0",
13
13
  "karma-chrome-launcher": "~3.2.0",
14
14
  "karma-coverage": "~2.2.0",
@@ -16,7 +16,7 @@ exports.latestVersions = {
16
16
  // As Angular CLI works with same minor versions of Angular Framework, a tilde match for the current
17
17
  Angular: '^21.0.0-next.0',
18
18
  NgPackagr: '^21.0.0-next.0',
19
- DevkitBuildAngular: '^21.0.0-next.5',
20
- AngularBuild: '^21.0.0-next.5',
21
- AngularSSR: '^21.0.0-next.5',
19
+ DevkitBuildAngular: '^21.0.0-next.6',
20
+ AngularBuild: '^21.0.0-next.6',
21
+ AngularSSR: '^21.0.0-next.6',
22
22
  };
@@ -9,3 +9,4 @@ import { SchematicsException } from '@angular-devkit/schematics';
9
9
  import { ProjectDefinition } from './workspace';
10
10
  export declare function targetBuildNotFoundError(): SchematicsException;
11
11
  export declare function isUsingApplicationBuilder(project: ProjectDefinition): boolean;
12
+ export declare function isZonelessApp(project: ProjectDefinition): boolean;
@@ -9,6 +9,7 @@
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.targetBuildNotFoundError = targetBuildNotFoundError;
11
11
  exports.isUsingApplicationBuilder = isUsingApplicationBuilder;
12
+ exports.isZonelessApp = isZonelessApp;
12
13
  const schematics_1 = require("@angular-devkit/schematics");
13
14
  const workspace_models_1 = require("./workspace-models");
14
15
  function targetBuildNotFoundError() {
@@ -19,3 +20,12 @@ function isUsingApplicationBuilder(project) {
19
20
  const isUsingApplicationBuilder = buildBuilder === workspace_models_1.Builders.Application || buildBuilder === workspace_models_1.Builders.BuildApplication;
20
21
  return isUsingApplicationBuilder;
21
22
  }
23
+ function isZonelessApp(project) {
24
+ const buildTarget = project.targets.get('build');
25
+ if (!buildTarget?.options?.polyfills) {
26
+ return true;
27
+ }
28
+ const polyfills = buildTarget.options.polyfills;
29
+ const polyfillsList = Array.isArray(polyfills) ? polyfills : [polyfills];
30
+ return !polyfillsList.includes('zone.js');
31
+ }