mmt-testlight 1.42.1-pre → 1.42.3-pre
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 +5 -1
- package/dist/cli.js +134 -240
- package/esbuild.pkg.mjs +39 -0
- package/package.json +36 -16
- package/src/pkg-entry.cjs +112 -0
- package/src/selfUpdate.test.ts +43 -0
- package/src/selfUpdate.ts +11 -1
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Multimeter CLI (mmtcli)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**testlight** runs Multimeter YAML `.mmt` tests in CI and locally. npm package: `mmt-testlight`.
|
|
4
|
+
|
|
5
|
+
Multimeter is an AI-powered REST Client and API testing tool for VS Code and CI. It is not an electrical multimeter. Git-native alternative to Postman. Docs: https://mmt.dev
|
|
4
6
|
|
|
5
7
|
## Usage
|
|
6
8
|
|
|
@@ -22,6 +24,8 @@ npm run build
|
|
|
22
24
|
|
|
23
25
|
## Bundle standalone binaries (pkg)
|
|
24
26
|
|
|
27
|
+
Uses `@yao-pkg/pkg` in SEA mode (Node 22). Requires Node ≥ 22 on the machine that builds binaries.
|
|
28
|
+
|
|
25
29
|
```
|
|
26
30
|
npm run pkg
|
|
27
31
|
```
|
package/dist/cli.js
CHANGED
|
@@ -25513,6 +25513,7 @@ function resolvePassphrase(passphrasePlain, passphraseEnv, envVars, processEnv)
|
|
|
25513
25513
|
var DEFAULT_NETWORK_CONFIG;
|
|
25514
25514
|
var init_NetworkData = __esm({
|
|
25515
25515
|
"../core/src/NetworkData.ts"() {
|
|
25516
|
+
"use strict";
|
|
25516
25517
|
DEFAULT_NETWORK_CONFIG = {
|
|
25517
25518
|
ca: { enabled: false },
|
|
25518
25519
|
clients: [],
|
|
@@ -36327,118 +36328,138 @@ var require_browser = __commonJS({
|
|
|
36327
36328
|
}
|
|
36328
36329
|
});
|
|
36329
36330
|
|
|
36330
|
-
// node_modules/
|
|
36331
|
-
var
|
|
36332
|
-
|
|
36333
|
-
|
|
36334
|
-
|
|
36335
|
-
const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
|
|
36336
|
-
const position = argv.indexOf(prefix + flag);
|
|
36337
|
-
const terminatorPosition = argv.indexOf("--");
|
|
36338
|
-
return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
|
|
36339
|
-
};
|
|
36340
|
-
}
|
|
36331
|
+
// ../node_modules/supports-color/index.js
|
|
36332
|
+
var supports_color_exports = {};
|
|
36333
|
+
__export(supports_color_exports, {
|
|
36334
|
+
createSupportsColor: () => createSupportsColor,
|
|
36335
|
+
default: () => supports_color_default
|
|
36341
36336
|
});
|
|
36342
|
-
|
|
36343
|
-
|
|
36344
|
-
|
|
36345
|
-
|
|
36346
|
-
|
|
36347
|
-
|
|
36348
|
-
|
|
36349
|
-
|
|
36350
|
-
|
|
36351
|
-
|
|
36352
|
-
if (hasFlag2("no-color") || hasFlag2("no-colors") || hasFlag2("color=false") || hasFlag2("color=never")) {
|
|
36353
|
-
forceColor = 0;
|
|
36354
|
-
} else if (hasFlag2("color") || hasFlag2("colors") || hasFlag2("color=true") || hasFlag2("color=always")) {
|
|
36355
|
-
forceColor = 1;
|
|
36356
|
-
}
|
|
36357
|
-
if ("FORCE_COLOR" in env2) {
|
|
36358
|
-
if (env2.FORCE_COLOR === "true") {
|
|
36359
|
-
forceColor = 1;
|
|
36360
|
-
} else if (env2.FORCE_COLOR === "false") {
|
|
36361
|
-
forceColor = 0;
|
|
36362
|
-
} else {
|
|
36363
|
-
forceColor = env2.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env2.FORCE_COLOR, 10), 3);
|
|
36364
|
-
}
|
|
36337
|
+
function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : import_node_process.default.argv) {
|
|
36338
|
+
const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
|
|
36339
|
+
const position = argv.indexOf(prefix + flag);
|
|
36340
|
+
const terminatorPosition = argv.indexOf("--");
|
|
36341
|
+
return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
|
|
36342
|
+
}
|
|
36343
|
+
function envForceColor() {
|
|
36344
|
+
if ("FORCE_COLOR" in env) {
|
|
36345
|
+
if (env.FORCE_COLOR === "true") {
|
|
36346
|
+
return 1;
|
|
36365
36347
|
}
|
|
36366
|
-
|
|
36367
|
-
|
|
36368
|
-
return false;
|
|
36369
|
-
}
|
|
36370
|
-
return {
|
|
36371
|
-
level,
|
|
36372
|
-
hasBasic: true,
|
|
36373
|
-
has256: level >= 2,
|
|
36374
|
-
has16m: level >= 3
|
|
36375
|
-
};
|
|
36348
|
+
if (env.FORCE_COLOR === "false") {
|
|
36349
|
+
return 0;
|
|
36376
36350
|
}
|
|
36377
|
-
|
|
36378
|
-
|
|
36379
|
-
|
|
36380
|
-
|
|
36381
|
-
|
|
36382
|
-
|
|
36383
|
-
|
|
36384
|
-
|
|
36385
|
-
|
|
36386
|
-
|
|
36387
|
-
|
|
36388
|
-
|
|
36389
|
-
|
|
36390
|
-
|
|
36391
|
-
|
|
36392
|
-
|
|
36393
|
-
|
|
36394
|
-
|
|
36395
|
-
|
|
36396
|
-
|
|
36397
|
-
|
|
36398
|
-
|
|
36399
|
-
|
|
36400
|
-
|
|
36401
|
-
|
|
36402
|
-
|
|
36403
|
-
|
|
36404
|
-
|
|
36405
|
-
|
|
36406
|
-
|
|
36407
|
-
|
|
36408
|
-
|
|
36409
|
-
|
|
36410
|
-
|
|
36411
|
-
|
|
36412
|
-
|
|
36413
|
-
|
|
36414
|
-
|
|
36415
|
-
|
|
36416
|
-
|
|
36417
|
-
|
|
36418
|
-
|
|
36419
|
-
|
|
36420
|
-
|
|
36351
|
+
return env.FORCE_COLOR.length === 0 ? 1 : Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3);
|
|
36352
|
+
}
|
|
36353
|
+
}
|
|
36354
|
+
function translateLevel(level) {
|
|
36355
|
+
if (level === 0) {
|
|
36356
|
+
return false;
|
|
36357
|
+
}
|
|
36358
|
+
return {
|
|
36359
|
+
level,
|
|
36360
|
+
hasBasic: true,
|
|
36361
|
+
has256: level >= 2,
|
|
36362
|
+
has16m: level >= 3
|
|
36363
|
+
};
|
|
36364
|
+
}
|
|
36365
|
+
function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
|
|
36366
|
+
const noFlagForceColor = envForceColor();
|
|
36367
|
+
if (noFlagForceColor !== void 0) {
|
|
36368
|
+
flagForceColor = noFlagForceColor;
|
|
36369
|
+
}
|
|
36370
|
+
const forceColor = sniffFlags ? flagForceColor : noFlagForceColor;
|
|
36371
|
+
if (forceColor === 0) {
|
|
36372
|
+
return 0;
|
|
36373
|
+
}
|
|
36374
|
+
if (sniffFlags) {
|
|
36375
|
+
if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
|
|
36376
|
+
return 3;
|
|
36377
|
+
}
|
|
36378
|
+
if (hasFlag("color=256")) {
|
|
36379
|
+
return 2;
|
|
36380
|
+
}
|
|
36381
|
+
}
|
|
36382
|
+
if ("TF_BUILD" in env && "AGENT_NAME" in env) {
|
|
36383
|
+
return 1;
|
|
36384
|
+
}
|
|
36385
|
+
if (haveStream && !streamIsTTY && forceColor === void 0) {
|
|
36386
|
+
return 0;
|
|
36387
|
+
}
|
|
36388
|
+
const min = forceColor || 0;
|
|
36389
|
+
if (env.TERM === "dumb") {
|
|
36390
|
+
return min;
|
|
36391
|
+
}
|
|
36392
|
+
if (import_node_process.default.platform === "win32") {
|
|
36393
|
+
const osRelease = import_node_os.default.release().split(".");
|
|
36394
|
+
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
|
|
36395
|
+
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
36396
|
+
}
|
|
36397
|
+
return 1;
|
|
36398
|
+
}
|
|
36399
|
+
if ("CI" in env) {
|
|
36400
|
+
if ("GITHUB_ACTIONS" in env || "GITEA_ACTIONS" in env) {
|
|
36401
|
+
return 3;
|
|
36402
|
+
}
|
|
36403
|
+
if (["TRAVIS", "CIRCLECI", "APPVEYOR", "GITLAB_CI", "BUILDKITE", "DRONE"].some((sign) => sign in env) || env.CI_NAME === "codeship") {
|
|
36404
|
+
return 1;
|
|
36405
|
+
}
|
|
36406
|
+
return min;
|
|
36407
|
+
}
|
|
36408
|
+
if ("TEAMCITY_VERSION" in env) {
|
|
36409
|
+
return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
|
|
36410
|
+
}
|
|
36411
|
+
if (env.COLORTERM === "truecolor") {
|
|
36412
|
+
return 3;
|
|
36413
|
+
}
|
|
36414
|
+
if (env.TERM === "xterm-kitty") {
|
|
36415
|
+
return 3;
|
|
36416
|
+
}
|
|
36417
|
+
if ("TERM_PROGRAM" in env) {
|
|
36418
|
+
const version = Number.parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
|
|
36419
|
+
switch (env.TERM_PROGRAM) {
|
|
36420
|
+
case "iTerm.app": {
|
|
36421
|
+
return version >= 3 ? 3 : 2;
|
|
36421
36422
|
}
|
|
36422
|
-
|
|
36423
|
+
case "Apple_Terminal": {
|
|
36423
36424
|
return 2;
|
|
36424
36425
|
}
|
|
36425
|
-
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env2.TERM)) {
|
|
36426
|
-
return 1;
|
|
36427
|
-
}
|
|
36428
|
-
if ("COLORTERM" in env2) {
|
|
36429
|
-
return 1;
|
|
36430
|
-
}
|
|
36431
|
-
return min;
|
|
36432
36426
|
}
|
|
36433
|
-
|
|
36434
|
-
|
|
36435
|
-
|
|
36427
|
+
}
|
|
36428
|
+
if (/-256(color)?$/i.test(env.TERM)) {
|
|
36429
|
+
return 2;
|
|
36430
|
+
}
|
|
36431
|
+
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
|
|
36432
|
+
return 1;
|
|
36433
|
+
}
|
|
36434
|
+
if ("COLORTERM" in env) {
|
|
36435
|
+
return 1;
|
|
36436
|
+
}
|
|
36437
|
+
return min;
|
|
36438
|
+
}
|
|
36439
|
+
function createSupportsColor(stream4, options = {}) {
|
|
36440
|
+
const level = _supportsColor(stream4, {
|
|
36441
|
+
streamIsTTY: stream4 && stream4.isTTY,
|
|
36442
|
+
...options
|
|
36443
|
+
});
|
|
36444
|
+
return translateLevel(level);
|
|
36445
|
+
}
|
|
36446
|
+
var import_node_process, import_node_os, import_node_tty, env, flagForceColor, supportsColor, supports_color_default;
|
|
36447
|
+
var init_supports_color = __esm({
|
|
36448
|
+
"../node_modules/supports-color/index.js"() {
|
|
36449
|
+
import_node_process = __toESM(require("node:process"), 1);
|
|
36450
|
+
import_node_os = __toESM(require("node:os"), 1);
|
|
36451
|
+
import_node_tty = __toESM(require("node:tty"), 1);
|
|
36452
|
+
({ env } = import_node_process.default);
|
|
36453
|
+
if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
|
|
36454
|
+
flagForceColor = 0;
|
|
36455
|
+
} else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
|
|
36456
|
+
flagForceColor = 1;
|
|
36436
36457
|
}
|
|
36437
|
-
|
|
36438
|
-
|
|
36439
|
-
|
|
36440
|
-
stderr: translateLevel2(supportsColor2(true, tty2.isatty(2)))
|
|
36458
|
+
supportsColor = {
|
|
36459
|
+
stdout: createSupportsColor({ isTTY: import_node_tty.default.isatty(1) }),
|
|
36460
|
+
stderr: createSupportsColor({ isTTY: import_node_tty.default.isatty(2) })
|
|
36441
36461
|
};
|
|
36462
|
+
supports_color_default = supportsColor;
|
|
36442
36463
|
}
|
|
36443
36464
|
});
|
|
36444
36465
|
|
|
@@ -36460,7 +36481,7 @@ var require_node = __commonJS({
|
|
|
36460
36481
|
);
|
|
36461
36482
|
exports2.colors = [6, 2, 3, 4, 5, 1];
|
|
36462
36483
|
try {
|
|
36463
|
-
const supportsColor2 =
|
|
36484
|
+
const supportsColor2 = (init_supports_color(), __toCommonJS(supports_color_exports));
|
|
36464
36485
|
if (supportsColor2 && (supportsColor2.stderr || supportsColor2).level >= 2) {
|
|
36465
36486
|
exports2.colors = [
|
|
36466
36487
|
20,
|
|
@@ -51750,141 +51771,6 @@ var require_browser2 = __commonJS({
|
|
|
51750
51771
|
}
|
|
51751
51772
|
});
|
|
51752
51773
|
|
|
51753
|
-
// ../node_modules/supports-color/index.js
|
|
51754
|
-
var supports_color_exports = {};
|
|
51755
|
-
__export(supports_color_exports, {
|
|
51756
|
-
createSupportsColor: () => createSupportsColor,
|
|
51757
|
-
default: () => supports_color_default
|
|
51758
|
-
});
|
|
51759
|
-
function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : import_node_process.default.argv) {
|
|
51760
|
-
const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
|
|
51761
|
-
const position = argv.indexOf(prefix + flag);
|
|
51762
|
-
const terminatorPosition = argv.indexOf("--");
|
|
51763
|
-
return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
|
|
51764
|
-
}
|
|
51765
|
-
function envForceColor() {
|
|
51766
|
-
if ("FORCE_COLOR" in env) {
|
|
51767
|
-
if (env.FORCE_COLOR === "true") {
|
|
51768
|
-
return 1;
|
|
51769
|
-
}
|
|
51770
|
-
if (env.FORCE_COLOR === "false") {
|
|
51771
|
-
return 0;
|
|
51772
|
-
}
|
|
51773
|
-
return env.FORCE_COLOR.length === 0 ? 1 : Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3);
|
|
51774
|
-
}
|
|
51775
|
-
}
|
|
51776
|
-
function translateLevel(level) {
|
|
51777
|
-
if (level === 0) {
|
|
51778
|
-
return false;
|
|
51779
|
-
}
|
|
51780
|
-
return {
|
|
51781
|
-
level,
|
|
51782
|
-
hasBasic: true,
|
|
51783
|
-
has256: level >= 2,
|
|
51784
|
-
has16m: level >= 3
|
|
51785
|
-
};
|
|
51786
|
-
}
|
|
51787
|
-
function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
|
|
51788
|
-
const noFlagForceColor = envForceColor();
|
|
51789
|
-
if (noFlagForceColor !== void 0) {
|
|
51790
|
-
flagForceColor = noFlagForceColor;
|
|
51791
|
-
}
|
|
51792
|
-
const forceColor = sniffFlags ? flagForceColor : noFlagForceColor;
|
|
51793
|
-
if (forceColor === 0) {
|
|
51794
|
-
return 0;
|
|
51795
|
-
}
|
|
51796
|
-
if (sniffFlags) {
|
|
51797
|
-
if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
|
|
51798
|
-
return 3;
|
|
51799
|
-
}
|
|
51800
|
-
if (hasFlag("color=256")) {
|
|
51801
|
-
return 2;
|
|
51802
|
-
}
|
|
51803
|
-
}
|
|
51804
|
-
if ("TF_BUILD" in env && "AGENT_NAME" in env) {
|
|
51805
|
-
return 1;
|
|
51806
|
-
}
|
|
51807
|
-
if (haveStream && !streamIsTTY && forceColor === void 0) {
|
|
51808
|
-
return 0;
|
|
51809
|
-
}
|
|
51810
|
-
const min = forceColor || 0;
|
|
51811
|
-
if (env.TERM === "dumb") {
|
|
51812
|
-
return min;
|
|
51813
|
-
}
|
|
51814
|
-
if (import_node_process.default.platform === "win32") {
|
|
51815
|
-
const osRelease = import_node_os.default.release().split(".");
|
|
51816
|
-
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
|
|
51817
|
-
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
51818
|
-
}
|
|
51819
|
-
return 1;
|
|
51820
|
-
}
|
|
51821
|
-
if ("CI" in env) {
|
|
51822
|
-
if ("GITHUB_ACTIONS" in env || "GITEA_ACTIONS" in env) {
|
|
51823
|
-
return 3;
|
|
51824
|
-
}
|
|
51825
|
-
if (["TRAVIS", "CIRCLECI", "APPVEYOR", "GITLAB_CI", "BUILDKITE", "DRONE"].some((sign) => sign in env) || env.CI_NAME === "codeship") {
|
|
51826
|
-
return 1;
|
|
51827
|
-
}
|
|
51828
|
-
return min;
|
|
51829
|
-
}
|
|
51830
|
-
if ("TEAMCITY_VERSION" in env) {
|
|
51831
|
-
return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
|
|
51832
|
-
}
|
|
51833
|
-
if (env.COLORTERM === "truecolor") {
|
|
51834
|
-
return 3;
|
|
51835
|
-
}
|
|
51836
|
-
if (env.TERM === "xterm-kitty") {
|
|
51837
|
-
return 3;
|
|
51838
|
-
}
|
|
51839
|
-
if ("TERM_PROGRAM" in env) {
|
|
51840
|
-
const version = Number.parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
|
|
51841
|
-
switch (env.TERM_PROGRAM) {
|
|
51842
|
-
case "iTerm.app": {
|
|
51843
|
-
return version >= 3 ? 3 : 2;
|
|
51844
|
-
}
|
|
51845
|
-
case "Apple_Terminal": {
|
|
51846
|
-
return 2;
|
|
51847
|
-
}
|
|
51848
|
-
}
|
|
51849
|
-
}
|
|
51850
|
-
if (/-256(color)?$/i.test(env.TERM)) {
|
|
51851
|
-
return 2;
|
|
51852
|
-
}
|
|
51853
|
-
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
|
|
51854
|
-
return 1;
|
|
51855
|
-
}
|
|
51856
|
-
if ("COLORTERM" in env) {
|
|
51857
|
-
return 1;
|
|
51858
|
-
}
|
|
51859
|
-
return min;
|
|
51860
|
-
}
|
|
51861
|
-
function createSupportsColor(stream4, options = {}) {
|
|
51862
|
-
const level = _supportsColor(stream4, {
|
|
51863
|
-
streamIsTTY: stream4 && stream4.isTTY,
|
|
51864
|
-
...options
|
|
51865
|
-
});
|
|
51866
|
-
return translateLevel(level);
|
|
51867
|
-
}
|
|
51868
|
-
var import_node_process, import_node_os, import_node_tty, env, flagForceColor, supportsColor, supports_color_default;
|
|
51869
|
-
var init_supports_color = __esm({
|
|
51870
|
-
"../node_modules/supports-color/index.js"() {
|
|
51871
|
-
import_node_process = __toESM(require("node:process"), 1);
|
|
51872
|
-
import_node_os = __toESM(require("node:os"), 1);
|
|
51873
|
-
import_node_tty = __toESM(require("node:tty"), 1);
|
|
51874
|
-
({ env } = import_node_process.default);
|
|
51875
|
-
if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
|
|
51876
|
-
flagForceColor = 0;
|
|
51877
|
-
} else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
|
|
51878
|
-
flagForceColor = 1;
|
|
51879
|
-
}
|
|
51880
|
-
supportsColor = {
|
|
51881
|
-
stdout: createSupportsColor({ isTTY: import_node_tty.default.isatty(1) }),
|
|
51882
|
-
stderr: createSupportsColor({ isTTY: import_node_tty.default.isatty(2) })
|
|
51883
|
-
};
|
|
51884
|
-
supports_color_default = supportsColor;
|
|
51885
|
-
}
|
|
51886
|
-
});
|
|
51887
|
-
|
|
51888
51774
|
// ../node_modules/debug/src/node.js
|
|
51889
51775
|
var require_node2 = __commonJS({
|
|
51890
51776
|
"../node_modules/debug/src/node.js"(exports2, module2) {
|
|
@@ -84329,10 +84215,18 @@ function detectPlatform(unameOs = process.platform, unameArch = process.arch) {
|
|
|
84329
84215
|
}
|
|
84330
84216
|
return `${osName}-${arch}`;
|
|
84331
84217
|
}
|
|
84218
|
+
function isSeaBinary() {
|
|
84219
|
+
try {
|
|
84220
|
+
const sea = require("node:sea");
|
|
84221
|
+
return typeof sea.isSea === "function" && sea.isSea();
|
|
84222
|
+
} catch {
|
|
84223
|
+
return false;
|
|
84224
|
+
}
|
|
84225
|
+
}
|
|
84332
84226
|
function detectInstallChannel(execPath, scriptPath) {
|
|
84333
84227
|
const exec = execPath.replace(/\\/g, "/");
|
|
84334
84228
|
const script = (scriptPath || "").replace(/\\/g, "/");
|
|
84335
|
-
if (process.pkg) {
|
|
84229
|
+
if (process.pkg || isSeaBinary()) {
|
|
84336
84230
|
return "standalone";
|
|
84337
84231
|
}
|
|
84338
84232
|
if (/\/Cellar\/mmt-testlight\//i.test(exec) || /\/homebrew\/.*(mmt-testlight|testlight)/i.test(exec)) {
|
package/esbuild.pkg.mjs
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as esbuild from 'esbuild';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import {fileURLToPath} from 'url';
|
|
4
|
+
|
|
5
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
const coreDir = path.resolve(__dirname, '..', 'core', 'src');
|
|
7
|
+
|
|
8
|
+
// Same resolver as esbuild.mjs so the pkg bundle inlines core from source.
|
|
9
|
+
const mmtCorePlugin = {
|
|
10
|
+
name: 'mmt-core-resolver',
|
|
11
|
+
setup(build) {
|
|
12
|
+
build.onResolve({filter: /^mmt-core$/}, () => ({
|
|
13
|
+
path: path.join(coreDir, 'index.ts'),
|
|
14
|
+
}));
|
|
15
|
+
build.onResolve({filter: /^mmt-core\//}, (args) => {
|
|
16
|
+
const sub = args.path.replace(/^mmt-core\//, '');
|
|
17
|
+
return {path: path.join(coreDir, sub + '.ts')};
|
|
18
|
+
});
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
await esbuild.build({
|
|
23
|
+
entryPoints: ['src/pkg-entry.cjs'],
|
|
24
|
+
bundle: true,
|
|
25
|
+
platform: 'node',
|
|
26
|
+
target: 'node22',
|
|
27
|
+
format: 'cjs',
|
|
28
|
+
outfile: 'dist-cjs/pkg-bundle.cjs',
|
|
29
|
+
plugins: [mmtCorePlugin],
|
|
30
|
+
resolveExtensions: ['.ts', '.js', '.cjs', '.mjs', '.json'],
|
|
31
|
+
// Native addons + reflection protos stay on disk for pkg to embed.
|
|
32
|
+
external: [
|
|
33
|
+
'@grpc/grpc-js',
|
|
34
|
+
'@grpc/proto-loader',
|
|
35
|
+
],
|
|
36
|
+
logOverride: {
|
|
37
|
+
'unsupported-dynamic-import': 'silent',
|
|
38
|
+
},
|
|
39
|
+
});
|
package/package.json
CHANGED
|
@@ -1,9 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mmt-testlight",
|
|
3
|
-
"version": "1.42.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.42.3-pre",
|
|
4
|
+
"description": "AI-powered REST Client and Git-native API testing CLI for YAML .mmt files. Same tests in VS Code and CI. Alternative to Postman.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"private": false,
|
|
7
|
+
"homepage": "https://mmt.dev/docs/features/testlight/install",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/mshobeyri/multimeter.git",
|
|
11
|
+
"directory": "mmtcli"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/mshobeyri/multimeter/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"api-testing",
|
|
18
|
+
"rest-client",
|
|
19
|
+
"cli",
|
|
20
|
+
"ci",
|
|
21
|
+
"yaml",
|
|
22
|
+
"postman-alternative",
|
|
23
|
+
"testlight",
|
|
24
|
+
"multimeter",
|
|
25
|
+
"mcp"
|
|
26
|
+
],
|
|
7
27
|
"bin": {
|
|
8
28
|
"testlight": "dist/cli.js",
|
|
9
29
|
"mmt": "dist/cli.js"
|
|
@@ -13,25 +33,20 @@
|
|
|
13
33
|
"build": "node esbuild.mjs",
|
|
14
34
|
"build:tsc": "tsc -p tsconfig.json",
|
|
15
35
|
"build:cjs": "tsc -p tsconfig.cjs.json",
|
|
36
|
+
"build:pkg-bundle": "node esbuild.pkg.mjs",
|
|
16
37
|
"dev": "tsx src/cli.ts --help",
|
|
17
38
|
"clean": "rimraf dist",
|
|
18
|
-
"pkg": "rimraf dist-cjs && npm run build:
|
|
39
|
+
"pkg": "rimraf dist-cjs && npm run build:pkg-bundle && bash ../scripts/build-binaries.sh",
|
|
19
40
|
"test": "echo \"(no tests yet)\""
|
|
20
41
|
},
|
|
21
42
|
"pkg": {
|
|
22
|
-
"scripts": [
|
|
23
|
-
"dist-cjs/**/*.js",
|
|
24
|
-
"node_modules/mmt-core/dist/**/*.js",
|
|
25
|
-
"../core/dist/**/*.js"
|
|
26
|
-
],
|
|
27
43
|
"assets": [
|
|
28
|
-
"node_modules/
|
|
29
|
-
"node_modules/
|
|
30
|
-
"node_modules/
|
|
31
|
-
"node_modules/
|
|
32
|
-
"node_modules/
|
|
33
|
-
"node_modules/
|
|
34
|
-
"../core/dist/**"
|
|
44
|
+
"node_modules/@grpc/grpc-js/**",
|
|
45
|
+
"node_modules/@grpc/proto-loader/**",
|
|
46
|
+
"../node_modules/@grpc/grpc-js/**",
|
|
47
|
+
"../node_modules/@grpc/proto-loader/**",
|
|
48
|
+
"../core/node_modules/@grpc/grpc-js/**",
|
|
49
|
+
"../core/node_modules/@grpc/proto-loader/**"
|
|
35
50
|
]
|
|
36
51
|
},
|
|
37
52
|
"dependencies": {
|
|
@@ -44,9 +59,14 @@
|
|
|
44
59
|
"node-forge": "^1.3.2"
|
|
45
60
|
},
|
|
46
61
|
"devDependencies": {
|
|
62
|
+
"@grpc/grpc-js": "^1.12.6",
|
|
63
|
+
"@grpc/proto-loader": "^0.7.13",
|
|
47
64
|
"@types/js-yaml": "^4.0.9",
|
|
48
65
|
"@types/node": "^20.11.30",
|
|
49
|
-
"pkg": "^
|
|
66
|
+
"@yao-pkg/pkg": "^6.22.0",
|
|
67
|
+
"pe-library": "^2.0.1",
|
|
68
|
+
"png-to-ico": "^2.1.8",
|
|
69
|
+
"resedit": "^3.1.0",
|
|
50
70
|
"rimraf": "^5.0.5",
|
|
51
71
|
"tsx": "^4.7.0",
|
|
52
72
|
"typescript": "^5.4.2"
|
package/src/pkg-entry.cjs
CHANGED
|
@@ -547,6 +547,7 @@ function printHelp() {
|
|
|
547
547
|
const commands = formatHelpRows([
|
|
548
548
|
['run [options] <file>', 'Run a .mmt file'],
|
|
549
549
|
['print-js [options] <file>', 'Print generated JS for a test'],
|
|
550
|
+
['update [options]', 'Update this standalone binary from GitHub Releases'],
|
|
550
551
|
['debug-resolve', 'Print pkg module resolution info'],
|
|
551
552
|
]);
|
|
552
553
|
const options = formatHelpRows([
|
|
@@ -569,6 +570,8 @@ function printHelp() {
|
|
|
569
570
|
['testlight run path/to/test.mmt'],
|
|
570
571
|
['testlight run path/to/test.mmt -e api_url=https://test.mmt.dev -q'],
|
|
571
572
|
['testlight print-js path/to/test.mmt'],
|
|
573
|
+
['testlight update'],
|
|
574
|
+
['testlight update --check'],
|
|
572
575
|
], ' ', 0);
|
|
573
576
|
const out = [
|
|
574
577
|
'Usage: testlight <command> [options]',
|
|
@@ -643,6 +646,35 @@ function printPrintJsHelp() {
|
|
|
643
646
|
process.stdout.write(out + '\n');
|
|
644
647
|
}
|
|
645
648
|
|
|
649
|
+
function printUpdateHelp() {
|
|
650
|
+
const options = formatHelpRows([
|
|
651
|
+
['-h, --help', 'Show help'],
|
|
652
|
+
['--check', 'Only check whether an update is available'],
|
|
653
|
+
['--to <version>', 'Install a specific version (e.g. 1.38.1)'],
|
|
654
|
+
['--channel <name>', 'Latest matching channel (beta, rc, prerelease)'],
|
|
655
|
+
['--force', 'Reinstall even when already newest'],
|
|
656
|
+
['--repo <owner/name>', 'GitHub repo (default: mshobeyri/multimeter)'],
|
|
657
|
+
['--base-url <url>', 'Portal/mirror base URL'],
|
|
658
|
+
]);
|
|
659
|
+
const examples = formatHelpRows([
|
|
660
|
+
['testlight update'],
|
|
661
|
+
['testlight update --check'],
|
|
662
|
+
['testlight update --to 1.38.1'],
|
|
663
|
+
], ' ', 0);
|
|
664
|
+
const out = [
|
|
665
|
+
'Usage: testlight update [options]',
|
|
666
|
+
'',
|
|
667
|
+
'Update this standalone binary from GitHub Releases (or a portal mirror)',
|
|
668
|
+
'',
|
|
669
|
+
'Options:',
|
|
670
|
+
...options,
|
|
671
|
+
'',
|
|
672
|
+
'Examples:',
|
|
673
|
+
...examples,
|
|
674
|
+
].join('\n');
|
|
675
|
+
process.stdout.write(out + '\n');
|
|
676
|
+
}
|
|
677
|
+
|
|
646
678
|
function coerceCliValue(v) {
|
|
647
679
|
const t = String(v ?? '').trim();
|
|
648
680
|
if (/^(true|false)$/i.test(t)) {
|
|
@@ -919,6 +951,53 @@ function parsePrintJsArgv(argv) {
|
|
|
919
951
|
return { filePath, opts };
|
|
920
952
|
}
|
|
921
953
|
|
|
954
|
+
function parseUpdateArgv(argv) {
|
|
955
|
+
const opts = {
|
|
956
|
+
check: false,
|
|
957
|
+
to: undefined,
|
|
958
|
+
channel: undefined,
|
|
959
|
+
force: false,
|
|
960
|
+
repo: undefined,
|
|
961
|
+
baseUrl: undefined,
|
|
962
|
+
help: false,
|
|
963
|
+
};
|
|
964
|
+
for (let i = 1; i < argv.length; i++) {
|
|
965
|
+
const a = argv[i];
|
|
966
|
+
if (!a) {
|
|
967
|
+
continue;
|
|
968
|
+
}
|
|
969
|
+
if (a === '-h' || a === '--help') {
|
|
970
|
+
opts.help = true;
|
|
971
|
+
continue;
|
|
972
|
+
}
|
|
973
|
+
if (a === '--check') {
|
|
974
|
+
opts.check = true;
|
|
975
|
+
continue;
|
|
976
|
+
}
|
|
977
|
+
if (a === '--force') {
|
|
978
|
+
opts.force = true;
|
|
979
|
+
continue;
|
|
980
|
+
}
|
|
981
|
+
if (a === '--to') {
|
|
982
|
+
opts.to = argv[++i];
|
|
983
|
+
continue;
|
|
984
|
+
}
|
|
985
|
+
if (a === '--channel') {
|
|
986
|
+
opts.channel = argv[++i];
|
|
987
|
+
continue;
|
|
988
|
+
}
|
|
989
|
+
if (a === '--repo') {
|
|
990
|
+
opts.repo = argv[++i];
|
|
991
|
+
continue;
|
|
992
|
+
}
|
|
993
|
+
if (a === '--base-url') {
|
|
994
|
+
opts.baseUrl = argv[++i];
|
|
995
|
+
continue;
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
return opts;
|
|
999
|
+
}
|
|
1000
|
+
|
|
922
1001
|
function parseLogLevel(argv) {
|
|
923
1002
|
for (let i = 1; i < argv.length; i++) {
|
|
924
1003
|
const a = argv[i];
|
|
@@ -1023,6 +1102,39 @@ async function main() {
|
|
|
1023
1102
|
process.stdout.write(msgs.join('\n') + '\n');
|
|
1024
1103
|
return;
|
|
1025
1104
|
}
|
|
1105
|
+
if (command === 'update') {
|
|
1106
|
+
const parsed = parseUpdateArgv(argv);
|
|
1107
|
+
if (parsed.help) {
|
|
1108
|
+
printUpdateHelp();
|
|
1109
|
+
return;
|
|
1110
|
+
}
|
|
1111
|
+
let currentVersion = '';
|
|
1112
|
+
try {
|
|
1113
|
+
currentVersion = String(require('../package.json').version || '');
|
|
1114
|
+
} catch {
|
|
1115
|
+
currentVersion = '';
|
|
1116
|
+
}
|
|
1117
|
+
try {
|
|
1118
|
+
const {runUpdate} = require('./selfUpdate');
|
|
1119
|
+
const result = await runUpdate({
|
|
1120
|
+
currentVersion,
|
|
1121
|
+
checkOnly: !!parsed.check,
|
|
1122
|
+
version: parsed.to,
|
|
1123
|
+
channel: parsed.channel,
|
|
1124
|
+
force: !!parsed.force,
|
|
1125
|
+
repo: parsed.repo,
|
|
1126
|
+
releaseBaseUrl: parsed.baseUrl,
|
|
1127
|
+
});
|
|
1128
|
+
process.stdout.write(String(result.message || '') + '\n');
|
|
1129
|
+
if (!result.ok) {
|
|
1130
|
+
process.exitCode = 2;
|
|
1131
|
+
}
|
|
1132
|
+
} catch (e) {
|
|
1133
|
+
process.stderr.write(`Error updating testlight: ${e && e.message ? e.message : e}\n`);
|
|
1134
|
+
process.exitCode = 2;
|
|
1135
|
+
}
|
|
1136
|
+
return;
|
|
1137
|
+
}
|
|
1026
1138
|
if (command !== 'run' && command !== 'print-js') {
|
|
1027
1139
|
process.stderr.write(`Unknown command: ${command}\n`);
|
|
1028
1140
|
printHelp();
|
package/src/selfUpdate.test.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import os from 'os';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import {execFileSync} from 'child_process';
|
|
1
5
|
import {
|
|
2
6
|
buildDownloadUrl,
|
|
3
7
|
compareVersions,
|
|
@@ -5,6 +9,7 @@ import {
|
|
|
5
9
|
detectPlatform,
|
|
6
10
|
normalizeVersion,
|
|
7
11
|
planUpdate,
|
|
12
|
+
runUpdate,
|
|
8
13
|
} from './selfUpdate';
|
|
9
14
|
|
|
10
15
|
describe('selfUpdate helpers', () => {
|
|
@@ -31,6 +36,7 @@ describe('selfUpdate helpers', () => {
|
|
|
31
36
|
'/usr/local/bin/node',
|
|
32
37
|
'/usr/local/lib/node_modules/mmt-testlight/dist/cli.js'))
|
|
33
38
|
.toBe('npm');
|
|
39
|
+
expect(detectInstallChannel('/Applications/testlight')).toBe('standalone');
|
|
34
40
|
});
|
|
35
41
|
|
|
36
42
|
it('builds github and portal download urls', () => {
|
|
@@ -76,4 +82,41 @@ describe('selfUpdate helpers', () => {
|
|
|
76
82
|
expect(plan.action).toBe('download');
|
|
77
83
|
expect(plan.downloadUrl).toContain('/v1.2.3/testlight-');
|
|
78
84
|
});
|
|
85
|
+
|
|
86
|
+
it('replaces a standalone binary from a downloaded archive', async () => {
|
|
87
|
+
if (process.platform === 'win32') {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'testlight-update-test-'));
|
|
91
|
+
try {
|
|
92
|
+
const installDir = path.join(tmp, 'install');
|
|
93
|
+
const payloadDir = path.join(tmp, 'payload');
|
|
94
|
+
fs.mkdirSync(installDir);
|
|
95
|
+
fs.mkdirSync(payloadDir);
|
|
96
|
+
const current = path.join(installDir, 'testlight');
|
|
97
|
+
fs.writeFileSync(current, 'OLD');
|
|
98
|
+
fs.chmodSync(current, 0o755);
|
|
99
|
+
fs.writeFileSync(path.join(payloadDir, 'testlight'), 'NEW');
|
|
100
|
+
const archive = path.join(tmp, 'pkg.tar.gz');
|
|
101
|
+
execFileSync('tar', ['-czf', archive, '-C', payloadDir, 'testlight']);
|
|
102
|
+
|
|
103
|
+
const result = await runUpdate({
|
|
104
|
+
currentVersion: '1.0.0',
|
|
105
|
+
version: '1.2.3',
|
|
106
|
+
execPath: current,
|
|
107
|
+
fetchJson: async () => ({tag_name: 'v1.2.3'}),
|
|
108
|
+
downloadToFile: async (_url, dest) => {
|
|
109
|
+
fs.copyFileSync(archive, dest);
|
|
110
|
+
},
|
|
111
|
+
log: () => {},
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
expect(result.ok).toBe(true);
|
|
115
|
+
expect(result.updated).toBe(true);
|
|
116
|
+
expect(fs.readFileSync(current, 'utf8')).toBe('NEW');
|
|
117
|
+
expect(fs.lstatSync(path.join(installDir, 'mmt')).isSymbolicLink()).toBe(true);
|
|
118
|
+
} finally {
|
|
119
|
+
fs.rmSync(tmp, {recursive: true, force: true});
|
|
120
|
+
}
|
|
121
|
+
});
|
|
79
122
|
});
|
package/src/selfUpdate.ts
CHANGED
|
@@ -107,11 +107,21 @@ export function detectPlatform(
|
|
|
107
107
|
return `${osName}-${arch}` as UpdatePlatform;
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
function isSeaBinary(): boolean {
|
|
111
|
+
try {
|
|
112
|
+
// Node 20+ official SEA (used by @yao-pkg/pkg --sea). Not set for vercel/pkg.
|
|
113
|
+
const sea = require('node:sea') as {isSea?: () => boolean};
|
|
114
|
+
return typeof sea.isSea === 'function' && sea.isSea();
|
|
115
|
+
} catch {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
110
120
|
export function detectInstallChannel(execPath: string, scriptPath?: string):
|
|
111
121
|
InstallChannel {
|
|
112
122
|
const exec = execPath.replace(/\\/g, '/');
|
|
113
123
|
const script = (scriptPath || '').replace(/\\/g, '/');
|
|
114
|
-
if ((process as any).pkg) {
|
|
124
|
+
if ((process as any).pkg || isSeaBinary()) {
|
|
115
125
|
return 'standalone';
|
|
116
126
|
}
|
|
117
127
|
if (/\/Cellar\/mmt-testlight\//i.test(exec) ||
|