@voltro/cli 0.53.0 → 0.54.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 +195 -0
- package/dist/{agentsMd-0l980yhL.js → agentsMd-BaLC10Na.js} +110 -82
- package/dist/agentsMd-DCY1RSs8.js +2 -0
- package/dist/apiBuild-CeUN55uk.js +2 -0
- package/dist/{apiBuild-CaPfoWku.js → apiBuild-DTWp0S_q.js} +2 -2
- package/dist/bin.js +1 -1
- package/dist/{build-D-OnvNMf.js → build-D4ygSbnV.js} +114 -114
- package/dist/{checkCommand-C5elt0tW.js → checkCommand-Dg1G7Gwd.js} +6 -6
- package/dist/{checkCommand-D2ZduVlh.js → checkCommand-L7DTlpIF.js} +1 -1
- package/dist/{cloudCmd-QUXh-b5w.js → cloudCmd-DzKcSYuy.js} +1 -1
- package/dist/{codegen-FEk8AZHb.js → codegen-DSLM8Su9.js} +2 -2
- package/dist/codegen-DjgxEOnD.js +2 -0
- package/dist/codegenCommand-CG_Vx4lc.js +41 -0
- package/dist/{codemodRunner-BjtB2lq6.js → codemodRunner-Cd4xkC6u.js} +9 -9
- package/dist/{commands-DyxAmhP0.js → commands-6Kzi92Np.js} +96 -73
- package/dist/{dashboardCommand-BdKTyT13.js → dashboardCommand-Cq1PWvI1.js} +3 -3
- package/dist/{dataCommand-Bab9X7s8.js → dataCommand-DYzW8vkv.js} +3 -3
- package/dist/{dbCommand-06O2finM.js → dbCommand-B4NWZtGL.js} +3 -3
- package/dist/dbCommand-CSFWs9ev.js +2 -0
- package/dist/{dev-C6LGF4iY.js → dev-CmuvUKRq.js} +2236 -2219
- package/dist/{dev-GjJWAYo2.js → dev-cKUiZZsB.js} +1 -1
- package/dist/{doctorCommand-etMkflRc.js → doctorCommand-DCiFVMtZ.js} +21 -21
- package/dist/doctorCommand-J3qu4E0Y.js +2 -0
- package/dist/{dormancyCommand-UwZ1AZzB.js → dormancyCommand-w1TrmgYP.js} +1 -1
- package/dist/{embeddingsCommand-C70zWHwo.js → embeddingsCommand-CMgPyRTr.js} +1 -1
- package/dist/{envCommand-dSyKvRkM.js → envCommand-Cyynmcfa.js} +15 -15
- package/dist/{evolveCommand-CG0_ebO5.js → evolveCommand-BwvQ8dVH.js} +2 -2
- package/dist/fileConventions-l-RIXbx8.js +36 -0
- package/dist/{fileTaxonomy-B7uxipWS.js → fileTaxonomy-CbyMQYx_.js} +37 -37
- package/dist/{frameworkTableAssembly-DKx3ba3S.js → frameworkTableAssembly-D7LJuALW.js} +5 -5
- package/dist/frameworkTableAssembly-IPD1pUnZ.js +2 -0
- package/dist/index.js +2 -2
- package/dist/{infoCommand-_53iOc_j.js → infoCommand-DlYlUPqs.js} +1 -1
- package/dist/{metaCommands-Cn2oboG4.js → metaCommands-x7RCi2AF.js} +2 -2
- package/dist/{migrate-Cko9rswM.js → migrate-BK_Bbx-_.js} +2 -2
- package/dist/mobileCommand-D9O6iq3D.js +428 -0
- package/dist/mobileCommand-DAum7tsG.js +2 -0
- package/dist/{pageConvention-C938S8oC.js → pageConvention-CMpfDN6r.js} +1 -1
- package/dist/{privacyCommand-DWTQMC6R.js → privacyCommand-BCa2OoZG.js} +2 -2
- package/dist/{probeCommand-DkGGLknv.js → probeCommand-_C0YU207.js} +1 -1
- package/dist/{projectScaffold-EzlErR4E.js → projectScaffold-CJfP-xbT.js} +1 -1
- package/dist/{projectScaffold-B4dmTlwT.js → projectScaffold-CSN0OzBV.js} +2 -2
- package/dist/renderModeScan-43yQ2opo.js +147 -0
- package/dist/{renderProfile-CskIgAfn.js → renderProfile-DvrhVJHa.js} +2 -2
- package/dist/{runtimeTrace-c0APJz7E.js → runtimeTrace-CGWx1Q6l.js} +1 -1
- package/dist/{sdkgen-BiQCgIEr.js → sdkgen-CDGHQUFj.js} +1 -1
- package/dist/serveCommand-BiPe8BJm.js +2 -0
- package/dist/{serveCommand-CueKQgzl.js → serveCommand-Bje09q1v.js} +708 -708
- package/dist/serveEntry.js +1 -1
- package/dist/start-B0bnJgxI.js +3 -0
- package/dist/{start-ekPan8BT.js → start-Clz-1BHB.js} +511 -504
- package/dist/startEntry.js +1 -1
- package/dist/{staticCommand-xlSL-IWk.js → staticCommand-ey0kYmOT.js} +1 -1
- package/dist/{subcommandNames-DpYs3DXr.js → subcommandNames-CDzfEtKV.js} +3 -3
- package/dist/{templates-BR-fb4SP.js → templates-BTWZkJJT.js} +41 -9
- package/dist/{test-BWPQcRoB.js → test-D_kW4KMj.js} +1 -1
- package/dist/updateCommand-CIoVDKnj.js +2 -0
- package/dist/{updateCommand-C_8I8Rzo.js → updateCommand-CRJlAOaM.js} +1 -1
- package/dist/{webDev-oczpugbx.js → webDev-DSI9SOhs.js} +1127 -1090
- package/dist/{webDev-C7jWJ5dX.js → webDev-DlvZO30c.js} +1 -1
- package/dist/{webhooksCommand-4SVPDjKg.js → webhooksCommand-BvzXNHji.js} +1 -1
- package/dist/workspaceDeps-RKEkX92S.js +45 -0
- package/package.json +19 -19
- package/templates/AGENTS.core.md +2 -0
- package/templates/AGENTS.md +4 -2
- package/templates/agent-docs/_index.md +2 -2
- package/templates/agent-docs/_manifest.json +1 -1
- package/templates/agent-docs/ai.md +4 -4
- package/templates/agent-docs/authentication.md +72 -0
- package/templates/agent-docs/cli.md +4 -1
- package/templates/agent-docs/data.md +61 -12
- package/templates/agent-docs/database/advancedqueries.md +1 -1
- package/templates/agent-docs/database/migrations.md +1 -1
- package/templates/agent-docs/database/seedsdialects.md +64 -2
- package/templates/agent-docs/internationalization.md +2 -0
- package/templates/agent-docs/introduction.md +25 -0
- package/templates/agent-docs/local-first-mobile.md +139 -41
- package/templates/agent-docs/observability.md +4 -2
- package/templates/agent-docs/plugins/atlassian.md +2 -2
- package/templates/agent-docs/plugins/audit.md +2 -2
- package/templates/agent-docs/plugins/billing.md +1 -1
- package/templates/agent-docs/plugins/cdc-out.md +8 -3
- package/templates/agent-docs/plugins/comments.md +22 -0
- package/templates/agent-docs/plugins/presence.md +32 -3
- package/templates/agent-docs/plugins/prometheus.md +2 -0
- package/templates/agent-docs/plugins/queue.md +47 -4
- package/templates/agent-docs/plugins.md +6 -6
- package/templates/agent-docs/reference.md +20 -1
- package/templates/agent-docs/routing.md +63 -9
- package/templates/agent-docs/scheduling.md +1 -1
- package/templates/agent-docs/schema-driven-ui.md +12 -1
- package/templates/agent-docs/templates/appshells.md +36 -4
- package/templates/agent-docs/whats-new.md +109 -135
- package/templates/apps/api-ai/package.json +6 -6
- 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 +9 -9
- package/templates/apps/api-collab/README.md +3 -3
- package/templates/apps/api-collab/app.config.ts +1 -1
- package/templates/apps/api-collab/database/schema.ts +12 -8
- package/templates/apps/api-collab/mutations/documents.create.mutation.server.ts +1 -1
- package/templates/apps/api-collab/mutations/documents.setBody.mutation.server.ts +1 -1
- package/templates/apps/api-collab/mutations/documents.setBody.mutation.ts +1 -1
- package/templates/apps/api-collab/package.json +8 -8
- package/templates/apps/api-collab/template.json +1 -1
- package/templates/apps/api-collab/tests/documents.setBody.test.ts +10 -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-row-history/package.json +8 -8
- package/templates/apps/api-saas/package.json +11 -10
- 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-webhooks/package.json +9 -9
- package/templates/apps/changelog/package.json +7 -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/README.md +43 -24
- package/templates/apps/frontend-collab/app.config.ts +3 -3
- package/templates/apps/frontend-collab/package.json +14 -10
- package/templates/apps/frontend-collab/src/locales/de.ts +1 -2
- package/templates/apps/frontend-collab/src/locales/en.ts +1 -2
- package/templates/apps/frontend-collab/src/pages/page.test.tsx +72 -76
- package/templates/apps/frontend-collab/src/pages/page.tsx +45 -22
- package/templates/apps/frontend-collab/template.json +2 -2
- 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 +8 -7
- package/templates/apps/frontend-i18n/package.json +6 -6
- package/templates/apps/frontend-landing/README.md +48 -0
- package/templates/apps/frontend-landing/app.config.ts +28 -0
- package/templates/apps/frontend-landing/package.json +7 -6
- package/templates/apps/frontend-landing/src/assets/hero.jpg +0 -0
- package/templates/apps/frontend-landing/src/fonts/Geist-Variable.woff2 +0 -0
- package/templates/apps/frontend-landing/src/fonts/LICENSE-Geist.txt +92 -0
- package/templates/apps/frontend-landing/src/globals.css +15 -0
- package/templates/apps/frontend-landing/src/globals.d.ts +17 -0
- package/templates/apps/frontend-landing/src/locales/de.ts +3 -2
- package/templates/apps/frontend-landing/src/locales/en.ts +5 -2
- package/templates/apps/frontend-landing/src/pages/page.test.tsx +79 -0
- package/templates/apps/frontend-landing/src/pages/page.tsx +26 -3
- package/templates/apps/frontend-landing/template.json +2 -2
- 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 +8 -7
- package/templates/apps/frontend-status/package.json +8 -8
- package/templates/apps/mobile-app/package.json +12 -11
- package/templates/apps/mobile-app/src/lib/deeplinks.ts +29 -17
- package/templates/apps/mobile-app/tests/deeplinks.test.ts +16 -0
- package/dist/agentsMd-SDDSkyl4.js +0 -2
- package/dist/apiBuild-DHtLXYx9.js +0 -2
- package/dist/codegen-BWpt3VgF.js +0 -2
- package/dist/codegenCommand-BOiWQ5hz.js +0 -137
- package/dist/dbCommand-B1EXBC6f.js +0 -2
- package/dist/doctorCommand-B0hX0tdz.js +0 -2
- package/dist/fileConventions-DASGEmj-.js +0 -35
- package/dist/frameworkTableAssembly-C_7Z-rMs.js +0 -2
- package/dist/renderModeScan-CUbOeOAg.js +0 -122
- package/dist/serveCommand-DsnrVN3U.js +0 -2
- package/dist/start-BJzZLbt8.js +0 -3
- package/dist/updateCommand-Bqql_rsQ.js +0 -2
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
import { a as e, r as t } from "./subcommandNames-CDzfEtKV.js";
|
|
2
|
+
import { t as n } from "./cliArgs-D4p8n7EE.js";
|
|
3
|
+
import { s as r } from "./fileConventions-l-RIXbx8.js";
|
|
4
|
+
import { t as i } from "./workspaceDeps-RKEkX92S.js";
|
|
5
|
+
import { join as a, relative as o, resolve as s, sep as c } from "node:path";
|
|
6
|
+
import { promises as l } from "node:fs";
|
|
7
|
+
import { pathToFileURL as u } from "node:url";
|
|
8
|
+
//#region src/mobileCodegen.ts
|
|
9
|
+
var d = "voltro.mobile.ts", f = a(".framework", "mobileApis.generated.ts"), p = (e) => e.replace(/[^a-zA-Z0-9]/g, "_"), m = async (e) => {
|
|
10
|
+
let t = a(e, d);
|
|
11
|
+
try {
|
|
12
|
+
await l.stat(t);
|
|
13
|
+
} catch {
|
|
14
|
+
return { present: !1 };
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
let e = (await import(`${u(t).href}?t=${Date.now()}`)).default;
|
|
18
|
+
return e === void 0 || typeof e != "object" || e.apis === void 0 ? {
|
|
19
|
+
present: !0,
|
|
20
|
+
error: /* @__PURE__ */ Error(`${d} has no default export with an \`apis\` map`)
|
|
21
|
+
} : {
|
|
22
|
+
present: !0,
|
|
23
|
+
binding: e
|
|
24
|
+
};
|
|
25
|
+
} catch (e) {
|
|
26
|
+
return {
|
|
27
|
+
present: !0,
|
|
28
|
+
error: e instanceof Error ? e : Error(String(e))
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
}, h = (e, t) => {
|
|
32
|
+
let n = t.filter(([, e]) => e.package !== void 0).map(([e, t]) => {
|
|
33
|
+
let n = `${p(e)}Group`, r = `${p(e)}Descriptors`;
|
|
34
|
+
return `import { ${n === "appGroup" ? "appGroup" : `appGroup as ${n}`}, ${r === "appDescriptors" ? "appDescriptors" : `appDescriptors as ${r}`} } from '${t.package}/rpcGroup'`;
|
|
35
|
+
}), r = t.map(([e, t]) => t.package === void 0 ? ` // ${JSON.stringify(e)}: declared with \`url\` only — no local rpc surface to import.\n // Add \`package: '<the api package>'\` to ${d} to get typed hooks for it.` : ` { ${[
|
|
36
|
+
`name: ${JSON.stringify(e)}`,
|
|
37
|
+
`group: ${p(e)}Group`,
|
|
38
|
+
`descriptors: ${p(e)}Descriptors`,
|
|
39
|
+
`wsUrl: wsUrl(${JSON.stringify(e)})`
|
|
40
|
+
].join(", ")} },`), i = t.filter(([, e]) => e.url !== void 0).map(([e, t]) => ` ${JSON.stringify(e)}: ${JSON.stringify(t.url)},`);
|
|
41
|
+
return [
|
|
42
|
+
"// GENERATED BY `voltro codegen` — do not edit; regenerate with `voltro codegen`.",
|
|
43
|
+
"//",
|
|
44
|
+
`// The api bindings declared in ${d}. Only the BINDING is`,
|
|
45
|
+
"// generated: the procedure types ride the imports below, so a schema change",
|
|
46
|
+
"// in an api needs no regeneration here.",
|
|
47
|
+
"",
|
|
48
|
+
...n,
|
|
49
|
+
"import type { MobileApiBinding } from '@voltro/react-native'",
|
|
50
|
+
"",
|
|
51
|
+
"/** Every api this app talks to, bound to a runtime-resolved ws URL.",
|
|
52
|
+
" *",
|
|
53
|
+
" * The URL is a parameter because it differs per environment and `localhost`",
|
|
54
|
+
" * on a device is the DEVICE — see `resolveDevWsUrl` in @voltro/react-native. */",
|
|
55
|
+
"export const mobileApis = (",
|
|
56
|
+
" wsUrl: (apiName: string) => string,",
|
|
57
|
+
"): ReadonlyArray<MobileApiBinding> => [",
|
|
58
|
+
...r,
|
|
59
|
+
"]",
|
|
60
|
+
"",
|
|
61
|
+
"/** Api names in declaration order — the keys the hooks bind to. */",
|
|
62
|
+
`export const MOBILE_API_NAMES = [${t.map(([e]) => JSON.stringify(e)).join(", ")}] as const`,
|
|
63
|
+
...i.length > 0 ? [
|
|
64
|
+
"",
|
|
65
|
+
`/** URLs declared in ${d} for apis this app does not build. */`,
|
|
66
|
+
"export const MOBILE_API_URLS: Readonly<Record<string, string>> = {",
|
|
67
|
+
...i,
|
|
68
|
+
"}"
|
|
69
|
+
] : [],
|
|
70
|
+
""
|
|
71
|
+
].join("\n");
|
|
72
|
+
}, g = async (e) => {
|
|
73
|
+
let t = s(e), n = await m(t);
|
|
74
|
+
if (!n.present) return { kind: "not-a-mobile-app" };
|
|
75
|
+
if ("error" in n) return {
|
|
76
|
+
kind: "refused",
|
|
77
|
+
reason: `${d} could not be loaded — ${n.error.message}`
|
|
78
|
+
};
|
|
79
|
+
let r = Object.entries(n.binding.apis);
|
|
80
|
+
if (r.length === 0) return {
|
|
81
|
+
kind: "refused",
|
|
82
|
+
reason: `${d} declares no apis`
|
|
83
|
+
};
|
|
84
|
+
for (let [e, t] of r) if (t.package === void 0 && t.url === void 0) return {
|
|
85
|
+
kind: "refused",
|
|
86
|
+
reason: `api ${JSON.stringify(e)} declares neither \`package\` nor \`url\``
|
|
87
|
+
};
|
|
88
|
+
for (let [e, n] of r) if (n.package !== void 0 && await i(t, n.package) === null) return {
|
|
89
|
+
kind: "refused",
|
|
90
|
+
reason: `api ${JSON.stringify(e)}: ${n.package} is not a workspace dependency of this app. Add it to the app's package.json (\`"${n.package}": "workspace:*"\`) and install.`
|
|
91
|
+
};
|
|
92
|
+
let o = a(t, f), c = h(t, r);
|
|
93
|
+
await l.mkdir(a(t, ".framework"), { recursive: !0 });
|
|
94
|
+
let u = null;
|
|
95
|
+
try {
|
|
96
|
+
u = await l.readFile(o, "utf8");
|
|
97
|
+
} catch {}
|
|
98
|
+
return u !== c && await l.writeFile(o, c, "utf8"), {
|
|
99
|
+
kind: "wrote",
|
|
100
|
+
file: o,
|
|
101
|
+
apis: r.map(([e]) => e)
|
|
102
|
+
};
|
|
103
|
+
}, _ = (e, t) => t.kind === "wrote" ? `voltro codegen: wrote ${o(e, t.file)} (apis ${t.apis.join(", ")})` : t.kind === "refused" ? `voltro codegen: ${t.reason} — refusing to write.` : `voltro codegen: no ${d} here — not a mobile app.`, v = a(".framework", "deepLinks.generated.ts"), y = [a("src", "app"), "app"], b = /\.(tsx|ts|jsx|js)$/, x = (e) => {
|
|
104
|
+
let t = e.split(c).join("/");
|
|
105
|
+
if (!b.test(t)) return {
|
|
106
|
+
kind: "skip",
|
|
107
|
+
reason: "not a route file extension"
|
|
108
|
+
};
|
|
109
|
+
if (/\.(test|spec)\.[jt]sx?$/.test(t)) return {
|
|
110
|
+
kind: "skip",
|
|
111
|
+
reason: "a test file"
|
|
112
|
+
};
|
|
113
|
+
if (/\+api\.[jt]sx?$/.test(t) || /\+api\.[jt]sx?$/.test(t)) return {
|
|
114
|
+
kind: "skip",
|
|
115
|
+
reason: "an Expo Router API route, not a screen"
|
|
116
|
+
};
|
|
117
|
+
if (r.test(t)) return {
|
|
118
|
+
kind: "skip",
|
|
119
|
+
reason: "a *.deepLink.ts inside the router directory"
|
|
120
|
+
};
|
|
121
|
+
let n = t.replace(b, "").split("/"), i = [];
|
|
122
|
+
for (let [e, t] of n.entries()) {
|
|
123
|
+
let r = e === n.length - 1;
|
|
124
|
+
if (t.startsWith("+")) return {
|
|
125
|
+
kind: "skip",
|
|
126
|
+
reason: `\`${t}\` is an Expo Router special file, not a screen`
|
|
127
|
+
};
|
|
128
|
+
if (t.startsWith("_")) return {
|
|
129
|
+
kind: "skip",
|
|
130
|
+
reason: `\`${t}\` is not a route (Expo Router reserves the \`_\` prefix)`
|
|
131
|
+
};
|
|
132
|
+
if (t.startsWith(".")) return {
|
|
133
|
+
kind: "skip",
|
|
134
|
+
reason: "a dot-file"
|
|
135
|
+
};
|
|
136
|
+
if (!(t.startsWith("(") && t.endsWith(")"))) {
|
|
137
|
+
if (t.startsWith("[...") && t.endsWith("]")) return {
|
|
138
|
+
kind: "skip",
|
|
139
|
+
reason: `\`${t}\` is a catch-all — the matcher has no catch-all segment, so declare this one in a \`*.deepLink.ts\``
|
|
140
|
+
};
|
|
141
|
+
if (t.startsWith("[") && t.endsWith("]")) {
|
|
142
|
+
let e = t.slice(1, -1).replace(/^\[|\]$/g, "");
|
|
143
|
+
if (e.length === 0) return {
|
|
144
|
+
kind: "skip",
|
|
145
|
+
reason: "an empty dynamic segment"
|
|
146
|
+
};
|
|
147
|
+
i.push(`:${e}`);
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
r && t === "index" || i.push(t);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
kind: "route",
|
|
155
|
+
pattern: `/${i.join("/")}`.replace(/\/{2,}/g, "/")
|
|
156
|
+
};
|
|
157
|
+
}, S = (e, t) => {
|
|
158
|
+
let n = e.split("/"), r = t.split("/");
|
|
159
|
+
for (let e = 0; e < Math.min(n.length, r.length); e++) {
|
|
160
|
+
let t = n[e].startsWith(":");
|
|
161
|
+
if (t !== r[e].startsWith(":")) return t ? 1 : -1;
|
|
162
|
+
}
|
|
163
|
+
return n.length === r.length ? e < t ? -1 : +(e > t) : n.length - r.length;
|
|
164
|
+
}, C = async (e, t) => {
|
|
165
|
+
let n;
|
|
166
|
+
try {
|
|
167
|
+
n = await l.readdir(e, { withFileTypes: !0 });
|
|
168
|
+
} catch {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
for (let r of n) {
|
|
172
|
+
if (r.name.startsWith(".") || r.name === "node_modules") continue;
|
|
173
|
+
let n = a(e, r.name);
|
|
174
|
+
r.isDirectory() ? await C(n, t) : t(n);
|
|
175
|
+
}
|
|
176
|
+
}, w = async (e) => {
|
|
177
|
+
try {
|
|
178
|
+
return await l.stat(e), !0;
|
|
179
|
+
} catch {
|
|
180
|
+
return !1;
|
|
181
|
+
}
|
|
182
|
+
}, T = async (e) => {
|
|
183
|
+
for (let t of y) if (await w(a(e, t))) return t;
|
|
184
|
+
return null;
|
|
185
|
+
}, E = async (e) => {
|
|
186
|
+
let t = await T(e), n = [], i = [];
|
|
187
|
+
if (await C(e, (a) => {
|
|
188
|
+
let s = o(e, a);
|
|
189
|
+
if (s.startsWith("..") || !r.test(a)) return;
|
|
190
|
+
let l = s.split(c).join("/");
|
|
191
|
+
if (t !== null && l.startsWith(`${t.split(c).join("/")}/`)) {
|
|
192
|
+
i.push(l);
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
n.push({
|
|
196
|
+
file: l,
|
|
197
|
+
importPath: `../${l.replace(/\.ts$/, "")}`
|
|
198
|
+
});
|
|
199
|
+
}), i.length > 0) return {
|
|
200
|
+
kind: "refused",
|
|
201
|
+
reason: `${i.join(", ")} — a *.deepLink.ts inside \`${t}\` becomes a SCREEN. Expo Router routes every .ts/.tsx under its app directory, so this file ships a route named after itself. Move it outside the router directory (e.g. src/lib/).`
|
|
202
|
+
};
|
|
203
|
+
let s = [], l = [];
|
|
204
|
+
if (t !== null) {
|
|
205
|
+
let n = a(e, t);
|
|
206
|
+
await C(n, (t) => {
|
|
207
|
+
let r = x(o(n, t)), i = o(e, t).split(c).join("/");
|
|
208
|
+
r.kind === "route" ? s.push({
|
|
209
|
+
pattern: r.pattern,
|
|
210
|
+
file: i
|
|
211
|
+
}) : l.push({
|
|
212
|
+
file: i,
|
|
213
|
+
reason: r.reason
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
let u = /* @__PURE__ */ new Set(), d = s.sort((e, t) => S(e.pattern, t.pattern)).filter((e) => !u.has(e.pattern) && (u.add(e.pattern), !0));
|
|
218
|
+
return {
|
|
219
|
+
kind: "collected",
|
|
220
|
+
table: {
|
|
221
|
+
routerDir: t,
|
|
222
|
+
declared: n.sort((e, t) => e.file < t.file ? -1 : +(e.file > t.file)),
|
|
223
|
+
derived: d,
|
|
224
|
+
skipped: l.sort((e, t) => e.file < t.file ? -1 : +(e.file > t.file))
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
}, D = (e) => `declared${e}`, O = (e) => {
|
|
228
|
+
let t = [
|
|
229
|
+
"// GENERATED BY `voltro mobile codegen` — do not edit; regenerate with",
|
|
230
|
+
"// `voltro mobile codegen`.",
|
|
231
|
+
"//",
|
|
232
|
+
"// The app's deep-link table, from two sources:",
|
|
233
|
+
"//",
|
|
234
|
+
`// · DERIVED — one link per Expo Router screen under \`${e.routerDir ?? "(no router directory found)"}\`.`,
|
|
235
|
+
"// A screen is reachable by URL, so its link needs no file.",
|
|
236
|
+
"// · DECLARED — every `*.deepLink.ts` in the app. These come FIRST, so a",
|
|
237
|
+
"// declared link for a pattern overrides the derived one for it.",
|
|
238
|
+
"",
|
|
239
|
+
"import { defineDeepLink, deepLinkHref, type DeepLinkDescriptor } from '@voltro/react-native'"
|
|
240
|
+
];
|
|
241
|
+
for (let [n, r] of e.declared.entries()) t.push(`import ${D(n)} from '${r.importPath}'`);
|
|
242
|
+
return t.push("", "/** Patterns derived from the router tree, most specific first. */", "export const DERIVED_DEEP_LINK_PATTERNS = [", ...e.derived.map((e) => ` ${JSON.stringify(e.pattern)}, // ${e.file}`), "] as const", "", "/** Deep links declared by hand (`*.deepLink.ts`). */", "export const DECLARED_DEEP_LINKS: ReadonlyArray<DeepLinkDescriptor> = [", ...e.declared.map((e, t) => ` ${D(t)}, // ${e.file}`), "]", ""), e.skipped.length > 0 && t.push("// Router files that are NOT deep links. Listed rather than dropped: a", "// screen missing from the table above is otherwise indistinguishable from", "// one that has no link.", ...e.skipped.map((e) => `// ${e.file} — ${e.reason}`), ""), t.push("/**", " * The app's deep links, bound to a navigate function (expo-router's `router.push`).", " *", " * Order is the resolution order — `matchFirstDeepLink` is first-match-wins.", " * A derived pattern a declared link already covers is dropped here rather", " * than listed twice.", " */", "export const deepLinks = (", " navigate: (href: string) => void,", "): ReadonlyArray<DeepLinkDescriptor> => {", " const declaredPatterns = new Set(DECLARED_DEEP_LINKS.map((link) => link.pattern))", " const derived: ReadonlyArray<string> = DERIVED_DEEP_LINK_PATTERNS", " return [", " ...DECLARED_DEEP_LINKS,", " ...derived", " .filter((pattern) => !declaredPatterns.has(pattern))", " .map((pattern) =>", " defineDeepLink({", " pattern,", " // A derived link navigates to the screen it was derived FROM —", " // the same path, with the captured params put back.", " handler: (params) => navigate(deepLinkHref(pattern, params)),", " })),", " ]", "}", ""), t.join("\n");
|
|
243
|
+
}, k = async (e) => {
|
|
244
|
+
let t = await E(e);
|
|
245
|
+
if (t.kind === "refused") return t;
|
|
246
|
+
let n = a(e, v), r = O(t.table);
|
|
247
|
+
await l.mkdir(a(e, ".framework"), { recursive: !0 });
|
|
248
|
+
let i = null;
|
|
249
|
+
try {
|
|
250
|
+
i = await l.readFile(n, "utf8");
|
|
251
|
+
} catch {}
|
|
252
|
+
return i !== r && await l.writeFile(n, r, "utf8"), {
|
|
253
|
+
kind: "wrote",
|
|
254
|
+
file: n,
|
|
255
|
+
derived: t.table.derived.length,
|
|
256
|
+
declared: t.table.declared.length,
|
|
257
|
+
skipped: t.table.skipped,
|
|
258
|
+
routerDir: t.table.routerDir
|
|
259
|
+
};
|
|
260
|
+
}, A = (e) => {
|
|
261
|
+
let t = /pattern\s*:\s*(['"`])(\/[^'"`\n]*)\1/.exec(e);
|
|
262
|
+
return t === null ? null : t[2];
|
|
263
|
+
}, j = async (e, t) => {
|
|
264
|
+
let n = [], r = [];
|
|
265
|
+
for (let i of t.declared) {
|
|
266
|
+
let t = "";
|
|
267
|
+
try {
|
|
268
|
+
t = await l.readFile(a(e, i.file), "utf8");
|
|
269
|
+
} catch {}
|
|
270
|
+
let o = A(t);
|
|
271
|
+
o === null ? r.push(i.file) : n.push(o);
|
|
272
|
+
}
|
|
273
|
+
return {
|
|
274
|
+
patterns: n,
|
|
275
|
+
unreadable: r
|
|
276
|
+
};
|
|
277
|
+
}, M = /^[A-Z0-9]{10}$/, N = /^[A-Za-z][A-Za-z0-9_-]*(\.[A-Za-z0-9_-]+)+$/, P = /^[A-Za-z][A-Za-z0-9_]*(\.[A-Za-z0-9_]+)+$/, F = (e) => {
|
|
278
|
+
let t = e.split("/").map((e) => e.startsWith(":") ? "*" : e).join("/");
|
|
279
|
+
return t.length === 0 ? "/" : t;
|
|
280
|
+
}, I = (e) => {
|
|
281
|
+
let t = e.trim().replace(/[:\s]/g, "").toUpperCase();
|
|
282
|
+
return /^[0-9A-F]{64}$/.test(t) ? (t.match(/.{2}/g) ?? []).join(":") : null;
|
|
283
|
+
}, L = (e) => {
|
|
284
|
+
let t = [], n = e.appleTeamId.trim().toUpperCase();
|
|
285
|
+
M.test(n) || t.push(`apple team id ${JSON.stringify(e.appleTeamId)} is not a 10-character Team ID. Find it in the Apple Developer portal under Membership details, and pass it as \`--team-id\` (or set VOLTRO_APPLE_TEAM_ID).`), N.test(e.bundleIdentifier) || t.push(`ios bundle identifier ${JSON.stringify(e.bundleIdentifier)} is not reverse-DNS. It comes from the Expo config's \`ios.bundleIdentifier\`.`), P.test(e.androidPackage) || t.push(`android package ${JSON.stringify(e.androidPackage)} is not a Java package name. It comes from the Expo config's \`android.package\`.`);
|
|
286
|
+
let r = [];
|
|
287
|
+
for (let n of e.sha256CertFingerprints) {
|
|
288
|
+
let e = I(n);
|
|
289
|
+
e === null ? t.push(`${JSON.stringify(n)} is not a SHA-256 fingerprint (32 hex bytes). Get it with \`keytool -list -v -keystore <your.keystore>\`, or from Play Console → Setup → App signing.`) : r.includes(e) || r.push(e);
|
|
290
|
+
}
|
|
291
|
+
if (e.sha256CertFingerprints.length === 0 && t.push("no android signing fingerprint. Pass `--fingerprint <sha256>` (repeatable — a debug keystore and Play App Signing are different certificates and BOTH must be listed, or App Links verify in one build and not the other)."), e.patterns.length === 0 && t.push("the app answers no deep links, so an association file would grant the app nothing. Add a screen under the router directory, or a `*.deepLink.ts`."), t.length > 0) return {
|
|
292
|
+
kind: "refused",
|
|
293
|
+
reasons: t
|
|
294
|
+
};
|
|
295
|
+
let i = /* @__PURE__ */ new Set(), a = e.patterns.map((e) => ({
|
|
296
|
+
pattern: e,
|
|
297
|
+
component: F(e)
|
|
298
|
+
})).filter(({ component: e }) => !i.has(e) && (i.add(e), !0)).map(({ pattern: e, component: t }) => ({
|
|
299
|
+
"/": t,
|
|
300
|
+
comment: `opens the app for ${e}`
|
|
301
|
+
}));
|
|
302
|
+
return {
|
|
303
|
+
kind: "built",
|
|
304
|
+
aasa: { applinks: { details: [{
|
|
305
|
+
appIDs: [`${n}.${e.bundleIdentifier}`],
|
|
306
|
+
components: a
|
|
307
|
+
}] } },
|
|
308
|
+
assetLinks: [{
|
|
309
|
+
relation: ["delegate_permission/common.handle_all_urls"],
|
|
310
|
+
target: {
|
|
311
|
+
namespace: "android_app",
|
|
312
|
+
package_name: e.androidPackage,
|
|
313
|
+
sha256_cert_fingerprints: r
|
|
314
|
+
}
|
|
315
|
+
}]
|
|
316
|
+
};
|
|
317
|
+
}, R = "apple-app-site-association", z = "assetlinks.json", B = ".well-known", V = [
|
|
318
|
+
"app.config.ts",
|
|
319
|
+
"app.config.js",
|
|
320
|
+
"app.config.json",
|
|
321
|
+
"app.json"
|
|
322
|
+
], H = async (e) => {
|
|
323
|
+
try {
|
|
324
|
+
return await l.stat(e), !0;
|
|
325
|
+
} catch {
|
|
326
|
+
return !1;
|
|
327
|
+
}
|
|
328
|
+
}, U = async (e) => {
|
|
329
|
+
for (let t of V) {
|
|
330
|
+
let n = a(e, t);
|
|
331
|
+
if (await H(n)) try {
|
|
332
|
+
if (t.endsWith(".json")) {
|
|
333
|
+
let e = JSON.parse(await l.readFile(n, "utf8"));
|
|
334
|
+
return {
|
|
335
|
+
kind: "loaded",
|
|
336
|
+
config: e.expo ?? e,
|
|
337
|
+
file: n
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
let e = (await import(`${u(n).href}?t=${Date.now()}`)).default, r = typeof e == "function" ? e({ config: {} }) : e;
|
|
341
|
+
return r === void 0 || typeof r != "object" ? {
|
|
342
|
+
kind: "failed",
|
|
343
|
+
file: n,
|
|
344
|
+
error: /* @__PURE__ */ Error("no default export with an Expo config object")
|
|
345
|
+
} : {
|
|
346
|
+
kind: "loaded",
|
|
347
|
+
config: r,
|
|
348
|
+
file: n
|
|
349
|
+
};
|
|
350
|
+
} catch (e) {
|
|
351
|
+
return {
|
|
352
|
+
kind: "failed",
|
|
353
|
+
file: n,
|
|
354
|
+
error: e instanceof Error ? e : Error(String(e))
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
return { kind: "absent" };
|
|
359
|
+
}, W = async (e) => {
|
|
360
|
+
let t = await g(e);
|
|
361
|
+
return t.kind === "not-a-mobile-app" ? {
|
|
362
|
+
apis: t,
|
|
363
|
+
deepLinks: null
|
|
364
|
+
} : {
|
|
365
|
+
apis: t,
|
|
366
|
+
deepLinks: await k(e)
|
|
367
|
+
};
|
|
368
|
+
}, G = (e, t) => {
|
|
369
|
+
console.log(_(e, t.apis));
|
|
370
|
+
let n = t.deepLinks;
|
|
371
|
+
if (n === null) return 1;
|
|
372
|
+
if (n.kind === "refused") return console.error(`voltro mobile codegen: ${n.reason}`), 1;
|
|
373
|
+
let r = t.apis.kind !== "wrote";
|
|
374
|
+
n.routerDir === null ? console.log(`voltro mobile codegen: wrote ${o(e, n.file)} (${n.declared} declared link(s); no Expo Router directory found, so nothing was derived)`) : console.log(`voltro mobile codegen: wrote ${o(e, n.file)} (${n.derived} link(s) derived from ${n.routerDir}, ${n.declared} declared)`);
|
|
375
|
+
for (let e of n.skipped) e.reason.includes("catch-all") && console.log(` not derived: ${e.file} — ${e.reason}`);
|
|
376
|
+
return +!!r;
|
|
377
|
+
}, K = async (e) => G(e, await W(e)), q = (e, t) => {
|
|
378
|
+
let n = e.indexOf(t);
|
|
379
|
+
if (n !== -1 && n + 1 < e.length) return e[n + 1];
|
|
380
|
+
let r = e.find((e) => e.startsWith(`${t}=`));
|
|
381
|
+
return r === void 0 ? void 0 : r.slice(t.length + 1);
|
|
382
|
+
}, J = (e, t) => {
|
|
383
|
+
let n = [];
|
|
384
|
+
for (let [r, i] of e.entries()) i === t && r + 1 < e.length ? n.push(e[r + 1]) : i.startsWith(`${t}=`) && n.push(i.slice(t.length + 1));
|
|
385
|
+
return n;
|
|
386
|
+
}, Y = async (e, t) => {
|
|
387
|
+
let n = await U(e);
|
|
388
|
+
if (n.kind === "absent") return console.error(`voltro mobile links: no Expo config in ${e} (looked for ${V.join(", ")}) — this is not a mobile app.`), 1;
|
|
389
|
+
if (n.kind === "failed") return console.error(`voltro mobile links: ${o(e, n.file)} could not be loaded — ${n.error.message}.`), console.error(" Refusing to write: the association files would carry no bundle id and would publish anyway."), 1;
|
|
390
|
+
let r = await E(e);
|
|
391
|
+
if (r.kind === "refused") return console.error(`voltro mobile links: ${r.reason}`), 1;
|
|
392
|
+
let i = await j(e, r.table);
|
|
393
|
+
for (let e of i.unreadable) console.error(`voltro mobile links: ${e} declares a computed \`pattern\`, which cannot be read without running the module. Its path is NOT in the generated files — spell the pattern as a string literal, or add it by hand afterwards.`);
|
|
394
|
+
let c = [...i.patterns, ...r.table.derived.map((e) => e.pattern)], u = L({
|
|
395
|
+
bundleIdentifier: n.config.ios?.bundleIdentifier ?? "",
|
|
396
|
+
appleTeamId: q(t, "--team-id") ?? process.env.VOLTRO_APPLE_TEAM_ID ?? "",
|
|
397
|
+
androidPackage: n.config.android?.package ?? "",
|
|
398
|
+
sha256CertFingerprints: [...J(t, "--fingerprint"), ...process.env.VOLTRO_ANDROID_CERT_FINGERPRINT === void 0 ? [] : [process.env.VOLTRO_ANDROID_CERT_FINGERPRINT]],
|
|
399
|
+
patterns: c
|
|
400
|
+
});
|
|
401
|
+
if (u.kind === "refused") {
|
|
402
|
+
console.error("voltro mobile links: refusing to write —");
|
|
403
|
+
for (let e of u.reasons) console.error(` · ${e}`);
|
|
404
|
+
return 1;
|
|
405
|
+
}
|
|
406
|
+
let d = s(e, q(t, "--out") ?? ".well-known");
|
|
407
|
+
await l.mkdir(d, { recursive: !0 });
|
|
408
|
+
let f = a(d, R), p = a(d, z);
|
|
409
|
+
await l.writeFile(f, `${JSON.stringify(u.aasa, null, 2)}\n`, "utf8"), await l.writeFile(p, `${JSON.stringify(u.assetLinks, null, 2)}\n`, "utf8");
|
|
410
|
+
let m = u.aasa.applinks.details[0].components.length;
|
|
411
|
+
console.log(`voltro mobile links: wrote ${o(e, f)} (${m} path component(s))`), console.log(`voltro mobile links: wrote ${o(e, p)}`), console.log(` Serve both from https://<your-domain>/${B}/ as application/json, over https, with no redirect. iOS fetches the association file itself — a redirect is a silent failure.`);
|
|
412
|
+
let h = n.config.ios?.associatedDomains ?? [];
|
|
413
|
+
return h.length === 0 ? console.log(" NOTE: the Expo config declares no `ios.associatedDomains`. iOS will not fetch the association file until it does — add `ios: { associatedDomains: [\"applinks:<your-domain>\"] }`.") : console.log(` ios.associatedDomains: ${h.join(", ")}`), 0;
|
|
414
|
+
}, X = {
|
|
415
|
+
codegen: (e) => K(e),
|
|
416
|
+
links: (e, t) => Y(e, t)
|
|
417
|
+
}, Z = async (r) => {
|
|
418
|
+
let i = r[0];
|
|
419
|
+
if (i === void 0 || i === "--help" || i === "-h" || !(i in X)) return i !== void 0 && i !== "--help" && i !== "-h" && console.error(`voltro mobile: unknown subcommand ${JSON.stringify(i)}`), console.log(`voltro mobile ${e(t)}`), console.log(""), console.log(" codegen [app] regenerate the api binding + the deep-link table"), console.log(" links [app] emit apple-app-site-association + assetlinks.json"), console.log(""), console.log(" --team-id <id> Apple Team ID (or VOLTRO_APPLE_TEAM_ID)"), console.log(" --fingerprint <sha256> Android signing cert SHA-256 (repeatable,"), console.log(" or VOLTRO_ANDROID_CERT_FINGERPRINT)"), console.log(" --out <dir> where to write them (default: .well-known/)"), i === void 0 || i === "--help" || i === "-h" ? 0 : 1;
|
|
420
|
+
let a = r.slice(1), o = s(n(a, Q) ?? process.cwd());
|
|
421
|
+
return X[i](o, a);
|
|
422
|
+
}, Q = [
|
|
423
|
+
"--fingerprint",
|
|
424
|
+
"--out",
|
|
425
|
+
"--team-id"
|
|
426
|
+
];
|
|
427
|
+
//#endregion
|
|
428
|
+
export { d as a, Z as i, G as n, W as r, U as t };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as e } from "./cliError-BmdYnghb.js";
|
|
2
2
|
import { i as t, n, t as r } from "./cliArgs-D4p8n7EE.js";
|
|
3
|
-
import {
|
|
3
|
+
import { S as i, x as a } from "./fileConventions-l-RIXbx8.js";
|
|
4
4
|
import { n as o } from "./cliOutput-D1tSBoRM.js";
|
|
5
5
|
import { join as s, resolve as c } from "node:path";
|
|
6
6
|
import { promises as l } from "node:fs";
|
|
@@ -38,7 +38,7 @@ var _ = d({ scope: "voltro:privacy" }), v = /* @__PURE__ */ new Set([
|
|
|
38
38
|
return await r(e), n;
|
|
39
39
|
}, x = (e) => typeof e == "object" && !!e && "tableName" in e && "fields" in e && typeof e.tableName == "string", S = async (e) => {
|
|
40
40
|
f();
|
|
41
|
-
let t = 0, n = 0, r = [...await b(e,
|
|
41
|
+
let t = 0, n = 0, r = [...await b(e, i), ...await b(e, a)];
|
|
42
42
|
for (let e of r) {
|
|
43
43
|
let r;
|
|
44
44
|
try {
|
|
@@ -108,7 +108,7 @@ server and in this shell.`);
|
|
|
108
108
|
}, m = async (e) => {
|
|
109
109
|
let t = /* @__PURE__ */ new Map();
|
|
110
110
|
try {
|
|
111
|
-
let { walk: n, loadDiscovered: r } = await import("./dev-
|
|
111
|
+
let { walk: n, loadDiscovered: r } = await import("./dev-cKUiZZsB.js"), i = await r(await n(e)), a = [
|
|
112
112
|
...i.queries,
|
|
113
113
|
...i.mutations,
|
|
114
114
|
...i.actions,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { c as e, l as t, s as n } from "./projectScaffold-
|
|
1
|
+
import { c as e, l as t, s as n } from "./projectScaffold-CSN0OzBV.js";
|
|
2
2
|
export { n as runAddApp, e as runCreateProject, t as runListTemplates };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { a as e, i as t, n, r, t as i } from "./templates-
|
|
1
|
+
import { a as e, i as t, n, r, t as i } from "./templates-BTWZkJJT.js";
|
|
2
2
|
import { i as a, n as o, t as s } from "./cloudClient-DWL-Hw_T.js";
|
|
3
3
|
import { t as c } from "./cliRuntime-Dh7UDinH.js";
|
|
4
|
-
import { n as l } from "./agentsMd-
|
|
4
|
+
import { n as l } from "./agentsMd-BaLC10Na.js";
|
|
5
5
|
import { n as u } from "./addCommand-C05L9tZh.js";
|
|
6
6
|
import { a as d, n as f, r as p } from "./baselineCommand-Ck2Xm8M7.js";
|
|
7
7
|
import { basename as m, dirname as h, join as g, resolve as _ } from "node:path";
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { dirname as e, join as t, resolve as n } from "node:path";
|
|
2
|
+
import { readFile as r } from "node:fs/promises";
|
|
3
|
+
//#region src/isrCache.ts
|
|
4
|
+
var i = () => {
|
|
5
|
+
let e = /* @__PURE__ */ new Map(), t = /* @__PURE__ */ new Map(), n = (e) => {
|
|
6
|
+
t.set(e, (t.get(e) ?? 0) + 1);
|
|
7
|
+
};
|
|
8
|
+
return {
|
|
9
|
+
get(t) {
|
|
10
|
+
return e.get(t);
|
|
11
|
+
},
|
|
12
|
+
set(n, r, i) {
|
|
13
|
+
return i?.ifGeneration !== void 0 && (t.get(n) ?? 0) !== i.ifGeneration ? !1 : (e.set(n, r), !0);
|
|
14
|
+
},
|
|
15
|
+
generation(e) {
|
|
16
|
+
return t.get(e) ?? 0;
|
|
17
|
+
},
|
|
18
|
+
invalidate(t) {
|
|
19
|
+
e.delete(t), n(t);
|
|
20
|
+
},
|
|
21
|
+
invalidateBy(t) {
|
|
22
|
+
let r = 0;
|
|
23
|
+
for (let i of e.keys()) t(i) && (e.delete(i), n(i), r++);
|
|
24
|
+
return r;
|
|
25
|
+
},
|
|
26
|
+
clear() {
|
|
27
|
+
for (let t of e.keys()) n(t);
|
|
28
|
+
e.clear();
|
|
29
|
+
},
|
|
30
|
+
size() {
|
|
31
|
+
return e.size;
|
|
32
|
+
},
|
|
33
|
+
snapshot() {
|
|
34
|
+
return Array.from(e.entries());
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}, a = (e) => {
|
|
38
|
+
if (typeof e == "number" && Number.isFinite(e) && e > 0) return e * 1e3;
|
|
39
|
+
if (typeof e != "string") return null;
|
|
40
|
+
let t = /^\s*(\d+)\s*(s|seconds?|m|minutes?|h|hours?|d|days?)\s*$/i.exec(e);
|
|
41
|
+
if (!t) return null;
|
|
42
|
+
let n = parseInt(t[1], 10);
|
|
43
|
+
if (!Number.isFinite(n) || n <= 0) return null;
|
|
44
|
+
let r = t[2].toLowerCase();
|
|
45
|
+
return r === "s" || r.startsWith("second") ? n * 1e3 : r === "m" || r.startsWith("minute") ? n * 6e4 : r === "h" || r.startsWith("hour") ? n * 36e5 : r === "d" || r.startsWith("day") ? n * 864e5 : null;
|
|
46
|
+
}, o = (e, t = {}) => {
|
|
47
|
+
let n = [e];
|
|
48
|
+
return t.tenant !== void 0 && t.tenant !== "" && n.push(`tenant=${t.tenant}`), t.locale !== void 0 && t.locale !== "" && n.push(`lang=${t.locale}`), n.join("|");
|
|
49
|
+
}, s = (e, t) => e.expiresAt > t, c = (e, t) => e.expiresAt <= t && e.servableUntil > t, l = [
|
|
50
|
+
"static",
|
|
51
|
+
"spa",
|
|
52
|
+
"ssr",
|
|
53
|
+
"isr"
|
|
54
|
+
], u = (e) => typeof e == "string" && l.includes(e), d = l.map((e) => `'${e}'`).join(" | "), f = (e, t) => `[voltro] ${e}: unknown renderMode '${t}'.\n Valid values: ${d}.${t === "client" || t === "csr" || t === "browser" ? "\n A page that renders only in the browser is 'spa': it is skipped by the prerender and mounts on the client. If its route has a layout, that layout still renders server-side as an SSR shell." : t === "server" || t === "dynamic" ? "\n A page rendered per request is 'ssr'." : t === "ssg" || t === "prerender" ? "\n A page rendered once at build time is 'static' (the default)." : ""}`, p = class extends Error {
|
|
55
|
+
page;
|
|
56
|
+
value;
|
|
57
|
+
name = "InvalidRenderModeError";
|
|
58
|
+
constructor(e, t) {
|
|
59
|
+
super(f(e, t)), this.page = e, this.value = t;
|
|
60
|
+
}
|
|
61
|
+
}, m = (e, t = "<page>") => {
|
|
62
|
+
if (e.renderMode !== void 0 && e.renderMode !== null) {
|
|
63
|
+
if (!u(e.renderMode)) throw new p(t, String(e.renderMode));
|
|
64
|
+
return e.renderMode;
|
|
65
|
+
}
|
|
66
|
+
return e.dynamic === "force-dynamic" ? "ssr" : (e.dynamic, "static");
|
|
67
|
+
}, h = (e, t = "<page>") => ({
|
|
68
|
+
renderMode: m(e, t),
|
|
69
|
+
tenantAware: e.tenantAware === !0,
|
|
70
|
+
revalidateMs: a(e.revalidate),
|
|
71
|
+
staleWhileRevalidateMs: a(e.staleWhileRevalidate) ?? 0,
|
|
72
|
+
cacheInvalidatesOn: Array.isArray(e.cacheInvalidatesOn) ? e.cacheInvalidatesOn : [],
|
|
73
|
+
interactive: e.interactive ?? "full",
|
|
74
|
+
hasLoader: typeof e.loader == "function",
|
|
75
|
+
hasMeta: e.meta != null,
|
|
76
|
+
hasGetStaticPaths: typeof e.getStaticPaths == "function",
|
|
77
|
+
hasOgImage: typeof e.ogImage == "function",
|
|
78
|
+
ppr: e.ppr === !0
|
|
79
|
+
}), g = /export\s+const\s+renderMode\s*(?::[^=]+)?=\s*['"]([^'"]*)['"]/, _ = (e) => g.exec(e)?.[1] ?? null, v = /export\s*\{([^}]*)\}\s*from\s*['"]([^'"]+)['"]/g, y = (e) => {
|
|
80
|
+
v.lastIndex = 0;
|
|
81
|
+
let t;
|
|
82
|
+
for (; (t = v.exec(e)) !== null;) {
|
|
83
|
+
let e = t[2];
|
|
84
|
+
if (e.startsWith(".")) for (let n of t[1].split(",")) {
|
|
85
|
+
let t = n.lastIndexOf(" as ");
|
|
86
|
+
if ((t === -1 ? n : n.slice(t + 4)).trim() === "renderMode") return e;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return null;
|
|
90
|
+
}, b = /export\s*\{([^}]*)\}/g, x = (e) => {
|
|
91
|
+
if (/export\s+default\b/.test(e)) return !0;
|
|
92
|
+
b.lastIndex = 0;
|
|
93
|
+
let t;
|
|
94
|
+
for (; (t = b.exec(e)) !== null;) for (let e of t[1].split(",")) {
|
|
95
|
+
let t = e.lastIndexOf(" as ");
|
|
96
|
+
if ((t === -1 ? e : e.slice(t + 4)).trim() === "default") return !0;
|
|
97
|
+
}
|
|
98
|
+
return !1;
|
|
99
|
+
}, S = async (e, t, n = /* @__PURE__ */ new Set()) => {
|
|
100
|
+
if (/^export const searchParams\b/m.test(e)) return !0;
|
|
101
|
+
b.lastIndex = 0;
|
|
102
|
+
let i;
|
|
103
|
+
for (; (i = b.exec(e)) !== null;) for (let e of i[1].split(",")) {
|
|
104
|
+
let t = e.lastIndexOf(" as ");
|
|
105
|
+
if ((t === -1 ? e : e.slice(t + 4)).trim() === "searchParams") return !0;
|
|
106
|
+
}
|
|
107
|
+
if (n.size >= 4) return !1;
|
|
108
|
+
let a = new RegExp(C, "g"), o;
|
|
109
|
+
for (; (o = a.exec(e)) !== null;) {
|
|
110
|
+
let e = o[1];
|
|
111
|
+
if (e.startsWith(".")) for (let i of w(t, e)) {
|
|
112
|
+
if (n.has(i)) continue;
|
|
113
|
+
let e;
|
|
114
|
+
try {
|
|
115
|
+
e = await r(i, "utf8");
|
|
116
|
+
} catch {
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
let t = new Set(n);
|
|
120
|
+
if (t.add(i), await S(e, i, t)) return !0;
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return !1;
|
|
125
|
+
}, C = String.raw`export\s+\*\s+from\s+['"]([^'"]+)['"]`, w = (r, i) => {
|
|
126
|
+
let a = n(e(r), i);
|
|
127
|
+
return /\.[tj]sx?$/.test(i) ? [a] : [
|
|
128
|
+
`${a}.tsx`,
|
|
129
|
+
`${a}.ts`,
|
|
130
|
+
t(a, "index.tsx"),
|
|
131
|
+
t(a, "index.ts")
|
|
132
|
+
];
|
|
133
|
+
}, T = async (e, n) => {
|
|
134
|
+
let i = (await Promise.all(n.map(async (n) => {
|
|
135
|
+
let i;
|
|
136
|
+
try {
|
|
137
|
+
i = await r(t(e, n.file), "utf8");
|
|
138
|
+
} catch {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
let a = _(i);
|
|
142
|
+
return a !== null && !u(a) ? f(t("src", "pages", n.file), a) : a === "isr" && await S(i, t(e, n.file)) ? `${t("src", "pages", n.file)} declares BOTH renderMode 'isr' and a \`searchParams\` schema.\n\n The isr cache is keyed by path (plus tenant+locale) — the query string is not part of\n the key, so the first request's variant would be cached and served for every other\n query. A page whose render varies by search params cannot be isr-cached safely.\n\n Fix: use \`renderMode: 'ssr'\` (per-request render, params fully honoured), or remove\n the \`searchParams\` export and read the query client-side only.` : x(i) ? null : `${t("src", "pages", n.file)} is a route (a \`page.tsx\` under src/pages/) but exports no default.\n\n A page's default export IS its component — the router has nothing to render without it,\n and the failure would otherwise surface only in \`voltro build\`'s prerender as\n "SSR received a descriptor with no Component", long after the file was written.\n\n Fix: \`export default function Page() { … }\`, or re-export another page's component\n (\`export { default } from '../page'\`). If this file is NOT a route, rename it —\n only the reserved names route, and anything else under src/pages/ is ordinary code\n that may live beside the page that uses it.`;
|
|
143
|
+
}))).filter((e) => e !== null);
|
|
144
|
+
if (i.length !== 0) throw Error(i.join("\n\n"));
|
|
145
|
+
};
|
|
146
|
+
//#endregion
|
|
147
|
+
export { h as a, m as c, c as d, i as f, l as i, o as l, _ as n, u as o, a as p, y as r, f as s, T as t, s as u };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { i as t, n, o as r, r as i, s as a } from "./renderModeScan-
|
|
1
|
+
import { g as e } from "./fileConventions-l-RIXbx8.js";
|
|
2
|
+
import { i as t, n, o as r, r as i, s as a } from "./renderModeScan-43yQ2opo.js";
|
|
3
3
|
import { dirname as o, join as s, relative as c, resolve as l } from "node:path";
|
|
4
4
|
import { Effect as u } from "effect";
|
|
5
5
|
import { readFile as d, readdir as f } from "node:fs/promises";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as e } from "./apiBuild-
|
|
1
|
+
import { n as e } from "./apiBuild-DTWp0S_q.js";
|
|
2
2
|
import { join as t, resolve as n, sep as r } from "node:path";
|
|
3
3
|
import { existsSync as i, promises as a } from "node:fs";
|
|
4
4
|
import { createLogger as o } from "@voltro/logger";
|
|
@@ -422,7 +422,7 @@ let package = Package(
|
|
|
422
422
|
await l.mkdir(o(e), { recursive: !0 }), await l.writeFile(e, n.content, "utf8");
|
|
423
423
|
}
|
|
424
424
|
}, X = async (e) => {
|
|
425
|
-
let { offlineManifest: t } = await import("./checkCommand-
|
|
425
|
+
let { offlineManifest: t } = await import("./checkCommand-L7DTlpIF.js"), { manifest: n } = await t(e);
|
|
426
426
|
return n;
|
|
427
427
|
}, Z = async (e) => {
|
|
428
428
|
let t = J(await (e.manifestProvider ?? X)(e.root), {
|