@pikku/core 0.11.0 → 0.11.2

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.
Files changed (184) hide show
  1. package/CHANGELOG.md +35 -1
  2. package/dist/errors/error-handler.js +3 -3
  3. package/dist/errors/errors.d.ts +1 -1
  4. package/dist/errors/errors.js +3 -3
  5. package/dist/function/function-runner.d.ts +8 -8
  6. package/dist/function/function-runner.js +88 -23
  7. package/dist/function/functions.types.d.ts +104 -33
  8. package/dist/function/functions.types.js +50 -7
  9. package/dist/handle-error.d.ts +1 -1
  10. package/dist/handle-error.js +1 -1
  11. package/dist/index.d.ts +6 -2
  12. package/dist/index.js +5 -2
  13. package/dist/middleware/auth-apikey.d.ts +1 -1
  14. package/dist/middleware/auth-apikey.js +3 -3
  15. package/dist/middleware/auth-bearer.d.ts +1 -1
  16. package/dist/middleware/auth-bearer.js +3 -3
  17. package/dist/middleware/auth-cookie.d.ts +1 -1
  18. package/dist/middleware/auth-cookie.js +5 -5
  19. package/dist/middleware/timeout.d.ts +1 -1
  20. package/dist/middleware/timeout.js +3 -2
  21. package/dist/middleware-runner.d.ts +6 -20
  22. package/dist/middleware-runner.js +19 -20
  23. package/dist/permissions.d.ts +6 -89
  24. package/dist/permissions.js +24 -81
  25. package/dist/pikku-state.d.ts +32 -104
  26. package/dist/pikku-state.js +140 -66
  27. package/dist/schema.d.ts +8 -6
  28. package/dist/schema.js +25 -13
  29. package/dist/services/user-session-service.d.ts +7 -3
  30. package/dist/services/user-session-service.js +8 -1
  31. package/dist/services/workflow-service.d.ts +38 -0
  32. package/dist/services/workflow-service.js +1 -0
  33. package/dist/types/core.types.d.ts +40 -41
  34. package/dist/types/core.types.js +4 -15
  35. package/dist/types/state.types.d.ts +135 -0
  36. package/dist/types/state.types.js +1 -0
  37. package/dist/utils.d.ts +9 -1
  38. package/dist/utils.js +48 -3
  39. package/dist/wirings/channel/channel-common.js +2 -3
  40. package/dist/wirings/channel/channel-handler.d.ts +3 -2
  41. package/dist/wirings/channel/channel-handler.js +7 -10
  42. package/dist/wirings/channel/channel-runner.d.ts +2 -2
  43. package/dist/wirings/channel/channel-runner.js +5 -5
  44. package/dist/wirings/channel/channel.types.d.ts +10 -5
  45. package/dist/wirings/channel/local/local-channel-runner.d.ts +1 -1
  46. package/dist/wirings/channel/local/local-channel-runner.js +19 -26
  47. package/dist/wirings/channel/log-channels.js +1 -1
  48. package/dist/wirings/channel/serverless/serverless-channel-runner.d.ts +1 -1
  49. package/dist/wirings/channel/serverless/serverless-channel-runner.js +43 -48
  50. package/dist/wirings/cli/channel/cli-channel-runner.js +3 -2
  51. package/dist/wirings/cli/cli-runner.d.ts +5 -5
  52. package/dist/wirings/cli/cli-runner.js +20 -38
  53. package/dist/wirings/cli/cli.types.d.ts +16 -11
  54. package/dist/wirings/forge-node/forge-node.types.d.ts +120 -0
  55. package/dist/wirings/forge-node/forge-node.types.js +38 -0
  56. package/dist/wirings/forge-node/index.d.ts +1 -0
  57. package/dist/wirings/forge-node/index.js +1 -0
  58. package/dist/wirings/http/http-runner.d.ts +8 -8
  59. package/dist/wirings/http/http-runner.js +46 -51
  60. package/dist/wirings/http/http.types.d.ts +19 -11
  61. package/dist/wirings/http/log-http-routes.js +1 -1
  62. package/dist/wirings/http/routers/path-to-regex.js +2 -2
  63. package/dist/wirings/mcp/mcp-runner.d.ts +2 -2
  64. package/dist/wirings/mcp/mcp-runner.js +33 -40
  65. package/dist/wirings/mcp/mcp.types.d.ts +6 -0
  66. package/dist/wirings/queue/queue-runner.d.ts +3 -3
  67. package/dist/wirings/queue/queue-runner.js +13 -23
  68. package/dist/wirings/queue/queue.types.d.ts +4 -11
  69. package/dist/wirings/rpc/index.d.ts +1 -1
  70. package/dist/wirings/rpc/index.js +1 -1
  71. package/dist/wirings/rpc/rpc-runner.d.ts +17 -16
  72. package/dist/wirings/rpc/rpc-runner.js +98 -61
  73. package/dist/wirings/rpc/rpc-types.d.ts +7 -0
  74. package/dist/wirings/scheduler/log-schedulers.js +1 -1
  75. package/dist/wirings/scheduler/scheduler-runner.d.ts +3 -3
  76. package/dist/wirings/scheduler/scheduler-runner.js +18 -29
  77. package/dist/wirings/scheduler/scheduler.types.d.ts +3 -8
  78. package/dist/wirings/trigger/index.d.ts +2 -0
  79. package/dist/wirings/trigger/index.js +2 -0
  80. package/dist/wirings/trigger/trigger-runner.d.ts +29 -0
  81. package/dist/wirings/trigger/trigger-runner.js +57 -0
  82. package/dist/wirings/trigger/trigger.types.d.ts +42 -0
  83. package/dist/wirings/trigger/trigger.types.js +1 -0
  84. package/dist/wirings/workflow/dsl/index.d.ts +5 -0
  85. package/dist/wirings/workflow/dsl/index.js +4 -0
  86. package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +286 -0
  87. package/dist/wirings/workflow/dsl/workflow-dsl.types.js +5 -0
  88. package/dist/wirings/workflow/dsl/workflow-runner.d.ts +5 -0
  89. package/dist/wirings/workflow/dsl/workflow-runner.js +22 -0
  90. package/dist/wirings/workflow/graph/graph-node.d.ts +122 -0
  91. package/dist/wirings/workflow/graph/graph-node.js +58 -0
  92. package/dist/wirings/workflow/graph/graph-runner.d.ts +35 -0
  93. package/dist/wirings/workflow/graph/graph-runner.js +452 -0
  94. package/dist/wirings/workflow/graph/index.d.ts +3 -0
  95. package/dist/wirings/workflow/graph/index.js +3 -0
  96. package/dist/wirings/workflow/graph/workflow-graph.types.d.ts +95 -0
  97. package/dist/wirings/workflow/graph/workflow-graph.types.js +15 -0
  98. package/dist/wirings/workflow/index.d.ts +7 -3
  99. package/dist/wirings/workflow/index.js +6 -3
  100. package/dist/wirings/workflow/pikku-workflow-service.d.ts +108 -10
  101. package/dist/wirings/workflow/pikku-workflow-service.js +274 -165
  102. package/dist/wirings/workflow/wire-workflow.d.ts +42 -0
  103. package/dist/wirings/workflow/wire-workflow.js +53 -0
  104. package/dist/wirings/workflow/workflow-utils.d.ts +23 -0
  105. package/dist/wirings/workflow/workflow-utils.js +66 -0
  106. package/dist/wirings/workflow/workflow.types.d.ts +135 -128
  107. package/package.json +11 -2
  108. package/src/errors/error-handler.ts +3 -3
  109. package/src/errors/errors.ts +3 -3
  110. package/src/factory-functions.test.ts +9 -36
  111. package/src/function/function-runner.test.ts +58 -69
  112. package/src/function/function-runner.ts +130 -37
  113. package/src/function/functions.types.ts +193 -54
  114. package/src/handle-error.ts +1 -1
  115. package/src/index.ts +10 -5
  116. package/src/middleware/auth-apikey.test.ts +360 -0
  117. package/src/middleware/auth-apikey.ts +3 -7
  118. package/src/middleware/auth-bearer.test.ts +447 -0
  119. package/src/middleware/auth-bearer.ts +27 -33
  120. package/src/middleware/auth-cookie.test.ts +525 -0
  121. package/src/middleware/auth-cookie.ts +6 -6
  122. package/src/middleware/timeout.ts +4 -2
  123. package/src/middleware-runner.test.ts +58 -127
  124. package/src/middleware-runner.ts +29 -25
  125. package/src/permissions.test.ts +68 -130
  126. package/src/permissions.ts +41 -100
  127. package/src/pikku-state.ts +156 -201
  128. package/src/schema.ts +42 -13
  129. package/src/services/user-session-service.ts +14 -4
  130. package/src/services/workflow-service.ts +74 -0
  131. package/src/types/core.types.ts +79 -58
  132. package/src/types/state.types.ts +195 -0
  133. package/src/utils.ts +59 -4
  134. package/src/wirings/channel/channel-common.ts +4 -7
  135. package/src/wirings/channel/channel-handler.ts +17 -23
  136. package/src/wirings/channel/channel-runner.ts +7 -7
  137. package/src/wirings/channel/channel.types.ts +14 -11
  138. package/src/wirings/channel/local/local-channel-runner.test.ts +8 -4
  139. package/src/wirings/channel/local/local-channel-runner.ts +23 -38
  140. package/src/wirings/channel/log-channels.ts +1 -1
  141. package/src/wirings/channel/serverless/serverless-channel-runner.ts +53 -79
  142. package/src/wirings/cli/channel/cli-channel-runner.ts +4 -3
  143. package/src/wirings/cli/cli-runner.test.ts +26 -26
  144. package/src/wirings/cli/cli-runner.ts +34 -71
  145. package/src/wirings/cli/cli.types.ts +23 -16
  146. package/src/wirings/forge-node/forge-node.types.ts +135 -0
  147. package/src/wirings/forge-node/index.ts +1 -0
  148. package/src/wirings/http/http-runner.test.ts +10 -10
  149. package/src/wirings/http/http-runner.ts +56 -66
  150. package/src/wirings/http/http.types.ts +19 -14
  151. package/src/wirings/http/log-http-routes.ts +1 -1
  152. package/src/wirings/http/routers/path-to-regex.test.ts +30 -19
  153. package/src/wirings/http/routers/path-to-regex.ts +2 -2
  154. package/src/wirings/mcp/mcp-runner.ts +44 -69
  155. package/src/wirings/mcp/mcp.types.ts +6 -0
  156. package/src/wirings/queue/queue-runner.test.ts +641 -0
  157. package/src/wirings/queue/queue-runner.ts +16 -38
  158. package/src/wirings/queue/queue.types.ts +4 -11
  159. package/src/wirings/rpc/index.ts +1 -1
  160. package/src/wirings/rpc/rpc-runner.ts +129 -77
  161. package/src/wirings/rpc/rpc-types.ts +8 -0
  162. package/src/wirings/scheduler/log-schedulers.ts +1 -1
  163. package/src/wirings/scheduler/scheduler-runner.test.ts +627 -0
  164. package/src/wirings/scheduler/scheduler-runner.ts +29 -55
  165. package/src/wirings/scheduler/scheduler.types.ts +3 -9
  166. package/src/wirings/trigger/index.ts +2 -0
  167. package/src/wirings/trigger/trigger-runner.ts +96 -0
  168. package/src/wirings/trigger/trigger.types.ts +56 -0
  169. package/src/wirings/workflow/dsl/index.ts +30 -0
  170. package/src/wirings/workflow/dsl/workflow-dsl.types.ts +312 -0
  171. package/src/wirings/workflow/dsl/workflow-runner.ts +27 -0
  172. package/src/wirings/workflow/graph/graph-node.ts +227 -0
  173. package/src/wirings/workflow/graph/graph-runner.ts +694 -0
  174. package/src/wirings/workflow/graph/index.ts +3 -0
  175. package/src/wirings/workflow/graph/workflow-graph.types.ts +126 -0
  176. package/src/wirings/workflow/index.ts +60 -12
  177. package/src/wirings/workflow/pikku-workflow-service.ts +401 -195
  178. package/src/wirings/workflow/wire-workflow.ts +94 -0
  179. package/src/wirings/workflow/workflow-utils.ts +120 -0
  180. package/src/wirings/workflow/workflow.types.ts +167 -188
  181. package/tsconfig.tsbuildinfo +1 -1
  182. package/dist/wirings/workflow/workflow-runner.d.ts +0 -35
  183. package/dist/wirings/workflow/workflow-runner.js +0 -68
  184. package/src/wirings/workflow/workflow-runner.ts +0 -85
package/CHANGELOG.md CHANGED
@@ -1,12 +1,46 @@
1
1
  ## 0.11.0
2
2
 
3
+ ## 0.11.2
4
+
5
+ ### Patch Changes
6
+
7
+ - db9c7bf: Add workflow graph system with type-safe builder
8
+
9
+ ## 0.11.2
10
+
11
+ ### Features
12
+
13
+ - f35e89da: Add workflow graph system with type-safe builder
14
+ - `createGraph<RPCMap>()` for building workflow graphs with full type safety
15
+ - `wireWorkflowGraph()` for registering workflow graphs
16
+ - `graphNode()` helper for type-safe node creation
17
+ - Graph scheduler for execution (continueGraph, startWorkflowGraph)
18
+ - TypedRef for type-safe input refs in workflow graphs
19
+ - `setBranchTaken` added to WorkflowService interface
20
+ - Trigger runner for workflow triggers
21
+
22
+ ### Breaking Changes
23
+
24
+ - Rename `pikkuWorkflowFunc` to `pikkuWorkflowComplexFunc`
25
+ - Rename `pikkuWorkflowDSTFunc` to `pikkuWorkflowFunc`
26
+
27
+ ## 0.11.1
28
+
29
+ ### Patch Changes
30
+
31
+ - 4b811db: chore: updating all dependencies
32
+ - e12a00c: feat: adding initialSession to PikkuWire which is correctly typed (undefined / not depending on function type)
33
+ - 4579434: breaking: changing the signature of functions
34
+ - 28aeb7f: breaking: extract docs in the wiring meta
35
+ - ce902b1: feat: adding in pikkuSimpleWorkflowFunc
36
+ - 06e1a31: breaking: change session services to wire services
37
+
3
38
  ### Minor Changes
4
39
 
5
40
  - Add workflow orchestration engine with step execution and retries
6
41
  - Add scheduler service abstraction
7
42
  - Remove file-based channel and eventhub stores
8
43
 
9
-
10
44
  # @pikku/core
11
45
 
12
46
  ## 0.10.2
@@ -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
  };
@@ -2,7 +2,7 @@
2
2
  * The server cannot or will not process the request due to client error (e.g., malformed request syntax).
3
3
  */
4
4
  import { PikkuError } from './error-handler.js';
5
- export declare class InvalidMiddlewareInteractionError extends PikkuError {
5
+ export declare class InvalidMiddlewareWireError extends PikkuError {
6
6
  }
7
7
  /**
8
8
  * The server cannot or will not process the request due to client error (e.g., malformed request syntax).
@@ -2,11 +2,11 @@
2
2
  * The server cannot or will not process the request due to client error (e.g., malformed request syntax).
3
3
  */
4
4
  import { addError, PikkuError } from './error-handler.js';
5
- export class InvalidMiddlewareInteractionError extends PikkuError {
5
+ export class InvalidMiddlewareWireError extends PikkuError {
6
6
  }
7
- addError(InvalidMiddlewareInteractionError, {
7
+ addError(InvalidMiddlewareWireError, {
8
8
  status: 500,
9
- message: 'The middleware interaction is invalid for the current wiring type.',
9
+ message: 'The middleware wire is invalid for the current wiring type.',
10
10
  });
11
11
  /**
12
12
  * The server cannot or will not process the request due to client error (e.g., malformed request syntax).
@@ -1,12 +1,11 @@
1
- import { CoreServices, CoreUserSession, CorePikkuMiddleware, PikkuWiringTypes, CoreSingletonServices, PikkuInteraction, MiddlewareMetadata, PermissionMetadata } from '../types/core.types.js';
1
+ import { CoreServices, CoreUserSession, CorePikkuMiddleware, PikkuWiringTypes, PikkuWire, MiddlewareMetadata, PermissionMetadata, CoreSingletonServices, CreateWireServices } from '../types/core.types.js';
2
2
  import { CorePermissionGroup, CorePikkuFunctionConfig, CorePikkuPermission } from './functions.types.js';
3
- import { UserSessionService } from '../services/user-session-service.js';
4
- export declare const addFunction: (funcName: string, funcConfig: CorePikkuFunctionConfig<any, any>) => void;
5
- export declare const runPikkuFuncDirectly: <In, Out>(funcName: string, allServices: CoreServices, data: In, session?: CoreUserSession) => Promise<Out>;
6
- export declare const runPikkuFunc: <In = any, Out = any>(wireType: PikkuWiringTypes, wireId: string, funcName: string, { getAllServices, singletonServices, data, userSession, auth: wiringAuth, inheritedMiddleware, wireMiddleware, inheritedPermissions, wirePermissions, coerceDataFromSchema, tags, interaction, }: {
3
+ import { SessionService } from '../services/user-session-service.js';
4
+ export declare const addFunction: (funcName: string, funcConfig: CorePikkuFunctionConfig<any, any>, packageName?: string | null) => void;
5
+ export declare const runPikkuFuncDirectly: <In, Out>(funcName: string, allServices: CoreServices, wire: PikkuWire, data: In, userSession?: SessionService<CoreUserSession>, packageName?: string | null) => Promise<Out>;
6
+ export declare const runPikkuFunc: <In = any, Out = any>(wireType: PikkuWiringTypes, wireId: string, funcName: string, { singletonServices, createWireServices, data, auth: wiringAuth, inheritedMiddleware, wireMiddleware, inheritedPermissions, wirePermissions, coerceDataFromSchema, tags, wire, packageName, }: {
7
7
  singletonServices: CoreSingletonServices;
8
- getAllServices: (session?: CoreUserSession) => Promise<CoreServices> | CoreServices;
9
- userSession?: UserSessionService<CoreUserSession>;
8
+ createWireServices?: CreateWireServices;
10
9
  data: () => Promise<In> | In;
11
10
  auth?: boolean;
12
11
  inheritedMiddleware?: MiddlewareMetadata[];
@@ -15,5 +14,6 @@ export declare const runPikkuFunc: <In = any, Out = any>(wireType: PikkuWiringTy
15
14
  wirePermissions?: CorePermissionGroup | CorePikkuPermission[];
16
15
  coerceDataFromSchema?: boolean;
17
16
  tags?: string[];
18
- interaction: PikkuInteraction;
17
+ wire: PikkuWire;
18
+ packageName?: string | null;
19
19
  }) => Promise<Out>;
@@ -3,25 +3,76 @@ import { runPermissions } from '../permissions.js';
3
3
  import { pikkuState } from '../pikku-state.js';
4
4
  import { coerceTopLevelDataFromSchema, validateSchema } from '../schema.js';
5
5
  import { ForbiddenError } from '../errors/errors.js';
6
- export const addFunction = (funcName, funcConfig) => {
7
- pikkuState('function', 'functions').set(funcName, funcConfig);
6
+ import { rpcService } from '../wirings/rpc/rpc-runner.js';
7
+ import { closeWireServices } from '../utils.js';
8
+ /**
9
+ * Get or create singleton services for an external package.
10
+ * Services are cached in pikkuState to avoid recreation on each call.
11
+ *
12
+ * @param packageName - The external package name
13
+ * @param parentServices - The parent/caller's singleton services (used as base)
14
+ * @returns The package's singleton services
15
+ */
16
+ const getOrCreatePackageSingletonServices = async (packageName, parentServices) => {
17
+ // Check if we already have cached singleton services for this package
18
+ const cachedServices = pikkuState(packageName, 'package', 'singletonServices');
19
+ if (cachedServices) {
20
+ return cachedServices;
21
+ }
22
+ // Get the package's service factories
23
+ const factories = pikkuState(packageName, 'package', 'factories');
24
+ if (!factories || !factories.createSingletonServices) {
25
+ // No factories registered, use parent services
26
+ return parentServices;
27
+ }
28
+ // Create config for the package (use parent config if no factory)
29
+ let config = parentServices.config;
30
+ if (factories.createConfig) {
31
+ config = await factories.createConfig(parentServices.variables);
32
+ }
33
+ // Create singleton services for the package, passing parent services as existing
34
+ const packageServices = await factories.createSingletonServices(config, parentServices);
35
+ // Cache the services
36
+ pikkuState(packageName, 'package', 'singletonServices', packageServices);
37
+ return packageServices;
8
38
  };
9
- export const runPikkuFuncDirectly = async (funcName, allServices, data, session) => {
10
- const funcConfig = pikkuState('function', 'functions').get(funcName);
39
+ export const addFunction = (funcName, funcConfig, packageName = null) => {
40
+ pikkuState(packageName, 'function', 'functions').set(funcName, funcConfig);
41
+ };
42
+ export const runPikkuFuncDirectly = async (funcName, allServices, wire, data, userSession, packageName = null) => {
43
+ const funcConfig = pikkuState(packageName, 'function', 'functions').get(funcName);
11
44
  if (!funcConfig) {
12
45
  throw new Error(`Function not found: ${funcName}`);
13
46
  }
14
- return (await funcConfig.func(allServices, data, session));
47
+ // Inject session into wire
48
+ const wireWithSession = {
49
+ ...wire,
50
+ session: userSession,
51
+ };
52
+ return (await funcConfig.func(allServices, data, wireWithSession));
15
53
  };
16
- export const runPikkuFunc = async (wireType, wireId, funcName, { getAllServices, singletonServices, data, userSession, auth: wiringAuth, inheritedMiddleware, wireMiddleware, inheritedPermissions, wirePermissions, coerceDataFromSchema, tags = [], interaction, }) => {
17
- const funcConfig = pikkuState('function', 'functions').get(funcName);
54
+ export const runPikkuFunc = async (wireType, wireId, funcName, { singletonServices, createWireServices, data, auth: wiringAuth, inheritedMiddleware, wireMiddleware, inheritedPermissions, wirePermissions, coerceDataFromSchema, tags = [], wire, packageName = null, }) => {
55
+ const funcConfig = pikkuState(packageName, 'function', 'functions').get(funcName);
18
56
  if (!funcConfig) {
19
57
  throw new Error(`Function not found: ${funcName}`);
20
58
  }
21
- const funcMeta = pikkuState('function', 'meta')[funcName];
59
+ const allMeta = pikkuState(packageName, 'function', 'meta');
60
+ const funcMeta = allMeta[funcName];
22
61
  if (!funcMeta) {
23
62
  throw new Error(`Function meta not found: ${funcName}`);
24
63
  }
64
+ // For external packages, get or create their singleton services
65
+ const resolvedSingletonServices = packageName
66
+ ? await getOrCreatePackageSingletonServices(packageName, singletonServices)
67
+ : singletonServices;
68
+ // Get the package's createWireServices if available
69
+ let resolvedCreateWireServices = createWireServices;
70
+ if (packageName) {
71
+ const factories = pikkuState(packageName, 'package', 'factories');
72
+ if (factories?.createWireServices) {
73
+ resolvedCreateWireServices = factories.createWireServices;
74
+ }
75
+ }
25
76
  // Convert tags to PermissionMetadata and merge with inheritedPermissions
26
77
  const mergedInheritedPermissions = [
27
78
  ...(inheritedPermissions || []),
@@ -29,16 +80,21 @@ export const runPikkuFunc = async (wireType, wireId, funcName, { getAllServices,
29
80
  ];
30
81
  // Helper function to run permissions and execute the function
31
82
  const executeFunction = async () => {
32
- const session = await userSession?.get();
83
+ const initialSession = wire.session?.freezeInitial();
84
+ const wireWithInitialSession = {
85
+ ...wire,
86
+ initialSession,
87
+ };
33
88
  if (wiringAuth === true || funcConfig.auth === true) {
34
89
  // This means it was explicitly enabled in either wiring or function and has to be respected
35
- if (!session) {
90
+ if (!initialSession) {
36
91
  throw new ForbiddenError('Authentication required');
37
92
  }
38
93
  }
39
94
  if (wiringAuth === undefined && funcConfig.auth === undefined) {
40
95
  // We always default to requiring auth unless explicitly disabled
41
- if (!session) {
96
+ if (!initialSession) {
97
+ // TODO: Critical, we need to figure out how to make this work with different wirings
42
98
  // throw new ForbiddenError('Authentication required')
43
99
  }
44
100
  }
@@ -48,37 +104,46 @@ export const runPikkuFunc = async (wireType, wireId, funcName, { getAllServices,
48
104
  const inputSchemaName = funcMeta.inputSchemaName;
49
105
  if (inputSchemaName) {
50
106
  // Validate request data against the defined schema, if any
51
- await validateSchema(singletonServices.logger, singletonServices.schema, inputSchemaName, actualData);
107
+ await validateSchema(resolvedSingletonServices.logger, resolvedSingletonServices.schema, inputSchemaName, actualData, packageName);
52
108
  // Coerce (top level) query string parameters or date objects if specified by the schema
53
109
  if (coerceDataFromSchema) {
54
- coerceTopLevelDataFromSchema(inputSchemaName, actualData);
110
+ coerceTopLevelDataFromSchema(inputSchemaName, actualData, packageName);
55
111
  }
56
112
  }
57
- const allServices = await getAllServices(session);
58
- // Run permissions check with combined permissions: inheritedPermissions (including tags) → wirePermissions → funcPermissions
59
113
  await runPermissions(wireType, wireId, {
60
114
  wireInheritedPermissions: mergedInheritedPermissions,
61
115
  wirePermissions: wirePermissions,
62
116
  funcInheritedPermissions: funcMeta.permissions,
63
117
  funcPermissions: funcConfig.permissions,
64
- allServices,
118
+ services: resolvedSingletonServices,
119
+ wire: { ...wireWithInitialSession, rpc: undefined },
65
120
  data: actualData,
66
- session,
121
+ packageName,
67
122
  });
68
- return await funcConfig.func(allServices, actualData, session);
123
+ const wireServices = await resolvedCreateWireServices?.(resolvedSingletonServices, wireWithInitialSession);
124
+ try {
125
+ const services = { ...resolvedSingletonServices, ...wireServices };
126
+ const rpc = rpcService.getContextRPCService(services, wireWithInitialSession);
127
+ return await funcConfig.func(services, actualData, {
128
+ ...wireWithInitialSession,
129
+ rpc,
130
+ });
131
+ }
132
+ finally {
133
+ if (wireServices) {
134
+ await closeWireServices(resolvedSingletonServices.logger, wireServices);
135
+ }
136
+ }
69
137
  };
70
- // Combine all middleware: inheritedMiddleware → wireMiddleware → funcMiddleware
71
138
  const allMiddleware = combineMiddleware(wireType, wireId, {
72
139
  wireInheritedMiddleware: inheritedMiddleware,
73
140
  wireMiddleware,
74
141
  funcInheritedMiddleware: funcMeta.middleware,
75
142
  funcMiddleware: funcConfig.middleware,
143
+ packageName,
76
144
  });
77
145
  if (allMiddleware.length > 0) {
78
- return (await runMiddleware({
79
- ...singletonServices,
80
- userSession,
81
- }, interaction, allMiddleware, executeFunction));
146
+ return (await runMiddleware(resolvedSingletonServices, wire, allMiddleware, executeFunction));
82
147
  }
83
148
  return (await executeFunction());
84
149
  };
@@ -1,33 +1,23 @@
1
- import { PikkuChannel } from '../wirings/channel/channel.types.js';
2
- import type { CoreServices, CoreSingletonServices, CoreUserSession, PikkuDocs, CorePikkuMiddleware } from '../types/core.types.js';
1
+ import type { CoreServices, CoreSingletonServices, CoreUserSession, CorePikkuMiddleware, PikkuWire, PickRequired } from '../types/core.types.js';
2
+ import { Session } from 'inspector';
3
3
  /**
4
4
  * Represents a core API function that performs an operation using core services and a user session.
5
5
  *
6
6
  * @template In - The input type.
7
7
  * @template Out - The output type.
8
- * @template ChannelData - The channel data type.
9
8
  * @template Services - The services type, defaults to `CoreServices`.
10
- * @template Session - The session type, defaults to `CoreUserSession`.
9
+ * @template Wire - The wire type, defaults to `PikkuWire<In, Out>`.
11
10
  */
12
- export type CorePikkuFunction<In, Out, ChannelData extends unknown | null = null, Services extends CoreSingletonServices = CoreServices & (ChannelData extends null ? {
13
- channel?: PikkuChannel<unknown, Out> | undefined;
14
- } : {
15
- channel: PikkuChannel<ChannelData, Out>;
16
- }), Session extends CoreUserSession = CoreUserSession> = (services: Services, data: In, session: Session) => ChannelData extends null ? Promise<Out> : Promise<Out> | Promise<void>;
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
12
  /**
18
13
  * Represents a core API function that can be used without a session.
19
14
  *
20
15
  * @template In - The input type.
21
16
  * @template Out - The output type.
22
- * @template ChannelData - The channel data type.
23
17
  * @template Services - The services type, defaults to `CoreServices`.
24
- * @template Session - The session type, defaults to `CoreUserSession`.
18
+ * @template Wire - The wire type, defaults to `PikkuWire<In, Out>`.
25
19
  */
26
- export type CorePikkuFunctionSessionless<In, Out, ChannelData extends unknown | null = null, Services extends CoreSingletonServices = CoreServices & (ChannelData extends null ? {
27
- channel?: PikkuChannel<unknown, Out> | undefined;
28
- } : {
29
- channel: PikkuChannel<ChannelData, Out>;
30
- }), Session extends CoreUserSession = CoreUserSession> = (services: Services, data: In, session?: Session) => ChannelData extends null ? Promise<Out> : Promise<Out> | Promise<void>;
20
+ export type CorePikkuFunctionSessionless<In, Out, Services extends CoreSingletonServices = CoreServices, Wire extends PikkuWire<In, Out, false, CoreUserSession, any, any, any> = PikkuWire<In, Out, false, CoreUserSession, any, any, any>> = (services: Services, data: In, wire: Wire) => Wire['channel'] extends null ? Promise<Out> : Promise<Out> | Promise<void>;
31
21
  /**
32
22
  * Represents a function that checks permissions for a given operation.
33
23
  *
@@ -35,7 +25,7 @@ export type CorePikkuFunctionSessionless<In, Out, ChannelData extends unknown |
35
25
  * @template Services - The services type, defaults to `CoreServices`.
36
26
  * @template Session - The session type, defaults to `CoreUserSession`.
37
27
  */
38
- export type CorePikkuPermission<In = any, Services extends CoreSingletonServices = CoreServices, Session extends CoreUserSession = CoreUserSession> = (services: Services, data: In, session?: Session) => Promise<boolean>;
28
+ export type CorePikkuPermission<In = any, Services extends CoreSingletonServices = CoreServices, Wire extends PikkuWire<In, never, false, CoreUserSession, any, never, never> = PikkuWire<In, never, false, CoreUserSession, never, never, never>> = (services: Services, data: In, wire: Wire) => Promise<boolean>;
39
29
  /**
40
30
  * Configuration object for creating a permission with metadata
41
31
  *
@@ -43,11 +33,11 @@ export type CorePikkuPermission<In = any, Services extends CoreSingletonServices
43
33
  * @template Services - The services type, defaults to `CoreServices`.
44
34
  * @template Session - The session type, defaults to `CoreUserSession`.
45
35
  */
46
- export type CorePikkuPermissionConfig<In = any, Services extends CoreSingletonServices = CoreServices, Session extends CoreUserSession = CoreUserSession> = {
36
+ export type CorePikkuPermissionConfig<In = any, Services extends CoreSingletonServices = CoreServices, Wire extends PikkuWire<In, never, false, CoreUserSession> = PikkuWire<In, never, false, CoreUserSession>> = {
47
37
  /** The permission function */
48
- func: CorePikkuPermission<In, Services, Session>;
49
- /** Optional human-readable name for the permission */
50
- name?: string;
38
+ func: CorePikkuPermission<In, Services, Wire>;
39
+ /** Optional human-readable title for the permission */
40
+ title?: string;
51
41
  /** Optional description of what the permission checks */
52
42
  description?: string;
53
43
  };
@@ -59,22 +49,24 @@ export type CorePikkuPermissionConfig<In = any, Services extends CoreSingletonSe
59
49
  * ```typescript
60
50
  * // Direct function syntax
61
51
  * export const adminPermission = pikkuPermission(
62
- * async ({ logger }, data, session) => {
63
- * return session?.role === 'admin'
52
+ * async ({ logger }, _data, { session }) => {
53
+ * const currentSession = await session.get()
54
+ * return currentSession?.role === 'admin'
64
55
  * }
65
56
  * )
66
57
  *
67
58
  * // Configuration object syntax with metadata
68
59
  * export const adminPermission = pikkuPermission({
69
- * name: 'Admin Permission',
60
+ * title: 'Admin Permission',
70
61
  * description: 'Checks if user has admin role',
71
- * func: async ({ logger }, data, session) => {
72
- * return session?.role === 'admin'
62
+ * func: async ({ logger }, _data, { session }) => {
63
+ * const currentSession = await session.get()
64
+ * return currentSession?.role === 'admin'
73
65
  * }
74
66
  * })
75
67
  * ```
76
68
  */
77
- export declare const pikkuPermission: <In = any, Services extends CoreSingletonServices = CoreServices, Session extends CoreUserSession = CoreUserSession>(permission: CorePikkuPermission<In, Services, Session> | CorePikkuPermissionConfig<In, Services, Session>) => CorePikkuPermission<In, Services, Session>;
69
+ export declare const pikkuPermission: <In = any, Services extends CoreSingletonServices = CoreServices, Wire extends PickRequired<PikkuWire<In, never, false, CoreUserSession>, "session"> = PickRequired<PikkuWire<In, never, false, CoreUserSession>, "session">>(permission: CorePikkuPermission<In, Services, Wire> | CorePikkuPermissionConfig<In, Services, Wire>) => CorePikkuPermission<In, Services, Wire>;
78
70
  /**
79
71
  * A factory function that takes input and returns a permission
80
72
  * Used when permissions need configuration/input parameters
@@ -83,7 +75,7 @@ export declare const pikkuPermission: <In = any, Services extends CoreSingletonS
83
75
  * @template Services - The services type, defaults to `CoreServices`.
84
76
  * @template Session - The session type, defaults to `CoreUserSession`.
85
77
  */
86
- export type CorePikkuPermissionFactory<In = any, Services extends CoreSingletonServices = CoreServices, Session extends CoreUserSession = CoreUserSession> = (input: In) => CorePikkuPermission<any, Services, Session>;
78
+ export type CorePikkuPermissionFactory<In = any, Services extends CoreSingletonServices = CoreServices, Wire extends PikkuWire<In, never, false, CoreUserSession> = PikkuWire<In, never, false, CoreUserSession>> = (input: In) => CorePikkuPermission<any, Services, Wire>;
87
79
  /**
88
80
  * Factory function for creating permission factories
89
81
  * Use this when your permission needs configuration/input parameters
@@ -93,8 +85,9 @@ export type CorePikkuPermissionFactory<In = any, Services extends CoreSingletonS
93
85
  * export const requireRole = pikkuPermissionFactory<{ role: string }>(({
94
86
  * role
95
87
  * }) => {
96
- * return pikkuPermission(async ({ logger }, data, session) => {
97
- * if (!session || session.role !== role) {
88
+ * return pikkuPermission(async ({ logger }, data, { session }) => {
89
+ * const currentSession = await session.get()
90
+ * if (!currentSession || currentSession.role !== role) {
98
91
  * logger.warn(`Permission denied: required role '${role}'`)
99
92
  * return false
100
93
  * }
@@ -105,14 +98,92 @@ export type CorePikkuPermissionFactory<In = any, Services extends CoreSingletonS
105
98
  */
106
99
  export declare const pikkuPermissionFactory: <In = any>(factory: CorePikkuPermissionFactory<In>) => CorePikkuPermissionFactory<In>;
107
100
  export type CorePermissionGroup<PikkuPermission = CorePikkuPermission<any>> = Record<string, PikkuPermission | PikkuPermission[]> | undefined;
108
- 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> = CorePikkuMiddleware<any>> = {
109
- name?: string;
101
+ /**
102
+ * Zod schema type - matches z.ZodType shape for type inference
103
+ * This avoids requiring zod as a dependency while allowing schema inference
104
+ */
105
+ export type ZodLike<T = any> = {
106
+ _input: T;
107
+ _output: T;
108
+ };
109
+ export type CorePikkuFunctionConfig<PikkuFunction extends CorePikkuFunction<any, any, any, any> | CorePikkuFunctionSessionless<any, any, any, any>, PikkuPermission extends CorePikkuPermission<any, any, any> = CorePikkuPermission<any>, PikkuMiddleware extends CorePikkuMiddleware<any, any> = CorePikkuMiddleware<any, any>, InputSchema extends ZodLike | undefined = undefined, OutputSchema extends ZodLike | undefined = undefined> = {
110
+ /** Optional human-readable title for the function */
111
+ title?: string;
112
+ /** Optional description of what the function does */
113
+ description?: string;
114
+ override?: string;
115
+ tags?: string[];
110
116
  expose?: boolean;
111
117
  internal?: boolean;
112
118
  func: PikkuFunction;
113
119
  auth?: boolean;
114
120
  permissions?: CorePermissionGroup<PikkuPermission>;
115
121
  middleware?: PikkuMiddleware[];
122
+ input?: InputSchema;
123
+ output?: OutputSchema;
124
+ };
125
+ /**
126
+ * A trigger function that sets up a subscription and returns a teardown function.
127
+ * The trigger is fired via wire.trigger.trigger(data).
128
+ *
129
+ * @template TConfig - Configuration type (hardcoded when wired)
130
+ * @template TOutput - Output type produced when trigger fires
131
+ * @template Services - Services available to the trigger
132
+ */
133
+ export type CorePikkuTriggerFunction<TConfig = unknown, TOutput = unknown, Services extends CoreSingletonServices = CoreSingletonServices> = (services: Services, config: TConfig, wire: {
134
+ trigger: {
135
+ trigger: (data: TOutput) => void;
136
+ };
137
+ }) => Promise<() => void | Promise<void>>;
138
+ /**
139
+ * Configuration object for creating a trigger function with metadata
140
+ */
141
+ export type CorePikkuTriggerFunctionConfig<TConfig = unknown, TOutput = unknown, Services extends CoreSingletonServices = CoreSingletonServices, ConfigSchema extends ZodLike | undefined = undefined, OutputSchema extends ZodLike | undefined = undefined> = {
142
+ /** Optional human-readable title for the trigger */
143
+ title?: string;
144
+ /** Optional description of what the trigger does */
145
+ description?: string;
146
+ /** Optional tags for categorization */
116
147
  tags?: string[];
117
- docs?: PikkuDocs;
148
+ /** The trigger function */
149
+ func: CorePikkuTriggerFunction<TConfig, TOutput, Services>;
150
+ /** Optional Zod schema for config validation */
151
+ config?: ConfigSchema;
152
+ /** Optional Zod schema for output validation */
153
+ output?: OutputSchema;
118
154
  };
155
+ /**
156
+ * Factory function for creating trigger functions
157
+ * Supports both direct function and configuration object syntax
158
+ *
159
+ * @example
160
+ * ```typescript
161
+ * // Direct function syntax
162
+ * export const redisSubscribeTrigger = pikkuTriggerFunc<
163
+ * { channel: string },
164
+ * { message: string }
165
+ * >(async ({ redis }, { channel }, { trigger }) => {
166
+ * const subscriber = redis.duplicate()
167
+ * await subscriber.subscribe(channel, (msg) => {
168
+ * trigger.trigger({ message: msg })
169
+ * })
170
+ * return () => subscriber.unsubscribe()
171
+ * })
172
+ *
173
+ * // Configuration object syntax with metadata
174
+ * export const redisSubscribeTrigger = pikkuTriggerFunc({
175
+ * title: 'Redis Subscribe Trigger',
176
+ * description: 'Listens to Redis pub/sub channel',
177
+ * config: z.object({ channel: z.string() }),
178
+ * output: z.object({ message: z.string() }),
179
+ * func: async ({ redis }, { channel }, { trigger }) => {
180
+ * const subscriber = redis.duplicate()
181
+ * await subscriber.subscribe(channel, (msg) => {
182
+ * trigger.trigger({ message: msg })
183
+ * })
184
+ * return () => subscriber.unsubscribe()
185
+ * }
186
+ * })
187
+ * ```
188
+ */
189
+ export declare const pikkuTriggerFunc: <TConfig = unknown, TOutput = unknown, Services extends CoreSingletonServices = CoreSingletonServices, ConfigSchema extends ZodLike | undefined = undefined, OutputSchema extends ZodLike | undefined = undefined>(triggerOrConfig: CorePikkuTriggerFunction<TConfig, TOutput, Services> | CorePikkuTriggerFunctionConfig<TConfig, TOutput, Services, ConfigSchema, OutputSchema>) => CorePikkuTriggerFunctionConfig<TConfig, TOutput, Services, ConfigSchema, OutputSchema>;
@@ -6,17 +6,19 @@
6
6
  * ```typescript
7
7
  * // Direct function syntax
8
8
  * export const adminPermission = pikkuPermission(
9
- * async ({ logger }, data, session) => {
10
- * return session?.role === 'admin'
9
+ * async ({ logger }, _data, { session }) => {
10
+ * const currentSession = await session.get()
11
+ * return currentSession?.role === 'admin'
11
12
  * }
12
13
  * )
13
14
  *
14
15
  * // Configuration object syntax with metadata
15
16
  * export const adminPermission = pikkuPermission({
16
- * name: 'Admin Permission',
17
+ * title: 'Admin Permission',
17
18
  * description: 'Checks if user has admin role',
18
- * func: async ({ logger }, data, session) => {
19
- * return session?.role === 'admin'
19
+ * func: async ({ logger }, _data, { session }) => {
20
+ * const currentSession = await session.get()
21
+ * return currentSession?.role === 'admin'
20
22
  * }
21
23
  * })
22
24
  * ```
@@ -33,8 +35,9 @@ export const pikkuPermission = (permission) => {
33
35
  * export const requireRole = pikkuPermissionFactory<{ role: string }>(({
34
36
  * role
35
37
  * }) => {
36
- * return pikkuPermission(async ({ logger }, data, session) => {
37
- * if (!session || session.role !== role) {
38
+ * return pikkuPermission(async ({ logger }, data, { session }) => {
39
+ * const currentSession = await session.get()
40
+ * if (!currentSession || currentSession.role !== role) {
38
41
  * logger.warn(`Permission denied: required role '${role}'`)
39
42
  * return false
40
43
  * }
@@ -46,3 +49,43 @@ export const pikkuPermission = (permission) => {
46
49
  export const pikkuPermissionFactory = (factory) => {
47
50
  return factory;
48
51
  };
52
+ /**
53
+ * Factory function for creating trigger functions
54
+ * Supports both direct function and configuration object syntax
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * // Direct function syntax
59
+ * export const redisSubscribeTrigger = pikkuTriggerFunc<
60
+ * { channel: string },
61
+ * { message: string }
62
+ * >(async ({ redis }, { channel }, { trigger }) => {
63
+ * const subscriber = redis.duplicate()
64
+ * await subscriber.subscribe(channel, (msg) => {
65
+ * trigger.trigger({ message: msg })
66
+ * })
67
+ * return () => subscriber.unsubscribe()
68
+ * })
69
+ *
70
+ * // Configuration object syntax with metadata
71
+ * export const redisSubscribeTrigger = pikkuTriggerFunc({
72
+ * title: 'Redis Subscribe Trigger',
73
+ * description: 'Listens to Redis pub/sub channel',
74
+ * config: z.object({ channel: z.string() }),
75
+ * output: z.object({ message: z.string() }),
76
+ * func: async ({ redis }, { channel }, { trigger }) => {
77
+ * const subscriber = redis.duplicate()
78
+ * await subscriber.subscribe(channel, (msg) => {
79
+ * trigger.trigger({ message: msg })
80
+ * })
81
+ * return () => subscriber.unsubscribe()
82
+ * }
83
+ * })
84
+ * ```
85
+ */
86
+ export const pikkuTriggerFunc = (triggerOrConfig) => {
87
+ if (typeof triggerOrConfig === 'function') {
88
+ return { func: triggerOrConfig };
89
+ }
90
+ return triggerOrConfig;
91
+ };
@@ -4,7 +4,7 @@ import { PikkuHTTP } from './wirings/http/http.types.js';
4
4
  * Handle errors that occur during route processing
5
5
  *
6
6
  * @param {any} e - The error that occurred
7
- * @param {PikkuHTTP | undefined} http - HTTP interaction object
7
+ * @param {PikkuHTTP | undefined} http - HTTP wire object
8
8
  * @param {string} trackerId - Unique ID for tracking this error
9
9
  * @param {Logger} logger - Logger service
10
10
  * @param {number[]} logWarningsForStatusCodes - HTTP status codes to log as warnings
@@ -4,7 +4,7 @@ import { NotFoundError } from './errors/errors.js';
4
4
  * Handle errors that occur during route processing
5
5
  *
6
6
  * @param {any} e - The error that occurred
7
- * @param {PikkuHTTP | undefined} http - HTTP interaction object
7
+ * @param {PikkuHTTP | undefined} http - HTTP wire object
8
8
  * @param {string} trackerId - Unique ID for tracking this error
9
9
  * @param {Logger} logger - Logger service
10
10
  * @param {number[]} logWarningsForStatusCodes - HTTP status codes to log as warnings
package/dist/index.d.ts CHANGED
@@ -17,12 +17,16 @@ export * from './wirings/scheduler/index.js';
17
17
  export * from './wirings/rpc/index.js';
18
18
  export * from './wirings/queue/index.js';
19
19
  export * from './wirings/workflow/index.js';
20
+ export * from './wirings/workflow/graph/index.js';
20
21
  export * from './wirings/mcp/index.js';
21
22
  export * from './wirings/cli/index.js';
23
+ export * from './wirings/forge-node/index.js';
24
+ export * from './wirings/trigger/index.js';
22
25
  export * from './errors/index.js';
23
26
  export * from './middleware/index.js';
24
27
  export * from './utils.js';
25
28
  export * from './time-utils.js';
26
- export { pikkuState } from './pikku-state.js';
27
- export { runMiddleware, addMiddleware, getMiddlewareByName, } from './middleware-runner.js';
29
+ export { pikkuState, initializePikkuState, resetPikkuState, addPackageServiceFactories, } from './pikku-state.js';
30
+ export type { PikkuPackageState } from './types/state.types.js';
31
+ export { runMiddleware, addMiddleware } from './middleware-runner.js';
28
32
  export { addPermission } from './permissions.js';
package/dist/index.js CHANGED
@@ -17,12 +17,15 @@ export * from './wirings/scheduler/index.js';
17
17
  export * from './wirings/rpc/index.js';
18
18
  export * from './wirings/queue/index.js';
19
19
  export * from './wirings/workflow/index.js';
20
+ export * from './wirings/workflow/graph/index.js';
20
21
  export * from './wirings/mcp/index.js';
21
22
  export * from './wirings/cli/index.js';
23
+ export * from './wirings/forge-node/index.js';
24
+ export * from './wirings/trigger/index.js';
22
25
  export * from './errors/index.js';
23
26
  export * from './middleware/index.js';
24
27
  export * from './utils.js';
25
28
  export * from './time-utils.js';
26
- export { pikkuState } from './pikku-state.js';
27
- export { runMiddleware, addMiddleware, getMiddlewareByName, } from './middleware-runner.js';
29
+ export { pikkuState, initializePikkuState, resetPikkuState, addPackageServiceFactories, } from './pikku-state.js';
30
+ export { runMiddleware, addMiddleware } from './middleware-runner.js';
28
31
  export { addPermission } from './permissions.js';