@zokugun/artifact 0.6.3 → 0.7.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/lib/cli.js +14 -4
- package/lib/commands/add.d.ts +9 -3
- package/lib/commands/add.js +7 -1
- package/lib/commands/remove.js +2 -1
- package/lib/commands/update.js +2 -1
- package/lib/steps/replace-templates.d.ts +1 -1
- package/lib/steps/replace-templates.js +2 -1
- package/lib/steps/validate-not-present-package.js +2 -2
- package/lib/types/context.d.ts +2 -0
- package/lib/types/context.js +0 -4
- package/lib/utils/template.d.ts +1 -1
- package/lib/utils/template.js +58 -11
- package/package.json +3 -2
package/lib/cli.js
CHANGED
|
@@ -8,27 +8,37 @@ const package_json_1 = __importDefault(require("../package.json"));
|
|
|
8
8
|
const index_js_1 = require("./commands/index.js");
|
|
9
9
|
const program = new commander_1.Command();
|
|
10
10
|
program
|
|
11
|
-
.version(package_json_1.default.version, '-
|
|
11
|
+
.version(package_json_1.default.version, '-v, --version')
|
|
12
12
|
.description(package_json_1.default.description);
|
|
13
13
|
program
|
|
14
14
|
.command('add')
|
|
15
15
|
.description('add an artifact to the current project')
|
|
16
16
|
.option('-d, --dry-run', 'fake install')
|
|
17
|
-
.option('
|
|
17
|
+
.option('--verbose', 'output more details')
|
|
18
|
+
.option('--var <name=value>', 'pass a variable (format: name=value), repeatable', (pair, previous = []) => {
|
|
19
|
+
const index = pair.indexOf('=');
|
|
20
|
+
if (index === -1) {
|
|
21
|
+
throw new Error('--var expects format name=value');
|
|
22
|
+
}
|
|
23
|
+
const name = pair.slice(0, index);
|
|
24
|
+
const value = pair.slice(index + 1);
|
|
25
|
+
previous.push({ name, value });
|
|
26
|
+
return previous;
|
|
27
|
+
}, [])
|
|
18
28
|
.argument('<artifacts...>')
|
|
19
29
|
.action(index_js_1.add);
|
|
20
30
|
program
|
|
21
31
|
.command('update')
|
|
22
32
|
.description('update the current project using the installed artifacts')
|
|
23
33
|
.option('-d, --dry-run', 'fake update')
|
|
24
|
-
.option('
|
|
34
|
+
.option('--verbose', 'output more details')
|
|
25
35
|
.alias('up')
|
|
26
36
|
.action(index_js_1.update);
|
|
27
37
|
program
|
|
28
38
|
.command('remove')
|
|
29
39
|
.description('remove an artifact from the current project')
|
|
30
40
|
.option('-d, --dry-run', 'fake uninstall')
|
|
31
|
-
.option('
|
|
41
|
+
.option('--verbose', 'output more details')
|
|
32
42
|
.argument('<artifacts...>')
|
|
33
43
|
.alias('rm')
|
|
34
44
|
.action(index_js_1.remove);
|
package/lib/commands/add.d.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
type CLIOptions = {
|
|
2
|
+
dryRun?: boolean;
|
|
2
3
|
force?: boolean;
|
|
3
4
|
skip?: boolean;
|
|
5
|
+
var?: Array<{
|
|
6
|
+
name: string;
|
|
7
|
+
value: string;
|
|
8
|
+
}>;
|
|
4
9
|
verbose?: boolean;
|
|
5
|
-
|
|
6
|
-
|
|
10
|
+
};
|
|
11
|
+
export declare function add(specs: string[], inputOptions?: CLIOptions): Promise<void>;
|
|
12
|
+
export {};
|
package/lib/commands/add.js
CHANGED
|
@@ -37,11 +37,17 @@ async function add(specs, inputOptions) {
|
|
|
37
37
|
cli_utils_1.logger.beginTimer();
|
|
38
38
|
const targetPath = process_1.default.cwd();
|
|
39
39
|
const options = {
|
|
40
|
+
dryRun: inputOptions?.dryRun ?? false,
|
|
40
41
|
force: inputOptions?.force ?? false,
|
|
41
42
|
skip: inputOptions?.skip ?? false,
|
|
43
|
+
variables: {},
|
|
42
44
|
verbose: inputOptions?.verbose ?? false,
|
|
43
|
-
dryRun: inputOptions?.dryRun ?? false,
|
|
44
45
|
};
|
|
46
|
+
if (inputOptions?.var) {
|
|
47
|
+
for (const { name, value } of inputOptions.var) {
|
|
48
|
+
options.variables[name] = value;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
45
51
|
const configResult = await (0, index_js_1.readInstallConfig)(targetPath);
|
|
46
52
|
if (configResult.fails) {
|
|
47
53
|
cli_utils_1.logger.fatal(configResult.error);
|
package/lib/commands/remove.js
CHANGED
|
@@ -32,10 +32,11 @@ async function remove(specs, inputOptions) {
|
|
|
32
32
|
cli_utils_1.logger.beginTimer();
|
|
33
33
|
const targetPath = process_1.default.cwd();
|
|
34
34
|
const options = {
|
|
35
|
+
dryRun: inputOptions?.dryRun ?? false,
|
|
35
36
|
force: inputOptions?.force ?? false,
|
|
36
37
|
skip: inputOptions?.skip ?? false,
|
|
38
|
+
variables: {},
|
|
37
39
|
verbose: inputOptions?.verbose ?? false,
|
|
38
|
-
dryRun: inputOptions?.dryRun ?? false,
|
|
39
40
|
};
|
|
40
41
|
const configResult = await (0, index_js_1.readInstallConfig)(targetPath);
|
|
41
42
|
if (configResult.fails) {
|
package/lib/commands/update.js
CHANGED
|
@@ -37,10 +37,11 @@ async function update(inputOptions) {
|
|
|
37
37
|
cli_utils_1.logger.beginTimer();
|
|
38
38
|
const targetPath = process_1.default.cwd();
|
|
39
39
|
const options = {
|
|
40
|
+
dryRun: inputOptions?.dryRun ?? false,
|
|
40
41
|
force: inputOptions?.force ?? false,
|
|
41
42
|
skip: false,
|
|
43
|
+
variables: {},
|
|
42
44
|
verbose: inputOptions?.verbose ?? false,
|
|
43
|
-
dryRun: inputOptions?.dryRun ?? false,
|
|
44
45
|
};
|
|
45
46
|
const configResult = await (0, index_js_1.readInstallConfig)(targetPath);
|
|
46
47
|
if (configResult.fails) {
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { type AsyncDResult } from '@zokugun/xtry';
|
|
2
2
|
import { type Context } from '../types/context.js';
|
|
3
|
-
export declare function replaceTemplates({ textFiles, binaryFiles, targetPath, config, incomingConfig }: Context): AsyncDResult;
|
|
3
|
+
export declare function replaceTemplates({ textFiles, binaryFiles, targetPath, config, incomingConfig, options }: Context): AsyncDResult;
|
|
@@ -3,10 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.replaceTemplates = replaceTemplates;
|
|
4
4
|
const xtry_1 = require("@zokugun/xtry");
|
|
5
5
|
const template_js_1 = require("../utils/template.js");
|
|
6
|
-
async function replaceTemplates({ textFiles, binaryFiles, targetPath, config, incomingConfig }) {
|
|
6
|
+
async function replaceTemplates({ textFiles, binaryFiles, targetPath, config, incomingConfig, options }) {
|
|
7
7
|
const variables = {
|
|
8
8
|
...incomingConfig?.variables,
|
|
9
9
|
...config?.variables,
|
|
10
|
+
...options.variables,
|
|
10
11
|
};
|
|
11
12
|
const engine = new template_js_1.TemplateEngine(targetPath, variables);
|
|
12
13
|
for (const file of textFiles) {
|
|
@@ -12,12 +12,12 @@ async function validateNotPresentPackage({ incomingPackage, config, options }) {
|
|
|
12
12
|
if (artifact) {
|
|
13
13
|
if (options.skip) {
|
|
14
14
|
if (options.verbose) {
|
|
15
|
-
cli_utils_1.logger.debug(
|
|
15
|
+
cli_utils_1.logger.debug(`The "${name}" artifact is already present, skipping...`);
|
|
16
16
|
}
|
|
17
17
|
return xtry_1.OK_TRUE;
|
|
18
18
|
}
|
|
19
19
|
else {
|
|
20
|
-
return (0, xtry_1.err)(
|
|
20
|
+
return (0, xtry_1.err)(`The "${name}" artifact has already been added.`);
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
return xtry_1.OK;
|
package/lib/types/context.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type Primitive } from '@zokugun/is-it-type';
|
|
1
2
|
import { type AsyncDResult } from '@zokugun/xtry';
|
|
2
3
|
import { type BinaryFile } from './binary-file.js';
|
|
3
4
|
import { type Request, type InstallConfig, type PackageConfig, type ArtifactResult, type PackageManifest, type FileTransform } from './config.js';
|
|
@@ -45,6 +46,7 @@ export type Options = {
|
|
|
45
46
|
skip: boolean;
|
|
46
47
|
verbose: boolean;
|
|
47
48
|
dryRun: boolean;
|
|
49
|
+
variables: Record<string, Primitive>;
|
|
48
50
|
};
|
|
49
51
|
export type Block = {
|
|
50
52
|
name: string;
|
package/lib/types/context.js
CHANGED
package/lib/utils/template.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export declare class TemplateEngine {
|
|
|
8
8
|
constructor(basePath: string, variables?: Record<string, Primitive>);
|
|
9
9
|
render(template: string): DResult<string>;
|
|
10
10
|
private getValueByPath;
|
|
11
|
+
private evaluateExpression;
|
|
11
12
|
private parseFile;
|
|
12
13
|
private readConfigFile;
|
|
13
14
|
private resolveExpression;
|
|
@@ -15,4 +16,3 @@ export declare class TemplateEngine {
|
|
|
15
16
|
private splitPlaceholder;
|
|
16
17
|
private toDate;
|
|
17
18
|
}
|
|
18
|
-
export declare function unescapeCode(code: string): string;
|
package/lib/utils/template.js
CHANGED
|
@@ -37,19 +37,26 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
exports.TemplateEngine = void 0;
|
|
40
|
-
exports.unescapeCode = unescapeCode;
|
|
41
40
|
const path_1 = __importDefault(require("path"));
|
|
42
41
|
const sync_1 = __importDefault(require("@zokugun/fs-extra-plus/sync"));
|
|
43
42
|
const is_it_type_1 = require("@zokugun/is-it-type");
|
|
44
43
|
const xtry_1 = require("@zokugun/xtry");
|
|
45
44
|
const dayjs_1 = __importDefault(require("dayjs"));
|
|
46
45
|
const utc_1 = __importDefault(require("dayjs/plugin/utc"));
|
|
46
|
+
const git_url_parse_1 = __importDefault(require("git-url-parse"));
|
|
47
47
|
const lodash_es_1 = require("lodash-es");
|
|
48
48
|
const YAML = __importStar(require("../parsers/yaml.js"));
|
|
49
49
|
const try_json_js_1 = require("./try-json.js");
|
|
50
50
|
dayjs_1.default.extend(utc_1.default);
|
|
51
51
|
const EXPRESSION_REGEX = /#\[\[(.*?)]]/g;
|
|
52
|
-
const
|
|
52
|
+
const PATH_PROPERTY_REGEX = /^(\w+?)(?:\.|$)(.*)$/;
|
|
53
|
+
const PIPE_SEPARATOR_REGEX = /\s*\|>\s*/;
|
|
54
|
+
// Pattern: |> fn(_).prop
|
|
55
|
+
const PIPE_CALL_REGEX = /^([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*)\(\s*_\s*\)\s*(\.\s*.*?)\s*$/;
|
|
56
|
+
// Pattern: |> fn
|
|
57
|
+
const PIPE_FUNCTION_REGEX = /^([A-Za-z_$][\w$]+(?:\.[A-Za-z_$][\w$]*)*)\s*$/;
|
|
58
|
+
// Pattern: |> _.prop
|
|
59
|
+
const PIPE_PROPERTY_REGEX = /^_\.\s*(.*?)\s*$/;
|
|
53
60
|
const PLACEHOLDER_REGEX = /^((?:[^/.]+(?:[^/]+\/)*\/)?\.?[^.]+(?:\.(?:json|ya?ml))?)\.(.*)$/;
|
|
54
61
|
class TemplateEngine {
|
|
55
62
|
basePath;
|
|
@@ -79,7 +86,7 @@ class TemplateEngine {
|
|
|
79
86
|
let currentPath = propertyPath;
|
|
80
87
|
let currentValue = values;
|
|
81
88
|
let match;
|
|
82
|
-
while ((match =
|
|
89
|
+
while ((match = PATH_PROPERTY_REGEX.exec(currentPath))) {
|
|
83
90
|
if (!(0, lodash_es_1.isPlainObject)(currentValue)) {
|
|
84
91
|
return (0, xtry_1.err)(`Property path not found: ${propertyPath}`);
|
|
85
92
|
}
|
|
@@ -89,12 +96,51 @@ class TemplateEngine {
|
|
|
89
96
|
}
|
|
90
97
|
currentPath = match[2];
|
|
91
98
|
if (currentPath.length === 0) {
|
|
92
|
-
return (0, xtry_1.ok)(currentValue);
|
|
99
|
+
return (0, xtry_1.ok)({ value: currentValue });
|
|
93
100
|
}
|
|
94
101
|
}
|
|
102
|
+
return (0, xtry_1.ok)({ value: currentValue, expression: `.${currentPath}` });
|
|
103
|
+
} // }}}
|
|
104
|
+
evaluateExpression(expression, values) {
|
|
105
|
+
const operands = expression.split(PIPE_SEPARATOR_REGEX);
|
|
106
|
+
const root = this.getValueByPath(values, operands.shift());
|
|
107
|
+
if (root.fails) {
|
|
108
|
+
return root;
|
|
109
|
+
}
|
|
110
|
+
const { value, expression: rootExpression } = root.value;
|
|
111
|
+
if (operands.length === 0) {
|
|
112
|
+
if ((0, is_it_type_1.isNonEmptyString)(rootExpression)) {
|
|
113
|
+
// eslint-disable-next-line no-new-func
|
|
114
|
+
const fn = new Function('it', `return it${unescapeCode(rootExpression)};`);
|
|
115
|
+
return (0, xtry_1.ok)(fn(value));
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
return (0, xtry_1.ok)(value);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
const lines = [];
|
|
122
|
+
if ((0, is_it_type_1.isNonEmptyString)(rootExpression)) {
|
|
123
|
+
lines.push(`it = it${unescapeCode(rootExpression)};`);
|
|
124
|
+
}
|
|
125
|
+
let match = null;
|
|
126
|
+
for (const operand of operands) {
|
|
127
|
+
if ((match = PIPE_FUNCTION_REGEX.exec(operand))) {
|
|
128
|
+
lines.push(`it = ${unescapeCode(match[1])}(it);`);
|
|
129
|
+
}
|
|
130
|
+
else if ((match = PIPE_PROPERTY_REGEX.exec(operand))) {
|
|
131
|
+
lines.push(`it = it.${unescapeCode(match[1])};`);
|
|
132
|
+
}
|
|
133
|
+
else if ((match = PIPE_CALL_REGEX.exec(operand))) {
|
|
134
|
+
lines.push(`it = ${unescapeCode(match[1])}(it)${unescapeCode(match[2])};`);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
return (0, xtry_1.err)(`Cannot evaluate "${expression}"`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
lines.push('return it;');
|
|
95
141
|
// eslint-disable-next-line no-new-func
|
|
96
|
-
const fn = new Function('it',
|
|
97
|
-
return (0, xtry_1.ok)(fn(
|
|
142
|
+
const fn = new Function('it, toGitUrl', lines.join('\n'));
|
|
143
|
+
return (0, xtry_1.ok)(fn(value, git_url_parse_1.default));
|
|
98
144
|
} // }}}
|
|
99
145
|
parseFile(filename) {
|
|
100
146
|
const result = sync_1.default.readFile(filename, 'utf8');
|
|
@@ -151,14 +197,15 @@ class TemplateEngine {
|
|
|
151
197
|
if (readResult.fails) {
|
|
152
198
|
return readResult;
|
|
153
199
|
}
|
|
154
|
-
const getValueResult = this.getValueByPath(readResult.value, propertyPath);
|
|
155
|
-
|
|
156
|
-
|
|
200
|
+
// const getValueResult = this.getValueByPath(readResult.value, propertyPath);
|
|
201
|
+
const evalResult = this.evaluateExpression(propertyPath, readResult.value);
|
|
202
|
+
if (evalResult.fails) {
|
|
203
|
+
return evalResult;
|
|
157
204
|
}
|
|
158
|
-
if ((0, lodash_es_1.isNil)(
|
|
205
|
+
if ((0, lodash_es_1.isNil)(evalResult.value)) {
|
|
159
206
|
return (0, xtry_1.err)(expression);
|
|
160
207
|
}
|
|
161
|
-
return (0, xtry_1.ok)(String(
|
|
208
|
+
return (0, xtry_1.ok)(String(evalResult.value));
|
|
162
209
|
}
|
|
163
210
|
} // }}}
|
|
164
211
|
resolveVariable(name) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zokugun/artifact",
|
|
3
3
|
"description": "Boilerplate your project & keep your configurations up to date",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.7.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Baptiste Augrain",
|
|
7
7
|
"email": "daiyam@zokugun.org"
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"release": "release-it",
|
|
38
38
|
"test": "tsc -p test && mocha",
|
|
39
39
|
"test:dev": "mocha",
|
|
40
|
-
"test:watch": "tsc-watch -p src -p test --onSuccess 'mocha -g=\"\"'",
|
|
40
|
+
"test:watch": "tsc-watch -p src -p test --onSuccess 'mocha -g=\"vars.exp.pipe.gitname.dotprop\"'",
|
|
41
41
|
"update:artifacts": "artifact update",
|
|
42
42
|
"update:ci": "PINACT_MIN_AGE=7 pinact run",
|
|
43
43
|
"update:deps": "taze",
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"@zokugun/xtry": "0.11.4",
|
|
54
54
|
"dayjs": "1.11.20",
|
|
55
55
|
"editorconfig": "0.15.3",
|
|
56
|
+
"git-url-parse": "16.1.0",
|
|
56
57
|
"globby": "11.1.0",
|
|
57
58
|
"istextorbinary": "6.0.0",
|
|
58
59
|
"jq-wasm": "1.1.0-jq-1.8.1",
|