@yorozu/build 0.1.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/LICENSE +21 -0
- package/README.md +38 -0
- package/chunks/21EFCjEU.js +19160 -0
- package/chunks/CMapqBQB.js +2620 -0
- package/chunks/CYSd7-PF.js +623 -0
- package/chunks/Cr5v7tI0.js +1824 -0
- package/ci/github-actions.d.ts +3 -0
- package/ci/index.d.ts +1 -0
- package/cli/commands/_utils.d.ts +8 -0
- package/cli/commands/build.d.ts +40 -0
- package/cli/commands/bump-version.d.ts +27 -0
- package/cli/commands/cr.d.ts +27 -0
- package/cli/commands/docs.d.ts +9 -0
- package/cli/commands/find-changed-packages.d.ts +10 -0
- package/cli/commands/gen-changelog.d.ts +10 -0
- package/cli/commands/gen-deps-graph.d.ts +15 -0
- package/cli/commands/jsr.d.ts +6 -0
- package/cli/commands/lint/config.d.ts +1 -0
- package/cli/commands/lint/index.d.ts +11 -0
- package/cli/commands/lint/validate-workspace-deps.d.ts +23 -0
- package/cli/commands/publish.d.ts +62 -0
- package/cli/commands/release.d.ts +45 -0
- package/cli/index.d.ts +8 -0
- package/cli/log.d.ts +3 -0
- package/cli/main.d.ts +2 -0
- package/config.d.ts +57 -0
- package/git/github.d.ts +15 -0
- package/git/index.d.ts +2 -0
- package/git/utils.d.ts +38 -0
- package/index.d.ts +8 -0
- package/index.js +26 -0
- package/jsr/_deno-directives.d.ts +1 -0
- package/jsr/config.d.ts +1 -0
- package/jsr/create-packages.d.ts +8 -0
- package/jsr/deno-json.d.ts +19 -0
- package/jsr/generate-workspace.d.ts +9 -0
- package/jsr/index.d.ts +6 -0
- package/jsr/populate.d.ts +10 -0
- package/jsr/utils/external-libs.d.ts +8 -0
- package/jsr/utils/index.d.ts +4 -0
- package/jsr/utils/jsr-api.d.ts +23 -0
- package/jsr/utils/jsr-json.d.ts +10 -0
- package/jsr/utils/jsr.d.ts +10 -0
- package/jsr.d.ts +1 -0
- package/jsr.js +2 -0
- package/misc/_config.d.ts +2 -0
- package/misc/exec.d.ts +15 -0
- package/misc/fs.d.ts +4 -0
- package/misc/index.d.ts +6 -0
- package/misc/path.d.ts +1 -0
- package/misc/publish-order.d.ts +3 -0
- package/misc/tsconfig.d.ts +2 -0
- package/npm/index.d.ts +1 -0
- package/npm/npm-api.d.ts +6 -0
- package/package-json/collect-package-jsons.d.ts +9 -0
- package/package-json/find-package-json.d.ts +1 -0
- package/package-json/index.d.ts +6 -0
- package/package-json/parse.d.ts +11 -0
- package/package-json/process-package-json.d.ts +20 -0
- package/package-json/types.d.ts +39 -0
- package/package-json/utils.d.ts +4 -0
- package/package.json +59 -0
- package/versioning/bump-version.d.ts +31 -0
- package/versioning/collect-files.d.ts +21 -0
- package/versioning/generate-changelog.d.ts +8 -0
- package/versioning/index.d.ts +4 -0
- package/versioning/types.d.ts +21 -0
- package/vite/build-plugin.d.ts +73 -0
- package/vite/config.d.ts +47 -0
- package/vite/index.d.ts +2 -0
- package/vite.d.ts +1 -0
- package/vite.js +184 -0
- package/yorozu-build.d.ts +1 -0
- package/yorozu-build.js +527 -0
|
@@ -0,0 +1,2620 @@
|
|
|
1
|
+
import { __toESM as __toESM$1, asNonNull, asyncPool, collectPackageJsons, error, fileExists, filterPackageJsonsForPublish, findPackageByName, findRootPackage, getWorkspaceRoot, info, loadBuildConfig, normalizeFilePath, number, object, parsePackageJsonFile, processPackageJson, require_picomatch, string as string$1, warn } from "./21EFCjEU.js";
|
|
2
|
+
import { exec, require_semver, sortWorkspaceByPublishOrder } from "./Cr5v7tI0.js";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
4
|
+
import { appendFileSync } from "node:fs";
|
|
5
|
+
import { EOL, tmpdir } from "node:os";
|
|
6
|
+
import process$1 from "node:process";
|
|
7
|
+
import { join, relative, resolve } from "node:path";
|
|
8
|
+
import * as fsp from "node:fs/promises";
|
|
9
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
10
|
+
import * as td from "typedoc";
|
|
11
|
+
//#region src/ci/github-actions.ts
|
|
12
|
+
function isRunningInGithubActions() {
|
|
13
|
+
return Boolean(process$1.env.GITHUB_ACTIONS);
|
|
14
|
+
}
|
|
15
|
+
function getGithubActionsInput(name) {
|
|
16
|
+
let input = process$1.env[`INPUT_${name.replace(/ /g, "_").toUpperCase()}`];
|
|
17
|
+
if (input === void 0) return void 0;
|
|
18
|
+
return input.trim();
|
|
19
|
+
}
|
|
20
|
+
function writeGithubActionsOutput(name, value) {
|
|
21
|
+
if (process$1.env.GITHUB_OUTPUT === void 0) throw new Error("GITHUB_OUTPUT is not set");
|
|
22
|
+
if (!value.includes(EOL)) {
|
|
23
|
+
appendFileSync(process$1.env.GITHUB_OUTPUT, `${name}=${value}${EOL}`, "utf8");
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
let delim = `---${randomUUID()}---`;
|
|
27
|
+
appendFileSync(process$1.env.GITHUB_OUTPUT, `${name}<<${delim}${EOL}${value}${EOL}${delim}${EOL}`, "utf8");
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region ../utils/src/structures/lru-map.ts
|
|
31
|
+
var LruMap = class {
|
|
32
|
+
#capacity;
|
|
33
|
+
#map;
|
|
34
|
+
constructor(capacity, MapImpl = Map) {
|
|
35
|
+
this.#capacity = capacity;
|
|
36
|
+
this.#map = new MapImpl();
|
|
37
|
+
}
|
|
38
|
+
get size() {
|
|
39
|
+
return this.#map.size;
|
|
40
|
+
}
|
|
41
|
+
get(key) {
|
|
42
|
+
if (!this.#map.has(key)) return void 0;
|
|
43
|
+
let value = this.#map.get(key);
|
|
44
|
+
this.#map.delete(key);
|
|
45
|
+
this.#map.set(key, value);
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
48
|
+
has(key) {
|
|
49
|
+
return this.#map.has(key);
|
|
50
|
+
}
|
|
51
|
+
set(key, value) {
|
|
52
|
+
if (this.#map.has(key)) this.#map.delete(key);
|
|
53
|
+
this.#map.set(key, value);
|
|
54
|
+
if (this.#map.size > this.#capacity) {
|
|
55
|
+
let oldest = this.#map.keys().next().value;
|
|
56
|
+
if (oldest !== void 0) this.#map.delete(oldest);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
delete(key) {
|
|
60
|
+
this.#map.delete(key);
|
|
61
|
+
}
|
|
62
|
+
clear() {
|
|
63
|
+
this.#map.clear();
|
|
64
|
+
}
|
|
65
|
+
*[Symbol.iterator]() {
|
|
66
|
+
yield* this.#map;
|
|
67
|
+
}
|
|
68
|
+
entries() {
|
|
69
|
+
return this.#map.entries();
|
|
70
|
+
}
|
|
71
|
+
keys() {
|
|
72
|
+
return this.#map.keys();
|
|
73
|
+
}
|
|
74
|
+
values() {
|
|
75
|
+
return this.#map.values();
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
//#endregion
|
|
79
|
+
//#region ../../node_modules/.pnpm/@drizzle-team+brocli@0.12.0/node_modules/@drizzle-team/brocli/index.js
|
|
80
|
+
var __create = Object.create;
|
|
81
|
+
var __defProp = Object.defineProperty;
|
|
82
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
83
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
84
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
85
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
86
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
87
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
88
|
+
};
|
|
89
|
+
var __copyProps = (to, from, except, desc) => {
|
|
90
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
91
|
+
for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
92
|
+
get: () => from[key],
|
|
93
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
return to;
|
|
97
|
+
};
|
|
98
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
99
|
+
value: mod,
|
|
100
|
+
enumerable: true
|
|
101
|
+
}) : target, mod));
|
|
102
|
+
var require_clone = __commonJS({ "node_modules/.pnpm/clone@2.1.2/node_modules/clone/clone.js"(exports, module) {
|
|
103
|
+
"use strict";
|
|
104
|
+
var clone2 = function() {
|
|
105
|
+
"use strict";
|
|
106
|
+
function _instanceof(obj, type) {
|
|
107
|
+
return type != null && obj instanceof type;
|
|
108
|
+
}
|
|
109
|
+
var nativeMap;
|
|
110
|
+
try {
|
|
111
|
+
nativeMap = Map;
|
|
112
|
+
} catch (_) {
|
|
113
|
+
nativeMap = function() {};
|
|
114
|
+
}
|
|
115
|
+
var nativeSet;
|
|
116
|
+
try {
|
|
117
|
+
nativeSet = Set;
|
|
118
|
+
} catch (_) {
|
|
119
|
+
nativeSet = function() {};
|
|
120
|
+
}
|
|
121
|
+
var nativePromise;
|
|
122
|
+
try {
|
|
123
|
+
nativePromise = Promise;
|
|
124
|
+
} catch (_) {
|
|
125
|
+
nativePromise = function() {};
|
|
126
|
+
}
|
|
127
|
+
function clone3(parent, circular, depth, prototype, includeNonEnumerable) {
|
|
128
|
+
if (typeof circular === "object") {
|
|
129
|
+
depth = circular.depth;
|
|
130
|
+
prototype = circular.prototype;
|
|
131
|
+
includeNonEnumerable = circular.includeNonEnumerable;
|
|
132
|
+
circular = circular.circular;
|
|
133
|
+
}
|
|
134
|
+
var allParents = [];
|
|
135
|
+
var allChildren = [];
|
|
136
|
+
var useBuffer = typeof Buffer != "undefined";
|
|
137
|
+
if (typeof circular == "undefined") circular = true;
|
|
138
|
+
if (typeof depth == "undefined") depth = Infinity;
|
|
139
|
+
function _clone(parent2, depth2) {
|
|
140
|
+
if (parent2 === null) return null;
|
|
141
|
+
if (depth2 === 0) return parent2;
|
|
142
|
+
var child;
|
|
143
|
+
var proto;
|
|
144
|
+
if (typeof parent2 != "object") return parent2;
|
|
145
|
+
if (_instanceof(parent2, nativeMap)) child = new nativeMap();
|
|
146
|
+
else if (_instanceof(parent2, nativeSet)) child = new nativeSet();
|
|
147
|
+
else if (_instanceof(parent2, nativePromise)) child = new nativePromise(function(resolve, reject) {
|
|
148
|
+
parent2.then(function(value) {
|
|
149
|
+
resolve(_clone(value, depth2 - 1));
|
|
150
|
+
}, function(err) {
|
|
151
|
+
reject(_clone(err, depth2 - 1));
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
else if (clone3.__isArray(parent2)) child = [];
|
|
155
|
+
else if (clone3.__isRegExp(parent2)) {
|
|
156
|
+
child = new RegExp(parent2.source, __getRegExpFlags(parent2));
|
|
157
|
+
if (parent2.lastIndex) child.lastIndex = parent2.lastIndex;
|
|
158
|
+
} else if (clone3.__isDate(parent2)) child = new Date(parent2.getTime());
|
|
159
|
+
else if (useBuffer && Buffer.isBuffer(parent2)) {
|
|
160
|
+
if (Buffer.allocUnsafe) child = Buffer.allocUnsafe(parent2.length);
|
|
161
|
+
else child = new Buffer(parent2.length);
|
|
162
|
+
parent2.copy(child);
|
|
163
|
+
return child;
|
|
164
|
+
} else if (_instanceof(parent2, Error)) child = Object.create(parent2);
|
|
165
|
+
else if (typeof prototype == "undefined") {
|
|
166
|
+
proto = Object.getPrototypeOf(parent2);
|
|
167
|
+
child = Object.create(proto);
|
|
168
|
+
} else {
|
|
169
|
+
child = Object.create(prototype);
|
|
170
|
+
proto = prototype;
|
|
171
|
+
}
|
|
172
|
+
if (circular) {
|
|
173
|
+
var index = allParents.indexOf(parent2);
|
|
174
|
+
if (index != -1) return allChildren[index];
|
|
175
|
+
allParents.push(parent2);
|
|
176
|
+
allChildren.push(child);
|
|
177
|
+
}
|
|
178
|
+
if (_instanceof(parent2, nativeMap)) parent2.forEach(function(value, key) {
|
|
179
|
+
var keyChild = _clone(key, depth2 - 1);
|
|
180
|
+
var valueChild = _clone(value, depth2 - 1);
|
|
181
|
+
child.set(keyChild, valueChild);
|
|
182
|
+
});
|
|
183
|
+
if (_instanceof(parent2, nativeSet)) parent2.forEach(function(value) {
|
|
184
|
+
var entryChild = _clone(value, depth2 - 1);
|
|
185
|
+
child.add(entryChild);
|
|
186
|
+
});
|
|
187
|
+
for (var i in parent2) {
|
|
188
|
+
var attrs;
|
|
189
|
+
if (proto) attrs = Object.getOwnPropertyDescriptor(proto, i);
|
|
190
|
+
if (attrs && attrs.set == null) continue;
|
|
191
|
+
child[i] = _clone(parent2[i], depth2 - 1);
|
|
192
|
+
}
|
|
193
|
+
if (Object.getOwnPropertySymbols) {
|
|
194
|
+
var symbols = Object.getOwnPropertySymbols(parent2);
|
|
195
|
+
for (var i = 0; i < symbols.length; i++) {
|
|
196
|
+
var symbol = symbols[i];
|
|
197
|
+
var descriptor = Object.getOwnPropertyDescriptor(parent2, symbol);
|
|
198
|
+
if (descriptor && !descriptor.enumerable && !includeNonEnumerable) continue;
|
|
199
|
+
child[symbol] = _clone(parent2[symbol], depth2 - 1);
|
|
200
|
+
if (!descriptor.enumerable) Object.defineProperty(child, symbol, { enumerable: false });
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
if (includeNonEnumerable) {
|
|
204
|
+
var allPropertyNames = Object.getOwnPropertyNames(parent2);
|
|
205
|
+
for (var i = 0; i < allPropertyNames.length; i++) {
|
|
206
|
+
var propertyName = allPropertyNames[i];
|
|
207
|
+
var descriptor = Object.getOwnPropertyDescriptor(parent2, propertyName);
|
|
208
|
+
if (descriptor && descriptor.enumerable) continue;
|
|
209
|
+
child[propertyName] = _clone(parent2[propertyName], depth2 - 1);
|
|
210
|
+
Object.defineProperty(child, propertyName, { enumerable: false });
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return child;
|
|
214
|
+
}
|
|
215
|
+
return _clone(parent, depth);
|
|
216
|
+
}
|
|
217
|
+
clone3.clonePrototype = function clonePrototype(parent) {
|
|
218
|
+
if (parent === null) return null;
|
|
219
|
+
var c = function() {};
|
|
220
|
+
c.prototype = parent;
|
|
221
|
+
return new c();
|
|
222
|
+
};
|
|
223
|
+
function __objToStr(o) {
|
|
224
|
+
return Object.prototype.toString.call(o);
|
|
225
|
+
}
|
|
226
|
+
clone3.__objToStr = __objToStr;
|
|
227
|
+
function __isDate(o) {
|
|
228
|
+
return typeof o === "object" && __objToStr(o) === "[object Date]";
|
|
229
|
+
}
|
|
230
|
+
clone3.__isDate = __isDate;
|
|
231
|
+
function __isArray(o) {
|
|
232
|
+
return typeof o === "object" && __objToStr(o) === "[object Array]";
|
|
233
|
+
}
|
|
234
|
+
clone3.__isArray = __isArray;
|
|
235
|
+
function __isRegExp(o) {
|
|
236
|
+
return typeof o === "object" && __objToStr(o) === "[object RegExp]";
|
|
237
|
+
}
|
|
238
|
+
clone3.__isRegExp = __isRegExp;
|
|
239
|
+
function __getRegExpFlags(re) {
|
|
240
|
+
var flags = "";
|
|
241
|
+
if (re.global) flags += "g";
|
|
242
|
+
if (re.ignoreCase) flags += "i";
|
|
243
|
+
if (re.multiline) flags += "m";
|
|
244
|
+
return flags;
|
|
245
|
+
}
|
|
246
|
+
clone3.__getRegExpFlags = __getRegExpFlags;
|
|
247
|
+
return clone3;
|
|
248
|
+
}();
|
|
249
|
+
if (typeof module === "object" && module.exports) module.exports = clone2;
|
|
250
|
+
} });
|
|
251
|
+
var require_quote = __commonJS({ "node_modules/.pnpm/shell-quote@1.8.1/node_modules/shell-quote/quote.js"(exports, module) {
|
|
252
|
+
"use strict";
|
|
253
|
+
module.exports = function quote(xs) {
|
|
254
|
+
return xs.map(function(s) {
|
|
255
|
+
if (s && typeof s === "object") return s.op.replace(/(.)/g, "\\$1");
|
|
256
|
+
if (/["\s]/.test(s) && !/'/.test(s)) return "'" + s.replace(/(['\\])/g, "\\$1") + "'";
|
|
257
|
+
if (/["'\s]/.test(s)) return "\"" + s.replace(/(["\\$`!])/g, "\\$1") + "\"";
|
|
258
|
+
return String(s).replace(/([A-Za-z]:)?([#!"$&'()*,:;<=>?@[\\\]^`{|}])/g, "$1\\$2");
|
|
259
|
+
}).join(" ");
|
|
260
|
+
};
|
|
261
|
+
} });
|
|
262
|
+
var require_parse = __commonJS({ "node_modules/.pnpm/shell-quote@1.8.1/node_modules/shell-quote/parse.js"(exports, module) {
|
|
263
|
+
"use strict";
|
|
264
|
+
var CONTROL = "(?:" + [
|
|
265
|
+
"\\|\\|",
|
|
266
|
+
"\\&\\&",
|
|
267
|
+
";;",
|
|
268
|
+
"\\|\\&",
|
|
269
|
+
"\\<\\(",
|
|
270
|
+
"\\<\\<\\<",
|
|
271
|
+
">>",
|
|
272
|
+
">\\&",
|
|
273
|
+
"<\\&",
|
|
274
|
+
"[&;()|<>]"
|
|
275
|
+
].join("|") + ")";
|
|
276
|
+
var controlRE = new RegExp("^" + CONTROL + "$");
|
|
277
|
+
var META = "|&;()<> \\t";
|
|
278
|
+
var SINGLE_QUOTE = "\"((\\\\\"|[^\"])*?)\"";
|
|
279
|
+
var DOUBLE_QUOTE = "'((\\\\'|[^'])*?)'";
|
|
280
|
+
var hash = /^#$/;
|
|
281
|
+
var SQ = "'";
|
|
282
|
+
var DQ = "\"";
|
|
283
|
+
var DS = "$";
|
|
284
|
+
var TOKEN = "";
|
|
285
|
+
var mult = 4294967296;
|
|
286
|
+
for (i = 0; i < 4; i++) TOKEN += (mult * Math.random()).toString(16);
|
|
287
|
+
var i;
|
|
288
|
+
var startsWithToken = new RegExp("^" + TOKEN);
|
|
289
|
+
function matchAll(s, r) {
|
|
290
|
+
var origIndex = r.lastIndex;
|
|
291
|
+
var matches = [];
|
|
292
|
+
var matchObj;
|
|
293
|
+
while (matchObj = r.exec(s)) {
|
|
294
|
+
matches.push(matchObj);
|
|
295
|
+
if (r.lastIndex === matchObj.index) r.lastIndex += 1;
|
|
296
|
+
}
|
|
297
|
+
r.lastIndex = origIndex;
|
|
298
|
+
return matches;
|
|
299
|
+
}
|
|
300
|
+
function getVar(env, pre, key) {
|
|
301
|
+
var r = typeof env === "function" ? env(key) : env[key];
|
|
302
|
+
if (typeof r === "undefined" && key != "") r = "";
|
|
303
|
+
else if (typeof r === "undefined") r = "$";
|
|
304
|
+
if (typeof r === "object") return pre + TOKEN + JSON.stringify(r) + TOKEN;
|
|
305
|
+
return pre + r;
|
|
306
|
+
}
|
|
307
|
+
function parseInternal(string2, env, opts) {
|
|
308
|
+
if (!opts) opts = {};
|
|
309
|
+
var BS = opts.escape || "\\";
|
|
310
|
+
var BAREWORD = "(\\" + BS + `['"` + META + `]|[^\\s'"` + META + "])+";
|
|
311
|
+
var matches = matchAll(string2, new RegExp(["(" + CONTROL + ")", "(" + BAREWORD + "|" + SINGLE_QUOTE + "|" + DOUBLE_QUOTE + ")+"].join("|"), "g"));
|
|
312
|
+
if (matches.length === 0) return [];
|
|
313
|
+
if (!env) env = {};
|
|
314
|
+
var commented = false;
|
|
315
|
+
return matches.map(function(match) {
|
|
316
|
+
var s = match[0];
|
|
317
|
+
if (!s || commented) return;
|
|
318
|
+
if (controlRE.test(s)) return { op: s };
|
|
319
|
+
var quote = false;
|
|
320
|
+
var esc = false;
|
|
321
|
+
var out = "";
|
|
322
|
+
var isGlob = false;
|
|
323
|
+
var i2;
|
|
324
|
+
function parseEnvVar() {
|
|
325
|
+
i2 += 1;
|
|
326
|
+
var varend;
|
|
327
|
+
var varname;
|
|
328
|
+
var char = s.charAt(i2);
|
|
329
|
+
if (char === "{") {
|
|
330
|
+
i2 += 1;
|
|
331
|
+
if (s.charAt(i2) === "}") throw new Error("Bad substitution: " + s.slice(i2 - 2, i2 + 1));
|
|
332
|
+
varend = s.indexOf("}", i2);
|
|
333
|
+
if (varend < 0) throw new Error("Bad substitution: " + s.slice(i2));
|
|
334
|
+
varname = s.slice(i2, varend);
|
|
335
|
+
i2 = varend;
|
|
336
|
+
} else if (/[*@#?$!_-]/.test(char)) {
|
|
337
|
+
varname = char;
|
|
338
|
+
i2 += 1;
|
|
339
|
+
} else {
|
|
340
|
+
var slicedFromI = s.slice(i2);
|
|
341
|
+
varend = slicedFromI.match(/[^\w\d_]/);
|
|
342
|
+
if (!varend) {
|
|
343
|
+
varname = slicedFromI;
|
|
344
|
+
i2 = s.length;
|
|
345
|
+
} else {
|
|
346
|
+
varname = slicedFromI.slice(0, varend.index);
|
|
347
|
+
i2 += varend.index - 1;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return getVar(env, "", varname);
|
|
351
|
+
}
|
|
352
|
+
for (i2 = 0; i2 < s.length; i2++) {
|
|
353
|
+
var c = s.charAt(i2);
|
|
354
|
+
isGlob = isGlob || !quote && (c === "*" || c === "?");
|
|
355
|
+
if (esc) {
|
|
356
|
+
out += c;
|
|
357
|
+
esc = false;
|
|
358
|
+
} else if (quote) if (c === quote) quote = false;
|
|
359
|
+
else if (quote == SQ) out += c;
|
|
360
|
+
else if (c === BS) {
|
|
361
|
+
i2 += 1;
|
|
362
|
+
c = s.charAt(i2);
|
|
363
|
+
if (c === DQ || c === BS || c === DS) out += c;
|
|
364
|
+
else out += BS + c;
|
|
365
|
+
} else if (c === DS) out += parseEnvVar();
|
|
366
|
+
else out += c;
|
|
367
|
+
else if (c === DQ || c === SQ) quote = c;
|
|
368
|
+
else if (controlRE.test(c)) return { op: s };
|
|
369
|
+
else if (hash.test(c)) {
|
|
370
|
+
commented = true;
|
|
371
|
+
var commentObj = { comment: string2.slice(match.index + i2 + 1) };
|
|
372
|
+
if (out.length) return [out, commentObj];
|
|
373
|
+
return [commentObj];
|
|
374
|
+
} else if (c === BS) esc = true;
|
|
375
|
+
else if (c === DS) out += parseEnvVar();
|
|
376
|
+
else out += c;
|
|
377
|
+
}
|
|
378
|
+
if (isGlob) return {
|
|
379
|
+
op: "glob",
|
|
380
|
+
pattern: out
|
|
381
|
+
};
|
|
382
|
+
return out;
|
|
383
|
+
}).reduce(function(prev, arg) {
|
|
384
|
+
return typeof arg === "undefined" ? prev : prev.concat(arg);
|
|
385
|
+
}, []);
|
|
386
|
+
}
|
|
387
|
+
module.exports = function parse(s, env, opts) {
|
|
388
|
+
var mapped = parseInternal(s, env, opts);
|
|
389
|
+
if (typeof env !== "function") return mapped;
|
|
390
|
+
return mapped.reduce(function(acc, s2) {
|
|
391
|
+
if (typeof s2 === "object") return acc.concat(s2);
|
|
392
|
+
var xs = s2.split(RegExp("(" + TOKEN + ".*?" + TOKEN + ")", "g"));
|
|
393
|
+
if (xs.length === 1) return acc.concat(xs[0]);
|
|
394
|
+
return acc.concat(xs.filter(Boolean).map(function(x) {
|
|
395
|
+
if (startsWithToken.test(x)) return JSON.parse(x.split(TOKEN)[1]);
|
|
396
|
+
return x;
|
|
397
|
+
}));
|
|
398
|
+
}, []);
|
|
399
|
+
};
|
|
400
|
+
} });
|
|
401
|
+
var require_shell_quote = __commonJS({ "node_modules/.pnpm/shell-quote@1.8.1/node_modules/shell-quote/index.js"(exports) {
|
|
402
|
+
"use strict";
|
|
403
|
+
exports.quote = require_quote();
|
|
404
|
+
exports.parse = require_parse();
|
|
405
|
+
} });
|
|
406
|
+
var BroCliError = class extends Error {
|
|
407
|
+
constructor(message, event) {
|
|
408
|
+
super(message === void 0 ? message : `BroCli error: ${message}`);
|
|
409
|
+
this.event = event;
|
|
410
|
+
}
|
|
411
|
+
};
|
|
412
|
+
var import_clone = __toESM(require_clone(), 1);
|
|
413
|
+
var getOptionTypeText = (option) => {
|
|
414
|
+
let result = "";
|
|
415
|
+
switch (option.type) {
|
|
416
|
+
case "boolean":
|
|
417
|
+
result = "";
|
|
418
|
+
break;
|
|
419
|
+
case "number":
|
|
420
|
+
if ((option.minVal ?? option.maxVal) !== void 0) {
|
|
421
|
+
let text = "";
|
|
422
|
+
if (option.isInt) text = text + `integer `;
|
|
423
|
+
if (option.minVal !== void 0) text = text + `[${option.minVal};`;
|
|
424
|
+
else text = text + `(\u221E;`;
|
|
425
|
+
if (option.maxVal !== void 0) text = text + `${option.maxVal}]`;
|
|
426
|
+
else text = text + `\u221E)`;
|
|
427
|
+
result = text;
|
|
428
|
+
break;
|
|
429
|
+
}
|
|
430
|
+
if (option.isInt) {
|
|
431
|
+
result = "integer";
|
|
432
|
+
break;
|
|
433
|
+
}
|
|
434
|
+
result = "number";
|
|
435
|
+
break;
|
|
436
|
+
case "string":
|
|
437
|
+
if (option.enumVals) {
|
|
438
|
+
result = "[ " + option.enumVals.join(" | ") + " ]";
|
|
439
|
+
break;
|
|
440
|
+
}
|
|
441
|
+
result = "string";
|
|
442
|
+
break;
|
|
443
|
+
case "positional":
|
|
444
|
+
result = `${option.isRequired ? "<" : "["}${option.enumVals ? option.enumVals.join("|") : option.name}${option.isRequired ? ">" : "]"}`;
|
|
445
|
+
break;
|
|
446
|
+
}
|
|
447
|
+
if (option.isRequired && option.type !== "positional") result = "!" + (result.length ? "" + result : " ");
|
|
448
|
+
return result;
|
|
449
|
+
};
|
|
450
|
+
var defaultEventHandler = async (event) => {
|
|
451
|
+
switch (event.type) {
|
|
452
|
+
case "command_help": {
|
|
453
|
+
const command2 = event.command;
|
|
454
|
+
const commandName = getCommandNameWithParents(command2);
|
|
455
|
+
const cliName = event.name;
|
|
456
|
+
const desc = command2.desc ?? command2.shortDesc;
|
|
457
|
+
const subs = command2.subcommands?.filter((s) => !s.hidden);
|
|
458
|
+
const subcommands = subs && subs.length ? subs : void 0;
|
|
459
|
+
const defaultGlobals = [{
|
|
460
|
+
config: {
|
|
461
|
+
name: "--help",
|
|
462
|
+
aliases: ["-h"],
|
|
463
|
+
type: "boolean",
|
|
464
|
+
description: `help for ${commandName}`,
|
|
465
|
+
default: void 0
|
|
466
|
+
},
|
|
467
|
+
$output: void 0
|
|
468
|
+
}, {
|
|
469
|
+
config: {
|
|
470
|
+
name: "--version",
|
|
471
|
+
aliases: ["-v"],
|
|
472
|
+
type: "boolean",
|
|
473
|
+
description: `version${cliName ? ` for ${cliName}` : ""}`,
|
|
474
|
+
default: void 0
|
|
475
|
+
},
|
|
476
|
+
$output: void 0
|
|
477
|
+
}];
|
|
478
|
+
const globals = event.globals ? [...Object.values(event.globals), ...defaultGlobals] : defaultGlobals;
|
|
479
|
+
if (desc !== void 0) console.log(`
|
|
480
|
+
${desc}`);
|
|
481
|
+
const opts = Object.values(command2.options ?? {}).filter((opt) => !opt.config.isHidden);
|
|
482
|
+
const positionals = opts.filter((opt) => opt.config.type === "positional");
|
|
483
|
+
const options = [...opts.filter((opt) => opt.config.type !== "positional"), ...globals];
|
|
484
|
+
console.log("\nUsage:");
|
|
485
|
+
if (command2.handler) console.log(` ${cliName ? cliName + " " : ""}${commandName}${positionals.length ? " " + positionals.map(({ config: p }) => getOptionTypeText(p)).join(" ") : ""} [flags]`);
|
|
486
|
+
else console.log(` ${cliName ? cliName + " " : ""}${commandName} [command]`);
|
|
487
|
+
if (command2.aliases) {
|
|
488
|
+
console.log(`
|
|
489
|
+
Aliases:`);
|
|
490
|
+
console.log(` ${[command2.name, ...command2.aliases].join(", ")}`);
|
|
491
|
+
}
|
|
492
|
+
if (subcommands) {
|
|
493
|
+
console.log("\nAvailable Commands:");
|
|
494
|
+
const paddedLength = subcommands.reduce((p, e) => e.name.length > p ? e.name.length : p, 0) + 3;
|
|
495
|
+
const preDescPad = 2 + paddedLength;
|
|
496
|
+
const data = subcommands.map((s) => ` ${s.name.padEnd(paddedLength)}${(() => {
|
|
497
|
+
const description = s.shortDesc ?? s.desc;
|
|
498
|
+
if (!description?.length) return "";
|
|
499
|
+
const split = description.split("\n");
|
|
500
|
+
return [split.shift(), ...split.map((s2) => "".padEnd(preDescPad) + s2)].join("\n");
|
|
501
|
+
})()}`).join("\n");
|
|
502
|
+
console.log(data);
|
|
503
|
+
}
|
|
504
|
+
if (options.length) {
|
|
505
|
+
const aliasLength = options.reduce((p, e) => {
|
|
506
|
+
const currentLength = e.config.aliases.reduce((pa, a) => pa + a.length, 0) + (e.config.aliases.length - 1) * 2 + 1;
|
|
507
|
+
return currentLength > p ? currentLength : p;
|
|
508
|
+
}, 0);
|
|
509
|
+
const paddedAliasLength = aliasLength > 0 ? aliasLength + 1 : 0;
|
|
510
|
+
const nameLength = options.reduce((p, e) => {
|
|
511
|
+
const typeLen = getOptionTypeText(e.config).length;
|
|
512
|
+
const length = typeLen > 0 ? e.config.name.length + 1 + typeLen : e.config.name.length;
|
|
513
|
+
return length > p ? length : p;
|
|
514
|
+
}, 0) + 3;
|
|
515
|
+
const preDescPad = paddedAliasLength + nameLength + 2;
|
|
516
|
+
const data = options.map(({ config: opt }) => ` ${`${opt.aliases.length ? opt.aliases.join(", ") + "," : ""}`.padEnd(paddedAliasLength)}${`${opt.name}${(() => {
|
|
517
|
+
const typeText = getOptionTypeText(opt);
|
|
518
|
+
return typeText.length ? " " + typeText : "";
|
|
519
|
+
})()}`.padEnd(nameLength)}${(() => {
|
|
520
|
+
if (!opt.description?.length) return opt.default !== void 0 ? `default: ${JSON.stringify(opt.default)}` : "";
|
|
521
|
+
const split = opt.description.split("\n");
|
|
522
|
+
const first = split.shift();
|
|
523
|
+
const def = opt.default !== void 0 ? ` (default: ${JSON.stringify(opt.default)})` : "";
|
|
524
|
+
return [first, ...split.map((s) => "".padEnd(preDescPad) + s)].join("\n") + def;
|
|
525
|
+
})()}`).join("\n");
|
|
526
|
+
console.log("\nFlags:");
|
|
527
|
+
console.log(data);
|
|
528
|
+
}
|
|
529
|
+
if (subcommands) console.log(`
|
|
530
|
+
Use "${cliName ? cliName + " " : ""}${commandName} [command] --help" for more information about a command.
|
|
531
|
+
`);
|
|
532
|
+
return true;
|
|
533
|
+
}
|
|
534
|
+
case "global_help": {
|
|
535
|
+
const cliName = event.name;
|
|
536
|
+
const desc = event.description;
|
|
537
|
+
const commands = event.commands.filter((c) => !c.hidden);
|
|
538
|
+
const defaultGlobals = [{
|
|
539
|
+
config: {
|
|
540
|
+
name: "--help",
|
|
541
|
+
aliases: ["-h"],
|
|
542
|
+
type: "boolean",
|
|
543
|
+
description: `help${cliName ? ` for ${cliName}` : ""}`,
|
|
544
|
+
default: void 0
|
|
545
|
+
},
|
|
546
|
+
$output: void 0
|
|
547
|
+
}, {
|
|
548
|
+
config: {
|
|
549
|
+
name: "--version",
|
|
550
|
+
aliases: ["-v"],
|
|
551
|
+
type: "boolean",
|
|
552
|
+
description: `version${cliName ? ` for ${cliName}` : ""}`,
|
|
553
|
+
default: void 0
|
|
554
|
+
},
|
|
555
|
+
$output: void 0
|
|
556
|
+
}];
|
|
557
|
+
const globals = event.globals ? [...defaultGlobals, ...Object.values(event.globals)] : defaultGlobals;
|
|
558
|
+
if (desc !== void 0) console.log(`${desc}
|
|
559
|
+
`);
|
|
560
|
+
console.log("Usage:");
|
|
561
|
+
console.log(` ${cliName ? cliName + " " : ""}[command]`);
|
|
562
|
+
if (commands.length) {
|
|
563
|
+
console.log("\nAvailable Commands:");
|
|
564
|
+
const paddedLength = commands.reduce((p, e) => e.name.length > p ? e.name.length : p, 0) + 3;
|
|
565
|
+
const data = commands.map((c) => ` ${c.name.padEnd(paddedLength)}${(() => {
|
|
566
|
+
const desc2 = c.shortDesc ?? c.desc;
|
|
567
|
+
if (!desc2?.length) return "";
|
|
568
|
+
const split = desc2.split("\n");
|
|
569
|
+
return [split.shift(), ...split.map((s) => "".padEnd(paddedLength + 2) + s)].join("\n");
|
|
570
|
+
})()}`).join("\n");
|
|
571
|
+
console.log(data);
|
|
572
|
+
} else console.log("\nNo available commands.");
|
|
573
|
+
const aliasLength = globals.reduce((p, e) => {
|
|
574
|
+
const currentLength = e.config.aliases.reduce((pa, a) => pa + a.length, 0) + (e.config.aliases.length - 1) * 2 + 1;
|
|
575
|
+
return currentLength > p ? currentLength : p;
|
|
576
|
+
}, 0);
|
|
577
|
+
const paddedAliasLength = aliasLength > 0 ? aliasLength + 1 : 0;
|
|
578
|
+
const nameLength = globals.reduce((p, e) => {
|
|
579
|
+
const typeLen = getOptionTypeText(e.config).length;
|
|
580
|
+
const length = typeLen > 0 ? e.config.name.length + 1 + typeLen : e.config.name.length;
|
|
581
|
+
return length > p ? length : p;
|
|
582
|
+
}, 0) + 3;
|
|
583
|
+
const preDescPad = paddedAliasLength + nameLength + 2;
|
|
584
|
+
const gData = globals.map(({ config: opt }) => ` ${`${opt.aliases.length ? opt.aliases.join(", ") + "," : ""}`.padEnd(paddedAliasLength)}${`${opt.name}${(() => {
|
|
585
|
+
const typeText = getOptionTypeText(opt);
|
|
586
|
+
return typeText.length ? " " + typeText : "";
|
|
587
|
+
})()}`.padEnd(nameLength)}${(() => {
|
|
588
|
+
if (!opt.description?.length) return opt.default !== void 0 ? `default: ${JSON.stringify(opt.default)}` : "";
|
|
589
|
+
const split = opt.description.split("\n");
|
|
590
|
+
const first = split.shift();
|
|
591
|
+
const def = opt.default !== void 0 ? ` (default: ${JSON.stringify(opt.default)})` : "";
|
|
592
|
+
return [first, ...split.map((s) => "".padEnd(preDescPad) + s)].join("\n") + def;
|
|
593
|
+
})()}`).join("\n");
|
|
594
|
+
console.log("\nFlags:");
|
|
595
|
+
console.log(gData);
|
|
596
|
+
return true;
|
|
597
|
+
}
|
|
598
|
+
case "version": return true;
|
|
599
|
+
case "error": {
|
|
600
|
+
let msg;
|
|
601
|
+
switch (event.violation) {
|
|
602
|
+
case "above_max": {
|
|
603
|
+
const matchedName = event.offender.namePart;
|
|
604
|
+
const data = event.offender.dataPart;
|
|
605
|
+
msg = `Invalid value: number type argument '${matchedName}' expects maximal value of ${event.option.maxVal} as an input, got: ${data}`;
|
|
606
|
+
break;
|
|
607
|
+
}
|
|
608
|
+
case "below_min": {
|
|
609
|
+
const matchedName = event.offender.namePart;
|
|
610
|
+
const data = event.offender.dataPart;
|
|
611
|
+
msg = `Invalid value: number type argument '${matchedName}' expects minimal value of ${event.option.minVal} as an input, got: ${data}`;
|
|
612
|
+
break;
|
|
613
|
+
}
|
|
614
|
+
case "expected_int":
|
|
615
|
+
msg = `Invalid value: number type argument '${event.offender.namePart}' expects an integer as an input, got: ${event.offender.dataPart}`;
|
|
616
|
+
break;
|
|
617
|
+
case "invalid_boolean_syntax": {
|
|
618
|
+
const matchedName = event.offender.namePart;
|
|
619
|
+
event.offender.dataPart;
|
|
620
|
+
msg = `Invalid syntax: boolean type argument '${matchedName}' must have it's value passed in the following formats: ${matchedName}=<value> | ${matchedName} <value> | ${matchedName}.
|
|
621
|
+
Allowed values: true, false, 0, 1`;
|
|
622
|
+
break;
|
|
623
|
+
}
|
|
624
|
+
case "invalid_string_syntax": {
|
|
625
|
+
const matchedName = event.offender.namePart;
|
|
626
|
+
msg = `Invalid syntax: string type argument '${matchedName}' must have it's value passed in the following formats: ${matchedName}=<value> | ${matchedName} <value>`;
|
|
627
|
+
break;
|
|
628
|
+
}
|
|
629
|
+
case "invalid_number_syntax": {
|
|
630
|
+
const matchedName = event.offender.namePart;
|
|
631
|
+
msg = `Invalid syntax: number type argument '${matchedName}' must have it's value passed in the following formats: ${matchedName}=<value> | ${matchedName} <value>`;
|
|
632
|
+
break;
|
|
633
|
+
}
|
|
634
|
+
case "invalid_number_value":
|
|
635
|
+
msg = `Invalid value: number type argument '${event.offender.namePart}' expects a number as an input, got: ${event.offender.dataPart}`;
|
|
636
|
+
break;
|
|
637
|
+
case "enum_violation": {
|
|
638
|
+
const matchedName = event.offender.namePart;
|
|
639
|
+
const data = event.offender.dataPart;
|
|
640
|
+
const option = event.option;
|
|
641
|
+
const values = option.enumVals;
|
|
642
|
+
msg = option.type === "positional" ? `Invalid value: value for the positional argument '${option.name}' must be either one of the following: ${values.join(", ")}; Received: ${data}` : `Invalid value: value for the argument '${matchedName}' must be either one of the following: ${values.join(", ")}; Received: ${data}`;
|
|
643
|
+
break;
|
|
644
|
+
}
|
|
645
|
+
case "unknown_command_error": {
|
|
646
|
+
const msg2 = `Unknown command: '${event.offender}'.
|
|
647
|
+
Type '--help' to get help on the cli.`;
|
|
648
|
+
console.error(msg2);
|
|
649
|
+
return true;
|
|
650
|
+
}
|
|
651
|
+
case "unknown_subcommand_error": {
|
|
652
|
+
const cName = getCommandNameWithParents(event.command);
|
|
653
|
+
const msg2 = `Unknown command: ${cName} ${event.offender}.
|
|
654
|
+
Type '${cName} --help' to get the help on command.`;
|
|
655
|
+
console.error(msg2);
|
|
656
|
+
return true;
|
|
657
|
+
}
|
|
658
|
+
case "missing_args_error": {
|
|
659
|
+
const { missing: missingOpts, command: command2 } = event;
|
|
660
|
+
msg = command2 === "globals" ? `Missing` : `Command '${command2.name}' is missing following required options: ${missingOpts.map((opt) => {
|
|
661
|
+
const name = opt.shift();
|
|
662
|
+
const aliases = opt;
|
|
663
|
+
if (aliases.length) return `${name} [${aliases.join(", ")}]`;
|
|
664
|
+
return name;
|
|
665
|
+
}).join(", ")}`;
|
|
666
|
+
break;
|
|
667
|
+
}
|
|
668
|
+
case "unrecognized_args_error": {
|
|
669
|
+
const { command: command2, unrecognized } = event;
|
|
670
|
+
msg = `Unrecognized options for command '${command2.name}': ${unrecognized.join(", ")}`;
|
|
671
|
+
break;
|
|
672
|
+
}
|
|
673
|
+
case "unknown_error": {
|
|
674
|
+
const e = event.error;
|
|
675
|
+
console.error(typeof e === "object" && e !== null && "message" in e ? e.message : e);
|
|
676
|
+
return true;
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
console.error(msg);
|
|
680
|
+
return true;
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
return false;
|
|
684
|
+
};
|
|
685
|
+
var eventHandlerWrapper = (customEventHandler) => async (event, options) => await customEventHandler(event, options) ? true : await defaultEventHandler(event, options);
|
|
686
|
+
__toESM(require_shell_quote(), 1);
|
|
687
|
+
function isInt(value) {
|
|
688
|
+
return value === Math.floor(value);
|
|
689
|
+
}
|
|
690
|
+
var executeOrLog = async (target, arg) => typeof target === "string" ? console.log(target) : target ? await target(arg) : void 0;
|
|
691
|
+
var generatePrefix = (name) => name.startsWith("-") ? name : name.length > 1 ? `--${name}` : `-${name}`;
|
|
692
|
+
var validateOptions = (config) => {
|
|
693
|
+
const cloned = (0, import_clone.default)(config);
|
|
694
|
+
const entries = [];
|
|
695
|
+
const storedNames = [];
|
|
696
|
+
const cfgEntries = Object.entries(cloned);
|
|
697
|
+
for (const [key, value] of cfgEntries) {
|
|
698
|
+
const cfg = value._.config;
|
|
699
|
+
if (cfg.name === void 0) cfg.name = key;
|
|
700
|
+
if (cfg.type === "positional") continue;
|
|
701
|
+
if (cfg.name.includes("=")) throw new BroCliError(`Can't define option '${generatePrefix(cfg.name)}' - option names and aliases cannot contain '='!`);
|
|
702
|
+
for (const alias of cfg.aliases) if (alias.includes("=")) throw new BroCliError(`Can't define option '${generatePrefix(cfg.name)}' - option names and aliases cannot contain '='!`);
|
|
703
|
+
cfg.name = generatePrefix(cfg.name);
|
|
704
|
+
cfg.aliases = cfg.aliases.map((a) => generatePrefix(a));
|
|
705
|
+
}
|
|
706
|
+
for (const [key, value] of cfgEntries) {
|
|
707
|
+
const cfg = value._.config;
|
|
708
|
+
if (cfg.type === "positional") {
|
|
709
|
+
entries.push([key, {
|
|
710
|
+
config: cfg,
|
|
711
|
+
$output: void 0
|
|
712
|
+
}]);
|
|
713
|
+
continue;
|
|
714
|
+
}
|
|
715
|
+
const reservedNames = [
|
|
716
|
+
"--help",
|
|
717
|
+
"-h",
|
|
718
|
+
"--version",
|
|
719
|
+
"-v"
|
|
720
|
+
];
|
|
721
|
+
const allNames = [cfg.name, ...cfg.aliases];
|
|
722
|
+
for (const name of allNames) {
|
|
723
|
+
const match = reservedNames.find((n) => n === name);
|
|
724
|
+
if (match) throw new BroCliError(`Can't define option '${cfg.name}' - name '${match}' is reserved!`);
|
|
725
|
+
}
|
|
726
|
+
for (const storage of storedNames) {
|
|
727
|
+
if (!storage.find((e) => e === cfg.name)) continue;
|
|
728
|
+
throw new BroCliError(`Can't define option '${cfg.name}' - name is already in use by option '${storage[0]}'!`);
|
|
729
|
+
}
|
|
730
|
+
for (const alias of cfg.aliases) for (const storage of storedNames) {
|
|
731
|
+
if (!storage.find((e) => e === alias)) continue;
|
|
732
|
+
throw new BroCliError(`Can't define option '${cfg.name}' - alias '${alias}' is already in use by option '${storage[0]}'!`);
|
|
733
|
+
}
|
|
734
|
+
const currentNames = [cfg.name, ...cfg.aliases];
|
|
735
|
+
storedNames.push(currentNames);
|
|
736
|
+
currentNames.forEach((name, idx) => {
|
|
737
|
+
if (currentNames.findIndex((e) => e === name) === idx) return;
|
|
738
|
+
throw new BroCliError(`Can't define option '${cfg.name}' - duplicate alias '${name}'!`);
|
|
739
|
+
});
|
|
740
|
+
entries.push([key, {
|
|
741
|
+
config: cfg,
|
|
742
|
+
$output: void 0
|
|
743
|
+
}]);
|
|
744
|
+
}
|
|
745
|
+
return Object.fromEntries(entries);
|
|
746
|
+
};
|
|
747
|
+
var assignParent = (parent, subcommands) => subcommands.forEach((e) => {
|
|
748
|
+
e.parent = parent;
|
|
749
|
+
if (e.subcommands) assignParent(e, e.subcommands);
|
|
750
|
+
});
|
|
751
|
+
var command = (command2) => {
|
|
752
|
+
const allNames = command2.aliases ? [command2.name, ...command2.aliases] : [command2.name];
|
|
753
|
+
const cmd = (0, import_clone.default)(command2);
|
|
754
|
+
if (command2.subcommands && command2.options && Object.values(command2.options).find((opt) => opt._.config.type === "positional")) throw new BroCliError(`Can't define command '${cmd.name}' - command can't have subcommands and positional args at the same time!`);
|
|
755
|
+
if (!command2.handler && !command2.subcommands) throw new BroCliError(`Can't define command '${cmd.name}' - command without subcommands must have a handler present!`);
|
|
756
|
+
cmd.options = command2.options ? validateOptions(command2.options) : void 0;
|
|
757
|
+
cmd.name = cmd.name ?? cmd.aliases?.shift();
|
|
758
|
+
if (!cmd.name) throw new BroCliError(`Can't define command without name!`);
|
|
759
|
+
cmd.aliases = cmd.aliases?.length ? cmd.aliases : void 0;
|
|
760
|
+
if (cmd.name.startsWith("-")) throw new BroCliError(`Can't define command '${cmd.name}' - command name can't start with '-'!`);
|
|
761
|
+
cmd.aliases?.forEach((a) => {
|
|
762
|
+
if (a.startsWith("-")) throw new BroCliError(`Can't define command '${cmd.name}' - command aliases can't start with '-'!`);
|
|
763
|
+
});
|
|
764
|
+
allNames.forEach((n, i) => {
|
|
765
|
+
if (n === "help") throw new BroCliError(`Can't define command '${cmd.name}' - 'help' is a reserved name. If you want to redefine help message - do so in runCli's config.`);
|
|
766
|
+
const lCaseName = n?.toLowerCase();
|
|
767
|
+
if (lCaseName === "0" || lCaseName === "1" || lCaseName === "true" || lCaseName === "false") throw new BroCliError(`Can't define command '${cmd.name}' - '${n}' is a reserved for boolean values name!`);
|
|
768
|
+
if (allNames.findIndex((an) => an === n) !== i) throw new BroCliError(`Can't define command '${cmd.name}' - duplicate alias '${n}'!`);
|
|
769
|
+
});
|
|
770
|
+
if (cmd.subcommands) assignParent(cmd, cmd.subcommands);
|
|
771
|
+
return cmd;
|
|
772
|
+
};
|
|
773
|
+
var getCommandInner = (commands, candidates, args, cliName, cliDescription) => {
|
|
774
|
+
const { data: arg, originalIndex: index } = candidates.shift();
|
|
775
|
+
const command2 = commands.find((c) => {
|
|
776
|
+
return (c.aliases ? [c.name, ...c.aliases] : [c.name]).find((name) => name === arg);
|
|
777
|
+
});
|
|
778
|
+
if (!command2) return {
|
|
779
|
+
command: command2,
|
|
780
|
+
args
|
|
781
|
+
};
|
|
782
|
+
const newArgs = removeByIndex(args, index);
|
|
783
|
+
if (!candidates.length || !command2.subcommands) return {
|
|
784
|
+
command: command2,
|
|
785
|
+
args: newArgs
|
|
786
|
+
};
|
|
787
|
+
const newCandidates = candidates.map((c) => ({
|
|
788
|
+
data: c.data,
|
|
789
|
+
originalIndex: c.originalIndex - 1
|
|
790
|
+
}));
|
|
791
|
+
const subcommand = getCommandInner(command2.subcommands, newCandidates, newArgs, cliName, cliDescription);
|
|
792
|
+
if (!subcommand.command) throw new BroCliError(void 0, {
|
|
793
|
+
type: "error",
|
|
794
|
+
violation: "unknown_subcommand_error",
|
|
795
|
+
name: cliName,
|
|
796
|
+
description: cliDescription,
|
|
797
|
+
command: command2,
|
|
798
|
+
offender: candidates[0].data
|
|
799
|
+
});
|
|
800
|
+
return subcommand;
|
|
801
|
+
};
|
|
802
|
+
var getCommand = (commands, args, cliName, cliDescription) => {
|
|
803
|
+
const candidates = [];
|
|
804
|
+
for (let i = 0; i < args.length; ++i) {
|
|
805
|
+
const arg = args[i];
|
|
806
|
+
if (arg === "--help" || arg === "-h" || arg === "--version" || arg === "-v") {
|
|
807
|
+
const lCaseNext = args[i + 1]?.toLowerCase();
|
|
808
|
+
if (lCaseNext === "0" || lCaseNext === "1" || lCaseNext === "true" || lCaseNext === "false") ++i;
|
|
809
|
+
continue;
|
|
810
|
+
}
|
|
811
|
+
if (arg?.startsWith("-")) {
|
|
812
|
+
if (!arg.includes("=")) ++i;
|
|
813
|
+
continue;
|
|
814
|
+
}
|
|
815
|
+
candidates.push({
|
|
816
|
+
data: arg,
|
|
817
|
+
originalIndex: i
|
|
818
|
+
});
|
|
819
|
+
}
|
|
820
|
+
if (!candidates.length) return {
|
|
821
|
+
command: void 0,
|
|
822
|
+
args
|
|
823
|
+
};
|
|
824
|
+
const firstCandidate = candidates[0];
|
|
825
|
+
if (firstCandidate.data === "help") return {
|
|
826
|
+
command: "help",
|
|
827
|
+
args: removeByIndex(args, firstCandidate.originalIndex)
|
|
828
|
+
};
|
|
829
|
+
const { command: command2, args: argsRes } = getCommandInner(commands, candidates, args, cliName, cliDescription);
|
|
830
|
+
if (!command2) throw new BroCliError(void 0, {
|
|
831
|
+
type: "error",
|
|
832
|
+
violation: "unknown_command_error",
|
|
833
|
+
commands,
|
|
834
|
+
name: cliName,
|
|
835
|
+
description: cliDescription,
|
|
836
|
+
offender: firstCandidate.data
|
|
837
|
+
});
|
|
838
|
+
return {
|
|
839
|
+
command: command2,
|
|
840
|
+
args: argsRes
|
|
841
|
+
};
|
|
842
|
+
};
|
|
843
|
+
var parseArg = (command2, options, positionals, arg, nextArg, cliName, cliDescription) => {
|
|
844
|
+
let data = void 0;
|
|
845
|
+
const argSplit = arg.split("=");
|
|
846
|
+
const hasEq = arg.includes("=");
|
|
847
|
+
const namePart = argSplit.shift();
|
|
848
|
+
const dataPart = hasEq ? argSplit.join("=") : nextArg;
|
|
849
|
+
let lcaseData = dataPart?.toLowerCase();
|
|
850
|
+
let skipNext = !hasEq;
|
|
851
|
+
if (namePart === "--help" || namePart === "-h") return {
|
|
852
|
+
isHelp: true,
|
|
853
|
+
skipNext: !hasEq && nextArg?.startsWith("-") ? false : skipNext
|
|
854
|
+
};
|
|
855
|
+
if (namePart === "--version" || namePart === "-v") return {
|
|
856
|
+
isVersion: true,
|
|
857
|
+
skipNext: !hasEq && nextArg?.startsWith("-") ? false : skipNext
|
|
858
|
+
};
|
|
859
|
+
if (!arg.startsWith("-")) {
|
|
860
|
+
if (!positionals.length) return {};
|
|
861
|
+
const pos = positionals.shift();
|
|
862
|
+
if (pos[1].enumVals && !pos[1].enumVals.find((val) => val === arg)) throw new BroCliError(void 0, {
|
|
863
|
+
type: "error",
|
|
864
|
+
name: cliName,
|
|
865
|
+
description: cliDescription,
|
|
866
|
+
violation: "enum_violation",
|
|
867
|
+
command: command2,
|
|
868
|
+
option: pos[1],
|
|
869
|
+
offender: { dataPart: arg }
|
|
870
|
+
});
|
|
871
|
+
data = arg;
|
|
872
|
+
return {
|
|
873
|
+
data,
|
|
874
|
+
skipNext: false,
|
|
875
|
+
name: pos[0],
|
|
876
|
+
option: pos[1]
|
|
877
|
+
};
|
|
878
|
+
}
|
|
879
|
+
const option = options.find(([optKey, opt]) => {
|
|
880
|
+
const names = [opt.name, ...opt.aliases];
|
|
881
|
+
if (opt.type === "boolean") {
|
|
882
|
+
if (!names.find((name) => name === namePart)) return false;
|
|
883
|
+
if (!hasEq && nextArg?.startsWith("-")) {
|
|
884
|
+
data = true;
|
|
885
|
+
skipNext = false;
|
|
886
|
+
return true;
|
|
887
|
+
}
|
|
888
|
+
if (lcaseData === void 0 || lcaseData === "" || lcaseData === "true" || lcaseData === "1") {
|
|
889
|
+
data = true;
|
|
890
|
+
return true;
|
|
891
|
+
}
|
|
892
|
+
if (lcaseData === "false" || lcaseData === "0") {
|
|
893
|
+
data = false;
|
|
894
|
+
return true;
|
|
895
|
+
}
|
|
896
|
+
if (!hasEq) {
|
|
897
|
+
data = true;
|
|
898
|
+
skipNext = false;
|
|
899
|
+
return true;
|
|
900
|
+
}
|
|
901
|
+
throw new BroCliError(void 0, {
|
|
902
|
+
type: "error",
|
|
903
|
+
name: cliName,
|
|
904
|
+
description: cliDescription,
|
|
905
|
+
violation: "invalid_boolean_syntax",
|
|
906
|
+
option: opt,
|
|
907
|
+
command: command2,
|
|
908
|
+
offender: {
|
|
909
|
+
namePart,
|
|
910
|
+
dataPart
|
|
911
|
+
}
|
|
912
|
+
});
|
|
913
|
+
} else {
|
|
914
|
+
if (!names.find((name) => name === namePart)) return false;
|
|
915
|
+
if (opt.type === "string") {
|
|
916
|
+
if (!hasEq && nextArg === void 0) throw new BroCliError(void 0, {
|
|
917
|
+
type: "error",
|
|
918
|
+
name: cliName,
|
|
919
|
+
description: cliDescription,
|
|
920
|
+
violation: "invalid_string_syntax",
|
|
921
|
+
option: opt,
|
|
922
|
+
command: command2,
|
|
923
|
+
offender: {
|
|
924
|
+
namePart,
|
|
925
|
+
dataPart
|
|
926
|
+
}
|
|
927
|
+
});
|
|
928
|
+
if (opt.enumVals && !opt.enumVals.find((val) => val === dataPart)) throw new BroCliError(void 0, {
|
|
929
|
+
type: "error",
|
|
930
|
+
name: cliName,
|
|
931
|
+
description: cliDescription,
|
|
932
|
+
violation: "enum_violation",
|
|
933
|
+
option: opt,
|
|
934
|
+
command: command2,
|
|
935
|
+
offender: {
|
|
936
|
+
namePart,
|
|
937
|
+
dataPart
|
|
938
|
+
}
|
|
939
|
+
});
|
|
940
|
+
data = dataPart;
|
|
941
|
+
return true;
|
|
942
|
+
}
|
|
943
|
+
if (!hasEq && nextArg === void 0) throw new BroCliError(void 0, {
|
|
944
|
+
type: "error",
|
|
945
|
+
name: cliName,
|
|
946
|
+
description: cliDescription,
|
|
947
|
+
violation: "invalid_number_syntax",
|
|
948
|
+
option: opt,
|
|
949
|
+
command: command2,
|
|
950
|
+
offender: {
|
|
951
|
+
namePart,
|
|
952
|
+
dataPart
|
|
953
|
+
}
|
|
954
|
+
});
|
|
955
|
+
const numData = Number(dataPart);
|
|
956
|
+
if (isNaN(numData)) throw new BroCliError(void 0, {
|
|
957
|
+
type: "error",
|
|
958
|
+
name: cliName,
|
|
959
|
+
description: cliDescription,
|
|
960
|
+
violation: "invalid_number_value",
|
|
961
|
+
option: opt,
|
|
962
|
+
command: command2,
|
|
963
|
+
offender: {
|
|
964
|
+
namePart,
|
|
965
|
+
dataPart
|
|
966
|
+
}
|
|
967
|
+
});
|
|
968
|
+
if (opt.isInt && !isInt(numData)) throw new BroCliError(void 0, {
|
|
969
|
+
type: "error",
|
|
970
|
+
name: cliName,
|
|
971
|
+
description: cliDescription,
|
|
972
|
+
violation: "expected_int",
|
|
973
|
+
option: opt,
|
|
974
|
+
command: command2,
|
|
975
|
+
offender: {
|
|
976
|
+
namePart,
|
|
977
|
+
dataPart
|
|
978
|
+
}
|
|
979
|
+
});
|
|
980
|
+
if (opt.minVal !== void 0 && numData < opt.minVal) throw new BroCliError(void 0, {
|
|
981
|
+
type: "error",
|
|
982
|
+
name: cliName,
|
|
983
|
+
description: cliDescription,
|
|
984
|
+
violation: "below_min",
|
|
985
|
+
option: opt,
|
|
986
|
+
command: command2,
|
|
987
|
+
offender: {
|
|
988
|
+
namePart,
|
|
989
|
+
dataPart
|
|
990
|
+
}
|
|
991
|
+
});
|
|
992
|
+
if (opt.maxVal !== void 0 && numData > opt.maxVal) throw new BroCliError(void 0, {
|
|
993
|
+
type: "error",
|
|
994
|
+
name: cliName,
|
|
995
|
+
description: cliDescription,
|
|
996
|
+
violation: "above_max",
|
|
997
|
+
option: opt,
|
|
998
|
+
command: command2,
|
|
999
|
+
offender: {
|
|
1000
|
+
namePart,
|
|
1001
|
+
dataPart
|
|
1002
|
+
}
|
|
1003
|
+
});
|
|
1004
|
+
data = numData;
|
|
1005
|
+
return true;
|
|
1006
|
+
}
|
|
1007
|
+
});
|
|
1008
|
+
return {
|
|
1009
|
+
data,
|
|
1010
|
+
skipNext,
|
|
1011
|
+
name: option?.[0],
|
|
1012
|
+
option: option?.[1]
|
|
1013
|
+
};
|
|
1014
|
+
};
|
|
1015
|
+
var parseOptions = (command2, args, cliName, cliDescription, omitKeysOfUndefinedOptions) => {
|
|
1016
|
+
const options = command2.options;
|
|
1017
|
+
let noOpts = !options;
|
|
1018
|
+
const optEntries = Object.entries(options ?? {}).map((opt) => [opt[0], opt[1].config]);
|
|
1019
|
+
const nonPositionalEntries = optEntries.filter(([key, opt]) => opt.type !== "positional");
|
|
1020
|
+
const positionalEntries = optEntries.filter(([key, opt]) => opt.type === "positional");
|
|
1021
|
+
const result = {};
|
|
1022
|
+
const missingRequiredArr = [];
|
|
1023
|
+
const unrecognizedArgsArr = [];
|
|
1024
|
+
for (let i = 0; i < args.length; ++i) {
|
|
1025
|
+
const arg = args[i];
|
|
1026
|
+
const nextArg = args[i + 1];
|
|
1027
|
+
const { data, name, option, skipNext, isHelp, isVersion } = parseArg(command2, nonPositionalEntries, positionalEntries, arg, nextArg, cliName, cliDescription);
|
|
1028
|
+
if (!option) unrecognizedArgsArr.push(arg.split("=")[0]);
|
|
1029
|
+
if (skipNext) ++i;
|
|
1030
|
+
if (isHelp) return "help";
|
|
1031
|
+
if (isVersion) return "version";
|
|
1032
|
+
result[name] = data;
|
|
1033
|
+
}
|
|
1034
|
+
for (const [optKey, option] of optEntries) {
|
|
1035
|
+
const data = result[optKey] ?? option.default;
|
|
1036
|
+
if (!omitKeysOfUndefinedOptions) result[optKey] = data;
|
|
1037
|
+
else if (data !== void 0) result[optKey] = data;
|
|
1038
|
+
if (option.isRequired && result[optKey] === void 0) missingRequiredArr.push([option.name, ...option.aliases]);
|
|
1039
|
+
}
|
|
1040
|
+
if (missingRequiredArr.length) throw new BroCliError(void 0, {
|
|
1041
|
+
type: "error",
|
|
1042
|
+
violation: "missing_args_error",
|
|
1043
|
+
name: cliName,
|
|
1044
|
+
description: cliDescription,
|
|
1045
|
+
command: command2,
|
|
1046
|
+
missing: missingRequiredArr
|
|
1047
|
+
});
|
|
1048
|
+
if (unrecognizedArgsArr.length) throw new BroCliError(void 0, {
|
|
1049
|
+
type: "error",
|
|
1050
|
+
violation: "unrecognized_args_error",
|
|
1051
|
+
name: cliName,
|
|
1052
|
+
description: cliDescription,
|
|
1053
|
+
command: command2,
|
|
1054
|
+
unrecognized: unrecognizedArgsArr
|
|
1055
|
+
});
|
|
1056
|
+
return noOpts ? void 0 : result;
|
|
1057
|
+
};
|
|
1058
|
+
var parseGlobals = (command2, globals, args, cliName, cliDescription, omitKeysOfUndefinedOptions, ignoreSpecialCases) => {
|
|
1059
|
+
if (!globals) return void 0;
|
|
1060
|
+
const optEntries = Object.entries(globals).map((opt) => [opt[0], opt[1].config]);
|
|
1061
|
+
const result = {};
|
|
1062
|
+
const missingRequiredArr = [];
|
|
1063
|
+
for (let i = 0; i < args.length; ++i) {
|
|
1064
|
+
const arg = args[i];
|
|
1065
|
+
const nextArg = args[i + 1];
|
|
1066
|
+
const { data, name, option, skipNext, isHelp, isVersion } = parseArg(command2, optEntries, [], arg, nextArg, cliName, cliDescription);
|
|
1067
|
+
if (skipNext) ++i;
|
|
1068
|
+
if (!ignoreSpecialCases) {
|
|
1069
|
+
if (isHelp) return "help";
|
|
1070
|
+
if (isVersion) return "version";
|
|
1071
|
+
}
|
|
1072
|
+
if (!option) continue;
|
|
1073
|
+
delete args[i];
|
|
1074
|
+
if (skipNext) delete args[i - 1];
|
|
1075
|
+
result[name] = data;
|
|
1076
|
+
}
|
|
1077
|
+
for (const [optKey, option] of optEntries) {
|
|
1078
|
+
const data = result[optKey] ?? option.default;
|
|
1079
|
+
if (!omitKeysOfUndefinedOptions) result[optKey] = data;
|
|
1080
|
+
else if (data !== void 0) result[optKey] = data;
|
|
1081
|
+
if (option.isRequired && result[optKey] === void 0) missingRequiredArr.push([option.name, ...option.aliases]);
|
|
1082
|
+
}
|
|
1083
|
+
if (missingRequiredArr.length) throw new BroCliError(void 0, {
|
|
1084
|
+
type: "error",
|
|
1085
|
+
violation: "missing_args_error",
|
|
1086
|
+
name: cliName,
|
|
1087
|
+
description: cliDescription,
|
|
1088
|
+
command: command2,
|
|
1089
|
+
missing: missingRequiredArr
|
|
1090
|
+
});
|
|
1091
|
+
return Object.keys(result).length ? result : void 0;
|
|
1092
|
+
};
|
|
1093
|
+
var getCommandNameWithParents = (command2) => command2.parent ? `${getCommandNameWithParents(command2.parent)} ${command2.name}` : command2.name;
|
|
1094
|
+
var validateCommands = (commands, parent) => {
|
|
1095
|
+
const storedNames = {};
|
|
1096
|
+
for (const cmd of commands) {
|
|
1097
|
+
const storageVals = Object.values(storedNames);
|
|
1098
|
+
for (const storage of storageVals) {
|
|
1099
|
+
if (!storage.find((e) => e === cmd.name)) continue;
|
|
1100
|
+
throw new BroCliError(`Can't define command '${getCommandNameWithParents(cmd)}': name is already in use by command '${parent ? `${getCommandNameWithParents(parent)} ` : ""}${storage[0]}'!`);
|
|
1101
|
+
}
|
|
1102
|
+
if (cmd.aliases) for (const alias of cmd.aliases) for (const storage of storageVals) {
|
|
1103
|
+
if (!storage.find((e) => e === alias)) continue;
|
|
1104
|
+
throw new BroCliError(`Can't define command '${getCommandNameWithParents(cmd)}': alias '${alias}' is already in use by command '${parent ? `${getCommandNameWithParents(parent)} ` : ""}${storage[0]}'!`);
|
|
1105
|
+
}
|
|
1106
|
+
storedNames[cmd.name] = cmd.aliases ? [cmd.name, ...cmd.aliases] : [cmd.name];
|
|
1107
|
+
if (cmd.subcommands) cmd.subcommands = validateCommands(cmd.subcommands, cmd);
|
|
1108
|
+
}
|
|
1109
|
+
return commands;
|
|
1110
|
+
};
|
|
1111
|
+
var validateGlobalsInner = (commands, globals) => {
|
|
1112
|
+
for (const c of commands) {
|
|
1113
|
+
const { options } = c;
|
|
1114
|
+
if (!options) continue;
|
|
1115
|
+
for (const { config: opt } of Object.values(options)) {
|
|
1116
|
+
if (globals.find(({ config: g }) => g.name === opt.name)) throw new BroCliError(`Global options overlap with option '${opt.name}' of command '${getCommandNameWithParents(c)}' on name`);
|
|
1117
|
+
let foundAliasOverlap = opt.aliases.find((a) => globals.find(({ config: g }) => g.name === a)) ?? globals.find(({ config: g }) => opt.aliases.find((a) => a === g.name));
|
|
1118
|
+
if (!foundAliasOverlap) for (const { config: g } of globals) {
|
|
1119
|
+
foundAliasOverlap = g.aliases.find((gAlias) => opt.name === gAlias);
|
|
1120
|
+
if (foundAliasOverlap) break;
|
|
1121
|
+
}
|
|
1122
|
+
if (!foundAliasOverlap) for (const { config: g } of globals) {
|
|
1123
|
+
foundAliasOverlap = g.aliases.find((gAlias) => opt.aliases.find((a) => a === gAlias));
|
|
1124
|
+
if (foundAliasOverlap) break;
|
|
1125
|
+
}
|
|
1126
|
+
if (foundAliasOverlap) throw new BroCliError(`Global options overlap with option '${opt.name}' of command '${getCommandNameWithParents(c)}' on alias '${foundAliasOverlap}'`);
|
|
1127
|
+
}
|
|
1128
|
+
if (c.subcommands) validateGlobalsInner(c.subcommands, globals);
|
|
1129
|
+
}
|
|
1130
|
+
};
|
|
1131
|
+
var validateGlobals = (commands, globals) => {
|
|
1132
|
+
if (!globals) return;
|
|
1133
|
+
validateGlobalsInner(commands, Object.values(globals));
|
|
1134
|
+
};
|
|
1135
|
+
var removeByIndex = (arr, idx) => [...arr.slice(0, idx), ...arr.slice(idx + 1, arr.length)];
|
|
1136
|
+
var run = async (commands, config) => {
|
|
1137
|
+
const eventHandler = config?.theme ? eventHandlerWrapper(config.theme) : defaultEventHandler;
|
|
1138
|
+
const argSource = config?.argSource ?? process.argv;
|
|
1139
|
+
const version = config?.version;
|
|
1140
|
+
const help = config?.help;
|
|
1141
|
+
const omitKeysOfUndefinedOptions = config?.omitKeysOfUndefinedOptions ?? false;
|
|
1142
|
+
const cliName = config?.name;
|
|
1143
|
+
const cliDescription = config?.description;
|
|
1144
|
+
const globals = config?.globals;
|
|
1145
|
+
let prepassError;
|
|
1146
|
+
let processedGlobals;
|
|
1147
|
+
let processedCmds;
|
|
1148
|
+
const args = argSource.slice(2, argSource.length);
|
|
1149
|
+
try {
|
|
1150
|
+
processedCmds = validateCommands(commands);
|
|
1151
|
+
processedGlobals = globals ? validateOptions(globals) : void 0;
|
|
1152
|
+
if (processedGlobals) validateGlobals(processedCmds, processedGlobals);
|
|
1153
|
+
} catch (e) {
|
|
1154
|
+
prepassError = e;
|
|
1155
|
+
processedCmds = [];
|
|
1156
|
+
}
|
|
1157
|
+
let preparseError;
|
|
1158
|
+
let _preparsedGlobals;
|
|
1159
|
+
const preparsedGlobals = () => {
|
|
1160
|
+
if (preparseError) throw preparseError;
|
|
1161
|
+
return _preparsedGlobals;
|
|
1162
|
+
};
|
|
1163
|
+
try {
|
|
1164
|
+
_preparsedGlobals = parseGlobals("globals", processedGlobals, [...args], cliName, cliDescription, omitKeysOfUndefinedOptions, true);
|
|
1165
|
+
} catch (e) {
|
|
1166
|
+
preparseError = e;
|
|
1167
|
+
}
|
|
1168
|
+
try {
|
|
1169
|
+
if (prepassError) throw prepassError;
|
|
1170
|
+
if (!args.length) return help !== void 0 ? await executeOrLog(help, preparsedGlobals()) : await eventHandler({
|
|
1171
|
+
type: "global_help",
|
|
1172
|
+
description: cliDescription,
|
|
1173
|
+
name: cliName,
|
|
1174
|
+
commands: processedCmds,
|
|
1175
|
+
globals: processedGlobals
|
|
1176
|
+
}, preparsedGlobals());
|
|
1177
|
+
const helpIndex = args.findIndex((arg) => arg === "--help" || arg === "-h");
|
|
1178
|
+
if (helpIndex !== -1 && (helpIndex > 0 ? args[helpIndex - 1]?.startsWith("-") && !args[helpIndex - 1].includes("=") ? false : true : true)) {
|
|
1179
|
+
const command3 = getCommand(processedCmds, args, cliName, cliDescription).command;
|
|
1180
|
+
if (typeof command3 === "object") return command3.help !== void 0 ? await executeOrLog(command3.help) : await eventHandler({
|
|
1181
|
+
type: "command_help",
|
|
1182
|
+
description: cliDescription,
|
|
1183
|
+
name: cliName,
|
|
1184
|
+
command: command3,
|
|
1185
|
+
globals: processedGlobals
|
|
1186
|
+
}, preparsedGlobals());
|
|
1187
|
+
else return help !== void 0 ? await executeOrLog(help, preparsedGlobals()) : await eventHandler({
|
|
1188
|
+
type: "global_help",
|
|
1189
|
+
description: cliDescription,
|
|
1190
|
+
name: cliName,
|
|
1191
|
+
commands: processedCmds,
|
|
1192
|
+
globals: processedGlobals
|
|
1193
|
+
}, preparsedGlobals());
|
|
1194
|
+
}
|
|
1195
|
+
const versionIndex = args.findIndex((arg) => arg === "--version" || arg === "-v");
|
|
1196
|
+
if (versionIndex !== -1 && (versionIndex > 0 ? args[versionIndex - 1]?.startsWith("-") ? false : true : true)) return version !== void 0 ? await executeOrLog(version, preparsedGlobals()) : await eventHandler({
|
|
1197
|
+
type: "version",
|
|
1198
|
+
name: cliName,
|
|
1199
|
+
description: cliDescription
|
|
1200
|
+
}, preparsedGlobals());
|
|
1201
|
+
const { command: command2, args: newArgs } = getCommand(processedCmds, args, cliName, cliDescription);
|
|
1202
|
+
if (!command2) return help !== void 0 ? await executeOrLog(help, preparsedGlobals()) : await eventHandler({
|
|
1203
|
+
type: "global_help",
|
|
1204
|
+
description: cliDescription,
|
|
1205
|
+
name: cliName,
|
|
1206
|
+
commands: processedCmds,
|
|
1207
|
+
globals: processedGlobals
|
|
1208
|
+
}, preparsedGlobals());
|
|
1209
|
+
if (command2 === "help") {
|
|
1210
|
+
let helpCommand;
|
|
1211
|
+
let newestArgs = newArgs;
|
|
1212
|
+
do {
|
|
1213
|
+
const res = getCommand(processedCmds, newestArgs, cliName, cliDescription);
|
|
1214
|
+
helpCommand = res.command;
|
|
1215
|
+
newestArgs = res.args;
|
|
1216
|
+
} while (helpCommand === "help");
|
|
1217
|
+
return helpCommand ? helpCommand.help !== void 0 ? await executeOrLog(helpCommand.help) : await eventHandler({
|
|
1218
|
+
type: "command_help",
|
|
1219
|
+
description: cliDescription,
|
|
1220
|
+
name: cliName,
|
|
1221
|
+
command: helpCommand,
|
|
1222
|
+
globals: processedGlobals
|
|
1223
|
+
}, preparsedGlobals()) : help !== void 0 ? await executeOrLog(help, preparsedGlobals()) : await eventHandler({
|
|
1224
|
+
type: "global_help",
|
|
1225
|
+
description: cliDescription,
|
|
1226
|
+
name: cliName,
|
|
1227
|
+
commands: processedCmds,
|
|
1228
|
+
globals: processedGlobals
|
|
1229
|
+
}, preparsedGlobals());
|
|
1230
|
+
}
|
|
1231
|
+
const gOptionResult = parseGlobals(command2, processedGlobals, newArgs, cliName, cliDescription, omitKeysOfUndefinedOptions);
|
|
1232
|
+
const optionResult = gOptionResult && (gOptionResult === "help" || gOptionResult === "version") ? gOptionResult : parseOptions(command2, globals ? newArgs.filter((a) => a !== void 0) : newArgs, cliName, cliDescription, omitKeysOfUndefinedOptions);
|
|
1233
|
+
if (optionResult === "help" || gOptionResult === "help") return command2.help !== void 0 ? await executeOrLog(command2.help) : await eventHandler({
|
|
1234
|
+
type: "command_help",
|
|
1235
|
+
description: cliDescription,
|
|
1236
|
+
name: cliName,
|
|
1237
|
+
command: command2,
|
|
1238
|
+
globals: processedGlobals
|
|
1239
|
+
}, preparsedGlobals());
|
|
1240
|
+
if (optionResult === "version" || gOptionResult === "version") return version !== void 0 ? await executeOrLog(version, preparsedGlobals()) : await eventHandler({
|
|
1241
|
+
type: "version",
|
|
1242
|
+
name: cliName,
|
|
1243
|
+
description: cliDescription
|
|
1244
|
+
}, preparsedGlobals());
|
|
1245
|
+
if (command2.handler) {
|
|
1246
|
+
if (config?.hook) await config.hook("before", command2, gOptionResult);
|
|
1247
|
+
await command2.handler(command2.transform ? await command2.transform(optionResult) : optionResult);
|
|
1248
|
+
if (config?.hook) await config.hook("after", command2, gOptionResult);
|
|
1249
|
+
return;
|
|
1250
|
+
} else return command2.help !== void 0 ? await executeOrLog(command2.help) : await eventHandler({
|
|
1251
|
+
type: "command_help",
|
|
1252
|
+
description: cliDescription,
|
|
1253
|
+
name: cliName,
|
|
1254
|
+
command: command2,
|
|
1255
|
+
globals: processedGlobals
|
|
1256
|
+
}, preparsedGlobals());
|
|
1257
|
+
} catch (e) {
|
|
1258
|
+
if (e instanceof BroCliError) if (e.event) await eventHandler(e.event, preparsedGlobals());
|
|
1259
|
+
else if (!config?.noExit) console.error(e.message);
|
|
1260
|
+
else return e.message;
|
|
1261
|
+
else await eventHandler({
|
|
1262
|
+
type: "error",
|
|
1263
|
+
violation: "unknown_error",
|
|
1264
|
+
name: cliName,
|
|
1265
|
+
description: cliDescription,
|
|
1266
|
+
error: e
|
|
1267
|
+
}, preparsedGlobals());
|
|
1268
|
+
if (!config?.noExit) process.exit(1);
|
|
1269
|
+
return;
|
|
1270
|
+
}
|
|
1271
|
+
};
|
|
1272
|
+
var OptionBuilderBase = class _OptionBuilderBase {
|
|
1273
|
+
_;
|
|
1274
|
+
config = () => this._.config;
|
|
1275
|
+
constructor(config) {
|
|
1276
|
+
this._ = {
|
|
1277
|
+
config: config ?? {
|
|
1278
|
+
aliases: [],
|
|
1279
|
+
type: "string"
|
|
1280
|
+
},
|
|
1281
|
+
$output: void 0
|
|
1282
|
+
};
|
|
1283
|
+
}
|
|
1284
|
+
string(name) {
|
|
1285
|
+
return new _OptionBuilderBase({
|
|
1286
|
+
...this.config(),
|
|
1287
|
+
type: "string",
|
|
1288
|
+
name
|
|
1289
|
+
});
|
|
1290
|
+
}
|
|
1291
|
+
number(name) {
|
|
1292
|
+
return new _OptionBuilderBase({
|
|
1293
|
+
...this.config(),
|
|
1294
|
+
type: "number",
|
|
1295
|
+
name
|
|
1296
|
+
});
|
|
1297
|
+
}
|
|
1298
|
+
boolean(name) {
|
|
1299
|
+
return new _OptionBuilderBase({
|
|
1300
|
+
...this.config(),
|
|
1301
|
+
type: "boolean",
|
|
1302
|
+
name
|
|
1303
|
+
});
|
|
1304
|
+
}
|
|
1305
|
+
positional(displayName) {
|
|
1306
|
+
return new _OptionBuilderBase({
|
|
1307
|
+
...this.config(),
|
|
1308
|
+
type: "positional",
|
|
1309
|
+
name: displayName
|
|
1310
|
+
});
|
|
1311
|
+
}
|
|
1312
|
+
alias(...aliases) {
|
|
1313
|
+
return new _OptionBuilderBase({
|
|
1314
|
+
...this.config(),
|
|
1315
|
+
aliases
|
|
1316
|
+
});
|
|
1317
|
+
}
|
|
1318
|
+
desc(description) {
|
|
1319
|
+
return new _OptionBuilderBase({
|
|
1320
|
+
...this.config(),
|
|
1321
|
+
description
|
|
1322
|
+
});
|
|
1323
|
+
}
|
|
1324
|
+
hidden() {
|
|
1325
|
+
return new _OptionBuilderBase({
|
|
1326
|
+
...this.config(),
|
|
1327
|
+
isHidden: true
|
|
1328
|
+
});
|
|
1329
|
+
}
|
|
1330
|
+
required() {
|
|
1331
|
+
return new _OptionBuilderBase({
|
|
1332
|
+
...this.config(),
|
|
1333
|
+
isRequired: true
|
|
1334
|
+
});
|
|
1335
|
+
}
|
|
1336
|
+
default(value) {
|
|
1337
|
+
const config = this.config();
|
|
1338
|
+
const enums = config.enumVals;
|
|
1339
|
+
if (enums && !enums.find((v) => value === v)) throw new Error(`Option enums [ ${enums.join(", ")} ] are incompatible with default value ${value}`);
|
|
1340
|
+
return new _OptionBuilderBase({
|
|
1341
|
+
...config,
|
|
1342
|
+
default: value
|
|
1343
|
+
});
|
|
1344
|
+
}
|
|
1345
|
+
enum(...values) {
|
|
1346
|
+
const config = this.config();
|
|
1347
|
+
const defaultVal = config.default;
|
|
1348
|
+
if (defaultVal !== void 0 && !values.find((v) => defaultVal === v)) throw new Error(`Option enums [ ${values.join(", ")} ] are incompatible with default value ${defaultVal}`);
|
|
1349
|
+
return new _OptionBuilderBase({
|
|
1350
|
+
...config,
|
|
1351
|
+
enumVals: values
|
|
1352
|
+
});
|
|
1353
|
+
}
|
|
1354
|
+
min(value) {
|
|
1355
|
+
const config = this.config();
|
|
1356
|
+
const maxVal = config.maxVal;
|
|
1357
|
+
if (maxVal !== void 0 && maxVal < value) throw new BroCliError("Unable to define option's min value to be higher than max value!");
|
|
1358
|
+
return new _OptionBuilderBase({
|
|
1359
|
+
...config,
|
|
1360
|
+
minVal: value
|
|
1361
|
+
});
|
|
1362
|
+
}
|
|
1363
|
+
max(value) {
|
|
1364
|
+
const config = this.config();
|
|
1365
|
+
const minVal = config.minVal;
|
|
1366
|
+
if (minVal !== void 0 && minVal > value) throw new BroCliError("Unable to define option's max value to be lower than min value!");
|
|
1367
|
+
return new _OptionBuilderBase({
|
|
1368
|
+
...config,
|
|
1369
|
+
maxVal: value
|
|
1370
|
+
});
|
|
1371
|
+
}
|
|
1372
|
+
int() {
|
|
1373
|
+
return new _OptionBuilderBase({
|
|
1374
|
+
...this.config(),
|
|
1375
|
+
isInt: true
|
|
1376
|
+
});
|
|
1377
|
+
}
|
|
1378
|
+
};
|
|
1379
|
+
function string(name) {
|
|
1380
|
+
return typeof name === "string" ? new OptionBuilderBase().string(name) : new OptionBuilderBase().string();
|
|
1381
|
+
}
|
|
1382
|
+
function boolean(name) {
|
|
1383
|
+
return typeof name === "string" ? new OptionBuilderBase().boolean(name) : new OptionBuilderBase().boolean();
|
|
1384
|
+
}
|
|
1385
|
+
function positional(displayName) {
|
|
1386
|
+
return typeof displayName === "string" ? new OptionBuilderBase().positional(displayName) : new OptionBuilderBase().positional();
|
|
1387
|
+
}
|
|
1388
|
+
//#endregion
|
|
1389
|
+
//#region src/cli/commands/_utils.ts
|
|
1390
|
+
function resolveWorkspaceRoot(root) {
|
|
1391
|
+
return root != null ? resolve(process$1.cwd(), root) : getWorkspaceRoot();
|
|
1392
|
+
}
|
|
1393
|
+
async function loadConfig(params) {
|
|
1394
|
+
let { workspaceRoot, require = false } = params;
|
|
1395
|
+
let config = await loadBuildConfig(workspaceRoot);
|
|
1396
|
+
if (!config && require) throw new Error(`Config not found at ${workspaceRoot}`);
|
|
1397
|
+
return config ?? null;
|
|
1398
|
+
}
|
|
1399
|
+
//#endregion
|
|
1400
|
+
//#region src/cli/commands/build.ts
|
|
1401
|
+
async function resolveViteConfig(workspaceRoot, configured) {
|
|
1402
|
+
if (configured != null) return configured;
|
|
1403
|
+
if (await fileExists(join(workspaceRoot, "vite.config.ts"))) return "vite.config.ts";
|
|
1404
|
+
if (await fileExists(join(workspaceRoot, "vite.config.js"))) return "vite.config.js";
|
|
1405
|
+
return "vite.config.ts";
|
|
1406
|
+
}
|
|
1407
|
+
/**
|
|
1408
|
+
* build a single package using vite
|
|
1409
|
+
*
|
|
1410
|
+
* tiny wrapper on top of `vite build`
|
|
1411
|
+
*/
|
|
1412
|
+
async function buildPackage(params) {
|
|
1413
|
+
let config = await loadConfig({ workspaceRoot: params.workspaceRoot });
|
|
1414
|
+
let workspacePackages = params.workspace ?? await collectPackageJsons(params.workspaceRoot, true);
|
|
1415
|
+
let viteConfig = await resolveViteConfig(params.workspaceRoot, config?.viteConfig);
|
|
1416
|
+
let packageRoot = findPackageByName(workspacePackages, params.packageName).path;
|
|
1417
|
+
let env = {
|
|
1418
|
+
...process$1.env,
|
|
1419
|
+
__YOROZU_INTERNAL_PACKAGES_LIST: JSON.stringify(workspacePackages)
|
|
1420
|
+
};
|
|
1421
|
+
if (params.fixedVersion != null) env.__YOROZU_INTERNAL_FIXED_VERSION = params.fixedVersion;
|
|
1422
|
+
await exec([
|
|
1423
|
+
"npx",
|
|
1424
|
+
"vite",
|
|
1425
|
+
"build",
|
|
1426
|
+
"--config",
|
|
1427
|
+
join(params.workspaceRoot, viteConfig)
|
|
1428
|
+
], {
|
|
1429
|
+
env,
|
|
1430
|
+
cwd: packageRoot,
|
|
1431
|
+
stdio: "inherit",
|
|
1432
|
+
throwOnError: true
|
|
1433
|
+
});
|
|
1434
|
+
}
|
|
1435
|
+
/**
|
|
1436
|
+
* build every npm-publishable workspace package in publish order
|
|
1437
|
+
*/
|
|
1438
|
+
async function buildWorkspace(params) {
|
|
1439
|
+
let workspace = await collectPackageJsons(params.workspaceRoot, true);
|
|
1440
|
+
let ordered = filterPackageJsonsForPublish(sortWorkspaceByPublishOrder(workspace.filter((pkg) => !pkg.root)), "npm");
|
|
1441
|
+
for (let pkg of ordered) {
|
|
1442
|
+
let packageName = asNonNull(pkg.json.name);
|
|
1443
|
+
info(`building ${packageName}`);
|
|
1444
|
+
await buildPackage({
|
|
1445
|
+
workspaceRoot: params.workspaceRoot,
|
|
1446
|
+
workspace,
|
|
1447
|
+
packageName,
|
|
1448
|
+
fixedVersion: params.fixedVersion
|
|
1449
|
+
});
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
var buildPackageCli = command({
|
|
1453
|
+
name: "build",
|
|
1454
|
+
desc: "build a package",
|
|
1455
|
+
options: {
|
|
1456
|
+
config: string("config").desc("path to the build.config.js file"),
|
|
1457
|
+
root: string().desc("path to the root of the workspace (default: cwd)"),
|
|
1458
|
+
packageName: positional("package-name").desc("name of the package to build (or :all to build the entire workspace)").default(":all"),
|
|
1459
|
+
fixedVersion: string("fixed-version").desc("fixed version for every managed package (useful for pre-releases)")
|
|
1460
|
+
},
|
|
1461
|
+
handler: async (args) => {
|
|
1462
|
+
let workspaceRoot = args.root != null ? resolve(process$1.cwd(), args.root) : getWorkspaceRoot();
|
|
1463
|
+
if (args.packageName === ":all") {
|
|
1464
|
+
await buildWorkspace({
|
|
1465
|
+
workspaceRoot,
|
|
1466
|
+
fixedVersion: args.fixedVersion
|
|
1467
|
+
});
|
|
1468
|
+
return;
|
|
1469
|
+
}
|
|
1470
|
+
await buildPackage({
|
|
1471
|
+
workspaceRoot,
|
|
1472
|
+
packageName: args.packageName,
|
|
1473
|
+
configPath: args.config,
|
|
1474
|
+
fixedVersion: args.fixedVersion
|
|
1475
|
+
});
|
|
1476
|
+
}
|
|
1477
|
+
});
|
|
1478
|
+
//#endregion
|
|
1479
|
+
//#region src/npm/npm-api.ts
|
|
1480
|
+
var USER_AGENT$1 = "@yorozu/build";
|
|
1481
|
+
var DEFAULT_REGISTRY = "https://registry.npmjs.org";
|
|
1482
|
+
var REQUEST_TIMEOUT_MS$1 = 3e4;
|
|
1483
|
+
var NPM_PACKAGE_NAME_REGEX = /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
|
|
1484
|
+
async function npmCheckVersion(params) {
|
|
1485
|
+
let url = `${(params.registry ?? DEFAULT_REGISTRY).replace(/\/$/, "")}/${params.package}/${params.version}`;
|
|
1486
|
+
let res = await fetch(url, {
|
|
1487
|
+
headers: { "User-Agent": USER_AGENT$1 },
|
|
1488
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS$1)
|
|
1489
|
+
});
|
|
1490
|
+
if (res.body) res.body.cancel();
|
|
1491
|
+
return res.status === 200;
|
|
1492
|
+
}
|
|
1493
|
+
//#endregion
|
|
1494
|
+
//#region src/cli/commands/publish.ts
|
|
1495
|
+
var DEFAULT_REGISTRY_URL = "https://registry.npmjs.org";
|
|
1496
|
+
function normalizeNpmAuthToken(token) {
|
|
1497
|
+
if (token == null) return void 0;
|
|
1498
|
+
let trimmed = token.trim();
|
|
1499
|
+
return trimmed === "" ? void 0 : trimmed;
|
|
1500
|
+
}
|
|
1501
|
+
function formatNpmAuthRc(registryUrl, token) {
|
|
1502
|
+
return `${new URL(":_authToken", registryUrl).href.replace(/^https:\/\//, "//")}=${token}\n`;
|
|
1503
|
+
}
|
|
1504
|
+
async function prepareNpmPublishAuth(params) {
|
|
1505
|
+
let token = normalizeNpmAuthToken(params.token);
|
|
1506
|
+
if (token == null) return {
|
|
1507
|
+
extraArgs: [],
|
|
1508
|
+
extraEnv: {},
|
|
1509
|
+
cleanup: async () => {}
|
|
1510
|
+
};
|
|
1511
|
+
let dir = await fsp.mkdtemp(join(tmpdir(), "yorozu-npm-auth-"));
|
|
1512
|
+
let npmrcPath = join(dir, ".npmrc");
|
|
1513
|
+
await fsp.writeFile(npmrcPath, formatNpmAuthRc(params.registryUrl, token), { mode: 384 });
|
|
1514
|
+
return {
|
|
1515
|
+
extraArgs: ["--userconfig", npmrcPath],
|
|
1516
|
+
extraEnv: {
|
|
1517
|
+
NPM_TOKEN: token,
|
|
1518
|
+
NODE_AUTH_TOKEN: token
|
|
1519
|
+
},
|
|
1520
|
+
cleanup: async () => {
|
|
1521
|
+
await fsp.rm(dir, {
|
|
1522
|
+
recursive: true,
|
|
1523
|
+
force: true
|
|
1524
|
+
});
|
|
1525
|
+
}
|
|
1526
|
+
};
|
|
1527
|
+
}
|
|
1528
|
+
async function publishPackages(params) {
|
|
1529
|
+
let { workspaceRoot = process$1.cwd(), workspace = await collectPackageJsons(workspaceRoot, true), packages, unpublishExisting = false, skipVersionCheck = false, registryUrl = DEFAULT_REGISTRY_URL, token, distDir = "dist", publishArgs = [], dryRun, withTarballs, withBuild, fixedVersion, noProvenance = false } = params;
|
|
1530
|
+
let ordered = filterPackageJsonsForPublish(sortWorkspaceByPublishOrder(workspace.filter((pkg) => !pkg.root)), "npm");
|
|
1531
|
+
let toPublish = packages.length === 1 && packages[0] === ":all" ? ordered : ordered.filter((pkg) => packages.includes(asNonNull(pkg.json.name)));
|
|
1532
|
+
let failed = [];
|
|
1533
|
+
let tarballs = [];
|
|
1534
|
+
let auth = await prepareNpmPublishAuth({
|
|
1535
|
+
token: dryRun ? void 0 : token,
|
|
1536
|
+
registryUrl
|
|
1537
|
+
});
|
|
1538
|
+
let npmEnv = {
|
|
1539
|
+
...process$1.env,
|
|
1540
|
+
...auth.extraEnv
|
|
1541
|
+
};
|
|
1542
|
+
try {
|
|
1543
|
+
if (!dryRun) await exec([
|
|
1544
|
+
"npm",
|
|
1545
|
+
...auth.extraArgs,
|
|
1546
|
+
"whoami",
|
|
1547
|
+
"--registry",
|
|
1548
|
+
registryUrl
|
|
1549
|
+
], {
|
|
1550
|
+
throwOnError: true,
|
|
1551
|
+
env: npmEnv
|
|
1552
|
+
});
|
|
1553
|
+
if (!noProvenance && isRunningInGithubActions() && Boolean(process$1.env.ACTIONS_ID_TOKEN_REQUEST_URL) && registryUrl === DEFAULT_REGISTRY_URL) {
|
|
1554
|
+
if (!publishArgs.some((it) => it.startsWith("--provenance"))) publishArgs.push("--provenance");
|
|
1555
|
+
}
|
|
1556
|
+
for (let pkg of toPublish) {
|
|
1557
|
+
let pkgVersion = fixedVersion ?? asNonNull(pkg.json.version);
|
|
1558
|
+
if (!dryRun && !skipVersionCheck && await npmCheckVersion({
|
|
1559
|
+
registry: registryUrl,
|
|
1560
|
+
package: asNonNull(pkg.json.name),
|
|
1561
|
+
version: pkgVersion
|
|
1562
|
+
})) if (unpublishExisting) await exec([
|
|
1563
|
+
"npm",
|
|
1564
|
+
...auth.extraArgs,
|
|
1565
|
+
"unpublish",
|
|
1566
|
+
"--force",
|
|
1567
|
+
"--registry",
|
|
1568
|
+
registryUrl,
|
|
1569
|
+
`${asNonNull(pkg.json.name)}@${pkgVersion}`
|
|
1570
|
+
], {
|
|
1571
|
+
stdio: "inherit",
|
|
1572
|
+
env: npmEnv
|
|
1573
|
+
});
|
|
1574
|
+
else {
|
|
1575
|
+
info(`Skipping ${pkg.json.name}@${pkgVersion} because it is already published`);
|
|
1576
|
+
continue;
|
|
1577
|
+
}
|
|
1578
|
+
if (withBuild) if (pkg.json.scripts?.build !== void 0) {
|
|
1579
|
+
if ((await exec([
|
|
1580
|
+
"npm",
|
|
1581
|
+
"run",
|
|
1582
|
+
"build"
|
|
1583
|
+
], {
|
|
1584
|
+
cwd: join(pkg.path),
|
|
1585
|
+
stdio: "inherit"
|
|
1586
|
+
})).exitCode !== 0) {
|
|
1587
|
+
info(`failed to build ${pkg.json.name}`);
|
|
1588
|
+
failed.push(asNonNull(pkg.json.name));
|
|
1589
|
+
continue;
|
|
1590
|
+
}
|
|
1591
|
+
} else try {
|
|
1592
|
+
await buildPackage({
|
|
1593
|
+
workspaceRoot,
|
|
1594
|
+
workspace,
|
|
1595
|
+
packageName: asNonNull(pkg.json.name),
|
|
1596
|
+
fixedVersion
|
|
1597
|
+
});
|
|
1598
|
+
} catch (err) {
|
|
1599
|
+
info(`failed to build ${pkg.json.name}:`);
|
|
1600
|
+
error(err instanceof Error ? err : new Error(String(err)));
|
|
1601
|
+
failed.push(asNonNull(pkg.json.name));
|
|
1602
|
+
continue;
|
|
1603
|
+
}
|
|
1604
|
+
let fullDistDir = join(pkg.path, distDir);
|
|
1605
|
+
if (fixedVersion != null) {
|
|
1606
|
+
let distPkgJsonPath = join(fullDistDir, "package.json");
|
|
1607
|
+
let pkgJson = await parsePackageJsonFile(distPkgJsonPath);
|
|
1608
|
+
pkgJson.version = fixedVersion;
|
|
1609
|
+
await fsp.writeFile(distPkgJsonPath, JSON.stringify(pkgJson, null, 4));
|
|
1610
|
+
}
|
|
1611
|
+
info(`publishing ${pkg.json.name}@${pkgVersion}`);
|
|
1612
|
+
if (pkg.json.name?.includes("/")) {
|
|
1613
|
+
if (!publishArgs.some((it) => it.startsWith("--access"))) publishArgs.push("--access=public");
|
|
1614
|
+
}
|
|
1615
|
+
if ((await exec([
|
|
1616
|
+
"npm",
|
|
1617
|
+
...auth.extraArgs,
|
|
1618
|
+
"publish",
|
|
1619
|
+
"--registry",
|
|
1620
|
+
registryUrl,
|
|
1621
|
+
...dryRun ? ["--dry-run"] : ["-q"],
|
|
1622
|
+
...publishArgs
|
|
1623
|
+
], {
|
|
1624
|
+
cwd: fullDistDir,
|
|
1625
|
+
stdio: "inherit",
|
|
1626
|
+
env: npmEnv
|
|
1627
|
+
})).exitCode !== 0) failed.push(asNonNull(pkg.json.name));
|
|
1628
|
+
if (withTarballs) {
|
|
1629
|
+
let tar = await exec([
|
|
1630
|
+
"npm",
|
|
1631
|
+
"pack",
|
|
1632
|
+
"-q"
|
|
1633
|
+
], { cwd: fullDistDir });
|
|
1634
|
+
if (tar.exitCode !== 0) error(new Error(tar.stderr));
|
|
1635
|
+
else tarballs.push(join(fullDistDir, tar.stdout.trim()));
|
|
1636
|
+
}
|
|
1637
|
+
}
|
|
1638
|
+
return {
|
|
1639
|
+
failed,
|
|
1640
|
+
tarballs
|
|
1641
|
+
};
|
|
1642
|
+
} finally {
|
|
1643
|
+
await auth.cleanup();
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1646
|
+
var publishPackagesCli = command({
|
|
1647
|
+
name: "publish",
|
|
1648
|
+
desc: "publish packages to npm",
|
|
1649
|
+
options: {
|
|
1650
|
+
root: string().desc("path to the root of the workspace (default: cwd)"),
|
|
1651
|
+
unpublishExisting: boolean("unpublish-existing").desc("whether to unpublish if the version is already published (only available for certain registries, won't work with registry.npmjs.org)"),
|
|
1652
|
+
skipVersionCheck: boolean("skip-version-check").desc("whether to skip checking if the version is already published"),
|
|
1653
|
+
registryUrl: string("registry").desc("URL of the registry to publish to"),
|
|
1654
|
+
token: string("token").desc("token to use for publishing (passed via env and a temporary local .npmrc, never the global config)"),
|
|
1655
|
+
distDir: string("dist-dir").desc("directory to publish from, relative to package root (default: dist)"),
|
|
1656
|
+
dryRun: boolean("dry-run").desc("whether to skip publishing and only print what is going to happen"),
|
|
1657
|
+
publishArgs: string("publish-args").desc("arguments to pass to `npm publish`"),
|
|
1658
|
+
packages: positional("packages").desc("name of the packages to publish (comma-separated, or :all to publish the entire workspace)").default(":all"),
|
|
1659
|
+
withTarballs: boolean("with-tarballs").desc("whether to generate tarballs in the dist directory using `npm pack` (doesn't work with jsr)"),
|
|
1660
|
+
withBuild: boolean("with-build").desc("whether to build the package before publishing using `build` npm script (or defaulting to building using yorozu-build if one is not found)"),
|
|
1661
|
+
fixedVersion: string("fixed-version").desc("fixed version for every managed package (useful for pre-releases)"),
|
|
1662
|
+
noProvenance: boolean("no-provenance").desc("version to NOT use provenance even when it should be possible")
|
|
1663
|
+
},
|
|
1664
|
+
handler: async (options) => {
|
|
1665
|
+
let { failed, tarballs } = await publishPackages({
|
|
1666
|
+
...options,
|
|
1667
|
+
workspaceRoot: options.root != null ? resolve(process$1.cwd(), options.root) : getWorkspaceRoot(),
|
|
1668
|
+
packages: options.packages.split(","),
|
|
1669
|
+
publishArgs: options.publishArgs?.split(" ")
|
|
1670
|
+
});
|
|
1671
|
+
if (failed.length > 0) {
|
|
1672
|
+
info("failed to publish:");
|
|
1673
|
+
for (let pkg of failed) info(` ${pkg}`);
|
|
1674
|
+
process$1.exit(1);
|
|
1675
|
+
}
|
|
1676
|
+
if (tarballs.length > 0) if (isRunningInGithubActions()) {
|
|
1677
|
+
info("written paths to tarballs to `tarballs` output");
|
|
1678
|
+
writeGithubActionsOutput("tarballs", tarballs.join(","));
|
|
1679
|
+
} else {
|
|
1680
|
+
info("tarballs generated:");
|
|
1681
|
+
for (let tar of tarballs) info(` ${tar}`);
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
});
|
|
1685
|
+
//#endregion
|
|
1686
|
+
//#region src/cli/commands/docs.ts
|
|
1687
|
+
var CUSTOM_ROOT_FIELDS = ["includePackages", "excludePackages"];
|
|
1688
|
+
var DEFAULT_CONFIG = {
|
|
1689
|
+
includeVersion: true,
|
|
1690
|
+
validation: {
|
|
1691
|
+
notExported: true,
|
|
1692
|
+
invalidLink: true,
|
|
1693
|
+
notDocumented: false
|
|
1694
|
+
},
|
|
1695
|
+
excludePrivate: true,
|
|
1696
|
+
excludeExternals: true,
|
|
1697
|
+
excludeInternal: true,
|
|
1698
|
+
exclude: [
|
|
1699
|
+
"**/*/node_modules",
|
|
1700
|
+
"**/*.unit.ts",
|
|
1701
|
+
"**/*.test.ts",
|
|
1702
|
+
"**/*.test-utils.ts"
|
|
1703
|
+
]
|
|
1704
|
+
};
|
|
1705
|
+
var YorozuTypedocReader = class {
|
|
1706
|
+
name = "@yorozu/build";
|
|
1707
|
+
order = 0;
|
|
1708
|
+
supportsPackages = true;
|
|
1709
|
+
_workspace;
|
|
1710
|
+
_rootConfig;
|
|
1711
|
+
constructor(workspaceRoot) {
|
|
1712
|
+
this.workspaceRoot = workspaceRoot;
|
|
1713
|
+
}
|
|
1714
|
+
_forwardOptions(options, config, cwd) {
|
|
1715
|
+
for (let [key, val] of Object.entries(config)) {
|
|
1716
|
+
if (CUSTOM_ROOT_FIELDS.includes(key)) continue;
|
|
1717
|
+
options.setValue(key, val, cwd);
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1720
|
+
async read(options, _logger, cwd, _usedFile) {
|
|
1721
|
+
if (cwd === this.workspaceRoot) {
|
|
1722
|
+
let config = await loadBuildConfig(cwd);
|
|
1723
|
+
this._rootConfig = config;
|
|
1724
|
+
let data = config?.typedoc;
|
|
1725
|
+
if (data != null) this._forwardOptions(options, data, cwd);
|
|
1726
|
+
options.setValue("entryPointStrategy", "packages");
|
|
1727
|
+
this._workspace = await collectPackageJsons(cwd);
|
|
1728
|
+
let entrypoints = [];
|
|
1729
|
+
for (let pkg of this._workspace) {
|
|
1730
|
+
let pkgName = asNonNull(pkg.json.name);
|
|
1731
|
+
if (data?.includePackages && !data.includePackages.includes(pkgName)) continue;
|
|
1732
|
+
if (data?.excludePackages?.includes(pkgName)) continue;
|
|
1733
|
+
if (pkg.json.exports == null && !data?.includePackages?.includes(pkgName)) continue;
|
|
1734
|
+
entrypoints.push(pkg.path);
|
|
1735
|
+
}
|
|
1736
|
+
options.setValue("entryPoints", entrypoints, cwd);
|
|
1737
|
+
return;
|
|
1738
|
+
}
|
|
1739
|
+
let rootConfig = asNonNull(this._rootConfig);
|
|
1740
|
+
if (rootConfig.typedoc != null) this._forwardOptions(options, rootConfig.typedoc, cwd);
|
|
1741
|
+
let pkg = asNonNull(this._workspace?.find((item) => item.path.replace(/\/$/, "") === cwd.replace(/\/$/, "")));
|
|
1742
|
+
let pkgConfig = await loadBuildConfig(cwd);
|
|
1743
|
+
let hookContext = {
|
|
1744
|
+
outDir: "",
|
|
1745
|
+
packageDir: pkg.path,
|
|
1746
|
+
packageName: asNonNull(pkg.json.name),
|
|
1747
|
+
packageJson: pkg.json,
|
|
1748
|
+
jsr: false,
|
|
1749
|
+
typedoc: true
|
|
1750
|
+
};
|
|
1751
|
+
pkgConfig?.preparePackageJson?.(hookContext);
|
|
1752
|
+
let { entrypoints } = processPackageJson({
|
|
1753
|
+
packageJson: pkg.json,
|
|
1754
|
+
onlyEntrypoints: true
|
|
1755
|
+
});
|
|
1756
|
+
options.setValue("entryPoints", Object.values(Object.fromEntries(entrypoints)), cwd);
|
|
1757
|
+
if (!pkgConfig?.typedoc) return;
|
|
1758
|
+
let data = pkgConfig.typedoc;
|
|
1759
|
+
if (typeof data === "function") data = data(options.getRawValues());
|
|
1760
|
+
this._forwardOptions(options, data, cwd);
|
|
1761
|
+
}
|
|
1762
|
+
};
|
|
1763
|
+
async function generateDocs(params) {
|
|
1764
|
+
let app = await td.Application.bootstrapWithPlugins(DEFAULT_CONFIG, [
|
|
1765
|
+
new YorozuTypedocReader(params.workspaceRoot),
|
|
1766
|
+
new td.TSConfigReader(),
|
|
1767
|
+
new td.TypeDocReader()
|
|
1768
|
+
]);
|
|
1769
|
+
let project = await app.convert();
|
|
1770
|
+
if (!project) throw new Error("Could not convert to typedoc project");
|
|
1771
|
+
if (app.options.getValue("treatWarningsAsErrors") && app.logger.hasWarnings()) throw new Error("There were warnings while converting the project");
|
|
1772
|
+
let preValidationWarnCount = app.logger.warningCount;
|
|
1773
|
+
app.validate(project);
|
|
1774
|
+
let hadValidationWarnings = app.logger.warningCount !== preValidationWarnCount;
|
|
1775
|
+
if (app.logger.hasErrors()) throw new Error("There were errors while validating the project");
|
|
1776
|
+
if (hadValidationWarnings && (app.options.getValue("treatWarningsAsErrors") || app.options.getValue("treatValidationWarningsAsErrors"))) throw new Error("There were warnings while validating the project");
|
|
1777
|
+
if (app.options.getValue("emit") === "none") return;
|
|
1778
|
+
await app.generateOutputs(project);
|
|
1779
|
+
if (app.logger.hasErrors()) throw new Error("There were errors while generating the outputs");
|
|
1780
|
+
if (app.options.getValue("treatWarningsAsErrors") && app.logger.hasWarnings()) throw new Error("There were warnings while generating the outputs");
|
|
1781
|
+
}
|
|
1782
|
+
var generateDocsCli = command({
|
|
1783
|
+
name: "docs",
|
|
1784
|
+
desc: "generate docs using typedoc",
|
|
1785
|
+
options: { root: string().desc("path to the root of the workspace (default: cwd)") },
|
|
1786
|
+
handler: async (args) => {
|
|
1787
|
+
await generateDocs({ workspaceRoot: resolveWorkspaceRoot(args.root) });
|
|
1788
|
+
}
|
|
1789
|
+
});
|
|
1790
|
+
//#endregion
|
|
1791
|
+
//#region src/cli/commands/gen-deps-graph.ts
|
|
1792
|
+
async function generateDepsGraph(params) {
|
|
1793
|
+
let { workspaceRoot, includeRoot = false, includeExternal = false } = params;
|
|
1794
|
+
let pjs = await collectPackageJsons(workspaceRoot, includeRoot);
|
|
1795
|
+
let workspacePackages = /* @__PURE__ */ new Set();
|
|
1796
|
+
let commonPrefix;
|
|
1797
|
+
for (let { json: pj } of pjs) {
|
|
1798
|
+
if (pj.name === void 0) continue;
|
|
1799
|
+
workspacePackages.add(pj.name);
|
|
1800
|
+
let [org, name] = pj.name.split("/");
|
|
1801
|
+
if (!name) {
|
|
1802
|
+
commonPrefix = void 0;
|
|
1803
|
+
break;
|
|
1804
|
+
}
|
|
1805
|
+
if (commonPrefix === void 0) commonPrefix = org;
|
|
1806
|
+
else if (commonPrefix !== org) {
|
|
1807
|
+
commonPrefix = void 0;
|
|
1808
|
+
break;
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
const getName = (name) => {
|
|
1812
|
+
if (commonPrefix !== void 0) {
|
|
1813
|
+
let [org, pkg] = name.split("/");
|
|
1814
|
+
if (org === commonPrefix) return pkg;
|
|
1815
|
+
}
|
|
1816
|
+
return name;
|
|
1817
|
+
};
|
|
1818
|
+
let lines = [];
|
|
1819
|
+
for (let { json: pj } of pjs) {
|
|
1820
|
+
if (pj.name === void 0) continue;
|
|
1821
|
+
let name = getName(pj.name);
|
|
1822
|
+
for (let dep of Object.keys(pj.dependencies || {})) {
|
|
1823
|
+
if (!workspacePackages.has(dep) && !includeExternal) continue;
|
|
1824
|
+
lines.push(`"${name}" -> "${getName(dep)}"`);
|
|
1825
|
+
}
|
|
1826
|
+
for (let dep of Object.keys(pj.devDependencies || {})) {
|
|
1827
|
+
if (!workspacePackages.has(dep) && !includeExternal) continue;
|
|
1828
|
+
lines.push(`"${name}" -> "${getName(dep)}" [style=dashed,color=grey]`);
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
1831
|
+
return `digraph {\n${lines.join("\n")}\n}`;
|
|
1832
|
+
}
|
|
1833
|
+
var generateDepsGraphCli = command({
|
|
1834
|
+
name: "gen-deps-graph",
|
|
1835
|
+
desc: "generate a graphviz dot file of the workspace dependencies",
|
|
1836
|
+
options: {
|
|
1837
|
+
includeRoot: boolean("include-root").desc("whether to include the root package.json in the graph"),
|
|
1838
|
+
includeExternal: boolean("include-external").desc("whether to include external dependencies in the graph"),
|
|
1839
|
+
root: string().desc("path to the root of the workspace (default: cwd)")
|
|
1840
|
+
},
|
|
1841
|
+
handler: async (args) => {
|
|
1842
|
+
info(await generateDepsGraph({
|
|
1843
|
+
workspaceRoot: resolveWorkspaceRoot(args.root),
|
|
1844
|
+
includeRoot: args.includeRoot,
|
|
1845
|
+
includeExternal: args.includeExternal
|
|
1846
|
+
}));
|
|
1847
|
+
}
|
|
1848
|
+
});
|
|
1849
|
+
//#endregion
|
|
1850
|
+
//#region src/git/utils.ts
|
|
1851
|
+
var CONVENTIONAL_COMMIT_RE = /^(\w+)(?:\(([^)]+)\))?(!?): (.+)$/;
|
|
1852
|
+
var BREAKING_CHANGE_RE = /^BREAKING[- ]CHANGE:/;
|
|
1853
|
+
async function getLatestTag(cwd) {
|
|
1854
|
+
let res = await exec([
|
|
1855
|
+
"git",
|
|
1856
|
+
"describe",
|
|
1857
|
+
"--abbrev=0",
|
|
1858
|
+
"--tags"
|
|
1859
|
+
], { cwd });
|
|
1860
|
+
if (res.exitCode !== 0) {
|
|
1861
|
+
if (res.stderr.match(/^fatal: (?:No names found|No tags can describe)/i)) return null;
|
|
1862
|
+
throw new Error(`git describe failed: ${res.stderr}`);
|
|
1863
|
+
}
|
|
1864
|
+
return res.stdout.trim();
|
|
1865
|
+
}
|
|
1866
|
+
async function getFirstCommit(cwd) {
|
|
1867
|
+
return (await exec([
|
|
1868
|
+
"git",
|
|
1869
|
+
"rev-list",
|
|
1870
|
+
"--max-parents=0",
|
|
1871
|
+
"HEAD"
|
|
1872
|
+
], {
|
|
1873
|
+
cwd,
|
|
1874
|
+
throwOnError: true
|
|
1875
|
+
})).stdout.trim();
|
|
1876
|
+
}
|
|
1877
|
+
async function getCurrentCommit(cwd) {
|
|
1878
|
+
return (await exec([
|
|
1879
|
+
"git",
|
|
1880
|
+
"rev-parse",
|
|
1881
|
+
"HEAD"
|
|
1882
|
+
], {
|
|
1883
|
+
cwd,
|
|
1884
|
+
throwOnError: true
|
|
1885
|
+
})).stdout.trim();
|
|
1886
|
+
}
|
|
1887
|
+
async function getCurrentBranch(cwd) {
|
|
1888
|
+
return (await exec([
|
|
1889
|
+
"git",
|
|
1890
|
+
"rev-parse",
|
|
1891
|
+
"--abbrev-ref",
|
|
1892
|
+
"HEAD"
|
|
1893
|
+
], {
|
|
1894
|
+
cwd,
|
|
1895
|
+
throwOnError: true
|
|
1896
|
+
})).stdout.trim();
|
|
1897
|
+
}
|
|
1898
|
+
async function gitTagExists(tag, cwd) {
|
|
1899
|
+
return (await exec([
|
|
1900
|
+
"git",
|
|
1901
|
+
"tag",
|
|
1902
|
+
"--list",
|
|
1903
|
+
tag
|
|
1904
|
+
], {
|
|
1905
|
+
cwd,
|
|
1906
|
+
throwOnError: true
|
|
1907
|
+
})).stdout.trim() !== "";
|
|
1908
|
+
}
|
|
1909
|
+
async function findChangedFiles(params) {
|
|
1910
|
+
let { since, until = "HEAD", cwd } = params;
|
|
1911
|
+
let files = (await exec([
|
|
1912
|
+
"git",
|
|
1913
|
+
"diff",
|
|
1914
|
+
"--name-only",
|
|
1915
|
+
since,
|
|
1916
|
+
until
|
|
1917
|
+
], {
|
|
1918
|
+
cwd,
|
|
1919
|
+
throwOnError: true
|
|
1920
|
+
})).stdout.trim().split("\n");
|
|
1921
|
+
if (files.length === 1 && files[0] === "") return [];
|
|
1922
|
+
return files;
|
|
1923
|
+
}
|
|
1924
|
+
async function getCommitsBetween(params) {
|
|
1925
|
+
let { since, until = "HEAD", cwd, files } = params;
|
|
1926
|
+
let delim = `---${randomUUID()}---`;
|
|
1927
|
+
let lines = (await exec([
|
|
1928
|
+
"git",
|
|
1929
|
+
"log",
|
|
1930
|
+
`--pretty=format:%H %s%n%an%n%ae%n%aI%n%cn%n%ce%n%cI%n%b%n${delim}`,
|
|
1931
|
+
since != null ? `${since}..${until}` : until,
|
|
1932
|
+
...files?.length ? ["--", ...files] : []
|
|
1933
|
+
], {
|
|
1934
|
+
cwd,
|
|
1935
|
+
throwOnError: true
|
|
1936
|
+
})).stdout.trim().split("\n");
|
|
1937
|
+
if (lines.length === 1 && lines[0] === "") return [];
|
|
1938
|
+
let items = [];
|
|
1939
|
+
let current = null;
|
|
1940
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1941
|
+
let line = lines[i];
|
|
1942
|
+
if (line === delim) {
|
|
1943
|
+
if (current) items.push(current);
|
|
1944
|
+
current = null;
|
|
1945
|
+
} else if (current) {
|
|
1946
|
+
if (current.description) current.description += "\n";
|
|
1947
|
+
current.description += line;
|
|
1948
|
+
} else {
|
|
1949
|
+
let [hash, ...msg] = line.split(" ");
|
|
1950
|
+
let authorName = lines[++i];
|
|
1951
|
+
let authorEmail = lines[++i];
|
|
1952
|
+
let authorDate = lines[++i];
|
|
1953
|
+
let committerName = lines[++i];
|
|
1954
|
+
let committerEmail = lines[++i];
|
|
1955
|
+
let committerDate = lines[++i];
|
|
1956
|
+
current = {
|
|
1957
|
+
hash,
|
|
1958
|
+
author: {
|
|
1959
|
+
name: authorName,
|
|
1960
|
+
email: authorEmail,
|
|
1961
|
+
date: new Date(authorDate)
|
|
1962
|
+
},
|
|
1963
|
+
committer: {
|
|
1964
|
+
name: committerName,
|
|
1965
|
+
email: committerEmail,
|
|
1966
|
+
date: new Date(committerDate)
|
|
1967
|
+
},
|
|
1968
|
+
message: msg.join(" "),
|
|
1969
|
+
description: ""
|
|
1970
|
+
};
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
if (current) items.push(current);
|
|
1974
|
+
return items.reverse();
|
|
1975
|
+
}
|
|
1976
|
+
function parseConventionalCommit(msg) {
|
|
1977
|
+
let [header, ...rest] = msg.split("\n");
|
|
1978
|
+
let match = header.match(CONVENTIONAL_COMMIT_RE);
|
|
1979
|
+
if (!match) return null;
|
|
1980
|
+
let [, type, scope, bang, subject] = match;
|
|
1981
|
+
let footerBreaking = rest.some((line) => BREAKING_CHANGE_RE.test(line.trim()));
|
|
1982
|
+
return {
|
|
1983
|
+
type,
|
|
1984
|
+
...scope ? { scope } : {},
|
|
1985
|
+
breaking: Boolean(bang) || footerBreaking,
|
|
1986
|
+
subject
|
|
1987
|
+
};
|
|
1988
|
+
}
|
|
1989
|
+
//#endregion
|
|
1990
|
+
//#region src/misc/tsconfig.ts
|
|
1991
|
+
var import_picomatch = /* @__PURE__ */ __toESM$1(require_picomatch(), 1);
|
|
1992
|
+
var tsconfigFilesCache = new LruMap(32);
|
|
1993
|
+
async function getTsconfigFor(cwd) {
|
|
1994
|
+
let res = await exec([
|
|
1995
|
+
"npx",
|
|
1996
|
+
"tsc",
|
|
1997
|
+
"--showConfig"
|
|
1998
|
+
], {
|
|
1999
|
+
cwd,
|
|
2000
|
+
throwOnError: true
|
|
2001
|
+
});
|
|
2002
|
+
return JSON.parse(res.stdout);
|
|
2003
|
+
}
|
|
2004
|
+
async function getTsconfigFiles(cwd) {
|
|
2005
|
+
let cached = tsconfigFilesCache.get(cwd);
|
|
2006
|
+
if (cached) return cached;
|
|
2007
|
+
let config = await getTsconfigFor(cwd);
|
|
2008
|
+
if (typeof config !== "object" || config === null) throw new Error("tsconfig.json is not an object");
|
|
2009
|
+
if (!("files" in config) || !Array.isArray(config.files)) throw new Error("tsconfig.json > .files is not an array");
|
|
2010
|
+
let files = config.files.map((file) => file.replace(/^\.\//, ""));
|
|
2011
|
+
tsconfigFilesCache.set(cwd, files);
|
|
2012
|
+
return files;
|
|
2013
|
+
}
|
|
2014
|
+
//#endregion
|
|
2015
|
+
//#region src/versioning/collect-files.ts
|
|
2016
|
+
var DEFAULT_EXCLUDE = ["**/*.unit.ts", "**/*.md"];
|
|
2017
|
+
async function defaultShouldInclude(file) {
|
|
2018
|
+
if (!file.file.endsWith(".ts")) return true;
|
|
2019
|
+
try {
|
|
2020
|
+
return (await getTsconfigFiles(join(file.root, file.package.path))).includes(file.file);
|
|
2021
|
+
} catch {
|
|
2022
|
+
return true;
|
|
2023
|
+
}
|
|
2024
|
+
}
|
|
2025
|
+
function fileBelongsToPackage(file, pkgPath) {
|
|
2026
|
+
if (pkgPath === "" || pkgPath === ".") return true;
|
|
2027
|
+
return file === pkgPath || file.startsWith(`${pkgPath}/`);
|
|
2028
|
+
}
|
|
2029
|
+
async function findProjectChangedFiles(params) {
|
|
2030
|
+
let { params: { include, exclude = DEFAULT_EXCLUDE, shouldInclude = defaultShouldInclude } = {}, root: rootInput = process$1.cwd(), since, until } = params;
|
|
2031
|
+
let root = normalizeFilePath(rootInput);
|
|
2032
|
+
let changed = await findChangedFiles({
|
|
2033
|
+
since,
|
|
2034
|
+
until,
|
|
2035
|
+
cwd: root
|
|
2036
|
+
});
|
|
2037
|
+
if (!changed.length) return [];
|
|
2038
|
+
let packages = (params.workspace ?? await collectPackageJsons(root)).filter((pkg) => !pkg.root).map((pkg) => ({
|
|
2039
|
+
pkg,
|
|
2040
|
+
relPath: relative(root, pkg.path)
|
|
2041
|
+
})).sort((a, b) => b.relPath.length - a.relPath.length);
|
|
2042
|
+
let files = [];
|
|
2043
|
+
let includeGlobs = include == null ? null : (0, import_picomatch.default)(include);
|
|
2044
|
+
let excludeGlobs = exclude == null ? null : (0, import_picomatch.default)(exclude);
|
|
2045
|
+
for (let file of changed) {
|
|
2046
|
+
let match = packages.find((item) => fileBelongsToPackage(file, item.relPath));
|
|
2047
|
+
if (!match) continue;
|
|
2048
|
+
let relPath = relative(match.relPath, file);
|
|
2049
|
+
if (includeGlobs != null && !includeGlobs(relPath)) continue;
|
|
2050
|
+
if (excludeGlobs != null && excludeGlobs(relPath)) continue;
|
|
2051
|
+
let info = {
|
|
2052
|
+
file: relPath,
|
|
2053
|
+
package: match.pkg,
|
|
2054
|
+
root
|
|
2055
|
+
};
|
|
2056
|
+
if (!await shouldInclude(info)) continue;
|
|
2057
|
+
files.push(info);
|
|
2058
|
+
}
|
|
2059
|
+
return files;
|
|
2060
|
+
}
|
|
2061
|
+
async function findProjectChangedPackages(params) {
|
|
2062
|
+
let files = await findProjectChangedFiles(params);
|
|
2063
|
+
let set = /* @__PURE__ */ new Set();
|
|
2064
|
+
for (let file of files) set.add(file.package);
|
|
2065
|
+
return Array.from(set);
|
|
2066
|
+
}
|
|
2067
|
+
//#endregion
|
|
2068
|
+
//#region src/cli/commands/cr.ts
|
|
2069
|
+
function selectChangedNpmPackages(params) {
|
|
2070
|
+
let { publishable, changed } = params;
|
|
2071
|
+
let selected = [...changed];
|
|
2072
|
+
let selectedNames = /* @__PURE__ */ new Set();
|
|
2073
|
+
for (let pkg of selected) selectedNames.add(asNonNull(pkg.json.name));
|
|
2074
|
+
let hadChanges = true;
|
|
2075
|
+
while (hadChanges) {
|
|
2076
|
+
hadChanges = false;
|
|
2077
|
+
for (let pkg of publishable) {
|
|
2078
|
+
let pkgName = asNonNull(pkg.json.name);
|
|
2079
|
+
for (let field of ["dependencies", "peerDependencies"]) {
|
|
2080
|
+
let deps = pkg.json[field];
|
|
2081
|
+
if (deps == null) continue;
|
|
2082
|
+
for (let name of Object.keys(deps)) if (selectedNames.has(name) && !selectedNames.has(pkgName)) {
|
|
2083
|
+
hadChanges = true;
|
|
2084
|
+
selected.push(pkg);
|
|
2085
|
+
selectedNames.add(pkgName);
|
|
2086
|
+
break;
|
|
2087
|
+
}
|
|
2088
|
+
}
|
|
2089
|
+
}
|
|
2090
|
+
}
|
|
2091
|
+
return filterPackageJsonsForPublish(selected, "npm");
|
|
2092
|
+
}
|
|
2093
|
+
async function runContinuousRelease(params) {
|
|
2094
|
+
let { workspaceRoot = resolveWorkspaceRoot(), workspace = await collectPackageJsons(workspaceRoot, true), distDir = "dist", extraArgs = [], onlyChanged = false, onlyChangedSince } = params;
|
|
2095
|
+
let workspaceWithoutRoot = workspace.filter((pkg) => !pkg.root);
|
|
2096
|
+
let packages = filterPackageJsonsForPublish(workspaceWithoutRoot, "npm");
|
|
2097
|
+
if (onlyChanged) {
|
|
2098
|
+
let config = await loadConfig({
|
|
2099
|
+
workspaceRoot,
|
|
2100
|
+
require: false
|
|
2101
|
+
});
|
|
2102
|
+
let since = onlyChangedSince ?? await getLatestTag(workspaceRoot);
|
|
2103
|
+
if (since == null) throw new Error("no previous tag found, cannot determine changeset");
|
|
2104
|
+
let changedPackages = await findProjectChangedPackages({
|
|
2105
|
+
params: config?.versioning,
|
|
2106
|
+
workspace: workspaceWithoutRoot,
|
|
2107
|
+
root: workspaceRoot,
|
|
2108
|
+
since
|
|
2109
|
+
});
|
|
2110
|
+
if (!changedPackages.length) {
|
|
2111
|
+
info(`no packages changed since ${since}, nothing to do`);
|
|
2112
|
+
return;
|
|
2113
|
+
}
|
|
2114
|
+
packages = selectChangedNpmPackages({
|
|
2115
|
+
publishable: packages,
|
|
2116
|
+
changed: changedPackages
|
|
2117
|
+
});
|
|
2118
|
+
if (!packages.length) {
|
|
2119
|
+
info(`no packages changed since ${since}, nothing to do`);
|
|
2120
|
+
return;
|
|
2121
|
+
}
|
|
2122
|
+
info(`only publishing changed packages since ${since}:`);
|
|
2123
|
+
for (let pkg of packages) info(` - ${pkg.json.name}`);
|
|
2124
|
+
}
|
|
2125
|
+
if (!isRunningInGithubActions()) throw new Error("cr command is only supported in github actions");
|
|
2126
|
+
let distPaths = [];
|
|
2127
|
+
for (let pkg of packages) {
|
|
2128
|
+
if (pkg.json.scripts?.build !== void 0) await exec([
|
|
2129
|
+
"npm",
|
|
2130
|
+
"run",
|
|
2131
|
+
"build"
|
|
2132
|
+
], {
|
|
2133
|
+
cwd: join(pkg.path),
|
|
2134
|
+
stdio: "inherit",
|
|
2135
|
+
throwOnError: true
|
|
2136
|
+
});
|
|
2137
|
+
else await buildPackage({
|
|
2138
|
+
workspaceRoot,
|
|
2139
|
+
workspace,
|
|
2140
|
+
packageName: asNonNull(pkg.json.name)
|
|
2141
|
+
});
|
|
2142
|
+
distPaths.push(join(pkg.path, distDir));
|
|
2143
|
+
}
|
|
2144
|
+
if (extraArgs.some((item) => item.startsWith("--pnpm"))) warn("`--pnpm` flag is not supported and may cause issues, please avoid using it");
|
|
2145
|
+
await exec([
|
|
2146
|
+
"npx",
|
|
2147
|
+
"pkg-pr-new",
|
|
2148
|
+
"publish",
|
|
2149
|
+
...extraArgs,
|
|
2150
|
+
...distPaths
|
|
2151
|
+
], {
|
|
2152
|
+
cwd: workspaceRoot,
|
|
2153
|
+
throwOnError: true,
|
|
2154
|
+
stdio: "inherit"
|
|
2155
|
+
});
|
|
2156
|
+
}
|
|
2157
|
+
var runContinuousReleaseCli = command({
|
|
2158
|
+
name: "cr",
|
|
2159
|
+
desc: "publish the workspace to pkg.pr.new",
|
|
2160
|
+
options: {
|
|
2161
|
+
root: string().desc("path to the root of the workspace (default: cwd)"),
|
|
2162
|
+
distDir: string("dist-dir").desc("directory to publish from, relative to package root (default: dist)"),
|
|
2163
|
+
extraArgs: string("extra-args").desc("extra arguments to pass to pkg-pr-new"),
|
|
2164
|
+
onlyChanged: boolean("only-changed").desc("whether to only publish packages changed since the last release.").default(false),
|
|
2165
|
+
onlyChangedSince: string("only-changed-since").desc("starting point for the changelog (defaults to latest tag)")
|
|
2166
|
+
},
|
|
2167
|
+
transform: (args) => {
|
|
2168
|
+
return {
|
|
2169
|
+
workspaceRoot: resolveWorkspaceRoot(args.root),
|
|
2170
|
+
distDir: args.distDir,
|
|
2171
|
+
extraArgs: args.extraArgs?.split(" "),
|
|
2172
|
+
onlyChanged: args.onlyChanged,
|
|
2173
|
+
onlyChangedSince: args.onlyChangedSince
|
|
2174
|
+
};
|
|
2175
|
+
},
|
|
2176
|
+
handler: runContinuousRelease
|
|
2177
|
+
});
|
|
2178
|
+
//#endregion
|
|
2179
|
+
//#region src/cli/commands/lint/validate-workspace-deps.ts
|
|
2180
|
+
var import_semver = /* @__PURE__ */ __toESM$1(require_semver(), 1);
|
|
2181
|
+
var DEP_FIELDS = [
|
|
2182
|
+
"dependencies",
|
|
2183
|
+
"devDependencies",
|
|
2184
|
+
"peerDependencies",
|
|
2185
|
+
"optionalDependencies"
|
|
2186
|
+
];
|
|
2187
|
+
function versionsCompatible(version, otherVersion) {
|
|
2188
|
+
if (otherVersion.match(/^(?:https?:\/\/|catalog:)/)) return version === otherVersion;
|
|
2189
|
+
if ((0, import_semver.valid)(version) != null) return (0, import_semver.satisfies)(version, otherVersion);
|
|
2190
|
+
if ((0, import_semver.validRange)(version) != null) return (0, import_semver.subset)(otherVersion, version);
|
|
2191
|
+
return version === otherVersion;
|
|
2192
|
+
}
|
|
2193
|
+
async function validateWorkspaceDeps(params) {
|
|
2194
|
+
let { workspaceRoot, config: { includeRoot, externalDependencies: { enabled: externalDependenciesEnabled = true, skipPeerDependencies: externalDependenciesSkipPeerDependencies = false, shouldSkip: externalDependenciesShouldSkip } = {} } = {} } = params;
|
|
2195
|
+
let packages = params.packages ?? await collectPackageJsons(workspaceRoot, includeRoot);
|
|
2196
|
+
let packagesMap = new Map(packages.map((pkg) => [pkg.json.name, pkg]));
|
|
2197
|
+
let versions = {};
|
|
2198
|
+
let errors = [];
|
|
2199
|
+
for (let pkg of packages) {
|
|
2200
|
+
let pj = pkg.json;
|
|
2201
|
+
if (pj.name === void 0) throw new Error("package.json without name is not supported");
|
|
2202
|
+
for (let field of DEP_FIELDS) {
|
|
2203
|
+
let deps = pj[field];
|
|
2204
|
+
if (!deps) continue;
|
|
2205
|
+
for (let [name, version] of Object.entries(deps)) {
|
|
2206
|
+
if (packagesMap.has(name)) {
|
|
2207
|
+
let otherPkg = packagesMap.get(name);
|
|
2208
|
+
if (!Boolean(otherPkg?.json.yorozu?.standalone) && !version.startsWith("workspace:")) errors.push({
|
|
2209
|
+
type: "internal",
|
|
2210
|
+
package: pj.name,
|
|
2211
|
+
dependency: name,
|
|
2212
|
+
subtype: "not_workspace_proto"
|
|
2213
|
+
});
|
|
2214
|
+
continue;
|
|
2215
|
+
}
|
|
2216
|
+
if (version.startsWith("workspace:")) {
|
|
2217
|
+
errors.push({
|
|
2218
|
+
type: "internal",
|
|
2219
|
+
package: pj.name,
|
|
2220
|
+
dependency: name,
|
|
2221
|
+
subtype: "not_workspace_dep"
|
|
2222
|
+
});
|
|
2223
|
+
continue;
|
|
2224
|
+
}
|
|
2225
|
+
if (!externalDependenciesEnabled) continue;
|
|
2226
|
+
if (field === "peerDependencies" && externalDependenciesSkipPeerDependencies) continue;
|
|
2227
|
+
if (externalDependenciesShouldSkip?.({
|
|
2228
|
+
package: pkg,
|
|
2229
|
+
dependency: name,
|
|
2230
|
+
version,
|
|
2231
|
+
field
|
|
2232
|
+
})) continue;
|
|
2233
|
+
if (versions[name] === void 0) versions[name] = {};
|
|
2234
|
+
for (let [pkgName, pkgDepVersion] of Object.entries(versions[name])) if (!versionsCompatible(version, pkgDepVersion)) errors.push({
|
|
2235
|
+
type: "external",
|
|
2236
|
+
package: pj.name,
|
|
2237
|
+
dependency: name,
|
|
2238
|
+
version,
|
|
2239
|
+
at: field,
|
|
2240
|
+
otherPackage: pkgName,
|
|
2241
|
+
otherVersion: pkgDepVersion
|
|
2242
|
+
});
|
|
2243
|
+
versions[name][pj.name] = version;
|
|
2244
|
+
}
|
|
2245
|
+
}
|
|
2246
|
+
}
|
|
2247
|
+
return errors;
|
|
2248
|
+
}
|
|
2249
|
+
//#endregion
|
|
2250
|
+
//#region src/git/github.ts
|
|
2251
|
+
var USER_AGENT = "@yorozu/build";
|
|
2252
|
+
var GITHUB_API_VERSION = "2022-11-28";
|
|
2253
|
+
var DEFAULT_API_URL = "https://api.github.com";
|
|
2254
|
+
var REQUEST_TIMEOUT_MS = 3e4;
|
|
2255
|
+
var UPLOAD_TIMEOUT_MS = 6e4;
|
|
2256
|
+
var ReleaseResponseSchema = object({
|
|
2257
|
+
id: number(),
|
|
2258
|
+
upload_url: string$1()
|
|
2259
|
+
});
|
|
2260
|
+
function toBodyInit(body) {
|
|
2261
|
+
return body;
|
|
2262
|
+
}
|
|
2263
|
+
function githubHeaders(token, extra) {
|
|
2264
|
+
return {
|
|
2265
|
+
Accept: "application/vnd.github+json",
|
|
2266
|
+
"User-Agent": USER_AGENT,
|
|
2267
|
+
"X-GitHub-Api-Version": GITHUB_API_VERSION,
|
|
2268
|
+
Authorization: `Bearer ${token}`,
|
|
2269
|
+
...extra
|
|
2270
|
+
};
|
|
2271
|
+
}
|
|
2272
|
+
async function readErrorBody(res) {
|
|
2273
|
+
try {
|
|
2274
|
+
return await res.text();
|
|
2275
|
+
} catch {
|
|
2276
|
+
return "";
|
|
2277
|
+
}
|
|
2278
|
+
}
|
|
2279
|
+
async function createGithubRelease(params) {
|
|
2280
|
+
let apiUrl = (params.apiUrl ?? DEFAULT_API_URL).replace(/\/$/, "");
|
|
2281
|
+
let res = await fetch(`${apiUrl}/repos/${params.repo}/releases`, {
|
|
2282
|
+
method: "POST",
|
|
2283
|
+
headers: githubHeaders(params.token, { "Content-Type": "application/json" }),
|
|
2284
|
+
body: JSON.stringify({
|
|
2285
|
+
tag_name: params.tag,
|
|
2286
|
+
name: params.name,
|
|
2287
|
+
body: params.body,
|
|
2288
|
+
draft: params.draft ?? false,
|
|
2289
|
+
prerelease: params.prerelease ?? false
|
|
2290
|
+
}),
|
|
2291
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
2292
|
+
});
|
|
2293
|
+
if (res.status !== 201) throw new Error(`GitHub release request failed with ${res.status}: ${await readErrorBody(res)}`);
|
|
2294
|
+
let release = ReleaseResponseSchema.parse(await res.json());
|
|
2295
|
+
let uploadUrl = release.upload_url.split("{")[0];
|
|
2296
|
+
if (params.artifacts != null && params.artifacts.length > 0) await asyncPool(params.artifacts, async (file) => {
|
|
2297
|
+
let url = new URL(uploadUrl);
|
|
2298
|
+
url.searchParams.set("name", file.name);
|
|
2299
|
+
let upload = await fetch(url, {
|
|
2300
|
+
method: "POST",
|
|
2301
|
+
headers: githubHeaders(params.token, {
|
|
2302
|
+
"Content-Type": file.type,
|
|
2303
|
+
"Content-Length": String(file.body.byteLength)
|
|
2304
|
+
}),
|
|
2305
|
+
body: toBodyInit(file.body),
|
|
2306
|
+
signal: AbortSignal.timeout(UPLOAD_TIMEOUT_MS)
|
|
2307
|
+
});
|
|
2308
|
+
if (upload.status !== 201) throw new Error(`failed to upload artifact: ${file.name}: GitHub artifact upload failed with ${upload.status}: ${await readErrorBody(upload)}`);
|
|
2309
|
+
});
|
|
2310
|
+
return release.id;
|
|
2311
|
+
}
|
|
2312
|
+
//#endregion
|
|
2313
|
+
//#region ../../node_modules/.pnpm/detect-indent@7.0.2/node_modules/detect-indent/index.js
|
|
2314
|
+
var INDENT_REGEX = /^(?:( )+|\t+)/;
|
|
2315
|
+
var INDENT_TYPE_SPACE = "space";
|
|
2316
|
+
var INDENT_TYPE_TAB = "tab";
|
|
2317
|
+
function shouldIgnoreSingleSpace(ignoreSingleSpaces, indentType, value) {
|
|
2318
|
+
return ignoreSingleSpaces && indentType === INDENT_TYPE_SPACE && value === 1;
|
|
2319
|
+
}
|
|
2320
|
+
/**
|
|
2321
|
+
Make a Map that counts how many indents/unindents have occurred for a given size and how many lines follow a given indentation.
|
|
2322
|
+
|
|
2323
|
+
The key is a concatenation of the indentation type (s = space and t = tab) and the size of the indents/unindents.
|
|
2324
|
+
|
|
2325
|
+
```
|
|
2326
|
+
indents = {
|
|
2327
|
+
t3: [1, 0],
|
|
2328
|
+
t4: [1, 5],
|
|
2329
|
+
s5: [1, 0],
|
|
2330
|
+
s12: [1, 0],
|
|
2331
|
+
}
|
|
2332
|
+
```
|
|
2333
|
+
*/
|
|
2334
|
+
function makeIndentsMap(string, ignoreSingleSpaces) {
|
|
2335
|
+
const indents = /* @__PURE__ */ new Map();
|
|
2336
|
+
let previousSize = 0;
|
|
2337
|
+
let previousIndentType;
|
|
2338
|
+
let key;
|
|
2339
|
+
for (const line of string.split(/\n/g)) {
|
|
2340
|
+
if (!line) continue;
|
|
2341
|
+
const matches = line.match(INDENT_REGEX);
|
|
2342
|
+
if (matches === null) {
|
|
2343
|
+
previousSize = 0;
|
|
2344
|
+
previousIndentType = "";
|
|
2345
|
+
} else {
|
|
2346
|
+
const indent = matches[0].length;
|
|
2347
|
+
const indentType = matches[1] ? INDENT_TYPE_SPACE : INDENT_TYPE_TAB;
|
|
2348
|
+
if (shouldIgnoreSingleSpace(ignoreSingleSpaces, indentType, indent)) continue;
|
|
2349
|
+
if (indentType !== previousIndentType) previousSize = 0;
|
|
2350
|
+
previousIndentType = indentType;
|
|
2351
|
+
let use = 1;
|
|
2352
|
+
let weight = 0;
|
|
2353
|
+
const indentDifference = indent - previousSize;
|
|
2354
|
+
previousSize = indent;
|
|
2355
|
+
if (indentDifference === 0) {
|
|
2356
|
+
use = 0;
|
|
2357
|
+
weight = 1;
|
|
2358
|
+
} else {
|
|
2359
|
+
const absoluteIndentDifference = Math.abs(indentDifference);
|
|
2360
|
+
if (shouldIgnoreSingleSpace(ignoreSingleSpaces, indentType, absoluteIndentDifference)) continue;
|
|
2361
|
+
key = encodeIndentsKey(indentType, absoluteIndentDifference);
|
|
2362
|
+
}
|
|
2363
|
+
const entry = indents.get(key);
|
|
2364
|
+
indents.set(key, entry === void 0 ? [1, 0] : [entry[0] + use, entry[1] + weight]);
|
|
2365
|
+
}
|
|
2366
|
+
}
|
|
2367
|
+
return indents;
|
|
2368
|
+
}
|
|
2369
|
+
function encodeIndentsKey(indentType, indentAmount) {
|
|
2370
|
+
return (indentType === INDENT_TYPE_SPACE ? "s" : "t") + String(indentAmount);
|
|
2371
|
+
}
|
|
2372
|
+
function decodeIndentsKey(indentsKey) {
|
|
2373
|
+
return {
|
|
2374
|
+
type: indentsKey[0] === "s" ? INDENT_TYPE_SPACE : INDENT_TYPE_TAB,
|
|
2375
|
+
amount: Number(indentsKey.slice(1))
|
|
2376
|
+
};
|
|
2377
|
+
}
|
|
2378
|
+
function getMostUsedKey(indents) {
|
|
2379
|
+
let result;
|
|
2380
|
+
let maxUsed = 0;
|
|
2381
|
+
let maxWeight = 0;
|
|
2382
|
+
for (const [key, [usedCount, weight]] of indents) if (usedCount > maxUsed || usedCount === maxUsed && weight > maxWeight) {
|
|
2383
|
+
maxUsed = usedCount;
|
|
2384
|
+
maxWeight = weight;
|
|
2385
|
+
result = key;
|
|
2386
|
+
}
|
|
2387
|
+
return result;
|
|
2388
|
+
}
|
|
2389
|
+
function makeIndentString(type, amount) {
|
|
2390
|
+
return (type === INDENT_TYPE_SPACE ? " " : " ").repeat(amount);
|
|
2391
|
+
}
|
|
2392
|
+
function detectIndent(string) {
|
|
2393
|
+
if (typeof string !== "string") throw new TypeError("Expected a string");
|
|
2394
|
+
let indents = makeIndentsMap(string, true);
|
|
2395
|
+
if (indents.size === 0) indents = makeIndentsMap(string, false);
|
|
2396
|
+
const keyOfMostUsedIndent = getMostUsedKey(indents);
|
|
2397
|
+
let type;
|
|
2398
|
+
let amount = 0;
|
|
2399
|
+
let indent = "";
|
|
2400
|
+
if (keyOfMostUsedIndent !== void 0) {
|
|
2401
|
+
({type, amount} = decodeIndentsKey(keyOfMostUsedIndent));
|
|
2402
|
+
indent = makeIndentString(type, amount);
|
|
2403
|
+
}
|
|
2404
|
+
return {
|
|
2405
|
+
amount,
|
|
2406
|
+
type,
|
|
2407
|
+
indent
|
|
2408
|
+
};
|
|
2409
|
+
}
|
|
2410
|
+
//#endregion
|
|
2411
|
+
//#region src/versioning/bump-version.ts
|
|
2412
|
+
function isOwnVersioning(pkg) {
|
|
2413
|
+
return Boolean(pkg.json.yorozu?.ownVersioning);
|
|
2414
|
+
}
|
|
2415
|
+
function isStandalone(pkg) {
|
|
2416
|
+
return Boolean(pkg.json.yorozu?.standalone);
|
|
2417
|
+
}
|
|
2418
|
+
function isManaged(pkg) {
|
|
2419
|
+
return !pkg.root && !isOwnVersioning(pkg) && !isStandalone(pkg);
|
|
2420
|
+
}
|
|
2421
|
+
function parseCommit(commit) {
|
|
2422
|
+
return parseConventionalCommit(`${commit.message}\n${commit.description}`);
|
|
2423
|
+
}
|
|
2424
|
+
function summarizeCommits(commits) {
|
|
2425
|
+
let hasBreakingChanges = false;
|
|
2426
|
+
let hasFeatures = false;
|
|
2427
|
+
for (let commit of commits) {
|
|
2428
|
+
let parsed = parseCommit(commit);
|
|
2429
|
+
if (!parsed) continue;
|
|
2430
|
+
if (parsed.breaking) hasBreakingChanges = true;
|
|
2431
|
+
if (parsed.type === "feat") hasFeatures = true;
|
|
2432
|
+
}
|
|
2433
|
+
return {
|
|
2434
|
+
hasBreakingChanges,
|
|
2435
|
+
hasFeatures
|
|
2436
|
+
};
|
|
2437
|
+
}
|
|
2438
|
+
function bumpFromFlags(oldVersion, flags) {
|
|
2439
|
+
let parsedVersion = (0, import_semver.parse)(oldVersion);
|
|
2440
|
+
if (!parsedVersion) throw new Error(`Invalid version: ${oldVersion}`);
|
|
2441
|
+
if (flags.hasBreakingChanges) {
|
|
2442
|
+
if (parsedVersion.major === 0 && parsedVersion.minor === 0) return "patch";
|
|
2443
|
+
if (parsedVersion.major === 0) return "minor";
|
|
2444
|
+
return "major";
|
|
2445
|
+
}
|
|
2446
|
+
if (flags.hasFeatures) return parsedVersion.major === 0 ? "patch" : "minor";
|
|
2447
|
+
return "patch";
|
|
2448
|
+
}
|
|
2449
|
+
function determineBumpType(params) {
|
|
2450
|
+
return bumpFromFlags(params.oldVersion, summarizeCommits(params.commits));
|
|
2451
|
+
}
|
|
2452
|
+
async function writePackageVersion(pkg, version, dryRun) {
|
|
2453
|
+
if (!dryRun) {
|
|
2454
|
+
let pkgJsonPath = pkg.packageJsonPath;
|
|
2455
|
+
let pkgJsonText = await readFile(pkgJsonPath, "utf8");
|
|
2456
|
+
let indent = detectIndent(pkgJsonText).indent || " ";
|
|
2457
|
+
let pkgJson = JSON.parse(pkgJsonText);
|
|
2458
|
+
pkgJson.version = version;
|
|
2459
|
+
await writeFile(pkgJsonPath, `${JSON.stringify(pkgJson, null, indent)}\n`);
|
|
2460
|
+
}
|
|
2461
|
+
pkg.json.version = version;
|
|
2462
|
+
}
|
|
2463
|
+
async function nextStandaloneVersion(pkg, cwd) {
|
|
2464
|
+
let current = asNonNull(pkg.json.version);
|
|
2465
|
+
let tag;
|
|
2466
|
+
try {
|
|
2467
|
+
tag = await getLatestTag(pkg.path);
|
|
2468
|
+
} catch {
|
|
2469
|
+
tag = null;
|
|
2470
|
+
}
|
|
2471
|
+
if (tag == null) return current;
|
|
2472
|
+
let commits;
|
|
2473
|
+
try {
|
|
2474
|
+
let rel = relative(normalizeFilePath(cwd), pkg.path);
|
|
2475
|
+
let pathspec = rel === "" || rel === "." ? "." : rel.endsWith("/") ? rel : `${rel}/`;
|
|
2476
|
+
commits = await getCommitsBetween({
|
|
2477
|
+
since: tag,
|
|
2478
|
+
cwd,
|
|
2479
|
+
files: [pathspec]
|
|
2480
|
+
});
|
|
2481
|
+
} catch {
|
|
2482
|
+
return current;
|
|
2483
|
+
}
|
|
2484
|
+
if (commits.length === 0) return current;
|
|
2485
|
+
let bumpType = determineBumpType({
|
|
2486
|
+
oldVersion: current,
|
|
2487
|
+
commits
|
|
2488
|
+
});
|
|
2489
|
+
let next = (0, import_semver.inc)(current, bumpType);
|
|
2490
|
+
if (next == null) throw new Error(`Invalid version increment: ${current} → ${bumpType}`);
|
|
2491
|
+
return next;
|
|
2492
|
+
}
|
|
2493
|
+
function recordVersion(nextVersions, changedPackages, pkg, prevVersion, next) {
|
|
2494
|
+
if (pkg.json.name != null) nextVersions[pkg.json.name] = next;
|
|
2495
|
+
if (next !== prevVersion) changedPackages.push({
|
|
2496
|
+
package: pkg,
|
|
2497
|
+
prevVersion
|
|
2498
|
+
});
|
|
2499
|
+
}
|
|
2500
|
+
async function bumpVersion(params) {
|
|
2501
|
+
let { workspace, type: explicitType, cwd = process$1.cwd(), since, dryRun = false, withRoot = false } = params;
|
|
2502
|
+
let rootPackage = findRootPackage(workspace);
|
|
2503
|
+
let previousVersion = rootPackage.json.version;
|
|
2504
|
+
if (previousVersion == null) throw new Error("Workspace root package.json is missing a version");
|
|
2505
|
+
let type;
|
|
2506
|
+
let hasFeatures = false;
|
|
2507
|
+
let hasBreakingChanges = false;
|
|
2508
|
+
if (explicitType == null) {
|
|
2509
|
+
let commits = await getCommitsBetween({
|
|
2510
|
+
since,
|
|
2511
|
+
cwd
|
|
2512
|
+
});
|
|
2513
|
+
({hasFeatures, hasBreakingChanges} = summarizeCommits(commits));
|
|
2514
|
+
type = bumpFromFlags(previousVersion, {
|
|
2515
|
+
hasFeatures,
|
|
2516
|
+
hasBreakingChanges
|
|
2517
|
+
});
|
|
2518
|
+
} else type = explicitType;
|
|
2519
|
+
let nextVersion = (0, import_semver.inc)(previousVersion, type);
|
|
2520
|
+
if (nextVersion == null) throw new Error(`Invalid version increment: ${previousVersion} → ${type}`);
|
|
2521
|
+
let nextVersions = {};
|
|
2522
|
+
let changedPackages = [];
|
|
2523
|
+
for (let pkg of workspace) {
|
|
2524
|
+
if (!isManaged(pkg)) continue;
|
|
2525
|
+
let prevVersion = asNonNull(pkg.json.version);
|
|
2526
|
+
await writePackageVersion(pkg, nextVersion, dryRun);
|
|
2527
|
+
recordVersion(nextVersions, changedPackages, pkg, prevVersion, nextVersion);
|
|
2528
|
+
}
|
|
2529
|
+
if (withRoot) {
|
|
2530
|
+
await writePackageVersion(rootPackage, nextVersion, dryRun);
|
|
2531
|
+
recordVersion(nextVersions, changedPackages, rootPackage, previousVersion, nextVersion);
|
|
2532
|
+
}
|
|
2533
|
+
for (let pkg of workspace) {
|
|
2534
|
+
if (pkg.root || isOwnVersioning(pkg) || !isStandalone(pkg)) continue;
|
|
2535
|
+
let prevVersion = asNonNull(pkg.json.version);
|
|
2536
|
+
let standaloneNext = await nextStandaloneVersion(pkg, cwd);
|
|
2537
|
+
if (standaloneNext === prevVersion) continue;
|
|
2538
|
+
await writePackageVersion(pkg, standaloneNext, dryRun);
|
|
2539
|
+
recordVersion(nextVersions, changedPackages, pkg, prevVersion, standaloneNext);
|
|
2540
|
+
}
|
|
2541
|
+
return {
|
|
2542
|
+
previousVersion,
|
|
2543
|
+
nextVersion,
|
|
2544
|
+
nextVersions,
|
|
2545
|
+
changedPackages,
|
|
2546
|
+
releaseType: type,
|
|
2547
|
+
hasBreakingChanges,
|
|
2548
|
+
hasFeatures
|
|
2549
|
+
};
|
|
2550
|
+
}
|
|
2551
|
+
//#endregion
|
|
2552
|
+
//#region src/versioning/generate-changelog.ts
|
|
2553
|
+
var SKIPPED_TYPES = new Set([
|
|
2554
|
+
"chore",
|
|
2555
|
+
"ci",
|
|
2556
|
+
"docs",
|
|
2557
|
+
"test"
|
|
2558
|
+
]);
|
|
2559
|
+
function defaultOnParseFailed(commit) {
|
|
2560
|
+
warn(`Failed to parse commit message: ${commit.message}`);
|
|
2561
|
+
}
|
|
2562
|
+
function defaultCommitFormatter(commit, parsed) {
|
|
2563
|
+
let line = `- ${commit.hash}: ${parsed.breaking ? "**❗ BREAKING** " : ""}${commit.message}`;
|
|
2564
|
+
if (parsed.breaking && commit.description) line += `\n${commit.description.trim().split("\n").map((item) => ` ${item}`).join("\n")}`;
|
|
2565
|
+
return line;
|
|
2566
|
+
}
|
|
2567
|
+
function defaultCommitFilter(_commit, parsed) {
|
|
2568
|
+
if (parsed.breaking) return true;
|
|
2569
|
+
if (!parsed.type || SKIPPED_TYPES.has(parsed.type)) return false;
|
|
2570
|
+
return true;
|
|
2571
|
+
}
|
|
2572
|
+
function defaultPackageCommitsFormatter(packageName, commits) {
|
|
2573
|
+
return `### ${packageName}\n${Object.values(commits).join("\n")}`;
|
|
2574
|
+
}
|
|
2575
|
+
async function generateChangelog(params) {
|
|
2576
|
+
let { cwd, since, params: { changelog: { onCommitParseFailed = defaultOnParseFailed, onCommitsFetched, commitFilter = defaultCommitFilter, commitFilterWithFiles, commitFormatter = defaultCommitFormatter, packageCommitsFormatter = defaultPackageCommitsFormatter } = {} } = {} } = params;
|
|
2577
|
+
let commitsByPackage = {};
|
|
2578
|
+
let changedFiles = await findProjectChangedFiles({
|
|
2579
|
+
params: params.params ?? {},
|
|
2580
|
+
workspace: params.workspace,
|
|
2581
|
+
root: cwd,
|
|
2582
|
+
since
|
|
2583
|
+
});
|
|
2584
|
+
let changedFilesByPackage = /* @__PURE__ */ new Map();
|
|
2585
|
+
for (let file of changedFiles) changedFilesByPackage.set(join(relative(file.root, file.package.path), file.file), file.package);
|
|
2586
|
+
let commits = await getCommitsBetween({
|
|
2587
|
+
since,
|
|
2588
|
+
cwd
|
|
2589
|
+
});
|
|
2590
|
+
await onCommitsFetched?.(commits);
|
|
2591
|
+
for (let commit of commits) {
|
|
2592
|
+
let parsed = parseConventionalCommit(`${commit.message}\n${commit.description}`);
|
|
2593
|
+
if (!parsed) {
|
|
2594
|
+
onCommitParseFailed(commit);
|
|
2595
|
+
continue;
|
|
2596
|
+
}
|
|
2597
|
+
if (!commitFilter(commit, parsed)) continue;
|
|
2598
|
+
let changed = await findChangedFiles({
|
|
2599
|
+
since: `${commit.hash}~1`,
|
|
2600
|
+
until: commit.hash,
|
|
2601
|
+
cwd
|
|
2602
|
+
});
|
|
2603
|
+
if (commitFilterWithFiles && !commitFilterWithFiles(commit, parsed, changed)) continue;
|
|
2604
|
+
for (let file of changed) {
|
|
2605
|
+
let pkg = changedFilesByPackage.get(file);
|
|
2606
|
+
if (!pkg) continue;
|
|
2607
|
+
let packageName = asNonNull(pkg.json.name);
|
|
2608
|
+
if (commitsByPackage[packageName] == null) commitsByPackage[packageName] = {};
|
|
2609
|
+
commitsByPackage[packageName][commit.hash] = commitFormatter(commit, parsed, changed);
|
|
2610
|
+
}
|
|
2611
|
+
}
|
|
2612
|
+
let changelog = "";
|
|
2613
|
+
for (let [pkg, packageCommits] of Object.entries(commitsByPackage)) {
|
|
2614
|
+
changelog += packageCommitsFormatter(pkg, packageCommits);
|
|
2615
|
+
changelog += "\n\n";
|
|
2616
|
+
}
|
|
2617
|
+
return changelog;
|
|
2618
|
+
}
|
|
2619
|
+
//#endregion
|
|
2620
|
+
export { LruMap, NPM_PACKAGE_NAME_REGEX, boolean, buildPackage, buildPackageCli, buildWorkspace, bumpVersion, command, createGithubRelease, determineBumpType, findChangedFiles, findProjectChangedFiles, findProjectChangedPackages, generateChangelog, generateDepsGraph, generateDepsGraphCli, generateDocs, generateDocsCli, getCommitsBetween, getCurrentBranch, getCurrentCommit, getFirstCommit, getGithubActionsInput, getLatestTag, getTsconfigFiles, getTsconfigFor, gitTagExists, isRunningInGithubActions, loadConfig, npmCheckVersion, parseConventionalCommit, publishPackages, publishPackagesCli, resolveWorkspaceRoot, run, runContinuousRelease, runContinuousReleaseCli, string, validateWorkspaceDeps, writeGithubActionsOutput };
|