@zokugun/artifact 0.4.4 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/lib/cli.js +1 -1
  2. package/lib/commands/add.js +32 -44
  3. package/lib/commands/list.js +15 -27
  4. package/lib/commands/update.js +34 -46
  5. package/lib/compositors/compose.js +4 -5
  6. package/lib/compositors/fork.js +2 -2
  7. package/lib/compositors/json.js +1 -1
  8. package/lib/compositors/rc.js +1 -2
  9. package/lib/configs/install/read-install-config.js +74 -82
  10. package/lib/configs/install/write-install-config.js +21 -32
  11. package/lib/configs/package/read-package-config.js +33 -44
  12. package/lib/parsers/jsonc/stringify.js +11 -14
  13. package/lib/routes/command.js +26 -32
  14. package/lib/routes/lines-concat.js +1 -1
  15. package/lib/routes/list-concat.js +1 -1
  16. package/lib/routes/list-sort-concat.js +1 -1
  17. package/lib/routes/map-concat.js +2 -2
  18. package/lib/routes/overwrite.js +1 -1
  19. package/lib/routes/primitive.js +1 -1
  20. package/lib/steps/apply-formatting.js +7 -18
  21. package/lib/steps/configure-branches.js +43 -54
  22. package/lib/steps/configure-install-file-actions.js +52 -63
  23. package/lib/steps/configure-update-file-actions.js +63 -74
  24. package/lib/steps/copy-binary-files.js +29 -40
  25. package/lib/steps/execute-first-block.js +61 -75
  26. package/lib/steps/execute-next-block.js +6 -17
  27. package/lib/steps/index.js +23 -16
  28. package/lib/steps/insert-final-new-line.js +7 -18
  29. package/lib/steps/merge-text-files.js +70 -79
  30. package/lib/steps/read-editor-config.js +35 -46
  31. package/lib/steps/read-files.js +38 -48
  32. package/lib/steps/read-incoming-config.js +7 -18
  33. package/lib/steps/read-incoming-package.js +7 -18
  34. package/lib/steps/remove-files.js +18 -29
  35. package/lib/steps/replace-templates.js +15 -20
  36. package/lib/steps/validate-newer-package.js +8 -19
  37. package/lib/steps/validate-not-present-package.js +15 -26
  38. package/lib/steps/write-text-files.js +16 -27
  39. package/lib/utils/command/dedupe-strings.js +12 -0
  40. package/lib/utils/command/index.js +11 -1
  41. package/lib/utils/command/merge-and-chains.js +91 -0
  42. package/lib/utils/command/merge-command-records.js +82 -0
  43. package/lib/utils/command/merge-flag-tokens.js +14 -0
  44. package/lib/utils/command/merge-flags-as-string.js +10 -0
  45. package/lib/utils/command/merge-or-segments.js +85 -0
  46. package/lib/utils/command/merge-parts-by-prefix.js +25 -0
  47. package/lib/utils/command/merge-semicolon-segments.js +127 -0
  48. package/lib/utils/command/merge-with-semicolon-mix.js +48 -0
  49. package/lib/utils/command/prefix-of-command.js +7 -0
  50. package/lib/utils/command/split-chain.js +6 -0
  51. package/lib/utils/command/split-prefix-and-flags.js +29 -0
  52. package/lib/utils/command/split-segments.js +6 -0
  53. package/lib/utils/read-buffer.js +13 -24
  54. package/lib/utils/template.js +63 -31
  55. package/lib/utils/try-json.js +1 -1
  56. package/package.json +4 -4
@@ -1,13 +1,4 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
12
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
4
  };
@@ -15,21 +6,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
6
  exports.readBuffer = readBuffer;
16
7
  const buffer_1 = require("buffer");
17
8
  const promises_1 = __importDefault(require("fs/promises"));
18
- function readBuffer(filepath_1, size_1) {
19
- return __awaiter(this, arguments, void 0, function* (filepath, size, offset = 0) {
20
- const buffer = buffer_1.Buffer.alloc(size);
21
- const file = yield promises_1.default.open(filepath, 'r');
22
- try {
23
- const { bytesRead } = yield file.read(buffer, 0, size, offset);
24
- if (bytesRead < size) {
25
- return buffer.slice(0, bytesRead);
26
- }
27
- else {
28
- return buffer;
29
- }
9
+ async function readBuffer(filepath, size, offset = 0) {
10
+ const buffer = buffer_1.Buffer.alloc(size);
11
+ const file = await promises_1.default.open(filepath, 'r');
12
+ try {
13
+ const { bytesRead } = await file.read(buffer, 0, size, offset);
14
+ if (bytesRead < size) {
15
+ return buffer.slice(0, bytesRead);
30
16
  }
31
- finally {
32
- yield file.close();
17
+ else {
18
+ return buffer;
33
19
  }
34
- });
20
+ }
21
+ finally {
22
+ await file.close();
23
+ }
35
24
  }
@@ -37,6 +37,7 @@ 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;
40
41
  const path_1 = __importDefault(require("path"));
41
42
  const dayjs_1 = __importDefault(require("dayjs"));
42
43
  const utc_1 = __importDefault(require("dayjs/plugin/utc"));
@@ -45,7 +46,8 @@ const lodash_1 = require("lodash");
45
46
  const YAML = __importStar(require("../parsers/yaml"));
46
47
  const try_json_1 = require("./try-json");
47
48
  dayjs_1.default.extend(utc_1.default);
48
- const PLACEHOLDER_REGEX = /^((?:[^/]+(?:[^/]+\/)*\/)?\.?[^.]+(?:\.(?:json|ya?ml))?)\.(.*)$/;
49
+ const NEXT_PROPERTY_REGEX = /^(\w+?)((?=\.|$).*)$/;
50
+ const PLACEHOLDER_REGEX = /^((?:[^/.]+(?:[^/]+\/)*\/)?\.?[^.]+(?:\.(?:json|ya?ml))?)\.(.*)$/;
49
51
  class TemplateError extends Error {
50
52
  constructor(message) {
51
53
  super(message);
@@ -53,49 +55,44 @@ class TemplateError extends Error {
53
55
  } // }}}
54
56
  }
55
57
  class TemplateEngine {
56
- constructor(basePath) {
58
+ constructor(basePath, variables) {
57
59
  this.fileCache = new Map();
60
+ this.variableCache = new Map();
58
61
  this.basePath = basePath;
62
+ this.variables = variables ?? {};
59
63
  } // }}}
60
64
  render(template) {
61
65
  const pattern = /#\[\[(.*?)]]/g;
62
- return template.replace(pattern, (_, placeholder) => {
63
- const [name, propertyPath] = this.splitPlaceholder(placeholder);
64
- if (!name || !propertyPath) {
65
- throw new TemplateError(`Invalid placeholder format: ${placeholder}. Expected format: #[[filename.property]]`);
66
- }
67
- if (name === 'date') {
68
- return this.toDate(propertyPath);
69
- }
70
- const fileContent = this.readConfigFile(name);
71
- const value = this.getValueByPath(fileContent, propertyPath);
72
- if ((0, lodash_1.isNil)(value)) {
73
- throw new TemplateError(placeholder);
74
- }
75
- return String(value);
76
- });
66
+ return template.replace(pattern, (_, placeholder) => this.resolveExpression(placeholder));
77
67
  } // }}}
78
68
  getValueByPath(values, propertyPath) {
79
- const parts = propertyPath.split('.');
80
- let current = values;
81
- for (const part of parts) {
82
- if (!(0, lodash_1.isPlainObject)(current)) {
69
+ let currentPath = propertyPath;
70
+ let currentValue = values;
71
+ // eslint-disable-next-line @typescript-eslint/ban-types
72
+ let match;
73
+ while ((match = NEXT_PROPERTY_REGEX.exec(currentPath))) {
74
+ if (!(0, lodash_1.isPlainObject)(currentValue)) {
83
75
  throw new TemplateError(`Property path not found: ${propertyPath}`);
84
76
  }
85
- current = current[part];
86
- }
87
- if ((0, lodash_1.isNil)(current)) {
88
- throw new TemplateError(`Property not found: ${propertyPath}`);
77
+ currentValue = currentValue[match[1]];
78
+ if ((0, lodash_1.isNil)(currentValue)) {
79
+ throw new TemplateError(`Property not found: ${propertyPath}`);
80
+ }
81
+ currentPath = match[2];
82
+ if (currentPath.length === 0) {
83
+ return currentValue;
84
+ }
89
85
  }
90
- return current;
86
+ // eslint-disable-next-line no-new-func
87
+ const fn = new Function('it', `return it${unescapeCode(currentPath)};`);
88
+ return fn(currentValue);
91
89
  } // }}}
92
90
  parseFile(filename) {
93
- var _a;
94
91
  let content;
95
92
  try {
96
93
  content = fs_extra_1.default.readFileSync(filename, 'utf8');
97
94
  }
98
- catch (_b) {
95
+ catch {
99
96
  throw new TemplateError(`File not found: ${filename}`);
100
97
  }
101
98
  const ext = path_1.default.extname(filename).toLowerCase();
@@ -107,7 +104,7 @@ class TemplateEngine {
107
104
  return YAML.parse(content);
108
105
  }
109
106
  else {
110
- return (_a = (0, try_json_1.tryJson)(content)) !== null && _a !== void 0 ? _a : YAML.parse(content);
107
+ return (0, try_json_1.tryJson)(content) ?? YAML.parse(content);
111
108
  }
112
109
  }
113
110
  catch (parseError) {
@@ -124,10 +121,42 @@ class TemplateEngine {
124
121
  this.fileCache.set(filename, content);
125
122
  return content;
126
123
  } // }}}
124
+ resolveExpression(expression) {
125
+ const [name, propertyPath] = this.splitPlaceholder(expression);
126
+ if (!name || !propertyPath) {
127
+ throw new TemplateError(`Invalid expression format: ${expression}. Expected format: #[[filename.property]]`);
128
+ }
129
+ if (name === 'date') {
130
+ return this.toDate(propertyPath);
131
+ }
132
+ else if (name === 'vars') {
133
+ return this.resolveVariable(propertyPath);
134
+ }
135
+ else {
136
+ const fileContent = this.readConfigFile(name);
137
+ const value = this.getValueByPath(fileContent, propertyPath);
138
+ if ((0, lodash_1.isNil)(value)) {
139
+ throw new TemplateError(expression);
140
+ }
141
+ return String(value);
142
+ }
143
+ } // }}}
144
+ resolveVariable(name) {
145
+ if (this.variableCache.has(name)) {
146
+ return this.variableCache.get(name);
147
+ }
148
+ const expression = this.variables[name];
149
+ if (typeof expression !== 'string' || expression.trim().length === 0) {
150
+ throw new TemplateError(`Invalid variable: ${name}.`);
151
+ }
152
+ const content = this.resolveExpression(expression);
153
+ this.variableCache.set(name, content);
154
+ return content;
155
+ } // }}}
127
156
  splitPlaceholder(placeholder) {
128
157
  const matches = PLACEHOLDER_REGEX.exec(placeholder);
129
158
  if (!matches) {
130
- throw new TemplateError(`Invalid placeholder format: ${placeholder}. Expected format: #[[filename.property]]`);
159
+ throw new TemplateError(`Invalid expression format: ${placeholder}. Expected format: #[[filename.property]]`);
131
160
  }
132
161
  const [, filename, propertyPath] = matches;
133
162
  return [filename, propertyPath];
@@ -140,9 +169,12 @@ class TemplateEngine {
140
169
  }
141
170
  return now.format(format);
142
171
  }
143
- catch (_a) {
172
+ catch {
144
173
  throw new TemplateError(`Invalid date format: ${format}`);
145
174
  }
146
175
  } // }}}
147
176
  }
148
177
  exports.TemplateEngine = TemplateEngine;
178
+ function unescapeCode(code) {
179
+ return code.replace(/\\('|\\)/g, '$1').replace(/[\r\t\n]/g, ' ');
180
+ }
@@ -5,7 +5,7 @@ function tryJson(value) {
5
5
  try {
6
6
  return JSON.parse(value);
7
7
  }
8
- catch (_a) {
8
+ catch {
9
9
  return undefined;
10
10
  }
11
11
  }
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.4",
4
+ "version": "0.5.1",
5
5
  "author": {
6
6
  "name": "Baptiste Augrain",
7
7
  "email": "daiyam@zokugun.org"
@@ -27,14 +27,14 @@
27
27
  "release": "release-it",
28
28
  "test": "tsc -p test && mocha",
29
29
  "test:dev": "mocha",
30
- "test:watch": "tsc-watch -p src -p test --onSuccess 'mocha'",
30
+ "test:watch": "tsc-watch -p src -p test --onSuccess 'mocha -g=\"\"'",
31
31
  "watch:src": "tsc-watch -p src",
32
32
  "watch:test": "tsc-watch -p test"
33
33
  },
34
34
  "dependencies": {
35
+ "@zokugun/cli-utils": "^0.2.0",
35
36
  "@zokugun/configdotts-merge": "^0.2.0",
36
37
  "ansi-colors": "^4.1.1",
37
- "commander": "^9.0.0",
38
38
  "dayjs": "^1.11.13",
39
39
  "detect-indent": "^6.1.0",
40
40
  "editorconfig": "^0.15.3",
@@ -62,7 +62,7 @@
62
62
  "@types/lodash": "^4.14.172",
63
63
  "@types/micromatch": "^4.0.2",
64
64
  "@types/mocha": "^9.0.0",
65
- "@types/node": "^14.17.15",
65
+ "@types/node": "20.19.39",
66
66
  "@types/npm": "^7.19.0",
67
67
  "@types/pacote": "^11.1.1",
68
68
  "@types/semver": "^7.3.8",