@starci/hfs 4.0.8 → 4.0.9
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 +9 -0
- package/README.md +81 -39
- package/emit/contracts.mjs +56 -9
- package/emit/db-types.mjs +169 -0
- package/emit/events.mjs +41 -0
- package/emit/operations-worker.mjs +1 -1
- package/emit/operations.mjs +2 -2
- package/emit/schema-worker.mjs +1 -1
- package/lint/bound-sys.cjs +50 -0
- package/lint/run.mjs +53 -19
- package/package.json +14 -9
- package/report/sonar.mjs +8 -8
- package/runtime/engine/config.mjs +494 -0
- package/runtime/engine/invalid-config.mjs +15 -0
- package/runtime/engine/orca-config.mjs +27 -0
- package/runtime/knowledge/hfs/canon-pins.yaml +160 -29
- package/runtime/knowledge/hfs/peer-integrations.yaml +2 -2
- package/runtime/knowledge/hfs/rules.yaml +2059 -0
- package/runtime/knowledge/hfs/slots.yaml +912 -120
- package/runtime/knowledge/patterns/be/api.yaml +369 -0
- package/runtime/knowledge/patterns/be/cli.yaml +297 -0
- package/runtime/knowledge/patterns/be/domain.yaml +113 -0
- package/runtime/knowledge/patterns/be/event-bus.yaml +285 -0
- package/runtime/knowledge/patterns/be/jobs.yaml +261 -0
- package/runtime/knowledge/patterns/be/projections.yaml +178 -0
- package/runtime/knowledge/patterns/be/queues.yaml +236 -0
- package/runtime/knowledge/patterns/be/reactors.yaml +140 -0
- package/runtime/knowledge/patterns/be/realtime.yaml +222 -0
- package/runtime/knowledge/patterns/be/saga.yaml +248 -0
- package/runtime/knowledge/patterns/be/webhooks.yaml +221 -0
- package/runtime/knowledge/patterns/fe/folder.yaml +131 -25
- package/runtime/knowledge/sonar-gate.yaml +52 -18
- package/runtime/modules/kernel/failure-codes.yaml +571 -51
- package/runtime/modules/models/registry.yaml +591 -0
- package/runtime/modules/models/runtimes.yaml +701 -0
- package/runtime/scripts/api/fs/forbidden-root.mjs +51 -0
- package/runtime/scripts/api/fs/is-link-like.mjs +25 -0
- package/runtime/scripts/api/fs/lib.mjs +10 -2
- package/runtime/scripts/api/fs/safe-remove.mjs +12 -132
- package/runtime/scripts/api/git/config-get.mjs +10 -0
- package/runtime/scripts/api/git/diff.mjs +5 -0
- package/runtime/scripts/api/git/lib.mjs +16 -26
- package/runtime/scripts/api/git/log.mjs +5 -0
- package/runtime/scripts/api/git/ls-files.mjs +6 -0
- package/runtime/scripts/api/git/ls-tree.mjs +5 -0
- package/runtime/scripts/api/git/merge-base.mjs +9 -0
- package/runtime/scripts/api/git/remote.mjs +5 -0
- package/runtime/scripts/api/git/rev-parse-query.mjs +5 -0
- package/runtime/scripts/api/git/show.mjs +6 -0
- package/runtime/scripts/api/sops/decrypt.mjs +9 -5
- package/runtime/scripts/api/sops/lib.mjs +35 -0
- package/runtime/scripts/api/sops/seal.mjs +18 -0
- package/runtime/scripts/hfs/architecture/ast-walks.mjs +220 -0
- package/runtime/scripts/hfs/architecture/backend.mjs +16 -23
- package/runtime/scripts/hfs/architecture/background-unowned.mjs +16 -34
- package/runtime/scripts/hfs/architecture/client-reaches-server.mjs +3 -1
- package/runtime/scripts/hfs/architecture/clones.mjs +4 -4
- package/runtime/scripts/hfs/architecture/config.mjs +9 -6
- package/runtime/scripts/hfs/architecture/connection-map.mjs +20 -8
- package/runtime/scripts/hfs/architecture/context-coupling.mjs +88 -0
- package/runtime/scripts/hfs/architecture/context-map.mjs +237 -0
- package/runtime/scripts/hfs/architecture/context-owner.mjs +82 -0
- package/runtime/scripts/hfs/architecture/context-platform-tables.mjs +47 -0
- package/runtime/scripts/hfs/architecture/context-transaction.mjs +60 -0
- package/runtime/scripts/hfs/architecture/contract-fixture-guard.mjs +4 -10
- package/runtime/scripts/hfs/architecture/contracts.mjs +33 -162
- package/runtime/scripts/hfs/architecture/dead-exports.mjs +58 -29
- package/runtime/scripts/hfs/architecture/doc-language.mjs +1 -1
- package/runtime/scripts/hfs/architecture/entrypoint.mjs +2 -1
- package/runtime/scripts/hfs/architecture/fe-slot-allows.mjs +1 -1
- package/runtime/scripts/hfs/architecture/feature-shape.mjs +5 -2
- package/runtime/scripts/hfs/architecture/framework-pinned.mjs +1 -1
- package/runtime/scripts/hfs/architecture/frontend.mjs +17 -43
- package/runtime/scripts/hfs/architecture/hfs.mjs +24 -39
- package/runtime/scripts/hfs/architecture/i18n-keys.mjs +1 -1
- package/runtime/scripts/hfs/architecture/index.mjs +17 -4
- package/runtime/scripts/hfs/architecture/machine-ast.mjs +44 -11
- package/runtime/scripts/hfs/architecture/managed-scripts.mjs +27 -0
- package/runtime/scripts/hfs/architecture/module-per-transport.mjs +30 -6
- package/runtime/scripts/hfs/architecture/next-data.mjs +22 -63
- package/runtime/scripts/hfs/architecture/owners.mjs +35 -15
- package/runtime/scripts/hfs/architecture/register-once.mjs +2 -1
- package/runtime/scripts/hfs/architecture/registration.mjs +23 -81
- package/runtime/scripts/hfs/architecture/required-files.mjs +20 -12
- package/runtime/scripts/hfs/architecture/schema-owner.mjs +17 -114
- package/runtime/scripts/hfs/architecture/server-action.mjs +24 -0
- package/runtime/scripts/hfs/architecture/side-boundary.mjs +16 -0
- package/runtime/scripts/hfs/architecture/source-names.mjs +27 -147
- package/runtime/scripts/hfs/architecture/sql-owner.mjs +59 -18
- package/runtime/scripts/hfs/architecture/sql-returning.mjs +64 -0
- package/runtime/scripts/hfs/architecture/supabase-ast.mjs +111 -0
- package/runtime/scripts/hfs/architecture/supabase-be.mjs +131 -0
- package/runtime/scripts/hfs/architecture/supabase-tables.mjs +42 -0
- package/runtime/scripts/hfs/architecture/supabase.mjs +434 -0
- package/runtime/scripts/hfs/architecture/surface.mjs +9 -3
- package/runtime/scripts/hfs/architecture/test-world-files.mjs +9 -19
- package/runtime/scripts/hfs/architecture/tiers.mjs +47 -5
- package/runtime/scripts/hfs/architecture/transport-owner.mjs +3 -3
- package/runtime/scripts/hfs/architecture/typescript.mjs +12 -26
- package/runtime/scripts/hfs/architecture.mjs +4 -4
- package/runtime/scripts/hfs/check.mjs +75 -72
- package/runtime/scripts/hfs/coverage-scope.mjs +162 -0
- package/runtime/scripts/hfs/declaration-shape.mjs +62 -0
- package/runtime/scripts/hfs/declaration-slots.mjs +75 -0
- package/runtime/scripts/hfs/edition-slots.mjs +66 -0
- package/runtime/scripts/hfs/manifest-shape.mjs +109 -32
- package/runtime/scripts/hfs/param-names.mjs +18 -0
- package/runtime/scripts/hfs/path-findings.mjs +1 -1
- package/runtime/scripts/hfs/repo-identity.mjs +9 -6
- package/runtime/scripts/hfs/rule-params-shape.mjs +50 -0
- package/runtime/scripts/hfs/rules/app-root.mjs +51 -0
- package/runtime/scripts/hfs/rules/cli.mjs +37 -0
- package/runtime/scripts/hfs/rules/contract-compat.mjs +71 -0
- package/runtime/scripts/hfs/rules/contract.mjs +10 -9
- package/runtime/scripts/hfs/rules/database-config.mjs +102 -0
- package/runtime/scripts/hfs/rules/database-constants.mjs +13 -0
- package/runtime/scripts/hfs/rules/database-migrations.mjs +111 -0
- package/runtime/scripts/hfs/rules/database-plpgsql.mjs +233 -0
- package/runtime/scripts/hfs/rules/database-sql.mjs +336 -0
- package/runtime/scripts/hfs/rules/database.mjs +68 -0
- package/runtime/scripts/hfs/rules/deps.mjs +1 -1
- package/runtime/scripts/hfs/rules/docker.mjs +259 -0
- package/runtime/scripts/hfs/rules/edition.mjs +111 -0
- package/runtime/scripts/hfs/rules/event-bus.mjs +153 -0
- package/runtime/scripts/hfs/rules/fe-contract-documents.mjs +1 -1
- package/runtime/scripts/hfs/rules/fe-no-tests.mjs +6 -5
- package/runtime/scripts/hfs/rules/frontend-tree.mjs +9 -9
- package/runtime/scripts/hfs/rules/integration-specs.mjs +3 -6
- package/runtime/scripts/hfs/rules/kinds.mjs +84 -0
- package/runtime/scripts/hfs/rules/lint-suppression.mjs +1 -1
- package/runtime/scripts/hfs/rules/monorepo.mjs +179 -0
- package/runtime/scripts/hfs/rules/peer-integrations.mjs +3 -3
- package/runtime/scripts/hfs/rules/pipeline.mjs +11 -21
- package/runtime/scripts/hfs/rules/proof-commands.mjs +2 -2
- package/runtime/scripts/hfs/rules/read.mjs +1 -1
- package/runtime/scripts/hfs/rules/repo-local-checks.mjs +2 -2
- package/runtime/scripts/hfs/rules/saga.mjs +170 -0
- package/runtime/scripts/hfs/rules/secrets.mjs +3 -3
- package/runtime/scripts/hfs/rules/services.mjs +220 -0
- package/runtime/scripts/hfs/rules/spec-placement.mjs +1 -1
- package/runtime/scripts/hfs/rules/stacks.mjs +3 -3
- package/runtime/scripts/hfs/rules/supabase-secrets.mjs +89 -0
- package/runtime/scripts/hfs/rules/test-topology.mjs +2 -2
- package/runtime/scripts/hfs/secret.mjs +175 -0
- package/runtime/scripts/hfs/slots.mjs +78 -108
- package/runtime/scripts/hfs/sql/pg-parse.mjs +46 -0
- package/runtime/scripts/hfs/test-world-slot.mjs +6 -0
- package/runtime/scripts/hfs/tree.mjs +5 -4
- package/runtime/scripts/hfs/typescript-programs.mjs +0 -5
- package/runtime/scripts/hfs/view.mjs +3 -2
- package/runtime/scripts/lib/dockerfile.mjs +124 -0
- package/runtime/scripts/lib/env.mjs +10 -0
- package/runtime/scripts/lib/event-contract.mjs +103 -0
- package/runtime/scripts/lib/git.mjs +36 -0
- package/runtime/scripts/lib/graphql-contract.mjs +1 -1
- package/runtime/scripts/lib/i18n.mjs +86 -0
- package/runtime/scripts/lib/json.mjs +13 -3
- package/runtime/scripts/lib/language.mjs +24 -5
- package/runtime/scripts/lib/list.mjs +20 -0
- package/runtime/scripts/lib/package-at.mjs +37 -0
- package/runtime/scripts/lib/path-key.mjs +57 -2
- package/runtime/scripts/lib/read-text.mjs +34 -0
- package/runtime/scripts/lib/regex.mjs +4 -0
- package/runtime/scripts/lib/same-text.mjs +5 -0
- package/runtime/scripts/lib/secret-patterns.mjs +4 -3
- package/runtime/scripts/lib/sleep-sync.mjs +2 -1
- package/runtime/scripts/lib/sops-envelope.mjs +58 -0
- package/runtime/scripts/lib/stack-services.mjs +7 -31
- package/runtime/scripts/lib/ts-ast.mjs +35 -0
- package/runtime/scripts/lib/walk.mjs +4 -3
- package/scaffold/add-app.mjs +174 -0
- package/scaffold/add-cli-lite.mjs +257 -0
- package/scaffold/add-inbox-lite.mjs +314 -0
- package/scaffold/add-table.mjs +344 -0
- package/scaffold/add.mjs +299 -0
- package/scaffold/app.mjs +358 -69
- package/scaffold/edition-gate.mjs +25 -0
- package/scaffold/image.mjs +19 -0
- package/scaffold/lite-exports.mjs +186 -0
- package/scaffold/service.mjs +32 -26
- package/scaffold/supabase-ports.mjs +26 -0
- package/src/main.mjs +327 -0
- package/sync/cli.mjs +6 -9
- package/sync/format.mjs +1 -1
- package/sync/hygiene.mjs +10 -10
- package/sync/index.mjs +167 -104
- package/sync/managed.mjs +19 -11
- package/sync/sonar-key.mjs +5 -0
- package/templates/app/ci-workflows/github/workflows/ci.yml +14 -14
- package/templates/app/ci-workflows/github/workflows/images.yml +37 -0
- package/templates/app/ci-workflows/sonar-steps.yml +9 -0
- package/templates/app/ci-workflows-lite/github/workflows/ci.yml +66 -0
- package/templates/app/ci-workflows-lite/github/workflows/db-deploy.yml +31 -0
- package/templates/app/ci-workflows-lite/github/workflows/images.yml +37 -0
- package/templates/app/codegen-lite/scripts/codegen.mjs +32 -0
- package/templates/app/docker-ignore/dockerignore +50 -0
- package/templates/app/gitignore-lite +35 -0
- package/templates/app/hooks/husky/pre-commit +3 -8
- package/templates/app/hooks/husky/pre-push +45 -6
- package/templates/app/package-scripts/core.json +8 -0
- package/templates/app/package-scripts/package.json +3 -10
- package/templates/app/package-scripts-lite/package.json +15 -0
- package/templates/app/quality-config/codecov.yml +15 -3
- package/templates/app/quality-config/sonar-base.properties +4 -0
- package/templates/app/quality-config/sonar-project.properties +1 -4
- package/templates/app/quality-config-lite/sonar-project.properties +5 -0
- package/templates/app/skeleton/.starcistacks/dev/seeds/primary-notes.sql +5 -0
- package/templates/app/skeleton/.starciwork/features/system-health/index.yaml +4 -0
- package/templates/app/skeleton/.starciwork/{features/index.yaml → index.yaml} +2 -2
- package/templates/app/skeleton/README.md +7 -5
- package/templates/app/skeleton-lite/.sops.yaml +3 -0
- package/templates/app/skeleton-lite/.starcistacks/dev/environment.json +5 -0
- package/templates/app/skeleton-lite/.starcistacks/dev/secrets/.gitkeep +1 -0
- package/templates/app/skeleton-lite/.starciwork/shell/index.yaml +55 -0
- package/templates/app/skeleton-lite/README.md +40 -0
- package/templates/app/skeleton-lite/supabase/config.toml +41 -0
- package/templates/app/skeleton-lite/supabase/migrations/__timestamp___baseline.sql +56 -0
- package/templates/app/skeleton-lite/supabase/seed.sql +0 -0
- package/templates/app/task-graph/turbo.json +23 -0
- package/templates/app/tool-config-lite/prettierignore +2 -0
- package/templates/app/tool-config-lite/prettierrc +1 -0
- package/templates/app/upgrade-full/.starcistacks/application-stacks.yaml +38 -0
- package/templates/app/upgrade-full/.starcistacks/dev/README.md +10 -0
- package/templates/app/upgrade-full/.starcistacks/dev/infra/compose/api.yaml +13 -0
- package/templates/app/upgrade-full/.starcistacks/dev/infra/compose/compose.yaml +3 -0
- package/templates/app/upgrade-full/.starcistacks/dev/infra/compose/postgres.yaml +12 -0
- package/templates/app/upgrade-full/.starcistacks/dev/infra/metadata.json +7 -0
- package/templates/be/common/main-listen.ts.partial +14 -0
- package/templates/be/common/sql-ident.ts.partial +7 -0
- package/templates/be/common/sql-tag.ts.partial +5 -0
- package/templates/be/image/api/Dockerfile +38 -0
- package/templates/be/image/cli/Dockerfile +38 -0
- package/templates/be/image/worker/Dockerfile +36 -0
- package/templates/be/inbox/database-client.ts.tpl +50 -0
- package/templates/be/inbox/index.ts.tpl +2 -0
- package/templates/be/inbox/migration.sql.tpl +29 -0
- package/templates/be/inbox/module-definition.ts.tpl +6 -0
- package/templates/be/inbox/module.ts.tpl +14 -0
- package/templates/be/inbox/options.ts.tpl +2 -0
- package/templates/be/inbox/service.ts.tpl +33 -0
- package/templates/be/inbox/sql.ts.tpl +16 -0
- package/templates/be/inbox/webhook-door.ts.tpl +36 -0
- package/templates/be/patterns/api/application.command.http.ts.tpl +10 -0
- package/templates/be/patterns/api/application.command.ts.tpl +10 -0
- package/templates/be/patterns/api/application.contracts.ts.tpl +11 -0
- package/templates/be/patterns/api/application.handler.http.ts.tpl +22 -0
- package/templates/be/patterns/api/application.handler.ts.tpl +22 -0
- package/templates/be/patterns/api/feature.index.http.ts.tpl +1 -0
- package/templates/be/patterns/api/feature.index.ts.tpl +1 -0
- package/templates/be/patterns/api/feature.module.ts.tpl +6 -0
- package/templates/be/patterns/api/graphql.input.ts.tpl +13 -0
- package/templates/be/patterns/api/graphql.mapper.ts.tpl +9 -0
- package/templates/be/patterns/api/graphql.module.ts.tpl +7 -0
- package/templates/be/patterns/api/graphql.resolver.ts.tpl +27 -0
- package/templates/be/patterns/api/graphql.type.ts.tpl +9 -0
- package/templates/be/patterns/api/http.controller.ts.tpl +27 -0
- package/templates/be/patterns/api/http.mapper.ts.tpl +9 -0
- package/templates/be/patterns/api/http.module.ts.tpl +7 -0
- package/templates/be/patterns/api/http.request.ts.tpl +10 -0
- package/templates/be/patterns/api/http.response.ts.tpl +5 -0
- package/templates/be/patterns/cli/group.cli.spec.ts.tpl +15 -0
- package/templates/be/patterns/cli/group.cli.ts.tpl +11 -0
- package/templates/be/patterns/cli/group.module.ts.tpl +7 -0
- package/templates/be/patterns/cli/sub.run.cli.spec.ts.tpl +17 -0
- package/templates/be/patterns/cli/sub.run.cli.ts.tpl +15 -0
- package/templates/be/patterns/event-bus/platform/errors/event-bus.error.ts.tpl +22 -0
- package/templates/be/patterns/event-bus/platform/event-bus.config.ts.tpl +19 -0
- package/templates/be/patterns/event-bus/platform/event-bus.contracts.ts.tpl +58 -0
- package/templates/be/patterns/event-bus/platform/event-bus.decorators.ts.tpl +46 -0
- package/templates/be/patterns/event-bus/platform/event-bus.log-events.ts.tpl +12 -0
- package/templates/be/patterns/event-bus/platform/event-bus.module-definition.ts.tpl +10 -0
- package/templates/be/patterns/event-bus/platform/event-bus.module.ts.tpl +52 -0
- package/templates/be/patterns/event-bus/platform/event-bus.options.ts.tpl +19 -0
- package/templates/be/patterns/event-bus/platform/event-bus.port.ts.tpl +28 -0
- package/templates/be/patterns/event-bus/platform/event-bus.service.spec.ts.tpl +165 -0
- package/templates/be/patterns/event-bus/platform/event-bus.service.ts.tpl +93 -0
- package/templates/be/patterns/event-bus/platform/event-envelope.policy.spec.ts.tpl +90 -0
- package/templates/be/patterns/event-bus/platform/event-envelope.policy.ts.tpl +58 -0
- package/templates/be/patterns/event-bus/platform/event-relay.service.spec.ts.tpl +136 -0
- package/templates/be/patterns/event-bus/platform/event-relay.service.ts.tpl +56 -0
- package/templates/be/patterns/event-bus/platform/event-runner.service.spec.ts.tpl +272 -0
- package/templates/be/patterns/event-bus/platform/event-runner.service.ts.tpl +128 -0
- package/templates/be/patterns/event-bus/platform/event-transport.port.ts.tpl +180 -0
- package/templates/be/patterns/event-bus/platform/event.policy.spec.ts.tpl +67 -0
- package/templates/be/patterns/event-bus/platform/event.policy.ts.tpl +38 -0
- package/templates/be/patterns/event-bus/platform/index.ts.tpl +11 -0
- package/templates/be/patterns/event-bus/platform/kafka-event-transport.client.spec.ts.tpl +348 -0
- package/templates/be/patterns/event-bus/platform/kafka-event-transport.client.ts.tpl +241 -0
- package/templates/be/patterns/event-bus/platform/messages/event-bus.messages.ts.tpl +15 -0
- package/templates/be/patterns/event-bus/platform/persistence/connection.ts.tpl +8 -0
- package/templates/be/patterns/event-bus/platform/persistence/entities/event-outbox.entity.ts.tpl +37 -0
- package/templates/be/patterns/event-bus/platform/persistence/event-bus.rows.ts.tpl +11 -0
- package/templates/be/patterns/event-bus/platform/persistence/event-bus.sql.ts.tpl +12 -0
- package/templates/be/patterns/event-bus/platform/persistence/migrations/1789800009000-create-event-outbox.ts.tpl +26 -0
- package/templates/be/patterns/jobs/job.index.ts.tpl +1 -0
- package/templates/be/patterns/jobs/job.module.ts.tpl +6 -0
- package/templates/be/patterns/jobs/job.processor.ts.tpl +20 -0
- package/templates/be/patterns/jobs/job.queue.module.ts.tpl +20 -0
- package/templates/be/patterns/jobs/job.step.ts.tpl +19 -0
- package/templates/be/patterns/jobs/platform/fenced.processor.spec.ts.tpl +31 -0
- package/templates/be/patterns/jobs/platform/fenced.processor.ts.tpl +13 -0
- package/templates/be/patterns/jobs/platform/job-claim.service.spec.ts.tpl +150 -0
- package/templates/be/patterns/jobs/platform/job-claim.service.ts.tpl +100 -0
- package/templates/be/patterns/jobs/platform/job-runner.service.spec.ts.tpl +138 -0
- package/templates/be/patterns/jobs/platform/job-runner.service.ts.tpl +69 -0
- package/templates/be/patterns/jobs/platform/jobs.config.ts.tpl +11 -0
- package/templates/be/patterns/jobs/platform/jobs.contracts.ts.tpl +62 -0
- package/templates/be/patterns/jobs/platform/jobs.decorators.ts.tpl +31 -0
- package/templates/be/patterns/jobs/platform/jobs.error.ts.tpl +22 -0
- package/templates/be/patterns/jobs/platform/jobs.index.ts.tpl +11 -0
- package/templates/be/patterns/jobs/platform/jobs.log-events.ts.tpl +9 -0
- package/templates/be/patterns/jobs/platform/jobs.messages.ts.tpl +15 -0
- package/templates/be/patterns/jobs/platform/jobs.module-definition.ts.tpl +10 -0
- package/templates/be/patterns/jobs/platform/jobs.module.ts.tpl +32 -0
- package/templates/be/patterns/jobs/platform/jobs.options.ts.tpl +11 -0
- package/templates/be/patterns/jobs/platform/jobs.port.ts.tpl +36 -0
- package/templates/be/patterns/jobs/platform/persistence.connection.ts.tpl +8 -0
- package/templates/be/patterns/jobs/platform/persistence.job.entity.ts.tpl +53 -0
- package/templates/be/patterns/jobs/platform/persistence.jobs.rows.ts.tpl +13 -0
- package/templates/be/patterns/jobs/platform/persistence.jobs.sql.ts.tpl +33 -0
- package/templates/be/patterns/jobs/platform/persistence.migration.ts.tpl +29 -0
- package/templates/be/patterns/outbox/platform/index.ts.tpl +2 -0
- package/templates/be/patterns/outbox/platform/outbox-relay.policy.spec.ts.tpl +96 -0
- package/templates/be/patterns/outbox/platform/outbox-relay.policy.ts.tpl +78 -0
- package/templates/be/patterns/outbox/platform/outbox.log-events.ts.tpl +5 -0
- package/templates/be/patterns/projections/migration.ts.tpl +18 -0
- package/templates/be/patterns/projections/persistence.connection.ts.tpl +8 -0
- package/templates/be/patterns/projections/projection.entity.ts.tpl +9 -0
- package/templates/be/patterns/projections/projection.index.ts.tpl +3 -0
- package/templates/be/patterns/projections/projection.module-definition.ts.tpl +7 -0
- package/templates/be/patterns/projections/projection.module.ts.tpl +18 -0
- package/templates/be/patterns/projections/projection.options.ts.tpl +2 -0
- package/templates/be/patterns/projections/projection.projection.spec.ts.tpl +55 -0
- package/templates/be/patterns/projections/projection.projection.ts.tpl +21 -0
- package/templates/be/patterns/queues/platform/bullmq-queue-transport.client.spec.ts.tpl +142 -0
- package/templates/be/patterns/queues/platform/bullmq-queue-transport.client.ts.tpl +81 -0
- package/templates/be/patterns/queues/platform/persistence.connection.ts.tpl +8 -0
- package/templates/be/patterns/queues/platform/persistence.migration.ts.tpl +25 -0
- package/templates/be/patterns/queues/platform/persistence.queue-outbox.entity.ts.tpl +25 -0
- package/templates/be/patterns/queues/platform/persistence.queue.rows.ts.tpl +9 -0
- package/templates/be/patterns/queues/platform/persistence.queue.sql.ts.tpl +12 -0
- package/templates/be/patterns/queues/platform/queue-outbox.service.spec.ts.tpl +48 -0
- package/templates/be/patterns/queues/platform/queue-outbox.service.ts.tpl +17 -0
- package/templates/be/patterns/queues/platform/queue-relay.service.spec.ts.tpl +128 -0
- package/templates/be/patterns/queues/platform/queue-relay.service.ts.tpl +48 -0
- package/templates/be/patterns/queues/platform/queue-transport.port.ts.tpl +115 -0
- package/templates/be/patterns/queues/platform/queue-worker.service.spec.ts.tpl +91 -0
- package/templates/be/patterns/queues/platform/queue-worker.service.ts.tpl +45 -0
- package/templates/be/patterns/queues/platform/queue.config.ts.tpl +15 -0
- package/templates/be/patterns/queues/platform/queue.contracts.ts.tpl +31 -0
- package/templates/be/patterns/queues/platform/queue.decorators.ts.tpl +45 -0
- package/templates/be/patterns/queues/platform/queue.index.ts.tpl +7 -0
- package/templates/be/patterns/queues/platform/queue.log-events.ts.tpl +5 -0
- package/templates/be/patterns/queues/platform/queue.module-definition.ts.tpl +10 -0
- package/templates/be/patterns/queues/platform/queue.module.ts.tpl +62 -0
- package/templates/be/patterns/queues/platform/queue.options.ts.tpl +22 -0
- package/templates/be/patterns/queues/platform/queue.policy.spec.ts.tpl +19 -0
- package/templates/be/patterns/queues/platform/queue.policy.ts.tpl +11 -0
- package/templates/be/patterns/queues/platform/queue.port.ts.tpl +14 -0
- package/templates/be/patterns/queues/queue.index.ts.tpl +3 -0
- package/templates/be/patterns/queues/queue.module.ts.tpl +6 -0
- package/templates/be/patterns/queues/queue.queue.ts.tpl +23 -0
- package/templates/be/patterns/reactors/application.command.ts.tpl +10 -0
- package/templates/be/patterns/reactors/application.contracts.ts.tpl +12 -0
- package/templates/be/patterns/reactors/application.handler.ts.tpl +22 -0
- package/templates/be/patterns/reactors/consumer.ts.tpl +19 -0
- package/templates/be/patterns/reactors/message.module.ts.tpl +20 -0
- package/templates/be/patterns/reactors/reactor.index.ts.tpl +1 -0
- package/templates/be/patterns/reactors/reactor.module.ts.tpl +6 -0
- package/templates/be/patterns/realtime/channel.graphql.module.ts.tpl +6 -0
- package/templates/be/patterns/realtime/channel.index.ts.tpl +1 -0
- package/templates/be/patterns/realtime/channel.input.ts.tpl +12 -0
- package/templates/be/patterns/realtime/channel.subscription.spec.ts.tpl +51 -0
- package/templates/be/patterns/realtime/channel.subscription.ts.tpl +32 -0
- package/templates/be/patterns/realtime/channel.type.ts.tpl +9 -0
- package/templates/be/patterns/saga/saga.compensate.command.ts.tpl +11 -0
- package/templates/be/patterns/saga/saga.compensate.contracts.ts.tpl +7 -0
- package/templates/be/patterns/saga/saga.compensate.handler.ts.tpl +22 -0
- package/templates/be/patterns/saga/saga.compensation.ts.tpl +21 -0
- package/templates/be/patterns/saga/saga.complete.command.ts.tpl +11 -0
- package/templates/be/patterns/saga/saga.complete.contracts.ts.tpl +7 -0
- package/templates/be/patterns/saga/saga.complete.handler.ts.tpl +22 -0
- package/templates/be/patterns/saga/saga.done.consumer.ts.tpl +21 -0
- package/templates/be/patterns/saga/saga.failed.consumer.ts.tpl +21 -0
- package/templates/be/patterns/saga/saga.index.ts.tpl +1 -0
- package/templates/be/patterns/saga/saga.message.module.ts.tpl +23 -0
- package/templates/be/patterns/saga/saga.module.ts.tpl +20 -0
- package/templates/be/patterns/saga/saga.service.spec.ts.tpl +70 -0
- package/templates/be/patterns/saga/saga.service.ts.tpl +44 -0
- package/templates/be/patterns/saga/saga.state.ts.tpl +14 -0
- package/templates/be/patterns/saga/saga.step.ts.tpl +11 -0
- package/templates/be/patterns/saga/saga.undo.command.ts.tpl +10 -0
- package/templates/be/patterns/saga/saga.undo.contracts.ts.tpl +5 -0
- package/templates/be/patterns/saga/saga.undo.handler.ts.tpl +21 -0
- package/templates/be/patterns/webhooks/webhook.door.spec.ts.tpl +72 -0
- package/templates/be/patterns/webhooks/webhook.door.ts.tpl +36 -0
- package/templates/be/patterns/webhooks/webhook.http.module.ts.tpl +6 -0
- package/templates/be/patterns/webhooks/webhook.index.ts.tpl +1 -0
- package/templates/be/patterns/webhooks/webhook.request.ts.tpl +9 -0
- package/templates/be/skeleton/apps/__app__/src/__app__.options.ts +3 -0
- package/templates/be/skeleton/apps/__app__/src/app.module.ts +15 -2
- package/templates/be/skeleton/apps/__app__/src/main.ts +7 -15
- package/templates/be/skeleton/apps/cli/src/app.module.ts +30 -0
- package/templates/be/skeleton/apps/cli/src/cli.options.ts +22 -0
- package/templates/be/skeleton/apps/cli/src/main.ts +24 -0
- package/templates/be/skeleton/src/features/cli/cli.module.ts +7 -0
- package/templates/be/skeleton/src/features/cli/index.ts +1 -0
- package/templates/be/skeleton/src/features/cli/migrate/migrate.cli.spec.ts +17 -0
- package/templates/be/skeleton/src/features/cli/migrate/migrate.cli.ts +15 -0
- package/templates/be/skeleton/src/features/cli/migrate/migrate.module.ts +7 -0
- package/templates/be/skeleton/src/features/cli/migrate/subs/run.cli.spec.ts +17 -0
- package/templates/be/skeleton/src/features/cli/migrate/subs/run.cli.ts +18 -0
- package/templates/be/skeleton/src/features/cli/seed/seed.cli.spec.ts +17 -0
- package/templates/be/skeleton/src/features/cli/seed/seed.cli.ts +15 -0
- package/templates/be/skeleton/src/features/cli/seed/seed.module.ts +7 -0
- package/templates/be/skeleton/src/features/cli/seed/subs/run.cli.spec.ts +33 -0
- package/templates/be/skeleton/src/features/cli/seed/subs/run.cli.ts +34 -0
- package/templates/be/skeleton/src/modules/domain/identity/admission.policy.spec.ts +13 -0
- package/templates/be/skeleton/src/modules/domain/identity/auth.guard.spec.ts +40 -0
- package/templates/be/skeleton/src/modules/domain/identity/messages/identity.messages.ts +1 -1
- package/templates/be/skeleton/src/modules/domain/note/errors/note.error.ts +16 -0
- package/templates/be/skeleton/src/modules/domain/note/index.ts +3 -0
- package/templates/be/skeleton/src/modules/domain/note/note.contracts.ts +19 -0
- package/templates/be/skeleton/src/modules/domain/note/note.decorators.ts +9 -0
- package/templates/be/skeleton/src/modules/domain/note/note.module-definition.ts +7 -0
- package/templates/be/skeleton/src/modules/domain/note/note.module.ts +19 -0
- package/templates/be/skeleton/src/modules/domain/note/note.options.ts +2 -0
- package/templates/be/skeleton/src/modules/domain/note/note.service.spec.ts +76 -0
- package/templates/be/skeleton/src/modules/domain/note/note.service.ts +37 -0
- package/templates/be/skeleton/src/modules/domain/note/persistence/connection.ts +8 -0
- package/templates/be/skeleton/src/modules/domain/note/persistence/entities/note.entity.ts +17 -0
- package/templates/be/skeleton/src/modules/domain/note/persistence/migrations/1790000000000-init-note.ts +22 -0
- package/templates/be/skeleton/src/modules/domain/note/persistence/note.rows.ts +17 -0
- package/templates/be/skeleton/src/modules/domain/note/persistence/note.sql.ts +4 -0
- package/templates/be/skeleton/src/modules/platform/config/env-source.config.ts +20 -0
- package/templates/be/skeleton/src/modules/platform/config/index.ts +1 -1
- package/templates/be/skeleton/src/modules/platform/cqrs/cqrs.contracts.ts +18 -0
- package/templates/be/skeleton/src/modules/platform/database/connection-source.client.spec.ts +41 -0
- package/templates/be/skeleton/src/modules/platform/database/connection-source.client.ts +17 -0
- package/templates/be/skeleton/src/modules/platform/database/database.module-definition.ts +13 -0
- package/templates/be/skeleton/src/modules/platform/database/database.module.ts +77 -0
- package/templates/be/skeleton/src/modules/platform/database/database.options.ts +30 -0
- package/templates/be/skeleton/src/modules/platform/database/database.port.ts +65 -0
- package/templates/be/skeleton/src/modules/platform/database/database.sql.ts +47 -0
- package/templates/be/skeleton/src/modules/platform/database/errors/database.error.ts +16 -0
- package/templates/be/skeleton/src/modules/platform/database/index.ts +9 -0
- package/templates/be/skeleton/src/modules/platform/database/migrate-connections.client.ts +30 -0
- package/templates/be/skeleton/src/modules/platform/database/migration-runner.service.spec.ts +84 -0
- package/templates/be/skeleton/src/modules/platform/database/migration-runner.service.ts +23 -0
- package/templates/be/skeleton/src/modules/platform/database/primary.config.ts +9 -0
- package/templates/be/skeleton/src/modules/platform/database/primary.connection.ts +2 -0
- package/templates/be/skeleton/src/modules/platform/database/primary.decorators.ts +10 -0
- package/templates/be/skeleton/src/modules/platform/database/seed-connections.client.spec.ts +108 -0
- package/templates/be/skeleton/src/modules/platform/database/seed-connections.client.ts +75 -0
- package/templates/be/skeleton/src/modules/platform/database/seed-runner.service.spec.ts +88 -0
- package/templates/be/skeleton/src/modules/platform/database/seed-runner.service.ts +29 -0
- package/templates/be/skeleton/src/modules/platform/errors/errors.filter.spec.ts +48 -0
- package/templates/be/skeleton/src/modules/platform/errors/messages/errors.messages.ts +1 -1
- package/templates/be/skeleton/src/modules/platform/http-security/errors/http-security.error.ts +12 -0
- package/templates/be/skeleton/src/modules/platform/http-security/execution-request.mapper.spec.ts +16 -0
- package/templates/be/skeleton/src/modules/platform/http-security/http-security.config.ts +8 -1
- package/templates/be/skeleton/src/modules/platform/http-security/http-security.decorators.ts +8 -0
- package/templates/be/skeleton/src/modules/platform/http-security/http-security.module.ts +14 -1
- package/templates/be/skeleton/src/modules/platform/http-security/http-security.options.ts +12 -0
- package/templates/be/skeleton/src/modules/platform/http-security/messages/http-security.messages.ts +10 -2
- package/templates/be/skeleton/src/modules/platform/http-security/origin.guard.spec.ts +63 -0
- package/templates/be/skeleton/src/modules/platform/http-security/rate-limit.guard.spec.ts +108 -0
- package/templates/be/skeleton/src/modules/platform/http-security/request-validation.service.spec.ts +39 -0
- package/templates/be/skeleton/src/modules/platform/http-security/request-validation.service.ts +25 -0
- package/templates/be/skeleton/src/modules/platform/http-security/webhook-signature.service.spec.ts +172 -0
- package/templates/be/skeleton/src/modules/platform/http-security/webhook-signature.service.ts +66 -0
- package/templates/be/skeleton/src/modules/platform/logging/logging.log-events.ts +3 -1
- package/templates/be/skeleton/src/modules/platform/primitives/outcome.mapper.spec.ts +52 -0
- package/templates/be/skeleton-lite/apps/api/Dockerfile +37 -0
- package/templates/be/skeleton-lite/apps/api/src/api.options.ts +16 -0
- package/templates/be/skeleton-lite/apps/api/src/app.module.ts +81 -0
- package/templates/be/skeleton-lite/apps/api/src/main.ts +34 -0
- package/templates/be/skeleton-lite/src/modules/domain/identity/admission.policy.ts +14 -0
- package/templates/be/skeleton-lite/src/modules/domain/identity/auth.guard.ts +50 -0
- package/templates/be/skeleton-lite/src/modules/domain/identity/identity.contracts.ts +26 -0
- package/templates/be/skeleton-lite/src/modules/domain/identity/identity.decorators.ts +19 -0
- package/templates/be/skeleton-lite/src/modules/domain/identity/identity.module.ts +26 -0
- package/templates/be/skeleton-lite/src/modules/domain/identity/identity.options.ts +7 -0
- package/templates/be/skeleton-lite/src/modules/domain/identity/index.ts +6 -0
- package/templates/be/skeleton-lite/src/modules/integrations/supabase/errors/supabase.error.ts +19 -0
- package/templates/be/skeleton-lite/src/modules/integrations/supabase/index.ts +10 -0
- package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.client.ts +24 -0
- package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.config.ts +8 -0
- package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.decorators.ts +17 -0
- package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.jwks.ts +32 -0
- package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.options.ts +24 -0
- package/templates/be/skeleton-lite/src/modules/platform/cqrs/index.ts +4 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/database.module.ts +54 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/database.options.ts +23 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/database.port.ts +10 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/database.sql.ts +49 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/index.ts +4 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/migration-runner.service.ts +21 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/primary.config.ts +11 -0
- package/templates/be/skeleton-lite/src/modules/platform/database/seed-runner.service.ts +28 -0
- package/templates/be/skeleton-lite/src/modules/platform/http-security/http-security.module.ts +25 -0
- package/templates/be/skeleton-lite/src/modules/platform/http-security/index.ts +9 -0
- package/templates/be/skeleton-lite/src/modules/platform/i18n/index.ts +4 -0
- package/templates/be/skeleton-lite/src/modules/platform/logging/index.ts +5 -0
- package/templates/be/table/error.ts.tpl +16 -0
- package/templates/be/table/index.ts.tpl +2 -0
- package/templates/be/table/migration.sql.tpl +51 -0
- package/templates/be/table/module-definition.ts.tpl +7 -0
- package/templates/be/table/module.ts.tpl +14 -0
- package/templates/be/table/options.ts.tpl +2 -0
- package/templates/be/table/rows.ts.tpl +4 -0
- package/templates/be/table/service.ts.tpl +23 -0
- package/templates/be/table/sql.ts.tpl +4 -0
- package/templates/be/tool-config/jest.config.js +3 -1
- package/templates/be/upgrade-full/apps/cli/src/app.module.ts +14 -0
- package/templates/be/upgrade-full/apps/cli/src/main.ts +26 -0
- package/templates/be/upgrade-full/src/features/cli/cli.module.ts +6 -0
- package/templates/be/upgrade-full/src/features/cli/migrate/subs/run.cli.ts +23 -0
- package/templates/common/gitignore.base +1 -2
- package/templates/fe/app/package.json.tpl +1 -0
- package/templates/fe/app/tsconfig.json +12 -0
- package/templates/fe/common/app-layout.tsx.partial +8 -0
- package/templates/fe/common/site-shell.tsx.partial +9 -0
- package/templates/fe/image/next/Dockerfile +42 -0
- package/templates/fe/skeleton/apps/app/next.config.ts +23 -0
- package/templates/fe/skeleton/apps/app/postcss.config.mjs +7 -0
- package/templates/fe/skeleton/apps/{__app__ → app}/src/app/[locale]/error.tsx +2 -2
- package/templates/fe/skeleton/apps/app/src/app/[locale]/layout.tsx +22 -0
- package/templates/fe/skeleton/apps/{__app__ → app}/src/app/[locale]/loading.tsx +2 -2
- package/templates/fe/skeleton/apps/{__app__ → app}/src/app/[locale]/not-found.tsx +2 -2
- package/templates/fe/skeleton/apps/app/src/app/[locale]/page.tsx +9 -0
- package/templates/fe/skeleton/apps/{__app__ → app}/src/app/global-error.tsx +2 -2
- package/templates/fe/skeleton/apps/app/src/app/globals.css +10 -0
- package/templates/fe/skeleton/apps/app/src/features/layouts/AppLayout/index.tsx +18 -0
- package/templates/fe/skeleton/apps/app/src/features/pages/AppErrorPage/component.tsx +19 -0
- package/templates/fe/skeleton/apps/app/src/features/pages/AppErrorPage/index.tsx +11 -0
- package/templates/fe/skeleton/apps/app/src/features/pages/AppGlobalErrorPage/index.tsx +16 -0
- package/templates/fe/skeleton/apps/app/src/features/pages/AppHomePage/component.tsx +10 -0
- package/templates/fe/skeleton/apps/app/src/features/pages/AppHomePage/index.tsx +15 -0
- package/templates/fe/skeleton/apps/app/src/features/pages/AppLoadingPage/index.tsx +8 -0
- package/templates/fe/skeleton/apps/app/src/features/pages/AppNotFoundPage/index.tsx +9 -0
- package/templates/fe/skeleton/apps/app/src/modules/i18n/index.ts +4 -0
- package/templates/fe/skeleton/apps/app/src/modules/i18n/messages/vi.json +28 -0
- package/templates/fe/skeleton/apps/app/src/modules/i18n/request.ts +4 -0
- package/templates/fe/skeleton/apps/app/src/modules/routes/index.ts +4 -0
- package/templates/fe/skeleton/apps/app/src/proxy.ts +1 -0
- package/templates/fe/skeleton/apps/{__app__ → landing}/next.config.ts +4 -2
- package/templates/fe/skeleton/apps/landing/postcss.config.mjs +7 -0
- package/templates/fe/skeleton/apps/landing/src/app/[locale]/error.tsx +10 -0
- package/templates/fe/skeleton/apps/landing/src/app/[locale]/layout.tsx +22 -0
- package/templates/fe/skeleton/apps/landing/src/app/[locale]/loading.tsx +6 -0
- package/templates/fe/skeleton/apps/landing/src/app/[locale]/not-found.tsx +6 -0
- package/templates/fe/skeleton/apps/landing/src/app/[locale]/page.tsx +9 -0
- package/templates/fe/skeleton/apps/landing/src/app/global-error.tsx +10 -0
- package/templates/fe/skeleton/apps/landing/src/app/globals.css +10 -0
- package/templates/fe/skeleton/apps/landing/src/features/layouts/LandingLayout/index.tsx +24 -0
- package/templates/fe/skeleton/apps/landing/src/features/pages/LandingErrorPage/component.tsx +18 -0
- package/templates/fe/skeleton/apps/landing/src/features/pages/LandingErrorPage/index.tsx +11 -0
- package/templates/fe/skeleton/apps/landing/src/features/pages/LandingGlobalErrorPage/index.tsx +16 -0
- package/templates/fe/skeleton/apps/landing/src/features/pages/LandingLoadingPage/index.tsx +8 -0
- package/templates/fe/skeleton/apps/landing/src/features/pages/LandingNotFoundPage/index.tsx +9 -0
- package/templates/fe/skeleton/apps/landing/src/features/pages/LandingPage/component.tsx +24 -0
- package/templates/fe/skeleton/apps/landing/src/features/pages/LandingPage/index.tsx +16 -0
- package/templates/fe/skeleton/apps/landing/src/modules/config/index.ts +12 -0
- package/templates/fe/skeleton/apps/landing/src/modules/i18n/index.ts +7 -0
- package/templates/fe/skeleton/apps/landing/src/modules/i18n/messages/vi.json +31 -0
- package/templates/fe/skeleton/apps/landing/src/modules/i18n/request.ts +4 -0
- package/templates/fe/skeleton/apps/landing/src/modules/routes/index.ts +4 -0
- package/templates/fe/skeleton/apps/landing/src/proxy.ts +1 -0
- package/templates/fe/skeleton/packages/__project__-i18n/src/index.ts +49 -0
- package/templates/fe/skeleton/packages/__project__-i18n/src/proxy.ts +24 -0
- package/templates/fe/skeleton/packages/__project__-i18n/src/routing.ts +20 -0
- package/templates/fe/skeleton/packages/__project__-ui/src/branches/Providers/index.tsx +23 -0
- package/templates/fe/skeleton/packages/__project__-ui/src/composites/ErrorNotice/index.tsx +14 -0
- package/templates/fe/skeleton/packages/__project__-ui/src/composites/GlobalErrorNotice/index.tsx +25 -0
- package/templates/fe/skeleton/packages/__project__-ui/src/composites/LoadingNotice/index.tsx +9 -0
- package/templates/fe/skeleton/packages/__project__-ui/src/composites/LocaleShell/index.tsx +21 -0
- package/templates/fe/skeleton/packages/__project__-ui/src/composites/NotFoundNotice/index.tsx +19 -0
- package/templates/fe/skeleton/packages/__project__-ui/src/composites/SiteShell/classNames.ts +4 -0
- package/templates/fe/skeleton/packages/__project__-ui/src/composites/SiteShell/index.tsx +19 -0
- package/templates/fe/skeleton/packages/__project__-ui/src/index.ts +6 -0
- package/templates/fe/skeleton-lite/apps/web/next.config.ts +22 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/error.tsx +10 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/layout.tsx +37 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/loading.tsx +6 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/not-found.tsx +6 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/page.tsx +9 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/providers.tsx +26 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/auth/callback/route.ts +24 -0
- package/templates/fe/skeleton-lite/apps/web/src/app/global-error.tsx +10 -0
- package/templates/fe/{skeleton/apps/__app__ → skeleton-lite/apps/web}/src/app/globals.css +1 -1
- package/templates/fe/skeleton-lite/apps/web/src/app/health/live/route.ts +5 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/blocks/SignInForm/component.tsx +29 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/blocks/SignInForm/index.tsx +41 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/blocks/SignOutButton/component.tsx +17 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/blocks/SignOutButton/index.tsx +38 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/composites/ErrorNotice/index.tsx +13 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/composites/GlobalErrorNotice/index.tsx +24 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/composites/LoadingNotice/index.tsx +7 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/composites/NotFoundNotice/index.tsx +18 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/composites/SiteShell/classNames.ts +4 -0
- package/templates/fe/skeleton-lite/apps/web/src/components/composites/SiteShell/index.tsx +13 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/layouts/AppLayout/index.tsx +31 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppErrorPage/component.tsx +12 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppErrorPage/index.tsx +10 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppGlobalErrorPage/index.tsx +15 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppHomePage/component.tsx +14 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppHomePage/index.tsx +30 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppLoadingPage/index.tsx +8 -0
- package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppNotFoundPage/index.tsx +9 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/brand/brand.css +20 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/brand/index.ts +2 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/config/index.ts +20 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/db/auth/read-session.ts +25 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/db/auth/write-sign-in.ts +25 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/db/auth/write-sign-out.ts +17 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/db/browser.ts +14 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/db/index.ts +3 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/db/outcome.ts +59 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/db/principal.ts +29 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/db/server.ts +70 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/db/validation/validation.mapper.ts +50 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/index.ts +8 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/messages/vi.json +48 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/request.ts +16 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/routing.ts +14 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/routes/index.ts +7 -0
- package/templates/fe/skeleton-lite/apps/web/src/modules/routes/safe-next-path.ts +26 -0
- package/templates/fe/skeleton-lite/apps/web/src/proxy.ts +43 -0
- package/templates/fe/table/read.ts.tpl +16 -0
- package/templates/fe/table/write.ts.tpl +16 -0
- package/upgrade/check.mjs +137 -0
- package/upgrade/index.mjs +524 -0
- package/bin/hfs.mjs +0 -233
- package/runtime/scripts/api/fs/rmdir-link.mjs +0 -12
- package/runtime/scripts/lib/test-secrets.mjs +0 -116
- package/templates/fe/skeleton/apps/__app__/src/app/[locale]/layout.tsx +0 -20
- package/templates/fe/skeleton/apps/__app__/src/app/[locale]/page.tsx +0 -9
- package/templates/fe/skeleton/apps/__app__/src/components/composites/FailureScreen/index.tsx +0 -28
- package/templates/fe/skeleton/apps/__app__/src/features/layouts/LocaleShell/index.tsx +0 -35
- package/templates/fe/skeleton/apps/__app__/src/features/pages/ErrorPage/component.tsx +0 -19
- package/templates/fe/skeleton/apps/__app__/src/features/pages/ErrorPage/index.tsx +0 -11
- package/templates/fe/skeleton/apps/__app__/src/features/pages/GlobalErrorPage/component.tsx +0 -24
- package/templates/fe/skeleton/apps/__app__/src/features/pages/GlobalErrorPage/index.tsx +0 -14
- package/templates/fe/skeleton/apps/__app__/src/features/pages/HomePage/component.tsx +0 -21
- package/templates/fe/skeleton/apps/__app__/src/features/pages/HomePage/index.tsx +0 -15
- package/templates/fe/skeleton/apps/__app__/src/features/pages/LoadingPage/component.tsx +0 -23
- package/templates/fe/skeleton/apps/__app__/src/features/pages/LoadingPage/index.tsx +0 -8
- package/templates/fe/skeleton/apps/__app__/src/features/pages/NotFoundPage/component.tsx +0 -28
- package/templates/fe/skeleton/apps/__app__/src/features/pages/NotFoundPage/index.tsx +0 -8
- package/templates/fe/skeleton/apps/__app__/src/modules/i18n/config.ts +0 -8
- package/templates/fe/skeleton/apps/__app__/src/modules/i18n/index.ts +0 -2
- package/templates/fe/skeleton/apps/__app__/src/modules/i18n/messages/vi.json +0 -25
- package/templates/fe/skeleton/apps/__app__/src/modules/i18n/request.ts +0 -19
- package/templates/fe/skeleton/apps/__app__/src/modules/i18n/routing.ts +0 -9
- package/templates/fe/skeleton/apps/__app__/src/modules/routes/index.ts +0 -4
- package/templates/fe/skeleton/apps/__app__/src/proxy.ts +0 -10
- /package/templates/be/skeleton/src/features/{system-health → api/system-health}/application/check-liveness.contracts.ts +0 -0
- /package/templates/be/skeleton/src/features/{system-health → api/system-health}/application/check-liveness.handler.ts +0 -0
- /package/templates/be/skeleton/src/features/{system-health → api/system-health}/application/check-liveness.query.ts +0 -0
- /package/templates/be/skeleton/src/features/{system-health → api/system-health}/index.ts +0 -0
- /package/templates/be/skeleton/src/features/{system-health → api/system-health}/system-health.module.ts +0 -0
- /package/templates/be/skeleton/src/features/{system-health → api/system-health}/transport/http/live.controller.ts +0 -0
- /package/templates/be/skeleton/src/features/{system-health → api/system-health}/transport/http/system-health-http.module.ts +0 -0
- /package/templates/fe/skeleton/apps/{__app__ → app}/src/app/health/live/route.ts +0 -0
- /package/templates/fe/skeleton/apps/{__app__ → app}/src/modules/config/index.ts +0 -0
- /package/templates/fe/{skeleton/apps/__app__ → skeleton-lite/apps/web}/postcss.config.mjs +0 -0
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
schema: starci/knowledge-source@1
|
|
2
|
+
id: be.api
|
|
3
|
+
title: Backend api feature
|
|
4
|
+
purpose: |-
|
|
5
|
+
Given a scenario a request or a background transport triggers, where does it live and how is it written? It is an api
|
|
6
|
+
feature, `be/src/features/api/<feature>/`, the trigger kind the api apps compose. Its application layer is CQRS: one
|
|
7
|
+
typed command or query per operation and one handler that owns the scenario, dispatched by a transport directly on the
|
|
8
|
+
bus. There is no use-case class and no forwarder service. Inside one bounded context the work is synchronous; an event
|
|
9
|
+
only crosses contexts or carries async work.
|
|
10
|
+
appliesTo:
|
|
11
|
+
- backend
|
|
12
|
+
family: be
|
|
13
|
+
# The slot ids this topic teaches (knowledge/hfs/slots.yaml); scripts/gates/read-digest.mjs inverts these
|
|
14
|
+
# into the READ-step slot -> pattern-topic map (knowledge/op-gate.yaml kinds), each slot's topics in index.yaml order.
|
|
15
|
+
slots: [be.feature, be.feature.application]
|
|
16
|
+
provenance:
|
|
17
|
+
reviewedAt: 2026-10-02
|
|
18
|
+
sources:
|
|
19
|
+
- knowledge/hfs/README.md
|
|
20
|
+
- knowledge/hfs/slots.yaml
|
|
21
|
+
- knowledge/hfs/rules.yaml
|
|
22
|
+
- owner-locked BE convention 2026-09-30
|
|
23
|
+
- owner decision 2026-10-02 (features grouped by trigger kind; synchronous inside a context)
|
|
24
|
+
- https://docs.nestjs.com/recipes/cqrs
|
|
25
|
+
limitations: |-
|
|
26
|
+
Static checks prove the shape of a feature, a message, its handler and the dispatch, and that SQL touches only tables its
|
|
27
|
+
owner may reach. They do not prove that a handler decides the right thing, that a transaction boundary is right, that a
|
|
28
|
+
context boundary is drawn where the business draws it or that a refusal is chosen over an exception correctly; the
|
|
29
|
+
service spec of the service the handler calls and the e2e run prove behavior, and design review proves the boundary.
|
|
30
|
+
rules:
|
|
31
|
+
- id: BE-CQRS-1
|
|
32
|
+
title: The application folder holds messages, handlers, contracts and support only
|
|
33
|
+
kind: mandatory
|
|
34
|
+
hfsRules: [R87, R29]
|
|
35
|
+
requirement: |-
|
|
36
|
+
`be/src/features/api/<feature>/application/` holds `<action>.command.ts` or `<action>.query.ts`, `<action>.handler.ts`,
|
|
37
|
+
`<action>.contracts.ts` and the opt-in `support/` folder of helpers local to the feature. A
|
|
38
|
+
`*.use-case.ts` file, a forwarder `<op>.service.ts` and a folder named after a protocol do not exist. A read is a
|
|
39
|
+
query and a write is a command; a handler never serves both.
|
|
40
|
+
rationale: |-
|
|
41
|
+
One shape for every operation gives one interception point and one message object, so a reader finds the scenario
|
|
42
|
+
in the handler and never in a wrapper around it.
|
|
43
|
+
cases:
|
|
44
|
+
- id: case-1
|
|
45
|
+
when: A new write operation
|
|
46
|
+
write: 'application/start-checkout.command.ts, start-checkout.handler.ts, start-checkout.contracts.ts (the handler has no spec: its service does).'
|
|
47
|
+
- id: case-2
|
|
48
|
+
when: A new read operation
|
|
49
|
+
write: 'application/get-cart.query.ts, get-cart.handler.ts, get-cart.contracts.ts (the handler has no spec: its service does).'
|
|
50
|
+
verification:
|
|
51
|
+
automated:
|
|
52
|
+
- BE_CQRS_SHAPE
|
|
53
|
+
- BE_READONLY_BOUNDARY
|
|
54
|
+
- BE_FEATURE_SHAPE
|
|
55
|
+
- BE_FEATURE_LAYOUT_INVALID
|
|
56
|
+
- BE_APPLICATION_IMPORTS_TRANSPORT
|
|
57
|
+
- BE_APPLICATION_TRANSPORT_FRAMEWORK
|
|
58
|
+
manual:
|
|
59
|
+
- Confirm each operation is a command or a query and no handler mixes both.
|
|
60
|
+
relatedExamples: []
|
|
61
|
+
- id: BE-CQRS-2
|
|
62
|
+
title: A message is a typed Command or Query carrying one params field
|
|
63
|
+
kind: mandatory
|
|
64
|
+
hfsRules: [R87, R37]
|
|
65
|
+
requirement: |-
|
|
66
|
+
`export class <Action>Command extends Command<<Action>Result> { constructor(readonly params: ExecuteParams<<Action>Request>) { super() } }`
|
|
67
|
+
(`Query<R>` for reads). One `readonly params` field, no methods, no defaults. `ExecuteParams<T> = { request: T; principal: Principal }`
|
|
68
|
+
for an authenticated operation and `PublicExecuteParams<T> = { request: T }` for a `@Public` one, so the type states
|
|
69
|
+
whether the door is public and the principal is never optional. `Principal = { id: string; roles: ReadonlyArray<Role> }`
|
|
70
|
+
is owned by `platform/cqrs`. An entity never travels in params.
|
|
71
|
+
rationale: |-
|
|
72
|
+
`@nestjs/cqrs` 11 types `execute` with the message's result type, so the compiler proves what the transport gets
|
|
73
|
+
back, and a principal that cannot be absent removes a class of authorization bugs.
|
|
74
|
+
cases:
|
|
75
|
+
- id: case-1
|
|
76
|
+
when: An authenticated command
|
|
77
|
+
write: 'export class StartCheckoutCommand extends Command<StartCheckoutResult> { constructor(readonly params: ExecuteParams<StartCheckoutRequest>) { super() } }'
|
|
78
|
+
- id: case-2
|
|
79
|
+
when: A public query
|
|
80
|
+
write: 'export class CheckHealthQuery extends Query<CheckHealthResult> { constructor(readonly params: PublicExecuteParams<CheckHealthRequest>) { super() } }'
|
|
81
|
+
verification:
|
|
82
|
+
automated:
|
|
83
|
+
- BE_CQRS_SHAPE
|
|
84
|
+
- BE_READONLY_BOUNDARY
|
|
85
|
+
- BE_ENTITY_IN_CONTRACT
|
|
86
|
+
manual:
|
|
87
|
+
- Review that the request carries what the operation needs and nothing of the transport.
|
|
88
|
+
relatedExamples: []
|
|
89
|
+
- id: BE-CQRS-3
|
|
90
|
+
title: A handler overrides process and returns its declared result
|
|
91
|
+
kind: mandatory
|
|
92
|
+
hfsRules: [R87, R75, R48, R203]
|
|
93
|
+
requirement: |-
|
|
94
|
+
`@CommandHandler(X)` or `@QueryHandler(X)` on a class that `extends ICQRSHandler<X, XResult>` and implements
|
|
95
|
+
`protected override async process(message)`; it never overrides `execute`. `ICQRSHandler.execute` is load-bearing: it
|
|
96
|
+
logs `OperationFailed` with the operation name and the error and rethrows, and counts refused outcomes. `<Action>Result`
|
|
97
|
+
is a plain projection type or an `Outcome<Value, Code>` and the return type of `process` is declared. The handler opens
|
|
98
|
+
the transaction (`this.entityManager.transaction(async (manager) => ...)`), stamps `this.clock.now()` once and passes
|
|
99
|
+
it down. The handler is thin (R203 `BE_FEATURE_THIN`): its `process` maps the message, makes one delegating call to an
|
|
100
|
+
injected `*.service` and returns the result, so it has no unit spec; the decisions (persisted state, the `where` that
|
|
101
|
+
holds ownership, nothing written on a refusal) live in the service and its `<name>.service.spec.ts` asserts them.
|
|
102
|
+
rationale: |-
|
|
103
|
+
A single template gives every operation the same failure log and metric, and the service spec pins the decision the
|
|
104
|
+
handler delegates.
|
|
105
|
+
cases:
|
|
106
|
+
- id: case-1
|
|
107
|
+
when: A handler
|
|
108
|
+
write: |-
|
|
109
|
+
@CommandHandler(StartCheckoutCommand)
|
|
110
|
+
/** Opens a checkout, or refuses with a purchase code. */
|
|
111
|
+
export class StartCheckoutHandler extends ICQRSHandler<StartCheckoutCommand, StartCheckoutResult> {
|
|
112
|
+
constructor(
|
|
113
|
+
@InjectPrimaryEntityManager() private readonly entityManager: EntityManager,
|
|
114
|
+
@InjectClock() private readonly clock: Clock,
|
|
115
|
+
private readonly purchaseService: PurchaseService,
|
|
116
|
+
) { super() }
|
|
117
|
+
|
|
118
|
+
protected override async process(command: StartCheckoutCommand): Promise<StartCheckoutResult> {
|
|
119
|
+
const at = this.clock.now()
|
|
120
|
+
return this.entityManager.transaction(async (manager) => this.purchaseService.open({ manager, learnerId: command.params.principal.id, offerId: command.params.request.offerId, at }))
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
verification:
|
|
124
|
+
automated:
|
|
125
|
+
- BE_CQRS_SHAPE
|
|
126
|
+
- BE_READONLY_BOUNDARY
|
|
127
|
+
- BE_RETURN_TYPE
|
|
128
|
+
- BE_SPEC_QUALITY
|
|
129
|
+
- BE_FEATURE_THIN
|
|
130
|
+
manual:
|
|
131
|
+
- Confirm the service spec the handler calls asserts refusal paths and ownership, not only that a mock was called.
|
|
132
|
+
relatedExamples: []
|
|
133
|
+
- id: BE-CQRS-4
|
|
134
|
+
title: The bus is the only way into a handler; nothing forwards
|
|
135
|
+
kind: mandatory
|
|
136
|
+
hfsRules: [R87, R88, R90]
|
|
137
|
+
requirement: |-
|
|
138
|
+
A handler is reached only through `commandBus.execute` or `queryBus.execute` from a transport (the transport side is
|
|
139
|
+
transport.yaml BE-TRANSPORT-2). No `<op>.service.ts` sits between a transport and a handler. Work that stays
|
|
140
|
+
inside one context is synchronous: the handler calls the domain service in one transaction. A follow-up that must happen
|
|
141
|
+
anyway or that crosses a context is an event published inside that transaction (event-bus.yaml, BE-API-2), never an
|
|
142
|
+
in-process event: `EventBus`, `@EventsHandler`, `EventEmitter2`, `@OnEvent` and NATS bridges are not used.
|
|
143
|
+
rationale: |-
|
|
144
|
+
A forwarder is pure indirection where logic creeps in, and an in-process event does not survive a crash between the
|
|
145
|
+
commit and the delivery.
|
|
146
|
+
cases:
|
|
147
|
+
- id: case-1
|
|
148
|
+
when: A resolver needs an operation
|
|
149
|
+
write: '`constructor(@InjectCommandBus() private readonly commandBus: CommandBus) {}` then `this.commandBus.execute(new StartCheckoutCommand({ request, principal }))`.'
|
|
150
|
+
- id: case-2
|
|
151
|
+
when: A follow-up effect in another context after a write
|
|
152
|
+
write: 'the domain service the handler calls publishes the event with eventBus.publish(event, tx) in its own transaction; a reactor or job consumes it (event-bus.yaml).'
|
|
153
|
+
verification:
|
|
154
|
+
automated:
|
|
155
|
+
- BE_CQRS_SHAPE
|
|
156
|
+
- BE_READONLY_BOUNDARY
|
|
157
|
+
- BE_TRANSPORT_SHAPE
|
|
158
|
+
- BE_INFRA_OWNER
|
|
159
|
+
manual: []
|
|
160
|
+
relatedExamples: []
|
|
161
|
+
- id: BE-API-1
|
|
162
|
+
title: An api feature has one fixed shape and is composed only by apps
|
|
163
|
+
kind: mandatory
|
|
164
|
+
hfsRules: [R29, R28, R30, R31, R45]
|
|
165
|
+
requirement: |-
|
|
166
|
+
An api feature is `be/src/features/api/<feature>/` (slot `be.feature`) and holds `index.ts`, `<feature>.module.ts`,
|
|
167
|
+
`application/` (`be.feature.application`, with the opt-in `support/`, `be.feature.application.support`),
|
|
168
|
+
`transport/<protocol>/` and, when it has copy, `messages/` (`be.feature.messages`), and nothing else. A protocol lives
|
|
169
|
+
in `transport/graphql`, `transport/http` (`be.transport.{graphql,http}`, composed by an api app) or
|
|
170
|
+
`transport/message` (`be.transport.message`, composed by the api app that owns it or by a worker app), each with
|
|
171
|
+
exactly one Nest module `<feature>-<protocol>.module.ts`, its resolvers, controllers or consumers, their `<action>.mapper.ts` and `dto/` where the protocol has DTOs (shapes in
|
|
172
|
+
transport.yaml). The feature imports only downward into `src/modules/*`, never another api feature and never another
|
|
173
|
+
trigger kind such as `features/cli`; only `be/apps/*` composes it (folder.yaml BE-FOLDER-2).
|
|
174
|
+
rationale: |-
|
|
175
|
+
Several entry protocols share one operation without importing transport DTOs into the application layer, and an app can
|
|
176
|
+
compose only the transports it serves.
|
|
177
|
+
cases:
|
|
178
|
+
- id: case-1
|
|
179
|
+
when: An operation reachable over HTTP and GraphQL
|
|
180
|
+
write: application/place-order.command.ts and its handler once; transport/http/place-order.controller.ts and transport/graphql/place-order.resolver.ts each dispatch it.
|
|
181
|
+
- id: case-2
|
|
182
|
+
when: A conversion has substance
|
|
183
|
+
write: transport/graphql/place-order.mapper.ts with toPlaceOrderType and toPlaceOrderRequest.
|
|
184
|
+
- id: case-3
|
|
185
|
+
when: A feature grows past 250 source files
|
|
186
|
+
write: Split it by product capability into api features, moving shared behavior into a domain capability.
|
|
187
|
+
- id: case-4
|
|
188
|
+
when: An api feature imports features/cli/seed/subs/demo.cli.ts to reuse its rows
|
|
189
|
+
write: 'Refused (BE_FEATURE_IMPORTS_FEATURE): both kinds import the domain capability that owns the rows instead.'
|
|
190
|
+
verification:
|
|
191
|
+
automated:
|
|
192
|
+
- BE_FEATURE_SHAPE
|
|
193
|
+
- BE_FEATURE_LAYOUT_INVALID
|
|
194
|
+
- BE_APPLICATION_IMPORTS_TRANSPORT
|
|
195
|
+
- BE_APPLICATION_TRANSPORT_FRAMEWORK
|
|
196
|
+
- BE_FEATURE_IMPORTS_FEATURE
|
|
197
|
+
- BE_PUBLIC_SURFACE
|
|
198
|
+
- ARCH_OWNER_EXPORT_BYPASS
|
|
199
|
+
- ARCH_OWNER_EXPORT_STAR
|
|
200
|
+
- HFS_ALIAS_REEXPORT
|
|
201
|
+
- ARCH_PACKAGE_EXPORT_BYPASS
|
|
202
|
+
- BE_FEATURE_NOT_COMPOSED
|
|
203
|
+
- BE_MODULE_SHAPE
|
|
204
|
+
- BE_MODULE_HANDLER_REGISTRATION
|
|
205
|
+
- BE_MODULE_PROVIDER_REREGISTRATION
|
|
206
|
+
manual:
|
|
207
|
+
- Review application contracts for request-context, ORM entity and protocol DTO leaks.
|
|
208
|
+
relatedExamples: []
|
|
209
|
+
- id: BE-API-2
|
|
210
|
+
title: Inside one context the work is synchronous; events only cross contexts or carry async work
|
|
211
|
+
kind: mandatory
|
|
212
|
+
hfsRules: [R87, R26, R86, R82]
|
|
213
|
+
requirement: |-
|
|
214
|
+
A context is one bounded context: one domain capability set under `src/modules/domain/`, which may own one Postgres
|
|
215
|
+
schema. Work inside one context is synchronous: the handler calls that context's domain service directly, in one
|
|
216
|
+
transaction it opens, and emits no event to reach code of the same context. An event (an outbox message consumed in
|
|
217
|
+
`transport/message/`) exists only to cross into another context or to carry work that runs later. A feature never reads
|
|
218
|
+
or writes another context's tables or state directly; it receives that context's facts through an event or reads a
|
|
219
|
+
projection its own context owns.
|
|
220
|
+
rationale: |-
|
|
221
|
+
An event inside one context turns one atomic decision into a chain that can half-fail, while a direct read of another
|
|
222
|
+
context's state couples two owners through their storage and bypasses the owner's rules.
|
|
223
|
+
cases:
|
|
224
|
+
- id: case-1
|
|
225
|
+
when: add-cart-item (passing)
|
|
226
|
+
write: 'AddCartItemHandler opens one transaction and calls `this.cartService.addItem({ manager, buyerId, productId, quantity, at })`; the cart rows and the quantity check commit together, with no event.'
|
|
227
|
+
- id: case-2
|
|
228
|
+
when: The order feature needs the payment state (violating)
|
|
229
|
+
write: 'Refused: PlaceOrderHandler querying the payment tables or calling PaymentService to read whether a payment settled. The payment context publishes PaymentSettled through its outbox, and an order consumer in transport/message records it in an order-owned projection the order handler reads.'
|
|
230
|
+
- id: case-3
|
|
231
|
+
when: A confirmation mail after the order commits (async)
|
|
232
|
+
write: 'The order handler enqueues OrderPlaced in its transaction; the mail runs later from a consumer, never inside the order transaction.'
|
|
233
|
+
verification:
|
|
234
|
+
automated:
|
|
235
|
+
- BE_CQRS_SHAPE
|
|
236
|
+
- BE_READONLY_BOUNDARY
|
|
237
|
+
- BE_TIER_DIRECTION
|
|
238
|
+
- FE_TIER_DIRECTION
|
|
239
|
+
- ARCH_PACKAGE_IMPORTS_APP
|
|
240
|
+
- BE_SQL_TABLE_OWNER
|
|
241
|
+
- BE_TRANSACTION_EXTERNAL_CALL
|
|
242
|
+
manual:
|
|
243
|
+
- Confirm each event crosses a context boundary or carries deferred work, and that no handler waits on an event of its own context.
|
|
244
|
+
relatedExamples: []
|
|
245
|
+
- id: BE-API-3
|
|
246
|
+
title: Every operation has an e2e flow on the real app
|
|
247
|
+
kind: mandatory
|
|
248
|
+
hfsRules: [R46, R41]
|
|
249
|
+
requirement: |-
|
|
250
|
+
Each resolver method and controller action of an api feature is driven by an e2e spec (`src/tests/e2e/<area>/*.e2e-spec.ts`) that boots the
|
|
251
|
+
app's real AppModule and calls it as a client does: the happy path, the refusal the command declares and the denial of an unauthenticated caller.
|
|
252
|
+
rationale: |-
|
|
253
|
+
A transport is thin (R203 `BE_FEATURE_THIN`) and has no logic to unit-test; what can break is the wiring, the guards and the mapping, which only the booted app exercises.
|
|
254
|
+
cases:
|
|
255
|
+
- id: case-1
|
|
256
|
+
when: A new mutation
|
|
257
|
+
write: 'checkout.e2e-spec.ts signs a shopper in, runs startCheckout, asserts the typed payload, then asserts the same call without a token is refused.'
|
|
258
|
+
verification:
|
|
259
|
+
automated:
|
|
260
|
+
- BE_BACKGROUND_UNOWNED
|
|
261
|
+
- BE_DEFAULT_DENY
|
|
262
|
+
manual:
|
|
263
|
+
- Confirm the spec asserts the error code of each refusal, not only a status.
|
|
264
|
+
relatedExamples: [api]
|
|
265
|
+
- id: BE-OPERATIONS-1
|
|
266
|
+
title: A versioned operation is declared once in the app's typed operation table
|
|
267
|
+
kind: mandatory
|
|
268
|
+
hfsRules: [R95, R88, R23]
|
|
269
|
+
requirement: |-
|
|
270
|
+
A versioned operation `<name>@<version>` (for example `sales.policy@1`) that an app serves over one operation route is
|
|
271
|
+
declared once, in the app's operation table `be/apps/<app>/src/operations.ts`, which exports `OPERATIONS`. The table is made by
|
|
272
|
+
`defineOperations` of the platform capability `operations` (`be/src/modules/platform/operations/`, which declares
|
|
273
|
+
`OperationContract<Input, Output, RefusalCode>`, `query`, `mutation`, `defineOperations`, `OperationRequest<Table>` and
|
|
274
|
+
`OperationReply<Table>`). `Input` and `Output` are named, closed types: never `any`, `unknown`, `Record<string, unknown>`,
|
|
275
|
+
`object`, an unbound generic, a function or `Date`. `RefusalCode` is a closed union of string literals, or omitted for an
|
|
276
|
+
operation that never refuses. The one route of the app takes `@Body() request: OperationRequest<Table>` and answers
|
|
277
|
+
`Promise<OperationReply<Table>>` of the same table; the wire is `{ operation, requestId, input }` in and `{ operation, requestId,
|
|
278
|
+
outcome }` out, `outcome` being the canon Outcome `{ kind: "ok", value }` or `{ kind: "refused", code }`. `starci app emit`
|
|
279
|
+
derives `be/contracts/<app>/openapi.json` (OpenAPI 3.1, `x-operation: "<name>@<version>"`, a oneOf over the operations) from the
|
|
280
|
+
table with the type checker, and the full `starci app check` fails when the committed file is stale.
|
|
281
|
+
rationale: |-
|
|
282
|
+
The operation set of an app is a contract the front end (`fe/`, through the root codegen) and other consumers generate a client from. A name-to-string registry with `unknown`
|
|
283
|
+
bodies and results forces every client to hand-type the wire; one typed table gives the client generator, the route and the
|
|
284
|
+
handlers the same types.
|
|
285
|
+
cases:
|
|
286
|
+
- id: case-1
|
|
287
|
+
when: A query with two refusals and a mutation with none
|
|
288
|
+
write: |-
|
|
289
|
+
// be/apps/core/src/operations.ts
|
|
290
|
+
export const OPERATIONS = defineOperations({
|
|
291
|
+
"sales.policy@1": query<SalesPolicyAsk, SalesPolicyView, "DENIED" | "INVALID">(),
|
|
292
|
+
"sales.close@1": mutation<SalesCloseAsk, SalesOpportunityView>(),
|
|
293
|
+
})
|
|
294
|
+
// features/api/sales/transport/http/operations.controller.ts
|
|
295
|
+
@Post("operations")
|
|
296
|
+
async invoke(@Body() request: OperationRequest<typeof OPERATIONS>): Promise<OperationReply<typeof OPERATIONS>> { ... }
|
|
297
|
+
verification:
|
|
298
|
+
automated:
|
|
299
|
+
- BE_OPERATION_CONTRACT
|
|
300
|
+
- BE_TRANSPORT_SHAPE
|
|
301
|
+
- HFS_CONTRACT_SNAPSHOT_DRIFT
|
|
302
|
+
manual:
|
|
303
|
+
- Confirm each refusal code is one the operation's owner can actually answer.
|
|
304
|
+
relatedExamples: [api]
|
|
305
|
+
files:
|
|
306
|
+
- path: src/features/api/<feature>/index.ts
|
|
307
|
+
slot: be.feature
|
|
308
|
+
role: The public surface of the feature; only apps import it.
|
|
309
|
+
rules: [BE_PUBLIC_SURFACE]
|
|
310
|
+
template: api/feature.index.ts.tpl
|
|
311
|
+
- path: src/features/api/<feature>/<feature>.module.ts
|
|
312
|
+
slot: be.feature
|
|
313
|
+
role: Composes the application handlers.
|
|
314
|
+
template: api/feature.module.ts.tpl
|
|
315
|
+
- path: src/features/api/<feature>/application/<action>.command.ts
|
|
316
|
+
slot: be.feature.application
|
|
317
|
+
role: One command (or `.query.ts`) carrying one `params` field.
|
|
318
|
+
template: api/application.command.ts.tpl
|
|
319
|
+
- path: src/features/api/<feature>/application/<action>.handler.ts
|
|
320
|
+
slot: be.feature.application
|
|
321
|
+
role: Overrides `process` and calls the domain service of its context.
|
|
322
|
+
template: api/application.handler.ts.tpl
|
|
323
|
+
- path: src/features/api/<feature>/application/<action>.contracts.ts
|
|
324
|
+
slot: be.feature.application
|
|
325
|
+
role: The plain request and result types of the action.
|
|
326
|
+
template: api/application.contracts.ts.tpl
|
|
327
|
+
- path: src/features/api/<feature>/transport/graphql/<action>.resolver.ts
|
|
328
|
+
slot: be.transport.graphql
|
|
329
|
+
role: The GraphQL door of one operation; dispatches one message.
|
|
330
|
+
rules: [BE_TRANSPORT_SHAPE, BE_DEFAULT_DENY]
|
|
331
|
+
template: api/graphql.resolver.ts.tpl
|
|
332
|
+
- path: src/features/api/<feature>/transport/graphql/dto/<action>.input.ts
|
|
333
|
+
slot: be.transport.graphql
|
|
334
|
+
role: The bounded input of the operation.
|
|
335
|
+
rules: [BE_INPUT_BOUNDED]
|
|
336
|
+
template: api/graphql.input.ts.tpl
|
|
337
|
+
- path: src/features/api/<feature>/transport/graphql/dto/<action>.type.ts
|
|
338
|
+
slot: be.transport.graphql
|
|
339
|
+
role: The typed output of the operation.
|
|
340
|
+
template: api/graphql.type.ts.tpl
|
|
341
|
+
- path: src/features/api/<feature>/transport/graphql/<action>.mapper.ts
|
|
342
|
+
slot: be.transport.graphql
|
|
343
|
+
role: Maps the input to the request and the result to the type.
|
|
344
|
+
template: api/graphql.mapper.ts.tpl
|
|
345
|
+
- path: src/features/api/<feature>/transport/graphql/<feature>-graphql.module.ts
|
|
346
|
+
slot: be.transport.graphql
|
|
347
|
+
role: One module for the whole GraphQL transport of the feature.
|
|
348
|
+
template: api/graphql.module.ts.tpl
|
|
349
|
+
- path: src/features/api/<feature>/transport/http/<action>.controller.ts
|
|
350
|
+
slot: be.transport.http
|
|
351
|
+
role: A REST door, only where GraphQL cannot serve (health, byte streams, the operation route).
|
|
352
|
+
optional: true
|
|
353
|
+
rules: [BE_TRANSPORT_SHAPE, BE_DEFAULT_DENY]
|
|
354
|
+
- path: src/features/api/<feature>/transport/http/<feature>-http.module.ts
|
|
355
|
+
slot: be.transport.http
|
|
356
|
+
role: One module for the whole HTTP transport of the feature.
|
|
357
|
+
optional: true
|
|
358
|
+
- path: src/features/api/<feature>/messages/<feature>.messages.ts
|
|
359
|
+
slot: be.feature.messages
|
|
360
|
+
role: The keyed vi and en text of the feature.
|
|
361
|
+
optional: true
|
|
362
|
+
- path: contracts/<app>/schema.graphql
|
|
363
|
+
slot: be.contract.graphql
|
|
364
|
+
role: The emitted GraphQL snapshot of the app; a stale file fails the full check.
|
|
365
|
+
optional: true
|
|
366
|
+
- path: src/tests/e2e/<area>/<action>.e2e-spec.ts
|
|
367
|
+
slot: be.tests.e2e
|
|
368
|
+
role: The operation on the booted app, refusal and unauthenticated call included.
|
|
369
|
+
optional: true
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
schema: starci/knowledge-source@1
|
|
2
|
+
id: be.cli
|
|
3
|
+
title: Backend cli
|
|
4
|
+
purpose: |-
|
|
5
|
+
Given a one-off action (migrate, seed, sync, backup, an operator command), where does it live and how is it written? Every
|
|
6
|
+
one-off action is a nest-commander command of the cli feature root `be/src/features/cli/`, compiled into the one cli app
|
|
7
|
+
`be/apps/cli` and shipped as one image run as `cli <group> <command>`. A command is an action runner: thin (R203
|
|
8
|
+
`BE_FEATURE_THIN`) like every other feature file — it maps the command line and makes one delegating call into the
|
|
9
|
+
modules — and it still owes its unit spec beside it (the `cli` role of `ruleParams.be.unitRoles`). Its slot is
|
|
10
|
+
`coverage: none`, so a command is never a coverage target.
|
|
11
|
+
appliesTo:
|
|
12
|
+
- backend
|
|
13
|
+
family: be
|
|
14
|
+
# The slot ids this topic teaches (knowledge/hfs/slots.yaml); scripts/gates/read-digest.mjs inverts these
|
|
15
|
+
# into the READ-step slot -> pattern-topic map (knowledge/op-gate.yaml kinds), each slot's topics in index.yaml order.
|
|
16
|
+
slots: [be.app.cli, be.cli]
|
|
17
|
+
pattern: cli
|
|
18
|
+
provenance:
|
|
19
|
+
reviewedAt: 2026-10-02
|
|
20
|
+
sources:
|
|
21
|
+
- knowledge/hfs/README.md
|
|
22
|
+
- knowledge/hfs/slots.yaml
|
|
23
|
+
- knowledge/hfs/rules.yaml
|
|
24
|
+
- owner decision 2026-10-02 (one cli app on nest-commander; features grouped by trigger kind)
|
|
25
|
+
- https://docs.nestjs.com/recipes/nest-commander
|
|
26
|
+
limitations: |-
|
|
27
|
+
Static checks prove where a command is declared, how the cli app boots, that every command has its spec beside it and
|
|
28
|
+
that nothing else parses the command line. They do not prove that a migration or a seed is right for live data, that a
|
|
29
|
+
deploy runs the migrate command first and once, or that an operator command is safe to re-run; the command's spec, the
|
|
30
|
+
test world's migration run and the deploy review prove those.
|
|
31
|
+
rules:
|
|
32
|
+
- id: BE-CLI-1
|
|
33
|
+
title: One cli app boots nest-commander and never serves
|
|
34
|
+
kind: mandatory
|
|
35
|
+
hfsRules: [R147, R148]
|
|
36
|
+
requirement: |-
|
|
37
|
+
Every one-off action of a back end runs in ONE app, `be/apps/cli` (slot `be.app.cli`, kind `cli`, named `cli`). It is
|
|
38
|
+
required as soon as the back end declares a connection in `hfs.json` `sides.be.connections` (its migrations run as
|
|
39
|
+
`cli migrate run`) or tracks a command under `src/features/cli/`, and it tracks its image `be/apps/cli/Dockerfile`: one
|
|
40
|
+
image, run as `cli <group> <command>`. `apps/cli/src/main.ts` boots with `CommandFactory.run(AppModule, logger)` of
|
|
41
|
+
nest-commander and never serves: no `NestFactory.create*`, no `.listen()`, no microservice connection, no
|
|
42
|
+
`@nestjs/platform-*` adapter and no `@nestjs/microservices`. `apps/cli/src/app.module.ts` composes the platform modules
|
|
43
|
+
the commands need (the database capability over every connection with its entities and migrations, like an api app) and
|
|
44
|
+
the static cli feature root module `CliModule`; `apps/cli/src/cli.options.ts` carries what the cli reads from the
|
|
45
|
+
environment, the connections it migrates among them.
|
|
46
|
+
rationale: |-
|
|
47
|
+
One image for every operator action gives one place to find, deploy and audit them, and a process that never listens
|
|
48
|
+
cannot become a second, unguarded door into the application.
|
|
49
|
+
cases:
|
|
50
|
+
- id: case-1
|
|
51
|
+
when: The cli entry
|
|
52
|
+
write: |-
|
|
53
|
+
// be/apps/cli/src/main.ts
|
|
54
|
+
async function bootstrap(): Promise<void> {
|
|
55
|
+
await CommandFactory.run(AppModule.register(parseCliOptions(EnvSource.fromProcess())), new JsonLinesLogger())
|
|
56
|
+
}
|
|
57
|
+
void bootstrap()
|
|
58
|
+
- id: case-2
|
|
59
|
+
when: The cli app calls `NestFactory.createApplicationContext` or `app.listen()`
|
|
60
|
+
write: 'Refused (BE_CLI_BOOTSTRAP): the cli app boots only through CommandFactory.run.'
|
|
61
|
+
- id: case-3
|
|
62
|
+
when: A back end declares a connection and has no apps/cli
|
|
63
|
+
write: 'Refused (BE_CLI_REQUIRED): add be/apps/cli with main.ts, app.module.ts, cli.options.ts and its Dockerfile, declared as { "name": "cli", "kind": "cli" } in hfs.json sides.be.apps.'
|
|
64
|
+
verification:
|
|
65
|
+
automated:
|
|
66
|
+
- BE_CLI_REQUIRED
|
|
67
|
+
- BE_CLI_BOOTSTRAP
|
|
68
|
+
manual:
|
|
69
|
+
- Confirm the deploy runs the cli image as a job and never as a long-running service.
|
|
70
|
+
relatedExamples: []
|
|
71
|
+
- id: BE-CLI-2
|
|
72
|
+
title: Commands live in the cli feature root as groups and sub-commands
|
|
73
|
+
kind: mandatory
|
|
74
|
+
hfsRules: [R149]
|
|
75
|
+
requirement: |-
|
|
76
|
+
A nest-commander command (`@Command` or `@SubCommand`) is declared only in the cli feature root `src/features/cli/`
|
|
77
|
+
(slot `be.cli`). The root holds `index.ts` and `cli.module.ts` and one folder per group: `<group>/<group>.cli.ts` (the
|
|
78
|
+
group `@Command` with its `subCommands`), `<group>/<group>.module.ts` and `<group>/subs/<name>.cli.ts` (a `@SubCommand`
|
|
79
|
+
class extending `CommandRunner`), one command per file. The cli feature root is a feature, so every module of it is a
|
|
80
|
+
static `@Module({ imports, providers })` with no module definition, no options file and no `register`: `CliModule`
|
|
81
|
+
imports each group module and a group module provides its commands. A command makes its one delegating call on an
|
|
82
|
+
injected runner service of the modules (the migrate and seed runners of `platform/database`) and takes its options
|
|
83
|
+
from a nest-commander `@Option` of its own (`cli seed run --env <name>`). The suffix is
|
|
84
|
+
`.cli.ts`, because `.command.ts` is the CQRS message (api.yaml).
|
|
85
|
+
rationale: |-
|
|
86
|
+
A fixed group and sub-command layout maps the command line `cli <group> <command>` to one file path, so an operator
|
|
87
|
+
command and its spec are found from the name alone.
|
|
88
|
+
cases:
|
|
89
|
+
- id: case-1
|
|
90
|
+
when: The migrate group
|
|
91
|
+
write: |-
|
|
92
|
+
// be/src/features/cli/migrate/migrate.cli.ts
|
|
93
|
+
@Command({ name: "migrate", subCommands: [RunCli], description: "Schema migrations of every connection" })
|
|
94
|
+
/** The migrate group; without a sub-command it shows its help. */
|
|
95
|
+
export class MigrateCli extends CommandRunner {
|
|
96
|
+
async run(): Promise<void> { this.command.help() }
|
|
97
|
+
}
|
|
98
|
+
- id: case-2
|
|
99
|
+
when: A `@SubCommand` declared in src/modules/platform/database/reindex.cli.ts or in features/api/
|
|
100
|
+
write: 'Refused (BE_CLI_COMMAND_SHAPE, BE_CLI_OWNER): move it to src/features/cli/<group>/subs/reindex.cli.ts and register it in the group module.'
|
|
101
|
+
verification:
|
|
102
|
+
automated:
|
|
103
|
+
- BE_CLI_COMMAND_SHAPE
|
|
104
|
+
manual: []
|
|
105
|
+
relatedExamples: []
|
|
106
|
+
- id: BE-CLI-3
|
|
107
|
+
title: A command is an action runner with its own unit spec
|
|
108
|
+
kind: mandatory
|
|
109
|
+
hfsRules: [R149, R47, R102, R203]
|
|
110
|
+
requirement: |-
|
|
111
|
+
A cli command is thin (R203 `BE_FEATURE_THIN`) like every other file of a feature-tier slot: `run` maps the command
|
|
112
|
+
line and makes one delegating call into the modules (a service, a platform capability or a modules function), with no
|
|
113
|
+
branch, loop, `try`, `throw` or computation. As an action runner it is exempt from the transport-shape law R88 (the
|
|
114
|
+
`exempt` of the `cli` entry of `ruleParams.be.unitRoles`), and it still owes its unit spec `<name>.cli.spec.ts` beside
|
|
115
|
+
it, built like a service spec (test.yaml BE-TEST-2), which asserts the delegation. The slot `be.cli` is
|
|
116
|
+
`coverage: none`, so a command is never a coverage target. A command never imports an api feature: what it shares
|
|
117
|
+
with a request lives in a domain capability (folder.yaml BE-FOLDER-2).
|
|
118
|
+
rationale: |-
|
|
119
|
+
An operator action runs against production data, often once; its delegation has no request path that an e2e run
|
|
120
|
+
exercises, so the unit spec is the only automatic proof that the command hands its inputs to the right module.
|
|
121
|
+
cases:
|
|
122
|
+
- id: case-1
|
|
123
|
+
when: A seed command
|
|
124
|
+
write: 'features/cli/seed/subs/demo.cli.ts (`@SubCommand({ name: "demo" })`, `DemoSeedCli extends CommandRunner`) reads its options and calls the seed runner of a platform or domain capability; demo.cli.spec.ts beside it asserts the delegation.'
|
|
125
|
+
- id: case-2
|
|
126
|
+
when: A command with no spec
|
|
127
|
+
write: 'Refused (BE_CLI_COMMAND_SHAPE, unit-test-colocated): features/cli/db/subs/backup.cli.ts without backup.cli.spec.ts beside it.'
|
|
128
|
+
verification:
|
|
129
|
+
automated:
|
|
130
|
+
- BE_CLI_COMMAND_SHAPE
|
|
131
|
+
- BE_TEST_TOPOLOGY
|
|
132
|
+
- BE_CONTRACT_UNGUARDED
|
|
133
|
+
- BE_SPEC_PLACEMENT
|
|
134
|
+
- BE_FEATURE_THIN
|
|
135
|
+
manual:
|
|
136
|
+
- Confirm a command that writes is safe to re-run or refuses a second run explicitly.
|
|
137
|
+
relatedExamples: []
|
|
138
|
+
- id: BE-CLI-4
|
|
139
|
+
title: Only the cli parses the command line
|
|
140
|
+
kind: mandatory
|
|
141
|
+
hfsRules: [R150]
|
|
142
|
+
requirement: |-
|
|
143
|
+
`nest-commander` is imported only by `be/apps/cli` and `src/features/cli/`. No back-end source parses command-line
|
|
144
|
+
arguments itself: `process.argv` and the parsers `commander`, `yargs` and `minimist` are refused everywhere, the cli
|
|
145
|
+
included. A one-off action anywhere but a cli command is a door this rule closes.
|
|
146
|
+
rationale: |-
|
|
147
|
+
A flag read in an api app's main.ts or a script beside the source is an operator door no review sees and no spec
|
|
148
|
+
covers.
|
|
149
|
+
cases:
|
|
150
|
+
- id: case-1
|
|
151
|
+
when: An api main.ts reads `process.argv.includes("--seed")` to seed before listening
|
|
152
|
+
write: 'Refused (BE_CLI_OWNER): the seed is `cli seed demo`, run as its own job.'
|
|
153
|
+
verification:
|
|
154
|
+
automated:
|
|
155
|
+
- BE_CLI_OWNER
|
|
156
|
+
manual: []
|
|
157
|
+
relatedExamples: []
|
|
158
|
+
- id: BE-CLI-5
|
|
159
|
+
title: Migrations and seeds run only as cli commands
|
|
160
|
+
kind: mandatory
|
|
161
|
+
hfsRules: [R34, R147]
|
|
162
|
+
requirement: |-
|
|
163
|
+
Migrations run only through the cli migrate command (`cli migrate run`) and through the test world over the same
|
|
164
|
+
connection list (`cli.options.ts`); `starci gate run --root <app>` verifies that path. Seed data never sits in a
|
|
165
|
+
migration: it is a sub-command of the `seed` group. Api and worker apps neither migrate nor seed (persistence.yaml
|
|
166
|
+
BE-PERSISTENCE-2).
|
|
167
|
+
rationale: |-
|
|
168
|
+
One runner per connection removes the race of two processes migrating, and one list shared with the test world makes
|
|
169
|
+
the tested schema the deployed one.
|
|
170
|
+
cases:
|
|
171
|
+
- id: case-1
|
|
172
|
+
when: The migrate command
|
|
173
|
+
write: 'features/cli/migrate/subs/run.cli.ts (`@SubCommand({ name: "run" })`, `RunCli extends CommandRunner`) makes one call on `MigrationRunnerService` of `platform/database`, which migrates every connection in order and fails the process on the first error; run.cli.spec.ts beside it.'
|
|
174
|
+
- id: case-2
|
|
175
|
+
when: A module runs `dataSource.runMigrations()` at boot of an api app
|
|
176
|
+
write: 'Refused (BE_SCHEMA_AUTHORITY): only the cli and the test world run migrations.'
|
|
177
|
+
verification:
|
|
178
|
+
automated:
|
|
179
|
+
- BE_SCHEMA_AUTHORITY
|
|
180
|
+
- BE_CLI_REQUIRED
|
|
181
|
+
manual:
|
|
182
|
+
- Confirm the deploy runs `cli migrate run` to completion before the api and worker apps start.
|
|
183
|
+
relatedExamples: []
|
|
184
|
+
files:
|
|
185
|
+
- path: apps/cli/Dockerfile
|
|
186
|
+
slot: repo.app-image
|
|
187
|
+
optional: true
|
|
188
|
+
role: the one cli image, run as `cli <group> <command>`
|
|
189
|
+
rules:
|
|
190
|
+
- BE_CLI_REQUIRED
|
|
191
|
+
- path: apps/cli/src/main.ts
|
|
192
|
+
slot: be.app.cli
|
|
193
|
+
optional: true
|
|
194
|
+
role: CommandFactory.run(AppModule, logger); never serves
|
|
195
|
+
rules:
|
|
196
|
+
- BE_CLI_BOOTSTRAP
|
|
197
|
+
- BE_ENTRYPOINT_ONLY_IN_APPS
|
|
198
|
+
- path: apps/cli/src/app.module.ts
|
|
199
|
+
slot: be.app.cli
|
|
200
|
+
optional: true
|
|
201
|
+
role: composes the platform modules and CliModule; no business code
|
|
202
|
+
rules:
|
|
203
|
+
- BE_APP_COMPOSITION_ONLY
|
|
204
|
+
- BE_CLI_BOOTSTRAP
|
|
205
|
+
- path: apps/cli/src/cli.options.ts
|
|
206
|
+
slot: be.app.cli
|
|
207
|
+
optional: true
|
|
208
|
+
role: what the cli reads from the environment, the connection list it migrates among them
|
|
209
|
+
rules:
|
|
210
|
+
- BE_CLI_REQUIRED
|
|
211
|
+
- BE_SCHEMA_AUTHORITY
|
|
212
|
+
- path: src/features/cli/index.ts
|
|
213
|
+
slot: be.cli
|
|
214
|
+
optional: true
|
|
215
|
+
role: exports CliModule to the cli app
|
|
216
|
+
rules:
|
|
217
|
+
- BE_PUBLIC_SURFACE
|
|
218
|
+
- path: src/features/cli/cli.module.ts
|
|
219
|
+
slot: be.cli
|
|
220
|
+
optional: true
|
|
221
|
+
role: the static cli feature root module; imports each group module
|
|
222
|
+
rules:
|
|
223
|
+
- BE_CLI_COMMAND_SHAPE
|
|
224
|
+
- BE_MODULE_SHAPE
|
|
225
|
+
- path: src/features/cli/migrate/migrate.cli.ts
|
|
226
|
+
slot: be.cli
|
|
227
|
+
optional: true
|
|
228
|
+
role: the migrate group @Command and its subCommands
|
|
229
|
+
rules:
|
|
230
|
+
- BE_CLI_COMMAND_SHAPE
|
|
231
|
+
- BE_CLI_OWNER
|
|
232
|
+
spec: src/features/cli/migrate/migrate.cli.spec.ts
|
|
233
|
+
- path: src/features/cli/migrate/migrate.module.ts
|
|
234
|
+
slot: be.cli
|
|
235
|
+
optional: true
|
|
236
|
+
role: "the static migrate group module: provides its command and sub-commands"
|
|
237
|
+
rules:
|
|
238
|
+
- BE_CLI_COMMAND_SHAPE
|
|
239
|
+
- BE_MODULE_SHAPE
|
|
240
|
+
- path: src/features/cli/migrate/subs/run.cli.ts
|
|
241
|
+
slot: be.cli
|
|
242
|
+
optional: true
|
|
243
|
+
role: "`cli migrate run`: one delegating call on the migration runner of `platform/database`, the one runner of the schema"
|
|
244
|
+
rules:
|
|
245
|
+
- BE_CLI_COMMAND_SHAPE
|
|
246
|
+
- BE_SCHEMA_AUTHORITY
|
|
247
|
+
spec: src/features/cli/migrate/subs/run.cli.spec.ts
|
|
248
|
+
- path: src/features/cli/seed/seed.cli.ts
|
|
249
|
+
slot: be.cli
|
|
250
|
+
optional: true
|
|
251
|
+
role: the seed group @Command and its subCommands
|
|
252
|
+
rules:
|
|
253
|
+
- BE_CLI_COMMAND_SHAPE
|
|
254
|
+
- BE_CLI_OWNER
|
|
255
|
+
spec: src/features/cli/seed/seed.cli.spec.ts
|
|
256
|
+
- path: src/features/cli/seed/seed.module.ts
|
|
257
|
+
slot: be.cli
|
|
258
|
+
optional: true
|
|
259
|
+
role: "the static seed group module: provides its command and sub-commands"
|
|
260
|
+
rules:
|
|
261
|
+
- BE_CLI_COMMAND_SHAPE
|
|
262
|
+
- BE_MODULE_SHAPE
|
|
263
|
+
- path: src/features/cli/seed/subs/run.cli.ts
|
|
264
|
+
slot: be.cli
|
|
265
|
+
optional: true
|
|
266
|
+
role: "`cli seed run [--env <name>]`: one delegating call on the seed runner of `platform/database`"
|
|
267
|
+
rules:
|
|
268
|
+
- BE_CLI_COMMAND_SHAPE
|
|
269
|
+
spec: src/features/cli/seed/subs/run.cli.spec.ts
|
|
270
|
+
- path: src/features/cli/<group>/<group>.cli.ts
|
|
271
|
+
slot: be.cli
|
|
272
|
+
role: the group @Command and its subCommands
|
|
273
|
+
template: cli/group.cli.ts.tpl
|
|
274
|
+
rules:
|
|
275
|
+
- BE_CLI_COMMAND_SHAPE
|
|
276
|
+
- BE_CLI_OWNER
|
|
277
|
+
- path: src/features/cli/<group>/<group>.cli.spec.ts
|
|
278
|
+
slot: be.cli
|
|
279
|
+
role: the unit spec of the group, beside it
|
|
280
|
+
template: cli/group.cli.spec.ts.tpl
|
|
281
|
+
- path: src/features/cli/<group>/<group>.module.ts
|
|
282
|
+
slot: be.cli
|
|
283
|
+
role: "the static group module: provides its command and sub-commands"
|
|
284
|
+
template: cli/group.module.ts.tpl
|
|
285
|
+
rules:
|
|
286
|
+
- BE_CLI_COMMAND_SHAPE
|
|
287
|
+
- BE_MODULE_SHAPE
|
|
288
|
+
- path: src/features/cli/<group>/subs/run.cli.ts
|
|
289
|
+
slot: be.cli
|
|
290
|
+
role: the first sub-command of the group; one delegating call on the injected runner service
|
|
291
|
+
template: cli/sub.run.cli.ts.tpl
|
|
292
|
+
rules:
|
|
293
|
+
- BE_CLI_COMMAND_SHAPE
|
|
294
|
+
- path: src/features/cli/<group>/subs/run.cli.spec.ts
|
|
295
|
+
slot: be.cli
|
|
296
|
+
role: the unit spec of the sub-command, beside it
|
|
297
|
+
template: cli/sub.run.cli.spec.ts.tpl
|