lopebase 0.4.0 → 0.4.2
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/dist/lopebase.js +260 -245
- package/package.json +3 -2
package/dist/lopebase.js
CHANGED
|
@@ -14,7 +14,7 @@ var __toESMCache_node, __toESMCache_esm, __toESM = (mod, isNodeMode, target) =>
|
|
|
14
14
|
return cached;
|
|
15
15
|
}
|
|
16
16
|
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
17
|
-
let to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: !0 }) : target;
|
|
17
|
+
let to = isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", { value: mod, enumerable: !0 }) : target;
|
|
18
18
|
if (mod && typeof mod === "object" || typeof mod === "function") {
|
|
19
19
|
for (let key of __getOwnPropNames(mod))
|
|
20
20
|
if (!__hasOwnProp.call(to, key))
|
|
@@ -157,8 +157,8 @@ var require_windows = __commonJS(function(exports, module) {
|
|
|
157
157
|
if (pathext = pathext.split(";"), pathext.indexOf("") !== -1)
|
|
158
158
|
return !0;
|
|
159
159
|
for (var i = 0;i < pathext.length; i++) {
|
|
160
|
-
var
|
|
161
|
-
if (
|
|
160
|
+
var p = pathext[i].toLowerCase();
|
|
161
|
+
if (p && path.substr(-p.length).toLowerCase() === p)
|
|
162
162
|
return !0;
|
|
163
163
|
}
|
|
164
164
|
return !1;
|
|
@@ -195,7 +195,7 @@ var require_mode = __commonJS(function(exports, module) {
|
|
|
195
195
|
return stat.isFile() && checkMode(stat, options);
|
|
196
196
|
}
|
|
197
197
|
function checkMode(stat, options) {
|
|
198
|
-
var { mode: mod, uid, gid } = stat, myUid = options.uid !== void 0 ? options.uid : process.getuid && process.getuid(), myGid = options.gid !== void 0 ? options.gid : process.getgid && process.getgid(),
|
|
198
|
+
var { mode: mod, uid, gid } = stat, myUid = options.uid !== void 0 ? options.uid : process.getuid && process.getuid(), myGid = options.gid !== void 0 ? options.gid : process.getgid && process.getgid(), u = parseInt("100", 8), g = parseInt("010", 8), o = parseInt("001", 8), ug = u | g, ret = mod & o || mod & g && gid === myGid || mod & u && uid === myUid || mod & ug && myUid === 0;
|
|
199
199
|
return ret;
|
|
200
200
|
}
|
|
201
201
|
});
|
|
@@ -268,19 +268,19 @@ var require_which = __commonJS(function(exports, module) {
|
|
|
268
268
|
let { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt), found = [], step = (i) => new Promise((resolve, reject) => {
|
|
269
269
|
if (i === pathEnv.length)
|
|
270
270
|
return opt.all && found.length ? resolve(found) : reject(getNotFoundError(cmd));
|
|
271
|
-
let ppRaw = pathEnv[i], pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw, pCmd = path.join(pathPart, cmd),
|
|
272
|
-
resolve(subStep(
|
|
273
|
-
}), subStep = (
|
|
271
|
+
let ppRaw = pathEnv[i], pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw, pCmd = path.join(pathPart, cmd), p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
|
|
272
|
+
resolve(subStep(p, i, 0));
|
|
273
|
+
}), subStep = (p, i, ii) => new Promise((resolve, reject) => {
|
|
274
274
|
if (ii === pathExt.length)
|
|
275
275
|
return resolve(step(i + 1));
|
|
276
276
|
let ext = pathExt[ii];
|
|
277
|
-
isexe(
|
|
277
|
+
isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
|
|
278
278
|
if (!er && is)
|
|
279
279
|
if (opt.all)
|
|
280
|
-
found.push(
|
|
280
|
+
found.push(p + ext);
|
|
281
281
|
else
|
|
282
|
-
return resolve(
|
|
283
|
-
return resolve(subStep(
|
|
282
|
+
return resolve(p + ext);
|
|
283
|
+
return resolve(subStep(p, i, ii + 1));
|
|
284
284
|
});
|
|
285
285
|
});
|
|
286
286
|
return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
|
|
@@ -288,9 +288,9 @@ var require_which = __commonJS(function(exports, module) {
|
|
|
288
288
|
opt = opt || {};
|
|
289
289
|
let { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt), found = [];
|
|
290
290
|
for (let i = 0;i < pathEnv.length; i++) {
|
|
291
|
-
let ppRaw = pathEnv[i], pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw, pCmd = path.join(pathPart, cmd),
|
|
292
|
-
for (let
|
|
293
|
-
let cur =
|
|
291
|
+
let ppRaw = pathEnv[i], pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw, pCmd = path.join(pathPart, cmd), p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
|
|
292
|
+
for (let j = 0;j < pathExt.length; j++) {
|
|
293
|
+
let cur = p + pathExt[j];
|
|
294
294
|
try {
|
|
295
295
|
if (isexe.sync(cur, { pathExt: pathExtExe }))
|
|
296
296
|
if (opt.all)
|
|
@@ -337,7 +337,7 @@ var require_resolveCommand = __commonJS(function(exports, module) {
|
|
|
337
337
|
path: env[getPathKey({ env })],
|
|
338
338
|
pathExt: withoutPathExt ? path.delimiter : void 0
|
|
339
339
|
});
|
|
340
|
-
} catch (
|
|
340
|
+
} catch (e) {} finally {
|
|
341
341
|
if (shouldSwitchCwd)
|
|
342
342
|
process.chdir(cwd);
|
|
343
343
|
}
|
|
@@ -392,7 +392,7 @@ var require_readShebang = __commonJS(function(exports, module) {
|
|
|
392
392
|
let buffer = Buffer.alloc(150), fd;
|
|
393
393
|
try {
|
|
394
394
|
fd = fs.openSync(command, "r"), fs.readSync(fd, buffer, 0, 150, 0), fs.closeSync(fd);
|
|
395
|
-
} catch (
|
|
395
|
+
} catch (e) {}
|
|
396
396
|
return shebangCommand(buffer.toString());
|
|
397
397
|
}
|
|
398
398
|
module.exports = readShebang;
|
|
@@ -968,17 +968,17 @@ var V2 = ce(), u = (t, n) => V2 ? t : n, le = u("◆", "*"), L2 = u("■", "x"),
|
|
|
968
968
|
return import_picocolors2.default.green(C);
|
|
969
969
|
}
|
|
970
970
|
}, G2 = (t) => {
|
|
971
|
-
let { cursor: n, options:
|
|
972
|
-
n >=
|
|
973
|
-
let $
|
|
974
|
-
return
|
|
975
|
-
let
|
|
976
|
-
return
|
|
971
|
+
let { cursor: n, options: r, style: i } = t, s = t.maxItems ?? Number.POSITIVE_INFINITY, c = Math.max(process.stdout.rows - 4, 0), a = Math.min(c, Math.max(s, 5)), l = 0;
|
|
972
|
+
n >= l + a - 3 ? l = Math.max(Math.min(n - a + 3, r.length - a), 0) : n < l + 2 && (l = Math.max(n - 2, 0));
|
|
973
|
+
let $ = a < r.length && l > 0, g = a < r.length && l + a < r.length;
|
|
974
|
+
return r.slice(l, l + a).map((p, v, f) => {
|
|
975
|
+
let j = v === 0 && $, E = v === f.length - 1 && g;
|
|
976
|
+
return j || E ? import_picocolors2.default.dim("...") : i(p, v + l === n);
|
|
977
977
|
});
|
|
978
978
|
}, he = (t) => new RD({ validate: t.validate, placeholder: t.placeholder, defaultValue: t.defaultValue, initialValue: t.initialValue, render() {
|
|
979
979
|
let n = `${import_picocolors2.default.gray(o)}
|
|
980
980
|
${b2(this.state)} ${t.message}
|
|
981
|
-
`,
|
|
981
|
+
`, r = t.placeholder ? import_picocolors2.default.inverse(t.placeholder[0]) + import_picocolors2.default.dim(t.placeholder.slice(1)) : import_picocolors2.default.inverse(import_picocolors2.default.hidden("_")), i = this.value ? this.valueWithCursor : r;
|
|
982
982
|
switch (this.state) {
|
|
983
983
|
case "error":
|
|
984
984
|
return `${n.trim()}
|
|
@@ -998,7 +998,7 @@ ${import_picocolors2.default.cyan(d2)}
|
|
|
998
998
|
} }).prompt(), ge = (t) => new MD({ validate: t.validate, mask: t.mask ?? $e, render() {
|
|
999
999
|
let n = `${import_picocolors2.default.gray(o)}
|
|
1000
1000
|
${b2(this.state)} ${t.message}
|
|
1001
|
-
`,
|
|
1001
|
+
`, r = this.valueWithCursor, i = this.masked;
|
|
1002
1002
|
switch (this.state) {
|
|
1003
1003
|
case "error":
|
|
1004
1004
|
return `${n.trim()}
|
|
@@ -1011,16 +1011,16 @@ ${import_picocolors2.default.yellow(d2)} ${import_picocolors2.default.yellow(th
|
|
|
1011
1011
|
return `${n}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(i ?? ""))}${i ? `
|
|
1012
1012
|
${import_picocolors2.default.gray(o)}` : ""}`;
|
|
1013
1013
|
default:
|
|
1014
|
-
return `${n}${import_picocolors2.default.cyan(o)} ${
|
|
1014
|
+
return `${n}${import_picocolors2.default.cyan(o)} ${r}
|
|
1015
1015
|
${import_picocolors2.default.cyan(d2)}
|
|
1016
1016
|
`;
|
|
1017
1017
|
}
|
|
1018
1018
|
} }).prompt(), ye = (t) => {
|
|
1019
|
-
let n = t.active ?? "Yes",
|
|
1020
|
-
return new dD({ active: n, inactive:
|
|
1019
|
+
let n = t.active ?? "Yes", r = t.inactive ?? "No";
|
|
1020
|
+
return new dD({ active: n, inactive: r, initialValue: t.initialValue ?? !0, render() {
|
|
1021
1021
|
let i = `${import_picocolors2.default.gray(o)}
|
|
1022
1022
|
${b2(this.state)} ${t.message}
|
|
1023
|
-
`, s = this.value ? n :
|
|
1023
|
+
`, s = this.value ? n : r;
|
|
1024
1024
|
switch (this.state) {
|
|
1025
1025
|
case "submit":
|
|
1026
1026
|
return `${i}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.dim(s)}`;
|
|
@@ -1028,19 +1028,19 @@ ${b2(this.state)} ${t.message}
|
|
|
1028
1028
|
return `${i}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(s))}
|
|
1029
1029
|
${import_picocolors2.default.gray(o)}`;
|
|
1030
1030
|
default:
|
|
1031
|
-
return `${i}${import_picocolors2.default.cyan(o)} ${this.value ? `${import_picocolors2.default.green(k2)} ${n}` : `${import_picocolors2.default.dim(P2)} ${import_picocolors2.default.dim(n)}`} ${import_picocolors2.default.dim("/")} ${this.value ? `${import_picocolors2.default.dim(P2)} ${import_picocolors2.default.dim(
|
|
1031
|
+
return `${i}${import_picocolors2.default.cyan(o)} ${this.value ? `${import_picocolors2.default.green(k2)} ${n}` : `${import_picocolors2.default.dim(P2)} ${import_picocolors2.default.dim(n)}`} ${import_picocolors2.default.dim("/")} ${this.value ? `${import_picocolors2.default.dim(P2)} ${import_picocolors2.default.dim(r)}` : `${import_picocolors2.default.green(k2)} ${r}`}
|
|
1032
1032
|
${import_picocolors2.default.cyan(d2)}
|
|
1033
1033
|
`;
|
|
1034
1034
|
}
|
|
1035
1035
|
} }).prompt();
|
|
1036
1036
|
}, ve = (t) => {
|
|
1037
|
-
let n = (
|
|
1038
|
-
let s =
|
|
1037
|
+
let n = (r, i) => {
|
|
1038
|
+
let s = r.label ?? String(r.value);
|
|
1039
1039
|
switch (i) {
|
|
1040
1040
|
case "selected":
|
|
1041
1041
|
return `${import_picocolors2.default.dim(s)}`;
|
|
1042
1042
|
case "active":
|
|
1043
|
-
return `${import_picocolors2.default.green(k2)} ${s} ${
|
|
1043
|
+
return `${import_picocolors2.default.green(k2)} ${s} ${r.hint ? import_picocolors2.default.dim(`(${r.hint})`) : ""}`;
|
|
1044
1044
|
case "cancelled":
|
|
1045
1045
|
return `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(s))}`;
|
|
1046
1046
|
default:
|
|
@@ -1048,17 +1048,17 @@ ${import_picocolors2.default.cyan(d2)}
|
|
|
1048
1048
|
}
|
|
1049
1049
|
};
|
|
1050
1050
|
return new LD({ options: t.options, initialValue: t.initialValue, render() {
|
|
1051
|
-
let
|
|
1051
|
+
let r = `${import_picocolors2.default.gray(o)}
|
|
1052
1052
|
${b2(this.state)} ${t.message}
|
|
1053
1053
|
`;
|
|
1054
1054
|
switch (this.state) {
|
|
1055
1055
|
case "submit":
|
|
1056
|
-
return `${
|
|
1056
|
+
return `${r}${import_picocolors2.default.gray(o)} ${n(this.options[this.cursor], "selected")}`;
|
|
1057
1057
|
case "cancel":
|
|
1058
|
-
return `${
|
|
1058
|
+
return `${r}${import_picocolors2.default.gray(o)} ${n(this.options[this.cursor], "cancelled")}
|
|
1059
1059
|
${import_picocolors2.default.gray(o)}`;
|
|
1060
1060
|
default:
|
|
1061
|
-
return `${
|
|
1061
|
+
return `${r}${import_picocolors2.default.cyan(o)} ${G2({ cursor: this.cursor, options: this.options, maxItems: t.maxItems, style: (i, s) => n(i, s ? "active" : "inactive") }).join(`
|
|
1062
1062
|
${import_picocolors2.default.cyan(o)} `)}
|
|
1063
1063
|
${import_picocolors2.default.cyan(d2)}
|
|
1064
1064
|
`;
|
|
@@ -1066,16 +1066,16 @@ ${import_picocolors2.default.cyan(d2)}
|
|
|
1066
1066
|
} }).prompt();
|
|
1067
1067
|
};
|
|
1068
1068
|
var fe = (t) => {
|
|
1069
|
-
let n = (
|
|
1070
|
-
let s =
|
|
1071
|
-
return i === "active" ? `${import_picocolors2.default.cyan(A2)} ${s} ${
|
|
1069
|
+
let n = (r, i) => {
|
|
1070
|
+
let s = r.label ?? String(r.value);
|
|
1071
|
+
return i === "active" ? `${import_picocolors2.default.cyan(A2)} ${s} ${r.hint ? import_picocolors2.default.dim(`(${r.hint})`) : ""}` : i === "selected" ? `${import_picocolors2.default.green(T)} ${import_picocolors2.default.dim(s)} ${r.hint ? import_picocolors2.default.dim(`(${r.hint})`) : ""}` : i === "cancelled" ? `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(s))}` : i === "active-selected" ? `${import_picocolors2.default.green(T)} ${s} ${r.hint ? import_picocolors2.default.dim(`(${r.hint})`) : ""}` : i === "submitted" ? `${import_picocolors2.default.dim(s)}` : `${import_picocolors2.default.dim(F)} ${import_picocolors2.default.dim(s)}`;
|
|
1072
1072
|
};
|
|
1073
|
-
return new SD({ options: t.options, initialValues: t.initialValues, required: t.required ?? !0, cursorAt: t.cursorAt, validate(
|
|
1074
|
-
if (this.required &&
|
|
1073
|
+
return new SD({ options: t.options, initialValues: t.initialValues, required: t.required ?? !0, cursorAt: t.cursorAt, validate(r) {
|
|
1074
|
+
if (this.required && r.length === 0)
|
|
1075
1075
|
return `Please select at least one option.
|
|
1076
1076
|
${import_picocolors2.default.reset(import_picocolors2.default.dim(`Press ${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(" space ")))} to select, ${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(" enter ")))} to submit`))}`;
|
|
1077
1077
|
}, render() {
|
|
1078
|
-
let
|
|
1078
|
+
let r = `${import_picocolors2.default.gray(o)}
|
|
1079
1079
|
${b2(this.state)} ${t.message}
|
|
1080
1080
|
`, i = (s, c) => {
|
|
1081
1081
|
let a = this.value.includes(s.value);
|
|
@@ -1083,23 +1083,23 @@ ${b2(this.state)} ${t.message}
|
|
|
1083
1083
|
};
|
|
1084
1084
|
switch (this.state) {
|
|
1085
1085
|
case "submit":
|
|
1086
|
-
return `${
|
|
1086
|
+
return `${r}${import_picocolors2.default.gray(o)} ${this.options.filter(({ value: s }) => this.value.includes(s)).map((s) => n(s, "submitted")).join(import_picocolors2.default.dim(", ")) || import_picocolors2.default.dim("none")}`;
|
|
1087
1087
|
case "cancel": {
|
|
1088
1088
|
let s = this.options.filter(({ value: c }) => this.value.includes(c)).map((c) => n(c, "cancelled")).join(import_picocolors2.default.dim(", "));
|
|
1089
|
-
return `${
|
|
1089
|
+
return `${r}${import_picocolors2.default.gray(o)} ${s.trim() ? `${s}
|
|
1090
1090
|
${import_picocolors2.default.gray(o)}` : ""}`;
|
|
1091
1091
|
}
|
|
1092
1092
|
case "error": {
|
|
1093
1093
|
let s = this.error.split(`
|
|
1094
1094
|
`).map((c, a) => a === 0 ? `${import_picocolors2.default.yellow(d2)} ${import_picocolors2.default.yellow(c)}` : ` ${c}`).join(`
|
|
1095
1095
|
`);
|
|
1096
|
-
return `${
|
|
1096
|
+
return `${r + import_picocolors2.default.yellow(o)} ${G2({ options: this.options, cursor: this.cursor, maxItems: t.maxItems, style: i }).join(`
|
|
1097
1097
|
${import_picocolors2.default.yellow(o)} `)}
|
|
1098
1098
|
${s}
|
|
1099
1099
|
`;
|
|
1100
1100
|
}
|
|
1101
1101
|
default:
|
|
1102
|
-
return `${
|
|
1102
|
+
return `${r}${import_picocolors2.default.cyan(o)} ${G2({ options: this.options, cursor: this.cursor, maxItems: t.maxItems, style: i }).join(`
|
|
1103
1103
|
${import_picocolors2.default.cyan(o)} `)}
|
|
1104
1104
|
${import_picocolors2.default.cyan(d2)}
|
|
1105
1105
|
`;
|
|
@@ -1107,13 +1107,13 @@ ${import_picocolors2.default.cyan(d2)}
|
|
|
1107
1107
|
} }).prompt();
|
|
1108
1108
|
};
|
|
1109
1109
|
var Me = (t = "", n = "") => {
|
|
1110
|
-
let
|
|
1110
|
+
let r = `
|
|
1111
1111
|
${t}
|
|
1112
1112
|
`.split(`
|
|
1113
|
-
`), i = S2(n).length, s = Math.max(
|
|
1114
|
-
let $
|
|
1115
|
-
return
|
|
1116
|
-
}, 0), i) + 2, c =
|
|
1113
|
+
`), i = S2(n).length, s = Math.max(r.reduce((a, l) => {
|
|
1114
|
+
let $ = S2(l);
|
|
1115
|
+
return $.length > a ? $.length : a;
|
|
1116
|
+
}, 0), i) + 2, c = r.map((a) => `${import_picocolors2.default.gray(o)} ${import_picocolors2.default.dim(a)}${" ".repeat(s - S2(a).length)}${import_picocolors2.default.gray(o)}`).join(`
|
|
1117
1117
|
`);
|
|
1118
1118
|
process.stdout.write(`${import_picocolors2.default.gray(o)}
|
|
1119
1119
|
${import_picocolors2.default.green(C)} ${import_picocolors2.default.reset(n)} ${import_picocolors2.default.gray(_2.repeat(Math.max(s - i - 1, 1)) + me)}
|
|
@@ -1133,13 +1133,13 @@ ${import_picocolors2.default.gray(d2)} ${t}
|
|
|
1133
1133
|
|
|
1134
1134
|
`);
|
|
1135
1135
|
}, M2 = { message: (t = "", { symbol: n = import_picocolors2.default.gray(o) } = {}) => {
|
|
1136
|
-
let
|
|
1136
|
+
let r = [`${import_picocolors2.default.gray(o)}`];
|
|
1137
1137
|
if (t) {
|
|
1138
1138
|
let [i, ...s] = t.split(`
|
|
1139
1139
|
`);
|
|
1140
|
-
|
|
1140
|
+
r.push(`${n} ${i}`, ...s.map((c) => `${import_picocolors2.default.gray(o)} ${c}`));
|
|
1141
1141
|
}
|
|
1142
|
-
process.stdout.write(`${
|
|
1142
|
+
process.stdout.write(`${r.join(`
|
|
1143
1143
|
`)}
|
|
1144
1144
|
`);
|
|
1145
1145
|
}, info: (t) => {
|
|
@@ -1156,52 +1156,52 @@ ${import_picocolors2.default.gray(d2)} ${t}
|
|
|
1156
1156
|
M2.message(t, { symbol: import_picocolors2.default.red(K2) });
|
|
1157
1157
|
} }, J2 = `${import_picocolors2.default.gray(o)} `;
|
|
1158
1158
|
var Y2 = ({ indicator: t = "dots" } = {}) => {
|
|
1159
|
-
let n = V2 ? ["◒", "◐", "◓", "◑"] : ["•", "o", "O", "0"],
|
|
1160
|
-
let
|
|
1161
|
-
a &&
|
|
1162
|
-
},
|
|
1163
|
-
process.on("uncaughtExceptionMonitor",
|
|
1159
|
+
let n = V2 ? ["◒", "◐", "◓", "◑"] : ["•", "o", "O", "0"], r = V2 ? 80 : 120, i = process.env.CI === "true", s, c, a = !1, l = "", $, g = performance.now(), p = (m) => {
|
|
1160
|
+
let h = m > 1 ? "Something went wrong" : "Canceled";
|
|
1161
|
+
a && N(h, m);
|
|
1162
|
+
}, v = () => p(2), f = () => p(1), j = () => {
|
|
1163
|
+
process.on("uncaughtExceptionMonitor", v), process.on("unhandledRejection", v), process.on("SIGINT", f), process.on("SIGTERM", f), process.on("exit", p);
|
|
1164
1164
|
}, E = () => {
|
|
1165
|
-
process.removeListener("uncaughtExceptionMonitor",
|
|
1166
|
-
},
|
|
1167
|
-
if ($
|
|
1165
|
+
process.removeListener("uncaughtExceptionMonitor", v), process.removeListener("unhandledRejection", v), process.removeListener("SIGINT", f), process.removeListener("SIGTERM", f), process.removeListener("exit", p);
|
|
1166
|
+
}, B = () => {
|
|
1167
|
+
if ($ === void 0)
|
|
1168
1168
|
return;
|
|
1169
1169
|
i && process.stdout.write(`
|
|
1170
1170
|
`);
|
|
1171
|
-
let
|
|
1171
|
+
let m = $.split(`
|
|
1172
1172
|
`);
|
|
1173
|
-
process.stdout.write(import_sisteransi2.cursor.move(-999,
|
|
1174
|
-
},
|
|
1175
|
-
let
|
|
1176
|
-
return
|
|
1177
|
-
},
|
|
1178
|
-
a = !0, s = fD(),
|
|
1173
|
+
process.stdout.write(import_sisteransi2.cursor.move(-999, m.length - 1)), process.stdout.write(import_sisteransi2.erase.down(m.length));
|
|
1174
|
+
}, R = (m) => m.replace(/\.+$/, ""), O = (m) => {
|
|
1175
|
+
let h = (performance.now() - m) / 1000, w = Math.floor(h / 60), I = Math.floor(h % 60);
|
|
1176
|
+
return w > 0 ? `[${w}m ${I}s]` : `[${I}s]`;
|
|
1177
|
+
}, H = (m = "") => {
|
|
1178
|
+
a = !0, s = fD(), l = R(m), g = performance.now(), process.stdout.write(`${import_picocolors2.default.gray(o)}
|
|
1179
1179
|
`);
|
|
1180
|
-
let
|
|
1181
|
-
|
|
1182
|
-
if (i &&
|
|
1180
|
+
let h = 0, w = 0;
|
|
1181
|
+
j(), c = setInterval(() => {
|
|
1182
|
+
if (i && l === $)
|
|
1183
1183
|
return;
|
|
1184
|
-
|
|
1185
|
-
let
|
|
1184
|
+
B(), $ = l;
|
|
1185
|
+
let I = import_picocolors2.default.magenta(n[h]);
|
|
1186
1186
|
if (i)
|
|
1187
|
-
process.stdout.write(`${
|
|
1187
|
+
process.stdout.write(`${I} ${l}...`);
|
|
1188
1188
|
else if (t === "timer")
|
|
1189
|
-
process.stdout.write(`${
|
|
1189
|
+
process.stdout.write(`${I} ${l} ${O(g)}`);
|
|
1190
1190
|
else {
|
|
1191
|
-
let
|
|
1192
|
-
process.stdout.write(`${
|
|
1191
|
+
let z = ".".repeat(Math.floor(w)).slice(0, 3);
|
|
1192
|
+
process.stdout.write(`${I} ${l}${z}`);
|
|
1193
1193
|
}
|
|
1194
|
-
|
|
1195
|
-
},
|
|
1196
|
-
},
|
|
1197
|
-
a = !1, clearInterval(c),
|
|
1198
|
-
let
|
|
1199
|
-
|
|
1200
|
-
`) : process.stdout.write(`${
|
|
1194
|
+
h = h + 1 < n.length ? h + 1 : 0, w = w < n.length ? w + 0.125 : 0;
|
|
1195
|
+
}, r);
|
|
1196
|
+
}, N = (m = "", h = 0) => {
|
|
1197
|
+
a = !1, clearInterval(c), B();
|
|
1198
|
+
let w = h === 0 ? import_picocolors2.default.green(C) : h === 1 ? import_picocolors2.default.red(L2) : import_picocolors2.default.red(W2);
|
|
1199
|
+
l = R(m ?? l), t === "timer" ? process.stdout.write(`${w} ${l} ${O(g)}
|
|
1200
|
+
`) : process.stdout.write(`${w} ${l}
|
|
1201
1201
|
`), E(), s();
|
|
1202
1202
|
};
|
|
1203
|
-
return { start:
|
|
1204
|
-
|
|
1203
|
+
return { start: H, stop: N, message: (m = "") => {
|
|
1204
|
+
l = R(m ?? l);
|
|
1205
1205
|
} };
|
|
1206
1206
|
};
|
|
1207
1207
|
|
|
@@ -1209,7 +1209,7 @@ var Y2 = ({ indicator: t = "dots" } = {}) => {
|
|
|
1209
1209
|
var SIGNATURE_HEADER = "lopebase-signature";
|
|
1210
1210
|
var enc = /* @__PURE__ */ new TextEncoder;
|
|
1211
1211
|
function hex(bytes) {
|
|
1212
|
-
return [...new Uint8Array(bytes)].map((
|
|
1212
|
+
return [...new Uint8Array(bytes)].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1213
1213
|
}
|
|
1214
1214
|
async function sha256Hex(data) {
|
|
1215
1215
|
return hex(await crypto.subtle.digest("SHA-256", data));
|
|
@@ -1220,8 +1220,8 @@ async function hmacHex(secret, message) {
|
|
|
1220
1220
|
}
|
|
1221
1221
|
function newSigningSecret() {
|
|
1222
1222
|
let bytes = crypto.getRandomValues(new Uint8Array(32)), bin = "";
|
|
1223
|
-
for (let
|
|
1224
|
-
bin += String.fromCharCode(
|
|
1223
|
+
for (let b of bytes)
|
|
1224
|
+
bin += String.fromCharCode(b);
|
|
1225
1225
|
return "lbs_" + btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
1226
1226
|
}
|
|
1227
1227
|
function payload(t, method, pathAndQuery, bodyHash) {
|
|
@@ -1258,7 +1258,7 @@ var SENSITIVE_PARTS = /* @__PURE__ */ new Set([
|
|
|
1258
1258
|
]), SENSITIVE_JOINED = /apikey|privatekey|secretkey|accesskey|accountnumber|routingnumber|stripecustomer|paymentmethod|recoverycode/;
|
|
1259
1259
|
function isSensitiveFieldName(name) {
|
|
1260
1260
|
let parts = name.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase().split(/[^a-z0-9]+/).filter(Boolean);
|
|
1261
|
-
if (parts.some((
|
|
1261
|
+
if (parts.some((p) => SENSITIVE_PARTS.has(p)))
|
|
1262
1262
|
return !0;
|
|
1263
1263
|
return SENSITIVE_JOINED.test(parts.join(""));
|
|
1264
1264
|
}
|
|
@@ -1277,12 +1277,12 @@ function conformanceChecks(opts) {
|
|
|
1277
1277
|
let remote = !opts.adapter, base = opts.baseUrl ? opts.baseUrl.replace(/\/$/, "") : `${opts.origin ?? "https://property.test"}${(opts.basePath ?? opts.adapter?.config.basePath ?? DEFAULT_BASE_PATH).replace(/\/$/, "")}`, send = (req) => opts.adapter ? opts.adapter.handle(req) : fetch(req);
|
|
1278
1278
|
async function signedHeaders(url, method, bodyText, timestamp) {
|
|
1279
1279
|
if (opts.secret) {
|
|
1280
|
-
let
|
|
1280
|
+
let u = new URL(url);
|
|
1281
1281
|
return {
|
|
1282
1282
|
[SIGNATURE_HEADER]: await signRequest({
|
|
1283
1283
|
secret: opts.secret,
|
|
1284
1284
|
method,
|
|
1285
|
-
pathAndQuery:
|
|
1285
|
+
pathAndQuery: u.pathname + u.search,
|
|
1286
1286
|
body: bodyText,
|
|
1287
1287
|
timestamp
|
|
1288
1288
|
})
|
|
@@ -1300,14 +1300,14 @@ function conformanceChecks(opts) {
|
|
|
1300
1300
|
...init?.headers
|
|
1301
1301
|
}
|
|
1302
1302
|
}));
|
|
1303
|
-
}, resources = () => authed("/resources").then((
|
|
1303
|
+
}, resources = () => authed("/resources").then((r) => body(r)), checks = [
|
|
1304
1304
|
{
|
|
1305
1305
|
name: "GET /health returns { ok } without auth",
|
|
1306
1306
|
async run() {
|
|
1307
1307
|
let res = await send(new Request(`${base}/health`));
|
|
1308
1308
|
assert.equal(res.status, 200);
|
|
1309
|
-
let
|
|
1310
|
-
assert.equal(typeof
|
|
1309
|
+
let b = await body(res);
|
|
1310
|
+
assert.equal(typeof b.ok, "boolean");
|
|
1311
1311
|
}
|
|
1312
1312
|
},
|
|
1313
1313
|
{
|
|
@@ -1322,10 +1322,10 @@ function conformanceChecks(opts) {
|
|
|
1322
1322
|
async run() {
|
|
1323
1323
|
let res = await authed("/resources");
|
|
1324
1324
|
assert.equal(res.status, 200);
|
|
1325
|
-
let
|
|
1326
|
-
assert.ok(Array.isArray(
|
|
1327
|
-
for (let
|
|
1328
|
-
assert.ok(
|
|
1325
|
+
let b = await body(res);
|
|
1326
|
+
assert.ok(Array.isArray(b.resources));
|
|
1327
|
+
for (let r of b.resources)
|
|
1328
|
+
assert.ok(r.name && r.label && r.readCapability), assert.ok(Array.isArray(r.fields));
|
|
1329
1329
|
}
|
|
1330
1330
|
},
|
|
1331
1331
|
{
|
|
@@ -1333,9 +1333,9 @@ function conformanceChecks(opts) {
|
|
|
1333
1333
|
async run() {
|
|
1334
1334
|
let res = await authed("/actions");
|
|
1335
1335
|
assert.equal(res.status, 200);
|
|
1336
|
-
let
|
|
1337
|
-
assert.ok(Array.isArray(
|
|
1338
|
-
for (let a of
|
|
1336
|
+
let b = await body(res);
|
|
1337
|
+
assert.ok(Array.isArray(b.actions));
|
|
1338
|
+
for (let a of b.actions)
|
|
1339
1339
|
assert.ok(a.name && a.label && a.capability), assert.ok(Array.isArray(a.params));
|
|
1340
1340
|
}
|
|
1341
1341
|
},
|
|
@@ -1354,7 +1354,7 @@ function conformanceChecks(opts) {
|
|
|
1354
1354
|
{
|
|
1355
1355
|
name: "GET /resources/:name/:id returns a row or 404-null",
|
|
1356
1356
|
async run() {
|
|
1357
|
-
let cat = await resources(), meta = opts.sampleResource ? cat.resources.find((
|
|
1357
|
+
let cat = await resources(), meta = opts.sampleResource ? cat.resources.find((r) => r.name === opts.sampleResource) : cat.resources[0];
|
|
1358
1358
|
if (!meta)
|
|
1359
1359
|
return;
|
|
1360
1360
|
let first = (await body(await authed(`/resources/${meta.name}?limit=1`))).rows[0];
|
|
@@ -1369,8 +1369,8 @@ function conformanceChecks(opts) {
|
|
|
1369
1369
|
async run() {
|
|
1370
1370
|
let res = await authed("/audit");
|
|
1371
1371
|
assert.equal(res.status, 200);
|
|
1372
|
-
let
|
|
1373
|
-
assert.ok(Array.isArray(
|
|
1372
|
+
let b = await body(res);
|
|
1373
|
+
assert.ok(Array.isArray(b.rows));
|
|
1374
1374
|
}
|
|
1375
1375
|
},
|
|
1376
1376
|
{
|
|
@@ -1384,24 +1384,24 @@ function conformanceChecks(opts) {
|
|
|
1384
1384
|
name: "no field in the catalog looks like a secret unless marked safe",
|
|
1385
1385
|
async run() {
|
|
1386
1386
|
let cat = await resources();
|
|
1387
|
-
for (let
|
|
1388
|
-
for (let f of
|
|
1389
|
-
assert.ok(!isSensitiveFieldName(f.name) || f.sensitive === "allow", `${
|
|
1387
|
+
for (let r of cat.resources)
|
|
1388
|
+
for (let f of r.fields)
|
|
1389
|
+
assert.ok(!isSensitiveFieldName(f.name) || f.sensitive === "allow", `${r.name}.${f.name} looks sensitive`);
|
|
1390
1390
|
}
|
|
1391
1391
|
},
|
|
1392
1392
|
{
|
|
1393
1393
|
name: "rows contain only declared fields, and a page is at most 100",
|
|
1394
1394
|
async run() {
|
|
1395
1395
|
let cat = await resources();
|
|
1396
|
-
for (let
|
|
1397
|
-
let res = await authed(`/resources/${
|
|
1396
|
+
for (let r of cat.resources) {
|
|
1397
|
+
let res = await authed(`/resources/${r.name}?limit=1000`);
|
|
1398
1398
|
assert.equal(res.status, 200);
|
|
1399
1399
|
let page = await body(res);
|
|
1400
|
-
assert.ok(page.rows.length <= 100, `${
|
|
1401
|
-
let declared = /* @__PURE__ */ new Set(["id", ...
|
|
1400
|
+
assert.ok(page.rows.length <= 100, `${r.name} returned ${page.rows.length} rows`);
|
|
1401
|
+
let declared = /* @__PURE__ */ new Set(["id", ...r.fields.map((f) => f.name)]);
|
|
1402
1402
|
for (let row of page.rows)
|
|
1403
|
-
for (let
|
|
1404
|
-
assert.ok(declared.has(
|
|
1403
|
+
for (let k of Object.keys(row))
|
|
1404
|
+
assert.ok(declared.has(k), `${r.name} returned undeclared field ${k}`);
|
|
1405
1405
|
}
|
|
1406
1406
|
}
|
|
1407
1407
|
},
|
|
@@ -1419,7 +1419,7 @@ function conformanceChecks(opts) {
|
|
|
1419
1419
|
{
|
|
1420
1420
|
name: "a mutation writes an audit row (PATCH round-trips into /audit)",
|
|
1421
1421
|
async run() {
|
|
1422
|
-
let writable = (await resources()).resources.find((
|
|
1422
|
+
let writable = (await resources()).resources.find((r) => r.writeCapability && r.fields.some((f) => f.editable));
|
|
1423
1423
|
if (!writable || remote)
|
|
1424
1424
|
return;
|
|
1425
1425
|
let row = (await body(await authed(`/resources/${writable.name}?limit=1`))).rows[0];
|
|
@@ -1455,8 +1455,8 @@ async function checkAdapter(input) {
|
|
|
1455
1455
|
})
|
|
1456
1456
|
} : { authorization: `Bearer ${input.token ?? ""}` };
|
|
1457
1457
|
status = (await fetch(url, { headers })).status;
|
|
1458
|
-
} catch (
|
|
1459
|
-
let error = `Could not reach ${base} (${
|
|
1458
|
+
} catch (e) {
|
|
1459
|
+
let error = `Could not reach ${base} (${e instanceof Error ? e.message : String(e)}).`;
|
|
1460
1460
|
return log(`FAIL ${error}`), { passed, failed: [{ name: "reachable", error }] };
|
|
1461
1461
|
}
|
|
1462
1462
|
if (status === 401) {
|
|
@@ -1474,9 +1474,9 @@ async function checkAdapter(input) {
|
|
|
1474
1474
|
}))
|
|
1475
1475
|
try {
|
|
1476
1476
|
await c.run(), passed++, log(`pass ${c.name}`);
|
|
1477
|
-
} catch (
|
|
1478
|
-
let error =
|
|
1479
|
-
`)[0] : String(
|
|
1477
|
+
} catch (e) {
|
|
1478
|
+
let error = e instanceof Error ? e.message.split(`
|
|
1479
|
+
`)[0] : String(e);
|
|
1480
1480
|
failed.push({ name: c.name, error }), log(`FAIL ${c.name}: ${error}`);
|
|
1481
1481
|
}
|
|
1482
1482
|
return { passed, failed };
|
|
@@ -1490,7 +1490,7 @@ var AGENTS = [
|
|
|
1490
1490
|
id: "claude",
|
|
1491
1491
|
label: "Claude Code",
|
|
1492
1492
|
bin: "claude",
|
|
1493
|
-
args: (
|
|
1493
|
+
args: (p) => [p],
|
|
1494
1494
|
mcpAdd: (argv) => [
|
|
1495
1495
|
"mcp",
|
|
1496
1496
|
"add",
|
|
@@ -1505,27 +1505,27 @@ var AGENTS = [
|
|
|
1505
1505
|
id: "codex",
|
|
1506
1506
|
label: "Codex",
|
|
1507
1507
|
bin: "codex",
|
|
1508
|
-
args: (
|
|
1508
|
+
args: (p) => [p],
|
|
1509
1509
|
mcpAdd: (argv) => ["mcp", "add", "lopebase", "--", ...argv]
|
|
1510
1510
|
},
|
|
1511
1511
|
{
|
|
1512
1512
|
id: "gemini",
|
|
1513
1513
|
label: "Gemini CLI",
|
|
1514
1514
|
bin: "gemini",
|
|
1515
|
-
args: (
|
|
1515
|
+
args: (p) => ["-i", p],
|
|
1516
1516
|
mcpAdd: (argv) => ["mcp", "add", "lopebase", ...argv]
|
|
1517
1517
|
},
|
|
1518
1518
|
{
|
|
1519
1519
|
id: "opencode",
|
|
1520
1520
|
label: "opencode",
|
|
1521
1521
|
bin: "opencode",
|
|
1522
|
-
args: (
|
|
1522
|
+
args: (p) => ["--prompt", p]
|
|
1523
1523
|
},
|
|
1524
1524
|
{
|
|
1525
1525
|
id: "cursor-agent",
|
|
1526
1526
|
label: "Cursor Agent",
|
|
1527
1527
|
bin: "cursor-agent",
|
|
1528
|
-
args: (
|
|
1528
|
+
args: (p) => [p]
|
|
1529
1529
|
}
|
|
1530
1530
|
];
|
|
1531
1531
|
function isInstalled(bin) {
|
|
@@ -1564,17 +1564,17 @@ import os from "node:os";
|
|
|
1564
1564
|
import path from "node:path";
|
|
1565
1565
|
var DEFAULT_URL = "https://app.lopebase.com";
|
|
1566
1566
|
function workspaceUrl(input) {
|
|
1567
|
-
let
|
|
1568
|
-
if (!
|
|
1567
|
+
let v = input.trim().replace(/\/+$/, "");
|
|
1568
|
+
if (!v)
|
|
1569
1569
|
return null;
|
|
1570
|
-
if (/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i.test(
|
|
1571
|
-
return `https://${
|
|
1572
|
-
let withScheme = /^https?:\/\//i.test(
|
|
1570
|
+
if (/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i.test(v))
|
|
1571
|
+
return `https://${v.toLowerCase()}.lopebase.com`;
|
|
1572
|
+
let withScheme = /^https?:\/\//i.test(v) ? v : `https://${v}`;
|
|
1573
1573
|
try {
|
|
1574
|
-
let
|
|
1575
|
-
if (!
|
|
1574
|
+
let u = new URL(withScheme);
|
|
1575
|
+
if (!u.hostname.includes(".") && u.hostname !== "localhost")
|
|
1576
1576
|
return null;
|
|
1577
|
-
return `${
|
|
1577
|
+
return `${u.origin}${u.pathname.replace(/\/+$/, "")}`;
|
|
1578
1578
|
} catch {
|
|
1579
1579
|
return null;
|
|
1580
1580
|
}
|
|
@@ -1624,7 +1624,7 @@ var APP_SIDE_ENV = /^(NEXT_PUBLIC_|PUBLIC_|VITE_|NUXT_PUBLIC_|EXPO_PUBLIC_|REACT
|
|
|
1624
1624
|
function evidenceFor(facts, rule) {
|
|
1625
1625
|
let out = [], weak = [];
|
|
1626
1626
|
for (let re of rule.deps ?? []) {
|
|
1627
|
-
let hit = facts.dependencies.find((
|
|
1627
|
+
let hit = facts.dependencies.find((d) => re.test(d));
|
|
1628
1628
|
if (hit)
|
|
1629
1629
|
out.push(`uses ${hit.replace(/^(py|gem|composer|go|cargo):/, "")}`);
|
|
1630
1630
|
}
|
|
@@ -1634,7 +1634,7 @@ function evidenceFor(facts, rule) {
|
|
|
1634
1634
|
out.push(`has ${hit.replace(/#.*$/, "")}`);
|
|
1635
1635
|
}
|
|
1636
1636
|
for (let re of rule.env ?? []) {
|
|
1637
|
-
let hit = facts.envKeys.find((
|
|
1637
|
+
let hit = facts.envKeys.find((k) => re.test(k));
|
|
1638
1638
|
if (hit)
|
|
1639
1639
|
(APP_SIDE_ENV.test(hit) ? out : weak).push(`env ${hit}`);
|
|
1640
1640
|
}
|
|
@@ -1673,6 +1673,21 @@ var SOURCE_RULES = {
|
|
|
1673
1673
|
},
|
|
1674
1674
|
why: "Traffic and sources on your dashboard."
|
|
1675
1675
|
},
|
|
1676
|
+
plausible: {
|
|
1677
|
+
label: "Plausible",
|
|
1678
|
+
rule: {
|
|
1679
|
+
deps: [
|
|
1680
|
+
/^next-plausible$/,
|
|
1681
|
+
/^plausible-tracker$/,
|
|
1682
|
+
/^@plausible-analytics\/tracker$/,
|
|
1683
|
+
/^@nuxtjs\/plausible$/,
|
|
1684
|
+
/^gatsby-plugin-plausible$/,
|
|
1685
|
+
/^vue-plausible$/
|
|
1686
|
+
],
|
|
1687
|
+
env: [/PLAUSIBLE/]
|
|
1688
|
+
},
|
|
1689
|
+
why: "Pageviews and visitors on your dashboard."
|
|
1690
|
+
},
|
|
1676
1691
|
sentry: {
|
|
1677
1692
|
label: "Sentry",
|
|
1678
1693
|
rule: {
|
|
@@ -2131,7 +2146,7 @@ function detectStack(facts) {
|
|
|
2131
2146
|
evidence: [],
|
|
2132
2147
|
why: "Know the moment the site goes down. Nothing to install."
|
|
2133
2148
|
});
|
|
2134
|
-
if (isWebsite && !has("posthog") && !has("ga4")) {
|
|
2149
|
+
if (isWebsite && !has("posthog") && !has("ga4") && !has("plausible")) {
|
|
2135
2150
|
if (gaps.push("No product analytics found."), !listed("posthog"))
|
|
2136
2151
|
sources.push({
|
|
2137
2152
|
source: "posthog",
|
|
@@ -2168,27 +2183,27 @@ async function startDeviceLogin(url, opts = {}) {
|
|
|
2168
2183
|
});
|
|
2169
2184
|
if (!res.ok)
|
|
2170
2185
|
return null;
|
|
2171
|
-
let
|
|
2172
|
-
if (typeof
|
|
2186
|
+
let b = await res.json();
|
|
2187
|
+
if (typeof b.device_code !== "string" || typeof b.user_code !== "string")
|
|
2173
2188
|
return null;
|
|
2174
2189
|
return {
|
|
2175
|
-
deviceCode:
|
|
2176
|
-
userCode:
|
|
2177
|
-
verifyUrl: String(
|
|
2178
|
-
interval: Number(
|
|
2179
|
-
expiresIn: Number(
|
|
2190
|
+
deviceCode: b.device_code,
|
|
2191
|
+
userCode: b.user_code,
|
|
2192
|
+
verifyUrl: String(b.verification_uri_complete ?? b.verification_uri),
|
|
2193
|
+
interval: Number(b.interval) || 5,
|
|
2194
|
+
expiresIn: Number(b.expires_in) || 600
|
|
2180
2195
|
};
|
|
2181
2196
|
} catch {
|
|
2182
2197
|
return null;
|
|
2183
2198
|
}
|
|
2184
2199
|
}
|
|
2185
2200
|
async function pollDeviceLogin(url, start, opts = {}) {
|
|
2186
|
-
let f = opts.fetchImpl ?? fetch, sleep = opts.sleep ?? ((ms) => new Promise((
|
|
2201
|
+
let f = opts.fetchImpl ?? fetch, sleep = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms))), interval = start.interval, deadline = Date.now() + start.expiresIn * 1000;
|
|
2187
2202
|
while (Date.now() < deadline) {
|
|
2188
2203
|
await sleep(interval * 1000);
|
|
2189
|
-
let
|
|
2204
|
+
let body;
|
|
2190
2205
|
try {
|
|
2191
|
-
|
|
2206
|
+
body = await (await f(`${url}/api/oauth/token`, {
|
|
2192
2207
|
method: "POST",
|
|
2193
2208
|
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
2194
2209
|
body: new URLSearchParams({
|
|
@@ -2199,14 +2214,14 @@ async function pollDeviceLogin(url, start, opts = {}) {
|
|
|
2199
2214
|
} catch {
|
|
2200
2215
|
continue;
|
|
2201
2216
|
}
|
|
2202
|
-
if (typeof
|
|
2217
|
+
if (typeof body.access_token === "string")
|
|
2203
2218
|
return {
|
|
2204
2219
|
ok: !0,
|
|
2205
|
-
token:
|
|
2206
|
-
url: typeof
|
|
2207
|
-
scope: String(
|
|
2220
|
+
token: body.access_token,
|
|
2221
|
+
url: typeof body.workspace_url === "string" ? body.workspace_url : url,
|
|
2222
|
+
scope: String(body.scope ?? "")
|
|
2208
2223
|
};
|
|
2209
|
-
switch (
|
|
2224
|
+
switch (body.error) {
|
|
2210
2225
|
case "authorization_pending":
|
|
2211
2226
|
continue;
|
|
2212
2227
|
case "slow_down":
|
|
@@ -2228,7 +2243,7 @@ async function pollDeviceLogin(url, start, opts = {}) {
|
|
|
2228
2243
|
return {
|
|
2229
2244
|
ok: !1,
|
|
2230
2245
|
reason: "error",
|
|
2231
|
-
message: String(
|
|
2246
|
+
message: String(body.error_description ?? body.error ?? "Sign-in failed.")
|
|
2232
2247
|
};
|
|
2233
2248
|
}
|
|
2234
2249
|
}
|
|
@@ -2297,7 +2312,7 @@ async function runMcpProxy(auth, fetchImpl = fetch) {
|
|
|
2297
2312
|
}
|
|
2298
2313
|
process.stdout.write(`${text}
|
|
2299
2314
|
`);
|
|
2300
|
-
} catch (
|
|
2315
|
+
} catch (e) {
|
|
2301
2316
|
if (id === null)
|
|
2302
2317
|
return;
|
|
2303
2318
|
write({
|
|
@@ -2305,7 +2320,7 @@ async function runMcpProxy(auth, fetchImpl = fetch) {
|
|
|
2305
2320
|
id,
|
|
2306
2321
|
error: {
|
|
2307
2322
|
code: -32000,
|
|
2308
|
-
message: `Could not reach LopeBase at ${endpoint}: ${String(
|
|
2323
|
+
message: `Could not reach LopeBase at ${endpoint}: ${String(e)}`
|
|
2309
2324
|
}
|
|
2310
2325
|
});
|
|
2311
2326
|
}
|
|
@@ -2393,15 +2408,15 @@ var MONOREPO_DIRS = ["apps", "packages", "services", "sites", "web", "site"], SK
|
|
|
2393
2408
|
".github/workflows",
|
|
2394
2409
|
"content/config.ts"
|
|
2395
2410
|
], EXAMPLE_ENV = /^(\.env\.(example|sample|template|dist|local\.example|development\.example|production\.example)|example\.env|\.dev\.vars\.example)$/;
|
|
2396
|
-
function readText(
|
|
2411
|
+
function readText(file) {
|
|
2397
2412
|
try {
|
|
2398
|
-
return readFileSync2(
|
|
2413
|
+
return readFileSync2(file, "utf8");
|
|
2399
2414
|
} catch {
|
|
2400
2415
|
return null;
|
|
2401
2416
|
}
|
|
2402
2417
|
}
|
|
2403
|
-
function readJson(
|
|
2404
|
-
let text = readText(
|
|
2418
|
+
function readJson(file) {
|
|
2419
|
+
let text = readText(file);
|
|
2405
2420
|
if (text === null)
|
|
2406
2421
|
return null;
|
|
2407
2422
|
try {
|
|
@@ -2410,9 +2425,9 @@ function readJson(file2) {
|
|
|
2410
2425
|
return null;
|
|
2411
2426
|
}
|
|
2412
2427
|
}
|
|
2413
|
-
function isDir(
|
|
2428
|
+
function isDir(p) {
|
|
2414
2429
|
try {
|
|
2415
|
-
return statSync(
|
|
2430
|
+
return statSync(p).isDirectory();
|
|
2416
2431
|
} catch {
|
|
2417
2432
|
return !1;
|
|
2418
2433
|
}
|
|
@@ -2437,14 +2452,14 @@ function isPackage(dir) {
|
|
|
2437
2452
|
}
|
|
2438
2453
|
function workspaceGlobs(root) {
|
|
2439
2454
|
let globs = [], ws = readJson(path2.join(root, "package.json"))?.workspaces, list = Array.isArray(ws) ? ws : ws && typeof ws === "object" && Array.isArray(ws.packages) ? ws.packages : [];
|
|
2440
|
-
for (let
|
|
2441
|
-
if (typeof
|
|
2442
|
-
globs.push(
|
|
2455
|
+
for (let g of list)
|
|
2456
|
+
if (typeof g === "string")
|
|
2457
|
+
globs.push(g);
|
|
2443
2458
|
let pnpm = readText(path2.join(root, "pnpm-workspace.yaml"));
|
|
2444
2459
|
if (pnpm)
|
|
2445
|
-
for (let
|
|
2446
|
-
globs.push(
|
|
2447
|
-
return globs.filter((
|
|
2460
|
+
for (let m of pnpm.matchAll(/^\s*-\s*["']?([^"'\s#]+)["']?/gm))
|
|
2461
|
+
globs.push(m[1]);
|
|
2462
|
+
return globs.filter((g) => !g.startsWith("!"));
|
|
2448
2463
|
}
|
|
2449
2464
|
function expandGlob(root, glob) {
|
|
2450
2465
|
let clean = glob.replace(/\/\*\*$/, "/*").replace(/\/$/, "");
|
|
@@ -2453,24 +2468,24 @@ function expandGlob(root, glob) {
|
|
|
2453
2468
|
return isDir(dir) ? [dir] : [];
|
|
2454
2469
|
}
|
|
2455
2470
|
let [base] = clean.split("*"), parent = path2.join(root, base);
|
|
2456
|
-
return listDir(parent).filter((
|
|
2471
|
+
return listDir(parent).filter((e) => !SKIP_DIRS.has(e) && !e.startsWith(".")).map((e) => path2.join(parent, e)).filter(isDir);
|
|
2457
2472
|
}
|
|
2458
2473
|
function packageDirs(root) {
|
|
2459
2474
|
let dirs = /* @__PURE__ */ new Set([root]);
|
|
2460
|
-
for (let
|
|
2461
|
-
for (let
|
|
2462
|
-
if (isPackage(
|
|
2463
|
-
dirs.add(
|
|
2475
|
+
for (let g of workspaceGlobs(root))
|
|
2476
|
+
for (let d of expandGlob(root, g))
|
|
2477
|
+
if (isPackage(d))
|
|
2478
|
+
dirs.add(d);
|
|
2464
2479
|
for (let group of MONOREPO_DIRS) {
|
|
2465
|
-
let
|
|
2466
|
-
if (!isDir(
|
|
2480
|
+
let g = path2.join(root, group);
|
|
2481
|
+
if (!isDir(g))
|
|
2467
2482
|
continue;
|
|
2468
|
-
if (isPackage(
|
|
2469
|
-
dirs.add(
|
|
2470
|
-
for (let entry of listDir(
|
|
2471
|
-
let
|
|
2472
|
-
if (!SKIP_DIRS.has(entry) && isDir(
|
|
2473
|
-
dirs.add(
|
|
2483
|
+
if (isPackage(g))
|
|
2484
|
+
dirs.add(g);
|
|
2485
|
+
for (let entry of listDir(g)) {
|
|
2486
|
+
let d = path2.join(g, entry);
|
|
2487
|
+
if (!SKIP_DIRS.has(entry) && isDir(d) && isPackage(d))
|
|
2488
|
+
dirs.add(d);
|
|
2474
2489
|
}
|
|
2475
2490
|
}
|
|
2476
2491
|
return [...dirs].slice(0, MAX_PACKAGES);
|
|
@@ -2478,36 +2493,36 @@ function packageDirs(root) {
|
|
|
2478
2493
|
function pythonRequirements(text) {
|
|
2479
2494
|
let out = [];
|
|
2480
2495
|
for (let line of text.split(/\r?\n/)) {
|
|
2481
|
-
let
|
|
2482
|
-
if (
|
|
2483
|
-
out.push(
|
|
2496
|
+
let m = /^\s*([A-Za-z0-9][A-Za-z0-9._-]*)/.exec(line.replace(/#.*/, ""));
|
|
2497
|
+
if (m && !line.trim().startsWith("-"))
|
|
2498
|
+
out.push(m[1].toLowerCase());
|
|
2484
2499
|
}
|
|
2485
2500
|
return out;
|
|
2486
2501
|
}
|
|
2487
2502
|
function pythonProjectDeps(text) {
|
|
2488
2503
|
let out = /* @__PURE__ */ new Set;
|
|
2489
2504
|
for (let block of text.matchAll(/(?:^|\n)\s*dependencies\s*=\s*\[([\s\S]*?)\]/g))
|
|
2490
|
-
for (let
|
|
2491
|
-
out.add(
|
|
2505
|
+
for (let m of block[1].matchAll(/["']([A-Za-z0-9][A-Za-z0-9._-]*)/g))
|
|
2506
|
+
out.add(m[1].toLowerCase());
|
|
2492
2507
|
for (let table of text.matchAll(/\[(?:tool\.poetry\.(?:group\.[a-z]+\.)?dependencies|(?:dev-)?packages)\]([\s\S]*?)(?=\n\[|$)/g))
|
|
2493
|
-
for (let
|
|
2494
|
-
out.add(
|
|
2508
|
+
for (let m of table[1].matchAll(/^\s*([A-Za-z0-9][A-Za-z0-9._-]*)\s*=/gm))
|
|
2509
|
+
out.add(m[1].toLowerCase());
|
|
2495
2510
|
return out.delete("python"), [...out];
|
|
2496
2511
|
}
|
|
2497
2512
|
function gemfileDeps(text) {
|
|
2498
|
-
return [...text.matchAll(/^\s*gem\s+["']([^"']+)["']/gm)].map((
|
|
2513
|
+
return [...text.matchAll(/^\s*gem\s+["']([^"']+)["']/gm)].map((m) => m[1]);
|
|
2499
2514
|
}
|
|
2500
2515
|
function goModDeps(text) {
|
|
2501
2516
|
let out = [];
|
|
2502
|
-
for (let
|
|
2503
|
-
out.push(
|
|
2517
|
+
for (let m of text.matchAll(/^\s*(?:require\s+)?([a-z0-9.-]+\.[a-z]+\/[^\s]+)\s+v[0-9]/gm))
|
|
2518
|
+
out.push(m[1]);
|
|
2504
2519
|
return out;
|
|
2505
2520
|
}
|
|
2506
2521
|
function cargoDeps(text) {
|
|
2507
2522
|
let out = [];
|
|
2508
2523
|
for (let table of text.matchAll(/\[(?:dev-|build-)?dependencies\]([\s\S]*?)(?=\n\[|$)/g))
|
|
2509
|
-
for (let
|
|
2510
|
-
out.push(
|
|
2524
|
+
for (let m of table[1].matchAll(/^\s*([A-Za-z0-9_-]+)\s*=/gm))
|
|
2525
|
+
out.push(m[1]);
|
|
2511
2526
|
return out;
|
|
2512
2527
|
}
|
|
2513
2528
|
function manifestDeps(dir) {
|
|
@@ -2526,10 +2541,10 @@ function manifestDeps(dir) {
|
|
|
2526
2541
|
if (gem)
|
|
2527
2542
|
add("gem", gemfileDeps(gem));
|
|
2528
2543
|
let composer = readJson(path2.join(dir, "composer.json"));
|
|
2529
|
-
for (let
|
|
2530
|
-
let
|
|
2531
|
-
if (
|
|
2532
|
-
add("composer", Object.keys(
|
|
2544
|
+
for (let k of ["require", "require-dev"]) {
|
|
2545
|
+
let d = composer?.[k];
|
|
2546
|
+
if (d && typeof d === "object")
|
|
2547
|
+
add("composer", Object.keys(d));
|
|
2533
2548
|
}
|
|
2534
2549
|
let gomod = readText(path2.join(dir, "go.mod"));
|
|
2535
2550
|
if (gomod)
|
|
@@ -2543,7 +2558,7 @@ function siteFromWrangler(text) {
|
|
|
2543
2558
|
let first = [
|
|
2544
2559
|
...text.matchAll(/(?:pattern|route)["']?\s*[:=]\s*["']([^"'*/\s]+)/g),
|
|
2545
2560
|
...text.matchAll(/custom_domain["']?\s*[:=]\s*["']([^"'*/\s]+)/g)
|
|
2546
|
-
].map((
|
|
2561
|
+
].map((m) => m[1].toLowerCase()).filter((h) => h.includes(".") && !h.endsWith("workers.dev"))[0];
|
|
2547
2562
|
if (!first)
|
|
2548
2563
|
return;
|
|
2549
2564
|
return `https://${first.replace(/^(app|www|api|console)\./, "")}`;
|
|
@@ -2551,26 +2566,26 @@ function siteFromWrangler(text) {
|
|
|
2551
2566
|
var NOT_A_SITE = /(^|\.)(localhost|example\.(com|org)|your-?(site|domain)\.[a-z]+|vercel\.app|netlify\.app|pages\.dev|workers\.dev|github\.com|gitlab\.com|npmjs\.com)$/;
|
|
2552
2567
|
function publicSite(url) {
|
|
2553
2568
|
try {
|
|
2554
|
-
let
|
|
2555
|
-
if (!
|
|
2569
|
+
let u = new URL(url.startsWith("http") ? url : `https://${url}`);
|
|
2570
|
+
if (!u.hostname.includes(".") || NOT_A_SITE.test(u.hostname))
|
|
2556
2571
|
return;
|
|
2557
|
-
return `https://${
|
|
2572
|
+
return `https://${u.hostname.replace(/^www\./, "")}`;
|
|
2558
2573
|
} catch {
|
|
2559
2574
|
return;
|
|
2560
2575
|
}
|
|
2561
2576
|
}
|
|
2562
2577
|
function siteFromConfig(text) {
|
|
2563
|
-
let
|
|
2564
|
-
return
|
|
2578
|
+
let m = /\b(?:site|siteUrl|baseURL|baseUrl|url)\s*[:=]\s*["'`](https?:\/\/[^"'`\s]+)["'`]/.exec(text);
|
|
2579
|
+
return m ? publicSite(m[1]) : void 0;
|
|
2565
2580
|
}
|
|
2566
2581
|
function githubRepo(gitConfig) {
|
|
2567
2582
|
let remotes = [
|
|
2568
2583
|
...gitConfig.matchAll(/\[remote "([^"]+)"\][^[]*?url\s*=\s*(\S+)/g)
|
|
2569
|
-
].sort((a,
|
|
2584
|
+
].sort((a, b) => Number(b[1] === "origin") - Number(a[1] === "origin"));
|
|
2570
2585
|
for (let [, , url] of remotes) {
|
|
2571
|
-
let
|
|
2572
|
-
if (
|
|
2573
|
-
return `${
|
|
2586
|
+
let m = /github\.com[:/]([\w.-]+)\/([\w.-]+?)(?:\.git)?\/?$/.exec(url);
|
|
2587
|
+
if (m)
|
|
2588
|
+
return `${m[1]}/${m[2]}`;
|
|
2574
2589
|
}
|
|
2575
2590
|
return;
|
|
2576
2591
|
}
|
|
@@ -2585,21 +2600,21 @@ function readGitConfig(root) {
|
|
|
2585
2600
|
return readText(path2.join(gitDir, "config")) ?? readText(path2.join(gitDir, "..", "..", "config"));
|
|
2586
2601
|
}
|
|
2587
2602
|
function siteFromHtml(html) {
|
|
2588
|
-
let
|
|
2589
|
-
return
|
|
2603
|
+
let m = /<link[^>]+rel=["']canonical["'][^>]+href=["'](https?:\/\/[^"']+)/i.exec(html) ?? /<link[^>]+href=["'](https?:\/\/[^"']+)["'][^>]+rel=["']canonical["']/i.exec(html) ?? /<meta[^>]+property=["']og:url["'][^>]+content=["'](https?:\/\/[^"']+)/i.exec(html);
|
|
2604
|
+
return m ? publicSite(m[1]) : void 0;
|
|
2590
2605
|
}
|
|
2591
2606
|
function envKeyNames(text) {
|
|
2592
2607
|
let out = [];
|
|
2593
2608
|
for (let line of text.split(/\r?\n/)) {
|
|
2594
|
-
let
|
|
2595
|
-
if (
|
|
2596
|
-
out.push(
|
|
2609
|
+
let m = /^\s*(?:#\s*)?(?:export\s+)?([A-Z][A-Z0-9_]*)\s*=/.exec(line);
|
|
2610
|
+
if (m)
|
|
2611
|
+
out.push(m[1]);
|
|
2597
2612
|
}
|
|
2598
2613
|
return out;
|
|
2599
2614
|
}
|
|
2600
2615
|
var SITE_CONFIGS = /^(astro\.config\.\w+|next-sitemap\.config\.\w+|gatsby-config\.\w+|docusaurus\.config\.\w+|hugo\.toml|config\.toml|_config\.ya?ml|nuxt\.config\.\w+)$/;
|
|
2601
2616
|
function scanProject(root, onProgress) {
|
|
2602
|
-
let deps = /* @__PURE__ */ new Set, files = /* @__PURE__ */ new Set, envKeys = /* @__PURE__ */ new Set, name, siteUrl, dirs = packageDirs(root), relDir = (
|
|
2617
|
+
let deps = /* @__PURE__ */ new Set, files = /* @__PURE__ */ new Set, envKeys = /* @__PURE__ */ new Set, name, siteUrl, dirs = packageDirs(root), relDir = (d) => path2.relative(root, d).split(path2.sep).join("/") || ".";
|
|
2603
2618
|
onProgress?.({
|
|
2604
2619
|
label: `Found ${dirs.length} ${dirs.length === 1 ? "package" : "packages"}`,
|
|
2605
2620
|
detail: dirs.length > 1 ? dirs.map(relDir).join(", ") : void 0
|
|
@@ -2612,22 +2627,22 @@ function scanProject(root, onProgress) {
|
|
|
2612
2627
|
name = pkg.name;
|
|
2613
2628
|
if (!siteUrl && typeof pkg.homepage === "string")
|
|
2614
2629
|
siteUrl = publicSite(pkg.homepage);
|
|
2615
|
-
for (let
|
|
2616
|
-
let
|
|
2617
|
-
if (
|
|
2618
|
-
for (let n of Object.keys(
|
|
2630
|
+
for (let k of ["dependencies", "devDependencies"]) {
|
|
2631
|
+
let d = pkg[k];
|
|
2632
|
+
if (d && typeof d === "object")
|
|
2633
|
+
for (let n of Object.keys(d))
|
|
2619
2634
|
deps.add(n);
|
|
2620
2635
|
}
|
|
2621
2636
|
}
|
|
2622
|
-
for (let
|
|
2623
|
-
deps.add(
|
|
2637
|
+
for (let d of manifestDeps(dir))
|
|
2638
|
+
deps.add(d);
|
|
2624
2639
|
for (let entry of listDir(dir)) {
|
|
2625
2640
|
if (EXAMPLE_ENV.test(entry)) {
|
|
2626
2641
|
let text = readText(path2.join(dir, entry));
|
|
2627
2642
|
if (text) {
|
|
2628
2643
|
envFiles++;
|
|
2629
|
-
for (let
|
|
2630
|
-
envKeys.add(
|
|
2644
|
+
for (let k of envKeyNames(text))
|
|
2645
|
+
envKeys.add(k);
|
|
2631
2646
|
}
|
|
2632
2647
|
}
|
|
2633
2648
|
if (!MARKERS.some((re) => re.test(entry)))
|
|
@@ -2693,7 +2708,7 @@ var import_picocolors3 = __toESM(require_picocolors(), 1), MARK = [
|
|
|
2693
2708
|
function motionAllowed(argv = process.argv, env = process.env, isTTY = Boolean(process.stdout.isTTY)) {
|
|
2694
2709
|
return isTTY && !env.CI && !env.LOPEBASE_NO_MOTION && env.TERM !== "dumb" && !argv.includes("--no-motion");
|
|
2695
2710
|
}
|
|
2696
|
-
var sleep = (ms) => new Promise((
|
|
2711
|
+
var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
2697
2712
|
function logoLines(opts) {
|
|
2698
2713
|
let right = {
|
|
2699
2714
|
3: `${import_picocolors3.default.bold("Lope")}${import_picocolors3.default.dim("Base")}${opts.version ? import_picocolors3.default.dim(` v${opts.version}`) : ""}`,
|
|
@@ -2714,7 +2729,7 @@ ${lines.join(`
|
|
|
2714
2729
|
`);
|
|
2715
2730
|
return;
|
|
2716
2731
|
}
|
|
2717
|
-
let blank = MARK.map((
|
|
2732
|
+
let blank = MARK.map((r) => " ".repeat(r.length)), frame = (shown) => MARK.map((row, i) => shown.has(i) ? HORIZON.has(i) ? import_picocolors3.default.yellow(import_picocolors3.default.dim(row)) : import_picocolors3.default.yellow(row) : blank[i]), up = `\x1B[${MARK.length}A`, onInterrupt = () => {
|
|
2718
2733
|
write(`\x1B[?25h
|
|
2719
2734
|
`), process.exit(130);
|
|
2720
2735
|
};
|
|
@@ -2768,8 +2783,8 @@ function stackRows(detection, facts) {
|
|
|
2768
2783
|
rows.push(["Repo", facts.repo]);
|
|
2769
2784
|
if (!rows.length)
|
|
2770
2785
|
return [import_picocolors3.default.dim("Nothing recognized yet. Your agent will look closer.")];
|
|
2771
|
-
let width = Math.max(...rows.map(([
|
|
2772
|
-
return rows.map(([
|
|
2786
|
+
let width = Math.max(...rows.map(([k]) => k.length));
|
|
2787
|
+
return rows.map(([k, v]) => `${import_picocolors3.default.dim(k.padEnd(width))} ${v}`);
|
|
2773
2788
|
}
|
|
2774
2789
|
var PLAN = [
|
|
2775
2790
|
{
|
|
@@ -2861,12 +2876,12 @@ async function checkToken(auth) {
|
|
|
2861
2876
|
});
|
|
2862
2877
|
if (res.status === 401)
|
|
2863
2878
|
return { ok: !1, message: "That token is not valid or has expired." };
|
|
2864
|
-
let
|
|
2865
|
-
return { ok: !0, products: JSON.parse(
|
|
2866
|
-
} catch (
|
|
2879
|
+
let body = await res.json();
|
|
2880
|
+
return { ok: !0, products: JSON.parse(body.result?.content?.[0]?.text ?? "[]").length };
|
|
2881
|
+
} catch (e) {
|
|
2867
2882
|
return {
|
|
2868
2883
|
ok: !1,
|
|
2869
|
-
message: `Could not reach ${auth.url} (${String(
|
|
2884
|
+
message: `Could not reach ${auth.url} (${String(e)}).`
|
|
2870
2885
|
};
|
|
2871
2886
|
}
|
|
2872
2887
|
}
|
|
@@ -2894,8 +2909,8 @@ async function login() {
|
|
|
2894
2909
|
s.start("Waiting for you to approve in the browser");
|
|
2895
2910
|
let res = await pollDeviceLogin(url, device);
|
|
2896
2911
|
if (res.ok) {
|
|
2897
|
-
let
|
|
2898
|
-
return s.stop(`Connected to ${import_picocolors4.default.bold(res.url)}. Saved to ${import_picocolors4.default.dim(
|
|
2912
|
+
let file = saveAuth({ url: res.url, token: res.token });
|
|
2913
|
+
return s.stop(`Connected to ${import_picocolors4.default.bold(res.url)}. Saved to ${import_picocolors4.default.dim(file)}`), { url: res.url, token: res.token };
|
|
2899
2914
|
}
|
|
2900
2915
|
if (s.stop(import_picocolors4.default.red(res.message)), res.reason === "denied")
|
|
2901
2916
|
bail("Nothing was connected.");
|
|
@@ -2908,7 +2923,7 @@ async function askWorkspace() {
|
|
|
2908
2923
|
return workspaceUrl(guard(await he({
|
|
2909
2924
|
message: "Your LopeBase workspace (name or address)",
|
|
2910
2925
|
placeholder: "yourteam or https://yourteam.lopebase.com",
|
|
2911
|
-
validate: (
|
|
2926
|
+
validate: (v) => workspaceUrl(v ?? "") ? void 0 : "Type your workspace name, like yourteam, or its full address"
|
|
2912
2927
|
})));
|
|
2913
2928
|
}
|
|
2914
2929
|
async function pasteLogin(url) {
|
|
@@ -2922,29 +2937,29 @@ async function pasteLogin(url) {
|
|
|
2922
2937
|
for (;; ) {
|
|
2923
2938
|
let token = guard(await ge({
|
|
2924
2939
|
message: "Paste the agent token",
|
|
2925
|
-
validate: (
|
|
2940
|
+
validate: (v) => v?.startsWith("lb_agent_") ? void 0 : "Tokens start with lb_agent_"
|
|
2926
2941
|
})).trim(), s = Y2();
|
|
2927
2942
|
s.start("Checking the token");
|
|
2928
2943
|
let check = await checkToken({ url, token });
|
|
2929
2944
|
if (check.ok) {
|
|
2930
|
-
let
|
|
2931
|
-
return s.stop(`Signed in. ${check.products} product(s) in this workspace. Saved to ${import_picocolors4.default.dim(
|
|
2945
|
+
let file = saveAuth({ url, token });
|
|
2946
|
+
return s.stop(`Signed in. ${check.products} product(s) in this workspace. Saved to ${import_picocolors4.default.dim(file)}`), { url, token };
|
|
2932
2947
|
}
|
|
2933
2948
|
s.stop(import_picocolors4.default.red(check.message ?? "That did not work."));
|
|
2934
2949
|
}
|
|
2935
2950
|
}
|
|
2936
|
-
async function printDetection(
|
|
2937
|
-
Me(stackRows(
|
|
2951
|
+
async function printDetection(d, facts) {
|
|
2952
|
+
Me(stackRows(d, facts).join(`
|
|
2938
2953
|
`), "Your stack"), await pace(motion, 150);
|
|
2939
|
-
let found =
|
|
2954
|
+
let found = d.sources.filter((s) => s.status === "found");
|
|
2940
2955
|
if (found.length)
|
|
2941
2956
|
Me(found.map((s) => `${import_picocolors4.default.green("●")} ${import_picocolors4.default.bold(s.label)} ${import_picocolors4.default.dim(s.evidence.join(", "))}`).join(`
|
|
2942
2957
|
`), "Already in your code, ready to connect"), await pace(motion, 150);
|
|
2943
|
-
let possible =
|
|
2958
|
+
let possible = d.sources.filter((s) => s.status === "possible");
|
|
2944
2959
|
if (possible.length)
|
|
2945
2960
|
Me(possible.map((s) => `${import_picocolors4.default.yellow("?")} ${import_picocolors4.default.bold(s.label)} ${import_picocolors4.default.dim(`only ${s.evidence.join(", ")}`)}`).join(`
|
|
2946
2961
|
`), "Maybe in use, your agent will check"), await pace(motion, 150);
|
|
2947
|
-
for (let gap of
|
|
2962
|
+
for (let gap of d.gaps)
|
|
2948
2963
|
M2.info(import_picocolors4.default.dim(gap));
|
|
2949
2964
|
}
|
|
2950
2965
|
async function scanWithProgress() {
|
|
@@ -2986,13 +3001,13 @@ async function init() {
|
|
|
2986
3001
|
await printDetection(detection, facts), M2.step(stepTitle(2));
|
|
2987
3002
|
let auth = loadAuth();
|
|
2988
3003
|
if (auth) {
|
|
2989
|
-
let
|
|
2990
|
-
|
|
3004
|
+
let s = Y2();
|
|
3005
|
+
s.start(`Checking your connection to ${auth.url}`);
|
|
2991
3006
|
let check = await checkToken(auth);
|
|
2992
3007
|
if (check.ok)
|
|
2993
|
-
|
|
3008
|
+
s.stop(`Connected to ${import_picocolors4.default.bold(auth.url)}. ${check.products} ${check.products === 1 ? "product" : "products"} so far.`);
|
|
2994
3009
|
else
|
|
2995
|
-
|
|
3010
|
+
s.stop(import_picocolors4.default.yellow("Your saved connection no longer works.")), auth = null;
|
|
2996
3011
|
}
|
|
2997
3012
|
auth ??= await login(), M2.step(stepTitle(3));
|
|
2998
3013
|
let productName = guard(await he({
|
|
@@ -3047,7 +3062,7 @@ async function init() {
|
|
|
3047
3062
|
stdio: "inherit",
|
|
3048
3063
|
cwd
|
|
3049
3064
|
});
|
|
3050
|
-
child.on("error", (
|
|
3065
|
+
child.on("error", (e) => bail(`Could not start ${agent.label}: ${e.message}`)), child.on("exit", (code) => process.exit(code ?? 0));
|
|
3051
3066
|
}
|
|
3052
3067
|
async function main() {
|
|
3053
3068
|
switch (command) {
|
|
@@ -3079,7 +3094,7 @@ async function main() {
|
|
|
3079
3094
|
baseUrl: rest[1],
|
|
3080
3095
|
secret,
|
|
3081
3096
|
token: secret ? void 0 : token,
|
|
3082
|
-
log: (
|
|
3097
|
+
log: (l) => console.log(l.startsWith("FAIL") ? import_picocolors4.default.red(l) : import_picocolors4.default.green(l))
|
|
3083
3098
|
});
|
|
3084
3099
|
console.log(res.failed.length ? import_picocolors4.default.red(`${res.failed.length} failed, ${res.passed} passed`) : import_picocolors4.default.green(`All ${res.passed} checks passed. Ready to connect.`)), process.exit(res.failed.length ? 1 : 0);
|
|
3085
3100
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lopebase",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "Set up LopeBase from your project's folder: scan your stack, connect your workspace, and let your coding agent do the rest.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -57,5 +57,6 @@
|
|
|
57
57
|
"author": "LopeBase by Jackalope Digital <contact@jackalope.digital> (https://lopebase.com)",
|
|
58
58
|
"bugs": {
|
|
59
59
|
"email": "contact@jackalope.digital"
|
|
60
|
-
}
|
|
60
|
+
},
|
|
61
|
+
"mcpName": "io.github.Jackalope-Dev/lopebase"
|
|
61
62
|
}
|