@angular-devkit/schematics 14.0.0-next.7 → 14.0.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/README.md CHANGED
@@ -23,7 +23,7 @@ What distinguishes Schematics from other generators, such as Yeoman or Yarn Crea
23
23
 
24
24
  # Tooling
25
25
 
26
- Schematics is a library, and does not work by itself. A [reference CLI](https://github.com/angular/angular-cli/blob/master/packages/angular_devkit/schematics_cli/bin/schematics.ts) is available on this repository, and is published on NPM at [@angular-devkit/schematics-cli](https://www.npmjs.com/package/@angular-devkit/schematics-cli). This document explains the library usage and the tooling API, but does not go into the tool implementation itself.
26
+ Schematics is a library, and does not work by itself. A [reference CLI](https://github.com/angular/angular-cli/blob/main/packages/angular_devkit/schematics_cli/bin/schematics.ts) is available on this repository, and is published on NPM at [@angular-devkit/schematics-cli](https://www.npmjs.com/package/@angular-devkit/schematics-cli). This document explains the library usage and the tooling API, but does not go into the tool implementation itself.
27
27
 
28
28
  The tooling is responsible for the following tasks:
29
29
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@angular-devkit/schematics",
3
- "version": "14.0.0-next.7",
3
+ "version": "14.0.0-rc.0",
4
4
  "description": "Angular Schematics - Library",
5
5
  "main": "src/index.js",
6
6
  "typings": "src/index.d.ts",
@@ -18,7 +18,7 @@
18
18
  "schematics"
19
19
  ],
20
20
  "dependencies": {
21
- "@angular-devkit/core": "14.0.0-next.7",
21
+ "@angular-devkit/core": "14.0.0-rc.0",
22
22
  "jsonc-parser": "3.0.0",
23
23
  "magic-string": "0.26.1",
24
24
  "ora": "5.4.1",
@@ -54,7 +54,7 @@ export declare class TaskScheduler {
54
54
  constructor(_context: SchematicContext);
55
55
  private _calculatePriority;
56
56
  private _mapDependencies;
57
- schedule<T>(taskConfiguration: TaskConfiguration<T>): TaskId;
57
+ schedule<T extends object>(taskConfiguration: TaskConfiguration<T>): TaskId;
58
58
  finalize(): ReadonlyArray<TaskInfo>;
59
59
  }
60
60
  export declare class SchematicEngine<CollectionT extends object, SchematicT extends object> implements Engine<CollectionT, SchematicT> {
@@ -124,7 +124,7 @@ export interface TypedSchematicContext<CollectionMetadataT extends object, Schem
124
124
  readonly schematic: Schematic<CollectionMetadataT, SchematicMetadataT>;
125
125
  readonly strategy: MergeStrategy;
126
126
  readonly interactive: boolean;
127
- addTask<T>(task: TaskConfigurationGenerator<T>, dependencies?: Array<TaskId>): TaskId;
127
+ addTask<T extends object>(task: TaskConfigurationGenerator<T>, dependencies?: Array<TaskId>): TaskId;
128
128
  }
129
129
  /**
130
130
  * This is used by the Schematics implementations in order to avoid needing to have typing from
package/src/index.d.ts CHANGED
@@ -5,6 +5,7 @@
5
5
  * Use of this source code is governed by an MIT-style license that can be
6
6
  * found in the LICENSE file at https://angular.io/license
7
7
  */
8
+ import { strings } from '@angular-devkit/core';
8
9
  import * as formats from './formats/index';
9
10
  import { FilePredicate, MergeStrategy, Tree as TreeInterface } from './tree/interface';
10
11
  import * as workflow from './workflow/index';
@@ -28,8 +29,7 @@ export * from './engine/schematic';
28
29
  export * from './sink/dryrun';
29
30
  export * from './sink/host';
30
31
  export * from './sink/sink';
31
- export { formats };
32
- export { workflow };
32
+ export { formats, strings, workflow };
33
33
  export interface TreeConstructor {
34
34
  empty(): TreeInterface;
35
35
  branch(tree: TreeInterface): TreeInterface;
package/src/index.js CHANGED
@@ -33,7 +33,9 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
33
33
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
34
34
  };
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.Tree = exports.workflow = exports.formats = exports.SchematicsException = void 0;
36
+ exports.Tree = exports.workflow = exports.strings = exports.formats = exports.SchematicsException = void 0;
37
+ const core_1 = require("@angular-devkit/core");
38
+ Object.defineProperty(exports, "strings", { enumerable: true, get: function () { return core_1.strings; } });
37
39
  const formats = __importStar(require("./formats/index"));
38
40
  exports.formats = formats;
39
41
  const interface_1 = require("./tree/interface");
@@ -35,5 +35,5 @@ export declare function pathTemplate<T extends PathTemplateData>(options: T): Ru
35
35
  * Remove every `.template` suffix from file names.
36
36
  */
37
37
  export declare function renameTemplateFiles(): Rule;
38
- export declare function template<T>(options: T): Rule;
39
- export declare function applyTemplates<T>(options: T): Rule;
38
+ export declare function template<T extends object>(options: T): Rule;
39
+ export declare function applyTemplates<T extends object>(options: T): Rule;
@@ -6,6 +6,7 @@
6
6
  * found in the LICENSE file at https://angular.io/license
7
7
  */
8
8
  /// <reference types="node" />
9
+ import { JsonValue } from '@angular-devkit/core';
9
10
  import { Action } from './action';
10
11
  import { DirEntry, FileEntry, FileVisitor, MergeStrategy, Tree, UpdateRecorder } from './interface';
11
12
  export declare class DelegateTree implements Tree {
@@ -15,6 +16,8 @@ export declare class DelegateTree implements Tree {
15
16
  merge(other: Tree, strategy?: MergeStrategy): void;
16
17
  get root(): DirEntry;
17
18
  read(path: string): Buffer | null;
19
+ readText(path: string): string;
20
+ readJson(path: string): JsonValue;
18
21
  exists(path: string): boolean;
19
22
  get(path: string): FileEntry | null;
20
23
  getDir(path: string): DirEntry;
@@ -26,6 +26,12 @@ class DelegateTree {
26
26
  read(path) {
27
27
  return this._other.read(path);
28
28
  }
29
+ readText(path) {
30
+ return this._other.readText(path);
31
+ }
32
+ readJson(path) {
33
+ return this._other.readJson(path);
34
+ }
29
35
  exists(path) {
30
36
  return this._other.exists(path);
31
37
  }
@@ -6,7 +6,7 @@
6
6
  * found in the LICENSE file at https://angular.io/license
7
7
  */
8
8
  /// <reference types="node" />
9
- import { Path, PathFragment, virtualFs } from '@angular-devkit/core';
9
+ import { JsonValue, Path, PathFragment, virtualFs } from '@angular-devkit/core';
10
10
  import { Action } from './action';
11
11
  import { DirEntry, FileEntry, FilePredicate, FileVisitor, MergeStrategy, Tree, UpdateRecorder } from './interface';
12
12
  export declare class HostDirEntry implements DirEntry {
@@ -41,6 +41,8 @@ export declare class HostTree implements Tree {
41
41
  merge(other: Tree, strategy?: MergeStrategy): void;
42
42
  get root(): DirEntry;
43
43
  read(path: string): Buffer | null;
44
+ readText(path: string): string;
45
+ readJson(path: string): JsonValue;
44
46
  exists(path: string): boolean;
45
47
  get(path: string): FileEntry | null;
46
48
  getDir(path: string): DirEntry;
@@ -9,8 +9,10 @@
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.FilterHostTree = exports.HostCreateTree = exports.HostTree = exports.HostDirEntry = void 0;
11
11
  const core_1 = require("@angular-devkit/core");
12
+ const jsonc_parser_1 = require("jsonc-parser");
12
13
  const rxjs_1 = require("rxjs");
13
14
  const operators_1 = require("rxjs/operators");
15
+ const util_1 = require("util");
14
16
  const exception_1 = require("../exception/exception");
15
17
  const delegate_1 = require("./delegate");
16
18
  const entry_1 = require("./entry");
@@ -208,6 +210,34 @@ class HostTree {
208
210
  const entry = this.get(path);
209
211
  return entry ? entry.content : null;
210
212
  }
213
+ readText(path) {
214
+ const data = this.read(path);
215
+ if (data === null) {
216
+ throw new exception_1.FileDoesNotExistException(path);
217
+ }
218
+ const decoder = new util_1.TextDecoder('utf-8', { fatal: true });
219
+ try {
220
+ // With the `fatal` option enabled, invalid data will throw a TypeError
221
+ return decoder.decode(data);
222
+ }
223
+ catch (e) {
224
+ if (e instanceof TypeError) {
225
+ throw new Error(`Failed to decode "${path}" as UTF-8 text.`);
226
+ }
227
+ throw e;
228
+ }
229
+ }
230
+ readJson(path) {
231
+ const content = this.readText(path);
232
+ const errors = [];
233
+ const result = (0, jsonc_parser_1.parse)(content, errors, { allowTrailingComma: true });
234
+ // If there is a parse error throw with the error information
235
+ if (errors[0]) {
236
+ const { error, offset } = errors[0];
237
+ throw new Error(`Failed to parse "${path}" as JSON. ${(0, jsonc_parser_1.printParseErrorCode)(error)} at offset: ${offset}.`);
238
+ }
239
+ return result;
240
+ }
211
241
  exists(path) {
212
242
  return this._recordSync.isFile(this._normalizePath(path));
213
243
  }
@@ -6,7 +6,7 @@
6
6
  * found in the LICENSE file at https://angular.io/license
7
7
  */
8
8
  /// <reference types="node" />
9
- import { Path, PathFragment } from '@angular-devkit/core';
9
+ import { JsonValue, Path, PathFragment } from '@angular-devkit/core';
10
10
  import { Action } from './action';
11
11
  export declare enum MergeStrategy {
12
12
  AllowOverwriteConflict = 2,
@@ -41,6 +41,28 @@ export interface Tree {
41
41
  merge(other: Tree, strategy?: MergeStrategy): void;
42
42
  readonly root: DirEntry;
43
43
  read(path: string): Buffer | null;
44
+ /**
45
+ * Reads a file from the Tree as a UTF-8 encoded text file.
46
+ *
47
+ * @param path The path of the file to read.
48
+ * @returns A string containing the contents of the file.
49
+ * @throws {@link FileDoesNotExistException} if the file is not found.
50
+ * @throws An error if the file contains invalid UTF-8 characters.
51
+ */
52
+ readText(path: string): string;
53
+ /**
54
+ * Reads and parses a file from the Tree as a UTF-8 encoded JSON file.
55
+ * Supports parsing JSON (RFC 8259) with the following extensions:
56
+ * * Single-line and multi-line JavaScript comments
57
+ * * Trailing commas within objects and arrays
58
+ *
59
+ * @param path The path of the file to read.
60
+ * @returns A JsonValue containing the parsed contents of the file.
61
+ * @throws {@link FileDoesNotExistException} if the file is not found.
62
+ * @throws An error if the file contains invalid UTF-8 characters.
63
+ * @throws An error if the file contains malformed JSON.
64
+ */
65
+ readJson(path: string): JsonValue;
44
66
  exists(path: string): boolean;
45
67
  get(path: string): FileEntry | null;
46
68
  getDir(path: string): DirEntry;
@@ -6,7 +6,7 @@
6
6
  * found in the LICENSE file at https://angular.io/license
7
7
  */
8
8
  /// <reference types="node" />
9
- import { BaseException, Path, PathFragment } from '@angular-devkit/core';
9
+ import { BaseException, JsonValue, Path, PathFragment } from '@angular-devkit/core';
10
10
  import { Action } from './action';
11
11
  import { DirEntry, MergeStrategy, Tree, UpdateRecorder } from './interface';
12
12
  export declare class CannotCreateFileException extends BaseException {
@@ -28,6 +28,8 @@ export declare class NullTree implements Tree {
28
28
  readonly root: DirEntry;
29
29
  exists(_path: string): boolean;
30
30
  read(_path: string): null;
31
+ readText(path: string): string;
32
+ readJson(path: string): JsonValue;
31
33
  get(_path: string): null;
32
34
  getDir(path: string): NullTreeDirEntry;
33
35
  visit(): void;
package/src/tree/null.js CHANGED
@@ -54,6 +54,12 @@ class NullTree {
54
54
  read(_path) {
55
55
  return null;
56
56
  }
57
+ readText(path) {
58
+ throw new exception_1.FileDoesNotExistException(path);
59
+ }
60
+ readJson(path) {
61
+ throw new exception_1.FileDoesNotExistException(path);
62
+ }
57
63
  get(_path) {
58
64
  return null;
59
65
  }
@@ -6,7 +6,7 @@
6
6
  * found in the LICENSE file at https://angular.io/license
7
7
  */
8
8
  /// <reference types="node" />
9
- import { Path, PathFragment } from '@angular-devkit/core';
9
+ import { JsonValue, Path, PathFragment } from '@angular-devkit/core';
10
10
  import { Action } from './action';
11
11
  import { DirEntry, FileEntry, FileVisitor, MergeStrategy, Tree, UpdateRecorder } from './interface';
12
12
  declare class ScopedDirEntry implements DirEntry {
@@ -29,6 +29,8 @@ export declare class ScopedTree implements Tree {
29
29
  branch(): Tree;
30
30
  merge(other: Tree, strategy?: MergeStrategy): void;
31
31
  read(path: string): Buffer | null;
32
+ readText(path: string): string;
33
+ readJson(path: string): JsonValue;
32
34
  exists(path: string): boolean;
33
35
  get(path: string): FileEntry | null;
34
36
  getDir(path: string): DirEntry;
@@ -83,6 +83,12 @@ class ScopedTree {
83
83
  read(path) {
84
84
  return this._base.read(this._fullPath(path));
85
85
  }
86
+ readText(path) {
87
+ return this._base.readText(this._fullPath(path));
88
+ }
89
+ readJson(path) {
90
+ return this._base.readJson(this._fullPath(path));
91
+ }
86
92
  exists(path) {
87
93
  return this._base.exists(this._fullPath(path));
88
94
  }
@@ -110,6 +110,9 @@ function default_1(factoryOptions = {}) {
110
110
  if (options.quiet && taskPackageManagerProfile.quietArgument) {
111
111
  args.push(taskPackageManagerProfile.quietArgument);
112
112
  }
113
+ if (!options.allowScripts) {
114
+ args.push('--ignore-scripts');
115
+ }
113
116
  if (factoryOptions.registry) {
114
117
  args.push(`--registry="${factoryOptions.registry}"`);
115
118
  }
@@ -13,10 +13,12 @@ interface NodePackageInstallTaskOptions {
13
13
  workingDirectory?: string;
14
14
  quiet?: boolean;
15
15
  hideOutput?: boolean;
16
+ allowScripts?: boolean;
16
17
  }
17
18
  export declare class NodePackageInstallTask implements TaskConfigurationGenerator<NodePackageTaskOptions> {
18
19
  quiet: boolean;
19
20
  hideOutput: boolean;
21
+ allowScripts: boolean;
20
22
  workingDirectory?: string;
21
23
  packageManager?: string;
22
24
  packageName?: string;
@@ -13,6 +13,7 @@ class NodePackageInstallTask {
13
13
  constructor(options) {
14
14
  this.quiet = true;
15
15
  this.hideOutput = true;
16
+ this.allowScripts = false;
16
17
  if (typeof options === 'string') {
17
18
  this.workingDirectory = options;
18
19
  }
@@ -32,6 +33,9 @@ class NodePackageInstallTask {
32
33
  if (options.packageName != undefined) {
33
34
  this.packageName = options.packageName;
34
35
  }
36
+ if (options.allowScripts !== undefined) {
37
+ this.allowScripts = options.allowScripts;
38
+ }
35
39
  }
36
40
  }
37
41
  toConfiguration() {
@@ -44,6 +48,7 @@ class NodePackageInstallTask {
44
48
  workingDirectory: this.workingDirectory,
45
49
  packageManager: this.packageManager,
46
50
  packageName: this.packageName,
51
+ allowScripts: this.allowScripts,
47
52
  },
48
53
  };
49
54
  }
@@ -20,4 +20,5 @@ export interface NodePackageTaskOptions {
20
20
  workingDirectory?: string;
21
21
  packageName?: string;
22
22
  packageManager?: string;
23
+ allowScripts?: boolean;
23
24
  }
@@ -23,7 +23,7 @@ export declare class SchematicTestRunner {
23
23
  get logger(): logging.Logger;
24
24
  get tasks(): TaskConfiguration[];
25
25
  registerCollection(collectionName: string, collectionPath: string): void;
26
- runSchematicAsync<SchematicSchemaT>(schematicName: string, opts?: SchematicSchemaT, tree?: Tree): Observable<UnitTestTree>;
27
- runExternalSchematicAsync<SchematicSchemaT>(collectionName: string, schematicName: string, opts?: SchematicSchemaT, tree?: Tree): Observable<UnitTestTree>;
26
+ runSchematicAsync<SchematicSchemaT extends object>(schematicName: string, opts?: SchematicSchemaT, tree?: Tree): Observable<UnitTestTree>;
27
+ runExternalSchematicAsync<SchematicSchemaT extends object>(collectionName: string, schematicName: string, opts?: SchematicSchemaT, tree?: Tree): Observable<UnitTestTree>;
28
28
  callRule(rule: Rule, tree: Tree, parentContext?: Partial<SchematicContext>): Observable<Tree>;
29
29
  }
@@ -14,6 +14,7 @@ export interface FileSystemCollectionDescription {
14
14
  readonly schematics: {
15
15
  [name: string]: FileSystemSchematicDesc;
16
16
  };
17
+ readonly encapsulation?: boolean;
17
18
  }
18
19
  export interface FileSystemSchematicJsonDescription {
19
20
  readonly aliases?: string[];
@@ -11,7 +11,7 @@ import { Observable } from 'rxjs';
11
11
  import { Url } from 'url';
12
12
  import { RuleFactory, Source, TaskExecutor, TaskExecutorFactory } from '../src';
13
13
  import { FileSystemCollectionDesc, FileSystemEngineHost, FileSystemSchematicContext, FileSystemSchematicDesc, FileSystemSchematicDescription } from './description';
14
- export declare type OptionTransform<T extends object, R extends object> = (schematic: FileSystemSchematicDescription, options: T, context?: FileSystemSchematicContext) => Observable<R> | PromiseLike<R> | R;
14
+ export declare type OptionTransform<T extends object | null, R extends object> = (schematic: FileSystemSchematicDescription, options: T, context?: FileSystemSchematicContext) => Observable<R> | PromiseLike<R> | R;
15
15
  export declare type ContextTransform = (context: FileSystemSchematicContext) => FileSystemSchematicContext;
16
16
  export declare class CollectionCannotBeResolvedException extends BaseException {
17
17
  constructor(name: string);
@@ -46,7 +46,7 @@ export declare class SchematicNameCollisionException extends BaseException {
46
46
  */
47
47
  export declare abstract class FileSystemEngineHostBase implements FileSystemEngineHost {
48
48
  protected abstract _resolveCollectionPath(name: string, requester?: string): string;
49
- protected abstract _resolveReferenceString(name: string, parentPath: string): {
49
+ protected abstract _resolveReferenceString(name: string, parentPath: string, collectionDescription: FileSystemCollectionDesc): {
50
50
  ref: RuleFactory<{}>;
51
51
  path: string;
52
52
  } | null;
@@ -56,7 +56,7 @@ export declare abstract class FileSystemEngineHostBase implements FileSystemEngi
56
56
  private _contextTransforms;
57
57
  private _taskFactories;
58
58
  listSchematicNames(collection: FileSystemCollectionDesc, includeHidden?: boolean): string[];
59
- registerOptionsTransform<T extends object, R extends object>(t: OptionTransform<T, R>): void;
59
+ registerOptionsTransform<T extends object | null, R extends object>(t: OptionTransform<T, R>): void;
60
60
  registerContextTransform(t: ContextTransform): void;
61
61
  /**
62
62
  *
@@ -178,7 +178,7 @@ class FileSystemEngineHostBase {
178
178
  if (!partialDesc.factory) {
179
179
  throw new SchematicMissingFactoryException(name);
180
180
  }
181
- const resolvedRef = this._resolveReferenceString(partialDesc.factory, collectionPath);
181
+ const resolvedRef = this._resolveReferenceString(partialDesc.factory, collectionPath, collection);
182
182
  if (!resolvedRef) {
183
183
  throw new FactoryCannotBeResolvedException(name);
184
184
  }
@@ -20,7 +20,7 @@ export declare class NodeModulesEngineHost extends FileSystemEngineHostBase {
20
20
  constructor(paths?: string[] | undefined);
21
21
  private resolve;
22
22
  protected _resolveCollectionPath(name: string, requester?: string): string;
23
- protected _resolveReferenceString(refString: string, parentPath: string): {
23
+ protected _resolveReferenceString(refString: string, parentPath: string, collectionDescription?: FileSystemCollectionDesc): {
24
24
  ref: RuleFactory<{}>;
25
25
  path: string;
26
26
  } | null;
@@ -81,7 +81,7 @@ class NodeModulesEngineHost extends file_system_engine_host_base_1.FileSystemEng
81
81
  (0, file_system_utility_1.readJsonFile)(collectionPath);
82
82
  return collectionPath;
83
83
  }
84
- _resolveReferenceString(refString, parentPath) {
84
+ _resolveReferenceString(refString, parentPath, collectionDescription) {
85
85
  const ref = new export_ref_1.ExportStringRef(refString, parentPath);
86
86
  if (!ref.ref) {
87
87
  return null;
@@ -11,4 +11,4 @@ import { FileSystemSchematicContext, FileSystemSchematicDescription } from './de
11
11
  export declare class InvalidInputOptions<T = {}> extends schema.SchemaValidationException {
12
12
  constructor(options: T, errors: schema.SchemaValidatorError[]);
13
13
  }
14
- export declare function validateOptionsWithSchema(registry: schema.SchemaRegistry): <T extends {}>(schematic: FileSystemSchematicDescription, options: T, context?: FileSystemSchematicContext | undefined) => Observable<T>;
14
+ export declare function validateOptionsWithSchema(registry: schema.SchemaRegistry): <T extends {} | null>(schematic: FileSystemSchematicDescription, options: T, context?: FileSystemSchematicContext | undefined) => Observable<T>;
@@ -19,7 +19,7 @@ export interface NodeWorkflowOptions {
19
19
  registry?: schema.CoreSchemaRegistry;
20
20
  resolvePaths?: string[];
21
21
  schemaValidation?: boolean;
22
- optionTransforms?: OptionTransform<object, object>[];
22
+ optionTransforms?: OptionTransform<Record<string, unknown> | null, object>[];
23
23
  engineHostCreator?: (options: NodeWorkflowOptions) => NodeModulesEngineHost;
24
24
  }
25
25
  /**