1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.applyWithSkipExisting = exports.renameDirSyncInTree = exports.renameSyncInTree = exports.replaceNodeValue = exports.insertImport = exports.createOrUpdate = exports.getProjectConfig = exports.updatePackageJsonDependencies = exports.addDepsToPackageJson = exports.readWorkspace = exports.updateNxJsonInTree = exports.appsDir = exports.libsDir = exports.readNxJsonInTree = exports.updateWorkspaceInTree = exports.updateJsonInTree = exports.allFilesInDirInHost = exports.getFileDataInHost = exports.readJsonInTree = exports.insert = exports.addGlobal = exports.getImport = exports.addIncludeToTsConfig = exports.offset = exports.findClass = exports.addMethod = exports.addParameterToConstructor = exports.ReplaceChange = exports.RemoveChange = exports.InsertChange = exports.NoopChange = exports.getSourceNodes = exports.findNodes = exports.sortObjectByKeys = void 0;
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 | const schematics_1 = require("@angular-devkit/schematics");
|
12 | const ts = require("typescript");
|
13 | const devkit_1 = require("@nrwl/devkit");
|
14 | const cli_config_utils_1 = require("./cli-config-utils");
|
15 | const core_1 = require("@angular-devkit/core");
|
16 | const add_install_task_1 = require("./rules/add-install-task");
|
17 | const find_nodes_1 = require("../utilities/typescript/find-nodes");
|
18 | const get_source_nodes_1 = require("../utilities/typescript/get-source-nodes");
|
19 | function nodesByPosition(first, second) {
|
20 | return first.getStart() - second.getStart();
|
21 | }
|
22 | function insertAfterLastOccurrence(nodes, toInsert, file, fallbackPos, syntaxKind) {
|
23 |
|
24 | let lastItem = [...nodes].sort(nodesByPosition).pop();
|
25 | if (!lastItem) {
|
26 | throw new Error();
|
27 | }
|
28 | if (syntaxKind) {
|
29 | lastItem = (0, find_nodes_1.findNodes)(lastItem, syntaxKind).sort(nodesByPosition).pop();
|
30 | }
|
31 | if (!lastItem && fallbackPos == undefined) {
|
32 | throw new Error(`tried to insert ${toInsert} as first occurrence with no fallback position`);
|
33 | }
|
34 | const lastItemPosition = lastItem ? lastItem.getEnd() : fallbackPos;
|
35 | return new InsertChange(file, lastItemPosition, toInsert);
|
36 | }
|
37 | function sortObjectByKeys(obj) {
|
38 | return Object.keys(obj)
|
39 | .sort()
|
40 | .reduce((result, key) => {
|
41 | return Object.assign(Object.assign({}, result), { [key]: obj[key] });
|
42 | }, {});
|
43 | }
|
44 | exports.sortObjectByKeys = sortObjectByKeys;
|
45 | var find_nodes_2 = require("../utilities/typescript/find-nodes");
|
46 | Object.defineProperty(exports, "findNodes", { enumerable: true, get: function () { return find_nodes_2.findNodes; } });
|
47 | var get_source_nodes_2 = require("../utilities/typescript/get-source-nodes");
|
48 | Object.defineProperty(exports, "getSourceNodes", { enumerable: true, get: function () { return get_source_nodes_2.getSourceNodes; } });
|
49 | class NoopChange {
|
50 | constructor() {
|
51 | this.type = 'noop';
|
52 | this.description = 'No operation.';
|
53 | this.order = Infinity;
|
54 | this.path = null;
|
55 | }
|
56 | apply() {
|
57 | return Promise.resolve();
|
58 | }
|
59 | }
|
60 | exports.NoopChange = NoopChange;
|
61 | class InsertChange {
|
62 | constructor(path, pos, toAdd) {
|
63 | this.path = path;
|
64 | this.pos = pos;
|
65 | this.toAdd = toAdd;
|
66 | this.type = 'insert';
|
67 | if (pos < 0) {
|
68 | throw new Error('Negative positions are invalid');
|
69 | }
|
70 | this.description = `Inserted ${toAdd} into position ${pos} of ${path}`;
|
71 | this.order = pos;
|
72 | }
|
73 | apply(host) {
|
74 | return host.read(this.path).then((content) => {
|
75 | const prefix = content.substring(0, this.pos);
|
76 | const suffix = content.substring(this.pos);
|
77 | return host.write(this.path, `${prefix}${this.toAdd}${suffix}`);
|
78 | });
|
79 | }
|
80 | }
|
81 | exports.InsertChange = InsertChange;
|
82 | class RemoveChange {
|
83 | constructor(path, pos, toRemove) {
|
84 | this.path = path;
|
85 | this.pos = pos;
|
86 | this.toRemove = toRemove;
|
87 | this.type = 'remove';
|
88 | if (pos < 0) {
|
89 | throw new Error('Negative positions are invalid');
|
90 | }
|
91 | this.description = `Removed ${toRemove} into position ${pos} of ${path}`;
|
92 | this.order = pos;
|
93 | }
|
94 | apply(host) {
|
95 | return host.read(this.path).then((content) => {
|
96 | const prefix = content.substring(0, this.pos);
|
97 | const suffix = content.substring(this.pos + this.toRemove.length);
|
98 | return host.write(this.path, `${prefix}${suffix}`);
|
99 | });
|
100 | }
|
101 | }
|
102 | exports.RemoveChange = RemoveChange;
|
103 | class ReplaceChange {
|
104 | constructor(path, pos, oldText, newText) {
|
105 | this.path = path;
|
106 | this.pos = pos;
|
107 | this.oldText = oldText;
|
108 | this.newText = newText;
|
109 | this.type = 'replace';
|
110 | if (pos < 0) {
|
111 | throw new Error('Negative positions are invalid');
|
112 | }
|
113 | this.description = `Replaced ${oldText} into position ${pos} of ${path} with ${newText}`;
|
114 | this.order = pos;
|
115 | }
|
116 | apply(host) {
|
117 | return host.read(this.path).then((content) => {
|
118 | const prefix = content.substring(0, this.pos);
|
119 | const suffix = content.substring(this.pos + this.oldText.length);
|
120 | const text = content.substring(this.pos, this.pos + this.oldText.length);
|
121 | if (text !== this.oldText) {
|
122 | return Promise.reject(new Error(`Invalid replace: "${text}" != "${this.oldText}".`));
|
123 | }
|
124 | return host.write(this.path, `${prefix}${this.newText}${suffix}`);
|
125 | });
|
126 | }
|
127 | }
|
128 | exports.ReplaceChange = ReplaceChange;
|
129 | function addParameterToConstructor(source, modulePath, opts) {
|
130 | const clazz = findClass(source, opts.className);
|
131 | const constructor = clazz.members.filter((m) => m.kind === ts.SyntaxKind.Constructor)[0];
|
132 | if (constructor) {
|
133 | throw new Error('Should be tested');
|
134 | }
|
135 | else {
|
136 | const methodHeader = `constructor(${opts.param})`;
|
137 | return addMethod(source, modulePath, {
|
138 | className: opts.className,
|
139 | methodHeader,
|
140 | body: null,
|
141 | });
|
142 | }
|
143 | }
|
144 | exports.addParameterToConstructor = addParameterToConstructor;
|
145 | function addMethod(source, modulePath, opts) {
|
146 | const clazz = findClass(source, opts.className);
|
147 | const body = opts.body
|
148 | ? `
|
149 | ${opts.methodHeader} {
|
150 | ${offset(opts.body, 1, false)}
|
151 | }
|
152 | `
|
153 | : `
|
154 | ${opts.methodHeader} {}
|
155 | `;
|
156 | return [new InsertChange(modulePath, clazz.end - 1, offset(body, 1, true))];
|
157 | }
|
158 | exports.addMethod = addMethod;
|
159 | function findClass(source, className, silent = false) {
|
160 | const nodes = (0, get_source_nodes_1.getSourceNodes)(source);
|
161 | const clazz = (nodes.filter((n) => n.kind === ts.SyntaxKind.ClassDeclaration &&
|
162 | n.name.text === className)[0]);
|
163 | if (!clazz && !silent) {
|
164 | throw new Error(`Cannot find class '${className}'`);
|
165 | }
|
166 | return clazz;
|
167 | }
|
168 | exports.findClass = findClass;
|
169 | function offset(text, numberOfTabs, wrap) {
|
170 | const lines = text
|
171 | .trim()
|
172 | .split('\n')
|
173 | .map((line) => {
|
174 | let tabs = '';
|
175 | for (let c = 0; c < numberOfTabs; ++c) {
|
176 | tabs += ' ';
|
177 | }
|
178 | return `${tabs}${line}`;
|
179 | })
|
180 | .join('\n');
|
181 | return wrap ? `\n${lines}\n` : lines;
|
182 | }
|
183 | exports.offset = offset;
|
184 | function addIncludeToTsConfig(tsConfigPath, source, include) {
|
185 | const includeKeywordPos = source.text.indexOf('"include":');
|
186 | if (includeKeywordPos > -1) {
|
187 | const includeArrayEndPos = source.text.indexOf(']', includeKeywordPos);
|
188 | return [new InsertChange(tsConfigPath, includeArrayEndPos, include)];
|
189 | }
|
190 | else {
|
191 | return [];
|
192 | }
|
193 | }
|
194 | exports.addIncludeToTsConfig = addIncludeToTsConfig;
|
195 | function getImport(source, predicate) {
|
196 | const allImports = (0, find_nodes_1.findNodes)(source, ts.SyntaxKind.ImportDeclaration);
|
197 | const matching = allImports.filter((i) => predicate(i.moduleSpecifier.getText()));
|
198 | return matching.map((i) => {
|
199 | const moduleSpec = i.moduleSpecifier
|
200 | .getText()
|
201 | .substring(1, i.moduleSpecifier.getText().length - 1);
|
202 | const t = i.importClause.namedBindings.getText();
|
203 | const bindings = t
|
204 | .replace('{', '')
|
205 | .replace('}', '')
|
206 | .split(',')
|
207 | .map((q) => q.trim());
|
208 | return { moduleSpec, bindings };
|
209 | });
|
210 | }
|
211 | exports.getImport = getImport;
|
212 | function addGlobal(source, modulePath, statement) {
|
213 | const allImports = (0, find_nodes_1.findNodes)(source, ts.SyntaxKind.ImportDeclaration);
|
214 | if (allImports.length > 0) {
|
215 | const lastImport = allImports[allImports.length - 1];
|
216 | return [
|
217 | new InsertChange(modulePath, lastImport.end + 1, `\n${statement}\n`),
|
218 | ];
|
219 | }
|
220 | else {
|
221 | return [new InsertChange(modulePath, 0, `${statement}\n`)];
|
222 | }
|
223 | }
|
224 | exports.addGlobal = addGlobal;
|
225 | function insert(host, modulePath, changes) {
|
226 | if (changes.length < 1) {
|
227 | return;
|
228 | }
|
229 |
|
230 | const orderedChanges = changes.sort((a, b) => b.order - a.order);
|
231 | const recorder = host.beginUpdate(modulePath);
|
232 | for (const change of orderedChanges) {
|
233 | if (change.type == 'insert') {
|
234 | recorder.insertLeft(change.pos, change.toAdd);
|
235 | }
|
236 | else if (change.type == 'remove') {
|
237 | recorder.remove(change.pos - 1, change.toRemove.length + 1);
|
238 | }
|
239 | else if (change.type == 'replace') {
|
240 | recorder.remove(change.pos, change.oldText.length);
|
241 | recorder.insertLeft(change.pos, change.newText);
|
242 | }
|
243 | else if (change.type === 'noop') {
|
244 |
|
245 | }
|
246 | else {
|
247 | throw new Error(`Unexpected Change '${change.constructor.name}'`);
|
248 | }
|
249 | }
|
250 | host.commitUpdate(recorder);
|
251 | }
|
252 | exports.insert = insert;
|
253 |
|
254 |
|
255 |
|
256 |
|
257 |
|
258 |
|
259 | function readJsonInTree(host, path) {
|
260 | if (!host.exists(path)) {
|
261 | throw new Error(`Cannot find ${path}`);
|
262 | }
|
263 | try {
|
264 | return (0, devkit_1.parseJson)(host.read(path).toString('utf-8'));
|
265 | }
|
266 | catch (e) {
|
267 | throw new Error(`Cannot parse ${path}: ${e.message}`);
|
268 | }
|
269 | }
|
270 | exports.readJsonInTree = readJsonInTree;
|
271 |
|
272 |
|
273 |
|
274 |
|
275 | function getFileDataInHost(host, path) {
|
276 | return {
|
277 | file: path,
|
278 | ext: (0, core_1.extname)((0, core_1.normalize)(path)),
|
279 | hash: '',
|
280 | };
|
281 | }
|
282 | exports.getFileDataInHost = getFileDataInHost;
|
283 | function allFilesInDirInHost(host, path, options = { recursive: true }) {
|
284 | const dir = host.getDir(path);
|
285 | const res = [];
|
286 | dir.subfiles.forEach((p) => {
|
287 | res.push((0, core_1.join)(path, p));
|
288 | });
|
289 | if (!options.recursive) {
|
290 | return res;
|
291 | }
|
292 | dir.subdirs.forEach((p) => {
|
293 | res.push(...allFilesInDirInHost(host, (0, core_1.join)(path, p)));
|
294 | });
|
295 | return res;
|
296 | }
|
297 | exports.allFilesInDirInHost = allFilesInDirInHost;
|
298 |
|
299 |
|
300 |
|
301 |
|
302 |
|
303 |
|
304 | function updateJsonInTree(path, callback) {
|
305 | return (host, context) => {
|
306 | if (!host.exists(path)) {
|
307 | host.create(path, (0, devkit_1.serializeJson)(callback({}, context)));
|
308 | return host;
|
309 | }
|
310 | host.overwrite(path, (0, devkit_1.serializeJson)(callback(readJsonInTree(host, path), context)));
|
311 | return host;
|
312 | };
|
313 | }
|
314 | exports.updateJsonInTree = updateJsonInTree;
|
315 | function updateWorkspaceInTree(callback) {
|
316 | return (host, context = undefined) => {
|
317 | const path = (0, cli_config_utils_1.getWorkspacePath)(host);
|
318 | host.overwrite(path, (0, devkit_1.serializeJson)(callback(readJsonInTree(host, path), context, host)));
|
319 | return host;
|
320 | };
|
321 | }
|
322 | exports.updateWorkspaceInTree = updateWorkspaceInTree;
|
323 | function readNxJsonInTree(host) {
|
324 | return readJsonInTree(host, 'nx.json');
|
325 | }
|
326 | exports.readNxJsonInTree = readNxJsonInTree;
|
327 | function libsDir(host) {
|
328 | var _a, _b;
|
329 | const json = readJsonInTree(host, 'nx.json');
|
330 | return (_b = (_a = json === null || json === void 0 ? void 0 : json.workspaceLayout) === null || _a === void 0 ? void 0 : _a.libsDir) !== null && _b !== void 0 ? _b : 'libs';
|
331 | }
|
332 | exports.libsDir = libsDir;
|
333 | function appsDir(host) {
|
334 | var _a, _b;
|
335 | const json = readJsonInTree(host, 'nx.json');
|
336 | return (_b = (_a = json === null || json === void 0 ? void 0 : json.workspaceLayout) === null || _a === void 0 ? void 0 : _a.appsDir) !== null && _b !== void 0 ? _b : 'apps';
|
337 | }
|
338 | exports.appsDir = appsDir;
|
339 | function updateNxJsonInTree(callback) {
|
340 | return (host, context) => {
|
341 | host.overwrite('nx.json', (0, devkit_1.serializeJson)(callback(readJsonInTree(host, 'nx.json'), context)));
|
342 | return host;
|
343 | };
|
344 | }
|
345 | exports.updateNxJsonInTree = updateNxJsonInTree;
|
346 | function readWorkspace(host) {
|
347 | const path = (0, cli_config_utils_1.getWorkspacePath)(host);
|
348 | return readJsonInTree(host, path);
|
349 | }
|
350 | exports.readWorkspace = readWorkspace;
|
351 |
|
352 |
|
353 |
|
354 |
|
355 | function requiresAddingOfPackages(packageJsonFile, deps, devDeps) {
|
356 | let needsDepsUpdate = false;
|
357 | let needsDevDepsUpdate = false;
|
358 | packageJsonFile.dependencies = packageJsonFile.dependencies || {};
|
359 | packageJsonFile.devDependencies = packageJsonFile.devDependencies || {};
|
360 | if (Object.keys(deps).length > 0) {
|
361 | needsDepsUpdate = Object.keys(deps).some((entry) => !packageJsonFile.dependencies[entry]);
|
362 | }
|
363 | if (Object.keys(devDeps).length > 0) {
|
364 | needsDevDepsUpdate = Object.keys(devDeps).some((entry) => !packageJsonFile.devDependencies[entry]);
|
365 | }
|
366 | return needsDepsUpdate || needsDevDepsUpdate;
|
367 | }
|
368 |
|
369 |
|
370 |
|
371 |
|
372 |
|
373 |
|
374 |
|
375 |
|
376 | function addDepsToPackageJson(deps, devDeps, addInstall = true) {
|
377 | return (host, context) => {
|
378 | const currentPackageJson = readJsonInTree(host, 'package.json');
|
379 | if (requiresAddingOfPackages(currentPackageJson, deps, devDeps)) {
|
380 | return (0, schematics_1.chain)([
|
381 | updateJsonInTree('package.json', (json, context) => {
|
382 | json.dependencies = Object.assign(Object.assign(Object.assign({}, (json.dependencies || {})), deps), (json.dependencies || {}));
|
383 | json.devDependencies = Object.assign(Object.assign(Object.assign({}, (json.devDependencies || {})), devDeps), (json.devDependencies || {}));
|
384 | json.dependencies = sortObjectByKeys(json.dependencies);
|
385 | json.devDependencies = sortObjectByKeys(json.devDependencies);
|
386 | return json;
|
387 | }),
|
388 | (0, add_install_task_1.addInstallTask)({
|
389 | skipInstall: !addInstall,
|
390 | }),
|
391 | ]);
|
392 | }
|
393 | else {
|
394 | return (0, schematics_1.noop)();
|
395 | }
|
396 | };
|
397 | }
|
398 | exports.addDepsToPackageJson = addDepsToPackageJson;
|
399 | function updatePackageJsonDependencies(deps, devDeps, addInstall = true) {
|
400 | return (0, schematics_1.chain)([
|
401 | updateJsonInTree('package.json', (json, context) => {
|
402 | json.dependencies = Object.assign(Object.assign({}, (json.dependencies || {})), deps);
|
403 | json.devDependencies = Object.assign(Object.assign({}, (json.devDependencies || {})), devDeps);
|
404 | json.dependencies = sortObjectByKeys(json.dependencies);
|
405 | json.devDependencies = sortObjectByKeys(json.devDependencies);
|
406 | return json;
|
407 | }),
|
408 | (0, add_install_task_1.addInstallTask)({
|
409 | skipInstall: !addInstall,
|
410 | }),
|
411 | ]);
|
412 | }
|
413 | exports.updatePackageJsonDependencies = updatePackageJsonDependencies;
|
414 | function getProjectConfig(host, name) {
|
415 | const workspaceJson = readJsonInTree(host, (0, cli_config_utils_1.getWorkspacePath)(host));
|
416 | const projectConfig = workspaceJson.projects[name];
|
417 | if (!projectConfig) {
|
418 | throw new Error(`Cannot find project '${name}'`);
|
419 | }
|
420 | else if (typeof projectConfig === 'string') {
|
421 | return readJsonInTree(host, projectConfig);
|
422 | }
|
423 | else {
|
424 | return projectConfig;
|
425 | }
|
426 | }
|
427 | exports.getProjectConfig = getProjectConfig;
|
428 | function createOrUpdate(host, path, content) {
|
429 | if (host.exists(path)) {
|
430 | host.overwrite(path, content);
|
431 | }
|
432 | else {
|
433 | host.create(path, content);
|
434 | }
|
435 | }
|
436 | exports.createOrUpdate = createOrUpdate;
|
437 | function insertImport(source, fileToEdit, symbolName, fileName, isDefault = false) {
|
438 | const rootNode = source;
|
439 | const allImports = (0, find_nodes_1.findNodes)(rootNode, ts.SyntaxKind.ImportDeclaration);
|
440 |
|
441 | const relevantImports = allImports.filter((node) => {
|
442 |
|
443 | const importFiles = node
|
444 | .getChildren()
|
445 | .filter((child) => child.kind === ts.SyntaxKind.StringLiteral)
|
446 | .map((n) => n.text);
|
447 | return importFiles.filter((file) => file === fileName).length === 1;
|
448 | });
|
449 | if (relevantImports.length > 0) {
|
450 | let importsAsterisk = false;
|
451 |
|
452 | const imports = [];
|
453 | relevantImports.forEach((n) => {
|
454 | Array.prototype.push.apply(imports, (0, find_nodes_1.findNodes)(n, ts.SyntaxKind.Identifier));
|
455 | if ((0, find_nodes_1.findNodes)(n, ts.SyntaxKind.AsteriskToken).length > 0) {
|
456 | importsAsterisk = true;
|
457 | }
|
458 | });
|
459 |
|
460 | if (importsAsterisk) {
|
461 | return new NoopChange();
|
462 | }
|
463 | const importTextNodes = imports.filter((n) => n.text === symbolName);
|
464 |
|
465 | if (importTextNodes.length === 0) {
|
466 | const fallbackPos = (0, find_nodes_1.findNodes)(relevantImports[0], ts.SyntaxKind.CloseBraceToken)[0].getStart() ||
|
467 | (0, find_nodes_1.findNodes)(relevantImports[0], ts.SyntaxKind.FromKeyword)[0].getStart();
|
468 | return insertAfterLastOccurrence(imports, `, ${symbolName}`, fileToEdit, fallbackPos);
|
469 | }
|
470 | return new NoopChange();
|
471 | }
|
472 |
|
473 | const useStrict = (0, find_nodes_1.findNodes)(rootNode, ts.SyntaxKind.StringLiteral).filter((n) => n.text === 'use strict');
|
474 | let fallbackPos = 0;
|
475 | if (useStrict.length > 0) {
|
476 | fallbackPos = useStrict[0].end;
|
477 | }
|
478 | const open = isDefault ? '' : '{ ';
|
479 | const close = isDefault ? '' : ' }';
|
480 |
|
481 | const insertAtBeginning = allImports.length === 0 && useStrict.length === 0;
|
482 | const separator = insertAtBeginning ? '' : ';\n';
|
483 | const toInsert = `${separator}import ${open}${symbolName}${close}` +
|
484 | ` from '${fileName}'${insertAtBeginning ? ';\n' : ''}`;
|
485 | return insertAfterLastOccurrence(allImports, toInsert, fileToEdit, fallbackPos, ts.SyntaxKind.StringLiteral);
|
486 | }
|
487 | exports.insertImport = insertImport;
|
488 | function replaceNodeValue(host, modulePath, node, content) {
|
489 | insert(host, modulePath, [
|
490 | new ReplaceChange(modulePath, node.getStart(node.getSourceFile()), node.getFullText(), content),
|
491 | ]);
|
492 | }
|
493 | exports.replaceNodeValue = replaceNodeValue;
|
494 | function renameSyncInTree(tree, from, to, cb) {
|
495 | if (!tree.exists(from)) {
|
496 | cb(`Path: ${from} does not exist`);
|
497 | }
|
498 | else if (tree.exists(to)) {
|
499 | cb(`Path: ${to} already exists`);
|
500 | }
|
501 | else {
|
502 | renameFile(tree, from, to);
|
503 | cb(null);
|
504 | }
|
505 | }
|
506 | exports.renameSyncInTree = renameSyncInTree;
|
507 | function renameDirSyncInTree(tree, from, to, cb) {
|
508 | const dir = tree.getDir(from);
|
509 | if (!dirExists(dir)) {
|
510 | cb(`Path: ${from} does not exist`);
|
511 | return;
|
512 | }
|
513 | dir.visit((path) => {
|
514 | const destination = path.replace(from, to);
|
515 | renameFile(tree, path, destination);
|
516 | });
|
517 | cb(null);
|
518 | }
|
519 | exports.renameDirSyncInTree = renameDirSyncInTree;
|
520 | function dirExists(dir) {
|
521 | return dir.subdirs.length + dir.subfiles.length !== 0;
|
522 | }
|
523 | function renameFile(tree, from, to) {
|
524 | const buffer = tree.read(from);
|
525 | if (!buffer) {
|
526 | return;
|
527 | }
|
528 | tree.create(to, buffer);
|
529 | tree.delete(from);
|
530 | }
|
531 |
|
532 |
|
533 |
|
534 | function applyWithSkipExisting(source, rules) {
|
535 | return (tree, _context) => {
|
536 | const rule = (0, schematics_1.mergeWith)((0, schematics_1.apply)(source, [
|
537 | ...rules,
|
538 | (0, schematics_1.forEach)((fileEntry) => {
|
539 | if (tree.exists(fileEntry.path)) {
|
540 | return null;
|
541 | }
|
542 | return fileEntry;
|
543 | }),
|
544 | ]));
|
545 | return rule(tree, _context);
|
546 | };
|
547 | }
|
548 | exports.applyWithSkipExisting = applyWithSkipExisting;
|
549 |
|
\ | No newline at end of file |