@rrlab/cli 1.3.5 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/cli.usage.kdl +1 -1
- package/dist/plugin/__tests__/bin-probe.test.mjs +1 -1
- package/dist/plugin/__tests__/decide-scaffold.test.mjs +1 -1
- package/dist/plugin/__tests__/define-plugin.test.mjs +1 -1
- package/dist/plugin/__tests__/pick-preset.test.mjs +1 -1
- package/dist/plugin/__tests__/registry.test.mjs +1 -1
- package/dist/run.mjs +77 -19
- package/dist/{test.DNmyFkvJ-h0bAJWRJ.mjs → test.DNmyFkvJ-Bszob22e.mjs} +116 -81
- package/package.json +5 -5
- package/src/actions/plugins/add.ts +2 -2
- package/src/actions/plugins/remove.ts +5 -2
- package/src/errors/confirmation-required.ts +7 -0
- package/src/services/config-ast.ts +50 -9
- package/src/services/prompts.ts +9 -0
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
## Prerequisites
|
|
10
10
|
|
|
11
|
-
- Node.js >=
|
|
11
|
+
- Node.js >= 22.18.0
|
|
12
12
|
|
|
13
13
|
## Installation
|
|
14
14
|
|
|
@@ -40,6 +40,7 @@ See [`CLI.md`](./CLI.md) for the full reference (auto-generated per release).
|
|
|
40
40
|
| `oxc` | [oxlint](https://oxc.rs/docs/guide/usage/linter.html) + [oxfmt](https://oxc.rs/docs/guide/usage/formatter.html) | `rr plugins add oxc` |
|
|
41
41
|
| `ts` | [tsc](https://www.typescriptlang.org) | `rr plugins add ts` |
|
|
42
42
|
| `tsdown` | [tsdown](https://tsdown.dev) | `rr plugins add tsdown` |
|
|
43
|
+
| `vitest` | [vitest](https://vitest.dev) | `rr plugins add vitest` |
|
|
43
44
|
|
|
44
45
|
Install one with:
|
|
45
46
|
|
package/dist/cli.usage.kdl
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @generated by @usage-spec/commander from Commander.js metadata
|
|
2
2
|
name rr
|
|
3
3
|
bin rr
|
|
4
|
-
version "1.
|
|
4
|
+
version "1.4.0"
|
|
5
5
|
usage "[options] [command]"
|
|
6
6
|
flag --about help="show credits & inspiration"
|
|
7
7
|
flag --usage help="print KDL spec for this CLI (https://kdl.dev)"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ToolService } from "../tool-service.mjs";
|
|
2
2
|
import { probeBins } from "../bin-probe.mjs";
|
|
3
|
-
import { i as it, r as describe, t as globalExpect } from "../../test.DNmyFkvJ-
|
|
3
|
+
import { i as it, r as describe, t as globalExpect } from "../../test.DNmyFkvJ-Bszob22e.mjs";
|
|
4
4
|
//#region src/lib/plugin/__tests__/bin-probe.test.ts
|
|
5
5
|
const FROM = import.meta.url;
|
|
6
6
|
var ResolvableService = class extends ToolService {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { decideScaffold } from "../decide-scaffold.mjs";
|
|
2
|
-
import { i as it, n as vi, r as describe, t as globalExpect } from "../../test.DNmyFkvJ-
|
|
2
|
+
import { i as it, n as vi, r as describe, t as globalExpect } from "../../test.DNmyFkvJ-Bszob22e.mjs";
|
|
3
3
|
//#region src/lib/plugin/__tests__/decide-scaffold.test.ts
|
|
4
4
|
function makeCtx(overrides = {}) {
|
|
5
5
|
return {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ToolService } from "../tool-service.mjs";
|
|
2
2
|
import { definePlugin } from "../define-plugin.mjs";
|
|
3
|
-
import { i as it, r as describe, t as globalExpect } from "../../test.DNmyFkvJ-
|
|
3
|
+
import { i as it, r as describe, t as globalExpect } from "../../test.DNmyFkvJ-Bszob22e.mjs";
|
|
4
4
|
//#region src/lib/plugin/__tests__/define-plugin.test.ts
|
|
5
5
|
function ctx() {
|
|
6
6
|
return {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { pickPreset } from "../pick-preset.mjs";
|
|
2
|
-
import { i as it, n as vi, r as describe, t as globalExpect } from "../../test.DNmyFkvJ-
|
|
2
|
+
import { i as it, n as vi, r as describe, t as globalExpect } from "../../test.DNmyFkvJ-Bszob22e.mjs";
|
|
3
3
|
//#region src/lib/plugin/__tests__/pick-preset.test.ts
|
|
4
4
|
function makeCtx(overrides = {}) {
|
|
5
5
|
return {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as PluginRegistry } from "../../registry-B-GhzVIO.mjs";
|
|
2
|
-
import { i as it, r as describe, t as globalExpect } from "../../test.DNmyFkvJ-
|
|
2
|
+
import { i as it, r as describe, t as globalExpect } from "../../test.DNmyFkvJ-Bszob22e.mjs";
|
|
3
3
|
//#region src/lib/plugin/__tests__/registry.test.ts
|
|
4
4
|
function plugin(name) {
|
|
5
5
|
return {
|
package/dist/run.mjs
CHANGED
|
@@ -12,7 +12,7 @@ import { rimraf } from "rimraf";
|
|
|
12
12
|
import * as clack from "@clack/prompts";
|
|
13
13
|
import { addDependency, detectPackageManager, removeDependency } from "nypm";
|
|
14
14
|
import fs$1 from "node:fs/promises";
|
|
15
|
-
import { builders, generateCode, loadFile, parseModule
|
|
15
|
+
import { builders, generateCode, loadFile, parseModule } from "magicast";
|
|
16
16
|
import * as cjson from "comment-json";
|
|
17
17
|
import { generateToStdout } from "@usage-spec/commander";
|
|
18
18
|
//#region src/errors/known-error.ts
|
|
@@ -953,12 +953,7 @@ var ConfigAstService = class {
|
|
|
953
953
|
};
|
|
954
954
|
}
|
|
955
955
|
async save(loaded) {
|
|
956
|
-
|
|
957
|
-
const { code } = generateCode(loaded.mod);
|
|
958
|
-
await fs$1.writeFile(loaded.filepath, code, "utf8");
|
|
959
|
-
return;
|
|
960
|
-
}
|
|
961
|
-
await writeFile(loaded.mod.$ast, loaded.filepath);
|
|
956
|
+
await fs$1.writeFile(loaded.filepath, tidy(generateCode(loaded.mod).code), "utf8");
|
|
962
957
|
}
|
|
963
958
|
/**
|
|
964
959
|
* Returns true when the config's `plugins` array contains a call to the
|
|
@@ -979,11 +974,14 @@ var ConfigAstService = class {
|
|
|
979
974
|
*/
|
|
980
975
|
addPlugin(mod, entry) {
|
|
981
976
|
if (this.hasPlugin(mod, entry.exportName)) return { changed: false };
|
|
982
|
-
if (!mod.imports[entry.exportName])
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
977
|
+
if (!mod.imports[entry.exportName]) {
|
|
978
|
+
mod.imports.$add({
|
|
979
|
+
from: entry.pkgName,
|
|
980
|
+
imported: "default",
|
|
981
|
+
local: entry.exportName
|
|
982
|
+
});
|
|
983
|
+
this.#placeImport(mod, entry.pkgName);
|
|
984
|
+
}
|
|
987
985
|
this.#ensureDefineConfig(mod);
|
|
988
986
|
this.#ensurePluginsArray(mod).push(builders.functionCall(entry.exportName));
|
|
989
987
|
return { changed: true };
|
|
@@ -1028,12 +1026,32 @@ var ConfigAstService = class {
|
|
|
1028
1026
|
if (!opts || typeof opts !== "object") return void 0;
|
|
1029
1027
|
return opts.plugins;
|
|
1030
1028
|
}
|
|
1029
|
+
/**
|
|
1030
|
+
* Moves the import of `source`, which `imports.$add` puts first, to its
|
|
1031
|
+
* sorted place among the other imports, leaving those in their order: a
|
|
1032
|
+
* sorted file stays sorted, so `rr jsc` passes on what rr wrote.
|
|
1033
|
+
*/
|
|
1034
|
+
#placeImport(mod, source) {
|
|
1035
|
+
const program = mod.$ast;
|
|
1036
|
+
if (program.type !== "Program") return;
|
|
1037
|
+
const { body } = program;
|
|
1038
|
+
const from = body.findIndex((node) => node.type === "ImportDeclaration" && node.source.value === source);
|
|
1039
|
+
if (from === -1) return;
|
|
1040
|
+
const [added] = body.splice(from, 1);
|
|
1041
|
+
if (!added) return;
|
|
1042
|
+
const before = body.findIndex((node) => node.type === "ImportDeclaration" && compareImportSources(node.source.value, source) > 0);
|
|
1043
|
+
const lastImport = body.reduce((last, node, i) => node.type === "ImportDeclaration" ? i : last, -1);
|
|
1044
|
+
body.splice(before === -1 ? lastImport + 1 : before, 0, added);
|
|
1045
|
+
}
|
|
1031
1046
|
#ensureDefineConfig(mod) {
|
|
1032
|
-
if (!mod.imports.defineConfig)
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1047
|
+
if (!mod.imports.defineConfig) {
|
|
1048
|
+
mod.imports.$add({
|
|
1049
|
+
from: "@rrlab/cli/config",
|
|
1050
|
+
imported: "defineConfig",
|
|
1051
|
+
local: "defineConfig"
|
|
1052
|
+
});
|
|
1053
|
+
this.#placeImport(mod, "@rrlab/cli/config");
|
|
1054
|
+
}
|
|
1037
1055
|
if (!mod.exports.default) mod.exports.default = builders.functionCall("defineConfig", { plugins: [] });
|
|
1038
1056
|
}
|
|
1039
1057
|
#ensurePluginsArray(mod) {
|
|
@@ -1054,6 +1072,30 @@ var ConfigAstService = class {
|
|
|
1054
1072
|
if (typeof callee === "string") return callee;
|
|
1055
1073
|
}
|
|
1056
1074
|
};
|
|
1075
|
+
/**
|
|
1076
|
+
* Undoes two recast habits that formatters reject: it keeps the blank line that
|
|
1077
|
+
* followed an import when rr inserts another after it, and it drops the final
|
|
1078
|
+
* newline.
|
|
1079
|
+
*/
|
|
1080
|
+
function tidy(code) {
|
|
1081
|
+
const joined = code.replace(/^(import\b[^;]*;)\n(?:[ \t]*\n)+(?=import\b)/gm, "$1\n");
|
|
1082
|
+
return joined.endsWith("\n") ? joined : `${joined}\n`;
|
|
1083
|
+
}
|
|
1084
|
+
/**
|
|
1085
|
+
* Biome's organizeImports order: protocol imports (`node:fs`), then packages,
|
|
1086
|
+
* then aliases (`#src/…`, `@/…`, `~/…`), then paths. Within a group, plain
|
|
1087
|
+
* code-unit order, which matches Biome for these names (`ts-plugin` before
|
|
1088
|
+
* `tsdown-plugin`; `localeCompare` flips them).
|
|
1089
|
+
*/
|
|
1090
|
+
function compareImportSources(a, b) {
|
|
1091
|
+
const group = (source) => {
|
|
1092
|
+
if (/^[a-z]+:/.test(source)) return 0;
|
|
1093
|
+
if (/^(#|@\/|~)/.test(source)) return 2;
|
|
1094
|
+
if (source.startsWith(".") || source.startsWith("/")) return 3;
|
|
1095
|
+
return 1;
|
|
1096
|
+
};
|
|
1097
|
+
return group(a) - group(b) || (a < b ? -1 : a > b ? 1 : 0);
|
|
1098
|
+
}
|
|
1057
1099
|
const MINIMAL_TEMPLATE = `import { defineConfig } from "@rrlab/cli/config";
|
|
1058
1100
|
|
|
1059
1101
|
export default defineConfig({
|
|
@@ -1253,6 +1295,14 @@ async function pathExists(p) {
|
|
|
1253
1295
|
//#endregion
|
|
1254
1296
|
//#region src/services/prompts.ts
|
|
1255
1297
|
/**
|
|
1298
|
+
* Whether a prompt can run: clack reads keys from stdin and draws on stdout,
|
|
1299
|
+
* so both have to be terminals. An agent, a script or CI usually has neither,
|
|
1300
|
+
* and a prompt there waits forever or exits on a closed stdin.
|
|
1301
|
+
*/
|
|
1302
|
+
function canPrompt() {
|
|
1303
|
+
return !!process.stdin.isTTY && !!process.stdout.isTTY;
|
|
1304
|
+
}
|
|
1305
|
+
/**
|
|
1256
1306
|
* Adapter that exposes the subset of `@clack/prompts` matching the
|
|
1257
1307
|
* `ClackPrompts` contract from `@rrlab/cli/plugin`. The contract intentionally
|
|
1258
1308
|
* stays narrow (`select`, `confirm`, `isCancel`) so plugin install hooks can
|
|
@@ -1450,7 +1500,7 @@ async function addPluginAction({ ctx, args, options }) {
|
|
|
1450
1500
|
flags: {
|
|
1451
1501
|
force: !!options.force,
|
|
1452
1502
|
yes: !!options.yes,
|
|
1453
|
-
nonInteractive: !!options.yes
|
|
1503
|
+
nonInteractive: !!options.yes || !canPrompt()
|
|
1454
1504
|
},
|
|
1455
1505
|
release: new ReleaseService(tag)
|
|
1456
1506
|
};
|
|
@@ -1509,6 +1559,13 @@ async function listPluginsAction({ ctx }) {
|
|
|
1509
1559
|
for (const name of plugins) logger.info(` - ${name}`);
|
|
1510
1560
|
}
|
|
1511
1561
|
//#endregion
|
|
1562
|
+
//#region src/errors/confirmation-required.ts
|
|
1563
|
+
var ConfirmationRequiredError = class extends KnownError {
|
|
1564
|
+
constructor(command) {
|
|
1565
|
+
super(`'${command}' asks for confirmation, and there's no terminal to ask in. Re-run it with --yes.`);
|
|
1566
|
+
}
|
|
1567
|
+
};
|
|
1568
|
+
//#endregion
|
|
1512
1569
|
//#region src/actions/plugins/remove.ts
|
|
1513
1570
|
async function removePluginAction({ ctx, args, options }) {
|
|
1514
1571
|
const { name } = args;
|
|
@@ -1528,7 +1585,7 @@ async function removePluginAction({ ctx, args, options }) {
|
|
|
1528
1585
|
prompts: createClackPrompts(),
|
|
1529
1586
|
flags: {
|
|
1530
1587
|
yes: !!options.yes,
|
|
1531
|
-
nonInteractive: !!options.yes
|
|
1588
|
+
nonInteractive: !!options.yes || !canPrompt()
|
|
1532
1589
|
}
|
|
1533
1590
|
});
|
|
1534
1591
|
} catch (err) {
|
|
@@ -1557,6 +1614,7 @@ async function removePluginAction({ ctx, args, options }) {
|
|
|
1557
1614
|
return;
|
|
1558
1615
|
}
|
|
1559
1616
|
if (!options.yes) {
|
|
1617
|
+
if (!canPrompt()) throw new ConfirmationRequiredError(`rr plugins remove ${name}`);
|
|
1560
1618
|
const choice = await clack.confirm({
|
|
1561
1619
|
message: "Proceed?",
|
|
1562
1620
|
initialValue: false
|
|
@@ -81,7 +81,7 @@ function C({ force: e } = {}) {
|
|
|
81
81
|
}
|
|
82
82
|
var y = C();
|
|
83
83
|
//#endregion
|
|
84
|
-
//#region ../../node_modules/.pnpm/@vitest+pretty-format@4.1.
|
|
84
|
+
//#region ../../node_modules/.pnpm/@vitest+pretty-format@4.1.12/node_modules/@vitest/pretty-format/dist/index.js
|
|
85
85
|
function _mergeNamespaces(n, m) {
|
|
86
86
|
m.forEach(function(e) {
|
|
87
87
|
e && typeof e !== "string" && !Array.isArray(e) && Object.keys(e).forEach(function(k) {
|
|
@@ -964,7 +964,7 @@ const plugins = {
|
|
|
964
964
|
Error: ErrorPlugin
|
|
965
965
|
};
|
|
966
966
|
//#endregion
|
|
967
|
-
//#region ../../node_modules/.pnpm/@vitest+utils@4.1.
|
|
967
|
+
//#region ../../node_modules/.pnpm/@vitest+utils@4.1.12/node_modules/@vitest/utils/dist/display.js
|
|
968
968
|
const ansiColors$1 = {
|
|
969
969
|
bold: ["1", "22"],
|
|
970
970
|
dim: ["2", "22"],
|
|
@@ -1518,7 +1518,7 @@ function objDisplay$1(obj, options = {}) {
|
|
|
1518
1518
|
return str;
|
|
1519
1519
|
}
|
|
1520
1520
|
//#endregion
|
|
1521
|
-
//#region ../../node_modules/.pnpm/@vitest+utils@4.1.
|
|
1521
|
+
//#region ../../node_modules/.pnpm/@vitest+utils@4.1.12/node_modules/@vitest/utils/dist/helpers.js
|
|
1522
1522
|
/**
|
|
1523
1523
|
* Get original stacktrace without source map support the most performant way.
|
|
1524
1524
|
* - Create only 1 stack frame.
|
|
@@ -3004,7 +3004,7 @@ function getCommonAndChangedSubstrings(diffs, op, hasCommonDiff) {
|
|
|
3004
3004
|
return diffs.reduce((reduced, diff) => reduced + (diff[0] === 0 ? diff[1] : diff[0] === op ? hasCommonDiff ? y.inverse(diff[1]) : diff[1] : ""), "");
|
|
3005
3005
|
}
|
|
3006
3006
|
//#endregion
|
|
3007
|
-
//#region ../../node_modules/.pnpm/@vitest+utils@4.1.
|
|
3007
|
+
//#region ../../node_modules/.pnpm/@vitest+utils@4.1.12/node_modules/@vitest/utils/dist/serialize.js
|
|
3008
3008
|
const IS_RECORD_SYMBOL$1 = "@@__IMMUTABLE_RECORD__@@";
|
|
3009
3009
|
const IS_COLLECTION_SYMBOL = "@@__IMMUTABLE_ITERABLE__@@";
|
|
3010
3010
|
function isImmutable(v) {
|
|
@@ -3078,7 +3078,7 @@ function normalizeErrorMessage(message) {
|
|
|
3078
3078
|
return message.replace(/\(0\s?,\s?__vite_ssr_import_\d+__.(\w+)\)/g, "$1").replace(/__(vite_ssr_import|vi_import)_\d+__\./g, "").replace(/getByTestId('__vitest_\d+__')/g, "page");
|
|
3079
3079
|
}
|
|
3080
3080
|
//#endregion
|
|
3081
|
-
//#region ../../node_modules/.pnpm/@vitest+utils@4.1.
|
|
3081
|
+
//#region ../../node_modules/.pnpm/@vitest+utils@4.1.12/node_modules/@vitest/utils/dist/error.js
|
|
3082
3082
|
function processError(_err, diffOptions, seen = /* @__PURE__ */ new WeakSet()) {
|
|
3083
3083
|
if (!_err || typeof _err !== "object") return { message: String(_err) };
|
|
3084
3084
|
const err = _err;
|
|
@@ -3108,7 +3108,7 @@ function prettifyValue(value, options) {
|
|
|
3108
3108
|
return value;
|
|
3109
3109
|
}
|
|
3110
3110
|
//#endregion
|
|
3111
|
-
//#region ../../node_modules/.pnpm/@vitest+utils@4.1.
|
|
3111
|
+
//#region ../../node_modules/.pnpm/@vitest+utils@4.1.12/node_modules/@vitest/utils/dist/timers.js
|
|
3112
3112
|
const SAFE_TIMERS_SYMBOL = Symbol("vitest:SAFE_TIMERS");
|
|
3113
3113
|
function getSafeTimers() {
|
|
3114
3114
|
const { setTimeout: safeSetTimeout, setInterval: safeSetInterval, clearInterval: safeClearInterval, clearTimeout: safeClearTimeout, setImmediate: safeSetImmediate, clearImmediate: safeClearImmediate, queueMicrotask: safeQueueMicrotask } = globalThis[SAFE_TIMERS_SYMBOL] || globalThis;
|
|
@@ -3142,7 +3142,7 @@ function delay(timeout, scheduler = setTimeout) {
|
|
|
3142
3142
|
return new Promise((resolve) => scheduler(resolve, timeout));
|
|
3143
3143
|
}
|
|
3144
3144
|
//#endregion
|
|
3145
|
-
//#region ../../node_modules/.pnpm/@vitest+utils@4.1.
|
|
3145
|
+
//#region ../../node_modules/.pnpm/@vitest+utils@4.1.12/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js
|
|
3146
3146
|
const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
|
|
3147
3147
|
function normalizeWindowsPath(input = "") {
|
|
3148
3148
|
if (!input) return input;
|
|
@@ -3221,7 +3221,7 @@ const isAbsolute = function(p) {
|
|
|
3221
3221
|
return _IS_ABSOLUTE_RE.test(p);
|
|
3222
3222
|
};
|
|
3223
3223
|
//#endregion
|
|
3224
|
-
//#region ../../node_modules/.pnpm/@vitest+utils@4.1.
|
|
3224
|
+
//#region ../../node_modules/.pnpm/@vitest+utils@4.1.12/node_modules/@vitest/utils/dist/source-map.js
|
|
3225
3225
|
var comma = ",".charCodeAt(0);
|
|
3226
3226
|
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
3227
3227
|
var intToChar = new Uint8Array(64);
|
|
@@ -3589,7 +3589,7 @@ function getOriginalPosition(map, needle) {
|
|
|
3589
3589
|
return result;
|
|
3590
3590
|
}
|
|
3591
3591
|
//#endregion
|
|
3592
|
-
//#region ../../node_modules/.pnpm/@vitest+runner@4.1.
|
|
3592
|
+
//#region ../../node_modules/.pnpm/@vitest+runner@4.1.12/node_modules/@vitest/runner/dist/chunk-artifact.js
|
|
3593
3593
|
var PendingError = class extends Error {
|
|
3594
3594
|
code = "VITEST_PENDING";
|
|
3595
3595
|
taskId;
|
|
@@ -5092,7 +5092,7 @@ function manageArtifactAttachment(attachment) {
|
|
|
5092
5092
|
if (attachment.body != null) attachment.bodyEncoding ??= "base64";
|
|
5093
5093
|
}
|
|
5094
5094
|
//#endregion
|
|
5095
|
-
//#region ../../node_modules/.pnpm/vitest@4.1.
|
|
5095
|
+
//#region ../../node_modules/.pnpm/vitest@4.1.12_@types+node@25.9.1_vite@8.3.4_@types+node@25.9.1_yaml@2.9.1_/node_modules/vitest/dist/chunks/utils.BX5Fg8C4.js
|
|
5096
5096
|
const NAME_WORKER_STATE = "__vitest_worker__";
|
|
5097
5097
|
function getWorkerState() {
|
|
5098
5098
|
const workerState = globalThis[NAME_WORKER_STATE];
|
|
@@ -5132,7 +5132,7 @@ async function waitForImportsToResolve() {
|
|
|
5132
5132
|
await waitForImportsToResolve();
|
|
5133
5133
|
}
|
|
5134
5134
|
//#endregion
|
|
5135
|
-
//#region ../../node_modules/.pnpm/@vitest+spy@4.1.
|
|
5135
|
+
//#region ../../node_modules/.pnpm/@vitest+spy@4.1.12/node_modules/@vitest/spy/dist/index.js
|
|
5136
5136
|
function isMockFunction(fn) {
|
|
5137
5137
|
return typeof fn === "function" && "_isMockFunction" in fn && fn._isMockFunction === true;
|
|
5138
5138
|
}
|
|
@@ -5515,7 +5515,7 @@ function throwConstructorError(shorthand) {
|
|
|
5515
5515
|
throw new TypeError(`Cannot use \`${shorthand}\` when called with \`new\`. Use \`mockImplementation\` with a \`class\` keyword instead. See https://vitest.dev/api/mock#class-support for more information.`);
|
|
5516
5516
|
}
|
|
5517
5517
|
//#endregion
|
|
5518
|
-
//#region ../../node_modules/.pnpm/chai@6.
|
|
5518
|
+
//#region ../../node_modules/.pnpm/chai@6.3.0/node_modules/chai/index.js
|
|
5519
5519
|
var __defProp = Object.defineProperty;
|
|
5520
5520
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {
|
|
5521
5521
|
enumerable: true,
|
|
@@ -5596,6 +5596,7 @@ function compatibleConstructor(thrown, errorLike) {
|
|
|
5596
5596
|
__name(compatibleConstructor, "compatibleConstructor");
|
|
5597
5597
|
function compatibleMessage(thrown, errMatcher) {
|
|
5598
5598
|
const comparisonString = typeof thrown === "string" ? thrown : thrown.message;
|
|
5599
|
+
if (comparisonString === void 0) return false;
|
|
5599
5600
|
if (isRegExp(errMatcher)) return errMatcher.test(comparisonString);
|
|
5600
5601
|
else if (typeof errMatcher === "string") return comparisonString.indexOf(errMatcher) !== -1;
|
|
5601
5602
|
return false;
|
|
@@ -6252,8 +6253,10 @@ function inspect2(obj, showHidden, depth, colors) {
|
|
|
6252
6253
|
__name(inspect2, "inspect");
|
|
6253
6254
|
function objDisplay(obj) {
|
|
6254
6255
|
let str = inspect2(obj), type3 = Object.prototype.toString.call(obj);
|
|
6255
|
-
if (config.truncateThreshold && str.length >= config.truncateThreshold) if (type3 === "[object Function]")
|
|
6256
|
-
|
|
6256
|
+
if (config.truncateThreshold && str.length >= config.truncateThreshold) if (type3 === "[object Function]") {
|
|
6257
|
+
const objAsFunction = obj;
|
|
6258
|
+
return !objAsFunction.name || objAsFunction.name === "" ? "[Function]" : "[Function: " + objAsFunction.name + "]";
|
|
6259
|
+
} else if (type3 === "[object Array]") return "[ Array(" + obj.length + ") ]";
|
|
6257
6260
|
else if (type3 === "[object Object]") {
|
|
6258
6261
|
let keys = Object.keys(obj);
|
|
6259
6262
|
return "{ Object (" + (keys.length > 2 ? keys.splice(0, 2).join(", ") + ", ..." : keys.join(", ")) + ") }";
|
|
@@ -6266,25 +6269,24 @@ function getMessage2(obj, args) {
|
|
|
6266
6269
|
let val = flag(obj, "object");
|
|
6267
6270
|
let expected = args[3];
|
|
6268
6271
|
let actual = getActual(obj, args);
|
|
6269
|
-
let
|
|
6272
|
+
let rawMsg = negate ? args[2] : args[1];
|
|
6270
6273
|
let flagMsg = flag(obj, "message");
|
|
6271
|
-
if (typeof
|
|
6272
|
-
msg =
|
|
6273
|
-
|
|
6274
|
-
return objDisplay(
|
|
6275
|
-
}).replace(/#\{act\}/g, function() {
|
|
6276
|
-
return objDisplay(actual);
|
|
6277
|
-
}).replace(/#\{exp\}/g, function() {
|
|
6274
|
+
if (typeof rawMsg === "function") rawMsg = rawMsg();
|
|
6275
|
+
const msg = (rawMsg || "").replace(/#\{(this|act|exp)\}/g, function(_, tag) {
|
|
6276
|
+
if (tag === "this") return objDisplay(val);
|
|
6277
|
+
if (tag === "act") return objDisplay(actual);
|
|
6278
6278
|
return objDisplay(expected);
|
|
6279
6279
|
});
|
|
6280
6280
|
return flagMsg ? flagMsg + ": " + msg : msg;
|
|
6281
6281
|
}
|
|
6282
6282
|
__name(getMessage2, "getMessage");
|
|
6283
|
-
function transferFlags(
|
|
6284
|
-
|
|
6285
|
-
|
|
6283
|
+
function transferFlags(source, object, includeAll) {
|
|
6284
|
+
const sourceWithFlags = source;
|
|
6285
|
+
const objWithFlags = object;
|
|
6286
|
+
let flags = sourceWithFlags.__flags || (sourceWithFlags.__flags = /* @__PURE__ */ Object.create(null));
|
|
6287
|
+
const objFlags = objWithFlags.__flags || (objWithFlags.__flags = /* @__PURE__ */ Object.create(null));
|
|
6286
6288
|
includeAll = arguments.length === 3 ? includeAll : true;
|
|
6287
|
-
for (let flag3 in flags) if (includeAll || flag3 !== "object" && flag3 !== "ssfi" && flag3 !== "lockSsfi" && flag3 != "message")
|
|
6289
|
+
for (let flag3 in flags) if (includeAll || flag3 !== "object" && flag3 !== "ssfi" && flag3 !== "lockSsfi" && flag3 != "message") objFlags[flag3] = flags[flag3];
|
|
6288
6290
|
}
|
|
6289
6291
|
__name(transferFlags, "transferFlags");
|
|
6290
6292
|
function type2(obj) {
|
|
@@ -6611,9 +6613,9 @@ var _Assertion = class _Assertion {
|
|
|
6611
6613
|
* - `eql`: This flag contains the deepEqual function to be used by the assertion.
|
|
6612
6614
|
*
|
|
6613
6615
|
* @param {unknown} obj target of the assertion
|
|
6614
|
-
* @param {string}
|
|
6615
|
-
* @param {Function}
|
|
6616
|
-
* @param {boolean}
|
|
6616
|
+
* @param {string=} msg (optional) custom error message
|
|
6617
|
+
* @param {Function=} ssfi (optional) starting point for removing stack frames
|
|
6618
|
+
* @param {boolean=} lockSsfi (optional) whether or not the ssfi flag is locked
|
|
6617
6619
|
*/
|
|
6618
6620
|
constructor(obj, msg, ssfi, lockSsfi) {
|
|
6619
6621
|
/** @type {{}} */
|
|
@@ -6647,44 +6649,44 @@ var _Assertion = class _Assertion {
|
|
|
6647
6649
|
}
|
|
6648
6650
|
/**
|
|
6649
6651
|
* @param {string} name
|
|
6650
|
-
* @param {
|
|
6652
|
+
* @param {(...args: never) => unknown} fn
|
|
6651
6653
|
*/
|
|
6652
6654
|
static addProperty(name, fn) {
|
|
6653
6655
|
addProperty(this.prototype, name, fn);
|
|
6654
6656
|
}
|
|
6655
6657
|
/**
|
|
6656
6658
|
* @param {string} name
|
|
6657
|
-
* @param {
|
|
6659
|
+
* @param {(...args: never) => unknown} fn
|
|
6658
6660
|
*/
|
|
6659
6661
|
static addMethod(name, fn) {
|
|
6660
6662
|
addMethod(this.prototype, name, fn);
|
|
6661
6663
|
}
|
|
6662
6664
|
/**
|
|
6663
6665
|
* @param {string} name
|
|
6664
|
-
* @param {
|
|
6665
|
-
* @param {
|
|
6666
|
+
* @param {(...args: never) => unknown} fn
|
|
6667
|
+
* @param {(...args: never) => unknown} chainingBehavior
|
|
6666
6668
|
*/
|
|
6667
6669
|
static addChainableMethod(name, fn, chainingBehavior) {
|
|
6668
6670
|
addChainableMethod(this.prototype, name, fn, chainingBehavior);
|
|
6669
6671
|
}
|
|
6670
6672
|
/**
|
|
6671
6673
|
* @param {string} name
|
|
6672
|
-
* @param {
|
|
6674
|
+
* @param {(...args: never) => unknown} fn
|
|
6673
6675
|
*/
|
|
6674
6676
|
static overwriteProperty(name, fn) {
|
|
6675
6677
|
overwriteProperty(this.prototype, name, fn);
|
|
6676
6678
|
}
|
|
6677
6679
|
/**
|
|
6678
6680
|
* @param {string} name
|
|
6679
|
-
* @param {
|
|
6681
|
+
* @param {(...args: never) => unknown} fn
|
|
6680
6682
|
*/
|
|
6681
6683
|
static overwriteMethod(name, fn) {
|
|
6682
6684
|
overwriteMethod(this.prototype, name, fn);
|
|
6683
6685
|
}
|
|
6684
6686
|
/**
|
|
6685
6687
|
* @param {string} name
|
|
6686
|
-
* @param {
|
|
6687
|
-
* @param {
|
|
6688
|
+
* @param {(...args: never) => unknown} fn
|
|
6689
|
+
* @param {(...args: never) => unknown} chainingBehavior
|
|
6688
6690
|
*/
|
|
6689
6691
|
static overwriteChainableMethod(name, fn, chainingBehavior) {
|
|
6690
6692
|
overwriteChainableMethod(this.prototype, name, fn, chainingBehavior);
|
|
@@ -6741,6 +6743,11 @@ __name(_Assertion, "Assertion");
|
|
|
6741
6743
|
var Assertion = _Assertion;
|
|
6742
6744
|
var events = new EventTarget();
|
|
6743
6745
|
var _PluginEvent = class _PluginEvent extends Event {
|
|
6746
|
+
/**
|
|
6747
|
+
* @param {string} type
|
|
6748
|
+
* @param {string} name
|
|
6749
|
+
* @param {Function} fn
|
|
6750
|
+
*/
|
|
6744
6751
|
constructor(type3, name, fn) {
|
|
6745
6752
|
super(type3);
|
|
6746
6753
|
this.name = String(name);
|
|
@@ -6771,7 +6778,7 @@ function addProperty(ctx, name, getter) {
|
|
|
6771
6778
|
__name(addProperty, "addProperty");
|
|
6772
6779
|
var fnLengthDesc = Object.getOwnPropertyDescriptor(function() {}, "length");
|
|
6773
6780
|
function addLengthGuard(fn, assertionName, isChainable) {
|
|
6774
|
-
if (!fnLengthDesc
|
|
6781
|
+
if (!fnLengthDesc?.configurable) return fn;
|
|
6775
6782
|
Object.defineProperty(fn, "length", { get: /* @__PURE__ */ __name(function() {
|
|
6776
6783
|
if (isChainable) throw Error("Invalid Chai property: " + assertionName + ".length. Due to a compatibility issue, \"length\" cannot directly follow \"" + assertionName + "\". Use \"" + assertionName + ".lengthOf\" instead.");
|
|
6777
6784
|
throw Error("Invalid Chai property: " + assertionName + ".length. See docs for proper usage of \"" + assertionName + "\".");
|
|
@@ -6803,7 +6810,7 @@ function proxify(obj, nonChainableMethodName) {
|
|
|
6803
6810
|
if (!isProxyEnabled()) return obj;
|
|
6804
6811
|
return new Proxy(obj, { get: /* @__PURE__ */ __name(function proxyGetter(target, property) {
|
|
6805
6812
|
if (typeof property === "string" && config.proxyExcludedKeys.indexOf(property) === -1 && !Reflect.has(target, property)) {
|
|
6806
|
-
if (nonChainableMethodName) throw Error("Invalid Chai property: " + nonChainableMethodName + "." + property + ". See docs for proper usage of \"" + nonChainableMethodName + "\".");
|
|
6813
|
+
if (nonChainableMethodName) throw Error("Invalid Chai property: " + String(nonChainableMethodName) + "." + property + ". See docs for proper usage of \"" + String(nonChainableMethodName) + "\".");
|
|
6807
6814
|
let suggestion = null;
|
|
6808
6815
|
let suggestionDistance = 4;
|
|
6809
6816
|
getProperties(target).forEach(function(prop) {
|
|
@@ -6859,7 +6866,8 @@ function addMethod(ctx, name, method) {
|
|
|
6859
6866
|
}
|
|
6860
6867
|
__name(addMethod, "addMethod");
|
|
6861
6868
|
function overwriteProperty(ctx, name, getter) {
|
|
6862
|
-
let _get = Object.getOwnPropertyDescriptor(ctx, name)
|
|
6869
|
+
let _get = Object.getOwnPropertyDescriptor(ctx, name);
|
|
6870
|
+
let _super = /* @__PURE__ */ __name(function() {}, "_super");
|
|
6863
6871
|
if (_get && "function" === typeof _get.get) _super = _get.get;
|
|
6864
6872
|
Object.defineProperty(ctx, name, {
|
|
6865
6873
|
get: /* @__PURE__ */ __name(function overwritingPropertyGetter() {
|
|
@@ -6878,11 +6886,12 @@ function overwriteProperty(ctx, name, getter) {
|
|
|
6878
6886
|
}
|
|
6879
6887
|
__name(overwriteProperty, "overwriteProperty");
|
|
6880
6888
|
function overwriteMethod(ctx, name, method) {
|
|
6881
|
-
let _method = ctx[name]
|
|
6882
|
-
|
|
6889
|
+
let _method = ctx[name];
|
|
6890
|
+
let _super = /* @__PURE__ */ __name(function() {
|
|
6891
|
+
throw new Error(String(name) + " is not a function");
|
|
6883
6892
|
}, "_super");
|
|
6884
6893
|
if (_method && "function" === typeof _method) _super = _method;
|
|
6885
|
-
|
|
6894
|
+
function overwritingMethodWrapper() {
|
|
6886
6895
|
if (!flag(this, "lockSsfi")) flag(this, "ssfi", overwritingMethodWrapper);
|
|
6887
6896
|
let origLockSsfi = flag(this, "lockSsfi");
|
|
6888
6897
|
flag(this, "lockSsfi", true);
|
|
@@ -6892,8 +6901,9 @@ function overwriteMethod(ctx, name, method) {
|
|
|
6892
6901
|
let newAssertion = new Assertion();
|
|
6893
6902
|
transferFlags(this, newAssertion);
|
|
6894
6903
|
return newAssertion;
|
|
6895
|
-
}
|
|
6896
|
-
|
|
6904
|
+
}
|
|
6905
|
+
__name(overwritingMethodWrapper, "overwritingMethodWrapper");
|
|
6906
|
+
addLengthGuard(overwritingMethodWrapper, String(name), false);
|
|
6897
6907
|
ctx[name] = proxify(overwritingMethodWrapper, name);
|
|
6898
6908
|
}
|
|
6899
6909
|
__name(overwriteMethod, "overwriteMethod");
|
|
@@ -6907,6 +6917,12 @@ var excludeNames = Object.getOwnPropertyNames(testFn).filter(function(name) {
|
|
|
6907
6917
|
var call = Function.prototype.call;
|
|
6908
6918
|
var apply = Function.prototype.apply;
|
|
6909
6919
|
var _PluginAddChainableMethodEvent = class _PluginAddChainableMethodEvent extends PluginEvent {
|
|
6920
|
+
/**
|
|
6921
|
+
* @param {string} type
|
|
6922
|
+
* @param {string} name
|
|
6923
|
+
* @param {Function} fn
|
|
6924
|
+
* @param {Function} chainingBehavior
|
|
6925
|
+
*/
|
|
6910
6926
|
constructor(type3, name, fn, chainingBehavior) {
|
|
6911
6927
|
super(type3, name, fn);
|
|
6912
6928
|
this.chainingBehavior = chainingBehavior;
|
|
@@ -6915,24 +6931,26 @@ var _PluginAddChainableMethodEvent = class _PluginAddChainableMethodEvent extend
|
|
|
6915
6931
|
__name(_PluginAddChainableMethodEvent, "PluginAddChainableMethodEvent");
|
|
6916
6932
|
var PluginAddChainableMethodEvent = _PluginAddChainableMethodEvent;
|
|
6917
6933
|
function addChainableMethod(ctx, name, method, chainingBehavior) {
|
|
6934
|
+
const ctxChainable = ctx;
|
|
6918
6935
|
if (typeof chainingBehavior !== "function") chainingBehavior = /* @__PURE__ */ __name(function() {}, "chainingBehavior");
|
|
6919
6936
|
let chainableBehavior = {
|
|
6920
6937
|
method,
|
|
6921
6938
|
chainingBehavior
|
|
6922
6939
|
};
|
|
6923
|
-
if (!
|
|
6924
|
-
|
|
6940
|
+
if (!ctxChainable.__methods) ctxChainable.__methods = {};
|
|
6941
|
+
ctxChainable.__methods[name] = chainableBehavior;
|
|
6925
6942
|
Object.defineProperty(ctx, name, {
|
|
6926
6943
|
get: /* @__PURE__ */ __name(function chainableMethodGetter() {
|
|
6927
6944
|
chainableBehavior.chainingBehavior.call(this);
|
|
6928
|
-
|
|
6945
|
+
function chainableMethodWrapper(...args) {
|
|
6929
6946
|
if (!flag(this, "lockSsfi")) flag(this, "ssfi", chainableMethodWrapper);
|
|
6930
|
-
let result = chainableBehavior.method.apply(this,
|
|
6947
|
+
let result = chainableBehavior.method.apply(this, args);
|
|
6931
6948
|
if (result !== void 0) return result;
|
|
6932
6949
|
let newAssertion = new Assertion();
|
|
6933
6950
|
transferFlags(this, newAssertion);
|
|
6934
6951
|
return newAssertion;
|
|
6935
|
-
}
|
|
6952
|
+
}
|
|
6953
|
+
__name(chainableMethodWrapper, "chainableMethodWrapper");
|
|
6936
6954
|
addLengthGuard(chainableMethodWrapper, name, true);
|
|
6937
6955
|
if (canSetPrototype) {
|
|
6938
6956
|
let prototype = Object.create(this);
|
|
@@ -6941,7 +6959,8 @@ function addChainableMethod(ctx, name, method, chainingBehavior) {
|
|
|
6941
6959
|
Object.setPrototypeOf(chainableMethodWrapper, prototype);
|
|
6942
6960
|
} else Object.getOwnPropertyNames(ctx).forEach(function(asserterName) {
|
|
6943
6961
|
if (excludeNames.indexOf(asserterName) !== -1) return;
|
|
6944
|
-
|
|
6962
|
+
let pd = Object.getOwnPropertyDescriptor(ctx, asserterName);
|
|
6963
|
+
if (pd) Object.defineProperty(chainableMethodWrapper, asserterName, pd);
|
|
6945
6964
|
});
|
|
6946
6965
|
transferFlags(this, chainableMethodWrapper);
|
|
6947
6966
|
return proxify(chainableMethodWrapper);
|
|
@@ -6978,7 +6997,7 @@ __name(compareByInspect, "compareByInspect");
|
|
|
6978
6997
|
function getOwnEnumerablePropertySymbols(obj) {
|
|
6979
6998
|
if (typeof Object.getOwnPropertySymbols !== "function") return [];
|
|
6980
6999
|
return Object.getOwnPropertySymbols(obj).filter(function(sym) {
|
|
6981
|
-
return Object.getOwnPropertyDescriptor(obj, sym)
|
|
7000
|
+
return Object.getOwnPropertyDescriptor(obj, sym)?.enumerable;
|
|
6982
7001
|
});
|
|
6983
7002
|
}
|
|
6984
7003
|
__name(getOwnEnumerablePropertySymbols, "getOwnEnumerablePropertySymbols");
|
|
@@ -7001,13 +7020,14 @@ function getOperator(obj, args) {
|
|
|
7001
7020
|
let negate = flag(obj, "negate");
|
|
7002
7021
|
let expected = args[3];
|
|
7003
7022
|
let msg = negate ? args[2] : args[1];
|
|
7004
|
-
if (operator) return operator;
|
|
7023
|
+
if (operator) return String(operator);
|
|
7005
7024
|
if (typeof msg === "function") msg = msg();
|
|
7006
7025
|
msg = msg || "";
|
|
7007
7026
|
if (!msg) return;
|
|
7008
|
-
|
|
7027
|
+
const msgString = String(msg);
|
|
7028
|
+
if (/\shave\s/.test(msgString)) return;
|
|
7009
7029
|
let isObject = isObjectType(expected);
|
|
7010
|
-
if (/\snot\s/.test(
|
|
7030
|
+
if (/\snot\s/.test(msgString)) return isObject ? "notDeepStrictEqual" : "notStrictEqual";
|
|
7011
7031
|
return isObject ? "deepStrictEqual" : "strictEqual";
|
|
7012
7032
|
}
|
|
7013
7033
|
__name(getOperator, "getOperator");
|
|
@@ -7511,18 +7531,19 @@ function assertKeys(keys) {
|
|
|
7511
7531
|
if (!keys.length) throw new AssertionError(flagMsg + "keys required", void 0, ssfi);
|
|
7512
7532
|
let len = keys.length, any = flag2(this, "any"), all = flag2(this, "all"), expected = keys, isEql = isDeep ? flag2(this, "eql") : (val1, val2) => val1 === val2;
|
|
7513
7533
|
if (!any && !all) all = true;
|
|
7514
|
-
|
|
7534
|
+
const uniqueExpected = [...new Set(expected)];
|
|
7535
|
+
if (any) ok = uniqueExpected.some(function(expectedKey) {
|
|
7515
7536
|
return actual.some(function(actualKey) {
|
|
7516
7537
|
return isEql(expectedKey, actualKey);
|
|
7517
7538
|
});
|
|
7518
7539
|
});
|
|
7519
7540
|
if (all) {
|
|
7520
|
-
ok =
|
|
7541
|
+
ok = uniqueExpected.every(function(expectedKey) {
|
|
7521
7542
|
return actual.some(function(actualKey) {
|
|
7522
7543
|
return isEql(expectedKey, actualKey);
|
|
7523
7544
|
});
|
|
7524
7545
|
});
|
|
7525
|
-
if (!flag2(this, "contains")) ok = ok &&
|
|
7546
|
+
if (!flag2(this, "contains")) ok = ok && uniqueExpected.length == actual.length;
|
|
7526
7547
|
}
|
|
7527
7548
|
if (len > 1) {
|
|
7528
7549
|
keys = keys.map(function(key) {
|
|
@@ -7674,28 +7695,32 @@ Assertion.addMethod("members", function(subset, msg) {
|
|
|
7674
7695
|
Assertion.addProperty("iterable", function(msg) {
|
|
7675
7696
|
if (msg) flag2(this, "message", msg);
|
|
7676
7697
|
let obj = flag2(this, "object");
|
|
7677
|
-
this.assert(obj != void 0 && obj[Symbol.iterator], "expected #{this} to be an iterable", "expected #{this} to not be an iterable", obj);
|
|
7698
|
+
this.assert(obj != void 0 && typeof obj[Symbol.iterator] === "function", "expected #{this} to be an iterable", "expected #{this} to not be an iterable", obj);
|
|
7678
7699
|
});
|
|
7679
7700
|
function oneOf(list, msg) {
|
|
7680
7701
|
if (msg) flag2(this, "message", msg);
|
|
7681
7702
|
let expected = flag2(this, "object"), flagMsg = flag2(this, "message"), ssfi = flag2(this, "ssfi"), contains = flag2(this, "contains"), isDeep = flag2(this, "deep"), eql = flag2(this, "eql");
|
|
7682
7703
|
new Assertion(list, flagMsg, ssfi, true).to.be.an("array");
|
|
7683
7704
|
if (contains) this.assert(list.some(function(possibility) {
|
|
7684
|
-
return expected.indexOf(possibility) > -1
|
|
7685
|
-
|
|
7705
|
+
return expected.indexOf(possibility) > -1 || isDeep && Array.isArray(expected) && expected.some(function(item) {
|
|
7706
|
+
return eql(item, possibility);
|
|
7707
|
+
});
|
|
7708
|
+
}), "expected #{this} to " + (isDeep ? "deeply " : "") + "contain one of #{exp}", "expected #{this} to not " + (isDeep ? "deeply " : "") + "contain one of #{exp}", list, expected);
|
|
7686
7709
|
else if (isDeep) this.assert(list.some(function(possibility) {
|
|
7687
7710
|
return eql(expected, possibility);
|
|
7688
|
-
}), "expected #{this} to deeply equal one of #{exp}", "expected #{this} to deeply equal one of #{exp}", list, expected);
|
|
7711
|
+
}), "expected #{this} to deeply equal one of #{exp}", "expected #{this} to not deeply equal one of #{exp}", list, expected);
|
|
7689
7712
|
else this.assert(list.indexOf(expected) > -1, "expected #{this} to be one of #{exp}", "expected #{this} to not be one of #{exp}", list, expected);
|
|
7690
7713
|
}
|
|
7691
7714
|
__name(oneOf, "oneOf");
|
|
7692
7715
|
Assertion.addMethod("oneOf", oneOf);
|
|
7693
7716
|
function assertChanges(subject, prop, msg) {
|
|
7694
7717
|
if (msg) flag2(this, "message", msg);
|
|
7695
|
-
|
|
7718
|
+
const fn = flag2(this, "object");
|
|
7719
|
+
const flagMsg = flag2(this, "message");
|
|
7720
|
+
const ssfi = flag2(this, "ssfi");
|
|
7696
7721
|
new Assertion(fn, flagMsg, ssfi, true).is.a("function");
|
|
7697
7722
|
let initial;
|
|
7698
|
-
if (
|
|
7723
|
+
if (prop === null || prop === void 0) {
|
|
7699
7724
|
new Assertion(subject, flagMsg, ssfi, true).is.a("function");
|
|
7700
7725
|
initial = subject();
|
|
7701
7726
|
} else {
|
|
@@ -7703,7 +7728,9 @@ function assertChanges(subject, prop, msg) {
|
|
|
7703
7728
|
initial = subject[prop];
|
|
7704
7729
|
}
|
|
7705
7730
|
fn();
|
|
7706
|
-
let final = prop === void 0 || prop === null ? subject() :
|
|
7731
|
+
let final = prop === void 0 || prop === null ? subject() :
|
|
7732
|
+
/** @type {Record<PropertyKey, unknown>} */
|
|
7733
|
+
subject[prop];
|
|
7707
7734
|
let msgObj = prop === void 0 || prop === null ? initial : "." + prop;
|
|
7708
7735
|
flag2(this, "deltaMsgObj", msgObj);
|
|
7709
7736
|
flag2(this, "initialDeltaValue", initial);
|
|
@@ -7717,10 +7744,12 @@ Assertion.addMethod("change", assertChanges);
|
|
|
7717
7744
|
Assertion.addMethod("changes", assertChanges);
|
|
7718
7745
|
function assertIncreases(subject, prop, msg) {
|
|
7719
7746
|
if (msg) flag2(this, "message", msg);
|
|
7720
|
-
|
|
7747
|
+
const fn = flag2(this, "object");
|
|
7748
|
+
const flagMsg = flag2(this, "message");
|
|
7749
|
+
const ssfi = flag2(this, "ssfi");
|
|
7721
7750
|
new Assertion(fn, flagMsg, ssfi, true).is.a("function");
|
|
7722
7751
|
let initial;
|
|
7723
|
-
if (
|
|
7752
|
+
if (prop === null || prop === void 0) {
|
|
7724
7753
|
new Assertion(subject, flagMsg, ssfi, true).is.a("function");
|
|
7725
7754
|
initial = subject();
|
|
7726
7755
|
} else {
|
|
@@ -7729,7 +7758,9 @@ function assertIncreases(subject, prop, msg) {
|
|
|
7729
7758
|
}
|
|
7730
7759
|
new Assertion(initial, flagMsg, ssfi, true).is.a("number");
|
|
7731
7760
|
fn();
|
|
7732
|
-
let final = prop === void 0 || prop === null ? subject() :
|
|
7761
|
+
let final = prop === void 0 || prop === null ? subject() :
|
|
7762
|
+
/** @type {Record<PropertyKey, number>} */
|
|
7763
|
+
subject[prop];
|
|
7733
7764
|
let msgObj = prop === void 0 || prop === null ? initial : "." + prop;
|
|
7734
7765
|
flag2(this, "deltaMsgObj", msgObj);
|
|
7735
7766
|
flag2(this, "initialDeltaValue", initial);
|
|
@@ -7743,10 +7774,12 @@ Assertion.addMethod("increase", assertIncreases);
|
|
|
7743
7774
|
Assertion.addMethod("increases", assertIncreases);
|
|
7744
7775
|
function assertDecreases(subject, prop, msg) {
|
|
7745
7776
|
if (msg) flag2(this, "message", msg);
|
|
7746
|
-
|
|
7777
|
+
const fn = flag2(this, "object");
|
|
7778
|
+
const flagMsg = flag2(this, "message");
|
|
7779
|
+
const ssfi = flag2(this, "ssfi");
|
|
7747
7780
|
new Assertion(fn, flagMsg, ssfi, true).is.a("function");
|
|
7748
7781
|
let initial;
|
|
7749
|
-
if (
|
|
7782
|
+
if (prop === null || prop === void 0) {
|
|
7750
7783
|
new Assertion(subject, flagMsg, ssfi, true).is.a("function");
|
|
7751
7784
|
initial = subject();
|
|
7752
7785
|
} else {
|
|
@@ -7755,7 +7788,9 @@ function assertDecreases(subject, prop, msg) {
|
|
|
7755
7788
|
}
|
|
7756
7789
|
new Assertion(initial, flagMsg, ssfi, true).is.a("number");
|
|
7757
7790
|
fn();
|
|
7758
|
-
let final = prop === void 0 || prop === null ? subject() :
|
|
7791
|
+
let final = prop === void 0 || prop === null ? subject() :
|
|
7792
|
+
/** @type {Record<PropertyKey, number>} */
|
|
7793
|
+
subject[prop];
|
|
7759
7794
|
let msgObj = prop === void 0 || prop === null ? initial : "." + prop;
|
|
7760
7795
|
flag2(this, "deltaMsgObj", msgObj);
|
|
7761
7796
|
flag2(this, "initialDeltaValue", initial);
|
|
@@ -7834,12 +7869,12 @@ function expect(val, message) {
|
|
|
7834
7869
|
}
|
|
7835
7870
|
__name(expect, "expect");
|
|
7836
7871
|
expect.fail = function(actual, expected, message, operator) {
|
|
7872
|
+
let msg = message;
|
|
7837
7873
|
if (arguments.length < 2) {
|
|
7838
|
-
|
|
7874
|
+
msg = actual;
|
|
7839
7875
|
actual = void 0;
|
|
7840
7876
|
}
|
|
7841
|
-
|
|
7842
|
-
throw new AssertionError(message, {
|
|
7877
|
+
throw new AssertionError(msg || "expect.fail()", {
|
|
7843
7878
|
actual,
|
|
7844
7879
|
expected,
|
|
7845
7880
|
operator
|
|
@@ -8291,7 +8326,7 @@ assert$1.oneOf = function(inList, list, msg) {
|
|
|
8291
8326
|
new Assertion(inList, msg, assert$1.oneOf, true).to.be.oneOf(list);
|
|
8292
8327
|
};
|
|
8293
8328
|
assert$1.isIterable = function(obj, msg) {
|
|
8294
|
-
if (obj == void 0 ||
|
|
8329
|
+
if (obj == void 0 || typeof obj[Symbol.iterator] !== "function") {
|
|
8295
8330
|
msg = msg ? `${msg} expected ${inspect2(obj)} to be an iterable` : `expected ${inspect2(obj)} to be an iterable`;
|
|
8296
8331
|
throw new AssertionError(msg, void 0, assert$1.isIterable);
|
|
8297
8332
|
}
|
|
@@ -8485,7 +8520,7 @@ function use(fn) {
|
|
|
8485
8520
|
}
|
|
8486
8521
|
__name(use, "use");
|
|
8487
8522
|
//#endregion
|
|
8488
|
-
//#region ../../node_modules/.pnpm/@vitest+expect@4.1.
|
|
8523
|
+
//#region ../../node_modules/.pnpm/@vitest+expect@4.1.12/node_modules/@vitest/expect/dist/index.js
|
|
8489
8524
|
const ChaiStyleAssertions = (chai, utils) => {
|
|
8490
8525
|
function defProperty(name, delegateTo) {
|
|
8491
8526
|
utils.addProperty(chai.Assertion.prototype, name, function() {
|
|
@@ -9947,7 +9982,7 @@ const JestExtend = (chai, utils) => {
|
|
|
9947
9982
|
});
|
|
9948
9983
|
};
|
|
9949
9984
|
//#endregion
|
|
9950
|
-
//#region ../../node_modules/.pnpm/@vitest+utils@4.1.
|
|
9985
|
+
//#region ../../node_modules/.pnpm/@vitest+utils@4.1.12/node_modules/@vitest/utils/dist/offset.js
|
|
9951
9986
|
const lineSplitRE = /\r?\n/;
|
|
9952
9987
|
function positionToOffset(source, lineNumber, columnNumber) {
|
|
9953
9988
|
const lines = source.split(lineSplitRE);
|
|
@@ -9971,10 +10006,10 @@ function offsetToLineNumber(source, offset) {
|
|
|
9971
10006
|
return line + 1;
|
|
9972
10007
|
}
|
|
9973
10008
|
//#endregion
|
|
9974
|
-
//#region ../../node_modules/.pnpm/vitest@4.1.
|
|
10009
|
+
//#region ../../node_modules/.pnpm/vitest@4.1.12_@types+node@25.9.1_vite@8.3.4_@types+node@25.9.1_yaml@2.9.1_/node_modules/vitest/dist/chunks/_commonjsHelpers.D26ty3Ew.js
|
|
9975
10010
|
var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
|
|
9976
10011
|
//#endregion
|
|
9977
|
-
//#region ../../node_modules/.pnpm/vitest@4.1.
|
|
10012
|
+
//#region ../../node_modules/.pnpm/vitest@4.1.12_@types+node@25.9.1_vite@8.3.4_@types+node@25.9.1_yaml@2.9.1_/node_modules/vitest/dist/chunks/rpc.MzXet3jl.js
|
|
9978
10013
|
const RealDate = Date;
|
|
9979
10014
|
let now = null;
|
|
9980
10015
|
var MockDate = class MockDate extends RealDate {
|
|
@@ -10023,7 +10058,7 @@ function resetDate() {
|
|
|
10023
10058
|
}
|
|
10024
10059
|
const { get } = Reflect;
|
|
10025
10060
|
//#endregion
|
|
10026
|
-
//#region ../../node_modules/.pnpm/@vitest+snapshot@4.1.
|
|
10061
|
+
//#region ../../node_modules/.pnpm/@vitest+snapshot@4.1.12/node_modules/@vitest/snapshot/dist/index.js
|
|
10027
10062
|
function getDefaultExportFromCjs(x) {
|
|
10028
10063
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
|
|
10029
10064
|
}
|
|
@@ -10937,7 +10972,7 @@ function raceWith(promise, other) {
|
|
|
10937
10972
|
}))]);
|
|
10938
10973
|
}
|
|
10939
10974
|
//#endregion
|
|
10940
|
-
//#region ../../node_modules/.pnpm/vitest@4.1.
|
|
10975
|
+
//#region ../../node_modules/.pnpm/vitest@4.1.12_@types+node@25.9.1_vite@8.3.4_@types+node@25.9.1_yaml@2.9.1_/node_modules/vitest/dist/chunks/test.DNmyFkvJ.js
|
|
10941
10976
|
var fakeTimersSrc = {};
|
|
10942
10977
|
var global$1;
|
|
10943
10978
|
var hasRequiredGlobal;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rrlab/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "The CLI toolbox to fullstack common scripts in Variable Land",
|
|
5
5
|
"homepage": "https://github.com/withvariablelab/dx/tree/main/run-run/cli#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"access": "public"
|
|
44
44
|
},
|
|
45
45
|
"engines": {
|
|
46
|
-
"node": ">=
|
|
46
|
+
"node": ">=22.18.0"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@clack/prompts": "0.11.0",
|
|
@@ -57,12 +57,12 @@
|
|
|
57
57
|
"memoize": "10.2.0",
|
|
58
58
|
"nypm": "0.6.0",
|
|
59
59
|
"rimraf": "6.1.3",
|
|
60
|
-
"@variablelab/loggy": "0.
|
|
61
|
-
"@variablelab/clibuddy": "0.
|
|
60
|
+
"@variablelab/loggy": "0.3.0",
|
|
61
|
+
"@variablelab/clibuddy": "0.8.0"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"tsdown": "0.22.0",
|
|
65
|
-
"@rrlab/tsdown-config": "^0.
|
|
65
|
+
"@rrlab/tsdown-config": "^0.2.0"
|
|
66
66
|
},
|
|
67
67
|
"scripts": {
|
|
68
68
|
"build": "tsdown && pnpm build:kdl",
|
|
@@ -10,7 +10,7 @@ import { ConfigAstService } from "#src/services/config-ast.ts";
|
|
|
10
10
|
import type { ContextValue } from "#src/services/context.ts";
|
|
11
11
|
import { applyFileOp } from "#src/services/file-ops.ts";
|
|
12
12
|
import { logger } from "#src/services/logger.ts";
|
|
13
|
-
import { createClackPrompts } from "#src/services/prompts.ts";
|
|
13
|
+
import { canPrompt, createClackPrompts } from "#src/services/prompts.ts";
|
|
14
14
|
import { ReleaseService } from "#src/services/release.ts";
|
|
15
15
|
import { describeWorkspaceChoice, resolveWorkspaceChoice, toNypmWorkspace } from "#src/services/workspace-target.ts";
|
|
16
16
|
import { type AddOptions, hasInPackageJson, type PluginModule, reportFileOp } from "./shared.ts";
|
|
@@ -104,7 +104,7 @@ export async function addPluginAction({ ctx, args, options }: AddPluginActionCon
|
|
|
104
104
|
flags: {
|
|
105
105
|
force: !!options.force,
|
|
106
106
|
yes: !!options.yes,
|
|
107
|
-
nonInteractive: !!options.yes,
|
|
107
|
+
nonInteractive: !!options.yes || !canPrompt(),
|
|
108
108
|
},
|
|
109
109
|
release: new ReleaseService(tag),
|
|
110
110
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import * as clack from "@clack/prompts";
|
|
3
3
|
import { detectPackageManager, removeDependency } from "nypm";
|
|
4
|
+
import { ConfirmationRequiredError } from "#src/errors/confirmation-required.ts";
|
|
4
5
|
import { PLUGINS_DIRECTORY, type PluginName } from "#src/lib/plugin/directory.ts";
|
|
5
6
|
import type { UninstallResult } from "#src/lib/plugin/types.ts";
|
|
6
7
|
import { withSpinner } from "#src/render/steps.ts";
|
|
@@ -8,7 +9,7 @@ import { ConfigAstService } from "#src/services/config-ast.ts";
|
|
|
8
9
|
import type { ContextValue } from "#src/services/context.ts";
|
|
9
10
|
import { applyFileOp, describeFileOp } from "#src/services/file-ops.ts";
|
|
10
11
|
import { logger } from "#src/services/logger.ts";
|
|
11
|
-
import { createClackPrompts } from "#src/services/prompts.ts";
|
|
12
|
+
import { canPrompt, createClackPrompts } from "#src/services/prompts.ts";
|
|
12
13
|
import { describeWorkspaceChoice, resolveWorkspaceChoice, toNypmWorkspace } from "#src/services/workspace-target.ts";
|
|
13
14
|
import { hasInPackageJson, type PluginModule, type RemoveOptions, reportFileOp } from "./shared.ts";
|
|
14
15
|
|
|
@@ -41,7 +42,7 @@ export async function removePluginAction({ ctx, args, options }: RemovePluginAct
|
|
|
41
42
|
logger,
|
|
42
43
|
appPkg: ctx.appPkg,
|
|
43
44
|
prompts: createClackPrompts(),
|
|
44
|
-
flags: { yes: !!options.yes, nonInteractive: !!options.yes },
|
|
45
|
+
flags: { yes: !!options.yes, nonInteractive: !!options.yes || !canPrompt() },
|
|
45
46
|
});
|
|
46
47
|
}
|
|
47
48
|
} catch (err) {
|
|
@@ -83,6 +84,8 @@ export async function removePluginAction({ ctx, args, options }: RemovePluginAct
|
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
if (!options.yes) {
|
|
87
|
+
// Removing deletes files and dependencies: without a terminal to confirm in, insist on --yes.
|
|
88
|
+
if (!canPrompt()) throw new ConfirmationRequiredError(`rr plugins remove ${name}`);
|
|
86
89
|
const choice = await clack.confirm({ message: "Proceed?", initialValue: false });
|
|
87
90
|
if (clack.isCancel(choice) || choice !== true) {
|
|
88
91
|
clack.outro("Aborted.");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { builders, generateCode, loadFile, type ProxifiedModule, parseModule
|
|
3
|
+
import { builders, generateCode, loadFile, type ProxifiedModule, parseModule } from "magicast";
|
|
4
4
|
|
|
5
5
|
const CONFIG_FILENAMES = ["run-run.config.ts", "run-run.config.mts"] as const;
|
|
6
6
|
|
|
@@ -50,14 +50,7 @@ export class ConfigAstService {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
async save(loaded: LoadedConfig): Promise<void> {
|
|
53
|
-
|
|
54
|
-
// For a fresh file, write the generated code instead of using
|
|
55
|
-
// `writeFile` — writeFile expects an existing file as a starting point.
|
|
56
|
-
const { code } = generateCode(loaded.mod);
|
|
57
|
-
await fs.writeFile(loaded.filepath, code, "utf8");
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
await writeFile(loaded.mod.$ast, loaded.filepath);
|
|
53
|
+
await fs.writeFile(loaded.filepath, tidy(generateCode(loaded.mod).code), "utf8");
|
|
61
54
|
}
|
|
62
55
|
|
|
63
56
|
/**
|
|
@@ -84,6 +77,7 @@ export class ConfigAstService {
|
|
|
84
77
|
// Ensure the import binding exists.
|
|
85
78
|
if (!mod.imports[entry.exportName]) {
|
|
86
79
|
mod.imports.$add({ from: entry.pkgName, imported: "default", local: entry.exportName });
|
|
80
|
+
this.#placeImport(mod, entry.pkgName);
|
|
87
81
|
}
|
|
88
82
|
|
|
89
83
|
// Ensure `defineConfig` import + default export shape.
|
|
@@ -151,9 +145,30 @@ export class ConfigAstService {
|
|
|
151
145
|
return opts.plugins;
|
|
152
146
|
}
|
|
153
147
|
|
|
148
|
+
/**
|
|
149
|
+
* Moves the import of `source`, which `imports.$add` puts first, to its
|
|
150
|
+
* sorted place among the other imports, leaving those in their order: a
|
|
151
|
+
* sorted file stays sorted, so `rr jsc` passes on what rr wrote.
|
|
152
|
+
*/
|
|
153
|
+
#placeImport(mod: ProxifiedModule, source: string): void {
|
|
154
|
+
const program = mod.$ast;
|
|
155
|
+
if (program.type !== "Program") return;
|
|
156
|
+
const { body } = program;
|
|
157
|
+
const from = body.findIndex((node) => node.type === "ImportDeclaration" && node.source.value === source);
|
|
158
|
+
if (from === -1) return;
|
|
159
|
+
const [added] = body.splice(from, 1);
|
|
160
|
+
if (!added) return;
|
|
161
|
+
const before = body.findIndex(
|
|
162
|
+
(node) => node.type === "ImportDeclaration" && compareImportSources(node.source.value, source) > 0,
|
|
163
|
+
);
|
|
164
|
+
const lastImport = body.reduce((last, node, i) => (node.type === "ImportDeclaration" ? i : last), -1);
|
|
165
|
+
body.splice(before === -1 ? lastImport + 1 : before, 0, added);
|
|
166
|
+
}
|
|
167
|
+
|
|
154
168
|
#ensureDefineConfig(mod: ProxifiedModule): void {
|
|
155
169
|
if (!mod.imports.defineConfig) {
|
|
156
170
|
mod.imports.$add({ from: "@rrlab/cli/config", imported: "defineConfig", local: "defineConfig" });
|
|
171
|
+
this.#placeImport(mod, "@rrlab/cli/config");
|
|
157
172
|
}
|
|
158
173
|
// biome-ignore lint/suspicious/noExplicitAny: magicast proxies are opaque
|
|
159
174
|
const def = (mod.exports as any).default;
|
|
@@ -194,6 +209,32 @@ export class ConfigAstService {
|
|
|
194
209
|
}
|
|
195
210
|
}
|
|
196
211
|
|
|
212
|
+
/**
|
|
213
|
+
* Undoes two recast habits that formatters reject: it keeps the blank line that
|
|
214
|
+
* followed an import when rr inserts another after it, and it drops the final
|
|
215
|
+
* newline.
|
|
216
|
+
*/
|
|
217
|
+
function tidy(code: string): string {
|
|
218
|
+
const joined = code.replace(/^(import\b[^;]*;)\n(?:[ \t]*\n)+(?=import\b)/gm, "$1\n");
|
|
219
|
+
return joined.endsWith("\n") ? joined : `${joined}\n`;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Biome's organizeImports order: protocol imports (`node:fs`), then packages,
|
|
224
|
+
* then aliases (`#src/…`, `@/…`, `~/…`), then paths. Within a group, plain
|
|
225
|
+
* code-unit order, which matches Biome for these names (`ts-plugin` before
|
|
226
|
+
* `tsdown-plugin`; `localeCompare` flips them).
|
|
227
|
+
*/
|
|
228
|
+
function compareImportSources(a: string, b: string): number {
|
|
229
|
+
const group = (source: string) => {
|
|
230
|
+
if (/^[a-z]+:/.test(source)) return 0;
|
|
231
|
+
if (/^(#|@\/|~)/.test(source)) return 2;
|
|
232
|
+
if (source.startsWith(".") || source.startsWith("/")) return 3;
|
|
233
|
+
return 1;
|
|
234
|
+
};
|
|
235
|
+
return group(a) - group(b) || (a < b ? -1 : a > b ? 1 : 0);
|
|
236
|
+
}
|
|
237
|
+
|
|
197
238
|
const MINIMAL_TEMPLATE = `import { defineConfig } from "@rrlab/cli/config";
|
|
198
239
|
|
|
199
240
|
export default defineConfig({
|
package/src/services/prompts.ts
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import * as clack from "@clack/prompts";
|
|
2
2
|
import type { ClackPrompts } from "#src/lib/plugin/types.ts";
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Whether a prompt can run: clack reads keys from stdin and draws on stdout,
|
|
6
|
+
* so both have to be terminals. An agent, a script or CI usually has neither,
|
|
7
|
+
* and a prompt there waits forever or exits on a closed stdin.
|
|
8
|
+
*/
|
|
9
|
+
export function canPrompt(): boolean {
|
|
10
|
+
return !!process.stdin.isTTY && !!process.stdout.isTTY;
|
|
11
|
+
}
|
|
12
|
+
|
|
4
13
|
/**
|
|
5
14
|
* Adapter that exposes the subset of `@clack/prompts` matching the
|
|
6
15
|
* `ClackPrompts` contract from `@rrlab/cli/plugin`. The contract intentionally
|