@voltro/cli 0.38.0 → 0.39.1
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 +276 -0
- package/THIRD-PARTY-NOTICES.md +80 -45
- package/dist/{addCommand-BNeoeSxe.js → addCommand-C05L9tZh.js} +2 -2
- package/dist/addCommand-C3MdJG-a.js +2 -0
- package/dist/{agentsMd-mhQMF1bx.js → agentsMd-7zI2h5l9.js} +3 -3
- package/dist/agentsMd-BFCXh2gl.js +2 -0
- package/dist/apiBuild-BmR_bIxN.js +2 -0
- package/dist/{apiBuild-CvacV4zA.js → apiBuild-D9FB13_2.js} +3 -3
- package/dist/baselineCommand-CXv680Dc.js +2 -0
- package/dist/{baselineCommand-C6NMt-oa.js → baselineCommand-Ck2Xm8M7.js} +18 -18
- package/dist/bin.js +1 -1
- package/dist/{build-_LoTC1s0.js → build-DORV5mLM.js} +107 -100
- package/dist/{capabilitiesCommand-nq_pz5xd.js → capabilitiesCommand-D5gucwYa.js} +8 -8
- package/dist/{checkCommand-Pjk5sBl2.js → checkCommand-Bf6oMao4.js} +35 -35
- package/dist/{checkCommand-wibtQx-N.js → checkCommand-D9qK_gtA.js} +1 -1
- package/dist/{cloudCmd-NQSwe_Qk.js → cloudCmd-C42gaO8s.js} +16 -16
- package/dist/{clusterCmd-D5wsCmA_.js → clusterCmd-DrVFCzSj.js} +8 -4
- package/dist/{codegen-GYYcdpCg.js → codegen-CbpGCWLG.js} +1 -1
- package/dist/codegen-i8QGcHsi.js +2 -0
- package/dist/codegenCommand-CxOyKmc1.js +129 -0
- package/dist/{codemodRunner-CXgQ-ecJ.js → codemodRunner-D-jTyvWo.js} +622 -551
- package/dist/{commands-DaZVi9wi.js → commands-D6aW_6AR.js} +48 -48
- package/dist/{connectionConfig-UFlIEiys.js → connectionConfig-Bk9IC7D0.js} +1 -1
- package/dist/{dashboardCommand-Dxy_kmoW.js → dashboardCommand-CwTZh-XZ.js} +3 -3
- package/dist/{dataCommand-D6-Ha2lf.js → dataCommand-Cc9RiLQZ.js} +14 -11
- package/dist/{dbCommand-C4UW8cVN.js → dbCommand-DSwGv9wS.js} +50 -49
- package/dist/dbCommand-DcqEyxju.js +2 -0
- package/dist/{dev-E7Eo5GHc.js → dev-3mgc8c-H.js} +2260 -2184
- package/dist/dev-CjJAasDs.js +3 -0
- package/dist/{dialectDriver-CgXnDfec.js → dialectDriver-czCHYpeH.js} +2 -1
- package/dist/doctorCommand-Cghssndo.js +2 -0
- package/dist/{doctorCommand-gmDyALFL.js → doctorCommand-oLuzc-aC.js} +261 -244
- package/dist/{dormancyCommand-CE6wG8lj.js → dormancyCommand-Bxe4WtHU.js} +1 -1
- package/dist/{e2eCmd-BRabZww-.js → e2eCmd-uFHig1hV.js} +8 -2
- package/dist/{embeddingsCommand-C3uAuf6N.js → embeddingsCommand-CyNQkFIc.js} +6 -6
- package/dist/{envCommand-DzuWh8ya.js → envCommand-CAkSgBbh.js} +19 -19
- package/dist/{evolveCommand-DPLqcYb2.js → evolveCommand-CWhBoe_P.js} +6 -8
- package/dist/frameworkTableAssembly-DgylYh9_.js +2 -0
- package/dist/{generateCommand-DbgcUpGw.js → generateCommand-CcyvH2ve.js} +1 -1
- package/dist/index.js +1 -1
- package/dist/{infoCommand-CmczGj_l.js → infoCommand-CTo8Jnhq.js} +7 -7
- package/dist/inspect-B7U7Cl_Z.js +1192 -0
- package/dist/inspect-DUze25t0.js +2 -0
- package/dist/{inspectCmd-EHFZ9yYu.js → inspectCmd-niF97fAq.js} +5 -5
- package/dist/inspectGateHint-BjnFubmH.js +7 -0
- package/dist/{logFileSink-C_D2wRN1.js → logFileSink-B4uP8pvf.js} +1 -1
- package/dist/{logsCmd-D36xK7Zu.js → logsCmd-B6oNsfaZ.js} +10 -7
- package/dist/{manifestBuild-hpPLaGxV.js → manifestBuild-BK42hu0k.js} +1 -1
- package/dist/manifestBuild-j0n109tt.js +2 -0
- package/dist/{metaCommands-CIoQNlaQ.js → metaCommands-DUYR--Ts.js} +1 -1
- package/dist/{migrate-RwgUWXfc.js → migrate-BnPw2zC8.js} +7 -4
- package/dist/{packageCommand-Cug_3Ogl.js → packageCommand-9SVyvsSo.js} +3 -2
- package/dist/{probeCommand-BPEpwT32.js → probeCommand-C9gazU0H.js} +35 -24
- package/dist/{projectScaffold-CxgtJvlb.js → projectScaffold-BEhhHjPr.js} +1 -1
- package/dist/{projectScaffold-DDgWbNLe.js → projectScaffold-BvhLOrLq.js} +17 -15
- package/dist/{runtimeTrace-6jfznSzr.js → runtimeTrace-gNXeLf6H.js} +1 -1
- package/dist/{scheduleManifestCmd-D2x0CTTY.js → scheduleManifestCmd-kmWzrO_w.js} +6 -9
- package/dist/{sdkgen-CEJZZQUA.js → sdkgen-C8zz10-X.js} +4 -4
- package/dist/{seedRunner-ZmLSqNe2.js → seedRunner-IdHEprqf.js} +1 -4
- package/dist/serveCommand-BpK8-m1N.js +1770 -0
- package/dist/serveCommand-CW-goXvh.js +2 -0
- package/dist/serveEntry.js +2 -2
- package/dist/{serverlessCommand-CfJZy6dS.js → serverlessCommand-DbJ7Plg9.js} +3 -3
- package/dist/{start-CidwCcjl.js → start-BNuTWdRd.js} +1 -1
- package/dist/{start-RCh6qKFe.js → start-ft_KzFTd.js} +257 -254
- package/dist/startEntry.js +1 -1
- package/dist/{test-DIQ0jlkQ.js → test-CLYXrZ2F.js} +1 -1
- package/dist/{tracesCmd-DStmCJPi.js → tracesCmd-DgtgOUdi.js} +7 -4
- package/dist/{typecheckCommand-BlsWiCNq.js → typecheckCommand-BuCtT92o.js} +7 -7
- package/dist/updateCommand-6FMU2klq.js +2 -0
- package/dist/{updateCommand-CmksX7m_.js → updateCommand-CHBmCB17.js} +5 -3
- package/dist/{webDev-BKdD7c_a.js → webDev-CTpSY-e_.js} +813 -775
- package/dist/webDev-id3I5PvG.js +2 -0
- package/dist/{webhookDiscovery-D7VaeMlz.js → webhookDiscovery-CphsQe59.js} +4 -6
- package/dist/{webhookDiscovery-CrGAfhIG.js → webhookDiscovery-il9ti-HE.js} +1 -1
- package/dist/{webhooksCommand-BHeaF1ZJ.js → webhooksCommand-EccPZQZ4.js} +1 -1
- package/package.json +27 -21
- package/templates/AGENTS.md +2 -2
- package/templates/agent-docs/_index.md +2 -2
- package/templates/agent-docs/_manifest.json +2 -2
- package/templates/agent-docs/authentication.md +43 -4
- package/templates/agent-docs/cli.md +17 -13
- package/templates/agent-docs/data.md +44 -1
- package/templates/agent-docs/database/migrations.md +2 -2
- package/templates/agent-docs/database/seedsdialects.md +2 -2
- package/templates/agent-docs/deployment.md +21 -7
- package/templates/agent-docs/internationalization.md +10 -3
- package/templates/agent-docs/local-first-mobile.md +141 -20
- package/templates/agent-docs/plugins/mail.md +1 -1
- package/templates/agent-docs/plugins/ratelimit.md +1 -1
- package/templates/agent-docs/plugins.md +3 -1
- package/templates/agent-docs/releases.md +130 -1
- package/templates/agent-docs/routing.md +34 -2
- package/templates/agent-docs/templates/apibackends.md +1 -1
- package/templates/agent-docs/templates/mobile.md +1 -1
- package/templates/agent-docs/whats-new.md +26 -66
- 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-collab/package.json +8 -8
- package/templates/apps/api-data-advanced/package.json +8 -8
- package/templates/apps/api-durable/package.json +8 -8
- package/templates/apps/api-durable/startup/warm.startup.tsx +16 -2
- 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/authz.ts +16 -1
- 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/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/README.md +41 -17
- package/templates/apps/mobile-app/app.config.ts +1 -1
- package/templates/apps/mobile-app/package.json +15 -11
- package/templates/apps/mobile-app/src/app/_layout.tsx +44 -13
- package/templates/apps/mobile-app/src/app/index.tsx +1 -1
- package/templates/apps/mobile-app/src/app/settings.tsx +4 -1
- package/templates/apps/mobile-app/src/client.ts +74 -57
- package/templates/apps/mobile-app/src/lib/api.ts +4 -4
- package/templates/apps/mobile-app/src/lib/deeplinks.ts +6 -6
- package/templates/apps/mobile-app/src/persistence.ts +24 -3
- package/templates/apps/mobile-app/tsconfig.json +17 -3
- package/dist/addCommand-aXSQveak.js +0 -2
- package/dist/agentsMd-BTchIZku.js +0 -2
- package/dist/apiBuild-ttSDDOGp.js +0 -2
- package/dist/baselineCommand-Cfw2Afwm.js +0 -2
- package/dist/codegen-uYrrDzQv.js +0 -2
- package/dist/codegenCommand-C60m_LCp.js +0 -30
- package/dist/dbCommand-CC-qNzpz.js +0 -2
- package/dist/dev-CAOoXOkc.js +0 -3
- package/dist/doctorCommand-Cjl8Yii8.js +0 -2
- package/dist/frameworkTableAssembly-YyVe32Cb.js +0 -2
- package/dist/inspect-CjTYzAs_.js +0 -1190
- package/dist/inspect-P4pxoMaV.js +0 -2
- package/dist/inspectGateHint-BF6608UT.js +0 -4
- package/dist/manifestBuild-COkJoyAr.js +0 -2
- package/dist/serveCommand-DNRF2nDI.js +0 -2
- package/dist/serveCommand-DnY4VS3D.js +0 -1767
- package/dist/updateCommand-B0J_T9Vs.js +0 -2
- package/dist/webDev-CcJfdSjl2.js +0 -2
|
@@ -12,16 +12,16 @@
|
|
|
12
12
|
"test": "voltro test"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@voltro/cli": "0.
|
|
16
|
-
"@voltro/client": "0.
|
|
17
|
-
"@voltro/env": "0.
|
|
18
|
-
"@voltro/i18n": "0.
|
|
19
|
-
"@voltro/web": "0.
|
|
15
|
+
"@voltro/cli": "0.39.1",
|
|
16
|
+
"@voltro/client": "0.39.1",
|
|
17
|
+
"@voltro/env": "0.39.1",
|
|
18
|
+
"@voltro/i18n": "0.39.1",
|
|
19
|
+
"@voltro/web": "0.39.1",
|
|
20
20
|
"react": "^19.0.0",
|
|
21
21
|
"react-dom": "^19.0.0"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@voltro/devtools": "0.
|
|
24
|
+
"@voltro/devtools": "0.39.1",
|
|
25
25
|
"@types/react": "^19.0.0",
|
|
26
26
|
"@types/react-dom": "^19.0.0",
|
|
27
27
|
"jsdom": "^30.0.0",
|
|
@@ -12,17 +12,17 @@
|
|
|
12
12
|
"typecheck": "tsc --noEmit"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@voltro/cli": "0.
|
|
16
|
-
"@voltro/client": "0.
|
|
17
|
-
"@voltro/env": "0.
|
|
18
|
-
"@voltro/i18n": "0.
|
|
19
|
-
"@voltro/ui-shadcn": "0.
|
|
20
|
-
"@voltro/web": "0.
|
|
15
|
+
"@voltro/cli": "0.39.1",
|
|
16
|
+
"@voltro/client": "0.39.1",
|
|
17
|
+
"@voltro/env": "0.39.1",
|
|
18
|
+
"@voltro/i18n": "0.39.1",
|
|
19
|
+
"@voltro/ui-shadcn": "0.39.1",
|
|
20
|
+
"@voltro/web": "0.39.1",
|
|
21
21
|
"react": "^19.0.0",
|
|
22
22
|
"react-dom": "^19.0.0"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"@voltro/devtools": "0.
|
|
25
|
+
"@voltro/devtools": "0.39.1",
|
|
26
26
|
"@types/react": "^19.0.0",
|
|
27
27
|
"@types/react-dom": "^19.0.0",
|
|
28
28
|
"jsdom": "^30.0.0",
|
|
@@ -12,18 +12,18 @@
|
|
|
12
12
|
"test": "voltro test"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@{{projectName}}/api": "0.
|
|
16
|
-
"@voltro/cli": "0.
|
|
17
|
-
"@voltro/client": "0.
|
|
18
|
-
"@voltro/env": "0.
|
|
19
|
-
"@voltro/i18n": "0.
|
|
20
|
-
"@voltro/ui-shadcn": "0.
|
|
21
|
-
"@voltro/web": "0.
|
|
15
|
+
"@{{projectName}}/api": "0.39.1",
|
|
16
|
+
"@voltro/cli": "0.39.1",
|
|
17
|
+
"@voltro/client": "0.39.1",
|
|
18
|
+
"@voltro/env": "0.39.1",
|
|
19
|
+
"@voltro/i18n": "0.39.1",
|
|
20
|
+
"@voltro/ui-shadcn": "0.39.1",
|
|
21
|
+
"@voltro/web": "0.39.1",
|
|
22
22
|
"react": "^19.0.0",
|
|
23
23
|
"react-dom": "^19.0.0"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@voltro/devtools": "0.
|
|
26
|
+
"@voltro/devtools": "0.39.1",
|
|
27
27
|
"@types/react": "^19.0.0",
|
|
28
28
|
"@types/react-dom": "^19.0.0",
|
|
29
29
|
"jsdom": "^30.0.0",
|
|
@@ -12,18 +12,18 @@
|
|
|
12
12
|
"test": "voltro test"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@{{projectName}}/api": "0.
|
|
16
|
-
"@voltro/cli": "0.
|
|
17
|
-
"@voltro/client": "0.
|
|
18
|
-
"@voltro/env": "0.
|
|
19
|
-
"@voltro/i18n": "0.
|
|
20
|
-
"@voltro/ui-shadcn": "0.
|
|
21
|
-
"@voltro/web": "0.
|
|
15
|
+
"@{{projectName}}/api": "0.39.1",
|
|
16
|
+
"@voltro/cli": "0.39.1",
|
|
17
|
+
"@voltro/client": "0.39.1",
|
|
18
|
+
"@voltro/env": "0.39.1",
|
|
19
|
+
"@voltro/i18n": "0.39.1",
|
|
20
|
+
"@voltro/ui-shadcn": "0.39.1",
|
|
21
|
+
"@voltro/web": "0.39.1",
|
|
22
22
|
"react": "^19.0.0",
|
|
23
23
|
"react-dom": "^19.0.0"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@voltro/devtools": "0.
|
|
26
|
+
"@voltro/devtools": "0.39.1",
|
|
27
27
|
"@types/react": "^19.0.0",
|
|
28
28
|
"@types/react-dom": "^19.0.0",
|
|
29
29
|
"jsdom": "^30.0.0",
|
|
@@ -12,17 +12,17 @@
|
|
|
12
12
|
"typecheck": "tsc --noEmit"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@voltro/cli": "0.
|
|
16
|
-
"@voltro/client": "0.
|
|
17
|
-
"@voltro/env": "0.
|
|
18
|
-
"@voltro/i18n": "0.
|
|
19
|
-
"@voltro/ui-shadcn": "0.
|
|
20
|
-
"@voltro/web": "0.
|
|
15
|
+
"@voltro/cli": "0.39.1",
|
|
16
|
+
"@voltro/client": "0.39.1",
|
|
17
|
+
"@voltro/env": "0.39.1",
|
|
18
|
+
"@voltro/i18n": "0.39.1",
|
|
19
|
+
"@voltro/ui-shadcn": "0.39.1",
|
|
20
|
+
"@voltro/web": "0.39.1",
|
|
21
21
|
"react": "^19.0.0",
|
|
22
22
|
"react-dom": "^19.0.0"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"@voltro/devtools": "0.
|
|
25
|
+
"@voltro/devtools": "0.39.1",
|
|
26
26
|
"@types/react": "^19.0.0",
|
|
27
27
|
"@types/react-dom": "^19.0.0",
|
|
28
28
|
"jsdom": "^30.0.0",
|
|
@@ -12,17 +12,17 @@
|
|
|
12
12
|
"test": "voltro test"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@voltro/cli": "0.
|
|
16
|
-
"@voltro/client": "0.
|
|
17
|
-
"@voltro/env": "0.
|
|
18
|
-
"@voltro/i18n": "0.
|
|
19
|
-
"@voltro/ui-shadcn": "0.
|
|
20
|
-
"@voltro/web": "0.
|
|
15
|
+
"@voltro/cli": "0.39.1",
|
|
16
|
+
"@voltro/client": "0.39.1",
|
|
17
|
+
"@voltro/env": "0.39.1",
|
|
18
|
+
"@voltro/i18n": "0.39.1",
|
|
19
|
+
"@voltro/ui-shadcn": "0.39.1",
|
|
20
|
+
"@voltro/web": "0.39.1",
|
|
21
21
|
"react": "^19.0.0",
|
|
22
22
|
"react-dom": "^19.0.0"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"@voltro/devtools": "0.
|
|
25
|
+
"@voltro/devtools": "0.39.1",
|
|
26
26
|
"@types/react": "^19.0.0",
|
|
27
27
|
"@types/react-dom": "^19.0.0",
|
|
28
28
|
"jsdom": "^30.0.0",
|
|
@@ -12,18 +12,18 @@
|
|
|
12
12
|
"test": "voltro test"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@{{projectName}}/api": "0.
|
|
16
|
-
"@voltro/cli": "0.
|
|
17
|
-
"@voltro/client": "0.
|
|
18
|
-
"@voltro/env": "0.
|
|
19
|
-
"@voltro/i18n": "0.
|
|
20
|
-
"@voltro/ui-shadcn": "0.
|
|
21
|
-
"@voltro/web": "0.
|
|
15
|
+
"@{{projectName}}/api": "0.39.1",
|
|
16
|
+
"@voltro/cli": "0.39.1",
|
|
17
|
+
"@voltro/client": "0.39.1",
|
|
18
|
+
"@voltro/env": "0.39.1",
|
|
19
|
+
"@voltro/i18n": "0.39.1",
|
|
20
|
+
"@voltro/ui-shadcn": "0.39.1",
|
|
21
|
+
"@voltro/web": "0.39.1",
|
|
22
22
|
"react": "^19.0.0",
|
|
23
23
|
"react-dom": "^19.0.0"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@voltro/devtools": "0.
|
|
26
|
+
"@voltro/devtools": "0.39.1",
|
|
27
27
|
"@types/react": "^19.0.0",
|
|
28
28
|
"@types/react-dom": "^19.0.0",
|
|
29
29
|
"jsdom": "^30.0.0",
|
|
@@ -12,16 +12,16 @@
|
|
|
12
12
|
"test": "voltro test"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@voltro/cli": "0.
|
|
16
|
-
"@voltro/client": "0.
|
|
17
|
-
"@voltro/env": "0.
|
|
18
|
-
"@voltro/i18n": "0.
|
|
19
|
-
"@voltro/web": "0.
|
|
15
|
+
"@voltro/cli": "0.39.1",
|
|
16
|
+
"@voltro/client": "0.39.1",
|
|
17
|
+
"@voltro/env": "0.39.1",
|
|
18
|
+
"@voltro/i18n": "0.39.1",
|
|
19
|
+
"@voltro/web": "0.39.1",
|
|
20
20
|
"react": "^19.0.0",
|
|
21
21
|
"react-dom": "^19.0.0"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@voltro/devtools": "0.
|
|
24
|
+
"@voltro/devtools": "0.39.1",
|
|
25
25
|
"@types/react": "^19.0.0",
|
|
26
26
|
"@types/react-dom": "^19.0.0",
|
|
27
27
|
"jsdom": "^30.0.0",
|
|
@@ -12,18 +12,18 @@
|
|
|
12
12
|
"test": "voltro test"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@{{projectName}}/api": "0.
|
|
16
|
-
"@voltro/cli": "0.
|
|
17
|
-
"@voltro/client": "0.
|
|
18
|
-
"@voltro/env": "0.
|
|
19
|
-
"@voltro/i18n": "0.
|
|
20
|
-
"@voltro/ui-shadcn": "0.
|
|
21
|
-
"@voltro/web": "0.
|
|
15
|
+
"@{{projectName}}/api": "0.39.1",
|
|
16
|
+
"@voltro/cli": "0.39.1",
|
|
17
|
+
"@voltro/client": "0.39.1",
|
|
18
|
+
"@voltro/env": "0.39.1",
|
|
19
|
+
"@voltro/i18n": "0.39.1",
|
|
20
|
+
"@voltro/ui-shadcn": "0.39.1",
|
|
21
|
+
"@voltro/web": "0.39.1",
|
|
22
22
|
"react": "^19.0.0",
|
|
23
23
|
"react-dom": "^19.0.0"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@voltro/devtools": "0.
|
|
26
|
+
"@voltro/devtools": "0.39.1",
|
|
27
27
|
"@types/react": "^19.0.0",
|
|
28
28
|
"@types/react-dom": "^19.0.0",
|
|
29
29
|
"jsdom": "^30.0.0",
|
|
@@ -15,12 +15,14 @@ registration for push.
|
|
|
15
15
|
# 1. In one shell — the api (scaffold it with --api=api-backend):
|
|
16
16
|
voltro dev
|
|
17
17
|
|
|
18
|
-
# 2.
|
|
19
|
-
#
|
|
20
|
-
export EXPO_PUBLIC_API_URL="http://192.168.x.x:4000"
|
|
21
|
-
|
|
22
|
-
# 3. In another shell — the app:
|
|
18
|
+
# 2. In another shell — the app. `pnpm ios` runs `voltro codegen` first, which
|
|
19
|
+
# writes this app's api binding from voltro.mobile.ts.
|
|
23
20
|
pnpm ios # or: pnpm android · pnpm start (Expo Go)
|
|
21
|
+
|
|
22
|
+
# The ws URL is derived from the host running Metro, so a device on the same
|
|
23
|
+
# wifi reaches your machine. Override it for a deployed api:
|
|
24
|
+
# export EXPO_PUBLIC_API_WS_URL="wss://api.example.com/ws"
|
|
25
|
+
# export EXPO_PUBLIC_API_PORT=4000 # if your api is not on 4000
|
|
24
26
|
```
|
|
25
27
|
|
|
26
28
|
## What's here
|
|
@@ -31,25 +33,32 @@ pnpm ios # or: pnpm android · pnpm start (Expo Go)
|
|
|
31
33
|
| `src/lib/deeplinks.ts` | the typed deep-link table + pure resolver (**tested**) |
|
|
32
34
|
| `src/lib/sync.ts` | the background-sync decision layer (**tested**) |
|
|
33
35
|
| `src/lib/notifications.ts` | build a `_voltro_devices` row from a push token (**tested**) |
|
|
34
|
-
| `src/client.ts` | the Voltro client
|
|
36
|
+
| `src/client.ts` | the Voltro client: generated api binding + supervisor + persistence |
|
|
35
37
|
| `src/persistence.ts` | RN key-value with the secure/plain split |
|
|
36
38
|
| `src/app/*` | Expo Router screens (list, detail, settings) |
|
|
37
39
|
| `voltro.mobile.ts` | which api(s) this app consumes |
|
|
38
40
|
|
|
39
41
|
## Honest status (read before you expect the loop to work on a device)
|
|
40
42
|
|
|
41
|
-
The
|
|
42
|
-
|
|
43
|
-
the
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
The client is wired: `voltro codegen` writes this app's api binding from
|
|
44
|
+
`voltro.mobile.ts`, and `src/client.ts` connects it through the SAME reconnect
|
|
45
|
+
supervisor the web client uses, with persisted stores hydrated before the first
|
|
46
|
+
render. The start scripts run codegen, so `pnpm ios` needs no separate step.
|
|
47
|
+
|
|
48
|
+
What is NOT verified in this repository is the one thing only a device can tell
|
|
49
|
+
you: that the loop runs under Metro on a simulator or a phone. There is no
|
|
50
|
+
iOS/Android toolchain in the framework's sandbox, so booting the app is your
|
|
51
|
+
Expo/EAS CI step. The unit tests here run without one and deliberately do not
|
|
52
|
+
pretend otherwise.
|
|
53
|
+
|
|
54
|
+
Two things to check first if a device shows loading forever:
|
|
49
55
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
56
|
+
- **`localhost` on a phone is the phone.** The ws URL is derived from the host
|
|
57
|
+
running Metro (`resolveDevWsUrl`), which works on a device on the same wifi.
|
|
58
|
+
Set `EXPO_PUBLIC_API_WS_URL` to point somewhere else.
|
|
59
|
+
- **The api must be running.** `voltro dev` in the project root boots it; this
|
|
60
|
+
app is deliberately not part of that orchestration, because Expo owns its own
|
|
61
|
+
dev server.
|
|
53
62
|
|
|
54
63
|
## Tests
|
|
55
64
|
|
|
@@ -57,3 +66,18 @@ framework repo's sandbox.
|
|
|
57
66
|
pnpm test # the pure lib — no simulator needed
|
|
58
67
|
pnpm typecheck # tsc over the app (needs Expo/RN types installed)
|
|
59
68
|
```
|
|
69
|
+
|
|
70
|
+
### Why this app's `tsconfig.json` overrides Expo's base
|
|
71
|
+
|
|
72
|
+
Three overrides, each for a reason that shows up as a hard error without it:
|
|
73
|
+
|
|
74
|
+
- **`moduleResolution: "bundler"`** — Expo's base sets `node` (node10), which
|
|
75
|
+
TypeScript 6 rejects outright. `bundler` is also the honest description of
|
|
76
|
+
Metro.
|
|
77
|
+
- **`types: ["node", "react"]`** — `process.env.EXPO_PUBLIC_*` is Expo's own
|
|
78
|
+
idiom for build-time config, and `process` needs a type. Listing the types
|
|
79
|
+
explicitly keeps everything else out.
|
|
80
|
+
- **`@types/node` as a devDependency** — the other half of the same line.
|
|
81
|
+
|
|
82
|
+
Run `pnpm typecheck` after `voltro codegen`, in that order: the generated api
|
|
83
|
+
binding is a real import and the app does not typecheck without it.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// mobile app is not run by `voltro dev` — Expo owns Metro and the simulator
|
|
5
5
|
// (`expo start` / `expo run:ios`). The sibling api this app consumes still runs
|
|
6
6
|
// under `voltro dev`; the app connects to it over HTTP/WebSocket via
|
|
7
|
-
// `
|
|
7
|
+
// `EXPO_PUBLIC_API_WS_URL` / `EXPO_PUBLIC_API_PORT` (see src/client.ts).
|
|
8
8
|
//
|
|
9
9
|
// `scheme` is the custom URL scheme that makes deep links open THIS app
|
|
10
10
|
// (`{{appName}}://orders/42`). Keep it in sync with the deep-link table in
|
|
@@ -4,32 +4,36 @@
|
|
|
4
4
|
"private": true,
|
|
5
5
|
"main": "expo-router/entry",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"start": "expo start",
|
|
8
|
-
"ios": "expo run:ios",
|
|
9
|
-
"android": "expo run:android",
|
|
10
|
-
"web": "expo start --web",
|
|
7
|
+
"start": "voltro codegen . && expo start",
|
|
8
|
+
"ios": "voltro codegen . && expo run:ios",
|
|
9
|
+
"android": "voltro codegen . && expo run:android",
|
|
10
|
+
"web": "voltro codegen . && expo start --web",
|
|
11
11
|
"test": "vitest run",
|
|
12
|
-
"typecheck": "tsc --noEmit"
|
|
12
|
+
"typecheck": "tsc --noEmit",
|
|
13
|
+
"codegen": "voltro codegen ."
|
|
13
14
|
},
|
|
14
15
|
"dependencies": {
|
|
15
|
-
"@
|
|
16
|
-
"@
|
|
16
|
+
"@react-native-async-storage/async-storage": "1.23.1",
|
|
17
|
+
"@react-native-community/netinfo": "11.4.1",
|
|
18
|
+
"@voltro/client": "0.39.1",
|
|
19
|
+
"@voltro/react-native": "0.39.1",
|
|
20
|
+
"@{{projectName}}/api": "0.39.1",
|
|
17
21
|
"expo": "^52.0.0",
|
|
18
22
|
"expo-constants": "~17.0.0",
|
|
19
23
|
"expo-linking": "~7.0.0",
|
|
20
24
|
"expo-router": "~4.0.0",
|
|
21
25
|
"expo-secure-store": "~14.0.0",
|
|
26
|
+
"expo-splash-screen": "~0.29.0",
|
|
22
27
|
"expo-status-bar": "~2.0.0",
|
|
23
|
-
"@react-native-async-storage/async-storage": "1.23.1",
|
|
24
|
-
"@react-native-community/netinfo": "11.4.1",
|
|
25
28
|
"react": "^19.0.0",
|
|
26
29
|
"react-native": "0.76.5"
|
|
27
30
|
},
|
|
28
31
|
"devDependencies": {
|
|
29
|
-
"@
|
|
32
|
+
"@types/node": "^22.0.0",
|
|
30
33
|
"@types/react": "^19.0.0",
|
|
31
|
-
"typescript": "^6.0.3",
|
|
32
34
|
"@vitest/coverage-v8": "^4.1.10",
|
|
35
|
+
"@voltro/cli": "0.39.1",
|
|
36
|
+
"typescript": "^6.0.3",
|
|
33
37
|
"vitest": "^4.1.10"
|
|
34
38
|
}
|
|
35
39
|
}
|
|
@@ -1,21 +1,35 @@
|
|
|
1
|
-
// Root layout — wires the Voltro client
|
|
2
|
-
//
|
|
1
|
+
// Root layout — wires the Voltro client, deep-link routing, and a connection
|
|
2
|
+
// banner around the whole app.
|
|
3
3
|
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
4
|
+
// The boot ORDER here is load-bearing, and it is the one thing to preserve if
|
|
5
|
+
// you rewrite this file:
|
|
6
|
+
//
|
|
7
|
+
// 1. hydrate persisted stores, THEN install them as the backing store;
|
|
8
|
+
// 2. only then render the app.
|
|
9
|
+
//
|
|
10
|
+
// A store reads during render and a render cannot await, so rendering first
|
|
11
|
+
// shows empty state and flickers into the saved state a frame later. The splash
|
|
12
|
+
// screen stays up until step 1 finishes — that is what it is for.
|
|
13
|
+
//
|
|
14
|
+
// Connecting is deliberately NOT part of that gate. The app must open offline.
|
|
7
15
|
import { useEffect, useState } from 'react'
|
|
8
16
|
import { Stack, useRouter } from 'expo-router'
|
|
9
17
|
import * as Linking from 'expo-linking'
|
|
18
|
+
import * as SplashScreen from 'expo-splash-screen'
|
|
10
19
|
import { StatusBar } from 'expo-status-bar'
|
|
11
|
-
import { FrameworkRuntimesProvider, type ApiHandle } from '@voltro/client'
|
|
20
|
+
import { FrameworkRuntimesProvider, type ApiHandle, type ResolvedClient } from '@voltro/client'
|
|
12
21
|
import { useMobileConnectionStatus } from '@voltro/react-native'
|
|
13
22
|
import { Text, View } from 'react-native'
|
|
14
|
-
import {
|
|
23
|
+
import { connectApis, handlesFor, onlineSource, preparePersistence } from '../client'
|
|
15
24
|
import { handleDeepLink, makeDeepLinks } from '../lib/deeplinks'
|
|
16
25
|
|
|
26
|
+
void SplashScreen.preventAutoHideAsync()
|
|
27
|
+
|
|
17
28
|
function ConnectionBanner() {
|
|
18
|
-
|
|
29
|
+
// Reachability comes from NetInfo. The default source reads `navigator.onLine`,
|
|
30
|
+
// which React Native does not have — so on a device it would answer "online"
|
|
31
|
+
// forever, including in airplane mode.
|
|
32
|
+
const { status } = useMobileConnectionStatus({ onlineSource })
|
|
19
33
|
if (status === 'connected') return null
|
|
20
34
|
return (
|
|
21
35
|
<View style={{ backgroundColor: status === 'offline' ? '#b91c1c' : '#b45309', padding: 8 }}>
|
|
@@ -27,16 +41,31 @@ function ConnectionBanner() {
|
|
|
27
41
|
}
|
|
28
42
|
|
|
29
43
|
export default function RootLayout() {
|
|
30
|
-
|
|
31
|
-
// @voltro/client's buildApiRuntime). Empty until it resolves; the hooks render
|
|
32
|
-
// their loading state meanwhile.
|
|
44
|
+
const [ready, setReady] = useState(false)
|
|
33
45
|
const [apis, setApis] = useState<ReadonlyMap<string, ApiHandle>>(() => new Map())
|
|
46
|
+
const router = useRouter()
|
|
47
|
+
|
|
48
|
+
// 1. Persisted state, before anything renders.
|
|
34
49
|
useEffect(() => {
|
|
35
50
|
let live = true
|
|
36
|
-
void
|
|
51
|
+
void preparePersistence()
|
|
52
|
+
.catch(() => { /* a device with no readable storage still gets an app */ })
|
|
53
|
+
.finally(() => {
|
|
54
|
+
if (!live) return
|
|
55
|
+
setReady(true)
|
|
56
|
+
void SplashScreen.hideAsync()
|
|
57
|
+
})
|
|
37
58
|
return () => { live = false }
|
|
38
59
|
}, [])
|
|
39
|
-
|
|
60
|
+
|
|
61
|
+
// 2. Connect, and keep connected. The supervisor re-dials with backoff; a
|
|
62
|
+
// dropped socket needs no handling here.
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
const supervisor = connectApis((clients: ReadonlyMap<string, ResolvedClient>) => {
|
|
65
|
+
setApis(handlesFor(clients))
|
|
66
|
+
})
|
|
67
|
+
return () => supervisor.dispose()
|
|
68
|
+
}, [])
|
|
40
69
|
|
|
41
70
|
// Route inbound URLs (universal links, custom scheme, push taps) through the
|
|
42
71
|
// ONE typed link table — the same `matchFirstDeepLink` path push will use.
|
|
@@ -51,6 +80,8 @@ export default function RootLayout() {
|
|
|
51
80
|
return () => sub.remove()
|
|
52
81
|
}, [router])
|
|
53
82
|
|
|
83
|
+
if (!ready) return null
|
|
84
|
+
|
|
54
85
|
return (
|
|
55
86
|
<FrameworkRuntimesProvider apis={apis}>
|
|
56
87
|
<StatusBar style="auto" />
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// The SAME hooks as the web frontend: `useSubscription('notes.list')` streams
|
|
4
4
|
// the server-side query; `useMutation('notes.create')` writes it. When the
|
|
5
5
|
// mutation lands, the server pushes a delta and this list re-renders — no
|
|
6
|
-
// refetch, no polling.
|
|
6
|
+
// refetch, no polling.
|
|
7
7
|
//
|
|
8
8
|
// Both come from `../lib/api`, which binds them ONCE to the api's generated
|
|
9
9
|
// procedure map — so the tag autocompletes, a typo is a compile error, and the
|
|
@@ -3,9 +3,12 @@ import { useState } from 'react'
|
|
|
3
3
|
import { Pressable, Text, View } from 'react-native'
|
|
4
4
|
import { useMobileConnectionStatus } from '@voltro/react-native'
|
|
5
5
|
import { buildDeviceRegistration } from '../lib/notifications'
|
|
6
|
+
import { onlineSource } from '../client'
|
|
6
7
|
|
|
7
8
|
export default function Settings() {
|
|
8
|
-
|
|
9
|
+
// Same injected source as the banner in _layout: the default reads
|
|
10
|
+
// `navigator.onLine`, which React Native does not have.
|
|
11
|
+
const { status, reportSuccess, reportFailure } = useMobileConnectionStatus({ onlineSource })
|
|
9
12
|
const [registered, setRegistered] = useState<string | null>(null)
|
|
10
13
|
|
|
11
14
|
return (
|