UNPKG

18 kBJavaScriptView Raw
1"use strict";
2var __values = (this && this.__values) || function(o) {
3 var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
4 if (m) return m.call(o);
5 if (o && typeof o.length === "number") return {
6 next: function () {
7 if (o && i >= o.length) o = void 0;
8 return { value: o && o[i++], done: !o };
9 }
10 };
11 throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
12};
13var __read = (this && this.__read) || function (o, n) {
14 var m = typeof Symbol === "function" && o[Symbol.iterator];
15 if (!m) return o;
16 var i = m.call(o), r, ar = [], e;
17 try {
18 while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
19 }
20 catch (error) { e = { error: error }; }
21 finally {
22 try {
23 if (r && !r.done && (m = i["return"])) m.call(i);
24 }
25 finally { if (e) throw e.error; }
26 }
27 return ar;
28};
29var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
30 if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
31 if (ar || !(i in from)) {
32 if (!ar) ar = Array.prototype.slice.call(from, 0, i);
33 ar[i] = from[i];
34 }
35 }
36 return to.concat(ar || Array.prototype.slice.call(from));
37};
38Object.defineProperty(exports, "__esModule", { value: true });
39exports.findBootstrapApplicationCall = exports.addFunctionalProvidersToStandaloneBootstrap = exports.callsProvidersFunction = void 0;
40// copied from https://github.com/angular/angular-cli/blob/17.3.x/packages/schematics/angular/private/standalone.ts
41var schematics_1 = require("@angular-devkit/schematics");
42var path_1 = require("path");
43var ast_utils_1 = require("./ast-utils");
44var change_1 = require("./change");
45var ts = require("typescript");
46/**
47 * Checks whether a providers function is being called in a `bootstrapApplication` call.
48 * @param tree File tree of the project.
49 * @param filePath Path of the file in which to check.
50 * @param functionName Name of the function to search for.
51 * @deprecated Private utility that will be removed. Use `addRootImport` or `addRootProvider` from
52 * `@schematics/angular/utility` instead.
53 */
54function callsProvidersFunction(tree, filePath, functionName) {
55 var sourceFile = createSourceFile(tree, filePath);
56 var bootstrapCall = findBootstrapApplicationCall(sourceFile);
57 var appConfig = bootstrapCall
58 ? findAppConfig(bootstrapCall, tree, filePath)
59 : null;
60 var providersLiteral = appConfig
61 ? findProvidersLiteral(appConfig.node)
62 : null;
63 return !!(providersLiteral === null || providersLiteral === void 0 ? void 0 : providersLiteral.elements.some(function (el) {
64 return ts.isCallExpression(el) &&
65 ts.isIdentifier(el.expression) &&
66 el.expression.text === functionName;
67 }));
68}
69exports.callsProvidersFunction = callsProvidersFunction;
70/**
71 * Adds a providers function call to the `bootstrapApplication` call.
72 * @param tree File tree of the project.
73 * @param filePath Path to the file that should be updated.
74 * @param functionName Name of the function that should be called.
75 * @param importPath Path from which to import the function.
76 * @param args Arguments to use when calling the function.
77 * @return The file path that the provider was added to.
78 * @deprecated Private utility that will be removed. Use `addRootImport` or `addRootProvider` from
79 * `@schematics/angular/utility` instead.
80 */
81function addFunctionalProvidersToStandaloneBootstrap(tree, filePath, functionName, importPath, args) {
82 if (args === void 0) { args = []; }
83 var sourceFile = createSourceFile(tree, filePath);
84 var bootstrapCall = findBootstrapApplicationCall(sourceFile);
85 var addImports = function (file, recorder) {
86 var change = (0, ast_utils_1.insertImport)(file, file.getText(), functionName, importPath);
87 if (change instanceof change_1.InsertChange) {
88 recorder.insertLeft(change.pos, change.toAdd);
89 }
90 };
91 if (!bootstrapCall) {
92 throw new schematics_1.SchematicsException("Could not find bootstrapApplication call in ".concat(filePath));
93 }
94 var providersCall = ts.factory.createCallExpression(ts.factory.createIdentifier(functionName), undefined, args);
95 // If there's only one argument, we have to create a new object literal.
96 if (bootstrapCall.arguments.length === 1) {
97 var recorder_1 = tree.beginUpdate(filePath);
98 addNewAppConfigToCall(bootstrapCall, providersCall, recorder_1);
99 addImports(sourceFile, recorder_1);
100 tree.commitUpdate(recorder_1);
101 return filePath;
102 }
103 // If the config is a `mergeApplicationProviders` call, add another config to it.
104 if (isMergeAppConfigCall(bootstrapCall.arguments[1])) {
105 var recorder_2 = tree.beginUpdate(filePath);
106 addNewAppConfigToCall(bootstrapCall.arguments[1], providersCall, recorder_2);
107 addImports(sourceFile, recorder_2);
108 tree.commitUpdate(recorder_2);
109 return filePath;
110 }
111 // Otherwise attempt to merge into the current config.
112 var appConfig = findAppConfig(bootstrapCall, tree, filePath);
113 if (!appConfig) {
114 throw new schematics_1.SchematicsException("Could not statically analyze config in bootstrapApplication call in ".concat(filePath));
115 }
116 var configFilePath = appConfig.filePath, config = appConfig.node;
117 var recorder = tree.beginUpdate(configFilePath);
118 var providersLiteral = findProvidersLiteral(config);
119 addImports(config.getSourceFile(), recorder);
120 if (providersLiteral) {
121 // If there's a `providers` array, add the import to it.
122 addElementToArray(providersLiteral, providersCall, recorder);
123 }
124 else {
125 // Otherwise add a `providers` array to the existing object literal.
126 addProvidersToObjectLiteral(config, providersCall, recorder);
127 }
128 tree.commitUpdate(recorder);
129 return configFilePath;
130}
131exports.addFunctionalProvidersToStandaloneBootstrap = addFunctionalProvidersToStandaloneBootstrap;
132/**
133 * Finds the call to `bootstrapApplication` within a file.
134 * @deprecated Private utility that will be removed. Use `addRootImport` or `addRootProvider` from
135 * `@schematics/angular/utility` instead.
136 */
137function findBootstrapApplicationCall(sourceFile) {
138 var localName = findImportLocalName(sourceFile, 'bootstrapApplication', '@angular/platform-browser');
139 if (!localName) {
140 return null;
141 }
142 var result = null;
143 sourceFile.forEachChild(function walk(node) {
144 if (ts.isCallExpression(node) &&
145 ts.isIdentifier(node.expression) &&
146 node.expression.text === localName) {
147 result = node;
148 }
149 if (!result) {
150 node.forEachChild(walk);
151 }
152 });
153 return result;
154}
155exports.findBootstrapApplicationCall = findBootstrapApplicationCall;
156/** Finds the `providers` array literal within an application config. */
157function findProvidersLiteral(config) {
158 var e_1, _a;
159 try {
160 for (var _b = __values(config.properties), _c = _b.next(); !_c.done; _c = _b.next()) {
161 var prop = _c.value;
162 if (ts.isPropertyAssignment(prop) &&
163 ts.isIdentifier(prop.name) &&
164 prop.name.text === 'providers' &&
165 ts.isArrayLiteralExpression(prop.initializer)) {
166 return prop.initializer;
167 }
168 }
169 }
170 catch (e_1_1) { e_1 = { error: e_1_1 }; }
171 finally {
172 try {
173 if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
174 }
175 finally { if (e_1) throw e_1.error; }
176 }
177 return null;
178}
179/**
180 * Resolves the node that defines the app config from a bootstrap call.
181 * @param bootstrapCall Call for which to resolve the config.
182 * @param tree File tree of the project.
183 * @param filePath File path of the bootstrap call.
184 */
185function findAppConfig(bootstrapCall, tree, filePath) {
186 if (bootstrapCall.arguments.length > 1) {
187 var config = bootstrapCall.arguments[1];
188 if (ts.isObjectLiteralExpression(config)) {
189 return { filePath: filePath, node: config };
190 }
191 if (ts.isIdentifier(config)) {
192 return resolveAppConfigFromIdentifier(config, tree, filePath);
193 }
194 }
195 return null;
196}
197/**
198 * Resolves the app config from an identifier referring to it.
199 * @param identifier Identifier referring to the app config.
200 * @param tree File tree of the project.
201 * @param bootstapFilePath Path of the bootstrap call.
202 */
203function resolveAppConfigFromIdentifier(identifier, tree, bootstapFilePath) {
204 var e_2, _a, e_3, _b;
205 var _c;
206 var sourceFile = identifier.getSourceFile();
207 try {
208 for (var _d = __values(sourceFile.statements), _e = _d.next(); !_e.done; _e = _d.next()) {
209 var node = _e.value;
210 // Only look at relative imports. This will break if the app uses a path
211 // mapping to refer to the import, but in order to resolve those, we would
212 // need knowledge about the entire program.
213 if (!ts.isImportDeclaration(node) ||
214 !((_c = node.importClause) === null || _c === void 0 ? void 0 : _c.namedBindings) ||
215 !ts.isNamedImports(node.importClause.namedBindings) ||
216 !ts.isStringLiteralLike(node.moduleSpecifier) ||
217 !node.moduleSpecifier.text.startsWith('.')) {
218 continue;
219 }
220 try {
221 for (var _f = (e_3 = void 0, __values(node.importClause.namedBindings.elements)), _g = _f.next(); !_g.done; _g = _f.next()) {
222 var specifier = _g.value;
223 if (specifier.name.text !== identifier.text) {
224 continue;
225 }
226 // Look for a variable with the imported name in the file. Note that ideally we would use
227 // the type checker to resolve this, but we can't because these utilities are set up to
228 // operate on individual files, not the entire program.
229 var filePath = (0, path_1.join)((0, path_1.dirname)(bootstapFilePath), node.moduleSpecifier.text + '.ts');
230 var importedSourceFile = createSourceFile(tree, filePath);
231 var resolvedVariable = findAppConfigFromVariableName(importedSourceFile, (specifier.propertyName || specifier.name).text);
232 if (resolvedVariable) {
233 return { filePath: filePath, node: resolvedVariable };
234 }
235 }
236 }
237 catch (e_3_1) { e_3 = { error: e_3_1 }; }
238 finally {
239 try {
240 if (_g && !_g.done && (_b = _f.return)) _b.call(_f);
241 }
242 finally { if (e_3) throw e_3.error; }
243 }
244 }
245 }
246 catch (e_2_1) { e_2 = { error: e_2_1 }; }
247 finally {
248 try {
249 if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
250 }
251 finally { if (e_2) throw e_2.error; }
252 }
253 var variableInSameFile = findAppConfigFromVariableName(sourceFile, identifier.text);
254 return variableInSameFile
255 ? { filePath: bootstapFilePath, node: variableInSameFile }
256 : null;
257}
258/**
259 * Finds an app config within the top-level variables of a file.
260 * @param sourceFile File in which to search for the config.
261 * @param variableName Name of the variable containing the config.
262 */
263function findAppConfigFromVariableName(sourceFile, variableName) {
264 var e_4, _a, e_5, _b;
265 try {
266 for (var _c = __values(sourceFile.statements), _d = _c.next(); !_d.done; _d = _c.next()) {
267 var node = _d.value;
268 if (ts.isVariableStatement(node)) {
269 try {
270 for (var _e = (e_5 = void 0, __values(node.declarationList.declarations)), _f = _e.next(); !_f.done; _f = _e.next()) {
271 var decl = _f.value;
272 if (ts.isIdentifier(decl.name) &&
273 decl.name.text === variableName &&
274 decl.initializer &&
275 ts.isObjectLiteralExpression(decl.initializer)) {
276 return decl.initializer;
277 }
278 }
279 }
280 catch (e_5_1) { e_5 = { error: e_5_1 }; }
281 finally {
282 try {
283 if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
284 }
285 finally { if (e_5) throw e_5.error; }
286 }
287 }
288 }
289 }
290 catch (e_4_1) { e_4 = { error: e_4_1 }; }
291 finally {
292 try {
293 if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
294 }
295 finally { if (e_4) throw e_4.error; }
296 }
297 return null;
298}
299/**
300 * Finds the local name of an imported symbol. Could be the symbol name itself or its alias.
301 * @param sourceFile File within which to search for the import.
302 * @param name Actual name of the import, not its local alias.
303 * @param moduleName Name of the module from which the symbol is imported.
304 */
305function findImportLocalName(sourceFile, name, moduleName) {
306 var e_6, _a, e_7, _b;
307 try {
308 for (var _c = __values(sourceFile.statements), _d = _c.next(); !_d.done; _d = _c.next()) {
309 var node = _d.value;
310 // Only look for top-level imports.
311 if (!ts.isImportDeclaration(node) ||
312 !ts.isStringLiteral(node.moduleSpecifier) ||
313 node.moduleSpecifier.text !== moduleName) {
314 continue;
315 }
316 // Filter out imports that don't have the right shape.
317 if (!node.importClause ||
318 !node.importClause.namedBindings ||
319 !ts.isNamedImports(node.importClause.namedBindings)) {
320 continue;
321 }
322 try {
323 // Look through the elements of the declaration for the specific import.
324 for (var _e = (e_7 = void 0, __values(node.importClause.namedBindings.elements)), _f = _e.next(); !_f.done; _f = _e.next()) {
325 var element = _f.value;
326 if ((element.propertyName || element.name).text === name) {
327 // The local name is always in `name`.
328 return element.name.text;
329 }
330 }
331 }
332 catch (e_7_1) { e_7 = { error: e_7_1 }; }
333 finally {
334 try {
335 if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
336 }
337 finally { if (e_7) throw e_7.error; }
338 }
339 }
340 }
341 catch (e_6_1) { e_6 = { error: e_6_1 }; }
342 finally {
343 try {
344 if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
345 }
346 finally { if (e_6) throw e_6.error; }
347 }
348 return null;
349}
350/** Creates a source file from a file path within a project. */
351function createSourceFile(tree, filePath) {
352 return ts.createSourceFile(filePath, tree.readText(filePath), ts.ScriptTarget.Latest, true);
353}
354/**
355 * Creates a new app config object literal and adds it to a call expression as an argument.
356 * @param call Call to which to add the config.
357 * @param expression Expression that should inserted into the new config.
358 * @param recorder Recorder to which to log the change.
359 */
360function addNewAppConfigToCall(call, expression, recorder) {
361 var newCall = ts.factory.updateCallExpression(call, call.expression, call.typeArguments, __spreadArray(__spreadArray([], __read(call.arguments), false), [
362 ts.factory.createObjectLiteralExpression([
363 ts.factory.createPropertyAssignment('providers', ts.factory.createArrayLiteralExpression([expression])),
364 ], true),
365 ], false));
366 recorder.remove(call.getStart(), call.getWidth());
367 recorder.insertRight(call.getStart(), ts
368 .createPrinter()
369 .printNode(ts.EmitHint.Unspecified, newCall, call.getSourceFile()));
370}
371/**
372 * Adds an element to an array literal expression.
373 * @param node Array to which to add the element.
374 * @param element Element to be added.
375 * @param recorder Recorder to which to log the change.
376 */
377function addElementToArray(node, element, recorder) {
378 var newLiteral = ts.factory.updateArrayLiteralExpression(node, __spreadArray(__spreadArray([], __read(node.elements), false), [
379 element,
380 ], false));
381 recorder.remove(node.getStart(), node.getWidth());
382 recorder.insertRight(node.getStart(), ts
383 .createPrinter()
384 .printNode(ts.EmitHint.Unspecified, newLiteral, node.getSourceFile()));
385}
386/**
387 * Adds a `providers` property to an object literal.
388 * @param node Literal to which to add the `providers`.
389 * @param expression Provider that should be part of the generated `providers` array.
390 * @param recorder Recorder to which to log the change.
391 */
392function addProvidersToObjectLiteral(node, expression, recorder) {
393 var newOptionsLiteral = ts.factory.updateObjectLiteralExpression(node, __spreadArray(__spreadArray([], __read(node.properties), false), [
394 ts.factory.createPropertyAssignment('providers', ts.factory.createArrayLiteralExpression([expression])),
395 ], false));
396 recorder.remove(node.getStart(), node.getWidth());
397 recorder.insertRight(node.getStart(), ts
398 .createPrinter()
399 .printNode(ts.EmitHint.Unspecified, newOptionsLiteral, node.getSourceFile()));
400}
401/** Checks whether a node is a call to `mergeApplicationConfig`. */
402function isMergeAppConfigCall(node) {
403 if (!ts.isCallExpression(node)) {
404 return false;
405 }
406 var localName = findImportLocalName(node.getSourceFile(), 'mergeApplicationConfig', '@angular/core');
407 return (!!localName &&
408 ts.isIdentifier(node.expression) &&
409 node.expression.text === localName);
410}
411//# sourceMappingURL=standalone.js.map
\No newline at end of file