@udohjeremiah/moniq 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 +3 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +1295 -0
- package/dist/cli.js.map +1 -0
- package/dist/dist-B1TNZsla.js +12055 -0
- package/dist/dist-B1TNZsla.js.map +1 -0
- package/dist/index.d.ts +62 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +289 -0
- package/dist/index.js.map +1 -0
- package/package.json +62 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,1295 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { n as loadConfig } from "./dist-B1TNZsla.js";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { styleText } from "node:util";
|
|
6
|
+
import { access } from "node:fs/promises";
|
|
7
|
+
import { execFileSync } from "node:child_process";
|
|
8
|
+
//#region ../../node_modules/.pnpm/cac@7.0.0/node_modules/cac/dist/index.js
|
|
9
|
+
function toArr(any) {
|
|
10
|
+
return any == null ? [] : Array.isArray(any) ? any : [any];
|
|
11
|
+
}
|
|
12
|
+
function toVal(out, key, val, opts) {
|
|
13
|
+
var x, old = out[key], nxt = !!~opts.string.indexOf(key) ? val == null || val === true ? "" : String(val) : typeof val === "boolean" ? val : !!~opts.boolean.indexOf(key) ? val === "false" ? false : val === "true" || (out._.push((x = +val, x * 0 === 0) ? x : val), !!val) : (x = +val, x * 0 === 0) ? x : val;
|
|
14
|
+
out[key] = old == null ? nxt : Array.isArray(old) ? old.concat(nxt) : [old, nxt];
|
|
15
|
+
}
|
|
16
|
+
function lib_default(args, opts) {
|
|
17
|
+
args = args || [];
|
|
18
|
+
opts = opts || {};
|
|
19
|
+
var k, arr, arg, name, val, out = { _: [] };
|
|
20
|
+
var i = 0, j = 0, idx = 0, len = args.length;
|
|
21
|
+
const alibi = opts.alias !== void 0;
|
|
22
|
+
const strict = opts.unknown !== void 0;
|
|
23
|
+
const defaults = opts.default !== void 0;
|
|
24
|
+
opts.alias = opts.alias || {};
|
|
25
|
+
opts.string = toArr(opts.string);
|
|
26
|
+
opts.boolean = toArr(opts.boolean);
|
|
27
|
+
if (alibi) for (k in opts.alias) {
|
|
28
|
+
arr = opts.alias[k] = toArr(opts.alias[k]);
|
|
29
|
+
for (i = 0; i < arr.length; i++) (opts.alias[arr[i]] = arr.concat(k)).splice(i, 1);
|
|
30
|
+
}
|
|
31
|
+
for (i = opts.boolean.length; i-- > 0;) {
|
|
32
|
+
arr = opts.alias[opts.boolean[i]] || [];
|
|
33
|
+
for (j = arr.length; j-- > 0;) opts.boolean.push(arr[j]);
|
|
34
|
+
}
|
|
35
|
+
for (i = opts.string.length; i-- > 0;) {
|
|
36
|
+
arr = opts.alias[opts.string[i]] || [];
|
|
37
|
+
for (j = arr.length; j-- > 0;) opts.string.push(arr[j]);
|
|
38
|
+
}
|
|
39
|
+
if (defaults) for (k in opts.default) {
|
|
40
|
+
name = typeof opts.default[k];
|
|
41
|
+
arr = opts.alias[k] = opts.alias[k] || [];
|
|
42
|
+
if (opts[name] !== void 0) {
|
|
43
|
+
opts[name].push(k);
|
|
44
|
+
for (i = 0; i < arr.length; i++) opts[name].push(arr[i]);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const keys = strict ? Object.keys(opts.alias) : [];
|
|
48
|
+
for (i = 0; i < len; i++) {
|
|
49
|
+
arg = args[i];
|
|
50
|
+
if (arg === "--") {
|
|
51
|
+
out._ = out._.concat(args.slice(++i));
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
for (j = 0; j < arg.length; j++) if (arg.charCodeAt(j) !== 45) break;
|
|
55
|
+
if (j === 0) out._.push(arg);
|
|
56
|
+
else if (arg.substring(j, j + 3) === "no-") {
|
|
57
|
+
name = arg.substring(j + 3);
|
|
58
|
+
if (strict && !~keys.indexOf(name)) return opts.unknown(arg);
|
|
59
|
+
out[name] = false;
|
|
60
|
+
} else {
|
|
61
|
+
for (idx = j + 1; idx < arg.length; idx++) if (arg.charCodeAt(idx) === 61) break;
|
|
62
|
+
name = arg.substring(j, idx);
|
|
63
|
+
val = arg.substring(++idx) || i + 1 === len || ("" + args[i + 1]).charCodeAt(0) === 45 || args[++i];
|
|
64
|
+
arr = j === 2 ? [name] : name;
|
|
65
|
+
for (idx = 0; idx < arr.length; idx++) {
|
|
66
|
+
name = arr[idx];
|
|
67
|
+
if (strict && !~keys.indexOf(name)) return opts.unknown("-".repeat(j) + name);
|
|
68
|
+
toVal(out, name, idx + 1 < arr.length || val, opts);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (defaults) {
|
|
73
|
+
for (k in opts.default) if (out[k] === void 0) out[k] = opts.default[k];
|
|
74
|
+
}
|
|
75
|
+
if (alibi) for (k in out) {
|
|
76
|
+
arr = opts.alias[k] || [];
|
|
77
|
+
while (arr.length > 0) out[arr.shift()] = out[k];
|
|
78
|
+
}
|
|
79
|
+
return out;
|
|
80
|
+
}
|
|
81
|
+
function removeBrackets(v) {
|
|
82
|
+
return v.replace(/[<[].+/, "").trim();
|
|
83
|
+
}
|
|
84
|
+
function findAllBrackets(v) {
|
|
85
|
+
const ANGLED_BRACKET_RE_GLOBAL = /<([^>]+)>/g;
|
|
86
|
+
const SQUARE_BRACKET_RE_GLOBAL = /\[([^\]]+)\]/g;
|
|
87
|
+
const res = [];
|
|
88
|
+
const parse = (match) => {
|
|
89
|
+
let variadic = false;
|
|
90
|
+
let value = match[1];
|
|
91
|
+
if (value.startsWith("...")) {
|
|
92
|
+
value = value.slice(3);
|
|
93
|
+
variadic = true;
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
required: match[0].startsWith("<"),
|
|
97
|
+
value,
|
|
98
|
+
variadic
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
let angledMatch;
|
|
102
|
+
while (angledMatch = ANGLED_BRACKET_RE_GLOBAL.exec(v)) res.push(parse(angledMatch));
|
|
103
|
+
let squareMatch;
|
|
104
|
+
while (squareMatch = SQUARE_BRACKET_RE_GLOBAL.exec(v)) res.push(parse(squareMatch));
|
|
105
|
+
return res;
|
|
106
|
+
}
|
|
107
|
+
function getMriOptions(options) {
|
|
108
|
+
const result = {
|
|
109
|
+
alias: {},
|
|
110
|
+
boolean: []
|
|
111
|
+
};
|
|
112
|
+
for (const [index, option] of options.entries()) {
|
|
113
|
+
if (option.names.length > 1) result.alias[option.names[0]] = option.names.slice(1);
|
|
114
|
+
if (option.isBoolean) if (option.negated) {
|
|
115
|
+
if (!options.some((o, i) => {
|
|
116
|
+
return i !== index && o.names.some((name) => option.names.includes(name)) && typeof o.required === "boolean";
|
|
117
|
+
})) result.boolean.push(option.names[0]);
|
|
118
|
+
} else result.boolean.push(option.names[0]);
|
|
119
|
+
}
|
|
120
|
+
return result;
|
|
121
|
+
}
|
|
122
|
+
function findLongest(arr) {
|
|
123
|
+
return arr.sort((a, b) => {
|
|
124
|
+
return a.length > b.length ? -1 : 1;
|
|
125
|
+
})[0];
|
|
126
|
+
}
|
|
127
|
+
function padRight(str, length) {
|
|
128
|
+
return str.length >= length ? str : `${str}${" ".repeat(length - str.length)}`;
|
|
129
|
+
}
|
|
130
|
+
function camelcase(input) {
|
|
131
|
+
return input.replaceAll(/([a-z])-([a-z])/g, (_, p1, p2) => {
|
|
132
|
+
return p1 + p2.toUpperCase();
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
function setDotProp(obj, keys, val) {
|
|
136
|
+
let current = obj;
|
|
137
|
+
for (let i = 0; i < keys.length; i++) {
|
|
138
|
+
const key = keys[i];
|
|
139
|
+
if (i === keys.length - 1) {
|
|
140
|
+
current[key] = val;
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
if (current[key] == null) {
|
|
144
|
+
const nextKeyIsArrayIndex = +keys[i + 1] > -1;
|
|
145
|
+
current[key] = nextKeyIsArrayIndex ? [] : {};
|
|
146
|
+
}
|
|
147
|
+
current = current[key];
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function setByType(obj, transforms) {
|
|
151
|
+
for (const key of Object.keys(transforms)) {
|
|
152
|
+
const transform = transforms[key];
|
|
153
|
+
if (transform.shouldTransform) {
|
|
154
|
+
obj[key] = [obj[key]].flat();
|
|
155
|
+
if (typeof transform.transformFunction === "function") obj[key] = obj[key].map(transform.transformFunction);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function getFileName(input) {
|
|
160
|
+
const m = /([^\\/]+)$/.exec(input);
|
|
161
|
+
return m ? m[1] : "";
|
|
162
|
+
}
|
|
163
|
+
function camelcaseOptionName(name) {
|
|
164
|
+
return name.split(".").map((v, i) => {
|
|
165
|
+
return i === 0 ? camelcase(v) : v;
|
|
166
|
+
}).join(".");
|
|
167
|
+
}
|
|
168
|
+
var CACError = class extends Error {
|
|
169
|
+
constructor(message) {
|
|
170
|
+
super(message);
|
|
171
|
+
this.name = "CACError";
|
|
172
|
+
if (typeof Error.captureStackTrace !== "function") this.stack = new Error(message).stack;
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
var Option = class {
|
|
176
|
+
rawName;
|
|
177
|
+
description;
|
|
178
|
+
/** Option name */
|
|
179
|
+
name;
|
|
180
|
+
/** Option name and aliases */
|
|
181
|
+
names;
|
|
182
|
+
isBoolean;
|
|
183
|
+
required;
|
|
184
|
+
config;
|
|
185
|
+
negated;
|
|
186
|
+
constructor(rawName, description, config) {
|
|
187
|
+
this.rawName = rawName;
|
|
188
|
+
this.description = description;
|
|
189
|
+
this.config = Object.assign({}, config);
|
|
190
|
+
rawName = rawName.replaceAll(".*", "");
|
|
191
|
+
this.negated = false;
|
|
192
|
+
this.names = removeBrackets(rawName).split(",").map((v) => {
|
|
193
|
+
let name = v.trim().replace(/^-{1,2}/, "");
|
|
194
|
+
if (name.startsWith("no-")) {
|
|
195
|
+
this.negated = true;
|
|
196
|
+
name = name.replace(/^no-/, "");
|
|
197
|
+
}
|
|
198
|
+
return camelcaseOptionName(name);
|
|
199
|
+
}).sort((a, b) => a.length > b.length ? 1 : -1);
|
|
200
|
+
this.name = this.names.at(-1);
|
|
201
|
+
if (this.negated && this.config.default == null) this.config.default = true;
|
|
202
|
+
if (rawName.includes("<")) this.required = true;
|
|
203
|
+
else if (rawName.includes("[")) this.required = false;
|
|
204
|
+
else this.isBoolean = true;
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
let runtimeProcessArgs;
|
|
208
|
+
let runtimeInfo;
|
|
209
|
+
if (typeof process !== "undefined") {
|
|
210
|
+
let runtimeName;
|
|
211
|
+
if (typeof Deno !== "undefined" && typeof Deno.version?.deno === "string") runtimeName = "deno";
|
|
212
|
+
else if (typeof Bun !== "undefined" && typeof Bun.version === "string") runtimeName = "bun";
|
|
213
|
+
else runtimeName = "node";
|
|
214
|
+
runtimeInfo = `${process.platform}-${process.arch} ${runtimeName}-${process.version}`;
|
|
215
|
+
runtimeProcessArgs = process.argv;
|
|
216
|
+
} else if (typeof navigator === "undefined") runtimeInfo = `unknown`;
|
|
217
|
+
else runtimeInfo = `${navigator.platform} ${navigator.userAgent}`;
|
|
218
|
+
var Command = class {
|
|
219
|
+
rawName;
|
|
220
|
+
description;
|
|
221
|
+
config;
|
|
222
|
+
cli;
|
|
223
|
+
options;
|
|
224
|
+
aliasNames;
|
|
225
|
+
name;
|
|
226
|
+
args;
|
|
227
|
+
commandAction;
|
|
228
|
+
usageText;
|
|
229
|
+
versionNumber;
|
|
230
|
+
examples;
|
|
231
|
+
helpCallback;
|
|
232
|
+
globalCommand;
|
|
233
|
+
constructor(rawName, description, config = {}, cli) {
|
|
234
|
+
this.rawName = rawName;
|
|
235
|
+
this.description = description;
|
|
236
|
+
this.config = config;
|
|
237
|
+
this.cli = cli;
|
|
238
|
+
this.options = [];
|
|
239
|
+
this.aliasNames = [];
|
|
240
|
+
this.name = removeBrackets(rawName);
|
|
241
|
+
this.args = findAllBrackets(rawName);
|
|
242
|
+
this.examples = [];
|
|
243
|
+
}
|
|
244
|
+
usage(text) {
|
|
245
|
+
this.usageText = text;
|
|
246
|
+
return this;
|
|
247
|
+
}
|
|
248
|
+
allowUnknownOptions() {
|
|
249
|
+
this.config.allowUnknownOptions = true;
|
|
250
|
+
return this;
|
|
251
|
+
}
|
|
252
|
+
ignoreOptionDefaultValue() {
|
|
253
|
+
this.config.ignoreOptionDefaultValue = true;
|
|
254
|
+
return this;
|
|
255
|
+
}
|
|
256
|
+
version(version, customFlags = "-v, --version") {
|
|
257
|
+
this.versionNumber = version;
|
|
258
|
+
this.option(customFlags, "Display version number");
|
|
259
|
+
return this;
|
|
260
|
+
}
|
|
261
|
+
example(example) {
|
|
262
|
+
this.examples.push(example);
|
|
263
|
+
return this;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Add a option for this command
|
|
267
|
+
* @param rawName Raw option name(s)
|
|
268
|
+
* @param description Option description
|
|
269
|
+
* @param config Option config
|
|
270
|
+
*/
|
|
271
|
+
option(rawName, description, config) {
|
|
272
|
+
const option = new Option(rawName, description, config);
|
|
273
|
+
this.options.push(option);
|
|
274
|
+
return this;
|
|
275
|
+
}
|
|
276
|
+
alias(name) {
|
|
277
|
+
this.aliasNames.push(name);
|
|
278
|
+
return this;
|
|
279
|
+
}
|
|
280
|
+
action(callback) {
|
|
281
|
+
this.commandAction = callback;
|
|
282
|
+
return this;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Check if a command name is matched by this command
|
|
286
|
+
* @param name Command name
|
|
287
|
+
*/
|
|
288
|
+
isMatched(name) {
|
|
289
|
+
return this.name === name || this.aliasNames.includes(name);
|
|
290
|
+
}
|
|
291
|
+
get isDefaultCommand() {
|
|
292
|
+
return this.name === "" || this.aliasNames.includes("!");
|
|
293
|
+
}
|
|
294
|
+
get isGlobalCommand() {
|
|
295
|
+
return this instanceof GlobalCommand;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Check if an option is registered in this command
|
|
299
|
+
* @param name Option name
|
|
300
|
+
*/
|
|
301
|
+
hasOption(name) {
|
|
302
|
+
name = name.split(".")[0];
|
|
303
|
+
return this.options.find((option) => {
|
|
304
|
+
return option.names.includes(name);
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
outputHelp() {
|
|
308
|
+
const { name, commands } = this.cli;
|
|
309
|
+
const { versionNumber, options: globalOptions, helpCallback } = this.cli.globalCommand;
|
|
310
|
+
let sections = [{ body: `${name}${versionNumber ? `/${versionNumber}` : ""}` }];
|
|
311
|
+
sections.push({
|
|
312
|
+
title: "Usage",
|
|
313
|
+
body: ` $ ${name} ${this.usageText || this.rawName}`
|
|
314
|
+
});
|
|
315
|
+
if ((this.isGlobalCommand || this.isDefaultCommand) && commands.length > 0) {
|
|
316
|
+
const longestCommandName = findLongest(commands.map((command) => command.rawName));
|
|
317
|
+
sections.push({
|
|
318
|
+
title: "Commands",
|
|
319
|
+
body: commands.map((command) => {
|
|
320
|
+
return ` ${padRight(command.rawName, longestCommandName.length)} ${command.description}`;
|
|
321
|
+
}).join("\n")
|
|
322
|
+
}, {
|
|
323
|
+
title: `For more info, run any command with the \`--help\` flag`,
|
|
324
|
+
body: commands.map((command) => ` $ ${name}${command.name === "" ? "" : ` ${command.name}`} --help`).join("\n")
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
let options = this.isGlobalCommand ? globalOptions : [...this.options, ...globalOptions || []];
|
|
328
|
+
if (!this.isGlobalCommand && !this.isDefaultCommand) options = options.filter((option) => option.name !== "version");
|
|
329
|
+
if (options.length > 0) {
|
|
330
|
+
const longestOptionName = findLongest(options.map((option) => option.rawName));
|
|
331
|
+
sections.push({
|
|
332
|
+
title: "Options",
|
|
333
|
+
body: options.map((option) => {
|
|
334
|
+
return ` ${padRight(option.rawName, longestOptionName.length)} ${option.description} ${option.config.default === void 0 ? "" : `(default: ${option.config.default})`}`;
|
|
335
|
+
}).join("\n")
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
if (this.examples.length > 0) sections.push({
|
|
339
|
+
title: "Examples",
|
|
340
|
+
body: this.examples.map((example) => {
|
|
341
|
+
if (typeof example === "function") return example(name);
|
|
342
|
+
return example;
|
|
343
|
+
}).join("\n")
|
|
344
|
+
});
|
|
345
|
+
if (helpCallback) sections = helpCallback(sections) || sections;
|
|
346
|
+
console.info(sections.map((section) => {
|
|
347
|
+
return section.title ? `${section.title}:\n${section.body}` : section.body;
|
|
348
|
+
}).join("\n\n"));
|
|
349
|
+
}
|
|
350
|
+
outputVersion() {
|
|
351
|
+
const { name } = this.cli;
|
|
352
|
+
const { versionNumber } = this.cli.globalCommand;
|
|
353
|
+
if (versionNumber) console.info(`${name}/${versionNumber} ${runtimeInfo}`);
|
|
354
|
+
}
|
|
355
|
+
checkRequiredArgs() {
|
|
356
|
+
const minimalArgsCount = this.args.filter((arg) => arg.required).length;
|
|
357
|
+
if (this.cli.args.length < minimalArgsCount) throw new CACError(`missing required args for command \`${this.rawName}\``);
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Check if the parsed options contain any unknown options
|
|
361
|
+
*
|
|
362
|
+
* Exit and output error when true
|
|
363
|
+
*/
|
|
364
|
+
checkUnknownOptions() {
|
|
365
|
+
const { options, globalCommand } = this.cli;
|
|
366
|
+
if (!this.config.allowUnknownOptions) {
|
|
367
|
+
for (const name of Object.keys(options)) if (name !== "--" && !this.hasOption(name) && !globalCommand.hasOption(name)) throw new CACError(`Unknown option \`${name.length > 1 ? `--${name}` : `-${name}`}\``);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Check if the required string-type options exist
|
|
372
|
+
*/
|
|
373
|
+
checkOptionValue() {
|
|
374
|
+
const { options: parsedOptions, globalCommand } = this.cli;
|
|
375
|
+
const options = [...globalCommand.options, ...this.options];
|
|
376
|
+
for (const option of options) {
|
|
377
|
+
const value = parsedOptions[option.name.split(".")[0]];
|
|
378
|
+
if (option.required) {
|
|
379
|
+
const hasNegated = options.some((o) => o.negated && o.names.includes(option.name));
|
|
380
|
+
if (value === true || value === false && !hasNegated) throw new CACError(`option \`${option.rawName}\` value is missing`);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Check if the number of args is more than expected
|
|
386
|
+
*/
|
|
387
|
+
checkUnusedArgs() {
|
|
388
|
+
const maximumArgsCount = this.args.some((arg) => arg.variadic) ? Infinity : this.args.length;
|
|
389
|
+
if (maximumArgsCount < this.cli.args.length) throw new CACError(`Unused args: ${this.cli.args.slice(maximumArgsCount).map((arg) => `\`${arg}\``).join(", ")}`);
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
var GlobalCommand = class extends Command {
|
|
393
|
+
constructor(cli) {
|
|
394
|
+
super("@@global@@", "", {}, cli);
|
|
395
|
+
}
|
|
396
|
+
};
|
|
397
|
+
var CAC = class extends EventTarget {
|
|
398
|
+
/** The program name to display in help and version message */
|
|
399
|
+
name;
|
|
400
|
+
commands;
|
|
401
|
+
globalCommand;
|
|
402
|
+
matchedCommand;
|
|
403
|
+
matchedCommandName;
|
|
404
|
+
/**
|
|
405
|
+
* Raw CLI arguments
|
|
406
|
+
*/
|
|
407
|
+
rawArgs;
|
|
408
|
+
/**
|
|
409
|
+
* Parsed CLI arguments
|
|
410
|
+
*/
|
|
411
|
+
args;
|
|
412
|
+
/**
|
|
413
|
+
* Parsed CLI options, camelCased
|
|
414
|
+
*/
|
|
415
|
+
options;
|
|
416
|
+
showHelpOnExit;
|
|
417
|
+
showVersionOnExit;
|
|
418
|
+
/**
|
|
419
|
+
* @param name The program name to display in help and version message
|
|
420
|
+
*/
|
|
421
|
+
constructor(name = "") {
|
|
422
|
+
super();
|
|
423
|
+
this.name = name;
|
|
424
|
+
this.commands = [];
|
|
425
|
+
this.rawArgs = [];
|
|
426
|
+
this.args = [];
|
|
427
|
+
this.options = {};
|
|
428
|
+
this.globalCommand = new GlobalCommand(this);
|
|
429
|
+
this.globalCommand.usage("<command> [options]");
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Add a global usage text.
|
|
433
|
+
*
|
|
434
|
+
* This is not used by sub-commands.
|
|
435
|
+
*/
|
|
436
|
+
usage(text) {
|
|
437
|
+
this.globalCommand.usage(text);
|
|
438
|
+
return this;
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Add a sub-command
|
|
442
|
+
*/
|
|
443
|
+
command(rawName, description, config) {
|
|
444
|
+
const command = new Command(rawName, description || "", config, this);
|
|
445
|
+
command.globalCommand = this.globalCommand;
|
|
446
|
+
this.commands.push(command);
|
|
447
|
+
return command;
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Add a global CLI option.
|
|
451
|
+
*
|
|
452
|
+
* Which is also applied to sub-commands.
|
|
453
|
+
*/
|
|
454
|
+
option(rawName, description, config) {
|
|
455
|
+
this.globalCommand.option(rawName, description, config);
|
|
456
|
+
return this;
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Show help message when `-h, --help` flags appear.
|
|
460
|
+
*
|
|
461
|
+
*/
|
|
462
|
+
help(callback) {
|
|
463
|
+
this.globalCommand.option("-h, --help", "Display this message");
|
|
464
|
+
this.globalCommand.helpCallback = callback;
|
|
465
|
+
this.showHelpOnExit = true;
|
|
466
|
+
return this;
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Show version number when `-v, --version` flags appear.
|
|
470
|
+
*
|
|
471
|
+
*/
|
|
472
|
+
version(version, customFlags = "-v, --version") {
|
|
473
|
+
this.globalCommand.version(version, customFlags);
|
|
474
|
+
this.showVersionOnExit = true;
|
|
475
|
+
return this;
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* Add a global example.
|
|
479
|
+
*
|
|
480
|
+
* This example added here will not be used by sub-commands.
|
|
481
|
+
*/
|
|
482
|
+
example(example) {
|
|
483
|
+
this.globalCommand.example(example);
|
|
484
|
+
return this;
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Output the corresponding help message
|
|
488
|
+
* When a sub-command is matched, output the help message for the command
|
|
489
|
+
* Otherwise output the global one.
|
|
490
|
+
*
|
|
491
|
+
*/
|
|
492
|
+
outputHelp() {
|
|
493
|
+
if (this.matchedCommand) this.matchedCommand.outputHelp();
|
|
494
|
+
else this.globalCommand.outputHelp();
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* Output the version number.
|
|
498
|
+
*
|
|
499
|
+
*/
|
|
500
|
+
outputVersion() {
|
|
501
|
+
this.globalCommand.outputVersion();
|
|
502
|
+
}
|
|
503
|
+
setParsedInfo({ args, options }, matchedCommand, matchedCommandName) {
|
|
504
|
+
this.args = args;
|
|
505
|
+
this.options = options;
|
|
506
|
+
if (matchedCommand) this.matchedCommand = matchedCommand;
|
|
507
|
+
if (matchedCommandName) this.matchedCommandName = matchedCommandName;
|
|
508
|
+
return this;
|
|
509
|
+
}
|
|
510
|
+
unsetMatchedCommand() {
|
|
511
|
+
this.matchedCommand = void 0;
|
|
512
|
+
this.matchedCommandName = void 0;
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Parse argv
|
|
516
|
+
*/
|
|
517
|
+
parse(argv, { run = true } = {}) {
|
|
518
|
+
if (!argv) {
|
|
519
|
+
if (!runtimeProcessArgs) throw new Error("No argv provided and runtime process argv is not available.");
|
|
520
|
+
argv = runtimeProcessArgs;
|
|
521
|
+
}
|
|
522
|
+
this.rawArgs = argv;
|
|
523
|
+
if (!this.name) this.name = argv[1] ? getFileName(argv[1]) : "cli";
|
|
524
|
+
let shouldParse = true;
|
|
525
|
+
for (const command of this.commands) {
|
|
526
|
+
const parsed = this.mri(argv.slice(2), command);
|
|
527
|
+
const commandName = parsed.args[0];
|
|
528
|
+
if (command.isMatched(commandName)) {
|
|
529
|
+
shouldParse = false;
|
|
530
|
+
const parsedInfo = {
|
|
531
|
+
...parsed,
|
|
532
|
+
args: parsed.args.slice(1)
|
|
533
|
+
};
|
|
534
|
+
this.setParsedInfo(parsedInfo, command, commandName);
|
|
535
|
+
this.dispatchEvent(new CustomEvent(`command:${commandName}`, { detail: command }));
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
if (shouldParse) {
|
|
539
|
+
for (const command of this.commands) if (command.isDefaultCommand) {
|
|
540
|
+
shouldParse = false;
|
|
541
|
+
const parsed = this.mri(argv.slice(2), command);
|
|
542
|
+
this.setParsedInfo(parsed, command);
|
|
543
|
+
this.dispatchEvent(new CustomEvent("command:!", { detail: command }));
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
if (shouldParse) {
|
|
547
|
+
const parsed = this.mri(argv.slice(2));
|
|
548
|
+
this.setParsedInfo(parsed);
|
|
549
|
+
}
|
|
550
|
+
if (this.options.help && this.showHelpOnExit) {
|
|
551
|
+
this.outputHelp();
|
|
552
|
+
run = false;
|
|
553
|
+
this.unsetMatchedCommand();
|
|
554
|
+
}
|
|
555
|
+
if (this.options.version && this.showVersionOnExit && this.matchedCommandName == null) {
|
|
556
|
+
this.outputVersion();
|
|
557
|
+
run = false;
|
|
558
|
+
this.unsetMatchedCommand();
|
|
559
|
+
}
|
|
560
|
+
const parsedArgv = {
|
|
561
|
+
args: this.args,
|
|
562
|
+
options: this.options
|
|
563
|
+
};
|
|
564
|
+
if (run) this.runMatchedCommand();
|
|
565
|
+
if (!this.matchedCommand && this.args[0]) this.dispatchEvent(new CustomEvent("command:*", { detail: this.args[0] }));
|
|
566
|
+
return parsedArgv;
|
|
567
|
+
}
|
|
568
|
+
mri(argv, command) {
|
|
569
|
+
const cliOptions = [...this.globalCommand.options, ...command ? command.options : []];
|
|
570
|
+
const mriOptions = getMriOptions(cliOptions);
|
|
571
|
+
let argsAfterDoubleDashes = [];
|
|
572
|
+
const doubleDashesIndex = argv.indexOf("--");
|
|
573
|
+
if (doubleDashesIndex !== -1) {
|
|
574
|
+
argsAfterDoubleDashes = argv.slice(doubleDashesIndex + 1);
|
|
575
|
+
argv = argv.slice(0, doubleDashesIndex);
|
|
576
|
+
}
|
|
577
|
+
let parsed = lib_default(argv, mriOptions);
|
|
578
|
+
parsed = Object.keys(parsed).reduce((res, name) => {
|
|
579
|
+
return {
|
|
580
|
+
...res,
|
|
581
|
+
[camelcaseOptionName(name)]: parsed[name]
|
|
582
|
+
};
|
|
583
|
+
}, { _: [] });
|
|
584
|
+
const args = parsed._;
|
|
585
|
+
const options = { "--": argsAfterDoubleDashes };
|
|
586
|
+
const ignoreDefault = command && command.config.ignoreOptionDefaultValue ? command.config.ignoreOptionDefaultValue : this.globalCommand.config.ignoreOptionDefaultValue;
|
|
587
|
+
const transforms = Object.create(null);
|
|
588
|
+
for (const cliOption of cliOptions) {
|
|
589
|
+
if (!ignoreDefault && cliOption.config.default !== void 0) for (const name of cliOption.names) options[name] = cliOption.config.default;
|
|
590
|
+
if (Array.isArray(cliOption.config.type) && transforms[cliOption.name] === void 0) {
|
|
591
|
+
transforms[cliOption.name] = Object.create(null);
|
|
592
|
+
transforms[cliOption.name].shouldTransform = true;
|
|
593
|
+
transforms[cliOption.name].transformFunction = cliOption.config.type[0];
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
for (const key of Object.keys(parsed)) if (key !== "_") {
|
|
597
|
+
setDotProp(options, key.split("."), parsed[key]);
|
|
598
|
+
setByType(options, transforms);
|
|
599
|
+
}
|
|
600
|
+
return {
|
|
601
|
+
args,
|
|
602
|
+
options
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
runMatchedCommand() {
|
|
606
|
+
const { args, options, matchedCommand: command } = this;
|
|
607
|
+
if (!command || !command.commandAction) return;
|
|
608
|
+
command.checkUnknownOptions();
|
|
609
|
+
command.checkOptionValue();
|
|
610
|
+
command.checkRequiredArgs();
|
|
611
|
+
command.checkUnusedArgs();
|
|
612
|
+
const actionArgs = [];
|
|
613
|
+
command.args.forEach((arg, index) => {
|
|
614
|
+
if (arg.variadic) actionArgs.push(args.slice(index));
|
|
615
|
+
else actionArgs.push(args[index]);
|
|
616
|
+
});
|
|
617
|
+
actionArgs.push(options);
|
|
618
|
+
return command.commandAction.apply(this, actionArgs);
|
|
619
|
+
}
|
|
620
|
+
};
|
|
621
|
+
/**
|
|
622
|
+
* @param name The program name to display in help and version message
|
|
623
|
+
*/
|
|
624
|
+
const cac = (name = "") => new CAC(name);
|
|
625
|
+
//#endregion
|
|
626
|
+
//#region ../workspace/dist/index.js
|
|
627
|
+
async function readPackageJson(path) {
|
|
628
|
+
const { readFile } = await import("node:fs/promises");
|
|
629
|
+
const content = await readFile(path, "utf8");
|
|
630
|
+
return JSON.parse(content);
|
|
631
|
+
}
|
|
632
|
+
function getScript(packageJson, name) {
|
|
633
|
+
const scripts = packageJson["scripts"];
|
|
634
|
+
if (typeof scripts !== "object" || scripts === null) return;
|
|
635
|
+
const value = Object.entries(scripts).find(([k]) => k === name)?.[1];
|
|
636
|
+
return typeof value === "string" ? value : void 0;
|
|
637
|
+
}
|
|
638
|
+
const npmCommand = getNpmCommand();
|
|
639
|
+
const pnpmCommand = getPnpmCommand();
|
|
640
|
+
const yarnCommand = getYarnCommand();
|
|
641
|
+
function discoverWorkspace(root) {
|
|
642
|
+
const pm = detectPackageManager(root);
|
|
643
|
+
let output;
|
|
644
|
+
switch (pm) {
|
|
645
|
+
case "npm": {
|
|
646
|
+
output = execFileSync(npmCommand, [
|
|
647
|
+
"ls",
|
|
648
|
+
"--workspaces",
|
|
649
|
+
"--all",
|
|
650
|
+
"--json",
|
|
651
|
+
"--depth",
|
|
652
|
+
"0"
|
|
653
|
+
], {
|
|
654
|
+
cwd: root,
|
|
655
|
+
encoding: "utf8"
|
|
656
|
+
});
|
|
657
|
+
const tree = JSON.parse(output);
|
|
658
|
+
return Object.values(tree.dependencies ?? {}).map((entry) => ({ path: entry.path }));
|
|
659
|
+
}
|
|
660
|
+
case "pnpm":
|
|
661
|
+
output = execFileSync(pnpmCommand, [
|
|
662
|
+
"ls",
|
|
663
|
+
"-r",
|
|
664
|
+
"--depth",
|
|
665
|
+
"-1",
|
|
666
|
+
"--json"
|
|
667
|
+
], {
|
|
668
|
+
cwd: root,
|
|
669
|
+
encoding: "utf8"
|
|
670
|
+
});
|
|
671
|
+
return JSON.parse(output).map((entry) => ({ path: entry.path }));
|
|
672
|
+
case "yarn":
|
|
673
|
+
output = execFileSync(yarnCommand, [
|
|
674
|
+
"workspaces",
|
|
675
|
+
"list",
|
|
676
|
+
"--json"
|
|
677
|
+
], {
|
|
678
|
+
cwd: root,
|
|
679
|
+
encoding: "utf8"
|
|
680
|
+
});
|
|
681
|
+
return output.trim().split("\n").filter(Boolean).map((line) => JSON.parse(line)).map((entry) => ({ path: path.resolve(root, entry.location) }));
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
function detectPackageManager(root) {
|
|
685
|
+
const userAgent = process.env["npm_config_user_agent"] ?? "";
|
|
686
|
+
if (userAgent.startsWith("pnpm")) return "pnpm";
|
|
687
|
+
if (userAgent.startsWith("yarn")) return "yarn";
|
|
688
|
+
if (userAgent.startsWith("npm")) return "npm";
|
|
689
|
+
const request = createRequire(import.meta.url);
|
|
690
|
+
for (const [lockFile, pm] of Object.entries({
|
|
691
|
+
"package-lock.json": "npm",
|
|
692
|
+
"pnpm-lock.yaml": "pnpm",
|
|
693
|
+
"yarn.lock": "yarn"
|
|
694
|
+
})) try {
|
|
695
|
+
request.resolve(path.join(root, lockFile));
|
|
696
|
+
return pm;
|
|
697
|
+
} catch {}
|
|
698
|
+
try {
|
|
699
|
+
const rawPm = request(path.join(root, "package.json"))["packageManager"];
|
|
700
|
+
const pm = typeof rawPm === "string" ? rawPm.split("@", 2)[0] ?? "" : "";
|
|
701
|
+
if ([
|
|
702
|
+
"npm",
|
|
703
|
+
"pnpm",
|
|
704
|
+
"yarn"
|
|
705
|
+
].includes(pm)) return pm;
|
|
706
|
+
} catch {}
|
|
707
|
+
return "pnpm";
|
|
708
|
+
}
|
|
709
|
+
function getNpmCommand() {
|
|
710
|
+
return path.join(path.dirname(process.execPath), "npm");
|
|
711
|
+
}
|
|
712
|
+
function getPnpmCommand() {
|
|
713
|
+
try {
|
|
714
|
+
const request = createRequire(import.meta.url);
|
|
715
|
+
const specifier = ["pnpm", "package.json"].join("/");
|
|
716
|
+
const packagePath = request.resolve(specifier);
|
|
717
|
+
return path.resolve(path.dirname(packagePath), "bin", "pnpm.cjs");
|
|
718
|
+
} catch {
|
|
719
|
+
return "pnpm";
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
function getYarnCommand() {
|
|
723
|
+
try {
|
|
724
|
+
const request = createRequire(import.meta.url);
|
|
725
|
+
const specifier = [
|
|
726
|
+
"@yarnpkg",
|
|
727
|
+
"cli",
|
|
728
|
+
"package.json"
|
|
729
|
+
].join("/");
|
|
730
|
+
const packagePath = request.resolve(specifier);
|
|
731
|
+
return path.resolve(path.dirname(packagePath), "sources", "bin", "yarn.js");
|
|
732
|
+
} catch {
|
|
733
|
+
try {
|
|
734
|
+
const request = createRequire(import.meta.url);
|
|
735
|
+
const specifier = ["yarn", "package.json"].join("/");
|
|
736
|
+
const packagePath = request.resolve(specifier);
|
|
737
|
+
return path.resolve(path.dirname(packagePath), "bin", "yarn.js");
|
|
738
|
+
} catch {
|
|
739
|
+
return "yarn";
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
//#endregion
|
|
744
|
+
//#region ../../node_modules/.pnpm/wildcard-match@5.1.4/node_modules/wildcard-match/build/index.es.mjs
|
|
745
|
+
/**
|
|
746
|
+
* Escapes a character if it has a special meaning in regular expressions
|
|
747
|
+
* and returns the character as is if it doesn't
|
|
748
|
+
*/
|
|
749
|
+
function escapeRegExpChar(char) {
|
|
750
|
+
if (char === "-" || char === "^" || char === "$" || char === "+" || char === "." || char === "(" || char === ")" || char === "|" || char === "[" || char === "]" || char === "{" || char === "}" || char === "*" || char === "?" || char === "\\") return "\\".concat(char);
|
|
751
|
+
else return char;
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Escapes all characters in a given string that have a special meaning in regular expressions
|
|
755
|
+
*/
|
|
756
|
+
function escapeRegExpString(str) {
|
|
757
|
+
var result = "";
|
|
758
|
+
for (var i = 0; i < str.length; i++) result += escapeRegExpChar(str[i]);
|
|
759
|
+
return result;
|
|
760
|
+
}
|
|
761
|
+
/**
|
|
762
|
+
* Transforms one or more glob patterns into a RegExp pattern
|
|
763
|
+
*/
|
|
764
|
+
function transform(pattern, separator) {
|
|
765
|
+
if (separator === void 0) separator = true;
|
|
766
|
+
if (Array.isArray(pattern)) {
|
|
767
|
+
var regExpPatterns = pattern.map(function(p) {
|
|
768
|
+
return "^".concat(transform(p, separator), "$");
|
|
769
|
+
});
|
|
770
|
+
return "(?:".concat(regExpPatterns.join("|"), ")");
|
|
771
|
+
}
|
|
772
|
+
var separatorSplitter = "";
|
|
773
|
+
var separatorMatcher = "";
|
|
774
|
+
var wildcard = ".";
|
|
775
|
+
if (separator === true) {
|
|
776
|
+
separatorSplitter = "/";
|
|
777
|
+
separatorMatcher = "[/\\\\]";
|
|
778
|
+
wildcard = "[^/\\\\]";
|
|
779
|
+
} else if (separator) {
|
|
780
|
+
separatorSplitter = separator;
|
|
781
|
+
separatorMatcher = escapeRegExpString(separatorSplitter);
|
|
782
|
+
if (separatorMatcher.length > 1) {
|
|
783
|
+
separatorMatcher = "(?:".concat(separatorMatcher, ")");
|
|
784
|
+
wildcard = "((?!".concat(separatorMatcher, ").)");
|
|
785
|
+
} else wildcard = "[^".concat(separatorMatcher, "]");
|
|
786
|
+
}
|
|
787
|
+
var requiredSeparator = separator ? "".concat(separatorMatcher, "+?") : "";
|
|
788
|
+
var optionalSeparator = separator ? "".concat(separatorMatcher, "*?") : "";
|
|
789
|
+
var segments = separator ? pattern.split(separatorSplitter) : [pattern];
|
|
790
|
+
var result = "";
|
|
791
|
+
for (var s = 0; s < segments.length; s++) {
|
|
792
|
+
var segment = segments[s];
|
|
793
|
+
var nextSegment = segments[s + 1];
|
|
794
|
+
var currentSeparator = "";
|
|
795
|
+
if (!segment && s > 0) continue;
|
|
796
|
+
if (separator) if (s === segments.length - 1) currentSeparator = optionalSeparator;
|
|
797
|
+
else if (nextSegment !== "**") currentSeparator = requiredSeparator;
|
|
798
|
+
else currentSeparator = "";
|
|
799
|
+
if (separator && segment === "**") {
|
|
800
|
+
if (currentSeparator) {
|
|
801
|
+
result += s === 0 ? "" : s === segments.length - 1 ? "(?:".concat(requiredSeparator, "|$)") : requiredSeparator;
|
|
802
|
+
result += "(?:".concat(wildcard, "*?").concat(currentSeparator, ")*?");
|
|
803
|
+
}
|
|
804
|
+
continue;
|
|
805
|
+
}
|
|
806
|
+
for (var c = 0; c < segment.length; c++) {
|
|
807
|
+
var char = segment[c];
|
|
808
|
+
if (char === "\\") {
|
|
809
|
+
if (c < segment.length - 1) {
|
|
810
|
+
result += escapeRegExpChar(segment[c + 1]);
|
|
811
|
+
c++;
|
|
812
|
+
}
|
|
813
|
+
} else if (char === "?") result += wildcard;
|
|
814
|
+
else if (char === "*") result += "".concat(wildcard, "*?");
|
|
815
|
+
else result += escapeRegExpChar(char);
|
|
816
|
+
}
|
|
817
|
+
result += currentSeparator;
|
|
818
|
+
}
|
|
819
|
+
return result;
|
|
820
|
+
}
|
|
821
|
+
function isMatch(regexp, sample) {
|
|
822
|
+
if (typeof sample !== "string") throw new TypeError("Sample must be a string, but ".concat(typeof sample, " given"));
|
|
823
|
+
return regexp.test(sample);
|
|
824
|
+
}
|
|
825
|
+
/**
|
|
826
|
+
* Compiles one or more glob patterns into a RegExp and returns an isMatch function.
|
|
827
|
+
* The isMatch function takes a sample string as its only argument and returns `true`
|
|
828
|
+
* if the string matches the pattern(s).
|
|
829
|
+
*
|
|
830
|
+
* ```js
|
|
831
|
+
* wildcardMatch('src/*.js')('src/index.js') //=> true
|
|
832
|
+
* ```
|
|
833
|
+
*
|
|
834
|
+
* ```js
|
|
835
|
+
* const isMatch = wildcardMatch('*.example.com', '.')
|
|
836
|
+
* isMatch('foo.example.com') //=> true
|
|
837
|
+
* isMatch('foo.bar.com') //=> false
|
|
838
|
+
* ```
|
|
839
|
+
*/
|
|
840
|
+
function wildcardMatch(pattern, options) {
|
|
841
|
+
if (typeof pattern !== "string" && !Array.isArray(pattern)) throw new TypeError("The first argument must be a single pattern string or an array of patterns, but ".concat(typeof pattern, " given"));
|
|
842
|
+
if (typeof options === "string" || typeof options === "boolean") options = { separator: options };
|
|
843
|
+
if (arguments.length === 2 && !(typeof options === "undefined" || typeof options === "object" && options !== null && !Array.isArray(options))) throw new TypeError("The second argument must be an options object or a string/boolean separator, but ".concat(typeof options, " given"));
|
|
844
|
+
options = options || {};
|
|
845
|
+
if (options.separator === "\\") throw new Error("\\ is not a valid separator because it is used for escaping. Try setting the separator to `true` instead");
|
|
846
|
+
var regexpPattern = transform(pattern, options.separator);
|
|
847
|
+
var regexp = new RegExp("^".concat(regexpPattern, "$"), options.flags);
|
|
848
|
+
var fn = isMatch.bind(null, regexp);
|
|
849
|
+
fn.options = options;
|
|
850
|
+
fn.pattern = pattern;
|
|
851
|
+
fn.regexp = regexp;
|
|
852
|
+
return fn;
|
|
853
|
+
}
|
|
854
|
+
//#endregion
|
|
855
|
+
//#region ../core/dist/index.js
|
|
856
|
+
async function resolveScriptPolicies(scriptsConfig, root, packages_) {
|
|
857
|
+
const diagnostics = [];
|
|
858
|
+
const entries = Object.entries(scriptsConfig ?? {});
|
|
859
|
+
for (const [scriptName, policyOrArray] of entries) {
|
|
860
|
+
const policies = Array.isArray(policyOrArray) ? policyOrArray : [policyOrArray];
|
|
861
|
+
for (const package_ of packages_) {
|
|
862
|
+
const relativePath = path.relative(root, package_.path);
|
|
863
|
+
const policy = pickPolicy(policies, relativePath);
|
|
864
|
+
if (policy !== void 0 && policy.severity !== "off") await resolvePolicy(policy, scriptName, package_, relativePath, diagnostics);
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
return diagnostics;
|
|
868
|
+
}
|
|
869
|
+
function isCommandMatch(actual, expected) {
|
|
870
|
+
if (typeof expected === "function") return expected(actual);
|
|
871
|
+
if (expected instanceof RegExp) return expected.test(actual);
|
|
872
|
+
return actual === expected;
|
|
873
|
+
}
|
|
874
|
+
function isGlobMatch(pattern, relativePath) {
|
|
875
|
+
if (pattern === "*") return true;
|
|
876
|
+
if (pattern === ".") return relativePath === "." || relativePath === "";
|
|
877
|
+
return wildcardMatch(pattern)(relativePath);
|
|
878
|
+
}
|
|
879
|
+
function isMatchAny(patterns, relativePath) {
|
|
880
|
+
for (const pattern of patterns) if (isGlobMatch(pattern, relativePath)) return true;
|
|
881
|
+
return false;
|
|
882
|
+
}
|
|
883
|
+
function isPolicyMatch(policy, relativePath) {
|
|
884
|
+
const include = policy.include ?? ["*"];
|
|
885
|
+
const exclude = policy.exclude ?? [];
|
|
886
|
+
return isMatchAny(include, relativePath) && !isMatchAny(exclude, relativePath);
|
|
887
|
+
}
|
|
888
|
+
function pickPolicy(policies, relativePath) {
|
|
889
|
+
for (const policy of policies) if (isPolicyMatch(policy, relativePath)) return policy;
|
|
890
|
+
}
|
|
891
|
+
async function resolvePolicy(policy, scriptName, package_, relativePath, diagnostics) {
|
|
892
|
+
const packageJson = await readPackageJson(path.join(package_.path, "package.json"));
|
|
893
|
+
const packageDisplayName = packageJson["name"] ?? path.basename(package_.path);
|
|
894
|
+
const hasScript = getScript(packageJson, scriptName) !== void 0;
|
|
895
|
+
const severity = policy.severity ?? "error";
|
|
896
|
+
if (policy.required !== false && !hasScript) {
|
|
897
|
+
diagnostics.push({
|
|
898
|
+
fix: policy.autofix && typeof policy.command === "string" ? policy.command : void 0,
|
|
899
|
+
message: `Missing required script "${scriptName}"`,
|
|
900
|
+
packageName: packageDisplayName,
|
|
901
|
+
packagePath: package_.path,
|
|
902
|
+
scriptName,
|
|
903
|
+
severity
|
|
904
|
+
});
|
|
905
|
+
return;
|
|
906
|
+
}
|
|
907
|
+
if (policy.command === void 0 || !hasScript) return;
|
|
908
|
+
if (policy.allowCustomCommands !== void 0 && isMatchAny(policy.allowCustomCommands, relativePath)) return;
|
|
909
|
+
const actualCommand = getScript(packageJson, scriptName);
|
|
910
|
+
if (actualCommand !== void 0 && isCommandMatch(actualCommand, policy.command)) return;
|
|
911
|
+
diagnostics.push({
|
|
912
|
+
actual: actualCommand,
|
|
913
|
+
expected: typeof policy.command === "string" ? policy.command : void 0,
|
|
914
|
+
fix: policy.autofix && typeof policy.command === "string" ? policy.command : void 0,
|
|
915
|
+
message: `Unexpected command for script "${scriptName}"`,
|
|
916
|
+
packageName: packageDisplayName,
|
|
917
|
+
packagePath: package_.path,
|
|
918
|
+
scriptName,
|
|
919
|
+
severity
|
|
920
|
+
});
|
|
921
|
+
}
|
|
922
|
+
async function resolve(config, root, packages_) {
|
|
923
|
+
const diagnostics = [];
|
|
924
|
+
const scriptDiags = await resolveScriptPolicies(config.scripts, root, packages_);
|
|
925
|
+
diagnostics.push(...scriptDiags);
|
|
926
|
+
return diagnostics;
|
|
927
|
+
}
|
|
928
|
+
//#endregion
|
|
929
|
+
//#region ../cli/dist/index.js
|
|
930
|
+
function formatDiagnostics(diagnostics, options) {
|
|
931
|
+
if ((options?.format ?? "pretty") === "json") return formatJson(diagnostics);
|
|
932
|
+
return formatPretty(diagnostics, options?.isDryRun);
|
|
933
|
+
}
|
|
934
|
+
function formatJson(diagnostics) {
|
|
935
|
+
return `${JSON.stringify(diagnostics, void 0, 2)}\n`;
|
|
936
|
+
}
|
|
937
|
+
function formatPretty(diagnostics, isDryRun) {
|
|
938
|
+
if (diagnostics.length === 0) return styleText(["bold", "green"], "✅ No issues found.");
|
|
939
|
+
const lines = [];
|
|
940
|
+
const byPackage = /* @__PURE__ */ new Map();
|
|
941
|
+
for (const d of diagnostics) {
|
|
942
|
+
const array = byPackage.get(d.packageName);
|
|
943
|
+
if (array) array.push(d);
|
|
944
|
+
else byPackage.set(d.packageName, [d]);
|
|
945
|
+
}
|
|
946
|
+
for (const [packageName, diags] of byPackage) {
|
|
947
|
+
lines.push("", `📦 ${styleText(["bold", "cyan"], packageName)}`);
|
|
948
|
+
for (const d of diags) pushDiagnostic(lines, d, isDryRun);
|
|
949
|
+
}
|
|
950
|
+
const errorCount = diagnostics.filter((d) => d.severity === "error").length;
|
|
951
|
+
const warningCount = diagnostics.filter((d) => d.severity === "warn").length;
|
|
952
|
+
const countParts = [];
|
|
953
|
+
if (errorCount > 0) countParts.push(styleText("red", `${String(errorCount)} error(s)`));
|
|
954
|
+
if (warningCount > 0) countParts.push(styleText("yellow", `${String(warningCount)} warning(s)`));
|
|
955
|
+
const summary = countParts.join(", ");
|
|
956
|
+
const summaryLine = `📋 Found ${String(diagnostics.length)} issue(s) — ${summary.length > 0 ? summary : "all clear"}`;
|
|
957
|
+
lines.push("", styleText("dim", summaryLine));
|
|
958
|
+
if (isDryRun) {
|
|
959
|
+
const fixableCount = diagnostics.filter((d) => d.fix && d.severity !== "off").length;
|
|
960
|
+
lines.push("", styleText("dim", `🔮 Dry-run: ${String(fixableCount)} fix(es) available`));
|
|
961
|
+
}
|
|
962
|
+
return lines.join("\n");
|
|
963
|
+
}
|
|
964
|
+
function pushDiagnostic(lines, d, isDryRun) {
|
|
965
|
+
const badge = severityBadge(d.severity);
|
|
966
|
+
const emoji = severityEmoji(d.severity);
|
|
967
|
+
lines.push(` ${emoji} ${badge} ${d.message}`);
|
|
968
|
+
if (d.expected && d.actual) lines.push(` ${styleText("dim", "Expected:")} ${styleText("cyan", d.expected)}`, ` ${styleText("dim", "Actual:")} ${styleText("red", d.actual)}`);
|
|
969
|
+
else if (d.expected) lines.push(` ${styleText("dim", "Expected:")} ${styleText("cyan", d.expected)}`);
|
|
970
|
+
else if (d.actual) lines.push(` ${styleText("dim", "Actual:")} ${styleText("red", d.actual)}`);
|
|
971
|
+
if (d.fix) {
|
|
972
|
+
const label = styleText("dim", isDryRun ? "Would fix:" : "Fix:");
|
|
973
|
+
const icon = isDryRun ? "🔮" : "🔧";
|
|
974
|
+
lines.push(` ${icon} ${label} ${d.fix}`);
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
function severityBadge(severity) {
|
|
978
|
+
if (severity === "error") return styleText(["bold", "red"], "ERROR");
|
|
979
|
+
if (severity === "warn") return styleText(["bold", "yellow"], "WARN");
|
|
980
|
+
return styleText("gray", "OFF");
|
|
981
|
+
}
|
|
982
|
+
function severityEmoji(severity) {
|
|
983
|
+
if (severity === "error") return "❌";
|
|
984
|
+
if (severity === "warn") return "⚠️ ";
|
|
985
|
+
return "⚪";
|
|
986
|
+
}
|
|
987
|
+
async function applyScriptFixes(diagnostics, options) {
|
|
988
|
+
const fixable = diagnostics.filter((d) => d.fix && d.severity !== "off");
|
|
989
|
+
const isDryRun = options?.isDryRun ?? false;
|
|
990
|
+
let fixed = 0;
|
|
991
|
+
let errors = 0;
|
|
992
|
+
const packages = /* @__PURE__ */ new Set();
|
|
993
|
+
for (const d of fixable) {
|
|
994
|
+
if (!d.fix) continue;
|
|
995
|
+
if (isDryRun) {
|
|
996
|
+
fixed++;
|
|
997
|
+
packages.add(d.packagePath);
|
|
998
|
+
continue;
|
|
999
|
+
}
|
|
1000
|
+
try {
|
|
1001
|
+
const packageFilePath = path.join(d.packagePath, "package.json");
|
|
1002
|
+
const { readFile, writeFile } = await import("node:fs/promises");
|
|
1003
|
+
const content = await readFile(packageFilePath, "utf8");
|
|
1004
|
+
const package_ = JSON.parse(content);
|
|
1005
|
+
const scriptName = d.scriptName;
|
|
1006
|
+
if (!scriptName) continue;
|
|
1007
|
+
const scriptsRecord = package_["scripts"];
|
|
1008
|
+
if (scriptsRecord) {
|
|
1009
|
+
const entries = Object.entries(scriptsRecord);
|
|
1010
|
+
if (!Object.hasOwn(scriptsRecord, scriptName)) entries.push([scriptName, d.fix]);
|
|
1011
|
+
package_["scripts"] = Object.fromEntries(entries.map(([name, command]) => {
|
|
1012
|
+
return name === scriptName ? [name, d.fix ?? command] : [name, command];
|
|
1013
|
+
}));
|
|
1014
|
+
}
|
|
1015
|
+
await writeFile(packageFilePath, `${JSON.stringify(package_, void 0, 2)}\n`, "utf8");
|
|
1016
|
+
fixed++;
|
|
1017
|
+
packages.add(d.packagePath);
|
|
1018
|
+
} catch {
|
|
1019
|
+
errors++;
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
return {
|
|
1023
|
+
errors,
|
|
1024
|
+
fixed,
|
|
1025
|
+
isDryRun,
|
|
1026
|
+
packageCount: packages.size
|
|
1027
|
+
};
|
|
1028
|
+
}
|
|
1029
|
+
async function check(options) {
|
|
1030
|
+
const cwd = process.cwd();
|
|
1031
|
+
let config;
|
|
1032
|
+
try {
|
|
1033
|
+
config = await loadConfig(cwd);
|
|
1034
|
+
} catch {
|
|
1035
|
+
throw new Error("No moniq.config file found in or above the current directory.");
|
|
1036
|
+
}
|
|
1037
|
+
const packages = discoverWorkspace(cwd);
|
|
1038
|
+
if (packages.length === 0) throw new Error("No workspace packages found.");
|
|
1039
|
+
const diagnostics = await resolve(config, cwd, packages);
|
|
1040
|
+
let fixSummary;
|
|
1041
|
+
if (options.fix) fixSummary = await applyScriptFixes(diagnostics, { isDryRun: options.isDryRun });
|
|
1042
|
+
if (options.format !== "json") {
|
|
1043
|
+
console.log(` 🔍 Scanned ${String(packages.length)} package(s)`);
|
|
1044
|
+
console.log();
|
|
1045
|
+
}
|
|
1046
|
+
console.log(formatDiagnostics(diagnostics, {
|
|
1047
|
+
format: options.format,
|
|
1048
|
+
isDryRun: options.isDryRun
|
|
1049
|
+
}));
|
|
1050
|
+
if (fixSummary) if (fixSummary.isDryRun) {
|
|
1051
|
+
const message = `🔮 Dry-run: ${String(fixSummary.fixed)} fix(es) available, ${String(fixSummary.errors)} error(s)`;
|
|
1052
|
+
console.log(styleText("dim", message));
|
|
1053
|
+
} else {
|
|
1054
|
+
const message = `✅ Fixed ${String(fixSummary.fixed)} issue(s) across ${String(fixSummary.packageCount)} package(s)`;
|
|
1055
|
+
console.log(styleText(["bold", "green"], message));
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
async function doctor() {
|
|
1059
|
+
const cwd = process.cwd();
|
|
1060
|
+
const issues = [];
|
|
1061
|
+
try {
|
|
1062
|
+
const config = await loadConfig(cwd);
|
|
1063
|
+
issues.push({
|
|
1064
|
+
message: "moniq.config file found and loadable.",
|
|
1065
|
+
severity: "warn"
|
|
1066
|
+
});
|
|
1067
|
+
checkScriptPolicies(config, issues);
|
|
1068
|
+
} catch {
|
|
1069
|
+
issues.push({
|
|
1070
|
+
message: "No moniq.config file found in or above the current directory.",
|
|
1071
|
+
severity: "error"
|
|
1072
|
+
});
|
|
1073
|
+
}
|
|
1074
|
+
try {
|
|
1075
|
+
const packageCount = discoverWorkspace(cwd).length;
|
|
1076
|
+
if (packageCount === 0) issues.push({
|
|
1077
|
+
message: "No workspace packages detected. Check your workspace configuration.",
|
|
1078
|
+
severity: "warn"
|
|
1079
|
+
});
|
|
1080
|
+
else issues.push({
|
|
1081
|
+
message: `Detected ${String(packageCount)} workspace package(s).`,
|
|
1082
|
+
severity: "warn"
|
|
1083
|
+
});
|
|
1084
|
+
} catch {
|
|
1085
|
+
issues.push({
|
|
1086
|
+
message: "Failed to discover workspace packages. Ensure a lock file or packageManager field is present.",
|
|
1087
|
+
severity: "error"
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
1090
|
+
console.log();
|
|
1091
|
+
console.log(` ${styleText("bold", "🏥 Configuration Doctor")}`);
|
|
1092
|
+
console.log();
|
|
1093
|
+
if (issues.length === 0) {
|
|
1094
|
+
console.log(` ${styleText(["bold", "green"], "✅ Everything looks good!")}`);
|
|
1095
|
+
return;
|
|
1096
|
+
}
|
|
1097
|
+
for (const issue of issues) {
|
|
1098
|
+
const icon = issue.severity === "error" ? "❌" : "⚠️ ";
|
|
1099
|
+
const label = issue.severity === "error" ? styleText(["bold", "red"], "ERROR") : styleText(["bold", "yellow"], "WARN");
|
|
1100
|
+
console.log(` ${icon} ${label} ${issue.message}`);
|
|
1101
|
+
}
|
|
1102
|
+
const errorCount = issues.filter((index) => index.severity === "error").length;
|
|
1103
|
+
const warningCount = issues.filter((index) => index.severity === "warn").length;
|
|
1104
|
+
const summary = styleText("dim", `Found ${`${String(errorCount)} error(s)`}, ${`${String(warningCount)} warning(s)`}`);
|
|
1105
|
+
console.log();
|
|
1106
|
+
console.log(` ${summary}`);
|
|
1107
|
+
if (errorCount > 0) {
|
|
1108
|
+
const tip = styleText(["bold", "cyan"], "💡 Tip:");
|
|
1109
|
+
const hint = styleText("dim", "moniq init");
|
|
1110
|
+
console.log();
|
|
1111
|
+
console.log(` ${tip} Run ${hint} to scaffold a starter configuration.`);
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
function checkScriptPolicies(config, issues) {
|
|
1115
|
+
const scripts = config.scripts;
|
|
1116
|
+
if (!scripts) return;
|
|
1117
|
+
for (const [name, policyOrArray] of Object.entries(scripts)) {
|
|
1118
|
+
const policies = Array.isArray(policyOrArray) ? policyOrArray : [policyOrArray];
|
|
1119
|
+
for (const policy of policies) {
|
|
1120
|
+
const sev = policy.severity;
|
|
1121
|
+
if (sev !== void 0 && ![
|
|
1122
|
+
"error",
|
|
1123
|
+
"off",
|
|
1124
|
+
"warn"
|
|
1125
|
+
].includes(sev)) issues.push({
|
|
1126
|
+
message: `Script policy "${name}" has invalid severity "${sev}".`,
|
|
1127
|
+
severity: "error"
|
|
1128
|
+
});
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
const colorFns = [
|
|
1133
|
+
(s) => styleText("cyan", s),
|
|
1134
|
+
(s) => styleText("magenta", s),
|
|
1135
|
+
(s) => styleText("green", s),
|
|
1136
|
+
(s) => styleText("yellow", s),
|
|
1137
|
+
(s) => styleText("blue", s)
|
|
1138
|
+
];
|
|
1139
|
+
const letterRows = [
|
|
1140
|
+
[
|
|
1141
|
+
"███╗ ███╗",
|
|
1142
|
+
"████╗ ████║",
|
|
1143
|
+
"██╔████╔██║",
|
|
1144
|
+
"██║╚██╔╝██║",
|
|
1145
|
+
"██║ ╚═╝ ██║",
|
|
1146
|
+
"╚═╝ ╚═╝"
|
|
1147
|
+
],
|
|
1148
|
+
[
|
|
1149
|
+
" ██████╗ ",
|
|
1150
|
+
"██╔═══██╗",
|
|
1151
|
+
"██║ ██║",
|
|
1152
|
+
"██║ ██║",
|
|
1153
|
+
"╚██████╔╝",
|
|
1154
|
+
" ╚═════╝ "
|
|
1155
|
+
],
|
|
1156
|
+
[
|
|
1157
|
+
"███╗ ██╗",
|
|
1158
|
+
"████╗ ██║",
|
|
1159
|
+
"██╔██╗ ██║",
|
|
1160
|
+
"██║╚██╗██║",
|
|
1161
|
+
"██║ ╚████║",
|
|
1162
|
+
"╚═╝ ╚═══╝"
|
|
1163
|
+
],
|
|
1164
|
+
[
|
|
1165
|
+
"██╗",
|
|
1166
|
+
"██║",
|
|
1167
|
+
"██║",
|
|
1168
|
+
"██║",
|
|
1169
|
+
"██║",
|
|
1170
|
+
"╚═╝"
|
|
1171
|
+
],
|
|
1172
|
+
[
|
|
1173
|
+
" ██████╗ ",
|
|
1174
|
+
"██╔═══██╗",
|
|
1175
|
+
"██║ ██║",
|
|
1176
|
+
"██║ ██║",
|
|
1177
|
+
"╚██████╔╝",
|
|
1178
|
+
" ╚════╝╗ "
|
|
1179
|
+
]
|
|
1180
|
+
];
|
|
1181
|
+
const DESCRIPTION = "Policy-driven workspace linter for JavaScript/TypeScript monorepos.";
|
|
1182
|
+
function renderBanner() {
|
|
1183
|
+
const lines = [];
|
|
1184
|
+
for (let rowIndex = 0; rowIndex < 6; rowIndex++) lines.push(assembleRow(rowIndex));
|
|
1185
|
+
const description = centerPad(DESCRIPTION, 62);
|
|
1186
|
+
lines.push("", description);
|
|
1187
|
+
return lines.join("\n");
|
|
1188
|
+
}
|
|
1189
|
+
function assembleRow(rowIndex) {
|
|
1190
|
+
let row = " ".repeat(6);
|
|
1191
|
+
for (let columnIndex = 0; columnIndex < 5; columnIndex++) {
|
|
1192
|
+
row += rowPart(columnIndex, rowIndex);
|
|
1193
|
+
if (columnIndex < 4) row += " ";
|
|
1194
|
+
}
|
|
1195
|
+
return row;
|
|
1196
|
+
}
|
|
1197
|
+
function centerPad(text, width) {
|
|
1198
|
+
const pad = Math.max(0, Math.floor((width - text.length) / 2));
|
|
1199
|
+
return " ".repeat(pad) + text;
|
|
1200
|
+
}
|
|
1201
|
+
function rowPart(columnIndex, rowIndex) {
|
|
1202
|
+
const rows = letterRows.at(columnIndex);
|
|
1203
|
+
const colorFunction = colorFns.at(columnIndex);
|
|
1204
|
+
if (rows === void 0 || colorFunction === void 0) return "";
|
|
1205
|
+
const line = rows.at(rowIndex);
|
|
1206
|
+
return line === void 0 ? "" : colorFunction(line);
|
|
1207
|
+
}
|
|
1208
|
+
const SUPPORTED_LANGS = [
|
|
1209
|
+
"ts",
|
|
1210
|
+
"js",
|
|
1211
|
+
"mjs",
|
|
1212
|
+
"cjs",
|
|
1213
|
+
"mts",
|
|
1214
|
+
"cts"
|
|
1215
|
+
];
|
|
1216
|
+
const STARTER_CONFIG = `import { defineConfig } from "@udohjeremiah/moniq";
|
|
1217
|
+
|
|
1218
|
+
export default defineConfig({
|
|
1219
|
+
scripts: {
|
|
1220
|
+
dev: { required: true },
|
|
1221
|
+
build: { required: true },
|
|
1222
|
+
lint: { required: true },
|
|
1223
|
+
},
|
|
1224
|
+
});
|
|
1225
|
+
`;
|
|
1226
|
+
async function init(options) {
|
|
1227
|
+
const { lang } = options;
|
|
1228
|
+
if (!SUPPORTED_LANGS.includes(lang)) {
|
|
1229
|
+
const unsupportedMessage = `Unsupported --lang "${lang}". Supported: ${SUPPORTED_LANGS.join(", ")}`;
|
|
1230
|
+
console.error(` ${styleText("yellow", unsupportedMessage)}`);
|
|
1231
|
+
process.exitCode = 1;
|
|
1232
|
+
return;
|
|
1233
|
+
}
|
|
1234
|
+
const cwd = process.cwd();
|
|
1235
|
+
const filename = `moniq.config.${lang}`;
|
|
1236
|
+
const targetPath = path.join(cwd, filename);
|
|
1237
|
+
try {
|
|
1238
|
+
await access(targetPath);
|
|
1239
|
+
const existsMessage = `⚠️ ${filename} already exists. Remove it first to reinitialize.`;
|
|
1240
|
+
console.log(` ${styleText("yellow", existsMessage)}`);
|
|
1241
|
+
return;
|
|
1242
|
+
} catch {}
|
|
1243
|
+
const { writeFile } = await import("node:fs/promises");
|
|
1244
|
+
await writeFile(targetPath, STARTER_CONFIG, "utf8");
|
|
1245
|
+
console.log(renderBanner());
|
|
1246
|
+
console.log();
|
|
1247
|
+
const created = `✅ Created ${filename}`;
|
|
1248
|
+
console.log(` ${styleText(["bold", "green"], created)}`);
|
|
1249
|
+
console.log();
|
|
1250
|
+
console.log(` ${styleText("dim", "Next steps:")}`);
|
|
1251
|
+
console.log(` 1. ${styleText("dim", "Edit")} ${styleText("cyan", filename)} ${styleText("dim", "to configure your script policies.")}`);
|
|
1252
|
+
console.log(` 2. ${styleText("dim", "Run")} ${styleText("cyan", "moniq doctor")} ${styleText("dim", "to verify your configuration.")}`);
|
|
1253
|
+
console.log(` 3. ${styleText("dim", "Run")} ${styleText("cyan", "moniq check")} ${styleText("dim", "to validate your workspace.")}`);
|
|
1254
|
+
console.log(` 4. ${styleText("dim", "Run")} ${styleText("cyan", "moniq fix")} ${styleText("dim", "to apply automatic fixes.")}`);
|
|
1255
|
+
console.log();
|
|
1256
|
+
}
|
|
1257
|
+
const cli = cac("moniq");
|
|
1258
|
+
cli.command("check", "Run policy checks").option("--format <fmt>", "Output format: pretty or json", { default: "pretty" }).action(async (options) => {
|
|
1259
|
+
const fmt = typeof options["format"] === "string" ? options["format"] : "pretty";
|
|
1260
|
+
try {
|
|
1261
|
+
await check({
|
|
1262
|
+
fix: false,
|
|
1263
|
+
format: fmt
|
|
1264
|
+
});
|
|
1265
|
+
} catch (error) {
|
|
1266
|
+
console.error(String(error));
|
|
1267
|
+
process.exitCode = 1;
|
|
1268
|
+
}
|
|
1269
|
+
});
|
|
1270
|
+
cli.command("fix", "Run policy checks and apply autofixes").option("--dry-run", "Preview autofixes without writing to files").option("--format <fmt>", "Output format: pretty or json", { default: "pretty" }).action(async (options) => {
|
|
1271
|
+
const isDryRun = options["dryRun"] === true;
|
|
1272
|
+
const fmt = typeof options["format"] === "string" ? options["format"] : "pretty";
|
|
1273
|
+
try {
|
|
1274
|
+
await check({
|
|
1275
|
+
fix: true,
|
|
1276
|
+
format: fmt,
|
|
1277
|
+
isDryRun
|
|
1278
|
+
});
|
|
1279
|
+
} catch (error) {
|
|
1280
|
+
console.error(String(error));
|
|
1281
|
+
process.exitCode = 1;
|
|
1282
|
+
}
|
|
1283
|
+
});
|
|
1284
|
+
cli.command("doctor", "Detect configuration mistakes").action(async () => {
|
|
1285
|
+
await doctor();
|
|
1286
|
+
});
|
|
1287
|
+
cli.command("init", "Scaffold a moniq.config file in the current directory").option("--lang <type>", "Config language: ts, js, mjs, cjs, mts, cts (default: ts)").action(async (options) => {
|
|
1288
|
+
await init({ lang: typeof options["lang"] === "string" ? options["lang"] : "ts" });
|
|
1289
|
+
});
|
|
1290
|
+
cli.help();
|
|
1291
|
+
cli.parse();
|
|
1292
|
+
//#endregion
|
|
1293
|
+
export {};
|
|
1294
|
+
|
|
1295
|
+
//# sourceMappingURL=cli.js.map
|