@pikku/core 0.11.2 → 0.12.1
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 +57 -2
- package/dist/crypto-utils.d.ts +2 -0
- package/dist/crypto-utils.js +78 -0
- package/dist/errors/errors.d.ts +14 -0
- package/dist/errors/errors.js +26 -0
- package/dist/errors/index.d.ts +1 -1
- package/dist/errors/index.js +1 -1
- package/dist/function/function-runner.d.ts +10 -4
- package/dist/function/function-runner.js +126 -45
- package/dist/function/functions.types.d.ts +32 -87
- package/dist/function/functions.types.js +16 -46
- package/dist/function/index.d.ts +2 -2
- package/dist/function/index.js +1 -2
- package/dist/handle-error.d.ts +2 -2
- package/dist/handle-error.js +3 -12
- package/dist/index.d.ts +30 -26
- package/dist/index.js +19 -29
- package/dist/internal.d.ts +3 -0
- package/dist/internal.js +2 -0
- package/dist/middleware/auth-apikey.d.ts +2 -2
- package/dist/middleware/auth-apikey.js +3 -3
- package/dist/middleware/auth-bearer.d.ts +3 -3
- package/dist/middleware/auth-bearer.js +4 -7
- package/dist/middleware/auth-cookie.d.ts +4 -4
- package/dist/middleware/auth-cookie.js +7 -9
- package/dist/middleware/cors.d.ts +46 -0
- package/dist/middleware/cors.js +81 -0
- package/dist/middleware/index.d.ts +5 -3
- package/dist/middleware/index.js +5 -3
- package/dist/middleware/remote-auth.d.ts +5 -0
- package/dist/middleware/remote-auth.js +55 -0
- package/dist/middleware/timeout.d.ts +2 -2
- package/dist/middleware-runner.d.ts +1 -1
- package/dist/middleware-runner.js +8 -10
- package/dist/permissions.d.ts +2 -2
- package/dist/permissions.js +11 -15
- package/dist/pikku-state.d.ts +10 -8
- package/dist/pikku-state.js +48 -25
- package/dist/schema.d.ts +4 -4
- package/dist/schema.js +20 -15
- package/dist/services/ai-agent-runner-service.d.ts +43 -0
- package/dist/services/ai-agent-runner-service.js +1 -0
- package/dist/services/ai-run-state-service.d.ts +13 -0
- package/dist/services/ai-run-state-service.js +1 -0
- package/dist/services/ai-storage-service.d.ts +18 -0
- package/dist/services/ai-storage-service.js +1 -0
- package/dist/services/content-service.d.ts +6 -0
- package/dist/services/deployment-service.d.ts +19 -0
- package/dist/services/deployment-service.js +1 -0
- package/dist/services/gopass-secrets.d.ts +47 -0
- package/dist/services/gopass-secrets.js +97 -0
- package/dist/services/in-memory-ai-run-state-service.d.ts +15 -0
- package/dist/services/in-memory-ai-run-state-service.js +44 -0
- package/dist/services/in-memory-trigger-service.d.ts +22 -0
- package/dist/services/in-memory-trigger-service.js +48 -0
- package/dist/services/in-memory-workflow-service.d.ts +59 -0
- package/dist/services/in-memory-workflow-service.js +287 -0
- package/dist/services/index.d.ts +26 -11
- package/dist/services/index.js +11 -13
- package/dist/services/local-content.d.ts +2 -1
- package/dist/services/local-content.js +6 -1
- package/dist/services/local-secrets.d.ts +25 -2
- package/dist/services/local-secrets.js +45 -0
- package/dist/services/local-variables.d.ts +6 -1
- package/dist/services/local-variables.js +18 -0
- package/dist/services/logger-console.d.ts +2 -1
- package/dist/services/scheduler-service.d.ts +9 -1
- package/dist/services/scheduler-service.js +8 -0
- package/dist/services/schema-service.d.ts +6 -0
- package/dist/services/scoped-secret-service.d.ts +16 -0
- package/dist/services/scoped-secret-service.js +35 -0
- package/dist/services/secret-service.d.ts +25 -4
- package/dist/services/trigger-service.d.ts +16 -0
- package/dist/services/trigger-service.js +1 -0
- package/dist/services/typed-secret-service.d.ts +30 -0
- package/dist/services/typed-secret-service.js +40 -0
- package/dist/services/typed-variables-service.d.ts +27 -0
- package/dist/services/typed-variables-service.js +46 -0
- package/dist/services/user-session-service.d.ts +15 -2
- package/dist/services/user-session-service.js +17 -0
- package/dist/services/variables-service.d.ts +5 -0
- package/dist/services/workflow-service.d.ts +9 -5
- package/dist/types/core.types.d.ts +67 -25
- package/dist/types/core.types.js +8 -1
- package/dist/types/state.types.d.ts +53 -59
- package/dist/utils.d.ts +7 -6
- package/dist/utils.js +27 -12
- package/dist/version.d.ts +6 -0
- package/dist/version.js +19 -0
- package/dist/wirings/ai-agent/ai-agent-assistant-ui.d.ts +5 -0
- package/dist/wirings/ai-agent/ai-agent-assistant-ui.js +146 -0
- package/dist/wirings/ai-agent/ai-agent-helpers.d.ts +28 -0
- package/dist/wirings/ai-agent/ai-agent-helpers.js +40 -0
- package/dist/wirings/ai-agent/ai-agent-memory.d.ts +29 -0
- package/dist/wirings/ai-agent/ai-agent-memory.js +199 -0
- package/dist/wirings/ai-agent/ai-agent-model-config.d.ts +9 -0
- package/dist/wirings/ai-agent/ai-agent-model-config.js +36 -0
- package/dist/wirings/ai-agent/ai-agent-prepare.d.ts +59 -0
- package/dist/wirings/ai-agent/ai-agent-prepare.js +348 -0
- package/dist/wirings/ai-agent/ai-agent-registry.d.ts +15 -0
- package/dist/wirings/ai-agent/ai-agent-registry.js +47 -0
- package/dist/wirings/ai-agent/ai-agent-runner.d.ts +3 -0
- package/dist/wirings/ai-agent/ai-agent-runner.js +195 -0
- package/dist/wirings/ai-agent/ai-agent-stream.d.ts +12 -0
- package/dist/wirings/ai-agent/ai-agent-stream.js +662 -0
- package/dist/wirings/ai-agent/ai-agent.types.d.ts +313 -0
- package/dist/wirings/ai-agent/ai-agent.types.js +1 -0
- package/dist/wirings/ai-agent/index.d.ts +7 -0
- package/dist/wirings/ai-agent/index.js +6 -0
- package/dist/wirings/channel/channel-common.d.ts +8 -5
- package/dist/wirings/channel/channel-common.js +15 -8
- package/dist/wirings/channel/channel-handler.d.ts +3 -3
- package/dist/wirings/channel/channel-handler.js +15 -6
- package/dist/wirings/channel/channel-middleware-runner.d.ts +9 -0
- package/dist/wirings/channel/channel-middleware-runner.js +73 -0
- package/dist/wirings/channel/channel-runner.d.ts +5 -5
- package/dist/wirings/channel/channel-runner.js +10 -9
- package/dist/wirings/channel/channel-store.d.ts +1 -1
- package/dist/wirings/channel/channel.types.d.ts +9 -7
- package/dist/wirings/channel/define-channel-routes.d.ts +21 -0
- package/dist/wirings/channel/define-channel-routes.js +23 -0
- package/dist/wirings/channel/index.d.ts +10 -8
- package/dist/wirings/channel/index.js +7 -8
- package/dist/wirings/channel/local/index.d.ts +3 -3
- package/dist/wirings/channel/local/index.js +3 -3
- package/dist/wirings/channel/local/local-channel-runner.d.ts +7 -2
- package/dist/wirings/channel/local/local-channel-runner.js +22 -9
- package/dist/wirings/channel/local/local-eventhub-service.d.ts +2 -2
- package/dist/wirings/channel/log-channels.d.ts +1 -1
- package/dist/wirings/channel/pikku-abstract-channel-handler.d.ts +1 -1
- package/dist/wirings/channel/serverless/index.d.ts +1 -1
- package/dist/wirings/channel/serverless/index.js +1 -1
- package/dist/wirings/channel/serverless/serverless-channel-runner.d.ts +4 -4
- package/dist/wirings/channel/serverless/serverless-channel-runner.js +40 -23
- package/dist/wirings/cli/channel/cli-channel-runner.d.ts +1 -1
- package/dist/wirings/cli/channel/index.d.ts +1 -1
- package/dist/wirings/cli/channel/index.js +1 -1
- package/dist/wirings/cli/cli-runner.d.ts +3 -3
- package/dist/wirings/cli/cli-runner.js +12 -8
- package/dist/wirings/cli/cli.types.d.ts +9 -9
- package/dist/wirings/cli/command-parser.d.ts +1 -1
- package/dist/wirings/cli/define-cli-commands.d.ts +19 -0
- package/dist/wirings/cli/define-cli-commands.js +20 -0
- package/dist/wirings/cli/index.d.ts +2 -3
- package/dist/wirings/cli/index.js +1 -3
- package/dist/wirings/http/http-routes.d.ts +69 -0
- package/dist/wirings/http/http-routes.js +139 -0
- package/dist/wirings/http/http-runner.d.ts +9 -9
- package/dist/wirings/http/http-runner.js +79 -34
- package/dist/wirings/http/http.types.d.ts +77 -41
- package/dist/wirings/http/index.d.ts +5 -4
- package/dist/wirings/http/index.js +4 -3
- package/dist/wirings/http/log-http-routes.d.ts +1 -1
- package/dist/wirings/http/pikku-fetch-http-request.d.ts +1 -1
- package/dist/wirings/http/pikku-fetch-http-response.d.ts +2 -2
- package/dist/wirings/http/pikku-fetch-http-response.js +6 -1
- package/dist/wirings/http/routers/http-router.d.ts +1 -1
- package/dist/wirings/http/routers/path-to-regex.d.ts +2 -2
- package/dist/wirings/mcp/index.d.ts +4 -3
- package/dist/wirings/mcp/index.js +3 -3
- package/dist/wirings/mcp/mcp-endpoint-registry.d.ts +1 -1
- package/dist/wirings/mcp/mcp-runner.d.ts +1 -6
- package/dist/wirings/mcp/mcp-runner.js +28 -40
- package/dist/wirings/mcp/mcp.types.d.ts +5 -5
- package/dist/wirings/node/index.d.ts +2 -0
- package/dist/wirings/node/index.js +1 -0
- package/dist/wirings/node/node.types.d.ts +20 -0
- package/dist/wirings/node/node.types.js +1 -0
- package/dist/wirings/oauth2/index.d.ts +3 -0
- package/dist/wirings/oauth2/index.js +2 -0
- package/dist/wirings/oauth2/oauth2-client.d.ts +47 -0
- package/dist/wirings/oauth2/oauth2-client.js +267 -0
- package/dist/wirings/oauth2/oauth2.types.d.ts +65 -0
- package/dist/wirings/oauth2/oauth2.types.js +4 -0
- package/dist/wirings/oauth2/wire-oauth2-credential.d.ts +20 -0
- package/dist/wirings/oauth2/wire-oauth2-credential.js +21 -0
- package/dist/wirings/queue/index.d.ts +1 -1
- package/dist/wirings/queue/queue-runner.d.ts +1 -5
- package/dist/wirings/queue/queue-runner.js +11 -8
- package/dist/wirings/queue/queue.types.d.ts +5 -5
- package/dist/wirings/queue/register-queue-helper.d.ts +2 -2
- package/dist/wirings/queue/register-queue-helper.js +1 -1
- package/dist/wirings/queue/validate-worker-config.d.ts +1 -1
- package/dist/wirings/rpc/index.d.ts +3 -1
- package/dist/wirings/rpc/index.js +2 -1
- package/dist/wirings/rpc/rpc-runner.d.ts +58 -8
- package/dist/wirings/rpc/rpc-runner.js +177 -31
- package/dist/wirings/rpc/rpc-types.d.ts +20 -4
- package/dist/wirings/rpc/wire-addon.d.ts +10 -0
- package/dist/wirings/rpc/wire-addon.js +9 -0
- package/dist/wirings/scheduler/index.d.ts +2 -2
- package/dist/wirings/scheduler/index.js +1 -2
- package/dist/wirings/scheduler/log-schedulers.d.ts +1 -1
- package/dist/wirings/scheduler/scheduler-runner.d.ts +3 -5
- package/dist/wirings/scheduler/scheduler-runner.js +11 -14
- package/dist/wirings/scheduler/scheduler.types.d.ts +2 -2
- package/dist/wirings/secret/index.d.ts +3 -0
- package/dist/wirings/secret/index.js +2 -0
- package/dist/wirings/secret/secret.types.d.ts +27 -0
- package/dist/wirings/secret/secret.types.js +1 -0
- package/dist/wirings/secret/validate-secret-definitions.d.ts +6 -0
- package/dist/wirings/secret/validate-secret-definitions.js +55 -0
- package/dist/wirings/trigger/index.d.ts +3 -2
- package/dist/wirings/trigger/index.js +2 -2
- package/dist/wirings/trigger/pikku-trigger-service.d.ts +22 -0
- package/dist/wirings/trigger/pikku-trigger-service.js +70 -0
- package/dist/wirings/trigger/trigger-runner.d.ts +18 -9
- package/dist/wirings/trigger/trigger-runner.js +48 -19
- package/dist/wirings/trigger/trigger.types.d.ts +99 -11
- package/dist/wirings/trigger/trigger.types.js +40 -1
- package/dist/wirings/variable/index.d.ts +3 -0
- package/dist/wirings/variable/index.js +2 -0
- package/dist/wirings/variable/validate-variable-definitions.d.ts +6 -0
- package/dist/wirings/variable/validate-variable-definitions.js +45 -0
- package/dist/wirings/variable/variable.types.d.ts +18 -0
- package/dist/wirings/variable/variable.types.js +1 -0
- package/dist/wirings/workflow/dsl/index.d.ts +1 -1
- package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +7 -1
- package/dist/wirings/workflow/dsl/workflow-runner.js +3 -2
- package/dist/wirings/workflow/graph/graph-node.d.ts +1 -6
- package/dist/wirings/workflow/graph/graph-runner.d.ts +5 -31
- package/dist/wirings/workflow/graph/graph-runner.js +384 -296
- package/dist/wirings/workflow/graph/index.d.ts +4 -3
- package/dist/wirings/workflow/graph/index.js +3 -3
- package/dist/wirings/workflow/graph/template.d.ts +15 -0
- package/dist/wirings/workflow/graph/template.js +27 -0
- package/dist/wirings/workflow/graph/wire-workflow-graph.d.ts +15 -0
- package/dist/wirings/workflow/graph/wire-workflow-graph.js +8 -0
- package/dist/wirings/workflow/graph/workflow-graph.types.d.ts +0 -13
- package/dist/wirings/workflow/index.d.ts +6 -6
- package/dist/wirings/workflow/index.js +6 -4
- package/dist/wirings/workflow/pikku-workflow-service.d.ts +29 -19
- package/dist/wirings/workflow/pikku-workflow-service.js +217 -82
- package/dist/wirings/workflow/workflow-helpers.d.ts +36 -0
- package/dist/wirings/workflow/workflow-helpers.js +38 -0
- package/dist/wirings/workflow/workflow.types.d.ts +42 -95
- package/package.json +14 -15
- package/run-tests.sh +4 -1
- package/src/crypto-utils.test.ts +116 -0
- package/src/crypto-utils.ts +99 -0
- package/src/errors/error.test.ts +143 -2
- package/src/errors/errors.ts +27 -0
- package/src/errors/index.ts +1 -1
- package/src/factory-functions.test.ts +42 -2
- package/src/function/function-runner.test.ts +6 -13
- package/src/function/function-runner.ts +161 -53
- package/src/function/functions.types.ts +63 -132
- package/src/function/index.ts +5 -2
- package/src/handle-error.test.ts +361 -0
- package/src/handle-error.ts +6 -14
- package/src/index.ts +97 -30
- package/src/internal.ts +6 -0
- package/src/middleware/auth-apikey.test.ts +16 -13
- package/src/middleware/auth-apikey.ts +3 -3
- package/src/middleware/auth-bearer.test.ts +18 -15
- package/src/middleware/auth-bearer.ts +27 -32
- package/src/middleware/auth-cookie.test.ts +17 -14
- package/src/middleware/auth-cookie.ts +9 -13
- package/src/middleware/cors.test.ts +424 -0
- package/src/middleware/cors.ts +104 -0
- package/src/middleware/index.ts +5 -3
- package/src/middleware/remote-auth.test.ts +488 -0
- package/src/middleware/remote-auth.ts +68 -0
- package/src/middleware-runner.test.ts +123 -1
- package/src/middleware-runner.ts +13 -13
- package/src/permissions.test.ts +83 -9
- package/src/permissions.ts +17 -19
- package/src/pikku-state.test.ts +224 -0
- package/src/pikku-state.ts +59 -35
- package/src/run-tests-script.test.ts +49 -0
- package/src/schema.test.ts +198 -6
- package/src/schema.ts +28 -21
- package/src/services/ai-agent-runner-service.ts +41 -0
- package/src/services/ai-run-state-service.ts +20 -0
- package/src/services/ai-storage-service.ts +39 -0
- package/src/services/content-service.ts +7 -0
- package/src/services/deployment-service.ts +22 -0
- package/src/services/gopass-secrets.ts +98 -0
- package/src/services/in-memory-ai-run-state-service.ts +73 -0
- package/src/services/in-memory-trigger-service.ts +64 -0
- package/src/services/in-memory-workflow-service.test.ts +351 -0
- package/src/services/in-memory-workflow-service.ts +395 -0
- package/src/services/index.ts +50 -14
- package/src/services/local-content.ts +9 -3
- package/src/services/local-secrets.test.ts +80 -0
- package/src/services/local-secrets.ts +53 -2
- package/src/services/local-variables.test.ts +61 -0
- package/src/services/local-variables.ts +23 -1
- package/src/services/logger-console.test.ts +118 -0
- package/src/services/logger-console.ts +2 -1
- package/src/services/scheduler-service.ts +11 -1
- package/src/services/schema-service.ts +7 -0
- package/src/services/scoped-secret-service.test.ts +74 -0
- package/src/services/scoped-secret-service.ts +41 -0
- package/src/services/secret-service.ts +25 -4
- package/src/services/trigger-service.ts +17 -0
- package/src/services/typed-secret-service.test.ts +93 -0
- package/src/services/typed-secret-service.ts +70 -0
- package/src/services/typed-variables-service.test.ts +73 -0
- package/src/services/typed-variables-service.ts +81 -0
- package/src/services/user-session-service.test.ts +113 -0
- package/src/services/user-session-service.ts +25 -2
- package/src/services/variables-service.ts +5 -0
- package/src/services/workflow-service.ts +23 -13
- package/src/time-utils.test.ts +1 -1
- package/src/types/core.types.ts +95 -24
- package/src/types/state.types.ts +56 -73
- package/src/utils.test.ts +350 -0
- package/src/utils.ts +33 -18
- package/src/version.test.ts +80 -0
- package/src/version.ts +25 -0
- package/src/wirings/ai-agent/ai-agent-assistant-ui.test.ts +363 -0
- package/src/wirings/ai-agent/ai-agent-assistant-ui.ts +214 -0
- package/src/wirings/ai-agent/ai-agent-helpers.test.ts +152 -0
- package/src/wirings/ai-agent/ai-agent-helpers.ts +76 -0
- package/src/wirings/ai-agent/ai-agent-memory.ts +300 -0
- package/src/wirings/ai-agent/ai-agent-model-config.test.ts +115 -0
- package/src/wirings/ai-agent/ai-agent-model-config.ts +43 -0
- package/src/wirings/ai-agent/ai-agent-prepare.ts +504 -0
- package/src/wirings/ai-agent/ai-agent-registry.test.ts +37 -0
- package/src/wirings/ai-agent/ai-agent-registry.ts +82 -0
- package/src/wirings/ai-agent/ai-agent-runner.test.ts +317 -0
- package/src/wirings/ai-agent/ai-agent-runner.ts +251 -0
- package/src/wirings/ai-agent/ai-agent-stream.test.ts +652 -0
- package/src/wirings/ai-agent/ai-agent-stream.ts +1049 -0
- package/src/wirings/ai-agent/ai-agent.types.ts +328 -0
- package/src/wirings/ai-agent/index.ts +39 -0
- package/src/wirings/channel/channel-common.ts +33 -20
- package/src/wirings/channel/channel-handler.ts +26 -9
- package/src/wirings/channel/channel-middleware-runner.ts +119 -0
- package/src/wirings/channel/channel-runner.ts +15 -16
- package/src/wirings/channel/channel-store.ts +1 -1
- package/src/wirings/channel/channel.types.ts +21 -9
- package/src/wirings/channel/define-channel-routes.ts +25 -0
- package/src/wirings/channel/index.ts +23 -8
- package/src/wirings/channel/local/index.ts +3 -3
- package/src/wirings/channel/local/local-channel-runner.test.ts +57 -7
- package/src/wirings/channel/local/local-channel-runner.ts +40 -19
- package/src/wirings/channel/local/local-eventhub-service.test.ts +2 -2
- package/src/wirings/channel/local/local-eventhub-service.ts +2 -2
- package/src/wirings/channel/log-channels.ts +1 -1
- package/src/wirings/channel/pikku-abstract-channel-handler.ts +1 -1
- package/src/wirings/channel/serverless/index.ts +5 -1
- package/src/wirings/channel/serverless/serverless-channel-runner.ts +57 -36
- package/src/wirings/cli/channel/cli-channel-runner.ts +1 -1
- package/src/wirings/cli/channel/index.ts +1 -1
- package/src/wirings/cli/cli-runner.test.ts +10 -10
- package/src/wirings/cli/cli-runner.ts +28 -14
- package/src/wirings/cli/cli.types.ts +14 -14
- package/src/wirings/cli/command-parser.test.ts +9 -9
- package/src/wirings/cli/command-parser.ts +1 -1
- package/src/wirings/cli/define-cli-commands.ts +24 -0
- package/src/wirings/cli/index.ts +10 -4
- package/src/wirings/http/http-routes.test.ts +322 -0
- package/src/wirings/http/http-routes.ts +198 -0
- package/src/wirings/http/http-runner.test.ts +12 -20
- package/src/wirings/http/http-runner.ts +101 -51
- package/src/wirings/http/http.types.ts +119 -48
- package/src/wirings/http/index.ts +16 -4
- package/src/wirings/http/log-http-routes.ts +1 -1
- package/src/wirings/http/pikku-fetch-http-request.ts +1 -1
- package/src/wirings/http/pikku-fetch-http-response.ts +12 -5
- package/src/wirings/http/routers/http-router.ts +1 -1
- package/src/wirings/http/routers/path-to-regex.test.ts +1 -1
- package/src/wirings/http/routers/path-to-regex.ts +4 -3
- package/src/wirings/mcp/index.ts +27 -3
- package/src/wirings/mcp/mcp-endpoint-registry.test.ts +3 -3
- package/src/wirings/mcp/mcp-endpoint-registry.ts +5 -1
- package/src/wirings/mcp/mcp-runner.ts +48 -65
- package/src/wirings/mcp/mcp.types.ts +5 -5
- package/src/wirings/node/index.ts +2 -0
- package/src/wirings/node/node.types.ts +23 -0
- package/src/wirings/oauth2/index.ts +3 -0
- package/src/wirings/oauth2/oauth2-client.test.ts +929 -0
- package/src/wirings/oauth2/oauth2-client.ts +335 -0
- package/src/wirings/oauth2/oauth2.types.ts +69 -0
- package/src/wirings/oauth2/wire-oauth2-credential.ts +23 -0
- package/src/wirings/queue/index.ts +13 -2
- package/src/wirings/queue/queue-runner.test.ts +142 -73
- package/src/wirings/queue/queue-runner.ts +18 -14
- package/src/wirings/queue/queue.types.ts +5 -5
- package/src/wirings/queue/register-queue-helper.ts +3 -5
- package/src/wirings/queue/validate-worker-config.test.ts +108 -0
- package/src/wirings/queue/validate-worker-config.ts +4 -1
- package/src/wirings/rpc/index.ts +3 -1
- package/src/wirings/rpc/rpc-runner.ts +254 -41
- package/src/wirings/rpc/rpc-types.ts +28 -4
- package/src/wirings/rpc/wire-addon.ts +20 -0
- package/src/wirings/scheduler/index.ts +6 -4
- package/src/wirings/scheduler/log-schedulers.ts +1 -1
- package/src/wirings/scheduler/scheduler-runner.test.ts +78 -45
- package/src/wirings/scheduler/scheduler-runner.ts +20 -27
- package/src/wirings/scheduler/scheduler.types.ts +2 -2
- package/src/wirings/secret/index.ts +9 -0
- package/src/wirings/secret/secret.types.ts +32 -0
- package/src/wirings/secret/validate-secret-definitions.test.ts +140 -0
- package/src/wirings/secret/validate-secret-definitions.ts +82 -0
- package/src/wirings/trigger/index.ts +10 -2
- package/src/wirings/trigger/pikku-trigger-service.ts +112 -0
- package/src/wirings/trigger/trigger-runner.test.ts +79 -0
- package/src/wirings/trigger/trigger-runner.ts +80 -41
- package/src/wirings/trigger/trigger.types.ts +144 -22
- package/src/wirings/variable/index.ts +8 -0
- package/src/wirings/variable/validate-variable-definitions.test.ts +91 -0
- package/src/wirings/variable/validate-variable-definitions.ts +69 -0
- package/src/wirings/variable/variable.types.ts +22 -0
- package/src/wirings/workflow/dsl/index.ts +1 -0
- package/src/wirings/workflow/dsl/workflow-dsl.types.ts +9 -1
- package/src/wirings/workflow/dsl/workflow-runner.ts +4 -3
- package/src/wirings/workflow/graph/graph-node.ts +1 -6
- package/src/wirings/workflow/graph/graph-runner.test.ts +487 -0
- package/src/wirings/workflow/graph/graph-runner.ts +496 -374
- package/src/wirings/workflow/graph/index.ts +14 -3
- package/src/wirings/workflow/graph/template.test.ts +49 -0
- package/src/wirings/workflow/graph/template.ts +42 -0
- package/src/wirings/workflow/graph/wire-workflow-graph.ts +29 -0
- package/src/wirings/workflow/graph/workflow-graph.types.ts +0 -22
- package/src/wirings/workflow/index.ts +21 -10
- package/src/wirings/workflow/pikku-workflow-service.test.ts +200 -0
- package/src/wirings/workflow/pikku-workflow-service.ts +308 -105
- package/src/wirings/workflow/workflow-helpers.test.ts +129 -0
- package/src/wirings/workflow/workflow-helpers.ts +79 -0
- package/src/wirings/workflow/workflow.types.ts +47 -92
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/wirings/forge-node/forge-node.types.d.ts +0 -120
- package/dist/wirings/forge-node/forge-node.types.js +0 -38
- package/dist/wirings/forge-node/index.d.ts +0 -1
- package/dist/wirings/forge-node/index.js +0 -1
- package/dist/wirings/workflow/wire-workflow.d.ts +0 -42
- package/dist/wirings/workflow/wire-workflow.js +0 -53
- package/dist/wirings/workflow/workflow-utils.d.ts +0 -23
- package/dist/wirings/workflow/workflow-utils.js +0 -66
- package/src/wirings/forge-node/forge-node.types.ts +0 -135
- package/src/wirings/forge-node/index.ts +0 -1
- package/src/wirings/workflow/wire-workflow.ts +0 -94
- package/src/wirings/workflow/workflow-utils.ts +0 -120
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { describe, test } from 'node:test'
|
|
2
|
+
import assert from 'node:assert'
|
|
3
|
+
import { LocalVariablesService } from './local-variables.js'
|
|
4
|
+
|
|
5
|
+
describe('LocalVariablesService', () => {
|
|
6
|
+
test('should get a variable', () => {
|
|
7
|
+
const service = new LocalVariablesService({ MY_VAR: 'hello' })
|
|
8
|
+
assert.strictEqual(service.get('MY_VAR'), 'hello')
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
test('should return undefined for missing variable', () => {
|
|
12
|
+
const service = new LocalVariablesService({})
|
|
13
|
+
assert.strictEqual(service.get('MISSING'), undefined)
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
test('should set a variable', () => {
|
|
17
|
+
const service = new LocalVariablesService({})
|
|
18
|
+
service.set('KEY', 'value')
|
|
19
|
+
assert.strictEqual(service.get('KEY'), 'value')
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
test('should delete a variable', () => {
|
|
23
|
+
const service = new LocalVariablesService({ KEY: 'val' })
|
|
24
|
+
service.delete('KEY')
|
|
25
|
+
assert.strictEqual(service.get('KEY'), undefined)
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
test('should check if variable exists', () => {
|
|
29
|
+
const service = new LocalVariablesService({ KEY: 'val' })
|
|
30
|
+
assert.strictEqual(service.has('KEY'), true)
|
|
31
|
+
assert.strictEqual(service.has('MISSING'), false)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
test('should get all variables', () => {
|
|
35
|
+
const vars = { A: '1', B: '2' }
|
|
36
|
+
const service = new LocalVariablesService(vars)
|
|
37
|
+
assert.deepStrictEqual(service.getAll(), vars)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
test('should get JSON variable', () => {
|
|
41
|
+
const service = new LocalVariablesService({ DATA: '{"key":"val"}' })
|
|
42
|
+
const result = service.getJSON('DATA')
|
|
43
|
+
assert.deepStrictEqual(result, { key: 'val' })
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
test('should return undefined for missing JSON variable', () => {
|
|
47
|
+
const service = new LocalVariablesService({})
|
|
48
|
+
assert.strictEqual(service.getJSON('MISSING'), undefined)
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
test('should set JSON variable', () => {
|
|
52
|
+
const service = new LocalVariablesService({})
|
|
53
|
+
service.setJSON('DATA', { key: 'val' })
|
|
54
|
+
assert.strictEqual(service.get('DATA'), '{"key":"val"}')
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
test('should handle has with undefined value', () => {
|
|
58
|
+
const service = new LocalVariablesService({ KEY: undefined })
|
|
59
|
+
assert.strictEqual(service.has('KEY'), false)
|
|
60
|
+
})
|
|
61
|
+
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { VariablesService } from './variables-service.js'
|
|
1
|
+
import type { VariablesService } from './variables-service.js'
|
|
2
2
|
|
|
3
3
|
export class LocalVariablesService implements VariablesService {
|
|
4
4
|
constructor(
|
|
@@ -14,4 +14,26 @@ export class LocalVariablesService implements VariablesService {
|
|
|
14
14
|
public get(name: string): Promise<string | undefined> | string | undefined {
|
|
15
15
|
return this.variables[name]
|
|
16
16
|
}
|
|
17
|
+
|
|
18
|
+
public getJSON<T = unknown>(name: string): T | undefined {
|
|
19
|
+
const value = this.variables[name]
|
|
20
|
+
if (value === undefined) return undefined
|
|
21
|
+
return JSON.parse(value)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public set(name: string, value: string): void {
|
|
25
|
+
this.variables[name] = value
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public setJSON(name: string, value: unknown): void {
|
|
29
|
+
this.variables[name] = JSON.stringify(value)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public has(name: string): boolean {
|
|
33
|
+
return name in this.variables && this.variables[name] !== undefined
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public delete(name: string): void {
|
|
37
|
+
delete this.variables[name]
|
|
38
|
+
}
|
|
17
39
|
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { describe, test, beforeEach } from 'node:test'
|
|
2
|
+
import assert from 'node:assert'
|
|
3
|
+
import { ConsoleLogger } from './logger-console.js'
|
|
4
|
+
import { LogLevel } from './logger.js'
|
|
5
|
+
|
|
6
|
+
describe('ConsoleLogger', () => {
|
|
7
|
+
let logger: ConsoleLogger
|
|
8
|
+
let captured: { method: string; args: any[] }[]
|
|
9
|
+
let origConsole: Record<string, any>
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
logger = new ConsoleLogger()
|
|
13
|
+
captured = []
|
|
14
|
+
origConsole = {
|
|
15
|
+
trace: console.trace,
|
|
16
|
+
debug: console.debug,
|
|
17
|
+
info: console.info,
|
|
18
|
+
warn: console.warn,
|
|
19
|
+
error: console.error,
|
|
20
|
+
log: console.log,
|
|
21
|
+
}
|
|
22
|
+
console.trace = (...args: any[]) => captured.push({ method: 'trace', args })
|
|
23
|
+
console.debug = (...args: any[]) => captured.push({ method: 'debug', args })
|
|
24
|
+
console.info = (...args: any[]) => captured.push({ method: 'info', args })
|
|
25
|
+
console.warn = (...args: any[]) => captured.push({ method: 'warn', args })
|
|
26
|
+
console.error = (...args: any[]) => captured.push({ method: 'error', args })
|
|
27
|
+
console.log = (...args: any[]) => captured.push({ method: 'log', args })
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
// Restore console after each test
|
|
31
|
+
test('should log info at default level', () => {
|
|
32
|
+
logger.info('test message')
|
|
33
|
+
assert.strictEqual(captured.length, 1)
|
|
34
|
+
assert.strictEqual(captured[0].method, 'info')
|
|
35
|
+
assert.ok(captured[0].args.includes('test message'))
|
|
36
|
+
Object.assign(console, origConsole)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test('should not log debug at default info level', () => {
|
|
40
|
+
logger.debug('debug message')
|
|
41
|
+
assert.strictEqual(captured.length, 0)
|
|
42
|
+
Object.assign(console, origConsole)
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
test('should log debug when level is set to debug', () => {
|
|
46
|
+
logger.setLevel(LogLevel.debug)
|
|
47
|
+
logger.debug('debug message')
|
|
48
|
+
assert.strictEqual(captured.length, 1)
|
|
49
|
+
assert.strictEqual(captured[0].method, 'debug')
|
|
50
|
+
Object.assign(console, origConsole)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
test('should log warn at info level', () => {
|
|
54
|
+
logger.warn('warning')
|
|
55
|
+
assert.strictEqual(captured.length, 1)
|
|
56
|
+
assert.strictEqual(captured[0].method, 'warn')
|
|
57
|
+
Object.assign(console, origConsole)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
test('should log error at info level', () => {
|
|
61
|
+
logger.error('error message')
|
|
62
|
+
assert.strictEqual(captured.length, 1)
|
|
63
|
+
assert.strictEqual(captured[0].method, 'error')
|
|
64
|
+
Object.assign(console, origConsole)
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
test('should log Error instance with stack trace', () => {
|
|
68
|
+
const err = new Error('test error')
|
|
69
|
+
logger.error(err)
|
|
70
|
+
assert.strictEqual(captured.length, 2) // error message + stack
|
|
71
|
+
assert.ok(captured[0].args.includes('test error'))
|
|
72
|
+
assert.strictEqual(captured[1].args[0], 'STACK:')
|
|
73
|
+
Object.assign(console, origConsole)
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
test('should not log info when level is error', () => {
|
|
77
|
+
logger.setLevel(LogLevel.error)
|
|
78
|
+
logger.info('info')
|
|
79
|
+
logger.warn('warn')
|
|
80
|
+
logger.debug('debug')
|
|
81
|
+
assert.strictEqual(captured.length, 0)
|
|
82
|
+
Object.assign(console, origConsole)
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
test('should log error when level is error', () => {
|
|
86
|
+
logger.setLevel(LogLevel.error)
|
|
87
|
+
logger.error('critical')
|
|
88
|
+
assert.strictEqual(captured.length, 1)
|
|
89
|
+
Object.assign(console, origConsole)
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
test('should support trace level when enabled', () => {
|
|
93
|
+
logger.setLevel(LogLevel.trace)
|
|
94
|
+
logger.trace!('trace message')
|
|
95
|
+
assert.strictEqual(captured.length, 1)
|
|
96
|
+
assert.strictEqual(captured[0].method, 'trace')
|
|
97
|
+
Object.assign(console, origConsole)
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
test('should log with additional metadata', () => {
|
|
101
|
+
logger.info('message', { extra: 'data' })
|
|
102
|
+
assert.ok(captured[0].args.includes('message'))
|
|
103
|
+
Object.assign(console, origConsole)
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
test('should handle object messages in info', () => {
|
|
107
|
+
logger.info({ key: 'value' })
|
|
108
|
+
assert.strictEqual(captured.length, 1)
|
|
109
|
+
Object.assign(console, origConsole)
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
test('log method should respect level', () => {
|
|
113
|
+
logger.setLevel(LogLevel.error)
|
|
114
|
+
logger.log('info', 'should not show')
|
|
115
|
+
assert.strictEqual(captured.length, 0)
|
|
116
|
+
Object.assign(console, origConsole)
|
|
117
|
+
})
|
|
118
|
+
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CoreUserSession } from '../types/core.types.js'
|
|
1
|
+
import type { CoreUserSession } from '../types/core.types.js'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Minimal metadata for listing scheduled tasks
|
|
@@ -73,4 +73,14 @@ export abstract class SchedulerService {
|
|
|
73
73
|
* Close any open connections
|
|
74
74
|
*/
|
|
75
75
|
abstract close(): Promise<void>
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Start recurring scheduled tasks
|
|
79
|
+
*/
|
|
80
|
+
async start(): Promise<void> {}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Stop recurring scheduled tasks
|
|
84
|
+
*/
|
|
85
|
+
async stop(): Promise<void> {}
|
|
76
86
|
}
|
|
@@ -23,4 +23,11 @@ export interface SchemaService {
|
|
|
23
23
|
* @returns {Set<string>} A set containing the names of all available schemas.
|
|
24
24
|
*/
|
|
25
25
|
getSchemaNames: () => Set<string>
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Retrieves the property keys from a compiled JSON schema.
|
|
29
|
+
* @param {string} schemaName - The name of the schema.
|
|
30
|
+
* @returns {string[]} An array of property keys, or empty array if schema not found.
|
|
31
|
+
*/
|
|
32
|
+
getSchemaKeys: (schemaName: string) => string[]
|
|
26
33
|
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { describe, test } from 'node:test'
|
|
2
|
+
import assert from 'node:assert'
|
|
3
|
+
import { ScopedSecretService } from './scoped-secret-service.js'
|
|
4
|
+
|
|
5
|
+
const createMockSecrets = () => ({
|
|
6
|
+
getSecret: async (key: string) => `value-of-${key}`,
|
|
7
|
+
getSecretJSON: async (key: string) => ({ key }),
|
|
8
|
+
hasSecret: async () => true,
|
|
9
|
+
setSecretJSON: async () => {},
|
|
10
|
+
deleteSecret: async () => {},
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
describe('ScopedSecretService', () => {
|
|
14
|
+
test('should allow access to allowed keys', async () => {
|
|
15
|
+
const mock = createMockSecrets()
|
|
16
|
+
const scoped = new ScopedSecretService(mock, new Set(['KEY1', 'KEY2']))
|
|
17
|
+
const result = await scoped.getSecret('KEY1')
|
|
18
|
+
assert.strictEqual(result, 'value-of-KEY1')
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
test('should deny access to non-allowed keys', async () => {
|
|
22
|
+
const mock = createMockSecrets()
|
|
23
|
+
const scoped = new ScopedSecretService(mock, new Set(['KEY1']))
|
|
24
|
+
await assert.rejects(() => scoped.getSecret('KEY2'), {
|
|
25
|
+
message: 'Access denied to secret key: KEY2',
|
|
26
|
+
})
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test('should allow getSecretJSON for allowed keys', async () => {
|
|
30
|
+
const mock = createMockSecrets()
|
|
31
|
+
const scoped = new ScopedSecretService(mock, new Set(['KEY1']))
|
|
32
|
+
const result = await scoped.getSecretJSON('KEY1')
|
|
33
|
+
assert.deepStrictEqual(result, { key: 'KEY1' })
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
test('should deny getSecretJSON for non-allowed keys', async () => {
|
|
37
|
+
const mock = createMockSecrets()
|
|
38
|
+
const scoped = new ScopedSecretService(mock, new Set(['KEY1']))
|
|
39
|
+
await assert.rejects(() => scoped.getSecretJSON('FORBIDDEN'), {
|
|
40
|
+
message: 'Access denied to secret key: FORBIDDEN',
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
test('should allow hasSecret for allowed keys', async () => {
|
|
45
|
+
const mock = createMockSecrets()
|
|
46
|
+
const scoped = new ScopedSecretService(mock, new Set(['KEY1']))
|
|
47
|
+
const result = await scoped.hasSecret('KEY1')
|
|
48
|
+
assert.strictEqual(result, true)
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
test('should deny hasSecret for non-allowed keys', async () => {
|
|
52
|
+
const mock = createMockSecrets()
|
|
53
|
+
const scoped = new ScopedSecretService(mock, new Set(['KEY1']))
|
|
54
|
+
await assert.rejects(() => scoped.hasSecret('KEY2'), {
|
|
55
|
+
message: 'Access denied to secret key: KEY2',
|
|
56
|
+
})
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
test('should always throw on setSecretJSON', async () => {
|
|
60
|
+
const mock = createMockSecrets()
|
|
61
|
+
const scoped = new ScopedSecretService(mock, new Set(['KEY1']))
|
|
62
|
+
await assert.rejects(() => scoped.setSecretJSON('KEY1', 'val'), {
|
|
63
|
+
message: 'setSecretJSON is not allowed in scoped secret service',
|
|
64
|
+
})
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
test('should always throw on deleteSecret', async () => {
|
|
68
|
+
const mock = createMockSecrets()
|
|
69
|
+
const scoped = new ScopedSecretService(mock, new Set(['KEY1']))
|
|
70
|
+
await assert.rejects(() => scoped.deleteSecret('KEY1'), {
|
|
71
|
+
message: 'deleteSecret is not allowed in scoped secret service',
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
})
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { SecretService } from './secret-service.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A read-only wrapper around SecretService that restricts access
|
|
5
|
+
* to only a defined set of allowed secret keys.
|
|
6
|
+
*/
|
|
7
|
+
export class ScopedSecretService implements SecretService {
|
|
8
|
+
constructor(
|
|
9
|
+
private secrets: SecretService,
|
|
10
|
+
private allowedKeys: Set<string>
|
|
11
|
+
) {}
|
|
12
|
+
|
|
13
|
+
private assertAllowed(key: string): void {
|
|
14
|
+
if (!this.allowedKeys.has(key)) {
|
|
15
|
+
throw new Error(`Access denied to secret key: ${key}`)
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async getSecret(key: string): Promise<string> {
|
|
20
|
+
this.assertAllowed(key)
|
|
21
|
+
return this.secrets.getSecret(key)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async getSecretJSON<T = {}>(key: string): Promise<T> {
|
|
25
|
+
this.assertAllowed(key)
|
|
26
|
+
return this.secrets.getSecretJSON<T>(key)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async hasSecret(key: string): Promise<boolean> {
|
|
30
|
+
this.assertAllowed(key)
|
|
31
|
+
return this.secrets.hasSecret(key)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async setSecretJSON(_key: string, _value: unknown): Promise<void> {
|
|
35
|
+
throw new Error('setSecretJSON is not allowed in scoped secret service')
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async deleteSecret(_key: string): Promise<void> {
|
|
39
|
+
throw new Error('deleteSecret is not allowed in scoped secret service')
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -1,17 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Interface for retrieving secrets.
|
|
2
|
+
* Interface for retrieving and managing secrets.
|
|
3
3
|
*/
|
|
4
4
|
export interface SecretService {
|
|
5
5
|
/**
|
|
6
|
-
* Retrieves a secret by key.
|
|
6
|
+
* Retrieves a secret by key and parses it as JSON.
|
|
7
7
|
* @param key - The key of the secret to retrieve.
|
|
8
|
-
* @returns A promise that resolves to the secret value.
|
|
8
|
+
* @returns A promise that resolves to the parsed secret value.
|
|
9
|
+
* @throws If the secret is not found.
|
|
9
10
|
*/
|
|
10
11
|
getSecretJSON<Return = {}>(key: string): Promise<Return>
|
|
11
12
|
/**
|
|
12
|
-
* Retrieves a secret by key.
|
|
13
|
+
* Retrieves a secret by key as a string.
|
|
13
14
|
* @param key - The key of the secret to retrieve.
|
|
14
15
|
* @returns A promise that resolves to the secret value.
|
|
16
|
+
* @throws If the secret is not found.
|
|
15
17
|
*/
|
|
16
18
|
getSecret(key: string): Promise<string>
|
|
19
|
+
/**
|
|
20
|
+
* Checks if a secret exists without throwing.
|
|
21
|
+
* @param key - The key of the secret to check.
|
|
22
|
+
* @returns A promise that resolves to true if the secret exists, false otherwise.
|
|
23
|
+
*/
|
|
24
|
+
hasSecret(key: string): Promise<boolean>
|
|
25
|
+
/**
|
|
26
|
+
* Stores a JSON value as a secret.
|
|
27
|
+
* @param key - The key to store the secret under.
|
|
28
|
+
* @param value - The JSON value to store.
|
|
29
|
+
* @returns A promise that resolves when the secret is stored.
|
|
30
|
+
*/
|
|
31
|
+
setSecretJSON(key: string, value: unknown): Promise<void>
|
|
32
|
+
/**
|
|
33
|
+
* Deletes a secret by key.
|
|
34
|
+
* @param key - The key of the secret to delete.
|
|
35
|
+
* @returns A promise that resolves when the secret is deleted.
|
|
36
|
+
*/
|
|
37
|
+
deleteSecret(key: string): Promise<void>
|
|
17
38
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Abstract TriggerService interface.
|
|
3
|
+
*
|
|
4
|
+
* Implementations manage trigger subscriptions — listening to external events
|
|
5
|
+
* and dispatching to RPC targets or workflow starts.
|
|
6
|
+
*/
|
|
7
|
+
export interface TriggerService {
|
|
8
|
+
/**
|
|
9
|
+
* Start all triggers
|
|
10
|
+
*/
|
|
11
|
+
start(): Promise<void>
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Stop all triggers
|
|
15
|
+
*/
|
|
16
|
+
stop(): Promise<void>
|
|
17
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { describe, test } from 'node:test'
|
|
2
|
+
import assert from 'node:assert'
|
|
3
|
+
import { TypedSecretService } from './typed-secret-service.js'
|
|
4
|
+
|
|
5
|
+
const createMockSecrets = (store: Map<string, string> = new Map()) => ({
|
|
6
|
+
getSecret: async (key: string) => {
|
|
7
|
+
const val = store.get(key)
|
|
8
|
+
if (!val) throw new Error(`Not found: ${key}`)
|
|
9
|
+
return val
|
|
10
|
+
},
|
|
11
|
+
getSecretJSON: async (key: string) => {
|
|
12
|
+
const val = store.get(key)
|
|
13
|
+
if (!val) throw new Error(`Not found: ${key}`)
|
|
14
|
+
return JSON.parse(val)
|
|
15
|
+
},
|
|
16
|
+
hasSecret: async (key: string) => store.has(key),
|
|
17
|
+
setSecretJSON: async (key: string, value: unknown) => {
|
|
18
|
+
store.set(key, JSON.stringify(value))
|
|
19
|
+
},
|
|
20
|
+
deleteSecret: async (key: string) => {
|
|
21
|
+
store.delete(key)
|
|
22
|
+
},
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
describe('TypedSecretService', () => {
|
|
26
|
+
test('should delegate getSecret to underlying service', async () => {
|
|
27
|
+
const store = new Map([['API_KEY', 'sk-123']])
|
|
28
|
+
const service = new TypedSecretService(createMockSecrets(store), {})
|
|
29
|
+
const result = await service.getSecret('API_KEY')
|
|
30
|
+
assert.strictEqual(result, 'sk-123')
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
test('should delegate getSecretJSON to underlying service', async () => {
|
|
34
|
+
const store = new Map([['CONFIG', '{"port":3000}']])
|
|
35
|
+
const service = new TypedSecretService(createMockSecrets(store), {})
|
|
36
|
+
const result = await service.getSecretJSON('CONFIG')
|
|
37
|
+
assert.deepStrictEqual(result, { port: 3000 })
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
test('should delegate hasSecret to underlying service', async () => {
|
|
41
|
+
const store = new Map([['EXISTS', 'val']])
|
|
42
|
+
const service = new TypedSecretService(createMockSecrets(store), {})
|
|
43
|
+
assert.strictEqual(await service.hasSecret('EXISTS'), true)
|
|
44
|
+
assert.strictEqual(await service.hasSecret('MISSING'), false)
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
test('should delegate setSecretJSON to underlying service', async () => {
|
|
48
|
+
const store = new Map<string, string>()
|
|
49
|
+
const service = new TypedSecretService(createMockSecrets(store), {})
|
|
50
|
+
await service.setSecretJSON('NEW_KEY', { data: 'val' })
|
|
51
|
+
assert.strictEqual(store.get('NEW_KEY'), '{"data":"val"}')
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
test('should delegate deleteSecret to underlying service', async () => {
|
|
55
|
+
const store = new Map([['KEY', 'val']])
|
|
56
|
+
const service = new TypedSecretService(createMockSecrets(store), {})
|
|
57
|
+
await service.deleteSecret('KEY')
|
|
58
|
+
assert.strictEqual(store.has('KEY'), false)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
test('should get all status for credentials', async () => {
|
|
62
|
+
const store = new Map([['STRIPE_KEY', 'sk-123']])
|
|
63
|
+
const meta = {
|
|
64
|
+
STRIPE_KEY: { name: 'stripe', displayName: 'Stripe' },
|
|
65
|
+
GITHUB_TOKEN: {
|
|
66
|
+
name: 'github',
|
|
67
|
+
displayName: 'GitHub',
|
|
68
|
+
oauth2: { tokenSecretId: 'GH_TOKEN' },
|
|
69
|
+
},
|
|
70
|
+
}
|
|
71
|
+
const service = new TypedSecretService(createMockSecrets(store), meta)
|
|
72
|
+
const status = await service.getAllStatus()
|
|
73
|
+
assert.strictEqual(status.length, 2)
|
|
74
|
+
const stripeStatus = status.find((s) => s.secretId === 'STRIPE_KEY')!
|
|
75
|
+
assert.strictEqual(stripeStatus.isConfigured, true)
|
|
76
|
+
assert.strictEqual(stripeStatus.displayName, 'Stripe')
|
|
77
|
+
const ghStatus = status.find((s) => s.secretId === 'GITHUB_TOKEN')!
|
|
78
|
+
assert.strictEqual(ghStatus.isConfigured, false)
|
|
79
|
+
assert.deepStrictEqual(ghStatus.oauth2, { tokenSecretId: 'GH_TOKEN' })
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
test('should get missing credentials', async () => {
|
|
83
|
+
const store = new Map([['STRIPE_KEY', 'sk-123']])
|
|
84
|
+
const meta = {
|
|
85
|
+
STRIPE_KEY: { name: 'stripe', displayName: 'Stripe' },
|
|
86
|
+
GITHUB_TOKEN: { name: 'github', displayName: 'GitHub' },
|
|
87
|
+
}
|
|
88
|
+
const service = new TypedSecretService(createMockSecrets(store), meta)
|
|
89
|
+
const missing = await service.getMissing()
|
|
90
|
+
assert.strictEqual(missing.length, 1)
|
|
91
|
+
assert.strictEqual(missing[0].secretId, 'GITHUB_TOKEN')
|
|
92
|
+
})
|
|
93
|
+
})
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { SecretService } from './secret-service.js'
|
|
2
|
+
|
|
3
|
+
export interface CredentialStatus {
|
|
4
|
+
secretId: string
|
|
5
|
+
name: string
|
|
6
|
+
displayName: string
|
|
7
|
+
isConfigured: boolean
|
|
8
|
+
oauth2?: { tokenSecretId: string }
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type CredentialMeta = {
|
|
12
|
+
name: string
|
|
13
|
+
displayName: string
|
|
14
|
+
oauth2?: { tokenSecretId: string }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class TypedSecretService<TMap = Record<string, unknown>>
|
|
18
|
+
implements SecretService
|
|
19
|
+
{
|
|
20
|
+
constructor(
|
|
21
|
+
private secrets: SecretService,
|
|
22
|
+
private credentialsMeta: Record<string, CredentialMeta>
|
|
23
|
+
) {}
|
|
24
|
+
|
|
25
|
+
async getSecretJSON<K extends keyof TMap & string>(key: K): Promise<TMap[K]>
|
|
26
|
+
async getSecretJSON<T = unknown>(key: string): Promise<T>
|
|
27
|
+
async getSecretJSON(key: string): Promise<unknown> {
|
|
28
|
+
return this.secrets.getSecretJSON(key)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async getSecret(key: string): Promise<string> {
|
|
32
|
+
return this.secrets.getSecret(key)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async hasSecret(key: string): Promise<boolean> {
|
|
36
|
+
return this.secrets.hasSecret(key)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async setSecretJSON<K extends string>(
|
|
40
|
+
key: K,
|
|
41
|
+
value: K extends keyof TMap ? TMap[K] : unknown
|
|
42
|
+
): Promise<void> {
|
|
43
|
+
return this.secrets.setSecretJSON(key, value)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async deleteSecret(key: string): Promise<void> {
|
|
47
|
+
return this.secrets.deleteSecret(key)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async getAllStatus(): Promise<CredentialStatus[]> {
|
|
51
|
+
const results: CredentialStatus[] = []
|
|
52
|
+
|
|
53
|
+
for (const [secretId, meta] of Object.entries(this.credentialsMeta)) {
|
|
54
|
+
results.push({
|
|
55
|
+
secretId,
|
|
56
|
+
name: meta.name,
|
|
57
|
+
displayName: meta.displayName,
|
|
58
|
+
isConfigured: await this.secrets.hasSecret(secretId),
|
|
59
|
+
oauth2: meta.oauth2,
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return results
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async getMissing(): Promise<CredentialStatus[]> {
|
|
67
|
+
const all = await this.getAllStatus()
|
|
68
|
+
return all.filter((c) => !c.isConfigured)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { describe, test } from 'node:test'
|
|
2
|
+
import assert from 'node:assert'
|
|
3
|
+
import { TypedVariablesService } from './typed-variables-service.js'
|
|
4
|
+
import { LocalVariablesService } from './local-variables.js'
|
|
5
|
+
|
|
6
|
+
describe('TypedVariablesService', () => {
|
|
7
|
+
const createService = (vars: Record<string, string | undefined> = {}) => {
|
|
8
|
+
const underlying = new LocalVariablesService(vars)
|
|
9
|
+
const meta = {
|
|
10
|
+
DB_URL: { name: 'DB_URL', displayName: 'Database URL' },
|
|
11
|
+
API_KEY: { name: 'API_KEY', displayName: 'API Key' },
|
|
12
|
+
}
|
|
13
|
+
return new TypedVariablesService(underlying, meta)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
test('should delegate get to underlying service', () => {
|
|
17
|
+
const service = createService({ DB_URL: 'postgres://...' })
|
|
18
|
+
assert.strictEqual(service.get('DB_URL'), 'postgres://...')
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
test('should delegate set to underlying service', () => {
|
|
22
|
+
const service = createService()
|
|
23
|
+
service.set('DB_URL', 'new-value')
|
|
24
|
+
assert.strictEqual(service.get('DB_URL'), 'new-value')
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
test('should delegate has to underlying service', () => {
|
|
28
|
+
const service = createService({ DB_URL: 'val' })
|
|
29
|
+
assert.strictEqual(service.has('DB_URL'), true)
|
|
30
|
+
assert.strictEqual(service.has('MISSING'), false)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
test('should delegate delete to underlying service', () => {
|
|
34
|
+
const service = createService({ DB_URL: 'val' })
|
|
35
|
+
service.delete('DB_URL')
|
|
36
|
+
assert.strictEqual(service.has('DB_URL'), false)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test('should delegate getJSON to underlying service', () => {
|
|
40
|
+
const service = createService({ DATA: '{"key":"val"}' })
|
|
41
|
+
assert.deepStrictEqual(service.getJSON('DATA'), { key: 'val' })
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
test('should delegate setJSON to underlying service', () => {
|
|
45
|
+
const service = createService()
|
|
46
|
+
service.setJSON('DATA', { key: 'val' })
|
|
47
|
+
assert.strictEqual(service.get('DATA'), '{"key":"val"}')
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
test('should get all status for configured variables', async () => {
|
|
51
|
+
const service = createService({ DB_URL: 'postgres://...' })
|
|
52
|
+
const status = await service.getAllStatus()
|
|
53
|
+
assert.strictEqual(status.length, 2)
|
|
54
|
+
const dbStatus = status.find((s) => s.variableId === 'DB_URL')!
|
|
55
|
+
assert.strictEqual(dbStatus.isConfigured, true)
|
|
56
|
+
assert.strictEqual(dbStatus.displayName, 'Database URL')
|
|
57
|
+
const apiStatus = status.find((s) => s.variableId === 'API_KEY')!
|
|
58
|
+
assert.strictEqual(apiStatus.isConfigured, false)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
test('should get missing variables', async () => {
|
|
62
|
+
const service = createService({ DB_URL: 'val' })
|
|
63
|
+
const missing = await service.getMissing()
|
|
64
|
+
assert.strictEqual(missing.length, 1)
|
|
65
|
+
assert.strictEqual(missing[0].variableId, 'API_KEY')
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
test('should return empty missing when all configured', async () => {
|
|
69
|
+
const service = createService({ DB_URL: 'val', API_KEY: 'key' })
|
|
70
|
+
const missing = await service.getMissing()
|
|
71
|
+
assert.strictEqual(missing.length, 0)
|
|
72
|
+
})
|
|
73
|
+
})
|