@schematics/angular 17.1.0-next.2 → 17.1.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -77,6 +77,7 @@ function default_1(options) {
77
77
  options.ssr
78
78
  ? (0, schematics_1.schematic)('ssr', {
79
79
  project: options.name,
80
+ skipInstall: true,
80
81
  })
81
82
  : (0, schematics_1.noop)(),
82
83
  options.skipPackageJson ? (0, schematics_1.noop)() : addDependenciesToPackageJson(options),
@@ -9,7 +9,7 @@
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
10
  const core_1 = require("@angular-devkit/core");
11
11
  const schematics_1 = require("@angular-devkit/schematics");
12
- const node_path_1 = require("node:path");
12
+ const posix_1 = require("node:path/posix");
13
13
  const json_file_1 = require("../../utility/json-file");
14
14
  const workspace_1 = require("../../utility/workspace");
15
15
  const workspace_models_1 = require("../../utility/workspace-models");
@@ -40,17 +40,42 @@ function default_1() {
40
40
  if (usesNoLongerSupportedOptions(options, context, name)) {
41
41
  continue;
42
42
  }
43
+ if (options['index'] === '') {
44
+ options['index'] = false;
45
+ }
43
46
  // Rename and transform options
44
47
  options['browser'] = options['main'];
45
48
  if (hasServerTarget && typeof options['browser'] === 'string') {
46
- options['server'] = (0, node_path_1.dirname)(options['browser']) + '/main.server.ts';
49
+ options['server'] = (0, posix_1.dirname)(options['browser']) + '/main.server.ts';
47
50
  }
48
51
  options['serviceWorker'] = options['ngswConfigPath'] ?? options['serviceWorker'];
49
52
  if (typeof options['polyfills'] === 'string') {
50
53
  options['polyfills'] = [options['polyfills']];
51
54
  }
52
- if (typeof options['outputPath'] === 'string') {
53
- options['outputPath'] = options['outputPath']?.replace(/\/browser\/?$/, '');
55
+ let outputPath = options['outputPath'];
56
+ if (typeof outputPath === 'string') {
57
+ if (!/\/browser\/?$/.test(outputPath)) {
58
+ // TODO: add prompt.
59
+ context.logger.warn(`The output location of the browser build has been updated from "${outputPath}" to ` +
60
+ `"${(0, posix_1.join)(outputPath, 'browser')}". ` +
61
+ 'You might need to adjust your deployment pipeline or, as an alternative, ' +
62
+ 'set outputPath.browser to "" in order to maintain the previous functionality.');
63
+ }
64
+ else {
65
+ outputPath = outputPath.replace(/\/browser\/?$/, '');
66
+ }
67
+ options['outputPath'] = {
68
+ base: outputPath,
69
+ };
70
+ if (typeof options['resourcesOutputPath'] === 'string') {
71
+ const media = options['resourcesOutputPath'].replaceAll('/', '');
72
+ if (media && media !== 'media') {
73
+ options['outputPath'] = {
74
+ base: outputPath,
75
+ media: media,
76
+ };
77
+ }
78
+ }
54
79
  }
55
80
  // Delete removed options
56
81
  delete options['deployUrl'];
@@ -132,10 +157,5 @@ function usesNoLongerSupportedOptions({ deployUrl, resourcesOutputPath }, contex
132
157
  hasUsage = true;
133
158
  context.logger.warn(`Skipping migration for project "${projectName}". "deployUrl" option is not available in the application builder.`);
134
159
  }
135
- if (typeof resourcesOutputPath === 'string' && /^\/?media\/?$/.test(resourcesOutputPath)) {
136
- hasUsage = true;
137
- context.logger.warn(`Skipping migration for project "${projectName}". "resourcesOutputPath" option is not available in the application builder.` +
138
- `Media files will be output into a "media" directory within the output location.`);
139
- }
140
160
  return hasUsage;
141
161
  }
package/module/index.js CHANGED
@@ -142,6 +142,7 @@ function default_1(options) {
142
142
  name: options.name,
143
143
  path: options.path,
144
144
  project: options.project,
145
+ standalone: false,
145
146
  };
146
147
  return (0, schematics_1.chain)([
147
148
  !isLazyLoadedModuleGen ? addImportToNgModule(options) : (0, schematics_1.noop)(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schematics/angular",
3
- "version": "17.1.0-next.2",
3
+ "version": "17.1.0-rc.0",
4
4
  "description": "Schematics specific to Angular",
5
5
  "homepage": "https://github.com/angular/angular-cli",
6
6
  "keywords": [
@@ -23,8 +23,8 @@
23
23
  },
24
24
  "schematics": "./collection.json",
25
25
  "dependencies": {
26
- "@angular-devkit/core": "17.1.0-next.2",
27
- "@angular-devkit/schematics": "17.1.0-next.2",
26
+ "@angular-devkit/core": "17.1.0-rc.0",
27
+ "@angular-devkit/schematics": "17.1.0-rc.0",
28
28
  "jsonc-parser": "3.2.0"
29
29
  },
30
30
  "repository": {
@@ -9,7 +9,7 @@ import <% if (isStandalone) { %>bootstrap<% } else { %>AppServerModule<% } %> fr
9
9
  export function app(): express.Express {
10
10
  const server = express();
11
11
  const serverDistFolder = dirname(fileURLToPath(import.meta.url));
12
- const browserDistFolder = resolve(serverDistFolder, '../browser');
12
+ const browserDistFolder = resolve(serverDistFolder, '../<%= browserDistDirectory %>');
13
13
  const indexHtml = join(serverDistFolder, 'index.server.html');
14
14
 
15
15
  const commonEngine = new CommonEngine();
@@ -19,7 +19,7 @@ export function app(): express.Express {
19
19
 
20
20
  // Example Express Rest API endpoints
21
21
  // server.get('/api/**', (req, res) => { });
22
- // Serve static files from /browser
22
+ // Serve static files from /<%= browserDistDirectory %>
23
23
  server.get('*.*', express.static(browserDistFolder, {
24
24
  maxAge: '1y'
25
25
  }));
package/ssr/index.js CHANGED
@@ -9,6 +9,7 @@
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
10
  const core_1 = require("@angular-devkit/core");
11
11
  const schematics_1 = require("@angular-devkit/schematics");
12
+ const node_path_1 = require("node:path");
12
13
  const utility_1 = require("../utility");
13
14
  const json_file_1 = require("../utility/json-file");
14
15
  const latest_versions_1 = require("../utility/latest-versions");
@@ -19,20 +20,55 @@ const workspace_1 = require("../utility/workspace");
19
20
  const workspace_models_1 = require("../utility/workspace-models");
20
21
  const SERVE_SSR_TARGET_NAME = 'serve-ssr';
21
22
  const PRERENDER_TARGET_NAME = 'prerender';
22
- async function getOutputPath(host, projectName, target) {
23
+ const DEFAULT_BROWSER_DIR = 'browser';
24
+ const DEFAULT_MEDIA_DIR = 'media';
25
+ const DEFAULT_SERVER_DIR = 'server';
26
+ async function getLegacyOutputPaths(host, projectName, target) {
23
27
  // Generate new output paths
24
28
  const workspace = await (0, utility_1.readWorkspace)(host);
25
29
  const project = workspace.projects.get(projectName);
26
- const serverTarget = project?.targets.get(target);
27
- if (!serverTarget || !serverTarget.options) {
30
+ const architectTarget = project?.targets.get(target);
31
+ if (!architectTarget?.options) {
28
32
  throw new schematics_1.SchematicsException(`Cannot find 'options' for ${projectName} ${target} target.`);
29
33
  }
30
- const { outputPath } = serverTarget.options;
34
+ const { outputPath } = architectTarget.options;
31
35
  if (typeof outputPath !== 'string') {
32
36
  throw new schematics_1.SchematicsException(`outputPath for ${projectName} ${target} target is not a string.`);
33
37
  }
34
38
  return outputPath;
35
39
  }
40
+ async function getApplicationBuilderOutputPaths(host, projectName) {
41
+ // Generate new output paths
42
+ const target = 'build';
43
+ const workspace = await (0, utility_1.readWorkspace)(host);
44
+ const project = workspace.projects.get(projectName);
45
+ const architectTarget = project?.targets.get(target);
46
+ if (!architectTarget?.options) {
47
+ throw new schematics_1.SchematicsException(`Cannot find 'options' for ${projectName} ${target} target.`);
48
+ }
49
+ const { outputPath } = architectTarget.options;
50
+ if (outputPath === null || outputPath === undefined) {
51
+ throw new schematics_1.SchematicsException(`outputPath for ${projectName} ${target} target is undeined or null.`);
52
+ }
53
+ const defaultDirs = {
54
+ server: DEFAULT_SERVER_DIR,
55
+ browser: DEFAULT_BROWSER_DIR,
56
+ };
57
+ if (outputPath && (0, core_1.isJsonObject)(outputPath)) {
58
+ return {
59
+ ...defaultDirs,
60
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
61
+ ...outputPath,
62
+ };
63
+ }
64
+ if (typeof outputPath !== 'string') {
65
+ throw new schematics_1.SchematicsException(`outputPath for ${projectName} ${target} target is not a string.`);
66
+ }
67
+ return {
68
+ base: outputPath,
69
+ ...defaultDirs,
70
+ };
71
+ }
36
72
  function addScriptsRule({ project }, isUsingApplicationBuilder) {
37
73
  return async (host) => {
38
74
  const pkgPath = '/package.json';
@@ -41,12 +77,12 @@ function addScriptsRule({ project }, isUsingApplicationBuilder) {
41
77
  throw new schematics_1.SchematicsException('Could not find package.json');
42
78
  }
43
79
  if (isUsingApplicationBuilder) {
44
- const distPath = await getOutputPath(host, project, 'build');
80
+ const { base, server } = await getApplicationBuilderOutputPaths(host, project);
45
81
  pkg.scripts ??= {};
46
- pkg.scripts[`serve:ssr:${project}`] = `node ${distPath}/server/server.mjs`;
82
+ pkg.scripts[`serve:ssr:${project}`] = `node ${node_path_1.posix.join(base, server)}/server.mjs`;
47
83
  }
48
84
  else {
49
- const serverDist = await getOutputPath(host, project, 'server');
85
+ const serverDist = await getLegacyOutputPaths(host, project, 'server');
50
86
  pkg.scripts = {
51
87
  ...pkg.scripts,
52
88
  'dev:ssr': `ng run ${project}:${SERVE_SSR_TARGET_NAME}`,
@@ -79,14 +115,30 @@ function updateApplicationBuilderTsConfigRule(options) {
79
115
  }
80
116
  };
81
117
  }
82
- function updateApplicationBuilderWorkspaceConfigRule(projectRoot, options) {
118
+ function updateApplicationBuilderWorkspaceConfigRule(projectRoot, options, { logger }) {
83
119
  return (0, utility_1.updateWorkspace)((workspace) => {
84
120
  const buildTarget = workspace.projects.get(options.project)?.targets.get('build');
85
121
  if (!buildTarget) {
86
122
  return;
87
123
  }
124
+ let outputPath = buildTarget.options?.outputPath;
125
+ if (outputPath && (0, core_1.isJsonObject)(outputPath)) {
126
+ if (outputPath.browser === '') {
127
+ const base = outputPath.base;
128
+ logger.warn(`The output location of the browser build has been updated from "${base}" to "${node_path_1.posix.join(base, DEFAULT_BROWSER_DIR)}".
129
+ You might need to adjust your deployment pipeline.`);
130
+ if ((outputPath.media && outputPath.media !== DEFAULT_MEDIA_DIR) ||
131
+ (outputPath.server && outputPath.server !== DEFAULT_SERVER_DIR)) {
132
+ delete outputPath.browser;
133
+ }
134
+ else {
135
+ outputPath = outputPath.base;
136
+ }
137
+ }
138
+ }
88
139
  buildTarget.options = {
89
140
  ...buildTarget.options,
141
+ outputPath,
90
142
  prerender: true,
91
143
  ssr: {
92
144
  entry: (0, core_1.join)((0, core_1.normalize)(projectRoot), 'server.ts'),
@@ -169,36 +221,43 @@ function updateWebpackBuilderServerTsConfigRule(options) {
169
221
  }
170
222
  };
171
223
  }
172
- function addDependencies(isUsingApplicationBuilder) {
224
+ function addDependencies({ skipInstall }, isUsingApplicationBuilder) {
225
+ const install = skipInstall ? utility_1.InstallBehavior.None : utility_1.InstallBehavior.Auto;
173
226
  const rules = [
174
227
  (0, utility_1.addDependency)('@angular/ssr', latest_versions_1.latestVersions.AngularSSR, {
175
228
  type: utility_1.DependencyType.Default,
229
+ install,
176
230
  }),
177
231
  (0, utility_1.addDependency)('express', latest_versions_1.latestVersions['express'], {
178
232
  type: utility_1.DependencyType.Default,
233
+ install,
179
234
  }),
180
235
  (0, utility_1.addDependency)('@types/express', latest_versions_1.latestVersions['@types/express'], {
181
236
  type: utility_1.DependencyType.Dev,
237
+ install,
182
238
  }),
183
239
  ];
184
240
  if (!isUsingApplicationBuilder) {
185
241
  rules.push((0, utility_1.addDependency)('browser-sync', latest_versions_1.latestVersions['browser-sync'], {
186
242
  type: utility_1.DependencyType.Dev,
243
+ install,
187
244
  }));
188
245
  }
189
246
  return (0, schematics_1.chain)(rules);
190
247
  }
191
248
  function addServerFile(options, isStandalone) {
192
249
  return async (host) => {
250
+ const projectName = options.project;
193
251
  const workspace = await (0, utility_1.readWorkspace)(host);
194
- const project = workspace.projects.get(options.project);
252
+ const project = workspace.projects.get(projectName);
195
253
  if (!project) {
196
- throw new schematics_1.SchematicsException(`Invalid project name (${options.project})`);
254
+ throw new schematics_1.SchematicsException(`Invalid project name (${projectName})`);
197
255
  }
198
- const browserDistDirectory = await getOutputPath(host, options.project, 'build');
199
- return (0, schematics_1.mergeWith)((0, schematics_1.apply)((0, schematics_1.url)(`./files/${project?.targets?.get('build')?.builder === workspace_models_1.Builders.Application
200
- ? 'application-builder'
201
- : 'server-builder'}`), [
256
+ const isUsingApplicationBuilder = project?.targets?.get('build')?.builder === workspace_models_1.Builders.Application;
257
+ const browserDistDirectory = isUsingApplicationBuilder
258
+ ? (await getApplicationBuilderOutputPaths(host, projectName)).browser
259
+ : await getLegacyOutputPaths(host, projectName, 'build');
260
+ return (0, schematics_1.mergeWith)((0, schematics_1.apply)((0, schematics_1.url)(`./files/${isUsingApplicationBuilder ? 'application-builder' : 'server-builder'}`), [
202
261
  (0, schematics_1.applyTemplates)({
203
262
  ...core_1.strings,
204
263
  ...options,
@@ -210,7 +269,7 @@ function addServerFile(options, isStandalone) {
210
269
  };
211
270
  }
212
271
  function default_1(options) {
213
- return async (host) => {
272
+ return async (host, context) => {
214
273
  const browserEntryPoint = await (0, util_1.getMainFilePath)(host, options.project);
215
274
  const isStandalone = (0, ng_ast_utils_1.isStandaloneApp)(host, browserEntryPoint);
216
275
  const workspace = await (0, workspace_1.getWorkspace)(host);
@@ -226,7 +285,7 @@ function default_1(options) {
226
285
  }),
227
286
  ...(isUsingApplicationBuilder
228
287
  ? [
229
- updateApplicationBuilderWorkspaceConfigRule(clientProject.root, options),
288
+ updateApplicationBuilderWorkspaceConfigRule(clientProject.root, options, context),
230
289
  updateApplicationBuilderTsConfigRule(options),
231
290
  ]
232
291
  : [
@@ -235,7 +294,7 @@ function default_1(options) {
235
294
  ]),
236
295
  addServerFile(options, isStandalone),
237
296
  addScriptsRule(options, isUsingApplicationBuilder),
238
- addDependencies(isUsingApplicationBuilder),
297
+ addDependencies(options, isUsingApplicationBuilder),
239
298
  ]);
240
299
  };
241
300
  }
@@ -324,7 +324,7 @@ function addSymbolToNgModuleMetadata(source, ngModulePath, metadataField, symbol
324
324
  !ts.isArrayLiteralExpression(assignment.initializer)) {
325
325
  return [];
326
326
  }
327
- let expresssion;
327
+ let expression;
328
328
  const assignmentInit = assignment.initializer;
329
329
  const elements = assignmentInit.elements;
330
330
  if (elements.length) {
@@ -332,21 +332,21 @@ function addSymbolToNgModuleMetadata(source, ngModulePath, metadataField, symbol
332
332
  if (symbolsArray.includes(core_1.tags.oneLine `${symbolName}`)) {
333
333
  return [];
334
334
  }
335
- expresssion = elements[elements.length - 1];
335
+ expression = elements[elements.length - 1];
336
336
  }
337
337
  else {
338
- expresssion = assignmentInit;
338
+ expression = assignmentInit;
339
339
  }
340
340
  let toInsert;
341
- let position = expresssion.getEnd();
342
- if (ts.isArrayLiteralExpression(expresssion)) {
341
+ let position = expression.getEnd();
342
+ if (ts.isArrayLiteralExpression(expression)) {
343
343
  // We found the field but it's empty. Insert it just before the `]`.
344
344
  position--;
345
345
  toInsert = `\n${core_1.tags.indentBy(4) `${symbolName}`}\n `;
346
346
  }
347
347
  else {
348
348
  // Get the indentation of the last element, if any.
349
- const text = expresssion.getFullText(source);
349
+ const text = expression.getFullText(source);
350
350
  const matches = text.match(/^(\r?\n)(\s*)/);
351
351
  if (matches) {
352
352
  toInsert = `,${matches[1]}${core_1.tags.indentBy(matches[2].length) `${symbolName}`}`;
@@ -6,7 +6,7 @@
6
6
  "@types/express": "^4.17.17",
7
7
  "@types/jasmine": "~5.1.0",
8
8
  "@types/node": "^18.18.0",
9
- "browser-sync": "^2.29.3",
9
+ "browser-sync": "^3.0.0",
10
10
  "express": "^4.18.2",
11
11
  "jasmine-core": "~5.1.0",
12
12
  "jasmine-spec-reporter": "~7.0.0",
@@ -14,6 +14,6 @@ exports.latestVersions = {
14
14
  ...require('./latest-versions/package.json')['dependencies'],
15
15
  // As Angular CLI works with same minor versions of Angular Framework, a tilde match for the current
16
16
  Angular: '^17.1.0-next.0',
17
- DevkitBuildAngular: '^17.1.0-next.2',
18
- AngularSSR: '^17.1.0-next.2',
17
+ DevkitBuildAngular: '^17.1.0-rc.0',
18
+ AngularSSR: '^17.1.0-rc.0',
19
19
  };
@@ -66,7 +66,11 @@ export interface BrowserBuilderOptions extends BrowserBuilderBaseOptions {
66
66
  webWorkerTsConfig?: string;
67
67
  }
68
68
  export interface ServeBuilderOptions {
69
+ /**
70
+ * @deprecated not used since version 17.0.0. Use the property "buildTarget" instead.
71
+ */
69
72
  browserTarget: string;
73
+ buildTarget?: string;
70
74
  }
71
75
  export interface LibraryBuilderOptions {
72
76
  tsConfig: string;