UNPKG

10.9 kBJavaScriptView Raw
1"use strict";
2// inspired by:
3// https://github.com/angular/angular-cli/blob/d202480a1707be6575b2c8cf0383cfe6db44413c/packages/schematics/angular/utility/ast-utils.ts
4// https://github.com/angular/angular-cli/blob/d202480a1707be6575b2c8cf0383cfe6db44413c/packages/schematics/angular/utility/ng-ast-utils.ts
5// https://github.com/NativeScript/nativescript-schematics/blob/438b9e3ef613389980bfa9d071e28ca1f32ab04f/src/ast-utils.ts
6Object.defineProperty(exports, "__esModule", { value: true });
7const path_1 = require("path");
8const ts = require("typescript");
9const transformers_1 = require("@ngtools/webpack/src/transformers");
10const ast_utils_1 = require("../utils/ast-utils");
11const transformers_utils_1 = require("../utils/transformers-utils");
12function nsReplaceLazyLoader(getNgCompiler) {
13 const getTypeChecker = () => getNgCompiler().typeChecker;
14 const standardTransform = function (sourceFile) {
15 let ops = [];
16 const entryModule = transformers_utils_1.getResolvedEntryModule(getNgCompiler());
17 const sourceFilePath = path_1.join(path_1.dirname(sourceFile.fileName), path_1.basename(sourceFile.fileName, path_1.extname(sourceFile.fileName)));
18 if (!entryModule || path_1.normalize(sourceFilePath) !== path_1.normalize(entryModule.path)) {
19 return ops;
20 }
21 try {
22 ops = addArrayPropertyValueToNgModule(sourceFile, "providers", "NgModuleFactoryLoader", "{ provide: nsNgCoreImport_Generated.NgModuleFactoryLoader, useClass: NSLazyModulesLoader_Generated }") || [];
23 }
24 catch (e) {
25 ops = [];
26 }
27 return ops;
28 };
29 return transformers_1.makeTransform(standardTransform, getTypeChecker);
30}
31exports.nsReplaceLazyLoader = nsReplaceLazyLoader;
32function addArrayPropertyValueToNgModule(sourceFile, targetPropertyName, newPropertyValueMatch, newPropertyValue) {
33 const ngModuleConfigNodesInFile = ast_utils_1.getDecoratorMetadata(sourceFile, "NgModule", "@angular/core");
34 let ngModuleConfigNode = ngModuleConfigNodesInFile && ngModuleConfigNodesInFile[0];
35 if (!ngModuleConfigNode) {
36 return null;
37 }
38 const importsInFile = transformers_1.collectDeepNodes(sourceFile, ts.SyntaxKind.ImportDeclaration);
39 const lastImport = importsInFile && importsInFile[importsInFile.length - 1];
40 if (!lastImport) {
41 return null;
42 }
43 const ngLazyLoaderNode = ts.createIdentifier(exports.NgLazyLoaderCode);
44 if (ngModuleConfigNode.kind === ts.SyntaxKind.Identifier) {
45 const ngModuleConfigIndentifierNode = ngModuleConfigNode;
46 // cases like @NgModule(myCoolConfig)
47 const configObjectDeclarationNodes = transformers_1.collectDeepNodes(sourceFile, ts.SyntaxKind.VariableStatement).filter(imp => {
48 return ast_utils_1.findIdentifierNode(imp, ngModuleConfigIndentifierNode.getText());
49 });
50 // will be undefined when the object is imported from another file
51 const configObjectDeclaration = (configObjectDeclarationNodes && configObjectDeclarationNodes[0]);
52 const configObjectName = ngModuleConfigIndentifierNode.escapedText.trim();
53 const configObjectSetupCode = getConfigObjectSetupCode(configObjectName, targetPropertyName, newPropertyValueMatch, newPropertyValue);
54 const configObjectSetupNode = ts.createIdentifier(configObjectSetupCode);
55 return [
56 new transformers_1.AddNodeOperation(sourceFile, lastImport, undefined, ngLazyLoaderNode),
57 new transformers_1.AddNodeOperation(sourceFile, configObjectDeclaration || lastImport, undefined, configObjectSetupNode)
58 ];
59 }
60 else if (ngModuleConfigNode.kind === ts.SyntaxKind.ObjectLiteralExpression) {
61 // cases like @NgModule({ bootstrap: ... })
62 const ngModuleConfigObjectNode = ngModuleConfigNode;
63 const matchingProperties = ast_utils_1.getObjectPropertyMatches(ngModuleConfigObjectNode, sourceFile, targetPropertyName);
64 if (!matchingProperties) {
65 // invalid object
66 return null;
67 }
68 if (matchingProperties.length === 0) {
69 if (ngModuleConfigObjectNode.properties.length === 0) {
70 // empty object @NgModule({ })
71 return null;
72 }
73 // the target field is missing, we will insert it @NgModule({ otherProps })
74 const lastConfigObjPropertyNode = ngModuleConfigObjectNode.properties[ngModuleConfigObjectNode.properties.length - 1];
75 const newTargetPropertyNode = ts.createIdentifier(`${targetPropertyName}: [${newPropertyValue}]`);
76 return [
77 new transformers_1.AddNodeOperation(sourceFile, lastConfigObjPropertyNode, undefined, newTargetPropertyNode),
78 new transformers_1.AddNodeOperation(sourceFile, lastImport, undefined, ngLazyLoaderNode)
79 ];
80 }
81 // the target property is found
82 const targetPropertyNode = matchingProperties[0];
83 if (targetPropertyNode.initializer.kind !== ts.SyntaxKind.ArrayLiteralExpression) {
84 // not an array
85 return null;
86 }
87 const targetPropertyValuesNode = targetPropertyNode.initializer;
88 const targetPropertyValues = targetPropertyValuesNode.elements;
89 if (targetPropertyValues.length > 0) {
90 // @NgModule({ targetProperty: [ someValues ] })
91 const targetPropertyValuesStrings = targetPropertyValues.map(node => node.getText());
92 const wholeWordPropValueRegex = new RegExp("\\b" + newPropertyValueMatch + "\\b");
93 if (targetPropertyValuesStrings.some(((value) => wholeWordPropValueRegex.test(value)))) {
94 // already registered
95 return null;
96 }
97 const lastPropertyValueNode = targetPropertyValues[targetPropertyValues.length - 1];
98 const newPropertyValueNode = ts.createIdentifier(`${newPropertyValue}`);
99 return [
100 new transformers_1.AddNodeOperation(sourceFile, lastPropertyValueNode, undefined, newPropertyValueNode),
101 new transformers_1.AddNodeOperation(sourceFile, lastImport, undefined, ngLazyLoaderNode)
102 ];
103 }
104 else {
105 // empty array @NgModule({ targetProperty: [ ] })
106 const newTargetPropertyValuesNode = ts.createIdentifier(`[${newPropertyValue}]`);
107 return [
108 new transformers_1.ReplaceNodeOperation(sourceFile, targetPropertyValuesNode, newTargetPropertyValuesNode),
109 new transformers_1.AddNodeOperation(sourceFile, lastImport, undefined, ngLazyLoaderNode)
110 ];
111 }
112 }
113}
114exports.addArrayPropertyValueToNgModule = addArrayPropertyValueToNgModule;
115// handles cases like @NgModule(myCoolConfig) by returning a code snippet for processing
116// the config object and configuring its {{targetPropertyName}} based on the specified arguments
117// e.g.
118// if (!myCoolConfig.providers) {
119// myCoolConfig.providers = [];
120// }
121// if (Array.isArray(myCoolConfig.providers)) {
122// var wholeWordPropertyRegex = new RegExp("\bNgModuleFactoryLoader\b");
123// if (!myCoolConfig.providers.some(function (property) { return wholeWordPropertyRegex.test(property); })) {
124// myCoolConfig.providers.push({ provide: nsNgCoreImport_Generated.NgModuleFactoryLoader, useClass: NSLazyModulesLoader_Generated });
125// }
126// }
127function getConfigObjectSetupCode(configObjectName, targetPropertyName, newPropertyValueMatch, newPropertyValue) {
128 return `
129if (!${configObjectName}.${targetPropertyName}) {
130 ${configObjectName}.${targetPropertyName} = [];
131}
132if (Array.isArray(${configObjectName}.${targetPropertyName})) {
133 var wholeWordPropertyRegex = new RegExp("\\b${newPropertyValueMatch}\\b");
134 if (!${configObjectName}.${targetPropertyName}.some(function (property) { return wholeWordPropertyRegex.test(property); })) {
135 ${configObjectName}.${targetPropertyName}.push(${newPropertyValue});
136 }
137}
138`;
139}
140exports.getConfigObjectSetupCode = getConfigObjectSetupCode;
141// based on: https://github.com/angular/angular/blob/4c2ce4e8ba4c5ac5ce8754d67bc6603eaad4564a/packages/core/src/linker/system_js_ng_module_factory_loader.ts
142// when @angular/core is an external module, this fixes https://github.com/NativeScript/nativescript-cli/issues/4024 by including the lazy loader INSIDE the bundle allowing it to access the lazy modules
143exports.NgLazyLoaderCode = `
144var nsNgCoreImport_Generated = require("@angular/core");
145var NSLazyModulesLoader_Generated = /** @class */ (function () {
146 function NSLazyModulesLoader_Generated(_compiler, config) {
147 this._compiler = _compiler;
148 this._config = config || {
149 factoryPathPrefix: '',
150 factoryPathSuffix: '.ngfactory',
151 };
152 }
153 NSLazyModulesLoader_Generated.prototype.load = function (path) {
154 var offlineMode = this._compiler instanceof nsNgCoreImport_Generated.Compiler;
155 return offlineMode ? this.loadFactory(path) : this.loadAndCompile(path);
156 };
157 NSLazyModulesLoader_Generated.prototype.loadAndCompile = function (path) {
158 var _this = this;
159 var _a = path.split('#'), module = _a[0], exportName = _a[1];
160 if (exportName === undefined) {
161 exportName = 'default';
162 }
163 return import(module)
164 .then(function (module) { return module[exportName]; })
165 .then(function (type) { return _this.checkNotEmpty(type, module, exportName); })
166 .then(function (type) { return _this._compiler.compileModuleAsync(type); });
167 };
168 NSLazyModulesLoader_Generated.prototype.loadFactory = function (path) {
169 var _this = this;
170 var _a = path.split('#'), module = _a[0], exportName = _a[1];
171 var factoryClassSuffix = 'NgFactory';
172 if (exportName === undefined) {
173 exportName = 'default';
174 factoryClassSuffix = '';
175 }
176 return import(this._config.factoryPathPrefix + module + this._config.factoryPathSuffix)
177 .then(function (module) { return module[exportName + factoryClassSuffix]; })
178 .then(function (factory) { return _this.checkNotEmpty(factory, module, exportName); });
179 };
180 NSLazyModulesLoader_Generated.prototype.checkNotEmpty = function (value, modulePath, exportName) {
181 if (!value) {
182 throw new Error("Cannot find '" + exportName + "' in '" + modulePath + "'");
183 }
184 return value;
185 };
186 NSLazyModulesLoader_Generated = __decorate([
187 nsNgCoreImport_Generated.Injectable(),
188 __param(1, nsNgCoreImport_Generated.Optional()),
189 __metadata("design:paramtypes", [nsNgCoreImport_Generated.Compiler, nsNgCoreImport_Generated.SystemJsNgModuleLoaderConfig])
190 ], NSLazyModulesLoader_Generated);
191 return NSLazyModulesLoader_Generated;
192}());
193`;
194//# sourceMappingURL=ns-replace-lazy-loader.js.map
\No newline at end of file