lopebase 0.6.5 → 0.6.6

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.
Files changed (3) hide show
  1. package/README.md +29 -0
  2. package/dist/lopebase.js +566 -281
  3. package/package.json +2 -1
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 || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", { value: mod, enumerable: !0 }) : target;
17
+ let to = isNodeMode || !mod || !mod.__esModule ? __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 p = pathext[i].toLowerCase();
161
- if (p && path.substr(-p.length).toLowerCase() === p)
160
+ var p2 = pathext[i].toLowerCase();
161
+ if (p2 && path.substr(-p2.length).toLowerCase() === p2)
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(), 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;
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(), u2 = parseInt("100", 8), g2 = parseInt("010", 8), o2 = parseInt("001", 8), ug = u2 | g2, ret = mod & o2 || mod & g2 && gid === myGid || mod & u2 && 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), 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) => {
271
+ let ppRaw = pathEnv[i], pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw, pCmd = path.join(pathPart, cmd), p2 = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
272
+ resolve(subStep(p2, i, 0));
273
+ }), subStep = (p2, 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(p + ext, { pathExt: pathExtExe }, (er, is) => {
277
+ isexe(p2 + ext, { pathExt: pathExtExe }, (er, is) => {
278
278
  if (!er && is)
279
279
  if (opt.all)
280
- found.push(p + ext);
280
+ found.push(p2 + ext);
281
281
  else
282
- return resolve(p + ext);
283
- return resolve(subStep(p, i, ii + 1));
282
+ return resolve(p2 + ext);
283
+ return resolve(subStep(p2, 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), 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];
291
+ let ppRaw = pathEnv[i], pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw, pCmd = path.join(pathPart, cmd), p2 = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
292
+ for (let j2 = 0;j2 < pathExt.length; j2++) {
293
+ let cur = p2 + pathExt[j2];
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 (e) {} finally {
340
+ } catch (e2) {} 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 (e) {}
395
+ } catch (e2) {}
396
396
  return shebangCommand(buffer.toString());
397
397
  }
398
398
  module.exports = readShebang;
@@ -502,7 +502,7 @@ var require_cross_spawn = __commonJS(function(exports, module) {
502
502
 
503
503
  // bin/lopebase.ts
504
504
  import { spawn as spawn2 } from "node:child_process";
505
- import { readFileSync as readFileSync4 } from "node:fs";
505
+ import { readFileSync as readFileSync5 } from "node:fs";
506
506
 
507
507
  // ../../node_modules/.bun/@clack+prompts@0.11.0/node_modules/@clack/prompts/dist/index.mjs
508
508
  import { stripVTControlCharacters as S2 } from "node:util";
@@ -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: 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);
971
+ let { cursor: n, options: r2, 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)), l2 = 0;
972
+ n >= l2 + a - 3 ? l2 = Math.max(Math.min(n - a + 3, r2.length - a), 0) : n < l2 + 2 && (l2 = Math.max(n - 2, 0));
973
+ let $2 = a < r2.length && l2 > 0, g2 = a < r2.length && l2 + a < r2.length;
974
+ return r2.slice(l2, l2 + a).map((p2, v2, f) => {
975
+ let j2 = v2 === 0 && $2, E = v2 === f.length - 1 && g2;
976
+ return j2 || E ? import_picocolors2.default.dim("...") : i(p2, v2 + l2 === 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
- `, 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;
981
+ `, r2 = 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 : r2;
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
- `, r = this.valueWithCursor, i = this.masked;
1001
+ `, r2 = 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)} ${r}
1014
+ return `${n}${import_picocolors2.default.cyan(o)} ${r2}
1015
1015
  ${import_picocolors2.default.cyan(d2)}
1016
1016
  `;
1017
1017
  }
1018
1018
  } }).prompt(), ye = (t) => {
1019
- let n = t.active ?? "Yes", r = t.inactive ?? "No";
1020
- return new dD({ active: n, inactive: r, initialValue: t.initialValue ?? !0, render() {
1019
+ let n = t.active ?? "Yes", r2 = t.inactive ?? "No";
1020
+ return new dD({ active: n, inactive: r2, 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 : r;
1023
+ `, s = this.value ? n : r2;
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(r)}` : `${import_picocolors2.default.green(k2)} ${r}`}
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(r2)}` : `${import_picocolors2.default.green(k2)} ${r2}`}
1032
1032
  ${import_picocolors2.default.cyan(d2)}
1033
1033
  `;
1034
1034
  }
1035
1035
  } }).prompt();
1036
1036
  }, ve = (t) => {
1037
- let n = (r, i) => {
1038
- let s = r.label ?? String(r.value);
1037
+ let n = (r2, i) => {
1038
+ let s = r2.label ?? String(r2.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} ${r.hint ? import_picocolors2.default.dim(`(${r.hint})`) : ""}`;
1043
+ return `${import_picocolors2.default.green(k2)} ${s} ${r2.hint ? import_picocolors2.default.dim(`(${r2.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 r = `${import_picocolors2.default.gray(o)}
1051
+ let r2 = `${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 `${r}${import_picocolors2.default.gray(o)} ${n(this.options[this.cursor], "selected")}`;
1056
+ return `${r2}${import_picocolors2.default.gray(o)} ${n(this.options[this.cursor], "selected")}`;
1057
1057
  case "cancel":
1058
- return `${r}${import_picocolors2.default.gray(o)} ${n(this.options[this.cursor], "cancelled")}
1058
+ return `${r2}${import_picocolors2.default.gray(o)} ${n(this.options[this.cursor], "cancelled")}
1059
1059
  ${import_picocolors2.default.gray(o)}`;
1060
1060
  default:
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(`
1061
+ return `${r2}${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 = (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)}`;
1069
+ let n = (r2, i) => {
1070
+ let s = r2.label ?? String(r2.value);
1071
+ return i === "active" ? `${import_picocolors2.default.cyan(A2)} ${s} ${r2.hint ? import_picocolors2.default.dim(`(${r2.hint})`) : ""}` : i === "selected" ? `${import_picocolors2.default.green(T)} ${import_picocolors2.default.dim(s)} ${r2.hint ? import_picocolors2.default.dim(`(${r2.hint})`) : ""}` : i === "cancelled" ? `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(s))}` : i === "active-selected" ? `${import_picocolors2.default.green(T)} ${s} ${r2.hint ? import_picocolors2.default.dim(`(${r2.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(r) {
1074
- if (this.required && r.length === 0)
1073
+ return new SD({ options: t.options, initialValues: t.initialValues, required: t.required ?? !0, cursorAt: t.cursorAt, validate(r2) {
1074
+ if (this.required && r2.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 r = `${import_picocolors2.default.gray(o)}
1078
+ let r2 = `${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 `${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")}`;
1086
+ return `${r2}${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 `${r}${import_picocolors2.default.gray(o)} ${s.trim() ? `${s}
1089
+ return `${r2}${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 `${r + import_picocolors2.default.yellow(o)} ${G2({ options: this.options, cursor: this.cursor, maxItems: t.maxItems, style: i }).join(`
1096
+ return `${r2 + 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 `${r}${import_picocolors2.default.cyan(o)} ${G2({ options: this.options, cursor: this.cursor, maxItems: t.maxItems, style: i }).join(`
1102
+ return `${r2}${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 r = `
1110
+ let r2 = `
1111
1111
  ${t}
1112
1112
  `.split(`
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(`
1113
+ `), i = S2(n).length, s = Math.max(r2.reduce((a, l2) => {
1114
+ let $2 = S2(l2);
1115
+ return $2.length > a ? $2.length : a;
1116
+ }, 0), i) + 2, c = r2.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 r = [`${import_picocolors2.default.gray(o)}`];
1136
+ let r2 = [`${import_picocolors2.default.gray(o)}`];
1137
1137
  if (t) {
1138
1138
  let [i, ...s] = t.split(`
1139
1139
  `);
1140
- r.push(`${n} ${i}`, ...s.map((c) => `${import_picocolors2.default.gray(o)} ${c}`));
1140
+ r2.push(`${n} ${i}`, ...s.map((c) => `${import_picocolors2.default.gray(o)} ${c}`));
1141
1141
  }
1142
- process.stdout.write(`${r.join(`
1142
+ process.stdout.write(`${r2.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"], 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);
1159
+ let n = V2 ? ["◒", "◐", "◓", "◑"] : ["•", "o", "O", "0"], r2 = V2 ? 80 : 120, i = process.env.CI === "true", s, c, a = !1, l2 = "", $2, g2 = performance.now(), p2 = (m2) => {
1160
+ let h2 = m2 > 1 ? "Something went wrong" : "Canceled";
1161
+ a && N2(h2, m2);
1162
+ }, v2 = () => p2(2), f = () => p2(1), j2 = () => {
1163
+ process.on("uncaughtExceptionMonitor", v2), process.on("unhandledRejection", v2), process.on("SIGINT", f), process.on("SIGTERM", f), process.on("exit", p2);
1164
1164
  }, E = () => {
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)
1165
+ process.removeListener("uncaughtExceptionMonitor", v2), process.removeListener("unhandledRejection", v2), process.removeListener("SIGINT", f), process.removeListener("SIGTERM", f), process.removeListener("exit", p2);
1166
+ }, B2 = () => {
1167
+ if ($2 === void 0)
1168
1168
  return;
1169
1169
  i && process.stdout.write(`
1170
1170
  `);
1171
- let m = $.split(`
1171
+ let m2 = $2.split(`
1172
1172
  `);
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)}
1173
+ process.stdout.write(import_sisteransi2.cursor.move(-999, m2.length - 1)), process.stdout.write(import_sisteransi2.erase.down(m2.length));
1174
+ }, R2 = (m2) => m2.replace(/\.+$/, ""), O2 = (m2) => {
1175
+ let h2 = (performance.now() - m2) / 1000, w2 = Math.floor(h2 / 60), I2 = Math.floor(h2 % 60);
1176
+ return w2 > 0 ? `[${w2}m ${I2}s]` : `[${I2}s]`;
1177
+ }, H2 = (m2 = "") => {
1178
+ a = !0, s = fD(), l2 = R2(m2), g2 = performance.now(), process.stdout.write(`${import_picocolors2.default.gray(o)}
1179
1179
  `);
1180
- let h = 0, w = 0;
1181
- j(), c = setInterval(() => {
1182
- if (i && l === $)
1180
+ let h2 = 0, w2 = 0;
1181
+ j2(), c = setInterval(() => {
1182
+ if (i && l2 === $2)
1183
1183
  return;
1184
- B(), $ = l;
1185
- let I = import_picocolors2.default.magenta(n[h]);
1184
+ B2(), $2 = l2;
1185
+ let I2 = import_picocolors2.default.magenta(n[h2]);
1186
1186
  if (i)
1187
- process.stdout.write(`${I} ${l}...`);
1187
+ process.stdout.write(`${I2} ${l2}...`);
1188
1188
  else if (t === "timer")
1189
- process.stdout.write(`${I} ${l} ${O(g)}`);
1189
+ process.stdout.write(`${I2} ${l2} ${O2(g2)}`);
1190
1190
  else {
1191
- let z = ".".repeat(Math.floor(w)).slice(0, 3);
1192
- process.stdout.write(`${I} ${l}${z}`);
1191
+ let z2 = ".".repeat(Math.floor(w2)).slice(0, 3);
1192
+ process.stdout.write(`${I2} ${l2}${z2}`);
1193
1193
  }
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}
1194
+ h2 = h2 + 1 < n.length ? h2 + 1 : 0, w2 = w2 < n.length ? w2 + 0.125 : 0;
1195
+ }, r2);
1196
+ }, N2 = (m2 = "", h2 = 0) => {
1197
+ a = !1, clearInterval(c), B2();
1198
+ let w2 = h2 === 0 ? import_picocolors2.default.green(C) : h2 === 1 ? import_picocolors2.default.red(L2) : import_picocolors2.default.red(W2);
1199
+ l2 = R2(m2 ?? l2), t === "timer" ? process.stdout.write(`${w2} ${l2} ${O2(g2)}
1200
+ `) : process.stdout.write(`${w2} ${l2}
1201
1201
  `), E(), s();
1202
1202
  };
1203
- return { start: H, stop: N, message: (m = "") => {
1204
- l = R(m ?? l);
1203
+ return { start: H2, stop: N2, message: (m2 = "") => {
1204
+ l2 = R2(m2 ?? l2);
1205
1205
  } };
1206
1206
  };
1207
1207
 
@@ -1284,29 +1284,29 @@ var ADAPTER_VERSION = "0.4.2", ADAPTER_RELEASES = [
1284
1284
  steps: []
1285
1285
  }
1286
1286
  ];
1287
- function compareVersions(a, b) {
1288
- let parts = (v) => (v.match(/^\D*(\d+)\.(\d+)\.(\d+)/) ?? []).slice(1).map(Number), [x, y] = [parts(a), parts(b)];
1289
- if (x.length !== 3)
1290
- return y.length === 3 ? -1 : 0;
1291
- if (y.length !== 3)
1287
+ function compareVersions(a, b3) {
1288
+ let parts = (v2) => (v2.match(/^\D*(\d+)\.(\d+)\.(\d+)/) ?? []).slice(1).map(Number), [x2, y3] = [parts(a), parts(b3)];
1289
+ if (x2.length !== 3)
1290
+ return y3.length === 3 ? -1 : 0;
1291
+ if (y3.length !== 3)
1292
1292
  return 1;
1293
1293
  for (let i = 0;i < 3; i++)
1294
- if (x[i] !== y[i])
1295
- return x[i] < y[i] ? -1 : 1;
1294
+ if (x2[i] !== y3[i])
1295
+ return x2[i] < y3[i] ? -1 : 1;
1296
1296
  return 0;
1297
1297
  }
1298
1298
  function releasesSince(version) {
1299
- return ADAPTER_RELEASES.filter((r) => !version || compareVersions(r.version, version) > 0).reverse();
1299
+ return ADAPTER_RELEASES.filter((r2) => !version || compareVersions(r2.version, version) > 0).reverse();
1300
1300
  }
1301
1301
  function upgradePrompt(fromVersion) {
1302
- let todo = releasesSince(fromVersion), breaking = todo.flatMap((r) => r.breaking ?? []), steps = todo.flatMap((r) => r.steps);
1302
+ let todo = releasesSince(fromVersion), breaking = todo.flatMap((r2) => r2.breaking ?? []), steps = todo.flatMap((r2) => r2.steps);
1303
1303
  return [
1304
1304
  `Update this app's LopeBase adapter (@lopebase/adapter) from ${fromVersion ?? "its current version"} to 0.4.2.`,
1305
1305
  "",
1306
1306
  "1. Install it with this repo's package manager, for example `npm install @lopebase/adapter@latest`. A 0.x range like ^0.1.2 does not pick up 0.2 or later on its own.",
1307
1307
  ...breaking.length ? [
1308
1308
  "2. These changes would stop the adapter from starting; handle each one:",
1309
- ...breaking.map((b) => ` - ${b}`)
1309
+ ...breaking.map((b3) => ` - ${b3}`)
1310
1310
  ] : ["2. Nothing in this update stops an existing adapter from starting."],
1311
1311
  ...steps.length ? [
1312
1312
  "3. Adopt what is new, asking the human before each change:",
@@ -1322,7 +1322,7 @@ function upgradePrompt(fromVersion) {
1322
1322
  var SIGNATURE_HEADER = "lopebase-signature";
1323
1323
  var enc = /* @__PURE__ */ new TextEncoder;
1324
1324
  function hex(bytes) {
1325
- return [...new Uint8Array(bytes)].map((b) => b.toString(16).padStart(2, "0")).join("");
1325
+ return [...new Uint8Array(bytes)].map((b3) => b3.toString(16).padStart(2, "0")).join("");
1326
1326
  }
1327
1327
  async function sha256Hex(data) {
1328
1328
  return hex(await crypto.subtle.digest("SHA-256", data));
@@ -1333,8 +1333,8 @@ async function hmacHex(secret, message) {
1333
1333
  }
1334
1334
  function newSigningSecret() {
1335
1335
  let bytes = crypto.getRandomValues(new Uint8Array(32)), bin = "";
1336
- for (let b of bytes)
1337
- bin += String.fromCharCode(b);
1336
+ for (let b3 of bytes)
1337
+ bin += String.fromCharCode(b3);
1338
1338
  return "lbs_" + btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
1339
1339
  }
1340
1340
  function payload(t, method, pathAndQuery, bodyHash) {
@@ -1371,7 +1371,7 @@ var SENSITIVE_PARTS = /* @__PURE__ */ new Set([
1371
1371
  ]), SENSITIVE_JOINED = /apikey|privatekey|secretkey|accesskey|accountnumber|routingnumber|stripecustomer|paymentmethod|recoverycode/;
1372
1372
  function isSensitiveFieldName(name) {
1373
1373
  let parts = name.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase().split(/[^a-z0-9]+/).filter(Boolean);
1374
- if (parts.some((p) => SENSITIVE_PARTS.has(p)))
1374
+ if (parts.some((p2) => SENSITIVE_PARTS.has(p2)))
1375
1375
  return !0;
1376
1376
  return SENSITIVE_JOINED.test(parts.join(""));
1377
1377
  }
@@ -1390,12 +1390,12 @@ function conformanceChecks(opts) {
1390
1390
  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);
1391
1391
  async function signedHeaders(url, method, bodyText, timestamp) {
1392
1392
  if (opts.secret) {
1393
- let u = new URL(url);
1393
+ let u2 = new URL(url);
1394
1394
  return {
1395
1395
  [SIGNATURE_HEADER]: await signRequest({
1396
1396
  secret: opts.secret,
1397
1397
  method,
1398
- pathAndQuery: u.pathname + u.search,
1398
+ pathAndQuery: u2.pathname + u2.search,
1399
1399
  body: bodyText,
1400
1400
  timestamp
1401
1401
  })
@@ -1413,14 +1413,14 @@ function conformanceChecks(opts) {
1413
1413
  ...init?.headers
1414
1414
  }
1415
1415
  }));
1416
- }, resources = () => authed("/resources").then((r) => body(r)), checks = [
1416
+ }, resources = () => authed("/resources").then((r2) => body(r2)), checks = [
1417
1417
  {
1418
1418
  name: "GET /health returns { ok } without auth",
1419
1419
  async run() {
1420
1420
  let res = await send(new Request(`${base}/health`));
1421
1421
  assert.equal(res.status, 200);
1422
- let b = await body(res);
1423
- assert.equal(typeof b.ok, "boolean");
1422
+ let b3 = await body(res);
1423
+ assert.equal(typeof b3.ok, "boolean");
1424
1424
  }
1425
1425
  },
1426
1426
  {
@@ -1435,10 +1435,10 @@ function conformanceChecks(opts) {
1435
1435
  async run() {
1436
1436
  let res = await authed("/resources");
1437
1437
  assert.equal(res.status, 200);
1438
- let b = await body(res);
1439
- assert.ok(Array.isArray(b.resources));
1440
- for (let r of b.resources)
1441
- assert.ok(r.name && r.label && r.readCapability), assert.ok(Array.isArray(r.fields));
1438
+ let b3 = await body(res);
1439
+ assert.ok(Array.isArray(b3.resources));
1440
+ for (let r2 of b3.resources)
1441
+ assert.ok(r2.name && r2.label && r2.readCapability), assert.ok(Array.isArray(r2.fields));
1442
1442
  }
1443
1443
  },
1444
1444
  {
@@ -1446,9 +1446,9 @@ function conformanceChecks(opts) {
1446
1446
  async run() {
1447
1447
  let res = await authed("/actions");
1448
1448
  assert.equal(res.status, 200);
1449
- let b = await body(res);
1450
- assert.ok(Array.isArray(b.actions));
1451
- for (let a of b.actions)
1449
+ let b3 = await body(res);
1450
+ assert.ok(Array.isArray(b3.actions));
1451
+ for (let a of b3.actions)
1452
1452
  assert.ok(a.name && a.label && a.capability), assert.ok(Array.isArray(a.params));
1453
1453
  }
1454
1454
  },
@@ -1467,7 +1467,7 @@ function conformanceChecks(opts) {
1467
1467
  {
1468
1468
  name: "GET /resources/:name/:id returns a row or 404-null",
1469
1469
  async run() {
1470
- let cat = await resources(), meta = opts.sampleResource ? cat.resources.find((r) => r.name === opts.sampleResource) : cat.resources[0];
1470
+ let cat = await resources(), meta = opts.sampleResource ? cat.resources.find((r2) => r2.name === opts.sampleResource) : cat.resources[0];
1471
1471
  if (!meta)
1472
1472
  return;
1473
1473
  let first = (await body(await authed(`/resources/${meta.name}?limit=1`))).rows[0];
@@ -1482,8 +1482,8 @@ function conformanceChecks(opts) {
1482
1482
  async run() {
1483
1483
  let res = await authed("/audit");
1484
1484
  assert.equal(res.status, 200);
1485
- let b = await body(res);
1486
- assert.ok(Array.isArray(b.rows));
1485
+ let b3 = await body(res);
1486
+ assert.ok(Array.isArray(b3.rows));
1487
1487
  }
1488
1488
  },
1489
1489
  {
@@ -1497,24 +1497,24 @@ function conformanceChecks(opts) {
1497
1497
  name: "no field in the catalog looks like a secret unless marked safe",
1498
1498
  async run() {
1499
1499
  let cat = await resources();
1500
- for (let r of cat.resources)
1501
- for (let f of r.fields)
1502
- assert.ok(!isSensitiveFieldName(f.name) || f.sensitive === "allow", `${r.name}.${f.name} looks sensitive`);
1500
+ for (let r2 of cat.resources)
1501
+ for (let f of r2.fields)
1502
+ assert.ok(!isSensitiveFieldName(f.name) || f.sensitive === "allow", `${r2.name}.${f.name} looks sensitive`);
1503
1503
  }
1504
1504
  },
1505
1505
  {
1506
1506
  name: "rows contain only declared fields, and a page is at most 100",
1507
1507
  async run() {
1508
1508
  let cat = await resources();
1509
- for (let r of cat.resources) {
1510
- let res = await authed(`/resources/${r.name}?limit=1000`);
1509
+ for (let r2 of cat.resources) {
1510
+ let res = await authed(`/resources/${r2.name}?limit=1000`);
1511
1511
  assert.equal(res.status, 200);
1512
1512
  let page = await body(res);
1513
- assert.ok(page.rows.length <= 100, `${r.name} returned ${page.rows.length} rows`);
1514
- let declared = /* @__PURE__ */ new Set(["id", ...r.fields.map((f) => f.name)]);
1513
+ assert.ok(page.rows.length <= 100, `${r2.name} returned ${page.rows.length} rows`);
1514
+ let declared = /* @__PURE__ */ new Set(["id", ...r2.fields.map((f) => f.name)]);
1515
1515
  for (let row of page.rows)
1516
- for (let k of Object.keys(row))
1517
- assert.ok(declared.has(k), `${r.name} returned undeclared field ${k}`);
1516
+ for (let k3 of Object.keys(row))
1517
+ assert.ok(declared.has(k3), `${r2.name} returned undeclared field ${k3}`);
1518
1518
  }
1519
1519
  }
1520
1520
  },
@@ -1532,7 +1532,7 @@ function conformanceChecks(opts) {
1532
1532
  {
1533
1533
  name: "a mutation writes an audit row (PATCH round-trips into /audit)",
1534
1534
  async run() {
1535
- let writable = (await resources()).resources.find((r) => r.writeCapability && r.fields.some((f) => f.editable));
1535
+ let writable = (await resources()).resources.find((r2) => r2.writeCapability && r2.fields.some((f) => f.editable));
1536
1536
  if (!writable || remote)
1537
1537
  return;
1538
1538
  let row = (await body(await authed(`/resources/${writable.name}?limit=1`))).rows[0];
@@ -1568,8 +1568,8 @@ async function checkAdapter(input) {
1568
1568
  })
1569
1569
  } : { authorization: `Bearer ${input.token ?? ""}` };
1570
1570
  status = (await fetch(url, { headers })).status;
1571
- } catch (e) {
1572
- let error = `Could not reach ${base} (${e instanceof Error ? e.message : String(e)}).`;
1571
+ } catch (e2) {
1572
+ let error = `Could not reach ${base} (${e2 instanceof Error ? e2.message : String(e2)}).`;
1573
1573
  return log(`FAIL ${error}`), { passed, failed: [{ name: "reachable", error }] };
1574
1574
  }
1575
1575
  if (status === 401) {
@@ -1587,9 +1587,9 @@ async function checkAdapter(input) {
1587
1587
  }))
1588
1588
  try {
1589
1589
  await c.run(), passed++, log(`pass ${c.name}`);
1590
- } catch (e) {
1591
- let error = e instanceof Error ? e.message.split(`
1592
- `)[0] : String(e);
1590
+ } catch (e2) {
1591
+ let error = e2 instanceof Error ? e2.message.split(`
1592
+ `)[0] : String(e2);
1593
1593
  failed.push({ name: c.name, error }), log(`FAIL ${c.name}: ${error}`);
1594
1594
  }
1595
1595
  return { passed, failed };
@@ -1603,7 +1603,7 @@ var AGENTS = [
1603
1603
  id: "claude",
1604
1604
  label: "Claude Code",
1605
1605
  bin: "claude",
1606
- args: (p) => [p],
1606
+ args: (p2) => [p2],
1607
1607
  mcpAdd: (argv) => [
1608
1608
  "mcp",
1609
1609
  "add",
@@ -1618,27 +1618,27 @@ var AGENTS = [
1618
1618
  id: "codex",
1619
1619
  label: "Codex",
1620
1620
  bin: "codex",
1621
- args: (p) => [p],
1621
+ args: (p2) => [p2],
1622
1622
  mcpAdd: (argv) => ["mcp", "add", "lopebase", "--", ...argv]
1623
1623
  },
1624
1624
  {
1625
1625
  id: "gemini",
1626
1626
  label: "Gemini CLI",
1627
1627
  bin: "gemini",
1628
- args: (p) => ["-i", p],
1628
+ args: (p2) => ["-i", p2],
1629
1629
  mcpAdd: (argv) => ["mcp", "add", "lopebase", ...argv]
1630
1630
  },
1631
1631
  {
1632
1632
  id: "opencode",
1633
1633
  label: "opencode",
1634
1634
  bin: "opencode",
1635
- args: (p) => ["--prompt", p]
1635
+ args: (p2) => ["--prompt", p2]
1636
1636
  },
1637
1637
  {
1638
1638
  id: "cursor-agent",
1639
1639
  label: "Cursor Agent",
1640
1640
  bin: "cursor-agent",
1641
- args: (p) => [p]
1641
+ args: (p2) => [p2]
1642
1642
  }
1643
1643
  ];
1644
1644
  function isInstalled(bin) {
@@ -1665,29 +1665,287 @@ function installedAgents() {
1665
1665
  return AGENTS.filter((a) => isInstalled(a.bin));
1666
1666
  }
1667
1667
 
1668
+ // src/blog-check.ts
1669
+ import { readdirSync, readFileSync, statSync } from "node:fs";
1670
+ import { join } from "node:path";
1671
+ // ../lopebase-blog/src/contract.ts
1672
+ var shared = {
1673
+ title: { kind: "string", required: !0, role: "title" },
1674
+ description: { kind: "string", required: !0, role: "description" },
1675
+ author: { kind: "string", role: "author" },
1676
+ tags: { kind: "tags", role: "tags" }
1677
+ }, markdownKeys = {
1678
+ ...shared,
1679
+ date: { kind: "date", required: !0, role: "date" },
1680
+ slug: { kind: "string", required: !0, role: "slug" },
1681
+ updated: { kind: "date", role: "updated" },
1682
+ image: { kind: "url", role: "image" },
1683
+ image_alt: { kind: "string", role: "imageAlt" },
1684
+ faq: { kind: "faq", role: "faq" }
1685
+ }, BLOG_PRESETS = {
1686
+ markdown: {
1687
+ dir: "content/blog",
1688
+ ext: ".md",
1689
+ keys: markdownKeys,
1690
+ slugKey: "slug"
1691
+ },
1692
+ "next-mdx": {
1693
+ dir: "content/blog",
1694
+ ext: ".mdx",
1695
+ keys: markdownKeys,
1696
+ slugKey: "slug"
1697
+ },
1698
+ astro: {
1699
+ dir: "src/content/blog",
1700
+ ext: ".md",
1701
+ keys: {
1702
+ ...shared,
1703
+ pubDate: { kind: "date", required: !0, role: "date" },
1704
+ updatedDate: { kind: "date", role: "updated" },
1705
+ heroImage: { kind: "url", role: "image" }
1706
+ }
1707
+ },
1708
+ hugo: {
1709
+ dir: "content/posts",
1710
+ ext: ".md",
1711
+ keys: {
1712
+ ...shared,
1713
+ date: { kind: "datetime", required: !0, role: "date" },
1714
+ slug: { kind: "string", required: !0, role: "slug" },
1715
+ lastmod: { kind: "datetime", role: "updated" },
1716
+ images: { kind: "urls", role: "images" }
1717
+ },
1718
+ slugKey: "slug"
1719
+ },
1720
+ jekyll: {
1721
+ dir: "_posts",
1722
+ ext: ".md",
1723
+ keys: {
1724
+ layout: { kind: "layout", required: !0 },
1725
+ ...shared,
1726
+ date: { kind: "date", required: !0, role: "date" },
1727
+ last_modified_at: { kind: "date", role: "updated" },
1728
+ image: { kind: "url", role: "image" }
1729
+ },
1730
+ datedFileKey: "date"
1731
+ }
1732
+ }, isBlogFormat = (v2) => Object.hasOwn(BLOG_PRESETS, v2), SLUG = /^[a-z0-9]+(?:-[a-z0-9]+)*$/, DATE = /^(\d{4})-(\d{2})-(\d{2})$/, DATETIME = /^(\d{4})-(\d{2})-(\d{2})T([01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/, JEKYLL_FILE = /^(\d{4}-\d{2}-\d{2})-(.+)$/, HTML_TAG = /<\/?[A-Za-z][A-Za-z0-9-]*(?:\s[^<>]*)?\/?>|<!--/;
1733
+ function realDate(y3, m2, d3) {
1734
+ let date = new Date(Date.UTC(+y3, +m2 - 1, +d3));
1735
+ return date.getUTCFullYear() === +y3 && date.getUTCMonth() === +m2 - 1 && date.getUTCDate() === +d3;
1736
+ }
1737
+ function isUrl(v2) {
1738
+ if (typeof v2 !== "string")
1739
+ return !1;
1740
+ try {
1741
+ let u2 = new URL(v2);
1742
+ return u2.protocol === "https:" || u2.protocol === "http:";
1743
+ } catch {
1744
+ return !1;
1745
+ }
1746
+ }
1747
+ var filled = (v2) => typeof v2 === "string" && v2.trim() !== "";
1748
+ function json(raw) {
1749
+ try {
1750
+ return { ok: !0, value: JSON.parse(raw) };
1751
+ } catch {
1752
+ return { ok: !1 };
1753
+ }
1754
+ }
1755
+ function checkValue(key, kind, raw) {
1756
+ switch (kind) {
1757
+ case "layout":
1758
+ return raw === "post" ? void 0 : `${key} must be post`;
1759
+ case "date": {
1760
+ let m2 = DATE.exec(raw);
1761
+ return m2 && realDate(m2[1], m2[2], m2[3]) ? void 0 : `${key} must be a date like 2026-11-05`;
1762
+ }
1763
+ case "datetime": {
1764
+ let m2 = DATETIME.exec(raw);
1765
+ return m2 && realDate(m2[1], m2[2], m2[3]) ? void 0 : `${key} must be a date and time like 2026-11-05T15:00:00Z`;
1766
+ }
1767
+ case "string": {
1768
+ let v2 = json(raw);
1769
+ if (!v2.ok || typeof v2.value !== "string")
1770
+ return `${key} must be a quoted string`;
1771
+ return v2.value.trim() ? void 0 : `${key} is empty`;
1772
+ }
1773
+ case "url": {
1774
+ let v2 = json(raw);
1775
+ return v2.ok && isUrl(v2.value) ? void 0 : `${key} must be a quoted http or https address`;
1776
+ }
1777
+ case "tags": {
1778
+ let v2 = json(raw);
1779
+ return v2.ok && Array.isArray(v2.value) && v2.value.every((t) => typeof t === "string") ? void 0 : `${key} must be a list of quoted strings, like ["seo"]`;
1780
+ }
1781
+ case "urls": {
1782
+ let v2 = json(raw);
1783
+ return v2.ok && Array.isArray(v2.value) && v2.value.every(isUrl) ? void 0 : `${key} must be a list of quoted http or https addresses`;
1784
+ }
1785
+ case "faq": {
1786
+ let v2 = json(raw);
1787
+ return v2.ok && Array.isArray(v2.value) && v2.value.every((f) => f !== null && typeof f === "object" && filled(f.q) && filled(f.a)) ? void 0 : `${key} must be one line of JSON like [{"q": "A question?", "a": "An answer."}]`;
1788
+ }
1789
+ }
1790
+ }
1791
+ function proseOnly(body2) {
1792
+ let out = [], fence;
1793
+ for (let line of body2.split(`
1794
+ `)) {
1795
+ let open = /^\s{0,3}(`{3,}|~{3,})/.exec(line);
1796
+ if (fence) {
1797
+ if (open && open[1][0] === fence[0] && open[1].length >= fence.length)
1798
+ fence = void 0;
1799
+ continue;
1800
+ }
1801
+ if (open) {
1802
+ fence = open[1];
1803
+ continue;
1804
+ }
1805
+ out.push(line.replace(/(`+)[^`]*?\1/g, ""));
1806
+ }
1807
+ return out;
1808
+ }
1809
+ function inspectPost(fileName, text, format) {
1810
+ let preset = BLOG_PRESETS[format], problems = [], base = fileName.endsWith(preset.ext) ? fileName.slice(0, fileName.length - preset.ext.length) : fileName.replace(/\.[^.]*$/, ""), fileSlug = base, fileDate;
1811
+ if (preset.datedFileKey) {
1812
+ let m2 = JEKYLL_FILE.exec(base);
1813
+ if (m2)
1814
+ fileDate = m2[1], fileSlug = m2[2];
1815
+ else
1816
+ problems.push("file name must look like YYYY-MM-DD-<slug>.md");
1817
+ }
1818
+ if (!SLUG.test(fileSlug))
1819
+ problems.push(`file name slug "${fileSlug}" must be lowercase words joined by hyphens`);
1820
+ let lines = text.replace(/^/, "").split(/\r?\n/), end = lines[0] === "---" ? lines.indexOf("---", 1) : -1;
1821
+ if (end < 0)
1822
+ return problems.push("front matter must open and close with --- lines at the top"), { slug: fileSlug, problems };
1823
+ let raws = /* @__PURE__ */ new Map;
1824
+ for (let line of lines.slice(1, end)) {
1825
+ if (!line.trim())
1826
+ continue;
1827
+ let m2 = /^([A-Za-z_][A-Za-z0-9_]*):\s*(.*)$/.exec(line);
1828
+ if (!m2) {
1829
+ problems.push(`front matter line is not "key: value": ${line.trim()}`);
1830
+ continue;
1831
+ }
1832
+ if (raws.has(m2[1]))
1833
+ problems.push(`${m2[1]} appears more than once`);
1834
+ raws.set(m2[1], m2[2].trim());
1835
+ }
1836
+ let values = {};
1837
+ for (let [key, spec] of Object.entries(preset.keys)) {
1838
+ let raw = raws.get(key);
1839
+ if (raw === void 0 || raw === "") {
1840
+ if (spec.required)
1841
+ problems.push(`missing ${key}`);
1842
+ continue;
1843
+ }
1844
+ let problem = checkValue(key, spec.kind, raw);
1845
+ if (problem)
1846
+ problems.push(problem);
1847
+ else if (spec.role)
1848
+ values[spec.role] = spec.kind === "date" || spec.kind === "datetime" ? raw : JSON.parse(raw);
1849
+ }
1850
+ let slug = fileSlug;
1851
+ if (preset.slugKey) {
1852
+ let v2 = json(raws.get(preset.slugKey) ?? "");
1853
+ if (v2.ok && typeof v2.value === "string" && v2.value) {
1854
+ if (!SLUG.test(v2.value))
1855
+ problems.push(`${preset.slugKey} "${v2.value}" must be lowercase words joined by hyphens`);
1856
+ else if (v2.value !== fileSlug)
1857
+ problems.push(`${preset.slugKey} "${v2.value}" does not match the file name "${fileSlug}"`);
1858
+ slug = v2.value;
1859
+ }
1860
+ }
1861
+ if (preset.datedFileKey && fileDate) {
1862
+ let date = raws.get(preset.datedFileKey);
1863
+ if (date && DATE.test(date) && date !== fileDate)
1864
+ problems.push(`${preset.datedFileKey} ${date} does not match the file name date ${fileDate}`);
1865
+ }
1866
+ let body2 = lines.slice(end + 1).join(`
1867
+ `), fields = { slug, values, body: body2 };
1868
+ if (!body2.trim())
1869
+ return problems.push("the post has no body"), { slug, problems, fields };
1870
+ let prose = proseOnly(body2), first = body2.split(`
1871
+ `).find((l2) => l2.trim());
1872
+ if (first && /^\s{0,3}#(?:\s|$)/.test(first))
1873
+ problems.push("the body starts with a # heading; the title comes from front matter");
1874
+ if (!prose.some((l2) => /^\s{0,3}## /.test(l2)))
1875
+ problems.push("the body needs at least one ## heading");
1876
+ if (prose.some((l2) => HTML_TAG.test(l2)))
1877
+ problems.push("the body has raw HTML outside code; use Markdown instead");
1878
+ return { slug, problems, fields };
1879
+ }
1880
+ function checkPost(fileName, text, format) {
1881
+ let { slug, problems } = inspectPost(fileName, text, format);
1882
+ return { slug, problems };
1883
+ }
1884
+ // src/blog-check.ts
1885
+ function checkBlog(opts) {
1886
+ let format = opts.format ?? "markdown", preset = BLOG_PRESETS[format], dir = (opts.dir ?? preset.dir).replace(/\\/g, "/").replace(/\/+$/, ""), abs = join(opts.cwd, dir), problems = [], names;
1887
+ try {
1888
+ if (!statSync(abs).isDirectory())
1889
+ return {
1890
+ dir,
1891
+ posts: 0,
1892
+ problems: [{ file: dir, problem: "is not a folder" }]
1893
+ };
1894
+ names = readdirSync(abs, { withFileTypes: !0 }).filter((e2) => e2.isFile() && e2.name.endsWith(preset.ext)).map((e2) => e2.name).sort();
1895
+ } catch {
1896
+ return {
1897
+ dir,
1898
+ posts: 0,
1899
+ problems: opts.allowEmpty ? [] : [{ file: dir, problem: "folder not found (pass --allow-empty)" }]
1900
+ };
1901
+ }
1902
+ if (!names.length && !opts.allowEmpty)
1903
+ problems.push({
1904
+ file: dir,
1905
+ problem: `no ${preset.ext} posts found (pass --allow-empty)`
1906
+ });
1907
+ let seen = /* @__PURE__ */ new Map;
1908
+ for (let name of names) {
1909
+ let file = `${dir}/${name}`, res = checkPost(name, readFileSync(join(abs, name), "utf8"), format);
1910
+ for (let problem of res.problems)
1911
+ problems.push({ file, problem });
1912
+ if (res.slug) {
1913
+ let other = seen.get(res.slug);
1914
+ if (other)
1915
+ problems.push({
1916
+ file,
1917
+ problem: `slug "${res.slug}" is also used by ${other}`
1918
+ });
1919
+ else
1920
+ seen.set(res.slug, file);
1921
+ }
1922
+ }
1923
+ return { dir, posts: names.length, problems };
1924
+ }
1925
+
1668
1926
  // src/config.ts
1669
1927
  import {
1670
1928
  chmodSync,
1671
1929
  existsSync,
1672
1930
  mkdirSync,
1673
- readFileSync,
1931
+ readFileSync as readFileSync2,
1674
1932
  writeFileSync
1675
1933
  } from "node:fs";
1676
1934
  import os from "node:os";
1677
1935
  import path from "node:path";
1678
1936
  var DEFAULT_URL = "https://app.lopebase.com";
1679
1937
  function workspaceUrl(input) {
1680
- let v = input.trim().replace(/\/+$/, "");
1681
- if (!v)
1938
+ let v2 = input.trim().replace(/\/+$/, "");
1939
+ if (!v2)
1682
1940
  return null;
1683
- if (/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i.test(v))
1684
- return `https://${v.toLowerCase()}.lopebase.com`;
1685
- let withScheme = /^https?:\/\//i.test(v) ? v : `https://${v}`;
1941
+ if (/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i.test(v2))
1942
+ return `https://${v2.toLowerCase()}.lopebase.com`;
1943
+ let withScheme = /^https?:\/\//i.test(v2) ? v2 : `https://${v2}`;
1686
1944
  try {
1687
- let u = new URL(withScheme);
1688
- if (!u.hostname.includes(".") && u.hostname !== "localhost")
1945
+ let u2 = new URL(withScheme);
1946
+ if (!u2.hostname.includes(".") && u2.hostname !== "localhost")
1689
1947
  return null;
1690
- return `${u.origin}${u.pathname.replace(/\/+$/, "")}`;
1948
+ return `${u2.origin}${u2.pathname.replace(/\/+$/, "")}`;
1691
1949
  } catch {
1692
1950
  return null;
1693
1951
  }
@@ -1716,7 +1974,7 @@ function loadAuth() {
1716
1974
  if (!existsSync(authFile()))
1717
1975
  return null;
1718
1976
  try {
1719
- let a = JSON.parse(readFileSync(authFile(), "utf8"));
1977
+ let a = JSON.parse(readFileSync2(authFile(), "utf8"));
1720
1978
  if (!a.token)
1721
1979
  return null;
1722
1980
  return { url: envUrl || a.url || DEFAULT_URL, token: a.token };
@@ -1737,7 +1995,7 @@ var APP_SIDE_ENV = /^(NEXT_PUBLIC_|PUBLIC_|VITE_|NUXT_PUBLIC_|EXPO_PUBLIC_|REACT
1737
1995
  function evidenceFor(facts, rule) {
1738
1996
  let out = [], weak = [];
1739
1997
  for (let re of rule.deps ?? []) {
1740
- let hit = facts.dependencies.find((d) => re.test(d));
1998
+ let hit = facts.dependencies.find((d3) => re.test(d3));
1741
1999
  if (hit)
1742
2000
  out.push(`uses ${hit.replace(/^(py|gem|composer|go|cargo):/, "")}`);
1743
2001
  }
@@ -1747,7 +2005,7 @@ function evidenceFor(facts, rule) {
1747
2005
  out.push(`has ${hit.replace(/#.*$/, "")}`);
1748
2006
  }
1749
2007
  for (let re of rule.env ?? []) {
1750
- let hit = facts.envKeys.find((k) => re.test(k));
2008
+ let hit = facts.envKeys.find((k3) => re.test(k3));
1751
2009
  if (hit)
1752
2010
  (APP_SIDE_ENV.test(hit) ? out : weak).push(`env ${hit}`);
1753
2011
  }
@@ -2329,11 +2587,11 @@ var QUEUES = [
2329
2587
  [/^py:celery$/, "Job queue (Celery)"],
2330
2588
  [/^gem:sidekiq$/, "Job queue (Sidekiq)"]
2331
2589
  ], NOT_A_SERVICE = /* @__PURE__ */ new Set(["Prisma", "Drizzle"]);
2332
- function watchList(d, facts) {
2590
+ function watchList(d3, facts) {
2333
2591
  let slug = (s) => s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, ""), out = [];
2334
- if (d.sources.some((s) => s.source === "uptime") || facts.siteUrl)
2592
+ if (d3.sources.some((s) => s.source === "uptime") || facts.siteUrl)
2335
2593
  out.push({ id: "site", label: facts.siteUrl ?? "Website", how: "address" });
2336
- for (let s of d.stack)
2594
+ for (let s of d3.stack)
2337
2595
  if (s.kind === "database" && !NOT_A_SERVICE.has(s.name))
2338
2596
  out.push({ id: slug(s.name), label: s.name, how: "service" });
2339
2597
  for (let [re, label] of QUEUES)
@@ -2343,7 +2601,7 @@ function watchList(d, facts) {
2343
2601
  label,
2344
2602
  how: "service"
2345
2603
  });
2346
- let email = d.stack.find((s) => s.kind === "email" && s.name !== "Nodemailer");
2604
+ let email = d3.stack.find((s) => s.kind === "email" && s.name !== "Nodemailer");
2347
2605
  if (email)
2348
2606
  out.push({
2349
2607
  id: "email",
@@ -2351,7 +2609,7 @@ function watchList(d, facts) {
2351
2609
  how: "service"
2352
2610
  });
2353
2611
  let seen = /* @__PURE__ */ new Set;
2354
- return out.filter((w) => !seen.has(w.id) && seen.add(w.id));
2612
+ return out.filter((w2) => !seen.has(w2.id) && seen.add(w2.id));
2355
2613
  }
2356
2614
 
2357
2615
  // src/device-login.ts
@@ -2368,27 +2626,27 @@ async function startDeviceLogin(url, opts = {}) {
2368
2626
  });
2369
2627
  if (!res.ok)
2370
2628
  return null;
2371
- let b = await res.json();
2372
- if (typeof b.device_code !== "string" || typeof b.user_code !== "string")
2629
+ let b3 = await res.json();
2630
+ if (typeof b3.device_code !== "string" || typeof b3.user_code !== "string")
2373
2631
  return null;
2374
2632
  return {
2375
- deviceCode: b.device_code,
2376
- userCode: b.user_code,
2377
- verifyUrl: String(b.verification_uri_complete ?? b.verification_uri),
2378
- interval: Number(b.interval) || 5,
2379
- expiresIn: Number(b.expires_in) || 600
2633
+ deviceCode: b3.device_code,
2634
+ userCode: b3.user_code,
2635
+ verifyUrl: String(b3.verification_uri_complete ?? b3.verification_uri),
2636
+ interval: Number(b3.interval) || 5,
2637
+ expiresIn: Number(b3.expires_in) || 600
2380
2638
  };
2381
2639
  } catch {
2382
2640
  return null;
2383
2641
  }
2384
2642
  }
2385
2643
  async function pollDeviceLogin(url, start, opts = {}) {
2386
- let f = opts.fetchImpl ?? fetch, sleep = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms))), interval = start.interval, deadline = Date.now() + start.expiresIn * 1000;
2644
+ let f = opts.fetchImpl ?? fetch, sleep = opts.sleep ?? ((ms) => new Promise((r2) => setTimeout(r2, ms))), interval = start.interval, deadline = Date.now() + start.expiresIn * 1000;
2387
2645
  while (Date.now() < deadline) {
2388
2646
  await sleep(interval * 1000);
2389
- let body;
2647
+ let body2;
2390
2648
  try {
2391
- body = await (await f(`${url}/api/oauth/token`, {
2649
+ body2 = await (await f(`${url}/api/oauth/token`, {
2392
2650
  method: "POST",
2393
2651
  headers: { "content-type": "application/x-www-form-urlencoded" },
2394
2652
  body: new URLSearchParams({
@@ -2399,14 +2657,14 @@ async function pollDeviceLogin(url, start, opts = {}) {
2399
2657
  } catch {
2400
2658
  continue;
2401
2659
  }
2402
- if (typeof body.access_token === "string")
2660
+ if (typeof body2.access_token === "string")
2403
2661
  return {
2404
2662
  ok: !0,
2405
- token: body.access_token,
2406
- url: typeof body.workspace_url === "string" ? body.workspace_url : url,
2407
- scope: String(body.scope ?? "")
2663
+ token: body2.access_token,
2664
+ url: typeof body2.workspace_url === "string" ? body2.workspace_url : url,
2665
+ scope: String(body2.scope ?? "")
2408
2666
  };
2409
- switch (body.error) {
2667
+ switch (body2.error) {
2410
2668
  case "authorization_pending":
2411
2669
  continue;
2412
2670
  case "slow_down":
@@ -2428,7 +2686,7 @@ async function pollDeviceLogin(url, start, opts = {}) {
2428
2686
  return {
2429
2687
  ok: !1,
2430
2688
  reason: "error",
2431
- message: String(body.error_description ?? body.error ?? "Sign-in failed.")
2689
+ message: String(body2.error_description ?? body2.error ?? "Sign-in failed.")
2432
2690
  };
2433
2691
  }
2434
2692
  }
@@ -2497,7 +2755,7 @@ async function runMcpProxy(auth, fetchImpl = fetch) {
2497
2755
  }
2498
2756
  process.stdout.write(`${text}
2499
2757
  `);
2500
- } catch (e) {
2758
+ } catch (e2) {
2501
2759
  if (id === null)
2502
2760
  return;
2503
2761
  write({
@@ -2505,7 +2763,7 @@ async function runMcpProxy(auth, fetchImpl = fetch) {
2505
2763
  id,
2506
2764
  error: {
2507
2765
  code: -32000,
2508
- message: `Could not reach LopeBase at ${endpoint}: ${String(e)}`
2766
+ message: `Could not reach LopeBase at ${endpoint}: ${String(e2)}`
2509
2767
  }
2510
2768
  });
2511
2769
  }
@@ -2523,7 +2781,7 @@ function onboardingPrompt(input) {
2523
2781
  `- Stack: ${stack}`,
2524
2782
  `- Already in use: ${found.map((s) => s.label).join(", ") || "none of the sources LopeBase reads"}`,
2525
2783
  `- The human wants connected: ${chosen.join(", ") || "whatever get_onboarding_status recommends"}`,
2526
- `- Worth watching for uptime: ${(input.watch ?? []).map((w) => `${w.label} (${w.how === "address" ? "uptime check on its address" : "adapter health service"})`).join(", ") || "the site, if it has one"}`,
2784
+ `- Worth watching for uptime: ${(input.watch ?? []).map((w2) => `${w2.label} (${w2.how === "address" ? "uptime check on its address" : "adapter health service"})`).join(", ") || "the site, if it has one"}`,
2527
2785
  `- LopeBase pageviews: ${input.pageviews ? "yes, the human wants them" : "not chosen; offer once, do not push"}`,
2528
2786
  "",
2529
2787
  "How to work:",
@@ -2541,7 +2799,7 @@ function onboardingPrompt(input) {
2541
2799
  }
2542
2800
 
2543
2801
  // src/scan.ts
2544
- import { existsSync as existsSync2, readdirSync, readFileSync as readFileSync2, statSync } from "node:fs";
2802
+ import { existsSync as existsSync2, readdirSync as readdirSync2, readFileSync as readFileSync3, statSync as statSync2 } from "node:fs";
2545
2803
  import path2 from "node:path";
2546
2804
  var MONOREPO_DIRS = ["apps", "packages", "services", "sites", "web", "site"], SKIP_DIRS = /* @__PURE__ */ new Set([
2547
2805
  "node_modules",
@@ -2597,15 +2855,15 @@ var MONOREPO_DIRS = ["apps", "packages", "services", "sites", "web", "site"], SK
2597
2855
  ".github/workflows",
2598
2856
  "content/config.ts"
2599
2857
  ], EXAMPLE_ENV = /^(\.env\.(example|sample|template|dist|local\.example|development\.example|production\.example)|example\.env|\.dev\.vars\.example)$/;
2600
- function readText(file) {
2858
+ function readText(file2) {
2601
2859
  try {
2602
- return readFileSync2(file, "utf8");
2860
+ return readFileSync3(file2, "utf8");
2603
2861
  } catch {
2604
2862
  return null;
2605
2863
  }
2606
2864
  }
2607
- function readJson(file) {
2608
- let text = readText(file);
2865
+ function readJson(file2) {
2866
+ let text = readText(file2);
2609
2867
  if (text === null)
2610
2868
  return null;
2611
2869
  try {
@@ -2614,16 +2872,16 @@ function readJson(file) {
2614
2872
  return null;
2615
2873
  }
2616
2874
  }
2617
- function isDir(p) {
2875
+ function isDir(p2) {
2618
2876
  try {
2619
- return statSync(p).isDirectory();
2877
+ return statSync2(p2).isDirectory();
2620
2878
  } catch {
2621
2879
  return !1;
2622
2880
  }
2623
2881
  }
2624
2882
  function listDir(dir) {
2625
2883
  try {
2626
- return readdirSync(dir);
2884
+ return readdirSync2(dir);
2627
2885
  } catch {
2628
2886
  return [];
2629
2887
  }
@@ -2641,14 +2899,14 @@ function isPackage(dir) {
2641
2899
  }
2642
2900
  function workspaceGlobs(root) {
2643
2901
  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 : [];
2644
- for (let g of list)
2645
- if (typeof g === "string")
2646
- globs.push(g);
2902
+ for (let g2 of list)
2903
+ if (typeof g2 === "string")
2904
+ globs.push(g2);
2647
2905
  let pnpm = readText(path2.join(root, "pnpm-workspace.yaml"));
2648
2906
  if (pnpm)
2649
- for (let m of pnpm.matchAll(/^\s*-\s*["']?([^"'\s#]+)["']?/gm))
2650
- globs.push(m[1]);
2651
- return globs.filter((g) => !g.startsWith("!"));
2907
+ for (let m2 of pnpm.matchAll(/^\s*-\s*["']?([^"'\s#]+)["']?/gm))
2908
+ globs.push(m2[1]);
2909
+ return globs.filter((g2) => !g2.startsWith("!"));
2652
2910
  }
2653
2911
  function expandGlob(root, glob) {
2654
2912
  let clean = glob.replace(/\/\*\*$/, "/*").replace(/\/$/, "");
@@ -2657,24 +2915,24 @@ function expandGlob(root, glob) {
2657
2915
  return isDir(dir) ? [dir] : [];
2658
2916
  }
2659
2917
  let [base] = clean.split("*"), parent = path2.join(root, base);
2660
- return listDir(parent).filter((e) => !SKIP_DIRS.has(e) && !e.startsWith(".")).map((e) => path2.join(parent, e)).filter(isDir);
2918
+ return listDir(parent).filter((e2) => !SKIP_DIRS.has(e2) && !e2.startsWith(".")).map((e2) => path2.join(parent, e2)).filter(isDir);
2661
2919
  }
2662
2920
  function packageDirs(root) {
2663
2921
  let dirs = /* @__PURE__ */ new Set([root]);
2664
- for (let g of workspaceGlobs(root))
2665
- for (let d of expandGlob(root, g))
2666
- if (isPackage(d))
2667
- dirs.add(d);
2922
+ for (let g2 of workspaceGlobs(root))
2923
+ for (let d3 of expandGlob(root, g2))
2924
+ if (isPackage(d3))
2925
+ dirs.add(d3);
2668
2926
  for (let group of MONOREPO_DIRS) {
2669
- let g = path2.join(root, group);
2670
- if (!isDir(g))
2927
+ let g2 = path2.join(root, group);
2928
+ if (!isDir(g2))
2671
2929
  continue;
2672
- if (isPackage(g))
2673
- dirs.add(g);
2674
- for (let entry of listDir(g)) {
2675
- let d = path2.join(g, entry);
2676
- if (!SKIP_DIRS.has(entry) && isDir(d) && isPackage(d))
2677
- dirs.add(d);
2930
+ if (isPackage(g2))
2931
+ dirs.add(g2);
2932
+ for (let entry of listDir(g2)) {
2933
+ let d3 = path2.join(g2, entry);
2934
+ if (!SKIP_DIRS.has(entry) && isDir(d3) && isPackage(d3))
2935
+ dirs.add(d3);
2678
2936
  }
2679
2937
  }
2680
2938
  return [...dirs].slice(0, MAX_PACKAGES);
@@ -2682,36 +2940,36 @@ function packageDirs(root) {
2682
2940
  function pythonRequirements(text) {
2683
2941
  let out = [];
2684
2942
  for (let line of text.split(/\r?\n/)) {
2685
- let m = /^\s*([A-Za-z0-9][A-Za-z0-9._-]*)/.exec(line.replace(/#.*/, ""));
2686
- if (m && !line.trim().startsWith("-"))
2687
- out.push(m[1].toLowerCase());
2943
+ let m2 = /^\s*([A-Za-z0-9][A-Za-z0-9._-]*)/.exec(line.replace(/#.*/, ""));
2944
+ if (m2 && !line.trim().startsWith("-"))
2945
+ out.push(m2[1].toLowerCase());
2688
2946
  }
2689
2947
  return out;
2690
2948
  }
2691
2949
  function pythonProjectDeps(text) {
2692
2950
  let out = /* @__PURE__ */ new Set;
2693
2951
  for (let block of text.matchAll(/(?:^|\n)\s*dependencies\s*=\s*\[([\s\S]*?)\]/g))
2694
- for (let m of block[1].matchAll(/["']([A-Za-z0-9][A-Za-z0-9._-]*)/g))
2695
- out.add(m[1].toLowerCase());
2952
+ for (let m2 of block[1].matchAll(/["']([A-Za-z0-9][A-Za-z0-9._-]*)/g))
2953
+ out.add(m2[1].toLowerCase());
2696
2954
  for (let table of text.matchAll(/\[(?:tool\.poetry\.(?:group\.[a-z]+\.)?dependencies|(?:dev-)?packages)\]([\s\S]*?)(?=\n\[|$)/g))
2697
- for (let m of table[1].matchAll(/^\s*([A-Za-z0-9][A-Za-z0-9._-]*)\s*=/gm))
2698
- out.add(m[1].toLowerCase());
2955
+ for (let m2 of table[1].matchAll(/^\s*([A-Za-z0-9][A-Za-z0-9._-]*)\s*=/gm))
2956
+ out.add(m2[1].toLowerCase());
2699
2957
  return out.delete("python"), [...out];
2700
2958
  }
2701
2959
  function gemfileDeps(text) {
2702
- return [...text.matchAll(/^\s*gem\s+["']([^"']+)["']/gm)].map((m) => m[1]);
2960
+ return [...text.matchAll(/^\s*gem\s+["']([^"']+)["']/gm)].map((m2) => m2[1]);
2703
2961
  }
2704
2962
  function goModDeps(text) {
2705
2963
  let out = [];
2706
- for (let m of text.matchAll(/^\s*(?:require\s+)?([a-z0-9.-]+\.[a-z]+\/[^\s]+)\s+v[0-9]/gm))
2707
- out.push(m[1]);
2964
+ for (let m2 of text.matchAll(/^\s*(?:require\s+)?([a-z0-9.-]+\.[a-z]+\/[^\s]+)\s+v[0-9]/gm))
2965
+ out.push(m2[1]);
2708
2966
  return out;
2709
2967
  }
2710
2968
  function cargoDeps(text) {
2711
2969
  let out = [];
2712
2970
  for (let table of text.matchAll(/\[(?:dev-|build-)?dependencies\]([\s\S]*?)(?=\n\[|$)/g))
2713
- for (let m of table[1].matchAll(/^\s*([A-Za-z0-9_-]+)\s*=/gm))
2714
- out.push(m[1]);
2971
+ for (let m2 of table[1].matchAll(/^\s*([A-Za-z0-9_-]+)\s*=/gm))
2972
+ out.push(m2[1]);
2715
2973
  return out;
2716
2974
  }
2717
2975
  function manifestDeps(dir) {
@@ -2730,10 +2988,10 @@ function manifestDeps(dir) {
2730
2988
  if (gem)
2731
2989
  add("gem", gemfileDeps(gem));
2732
2990
  let composer = readJson(path2.join(dir, "composer.json"));
2733
- for (let k of ["require", "require-dev"]) {
2734
- let d = composer?.[k];
2735
- if (d && typeof d === "object")
2736
- add("composer", Object.keys(d));
2991
+ for (let k3 of ["require", "require-dev"]) {
2992
+ let d3 = composer?.[k3];
2993
+ if (d3 && typeof d3 === "object")
2994
+ add("composer", Object.keys(d3));
2737
2995
  }
2738
2996
  let gomod = readText(path2.join(dir, "go.mod"));
2739
2997
  if (gomod)
@@ -2747,7 +3005,7 @@ function siteFromWrangler(text) {
2747
3005
  let first = [
2748
3006
  ...text.matchAll(/(?:pattern|route)["']?\s*[:=]\s*["']([^"'*/\s]+)/g),
2749
3007
  ...text.matchAll(/custom_domain["']?\s*[:=]\s*["']([^"'*/\s]+)/g)
2750
- ].map((m) => m[1].toLowerCase()).filter((h) => h.includes(".") && !h.endsWith("workers.dev"))[0];
3008
+ ].map((m2) => m2[1].toLowerCase()).filter((h2) => h2.includes(".") && !h2.endsWith("workers.dev"))[0];
2751
3009
  if (!first)
2752
3010
  return;
2753
3011
  return `https://${first.replace(/^(app|www|api|console)\./, "")}`;
@@ -2755,26 +3013,26 @@ function siteFromWrangler(text) {
2755
3013
  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)$/;
2756
3014
  function publicSite(url) {
2757
3015
  try {
2758
- let u = new URL(url.startsWith("http") ? url : `https://${url}`);
2759
- if (!u.hostname.includes(".") || NOT_A_SITE.test(u.hostname))
3016
+ let u2 = new URL(url.startsWith("http") ? url : `https://${url}`);
3017
+ if (!u2.hostname.includes(".") || NOT_A_SITE.test(u2.hostname))
2760
3018
  return;
2761
- return `https://${u.hostname.replace(/^www\./, "")}`;
3019
+ return `https://${u2.hostname.replace(/^www\./, "")}`;
2762
3020
  } catch {
2763
3021
  return;
2764
3022
  }
2765
3023
  }
2766
3024
  function siteFromConfig(text) {
2767
- let m = /\b(?:site|siteUrl|baseURL|baseUrl|url)\s*[:=]\s*["'`](https?:\/\/[^"'`\s]+)["'`]/.exec(text);
2768
- return m ? publicSite(m[1]) : void 0;
3025
+ let m2 = /\b(?:site|siteUrl|baseURL|baseUrl|url)\s*[:=]\s*["'`](https?:\/\/[^"'`\s]+)["'`]/.exec(text);
3026
+ return m2 ? publicSite(m2[1]) : void 0;
2769
3027
  }
2770
3028
  function githubRepo(gitConfig) {
2771
3029
  let remotes = [
2772
3030
  ...gitConfig.matchAll(/\[remote "([^"]+)"\][^[]*?url\s*=\s*(\S+)/g)
2773
- ].sort((a, b) => Number(b[1] === "origin") - Number(a[1] === "origin"));
3031
+ ].sort((a, b3) => Number(b3[1] === "origin") - Number(a[1] === "origin"));
2774
3032
  for (let [, , url] of remotes) {
2775
- let m = /github\.com[:/]([\w.-]+)\/([\w.-]+?)(?:\.git)?\/?$/.exec(url);
2776
- if (m)
2777
- return `${m[1]}/${m[2]}`;
3033
+ let m2 = /github\.com[:/]([\w.-]+)\/([\w.-]+?)(?:\.git)?\/?$/.exec(url);
3034
+ if (m2)
3035
+ return `${m2[1]}/${m2[2]}`;
2778
3036
  }
2779
3037
  return;
2780
3038
  }
@@ -2789,21 +3047,21 @@ function readGitConfig(root) {
2789
3047
  return readText(path2.join(gitDir, "config")) ?? readText(path2.join(gitDir, "..", "..", "config"));
2790
3048
  }
2791
3049
  function siteFromHtml(html) {
2792
- 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);
2793
- return m ? publicSite(m[1]) : void 0;
3050
+ let m2 = /<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);
3051
+ return m2 ? publicSite(m2[1]) : void 0;
2794
3052
  }
2795
3053
  function envKeyNames(text) {
2796
3054
  let out = [];
2797
3055
  for (let line of text.split(/\r?\n/)) {
2798
- let m = /^\s*(?:#\s*)?(?:export\s+)?([A-Z][A-Z0-9_]*)\s*=/.exec(line);
2799
- if (m)
2800
- out.push(m[1]);
3056
+ let m2 = /^\s*(?:#\s*)?(?:export\s+)?([A-Z][A-Z0-9_]*)\s*=/.exec(line);
3057
+ if (m2)
3058
+ out.push(m2[1]);
2801
3059
  }
2802
3060
  return out;
2803
3061
  }
2804
3062
  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+)$/;
2805
3063
  function scanProject(root, onProgress) {
2806
- 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("/") || ".";
3064
+ let deps = /* @__PURE__ */ new Set, files = /* @__PURE__ */ new Set, envKeys = /* @__PURE__ */ new Set, name, siteUrl, dirs = packageDirs(root), relDir = (d3) => path2.relative(root, d3).split(path2.sep).join("/") || ".";
2807
3065
  onProgress?.({
2808
3066
  label: `Found ${dirs.length} ${dirs.length === 1 ? "package" : "packages"}`,
2809
3067
  detail: dirs.length > 1 ? dirs.map(relDir).join(", ") : void 0
@@ -2816,22 +3074,22 @@ function scanProject(root, onProgress) {
2816
3074
  name = pkg.name;
2817
3075
  if (!siteUrl && typeof pkg.homepage === "string")
2818
3076
  siteUrl = publicSite(pkg.homepage);
2819
- for (let k of ["dependencies", "devDependencies"]) {
2820
- let d = pkg[k];
2821
- if (d && typeof d === "object")
2822
- for (let n of Object.keys(d))
3077
+ for (let k3 of ["dependencies", "devDependencies"]) {
3078
+ let d3 = pkg[k3];
3079
+ if (d3 && typeof d3 === "object")
3080
+ for (let n of Object.keys(d3))
2823
3081
  deps.add(n);
2824
3082
  }
2825
3083
  }
2826
- for (let d of manifestDeps(dir))
2827
- deps.add(d);
3084
+ for (let d3 of manifestDeps(dir))
3085
+ deps.add(d3);
2828
3086
  for (let entry of listDir(dir)) {
2829
3087
  if (EXAMPLE_ENV.test(entry)) {
2830
3088
  let text = readText(path2.join(dir, entry));
2831
3089
  if (text) {
2832
3090
  envFiles++;
2833
- for (let k of envKeyNames(text))
2834
- envKeys.add(k);
3091
+ for (let k3 of envKeyNames(text))
3092
+ envKeys.add(k3);
2835
3093
  }
2836
3094
  }
2837
3095
  if (!MARKERS.some((re) => re.test(entry)))
@@ -2902,8 +3160,8 @@ function paint(rgb, text, bg = !1) {
2902
3160
  return text;
2903
3161
  if (!trueColor())
2904
3162
  return bg ? import_picocolors3.default.bgMagenta(import_picocolors3.default.black(text)) : import_picocolors3.default.magenta(text);
2905
- let [r, g, b] = rgb;
2906
- return `\x1B[${bg ? 48 : 38};2;${r};${g};${b}m${text}\x1B[${bg ? 49 : 39}m`;
3163
+ let [r2, g2, b3] = rgb;
3164
+ return `\x1B[${bg ? 48 : 38};2;${r2};${g2};${b3}m${text}\x1B[${bg ? 49 : 39}m`;
2907
3165
  }
2908
3166
  var brand = (text) => paint(BRAND, text), badge = (text) => paint(BRAND, import_picocolors3.default.black(import_picocolors3.default.bold(` ${text} `)), !0), ramp = (i, text) => paint(RAMP[Math.min(i, RAMP.length - 1)], text), MARK = [
2909
3167
  " ▗▖ ▗▖ ",
@@ -2918,7 +3176,7 @@ var brand = (text) => paint(BRAND, text), badge = (text) => paint(BRAND, import_
2918
3176
  function motionAllowed(argv = process.argv, env = process.env, isTTY = Boolean(process.stdout.isTTY)) {
2919
3177
  return isTTY && !env.CI && !env.LOPEBASE_NO_MOTION && env.TERM !== "dumb" && !argv.includes("--no-motion");
2920
3178
  }
2921
- var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
3179
+ var sleep = (ms) => new Promise((r2) => setTimeout(r2, ms));
2922
3180
  function logoLines(opts) {
2923
3181
  let right = {
2924
3182
  3: `${import_picocolors3.default.bold("Lope")}${brand("Base")}${opts.version ? import_picocolors3.default.dim(` v${opts.version}`) : ""}`,
@@ -2939,7 +3197,7 @@ ${lines.join(`
2939
3197
  `);
2940
3198
  return;
2941
3199
  }
2942
- let blank = MARK.map((r) => " ".repeat(r.length)), frame = (shown) => MARK.map((row, i) => shown.has(i) ? HORIZON.has(i) ? import_picocolors3.default.dim(ramp(i, row)) : ramp(i, row) : blank[i]), up = `\x1B[${MARK.length}A`, onInterrupt = () => {
3200
+ let blank = MARK.map((r2) => " ".repeat(r2.length)), frame = (shown) => MARK.map((row, i) => shown.has(i) ? HORIZON.has(i) ? import_picocolors3.default.dim(ramp(i, row)) : ramp(i, row) : blank[i]), up = `\x1B[${MARK.length}A`, onInterrupt = () => {
2943
3201
  write(`\x1B[?25h
2944
3202
  `), process.exit(130);
2945
3203
  };
@@ -2993,8 +3251,8 @@ function stackRows(detection, facts) {
2993
3251
  rows.push(["Repo", facts.repo]);
2994
3252
  if (!rows.length)
2995
3253
  return [import_picocolors3.default.dim("Nothing recognized yet. Your agent will look closer.")];
2996
- let width = Math.max(...rows.map(([k]) => k.length));
2997
- return rows.map(([k, v]) => `${import_picocolors3.default.dim(k.padEnd(width))} ${v}`);
3254
+ let width = Math.max(...rows.map(([k3]) => k3.length));
3255
+ return rows.map(([k3, v2]) => `${import_picocolors3.default.dim(k3.padEnd(width))} ${v2}`);
2998
3256
  }
2999
3257
  var PLAN = [
3000
3258
  {
@@ -3019,13 +3277,13 @@ function planLines() {
3019
3277
  ${import_picocolors3.default.dim(s.detail)}`);
3020
3278
  }
3021
3279
  function stepRail(n, total = PLAN.length) {
3022
- return Array.from({ length: total }, (_, i) => i < n ? brand("◆") : import_picocolors3.default.dim("◇")).join(import_picocolors3.default.dim(" ── "));
3280
+ return Array.from({ length: total }, (_3, i) => i < n ? brand("◆") : import_picocolors3.default.dim("◇")).join(import_picocolors3.default.dim(" ── "));
3023
3281
  }
3024
3282
  function stepTitle(n) {
3025
3283
  return `${stepRail(n)} ${import_picocolors3.default.dim(`Step ${n} of ${PLAN.length}`)} ${import_picocolors3.default.bold(PLAN[n - 1].title)}`;
3026
3284
  }
3027
3285
  async function horizon(opts) {
3028
- let write = opts.write ?? ((s) => process.stdout.write(s)), width = opts.width ?? 28, line = (n) => Array.from({ length: n }, (_, i) => ramp(Math.floor(i / width * RAMP.length), "━")).join("");
3286
+ let write = opts.write ?? ((s) => process.stdout.write(s)), width = opts.width ?? 28, line = (n) => Array.from({ length: n }, (_3, i) => ramp(Math.floor(i / width * RAMP.length), "━")).join("");
3029
3287
  if (!opts.motion) {
3030
3288
  write(` ${line(width)}
3031
3289
  `);
@@ -3037,15 +3295,15 @@ async function horizon(opts) {
3037
3295
  `);
3038
3296
  }
3039
3297
  function watchRows(items) {
3040
- return items.map((w) => w.how === "address" ? `${brand("◉")} ${import_picocolors3.default.bold(w.label)} ${import_picocolors3.default.dim("uptime check, every 15 minutes")}` : `${brand("○")} ${import_picocolors3.default.bold(w.label)} ${import_picocolors3.default.dim("a service in the adapter's health list")}`);
3298
+ return items.map((w2) => w2.how === "address" ? `${brand("◉")} ${import_picocolors3.default.bold(w2.label)} ${import_picocolors3.default.dim("uptime check, every 15 minutes")}` : `${brand("○")} ${import_picocolors3.default.bold(w2.label)} ${import_picocolors3.default.dim("a service in the adapter's health list")}`);
3041
3299
  }
3042
3300
 
3043
3301
  // src/update.ts
3044
- import { readFileSync as readFileSync3 } from "node:fs";
3302
+ import { readFileSync as readFileSync4 } from "node:fs";
3045
3303
  import path3 from "node:path";
3046
- var readJson2 = (file) => {
3304
+ var readJson2 = (file2) => {
3047
3305
  try {
3048
- return JSON.parse(readFileSync3(file, "utf8"));
3306
+ return JSON.parse(readFileSync4(file2, "utf8"));
3049
3307
  } catch {
3050
3308
  return null;
3051
3309
  }
@@ -3062,7 +3320,7 @@ function findAdapterInstalls(root) {
3062
3320
  }["@lopebase/adapter"];
3063
3321
  if (!range || range.startsWith("workspace:"))
3064
3322
  continue;
3065
- let installed = [dir, root].map((d) => readJson2(path3.join(d, "node_modules/@lopebase/adapter/package.json"))).find((p) => typeof p?.version === "string")?.version;
3323
+ let installed = [dir, root].map((d3) => readJson2(path3.join(d3, "node_modules/@lopebase/adapter/package.json"))).find((p2) => typeof p2?.version === "string")?.version;
3066
3324
  out.push({ dir: path3.relative(root, dir) || ".", range, installed });
3067
3325
  }
3068
3326
  return out;
@@ -3079,8 +3337,8 @@ async function latestOnNpm(name, timeoutMs = 1500, fetchImpl = fetch) {
3079
3337
  });
3080
3338
  if (!res.ok)
3081
3339
  return;
3082
- let body = await res.json();
3083
- return typeof body.version === "string" ? body.version : void 0;
3340
+ let body2 = await res.json();
3341
+ return typeof body2.version === "string" ? body2.version : void 0;
3084
3342
  } catch {
3085
3343
  return;
3086
3344
  }
@@ -3099,6 +3357,8 @@ ${import_picocolors4.default.bold("Usage")}
3099
3357
  npx lopebase mcp run the LopeBase tools as a stdio MCP server
3100
3358
  npx lopebase adapter secret print a new @lopebase/adapter signing secret
3101
3359
  npx lopebase adapter check <url> test a running adapter (reads LOPEBASE_SIGNING_SECRET)
3360
+ npx lopebase blog check [dir] check the blog posts LopeBase publishes to your repo
3361
+ (--format <preset>, --allow-empty)
3102
3362
 
3103
3363
  ${import_picocolors4.default.bold("Options")}
3104
3364
  --print print the agent prompt instead of starting an agent
@@ -3114,7 +3374,7 @@ ${import_picocolors4.default.bold("Learn more")}
3114
3374
  }, cwd = process.cwd(), motion = motionAllowed(), TAGLINE = "Every product, one place.", PAGEVIEWS = "LopeBase pageviews";
3115
3375
  function version() {
3116
3376
  try {
3117
- return JSON.parse(readFileSync4(new URL("../package.json", import.meta.url), "utf8")).version;
3377
+ return JSON.parse(readFileSync5(new URL("../package.json", import.meta.url), "utf8")).version;
3118
3378
  } catch {
3119
3379
  return;
3120
3380
  }
@@ -3151,12 +3411,12 @@ async function checkToken(auth) {
3151
3411
  });
3152
3412
  if (res.status === 401)
3153
3413
  return { ok: !1, message: "That token is not valid or has expired." };
3154
- let body = await res.json();
3155
- return { ok: !0, products: JSON.parse(body.result?.content?.[0]?.text ?? "[]").length };
3156
- } catch (e) {
3414
+ let body2 = await res.json();
3415
+ return { ok: !0, products: JSON.parse(body2.result?.content?.[0]?.text ?? "[]").length };
3416
+ } catch (e2) {
3157
3417
  return {
3158
3418
  ok: !1,
3159
- message: `Could not reach ${auth.url} (${String(e)}).`
3419
+ message: `Could not reach ${auth.url} (${String(e2)}).`
3160
3420
  };
3161
3421
  }
3162
3422
  }
@@ -3184,8 +3444,8 @@ async function login() {
3184
3444
  s.start("Waiting for you to approve in the browser");
3185
3445
  let res = await pollDeviceLogin(url, device);
3186
3446
  if (res.ok) {
3187
- let file = saveAuth({ url: res.url, token: res.token });
3188
- return s.stop(`Connected to ${import_picocolors4.default.bold(res.url)}. Saved to ${import_picocolors4.default.dim(file)}`), { url: res.url, token: res.token };
3447
+ let file2 = saveAuth({ url: res.url, token: res.token });
3448
+ return s.stop(`Connected to ${import_picocolors4.default.bold(res.url)}. Saved to ${import_picocolors4.default.dim(file2)}`), { url: res.url, token: res.token };
3189
3449
  }
3190
3450
  if (s.stop(import_picocolors4.default.red(res.message)), res.reason === "denied")
3191
3451
  bail("Nothing was connected.");
@@ -3198,7 +3458,7 @@ async function askWorkspace() {
3198
3458
  return workspaceUrl(guard(await he({
3199
3459
  message: "Your LopeBase workspace (name or address)",
3200
3460
  placeholder: "yourteam or https://yourteam.lopebase.com",
3201
- validate: (v) => workspaceUrl(v ?? "") ? void 0 : "Type your workspace name, like yourteam, or its full address"
3461
+ validate: (v2) => workspaceUrl(v2 ?? "") ? void 0 : "Type your workspace name, like yourteam, or its full address"
3202
3462
  })));
3203
3463
  }
3204
3464
  async function pasteLogin(url) {
@@ -3212,33 +3472,33 @@ async function pasteLogin(url) {
3212
3472
  for (;; ) {
3213
3473
  let token = guard(await ge({
3214
3474
  message: "Paste the agent token",
3215
- validate: (v) => v?.startsWith("lb_agent_") ? void 0 : "Tokens start with lb_agent_"
3475
+ validate: (v2) => v2?.startsWith("lb_agent_") ? void 0 : "Tokens start with lb_agent_"
3216
3476
  })).trim(), s = Y2();
3217
3477
  s.start("Checking the token");
3218
3478
  let check = await checkToken({ url, token });
3219
3479
  if (check.ok) {
3220
- let file = saveAuth({ url, token });
3221
- return s.stop(`Signed in. ${check.products} ${check.products === 1 ? "property" : "properties"} in this workspace. Saved to ${import_picocolors4.default.dim(file)}`), { url, token };
3480
+ let file2 = saveAuth({ url, token });
3481
+ return s.stop(`Signed in. ${check.products} ${check.products === 1 ? "property" : "properties"} in this workspace. Saved to ${import_picocolors4.default.dim(file2)}`), { url, token };
3222
3482
  }
3223
3483
  s.stop(import_picocolors4.default.red(check.message ?? "That did not work."));
3224
3484
  }
3225
3485
  }
3226
- async function printDetection(d, facts) {
3227
- Me(stackRows(d, facts).join(`
3486
+ async function printDetection(d3, facts) {
3487
+ Me(stackRows(d3, facts).join(`
3228
3488
  `), "Your stack"), await pace(motion, 150);
3229
- let found = d.sources.filter((s) => s.status === "found");
3489
+ let found = d3.sources.filter((s) => s.status === "found");
3230
3490
  if (found.length)
3231
3491
  Me(found.map((s) => `${import_picocolors4.default.green("●")} ${import_picocolors4.default.bold(s.label)} ${import_picocolors4.default.dim(s.evidence.join(", "))}`).join(`
3232
3492
  `), "Already in your code, ready to connect"), await pace(motion, 150);
3233
- let possible = d.sources.filter((s) => s.status === "possible");
3493
+ let possible = d3.sources.filter((s) => s.status === "possible");
3234
3494
  if (possible.length)
3235
3495
  Me(possible.map((s) => `${import_picocolors4.default.yellow("?")} ${import_picocolors4.default.bold(s.label)} ${import_picocolors4.default.dim(`only ${s.evidence.join(", ")}`)}`).join(`
3236
3496
  `), "Maybe in use, your agent will check"), await pace(motion, 150);
3237
- let watch = watchList(d, facts);
3497
+ let watch = watchList(d3, facts);
3238
3498
  if (watch.length)
3239
3499
  Me(watchRows(watch).join(`
3240
3500
  `), "Worth watching for uptime"), await pace(motion, 150);
3241
- for (let gap of d.gaps)
3501
+ for (let gap of d3.gaps)
3242
3502
  M2.info(import_picocolors4.default.dim(gap));
3243
3503
  }
3244
3504
  async function scanWithProgress() {
@@ -3300,7 +3560,7 @@ async function init() {
3300
3560
  label: src.status === "found" ? src.label : src.status === "possible" ? `${src.label} ${import_picocolors4.default.dim("(maybe in use, we'll check)")}` : `${src.label} ${import_picocolors4.default.dim("(not set up yet, we'll help)")}`,
3301
3561
  hint: src.why
3302
3562
  })),
3303
- ...watchList(detection, facts).some((w) => w.how === "address") ? [
3563
+ ...watchList(detection, facts).some((w2) => w2.how === "address") ? [
3304
3564
  {
3305
3565
  value: PAGEVIEWS,
3306
3566
  label: `${PAGEVIEWS} ${import_picocolors4.default.dim("(one tag, no cookies)")}`,
@@ -3324,7 +3584,7 @@ async function init() {
3324
3584
  `${import_picocolors4.default.bold(agent)} will now:`,
3325
3585
  ` ${brand("1.")} add ${import_picocolors4.default.bold(productName || "this product")} to your workspace`,
3326
3586
  ` ${brand("2.")} connect ${chosen.length ? chosen.join(", ") : "what it recommends"}`,
3327
- ` ${brand("3.")} pick what to watch for uptime: ${watchList(detection, facts).map((w) => w.label).join(", ") || "the site"}`,
3587
+ ` ${brand("3.")} pick what to watch for uptime: ${watchList(detection, facts).map((w2) => w2.label).join(", ") || "the site"}`,
3328
3588
  ` ${brand("4.")} stop and ask you for any sign-in, key, or yes`,
3329
3589
  "",
3330
3590
  import_picocolors4.default.dim("You can follow along in your workspace as each one turns green.")
@@ -3362,7 +3622,7 @@ async function handOff(prompt, plan) {
3362
3622
  stdio: "inherit",
3363
3623
  cwd
3364
3624
  });
3365
- child.on("error", (e) => bail(`Could not start ${agent.label}: ${e.message}`)), child.on("exit", (code) => process.exit(code ?? 0));
3625
+ child.on("error", (e2) => bail(`Could not start ${agent.label}: ${e2.message}`)), child.on("exit", (code) => process.exit(code ?? 0));
3366
3626
  }
3367
3627
  async function noticeNewerCli() {
3368
3628
  let mine = version(), latest = await latestOnNpm("lopebase");
@@ -3388,11 +3648,11 @@ async function update() {
3388
3648
  let latest = npmLatest && isBehind(ADAPTER_VERSION, npmLatest) ? npmLatest : ADAPTER_VERSION, behind = installs.filter((i) => isBehind(runningVersion(i), latest));
3389
3649
  if (s.stop(installs.map((i) => `${i.dir === "." ? "This folder" : i.dir} runs ${import_picocolors4.default.bold(runningVersion(i))}`).join(", ")), !behind.length)
3390
3650
  return Se(`Up to date with ${import_picocolors4.default.bold(latest)}.`);
3391
- let from = behind.map(runningVersion).sort((a, b) => isBehind(a, b) ? -1 : 1)[0], releases = releasesSince(from);
3392
- if (Me(releases.flatMap((r) => [
3393
- `${brand("◆")} ${import_picocolors4.default.bold(r.version)} ${import_picocolors4.default.dim(r.date)}`,
3394
- ...r.features.map((f) => ` ${f}`),
3395
- ...(r.breaking ?? []).map((b) => ` ${import_picocolors4.default.yellow("!")} ${b}`)
3651
+ let from = behind.map(runningVersion).sort((a, b3) => isBehind(a, b3) ? -1 : 1)[0], releases2 = releasesSince(from);
3652
+ if (Me(releases2.flatMap((r2) => [
3653
+ `${brand("◆")} ${import_picocolors4.default.bold(r2.version)} ${import_picocolors4.default.dim(r2.date)}`,
3654
+ ...r2.features.map((f) => ` ${f}`),
3655
+ ...(r2.breaking ?? []).map((b3) => ` ${import_picocolors4.default.yellow("!")} ${b3}`)
3396
3656
  ]).join(`
3397
3657
  `), `New since ${from}`), npmLatest && isBehind(ADAPTER_VERSION, npmLatest))
3398
3658
  M2.warn(`npm has ${npmLatest}, newer than these notes. Run ${brand("npx lopebase@latest update")} for its steps.`);
@@ -3411,6 +3671,29 @@ The adapter is in: ${where}. If you have the lopebase MCP tools, call get_onboar
3411
3671
  ` ${brand("3.")} run the adapter check and your tests`
3412
3672
  ]);
3413
3673
  }
3674
+ var BLOG_USAGE = `Usage:
3675
+ lopebase blog check [dir] [--format <preset>] [--allow-empty]
3676
+
3677
+ Presets: ${Object.entries(BLOG_PRESETS).map(([name, preset]) => `${name} (${preset.dir})`).join(", ")}. Default: markdown.`;
3678
+ function blog() {
3679
+ if (rest[0] !== "check")
3680
+ return console.log(BLOG_USAGE), process.exit(rest[0] ? 1 : 0);
3681
+ let format = option("format") ?? "markdown";
3682
+ if (!isBlogFormat(format))
3683
+ return console.error(`Unknown format "${format}".
3684
+
3685
+ ${BLOG_USAGE}`), process.exit(1);
3686
+ let dir = rest.slice(1).find((a, i, args) => !a.startsWith("--") && args[i - 1] !== "--format"), res = checkBlog({
3687
+ cwd,
3688
+ format,
3689
+ dir,
3690
+ allowEmpty: flag("allow-empty")
3691
+ });
3692
+ for (let { file: file2, problem } of res.problems)
3693
+ console.log(`${file2}: ${problem}`);
3694
+ let posts = `${res.posts} ${res.posts === 1 ? "post" : "posts"}`;
3695
+ console.log(res.problems.length ? import_picocolors4.default.red(`${res.problems.length} ${res.problems.length === 1 ? "problem" : "problems"} in ${posts} in ${res.dir}.`) : import_picocolors4.default.green(`Checked ${posts} in ${res.dir}. All good.`)), process.exit(res.problems.length ? 1 : 0);
3696
+ }
3414
3697
  async function main() {
3415
3698
  switch (command) {
3416
3699
  case "init":
@@ -3444,7 +3727,7 @@ async function main() {
3444
3727
  baseUrl: rest[1],
3445
3728
  secret,
3446
3729
  token: secret ? void 0 : token,
3447
- log: (l) => console.log(l.startsWith("FAIL") ? import_picocolors4.default.red(l) : import_picocolors4.default.green(l))
3730
+ log: (l2) => console.log(l2.startsWith("FAIL") ? import_picocolors4.default.red(l2) : import_picocolors4.default.green(l2))
3448
3731
  });
3449
3732
  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);
3450
3733
  }
@@ -3452,6 +3735,8 @@ async function main() {
3452
3735
  lopebase adapter secret print a new signing secret
3453
3736
  lopebase adapter check <base-url> test a running adapter (reads LOPEBASE_SIGNING_SECRET)`), process.exit(sub ? 1 : 0);
3454
3737
  }
3738
+ case "blog":
3739
+ return blog();
3455
3740
  case "mcp": {
3456
3741
  let auth = loadAuth();
3457
3742
  if (!auth)