@voltro/cli 0.36.0 → 0.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +182 -0
- package/dist/{apiBuild-DiE9zcj6.js → apiBuild-CvacV4zA.js} +2 -2
- package/dist/apiBuild-ttSDDOGp.js +2 -0
- package/dist/{baselineCommand-DIttzO8A.js → baselineCommand-C6NMt-oa.js} +1 -4
- package/dist/baselineCommand-Cfw2Afwm.js +2 -0
- package/dist/bin.js +1 -1
- package/dist/bootRefusal-pgvDxlrU.js +7 -0
- package/dist/{build-DBe6c7qC.js → build-_LoTC1s0.js} +31 -31
- package/dist/{checkCommand-BhG0gmUD.js → checkCommand-Pjk5sBl2.js} +3 -3
- package/dist/{checkCommand-BTA6P3Yr.js → checkCommand-wibtQx-N.js} +1 -1
- package/dist/{cloudCmd-Cvv5HGaZ.js → cloudCmd-NQSwe_Qk.js} +1 -1
- package/dist/{codegen-CYM3Zqrf.js → codegen-GYYcdpCg.js} +2 -2
- package/dist/codegen-uYrrDzQv.js +2 -0
- package/dist/{codegenCommand-DH-8ZXzR.js → codegenCommand-C60m_LCp.js} +2 -2
- package/dist/{codemodRunner-DjQGrdmg.js → codemodRunner-CXgQ-ecJ.js} +339 -167
- package/dist/{commands-Bp7utV-7.js → commands-DaZVi9wi.js} +74 -73
- package/dist/{dashboardCommand-D5Jwjmr1.js → dashboardCommand-Dxy_kmoW.js} +3 -3
- package/dist/{dataCommand-DnCm0B2C.js → dataCommand-D6-Ha2lf.js} +2 -2
- package/dist/{dbCommand-O8HA63s2.js → dbCommand-C4UW8cVN.js} +353 -351
- package/dist/dbCommand-CC-qNzpz.js +2 -0
- package/dist/{dev-BSFTgCQ5.js → dev-CAOoXOkc.js} +1 -1
- package/dist/{dev-Dc4cpmRl.js → dev-E7Eo5GHc.js} +262 -261
- package/dist/doctorCommand-Cjl8Yii8.js +2 -0
- package/dist/{doctorCommand-CNFtt3nR.js → doctorCommand-gmDyALFL.js} +10 -10
- package/dist/{dormancyCommand-6F6NsJKf.js → dormancyCommand-CE6wG8lj.js} +1 -1
- package/dist/{embeddingsCommand-DRRdneJD.js → embeddingsCommand-C3uAuf6N.js} +1 -1
- package/dist/{envCommand-TZzcyqZ-.js → envCommand-DzuWh8ya.js} +19 -19
- package/dist/{evolveCommand-iU35TPjT.js → evolveCommand-DPLqcYb2.js} +2 -2
- package/dist/index.js +2 -2
- package/dist/{infoCommand-unqisJGp.js → infoCommand-CmczGj_l.js} +1 -1
- package/dist/inspectGateHint-BF6608UT.js +4 -0
- package/dist/{metaCommands-7MJfZ5cf.js → metaCommands-CIoQNlaQ.js} +1 -1
- package/dist/{migrate-BV7I-ZHZ.js → migrate-RwgUWXfc.js} +1 -1
- package/dist/{privacyCommand-C-Df56U_.js → privacyCommand-XejDMvmu.js} +4 -3
- package/dist/{probeCommand-CZfaaUOZ.js → probeCommand-BPEpwT32.js} +40 -39
- package/dist/{projectScaffold-DmzEKHib.js → projectScaffold-CxgtJvlb.js} +1 -1
- package/dist/{projectScaffold-LMMtaavR.js → projectScaffold-DDgWbNLe.js} +2 -2
- package/dist/{runtimeTrace-D5LJ_N55.js → runtimeTrace-6jfznSzr.js} +1 -1
- package/dist/{sdkgen-82xVuvbt.js → sdkgen-CEJZZQUA.js} +1 -1
- package/dist/serveCommand-DNRF2nDI.js +2 -0
- package/dist/{serveCommand-VVGcIMIw.js → serveCommand-DnY4VS3D.js} +541 -540
- package/dist/serveEntry.js +1 -1
- package/dist/{start-BgN62boB.js → start-CidwCcjl.js} +1 -1
- package/dist/{start-T4VesWiM.js → start-RCh6qKFe.js} +24 -24
- package/dist/startEntry.js +1 -1
- package/dist/startup.d.ts +40 -1
- package/dist/startup.js +2 -2
- package/dist/startupRunner-CEqQq7ax.js +108 -0
- package/dist/subcommandNames-CKG5Dz3a.js +27 -0
- package/dist/{templates-De8IR5-c.js → templates-BR-fb4SP.js} +1 -4
- package/dist/{test-CI6iDsYc.js → test-DIQ0jlkQ.js} +1 -1
- package/dist/updateCommand-B0J_T9Vs.js +2 -0
- package/dist/{updateCommand-CwnUK_mf.js → updateCommand-CmksX7m_.js} +1 -1
- package/dist/{webDev-Dybxew86.js → webDev-BKdD7c_a.js} +689 -691
- package/dist/webDev-CcJfdSjl2.js +2 -0
- package/dist/{webhooksCommand-di1CJVzu.js → webhooksCommand-BHeaF1ZJ.js} +1 -1
- package/package.json +35 -17
- package/templates/AGENTS.md +1 -1
- package/templates/agent-docs/_index.md +1 -1
- package/templates/agent-docs/cli.md +16 -0
- package/templates/agent-docs/data.md +30 -0
- package/templates/agent-docs/plugins/audit.md +50 -0
- package/templates/agent-docs/plugins/auth.md +4 -6
- package/templates/agent-docs/reference.md +3 -2
- package/templates/agent-docs/whats-new.md +59 -35
- package/templates/apps/api-ai/package.json +7 -7
- package/templates/apps/api-auth/package.json +8 -8
- package/templates/apps/api-backend/package.json +7 -7
- package/templates/apps/api-backend-deactivation/package.json +7 -7
- package/templates/apps/api-backend-mail/package.json +8 -8
- package/templates/apps/api-backend-mariadb/package.json +9 -9
- package/templates/apps/api-backend-sqlite/package.json +8 -8
- package/templates/apps/api-backend-storage/package.json +8 -8
- package/templates/apps/api-cms/package.json +10 -10
- package/templates/apps/api-cms/tests/content.write.test.ts +16 -2
- package/templates/apps/api-collab/mutations/documents.setBody.mutation.server.ts +11 -5
- package/templates/apps/api-collab/package.json +8 -8
- package/templates/apps/api-collab/tests/documents.setBody.test.ts +8 -2
- package/templates/apps/api-data-advanced/package.json +8 -8
- package/templates/apps/api-durable/package.json +8 -8
- package/templates/apps/api-feature-flags/package.json +9 -9
- package/templates/apps/api-governance/package.json +8 -8
- package/templates/apps/api-kv/package.json +8 -8
- package/templates/apps/api-moderation/package.json +8 -8
- package/templates/apps/api-observability/package.json +8 -8
- package/templates/apps/api-ratelimit/package.json +8 -8
- package/templates/apps/api-rbac/package.json +8 -8
- package/templates/apps/api-rest/package.json +7 -7
- package/templates/apps/api-saas/package.json +11 -11
- package/templates/apps/api-saas-starter/package.json +10 -10
- package/templates/apps/api-search/package.json +8 -8
- package/templates/apps/api-status/package.json +8 -8
- package/templates/apps/api-versioning/mutations/documents.update.mutation.server.ts +7 -5
- package/templates/apps/api-versioning/package.json +8 -8
- package/templates/apps/api-webhooks/package.json +9 -9
- package/templates/apps/changelog/package.json +6 -6
- package/templates/apps/edge-functions/package.json +2 -2
- package/templates/apps/frontend-admin/package.json +8 -8
- package/templates/apps/frontend-app/package.json +9 -9
- package/templates/apps/frontend-auth/package.json +8 -8
- package/templates/apps/frontend-blank/package.json +7 -7
- package/templates/apps/frontend-cms/package.json +9 -9
- package/templates/apps/frontend-collab/package.json +10 -10
- package/templates/apps/frontend-contact/package.json +7 -7
- package/templates/apps/frontend-dashboard/package.json +7 -7
- package/templates/apps/frontend-docs/package.json +7 -7
- package/templates/apps/frontend-i18n/package.json +6 -6
- package/templates/apps/frontend-landing/package.json +7 -7
- package/templates/apps/frontend-portal/package.json +8 -8
- package/templates/apps/frontend-saas/package.json +8 -8
- package/templates/apps/frontend-spa/package.json +7 -7
- package/templates/apps/frontend-ssr/package.json +7 -7
- package/templates/apps/frontend-ssr-api/package.json +8 -8
- package/templates/apps/frontend-static-blog/package.json +6 -6
- package/templates/apps/frontend-status/package.json +8 -8
- package/templates/apps/mobile-app/package.json +3 -3
- package/templates/patches/@effect__cluster@0.60.0.patch +51 -3
- package/dist/apiBuild-ZEZnCXn2.js +0 -2
- package/dist/baselineCommand-C2ClWZN3.js +0 -2
- package/dist/codegen-ChBi_hVa.js +0 -2
- package/dist/dbCommand-DS4b97Is.js +0 -2
- package/dist/doctorCommand-BYffQc0s.js +0 -2
- package/dist/serveCommand-CEBVP36A.js +0 -2
- package/dist/startupRunner-DPGFchOa.js +0 -71
- package/dist/updateCommand-CSBXVsYq.js +0 -2
- package/dist/webDev-BcykISYQ2.js +0 -2
package/dist/serveEntry.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as e } from "./loadEnv-D9nEOClM.js";
|
|
2
2
|
import { r as t } from "./appModuleLoader-C9r9mxZt.js";
|
|
3
3
|
import { i as n } from "./dialectDriver-CgXnDfec.js";
|
|
4
|
-
import { t as r } from "./serveCommand-
|
|
4
|
+
import { t as r } from "./serveCommand-DnY4VS3D.js";
|
|
5
5
|
export { e as loadDotEnv, t as registerAppModules, n as registerDriver, r as runServe };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { i as e, t } from "./nodeEnvironment-cGFAj1J8.js";
|
|
2
2
|
import { r as n } from "./appPort-B_HpJ_ck.js";
|
|
3
|
-
import { A as r, B as i, C as a, D as o, E as s, H as c, I as l, J as u, N as d, O as f, P as p, S as m, T as ee, U as h, V as g, a as _, b as v, d as y, f as b, i as x, j as S, k as te,
|
|
3
|
+
import { A as r, B as i, C as a, D as o, E as s, H as c, I as l, J as u, N as d, O as f, P as p, S as m, T as ee, U as h, V as g, a as _, b as v, d as y, f as b, i as x, j as S, k as te, lt as C, n as w, ot as ne, q as T, s as re, w as E, x as ie, y as ae, z as D } from "./webDev-BKdD7c_a.js";
|
|
4
4
|
import { o as O, t as k } from "./connectionConfig-UFlIEiys.js";
|
|
5
5
|
import { A, D as j, a as M, h as oe, j as N, k as se } from "./inspect-CjTYzAs_.js";
|
|
6
6
|
import { a as ce, c as P, d as le, f as ue, l as F, p as I, u as de } from "./renderModeScan-D7J1B7Kw.js";
|
|
@@ -210,10 +210,10 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
210
210
|
}, Ne = async (e) => {
|
|
211
211
|
let { provider: t, route: n, params: i, pathname: c, dirs: l, shellTemplate: u, requestHeaders: d, requestUrl: p = "", apiOrigin: ee, apiName: h } = e, { search: g } = r(p), v = x(ee, d.cookie, { apiName: h }), y = await t.getPage(n.pattern, n.file), b = P(y, n.file), S = b === "spa" && re(l, n.dirChain).some((e) => e.hasLayout);
|
|
212
212
|
if (b !== "ssr" && b !== "isr" && !S) return null;
|
|
213
|
-
let
|
|
213
|
+
let C = re(l, n.dirChain), w = {}, ne = null, T, ae = new AbortController();
|
|
214
214
|
try {
|
|
215
|
-
(await t.getHelpers()).beginStoreSeeds(), {chain:
|
|
216
|
-
entries:
|
|
215
|
+
(await t.getHelpers()).beginStoreSeeds(), {chain: T, segmentLoaderData: w} = await _({
|
|
216
|
+
entries: C,
|
|
217
217
|
loadLayout: (e) => t.getLayout(e.dir),
|
|
218
218
|
loadError: (e) => t.getError(e.dir),
|
|
219
219
|
loadPending: (e) => t.getPending(e.dir),
|
|
@@ -225,7 +225,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
225
225
|
headers: d,
|
|
226
226
|
query: v
|
|
227
227
|
}
|
|
228
|
-
}), typeof y.loader == "function" && !S && (
|
|
228
|
+
}), typeof y.loader == "function" && !S && (ne = await y.loader({
|
|
229
229
|
params: i,
|
|
230
230
|
pathname: c,
|
|
231
231
|
search: g,
|
|
@@ -243,7 +243,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
243
243
|
throw e;
|
|
244
244
|
}
|
|
245
245
|
let D = await t.getHelpers();
|
|
246
|
-
S || await
|
|
246
|
+
S || await ie({
|
|
247
247
|
pageMod: y,
|
|
248
248
|
params: i,
|
|
249
249
|
query: v,
|
|
@@ -263,7 +263,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
263
263
|
ErrorBoundary: y.ErrorBoundary,
|
|
264
264
|
Pending: y.Pending,
|
|
265
265
|
renderMode: b,
|
|
266
|
-
chain:
|
|
266
|
+
chain: T
|
|
267
267
|
}, k = {
|
|
268
268
|
cookies: D.parseCookieHeader(d.cookie),
|
|
269
269
|
headers: d,
|
|
@@ -280,7 +280,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
280
280
|
params: i,
|
|
281
281
|
pathname: c,
|
|
282
282
|
search: g,
|
|
283
|
-
segmentLoaderData:
|
|
283
|
+
segmentLoaderData: w,
|
|
284
284
|
requestContext: k,
|
|
285
285
|
...A ? {
|
|
286
286
|
outerWrap: A.outerWrap,
|
|
@@ -297,7 +297,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
297
297
|
let n = a({ shell: u });
|
|
298
298
|
return {
|
|
299
299
|
renderMode: "spa",
|
|
300
|
-
stream: (i) =>
|
|
300
|
+
stream: (i) => E({
|
|
301
301
|
res: i,
|
|
302
302
|
shell: n,
|
|
303
303
|
htmlLang: t,
|
|
@@ -332,8 +332,8 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
332
332
|
pathname: c,
|
|
333
333
|
renderMode: b,
|
|
334
334
|
interactive: j,
|
|
335
|
-
loaderData:
|
|
336
|
-
segmentLoaderData:
|
|
335
|
+
loaderData: ne,
|
|
336
|
+
segmentLoaderData: w,
|
|
337
337
|
pageLoaderRan: typeof y.loader == "function"
|
|
338
338
|
}), oe = {
|
|
339
339
|
descriptor: O,
|
|
@@ -357,7 +357,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
357
357
|
let e = A?.locale ?? k.cookies["voltro:locale"] ?? "en", t = a({ shell: u });
|
|
358
358
|
return {
|
|
359
359
|
renderMode: "ssr",
|
|
360
|
-
stream: (n) =>
|
|
360
|
+
stream: (n) => E({
|
|
361
361
|
res: n,
|
|
362
362
|
shell: t,
|
|
363
363
|
htmlLang: e,
|
|
@@ -415,7 +415,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
415
415
|
async close() {}
|
|
416
416
|
};
|
|
417
417
|
}, Fe = async (e, t) => {
|
|
418
|
-
let n = await
|
|
418
|
+
let n = await C("vite", () => import("vite")), r = (await import("@vitejs/plugin-react")).default, i = (await import("@tailwindcss/vite")).default, a = await n.createServer({
|
|
419
419
|
root: t,
|
|
420
420
|
envPrefix: "__VOLTRO_VITE_ENV_DISABLED__",
|
|
421
421
|
plugins: [r(), i()],
|
|
@@ -432,7 +432,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
432
432
|
},
|
|
433
433
|
appType: "custom",
|
|
434
434
|
logLevel: "warn"
|
|
435
|
-
}), o = L(e, "src", "pages"), s = (e) => e === "" ? o : L(o, e), c =
|
|
435
|
+
}), o = L(e, "src", "pages"), s = (e) => e === "" ? o : L(o, e), c = T({
|
|
436
436
|
limit: u(),
|
|
437
437
|
onColdStart: (e) => q.debug("ssr cold-compile start", { id: e }),
|
|
438
438
|
onColdEnd: (e, { durationMs: t, failed: n }) => q.debug(`ssr cold-compile ${n ? "FAILED" : "end"} ${t}ms`, {
|
|
@@ -472,7 +472,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
472
472
|
ran: !0,
|
|
473
473
|
exitCode: 1
|
|
474
474
|
};
|
|
475
|
-
let { resolved: o } = await
|
|
475
|
+
let { resolved: o } = await ne({
|
|
476
476
|
rawEnv: a.env,
|
|
477
477
|
appType: "web",
|
|
478
478
|
root: t,
|
|
@@ -494,17 +494,17 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
494
494
|
ran: !0,
|
|
495
495
|
exitCode: 1
|
|
496
496
|
};
|
|
497
|
-
let C = a.name ?? "unnamed",
|
|
497
|
+
let C = a.name ?? "unnamed", T = he("web", C, m), E = ge(C);
|
|
498
498
|
await fe({
|
|
499
|
-
id:
|
|
499
|
+
id: T,
|
|
500
500
|
name: C,
|
|
501
501
|
kind: "web",
|
|
502
502
|
url: `http://localhost:${m}`,
|
|
503
503
|
pid: process.pid,
|
|
504
504
|
status: "booting",
|
|
505
|
-
logFile:
|
|
505
|
+
logFile: E.path
|
|
506
506
|
}).catch(() => {});
|
|
507
|
-
let
|
|
507
|
+
let ie = L(x, "_voltro", "shell.html"), P = await Z(ie) ? await z.readFile(ie, "utf8") : await z.readFile(te, "utf8"), I = await b(t, a), ye = w(I[0]), be = I[0]?.name, R, B = null, xe = process.env.SSR_CACHE === "postgres";
|
|
508
508
|
if (xe && k()) B = new (await (import("pg"))).default.Client(O()), await B.connect(), R = De({ client: B }), q.info("isr cache backend: postgres", { table: "voltro_isr_cache" });
|
|
509
509
|
else if (xe) {
|
|
510
510
|
let t = "SSR_CACHE=postgres, but nothing in the environment names a database (looked for DB_URL, DB_PRIMARY_URL, DB_DIRECT_URL, DB_MIGRATE_URL, DB_HOST, PG_HOST).";
|
|
@@ -1023,13 +1023,13 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1023
1023
|
}), q.debug("dynamic + ssr/isr routes resolve via SSR loader");
|
|
1024
1024
|
try {
|
|
1025
1025
|
await fe({
|
|
1026
|
-
id:
|
|
1026
|
+
id: T,
|
|
1027
1027
|
name: C,
|
|
1028
1028
|
kind: "web",
|
|
1029
1029
|
url: `http://localhost:${m}`,
|
|
1030
1030
|
pid: process.pid,
|
|
1031
1031
|
status: "live",
|
|
1032
|
-
logFile:
|
|
1032
|
+
logFile: E.path
|
|
1033
1033
|
});
|
|
1034
1034
|
let e = p(t);
|
|
1035
1035
|
if (e) {
|
|
@@ -1038,13 +1038,13 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1038
1038
|
}
|
|
1039
1039
|
setInterval(() => {
|
|
1040
1040
|
fe({
|
|
1041
|
-
id:
|
|
1041
|
+
id: T,
|
|
1042
1042
|
name: C,
|
|
1043
1043
|
kind: "web",
|
|
1044
1044
|
url: `http://localhost:${m}`,
|
|
1045
1045
|
pid: process.pid,
|
|
1046
1046
|
status: "live",
|
|
1047
|
-
logFile:
|
|
1047
|
+
logFile: E.path
|
|
1048
1048
|
}).catch(() => {});
|
|
1049
1049
|
}, 1e4).unref();
|
|
1050
1050
|
} catch (e) {
|
|
@@ -1066,7 +1066,7 @@ CREATE INDEX IF NOT EXISTS ${e}_servable_until_idx ON ${e} (servable_until);
|
|
|
1066
1066
|
if (Ge = !0, q.info(`received ${e}, shutting down`, { signal: e }), Ue.close(), await $.stop(), B) try {
|
|
1067
1067
|
await B.end();
|
|
1068
1068
|
} catch {}
|
|
1069
|
-
await K.close(), await me(
|
|
1069
|
+
await K.close(), await me(T), await E.dispose(), process.exit(0);
|
|
1070
1070
|
}
|
|
1071
1071
|
};
|
|
1072
1072
|
process.on("SIGINT", Ke("SIGINT")), process.on("SIGTERM", Ke("SIGTERM"));
|
package/dist/startEntry.js
CHANGED
package/dist/startup.d.ts
CHANGED
|
@@ -3,6 +3,35 @@ import { StartupContext } from '@voltro/runtime';
|
|
|
3
3
|
import { StartupFn } from '@voltro/runtime';
|
|
4
4
|
import { SyncLogger } from '@voltro/logger';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* How long a startup may run before the boot refuses it.
|
|
8
|
+
*
|
|
9
|
+
* ── Why there is a ceiling at all, and why it used to be 2 seconds ─────────
|
|
10
|
+
*
|
|
11
|
+
* The old value was 2000 ms and it was not a ceiling — it was a RACE the boot
|
|
12
|
+
* always won. A startup slower than that was reported as fine and the boot
|
|
13
|
+
* moved on, so a rejection arriving afterwards had nothing left to refuse.
|
|
14
|
+
*
|
|
15
|
+
* That race existed to protect one shape: a startup that never returns because
|
|
16
|
+
* it holds a fiber until shutdown. Counted before changing it, that shape
|
|
17
|
+
* appears in ZERO of the four startups this framework ships — `warm.startup.tsx`
|
|
18
|
+
* (twice), `searchBackfill.startup.tsx` and the memory fixture's all return.
|
|
19
|
+
* `warm` is the one to copy: it starts an interval, hands the teardown back
|
|
20
|
+
* through `onShutdown`, and returns.
|
|
21
|
+
*
|
|
22
|
+
* So the race protected the shape we discourage and penalised the shape we
|
|
23
|
+
* teach — and the penalised one includes `searchBackfill`, our own example,
|
|
24
|
+
* which awaits a full-table query plus an index backfill and is the likeliest
|
|
25
|
+
* thing in the box to exceed two seconds. Slow AND failing put a consumer back
|
|
26
|
+
* in exactly the silent state this file was fixed for.
|
|
27
|
+
*
|
|
28
|
+
* 60 seconds because the number now has one job: turn "hangs forever" into
|
|
29
|
+
* something diagnosable. It must never fire for honest work, and a boot that
|
|
30
|
+
* refuses after a minute with a message naming the file beats one that waits
|
|
31
|
+
* for a fiber that is never coming.
|
|
32
|
+
*/
|
|
33
|
+
export declare const DEFAULT_STARTUP_TIMEOUT_MS = 60000;
|
|
34
|
+
|
|
6
35
|
export declare interface DiscoveredStartup {
|
|
7
36
|
readonly file: string;
|
|
8
37
|
readonly id: string;
|
|
@@ -13,7 +42,7 @@ export declare const loadStartupFiles: (files: ReadonlyArray<string>, log: SyncL
|
|
|
13
42
|
|
|
14
43
|
/** Run every discovered startup. Returns a handle whose `shutdown()`
|
|
15
44
|
* drains every registered teardown LIFO. */
|
|
16
|
-
export declare const runStartups: (startups: ReadonlyArray<DiscoveredStartup>, store: DataStore, parentLog: SyncLogger) => Promise<StartupHandle>;
|
|
45
|
+
export declare const runStartups: (startups: ReadonlyArray<DiscoveredStartup>, store: DataStore, parentLog: SyncLogger, ceilingMs?: number) => Promise<StartupHandle>;
|
|
17
46
|
|
|
18
47
|
export { StartupContext }
|
|
19
48
|
|
|
@@ -23,4 +52,14 @@ export declare interface StartupHandle {
|
|
|
23
52
|
readonly shutdown: () => Promise<void>;
|
|
24
53
|
}
|
|
25
54
|
|
|
55
|
+
/**
|
|
56
|
+
* The ceiling, from `VOLTRO_STARTUP_TIMEOUT_MS`.
|
|
57
|
+
*
|
|
58
|
+
* An app with a genuinely long backfill raises it; the env var is the whole
|
|
59
|
+
* knob, and the refusal names it so nobody has to find this constant. Not an
|
|
60
|
+
* `app.config.ts` field: this is an operational safety limit, not a design
|
|
61
|
+
* choice about the app, and the parameter below is the seam if that changes.
|
|
62
|
+
*/
|
|
63
|
+
export declare const startupTimeoutMsFromEnv: (envValue: string | undefined) => number;
|
|
64
|
+
|
|
26
65
|
export { }
|
package/dist/startup.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { t as loadStartupFiles,
|
|
1
|
+
import { i as e, n as t, r as n, t as r } from "./startupRunner-CEqQq7ax.js";
|
|
2
|
+
export { r as DEFAULT_STARTUP_TIMEOUT_MS, t as loadStartupFiles, n as runStartups, e as startupTimeoutMsFromEnv };
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { n as e } from "./appModuleLoader-C9r9mxZt.js";
|
|
2
|
+
import { t } from "./bootRefusal-pgvDxlrU.js";
|
|
3
|
+
import { basename as n } from "node:path";
|
|
4
|
+
import { publishServerError as r } from "@voltro/protocol";
|
|
5
|
+
//#region src/startupRunner.ts
|
|
6
|
+
var i = (e) => e.replace(/\.startup\.tsx?$/, ""), a = async (r, a) => {
|
|
7
|
+
let o = [];
|
|
8
|
+
for (let a of r) {
|
|
9
|
+
let r;
|
|
10
|
+
try {
|
|
11
|
+
r = await e(a);
|
|
12
|
+
} catch (e) {
|
|
13
|
+
throw t(`startup file \`${a}\` could not be imported — refusing to boot.\n cause: ${e instanceof Error ? e.message : String(e)}\n
|
|
14
|
+
It was discovered as a startup, so whatever it registers is missing from this process. Skipping it would leave a server that looks healthy.`);
|
|
15
|
+
}
|
|
16
|
+
let s = r.default;
|
|
17
|
+
if (typeof s != "function") throw t(`startup file \`${a}\` has no default-exported function — refusing to boot.\n
|
|
18
|
+
The convention is a DEFAULT-exported function, not a \`defineX\` wrapper:
|
|
19
|
+
|
|
20
|
+
export default async (ctx) => { /* register here */ }
|
|
21
|
+
|
|
22
|
+
A named export is discovered and never runs, which is indistinguishable from a startup that ran and did nothing.`);
|
|
23
|
+
o.push({
|
|
24
|
+
file: a,
|
|
25
|
+
id: i(n(a)),
|
|
26
|
+
fn: s
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return o;
|
|
30
|
+
}, o = 6e4, s = (e) => {
|
|
31
|
+
let t = Number(e);
|
|
32
|
+
return Number.isFinite(t) && t > 0 ? t : o;
|
|
33
|
+
}, c = async (e, n, i, a = s(process.env.VOLTRO_STARTUP_TIMEOUT_MS)) => {
|
|
34
|
+
let o = [];
|
|
35
|
+
for (let s of e) {
|
|
36
|
+
let e = i.child(`startup:${s.id}`), c = {
|
|
37
|
+
store: n,
|
|
38
|
+
log: e,
|
|
39
|
+
id: s.id,
|
|
40
|
+
onShutdown: (e) => {
|
|
41
|
+
o.push({
|
|
42
|
+
id: s.id,
|
|
43
|
+
cb: e
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}, l, u = !1;
|
|
47
|
+
try {
|
|
48
|
+
let e = s.fn(c);
|
|
49
|
+
if (e instanceof Promise) {
|
|
50
|
+
let t, n = new Promise((e) => {
|
|
51
|
+
t = setTimeout(() => e("timeout"), a);
|
|
52
|
+
});
|
|
53
|
+
try {
|
|
54
|
+
u = await Promise.race([e.then(() => "done", (e) => (l = e, r({
|
|
55
|
+
error: e,
|
|
56
|
+
source: "startup",
|
|
57
|
+
name: s.id
|
|
58
|
+
}), "done")), n]) === "timeout";
|
|
59
|
+
} finally {
|
|
60
|
+
t !== void 0 && clearTimeout(t);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
} catch (e) {
|
|
64
|
+
l = e, r({
|
|
65
|
+
error: e,
|
|
66
|
+
source: "startup",
|
|
67
|
+
name: s.id
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
if (l !== void 0) throw e.error("startup: failed", { file: s.file }, l), t(`startup \`${s.id}\` failed — refusing to boot.\n file: ${s.file}\n cause: ${l instanceof Error ? l.message : String(l)}\n
|
|
71
|
+
A startup is where an app REGISTERS things the request path depends on (\`setRowFilter\` is the one that matters most). Continuing past a failed one produces a server that looks healthy and is missing whatever the startup was there to install — which is why this used to be a warning and is now a refusal.
|
|
72
|
+
|
|
73
|
+
If this failure IS acceptable, catch it inside the startup function itself, where the decision is visible to a reviewer.`);
|
|
74
|
+
if (u) throw e.error("startup: never returned", {
|
|
75
|
+
file: s.file,
|
|
76
|
+
ceilingMs: a
|
|
77
|
+
}), t(`startup \`${s.id}\` did not return within ${a}ms — refusing to boot.\n file: ${s.file}\n
|
|
78
|
+
A startup must START its work and RETURN. Hand the teardown back through
|
|
79
|
+
\`onShutdown\` instead of awaiting forever:
|
|
80
|
+
|
|
81
|
+
export default async ({ store, log, onShutdown }) => {
|
|
82
|
+
const timer = setInterval(() => sync(store), 60_000)
|
|
83
|
+
onShutdown(() => clearInterval(timer))
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
Awaiting a fiber that resolves only on shutdown used to be allowed, and it
|
|
87
|
+
is what made a slow startup that then FAILED unreportable — the boot had
|
|
88
|
+
already moved on, so nothing was left to refuse.
|
|
89
|
+
|
|
90
|
+
If this startup is legitimately slower than ${a}ms, raise\nVOLTRO_STARTUP_TIMEOUT_MS — or, better, do the registration first and the
|
|
91
|
+
long work after, so a failure in the long half cannot hide a missing
|
|
92
|
+
registration.`);
|
|
93
|
+
e.info("startup: registered");
|
|
94
|
+
}
|
|
95
|
+
return { shutdown: async () => {
|
|
96
|
+
for (let e = o.length - 1; e >= 0; e--) {
|
|
97
|
+
let { id: t, cb: n } = o[e], r = i.child(`startup:${t}`);
|
|
98
|
+
try {
|
|
99
|
+
let e = n();
|
|
100
|
+
e instanceof Promise && await Promise.race([e, new Promise((e) => setTimeout(e, 5e3))]);
|
|
101
|
+
} catch (e) {
|
|
102
|
+
r.warn("startup: teardown threw", {}, e);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
} };
|
|
106
|
+
};
|
|
107
|
+
//#endregion
|
|
108
|
+
export { s as i, a as n, c as r, o as t };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//#region src/subcommandNames.ts
|
|
2
|
+
var e = [
|
|
3
|
+
"plan",
|
|
4
|
+
"apply",
|
|
5
|
+
"branch",
|
|
6
|
+
"plans",
|
|
7
|
+
"drift",
|
|
8
|
+
"squash",
|
|
9
|
+
"restore-snapshot",
|
|
10
|
+
"generate",
|
|
11
|
+
"migrate",
|
|
12
|
+
"rollback",
|
|
13
|
+
"status",
|
|
14
|
+
"files",
|
|
15
|
+
"rollback-file",
|
|
16
|
+
"seed",
|
|
17
|
+
"gc-snapshots",
|
|
18
|
+
"adopt",
|
|
19
|
+
"scan-credentials",
|
|
20
|
+
"encrypt-column"
|
|
21
|
+
], t = [
|
|
22
|
+
"scope",
|
|
23
|
+
"export",
|
|
24
|
+
"erase"
|
|
25
|
+
], n = (e) => `<${e.join("|")}>`;
|
|
26
|
+
//#endregion
|
|
27
|
+
export { t as n, n as r, e as t };
|
|
@@ -4,10 +4,7 @@ import { fileURLToPath as s } from "node:url";
|
|
|
4
4
|
//#region src/templates.ts
|
|
5
5
|
var c = e(s(import.meta.url)), l = (() => {
|
|
6
6
|
let n = process.env.VOLTRO_TEMPLATES_DIR;
|
|
7
|
-
if (n)
|
|
8
|
-
let e = t(n, "apps");
|
|
9
|
-
if (i(e)) return e;
|
|
10
|
-
}
|
|
7
|
+
if (n) return t(n, "apps");
|
|
11
8
|
let a = r(c, "..", "templates", "apps"), o = c;
|
|
12
9
|
for (let n = 0; n < 12; n++) {
|
|
13
10
|
for (let e of ["voltro-templates", ".voltro-templates"]) {
|
|
@@ -79,7 +79,7 @@ var d = l({ scope: "voltro:test" }), f = (e) => {
|
|
|
79
79
|
}, C = async (e) => {
|
|
80
80
|
let t = m(e);
|
|
81
81
|
if (!o(t.root)) return console.error(`voltro test: no such directory: ${t.root}`), 1;
|
|
82
|
-
let { checkRpcGroupFreshness: n } = await import("./codegen-
|
|
82
|
+
let { checkRpcGroupFreshness: n } = await import("./codegen-uYrrDzQv.js"), r = await n(t.root);
|
|
83
83
|
if (r.kind === "stale") return console.error(`voltro test: ${r.file} is stale — ${r.reason}.`), console.error(" The tests would run against the previously generated procedure group, pass, and prove nothing about the descriptors you just edited.\n Run `voltro codegen` (or boot `voltro dev` once) and try again."), 1;
|
|
84
84
|
d.info("running vitest", {
|
|
85
85
|
root: t.root,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as e, r as t, t as n } from "./codemodRunner-
|
|
1
|
+
import { n as e, r as t, t as n } from "./codemodRunner-CXgQ-ecJ.js";
|
|
2
2
|
import { basename as r, dirname as i, join as a, relative as o, resolve as s } from "node:path";
|
|
3
3
|
import { existsSync as c, readFileSync as l, readdirSync as u, statSync as d, writeFileSync as f } from "node:fs";
|
|
4
4
|
import { totalmem as p } from "node:os";
|