@repo-os/repoos 0.5.45
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/LICENSE.md +110 -0
- package/README.md +272 -0
- package/dist/.build-info.json +4 -0
- package/dist/.build-stamp.json +3 -0
- package/dist/cli/colors.d.ts +13 -0
- package/dist/cli/colors.js +37 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +221 -0
- package/dist/commands/check.d.ts +170 -0
- package/dist/commands/check.js +1227 -0
- package/dist/commands/docs.d.ts +2 -0
- package/dist/commands/docs.js +70 -0
- package/dist/commands/gc.d.ts +1 -0
- package/dist/commands/gc.js +57 -0
- package/dist/commands/init.d.ts +9 -0
- package/dist/commands/init.js +699 -0
- package/dist/commands/screenshots.d.ts +7 -0
- package/dist/commands/screenshots.js +77 -0
- package/dist/commands/serve.d.ts +55 -0
- package/dist/commands/serve.js +204 -0
- package/dist/commands/status.d.ts +140 -0
- package/dist/commands/status.js +569 -0
- package/dist/commands/stop.d.ts +1 -0
- package/dist/commands/stop.js +59 -0
- package/dist/commands/tasks.d.ts +47 -0
- package/dist/commands/tasks.js +334 -0
- package/dist/commands/tunnel.d.ts +1 -0
- package/dist/commands/tunnel.js +1271 -0
- package/dist/commands/ui-harness.d.ts +53 -0
- package/dist/commands/ui-harness.js +62 -0
- package/dist/commands/ui-smoke.d.ts +6 -0
- package/dist/commands/ui-smoke.js +220 -0
- package/dist/commands/upgrade.d.ts +15 -0
- package/dist/commands/upgrade.js +188 -0
- package/dist/core/auth-store.d.ts +81 -0
- package/dist/core/auth-store.js +530 -0
- package/dist/core/auth.d.ts +75 -0
- package/dist/core/auth.js +124 -0
- package/dist/core/bootstrap.d.ts +41 -0
- package/dist/core/bootstrap.js +236 -0
- package/dist/core/build.d.ts +92 -0
- package/dist/core/build.js +249 -0
- package/dist/core/canary.d.ts +10 -0
- package/dist/core/canary.js +14 -0
- package/dist/core/check-failure-summary.d.ts +10 -0
- package/dist/core/check-failure-summary.js +34 -0
- package/dist/core/config.d.ts +160 -0
- package/dist/core/config.js +1288 -0
- package/dist/core/context-pack.d.ts +74 -0
- package/dist/core/context-pack.js +778 -0
- package/dist/core/db.d.ts +236 -0
- package/dist/core/db.js +747 -0
- package/dist/core/detect.d.ts +69 -0
- package/dist/core/detect.js +251 -0
- package/dist/core/docs.d.ts +76 -0
- package/dist/core/docs.js +225 -0
- package/dist/core/frontmatter.d.ts +29 -0
- package/dist/core/frontmatter.js +215 -0
- package/dist/core/git.d.ts +505 -0
- package/dist/core/git.js +1453 -0
- package/dist/core/indexer.d.ts +33 -0
- package/dist/core/indexer.js +282 -0
- package/dist/core/input.d.ts +66 -0
- package/dist/core/input.js +222 -0
- package/dist/core/logger.d.ts +70 -0
- package/dist/core/logger.js +138 -0
- package/dist/core/models.d.ts +45 -0
- package/dist/core/models.js +291 -0
- package/dist/core/net-probe.d.ts +4 -0
- package/dist/core/net-probe.js +20 -0
- package/dist/core/providers/deepinfra.d.ts +23 -0
- package/dist/core/providers/deepinfra.js +44 -0
- package/dist/core/providers/index.d.ts +24 -0
- package/dist/core/providers/index.js +59 -0
- package/dist/core/providers/openrouter.d.ts +28 -0
- package/dist/core/providers/openrouter.js +82 -0
- package/dist/core/providers/spend.d.ts +86 -0
- package/dist/core/providers/spend.js +286 -0
- package/dist/core/providers/types.d.ts +56 -0
- package/dist/core/providers/types.js +39 -0
- package/dist/core/repoos.d.ts +59 -0
- package/dist/core/repoos.js +221 -0
- package/dist/core/runtime.d.ts +35 -0
- package/dist/core/runtime.js +167 -0
- package/dist/core/skills-registry.d.ts +39 -0
- package/dist/core/skills-registry.js +148 -0
- package/dist/core/skills-registry.test.d.ts +1 -0
- package/dist/core/skills-registry.test.js +52 -0
- package/dist/core/sysmem.d.ts +7 -0
- package/dist/core/sysmem.js +55 -0
- package/dist/core/tailscale.d.ts +2 -0
- package/dist/core/tailscale.js +19 -0
- package/dist/core/task.d.ts +53 -0
- package/dist/core/task.js +310 -0
- package/dist/core/toml-line.d.ts +20 -0
- package/dist/core/toml-line.js +52 -0
- package/dist/core/toml-validate.d.ts +44 -0
- package/dist/core/toml-validate.js +335 -0
- package/dist/core/tunnel-assistant.d.ts +30 -0
- package/dist/core/tunnel-assistant.js +65 -0
- package/dist/core/tunnel-registry.d.ts +96 -0
- package/dist/core/tunnel-registry.js +267 -0
- package/dist/core/tunnel-registry.test.d.ts +1 -0
- package/dist/core/tunnel-registry.test.js +309 -0
- package/dist/core/tunnel.d.ts +103 -0
- package/dist/core/tunnel.js +320 -0
- package/dist/core/types.d.ts +811 -0
- package/dist/core/types.js +27 -0
- package/dist/core/worktree-gc.d.ts +57 -0
- package/dist/core/worktree-gc.js +194 -0
- package/dist/server/__tests__/integration-job.test.d.ts +1 -0
- package/dist/server/__tests__/integration-job.test.js +129 -0
- package/dist/server/agents.d.ts +1020 -0
- package/dist/server/agents.js +4070 -0
- package/dist/server/attachments.d.ts +51 -0
- package/dist/server/attachments.js +130 -0
- package/dist/server/auto-engineering.d.ts +45 -0
- package/dist/server/auto-engineering.js +275 -0
- package/dist/server/branchless-release.d.ts +22 -0
- package/dist/server/branchless-release.js +67 -0
- package/dist/server/built-in-agents.d.ts +305 -0
- package/dist/server/built-in-agents.js +1838 -0
- package/dist/server/cto-monitor.d.ts +35 -0
- package/dist/server/cto-monitor.js +281 -0
- package/dist/server/cto.d.ts +125 -0
- package/dist/server/cto.js +590 -0
- package/dist/server/deployments.d.ts +119 -0
- package/dist/server/deployments.js +325 -0
- package/dist/server/diff-snapshot.d.ts +20 -0
- package/dist/server/diff-snapshot.js +73 -0
- package/dist/server/done.d.ts +160 -0
- package/dist/server/done.js +488 -0
- package/dist/server/freeform.d.ts +55 -0
- package/dist/server/freeform.js +179 -0
- package/dist/server/handoff.d.ts +99 -0
- package/dist/server/handoff.js +575 -0
- package/dist/server/hetzner.d.ts +45 -0
- package/dist/server/hetzner.js +117 -0
- package/dist/server/icons.d.ts +8 -0
- package/dist/server/icons.js +195 -0
- package/dist/server/integration-job.d.ts +75 -0
- package/dist/server/integration-job.js +144 -0
- package/dist/server/integration-orchestrator.d.ts +211 -0
- package/dist/server/integration-orchestrator.js +1299 -0
- package/dist/server/integration-status.d.ts +48 -0
- package/dist/server/integration-status.js +71 -0
- package/dist/server/live-index.d.ts +295 -0
- package/dist/server/live-index.js +452 -0
- package/dist/server/model-test.d.ts +20 -0
- package/dist/server/model-test.js +100 -0
- package/dist/server/ntfy.d.ts +57 -0
- package/dist/server/ntfy.js +112 -0
- package/dist/server/pm-attachments.d.ts +35 -0
- package/dist/server/pm-attachments.js +181 -0
- package/dist/server/pm-runs.d.ts +58 -0
- package/dist/server/pm-runs.js +80 -0
- package/dist/server/preview.d.ts +174 -0
- package/dist/server/preview.js +641 -0
- package/dist/server/release.d.ts +88 -0
- package/dist/server/release.js +449 -0
- package/dist/server/reload.d.ts +194 -0
- package/dist/server/reload.js +586 -0
- package/dist/server/remote-validation.d.ts +132 -0
- package/dist/server/remote-validation.js +478 -0
- package/dist/server/repo-lock.d.ts +36 -0
- package/dist/server/repo-lock.js +141 -0
- package/dist/server/review-guard.d.ts +14 -0
- package/dist/server/review-guard.js +159 -0
- package/dist/server/review.d.ts +243 -0
- package/dist/server/review.js +1211 -0
- package/dist/server/routes/agents.d.ts +6 -0
- package/dist/server/routes/agents.js +28 -0
- package/dist/server/routes/auth.d.ts +60 -0
- package/dist/server/routes/auth.js +755 -0
- package/dist/server/routes/config.d.ts +20 -0
- package/dist/server/routes/config.js +347 -0
- package/dist/server/routes/debugger.d.ts +33 -0
- package/dist/server/routes/debugger.js +360 -0
- package/dist/server/routes/deployments.d.ts +3 -0
- package/dist/server/routes/deployments.js +16 -0
- package/dist/server/routes/docs.d.ts +8 -0
- package/dist/server/routes/docs.js +135 -0
- package/dist/server/routes/helpers.d.ts +21 -0
- package/dist/server/routes/helpers.js +171 -0
- package/dist/server/routes/index.d.ts +19 -0
- package/dist/server/routes/index.js +18 -0
- package/dist/server/routes/info.d.ts +17 -0
- package/dist/server/routes/info.js +177 -0
- package/dist/server/routes/inputs.d.ts +7 -0
- package/dist/server/routes/inputs.js +125 -0
- package/dist/server/routes/model-providers.d.ts +27 -0
- package/dist/server/routes/model-providers.js +94 -0
- package/dist/server/routes/models.d.ts +3 -0
- package/dist/server/routes/models.js +36 -0
- package/dist/server/routes/notify.d.ts +2 -0
- package/dist/server/routes/notify.js +17 -0
- package/dist/server/routes/playground.d.ts +29 -0
- package/dist/server/routes/playground.js +81 -0
- package/dist/server/routes/release.d.ts +20 -0
- package/dist/server/routes/release.js +86 -0
- package/dist/server/routes/router.d.ts +12 -0
- package/dist/server/routes/router.js +32 -0
- package/dist/server/routes/skill-registry.d.ts +5 -0
- package/dist/server/routes/skill-registry.js +51 -0
- package/dist/server/routes/tasks.d.ts +58 -0
- package/dist/server/routes/tasks.js +1442 -0
- package/dist/server/routes/transcribe.d.ts +2 -0
- package/dist/server/routes/transcribe.js +124 -0
- package/dist/server/routes/types.d.ts +68 -0
- package/dist/server/routes/types.js +1 -0
- package/dist/server/routes/ui.d.ts +5 -0
- package/dist/server/routes/ui.js +81 -0
- package/dist/server/routes/utils.d.ts +3 -0
- package/dist/server/routes/utils.js +23 -0
- package/dist/server/serve-reaper.d.ts +135 -0
- package/dist/server/serve-reaper.js +491 -0
- package/dist/server/server.d.ts +49 -0
- package/dist/server/server.js +2171 -0
- package/dist/server/supervisor.d.ts +89 -0
- package/dist/server/supervisor.js +231 -0
- package/dist/server/system.d.ts +198 -0
- package/dist/server/system.js +480 -0
- package/dist/server/task-check.d.ts +45 -0
- package/dist/server/task-check.js +71 -0
- package/dist/server/task-transitions.d.ts +51 -0
- package/dist/server/task-transitions.js +78 -0
- package/dist/server/task-watchdog.d.ts +158 -0
- package/dist/server/task-watchdog.js +681 -0
- package/dist/server/test-run.d.ts +28 -0
- package/dist/server/test-run.js +81 -0
- package/dist/server/watcher.d.ts +21 -0
- package/dist/server/watcher.js +194 -0
- package/dist/server/write.d.ts +94 -0
- package/dist/server/write.js +345 -0
- package/dist/ui/assets/AgentsView-CF4wRvHh.css +1 -0
- package/dist/ui/assets/AgentsView-D-myL-kA.js +1 -0
- package/dist/ui/assets/ContextView-D3TC-RSp.css +1 -0
- package/dist/ui/assets/ContextView-DsOqAdyE.js +4 -0
- package/dist/ui/assets/DashboardView-BOhsIJqO.js +1 -0
- package/dist/ui/assets/DashboardView-Ck9o0RP2.css +1 -0
- package/dist/ui/assets/DeploymentsView--iIUVfEH.css +1 -0
- package/dist/ui/assets/DeploymentsView-DXu_FYR2.js +1 -0
- package/dist/ui/assets/InputsView-24HVbVPk.js +1 -0
- package/dist/ui/assets/InputsView-BLb7GHtx.css +1 -0
- package/dist/ui/assets/LoginView-6QlGg6cx.css +1 -0
- package/dist/ui/assets/LoginView-BqupI0Lt.js +1 -0
- package/dist/ui/assets/ReleasesView-BEG1A0YH.css +1 -0
- package/dist/ui/assets/ReleasesView-CAgMuxpe.js +3 -0
- package/dist/ui/assets/SettingsView-CA-NYSMK.css +1 -0
- package/dist/ui/assets/SettingsView-O3iZSnjg.js +3 -0
- package/dist/ui/assets/WorkView-D8Tl6qwy.js +1 -0
- package/dist/ui/assets/WorkView-DMYL2s3W.css +1 -0
- package/dist/ui/assets/abnfDiagram-VCTEODGH-J5lkSnEE.js +1 -0
- package/dist/ui/assets/arc-BHZnmhhM.js +1 -0
- package/dist/ui/assets/architecture-7GRP2DOG-pLdFt-xS.js +1 -0
- package/dist/ui/assets/architectureDiagram-5GKGNRK7-C3k89uKX.js +36 -0
- package/dist/ui/assets/array-BifhSqXX.js +1 -0
- package/dist/ui/assets/blockDiagram-I7D4REHJ-AWNoBzop.js +129 -0
- package/dist/ui/assets/button-lbikqSph.js +1 -0
- package/dist/ui/assets/c4Diagram-7LVT6UL2-DKG1D5gd.js +38 -0
- package/dist/ui/assets/channel-gA4qBv3A.js +1 -0
- package/dist/ui/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
- package/dist/ui/assets/chunk-4HAMMTFA-D1YR8lF_.js +62 -0
- package/dist/ui/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
- package/dist/ui/assets/chunk-75Z2AOVW-5GuBxfsL.js +2 -0
- package/dist/ui/assets/chunk-DU6HZSFF-DfdNNqwa.js +127 -0
- package/dist/ui/assets/chunk-F27PBJKO-BPZzinQ4.js +1 -0
- package/dist/ui/assets/chunk-FOHPRMQF-l2z4K2jD.js +161 -0
- package/dist/ui/assets/chunk-GMAD6QVW-DGWvSKj5.js +72 -0
- package/dist/ui/assets/chunk-GVQU2GXP-D6Aw75wJ.js +1 -0
- package/dist/ui/assets/chunk-IMKFNOWR-B8mMBKCW.js +231 -0
- package/dist/ui/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
- package/dist/ui/assets/chunk-L3NEJ4N5-D5OJuXYE.js +1 -0
- package/dist/ui/assets/chunk-OSK3NFVY-B7r9w2UW.js +10 -0
- package/dist/ui/assets/chunk-P2QGCYS3-C74X4AQX.js +1 -0
- package/dist/ui/assets/chunk-POPQ4Y6H-C5_u1gUS.js +1 -0
- package/dist/ui/assets/chunk-PWAF6VOD-DfoTLtxn.js +1 -0
- package/dist/ui/assets/chunk-SHT3W25Y-D40m2eqz.js +168 -0
- package/dist/ui/assets/chunk-SVP7TREG-euxi0Kap.js +88 -0
- package/dist/ui/assets/chunk-TICWLB2K-fkdxngzN.js +206 -0
- package/dist/ui/assets/chunk-XXDRQBXY-DFBUG-OT.js +1 -0
- package/dist/ui/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
- package/dist/ui/assets/classDiagram-ZZMXUADV-BzW8bq2P.js +1 -0
- package/dist/ui/assets/classDiagram-v2-VYDZK3BY-BzW8bq2P.js +1 -0
- package/dist/ui/assets/cose-bilkent-JH36ORCC-BTcgMon1.js +1 -0
- package/dist/ui/assets/cynefin-OW5HDTMX-B5m_COsS.js +1 -0
- package/dist/ui/assets/cynefinDiagram-5FMLGOSQ-C-AG6CGe.js +62 -0
- package/dist/ui/assets/cytoscape.esm-FBntH-9t.js +321 -0
- package/dist/ui/assets/dagre-GXQ25YYZ-DDfDnp8L.js +4 -0
- package/dist/ui/assets/dagre-PrKaheQc.js +1 -0
- package/dist/ui/assets/defaultLocale-BFoDCU3G.js +1 -0
- package/dist/ui/assets/diagram-S7CK7UJ4-DjQZAlEY.js +30 -0
- package/dist/ui/assets/diagram-UQ7AKVKN-DAZ9yp1B.js +41 -0
- package/dist/ui/assets/diagram-VSXAHHWV-BWepUKJD.js +3 -0
- package/dist/ui/assets/diagram-VX7I27RA-EcV1J81b.js +24 -0
- package/dist/ui/assets/diagram-Z3DM3KII-Dbz7XU_K.js +24 -0
- package/dist/ui/assets/dist-DTg6UBE_.js +1 -0
- package/dist/ui/assets/ebnfDiagram-PWID7BFC-BUyQw8Mm.js +1 -0
- package/dist/ui/assets/erDiagram-RLTQ6QDP-WVf8ukKt.js +99 -0
- package/dist/ui/assets/eventmodeling-NTZA5JFV-DHqyLOAn.js +1 -0
- package/dist/ui/assets/flowDiagram-HODETNUW-CYk_ze5K.js +1 -0
- package/dist/ui/assets/ganttDiagram-EL5Y4UJY-rB4MZuB-.js +292 -0
- package/dist/ui/assets/gitGraph-4MIJSDKK-BOTWM8dY.js +1 -0
- package/dist/ui/assets/gitGraphDiagram-WWUBYQGX-eYscuhtP.js +106 -0
- package/dist/ui/assets/graphlib-DS17s2tU.js +1 -0
- package/dist/ui/assets/index-BACBfnga.css +1 -0
- package/dist/ui/assets/index-BOQ-ust6.js +26 -0
- package/dist/ui/assets/info-A6RAGUB7-_67wOORe.js +1 -0
- package/dist/ui/assets/infoDiagram-27XIBGKW-XVXbddTA.js +2 -0
- package/dist/ui/assets/init-C-OQMol4.js +1 -0
- package/dist/ui/assets/ishikawaDiagram-5VMMS53U-ClLNiEru.js +70 -0
- package/dist/ui/assets/journeyDiagram-3NMN7TZE-NRawjR6i.js +139 -0
- package/dist/ui/assets/kanban-definition-UXKFOSKX-BgSzBfIx.js +89 -0
- package/dist/ui/assets/katex-DolUETbr.js +257 -0
- package/dist/ui/assets/line-KAyfuul4.js +1 -0
- package/dist/ui/assets/linear-cCCPOpu7.js +1 -0
- package/dist/ui/assets/mermaid-parser.core-CgXZk1iN.js +7 -0
- package/dist/ui/assets/mermaid.core-BUUkChHW.js +44 -0
- package/dist/ui/assets/mindmap-definition-YA3MSWOX-Cpn7vW4r.js +96 -0
- package/dist/ui/assets/ordinal-BDEzSJ7C.js +1 -0
- package/dist/ui/assets/packet-AYTQ26CC-0lZwM-d6.js +1 -0
- package/dist/ui/assets/path-COt_16Va.js +1 -0
- package/dist/ui/assets/pegDiagram-XKGWAZYB-impy0inn.js +1 -0
- package/dist/ui/assets/pie-WAS4IAKB-CqfdGHYg.js +1 -0
- package/dist/ui/assets/pieDiagram-E7YTZNPT-CxjL4I1h.js +39 -0
- package/dist/ui/assets/quadrantDiagram-AXDQQJYC-Cjd1QMIe.js +7 -0
- package/dist/ui/assets/radar-RG4KPBEZ-CRkQIwiv.js +1 -0
- package/dist/ui/assets/railroad-74A4TZTK-i67XSWTB.js +1 -0
- package/dist/ui/assets/railroad-abnf-HS5TGJTU-Cv9m5aS3.js +1 -0
- package/dist/ui/assets/railroad-ebnf-LZEXJU2U-C5ZIn-Jh.js +1 -0
- package/dist/ui/assets/railroad-peg-WCYAUIDC-CGra9Oq-.js +1 -0
- package/dist/ui/assets/railroadDiagram-O6MQD6OU-_pK0qyaY.js +1 -0
- package/dist/ui/assets/releases-B0WNV-SY.js +1 -0
- package/dist/ui/assets/repoos-cto-square.webp +0 -0
- package/dist/ui/assets/repoos-helpful-pm-square.webp +0 -0
- package/dist/ui/assets/repoos-orchestrator-square.webp +0 -0
- package/dist/ui/assets/repoos-performance-agent-square.webp +0 -0
- package/dist/ui/assets/repoos-ross-from-friends-square.webp +0 -0
- package/dist/ui/assets/repoos-tech-debt-agent-square.webp +0 -0
- package/dist/ui/assets/requirementDiagram-BXWQKSXE-CRrFX-yw.js +84 -0
- package/dist/ui/assets/rough.esm-By172zw-.js +1 -0
- package/dist/ui/assets/sankeyDiagram-P5KCCOFB-X_xFRj9E.js +40 -0
- package/dist/ui/assets/sequenceDiagram-WJ2MYXX4-Byb49lKf.js +162 -0
- package/dist/ui/assets/sizeCapture-INFHLROL-B0uUizjq.js +1 -0
- package/dist/ui/assets/src-BH-TyZbA.js +1 -0
- package/dist/ui/assets/stateDiagram-D77RDMKH-CzaPrqYF.js +1 -0
- package/dist/ui/assets/stateDiagram-v2-MP3YSRHH-BCXckz7K.js +1 -0
- package/dist/ui/assets/swimlanes-42K2YHIH-Cx_1lnqr.js +1 -0
- package/dist/ui/assets/swimlanesDiagram-VR7AAH4N-54qsKi6A.js +8 -0
- package/dist/ui/assets/timeline-definition-24CTP7MA-B1IbZPQ-.js +120 -0
- package/dist/ui/assets/treeView-Q6P3EWNA-DFWhVE3d.js +1 -0
- package/dist/ui/assets/treemap-WGGIJYW6-BmbYPThn.js +1 -0
- package/dist/ui/assets/vendor-ui-DPm7zLxi.js +3 -0
- package/dist/ui/assets/vendor-vue-CobgyEJp.js +1 -0
- package/dist/ui/assets/vennDiagram-4TSXK5OY-Ae2AtRpt.js +34 -0
- package/dist/ui/assets/wardley-WFR3VGLG-BtD4X4tL.js +1 -0
- package/dist/ui/assets/wardleyDiagram-VM6X3IG4-B3YN2fTd.js +78 -0
- package/dist/ui/assets/xychartDiagram-S5SC5T6Z-CIzJfMKA.js +7 -0
- package/dist/ui/favicon.svg +11 -0
- package/dist/ui/index.html +49 -0
- package/dist/ui/sw.js +48 -0
- package/package.json +91 -0
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency-free TOML syntax validator (#0375).
|
|
3
|
+
*
|
|
4
|
+
* The Settings page's raw editor writes `repoos.toml` verbatim, so a malformed
|
|
5
|
+
* save must be rejected *before* it reaches disk — `loadConfig`'s reader is
|
|
6
|
+
* deliberately forgiving (it skips lines it can't parse), which would turn a
|
|
7
|
+
* typo into a silently-ignored config instead of an error the user can see.
|
|
8
|
+
*
|
|
9
|
+
* This is a validator, not a parser: it walks the document and reports the
|
|
10
|
+
* first structural problem it finds (unterminated string/array, missing `=`,
|
|
11
|
+
* bad table header, invalid scalar) with a 1-based line number. It accepts the
|
|
12
|
+
* TOML shapes RepoOS itself emits plus the common hand-written ones (dotted
|
|
13
|
+
* and quoted keys, literal strings, single-line arrays, dates/times,
|
|
14
|
+
* hex/octal/binary numbers). It deliberately does not enforce key uniqueness
|
|
15
|
+
* or table-redefinition rules — those are valid-TOML concerns that never
|
|
16
|
+
* affect what `loadConfig` reads, and rejecting on them would make the escape
|
|
17
|
+
* hatch stricter than the loader it feeds.
|
|
18
|
+
*
|
|
19
|
+
* Crucially, it rejects the *valid TOML* shapes that `parseFlatToml`
|
|
20
|
+
* (`config.ts`) cannot read: multi-line strings, multi-line arrays, and inline
|
|
21
|
+
* tables. Those would otherwise sail through a save and then be silently
|
|
22
|
+
* misread (the first line of a multi-line array parses as the string `"["`,
|
|
23
|
+
* an inline table as a plain string), so a whole save could take no effect
|
|
24
|
+
* with no error — the exact silent-config failure this gate exists to stop.
|
|
25
|
+
*/
|
|
26
|
+
class TomlSyntaxError extends Error {
|
|
27
|
+
line;
|
|
28
|
+
constructor(message, line) {
|
|
29
|
+
super(message);
|
|
30
|
+
this.line = line;
|
|
31
|
+
this.name = "TomlSyntaxError";
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const BARE_KEY_CHAR = /^[A-Za-z0-9_-]$/;
|
|
35
|
+
const INT_DECIMAL = /^[+-]?(0|[1-9](_?[0-9])*)$/;
|
|
36
|
+
const INT_HEX = /^[+-]?0x[0-9A-Fa-f](_?[0-9A-Fa-f])*$/;
|
|
37
|
+
const INT_OCTAL = /^[+-]?0o[0-7](_?[0-7])*$/;
|
|
38
|
+
const INT_BINARY = /^[+-]?0b[01](_?[01])*$/;
|
|
39
|
+
const FLOAT = /^[+-]?(0|[1-9](_?[0-9])*)(\.[0-9](_?[0-9])*)?([eE][+-]?[0-9](_?[0-9])*)?$/;
|
|
40
|
+
const SPECIAL_FLOAT = /^[+-]?(inf|nan)$/;
|
|
41
|
+
const DATETIME = /^\d{4}-\d{2}-\d{2}([Tt ]\d{2}:\d{2}:\d{2}(\.\d+)?([Zz]|[+-]\d{2}:\d{2})?)?$/;
|
|
42
|
+
const LOCALTIME = /^\d{2}:\d{2}:\d{2}(\.\d+)?$/;
|
|
43
|
+
function isBareValue(token) {
|
|
44
|
+
if (token === "true" || token === "false")
|
|
45
|
+
return true;
|
|
46
|
+
return (INT_DECIMAL.test(token) ||
|
|
47
|
+
INT_HEX.test(token) ||
|
|
48
|
+
INT_OCTAL.test(token) ||
|
|
49
|
+
INT_BINARY.test(token) ||
|
|
50
|
+
FLOAT.test(token) ||
|
|
51
|
+
SPECIAL_FLOAT.test(token) ||
|
|
52
|
+
DATETIME.test(token) ||
|
|
53
|
+
LOCALTIME.test(token));
|
|
54
|
+
}
|
|
55
|
+
class TomlScanner {
|
|
56
|
+
source;
|
|
57
|
+
i = 0;
|
|
58
|
+
line = 1;
|
|
59
|
+
constructor(source) {
|
|
60
|
+
this.source = source;
|
|
61
|
+
}
|
|
62
|
+
eof() {
|
|
63
|
+
return this.i >= this.source.length;
|
|
64
|
+
}
|
|
65
|
+
/** Current 1-based line, for callers that need to detect a value spanning lines. */
|
|
66
|
+
get lineNumber() {
|
|
67
|
+
return this.line;
|
|
68
|
+
}
|
|
69
|
+
peek(offset = 0) {
|
|
70
|
+
return this.source[this.i + offset] ?? "";
|
|
71
|
+
}
|
|
72
|
+
advance() {
|
|
73
|
+
const ch = this.source[this.i++];
|
|
74
|
+
if (ch === "\n")
|
|
75
|
+
this.line++;
|
|
76
|
+
return ch;
|
|
77
|
+
}
|
|
78
|
+
fail(message) {
|
|
79
|
+
throw new TomlSyntaxError(message, this.line);
|
|
80
|
+
}
|
|
81
|
+
/** Spaces and tabs only — never crosses a line boundary. */
|
|
82
|
+
skipInlineWhitespace() {
|
|
83
|
+
while (!this.eof()) {
|
|
84
|
+
const ch = this.peek();
|
|
85
|
+
if (ch === " " || ch === "\t")
|
|
86
|
+
this.advance();
|
|
87
|
+
else
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
skipWhitespace() {
|
|
92
|
+
while (!this.eof()) {
|
|
93
|
+
const ch = this.peek();
|
|
94
|
+
if (ch === " " || ch === "\t" || ch === "\r" || ch === "\n")
|
|
95
|
+
this.advance();
|
|
96
|
+
else
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
skipComment() {
|
|
101
|
+
if (this.peek() !== "#")
|
|
102
|
+
return;
|
|
103
|
+
while (!this.eof() && this.peek() !== "\n")
|
|
104
|
+
this.advance();
|
|
105
|
+
}
|
|
106
|
+
/** After a complete statement: trailing whitespace, an optional comment, then EOL/EOF. */
|
|
107
|
+
finishStatement() {
|
|
108
|
+
this.skipInlineWhitespace();
|
|
109
|
+
this.skipComment();
|
|
110
|
+
if (this.eof())
|
|
111
|
+
return;
|
|
112
|
+
if (this.peek() === "\n" || this.peek() === "\r") {
|
|
113
|
+
if (this.peek() === "\r")
|
|
114
|
+
this.advance();
|
|
115
|
+
if (this.peek() === "\n")
|
|
116
|
+
this.advance();
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
this.fail(`unexpected character ${JSON.stringify(this.peek())} after statement`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/** Parse a dotted key path (`a.b`, `"a b".c`); validates but discards the value. */
|
|
123
|
+
function parseKey(sc) {
|
|
124
|
+
parseSimpleKey(sc);
|
|
125
|
+
sc.skipInlineWhitespace();
|
|
126
|
+
while (sc.peek() === ".") {
|
|
127
|
+
sc.advance();
|
|
128
|
+
sc.skipInlineWhitespace();
|
|
129
|
+
parseSimpleKey(sc);
|
|
130
|
+
sc.skipInlineWhitespace();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function parseSimpleKey(sc) {
|
|
134
|
+
const ch = sc.peek();
|
|
135
|
+
if (ch === '"') {
|
|
136
|
+
readBasicString(sc);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (ch === "'") {
|
|
140
|
+
readLiteralString(sc);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
let key = "";
|
|
144
|
+
while (!sc.eof() && BARE_KEY_CHAR.test(sc.peek()))
|
|
145
|
+
key += sc.advance();
|
|
146
|
+
if (!key)
|
|
147
|
+
sc.fail("expected a key");
|
|
148
|
+
}
|
|
149
|
+
function readBasicString(sc) {
|
|
150
|
+
sc.advance(); // opening quote
|
|
151
|
+
while (!sc.eof()) {
|
|
152
|
+
const ch = sc.peek();
|
|
153
|
+
if (ch === "\n" || ch === "\r")
|
|
154
|
+
sc.fail("unterminated string");
|
|
155
|
+
if (ch === '"') {
|
|
156
|
+
sc.advance();
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
if (ch === "\\") {
|
|
160
|
+
sc.advance();
|
|
161
|
+
if (sc.eof())
|
|
162
|
+
sc.fail("unterminated string");
|
|
163
|
+
sc.advance();
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
sc.advance();
|
|
167
|
+
}
|
|
168
|
+
sc.fail("unterminated string");
|
|
169
|
+
}
|
|
170
|
+
function readLiteralString(sc) {
|
|
171
|
+
sc.advance(); // opening quote
|
|
172
|
+
while (!sc.eof()) {
|
|
173
|
+
const ch = sc.peek();
|
|
174
|
+
if (ch === "\n" || ch === "\r")
|
|
175
|
+
sc.fail("unterminated string");
|
|
176
|
+
if (ch === "'") {
|
|
177
|
+
sc.advance();
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
sc.advance();
|
|
181
|
+
}
|
|
182
|
+
sc.fail("unterminated string");
|
|
183
|
+
}
|
|
184
|
+
const MULTILINE_UNSUPPORTED = "multi-line strings aren't supported — keep each value on one line";
|
|
185
|
+
function readArray(sc) {
|
|
186
|
+
sc.advance(); // [
|
|
187
|
+
while (true) {
|
|
188
|
+
sc.skipWhitespace();
|
|
189
|
+
sc.skipComment();
|
|
190
|
+
sc.skipWhitespace();
|
|
191
|
+
if (sc.eof())
|
|
192
|
+
sc.fail("unterminated array");
|
|
193
|
+
if (sc.peek() === "]") {
|
|
194
|
+
sc.advance();
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
readValue(sc);
|
|
198
|
+
sc.skipWhitespace();
|
|
199
|
+
sc.skipComment();
|
|
200
|
+
sc.skipWhitespace();
|
|
201
|
+
if (sc.peek() === ",") {
|
|
202
|
+
sc.advance();
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
if (sc.peek() === "]") {
|
|
206
|
+
sc.advance();
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
sc.fail("expected ',' or ']' in array");
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
function readBareValue(sc) {
|
|
213
|
+
let token = "";
|
|
214
|
+
while (!sc.eof()) {
|
|
215
|
+
const ch = sc.peek();
|
|
216
|
+
if (ch === " " ||
|
|
217
|
+
ch === "\t" ||
|
|
218
|
+
ch === "\r" ||
|
|
219
|
+
ch === "\n" ||
|
|
220
|
+
ch === "," ||
|
|
221
|
+
ch === "]" ||
|
|
222
|
+
ch === "}" ||
|
|
223
|
+
ch === "#") {
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
token += sc.advance();
|
|
227
|
+
}
|
|
228
|
+
if (!token)
|
|
229
|
+
sc.fail("expected a value");
|
|
230
|
+
if (!isBareValue(token))
|
|
231
|
+
sc.fail(`invalid value ${JSON.stringify(token)}`);
|
|
232
|
+
}
|
|
233
|
+
function readValue(sc) {
|
|
234
|
+
const ch = sc.peek();
|
|
235
|
+
if (ch === '"') {
|
|
236
|
+
if (sc.peek(1) === '"' && sc.peek(2) === '"')
|
|
237
|
+
sc.fail(MULTILINE_UNSUPPORTED);
|
|
238
|
+
readBasicString(sc);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
if (ch === "'") {
|
|
242
|
+
if (sc.peek(1) === "'" && sc.peek(2) === "'")
|
|
243
|
+
sc.fail(MULTILINE_UNSUPPORTED);
|
|
244
|
+
readLiteralString(sc);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
if (ch === "[") {
|
|
248
|
+
readArray(sc);
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
if (ch === "{") {
|
|
252
|
+
sc.fail("inline tables aren't supported — use a [section] or [[array-of-tables]] block instead");
|
|
253
|
+
}
|
|
254
|
+
readBareValue(sc);
|
|
255
|
+
}
|
|
256
|
+
function readTableHeader(sc) {
|
|
257
|
+
sc.advance(); // [
|
|
258
|
+
let array = false;
|
|
259
|
+
if (sc.peek() === "[") {
|
|
260
|
+
sc.advance();
|
|
261
|
+
array = true;
|
|
262
|
+
}
|
|
263
|
+
sc.skipInlineWhitespace();
|
|
264
|
+
parseKey(sc);
|
|
265
|
+
sc.skipInlineWhitespace();
|
|
266
|
+
if (array) {
|
|
267
|
+
if (!(sc.peek() === "]" && sc.peek(1) === "]")) {
|
|
268
|
+
sc.fail("expected ']]' to close an array-of-tables header");
|
|
269
|
+
}
|
|
270
|
+
sc.advance();
|
|
271
|
+
sc.advance();
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
if (sc.peek() !== "]")
|
|
275
|
+
sc.fail("expected ']' to close a table header");
|
|
276
|
+
sc.advance();
|
|
277
|
+
}
|
|
278
|
+
sc.finishStatement();
|
|
279
|
+
}
|
|
280
|
+
function readKeyValue(sc) {
|
|
281
|
+
parseKey(sc);
|
|
282
|
+
sc.skipInlineWhitespace();
|
|
283
|
+
if (sc.peek() !== "=")
|
|
284
|
+
sc.fail("expected '=' after key");
|
|
285
|
+
sc.advance();
|
|
286
|
+
sc.skipInlineWhitespace();
|
|
287
|
+
const startLine = sc.lineNumber;
|
|
288
|
+
readValue(sc);
|
|
289
|
+
if (sc.lineNumber !== startLine) {
|
|
290
|
+
sc.fail("multi-line values aren't supported by RepoOS's config reader — keep arrays on a single line");
|
|
291
|
+
}
|
|
292
|
+
sc.finishStatement();
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Validate a TOML document's syntax. Returns `{ ok: true }` when the whole
|
|
296
|
+
* document is structurally well-formed, or `{ ok: false, error, line }` with
|
|
297
|
+
* the first problem found. Never throws on malformed input.
|
|
298
|
+
*/
|
|
299
|
+
export function validateToml(source) {
|
|
300
|
+
const sc = new TomlScanner(source);
|
|
301
|
+
try {
|
|
302
|
+
while (!sc.eof()) {
|
|
303
|
+
sc.skipWhitespace();
|
|
304
|
+
if (sc.eof())
|
|
305
|
+
break;
|
|
306
|
+
const ch = sc.peek();
|
|
307
|
+
if (ch === "#") {
|
|
308
|
+
sc.skipComment();
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
if (ch === "[") {
|
|
312
|
+
readTableHeader(sc);
|
|
313
|
+
continue;
|
|
314
|
+
}
|
|
315
|
+
readKeyValue(sc);
|
|
316
|
+
}
|
|
317
|
+
return { ok: true };
|
|
318
|
+
}
|
|
319
|
+
catch (err) {
|
|
320
|
+
if (err instanceof TomlSyntaxError) {
|
|
321
|
+
return { ok: false, error: err.message, line: err.line };
|
|
322
|
+
}
|
|
323
|
+
throw err;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Format a validation failure for display, with the line folded into the
|
|
328
|
+
* message so callers that only carry a string (the HTTP JSON error, the store)
|
|
329
|
+
* still surface it.
|
|
330
|
+
*/
|
|
331
|
+
export function formatTomlError(result) {
|
|
332
|
+
if (result.ok)
|
|
333
|
+
return "";
|
|
334
|
+
return `Invalid TOML on line ${result.line}: ${result.error}`;
|
|
335
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type TunnelRunMode = "foreground" | "background";
|
|
2
|
+
export interface TunnelPublishInput {
|
|
3
|
+
zone: string;
|
|
4
|
+
app: string;
|
|
5
|
+
port: number | string;
|
|
6
|
+
emails: string[] | string;
|
|
7
|
+
runMode: TunnelRunMode;
|
|
8
|
+
/** Skip Cloudflare Access entirely — fully public at the edge, native auth only. */
|
|
9
|
+
noAccess?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface TunnelPublishPlan {
|
|
12
|
+
zone: string;
|
|
13
|
+
app: string;
|
|
14
|
+
port: number;
|
|
15
|
+
emails: string[];
|
|
16
|
+
runMode: TunnelRunMode;
|
|
17
|
+
noAccess: boolean;
|
|
18
|
+
hostname: string;
|
|
19
|
+
publicUrl: string;
|
|
20
|
+
localOrigin: string;
|
|
21
|
+
commands: {
|
|
22
|
+
setup: string;
|
|
23
|
+
create: string;
|
|
24
|
+
run: string;
|
|
25
|
+
status: string;
|
|
26
|
+
};
|
|
27
|
+
authNote: string;
|
|
28
|
+
}
|
|
29
|
+
export declare function validateTunnelPublishInput(input: TunnelPublishInput): string[];
|
|
30
|
+
export declare function buildTunnelPublishPlan(input: TunnelPublishInput): TunnelPublishPlan;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
const isValidAppName = (value) => /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$/.test(value);
|
|
2
|
+
const isValidEmail = (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
|
|
3
|
+
export function validateTunnelPublishInput(input) {
|
|
4
|
+
const errors = [];
|
|
5
|
+
const zone = input.zone.trim().toLowerCase().replace(/\.$/, "");
|
|
6
|
+
if (!/^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/.test(zone)) {
|
|
7
|
+
errors.push("Enter a valid Cloudflare zone such as repoos.org.");
|
|
8
|
+
}
|
|
9
|
+
const app = input.app.trim().toLowerCase();
|
|
10
|
+
if (!isValidAppName(app))
|
|
11
|
+
errors.push("App name must use letters, numbers, hyphens, or underscores.");
|
|
12
|
+
const port = Number(input.port);
|
|
13
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
14
|
+
errors.push("Local port must be an integer from 1 to 65535.");
|
|
15
|
+
}
|
|
16
|
+
if (!input.noAccess) {
|
|
17
|
+
const rawEmails = Array.isArray(input.emails) ? input.emails : input.emails.split(",");
|
|
18
|
+
const emails = rawEmails.map((email) => email.trim()).filter(Boolean);
|
|
19
|
+
if (!emails.length)
|
|
20
|
+
errors.push("Add at least one allowed email address (or skip Cloudflare Access).");
|
|
21
|
+
if (emails.some((email) => !isValidEmail(email)))
|
|
22
|
+
errors.push("Every allowed email must be a valid email address.");
|
|
23
|
+
}
|
|
24
|
+
if (input.runMode !== "foreground" && input.runMode !== "background") {
|
|
25
|
+
errors.push("Choose foreground or background run mode.");
|
|
26
|
+
}
|
|
27
|
+
return errors;
|
|
28
|
+
}
|
|
29
|
+
export function buildTunnelPublishPlan(input) {
|
|
30
|
+
const errors = validateTunnelPublishInput(input);
|
|
31
|
+
if (errors.length)
|
|
32
|
+
throw new Error(errors.join(" "));
|
|
33
|
+
const zone = input.zone.trim().toLowerCase().replace(/\.$/, "");
|
|
34
|
+
const app = input.app.trim().toLowerCase();
|
|
35
|
+
const port = Number(input.port);
|
|
36
|
+
const noAccess = !!input.noAccess;
|
|
37
|
+
const rawEmails = Array.isArray(input.emails) ? input.emails : input.emails.split(",");
|
|
38
|
+
const emails = noAccess
|
|
39
|
+
? []
|
|
40
|
+
: [...new Set(rawEmails.map((email) => email.trim().toLowerCase()).filter(Boolean))];
|
|
41
|
+
const hostname = `${app}.${zone}`;
|
|
42
|
+
const allow = emails.join(",");
|
|
43
|
+
return {
|
|
44
|
+
zone,
|
|
45
|
+
app,
|
|
46
|
+
port,
|
|
47
|
+
emails,
|
|
48
|
+
runMode: input.runMode,
|
|
49
|
+
noAccess,
|
|
50
|
+
hostname,
|
|
51
|
+
publicUrl: `https://${hostname}`,
|
|
52
|
+
localOrigin: `http://localhost:${port}`,
|
|
53
|
+
commands: {
|
|
54
|
+
setup: "repoos tunnel setup",
|
|
55
|
+
create: noAccess
|
|
56
|
+
? `repoos tunnel create ${app} --port ${port} --domain ${hostname} --no-access`
|
|
57
|
+
: `repoos tunnel create ${app} --port ${port} --domain ${hostname} --allow ${allow}`,
|
|
58
|
+
run: input.runMode === "background" ? "repoos tunnel install" : "repoos tunnel start",
|
|
59
|
+
status: "repoos tunnel status",
|
|
60
|
+
},
|
|
61
|
+
authNote: noAccess
|
|
62
|
+
? "This app skips Cloudflare Access entirely — it's fully public at Cloudflare's edge. RepoOS native auth (auth.enabled = true in repoos.toml) is its ONLY gate, and `repoos tunnel create` will refuse --no-access unless it's already on."
|
|
63
|
+
: "When using a public Cloudflare Tunnel, enable RepoOS native auth (auth.enabled = true in repoos.toml) for an additional layer of access control beyond Cloudflare Access. This ensures RepoOS itself rejects unauthorized requests, even if the tunnel is publicly accessible.",
|
|
64
|
+
};
|
|
65
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { type TunnelApp, type TunnelConfig } from "./tunnel.js";
|
|
2
|
+
/** A registry entry: a published app plus which repo checkout owns it. */
|
|
3
|
+
export interface RegistryApp extends TunnelApp {
|
|
4
|
+
/** Absolute path to the repo checkout that created this app. */
|
|
5
|
+
ownerRoot: string;
|
|
6
|
+
}
|
|
7
|
+
/** The machine-level registry: one shared tunnel identity + every repo's apps. */
|
|
8
|
+
export interface TunnelRegistry {
|
|
9
|
+
tunnelId: string;
|
|
10
|
+
tunnelName: string;
|
|
11
|
+
domain: string;
|
|
12
|
+
apps: Record<string, RegistryApp>;
|
|
13
|
+
}
|
|
14
|
+
export declare function emptyRegistry(): TunnelRegistry;
|
|
15
|
+
/** Default location — one registry per machine, outside any repo. */
|
|
16
|
+
export declare function registryPath(): string;
|
|
17
|
+
export declare function parseRegistry(text: string): TunnelRegistry;
|
|
18
|
+
export declare function serializeRegistry(reg: TunnelRegistry): string;
|
|
19
|
+
/** Read the machine registry. Missing file reads as an empty registry. */
|
|
20
|
+
export declare function readRegistry(path?: string): TunnelRegistry;
|
|
21
|
+
/**
|
|
22
|
+
* Persist the machine registry (0600 — same treatment as the derived ingress
|
|
23
|
+
* config). Writes to a sibling temp file and renames it over the real path
|
|
24
|
+
* (atomic on POSIX) so a concurrent reader (another repo's `tunnel list`, or
|
|
25
|
+
* this same read done mid-write) never observes a truncated/partial file.
|
|
26
|
+
*/
|
|
27
|
+
export declare function writeRegistry(reg: TunnelRegistry, path?: string): void;
|
|
28
|
+
/**
|
|
29
|
+
* Hold an exclusive lock on the registry while running `fn`. Two `repoos
|
|
30
|
+
* tunnel` processes on the same machine — the exact scenario this registry
|
|
31
|
+
* exists for — can otherwise race a read-modify-write and silently drop one
|
|
32
|
+
* another's change (last write wins). A sibling `<path>.lock` file created
|
|
33
|
+
* with the atomic create-if-absent (`wx`) flag serves as a simple
|
|
34
|
+
* cross-process mutex: a lock older than {@link LOCK_STALE_MS} is assumed to
|
|
35
|
+
* be left behind by a crashed process and is stolen rather than waited on
|
|
36
|
+
* forever.
|
|
37
|
+
*/
|
|
38
|
+
export declare function withRegistryLock<T>(path: string, fn: () => T): T;
|
|
39
|
+
/**
|
|
40
|
+
* Reconcile a repo's tunnel identity against the registry's. A machine runs
|
|
41
|
+
* ONE Cloudflare Tunnel, so if the registry already has an identity and this
|
|
42
|
+
* repo's disagrees, refuse rather than silently picking one — returns an
|
|
43
|
+
* error message. When the registry has no identity yet, adopts the repo's
|
|
44
|
+
* (mutates `reg` in place). No-ops when the repo itself isn't set up yet.
|
|
45
|
+
*/
|
|
46
|
+
export declare function reconcileIdentity(reg: TunnelRegistry, tunnel: TunnelConfig): string | null;
|
|
47
|
+
/** Add or replace a registry entry, tagging it with its owning repo. */
|
|
48
|
+
export declare function upsertApp(reg: TunnelRegistry, name: string, app: TunnelApp, ownerRoot: string): void;
|
|
49
|
+
/** Remove a registry entry (no-ops when absent). */
|
|
50
|
+
export declare function removeApp(reg: TunnelRegistry, name: string): void;
|
|
51
|
+
/** Strip `ownerRoot` back to plain `TunnelApp`s — the shape `renderCloudflaredConfig` expects. */
|
|
52
|
+
export declare function unionApps(reg: TunnelRegistry): Record<string, TunnelApp>;
|
|
53
|
+
/**
|
|
54
|
+
* Reconcile the registry against THIS repo's own `repoos.toml [tunnel.apps]`
|
|
55
|
+
* — still the git-tracked, hand-edited source of truth for the apps this
|
|
56
|
+
* repo publishes. Mutates `reg` in place and returns the names that were
|
|
57
|
+
* newly seeded (for the same one-time log line callers have always printed).
|
|
58
|
+
* Three cases, keyed entirely on `ownerRoot` so another repo's entries are
|
|
59
|
+
* never touched:
|
|
60
|
+
*
|
|
61
|
+
* - in `tunnel.apps`, missing from the registry → seed it (first run after
|
|
62
|
+
* upgrade, or a brand-new `create` on an otherwise-synced registry).
|
|
63
|
+
* - in `tunnel.apps` AND already registered under THIS repo's `ownerRoot`,
|
|
64
|
+
* but with different fields (hostname/port/access edited by hand in
|
|
65
|
+
* repoos.toml rather than through `repoos tunnel`) → overwrite the
|
|
66
|
+
* registry entry so it can't drift from the file that's supposed to be
|
|
67
|
+
* authoritative for it.
|
|
68
|
+
* - registered under THIS repo's `ownerRoot` but no longer in `tunnel.apps`
|
|
69
|
+
* (deleted by hand rather than via `repoos tunnel destroy`) → drop it,
|
|
70
|
+
* since this repo no longer declares it.
|
|
71
|
+
*
|
|
72
|
+
* An entry owned by a DIFFERENT repo is left alone in every case, even when
|
|
73
|
+
* this repo's own `tunnel.apps` happens to declare the same name (a
|
|
74
|
+
* pre-existing collision — surfaced to the user elsewhere, not silently
|
|
75
|
+
* resolved here).
|
|
76
|
+
*
|
|
77
|
+
* Deliberately per-app rather than gated on "registry is totally empty": on
|
|
78
|
+
* a machine with multiple PRE-EXISTING repos (each already publishing its
|
|
79
|
+
* own apps before this registry existed), each repo seeds its own apps into
|
|
80
|
+
* the registry the first time IT runs `create`/`install`/`start`, regardless
|
|
81
|
+
* of whether another repo got there first and seeded its own — that's
|
|
82
|
+
* exactly the scenario (celleris + dev on one tunnel) this registry exists
|
|
83
|
+
* to fix. For the common single-repo case this still behaves like a
|
|
84
|
+
* one-time full migration, since every app is missing on the first run and
|
|
85
|
+
* every run after that is a no-op unless repoos.toml itself changed.
|
|
86
|
+
*/
|
|
87
|
+
export declare function syncFromRepo(reg: TunnelRegistry, tunnel: TunnelConfig, root: string): string[];
|
|
88
|
+
/** A registry entry annotated with whether its owning repo checkout still exists on disk. */
|
|
89
|
+
export interface RegistryAppHealth {
|
|
90
|
+
name: string;
|
|
91
|
+
app: RegistryApp;
|
|
92
|
+
/** `ownerRoot` no longer exists on disk — the repo that published this app is gone. */
|
|
93
|
+
stale: boolean;
|
|
94
|
+
}
|
|
95
|
+
/** Every registry app, sorted by name, annotated with staleness. */
|
|
96
|
+
export declare function annotateStale(reg: TunnelRegistry): RegistryAppHealth[];
|