@pikku/core 0.11.1 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +55 -0
- package/dist/crypto-utils.d.ts +2 -0
- package/dist/crypto-utils.js +78 -0
- package/dist/errors/error-handler.js +3 -3
- package/dist/errors/errors.d.ts +8 -0
- package/dist/errors/errors.js +16 -0
- package/dist/errors/index.d.ts +0 -1
- package/dist/errors/index.js +0 -1
- package/dist/function/function-runner.d.ts +10 -3
- package/dist/function/function-runner.js +136 -31
- package/dist/function/functions.types.d.ts +35 -12
- package/dist/function/functions.types.js +16 -6
- package/dist/function/index.d.ts +2 -2
- package/dist/function/index.js +1 -2
- package/dist/handle-error.js +1 -10
- package/dist/index.d.ts +30 -24
- package/dist/index.js +19 -27
- package/dist/middleware/auth-apikey.d.ts +1 -1
- package/dist/middleware/auth-apikey.js +3 -3
- package/dist/middleware/auth-bearer.d.ts +1 -1
- package/dist/middleware/auth-bearer.js +3 -6
- package/dist/middleware/auth-cookie.d.ts +1 -1
- package/dist/middleware/auth-cookie.js +6 -8
- package/dist/middleware/cors.d.ts +46 -0
- package/dist/middleware/cors.js +73 -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 +1 -1
- package/dist/middleware-runner.d.ts +3 -14
- package/dist/middleware-runner.js +14 -16
- package/dist/permissions.d.ts +3 -86
- package/dist/permissions.js +20 -80
- package/dist/pikku-state.d.ts +33 -104
- package/dist/pikku-state.js +150 -66
- package/dist/schema.d.ts +8 -6
- package/dist/schema.js +31 -18
- package/dist/services/ai-agent-runner-service.d.ts +24 -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/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 +94 -0
- package/dist/services/in-memory-trigger-service.d.ts +23 -0
- package/dist/services/in-memory-trigger-service.js +50 -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 +25 -11
- package/dist/services/index.js +10 -13
- package/dist/services/local-secrets.d.ts +23 -0
- package/dist/services/local-secrets.js +45 -0
- package/dist/services/local-variables.d.ts +5 -0
- package/dist/services/local-variables.js +18 -0
- package/dist/services/scheduler-service.d.ts +21 -1
- package/dist/services/scheduler-service.js +14 -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 +23 -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 +13 -0
- 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 +43 -0
- package/dist/services/workflow-service.js +1 -0
- package/dist/types/core.types.d.ts +54 -10
- package/dist/types/core.types.js +7 -0
- package/dist/types/state.types.d.ts +127 -0
- package/dist/types/state.types.js +1 -0
- package/dist/utils.d.ts +10 -1
- package/dist/utils.js +60 -3
- package/dist/version.d.ts +6 -0
- package/dist/version.js +19 -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 +60 -0
- package/dist/wirings/ai-agent/ai-agent-prepare.js +312 -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 +96 -0
- package/dist/wirings/ai-agent/ai-agent-stream.d.ts +11 -0
- package/dist/wirings/ai-agent/ai-agent-stream.js +503 -0
- package/dist/wirings/ai-agent/ai-agent.types.d.ts +254 -0
- package/dist/wirings/ai-agent/ai-agent.types.js +1 -0
- package/dist/wirings/ai-agent/index.d.ts +5 -0
- package/dist/wirings/ai-agent/index.js +4 -0
- package/dist/wirings/channel/channel-common.d.ts +7 -4
- package/dist/wirings/channel/channel-common.js +15 -8
- package/dist/wirings/channel/channel-handler.js +13 -4
- 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.js +12 -12
- package/dist/wirings/channel/channel.types.d.ts +5 -1
- 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.js +18 -6
- package/dist/wirings/channel/log-channels.js +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.js +17 -6
- package/dist/wirings/cli/channel/cli-channel-runner.js +3 -2
- 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 +1 -1
- package/dist/wirings/cli/cli-runner.js +22 -18
- package/dist/wirings/cli/cli.types.d.ts +7 -6
- 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 +2 -2
- package/dist/wirings/http/http-runner.js +62 -27
- package/dist/wirings/http/http.types.d.ts +77 -24
- package/dist/wirings/http/index.d.ts +5 -4
- package/dist/wirings/http/index.js +4 -3
- package/dist/wirings/http/log-http-routes.js +1 -1
- package/dist/wirings/http/routers/path-to-regex.js +2 -2
- package/dist/wirings/mcp/index.d.ts +4 -3
- package/dist/wirings/mcp/index.js +3 -3
- package/dist/wirings/mcp/mcp-runner.d.ts +1 -3
- package/dist/wirings/mcp/mcp-runner.js +42 -56
- package/dist/wirings/mcp/mcp.types.d.ts +3 -3
- 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 +2 -2
- package/dist/wirings/queue/index.js +1 -1
- package/dist/wirings/queue/queue-runner.d.ts +7 -0
- package/dist/wirings/queue/queue-runner.js +23 -12
- package/dist/wirings/queue/queue.types.d.ts +8 -2
- package/dist/wirings/rpc/index.d.ts +1 -1
- package/dist/wirings/rpc/index.js +1 -1
- package/dist/wirings/rpc/rpc-runner.d.ts +40 -13
- package/dist/wirings/rpc/rpc-runner.js +191 -25
- package/dist/wirings/rpc/rpc-types.d.ts +15 -4
- package/dist/wirings/scheduler/index.d.ts +3 -3
- package/dist/wirings/scheduler/index.js +2 -3
- package/dist/wirings/scheduler/log-schedulers.js +1 -1
- package/dist/wirings/scheduler/scheduler-runner.d.ts +5 -0
- package/dist/wirings/scheduler/scheduler-runner.js +28 -10
- 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 -0
- package/dist/wirings/trigger/index.js +2 -0
- package/dist/wirings/trigger/pikku-trigger-service.d.ts +26 -0
- package/dist/wirings/trigger/pikku-trigger-service.js +75 -0
- package/dist/wirings/trigger/trigger-runner.d.ts +42 -0
- package/dist/wirings/trigger/trigger-runner.js +85 -0
- package/dist/wirings/trigger/trigger.types.d.ts +130 -0
- package/dist/wirings/trigger/trigger.types.js +40 -0
- 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 +5 -0
- package/dist/wirings/workflow/dsl/index.js +4 -0
- package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +292 -0
- package/dist/wirings/workflow/dsl/workflow-dsl.types.js +5 -0
- package/dist/wirings/workflow/dsl/workflow-runner.d.ts +5 -0
- package/dist/wirings/workflow/dsl/workflow-runner.js +23 -0
- package/dist/wirings/workflow/graph/graph-node.d.ts +117 -0
- package/dist/wirings/workflow/graph/graph-node.js +58 -0
- package/dist/wirings/workflow/graph/graph-runner.d.ts +9 -0
- package/dist/wirings/workflow/graph/graph-runner.js +540 -0
- package/dist/wirings/workflow/graph/index.d.ts +4 -0
- package/dist/wirings/workflow/graph/index.js +3 -0
- 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 +82 -0
- package/dist/wirings/workflow/graph/workflow-graph.types.js +15 -0
- package/dist/wirings/workflow/index.d.ts +7 -12
- package/dist/wirings/workflow/index.js +8 -11
- package/dist/wirings/workflow/pikku-workflow-service.d.ts +114 -10
- package/dist/wirings/workflow/pikku-workflow-service.js +386 -115
- package/dist/wirings/workflow/workflow-helpers.d.ts +36 -0
- package/dist/wirings/workflow/workflow-helpers.js +38 -0
- package/dist/wirings/workflow/workflow-utils.d.ts +1 -0
- package/dist/wirings/workflow/workflow-utils.js +1 -0
- package/dist/wirings/workflow/workflow.types.d.ts +83 -214
- package/package.json +13 -6
- package/run-tests.sh +4 -1
- package/src/crypto-utils.ts +99 -0
- package/src/errors/error-handler.ts +3 -3
- package/src/errors/errors.ts +17 -0
- package/src/errors/index.ts +0 -1
- package/src/factory-functions.test.ts +42 -2
- package/src/function/function-runner.test.ts +5 -12
- package/src/function/function-runner.ts +195 -40
- package/src/function/functions.types.ts +66 -14
- package/src/function/index.ts +5 -2
- package/src/handle-error.ts +2 -10
- package/src/index.ts +106 -27
- package/src/middleware/auth-apikey.test.ts +15 -12
- package/src/middleware/auth-apikey.ts +3 -3
- package/src/middleware/auth-bearer.test.ts +17 -14
- package/src/middleware/auth-bearer.ts +25 -27
- package/src/middleware/auth-cookie.test.ts +16 -13
- package/src/middleware/auth-cookie.ts +6 -8
- package/src/middleware/cors.ts +96 -0
- package/src/middleware/index.ts +5 -3
- package/src/middleware/remote-auth.ts +68 -0
- package/src/middleware-runner.test.ts +122 -0
- package/src/middleware-runner.ts +24 -17
- package/src/permissions.test.ts +102 -86
- package/src/permissions.ts +32 -93
- package/src/pikku-state.ts +168 -201
- package/src/run-tests-script.test.ts +49 -0
- package/src/schema.ts +50 -18
- package/src/services/ai-agent-runner-service.ts +29 -0
- package/src/services/ai-run-state-service.ts +20 -0
- package/src/services/ai-storage-service.ts +39 -0
- package/src/services/deployment-service.ts +22 -0
- package/src/services/gopass-secrets.ts +95 -0
- package/src/services/in-memory-trigger-service.ts +68 -0
- package/src/services/in-memory-workflow-service.ts +395 -0
- package/src/services/index.ts +49 -14
- package/src/services/local-secrets.ts +51 -0
- package/src/services/local-variables.ts +22 -0
- package/src/services/scheduler-service.ts +29 -1
- package/src/services/schema-service.ts +7 -0
- package/src/services/scoped-secret-service.ts +41 -0
- package/src/services/secret-service.ts +25 -4
- package/src/services/trigger-service.ts +38 -0
- package/src/services/typed-secret-service.ts +70 -0
- package/src/services/typed-variables-service.ts +81 -0
- package/src/services/user-session-service.ts +23 -0
- package/src/services/variables-service.ts +5 -0
- package/src/services/workflow-service.ts +94 -0
- package/src/types/core.types.ts +82 -8
- package/src/types/state.types.ts +169 -0
- package/src/utils.ts +74 -5
- package/src/version.test.ts +80 -0
- package/src/version.ts +25 -0
- package/src/wirings/ai-agent/ai-agent-memory.ts +300 -0
- package/src/wirings/ai-agent/ai-agent-model-config.ts +43 -0
- package/src/wirings/ai-agent/ai-agent-prepare.ts +470 -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 +75 -0
- package/src/wirings/ai-agent/ai-agent-runner.ts +137 -0
- package/src/wirings/ai-agent/ai-agent-stream.test.ts +246 -0
- package/src/wirings/ai-agent/ai-agent-stream.ts +774 -0
- package/src/wirings/ai-agent/ai-agent.types.ts +273 -0
- package/src/wirings/ai-agent/index.ts +28 -0
- package/src/wirings/channel/channel-common.ts +32 -19
- package/src/wirings/channel/channel-handler.ts +18 -5
- package/src/wirings/channel/channel-middleware-runner.ts +119 -0
- package/src/wirings/channel/channel-runner.ts +14 -15
- package/src/wirings/channel/channel.types.ts +17 -1
- 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 +47 -2
- package/src/wirings/channel/local/local-channel-runner.ts +22 -6
- package/src/wirings/channel/log-channels.ts +1 -1
- package/src/wirings/channel/serverless/index.ts +5 -1
- package/src/wirings/channel/serverless/serverless-channel-runner.ts +22 -6
- package/src/wirings/cli/channel/cli-channel-runner.ts +4 -3
- package/src/wirings/cli/channel/index.ts +1 -1
- package/src/wirings/cli/cli-runner.test.ts +28 -28
- package/src/wirings/cli/cli-runner.ts +27 -19
- package/src/wirings/cli/cli.types.ts +12 -11
- package/src/wirings/cli/command-parser.test.ts +8 -8
- 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 +5 -5
- package/src/wirings/http/http-runner.ts +80 -29
- package/src/wirings/http/http.types.ts +121 -23
- package/src/wirings/http/index.ts +16 -4
- package/src/wirings/http/log-http-routes.ts +1 -1
- package/src/wirings/http/routers/path-to-regex.test.ts +30 -19
- package/src/wirings/http/routers/path-to-regex.ts +2 -2
- package/src/wirings/mcp/index.ts +27 -3
- package/src/wirings/mcp/mcp-endpoint-registry.test.ts +3 -3
- package/src/wirings/mcp/mcp-runner.ts +56 -67
- package/src/wirings/mcp/mcp.types.ts +3 -3
- 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 +14 -2
- package/src/wirings/queue/queue-runner.test.ts +115 -73
- package/src/wirings/queue/queue-runner.ts +39 -13
- package/src/wirings/queue/queue.types.ts +12 -2
- package/src/wirings/rpc/index.ts +1 -1
- package/src/wirings/rpc/rpc-runner.ts +270 -34
- package/src/wirings/rpc/rpc-types.ts +21 -4
- package/src/wirings/scheduler/index.ts +7 -4
- package/src/wirings/scheduler/log-schedulers.ts +1 -1
- package/src/wirings/scheduler/scheduler-runner.test.ts +97 -53
- package/src/wirings/scheduler/scheduler-runner.ts +50 -10
- package/src/wirings/secret/index.ts +9 -0
- package/src/wirings/secret/secret.types.ts +32 -0
- package/src/wirings/secret/validate-secret-definitions.ts +82 -0
- package/src/wirings/trigger/index.ts +10 -0
- package/src/wirings/trigger/pikku-trigger-service.ts +134 -0
- package/src/wirings/trigger/trigger-runner.ts +138 -0
- package/src/wirings/trigger/trigger.types.ts +178 -0
- package/src/wirings/variable/index.ts +8 -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 +31 -0
- package/src/wirings/workflow/dsl/workflow-dsl.types.ts +320 -0
- package/src/wirings/workflow/dsl/workflow-runner.ts +28 -0
- package/src/wirings/workflow/graph/graph-node.ts +222 -0
- package/src/wirings/workflow/graph/graph-runner.test.ts +495 -0
- package/src/wirings/workflow/graph/graph-runner.ts +816 -0
- package/src/wirings/workflow/graph/index.ts +14 -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 +104 -0
- package/src/wirings/workflow/index.ts +64 -26
- package/src/wirings/workflow/pikku-workflow-service.test.ts +212 -0
- package/src/wirings/workflow/pikku-workflow-service.ts +571 -136
- package/src/wirings/workflow/workflow-helpers.ts +79 -0
- package/src/wirings/workflow/workflow-utils.ts +0 -0
- package/src/wirings/workflow/workflow.types.ts +123 -279
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/wirings/workflow/workflow-runner.d.ts +0 -34
- package/dist/wirings/workflow/workflow-runner.js +0 -65
- package/src/function/function-runner.ts.bak +0 -188
- package/src/wirings/workflow/workflow-runner.ts +0 -72
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,60 @@
|
|
|
1
|
+
## 0.12.0
|
|
2
|
+
|
|
3
|
+
### New Features
|
|
4
|
+
|
|
5
|
+
- AI agents with `pikkuAIAgent()` — define agents with tools, sub-agents, memory, structured output, and streaming via SSE
|
|
6
|
+
- AI middleware hooks (`pikkuAIMiddleware`) for input, stream, and output transformation
|
|
7
|
+
- Tool approval flow — suspend agent execution pending human approval
|
|
8
|
+
- Channel middleware (`pikkuChannelMiddleware`) for intercepting and transforming channel events
|
|
9
|
+
- Remote RPC — call functions across servers with `rpc.remote()` and `DeploymentService`
|
|
10
|
+
- HTTP route groups with `wireHTTPRoutes` for shared basePath, tags, and auth
|
|
11
|
+
- Workflow graph engine with `createGraph()` type-safe builder
|
|
12
|
+
- Workflow HTTP helpers: `workflow()`, `workflowStart()`, `workflowStatus()`, `graphStart()`
|
|
13
|
+
- Workflow DSL with rich step types (branch, parallel, fanout, switch, filter)
|
|
14
|
+
- Trigger system with `wireTrigger()` and `wireTriggerSource()`
|
|
15
|
+
- OAuth2 support with `wireOAuth2Credential` and `OAuth2Client`
|
|
16
|
+
- Secret and variable declarations with `wireSecret()` and `wireVariable()`
|
|
17
|
+
- `TypedSecretService` and `TypedVariablesService` for compile-time validated access
|
|
18
|
+
- `defineCLICommands` and `defineChannelRoutes` for external composition
|
|
19
|
+
- Built-in CORS middleware
|
|
20
|
+
- `disabled: true` support on all wirings and functions
|
|
21
|
+
- `createWireServices` and `createConfig` are now optional
|
|
22
|
+
- `InMemoryWorkflowService` and `InMemoryTriggerService` for testing
|
|
23
|
+
|
|
24
|
+
### Breaking Changes
|
|
25
|
+
|
|
26
|
+
- `PikkuInteraction` → `PikkuWire`, `CreateSessionServices` → `CreateWireServices`
|
|
27
|
+
- `wireForgeCredential` → `wireCredential`
|
|
28
|
+
- `startWorkflowByWire` → `startWorkflowByHTTPWire`
|
|
29
|
+
- Renamed all `forge` → `node` naming
|
|
30
|
+
- Renamed `credential` → `secret` across core types
|
|
31
|
+
- `WorkflowService.createRun` signature changed (new `inline`, `graphHash` params)
|
|
32
|
+
- Auth enforced by default for `pikkuFunc`
|
|
33
|
+
|
|
1
34
|
## 0.11.0
|
|
2
35
|
|
|
36
|
+
## 0.11.2
|
|
37
|
+
|
|
38
|
+
### Patch Changes
|
|
39
|
+
|
|
40
|
+
- db9c7bf: Add workflow graph system with type-safe builder
|
|
41
|
+
|
|
42
|
+
### Features
|
|
43
|
+
|
|
44
|
+
- f35e89da: Add workflow graph system with type-safe builder
|
|
45
|
+
- `createGraph<RPCMap>()` for building workflow graphs with full type safety
|
|
46
|
+
- `wireWorkflowGraph()` for registering workflow graphs
|
|
47
|
+
- `graphNode()` helper for type-safe node creation
|
|
48
|
+
- Graph scheduler for execution (continueGraph, startWorkflowGraph)
|
|
49
|
+
- TypedRef for type-safe input refs in workflow graphs
|
|
50
|
+
- `setBranchTaken` added to WorkflowService interface
|
|
51
|
+
- Trigger runner for workflow triggers
|
|
52
|
+
|
|
53
|
+
### Breaking Changes
|
|
54
|
+
|
|
55
|
+
- Rename `pikkuWorkflowFunc` to `pikkuWorkflowComplexFunc`
|
|
56
|
+
- Rename `pikkuWorkflowDSTFunc` to `pikkuWorkflowFunc`
|
|
57
|
+
|
|
3
58
|
## 0.11.1
|
|
4
59
|
|
|
5
60
|
### Patch Changes
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
const encoder = new TextEncoder();
|
|
2
|
+
const decoder = new TextDecoder();
|
|
3
|
+
const getSubtle = () => {
|
|
4
|
+
const crypto = globalThis.crypto;
|
|
5
|
+
if (!crypto?.subtle) {
|
|
6
|
+
throw new Error('WebCrypto not available');
|
|
7
|
+
}
|
|
8
|
+
return crypto.subtle;
|
|
9
|
+
};
|
|
10
|
+
const base64Encode = (bytes) => {
|
|
11
|
+
if (typeof Buffer !== 'undefined') {
|
|
12
|
+
return Buffer.from(bytes).toString('base64');
|
|
13
|
+
}
|
|
14
|
+
let binary = '';
|
|
15
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
16
|
+
binary += String.fromCharCode(bytes[i]);
|
|
17
|
+
}
|
|
18
|
+
return btoa(binary);
|
|
19
|
+
};
|
|
20
|
+
const base64Decode = (input) => {
|
|
21
|
+
if (typeof Buffer !== 'undefined') {
|
|
22
|
+
return new Uint8Array(Buffer.from(input, 'base64'));
|
|
23
|
+
}
|
|
24
|
+
const binary = atob(input);
|
|
25
|
+
const bytes = new Uint8Array(binary.length);
|
|
26
|
+
for (let i = 0; i < binary.length; i++) {
|
|
27
|
+
bytes[i] = binary.charCodeAt(i);
|
|
28
|
+
}
|
|
29
|
+
return bytes;
|
|
30
|
+
};
|
|
31
|
+
const toBase64Url = (bytes) => {
|
|
32
|
+
return base64Encode(bytes)
|
|
33
|
+
.replace(/\+/g, '-')
|
|
34
|
+
.replace(/\//g, '_')
|
|
35
|
+
.replace(/=+$/g, '');
|
|
36
|
+
};
|
|
37
|
+
const fromBase64Url = (input) => {
|
|
38
|
+
let base64 = input.replace(/-/g, '+').replace(/_/g, '/');
|
|
39
|
+
while (base64.length % 4 !== 0)
|
|
40
|
+
base64 += '=';
|
|
41
|
+
return base64Decode(base64);
|
|
42
|
+
};
|
|
43
|
+
const deriveKey = async (secret) => {
|
|
44
|
+
const subtle = getSubtle();
|
|
45
|
+
const hash = await subtle.digest('SHA-256', encoder.encode(secret));
|
|
46
|
+
return subtle.importKey('raw', hash, { name: 'AES-GCM' }, false, [
|
|
47
|
+
'encrypt',
|
|
48
|
+
'decrypt',
|
|
49
|
+
]);
|
|
50
|
+
};
|
|
51
|
+
export const encryptJSON = async (secret, value) => {
|
|
52
|
+
const crypto = globalThis.crypto;
|
|
53
|
+
if (!crypto?.getRandomValues) {
|
|
54
|
+
throw new Error('WebCrypto not available');
|
|
55
|
+
}
|
|
56
|
+
const subtle = getSubtle();
|
|
57
|
+
const iv = crypto.getRandomValues(new Uint8Array(12));
|
|
58
|
+
const key = await deriveKey(secret);
|
|
59
|
+
const plaintext = encoder.encode(JSON.stringify(value));
|
|
60
|
+
const encrypted = await subtle.encrypt({ name: 'AES-GCM', iv }, key, plaintext);
|
|
61
|
+
const cipherBytes = new Uint8Array(encrypted);
|
|
62
|
+
const out = new Uint8Array(iv.length + cipherBytes.length);
|
|
63
|
+
out.set(iv, 0);
|
|
64
|
+
out.set(cipherBytes, iv.length);
|
|
65
|
+
return toBase64Url(out);
|
|
66
|
+
};
|
|
67
|
+
export const decryptJSON = async (secret, token) => {
|
|
68
|
+
const subtle = getSubtle();
|
|
69
|
+
const data = fromBase64Url(token);
|
|
70
|
+
if (data.length < 13) {
|
|
71
|
+
throw new Error('Invalid encrypted payload');
|
|
72
|
+
}
|
|
73
|
+
const iv = data.slice(0, 12);
|
|
74
|
+
const ciphertext = data.slice(12);
|
|
75
|
+
const key = await deriveKey(secret);
|
|
76
|
+
const decrypted = await subtle.decrypt({ name: 'AES-GCM', iv }, key, ciphertext);
|
|
77
|
+
return JSON.parse(decoder.decode(new Uint8Array(decrypted)));
|
|
78
|
+
};
|
|
@@ -19,7 +19,7 @@ export class PikkuError extends Error {
|
|
|
19
19
|
* @param details - The details of the error.
|
|
20
20
|
*/
|
|
21
21
|
export const addError = (error, { status, message }) => {
|
|
22
|
-
pikkuState('misc', 'errors').set(error, { status, message });
|
|
22
|
+
pikkuState(null, 'misc', 'errors').set(error, { status, message });
|
|
23
23
|
};
|
|
24
24
|
/**
|
|
25
25
|
* Adds multiple errors to the API errors map.
|
|
@@ -36,10 +36,10 @@ export const addErrors = (errors) => {
|
|
|
36
36
|
* @returns An object containing the status and message, or undefined if the error is not found.
|
|
37
37
|
*/
|
|
38
38
|
export const getErrorResponse = (error) => {
|
|
39
|
-
const errors = Array.from(pikkuState('misc', 'errors').entries());
|
|
39
|
+
const errors = Array.from(pikkuState(null, 'misc', 'errors').entries());
|
|
40
40
|
const foundError = errors.find(([e]) => e.name === error.constructor.name);
|
|
41
41
|
if (foundError) {
|
|
42
42
|
return foundError[1];
|
|
43
43
|
}
|
|
44
|
-
return pikkuState('misc', 'errors').get(error);
|
|
44
|
+
return pikkuState(null, 'misc', 'errors').get(error);
|
|
45
45
|
};
|
package/dist/errors/errors.d.ts
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
import { PikkuError } from './error-handler.js';
|
|
5
5
|
export declare class InvalidMiddlewareWireError extends PikkuError {
|
|
6
6
|
}
|
|
7
|
+
export declare class PikkuMissingMetaError extends PikkuError {
|
|
8
|
+
}
|
|
7
9
|
/**
|
|
8
10
|
* The server cannot or will not process the request due to client error (e.g., malformed request syntax).
|
|
9
11
|
* @group Error
|
|
@@ -190,3 +192,9 @@ export declare class HTTPVersionNotSupportedError extends PikkuError {
|
|
|
190
192
|
*/
|
|
191
193
|
export declare class MaxComputeTimeReachedError extends PikkuError {
|
|
192
194
|
}
|
|
195
|
+
/**
|
|
196
|
+
* A required schema was not found during validation.
|
|
197
|
+
* @group Error
|
|
198
|
+
*/
|
|
199
|
+
export declare class MissingSchemaError extends PikkuError {
|
|
200
|
+
}
|
package/dist/errors/errors.js
CHANGED
|
@@ -8,6 +8,12 @@ addError(InvalidMiddlewareWireError, {
|
|
|
8
8
|
status: 500,
|
|
9
9
|
message: 'The middleware wire is invalid for the current wiring type.',
|
|
10
10
|
});
|
|
11
|
+
export class PikkuMissingMetaError extends PikkuError {
|
|
12
|
+
}
|
|
13
|
+
addError(PikkuMissingMetaError, {
|
|
14
|
+
status: 500,
|
|
15
|
+
message: 'Required metadata is missing',
|
|
16
|
+
});
|
|
11
17
|
/**
|
|
12
18
|
* The server cannot or will not process the request due to client error (e.g., malformed request syntax).
|
|
13
19
|
* @group Error
|
|
@@ -321,3 +327,13 @@ addError(MaxComputeTimeReachedError, {
|
|
|
321
327
|
status: 524,
|
|
322
328
|
message: 'The server took too long to complete the request, reaching the maximum compute time allowed.',
|
|
323
329
|
});
|
|
330
|
+
/**
|
|
331
|
+
* A required schema was not found during validation.
|
|
332
|
+
* @group Error
|
|
333
|
+
*/
|
|
334
|
+
export class MissingSchemaError extends PikkuError {
|
|
335
|
+
}
|
|
336
|
+
addError(MissingSchemaError, {
|
|
337
|
+
status: 500,
|
|
338
|
+
message: 'A required schema was not found. Ensure schema generation has been run.',
|
|
339
|
+
});
|
package/dist/errors/index.d.ts
CHANGED
package/dist/errors/index.js
CHANGED
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
import { CoreServices, CoreUserSession, CorePikkuMiddleware, PikkuWiringTypes, PikkuWire, MiddlewareMetadata, PermissionMetadata, CoreSingletonServices, CreateWireServices } from '../types/core.types.js';
|
|
2
|
+
import type { CorePikkuChannelMiddleware } from '../wirings/channel/channel.types.js';
|
|
2
3
|
import { CorePermissionGroup, CorePikkuFunctionConfig, CorePikkuPermission } from './functions.types.js';
|
|
3
4
|
import { SessionService } from '../services/user-session-service.js';
|
|
4
|
-
export declare const addFunction: (funcName: string, funcConfig: CorePikkuFunctionConfig<any, any
|
|
5
|
-
export declare const
|
|
6
|
-
export declare const
|
|
5
|
+
export declare const addFunction: (funcName: string, funcConfig: CorePikkuFunctionConfig<any, any>, packageName?: string | null) => void;
|
|
6
|
+
export declare const getFunctionNames: (packageName?: string | null) => string[];
|
|
7
|
+
export declare const getAllFunctionNames: () => string[];
|
|
8
|
+
export declare const runPikkuFuncDirectly: <In, Out>(funcName: string, allServices: CoreServices, wire: PikkuWire, data: In, userSession?: SessionService<CoreUserSession>, packageName?: string | null) => Promise<Out>;
|
|
9
|
+
export declare const runPikkuFunc: <In = any, Out = any>(wireType: PikkuWiringTypes, wireId: string, funcName: string, { singletonServices, createWireServices, data, auth: wiringAuth, inheritedMiddleware, wireMiddleware, inheritedChannelMiddleware, wireChannelMiddleware, inheritedPermissions, wirePermissions, coerceDataFromSchema, tags, wire, sessionService, packageName, }: {
|
|
7
10
|
singletonServices: CoreSingletonServices;
|
|
8
11
|
createWireServices?: CreateWireServices;
|
|
9
12
|
data: () => Promise<In> | In;
|
|
10
13
|
auth?: boolean;
|
|
11
14
|
inheritedMiddleware?: MiddlewareMetadata[];
|
|
12
15
|
wireMiddleware?: CorePikkuMiddleware[];
|
|
16
|
+
inheritedChannelMiddleware?: MiddlewareMetadata[];
|
|
17
|
+
wireChannelMiddleware?: CorePikkuChannelMiddleware[];
|
|
13
18
|
inheritedPermissions?: PermissionMetadata[];
|
|
14
19
|
wirePermissions?: CorePermissionGroup | CorePikkuPermission[];
|
|
15
20
|
coerceDataFromSchema?: boolean;
|
|
16
21
|
tags?: string[];
|
|
17
22
|
wire: PikkuWire;
|
|
23
|
+
sessionService?: SessionService<CoreUserSession>;
|
|
24
|
+
packageName?: string | null;
|
|
18
25
|
}) => Promise<Out>;
|
|
@@ -1,34 +1,121 @@
|
|
|
1
1
|
import { runMiddleware, combineMiddleware } from '../middleware-runner.js';
|
|
2
|
+
import { combineChannelMiddleware, wrapChannelWithMiddleware, } from '../wirings/channel/channel-middleware-runner.js';
|
|
2
3
|
import { runPermissions } from '../permissions.js';
|
|
3
4
|
import { pikkuState } from '../pikku-state.js';
|
|
4
5
|
import { coerceTopLevelDataFromSchema, validateSchema } from '../schema.js';
|
|
6
|
+
import { parseVersionedId } from '../version.js';
|
|
7
|
+
import { createFunctionSessionWireProps, } from '../services/user-session-service.js';
|
|
5
8
|
import { ForbiddenError } from '../errors/errors.js';
|
|
6
9
|
import { rpcService } from '../wirings/rpc/rpc-runner.js';
|
|
7
10
|
import { closeWireServices } from '../utils.js';
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Get or create singleton services for an external package.
|
|
13
|
+
* Services are cached in pikkuState to avoid recreation on each call.
|
|
14
|
+
*
|
|
15
|
+
* @param packageName - The external package name
|
|
16
|
+
* @param parentServices - The parent/caller's singleton services (used as base)
|
|
17
|
+
* @returns The package's singleton services
|
|
18
|
+
*/
|
|
19
|
+
const getOrCreatePackageSingletonServices = async (packageName, parentServices) => {
|
|
20
|
+
// Check if we already have cached singleton services for this package
|
|
21
|
+
const cachedServices = pikkuState(packageName, 'package', 'singletonServices');
|
|
22
|
+
if (cachedServices) {
|
|
23
|
+
return cachedServices;
|
|
24
|
+
}
|
|
25
|
+
// Get the package's service factories
|
|
26
|
+
const factories = pikkuState(packageName, 'package', 'factories');
|
|
27
|
+
if (!factories || !factories.createSingletonServices) {
|
|
28
|
+
// No factories registered, use parent services
|
|
29
|
+
return parentServices;
|
|
30
|
+
}
|
|
31
|
+
// Create config for the package (use parent config if no factory)
|
|
32
|
+
let config = parentServices.config;
|
|
33
|
+
if (factories.createConfig) {
|
|
34
|
+
config = await factories.createConfig(parentServices.variables);
|
|
35
|
+
}
|
|
36
|
+
// Create singleton services for the package, passing parent services as existing
|
|
37
|
+
const packageServices = await factories.createSingletonServices(config, parentServices);
|
|
38
|
+
// Cache the services
|
|
39
|
+
pikkuState(packageName, 'package', 'singletonServices', packageServices);
|
|
40
|
+
return packageServices;
|
|
41
|
+
};
|
|
42
|
+
export const addFunction = (funcName, funcConfig, packageName = null) => {
|
|
43
|
+
pikkuState(packageName, 'function', 'functions').set(funcName, funcConfig);
|
|
44
|
+
};
|
|
45
|
+
export const getFunctionNames = (packageName = null) => {
|
|
46
|
+
const functionsMeta = pikkuState(packageName, 'function', 'meta');
|
|
47
|
+
return Object.keys(functionsMeta);
|
|
10
48
|
};
|
|
11
|
-
export const
|
|
12
|
-
const
|
|
49
|
+
export const getAllFunctionNames = () => {
|
|
50
|
+
const functions = [];
|
|
51
|
+
const mainFunctionsMeta = pikkuState(null, 'function', 'meta');
|
|
52
|
+
functions.push(...Object.keys(mainFunctionsMeta));
|
|
53
|
+
const externalPackages = pikkuState(null, 'rpc', 'externalPackages');
|
|
54
|
+
for (const [namespace, config] of externalPackages) {
|
|
55
|
+
const packageFunctionsMeta = pikkuState(config.package, 'function', 'meta');
|
|
56
|
+
for (const funcName of Object.keys(packageFunctionsMeta)) {
|
|
57
|
+
functions.push(`${namespace}:${funcName}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return functions;
|
|
61
|
+
};
|
|
62
|
+
export const runPikkuFuncDirectly = async (funcName, allServices, wire, data, userSession, packageName = null) => {
|
|
63
|
+
const funcConfig = pikkuState(packageName, 'function', 'functions').get(funcName);
|
|
13
64
|
if (!funcConfig) {
|
|
14
65
|
throw new Error(`Function not found: ${funcName}`);
|
|
15
66
|
}
|
|
16
|
-
// Inject session into wire
|
|
17
67
|
const wireWithSession = {
|
|
18
68
|
...wire,
|
|
19
|
-
|
|
69
|
+
...(userSession && createFunctionSessionWireProps(userSession)),
|
|
20
70
|
};
|
|
21
71
|
return (await funcConfig.func(allServices, data, wireWithSession));
|
|
22
72
|
};
|
|
23
|
-
export const runPikkuFunc = async (wireType, wireId, funcName, { singletonServices, createWireServices, data, auth: wiringAuth, inheritedMiddleware, wireMiddleware, inheritedPermissions, wirePermissions, coerceDataFromSchema, tags = [], wire, }) => {
|
|
24
|
-
|
|
73
|
+
export const runPikkuFunc = async (wireType, wireId, funcName, { singletonServices, createWireServices, data, auth: wiringAuth, inheritedMiddleware, wireMiddleware, inheritedChannelMiddleware, wireChannelMiddleware, inheritedPermissions, wirePermissions, coerceDataFromSchema, tags = [], wire, sessionService, packageName = null, }) => {
|
|
74
|
+
wire = {
|
|
75
|
+
...wire,
|
|
76
|
+
wireType: wire.wireType ?? wireType,
|
|
77
|
+
wireId: wire.wireId ?? wireId,
|
|
78
|
+
};
|
|
79
|
+
const funcMap = pikkuState(packageName, 'function', 'functions');
|
|
80
|
+
let funcConfig = funcMap.get(funcName);
|
|
81
|
+
const allMeta = pikkuState(packageName, 'function', 'meta');
|
|
82
|
+
let funcMeta = allMeta[funcName];
|
|
83
|
+
if (!funcConfig || !funcMeta) {
|
|
84
|
+
const { baseName, version } = parseVersionedId(funcName);
|
|
85
|
+
if (version !== null) {
|
|
86
|
+
funcConfig = funcConfig || funcMap.get(baseName);
|
|
87
|
+
funcMeta = funcMeta || allMeta[baseName];
|
|
88
|
+
if (funcConfig && funcMeta) {
|
|
89
|
+
singletonServices.logger.warn(`Version '${funcName}' not registered, resolved to '${baseName}'`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
25
93
|
if (!funcConfig) {
|
|
26
94
|
throw new Error(`Function not found: ${funcName}`);
|
|
27
95
|
}
|
|
28
|
-
const funcMeta = pikkuState('function', 'meta')[funcName];
|
|
29
96
|
if (!funcMeta) {
|
|
30
97
|
throw new Error(`Function meta not found: ${funcName}`);
|
|
31
98
|
}
|
|
99
|
+
// For external packages, get or create their singleton services
|
|
100
|
+
const resolvedSingletonServices = packageName
|
|
101
|
+
? await getOrCreatePackageSingletonServices(packageName, singletonServices)
|
|
102
|
+
: singletonServices;
|
|
103
|
+
// Get the package's createWireServices if available
|
|
104
|
+
let resolvedCreateWireServices = createWireServices;
|
|
105
|
+
if (packageName) {
|
|
106
|
+
const factories = pikkuState(packageName, 'package', 'factories');
|
|
107
|
+
if (factories?.createWireServices) {
|
|
108
|
+
resolvedCreateWireServices = factories.createWireServices;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const allChannelMiddleware = combineChannelMiddleware(wireType, wireId, {
|
|
112
|
+
wireInheritedChannelMiddleware: inheritedChannelMiddleware,
|
|
113
|
+
wireChannelMiddleware,
|
|
114
|
+
packageName,
|
|
115
|
+
});
|
|
116
|
+
const resolvedWire = allChannelMiddleware.length > 0 && wire.channel
|
|
117
|
+
? wrapChannelWithMiddleware(wire, resolvedSingletonServices, allChannelMiddleware)
|
|
118
|
+
: wire;
|
|
32
119
|
// Convert tags to PermissionMetadata and merge with inheritedPermissions
|
|
33
120
|
const mergedInheritedPermissions = [
|
|
34
121
|
...(inheritedPermissions || []),
|
|
@@ -36,22 +123,36 @@ export const runPikkuFunc = async (wireType, wireId, funcName, { singletonServic
|
|
|
36
123
|
];
|
|
37
124
|
// Helper function to run permissions and execute the function
|
|
38
125
|
const executeFunction = async () => {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
126
|
+
const functionWireProps = sessionService
|
|
127
|
+
? createFunctionSessionWireProps(sessionService)
|
|
128
|
+
: undefined;
|
|
129
|
+
const wireWithSession = {
|
|
130
|
+
...resolvedWire,
|
|
131
|
+
...functionWireProps,
|
|
43
132
|
};
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (
|
|
133
|
+
const session = wireWithSession.session;
|
|
134
|
+
if (funcMeta.sessionless) {
|
|
135
|
+
if (wiringAuth === true || funcConfig.auth === true) {
|
|
136
|
+
if (!session) {
|
|
137
|
+
throw new ForbiddenError('Authentication required');
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
else if (funcMeta.sessionless === false) {
|
|
142
|
+
if (wiringAuth === false || funcConfig.auth === false) {
|
|
143
|
+
resolvedSingletonServices.logger.warn(`Function '${funcName}' requires a session but auth was explicitly disabled — use pikkuSessionlessFunc instead.`);
|
|
144
|
+
}
|
|
145
|
+
else if (!session) {
|
|
47
146
|
throw new ForbiddenError('Authentication required');
|
|
48
147
|
}
|
|
49
148
|
}
|
|
50
|
-
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
149
|
+
else {
|
|
150
|
+
// TODO: Remove after a couple of releases — backward compat for
|
|
151
|
+
// generated metadata that doesn't include the `sessionless` field yet.
|
|
152
|
+
if (wiringAuth === true || funcConfig.auth === true) {
|
|
153
|
+
if (!session) {
|
|
154
|
+
throw new ForbiddenError('Authentication required');
|
|
155
|
+
}
|
|
55
156
|
}
|
|
56
157
|
}
|
|
57
158
|
// Evaluate the data from the lazy function
|
|
@@ -60,10 +161,10 @@ export const runPikkuFunc = async (wireType, wireId, funcName, { singletonServic
|
|
|
60
161
|
const inputSchemaName = funcMeta.inputSchemaName;
|
|
61
162
|
if (inputSchemaName) {
|
|
62
163
|
// Validate request data against the defined schema, if any
|
|
63
|
-
await validateSchema(
|
|
164
|
+
await validateSchema(resolvedSingletonServices.logger, resolvedSingletonServices.schema, inputSchemaName, actualData, packageName);
|
|
64
165
|
// Coerce (top level) query string parameters or date objects if specified by the schema
|
|
65
166
|
if (coerceDataFromSchema) {
|
|
66
|
-
coerceTopLevelDataFromSchema(inputSchemaName, actualData);
|
|
167
|
+
coerceTopLevelDataFromSchema(inputSchemaName, actualData, packageName);
|
|
67
168
|
}
|
|
68
169
|
}
|
|
69
170
|
await runPermissions(wireType, wireId, {
|
|
@@ -71,22 +172,25 @@ export const runPikkuFunc = async (wireType, wireId, funcName, { singletonServic
|
|
|
71
172
|
wirePermissions: wirePermissions,
|
|
72
173
|
funcInheritedPermissions: funcMeta.permissions,
|
|
73
174
|
funcPermissions: funcConfig.permissions,
|
|
74
|
-
services:
|
|
75
|
-
wire: { ...
|
|
175
|
+
services: resolvedSingletonServices,
|
|
176
|
+
wire: { ...wireWithSession, rpc: undefined },
|
|
76
177
|
data: actualData,
|
|
178
|
+
packageName,
|
|
77
179
|
});
|
|
78
|
-
const wireServices = await
|
|
180
|
+
const wireServices = await resolvedCreateWireServices?.(resolvedSingletonServices, wireWithSession);
|
|
79
181
|
try {
|
|
80
|
-
const services = { ...
|
|
81
|
-
const rpc = rpcService.getContextRPCService(services,
|
|
182
|
+
const services = { ...resolvedSingletonServices, ...wireServices };
|
|
183
|
+
const rpc = rpcService.getContextRPCService(services, wireWithSession, {
|
|
184
|
+
sessionService,
|
|
185
|
+
});
|
|
82
186
|
return await funcConfig.func(services, actualData, {
|
|
83
|
-
...
|
|
187
|
+
...wireWithSession,
|
|
84
188
|
rpc,
|
|
85
189
|
});
|
|
86
190
|
}
|
|
87
191
|
finally {
|
|
88
192
|
if (wireServices) {
|
|
89
|
-
await closeWireServices(
|
|
193
|
+
await closeWireServices(resolvedSingletonServices.logger, wireServices);
|
|
90
194
|
}
|
|
91
195
|
}
|
|
92
196
|
};
|
|
@@ -95,9 +199,10 @@ export const runPikkuFunc = async (wireType, wireId, funcName, { singletonServic
|
|
|
95
199
|
wireMiddleware,
|
|
96
200
|
funcInheritedMiddleware: funcMeta.middleware,
|
|
97
201
|
funcMiddleware: funcConfig.middleware,
|
|
202
|
+
packageName,
|
|
98
203
|
});
|
|
99
204
|
if (allMiddleware.length > 0) {
|
|
100
|
-
return (await runMiddleware(
|
|
205
|
+
return (await runMiddleware(resolvedSingletonServices, resolvedWire, allMiddleware, executeFunction));
|
|
101
206
|
}
|
|
102
207
|
return (await executeFunction());
|
|
103
208
|
};
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import type { CoreServices, CoreSingletonServices, CoreUserSession, CorePikkuMiddleware, PikkuWire, PickRequired } from '../types/core.types.js';
|
|
2
|
-
import {
|
|
2
|
+
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
3
|
+
import type { CoreNodeConfig } from '../wirings/node/node.types.js';
|
|
4
|
+
/**
|
|
5
|
+
* @deprecated Use StandardSchemaV1 from @standard-schema/spec instead.
|
|
6
|
+
* This alias exists only for backward compatibility with generated code.
|
|
7
|
+
*/
|
|
8
|
+
export type ZodLike<T = any> = StandardSchemaV1<T, T>;
|
|
3
9
|
/**
|
|
4
10
|
* Represents a core API function that performs an operation using core services and a user session.
|
|
5
11
|
*
|
|
@@ -8,7 +14,7 @@ import { Session } from 'inspector';
|
|
|
8
14
|
* @template Services - The services type, defaults to `CoreServices`.
|
|
9
15
|
* @template Wire - The wire type, defaults to `PikkuWire<In, Out>`.
|
|
10
16
|
*/
|
|
11
|
-
export type CorePikkuFunction<In, Out, Services extends CoreSingletonServices = CoreServices, Wire extends PikkuWire<In, Out> = PikkuWire<In, Out, true, Session>> = (services: Services, data: In, wire: Wire) => Wire['channel'] extends null ? Promise<Out> : Promise<Out> | Promise<void>;
|
|
17
|
+
export type CorePikkuFunction<In, Out, Services extends CoreSingletonServices = CoreServices, Session extends CoreUserSession = CoreUserSession, Wire extends PikkuWire<In, Out> = PikkuWire<In, Out, true, Session>> = (services: Services, data: In, wire: Wire) => Wire['channel'] extends null ? Promise<Out> : Promise<Out> | Promise<void>;
|
|
12
18
|
/**
|
|
13
19
|
* Represents a core API function that can be used without a session.
|
|
14
20
|
*
|
|
@@ -17,7 +23,7 @@ export type CorePikkuFunction<In, Out, Services extends CoreSingletonServices =
|
|
|
17
23
|
* @template Services - The services type, defaults to `CoreServices`.
|
|
18
24
|
* @template Wire - The wire type, defaults to `PikkuWire<In, Out>`.
|
|
19
25
|
*/
|
|
20
|
-
export type CorePikkuFunctionSessionless<In, Out, Services extends CoreSingletonServices = CoreServices, Wire extends PikkuWire<In, Out, false,
|
|
26
|
+
export type CorePikkuFunctionSessionless<In, Out, Services extends CoreSingletonServices = CoreServices, Session extends CoreUserSession = CoreUserSession, Wire extends PikkuWire<In, Out, false, Session, any, any, any> = PikkuWire<In, Out, false, Session, any, any, any>> = (services: Services, data: In, wire: Wire) => Wire['channel'] extends null ? Promise<Out> : Promise<Out> | Promise<void>;
|
|
21
27
|
/**
|
|
22
28
|
* Represents a function that checks permissions for a given operation.
|
|
23
29
|
*
|
|
@@ -49,8 +55,8 @@ export type CorePikkuPermissionConfig<In = any, Services extends CoreSingletonSe
|
|
|
49
55
|
* ```typescript
|
|
50
56
|
* // Direct function syntax
|
|
51
57
|
* export const adminPermission = pikkuPermission(
|
|
52
|
-
* async ({ logger }, _data, {
|
|
53
|
-
* const currentSession = await
|
|
58
|
+
* async ({ logger }, _data, { getSession }) => {
|
|
59
|
+
* const currentSession = await getSession()
|
|
54
60
|
* return currentSession?.role === 'admin'
|
|
55
61
|
* }
|
|
56
62
|
* )
|
|
@@ -59,8 +65,8 @@ export type CorePikkuPermissionConfig<In = any, Services extends CoreSingletonSe
|
|
|
59
65
|
* export const adminPermission = pikkuPermission({
|
|
60
66
|
* name: 'Admin Permission',
|
|
61
67
|
* description: 'Checks if user has admin role',
|
|
62
|
-
* func: async ({ logger }, _data, {
|
|
63
|
-
* const currentSession = await
|
|
68
|
+
* func: async ({ logger }, _data, { getSession }) => {
|
|
69
|
+
* const currentSession = await getSession()
|
|
64
70
|
* return currentSession?.role === 'admin'
|
|
65
71
|
* }
|
|
66
72
|
* })
|
|
@@ -85,8 +91,8 @@ export type CorePikkuPermissionFactory<In = any, Services extends CoreSingletonS
|
|
|
85
91
|
* export const requireRole = pikkuPermissionFactory<{ role: string }>(({
|
|
86
92
|
* role
|
|
87
93
|
* }) => {
|
|
88
|
-
* return pikkuPermission(async ({ logger }, data, {
|
|
89
|
-
* const currentSession = await
|
|
94
|
+
* return pikkuPermission(async ({ logger }, data, { getSession }) => {
|
|
95
|
+
* const currentSession = await getSession()
|
|
90
96
|
* if (!currentSession || currentSession.role !== role) {
|
|
91
97
|
* logger.warn(`Permission denied: required role '${role}'`)
|
|
92
98
|
* return false
|
|
@@ -97,14 +103,31 @@ export type CorePikkuPermissionFactory<In = any, Services extends CoreSingletonS
|
|
|
97
103
|
* ```
|
|
98
104
|
*/
|
|
99
105
|
export declare const pikkuPermissionFactory: <In = any>(factory: CorePikkuPermissionFactory<In>) => CorePikkuPermissionFactory<In>;
|
|
100
|
-
export type
|
|
101
|
-
export type
|
|
106
|
+
export type CorePikkuAuth<Services extends CoreSingletonServices = CoreServices, Session extends CoreUserSession = CoreUserSession> = (services: Services, session: Session) => Promise<boolean> | boolean;
|
|
107
|
+
export type CorePikkuAuthConfig<Services extends CoreSingletonServices = CoreServices, Session extends CoreUserSession = CoreUserSession> = {
|
|
108
|
+
func: CorePikkuAuth<Services, Session>;
|
|
102
109
|
name?: string;
|
|
110
|
+
description?: string;
|
|
111
|
+
};
|
|
112
|
+
export declare const pikkuAuth: <Services extends CoreSingletonServices = CoreServices, Session extends CoreUserSession = CoreUserSession>(auth: CorePikkuAuth<Services, Session> | CorePikkuAuthConfig<Services, Session>) => CorePikkuPermission<any, Services, any>;
|
|
113
|
+
export type CorePermissionGroup<PikkuPermission = CorePikkuPermission<any>> = Record<string, PikkuPermission | PikkuPermission[]> | undefined;
|
|
114
|
+
export type CorePikkuFunctionConfig<PikkuFunction extends CorePikkuFunction<any, any, any, any, any> | CorePikkuFunctionSessionless<any, any, any, any, any>, PikkuPermission extends CorePikkuPermission<any, any, any> = CorePikkuPermission<any>, PikkuMiddleware extends CorePikkuMiddleware<any, any> = CorePikkuMiddleware<any, any>, InputSchema extends StandardSchemaV1 | undefined = undefined, OutputSchema extends StandardSchemaV1 | undefined = undefined> = {
|
|
115
|
+
/** Optional human-readable title for the function */
|
|
116
|
+
title?: string;
|
|
117
|
+
/** Optional description of what the function does */
|
|
118
|
+
description?: string;
|
|
119
|
+
override?: string;
|
|
120
|
+
version?: number;
|
|
103
121
|
tags?: string[];
|
|
104
122
|
expose?: boolean;
|
|
105
|
-
|
|
123
|
+
remote?: boolean;
|
|
124
|
+
mcp?: boolean;
|
|
125
|
+
requiresApproval?: boolean;
|
|
106
126
|
func: PikkuFunction;
|
|
107
127
|
auth?: boolean;
|
|
108
128
|
permissions?: CorePermissionGroup<PikkuPermission>;
|
|
109
129
|
middleware?: PikkuMiddleware[];
|
|
130
|
+
input?: InputSchema;
|
|
131
|
+
output?: OutputSchema;
|
|
132
|
+
node?: CoreNodeConfig;
|
|
110
133
|
};
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* ```typescript
|
|
7
7
|
* // Direct function syntax
|
|
8
8
|
* export const adminPermission = pikkuPermission(
|
|
9
|
-
* async ({ logger }, _data, {
|
|
10
|
-
* const currentSession = await
|
|
9
|
+
* async ({ logger }, _data, { getSession }) => {
|
|
10
|
+
* const currentSession = await getSession()
|
|
11
11
|
* return currentSession?.role === 'admin'
|
|
12
12
|
* }
|
|
13
13
|
* )
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
* export const adminPermission = pikkuPermission({
|
|
17
17
|
* name: 'Admin Permission',
|
|
18
18
|
* description: 'Checks if user has admin role',
|
|
19
|
-
* func: async ({ logger }, _data, {
|
|
20
|
-
* const currentSession = await
|
|
19
|
+
* func: async ({ logger }, _data, { getSession }) => {
|
|
20
|
+
* const currentSession = await getSession()
|
|
21
21
|
* return currentSession?.role === 'admin'
|
|
22
22
|
* }
|
|
23
23
|
* })
|
|
@@ -35,8 +35,8 @@ export const pikkuPermission = (permission) => {
|
|
|
35
35
|
* export const requireRole = pikkuPermissionFactory<{ role: string }>(({
|
|
36
36
|
* role
|
|
37
37
|
* }) => {
|
|
38
|
-
* return pikkuPermission(async ({ logger }, data, {
|
|
39
|
-
* const currentSession = await
|
|
38
|
+
* return pikkuPermission(async ({ logger }, data, { getSession }) => {
|
|
39
|
+
* const currentSession = await getSession()
|
|
40
40
|
* if (!currentSession || currentSession.role !== role) {
|
|
41
41
|
* logger.warn(`Permission denied: required role '${role}'`)
|
|
42
42
|
* return false
|
|
@@ -49,3 +49,13 @@ export const pikkuPermission = (permission) => {
|
|
|
49
49
|
export const pikkuPermissionFactory = (factory) => {
|
|
50
50
|
return factory;
|
|
51
51
|
};
|
|
52
|
+
export const pikkuAuth = (auth) => {
|
|
53
|
+
const fn = typeof auth === 'function' ? auth : auth.func;
|
|
54
|
+
const wrapper = async (services, _data, wire) => {
|
|
55
|
+
const session = wire.session;
|
|
56
|
+
if (!session)
|
|
57
|
+
return false;
|
|
58
|
+
return fn(services, session);
|
|
59
|
+
};
|
|
60
|
+
return wrapper;
|
|
61
|
+
};
|
package/dist/function/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
1
|
+
export { addFunction, getAllFunctionNames } from './function-runner.js';
|
|
2
|
+
export type { CorePikkuFunction, CorePikkuFunctionSessionless, } from './functions.types.js';
|
package/dist/function/index.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
export * from './functions.types.js';
|
|
1
|
+
export { addFunction, getAllFunctionNames } from './function-runner.js';
|