toiljs 0.0.55 → 0.0.57
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/CHANGELOG.md +10 -0
- package/README.md +72 -14
- package/build/backend/.tsbuildinfo +1 -1
- package/build/cli/.tsbuildinfo +1 -1
- package/build/cli/index.js +293 -142
- package/build/client/.tsbuildinfo +1 -1
- package/build/client/auth.js +1 -1
- package/build/client/components/Image.d.ts +1 -1
- package/build/client/dev/devtools.js +4 -2
- package/build/client/index.d.ts +2 -2
- package/build/client/index.js +2 -2
- package/build/client/routing/Router.js +1 -1
- package/build/client/routing/hooks.js +2 -2
- package/build/client/routing/mount.js +1 -1
- package/build/compiler/.tsbuildinfo +1 -1
- package/build/compiler/docs.js +1 -1
- package/build/compiler/seo.js +1 -3
- package/build/compiler/template-build.d.ts +5 -2
- package/build/compiler/template-build.js +19 -7
- package/build/devserver/.tsbuildinfo +1 -1
- package/build/devserver/cache.js +0 -0
- package/build/devserver/crypto.js +45 -17
- package/build/devserver/database.d.ts +1 -1
- package/build/devserver/database.js +84 -0
- package/build/devserver/email/caps.js +0 -0
- package/build/devserver/email/config.js +7 -2
- package/build/devserver/email/validate.js +1 -4
- package/build/devserver/host.js +18 -1
- package/build/devserver/index.d.ts +1 -1
- package/build/devserver/index.js +3 -2
- package/build/devserver/module.js +51 -12
- package/build/devserver/proxy.js +2 -1
- package/build/io/.tsbuildinfo +1 -1
- package/build/io/codec.d.ts +5 -5
- package/build/io/codec.js +193 -77
- package/examples/basic/client/components/HoneycombBackground.tsx +1 -1
- package/examples/basic/client/public/images/logo.svg +37 -34
- package/examples/basic/client/public/index.html +14 -14
- package/examples/basic/client/routes/auth.tsx +18 -10
- package/examples/basic/client/routes/cookies.tsx +15 -24
- package/examples/basic/client/routes/crypto.tsx +4 -5
- package/examples/basic/client/routes/features/template/template.tsx +1 -1
- package/examples/basic/client/routes/hello.tsx +1 -1
- package/examples/basic/client/routes/pq.tsx +14 -14
- package/examples/basic/client/routes/rest.tsx +1 -3
- package/examples/basic/client/styles/main.css +25 -22
- package/examples/basic/client/toil.tsx +1 -1
- package/examples/basic/server/README.md +8 -8
- package/examples/basic/server/core/AppHandler.ts +4 -7
- package/examples/basic/server/routes/Auth.ts +13 -10
- package/examples/basic/server/routes/EnvDemo.ts +9 -3
- package/examples/basic/server/routes/Guestbook.ts +2 -4
- package/package.json +26 -26
- package/src/backend/index.ts +4 -2
- package/src/cli/create.ts +19 -4
- package/src/cli/diagnostics.ts +48 -0
- package/src/cli/doctor.ts +155 -9
- package/src/cli/notify.ts +1 -6
- package/src/cli/ui.ts +3 -3
- package/src/cli/version-check.ts +5 -1
- package/src/client/auth.ts +33 -10
- package/src/client/components/Form.tsx +2 -2
- package/src/client/components/Image.tsx +1 -1
- package/src/client/components/Script.tsx +1 -1
- package/src/client/components/Slot.tsx +1 -1
- package/src/client/dev/devtools.tsx +126 -55
- package/src/client/dev/error-overlay.tsx +7 -1
- package/src/client/head/metadata.ts +1 -1
- package/src/client/index.ts +13 -2
- package/src/client/routing/Router.tsx +2 -2
- package/src/client/routing/error-boundary.tsx +1 -1
- package/src/client/routing/hooks.ts +5 -3
- package/src/client/routing/loader.ts +2 -2
- package/src/client/routing/mount.tsx +5 -6
- package/src/compiler/docs.ts +1 -1
- package/src/compiler/email-preview.ts +1 -1
- package/src/compiler/generate.ts +1 -1
- package/src/compiler/seo.ts +1 -3
- package/src/compiler/ssg.ts +10 -4
- package/src/compiler/template-build.ts +43 -11
- package/src/compiler/template.ts +1 -4
- package/src/compiler/vite.ts +1 -1
- package/src/devserver/cache.ts +0 -0
- package/src/devserver/crypto.ts +140 -51
- package/src/devserver/database.ts +168 -9
- package/src/devserver/dotenv.ts +10 -2
- package/src/devserver/email/caps.ts +0 -0
- package/src/devserver/email/config.ts +8 -2
- package/src/devserver/email/index.ts +3 -3
- package/src/devserver/email/validate.ts +1 -4
- package/src/devserver/envelope.ts +3 -3
- package/src/devserver/host.ts +46 -6
- package/src/devserver/index.ts +15 -6
- package/src/devserver/module.ts +56 -14
- package/src/devserver/proxy.ts +5 -7
- package/src/io/codec.ts +226 -83
- package/test/devserver-database.test.ts +60 -0
- package/test/devserver-secrets.test.ts +59 -0
- package/test/doctor.test.ts +30 -0
package/build/cli/index.js
CHANGED
|
@@ -609,8 +609,8 @@ function block({
|
|
|
609
609
|
return;
|
|
610
610
|
}
|
|
611
611
|
if (!o2) return;
|
|
612
|
-
const i2 = a3 === "return" ? 0 : -1,
|
|
613
|
-
l.moveCursor(r2, i2,
|
|
612
|
+
const i2 = a3 === "return" ? 0 : -1, m2 = a3 === "return" ? -1 : 0;
|
|
613
|
+
l.moveCursor(r2, i2, m2, () => {
|
|
614
614
|
l.clearLine(r2, 1, () => {
|
|
615
615
|
e.once("keypress", n2);
|
|
616
616
|
});
|
|
@@ -628,9 +628,9 @@ function wrapTextWithPrefix(e, r2, o2, t2 = o2, s = o2, n2) {
|
|
|
628
628
|
hard: true,
|
|
629
629
|
trim: false
|
|
630
630
|
}).split(`
|
|
631
|
-
`).map((c2, i2,
|
|
632
|
-
const
|
|
633
|
-
return i2 === 0 ? `${t2}${
|
|
631
|
+
`).map((c2, i2, m2) => {
|
|
632
|
+
const d = n2 ? n2(c2, i2) : c2;
|
|
633
|
+
return i2 === 0 ? `${t2}${d}` : i2 === m2.length - 1 ? `${s}${d}` : `${o2}${d}`;
|
|
634
634
|
}).join(`
|
|
635
635
|
`);
|
|
636
636
|
}
|
|
@@ -941,7 +941,7 @@ function isUnicodeSupported() {
|
|
|
941
941
|
}
|
|
942
942
|
var unicode = isUnicodeSupported();
|
|
943
943
|
var isCI = () => process.env.CI === "true";
|
|
944
|
-
var unicodeOr = (
|
|
944
|
+
var unicodeOr = (o2, e) => unicode ? o2 : e;
|
|
945
945
|
var S_STEP_ACTIVE = unicodeOr("\u25C6", "*");
|
|
946
946
|
var S_STEP_CANCEL = unicodeOr("\u25A0", "x");
|
|
947
947
|
var S_STEP_ERROR = unicodeOr("\u25B2", "x");
|
|
@@ -967,8 +967,8 @@ var S_INFO = unicodeOr("\u25CF", "\u2022");
|
|
|
967
967
|
var S_SUCCESS = unicodeOr("\u25C6", "*");
|
|
968
968
|
var S_WARN = unicodeOr("\u25B2", "!");
|
|
969
969
|
var S_ERROR = unicodeOr("\u25A0", "x");
|
|
970
|
-
var symbol = (
|
|
971
|
-
switch (
|
|
970
|
+
var symbol = (o2) => {
|
|
971
|
+
switch (o2) {
|
|
972
972
|
case "initial":
|
|
973
973
|
case "active":
|
|
974
974
|
return styleText2("cyan", S_STEP_ACTIVE);
|
|
@@ -980,8 +980,8 @@ var symbol = (e) => {
|
|
|
980
980
|
return styleText2("green", S_STEP_SUBMIT);
|
|
981
981
|
}
|
|
982
982
|
};
|
|
983
|
-
var symbolBar = (
|
|
984
|
-
switch (
|
|
983
|
+
var symbolBar = (o2) => {
|
|
984
|
+
switch (o2) {
|
|
985
985
|
case "initial":
|
|
986
986
|
case "active":
|
|
987
987
|
return styleText2("cyan", S_BAR);
|
|
@@ -993,6 +993,10 @@ var symbolBar = (e) => {
|
|
|
993
993
|
return styleText2("green", S_BAR);
|
|
994
994
|
}
|
|
995
995
|
};
|
|
996
|
+
function formatInstructionFooter(o2, e) {
|
|
997
|
+
const r2 = [`${e ? `${styleText2("cyan", S_BAR)} ` : ""}${o2.join(" \u2022 ")}`];
|
|
998
|
+
return e && r2.push(styleText2("cyan", S_BAR_END)), r2;
|
|
999
|
+
}
|
|
996
1000
|
var E$1 = (l2, o2, g, c2, h2, O = false) => {
|
|
997
1001
|
let r2 = o2, w = 0;
|
|
998
1002
|
if (O)
|
|
@@ -1012,19 +1016,19 @@ var limitOptions = ({
|
|
|
1012
1016
|
columnPadding: O = 0,
|
|
1013
1017
|
rowPadding: r2 = 4
|
|
1014
1018
|
}) => {
|
|
1015
|
-
const i2 = getColumns(c2) - O, I = getRows(c2), C2 = styleText2("dim", "..."), x = Math.max(I - r2, 0),
|
|
1019
|
+
const i2 = getColumns(c2) - O, I = getRows(c2), C2 = styleText2("dim", "..."), x = Math.max(I - r2, 0), m2 = Math.max(Math.min(h2, x), 5);
|
|
1016
1020
|
let p = 0;
|
|
1017
|
-
l2 >=
|
|
1018
|
-
Math.min(l2 -
|
|
1021
|
+
l2 >= m2 - 3 && (p = Math.max(
|
|
1022
|
+
Math.min(l2 - m2 + 3, o2.length - m2),
|
|
1019
1023
|
0
|
|
1020
1024
|
));
|
|
1021
|
-
let f =
|
|
1025
|
+
let f = m2 < o2.length && p > 0, u3 = m2 < o2.length && p + m2 < o2.length;
|
|
1022
1026
|
const W2 = Math.min(
|
|
1023
|
-
p +
|
|
1027
|
+
p + m2,
|
|
1024
1028
|
o2.length
|
|
1025
1029
|
), e = [];
|
|
1026
|
-
let
|
|
1027
|
-
f &&
|
|
1030
|
+
let d = 0;
|
|
1031
|
+
f && d++, u3 && d++;
|
|
1028
1032
|
const v = p + (f ? 1 : 0), P = W2 - (u3 ? 1 : 0);
|
|
1029
1033
|
for (let t2 = v; t2 < P; t2++) {
|
|
1030
1034
|
const n2 = wrapAnsi(g(o2[t2], t2 === l2), i2, {
|
|
@@ -1032,10 +1036,10 @@ var limitOptions = ({
|
|
|
1032
1036
|
trim: false
|
|
1033
1037
|
}).split(`
|
|
1034
1038
|
`);
|
|
1035
|
-
e.push(n2),
|
|
1039
|
+
e.push(n2), d += n2.length;
|
|
1036
1040
|
}
|
|
1037
|
-
if (
|
|
1038
|
-
let t2 = 0, n2 = 0, s =
|
|
1041
|
+
if (d > x) {
|
|
1042
|
+
let t2 = 0, n2 = 0, s = d;
|
|
1039
1043
|
const M = l2 - v;
|
|
1040
1044
|
let a3 = x;
|
|
1041
1045
|
const T = () => E$1(e, s, 0, M, a3), L = () => E$1(
|
|
@@ -1095,42 +1099,29 @@ ${g}
|
|
|
1095
1099
|
}
|
|
1096
1100
|
}).prompt();
|
|
1097
1101
|
};
|
|
1098
|
-
var
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
const i2 = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR_START)} ` : "";
|
|
1106
|
-
i2.write(`${e}${o2}
|
|
1107
|
-
`);
|
|
1108
|
-
};
|
|
1109
|
-
var outro = (o2 = "", t2) => {
|
|
1110
|
-
const i2 = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR)}
|
|
1111
|
-
${styleText2("gray", S_BAR_END)} ` : "";
|
|
1112
|
-
i2.write(`${e}${o2}
|
|
1113
|
-
|
|
1114
|
-
`);
|
|
1115
|
-
};
|
|
1116
|
-
var d = (n2, a3) => n2.split(`
|
|
1117
|
-
`).map((m) => a3(m)).join(`
|
|
1102
|
+
var MULTISELECT_INSTRUCTIONS = [
|
|
1103
|
+
`${styleText2("dim", "\u2191/\u2193")} to navigate`,
|
|
1104
|
+
`${styleText2("dim", "Space:")} select`,
|
|
1105
|
+
`${styleText2("dim", "Enter:")} confirm`
|
|
1106
|
+
];
|
|
1107
|
+
var m = (n2, o2) => n2.split(`
|
|
1108
|
+
`).map((d) => o2(d)).join(`
|
|
1118
1109
|
`);
|
|
1119
1110
|
var multiselect = (n2) => {
|
|
1120
|
-
const
|
|
1111
|
+
const o2 = (t2, a3) => {
|
|
1121
1112
|
const r2 = t2.label ?? String(t2.value);
|
|
1122
|
-
return
|
|
1123
|
-
},
|
|
1113
|
+
return a3 === "disabled" ? `${styleText2("gray", S_CHECKBOX_INACTIVE)} ${m(r2, (l2) => styleText2(["strikethrough", "gray"], l2))}${t2.hint ? ` ${styleText2("dim", `(${t2.hint ?? "disabled"})`)}` : ""}` : a3 === "active" ? `${styleText2("cyan", S_CHECKBOX_ACTIVE)} ${r2}${t2.hint ? ` ${styleText2("dim", `(${t2.hint})`)}` : ""}` : a3 === "selected" ? `${styleText2("green", S_CHECKBOX_SELECTED)} ${m(r2, (l2) => styleText2("dim", l2))}${t2.hint ? ` ${styleText2("dim", `(${t2.hint})`)}` : ""}` : a3 === "cancelled" ? `${m(r2, (l2) => styleText2(["strikethrough", "dim"], l2))}` : a3 === "active-selected" ? `${styleText2("green", S_CHECKBOX_SELECTED)} ${r2}${t2.hint ? ` ${styleText2("dim", `(${t2.hint})`)}` : ""}` : a3 === "submitted" ? `${m(r2, (l2) => styleText2("dim", l2))}` : `${styleText2("dim", S_CHECKBOX_INACTIVE)} ${m(r2, (l2) => styleText2("dim", l2))}`;
|
|
1114
|
+
}, d = n2.required ?? true;
|
|
1124
1115
|
return new a$1({
|
|
1125
1116
|
options: n2.options,
|
|
1126
1117
|
signal: n2.signal,
|
|
1127
1118
|
input: n2.input,
|
|
1128
1119
|
output: n2.output,
|
|
1129
1120
|
initialValues: n2.initialValues,
|
|
1130
|
-
required:
|
|
1121
|
+
required: d,
|
|
1131
1122
|
cursorAt: n2.cursorAt,
|
|
1132
1123
|
validate(t2) {
|
|
1133
|
-
if (
|
|
1124
|
+
if (d && (t2 === void 0 || t2.length === 0))
|
|
1134
1125
|
return `Please select at least one option.
|
|
1135
1126
|
${styleText2(
|
|
1136
1127
|
"reset",
|
|
@@ -1144,22 +1135,22 @@ ${styleText2(
|
|
|
1144
1135
|
)}`;
|
|
1145
1136
|
},
|
|
1146
1137
|
render() {
|
|
1147
|
-
const t2 = n2.withGuide ?? settings.withGuide,
|
|
1138
|
+
const t2 = n2.withGuide ?? settings.withGuide, a3 = wrapTextWithPrefix(
|
|
1148
1139
|
n2.output,
|
|
1149
1140
|
n2.message,
|
|
1150
1141
|
t2 ? `${symbolBar(this.state)} ` : "",
|
|
1151
1142
|
`${symbol(this.state)} `
|
|
1152
1143
|
), r2 = `${t2 ? `${styleText2("gray", S_BAR)}
|
|
1153
|
-
` : ""}${
|
|
1154
|
-
`, l2 = this.value ?? [],
|
|
1144
|
+
` : ""}${a3}
|
|
1145
|
+
`, l2 = this.value ?? [], p = (i2, u3) => {
|
|
1155
1146
|
if (i2.disabled)
|
|
1156
|
-
return
|
|
1147
|
+
return o2(i2, "disabled");
|
|
1157
1148
|
const s = l2.includes(i2.value);
|
|
1158
|
-
return u3 && s ?
|
|
1149
|
+
return u3 && s ? o2(i2, "active-selected") : s ? o2(i2, "selected") : o2(i2, u3 ? "active" : "inactive");
|
|
1159
1150
|
};
|
|
1160
1151
|
switch (this.state) {
|
|
1161
1152
|
case "submit": {
|
|
1162
|
-
const i2 = this.options.filter(({ value: s }) => l2.includes(s)).map((s) =>
|
|
1153
|
+
const i2 = this.options.filter(({ value: s }) => l2.includes(s)).map((s) => o2(s, "submitted")).join(styleText2("dim", ", ")) || styleText2("dim", "none"), u3 = wrapTextWithPrefix(
|
|
1163
1154
|
n2.output,
|
|
1164
1155
|
i2,
|
|
1165
1156
|
t2 ? `${styleText2("gray", S_BAR)} ` : ""
|
|
@@ -1167,7 +1158,7 @@ ${styleText2(
|
|
|
1167
1158
|
return `${r2}${u3}`;
|
|
1168
1159
|
}
|
|
1169
1160
|
case "cancel": {
|
|
1170
|
-
const i2 = this.options.filter(({ value: s }) => l2.includes(s)).map((s) =>
|
|
1161
|
+
const i2 = this.options.filter(({ value: s }) => l2.includes(s)).map((s) => o2(s, "cancelled")).join(styleText2("dim", ", "));
|
|
1171
1162
|
if (i2.trim() === "")
|
|
1172
1163
|
return `${r2}${styleText2("gray", S_BAR)}`;
|
|
1173
1164
|
const u3 = wrapTextWithPrefix(
|
|
@@ -1181,10 +1172,10 @@ ${styleText2("gray", S_BAR)}` : ""}`;
|
|
|
1181
1172
|
case "error": {
|
|
1182
1173
|
const i2 = t2 ? `${styleText2("yellow", S_BAR)} ` : "", u3 = this.error.split(`
|
|
1183
1174
|
`).map(
|
|
1184
|
-
(
|
|
1175
|
+
($, x) => x === 0 ? `${t2 ? `${styleText2("yellow", S_BAR_END)} ` : ""}${styleText2("yellow", $)}` : ` ${$}`
|
|
1185
1176
|
).join(`
|
|
1186
1177
|
`), s = r2.split(`
|
|
1187
|
-
`).length,
|
|
1178
|
+
`).length, g = u3.split(`
|
|
1188
1179
|
`).length + 1;
|
|
1189
1180
|
return `${r2}${i2}${limitOptions({
|
|
1190
1181
|
output: n2.output,
|
|
@@ -1192,8 +1183,8 @@ ${styleText2("gray", S_BAR)}` : ""}`;
|
|
|
1192
1183
|
cursor: this.cursor,
|
|
1193
1184
|
maxItems: n2.maxItems,
|
|
1194
1185
|
columnPadding: i2.length,
|
|
1195
|
-
rowPadding: s +
|
|
1196
|
-
style:
|
|
1186
|
+
rowPadding: s + g,
|
|
1187
|
+
style: p
|
|
1197
1188
|
}).join(`
|
|
1198
1189
|
${i2}`)}
|
|
1199
1190
|
${u3}
|
|
@@ -1201,53 +1192,72 @@ ${u3}
|
|
|
1201
1192
|
}
|
|
1202
1193
|
default: {
|
|
1203
1194
|
const i2 = t2 ? `${styleText2("cyan", S_BAR)} ` : "", u3 = r2.split(`
|
|
1204
|
-
`).length, s = t2
|
|
1195
|
+
`).length, s = formatInstructionFooter(MULTISELECT_INSTRUCTIONS, t2), g = s.join(`
|
|
1196
|
+
`), $ = s.length + 1;
|
|
1205
1197
|
return `${r2}${i2}${limitOptions({
|
|
1206
1198
|
output: n2.output,
|
|
1207
1199
|
options: this.options,
|
|
1208
1200
|
cursor: this.cursor,
|
|
1209
1201
|
maxItems: n2.maxItems,
|
|
1210
1202
|
columnPadding: i2.length,
|
|
1211
|
-
rowPadding: u3 +
|
|
1212
|
-
style:
|
|
1203
|
+
rowPadding: u3 + $,
|
|
1204
|
+
style: p
|
|
1213
1205
|
}).join(`
|
|
1214
1206
|
${i2}`)}
|
|
1215
|
-
${
|
|
1207
|
+
${g}
|
|
1216
1208
|
`;
|
|
1217
1209
|
}
|
|
1218
1210
|
}
|
|
1219
1211
|
}
|
|
1220
1212
|
}).prompt();
|
|
1221
1213
|
};
|
|
1222
|
-
var
|
|
1214
|
+
var cancel = (o2 = "", t2) => {
|
|
1215
|
+
const i2 = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR_END)} ` : "";
|
|
1216
|
+
i2.write(`${e}${styleText2("red", o2)}
|
|
1217
|
+
|
|
1218
|
+
`);
|
|
1219
|
+
};
|
|
1220
|
+
var intro = (o2 = "", t2) => {
|
|
1221
|
+
const i2 = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR_START)} ` : "";
|
|
1222
|
+
i2.write(`${e}${o2}
|
|
1223
|
+
`);
|
|
1224
|
+
};
|
|
1225
|
+
var outro = (o2 = "", t2) => {
|
|
1226
|
+
const i2 = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR)}
|
|
1227
|
+
${styleText2("gray", S_BAR_END)} ` : "";
|
|
1228
|
+
i2.write(`${e}${o2}
|
|
1229
|
+
|
|
1230
|
+
`);
|
|
1231
|
+
};
|
|
1232
|
+
var W$1 = (o2) => o2;
|
|
1223
1233
|
var C = (o2, e, s) => {
|
|
1224
1234
|
const a3 = {
|
|
1225
1235
|
hard: true,
|
|
1226
1236
|
trim: false
|
|
1227
1237
|
}, i2 = wrapAnsi(o2, e, a3).split(`
|
|
1228
|
-
`), c2 = i2.reduce((n2,
|
|
1238
|
+
`), c2 = i2.reduce((n2, t2) => Math.max(dist_default2(t2), n2), 0), u3 = i2.map(s).reduce((n2, t2) => Math.max(dist_default2(t2), n2), 0), g = e - (u3 - c2);
|
|
1229
1239
|
return wrapAnsi(o2, g, a3);
|
|
1230
1240
|
};
|
|
1231
1241
|
var note = (o2 = "", e = "", s) => {
|
|
1232
1242
|
const a3 = s?.output ?? process$1.stdout, i2 = s?.withGuide ?? settings.withGuide, c2 = s?.format ?? W$1, g = ["", ...C(o2, getColumns(a3) - 6, c2).split(`
|
|
1233
|
-
`).map(c2), ""], n2 = dist_default2(e),
|
|
1234
|
-
g.reduce((
|
|
1243
|
+
`).map(c2), ""], n2 = dist_default2(e), t2 = Math.max(
|
|
1244
|
+
g.reduce((m2, F) => {
|
|
1235
1245
|
const O = dist_default2(F);
|
|
1236
|
-
return O >
|
|
1246
|
+
return O > m2 ? O : m2;
|
|
1237
1247
|
}, 0),
|
|
1238
1248
|
n2
|
|
1239
1249
|
) + 2, h2 = g.map(
|
|
1240
|
-
(
|
|
1250
|
+
(m2) => `${styleText2("gray", S_BAR)} ${m2}${" ".repeat(t2 - dist_default2(m2))}${styleText2("gray", S_BAR)}`
|
|
1241
1251
|
).join(`
|
|
1242
1252
|
`), T = i2 ? `${styleText2("gray", S_BAR)}
|
|
1243
1253
|
` : "", l$1 = i2 ? S_CONNECT_LEFT : S_CORNER_BOTTOM_LEFT;
|
|
1244
1254
|
a3.write(
|
|
1245
1255
|
`${T}${styleText2("green", S_STEP_SUBMIT)} ${styleText2("reset", e)} ${styleText2(
|
|
1246
1256
|
"gray",
|
|
1247
|
-
S_BAR_H.repeat(Math.max(
|
|
1257
|
+
S_BAR_H.repeat(Math.max(t2 - n2 - 1, 1)) + S_CORNER_TOP_RIGHT
|
|
1248
1258
|
)}
|
|
1249
1259
|
${h2}
|
|
1250
|
-
${styleText2("gray", l$1 + S_BAR_H.repeat(
|
|
1260
|
+
${styleText2("gray", l$1 + S_BAR_H.repeat(t2 + 2) + S_CORNER_BOTTOM_RIGHT)}
|
|
1251
1261
|
`
|
|
1252
1262
|
);
|
|
1253
1263
|
};
|
|
@@ -1260,18 +1270,18 @@ var spinner = ({
|
|
|
1260
1270
|
errorMessage: O,
|
|
1261
1271
|
frames: E = unicode ? ["\u25D2", "\u25D0", "\u25D3", "\u25D1"] : ["\u2022", "o", "O", "0"],
|
|
1262
1272
|
delay: F = unicode ? 80 : 120,
|
|
1263
|
-
signal:
|
|
1273
|
+
signal: m2,
|
|
1264
1274
|
...I
|
|
1265
1275
|
} = {}) => {
|
|
1266
1276
|
const u3 = isCI();
|
|
1267
|
-
let M, T,
|
|
1277
|
+
let M, T, d = false, S = false, s = "", p, w = performance.now();
|
|
1268
1278
|
const x = getColumns(n2), k = I?.styleFrame ?? W, g = (e) => {
|
|
1269
1279
|
const r2 = e > 1 ? O ?? settings.messages.error : G ?? settings.messages.cancel;
|
|
1270
|
-
S = e === 1,
|
|
1280
|
+
S = e === 1, d && (a3(r2, e), S && typeof h2 == "function" && h2());
|
|
1271
1281
|
}, f = () => g(2), i2 = () => g(1), A = () => {
|
|
1272
|
-
process.on("uncaughtExceptionMonitor", f), process.on("unhandledRejection", f), process.on("SIGINT", i2), process.on("SIGTERM", i2), process.on("exit", g),
|
|
1282
|
+
process.on("uncaughtExceptionMonitor", f), process.on("unhandledRejection", f), process.on("SIGINT", i2), process.on("SIGTERM", i2), process.on("exit", g), m2 && m2.addEventListener("abort", i2);
|
|
1273
1283
|
}, H = () => {
|
|
1274
|
-
process.removeListener("uncaughtExceptionMonitor", f), process.removeListener("unhandledRejection", f), process.removeListener("SIGINT", i2), process.removeListener("SIGTERM", i2), process.removeListener("exit", g),
|
|
1284
|
+
process.removeListener("uncaughtExceptionMonitor", f), process.removeListener("unhandledRejection", f), process.removeListener("SIGINT", i2), process.removeListener("SIGTERM", i2), process.removeListener("exit", g), m2 && m2.removeEventListener("abort", i2);
|
|
1275
1285
|
}, y = () => {
|
|
1276
1286
|
if (p === void 0) return;
|
|
1277
1287
|
u3 && n2.write(`
|
|
@@ -1286,7 +1296,7 @@ var spinner = ({
|
|
|
1286
1296
|
const r2 = (performance.now() - e) / 1e3, t2 = Math.floor(r2 / 60), o2 = Math.floor(r2 % 60);
|
|
1287
1297
|
return t2 > 0 ? `[${t2}m ${o2}s]` : `[${o2}s]`;
|
|
1288
1298
|
}, N = I.withGuide ?? settings.withGuide, P = (e = "") => {
|
|
1289
|
-
|
|
1299
|
+
d = true, M = block({ output: n2 }), s = C2(e), w = performance.now(), N && n2.write(`${styleText2("gray", S_BAR)}
|
|
1290
1300
|
`);
|
|
1291
1301
|
let r2 = 0, t2 = 0;
|
|
1292
1302
|
A(), T = setInterval(() => {
|
|
@@ -1310,8 +1320,8 @@ var spinner = ({
|
|
|
1310
1320
|
n2.write(j), r2 = r2 + 1 < E.length ? r2 + 1 : 0, t2 = t2 < 4 ? t2 + 0.125 : 0;
|
|
1311
1321
|
}, F);
|
|
1312
1322
|
}, a3 = (e = "", r2 = 0, t2 = false) => {
|
|
1313
|
-
if (!
|
|
1314
|
-
|
|
1323
|
+
if (!d) return;
|
|
1324
|
+
d = false, clearInterval(T), y();
|
|
1315
1325
|
const o2 = r2 === 0 ? styleText2("green", S_STEP_SUBMIT) : r2 === 1 ? styleText2("red", S_STEP_CANCEL) : styleText2("red", S_STEP_ERROR);
|
|
1316
1326
|
s = e ?? s, t2 || (l2 === "timer" ? n2.write(`${o2} ${s} ${_(w)}
|
|
1317
1327
|
`) : n2.write(`${o2} ${s}
|
|
@@ -1336,20 +1346,24 @@ var u2 = {
|
|
|
1336
1346
|
heavy: unicodeOr("\u2501", "="),
|
|
1337
1347
|
block: unicodeOr("\u2588", "#")
|
|
1338
1348
|
};
|
|
1339
|
-
var
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
var
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1349
|
+
var SELECT_INSTRUCTIONS = [
|
|
1350
|
+
`${styleText2("dim", "\u2191/\u2193")} to navigate`,
|
|
1351
|
+
`${styleText2("dim", "Enter:")} confirm`
|
|
1352
|
+
];
|
|
1353
|
+
var c = (t2, a3) => t2.includes(`
|
|
1354
|
+
`) ? t2.split(`
|
|
1355
|
+
`).map((i2) => a3(i2)).join(`
|
|
1356
|
+
`) : a3(t2);
|
|
1357
|
+
var select = (t2) => {
|
|
1358
|
+
const a3 = (i2, m2) => {
|
|
1359
|
+
const s = i2.label ?? String(i2.value);
|
|
1360
|
+
switch (m2) {
|
|
1347
1361
|
case "disabled":
|
|
1348
|
-
return `${styleText2("gray", S_RADIO_INACTIVE)} ${c(s, (n2) => styleText2("gray", n2))}${
|
|
1362
|
+
return `${styleText2("gray", S_RADIO_INACTIVE)} ${c(s, (n2) => styleText2("gray", n2))}${i2.hint ? ` ${styleText2("dim", `(${i2.hint ?? "disabled"})`)}` : ""}`;
|
|
1349
1363
|
case "selected":
|
|
1350
1364
|
return `${c(s, (n2) => styleText2("dim", n2))}`;
|
|
1351
1365
|
case "active":
|
|
1352
|
-
return `${styleText2("green", S_RADIO_ACTIVE)} ${s}${
|
|
1366
|
+
return `${styleText2("green", S_RADIO_ACTIVE)} ${s}${i2.hint ? ` ${styleText2("dim", `(${i2.hint})`)}` : ""}`;
|
|
1353
1367
|
case "cancelled":
|
|
1354
1368
|
return `${c(s, (n2) => styleText2(["strikethrough", "dim"], n2))}`;
|
|
1355
1369
|
default:
|
|
@@ -1357,52 +1371,53 @@ var select = (e) => {
|
|
|
1357
1371
|
}
|
|
1358
1372
|
};
|
|
1359
1373
|
return new a2({
|
|
1360
|
-
options:
|
|
1361
|
-
signal:
|
|
1362
|
-
input:
|
|
1363
|
-
output:
|
|
1364
|
-
initialValue:
|
|
1374
|
+
options: t2.options,
|
|
1375
|
+
signal: t2.signal,
|
|
1376
|
+
input: t2.input,
|
|
1377
|
+
output: t2.output,
|
|
1378
|
+
initialValue: t2.initialValue,
|
|
1365
1379
|
render() {
|
|
1366
|
-
const
|
|
1367
|
-
|
|
1368
|
-
|
|
1380
|
+
const i2 = t2.withGuide ?? settings.withGuide, m2 = `${symbol(this.state)} `, s = `${symbolBar(this.state)} `, n2 = wrapTextWithPrefix(
|
|
1381
|
+
t2.output,
|
|
1382
|
+
t2.message,
|
|
1369
1383
|
s,
|
|
1370
|
-
|
|
1371
|
-
), u3 = `${
|
|
1384
|
+
m2
|
|
1385
|
+
), u3 = `${i2 ? `${styleText2("gray", S_BAR)}
|
|
1372
1386
|
` : ""}${n2}
|
|
1373
1387
|
`;
|
|
1374
1388
|
switch (this.state) {
|
|
1375
1389
|
case "submit": {
|
|
1376
|
-
const r2 =
|
|
1377
|
-
|
|
1390
|
+
const r2 = i2 ? `${styleText2("gray", S_BAR)} ` : "", o2 = wrapTextWithPrefix(
|
|
1391
|
+
t2.output,
|
|
1378
1392
|
a3(this.options[this.cursor], "selected"),
|
|
1379
1393
|
r2
|
|
1380
1394
|
);
|
|
1381
|
-
return `${u3}${
|
|
1395
|
+
return `${u3}${o2}`;
|
|
1382
1396
|
}
|
|
1383
1397
|
case "cancel": {
|
|
1384
|
-
const r2 =
|
|
1385
|
-
|
|
1398
|
+
const r2 = i2 ? `${styleText2("gray", S_BAR)} ` : "", o2 = wrapTextWithPrefix(
|
|
1399
|
+
t2.output,
|
|
1386
1400
|
a3(this.options[this.cursor], "cancelled"),
|
|
1387
1401
|
r2
|
|
1388
1402
|
);
|
|
1389
|
-
return `${u3}${
|
|
1403
|
+
return `${u3}${o2}${i2 ? `
|
|
1390
1404
|
${styleText2("gray", S_BAR)}` : ""}`;
|
|
1391
1405
|
}
|
|
1392
1406
|
default: {
|
|
1393
|
-
const r2 =
|
|
1394
|
-
`).length,
|
|
1407
|
+
const r2 = i2 ? `${styleText2("cyan", S_BAR)} ` : "", o2 = u3.split(`
|
|
1408
|
+
`).length, $ = formatInstructionFooter(SELECT_INSTRUCTIONS, i2), h2 = $.join(`
|
|
1409
|
+
`), b = $.length + 1;
|
|
1395
1410
|
return `${u3}${r2}${limitOptions({
|
|
1396
|
-
output:
|
|
1411
|
+
output: t2.output,
|
|
1397
1412
|
cursor: this.cursor,
|
|
1398
1413
|
options: this.options,
|
|
1399
|
-
maxItems:
|
|
1414
|
+
maxItems: t2.maxItems,
|
|
1400
1415
|
columnPadding: r2.length,
|
|
1401
|
-
rowPadding:
|
|
1402
|
-
style: (p,
|
|
1416
|
+
rowPadding: o2 + b,
|
|
1417
|
+
style: (p, x) => a3(p, p.disabled ? "disabled" : x ? "active" : "inactive")
|
|
1403
1418
|
}).join(`
|
|
1404
1419
|
${r2}`)}
|
|
1405
|
-
${
|
|
1420
|
+
${h2}
|
|
1406
1421
|
`;
|
|
1407
1422
|
}
|
|
1408
1423
|
}
|
|
@@ -1424,10 +1439,10 @@ var text = (t2) => new n({
|
|
|
1424
1439
|
`, c2 = t2.placeholder ? styleText2("inverse", t2.placeholder[0]) + styleText2("dim", t2.placeholder.slice(1)) : styleText2(["inverse", "hidden"], "_"), o2 = this.userInput ? this.userInputWithCursor : c2, a3 = this.value ?? "";
|
|
1425
1440
|
switch (this.state) {
|
|
1426
1441
|
case "error": {
|
|
1427
|
-
const n2 = this.error ? ` ${styleText2("yellow", this.error)}` : "", r2 = i2 ? `${styleText2("yellow", S_BAR)} ` : "",
|
|
1442
|
+
const n2 = this.error ? ` ${styleText2("yellow", this.error)}` : "", r2 = i2 ? `${styleText2("yellow", S_BAR)} ` : "", d = i2 ? styleText2("yellow", S_BAR_END) : "";
|
|
1428
1443
|
return `${s.trim()}
|
|
1429
1444
|
${r2}${o2}
|
|
1430
|
-
${
|
|
1445
|
+
${d}${n2}
|
|
1431
1446
|
`;
|
|
1432
1447
|
}
|
|
1433
1448
|
case "submit": {
|
|
@@ -1588,11 +1603,11 @@ function capture(cmd, args, cwd) {
|
|
|
1588
1603
|
const child = onWindows ? spawn([cmd, ...args].join(" "), { cwd, shell: true }) : spawn(cmd, args, { cwd });
|
|
1589
1604
|
let stdout2 = "";
|
|
1590
1605
|
let stderr = "";
|
|
1591
|
-
child.stdout?.on("data", (
|
|
1592
|
-
stdout2 +=
|
|
1606
|
+
child.stdout?.on("data", (d) => {
|
|
1607
|
+
stdout2 += d.toString();
|
|
1593
1608
|
});
|
|
1594
|
-
child.stderr?.on("data", (
|
|
1595
|
-
stderr +=
|
|
1609
|
+
child.stderr?.on("data", (d) => {
|
|
1610
|
+
stderr += d.toString();
|
|
1596
1611
|
});
|
|
1597
1612
|
child.on("error", reject);
|
|
1598
1613
|
child.on("close", (code) => {
|
|
@@ -1680,9 +1695,7 @@ function visibleWidth(s) {
|
|
|
1680
1695
|
function box(lines, paint = (s) => s) {
|
|
1681
1696
|
const width = lines.reduce((w, l2) => Math.max(w, visibleWidth(l2)), 0);
|
|
1682
1697
|
const side = paint("\u2502");
|
|
1683
|
-
const body = lines.map(
|
|
1684
|
-
(l2) => ` ${side} ${l2}${" ".repeat(width - visibleWidth(l2))} ${side}`
|
|
1685
|
-
);
|
|
1698
|
+
const body = lines.map((l2) => ` ${side} ${l2}${" ".repeat(width - visibleWidth(l2))} ${side}`);
|
|
1686
1699
|
return [
|
|
1687
1700
|
" " + paint(`\u256D${"\u2500".repeat(width + 4)}\u256E`),
|
|
1688
1701
|
...body,
|
|
@@ -2025,7 +2038,7 @@ function scaffold(name, template, features, aiTools, images) {
|
|
|
2025
2038
|
"@types/react-dom": "^19.2.3",
|
|
2026
2039
|
eslint: "^10.2.0",
|
|
2027
2040
|
prettier: "^3.8.1",
|
|
2028
|
-
toilscript: "^0.1.
|
|
2041
|
+
toilscript: "^0.1.35",
|
|
2029
2042
|
typescript: "^6.0.3"
|
|
2030
2043
|
};
|
|
2031
2044
|
for (const dep of requiredPackages(features).sort()) {
|
|
@@ -2067,9 +2080,18 @@ export default defineConfig({
|
|
|
2067
2080
|
// Generated files don't need formatting. (toilscript server decorators like @main /
|
|
2068
2081
|
// @remote-on-functions are handled by the toiljs/prettier-plugin, so server/ is not ignored.)
|
|
2069
2082
|
".prettierignore": "node_modules\nbuild\n.toil\nshared/server.ts\ntoil-env.d.ts\ntoil-routes.d.ts\nserver/_emails.ts\nserver/toil-server-env.d.ts\n",
|
|
2070
|
-
".gitignore": "node_modules\nbuild\n.toil\nshared/server.ts\ntoil-env.d.ts\ntoil-routes.d.ts\n# Local dev env vars/secrets (never commit)\n.env\n.env.secrets\n",
|
|
2071
|
-
// Use the project's pinned TypeScript (node_modules) instead of VS Code's bundled
|
|
2072
|
-
|
|
2083
|
+
".gitignore": "node_modules\nbuild\n.toil\nshared/server.ts\ntoil-env.d.ts\ntoil-routes.d.ts\nhosts/*/_tmpl/\n# Local dev env vars/secrets (never commit)\n.env\n.env.secrets\n",
|
|
2084
|
+
// Use the project's pinned TypeScript (node_modules) instead of VS Code's bundled
|
|
2085
|
+
// version, and prompt to switch, so the editor loads the toilscript LS plugin wired
|
|
2086
|
+
// in server/tsconfig.json (which clears the @database / @data editor false positives).
|
|
2087
|
+
".vscode/settings.json": JSON.stringify(
|
|
2088
|
+
{
|
|
2089
|
+
"typescript.tsdk": "node_modules/typescript/lib",
|
|
2090
|
+
"typescript.enablePromptUseWorkspaceTsdk": true
|
|
2091
|
+
},
|
|
2092
|
+
null,
|
|
2093
|
+
4
|
|
2094
|
+
) + "\n",
|
|
2073
2095
|
"toil-env.d.ts": TOIL_ENV_DTS,
|
|
2074
2096
|
// Stub typed-routes augmentation (RoutePath = string until the first dev/build regenerates it).
|
|
2075
2097
|
"toil-routes.d.ts": "// AUTO-GENERATED by toil, do not edit.\nexport {};\n",
|
|
@@ -2120,9 +2142,15 @@ export default defineConfig({
|
|
|
2120
2142
|
null,
|
|
2121
2143
|
4
|
|
2122
2144
|
) + "\n",
|
|
2145
|
+
// The toilscript LS plugin teaches the editor about compiler-injected members
|
|
2146
|
+
// (`@database` static collections like `Db.users`, the `@data` codec, `@user`), so
|
|
2147
|
+
// stock TypeScript stops false-flagging them as TS2339. Editor-only; ignored by tsc.
|
|
2123
2148
|
"server/tsconfig.json": JSON.stringify(
|
|
2124
2149
|
{
|
|
2125
2150
|
extends: "toilscript/std/assembly.json",
|
|
2151
|
+
compilerOptions: {
|
|
2152
|
+
plugins: [{ name: "toilscript/std/ts-plugin.cjs" }]
|
|
2153
|
+
},
|
|
2126
2154
|
include: ["./**/*.ts"]
|
|
2127
2155
|
},
|
|
2128
2156
|
null,
|
|
@@ -2505,13 +2533,17 @@ import fs4 from "node:fs";
|
|
|
2505
2533
|
import { createRequire } from "node:module";
|
|
2506
2534
|
import path5 from "node:path";
|
|
2507
2535
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
2508
|
-
import {
|
|
2536
|
+
import {
|
|
2537
|
+
loadConfig as loadConfig2,
|
|
2538
|
+
scanRoutes,
|
|
2539
|
+
TOIL_SERVER_ENV_DTS as TOIL_SERVER_ENV_DTS2
|
|
2540
|
+
} from "toiljs/compiler";
|
|
2509
2541
|
|
|
2510
2542
|
// src/cli/diagnostics.ts
|
|
2511
2543
|
function parseVersion(v) {
|
|
2512
|
-
const
|
|
2513
|
-
if (!
|
|
2514
|
-
return [Number(
|
|
2544
|
+
const m2 = /(\d+)(?:\.(\d+))?(?:\.(\d+))?/.exec(v);
|
|
2545
|
+
if (!m2) return [0, 0, 0];
|
|
2546
|
+
return [Number(m2[1]), Number(m2[2] ?? 0), Number(m2[3] ?? 0)];
|
|
2515
2547
|
}
|
|
2516
2548
|
function satisfiesMin(version2, range) {
|
|
2517
2549
|
const [a3, b, c2] = parseVersion(version2);
|
|
@@ -2682,9 +2714,9 @@ function findRelativeAssets(files) {
|
|
|
2682
2714
|
const lines = file.source.split("\n");
|
|
2683
2715
|
for (let i2 = 0; i2 < lines.length; i2++) {
|
|
2684
2716
|
attr.lastIndex = 0;
|
|
2685
|
-
let
|
|
2686
|
-
while ((
|
|
2687
|
-
const value =
|
|
2717
|
+
let m2;
|
|
2718
|
+
while ((m2 = attr.exec(lines[i2])) !== null) {
|
|
2719
|
+
const value = m2[1] ?? m2[2] ?? "";
|
|
2688
2720
|
if (isBrokenRelativeAsset(value)) {
|
|
2689
2721
|
issues.push({ file: file.path, line: i2 + 1, value });
|
|
2690
2722
|
}
|
|
@@ -2838,6 +2870,27 @@ function checkRestDispatch(f) {
|
|
|
2838
2870
|
fix: "In your handler add `const hit = Rest.dispatch(req); if (hit != null) return hit;`, or set `Server.handler = () => new RestHandler()`."
|
|
2839
2871
|
};
|
|
2840
2872
|
}
|
|
2873
|
+
function checkServerTsPlugin(present) {
|
|
2874
|
+
return present ? { id: "server-ts-plugin", label: "toilscript editor plugin", status: "pass" } : {
|
|
2875
|
+
id: "server-ts-plugin",
|
|
2876
|
+
label: "toilscript editor plugin",
|
|
2877
|
+
status: "warn",
|
|
2878
|
+
detail: "server tsconfig is missing the toilscript LS plugin, so the editor wrongly flags @database static collections (e.g. GuestbookDb.totals) and @data members as TS2339",
|
|
2879
|
+
fix: 'Run `toiljs doctor --fix` to add { "plugins": [{ "name": "toilscript/std/ts-plugin.cjs" }] } to your server tsconfig, then pick the workspace TypeScript version and restart the TS server.'
|
|
2880
|
+
};
|
|
2881
|
+
}
|
|
2882
|
+
function checkAuthSecrets(f) {
|
|
2883
|
+
if (!f.usesAuth || f.sessionSecretSet) {
|
|
2884
|
+
return { id: "auth-secrets", label: "Session secret", status: "pass" };
|
|
2885
|
+
}
|
|
2886
|
+
return {
|
|
2887
|
+
id: "auth-secrets",
|
|
2888
|
+
label: "Session secret",
|
|
2889
|
+
status: "warn",
|
|
2890
|
+
detail: "auth is used but AUTH_SESSION_SECRET is unset: sessions fall back to a PUBLISHED key, so anyone can forge a session cookie and skip login",
|
|
2891
|
+
fix: `Set AUTH_SESSION_SECRET to a long random value in .env.secrets (local) and on your deploy target (also AUTH_OPRF_SEED / AUTH_KEM_SK if you use password login). Generate one: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))".`
|
|
2892
|
+
};
|
|
2893
|
+
}
|
|
2841
2894
|
function summarize(groups) {
|
|
2842
2895
|
let pass = 0;
|
|
2843
2896
|
let warn2 = 0;
|
|
@@ -2969,6 +3022,41 @@ function gatherRestFacts(root, toilconfig) {
|
|
|
2969
3022
|
}
|
|
2970
3023
|
return { hasControllers, dispatched };
|
|
2971
3024
|
}
|
|
3025
|
+
function secretDefined(root, key) {
|
|
3026
|
+
const raw = readFile(path5.join(root, ".env.secrets"));
|
|
3027
|
+
if (raw === null) return false;
|
|
3028
|
+
return new RegExp(`^\\s*(?:export\\s+)?${key}\\s*=\\s*\\S`, "m").test(raw);
|
|
3029
|
+
}
|
|
3030
|
+
function gatherAuthFacts(root, toilconfig) {
|
|
3031
|
+
let usesAuth = false;
|
|
3032
|
+
for (const src of serverSources(root, toilconfig)) {
|
|
3033
|
+
if (/\bAuthService\b/.test(src) || /@user\b/.test(src) || /@auth\b/.test(src)) {
|
|
3034
|
+
usesAuth = true;
|
|
3035
|
+
break;
|
|
3036
|
+
}
|
|
3037
|
+
}
|
|
3038
|
+
return { usesAuth, sessionSecretSet: secretDefined(root, "AUTH_SESSION_SECRET") };
|
|
3039
|
+
}
|
|
3040
|
+
var TS_PLUGIN_NAME = "toilscript/std/ts-plugin.cjs";
|
|
3041
|
+
function serverTsconfigPath(root, toilconfig) {
|
|
3042
|
+
const dirs = /* @__PURE__ */ new Set();
|
|
3043
|
+
const entries = Array.isArray(toilconfig?.entries) ? toilconfig.entries.filter((e) => typeof e === "string") : [];
|
|
3044
|
+
for (const e of entries) dirs.add(path5.dirname(path5.resolve(root, e)));
|
|
3045
|
+
if (dirs.size === 0) dirs.add(path5.join(root, "server"));
|
|
3046
|
+
for (const dir of dirs) {
|
|
3047
|
+
const p = path5.join(dir, "tsconfig.json");
|
|
3048
|
+
if (fs4.existsSync(p)) return p;
|
|
3049
|
+
}
|
|
3050
|
+
return null;
|
|
3051
|
+
}
|
|
3052
|
+
function tsconfigHasToilPlugin(tsconfig) {
|
|
3053
|
+
const plugins = asRecord(tsconfig?.compilerOptions)?.plugins;
|
|
3054
|
+
if (!Array.isArray(plugins)) return false;
|
|
3055
|
+
return plugins.some((p) => {
|
|
3056
|
+
const name = asRecord(p)?.name;
|
|
3057
|
+
return typeof name === "string" && name.includes("ts-plugin");
|
|
3058
|
+
});
|
|
3059
|
+
}
|
|
2972
3060
|
function applyRpcFix(root) {
|
|
2973
3061
|
const changed = [];
|
|
2974
3062
|
const skipped = [];
|
|
@@ -3064,7 +3152,9 @@ function applyRpcFix(root) {
|
|
|
3064
3152
|
}
|
|
3065
3153
|
const serverToilconfig = readJsonObject(path5.join(root, "toilconfig.json"));
|
|
3066
3154
|
if (serverToilconfig !== null) {
|
|
3067
|
-
const entries = Array.isArray(serverToilconfig.entries) ? serverToilconfig.entries.filter(
|
|
3155
|
+
const entries = Array.isArray(serverToilconfig.entries) ? serverToilconfig.entries.filter(
|
|
3156
|
+
(e) => typeof e === "string"
|
|
3157
|
+
) : [];
|
|
3068
3158
|
const dirs = /* @__PURE__ */ new Set();
|
|
3069
3159
|
for (const e of entries) dirs.add(path5.dirname(path5.resolve(root, e)));
|
|
3070
3160
|
if (dirs.size === 0) dirs.add(path5.join(root, "server"));
|
|
@@ -3154,6 +3244,50 @@ function applyPrettierFix(root, pkg) {
|
|
|
3154
3244
|
changed.push(".prettierrc.json");
|
|
3155
3245
|
return { changed, skipped };
|
|
3156
3246
|
}
|
|
3247
|
+
function applyServerEditorFix(root, toilconfig) {
|
|
3248
|
+
const changed = [];
|
|
3249
|
+
const skipped = [];
|
|
3250
|
+
const tsPath = serverTsconfigPath(root, toilconfig);
|
|
3251
|
+
if (tsPath === null) {
|
|
3252
|
+
skipped.push("server/tsconfig.json (not found; add the toilscript ts-plugin by hand)");
|
|
3253
|
+
} else {
|
|
3254
|
+
const rel = path5.relative(root, tsPath);
|
|
3255
|
+
const raw = readFile(tsPath);
|
|
3256
|
+
const parsed = raw !== null ? readJsonObject(tsPath) : null;
|
|
3257
|
+
if (parsed === null) {
|
|
3258
|
+
skipped.push(`${rel} (JSON with comments; add the "${TS_PLUGIN_NAME}" plugin by hand)`);
|
|
3259
|
+
} else if (!tsconfigHasToilPlugin(parsed)) {
|
|
3260
|
+
const co = asRecord(parsed.compilerOptions) ?? {};
|
|
3261
|
+
const existingPlugins = Array.isArray(co.plugins) ? co.plugins : [];
|
|
3262
|
+
co.plugins = [...existingPlugins, { name: TS_PLUGIN_NAME }];
|
|
3263
|
+
parsed.compilerOptions = co;
|
|
3264
|
+
writeFile(tsPath, JSON.stringify(parsed, null, 4) + "\n");
|
|
3265
|
+
changed.push(rel);
|
|
3266
|
+
}
|
|
3267
|
+
}
|
|
3268
|
+
const vsPath = path5.join(root, ".vscode", "settings.json");
|
|
3269
|
+
const vsRaw = readFile(vsPath);
|
|
3270
|
+
const vs = vsRaw !== null ? readJsonObject(vsPath) : {};
|
|
3271
|
+
if (vs === null) {
|
|
3272
|
+
skipped.push(".vscode/settings.json (unparseable; set typescript.tsdk by hand)");
|
|
3273
|
+
} else {
|
|
3274
|
+
let touched = false;
|
|
3275
|
+
if (vs["typescript.tsdk"] !== "node_modules/typescript/lib") {
|
|
3276
|
+
vs["typescript.tsdk"] = "node_modules/typescript/lib";
|
|
3277
|
+
touched = true;
|
|
3278
|
+
}
|
|
3279
|
+
if (vs["typescript.enablePromptUseWorkspaceTsdk"] !== true) {
|
|
3280
|
+
vs["typescript.enablePromptUseWorkspaceTsdk"] = true;
|
|
3281
|
+
touched = true;
|
|
3282
|
+
}
|
|
3283
|
+
if (touched) {
|
|
3284
|
+
fs4.mkdirSync(path5.dirname(vsPath), { recursive: true });
|
|
3285
|
+
writeFile(vsPath, JSON.stringify(vs, null, 4) + "\n");
|
|
3286
|
+
changed.push(".vscode/settings.json");
|
|
3287
|
+
}
|
|
3288
|
+
}
|
|
3289
|
+
return { changed, skipped };
|
|
3290
|
+
}
|
|
3157
3291
|
function frameworkMeta() {
|
|
3158
3292
|
const pkgPath = path5.resolve(
|
|
3159
3293
|
path5.dirname(fileURLToPath3(import.meta.url)),
|
|
@@ -3288,15 +3422,28 @@ async function runDoctor(opts) {
|
|
|
3288
3422
|
const peerChecks = Object.keys(meta.peers).map(peerName);
|
|
3289
3423
|
const rpcFix = serverPresent && opts.fix ? applyRpcFix(root) : null;
|
|
3290
3424
|
const prettierFix = serverPresent && opts.fix ? applyPrettierFix(root, projectPkg) : null;
|
|
3425
|
+
const editorFix = serverPresent && opts.fix ? applyServerEditorFix(root, toilconfig) : null;
|
|
3291
3426
|
const rpcFacts = gatherRpcFacts(root);
|
|
3292
3427
|
const restFacts = gatherRestFacts(root, toilconfig);
|
|
3428
|
+
const authFacts = gatherAuthFacts(root, toilconfig);
|
|
3293
3429
|
const prettierPresent = prettierPluginPresent(
|
|
3294
3430
|
root,
|
|
3295
3431
|
readJsonObject(path5.join(root, "package.json"))
|
|
3296
3432
|
);
|
|
3297
|
-
const
|
|
3298
|
-
|
|
3299
|
-
|
|
3433
|
+
const serverTsPath = serverPresent ? serverTsconfigPath(root, toilconfig) : null;
|
|
3434
|
+
const serverTsParsed = serverTsPath ? readJsonObject(serverTsPath) : null;
|
|
3435
|
+
const serverTsPluginPresent = serverTsPath === null || serverTsParsed === null ? true : tsconfigHasToilPlugin(serverTsParsed);
|
|
3436
|
+
const serverFix = rpcFix || prettierFix || editorFix ? {
|
|
3437
|
+
changed: [
|
|
3438
|
+
...rpcFix?.changed ?? [],
|
|
3439
|
+
...prettierFix?.changed ?? [],
|
|
3440
|
+
...editorFix?.changed ?? []
|
|
3441
|
+
],
|
|
3442
|
+
skipped: [
|
|
3443
|
+
...rpcFix?.skipped ?? [],
|
|
3444
|
+
...prettierFix?.skipped ?? [],
|
|
3445
|
+
...editorFix?.skipped ?? []
|
|
3446
|
+
]
|
|
3300
3447
|
} : null;
|
|
3301
3448
|
const groups = [
|
|
3302
3449
|
{
|
|
@@ -3354,10 +3501,14 @@ async function runDoctor(opts) {
|
|
|
3354
3501
|
checkWasmBuilt(wasmExists),
|
|
3355
3502
|
checkRpcWiring(rpcFacts),
|
|
3356
3503
|
checkRestDispatch(restFacts),
|
|
3357
|
-
checkPrettierPlugin(prettierPresent)
|
|
3504
|
+
checkPrettierPlugin(prettierPresent),
|
|
3505
|
+
checkServerTsPlugin(serverTsPluginPresent)
|
|
3358
3506
|
] : [checkToilconfig(false)]
|
|
3359
3507
|
}
|
|
3360
3508
|
];
|
|
3509
|
+
if (serverPresent) {
|
|
3510
|
+
groups.push({ title: "Security", checks: [checkAuthSecrets(authFacts)] });
|
|
3511
|
+
}
|
|
3361
3512
|
const summary = summarize(groups);
|
|
3362
3513
|
if (opts.json) {
|
|
3363
3514
|
process.stdout.write(JSON.stringify({ groups, summary, fixed: serverFix }, null, 2) + "\n");
|
|
@@ -3376,14 +3527,14 @@ async function runDoctor(opts) {
|
|
|
3376
3527
|
function renderRpcFix(result) {
|
|
3377
3528
|
const out = [];
|
|
3378
3529
|
if (result.changed.length > 0) {
|
|
3379
|
-
out.push(" " + success("fixed
|
|
3530
|
+
out.push(" " + success("fixed server wiring") + dim(` ${result.changed.join(", ")}`));
|
|
3380
3531
|
if (result.changed.includes("package.json")) {
|
|
3381
3532
|
out.push(
|
|
3382
3533
|
" " + dim("run your installer (npm/pnpm/yarn) if the toilscript version changed.")
|
|
3383
3534
|
);
|
|
3384
3535
|
}
|
|
3385
3536
|
} else {
|
|
3386
|
-
out.push(" " + dim("
|
|
3537
|
+
out.push(" " + dim("server wiring already in place, nothing to fix."));
|
|
3387
3538
|
}
|
|
3388
3539
|
for (const item of result.skipped) out.push(" " + warn("skipped") + dim(` ${item}`));
|
|
3389
3540
|
process.stdout.write(out.join("\n") + "\n\n");
|
|
@@ -3401,9 +3552,9 @@ import path6 from "node:path";
|
|
|
3401
3552
|
|
|
3402
3553
|
// src/cli/updates.ts
|
|
3403
3554
|
function parseVersion2(v) {
|
|
3404
|
-
const
|
|
3405
|
-
if (!
|
|
3406
|
-
return [Number(
|
|
3555
|
+
const m2 = /(\d+)(?:\.(\d+))?(?:\.(\d+))?/.exec(v);
|
|
3556
|
+
if (!m2) return [0, 0, 0];
|
|
3557
|
+
return [Number(m2[1]), Number(m2[2] ?? 0), Number(m2[3] ?? 0)];
|
|
3407
3558
|
}
|
|
3408
3559
|
function classifyBump(from, to) {
|
|
3409
3560
|
const [fa, fb, fc] = parseVersion2(from);
|
|
@@ -3569,9 +3720,9 @@ function isCacheFresh(cache, now, ttlMs = CHECK_TTL_MS) {
|
|
|
3569
3720
|
return cache.checkedAt <= now && now - cache.checkedAt < ttlMs;
|
|
3570
3721
|
}
|
|
3571
3722
|
function parseSemver(v) {
|
|
3572
|
-
const
|
|
3573
|
-
if (!
|
|
3574
|
-
return { nums: [Number(
|
|
3723
|
+
const m2 = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?/.exec(v.trim());
|
|
3724
|
+
if (!m2) return { nums: [0, 0, 0], pre: null };
|
|
3725
|
+
return { nums: [Number(m2[1]), Number(m2[2]), Number(m2[3])], pre: m2[4] ?? null };
|
|
3575
3726
|
}
|
|
3576
3727
|
function compareSemver(a3, b) {
|
|
3577
3728
|
const pa = parseSemver(a3);
|