@pikku/core 0.12.106 → 0.12.111
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +358 -0
- package/dist/analytics/analytics.d.ts +6 -0
- package/dist/analytics/analytics.js +58 -0
- package/dist/analytics/analytics.types.d.ts +156 -0
- package/dist/analytics/analytics.types.js +1 -0
- package/dist/analytics/anonymous-analytics-identity.d.ts +23 -0
- package/dist/analytics/anonymous-analytics-identity.js +27 -0
- package/dist/analytics/compose-analytics-identity.d.ts +14 -0
- package/dist/analytics/compose-analytics-identity.js +33 -0
- package/dist/analytics/cookie-analytics-identity.d.ts +24 -0
- package/dist/analytics/cookie-analytics-identity.js +37 -0
- package/dist/analytics/define-analytics-events.d.ts +22 -0
- package/dist/analytics/define-analytics-events.js +9 -0
- package/dist/analytics/fan-out-analytics.d.ts +15 -0
- package/dist/analytics/fan-out-analytics.js +36 -0
- package/dist/analytics/index.d.ts +13 -0
- package/dist/analytics/index.js +8 -0
- package/dist/analytics/logger-analytics-service.d.ts +14 -0
- package/dist/analytics/logger-analytics-service.js +23 -0
- package/dist/analytics/mint-cookie.d.ts +44 -0
- package/dist/analytics/mint-cookie.js +55 -0
- package/dist/errors/errors.d.ts +7 -0
- package/dist/errors/errors.js +17 -0
- package/dist/function/function-meta.types.d.ts +2 -0
- package/dist/function/function-runner.js +29 -0
- package/dist/function/functions.types.d.ts +22 -3
- package/dist/middleware/auth-apikey.d.ts +1 -1
- package/dist/pikku-state.d.ts +1 -1
- package/dist/scopes.d.ts +11 -0
- package/dist/scopes.js +17 -0
- package/dist/services/credential-wire-service.d.ts +1 -1
- package/dist/services/feature-flag-service.d.ts +100 -0
- package/dist/services/feature-flag-service.js +1 -0
- package/dist/services/index.d.ts +1 -0
- package/dist/services/meta-service.d.ts +16 -0
- package/dist/services/meta-service.js +19 -0
- package/dist/services/webhook-service.d.ts +7 -2
- package/dist/services/webhook-service.js +11 -6
- package/dist/testing/service-tests/agent-run-service-tests.d.ts +2 -2
- package/dist/testing/service-tests/agent-storage-service-tests.d.ts +1 -1
- package/dist/testing/service-tests/channel-store-tests.d.ts +1 -1
- package/dist/testing/service-tests/credential-service-tests.d.ts +1 -1
- package/dist/testing/service-tests/deployment-service-tests.d.ts +1 -1
- package/dist/testing/service-tests/event-hub-store-tests.d.ts +1 -1
- package/dist/testing/service-tests/secret-service-tests.d.ts +1 -1
- package/dist/testing/service-tests/session-store-tests.d.ts +1 -1
- package/dist/testing/service-tests/workflow-run-service-tests.d.ts +1 -1
- package/dist/testing/service-tests/workflow-service-tests.d.ts +1 -1
- package/dist/types/core.types.d.ts +23 -0
- package/dist/wirings/agent/agent-rpc.d.ts +1 -1
- package/dist/wirings/agent/agent-turn.d.ts +1 -1
- package/dist/wirings/agent-scorer/agent-scorer-live.d.ts +1 -1
- package/dist/wirings/channel/channel-common.d.ts +1 -1
- package/dist/wirings/channel/channel-rpc-validators.d.ts +2 -2
- package/dist/wirings/channel/channel-runner.d.ts +1 -1
- package/dist/wirings/channel/local/local-channel-runner.d.ts +1 -1
- package/dist/wirings/channel/serverless/serverless-channel-runner.d.ts +1 -1
- package/dist/wirings/cli/channel/cli-approval.d.ts +2 -2
- package/dist/wirings/flag/assert-feature-available.d.ts +15 -0
- package/dist/wirings/flag/assert-feature-available.js +23 -0
- package/dist/wirings/flag/cached-flag-source.d.ts +73 -0
- package/dist/wirings/flag/cached-flag-source.js +96 -0
- package/dist/wirings/flag/define-feature-flags.d.ts +33 -0
- package/dist/wirings/flag/define-feature-flags.js +32 -0
- package/dist/wirings/flag/flag.types.d.ts +97 -0
- package/dist/wirings/flag/flag.types.js +1 -0
- package/dist/wirings/flag/index.d.ts +7 -0
- package/dist/wirings/flag/index.js +5 -0
- package/dist/wirings/flag/resolve-flag.d.ts +52 -0
- package/dist/wirings/flag/resolve-flag.js +90 -0
- package/dist/wirings/flag/validate-flag-definitions.d.ts +26 -0
- package/dist/wirings/flag/validate-flag-definitions.js +103 -0
- package/dist/wirings/rpc/rpc-runner.js +3 -0
- package/dist/wirings/virtual-user/virtual-user-scaffold.d.ts +8 -8
- package/dist/wirings/virtual-user/virtual-user-schedule.d.ts +1 -1
- package/dist/wirings/workflow/workflow-queue-routing.d.ts +1 -1
- package/package.json +11 -5
- package/run-tests.sh +17 -9
- package/src/public-surface.json +26 -0
- package/src/agent-naming.test.ts +0 -68
- package/src/api-report.test.ts +0 -138
- package/src/app-alias-surface.test.ts +0 -179
- package/src/app-leaf-surface.test.ts +0 -222
- package/src/bootstrap-compat/root.ts +0 -20
- package/src/classification/column-form.test.ts +0 -97
- package/src/classification/column-form.ts +0 -55
- package/src/classification/data-classification.ts +0 -73
- package/src/classification/index.ts +0 -40
- package/src/classification/key-ids.ts +0 -2
- package/src/classification/secret-value.test.ts +0 -204
- package/src/classification/secret-value.ts +0 -106
- package/src/crypto-utils.test.ts +0 -668
- package/src/crypto-utils.ts +0 -460
- package/src/dev/hot-reload.test.ts +0 -587
- package/src/dev/hot-reload.ts +0 -225
- package/src/dev/module-runner.test.ts +0 -235
- package/src/dev/module-runner.ts +0 -138
- package/src/dev/reload-meta.test.ts +0 -183
- package/src/dev/reload-meta.ts +0 -144
- package/src/ecosystem-tier-removed.test.ts +0 -72
- package/src/env.ts +0 -1
- package/src/errors/error-handler.ts +0 -77
- package/src/errors/error.test.ts +0 -229
- package/src/errors/errors.ts +0 -393
- package/src/errors/index.ts +0 -11
- package/src/errors/serialized-error.ts +0 -12
- package/src/factory-functions.test.ts +0 -111
- package/src/function/abort-scope.test.ts +0 -97
- package/src/function/abort-scope.ts +0 -80
- package/src/function/function-meta.types.ts +0 -151
- package/src/function/function-runner.test.ts +0 -1619
- package/src/function/function-runner.ts +0 -499
- package/src/function/functions.types.ts +0 -319
- package/src/function/index.ts +0 -40
- package/src/function/list.types.test.ts +0 -100
- package/src/function/list.types.ts +0 -69
- package/src/function/pikku-request.test.ts +0 -35
- package/src/function/pikku-request.ts +0 -17
- package/src/gopass-secrets-removed.test.ts +0 -51
- package/src/handle-error.test.ts +0 -532
- package/src/handle-error.ts +0 -64
- package/src/middleware/auth-apikey.test.ts +0 -362
- package/src/middleware/auth-apikey.ts +0 -39
- package/src/middleware/auth-bearer.test.ts +0 -566
- package/src/middleware/auth-bearer.ts +0 -83
- package/src/middleware/auth-cookie.test.ts +0 -572
- package/src/middleware/auth-cookie.ts +0 -107
- package/src/middleware/cors.test.ts +0 -579
- package/src/middleware/cors.ts +0 -103
- package/src/middleware/index.ts +0 -30
- package/src/middleware/middleware-factories.ts +0 -76
- package/src/middleware/middleware.types.ts +0 -61
- package/src/middleware/remote-auth.test.ts +0 -547
- package/src/middleware/remote-auth.ts +0 -95
- package/src/middleware/remote-jobs-secret.ts +0 -35
- package/src/middleware/require-origin.test.ts +0 -115
- package/src/middleware/require-origin.ts +0 -79
- package/src/middleware/telemetry.ts +0 -83
- package/src/middleware-runner.test.ts +0 -578
- package/src/middleware-runner.ts +0 -232
- package/src/no-any-casts.test.ts +0 -57
- package/src/no-root-barrel.test.ts +0 -122
- package/src/permissions.test.ts +0 -256
- package/src/permissions.ts +0 -217
- package/src/pikku-state.test.ts +0 -198
- package/src/pikku-state.ts +0 -206
- package/src/production-barrels-stay-lean.test.ts +0 -110
- package/src/public-surface.test.ts +0 -133
- package/src/remote.test.ts +0 -173
- package/src/remote.ts +0 -56
- package/src/removed-legacy-exports.test.ts +0 -66
- package/src/run-tests-script.test.ts +0 -67
- package/src/schema.test.ts +0 -430
- package/src/schema.ts +0 -204
- package/src/scopes.test.ts +0 -203
- package/src/scopes.ts +0 -67
- package/src/services/agent-run-state-service.ts +0 -37
- package/src/services/agent-runner-service.ts +0 -238
- package/src/services/agent-storage-service.ts +0 -39
- package/src/services/ai-embedding-service.ts +0 -9
- package/src/services/audit-service.test.ts +0 -44
- package/src/services/audit-service.ts +0 -280
- package/src/services/content-service.ts +0 -65
- package/src/services/credential-service.ts +0 -20
- package/src/services/credential-wire-service.test.ts +0 -235
- package/src/services/credential-wire-service.ts +0 -120
- package/src/services/deployment-service.ts +0 -32
- package/src/services/email-service.test.ts +0 -100
- package/src/services/email-service.ts +0 -60
- package/src/services/email-template.test.ts +0 -311
- package/src/services/email-template.ts +0 -254
- package/src/services/file-scenario-run-store.test.ts +0 -349
- package/src/services/file-scenario-run-store.ts +0 -282
- package/src/services/gateway-service.ts +0 -5
- package/src/services/http-personas-converse.test.ts +0 -274
- package/src/services/http-personas.test.ts +0 -379
- package/src/services/http-personas.ts +0 -508
- package/src/services/in-memory-agent-run-state-service.ts +0 -87
- package/src/services/in-memory-queue-service.test.ts +0 -162
- package/src/services/in-memory-queue-service.ts +0 -78
- package/src/services/in-memory-session-store.test.ts +0 -58
- package/src/services/in-memory-session-store.ts +0 -20
- package/src/services/in-memory-trigger-service.ts +0 -47
- package/src/services/in-memory-workflow-service.test.ts +0 -430
- package/src/services/in-memory-workflow-service.ts +0 -595
- package/src/services/index.ts +0 -192
- package/src/services/istanbul-coverage-service.test.ts +0 -66
- package/src/services/istanbul-coverage-service.ts +0 -59
- package/src/services/jwt-service.ts +0 -15
- package/src/services/local-content-request-handler.test.ts +0 -240
- package/src/services/local-content-request-handler.ts +0 -295
- package/src/services/local-content.test.ts +0 -186
- package/src/services/local-content.ts +0 -242
- package/src/services/local-credential-service.ts +0 -63
- package/src/services/local-email-service.test.ts +0 -182
- package/src/services/local-email-service.ts +0 -43
- package/src/services/local-gateway-service.ts +0 -51
- package/src/services/local-secrets.test.ts +0 -95
- package/src/services/local-secrets.ts +0 -71
- package/src/services/local-variables.test.ts +0 -61
- package/src/services/local-variables.ts +0 -45
- package/src/services/logger-console.test.ts +0 -117
- package/src/services/logger-console.ts +0 -174
- package/src/services/logger.ts +0 -48
- package/src/services/meta-service.test.ts +0 -75
- package/src/services/meta-service.ts +0 -767
- package/src/services/persona-actor-secret.test.ts +0 -68
- package/src/services/persona-actor-secret.ts +0 -70
- package/src/services/persona-sign-in.test.ts +0 -219
- package/src/services/persona-sign-in.ts +0 -238
- package/src/services/personas-service.ts +0 -191
- package/src/services/pikku-user-id.test.ts +0 -62
- package/src/services/pikku-user-id.ts +0 -13
- package/src/services/queue-webhook-service.test.ts +0 -409
- package/src/services/queue-webhook-service.ts +0 -150
- package/src/services/remote-jobs.test.ts +0 -106
- package/src/services/remote-jobs.ts +0 -92
- package/src/services/scheduler-service.ts +0 -37
- package/src/services/schema-service.ts +0 -10
- package/src/services/scope-service.ts +0 -91
- package/src/services/scoped-credential-service.test.ts +0 -86
- package/src/services/scoped-credential-service.ts +0 -63
- package/src/services/scoped-secret-service.test.ts +0 -93
- package/src/services/scoped-secret-service.ts +0 -40
- package/src/services/secret-host-binding.test.ts +0 -138
- package/src/services/secret-host-binding.ts +0 -51
- package/src/services/secret-service.ts +0 -25
- package/src/services/secretless.test.ts +0 -54
- package/src/services/secretless.ts +0 -29
- package/src/services/session-store.ts +0 -9
- package/src/services/stub-tracker.test.ts +0 -104
- package/src/services/stub-tracker.ts +0 -175
- package/src/services/system-role-guard.test.ts +0 -96
- package/src/services/system-role-guard.ts +0 -71
- package/src/services/temporary-file-service.ts +0 -76
- package/src/services/trigger-service.ts +0 -5
- package/src/services/typed-credential-service.ts +0 -83
- package/src/services/typed-secret-service.test.ts +0 -204
- package/src/services/typed-secret-service.ts +0 -132
- package/src/services/typed-variables-service.test.ts +0 -166
- package/src/services/typed-variables-service.ts +0 -166
- package/src/services/user-session-service.test.ts +0 -147
- package/src/services/user-session-service.ts +0 -85
- package/src/services/v8-coverage-service.test.ts +0 -69
- package/src/services/v8-coverage-service.ts +0 -163
- package/src/services/variables-service.ts +0 -13
- package/src/services/webhook-service.ts +0 -147
- package/src/services/workflow-service.ts +0 -120
- package/src/side-effects-are-declared.test.ts +0 -84
- package/src/source-files-stay-composable.test.ts +0 -41
- package/src/template-alias-surface.test.ts +0 -240
- package/src/test-utils.ts +0 -38
- package/src/testing/index.ts +0 -3
- package/src/testing/service-tests/agent-run-service-tests.ts +0 -98
- package/src/testing/service-tests/agent-storage-service-tests.ts +0 -379
- package/src/testing/service-tests/channel-store-tests.ts +0 -98
- package/src/testing/service-tests/credential-service-tests.ts +0 -143
- package/src/testing/service-tests/deployment-service-tests.ts +0 -33
- package/src/testing/service-tests/event-hub-store-tests.ts +0 -48
- package/src/testing/service-tests/secret-service-tests.ts +0 -105
- package/src/testing/service-tests/session-store-tests.ts +0 -62
- package/src/testing/service-tests/workflow-run-service-tests.ts +0 -59
- package/src/testing/service-tests/workflow-service-tests.ts +0 -308
- package/src/testing/service-tests.ts +0 -95
- package/src/time-utils.test.ts +0 -56
- package/src/time-utils.ts +0 -89
- package/src/types/core.types.ts +0 -446
- package/src/types/index.ts +0 -25
- package/src/types/state.types.ts +0 -226
- package/src/types/typed-credentials.test.ts +0 -72
- package/src/utils/hash.test.ts +0 -68
- package/src/utils/hash.ts +0 -26
- package/src/utils/hmac.ts +0 -21
- package/src/utils/node-host-resolver.ts +0 -20
- package/src/utils/safe-fetch.test.ts +0 -515
- package/src/utils/safe-fetch.ts +0 -347
- package/src/utils.test.ts +0 -359
- package/src/utils.ts +0 -165
- package/src/version.test.ts +0 -80
- package/src/version.ts +0 -25
- package/src/wirings/actor-flow/actor-flow.types.ts +0 -40
- package/src/wirings/actor-flow/index.ts +0 -10
- package/src/wirings/actor-flow/run-conversation.test.ts +0 -187
- package/src/wirings/actor-flow/run-conversation.ts +0 -280
- package/src/wirings/addon/addon-auth-tags.test.ts +0 -219
- package/src/wirings/addon/addon-runner.ts +0 -236
- package/src/wirings/addon/addon-scopes.test.ts +0 -225
- package/src/wirings/addon/addon-secrets.test.ts +0 -391
- package/src/wirings/addon/index.ts +0 -12
- package/src/wirings/addon/remote-addon-auth.ts +0 -65
- package/src/wirings/addon/wire-addon.test.ts +0 -102
- package/src/wirings/addon/wire-addon.ts +0 -202
- package/src/wirings/addon/wire-remote-addon.ts +0 -41
- package/src/wirings/agent/agent-agui.test.ts +0 -1213
- package/src/wirings/agent/agent-agui.ts +0 -405
- package/src/wirings/agent/agent-authorization.test.ts +0 -208
- package/src/wirings/agent/agent-finalize.test.ts +0 -187
- package/src/wirings/agent/agent-finalize.ts +0 -197
- package/src/wirings/agent/agent-helpers.test.ts +0 -215
- package/src/wirings/agent/agent-helpers.ts +0 -96
- package/src/wirings/agent/agent-interrupt.test.ts +0 -833
- package/src/wirings/agent/agent-interrupt.ts +0 -400
- package/src/wirings/agent/agent-memory.test.ts +0 -397
- package/src/wirings/agent/agent-memory.ts +0 -496
- package/src/wirings/agent/agent-middleware.types.test.ts +0 -41
- package/src/wirings/agent/agent-model-config.test.ts +0 -103
- package/src/wirings/agent/agent-model-config.ts +0 -59
- package/src/wirings/agent/agent-prepare.test.ts +0 -977
- package/src/wirings/agent/agent-prepare.ts +0 -1083
- package/src/wirings/agent/agent-registry.test.ts +0 -455
- package/src/wirings/agent/agent-registry.ts +0 -99
- package/src/wirings/agent/agent-resume-authorization.test.ts +0 -206
- package/src/wirings/agent/agent-rpc.ts +0 -116
- package/src/wirings/agent/agent-runner.test.ts +0 -1229
- package/src/wirings/agent/agent-runner.ts +0 -858
- package/src/wirings/agent/agent-stream-delegate.test.ts +0 -381
- package/src/wirings/agent/agent-stream-output-hooks.test.ts +0 -353
- package/src/wirings/agent/agent-stream.test.ts +0 -1800
- package/src/wirings/agent/agent-stream.ts +0 -1639
- package/src/wirings/agent/agent-thread-ownership.test.ts +0 -297
- package/src/wirings/agent/agent-turn.test.ts +0 -65
- package/src/wirings/agent/agent-turn.ts +0 -122
- package/src/wirings/agent/agent-utils.ts +0 -20
- package/src/wirings/agent/agent.types.ts +0 -676
- package/src/wirings/agent/index.ts +0 -58
- package/src/wirings/agent/voice-input.test.ts +0 -220
- package/src/wirings/agent/voice-input.ts +0 -180
- package/src/wirings/agent/voice-output.test.ts +0 -510
- package/src/wirings/agent/voice-output.ts +0 -311
- package/src/wirings/agent-scorer/agent-scorer-grade.test.ts +0 -106
- package/src/wirings/agent-scorer/agent-scorer-grade.ts +0 -55
- package/src/wirings/agent-scorer/agent-scorer-judge.test.ts +0 -285
- package/src/wirings/agent-scorer/agent-scorer-judge.ts +0 -180
- package/src/wirings/agent-scorer/agent-scorer-live.test.ts +0 -174
- package/src/wirings/agent-scorer/agent-scorer-live.ts +0 -56
- package/src/wirings/agent-scorer/agent-scorer-registry.ts +0 -66
- package/src/wirings/agent-scorer/agent-scorer-sampling.test.ts +0 -34
- package/src/wirings/agent-scorer/agent-scorer-sampling.ts +0 -36
- package/src/wirings/agent-scorer/agent-scorer-snapshots.test.ts +0 -49
- package/src/wirings/agent-scorer/agent-scorer-snapshots.ts +0 -46
- package/src/wirings/agent-scorer/agent-scorer-worker.test.ts +0 -122
- package/src/wirings/agent-scorer/agent-scorer-worker.ts +0 -71
- package/src/wirings/agent-scorer/agent-scorer.ts +0 -102
- package/src/wirings/agent-scorer/agent-scorer.types.ts +0 -128
- package/src/wirings/agent-scorer/index.ts +0 -23
- package/src/wirings/channel/channel-common.ts +0 -102
- package/src/wirings/channel/channel-handler-shapes.test.ts +0 -72
- package/src/wirings/channel/channel-handler.test.ts +0 -322
- package/src/wirings/channel/channel-handler.ts +0 -259
- package/src/wirings/channel/channel-host-rpc.test.ts +0 -150
- package/src/wirings/channel/channel-host-rpc.ts +0 -69
- package/src/wirings/channel/channel-middleware-runner.test.ts +0 -188
- package/src/wirings/channel/channel-middleware-runner.ts +0 -126
- package/src/wirings/channel/channel-rpc-registry.ts +0 -116
- package/src/wirings/channel/channel-rpc-responder.ts +0 -117
- package/src/wirings/channel/channel-rpc-service.ts +0 -132
- package/src/wirings/channel/channel-rpc-validators.ts +0 -65
- package/src/wirings/channel/channel-rpc.test.ts +0 -841
- package/src/wirings/channel/channel-rpc.ts +0 -5
- package/src/wirings/channel/channel-rpc.types.ts +0 -160
- package/src/wirings/channel/channel-runner.ts +0 -164
- package/src/wirings/channel/channel-store.ts +0 -35
- package/src/wirings/channel/channel.types.ts +0 -193
- package/src/wirings/channel/define-channel-routes.ts +0 -5
- package/src/wirings/channel/eventhub-service.ts +0 -16
- package/src/wirings/channel/eventhub-store.ts +0 -13
- package/src/wirings/channel/index.ts +0 -40
- package/src/wirings/channel/local/index.ts +0 -3
- package/src/wirings/channel/local/local-channel-handler.ts +0 -98
- package/src/wirings/channel/local/local-channel-runner.test.ts +0 -339
- package/src/wirings/channel/local/local-channel-runner.ts +0 -271
- package/src/wirings/channel/local/local-eventhub-service.test.ts +0 -77
- package/src/wirings/channel/local/local-eventhub-service.ts +0 -69
- package/src/wirings/channel/log-channels.ts +0 -16
- package/src/wirings/channel/pikku-abstract-channel-handler.test.ts +0 -135
- package/src/wirings/channel/pikku-abstract-channel-handler.ts +0 -60
- package/src/wirings/channel/serverless/index.ts +0 -6
- package/src/wirings/channel/serverless/serverless-channel-runner.ts +0 -328
- package/src/wirings/cli/channel/cli-approval.test.ts +0 -177
- package/src/wirings/cli/channel/cli-approval.ts +0 -135
- package/src/wirings/cli/channel/cli-channel-runner.ts +0 -118
- package/src/wirings/cli/channel/cli-raw-channel-runner.test.ts +0 -192
- package/src/wirings/cli/channel/cli-raw-channel-runner.ts +0 -148
- package/src/wirings/cli/channel/cli-raw-client-runner.test.ts +0 -480
- package/src/wirings/cli/channel/cli-raw-client-runner.ts +0 -188
- package/src/wirings/cli/channel/index.ts +0 -6
- package/src/wirings/cli/cli-runner.test.ts +0 -969
- package/src/wirings/cli/cli-runner.ts +0 -538
- package/src/wirings/cli/cli.types.ts +0 -388
- package/src/wirings/cli/command-parser.test.ts +0 -1120
- package/src/wirings/cli/command-parser.ts +0 -713
- package/src/wirings/cli/define-cli-commands.ts +0 -13
- package/src/wirings/cli/format-cli-error.test.ts +0 -91
- package/src/wirings/cli/format-cli-error.ts +0 -96
- package/src/wirings/cli/index.ts +0 -19
- package/src/wirings/credential/credential.types.ts +0 -37
- package/src/wirings/credential/define-credential.ts +0 -49
- package/src/wirings/credential/index.ts +0 -7
- package/src/wirings/credential/validate-credential-definitions.ts +0 -63
- package/src/wirings/gateway/gateway-authorization.test.ts +0 -575
- package/src/wirings/gateway/gateway-channel-meta.test.ts +0 -44
- package/src/wirings/gateway/gateway-runner.test.ts +0 -581
- package/src/wirings/gateway/gateway-runner.ts +0 -411
- package/src/wirings/gateway/gateway.types.ts +0 -137
- package/src/wirings/gateway/index.ts +0 -15
- package/src/wirings/http/http-routes.test.ts +0 -318
- package/src/wirings/http/http-routes.ts +0 -111
- package/src/wirings/http/http-runner-addon-ref.test.ts +0 -238
- package/src/wirings/http/http-runner.test.ts +0 -503
- package/src/wirings/http/http-runner.ts +0 -462
- package/src/wirings/http/http.types.ts +0 -307
- package/src/wirings/http/index.ts +0 -27
- package/src/wirings/http/log-http-routes.ts +0 -18
- package/src/wirings/http/pikku-fetch-http-request.test.ts +0 -318
- package/src/wirings/http/pikku-fetch-http-request.ts +0 -260
- package/src/wirings/http/pikku-fetch-http-response.test.ts +0 -123
- package/src/wirings/http/pikku-fetch-http-response.ts +0 -149
- package/src/wirings/http/routers/http-router.ts +0 -13
- package/src/wirings/http/routers/path-to-regex.test.ts +0 -306
- package/src/wirings/http/routers/path-to-regex.ts +0 -115
- package/src/wirings/http/web-request.test.ts +0 -382
- package/src/wirings/http/web-request.ts +0 -162
- package/src/wirings/mcp/index.ts +0 -26
- package/src/wirings/mcp/mcp-endpoint-registry.test.ts +0 -388
- package/src/wirings/mcp/mcp-endpoint-registry.ts +0 -159
- package/src/wirings/mcp/mcp-runner.test.ts +0 -588
- package/src/wirings/mcp/mcp-runner.ts +0 -330
- package/src/wirings/mcp/mcp.types.ts +0 -199
- package/src/wirings/node/index.ts +0 -2
- package/src/wirings/node/node.types.ts +0 -23
- package/src/wirings/oauth2/index.ts +0 -1
- package/src/wirings/oauth2/oauth2.types.ts +0 -12
- package/src/wirings/persona/define-personas.ts +0 -33
- package/src/wirings/persona/index.ts +0 -75
- package/src/wirings/persona/persona-app-scopes.test.ts +0 -47
- package/src/wirings/persona/persona-app-scopes.ts +0 -74
- package/src/wirings/persona/persona-email.ts +0 -87
- package/src/wirings/persona/persona-environments.test.ts +0 -194
- package/src/wirings/persona/persona-environments.ts +0 -138
- package/src/wirings/persona/persona-mailbox.ts +0 -156
- package/src/wirings/persona/persona.test.ts +0 -230
- package/src/wirings/persona/persona.types.ts +0 -156
- package/src/wirings/persona/validate-personas.ts +0 -137
- package/src/wirings/queue/index.ts +0 -29
- package/src/wirings/queue/queue-identity.test.ts +0 -454
- package/src/wirings/queue/queue-identity.ts +0 -176
- package/src/wirings/queue/queue-runner.test.ts +0 -705
- package/src/wirings/queue/queue-runner.ts +0 -181
- package/src/wirings/queue/queue.types.ts +0 -161
- package/src/wirings/queue/register-queue-helper.ts +0 -46
- package/src/wirings/queue/signed-queue-service.ts +0 -60
- package/src/wirings/queue/validate-worker-config.test.ts +0 -108
- package/src/wirings/queue/validate-worker-config.ts +0 -90
- package/src/wirings/role/define-system-role.ts +0 -33
- package/src/wirings/role/index.ts +0 -13
- package/src/wirings/role/role.test.ts +0 -104
- package/src/wirings/role/role.types.ts +0 -47
- package/src/wirings/role/validate-role-definitions.ts +0 -93
- package/src/wirings/rpc/index.ts +0 -8
- package/src/wirings/rpc/rpc-runner.test.ts +0 -1130
- package/src/wirings/rpc/rpc-runner.ts +0 -566
- package/src/wirings/rpc/rpc-types.ts +0 -87
- package/src/wirings/scheduler/index.ts +0 -11
- package/src/wirings/scheduler/log-schedulers.ts +0 -16
- package/src/wirings/scheduler/scheduler-runner.test.ts +0 -835
- package/src/wirings/scheduler/scheduler-runner.ts +0 -138
- package/src/wirings/scheduler/scheduler.types.ts +0 -42
- package/src/wirings/scope/define-scope.ts +0 -33
- package/src/wirings/scope/index.ts +0 -15
- package/src/wirings/scope/scope.test.ts +0 -159
- package/src/wirings/scope/scope.types.ts +0 -42
- package/src/wirings/scope/validate-scope-definitions.ts +0 -107
- package/src/wirings/secret/index.ts +0 -9
- package/src/wirings/secret/secret.types.ts +0 -70
- package/src/wirings/secret/validate-secret-definitions.test.ts +0 -232
- package/src/wirings/secret/validate-secret-definitions.ts +0 -88
- package/src/wirings/trigger/index.ts +0 -9
- package/src/wirings/trigger/pikku-trigger-service.ts +0 -107
- package/src/wirings/trigger/trigger-runner.test.ts +0 -78
- package/src/wirings/trigger/trigger-runner.ts +0 -113
- package/src/wirings/trigger/trigger.types.ts +0 -100
- package/src/wirings/variable/index.ts +0 -8
- package/src/wirings/variable/validate-variable-definitions.test.ts +0 -115
- package/src/wirings/variable/validate-variable-definitions.ts +0 -71
- package/src/wirings/variable/variable.types.ts +0 -40
- package/src/wirings/virtual-user/index.ts +0 -107
- package/src/wirings/virtual-user/prepare-virtual-user-run.test.ts +0 -115
- package/src/wirings/virtual-user/prepare-virtual-user-run.ts +0 -95
- package/src/wirings/virtual-user/run-virtual-user.test.ts +0 -774
- package/src/wirings/virtual-user/run-virtual-user.ts +0 -684
- package/src/wirings/virtual-user/virtual-user-agents.test.ts +0 -72
- package/src/wirings/virtual-user/virtual-user-agents.ts +0 -62
- package/src/wirings/virtual-user/virtual-user-catalogue.test.ts +0 -215
- package/src/wirings/virtual-user/virtual-user-catalogue.ts +0 -184
- package/src/wirings/virtual-user/virtual-user-derive.test.ts +0 -426
- package/src/wirings/virtual-user/virtual-user-derive.ts +0 -161
- package/src/wirings/virtual-user/virtual-user-dispositions.test.ts +0 -68
- package/src/wirings/virtual-user/virtual-user-dispositions.ts +0 -210
- package/src/wirings/virtual-user/virtual-user-intents.test.ts +0 -218
- package/src/wirings/virtual-user/virtual-user-intents.ts +0 -185
- package/src/wirings/virtual-user/virtual-user-rng.test.ts +0 -72
- package/src/wirings/virtual-user/virtual-user-rng.ts +0 -50
- package/src/wirings/virtual-user/virtual-user-run-store.ts +0 -131
- package/src/wirings/virtual-user/virtual-user-scaffold.test.ts +0 -854
- package/src/wirings/virtual-user/virtual-user-scaffold.ts +0 -664
- package/src/wirings/virtual-user/virtual-user-schedule-store.ts +0 -93
- package/src/wirings/virtual-user/virtual-user-schedule.test.ts +0 -280
- package/src/wirings/virtual-user/virtual-user-schedule.ts +0 -156
- package/src/wirings/virtual-user/virtual-user-target.ts +0 -47
- package/src/wirings/virtual-user/virtual-user.types.ts +0 -215
- package/src/wirings/workflow/dsl/workflow-dsl.types.ts +0 -709
- package/src/wirings/workflow/dsl/workflow-runner.ts +0 -25
- package/src/wirings/workflow/feature.test.ts +0 -131
- package/src/wirings/workflow/feature.ts +0 -59
- package/src/wirings/workflow/graph/graph-foreach-queued.test.ts +0 -569
- package/src/wirings/workflow/graph/graph-foreach.test.ts +0 -626
- package/src/wirings/workflow/graph/graph-node.ts +0 -115
- package/src/wirings/workflow/graph/graph-runner.test.ts +0 -1049
- package/src/wirings/workflow/graph/graph-runner.ts +0 -1376
- package/src/wirings/workflow/graph/graph-validation.test.ts +0 -27
- package/src/wirings/workflow/graph/graph-validation.ts +0 -41
- package/src/wirings/workflow/graph/template.test.ts +0 -49
- package/src/wirings/workflow/graph/template.ts +0 -42
- package/src/wirings/workflow/graph/wire-workflow-graph.ts +0 -39
- package/src/wirings/workflow/graph/workflow-graph.types.ts +0 -75
- package/src/wirings/workflow/index.ts +0 -107
- package/src/wirings/workflow/pikku-scenario-service.ts +0 -1013
- package/src/wirings/workflow/pikku-workflow-service.test.ts +0 -963
- package/src/wirings/workflow/pikku-workflow-service.ts +0 -1993
- package/src/wirings/workflow/run-timeline.test.ts +0 -199
- package/src/wirings/workflow/run-timeline.ts +0 -185
- package/src/wirings/workflow/scenario-cookie-jar.test.ts +0 -107
- package/src/wirings/workflow/scenario-cookie-jar.ts +0 -57
- package/src/wirings/workflow/scenario-expectations.test.ts +0 -238
- package/src/wirings/workflow/scenario-hooks.test.ts +0 -259
- package/src/wirings/workflow/scenario-poll.test.ts +0 -64
- package/src/wirings/workflow/scenario-poll.ts +0 -27
- package/src/wirings/workflow/scenario-prose.test.ts +0 -275
- package/src/wirings/workflow/scenario-prose.ts +0 -86
- package/src/wirings/workflow/scenario-run.types.ts +0 -193
- package/src/wirings/workflow/scenario-service.test.ts +0 -147
- package/src/wirings/workflow/scenario-step-guards.ts +0 -23
- package/src/wirings/workflow/scenario-step.test.ts +0 -800
- package/src/wirings/workflow/scenario-step.types.ts +0 -262
- package/src/wirings/workflow/scenario-surface.test.ts +0 -146
- package/src/wirings/workflow/scenario-surface.ts +0 -71
- package/src/wirings/workflow/scenario.types.ts +0 -63
- package/src/wirings/workflow/workflow-approval-audit.ts +0 -47
- package/src/wirings/workflow/workflow-approval-policy.test.ts +0 -594
- package/src/wirings/workflow/workflow-approval-policy.ts +0 -68
- package/src/wirings/workflow/workflow-approval.ts +0 -290
- package/src/wirings/workflow/workflow-child-run-session.test.ts +0 -168
- package/src/wirings/workflow/workflow-constants.ts +0 -66
- package/src/wirings/workflow/workflow-dispatch-durability.test.ts +0 -116
- package/src/wirings/workflow/workflow-dispatch-payload.test.ts +0 -55
- package/src/wirings/workflow/workflow-dispatch-relay.test.ts +0 -128
- package/src/wirings/workflow/workflow-errors.ts +0 -132
- package/src/wirings/workflow/workflow-inline-authority.test.ts +0 -175
- package/src/wirings/workflow/workflow-invocation-id.test.ts +0 -51
- package/src/wirings/workflow/workflow-invocation-id.ts +0 -28
- package/src/wirings/workflow/workflow-meta-resolver.ts +0 -45
- package/src/wirings/workflow/workflow-mirror.test.ts +0 -171
- package/src/wirings/workflow/workflow-missing-meta.test.ts +0 -92
- package/src/wirings/workflow/workflow-on-error.test.ts +0 -145
- package/src/wirings/workflow/workflow-queue-routing.ts +0 -129
- package/src/wirings/workflow/workflow-queue-wiring.ts +0 -149
- package/src/wirings/workflow/workflow-queue-workers.test.ts +0 -131
- package/src/wirings/workflow/workflow-queue-workers.ts +0 -66
- package/src/wirings/workflow/workflow-recovery.ts +0 -192
- package/src/wirings/workflow/workflow-replay-snapshot.test.ts +0 -140
- package/src/wirings/workflow/workflow-retry-policy.test.ts +0 -113
- package/src/wirings/workflow/workflow-run-authority.test.ts +0 -212
- package/src/wirings/workflow/workflow-run-context.test.ts +0 -172
- package/src/wirings/workflow/workflow-run-engine.types.ts +0 -92
- package/src/wirings/workflow/workflow-run-ownership.ts +0 -37
- package/src/wirings/workflow/workflow-run-polling.test.ts +0 -127
- package/src/wirings/workflow/workflow-stalled-recovery.test.ts +0 -152
- package/src/wirings/workflow/workflow-status-stream.test.ts +0 -354
- package/src/wirings/workflow/workflow-status-stream.ts +0 -144
- package/src/wirings/workflow/workflow-step-claim.ts +0 -46
- package/src/wirings/workflow/workflow-step-ordinal.test.ts +0 -94
- package/src/wirings/workflow/workflow-step-session.test.ts +0 -87
- package/src/wirings/workflow/workflow-suspend.ts +0 -61
- package/src/wirings/workflow/workflow-terminal-run-guard.test.ts +0 -105
- package/src/wirings/workflow/workflow.types.ts +0 -268
- package/src/wirings-stay-decoupled.test.ts +0 -130
- package/tsconfig.json +0 -14
- package/tsconfig.tsbuildinfo +0 -1
- package/tsconfig.type-tests.json +0 -15
|
@@ -1,963 +0,0 @@
|
|
|
1
|
-
import { describe, test } from 'node:test'
|
|
2
|
-
import assert from 'node:assert/strict'
|
|
3
|
-
import type { StandardSchemaV1 } from '@standard-schema/spec'
|
|
4
|
-
|
|
5
|
-
import { InMemoryWorkflowService } from '../../services/in-memory-workflow-service.js'
|
|
6
|
-
import { pikkuState, resetPikkuState } from '../../pikku-state.js'
|
|
7
|
-
import { addWorkflow } from './dsl/workflow-runner.js'
|
|
8
|
-
import {
|
|
9
|
-
WorkflowApprovalResolvedError,
|
|
10
|
-
WorkflowSuspendedException,
|
|
11
|
-
} from './workflow-errors.js'
|
|
12
|
-
import type { PikkuWorkflowWire } from './workflow.types.js'
|
|
13
|
-
|
|
14
|
-
describe('pikku-workflow-service worker registration', () => {
|
|
15
|
-
test('registers sleeper function metadata after wireQueueWorkers', () => {
|
|
16
|
-
resetPikkuState()
|
|
17
|
-
|
|
18
|
-
const ws = new InMemoryWorkflowService()
|
|
19
|
-
ws.wireQueueWorkers()
|
|
20
|
-
|
|
21
|
-
const functionMeta = pikkuState(null, 'function', 'meta')
|
|
22
|
-
assert.deepEqual(functionMeta.pikkuWorkflowSleeper, {
|
|
23
|
-
pikkuFuncId: 'pikkuWorkflowSleeper',
|
|
24
|
-
sessionless: true,
|
|
25
|
-
functionType: 'helper',
|
|
26
|
-
inputSchemaName: null,
|
|
27
|
-
outputSchemaName: null,
|
|
28
|
-
})
|
|
29
|
-
})
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
describe('pikku-workflow-service per-workflow queue warning', () => {
|
|
33
|
-
const setup = (workflowNames: string[], perWorkflowQueues: string[] = []) => {
|
|
34
|
-
resetPikkuState()
|
|
35
|
-
const warnings: string[] = []
|
|
36
|
-
pikkuState(null, 'package', 'singletonServices', {
|
|
37
|
-
logger: {
|
|
38
|
-
error: () => {},
|
|
39
|
-
info: () => {},
|
|
40
|
-
debug: () => {},
|
|
41
|
-
warn: (message: string) => warnings.push(message),
|
|
42
|
-
},
|
|
43
|
-
} as any)
|
|
44
|
-
|
|
45
|
-
const metaState = pikkuState(null, 'workflows', 'meta')
|
|
46
|
-
for (const name of workflowNames) {
|
|
47
|
-
metaState[name] = {
|
|
48
|
-
name,
|
|
49
|
-
pikkuFuncId: name,
|
|
50
|
-
source: 'dsl',
|
|
51
|
-
graphHash: `${name}-hash`,
|
|
52
|
-
} as any
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const queueMeta = pikkuState(null, 'queue', 'meta')
|
|
56
|
-
for (const queueName of perWorkflowQueues) {
|
|
57
|
-
queueMeta[queueName] = {
|
|
58
|
-
pikkuFuncId: queueName,
|
|
59
|
-
name: queueName,
|
|
60
|
-
} as any
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return warnings
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
test('warns when workflows exist but no per-workflow orchestrator queue is registered', () => {
|
|
67
|
-
const warnings = setup(['someWorkflow'])
|
|
68
|
-
|
|
69
|
-
new InMemoryWorkflowService().wireQueueWorkers()
|
|
70
|
-
|
|
71
|
-
assert.ok(
|
|
72
|
-
warnings.some((w) => /no per-workflow orchestrator queues/.test(w)),
|
|
73
|
-
`expected a per-workflow queue warning, got: ${JSON.stringify(warnings)}`
|
|
74
|
-
)
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
test('does not warn when per-workflow orchestrator queues are present', () => {
|
|
78
|
-
const warnings = setup(['someWorkflow'], ['wf-orchestrator-some-workflow'])
|
|
79
|
-
|
|
80
|
-
new InMemoryWorkflowService().wireQueueWorkers()
|
|
81
|
-
|
|
82
|
-
assert.ok(
|
|
83
|
-
!warnings.some((w) => /no per-workflow orchestrator queues/.test(w)),
|
|
84
|
-
`expected no warning, got: ${JSON.stringify(warnings)}`
|
|
85
|
-
)
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
test('does not warn when the app registers no workflows at all', () => {
|
|
89
|
-
const warnings = setup([])
|
|
90
|
-
|
|
91
|
-
new InMemoryWorkflowService().wireQueueWorkers()
|
|
92
|
-
|
|
93
|
-
assert.ok(
|
|
94
|
-
!warnings.some((w) => /no per-workflow orchestrator queues/.test(w)),
|
|
95
|
-
`expected no warning, got: ${JSON.stringify(warnings)}`
|
|
96
|
-
)
|
|
97
|
-
})
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
describe('pikku-workflow-service run-level inline', () => {
|
|
101
|
-
test('workflow runs inline (and queues nothing) when no queue service is configured', async () => {
|
|
102
|
-
const ws = new InMemoryWorkflowService()
|
|
103
|
-
const workflowName = 'testRunInlineNoQueue'
|
|
104
|
-
const graphHash = 'run-inline-no-queue-hash'
|
|
105
|
-
|
|
106
|
-
pikkuState(null, 'package', 'singletonServices', {
|
|
107
|
-
logger: {
|
|
108
|
-
error: () => {},
|
|
109
|
-
info: () => {},
|
|
110
|
-
warn: () => {},
|
|
111
|
-
debug: () => {},
|
|
112
|
-
},
|
|
113
|
-
} as any)
|
|
114
|
-
|
|
115
|
-
const metaState = pikkuState(null, 'workflows', 'meta')
|
|
116
|
-
metaState[workflowName] = {
|
|
117
|
-
name: workflowName,
|
|
118
|
-
pikkuFuncId: workflowName,
|
|
119
|
-
source: 'dsl',
|
|
120
|
-
graphHash,
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const functionMetaState = pikkuState(null, 'function', 'meta')
|
|
124
|
-
functionMetaState[workflowName] = {
|
|
125
|
-
name: workflowName,
|
|
126
|
-
sessionless: true,
|
|
127
|
-
permissions: [],
|
|
128
|
-
} as any
|
|
129
|
-
|
|
130
|
-
addWorkflow(workflowName, {
|
|
131
|
-
func: async () => {
|
|
132
|
-
return { ok: true }
|
|
133
|
-
},
|
|
134
|
-
})
|
|
135
|
-
|
|
136
|
-
const { runId } = await ws.startWorkflow(workflowName, {}, {}, {})
|
|
137
|
-
|
|
138
|
-
const run = await ws.getRun(runId)
|
|
139
|
-
assert.equal(run?.inline, true, 'run should be marked as inline')
|
|
140
|
-
|
|
141
|
-
delete metaState[workflowName]
|
|
142
|
-
delete functionMetaState[workflowName]
|
|
143
|
-
pikkuState(null, 'workflows', 'registrations').delete(workflowName)
|
|
144
|
-
})
|
|
145
|
-
|
|
146
|
-
test('workflow is dispatched to the queue when a queueService exists', async () => {
|
|
147
|
-
const ws = new InMemoryWorkflowService()
|
|
148
|
-
const workflowName = 'testNonInlineMetaFlag'
|
|
149
|
-
const graphHash = 'non-inline-meta-hash'
|
|
150
|
-
|
|
151
|
-
let queued = false
|
|
152
|
-
pikkuState(null, 'package', 'singletonServices', {
|
|
153
|
-
queueService: {
|
|
154
|
-
add: async () => {
|
|
155
|
-
queued = true
|
|
156
|
-
},
|
|
157
|
-
},
|
|
158
|
-
} as any)
|
|
159
|
-
|
|
160
|
-
const metaState = pikkuState(null, 'workflows', 'meta')
|
|
161
|
-
metaState[workflowName] = {
|
|
162
|
-
name: workflowName,
|
|
163
|
-
pikkuFuncId: workflowName,
|
|
164
|
-
source: 'dsl',
|
|
165
|
-
graphHash,
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const functionMetaState = pikkuState(null, 'function', 'meta')
|
|
169
|
-
functionMetaState[workflowName] = {
|
|
170
|
-
name: workflowName,
|
|
171
|
-
sessionless: true,
|
|
172
|
-
permissions: [],
|
|
173
|
-
} as any
|
|
174
|
-
|
|
175
|
-
addWorkflow(workflowName, {
|
|
176
|
-
func: async () => {
|
|
177
|
-
return { ok: true }
|
|
178
|
-
},
|
|
179
|
-
})
|
|
180
|
-
|
|
181
|
-
await ws.startWorkflow(workflowName, {}, {})
|
|
182
|
-
|
|
183
|
-
await new Promise((r) => setTimeout(r, 50))
|
|
184
|
-
|
|
185
|
-
assert.equal(queued, true, 'workflow should have been queued')
|
|
186
|
-
|
|
187
|
-
delete metaState[workflowName]
|
|
188
|
-
delete functionMetaState[workflowName]
|
|
189
|
-
pikkuState(null, 'workflows', 'registrations').delete(workflowName)
|
|
190
|
-
})
|
|
191
|
-
})
|
|
192
|
-
|
|
193
|
-
describe('pikku-workflow-service per-function step dispatch', () => {
|
|
194
|
-
class TestWorkflowService extends InMemoryWorkflowService {
|
|
195
|
-
public callDispatchStep(rpcName: string, runId = 'run-1') {
|
|
196
|
-
return this.dispatchStep(runId, 'step-1', rpcName, {})
|
|
197
|
-
}
|
|
198
|
-
public markInline(runId: string) {
|
|
199
|
-
this.registerInlineRun(runId)
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
const setupFunction = (rpcName: string, workflowQueued?: boolean) => {
|
|
204
|
-
pikkuState(null, 'rpc', 'meta')[rpcName] = rpcName as any
|
|
205
|
-
pikkuState(null, 'function', 'meta')[rpcName] = {
|
|
206
|
-
pikkuFuncId: rpcName,
|
|
207
|
-
sessionless: true,
|
|
208
|
-
...(workflowQueued === undefined ? {} : { workflowQueued }),
|
|
209
|
-
} as any
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
const cleanup = (rpcName: string) => {
|
|
213
|
-
delete pikkuState(null, 'rpc', 'meta')[rpcName]
|
|
214
|
-
delete pikkuState(null, 'function', 'meta')[rpcName]
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
test('default (inline) step is NOT dispatched to the queue', async () => {
|
|
218
|
-
const ws = new TestWorkflowService()
|
|
219
|
-
let queued = false
|
|
220
|
-
pikkuState(null, 'package', 'singletonServices', {
|
|
221
|
-
logger: { error() {}, info() {}, warn() {}, debug() {} },
|
|
222
|
-
queueService: {
|
|
223
|
-
add: async () => {
|
|
224
|
-
queued = true
|
|
225
|
-
},
|
|
226
|
-
},
|
|
227
|
-
} as any)
|
|
228
|
-
|
|
229
|
-
setupFunction('defaultInlineStep')
|
|
230
|
-
const dispatched = await ws.callDispatchStep('defaultInlineStep')
|
|
231
|
-
assert.equal(dispatched, false, 'default step should run inline')
|
|
232
|
-
assert.equal(queued, false, 'default step should not queue')
|
|
233
|
-
cleanup('defaultInlineStep')
|
|
234
|
-
})
|
|
235
|
-
|
|
236
|
-
test('workflowQueued: true step IS dispatched to the queue when a queueService exists', async () => {
|
|
237
|
-
const ws = new TestWorkflowService()
|
|
238
|
-
let queued = false
|
|
239
|
-
pikkuState(null, 'package', 'singletonServices', {
|
|
240
|
-
logger: { error() {}, info() {}, warn() {}, debug() {} },
|
|
241
|
-
queueService: {
|
|
242
|
-
add: async () => {
|
|
243
|
-
queued = true
|
|
244
|
-
},
|
|
245
|
-
},
|
|
246
|
-
} as any)
|
|
247
|
-
|
|
248
|
-
setupFunction('queuedStep', true)
|
|
249
|
-
const dispatched = await ws.callDispatchStep('queuedStep')
|
|
250
|
-
assert.equal(dispatched, true, 'workflowQueued step should dispatch')
|
|
251
|
-
assert.equal(queued, true, 'workflowQueued step should queue')
|
|
252
|
-
cleanup('queuedStep')
|
|
253
|
-
})
|
|
254
|
-
|
|
255
|
-
const setupWorkflow = (name: string) => {
|
|
256
|
-
pikkuState(null, 'workflows', 'meta')[name] = {
|
|
257
|
-
name,
|
|
258
|
-
pikkuFuncId: name,
|
|
259
|
-
graphHash: 'hash',
|
|
260
|
-
} as any
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
const cleanupWorkflow = (name: string) => {
|
|
264
|
-
delete pikkuState(null, 'workflows', 'meta')[name]
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
test('a step naming a workflow queues even though it is unmarked', async () => {
|
|
268
|
-
const ws = new TestWorkflowService()
|
|
269
|
-
let queued = false
|
|
270
|
-
pikkuState(null, 'package', 'singletonServices', {
|
|
271
|
-
logger: { error() {}, info() {}, warn() {}, debug() {} },
|
|
272
|
-
queueService: {
|
|
273
|
-
add: async () => {
|
|
274
|
-
queued = true
|
|
275
|
-
},
|
|
276
|
-
},
|
|
277
|
-
} as any)
|
|
278
|
-
|
|
279
|
-
setupWorkflow('childWorkflowStep')
|
|
280
|
-
const dispatched = await ws.callDispatchStep('childWorkflowStep')
|
|
281
|
-
assert.equal(dispatched, true, 'a child workflow should dispatch')
|
|
282
|
-
assert.equal(queued, true, 'a child workflow should queue')
|
|
283
|
-
cleanupWorkflow('childWorkflowStep')
|
|
284
|
-
})
|
|
285
|
-
|
|
286
|
-
test('a step naming a workflow stays inline when the parent run is inline', async () => {
|
|
287
|
-
const ws = new TestWorkflowService()
|
|
288
|
-
let queued = false
|
|
289
|
-
pikkuState(null, 'package', 'singletonServices', {
|
|
290
|
-
logger: { error() {}, info() {}, warn() {}, debug() {} },
|
|
291
|
-
queueService: {
|
|
292
|
-
add: async () => {
|
|
293
|
-
queued = true
|
|
294
|
-
},
|
|
295
|
-
},
|
|
296
|
-
} as any)
|
|
297
|
-
|
|
298
|
-
setupWorkflow('childOfInlineParent')
|
|
299
|
-
ws.markInline('inline-parent')
|
|
300
|
-
const dispatched = await ws.callDispatchStep(
|
|
301
|
-
'childOfInlineParent',
|
|
302
|
-
'inline-parent'
|
|
303
|
-
)
|
|
304
|
-
assert.equal(dispatched, false, 'an inline parent keeps its child inline')
|
|
305
|
-
assert.equal(queued, false, 'an inline parent queues nothing')
|
|
306
|
-
cleanupWorkflow('childOfInlineParent')
|
|
307
|
-
})
|
|
308
|
-
|
|
309
|
-
test('a step naming a workflow stays inline when there is no queueService', async () => {
|
|
310
|
-
const ws = new TestWorkflowService()
|
|
311
|
-
pikkuState(null, 'package', 'singletonServices', {
|
|
312
|
-
logger: { error() {}, info() {}, warn() {}, debug() {} },
|
|
313
|
-
} as any)
|
|
314
|
-
|
|
315
|
-
setupWorkflow('childWorkflowNoQueue')
|
|
316
|
-
const dispatched = await ws.callDispatchStep('childWorkflowNoQueue')
|
|
317
|
-
assert.equal(dispatched, false, 'no queue leaves the child inline')
|
|
318
|
-
cleanupWorkflow('childWorkflowNoQueue')
|
|
319
|
-
})
|
|
320
|
-
|
|
321
|
-
test('workflowQueued: true step throws when no queueService is configured', async () => {
|
|
322
|
-
const ws = new TestWorkflowService()
|
|
323
|
-
pikkuState(null, 'package', 'singletonServices', {
|
|
324
|
-
logger: { error() {}, info() {}, warn() {}, debug() {} },
|
|
325
|
-
} as any)
|
|
326
|
-
|
|
327
|
-
setupFunction('queuedStepNoQueue', true)
|
|
328
|
-
await assert.rejects(
|
|
329
|
-
() => ws.callDispatchStep('queuedStepNoQueue'),
|
|
330
|
-
/workflowQueued: true.*no queue service/i
|
|
331
|
-
)
|
|
332
|
-
cleanup('queuedStepNoQueue')
|
|
333
|
-
})
|
|
334
|
-
})
|
|
335
|
-
|
|
336
|
-
describe('pikku-workflow-service version mismatch fallback', () => {
|
|
337
|
-
test('should fall back to stored graph for dsl workflow version mismatch', async () => {
|
|
338
|
-
const ws = new InMemoryWorkflowService()
|
|
339
|
-
const workflowName = 'testDslVersionMismatch'
|
|
340
|
-
const oldHash = 'old-hash'
|
|
341
|
-
const newHash = 'new-hash'
|
|
342
|
-
|
|
343
|
-
pikkuState(null, 'package', 'singletonServices', {
|
|
344
|
-
queueService: {
|
|
345
|
-
add: async () => {},
|
|
346
|
-
},
|
|
347
|
-
} as any)
|
|
348
|
-
|
|
349
|
-
const metaState = pikkuState(null, 'workflows', 'meta')
|
|
350
|
-
metaState[workflowName] = {
|
|
351
|
-
name: workflowName,
|
|
352
|
-
pikkuFuncId: workflowName,
|
|
353
|
-
source: 'dsl',
|
|
354
|
-
graphHash: newHash,
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
await ws.upsertWorkflowVersion(
|
|
358
|
-
workflowName,
|
|
359
|
-
oldHash,
|
|
360
|
-
{
|
|
361
|
-
name: workflowName,
|
|
362
|
-
pikkuFuncId: workflowName,
|
|
363
|
-
source: 'dsl',
|
|
364
|
-
graphHash: oldHash,
|
|
365
|
-
nodes: {
|
|
366
|
-
nodeA: { nodeId: 'nodeA', rpcName: 'doA' },
|
|
367
|
-
},
|
|
368
|
-
entryNodeIds: ['nodeA'],
|
|
369
|
-
},
|
|
370
|
-
'dsl'
|
|
371
|
-
)
|
|
372
|
-
const runId = await ws.createRun(workflowName, {}, false, oldHash, {
|
|
373
|
-
type: 'test',
|
|
374
|
-
})
|
|
375
|
-
|
|
376
|
-
await ws.runWorkflowJob(runId, {})
|
|
377
|
-
|
|
378
|
-
const step = await ws.getStepState(runId, 'nodeA')
|
|
379
|
-
const run = await ws.getRun(runId)
|
|
380
|
-
assert.notEqual(step.stepId, '')
|
|
381
|
-
assert.equal(step.status, 'pending')
|
|
382
|
-
assert.equal(run?.status, 'running')
|
|
383
|
-
|
|
384
|
-
delete metaState[workflowName]
|
|
385
|
-
})
|
|
386
|
-
|
|
387
|
-
test('should continue from stored graph version when hashes mismatch', async () => {
|
|
388
|
-
const ws = new InMemoryWorkflowService()
|
|
389
|
-
const workflowName = 'testGraphVersionMismatch'
|
|
390
|
-
const oldHash = 'old-graph-hash'
|
|
391
|
-
const newHash = 'new-graph-hash'
|
|
392
|
-
|
|
393
|
-
const metaState = pikkuState(null, 'workflows', 'meta')
|
|
394
|
-
metaState[workflowName] = {
|
|
395
|
-
name: workflowName,
|
|
396
|
-
pikkuFuncId: workflowName,
|
|
397
|
-
source: 'graph',
|
|
398
|
-
graphHash: newHash,
|
|
399
|
-
nodes: {
|
|
400
|
-
changedNode: { nodeId: 'changedNode', rpcName: 'changedRpc' },
|
|
401
|
-
},
|
|
402
|
-
entryNodeIds: ['changedNode'],
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
await ws.upsertWorkflowVersion(
|
|
406
|
-
workflowName,
|
|
407
|
-
oldHash,
|
|
408
|
-
{
|
|
409
|
-
name: workflowName,
|
|
410
|
-
pikkuFuncId: workflowName,
|
|
411
|
-
source: 'graph',
|
|
412
|
-
graphHash: oldHash,
|
|
413
|
-
nodes: {},
|
|
414
|
-
entryNodeIds: [],
|
|
415
|
-
},
|
|
416
|
-
'graph'
|
|
417
|
-
)
|
|
418
|
-
|
|
419
|
-
const runId = await ws.createRun(workflowName, {}, false, oldHash, {
|
|
420
|
-
type: 'test',
|
|
421
|
-
})
|
|
422
|
-
await ws.runWorkflowJob(runId, {})
|
|
423
|
-
|
|
424
|
-
const run = await ws.getRun(runId)
|
|
425
|
-
assert.equal(run?.status, 'completed')
|
|
426
|
-
|
|
427
|
-
delete metaState[workflowName]
|
|
428
|
-
})
|
|
429
|
-
})
|
|
430
|
-
|
|
431
|
-
describe('pikku-workflow-service executeWorkflowStep', () => {
|
|
432
|
-
test('should set pending step to running before succeeding', async () => {
|
|
433
|
-
const ws = new InMemoryWorkflowService()
|
|
434
|
-
pikkuState(null, 'package', 'singletonServices', {
|
|
435
|
-
queueService: {
|
|
436
|
-
add: async () => {},
|
|
437
|
-
},
|
|
438
|
-
} as any)
|
|
439
|
-
|
|
440
|
-
const runId = await ws.createRun(
|
|
441
|
-
'pending-step-running',
|
|
442
|
-
{},
|
|
443
|
-
false,
|
|
444
|
-
'hash',
|
|
445
|
-
{ type: 'test' }
|
|
446
|
-
)
|
|
447
|
-
await ws.insertStepState(runId, 'stepA', 'doStepA', { a: 1 })
|
|
448
|
-
|
|
449
|
-
await ws.executeWorkflowStep(
|
|
450
|
-
runId,
|
|
451
|
-
'stepA',
|
|
452
|
-
'doStepA',
|
|
453
|
-
{ a: 1 },
|
|
454
|
-
{
|
|
455
|
-
rpcWithWire: async () => ({ ok: true }),
|
|
456
|
-
}
|
|
457
|
-
)
|
|
458
|
-
|
|
459
|
-
const step = await ws.getStepState(runId, 'stepA')
|
|
460
|
-
assert.equal(step.status, 'succeeded')
|
|
461
|
-
assert.ok(step.runningAt instanceof Date)
|
|
462
|
-
})
|
|
463
|
-
})
|
|
464
|
-
|
|
465
|
-
describe('pikku-workflow-service suspend', () => {
|
|
466
|
-
test('should set run status to suspended when workflow.suspend is called', async () => {
|
|
467
|
-
const ws = new InMemoryWorkflowService()
|
|
468
|
-
pikkuState(null, 'package', 'singletonServices', {
|
|
469
|
-
queueService: {
|
|
470
|
-
add: async () => {},
|
|
471
|
-
},
|
|
472
|
-
} as any)
|
|
473
|
-
|
|
474
|
-
const workflowName = 'testSuspendWorkflow'
|
|
475
|
-
const graphHash = 'suspend-hash'
|
|
476
|
-
const metaState = pikkuState(null, 'workflows', 'meta')
|
|
477
|
-
metaState[workflowName] = {
|
|
478
|
-
name: workflowName,
|
|
479
|
-
pikkuFuncId: workflowName,
|
|
480
|
-
source: 'dsl',
|
|
481
|
-
graphHash,
|
|
482
|
-
}
|
|
483
|
-
const functionMetaState = pikkuState(null, 'function', 'meta')
|
|
484
|
-
functionMetaState[workflowName] = {
|
|
485
|
-
name: workflowName,
|
|
486
|
-
sessionless: true,
|
|
487
|
-
permissions: [],
|
|
488
|
-
} as any
|
|
489
|
-
|
|
490
|
-
addWorkflow(workflowName, {
|
|
491
|
-
func: async (
|
|
492
|
-
_services: any,
|
|
493
|
-
_data: any,
|
|
494
|
-
{ workflow }: { workflow: PikkuWorkflowWire }
|
|
495
|
-
) => {
|
|
496
|
-
await workflow.suspend('Needs approval')
|
|
497
|
-
return { ok: true }
|
|
498
|
-
},
|
|
499
|
-
})
|
|
500
|
-
|
|
501
|
-
const runId = await ws.createRun(workflowName, {}, false, graphHash, {
|
|
502
|
-
type: 'test',
|
|
503
|
-
})
|
|
504
|
-
await assert.rejects(
|
|
505
|
-
ws.runWorkflowJob(runId, {}),
|
|
506
|
-
(error: unknown) => error instanceof WorkflowSuspendedException
|
|
507
|
-
)
|
|
508
|
-
|
|
509
|
-
const run = await ws.getRun(runId)
|
|
510
|
-
assert.equal(run?.status, 'suspended')
|
|
511
|
-
assert.equal(run?.error?.code, 'WORKFLOW_SUSPENDED')
|
|
512
|
-
assert.equal(run?.error?.message, 'Needs approval')
|
|
513
|
-
|
|
514
|
-
await ws.resumeWorkflow(runId)
|
|
515
|
-
await ws.runWorkflowJob(runId, {})
|
|
516
|
-
const resumedRun = await ws.getRun(runId)
|
|
517
|
-
assert.equal(resumedRun?.status, 'completed')
|
|
518
|
-
assert.deepEqual(resumedRun?.output, { ok: true })
|
|
519
|
-
|
|
520
|
-
delete metaState[workflowName]
|
|
521
|
-
delete functionMetaState[workflowName]
|
|
522
|
-
pikkuState(null, 'workflows', 'registrations').delete(workflowName)
|
|
523
|
-
})
|
|
524
|
-
|
|
525
|
-
test('should support multiple independent suspend points in one workflow', async () => {
|
|
526
|
-
const ws = new InMemoryWorkflowService()
|
|
527
|
-
pikkuState(null, 'package', 'singletonServices', {
|
|
528
|
-
queueService: {
|
|
529
|
-
add: async () => {},
|
|
530
|
-
},
|
|
531
|
-
} as any)
|
|
532
|
-
|
|
533
|
-
const workflowName = 'testMultiSuspendWorkflow'
|
|
534
|
-
const graphHash = 'multi-suspend-hash'
|
|
535
|
-
const metaState = pikkuState(null, 'workflows', 'meta')
|
|
536
|
-
metaState[workflowName] = {
|
|
537
|
-
name: workflowName,
|
|
538
|
-
pikkuFuncId: workflowName,
|
|
539
|
-
source: 'dsl',
|
|
540
|
-
graphHash,
|
|
541
|
-
}
|
|
542
|
-
const functionMetaState = pikkuState(null, 'function', 'meta')
|
|
543
|
-
functionMetaState[workflowName] = {
|
|
544
|
-
name: workflowName,
|
|
545
|
-
sessionless: true,
|
|
546
|
-
permissions: [],
|
|
547
|
-
} as any
|
|
548
|
-
|
|
549
|
-
addWorkflow(workflowName, {
|
|
550
|
-
func: async (
|
|
551
|
-
_services: any,
|
|
552
|
-
_data: any,
|
|
553
|
-
{ workflow }: { workflow: PikkuWorkflowWire }
|
|
554
|
-
) => {
|
|
555
|
-
await workflow.suspend('Building')
|
|
556
|
-
await workflow.suspend('Awaiting approval')
|
|
557
|
-
return { ok: true }
|
|
558
|
-
},
|
|
559
|
-
})
|
|
560
|
-
|
|
561
|
-
const runId = await ws.createRun(workflowName, {}, false, graphHash, {
|
|
562
|
-
type: 'test',
|
|
563
|
-
})
|
|
564
|
-
|
|
565
|
-
await assert.rejects(
|
|
566
|
-
ws.runWorkflowJob(runId, {}),
|
|
567
|
-
(error: unknown) => error instanceof WorkflowSuspendedException
|
|
568
|
-
)
|
|
569
|
-
let run = await ws.getRun(runId)
|
|
570
|
-
assert.equal(run?.status, 'suspended')
|
|
571
|
-
assert.equal(run?.error?.message, 'Building')
|
|
572
|
-
|
|
573
|
-
await ws.resumeWorkflow(runId)
|
|
574
|
-
await assert.rejects(
|
|
575
|
-
ws.runWorkflowJob(runId, {}),
|
|
576
|
-
(error: unknown) => error instanceof WorkflowSuspendedException
|
|
577
|
-
)
|
|
578
|
-
run = await ws.getRun(runId)
|
|
579
|
-
assert.equal(run?.status, 'suspended')
|
|
580
|
-
assert.equal(run?.error?.message, 'Awaiting approval')
|
|
581
|
-
|
|
582
|
-
await ws.resumeWorkflow(runId)
|
|
583
|
-
await ws.runWorkflowJob(runId, {})
|
|
584
|
-
run = await ws.getRun(runId)
|
|
585
|
-
assert.equal(run?.status, 'completed')
|
|
586
|
-
assert.deepEqual(run?.output, { ok: true })
|
|
587
|
-
|
|
588
|
-
delete metaState[workflowName]
|
|
589
|
-
delete functionMetaState[workflowName]
|
|
590
|
-
pikkuState(null, 'workflows', 'registrations').delete(workflowName)
|
|
591
|
-
})
|
|
592
|
-
})
|
|
593
|
-
|
|
594
|
-
const approvalDecisionSchema: StandardSchemaV1<
|
|
595
|
-
{ approved: boolean; comment?: string },
|
|
596
|
-
{ approved: boolean; comment?: string }
|
|
597
|
-
> = {
|
|
598
|
-
'~standard': {
|
|
599
|
-
version: 1,
|
|
600
|
-
vendor: 'test',
|
|
601
|
-
validate: (value: unknown) => {
|
|
602
|
-
if (typeof value !== 'object' || value === null) {
|
|
603
|
-
return { issues: [{ message: 'expected an object' }] }
|
|
604
|
-
}
|
|
605
|
-
const { approved, comment } = value as Record<string, unknown>
|
|
606
|
-
if (typeof approved !== 'boolean') {
|
|
607
|
-
return {
|
|
608
|
-
issues: [
|
|
609
|
-
{ message: 'approved must be a boolean', path: ['approved'] },
|
|
610
|
-
],
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
|
-
if (comment !== undefined && typeof comment !== 'string') {
|
|
614
|
-
return {
|
|
615
|
-
issues: [{ message: 'comment must be a string', path: ['comment'] }],
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
return { value: { approved, ...(comment ? { comment } : {}) } }
|
|
619
|
-
},
|
|
620
|
-
},
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
const registerApprovalWorkflow = (
|
|
624
|
-
workflowName: string,
|
|
625
|
-
graphHash: string,
|
|
626
|
-
func: (
|
|
627
|
-
services: any,
|
|
628
|
-
data: any,
|
|
629
|
-
wire: { workflow: PikkuWorkflowWire }
|
|
630
|
-
) => Promise<any>
|
|
631
|
-
) => {
|
|
632
|
-
pikkuState(null, 'package', 'singletonServices', {
|
|
633
|
-
queueService: {
|
|
634
|
-
add: async () => {},
|
|
635
|
-
},
|
|
636
|
-
} as any)
|
|
637
|
-
|
|
638
|
-
const metaState = pikkuState(null, 'workflows', 'meta')
|
|
639
|
-
metaState[workflowName] = {
|
|
640
|
-
name: workflowName,
|
|
641
|
-
pikkuFuncId: workflowName,
|
|
642
|
-
source: 'dsl',
|
|
643
|
-
graphHash,
|
|
644
|
-
}
|
|
645
|
-
const functionMetaState = pikkuState(null, 'function', 'meta')
|
|
646
|
-
functionMetaState[workflowName] = {
|
|
647
|
-
name: workflowName,
|
|
648
|
-
sessionless: true,
|
|
649
|
-
permissions: [],
|
|
650
|
-
} as any
|
|
651
|
-
|
|
652
|
-
addWorkflow(workflowName, { func })
|
|
653
|
-
|
|
654
|
-
return () => {
|
|
655
|
-
delete metaState[workflowName]
|
|
656
|
-
delete functionMetaState[workflowName]
|
|
657
|
-
pikkuState(null, 'workflows', 'registrations').delete(workflowName)
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
describe('pikku-workflow-service approval', () => {
|
|
662
|
-
test('resuming without a decision must NOT fall through the approval', async () => {
|
|
663
|
-
const ws = new InMemoryWorkflowService()
|
|
664
|
-
const workflowName = 'testApprovalNoFallthrough'
|
|
665
|
-
const graphHash = 'approval-no-fallthrough'
|
|
666
|
-
let bodyRuns = 0
|
|
667
|
-
|
|
668
|
-
const cleanup = registerApprovalWorkflow(
|
|
669
|
-
workflowName,
|
|
670
|
-
graphHash,
|
|
671
|
-
async (_services, _data, { workflow }) => {
|
|
672
|
-
bodyRuns++
|
|
673
|
-
const decision = await workflow.approval('Approve invoice', {
|
|
674
|
-
schema: approvalDecisionSchema,
|
|
675
|
-
})
|
|
676
|
-
return { decision }
|
|
677
|
-
}
|
|
678
|
-
)
|
|
679
|
-
|
|
680
|
-
const runId = await ws.createRun(workflowName, {}, false, graphHash, {
|
|
681
|
-
type: 'test',
|
|
682
|
-
})
|
|
683
|
-
|
|
684
|
-
await assert.rejects(
|
|
685
|
-
ws.runWorkflowJob(runId, {}),
|
|
686
|
-
(error: unknown) => error instanceof WorkflowSuspendedException
|
|
687
|
-
)
|
|
688
|
-
assert.equal((await ws.getRun(runId))?.status, 'suspended')
|
|
689
|
-
|
|
690
|
-
await ws.resumeWorkflow(runId)
|
|
691
|
-
await assert.rejects(
|
|
692
|
-
ws.runWorkflowJob(runId, {}),
|
|
693
|
-
(error: unknown) => error instanceof WorkflowSuspendedException
|
|
694
|
-
)
|
|
695
|
-
assert.equal((await ws.getRun(runId))?.status, 'suspended')
|
|
696
|
-
assert.equal(bodyRuns, 2)
|
|
697
|
-
|
|
698
|
-
cleanup()
|
|
699
|
-
})
|
|
700
|
-
|
|
701
|
-
test('approveStep records a decision the workflow then returns', async () => {
|
|
702
|
-
const ws = new InMemoryWorkflowService()
|
|
703
|
-
const workflowName = 'testApprovalDecision'
|
|
704
|
-
const graphHash = 'approval-decision'
|
|
705
|
-
|
|
706
|
-
const cleanup = registerApprovalWorkflow(
|
|
707
|
-
workflowName,
|
|
708
|
-
graphHash,
|
|
709
|
-
async (_services, _data, { workflow }) => {
|
|
710
|
-
const decision = await workflow.approval('Approve invoice', {
|
|
711
|
-
schema: approvalDecisionSchema,
|
|
712
|
-
})
|
|
713
|
-
return { decision }
|
|
714
|
-
}
|
|
715
|
-
)
|
|
716
|
-
|
|
717
|
-
const runId = await ws.createRun(workflowName, {}, false, graphHash, {
|
|
718
|
-
type: 'test',
|
|
719
|
-
})
|
|
720
|
-
await assert.rejects(
|
|
721
|
-
ws.runWorkflowJob(runId, {}),
|
|
722
|
-
(error: unknown) => error instanceof WorkflowSuspendedException
|
|
723
|
-
)
|
|
724
|
-
|
|
725
|
-
await ws.approveStep(runId, 'Approve invoice', {
|
|
726
|
-
approved: true,
|
|
727
|
-
comment: 'lgtm',
|
|
728
|
-
})
|
|
729
|
-
await ws.runWorkflowJob(runId, {})
|
|
730
|
-
|
|
731
|
-
const run = await ws.getRun(runId)
|
|
732
|
-
assert.equal(run?.status, 'completed')
|
|
733
|
-
const decision = (run?.output as any)?.decision
|
|
734
|
-
assert.equal(decision.status, 'decided')
|
|
735
|
-
assert.deepEqual(decision.data, { approved: true, comment: 'lgtm' })
|
|
736
|
-
|
|
737
|
-
cleanup()
|
|
738
|
-
})
|
|
739
|
-
|
|
740
|
-
test('approveStep rejects a payload that fails the schema', async () => {
|
|
741
|
-
const ws = new InMemoryWorkflowService()
|
|
742
|
-
const workflowName = 'testApprovalSchema'
|
|
743
|
-
const graphHash = 'approval-schema'
|
|
744
|
-
|
|
745
|
-
const cleanup = registerApprovalWorkflow(
|
|
746
|
-
workflowName,
|
|
747
|
-
graphHash,
|
|
748
|
-
async (_services, _data, { workflow }) => {
|
|
749
|
-
const decision = await workflow.approval('Approve invoice', {
|
|
750
|
-
schema: approvalDecisionSchema,
|
|
751
|
-
})
|
|
752
|
-
return { decision }
|
|
753
|
-
}
|
|
754
|
-
)
|
|
755
|
-
|
|
756
|
-
const runId = await ws.createRun(workflowName, {}, false, graphHash, {
|
|
757
|
-
type: 'test',
|
|
758
|
-
})
|
|
759
|
-
await assert.rejects(
|
|
760
|
-
ws.runWorkflowJob(runId, {}),
|
|
761
|
-
(error: unknown) => error instanceof WorkflowSuspendedException
|
|
762
|
-
)
|
|
763
|
-
|
|
764
|
-
await ws.approveStep(runId, 'Approve invoice', { approved: 'yes-please' })
|
|
765
|
-
|
|
766
|
-
await assert.rejects(
|
|
767
|
-
ws.runWorkflowJob(runId, {}),
|
|
768
|
-
(error: unknown) => error instanceof WorkflowSuspendedException
|
|
769
|
-
)
|
|
770
|
-
assert.equal((await ws.getRun(runId))?.status, 'suspended')
|
|
771
|
-
|
|
772
|
-
const state = await ws.getRunState(runId)
|
|
773
|
-
assert.match(
|
|
774
|
-
JSON.stringify(state),
|
|
775
|
-
/approved/,
|
|
776
|
-
'expected the validation failure to be recorded in run state'
|
|
777
|
-
)
|
|
778
|
-
|
|
779
|
-
await ws.approveStep(runId, 'Approve invoice', { approved: false })
|
|
780
|
-
await ws.runWorkflowJob(runId, {})
|
|
781
|
-
const run = await ws.getRun(runId)
|
|
782
|
-
assert.equal(run?.status, 'completed')
|
|
783
|
-
const decision = (run?.output as any)?.decision
|
|
784
|
-
assert.equal(decision.status, 'decided')
|
|
785
|
-
assert.deepEqual(decision.data, { approved: false })
|
|
786
|
-
|
|
787
|
-
cleanup()
|
|
788
|
-
})
|
|
789
|
-
|
|
790
|
-
test('an expired approval returns { status: expired } instead of hanging', async () => {
|
|
791
|
-
const ws = new InMemoryWorkflowService()
|
|
792
|
-
const workflowName = 'testApprovalExpiry'
|
|
793
|
-
const graphHash = 'approval-expiry'
|
|
794
|
-
|
|
795
|
-
const cleanup = registerApprovalWorkflow(
|
|
796
|
-
workflowName,
|
|
797
|
-
graphHash,
|
|
798
|
-
async (_services, _data, { workflow }) => {
|
|
799
|
-
const decision = await workflow.approval('Approve invoice', {
|
|
800
|
-
schema: approvalDecisionSchema,
|
|
801
|
-
expiry: '10ms',
|
|
802
|
-
})
|
|
803
|
-
return { decision }
|
|
804
|
-
}
|
|
805
|
-
)
|
|
806
|
-
|
|
807
|
-
const runId = await ws.createRun(workflowName, {}, false, graphHash, {
|
|
808
|
-
type: 'test',
|
|
809
|
-
})
|
|
810
|
-
await assert.rejects(
|
|
811
|
-
ws.runWorkflowJob(runId, {}),
|
|
812
|
-
(error: unknown) => error instanceof WorkflowSuspendedException
|
|
813
|
-
)
|
|
814
|
-
|
|
815
|
-
await new Promise((resolve) => setTimeout(resolve, 25))
|
|
816
|
-
|
|
817
|
-
await ws.resumeWorkflow(runId)
|
|
818
|
-
await ws.runWorkflowJob(runId, {})
|
|
819
|
-
|
|
820
|
-
const run = await ws.getRun(runId)
|
|
821
|
-
assert.equal(run?.status, 'completed')
|
|
822
|
-
assert.deepEqual(run?.output, { decision: { status: 'expired' } })
|
|
823
|
-
|
|
824
|
-
cleanup()
|
|
825
|
-
})
|
|
826
|
-
|
|
827
|
-
test('a decision arriving after the gate resolved is rejected, not dropped', async () => {
|
|
828
|
-
const ws = new InMemoryWorkflowService()
|
|
829
|
-
const workflowName = 'testApprovalAfterResolved'
|
|
830
|
-
const graphHash = 'approval-after-resolved'
|
|
831
|
-
|
|
832
|
-
const cleanup = registerApprovalWorkflow(
|
|
833
|
-
workflowName,
|
|
834
|
-
graphHash,
|
|
835
|
-
async (_services, _data, { workflow }) => {
|
|
836
|
-
const decision = await workflow.approval('Approve invoice', {
|
|
837
|
-
schema: approvalDecisionSchema,
|
|
838
|
-
expiry: '10ms',
|
|
839
|
-
})
|
|
840
|
-
return { decision }
|
|
841
|
-
}
|
|
842
|
-
)
|
|
843
|
-
|
|
844
|
-
const runId = await ws.createRun(workflowName, {}, false, graphHash, {
|
|
845
|
-
type: 'test',
|
|
846
|
-
})
|
|
847
|
-
await assert.rejects(
|
|
848
|
-
ws.runWorkflowJob(runId, {}),
|
|
849
|
-
(error: unknown) => error instanceof WorkflowSuspendedException
|
|
850
|
-
)
|
|
851
|
-
|
|
852
|
-
await new Promise((resolve) => setTimeout(resolve, 25))
|
|
853
|
-
await ws.resumeWorkflow(runId)
|
|
854
|
-
await ws.runWorkflowJob(runId, {})
|
|
855
|
-
assert.equal((await ws.getRun(runId))?.status, 'completed')
|
|
856
|
-
|
|
857
|
-
await assert.rejects(
|
|
858
|
-
ws.approveStep(runId, 'Approve invoice', { approved: true }),
|
|
859
|
-
(error: unknown) =>
|
|
860
|
-
error instanceof WorkflowApprovalResolvedError &&
|
|
861
|
-
error.payload.outcome === 'expired'
|
|
862
|
-
)
|
|
863
|
-
|
|
864
|
-
const run = await ws.getRun(runId)
|
|
865
|
-
assert.deepEqual(run?.output, { decision: { status: 'expired' } })
|
|
866
|
-
|
|
867
|
-
cleanup()
|
|
868
|
-
})
|
|
869
|
-
|
|
870
|
-
test('a decision that landed before expiry wins over the expiry', async () => {
|
|
871
|
-
const ws = new InMemoryWorkflowService()
|
|
872
|
-
const workflowName = 'testApprovalExpiryRace'
|
|
873
|
-
const graphHash = 'approval-expiry-race'
|
|
874
|
-
|
|
875
|
-
const cleanup = registerApprovalWorkflow(
|
|
876
|
-
workflowName,
|
|
877
|
-
graphHash,
|
|
878
|
-
async (_services, _data, { workflow }) => {
|
|
879
|
-
const decision = await workflow.approval('Approve invoice', {
|
|
880
|
-
schema: approvalDecisionSchema,
|
|
881
|
-
expiry: '10ms',
|
|
882
|
-
})
|
|
883
|
-
return { decision }
|
|
884
|
-
}
|
|
885
|
-
)
|
|
886
|
-
|
|
887
|
-
const runId = await ws.createRun(workflowName, {}, false, graphHash, {
|
|
888
|
-
type: 'test',
|
|
889
|
-
})
|
|
890
|
-
await assert.rejects(
|
|
891
|
-
ws.runWorkflowJob(runId, {}),
|
|
892
|
-
(error: unknown) => error instanceof WorkflowSuspendedException
|
|
893
|
-
)
|
|
894
|
-
|
|
895
|
-
await ws.approveStep(runId, 'Approve invoice', { approved: true })
|
|
896
|
-
|
|
897
|
-
await new Promise((resolve) => setTimeout(resolve, 25))
|
|
898
|
-
await ws.resumeWorkflow(runId)
|
|
899
|
-
await ws.runWorkflowJob(runId, {})
|
|
900
|
-
|
|
901
|
-
const run = await ws.getRun(runId)
|
|
902
|
-
assert.equal(run?.status, 'completed')
|
|
903
|
-
const decision = (run?.output as any)?.decision
|
|
904
|
-
assert.equal(decision.status, 'decided')
|
|
905
|
-
assert.deepEqual(decision.data, { approved: true })
|
|
906
|
-
// Answered with no session, so there is nobody to name — but when the
|
|
907
|
-
// answer arrived is recorded either way.
|
|
908
|
-
assert.equal(decision.decidedBy, undefined)
|
|
909
|
-
assert.ok(!Number.isNaN(Date.parse(decision.decidedAt)))
|
|
910
|
-
|
|
911
|
-
cleanup()
|
|
912
|
-
})
|
|
913
|
-
})
|
|
914
|
-
|
|
915
|
-
describe('pikku-workflow-service run identity on failure', () => {
|
|
916
|
-
const runFailing = async (name: string) => {
|
|
917
|
-
resetPikkuState()
|
|
918
|
-
const ws = new InMemoryWorkflowService()
|
|
919
|
-
pikkuState(null, 'package', 'singletonServices', {
|
|
920
|
-
logger: { error() {}, info() {}, warn() {}, debug() {} },
|
|
921
|
-
} as any)
|
|
922
|
-
|
|
923
|
-
const metaState = pikkuState(null, 'workflows', 'meta')
|
|
924
|
-
metaState[name] = {
|
|
925
|
-
name,
|
|
926
|
-
pikkuFuncId: name,
|
|
927
|
-
source: 'scenario',
|
|
928
|
-
graphHash: `${name}-hash`,
|
|
929
|
-
} as any
|
|
930
|
-
pikkuState(null, 'function', 'meta')[name] = {
|
|
931
|
-
name,
|
|
932
|
-
sessionless: true,
|
|
933
|
-
permissions: [],
|
|
934
|
-
} as any
|
|
935
|
-
|
|
936
|
-
addWorkflow(name, {
|
|
937
|
-
func: async () => {
|
|
938
|
-
throw new Error('the scenario blew up')
|
|
939
|
-
},
|
|
940
|
-
} as any)
|
|
941
|
-
|
|
942
|
-
const created: string[] = []
|
|
943
|
-
let error: any
|
|
944
|
-
try {
|
|
945
|
-
await ws.startWorkflow(name, {}, {} as any, {}, {
|
|
946
|
-
onRunCreated: (runId: string) => created.push(runId),
|
|
947
|
-
} as any)
|
|
948
|
-
} catch (e: any) {
|
|
949
|
-
error = e
|
|
950
|
-
}
|
|
951
|
-
return { ws, created, error }
|
|
952
|
-
}
|
|
953
|
-
|
|
954
|
-
test('reports the run id of a run that fails inline', async () => {
|
|
955
|
-
const { ws, created, error } = await runFailing('onRunCreatedFailing')
|
|
956
|
-
|
|
957
|
-
assert.equal(error?.message, 'the scenario blew up')
|
|
958
|
-
assert.equal(created.length, 1, 'the run existed, so its id must be known')
|
|
959
|
-
const run = await ws.getRun(created[0]!)
|
|
960
|
-
assert.equal(run?.status, 'failed')
|
|
961
|
-
assert.equal(run?.error?.message, 'the scenario blew up')
|
|
962
|
-
})
|
|
963
|
-
})
|