@intentius/chant 0.13.1 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/audit/catalog.d.ts +45 -5
- package/dist/audit/catalog.d.ts.map +1 -1
- package/dist/audit/proof.d.ts +3 -0
- package/dist/audit/proof.d.ts.map +1 -1
- package/dist/audit/report-model.d.ts +4 -1
- package/dist/audit/report-model.d.ts.map +1 -1
- package/dist/audit/report.d.ts +3 -0
- package/dist/audit/report.d.ts.map +1 -1
- package/dist/audit/rules-doc.d.ts +8 -2
- package/dist/audit/rules-doc.d.ts.map +1 -1
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/lexicon-rolling-upgrade.d.ts +37 -0
- package/dist/cli/commands/lexicon-rolling-upgrade.d.ts.map +1 -0
- package/dist/cli/commands/lexicon-surface-diff.d.ts +48 -0
- package/dist/cli/commands/lexicon-surface-diff.d.ts.map +1 -0
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/commands/pinned-upgrade.d.ts +41 -0
- package/dist/cli/commands/pinned-upgrade.d.ts.map +1 -0
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/components.d.ts +39 -0
- package/dist/cli/handlers/components.d.ts.map +1 -0
- package/dist/cli/handlers/dev.d.ts +3 -0
- package/dist/cli/handlers/dev.d.ts.map +1 -1
- package/dist/cli/handlers/graph.d.ts +4 -2
- package/dist/cli/handlers/graph.d.ts.map +1 -1
- package/dist/cli/handlers/misc.d.ts.map +1 -1
- package/dist/cli/handlers/run.d.ts +49 -0
- package/dist/cli/handlers/run.d.ts.map +1 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/registry.d.ts +35 -0
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/codegen/fetch.d.ts +22 -0
- package/dist/codegen/fetch.d.ts.map +1 -1
- package/dist/codegen/lexicon-regen.d.ts +110 -0
- package/dist/codegen/lexicon-regen.d.ts.map +1 -0
- package/dist/codegen/pinned-upgrade.d.ts +153 -0
- package/dist/codegen/pinned-upgrade.d.ts.map +1 -0
- package/dist/codegen/rolling-upgrade.d.ts +138 -0
- package/dist/codegen/rolling-upgrade.d.ts.map +1 -0
- package/dist/codegen/surface-snapshot.d.ts +173 -0
- package/dist/codegen/surface-snapshot.d.ts.map +1 -0
- package/dist/codegen/version-bump.d.ts +21 -0
- package/dist/codegen/version-bump.d.ts.map +1 -0
- package/dist/components/auto-release.d.ts +93 -0
- package/dist/components/auto-release.d.ts.map +1 -0
- package/dist/components/builders.d.ts +37 -0
- package/dist/components/builders.d.ts.map +1 -0
- package/dist/components/capability-plugin-loader.d.ts +111 -0
- package/dist/components/capability-plugin-loader.d.ts.map +1 -0
- package/dist/components/capability-plugin-schema.d.ts +24 -0
- package/dist/components/capability-plugin-schema.d.ts.map +1 -0
- package/dist/components/capability-plugin.d.ts +85 -0
- package/dist/components/capability-plugin.d.ts.map +1 -0
- package/dist/components/capability.d.ts +89 -0
- package/dist/components/capability.d.ts.map +1 -0
- package/dist/components/cli-support.d.ts +204 -0
- package/dist/components/cli-support.d.ts.map +1 -0
- package/dist/components/component.d.ts +179 -0
- package/dist/components/component.d.ts.map +1 -0
- package/dist/components/config-defaults.d.ts +41 -0
- package/dist/components/config-defaults.d.ts.map +1 -0
- package/dist/components/discover.d.ts +60 -0
- package/dist/components/discover.d.ts.map +1 -0
- package/dist/components/driver-output.d.ts +20 -0
- package/dist/components/driver-output.d.ts.map +1 -0
- package/dist/components/driver.d.ts +209 -0
- package/dist/components/driver.d.ts.map +1 -0
- package/dist/components/index.d.ts +22 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/manifest-persistence.d.ts +79 -0
- package/dist/components/manifest-persistence.d.ts.map +1 -0
- package/dist/components/pilots/alb-ecs.pilot.d.ts +27 -0
- package/dist/components/pilots/alb-ecs.pilot.d.ts.map +1 -0
- package/dist/components/pilots/dynamodb.pilot.d.ts +22 -0
- package/dist/components/pilots/dynamodb.pilot.d.ts.map +1 -0
- package/dist/components/pilots/jar-emr.pilot.d.ts +37 -0
- package/dist/components/pilots/jar-emr.pilot.d.ts.map +1 -0
- package/dist/components/pilots/lambda.pilot.d.ts +35 -0
- package/dist/components/pilots/lambda.pilot.d.ts.map +1 -0
- package/dist/components/pilots/neo4j-fanout.pilot.d.ts +17 -0
- package/dist/components/pilots/neo4j-fanout.pilot.d.ts.map +1 -0
- package/dist/components/pilots/project.d.ts +13 -0
- package/dist/components/pilots/project.d.ts.map +1 -0
- package/dist/components/presets/ecs-fargate.d.ts +59 -0
- package/dist/components/presets/ecs-fargate.d.ts.map +1 -0
- package/dist/components/presets/index.d.ts +29 -0
- package/dist/components/presets/index.d.ts.map +1 -0
- package/dist/components/presets/lambda.d.ts +35 -0
- package/dist/components/presets/lambda.d.ts.map +1 -0
- package/dist/components/presets/single-host-compose.d.ts +43 -0
- package/dist/components/presets/single-host-compose.d.ts.map +1 -0
- package/dist/components/registry.d.ts +29 -0
- package/dist/components/registry.d.ts.map +1 -0
- package/dist/components/starter-plugin.d.ts +51 -0
- package/dist/components/starter-plugin.d.ts.map +1 -0
- package/dist/components/temporal-codegen-loader.d.ts +27 -0
- package/dist/components/temporal-codegen-loader.d.ts.map +1 -0
- package/dist/components/verbs/__tests__/mock-cloud-executor.d.ts +35 -0
- package/dist/components/verbs/__tests__/mock-cloud-executor.d.ts.map +1 -0
- package/dist/components/verbs/__tests__/mock-process-runner.d.ts +45 -0
- package/dist/components/verbs/__tests__/mock-process-runner.d.ts.map +1 -0
- package/dist/components/verbs/__tests__/mock-sbom-generator.d.ts +33 -0
- package/dist/components/verbs/__tests__/mock-sbom-generator.d.ts.map +1 -0
- package/dist/components/verbs/bom-writer.d.ts +155 -0
- package/dist/components/verbs/bom-writer.d.ts.map +1 -0
- package/dist/components/verbs/build-archive.d.ts +205 -0
- package/dist/components/verbs/build-archive.d.ts.map +1 -0
- package/dist/components/verbs/build.d.ts +150 -0
- package/dist/components/verbs/build.d.ts.map +1 -0
- package/dist/components/verbs/cloud-executor.d.ts +88 -0
- package/dist/components/verbs/cloud-executor.d.ts.map +1 -0
- package/dist/components/verbs/component-bom.d.ts +103 -0
- package/dist/components/verbs/component-bom.d.ts.map +1 -0
- package/dist/components/verbs/index.d.ts +49 -0
- package/dist/components/verbs/index.d.ts.map +1 -0
- package/dist/components/verbs/license-policy.d.ts +56 -0
- package/dist/components/verbs/license-policy.d.ts.map +1 -0
- package/dist/components/verbs/lockfile-sbom-generator.d.ts +81 -0
- package/dist/components/verbs/lockfile-sbom-generator.d.ts.map +1 -0
- package/dist/components/verbs/process-runner.d.ts +64 -0
- package/dist/components/verbs/process-runner.d.ts.map +1 -0
- package/dist/components/verbs/reproducibility.d.ts +80 -0
- package/dist/components/verbs/reproducibility.d.ts.map +1 -0
- package/dist/components/verbs/sbom-generator.d.ts +157 -0
- package/dist/components/verbs/sbom-generator.d.ts.map +1 -0
- package/dist/components/verbs/sbom.d.ts +79 -0
- package/dist/components/verbs/sbom.d.ts.map +1 -0
- package/dist/components/verbs/shell.d.ts +35 -0
- package/dist/components/verbs/shell.d.ts.map +1 -0
- package/dist/components/verbs/sign.d.ts +222 -0
- package/dist/components/verbs/sign.d.ts.map +1 -0
- package/dist/components/verbs/stub.d.ts +18 -0
- package/dist/components/verbs/stub.d.ts.map +1 -0
- package/dist/components/verbs/tool-sbom-generator.d.ts +51 -0
- package/dist/components/verbs/tool-sbom-generator.d.ts.map +1 -0
- package/dist/components/verbs/verify.d.ts +106 -0
- package/dist/components/verbs/verify.d.ts.map +1 -0
- package/dist/components/verbs/vex.d.ts +65 -0
- package/dist/components/verbs/vex.d.ts.map +1 -0
- package/dist/components/verbs/vuln-gate.d.ts +91 -0
- package/dist/components/verbs/vuln-gate.d.ts.map +1 -0
- package/dist/components/verbs/vuln-scan.d.ts +116 -0
- package/dist/components/verbs/vuln-scan.d.ts.map +1 -0
- package/dist/components/verbs/wait-verify.d.ts +85 -0
- package/dist/components/verbs/wait-verify.d.ts.map +1 -0
- package/dist/config.d.ts +205 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/lexicon.d.ts +78 -0
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/build-ledger-store.d.ts +121 -0
- package/dist/lifecycle/build-ledger-store.d.ts.map +1 -0
- package/dist/lifecycle/build-ledger.d.ts +225 -0
- package/dist/lifecycle/build-ledger.d.ts.map +1 -0
- package/dist/lifecycle/git.d.ts +84 -0
- package/dist/lifecycle/git.d.ts.map +1 -1
- package/dist/lifecycle/index.d.ts +5 -0
- package/dist/lifecycle/index.d.ts.map +1 -1
- package/dist/lifecycle/oras-referrer-lookup.d.ts +41 -0
- package/dist/lifecycle/oras-referrer-lookup.d.ts.map +1 -0
- package/dist/lifecycle/release-ledger.d.ts +122 -0
- package/dist/lifecycle/release-ledger.d.ts.map +1 -0
- package/dist/lifecycle/status.d.ts +150 -0
- package/dist/lifecycle/status.d.ts.map +1 -0
- package/dist/lint/component-checks.d.ts +95 -0
- package/dist/lint/component-checks.d.ts.map +1 -0
- package/dist/lint/engine.d.ts +23 -0
- package/dist/lint/engine.d.ts.map +1 -1
- package/dist/lint/presets/strict.json +8 -1
- package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-a.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-a.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-b.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-b.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/fail/orphan-lib.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/fail/orphan-lib.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/pass/emr-job.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/pass/emr-job.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/pass/jar-lib.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/pass/jar-lib.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/fail/search-service.component.d.ts +10 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/fail/search-service.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/pass/jar-lib.component.d.ts +3 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/pass/jar-lib.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/pass/search-service.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/pass/search-service.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/fail/migrator.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/fail/migrator.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/pass/migrator.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/pass/migrator.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/pass/orders-table.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/pass/orders-table.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/fail/neo4j-cluster.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/fail/neo4j-cluster.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp005/fail/search-service.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp005/fail/search-service.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp005/pass/search-service.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp005/pass/search-service.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp006/fail/legacy-tool.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp006/fail/legacy-tool.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp006/pass/legacy-tool.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp006/pass/legacy-tool.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/fail/inventory-table.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/fail/inventory-table.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/fail/orders-table.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/fail/orders-table.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/pass/orders-table.component.d.ts +3 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/pass/orders-table.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/pass/search-service.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/pass/search-service.component.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp001-publishes-never-applies.d.ts +20 -0
- package/dist/lint/rules/comp/comp001-publishes-never-applies.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp002-dangling-wiring-ref.d.ts +28 -0
- package/dist/lint/rules/comp/comp002-dangling-wiring-ref.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp003-mutating-no-rollback.d.ts +39 -0
- package/dist/lint/rules/comp/comp003-mutating-no-rollback.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts +37 -0
- package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp005-capability-kind-is-noun.d.ts +43 -0
- package/dist/lint/rules/comp/comp005-capability-kind-is-noun.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp006-shell-needs-reason.d.ts +22 -0
- package/dist/lint/rules/comp/comp006-shell-needs-reason.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp007-composition-sprawl.d.ts +33 -0
- package/dist/lint/rules/comp/comp007-composition-sprawl.d.ts.map +1 -0
- package/dist/lint/rules/comp/index.d.ts +18 -0
- package/dist/lint/rules/comp/index.d.ts.map +1 -0
- package/dist/lint/rules/comp/support.d.ts +71 -0
- package/dist/lint/rules/comp/support.d.ts.map +1 -0
- package/dist/lsp/lexicon-providers.d.ts.map +1 -1
- package/dist/op/activity-registry.d.ts +11 -6
- package/dist/op/activity-registry.d.ts.map +1 -1
- package/dist/op/activity-runtime.d.ts +24 -0
- package/dist/op/activity-runtime.d.ts.map +1 -0
- package/dist/op/builders.d.ts +56 -0
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/index.d.ts +2 -1
- package/dist/op/index.d.ts.map +1 -1
- package/dist/ownership.d.ts +20 -14
- package/dist/ownership.d.ts.map +1 -1
- package/package.json +14 -1
- package/src/audit/catalog.test.ts +74 -22
- package/src/audit/catalog.ts +74 -471
- package/src/audit/proof.ts +4 -2
- package/src/audit/report-html.test.ts +14 -7
- package/src/audit/report-model.ts +20 -9
- package/src/audit/report.test.ts +36 -13
- package/src/audit/report.ts +2 -0
- package/src/audit/rules-doc.test.ts +8 -6
- package/src/audit/rules-doc.ts +13 -5
- package/src/cli/commands/audit.ts +23 -18
- package/src/cli/commands/component-lint.test.ts +158 -0
- package/src/cli/commands/doctor.test.ts +116 -2
- package/src/cli/commands/doctor.ts +46 -0
- package/src/cli/commands/lexicon-rolling-upgrade.ts +198 -0
- package/src/cli/commands/lexicon-surface-diff.test.ts +104 -0
- package/src/cli/commands/lexicon-surface-diff.ts +185 -0
- package/src/cli/commands/lint.ts +142 -1
- package/src/cli/commands/pinned-upgrade.ts +204 -0
- package/src/cli/handlers/build.ts +58 -1
- package/src/cli/handlers/components.test.ts +504 -0
- package/src/cli/handlers/components.ts +404 -0
- package/src/cli/handlers/dev.ts +60 -1
- package/src/cli/handlers/graph.ts +47 -2
- package/src/cli/handlers/misc.ts +45 -1
- package/src/cli/handlers/run.test.ts +967 -3
- package/src/cli/handlers/run.ts +618 -11
- package/src/cli/main.test.ts +66 -0
- package/src/cli/main.ts +105 -2
- package/src/cli/registry.ts +35 -0
- package/src/codegen/fetch.test.ts +84 -3
- package/src/codegen/fetch.ts +76 -2
- package/src/codegen/lexicon-regen.test.ts +298 -0
- package/src/codegen/lexicon-regen.ts +545 -0
- package/src/codegen/pinned-upgrade.test.ts +399 -0
- package/src/codegen/pinned-upgrade.ts +423 -0
- package/src/codegen/rolling-upgrade.test.ts +333 -0
- package/src/codegen/rolling-upgrade.ts +320 -0
- package/src/codegen/surface-snapshot.test.ts +461 -0
- package/src/codegen/surface-snapshot.ts +546 -0
- package/src/codegen/version-bump.test.ts +47 -0
- package/src/codegen/version-bump.ts +39 -0
- package/src/components/README.md +130 -0
- package/src/components/SPRAWL-VALIDATION.md +181 -0
- package/src/components/__fixtures__/alb-ecs-service.json +51 -0
- package/src/components/__fixtures__/dynamodb-infra.json +32 -0
- package/src/components/__fixtures__/emr-job-consumer.json +26 -0
- package/src/components/__fixtures__/jar-lib-producer.json +16 -0
- package/src/components/__fixtures__/lambda-image-processor.json +28 -0
- package/src/components/__fixtures__/neo4j-fanout.json +34 -0
- package/src/components/__fixtures__/single-host-compose.json +29 -0
- package/src/components/auto-release.test.ts +217 -0
- package/src/components/auto-release.ts +216 -0
- package/src/components/builders.test.ts +45 -0
- package/src/components/builders.ts +71 -0
- package/src/components/capability-plugin-loader.ts +218 -0
- package/src/components/capability-plugin-schema.ts +56 -0
- package/src/components/capability-plugin.test.ts +235 -0
- package/src/components/capability-plugin.ts +108 -0
- package/src/components/capability.ts +117 -0
- package/src/components/cli-support.test.ts +579 -0
- package/src/components/cli-support.ts +481 -0
- package/src/components/component-schema.test.ts +265 -0
- package/src/components/component.schema.json +235 -0
- package/src/components/component.test.ts +251 -0
- package/src/components/component.ts +255 -0
- package/src/components/config-defaults.test.ts +263 -0
- package/src/components/config-defaults.ts +145 -0
- package/src/components/discover.test.ts +352 -0
- package/src/components/discover.ts +167 -0
- package/src/components/driver-output.ts +71 -0
- package/src/components/driver.test.ts +638 -0
- package/src/components/driver.ts +690 -0
- package/src/components/index.ts +113 -0
- package/src/components/manifest-persistence.test.ts +152 -0
- package/src/components/manifest-persistence.ts +164 -0
- package/src/components/pilots/README.md +33 -0
- package/src/components/pilots/alb-ecs.pilot.ts +63 -0
- package/src/components/pilots/dynamodb.pilot.ts +59 -0
- package/src/components/pilots/jar-emr.pilot.ts +69 -0
- package/src/components/pilots/lambda.pilot.ts +55 -0
- package/src/components/pilots/neo4j-fanout.pilot.ts +92 -0
- package/src/components/pilots/pilots-lint-clean.test.ts +78 -0
- package/src/components/pilots/pilots.test.ts +126 -0
- package/src/components/pilots/project.ts +13 -0
- package/src/components/presets/comp007-reduction.test.ts +122 -0
- package/src/components/presets/ecs-fargate.test.ts +84 -0
- package/src/components/presets/ecs-fargate.ts +103 -0
- package/src/components/presets/index.ts +32 -0
- package/src/components/presets/lambda.test.ts +35 -0
- package/src/components/presets/lambda.ts +53 -0
- package/src/components/presets/single-host-compose.test.ts +65 -0
- package/src/components/presets/single-host-compose.ts +64 -0
- package/src/components/registry.test.ts +112 -0
- package/src/components/registry.ts +37 -0
- package/src/components/starter-plugin.ts +105 -0
- package/src/components/temporal-codegen-loader.ts +41 -0
- package/src/components/verbs/__fixtures__/package-lock.json +45 -0
- package/src/components/verbs/__fixtures__/pom.xml +37 -0
- package/src/components/verbs/__fixtures__/schemas/cyclonedx-1.5.schema.json +3800 -0
- package/src/components/verbs/__fixtures__/schemas/cyclonedx-spdx-license.schema.json +621 -0
- package/src/components/verbs/__fixtures__/schemas/jsf-0.82.schema.json +240 -0
- package/src/components/verbs/__fixtures__/schemas/spdx-2.3.schema.json +740 -0
- package/src/components/verbs/__tests__/mock-cloud-executor.ts +102 -0
- package/src/components/verbs/__tests__/mock-process-runner.ts +79 -0
- package/src/components/verbs/__tests__/mock-sbom-generator.ts +85 -0
- package/src/components/verbs/bom-writer.test.ts +331 -0
- package/src/components/verbs/bom-writer.ts +386 -0
- package/src/components/verbs/build-archive.test.ts +251 -0
- package/src/components/verbs/build-archive.ts +296 -0
- package/src/components/verbs/build.test.ts +222 -0
- package/src/components/verbs/build.ts +252 -0
- package/src/components/verbs/cloud-executor.ts +181 -0
- package/src/components/verbs/component-bom.test.ts +219 -0
- package/src/components/verbs/component-bom.ts +189 -0
- package/src/components/verbs/index.ts +49 -0
- package/src/components/verbs/license-policy.ts +115 -0
- package/src/components/verbs/lockfile-sbom-generator.test.ts +195 -0
- package/src/components/verbs/lockfile-sbom-generator.ts +236 -0
- package/src/components/verbs/process-runner.test.ts +79 -0
- package/src/components/verbs/process-runner.ts +113 -0
- package/src/components/verbs/reproducibility.test.ts +24 -0
- package/src/components/verbs/reproducibility.ts +100 -0
- package/src/components/verbs/sbom-generator.test.ts +96 -0
- package/src/components/verbs/sbom-generator.ts +209 -0
- package/src/components/verbs/sbom.test.ts +184 -0
- package/src/components/verbs/sbom.ts +152 -0
- package/src/components/verbs/shell.test.ts +36 -0
- package/src/components/verbs/shell.ts +51 -0
- package/src/components/verbs/sign.test.ts +210 -0
- package/src/components/verbs/sign.ts +350 -0
- package/src/components/verbs/stub.ts +34 -0
- package/src/components/verbs/tool-sbom-generator.test.ts +194 -0
- package/src/components/verbs/tool-sbom-generator.ts +192 -0
- package/src/components/verbs/verify.test.ts +159 -0
- package/src/components/verbs/verify.ts +179 -0
- package/src/components/verbs/vex.ts +182 -0
- package/src/components/verbs/vuln-gate.test.ts +201 -0
- package/src/components/verbs/vuln-gate.ts +170 -0
- package/src/components/verbs/vuln-scan.test.ts +145 -0
- package/src/components/verbs/vuln-scan.ts +266 -0
- package/src/components/verbs/wait-verify.test.ts +111 -0
- package/src/components/verbs/wait-verify.ts +171 -0
- package/src/config.test.ts +74 -1
- package/src/config.ts +219 -0
- package/src/index.ts +32 -0
- package/src/lexicon.ts +88 -0
- package/src/lifecycle/build-ledger-store.test.ts +217 -0
- package/src/lifecycle/build-ledger-store.ts +165 -0
- package/src/lifecycle/build-ledger.test.ts +349 -0
- package/src/lifecycle/build-ledger.ts +305 -0
- package/src/lifecycle/git.test.ts +118 -0
- package/src/lifecycle/git.ts +149 -14
- package/src/lifecycle/index.ts +5 -0
- package/src/lifecycle/oras-referrer-lookup.test.ts +116 -0
- package/src/lifecycle/oras-referrer-lookup.ts +110 -0
- package/src/lifecycle/release-ledger.test.ts +209 -0
- package/src/lifecycle/release-ledger.ts +185 -0
- package/src/lifecycle/status.test.ts +330 -0
- package/src/lifecycle/status.ts +278 -0
- package/src/lint/component-checks.ts +148 -0
- package/src/lint/config.test.ts +21 -0
- package/src/lint/engine.ts +11 -2
- package/src/lint/presets/relaxed.json +8 -1
- package/src/lint/presets/strict.json +8 -1
- package/src/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-a.component.ts +9 -0
- package/src/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-b.component.ts +9 -0
- package/src/lint/rules/__fixtures__/comp/comp001/fail/orphan-lib.component.ts +11 -0
- package/src/lint/rules/__fixtures__/comp/comp001/pass/emr-job.component.ts +13 -0
- package/src/lint/rules/__fixtures__/comp/comp001/pass/jar-lib.component.ts +11 -0
- package/src/lint/rules/__fixtures__/comp/comp002/fail/search-service.component.ts +27 -0
- package/src/lint/rules/__fixtures__/comp/comp002/pass/jar-lib.component.ts +10 -0
- package/src/lint/rules/__fixtures__/comp/comp002/pass/search-service.component.ts +23 -0
- package/src/lint/rules/__fixtures__/comp/comp003/fail/migrator.component.ts +10 -0
- package/src/lint/rules/__fixtures__/comp/comp003/pass/migrator.component.ts +19 -0
- package/src/lint/rules/__fixtures__/comp/comp003/pass/orders-table.component.ts +10 -0
- package/src/lint/rules/__fixtures__/comp/comp004/fail/neo4j-cluster.component.ts +20 -0
- package/src/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.ts +23 -0
- package/src/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.ts +10 -0
- package/src/lint/rules/__fixtures__/comp/comp005/fail/search-service.component.ts +14 -0
- package/src/lint/rules/__fixtures__/comp/comp005/pass/search-service.component.ts +18 -0
- package/src/lint/rules/__fixtures__/comp/comp006/fail/legacy-tool.component.ts +10 -0
- package/src/lint/rules/__fixtures__/comp/comp006/pass/legacy-tool.component.ts +14 -0
- package/src/lint/rules/__fixtures__/comp/comp007/fail/inventory-table.component.ts +13 -0
- package/src/lint/rules/__fixtures__/comp/comp007/fail/orders-table.component.ts +13 -0
- package/src/lint/rules/__fixtures__/comp/comp007/pass/orders-table.component.ts +12 -0
- package/src/lint/rules/__fixtures__/comp/comp007/pass/search-service.component.ts +18 -0
- package/src/lint/rules/comp/comp.test.ts +378 -0
- package/src/lint/rules/comp/comp001-publishes-never-applies.ts +78 -0
- package/src/lint/rules/comp/comp002-dangling-wiring-ref.ts +94 -0
- package/src/lint/rules/comp/comp003-mutating-no-rollback.ts +115 -0
- package/src/lint/rules/comp/comp004-gate-needs-temporal.ts +66 -0
- package/src/lint/rules/comp/comp005-capability-kind-is-noun.ts +113 -0
- package/src/lint/rules/comp/comp006-shell-needs-reason.ts +55 -0
- package/src/lint/rules/comp/comp007-composition-sprawl.ts +71 -0
- package/src/lint/rules/comp/index.ts +37 -0
- package/src/lint/rules/comp/support.ts +173 -0
- package/src/lsp/lexicon-providers.test.ts +55 -0
- package/src/lsp/lexicon-providers.ts +13 -3
- package/src/op/activity-registry.test.ts +38 -0
- package/src/op/activity-registry.ts +31 -12
- package/src/op/activity-runtime.ts +73 -0
- package/src/op/builders.ts +92 -0
- package/src/op/index.ts +3 -1
- package/src/ownership.test.ts +24 -26
- package/src/ownership.ts +26 -38
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Preset: `EcsFargateComponent` (#566, epic #551 §"6. Presets (Level 2 reuse)").
|
|
3
|
+
*
|
|
4
|
+
* The named-composition builder for the ALB/ECS shape
|
|
5
|
+
* (`../pilots/alb-ecs.pilot.ts`): `docker-build` -> `publish-image` ->
|
|
6
|
+
* `cfn-deploy` (importing a shared ALB's cross-stack outputs) ->
|
|
7
|
+
* `ecs-update-service` -> `wait-steady-state` + `health-gate`, with the same
|
|
8
|
+
* component-declared `rollback-previous` compensation phase the pilot uses
|
|
9
|
+
* (no native rollback for an already-running service swap — see
|
|
10
|
+
* ../pilots/alb-ecs.pilot.ts's docstring).
|
|
11
|
+
*
|
|
12
|
+
* This is Level 2 reuse over Level 1 raw capabilities: a component that looks
|
|
13
|
+
* like this composes `EcsFargateComponent({ ... })` directly; the odd case
|
|
14
|
+
* that needs something extra starts from the same shape and drops to raw
|
|
15
|
+
* `phase()`/capability `Step`s where it is special (see
|
|
16
|
+
* docs/components/capabilities.mdx#presets--reuse-without-a-closed-set) —
|
|
17
|
+
* `./ecs-fargate.test.ts` demonstrates exactly that by re-deriving
|
|
18
|
+
* `alb-ecs.pilot.ts`'s `searchService` component from this preset and
|
|
19
|
+
* asserting the two project to the identical JSON contract.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import type { Component, Wiring } from "../component";
|
|
23
|
+
import { phase, stackOutput } from "../component";
|
|
24
|
+
|
|
25
|
+
export interface EcsFargateComponentConfig {
|
|
26
|
+
/** Component/service name (kebab-case) — becomes both the component's `name` and the ECS service name unless `service` overrides it. */
|
|
27
|
+
name: string;
|
|
28
|
+
/** ECS service name. Default: `name`. */
|
|
29
|
+
service?: string;
|
|
30
|
+
/** Docker build context. Default: ".". */
|
|
31
|
+
context?: string;
|
|
32
|
+
/** Path to the built CloudFormation template inside the archive. Default: `archive:<name>.template.json`. */
|
|
33
|
+
template?: string;
|
|
34
|
+
/** Health check path for the post-deploy `health-gate`. */
|
|
35
|
+
healthPath: string;
|
|
36
|
+
/** Other components that must complete first, beyond the shared-ALB stack (if any). */
|
|
37
|
+
dependsOn?: string[];
|
|
38
|
+
/**
|
|
39
|
+
* Shared ALB stack this service imports `ListenerArn`/`ClusterArn`/`Subnets`
|
|
40
|
+
* from, via cross-stack `stackOutput()` wiring — the same axis
|
|
41
|
+
* `alb-ecs.pilot.ts` exercises. Omit for a service with its own
|
|
42
|
+
* self-contained stack (no shared-ALB import; `cfn-deploy` receives no
|
|
43
|
+
* `inputs`).
|
|
44
|
+
*/
|
|
45
|
+
sharedAlbStack?: string;
|
|
46
|
+
/** Additional/override CloudFormation template inputs, merged with (and taking precedence over) the shared-ALB outputs. */
|
|
47
|
+
extraInputs?: Record<string, Wiring>;
|
|
48
|
+
/** ECS cluster reference passed to `ecs-update-service`. Default: `"$env.cluster"`. */
|
|
49
|
+
cluster?: Wiring;
|
|
50
|
+
/** Destination registry `publish-image` promotes to. Default: `"$env.registry"`. */
|
|
51
|
+
registry?: Wiring;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Expand an ECS/Fargate service behind an ALB to its standard
|
|
56
|
+
* Publish/Apply/Verify composition — the 80% shape `alb-ecs.pilot.ts` is the
|
|
57
|
+
* hand-composed reference for. Returns a full `Component`; a caller that
|
|
58
|
+
* needs one extra step (an additional Apply capability, a different Verify
|
|
59
|
+
* shape) spreads the result and edits `deploy`/`rollback` directly — the
|
|
60
|
+
* preset is a starting composition, not a closed strategy object.
|
|
61
|
+
*/
|
|
62
|
+
export function EcsFargateComponent(config: EcsFargateComponentConfig): Component {
|
|
63
|
+
const service = config.service ?? config.name;
|
|
64
|
+
const template = config.template ?? `archive:${config.name}.template.json`;
|
|
65
|
+
const cluster = config.cluster ?? "$env.cluster";
|
|
66
|
+
const registry = config.registry ?? "$env.registry";
|
|
67
|
+
|
|
68
|
+
const sharedAlbOutputs = config.sharedAlbStack
|
|
69
|
+
? {
|
|
70
|
+
listenerArn: stackOutput(config.sharedAlbStack, "ListenerArn"),
|
|
71
|
+
clusterArn: stackOutput(config.sharedAlbStack, "ClusterArn"),
|
|
72
|
+
subnets: stackOutput(config.sharedAlbStack, "Subnets"),
|
|
73
|
+
}
|
|
74
|
+
: undefined;
|
|
75
|
+
const inputs =
|
|
76
|
+
sharedAlbOutputs || config.extraInputs ? { ...sharedAlbOutputs, ...config.extraInputs } : undefined;
|
|
77
|
+
|
|
78
|
+
const dependsOn = [...(config.sharedAlbStack ? [config.sharedAlbStack] : []), ...(config.dependsOn ?? [])];
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
name: config.name,
|
|
82
|
+
archetype: "service",
|
|
83
|
+
dependsOn,
|
|
84
|
+
build: { kind: "docker-build", context: config.context ?? ".", into: "archive" },
|
|
85
|
+
deploy: [
|
|
86
|
+
phase("Publish", [{ kind: "publish-image", from: "archive", to: registry }]),
|
|
87
|
+
phase("Apply", [
|
|
88
|
+
{
|
|
89
|
+
kind: "cfn-deploy",
|
|
90
|
+
template,
|
|
91
|
+
imageRef: "@Publish.digest",
|
|
92
|
+
...(inputs ? { inputs } : {}),
|
|
93
|
+
},
|
|
94
|
+
{ kind: "ecs-update-service", cluster, service },
|
|
95
|
+
]),
|
|
96
|
+
phase("Verify", [
|
|
97
|
+
{ kind: "wait-steady-state", service },
|
|
98
|
+
{ kind: "health-gate", path: config.healthPath },
|
|
99
|
+
]),
|
|
100
|
+
],
|
|
101
|
+
rollback: [phase("Rollback", [{ kind: "rollback-previous", service, cluster }])],
|
|
102
|
+
};
|
|
103
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Preset library (#566, epic #551 §"6. Presets (Level 2 reuse)") — named
|
|
3
|
+
* composition builders for the common component shapes. Each preset expands
|
|
4
|
+
* to a full, valid `Component` (../component.ts): the same typed authoring
|
|
5
|
+
* form and JSON contract every hand-composed component projects to, so a
|
|
6
|
+
* preset-based component and a hand-composed one are indistinguishable to
|
|
7
|
+
* `projectToJson`, schema validation, lint, and the driver.
|
|
8
|
+
*
|
|
9
|
+
* This is Level 2 reuse over Level 1 raw capabilities
|
|
10
|
+
* (docs/components/capabilities.mdx#presets--reuse-without-a-closed-set): a
|
|
11
|
+
* component that matches one of these shapes calls the preset directly; the
|
|
12
|
+
* odd one that needs something extra spreads the returned `Component` and
|
|
13
|
+
* edits `deploy`/`rollback` where it is special. Presets remove composition
|
|
14
|
+
* copy-paste (the COMP007 lint hint) without creating a closed strategy set —
|
|
15
|
+
* see ./ecs-fargate.test.ts, ./lambda.test.ts, and
|
|
16
|
+
* ./single-host-compose.test.ts, each of which re-derives an existing
|
|
17
|
+
* hand-composed pilot/fixture from its preset and asserts the two project to
|
|
18
|
+
* the identical JSON contract.
|
|
19
|
+
*
|
|
20
|
+
* Deliberately not exhaustive: three presets covering the three archetypes'
|
|
21
|
+
* most common shapes (a load-balanced container service, a container-image
|
|
22
|
+
* Lambda function, and a registry-less single-host compose deploy), per
|
|
23
|
+
* #566's explicit scope ("start with the common shapes; an exhaustive
|
|
24
|
+
* catalog is out of scope").
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
export { EcsFargateComponent, type EcsFargateComponentConfig } from "./ecs-fargate";
|
|
28
|
+
export { LambdaComponent, type LambdaComponentConfig } from "./lambda";
|
|
29
|
+
export {
|
|
30
|
+
SingleHostComposeComponent,
|
|
31
|
+
type SingleHostComposeComponentConfig,
|
|
32
|
+
} from "./single-host-compose";
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `LambdaComponent` (#566): schema validity, and equivalence with the
|
|
3
|
+
* hand-composed `lambda.pilot.ts` reference component.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, expect, it } from "vitest";
|
|
7
|
+
import Ajv2020 from "ajv/dist/2020";
|
|
8
|
+
import componentSchema from "../component.schema.json";
|
|
9
|
+
import { projectToJson } from "../component";
|
|
10
|
+
import { imageProcessor } from "../pilots/lambda.pilot";
|
|
11
|
+
import { LambdaComponent } from "./lambda";
|
|
12
|
+
|
|
13
|
+
const ajv = new Ajv2020({ strict: true, allErrors: true });
|
|
14
|
+
const validate = ajv.compile(componentSchema);
|
|
15
|
+
|
|
16
|
+
describe("LambdaComponent preset", () => {
|
|
17
|
+
it("expands to a component that projects to schema-valid JSON", () => {
|
|
18
|
+
const component = LambdaComponent({ name: "image-processor-lambda", functionName: "image-processor" });
|
|
19
|
+
const projected = projectToJson(component);
|
|
20
|
+
const valid = validate(projected);
|
|
21
|
+
if (!valid) throw new Error(ajv.errorsText(validate.errors));
|
|
22
|
+
expect(valid).toBe(true);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("re-derives lambda.pilot.ts's hand-composed imageProcessor component byte-for-byte (as data)", () => {
|
|
26
|
+
const fromPreset = LambdaComponent({ name: "image-processor-lambda", functionName: "image-processor" });
|
|
27
|
+
expect(projectToJson(fromPreset)).toEqual(projectToJson(imageProcessor));
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("defaults functionName to the component name when omitted", () => {
|
|
31
|
+
const component = LambdaComponent({ name: "thumbnailer" });
|
|
32
|
+
const applyStep = component.deploy.find((p) => p.phase === "Apply")!.steps[0] as unknown as { functionName: string };
|
|
33
|
+
expect(applyStep.functionName).toBe("thumbnailer");
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Preset: `LambdaComponent` (#566, epic #551 §"6. Presets (Level 2 reuse)").
|
|
3
|
+
*
|
|
4
|
+
* The named-composition builder for the container-image Lambda shape
|
|
5
|
+
* (`../pilots/lambda.pilot.ts`): `docker-build` -> `publish-image` ->
|
|
6
|
+
* `lambda-deploy` -> `health-gate` against the function's alias. Distinct
|
|
7
|
+
* from `EcsFargateComponent`'s apply family on purpose — no CloudFormation
|
|
8
|
+
* stack in Apply at all, matching the pilot's documented "first pilot whose
|
|
9
|
+
* Apply phase contains no cfn-deploy" shape.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { Component } from "../component";
|
|
13
|
+
import { phase } from "../component";
|
|
14
|
+
|
|
15
|
+
export interface LambdaComponentConfig {
|
|
16
|
+
/** Component name (kebab-case) — becomes both the component's `name` and, by default, the Lambda function name. */
|
|
17
|
+
name: string;
|
|
18
|
+
/** Lambda function name. Default: `name`. */
|
|
19
|
+
functionName?: string;
|
|
20
|
+
/** Docker build context. Default: ".". */
|
|
21
|
+
context?: string;
|
|
22
|
+
/** Alias to repoint at the new version after publish. Default: "live". */
|
|
23
|
+
alias?: string;
|
|
24
|
+
/** Destination registry `publish-image` promotes to. Default: `"$env.registry"`. */
|
|
25
|
+
registry?: string;
|
|
26
|
+
/** Other components that must complete first. */
|
|
27
|
+
dependsOn?: string[];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Expand a container-image AWS Lambda function to its standard
|
|
32
|
+
* Publish/Apply/Verify composition — the reference shape
|
|
33
|
+
* `lambda.pilot.ts` hand-composes. Reuses `docker-build`/`publish-image`
|
|
34
|
+
* unchanged from `EcsFargateComponent`'s build axis (build + promote-by-digest
|
|
35
|
+
* is identical for a container-image Lambda); only the apply/verify shape
|
|
36
|
+
* differs.
|
|
37
|
+
*/
|
|
38
|
+
export function LambdaComponent(config: LambdaComponentConfig): Component {
|
|
39
|
+
const functionName = config.functionName ?? config.name;
|
|
40
|
+
const alias = config.alias ?? "live";
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
name: config.name,
|
|
44
|
+
archetype: "service",
|
|
45
|
+
dependsOn: config.dependsOn ?? [],
|
|
46
|
+
build: { kind: "docker-build", context: config.context ?? ".", into: "archive" },
|
|
47
|
+
deploy: [
|
|
48
|
+
phase("Publish", [{ kind: "publish-image", from: "archive", to: config.registry ?? "$env.registry" }]),
|
|
49
|
+
phase("Apply", [{ kind: "lambda-deploy", functionName, codeRef: "@Publish.uri", alias }]),
|
|
50
|
+
phase("Verify", [{ kind: "health-gate", path: "@Apply.functionArn" }]),
|
|
51
|
+
],
|
|
52
|
+
};
|
|
53
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `SingleHostComposeComponent` (#566): schema validity, and equivalence with
|
|
3
|
+
* the hand-written `__fixtures__/single-host-compose.json` reference
|
|
4
|
+
* document — the fixture is the authoritative hand-composed form for this
|
|
5
|
+
* shape (no `*.pilot.ts` TypeScript authoring form exists for it yet, unlike
|
|
6
|
+
* the ALB/ECS and Lambda shapes), matching how `../pilots/pilots.test.ts`
|
|
7
|
+
* compares a pilot's projection against its `__fixtures__/*.json` sibling.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { readFileSync } from "node:fs";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { describe, expect, it } from "vitest";
|
|
13
|
+
import Ajv2020 from "ajv/dist/2020";
|
|
14
|
+
import componentSchema from "../component.schema.json";
|
|
15
|
+
import { projectToJson } from "../component";
|
|
16
|
+
import { SingleHostComposeComponent } from "./single-host-compose";
|
|
17
|
+
|
|
18
|
+
const ajv = new Ajv2020({ strict: true, allErrors: true });
|
|
19
|
+
const validate = ajv.compile(componentSchema);
|
|
20
|
+
|
|
21
|
+
function loadFixture(name: string): unknown {
|
|
22
|
+
return JSON.parse(readFileSync(join(import.meta.dirname, "..", "__fixtures__", name), "utf-8"));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
describe("SingleHostComposeComponent preset", () => {
|
|
26
|
+
it("expands to a component that projects to schema-valid JSON", () => {
|
|
27
|
+
const component = SingleHostComposeComponent({
|
|
28
|
+
name: "monitoring-host",
|
|
29
|
+
healthPath: "/-/healthy",
|
|
30
|
+
healthPort: 9090,
|
|
31
|
+
});
|
|
32
|
+
const projected = projectToJson(component);
|
|
33
|
+
const valid = validate(projected);
|
|
34
|
+
if (!valid) throw new Error(ajv.errorsText(validate.errors));
|
|
35
|
+
expect(valid).toBe(true);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("re-derives the hand-written single-host-compose.json fixture (as data, ignoring document-level $schema/contractVersion provenance fields)", () => {
|
|
39
|
+
const fromPreset = SingleHostComposeComponent({
|
|
40
|
+
name: "monitoring-host",
|
|
41
|
+
// The fixture's on-host path is "/opt/monitoring/..." rather than this
|
|
42
|
+
// preset's "<name>"-derived default ("/opt/monitoring-host/...") — pass
|
|
43
|
+
// it explicitly to match the pre-existing hand-written fixture exactly.
|
|
44
|
+
hostComposePath: "/opt/monitoring/compose.yaml",
|
|
45
|
+
healthPath: "/-/healthy",
|
|
46
|
+
healthPort: 9090,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const fixture = loadFixture("single-host-compose.json") as Record<string, unknown>;
|
|
50
|
+
const { $schema: _s, contractVersion: _v, ...fixtureContent } = fixture;
|
|
51
|
+
expect(projectToJson(fromPreset)).toEqual(fixtureContent);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("defaults host and the on-host compose path when omitted", () => {
|
|
55
|
+
const component = SingleHostComposeComponent({
|
|
56
|
+
name: "monitoring-host",
|
|
57
|
+
healthPath: "/-/healthy",
|
|
58
|
+
healthPort: 9090,
|
|
59
|
+
});
|
|
60
|
+
const applyPhase = component.deploy.find((p) => p.phase === "Apply")!;
|
|
61
|
+
const copyStep = applyPhase.steps[0] as unknown as { host: string; to: string };
|
|
62
|
+
expect(copyStep.host).toBe("$env.host");
|
|
63
|
+
expect(copyStep.to).toBe("/opt/monitoring-host/compose.yaml");
|
|
64
|
+
});
|
|
65
|
+
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Preset: `SingleHostComposeComponent` (#566, epic #551 §"6. Presets (Level 2
|
|
3
|
+
* reuse)").
|
|
4
|
+
*
|
|
5
|
+
* The named-composition builder for the registry-less single-host Docker
|
|
6
|
+
* Compose shape (`../__fixtures__/single-host-compose.json`): `docker-build`
|
|
7
|
+
* -> `load-image-on-host` (registry-free promotion, see
|
|
8
|
+
* ../verbs/publish.ts's `load-image-on-host` docstring) -> `copy-to-host` the
|
|
9
|
+
* compose file -> `remote-exec` a `docker compose up -d` -> `wait-endpoint`
|
|
10
|
+
* against the service's health path. This is the N=1 case of the fan-out
|
|
11
|
+
* shape `neo4j-fanout.pilot.ts` composes by hand at N=3 — single-host compose
|
|
12
|
+
* and a host fleet are the same composition shape at different N (see
|
|
13
|
+
* docs/components/composition-and-wiring.mdx#fan-out-is-composition-not-orchestrator-knowledge).
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import type { Component } from "../component";
|
|
17
|
+
import { phase } from "../component";
|
|
18
|
+
|
|
19
|
+
export interface SingleHostComposeComponentConfig {
|
|
20
|
+
/** Component name (kebab-case). */
|
|
21
|
+
name: string;
|
|
22
|
+
/** Docker build context. Default: ".". */
|
|
23
|
+
context?: string;
|
|
24
|
+
/** Path to the compose file inside the archive. Default: "archive:compose.yaml". */
|
|
25
|
+
composeFile?: string;
|
|
26
|
+
/** Destination path for the compose file on the host. Default: `/opt/<name>/compose.yaml`. */
|
|
27
|
+
hostComposePath?: string;
|
|
28
|
+
/** Target host (SSM instance id, hostname, or host group). Default: `"$env.host"`. */
|
|
29
|
+
host?: string;
|
|
30
|
+
/** Health check path polled after `docker compose up -d`. */
|
|
31
|
+
healthPath: string;
|
|
32
|
+
/** Port the health check listens on. */
|
|
33
|
+
healthPort: number;
|
|
34
|
+
/** Other components that must complete first. */
|
|
35
|
+
dependsOn?: string[];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Expand a single-host Docker Compose deploy to its standard
|
|
40
|
+
* Publish/Apply/Verify composition. No registry ever in the path: the built
|
|
41
|
+
* image tarball is copied straight onto the host and `docker load`ed there
|
|
42
|
+
* (`load-image-on-host`), the compose file follows the same way, and
|
|
43
|
+
* `docker compose up -d` runs via `remote-exec` — the registry-less backend
|
|
44
|
+
* axis documented in docs/components/build-archive.mdx.
|
|
45
|
+
*/
|
|
46
|
+
export function SingleHostComposeComponent(config: SingleHostComposeComponentConfig): Component {
|
|
47
|
+
const host = config.host ?? "$env.host";
|
|
48
|
+
const hostComposePath = config.hostComposePath ?? `/opt/${config.name}/compose.yaml`;
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
name: config.name,
|
|
52
|
+
archetype: "service",
|
|
53
|
+
dependsOn: config.dependsOn ?? [],
|
|
54
|
+
build: { kind: "docker-build", context: config.context ?? ".", into: "archive" },
|
|
55
|
+
deploy: [
|
|
56
|
+
phase("Publish", [{ kind: "load-image-on-host", from: "archive", host }]),
|
|
57
|
+
phase("Apply", [
|
|
58
|
+
{ kind: "copy-to-host", from: config.composeFile ?? "archive:compose.yaml", to: hostComposePath, host },
|
|
59
|
+
{ kind: "remote-exec", host, command: `docker compose -f ${hostComposePath} up -d` },
|
|
60
|
+
]),
|
|
61
|
+
phase("Verify", [{ kind: "wait-endpoint", host, path: config.healthPath, port: config.healthPort }]),
|
|
62
|
+
],
|
|
63
|
+
};
|
|
64
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { createCapabilityRegistry, STARTER_VERB_FAMILIES } from "./registry";
|
|
3
|
+
import { CapabilityNotImplementedError } from "./capability";
|
|
4
|
+
import { stubCapability } from "./verbs/stub";
|
|
5
|
+
|
|
6
|
+
const ALL_STARTER_KINDS = Object.values(STARTER_VERB_FAMILIES).flat();
|
|
7
|
+
|
|
8
|
+
describe("createCapabilityRegistry", () => {
|
|
9
|
+
test("resolves every starter verb by kind", () => {
|
|
10
|
+
const registry = createCapabilityRegistry();
|
|
11
|
+
for (const kind of ALL_STARTER_KINDS) {
|
|
12
|
+
expect(registry.has(kind)).toBe(true);
|
|
13
|
+
const capability = registry.resolve(kind);
|
|
14
|
+
expect(capability.kind).toBe(kind);
|
|
15
|
+
expect(typeof capability.run).toBe("function");
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test("kinds() lists exactly the starter set, sorted", () => {
|
|
20
|
+
const registry = createCapabilityRegistry();
|
|
21
|
+
expect(registry.kinds()).toEqual([...ALL_STARTER_KINDS].sort());
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test("throws a friendly error for an unregistered kind", () => {
|
|
25
|
+
const registry = createCapabilityRegistry();
|
|
26
|
+
expect(() => registry.resolve("nonexistent-verb")).toThrow(
|
|
27
|
+
/no capability registered for kind "nonexistent-verb"/,
|
|
28
|
+
);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// The starter set no longer carries any cloud leaf — `cfn-deploy` and the
|
|
32
|
+
// rest live in the aws lexicon now — so `cfn-deploy` is genuinely unknown to
|
|
33
|
+
// a core-only registry, resolving only once the aws capability plugin is
|
|
34
|
+
// loaded (see ./capability-plugin-loader.ts's lexicon path).
|
|
35
|
+
test("a cloud-leaf kind (cfn-deploy) is not in the core starter set", () => {
|
|
36
|
+
const registry = createCapabilityRegistry();
|
|
37
|
+
expect(registry.has("cfn-deploy")).toBe(false);
|
|
38
|
+
expect(() => registry.resolve("cfn-deploy")).toThrow(/no capability registered for kind "cfn-deploy"/);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test("registering a duplicate kind throws", () => {
|
|
42
|
+
const registry = createCapabilityRegistry();
|
|
43
|
+
expect(() =>
|
|
44
|
+
registry.register({
|
|
45
|
+
kind: "docker-build",
|
|
46
|
+
run: async () => ({ archivePath: "", digest: "" }),
|
|
47
|
+
}),
|
|
48
|
+
).toThrow('capability "docker-build" is already registered');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// No starter verb is a stub any more (all implemented), but the stub
|
|
52
|
+
// *mechanism* (./verbs/stub.ts) stays for third-party plugins / future verbs:
|
|
53
|
+
// a stub's run()/rollback() reject with CapabilityNotImplementedError, and
|
|
54
|
+
// the driver surfaces that as a failed step rather than crashing.
|
|
55
|
+
test("stubCapability run()/rollback() reject with CapabilityNotImplementedError, naming the kind", async () => {
|
|
56
|
+
const stub = stubCapability("some-future-verb", { rollback: true });
|
|
57
|
+
await expect(stub.run({ env: "dev", component: "test" }, {} as never)).rejects.toBeInstanceOf(
|
|
58
|
+
CapabilityNotImplementedError,
|
|
59
|
+
);
|
|
60
|
+
await expect(stub.run({ env: "dev", component: "test" }, {} as never)).rejects.toThrow(
|
|
61
|
+
'capability "some-future-verb" is not implemented',
|
|
62
|
+
);
|
|
63
|
+
expect(typeof stub.rollback).toBe("function");
|
|
64
|
+
await expect(stub.rollback?.({ env: "dev", component: "test" }, {} as never)).rejects.toBeInstanceOf(
|
|
65
|
+
CapabilityNotImplementedError,
|
|
66
|
+
);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test("capabilities without declared rollback have none", () => {
|
|
70
|
+
const registry = createCapabilityRegistry();
|
|
71
|
+
expect(registry.resolve("zip-package").rollback).toBeUndefined();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// The agnostic starter verbs are all real implementations — `run` is a real
|
|
75
|
+
// function, not the stub thrower.
|
|
76
|
+
test("agnostic starter verbs are real implementations, not stubs", () => {
|
|
77
|
+
const registry = createCapabilityRegistry();
|
|
78
|
+
for (const kind of [
|
|
79
|
+
"docker-build",
|
|
80
|
+
"zip-package",
|
|
81
|
+
"jvm-build",
|
|
82
|
+
"generate-sbom",
|
|
83
|
+
"sign",
|
|
84
|
+
"verify",
|
|
85
|
+
"vuln-gate",
|
|
86
|
+
"wait-cluster-healthy",
|
|
87
|
+
"wait-endpoint",
|
|
88
|
+
"health-gate",
|
|
89
|
+
]) {
|
|
90
|
+
const capability = registry.resolve(kind);
|
|
91
|
+
expect(typeof capability.run).toBe("function");
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test("family table lists exactly the agnostic starter families (cloud leaves moved to lexicons)", () => {
|
|
96
|
+
expect(Object.keys(STARTER_VERB_FAMILIES).sort()).toEqual(
|
|
97
|
+
["build", "escapeHatch", "sbom", "supplyChainPolicy", "supplyChainSecurity", "waitVerify"].sort(),
|
|
98
|
+
);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// #606: `generate-sbom` is a real implementation (over the injectable,
|
|
102
|
+
// artifact-type-keyed SbomGenerator — see ./verbs/sbom-generator.ts),
|
|
103
|
+
// defaulted to the hermetic lockfile-backed generator for dir/zip/jar
|
|
104
|
+
// artifacts (#630) — `forImage` still needs a real scanner backend wired
|
|
105
|
+
// in explicitly (#610).
|
|
106
|
+
test("#606 generate-sbom is registered and callable (default backend is the hermetic lockfile generator, #630)", () => {
|
|
107
|
+
const registry = createCapabilityRegistry();
|
|
108
|
+
const capability = registry.resolve("generate-sbom");
|
|
109
|
+
expect(typeof capability.run).toBe("function");
|
|
110
|
+
expect(capability.rollback).toBeUndefined();
|
|
111
|
+
});
|
|
112
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The starter capability registry — one `CapabilityRegistry` pre-seeded with
|
|
3
|
+
* every verb in the starter set (epic #551, issue #554). All stubs; no cloud
|
|
4
|
+
* calls except for the #557/#558 AWS leaves (real implementations).
|
|
5
|
+
*
|
|
6
|
+
* Phase 2 (#559) promotes this convention to a first-class plugin contract
|
|
7
|
+
* (./capability-plugin.ts): the starter verb set now ships as
|
|
8
|
+
* `starterCapabilityPlugin` (./starter-plugin.ts), and `createCapabilityRegistry`
|
|
9
|
+
* below builds its registry from that plugin's `capabilities()` instead of
|
|
10
|
+
* registering each verb inline. This is a pure refactor — same kinds, same
|
|
11
|
+
* capability instances, same registration order — so every existing caller
|
|
12
|
+
* (the driver, the pilots, ./registry.test.ts) is unaffected. New code
|
|
13
|
+
* should prefer `buildCapabilityRegistry` (./capability-plugin-loader.ts),
|
|
14
|
+
* which additionally supports loading third-party capability plugins on top
|
|
15
|
+
* of this same starter set, the way lexicons are discovered today.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { CapabilityRegistry } from "./capability";
|
|
19
|
+
import { starterCapabilityPlugin, STARTER_VERB_FAMILIES } from "./starter-plugin";
|
|
20
|
+
|
|
21
|
+
/** Build a fresh `CapabilityRegistry` containing every starter-set verb stub. */
|
|
22
|
+
export function createCapabilityRegistry(): CapabilityRegistry {
|
|
23
|
+
const registry = new CapabilityRegistry();
|
|
24
|
+
for (const capability of starterCapabilityPlugin.capabilities()) {
|
|
25
|
+
registry.register(capability);
|
|
26
|
+
}
|
|
27
|
+
return registry;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Every `kind` in the starter verb set, grouped by family — useful for tests
|
|
32
|
+
* and docs generation. Re-exported here (source of truth moved to
|
|
33
|
+
* ./starter-plugin.ts to avoid a module cycle with `starterCapabilityPlugin`)
|
|
34
|
+
* so every existing import of `STARTER_VERB_FAMILIES` from this module keeps
|
|
35
|
+
* working unchanged.
|
|
36
|
+
*/
|
|
37
|
+
export { STARTER_VERB_FAMILIES };
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The starter verb set (epic #551, #554/#557/#558), wrapped as a
|
|
3
|
+
* `CapabilityPlugin` (#559) — the built-in, always-loaded plugin that
|
|
4
|
+
* carries every Phase 1 capability forward under the Phase 2 plugin
|
|
5
|
+
* contract with **no behavior change**.
|
|
6
|
+
*
|
|
7
|
+
* Migration path from Phase 1 to Phase 2: Phase 1 (`createCapabilityRegistry`,
|
|
8
|
+
* ./registry.ts) constructed a `CapabilityRegistry` by registering each
|
|
9
|
+
* starter verb directly. Phase 2 introduces `CapabilityPlugin` as the
|
|
10
|
+
* discoverable, typed package contract (./capability-plugin.ts) that
|
|
11
|
+
* mirrors how lexicons are packaged (../lexicon.ts). Rather than rewrite the
|
|
12
|
+
* starter verbs, this module packages the *exact same* verb list as one
|
|
13
|
+
* `CapabilityPlugin` named "starter" — so:
|
|
14
|
+
*
|
|
15
|
+
* - `createCapabilityRegistry()` (./registry.ts) now builds its registry by
|
|
16
|
+
* registering `starterCapabilityPlugin.capabilities()` instead of calling
|
|
17
|
+
* `registry.register(...)` once per verb inline. Same kinds, same
|
|
18
|
+
* instances, same order, same resulting registry — verified by
|
|
19
|
+
* ./registry.test.ts, unchanged.
|
|
20
|
+
* - `buildCapabilityRegistry()` (./capability-plugin-loader.ts), the new
|
|
21
|
+
* Phase 2 entry point, always loads this plugin first, then layers any
|
|
22
|
+
* additional third-party capability plugins on top by `kind`.
|
|
23
|
+
* - The driver (./driver.ts) and every pilot (./pilots/*.pilot.ts) consume
|
|
24
|
+
* only a `CapabilityRegistry` instance and never construct one directly
|
|
25
|
+
* from verb modules, so neither needed to change for this migration —
|
|
26
|
+
* the compatibility guarantee #559 asks for.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import type { Capability } from "./capability";
|
|
30
|
+
import {
|
|
31
|
+
dockerBuildCapability,
|
|
32
|
+
zipPackageCapability,
|
|
33
|
+
jvmBuildCapability,
|
|
34
|
+
generateSbomCapability,
|
|
35
|
+
signCapability,
|
|
36
|
+
attestProvenanceCapability,
|
|
37
|
+
verifyCapability,
|
|
38
|
+
scanVulnerabilitiesCapability,
|
|
39
|
+
vulnGateCapability,
|
|
40
|
+
waitClusterHealthyCapability,
|
|
41
|
+
waitEndpointCapability,
|
|
42
|
+
healthGateCapability,
|
|
43
|
+
shellCapability,
|
|
44
|
+
} from "./verbs/index";
|
|
45
|
+
import type { CapabilityPlugin } from "./capability-plugin";
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Every `kind` in the starter verb set, grouped by family, per epic #551 and
|
|
49
|
+
* docs/components/capabilities.mdx. Source of truth (moved here from
|
|
50
|
+
* ./registry.ts in #559 to avoid a module cycle: ./registry.ts's
|
|
51
|
+
* `createCapabilityRegistry` depends on `starterCapabilityPlugin`, so this
|
|
52
|
+
* plugin module cannot depend back on ./registry.ts). Re-exported from
|
|
53
|
+
* ./registry.ts unchanged for existing importers.
|
|
54
|
+
*/
|
|
55
|
+
export const STARTER_VERB_FAMILIES = {
|
|
56
|
+
build: ["docker-build", "zip-package", "jvm-build"],
|
|
57
|
+
// `extract-config-bom` parses a synthesized CloudFormation template, so it
|
|
58
|
+
// moved to the aws lexicon (#684) alongside the other AWS leaves; core's sbom
|
|
59
|
+
// family keeps only the agnostic, artifact-type-keyed `generate-sbom`.
|
|
60
|
+
sbom: ["generate-sbom"],
|
|
61
|
+
supplyChainSecurity: ["sign", "attest-provenance", "verify"],
|
|
62
|
+
supplyChainPolicy: ["scan-vulnerabilities", "vuln-gate"],
|
|
63
|
+
// Only the *agnostic* wait/verify verbs are in the starter set; the
|
|
64
|
+
// cloud-specific waits (`wait-for-stack`/`wait-steady-state`/`wait-job`) are
|
|
65
|
+
// contributed by the relevant lexicon (aws) — see docs/components/cloud-boundary.
|
|
66
|
+
waitVerify: ["wait-cluster-healthy", "wait-endpoint", "health-gate"],
|
|
67
|
+
escapeHatch: ["shell"],
|
|
68
|
+
} as const;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Every starter-set verb, in the same registration order Phase 1's
|
|
72
|
+
* `createCapabilityRegistry` used. Listed individually (not as a shared
|
|
73
|
+
* array literal) for the same reason Phase 1 registered them individually:
|
|
74
|
+
* each capability's own `In`/`Out` generics must be inferred from its own
|
|
75
|
+
* type, not widened to a lossy common supertype.
|
|
76
|
+
*/
|
|
77
|
+
function starterCapabilities(): Array<Capability<never, unknown>> {
|
|
78
|
+
return [
|
|
79
|
+
dockerBuildCapability,
|
|
80
|
+
zipPackageCapability,
|
|
81
|
+
jvmBuildCapability,
|
|
82
|
+
generateSbomCapability,
|
|
83
|
+
signCapability,
|
|
84
|
+
attestProvenanceCapability,
|
|
85
|
+
verifyCapability,
|
|
86
|
+
scanVulnerabilitiesCapability,
|
|
87
|
+
vulnGateCapability,
|
|
88
|
+
waitClusterHealthyCapability,
|
|
89
|
+
waitEndpointCapability,
|
|
90
|
+
healthGateCapability,
|
|
91
|
+
shellCapability,
|
|
92
|
+
] as unknown as Array<Capability<never, unknown>>;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* The built-in capability plugin carrying the entire Phase 1 starter verb
|
|
97
|
+
* set forward under the Phase 2 contract. Always loaded first by
|
|
98
|
+
* `buildCapabilityRegistry` (./capability-plugin-loader.ts).
|
|
99
|
+
*/
|
|
100
|
+
export const starterCapabilityPlugin: CapabilityPlugin = {
|
|
101
|
+
name: "starter",
|
|
102
|
+
version: "1.0.0",
|
|
103
|
+
capabilities: starterCapabilities,
|
|
104
|
+
families: () => STARTER_VERB_FAMILIES,
|
|
105
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dynamic loader for the durable component → Temporal codegen (#589, epic
|
|
3
|
+
* #551 §5/§8). The actual `serializeComponent` generator lives in
|
|
4
|
+
* `@intentius/chant-lexicon-temporal` (`src/component-op/serializer.ts`),
|
|
5
|
+
* mirroring `Temporal::Op` codegen — core never statically depends on the
|
|
6
|
+
* Temporal lexicon, the same boundary `../op/activity-registry.ts`'s
|
|
7
|
+
* `loadActivities`/`loadProfiles` already keep for Op activities.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { DriverComponent } from "./driver";
|
|
11
|
+
|
|
12
|
+
/** Target environment (and env-config) baked into the generated workflow at compile time — see `serializeComponent`'s docstring in the Temporal lexicon for why this can't be resolved at workflow-run time instead. */
|
|
13
|
+
export interface ComponentTemporalCodegenOptions {
|
|
14
|
+
env?: string;
|
|
15
|
+
vars?: Record<string, unknown>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface ComponentTemporalCodegen {
|
|
19
|
+
/** Serialize one component into `{ "components/<name>/workflow.ts": "...", ... }`. */
|
|
20
|
+
serializeComponent(component: DriverComponent, options?: ComponentTemporalCodegenOptions): Record<string, string>;
|
|
21
|
+
/** Deterministic workflow function name for a component (mirrors the generated `export async function <fn>()`). */
|
|
22
|
+
componentWorkflowFnName(componentName: string): string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Dynamically import the Temporal lexicon's component codegen. Throws a
|
|
27
|
+
* friendly error if the lexicon is not installed — the durable component
|
|
28
|
+
* path needs the generator even though discovery/local execution never do.
|
|
29
|
+
*/
|
|
30
|
+
export async function loadComponentTemporalCodegen(): Promise<ComponentTemporalCodegen> {
|
|
31
|
+
try {
|
|
32
|
+
// Variable specifier so tsc does not statically resolve the optional dep.
|
|
33
|
+
const spec = "@intentius/chant-lexicon-temporal/component-op/serializer";
|
|
34
|
+
return (await import(spec)) as unknown as ComponentTemporalCodegen;
|
|
35
|
+
} catch (err) {
|
|
36
|
+
throw new Error(
|
|
37
|
+
"no durable component codegen available — install `@intentius/chant-lexicon-temporal` " +
|
|
38
|
+
`to run components with --temporal (${err instanceof Error ? err.message : String(err)})`,
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
}
|