@shipfox/api-definitions 2.0.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/.turbo/turbo-build.log +2 -0
- package/.turbo/turbo-type$colon$emit.log +1 -0
- package/.turbo/turbo-type.log +1 -0
- package/CHANGELOG.md +215 -0
- package/LICENSE +21 -0
- package/dist/config.d.ts +10 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +35 -0
- package/dist/config.js.map +1 -0
- package/dist/core/entities/index.d.ts +5 -0
- package/dist/core/entities/index.d.ts.map +1 -0
- package/dist/core/entities/index.js +6 -0
- package/dist/core/entities/index.js.map +1 -0
- package/dist/core/entities/integration-context.d.ts +11 -0
- package/dist/core/entities/integration-context.d.ts.map +1 -0
- package/dist/core/entities/integration-context.js +3 -0
- package/dist/core/entities/integration-context.js.map +1 -0
- package/dist/core/entities/sync-state.d.ts +19 -0
- package/dist/core/entities/sync-state.d.ts.map +1 -0
- package/dist/core/entities/sync-state.js +20 -0
- package/dist/core/entities/sync-state.js.map +1 -0
- package/dist/core/entities/workflow-definition.d.ts +35 -0
- package/dist/core/entities/workflow-definition.d.ts.map +1 -0
- package/dist/core/entities/workflow-definition.js +3 -0
- package/dist/core/entities/workflow-definition.js.map +1 -0
- package/dist/core/entities/workflow-model.d.ts +138 -0
- package/dist/core/entities/workflow-model.d.ts.map +1 -0
- package/dist/core/entities/workflow-model.js +3 -0
- package/dist/core/entities/workflow-model.js.map +1 -0
- package/dist/core/errors.d.ts +10 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +14 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/has-agent-step-integrations.d.ts +3 -0
- package/dist/core/has-agent-step-integrations.d.ts.map +1 -0
- package/dist/core/has-agent-step-integrations.js +5 -0
- package/dist/core/has-agent-step-integrations.js.map +1 -0
- package/dist/core/index.d.ts +9 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +9 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/parse-definition.d.ts +9 -0
- package/dist/core/parse-definition.d.ts.map +1 -0
- package/dist/core/parse-definition.js +17 -0
- package/dist/core/parse-definition.js.map +1 -0
- package/dist/core/sync-definitions.d.ts +44 -0
- package/dist/core/sync-definitions.d.ts.map +1 -0
- package/dist/core/sync-definitions.js +140 -0
- package/dist/core/sync-definitions.js.map +1 -0
- package/dist/core/validate-definition.d.ts +20 -0
- package/dist/core/validate-definition.d.ts.map +1 -0
- package/dist/core/validate-definition.js +61 -0
- package/dist/core/validate-definition.js.map +1 -0
- package/dist/core/workflow-model/constants.d.ts +2 -0
- package/dist/core/workflow-model/constants.d.ts.map +1 -0
- package/dist/core/workflow-model/constants.js +3 -0
- package/dist/core/workflow-model/constants.js.map +1 -0
- package/dist/core/workflow-model/cron-trigger.d.ts +16 -0
- package/dist/core/workflow-model/cron-trigger.d.ts.map +1 -0
- package/dist/core/workflow-model/cron-trigger.js +85 -0
- package/dist/core/workflow-model/cron-trigger.js.map +1 -0
- package/dist/core/workflow-model/index.d.ts +4 -0
- package/dist/core/workflow-model/index.d.ts.map +1 -0
- package/dist/core/workflow-model/index.js +5 -0
- package/dist/core/workflow-model/index.js.map +1 -0
- package/dist/core/workflow-model/invalid-workflow-model-error.d.ts +15 -0
- package/dist/core/workflow-model/invalid-workflow-model-error.d.ts.map +1 -0
- package/dist/core/workflow-model/invalid-workflow-model-error.js +9 -0
- package/dist/core/workflow-model/invalid-workflow-model-error.js.map +1 -0
- package/dist/core/workflow-model/map-job-ids.d.ts +4 -0
- package/dist/core/workflow-model/map-job-ids.d.ts.map +1 -0
- package/dist/core/workflow-model/map-job-ids.js +33 -0
- package/dist/core/workflow-model/map-job-ids.js.map +1 -0
- package/dist/core/workflow-model/normalize-agent-integrations.d.ts +12 -0
- package/dist/core/workflow-model/normalize-agent-integrations.d.ts.map +1 -0
- package/dist/core/workflow-model/normalize-agent-integrations.js +157 -0
- package/dist/core/workflow-model/normalize-agent-integrations.js.map +1 -0
- package/dist/core/workflow-model/normalize-dependencies.d.ts +6 -0
- package/dist/core/workflow-model/normalize-dependencies.d.ts.map +1 -0
- package/dist/core/workflow-model/normalize-dependencies.js +119 -0
- package/dist/core/workflow-model/normalize-dependencies.js.map +1 -0
- package/dist/core/workflow-model/normalize-env.d.ts +17 -0
- package/dist/core/workflow-model/normalize-env.d.ts.map +1 -0
- package/dist/core/workflow-model/normalize-env.js +40 -0
- package/dist/core/workflow-model/normalize-env.js.map +1 -0
- package/dist/core/workflow-model/normalize-if-condition.d.ts +14 -0
- package/dist/core/workflow-model/normalize-if-condition.d.ts.map +1 -0
- package/dist/core/workflow-model/normalize-if-condition.js +75 -0
- package/dist/core/workflow-model/normalize-if-condition.js.map +1 -0
- package/dist/core/workflow-model/normalize-job-checkout.d.ts +5 -0
- package/dist/core/workflow-model/normalize-job-checkout.d.ts.map +1 -0
- package/dist/core/workflow-model/normalize-job-checkout.js +16 -0
- package/dist/core/workflow-model/normalize-job-checkout.js.map +1 -0
- package/dist/core/workflow-model/normalize-job-listening.d.ts +10 -0
- package/dist/core/workflow-model/normalize-job-listening.d.ts.map +1 -0
- package/dist/core/workflow-model/normalize-job-listening.js +125 -0
- package/dist/core/workflow-model/normalize-job-listening.js.map +1 -0
- package/dist/core/workflow-model/normalize-job-success.d.ts +11 -0
- package/dist/core/workflow-model/normalize-job-success.d.ts.map +1 -0
- package/dist/core/workflow-model/normalize-job-success.js +23 -0
- package/dist/core/workflow-model/normalize-job-success.js.map +1 -0
- package/dist/core/workflow-model/normalize-jobs.d.ts +12 -0
- package/dist/core/workflow-model/normalize-jobs.d.ts.map +1 -0
- package/dist/core/workflow-model/normalize-jobs.js +935 -0
- package/dist/core/workflow-model/normalize-jobs.js.map +1 -0
- package/dist/core/workflow-model/normalize-needs.d.ts +2 -0
- package/dist/core/workflow-model/normalize-needs.d.ts.map +1 -0
- package/dist/core/workflow-model/normalize-needs.js +16 -0
- package/dist/core/workflow-model/normalize-needs.js.map +1 -0
- package/dist/core/workflow-model/normalize-step-gate.d.ts +15 -0
- package/dist/core/workflow-model/normalize-step-gate.d.ts.map +1 -0
- package/dist/core/workflow-model/normalize-step-gate.js +89 -0
- package/dist/core/workflow-model/normalize-step-gate.js.map +1 -0
- package/dist/core/workflow-model/normalize-step-outputs.d.ts +10 -0
- package/dist/core/workflow-model/normalize-step-outputs.d.ts.map +1 -0
- package/dist/core/workflow-model/normalize-step-outputs.js +32 -0
- package/dist/core/workflow-model/normalize-step-outputs.js.map +1 -0
- package/dist/core/workflow-model/normalize-triggers.d.ts +11 -0
- package/dist/core/workflow-model/normalize-triggers.d.ts.map +1 -0
- package/dist/core/workflow-model/normalize-triggers.js +128 -0
- package/dist/core/workflow-model/normalize-triggers.js.map +1 -0
- package/dist/core/workflow-model/normalize-workflow-document.d.ts +11 -0
- package/dist/core/workflow-model/normalize-workflow-document.d.ts.map +1 -0
- package/dist/core/workflow-model/normalize-workflow-document.js +43 -0
- package/dist/core/workflow-model/normalize-workflow-document.js.map +1 -0
- package/dist/core/workflow-model/parse-duration-ms.d.ts +11 -0
- package/dist/core/workflow-model/parse-duration-ms.d.ts.map +1 -0
- package/dist/core/workflow-model/parse-duration-ms.js +47 -0
- package/dist/core/workflow-model/parse-duration-ms.js.map +1 -0
- package/dist/core/workflow-model/parse-interpolation-field.d.ts +14 -0
- package/dist/core/workflow-model/parse-interpolation-field.d.ts.map +1 -0
- package/dist/core/workflow-model/parse-interpolation-field.js +377 -0
- package/dist/core/workflow-model/parse-interpolation-field.js.map +1 -0
- package/dist/core/workflow-model/stable-id.d.ts +2 -0
- package/dist/core/workflow-model/stable-id.d.ts.map +1 -0
- package/dist/core/workflow-model/stable-id.js +8 -0
- package/dist/core/workflow-model/stable-id.js.map +1 -0
- package/dist/core/workflow-model/validate-job-references.d.ts +10 -0
- package/dist/core/workflow-model/validate-job-references.d.ts.map +1 -0
- package/dist/core/workflow-model/validate-job-references.js +42 -0
- package/dist/core/workflow-model/validate-job-references.js.map +1 -0
- package/dist/core/workflow-model/validate-predicate-expression.d.ts +14 -0
- package/dist/core/workflow-model/validate-predicate-expression.d.ts.map +1 -0
- package/dist/core/workflow-model/validate-predicate-expression.js +273 -0
- package/dist/core/workflow-model/validate-predicate-expression.js.map +1 -0
- package/dist/core/workflow-model/validation-issue.d.ts +8 -0
- package/dist/core/workflow-model/validation-issue.d.ts.map +1 -0
- package/dist/core/workflow-model/validation-issue.js +17 -0
- package/dist/core/workflow-model/validation-issue.js.map +1 -0
- package/dist/core/workflow-model/workflow-field-label.d.ts +3 -0
- package/dist/core/workflow-model/workflow-field-label.d.ts.map +1 -0
- package/dist/core/workflow-model/workflow-field-label.js +47 -0
- package/dist/core/workflow-model/workflow-field-label.js.map +1 -0
- package/dist/core/workflow-yaml/index.d.ts +3 -0
- package/dist/core/workflow-yaml/index.d.ts.map +1 -0
- package/dist/core/workflow-yaml/index.js +4 -0
- package/dist/core/workflow-yaml/index.js.map +1 -0
- package/dist/core/workflow-yaml/invalid-workflow-yaml-error.d.ts +16 -0
- package/dist/core/workflow-yaml/invalid-workflow-yaml-error.d.ts.map +1 -0
- package/dist/core/workflow-yaml/invalid-workflow-yaml-error.js +12 -0
- package/dist/core/workflow-yaml/invalid-workflow-yaml-error.js.map +1 -0
- package/dist/core/workflow-yaml/parse-workflow-yaml.d.ts +9 -0
- package/dist/core/workflow-yaml/parse-workflow-yaml.d.ts.map +1 -0
- package/dist/core/workflow-yaml/parse-workflow-yaml.js +52 -0
- package/dist/core/workflow-yaml/parse-workflow-yaml.js.map +1 -0
- package/dist/core/workflow-yaml/source-locations.d.ts +3 -0
- package/dist/core/workflow-yaml/source-locations.d.ts.map +1 -0
- package/dist/core/workflow-yaml/source-locations.js +48 -0
- package/dist/core/workflow-yaml/source-locations.js.map +1 -0
- package/dist/db/db.d.ts +1277 -0
- package/dist/db/db.d.ts.map +1 -0
- package/dist/db/db.js +22 -0
- package/dist/db/db.js.map +1 -0
- package/dist/db/definition-triggers.d.ts +4 -0
- package/dist/db/definition-triggers.d.ts.map +1 -0
- package/dist/db/definition-triggers.js +17 -0
- package/dist/db/definition-triggers.js.map +1 -0
- package/dist/db/definitions.d.ts +63 -0
- package/dist/db/definitions.d.ts.map +1 -0
- package/dist/db/definitions.js +208 -0
- package/dist/db/definitions.js.map +1 -0
- package/dist/db/index.d.ts +8 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +10 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/schema/common.d.ts +2 -0
- package/dist/db/schema/common.d.ts.map +1 -0
- package/dist/db/schema/common.js +4 -0
- package/dist/db/schema/common.js.map +1 -0
- package/dist/db/schema/definitions.d.ts +237 -0
- package/dist/db/schema/definitions.d.ts.map +1 -0
- package/dist/db/schema/definitions.js +63 -0
- package/dist/db/schema/definitions.js.map +1 -0
- package/dist/db/schema/outbox.d.ts +195 -0
- package/dist/db/schema/outbox.d.ts.map +1 -0
- package/dist/db/schema/outbox.js +5 -0
- package/dist/db/schema/outbox.js.map +1 -0
- package/dist/db/schema/sync-states.d.ts +218 -0
- package/dist/db/schema/sync-states.d.ts.map +1 -0
- package/dist/db/schema/sync-states.js +68 -0
- package/dist/db/schema/sync-states.js.map +1 -0
- package/dist/db/sync-states.d.ts +21 -0
- package/dist/db/sync-states.d.ts.map +1 -0
- package/dist/db/sync-states.js +47 -0
- package/dist/db/sync-states.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +63 -0
- package/dist/index.js.map +1 -0
- package/dist/presentation/dto/definition.d.ts +6 -0
- package/dist/presentation/dto/definition.d.ts.map +1 -0
- package/dist/presentation/dto/definition.js +35 -0
- package/dist/presentation/dto/definition.js.map +1 -0
- package/dist/presentation/dto/index.d.ts +2 -0
- package/dist/presentation/dto/index.d.ts.map +1 -0
- package/dist/presentation/dto/index.js +3 -0
- package/dist/presentation/dto/index.js.map +1 -0
- package/dist/presentation/index.d.ts +2 -0
- package/dist/presentation/index.d.ts.map +1 -0
- package/dist/presentation/index.js +3 -0
- package/dist/presentation/index.js.map +1 -0
- package/dist/presentation/routes/create-definition.d.ts +9 -0
- package/dist/presentation/routes/create-definition.d.ts.map +1 -0
- package/dist/presentation/routes/create-definition.js +76 -0
- package/dist/presentation/routes/create-definition.js.map +1 -0
- package/dist/presentation/routes/get-definition.d.ts +2 -0
- package/dist/presentation/routes/get-definition.d.ts.map +1 -0
- package/dist/presentation/routes/get-definition.js +43 -0
- package/dist/presentation/routes/get-definition.js.map +1 -0
- package/dist/presentation/routes/index.d.ts +7 -0
- package/dist/presentation/routes/index.d.ts.map +1 -0
- package/dist/presentation/routes/index.js +22 -0
- package/dist/presentation/routes/index.js.map +1 -0
- package/dist/presentation/routes/list-definitions.d.ts +2 -0
- package/dist/presentation/routes/list-definitions.d.ts.map +1 -0
- package/dist/presentation/routes/list-definitions.js +56 -0
- package/dist/presentation/routes/list-definitions.js.map +1 -0
- package/dist/presentation/routes/validate-definition.d.ts +2 -0
- package/dist/presentation/routes/validate-definition.d.ts.map +1 -0
- package/dist/presentation/routes/validate-definition.js +43 -0
- package/dist/presentation/routes/validate-definition.js.map +1 -0
- package/dist/presentation/subscribers/index.d.ts +3 -0
- package/dist/presentation/subscribers/index.d.ts.map +1 -0
- package/dist/presentation/subscribers/index.js +4 -0
- package/dist/presentation/subscribers/index.js.map +1 -0
- package/dist/presentation/subscribers/on-project-source-bound.d.ts +3 -0
- package/dist/presentation/subscribers/on-project-source-bound.d.ts.map +1 -0
- package/dist/presentation/subscribers/on-project-source-bound.js +11 -0
- package/dist/presentation/subscribers/on-project-source-bound.js.map +1 -0
- package/dist/presentation/subscribers/on-project-source-commit-observed.d.ts +3 -0
- package/dist/presentation/subscribers/on-project-source-commit-observed.d.ts.map +1 -0
- package/dist/presentation/subscribers/on-project-source-commit-observed.js +13 -0
- package/dist/presentation/subscribers/on-project-source-commit-observed.js.map +1 -0
- package/dist/presentation/subscribers/start-definition-sync.d.ts +10 -0
- package/dist/presentation/subscribers/start-definition-sync.d.ts.map +1 -0
- package/dist/presentation/subscribers/start-definition-sync.js +26 -0
- package/dist/presentation/subscribers/start-definition-sync.js.map +1 -0
- package/dist/temporal/activities/index.d.ts +3 -0
- package/dist/temporal/activities/index.d.ts.map +1 -0
- package/dist/temporal/activities/index.js +3 -0
- package/dist/temporal/activities/index.js.map +1 -0
- package/dist/temporal/activities/sync-activities.d.ts +47 -0
- package/dist/temporal/activities/sync-activities.d.ts.map +1 -0
- package/dist/temporal/activities/sync-activities.js +128 -0
- package/dist/temporal/activities/sync-activities.js.map +1 -0
- package/dist/temporal/constants.d.ts +3 -0
- package/dist/temporal/constants.d.ts.map +1 -0
- package/dist/temporal/constants.js +4 -0
- package/dist/temporal/constants.js.map +1 -0
- package/dist/temporal/index.d.ts +3 -0
- package/dist/temporal/index.d.ts.map +1 -0
- package/dist/temporal/index.js +4 -0
- package/dist/temporal/index.js.map +1 -0
- package/dist/temporal/workflows/definition-sync.d.ts +20 -0
- package/dist/temporal/workflows/definition-sync.d.ts.map +1 -0
- package/dist/temporal/workflows/definition-sync.js +95 -0
- package/dist/temporal/workflows/definition-sync.js.map +1 -0
- package/dist/temporal/workflows/index.d.ts +2 -0
- package/dist/temporal/workflows/index.d.ts.map +1 -0
- package/dist/temporal/workflows/index.js +3 -0
- package/dist/temporal/workflows/index.js.map +1 -0
- package/dist/tsconfig.test.tsbuildinfo +1 -0
- package/drizzle/0000_initial.sql +64 -0
- package/drizzle/0001_definition_list_pagination.sql +1 -0
- package/drizzle/meta/0000_snapshot.json +527 -0
- package/drizzle/meta/_journal.json +20 -0
- package/drizzle.config.ts +11 -0
- package/package.json +89 -0
- package/src/config.test.ts +23 -0
- package/src/config.ts +50 -0
- package/src/core/entities/index.ts +4 -0
- package/src/core/entities/integration-context.ts +21 -0
- package/src/core/entities/sync-state.ts +40 -0
- package/src/core/entities/workflow-definition.ts +38 -0
- package/src/core/entities/workflow-model.ts +162 -0
- package/src/core/errors.ts +21 -0
- package/src/core/has-agent-step-integrations.ts +7 -0
- package/src/core/index.ts +23 -0
- package/src/core/parse-definition.test.ts +200 -0
- package/src/core/parse-definition.ts +28 -0
- package/src/core/sync-definitions.test.ts +390 -0
- package/src/core/sync-definitions.ts +216 -0
- package/src/core/validate-definition.test.ts +152 -0
- package/src/core/validate-definition.ts +72 -0
- package/src/core/workflow-model/README.md +129 -0
- package/src/core/workflow-model/constants.ts +1 -0
- package/src/core/workflow-model/cron-trigger.test.ts +29 -0
- package/src/core/workflow-model/cron-trigger.ts +83 -0
- package/src/core/workflow-model/index.ts +9 -0
- package/src/core/workflow-model/invalid-workflow-model-error.ts +71 -0
- package/src/core/workflow-model/map-job-ids.ts +33 -0
- package/src/core/workflow-model/normalize-agent-integrations.ts +208 -0
- package/src/core/workflow-model/normalize-dependencies.ts +139 -0
- package/src/core/workflow-model/normalize-env.ts +48 -0
- package/src/core/workflow-model/normalize-if-condition.ts +126 -0
- package/src/core/workflow-model/normalize-job-checkout.ts +19 -0
- package/src/core/workflow-model/normalize-job-listening.ts +121 -0
- package/src/core/workflow-model/normalize-job-success.ts +28 -0
- package/src/core/workflow-model/normalize-jobs.ts +1010 -0
- package/src/core/workflow-model/normalize-needs.ts +12 -0
- package/src/core/workflow-model/normalize-step-gate.ts +90 -0
- package/src/core/workflow-model/normalize-step-outputs.ts +36 -0
- package/src/core/workflow-model/normalize-triggers.ts +130 -0
- package/src/core/workflow-model/normalize-workflow-document.test.ts +4463 -0
- package/src/core/workflow-model/normalize-workflow-document.ts +63 -0
- package/src/core/workflow-model/parse-duration-ms.ts +58 -0
- package/src/core/workflow-model/parse-interpolation-field.ts +566 -0
- package/src/core/workflow-model/stable-id.ts +12 -0
- package/src/core/workflow-model/validate-job-references.ts +54 -0
- package/src/core/workflow-model/validate-predicate-expression.test.ts +161 -0
- package/src/core/workflow-model/validate-predicate-expression.ts +406 -0
- package/src/core/workflow-model/validation-issue.ts +27 -0
- package/src/core/workflow-model/workflow-field-label.ts +50 -0
- package/src/core/workflow-yaml/README.md +77 -0
- package/src/core/workflow-yaml/index.ts +11 -0
- package/src/core/workflow-yaml/invalid-workflow-yaml-error.ts +23 -0
- package/src/core/workflow-yaml/parse-workflow-yaml.test.ts +71 -0
- package/src/core/workflow-yaml/parse-workflow-yaml.ts +74 -0
- package/src/core/workflow-yaml/source-locations.ts +62 -0
- package/src/db/db.ts +18 -0
- package/src/db/definition-triggers.test.ts +95 -0
- package/src/db/definition-triggers.ts +17 -0
- package/src/db/definitions.test.ts +1309 -0
- package/src/db/definitions.ts +357 -0
- package/src/db/index.ts +31 -0
- package/src/db/schema/common.ts +3 -0
- package/src/db/schema/definitions.test.ts +36 -0
- package/src/db/schema/definitions.ts +76 -0
- package/src/db/schema/outbox.ts +4 -0
- package/src/db/schema/sync-states.ts +79 -0
- package/src/db/sync-states.test.ts +90 -0
- package/src/db/sync-states.ts +86 -0
- package/src/index.ts +104 -0
- package/src/presentation/dto/definition.test.ts +59 -0
- package/src/presentation/dto/definition.ts +41 -0
- package/src/presentation/dto/index.ts +1 -0
- package/src/presentation/index.ts +1 -0
- package/src/presentation/routes/create-definition.test.ts +356 -0
- package/src/presentation/routes/create-definition.ts +101 -0
- package/src/presentation/routes/get-definition.test.ts +79 -0
- package/src/presentation/routes/get-definition.ts +37 -0
- package/src/presentation/routes/index.test.ts +41 -0
- package/src/presentation/routes/index.ts +28 -0
- package/src/presentation/routes/list-definitions.test.ts +195 -0
- package/src/presentation/routes/list-definitions.ts +49 -0
- package/src/presentation/routes/validate-definition.test.ts +63 -0
- package/src/presentation/routes/validate-definition.ts +46 -0
- package/src/presentation/subscribers/index.ts +2 -0
- package/src/presentation/subscribers/on-project-source-bound.test.ts +65 -0
- package/src/presentation/subscribers/on-project-source-bound.ts +11 -0
- package/src/presentation/subscribers/on-project-source-commit-observed.test.ts +56 -0
- package/src/presentation/subscribers/on-project-source-commit-observed.ts +15 -0
- package/src/presentation/subscribers/start-definition-sync.ts +38 -0
- package/src/temporal/activities/index.ts +10 -0
- package/src/temporal/activities/sync-activities.test.ts +337 -0
- package/src/temporal/activities/sync-activities.ts +206 -0
- package/src/temporal/constants.ts +2 -0
- package/src/temporal/index.ts +2 -0
- package/src/temporal/workflows/definition-sync.test.ts +59 -0
- package/src/temporal/workflows/definition-sync.ts +116 -0
- package/src/temporal/workflows/index.ts +1 -0
- package/test/env.ts +7 -0
- package/test/factories/definition.ts +66 -0
- package/test/fixtures/invalid-cycle.yml +13 -0
- package/test/fixtures/invalid-missing-name.yml +4 -0
- package/test/fixtures/invalid-yaml-syntax.yml +6 -0
- package/test/fixtures/valid-dag.yml +25 -0
- package/test/fixtures/valid-listening-job.yml +21 -0
- package/test/fixtures/valid-simple.yml +18 -0
- package/test/fixtures/workflow-yaml/invalid/invalid-yaml-syntax.yaml +6 -0
- package/test/fixtures/workflow-yaml/invalid/missing-step-run.yaml +5 -0
- package/test/fixtures/workflow-yaml/valid/simple-build.document.json +26 -0
- package/test/fixtures/workflow-yaml/valid/simple-build.yaml +14 -0
- package/test/globalSetup.ts +25 -0
- package/test/index.ts +1 -0
- package/test/setup.ts +17 -0
- package/tsconfig.build.json +9 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/tsconfig.json +3 -0
- package/tsconfig.test.json +8 -0
- package/vitest.config.ts +11 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const invalidWorkflowModelErrorCode = 'invalid-workflow-model';
|
|
2
|
+
export class InvalidWorkflowModelError extends Error {
|
|
3
|
+
constructor(issues){
|
|
4
|
+
super('Invalid workflow model'), this.issues = issues, this.code = invalidWorkflowModelErrorCode;
|
|
5
|
+
this.name = 'InvalidWorkflowModelError';
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
//# sourceMappingURL=invalid-workflow-model-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/core/workflow-model/invalid-workflow-model-error.ts"],"sourcesContent":["export const invalidWorkflowModelErrorCode = 'invalid-workflow-model';\n\nexport type WorkflowModelValidationIssueCode =\n | 'context-unavailable-at-fill-site'\n | 'context-unavailable-at-predicate-site'\n | 'computed-context-key'\n | 'duplicate-job-id'\n | 'duplicate-step-id'\n | 'duplicate-trigger-id'\n | 'harness-provider-incompatible'\n | 'harness-thinking-incompatible'\n | 'harness-tool-incompatible'\n | 'integration-connection-not-capable'\n | 'integration-connection-not-found'\n | 'integration-write-not-allowed'\n | 'invalid-cron-event'\n | 'invalid-cron-schedule'\n | 'invalid-cron-timezone'\n | 'invalid-provider'\n | 'invalid-trigger-filter'\n | 'invalid-interpolation-expression'\n | 'invalid-interpolation-template'\n | 'invalid-duration'\n | 'invalid-listener-filter'\n | 'invalid-job-if'\n | 'invalid-job-output'\n | 'invalid-job-success'\n | 'invalid-output-schema'\n | 'invalid-runner-label'\n | 'invalid-step-gate-restart-from'\n | 'invalid-step-gate-success'\n | 'invalid-step-if'\n | 'job-dependency-cycle'\n | 'listening-job-missing-resolution-source'\n | 'listening-timeout-exceeds-run-timeout'\n | 'missing-harness-for-tools'\n | 'missing-connection-for-integration'\n | 'missing-job-needs-edge'\n | 'missing-cron-schedule'\n | 'missing-runner-label'\n | 'multiple-manual-triggers'\n | 'runner-context-not-bare'\n | 'runner-context-in-field'\n | 'runner-context-in-server-predicate'\n | 'self-job-dependency'\n | 'too-many-runner-labels'\n | 'unknown-secret-store'\n | 'unknown-interpolation-context'\n | 'unknown-integration-method'\n | 'unknown-integration-tool'\n | 'unknown-job-dependency'\n | 'untrusted-context-in-field'\n | 'vars-context-in-server-predicate';\n\nexport type WorkflowModelValidationIssuePathSegment = string | number;\n\nexport interface WorkflowModelValidationIssue {\n readonly code: WorkflowModelValidationIssueCode;\n readonly message: string;\n readonly path: readonly WorkflowModelValidationIssuePathSegment[];\n readonly details?: Readonly<Record<string, unknown>>;\n}\n\nexport class InvalidWorkflowModelError extends Error {\n readonly code = invalidWorkflowModelErrorCode;\n\n constructor(readonly issues: readonly WorkflowModelValidationIssue[]) {\n super('Invalid workflow model');\n this.name = 'InvalidWorkflowModelError';\n }\n}\n"],"names":["invalidWorkflowModelErrorCode","InvalidWorkflowModelError","Error","issues","code","name"],"mappings":"AAAA,OAAO,MAAMA,gCAAgC,yBAAyB;AA+DtE,OAAO,MAAMC,kCAAkCC;IAG7C,YAAY,AAASC,MAA+C,CAAE;QACpE,KAAK,CAAC,gCADaA,SAAAA,aAFZC,OAAOJ;QAId,IAAI,CAACK,IAAI,GAAG;IACd;AACF"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { WorkflowDocument } from '@shipfox/workflow-document';
|
|
2
|
+
import type { WorkflowModelValidationIssue } from './invalid-workflow-model-error.js';
|
|
3
|
+
export declare function mapJobIds(document: WorkflowDocument, issues: WorkflowModelValidationIssue[]): ReadonlyMap<string, string>;
|
|
4
|
+
//# sourceMappingURL=map-job-ids.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"map-job-ids.d.ts","sourceRoot":"","sources":["../../../src/core/workflow-model/map-job-ids.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,4BAA4B,CAAC;AACjE,OAAO,KAAK,EAAC,4BAA4B,EAAC,MAAM,mCAAmC,CAAC;AAIpF,wBAAgB,SAAS,CACvB,QAAQ,EAAE,gBAAgB,EAC1B,MAAM,EAAE,4BAA4B,EAAE,GACrC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAwB7B"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { stableId } from './stable-id.js';
|
|
2
|
+
import { issue } from './validation-issue.js';
|
|
3
|
+
export function mapJobIds(document, issues) {
|
|
4
|
+
const jobIdBySourceName = new Map();
|
|
5
|
+
const usedJobIds = new Map();
|
|
6
|
+
for (const sourceKey of Object.keys(document.jobs)){
|
|
7
|
+
const id = stableId(sourceKey);
|
|
8
|
+
const existingSourceKey = usedJobIds.get(id);
|
|
9
|
+
if (existingSourceKey !== undefined) {
|
|
10
|
+
issues.push(issue({
|
|
11
|
+
code: 'duplicate-job-id',
|
|
12
|
+
message: `Job keys "${existingSourceKey}" and "${sourceKey}" resolve to the same stable id "${id}".`,
|
|
13
|
+
path: [
|
|
14
|
+
'jobs',
|
|
15
|
+
sourceKey
|
|
16
|
+
],
|
|
17
|
+
details: {
|
|
18
|
+
id,
|
|
19
|
+
sourceKeys: [
|
|
20
|
+
existingSourceKey,
|
|
21
|
+
sourceKey
|
|
22
|
+
]
|
|
23
|
+
}
|
|
24
|
+
}));
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
usedJobIds.set(id, sourceKey);
|
|
28
|
+
jobIdBySourceName.set(sourceKey, id);
|
|
29
|
+
}
|
|
30
|
+
return jobIdBySourceName;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
//# sourceMappingURL=map-job-ids.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/core/workflow-model/map-job-ids.ts"],"sourcesContent":["import type {WorkflowDocument} from '@shipfox/workflow-document';\nimport type {WorkflowModelValidationIssue} from './invalid-workflow-model-error.js';\nimport {stableId} from './stable-id.js';\nimport {issue} from './validation-issue.js';\n\nexport function mapJobIds(\n document: WorkflowDocument,\n issues: WorkflowModelValidationIssue[],\n): ReadonlyMap<string, string> {\n const jobIdBySourceName = new Map<string, string>();\n const usedJobIds = new Map<string, string>();\n\n for (const sourceKey of Object.keys(document.jobs)) {\n const id = stableId(sourceKey);\n const existingSourceKey = usedJobIds.get(id);\n if (existingSourceKey !== undefined) {\n issues.push(\n issue({\n code: 'duplicate-job-id',\n message: `Job keys \"${existingSourceKey}\" and \"${sourceKey}\" resolve to the same stable id \"${id}\".`,\n path: ['jobs', sourceKey],\n details: {id, sourceKeys: [existingSourceKey, sourceKey]},\n }),\n );\n continue;\n }\n\n usedJobIds.set(id, sourceKey);\n jobIdBySourceName.set(sourceKey, id);\n }\n\n return jobIdBySourceName;\n}\n"],"names":["stableId","issue","mapJobIds","document","issues","jobIdBySourceName","Map","usedJobIds","sourceKey","Object","keys","jobs","id","existingSourceKey","get","undefined","push","code","message","path","details","sourceKeys","set"],"mappings":"AAEA,SAAQA,QAAQ,QAAO,iBAAiB;AACxC,SAAQC,KAAK,QAAO,wBAAwB;AAE5C,OAAO,SAASC,UACdC,QAA0B,EAC1BC,MAAsC;IAEtC,MAAMC,oBAAoB,IAAIC;IAC9B,MAAMC,aAAa,IAAID;IAEvB,KAAK,MAAME,aAAaC,OAAOC,IAAI,CAACP,SAASQ,IAAI,EAAG;QAClD,MAAMC,KAAKZ,SAASQ;QACpB,MAAMK,oBAAoBN,WAAWO,GAAG,CAACF;QACzC,IAAIC,sBAAsBE,WAAW;YACnCX,OAAOY,IAAI,CACTf,MAAM;gBACJgB,MAAM;gBACNC,SAAS,CAAC,UAAU,EAAEL,kBAAkB,OAAO,EAAEL,UAAU,iCAAiC,EAAEI,GAAG,EAAE,CAAC;gBACpGO,MAAM;oBAAC;oBAAQX;iBAAU;gBACzBY,SAAS;oBAACR;oBAAIS,YAAY;wBAACR;wBAAmBL;qBAAU;gBAAA;YAC1D;YAEF;QACF;QAEAD,WAAWe,GAAG,CAACV,IAAIJ;QACnBH,kBAAkBiB,GAAG,CAACd,WAAWI;IACnC;IAEA,OAAOP;AACT"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { WorkflowDocumentStepIntegration } from '@shipfox/workflow-document';
|
|
2
|
+
import type { IntegrationValidationContext } from '../entities/integration-context.js';
|
|
3
|
+
import type { WorkflowModelStepIntegration } from '../entities/workflow-model.js';
|
|
4
|
+
import type { WorkflowModelValidationIssue } from './invalid-workflow-model-error.js';
|
|
5
|
+
export declare function normalizeAgentIntegrations(params: {
|
|
6
|
+
integrations: readonly WorkflowDocumentStepIntegration[] | undefined;
|
|
7
|
+
sourceName: string;
|
|
8
|
+
stepIndex: number;
|
|
9
|
+
issues: WorkflowModelValidationIssue[];
|
|
10
|
+
integrationValidationContext?: IntegrationValidationContext | undefined;
|
|
11
|
+
}): readonly WorkflowModelStepIntegration[] | undefined;
|
|
12
|
+
//# sourceMappingURL=normalize-agent-integrations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-agent-integrations.d.ts","sourceRoot":"","sources":["../../../src/core/workflow-model/normalize-agent-integrations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,+BAA+B,EAAC,MAAM,4BAA4B,CAAC;AAChF,OAAO,KAAK,EAAC,4BAA4B,EAAC,MAAM,oCAAoC,CAAC;AACrF,OAAO,KAAK,EAAC,4BAA4B,EAAC,MAAM,+BAA+B,CAAC;AAChF,OAAO,KAAK,EAAC,4BAA4B,EAAC,MAAM,mCAAmC,CAAC;AAGpF,wBAAgB,0BAA0B,CAAC,MAAM,EAAE;IACjD,YAAY,EAAE,SAAS,+BAA+B,EAAE,GAAG,SAAS,CAAC;IACrE,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,4BAA4B,EAAE,CAAC;IACvC,4BAA4B,CAAC,EAAE,4BAA4B,GAAG,SAAS,CAAC;CACzE,GAAG,SAAS,4BAA4B,EAAE,GAAG,SAAS,CAQtD"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { issue } from './validation-issue.js';
|
|
2
|
+
export function normalizeAgentIntegrations(params) {
|
|
3
|
+
if (params.integrations === undefined) return undefined;
|
|
4
|
+
return params.integrations.map((integration, integrationIndex)=>{
|
|
5
|
+
const normalized = normalizeIntegration(integration);
|
|
6
|
+
validateIntegration({
|
|
7
|
+
...params,
|
|
8
|
+
integration,
|
|
9
|
+
normalized,
|
|
10
|
+
integrationIndex
|
|
11
|
+
});
|
|
12
|
+
return normalized;
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
function normalizeIntegration(integration) {
|
|
16
|
+
return {
|
|
17
|
+
...integration.connection === undefined ? {} : {
|
|
18
|
+
connection: integration.connection
|
|
19
|
+
},
|
|
20
|
+
include: dedupe(integration.include),
|
|
21
|
+
...integration.exclude === undefined ? {} : {
|
|
22
|
+
exclude: dedupe(integration.exclude)
|
|
23
|
+
},
|
|
24
|
+
allowWrite: integration.allow_write ?? false
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function validateIntegration(params) {
|
|
28
|
+
const context = params.integrationValidationContext;
|
|
29
|
+
if (context === undefined) return;
|
|
30
|
+
const connectionSlug = params.normalized.connection ?? context.defaultConnectionSlug;
|
|
31
|
+
if (connectionSlug === undefined) {
|
|
32
|
+
params.issues.push(issue({
|
|
33
|
+
code: 'missing-connection-for-integration',
|
|
34
|
+
message: 'Agent step integration requires a connection or a default source connection.',
|
|
35
|
+
path: integrationPath(params),
|
|
36
|
+
details: {
|
|
37
|
+
integrationIndex: params.integrationIndex
|
|
38
|
+
}
|
|
39
|
+
}));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const connection = context.workspaceConnectionSnapshot.get(connectionSlug);
|
|
43
|
+
if (connection === undefined) {
|
|
44
|
+
params.issues.push(issue({
|
|
45
|
+
code: 'integration-connection-not-found',
|
|
46
|
+
message: `Integration connection "${connectionSlug}" was not found in the workspace.`,
|
|
47
|
+
path: integrationConnectionPath(params),
|
|
48
|
+
details: {
|
|
49
|
+
connection: connectionSlug,
|
|
50
|
+
integrationIndex: params.integrationIndex
|
|
51
|
+
}
|
|
52
|
+
}));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const catalog = context.agentToolSelectionCatalogs.get(connection.provider);
|
|
56
|
+
if (catalog === undefined || !connection.capabilities.includes('agent_tools')) {
|
|
57
|
+
params.issues.push(issue({
|
|
58
|
+
code: 'integration-connection-not-capable',
|
|
59
|
+
message: `Integration connection "${connectionSlug}" does not support agent tools.`,
|
|
60
|
+
path: integrationConnectionPath(params),
|
|
61
|
+
details: {
|
|
62
|
+
connection: connectionSlug,
|
|
63
|
+
provider: connection.provider,
|
|
64
|
+
capabilities: connection.capabilities,
|
|
65
|
+
integrationIndex: params.integrationIndex
|
|
66
|
+
}
|
|
67
|
+
}));
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const selectorsByToken = new Map(catalog.selectors.map((selector)=>[
|
|
71
|
+
selector.token,
|
|
72
|
+
selector
|
|
73
|
+
]));
|
|
74
|
+
validateSelection({
|
|
75
|
+
...params,
|
|
76
|
+
field: 'include',
|
|
77
|
+
tokens: params.integration.include,
|
|
78
|
+
selectorsByToken
|
|
79
|
+
});
|
|
80
|
+
if (params.integration.exclude !== undefined) {
|
|
81
|
+
validateSelection({
|
|
82
|
+
...params,
|
|
83
|
+
field: 'exclude',
|
|
84
|
+
tokens: params.integration.exclude,
|
|
85
|
+
selectorsByToken
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
validateWriteSelection({
|
|
89
|
+
...params,
|
|
90
|
+
selectorsByToken
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
function validateSelection(params) {
|
|
94
|
+
params.tokens.forEach((token, tokenIndex)=>{
|
|
95
|
+
if (params.selectorsByToken.has(token)) return;
|
|
96
|
+
const code = classifyUnknownSelection(token, params.selectorsByToken);
|
|
97
|
+
params.issues.push(issue({
|
|
98
|
+
code,
|
|
99
|
+
message: code === 'unknown-integration-method' ? `Unknown integration tool method: ${token}.` : `Unknown integration tool: ${token}.`,
|
|
100
|
+
path: [
|
|
101
|
+
...integrationPath(params),
|
|
102
|
+
params.field,
|
|
103
|
+
tokenIndex
|
|
104
|
+
],
|
|
105
|
+
details: {
|
|
106
|
+
token
|
|
107
|
+
}
|
|
108
|
+
}));
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
function validateWriteSelection(params) {
|
|
112
|
+
if (params.normalized.allowWrite) return;
|
|
113
|
+
const writeTokens = dedupe(params.integration.include.filter((token)=>params.selectorsByToken.get(token)?.sensitivity === 'write'));
|
|
114
|
+
if (writeTokens.length === 0) return;
|
|
115
|
+
params.issues.push(issue({
|
|
116
|
+
code: 'integration-write-not-allowed',
|
|
117
|
+
message: `Integration selection includes write-capable tools but allow_write is not true: ${writeTokens.join(', ')}.`,
|
|
118
|
+
path: [
|
|
119
|
+
...integrationPath(params),
|
|
120
|
+
'include'
|
|
121
|
+
],
|
|
122
|
+
details: {
|
|
123
|
+
tokens: writeTokens
|
|
124
|
+
}
|
|
125
|
+
}));
|
|
126
|
+
}
|
|
127
|
+
function classifyUnknownSelection(token, selectorsByToken) {
|
|
128
|
+
const dotIndex = token.indexOf('.');
|
|
129
|
+
if (dotIndex < 1) return 'unknown-integration-tool';
|
|
130
|
+
const family = token.slice(0, dotIndex);
|
|
131
|
+
return selectorsByToken.get(family)?.kind === 'family' ? 'unknown-integration-method' : 'unknown-integration-tool';
|
|
132
|
+
}
|
|
133
|
+
function integrationConnectionPath(params) {
|
|
134
|
+
const path = integrationPath(params);
|
|
135
|
+
if (params.integration.connection === undefined) return path;
|
|
136
|
+
return [
|
|
137
|
+
...path,
|
|
138
|
+
'connection'
|
|
139
|
+
];
|
|
140
|
+
}
|
|
141
|
+
function integrationPath(params) {
|
|
142
|
+
return [
|
|
143
|
+
'jobs',
|
|
144
|
+
params.sourceName,
|
|
145
|
+
'steps',
|
|
146
|
+
params.stepIndex,
|
|
147
|
+
'integrations',
|
|
148
|
+
params.integrationIndex
|
|
149
|
+
];
|
|
150
|
+
}
|
|
151
|
+
function dedupe(values) {
|
|
152
|
+
return [
|
|
153
|
+
...new Set(values)
|
|
154
|
+
];
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
//# sourceMappingURL=normalize-agent-integrations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/core/workflow-model/normalize-agent-integrations.ts"],"sourcesContent":["import type {AgentToolSelector} from '@shipfox/api-integration-core-dto';\nimport type {WorkflowDocumentStepIntegration} from '@shipfox/workflow-document';\nimport type {IntegrationValidationContext} from '../entities/integration-context.js';\nimport type {WorkflowModelStepIntegration} from '../entities/workflow-model.js';\nimport type {WorkflowModelValidationIssue} from './invalid-workflow-model-error.js';\nimport {issue} from './validation-issue.js';\n\nexport function normalizeAgentIntegrations(params: {\n integrations: readonly WorkflowDocumentStepIntegration[] | undefined;\n sourceName: string;\n stepIndex: number;\n issues: WorkflowModelValidationIssue[];\n integrationValidationContext?: IntegrationValidationContext | undefined;\n}): readonly WorkflowModelStepIntegration[] | undefined {\n if (params.integrations === undefined) return undefined;\n\n return params.integrations.map((integration, integrationIndex) => {\n const normalized = normalizeIntegration(integration);\n validateIntegration({...params, integration, normalized, integrationIndex});\n return normalized;\n });\n}\n\nfunction normalizeIntegration(\n integration: WorkflowDocumentStepIntegration,\n): WorkflowModelStepIntegration {\n return {\n ...(integration.connection === undefined ? {} : {connection: integration.connection}),\n include: dedupe(integration.include),\n ...(integration.exclude === undefined ? {} : {exclude: dedupe(integration.exclude)}),\n allowWrite: integration.allow_write ?? false,\n };\n}\n\nfunction validateIntegration(params: {\n integration: WorkflowDocumentStepIntegration;\n normalized: WorkflowModelStepIntegration;\n sourceName: string;\n stepIndex: number;\n integrationIndex: number;\n issues: WorkflowModelValidationIssue[];\n integrationValidationContext?: IntegrationValidationContext | undefined;\n}): void {\n const context = params.integrationValidationContext;\n if (context === undefined) return;\n\n const connectionSlug = params.normalized.connection ?? context.defaultConnectionSlug;\n if (connectionSlug === undefined) {\n params.issues.push(\n issue({\n code: 'missing-connection-for-integration',\n message: 'Agent step integration requires a connection or a default source connection.',\n path: integrationPath(params),\n details: {integrationIndex: params.integrationIndex},\n }),\n );\n return;\n }\n\n const connection = context.workspaceConnectionSnapshot.get(connectionSlug);\n if (connection === undefined) {\n params.issues.push(\n issue({\n code: 'integration-connection-not-found',\n message: `Integration connection \"${connectionSlug}\" was not found in the workspace.`,\n path: integrationConnectionPath(params),\n details: {\n connection: connectionSlug,\n integrationIndex: params.integrationIndex,\n },\n }),\n );\n return;\n }\n\n const catalog = context.agentToolSelectionCatalogs.get(connection.provider);\n if (catalog === undefined || !connection.capabilities.includes('agent_tools')) {\n params.issues.push(\n issue({\n code: 'integration-connection-not-capable',\n message: `Integration connection \"${connectionSlug}\" does not support agent tools.`,\n path: integrationConnectionPath(params),\n details: {\n connection: connectionSlug,\n provider: connection.provider,\n capabilities: connection.capabilities,\n integrationIndex: params.integrationIndex,\n },\n }),\n );\n return;\n }\n\n const selectorsByToken = new Map(catalog.selectors.map((selector) => [selector.token, selector]));\n validateSelection({\n ...params,\n field: 'include',\n tokens: params.integration.include,\n selectorsByToken,\n });\n if (params.integration.exclude !== undefined) {\n validateSelection({\n ...params,\n field: 'exclude',\n tokens: params.integration.exclude,\n selectorsByToken,\n });\n }\n validateWriteSelection({...params, selectorsByToken});\n}\n\nfunction validateSelection(params: {\n field: 'include' | 'exclude';\n tokens: readonly string[];\n selectorsByToken: ReadonlyMap<string, AgentToolSelector>;\n sourceName: string;\n stepIndex: number;\n integrationIndex: number;\n issues: WorkflowModelValidationIssue[];\n}): void {\n params.tokens.forEach((token, tokenIndex) => {\n if (params.selectorsByToken.has(token)) return;\n\n const code = classifyUnknownSelection(token, params.selectorsByToken);\n params.issues.push(\n issue({\n code,\n message:\n code === 'unknown-integration-method'\n ? `Unknown integration tool method: ${token}.`\n : `Unknown integration tool: ${token}.`,\n path: [...integrationPath(params), params.field, tokenIndex],\n details: {token},\n }),\n );\n });\n}\n\nfunction validateWriteSelection(params: {\n integration: WorkflowDocumentStepIntegration;\n normalized: WorkflowModelStepIntegration;\n selectorsByToken: ReadonlyMap<string, AgentToolSelector>;\n sourceName: string;\n stepIndex: number;\n integrationIndex: number;\n issues: WorkflowModelValidationIssue[];\n}): void {\n if (params.normalized.allowWrite) return;\n\n const writeTokens = dedupe(\n params.integration.include.filter(\n (token) => params.selectorsByToken.get(token)?.sensitivity === 'write',\n ),\n );\n if (writeTokens.length === 0) return;\n\n params.issues.push(\n issue({\n code: 'integration-write-not-allowed',\n message: `Integration selection includes write-capable tools but allow_write is not true: ${writeTokens.join(', ')}.`,\n path: [...integrationPath(params), 'include'],\n details: {tokens: writeTokens},\n }),\n );\n}\n\nfunction classifyUnknownSelection(\n token: string,\n selectorsByToken: ReadonlyMap<string, AgentToolSelector>,\n): 'unknown-integration-method' | 'unknown-integration-tool' {\n const dotIndex = token.indexOf('.');\n if (dotIndex < 1) return 'unknown-integration-tool';\n\n const family = token.slice(0, dotIndex);\n return selectorsByToken.get(family)?.kind === 'family'\n ? 'unknown-integration-method'\n : 'unknown-integration-tool';\n}\n\nfunction integrationConnectionPath(params: {\n sourceName: string;\n stepIndex: number;\n integrationIndex: number;\n integration: WorkflowDocumentStepIntegration;\n}): readonly (string | number)[] {\n const path = integrationPath(params);\n if (params.integration.connection === undefined) return path;\n return [...path, 'connection'];\n}\n\nfunction integrationPath(params: {\n sourceName: string;\n stepIndex: number;\n integrationIndex: number;\n}): readonly (string | number)[] {\n return [\n 'jobs',\n params.sourceName,\n 'steps',\n params.stepIndex,\n 'integrations',\n params.integrationIndex,\n ];\n}\n\nfunction dedupe(values: readonly string[]): readonly string[] {\n return [...new Set(values)];\n}\n"],"names":["issue","normalizeAgentIntegrations","params","integrations","undefined","map","integration","integrationIndex","normalized","normalizeIntegration","validateIntegration","connection","include","dedupe","exclude","allowWrite","allow_write","context","integrationValidationContext","connectionSlug","defaultConnectionSlug","issues","push","code","message","path","integrationPath","details","workspaceConnectionSnapshot","get","integrationConnectionPath","catalog","agentToolSelectionCatalogs","provider","capabilities","includes","selectorsByToken","Map","selectors","selector","token","validateSelection","field","tokens","validateWriteSelection","forEach","tokenIndex","has","classifyUnknownSelection","writeTokens","filter","sensitivity","length","join","dotIndex","indexOf","family","slice","kind","sourceName","stepIndex","values","Set"],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { WorkflowDocumentJob } from '@shipfox/workflow-document';
|
|
2
|
+
import type { WorkflowModelDependency } from '../entities/workflow-model.js';
|
|
3
|
+
import type { WorkflowModelValidationIssue } from './invalid-workflow-model-error.js';
|
|
4
|
+
export declare function normalizeDependencies(jobs: Readonly<Record<string, WorkflowDocumentJob>>, jobIdBySourceName: ReadonlyMap<string, string>, issues: WorkflowModelValidationIssue[]): readonly WorkflowModelDependency[];
|
|
5
|
+
export declare function validateCycles(jobs: Readonly<Record<string, WorkflowDocumentJob>>, jobIdBySourceName: ReadonlyMap<string, string>, issues: WorkflowModelValidationIssue[]): void;
|
|
6
|
+
//# sourceMappingURL=normalize-dependencies.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-dependencies.d.ts","sourceRoot":"","sources":["../../../src/core/workflow-model/normalize-dependencies.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,4BAA4B,CAAC;AACpE,OAAO,KAAK,EAAC,uBAAuB,EAAC,MAAM,+BAA+B,CAAC;AAC3E,OAAO,KAAK,EAAC,4BAA4B,EAAC,MAAM,mCAAmC,CAAC;AAIpF,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,EACnD,iBAAiB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9C,MAAM,EAAE,4BAA4B,EAAE,GACrC,SAAS,uBAAuB,EAAE,CAqCpC;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,EACnD,iBAAiB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9C,MAAM,EAAE,4BAA4B,EAAE,GACrC,IAAI,CAiCN"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { normalizeNeeds } from './normalize-needs.js';
|
|
2
|
+
import { issue } from './validation-issue.js';
|
|
3
|
+
export function normalizeDependencies(jobs, jobIdBySourceName, issues) {
|
|
4
|
+
const dependencies = [];
|
|
5
|
+
for (const [sourceName, job] of Object.entries(jobs)){
|
|
6
|
+
const to = jobIdBySourceName.get(sourceName);
|
|
7
|
+
if (to === undefined) continue;
|
|
8
|
+
for (const dependencySourceName of normalizeNeeds(job.needs)){
|
|
9
|
+
if (!jobIdBySourceName.has(dependencySourceName)) {
|
|
10
|
+
issues.push(issue({
|
|
11
|
+
code: 'unknown-job-dependency',
|
|
12
|
+
message: `Job "${sourceName}" depends on unknown job "${dependencySourceName}".`,
|
|
13
|
+
path: [
|
|
14
|
+
'jobs',
|
|
15
|
+
sourceName,
|
|
16
|
+
'needs'
|
|
17
|
+
],
|
|
18
|
+
details: {
|
|
19
|
+
job: sourceName,
|
|
20
|
+
dependency: dependencySourceName
|
|
21
|
+
}
|
|
22
|
+
}));
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (dependencySourceName === sourceName) {
|
|
26
|
+
issues.push(issue({
|
|
27
|
+
code: 'self-job-dependency',
|
|
28
|
+
message: `Job "${sourceName}" depends on itself.`,
|
|
29
|
+
path: [
|
|
30
|
+
'jobs',
|
|
31
|
+
sourceName,
|
|
32
|
+
'needs'
|
|
33
|
+
],
|
|
34
|
+
details: {
|
|
35
|
+
job: sourceName
|
|
36
|
+
}
|
|
37
|
+
}));
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
dependencies.push({
|
|
41
|
+
from: jobIdBySourceName.get(dependencySourceName),
|
|
42
|
+
to
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return dependencies;
|
|
47
|
+
}
|
|
48
|
+
export function validateCycles(jobs, jobIdBySourceName, issues) {
|
|
49
|
+
const jobNames = Object.keys(jobs);
|
|
50
|
+
const adjacency = new Map();
|
|
51
|
+
for (const name of jobNames){
|
|
52
|
+
adjacency.set(name, []);
|
|
53
|
+
}
|
|
54
|
+
for (const [name, job] of Object.entries(jobs)){
|
|
55
|
+
for (const dependency of normalizeNeeds(job.needs)){
|
|
56
|
+
if (!jobIdBySourceName.has(dependency) || dependency === name) continue;
|
|
57
|
+
adjacency.get(dependency)?.push(name);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const cyclicNames = findCyclicSourceNames(jobNames, adjacency);
|
|
61
|
+
if (cyclicNames.length > 0) {
|
|
62
|
+
issues.push(issue({
|
|
63
|
+
code: 'job-dependency-cycle',
|
|
64
|
+
message: `Circular dependency detected among jobs: ${cyclicNames.join(', ')}.`,
|
|
65
|
+
path: [
|
|
66
|
+
'jobs'
|
|
67
|
+
],
|
|
68
|
+
details: {
|
|
69
|
+
cycleSourceNames: cyclicNames,
|
|
70
|
+
cycleJobIds: cyclicNames.flatMap((name)=>{
|
|
71
|
+
const id = jobIdBySourceName.get(name);
|
|
72
|
+
return id === undefined ? [] : [
|
|
73
|
+
id
|
|
74
|
+
];
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function findCyclicSourceNames(jobNames, adjacency) {
|
|
81
|
+
const indexes = new Map();
|
|
82
|
+
const lowLinks = new Map();
|
|
83
|
+
const stack = [];
|
|
84
|
+
const onStack = new Set();
|
|
85
|
+
const cyclicNames = new Set();
|
|
86
|
+
let index = 0;
|
|
87
|
+
const visit = (node)=>{
|
|
88
|
+
indexes.set(node, index);
|
|
89
|
+
lowLinks.set(node, index);
|
|
90
|
+
index += 1;
|
|
91
|
+
stack.push(node);
|
|
92
|
+
onStack.add(node);
|
|
93
|
+
for (const neighbor of adjacency.get(node) ?? []){
|
|
94
|
+
if (!indexes.has(neighbor)) {
|
|
95
|
+
visit(neighbor);
|
|
96
|
+
lowLinks.set(node, Math.min(lowLinks.get(node), lowLinks.get(neighbor)));
|
|
97
|
+
} else if (onStack.has(neighbor)) {
|
|
98
|
+
lowLinks.set(node, Math.min(lowLinks.get(node), indexes.get(neighbor)));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (lowLinks.get(node) !== indexes.get(node)) return;
|
|
102
|
+
const component = [];
|
|
103
|
+
while(stack.length > 0){
|
|
104
|
+
const member = stack.pop();
|
|
105
|
+
onStack.delete(member);
|
|
106
|
+
component.push(member);
|
|
107
|
+
if (member === node) break;
|
|
108
|
+
}
|
|
109
|
+
if (component.length > 1) {
|
|
110
|
+
for (const member of component)cyclicNames.add(member);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
for (const name of jobNames){
|
|
114
|
+
if (!indexes.has(name)) visit(name);
|
|
115
|
+
}
|
|
116
|
+
return jobNames.filter((name)=>cyclicNames.has(name));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
//# sourceMappingURL=normalize-dependencies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/core/workflow-model/normalize-dependencies.ts"],"sourcesContent":["import type {WorkflowDocumentJob} from '@shipfox/workflow-document';\nimport type {WorkflowModelDependency} from '../entities/workflow-model.js';\nimport type {WorkflowModelValidationIssue} from './invalid-workflow-model-error.js';\nimport {normalizeNeeds} from './normalize-needs.js';\nimport {issue} from './validation-issue.js';\n\nexport function normalizeDependencies(\n jobs: Readonly<Record<string, WorkflowDocumentJob>>,\n jobIdBySourceName: ReadonlyMap<string, string>,\n issues: WorkflowModelValidationIssue[],\n): readonly WorkflowModelDependency[] {\n const dependencies: WorkflowModelDependency[] = [];\n\n for (const [sourceName, job] of Object.entries(jobs)) {\n const to = jobIdBySourceName.get(sourceName);\n if (to === undefined) continue;\n\n for (const dependencySourceName of normalizeNeeds(job.needs)) {\n if (!jobIdBySourceName.has(dependencySourceName)) {\n issues.push(\n issue({\n code: 'unknown-job-dependency',\n message: `Job \"${sourceName}\" depends on unknown job \"${dependencySourceName}\".`,\n path: ['jobs', sourceName, 'needs'],\n details: {job: sourceName, dependency: dependencySourceName},\n }),\n );\n continue;\n }\n\n if (dependencySourceName === sourceName) {\n issues.push(\n issue({\n code: 'self-job-dependency',\n message: `Job \"${sourceName}\" depends on itself.`,\n path: ['jobs', sourceName, 'needs'],\n details: {job: sourceName},\n }),\n );\n continue;\n }\n\n dependencies.push({from: jobIdBySourceName.get(dependencySourceName) as string, to});\n }\n }\n\n return dependencies;\n}\n\nexport function validateCycles(\n jobs: Readonly<Record<string, WorkflowDocumentJob>>,\n jobIdBySourceName: ReadonlyMap<string, string>,\n issues: WorkflowModelValidationIssue[],\n): void {\n const jobNames = Object.keys(jobs);\n const adjacency = new Map<string, string[]>();\n\n for (const name of jobNames) {\n adjacency.set(name, []);\n }\n\n for (const [name, job] of Object.entries(jobs)) {\n for (const dependency of normalizeNeeds(job.needs)) {\n if (!jobIdBySourceName.has(dependency) || dependency === name) continue;\n\n adjacency.get(dependency)?.push(name);\n }\n }\n\n const cyclicNames = findCyclicSourceNames(jobNames, adjacency);\n if (cyclicNames.length > 0) {\n issues.push(\n issue({\n code: 'job-dependency-cycle',\n message: `Circular dependency detected among jobs: ${cyclicNames.join(', ')}.`,\n path: ['jobs'],\n details: {\n cycleSourceNames: cyclicNames,\n cycleJobIds: cyclicNames.flatMap((name) => {\n const id = jobIdBySourceName.get(name);\n return id === undefined ? [] : [id];\n }),\n },\n }),\n );\n }\n}\n\nfunction findCyclicSourceNames(\n jobNames: readonly string[],\n adjacency: ReadonlyMap<string, readonly string[]>,\n): readonly string[] {\n const indexes = new Map<string, number>();\n const lowLinks = new Map<string, number>();\n const stack: string[] = [];\n const onStack = new Set<string>();\n const cyclicNames = new Set<string>();\n let index = 0;\n\n const visit = (node: string) => {\n indexes.set(node, index);\n lowLinks.set(node, index);\n index += 1;\n stack.push(node);\n onStack.add(node);\n\n for (const neighbor of adjacency.get(node) ?? []) {\n if (!indexes.has(neighbor)) {\n visit(neighbor);\n lowLinks.set(\n node,\n Math.min(lowLinks.get(node) as number, lowLinks.get(neighbor) as number),\n );\n } else if (onStack.has(neighbor)) {\n lowLinks.set(node, Math.min(lowLinks.get(node) as number, indexes.get(neighbor) as number));\n }\n }\n\n if (lowLinks.get(node) !== indexes.get(node)) return;\n\n const component: string[] = [];\n while (stack.length > 0) {\n const member = stack.pop() as string;\n onStack.delete(member);\n component.push(member);\n if (member === node) break;\n }\n\n if (component.length > 1) {\n for (const member of component) cyclicNames.add(member);\n }\n };\n\n for (const name of jobNames) {\n if (!indexes.has(name)) visit(name);\n }\n\n return jobNames.filter((name) => cyclicNames.has(name));\n}\n"],"names":["normalizeNeeds","issue","normalizeDependencies","jobs","jobIdBySourceName","issues","dependencies","sourceName","job","Object","entries","to","get","undefined","dependencySourceName","needs","has","push","code","message","path","details","dependency","from","validateCycles","jobNames","keys","adjacency","Map","name","set","cyclicNames","findCyclicSourceNames","length","join","cycleSourceNames","cycleJobIds","flatMap","id","indexes","lowLinks","stack","onStack","Set","index","visit","node","add","neighbor","Math","min","component","member","pop","delete","filter"],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { AvailabilitySite, ExpressionTypeEnvironment } from '@shipfox/expression';
|
|
2
|
+
import type { WorkflowEnvTemplates } from '../entities/workflow-model.js';
|
|
3
|
+
import type { WorkflowModelValidationIssue, WorkflowModelValidationIssuePathSegment } from './invalid-workflow-model-error.js';
|
|
4
|
+
export declare function normalizeEnv(params: {
|
|
5
|
+
env: Readonly<Record<string, string | number | boolean>> | undefined;
|
|
6
|
+
path: readonly WorkflowModelValidationIssuePathSegment[];
|
|
7
|
+
issues: WorkflowModelValidationIssue[];
|
|
8
|
+
fillSite?: AvailabilitySite;
|
|
9
|
+
allowedJobReferences?: ReadonlySet<string>;
|
|
10
|
+
typeOverlay?: ExpressionTypeEnvironment | undefined;
|
|
11
|
+
}): {
|
|
12
|
+
env?: Readonly<Record<string, string>>;
|
|
13
|
+
templates?: {
|
|
14
|
+
env: WorkflowEnvTemplates;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=normalize-env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-env.d.ts","sourceRoot":"","sources":["../../../src/core/workflow-model/normalize-env.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,gBAAgB,EAAE,yBAAyB,EAAC,MAAM,qBAAqB,CAAC;AACrF,OAAO,KAAK,EAAC,oBAAoB,EAAwB,MAAM,+BAA+B,CAAC;AAC/F,OAAO,KAAK,EACV,4BAA4B,EAC5B,uCAAuC,EACxC,MAAM,mCAAmC,CAAC;AAG3C,wBAAgB,YAAY,CAAC,MAAM,EAAE;IACnC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IACrE,IAAI,EAAE,SAAS,uCAAuC,EAAE,CAAC;IACzD,MAAM,EAAE,4BAA4B,EAAE,CAAC;IACvC,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,oBAAoB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3C,WAAW,CAAC,EAAE,yBAAyB,GAAG,SAAS,CAAC;CACrD,GAAG;IAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAAC,SAAS,CAAC,EAAE;QAAC,GAAG,EAAE,oBAAoB,CAAA;KAAC,CAAA;CAAC,CAgCpF"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { parseInterpolationField } from './parse-interpolation-field.js';
|
|
2
|
+
export function normalizeEnv(params) {
|
|
3
|
+
const env = params.env;
|
|
4
|
+
if (env === undefined || Object.keys(env).length === 0) return {};
|
|
5
|
+
const normalizedEnv = Object.create(null);
|
|
6
|
+
const templates = Object.create(null);
|
|
7
|
+
for (const [key, value] of Object.entries(env)){
|
|
8
|
+
normalizedEnv[key] = String(value);
|
|
9
|
+
if (typeof value !== 'string') continue;
|
|
10
|
+
const template = parseInterpolationField({
|
|
11
|
+
field: 'env.value',
|
|
12
|
+
source: value,
|
|
13
|
+
path: [
|
|
14
|
+
...params.path,
|
|
15
|
+
key
|
|
16
|
+
],
|
|
17
|
+
issues: params.issues,
|
|
18
|
+
...params.fillSite === undefined ? {} : {
|
|
19
|
+
fillSite: params.fillSite
|
|
20
|
+
},
|
|
21
|
+
...params.allowedJobReferences === undefined ? {} : {
|
|
22
|
+
allowedJobReferences: params.allowedJobReferences
|
|
23
|
+
},
|
|
24
|
+
...params.typeOverlay === undefined ? {} : {
|
|
25
|
+
typeOverlay: params.typeOverlay
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
if (template !== undefined) templates[key] = template;
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
env: normalizedEnv,
|
|
32
|
+
...Object.keys(templates).length === 0 ? {} : {
|
|
33
|
+
templates: {
|
|
34
|
+
env: templates
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
//# sourceMappingURL=normalize-env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/core/workflow-model/normalize-env.ts"],"sourcesContent":["import type {AvailabilitySite, ExpressionTypeEnvironment} from '@shipfox/expression';\nimport type {WorkflowEnvTemplates, WorkflowFieldTemplate} from '../entities/workflow-model.js';\nimport type {\n WorkflowModelValidationIssue,\n WorkflowModelValidationIssuePathSegment,\n} from './invalid-workflow-model-error.js';\nimport {parseInterpolationField} from './parse-interpolation-field.js';\n\nexport function normalizeEnv(params: {\n env: Readonly<Record<string, string | number | boolean>> | undefined;\n path: readonly WorkflowModelValidationIssuePathSegment[];\n issues: WorkflowModelValidationIssue[];\n fillSite?: AvailabilitySite;\n allowedJobReferences?: ReadonlySet<string>;\n typeOverlay?: ExpressionTypeEnvironment | undefined;\n}): {env?: Readonly<Record<string, string>>; templates?: {env: WorkflowEnvTemplates}} {\n const env = params.env;\n if (env === undefined || Object.keys(env).length === 0) return {};\n\n const normalizedEnv: Record<string, string> = Object.create(null) as Record<string, string>;\n const templates: Record<string, WorkflowFieldTemplate> = Object.create(null) as Record<\n string,\n WorkflowFieldTemplate\n >;\n\n for (const [key, value] of Object.entries(env)) {\n normalizedEnv[key] = String(value);\n if (typeof value !== 'string') continue;\n\n const template = parseInterpolationField({\n field: 'env.value',\n source: value,\n path: [...params.path, key],\n issues: params.issues,\n ...(params.fillSite === undefined ? {} : {fillSite: params.fillSite}),\n ...(params.allowedJobReferences === undefined\n ? {}\n : {allowedJobReferences: params.allowedJobReferences}),\n ...(params.typeOverlay === undefined ? {} : {typeOverlay: params.typeOverlay}),\n });\n if (template !== undefined) templates[key] = template;\n }\n\n return {\n env: normalizedEnv,\n ...(Object.keys(templates).length === 0 ? {} : {templates: {env: templates}}),\n };\n}\n"],"names":["parseInterpolationField","normalizeEnv","params","env","undefined","Object","keys","length","normalizedEnv","create","templates","key","value","entries","String","template","field","source","path","issues","fillSite","allowedJobReferences","typeOverlay"],"mappings":"AAMA,SAAQA,uBAAuB,QAAO,iCAAiC;AAEvE,OAAO,SAASC,aAAaC,MAO5B;IACC,MAAMC,MAAMD,OAAOC,GAAG;IACtB,IAAIA,QAAQC,aAAaC,OAAOC,IAAI,CAACH,KAAKI,MAAM,KAAK,GAAG,OAAO,CAAC;IAEhE,MAAMC,gBAAwCH,OAAOI,MAAM,CAAC;IAC5D,MAAMC,YAAmDL,OAAOI,MAAM,CAAC;IAKvE,KAAK,MAAM,CAACE,KAAKC,MAAM,IAAIP,OAAOQ,OAAO,CAACV,KAAM;QAC9CK,aAAa,CAACG,IAAI,GAAGG,OAAOF;QAC5B,IAAI,OAAOA,UAAU,UAAU;QAE/B,MAAMG,WAAWf,wBAAwB;YACvCgB,OAAO;YACPC,QAAQL;YACRM,MAAM;mBAAIhB,OAAOgB,IAAI;gBAAEP;aAAI;YAC3BQ,QAAQjB,OAAOiB,MAAM;YACrB,GAAIjB,OAAOkB,QAAQ,KAAKhB,YAAY,CAAC,IAAI;gBAACgB,UAAUlB,OAAOkB,QAAQ;YAAA,CAAC;YACpE,GAAIlB,OAAOmB,oBAAoB,KAAKjB,YAChC,CAAC,IACD;gBAACiB,sBAAsBnB,OAAOmB,oBAAoB;YAAA,CAAC;YACvD,GAAInB,OAAOoB,WAAW,KAAKlB,YAAY,CAAC,IAAI;gBAACkB,aAAapB,OAAOoB,WAAW;YAAA,CAAC;QAC/E;QACA,IAAIP,aAAaX,WAAWM,SAAS,CAACC,IAAI,GAAGI;IAC/C;IAEA,OAAO;QACLZ,KAAKK;QACL,GAAIH,OAAOC,IAAI,CAACI,WAAWH,MAAM,KAAK,IAAI,CAAC,IAAI;YAACG,WAAW;gBAACP,KAAKO;YAAS;QAAC,CAAC;IAC9E;AACF"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ExpressionTypeEnvironment, type WorkflowExpression, type WorkflowPredicateField } from '@shipfox/expression';
|
|
2
|
+
import type { WorkflowModelValidationIssue, WorkflowModelValidationIssueCode, WorkflowModelValidationIssuePathSegment } from './invalid-workflow-model-error.js';
|
|
3
|
+
export declare function normalizeIfCondition(params: {
|
|
4
|
+
readonly field: Extract<WorkflowPredicateField, 'job.if' | 'step.if'>;
|
|
5
|
+
readonly source: string | undefined;
|
|
6
|
+
readonly site: 'job-activation' | 'step-dispatch';
|
|
7
|
+
readonly path: readonly WorkflowModelValidationIssuePathSegment[];
|
|
8
|
+
readonly invalidCode: Extract<WorkflowModelValidationIssueCode, 'invalid-job-if' | 'invalid-step-if'>;
|
|
9
|
+
readonly invalidMessage: string;
|
|
10
|
+
readonly issues: WorkflowModelValidationIssue[];
|
|
11
|
+
readonly allowedJobReferences: ReadonlySet<string>;
|
|
12
|
+
readonly typeOverlay: ExpressionTypeEnvironment;
|
|
13
|
+
}): WorkflowExpression | undefined;
|
|
14
|
+
//# sourceMappingURL=normalize-if-condition.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-if-condition.d.ts","sourceRoot":"","sources":["../../../src/core/workflow-model/normalize-if-condition.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,yBAAyB,EAI9B,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAE5B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EACV,4BAA4B,EAC5B,gCAAgC,EAChC,uCAAuC,EACxC,MAAM,mCAAmC,CAAC;AAO3C,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAC3C,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,sBAAsB,EAAE,QAAQ,GAAG,SAAS,CAAC,CAAC;IACtE,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,GAAG,eAAe,CAAC;IAClD,QAAQ,CAAC,IAAI,EAAE,SAAS,uCAAuC,EAAE,CAAC;IAClE,QAAQ,CAAC,WAAW,EAAE,OAAO,CAC3B,gCAAgC,EAChC,gBAAgB,GAAG,iBAAiB,CACrC,CAAC;IACF,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,4BAA4B,EAAE,CAAC;IAChD,QAAQ,CAAC,oBAAoB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACnD,QAAQ,CAAC,WAAW,EAAE,yBAAyB,CAAC;CACjD,GAAG,kBAAkB,GAAG,SAAS,CAoCjC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { extractExactContextRoots, InvalidWorkflowTemplateError, parseWorkflowTemplate } from '@shipfox/expression';
|
|
2
|
+
import { validatePredicateExpression } from './validate-predicate-expression.js';
|
|
3
|
+
import { issue } from './validation-issue.js';
|
|
4
|
+
import { workflowFieldLabel } from './workflow-field-label.js';
|
|
5
|
+
const ifExpressionSyntax = `\${{ }}`;
|
|
6
|
+
export function normalizeIfCondition(params) {
|
|
7
|
+
if (params.source === undefined) return undefined;
|
|
8
|
+
const source = params.source;
|
|
9
|
+
const expressionSegment = parseSingleExpression({
|
|
10
|
+
...params,
|
|
11
|
+
source
|
|
12
|
+
});
|
|
13
|
+
if (expressionSegment === undefined) return undefined;
|
|
14
|
+
const roots = extractExactContextRoots(expressionSegment.expression.source);
|
|
15
|
+
if (roots.includes('needs') && params.allowedJobReferences.size === 0) {
|
|
16
|
+
params.issues.push(issue({
|
|
17
|
+
code: params.invalidCode,
|
|
18
|
+
message: `${workflowFieldLabel(params.field)} cannot reference needs because the job has no direct needs.`,
|
|
19
|
+
path: params.path,
|
|
20
|
+
details: {
|
|
21
|
+
field: params.field,
|
|
22
|
+
source: params.source,
|
|
23
|
+
contextRoots: roots,
|
|
24
|
+
rejectedRoots: [
|
|
25
|
+
'needs'
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
}));
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
return validatePredicateExpression({
|
|
32
|
+
field: params.field,
|
|
33
|
+
source: expressionSegment.expression.source,
|
|
34
|
+
site: params.site,
|
|
35
|
+
path: params.path,
|
|
36
|
+
invalidCode: params.invalidCode,
|
|
37
|
+
invalidMessage: params.invalidMessage,
|
|
38
|
+
issues: params.issues,
|
|
39
|
+
allowedJobReferences: params.allowedJobReferences,
|
|
40
|
+
typeOverlay: params.typeOverlay
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
function parseSingleExpression(params) {
|
|
44
|
+
let segments;
|
|
45
|
+
try {
|
|
46
|
+
segments = parseWorkflowTemplate(params.source);
|
|
47
|
+
} catch (error) {
|
|
48
|
+
params.issues.push(invalidIfIssue({
|
|
49
|
+
...params,
|
|
50
|
+
reason: error instanceof InvalidWorkflowTemplateError ? error.reason : 'Template source did not parse.'
|
|
51
|
+
}));
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
const [segment] = segments;
|
|
55
|
+
if (segment?.kind === 'expr' && segments.length === 1) return segment;
|
|
56
|
+
params.issues.push(invalidIfIssue({
|
|
57
|
+
...params,
|
|
58
|
+
reason: `${workflowFieldLabel(params.field)} must be exactly one ${ifExpressionSyntax} expression.`
|
|
59
|
+
}));
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
function invalidIfIssue(params) {
|
|
63
|
+
return issue({
|
|
64
|
+
code: params.invalidCode,
|
|
65
|
+
message: params.invalidMessage,
|
|
66
|
+
path: params.path,
|
|
67
|
+
details: {
|
|
68
|
+
field: params.field,
|
|
69
|
+
source: params.source,
|
|
70
|
+
reason: params.reason
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
//# sourceMappingURL=normalize-if-condition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/core/workflow-model/normalize-if-condition.ts"],"sourcesContent":["import {\n type ExpressionTypeEnvironment,\n extractExactContextRoots,\n InvalidWorkflowTemplateError,\n parseWorkflowTemplate,\n type WorkflowExpression,\n type WorkflowPredicateField,\n type WorkflowTemplateExprSegment,\n} from '@shipfox/expression';\nimport type {\n WorkflowModelValidationIssue,\n WorkflowModelValidationIssueCode,\n WorkflowModelValidationIssuePathSegment,\n} from './invalid-workflow-model-error.js';\nimport {validatePredicateExpression} from './validate-predicate-expression.js';\nimport {issue} from './validation-issue.js';\nimport {workflowFieldLabel} from './workflow-field-label.js';\n\nconst ifExpressionSyntax = `\\${{ }}`;\n\nexport function normalizeIfCondition(params: {\n readonly field: Extract<WorkflowPredicateField, 'job.if' | 'step.if'>;\n readonly source: string | undefined;\n readonly site: 'job-activation' | 'step-dispatch';\n readonly path: readonly WorkflowModelValidationIssuePathSegment[];\n readonly invalidCode: Extract<\n WorkflowModelValidationIssueCode,\n 'invalid-job-if' | 'invalid-step-if'\n >;\n readonly invalidMessage: string;\n readonly issues: WorkflowModelValidationIssue[];\n readonly allowedJobReferences: ReadonlySet<string>;\n readonly typeOverlay: ExpressionTypeEnvironment;\n}): WorkflowExpression | undefined {\n if (params.source === undefined) return undefined;\n const source = params.source;\n\n const expressionSegment = parseSingleExpression({...params, source});\n if (expressionSegment === undefined) return undefined;\n\n const roots = extractExactContextRoots(expressionSegment.expression.source);\n if (roots.includes('needs') && params.allowedJobReferences.size === 0) {\n params.issues.push(\n issue({\n code: params.invalidCode,\n message: `${workflowFieldLabel(params.field)} cannot reference needs because the job has no direct needs.`,\n path: params.path,\n details: {\n field: params.field,\n source: params.source,\n contextRoots: roots,\n rejectedRoots: ['needs'],\n },\n }),\n );\n return undefined;\n }\n\n return validatePredicateExpression({\n field: params.field,\n source: expressionSegment.expression.source,\n site: params.site,\n path: params.path,\n invalidCode: params.invalidCode,\n invalidMessage: params.invalidMessage,\n issues: params.issues,\n allowedJobReferences: params.allowedJobReferences,\n typeOverlay: params.typeOverlay,\n });\n}\n\nfunction parseSingleExpression(params: {\n readonly field: WorkflowPredicateField;\n readonly source: string;\n readonly path: readonly WorkflowModelValidationIssuePathSegment[];\n readonly invalidCode: WorkflowModelValidationIssueCode;\n readonly invalidMessage: string;\n readonly issues: WorkflowModelValidationIssue[];\n}): WorkflowTemplateExprSegment | undefined {\n let segments: ReturnType<typeof parseWorkflowTemplate>;\n try {\n segments = parseWorkflowTemplate(params.source);\n } catch (error) {\n params.issues.push(\n invalidIfIssue({\n ...params,\n reason:\n error instanceof InvalidWorkflowTemplateError\n ? error.reason\n : 'Template source did not parse.',\n }),\n );\n return undefined;\n }\n\n const [segment] = segments;\n if (segment?.kind === 'expr' && segments.length === 1) return segment;\n\n params.issues.push(\n invalidIfIssue({\n ...params,\n reason: `${workflowFieldLabel(params.field)} must be exactly one ${ifExpressionSyntax} expression.`,\n }),\n );\n return undefined;\n}\n\nfunction invalidIfIssue(params: {\n readonly field: WorkflowPredicateField;\n readonly source: string;\n readonly path: readonly WorkflowModelValidationIssuePathSegment[];\n readonly invalidCode: WorkflowModelValidationIssueCode;\n readonly invalidMessage: string;\n readonly reason: string;\n}): WorkflowModelValidationIssue {\n return issue({\n code: params.invalidCode,\n message: params.invalidMessage,\n path: params.path,\n details: {\n field: params.field,\n source: params.source,\n reason: params.reason,\n },\n });\n}\n"],"names":["extractExactContextRoots","InvalidWorkflowTemplateError","parseWorkflowTemplate","validatePredicateExpression","issue","workflowFieldLabel","ifExpressionSyntax","normalizeIfCondition","params","source","undefined","expressionSegment","parseSingleExpression","roots","expression","includes","allowedJobReferences","size","issues","push","code","invalidCode","message","field","path","details","contextRoots","rejectedRoots","site","invalidMessage","typeOverlay","segments","error","invalidIfIssue","reason","segment","kind","length"],"mappings":"AAAA,SAEEA,wBAAwB,EACxBC,4BAA4B,EAC5BC,qBAAqB,QAIhB,sBAAsB;AAM7B,SAAQC,2BAA2B,QAAO,qCAAqC;AAC/E,SAAQC,KAAK,QAAO,wBAAwB;AAC5C,SAAQC,kBAAkB,QAAO,4BAA4B;AAE7D,MAAMC,qBAAqB,CAAC,OAAO,CAAC;AAEpC,OAAO,SAASC,qBAAqBC,MAapC;IACC,IAAIA,OAAOC,MAAM,KAAKC,WAAW,OAAOA;IACxC,MAAMD,SAASD,OAAOC,MAAM;IAE5B,MAAME,oBAAoBC,sBAAsB;QAAC,GAAGJ,MAAM;QAAEC;IAAM;IAClE,IAAIE,sBAAsBD,WAAW,OAAOA;IAE5C,MAAMG,QAAQb,yBAAyBW,kBAAkBG,UAAU,CAACL,MAAM;IAC1E,IAAII,MAAME,QAAQ,CAAC,YAAYP,OAAOQ,oBAAoB,CAACC,IAAI,KAAK,GAAG;QACrET,OAAOU,MAAM,CAACC,IAAI,CAChBf,MAAM;YACJgB,MAAMZ,OAAOa,WAAW;YACxBC,SAAS,GAAGjB,mBAAmBG,OAAOe,KAAK,EAAE,4DAA4D,CAAC;YAC1GC,MAAMhB,OAAOgB,IAAI;YACjBC,SAAS;gBACPF,OAAOf,OAAOe,KAAK;gBACnBd,QAAQD,OAAOC,MAAM;gBACrBiB,cAAcb;gBACdc,eAAe;oBAAC;iBAAQ;YAC1B;QACF;QAEF,OAAOjB;IACT;IAEA,OAAOP,4BAA4B;QACjCoB,OAAOf,OAAOe,KAAK;QACnBd,QAAQE,kBAAkBG,UAAU,CAACL,MAAM;QAC3CmB,MAAMpB,OAAOoB,IAAI;QACjBJ,MAAMhB,OAAOgB,IAAI;QACjBH,aAAab,OAAOa,WAAW;QAC/BQ,gBAAgBrB,OAAOqB,cAAc;QACrCX,QAAQV,OAAOU,MAAM;QACrBF,sBAAsBR,OAAOQ,oBAAoB;QACjDc,aAAatB,OAAOsB,WAAW;IACjC;AACF;AAEA,SAASlB,sBAAsBJ,MAO9B;IACC,IAAIuB;IACJ,IAAI;QACFA,WAAW7B,sBAAsBM,OAAOC,MAAM;IAChD,EAAE,OAAOuB,OAAO;QACdxB,OAAOU,MAAM,CAACC,IAAI,CAChBc,eAAe;YACb,GAAGzB,MAAM;YACT0B,QACEF,iBAAiB/B,+BACb+B,MAAME,MAAM,GACZ;QACR;QAEF,OAAOxB;IACT;IAEA,MAAM,CAACyB,QAAQ,GAAGJ;IAClB,IAAII,SAASC,SAAS,UAAUL,SAASM,MAAM,KAAK,GAAG,OAAOF;IAE9D3B,OAAOU,MAAM,CAACC,IAAI,CAChBc,eAAe;QACb,GAAGzB,MAAM;QACT0B,QAAQ,GAAG7B,mBAAmBG,OAAOe,KAAK,EAAE,qBAAqB,EAAEjB,mBAAmB,YAAY,CAAC;IACrG;IAEF,OAAOI;AACT;AAEA,SAASuB,eAAezB,MAOvB;IACC,OAAOJ,MAAM;QACXgB,MAAMZ,OAAOa,WAAW;QACxBC,SAASd,OAAOqB,cAAc;QAC9BL,MAAMhB,OAAOgB,IAAI;QACjBC,SAAS;YACPF,OAAOf,OAAOe,KAAK;YACnBd,QAAQD,OAAOC,MAAM;YACrByB,QAAQ1B,OAAO0B,MAAM;QACvB;IACF;AACF"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { WorkflowDocumentJobCheckout } from '@shipfox/workflow-document';
|
|
2
|
+
import type { WorkflowModelJobCheckout } from '../entities/workflow-model.js';
|
|
3
|
+
export declare const DEFAULT_JOB_CHECKOUT: WorkflowModelJobCheckout;
|
|
4
|
+
export declare function normalizeJobCheckout(checkout: WorkflowDocumentJobCheckout | undefined): WorkflowModelJobCheckout;
|
|
5
|
+
//# sourceMappingURL=normalize-job-checkout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-job-checkout.d.ts","sourceRoot":"","sources":["../../../src/core/workflow-model/normalize-job-checkout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,2BAA2B,EAAC,MAAM,4BAA4B,CAAC;AAC5E,OAAO,KAAK,EAAC,wBAAwB,EAAC,MAAM,+BAA+B,CAAC;AAE5E,eAAO,MAAM,oBAAoB,EAAE,wBAGlC,CAAC;AAEF,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,2BAA2B,GAAG,SAAS,GAChD,wBAAwB,CAQ1B"}
|