@decaf-ts/cli 0.3.8 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -3
- package/dist/cli.cjs +2 -326
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.js +2 -0
- package/dist/cli.js.map +1 -0
- package/lib/CliWrapper.cjs +107 -2
- package/lib/CliWrapper.d.ts +3 -0
- package/lib/CliWrapper.js.map +1 -0
- package/lib/bin/cli.cjs +1 -1
- package/lib/bin/cli.js.map +1 -0
- package/lib/constants.cjs +1 -1
- package/lib/constants.js.map +1 -0
- package/lib/demo/cli-module.cjs +1 -1
- package/lib/demo/cli-module.js.map +1 -0
- package/lib/esm/CliWrapper.d.ts +3 -0
- package/lib/esm/CliWrapper.js +107 -2
- package/lib/esm/CliWrapper.js.map +1 -0
- package/lib/esm/bin/cli.js +1 -1
- package/lib/esm/bin/cli.js.map +1 -0
- package/lib/esm/constants.js +1 -1
- package/lib/esm/constants.js.map +1 -0
- package/lib/esm/demo/cli-module.js +1 -1
- package/lib/esm/demo/cli-module.js.map +1 -0
- package/lib/esm/index.d.ts +0 -7
- package/lib/esm/index.js +1 -8
- package/lib/esm/index.js.map +1 -0
- package/lib/esm/types.js +1 -1
- package/lib/esm/types.js.map +1 -0
- package/lib/esm/utils.js +1 -1
- package/lib/esm/utils.js.map +1 -0
- package/lib/esm/version.d.ts +14 -0
- package/lib/esm/version.js +17 -0
- package/lib/esm/version.js.map +1 -0
- package/lib/index.cjs +1 -9
- package/lib/index.d.ts +0 -7
- package/lib/index.js.map +1 -0
- package/lib/types.cjs +1 -1
- package/lib/types.js.map +1 -0
- package/lib/utils.cjs +1 -1
- package/lib/utils.js.map +1 -0
- package/lib/version.cjs +20 -0
- package/lib/version.d.ts +14 -0
- package/lib/version.js.map +1 -0
- package/package.json +16 -47
- package/dist/cli.esm.cjs +0 -321
package/lib/index.d.ts
CHANGED
|
@@ -13,10 +13,3 @@ export * from "./CliWrapper";
|
|
|
13
13
|
*
|
|
14
14
|
* @module CLI
|
|
15
15
|
*/
|
|
16
|
-
/**
|
|
17
|
-
* @description Stores the current package version
|
|
18
|
-
* @summary A constant that holds the version string of the package, which is replaced during build
|
|
19
|
-
* @const VERSION
|
|
20
|
-
* @memberOf module:CLI
|
|
21
|
-
*/
|
|
22
|
-
export declare const VERSION = "0.3.8";
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,mDAA6B;AAE7B;;;;;;;;;;;;;GAaG"}
|
package/lib/types.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
//# sourceMappingURL=
|
|
3
|
+
//# sourceMappingURL=types.js.map
|
package/lib/types.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/lib/utils.cjs
CHANGED
|
@@ -136,4 +136,4 @@ class CLIUtils {
|
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
138
|
exports.CLIUtils = CLIUtils;
|
|
139
|
-
//# sourceMappingURL=
|
|
139
|
+
//# sourceMappingURL=utils.js.map
|
package/lib/utils.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,gDAAwB;AACxB,4CAAoB;AAIpB;;;;;;;;;;;;;GAaG;AACH,MAAa,QAAQ;IACnB;;;;;;OAMG;IACH,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,IAAY;QACpC,IAAI,CAAC;YACH,OAAO,QAAQ,CAAC,eAAe,oBAAQ,IAAI,wCAAE,CAAC;QAChD,CAAC;QAAC,OAAO,CAAU,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CACb,uBAAuB,IAAI,KAAK,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CACrE,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;;;;;;;OAQG;IACH,MAAM,CAAC,KAAK,CAAC,eAAe,CAAI,aAAyB;QACvD,mEAAmE;QACnE,OAAO,aAAa,CAAC,IAAI,CACvB,CAAC,CAAU,EAAE,EAAE,CAAC,CAAE,CAAoB,CAAC,OAAO,IAAI,CAAC,CAAM,CAC1D,CAAC;IACJ,CAAC;IAED;;;;;;;OAOG;IACH,MAAM,CAAC,UAAU,CAAC,OAAgB,EAAE,QAAgB;QAClD,MAAM,IAAI,GAAG,QAAQ,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QAC5C,OAAO;aACJ,IAAI,CAAC,IAAI,CAAC;aACV,WAAW,CAAC,QAAQ,IAAI,mBAAmB,CAAC;aAC5C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC;IAChD,CAAC;IAED;;;;;;;OAOG;IACK,MAAM,CAAC,UAAU,CAAC,QAAgB;QACxC,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CACf,YAAE,CAAC,YAAY,CAAC,cAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAC7D,CAAC;QACJ,CAAC;QAAC,OAAO,CAAU,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,+BAA+B,QAAQ,KAAK,CAAC,EAAE,CAAC,CAAC;QACnE,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,cAAc,CAAC,QAAgB;QACpC,OAAO,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAW,CAAC;IAC5D,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,WAAW,CAAC,QAAgB;QACjC,MAAM,IAAI,GAAI,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC1E,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC/B,CAAC;CACF;AA1FD,4BA0FC"}
|
package/lib/version.cjs
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PACKAGE_NAME = exports.VERSION = void 0;
|
|
4
|
+
const decoration_1 = require("@decaf-ts/decoration");
|
|
5
|
+
/**
|
|
6
|
+
* @description Stores the current package version
|
|
7
|
+
* @summary A constant that holds the version string of the package, which is replaced during build
|
|
8
|
+
* @const VERSION
|
|
9
|
+
* @memberOf module:CLI
|
|
10
|
+
*/
|
|
11
|
+
exports.VERSION = "0.3.9";
|
|
12
|
+
/**
|
|
13
|
+
* @description Stores the current package version
|
|
14
|
+
* @summary A constant that holds the version string of the package, which is replaced during build
|
|
15
|
+
* @const VERSION
|
|
16
|
+
* @memberOf module:CLI
|
|
17
|
+
*/
|
|
18
|
+
exports.PACKAGE_NAME = "@decaf-ts/cli";
|
|
19
|
+
decoration_1.Metadata.registerLibrary(exports.PACKAGE_NAME, exports.VERSION);
|
|
20
|
+
//# sourceMappingURL=version.js.map
|
package/lib/version.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description Stores the current package version
|
|
3
|
+
* @summary A constant that holds the version string of the package, which is replaced during build
|
|
4
|
+
* @const VERSION
|
|
5
|
+
* @memberOf module:CLI
|
|
6
|
+
*/
|
|
7
|
+
export declare const VERSION = "0.3.9";
|
|
8
|
+
/**
|
|
9
|
+
* @description Stores the current package version
|
|
10
|
+
* @summary A constant that holds the version string of the package, which is replaced during build
|
|
11
|
+
* @const VERSION
|
|
12
|
+
* @memberOf module:CLI
|
|
13
|
+
*/
|
|
14
|
+
export declare const PACKAGE_NAME = "@decaf-ts/cli";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":";;;AAAA,qDAAgD;AAEhD;;;;;GAKG;AACU,QAAA,OAAO,GAAG,aAAa,CAAC;AAErC;;;;;GAKG;AACU,QAAA,YAAY,GAAG,aAAa,CAAC;AAE1C,qBAAQ,CAAC,eAAe,CAAC,oBAAY,EAAE,eAAO,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decaf-ts/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "cli for decaf-ts projects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -58,22 +58,18 @@
|
|
|
58
58
|
"dist"
|
|
59
59
|
],
|
|
60
60
|
"keywords": [
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"mddocs",
|
|
66
|
-
"md",
|
|
67
|
-
"jsdoc",
|
|
68
|
-
"doc",
|
|
69
|
-
"docs",
|
|
70
|
-
"documentation",
|
|
71
|
-
"ci/cd",
|
|
72
|
-
"ci",
|
|
73
|
-
"cd",
|
|
74
|
-
"template",
|
|
61
|
+
"cli",
|
|
62
|
+
"command-line",
|
|
63
|
+
"decaf",
|
|
64
|
+
"tooling",
|
|
75
65
|
"typescript",
|
|
76
|
-
"
|
|
66
|
+
"devops",
|
|
67
|
+
"scaffolding",
|
|
68
|
+
"publish",
|
|
69
|
+
"automation",
|
|
70
|
+
"scripts",
|
|
71
|
+
"documentation",
|
|
72
|
+
"npm"
|
|
77
73
|
],
|
|
78
74
|
"author": "Tiago Venceslau and Contributors",
|
|
79
75
|
"license": "MIT",
|
|
@@ -82,39 +78,12 @@
|
|
|
82
78
|
},
|
|
83
79
|
"homepage": "https://github.com/decaf-ts/cli#readme",
|
|
84
80
|
"devDependencies": {
|
|
85
|
-
"@decaf-ts/utils": "latest"
|
|
86
|
-
"@eslint/js": "^9.25.1",
|
|
87
|
-
"@rollup/plugin-commonjs": "^28.0.3",
|
|
88
|
-
"@rollup/plugin-json": "^6.1.0",
|
|
89
|
-
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
90
|
-
"@rollup/plugin-typescript": "^12.1.2",
|
|
91
|
-
"@stylistic/eslint-plugin": "^4.2.0",
|
|
92
|
-
"@types/jest": "^29.5.14",
|
|
93
|
-
"clean-publish": "^5.1.0",
|
|
94
|
-
"dpdm": "^3.14.0",
|
|
95
|
-
"eslint": "^9.25.1",
|
|
96
|
-
"eslint-config-prettier": "^10.1.2",
|
|
97
|
-
"eslint-plugin-prettier": "^5.2.6",
|
|
98
|
-
"globals": "^16.0.0",
|
|
99
|
-
"jest": "^29.7.0",
|
|
100
|
-
"jest-html-reporters": "^3.1.7",
|
|
101
|
-
"jest-junit": "^16.0.0",
|
|
102
|
-
"jsdoc": "^4.0.4",
|
|
103
|
-
"jsdoc-mermaid": "^1.0.0",
|
|
104
|
-
"markdown-include": "^0.4.3",
|
|
105
|
-
"minimist": "^1.2.8",
|
|
106
|
-
"nodemon": "^3.1.9",
|
|
107
|
-
"npm-check-updates": "^18.0.0",
|
|
108
|
-
"prettier": "3.5.3",
|
|
109
|
-
"rimraf": "^6.0.1",
|
|
110
|
-
"rollup": "^4.40.0",
|
|
111
|
-
"ts-jest": "^29.3.2",
|
|
112
|
-
"ts-loader": "^9.5.2",
|
|
113
|
-
"ts-node": "^10.9.2",
|
|
114
|
-
"typescript": "^5.8.3",
|
|
115
|
-
"typescript-eslint": "^8.31.0"
|
|
81
|
+
"@decaf-ts/utils": "latest"
|
|
116
82
|
},
|
|
117
83
|
"dependencies": {
|
|
118
84
|
"commander": "^13.1.0"
|
|
85
|
+
},
|
|
86
|
+
"peerDependencies": {
|
|
87
|
+
"@decaf-ts/decoration": "^0.0.22"
|
|
119
88
|
}
|
|
120
89
|
}
|
package/dist/cli.esm.cjs
DELETED
|
@@ -1,321 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @description The filename that identifies Decaf CLI modules
|
|
7
|
-
* @summary The standard filename for CLI module files where each library must export a single CliModule function
|
|
8
|
-
*
|
|
9
|
-
* @const CLI_FILE_NAME
|
|
10
|
-
* @memberOf module:CLI
|
|
11
|
-
*/
|
|
12
|
-
const CLI_FILE_NAME = "cli-module";
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* @description Utility class for CLI operations
|
|
16
|
-
* @summary A static utility class that provides methods for loading modules, retrieving package information, and initializing CLI commands
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* // Initialize a Command object with package information
|
|
20
|
-
* const command = new Command();
|
|
21
|
-
* CLIUtils.initialize(command, './path/to/package');
|
|
22
|
-
*
|
|
23
|
-
* // Load a CLI module from a file
|
|
24
|
-
* const module = await CLIUtils.loadFromFile('./path/to/cli-module.js');
|
|
25
|
-
*
|
|
26
|
-
* @class CLIUtils
|
|
27
|
-
*/
|
|
28
|
-
class CLIUtils {
|
|
29
|
-
/**
|
|
30
|
-
* @description Dynamically imports a module file
|
|
31
|
-
* @summary Loads a JavaScript file and returns it as a CliModule, handling both ESM and CommonJS formats
|
|
32
|
-
*
|
|
33
|
-
* @param {string} path The file path to the module to load
|
|
34
|
-
* @return {Promise<CliModule>} A promise that resolves to the loaded CliModule
|
|
35
|
-
*/
|
|
36
|
-
static async loadFromFile(path) {
|
|
37
|
-
try {
|
|
38
|
-
return CLIUtils.normalizeImport(import(path));
|
|
39
|
-
}
|
|
40
|
-
catch (e) {
|
|
41
|
-
throw new Error(`Failed to load from ${path}: ${e instanceof Error ? e.message : e}`);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* @description Normalizes module imports to handle both ESM and CommonJS formats
|
|
46
|
-
* @summary Properly imports JavaScript files regardless of their module format by handling the ESM wrapper for CommonJS modules
|
|
47
|
-
*
|
|
48
|
-
* @template T The type of the imported module
|
|
49
|
-
* @param {Promise<T>} importPromise The promise returned by the dynamic import
|
|
50
|
-
* @return {Promise<T>} A promise that resolves to the normalized module
|
|
51
|
-
* @private
|
|
52
|
-
*/
|
|
53
|
-
static async normalizeImport(importPromise) {
|
|
54
|
-
// CommonJS's `module.exports` is wrapped as `default` in ESModule.
|
|
55
|
-
return importPromise.then((m) => (m.default || m));
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* @description Initializes a Command object with package information
|
|
59
|
-
* @summary Sets up a Commander Command object with the package name, description, and version from the package.json file
|
|
60
|
-
*
|
|
61
|
-
* @param {Command} command The Command object to initialize
|
|
62
|
-
* @param {string} [basePath] The base path where the package.json file is located, defaults to the current working directory
|
|
63
|
-
* @return {void}
|
|
64
|
-
*/
|
|
65
|
-
static initialize(command, basePath) {
|
|
66
|
-
const name = CLIUtils.packageName(basePath);
|
|
67
|
-
command
|
|
68
|
-
.name(name)
|
|
69
|
-
.description(`Runs ${name} related commands`)
|
|
70
|
-
.version(CLIUtils.packageVersion(basePath));
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* @description Retrieves and parses the package.json file
|
|
74
|
-
* @summary Reads the package.json file from the specified path and parses it into a JavaScript object
|
|
75
|
-
*
|
|
76
|
-
* @param {string} basePath The base path where the package.json file is located
|
|
77
|
-
* @return {Record<string, unknown>} The parsed package.json content as an object
|
|
78
|
-
* @private
|
|
79
|
-
*/
|
|
80
|
-
static getPackage(basePath) {
|
|
81
|
-
try {
|
|
82
|
-
return JSON.parse(fs.readFileSync(path.join(basePath, "package.json"), "utf8"));
|
|
83
|
-
}
|
|
84
|
-
catch (e) {
|
|
85
|
-
throw new Error(`Unable to read version from ${basePath}: ${e}`);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* @description Returns the version from package.json
|
|
90
|
-
* @summary Retrieves the version field from the package.json file at the specified path
|
|
91
|
-
*
|
|
92
|
-
* @param {string} basePath The base path where the package.json file is located
|
|
93
|
-
* @return {string} The package version string
|
|
94
|
-
*/
|
|
95
|
-
static packageVersion(basePath) {
|
|
96
|
-
return CLIUtils.getPackage(basePath)["version"];
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* @description Returns the name from package.json
|
|
100
|
-
* @summary Retrieves the name field from the package.json file at the specified path and extracts the package name without the scope
|
|
101
|
-
*
|
|
102
|
-
* @param {string} basePath The base path where the package.json file is located
|
|
103
|
-
* @return {string} The package name without the scope (e.g., "cli" from "@decaf-ts/cli")
|
|
104
|
-
*/
|
|
105
|
-
static packageName(basePath) {
|
|
106
|
-
const name = CLIUtils.getPackage(basePath)["name"].split("/");
|
|
107
|
-
return name[name.length - 1];
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* @description Utility class to handle CLI functionality from all Decaf modules
|
|
113
|
-
* @summary This class provides a wrapper around Commander.js to handle CLI commands from different Decaf modules.
|
|
114
|
-
* It crawls the filesystem to find CLI modules, loads them, and registers their commands.
|
|
115
|
-
*
|
|
116
|
-
* @param {string} [basePath] The base path to look for modules in. Defaults to `./`
|
|
117
|
-
* @param {number} [crawlLevels] Number of folder levels to crawl to find modules from the basePath. Defaults to 4
|
|
118
|
-
*
|
|
119
|
-
* @example
|
|
120
|
-
* // Create a new CLI wrapper and run it with custom options
|
|
121
|
-
* const cli = new CliWrapper('./src', 2);
|
|
122
|
-
* cli.run(process.argv).then(() => {
|
|
123
|
-
* console.log('CLI commands executed successfully');
|
|
124
|
-
* });
|
|
125
|
-
*
|
|
126
|
-
* @class CliWrapper
|
|
127
|
-
*/
|
|
128
|
-
class CliWrapper {
|
|
129
|
-
constructor(basePath = "./", crawlLevels = 4) {
|
|
130
|
-
this.basePath = basePath;
|
|
131
|
-
this.crawlLevels = crawlLevels;
|
|
132
|
-
this.modules = {};
|
|
133
|
-
this.rootPath = path.resolve(__dirname, "..");
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* @description Retrieves and initializes the Commander Command object
|
|
137
|
-
* @summary Lazy-loads the Command object, initializing it with the package name, description, and version
|
|
138
|
-
* @return {Command} The initialized Command object
|
|
139
|
-
* @private
|
|
140
|
-
*/
|
|
141
|
-
get command() {
|
|
142
|
-
if (!this._command) {
|
|
143
|
-
this._command = new Command();
|
|
144
|
-
CLIUtils.initialize(this._command, this.rootPath);
|
|
145
|
-
}
|
|
146
|
-
return this._command;
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* @description Loads and registers a module from a file
|
|
150
|
-
* @summary Dynamically imports a CLI module from the specified file path, initializes it, and registers it in the modules collection
|
|
151
|
-
*
|
|
152
|
-
* @param {string} filePath Path to the module file to load
|
|
153
|
-
* @param {string} rootPath Repository root path to find the package.json
|
|
154
|
-
* @return {Promise<string>} A promise that resolves to the module name
|
|
155
|
-
*
|
|
156
|
-
* @private
|
|
157
|
-
* @mermaid
|
|
158
|
-
* sequenceDiagram
|
|
159
|
-
* participant CliWrapper
|
|
160
|
-
* participant CLIUtils
|
|
161
|
-
* participant Module
|
|
162
|
-
*
|
|
163
|
-
* CliWrapper->>CLIUtils: loadFromFile(filePath)
|
|
164
|
-
* CLIUtils-->>CliWrapper: module
|
|
165
|
-
* CliWrapper->>CliWrapper: Get module name
|
|
166
|
-
* CliWrapper->>Command: new Command()
|
|
167
|
-
* Command-->>CliWrapper: cmd
|
|
168
|
-
* CliWrapper->>CLIUtils: initialize(cmd, path.dirname(rootPath))
|
|
169
|
-
* CliWrapper->>Module: module()
|
|
170
|
-
* Note over CliWrapper,Module: Handle Promise if needed
|
|
171
|
-
* Module-->>CliWrapper: Command instance
|
|
172
|
-
* CliWrapper->>CliWrapper: Store in modules[name]
|
|
173
|
-
* CliWrapper-->>CliWrapper: Return name
|
|
174
|
-
*/
|
|
175
|
-
async load(filePath, rootPath) {
|
|
176
|
-
let name;
|
|
177
|
-
try {
|
|
178
|
-
const module = await CLIUtils.loadFromFile(filePath);
|
|
179
|
-
name = module.name;
|
|
180
|
-
const cmd = new Command();
|
|
181
|
-
CLIUtils.initialize(cmd, rootPath);
|
|
182
|
-
let m = module();
|
|
183
|
-
if (m instanceof Promise)
|
|
184
|
-
m = await m;
|
|
185
|
-
this.modules[name] = m;
|
|
186
|
-
}
|
|
187
|
-
catch (e) {
|
|
188
|
-
throw new Error(`failed to load module ${name || "unnamed"} under ${filePath}: ${e instanceof Error ? e.message : e}`);
|
|
189
|
-
}
|
|
190
|
-
return name;
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* @description Finds and loads all CLI modules in the basePath
|
|
194
|
-
* @summary Uses the crawl method to find all CLI modules in the specified base path,
|
|
195
|
-
* then loads and registers each module as a subcommand
|
|
196
|
-
*
|
|
197
|
-
* @return {Promise<void>} A promise that resolves when all modules are loaded
|
|
198
|
-
*
|
|
199
|
-
* @private
|
|
200
|
-
* @mermaid
|
|
201
|
-
* sequenceDiagram
|
|
202
|
-
* participant CliWrapper
|
|
203
|
-
* participant Filesystem
|
|
204
|
-
* participant Module
|
|
205
|
-
*
|
|
206
|
-
* CliWrapper->>Filesystem: Join basePath with cwd
|
|
207
|
-
* CliWrapper->>CliWrapper: crawl(basePath, crawlLevels)
|
|
208
|
-
* CliWrapper-->>CliWrapper: modules[]
|
|
209
|
-
* loop For each module
|
|
210
|
-
* alt Not @decaf-ts/cli
|
|
211
|
-
* CliWrapper->>CliWrapper: load(module, cwd)
|
|
212
|
-
* CliWrapper-->>CliWrapper: name
|
|
213
|
-
* CliWrapper->>CliWrapper: Check if command exists
|
|
214
|
-
* alt Command doesn't exist
|
|
215
|
-
* CliWrapper->>Command: command(name).addCommand(modules[name])
|
|
216
|
-
* end
|
|
217
|
-
* end
|
|
218
|
-
* end
|
|
219
|
-
* CliWrapper->>Console: Log loaded modules
|
|
220
|
-
*/
|
|
221
|
-
async boot() {
|
|
222
|
-
const basePath = path.resolve(this.rootPath, this.basePath);
|
|
223
|
-
const modules = this.crawl(basePath, this.crawlLevels);
|
|
224
|
-
for (const module of modules) {
|
|
225
|
-
if (module.includes("@decaf-ts/cli")) {
|
|
226
|
-
continue;
|
|
227
|
-
}
|
|
228
|
-
let name;
|
|
229
|
-
try {
|
|
230
|
-
name = await this.load(module, this.rootPath);
|
|
231
|
-
}
|
|
232
|
-
catch (e) {
|
|
233
|
-
console.error(e);
|
|
234
|
-
continue;
|
|
235
|
-
}
|
|
236
|
-
if (!this.command.commands.find((c) => c["_name"] === name))
|
|
237
|
-
try {
|
|
238
|
-
this.command.command(name).addCommand(this.modules[name]);
|
|
239
|
-
}
|
|
240
|
-
catch (e) {
|
|
241
|
-
console.error(e);
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
console.log(`loaded modules:\n${Object.keys(this.modules)
|
|
245
|
-
.map((k) => `- ${k}`)
|
|
246
|
-
.join("\n")}`);
|
|
247
|
-
}
|
|
248
|
-
/**
|
|
249
|
-
* @description Recursively searches for CLI module files in the directory structure
|
|
250
|
-
* @summary Crawls the basePath up to the specified number of folder levels to find files named according to CLI_FILE_NAME
|
|
251
|
-
*
|
|
252
|
-
* @param {string} basePath The absolute base path to start searching in
|
|
253
|
-
* @param {number} [levels=2] The maximum number of directory levels to crawl
|
|
254
|
-
* @return {string[]} An array of file paths to CLI modules
|
|
255
|
-
*
|
|
256
|
-
* @private
|
|
257
|
-
*/
|
|
258
|
-
crawl(basePath, levels = 2) {
|
|
259
|
-
if (levels <= 0)
|
|
260
|
-
return [];
|
|
261
|
-
return fs.readdirSync(basePath).reduce((accum, file) => {
|
|
262
|
-
file = path.join(basePath, file);
|
|
263
|
-
if (fs.statSync(file).isDirectory()) {
|
|
264
|
-
accum.push(...this.crawl(file, levels - 1));
|
|
265
|
-
}
|
|
266
|
-
else if (file.match(new RegExp(`${CLI_FILE_NAME}.[cm]?js$`, "gm"))) {
|
|
267
|
-
accum.push(file);
|
|
268
|
-
}
|
|
269
|
-
return accum;
|
|
270
|
-
}, []);
|
|
271
|
-
}
|
|
272
|
-
/**
|
|
273
|
-
* @description Executes the CLI with the provided arguments
|
|
274
|
-
* @summary Boots the CLI by loading all modules, then parses and executes the command specified in the arguments
|
|
275
|
-
*
|
|
276
|
-
* @param {string[]} [args=process.argv] Command line arguments to parse and execute
|
|
277
|
-
* @return {Promise<void>} A promise that resolves when the command execution is complete
|
|
278
|
-
*
|
|
279
|
-
* @mermaid
|
|
280
|
-
* sequenceDiagram
|
|
281
|
-
* participant Client
|
|
282
|
-
* participant CliWrapper
|
|
283
|
-
* participant Command
|
|
284
|
-
*
|
|
285
|
-
* Client->>CliWrapper: run(args)
|
|
286
|
-
* CliWrapper->>CliWrapper: boot()
|
|
287
|
-
* Note over CliWrapper: Loads all modules
|
|
288
|
-
* CliWrapper->>Command: parseAsync(args)
|
|
289
|
-
* Command-->>CliWrapper: result
|
|
290
|
-
* CliWrapper-->>Client: result
|
|
291
|
-
*/
|
|
292
|
-
async run(args = process.argv) {
|
|
293
|
-
await this.boot();
|
|
294
|
-
return this.command.parseAsync(args);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
/**
|
|
299
|
-
* @description Decaf-ts' CLI module
|
|
300
|
-
* @summary This file will crawl the current working directory for files called {@link CLI_FILE_NAME}
|
|
301
|
-
* within the @decaf-ts namespace and load them as subcommands. It serves as the main entry point
|
|
302
|
-
* for the CLI functionality, exporting the CliWrapper class and VERSION constant.
|
|
303
|
-
*
|
|
304
|
-
* @example
|
|
305
|
-
* run module command - $ npx decaf <module name> <module command> ...<module command options>
|
|
306
|
-
* get module help - $ npx decaf help <module name>;
|
|
307
|
-
* list imported modules - $ npx decaf list;
|
|
308
|
-
* get cli help - $ npx decaf help;
|
|
309
|
-
*
|
|
310
|
-
* @module CLI
|
|
311
|
-
*/
|
|
312
|
-
/**
|
|
313
|
-
* @description Stores the current package version
|
|
314
|
-
* @summary A constant that holds the version string of the package, which is replaced during build
|
|
315
|
-
* @const VERSION
|
|
316
|
-
* @memberOf module:CLI
|
|
317
|
-
*/
|
|
318
|
-
const VERSION = "0.3.8";
|
|
319
|
-
|
|
320
|
-
export { CliWrapper, VERSION };
|
|
321
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLmVzbS5janMiLCJzb3VyY2VzIjpbIi4uL3NyYy9jb25zdGFudHMudHMiLCIuLi9zcmMvdXRpbHMudHMiLCIuLi9zcmMvQ2xpV3JhcHBlci50cyIsIi4uL3NyYy9pbmRleC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG5pbXBvcnQgeyBDbGlNb2R1bGUgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBUaGUgZmlsZW5hbWUgdGhhdCBpZGVudGlmaWVzIERlY2FmIENMSSBtb2R1bGVzXG4gKiBAc3VtbWFyeSBUaGUgc3RhbmRhcmQgZmlsZW5hbWUgZm9yIENMSSBtb2R1bGUgZmlsZXMgd2hlcmUgZWFjaCBsaWJyYXJ5IG11c3QgZXhwb3J0IGEgc2luZ2xlIENsaU1vZHVsZSBmdW5jdGlvblxuICpcbiAqIEBjb25zdCBDTElfRklMRV9OQU1FXG4gKiBAbWVtYmVyT2YgbW9kdWxlOkNMSVxuICovXG5leHBvcnQgY29uc3QgQ0xJX0ZJTEVfTkFNRSA9IFwiY2xpLW1vZHVsZVwiO1xuIiwiaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCBmcyBmcm9tIFwiZnNcIjtcbmltcG9ydCB7IENvbW1hbmQgfSBmcm9tIFwiY29tbWFuZGVyXCI7XG5pbXBvcnQgeyBDbGlNb2R1bGUgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBVdGlsaXR5IGNsYXNzIGZvciBDTEkgb3BlcmF0aW9uc1xuICogQHN1bW1hcnkgQSBzdGF0aWMgdXRpbGl0eSBjbGFzcyB0aGF0IHByb3ZpZGVzIG1ldGhvZHMgZm9yIGxvYWRpbmcgbW9kdWxlcywgcmV0cmlldmluZyBwYWNrYWdlIGluZm9ybWF0aW9uLCBhbmQgaW5pdGlhbGl6aW5nIENMSSBjb21tYW5kc1xuICogXG4gKiBAZXhhbXBsZVxuICogLy8gSW5pdGlhbGl6ZSBhIENvbW1hbmQgb2JqZWN0IHdpdGggcGFja2FnZSBpbmZvcm1hdGlvblxuICogY29uc3QgY29tbWFuZCA9IG5ldyBDb21tYW5kKCk7XG4gKiBDTElVdGlscy5pbml0aWFsaXplKGNvbW1hbmQsICcuL3BhdGgvdG8vcGFja2FnZScpO1xuICogXG4gKiAvLyBMb2FkIGEgQ0xJIG1vZHVsZSBmcm9tIGEgZmlsZVxuICogY29uc3QgbW9kdWxlID0gYXdhaXQgQ0xJVXRpbHMubG9hZEZyb21GaWxlKCcuL3BhdGgvdG8vY2xpLW1vZHVsZS5qcycpO1xuICogXG4gKiBAY2xhc3MgQ0xJVXRpbHNcbiAqL1xuZXhwb3J0IGNsYXNzIENMSVV0aWxzIHtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBEeW5hbWljYWxseSBpbXBvcnRzIGEgbW9kdWxlIGZpbGVcbiAgICogQHN1bW1hcnkgTG9hZHMgYSBKYXZhU2NyaXB0IGZpbGUgYW5kIHJldHVybnMgaXQgYXMgYSBDbGlNb2R1bGUsIGhhbmRsaW5nIGJvdGggRVNNIGFuZCBDb21tb25KUyBmb3JtYXRzXG4gICAqIFxuICAgKiBAcGFyYW0ge3N0cmluZ30gcGF0aCBUaGUgZmlsZSBwYXRoIHRvIHRoZSBtb2R1bGUgdG8gbG9hZFxuICAgKiBAcmV0dXJuIHtQcm9taXNlPENsaU1vZHVsZT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBsb2FkZWQgQ2xpTW9kdWxlXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgbG9hZEZyb21GaWxlKHBhdGg6IHN0cmluZyk6IFByb21pc2U8Q2xpTW9kdWxlPiB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBDTElVdGlscy5ub3JtYWxpemVJbXBvcnQoaW1wb3J0KHBhdGgpKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBGYWlsZWQgdG8gbG9hZCBmcm9tICR7cGF0aH06ICR7ZSBpbnN0YW5jZW9mIEVycm9yID8gZS5tZXNzYWdlIDogZX1gXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTm9ybWFsaXplcyBtb2R1bGUgaW1wb3J0cyB0byBoYW5kbGUgYm90aCBFU00gYW5kIENvbW1vbkpTIGZvcm1hdHNcbiAgICogQHN1bW1hcnkgUHJvcGVybHkgaW1wb3J0cyBKYXZhU2NyaXB0IGZpbGVzIHJlZ2FyZGxlc3Mgb2YgdGhlaXIgbW9kdWxlIGZvcm1hdCBieSBoYW5kbGluZyB0aGUgRVNNIHdyYXBwZXIgZm9yIENvbW1vbkpTIG1vZHVsZXNcbiAgICpcbiAgICogQHRlbXBsYXRlIFQgVGhlIHR5cGUgb2YgdGhlIGltcG9ydGVkIG1vZHVsZVxuICAgKiBAcGFyYW0ge1Byb21pc2U8VD59IGltcG9ydFByb21pc2UgVGhlIHByb21pc2UgcmV0dXJuZWQgYnkgdGhlIGR5bmFtaWMgaW1wb3J0XG4gICAqIEByZXR1cm4ge1Byb21pc2U8VD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBub3JtYWxpemVkIG1vZHVsZVxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgc3RhdGljIGFzeW5jIG5vcm1hbGl6ZUltcG9ydDxUPihpbXBvcnRQcm9taXNlOiBQcm9taXNlPFQ+KTogUHJvbWlzZTxUPiB7XG4gICAgLy8gQ29tbW9uSlMncyBgbW9kdWxlLmV4cG9ydHNgIGlzIHdyYXBwZWQgYXMgYGRlZmF1bHRgIGluIEVTTW9kdWxlLlxuICAgIHJldHVybiBpbXBvcnRQcm9taXNlLnRoZW4oXG4gICAgICAobTogdW5rbm93bikgPT4gKChtIGFzIHsgZGVmYXVsdDogVCB9KS5kZWZhdWx0IHx8IG0pIGFzIFRcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBJbml0aWFsaXplcyBhIENvbW1hbmQgb2JqZWN0IHdpdGggcGFja2FnZSBpbmZvcm1hdGlvblxuICAgKiBAc3VtbWFyeSBTZXRzIHVwIGEgQ29tbWFuZGVyIENvbW1hbmQgb2JqZWN0IHdpdGggdGhlIHBhY2thZ2UgbmFtZSwgZGVzY3JpcHRpb24sIGFuZCB2ZXJzaW9uIGZyb20gdGhlIHBhY2thZ2UuanNvbiBmaWxlXG4gICAqXG4gICAqIEBwYXJhbSB7Q29tbWFuZH0gY29tbWFuZCBUaGUgQ29tbWFuZCBvYmplY3QgdG8gaW5pdGlhbGl6ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2Jhc2VQYXRoXSBUaGUgYmFzZSBwYXRoIHdoZXJlIHRoZSBwYWNrYWdlLmpzb24gZmlsZSBpcyBsb2NhdGVkLCBkZWZhdWx0cyB0byB0aGUgY3VycmVudCB3b3JraW5nIGRpcmVjdG9yeVxuICAgKiBAcmV0dXJuIHt2b2lkfVxuICAgKi9cbiAgc3RhdGljIGluaXRpYWxpemUoY29tbWFuZDogQ29tbWFuZCwgYmFzZVBhdGg6IHN0cmluZykge1xuICAgIGNvbnN0IG5hbWUgPSBDTElVdGlscy5wYWNrYWdlTmFtZShiYXNlUGF0aCk7XG4gICAgY29tbWFuZFxuICAgICAgLm5hbWUobmFtZSlcbiAgICAgIC5kZXNjcmlwdGlvbihgUnVucyAke25hbWV9IHJlbGF0ZWQgY29tbWFuZHNgKVxuICAgICAgLnZlcnNpb24oQ0xJVXRpbHMucGFja2FnZVZlcnNpb24oYmFzZVBhdGgpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIGFuZCBwYXJzZXMgdGhlIHBhY2thZ2UuanNvbiBmaWxlXG4gICAqIEBzdW1tYXJ5IFJlYWRzIHRoZSBwYWNrYWdlLmpzb24gZmlsZSBmcm9tIHRoZSBzcGVjaWZpZWQgcGF0aCBhbmQgcGFyc2VzIGl0IGludG8gYSBKYXZhU2NyaXB0IG9iamVjdFxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYmFzZVBhdGggVGhlIGJhc2UgcGF0aCB3aGVyZSB0aGUgcGFja2FnZS5qc29uIGZpbGUgaXMgbG9jYXRlZFxuICAgKiBAcmV0dXJuIHtSZWNvcmQ8c3RyaW5nLCB1bmtub3duPn0gVGhlIHBhcnNlZCBwYWNrYWdlLmpzb24gY29udGVudCBhcyBhbiBvYmplY3RcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIGdldFBhY2thZ2UoYmFzZVBhdGg6IHN0cmluZyk6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIEpTT04ucGFyc2UoXG4gICAgICAgIGZzLnJlYWRGaWxlU3luYyhwYXRoLmpvaW4oYmFzZVBhdGgsIFwicGFja2FnZS5qc29uXCIpLCBcInV0ZjhcIilcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmFibGUgdG8gcmVhZCB2ZXJzaW9uIGZyb20gJHtiYXNlUGF0aH06ICR7ZX1gKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHVybnMgdGhlIHZlcnNpb24gZnJvbSBwYWNrYWdlLmpzb25cbiAgICogQHN1bW1hcnkgUmV0cmlldmVzIHRoZSB2ZXJzaW9uIGZpZWxkIGZyb20gdGhlIHBhY2thZ2UuanNvbiBmaWxlIGF0IHRoZSBzcGVjaWZpZWQgcGF0aFxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYmFzZVBhdGggVGhlIGJhc2UgcGF0aCB3aGVyZSB0aGUgcGFja2FnZS5qc29uIGZpbGUgaXMgbG9jYXRlZFxuICAgKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBwYWNrYWdlIHZlcnNpb24gc3RyaW5nXG4gICAqL1xuICBzdGF0aWMgcGFja2FnZVZlcnNpb24oYmFzZVBhdGg6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIENMSVV0aWxzLmdldFBhY2thZ2UoYmFzZVBhdGgpW1widmVyc2lvblwiXSBhcyBzdHJpbmc7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHVybnMgdGhlIG5hbWUgZnJvbSBwYWNrYWdlLmpzb25cbiAgICogQHN1bW1hcnkgUmV0cmlldmVzIHRoZSBuYW1lIGZpZWxkIGZyb20gdGhlIHBhY2thZ2UuanNvbiBmaWxlIGF0IHRoZSBzcGVjaWZpZWQgcGF0aCBhbmQgZXh0cmFjdHMgdGhlIHBhY2thZ2UgbmFtZSB3aXRob3V0IHRoZSBzY29wZVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYmFzZVBhdGggVGhlIGJhc2UgcGF0aCB3aGVyZSB0aGUgcGFja2FnZS5qc29uIGZpbGUgaXMgbG9jYXRlZFxuICAgKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBwYWNrYWdlIG5hbWUgd2l0aG91dCB0aGUgc2NvcGUgKGUuZy4sIFwiY2xpXCIgZnJvbSBcIkBkZWNhZi10cy9jbGlcIilcbiAgICovXG4gIHN0YXRpYyBwYWNrYWdlTmFtZShiYXNlUGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCBuYW1lID0gKENMSVV0aWxzLmdldFBhY2thZ2UoYmFzZVBhdGgpW1wibmFtZVwiXSBhcyBzdHJpbmcpLnNwbGl0KFwiL1wiKTtcbiAgICByZXR1cm4gbmFtZVtuYW1lLmxlbmd0aCAtIDFdO1xuICB9XG59XG4iLCJpbXBvcnQgeyBDb21tYW5kIH0gZnJvbSBcImNvbW1hbmRlclwiO1xuaW1wb3J0IGZzIGZyb20gXCJmc1wiO1xuaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IENMSV9GSUxFX05BTUUgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IENMSVV0aWxzIH0gZnJvbSBcIi4vdXRpbHNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gVXRpbGl0eSBjbGFzcyB0byBoYW5kbGUgQ0xJIGZ1bmN0aW9uYWxpdHkgZnJvbSBhbGwgRGVjYWYgbW9kdWxlc1xuICogQHN1bW1hcnkgVGhpcyBjbGFzcyBwcm92aWRlcyBhIHdyYXBwZXIgYXJvdW5kIENvbW1hbmRlci5qcyB0byBoYW5kbGUgQ0xJIGNvbW1hbmRzIGZyb20gZGlmZmVyZW50IERlY2FmIG1vZHVsZXMuXG4gKiBJdCBjcmF3bHMgdGhlIGZpbGVzeXN0ZW0gdG8gZmluZCBDTEkgbW9kdWxlcywgbG9hZHMgdGhlbSwgYW5kIHJlZ2lzdGVycyB0aGVpciBjb21tYW5kcy5cbiAqIFxuICogQHBhcmFtIHtzdHJpbmd9IFtiYXNlUGF0aF0gVGhlIGJhc2UgcGF0aCB0byBsb29rIGZvciBtb2R1bGVzIGluLiBEZWZhdWx0cyB0byBgLi9gXG4gKiBAcGFyYW0ge251bWJlcn0gW2NyYXdsTGV2ZWxzXSBOdW1iZXIgb2YgZm9sZGVyIGxldmVscyB0byBjcmF3bCB0byBmaW5kIG1vZHVsZXMgZnJvbSB0aGUgYmFzZVBhdGguIERlZmF1bHRzIHRvIDRcbiAqIFxuICogQGV4YW1wbGVcbiAqIC8vIENyZWF0ZSBhIG5ldyBDTEkgd3JhcHBlciBhbmQgcnVuIGl0IHdpdGggY3VzdG9tIG9wdGlvbnNcbiAqIGNvbnN0IGNsaSA9IG5ldyBDbGlXcmFwcGVyKCcuL3NyYycsIDIpO1xuICogY2xpLnJ1bihwcm9jZXNzLmFyZ3YpLnRoZW4oKCkgPT4ge1xuICogICBjb25zb2xlLmxvZygnQ0xJIGNvbW1hbmRzIGV4ZWN1dGVkIHN1Y2Nlc3NmdWxseScpO1xuICogfSk7XG4gKiBcbiAqIEBjbGFzcyBDbGlXcmFwcGVyXG4gKi9cbmV4cG9ydCBjbGFzcyBDbGlXcmFwcGVyIHtcbiAgcHJpdmF0ZSBfY29tbWFuZD86IENvbW1hbmQ7XG4gIHByaXZhdGUgbW9kdWxlczogUmVjb3JkPHN0cmluZywgQ29tbWFuZD4gPSB7fTtcbiAgcHJpdmF0ZSByZWFkb25seSByb290UGF0aDogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgYmFzZVBhdGg6IHN0cmluZyA9IFwiLi9cIixcbiAgICBwcml2YXRlIGNyYXdsTGV2ZWxzID0gNFxuICApIHtcbiAgICB0aGlzLnJvb3RQYXRoID0gcGF0aC5yZXNvbHZlKF9fZGlybmFtZSwgXCIuLlwiKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIGFuZCBpbml0aWFsaXplcyB0aGUgQ29tbWFuZGVyIENvbW1hbmQgb2JqZWN0XG4gICAqIEBzdW1tYXJ5IExhenktbG9hZHMgdGhlIENvbW1hbmQgb2JqZWN0LCBpbml0aWFsaXppbmcgaXQgd2l0aCB0aGUgcGFja2FnZSBuYW1lLCBkZXNjcmlwdGlvbiwgYW5kIHZlcnNpb25cbiAgICogQHJldHVybiB7Q29tbWFuZH0gVGhlIGluaXRpYWxpemVkIENvbW1hbmQgb2JqZWN0XG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwcml2YXRlIGdldCBjb21tYW5kKCkge1xuICAgIGlmICghdGhpcy5fY29tbWFuZCkge1xuICAgICAgdGhpcy5fY29tbWFuZCA9IG5ldyBDb21tYW5kKCk7XG4gICAgICBDTElVdGlscy5pbml0aWFsaXplKHRoaXMuX2NvbW1hbmQsIHRoaXMucm9vdFBhdGgpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fY29tbWFuZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gTG9hZHMgYW5kIHJlZ2lzdGVycyBhIG1vZHVsZSBmcm9tIGEgZmlsZVxuICAgKiBAc3VtbWFyeSBEeW5hbWljYWxseSBpbXBvcnRzIGEgQ0xJIG1vZHVsZSBmcm9tIHRoZSBzcGVjaWZpZWQgZmlsZSBwYXRoLCBpbml0aWFsaXplcyBpdCwgYW5kIHJlZ2lzdGVycyBpdCBpbiB0aGUgbW9kdWxlcyBjb2xsZWN0aW9uXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlUGF0aCBQYXRoIHRvIHRoZSBtb2R1bGUgZmlsZSB0byBsb2FkXG4gICAqIEBwYXJhbSB7c3RyaW5nfSByb290UGF0aCBSZXBvc2l0b3J5IHJvb3QgcGF0aCB0byBmaW5kIHRoZSBwYWNrYWdlLmpzb25cbiAgICogQHJldHVybiB7UHJvbWlzZTxzdHJpbmc+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgbW9kdWxlIG5hbWVcbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgQ2xpV3JhcHBlclxuICAgKiAgIHBhcnRpY2lwYW50IENMSVV0aWxzXG4gICAqICAgcGFydGljaXBhbnQgTW9kdWxlXG4gICAqICAgXG4gICAqICAgQ2xpV3JhcHBlci0+PkNMSVV0aWxzOiBsb2FkRnJvbUZpbGUoZmlsZVBhdGgpXG4gICAqICAgQ0xJVXRpbHMtLT4+Q2xpV3JhcHBlcjogbW9kdWxlXG4gICAqICAgQ2xpV3JhcHBlci0+PkNsaVdyYXBwZXI6IEdldCBtb2R1bGUgbmFtZVxuICAgKiAgIENsaVdyYXBwZXItPj5Db21tYW5kOiBuZXcgQ29tbWFuZCgpXG4gICAqICAgQ29tbWFuZC0tPj5DbGlXcmFwcGVyOiBjbWRcbiAgICogICBDbGlXcmFwcGVyLT4+Q0xJVXRpbHM6IGluaXRpYWxpemUoY21kLCBwYXRoLmRpcm5hbWUocm9vdFBhdGgpKVxuICAgKiAgIENsaVdyYXBwZXItPj5Nb2R1bGU6IG1vZHVsZSgpXG4gICAqICAgTm90ZSBvdmVyIENsaVdyYXBwZXIsTW9kdWxlOiBIYW5kbGUgUHJvbWlzZSBpZiBuZWVkZWRcbiAgICogICBNb2R1bGUtLT4+Q2xpV3JhcHBlcjogQ29tbWFuZCBpbnN0YW5jZVxuICAgKiAgIENsaVdyYXBwZXItPj5DbGlXcmFwcGVyOiBTdG9yZSBpbiBtb2R1bGVzW25hbWVdXG4gICAqICAgQ2xpV3JhcHBlci0tPj5DbGlXcmFwcGVyOiBSZXR1cm4gbmFtZVxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBsb2FkKGZpbGVQYXRoOiBzdHJpbmcsIHJvb3RQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGxldCBuYW1lO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBtb2R1bGUgPSBhd2FpdCBDTElVdGlscy5sb2FkRnJvbUZpbGUoZmlsZVBhdGgpO1xuICAgICAgbmFtZSA9IG1vZHVsZS5uYW1lO1xuICAgICAgY29uc3QgY21kID0gbmV3IENvbW1hbmQoKTtcbiAgICAgIENMSVV0aWxzLmluaXRpYWxpemUoY21kLCByb290UGF0aCk7XG4gICAgICBsZXQgbSA9IG1vZHVsZSgpO1xuICAgICAgaWYgKG0gaW5zdGFuY2VvZiBQcm9taXNlKSBtID0gYXdhaXQgbTtcbiAgICAgIHRoaXMubW9kdWxlc1tuYW1lXSA9IG07XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgZmFpbGVkIHRvIGxvYWQgbW9kdWxlICR7bmFtZSB8fCBcInVubmFtZWRcIn0gdW5kZXIgJHtmaWxlUGF0aH06ICR7ZSBpbnN0YW5jZW9mIEVycm9yID8gZS5tZXNzYWdlIDogZX1gXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gbmFtZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRmluZHMgYW5kIGxvYWRzIGFsbCBDTEkgbW9kdWxlcyBpbiB0aGUgYmFzZVBhdGhcbiAgICogQHN1bW1hcnkgVXNlcyB0aGUgY3Jhd2wgbWV0aG9kIHRvIGZpbmQgYWxsIENMSSBtb2R1bGVzIGluIHRoZSBzcGVjaWZpZWQgYmFzZSBwYXRoLCBcbiAgICogdGhlbiBsb2FkcyBhbmQgcmVnaXN0ZXJzIGVhY2ggbW9kdWxlIGFzIGEgc3ViY29tbWFuZFxuICAgKiBcbiAgICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBhbGwgbW9kdWxlcyBhcmUgbG9hZGVkXG4gICAqIFxuICAgKiBAcHJpdmF0ZVxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBDbGlXcmFwcGVyXG4gICAqICAgcGFydGljaXBhbnQgRmlsZXN5c3RlbVxuICAgKiAgIHBhcnRpY2lwYW50IE1vZHVsZVxuICAgKiAgIFxuICAgKiAgIENsaVdyYXBwZXItPj5GaWxlc3lzdGVtOiBKb2luIGJhc2VQYXRoIHdpdGggY3dkXG4gICAqICAgQ2xpV3JhcHBlci0+PkNsaVdyYXBwZXI6IGNyYXdsKGJhc2VQYXRoLCBjcmF3bExldmVscylcbiAgICogICBDbGlXcmFwcGVyLS0+PkNsaVdyYXBwZXI6IG1vZHVsZXNbXVxuICAgKiAgIGxvb3AgRm9yIGVhY2ggbW9kdWxlXG4gICAqICAgICBhbHQgTm90IEBkZWNhZi10cy9jbGlcbiAgICogICAgICAgQ2xpV3JhcHBlci0+PkNsaVdyYXBwZXI6IGxvYWQobW9kdWxlLCBjd2QpXG4gICAqICAgICAgIENsaVdyYXBwZXItLT4+Q2xpV3JhcHBlcjogbmFtZVxuICAgKiAgICAgICBDbGlXcmFwcGVyLT4+Q2xpV3JhcHBlcjogQ2hlY2sgaWYgY29tbWFuZCBleGlzdHNcbiAgICogICAgICAgYWx0IENvbW1hbmQgZG9lc24ndCBleGlzdFxuICAgKiAgICAgICAgIENsaVdyYXBwZXItPj5Db21tYW5kOiBjb21tYW5kKG5hbWUpLmFkZENvbW1hbmQobW9kdWxlc1tuYW1lXSlcbiAgICogICAgICAgZW5kXG4gICAqICAgICBlbmRcbiAgICogICBlbmRcbiAgICogICBDbGlXcmFwcGVyLT4+Q29uc29sZTogTG9nIGxvYWRlZCBtb2R1bGVzXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGJvb3QoKSB7XG4gICAgY29uc3QgYmFzZVBhdGggPSBwYXRoLnJlc29sdmUodGhpcy5yb290UGF0aCwgdGhpcy5iYXNlUGF0aCk7XG4gICAgY29uc3QgbW9kdWxlcyA9IHRoaXMuY3Jhd2woYmFzZVBhdGgsIHRoaXMuY3Jhd2xMZXZlbHMpO1xuICAgIGZvciAoY29uc3QgbW9kdWxlIG9mIG1vZHVsZXMpIHtcbiAgICAgIGlmIChtb2R1bGUuaW5jbHVkZXMoXCJAZGVjYWYtdHMvY2xpXCIpKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgbGV0IG5hbWU6IHN0cmluZztcbiAgICAgIHRyeSB7XG4gICAgICAgIG5hbWUgPSBhd2FpdCB0aGlzLmxvYWQobW9kdWxlLCB0aGlzLnJvb3RQYXRoKTtcbiAgICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihlKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChcbiAgICAgICAgIXRoaXMuY29tbWFuZC5jb21tYW5kcy5maW5kKFxuICAgICAgICAgIChjKSA9PiAoYyBhcyB1bmtub3duIGFzIFJlY29yZDxzdHJpbmcsIHN0cmluZz4pW1wiX25hbWVcIl0gPT09IG5hbWVcbiAgICAgICAgKVxuICAgICAgKVxuICAgICAgICB0cnkge1xuICAgICAgICAgIHRoaXMuY29tbWFuZC5jb21tYW5kKG5hbWUpLmFkZENvbW1hbmQodGhpcy5tb2R1bGVzW25hbWVdKTtcbiAgICAgICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgY29uc29sZS5sb2coXG4gICAgICBgbG9hZGVkIG1vZHVsZXM6XFxuJHtPYmplY3Qua2V5cyh0aGlzLm1vZHVsZXMpXG4gICAgICAgIC5tYXAoKGspID0+IGAtICR7a31gKVxuICAgICAgICAuam9pbihcIlxcblwiKX1gXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmVjdXJzaXZlbHkgc2VhcmNoZXMgZm9yIENMSSBtb2R1bGUgZmlsZXMgaW4gdGhlIGRpcmVjdG9yeSBzdHJ1Y3R1cmVcbiAgICogQHN1bW1hcnkgQ3Jhd2xzIHRoZSBiYXNlUGF0aCB1cCB0byB0aGUgc3BlY2lmaWVkIG51bWJlciBvZiBmb2xkZXIgbGV2ZWxzIHRvIGZpbmQgZmlsZXMgbmFtZWQgYWNjb3JkaW5nIHRvIENMSV9GSUxFX05BTUVcbiAgICogXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBiYXNlUGF0aCBUaGUgYWJzb2x1dGUgYmFzZSBwYXRoIHRvIHN0YXJ0IHNlYXJjaGluZyBpblxuICAgKiBAcGFyYW0ge251bWJlcn0gW2xldmVscz0yXSBUaGUgbWF4aW11bSBudW1iZXIgb2YgZGlyZWN0b3J5IGxldmVscyB0byBjcmF3bFxuICAgKiBAcmV0dXJuIHtzdHJpbmdbXX0gQW4gYXJyYXkgb2YgZmlsZSBwYXRocyB0byBDTEkgbW9kdWxlc1xuICAgKiBcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgY3Jhd2woYmFzZVBhdGg6IHN0cmluZywgbGV2ZWxzOiBudW1iZXIgPSAyKSB7XG4gICAgaWYgKGxldmVscyA8PSAwKSByZXR1cm4gW107XG4gICAgcmV0dXJuIGZzLnJlYWRkaXJTeW5jKGJhc2VQYXRoKS5yZWR1Y2UoKGFjY3VtOiBzdHJpbmdbXSwgZmlsZSkgPT4ge1xuICAgICAgZmlsZSA9IHBhdGguam9pbihiYXNlUGF0aCwgZmlsZSk7XG4gICAgICBpZiAoZnMuc3RhdFN5bmMoZmlsZSkuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgICBhY2N1bS5wdXNoKC4uLnRoaXMuY3Jhd2woZmlsZSwgbGV2ZWxzIC0gMSkpO1xuICAgICAgfSBlbHNlIGlmIChmaWxlLm1hdGNoKG5ldyBSZWdFeHAoYCR7Q0xJX0ZJTEVfTkFNRX0uW2NtXT9qcyRgLCBcImdtXCIpKSkge1xuICAgICAgICBhY2N1bS5wdXNoKGZpbGUpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFjY3VtO1xuICAgIH0sIFtdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRXhlY3V0ZXMgdGhlIENMSSB3aXRoIHRoZSBwcm92aWRlZCBhcmd1bWVudHNcbiAgICogQHN1bW1hcnkgQm9vdHMgdGhlIENMSSBieSBsb2FkaW5nIGFsbCBtb2R1bGVzLCB0aGVuIHBhcnNlcyBhbmQgZXhlY3V0ZXMgdGhlIGNvbW1hbmQgc3BlY2lmaWVkIGluIHRoZSBhcmd1bWVudHNcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmdbXX0gW2FyZ3M9cHJvY2Vzcy5hcmd2XSBDb21tYW5kIGxpbmUgYXJndW1lbnRzIHRvIHBhcnNlIGFuZCBleGVjdXRlXG4gICAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIGNvbW1hbmQgZXhlY3V0aW9uIGlzIGNvbXBsZXRlXG4gICAqIFxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBDbGllbnRcbiAgICogICBwYXJ0aWNpcGFudCBDbGlXcmFwcGVyXG4gICAqICAgcGFydGljaXBhbnQgQ29tbWFuZFxuICAgKiAgIFxuICAgKiAgIENsaWVudC0+PkNsaVdyYXBwZXI6IHJ1bihhcmdzKVxuICAgKiAgIENsaVdyYXBwZXItPj5DbGlXcmFwcGVyOiBib290KClcbiAgICogICBOb3RlIG92ZXIgQ2xpV3JhcHBlcjogTG9hZHMgYWxsIG1vZHVsZXNcbiAgICogICBDbGlXcmFwcGVyLT4+Q29tbWFuZDogcGFyc2VBc3luYyhhcmdzKVxuICAgKiAgIENvbW1hbmQtLT4+Q2xpV3JhcHBlcjogcmVzdWx0XG4gICAqICAgQ2xpV3JhcHBlci0tPj5DbGllbnQ6IHJlc3VsdFxuICAgKi9cbiAgYXN5bmMgcnVuKGFyZ3M6IHN0cmluZ1tdID0gcHJvY2Vzcy5hcmd2KSB7XG4gICAgYXdhaXQgdGhpcy5ib290KCk7XG4gICAgcmV0dXJuIHRoaXMuY29tbWFuZC5wYXJzZUFzeW5jKGFyZ3MpO1xuICB9XG59XG4iLCJleHBvcnQgKiBmcm9tIFwiLi9DbGlXcmFwcGVyXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIERlY2FmLXRzJyBDTEkgbW9kdWxlXG4gKiBAc3VtbWFyeSBUaGlzIGZpbGUgd2lsbCBjcmF3bCB0aGUgY3VycmVudCB3b3JraW5nIGRpcmVjdG9yeSBmb3IgZmlsZXMgY2FsbGVkIHtAbGluayBDTElfRklMRV9OQU1FfVxuICogd2l0aGluIHRoZSBAZGVjYWYtdHMgbmFtZXNwYWNlIGFuZCBsb2FkIHRoZW0gYXMgc3ViY29tbWFuZHMuIEl0IHNlcnZlcyBhcyB0aGUgbWFpbiBlbnRyeSBwb2ludFxuICogZm9yIHRoZSBDTEkgZnVuY3Rpb25hbGl0eSwgZXhwb3J0aW5nIHRoZSBDbGlXcmFwcGVyIGNsYXNzIGFuZCBWRVJTSU9OIGNvbnN0YW50LlxuICpcbiAqIEBleGFtcGxlXG4gKiBydW4gbW9kdWxlIGNvbW1hbmQgICAgIC0gJCBucHggZGVjYWYgPG1vZHVsZSBuYW1lPiA8bW9kdWxlIGNvbW1hbmQ+IC4uLjxtb2R1bGUgY29tbWFuZCBvcHRpb25zPlxuICogZ2V0IG1vZHVsZSBoZWxwICAgICAgICAtICQgbnB4IGRlY2FmIGhlbHAgPG1vZHVsZSBuYW1lPjtcbiAqIGxpc3QgaW1wb3J0ZWQgbW9kdWxlcyAgLSAkIG5weCBkZWNhZiBsaXN0O1xuICogZ2V0IGNsaSBoZWxwICAgICAgICAgICAtICQgbnB4IGRlY2FmIGhlbHA7XG4gKlxuICogQG1vZHVsZSBDTElcbiAqL1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBTdG9yZXMgdGhlIGN1cnJlbnQgcGFja2FnZSB2ZXJzaW9uXG4gKiBAc3VtbWFyeSBBIGNvbnN0YW50IHRoYXQgaG9sZHMgdGhlIHZlcnNpb24gc3RyaW5nIG9mIHRoZSBwYWNrYWdlLCB3aGljaCBpcyByZXBsYWNlZCBkdXJpbmcgYnVpbGRcbiAqIEBjb25zdCBWRVJTSU9OXG4gKiBAbWVtYmVyT2YgbW9kdWxlOkNMSVxuICovXG5leHBvcnQgY29uc3QgVkVSU0lPTiA9IFwiIyNWRVJTSU9OIyNcIjtcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBR0E7Ozs7OztBQU1HO0FBQ0ksTUFBTSxhQUFhLEdBQUcsWUFBWTs7QUNMekM7Ozs7Ozs7Ozs7Ozs7QUFhRztNQUNVLFFBQVEsQ0FBQTtBQUNuQjs7Ozs7O0FBTUc7QUFDSCxJQUFBLGFBQWEsWUFBWSxDQUFDLElBQVksRUFBQTtBQUNwQyxRQUFBLElBQUk7WUFDRixPQUFPLFFBQVEsQ0FBQyxlQUFlLENBQUMsT0FBTyxJQUFJLENBQUMsQ0FBQzs7UUFDN0MsT0FBTyxDQUFVLEVBQUU7WUFDbkIsTUFBTSxJQUFJLEtBQUssQ0FDYixDQUFBLG9CQUFBLEVBQXVCLElBQUksQ0FBSyxFQUFBLEVBQUEsQ0FBQyxZQUFZLEtBQUssR0FBRyxDQUFDLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBRSxDQUFBLENBQ3JFOzs7QUFJTDs7Ozs7Ozs7QUFRRztBQUNILElBQUEsYUFBYSxlQUFlLENBQUksYUFBeUIsRUFBQTs7QUFFdkQsUUFBQSxPQUFPLGFBQWEsQ0FBQyxJQUFJLENBQ3ZC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
|