@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.
- package/application/index.js +1 -0
- package/migrations/update-17/use-application-builder.js +29 -9
- package/module/index.js +1 -0
- package/package.json +3 -3
- package/ssr/files/application-builder/server.ts.template +2 -2
- package/ssr/index.js +77 -18
- package/utility/ast-utils.js +6 -6
- package/utility/latest-versions/package.json +1 -1
- package/utility/latest-versions.js +2 -2
- package/utility/workspace-models.d.ts +4 -0
package/application/index.js
CHANGED
|
@@ -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
|
|
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,
|
|
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
|
-
|
|
53
|
-
|
|
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-
|
|
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-
|
|
27
|
-
"@angular-devkit/schematics": "17.1.0-
|
|
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, '
|
|
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
|
|
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
|
-
|
|
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
|
|
27
|
-
if (!
|
|
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 } =
|
|
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
|
|
80
|
+
const { base, server } = await getApplicationBuilderOutputPaths(host, project);
|
|
45
81
|
pkg.scripts ??= {};
|
|
46
|
-
pkg.scripts[`serve:ssr:${project}`] = `node ${
|
|
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
|
|
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(
|
|
252
|
+
const project = workspace.projects.get(projectName);
|
|
195
253
|
if (!project) {
|
|
196
|
-
throw new schematics_1.SchematicsException(`Invalid project name (${
|
|
254
|
+
throw new schematics_1.SchematicsException(`Invalid project name (${projectName})`);
|
|
197
255
|
}
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
?
|
|
201
|
-
: '
|
|
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
|
}
|
package/utility/ast-utils.js
CHANGED
|
@@ -324,7 +324,7 @@ function addSymbolToNgModuleMetadata(source, ngModulePath, metadataField, symbol
|
|
|
324
324
|
!ts.isArrayLiteralExpression(assignment.initializer)) {
|
|
325
325
|
return [];
|
|
326
326
|
}
|
|
327
|
-
let
|
|
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
|
-
|
|
335
|
+
expression = elements[elements.length - 1];
|
|
336
336
|
}
|
|
337
337
|
else {
|
|
338
|
-
|
|
338
|
+
expression = assignmentInit;
|
|
339
339
|
}
|
|
340
340
|
let toInsert;
|
|
341
|
-
let position =
|
|
342
|
-
if (ts.isArrayLiteralExpression(
|
|
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 =
|
|
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}`}`;
|
|
@@ -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-
|
|
18
|
-
AngularSSR: '^17.1.0-
|
|
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;
|