depflow 3.0.0-dev.10 → 3.0.0-dev.11

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.
Files changed (172) hide show
  1. package/README.md +108 -43
  2. package/dist/builder/Builder.d.ts +279 -0
  3. package/dist/builder/Builder.js +391 -0
  4. package/dist/builder/Builder.js.map +1 -0
  5. package/dist/cli/CLI.d.ts +157 -0
  6. package/dist/cli/CLI.js +214 -0
  7. package/dist/cli/CLI.js.map +1 -0
  8. package/dist/cli/DepFLowCLI.d.ts +93 -0
  9. package/dist/cli/DepFLowCLI.js +413 -0
  10. package/dist/cli/DepFLowCLI.js.map +1 -0
  11. package/dist/cli/Flags.d.ts +106 -0
  12. package/dist/cli/Flags.js +125 -0
  13. package/dist/cli/Flags.js.map +1 -0
  14. package/dist/cli/bin.js +68 -0
  15. package/dist/cli/bin.js.map +1 -0
  16. package/dist/config/Config.d.ts +690 -0
  17. package/dist/config/Config.js +45 -0
  18. package/dist/config/Config.js.map +1 -0
  19. package/dist/config/ImportMap.d.ts +60 -0
  20. package/dist/config/ImportMap.js +66 -0
  21. package/dist/config/ImportMap.js.map +1 -0
  22. package/dist/config/JsonSchema.d.ts +12 -0
  23. package/dist/config/JsonSchema.js +26 -0
  24. package/dist/config/JsonSchema.js.map +1 -0
  25. package/dist/config/Settings.d.ts +201 -0
  26. package/dist/config/Settings.js +191 -0
  27. package/dist/config/Settings.js.map +1 -0
  28. package/dist/config/TSConfig.d.ts +73 -0
  29. package/dist/config/TSConfig.js +73 -0
  30. package/dist/config/TSConfig.js.map +1 -0
  31. package/dist/config/codecs/JsonCodec.d.ts +30 -0
  32. package/dist/config/codecs/JsonCodec.js +31 -0
  33. package/dist/config/codecs/JsonCodec.js.map +1 -0
  34. package/dist/config/codecs/YamlCodec.d.ts +62 -0
  35. package/dist/config/codecs/YamlCodec.js +89 -0
  36. package/dist/config/codecs/YamlCodec.js.map +1 -0
  37. package/dist/dependency/DepUtils.d.ts +50 -0
  38. package/dist/dependency/DepUtils.js +71 -0
  39. package/dist/dependency/DepUtils.js.map +1 -0
  40. package/dist/dependency/Dependency.d.ts +81 -0
  41. package/dist/dependency/Dependency.js +71 -0
  42. package/dist/dependency/Dependency.js.map +1 -0
  43. package/dist/dependency/Git.d.ts +75 -0
  44. package/dist/dependency/Git.js +97 -0
  45. package/dist/dependency/Git.js.map +1 -0
  46. package/dist/dependency/GitDependency.d.ts +30 -0
  47. package/dist/dependency/GitDependency.js +79 -0
  48. package/dist/dependency/GitDependency.js.map +1 -0
  49. package/dist/dependency/NpmDependency.d.ts +27 -0
  50. package/dist/dependency/NpmDependency.js +91 -0
  51. package/dist/dependency/NpmDependency.js.map +1 -0
  52. package/{build/support/PathResolver → dist/resolve}/AliasCompiler.d.ts +18 -5
  53. package/{build/support/PathResolver → dist/resolve}/AliasCompiler.js +31 -9
  54. package/dist/resolve/AliasCompiler.js.map +1 -0
  55. package/{build/support/PathResolver → dist/resolve}/PathResolver.d.ts +25 -8
  56. package/dist/resolve/PathResolver.js +133 -0
  57. package/dist/resolve/PathResolver.js.map +1 -0
  58. package/dist/resolve/PathRewriter.d.ts +24 -0
  59. package/{build/support/PathResolver → dist/resolve}/PathRewriter.js +21 -11
  60. package/dist/resolve/PathRewriter.js.map +1 -0
  61. package/{build → dist}/schema/Config/Builder.d.ts +114 -49
  62. package/dist/schema/Config/Builder.js +78 -0
  63. package/dist/schema/Config/Builder.js.map +1 -0
  64. package/{build → dist}/schema/Config/Config.d.ts +169 -78
  65. package/dist/schema/Config/Config.js +62 -0
  66. package/dist/schema/Config/Config.js.map +1 -0
  67. package/{build → dist}/schema/Config/Dependency.d.ts +219 -89
  68. package/dist/schema/Config/Dependency.js +80 -0
  69. package/dist/schema/Config/Dependency.js.map +1 -0
  70. package/{build → dist}/schema/Config/Extractor.d.ts +41 -17
  71. package/dist/schema/Config/Extractor.js +43 -0
  72. package/dist/schema/Config/Extractor.js.map +1 -0
  73. package/{build → dist}/schema/Config/Resolver.d.ts +25 -8
  74. package/dist/schema/Config/Resolver.js +43 -0
  75. package/dist/schema/Config/Resolver.js.map +1 -0
  76. package/{build → dist}/schema/Config/Transform.d.ts +22 -5
  77. package/dist/schema/Config/Transform.js +51 -0
  78. package/dist/schema/Config/Transform.js.map +1 -0
  79. package/dist/schema/Defaults.d.ts +20 -0
  80. package/dist/schema/Defaults.js +24 -0
  81. package/dist/schema/Defaults.js.map +1 -0
  82. package/dist/schema/ImportMap.d.ts +30 -0
  83. package/dist/schema/ImportMap.js +28 -0
  84. package/dist/schema/ImportMap.js.map +1 -0
  85. package/{build → dist}/schema/TSConfig.d.ts +23 -9
  86. package/dist/schema/TSConfig.js +39 -0
  87. package/dist/schema/TSConfig.js.map +1 -0
  88. package/{build → dist}/schema/schema.d.ts +11 -2
  89. package/{build → dist}/schema/schema.js +11 -2
  90. package/dist/schema/schema.js.map +1 -0
  91. package/dist/task/Command.d.ts +287 -0
  92. package/dist/task/Command.js +404 -0
  93. package/dist/task/Command.js.map +1 -0
  94. package/dist/task/Group.d.ts +15 -0
  95. package/dist/task/Group.js +29 -0
  96. package/dist/task/Group.js.map +1 -0
  97. package/dist/task/OutputPolicy.d.ts +262 -0
  98. package/dist/task/OutputPolicy.js +364 -0
  99. package/dist/task/OutputPolicy.js.map +1 -0
  100. package/dist/task/Task.d.ts +210 -0
  101. package/dist/task/Task.js +312 -0
  102. package/dist/task/Task.js.map +1 -0
  103. package/package.json +13 -10
  104. package/.gitignore +0 -7
  105. package/build/cli/DepFLowCLI.d.ts +0 -16
  106. package/build/cli/DepFLowCLI.js +0 -254
  107. package/build/cli/DepFLowCLI.js.map +0 -1
  108. package/build/cli/bin.js +0 -38
  109. package/build/cli/bin.js.map +0 -1
  110. package/build/config/Config.d.ts +0 -28
  111. package/build/config/Config.js +0 -46
  112. package/build/config/Config.js.map +0 -1
  113. package/build/config/ImportMap.d.ts +0 -51
  114. package/build/config/ImportMap.js +0 -97
  115. package/build/config/ImportMap.js.map +0 -1
  116. package/build/config/TSConfig.d.ts +0 -54
  117. package/build/config/TSConfig.js +0 -104
  118. package/build/config/TSConfig.js.map +0 -1
  119. package/build/schema/Config/Builder.js +0 -48
  120. package/build/schema/Config/Builder.js.map +0 -1
  121. package/build/schema/Config/Config.js +0 -20
  122. package/build/schema/Config/Config.js.map +0 -1
  123. package/build/schema/Config/Dependency.js +0 -25
  124. package/build/schema/Config/Dependency.js.map +0 -1
  125. package/build/schema/Config/Extractor.js +0 -25
  126. package/build/schema/Config/Extractor.js.map +0 -1
  127. package/build/schema/Config/Resolver.js +0 -25
  128. package/build/schema/Config/Resolver.js.map +0 -1
  129. package/build/schema/Config/Transform.js +0 -27
  130. package/build/schema/Config/Transform.js.map +0 -1
  131. package/build/schema/ImportMap.d.ts +0 -22
  132. package/build/schema/ImportMap.js +0 -12
  133. package/build/schema/ImportMap.js.map +0 -1
  134. package/build/schema/TSConfig.js +0 -19
  135. package/build/schema/TSConfig.js.map +0 -1
  136. package/build/schema/schema.js.map +0 -1
  137. package/build/support/Builder/Builder.d.ts +0 -46
  138. package/build/support/Builder/Builder.js +0 -116
  139. package/build/support/Builder/Builder.js.map +0 -1
  140. package/build/support/Dependency/Dependency.d.ts +0 -38
  141. package/build/support/Dependency/Dependency.js +0 -14
  142. package/build/support/Dependency/Dependency.js.map +0 -1
  143. package/build/support/Dependency/GitDependency.d.ts +0 -20
  144. package/build/support/Dependency/GitDependency.js +0 -67
  145. package/build/support/Dependency/GitDependency.js.map +0 -1
  146. package/build/support/Dependency/NpmDependency.d.ts +0 -18
  147. package/build/support/Dependency/NpmDependency.js +0 -65
  148. package/build/support/Dependency/NpmDependency.js.map +0 -1
  149. package/build/support/Git.d.ts +0 -53
  150. package/build/support/Git.js +0 -86
  151. package/build/support/Git.js.map +0 -1
  152. package/build/support/PathResolver/AliasCompiler.js.map +0 -1
  153. package/build/support/PathResolver/PathResolver.js +0 -105
  154. package/build/support/PathResolver/PathResolver.js.map +0 -1
  155. package/build/support/PathResolver/PathRewriter.d.ts +0 -18
  156. package/build/support/PathResolver/PathRewriter.js.map +0 -1
  157. package/build/support/PathResolver/Utils.d.ts +0 -36
  158. package/build/support/PathResolver/Utils.js +0 -45
  159. package/build/support/PathResolver/Utils.js.map +0 -1
  160. package/build/support/Task/Command.d.ts +0 -49
  161. package/build/support/Task/Command.js +0 -100
  162. package/build/support/Task/Command.js.map +0 -1
  163. package/build/support/Task/Task.d.ts +0 -84
  164. package/build/support/Task/Task.js +0 -145
  165. package/build/support/Task/Task.js.map +0 -1
  166. package/build/support/Utils.d.ts +0 -40
  167. package/build/support/Utils.js +0 -138
  168. package/build/support/Utils.js.map +0 -1
  169. package/build/support/Validator.d.ts +0 -22
  170. package/build/support/Validator.js +0 -28
  171. package/build/support/Validator.js.map +0 -1
  172. /package/{build → dist}/cli/bin.d.ts +0 -0
@@ -0,0 +1,73 @@
1
+ /**
2
+ * @author NetFeez <netfeez.dev@gmail.com>.
3
+ * @description Updates and persists TypeScript path mappings from compiled path aliases.
4
+ * @license Apache-2.0
5
+ */
6
+ import { Logger } from '@netfeez/vterm';
7
+ import schema from '../schema/schema.js';
8
+ import Settings from './Settings.js';
9
+ import type AliasCompiler from '../resolve/AliasCompiler.js';
10
+ export declare class TSConfig extends Settings<typeof schema.TSConfig> {
11
+ protected static schema: import("@netfeez/schema").Schema<{
12
+ readonly type: "object";
13
+ readonly additional: true;
14
+ readonly keys: {
15
+ readonly compilerOptions: {
16
+ readonly type: "object";
17
+ readonly additional: true;
18
+ readonly keys: {
19
+ readonly rootDir: {
20
+ readonly type: "string";
21
+ readonly description: "Root directory of the TypeScript source files.";
22
+ };
23
+ readonly outDir: {
24
+ readonly type: "string";
25
+ readonly description: "Output directory for the compiled files.";
26
+ };
27
+ readonly paths: {
28
+ readonly type: "object";
29
+ readonly additional: {
30
+ readonly type: "array";
31
+ readonly items: {
32
+ readonly type: "string";
33
+ };
34
+ };
35
+ readonly description: "Path mapping aliases used by TypeScript to resolve modules.";
36
+ };
37
+ };
38
+ readonly description: "The compiler options object of the tsconfig file.";
39
+ };
40
+ };
41
+ readonly description: "Structure of a tsconfig.json file.";
42
+ }>;
43
+ protected logger: Logger;
44
+ constructor(data: TSConfig.Data, options?: TSConfig.Options);
45
+ /**
46
+ * The formats of the tsconfig file: JSON only, so it never reaches a YAML parser.
47
+ * @returns The JSON codec of the file.
48
+ */
49
+ protected static get codecs(): readonly Settings.AnyCodec[];
50
+ /**
51
+ * Updates the paths in the tsconfig data based on the provided compiled aliases.
52
+ * It ensures that the compilerOptions and paths properties exist in the tsconfig data, and then iterates through the compiled aliases to construct the appropriate path mappings.
53
+ * For each alias, it calculates the relative path from the project root to the local target and normalizes it. If the alias is a wildcard, it appends '/*' to the target path.
54
+ * Finally, it updates the paths in the tsconfig data with the new mappings, allowing TypeScript to resolve module paths according to the defined aliases.
55
+ * @param aliases - An array of compiled aliases containing alias names, target paths, and wildcard information.
56
+ */
57
+ updatePaths(aliases: AliasCompiler.CompiledAlias[]): void;
58
+ /**
59
+ * Saves the current tsconfig data to a file.
60
+ * It constructs the path to the tsconfig file using the project root and filename, converts the data to a JSON string with proper formatting, and writes it to the file system using the File.write method.
61
+ * The method also includes error handling to log any issues that occur during the save process, ensuring that users are informed of any problems when attempting to save the tsconfig configuration.
62
+ * @param path - The path to the tsconfig file where the data should be saved.
63
+ * @returns A promise that resolves when the save operation is complete, or rejects if an error occurs during the process.
64
+ */
65
+ save(path?: string): Promise<void>;
66
+ }
67
+ export declare namespace TSConfig {
68
+ type Data = schema.TSConfig.Root;
69
+ interface Options extends Settings.Options {
70
+ logger?: Logger;
71
+ }
72
+ }
73
+ export default TSConfig;
@@ -0,0 +1,73 @@
1
+ /**
2
+ * @author NetFeez <netfeez.dev@gmail.com>.
3
+ * @description Updates and persists TypeScript path mappings from compiled path aliases.
4
+ * @license Apache-2.0
5
+ */
6
+ import { Logger } from '@netfeez/vterm';
7
+ import { Path } from '@netfeez/common-node';
8
+ import schema from '../schema/schema.js';
9
+ import Settings from './Settings.js';
10
+ import JsonCodec from './codecs/JsonCodec.js';
11
+ export class TSConfig extends Settings {
12
+ static schema = schema.TSConfig;
13
+ logger;
14
+ constructor(data, options = {}) {
15
+ super(data, options);
16
+ this.logger = options.logger || new Logger({ name: 'TS-CFG' });
17
+ }
18
+ /**
19
+ * The formats of the tsconfig file: JSON only, so it never reaches a YAML parser.
20
+ * @returns The JSON codec of the file.
21
+ */
22
+ static get codecs() { return [new JsonCodec()]; }
23
+ /**
24
+ * Updates the paths in the tsconfig data based on the provided compiled aliases.
25
+ * It ensures that the compilerOptions and paths properties exist in the tsconfig data, and then iterates through the compiled aliases to construct the appropriate path mappings.
26
+ * For each alias, it calculates the relative path from the project root to the local target and normalizes it. If the alias is a wildcard, it appends '/*' to the target path.
27
+ * Finally, it updates the paths in the tsconfig data with the new mappings, allowing TypeScript to resolve module paths according to the defined aliases.
28
+ * @param aliases - An array of compiled aliases containing alias names, target paths, and wildcard information.
29
+ */
30
+ updatePaths(aliases) {
31
+ if (!this.data.compilerOptions)
32
+ this.data.compilerOptions = {};
33
+ if (!this.data.compilerOptions.paths)
34
+ this.data.compilerOptions.paths = {};
35
+ const projectRoot = Path.dirname(this.path);
36
+ for (const alias of aliases) {
37
+ const key = alias.isWildcard ? `${alias.alias}/*` : alias.alias;
38
+ let target = Path.diff(projectRoot, alias.targets.local);
39
+ target = target.startsWith('.') ? target : `./${target}`;
40
+ target = Path.normalize(target);
41
+ let typeTarget;
42
+ if (alias.targets.type) {
43
+ typeTarget = Path.diff(projectRoot, alias.targets.type);
44
+ typeTarget = typeTarget.startsWith('.') ? typeTarget : `./${typeTarget}`;
45
+ typeTarget = Path.normalize(typeTarget);
46
+ }
47
+ if (alias.isWildcard) {
48
+ const suffix = target.endsWith('/') ? '*' : '/*';
49
+ target = `${target}${suffix}`;
50
+ if (typeTarget) {
51
+ typeTarget = `${typeTarget}${suffix}`;
52
+ }
53
+ }
54
+ this.data.compilerOptions.paths[key] = typeTarget ? [typeTarget, target] : [target];
55
+ }
56
+ }
57
+ /**
58
+ * Saves the current tsconfig data to a file.
59
+ * It constructs the path to the tsconfig file using the project root and filename, converts the data to a JSON string with proper formatting, and writes it to the file system using the File.write method.
60
+ * The method also includes error handling to log any issues that occur during the save process, ensuring that users are informed of any problems when attempting to save the tsconfig configuration.
61
+ * @param path - The path to the tsconfig file where the data should be saved.
62
+ * @returns A promise that resolves when the save operation is complete, or rejects if an error occurs during the process.
63
+ */
64
+ async save(path = this.path) {
65
+ await super.save(path);
66
+ if (path !== this.path)
67
+ this.path = path;
68
+ const filename = Path.fileName(path);
69
+ this.logger.log(`&C2Saved file &C4${filename}&C2 successfully.`);
70
+ }
71
+ }
72
+ export default TSConfig;
73
+ //# sourceMappingURL=TSConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TSConfig.js","sourceRoot":"","sources":["../../src/config/TSConfig.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @author NetFeez <netfeez.dev@gmail.com>.
3
+ * @description Reads and writes a config file as plain JSON.
4
+ * @license Apache-2.0
5
+ */
6
+ import type { JsonValue } from '@netfeez/yaml';
7
+ import type Settings from '../Settings.js';
8
+ /**
9
+ * Reads and writes a config file as plain JSON.
10
+ *
11
+ * JSON preserves nothing around the values, so it has no document of its own: the data is the
12
+ * document, and every save regenerates the file from it.
13
+ */
14
+ export declare class JsonCodec implements Settings.Codec<null, JsonValue> {
15
+ /** The file extensions this codec is selected by. */
16
+ readonly extensions: readonly string[];
17
+ /**
18
+ * Parses the JSON text into the data it holds.
19
+ * @param text - The JSON text of the file.
20
+ * @returns The data and the document of the file, or `null` when the text holds no document.
21
+ * @throws { SyntaxError } When the text is not valid JSON.
22
+ */
23
+ decode(text: string): Settings.Decoded<null> | null;
24
+ /** JSON has no document to create: the data is the document. **/
25
+ create(): null;
26
+ /** Renders the data as indented JSON. **/
27
+ encode(data: JsonValue, document: null): string;
28
+ }
29
+ export declare namespace JsonCodec { }
30
+ export default JsonCodec;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @author NetFeez <netfeez.dev@gmail.com>.
3
+ * @description Reads and writes a config file as plain JSON.
4
+ * @license Apache-2.0
5
+ */
6
+ /**
7
+ * Reads and writes a config file as plain JSON.
8
+ *
9
+ * JSON preserves nothing around the values, so it has no document of its own: the data is the
10
+ * document, and every save regenerates the file from it.
11
+ */
12
+ export class JsonCodec {
13
+ /** The file extensions this codec is selected by. */
14
+ extensions = ['.json'];
15
+ /**
16
+ * Parses the JSON text into the data it holds.
17
+ * @param text - The JSON text of the file.
18
+ * @returns The data and the document of the file, or `null` when the text holds no document.
19
+ * @throws { SyntaxError } When the text is not valid JSON.
20
+ */
21
+ decode(text) {
22
+ const data = JSON.parse(text);
23
+ return data === null ? null : { data, document: null };
24
+ }
25
+ /** JSON has no document to create: the data is the document. **/
26
+ create() { return null; }
27
+ /** Renders the data as indented JSON. **/
28
+ encode(data, document) { return JSON.stringify(data, null, 4); }
29
+ }
30
+ export default JsonCodec;
31
+ //# sourceMappingURL=JsonCodec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JsonCodec.js","sourceRoot":"","sources":["../../../src/config/codecs/JsonCodec.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH;;;;;GAKG;AACH,MAAM,OAAO,SAAS;IAClB,qDAAqD;IACrC,UAAU,GAAsB,CAAE,OAAO,CAAE,CAAC;IAE5D;;;;;OAKG;IACI,MAAM,CAAC,IAAY;QACtB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9B,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC3D,CAAC;IAED,iEAAiE;IAC1D,MAAM,KAAW,OAAO,IAAI,CAAC,CAAC,CAAC;IAEtC,0CAA0C;IACnC,MAAM,CAAC,IAAe,EAAE,QAAc,IAAY,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;CACnG;AAID,eAAe,SAAS,CAAC"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * @author NetFeez <netfeez.dev@gmail.com>.
3
+ * @description Reads and writes a config file as YAML, preserving the formatting of the file it was read from.
4
+ * @license Apache-2.0
5
+ */
6
+ import Schema, { Definition } from '@netfeez/schema';
7
+ import { type Document, type JsonValue } from '@netfeez/yaml';
8
+ import type Settings from '../Settings.js';
9
+ /**
10
+ * Reads and writes a config file as YAML, preserving the formatting of the file it was read from.
11
+ *
12
+ * The document is the YAML tree: the values it holds, plus everything YAML keeps around them (key
13
+ * order, indentation, comments). A document created from scratch is decorated with the file header
14
+ * and with the description the schema declares for each key, so a generated config documents itself.
15
+ */
16
+ export declare class YamlCodec implements Settings.Codec<Document, JsonValue> {
17
+ /** The file extensions this codec is selected by. */
18
+ readonly extensions: readonly string[];
19
+ protected schema: Schema<Definition.Definition>;
20
+ protected header: string[];
21
+ /**
22
+ * Creates the codec.
23
+ * @param schema - The schema whose key descriptions document a generated file.
24
+ * @param options - Options for the codec.
25
+ */
26
+ constructor(schema: Schema<Definition.Definition>, options?: YamlCodec.Options);
27
+ /**
28
+ * Parses the YAML text into the document it describes.
29
+ * @param text - The YAML text of the file.
30
+ * @returns The data and the document of the file, or `null` when the text holds no document.
31
+ * @throws { YamlError } When the text is not valid YAML.
32
+ *
33
+ * @remarks A file holding only comments, or nothing at all, parses into an empty tree: it has
34
+ * no data, so there is nothing to load and the defaults of the schema take over.
35
+ */
36
+ decode(text: string): Settings.Decoded<Document> | null;
37
+ /**
38
+ * Creates a document holding the data, with the file header and the schema descriptions.
39
+ * @param data - The data to hold in the new document.
40
+ * @returns The new document.
41
+ */
42
+ create(data: JsonValue): Document;
43
+ /**
44
+ * Synchronizes the data into the document and renders it, leaving everything the data does not
45
+ * touch (key order, indentation, and the comments of the keys it leaves alone) as it was.
46
+ * @param data - The data to render.
47
+ * @param document - The document the data is rendered through.
48
+ * @returns The YAML text of the document.
49
+ */
50
+ encode(data: JsonValue, document: Document): string;
51
+ /** Writes the file header and the schema description of every key the document has. **/
52
+ private decorate;
53
+ /** The description of every declared top-level key, as the comment lines of a generated file. **/
54
+ private descriptions;
55
+ }
56
+ export declare namespace YamlCodec {
57
+ interface Options {
58
+ /** The raw lines written at the top of a generated file, pushed verbatim. */
59
+ header?: string[];
60
+ }
61
+ }
62
+ export default YamlCodec;
@@ -0,0 +1,89 @@
1
+ /**
2
+ * @author NetFeez <netfeez.dev@gmail.com>.
3
+ * @description Reads and writes a config file as YAML, preserving the formatting of the file it was read from.
4
+ * @license Apache-2.0
5
+ */
6
+ import Yaml from '@netfeez/yaml';
7
+ /**
8
+ * Reads and writes a config file as YAML, preserving the formatting of the file it was read from.
9
+ *
10
+ * The document is the YAML tree: the values it holds, plus everything YAML keeps around them (key
11
+ * order, indentation, comments). A document created from scratch is decorated with the file header
12
+ * and with the description the schema declares for each key, so a generated config documents itself.
13
+ */
14
+ export class YamlCodec {
15
+ /** The file extensions this codec is selected by. */
16
+ extensions = ['.yaml', '.yml'];
17
+ schema;
18
+ header;
19
+ /**
20
+ * Creates the codec.
21
+ * @param schema - The schema whose key descriptions document a generated file.
22
+ * @param options - Options for the codec.
23
+ */
24
+ constructor(schema, options = {}) {
25
+ this.schema = schema;
26
+ this.header = options.header ?? [];
27
+ }
28
+ /**
29
+ * Parses the YAML text into the document it describes.
30
+ * @param text - The YAML text of the file.
31
+ * @returns The data and the document of the file, or `null` when the text holds no document.
32
+ * @throws { YamlError } When the text is not valid YAML.
33
+ *
34
+ * @remarks A file holding only comments, or nothing at all, parses into an empty tree: it has
35
+ * no data, so there is nothing to load and the defaults of the schema take over.
36
+ */
37
+ decode(text) {
38
+ const document = Yaml.parse(text);
39
+ const data = document.toJS();
40
+ return data === null ? null : { data, document };
41
+ }
42
+ /**
43
+ * Creates a document holding the data, with the file header and the schema descriptions.
44
+ * @param data - The data to hold in the new document.
45
+ * @returns The new document.
46
+ */
47
+ create(data) {
48
+ const document = Yaml.create(data);
49
+ this.decorate(document);
50
+ return document;
51
+ }
52
+ /**
53
+ * Synchronizes the data into the document and renders it, leaving everything the data does not
54
+ * touch (key order, indentation, and the comments of the keys it leaves alone) as it was.
55
+ * @param data - The data to render.
56
+ * @param document - The document the data is rendered through.
57
+ * @returns The YAML text of the document.
58
+ */
59
+ encode(data, document) {
60
+ document.sync(data);
61
+ return document.dump();
62
+ }
63
+ /** Writes the file header and the schema description of every key the document has. **/
64
+ decorate(document) {
65
+ if (this.header.length)
66
+ document.header.push(...this.header);
67
+ for (const [key, description] of Object.entries(this.descriptions())) {
68
+ const node = document.get(key);
69
+ if (!node)
70
+ continue;
71
+ node.meta.lead = description.map(line => line.startsWith('#') ? line : `# ${line}`);
72
+ }
73
+ }
74
+ /** The description of every declared top-level key, as the comment lines of a generated file. **/
75
+ descriptions() {
76
+ const definition = this.schema.definition;
77
+ if (definition.type !== 'object' || !definition.keys)
78
+ return {};
79
+ const descriptions = {};
80
+ for (const [key, value] of Object.entries(definition.keys)) {
81
+ if (!value.description)
82
+ continue;
83
+ descriptions[key] = value.description.split('\n').map(line => line.trim());
84
+ }
85
+ return descriptions;
86
+ }
87
+ }
88
+ export default YamlCodec;
89
+ //# sourceMappingURL=YamlCodec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"YamlCodec.js","sourceRoot":"","sources":["../../../src/config/codecs/YamlCodec.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,IAAuC,MAAM,eAAe,CAAC;AAKpE;;;;;;GAMG;AACH,MAAM,OAAO,SAAS;IAClB,qDAAqD;IACrC,UAAU,GAAsB,CAAE,OAAO,EAAE,MAAM,CAAE,CAAC;IAE1D,MAAM,CAAgC;IACtC,MAAM,CAAW;IAE3B;;;;OAIG;IACH,YAAmB,MAAqC,EAAE,OAAO,GAAsB,EAAE;QACrF,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC;IACvC,CAAC;IAED;;;;;;;;OAQG;IACI,MAAM,CAAC,IAAY;QACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC7B,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IACrD,CAAC;IAED;;;;OAIG;IACI,MAAM,CAAC,IAAe;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACxB,OAAO,QAAQ,CAAC;IACpB,CAAC;IAED;;;;;;OAMG;IACI,MAAM,CAAC,IAAe,EAAE,QAAkB;QAC7C,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpB,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,wFAAwF;IAChF,QAAQ,CAAC,QAAkB;QAC/B,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM;YAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;QAC7D,KAAK,MAAM,CAAC,GAAG,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC;YACnE,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC/B,IAAI,CAAC,IAAI;gBAAE,SAAS;YACpB,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;QACxF,CAAC;IACL,CAAC;IAED,kGAAkG;IAC1F,YAAY;QAChB,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC;QAC1C,IAAI,UAAU,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,UAAU,CAAC,IAAI;YAAE,OAAO,EAAE,CAAC;QAChE,MAAM,YAAY,GAA6B,EAAE,CAAC;QAClD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACzD,IAAI,CAAC,KAAK,CAAC,WAAW;gBAAE,SAAS;YACjC,YAAY,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAC/E,CAAC;QACD,OAAO,YAAY,CAAC;IACxB,CAAC;CACJ;AASD,eAAe,SAAS,CAAC"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * @author NetFeez <netfeez.dev@gmail.com>.
3
+ * @description Dependency source utilities: git repository validation and identity derivation.
4
+ * @license Apache-2.0
5
+ */
6
+ export declare namespace DepUtils {
7
+ /**
8
+ * Anything `git clone` accepts as a repository: a remote over one of the transports it speaks, or
9
+ * a local path of a repository. The name of a dependency is never derived from it, only the repo
10
+ * itself is.
11
+ *
12
+ * @remarks Every transport is spelled out so the accepted shapes are readable, but the `.git`
13
+ * suffix is what all of them share and what {@link DepUtils.repo} enforces, so the last member is
14
+ * the one that decides.
15
+ */
16
+ type Repo = `https://${string}.git` | `http://${string}.git` | `ssh://${string}.git` | `git://${string}.git` | `file://${string}.git` | `git@${string}.git` | `${string}.git`;
17
+ /**
18
+ * Validates that the provided value is a repository `git clone` accepts, and says what it is not when
19
+ * it does not: a URL with its scheme, an SCP like address or a local path of a repository.
20
+ * @param repo - The repository value to validate.
21
+ * @throws Will throw an error if the value is not a clonable repository.
22
+ *
23
+ * @remarks A repository always carries the `.git` suffix, whichever transport it comes in: it is what
24
+ * tells a repository apart from a page, a package or a folder, and the name of the dependency is
25
+ * derived from the same suffix, so both read one repository.
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * DepUtils.repo('https://github.com/NetFeez/omega.git');
30
+ * ```
31
+ */
32
+ function repo(repo: unknown): asserts repo is Repo;
33
+ /**
34
+ * Extracts the name a dependency is known by from its repository URL.
35
+ *
36
+ * Only a GitHub repository has a name that can be derived without asking, and the name it derives
37
+ * is the one the alias of the dependency takes everywhere else, so it is derived here and nowhere
38
+ * else.
39
+ * @param repo - The repository URL.
40
+ * @returns The repository name, as `<user>.<name>`.
41
+ * @throws { Error } When the repository is not a GitHub one, saying the name has to be given.
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * DepUtils.getRepoName('https://github.com/NetFeez/omega.git'); // 'NetFeez.omega'
46
+ * ```
47
+ */
48
+ function getRepoName(repo: string): string;
49
+ }
50
+ export default DepUtils;
@@ -0,0 +1,71 @@
1
+ /**
2
+ * @author NetFeez <netfeez.dev@gmail.com>.
3
+ * @description Dependency source utilities: git repository validation and identity derivation.
4
+ * @license Apache-2.0
5
+ */
6
+ export var DepUtils;
7
+ (function (DepUtils) {
8
+ /**
9
+ * Matches what `git clone` accepts, in the transports it speaks: a URL with its scheme, an SCP
10
+ * like address, or a local path of a repository.
11
+ */
12
+ const CLONEABLE_REGEX = /^(?:(?:https?|ssh|git|file):\/\/|git@)\S+$|\S*\.git$/;
13
+ /**
14
+ * Matches a github repository URL and captures its user and name, tolerating a missing `.git` suffix.
15
+ */
16
+ const GITHUB_REPO_REGEX = /^(?:https:\/\/github\.com\/([^/]+)\/([^/.]+)(?:\.git)?|git@github\.com:([^/]+)\/([^/.]+)(?:\.git)?)$/;
17
+ /**
18
+ * The suffix that tells a repository from anything else, checked on the value as a whole instead of
19
+ * anchoring it, so a local path of a repository keeps validating wherever it lives.
20
+ */
21
+ const GIT_SUFFIX_REGEX = /\.git$/;
22
+ /**
23
+ * Validates that the provided value is a repository `git clone` accepts, and says what it is not when
24
+ * it does not: a URL with its scheme, an SCP like address or a local path of a repository.
25
+ * @param repo - The repository value to validate.
26
+ * @throws Will throw an error if the value is not a clonable repository.
27
+ *
28
+ * @remarks A repository always carries the `.git` suffix, whichever transport it comes in: it is what
29
+ * tells a repository apart from a page, a package or a folder, and the name of the dependency is
30
+ * derived from the same suffix, so both read one repository.
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * DepUtils.repo('https://github.com/NetFeez/omega.git');
35
+ * ```
36
+ */
37
+ function repo(repo) {
38
+ if (typeof repo !== 'string' || !repo.trim())
39
+ throw new Error(`Not a clonable git repository: "${repo}".`);
40
+ if (!CLONEABLE_REGEX.test(repo) || !GIT_SUFFIX_REGEX.test(repo.trim()))
41
+ throw new Error(`Not a clonable git repository: "${repo}". Pass a repository ending in .git, a URL git can clone, an ssh address or a local path of a repository.`);
42
+ }
43
+ DepUtils.repo = repo;
44
+ /**
45
+ * Extracts the name a dependency is known by from its repository URL.
46
+ *
47
+ * Only a GitHub repository has a name that can be derived without asking, and the name it derives
48
+ * is the one the alias of the dependency takes everywhere else, so it is derived here and nowhere
49
+ * else.
50
+ * @param repo - The repository URL.
51
+ * @returns The repository name, as `<user>.<name>`.
52
+ * @throws { Error } When the repository is not a GitHub one, saying the name has to be given.
53
+ *
54
+ * @example
55
+ * ```ts
56
+ * DepUtils.getRepoName('https://github.com/NetFeez/omega.git'); // 'NetFeez.omega'
57
+ * ```
58
+ */
59
+ function getRepoName(repo) {
60
+ const match = repo.match(GITHUB_REPO_REGEX);
61
+ if (match) {
62
+ const user = match[1] || match[3];
63
+ const repoName = match[2] || match[4];
64
+ return `${user}.${repoName}`;
65
+ }
66
+ throw new Error(`Cannot derive a name from "${repo}": only GitHub repositories are named automatically, pass the name yourself.`);
67
+ }
68
+ DepUtils.getRepoName = getRepoName;
69
+ })(DepUtils || (DepUtils = {}));
70
+ export default DepUtils;
71
+ //# sourceMappingURL=DepUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DepUtils.js","sourceRoot":"","sources":["../../src/dependency/DepUtils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,KAAW,QAAQ,CAiFxB;AAjFD,WAAiB,QAAQ;IAmBrB;;;OAGG;IACH,MAAM,eAAe,GAAG,sDAAsD,CAAC;IAE/E;;OAEG;IACH,MAAM,iBAAiB,GAAG,sGAAsG,CAAC;IAEjI;;;OAGG;IACH,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IAElC;;;;;;;;;;;;;;OAcG;IACH,SAAgB,IAAI,CAAC,IAAa;QAC9B,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,IAAI,IAAI,CAAC,CAAC;QAC3G,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,IAAI,2GAA2G,CAAC,CAAC;IAChP,CAAC;IAHe,SAAA,IAAI,OAGnB,CAAA;IAED;;;;;;;;;;;;;;OAcG;IACH,SAAgB,WAAW,CAAC,IAAY;QACpC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAC5C,IAAI,KAAK,EAAE,CAAC;YACR,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC;YAClC,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC;YACtC,OAAO,GAAG,IAAI,IAAI,QAAQ,EAAE,CAAC;QACjC,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,8BAA8B,IAAI,8EAA8E,CAAC,CAAC;IACtI,CAAC;IATe,SAAA,WAAW,cAS1B,CAAA;AACL,CAAC,EAjFgB,QAAQ,KAAR,QAAQ,QAiFxB;AAED,eAAe,QAAQ,CAAC"}
@@ -0,0 +1,81 @@
1
+ import type Logger from "@netfeez/vterm";
2
+ import schema from "../schema/schema.js";
3
+ import type AliasCompiler from "../resolve/AliasCompiler.js";
4
+ import type OutputPolicy from "../task/OutputPolicy.js";
5
+ export declare abstract class Dependency {
6
+ readonly flowFolder: string;
7
+ readonly projectRoot: string;
8
+ /**
9
+ * The deadline every acquisition of a source runs under, in milliseconds. Acquisition is bounded so a
10
+ * repository that never answers is reported instead of waiting forever.
11
+ *
12
+ * @remarks It is not the deadline of a build step, which is the one the schema declares: a clone or an
13
+ * install of a large source legitimately takes longer than a build step, and cutting it at the build
14
+ * deadline would report a failure for work that is still on its way.
15
+ */
16
+ static readonly ACQUISITION_TIME_MS: number;
17
+ protected readonly logger: Logger | null;
18
+ protected readonly policy: OutputPolicy | null;
19
+ readonly name: string;
20
+ readonly builder: schema.Builder;
21
+ readonly resolver: AliasCompiler.Resolver;
22
+ /**
23
+ * Creates the dependency over the two roots it works between.
24
+ * @param flowFolder - The flow directory (`.depflow`) every checkout of the project lives in.
25
+ * @param projectRoot - The root of the project the artifacts of the dependency are meant to land in.
26
+ * @param info - The identity, the build pipeline and the resolver entries of the dependency.
27
+ * @param logger - Where the acquisition and the build of the dependency report to.
28
+ * @param policy - How the output of the commands the dependency runs is presented. Without it the
29
+ * dependency falls back to its logger, which streams the live output and says nothing else about it.
30
+ *
31
+ * @remarks The two roots are not the same and are not interchangeable: the flow folder owns the working
32
+ * copy of a dependency, the project root owns what the project consumes. A pipeline reads from the first
33
+ * and deposits into the second, which is why both travel together instead of one being derived from the
34
+ * other.
35
+ *
36
+ * @remarks The logger and the policy are not two ways of saying the same thing. The logger carries what
37
+ * the dependency decides to say about itself, and it says it whatever the user asked to be shown; the
38
+ * policy carries what the commands printed, and how much of it is shown depends on that. A dependency
39
+ * built through the CLI gets both, and a dependency built from a test gets neither.
40
+ */
41
+ constructor(flowFolder: string, projectRoot: string, info: Dependency.Info, logger?: Logger | null, policy?: OutputPolicy | null);
42
+ /**
43
+ * Resolves a folder of the dependency, relative to the flow folder, and guarantees it stays inside it.
44
+ * @param segments - The path of the folder inside the flow folder.
45
+ * @returns The normalized path of the folder.
46
+ * @throws { Error } When the segments escape the flow folder.
47
+ *
48
+ * @remarks A name is an identity, never a path: the schema rejects the ones that are not a single
49
+ * segment, and this is where the ones that reach a dependency any other way are stopped, before
50
+ * anything is cloned into them or removed from them.
51
+ */
52
+ protected resolve(...segments: string[]): string;
53
+ /**
54
+ * Whether the dependency is installed, which is the folder of its files being in place.
55
+ * @returns A promise resolving to `true` when the files of the dependency are there.
56
+ */
57
+ abstract isInstalled(): Promise<boolean>;
58
+ /**
59
+ * Install the dependency.
60
+ * This method should handle the installation process, such as downloading files, setting up configurations, etc.
61
+ */
62
+ abstract install(): Promise<void>;
63
+ /**
64
+ * Uninstall the dependency.
65
+ * This method should handle the uninstallation process, such as removing files, cleaning up configurations, etc.
66
+ */
67
+ abstract uninstall(): Promise<void>;
68
+ /**
69
+ * Build the dependency.
70
+ * This method should handle the build process, such as compiling code, bundling files, etc.
71
+ */
72
+ abstract build(): Promise<void>;
73
+ }
74
+ export declare namespace Dependency {
75
+ interface Info {
76
+ name: string;
77
+ builder?: schema.Builder;
78
+ resolver?: AliasCompiler.Resolver;
79
+ }
80
+ }
81
+ export default Dependency;
@@ -0,0 +1,71 @@
1
+ /**
2
+ * @author NetFeez <netfeez.dev@gmail.com>.
3
+ * @description Base contract for installable dependencies with their build pipeline and resolver.
4
+ * @license Apache-2.0
5
+ */
6
+ import { Path } from "@netfeez/common-node";
7
+ export class Dependency {
8
+ flowFolder;
9
+ projectRoot;
10
+ /**
11
+ * The deadline every acquisition of a source runs under, in milliseconds. Acquisition is bounded so a
12
+ * repository that never answers is reported instead of waiting forever.
13
+ *
14
+ * @remarks It is not the deadline of a build step, which is the one the schema declares: a clone or an
15
+ * install of a large source legitimately takes longer than a build step, and cutting it at the build
16
+ * deadline would report a failure for work that is still on its way.
17
+ */
18
+ static ACQUISITION_TIME_MS = 300000;
19
+ logger;
20
+ policy;
21
+ name;
22
+ builder;
23
+ resolver;
24
+ /**
25
+ * Creates the dependency over the two roots it works between.
26
+ * @param flowFolder - The flow directory (`.depflow`) every checkout of the project lives in.
27
+ * @param projectRoot - The root of the project the artifacts of the dependency are meant to land in.
28
+ * @param info - The identity, the build pipeline and the resolver entries of the dependency.
29
+ * @param logger - Where the acquisition and the build of the dependency report to.
30
+ * @param policy - How the output of the commands the dependency runs is presented. Without it the
31
+ * dependency falls back to its logger, which streams the live output and says nothing else about it.
32
+ *
33
+ * @remarks The two roots are not the same and are not interchangeable: the flow folder owns the working
34
+ * copy of a dependency, the project root owns what the project consumes. A pipeline reads from the first
35
+ * and deposits into the second, which is why both travel together instead of one being derived from the
36
+ * other.
37
+ *
38
+ * @remarks The logger and the policy are not two ways of saying the same thing. The logger carries what
39
+ * the dependency decides to say about itself, and it says it whatever the user asked to be shown; the
40
+ * policy carries what the commands printed, and how much of it is shown depends on that. A dependency
41
+ * built through the CLI gets both, and a dependency built from a test gets neither.
42
+ */
43
+ constructor(flowFolder, projectRoot, info, logger, policy) {
44
+ this.flowFolder = flowFolder;
45
+ this.projectRoot = projectRoot;
46
+ this.name = info.name;
47
+ this.builder = info.builder || [];
48
+ this.resolver = info.resolver || {};
49
+ this.logger = logger || null;
50
+ this.policy = policy || null;
51
+ }
52
+ /**
53
+ * Resolves a folder of the dependency, relative to the flow folder, and guarantees it stays inside it.
54
+ * @param segments - The path of the folder inside the flow folder.
55
+ * @returns The normalized path of the folder.
56
+ * @throws { Error } When the segments escape the flow folder.
57
+ *
58
+ * @remarks A name is an identity, never a path: the schema rejects the ones that are not a single
59
+ * segment, and this is where the ones that reach a dependency any other way are stopped, before
60
+ * anything is cloned into them or removed from them.
61
+ */
62
+ resolve(...segments) {
63
+ const root = Path.normalize(this.flowFolder);
64
+ const folder = Path.normalize(Path.join(root, ...segments));
65
+ if (!Path.isInside(root, folder))
66
+ throw new Error(`Dependency "${this.name}" resolves outside of the flow folder: ${folder}`);
67
+ return folder;
68
+ }
69
+ }
70
+ export default Dependency;
71
+ //# sourceMappingURL=Dependency.js.map