gazetta 0.6.0 → 0.8.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/admin-dist/assets/index-CBeq0rRb.js +693 -0
- package/admin-dist/assets/index-Dtg1dTZQ.css +1 -0
- package/admin-dist/assets/rolldown-runtime-BYbx6iT9.js +1 -0
- package/admin-dist/assets/{vendor-primevue-C0Q_YTCb.js → vendor-primevue-CBGHkaXv.js} +183 -39
- package/admin-dist/assets/{vendor-react-BipDVGow.js → vendor-react-BdW_kNCG.js} +2 -2
- package/admin-dist/assets/vendor-rjsf-lN2SztQt.js +33 -0
- package/admin-dist/assets/vendor-tiptap-C36yDquB.js +141 -0
- package/admin-dist/assets/vendor-vue-Bt5uR1VW.js +1 -0
- package/admin-dist/assets/workbox-window.prod.es5-DGMtIXHc.js +2 -0
- package/admin-dist/index.html +8 -8
- package/admin-dist/sw.js +1 -0
- package/dist/admin-api/archived-name-conflict.d.ts +31 -0
- package/dist/admin-api/archived-name-conflict.d.ts.map +1 -0
- package/dist/admin-api/archived-name-conflict.js +226 -0
- package/dist/admin-api/archived-name-conflict.js.map +1 -0
- package/dist/admin-api/cache-stats-logger.d.ts +83 -0
- package/dist/admin-api/cache-stats-logger.d.ts.map +1 -0
- package/dist/admin-api/cache-stats-logger.js +59 -0
- package/dist/admin-api/cache-stats-logger.js.map +1 -0
- package/dist/admin-api/error-response.d.ts +21 -0
- package/dist/admin-api/error-response.d.ts.map +1 -0
- package/dist/admin-api/error-response.js +12 -0
- package/dist/admin-api/error-response.js.map +1 -0
- package/dist/admin-api/hook-audit-emitter.d.ts +38 -0
- package/dist/admin-api/hook-audit-emitter.d.ts.map +1 -0
- package/dist/admin-api/hook-audit-emitter.js +21 -0
- package/dist/admin-api/hook-audit-emitter.js.map +1 -0
- package/dist/admin-api/index.d.ts +84 -2
- package/dist/admin-api/index.d.ts.map +1 -1
- package/dist/admin-api/index.js +257 -32
- package/dist/admin-api/index.js.map +1 -1
- package/dist/admin-api/middleware/audit.d.ts +25 -0
- package/dist/admin-api/middleware/audit.d.ts.map +1 -0
- package/dist/admin-api/middleware/audit.js +65 -0
- package/dist/admin-api/middleware/audit.js.map +1 -0
- package/dist/admin-api/middleware/capability.d.ts +8 -0
- package/dist/admin-api/middleware/capability.d.ts.map +1 -0
- package/dist/admin-api/middleware/capability.js +65 -0
- package/dist/admin-api/middleware/capability.js.map +1 -0
- package/dist/admin-api/middleware/principal.d.ts +18 -0
- package/dist/admin-api/middleware/principal.d.ts.map +1 -0
- package/dist/admin-api/middleware/principal.js +128 -0
- package/dist/admin-api/middleware/principal.js.map +1 -0
- package/dist/admin-api/routes/archive-review.d.ts +80 -0
- package/dist/admin-api/routes/archive-review.d.ts.map +1 -0
- package/dist/admin-api/routes/archive-review.js +70 -0
- package/dist/admin-api/routes/archive-review.js.map +1 -0
- package/dist/admin-api/routes/archive.d.ts +145 -0
- package/dist/admin-api/routes/archive.d.ts.map +1 -0
- package/dist/admin-api/routes/archive.js +540 -0
- package/dist/admin-api/routes/archive.js.map +1 -0
- package/dist/admin-api/routes/assets.d.ts +21 -0
- package/dist/admin-api/routes/assets.d.ts.map +1 -0
- package/dist/admin-api/routes/assets.js +586 -0
- package/dist/admin-api/routes/assets.js.map +1 -0
- package/dist/admin-api/routes/audit.d.ts +71 -0
- package/dist/admin-api/routes/audit.d.ts.map +1 -0
- package/dist/admin-api/routes/audit.js +178 -0
- package/dist/admin-api/routes/audit.js.map +1 -0
- package/dist/admin-api/routes/compare.d.ts.map +1 -1
- package/dist/admin-api/routes/compare.js +3 -2
- package/dist/admin-api/routes/compare.js.map +1 -1
- package/dist/admin-api/routes/fields.d.ts.map +1 -1
- package/dist/admin-api/routes/fields.js +2 -1
- package/dist/admin-api/routes/fields.js.map +1 -1
- package/dist/admin-api/routes/fragments.d.ts +13 -1
- package/dist/admin-api/routes/fragments.d.ts.map +1 -1
- package/dist/admin-api/routes/fragments.js +128 -67
- package/dist/admin-api/routes/fragments.js.map +1 -1
- package/dist/admin-api/routes/health.d.ts +60 -0
- package/dist/admin-api/routes/health.d.ts.map +1 -0
- package/dist/admin-api/routes/health.js +65 -0
- package/dist/admin-api/routes/health.js.map +1 -0
- package/dist/admin-api/routes/history.d.ts +2 -1
- package/dist/admin-api/routes/history.d.ts.map +1 -1
- package/dist/admin-api/routes/history.js +26 -4
- package/dist/admin-api/routes/history.js.map +1 -1
- package/dist/admin-api/routes/pages.d.ts +20 -1
- package/dist/admin-api/routes/pages.d.ts.map +1 -1
- package/dist/admin-api/routes/pages.js +158 -85
- package/dist/admin-api/routes/pages.js.map +1 -1
- package/dist/admin-api/routes/preview.d.ts.map +1 -1
- package/dist/admin-api/routes/preview.js +56 -17
- package/dist/admin-api/routes/preview.js.map +1 -1
- package/dist/admin-api/routes/publish.d.ts +19 -1
- package/dist/admin-api/routes/publish.d.ts.map +1 -1
- package/dist/admin-api/routes/publish.js +548 -99
- package/dist/admin-api/routes/publish.js.map +1 -1
- package/dist/admin-api/routes/rename.d.ts +62 -0
- package/dist/admin-api/routes/rename.d.ts.map +1 -0
- package/dist/admin-api/routes/rename.js +366 -0
- package/dist/admin-api/routes/rename.js.map +1 -0
- package/dist/admin-api/routes/site.d.ts.map +1 -1
- package/dist/admin-api/routes/site.js +6 -18
- package/dist/admin-api/routes/site.js.map +1 -1
- package/dist/admin-api/routes/system.d.ts +23 -0
- package/dist/admin-api/routes/system.d.ts.map +1 -0
- package/dist/admin-api/routes/system.js +115 -0
- package/dist/admin-api/routes/system.js.map +1 -0
- package/dist/admin-api/routes/templates.d.ts +11 -1
- package/dist/admin-api/routes/templates.d.ts.map +1 -1
- package/dist/admin-api/routes/templates.js +36 -3
- package/dist/admin-api/routes/templates.js.map +1 -1
- package/dist/admin-api/routes/validation.d.ts +47 -0
- package/dist/admin-api/routes/validation.d.ts.map +1 -0
- package/dist/admin-api/routes/validation.js +120 -0
- package/dist/admin-api/routes/validation.js.map +1 -0
- package/dist/admin-api/schemas/archive.d.ts +124 -0
- package/dist/admin-api/schemas/archive.d.ts.map +1 -0
- package/dist/admin-api/schemas/archive.js +93 -0
- package/dist/admin-api/schemas/archive.js.map +1 -0
- package/dist/admin-api/schemas/assets.d.ts +64 -0
- package/dist/admin-api/schemas/assets.d.ts.map +1 -0
- package/dist/admin-api/schemas/assets.js +59 -0
- package/dist/admin-api/schemas/assets.js.map +1 -0
- package/dist/admin-api/schemas/audit.d.ts +175 -0
- package/dist/admin-api/schemas/audit.d.ts.map +1 -0
- package/dist/admin-api/schemas/audit.js +91 -0
- package/dist/admin-api/schemas/audit.js.map +1 -0
- package/dist/admin-api/schemas/error.d.ts +94 -0
- package/dist/admin-api/schemas/error.d.ts.map +1 -0
- package/dist/admin-api/schemas/error.js +79 -0
- package/dist/admin-api/schemas/error.js.map +1 -0
- package/dist/admin-api/schemas/fragments.d.ts +2 -0
- package/dist/admin-api/schemas/fragments.d.ts.map +1 -1
- package/dist/admin-api/schemas/fragments.js +4 -0
- package/dist/admin-api/schemas/fragments.js.map +1 -1
- package/dist/admin-api/schemas/index.d.ts +10 -0
- package/dist/admin-api/schemas/index.d.ts.map +1 -1
- package/dist/admin-api/schemas/index.js +10 -0
- package/dist/admin-api/schemas/index.js.map +1 -1
- package/dist/admin-api/schemas/pages.d.ts +2 -0
- package/dist/admin-api/schemas/pages.d.ts.map +1 -1
- package/dist/admin-api/schemas/pages.js +11 -0
- package/dist/admin-api/schemas/pages.js.map +1 -1
- package/dist/admin-api/schemas/rename.d.ts +77 -0
- package/dist/admin-api/schemas/rename.d.ts.map +1 -0
- package/dist/admin-api/schemas/rename.js +75 -0
- package/dist/admin-api/schemas/rename.js.map +1 -0
- package/dist/admin-api/schemas/site.d.ts +3 -2
- package/dist/admin-api/schemas/site.d.ts.map +1 -1
- package/dist/admin-api/schemas/site.js +3 -2
- package/dist/admin-api/schemas/site.js.map +1 -1
- package/dist/admin-api/schemas/system.d.ts +28 -0
- package/dist/admin-api/schemas/system.d.ts.map +1 -0
- package/dist/admin-api/schemas/system.js +35 -0
- package/dist/admin-api/schemas/system.js.map +1 -0
- package/dist/admin-api/schemas/targets.d.ts +55 -0
- package/dist/admin-api/schemas/targets.d.ts.map +1 -1
- package/dist/admin-api/schemas/targets.js +46 -0
- package/dist/admin-api/schemas/targets.js.map +1 -1
- package/dist/admin-api/schemas/templates.d.ts +54 -0
- package/dist/admin-api/schemas/templates.d.ts.map +1 -1
- package/dist/admin-api/schemas/templates.js +21 -0
- package/dist/admin-api/schemas/templates.js.map +1 -1
- package/dist/admin-api/schemas/validation.d.ts +101 -0
- package/dist/admin-api/schemas/validation.d.ts.map +1 -0
- package/dist/admin-api/schemas/validation.js +57 -0
- package/dist/admin-api/schemas/validation.js.map +1 -0
- package/dist/admin-api/source-context.d.ts +66 -17
- package/dist/admin-api/source-context.d.ts.map +1 -1
- package/dist/admin-api/source-context.js +43 -8
- package/dist/admin-api/source-context.js.map +1 -1
- package/dist/ai/adapter-scaffold.d.ts +63 -0
- package/dist/ai/adapter-scaffold.d.ts.map +1 -0
- package/dist/ai/adapter-scaffold.js +89 -0
- package/dist/ai/adapter-scaffold.js.map +1 -0
- package/dist/ai/compose-prompt.d.ts +50 -0
- package/dist/ai/compose-prompt.d.ts.map +1 -0
- package/dist/ai/compose-prompt.js +49 -0
- package/dist/ai/compose-prompt.js.map +1 -0
- package/dist/ai/errors.d.ts +65 -0
- package/dist/ai/errors.d.ts.map +1 -0
- package/dist/ai/errors.js +59 -0
- package/dist/ai/errors.js.map +1 -0
- package/dist/ai/index.d.ts +17 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +16 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/provider.d.ts +76 -0
- package/dist/ai/provider.d.ts.map +1 -0
- package/dist/ai/provider.js +13 -0
- package/dist/ai/provider.js.map +1 -0
- package/dist/ai/refusal.d.ts +50 -0
- package/dist/ai/refusal.d.ts.map +1 -0
- package/dist/ai/refusal.js +100 -0
- package/dist/ai/refusal.js.map +1 -0
- package/dist/ai/vision-prep.d.ts +32 -0
- package/dist/ai/vision-prep.d.ts.map +1 -0
- package/dist/ai/vision-prep.js +113 -0
- package/dist/ai/vision-prep.js.map +1 -0
- package/dist/alt/adapter.d.ts +140 -0
- package/dist/alt/adapter.d.ts.map +1 -0
- package/dist/alt/adapter.js +7 -0
- package/dist/alt/adapter.js.map +1 -0
- package/dist/alt/anthropic.d.ts +63 -0
- package/dist/alt/anthropic.d.ts.map +1 -0
- package/dist/alt/anthropic.js +147 -0
- package/dist/alt/anthropic.js.map +1 -0
- package/dist/alt/config.d.ts +67 -0
- package/dist/alt/config.d.ts.map +1 -0
- package/dist/alt/config.js +41 -0
- package/dist/alt/config.js.map +1 -0
- package/dist/alt/factory.d.ts +19 -0
- package/dist/alt/factory.d.ts.map +1 -0
- package/dist/alt/factory.js +69 -0
- package/dist/alt/factory.js.map +1 -0
- package/dist/alt/null-adapter.d.ts +3 -0
- package/dist/alt/null-adapter.d.ts.map +1 -0
- package/dist/alt/null-adapter.js +43 -0
- package/dist/alt/null-adapter.js.map +1 -0
- package/dist/alt/ollama.d.ts +40 -0
- package/dist/alt/ollama.d.ts.map +1 -0
- package/dist/alt/ollama.js +139 -0
- package/dist/alt/ollama.js.map +1 -0
- package/dist/alt/openai.d.ts +46 -0
- package/dist/alt/openai.d.ts.map +1 -0
- package/dist/alt/openai.js +118 -0
- package/dist/alt/openai.js.map +1 -0
- package/dist/alt/prompt-policies.d.ts +79 -0
- package/dist/alt/prompt-policies.d.ts.map +1 -0
- package/dist/alt/prompt-policies.js +67 -0
- package/dist/alt/prompt-policies.js.map +1 -0
- package/dist/alt/route-handler.d.ts +56 -0
- package/dist/alt/route-handler.d.ts.map +1 -0
- package/dist/alt/route-handler.js +122 -0
- package/dist/alt/route-handler.js.map +1 -0
- package/dist/alt/suggester.d.ts +57 -0
- package/dist/alt/suggester.d.ts.map +1 -0
- package/dist/alt/suggester.js +133 -0
- package/dist/alt/suggester.js.map +1 -0
- package/dist/app.js +1 -1
- package/dist/app.js.map +1 -1
- package/dist/archive-aliases.d.ts +79 -0
- package/dist/archive-aliases.d.ts.map +1 -0
- package/dist/archive-aliases.js +60 -0
- package/dist/archive-aliases.js.map +1 -0
- package/dist/archive-helpers.d.ts +73 -0
- package/dist/archive-helpers.d.ts.map +1 -0
- package/dist/archive-helpers.js +94 -0
- package/dist/archive-helpers.js.map +1 -0
- package/dist/assets/analyze-audio.d.ts +3 -0
- package/dist/assets/analyze-audio.d.ts.map +1 -0
- package/dist/assets/analyze-audio.js +80 -0
- package/dist/assets/analyze-audio.js.map +1 -0
- package/dist/assets/analyze-image.d.ts +19 -0
- package/dist/assets/analyze-image.d.ts.map +1 -0
- package/dist/assets/analyze-image.js +123 -0
- package/dist/assets/analyze-image.js.map +1 -0
- package/dist/assets/analyze.d.ts +94 -0
- package/dist/assets/analyze.d.ts.map +1 -0
- package/dist/assets/analyze.js +45 -0
- package/dist/assets/analyze.js.map +1 -0
- package/dist/assets/asset-deps.d.ts +30 -0
- package/dist/assets/asset-deps.d.ts.map +1 -0
- package/dist/assets/asset-deps.js +42 -0
- package/dist/assets/asset-deps.js.map +1 -0
- package/dist/assets/asset-paths.d.ts +155 -0
- package/dist/assets/asset-paths.d.ts.map +1 -0
- package/dist/assets/asset-paths.js +197 -0
- package/dist/assets/asset-paths.js.map +1 -0
- package/dist/assets/delete.d.ts +75 -0
- package/dist/assets/delete.d.ts.map +1 -0
- package/dist/assets/delete.js +82 -0
- package/dist/assets/delete.js.map +1 -0
- package/dist/assets/errors.d.ts +241 -0
- package/dist/assets/errors.d.ts.map +1 -0
- package/dist/assets/errors.js +300 -0
- package/dist/assets/errors.js.map +1 -0
- package/dist/assets/find-refs.d.ts +37 -0
- package/dist/assets/find-refs.d.ts.map +1 -0
- package/dist/assets/find-refs.js +35 -0
- package/dist/assets/find-refs.js.map +1 -0
- package/dist/assets/hash.d.ts +13 -0
- package/dist/assets/hash.d.ts.map +1 -0
- package/dist/assets/hash.js +43 -0
- package/dist/assets/hash.js.map +1 -0
- package/dist/assets/image-metadata.d.ts +11 -0
- package/dist/assets/image-metadata.d.ts.map +1 -0
- package/dist/assets/image-metadata.js +31 -0
- package/dist/assets/image-metadata.js.map +1 -0
- package/dist/assets/ingest-locale.d.ts +86 -0
- package/dist/assets/ingest-locale.d.ts.map +1 -0
- package/dist/assets/ingest-locale.js +209 -0
- package/dist/assets/ingest-locale.js.map +1 -0
- package/dist/assets/ingest.d.ts +96 -0
- package/dist/assets/ingest.d.ts.map +1 -0
- package/dist/assets/ingest.js +308 -0
- package/dist/assets/ingest.js.map +1 -0
- package/dist/assets/kind-compat.d.ts +34 -0
- package/dist/assets/kind-compat.d.ts.map +1 -0
- package/dist/assets/kind-compat.js +33 -0
- package/dist/assets/kind-compat.js.map +1 -0
- package/dist/assets/list.d.ts +46 -0
- package/dist/assets/list.d.ts.map +1 -0
- package/dist/assets/list.js +102 -0
- package/dist/assets/list.js.map +1 -0
- package/dist/assets/manifest-default.d.ts +56 -0
- package/dist/assets/manifest-default.d.ts.map +1 -0
- package/dist/assets/manifest-default.js +120 -0
- package/dist/assets/manifest-default.js.map +1 -0
- package/dist/assets/manifest-filename.d.ts +52 -0
- package/dist/assets/manifest-filename.d.ts.map +1 -0
- package/dist/assets/manifest-filename.js +104 -0
- package/dist/assets/manifest-filename.js.map +1 -0
- package/dist/assets/manifest-locale.d.ts +60 -0
- package/dist/assets/manifest-locale.d.ts.map +1 -0
- package/dist/assets/manifest-locale.js +206 -0
- package/dist/assets/manifest-locale.js.map +1 -0
- package/dist/assets/manifest-merge.d.ts +66 -0
- package/dist/assets/manifest-merge.d.ts.map +1 -0
- package/dist/assets/manifest-merge.js +82 -0
- package/dist/assets/manifest-merge.js.map +1 -0
- package/dist/assets/manifest.d.ts +83 -0
- package/dist/assets/manifest.d.ts.map +1 -0
- package/dist/assets/manifest.js +93 -0
- package/dist/assets/manifest.js.map +1 -0
- package/dist/assets/mime-sniff.d.ts +18 -0
- package/dist/assets/mime-sniff.d.ts.map +1 -0
- package/dist/assets/mime-sniff.js +84 -0
- package/dist/assets/mime-sniff.js.map +1 -0
- package/dist/assets/preprocess-svg.d.ts +3 -0
- package/dist/assets/preprocess-svg.d.ts.map +1 -0
- package/dist/assets/preprocess-svg.js +49 -0
- package/dist/assets/preprocess-svg.js.map +1 -0
- package/dist/assets/preprocess.d.ts +62 -0
- package/dist/assets/preprocess.d.ts.map +1 -0
- package/dist/assets/preprocess.js +86 -0
- package/dist/assets/preprocess.js.map +1 -0
- package/dist/assets/publish-plan.d.ts +41 -0
- package/dist/assets/publish-plan.d.ts.map +1 -0
- package/dist/assets/publish-plan.js +49 -0
- package/dist/assets/publish-plan.js.map +1 -0
- package/dist/assets/publish.d.ts +33 -0
- package/dist/assets/publish.d.ts.map +1 -0
- package/dist/assets/publish.js +81 -0
- package/dist/assets/publish.js.map +1 -0
- package/dist/assets/refs.d.ts +37 -0
- package/dist/assets/refs.d.ts.map +1 -0
- package/dist/assets/refs.js +33 -0
- package/dist/assets/refs.js.map +1 -0
- package/dist/assets/remove-override.d.ts +42 -0
- package/dist/assets/remove-override.d.ts.map +1 -0
- package/dist/assets/remove-override.js +53 -0
- package/dist/assets/remove-override.js.map +1 -0
- package/dist/assets/rename.d.ts +43 -0
- package/dist/assets/rename.d.ts.map +1 -0
- package/dist/assets/rename.js +271 -0
- package/dist/assets/rename.js.map +1 -0
- package/dist/assets/replace.d.ts +37 -0
- package/dist/assets/replace.d.ts.map +1 -0
- package/dist/assets/replace.js +195 -0
- package/dist/assets/replace.js.map +1 -0
- package/dist/assets/resolve.d.ts +141 -0
- package/dist/assets/resolve.d.ts.map +1 -0
- package/dist/assets/resolve.js +381 -0
- package/dist/assets/resolve.js.map +1 -0
- package/dist/assets/rewrite-manifest-asset-ref.d.ts +44 -0
- package/dist/assets/rewrite-manifest-asset-ref.d.ts.map +1 -0
- package/dist/assets/rewrite-manifest-asset-ref.js +51 -0
- package/dist/assets/rewrite-manifest-asset-ref.js.map +1 -0
- package/dist/assets/scan-manifest-for-asset.d.ts +63 -0
- package/dist/assets/scan-manifest-for-asset.d.ts.map +1 -0
- package/dist/assets/scan-manifest-for-asset.js +105 -0
- package/dist/assets/scan-manifest-for-asset.js.map +1 -0
- package/dist/assets/serve-route.d.ts +45 -0
- package/dist/assets/serve-route.d.ts.map +1 -0
- package/dist/assets/serve-route.js +123 -0
- package/dist/assets/serve-route.js.map +1 -0
- package/dist/assets/svg-sanitize.d.ts +38 -0
- package/dist/assets/svg-sanitize.d.ts.map +1 -0
- package/dist/assets/svg-sanitize.js +209 -0
- package/dist/assets/svg-sanitize.js.map +1 -0
- package/dist/assets/update-metadata.d.ts +61 -0
- package/dist/assets/update-metadata.d.ts.map +1 -0
- package/dist/assets/update-metadata.js +82 -0
- package/dist/assets/update-metadata.js.map +1 -0
- package/dist/assets/url.d.ts +82 -0
- package/dist/assets/url.d.ts.map +1 -0
- package/dist/assets/url.js +103 -0
- package/dist/assets/url.js.map +1 -0
- package/dist/assets/validate.d.ts +74 -0
- package/dist/assets/validate.d.ts.map +1 -0
- package/dist/assets/validate.js +136 -0
- package/dist/assets/validate.js.map +1 -0
- package/dist/assets/variants.d.ts +23 -0
- package/dist/assets/variants.d.ts.map +1 -0
- package/dist/assets/variants.js +74 -0
- package/dist/assets/variants.js.map +1 -0
- package/dist/audit/config.d.ts +75 -0
- package/dist/audit/config.d.ts.map +1 -0
- package/dist/audit/config.js +91 -0
- package/dist/audit/config.js.map +1 -0
- package/dist/audit/context.d.ts +98 -0
- package/dist/audit/context.d.ts.map +1 -0
- package/dist/audit/context.js +51 -0
- package/dist/audit/context.js.map +1 -0
- package/dist/audit/errors.d.ts +73 -0
- package/dist/audit/errors.d.ts.map +1 -0
- package/dist/audit/errors.js +78 -0
- package/dist/audit/errors.js.map +1 -0
- package/dist/audit/index.d.ts +16 -0
- package/dist/audit/index.d.ts.map +1 -0
- package/dist/audit/index.js +10 -0
- package/dist/audit/index.js.map +1 -0
- package/dist/audit/provider.d.ts +73 -0
- package/dist/audit/provider.d.ts.map +1 -0
- package/dist/audit/provider.js +2 -0
- package/dist/audit/provider.js.map +1 -0
- package/dist/audit/providers/history.d.ts +66 -0
- package/dist/audit/providers/history.d.ts.map +1 -0
- package/dist/audit/providers/history.js +102 -0
- package/dist/audit/providers/history.js.map +1 -0
- package/dist/audit/pseudonymize.d.ts +26 -0
- package/dist/audit/pseudonymize.d.ts.map +1 -0
- package/dist/audit/pseudonymize.js +86 -0
- package/dist/audit/pseudonymize.js.map +1 -0
- package/dist/audit/recorder.d.ts +102 -0
- package/dist/audit/recorder.d.ts.map +1 -0
- package/dist/audit/recorder.js +55 -0
- package/dist/audit/recorder.js.map +1 -0
- package/dist/audit/retention.d.ts +83 -0
- package/dist/audit/retention.d.ts.map +1 -0
- package/dist/audit/retention.js +142 -0
- package/dist/audit/retention.js.map +1 -0
- package/dist/audit/source-ip.d.ts +32 -0
- package/dist/audit/source-ip.d.ts.map +1 -0
- package/dist/audit/source-ip.js +164 -0
- package/dist/audit/source-ip.js.map +1 -0
- package/dist/audit/types.d.ts +143 -0
- package/dist/audit/types.d.ts.map +1 -0
- package/dist/audit/types.js +33 -0
- package/dist/audit/types.js.map +1 -0
- package/dist/audit/user-agent.d.ts +28 -0
- package/dist/audit/user-agent.d.ts.map +1 -0
- package/dist/audit/user-agent.js +63 -0
- package/dist/audit/user-agent.js.map +1 -0
- package/dist/auth/capabilities.d.ts +28 -0
- package/dist/auth/capabilities.d.ts.map +1 -0
- package/dist/auth/capabilities.js +101 -0
- package/dist/auth/capabilities.js.map +1 -0
- package/dist/auth/config.d.ts +109 -0
- package/dist/auth/config.d.ts.map +1 -0
- package/dist/auth/config.js +221 -0
- package/dist/auth/config.js.map +1 -0
- package/dist/auth/errors.d.ts +72 -0
- package/dist/auth/errors.d.ts.map +1 -0
- package/dist/auth/errors.js +78 -0
- package/dist/auth/errors.js.map +1 -0
- package/dist/auth/factory.d.ts +43 -0
- package/dist/auth/factory.d.ts.map +1 -0
- package/dist/auth/factory.js +48 -0
- package/dist/auth/factory.js.map +1 -0
- package/dist/auth/index.d.ts +21 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +14 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/ip-match.d.ts +29 -0
- package/dist/auth/ip-match.d.ts.map +1 -0
- package/dist/auth/ip-match.js +162 -0
- package/dist/auth/ip-match.js.map +1 -0
- package/dist/auth/provider.d.ts +76 -0
- package/dist/auth/provider.d.ts.map +1 -0
- package/dist/auth/provider.js +2 -0
- package/dist/auth/provider.js.map +1 -0
- package/dist/auth/providers/aws-cognito.d.ts +55 -0
- package/dist/auth/providers/aws-cognito.d.ts.map +1 -0
- package/dist/auth/providers/aws-cognito.js +114 -0
- package/dist/auth/providers/aws-cognito.js.map +1 -0
- package/dist/auth/providers/azure-easy-auth.d.ts +7 -0
- package/dist/auth/providers/azure-easy-auth.d.ts.map +1 -0
- package/dist/auth/providers/azure-easy-auth.js +48 -0
- package/dist/auth/providers/azure-easy-auth.js.map +1 -0
- package/dist/auth/providers/cloudflare-access.d.ts +71 -0
- package/dist/auth/providers/cloudflare-access.d.ts.map +1 -0
- package/dist/auth/providers/cloudflare-access.js +120 -0
- package/dist/auth/providers/cloudflare-access.js.map +1 -0
- package/dist/auth/providers/forwarded-user.d.ts +31 -0
- package/dist/auth/providers/forwarded-user.d.ts.map +1 -0
- package/dist/auth/providers/forwarded-user.js +72 -0
- package/dist/auth/providers/forwarded-user.js.map +1 -0
- package/dist/auth/providers/none.d.ts +6 -0
- package/dist/auth/providers/none.d.ts.map +1 -0
- package/dist/auth/providers/none.js +19 -0
- package/dist/auth/providers/none.js.map +1 -0
- package/dist/auth/providers/tailscale.d.ts +7 -0
- package/dist/auth/providers/tailscale.d.ts.map +1 -0
- package/dist/auth/providers/tailscale.js +30 -0
- package/dist/auth/providers/tailscale.js.map +1 -0
- package/dist/auth/role-resolver.d.ts +38 -0
- package/dist/auth/role-resolver.d.ts.map +1 -0
- package/dist/auth/role-resolver.js +92 -0
- package/dist/auth/role-resolver.js.map +1 -0
- package/dist/auth/types.d.ts +150 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +60 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/cache/errors.d.ts +41 -0
- package/dist/cache/errors.d.ts.map +1 -0
- package/dist/cache/errors.js +44 -0
- package/dist/cache/errors.js.map +1 -0
- package/dist/cache/factories.d.ts +17 -0
- package/dist/cache/factories.d.ts.map +1 -0
- package/dist/cache/factories.js +17 -0
- package/dist/cache/factories.js.map +1 -0
- package/dist/cache/keys.d.ts +63 -0
- package/dist/cache/keys.d.ts.map +1 -0
- package/dist/cache/keys.js +145 -0
- package/dist/cache/keys.js.map +1 -0
- package/dist/cache/memory.d.ts +51 -0
- package/dist/cache/memory.d.ts.map +1 -0
- package/dist/cache/memory.js +204 -0
- package/dist/cache/memory.js.map +1 -0
- package/dist/cache/per-site.d.ts +22 -0
- package/dist/cache/per-site.d.ts.map +1 -0
- package/dist/cache/per-site.js +114 -0
- package/dist/cache/per-site.js.map +1 -0
- package/dist/cache/types.d.ts +142 -0
- package/dist/cache/types.d.ts.map +1 -0
- package/dist/cache/types.js +33 -0
- package/dist/cache/types.js.map +1 -0
- package/dist/cli/archive.d.ts +44 -0
- package/dist/cli/archive.d.ts.map +1 -0
- package/dist/cli/archive.js +310 -0
- package/dist/cli/archive.js.map +1 -0
- package/dist/cli/assets-cli.d.ts +58 -0
- package/dist/cli/assets-cli.d.ts.map +1 -0
- package/dist/cli/assets-cli.js +233 -0
- package/dist/cli/assets-cli.js.map +1 -0
- package/dist/cli/assets-display.d.ts +112 -0
- package/dist/cli/assets-display.d.ts.map +1 -0
- package/dist/cli/assets-display.js +106 -0
- package/dist/cli/assets-display.js.map +1 -0
- package/dist/cli/bootstrap.d.ts +15 -10
- package/dist/cli/bootstrap.d.ts.map +1 -1
- package/dist/cli/bootstrap.js +59 -24
- package/dist/cli/bootstrap.js.map +1 -1
- package/dist/cli/dev-template-watcher.d.ts +29 -0
- package/dist/cli/dev-template-watcher.d.ts.map +1 -0
- package/dist/cli/dev-template-watcher.js +38 -0
- package/dist/cli/dev-template-watcher.js.map +1 -0
- package/dist/cli/history.d.ts.map +1 -1
- package/dist/cli/history.js +5 -3
- package/dist/cli/history.js.map +1 -1
- package/dist/cli/index.js +737 -374
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/validate-flags.d.ts +29 -0
- package/dist/cli/validate-flags.d.ts.map +1 -0
- package/dist/cli/validate-flags.js +49 -0
- package/dist/cli/validate-flags.js.map +1 -0
- package/dist/compare.d.ts +1 -1
- package/dist/compare.d.ts.map +1 -1
- package/dist/compare.js +40 -35
- package/dist/compare.js.map +1 -1
- package/dist/component-ids.d.ts +25 -0
- package/dist/component-ids.d.ts.map +1 -0
- package/dist/component-ids.js +83 -0
- package/dist/component-ids.js.map +1 -0
- package/dist/config/define.d.ts +61 -0
- package/dist/config/define.d.ts.map +1 -0
- package/dist/config/define.js +64 -0
- package/dist/config/define.js.map +1 -0
- package/dist/config/errors.d.ts +32 -0
- package/dist/config/errors.d.ts.map +1 -0
- package/dist/config/errors.js +40 -0
- package/dist/config/errors.js.map +1 -0
- package/dist/config/index.d.ts +13 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +20 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/loader.d.ts +105 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +265 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/schemas.d.ts +89 -0
- package/dist/config/schemas.d.ts.map +1 -0
- package/dist/config/schemas.js +172 -0
- package/dist/config/schemas.js.map +1 -0
- package/dist/config/types.d.ts +32 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +15 -0
- package/dist/config/types.js.map +1 -0
- package/dist/dep-sidecars.d.ts +127 -0
- package/dist/dep-sidecars.d.ts.map +1 -0
- package/dist/dep-sidecars.js +122 -0
- package/dist/dep-sidecars.js.map +1 -0
- package/dist/deploy/cloudflare-workers.d.ts +46 -0
- package/dist/deploy/cloudflare-workers.d.ts.map +1 -0
- package/dist/deploy/cloudflare-workers.js +213 -0
- package/dist/deploy/cloudflare-workers.js.map +1 -0
- package/dist/deploy/errors.d.ts +66 -0
- package/dist/deploy/errors.d.ts.map +1 -0
- package/dist/deploy/errors.js +82 -0
- package/dist/deploy/errors.js.map +1 -0
- package/dist/deploy/index.d.ts +9 -0
- package/dist/deploy/index.d.ts.map +1 -0
- package/dist/deploy/index.js +3 -0
- package/dist/deploy/index.js.map +1 -0
- package/dist/deploy/types.d.ts +162 -0
- package/dist/deploy/types.d.ts.map +1 -0
- package/dist/deploy/types.js +2 -0
- package/dist/deploy/types.js.map +1 -0
- package/dist/editor/AssetEmbeddedWidget.d.ts +3 -0
- package/dist/editor/AssetEmbeddedWidget.d.ts.map +1 -0
- package/dist/editor/AssetEmbeddedWidget.js +146 -0
- package/dist/editor/AssetEmbeddedWidget.js.map +1 -0
- package/dist/editor/mount.d.ts +12 -1
- package/dist/editor/mount.d.ts.map +1 -1
- package/dist/editor/mount.js +36 -5
- package/dist/editor/mount.js.map +1 -1
- package/dist/format.d.ts +44 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +65 -0
- package/dist/format.js.map +1 -0
- package/dist/fragment-deps.d.ts +24 -0
- package/dist/fragment-deps.d.ts.map +1 -0
- package/dist/fragment-deps.js +20 -0
- package/dist/fragment-deps.js.map +1 -0
- package/dist/fragments/create.d.ts +70 -0
- package/dist/fragments/create.d.ts.map +1 -0
- package/dist/fragments/create.js +93 -0
- package/dist/fragments/create.js.map +1 -0
- package/dist/fragments/publish.d.ts +37 -0
- package/dist/fragments/publish.d.ts.map +1 -0
- package/dist/fragments/publish.js +52 -0
- package/dist/fragments/publish.js.map +1 -0
- package/dist/fragments/save.d.ts +81 -0
- package/dist/fragments/save.d.ts.map +1 -0
- package/dist/fragments/save.js +105 -0
- package/dist/fragments/save.js.map +1 -0
- package/dist/hash.d.ts +0 -6
- package/dist/hash.d.ts.map +1 -1
- package/dist/hash.js +0 -18
- package/dist/hash.js.map +1 -1
- package/dist/history-provider.d.ts.map +1 -1
- package/dist/history-provider.js +30 -8
- package/dist/history-provider.js.map +1 -1
- package/dist/history-recorder.d.ts +10 -6
- package/dist/history-recorder.d.ts.map +1 -1
- package/dist/history-recorder.js +13 -5
- package/dist/history-recorder.js.map +1 -1
- package/dist/history-restorer.d.ts.map +1 -1
- package/dist/history-restorer.js +34 -2
- package/dist/history-restorer.js.map +1 -1
- package/dist/history.d.ts +26 -8
- package/dist/history.d.ts.map +1 -1
- package/dist/hooks/audit-emitter.d.ts +73 -0
- package/dist/hooks/audit-emitter.d.ts.map +1 -0
- package/dist/hooks/audit-emitter.js +13 -0
- package/dist/hooks/audit-emitter.js.map +1 -0
- package/dist/hooks/context.d.ts +78 -0
- package/dist/hooks/context.d.ts.map +1 -0
- package/dist/hooks/context.js +56 -0
- package/dist/hooks/context.js.map +1 -0
- package/dist/hooks/contribution.d.ts +90 -0
- package/dist/hooks/contribution.d.ts.map +1 -0
- package/dist/hooks/contribution.js +2 -0
- package/dist/hooks/contribution.js.map +1 -0
- package/dist/hooks/dispatch.d.ts +30 -0
- package/dist/hooks/dispatch.d.ts.map +1 -0
- package/dist/hooks/dispatch.js +252 -0
- package/dist/hooks/dispatch.js.map +1 -0
- package/dist/hooks/errors.d.ts +100 -0
- package/dist/hooks/errors.d.ts.map +1 -0
- package/dist/hooks/errors.js +103 -0
- package/dist/hooks/errors.js.map +1 -0
- package/dist/hooks/index.d.ts +15 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +6 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/registry.d.ts +53 -0
- package/dist/hooks/registry.d.ts.map +1 -0
- package/dist/hooks/registry.js +139 -0
- package/dist/hooks/registry.js.map +1 -0
- package/dist/hooks/storage.d.ts +43 -0
- package/dist/hooks/storage.d.ts.map +1 -0
- package/dist/hooks/storage.js +2 -0
- package/dist/hooks/storage.js.map +1 -0
- package/dist/hooks/types.d.ts +324 -0
- package/dist/hooks/types.d.ts.map +1 -0
- package/dist/hooks/types.js +2 -0
- package/dist/hooks/types.js.map +1 -0
- package/dist/index.d.ts +27 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +50 -7
- package/dist/index.js.map +1 -1
- package/dist/locale.d.ts +25 -1
- package/dist/locale.d.ts.map +1 -1
- package/dist/locale.js +44 -2
- package/dist/locale.js.map +1 -1
- package/dist/manifest-save.d.ts +255 -0
- package/dist/manifest-save.d.ts.map +1 -0
- package/dist/manifest-save.js +260 -0
- package/dist/manifest-save.js.map +1 -0
- package/dist/manifest.d.ts +1 -2
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +43 -44
- package/dist/manifest.js.map +1 -1
- package/dist/node-floor.d.ts +3 -0
- package/dist/node-floor.d.ts.map +1 -0
- package/dist/node-floor.js +3 -0
- package/dist/node-floor.js.map +1 -0
- package/dist/pages/create.d.ts +103 -0
- package/dist/pages/create.d.ts.map +1 -0
- package/dist/pages/create.js +117 -0
- package/dist/pages/create.js.map +1 -0
- package/dist/pages/publish.d.ts +59 -0
- package/dist/pages/publish.d.ts.map +1 -0
- package/dist/pages/publish.js +78 -0
- package/dist/pages/publish.js.map +1 -0
- package/dist/pages/save.d.ts +97 -0
- package/dist/pages/save.d.ts.map +1 -0
- package/dist/pages/save.js +138 -0
- package/dist/pages/save.js.map +1 -0
- package/dist/providers/_atomic-write.d.ts +9 -0
- package/dist/providers/_atomic-write.d.ts.map +1 -0
- package/dist/providers/_atomic-write.js +72 -0
- package/dist/providers/_atomic-write.js.map +1 -0
- package/dist/providers/_rm-ignore-missing.d.ts +31 -0
- package/dist/providers/_rm-ignore-missing.d.ts.map +1 -0
- package/dist/providers/_rm-ignore-missing.js +12 -0
- package/dist/providers/_rm-ignore-missing.js.map +1 -0
- package/dist/providers/_stream-interop.d.ts +23 -0
- package/dist/providers/_stream-interop.d.ts.map +1 -0
- package/dist/providers/_stream-interop.js +21 -0
- package/dist/providers/_stream-interop.js.map +1 -0
- package/dist/providers/azure-blob.d.ts.map +1 -1
- package/dist/providers/azure-blob.js +60 -0
- package/dist/providers/azure-blob.js.map +1 -1
- package/dist/providers/factories.d.ts +65 -0
- package/dist/providers/factories.d.ts.map +1 -0
- package/dist/providers/factories.js +189 -0
- package/dist/providers/factories.js.map +1 -0
- package/dist/providers/filesystem.d.ts +4 -0
- package/dist/providers/filesystem.d.ts.map +1 -1
- package/dist/providers/filesystem.js +63 -2
- package/dist/providers/filesystem.js.map +1 -1
- package/dist/providers/s3.d.ts.map +1 -1
- package/dist/providers/s3.js +84 -1
- package/dist/providers/s3.js.map +1 -1
- package/dist/publish-item.d.ts +225 -0
- package/dist/publish-item.d.ts.map +1 -0
- package/dist/publish-item.js +210 -0
- package/dist/publish-item.js.map +1 -0
- package/dist/publish-rendered.d.ts +37 -17
- package/dist/publish-rendered.d.ts.map +1 -1
- package/dist/publish-rendered.js +144 -71
- package/dist/publish-rendered.js.map +1 -1
- package/dist/publish-renderers.d.ts +132 -0
- package/dist/publish-renderers.d.ts.map +1 -0
- package/dist/publish-renderers.js +240 -0
- package/dist/publish-renderers.js.map +1 -0
- package/dist/publish-run.d.ts +223 -0
- package/dist/publish-run.d.ts.map +1 -0
- package/dist/publish-run.js +307 -0
- package/dist/publish-run.js.map +1 -0
- package/dist/publish.d.ts +13 -12
- package/dist/publish.d.ts.map +1 -1
- package/dist/publish.js +24 -57
- package/dist/publish.js.map +1 -1
- package/dist/render-for-analysis.d.ts +24 -0
- package/dist/render-for-analysis.d.ts.map +1 -0
- package/dist/render-for-analysis.js +146 -0
- package/dist/render-for-analysis.js.map +1 -0
- package/dist/resolver.d.ts +12 -2
- package/dist/resolver.d.ts.map +1 -1
- package/dist/resolver.js +101 -32
- package/dist/resolver.js.map +1 -1
- package/dist/runtime/archive-marker.d.ts +62 -0
- package/dist/runtime/archive-marker.d.ts.map +1 -0
- package/dist/runtime/archive-marker.js +88 -0
- package/dist/runtime/archive-marker.js.map +1 -0
- package/dist/runtime/capability-gap-warnings.d.ts +42 -0
- package/dist/runtime/capability-gap-warnings.d.ts.map +1 -0
- package/dist/runtime/capability-gap-warnings.js +28 -0
- package/dist/runtime/capability-gap-warnings.js.map +1 -0
- package/dist/runtime/redirects-emit.d.ts +93 -0
- package/dist/runtime/redirects-emit.d.ts.map +1 -0
- package/dist/runtime/redirects-emit.js +89 -0
- package/dist/runtime/redirects-emit.js.map +1 -0
- package/dist/runtime/runtime-capabilities.d.ts +79 -0
- package/dist/runtime/runtime-capabilities.d.ts.map +1 -0
- package/dist/runtime/runtime-capabilities.js +60 -0
- package/dist/runtime/runtime-capabilities.js.map +1 -0
- package/dist/save-etag.d.ts +69 -0
- package/dist/save-etag.d.ts.map +1 -0
- package/dist/save-etag.js +118 -0
- package/dist/save-etag.js.map +1 -0
- package/dist/schema/dimensions.d.ts +78 -0
- package/dist/schema/dimensions.d.ts.map +1 -0
- package/dist/schema/dimensions.js +97 -0
- package/dist/schema/dimensions.js.map +1 -0
- package/dist/schema/helpers.d.ts +108 -0
- package/dist/schema/helpers.d.ts.map +1 -0
- package/dist/schema/helpers.js +133 -0
- package/dist/schema/helpers.js.map +1 -0
- package/dist/schema/index.d.ts +27 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +25 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/types.d.ts +390 -0
- package/dist/schema/types.d.ts.map +1 -0
- package/dist/schema/types.js +25 -0
- package/dist/schema/types.js.map +1 -0
- package/dist/selector-chain.d.ts +63 -0
- package/dist/selector-chain.d.ts.map +1 -0
- package/dist/selector-chain.js +58 -0
- package/dist/selector-chain.js.map +1 -0
- package/dist/sidecars.d.ts +19 -18
- package/dist/sidecars.d.ts.map +1 -1
- package/dist/sidecars.js +70 -62
- package/dist/sidecars.js.map +1 -1
- package/dist/site-loader.d.ts +42 -4
- package/dist/site-loader.d.ts.map +1 -1
- package/dist/site-loader.js +27 -8
- package/dist/site-loader.js.map +1 -1
- package/dist/targets.d.ts +21 -12
- package/dist/targets.d.ts.map +1 -1
- package/dist/targets.js +27 -117
- package/dist/targets.js.map +1 -1
- package/dist/testing/admin-cache-contract.d.ts +52 -0
- package/dist/testing/admin-cache-contract.d.ts.map +1 -0
- package/dist/testing/admin-cache-contract.js +203 -0
- package/dist/testing/admin-cache-contract.js.map +1 -0
- package/dist/testing/index.d.ts +11 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +11 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/themes.d.ts +69 -0
- package/dist/themes.d.ts.map +1 -0
- package/dist/themes.js +85 -0
- package/dist/themes.js.map +1 -0
- package/dist/transforms/adapter.d.ts +115 -0
- package/dist/transforms/adapter.d.ts.map +1 -0
- package/dist/transforms/adapter.js +2 -0
- package/dist/transforms/adapter.js.map +1 -0
- package/dist/transforms/cloudflare.d.ts +17 -0
- package/dist/transforms/cloudflare.d.ts.map +1 -0
- package/dist/transforms/cloudflare.js +110 -0
- package/dist/transforms/cloudflare.js.map +1 -0
- package/dist/transforms/factories.d.ts +16 -0
- package/dist/transforms/factories.d.ts.map +1 -0
- package/dist/transforms/factories.js +18 -0
- package/dist/transforms/factories.js.map +1 -0
- package/dist/transforms/index.d.ts +17 -0
- package/dist/transforms/index.d.ts.map +1 -0
- package/dist/transforms/index.js +6 -0
- package/dist/transforms/index.js.map +1 -0
- package/dist/transforms/sharp.d.ts +17 -0
- package/dist/transforms/sharp.d.ts.map +1 -0
- package/dist/transforms/sharp.js +57 -0
- package/dist/transforms/sharp.js.map +1 -0
- package/dist/types.d.ts +485 -34
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +20 -1
- package/dist/types.js.map +1 -1
- package/dist/validation/alt-required-walker.d.ts +27 -0
- package/dist/validation/alt-required-walker.d.ts.map +1 -0
- package/dist/validation/alt-required-walker.js +108 -0
- package/dist/validation/alt-required-walker.js.map +1 -0
- package/dist/validation/default-registry.d.ts +12 -0
- package/dist/validation/default-registry.d.ts.map +1 -0
- package/dist/validation/default-registry.js +55 -0
- package/dist/validation/default-registry.js.map +1 -0
- package/dist/validation/publish-audit.d.ts +44 -0
- package/dist/validation/publish-audit.d.ts.map +1 -0
- package/dist/validation/publish-audit.js +64 -0
- package/dist/validation/publish-audit.js.map +1 -0
- package/dist/validation/registry.d.ts +23 -0
- package/dist/validation/registry.d.ts.map +1 -0
- package/dist/validation/registry.js +15 -0
- package/dist/validation/registry.js.map +1 -0
- package/dist/validation/save-delta.d.ts +46 -0
- package/dist/validation/save-delta.d.ts.map +1 -0
- package/dist/validation/save-delta.js +57 -0
- package/dist/validation/save-delta.js.map +1 -0
- package/dist/validation/scanner.d.ts +91 -0
- package/dist/validation/scanner.d.ts.map +1 -0
- package/dist/validation/scanner.js +327 -0
- package/dist/validation/scanner.js.map +1 -0
- package/dist/validation/template-impact.d.ts +52 -0
- package/dist/validation/template-impact.d.ts.map +1 -0
- package/dist/validation/template-impact.js +53 -0
- package/dist/validation/template-impact.js.map +1 -0
- package/dist/validation/types.d.ts +123 -0
- package/dist/validation/types.d.ts.map +1 -0
- package/dist/validation/types.js +7 -0
- package/dist/validation/types.js.map +1 -0
- package/dist/validation/validators/accessibility.d.ts +3 -0
- package/dist/validation/validators/accessibility.d.ts.map +1 -0
- package/dist/validation/validators/accessibility.js +106 -0
- package/dist/validation/validators/accessibility.js.map +1 -0
- package/dist/validation/validators/aliasof-points-to-archived.d.ts +40 -0
- package/dist/validation/validators/aliasof-points-to-archived.d.ts.map +1 -0
- package/dist/validation/validators/aliasof-points-to-archived.js +34 -0
- package/dist/validation/validators/aliasof-points-to-archived.js.map +1 -0
- package/dist/validation/validators/alt-required.d.ts +3 -0
- package/dist/validation/validators/alt-required.d.ts.map +1 -0
- package/dist/validation/validators/alt-required.js +118 -0
- package/dist/validation/validators/alt-required.js.map +1 -0
- package/dist/validation/validators/archive-not-supported-on-target.d.ts +3 -0
- package/dist/validation/validators/archive-not-supported-on-target.d.ts.map +1 -0
- package/dist/validation/validators/archive-not-supported-on-target.js +38 -0
- package/dist/validation/validators/archive-not-supported-on-target.js.map +1 -0
- package/dist/validation/validators/broken-links.d.ts +3 -0
- package/dist/validation/validators/broken-links.d.ts.map +1 -0
- package/dist/validation/validators/broken-links.js +190 -0
- package/dist/validation/validators/broken-links.js.map +1 -0
- package/dist/validation/validators/circular-alias.d.ts +36 -0
- package/dist/validation/validators/circular-alias.d.ts.map +1 -0
- package/dist/validation/validators/circular-alias.js +63 -0
- package/dist/validation/validators/circular-alias.js.map +1 -0
- package/dist/validation/validators/circular-fragment.d.ts +15 -0
- package/dist/validation/validators/circular-fragment.d.ts.map +1 -0
- package/dist/validation/validators/circular-fragment.js +97 -0
- package/dist/validation/validators/circular-fragment.js.map +1 -0
- package/dist/validation/validators/dangling-alias.d.ts +38 -0
- package/dist/validation/validators/dangling-alias.d.ts.map +1 -0
- package/dist/validation/validators/dangling-alias.js +31 -0
- package/dist/validation/validators/dangling-alias.js.map +1 -0
- package/dist/validation/validators/deploy-target-type-supported.d.ts +3 -0
- package/dist/validation/validators/deploy-target-type-supported.d.ts.map +1 -0
- package/dist/validation/validators/deploy-target-type-supported.js +32 -0
- package/dist/validation/validators/deploy-target-type-supported.js.map +1 -0
- package/dist/validation/validators/dynamic-route-conflict.d.ts +18 -0
- package/dist/validation/validators/dynamic-route-conflict.d.ts.map +1 -0
- package/dist/validation/validators/dynamic-route-conflict.js +80 -0
- package/dist/validation/validators/dynamic-route-conflict.js.map +1 -0
- package/dist/validation/validators/html-validity.d.ts +3 -0
- package/dist/validation/validators/html-validity.d.ts.map +1 -0
- package/dist/validation/validators/html-validity.js +89 -0
- package/dist/validation/validators/html-validity.js.map +1 -0
- package/dist/validation/validators/orphaned-locale-file.d.ts +21 -0
- package/dist/validation/validators/orphaned-locale-file.d.ts.map +1 -0
- package/dist/validation/validators/orphaned-locale-file.js +84 -0
- package/dist/validation/validators/orphaned-locale-file.js.map +1 -0
- package/dist/validation/validators/referenced-archived-without-alias.d.ts +3 -0
- package/dist/validation/validators/referenced-archived-without-alias.d.ts.map +1 -0
- package/dist/validation/validators/referenced-archived-without-alias.js +65 -0
- package/dist/validation/validators/referenced-archived-without-alias.js.map +1 -0
- package/dist/validation/validators/referenced-asset-exists.d.ts +13 -0
- package/dist/validation/validators/referenced-asset-exists.d.ts.map +1 -0
- package/dist/validation/validators/referenced-asset-exists.js +80 -0
- package/dist/validation/validators/referenced-asset-exists.js.map +1 -0
- package/dist/validation/validators/referenced-fragment-exists.d.ts +9 -0
- package/dist/validation/validators/referenced-fragment-exists.d.ts.map +1 -0
- package/dist/validation/validators/referenced-fragment-exists.js +52 -0
- package/dist/validation/validators/referenced-fragment-exists.js.map +1 -0
- package/dist/validation/validators/referenced-template-exists.d.ts +10 -0
- package/dist/validation/validators/referenced-template-exists.d.ts.map +1 -0
- package/dist/validation/validators/referenced-template-exists.js +74 -0
- package/dist/validation/validators/referenced-template-exists.js.map +1 -0
- package/dist/validation/validators/schema-conformance.d.ts +17 -0
- package/dist/validation/validators/schema-conformance.d.ts.map +1 -0
- package/dist/validation/validators/schema-conformance.js +94 -0
- package/dist/validation/validators/schema-conformance.js.map +1 -0
- package/dist/validation/validators/target-deploy-coverage.d.ts +3 -0
- package/dist/validation/validators/target-deploy-coverage.d.ts.map +1 -0
- package/dist/validation/validators/target-deploy-coverage.js +37 -0
- package/dist/validation/validators/target-deploy-coverage.js.map +1 -0
- package/dist/validation/validators/unused-fragment.d.ts +16 -0
- package/dist/validation/validators/unused-fragment.d.ts.map +1 -0
- package/dist/validation/validators/unused-fragment.js +86 -0
- package/dist/validation/validators/unused-fragment.js.map +1 -0
- package/package.json +69 -27
- package/admin-dist/assets/index-B6pVot0Y.css +0 -1
- package/admin-dist/assets/index-DniLwxJA.js +0 -609
- package/admin-dist/assets/rolldown-runtime-COnpUsM8.js +0 -1
- package/admin-dist/assets/vendor-rjsf-HKBAjOmQ.js +0 -32
- package/admin-dist/assets/vendor-tiptap-IyO99U4R.js +0 -142
- package/admin-dist/assets/vendor-vue-D3wBSmDf.js +0 -1
- package/dist/providers/r2.d.ts +0 -8
- package/dist/providers/r2.d.ts.map +0 -1
- package/dist/providers/r2.js +0 -86
- package/dist/providers/r2.js.map +0 -1
- package/dist/publish-locale.d.ts +0 -44
- package/dist/publish-locale.d.ts.map +0 -1
- package/dist/publish-locale.js +0 -103
- package/dist/publish-locale.js.map +0 -1
- package/dist/source-sidecars.d.ts +0 -32
- package/dist/source-sidecars.d.ts.map +0 -1
- package/dist/source-sidecars.js +0 -98
- package/dist/source-sidecars.js.map +0 -1
package/dist/cli/index.js
CHANGED
|
@@ -5,14 +5,16 @@ import { serve } from '@hono/node-server';
|
|
|
5
5
|
import { serveStatic } from '@hono/node-server/serve-static';
|
|
6
6
|
import { Hono } from 'hono';
|
|
7
7
|
import { streamSSE } from 'hono/streaming';
|
|
8
|
-
import yaml from 'js-yaml';
|
|
9
8
|
import { loadSite } from '../site-loader.js';
|
|
10
9
|
import { resolvePage } from '../resolver.js';
|
|
11
10
|
import { renderPage } from '../renderer.js';
|
|
12
11
|
import { createFilesystemProvider } from '../providers/filesystem.js';
|
|
13
12
|
import { invalidateTemplate, invalidateAllTemplates } from '../template-loader.js';
|
|
13
|
+
import { REQUIRED_NODE_FLOOR } from '../node-floor.js';
|
|
14
|
+
import { isTemplateEventRecent, TEMPLATE_RECENT_CHANGE_WINDOW_MS } from './dev-template-watcher.js';
|
|
14
15
|
import { getEnvironment, getType, isEditable } from '../types.js';
|
|
15
|
-
import { createAdminApp } from '../admin-api/index.js';
|
|
16
|
+
import { buildHooksRegistry, createAdminApp } from '../admin-api/index.js';
|
|
17
|
+
import { parseValidateFlags } from './validate-flags.js';
|
|
16
18
|
// ANSI color helpers — no dependency, suppressed when NO_COLOR or CI
|
|
17
19
|
const noColor = !!process.env.NO_COLOR || !process.stdout.isTTY;
|
|
18
20
|
const c = {
|
|
@@ -27,6 +29,39 @@ const c = {
|
|
|
27
29
|
};
|
|
28
30
|
const args = process.argv.slice(2);
|
|
29
31
|
const command = args[0];
|
|
32
|
+
/**
|
|
33
|
+
* Load a site manifest from `siteDir` via the TS config loader. Recognizes
|
|
34
|
+
* `site.config.ts`, `site.config.js`, and `site.config.mjs`.
|
|
35
|
+
*
|
|
36
|
+
* Returns null when no config file is found.
|
|
37
|
+
*/
|
|
38
|
+
async function loadSiteManifestForCli(siteDir) {
|
|
39
|
+
const tsConfigCandidates = ['site.config.ts', 'site.config.js', 'site.config.mjs'];
|
|
40
|
+
if (!tsConfigCandidates.some(f => existsSync(join(siteDir, f))))
|
|
41
|
+
return null;
|
|
42
|
+
const { loadSiteConfig, siteConfigToManifest } = await import('../config/loader.js');
|
|
43
|
+
const loaded = await loadSiteConfig(siteDir);
|
|
44
|
+
if (!loaded)
|
|
45
|
+
return null;
|
|
46
|
+
return siteConfigToManifest(loaded.config);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Read `admin.hooks` factory contributions from a site manifest.
|
|
50
|
+
*
|
|
51
|
+
* The manifest types `admin?` as a loose record (`Record<string, unknown>`)
|
|
52
|
+
* to keep `SiteManifest` stable across foundation additions; each foundation
|
|
53
|
+
* narrow-types its own block at the consumption site. For hooks the runtime
|
|
54
|
+
* shape is `ReadonlyArray<HookContribution>` (per design-hooks.md
|
|
55
|
+
* "Registration"); we accept it as `unknown` here and cast at the boundary.
|
|
56
|
+
*
|
|
57
|
+
* Returns undefined when the field is absent or empty.
|
|
58
|
+
*/
|
|
59
|
+
function readHookContributions(manifest) {
|
|
60
|
+
const hooks = manifest?.admin?.hooks;
|
|
61
|
+
if (!Array.isArray(hooks) || hooks.length === 0)
|
|
62
|
+
return undefined;
|
|
63
|
+
return hooks;
|
|
64
|
+
}
|
|
30
65
|
// Served to /admin/* requests during dev-server startup before Vite middleware
|
|
31
66
|
// is attached. Polls /admin/ping every 500ms and reloads when the admin becomes
|
|
32
67
|
// reachable. See #132 and cli/index.ts for why this is needed.
|
|
@@ -122,6 +157,84 @@ function detectProjectRoot(siteDir) {
|
|
|
122
157
|
// Fallback — use siteDir (templates/ may not exist yet)
|
|
123
158
|
return siteDir;
|
|
124
159
|
}
|
|
160
|
+
/**
|
|
161
|
+
* Resolve the siteDir for any CLI command by extracting the site
|
|
162
|
+
* positional from the parsed args per the command's documented
|
|
163
|
+
* positional layout. Pure fs walk; no config eval — safe to call
|
|
164
|
+
* before env-load.
|
|
165
|
+
*
|
|
166
|
+
* Single dispatch table so env-load happens exactly once at the top
|
|
167
|
+
* of `main()`, before any config-eval can read process.env.
|
|
168
|
+
*/
|
|
169
|
+
async function resolveSiteDirForCommand(cmd, parsed) {
|
|
170
|
+
// Commands whose site positional sits at a fixed index.
|
|
171
|
+
if (cmd === 'build')
|
|
172
|
+
return resolveSiteDir(parsed.positional[0]);
|
|
173
|
+
if (cmd === 'dev' || cmd === 'validate' || cmd === 'admin')
|
|
174
|
+
return resolveSiteDir(parsed.positional[0]);
|
|
175
|
+
// `rollback <rev> [target|site] [site]`: site is positional[1] when
|
|
176
|
+
// site-shaped, else positional[2].
|
|
177
|
+
if (cmd === 'rollback') {
|
|
178
|
+
const second = parsed.positional[1];
|
|
179
|
+
const third = parsed.positional[2];
|
|
180
|
+
const secondIsSite = second && (second.includes('/') || hasSiteConfig(resolve(second)));
|
|
181
|
+
return resolveSiteDir(secondIsSite ? second : third);
|
|
182
|
+
}
|
|
183
|
+
// `publish|serve|deploy|history|undo [target|site] [site]`: site is
|
|
184
|
+
// positional[0] when site-shaped, else positional[1].
|
|
185
|
+
if (cmd === 'publish' || cmd === 'serve' || cmd === 'deploy' || cmd === 'history' || cmd === 'undo') {
|
|
186
|
+
const first = parsed.positional[0];
|
|
187
|
+
const firstIsSite = first && (first.includes('/') || hasSiteConfig(resolve(first)));
|
|
188
|
+
return resolveSiteDir(firstIsSite ? first : parsed.positional[1]);
|
|
189
|
+
}
|
|
190
|
+
// `translate <item> --to <locale> [target]` — no explicit site arg.
|
|
191
|
+
if (cmd === 'translate')
|
|
192
|
+
return resolveSiteDir(undefined);
|
|
193
|
+
// `assets <subcmd> [args...] [target] [site]`: layout differs by subcmd.
|
|
194
|
+
if (cmd === 'assets') {
|
|
195
|
+
const subcmd = parsed.positional[0];
|
|
196
|
+
const sitePositional = subcmd === 'info' ? parsed.positional[3] : parsed.positional[2];
|
|
197
|
+
return resolveSiteDir(sitePositional);
|
|
198
|
+
}
|
|
199
|
+
// `archive <subcmd> [args...] [target] [site]`: site at trailingStart+1.
|
|
200
|
+
if (cmd === 'archive') {
|
|
201
|
+
const subcmd = parsed.positional[0];
|
|
202
|
+
const requiredArgs = subcmd === 'rename' ? 2 : subcmd === 'purge' || subcmd === 'restore' ? 1 : 0;
|
|
203
|
+
return resolveSiteDir(parsed.positional[1 + requiredArgs + 1]);
|
|
204
|
+
}
|
|
205
|
+
// Unknown command → auto-detect (main's switch will reject with a
|
|
206
|
+
// clear "Unknown command" error after env-load runs).
|
|
207
|
+
return resolveSiteDir(undefined);
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Load `.env` + `.env.local` from project root and site dir, in that
|
|
211
|
+
* order, so per-site secrets override project-wide defaults. Must run
|
|
212
|
+
* BEFORE the first config-eval (the site's storage / deploy / etc.
|
|
213
|
+
* factories read `process.env` synchronously at construction). Skipped
|
|
214
|
+
* in CI — CI runners inject env directly.
|
|
215
|
+
*
|
|
216
|
+
* Per Q1 of CLI env-loading discipline: site-local `.env` is honored
|
|
217
|
+
* (gazetta.studio has its own `.env` with R2/Cloudflare creds; this
|
|
218
|
+
* function ensures factories see them at config-eval time).
|
|
219
|
+
*/
|
|
220
|
+
function loadEnvFiles(siteDir) {
|
|
221
|
+
if (process.env.CI)
|
|
222
|
+
return;
|
|
223
|
+
const projectRoot = detectProjectRoot(siteDir);
|
|
224
|
+
const envDirs = projectRoot !== siteDir ? [projectRoot, siteDir] : [siteDir];
|
|
225
|
+
for (const dir of envDirs) {
|
|
226
|
+
for (const name of ['.env', '.env.local']) {
|
|
227
|
+
const envPath = join(dir, name);
|
|
228
|
+
if (!existsSync(envPath))
|
|
229
|
+
continue;
|
|
230
|
+
for (const line of readFileSync(envPath, 'utf-8').split('\n')) {
|
|
231
|
+
const m = line.match(/^\s*([A-Z_][A-Z0-9_]*)\s*=\s*(.*)$/);
|
|
232
|
+
if (m && !(m[1] in process.env))
|
|
233
|
+
process.env[m[1]] = m[2].replace(/^["']|["']$/g, '');
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
125
238
|
function printHelp() {
|
|
126
239
|
console.log(`
|
|
127
240
|
gazetta - Stateless CMS for composable websites
|
|
@@ -141,6 +254,20 @@ function printHelp() {
|
|
|
141
254
|
gazetta undo [target] [site] Restore the previous revision (soft undo)
|
|
142
255
|
gazetta rollback <rev> [target] [site]
|
|
143
256
|
Restore an arbitrary revision by id
|
|
257
|
+
gazetta assets list [target] [site]
|
|
258
|
+
List assets on a target
|
|
259
|
+
gazetta assets info <name> [target] [site]
|
|
260
|
+
Show full detail (variants, overrides, refs) for one asset
|
|
261
|
+
gazetta assets reindex [target] [site]
|
|
262
|
+
Rebuild the asset-refs sidecar index from manifests
|
|
263
|
+
gazetta archive list [--kind=page|fragment] [target] [site]
|
|
264
|
+
List archived items
|
|
265
|
+
gazetta archive purge <name> [--kind=...] [--force] [target] [site]
|
|
266
|
+
Permanently delete an archive
|
|
267
|
+
gazetta archive restore <name> [--kind=...] [target] [site]
|
|
268
|
+
Unarchive an item (back to live)
|
|
269
|
+
gazetta archive rename <oldname> <newname> [--kind=...] [--no-keep-alias] [target] [site]
|
|
270
|
+
Rename a live item; keeps the redirect by default
|
|
144
271
|
gazetta help Show this help message
|
|
145
272
|
|
|
146
273
|
Options:
|
|
@@ -154,7 +281,7 @@ function printHelp() {
|
|
|
154
281
|
Site is auto-detected from sites/ directory. If multiple sites exist,
|
|
155
282
|
you'll be prompted to choose (or pass it as an argument).
|
|
156
283
|
|
|
157
|
-
Target is auto-detected as the first target in site.
|
|
284
|
+
Target is auto-detected as the first target in site.config.ts. If multiple
|
|
158
285
|
targets exist, you'll be prompted to choose (or pass it as an argument).
|
|
159
286
|
|
|
160
287
|
Examples:
|
|
@@ -207,24 +334,30 @@ function parseArgs(input) {
|
|
|
207
334
|
* For commands like `publish` and `serve`, the first positional is the target
|
|
208
335
|
* and the second is the site.
|
|
209
336
|
*/
|
|
337
|
+
/** Returns true if the directory contains a Gazetta site config (`site.config.ts`/.js/.mjs). */
|
|
338
|
+
function hasSiteConfig(dir) {
|
|
339
|
+
return (existsSync(join(dir, 'site.config.ts')) ||
|
|
340
|
+
existsSync(join(dir, 'site.config.js')) ||
|
|
341
|
+
existsSync(join(dir, 'site.config.mjs')));
|
|
342
|
+
}
|
|
210
343
|
async function resolveSiteDir(positionalSite) {
|
|
211
344
|
// Explicit site dir provided
|
|
212
345
|
if (positionalSite) {
|
|
213
346
|
const dir = resolve(positionalSite);
|
|
214
|
-
if (
|
|
347
|
+
if (hasSiteConfig(dir))
|
|
215
348
|
return dir;
|
|
216
349
|
// Maybe it's a site name under sites/
|
|
217
350
|
const sitesSubdir = resolve('sites', positionalSite);
|
|
218
|
-
if (
|
|
351
|
+
if (hasSiteConfig(sitesSubdir))
|
|
219
352
|
return sitesSubdir;
|
|
220
353
|
// Maybe it's a project root with sites/
|
|
221
354
|
const mainSite = resolve(dir, 'sites/main');
|
|
222
|
-
if (
|
|
355
|
+
if (hasSiteConfig(mainSite))
|
|
223
356
|
return mainSite;
|
|
224
357
|
return dir; // let loadSite produce a clear error
|
|
225
358
|
}
|
|
226
359
|
// Auto-detect: check current dir first
|
|
227
|
-
if (
|
|
360
|
+
if (hasSiteConfig(resolve('.')))
|
|
228
361
|
return resolve('.');
|
|
229
362
|
// Check sites/ directory
|
|
230
363
|
const sitesDir = resolve('sites');
|
|
@@ -232,7 +365,7 @@ async function resolveSiteDir(positionalSite) {
|
|
|
232
365
|
const { readdirSync, statSync } = await import('node:fs');
|
|
233
366
|
const sites = readdirSync(sitesDir).filter(name => {
|
|
234
367
|
const dir = join(sitesDir, name);
|
|
235
|
-
return statSync(dir).isDirectory() &&
|
|
368
|
+
return statSync(dir).isDirectory() && hasSiteConfig(dir);
|
|
236
369
|
});
|
|
237
370
|
if (sites.length === 1)
|
|
238
371
|
return join(sitesDir, sites[0]);
|
|
@@ -264,11 +397,10 @@ async function resolveSiteDir(positionalSite) {
|
|
|
264
397
|
async function resolveTarget(positionalTarget, siteDir) {
|
|
265
398
|
if (positionalTarget)
|
|
266
399
|
return positionalTarget;
|
|
267
|
-
const
|
|
268
|
-
if (!
|
|
400
|
+
const manifest = await loadSiteManifestForCli(siteDir);
|
|
401
|
+
if (!manifest)
|
|
269
402
|
return undefined;
|
|
270
|
-
const
|
|
271
|
-
const targets = Object.keys(siteYaml.targets ?? {});
|
|
403
|
+
const targets = Object.keys(manifest.targets ?? {});
|
|
272
404
|
if (targets.length <= 1)
|
|
273
405
|
return targets[0]; // auto-select if 0 or 1
|
|
274
406
|
if (process.env.CI) {
|
|
@@ -287,13 +419,27 @@ async function resolveTarget(positionalTarget, siteDir) {
|
|
|
287
419
|
async function runInit(dir) {
|
|
288
420
|
const { writeFile, mkdir } = await import('node:fs/promises');
|
|
289
421
|
const target = resolve(dir);
|
|
290
|
-
if (existsSync(join(target, 'sites')) || existsSync(join(target, 'site.
|
|
422
|
+
if (existsSync(join(target, 'sites')) || existsSync(join(target, 'site.config.ts'))) {
|
|
291
423
|
console.error(`\n Error: project already exists in ${target}\n`);
|
|
292
424
|
process.exit(1);
|
|
293
425
|
}
|
|
294
426
|
const name = target.split('/').pop() ?? 'my-site';
|
|
295
427
|
const files = {
|
|
296
|
-
'sites/main/site.
|
|
428
|
+
'sites/main/site.config.ts': `import { defineSite, filesystemStorage } from 'gazetta'
|
|
429
|
+
|
|
430
|
+
export default defineSite({
|
|
431
|
+
name: '${name}',
|
|
432
|
+
version: '1.0.0',
|
|
433
|
+
systemPages: ['404'],
|
|
434
|
+
targets: {
|
|
435
|
+
local: {
|
|
436
|
+
storage: filesystemStorage(),
|
|
437
|
+
// environment: 'local' (default); editable: true (default for local);
|
|
438
|
+
// filesystemStorage() defaults path to ./targets/local
|
|
439
|
+
},
|
|
440
|
+
},
|
|
441
|
+
})
|
|
442
|
+
`,
|
|
297
443
|
'templates/page-layout/index.ts': `import { z } from 'zod'
|
|
298
444
|
import type { TemplateFunction } from 'gazetta'
|
|
299
445
|
|
|
@@ -413,7 +559,7 @@ export default template
|
|
|
413
559
|
name,
|
|
414
560
|
private: true,
|
|
415
561
|
type: 'module',
|
|
416
|
-
engines: { node:
|
|
562
|
+
engines: { node: REQUIRED_NODE_FLOOR },
|
|
417
563
|
scripts: { dev: 'gazetta dev' },
|
|
418
564
|
dependencies: { gazetta: '*', react: '^19.0.0', 'react-dom': '^19.0.0', zod: '^4.0.0' },
|
|
419
565
|
}, null, 2) + '\n',
|
|
@@ -431,7 +577,7 @@ export default template
|
|
|
431
577
|
` ${c.dim('pages/home/')} ${c.dim('home page with hero + intro')}\n` +
|
|
432
578
|
` ${c.dim('pages/404/')} ${c.dim('error page')}\n` +
|
|
433
579
|
` ${c.dim('fragments/header/')} ${c.dim('shared header nav')}\n` +
|
|
434
|
-
` ${c.dim('site.
|
|
580
|
+
` ${c.dim('site.config.ts')} ${c.dim('site config + local target')}\n` +
|
|
435
581
|
`${c.bold('package.json')}`, `Created ${c.green(name)}/`);
|
|
436
582
|
// Run npm install
|
|
437
583
|
const s = spinner();
|
|
@@ -450,7 +596,7 @@ export default template
|
|
|
450
596
|
async function runPublish(siteDir, targetName, opts = {}) {
|
|
451
597
|
const projectRoot = detectProjectRoot(siteDir);
|
|
452
598
|
const templatesDir = join(projectRoot, 'templates');
|
|
453
|
-
// Source comes from the default editable target in site.
|
|
599
|
+
// Source comes from the default editable target in site.config.ts.
|
|
454
600
|
const { buildSourceContext } = await import('./bootstrap.js');
|
|
455
601
|
let source, manifest, targetConfigs;
|
|
456
602
|
try {
|
|
@@ -465,7 +611,7 @@ async function runPublish(siteDir, targetName, opts = {}) {
|
|
|
465
611
|
const site = await loadSite({ contentRoot: source.contentRoot, templatesDir, manifest });
|
|
466
612
|
const siteYaml = manifest;
|
|
467
613
|
if (!siteYaml.targets || Object.keys(siteYaml.targets).length === 0) {
|
|
468
|
-
console.error(`\n Error: no targets configured in site.
|
|
614
|
+
console.error(`\n Error: no targets configured in site.config.ts`);
|
|
469
615
|
process.exit(1);
|
|
470
616
|
}
|
|
471
617
|
// Determine which targets to publish to
|
|
@@ -478,19 +624,23 @@ async function runPublish(siteDir, targetName, opts = {}) {
|
|
|
478
624
|
}
|
|
479
625
|
// Initialize targets
|
|
480
626
|
const { createTargetRegistry } = await import('../targets.js');
|
|
481
|
-
const targets = await createTargetRegistry(Object.fromEntries(targetNames.map(n => [n, siteYaml.targets[n]]))
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
//
|
|
627
|
+
const targets = await createTargetRegistry(Object.fromEntries(targetNames.map(n => [n, siteYaml.targets[n]])));
|
|
628
|
+
// Per Cut 6 cutover: per-target render loop now goes through publishRun
|
|
629
|
+
// (imported below at use site). publishRun owns: per-item dispatch +
|
|
630
|
+
// asset publish + dep indices + site manifest. CLI keeps: incremental
|
|
631
|
+
// skip via compareTargets, locale fan-out into ItemRefs, console
|
|
632
|
+
// output via onProgress, sitemap+robots+redirects+purge post-loop.
|
|
633
|
+
const { scanTemplates, reportTemplateErrors } = await import('../templates-scan.js');
|
|
634
|
+
// Validate templates once for this publish run. publishRun consumes
|
|
635
|
+
// templateInfos directly and computes hashes internally (per Cut 5
|
|
636
|
+
// expansion); CLI only needs to scan + bail on invalid templates
|
|
637
|
+
// before launching the run.
|
|
487
638
|
const templateInfos = await scanTemplates(templatesDir, projectRoot);
|
|
488
639
|
const invalid = reportTemplateErrors(templateInfos);
|
|
489
640
|
if (invalid > 0) {
|
|
490
641
|
console.error(`\n ${c.red('✗')} Refusing to publish with invalid templates.`);
|
|
491
642
|
process.exit(1);
|
|
492
643
|
}
|
|
493
|
-
const templateHashes = templateHashesFrom(templateInfos);
|
|
494
644
|
console.log();
|
|
495
645
|
console.log(` ${c.bgGreen(c.bold(' gazetta '))} ${c.green('publish')} ${c.dim(site.manifest.name)}`);
|
|
496
646
|
console.log();
|
|
@@ -498,6 +648,24 @@ async function runPublish(siteDir, targetName, opts = {}) {
|
|
|
498
648
|
console.log(` ${c.dim('┃')} Fragments ${c.dim([...site.fragments.keys()].join(', '))}`);
|
|
499
649
|
console.log(` ${c.dim('┃')} Targets ${targetNames.join(', ')}`);
|
|
500
650
|
console.log();
|
|
651
|
+
// Cutover (Cut 6 of publish-pipeline-extraction): per-target render
|
|
652
|
+
// loop now delegates to `publishRun` for the per-target × per-item
|
|
653
|
+
// dispatch + asset publish + dep indices + site manifest. CLI keeps
|
|
654
|
+
// ownership of:
|
|
655
|
+
// - target registry init + per-target loop (so target-init failures
|
|
656
|
+
// can short-circuit just that target)
|
|
657
|
+
// - incremental skip via compareTargets (publishRun is filter-blind;
|
|
658
|
+
// CLI pre-filters ItemRefs[] based on per-locale unchanged sets)
|
|
659
|
+
// - locale fan-out (CLI expands page name → ItemRef[] including all
|
|
660
|
+
// locale variants supported by the target)
|
|
661
|
+
// - console output (onProgress callback formats human-readable lines)
|
|
662
|
+
// - sitemap / robots.txt / _redirects / cache purge (post-publishRun
|
|
663
|
+
// side effects on each target — kept inline)
|
|
664
|
+
//
|
|
665
|
+
// publishRun owns: per-item mode dispatch, archive short-circuit,
|
|
666
|
+
// sidecar emit, asset publish, dep indices, site manifest emit.
|
|
667
|
+
const { publishRun } = await import('../publish-run.js');
|
|
668
|
+
const { createContentRoot: _createContentRoot } = await import('../content-root.js');
|
|
501
669
|
for (const name of targetNames) {
|
|
502
670
|
const targetStorage = targets.get(name);
|
|
503
671
|
if (!targetStorage) {
|
|
@@ -507,7 +675,6 @@ async function runPublish(siteDir, targetName, opts = {}) {
|
|
|
507
675
|
const targetConfig = siteYaml.targets[name];
|
|
508
676
|
const { getType } = await import('../types.js');
|
|
509
677
|
const targetType = targetConfig ? getType(targetConfig) : 'static';
|
|
510
|
-
const isStatic = targetType === 'static';
|
|
511
678
|
console.log(` ${c.bold(name)} ${c.dim(`(${targetType})`)}`);
|
|
512
679
|
let totalFiles = 0;
|
|
513
680
|
let totalRemoved = 0;
|
|
@@ -529,96 +696,102 @@ async function runPublish(siteDir, targetName, opts = {}) {
|
|
|
529
696
|
unchanged.add(item);
|
|
530
697
|
}
|
|
531
698
|
let skipped = 0;
|
|
532
|
-
|
|
533
|
-
//
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
699
|
+
// Build the per-target ItemRef list. CLI does the locale fan-out
|
|
700
|
+
// explicitly here (vs publishRun, which treats the input list
|
|
701
|
+
// verbatim). Each (page|fragment, locale) cell becomes one ItemRef
|
|
702
|
+
// unless the unchanged set covers it.
|
|
703
|
+
const targetLocales = targetConfig?.locales;
|
|
704
|
+
const itemRefs = [];
|
|
705
|
+
const skippedNames = new Set(); // for console output (item entirely skipped)
|
|
706
|
+
// Pages — default + per-locale variants, filtered by target.locales when set.
|
|
707
|
+
for (const [pageName] of site.pages) {
|
|
708
|
+
const pageLocales = site.pageLocales.get(pageName);
|
|
709
|
+
const localesForPage = [undefined];
|
|
710
|
+
if (pageLocales) {
|
|
711
|
+
for (const loc of pageLocales.locales.keys()) {
|
|
712
|
+
if (targetLocales && !targetLocales.includes(loc))
|
|
713
|
+
continue;
|
|
714
|
+
localesForPage.push(loc);
|
|
715
|
+
}
|
|
548
716
|
}
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
717
|
+
let added = 0;
|
|
718
|
+
for (const loc of localesForPage) {
|
|
719
|
+
const key = loc ? `pages/${pageName}:${loc}` : `pages/${pageName}`;
|
|
720
|
+
if (unchanged.has(key))
|
|
552
721
|
continue;
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
722
|
+
itemRefs.push({ kind: 'page', name: pageName, locale: loc });
|
|
723
|
+
added++;
|
|
724
|
+
}
|
|
725
|
+
if (added === 0 && localesForPage.length > 0) {
|
|
726
|
+
skippedNames.add(`pages/${pageName}`);
|
|
727
|
+
skipped++;
|
|
558
728
|
}
|
|
559
729
|
}
|
|
560
|
-
|
|
561
|
-
|
|
730
|
+
// Fragments — only emitted as separate items for non-static targets
|
|
731
|
+
// (static bakes them into pages). For static, the publishRun spine
|
|
732
|
+
// still needs them in the site for page rendering (already loaded).
|
|
733
|
+
if (targetType !== 'static') {
|
|
562
734
|
for (const [fragName] of site.fragments) {
|
|
563
|
-
// Build per-locale unchanged set: null = default, 'fr' = French
|
|
564
|
-
const fragUnchanged = new Set();
|
|
565
|
-
if (unchanged.has(`fragments/${fragName}`))
|
|
566
|
-
fragUnchanged.add(null);
|
|
567
735
|
const fragLocales = site.fragmentLocales.get(fragName);
|
|
736
|
+
const localesForFrag = [undefined];
|
|
568
737
|
if (fragLocales) {
|
|
569
738
|
for (const loc of fragLocales.locales.keys()) {
|
|
570
|
-
if (
|
|
571
|
-
|
|
739
|
+
if (targetLocales && !targetLocales.includes(loc))
|
|
740
|
+
continue;
|
|
741
|
+
localesForFrag.push(loc);
|
|
572
742
|
}
|
|
573
743
|
}
|
|
574
|
-
|
|
575
|
-
const
|
|
576
|
-
|
|
744
|
+
let added = 0;
|
|
745
|
+
for (const loc of localesForFrag) {
|
|
746
|
+
const key = loc ? `fragments/${fragName}:${loc}` : `fragments/${fragName}`;
|
|
747
|
+
if (unchanged.has(key))
|
|
748
|
+
continue;
|
|
749
|
+
itemRefs.push({ kind: 'fragment', name: fragName, locale: loc });
|
|
750
|
+
added++;
|
|
751
|
+
}
|
|
752
|
+
if (added === 0 && localesForFrag.length > 0) {
|
|
753
|
+
skippedNames.add(`fragments/${fragName}`);
|
|
577
754
|
skipped++;
|
|
578
|
-
continue;
|
|
579
755
|
}
|
|
580
|
-
const { files, removed } = await publishFragmentAllLocales(fragName, sourceRoot, targetStorage, site, { templateHashes }, { templatesDir, targetLocales: targetConfig?.locales, unchangedLocales: fragUnchanged });
|
|
581
|
-
totalFiles += files;
|
|
582
|
-
totalRemoved += removed;
|
|
583
|
-
const skippedCount = fragUnchanged.size > 0 ? ` (${fragUnchanged.size} locale${fragUnchanged.size > 1 ? 's' : ''} skipped)` : '';
|
|
584
|
-
console.log(` ${c.green('✓')} @${fragName}${skippedCount}`);
|
|
585
756
|
}
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
757
|
+
}
|
|
758
|
+
// Delegate the per-item × per-target render loop + asset publish +
|
|
759
|
+
// dep indices + site manifest to publishRun. Single-target call;
|
|
760
|
+
// CLI loops targets itself so per-target init failures (storage
|
|
761
|
+
// missing) short-circuit just that target.
|
|
762
|
+
const runResult = await publishRun({
|
|
763
|
+
items: itemRefs,
|
|
764
|
+
targets: [name],
|
|
765
|
+
site,
|
|
766
|
+
sourceRoot: source.contentRoot,
|
|
767
|
+
siteManifest: manifest,
|
|
768
|
+
targetStorages: new Map([[name, targetStorage]]),
|
|
769
|
+
templateInfos,
|
|
770
|
+
onProgress: ev => {
|
|
771
|
+
if (ev.kind === 'item-done') {
|
|
772
|
+
if (ev.result.ok) {
|
|
773
|
+
const label = ev.result.kind === 'fragment' ? `@${ev.result.name}` : ev.result.name;
|
|
774
|
+
const localeMark = ev.result.locale ? c.dim(` (${ev.result.locale})`) : '';
|
|
775
|
+
console.log(` ${c.green('✓')} ${label}${localeMark}`);
|
|
776
|
+
}
|
|
777
|
+
else {
|
|
778
|
+
const label = ev.result.kind === 'fragment' ? `@${ev.result.name}` : ev.result.name;
|
|
779
|
+
console.error(` ${c.red('✗')} ${label}: ${ev.result.code}`);
|
|
596
780
|
}
|
|
597
781
|
}
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
targetLocales: targetConfig?.locales,
|
|
608
|
-
unchangedLocales: pageUnchanged,
|
|
609
|
-
});
|
|
610
|
-
totalFiles += files;
|
|
611
|
-
totalRemoved += removed;
|
|
612
|
-
const skippedCount = pageUnchanged.size > 0 ? ` (${pageUnchanged.size} locale${pageUnchanged.size > 1 ? 's' : ''} skipped)` : '';
|
|
613
|
-
console.log(` ${c.green('✓')} ${pageName}${skippedCount}`);
|
|
782
|
+
},
|
|
783
|
+
});
|
|
784
|
+
// Aggregate counts from publishRun's per-target result.
|
|
785
|
+
const tr = runResult.targets.find(t => t.name === name);
|
|
786
|
+
if (tr) {
|
|
787
|
+
totalFiles += tr.filesWritten;
|
|
788
|
+
totalRemoved += tr.filesRemoved;
|
|
789
|
+
if (tr.failed) {
|
|
790
|
+
console.error(` ${c.red('✗')} target failed: ${tr.failureReason ?? 'all items failed'}`);
|
|
614
791
|
}
|
|
615
792
|
}
|
|
616
793
|
if (skipped > 0)
|
|
617
794
|
console.log(` ${c.dim(`· ${skipped} unchanged (skipped)`)}`);
|
|
618
|
-
// Site manifest + fragment index
|
|
619
|
-
await publishSiteManifest(sourceRoot, targetStorage, site);
|
|
620
|
-
await publishFragmentIndex(sourceRoot, targetStorage, site);
|
|
621
|
-
totalFiles += 2;
|
|
622
795
|
// Sitemap + robots.txt — generated from target sidecars
|
|
623
796
|
const siteUrl = targetConfig?.siteUrl;
|
|
624
797
|
if (siteUrl) {
|
|
@@ -634,8 +807,6 @@ async function runPublish(siteDir, targetName, opts = {}) {
|
|
|
634
807
|
if (!targetPageSidecars.has(pageName)) {
|
|
635
808
|
targetPageSidecars.set(pageName, {
|
|
636
809
|
hash: '',
|
|
637
|
-
uses: [],
|
|
638
|
-
template: page.template,
|
|
639
810
|
pub: { lastPublished: now, noindex: !!page.metadata?.robots?.includes('noindex') },
|
|
640
811
|
});
|
|
641
812
|
}
|
|
@@ -646,8 +817,6 @@ async function runPublish(siteDir, targetName, opts = {}) {
|
|
|
646
817
|
if (!targetPageSidecars.has(key)) {
|
|
647
818
|
targetPageSidecars.set(key, {
|
|
648
819
|
hash: '',
|
|
649
|
-
uses: [],
|
|
650
|
-
template: localePage.template,
|
|
651
820
|
pub: { lastPublished: now, noindex: !!localePage.metadata?.robots?.includes('noindex') },
|
|
652
821
|
});
|
|
653
822
|
}
|
|
@@ -732,6 +901,36 @@ async function runPublish(siteDir, targetName, opts = {}) {
|
|
|
732
901
|
console.log(` ${c.dim('· robots.txt')}`);
|
|
733
902
|
}
|
|
734
903
|
}
|
|
904
|
+
// Host-format redirects file (e.g. _redirects for Cloudflare/Netlify).
|
|
905
|
+
// Per design-soft-delete.md Q10: plain-static targets without a worker
|
|
906
|
+
// can't read the per-page HTML marker; this file is the host-glue
|
|
907
|
+
// that makes archived-page redirects work for them. Independent of
|
|
908
|
+
// siteUrl — the format determines whether to emit at all.
|
|
909
|
+
const redirectsFormat = targetConfig?.redirects?.format;
|
|
910
|
+
if (redirectsFormat && redirectsFormat !== 'none') {
|
|
911
|
+
const { emitRedirects } = await import('../runtime/redirects-emit.js');
|
|
912
|
+
const { allPageEntries, deriveRoute } = await import('../site-loader.js');
|
|
913
|
+
const archives = [];
|
|
914
|
+
for (const entry of allPageEntries(site)) {
|
|
915
|
+
if (entry.page.archived !== true)
|
|
916
|
+
continue;
|
|
917
|
+
// Locale variants share the parent's archive state in v1; the
|
|
918
|
+
// default-locale row is the canonical entry. Per-locale archive
|
|
919
|
+
// is reserved for a future cut (per `design-soft-delete.md`
|
|
920
|
+
// future directions).
|
|
921
|
+
if (entry.locale)
|
|
922
|
+
continue;
|
|
923
|
+
const from = deriveRoute(entry.name);
|
|
924
|
+
const to = entry.page.aliasOf ? deriveRoute(entry.page.aliasOf) : undefined;
|
|
925
|
+
archives.push(to !== undefined ? { from, to } : { from });
|
|
926
|
+
}
|
|
927
|
+
const result = emitRedirects(redirectsFormat, archives);
|
|
928
|
+
if (result && result.body !== '') {
|
|
929
|
+
await targetStorage.writeFile(result.filename, result.body);
|
|
930
|
+
totalFiles++;
|
|
931
|
+
console.log(` ${c.dim(`· ${result.filename}`)}`);
|
|
932
|
+
}
|
|
933
|
+
}
|
|
735
934
|
const removedMsg = totalRemoved > 0 ? c.dim(` (${totalRemoved} old files cleaned)`) : '';
|
|
736
935
|
console.log(`\n ${c.green('✓')} ${c.bold(name)}: ${totalFiles} files published${removedMsg}\n`);
|
|
737
936
|
}
|
|
@@ -937,7 +1136,9 @@ async function runAdmin(siteDir, port) {
|
|
|
937
1136
|
app.get('/__reload', ctx => ctx.body(null, 204));
|
|
938
1137
|
const { buildSourceContext } = await import('./bootstrap.js');
|
|
939
1138
|
const { source, targetConfigs } = await buildSourceContext({ projectSiteDir: siteDir });
|
|
940
|
-
await
|
|
1139
|
+
const manifest = await loadSiteManifestForCli(siteDir);
|
|
1140
|
+
const hookContributions = readHookContributions(manifest);
|
|
1141
|
+
await setupProductionMode(app, source, siteDir, builtAdminDir, templatesDir, adminDir, targetConfigs, hookContributions, manifest);
|
|
941
1142
|
// SPA fallback for non-API admin routes
|
|
942
1143
|
app.get('*', ctx => {
|
|
943
1144
|
const indexPath = join(builtAdminDir, 'index.html');
|
|
@@ -945,10 +1146,10 @@ async function runAdmin(siteDir, port) {
|
|
|
945
1146
|
return ctx.html(readFileSync(indexPath, 'utf-8'));
|
|
946
1147
|
return ctx.notFound();
|
|
947
1148
|
});
|
|
948
|
-
const
|
|
1149
|
+
const siteManifest = (await loadSiteManifestForCli(siteDir)) ?? { name: 'gazetta' };
|
|
949
1150
|
const server = serve({ fetch: app.fetch, port }, () => {
|
|
950
1151
|
console.log();
|
|
951
|
-
console.log(` ${c.bgGreen(c.bold(' gazetta '))} ${c.green('admin')} ${c.dim(
|
|
1152
|
+
console.log(` ${c.bgGreen(c.bold(' gazetta '))} ${c.green('admin')} ${c.dim(siteManifest.name)}`);
|
|
952
1153
|
console.log();
|
|
953
1154
|
console.log(` ${c.dim('┃')} Admin ${c.cyan(`http://localhost:${port}/admin`)}`);
|
|
954
1155
|
console.log();
|
|
@@ -961,25 +1162,24 @@ async function runAdmin(siteDir, port) {
|
|
|
961
1162
|
}
|
|
962
1163
|
}
|
|
963
1164
|
async function runServe(siteDir, port, targetName) {
|
|
964
|
-
const
|
|
965
|
-
if (!
|
|
966
|
-
console.error(`\n Error: ${
|
|
1165
|
+
const siteYaml = await loadSiteManifestForCli(siteDir);
|
|
1166
|
+
if (!siteYaml) {
|
|
1167
|
+
console.error(`\n Error: no site config found in ${siteDir} (looked for site.config.ts)\n`);
|
|
967
1168
|
process.exit(1);
|
|
968
1169
|
}
|
|
969
|
-
const siteYaml = yaml.load(readFileSync(siteYamlPath, 'utf-8'));
|
|
970
1170
|
if (!siteYaml.targets || Object.keys(siteYaml.targets).length === 0) {
|
|
971
|
-
console.error('\n Error: no targets configured in site
|
|
1171
|
+
console.error('\n Error: no targets configured in site config\n');
|
|
972
1172
|
process.exit(1);
|
|
973
1173
|
}
|
|
974
1174
|
const name = targetName ?? Object.keys(siteYaml.targets)[0];
|
|
975
1175
|
const config = siteYaml.targets[name];
|
|
976
1176
|
if (!config) {
|
|
977
|
-
console.error(`\n Error: target "${name}" not found in site
|
|
1177
|
+
console.error(`\n Error: target "${name}" not found in site config\n`);
|
|
978
1178
|
process.exit(1);
|
|
979
1179
|
}
|
|
980
|
-
|
|
981
|
-
//
|
|
982
|
-
const storage =
|
|
1180
|
+
// Storage is already a constructed provider (Path X — operator-facing
|
|
1181
|
+
// factory ran at config-eval).
|
|
1182
|
+
const storage = config.storage;
|
|
983
1183
|
const { getType } = await import('../types.js');
|
|
984
1184
|
const { createServer } = await import('../serve.js');
|
|
985
1185
|
const app = createServer({ storage, type: getType(config) });
|
|
@@ -998,16 +1198,13 @@ async function runServe(siteDir, port, targetName) {
|
|
|
998
1198
|
}
|
|
999
1199
|
}
|
|
1000
1200
|
async function runDeploy(siteDir, targetName) {
|
|
1001
|
-
const
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
if (!existsSync(siteYamlPath)) {
|
|
1005
|
-
console.error(`\n Error: No site.yaml found at ${siteDir}\n`);
|
|
1201
|
+
const siteYaml = await loadSiteManifestForCli(siteDir);
|
|
1202
|
+
if (!siteYaml) {
|
|
1203
|
+
console.error(`\n Error: no site config found at ${siteDir} (looked for site.config.ts)\n`);
|
|
1006
1204
|
process.exit(1);
|
|
1007
1205
|
}
|
|
1008
|
-
const siteYaml = yaml.load(readFileSync(siteYamlPath, 'utf-8'));
|
|
1009
1206
|
if (!siteYaml.targets) {
|
|
1010
|
-
console.error(`\n Error: No targets configured in site
|
|
1207
|
+
console.error(`\n Error: No targets configured in site config\n`);
|
|
1011
1208
|
process.exit(1);
|
|
1012
1209
|
}
|
|
1013
1210
|
if (!targetName) {
|
|
@@ -1019,130 +1216,193 @@ async function runDeploy(siteDir, targetName) {
|
|
|
1019
1216
|
console.error(`\n Error: Unknown target "${targetName}". Available: ${Object.keys(siteYaml.targets).join(', ')}\n`);
|
|
1020
1217
|
process.exit(1);
|
|
1021
1218
|
}
|
|
1022
|
-
if (!target.
|
|
1023
|
-
console.error(`\n Error: Target "${targetName}" has no
|
|
1219
|
+
if (!target.deploy) {
|
|
1220
|
+
console.error(`\n Error: Target "${targetName}" has no \`deploy:\` adapter configured. Add to site.config.ts:\n\n ` +
|
|
1221
|
+
`import { cloudflareWorkersDeploy } from 'gazetta'\n ` +
|
|
1222
|
+
`deploy: cloudflareWorkersDeploy({\n ` +
|
|
1223
|
+
` apiToken: process.env.CLOUDFLARE_API_TOKEN!,\n ` +
|
|
1224
|
+
` accountId: process.env.CLOUDFLARE_ACCOUNT_ID!,\n ` +
|
|
1225
|
+
` name: '${targetName}',\n ` +
|
|
1226
|
+
` bucket: '${targetName}',\n })\n\n` +
|
|
1227
|
+
`For container hosts (Fly.io, Cloud Run, Railway, Render), use platform-native\n` +
|
|
1228
|
+
`deploy tooling; see docs/container-deployment.md.\n`);
|
|
1024
1229
|
process.exit(1);
|
|
1025
1230
|
}
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
await mkdir(tmpDir, { recursive: true });
|
|
1036
|
-
// Generate wrangler.toml
|
|
1037
|
-
let wranglerToml = `name = "${workerName}"\nmain = "index.ts"\ncompatibility_date = "2024-12-01"\nworkers_dev = true\n\n[[r2_buckets]]\nbinding = "SITE_BUCKET"\nbucket_name = "${bucketName}"\n`;
|
|
1038
|
-
// Add custom domain route if siteUrl is configured
|
|
1039
|
-
if (target.siteUrl) {
|
|
1040
|
-
const url = new URL(target.siteUrl);
|
|
1041
|
-
const hostname = url.hostname;
|
|
1042
|
-
wranglerToml += `\n[[routes]]\npattern = "${hostname}/*"\nzone_name = "${hostname}"\n`;
|
|
1043
|
-
}
|
|
1044
|
-
await writeFile(join(tmpDir, 'wrangler.toml'), wranglerToml);
|
|
1045
|
-
// Generate worker entry point
|
|
1046
|
-
const workerCode = `import { createWorker } from 'gazetta/workers/cloudflare-r2'\nexport default createWorker()\n`;
|
|
1047
|
-
await writeFile(join(tmpDir, 'index.ts'), workerCode);
|
|
1048
|
-
// Generate package.json for wrangler
|
|
1049
|
-
const pkgJson = JSON.stringify({
|
|
1050
|
-
type: 'module',
|
|
1051
|
-
dependencies: { gazetta: '*', hono: '*' },
|
|
1052
|
-
});
|
|
1053
|
-
await writeFile(join(tmpDir, 'package.json'), pkgJson);
|
|
1054
|
-
// Install deps and deploy
|
|
1055
|
-
console.log(` Deploying worker "${workerName}" to Cloudflare...`);
|
|
1231
|
+
const adapter = target.deploy;
|
|
1232
|
+
console.log(` ${c.cyan(`Deploying via ${adapter.name}...`)}`);
|
|
1233
|
+
// Build a no-op logger; v1 deploy doesn't require structured logging yet.
|
|
1234
|
+
const logger = {
|
|
1235
|
+
debug: (_o, _m) => { },
|
|
1236
|
+
info: (_o, _m) => { },
|
|
1237
|
+
warn: (o, m) => console.warn(` ${typeof o === 'string' ? o : (m ?? '')}`),
|
|
1238
|
+
error: (o, m) => console.error(` ${typeof o === 'string' ? o : (m ?? '')}`),
|
|
1239
|
+
};
|
|
1056
1240
|
try {
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1241
|
+
const result = await adapter.execute({
|
|
1242
|
+
target,
|
|
1243
|
+
targetName,
|
|
1244
|
+
// outputDir not used by worker-deploy adapters (worker reads R2 at request).
|
|
1245
|
+
// Adapters that need bytes (static-host) read storage themselves.
|
|
1246
|
+
outputDir: join(siteDir, 'dist', targetName),
|
|
1247
|
+
storage: target.storage,
|
|
1248
|
+
env: process.env,
|
|
1249
|
+
logger,
|
|
1250
|
+
signal: new AbortController().signal,
|
|
1251
|
+
});
|
|
1252
|
+
if (result.url)
|
|
1253
|
+
console.log(` ${c.green('✓')} Deployed: ${result.url}`);
|
|
1254
|
+
else
|
|
1255
|
+
console.log(` ${c.green('✓')} Deployed.`);
|
|
1061
1256
|
if (target.siteUrl)
|
|
1062
1257
|
console.log(` Site: ${target.siteUrl}`);
|
|
1063
1258
|
}
|
|
1064
1259
|
catch (err) {
|
|
1065
|
-
const
|
|
1066
|
-
|
|
1260
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1261
|
+
const adapterTag = err.adapter ?? adapter.name;
|
|
1262
|
+
console.error(`\n ${c.red(`Deploy failed (${adapterTag}):`)} ${message}\n`);
|
|
1067
1263
|
process.exit(1);
|
|
1068
1264
|
}
|
|
1069
|
-
|
|
1070
|
-
await rm(tmpDir, { recursive: true, force: true });
|
|
1071
|
-
}
|
|
1072
|
-
console.log(`\n ${c.green('✓')} Worker deployed. Now publish content:\n ${c.cyan(`gazetta publish ${targetName}`)}\n`);
|
|
1265
|
+
console.log(`\n ${c.green('✓')} Deploy complete. Publish content with:\n ${c.cyan(`gazetta publish ${targetName}`)}\n`);
|
|
1073
1266
|
}
|
|
1074
|
-
|
|
1267
|
+
const QUALITY_VALIDATORS = new Set(['accessibility', 'html-validity', 'broken-links']);
|
|
1268
|
+
async function runValidate(siteDir, rawArgs = []) {
|
|
1075
1269
|
const projectRoot = detectProjectRoot(siteDir);
|
|
1076
1270
|
const templatesDir = join(projectRoot, 'templates');
|
|
1271
|
+
const opts = parseValidateFlags(rawArgs);
|
|
1077
1272
|
console.log();
|
|
1078
1273
|
console.log(` ${c.bgGreen(c.bold(' gazetta '))} ${c.green('validate')} ${c.dim(siteDir)}`);
|
|
1079
1274
|
console.log();
|
|
1080
|
-
// 1.
|
|
1275
|
+
// 1. Load site
|
|
1276
|
+
const configLabel = existsSync(join(siteDir, 'site.config.ts'))
|
|
1277
|
+
? 'site.config.ts'
|
|
1278
|
+
: existsSync(join(siteDir, 'site.config.js'))
|
|
1279
|
+
? 'site.config.js'
|
|
1280
|
+
: 'site.config.mjs';
|
|
1281
|
+
const { buildSourceContext } = await import('./bootstrap.js');
|
|
1081
1282
|
let site;
|
|
1283
|
+
let source;
|
|
1082
1284
|
try {
|
|
1083
|
-
const
|
|
1084
|
-
|
|
1085
|
-
site = await loadSite({ contentRoot: source.contentRoot, templatesDir, manifest });
|
|
1086
|
-
console.log(` ${c.green('✓')}
|
|
1285
|
+
const built = await buildSourceContext({ projectSiteDir: siteDir });
|
|
1286
|
+
source = built.source;
|
|
1287
|
+
site = await loadSite({ contentRoot: source.contentRoot, templatesDir, manifest: built.manifest });
|
|
1288
|
+
console.log(` ${c.green('✓')} ${configLabel} ${c.dim(`— ${site.manifest.name}`)}`);
|
|
1087
1289
|
}
|
|
1088
1290
|
catch (err) {
|
|
1089
|
-
console.error(` ${c.red('✗')}
|
|
1291
|
+
console.error(` ${c.red('✗')} ${configLabel} ${c.dim(`— ${err.message}`)}`);
|
|
1090
1292
|
process.exit(1);
|
|
1091
1293
|
}
|
|
1092
|
-
|
|
1093
|
-
//
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1294
|
+
// 2. Build the registry. Skip quality validators (a11y, html-validity)
|
|
1295
|
+
// unless `--include-quality` — they trigger rendering and add seconds
|
|
1296
|
+
// per page; default keeps the CLI snappy for CI ref-existence gating.
|
|
1297
|
+
const { defaultValidatorRegistry } = await import('../validation/default-registry.js');
|
|
1298
|
+
const { createValidatorRegistry } = await import('../validation/registry.js');
|
|
1299
|
+
const fullRegistry = defaultValidatorRegistry();
|
|
1300
|
+
const filtered = opts.includeQuality
|
|
1301
|
+
? fullRegistry
|
|
1302
|
+
: createValidatorRegistry(fullRegistry.all().filter(v => !QUALITY_VALIDATORS.has(v.name)));
|
|
1303
|
+
// 3. Run via the scanner — same orchestrator as the admin background scan,
|
|
1304
|
+
// so the CLI exercises identical code paths.
|
|
1305
|
+
const { createValidationScanner } = await import('../validation/scanner.js');
|
|
1306
|
+
const { createMemoryCache } = await import('../cache/memory.js');
|
|
1307
|
+
const scanner = createValidationScanner({
|
|
1308
|
+
storage: source.storage,
|
|
1309
|
+
contentRoot: source.contentRoot,
|
|
1310
|
+
registry: filtered,
|
|
1311
|
+
cache: createMemoryCache(),
|
|
1312
|
+
siteOptions: { templatesDir, manifest: site.manifest },
|
|
1313
|
+
loadSiteImpl: async () => site,
|
|
1314
|
+
});
|
|
1315
|
+
await scanner.scanAll();
|
|
1316
|
+
const allIssues = scanner.allIssues();
|
|
1317
|
+
// 4. Per-item summary. Pages first, then fragments — matches the existing
|
|
1318
|
+
// output ordering for unsurprising diff vs. the prior implementation.
|
|
1319
|
+
let errorCount = 0;
|
|
1320
|
+
let warnCount = 0;
|
|
1321
|
+
let infoCount = 0;
|
|
1322
|
+
const issuesByPath = new Map();
|
|
1323
|
+
for (const issue of allIssues) {
|
|
1324
|
+
const list = issuesByPath.get(issue.itemPath) ?? [];
|
|
1325
|
+
list.push(issue);
|
|
1326
|
+
issuesByPath.set(issue.itemPath, list);
|
|
1327
|
+
if (issue.severity === 'error')
|
|
1328
|
+
errorCount++;
|
|
1329
|
+
else if (issue.severity === 'warn')
|
|
1330
|
+
warnCount++;
|
|
1331
|
+
else
|
|
1332
|
+
infoCount++;
|
|
1333
|
+
}
|
|
1334
|
+
function summaryGlyph(issues) {
|
|
1335
|
+
if (issues.some(i => i.severity === 'error'))
|
|
1336
|
+
return { glyph: '✗', color: c.red };
|
|
1337
|
+
if (issues.some(i => i.severity === 'warn'))
|
|
1338
|
+
return { glyph: '⚠', color: c.yellow };
|
|
1339
|
+
if (issues.length > 0)
|
|
1340
|
+
return { glyph: 'ⓘ', color: c.cyan };
|
|
1341
|
+
return { glyph: '✓', color: c.green };
|
|
1342
|
+
}
|
|
1343
|
+
function shouldShow(severity) {
|
|
1344
|
+
if (opts.severity === 'all')
|
|
1345
|
+
return true;
|
|
1346
|
+
if (opts.severity === 'warn')
|
|
1347
|
+
return severity !== 'info';
|
|
1348
|
+
return severity === 'error';
|
|
1106
1349
|
}
|
|
1107
|
-
// 3. Validate all pages
|
|
1108
1350
|
for (const [pageName, page] of site.pages) {
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1351
|
+
const path = `${page.dir}/page.json`;
|
|
1352
|
+
const issues = issuesByPath.get(path) ?? [];
|
|
1353
|
+
const visible = issues.filter(i => shouldShow(i.severity));
|
|
1354
|
+
const { glyph, color } = summaryGlyph(visible);
|
|
1355
|
+
const componentCount = page.components?.length ?? 0;
|
|
1356
|
+
console.log(` ${color(glyph)} ${pageName} ${c.dim(`(${componentCount} components)`)}`);
|
|
1357
|
+
if (opts.verbose) {
|
|
1358
|
+
for (const issue of visible) {
|
|
1359
|
+
console.log(` ${severityIcon(issue.severity)} ${issue.message}`);
|
|
1360
|
+
}
|
|
1114
1361
|
}
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1362
|
+
}
|
|
1363
|
+
for (const [fragName, frag] of site.fragments) {
|
|
1364
|
+
const path = `${frag.dir}/fragment.json`;
|
|
1365
|
+
const issues = issuesByPath.get(path) ?? [];
|
|
1366
|
+
const visible = issues.filter(i => shouldShow(i.severity));
|
|
1367
|
+
const { glyph, color } = summaryGlyph(visible);
|
|
1368
|
+
const childCount = frag.components?.length ?? 0;
|
|
1369
|
+
console.log(` ${color(glyph)} @${fragName} ${c.dim(`(${childCount} components)`)}`);
|
|
1370
|
+
if (opts.verbose) {
|
|
1371
|
+
for (const issue of visible) {
|
|
1372
|
+
console.log(` ${severityIcon(issue.severity)} ${issue.message}`);
|
|
1373
|
+
}
|
|
1118
1374
|
}
|
|
1119
1375
|
}
|
|
1120
|
-
//
|
|
1376
|
+
// 5. Project-structure checks (orphaned editors, missing custom fields).
|
|
1377
|
+
// These are project-layout concerns rather than per-item content rules,
|
|
1378
|
+
// so they don't fit the Validator interface — kept inline here.
|
|
1379
|
+
const adminDir = join(projectRoot, 'admin');
|
|
1121
1380
|
const projectStorage = createFilesystemProvider();
|
|
1122
1381
|
let templateNames = [];
|
|
1123
1382
|
try {
|
|
1124
1383
|
const entries = await projectStorage.readDir(templatesDir);
|
|
1125
|
-
templateNames = entries.filter(e => e.isDirectory).map(
|
|
1126
|
-
console.log(` ${c.green('✓')} ${c.dim(`${templateNames.length} templates`)}`);
|
|
1384
|
+
templateNames = entries.filter(e => e.isDirectory).map(e => e.name);
|
|
1127
1385
|
}
|
|
1128
1386
|
catch {
|
|
1129
|
-
|
|
1387
|
+
/* templates dir missing — site already errored above */
|
|
1130
1388
|
}
|
|
1131
|
-
//
|
|
1132
|
-
|
|
1389
|
+
// 5a. Orphaned editors: editor file exists but no matching template.
|
|
1390
|
+
// Always shown regardless of --severity since these are structural
|
|
1391
|
+
// issues operators need to know about even at the strictest filter.
|
|
1133
1392
|
const editorsDir = join(adminDir, 'editors');
|
|
1134
1393
|
if (existsSync(editorsDir)) {
|
|
1135
|
-
const
|
|
1136
|
-
|
|
1137
|
-
.filter(f => f.endsWith('.ts') || f.endsWith('.tsx'));
|
|
1394
|
+
const fs = await import('node:fs');
|
|
1395
|
+
const editorFiles = fs.readdirSync(editorsDir).filter(f => f.endsWith('.ts') || f.endsWith('.tsx'));
|
|
1138
1396
|
for (const file of editorFiles) {
|
|
1139
1397
|
const editorName = file.replace(/\.(ts|tsx)$/, '');
|
|
1140
1398
|
if (!templateNames.includes(editorName)) {
|
|
1141
1399
|
console.log(` ${c.yellow('⚠')} orphaned editor: ${c.dim(`admin/editors/${file}`)} ${c.dim('— no matching template')}`);
|
|
1400
|
+
warnCount++;
|
|
1142
1401
|
}
|
|
1143
1402
|
}
|
|
1144
1403
|
}
|
|
1145
|
-
//
|
|
1404
|
+
// 5b. Missing custom fields: schema references field: 'name' but no
|
|
1405
|
+
// admin/fields/name.{ts,tsx}. Hard error — render fails without it.
|
|
1146
1406
|
const fieldsDir = join(adminDir, 'fields');
|
|
1147
1407
|
const fieldFiles = existsSync(fieldsDir)
|
|
1148
1408
|
? (await import('node:fs'))
|
|
@@ -1150,96 +1410,60 @@ async function runValidate(siteDir) {
|
|
|
1150
1410
|
.filter(f => f.endsWith('.ts') || f.endsWith('.tsx'))
|
|
1151
1411
|
.map(f => f.replace(/\.(ts|tsx)$/, ''))
|
|
1152
1412
|
: [];
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
const
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
}
|
|
1170
|
-
catch {
|
|
1171
|
-
/* template load errors already caught above */
|
|
1172
|
-
}
|
|
1173
|
-
}
|
|
1174
|
-
// 7. Locale validation
|
|
1175
|
-
const { defaultLocaleFor } = await import('../locale.js');
|
|
1176
|
-
const defLoc = defaultLocaleFor(site.manifest);
|
|
1177
|
-
const hasI18n = !!site.manifest.locales?.supported?.length;
|
|
1178
|
-
// 7a. Warn about orphaned locale files when i18n is disabled
|
|
1179
|
-
if (!hasI18n && (site.pageLocales.size > 0 || site.fragmentLocales.size > 0)) {
|
|
1180
|
-
const orphanCount = site.pageLocales.size + site.fragmentLocales.size;
|
|
1181
|
-
console.log(` ${c.yellow('⚠')} ${orphanCount} locale file${orphanCount > 1 ? 's' : ''} found but i18n is disabled ${c.dim('— add locales.supported to site.yaml or remove *.locale.json files')}`);
|
|
1182
|
-
}
|
|
1183
|
-
// 7b. Warn about ambiguous page.en.json when en is default
|
|
1184
|
-
if (hasI18n) {
|
|
1185
|
-
for (const [name, entry] of site.pageLocales) {
|
|
1186
|
-
if (entry.locales.has(defLoc)) {
|
|
1187
|
-
console.log(` ${c.yellow('⚠')} page.${defLoc}.json in ${name} is ambiguous ${c.dim(`— "${defLoc}" is the default locale, use page.json instead`)}`);
|
|
1188
|
-
}
|
|
1189
|
-
}
|
|
1190
|
-
for (const [name, entry] of site.fragmentLocales) {
|
|
1191
|
-
if (entry.locales.has(defLoc)) {
|
|
1192
|
-
console.log(` ${c.yellow('⚠')} fragment.${defLoc}.json in ${name} is ambiguous ${c.dim(`— "${defLoc}" is the default locale, use fragment.json instead`)}`);
|
|
1193
|
-
}
|
|
1194
|
-
}
|
|
1195
|
-
}
|
|
1196
|
-
// 7c. Validate locale variant template/fragment refs
|
|
1197
|
-
if (hasI18n) {
|
|
1198
|
-
for (const [pageName, entry] of site.pageLocales) {
|
|
1199
|
-
for (const [locale] of entry.locales) {
|
|
1200
|
-
try {
|
|
1201
|
-
await resolvePage(pageName, site, locale);
|
|
1202
|
-
}
|
|
1203
|
-
catch (err) {
|
|
1204
|
-
console.error(` ${c.red('✗')} ${pageName} (${locale}) ${c.dim(`— ${err.message}`)}`);
|
|
1205
|
-
errors++;
|
|
1206
|
-
}
|
|
1207
|
-
}
|
|
1208
|
-
}
|
|
1209
|
-
}
|
|
1210
|
-
// 8. Cross-domain hreflang bidirectional check
|
|
1211
|
-
// For per-domain targets (each with siteUrl + single locale), verify that
|
|
1212
|
-
// all targets serving the same page cross-link to each other.
|
|
1213
|
-
if (hasI18n && site.manifest.targets) {
|
|
1214
|
-
const targetsWithSiteUrl = Object.entries(site.manifest.targets).filter(([, cfg]) => cfg.siteUrl && cfg.locales?.length === 1);
|
|
1215
|
-
if (targetsWithSiteUrl.length > 1) {
|
|
1216
|
-
const localeToUrl = new Map();
|
|
1217
|
-
for (const [, cfg] of targetsWithSiteUrl) {
|
|
1218
|
-
localeToUrl.set(cfg.locales[0], cfg.siteUrl);
|
|
1219
|
-
}
|
|
1220
|
-
const missingPairs = [];
|
|
1221
|
-
for (const [locA, urlA] of localeToUrl) {
|
|
1222
|
-
for (const [locB, urlB] of localeToUrl) {
|
|
1223
|
-
if (locA === locB)
|
|
1224
|
-
continue;
|
|
1225
|
-
// Each target's sitemap should cross-link to the other
|
|
1226
|
-
// We can't check the actual sitemaps here (would need network),
|
|
1227
|
-
// but we can verify the config is consistent
|
|
1413
|
+
if (templateNames.length > 0) {
|
|
1414
|
+
const { loadTemplate } = await import('../template-loader.js');
|
|
1415
|
+
const zod = await import('zod');
|
|
1416
|
+
for (const tplName of templateNames) {
|
|
1417
|
+
try {
|
|
1418
|
+
const loaded = await loadTemplate(projectStorage, templatesDir, tplName);
|
|
1419
|
+
const jsonSchema = zod.z.toJSONSchema(loaded.schema);
|
|
1420
|
+
const props = jsonSchema.properties;
|
|
1421
|
+
if (!props)
|
|
1422
|
+
continue;
|
|
1423
|
+
for (const [propName, prop] of Object.entries(props)) {
|
|
1424
|
+
const fieldRef = prop.field;
|
|
1425
|
+
if (fieldRef && !fieldFiles.includes(fieldRef)) {
|
|
1426
|
+
console.error(` ${c.red('✗')} template ${tplName}.${propName} references field "${fieldRef}" ${c.dim('— not found in admin/fields/')}`);
|
|
1427
|
+
errorCount++;
|
|
1428
|
+
}
|
|
1228
1429
|
}
|
|
1229
1430
|
}
|
|
1230
|
-
|
|
1231
|
-
|
|
1431
|
+
catch {
|
|
1432
|
+
/* template load errors surface via referenced-template-exists */
|
|
1232
1433
|
}
|
|
1233
1434
|
}
|
|
1234
1435
|
}
|
|
1436
|
+
// 6. Footer + exit code.
|
|
1235
1437
|
console.log();
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1438
|
+
const totalShown = opts.severity === 'all'
|
|
1439
|
+
? errorCount + warnCount + infoCount
|
|
1440
|
+
: opts.severity === 'warn'
|
|
1441
|
+
? errorCount + warnCount
|
|
1442
|
+
: errorCount;
|
|
1443
|
+
if (totalShown === 0) {
|
|
1444
|
+
console.log(` ${c.green('All good.')}\n`);
|
|
1445
|
+
return;
|
|
1242
1446
|
}
|
|
1447
|
+
const parts = [];
|
|
1448
|
+
if (errorCount > 0)
|
|
1449
|
+
parts.push(`${errorCount} error${errorCount > 1 ? 's' : ''}`);
|
|
1450
|
+
if (warnCount > 0 && opts.severity !== 'error')
|
|
1451
|
+
parts.push(`${warnCount} warning${warnCount > 1 ? 's' : ''}`);
|
|
1452
|
+
if (infoCount > 0 && opts.severity === 'all')
|
|
1453
|
+
parts.push(`${infoCount} info`);
|
|
1454
|
+
const summary = parts.join(', ');
|
|
1455
|
+
console.log(` ${summary}.\n`);
|
|
1456
|
+
// Exit non-zero if errors OR (warns AND warn-as-error is on).
|
|
1457
|
+
const fail = errorCount > 0 || (opts.warnAsError && warnCount > 0);
|
|
1458
|
+
if (fail)
|
|
1459
|
+
process.exit(1);
|
|
1460
|
+
}
|
|
1461
|
+
function severityIcon(severity) {
|
|
1462
|
+
if (severity === 'error')
|
|
1463
|
+
return c.red('✗');
|
|
1464
|
+
if (severity === 'warn')
|
|
1465
|
+
return c.yellow('⚠');
|
|
1466
|
+
return c.cyan('ⓘ');
|
|
1243
1467
|
}
|
|
1244
1468
|
function renderErrorOverlay(err) {
|
|
1245
1469
|
const message = err.message.replace(/</g, '<').replace(/>/g, '>');
|
|
@@ -1290,7 +1514,7 @@ async function runDev(siteDir, port) {
|
|
|
1290
1514
|
const projectRoot = detectProjectRoot(siteDir);
|
|
1291
1515
|
const templatesDir = join(projectRoot, 'templates');
|
|
1292
1516
|
const adminDir = join(projectRoot, 'admin');
|
|
1293
|
-
// Build the source context from the default editable target in site.
|
|
1517
|
+
// Build the source context from the default editable target in site.config.ts.
|
|
1294
1518
|
// Cloud targets aren't init'd — admin API handles them lazily.
|
|
1295
1519
|
const { buildSourceContext } = await import('./bootstrap.js');
|
|
1296
1520
|
const { source, manifest, targetConfigs } = await buildSourceContext({ projectSiteDir: siteDir });
|
|
@@ -1337,8 +1561,15 @@ async function runDev(siteDir, port) {
|
|
|
1337
1561
|
}
|
|
1338
1562
|
return next();
|
|
1339
1563
|
});
|
|
1564
|
+
// ---- Asset serve route ----
|
|
1565
|
+
// Serves /assets/* from the active source target's storage. Matches the
|
|
1566
|
+
// URL pattern emitted by the asset resolver, so templates rendering
|
|
1567
|
+
// <img src="/assets/hero-a3b2c1d4.jpg"> load from here in dev.
|
|
1568
|
+
const { assetServeRoutes } = await import('../assets/serve-route.js');
|
|
1569
|
+
app.route('/', assetServeRoutes(async () => source.storage));
|
|
1340
1570
|
// ---- Site page routes (default + locale variants) ----
|
|
1341
1571
|
const { allPageEntries } = await import('../site-loader.js');
|
|
1572
|
+
const { defaultLocaleFor: _devDefaultLocaleFor } = await import('../locale.js');
|
|
1342
1573
|
for (const { name: pageName, page, locale: pageLocale } of allPageEntries(site)) {
|
|
1343
1574
|
app.get(page.route, async (c) => {
|
|
1344
1575
|
try {
|
|
@@ -1353,7 +1584,7 @@ async function runDev(siteDir, port) {
|
|
|
1353
1584
|
route: freshPage?.route ?? page.route,
|
|
1354
1585
|
seo: {
|
|
1355
1586
|
siteName: freshSite.manifest.name,
|
|
1356
|
-
locale: pageLocale ?? freshSite.manifest
|
|
1587
|
+
locale: pageLocale ?? _devDefaultLocaleFor(freshSite.manifest),
|
|
1357
1588
|
defaultOgImage: freshSite.manifest.defaultOgImage,
|
|
1358
1589
|
},
|
|
1359
1590
|
});
|
|
@@ -1408,14 +1639,17 @@ async function runDev(siteDir, port) {
|
|
|
1408
1639
|
const isDevMode = cmsWebDir !== null;
|
|
1409
1640
|
// Admin Hono instance — captured so the template file watcher can
|
|
1410
1641
|
// invalidate its memoized template-scan cache on .ts/.tsx changes.
|
|
1642
|
+
// `rescanForTemplate` is optional: only the dev-mode setup decorates
|
|
1643
|
+
// it (production has no file watcher). Watcher uses optional-chaining.
|
|
1411
1644
|
let cmsApp = null;
|
|
1645
|
+
const hookContributions = readHookContributions(manifest);
|
|
1412
1646
|
if (isDevMode) {
|
|
1413
1647
|
// Dev mode: mount CMS API inline (same process = shared template cache)
|
|
1414
|
-
cmsApp = await setupCmsApi(app, source, siteDir, templatesDir, adminDir, targetConfigs);
|
|
1648
|
+
cmsApp = await setupCmsApi(app, source, siteDir, templatesDir, adminDir, targetConfigs, hookContributions, manifest);
|
|
1415
1649
|
}
|
|
1416
1650
|
else if (cmsStaticDir) {
|
|
1417
1651
|
// Production mode: inline CMS API + static files
|
|
1418
|
-
cmsApp = await setupProductionMode(app, source, siteDir, cmsStaticDir, templatesDir, adminDir, targetConfigs);
|
|
1652
|
+
cmsApp = await setupProductionMode(app, source, siteDir, cmsStaticDir, templatesDir, adminDir, targetConfigs, hookContributions, manifest);
|
|
1419
1653
|
}
|
|
1420
1654
|
// ---- 404 ----
|
|
1421
1655
|
app.notFound(c => {
|
|
@@ -1464,8 +1698,10 @@ async function runDev(siteDir, port) {
|
|
|
1464
1698
|
const env = getEnvironment(cfg);
|
|
1465
1699
|
const type = getType(cfg);
|
|
1466
1700
|
const ed = isEditable(cfg) ? 'editable ' : 'read-only';
|
|
1467
|
-
|
|
1468
|
-
|
|
1701
|
+
// Path X — the storage provider is opaque (operator constructed it via
|
|
1702
|
+
// factory at config-eval). Display target name + axes; the provider
|
|
1703
|
+
// identity is not introspectable from the StorageProvider interface.
|
|
1704
|
+
console.log(` ${c.dim('┃')} ${c.dim('•')} ${name.padEnd(14)} ${c.dim(env.padEnd(11))} ${c.dim(ed)} ${c.dim(type.padEnd(8))}`);
|
|
1469
1705
|
}
|
|
1470
1706
|
}
|
|
1471
1707
|
if (isDevMode && cmsWebDir) {
|
|
@@ -1551,7 +1787,15 @@ async function runDev(siteDir, port) {
|
|
|
1551
1787
|
// written into the source, so the scanner misses it. Include it
|
|
1552
1788
|
// explicitly to avoid a mid-session page reload when a TSX editor
|
|
1553
1789
|
// is first loaded (#122).
|
|
1554
|
-
|
|
1790
|
+
//
|
|
1791
|
+
// @formkit/drag-and-drop/vue is the ComponentTree's reorder lib
|
|
1792
|
+
// (#105). The package's main entry is CJS; the Vue subpath is
|
|
1793
|
+
// ESM. Vite's auto-scanner doesn't always pre-bundle subpath
|
|
1794
|
+
// ESM imports with mixed CJS-main packages on first load,
|
|
1795
|
+
// which triggers a runtime "Re-optimizing dependencies"
|
|
1796
|
+
// page reload mid-test on CI cold start. Explicit include
|
|
1797
|
+
// pins the subpath in the boot-time pre-bundle.
|
|
1798
|
+
include: ['react/jsx-dev-runtime', 'react/jsx-runtime', '@formkit/drag-and-drop/vue'],
|
|
1555
1799
|
},
|
|
1556
1800
|
server: {
|
|
1557
1801
|
middlewareMode: true,
|
|
@@ -1617,7 +1861,7 @@ async function runDev(siteDir, port) {
|
|
|
1617
1861
|
console.log();
|
|
1618
1862
|
});
|
|
1619
1863
|
// ---- File watching ----
|
|
1620
|
-
// Watch site dir for content changes (JSON manifests + site.
|
|
1864
|
+
// Watch site dir for content changes (JSON manifests + site.config.ts).
|
|
1621
1865
|
// Swallow FSWatcher 'error' events — Node's recursive watcher throws ENOENT
|
|
1622
1866
|
// when a watched subdir disappears (rm -rf during publish, git checkout).
|
|
1623
1867
|
// Letting it crash would take the whole dev server down; logging a warning
|
|
@@ -1636,15 +1880,12 @@ async function runDev(siteDir, port) {
|
|
|
1636
1880
|
if (filename.endsWith('.json') || filename.endsWith('.yaml')) {
|
|
1637
1881
|
console.log(` Manifest changed: ${filename}`);
|
|
1638
1882
|
invalidateAllTemplates();
|
|
1639
|
-
//
|
|
1640
|
-
//
|
|
1641
|
-
//
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
cmsApp?.writeSourceSidecar('page', pageMatch[1]).catch(() => { });
|
|
1646
|
-
else if (fragMatch)
|
|
1647
|
-
cmsApp?.writeSourceSidecar('fragment', fragMatch[1]).catch(() => { });
|
|
1883
|
+
// Out-of-band manifest changes (git pull, manual edit, e2e
|
|
1884
|
+
// test wipes) bypass the admin-api save handler that would
|
|
1885
|
+
// otherwise invalidate the AdminCache. Drop content-summary
|
|
1886
|
+
// entries so the next /api/pages or /api/fragments rebuilds
|
|
1887
|
+
// from disk. Best-effort; the void promise is fire-and-forget.
|
|
1888
|
+
void cmsApp?.invalidateContentCache();
|
|
1648
1889
|
notifyReload();
|
|
1649
1890
|
}
|
|
1650
1891
|
});
|
|
@@ -1657,13 +1898,34 @@ async function runDev(siteDir, port) {
|
|
|
1657
1898
|
if (filename.endsWith('.ts') || filename.endsWith('.tsx')) {
|
|
1658
1899
|
const parts = filename.split('/');
|
|
1659
1900
|
if (parts.length >= 1) {
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
//
|
|
1663
|
-
//
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
notifyReload()
|
|
1901
|
+
const templateName = parts[0];
|
|
1902
|
+
const fullPath = join(templatesDir, filename);
|
|
1903
|
+
// Suppress spurious events for files whose mtime predates the
|
|
1904
|
+
// watcher's recent window — these are kernel-delayed metadata
|
|
1905
|
+
// flushes for files written before the watcher began observing,
|
|
1906
|
+
// typical of the worker-scoped `cp -r` setup in the e2e fixture
|
|
1907
|
+
// (#286). Without the gate, the resulting notifyReload() closes
|
|
1908
|
+
// any open admin UI mid-interaction.
|
|
1909
|
+
void (async () => {
|
|
1910
|
+
if (!(await isTemplateEventRecent(fullPath, TEMPLATE_RECENT_CHANGE_WINDOW_MS))) {
|
|
1911
|
+
return;
|
|
1912
|
+
}
|
|
1913
|
+
console.log(` Template changed: ${templateName}`);
|
|
1914
|
+
invalidateTemplate(templateName);
|
|
1915
|
+
// Drop the admin-api's cached scan so next compare/publish
|
|
1916
|
+
// rehashes. Cheap (the scan is what's slow, not invalidation).
|
|
1917
|
+
cmsApp?.invalidateTemplatesCache();
|
|
1918
|
+
// Cut 6 — fire a validation rescan with the template-edit
|
|
1919
|
+
// cause so the scanner re-runs schema-conformance against
|
|
1920
|
+
// every page+fragment using this template. The ScanEvent
|
|
1921
|
+
// emits on the /__validation SSE channel; the admin's
|
|
1922
|
+
// TemplateChangedBanner consumes it to show the
|
|
1923
|
+
// template-developer's "did I break anything?" surface.
|
|
1924
|
+
// Fire-and-forget — the scan runs in the background and
|
|
1925
|
+
// the SSE event is the signal that it finished.
|
|
1926
|
+
void cmsApp?.rescanForTemplate?.(templateName);
|
|
1927
|
+
notifyReload();
|
|
1928
|
+
})();
|
|
1667
1929
|
}
|
|
1668
1930
|
}
|
|
1669
1931
|
});
|
|
@@ -1692,16 +1954,98 @@ function mountUserThemeRoute(cmsApp, adminDir) {
|
|
|
1692
1954
|
return c.body(readFileSync(themePath, 'utf-8'));
|
|
1693
1955
|
});
|
|
1694
1956
|
}
|
|
1695
|
-
|
|
1696
|
-
|
|
1957
|
+
/**
|
|
1958
|
+
* Build the background validation scanner (validation Cut 2). The scanner
|
|
1959
|
+
* is constructed against the resolved source's storage + cache; the boot
|
|
1960
|
+
* path kicks off an initial full-site scan in the background so admin
|
|
1961
|
+
* responses don't block on it.
|
|
1962
|
+
*
|
|
1963
|
+
* Returns null when the manifest is unavailable (site lacks site.config.ts)
|
|
1964
|
+
* — the admin app degrades gracefully (route returns empty issues; SSE
|
|
1965
|
+
* channel idle).
|
|
1966
|
+
*/
|
|
1967
|
+
async function buildValidationScanner(opts) {
|
|
1968
|
+
if (!opts.manifest)
|
|
1969
|
+
return null;
|
|
1970
|
+
const { createValidationScanner } = await import('../validation/scanner.js');
|
|
1971
|
+
const { defaultValidatorRegistry } = await import('../validation/default-registry.js');
|
|
1972
|
+
const scanner = createValidationScanner({
|
|
1973
|
+
storage: opts.source.storage,
|
|
1974
|
+
contentRoot: opts.source.contentRoot,
|
|
1975
|
+
registry: defaultValidatorRegistry(),
|
|
1976
|
+
cache: opts.source.cache,
|
|
1977
|
+
siteOptions: { templatesDir: opts.templatesDir, manifest: opts.manifest },
|
|
1978
|
+
});
|
|
1979
|
+
// Boot warm: kick off the initial scan in the background. Errors are
|
|
1980
|
+
// logged but don't block boot — broken validators surface as info-issues
|
|
1981
|
+
// rather than failing the admin process.
|
|
1982
|
+
void scanner.scanAll().catch(err => {
|
|
1983
|
+
console.error('[validation] initial scan failed:', err);
|
|
1984
|
+
});
|
|
1985
|
+
return scanner;
|
|
1986
|
+
}
|
|
1987
|
+
async function setupCmsApi(app, source, siteDir, templatesDir, adminDir, targetConfigs, contributions, manifest) {
|
|
1988
|
+
// Build + seal the hook registry from `admin.hooks` factory
|
|
1989
|
+
// contributions before wiring the admin app. Hooks are an opt-in
|
|
1990
|
+
// extension surface; sites without `admin.hooks` get an empty
|
|
1991
|
+
// registry (no overhead).
|
|
1992
|
+
const hooks = await buildHooksRegistry({ contributions });
|
|
1993
|
+
const validationScanner = await buildValidationScanner({ source, templatesDir, manifest });
|
|
1994
|
+
// Mount SSE on the OUTER Hono app — matches `/__reload`'s placement so
|
|
1995
|
+
// the browser EventSource (which connects without an `/admin/` prefix)
|
|
1996
|
+
// bypasses Vite's middleware and reaches the route. Same in prod for
|
|
1997
|
+
// consistency: a save from one tab updates the badge in every other
|
|
1998
|
+
// tab without polling.
|
|
1999
|
+
const { mountValidationSse } = await import('../admin-api/routes/validation.js');
|
|
2000
|
+
mountValidationSse(app, validationScanner);
|
|
2001
|
+
const cmsApp = createAdminApp({
|
|
2002
|
+
source,
|
|
2003
|
+
siteDir,
|
|
2004
|
+
templatesDir,
|
|
2005
|
+
adminDir,
|
|
2006
|
+
targetConfigs,
|
|
2007
|
+
hooks,
|
|
2008
|
+
validationScanner,
|
|
2009
|
+
});
|
|
2010
|
+
// Decorate cmsApp with the template-rescan hook before returning. The
|
|
2011
|
+
// file watcher in startServer() invokes this on `.ts/.tsx` changes
|
|
2012
|
+
// under `templates/{name}/`. Failure is fail-open (logged + dropped)
|
|
2013
|
+
// — a scan failure shouldn't break dev-mode hot reload.
|
|
2014
|
+
const decoratedApp = cmsApp;
|
|
2015
|
+
decoratedApp.rescanForTemplate = async (name) => {
|
|
2016
|
+
if (!validationScanner)
|
|
2017
|
+
return;
|
|
2018
|
+
try {
|
|
2019
|
+
await validationScanner.rescan({ kind: 'template', name });
|
|
2020
|
+
}
|
|
2021
|
+
catch (err) {
|
|
2022
|
+
console.warn(` Validation scanner: template rescan failed for "${name}": ${err.message}`);
|
|
2023
|
+
}
|
|
2024
|
+
};
|
|
1697
2025
|
mountUserThemeRoute(cmsApp, adminDir);
|
|
1698
2026
|
app.route('/admin', cmsApp);
|
|
1699
|
-
return
|
|
2027
|
+
return decoratedApp;
|
|
1700
2028
|
}
|
|
1701
2029
|
// ---- Production mode: inline CMS API + static files from admin-dist/ ----
|
|
1702
|
-
async function setupProductionMode(app, source, siteDir, cmsStaticDir, templatesDir, adminDir, targetConfigs) {
|
|
2030
|
+
async function setupProductionMode(app, source, siteDir, cmsStaticDir, templatesDir, adminDir, targetConfigs, contributions, manifest) {
|
|
2031
|
+
// Same shape as dev mode — `gazetta serve` reads `admin.hooks`
|
|
2032
|
+
// factory contributions from the same site config.
|
|
2033
|
+
const hooks = await buildHooksRegistry({ contributions });
|
|
2034
|
+
const validationScanner = await buildValidationScanner({ source, templatesDir, manifest });
|
|
2035
|
+
// SSE channel at the outer app's root; see setupCmsApi for rationale.
|
|
2036
|
+
const { mountValidationSse } = await import('../admin-api/routes/validation.js');
|
|
2037
|
+
mountValidationSse(app, validationScanner);
|
|
1703
2038
|
// Mount CMS API inline at /admin (production mode — bundled editors/fields)
|
|
1704
|
-
const cmsApp = createAdminApp({
|
|
2039
|
+
const cmsApp = createAdminApp({
|
|
2040
|
+
source,
|
|
2041
|
+
siteDir,
|
|
2042
|
+
templatesDir,
|
|
2043
|
+
adminDir,
|
|
2044
|
+
production: true,
|
|
2045
|
+
targetConfigs,
|
|
2046
|
+
hooks,
|
|
2047
|
+
validationScanner,
|
|
2048
|
+
});
|
|
1705
2049
|
mountUserThemeRoute(cmsApp, adminDir);
|
|
1706
2050
|
app.route('/admin', cmsApp);
|
|
1707
2051
|
// Serve pre-built CMS static files (includes bundled editors/fields)
|
|
@@ -1766,79 +2110,83 @@ async function main() {
|
|
|
1766
2110
|
await runInit(parsed.positional[0] ?? '.');
|
|
1767
2111
|
return;
|
|
1768
2112
|
}
|
|
1769
|
-
|
|
1770
|
-
|
|
2113
|
+
// ── Resolve siteDir once (fs walk; no config eval) + load .env
|
|
2114
|
+
// ── BEFORE any config-eval. Storage / deploy / AI factories read
|
|
2115
|
+
// ── process.env synchronously at construction; resolveTarget()
|
|
2116
|
+
// ── triggers config-eval, so env must be in place first. Per-
|
|
2117
|
+
// ── command positional layouts determine which slot carries the
|
|
2118
|
+
// ── site path. Site-local `.env` is honored (e.g.,
|
|
2119
|
+
// ── sites/gazetta.studio/.env with R2 creds) per design-config.md.
|
|
2120
|
+
siteDir = await resolveSiteDirForCommand(command, parsed);
|
|
2121
|
+
loadEnvFiles(siteDir);
|
|
2122
|
+
if (command === 'build') {
|
|
1771
2123
|
await runBuild(siteDir);
|
|
1772
2124
|
return;
|
|
1773
2125
|
}
|
|
1774
2126
|
else if (command === 'rollback') {
|
|
1775
2127
|
// gazetta rollback <rev> [target] [site]
|
|
1776
|
-
const [rev, second
|
|
2128
|
+
const [rev, second] = parsed.positional;
|
|
1777
2129
|
if (!rev || !rev.startsWith('rev-')) {
|
|
1778
2130
|
console.error(`\n Error: rollback requires a revision id as the first argument (e.g. gazetta rollback rev-1776337441608 [target])\n`);
|
|
1779
2131
|
process.exit(1);
|
|
1780
2132
|
return;
|
|
1781
2133
|
}
|
|
1782
2134
|
rollbackRevisionId = rev;
|
|
1783
|
-
const secondIsSite = second && (second.includes('/') ||
|
|
1784
|
-
|
|
1785
|
-
siteDir = await resolveSiteDir(second);
|
|
1786
|
-
targetName = await resolveTarget(undefined, siteDir);
|
|
1787
|
-
}
|
|
1788
|
-
else {
|
|
1789
|
-
siteDir = await resolveSiteDir(third);
|
|
1790
|
-
targetName = await resolveTarget(second, siteDir);
|
|
1791
|
-
}
|
|
2135
|
+
const secondIsSite = second && (second.includes('/') || hasSiteConfig(resolve(second)));
|
|
2136
|
+
targetName = secondIsSite ? await resolveTarget(undefined, siteDir) : await resolveTarget(second, siteDir);
|
|
1792
2137
|
}
|
|
1793
2138
|
else if (targetFirstCommands.has(command)) {
|
|
1794
2139
|
// gazetta publish [target] [site]
|
|
1795
|
-
const [first
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
if (firstIsSite) {
|
|
1799
|
-
siteDir = await resolveSiteDir(first);
|
|
1800
|
-
targetName = await resolveTarget(undefined, siteDir);
|
|
1801
|
-
}
|
|
1802
|
-
else {
|
|
1803
|
-
siteDir = await resolveSiteDir(second);
|
|
1804
|
-
targetName = await resolveTarget(first, siteDir);
|
|
1805
|
-
}
|
|
2140
|
+
const [first] = parsed.positional;
|
|
2141
|
+
const firstIsSite = first && (first.includes('/') || hasSiteConfig(resolve(first)));
|
|
2142
|
+
targetName = firstIsSite ? await resolveTarget(undefined, siteDir) : await resolveTarget(first, siteDir);
|
|
1806
2143
|
}
|
|
1807
2144
|
else if (siteOnlyCommands.has(command)) {
|
|
1808
|
-
siteDir
|
|
2145
|
+
// siteDir set up front; nothing more needed.
|
|
1809
2146
|
}
|
|
1810
2147
|
else if (command === 'translate') {
|
|
1811
2148
|
// gazetta translate <item> --to <locale> [target]
|
|
1812
|
-
// positional args after the item are the optional target name
|
|
1813
|
-
siteDir = await resolveSiteDir(undefined);
|
|
1814
|
-
// Find the target arg — skip the item (pages/... or fragments/...) and --to/locale flags
|
|
1815
2149
|
const translatePositionals = parsed.positional.filter(p => !p.startsWith('pages/') && !p.startsWith('fragments/'));
|
|
1816
2150
|
if (translatePositionals.length > 0)
|
|
1817
2151
|
targetName = translatePositionals[0];
|
|
1818
2152
|
}
|
|
2153
|
+
else if (command === 'assets') {
|
|
2154
|
+
// gazetta assets <subcommand> [args...] [target] [site]
|
|
2155
|
+
// assets list [target] [site] → subcmd, target, site
|
|
2156
|
+
// assets info <name> [target] [site] → subcmd, name, target, site
|
|
2157
|
+
// assets reindex [target] [site] → subcmd, target, site
|
|
2158
|
+
const subcmd = parsed.positional[0];
|
|
2159
|
+
const targetArg = subcmd === 'info' ? parsed.positional[2] : parsed.positional[1];
|
|
2160
|
+
targetName = targetArg ? await resolveTarget(targetArg, siteDir) : undefined;
|
|
2161
|
+
}
|
|
2162
|
+
else if (command === 'archive') {
|
|
2163
|
+
// gazetta archive <subcommand> [args...]
|
|
2164
|
+
//
|
|
2165
|
+
// Site/target resolution: positional after the subcommand's
|
|
2166
|
+
// required args are interpreted as [target] [site]. The archive
|
|
2167
|
+
// module honors `--kind=` / `--force` / `--no-keep-alias` flags
|
|
2168
|
+
// separately (those don't reach the parsed.positional list per
|
|
2169
|
+
// global parseArgs).
|
|
2170
|
+
//
|
|
2171
|
+
// Subcommand positional shapes:
|
|
2172
|
+
// archive list → []
|
|
2173
|
+
// archive purge <name> → [name]
|
|
2174
|
+
// archive restore <name> → [name]
|
|
2175
|
+
// archive rename <oldname> <newname> → [oldname, newname]
|
|
2176
|
+
//
|
|
2177
|
+
// Remaining slots are [target] [site] in that order.
|
|
2178
|
+
const subcmd = parsed.positional[0];
|
|
2179
|
+
const requiredArgs = subcmd === 'rename' ? 2 : subcmd === 'purge' || subcmd === 'restore' ? 1 : 0;
|
|
2180
|
+
const trailingStart = 1 + requiredArgs;
|
|
2181
|
+
const targetArg = parsed.positional[trailingStart];
|
|
2182
|
+
targetName = targetArg ? await resolveTarget(targetArg, siteDir) : undefined;
|
|
2183
|
+
}
|
|
1819
2184
|
else {
|
|
1820
2185
|
console.error(` Unknown command: ${command}\n`);
|
|
1821
2186
|
printHelp();
|
|
1822
2187
|
process.exit(1);
|
|
1823
2188
|
return;
|
|
1824
2189
|
}
|
|
1825
|
-
// Load .env from project root and site dir (skipped in CI)
|
|
1826
|
-
if (!process.env.CI) {
|
|
1827
|
-
const projectRoot = detectProjectRoot(siteDir);
|
|
1828
|
-
const envDirs = projectRoot !== siteDir ? [projectRoot, siteDir] : [siteDir];
|
|
1829
|
-
for (const dir of envDirs) {
|
|
1830
|
-
for (const name of ['.env', '.env.local']) {
|
|
1831
|
-
const envPath = join(dir, name);
|
|
1832
|
-
if (existsSync(envPath)) {
|
|
1833
|
-
for (const line of readFileSync(envPath, 'utf-8').split('\n')) {
|
|
1834
|
-
const m = line.match(/^\s*([A-Z_][A-Z0-9_]*)\s*=\s*(.*)$/);
|
|
1835
|
-
if (m && !(m[1] in process.env))
|
|
1836
|
-
process.env[m[1]] = m[2].replace(/^["']|["']$/g, '');
|
|
1837
|
-
}
|
|
1838
|
-
}
|
|
1839
|
-
}
|
|
1840
|
-
}
|
|
1841
|
-
}
|
|
1842
2190
|
switch (command) {
|
|
1843
2191
|
case 'publish':
|
|
1844
2192
|
await runPublish(siteDir, targetName, { force: parsed.force });
|
|
@@ -1850,7 +2198,7 @@ async function main() {
|
|
|
1850
2198
|
await runDeploy(siteDir, targetName);
|
|
1851
2199
|
break;
|
|
1852
2200
|
case 'validate':
|
|
1853
|
-
await runValidate(siteDir);
|
|
2201
|
+
await runValidate(siteDir, args.slice(1));
|
|
1854
2202
|
break;
|
|
1855
2203
|
case 'dev':
|
|
1856
2204
|
await runDev(siteDir, parsed.port ?? 3000);
|
|
@@ -1880,7 +2228,11 @@ async function main() {
|
|
|
1880
2228
|
}
|
|
1881
2229
|
// Resolve the content directory — translate operates on a target's filesystem.
|
|
1882
2230
|
// Uses the specified target or falls back to the first editable target.
|
|
1883
|
-
const siteYaml =
|
|
2231
|
+
const siteYaml = await loadSiteManifestForCli(siteDir);
|
|
2232
|
+
if (!siteYaml) {
|
|
2233
|
+
console.error(` Error: no site config found at ${siteDir}`);
|
|
2234
|
+
process.exit(1);
|
|
2235
|
+
}
|
|
1884
2236
|
const { isEditable } = await import('../types.js');
|
|
1885
2237
|
const resolvedTarget = targetName ?? Object.entries(siteYaml.targets ?? {}).find(([, cfg]) => isEditable(cfg))?.[0];
|
|
1886
2238
|
if (!resolvedTarget) {
|
|
@@ -1889,26 +2241,27 @@ async function main() {
|
|
|
1889
2241
|
}
|
|
1890
2242
|
const targetConfig = siteYaml.targets[resolvedTarget];
|
|
1891
2243
|
if (!targetConfig) {
|
|
1892
|
-
console.error(` Error: target "${resolvedTarget}" not found in site
|
|
2244
|
+
console.error(` Error: target "${resolvedTarget}" not found in site config`);
|
|
1893
2245
|
process.exit(1);
|
|
1894
2246
|
}
|
|
1895
|
-
|
|
1896
|
-
|
|
2247
|
+
// Translate goes through the storage provider so it works on any
|
|
2248
|
+
// storage backend (filesystem / R2 / S3 / Azure). Path X — the storage
|
|
2249
|
+
// provider was constructed by the operator's factory at config-eval.
|
|
2250
|
+
const storage = targetConfig.storage;
|
|
1897
2251
|
const baseName = isPage ? 'page' : 'fragment';
|
|
1898
|
-
const
|
|
1899
|
-
const
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
if (!existsSync(sourceFile)) {
|
|
1903
|
-
console.error(` Error: ${sourceFile} not found`);
|
|
2252
|
+
const sourcePath = `${itemArg}/${baseName}.json`;
|
|
2253
|
+
const destPath = `${itemArg}/${localeFilename(baseName, locale)}`;
|
|
2254
|
+
if (!(await storage.exists(sourcePath))) {
|
|
2255
|
+
console.error(` Error: ${sourcePath} not found on target "${resolvedTarget}"`);
|
|
1904
2256
|
process.exit(1);
|
|
1905
2257
|
}
|
|
1906
|
-
if (
|
|
1907
|
-
console.error(` Error: ${
|
|
2258
|
+
if (await storage.exists(destPath)) {
|
|
2259
|
+
console.error(` Error: ${destPath} already exists on target "${resolvedTarget}"`);
|
|
1908
2260
|
process.exit(1);
|
|
1909
2261
|
}
|
|
1910
|
-
await
|
|
1911
|
-
|
|
2262
|
+
const sourceContent = await storage.readFile(sourcePath);
|
|
2263
|
+
await storage.writeFile(destPath, sourceContent);
|
|
2264
|
+
console.log(` ${c.green('✓')} Created ${destPath}`);
|
|
1912
2265
|
console.log(` Edit the file to translate the content.`);
|
|
1913
2266
|
break;
|
|
1914
2267
|
}
|
|
@@ -1925,12 +2278,22 @@ async function main() {
|
|
|
1925
2278
|
await runHistoryRollback(ctx, rollbackRevisionId, { yes: parsed.yes });
|
|
1926
2279
|
break;
|
|
1927
2280
|
}
|
|
2281
|
+
case 'assets': {
|
|
2282
|
+
const { runAssetsSubcommand } = await import('./assets-cli.js');
|
|
2283
|
+
await runAssetsSubcommand({ args: args.slice(1), siteDir, targetName });
|
|
2284
|
+
break;
|
|
2285
|
+
}
|
|
2286
|
+
case 'archive': {
|
|
2287
|
+
const { runArchiveSubcommand } = await import('./archive.js');
|
|
2288
|
+
await runArchiveSubcommand({ args: args.slice(1), siteDir, targetName });
|
|
2289
|
+
break;
|
|
2290
|
+
}
|
|
1928
2291
|
}
|
|
1929
2292
|
}
|
|
1930
2293
|
/**
|
|
1931
2294
|
* Resolve site + target + config into the shape HistoryCommandContext
|
|
1932
2295
|
* expects. Lives here rather than in cli/history.ts so the target-
|
|
1933
|
-
* resolution logic (site
|
|
2296
|
+
* resolution logic (site config parsing, CI env handling) stays with
|
|
1934
2297
|
* the other CLI commands that already do it the same way.
|
|
1935
2298
|
*/
|
|
1936
2299
|
async function resolveHistoryContext(siteDir, targetName) {
|