@starci/hfs 4.2.17 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/README.md +7 -0
- package/db/migrate.mjs +361 -0
- package/db/post-cutover.mjs +136 -0
- package/emit/db-types.mjs +10 -1
- package/lint/run.mjs +1 -1
- package/package.json +4 -1
- package/release/gate.mjs +298 -0
- package/release/index.mjs +103 -0
- package/release/push.mjs +110 -0
- package/runtime/knowledge/hfs/canon-pins.yaml +11 -11
- package/runtime/knowledge/hfs/fe-stack.yaml +22 -1
- package/runtime/knowledge/hfs/rules.yaml +3437 -160
- package/runtime/knowledge/hfs/slots.yaml +430 -92
- package/runtime/knowledge/patterns/be/api.yaml +92 -2
- package/runtime/knowledge/patterns/be/cli.yaml +37 -9
- package/runtime/knowledge/patterns/be/event-bus.yaml +3 -3
- package/runtime/knowledge/patterns/be/jobs.yaml +20 -2
- package/runtime/knowledge/patterns/be/projections.yaml +4 -2
- package/runtime/knowledge/patterns/be/queues.yaml +11 -3
- package/runtime/knowledge/patterns/be/reactors.yaml +20 -1
- package/runtime/knowledge/patterns/be/realtime.yaml +25 -3
- package/runtime/knowledge/patterns/be/saga.yaml +20 -3
- package/runtime/knowledge/patterns/be/webhooks.yaml +210 -36
- package/runtime/knowledge/patterns/fe/folder.yaml +4 -0
- package/runtime/knowledge/sonar-gate.yaml +1 -1
- package/runtime/modules/kernel/failure-codes.yaml +3128 -47
- package/runtime/modules/models/runtimes.yaml +1 -1
- package/runtime/modules/schemas/application-stacks.schema.yaml +663 -0
- package/runtime/packages/cli/src/catalog.generated.mjs +14104 -0
- package/runtime/packages/cli/src/validate-args.mjs +213 -0
- package/runtime/scripts/api/git/add.mjs +5 -0
- package/runtime/scripts/api/git/cat-file.mjs +5 -0
- package/runtime/scripts/api/git/init.mjs +7 -0
- package/runtime/scripts/api/git/lib.mjs +3 -0
- package/runtime/scripts/api/git/tag.mjs +5 -0
- package/runtime/scripts/api/node/lib.mjs +20 -0
- package/runtime/scripts/api/node/run-node.mjs +6 -0
- package/runtime/scripts/api/sops/lib.mjs +41 -0
- package/runtime/scripts/api/sops/resolve-sops.mjs +7 -0
- package/runtime/scripts/api/sops/seal.mjs +1 -1
- package/runtime/scripts/api/sops/selected-age-recipient.mjs +7 -0
- package/runtime/scripts/api/supabase/database-dump.mjs +5 -0
- package/runtime/scripts/api/supabase/database-query.mjs +5 -0
- package/runtime/scripts/api/supabase/lib.mjs +44 -0
- package/runtime/scripts/api/supabase/migration-repair.mjs +5 -0
- package/runtime/scripts/hfs/app-wiring.mjs +201 -0
- package/runtime/scripts/hfs/architecture/backend-app-files.mjs +103 -0
- package/runtime/scripts/hfs/architecture/backend.mjs +22 -10
- package/runtime/scripts/hfs/architecture/background-unowned.mjs +157 -41
- package/runtime/scripts/hfs/architecture/canon-clones.mjs +240 -0
- package/runtime/scripts/hfs/architecture/canon-jsx-clones.mjs +143 -0
- package/runtime/scripts/hfs/architecture/client-reaches-server.mjs +6 -3
- package/runtime/scripts/hfs/architecture/clones.mjs +17 -8
- package/runtime/scripts/hfs/architecture/connection-map.mjs +14 -12
- package/runtime/scripts/hfs/architecture/context-map.mjs +25 -14
- package/runtime/scripts/hfs/architecture/context-owner.mjs +1 -2
- package/runtime/scripts/hfs/architecture/dead-exports-bindings.mjs +149 -0
- package/runtime/scripts/hfs/architecture/dead-exports.mjs +23 -50
- package/runtime/scripts/hfs/architecture/default-deny.mjs +8 -6
- package/runtime/scripts/hfs/architecture/frontend-block-render.mjs +104 -0
- package/runtime/scripts/hfs/architecture/frontend-world-render.mjs +30 -11
- package/runtime/scripts/hfs/architecture/frontend-world.mjs +1 -1
- package/runtime/scripts/hfs/architecture/function-spec-providers.mjs +153 -0
- package/runtime/scripts/hfs/architecture/hfs.mjs +3 -3
- package/runtime/scripts/hfs/architecture/i18n-keys.mjs +16 -3
- package/runtime/scripts/hfs/architecture/machine-ast.mjs +17 -0
- package/runtime/scripts/hfs/architecture/module-per-transport.mjs +49 -25
- package/runtime/scripts/hfs/architecture/next-data-inference.mjs +176 -0
- package/runtime/scripts/hfs/architecture/next-data-symbols.mjs +26 -0
- package/runtime/scripts/hfs/architecture/next-data.mjs +31 -23
- package/runtime/scripts/hfs/architecture/reachability.mjs +14 -0
- package/runtime/scripts/hfs/architecture/register-once.mjs +15 -7
- package/runtime/scripts/hfs/architecture/required-files.mjs +2 -1
- package/runtime/scripts/hfs/architecture/source-names.mjs +48 -3
- package/runtime/scripts/hfs/architecture/staged-consumers.mjs +37 -0
- package/runtime/scripts/hfs/architecture/supabase-ast.mjs +214 -17
- package/runtime/scripts/hfs/architecture/supabase-be.mjs +1 -6
- package/runtime/scripts/hfs/architecture/supabase.mjs +59 -21
- package/runtime/scripts/hfs/architecture/surface.mjs +2 -1
- package/runtime/scripts/hfs/architecture/tiers.mjs +11 -4
- package/runtime/scripts/hfs/architecture/typescript.mjs +1 -8
- package/runtime/scripts/hfs/architecture/unit-spec-providers.mjs +9 -13
- package/runtime/scripts/hfs/check-results.mjs +28 -0
- package/runtime/scripts/hfs/check.mjs +63 -72
- package/runtime/scripts/hfs/coverage-from.mjs +70 -0
- package/runtime/scripts/hfs/db-baseline-verb.mjs +276 -0
- package/runtime/scripts/hfs/db-plan-verb.mjs +254 -0
- package/runtime/scripts/hfs/db-restamp-verb.mjs +60 -0
- package/runtime/scripts/hfs/declaration-shape.mjs +39 -3
- package/runtime/scripts/hfs/doc-commands.mjs +367 -0
- package/runtime/scripts/hfs/edition-slots.mjs +2 -2
- package/runtime/scripts/hfs/example-secrets.mjs +158 -0
- package/runtime/scripts/hfs/manifest-shape.mjs +91 -6
- package/runtime/scripts/hfs/path-findings.mjs +32 -2
- package/runtime/scripts/hfs/refusal-codes.mjs +6 -0
- package/runtime/scripts/hfs/rule-catalog.mjs +156 -11
- package/runtime/scripts/hfs/rule-params-shape.mjs +22 -10
- package/runtime/scripts/hfs/rules/a15-findings.mjs +88 -0
- package/runtime/scripts/hfs/rules/app-env-required.mjs +20 -0
- package/runtime/scripts/hfs/rules/app-root.mjs +2 -2
- package/runtime/scripts/hfs/rules/assets.mjs +79 -0
- package/runtime/scripts/hfs/rules/boot-proof.mjs +16 -0
- package/runtime/scripts/hfs/rules/canon-copy-drift.mjs +59 -0
- package/runtime/scripts/hfs/rules/contract.mjs +66 -5
- package/runtime/scripts/hfs/rules/coverage-below.mjs +230 -0
- package/runtime/scripts/hfs/rules/database-access.mjs +343 -0
- package/runtime/scripts/hfs/rules/database-baseline.mjs +142 -0
- package/runtime/scripts/hfs/rules/database-config.mjs +250 -2
- package/runtime/scripts/hfs/rules/database-constants.mjs +9 -0
- package/runtime/scripts/hfs/rules/database-migrations.mjs +317 -37
- package/runtime/scripts/hfs/rules/database-plpgsql.mjs +119 -9
- package/runtime/scripts/hfs/rules/database-queue-sources.mjs +176 -0
- package/runtime/scripts/hfs/rules/database-queues.mjs +361 -0
- package/runtime/scripts/hfs/rules/database-sql.mjs +91 -9
- package/runtime/scripts/hfs/rules/database.mjs +11 -2
- package/runtime/scripts/hfs/rules/deploy-scan.mjs +192 -0
- package/runtime/scripts/hfs/rules/deploy-workflow.mjs +219 -0
- package/runtime/scripts/hfs/rules/doc-fresh.mjs +286 -0
- package/runtime/scripts/hfs/rules/docker-health.mjs +249 -0
- package/runtime/scripts/hfs/rules/docker.mjs +24 -7
- package/runtime/scripts/hfs/rules/edition.mjs +11 -10
- package/runtime/scripts/hfs/rules/env-parity.mjs +373 -0
- package/runtime/scripts/hfs/rules/env-value-shape.mjs +113 -0
- package/runtime/scripts/hfs/rules/event-bus.mjs +3 -2
- package/runtime/scripts/hfs/rules/event-tables.mjs +100 -0
- package/runtime/scripts/hfs/rules/fe-contract-documents.mjs +115 -15
- package/runtime/scripts/hfs/rules/fe-stack.mjs +57 -0
- package/runtime/scripts/hfs/rules/feature-files.mjs +28 -0
- package/runtime/scripts/hfs/rules/frontend-tree.mjs +54 -35
- package/runtime/scripts/hfs/rules/integration-specs.mjs +3 -2
- package/runtime/scripts/hfs/rules/lexicon.mjs +62 -0
- package/runtime/scripts/hfs/rules/lite-proof-lane.mjs +89 -0
- package/runtime/scripts/hfs/rules/monorepo.mjs +14 -1
- package/runtime/scripts/hfs/rules/pipeline.mjs +8 -1
- package/runtime/scripts/hfs/rules/proof-commands.mjs +2 -0
- package/runtime/scripts/hfs/rules/release-provenance.mjs +211 -0
- package/runtime/scripts/hfs/rules/saga-delivery.mjs +66 -0
- package/runtime/scripts/hfs/rules/saga.mjs +8 -16
- package/runtime/scripts/hfs/rules/script-hygiene.mjs +151 -0
- package/runtime/scripts/hfs/rules/secret-custody-only.mjs +65 -0
- package/runtime/scripts/hfs/rules/secrets.mjs +26 -0
- package/runtime/scripts/hfs/rules/services.mjs +4 -4
- package/runtime/scripts/hfs/rules/stack-tooling.mjs +93 -0
- package/runtime/scripts/hfs/rules/stacks-deploy.mjs +76 -0
- package/runtime/scripts/hfs/rules/stacks-ingress.mjs +87 -0
- package/runtime/scripts/hfs/rules/stacks-lite-backing.mjs +111 -0
- package/runtime/scripts/hfs/rules/stacks-release.mjs +366 -0
- package/runtime/scripts/hfs/rules/stacks-runtime.mjs +168 -0
- package/runtime/scripts/hfs/rules/stacks-swarm.mjs +417 -0
- package/runtime/scripts/hfs/rules/stacks.mjs +13 -8
- package/runtime/scripts/hfs/rules/supabase-secrets.mjs +1 -1
- package/runtime/scripts/hfs/rules/supply-chain.mjs +167 -0
- package/runtime/scripts/hfs/rules/unused-symbol-flow.mjs +101 -0
- package/runtime/scripts/hfs/rules/unused-symbol-ledger.mjs +77 -0
- package/runtime/scripts/hfs/rules/unused-symbol-translators.mjs +165 -0
- package/runtime/scripts/hfs/rules/unused-symbol-values.mjs +103 -0
- package/runtime/scripts/hfs/rules/unused-symbol.mjs +320 -0
- package/runtime/scripts/hfs/runtime-rules/source-ast.mjs +185 -0
- package/runtime/scripts/hfs/runtime-rules/workflow-source.mjs +19 -0
- package/runtime/scripts/hfs/sealed-members.mjs +101 -0
- package/runtime/scripts/hfs/secret-bootstrap-crypto.mjs +200 -0
- package/runtime/scripts/hfs/secret-document.mjs +97 -0
- package/runtime/scripts/hfs/secret-edit.mjs +170 -0
- package/runtime/scripts/hfs/secret-errors.mjs +20 -0
- package/runtime/scripts/hfs/secret-files.mjs +124 -0
- package/runtime/scripts/hfs/secret-init.mjs +300 -0
- package/runtime/scripts/hfs/secret-output.mjs +100 -0
- package/runtime/scripts/hfs/secret-sops.mjs +130 -0
- package/runtime/scripts/hfs/secret-store.mjs +163 -0
- package/runtime/scripts/hfs/secret.mjs +162 -193
- package/runtime/scripts/hfs/slot-imports.mjs +18 -3
- package/runtime/scripts/hfs/slot-required.mjs +13 -0
- package/runtime/scripts/hfs/slot-semantic-problems.mjs +2 -1
- package/runtime/scripts/hfs/slots.mjs +1 -0
- package/runtime/scripts/hfs/stack-config-kit.mjs +34 -0
- package/runtime/scripts/hfs/stack-deploy-config.mjs +313 -0
- package/runtime/scripts/hfs/stack-ingress-config.mjs +237 -0
- package/runtime/scripts/hfs/stacks-gate.mjs +414 -0
- package/runtime/scripts/hfs/starcistacks-runtime.mjs +61 -0
- package/runtime/scripts/hfs/tree-findings.mjs +22 -0
- package/runtime/scripts/lib/command-tokens.mjs +126 -0
- package/runtime/scripts/lib/compose-values.mjs +11 -0
- package/runtime/scripts/lib/deployment-findings.mjs +7 -0
- package/runtime/scripts/lib/json-clone.mjs +61 -0
- package/runtime/scripts/lib/list.mjs +4 -0
- package/runtime/scripts/lib/roots.mjs +59 -0
- package/runtime/scripts/lib/runtime-example.mjs +13 -0
- package/runtime/scripts/lib/secret-patterns.mjs +60 -5
- package/runtime/scripts/lib/sql-ast.mjs +32 -0
- package/runtime/scripts/lib/stack-services.mjs +1 -1
- package/runtime/scripts/lib/swarm-stack.mjs +126 -0
- package/runtime/scripts/lib/trim-end.mjs +8 -0
- package/runtime/scripts/lib/ts-analysis.mjs +23 -0
- package/runtime/scripts/lib/ts-ast.mjs +27 -2
- package/runtime/scripts/lib/workflow-events.mjs +8 -0
- package/scaffold/add-app.mjs +77 -59
- package/scaffold/add-cli-lite.mjs +24 -17
- package/scaffold/add-compose.mjs +79 -0
- package/scaffold/add-database-lite.mjs +14 -0
- package/scaffold/add-fe-overlay.mjs +122 -0
- package/scaffold/add-fe-page.mjs +269 -0
- package/scaffold/add-inbox-lite.mjs +87 -124
- package/scaffold/add-plan.mjs +183 -0
- package/scaffold/add-table.mjs +132 -70
- package/scaffold/add.mjs +186 -204
- package/scaffold/app.mjs +128 -43
- package/scaffold/edition-gate.mjs +3 -3
- package/scaffold/image.mjs +2 -2
- package/scaffold/lite-exports.mjs +2 -1
- package/scaffold/service.mjs +2 -2
- package/src/main.mjs +238 -119
- package/stack/age-install.mjs +37 -0
- package/stack/backup.mjs +100 -0
- package/stack/build-args.mjs +42 -0
- package/stack/build.mjs +173 -0
- package/stack/cli.mjs +130 -0
- package/stack/config.mjs +57 -0
- package/stack/context.mjs +57 -0
- package/stack/converge.mjs +107 -0
- package/stack/deploy.mjs +301 -0
- package/stack/digest.mjs +16 -0
- package/stack/docker-transport.mjs +53 -0
- package/stack/edge-alias.mjs +118 -0
- package/stack/errors.mjs +21 -0
- package/stack/image-scan.mjs +152 -0
- package/stack/ingress-create.mjs +114 -0
- package/stack/ingress-publish.mjs +273 -0
- package/stack/ingress.mjs +706 -0
- package/stack/jobs.mjs +51 -0
- package/stack/live-restore.mjs +177 -0
- package/stack/prepare.mjs +266 -0
- package/stack/private-file.mjs +22 -0
- package/stack/provision.mjs +90 -0
- package/stack/prune.mjs +46 -0
- package/stack/release-store.mjs +87 -0
- package/stack/remote.mjs +205 -0
- package/stack/render.mjs +149 -0
- package/stack/retire.mjs +47 -0
- package/stack/sealed.mjs +149 -0
- package/stack/task.mjs +42 -0
- package/stack/verify.mjs +99 -0
- package/sync/ci-commands.mjs +13 -0
- package/sync/index.mjs +127 -64
- package/sync/stack-images.mjs +127 -0
- package/templates/app/ci-workflows/github/workflows/ci.yml +5 -1
- package/templates/app/ci-workflows/github/workflows/images.yml +15 -3
- package/templates/app/ci-workflows/github/workflows/stack-deploy.yml +148 -0
- package/templates/app/ci-workflows-lite/github/workflows/ci.yml +7 -3
- package/templates/app/ci-workflows-lite/github/workflows/db-deploy.yml +38 -6
- package/templates/app/ci-workflows-lite/github/workflows/images.yml +14 -2
- package/templates/app/ci-workflows-lite/github/workflows/stack-deploy.yml +148 -0
- package/templates/app/codegen-graphql.mjs.partial +13 -2
- package/templates/app/codegen-lite/scripts/codegen.mjs +6 -1
- package/templates/app/codegen-prelude.mjs.partial +8 -0
- package/templates/app/gitignore +4 -0
- package/templates/app/gitignore-lite +4 -0
- package/templates/app/hooks/husky/pre-commit +7 -12
- package/templates/app/package-scripts/package.json +1 -0
- package/templates/app/package-scripts/supabase.json +7 -0
- package/templates/app/package-scripts-lite/package.json +1 -7
- package/templates/app/skeleton/.editorconfig +1 -0
- package/templates/app/skeleton/.gitattributes +7 -1
- package/templates/app/skeleton/.github/dependabot.yml +17 -0
- package/templates/app/skeleton/.nvmrc +1 -1
- package/templates/app/skeleton/.sops.yaml +1 -1
- package/templates/app/skeleton/.starcistacks/application-stacks.yaml +134 -1
- package/templates/app/skeleton/.starcistacks/dev/README.md +16 -0
- package/templates/app/skeleton/.starcistacks/dev/environment.json +5 -0
- package/templates/app/skeleton/.starcistacks/dev/infra/compose/stack.yaml +71 -0
- package/templates/app/skeleton/.starcistacks/dev/runtime/env/KEYS.md +14 -0
- package/templates/app/skeleton/.starcistacks/production/README.md +37 -0
- package/templates/app/skeleton/.starcistacks/production/environment.json +5 -0
- package/templates/app/skeleton/.starcistacks/production/infra/swarm/Caddyfile +15 -0
- package/templates/app/skeleton/.starcistacks/production/infra/swarm/owner-actions.md +11 -0
- package/templates/app/skeleton/.starcistacks/production/infra/swarm/recovery/restore-proof.md +7 -0
- package/templates/app/skeleton/.starcistacks/production/infra/swarm/releases/current.yaml +6 -0
- package/templates/app/skeleton/.starcistacks/production/infra/swarm/releases/images.lock.yaml +9 -0
- package/templates/app/skeleton/.starcistacks/production/infra/swarm/releases/previous.yaml +6 -0
- package/templates/app/skeleton/.starcistacks/production/infra/swarm/stack.yaml +142 -0
- package/templates/app/skeleton/.starcistacks/production/runtime/env/KEYS.md +14 -0
- package/templates/app/skeleton/README.md +6 -6
- package/templates/app/skeleton/scripts/codegen.mjs +1 -2
- package/templates/app/skeleton-lite/.editorconfig +16 -0
- package/templates/app/skeleton-lite/.gitattributes +8 -0
- package/templates/app/skeleton-lite/.github/dependabot.yml +17 -0
- package/templates/app/skeleton-lite/.nvmrc +1 -0
- package/templates/app/skeleton-lite/.sops.yaml +3 -2
- package/templates/app/skeleton-lite/.starcistacks/application-stacks.yaml +193 -0
- package/templates/app/skeleton-lite/.starcistacks/dev/README.md +20 -0
- package/templates/app/skeleton-lite/.starcistacks/dev/environment.json +2 -1
- package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/Caddyfile +16 -0
- package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/owner-actions.md +11 -0
- package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/recovery/restore-proof.md +7 -0
- package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/releases/current.yaml +6 -0
- package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/releases/images.lock.yaml +8 -0
- package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/releases/previous.yaml +6 -0
- package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/stack.yaml +120 -0
- package/templates/app/skeleton-lite/.starcistacks/dev/runtime/env/KEYS.md +18 -0
- package/templates/app/skeleton-lite/.starcistacks/production/README.md +38 -0
- package/templates/app/skeleton-lite/.starcistacks/production/environment.json +6 -0
- package/templates/app/skeleton-lite/.starcistacks/production/infra/swarm/Caddyfile +11 -0
- package/templates/app/skeleton-lite/.starcistacks/production/infra/swarm/owner-actions.md +11 -0
- package/templates/app/skeleton-lite/.starcistacks/production/infra/swarm/recovery/restore-proof.md +7 -0
- package/templates/app/skeleton-lite/.starcistacks/production/infra/swarm/releases/current.yaml +6 -0
- package/templates/app/skeleton-lite/.starcistacks/production/infra/swarm/releases/images.lock.yaml +8 -0
- package/templates/app/skeleton-lite/.starcistacks/production/infra/swarm/releases/previous.yaml +6 -0
- package/templates/app/skeleton-lite/.starcistacks/production/infra/swarm/stack.yaml +121 -0
- package/templates/app/skeleton-lite/.starcistacks/production/runtime/env/KEYS.md +21 -0
- package/templates/app/skeleton-lite/.starciwork/brand/index.yaml +12 -0
- package/templates/app/skeleton-lite/.starciwork/workspace.yaml +9 -0
- package/templates/app/skeleton-lite/README.md +8 -4
- package/templates/app/skeleton-lite/supabase/config.toml +8 -1
- package/templates/app/skeleton-lite/supabase/migrations/__timestamp___baseline.sql +15 -6
- package/templates/app/starciwork.gitignore-lite +6 -0
- package/templates/app/upgrade-full/.starcistacks/dev/README.md +13 -7
- package/templates/be/image/worker/Dockerfile +1 -1
- package/templates/be/inbox/database-client.spec.ts.tpl +22 -28
- package/templates/be/inbox/database-client.ts.tpl +14 -28
- package/templates/be/inbox/delivery-recorded.event.ts.tpl +36 -0
- package/templates/be/inbox/event-index.ts.tpl +1 -0
- package/templates/be/inbox/events.json.tpl +10 -0
- package/templates/be/inbox/migration.sql.tpl +1 -0
- package/templates/be/inbox/platform/event-bus/event-bus.contracts.ts.tpl +42 -0
- package/templates/be/inbox/platform/event-bus/event-bus.decorators.ts.tpl +9 -0
- package/templates/be/inbox/platform/event-bus/event-bus.module-definition.ts.tpl +6 -0
- package/templates/be/inbox/platform/event-bus/event-bus.module.ts.tpl +19 -0
- package/templates/be/inbox/platform/event-bus/event-bus.options.ts.tpl +2 -0
- package/templates/be/inbox/platform/event-bus/event-bus.port.ts.tpl +16 -0
- package/templates/be/inbox/platform/event-bus/event-bus.service.spec.ts.tpl +45 -0
- package/templates/be/inbox/platform/event-bus/event-bus.service.ts.tpl +15 -0
- package/templates/be/inbox/platform/event-bus/index.ts.tpl +5 -0
- package/templates/be/inbox/platform/event-bus/persistence/event-bus.sql.ts.tpl +5 -0
- package/templates/be/inbox/platform/inbox/inbox.decorators.ts.tpl +9 -0
- package/templates/be/inbox/platform/inbox/inbox.module-definition.ts.tpl +6 -0
- package/templates/be/inbox/platform/inbox/inbox.module.ts.tpl +19 -0
- package/templates/be/inbox/platform/inbox/inbox.options.ts.tpl +2 -0
- package/templates/be/inbox/platform/inbox/inbox.port.ts.tpl +10 -0
- package/templates/be/inbox/platform/inbox/inbox.service.spec.ts.tpl +41 -0
- package/templates/be/inbox/platform/inbox/inbox.service.ts.tpl +19 -0
- package/templates/be/inbox/platform/inbox/index.ts.tpl +3 -0
- package/templates/be/inbox/platform/inbox/persistence/inbox.sql.ts.tpl +7 -0
- package/templates/be/inbox/platform/migration.sql.tpl +48 -0
- package/templates/be/inbox/service.spec.ts.tpl +49 -20
- package/templates/be/inbox/service.ts.tpl +27 -16
- package/templates/be/inbox/sql.ts.tpl +2 -2
- package/templates/be/inbox/webhook-door.spec.ts.tpl +3 -3
- package/templates/be/inbox/webhook-door.ts.tpl +4 -3
- package/templates/be/patterns/api/feature.module-definition.ts.tpl +6 -0
- package/templates/be/patterns/api/feature.module.ts.tpl +2 -1
- package/templates/be/patterns/api/feature.options.ts.tpl +2 -0
- package/templates/be/patterns/api/graphql.module-definition.ts.tpl +6 -0
- package/templates/be/patterns/api/graphql.module.ts.tpl +3 -2
- package/templates/be/patterns/api/graphql.options.ts.tpl +2 -0
- package/templates/be/patterns/cli/group.module-definition.ts.tpl +6 -0
- package/templates/be/patterns/cli/group.module.ts.tpl +2 -1
- package/templates/be/patterns/cli/group.options.ts.tpl +2 -0
- package/templates/be/patterns/event-bus/platform/errors/event-bus.error.ts.tpl +0 -3
- package/templates/be/patterns/event-bus/platform/messages/event-bus.messages.ts.tpl +0 -2
- package/templates/be/patterns/jobs/job.module-definition.ts.tpl +6 -0
- package/templates/be/patterns/jobs/job.module.ts.tpl +2 -1
- package/templates/be/patterns/jobs/job.options.ts.tpl +2 -0
- package/templates/be/patterns/jobs/job.queue.module-definition.ts.tpl +6 -0
- package/templates/be/patterns/jobs/job.queue.module.ts.tpl +6 -3
- package/templates/be/patterns/jobs/job.queue.options.ts.tpl +2 -0
- package/templates/be/patterns/jobs/platform/fenced.processor.spec.ts.tpl +3 -1
- package/templates/be/patterns/outbox/platform/outbox-relay.policy.spec.ts.tpl +25 -9
- package/templates/be/patterns/queues/platform/queue.config.ts.tpl +1 -1
- package/templates/be/patterns/queues/platform/queue.index.ts.tpl +1 -1
- package/templates/be/patterns/queues/platform/queue.module-definition.ts.tpl +2 -2
- package/templates/be/patterns/queues/platform/queue.module.ts.tpl +11 -0
- package/templates/be/patterns/queues/platform/queue.options.ts.tpl +10 -0
- package/templates/be/patterns/queues/queue.module-definition.ts.tpl +6 -0
- package/templates/be/patterns/queues/queue.module.ts.tpl +2 -1
- package/templates/be/patterns/queues/queue.options.ts.tpl +2 -0
- package/templates/be/patterns/reactors/message.module-definition.ts.tpl +6 -0
- package/templates/be/patterns/reactors/message.module.ts.tpl +6 -3
- package/templates/be/patterns/reactors/message.options.ts.tpl +2 -0
- package/templates/be/patterns/reactors/reactor.module-definition.ts.tpl +6 -0
- package/templates/be/patterns/reactors/reactor.module.ts.tpl +2 -1
- package/templates/be/patterns/reactors/reactor.options.ts.tpl +2 -0
- package/templates/be/patterns/realtime/channel.gateway.spec.ts.tpl +188 -0
- package/templates/be/patterns/realtime/channel.gateway.ts.tpl +22 -0
- package/templates/be/patterns/realtime/channel.graphql.module-definition.ts.tpl +6 -0
- package/templates/be/patterns/realtime/channel.graphql.module.ts.tpl +2 -1
- package/templates/be/patterns/realtime/channel.graphql.options.ts.tpl +2 -0
- package/templates/be/patterns/realtime/channel.websocket.module-definition.ts.tpl +6 -0
- package/templates/be/patterns/realtime/channel.websocket.module.ts.tpl +110 -0
- package/templates/be/patterns/realtime/channel.websocket.options.ts.tpl +7 -0
- package/templates/be/patterns/saga/saga.message.module-definition.ts.tpl +6 -0
- package/templates/be/patterns/saga/saga.message.module.ts.tpl +6 -3
- package/templates/be/patterns/saga/saga.message.options.ts.tpl +2 -0
- package/templates/be/patterns/saga/saga.module-definition.ts.tpl +6 -0
- package/templates/be/patterns/saga/saga.module.ts.tpl +2 -1
- package/templates/be/patterns/saga/saga.options.ts.tpl +2 -0
- package/templates/be/patterns/webhooks/webhook.door.spec.ts.tpl +3 -3
- package/templates/be/patterns/webhooks/webhook.door.ts.tpl +3 -3
- package/templates/be/patterns/webhooks/webhook.http.module-definition.ts.tpl +6 -0
- package/templates/be/patterns/webhooks/webhook.http.module.ts.tpl +2 -1
- package/templates/be/patterns/webhooks/webhook.http.options.ts.tpl +2 -0
- package/templates/be/platform/graphql/localize-errors.mapper.spec.ts +80 -26
- package/templates/be/platform/graphql/localize-errors.mapper.ts +2 -5
- package/templates/be/skeleton/apps/__app__/src/__app__.env.ts +21 -0
- package/templates/be/skeleton/apps/__app__/src/__app__.options.ts +1 -1
- package/templates/be/skeleton/apps/__app__/src/app.module.ts +15 -45
- package/templates/be/skeleton/apps/__app__/src/compose/api.ts +4 -0
- package/templates/be/skeleton/apps/__app__/src/compose/domain.ts +11 -0
- package/templates/be/skeleton/apps/__app__/src/compose/platform.ts +44 -0
- package/templates/be/skeleton/apps/__app__/src/compose/system.ts +5 -0
- package/templates/be/skeleton/apps/__app__/src/compose/webhooks.ts +4 -0
- package/templates/be/skeleton/apps/__app__/src/main.ts +18 -10
- package/templates/be/skeleton/apps/cli/src/app.module.ts +3 -13
- package/templates/be/skeleton/apps/cli/src/cli.env.ts +13 -0
- package/templates/be/skeleton/apps/cli/src/cli.options.ts +7 -17
- package/templates/be/skeleton/apps/cli/src/compose/cli.ts +5 -0
- package/templates/be/skeleton/apps/cli/src/compose/platform.ts +24 -0
- package/templates/be/skeleton/apps/cli/src/main.ts +3 -2
- package/templates/be/skeleton/src/features/api/system-health/application/check-readiness.contracts.ts +2 -0
- package/templates/be/skeleton/src/features/api/system-health/application/check-readiness.handler.ts +22 -0
- package/templates/be/skeleton/src/features/api/system-health/application/check-readiness.query.ts +11 -0
- package/templates/be/skeleton/src/features/api/system-health/system-health.module-definition.ts +6 -0
- package/templates/be/skeleton/src/features/api/system-health/system-health.module.ts +5 -3
- package/templates/be/skeleton/src/features/api/system-health/system-health.options.ts +2 -0
- package/templates/be/skeleton/src/features/api/system-health/transport/http/ready.controller.ts +19 -0
- package/templates/be/skeleton/src/features/api/system-health/transport/http/system-health-http.module-definition.ts +6 -0
- package/templates/be/skeleton/src/features/api/system-health/transport/http/system-health-http.module.ts +8 -3
- package/templates/be/skeleton/src/features/api/system-health/transport/http/system-health-http.options.ts +2 -0
- package/templates/be/skeleton/src/features/cli/cli.module-definition.ts +6 -0
- package/templates/be/skeleton/src/features/cli/cli.module.ts +3 -2
- package/templates/be/skeleton/src/features/cli/cli.options.ts +2 -0
- package/templates/be/skeleton/src/features/cli/migrate/migrate.module-definition.ts +6 -0
- package/templates/be/skeleton/src/features/cli/migrate/migrate.module.ts +2 -1
- package/templates/be/skeleton/src/features/cli/migrate/migrate.options.ts +2 -0
- package/templates/be/skeleton/src/features/cli/seed/seed.module-definition.ts +6 -0
- package/templates/be/skeleton/src/features/cli/seed/seed.module.ts +2 -1
- package/templates/be/skeleton/src/features/cli/seed/seed.options.ts +2 -0
- package/templates/be/skeleton/src/features/cli/seed/subs/run.cli.spec.ts +5 -6
- package/templates/be/skeleton/src/modules/domain/identity/admission.policy.spec.ts +56 -4
- package/templates/be/skeleton/src/modules/domain/identity/admission.policy.ts +36 -5
- package/templates/be/skeleton/src/modules/domain/identity/auth.guard.spec.ts +39 -8
- package/templates/be/skeleton/src/modules/domain/identity/auth.guard.ts +14 -8
- package/templates/be/skeleton/src/modules/domain/identity/credential.contracts.ts +26 -0
- package/templates/be/skeleton/src/modules/domain/identity/credential.guard.spec.ts +119 -0
- package/templates/be/skeleton/src/modules/domain/identity/credential.guard.ts +43 -0
- package/templates/be/skeleton/src/modules/domain/identity/identity.contracts.ts +16 -0
- package/templates/be/skeleton/src/modules/domain/identity/identity.decorators.ts +18 -1
- package/templates/be/skeleton/src/modules/domain/identity/identity.module.ts +22 -4
- package/templates/be/skeleton/src/modules/domain/identity/identity.options.ts +8 -2
- package/templates/be/skeleton/src/modules/domain/identity/index.ts +1 -0
- package/templates/be/skeleton/src/modules/platform/config/env-source.config.ts +6 -6
- package/templates/be/skeleton/src/modules/platform/database/connection-source.client.spec.ts +11 -4
- package/templates/be/skeleton/src/modules/platform/database/database-probe.service.spec.ts +32 -0
- package/templates/be/skeleton/src/modules/platform/database/database-probe.service.ts +14 -0
- package/templates/be/skeleton/src/modules/platform/database/database.module.ts +7 -1
- package/templates/be/skeleton/src/modules/platform/database/index.ts +2 -0
- package/templates/be/skeleton/src/modules/platform/database/primary.decorators.ts +8 -0
- package/templates/be/skeleton/src/modules/platform/database/seed-connections.client.spec.ts +25 -6
- package/templates/be/skeleton/src/modules/platform/errors/errors.filter.spec.ts +16 -6
- package/templates/be/skeleton/src/modules/platform/http-security/edge-security.service.spec.ts +130 -0
- package/templates/be/skeleton/src/modules/platform/http-security/edge-security.service.ts +58 -0
- package/templates/be/skeleton/src/modules/platform/http-security/errors/http-security.error.ts +3 -0
- package/templates/be/skeleton/src/modules/platform/http-security/execution-request.mapper.spec.ts +16 -4
- package/templates/be/skeleton/src/modules/platform/http-security/http-security.config.ts +16 -10
- package/templates/be/skeleton/src/modules/platform/http-security/http-security.module.ts +3 -1
- package/templates/be/skeleton/src/modules/platform/http-security/http-security.options.ts +2 -0
- package/templates/be/skeleton/src/modules/platform/http-security/index.ts +5 -0
- package/templates/be/skeleton/src/modules/platform/http-security/messages/http-security.messages.ts +12 -5
- package/templates/be/skeleton/src/modules/platform/http-security/rate-limit.guard.spec.ts +13 -8
- package/templates/be/skeleton/src/modules/platform/http-security/readiness.contracts.ts +5 -0
- package/templates/be/skeleton/src/modules/platform/http-security/readiness.decorators.ts +7 -0
- package/templates/be/skeleton/src/modules/platform/http-security/readiness.service.spec.ts +86 -0
- package/templates/be/skeleton/src/modules/platform/http-security/readiness.service.ts +39 -0
- package/templates/be/skeleton/src/modules/platform/http-security/webhook-signature.service.spec.ts +139 -131
- package/templates/be/skeleton/src/modules/platform/i18n/index.ts +1 -1
- package/templates/be/skeleton/src/modules/platform/logging/json-logger.service.spec.ts +91 -67
- package/templates/be/skeleton/src/modules/platform/logging/json-logger.service.ts +5 -4
- package/templates/be/skeleton/src/modules/platform/logging/logging.log-events.ts +0 -2
- package/templates/be/skeleton/src/modules/platform/primitives/outcome.mapper.spec.ts +20 -6
- package/templates/be/skeleton/src/modules/platform/primitives/sequence.policy.spec.ts +16 -4
- package/templates/be/skeleton/src/modules/platform/retry/index.ts +3 -0
- package/templates/be/skeleton/src/modules/platform/retry/retry.decorators.ts +9 -0
- package/templates/be/skeleton/src/modules/platform/retry/retry.module-definition.ts +7 -0
- package/templates/be/skeleton/src/modules/platform/retry/retry.module.ts +19 -0
- package/templates/be/skeleton/src/modules/platform/retry/retry.options.ts +2 -0
- package/templates/be/skeleton/src/modules/platform/retry/retry.port.ts +11 -0
- package/templates/be/skeleton/src/modules/platform/retry/system-timer.service.spec.ts +36 -0
- package/templates/be/skeleton/src/modules/platform/retry/system-timer.service.ts +10 -0
- package/templates/be/skeleton/src/tests/contract/http-security/http-security.contract-spec.ts +54 -0
- package/templates/be/skeleton-lite/apps/api/src/api.env.ts +25 -0
- package/templates/be/skeleton-lite/apps/api/src/api.options.ts +1 -1
- package/templates/be/skeleton-lite/apps/api/src/app.module.ts +18 -58
- package/templates/be/skeleton-lite/apps/api/src/compose/api.ts +4 -0
- package/templates/be/skeleton-lite/apps/api/src/compose/domain.ts +10 -0
- package/templates/be/skeleton-lite/apps/api/src/compose/integrations.ts +16 -0
- package/templates/be/skeleton-lite/apps/api/src/compose/platform.ts +47 -0
- package/templates/be/skeleton-lite/apps/api/src/compose/system.ts +5 -0
- package/templates/be/skeleton-lite/apps/api/src/compose/webhooks.ts +4 -0
- package/templates/be/skeleton-lite/apps/api/src/main.ts +5 -13
- package/templates/be/skeleton-lite/apps/cli/src/cli.env.ts +17 -0
- package/templates/be/skeleton-lite/apps/cli/src/compose/platform.ts +12 -0
- package/templates/be/skeleton-lite/src/modules/domain/identity/admission.policy.spec.ts +71 -5
- package/templates/be/skeleton-lite/src/modules/domain/identity/admission.policy.ts +29 -2
- package/templates/be/skeleton-lite/src/modules/domain/identity/auth.guard.spec.ts +68 -15
- package/templates/be/skeleton-lite/src/modules/domain/identity/auth.guard.ts +14 -9
- package/templates/be/skeleton-lite/src/modules/domain/identity/identity.contracts.ts +9 -2
- package/templates/be/skeleton-lite/src/modules/domain/identity/identity.decorators.ts +16 -1
- package/templates/be/skeleton-lite/src/modules/domain/identity/identity.module.ts +19 -4
- package/templates/be/skeleton-lite/src/modules/domain/identity/identity.options.ts +5 -1
- package/templates/be/skeleton-lite/src/modules/domain/identity/index.ts +2 -1
- package/templates/be/skeleton-lite/src/modules/integrations/supabase/errors/supabase.error.ts +0 -3
- package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.client.spec.ts +17 -5
- package/templates/be/skeleton-lite/src/modules/platform/database/database.module.ts +24 -13
- package/templates/be/skeleton-lite/src/modules/platform/database/database.port.ts +5 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/errors/database.error.ts +16 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/index.ts +3 -0
- package/templates/be/skeleton-lite/src/modules/platform/http-security/http-security.module.ts +5 -2
- package/templates/be/skeleton-lite/src/modules/platform/http-security/index.ts +4 -1
- package/templates/be/skeleton-lite/src/modules/platform/i18n/index.ts +1 -1
- package/templates/be/skeleton-lite/src/modules/platform/logging/logging.log-events.ts +7 -0
- package/templates/be/skeleton-lite/src/tests/fixtures/builders/api.builder.ts +29 -0
- package/templates/be/skeleton-lite/src/tests/fixtures/builders/cli.builder.ts +16 -0
- package/templates/be/table/api/feature.module-definition.ts.tpl +6 -0
- package/templates/be/table/api/feature.module.ts.tpl +2 -1
- package/templates/be/table/api/feature.options.ts.tpl +2 -0
- package/templates/be/table/api/graphql.module-definition.ts.tpl +6 -0
- package/templates/be/table/api/graphql.module.ts.tpl +3 -2
- package/templates/be/table/api/graphql.options.ts.tpl +2 -0
- package/templates/be/table/migration.sql.tpl +1 -0
- package/templates/be/upgrade-full/apps/cli/src/app.module.ts +4 -6
- package/templates/be/upgrade-full/apps/cli/src/cli.env.ts +7 -0
- package/templates/be/upgrade-full/apps/cli/src/compose/cli.ts +5 -0
- package/templates/be/upgrade-full/apps/cli/src/compose/platform.ts +9 -0
- package/templates/be/upgrade-full/apps/cli/src/main.ts +3 -0
- package/templates/be/upgrade-full/src/features/cli/cli.module.ts +3 -2
- package/templates/fe/auth/supabase-client.ts.tpl +34 -0
- package/templates/fe/skeleton/apps/__app__/src/app/auth/callback/route.ts +11 -0
- package/templates/fe/skeleton/apps/__app__/src/components/blocks/SignInForm/index.tsx +6 -1
- package/templates/fe/skeleton/apps/__app__/src/components/leaves/Icon/index.tsx +4 -0
- package/templates/fe/skeleton/apps/__app__/src/features/overlays/AppGuideOverlay/component.tsx +31 -0
- package/templates/fe/skeleton/apps/__app__/src/features/overlays/AppGuideOverlay/index.tsx +24 -0
- package/templates/fe/skeleton/apps/__app__/src/hooks/auth/useSession.ts +6 -1
- package/templates/fe/skeleton/apps/__app__/src/hooks/auth/useSignOut.ts +3 -4
- package/templates/fe/skeleton/apps/__app__/src/hooks/zustand/appGuide/index.ts +1 -0
- package/templates/fe/skeleton/apps/__app__/src/hooks/zustand/appGuide/store.ts +15 -0
- package/templates/fe/skeleton/apps/__app__/src/modules/auth/pkce-client.ts +18 -0
- package/templates/fe/skeleton/apps/__app__/src/modules/auth/server.ts +19 -0
- package/templates/fe/skeleton/apps/app/src/features/pages/AppHomePage/index.tsx +7 -1
- package/templates/fe/skeleton/apps/app/src/modules/i18n/messages/en.json +57 -0
- package/templates/fe/skeleton/apps/app/src/modules/i18n/messages/vi.json +6 -0
- package/templates/fe/skeleton/apps/landing/src/modules/i18n/messages/en.json +31 -0
- package/templates/fe/skeleton/packages/__project__-i18n/src/routing.ts +1 -1
- package/templates/fe/skeleton/packages/__project__-ui/src/index.ts +1 -0
- package/templates/fe/skeleton-lite/apps/__app__/src/modules/auth/client.ts +1 -34
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppHomePage/index.tsx +7 -1
- package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/messages/en.json +57 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/messages/vi.json +30 -24
- package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/routing.ts +1 -1
- package/templates/fe/transport/graphql/clients/clients/auth.ts +1 -1
- package/templates/fe/transport/graphql/clients/links/locale.ts +2 -2
- package/upgrade/check.mjs +3 -1
- package/upgrade/file-state.mjs +68 -0
- package/upgrade/index.mjs +58 -94
- package/runtime/scripts/api/git/log.mjs +0 -5
- package/templates/app/skeleton-lite/.starciwork/shell/index.yaml +0 -55
package/scaffold/app.mjs
CHANGED
|
@@ -23,10 +23,13 @@ import { SUPABASE_PORT_VARIABLES, supabasePortVars } from './supabase-ports.mjs'
|
|
|
23
23
|
import { FE_APP_SCRIPTS, PACKAGE_MANAGER, WORKSPACES, WORKSPACE_LINT, feAppPackageName } from '../runtime/scripts/hfs/rules/monorepo.mjs';
|
|
24
24
|
import { isLinkLike } from '../runtime/scripts/api/fs/is-link-like.mjs';
|
|
25
25
|
import { unlinkOnly } from '../runtime/scripts/api/fs/lib.mjs';
|
|
26
|
+
import { initializeAppIdentity } from '../runtime/scripts/hfs/secret-init.mjs';
|
|
27
|
+
import { declaredSealedMembers, materializeDeclaredPlaceholders } from '../runtime/scripts/hfs/sealed-members.mjs';
|
|
26
28
|
import { revParseQuery } from '../runtime/scripts/api/git/rev-parse-query.mjs';
|
|
27
29
|
import { lsFiles } from '../runtime/scripts/api/git/ls-files.mjs';
|
|
28
30
|
import { insidePath, samePath } from '../runtime/scripts/lib/path-key.mjs';
|
|
29
31
|
import { byCodeUnit } from '../report/order.mjs';
|
|
32
|
+
import { sonarGateName } from '../sync/sonar-key.mjs';
|
|
30
33
|
|
|
31
34
|
const NAME = /^[a-z][a-z0-9-]*$/;
|
|
32
35
|
const APP_DIR = '__app__';
|
|
@@ -96,12 +99,14 @@ export function jsonText(value) {
|
|
|
96
99
|
const inner = `${indent} `;
|
|
97
100
|
if (Array.isArray(item)) {
|
|
98
101
|
if (item.every(entry => entry === null || typeof entry !== 'object')) return `[${item.map(entry => JSON.stringify(entry)).join(', ')}]`;
|
|
99
|
-
|
|
102
|
+
const entries = item.map(entry => `${inner}${print(entry, inner)}`).join(',\n');
|
|
103
|
+
return `[\n${entries}\n${indent}]`;
|
|
100
104
|
}
|
|
101
105
|
if (item !== null && typeof item === 'object') {
|
|
102
106
|
const keys = Object.keys(item);
|
|
103
107
|
if (!keys.length) return '{}';
|
|
104
|
-
|
|
108
|
+
const entries = keys.map(key => `${inner}${JSON.stringify(key)}: ${print(item[key], inner)}`).join(',\n');
|
|
109
|
+
return `{\n${entries}\n${indent}}`;
|
|
105
110
|
}
|
|
106
111
|
return JSON.stringify(item);
|
|
107
112
|
};
|
|
@@ -161,7 +166,7 @@ const STARTER_DEPENDENCIES = Object.freeze({
|
|
|
161
166
|
});
|
|
162
167
|
|
|
163
168
|
/**
|
|
164
|
-
* Lite keeps the production stack, the canon tools and the back end's unit run (
|
|
169
|
+
* Lite keeps the production stack, the canon tools and the back end's unit run (ruling:R212/case-1, amended by ruling:R212/case-4); it runs no test world of
|
|
165
170
|
* its own (no @starci/test-world). Both editions serve GraphQL from the api app (@nestjs/graphql over Apollo, owner ruling
|
|
166
171
|
* 2026-10-13); the fe stack's root tools are added from fe-stack.yaml by packageManifest.
|
|
167
172
|
*/
|
|
@@ -198,7 +203,7 @@ const FE_APP_DEPENDENCIES = Object.freeze({
|
|
|
198
203
|
* the front end is the Auth client of modules/auth only) and server-only for its own next-intl request config.
|
|
199
204
|
*/
|
|
200
205
|
const LITE_FE_APP_DEPENDENCIES = Object.freeze({
|
|
201
|
-
'@heroui/react': null, '@heroui/styles': null, '@starci/grammar': null, '@xyflow/react': null,
|
|
206
|
+
'@heroicons/react': null, '@heroui/react': null, '@heroui/styles': null, '@starci/grammar': null, '@starci/heroicons': null, '@xyflow/react': null,
|
|
202
207
|
'@supabase/supabase-js': null, next: null, 'next-intl': null, react: null, 'react-dom': null, 'server-only': null,
|
|
203
208
|
});
|
|
204
209
|
|
|
@@ -209,7 +214,7 @@ const LITE_FE_APP_DEPENDENCIES = Object.freeze({
|
|
|
209
214
|
* ./routing, client-safe: the default locale a client boundary reads).
|
|
210
215
|
*/
|
|
211
216
|
const FE_PACKAGES = Object.freeze({
|
|
212
|
-
ui: { exports: ['.'], dependencies: { '@heroui/react': null, '@starci/grammar': null, '@xyflow/react': null, 'next-intl': null, react: null } },
|
|
217
|
+
ui: { exports: ['.'], dependencies: { '@heroui/react': null, '@starci/grammar': null, '@starci/heroicons': null, '@xyflow/react': null, 'next-intl': null, react: null } },
|
|
213
218
|
i18n: { exports: ['.', './proxy', './routing'], dependencies: { next: null, 'next-intl': null, 'server-only': null } },
|
|
214
219
|
});
|
|
215
220
|
|
|
@@ -226,6 +231,47 @@ const starterDeclaration = (name, manifest = loadSlotManifest(), edition = 'full
|
|
|
226
231
|
sides: structuredClone(edition === 'lite' ? LITE_STARTER_SIDES : STARTER_SIDES),
|
|
227
232
|
});
|
|
228
233
|
|
|
234
|
+
/** Opting into a server PKCE callback also selects Supabase Auth and declares its route slot. */
|
|
235
|
+
function enableAuthCallback(declaration) {
|
|
236
|
+
requireAuthCallbackConnection(declaration);
|
|
237
|
+
declaration.sides.fe.optionalSlots = [...(declaration.sides.fe.optionalSlots ?? []), 'fe.route.callback'];
|
|
238
|
+
declaration.supabase ??= structuredClone(LITE_STARTER_SUPABASE);
|
|
239
|
+
declaration.supabase.redirectUrls = ['http://127.0.0.1:3000/auth/callback'];
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/** Callback-specific source files are excluded from the browser-only starter. */
|
|
243
|
+
const CALLBACK_SOURCE_FILES = Object.freeze(new Set([
|
|
244
|
+
'src/app/auth/callback/route.ts', 'src/modules/auth/server.ts', 'src/modules/auth/pkce-client.ts',
|
|
245
|
+
]));
|
|
246
|
+
export const hasAuthCallback = repo => (repo.sides.fe.optionalSlots ?? []).includes('fe.route.callback');
|
|
247
|
+
|
|
248
|
+
function requireAuthCallbackConnection(repo) {
|
|
249
|
+
if (!(repo.sides.be?.connections ?? []).some(entry => entry.provider === 'supabase'))
|
|
250
|
+
throw new ScaffoldError('HFS_ADD_CONNECTION_REQUIRED', 'the auth callback requires an existing Supabase connection; the full starter has none');
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/** Apply the callback's cookie-backed auth owner and its config readers to product apps only. */
|
|
254
|
+
export function callbackSourceFiles(files, repo) {
|
|
255
|
+
const enabled = hasAuthCallback(repo);
|
|
256
|
+
if (enabled) requireAuthCallbackConnection(repo);
|
|
257
|
+
const selected = files.filter(file => {
|
|
258
|
+
const [, , app, ...parts] = file.path.split('/');
|
|
259
|
+
const relative = parts.join('/');
|
|
260
|
+
if (relative === 'src/modules/auth/pkce-client.ts') return false;
|
|
261
|
+
return MARKETING_FE_APPS.has(app) || enabled || !CALLBACK_SOURCE_FILES.has(relative);
|
|
262
|
+
});
|
|
263
|
+
if (!enabled) return selected;
|
|
264
|
+
const config = fs.readFileSync(path.join(TEMPLATES_DIR, 'fe/skeleton-lite/apps/web/src/modules/config/index.ts'), 'utf8');
|
|
265
|
+
const client = render(fs.readFileSync(path.join(TEMPLATES_DIR, 'fe/skeleton/apps/__app__/src/modules/auth/pkce-client.ts'), 'utf8').replace(/\r\n/g, '\n'), PARTIAL_VARIABLES);
|
|
266
|
+
return selected.map(file => {
|
|
267
|
+
const [, , app, ...parts] = file.path.split('/');
|
|
268
|
+
if (MARKETING_FE_APPS.has(app)) return file;
|
|
269
|
+
const relative = parts.join('/');
|
|
270
|
+
if (relative === 'src/modules/config/index.ts') return { ...file, content: config };
|
|
271
|
+
return relative === 'src/modules/auth/client.ts' ? { ...file, content: client } : file;
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
|
|
229
275
|
/** A dependency section at the canon pins (a null range takes the pin, which must exist; every pinned name is null). */
|
|
230
276
|
function pinnedSection(entries, pins) {
|
|
231
277
|
const pinned = (dependency, range) => {
|
|
@@ -278,9 +324,10 @@ const workspaceSection = (entries, project, pins) => pinnedSection(Object.fromEn
|
|
|
278
324
|
* The package.json of the fe app workspace `app` of the app `project`: @<project>/<app>, private, the workspace scripts, its own
|
|
279
325
|
* dependencies. A product app (`core`, it carries the shared app core) also takes every core runtime package of the fe stack.
|
|
280
326
|
*/
|
|
281
|
-
function feAppManifest(project, app, pins, edition, { core = true, stack = coreFeStackPackages() } = {}) {
|
|
327
|
+
function feAppManifest(project, app, pins, edition, { core = true, authCallback = false, stack = coreFeStackPackages() } = {}) {
|
|
282
328
|
const base = edition === 'lite' ? LITE_FE_APP_DEPENDENCIES : FE_APP_DEPENDENCIES;
|
|
283
329
|
const dependencies = { ...base, ...(core ? Object.fromEntries(stack.app.filter(name => !Object.hasOwn(base, name)).map(name => [name, null])) : {}) };
|
|
330
|
+
if (core && authCallback) Object.assign(dependencies, { '@supabase/ssr': null, '@supabase/supabase-js': null, 'server-only': null });
|
|
284
331
|
return { name: feAppPackageName(project, app), version: '0.0.0', private: true, scripts: { ...FE_APP_SCRIPTS }, dependencies: workspaceSection(dependencies, project, pins) };
|
|
285
332
|
}
|
|
286
333
|
|
|
@@ -329,15 +376,15 @@ function nextAppTsconfig() {
|
|
|
329
376
|
};
|
|
330
377
|
}
|
|
331
378
|
|
|
332
|
-
/** The names a skeleton file may fill: {{project}}, {{app}}, {{appPascal}} (the side's app), {{sonarGate}} and the lite Supabase port block ({{supabasePort<Section>}}, supabase-ports.mjs). */
|
|
333
|
-
const SKELETON_VARIABLES = Object.freeze(['project', 'app', 'appPascal', 'sonarGate', ...SUPABASE_PORT_VARIABLES]);
|
|
379
|
+
/** The names a skeleton file may fill: {{project}}, {{app}}, {{appPascal}} (the side's app), {{sonarGate}}, {{registryVisibility}} (the image visibility written once into deploy.registry) and the lite Supabase port block ({{supabasePort<Section>}}, supabase-ports.mjs). */
|
|
380
|
+
const SKELETON_VARIABLES = Object.freeze(['project', 'app', 'appPascal', 'sonarGate', 'registryVisibility', ...SUPABASE_PORT_VARIABLES]);
|
|
334
381
|
|
|
335
382
|
/**
|
|
336
383
|
* A skeleton file with its variables filled. Only the skeleton names are variables: every other `{{name}}` is source the app keeps
|
|
337
384
|
* (a message placeholder of the i18n canon, `{{title}}` in a catalog), and a skeleton name with no value for this file is an error.
|
|
338
385
|
*/
|
|
339
386
|
function fill(source, vars, file) {
|
|
340
|
-
return source.replace(new RegExp(
|
|
387
|
+
return source.replace(new RegExp(String.raw`\{\{(${SKELETON_VARIABLES.join('|')})\}\}`, 'g'), (_, key) => {
|
|
341
388
|
if (!Object.hasOwn(vars, key)) throw new ScaffoldError('HFS_SCAFFOLD_TEMPLATE_VARIABLE', `${file} names {{${key}}}, which has no value outside a __app__ folder`);
|
|
342
389
|
return vars[key];
|
|
343
390
|
});
|
|
@@ -353,8 +400,7 @@ export const PARTIAL_VARIABLES = new Proxy(Object.create(null), {
|
|
|
353
400
|
const CLI_APP_DIR = 'apps/cli/';
|
|
354
401
|
const declaresCliApp = app => app.sides.be.apps.some(entry => entry.kind === 'cli' && entry.name === 'cli');
|
|
355
402
|
|
|
356
|
-
const LITE_APP_REUSED = new Set(['.editorconfig', '.gitattributes', '.nvmrc'
|
|
357
|
-
'.starciwork/index.yaml', '.starciwork/features/system-health/index.yaml']);
|
|
403
|
+
const LITE_APP_REUSED = new Set(['.editorconfig', '.gitattributes', '.nvmrc']);
|
|
358
404
|
const LITE_DEFERRED_GENERATOR_FILES = new Set([
|
|
359
405
|
'src/modules/platform/database/database.sql.ts',
|
|
360
406
|
'src/modules/platform/database/migration-runner.service.ts',
|
|
@@ -376,7 +422,7 @@ const liteOverlaid = (() => {
|
|
|
376
422
|
})();
|
|
377
423
|
/**
|
|
378
424
|
* A base be file lite reuses: a source file of the shared shape, and the unit spec beside a reused source file that the lite overlay
|
|
379
|
-
* does not replace (
|
|
425
|
+
* does not replace (ruling:R212/case-1, amended by ruling:R212/case-4: a lite back end keeps full's unit specs).
|
|
380
426
|
*/
|
|
381
427
|
const liteBaseFile = (scope, rel) => {
|
|
382
428
|
if (scope === 'app') return LITE_APP_REUSED.has(rel);
|
|
@@ -388,35 +434,58 @@ const liteBaseFile = (scope, rel) => {
|
|
|
388
434
|
};
|
|
389
435
|
const liteOverlayFile = (scope, rel) => scope !== 'be' || !LITE_DEFERRED_GENERATOR_FILES.has(rel);
|
|
390
436
|
|
|
437
|
+
function skeletonOutputPath(relative, { scope, app, vars }) {
|
|
438
|
+
const prefix = scope === 'app' ? '' : `${scope}/`;
|
|
439
|
+
const output = relative.split(PROJECT_DIR).join(app.project).split(TIMESTAMP).join(vars.timestamp);
|
|
440
|
+
return `${prefix}${output}`;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
function fixedSkeletonFiles(context, relative, source) {
|
|
444
|
+
const { scope, directory, app, vars, apps } = context;
|
|
445
|
+
if (scope === 'be' && relative === 'src/tests/fixtures/builders/cli.builder.ts' && !declaresCliApp(app)) return [];
|
|
446
|
+
if (scope === 'be' && relative.startsWith(CLI_APP_DIR) && !declaresCliApp(app)) return [];
|
|
447
|
+
const fixedApp = apps.find(entry => relative.startsWith(`apps/${entry.name}/`));
|
|
448
|
+
if (scope === 'fe' && relative.startsWith('apps/') && !fixedApp) return [];
|
|
449
|
+
const appVars = fixedApp ? { app: fixedApp.name, appPascal: pascal(fixedApp.name) } : {};
|
|
450
|
+
return [{
|
|
451
|
+
path: skeletonOutputPath(relative, context),
|
|
452
|
+
content: fill(source, { project: app.project, ...vars, ...appVars }, `${directory}/${relative}`),
|
|
453
|
+
}];
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
function variableSkeletonFiles(context, relative, source) {
|
|
457
|
+
const { scope, directory, app, vars, apps } = context;
|
|
458
|
+
const leaves = `apps/${APP_DIR}/src/components/leaves/`;
|
|
459
|
+
if (scope === 'fe' && app.edition === 'full' && relative.startsWith(leaves)) {
|
|
460
|
+
return fixedSkeletonFiles(context, relative.replace(leaves, `packages/${PROJECT_DIR}-ui/src/leaves/`), source);
|
|
461
|
+
}
|
|
462
|
+
const selectedApps = scope === 'fe' ? coreFeApps(apps) : apps;
|
|
463
|
+
return selectedApps.map(entry => ({
|
|
464
|
+
path: skeletonOutputPath(relative.split(APP_DIR).join(entry.name), context),
|
|
465
|
+
content: fill(source, { project: app.project, ...vars, app: entry.name, appPascal: pascal(entry.name) }, `${directory}/${relative}`),
|
|
466
|
+
}));
|
|
467
|
+
}
|
|
468
|
+
|
|
391
469
|
/** One skeleton directory rendered to app-relative files; `include` filters source-relative paths before variables are expanded. */
|
|
392
470
|
function skeletonDirectory(scope, directory, app, vars, include = () => true) {
|
|
393
471
|
const dir = path.join(TEMPLATES_DIR, scope, directory);
|
|
394
472
|
if (!fs.existsSync(dir)) throw new ScaffoldError('HFS_SCAFFOLD_SKELETON_MISSING', `no skeleton templates in templates/${scope}/${directory}`);
|
|
395
473
|
const apps = scope === 'app' ? [] : app.sides[scope].apps.filter(entry => scope === 'fe' || entry.kind === 'api');
|
|
396
|
-
const
|
|
397
|
-
const prefix = scope === 'app' ? '' : `${scope}/`;
|
|
474
|
+
const context = { scope, directory, app, vars, apps };
|
|
398
475
|
const files = [];
|
|
399
|
-
for (const rel of listFiles(dir).filter(include)) {
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
const
|
|
403
|
-
|
|
404
|
-
if (scope === 'be' && rel.startsWith(CLI_APP_DIR) && !declaresCliApp(app)) continue;
|
|
405
|
-
const fixedApp = apps.find(entry => rel.startsWith(`apps/${entry.name}/`));
|
|
406
|
-
if (scope === 'fe' && rel.startsWith('apps/') && !fixedApp) continue;
|
|
407
|
-
const appVars = fixedApp ? { app: fixedApp.name, appPascal: pascal(fixedApp.name) } : {};
|
|
408
|
-
files.push({ path: `${prefix}${output(rel)}`, content: fill(source, { ...once, ...appVars }, `${directory}/${rel}`) });
|
|
409
|
-
continue;
|
|
410
|
-
}
|
|
411
|
-
for (const entry of appsOf(rel)) files.push({ path: `${prefix}${output(rel.split(APP_DIR).join(entry.name))}`, content: fill(source, { ...once, app: entry.name, appPascal: pascal(entry.name) }, `${directory}/${rel}`) });
|
|
476
|
+
for (const rel of listFiles(dir).filter(relative => include(relative))) {
|
|
477
|
+
let source = render(fs.readFileSync(path.join(dir, rel), 'utf8').replace(/\r\n/g, '\n'), PARTIAL_VARIABLES);
|
|
478
|
+
if (scope === 'fe' && app.edition === 'full') source = source.replaceAll('"@/components/leaves/Icon"', `"@${app.project}/ui"`);
|
|
479
|
+
const rendered = rel.includes(APP_DIR) ? variableSkeletonFiles(context, rel, source) : fixedSkeletonFiles(context, rel, source);
|
|
480
|
+
files.push(...rendered);
|
|
412
481
|
}
|
|
413
482
|
return files;
|
|
414
483
|
}
|
|
415
484
|
|
|
416
|
-
/** The canonical
|
|
485
|
+
/** The canonical full Work workspace, catalog and feature nodes an edition upgrade may need. */
|
|
417
486
|
export function scaffoldWorkSeeds(project) {
|
|
418
487
|
return skeletonDirectory('app', 'skeleton', { project }, {},
|
|
419
|
-
rel => rel === '.starciwork/index.yaml' || rel.startsWith('.starciwork/features/'));
|
|
488
|
+
rel => rel === '.starciwork/workspace.yaml' || rel === '.starciwork/index.yaml' || rel.startsWith('.starciwork/features/'));
|
|
420
489
|
}
|
|
421
490
|
|
|
422
491
|
/**
|
|
@@ -433,7 +502,7 @@ function skeletonOf(scope, app, vars) {
|
|
|
433
502
|
for (const entry of scope === 'fe' ? app.sides.fe.apps : []) {
|
|
434
503
|
if (!unique.some(file => file.path.startsWith(`fe/apps/${entry.name}/`))) throw new ScaffoldError('HFS_SCAFFOLD_SKELETON_MISSING', `no skeleton templates for the fe app ${entry.name}`);
|
|
435
504
|
}
|
|
436
|
-
return unique;
|
|
505
|
+
return scope === 'fe' ? [...new Map(callbackSourceFiles(unique, app).map(file => [file.path, file])).values()] : unique;
|
|
437
506
|
}
|
|
438
507
|
|
|
439
508
|
/** The npm step that resolves the lockfile of a new app, exactly as the error names it. */
|
|
@@ -546,17 +615,40 @@ function scaffoldWrites(root, original) {
|
|
|
546
615
|
};
|
|
547
616
|
}
|
|
548
617
|
|
|
618
|
+
/** Generate the lite database types and translate generation errors into the scaffold failure contract. */
|
|
619
|
+
function emitScaffoldDatabaseTypes(root, name, writes, emitTypes) {
|
|
620
|
+
try {
|
|
621
|
+
const text = emitTypes({ root });
|
|
622
|
+
if (typeof text !== 'string' || !text.trim()) throw new Error('the Supabase CLI returned no database types');
|
|
623
|
+
writes.write(dbTypesPath, text);
|
|
624
|
+
} catch (error) {
|
|
625
|
+
throw new ScaffoldError('HFS_SCAFFOLD_TYPES_FAILED', `Supabase database types could not be generated for ${root} (${String(error?.message ?? error)}). Start the local Supabase stack and run starci app scaffold ${name} --edition lite again`);
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
|
|
549
629
|
/**
|
|
550
630
|
* `starci app scaffold <name>`: writes the new app under `into`, resolves its lockfile with npm (`lock`, npmLock), and returns
|
|
551
631
|
* `{ root, files }` (app-relative paths, sorted). `presets` is what sync loads from the installed @starci/jest-preset (the Sonar
|
|
552
632
|
* exclusions); the CLI passes the one it resolves. Failure removes only scaffold-owned entries, retaining an existing .git.
|
|
553
633
|
*/
|
|
554
|
-
|
|
634
|
+
/** Seal declared starter members to a fresh app recipient through the scaffold rollback owner. */
|
|
635
|
+
function initializeScaffoldSecrets(root, writes) {
|
|
636
|
+
if (!declaredSealedMembers(root).length) return [];
|
|
637
|
+
const write = (file, content) => writes.write(path.relative(root, file), content);
|
|
638
|
+
const initialized = initializeAppIdentity(root, { write });
|
|
639
|
+
const materialized = materializeDeclaredPlaceholders(root, { recipient: initialized.recipient, write });
|
|
640
|
+
return [...initialized.files, ...materialized.members];
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
export function scaffoldApp({ name, into, presets, edition = 'full', authCallback = false, registryVisibility = 'public', manifest = loadSlotManifest(), pins = bundledPins(), lock = npmLock, emitTypes = generateDbTypes, now = () => new Date() }) {
|
|
555
644
|
if (!NAME.test(String(name))) throw new ScaffoldError('HFS_SCAFFOLD_NAME_INVALID', `the app name ${name} must be kebab-case (a project name: ${NAME})`);
|
|
556
645
|
const root = path.resolve(into, name);
|
|
557
646
|
const original = fs.lstatSync(root, { throwIfNoEntry: false });
|
|
558
647
|
if (original && !emptyUnbornGit(root, original)) throw new ScaffoldError('HFS_SCAFFOLD_EXISTS', `${root} already exists; only a plain directory containing solely .git with unborn main and an empty index can be scaffolded`);
|
|
648
|
+
if (!['public', 'private'].includes(registryVisibility)) throw new ScaffoldError('HFS_SCAFFOLD_REGISTRY_VISIBILITY', `--registry-visibility accepts public or private (got ${registryVisibility})`);
|
|
649
|
+
if (typeof authCallback !== 'boolean') throw new ScaffoldError('HFS_SCAFFOLD_NAME_INVALID', 'authCallback must be a boolean');
|
|
559
650
|
const declaration = starterDeclaration(name, manifest, edition);
|
|
651
|
+
if (authCallback) enableAuthCallback(declaration);
|
|
560
652
|
const app = resolveRepoDeclaration(manifest, declaration);
|
|
561
653
|
const pkg = packageManifest(name, pins, app.edition);
|
|
562
654
|
const timestamp = now().toISOString().replace(/\D/g, '').slice(0, 14);
|
|
@@ -569,14 +661,14 @@ export function scaffoldApp({ name, into, presets, edition = 'full', manifest =
|
|
|
569
661
|
path: `fe/apps/${entry.name}/src/modules/types/ambient/styles.d.ts`,
|
|
570
662
|
content: '/** Declares stylesheets loaded by the Next bundler; non-CSS side-effect imports remain checked. */\ndeclare module "*.css" {}\n',
|
|
571
663
|
})),
|
|
572
|
-
...app.sides.fe.apps.map(entry => ({ path: `fe/apps/${entry.name}/package.json`, content: packageJsonText(feAppManifest(name, entry.name, pins, app.edition, { core: coreFeApps([entry]).length === 1 })) })),
|
|
664
|
+
...app.sides.fe.apps.map(entry => ({ path: `fe/apps/${entry.name}/package.json`, content: packageJsonText(feAppManifest(name, entry.name, pins, app.edition, { core: coreFeApps([entry]).length === 1, authCallback })) })),
|
|
573
665
|
...imageFiles(app),
|
|
574
666
|
...(app.edition === 'lite' ? [] : Object.keys(FE_PACKAGES).flatMap(pkg => [
|
|
575
667
|
{ path: `fe/packages/${name}-${pkg}/package.json`, content: packageJsonText(fePackageManifest(name, pkg, pins)) },
|
|
576
668
|
{ path: `fe/packages/${name}-${pkg}/tsconfig.json`, content: jsonText(fePackageTsconfig()) },
|
|
577
669
|
{ path: `fe/packages/${name}-${pkg}/tsconfig.build.json`, content: jsonText(fePackageBuildTsconfig()) },
|
|
578
670
|
])),
|
|
579
|
-
...['app', 'be', 'fe'].flatMap(scope => skeletonOf(scope, app, { sonarGate: parseYaml(fs.readFileSync(SONAR_GATE_FILE, 'utf8')).
|
|
671
|
+
...['app', 'be', 'fe'].flatMap(scope => skeletonOf(scope, app, { sonarGate: sonarGateName(parseYaml(fs.readFileSync(SONAR_GATE_FILE, 'utf8')), app.edition), timestamp, registryVisibility, ...supabasePortVars(name) })),
|
|
580
672
|
];
|
|
581
673
|
const writes = scaffoldWrites(root, original);
|
|
582
674
|
try {
|
|
@@ -584,19 +676,12 @@ export function scaffoldApp({ name, into, presets, edition = 'full', manifest =
|
|
|
584
676
|
const targets = renderTargets(declaration, presets, { manifest, source: appSource(root) });
|
|
585
677
|
for (const target of targets) writes.claim(target.path);
|
|
586
678
|
writeTargets(root, targets);
|
|
587
|
-
if (app.edition === 'lite')
|
|
588
|
-
|
|
589
|
-
const text = emitTypes({ root });
|
|
590
|
-
if (typeof text !== 'string' || !text.trim()) throw new Error('the Supabase CLI returned no database types');
|
|
591
|
-
writes.write(dbTypesPath, text);
|
|
592
|
-
} catch (error) {
|
|
593
|
-
throw new ScaffoldError('HFS_SCAFFOLD_TYPES_FAILED', `Supabase database types could not be generated for ${root} (${String(error?.message ?? error)}). Start the local Supabase stack and run starci app scaffold ${name} --edition lite again`);
|
|
594
|
-
}
|
|
595
|
-
}
|
|
679
|
+
if (app.edition === 'lite') emitScaffoldDatabaseTypes(root, name, writes, emitTypes);
|
|
680
|
+
const secretFiles = initializeScaffoldSecrets(root, writes);
|
|
596
681
|
let locked;
|
|
597
682
|
try { locked = lock(root); } finally { writes.lockfile(); }
|
|
598
683
|
if (!locked.ok) throw new ScaffoldError('HFS_SCAFFOLD_LOCK_FAILED', `\`${LOCK_STEP}\` could not resolve the lockfile of ${root} (${locked.detail}). Check the network and the npm registry, then run starci app scaffold ${name} again`);
|
|
599
|
-
return { root, files: [...new Set([...files.map(file => file.path), ...targets.map(target => target.path), ...(app.edition === 'lite' ? [dbTypesPath] : []), 'package-lock.json'])].sort(byCodeUnit) };
|
|
684
|
+
return { root, files: [...new Set([...files.map(file => file.path), ...targets.map(target => target.path), ...secretFiles, ...(app.edition === 'lite' ? [dbTypesPath] : []), 'package-lock.json'])].sort(byCodeUnit) };
|
|
600
685
|
} catch (error) {
|
|
601
686
|
const held = writes.rollback();
|
|
602
687
|
if (held.length) error.message += `; cleanup retained replaced or occupied entries: ${held.join(', ')}`;
|
|
@@ -14,9 +14,9 @@ export class EditionRefusal extends Error {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
* The refusal of a pattern noun in a lite app whose topic carries a `liteAdapter` (
|
|
18
|
-
* but the package
|
|
19
|
-
*
|
|
17
|
+
* The refusal of a pattern noun in a lite app whose topic carries a `liteAdapter` (ruling:R212/case-1, amended by ruling:R212/case-4):
|
|
18
|
+
* lite has the pattern, but the package carries only its full-adapter templates, so generating them would write adapter paths
|
|
19
|
+
* unavailable in lite. The pattern is written by hand using the topic's declared lite adapter until the package carries a lite template.
|
|
20
20
|
*/
|
|
21
21
|
export class LiteAdapterRefusal extends EditionRefusal {
|
|
22
22
|
constructor(command, topics) {
|
package/scaffold/image.mjs
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
// (templates/<side>/image/<kind>, the same render starci app scaffold uses). It never overwrites a file.
|
|
3
3
|
import fs from 'node:fs';
|
|
4
4
|
import path from 'node:path';
|
|
5
|
-
import { imageFiles, loadHfs, validateHfs } from '../sync/index.mjs';
|
|
5
|
+
import { appSource, imageFiles, loadHfs, validateHfs } from '../sync/index.mjs';
|
|
6
6
|
|
|
7
7
|
/** Writes the missing Dockerfiles of the app at `repoRoot` (the folder of hfs.json); the app-relative paths written. */
|
|
8
8
|
export function newImages({ repoRoot }) {
|
|
9
|
-
const files = imageFiles(validateHfs(loadHfs(repoRoot)));
|
|
9
|
+
const files = imageFiles(validateHfs(loadHfs(repoRoot)), appSource(repoRoot));
|
|
10
10
|
const written = [];
|
|
11
11
|
for (const file of files) {
|
|
12
12
|
const target = path.join(repoRoot, ...file.path.split('/'));
|
|
@@ -32,7 +32,8 @@ const REGISTRATIONS = Object.freeze({
|
|
|
32
32
|
{
|
|
33
33
|
file: "be/src/modules/platform/database/index.ts",
|
|
34
34
|
source: "./primary.decorators",
|
|
35
|
-
|
|
35
|
+
// PRIMARY_ENTITY_MANAGER: the token a generated table service's unit spec provides its EntityManager double under.
|
|
36
|
+
names: ["InjectPrimaryEntityManager", "PRIMARY_ENTITY_MANAGER"],
|
|
36
37
|
},
|
|
37
38
|
],
|
|
38
39
|
webhook: [
|
package/scaffold/service.mjs
CHANGED
|
@@ -319,7 +319,7 @@ const writeNew = (repoRoot, relative, text) => {
|
|
|
319
319
|
|
|
320
320
|
/** `starci app new spec be/<file>.service.ts` at the app root: writes the spec skeleton of an existing service; returns the created app-relative paths. */
|
|
321
321
|
export function newSpec({ repoRoot: appRoot, file, ts, manifest = loadSlotManifest() }) {
|
|
322
|
-
// A unit spec belongs to both editions (
|
|
322
|
+
// A unit spec belongs to both editions (ruling:R212/case-1, amended by ruling:R212/case-4): a lite back end keeps full's unit specs.
|
|
323
323
|
const { beRoot: repoRoot } = backEndOf(appRoot, manifest);
|
|
324
324
|
const relative = belowBackEnd(file);
|
|
325
325
|
if (!relative.endsWith('.service.ts')) throw new ScaffoldError('HFS_NEW_NOT_A_SERVICE', `${relative} is not a *.service.ts file: only services have a unit spec`);
|
|
@@ -333,7 +333,7 @@ export function newSpec({ repoRoot: appRoot, file, ts, manifest = loadSlotManife
|
|
|
333
333
|
|
|
334
334
|
/** `starci app new service be/<dir> <name> [--inject ...]` at the app root: writes the service and its spec skeleton; returns the created app-relative paths. */
|
|
335
335
|
export function newService({ repoRoot: appRoot, dir, name, inject = [], ts, manifest = loadSlotManifest() }) {
|
|
336
|
-
// The service and its unit spec belong to both editions (
|
|
336
|
+
// The service and its unit spec belong to both editions (ruling:R212/case-1, amended by ruling:R212/case-4).
|
|
337
337
|
const { beRoot: repoRoot } = backEndOf(appRoot, manifest);
|
|
338
338
|
if (!SERVICE_NAME.test(name)) throw new ScaffoldError('HFS_NEW_NAME_INVALID', `the service name ${name} must be kebab-case (member-profile), without the .service suffix`);
|
|
339
339
|
const relative = path.posix.join(belowBackEnd(dir), `${name}.service.ts`);
|