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.
- package/README.md +108 -43
- package/dist/builder/Builder.d.ts +279 -0
- package/dist/builder/Builder.js +391 -0
- package/dist/builder/Builder.js.map +1 -0
- package/dist/cli/CLI.d.ts +157 -0
- package/dist/cli/CLI.js +214 -0
- package/dist/cli/CLI.js.map +1 -0
- package/dist/cli/DepFLowCLI.d.ts +93 -0
- package/dist/cli/DepFLowCLI.js +413 -0
- package/dist/cli/DepFLowCLI.js.map +1 -0
- package/dist/cli/Flags.d.ts +106 -0
- package/dist/cli/Flags.js +125 -0
- package/dist/cli/Flags.js.map +1 -0
- package/dist/cli/bin.js +68 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/config/Config.d.ts +690 -0
- package/dist/config/Config.js +45 -0
- package/dist/config/Config.js.map +1 -0
- package/dist/config/ImportMap.d.ts +60 -0
- package/dist/config/ImportMap.js +66 -0
- package/dist/config/ImportMap.js.map +1 -0
- package/dist/config/JsonSchema.d.ts +12 -0
- package/dist/config/JsonSchema.js +26 -0
- package/dist/config/JsonSchema.js.map +1 -0
- package/dist/config/Settings.d.ts +201 -0
- package/dist/config/Settings.js +191 -0
- package/dist/config/Settings.js.map +1 -0
- package/dist/config/TSConfig.d.ts +73 -0
- package/dist/config/TSConfig.js +73 -0
- package/dist/config/TSConfig.js.map +1 -0
- package/dist/config/codecs/JsonCodec.d.ts +30 -0
- package/dist/config/codecs/JsonCodec.js +31 -0
- package/dist/config/codecs/JsonCodec.js.map +1 -0
- package/dist/config/codecs/YamlCodec.d.ts +62 -0
- package/dist/config/codecs/YamlCodec.js +89 -0
- package/dist/config/codecs/YamlCodec.js.map +1 -0
- package/dist/dependency/DepUtils.d.ts +50 -0
- package/dist/dependency/DepUtils.js +71 -0
- package/dist/dependency/DepUtils.js.map +1 -0
- package/dist/dependency/Dependency.d.ts +81 -0
- package/dist/dependency/Dependency.js +71 -0
- package/dist/dependency/Dependency.js.map +1 -0
- package/dist/dependency/Git.d.ts +75 -0
- package/dist/dependency/Git.js +97 -0
- package/dist/dependency/Git.js.map +1 -0
- package/dist/dependency/GitDependency.d.ts +30 -0
- package/dist/dependency/GitDependency.js +79 -0
- package/dist/dependency/GitDependency.js.map +1 -0
- package/dist/dependency/NpmDependency.d.ts +27 -0
- package/dist/dependency/NpmDependency.js +91 -0
- package/dist/dependency/NpmDependency.js.map +1 -0
- package/{build/support/PathResolver → dist/resolve}/AliasCompiler.d.ts +18 -5
- package/{build/support/PathResolver → dist/resolve}/AliasCompiler.js +31 -9
- package/dist/resolve/AliasCompiler.js.map +1 -0
- package/{build/support/PathResolver → dist/resolve}/PathResolver.d.ts +25 -8
- package/dist/resolve/PathResolver.js +133 -0
- package/dist/resolve/PathResolver.js.map +1 -0
- package/dist/resolve/PathRewriter.d.ts +24 -0
- package/{build/support/PathResolver → dist/resolve}/PathRewriter.js +21 -11
- package/dist/resolve/PathRewriter.js.map +1 -0
- package/{build → dist}/schema/Config/Builder.d.ts +114 -49
- package/dist/schema/Config/Builder.js +78 -0
- package/dist/schema/Config/Builder.js.map +1 -0
- package/{build → dist}/schema/Config/Config.d.ts +169 -78
- package/dist/schema/Config/Config.js +62 -0
- package/dist/schema/Config/Config.js.map +1 -0
- package/{build → dist}/schema/Config/Dependency.d.ts +219 -89
- package/dist/schema/Config/Dependency.js +80 -0
- package/dist/schema/Config/Dependency.js.map +1 -0
- package/{build → dist}/schema/Config/Extractor.d.ts +41 -17
- package/dist/schema/Config/Extractor.js +43 -0
- package/dist/schema/Config/Extractor.js.map +1 -0
- package/{build → dist}/schema/Config/Resolver.d.ts +25 -8
- package/dist/schema/Config/Resolver.js +43 -0
- package/dist/schema/Config/Resolver.js.map +1 -0
- package/{build → dist}/schema/Config/Transform.d.ts +22 -5
- package/dist/schema/Config/Transform.js +51 -0
- package/dist/schema/Config/Transform.js.map +1 -0
- package/dist/schema/Defaults.d.ts +20 -0
- package/dist/schema/Defaults.js +24 -0
- package/dist/schema/Defaults.js.map +1 -0
- package/dist/schema/ImportMap.d.ts +30 -0
- package/dist/schema/ImportMap.js +28 -0
- package/dist/schema/ImportMap.js.map +1 -0
- package/{build → dist}/schema/TSConfig.d.ts +23 -9
- package/dist/schema/TSConfig.js +39 -0
- package/dist/schema/TSConfig.js.map +1 -0
- package/{build → dist}/schema/schema.d.ts +11 -2
- package/{build → dist}/schema/schema.js +11 -2
- package/dist/schema/schema.js.map +1 -0
- package/dist/task/Command.d.ts +287 -0
- package/dist/task/Command.js +404 -0
- package/dist/task/Command.js.map +1 -0
- package/dist/task/Group.d.ts +15 -0
- package/dist/task/Group.js +29 -0
- package/dist/task/Group.js.map +1 -0
- package/dist/task/OutputPolicy.d.ts +262 -0
- package/dist/task/OutputPolicy.js +364 -0
- package/dist/task/OutputPolicy.js.map +1 -0
- package/dist/task/Task.d.ts +210 -0
- package/dist/task/Task.js +312 -0
- package/dist/task/Task.js.map +1 -0
- package/package.json +13 -10
- package/.gitignore +0 -7
- package/build/cli/DepFLowCLI.d.ts +0 -16
- package/build/cli/DepFLowCLI.js +0 -254
- package/build/cli/DepFLowCLI.js.map +0 -1
- package/build/cli/bin.js +0 -38
- package/build/cli/bin.js.map +0 -1
- package/build/config/Config.d.ts +0 -28
- package/build/config/Config.js +0 -46
- package/build/config/Config.js.map +0 -1
- package/build/config/ImportMap.d.ts +0 -51
- package/build/config/ImportMap.js +0 -97
- package/build/config/ImportMap.js.map +0 -1
- package/build/config/TSConfig.d.ts +0 -54
- package/build/config/TSConfig.js +0 -104
- package/build/config/TSConfig.js.map +0 -1
- package/build/schema/Config/Builder.js +0 -48
- package/build/schema/Config/Builder.js.map +0 -1
- package/build/schema/Config/Config.js +0 -20
- package/build/schema/Config/Config.js.map +0 -1
- package/build/schema/Config/Dependency.js +0 -25
- package/build/schema/Config/Dependency.js.map +0 -1
- package/build/schema/Config/Extractor.js +0 -25
- package/build/schema/Config/Extractor.js.map +0 -1
- package/build/schema/Config/Resolver.js +0 -25
- package/build/schema/Config/Resolver.js.map +0 -1
- package/build/schema/Config/Transform.js +0 -27
- package/build/schema/Config/Transform.js.map +0 -1
- package/build/schema/ImportMap.d.ts +0 -22
- package/build/schema/ImportMap.js +0 -12
- package/build/schema/ImportMap.js.map +0 -1
- package/build/schema/TSConfig.js +0 -19
- package/build/schema/TSConfig.js.map +0 -1
- package/build/schema/schema.js.map +0 -1
- package/build/support/Builder/Builder.d.ts +0 -46
- package/build/support/Builder/Builder.js +0 -116
- package/build/support/Builder/Builder.js.map +0 -1
- package/build/support/Dependency/Dependency.d.ts +0 -38
- package/build/support/Dependency/Dependency.js +0 -14
- package/build/support/Dependency/Dependency.js.map +0 -1
- package/build/support/Dependency/GitDependency.d.ts +0 -20
- package/build/support/Dependency/GitDependency.js +0 -67
- package/build/support/Dependency/GitDependency.js.map +0 -1
- package/build/support/Dependency/NpmDependency.d.ts +0 -18
- package/build/support/Dependency/NpmDependency.js +0 -65
- package/build/support/Dependency/NpmDependency.js.map +0 -1
- package/build/support/Git.d.ts +0 -53
- package/build/support/Git.js +0 -86
- package/build/support/Git.js.map +0 -1
- package/build/support/PathResolver/AliasCompiler.js.map +0 -1
- package/build/support/PathResolver/PathResolver.js +0 -105
- package/build/support/PathResolver/PathResolver.js.map +0 -1
- package/build/support/PathResolver/PathRewriter.d.ts +0 -18
- package/build/support/PathResolver/PathRewriter.js.map +0 -1
- package/build/support/PathResolver/Utils.d.ts +0 -36
- package/build/support/PathResolver/Utils.js +0 -45
- package/build/support/PathResolver/Utils.js.map +0 -1
- package/build/support/Task/Command.d.ts +0 -49
- package/build/support/Task/Command.js +0 -100
- package/build/support/Task/Command.js.map +0 -1
- package/build/support/Task/Task.d.ts +0 -84
- package/build/support/Task/Task.js +0 -145
- package/build/support/Task/Task.js.map +0 -1
- package/build/support/Utils.d.ts +0 -40
- package/build/support/Utils.js +0 -138
- package/build/support/Utils.js.map +0 -1
- package/build/support/Validator.d.ts +0 -22
- package/build/support/Validator.js +0 -28
- package/build/support/Validator.js.map +0 -1
- /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
|