@empire-builder-kit/nx 1.0.0-beta.9 → 1.0.0-rc.2
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/NOTICE +6 -0
- package/README.md +113 -3
- package/executors.json +30 -0
- package/package.json +84 -6
- package/src/api-contract/baseline-update.d.ts +82 -0
- package/src/api-contract/baseline-update.js +225 -0
- package/src/api-contract/baseline-update.js.map +1 -0
- package/src/api-contract/compatibility.d.ts +30 -0
- package/src/api-contract/compatibility.js +643 -0
- package/src/api-contract/compatibility.js.map +1 -0
- package/src/api-contract/contract-graph.d.ts +35 -0
- package/src/api-contract/contract-graph.js +141 -0
- package/src/api-contract/contract-graph.js.map +1 -0
- package/src/api-contract/evidence.d.ts +23 -0
- package/src/api-contract/evidence.js +87 -0
- package/src/api-contract/evidence.js.map +1 -0
- package/src/api-contract/index.d.ts +6 -0
- package/src/api-contract/index.js +10 -0
- package/src/api-contract/index.js.map +1 -0
- package/src/api-contract/model.d.ts +144 -0
- package/src/api-contract/model.fixtures.d.ts +2 -0
- package/src/api-contract/model.fixtures.js +81 -0
- package/src/api-contract/model.fixtures.js.map +1 -0
- package/src/api-contract/model.js +993 -0
- package/src/api-contract/model.js.map +1 -0
- package/src/api-contract/rollout.d.ts +32 -0
- package/src/api-contract/rollout.js +88 -0
- package/src/api-contract/rollout.js.map +1 -0
- package/src/authorization/compatibility.d.ts +62 -0
- package/src/authorization/compatibility.js +175 -0
- package/src/authorization/compatibility.js.map +1 -0
- package/src/authorization/index.d.ts +1 -0
- package/src/authorization/index.js +5 -0
- package/src/authorization/index.js.map +1 -0
- package/src/blueprints/execution.d.ts +25 -1
- package/src/blueprints/execution.js +246 -83
- package/src/blueprints/execution.js.map +1 -1
- package/src/blueprints/external-sandbox.d.ts +53 -0
- package/src/blueprints/external-sandbox.js +1182 -0
- package/src/blueprints/external-sandbox.js.map +1 -0
- package/src/blueprints/manifest.d.ts +42 -2
- package/src/blueprints/manifest.js +82 -27
- package/src/blueprints/manifest.js.map +1 -1
- package/src/blueprints/resolver.d.ts +14 -5
- package/src/blueprints/resolver.js +228 -68
- package/src/blueprints/resolver.js.map +1 -1
- package/src/cli/agent-command.d.ts +30 -0
- package/src/cli/agent-command.js +204 -0
- package/src/cli/agent-command.js.map +1 -0
- package/src/cli/agent-runtime.d.ts +25 -0
- package/src/cli/agent-runtime.js +488 -0
- package/src/cli/agent-runtime.js.map +1 -0
- package/src/cli/blueprint-authority.d.ts +9 -0
- package/src/cli/blueprint-authority.js +43 -0
- package/src/cli/blueprint-authority.js.map +1 -0
- package/src/cli/blueprint-command.d.ts +24 -0
- package/src/cli/blueprint-command.js +63 -0
- package/src/cli/blueprint-command.js.map +1 -0
- package/src/cli/bootstrap.d.ts +31 -0
- package/src/cli/bootstrap.js +165 -0
- package/src/cli/bootstrap.js.map +1 -0
- package/src/cli/dev-command.d.ts +92 -0
- package/src/cli/dev-command.js +561 -0
- package/src/cli/dev-command.js.map +1 -0
- package/src/cli/main.d.ts +131 -0
- package/src/cli/main.js +1199 -0
- package/src/cli/main.js.map +1 -0
- package/src/cli/output.d.ts +19 -0
- package/src/cli/output.js +51 -0
- package/src/cli/output.js.map +1 -0
- package/src/cli/personal-secret-runtime.d.ts +81 -0
- package/src/cli/personal-secret-runtime.js +567 -0
- package/src/cli/personal-secret-runtime.js.map +1 -0
- package/src/cli/secret-terminal.d.ts +12 -0
- package/src/cli/secret-terminal.js +128 -0
- package/src/cli/secret-terminal.js.map +1 -0
- package/src/container-images.d.ts +1 -0
- package/src/container-images.js +5 -0
- package/src/container-images.js.map +1 -0
- package/src/data-lifecycle/index.d.ts +3 -0
- package/src/data-lifecycle/index.js +7 -0
- package/src/data-lifecycle/index.js.map +1 -0
- package/src/data-lifecycle/model.d.ts +172 -0
- package/src/data-lifecycle/model.fixtures.d.ts +2 -0
- package/src/data-lifecycle/model.fixtures.js +244 -0
- package/src/data-lifecycle/model.fixtures.js.map +1 -0
- package/src/data-lifecycle/model.js +95 -0
- package/src/data-lifecycle/model.js.map +1 -0
- package/src/data-lifecycle/sensitive-artifacts.d.ts +28 -0
- package/src/data-lifecycle/sensitive-artifacts.js +146 -0
- package/src/data-lifecycle/sensitive-artifacts.js.map +1 -0
- package/src/data-lifecycle/validation.d.ts +32 -0
- package/src/data-lifecycle/validation.js +837 -0
- package/src/data-lifecycle/validation.js.map +1 -0
- package/src/database-retirement/contract.d.ts +68 -0
- package/src/database-retirement/contract.js +166 -0
- package/src/database-retirement/contract.js.map +1 -0
- package/src/database-retirement/index.d.ts +1 -0
- package/src/database-retirement/index.js +5 -0
- package/src/database-retirement/index.js.map +1 -0
- package/src/deterministic-order.d.ts +2 -0
- package/src/deterministic-order.js +7 -0
- package/src/deterministic-order.js.map +1 -0
- package/src/developer-agent/context.d.ts +27 -0
- package/src/developer-agent/context.js +497 -0
- package/src/developer-agent/context.js.map +1 -0
- package/src/developer-agent/generator-planning.d.ts +34 -0
- package/src/developer-agent/generator-planning.js +645 -0
- package/src/developer-agent/generator-planning.js.map +1 -0
- package/src/developer-agent/generator-preview.d.ts +8 -0
- package/src/developer-agent/generator-preview.js +650 -0
- package/src/developer-agent/generator-preview.js.map +1 -0
- package/src/developer-agent/git-inspection.d.ts +108 -0
- package/src/developer-agent/git-inspection.js +815 -0
- package/src/developer-agent/git-inspection.js.map +1 -0
- package/src/developer-agent/handoff.d.ts +43 -0
- package/src/developer-agent/handoff.js +698 -0
- package/src/developer-agent/handoff.js.map +1 -0
- package/src/developer-agent/index.d.ts +10 -0
- package/src/developer-agent/index.js +14 -0
- package/src/developer-agent/index.js.map +1 -0
- package/src/developer-agent/model.d.ts +481 -0
- package/src/developer-agent/model.js +143 -0
- package/src/developer-agent/model.js.map +1 -0
- package/src/developer-agent/operation-registry.d.ts +45 -0
- package/src/developer-agent/operation-registry.js +1255 -0
- package/src/developer-agent/operation-registry.js.map +1 -0
- package/src/developer-agent/ordering.d.ts +9 -0
- package/src/developer-agent/ordering.js +15 -0
- package/src/developer-agent/ordering.js.map +1 -0
- package/src/developer-agent/planning.d.ts +18 -0
- package/src/developer-agent/planning.js +447 -0
- package/src/developer-agent/planning.js.map +1 -0
- package/src/developer-agent/preview-changes.d.ts +26 -0
- package/src/developer-agent/preview-changes.js +203 -0
- package/src/developer-agent/preview-changes.js.map +1 -0
- package/src/developer-agent/preview-source.d.ts +2 -0
- package/src/developer-agent/preview-source.js +16 -0
- package/src/developer-agent/preview-source.js.map +1 -0
- package/src/developer-agent/validation.d.ts +18 -0
- package/src/developer-agent/validation.js +2617 -0
- package/src/developer-agent/validation.js.map +1 -0
- package/src/developer-agent/workspace-inspection.d.ts +20 -0
- package/src/developer-agent/workspace-inspection.js +1134 -0
- package/src/developer-agent/workspace-inspection.js.map +1 -0
- package/src/developer-agent/workspace-path.d.ts +6 -0
- package/src/developer-agent/workspace-path.js +22 -0
- package/src/developer-agent/workspace-path.js.map +1 -0
- package/src/executors/blueprint-trust/blueprint-trust.d.ts +29 -0
- package/src/executors/blueprint-trust/blueprint-trust.js +115 -0
- package/src/executors/blueprint-trust/blueprint-trust.js.map +1 -0
- package/src/executors/blueprint-trust/schema.json +27 -0
- package/src/executors/blueprint-verification/blueprint-verification.d.ts +13 -0
- package/src/executors/blueprint-verification/blueprint-verification.js +110 -0
- package/src/executors/blueprint-verification/blueprint-verification.js.map +1 -0
- package/src/executors/blueprint-verification/schema.json +44 -0
- package/src/executors/deployment-plan/deployment-plan.js +1 -0
- package/src/executors/deployment-plan/deployment-plan.js.map +1 -1
- package/src/executors/dev-doctor/dev-doctor.d.ts +19 -5
- package/src/executors/dev-doctor/dev-doctor.js +186 -32
- package/src/executors/dev-doctor/dev-doctor.js.map +1 -1
- package/src/executors/dev-doctor/schema.json +1 -6
- package/src/executors/dev-setup/dev-setup.d.ts +7 -1
- package/src/executors/dev-setup/dev-setup.js +14 -3
- package/src/executors/dev-setup/dev-setup.js.map +1 -1
- package/src/executors/developer-context/developer-context.d.ts +38 -0
- package/src/executors/developer-context/developer-context.js +78 -0
- package/src/executors/developer-context/developer-context.js.map +1 -0
- package/src/executors/developer-context/schema.json +87 -0
- package/src/executors/fleet/fleet.d.ts +12 -43
- package/src/executors/fleet/fleet.js +120 -500
- package/src/executors/fleet/fleet.js.map +1 -1
- package/src/executors/fleet/schema.json +64 -14
- package/src/executors/github-bootstrap/github-bootstrap.d.ts +1 -0
- package/src/executors/github-bootstrap/github-bootstrap.js +1 -0
- package/src/executors/github-bootstrap/github-bootstrap.js.map +1 -1
- package/src/executors/github-bootstrap/schema.json +5 -0
- package/src/executors/infrastructure-plan/infrastructure-plan.d.ts +144 -0
- package/src/executors/infrastructure-plan/infrastructure-plan.js +3320 -0
- package/src/executors/infrastructure-plan/infrastructure-plan.js.map +1 -0
- package/src/executors/infrastructure-plan/schema.json +78 -0
- package/src/executors/secret-guardrails/schema.json +6 -0
- package/src/executors/secret-guardrails/secret-guardrails.d.ts +3 -0
- package/src/executors/secret-guardrails/secret-guardrails.js +44 -0
- package/src/executors/secret-guardrails/secret-guardrails.js.map +1 -0
- package/src/executors/secret-metadata/schema.json +31 -0
- package/src/executors/secret-metadata/secret-metadata.d.ts +32 -0
- package/src/executors/secret-metadata/secret-metadata.js +131 -0
- package/src/executors/secret-metadata/secret-metadata.js.map +1 -0
- package/src/executors/sst-lifecycle/logging-preflight.d.ts +17 -0
- package/src/executors/sst-lifecycle/logging-preflight.js +196 -0
- package/src/executors/sst-lifecycle/logging-preflight.js.map +1 -0
- package/src/executors/sst-lifecycle/run-sst-command.d.ts +23 -3
- package/src/executors/sst-lifecycle/run-sst-command.js +113 -10
- package/src/executors/sst-lifecycle/run-sst-command.js.map +1 -1
- package/src/executors/sst-lifecycle/schema.json +9 -5
- package/src/executors/sst-lifecycle/secret-preflight.d.ts +25 -0
- package/src/executors/sst-lifecycle/secret-preflight.js +119 -0
- package/src/executors/sst-lifecycle/secret-preflight.js.map +1 -0
- package/src/foundation/discovery.d.ts +17 -1
- package/src/foundation/discovery.js +16 -1
- package/src/foundation/discovery.js.map +1 -1
- package/src/foundation/index.d.ts +3 -0
- package/src/foundation/index.js +3 -0
- package/src/foundation/index.js.map +1 -1
- package/src/foundation/local-database-contract.d.ts +1 -0
- package/src/foundation/local-database-contract.js +3 -0
- package/src/foundation/local-database-contract.js.map +1 -1
- package/src/foundation/logging-preflight.d.ts +30 -0
- package/src/foundation/logging-preflight.js +138 -0
- package/src/foundation/logging-preflight.js.map +1 -0
- package/src/foundation/logging.d.ts +70 -0
- package/src/foundation/logging.js +133 -0
- package/src/foundation/logging.js.map +1 -0
- package/src/foundation/preflight.d.ts +9 -0
- package/src/foundation/preflight.js +58 -2
- package/src/foundation/preflight.js.map +1 -1
- package/src/foundation/provision-database-bindings.d.ts +9 -1
- package/src/foundation/provision-database-bindings.js +25 -5
- package/src/foundation/provision-database-bindings.js.map +1 -1
- package/src/foundation/provision-logical-database.d.ts +10 -2
- package/src/foundation/provision-logical-database.js +68 -113
- package/src/foundation/provision-logical-database.js.map +1 -1
- package/src/foundation/router-origin-proof.d.ts +2 -0
- package/src/foundation/router-origin-proof.js +25 -0
- package/src/foundation/router-origin-proof.js.map +1 -0
- package/src/foundation/stages.d.ts +1 -0
- package/src/foundation/stages.js +9 -1
- package/src/foundation/stages.js.map +1 -1
- package/src/frontend-security/index.d.ts +1 -0
- package/src/frontend-security/index.js +5 -0
- package/src/frontend-security/index.js.map +1 -0
- package/src/frontend-security/security-headers.d.ts +50 -0
- package/src/frontend-security/security-headers.js +418 -0
- package/src/frontend-security/security-headers.js.map +1 -0
- package/src/generators/feature-registry.d.ts +13 -0
- package/src/generators/feature-registry.js +73 -0
- package/src/generators/feature-registry.js.map +1 -0
- package/src/generators/function/function.d.ts +1 -1
- package/src/generators/function/function.js +51 -6
- package/src/generators/function/function.js.map +1 -1
- package/src/generators/function/schema.d.ts +1 -0
- package/src/generators/function/schema.json +6 -1
- package/src/generators/logging-registry.d.ts +13 -0
- package/src/generators/logging-registry.js +62 -0
- package/src/generators/logging-registry.js.map +1 -0
- package/src/generators/post-generation-install.d.ts +67 -0
- package/src/generators/post-generation-install.js +3308 -0
- package/src/generators/post-generation-install.js.map +1 -0
- package/src/generators/preset/generator.js +3 -0
- package/src/generators/preset/generator.js.map +1 -1
- package/src/generators/preset/tool-versions.d.ts +18 -0
- package/src/generators/preset/tool-versions.js +22 -0
- package/src/generators/preset/tool-versions.js.map +1 -0
- package/src/generators/preset/workspace-files-developer-agent.d.ts +14 -0
- package/src/generators/preset/workspace-files-developer-agent.js +511 -0
- package/src/generators/preset/workspace-files-developer-agent.js.map +1 -0
- package/src/generators/preset/workspace-files-foundation-workload-roles.d.ts +6 -0
- package/src/generators/preset/workspace-files-foundation-workload-roles.js +406 -0
- package/src/generators/preset/workspace-files-foundation-workload-roles.js.map +1 -0
- package/src/generators/preset/workspace-files-performance-cost.d.ts +66 -0
- package/src/generators/preset/workspace-files-performance-cost.js +866 -0
- package/src/generators/preset/workspace-files-performance-cost.js.map +1 -0
- package/src/generators/preset/workspace-files-performance-load.d.ts +73 -0
- package/src/generators/preset/workspace-files-performance-load.js +801 -0
- package/src/generators/preset/workspace-files-performance-load.js.map +1 -0
- package/src/generators/preset/workspace-files-workload-role-baseline.d.ts +9 -0
- package/src/generators/preset/workspace-files-workload-role-baseline.js +1102 -0
- package/src/generators/preset/workspace-files-workload-role-baseline.js.map +1 -0
- package/src/generators/preset/workspace-files.d.ts +14 -1
- package/src/generators/preset/workspace-files.js +8189 -245
- package/src/generators/preset/workspace-files.js.map +1 -1
- package/src/generators/repository-policy/repository-policy.js +3 -47
- package/src/generators/repository-policy/repository-policy.js.map +1 -1
- package/src/generators/slice/built-in-plan-api-contract-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-api-contract-files.js +2656 -0
- package/src/generators/slice/built-in-plan-api-contract-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-api-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-api-files.js +1186 -0
- package/src/generators/slice/built-in-plan-api-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-async-work-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-async-work-files.js +7903 -0
- package/src/generators/slice/built-in-plan-async-work-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-authorization-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-authorization-files.js +2314 -0
- package/src/generators/slice/built-in-plan-authorization-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-authorization-infrastructure-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-authorization-infrastructure-files.js +559 -0
- package/src/generators/slice/built-in-plan-authorization-infrastructure-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-data-deletion-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-data-deletion-files.js +1101 -0
- package/src/generators/slice/built-in-plan-data-deletion-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-data-export-infrastructure-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-data-export-infrastructure-files.js +249 -0
- package/src/generators/slice/built-in-plan-data-export-infrastructure-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-data-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-data-files.js +1530 -0
- package/src/generators/slice/built-in-plan-data-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-data-lifecycle-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-data-lifecycle-files.js +750 -0
- package/src/generators/slice/built-in-plan-data-lifecycle-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-data-lifecycle-runtime-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-data-lifecycle-runtime-files.js +828 -0
- package/src/generators/slice/built-in-plan-data-lifecycle-runtime-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-data-retention-job-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-data-retention-job-files.js +2604 -0
- package/src/generators/slice/built-in-plan-data-retention-job-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-data-retention-launcher-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-data-retention-launcher-files.js +144 -0
- package/src/generators/slice/built-in-plan-data-retention-launcher-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-data-rights-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-data-rights-files.js +4628 -0
- package/src/generators/slice/built-in-plan-data-rights-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-database-lifecycle-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-database-lifecycle-files.js +1901 -0
- package/src/generators/slice/built-in-plan-database-lifecycle-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-database-retirement-rehearsal-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-database-retirement-rehearsal-files.js +485 -0
- package/src/generators/slice/built-in-plan-database-retirement-rehearsal-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-foundation-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-foundation-files.js +184 -0
- package/src/generators/slice/built-in-plan-foundation-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-frontend-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-frontend-files.js +2233 -0
- package/src/generators/slice/built-in-plan-frontend-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-infrastructure-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-infrastructure-files.js +3038 -0
- package/src/generators/slice/built-in-plan-infrastructure-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-infrastructure-safety-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-infrastructure-safety-files.js +312 -0
- package/src/generators/slice/built-in-plan-infrastructure-safety-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-metadata-files.d.ts +3 -0
- package/src/generators/slice/built-in-plan-metadata-files.js +219 -0
- package/src/generators/slice/built-in-plan-metadata-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-operations-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-operations-files.js +630 -0
- package/src/generators/slice/built-in-plan-operations-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-performance-files.d.ts +3 -0
- package/src/generators/slice/built-in-plan-performance-files.js +3293 -0
- package/src/generators/slice/built-in-plan-performance-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-project-files.d.ts +3 -0
- package/src/generators/slice/built-in-plan-project-files.js +979 -0
- package/src/generators/slice/built-in-plan-project-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-release-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-release-files.js +6387 -0
- package/src/generators/slice/built-in-plan-release-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-reliability-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-reliability-files.js +4499 -0
- package/src/generators/slice/built-in-plan-reliability-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-secret-runtime-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-secret-runtime-files.js +1004 -0
- package/src/generators/slice/built-in-plan-secret-runtime-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-shared.d.ts +53 -0
- package/src/generators/slice/built-in-plan-shared.js +113 -0
- package/src/generators/slice/built-in-plan-shared.js.map +1 -0
- package/src/generators/slice/built-in-plan-testing-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-testing-files.js +2356 -0
- package/src/generators/slice/built-in-plan-testing-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-verification-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-verification-files.js +358 -0
- package/src/generators/slice/built-in-plan-verification-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-web-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-web-files.js +430 -0
- package/src/generators/slice/built-in-plan-web-files.js.map +1 -0
- package/src/generators/slice/built-in-plan-workload-role-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-workload-role-files.js +2356 -0
- package/src/generators/slice/built-in-plan-workload-role-files.js.map +1 -0
- package/src/generators/slice/built-in-plan.d.ts +8 -0
- package/src/generators/slice/built-in-plan.js +264 -0
- package/src/generators/slice/built-in-plan.js.map +1 -0
- package/src/generators/slice/schema.json +1 -1
- package/src/generators/slice/slice.d.ts +1 -22
- package/src/generators/slice/slice.js +185 -1510
- package/src/generators/slice/slice.js.map +1 -1
- package/src/generators/upgrade/schema.d.ts +2 -0
- package/src/generators/upgrade/schema.json +11 -1
- package/src/generators/upgrade/upgrade.d.ts +51 -1
- package/src/generators/upgrade/upgrade.js +820 -82
- package/src/generators/upgrade/upgrade.js.map +1 -1
- package/src/generators/workload/frozen-container.d.ts +8 -0
- package/src/generators/workload/frozen-container.js +36 -0
- package/src/generators/workload/frozen-container.js.map +1 -0
- package/src/generators/workload/performance-registration.d.ts +32 -0
- package/src/generators/workload/performance-registration.js +226 -0
- package/src/generators/workload/performance-registration.js.map +1 -0
- package/src/generators/workload/reliability-registration.d.ts +16 -0
- package/src/generators/workload/reliability-registration.js +150 -0
- package/src/generators/workload/reliability-registration.js.map +1 -0
- package/src/generators/workload/schema.d.ts +1 -0
- package/src/generators/workload/schema.json +6 -1
- package/src/generators/workload/service-performance-files.d.ts +4 -0
- package/src/generators/workload/service-performance-files.js +1846 -0
- package/src/generators/workload/service-performance-files.js.map +1 -0
- package/src/generators/workload/workload.d.ts +3 -2
- package/src/generators/workload/workload.js +1083 -18
- package/src/generators/workload/workload.js.map +1 -1
- package/src/git-policy/action-pins.d.ts +10 -0
- package/src/git-policy/action-pins.js +10 -0
- package/src/git-policy/action-pins.js.map +1 -1
- package/src/git-policy/github-bootstrap.d.ts +14 -1
- package/src/git-policy/github-bootstrap.js +274 -46
- package/src/git-policy/github-bootstrap.js.map +1 -1
- package/src/index.d.ts +2 -0
- package/src/index.js +2 -0
- package/src/index.js.map +1 -1
- package/src/infrastructure-change/convergence.d.ts +13 -0
- package/src/infrastructure-change/convergence.js +85 -0
- package/src/infrastructure-change/convergence.js.map +1 -0
- package/src/infrastructure-change/drift.d.ts +13 -0
- package/src/infrastructure-change/drift.js +112 -0
- package/src/infrastructure-change/drift.js.map +1 -0
- package/src/infrastructure-change/index.d.ts +7 -0
- package/src/infrastructure-change/index.js +11 -0
- package/src/infrastructure-change/index.js.map +1 -0
- package/src/infrastructure-change/model.d.ts +253 -0
- package/src/infrastructure-change/model.js +28 -0
- package/src/infrastructure-change/model.js.map +1 -0
- package/src/infrastructure-change/normalize.d.ts +12 -0
- package/src/infrastructure-change/normalize.js +245 -0
- package/src/infrastructure-change/normalize.js.map +1 -0
- package/src/infrastructure-change/plan.d.ts +40 -0
- package/src/infrastructure-change/plan.js +361 -0
- package/src/infrastructure-change/plan.js.map +1 -0
- package/src/infrastructure-change/risk.d.ts +7 -0
- package/src/infrastructure-change/risk.js +269 -0
- package/src/infrastructure-change/risk.js.map +1 -0
- package/src/infrastructure-change/summary.d.ts +20 -0
- package/src/infrastructure-change/summary.js +130 -0
- package/src/infrastructure-change/summary.js.map +1 -0
- package/src/local-dev/context-discovery.d.ts +2 -0
- package/src/local-dev/context-discovery.js +59 -0
- package/src/local-dev/context-discovery.js.map +1 -0
- package/src/local-dev/contract-validation.d.ts +15 -0
- package/src/local-dev/contract-validation.js +84 -0
- package/src/local-dev/contract-validation.js.map +1 -0
- package/src/local-dev/contracts.d.ts +10 -1
- package/src/local-dev/contracts.js +57 -5
- package/src/local-dev/contracts.js.map +1 -1
- package/src/local-dev/control-contract.d.ts +67 -0
- package/src/local-dev/control-contract.js +180 -0
- package/src/local-dev/control-contract.js.map +1 -0
- package/src/local-dev/dev-command-core.d.ts +60 -0
- package/src/local-dev/dev-command-core.js +89 -0
- package/src/local-dev/dev-command-core.js.map +1 -0
- package/src/local-dev/effects.d.ts +16 -0
- package/src/local-dev/effects.js +63 -0
- package/src/local-dev/effects.js.map +1 -0
- package/src/local-dev/environment-inspector.d.ts +125 -0
- package/src/local-dev/environment-inspector.js +687 -0
- package/src/local-dev/environment-inspector.js.map +1 -0
- package/src/local-dev/environment-state.d.ts +113 -0
- package/src/local-dev/environment-state.js +463 -0
- package/src/local-dev/environment-state.js.map +1 -0
- package/src/local-dev/errors.d.ts +6 -0
- package/src/local-dev/errors.js +41 -0
- package/src/local-dev/errors.js.map +1 -0
- package/src/local-dev/fleet-client.d.ts +33 -0
- package/src/local-dev/fleet-client.js +156 -0
- package/src/local-dev/fleet-client.js.map +1 -0
- package/src/local-dev/fleet-configuration.d.ts +13 -0
- package/src/local-dev/fleet-configuration.js +71 -0
- package/src/local-dev/fleet-configuration.js.map +1 -0
- package/src/local-dev/fleet-inventory.d.ts +56 -0
- package/src/local-dev/fleet-inventory.js +469 -0
- package/src/local-dev/fleet-inventory.js.map +1 -0
- package/src/local-dev/fleet-ipc.d.ts +28 -0
- package/src/local-dev/fleet-ipc.js +267 -0
- package/src/local-dev/fleet-ipc.js.map +1 -0
- package/src/local-dev/fleet-launcher.d.ts +53 -0
- package/src/local-dev/fleet-launcher.js +379 -0
- package/src/local-dev/fleet-launcher.js.map +1 -0
- package/src/local-dev/fleet-lock.d.ts +41 -0
- package/src/local-dev/fleet-lock.js +135 -0
- package/src/local-dev/fleet-lock.js.map +1 -0
- package/src/local-dev/fleet-logs.d.ts +66 -0
- package/src/local-dev/fleet-logs.js +542 -0
- package/src/local-dev/fleet-logs.js.map +1 -0
- package/src/local-dev/fleet-process.d.ts +50 -0
- package/src/local-dev/fleet-process.js +289 -0
- package/src/local-dev/fleet-process.js.map +1 -0
- package/src/local-dev/fleet-runtime.d.ts +22 -0
- package/src/local-dev/fleet-runtime.js +368 -0
- package/src/local-dev/fleet-runtime.js.map +1 -0
- package/src/local-dev/fleet-session.d.ts +70 -0
- package/src/local-dev/fleet-session.js +301 -0
- package/src/local-dev/fleet-session.js.map +1 -0
- package/src/local-dev/fleet-slice-runner-daemon.d.ts +1 -0
- package/src/local-dev/fleet-slice-runner-daemon.js +21 -0
- package/src/local-dev/fleet-slice-runner-daemon.js.map +1 -0
- package/src/local-dev/fleet-startup.d.ts +22 -0
- package/src/local-dev/fleet-startup.js +114 -0
- package/src/local-dev/fleet-startup.js.map +1 -0
- package/src/local-dev/fleet-state.d.ts +62 -0
- package/src/local-dev/fleet-state.js +297 -0
- package/src/local-dev/fleet-state.js.map +1 -0
- package/src/local-dev/fleet-supervisor-daemon.d.ts +1 -0
- package/src/local-dev/fleet-supervisor-daemon.js +41 -0
- package/src/local-dev/fleet-supervisor-daemon.js.map +1 -0
- package/src/local-dev/fleet-supervisor.d.ts +52 -0
- package/src/local-dev/fleet-supervisor.js +384 -0
- package/src/local-dev/fleet-supervisor.js.map +1 -0
- package/src/local-dev/gateway.js +1 -1
- package/src/local-dev/gateway.js.map +1 -1
- package/src/local-dev/identity.js +4 -6
- package/src/local-dev/identity.js.map +1 -1
- package/src/local-dev/index.d.ts +1 -0
- package/src/local-dev/index.js +1 -0
- package/src/local-dev/index.js.map +1 -1
- package/src/local-dev/local-context.d.ts +62 -0
- package/src/local-dev/local-context.js +299 -0
- package/src/local-dev/local-context.js.map +1 -0
- package/src/local-dev/nx-workspace.d.ts +45 -0
- package/src/local-dev/nx-workspace.js +228 -0
- package/src/local-dev/nx-workspace.js.map +1 -0
- package/src/local-dev/personal-secret-ledger.d.ts +75 -0
- package/src/local-dev/personal-secret-ledger.js +391 -0
- package/src/local-dev/personal-secret-ledger.js.map +1 -0
- package/src/local-dev/personal-stage.d.ts +18 -0
- package/src/local-dev/personal-stage.js +129 -0
- package/src/local-dev/personal-stage.js.map +1 -0
- package/src/local-dev/private-state.d.ts +17 -0
- package/src/local-dev/private-state.js +254 -0
- package/src/local-dev/private-state.js.map +1 -0
- package/src/local-dev/process-identity.d.ts +9 -0
- package/src/local-dev/process-identity.js +79 -0
- package/src/local-dev/process-identity.js.map +1 -0
- package/src/local-dev/runtime-paths.d.ts +17 -0
- package/src/local-dev/runtime-paths.js +33 -0
- package/src/local-dev/runtime-paths.js.map +1 -0
- package/src/local-dev/secret-slice-claim.d.ts +17 -0
- package/src/local-dev/secret-slice-claim.js +75 -0
- package/src/local-dev/secret-slice-claim.js.map +1 -0
- package/src/local-dev/slice-claim.d.ts +36 -0
- package/src/local-dev/slice-claim.js +199 -0
- package/src/local-dev/slice-claim.js.map +1 -0
- package/src/local-dev/slice-runner.d.ts +121 -0
- package/src/local-dev/slice-runner.js +715 -0
- package/src/local-dev/slice-runner.js.map +1 -0
- package/src/local-dev/tls.js +51 -17
- package/src/local-dev/tls.js.map +1 -1
- package/src/ownership/composition.d.ts +5 -2
- package/src/ownership/composition.js +26 -3
- package/src/ownership/composition.js.map +1 -1
- package/src/ownership/hash.d.ts +1 -1
- package/src/ownership/hash.js +3 -1
- package/src/ownership/hash.js.map +1 -1
- package/src/ownership/record.d.ts +32 -1
- package/src/ownership/record.js +139 -2
- package/src/ownership/record.js.map +1 -1
- package/src/performance/cost-collection.d.ts +225 -0
- package/src/performance/cost-collection.js +825 -0
- package/src/performance/cost-collection.js.map +1 -0
- package/src/performance/cost-controls.d.ts +131 -0
- package/src/performance/cost-controls.js +336 -0
- package/src/performance/cost-controls.js.map +1 -0
- package/src/performance/evidence.d.ts +140 -0
- package/src/performance/evidence.js +599 -0
- package/src/performance/evidence.js.map +1 -0
- package/src/performance/index.d.ts +10 -0
- package/src/performance/index.js +14 -0
- package/src/performance/index.js.map +1 -0
- package/src/performance/load-safety.d.ts +84 -0
- package/src/performance/load-safety.js +346 -0
- package/src/performance/load-safety.js.map +1 -0
- package/src/performance/model.d.ts +129 -0
- package/src/performance/model.js +452 -0
- package/src/performance/model.js.map +1 -0
- package/src/performance/pr-artifact-budget.d.ts +42 -0
- package/src/performance/pr-artifact-budget.js +151 -0
- package/src/performance/pr-artifact-budget.js.map +1 -0
- package/src/performance/runner.d.ts +75 -0
- package/src/performance/runner.js +227 -0
- package/src/performance/runner.js.map +1 -0
- package/src/performance/scenario-endpoint.d.ts +1 -0
- package/src/performance/scenario-endpoint.js +5 -0
- package/src/performance/scenario-endpoint.js.map +1 -0
- package/src/performance/scenario.d.ts +193 -0
- package/src/performance/scenario.js +736 -0
- package/src/performance/scenario.js.map +1 -0
- package/src/performance/test-fixtures.d.ts +7 -0
- package/src/performance/test-fixtures.js +169 -0
- package/src/performance/test-fixtures.js.map +1 -0
- package/src/performance/unit-cost.d.ts +105 -0
- package/src/performance/unit-cost.js +364 -0
- package/src/performance/unit-cost.js.map +1 -0
- package/src/release/index.d.ts +4 -0
- package/src/release/index.js +8 -0
- package/src/release/index.js.map +1 -0
- package/src/release/lifecycle.d.ts +132 -0
- package/src/release/lifecycle.js +411 -0
- package/src/release/lifecycle.js.map +1 -0
- package/src/release/manifest.d.ts +148 -0
- package/src/release/manifest.js +503 -0
- package/src/release/manifest.js.map +1 -0
- package/src/release/rollout.d.ts +170 -0
- package/src/release/rollout.js +578 -0
- package/src/release/rollout.js.map +1 -0
- package/src/release/source-authority.d.ts +19 -0
- package/src/release/source-authority.js +195 -0
- package/src/release/source-authority.js.map +1 -0
- package/src/repository-policy/deployment-plan.d.ts +2 -1
- package/src/repository-policy/deployment-plan.js +2 -0
- package/src/repository-policy/deployment-plan.js.map +1 -1
- package/src/repository-policy/policy.d.ts +1 -1
- package/src/repository-policy/policy.js +29 -25
- package/src/repository-policy/policy.js.map +1 -1
- package/src/schemas/aggregate-count-evidence-v1.json +135 -0
- package/src/schemas/api-contract-baseline-v1.json +674 -0
- package/src/schemas/api-contract-compatibility-report-v1.json +126 -0
- package/src/schemas/aws-billing-actual-evidence-v1.json +407 -0
- package/src/schemas/blueprint-v1.json +18 -1
- package/src/schemas/data-lifecycle-policy-v1.json +517 -0
- package/src/schemas/generated-ownership-v2.json +22 -0
- package/src/schemas/performance-policy-v1.json +335 -0
- package/src/schemas/repository-policy-v1.json +1 -0
- package/src/schemas/testing-evidence-quarantine-v1.json +168 -0
- package/src/schemas/testing-evidence-result-v1.json +319 -0
- package/src/secrets/adapters.d.ts +49 -0
- package/src/secrets/adapters.js +184 -0
- package/src/secrets/adapters.js.map +1 -0
- package/src/secrets/aws-control-plane.d.ts +20 -0
- package/src/secrets/aws-control-plane.js +255 -0
- package/src/secrets/aws-control-plane.js.map +1 -0
- package/src/secrets/declaration-verification.d.ts +11 -0
- package/src/secrets/declaration-verification.js +68 -0
- package/src/secrets/declaration-verification.js.map +1 -0
- package/src/secrets/guardrails.d.ts +26 -0
- package/src/secrets/guardrails.js +328 -0
- package/src/secrets/guardrails.js.map +1 -0
- package/src/secrets/index.d.ts +12 -0
- package/src/secrets/index.js +16 -0
- package/src/secrets/index.js.map +1 -0
- package/src/secrets/metadata.d.ts +48 -0
- package/src/secrets/metadata.js +171 -0
- package/src/secrets/metadata.js.map +1 -0
- package/src/secrets/model.d.ts +49 -0
- package/src/secrets/model.js +125 -0
- package/src/secrets/model.js.map +1 -0
- package/src/secrets/operator.d.ts +101 -0
- package/src/secrets/operator.js +229 -0
- package/src/secrets/operator.js.map +1 -0
- package/src/secrets/permissions.d.ts +34 -0
- package/src/secrets/permissions.js +86 -0
- package/src/secrets/permissions.js.map +1 -0
- package/src/secrets/personal-command.d.ts +83 -0
- package/src/secrets/personal-command.js +197 -0
- package/src/secrets/personal-command.js.map +1 -0
- package/src/secrets/personal-ledger.d.ts +21 -0
- package/src/secrets/personal-ledger.js +135 -0
- package/src/secrets/personal-ledger.js.map +1 -0
- package/src/secrets/registry.d.ts +9 -0
- package/src/secrets/registry.js +86 -0
- package/src/secrets/registry.js.map +1 -0
- package/src/secrets/verification.d.ts +18 -0
- package/src/secrets/verification.js +139 -0
- package/src/secrets/verification.js.map +1 -0
- package/src/secrets/workload-access.d.ts +46 -0
- package/src/secrets/workload-access.js +163 -0
- package/src/secrets/workload-access.js.map +1 -0
- package/src/supply-chain/action-pins.d.ts +26 -0
- package/src/supply-chain/action-pins.js +208 -0
- package/src/supply-chain/action-pins.js.map +1 -0
- package/src/supply-chain/blueprint-trust-git.d.ts +130 -0
- package/src/supply-chain/blueprint-trust-git.js +1581 -0
- package/src/supply-chain/blueprint-trust-git.js.map +1 -0
- package/src/supply-chain/blueprint-trust-process.d.ts +4 -0
- package/src/supply-chain/blueprint-trust-process.js +88 -0
- package/src/supply-chain/blueprint-trust-process.js.map +1 -0
- package/src/supply-chain/blueprint-trust.d.ts +354 -0
- package/src/supply-chain/blueprint-trust.js +1558 -0
- package/src/supply-chain/blueprint-trust.js.map +1 -0
- package/src/supply-chain/blueprint-verification-authority.d.ts +62 -0
- package/src/supply-chain/blueprint-verification-authority.js +588 -0
- package/src/supply-chain/blueprint-verification-authority.js.map +1 -0
- package/src/supply-chain/blueprint-verification-execution.d.ts +68 -0
- package/src/supply-chain/blueprint-verification-execution.js +624 -0
- package/src/supply-chain/blueprint-verification-execution.js.map +1 -0
- package/src/supply-chain/build-output.d.ts +35 -0
- package/src/supply-chain/build-output.js +398 -0
- package/src/supply-chain/build-output.js.map +1 -0
- package/src/supply-chain/common.d.ts +21 -0
- package/src/supply-chain/common.js +107 -0
- package/src/supply-chain/common.js.map +1 -0
- package/src/supply-chain/container-artifact-contract.d.ts +23 -0
- package/src/supply-chain/container-artifact-contract.js +208 -0
- package/src/supply-chain/container-artifact-contract.js.map +1 -0
- package/src/supply-chain/container-release.d.ts +119 -0
- package/src/supply-chain/container-release.js +496 -0
- package/src/supply-chain/container-release.js.map +1 -0
- package/src/supply-chain/ecr-applicability.d.ts +19 -0
- package/src/supply-chain/ecr-applicability.js +103 -0
- package/src/supply-chain/ecr-applicability.js.map +1 -0
- package/src/supply-chain/ecr-scanning.d.ts +83 -0
- package/src/supply-chain/ecr-scanning.js +321 -0
- package/src/supply-chain/ecr-scanning.js.map +1 -0
- package/src/supply-chain/ecs-deployed-image.d.ts +85 -0
- package/src/supply-chain/ecs-deployed-image.js +300 -0
- package/src/supply-chain/ecs-deployed-image.js.map +1 -0
- package/src/supply-chain/errors.d.ts +6 -0
- package/src/supply-chain/errors.js +15 -0
- package/src/supply-chain/errors.js.map +1 -0
- package/src/supply-chain/generated-blueprint-trust-command.d.ts +4 -0
- package/src/supply-chain/generated-blueprint-trust-command.js +1362 -0
- package/src/supply-chain/generated-blueprint-trust-command.js.map +1 -0
- package/src/supply-chain/generated-command.d.ts +1 -0
- package/src/supply-chain/generated-command.js +687 -0
- package/src/supply-chain/generated-command.js.map +1 -0
- package/src/supply-chain/generated-container-release-command.d.ts +16 -0
- package/src/supply-chain/generated-container-release-command.js +2087 -0
- package/src/supply-chain/generated-container-release-command.js.map +1 -0
- package/src/supply-chain/generated-ecr-collector-command.d.ts +21 -0
- package/src/supply-chain/generated-ecr-collector-command.js +1338 -0
- package/src/supply-chain/generated-ecr-collector-command.js.map +1 -0
- package/src/supply-chain/generated-files.d.ts +13 -0
- package/src/supply-chain/generated-files.js +401 -0
- package/src/supply-chain/generated-files.js.map +1 -0
- package/src/supply-chain/generated-scanner-command.d.ts +1 -0
- package/src/supply-chain/generated-scanner-command.js +718 -0
- package/src/supply-chain/generated-scanner-command.js.map +1 -0
- package/src/supply-chain/index.d.ts +28 -0
- package/src/supply-chain/index.js +35 -0
- package/src/supply-chain/index.js.map +1 -0
- package/src/supply-chain/inventory.d.ts +79 -0
- package/src/supply-chain/inventory.js +717 -0
- package/src/supply-chain/inventory.js.map +1 -0
- package/src/supply-chain/license-expression.d.ts +7 -0
- package/src/supply-chain/license-expression.js +128 -0
- package/src/supply-chain/license-expression.js.map +1 -0
- package/src/supply-chain/pnpm-toolchain-authority.d.ts +31 -0
- package/src/supply-chain/pnpm-toolchain-authority.js +316 -0
- package/src/supply-chain/pnpm-toolchain-authority.js.map +1 -0
- package/src/supply-chain/policy.d.ts +105 -0
- package/src/supply-chain/policy.js +301 -0
- package/src/supply-chain/policy.js.map +1 -0
- package/src/supply-chain/publication.d.ts +48 -0
- package/src/supply-chain/publication.js +85 -0
- package/src/supply-chain/publication.js.map +1 -0
- package/src/supply-chain/sbom.d.ts +228 -0
- package/src/supply-chain/sbom.js +826 -0
- package/src/supply-chain/sbom.js.map +1 -0
- package/src/supply-chain/scanner.d.ts +77 -0
- package/src/supply-chain/scanner.js +502 -0
- package/src/supply-chain/scanner.js.map +1 -0
- package/src/supply-chain/vendored-source.d.ts +95 -0
- package/src/supply-chain/vendored-source.js +315 -0
- package/src/supply-chain/vendored-source.js.map +1 -0
- package/src/testing-evidence/fixture-scope.d.ts +52 -0
- package/src/testing-evidence/fixture-scope.js +140 -0
- package/src/testing-evidence/fixture-scope.js.map +1 -0
- package/src/testing-evidence/index.d.ts +5 -0
- package/src/testing-evidence/index.js +9 -0
- package/src/testing-evidence/index.js.map +1 -0
- package/src/testing-evidence/quarantine.d.ts +48 -0
- package/src/testing-evidence/quarantine.js +253 -0
- package/src/testing-evidence/quarantine.js.map +1 -0
- package/src/testing-evidence/result.d.ts +108 -0
- package/src/testing-evidence/result.js +571 -0
- package/src/testing-evidence/result.js.map +1 -0
- package/src/testing-evidence/runner-adapter.d.ts +51 -0
- package/src/testing-evidence/runner-adapter.js +288 -0
- package/src/testing-evidence/runner-adapter.js.map +1 -0
- package/src/testing-evidence/sensitive-artifacts.d.ts +13 -0
- package/src/testing-evidence/sensitive-artifacts.js +93 -0
- package/src/testing-evidence/sensitive-artifacts.js.map +1 -0
- package/src/work-markers/work-markers.js +4 -3
- package/src/work-markers/work-markers.js.map +1 -1
- package/src/workload-roles/account-baseline.d.ts +132 -0
- package/src/workload-roles/account-baseline.js +743 -0
- package/src/workload-roles/account-baseline.js.map +1 -0
- package/src/workload-roles/authority.d.ts +38 -0
- package/src/workload-roles/authority.js +156 -0
- package/src/workload-roles/authority.js.map +1 -0
- package/src/workload-roles/aws-adapter.d.ts +99 -0
- package/src/workload-roles/aws-adapter.js +416 -0
- package/src/workload-roles/aws-adapter.js.map +1 -0
- package/src/workload-roles/aws-internal-handler.d.ts +27 -0
- package/src/workload-roles/aws-internal-handler.js +58 -0
- package/src/workload-roles/aws-internal-handler.js.map +1 -0
- package/src/workload-roles/aws-s3-state.d.ts +52 -0
- package/src/workload-roles/aws-s3-state.js +164 -0
- package/src/workload-roles/aws-s3-state.js.map +1 -0
- package/src/workload-roles/aws-sdk-control-plane.d.ts +12 -0
- package/src/workload-roles/aws-sdk-control-plane.js +291 -0
- package/src/workload-roles/aws-sdk-control-plane.js.map +1 -0
- package/src/workload-roles/boundary.d.ts +33 -0
- package/src/workload-roles/boundary.js +130 -0
- package/src/workload-roles/boundary.js.map +1 -0
- package/src/workload-roles/convergence.d.ts +66 -0
- package/src/workload-roles/convergence.js +186 -0
- package/src/workload-roles/convergence.js.map +1 -0
- package/src/workload-roles/effective-policy.d.ts +51 -0
- package/src/workload-roles/effective-policy.js +183 -0
- package/src/workload-roles/effective-policy.js.map +1 -0
- package/src/workload-roles/handler.d.ts +43 -0
- package/src/workload-roles/handler.js +130 -0
- package/src/workload-roles/handler.js.map +1 -0
- package/src/workload-roles/history.d.ts +47 -0
- package/src/workload-roles/history.js +324 -0
- package/src/workload-roles/history.js.map +1 -0
- package/src/workload-roles/index.d.ts +17 -0
- package/src/workload-roles/index.js +21 -0
- package/src/workload-roles/index.js.map +1 -0
- package/src/workload-roles/injection.d.ts +119 -0
- package/src/workload-roles/injection.js +495 -0
- package/src/workload-roles/injection.js.map +1 -0
- package/src/workload-roles/manifest.d.ts +54 -0
- package/src/workload-roles/manifest.js +343 -0
- package/src/workload-roles/manifest.js.map +1 -0
- package/src/workload-roles/provisioner.d.ts +70 -0
- package/src/workload-roles/provisioner.js +231 -0
- package/src/workload-roles/provisioner.js.map +1 -0
- package/src/workload-roles/registration.d.ts +101 -0
- package/src/workload-roles/registration.js +457 -0
- package/src/workload-roles/registration.js.map +1 -0
- package/src/workload-roles/stage-boundary.d.ts +31 -0
- package/src/workload-roles/stage-boundary.js +208 -0
- package/src/workload-roles/stage-boundary.js.map +1 -0
- package/src/workload-roles/standard-slice.d.ts +54 -0
- package/src/workload-roles/standard-slice.js +252 -0
- package/src/workload-roles/standard-slice.js.map +1 -0
- package/migrations/standard-pre-v1-to-v1.md +0 -11
- package/src/foundation/aurora-logical-database.d.ts +0 -76
- package/src/foundation/aurora-logical-database.js +0 -419
- package/src/foundation/aurora-logical-database.js.map +0 -1
|
@@ -1,70 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.STANDARD_LOCAL_DEV_ADAPTER = exports.PRODUCT_PACKAGE_MANAGED_JSON_POINTERS = void 0;
|
|
4
|
-
exports.createBuiltInSlicePlan = createBuiltInSlicePlan;
|
|
3
|
+
exports.createBuiltInSlicePlan = exports.STANDARD_LOCAL_DEV_ADAPTER = exports.PRODUCT_PACKAGE_MANAGED_JSON_POINTERS = void 0;
|
|
5
4
|
exports.sliceGenerator = sliceGenerator;
|
|
5
|
+
const deterministic_order_js_1 = require("../../deterministic-order.js");
|
|
6
6
|
const devkit_1 = require("@nx/devkit");
|
|
7
7
|
const node_path_1 = require("node:path");
|
|
8
|
+
const node_util_1 = require("node:util");
|
|
8
9
|
const index_js_1 = require("../../blueprints/index.js");
|
|
9
10
|
const index_js_2 = require("../../foundation/index.js");
|
|
10
11
|
const index_js_3 = require("../../ownership/index.js");
|
|
11
12
|
const index_js_4 = require("../../repository-policy/index.js");
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
next: '16.2.3',
|
|
21
|
-
pg: '^8.22.0',
|
|
22
|
-
playwright: '^1.59.1',
|
|
23
|
-
react: '19.2.4',
|
|
24
|
-
reactDom: '19.2.4',
|
|
25
|
-
typesNode: '25.5.0',
|
|
26
|
-
typesReact: '19.2.14',
|
|
27
|
-
typesReactDom: '19.2.3',
|
|
28
|
-
vitest: '4.1.4',
|
|
29
|
-
};
|
|
30
|
-
exports.PRODUCT_PACKAGE_MANAGED_JSON_POINTERS = [
|
|
31
|
-
'/name',
|
|
32
|
-
'/version',
|
|
33
|
-
'/private',
|
|
34
|
-
'/dependencies/@aws-sdk~1client-cognito-identity-provider',
|
|
35
|
-
'/dependencies/@aws-sdk~1client-eventbridge',
|
|
36
|
-
'/dependencies/@aws-sdk~1client-rds-data',
|
|
37
|
-
'/dependencies/@aws-sdk~1client-secrets-manager',
|
|
38
|
-
'/dependencies/@aws-sdk~1client-ssm',
|
|
39
|
-
'/dependencies/@empire-builder-kit~1runtime',
|
|
40
|
-
'/dependencies/drizzle-orm',
|
|
41
|
-
'/dependencies/next',
|
|
42
|
-
'/dependencies/react',
|
|
43
|
-
'/dependencies/react-dom',
|
|
44
|
-
'/devDependencies/@playwright~1test',
|
|
45
|
-
'/devDependencies/@types~1node',
|
|
46
|
-
'/devDependencies/@types~1react',
|
|
47
|
-
'/devDependencies/@types~1react-dom',
|
|
48
|
-
'/devDependencies/drizzle-kit',
|
|
49
|
-
'/devDependencies/pg',
|
|
50
|
-
'/devDependencies/vitest',
|
|
51
|
-
'/exports/.~1contracts',
|
|
52
|
-
];
|
|
53
|
-
const STANDARD_LOCAL_DEV_ADAPTER = (name) => ({
|
|
54
|
-
adapterVersion: 1,
|
|
55
|
-
auth: {
|
|
56
|
-
callbackPaths: [`/${name}/api/auth/callback`],
|
|
57
|
-
logoutPaths: [`/${name}/api/auth/sign-out`],
|
|
58
|
-
},
|
|
59
|
-
databaseMode: 'local',
|
|
60
|
-
healthPath: `/${name}/api/health`,
|
|
61
|
-
kind: 'web',
|
|
62
|
-
portEnvironment: 'EBK_DEV_PORT',
|
|
63
|
-
routePrefix: `/${name}`,
|
|
64
|
-
target: 'dev',
|
|
65
|
-
websocket: true,
|
|
66
|
-
});
|
|
67
|
-
exports.STANDARD_LOCAL_DEV_ADAPTER = STANDARD_LOCAL_DEV_ADAPTER;
|
|
13
|
+
const blueprint_verification_authority_js_1 = require("../../supply-chain/blueprint-verification-authority.js");
|
|
14
|
+
const blueprint_trust_js_1 = require("../../supply-chain/blueprint-trust.js");
|
|
15
|
+
const post_generation_install_js_1 = require("../post-generation-install.js");
|
|
16
|
+
const built_in_plan_js_1 = require("./built-in-plan.js");
|
|
17
|
+
var built_in_plan_js_2 = require("./built-in-plan.js");
|
|
18
|
+
Object.defineProperty(exports, "PRODUCT_PACKAGE_MANAGED_JSON_POINTERS", { enumerable: true, get: function () { return built_in_plan_js_2.PRODUCT_PACKAGE_MANAGED_JSON_POINTERS; } });
|
|
19
|
+
Object.defineProperty(exports, "STANDARD_LOCAL_DEV_ADAPTER", { enumerable: true, get: function () { return built_in_plan_js_2.STANDARD_LOCAL_DEV_ADAPTER; } });
|
|
20
|
+
Object.defineProperty(exports, "createBuiltInSlicePlan", { enumerable: true, get: function () { return built_in_plan_js_2.createBuiltInSlicePlan; } });
|
|
68
21
|
function readJson(tree, path, label) {
|
|
69
22
|
const contents = tree.read(path, 'utf8');
|
|
70
23
|
if (contents === null) {
|
|
@@ -94,6 +47,84 @@ function workspaceScope(packageJson) {
|
|
|
94
47
|
function json(value) {
|
|
95
48
|
return `${JSON.stringify(value, null, 2)}\n`;
|
|
96
49
|
}
|
|
50
|
+
function assertExternalBlueprintVerificationProgram(input) {
|
|
51
|
+
(0, blueprint_verification_authority_js_1.assertExternalBlueprintGeneratedNxProjectConfinement)({
|
|
52
|
+
files: input.files,
|
|
53
|
+
root: input.root,
|
|
54
|
+
});
|
|
55
|
+
const projectFiles = input.files.filter(({ path }) => path === 'project.json' || path.endsWith('/project.json'));
|
|
56
|
+
const rootProjectFile = projectFiles.find(({ path }) => path === 'project.json');
|
|
57
|
+
if (!rootProjectFile) {
|
|
58
|
+
throw new Error('External Blueprint must generate one authoritative Slice project.json before workspace writes.');
|
|
59
|
+
}
|
|
60
|
+
const projectNames = new Set();
|
|
61
|
+
let rootProject;
|
|
62
|
+
for (const file of projectFiles) {
|
|
63
|
+
if (file.mode !== 'managed' || file.managedJsonPointers !== undefined) {
|
|
64
|
+
throw new Error(`External Blueprint ${file.path} must be whole-file managed.`);
|
|
65
|
+
}
|
|
66
|
+
let project;
|
|
67
|
+
try {
|
|
68
|
+
project = JSON.parse(file.contents);
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
throw new Error(`External Blueprint ${file.path} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
72
|
+
}
|
|
73
|
+
const expectedRoot = file.path === 'project.json'
|
|
74
|
+
? input.root
|
|
75
|
+
: node_path_1.posix.join(input.root, node_path_1.posix.dirname(file.path));
|
|
76
|
+
const projectName = project && typeof project === 'object' && !Array.isArray(project)
|
|
77
|
+
? project.name
|
|
78
|
+
: undefined;
|
|
79
|
+
const targets = project && typeof project === 'object' && !Array.isArray(project)
|
|
80
|
+
? project.targets
|
|
81
|
+
: undefined;
|
|
82
|
+
if (typeof projectName !== 'string' ||
|
|
83
|
+
!/^(?:[a-z0-9][a-z0-9._-]{0,127}|@[a-z0-9][a-z0-9._-]{0,62}\/[a-z0-9][a-z0-9._-]{0,63})$/.test(projectName) ||
|
|
84
|
+
projectNames.has(projectName) ||
|
|
85
|
+
project.root !== expectedRoot ||
|
|
86
|
+
!targets ||
|
|
87
|
+
typeof targets !== 'object' ||
|
|
88
|
+
Array.isArray(targets)) {
|
|
89
|
+
throw new Error(`External Blueprint ${file.path} must identify its exact canonical project root, unique normalized name, and target map.`);
|
|
90
|
+
}
|
|
91
|
+
projectNames.add(projectName);
|
|
92
|
+
if (file === rootProjectFile)
|
|
93
|
+
rootProject = project;
|
|
94
|
+
}
|
|
95
|
+
if (!rootProject ||
|
|
96
|
+
rootProject.name !== input.name ||
|
|
97
|
+
!(0, node_util_1.isDeepStrictEqual)([...projectNames].sort(), [...input.projects].sort())) {
|
|
98
|
+
throw new Error('External Blueprint generator result.projects must exactly identify every generated project.json.');
|
|
99
|
+
}
|
|
100
|
+
(0, blueprint_trust_js_1.blueprintVerificationTargetClosure)({
|
|
101
|
+
projectRoot: input.root,
|
|
102
|
+
roots: input.verification,
|
|
103
|
+
targets: rootProject.targets,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
const FORMAT_SENSITIVE_BUILT_IN_PATHS = new Set([
|
|
107
|
+
'api/generated/contract.json',
|
|
108
|
+
'api/generated/openapi.json',
|
|
109
|
+
'web/next-env.d.ts',
|
|
110
|
+
]);
|
|
111
|
+
function dataPolicyReviewSeed(tree, root) {
|
|
112
|
+
const path = node_path_1.posix.join(root, 'data/policy.json');
|
|
113
|
+
const existing = tree.read(path, 'utf8');
|
|
114
|
+
if (existing !== null) {
|
|
115
|
+
try {
|
|
116
|
+
const reviewedAt = JSON.parse(existing).governance?.reviewedAt;
|
|
117
|
+
if (typeof reviewedAt === 'string' &&
|
|
118
|
+
new Date(reviewedAt).toISOString() === reviewedAt) {
|
|
119
|
+
return reviewedAt;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
// The generated ownership/reconciliation path reports malformed policy.
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return new Date().toISOString();
|
|
127
|
+
}
|
|
97
128
|
function reportSlicePolicyPosture(tree, name) {
|
|
98
129
|
const contents = tree.read(index_js_4.REPOSITORY_POLICY_FILE, 'utf8');
|
|
99
130
|
if (contents === null) {
|
|
@@ -133,1462 +164,49 @@ function parseBlueprintInputs(inputs) {
|
|
|
133
164
|
throw new Error(`Blueprint --inputs must be valid JSON object syntax: ${error instanceof Error ? error.message : String(error)}`);
|
|
134
165
|
}
|
|
135
166
|
}
|
|
136
|
-
function renderStandardProductFiles(name, pascalName) {
|
|
137
|
-
return {
|
|
138
|
-
'database/bindings.json': json({
|
|
139
|
-
primary: {
|
|
140
|
-
active: 'primary',
|
|
141
|
-
provisioned: ['primary'],
|
|
142
|
-
},
|
|
143
|
-
}),
|
|
144
|
-
'contracts/events.ts': `export interface ${pascalName}CreatedData {
|
|
145
|
-
id: string;
|
|
146
|
-
occurredBy: string;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
export const ${pascalName}Created = {
|
|
150
|
-
detailType: '${pascalName}Created',
|
|
151
|
-
schemaVersion: 1,
|
|
152
|
-
source: '${name}',
|
|
153
|
-
} as const;
|
|
154
|
-
`,
|
|
155
|
-
'database/schema.ts': `import { pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core';
|
|
156
|
-
|
|
157
|
-
export const records = pgTable('records', {
|
|
158
|
-
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
|
|
159
|
-
id: uuid('id').defaultRandom().primaryKey(),
|
|
160
|
-
name: text('name').notNull(),
|
|
161
|
-
});
|
|
162
|
-
`,
|
|
163
|
-
'database/migrations/0000_initial.sql': `CREATE TABLE IF NOT EXISTS "records" (
|
|
164
|
-
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
165
|
-
"name" text NOT NULL,
|
|
166
|
-
"created_at" timestamptz NOT NULL DEFAULT now()
|
|
167
|
-
);
|
|
168
|
-
`,
|
|
169
|
-
'database/migrations/meta/_journal.json': json({
|
|
170
|
-
dialect: 'postgresql',
|
|
171
|
-
entries: [
|
|
172
|
-
{
|
|
173
|
-
idx: 0,
|
|
174
|
-
tag: '0000_initial',
|
|
175
|
-
version: '7',
|
|
176
|
-
when: 0,
|
|
177
|
-
breakpoints: true,
|
|
178
|
-
},
|
|
179
|
-
],
|
|
180
|
-
version: '7',
|
|
181
|
-
}),
|
|
182
|
-
'database/migrations/meta/0000_snapshot.json': json({
|
|
183
|
-
id: 'fdcf5ce3-ada5-44bf-bd9e-e01f2abe3bc4',
|
|
184
|
-
prevId: '00000000-0000-0000-0000-000000000000',
|
|
185
|
-
version: '7',
|
|
186
|
-
dialect: 'postgresql',
|
|
187
|
-
tables: {
|
|
188
|
-
'public.records': {
|
|
189
|
-
name: 'records',
|
|
190
|
-
schema: '',
|
|
191
|
-
columns: {
|
|
192
|
-
created_at: {
|
|
193
|
-
name: 'created_at',
|
|
194
|
-
type: 'timestamp with time zone',
|
|
195
|
-
primaryKey: false,
|
|
196
|
-
notNull: true,
|
|
197
|
-
default: 'now()',
|
|
198
|
-
},
|
|
199
|
-
id: {
|
|
200
|
-
name: 'id',
|
|
201
|
-
type: 'uuid',
|
|
202
|
-
primaryKey: true,
|
|
203
|
-
notNull: true,
|
|
204
|
-
default: 'gen_random_uuid()',
|
|
205
|
-
},
|
|
206
|
-
name: {
|
|
207
|
-
name: 'name',
|
|
208
|
-
type: 'text',
|
|
209
|
-
primaryKey: false,
|
|
210
|
-
notNull: true,
|
|
211
|
-
},
|
|
212
|
-
},
|
|
213
|
-
indexes: {},
|
|
214
|
-
foreignKeys: {},
|
|
215
|
-
compositePrimaryKeys: {},
|
|
216
|
-
uniqueConstraints: {},
|
|
217
|
-
policies: {},
|
|
218
|
-
checkConstraints: {},
|
|
219
|
-
isRLSEnabled: false,
|
|
220
|
-
},
|
|
221
|
-
},
|
|
222
|
-
enums: {},
|
|
223
|
-
schemas: {},
|
|
224
|
-
sequences: {},
|
|
225
|
-
roles: {},
|
|
226
|
-
policies: {},
|
|
227
|
-
views: {},
|
|
228
|
-
_meta: { columns: {}, schemas: {}, tables: {} },
|
|
229
|
-
}),
|
|
230
|
-
'database/drizzle.config.ts': `import { createDatabaseBindingPlan, resolveLocalDatabaseContract } from '@empire-builder-kit/nx/foundation';
|
|
231
|
-
import { defineConfig } from 'drizzle-kit';
|
|
232
|
-
import databaseBindings from './bindings.json';
|
|
233
|
-
|
|
234
|
-
const plan = createDatabaseBindingPlan(databaseBindings, {
|
|
235
|
-
slice: '${name}',
|
|
236
|
-
stage: 'development',
|
|
237
|
-
});
|
|
238
|
-
const activeDatabase = plan.active.primary;
|
|
239
|
-
if (!activeDatabase) throw new Error('Database binding "primary" is required.');
|
|
240
|
-
const localDatabase = resolveLocalDatabaseContract({
|
|
241
|
-
database: activeDatabase,
|
|
242
|
-
slice: '${name}',
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
export default defineConfig({
|
|
246
|
-
dbCredentials: {
|
|
247
|
-
url: process.env.DATABASE_URL ?? \`postgresql://\${localDatabase.username}:\${localDatabase.password}@\${localDatabase.host}:\${localDatabase.port}/\${localDatabase.database}\`,
|
|
248
|
-
},
|
|
249
|
-
dialect: 'postgresql',
|
|
250
|
-
out: './database/migrations',
|
|
251
|
-
schema: './database/schema.ts',
|
|
252
|
-
});
|
|
253
|
-
`,
|
|
254
|
-
'database/docker-compose.yml': `services:
|
|
255
|
-
database:
|
|
256
|
-
image: postgres:17-alpine
|
|
257
|
-
environment:
|
|
258
|
-
POSTGRES_DB: \${EBK_LOCAL_DATABASE}
|
|
259
|
-
POSTGRES_PASSWORD: \${EBK_LOCAL_DATABASE_PASSWORD}
|
|
260
|
-
POSTGRES_USER: \${EBK_LOCAL_DATABASE_USERNAME}
|
|
261
|
-
healthcheck:
|
|
262
|
-
test: [CMD-SHELL, "pg_isready -U \${EBK_LOCAL_DATABASE_USERNAME} -d \${EBK_LOCAL_DATABASE}"]
|
|
263
|
-
interval: 2s
|
|
264
|
-
timeout: 3s
|
|
265
|
-
retries: 15
|
|
266
|
-
ports:
|
|
267
|
-
- '\${EBK_LOCAL_DATABASE_PORT}:5432'
|
|
268
|
-
volumes:
|
|
269
|
-
- database-data:/var/lib/postgresql/data
|
|
270
|
-
|
|
271
|
-
volumes:
|
|
272
|
-
database-data:
|
|
273
|
-
`,
|
|
274
|
-
'api/health.ts': `import { createHttpJsonHandler } from '@empire-builder-kit/runtime/lambda';
|
|
275
|
-
|
|
276
|
-
export const handler = createHttpJsonHandler({
|
|
277
|
-
app: '${name}',
|
|
278
|
-
operation: 'health',
|
|
279
|
-
handle: () => ({ service: '${name}', status: 'ok' }),
|
|
280
|
-
});
|
|
281
|
-
`,
|
|
282
|
-
'web/src/app/api/health/route.ts': `export function GET() {
|
|
283
|
-
return Response.json({ service: '${name}-web', status: 'ok' });
|
|
284
|
-
}
|
|
285
|
-
`,
|
|
286
|
-
'api/protected.ts': `import { createBetterAuthConfig } from '@empire-builder-kit/runtime/auth';
|
|
287
|
-
import { createAuthGuard } from '@empire-builder-kit/runtime/auth-backend';
|
|
288
|
-
import { createHttpJsonHandler } from '@empire-builder-kit/runtime/lambda';
|
|
289
|
-
|
|
290
|
-
let guard: ReturnType<typeof createAuthGuard> | undefined;
|
|
291
|
-
function getGuard() {
|
|
292
|
-
return guard ??= createAuthGuard({
|
|
293
|
-
config: createBetterAuthConfig({
|
|
294
|
-
clientId: process.env.AUTH_CLIENT_ID ?? '',
|
|
295
|
-
region: process.env.AWS_REGION ?? '',
|
|
296
|
-
userPoolId: process.env.AUTH_USER_POOL_ID ?? '',
|
|
297
|
-
}),
|
|
298
|
-
policy: { defaultKind: 'customer' },
|
|
299
|
-
});
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
export const handler = createHttpJsonHandler({
|
|
303
|
-
app: '${name}',
|
|
304
|
-
operation: 'protected-example',
|
|
305
|
-
async handle({ event }) {
|
|
306
|
-
const principal = await getGuard().authorize(event);
|
|
307
|
-
return { message: 'Authenticated request accepted.', principal };
|
|
308
|
-
},
|
|
309
|
-
});
|
|
310
|
-
`,
|
|
311
|
-
'api/event-consumer.ts': `import { parseSqsEventBridgeRecords } from '@empire-builder-kit/runtime/events';
|
|
312
|
-
import type { ${pascalName}CreatedData } from '../contracts/events.js';
|
|
313
|
-
|
|
314
|
-
interface QueueRecord { body: string; messageId: string }
|
|
315
|
-
interface QueueEvent { Records: QueueRecord[] }
|
|
316
|
-
|
|
317
|
-
export async function handler(event: QueueEvent) {
|
|
318
|
-
const batch = parseSqsEventBridgeRecords<${pascalName}CreatedData>(event.Records);
|
|
319
|
-
for (const { detailType, envelope } of batch.events) {
|
|
320
|
-
console.info(JSON.stringify({
|
|
321
|
-
eventId: envelope.meta.eventId,
|
|
322
|
-
eventType: detailType,
|
|
323
|
-
message: '${name} event consumed',
|
|
324
|
-
}));
|
|
325
|
-
}
|
|
326
|
-
return {
|
|
327
|
-
batchItemFailures: batch.failures.map(({ messageId }) => ({
|
|
328
|
-
itemIdentifier: messageId ?? '',
|
|
329
|
-
})),
|
|
330
|
-
};
|
|
331
|
-
}
|
|
332
|
-
`,
|
|
333
|
-
'api/publish-created.ts': `import { EventBridgeClient, PutEventsCommand } from '@aws-sdk/client-eventbridge';
|
|
334
|
-
import { createBetterAuthConfig } from '@empire-builder-kit/runtime/auth';
|
|
335
|
-
import { createAuthGuard } from '@empire-builder-kit/runtime/auth-backend';
|
|
336
|
-
import { createEventPublisher } from '@empire-builder-kit/runtime/events';
|
|
337
|
-
import { createHttpJsonHandler } from '@empire-builder-kit/runtime/lambda';
|
|
338
|
-
import { ${pascalName}Created } from '../contracts/events.js';
|
|
339
|
-
|
|
340
|
-
const client = new EventBridgeClient({});
|
|
341
|
-
let guard: ReturnType<typeof createAuthGuard> | undefined;
|
|
342
|
-
let publish: ReturnType<typeof createEventPublisher> | undefined;
|
|
343
|
-
function getGuard() {
|
|
344
|
-
return guard ??= createAuthGuard({
|
|
345
|
-
config: createBetterAuthConfig({
|
|
346
|
-
clientId: process.env.AUTH_CLIENT_ID ?? '',
|
|
347
|
-
region: process.env.AWS_REGION ?? '',
|
|
348
|
-
userPoolId: process.env.AUTH_USER_POOL_ID ?? '',
|
|
349
|
-
}),
|
|
350
|
-
policy: { defaultKind: 'customer' },
|
|
351
|
-
});
|
|
352
|
-
}
|
|
353
|
-
function getPublisher() {
|
|
354
|
-
return publish ??= createEventPublisher({
|
|
355
|
-
busName: process.env.EVENT_BUS_NAME ?? '',
|
|
356
|
-
stage: process.env.EBK_STAGE ?? '',
|
|
357
|
-
send: (entry) => client.send(new PutEventsCommand({ Entries: [{
|
|
358
|
-
Detail: entry.detail,
|
|
359
|
-
DetailType: entry.detailType,
|
|
360
|
-
EventBusName: entry.eventBusName,
|
|
361
|
-
Source: entry.source,
|
|
362
|
-
}] })),
|
|
363
|
-
});
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
export const handler = createHttpJsonHandler({
|
|
367
|
-
app: '${name}',
|
|
368
|
-
operation: 'publish-created',
|
|
369
|
-
async handle({ context, event }) {
|
|
370
|
-
const principal = await getGuard().authorize(event);
|
|
371
|
-
const publishedEvent = await getPublisher()(${pascalName}Created, {
|
|
372
|
-
id: crypto.randomUUID(),
|
|
373
|
-
occurredBy: principal.id,
|
|
374
|
-
}, { context });
|
|
375
|
-
return { eventId: publishedEvent.meta.eventId };
|
|
376
|
-
},
|
|
377
|
-
});
|
|
378
|
-
`,
|
|
379
|
-
'infra/product.ts': `import { provisionDatabaseBindings } from '@empire-builder-kit/nx/foundation';
|
|
380
|
-
import databaseBindings from '../database/bindings.json';
|
|
381
|
-
import { getFoundationInfrastructure } from './foundation.js';
|
|
382
|
-
// <ebk:composition-imports:start>
|
|
383
|
-
// <ebk:composition-imports:end>
|
|
384
|
-
|
|
385
|
-
export function product() {
|
|
386
|
-
const devPortInput = $dev ? (process.env.EBK_DEV_PORT ?? '3000') : '3000';
|
|
387
|
-
if (!/^\\d+$/.test(devPortInput)) {
|
|
388
|
-
throw new Error('EBK_DEV_PORT must be an integer from 1024 through 65535.');
|
|
389
|
-
}
|
|
390
|
-
const devPort = Number(devPortInput);
|
|
391
|
-
if (!Number.isSafeInteger(devPort) || devPort < 1024 || devPort > 65535) {
|
|
392
|
-
throw new Error('EBK_DEV_PORT must be an integer from 1024 through 65535.');
|
|
393
|
-
}
|
|
394
|
-
const foundation = getFoundationInfrastructure();
|
|
395
|
-
const { db: database } = provisionDatabaseBindings(foundation, {
|
|
396
|
-
bindings: databaseBindings,
|
|
397
|
-
slice: '${name}',
|
|
398
|
-
}).primary;
|
|
399
|
-
// <ebk:workload-registrations:start>
|
|
400
|
-
// <ebk:workload-registrations:end>
|
|
401
|
-
|
|
402
|
-
const authClient = foundation.userPool.addClient('${pascalName}WebAuthClient', {
|
|
403
|
-
transform: {
|
|
404
|
-
client: {
|
|
405
|
-
explicitAuthFlows: [
|
|
406
|
-
'ALLOW_USER_PASSWORD_AUTH',
|
|
407
|
-
'ALLOW_REFRESH_TOKEN_AUTH',
|
|
408
|
-
],
|
|
409
|
-
preventUserExistenceErrors: 'ENABLED',
|
|
410
|
-
},
|
|
411
|
-
},
|
|
412
|
-
});
|
|
413
|
-
|
|
414
|
-
const api = new sst.aws.ApiGatewayV2('${pascalName}Api');
|
|
415
|
-
api.route('GET /health', {
|
|
416
|
-
environment: { EBK_STAGE: $app.stage },
|
|
417
|
-
handler: 'api/health.handler',
|
|
418
|
-
logging: { format: 'json', retention: '1 month' },
|
|
419
|
-
});
|
|
420
|
-
api.route('GET /protected', {
|
|
421
|
-
environment: {
|
|
422
|
-
AUTH_CLIENT_ID: authClient.id,
|
|
423
|
-
AUTH_USER_POOL_ID: foundation.userPool.id,
|
|
424
|
-
EBK_STAGE: $app.stage,
|
|
425
|
-
},
|
|
426
|
-
handler: 'api/protected.handler',
|
|
427
|
-
link: [database],
|
|
428
|
-
logging: { format: 'json', retention: '1 month' },
|
|
429
|
-
});
|
|
430
|
-
api.route('POST /events/example', {
|
|
431
|
-
environment: {
|
|
432
|
-
AUTH_CLIENT_ID: authClient.id,
|
|
433
|
-
AUTH_USER_POOL_ID: foundation.userPool.id,
|
|
434
|
-
EBK_STAGE: $app.stage,
|
|
435
|
-
EVENT_BUS_NAME: foundation.discovery.eventBusName,
|
|
436
|
-
},
|
|
437
|
-
handler: 'api/publish-created.handler',
|
|
438
|
-
link: [foundation.eventBus],
|
|
439
|
-
logging: { format: 'json', retention: '1 month' },
|
|
440
|
-
});
|
|
441
|
-
// <ebk:function-registrations:start>
|
|
442
|
-
// <ebk:function-registrations:end>
|
|
443
|
-
|
|
444
|
-
const eventDlq = new sst.aws.Queue('${pascalName}EventDlq');
|
|
445
|
-
const eventQueue = new sst.aws.Queue('${pascalName}EventQueue', {
|
|
446
|
-
dlq: { queue: eventDlq.arn, retry: 5 },
|
|
447
|
-
});
|
|
448
|
-
eventQueue.subscribe({
|
|
449
|
-
environment: { EBK_STAGE: $app.stage },
|
|
450
|
-
handler: 'api/event-consumer.handler',
|
|
451
|
-
logging: { format: 'json', retention: '1 month' },
|
|
452
|
-
}, {
|
|
453
|
-
batch: { partialResponses: true },
|
|
454
|
-
});
|
|
455
|
-
foundation.eventBus.subscribeQueue(
|
|
456
|
-
'${pascalName}CreatedEventRule',
|
|
457
|
-
eventQueue,
|
|
458
|
-
{
|
|
459
|
-
pattern: {
|
|
460
|
-
detail: { meta: { stage: [$app.stage] } },
|
|
461
|
-
detailType: ['${pascalName}Created'],
|
|
462
|
-
source: ['${name}'],
|
|
463
|
-
},
|
|
464
|
-
},
|
|
465
|
-
);
|
|
466
|
-
|
|
467
|
-
const web = new sst.aws.Nextjs('${pascalName}Web', {
|
|
468
|
-
dev: {
|
|
469
|
-
command: \`pnpm exec next dev web --hostname 127.0.0.1 --port \${devPort}\`,
|
|
470
|
-
directory: '.',
|
|
471
|
-
title: '${pascalName} web',
|
|
472
|
-
url: \`http://127.0.0.1:\${devPort}/${name}\`,
|
|
473
|
-
},
|
|
474
|
-
environment: {
|
|
475
|
-
AUTH_CLIENT_ID: authClient.id,
|
|
476
|
-
AUTH_USER_POOL_ID: foundation.userPool.id,
|
|
477
|
-
EBK_STAGE: $app.stage,
|
|
478
|
-
EBK_FLEET_ORIGIN: process.env.EBK_FLEET_ORIGIN ?? '',
|
|
479
|
-
EBK_SECURE_COOKIES: process.env.EBK_SECURE_COOKIES ?? '',
|
|
480
|
-
NEXT_PUBLIC_API_URL: api.url,
|
|
481
|
-
},
|
|
482
|
-
link: [database, foundation.userPool],
|
|
483
|
-
path: 'web',
|
|
484
|
-
router: { instance: foundation.router, path: '/${name}' },
|
|
485
|
-
transform: {
|
|
486
|
-
server: {
|
|
487
|
-
logging: { format: 'json', retention: '1 month' },
|
|
488
|
-
},
|
|
489
|
-
},
|
|
490
|
-
vpc: foundation.vpc,
|
|
491
|
-
});
|
|
492
|
-
|
|
493
|
-
const apiAlarm = new aws.cloudwatch.MetricAlarm('${pascalName}ApiErrors', {
|
|
494
|
-
alarmActions: [foundation.discovery.alertTopicArn],
|
|
495
|
-
comparisonOperator: 'GreaterThanOrEqualToThreshold',
|
|
496
|
-
dimensions: { ApiId: api.id },
|
|
497
|
-
evaluationPeriods: 1,
|
|
498
|
-
metricName: '5xx',
|
|
499
|
-
namespace: 'AWS/ApiGateway',
|
|
500
|
-
period: 300,
|
|
501
|
-
statistic: 'Sum',
|
|
502
|
-
threshold: 1,
|
|
503
|
-
treatMissingData: 'notBreaching',
|
|
504
|
-
});
|
|
505
|
-
const dlqAlarm = new aws.cloudwatch.MetricAlarm('${pascalName}EventDlqDepth', {
|
|
506
|
-
alarmActions: [foundation.discovery.alertTopicArn],
|
|
507
|
-
comparisonOperator: 'GreaterThanOrEqualToThreshold',
|
|
508
|
-
dimensions: { QueueName: eventDlq.name },
|
|
509
|
-
evaluationPeriods: 1,
|
|
510
|
-
metricName: 'ApproximateNumberOfMessagesVisible',
|
|
511
|
-
namespace: 'AWS/SQS',
|
|
512
|
-
period: 300,
|
|
513
|
-
statistic: 'Maximum',
|
|
514
|
-
threshold: 1,
|
|
515
|
-
treatMissingData: 'notBreaching',
|
|
516
|
-
});
|
|
517
|
-
const dashboard = new aws.cloudwatch.Dashboard('${pascalName}Dashboard', {
|
|
518
|
-
dashboardName: '${name}-' + $app.stage,
|
|
519
|
-
dashboardBody: JSON.stringify({
|
|
520
|
-
widgets: [{
|
|
521
|
-
type: 'text', x: 0, y: 0, width: 24, height: 3,
|
|
522
|
-
properties: { markdown: '# ${pascalName}\\nOwner: product' },
|
|
523
|
-
}],
|
|
524
|
-
}),
|
|
525
|
-
});
|
|
526
|
-
|
|
527
|
-
return {
|
|
528
|
-
api,
|
|
529
|
-
authClient,
|
|
530
|
-
dashboard,
|
|
531
|
-
database,
|
|
532
|
-
dlqAlarm,
|
|
533
|
-
eventDlq,
|
|
534
|
-
eventQueue,
|
|
535
|
-
apiAlarm,
|
|
536
|
-
web,
|
|
537
|
-
// <ebk:composition-outputs:start>
|
|
538
|
-
// <ebk:composition-outputs:end>
|
|
539
|
-
};
|
|
540
|
-
}
|
|
541
|
-
`,
|
|
542
|
-
'web/next-env.d.ts': `/// <reference types="next" />
|
|
543
|
-
/// <reference types="next/image-types/global" />
|
|
544
|
-
`,
|
|
545
|
-
'web/tsconfig.json': json({
|
|
546
|
-
extends: '../tsconfig.json',
|
|
547
|
-
compilerOptions: {
|
|
548
|
-
incremental: true,
|
|
549
|
-
plugins: [{ name: 'next' }],
|
|
550
|
-
},
|
|
551
|
-
include: ['next-env.d.ts', '.next/types/**/*.ts', '**/*.ts', '**/*.tsx'],
|
|
552
|
-
exclude: ['node_modules'],
|
|
553
|
-
}),
|
|
554
|
-
'web/next.config.ts': `import type { NextConfig } from 'next';
|
|
555
|
-
|
|
556
|
-
const fleetOrigin = process.env.EBK_FLEET_ORIGIN?.trim();
|
|
557
|
-
|
|
558
|
-
const config: NextConfig = {
|
|
559
|
-
...(fleetOrigin ? { allowedDevOrigins: [new URL(fleetOrigin).hostname] } : {}),
|
|
560
|
-
basePath: '/${name}',
|
|
561
|
-
reactStrictMode: true,
|
|
562
|
-
};
|
|
563
|
-
|
|
564
|
-
export default config;
|
|
565
|
-
`,
|
|
566
|
-
'web/open-next.config.ts': `const config = {
|
|
567
|
-
// OpenNext runs from this web directory. Point it at the slice package so it
|
|
568
|
-
// builds only this application instead of recursively invoking the Nx root.
|
|
569
|
-
buildCommand: 'pnpm exec next build web',
|
|
570
|
-
default: {},
|
|
571
|
-
packageJsonPath: '../package.json',
|
|
572
|
-
};
|
|
573
|
-
|
|
574
|
-
export default config;
|
|
575
|
-
`,
|
|
576
|
-
'web/src/app/globals.css': `:root { color-scheme: light dark; font-family: system-ui, sans-serif; }
|
|
577
|
-
body { margin: 0; background: #07111f; color: #edf6ff; }
|
|
578
|
-
main { max-width: 64rem; margin: 0 auto; padding: 5rem 1.5rem; }
|
|
579
|
-
.card { background: #102238; border: 1px solid #29425e; border-radius: 1rem; padding: 1.5rem; }
|
|
580
|
-
a { color: #78d5ff; }
|
|
581
|
-
input, button { box-sizing: border-box; display: block; margin-top: .75rem; padding: .75rem; width: 100%; }
|
|
582
|
-
button { background: #48b7de; border: 0; color: #04111b; cursor: pointer; font-weight: 700; }
|
|
583
|
-
`,
|
|
584
|
-
'web/src/app/layout.tsx': `import type { Metadata } from 'next';
|
|
585
|
-
import type { ReactNode } from 'react';
|
|
586
|
-
import './globals.css';
|
|
587
|
-
|
|
588
|
-
export const metadata: Metadata = { title: '${pascalName}' };
|
|
589
|
-
|
|
590
|
-
export default function Layout({ children }: Readonly<{ children: ReactNode }>) {
|
|
591
|
-
return <html lang="en"><body>{children}</body></html>;
|
|
592
|
-
}
|
|
593
|
-
`,
|
|
594
|
-
'web/src/app/page.tsx': `export default function Home() {
|
|
595
|
-
return <main>
|
|
596
|
-
<p>Empire Builder Kit Product Slice</p>
|
|
597
|
-
<h1>${pascalName}</h1>
|
|
598
|
-
<div className="card">
|
|
599
|
-
<p>The web app, Lambda API, logical Postgres database, Cognito client,
|
|
600
|
-
event buffer/DLQ, dashboard, and alarms are wired and owned here.</p>
|
|
601
|
-
<a href="/${name}/sign-in">Sign in</a>
|
|
602
|
-
</div>
|
|
603
|
-
</main>;
|
|
604
|
-
}
|
|
605
|
-
`,
|
|
606
|
-
'web/src/app/sign-in/page.tsx': `'use client';
|
|
607
|
-
|
|
608
|
-
import { useState, type FormEvent } from 'react';
|
|
609
|
-
|
|
610
|
-
export default function SignIn() {
|
|
611
|
-
const [message, setMessage] = useState('');
|
|
612
|
-
async function submit(event: FormEvent<HTMLFormElement>) {
|
|
613
|
-
event.preventDefault();
|
|
614
|
-
const data = new FormData(event.currentTarget);
|
|
615
|
-
const response = await fetch('/${name}/api/auth/sign-in', {
|
|
616
|
-
body: JSON.stringify({ email: data.get('email'), password: data.get('password') }),
|
|
617
|
-
headers: { 'content-type': 'application/json' },
|
|
618
|
-
method: 'POST',
|
|
619
|
-
});
|
|
620
|
-
setMessage(response.ok ? 'Signed in.' : 'Sign-in failed.');
|
|
621
|
-
}
|
|
622
|
-
return <main><div className="card"><h1>Sign in</h1>
|
|
623
|
-
<form onSubmit={submit}>
|
|
624
|
-
<label>Email<input name="email" type="email" autoComplete="username" required /></label>
|
|
625
|
-
<label>Password<input name="password" type="password" autoComplete="current-password" required /></label>
|
|
626
|
-
<button type="submit">Sign in</button>
|
|
627
|
-
</form><p role="status">{message}</p>
|
|
628
|
-
<a href="/${name}/password-reset">Reset password</a>
|
|
629
|
-
</div></main>;
|
|
630
|
-
}
|
|
631
|
-
`,
|
|
632
|
-
'web/src/app/password-reset/page.tsx': `'use client';
|
|
633
|
-
|
|
634
|
-
import { useState, type FormEvent } from 'react';
|
|
635
|
-
|
|
636
|
-
export default function PasswordReset() {
|
|
637
|
-
const [message, setMessage] = useState('');
|
|
638
|
-
async function submit(event: FormEvent<HTMLFormElement>) {
|
|
639
|
-
event.preventDefault();
|
|
640
|
-
const data = new FormData(event.currentTarget);
|
|
641
|
-
const response = await fetch('/${name}/api/auth/password-reset', {
|
|
642
|
-
body: JSON.stringify({ email: data.get('email') }),
|
|
643
|
-
headers: { 'content-type': 'application/json' },
|
|
644
|
-
method: 'POST',
|
|
645
|
-
});
|
|
646
|
-
setMessage(response.ok ? 'If the account exists, a reset code was sent.' : 'Request failed.');
|
|
647
|
-
}
|
|
648
|
-
return <main><div className="card"><h1>Reset password</h1>
|
|
649
|
-
<form onSubmit={submit}><label>Email<input name="email" type="email" required /></label>
|
|
650
|
-
<button type="submit">Send reset code</button></form><p role="status">{message}</p>
|
|
651
|
-
</div></main>;
|
|
652
|
-
}
|
|
653
|
-
`,
|
|
654
|
-
'web/src/app/api/auth/sign-in/route.ts': `import { InitiateAuthCommand, CognitoIdentityProviderClient } from '@aws-sdk/client-cognito-identity-provider';
|
|
655
|
-
import { createSessionTokenCookiePlan } from '@empire-builder-kit/runtime/auth-session';
|
|
656
|
-
import { cookies } from 'next/headers';
|
|
657
|
-
import { NextResponse } from 'next/server';
|
|
658
|
-
|
|
659
|
-
const cognito = new CognitoIdentityProviderClient({});
|
|
660
|
-
|
|
661
|
-
export async function POST(request: Request) {
|
|
662
|
-
const body = await request.json() as { email?: string; password?: string };
|
|
663
|
-
if (!body.email || !body.password) return NextResponse.json({ ok: false }, { status: 400 });
|
|
664
|
-
const result = await cognito.send(new InitiateAuthCommand({
|
|
665
|
-
AuthFlow: 'USER_PASSWORD_AUTH',
|
|
666
|
-
ClientId: process.env.AUTH_CLIENT_ID,
|
|
667
|
-
AuthParameters: { USERNAME: body.email, PASSWORD: body.password },
|
|
668
|
-
}));
|
|
669
|
-
const auth = result.AuthenticationResult;
|
|
670
|
-
if (!auth?.AccessToken || !auth.ExpiresIn) return NextResponse.json({ ok: false }, { status: 401 });
|
|
671
|
-
const secure = process.env.EBK_SECURE_COOKIES === 'true' || process.env.NODE_ENV === 'production';
|
|
672
|
-
const store = await cookies();
|
|
673
|
-
for (const { name, value, ...options } of createSessionTokenCookiePlan({
|
|
674
|
-
accessToken: auth.AccessToken,
|
|
675
|
-
expiresAt: Math.floor(Date.now() / 1000) + auth.ExpiresIn,
|
|
676
|
-
refreshToken: auth.RefreshToken,
|
|
677
|
-
}, { namespace: '${name}', secure })) store.set(name, value, options);
|
|
678
|
-
return NextResponse.json({ ok: true });
|
|
679
|
-
}
|
|
680
|
-
`,
|
|
681
|
-
'web/src/app/api/auth/refresh/route.ts': `import { InitiateAuthCommand, CognitoIdentityProviderClient } from '@aws-sdk/client-cognito-identity-provider';
|
|
682
|
-
import { createSessionTokenCookiePlan, getSessionTokenCookieNames } from '@empire-builder-kit/runtime/auth-session';
|
|
683
|
-
import { cookies } from 'next/headers';
|
|
684
|
-
import { NextResponse } from 'next/server';
|
|
685
|
-
|
|
686
|
-
const cognito = new CognitoIdentityProviderClient({});
|
|
687
|
-
|
|
688
|
-
export async function POST() {
|
|
689
|
-
const store = await cookies();
|
|
690
|
-
const secure = process.env.EBK_SECURE_COOKIES === 'true' || process.env.NODE_ENV === 'production';
|
|
691
|
-
const names = getSessionTokenCookieNames({ namespace: '${name}', secure });
|
|
692
|
-
const refreshToken = store.get(names.refresh)?.value;
|
|
693
|
-
if (!refreshToken) return NextResponse.json({ ok: false }, { status: 401 });
|
|
694
|
-
const result = await cognito.send(new InitiateAuthCommand({
|
|
695
|
-
AuthFlow: 'REFRESH_TOKEN_AUTH', ClientId: process.env.AUTH_CLIENT_ID,
|
|
696
|
-
AuthParameters: { REFRESH_TOKEN: refreshToken },
|
|
697
|
-
}));
|
|
698
|
-
const auth = result.AuthenticationResult;
|
|
699
|
-
if (!auth?.AccessToken || !auth.ExpiresIn) return NextResponse.json({ ok: false }, { status: 401 });
|
|
700
|
-
for (const { name, value, ...options } of createSessionTokenCookiePlan({
|
|
701
|
-
accessToken: auth.AccessToken,
|
|
702
|
-
expiresAt: Math.floor(Date.now() / 1000) + auth.ExpiresIn,
|
|
703
|
-
refreshToken: auth.RefreshToken ?? refreshToken,
|
|
704
|
-
}, { namespace: '${name}', secure })) store.set(name, value, options);
|
|
705
|
-
return NextResponse.json({ ok: true });
|
|
706
|
-
}
|
|
707
|
-
`,
|
|
708
|
-
'web/src/app/api/auth/sign-out/route.ts': `import { createSessionTokenCookieDeletionPlan } from '@empire-builder-kit/runtime/auth-session';
|
|
709
|
-
import { cookies } from 'next/headers';
|
|
710
|
-
import { NextResponse } from 'next/server';
|
|
711
|
-
|
|
712
|
-
export async function POST() {
|
|
713
|
-
const store = await cookies();
|
|
714
|
-
const secure = process.env.EBK_SECURE_COOKIES === 'true' || process.env.NODE_ENV === 'production';
|
|
715
|
-
for (const { name, value, ...options } of createSessionTokenCookieDeletionPlan({
|
|
716
|
-
namespace: '${name}',
|
|
717
|
-
secure,
|
|
718
|
-
})) store.set(name, value, options);
|
|
719
|
-
return NextResponse.json({ ok: true });
|
|
720
|
-
}
|
|
721
|
-
`,
|
|
722
|
-
'web/src/app/api/auth/password-reset/route.ts': `import { ForgotPasswordCommand, CognitoIdentityProviderClient } from '@aws-sdk/client-cognito-identity-provider';
|
|
723
|
-
import { NextResponse } from 'next/server';
|
|
724
|
-
|
|
725
|
-
const cognito = new CognitoIdentityProviderClient({});
|
|
726
|
-
export async function POST(request: Request) {
|
|
727
|
-
const body = await request.json() as { email?: string };
|
|
728
|
-
if (body.email) await cognito.send(new ForgotPasswordCommand({
|
|
729
|
-
ClientId: process.env.AUTH_CLIENT_ID, Username: body.email,
|
|
730
|
-
}));
|
|
731
|
-
return NextResponse.json({ ok: true });
|
|
732
|
-
}
|
|
733
|
-
`,
|
|
734
|
-
'web/src/app/api/auth/callback/route.ts': `import { NextResponse } from 'next/server';
|
|
735
|
-
|
|
736
|
-
export function GET() {
|
|
737
|
-
return NextResponse.json({
|
|
738
|
-
message: 'The Standard Blueprint uses server-side Cognito password auth; OAuth Blueprints may replace this callback.',
|
|
739
|
-
});
|
|
740
|
-
}
|
|
741
|
-
`,
|
|
742
|
-
'web/src/app/api/protected/route.ts': `import { getSessionTokenCookieNames } from '@empire-builder-kit/runtime/auth-session';
|
|
743
|
-
import { cookies } from 'next/headers';
|
|
744
|
-
import { NextResponse } from 'next/server';
|
|
745
|
-
|
|
746
|
-
export async function GET() {
|
|
747
|
-
const store = await cookies();
|
|
748
|
-
const names = getSessionTokenCookieNames({
|
|
749
|
-
namespace: '${name}',
|
|
750
|
-
secure: process.env.EBK_SECURE_COOKIES === 'true' || process.env.NODE_ENV === 'production',
|
|
751
|
-
});
|
|
752
|
-
const accessToken = store.get(names.access)?.value;
|
|
753
|
-
if (!accessToken) return NextResponse.json({ ok: false }, { status: 401 });
|
|
754
|
-
const response = await fetch((process.env.NEXT_PUBLIC_API_URL ?? '') + '/protected', {
|
|
755
|
-
headers: { authorization: 'Bearer ' + accessToken },
|
|
756
|
-
});
|
|
757
|
-
return new NextResponse(await response.text(), {
|
|
758
|
-
headers: { 'content-type': 'application/json' },
|
|
759
|
-
status: response.status,
|
|
760
|
-
});
|
|
761
|
-
}
|
|
762
|
-
`,
|
|
763
|
-
'web/src/app/page.spec.tsx': `import { renderToStaticMarkup } from 'react-dom/server';
|
|
764
|
-
import { describe, expect, it } from 'vitest';
|
|
765
|
-
import Home from './page.js';
|
|
766
|
-
|
|
767
|
-
describe('home page', () => {
|
|
768
|
-
it('renders the Product Slice identity and sign-in path', () => {
|
|
769
|
-
const html = renderToStaticMarkup(<Home />);
|
|
770
|
-
expect(html).toContain('${pascalName}');
|
|
771
|
-
expect(html).toContain('/sign-in');
|
|
772
|
-
});
|
|
773
|
-
});
|
|
774
|
-
`,
|
|
775
|
-
'vitest.config.ts': `import { configDefaults, defineConfig } from 'vitest/config';
|
|
776
|
-
export default defineConfig({
|
|
777
|
-
test: {
|
|
778
|
-
environment: 'node',
|
|
779
|
-
env: { EBK_STAGE: 'development' },
|
|
780
|
-
exclude: [...configDefaults.exclude, '**/dist/**', 'e2e/**'],
|
|
781
|
-
},
|
|
782
|
-
});
|
|
783
|
-
`,
|
|
784
|
-
'e2e/product.spec.ts': `import { expect, test } from '@playwright/test';
|
|
785
|
-
|
|
786
|
-
test('renders the product and sign-in journey', async ({ page }) => {
|
|
787
|
-
await page.goto(process.env.EBK_SMOKE_URL ?? 'http://localhost:3000/${name}');
|
|
788
|
-
await expect(page.getByRole('heading', { name: '${pascalName}' })).toBeVisible();
|
|
789
|
-
await page.getByRole('link', { name: 'Sign in' }).click();
|
|
790
|
-
await expect(page.getByRole('heading', { name: 'Sign in' })).toBeVisible();
|
|
791
|
-
});
|
|
792
|
-
`,
|
|
793
|
-
'playwright.config.ts': `import { defineConfig } from '@playwright/test';
|
|
794
|
-
export default defineConfig({
|
|
795
|
-
testDir: './e2e',
|
|
796
|
-
use: { trace: 'retain-on-failure' },
|
|
797
|
-
});
|
|
798
|
-
`,
|
|
799
|
-
};
|
|
800
|
-
}
|
|
801
|
-
function renderSliceFiles(name, scope, runtimeVersion, ownership) {
|
|
802
|
-
const pascalName = name
|
|
803
|
-
.split('-')
|
|
804
|
-
.map((segment) => segment[0]?.toUpperCase() + segment.slice(1))
|
|
805
|
-
.join('');
|
|
806
|
-
return {
|
|
807
|
-
'.ebk/ownership.json': json(ownership),
|
|
808
|
-
'README.md': `# ${name}
|
|
809
|
-
|
|
810
|
-
This Product Slice is an independent business and deployment boundary generated from the
|
|
811
|
-
built-in Empire Builder Kit Standard Blueprint.
|
|
812
|
-
|
|
813
|
-
It consumes the Standard Foundation through its versioned capability contract. Do not import
|
|
814
|
-
files from \`packages/foundation/infra\` or from another slice's internals.
|
|
815
|
-
|
|
816
|
-
## Included product baseline
|
|
817
|
-
|
|
818
|
-
- Next.js web application with sign-in, refresh, sign-out, callback, and password-reset paths
|
|
819
|
-
- Lambda HTTP API with health and JWT-protected routes
|
|
820
|
-
- stage- and slice-scoped logical Postgres database plus migration history
|
|
821
|
-
- typed EventBridge publisher and SQS/DLQ-backed consumer
|
|
822
|
-
- Product Slice dashboard and API/DLQ alarms routed through Foundation alerts
|
|
823
|
-
- Vitest source test and Playwright deployed-smoke path
|
|
824
|
-
|
|
825
|
-
Keep business contracts in \`contracts/\`. Add long-running Services and finite Jobs only when
|
|
826
|
-
the product needs them.
|
|
827
|
-
|
|
828
|
-
Add product dependencies with \`pnpm --filter ${scope}/${name} add <package>\`. EBK owns only
|
|
829
|
-
its recorded framework keys in this package manifest, so health checks and upgrades preserve
|
|
830
|
-
dependencies, scripts, and other keys added by the product team.
|
|
831
|
-
|
|
832
|
-
## Local database
|
|
833
|
-
|
|
834
|
-
Run \`pnpm nx run ${name}:dev --stage=development\`. The target starts Docker Postgres,
|
|
835
|
-
applies local migrations, and then starts SST live mode. Set \`EBK_DEV_PORT\` to choose the
|
|
836
|
-
Next.js port; it defaults to \`3000\`. The web readiness endpoint is
|
|
837
|
-
\`http://127.0.0.1:<port>/${name}/api/health\`.
|
|
838
|
-
|
|
839
|
-
The workspace fleet target discovers this slice through its versioned
|
|
840
|
-
\`metadata.ebk.localDev\` adapter. It supplies the exact HTTPS fleet origin, secure-cookie
|
|
841
|
-
signal, callback/logout URLs, and allocated internal port; do not persist a developer port in
|
|
842
|
-
this project.
|
|
843
|
-
|
|
844
|
-
\`database/bindings.json\` is the adopter-owned database selection contract. Add a candidate
|
|
845
|
-
identifier to \`primary.provisioned\` to provision it without moving workload traffic. After the
|
|
846
|
-
candidate is migrated and verified through the database-replacement runbook, change only
|
|
847
|
-
\`primary.active\` to select it on the next reviewed deployment. Do not edit managed
|
|
848
|
-
\`infra/product.ts\` or provision databases with Foundation master credentials.
|
|
849
|
-
|
|
850
|
-
The readiness route is framework-managed for local orchestration. Put product-specific
|
|
851
|
-
dependency and status checks under \`/${name}/api/status\` rather than editing that route.
|
|
852
|
-
|
|
853
|
-
Run \`pnpm nx run ${name}:db-local-down\` when finished. The named volume preserves local data
|
|
854
|
-
between sessions.
|
|
855
|
-
|
|
856
|
-
Use \`pnpm nx run ${name}:dev --stage=<personal-name>\` for a personal live relay. The target
|
|
857
|
-
maps that consumer stage to the \`development\` Foundation and reports both stages during
|
|
858
|
-
preflight. It never deploys a personal Foundation. A normal full deploy at a mapped personal
|
|
859
|
-
stage fails closed; use a canonical stage for \`${name}:deploy\`.
|
|
860
|
-
`,
|
|
861
|
-
'contracts/index.ts': `export const ${pascalName}ContractVersion = '1.0.0' as const;
|
|
862
|
-
|
|
863
|
-
// Export transport-neutral commands, events, DTOs, and clients from this package surface.
|
|
864
|
-
`,
|
|
865
|
-
'docs/architecture.md': `# ${name} architecture
|
|
866
|
-
|
|
867
|
-
## Boundary
|
|
868
|
-
|
|
869
|
-
This slice owns its product behavior, routes, app clients, logical databases, event rules,
|
|
870
|
-
queues, alarms, dashboards, and runbooks. The Foundation owns shared capacity and policy.
|
|
871
|
-
|
|
872
|
-
## Dependencies
|
|
873
|
-
|
|
874
|
-
- Foundation contract: \`^1\`
|
|
875
|
-
- Canonical stages map to the same Foundation stage; personal/preview stages map only to
|
|
876
|
-
\`development\`
|
|
877
|
-
- Other slices: contracts-only imports
|
|
878
|
-
`,
|
|
879
|
-
'docs/contracts.md': `# ${name} contracts
|
|
880
|
-
|
|
881
|
-
Published contracts belong in \`contracts/\`. Keep them transport-neutral and versioned.
|
|
882
|
-
Record consumed slice contracts here before adding a source dependency.
|
|
883
|
-
`,
|
|
884
|
-
'docs/runbooks.md': `# ${name} runbooks
|
|
885
|
-
|
|
886
|
-
Document deployment smoke checks, alarms, rollback, event redrive, database migration, and
|
|
887
|
-
Service or Job recovery procedures as those capabilities are added.
|
|
888
|
-
`,
|
|
889
|
-
'ebk-globals.d.ts': `declare const sst: any;
|
|
890
|
-
declare const aws: any;
|
|
891
|
-
declare const $app: { name: string; stage: string };
|
|
892
|
-
declare const $config: any;
|
|
893
|
-
declare const $dev: boolean;
|
|
894
|
-
declare const $interpolate: (
|
|
895
|
-
strings: TemplateStringsArray,
|
|
896
|
-
...values: unknown[]
|
|
897
|
-
) => unknown;
|
|
898
|
-
declare const $util: any;
|
|
899
|
-
`,
|
|
900
|
-
'infra/foundation.ts': `import {
|
|
901
|
-
foundationSsmPath,
|
|
902
|
-
productSliceRegistrationPath,
|
|
903
|
-
resolveFoundationStages,
|
|
904
|
-
type FoundationDiscovery,
|
|
905
|
-
} from '@empire-builder-kit/nx/foundation';
|
|
906
|
-
|
|
907
|
-
const stages = resolveFoundationStages({
|
|
908
|
-
consumerStage: $app.stage,
|
|
909
|
-
foundationStage: process.env.EBK_FOUNDATION_STAGE,
|
|
910
|
-
});
|
|
911
|
-
|
|
912
|
-
function foundationParameter(name: Parameters<typeof foundationSsmPath>[1]) {
|
|
913
|
-
return aws.ssm.getParameterOutput({
|
|
914
|
-
name: foundationSsmPath(stages.foundationStage, name),
|
|
915
|
-
}).value;
|
|
916
|
-
}
|
|
917
|
-
|
|
918
|
-
export function getFoundation(): FoundationDiscovery {
|
|
919
|
-
return {
|
|
920
|
-
alertTopicArn: foundationParameter('alertTopicArn'),
|
|
921
|
-
capabilities: foundationParameter('capabilities').apply((value: string) =>
|
|
922
|
-
value.split(',').map((capability) => capability.trim()),
|
|
923
|
-
),
|
|
924
|
-
clusterId: foundationParameter('clusterId'),
|
|
925
|
-
contractVersion: foundationParameter('contractVersion'),
|
|
926
|
-
databaseClusterArn: foundationParameter('databaseClusterArn'),
|
|
927
|
-
databaseClusterId: foundationParameter('databaseClusterId'),
|
|
928
|
-
databaseMasterSecretArn: foundationParameter('databaseMasterSecretArn'),
|
|
929
|
-
eventBusArn: foundationParameter('eventBusArn'),
|
|
930
|
-
eventBusName: foundationParameter('eventBusName'),
|
|
931
|
-
hasPublicDomain: foundationParameter('hasPublicDomain').apply(
|
|
932
|
-
(value: string) => value === 'true',
|
|
933
|
-
),
|
|
934
|
-
identityUserPoolArn: foundationParameter('identityUserPoolArn'),
|
|
935
|
-
identityUserPoolId: foundationParameter('identityUserPoolId'),
|
|
936
|
-
rootDomain: foundationParameter('rootDomain').apply((value: string) =>
|
|
937
|
-
value === 'none' ? undefined : value,
|
|
938
|
-
),
|
|
939
|
-
routerDistributionId: foundationParameter('routerDistributionId'),
|
|
940
|
-
routerUrl: foundationParameter('routerUrl'),
|
|
941
|
-
schemaVersion: foundationParameter('schemaVersion').apply(Number),
|
|
942
|
-
vpcId: foundationParameter('vpcId'),
|
|
943
|
-
} as FoundationDiscovery;
|
|
944
|
-
}
|
|
945
|
-
|
|
946
|
-
export function getFoundationInfrastructure() {
|
|
947
|
-
const discovery = getFoundation();
|
|
948
|
-
const vpc = sst.aws.Vpc.get('FoundationVpc', discovery.vpcId);
|
|
949
|
-
const cluster = sst.aws.Cluster.get('FoundationCluster', {
|
|
950
|
-
id: discovery.clusterId,
|
|
951
|
-
vpc,
|
|
952
|
-
});
|
|
953
|
-
const router = sst.aws.Router.get(
|
|
954
|
-
'FoundationRouter',
|
|
955
|
-
discovery.routerDistributionId,
|
|
956
|
-
);
|
|
957
|
-
const userPool = sst.aws.CognitoUserPool.get(
|
|
958
|
-
'FoundationIdentity',
|
|
959
|
-
discovery.identityUserPoolId,
|
|
960
|
-
);
|
|
961
|
-
const eventBus = sst.aws.Bus.get(
|
|
962
|
-
'FoundationEventBus',
|
|
963
|
-
discovery.eventBusName,
|
|
964
|
-
);
|
|
965
|
-
const database = sst.aws.Aurora.get(
|
|
966
|
-
'FoundationDatabase',
|
|
967
|
-
discovery.databaseClusterId,
|
|
968
|
-
);
|
|
969
|
-
|
|
970
|
-
return {
|
|
971
|
-
cluster,
|
|
972
|
-
database: {
|
|
973
|
-
cluster: database,
|
|
974
|
-
clusterArn: discovery.databaseClusterArn,
|
|
975
|
-
masterSecretArn: discovery.databaseMasterSecretArn,
|
|
976
|
-
},
|
|
977
|
-
discovery,
|
|
978
|
-
eventBus,
|
|
979
|
-
router,
|
|
980
|
-
userPool,
|
|
981
|
-
vpc,
|
|
982
|
-
};
|
|
983
|
-
}
|
|
984
|
-
|
|
985
|
-
export function registerProductSlice() {
|
|
986
|
-
return new aws.ssm.Parameter('${pascalName}ProductSliceRegistration', {
|
|
987
|
-
name: productSliceRegistrationPath(
|
|
988
|
-
stages.foundationStage,
|
|
989
|
-
stages.consumerStage,
|
|
990
|
-
'${name}',
|
|
991
|
-
),
|
|
992
|
-
type: 'String',
|
|
993
|
-
value: JSON.stringify({
|
|
994
|
-
consumerStage: stages.consumerStage,
|
|
995
|
-
foundationContract: '^1.0.0',
|
|
996
|
-
foundationStage: stages.foundationStage,
|
|
997
|
-
name: '${name}',
|
|
998
|
-
registrationVersion: 1,
|
|
999
|
-
}),
|
|
1000
|
-
});
|
|
1001
|
-
}
|
|
1002
|
-
`,
|
|
1003
|
-
'infra/index.ts': `import { getFoundation, registerProductSlice } from './foundation.js';
|
|
1004
|
-
import { product } from './product.js';
|
|
1005
|
-
|
|
1006
|
-
export function app() {
|
|
1007
|
-
const foundation = getFoundation();
|
|
1008
|
-
const registration = registerProductSlice();
|
|
1009
|
-
const resources = product();
|
|
1010
|
-
return {
|
|
1011
|
-
apiUrl: resources.api.url,
|
|
1012
|
-
authClientId: resources.authClient.id,
|
|
1013
|
-
foundationContractVersion: foundation.contractVersion,
|
|
1014
|
-
name: '${name}',
|
|
1015
|
-
registration: registration.name,
|
|
1016
|
-
stage: $app.stage,
|
|
1017
|
-
webUrl: resources.web.url,
|
|
1018
|
-
};
|
|
1019
|
-
}
|
|
1020
|
-
`,
|
|
1021
|
-
'package.json': json({
|
|
1022
|
-
name: `${scope}/${name}`,
|
|
1023
|
-
version: '0.0.0',
|
|
1024
|
-
private: true,
|
|
1025
|
-
dependencies: {
|
|
1026
|
-
'@aws-sdk/client-cognito-identity-provider': PRODUCT_VERSIONS.awsCognito,
|
|
1027
|
-
'@aws-sdk/client-eventbridge': PRODUCT_VERSIONS.awsEventBridge,
|
|
1028
|
-
'@aws-sdk/client-rds-data': PRODUCT_VERSIONS.awsRdsData,
|
|
1029
|
-
'@aws-sdk/client-secrets-manager': PRODUCT_VERSIONS.awsSecretsManager,
|
|
1030
|
-
'@aws-sdk/client-ssm': PRODUCT_VERSIONS.awsSsm,
|
|
1031
|
-
'@empire-builder-kit/runtime': runtimeVersion,
|
|
1032
|
-
'drizzle-orm': PRODUCT_VERSIONS.drizzle,
|
|
1033
|
-
next: PRODUCT_VERSIONS.next,
|
|
1034
|
-
react: PRODUCT_VERSIONS.react,
|
|
1035
|
-
'react-dom': PRODUCT_VERSIONS.reactDom,
|
|
1036
|
-
},
|
|
1037
|
-
devDependencies: {
|
|
1038
|
-
'@playwright/test': PRODUCT_VERSIONS.playwright,
|
|
1039
|
-
'@types/node': PRODUCT_VERSIONS.typesNode,
|
|
1040
|
-
'@types/react': PRODUCT_VERSIONS.typesReact,
|
|
1041
|
-
'@types/react-dom': PRODUCT_VERSIONS.typesReactDom,
|
|
1042
|
-
'drizzle-kit': PRODUCT_VERSIONS.drizzleKit,
|
|
1043
|
-
pg: PRODUCT_VERSIONS.pg,
|
|
1044
|
-
vitest: PRODUCT_VERSIONS.vitest,
|
|
1045
|
-
},
|
|
1046
|
-
exports: {
|
|
1047
|
-
'./contracts': {
|
|
1048
|
-
types: './contracts/index.ts',
|
|
1049
|
-
default: './contracts/index.ts',
|
|
1050
|
-
},
|
|
1051
|
-
},
|
|
1052
|
-
}),
|
|
1053
|
-
'project.json': json({
|
|
1054
|
-
name,
|
|
1055
|
-
$schema: '../../node_modules/nx/schemas/project-schema.json',
|
|
1056
|
-
projectType: 'application',
|
|
1057
|
-
sourceRoot: `packages/${name}/infra`,
|
|
1058
|
-
implicitDependencies: ['foundation'],
|
|
1059
|
-
tags: [
|
|
1060
|
-
`scope:${name}`,
|
|
1061
|
-
'type:slice',
|
|
1062
|
-
'type:sst',
|
|
1063
|
-
'layer:product',
|
|
1064
|
-
'visibility:internal',
|
|
1065
|
-
],
|
|
1066
|
-
metadata: {
|
|
1067
|
-
ebk: {
|
|
1068
|
-
localDev: (0, exports.STANDARD_LOCAL_DEV_ADAPTER)(name),
|
|
1069
|
-
},
|
|
1070
|
-
},
|
|
1071
|
-
targets: {
|
|
1072
|
-
build: {
|
|
1073
|
-
executor: 'nx:run-commands',
|
|
1074
|
-
dependsOn: ['typecheck'],
|
|
1075
|
-
options: {
|
|
1076
|
-
command: 'next build web',
|
|
1077
|
-
cwd: `packages/${name}`,
|
|
1078
|
-
},
|
|
1079
|
-
},
|
|
1080
|
-
'db-check': {
|
|
1081
|
-
executor: 'nx:run-commands',
|
|
1082
|
-
options: {
|
|
1083
|
-
command: 'node scripts/check-database.mjs',
|
|
1084
|
-
cwd: `packages/${name}`,
|
|
1085
|
-
},
|
|
1086
|
-
},
|
|
1087
|
-
'db-generate': {
|
|
1088
|
-
executor: 'nx:run-commands',
|
|
1089
|
-
options: {
|
|
1090
|
-
command: 'drizzle-kit generate --config=database/drizzle.config.ts',
|
|
1091
|
-
cwd: `packages/${name}`,
|
|
1092
|
-
},
|
|
1093
|
-
},
|
|
1094
|
-
'db-migrate': {
|
|
1095
|
-
executor: 'nx:run-commands',
|
|
1096
|
-
dependsOn: [{ target: 'deploy-infrastructure', params: 'forward' }],
|
|
1097
|
-
options: {
|
|
1098
|
-
command: 'node scripts/migrate-database.mjs',
|
|
1099
|
-
cwd: `packages/${name}`,
|
|
1100
|
-
forwardAllArgs: true,
|
|
1101
|
-
},
|
|
1102
|
-
},
|
|
1103
|
-
'db-local-down': {
|
|
1104
|
-
executor: 'nx:run-commands',
|
|
1105
|
-
options: {
|
|
1106
|
-
command: 'node scripts/local-database.mjs down',
|
|
1107
|
-
cwd: `packages/${name}`,
|
|
1108
|
-
},
|
|
1109
|
-
},
|
|
1110
|
-
'db-local-migrate': {
|
|
1111
|
-
executor: 'nx:run-commands',
|
|
1112
|
-
dependsOn: ['db-local-up'],
|
|
1113
|
-
options: {
|
|
1114
|
-
command: 'drizzle-kit migrate --config=database/drizzle.config.ts',
|
|
1115
|
-
cwd: `packages/${name}`,
|
|
1116
|
-
},
|
|
1117
|
-
},
|
|
1118
|
-
'db-local-up': {
|
|
1119
|
-
executor: 'nx:run-commands',
|
|
1120
|
-
dependsOn: ['db-check'],
|
|
1121
|
-
options: {
|
|
1122
|
-
command: 'node scripts/local-database.mjs up',
|
|
1123
|
-
cwd: `packages/${name}`,
|
|
1124
|
-
},
|
|
1125
|
-
},
|
|
1126
|
-
deploy: {
|
|
1127
|
-
executor: 'nx:run-commands',
|
|
1128
|
-
dependsOn: [{ target: 'db-migrate', params: 'forward' }],
|
|
1129
|
-
options: {
|
|
1130
|
-
command: 'node scripts/confirm-deploy.mjs',
|
|
1131
|
-
cwd: `packages/${name}`,
|
|
1132
|
-
forwardAllArgs: true,
|
|
1133
|
-
},
|
|
1134
|
-
},
|
|
1135
|
-
'deploy-infrastructure': {
|
|
1136
|
-
executor: '@empire-builder-kit/nx:deploy',
|
|
1137
|
-
dependsOn: [
|
|
1138
|
-
'verify',
|
|
1139
|
-
{ target: 'foundation-ready', params: 'forward' },
|
|
1140
|
-
],
|
|
1141
|
-
options: {
|
|
1142
|
-
cwd: `packages/${name}`,
|
|
1143
|
-
stage: 'development',
|
|
1144
|
-
stageMode: 'consumer',
|
|
1145
|
-
},
|
|
1146
|
-
},
|
|
1147
|
-
dev: {
|
|
1148
|
-
executor: '@empire-builder-kit/nx:dev',
|
|
1149
|
-
dependsOn: [
|
|
1150
|
-
'dev-prerequisite',
|
|
1151
|
-
'db-local-migrate',
|
|
1152
|
-
{ target: 'foundation-preflight', params: 'forward' },
|
|
1153
|
-
],
|
|
1154
|
-
options: {
|
|
1155
|
-
cwd: `packages/${name}`,
|
|
1156
|
-
stage: 'development',
|
|
1157
|
-
stageMode: 'consumer',
|
|
1158
|
-
},
|
|
1159
|
-
},
|
|
1160
|
-
'dev-prerequisite': {
|
|
1161
|
-
executor: 'nx:run-commands',
|
|
1162
|
-
dependsOn: ['db-check', 'typecheck'],
|
|
1163
|
-
options: {
|
|
1164
|
-
command: 'node scripts/verify-live-mode.mjs',
|
|
1165
|
-
cwd: `packages/${name}`,
|
|
1166
|
-
},
|
|
1167
|
-
},
|
|
1168
|
-
lint: {
|
|
1169
|
-
executor: 'nx:run-commands',
|
|
1170
|
-
options: {
|
|
1171
|
-
command: 'eslint .',
|
|
1172
|
-
cwd: `packages/${name}`,
|
|
1173
|
-
},
|
|
1174
|
-
},
|
|
1175
|
-
'foundation-preflight': {
|
|
1176
|
-
executor: '@empire-builder-kit/nx:foundation-preflight',
|
|
1177
|
-
options: {
|
|
1178
|
-
capabilities: [...ownership.foundation.capabilities],
|
|
1179
|
-
contract: ownership.foundation.contract,
|
|
1180
|
-
stage: 'development',
|
|
1181
|
-
},
|
|
1182
|
-
},
|
|
1183
|
-
'foundation-ready': {
|
|
1184
|
-
executor: '@empire-builder-kit/nx:foundation-preflight',
|
|
1185
|
-
dependsOn: [
|
|
1186
|
-
{ projects: ['foundation'], target: 'verify', params: 'ignore' },
|
|
1187
|
-
],
|
|
1188
|
-
options: {
|
|
1189
|
-
capabilities: [...ownership.foundation.capabilities],
|
|
1190
|
-
contract: ownership.foundation.contract,
|
|
1191
|
-
deployIfMissing: true,
|
|
1192
|
-
foundationProject: 'foundation',
|
|
1193
|
-
stage: 'development',
|
|
1194
|
-
},
|
|
1195
|
-
},
|
|
1196
|
-
refresh: {
|
|
1197
|
-
executor: '@empire-builder-kit/nx:refresh',
|
|
1198
|
-
options: {
|
|
1199
|
-
cwd: `packages/${name}`,
|
|
1200
|
-
stage: 'development',
|
|
1201
|
-
stageMode: 'consumer',
|
|
1202
|
-
},
|
|
1203
|
-
},
|
|
1204
|
-
remove: {
|
|
1205
|
-
executor: '@empire-builder-kit/nx:remove',
|
|
1206
|
-
options: {
|
|
1207
|
-
cwd: `packages/${name}`,
|
|
1208
|
-
stage: 'development',
|
|
1209
|
-
stageMode: 'consumer',
|
|
1210
|
-
},
|
|
1211
|
-
},
|
|
1212
|
-
'smoke-deployed': {
|
|
1213
|
-
executor: 'nx:run-commands',
|
|
1214
|
-
options: {
|
|
1215
|
-
command: 'playwright install chromium && playwright test',
|
|
1216
|
-
cwd: `packages/${name}`,
|
|
1217
|
-
},
|
|
1218
|
-
},
|
|
1219
|
-
'smoke-deployed-check': {
|
|
1220
|
-
executor: 'nx:run-commands',
|
|
1221
|
-
options: {
|
|
1222
|
-
command: 'playwright test --list',
|
|
1223
|
-
cwd: `packages/${name}`,
|
|
1224
|
-
},
|
|
1225
|
-
},
|
|
1226
|
-
test: {
|
|
1227
|
-
executor: 'nx:run-commands',
|
|
1228
|
-
options: {
|
|
1229
|
-
command: 'vitest run',
|
|
1230
|
-
cwd: `packages/${name}`,
|
|
1231
|
-
},
|
|
1232
|
-
},
|
|
1233
|
-
typecheck: {
|
|
1234
|
-
executor: 'nx:run-commands',
|
|
1235
|
-
options: {
|
|
1236
|
-
command: 'tsc --noEmit -p tsconfig.json',
|
|
1237
|
-
cwd: `packages/${name}`,
|
|
1238
|
-
},
|
|
1239
|
-
},
|
|
1240
|
-
unlock: {
|
|
1241
|
-
executor: '@empire-builder-kit/nx:unlock',
|
|
1242
|
-
options: {
|
|
1243
|
-
cwd: `packages/${name}`,
|
|
1244
|
-
stage: 'development',
|
|
1245
|
-
stageMode: 'consumer',
|
|
1246
|
-
},
|
|
1247
|
-
},
|
|
1248
|
-
verify: {
|
|
1249
|
-
executor: 'nx:run-commands',
|
|
1250
|
-
dependsOn: [
|
|
1251
|
-
'build',
|
|
1252
|
-
'db-check',
|
|
1253
|
-
'lint',
|
|
1254
|
-
'smoke-deployed-check',
|
|
1255
|
-
'test',
|
|
1256
|
-
'typecheck',
|
|
1257
|
-
],
|
|
1258
|
-
options: {
|
|
1259
|
-
command: 'node scripts/verify-slice.mjs',
|
|
1260
|
-
cwd: `packages/${name}`,
|
|
1261
|
-
},
|
|
1262
|
-
},
|
|
1263
|
-
},
|
|
1264
|
-
}),
|
|
1265
|
-
'scripts/verify-slice.mjs': `import { readFileSync } from 'node:fs';
|
|
1266
|
-
|
|
1267
|
-
const ownership = JSON.parse(
|
|
1268
|
-
readFileSync(new URL('../.ebk/ownership.json', import.meta.url), 'utf8'),
|
|
1269
|
-
);
|
|
1270
|
-
if (ownership.schemaVersion !== ${index_js_3.GENERATED_OWNERSHIP_SCHEMA_VERSION} || ownership.slice !== '${name}') {
|
|
1271
|
-
throw new Error('Slice ownership metadata is missing or incompatible.');
|
|
1272
|
-
}
|
|
1273
|
-
if (!ownership.foundation.capabilities.includes('deployment')) {
|
|
1274
|
-
throw new Error('Slice does not declare the Foundation deployment capability.');
|
|
1275
|
-
}
|
|
1276
|
-
process.stdout.write('${name} slice source contract verified.\\n');
|
|
1277
|
-
`,
|
|
1278
|
-
'scripts/verify-live-mode.mjs': `const origin = process.env.EBK_FLEET_ORIGIN?.trim();
|
|
1279
|
-
if (origin) {
|
|
1280
|
-
const parsed = new URL(origin);
|
|
1281
|
-
const supportedHostname = parsed.hostname.endsWith('.ebk.localhost') || parsed.hostname.endsWith('.test');
|
|
1282
|
-
if (parsed.protocol !== 'https:' || parsed.origin !== origin || !supportedHostname) {
|
|
1283
|
-
throw new Error('EBK_FLEET_ORIGIN must be an exact HTTPS *.ebk.localhost or adopter-managed *.test origin.');
|
|
1284
|
-
}
|
|
1285
|
-
if (process.env.EBK_SECURE_COOKIES !== 'true') {
|
|
1286
|
-
throw new Error('Fleet development requires EBK_SECURE_COOKIES=true.');
|
|
1287
|
-
}
|
|
1288
|
-
}
|
|
1289
|
-
process.stdout.write('${name} live-mode prerequisites verified.\\n');
|
|
1290
|
-
`,
|
|
1291
|
-
'scripts/check-database.mjs': `import { existsSync, readFileSync } from 'node:fs';
|
|
1292
|
-
import { createDatabaseBindingPlan } from '@empire-builder-kit/nx/foundation';
|
|
1293
|
-
import databaseBindings from '../database/bindings.json' with { type: 'json' };
|
|
1294
|
-
|
|
1295
|
-
const migration = new URL('../database/migrations/0000_initial.sql', import.meta.url);
|
|
1296
|
-
if (!existsSync(migration) || !readFileSync(migration, 'utf8').includes('CREATE TABLE')) {
|
|
1297
|
-
throw new Error('The initial database migration is missing or invalid.');
|
|
1298
|
-
}
|
|
1299
|
-
const plan = createDatabaseBindingPlan(databaseBindings, {
|
|
1300
|
-
slice: '${name}',
|
|
1301
|
-
stage: process.env.EBK_STAGE ?? 'development',
|
|
1302
|
-
});
|
|
1303
|
-
if (!plan.active.primary) throw new Error('Database binding "primary" is required.');
|
|
1304
|
-
process.stdout.write('${name} database history verified.\\n');
|
|
1305
|
-
`,
|
|
1306
|
-
'scripts/local-database.mjs': `import { spawnSync } from 'node:child_process';
|
|
1307
|
-
import { createDatabaseBindingPlan, resolveLocalDatabaseContract } from '@empire-builder-kit/nx/foundation';
|
|
1308
|
-
import databaseBindings from '../database/bindings.json' with { type: 'json' };
|
|
1309
|
-
|
|
1310
|
-
const action = process.argv[2];
|
|
1311
|
-
if (action !== 'up' && action !== 'down') {
|
|
1312
|
-
throw new Error('Usage: node scripts/local-database.mjs <up|down>');
|
|
1313
|
-
}
|
|
1314
|
-
const plan = createDatabaseBindingPlan(databaseBindings, {
|
|
1315
|
-
slice: '${name}',
|
|
1316
|
-
stage: 'development',
|
|
1317
|
-
});
|
|
1318
|
-
const activeDatabase = plan.active.primary;
|
|
1319
|
-
if (!activeDatabase) throw new Error('Database binding "primary" is required.');
|
|
1320
|
-
const local = resolveLocalDatabaseContract({
|
|
1321
|
-
database: activeDatabase,
|
|
1322
|
-
slice: '${name}',
|
|
1323
|
-
});
|
|
1324
|
-
const project = process.env.COMPOSE_PROJECT_NAME ?? ('ebk-${name}-' + activeDatabase)
|
|
1325
|
-
.replace(/[^a-z0-9_-]/g, '_')
|
|
1326
|
-
.toLowerCase();
|
|
1327
|
-
const args = ['compose', '--project-name', project, '-f', 'database/docker-compose.yml'];
|
|
1328
|
-
args.push(...(action === 'up' ? ['up', '-d', '--wait'] : ['down']));
|
|
1329
|
-
const result = spawnSync('docker', args, {
|
|
1330
|
-
env: {
|
|
1331
|
-
...process.env,
|
|
1332
|
-
EBK_LOCAL_DATABASE: local.database,
|
|
1333
|
-
EBK_LOCAL_DATABASE_PASSWORD: local.password,
|
|
1334
|
-
EBK_LOCAL_DATABASE_PORT: String(local.port),
|
|
1335
|
-
EBK_LOCAL_DATABASE_USERNAME: local.username,
|
|
1336
|
-
},
|
|
1337
|
-
stdio: 'inherit',
|
|
1338
|
-
});
|
|
1339
|
-
if (result.error) throw result.error;
|
|
1340
|
-
if (result.status !== 0) process.exit(result.status ?? 1);
|
|
1341
|
-
`,
|
|
1342
|
-
'scripts/confirm-deploy.mjs': `const stageArg = process.argv.find((value) => value.startsWith('--stage='));
|
|
1343
|
-
const stage = stageArg?.slice('--stage='.length) ?? 'development';
|
|
1344
|
-
process.stdout.write('${name} infrastructure and database migrations completed for ' + stage + '.\\n');
|
|
1345
|
-
`,
|
|
1346
|
-
'scripts/migrate-database.mjs': `import { createHash } from 'node:crypto';
|
|
1347
|
-
import { readdir, readFile } from 'node:fs/promises';
|
|
1348
|
-
import { createDatabaseBindingPlan, resolveFoundationStages } from '@empire-builder-kit/nx/foundation';
|
|
1349
|
-
import {
|
|
1350
|
-
BeginTransactionCommand,
|
|
1351
|
-
CommitTransactionCommand,
|
|
1352
|
-
ExecuteStatementCommand,
|
|
1353
|
-
RDSDataClient,
|
|
1354
|
-
RollbackTransactionCommand,
|
|
1355
|
-
} from '@aws-sdk/client-rds-data';
|
|
1356
|
-
import { DescribeSecretCommand, SecretsManagerClient } from '@aws-sdk/client-secrets-manager';
|
|
1357
|
-
import { GetParameterCommand, SSMClient } from '@aws-sdk/client-ssm';
|
|
1358
|
-
import databaseBindings from '../database/bindings.json' with { type: 'json' };
|
|
1359
|
-
|
|
1360
|
-
const stageArg = process.argv.find((value) => value.startsWith('--stage='));
|
|
1361
|
-
const foundationStageArg = process.argv.find((value) => value.startsWith('--foundationStage='));
|
|
1362
|
-
const { consumerStage: stage, foundationStage } = resolveFoundationStages({
|
|
1363
|
-
consumerStage: stageArg?.slice('--stage='.length) ?? 'development',
|
|
1364
|
-
foundationStage: foundationStageArg?.slice('--foundationStage='.length) ?? process.env.EBK_FOUNDATION_STAGE,
|
|
1365
|
-
});
|
|
1366
|
-
const bindingPlan = createDatabaseBindingPlan(databaseBindings, {
|
|
1367
|
-
slice: '${name}',
|
|
1368
|
-
stage,
|
|
1369
|
-
});
|
|
1370
|
-
const activeDatabase = bindingPlan.active.primary;
|
|
1371
|
-
if (!activeDatabase) throw new Error('Database binding "primary" is required.');
|
|
1372
|
-
const database = bindingPlan.identifiers[activeDatabase].database;
|
|
1373
|
-
const clusterParameter = '/ebk/' + foundationStage + '/foundation/databaseClusterArn';
|
|
1374
|
-
const clusterResponse = await new SSMClient({}).send(
|
|
1375
|
-
new GetParameterCommand({ Name: clusterParameter }),
|
|
1376
|
-
);
|
|
1377
|
-
const resourceArn = clusterResponse.Parameter?.Value;
|
|
1378
|
-
if (!resourceArn) throw new Error('Foundation database cluster ARN is missing at ' + clusterParameter + '.');
|
|
1379
|
-
const secretId = 'ebk/' + stage + '/${name}/database/' + activeDatabase + '/readwrite';
|
|
1380
|
-
const secretResponse = await new SecretsManagerClient({}).send(
|
|
1381
|
-
new DescribeSecretCommand({ SecretId: secretId }),
|
|
1382
|
-
);
|
|
1383
|
-
const secretArn = secretResponse.ARN;
|
|
1384
|
-
if (!secretArn) throw new Error('Logical database secret ARN is missing for ' + secretId + '.');
|
|
1385
|
-
|
|
1386
|
-
const client = new RDSDataClient({});
|
|
1387
|
-
const resumeRetryDelaysMs = [1_000, 2_000, 4_000, 8_000, 16_000];
|
|
1388
|
-
const sleep = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
1389
|
-
const send = async (command) => {
|
|
1390
|
-
for (let attempt = 0; ; attempt += 1) {
|
|
1391
|
-
try {
|
|
1392
|
-
return await client.send(command);
|
|
1393
|
-
} catch (error) {
|
|
1394
|
-
const resumable = error && typeof error === 'object' && error.name === 'DatabaseResumingException';
|
|
1395
|
-
if (!resumable || attempt >= resumeRetryDelaysMs.length) throw error;
|
|
1396
|
-
await sleep(resumeRetryDelaysMs[attempt]);
|
|
1397
|
-
}
|
|
1398
|
-
}
|
|
1399
|
-
};
|
|
1400
|
-
const execute = (sql, parameters = [], transactionId) => send(
|
|
1401
|
-
new ExecuteStatementCommand({
|
|
1402
|
-
database,
|
|
1403
|
-
parameters,
|
|
1404
|
-
resourceArn,
|
|
1405
|
-
secretArn,
|
|
1406
|
-
sql,
|
|
1407
|
-
transactionId,
|
|
1408
|
-
}),
|
|
1409
|
-
);
|
|
1410
|
-
|
|
1411
|
-
await execute('CREATE TABLE IF NOT EXISTS _ebk_migrations (name text PRIMARY KEY, checksum text NOT NULL, applied_at timestamptz NOT NULL DEFAULT now())');
|
|
1412
|
-
const directory = new URL('../database/migrations/', import.meta.url);
|
|
1413
|
-
const files = (await readdir(directory)).filter((file) => file.endsWith('.sql')).sort();
|
|
1414
|
-
for (const name of files) {
|
|
1415
|
-
const sql = await readFile(new URL(name, directory), 'utf8');
|
|
1416
|
-
const checksum = createHash('sha256').update(sql).digest('hex');
|
|
1417
|
-
const existing = await execute(
|
|
1418
|
-
'SELECT checksum FROM _ebk_migrations WHERE name = :name',
|
|
1419
|
-
[{ name: 'name', value: { stringValue: name } }],
|
|
1420
|
-
);
|
|
1421
|
-
const appliedChecksum = existing.records?.[0]?.[0]?.stringValue;
|
|
1422
|
-
if (appliedChecksum === checksum) continue;
|
|
1423
|
-
if (appliedChecksum) throw new Error('Applied migration changed: ' + name);
|
|
1424
|
-
|
|
1425
|
-
const transaction = await send(new BeginTransactionCommand({
|
|
1426
|
-
database,
|
|
1427
|
-
resourceArn,
|
|
1428
|
-
secretArn,
|
|
1429
|
-
}));
|
|
1430
|
-
if (!transaction.transactionId) throw new Error('Data API did not return a transaction id.');
|
|
1431
|
-
try {
|
|
1432
|
-
const statements = sql.split(/^--> statement-breakpoint\\s*$/m).map((value) => value.trim()).filter(Boolean);
|
|
1433
|
-
for (const statement of statements) await execute(statement, [], transaction.transactionId);
|
|
1434
|
-
await execute(
|
|
1435
|
-
'INSERT INTO _ebk_migrations (name, checksum) VALUES (:name, :checksum)',
|
|
1436
|
-
[
|
|
1437
|
-
{ name: 'name', value: { stringValue: name } },
|
|
1438
|
-
{ name: 'checksum', value: { stringValue: checksum } },
|
|
1439
|
-
],
|
|
1440
|
-
transaction.transactionId,
|
|
1441
|
-
);
|
|
1442
|
-
await send(new CommitTransactionCommand({
|
|
1443
|
-
resourceArn,
|
|
1444
|
-
secretArn,
|
|
1445
|
-
transactionId: transaction.transactionId,
|
|
1446
|
-
}));
|
|
1447
|
-
} catch (error) {
|
|
1448
|
-
await send(new RollbackTransactionCommand({
|
|
1449
|
-
resourceArn,
|
|
1450
|
-
secretArn,
|
|
1451
|
-
transactionId: transaction.transactionId,
|
|
1452
|
-
}));
|
|
1453
|
-
throw error;
|
|
1454
|
-
}
|
|
1455
|
-
}
|
|
1456
|
-
process.stdout.write('${name} database migrations completed for ' + stage + '.\\n');
|
|
1457
|
-
`,
|
|
1458
|
-
'sst-env.d.ts': `// Bootstrap placeholder. SST overwrites this file after install, dev, or deploy.
|
|
1459
|
-
export {};
|
|
1460
|
-
`,
|
|
1461
|
-
'sst.config.ts': `export default $config({
|
|
1462
|
-
app(input: { stage?: string } | undefined) {
|
|
1463
|
-
const production = input?.stage === 'production';
|
|
1464
|
-
return {
|
|
1465
|
-
name: '${name}',
|
|
1466
|
-
removal: production ? 'retain' : 'remove',
|
|
1467
|
-
protect: production,
|
|
1468
|
-
home: 'aws',
|
|
1469
|
-
providers: {
|
|
1470
|
-
aws: { region: process.env.AWS_REGION ?? 'us-east-1' },
|
|
1471
|
-
},
|
|
1472
|
-
};
|
|
1473
|
-
},
|
|
1474
|
-
async run() {
|
|
1475
|
-
const { app } = await import('./infra/index.js');
|
|
1476
|
-
return app();
|
|
1477
|
-
},
|
|
1478
|
-
});
|
|
1479
|
-
`,
|
|
1480
|
-
'tsconfig.json': json({
|
|
1481
|
-
extends: '../../tsconfig.base.json',
|
|
1482
|
-
compilerOptions: {
|
|
1483
|
-
allowJs: true,
|
|
1484
|
-
esModuleInterop: true,
|
|
1485
|
-
jsx: 'react-jsx',
|
|
1486
|
-
lib: ['dom', 'dom.iterable', 'es2022'],
|
|
1487
|
-
plugins: [{ name: 'next' }],
|
|
1488
|
-
resolveJsonModule: true,
|
|
1489
|
-
types: ['node'],
|
|
1490
|
-
},
|
|
1491
|
-
include: [
|
|
1492
|
-
'contracts/**/*.ts',
|
|
1493
|
-
'database/**/*.ts',
|
|
1494
|
-
'api/**/*.ts',
|
|
1495
|
-
'infra/**/*.ts',
|
|
1496
|
-
'jobs/**/*.ts',
|
|
1497
|
-
'services/**/*.ts',
|
|
1498
|
-
'web/**/*.ts',
|
|
1499
|
-
'web/**/*.tsx',
|
|
1500
|
-
'vitest.config.ts',
|
|
1501
|
-
'sst.config.ts',
|
|
1502
|
-
'sst-env.d.ts',
|
|
1503
|
-
'ebk-globals.d.ts',
|
|
1504
|
-
],
|
|
1505
|
-
exclude: ['.sst', 'dist', 'node_modules'],
|
|
1506
|
-
}),
|
|
1507
|
-
...renderStandardProductFiles(name, pascalName),
|
|
1508
|
-
};
|
|
1509
|
-
}
|
|
1510
|
-
function classifyPaths(files) {
|
|
1511
|
-
const seededPaths = new Set([
|
|
1512
|
-
'README.md',
|
|
1513
|
-
'database/bindings.json',
|
|
1514
|
-
'database/schema.ts',
|
|
1515
|
-
'web/src/app/globals.css',
|
|
1516
|
-
'web/src/app/layout.tsx',
|
|
1517
|
-
'web/src/app/page.spec.tsx',
|
|
1518
|
-
'web/src/app/page.tsx',
|
|
1519
|
-
'web/src/app/password-reset/page.tsx',
|
|
1520
|
-
'web/src/app/api/protected/route.ts',
|
|
1521
|
-
'web/src/app/sign-in/page.tsx',
|
|
1522
|
-
]);
|
|
1523
|
-
const seededPrefixes = [
|
|
1524
|
-
'api/',
|
|
1525
|
-
'contracts/',
|
|
1526
|
-
'database/migrations/',
|
|
1527
|
-
'docs/',
|
|
1528
|
-
'e2e/',
|
|
1529
|
-
];
|
|
1530
|
-
const toolOwnedPaths = new Set(['sst-env.d.ts', 'web/next-env.d.ts']);
|
|
1531
|
-
return Object.entries(files)
|
|
1532
|
-
.filter(([path]) => path !== '.ebk/ownership.json' && !toolOwnedPaths.has(path))
|
|
1533
|
-
.map(([path, contents]) => {
|
|
1534
|
-
const mode = seededPaths.has(path) ||
|
|
1535
|
-
seededPrefixes.some((prefix) => path.startsWith(prefix))
|
|
1536
|
-
? 'seeded'
|
|
1537
|
-
: 'managed';
|
|
1538
|
-
const managedJsonPointers = path === 'package.json'
|
|
1539
|
-
? [...exports.PRODUCT_PACKAGE_MANAGED_JSON_POINTERS]
|
|
1540
|
-
: undefined;
|
|
1541
|
-
if (managedJsonPointers) {
|
|
1542
|
-
(0, index_js_3.assertManagedJsonPointersExist)(contents, managedJsonPointers, `Built-in Standard Blueprint ${path}`);
|
|
1543
|
-
}
|
|
1544
|
-
return {
|
|
1545
|
-
...(managedJsonPointers ? { managedJsonPointers } : {}),
|
|
1546
|
-
mode,
|
|
1547
|
-
origin: 'blueprint',
|
|
1548
|
-
path,
|
|
1549
|
-
sha256: (0, index_js_3.hashOwnedContent)(contents, { managedJsonPointers }),
|
|
1550
|
-
};
|
|
1551
|
-
})
|
|
1552
|
-
.sort((left, right) => left.path.localeCompare(right.path));
|
|
1553
|
-
}
|
|
1554
|
-
function createBuiltInSlicePlan(name, scope, runtimeVersion, manifest, inputs) {
|
|
1555
|
-
const provisionalOwnership = {
|
|
1556
|
-
blueprint: { name: manifest.name, version: manifest.version },
|
|
1557
|
-
contracts: { consumes: [], publishes: [`${scope}/${name}/contracts`] },
|
|
1558
|
-
foundation: manifest.foundation,
|
|
1559
|
-
inputs,
|
|
1560
|
-
paths: [],
|
|
1561
|
-
projects: [name],
|
|
1562
|
-
schemaVersion: index_js_3.GENERATED_OWNERSHIP_SCHEMA_VERSION,
|
|
1563
|
-
slice: name,
|
|
1564
|
-
verification: manifest.verification,
|
|
1565
|
-
};
|
|
1566
|
-
const provisionalFiles = renderSliceFiles(name, scope, runtimeVersion, provisionalOwnership);
|
|
1567
|
-
const ownership = {
|
|
1568
|
-
...provisionalOwnership,
|
|
1569
|
-
paths: classifyPaths(provisionalFiles),
|
|
1570
|
-
};
|
|
1571
|
-
return {
|
|
1572
|
-
files: renderSliceFiles(name, scope, runtimeVersion, ownership),
|
|
1573
|
-
ownership,
|
|
1574
|
-
};
|
|
1575
|
-
}
|
|
1576
167
|
async function sliceGenerator(tree, options) {
|
|
1577
168
|
const name = requireSliceName(options.name);
|
|
1578
169
|
const root = node_path_1.posix.join('packages', name);
|
|
170
|
+
const blueprintReference = options.blueprint ?? 'standard';
|
|
171
|
+
const parsedInputs = parseBlueprintInputs(options.inputs);
|
|
172
|
+
const installOperation = {
|
|
173
|
+
generator: 'slice',
|
|
174
|
+
id: `generator:slice:${name}`,
|
|
175
|
+
key: `slice-${name}`,
|
|
176
|
+
request: {
|
|
177
|
+
blueprint: blueprintReference,
|
|
178
|
+
inputs: parsedInputs,
|
|
179
|
+
name,
|
|
180
|
+
skipFormat: options.skipFormat ?? false,
|
|
181
|
+
},
|
|
182
|
+
resumeArguments: [
|
|
183
|
+
'pnpm',
|
|
184
|
+
'nx',
|
|
185
|
+
'generate',
|
|
186
|
+
'@empire-builder-kit/nx:slice',
|
|
187
|
+
`--name=${name}`,
|
|
188
|
+
`--blueprint=${blueprintReference}`,
|
|
189
|
+
`--inputs=${JSON.stringify(parsedInputs)}`,
|
|
190
|
+
`--skipFormat=${String(options.skipFormat ?? false)}`,
|
|
191
|
+
'--skipInstall=false',
|
|
192
|
+
'--interactive=false',
|
|
193
|
+
],
|
|
194
|
+
sourceRoot: root,
|
|
195
|
+
};
|
|
196
|
+
const pendingInstall = (0, post_generation_install_js_1.resumePendingPostGenerationInstall)(tree, installOperation, options.skipInstall);
|
|
197
|
+
if (pendingInstall)
|
|
198
|
+
return pendingInstall;
|
|
1579
199
|
if (tree.exists(root)) {
|
|
1580
200
|
throw new Error(`Product Slice ${name} already exists at ${root}.`);
|
|
1581
201
|
}
|
|
1582
202
|
const packageJson = readJson(tree, 'package.json', 'Workspace package.json');
|
|
1583
203
|
const blueprint = (0, index_js_1.resolveBlueprint)({
|
|
204
|
+
localAuthoringPackages: packageJson.ebk?.blueprints?.localAuthoringPackages ?? [],
|
|
1584
205
|
localPackages: packageJson.ebk?.blueprints?.localPackages,
|
|
1585
206
|
reference: options.blueprint,
|
|
1586
|
-
trust: {
|
|
1587
|
-
packages: packageJson.ebk?.blueprints?.trustedPackages ?? [],
|
|
1588
|
-
},
|
|
1589
207
|
workspaceRoot: tree.root,
|
|
1590
208
|
});
|
|
1591
|
-
const inputResult = (0, index_js_1.validateBlueprintInputs)(blueprint.inputSchema,
|
|
209
|
+
const inputResult = (0, index_js_1.validateBlueprintInputs)(blueprint.inputSchema, parsedInputs);
|
|
1592
210
|
if (!inputResult.valid) {
|
|
1593
211
|
throw new Error(`Blueprint inputs are invalid:\n${inputResult.issues
|
|
1594
212
|
.map((issue) => `- ${issue.path}: ${issue.message}`)
|
|
@@ -1601,11 +219,38 @@ async function sliceGenerator(tree, options) {
|
|
|
1601
219
|
.map((issue) => `- ${issue.path}: ${issue.message}`)
|
|
1602
220
|
.join('\n')}`);
|
|
1603
221
|
}
|
|
222
|
+
const installScope = {
|
|
223
|
+
exactPaths: ['package.json'],
|
|
224
|
+
requiredPaths: [node_path_1.posix.join(root, '.ebk/ownership.json')],
|
|
225
|
+
roots: [root],
|
|
226
|
+
};
|
|
227
|
+
const installState = options.skipInstall
|
|
228
|
+
? undefined
|
|
229
|
+
: (0, post_generation_install_js_1.capturePostGenerationInstallState)(tree, installScope, installOperation);
|
|
1604
230
|
const scope = workspaceScope(packageJson);
|
|
1605
231
|
if (blueprint.source !== 'built-in') {
|
|
232
|
+
const nxVersion = packageJson.devDependencies?.['@empire-builder-kit/nx'];
|
|
233
|
+
const runtimeVersion = packageJson.dependencies?.['@empire-builder-kit/runtime'];
|
|
234
|
+
if (!nxVersion || !runtimeVersion) {
|
|
235
|
+
throw new Error('External Blueprint generation requires exact Nx and Runtime framework dependencies.');
|
|
236
|
+
}
|
|
1606
237
|
if (!blueprint.generatorPath) {
|
|
1607
238
|
throw new Error('Resolved external Blueprint has no generator entry point.');
|
|
1608
239
|
}
|
|
240
|
+
if (!blueprint.packageRoot) {
|
|
241
|
+
throw new Error('Resolved external Blueprint has no package root.');
|
|
242
|
+
}
|
|
243
|
+
if (blueprint.source === 'installed' &&
|
|
244
|
+
(!blueprint.registryIntegrity || !blueprint.lockfileDigest)) {
|
|
245
|
+
throw new Error('Resolved installed Blueprint has no lockfile and registry-integrity authority.');
|
|
246
|
+
}
|
|
247
|
+
const executionSource = blueprint.source === 'installed'
|
|
248
|
+
? {
|
|
249
|
+
lockfileDigest: blueprint.lockfileDigest,
|
|
250
|
+
registryIntegrity: blueprint.registryIntegrity,
|
|
251
|
+
source: 'installed',
|
|
252
|
+
}
|
|
253
|
+
: { source: 'local' };
|
|
1609
254
|
const generated = await (0, index_js_1.executeBlueprintGenerator)(blueprint.generatorPath, {
|
|
1610
255
|
foundation: compatibility.value,
|
|
1611
256
|
inputs: inputResult.value,
|
|
@@ -1613,9 +258,22 @@ async function sliceGenerator(tree, options) {
|
|
|
1613
258
|
name,
|
|
1614
259
|
root,
|
|
1615
260
|
workspace: {
|
|
261
|
+
framework: { nx: nxVersion, runtime: runtimeVersion },
|
|
1616
262
|
name: packageJson.name ?? '',
|
|
1617
263
|
scope,
|
|
1618
264
|
},
|
|
265
|
+
}, {
|
|
266
|
+
packageRoot: blueprint.packageRoot,
|
|
267
|
+
...executionSource,
|
|
268
|
+
workspaceRoot: tree.root,
|
|
269
|
+
});
|
|
270
|
+
(0, index_js_1.assertBlueprintDestinationPaths)(tree.root, root, generated.files.map(({ path }) => path));
|
|
271
|
+
assertExternalBlueprintVerificationProgram({
|
|
272
|
+
files: generated.files,
|
|
273
|
+
name,
|
|
274
|
+
projects: generated.projects,
|
|
275
|
+
root,
|
|
276
|
+
verification: blueprint.manifest.verification,
|
|
1619
277
|
});
|
|
1620
278
|
const ownershipPaths = generated.files.map(({ contents, managedJsonPointers, mode, path }) => ({
|
|
1621
279
|
...(managedJsonPointers ? { managedJsonPointers } : {}),
|
|
@@ -1624,12 +282,13 @@ async function sliceGenerator(tree, options) {
|
|
|
1624
282
|
path,
|
|
1625
283
|
sha256: (0, index_js_3.hashOwnedContent)(contents, { managedJsonPointers }),
|
|
1626
284
|
}));
|
|
1627
|
-
ownershipPaths.sort((left, right) => left.path
|
|
285
|
+
ownershipPaths.sort((left, right) => (0, deterministic_order_js_1.compareUtf16)(left.path, right.path));
|
|
1628
286
|
const ownership = {
|
|
1629
287
|
blueprint: {
|
|
1630
288
|
name: blueprint.manifest.name,
|
|
1631
289
|
version: blueprint.manifest.version,
|
|
1632
290
|
},
|
|
291
|
+
compositions: [],
|
|
1633
292
|
contracts: generated.contracts,
|
|
1634
293
|
foundation: blueprint.manifest.foundation,
|
|
1635
294
|
inputs: inputResult.value,
|
|
@@ -1664,15 +323,18 @@ async function sliceGenerator(tree, options) {
|
|
|
1664
323
|
await (0, devkit_1.formatFiles)(tree);
|
|
1665
324
|
}
|
|
1666
325
|
reportSlicePolicyPosture(tree, name);
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
326
|
+
if (options.skipInstall)
|
|
327
|
+
return undefined;
|
|
328
|
+
if (!installState) {
|
|
329
|
+
throw new Error('Post-generation install state was not prepared.');
|
|
330
|
+
}
|
|
331
|
+
return (0, post_generation_install_js_1.createPostGenerationInstallCallback)(tree, installState, installScope, installOperation);
|
|
1670
332
|
}
|
|
1671
333
|
const runtimeVersion = packageJson.dependencies?.['@empire-builder-kit/runtime'];
|
|
1672
334
|
if (!runtimeVersion) {
|
|
1673
335
|
throw new Error('Workspace package.json must depend on @empire-builder-kit/runtime before generating a Product Slice.');
|
|
1674
336
|
}
|
|
1675
|
-
const plan = createBuiltInSlicePlan(name, scope, runtimeVersion, blueprint.manifest, inputResult.value);
|
|
337
|
+
const plan = (0, built_in_plan_js_1.createBuiltInSlicePlan)(name, scope, runtimeVersion, blueprint.manifest, inputResult.value, dataPolicyReviewSeed(tree, root));
|
|
1676
338
|
const ownershipValidation = (0, index_js_3.validateGeneratedOwnershipRecord)(plan.ownership);
|
|
1677
339
|
if (!ownershipValidation.valid) {
|
|
1678
340
|
throw new Error(`Generated ownership metadata is invalid:\n${ownershipValidation.issues
|
|
@@ -1682,17 +344,30 @@ async function sliceGenerator(tree, options) {
|
|
|
1682
344
|
for (const [relativePath, contents] of Object.entries(plan.files)) {
|
|
1683
345
|
tree.write(node_path_1.posix.join(root, relativePath), contents);
|
|
1684
346
|
}
|
|
347
|
+
const restoreFormatSensitiveFiles = () => {
|
|
348
|
+
for (const [relativePath, contents] of Object.entries(plan.files)) {
|
|
349
|
+
if (relativePath.startsWith('database/migrations/') ||
|
|
350
|
+
FORMAT_SENSITIVE_BUILT_IN_PATHS.has(relativePath)) {
|
|
351
|
+
tree.write(node_path_1.posix.join(root, relativePath), contents);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
};
|
|
1685
355
|
if (!options.skipFormat) {
|
|
1686
356
|
await (0, devkit_1.formatFiles)(tree);
|
|
357
|
+
restoreFormatSensitiveFiles();
|
|
1687
358
|
}
|
|
1688
359
|
(0, index_js_3.restampProductSliceOwnership)(tree, name);
|
|
1689
360
|
if (!options.skipFormat) {
|
|
1690
361
|
await (0, devkit_1.formatFiles)(tree);
|
|
362
|
+
restoreFormatSensitiveFiles();
|
|
1691
363
|
}
|
|
1692
364
|
reportSlicePolicyPosture(tree, name);
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
365
|
+
if (options.skipInstall)
|
|
366
|
+
return undefined;
|
|
367
|
+
if (!installState) {
|
|
368
|
+
throw new Error('Post-generation install state was not prepared.');
|
|
369
|
+
}
|
|
370
|
+
return (0, post_generation_install_js_1.createPostGenerationInstallCallback)(tree, installState, installScope, installOperation);
|
|
1696
371
|
}
|
|
1697
372
|
exports.default = sliceGenerator;
|
|
1698
373
|
//# sourceMappingURL=slice.js.map
|