@gesslar/bedoc 1.1.0 → 1.3.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/dist/types/cli.d.ts +3 -0
- package/dist/types/cli.d.ts.map +10 -0
- package/dist/types/core/ActionManager.d.ts +27 -0
- package/dist/types/core/ActionManager.d.ts.map +10 -0
- package/dist/types/core/Configuration.d.ts +27 -0
- package/dist/types/core/Configuration.d.ts.map +10 -0
- package/dist/types/core/ConfigurationParameters.d.ts +38 -0
- package/dist/types/core/ConfigurationParameters.d.ts.map +10 -0
- package/dist/types/core/Conveyor.d.ts +47 -0
- package/dist/types/core/Conveyor.d.ts.map +10 -0
- package/dist/types/core/Core.d.ts +53 -0
- package/dist/types/core/Core.d.ts.map +10 -0
- package/dist/types/core/Discovery.d.ts +73 -0
- package/dist/types/core/Discovery.d.ts.map +10 -0
- package/dist/types/core/HookManager.d.ts +60 -0
- package/dist/types/core/HookManager.d.ts.map +10 -0
- package/dist/types/core/Logger.d.ts +55 -0
- package/dist/types/core/Logger.d.ts.map +10 -0
- package/dist/types/core/action/ParseManager.d.ts +8 -0
- package/dist/types/core/action/ParseManager.d.ts.map +10 -0
- package/dist/types/core/action/PrintManager.d.ts +8 -0
- package/dist/types/core/action/PrintManager.d.ts.map +10 -0
- package/dist/types/core/util/ActionUtil.d.ts +35 -0
- package/dist/types/core/util/ActionUtil.d.ts.map +10 -0
- package/dist/types/core/util/DataUtil.d.ts +52 -0
- package/dist/types/core/util/DataUtil.d.ts.map +10 -0
- package/dist/types/core/util/FDUtil.d.ts +146 -0
- package/dist/types/core/util/FDUtil.d.ts.map +10 -0
- package/dist/types/core/util/ModuleUtil.d.ts +27 -0
- package/dist/types/core/util/ModuleUtil.d.ts.map +10 -0
- package/dist/types/core/util/StringUtil.d.ts +5 -0
- package/dist/types/core/util/StringUtil.d.ts.map +10 -0
- package/dist/types/core/util/TypeSpec.d.ts +42 -0
- package/dist/types/core/util/TypeSpec.d.ts.map +10 -0
- package/dist/types/core/util/ValidUtil.d.ts +29 -0
- package/dist/types/core/util/ValidUtil.d.ts.map +10 -0
- package/package.json +10 -3
- package/src/cli.js +12 -11
- package/src/core/ActionManager.js +85 -22
- package/src/core/Conveyor.js +36 -16
- package/src/core/Core.js +68 -78
- package/src/core/Discovery.js +219 -65
- package/src/core/{HooksManager.js → HookManager.js} +14 -13
- package/src/core/Logger.js +3 -11
- package/src/core/action/ParseManager.js +0 -19
- package/src/core/action/PrintManager.js +0 -19
- package/src/core/util/DataUtil.js +3 -1
- package/src/core/util/FDUtil.js +1 -1
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
export type FDType = 'file' | 'directory';
|
|
2
|
+
|
|
3
|
+
export interface FileMap {
|
|
4
|
+
path: string;
|
|
5
|
+
uri: string;
|
|
6
|
+
absolutePath: string;
|
|
7
|
+
absoluteUri: string;
|
|
8
|
+
name: string;
|
|
9
|
+
module: string;
|
|
10
|
+
extension: string;
|
|
11
|
+
isFile: true;
|
|
12
|
+
isDirectory: false;
|
|
13
|
+
directory?: DirMap;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface DirMap {
|
|
17
|
+
path: string;
|
|
18
|
+
uri: string;
|
|
19
|
+
absolutePath: string;
|
|
20
|
+
absoluteUri: string;
|
|
21
|
+
name: string;
|
|
22
|
+
separator: string;
|
|
23
|
+
isFile: false;
|
|
24
|
+
isDirectory: true;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface FilenameParts {
|
|
28
|
+
basename: string;
|
|
29
|
+
dirname: string;
|
|
30
|
+
extname: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const fdType: Readonly<Record<Uppercase<FDType>, FDType>>;
|
|
34
|
+
export const fdTypes: readonly FDType[];
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Compose a directory map from a path
|
|
38
|
+
*
|
|
39
|
+
* @param {string} directory - The directory
|
|
40
|
+
* @returns {DirMap} A directory object
|
|
41
|
+
*/
|
|
42
|
+
export function composeDirectory(directory: string): DirMap;
|
|
43
|
+
/**
|
|
44
|
+
* Compose a file path from a directory and a file
|
|
45
|
+
*
|
|
46
|
+
* @param {string|DirMap} directoryNameorObject - The directory
|
|
47
|
+
* @param {string} fileName - The file
|
|
48
|
+
* @returns {FileMap} A file object
|
|
49
|
+
*/
|
|
50
|
+
export function composeFilename(directoryNameorObject: string | DirMap, fileName: string): FileMap;
|
|
51
|
+
/**
|
|
52
|
+
* Deconstruct a filename into parts
|
|
53
|
+
*
|
|
54
|
+
* @param {string} fileName - The filename to deconstruct
|
|
55
|
+
* @returns {FilenameParts} The filename parts
|
|
56
|
+
*/
|
|
57
|
+
export function deconstructFilenameToParts(fileName: string): FilenameParts;
|
|
58
|
+
/**
|
|
59
|
+
* Fix slashes in a path
|
|
60
|
+
*
|
|
61
|
+
* @param {string} pathName - The path to fix
|
|
62
|
+
* @returns {string} The fixed path
|
|
63
|
+
*/
|
|
64
|
+
export function fixSlashes(pathName: string): string;
|
|
65
|
+
/**
|
|
66
|
+
* Retrieve all files matching a specific glob pattern.
|
|
67
|
+
*
|
|
68
|
+
* @param {string|string[]} globPattern - The glob pattern(s) to search.
|
|
69
|
+
* @returns {Promise<FileMap[]>} An array of file objects
|
|
70
|
+
* @throws {Error} Throws an error for invalid input or search failure.
|
|
71
|
+
*/
|
|
72
|
+
export function getFiles(globPattern: string | string[]): Promise<FileMap[]>;
|
|
73
|
+
/**
|
|
74
|
+
* Lists the contents of a directory.
|
|
75
|
+
*
|
|
76
|
+
* @param {string} directory - The directory to list.
|
|
77
|
+
* @returns {Promise<{files: FileMap[], directories: DirMap[]}>} The files and
|
|
78
|
+
* directories in the directory.
|
|
79
|
+
*/
|
|
80
|
+
export function ls(directory: string): Promise<{
|
|
81
|
+
files: FileMap[];
|
|
82
|
+
directories: DirMap[];
|
|
83
|
+
}>;
|
|
84
|
+
/**
|
|
85
|
+
* Map a directory to a DirMap
|
|
86
|
+
*
|
|
87
|
+
* @param {string} directoryName - The directory to map
|
|
88
|
+
* @returns {DirMap} A directory object
|
|
89
|
+
*/
|
|
90
|
+
export function mapDirectory(directoryName: string): DirMap;
|
|
91
|
+
/**
|
|
92
|
+
* Map a file to a FileMap
|
|
93
|
+
*
|
|
94
|
+
* @param {string} fileName - The file to map
|
|
95
|
+
* @returns {FileMap} A file object
|
|
96
|
+
*/
|
|
97
|
+
export function mapFilename(fileName: string): FileMap;
|
|
98
|
+
/**
|
|
99
|
+
* Convert a path to a URI
|
|
100
|
+
*
|
|
101
|
+
* @param {string} pathName - The path to convert
|
|
102
|
+
* @returns {string} The URI
|
|
103
|
+
* @throws {Error} If the path is not a valid file path
|
|
104
|
+
*/
|
|
105
|
+
export function pathToUri(pathName: string): string;
|
|
106
|
+
/**
|
|
107
|
+
* Reads the content of a file synchronously.
|
|
108
|
+
*
|
|
109
|
+
* @param {FileMap} fileObject - The file map containing the file path
|
|
110
|
+
* @returns {string} The file contents
|
|
111
|
+
*/
|
|
112
|
+
export function readFile(fileObject: FileMap): string;
|
|
113
|
+
/**
|
|
114
|
+
* Resolves a path to an absolute path
|
|
115
|
+
*
|
|
116
|
+
* @param {string} directoryName - The path to resolve
|
|
117
|
+
* @returns {DirMap} The directory object
|
|
118
|
+
* @throws {Error}
|
|
119
|
+
*/
|
|
120
|
+
export function resolveDirectory(directoryName: string): DirMap;
|
|
121
|
+
/**
|
|
122
|
+
* Resolves a file to an absolute path
|
|
123
|
+
*
|
|
124
|
+
* @param {string} fileName - The file to resolve
|
|
125
|
+
* @param {DirMap} [directoryObject] - The directory object to resolve the
|
|
126
|
+
* file in
|
|
127
|
+
* @returns {FileMap} A file object (validated)
|
|
128
|
+
* @throws {Error}
|
|
129
|
+
*/
|
|
130
|
+
export function resolveFilename(fileName: string, directoryObject?: DirMap | null): FileMap;
|
|
131
|
+
/**
|
|
132
|
+
* Convert a URI to a path
|
|
133
|
+
*
|
|
134
|
+
* @param {string} pathName - The URI to convert
|
|
135
|
+
* @returns {string} The path
|
|
136
|
+
* @throws {Error} If the URI is not a valid file URL
|
|
137
|
+
*/
|
|
138
|
+
export function uriToPath(pathName: string): string;
|
|
139
|
+
/**
|
|
140
|
+
* Writes content to a file synchronously.
|
|
141
|
+
*
|
|
142
|
+
* @param {FileMap} fileObject - The file map containing the file path
|
|
143
|
+
* @param {string} content - The content to write
|
|
144
|
+
*/
|
|
145
|
+
export function writeFile(fileObject: FileMap, content: string): void;
|
|
146
|
+
//# sourceMappingURL=FDUtil.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"file": "FDUtil.d.ts",
|
|
4
|
+
"sourceRoot": "",
|
|
5
|
+
"sources": [
|
|
6
|
+
"../../../../src/core/util/FDUtil.js"
|
|
7
|
+
],
|
|
8
|
+
"names": [],
|
|
9
|
+
"mappings": "AAgBA,yBAAkE;AAFlE,0BAA6C;AA0N7C;;;;;GAKG;AACH,4CAHW,MAAM,GACJ,MAAM,CAIlB;AAjJD;;;;;;GAMG;AACH,uDAJW,MAAM,GAAC,MAAM,YACb,MAAM,GACJ,MAAM,CAiBlB;AAyCD;;;;;GAKG;AACH,qDAHW,MAAM,GACJ,MAAM,CAMlB;AAtJD;;;;;GAKG;AACH,qCAHW,MAAM,GACJ,MAAM,CAIlB;AAgJD;;;;;;GAMG;AACH,sCAJW,MAAM,GAAC,MAAM,EAAE,GACb,OAAO,CAAC,MAAM,EAAE,CAAC,CA+B7B;AAqCD;;;;;;GAMG;AACH,8BAJW,MAAM,GACJ,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,WAAW,EAAE,MAAM,EAAE,CAAA;CAAC,CAAC,CAsB7D;AAjID;;;;;GAKG;AACH,4CAHW,MAAM,GACJ,MAAM,CAalB;AArCD;;;;;GAKG;AACH,sCAHW,MAAM,GACJ,MAAM,CAclB;AA7GD;;;;;;GAMG;AACH,oCAJW,MAAM,GACJ,MAAM,CAUlB;AAoOD;;;;;GAKG;AACH,qCAHW,MAAM,GACJ,OAAO,CAAC,MAAM,CAAC,CAW3B;AA9ED;;;;;;GAMG;AACH,gDAJW,MAAM,GACJ,MAAM,CAmBlB;AA1KD;;;;;;;;GAQG;AACH,0CANW,MAAM,oBACN,MAAM,GAEJ,MAAM,CA2BlB;AAjDD;;;;;;GAMG;AACH,oCAJW,MAAM,GACJ,MAAM,CAUlB;AAqOD;;;;;GAKG;AACH,sCAHW,MAAM,WACN,MAAM,QAShB"
|
|
10
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { FileMap } from './FDUtil';
|
|
2
|
+
|
|
3
|
+
export default class ModuleUtil {
|
|
4
|
+
/**
|
|
5
|
+
* Requires a module synchronously
|
|
6
|
+
*
|
|
7
|
+
* @param {FileMap} fileObject - The file to require
|
|
8
|
+
* @returns {unknown} The required module
|
|
9
|
+
*/
|
|
10
|
+
static require(fileObject: FileMap): unknown;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Loads a JSON file asynchronously
|
|
14
|
+
*
|
|
15
|
+
* @param {FileMap} jsonFileObject - The JSON file to load
|
|
16
|
+
* @returns {Promise<Record<string, unknown>>} The parsed JSON content
|
|
17
|
+
*/
|
|
18
|
+
static loadJson(jsonFileObject: FileMap): Promise<Record<string, unknown>>;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Loads the package.json file asynchronously
|
|
22
|
+
*
|
|
23
|
+
* @returns {Promise<Record<string, unknown>>} The parsed package.json content
|
|
24
|
+
*/
|
|
25
|
+
static loadPackageJson(): Promise<Record<string, unknown>>;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=ModuleUtil.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"file": "ModuleUtil.d.ts",
|
|
4
|
+
"sourceRoot": "",
|
|
5
|
+
"sources": [
|
|
6
|
+
"../../../../src/core/util/ModuleUtil.js"
|
|
7
|
+
],
|
|
8
|
+
"names": [],
|
|
9
|
+
"mappings": "AAGA;IACE;;;;;OAKG;IACH,2BAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;;;OAKG;IACH,gCAHW,MAAM,GACJ,OAAO,CAAC,MAAM,CAAC,CAO3B;IAED;;;;OAIG;IACH,0BAFa,OAAO,CAAC,MAAM,CAAC,CAO3B;CACF"
|
|
10
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { DataType } from './DataUtil';
|
|
2
|
+
|
|
3
|
+
interface TypeSpecification {
|
|
4
|
+
typeName: DataType;
|
|
5
|
+
array: boolean;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface TypeSpecOptions {
|
|
9
|
+
delimiter?: string;
|
|
10
|
+
allowEmpty?: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface TypeSpecJSON {
|
|
14
|
+
specs: TypeSpecification[];
|
|
15
|
+
length: number;
|
|
16
|
+
stringRepresentation: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default class TypeSpec {
|
|
20
|
+
constructor(typeString: string, options?: TypeSpecOptions);
|
|
21
|
+
|
|
22
|
+
readonly specs: readonly TypeSpecification[];
|
|
23
|
+
readonly length: number;
|
|
24
|
+
readonly stringRepresentation: string;
|
|
25
|
+
|
|
26
|
+
toString(): string;
|
|
27
|
+
toJSON(): TypeSpecJSON;
|
|
28
|
+
|
|
29
|
+
forEach(callback: (spec: TypeSpecification) => void): void;
|
|
30
|
+
every(callback: (spec: TypeSpecification) => boolean): boolean;
|
|
31
|
+
some(callback: (spec: TypeSpecification) => boolean): boolean;
|
|
32
|
+
filter(callback: (spec: TypeSpecification) => boolean): TypeSpecification[];
|
|
33
|
+
map<T>(callback: (spec: TypeSpecification) => T): T[];
|
|
34
|
+
reduce<T>(callback: (acc: T, spec: TypeSpecification) => T, initialValue: T): T;
|
|
35
|
+
find(callback: (spec: TypeSpecification) => boolean): TypeSpecification | undefined;
|
|
36
|
+
|
|
37
|
+
match(value: unknown, options?: TypeSpecOptions): boolean;
|
|
38
|
+
|
|
39
|
+
#specs: TypeSpecification[];
|
|
40
|
+
#parse(typeString: string, options?: TypeSpecOptions): void;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=TypeSpec.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"file": "TypeSpec.d.ts",
|
|
4
|
+
"sourceRoot": "",
|
|
5
|
+
"sources": [
|
|
6
|
+
"../../../../src/core/util/TypeSpec.js"
|
|
7
|
+
],
|
|
8
|
+
"names": [],
|
|
9
|
+
"mappings": "AAIA;IAGE,uCAQC;IAJC,aAAwB;IACxB,eAAgC;IAChC,6BAA2C;IAI7C,mBAMC;IAED;;;;MAOC;IAED,6BAEC;IACD,8BAEC;IACD,6BAEC;IACD,6BAEC;IACD,0BAEC;IACD,8CAEC;IACD,yBAEC;IAED,yCAqCC;;CAoBF"
|
|
10
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import TypeSpec from './TypeSpec';
|
|
2
|
+
|
|
3
|
+
interface ValidTypeOptions {
|
|
4
|
+
allowEmpty?: boolean;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Validates a value against a type
|
|
9
|
+
*
|
|
10
|
+
* @throws {Error} If the value does not match the expected type
|
|
11
|
+
*/
|
|
12
|
+
export function validType(
|
|
13
|
+
value: unknown,
|
|
14
|
+
type: string | TypeSpec,
|
|
15
|
+
options?: ValidTypeOptions,
|
|
16
|
+
depth?: number
|
|
17
|
+
): void;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Asserts a condition
|
|
21
|
+
*
|
|
22
|
+
* @throws {Error} If the condition is not met, with optional argument in message
|
|
23
|
+
*/
|
|
24
|
+
export function assert(
|
|
25
|
+
condition: boolean,
|
|
26
|
+
message: string,
|
|
27
|
+
arg?: number | null
|
|
28
|
+
): asserts condition;
|
|
29
|
+
//# sourceMappingURL=ValidUtil.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"file": "ValidUtil.d.ts",
|
|
4
|
+
"sourceRoot": "",
|
|
5
|
+
"sources": [
|
|
6
|
+
"../../../../src/core/util/ValidUtil.js"
|
|
7
|
+
],
|
|
8
|
+
"names": [],
|
|
9
|
+
"mappings": "AAsBA;;;;;;;;GAQG;AACH,kCANW,OAAO,WACP,MAAM,QAEN,MAAM,QAmBhB;AAzCD;;;;;;;GAOG;AACH,iCALW,GAAC,QACD,MAAM,YAEN,MAAM,QAQhB"
|
|
10
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gesslar/bedoc",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Pluggable documentation engine for any language and format",
|
|
5
5
|
"publisher": "gesslar",
|
|
6
6
|
"main": "./src/core/Core.js",
|
|
@@ -14,12 +14,20 @@
|
|
|
14
14
|
"bin": {
|
|
15
15
|
"bedoc": "src/cli.js"
|
|
16
16
|
},
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"import": "./src/core/Core.js",
|
|
20
|
+
"types": "./dist/types/core/Core.d.ts"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
17
23
|
"type": "module",
|
|
24
|
+
"types": "dist/types/index.d.ts",
|
|
18
25
|
"scripts": {
|
|
19
26
|
"lint:check": "npx eslint .",
|
|
20
27
|
"lint:fix": "npx eslint . --fix"
|
|
21
28
|
},
|
|
22
29
|
"dependencies": {
|
|
30
|
+
"@gesslar/bedoc": "^1.2.0",
|
|
23
31
|
"commander": "^13.0.0",
|
|
24
32
|
"dotenv": "^16.4.7",
|
|
25
33
|
"error-stack-parser": "^2.1.4",
|
|
@@ -27,11 +35,10 @@
|
|
|
27
35
|
"globby": "^14.0.2",
|
|
28
36
|
"micromatch": "^4.0.8",
|
|
29
37
|
"node-fetch": "^3.3.2",
|
|
30
|
-
"vscode-uri": "^3.0.8",
|
|
31
38
|
"yaml": "^2.7.0"
|
|
32
39
|
},
|
|
33
40
|
"devDependencies": {
|
|
34
|
-
"@stylistic/eslint-plugin-js": "^
|
|
41
|
+
"@stylistic/eslint-plugin-js": "^3.0.0",
|
|
35
42
|
"axios": "^1.7.9",
|
|
36
43
|
"chokidar": "^4.0.3",
|
|
37
44
|
"eslint": "^9.18.0",
|
package/src/cli.js
CHANGED
|
@@ -63,7 +63,7 @@ const {resolveDirectory} = FDUtil
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
// Create core instance with validated config
|
|
66
|
-
BeDoc
|
|
66
|
+
const bedoc = await BeDoc
|
|
67
67
|
.new({
|
|
68
68
|
options: {
|
|
69
69
|
...optionsWithSources,
|
|
@@ -72,19 +72,20 @@ const {resolveDirectory} = FDUtil
|
|
|
72
72
|
},
|
|
73
73
|
source: Environment.CLI
|
|
74
74
|
})
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
75
|
+
const filesToProcess = bedoc.options.input.map(f => f.absolutePath)
|
|
76
|
+
const result = await bedoc.processFiles(filesToProcess)
|
|
77
|
+
const errored = result.errored
|
|
78
|
+
if(errored.length > 0)
|
|
79
|
+
throw new AggregateError(errored.map(e => e.error), "Error processing files")
|
|
80
|
+
} catch(error) {
|
|
81
|
+
if(error instanceof Error) {
|
|
82
|
+
if(error instanceof AggregateError) {
|
|
83
|
+
error.errors.forEach(e => console.error(e))
|
|
83
84
|
} else {
|
|
84
|
-
console.error(
|
|
85
|
+
console.error(error.message, error.stack)
|
|
85
86
|
}
|
|
86
87
|
} else {
|
|
87
|
-
console.error(
|
|
88
|
+
console.error("Error: %o", error)
|
|
88
89
|
}
|
|
89
90
|
|
|
90
91
|
process.exit(1)
|
|
@@ -1,27 +1,26 @@
|
|
|
1
|
-
import {hookPoints} from "./
|
|
1
|
+
import {hookPoints} from "./HookManager.js"
|
|
2
2
|
|
|
3
3
|
export default class ActionManager {
|
|
4
4
|
#action = null
|
|
5
|
-
#
|
|
6
|
-
#hooks = null
|
|
5
|
+
#hookManager = null
|
|
7
6
|
#contract
|
|
8
|
-
#module
|
|
9
7
|
#log
|
|
10
8
|
#debug
|
|
9
|
+
#file
|
|
11
10
|
|
|
12
11
|
constructor(actionDefinition, logger) {
|
|
13
12
|
this.#log = logger
|
|
14
13
|
this.#debug = this.#log.newDebug()
|
|
15
14
|
|
|
16
|
-
this.#
|
|
15
|
+
this.#initialize(actionDefinition)
|
|
17
16
|
}
|
|
18
17
|
|
|
19
|
-
#
|
|
18
|
+
#initialize(actionDefinition) {
|
|
20
19
|
const debug = this.#debug
|
|
21
20
|
|
|
22
21
|
debug("Setting up action", 2)
|
|
23
22
|
|
|
24
|
-
const {action,
|
|
23
|
+
const {action, file, contract} = actionDefinition
|
|
25
24
|
|
|
26
25
|
if(!action)
|
|
27
26
|
throw new Error("Action is required")
|
|
@@ -29,13 +28,9 @@ export default class ActionManager {
|
|
|
29
28
|
if(!contract)
|
|
30
29
|
throw new Error("Contract is required")
|
|
31
30
|
|
|
32
|
-
if(!module)
|
|
33
|
-
throw new Error("Module is required")
|
|
34
|
-
|
|
35
|
-
this.#module = module
|
|
36
31
|
this.#action = action
|
|
37
32
|
this.#contract = contract
|
|
38
|
-
this.#
|
|
33
|
+
this.#file = file
|
|
39
34
|
|
|
40
35
|
debug("Action setup complete", 2)
|
|
41
36
|
}
|
|
@@ -44,33 +39,101 @@ export default class ActionManager {
|
|
|
44
39
|
return this.#action
|
|
45
40
|
}
|
|
46
41
|
|
|
47
|
-
get
|
|
48
|
-
return this.#
|
|
42
|
+
get hookManager() {
|
|
43
|
+
return this.#hookManager
|
|
49
44
|
}
|
|
50
45
|
|
|
51
|
-
set
|
|
52
|
-
if(this.
|
|
46
|
+
set hookManager(hookManager) {
|
|
47
|
+
if(this.hookManager)
|
|
53
48
|
throw new Error("Hooks already set")
|
|
54
49
|
|
|
55
50
|
this.action.hook = hookManager.on.bind(this.action)
|
|
56
51
|
this.action.HOOKS = hookPoints
|
|
52
|
+
this.#hookManager = hookManager
|
|
57
53
|
this.action.hooks = hookManager.hooks
|
|
58
|
-
this.#hooks = hookManager
|
|
59
54
|
}
|
|
60
55
|
|
|
61
56
|
get contract() {
|
|
62
57
|
return this.#contract
|
|
63
58
|
}
|
|
64
59
|
|
|
65
|
-
get module() {
|
|
66
|
-
return this.#module
|
|
67
|
-
}
|
|
68
|
-
|
|
69
60
|
get meta() {
|
|
70
|
-
return this.#meta
|
|
61
|
+
return this.#action.meta
|
|
71
62
|
}
|
|
72
63
|
|
|
73
64
|
get log() {
|
|
74
65
|
return this.#log
|
|
75
66
|
}
|
|
67
|
+
|
|
68
|
+
async #setupAction() {
|
|
69
|
+
const setup = this.action?.setup
|
|
70
|
+
|
|
71
|
+
if(!setup)
|
|
72
|
+
return
|
|
73
|
+
|
|
74
|
+
await this.action.setup.call(
|
|
75
|
+
this.action, {parent: this, log: this.#log}
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async #cleanupAction() {
|
|
80
|
+
const cleanup = this.action?.cleanup
|
|
81
|
+
|
|
82
|
+
if(!cleanup)
|
|
83
|
+
return
|
|
84
|
+
|
|
85
|
+
await this.action.cleanup.call(this.action)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async #setupHooks() {
|
|
89
|
+
const setup = this.hookManager?.setup
|
|
90
|
+
|
|
91
|
+
if(!setup)
|
|
92
|
+
return
|
|
93
|
+
|
|
94
|
+
await this.hookManager.setup.call(
|
|
95
|
+
this.hookManager.hooks, {parent: this.action, log: this.#log}
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async #cleanupHooks() {
|
|
100
|
+
const cleanup = this.hookManager?.cleanup
|
|
101
|
+
|
|
102
|
+
if(!cleanup)
|
|
103
|
+
return
|
|
104
|
+
|
|
105
|
+
await this.hookManager.cleanup.call(this.hookManager.hooks)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async setupAction() {
|
|
109
|
+
this.#debug("Setting up action for %s", 2, this.meta.action)
|
|
110
|
+
|
|
111
|
+
await this.#setupHooks()
|
|
112
|
+
await this.#setupAction()
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async runAction({file,content}) {
|
|
116
|
+
const func = this.action.run
|
|
117
|
+
|
|
118
|
+
if(!func)
|
|
119
|
+
throw new Error(`No \`run\` function found for action \`${this.meta.action}\``)
|
|
120
|
+
|
|
121
|
+
const actionResult = await func.call(
|
|
122
|
+
this.action, {module: file.module, content}
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
return actionResult
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async cleanupAction() {
|
|
129
|
+
this.#debug("Post action", 2)
|
|
130
|
+
this.#debug("Cleaning up action for %s", 2, this.meta.action)
|
|
131
|
+
|
|
132
|
+
await this.#cleanupHooks()
|
|
133
|
+
await this.#cleanupAction()
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
toString() {
|
|
137
|
+
return `${this.#file?.module || "UNDEFINED"} (${this.meta?.action || "UNDEFINED"})`
|
|
138
|
+
}
|
|
76
139
|
}
|
package/src/core/Conveyor.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import {format} from "node:util"
|
|
2
|
+
|
|
1
3
|
import * as FDUtil from "./util/FDUtil.js"
|
|
2
4
|
|
|
3
5
|
const {readFile, writeFile, composeFilename} = FDUtil
|
|
@@ -6,9 +8,9 @@ export default class Conveyor {
|
|
|
6
8
|
#succeeded = []
|
|
7
9
|
#errored = []
|
|
8
10
|
|
|
9
|
-
constructor(
|
|
10
|
-
this.
|
|
11
|
-
this.
|
|
11
|
+
constructor(parse, print, logger, output) {
|
|
12
|
+
this.parse = parse
|
|
13
|
+
this.print = print
|
|
12
14
|
this.logger = logger
|
|
13
15
|
this.output = output
|
|
14
16
|
}
|
|
@@ -23,15 +25,19 @@ export default class Conveyor {
|
|
|
23
25
|
async convey(files, maxConcurrent = 10) {
|
|
24
26
|
const semaphore = Array(maxConcurrent).fill(Promise.resolve())
|
|
25
27
|
|
|
28
|
+
// Set up the actions
|
|
29
|
+
await this.parse.setupAction()
|
|
30
|
+
await this.print.setupAction()
|
|
31
|
+
|
|
26
32
|
for(const file of files) {
|
|
27
33
|
const slot = Promise.race(semaphore) // Wait for an available slot
|
|
28
34
|
semaphore.push(slot.then(async() => {
|
|
29
35
|
const result = await this.#processFile(file)
|
|
30
|
-
|
|
31
|
-
if(result.status === "success")
|
|
36
|
+
if(result.status === "success" || result.status === "warning")
|
|
32
37
|
this.#succeeded.push({input: file, output: result.file})
|
|
33
|
-
else
|
|
38
|
+
else {
|
|
34
39
|
this.#errored.push({input: file, error: result.error})
|
|
40
|
+
}
|
|
35
41
|
}))
|
|
36
42
|
semaphore.shift() // Remove the oldest promise
|
|
37
43
|
}
|
|
@@ -39,6 +45,10 @@ export default class Conveyor {
|
|
|
39
45
|
// Wait for all tasks to complete
|
|
40
46
|
await Promise.all(semaphore)
|
|
41
47
|
|
|
48
|
+
// Clean up actions
|
|
49
|
+
await this.parse.cleanupAction()
|
|
50
|
+
await this.print.cleanupAction()
|
|
51
|
+
|
|
42
52
|
return {succeeded: this.#succeeded, errored: this.#errored}
|
|
43
53
|
}
|
|
44
54
|
|
|
@@ -50,6 +60,8 @@ export default class Conveyor {
|
|
|
50
60
|
*/
|
|
51
61
|
async #processFile(file) {
|
|
52
62
|
const debug = this.logger.newDebug()
|
|
63
|
+
const warn = (...arg) => this.logger.warn(...arg)
|
|
64
|
+
const {parse, print} = this
|
|
53
65
|
|
|
54
66
|
try {
|
|
55
67
|
debug("Processing file: `%s`", 2, file.path)
|
|
@@ -59,26 +71,36 @@ export default class Conveyor {
|
|
|
59
71
|
debug("Read file content `%s` (%d bytes)", 2, file.path, fileContent.length)
|
|
60
72
|
|
|
61
73
|
// Step 2: Parse file
|
|
62
|
-
const parseResult = await
|
|
74
|
+
const parseResult = await parse.runAction({
|
|
75
|
+
file,
|
|
76
|
+
content: fileContent
|
|
77
|
+
})
|
|
63
78
|
if(parseResult.status === "error")
|
|
64
79
|
return parseResult
|
|
65
80
|
|
|
66
81
|
debug("Parsed file successfully: `%s`", 2, file.path)
|
|
67
82
|
|
|
68
83
|
// Step 3: Print file
|
|
69
|
-
const printResult = await
|
|
84
|
+
const printResult = await print.runAction({
|
|
70
85
|
file,
|
|
71
|
-
parseResult.result,
|
|
72
|
-
)
|
|
86
|
+
content: parseResult.result,
|
|
87
|
+
})
|
|
73
88
|
if(printResult.status === "error")
|
|
74
89
|
return printResult
|
|
75
90
|
|
|
76
91
|
debug("Printed file successfully: `%s`", 2, file.path)
|
|
77
92
|
|
|
78
93
|
// Step 4: Write output
|
|
79
|
-
const {destFile, content} = printResult
|
|
80
|
-
|
|
81
|
-
|
|
94
|
+
const {status: printStatus, destFile, content} = printResult
|
|
95
|
+
const isNullish = (value) => value == null // Checks null or undefined
|
|
96
|
+
|
|
97
|
+
if(printStatus !== "success" || isNullish(destFile) || isNullish(content)) {
|
|
98
|
+
return {status: "error", file, error: new Error("Invalid print result")}
|
|
99
|
+
} else if(!destFile || !content) {
|
|
100
|
+
const mess = format("No content or destination file for %s", file.path)
|
|
101
|
+
warn(mess)
|
|
102
|
+
return {status: "warning", file, warning: mess}
|
|
103
|
+
}
|
|
82
104
|
|
|
83
105
|
const writeResult = await this.#writeOutput(destFile, content)
|
|
84
106
|
|
|
@@ -87,9 +109,7 @@ export default class Conveyor {
|
|
|
87
109
|
|
|
88
110
|
return writeResult
|
|
89
111
|
} catch(error) {
|
|
90
|
-
|
|
91
|
-
this.logger.error(mess)
|
|
92
|
-
return {status: "error", error}
|
|
112
|
+
return {status: "error", file, error}
|
|
93
113
|
}
|
|
94
114
|
}
|
|
95
115
|
|