@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,152 @@
|
|
|
1
|
+
import {validateDefinition} from './validate-definition.js';
|
|
2
|
+
|
|
3
|
+
describe('validateDefinition', () => {
|
|
4
|
+
test('valid YAML returns { valid: true, definition }', () => {
|
|
5
|
+
const yaml = `
|
|
6
|
+
name: Test
|
|
7
|
+
runner: ubuntu-latest
|
|
8
|
+
jobs:
|
|
9
|
+
build:
|
|
10
|
+
steps:
|
|
11
|
+
- run: echo hello
|
|
12
|
+
`;
|
|
13
|
+
|
|
14
|
+
const result = validateDefinition(yaml);
|
|
15
|
+
|
|
16
|
+
expect(result.valid).toBe(true);
|
|
17
|
+
if (result.valid) {
|
|
18
|
+
expect(result.definition.document.name).toBe('Test');
|
|
19
|
+
expect(result.definition.document.jobs.build?.steps).toHaveLength(1);
|
|
20
|
+
expect(result.definition.model.jobs[0]?.id).toBe('build');
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test('invalid YAML syntax returns { valid: false, errors }', () => {
|
|
25
|
+
const result = validateDefinition('name: Bad\n invalid:\nindentation');
|
|
26
|
+
|
|
27
|
+
expect(result.valid).toBe(false);
|
|
28
|
+
if (!result.valid) {
|
|
29
|
+
expect(result.errors).toHaveLength(1);
|
|
30
|
+
expect(result.errors[0]?.message).toContain('Invalid workflow YAML syntax');
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('non-object YAML returns { valid: false, errors }', () => {
|
|
35
|
+
const stringResult = validateDefinition('just a string');
|
|
36
|
+
expect(stringResult.valid).toBe(false);
|
|
37
|
+
|
|
38
|
+
const nullResult = validateDefinition('');
|
|
39
|
+
expect(nullResult.valid).toBe(false);
|
|
40
|
+
|
|
41
|
+
const arrayResult = validateDefinition('- item1\n- item2');
|
|
42
|
+
expect(arrayResult.valid).toBe(false);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test('invalid document returns { valid: false, errors with details }', () => {
|
|
46
|
+
const yaml = `
|
|
47
|
+
jobs:
|
|
48
|
+
build:
|
|
49
|
+
steps:
|
|
50
|
+
- run: echo hello
|
|
51
|
+
`;
|
|
52
|
+
|
|
53
|
+
const result = validateDefinition(yaml);
|
|
54
|
+
|
|
55
|
+
expect(result.valid).toBe(false);
|
|
56
|
+
if (!result.valid) {
|
|
57
|
+
expect(result.errors.length).toBeGreaterThan(0);
|
|
58
|
+
expect(result.errors[0]?.message).toBeDefined();
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test('cyclic DAG returns { valid: false, errors with cycle info }', () => {
|
|
63
|
+
const yaml = `
|
|
64
|
+
name: Cyclic
|
|
65
|
+
runner: ubuntu-latest
|
|
66
|
+
jobs:
|
|
67
|
+
a:
|
|
68
|
+
needs: b
|
|
69
|
+
steps:
|
|
70
|
+
- run: echo a
|
|
71
|
+
b:
|
|
72
|
+
needs: a
|
|
73
|
+
steps:
|
|
74
|
+
- run: echo b
|
|
75
|
+
`;
|
|
76
|
+
|
|
77
|
+
const result = validateDefinition(yaml);
|
|
78
|
+
|
|
79
|
+
expect(result.valid).toBe(false);
|
|
80
|
+
if (!result.valid) {
|
|
81
|
+
expect(result.errors[0]?.message).toContain('Circular dependency');
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test('runner-less YAML returns a validation path for the missing runner', () => {
|
|
86
|
+
const yaml = `
|
|
87
|
+
name: Missing runner
|
|
88
|
+
jobs:
|
|
89
|
+
build:
|
|
90
|
+
steps:
|
|
91
|
+
- run: echo hello
|
|
92
|
+
`;
|
|
93
|
+
|
|
94
|
+
const result = validateDefinition(yaml);
|
|
95
|
+
|
|
96
|
+
expect(result.valid).toBe(false);
|
|
97
|
+
if (!result.valid) {
|
|
98
|
+
expect(result.errors).toContainEqual(expect.objectContaining({path: 'jobs.build.runner'}));
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test('default runner labels allow runner-less YAML', () => {
|
|
103
|
+
const yaml = `
|
|
104
|
+
name: Default runner
|
|
105
|
+
jobs:
|
|
106
|
+
build:
|
|
107
|
+
steps:
|
|
108
|
+
- run: echo hello
|
|
109
|
+
`;
|
|
110
|
+
|
|
111
|
+
const result = validateDefinition(yaml, {defaultRunnerLabels: ['ubuntu-latest']});
|
|
112
|
+
|
|
113
|
+
expect(result.valid).toBe(true);
|
|
114
|
+
if (result.valid) {
|
|
115
|
+
expect(result.definition.model.jobs[0]?.runner).toEqual(['ubuntu-latest']);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test('disabled Pi search tools return precise definition validation paths', () => {
|
|
120
|
+
const yaml = `
|
|
121
|
+
name: Pi tools
|
|
122
|
+
runner: ubuntu-latest
|
|
123
|
+
jobs:
|
|
124
|
+
inspect:
|
|
125
|
+
steps:
|
|
126
|
+
- harness: pi
|
|
127
|
+
prompt: Fetch without search.
|
|
128
|
+
tools: [fetch_content, web_search, get_search_content]
|
|
129
|
+
`;
|
|
130
|
+
|
|
131
|
+
const result = validateDefinition(yaml, {
|
|
132
|
+
harnessToolDeploymentConfig: {
|
|
133
|
+
pi: {enabledToolPackages: ['pi-web-access'], webSearchEnabled: false},
|
|
134
|
+
claude: {enabledToolPackages: []},
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
expect(result.valid).toBe(false);
|
|
139
|
+
if (!result.valid) {
|
|
140
|
+
expect(result.errors).toEqual([
|
|
141
|
+
expect.objectContaining({
|
|
142
|
+
path: 'jobs.inspect.steps.0.tools.1',
|
|
143
|
+
message: expect.stringContaining('web_search'),
|
|
144
|
+
}),
|
|
145
|
+
expect.objectContaining({
|
|
146
|
+
path: 'jobs.inspect.steps.0.tools.2',
|
|
147
|
+
message: expect.stringContaining('get_search_content'),
|
|
148
|
+
}),
|
|
149
|
+
]);
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
});
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type {HarnessToolDeploymentConfig} from '@shipfox/api-agent-dto';
|
|
2
|
+
import {InvalidWorkflowDocumentError} from '@shipfox/workflow-document';
|
|
3
|
+
import {definitionDefaultRunnerLabels, definitionHarnessToolDeploymentConfig} from '../config.js';
|
|
4
|
+
import type {IntegrationValidationContext} from './entities/integration-context.js';
|
|
5
|
+
import type {WorkflowDefinitionPayload} from './entities/workflow-definition.js';
|
|
6
|
+
import {InvalidWorkflowModelError, normalizeWorkflowDocument} from './workflow-model/index.js';
|
|
7
|
+
import {InvalidWorkflowYamlError, parseWorkflowYamlWithLocations} from './workflow-yaml/index.js';
|
|
8
|
+
|
|
9
|
+
export type ValidationError = {message: string; path?: string | undefined};
|
|
10
|
+
|
|
11
|
+
export type ValidationResult =
|
|
12
|
+
| {valid: true; definition: WorkflowDefinitionPayload}
|
|
13
|
+
| {valid: false; errors: ValidationError[]};
|
|
14
|
+
|
|
15
|
+
export function validateDefinition(
|
|
16
|
+
yamlContent: string,
|
|
17
|
+
options: {
|
|
18
|
+
defaultRunnerLabels?: readonly string[];
|
|
19
|
+
harnessToolDeploymentConfig?: HarnessToolDeploymentConfig;
|
|
20
|
+
integrationValidationContext?: IntegrationValidationContext;
|
|
21
|
+
} = {},
|
|
22
|
+
): ValidationResult {
|
|
23
|
+
try {
|
|
24
|
+
const {document, stepSourceLocations} = parseWorkflowYamlWithLocations(yamlContent);
|
|
25
|
+
const model = normalizeWorkflowDocument(document, {
|
|
26
|
+
defaultRunnerLabels: options.defaultRunnerLabels ?? definitionDefaultRunnerLabels,
|
|
27
|
+
harnessToolDeploymentConfig:
|
|
28
|
+
options.harnessToolDeploymentConfig ?? definitionHarnessToolDeploymentConfig,
|
|
29
|
+
integrationValidationContext: options.integrationValidationContext,
|
|
30
|
+
stepSourceLocations,
|
|
31
|
+
});
|
|
32
|
+
return {valid: true, definition: {document, model}};
|
|
33
|
+
} catch (error) {
|
|
34
|
+
return {valid: false, errors: validationErrorsFor(error)};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function validationErrorsFor(error: unknown): ValidationError[] {
|
|
39
|
+
if (error instanceof InvalidWorkflowYamlError) {
|
|
40
|
+
return [
|
|
41
|
+
validationError({
|
|
42
|
+
message: error.message,
|
|
43
|
+
path:
|
|
44
|
+
error.location === undefined
|
|
45
|
+
? undefined
|
|
46
|
+
: `${error.location.line}:${error.location.column}`,
|
|
47
|
+
}),
|
|
48
|
+
];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (error instanceof InvalidWorkflowDocumentError) {
|
|
52
|
+
return error.validationError.issues.map((issue) =>
|
|
53
|
+
validationError({
|
|
54
|
+
message: issue.message,
|
|
55
|
+
path: issue.path.join('.') || undefined,
|
|
56
|
+
}),
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (error instanceof InvalidWorkflowModelError) {
|
|
61
|
+
return error.issues.map((issue) =>
|
|
62
|
+
validationError({message: issue.message, path: issue.path.join('.')}),
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function validationError(params: {message: string; path?: string | undefined}): ValidationError {
|
|
70
|
+
if (params.path === undefined) return {message: params.message};
|
|
71
|
+
return {message: params.message, path: params.path};
|
|
72
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Workflow Model
|
|
2
|
+
|
|
3
|
+
Code that turns a checked workflow document into the model used by definitions.
|
|
4
|
+
|
|
5
|
+
## What it does
|
|
6
|
+
|
|
7
|
+
- **`WorkflowModel`**: Defines the stable workflow graph used after document
|
|
8
|
+
parsing.
|
|
9
|
+
- **`normalizeWorkflowDocument(document)`**: Expands shorthand fields, assigns
|
|
10
|
+
stable ids, validates explicit providers, and builds graph edges.
|
|
11
|
+
- **Step gates**: Parse run-step `gate.success` as a server-evaluated CEL
|
|
12
|
+
predicate against context roots available at step reporting, and check
|
|
13
|
+
`gate.on_failure.restart_from` against earlier named steps in the same job.
|
|
14
|
+
- **`InvalidWorkflowModelError`**: Reports semantic workflow errors found during
|
|
15
|
+
normalization.
|
|
16
|
+
|
|
17
|
+
Use this module after a workflow document has passed the shared document checks.
|
|
18
|
+
It gives later code one shape for jobs, steps, runners, and graph edges. This is
|
|
19
|
+
useful even when YAML is the only file format. YAML is for people to write. The
|
|
20
|
+
model is for Shipfox code to use.
|
|
21
|
+
|
|
22
|
+
This split keeps each step clear. The document package checks the public shape.
|
|
23
|
+
This module decides what that shape means for jobs and run order. Later code can
|
|
24
|
+
use the model without asking how the workflow was written.
|
|
25
|
+
|
|
26
|
+
Think of this as the hand off from what a person wrote to what the system can
|
|
27
|
+
run. A person may use short forms and names that are easy to read. The system
|
|
28
|
+
needs one clear form. This module makes that form once, so the rest of the code
|
|
29
|
+
does not have to guess.
|
|
30
|
+
|
|
31
|
+
This is why the module is here. It gives the rest of the app a clear way to do
|
|
32
|
+
its work. A test can set up one case, call one thing, and check what comes back.
|
|
33
|
+
That keeps the next step easy to read.
|
|
34
|
+
It is small.
|
|
35
|
+
|
|
36
|
+
## Installation / Setup
|
|
37
|
+
|
|
38
|
+
This code is part of `@shipfox/api-definitions`. It is not a standalone package.
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@shipfox/api-agent-dto": "workspace:*",
|
|
44
|
+
"@shipfox/workflow-document": "workspace:*"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Usage
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import {normalizeWorkflowDocument} from '#core/workflow-model/index.js';
|
|
53
|
+
|
|
54
|
+
const model = normalizeWorkflowDocument({
|
|
55
|
+
name: 'simple build',
|
|
56
|
+
runner: 'ubuntu-latest',
|
|
57
|
+
jobs: {
|
|
58
|
+
build: {
|
|
59
|
+
steps: [{run: 'npm test'}],
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
console.log(model.jobs[0]?.steps[0]?.command.value);
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Behavior Notes
|
|
68
|
+
|
|
69
|
+
The model does not own project ids, commit shas, refs, dates, database rows, or
|
|
70
|
+
file paths. Those fields belong to `WorkflowDefinition`.
|
|
71
|
+
|
|
72
|
+
Trigger filters stay as source strings in this module until event schemas define
|
|
73
|
+
the expression context needed to type-check them.
|
|
74
|
+
|
|
75
|
+
Event selectors use one document shape, `{source, event, with, filter}`, in
|
|
76
|
+
three roles. Workflow `triggers` start a run. Job `listening.on` fires job
|
|
77
|
+
executions. Job `listening.until` resolves the listening job.
|
|
78
|
+
|
|
79
|
+
The persisted `workflow_document` keeps author-provided runner labels exactly as
|
|
80
|
+
written. Canonical and defaulted labels live on `workflow_model.jobs[].runner`;
|
|
81
|
+
downstream consumers should read the model, not `document.runner`.
|
|
82
|
+
|
|
83
|
+
Run-step gate expressions are different. They are server-evaluated predicates,
|
|
84
|
+
so this module parses them against the shared context registry, rejects
|
|
85
|
+
runner-host roots, and checks that each root is available at step reporting. The
|
|
86
|
+
accepted model stores a `WorkflowExpression` with `language: 'cel'`, the
|
|
87
|
+
original source string, and the strongest check mode the referenced roots allow.
|
|
88
|
+
|
|
89
|
+
Agent steps keep omitted `provider`, `model`, and `thinking` fields omitted in
|
|
90
|
+
the definition model. Run materialization resolves runner-ready catalog defaults
|
|
91
|
+
before execution. Explicit providers are checked against the shared provider
|
|
92
|
+
catalog; explicit model ids are preserved because the shared seed catalog does
|
|
93
|
+
not yet carry each provider's full model list.
|
|
94
|
+
|
|
95
|
+
For now, run-step gates can use typed roots such as `step.exit_code`,
|
|
96
|
+
`step.status`, open output fields such as `step.outputs.pass`, and other server
|
|
97
|
+
roots that are available by step reporting. Guard optional output keys with
|
|
98
|
+
`has(step.outputs.pass)` before reading them so missing keys fail as a normal
|
|
99
|
+
false predicate instead of an uncheckable evaluation error.
|
|
100
|
+
|
|
101
|
+
`on_failure.restart_from` must name an earlier step in the same job. The runtime
|
|
102
|
+
host does not execute restart semantics yet. This module only records the
|
|
103
|
+
accepted meaning in the model.
|
|
104
|
+
|
|
105
|
+
If a rule needs project data or database state, put that rule in another layer.
|
|
106
|
+
This module should stay pure and easy to test.
|
|
107
|
+
|
|
108
|
+
If a rule can be checked from the document alone, it can live here. If a rule
|
|
109
|
+
needs a project, a user, a commit, or a database row, it should live with that
|
|
110
|
+
data.
|
|
111
|
+
|
|
112
|
+
Run this step before saving a new definition. That way bad links, bad ids, and
|
|
113
|
+
bad gate rules stop early, while the caller still knows which file field caused
|
|
114
|
+
the problem.
|
|
115
|
+
|
|
116
|
+
This also makes the next step simpler. The next step can read one clear shape
|
|
117
|
+
instead of checking many short forms again.
|
|
118
|
+
|
|
119
|
+
## Development
|
|
120
|
+
|
|
121
|
+
```sh
|
|
122
|
+
turbo check --filter=@shipfox/api-definitions
|
|
123
|
+
turbo type --filter=@shipfox/api-definitions
|
|
124
|
+
turbo test --filter=@shipfox/api-definitions
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## License
|
|
128
|
+
|
|
129
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const DEFAULT_RUN_TIMEOUT_MS = 30 * 24 * 60 * 60 * 1000;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {isValidCronExpression, isValidTimezone} from './cron-trigger.js';
|
|
2
|
+
|
|
3
|
+
describe('isValidCronExpression', () => {
|
|
4
|
+
it.each([['0 2 * * *'], ['*/15 9-17 * * 1-5'], ['0 2 * * MON']])('accepts %s', (expression) => {
|
|
5
|
+
const result = isValidCronExpression(expression);
|
|
6
|
+
|
|
7
|
+
expect(result).toBe(true);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it.each([['0 0 2 * * *'], ['@daily'], [' '], ['not a cron']])('rejects %s', (expression) => {
|
|
11
|
+
const result = isValidCronExpression(expression);
|
|
12
|
+
|
|
13
|
+
expect(result).toBe(false);
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
describe('isValidTimezone', () => {
|
|
18
|
+
it.each(['UTC', 'Europe/Paris', 'US/Pacific'])('accepts %s', (timezone) => {
|
|
19
|
+
const result = isValidTimezone(timezone);
|
|
20
|
+
|
|
21
|
+
expect(result).toBe(true);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('rejects an unknown timezone', () => {
|
|
25
|
+
const result = isValidTimezone('Not/A/Zone');
|
|
26
|
+
|
|
27
|
+
expect(result).toBe(false);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import {CronExpressionParser} from 'cron-parser';
|
|
2
|
+
import type {WorkflowModelValidationIssue} from './invalid-workflow-model-error.js';
|
|
3
|
+
import {issue} from './validation-issue.js';
|
|
4
|
+
|
|
5
|
+
export const cronTriggerDefaultTimezone = 'UTC';
|
|
6
|
+
const cronFieldSeparatorRegex = /\s+/;
|
|
7
|
+
|
|
8
|
+
export function validateCronTrigger(params: {
|
|
9
|
+
readonly sourceKey: string;
|
|
10
|
+
readonly trigger: {
|
|
11
|
+
readonly event: string;
|
|
12
|
+
};
|
|
13
|
+
readonly config: {
|
|
14
|
+
readonly schedule?: string | undefined;
|
|
15
|
+
readonly timezone?: string | undefined;
|
|
16
|
+
};
|
|
17
|
+
readonly issues: WorkflowModelValidationIssue[];
|
|
18
|
+
}): void {
|
|
19
|
+
const {sourceKey, trigger, config, issues} = params;
|
|
20
|
+
|
|
21
|
+
if (trigger.event !== 'tick') {
|
|
22
|
+
issues.push(
|
|
23
|
+
issue({
|
|
24
|
+
code: 'invalid-cron-event',
|
|
25
|
+
message: `A cron trigger must use event "tick"; found "${trigger.event}".`,
|
|
26
|
+
path: ['triggers', sourceKey, 'event'],
|
|
27
|
+
details: {event: trigger.event},
|
|
28
|
+
}),
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (config.schedule === undefined) {
|
|
33
|
+
issues.push(
|
|
34
|
+
issue({
|
|
35
|
+
code: 'missing-cron-schedule',
|
|
36
|
+
message: 'A cron trigger requires a schedule.',
|
|
37
|
+
path: ['triggers', sourceKey, 'config', 'schedule'],
|
|
38
|
+
}),
|
|
39
|
+
);
|
|
40
|
+
} else if (!isValidCronExpression(config.schedule)) {
|
|
41
|
+
issues.push(
|
|
42
|
+
issue({
|
|
43
|
+
code: 'invalid-cron-schedule',
|
|
44
|
+
message: 'Cron trigger schedule must be a valid 5-field cron expression.',
|
|
45
|
+
path: ['triggers', sourceKey, 'config', 'schedule'],
|
|
46
|
+
details: {schedule: config.schedule},
|
|
47
|
+
}),
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (config.timezone !== undefined && !isValidTimezone(config.timezone)) {
|
|
52
|
+
issues.push(
|
|
53
|
+
issue({
|
|
54
|
+
code: 'invalid-cron-timezone',
|
|
55
|
+
message: 'Cron trigger timezone must be a valid IANA time zone.',
|
|
56
|
+
path: ['triggers', sourceKey, 'config', 'timezone'],
|
|
57
|
+
details: {timezone: config.timezone},
|
|
58
|
+
}),
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function isValidCronExpression(expression: string): boolean {
|
|
64
|
+
const trimmedExpression = expression.trim();
|
|
65
|
+
if (trimmedExpression.length === 0) return false;
|
|
66
|
+
if (trimmedExpression.split(cronFieldSeparatorRegex).length !== 5) return false;
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
CronExpressionParser.parse(trimmedExpression);
|
|
70
|
+
return true;
|
|
71
|
+
} catch {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function isValidTimezone(timezone: string): boolean {
|
|
77
|
+
try {
|
|
78
|
+
new Intl.DateTimeFormat('en-US', {timeZone: timezone});
|
|
79
|
+
return true;
|
|
80
|
+
} catch {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export {DEFAULT_RUN_TIMEOUT_MS} from './constants.js';
|
|
2
|
+
export {
|
|
3
|
+
InvalidWorkflowModelError,
|
|
4
|
+
invalidWorkflowModelErrorCode,
|
|
5
|
+
type WorkflowModelValidationIssue,
|
|
6
|
+
type WorkflowModelValidationIssueCode,
|
|
7
|
+
type WorkflowModelValidationIssuePathSegment,
|
|
8
|
+
} from './invalid-workflow-model-error.js';
|
|
9
|
+
export {normalizeWorkflowDocument} from './normalize-workflow-document.js';
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
export const invalidWorkflowModelErrorCode = 'invalid-workflow-model';
|
|
2
|
+
|
|
3
|
+
export type WorkflowModelValidationIssueCode =
|
|
4
|
+
| 'context-unavailable-at-fill-site'
|
|
5
|
+
| 'context-unavailable-at-predicate-site'
|
|
6
|
+
| 'computed-context-key'
|
|
7
|
+
| 'duplicate-job-id'
|
|
8
|
+
| 'duplicate-step-id'
|
|
9
|
+
| 'duplicate-trigger-id'
|
|
10
|
+
| 'harness-provider-incompatible'
|
|
11
|
+
| 'harness-thinking-incompatible'
|
|
12
|
+
| 'harness-tool-incompatible'
|
|
13
|
+
| 'integration-connection-not-capable'
|
|
14
|
+
| 'integration-connection-not-found'
|
|
15
|
+
| 'integration-write-not-allowed'
|
|
16
|
+
| 'invalid-cron-event'
|
|
17
|
+
| 'invalid-cron-schedule'
|
|
18
|
+
| 'invalid-cron-timezone'
|
|
19
|
+
| 'invalid-provider'
|
|
20
|
+
| 'invalid-trigger-filter'
|
|
21
|
+
| 'invalid-interpolation-expression'
|
|
22
|
+
| 'invalid-interpolation-template'
|
|
23
|
+
| 'invalid-duration'
|
|
24
|
+
| 'invalid-listener-filter'
|
|
25
|
+
| 'invalid-job-if'
|
|
26
|
+
| 'invalid-job-output'
|
|
27
|
+
| 'invalid-job-success'
|
|
28
|
+
| 'invalid-output-schema'
|
|
29
|
+
| 'invalid-runner-label'
|
|
30
|
+
| 'invalid-step-gate-restart-from'
|
|
31
|
+
| 'invalid-step-gate-success'
|
|
32
|
+
| 'invalid-step-if'
|
|
33
|
+
| 'job-dependency-cycle'
|
|
34
|
+
| 'listening-job-missing-resolution-source'
|
|
35
|
+
| 'listening-timeout-exceeds-run-timeout'
|
|
36
|
+
| 'missing-harness-for-tools'
|
|
37
|
+
| 'missing-connection-for-integration'
|
|
38
|
+
| 'missing-job-needs-edge'
|
|
39
|
+
| 'missing-cron-schedule'
|
|
40
|
+
| 'missing-runner-label'
|
|
41
|
+
| 'multiple-manual-triggers'
|
|
42
|
+
| 'runner-context-not-bare'
|
|
43
|
+
| 'runner-context-in-field'
|
|
44
|
+
| 'runner-context-in-server-predicate'
|
|
45
|
+
| 'self-job-dependency'
|
|
46
|
+
| 'too-many-runner-labels'
|
|
47
|
+
| 'unknown-secret-store'
|
|
48
|
+
| 'unknown-interpolation-context'
|
|
49
|
+
| 'unknown-integration-method'
|
|
50
|
+
| 'unknown-integration-tool'
|
|
51
|
+
| 'unknown-job-dependency'
|
|
52
|
+
| 'untrusted-context-in-field'
|
|
53
|
+
| 'vars-context-in-server-predicate';
|
|
54
|
+
|
|
55
|
+
export type WorkflowModelValidationIssuePathSegment = string | number;
|
|
56
|
+
|
|
57
|
+
export interface WorkflowModelValidationIssue {
|
|
58
|
+
readonly code: WorkflowModelValidationIssueCode;
|
|
59
|
+
readonly message: string;
|
|
60
|
+
readonly path: readonly WorkflowModelValidationIssuePathSegment[];
|
|
61
|
+
readonly details?: Readonly<Record<string, unknown>>;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export class InvalidWorkflowModelError extends Error {
|
|
65
|
+
readonly code = invalidWorkflowModelErrorCode;
|
|
66
|
+
|
|
67
|
+
constructor(readonly issues: readonly WorkflowModelValidationIssue[]) {
|
|
68
|
+
super('Invalid workflow model');
|
|
69
|
+
this.name = 'InvalidWorkflowModelError';
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type {WorkflowDocument} from '@shipfox/workflow-document';
|
|
2
|
+
import type {WorkflowModelValidationIssue} from './invalid-workflow-model-error.js';
|
|
3
|
+
import {stableId} from './stable-id.js';
|
|
4
|
+
import {issue} from './validation-issue.js';
|
|
5
|
+
|
|
6
|
+
export function mapJobIds(
|
|
7
|
+
document: WorkflowDocument,
|
|
8
|
+
issues: WorkflowModelValidationIssue[],
|
|
9
|
+
): ReadonlyMap<string, string> {
|
|
10
|
+
const jobIdBySourceName = new Map<string, string>();
|
|
11
|
+
const usedJobIds = new Map<string, string>();
|
|
12
|
+
|
|
13
|
+
for (const sourceKey of Object.keys(document.jobs)) {
|
|
14
|
+
const id = stableId(sourceKey);
|
|
15
|
+
const existingSourceKey = usedJobIds.get(id);
|
|
16
|
+
if (existingSourceKey !== undefined) {
|
|
17
|
+
issues.push(
|
|
18
|
+
issue({
|
|
19
|
+
code: 'duplicate-job-id',
|
|
20
|
+
message: `Job keys "${existingSourceKey}" and "${sourceKey}" resolve to the same stable id "${id}".`,
|
|
21
|
+
path: ['jobs', sourceKey],
|
|
22
|
+
details: {id, sourceKeys: [existingSourceKey, sourceKey]},
|
|
23
|
+
}),
|
|
24
|
+
);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
usedJobIds.set(id, sourceKey);
|
|
29
|
+
jobIdBySourceName.set(sourceKey, id);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return jobIdBySourceName;
|
|
33
|
+
}
|