@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
@@ -1,19 +1,18 @@
1
1
  import { openChannel } from '../channel-runner.js';
2
- import { createHTTPInteraction } from '../../http/http-runner.js';
3
- import { closeSessionServices } from '../../../utils.js';
2
+ import { createHTTPWire } from '../../http/http-runner.js';
3
+ import { closeWireServices } from '../../../utils.js';
4
4
  import { processMessageHandlers } from '../channel-handler.js';
5
5
  import { PikkuLocalChannelHandler } from './local-channel-handler.js';
6
6
  import { handleHTTPError } from '../../../handle-error.js';
7
- import { PikkuUserSessionService } from '../../../services/user-session-service.js';
8
- import { rpcService } from '../../rpc/rpc-runner.js';
7
+ import { PikkuSessionService } from '../../../services/user-session-service.js';
9
8
  import { runChannelLifecycleWithMiddleware } from '../channel-common.js';
10
- export const runLocalChannel = async ({ singletonServices, channelId, request, response, route, createSessionServices, skipUserSession = false, respondWith404 = true, coerceDataFromSchema = true, logWarningsForStatusCodes = [], bubbleErrors = false, }) => {
11
- let sessionServices;
9
+ export const runLocalChannel = async ({ singletonServices, channelId, request, response, route, createWireServices, skipUserSession = false, respondWith404 = true, coerceDataFromSchema = true, logWarningsForStatusCodes = [], bubbleErrors = false, }) => {
10
+ let wireServices;
12
11
  let channelHandler;
13
- const userSession = new PikkuUserSessionService();
12
+ const userSession = new PikkuSessionService();
14
13
  let http;
15
14
  if (request) {
16
- http = createHTTPInteraction(request, response);
15
+ http = createHTTPWire(request, response);
17
16
  route = http?.request?.path();
18
17
  }
19
18
  let openingData, channelConfig, meta;
@@ -21,7 +20,7 @@ export const runLocalChannel = async ({ singletonServices, channelId, request, r
21
20
  ;
22
21
  ({ openingData, channelConfig, meta } = await openChannel({
23
22
  channelId,
24
- createSessionServices,
23
+ createWireServices,
25
24
  respondWith404,
26
25
  request,
27
26
  response,
@@ -40,17 +39,11 @@ export const runLocalChannel = async ({ singletonServices, channelId, request, r
40
39
  try {
41
40
  channelHandler = new PikkuLocalChannelHandler(channelId, channelConfig.name, openingData);
42
41
  const channel = channelHandler.getChannel();
43
- const session = await userSession.get();
44
- if (createSessionServices) {
45
- sessionServices = await createSessionServices(singletonServices, { http, channel }, session);
42
+ const wire = { channel, session: userSession };
43
+ if (createWireServices) {
44
+ wireServices = await createWireServices(singletonServices, wire);
46
45
  }
47
- const getAllServices = (channel, requiresAuth) => rpcService.injectRPCService({
48
- ...singletonServices,
49
- ...sessionServices,
50
- channel,
51
- userSession,
52
- }, interaction, requiresAuth);
53
- const interaction = { channel };
46
+ const services = { ...singletonServices, ...wireServices };
54
47
  channelHandler.registerOnOpen(async () => {
55
48
  if (channelConfig.onConnect && meta.connect) {
56
49
  try {
@@ -59,7 +52,7 @@ export const runLocalChannel = async ({ singletonServices, channelId, request, r
59
52
  meta: meta.connect,
60
53
  lifecycleConfig: channelConfig.onConnect,
61
54
  lifecycleType: 'connect',
62
- services: getAllServices(channel, false),
55
+ services,
63
56
  channel,
64
57
  data: openingData,
65
58
  });
@@ -81,7 +74,7 @@ export const runLocalChannel = async ({ singletonServices, channelId, request, r
81
74
  meta: meta.disconnect,
82
75
  lifecycleConfig: channelConfig.onDisconnect,
83
76
  lifecycleType: 'disconnect',
84
- services: getAllServices(channel, false),
77
+ services,
85
78
  channel,
86
79
  });
87
80
  }
@@ -90,11 +83,11 @@ export const runLocalChannel = async ({ singletonServices, channelId, request, r
90
83
  channel.send({ error: e.message || 'Unknown error' });
91
84
  }
92
85
  }
93
- if (sessionServices) {
94
- await closeSessionServices(singletonServices.logger, sessionServices);
86
+ if (wireServices) {
87
+ await closeWireServices(singletonServices.logger, wireServices);
95
88
  }
96
89
  });
97
- const onMessage = processMessageHandlers(getAllServices(channel), channelConfig, channelHandler);
90
+ const onMessage = processMessageHandlers(services, channelConfig, channelHandler, userSession);
98
91
  channelHandler.registerOnMessage(async (data) => {
99
92
  try {
100
93
  const result = await onMessage(data);
@@ -110,8 +103,8 @@ export const runLocalChannel = async ({ singletonServices, channelId, request, r
110
103
  handleHTTPError(e, http, channelId, singletonServices.logger, logWarningsForStatusCodes, respondWith404, bubbleErrors);
111
104
  }
112
105
  finally {
113
- if (sessionServices) {
114
- await closeSessionServices(singletonServices.logger, sessionServices);
106
+ if (wireServices) {
107
+ await closeWireServices(singletonServices.logger, wireServices);
115
108
  }
116
109
  }
117
110
  };
@@ -4,7 +4,7 @@ import { pikkuState } from '../../pikku-state.js';
4
4
  * @param logger - A logger for logging information.
5
5
  */
6
6
  export const logChannels = (logger) => {
7
- const channels = pikkuState('channel', 'channels');
7
+ const channels = pikkuState(null, 'channel', 'channels');
8
8
  if (channels.size === 0) {
9
9
  logger.info('No channels added');
10
10
  return;
@@ -5,6 +5,6 @@ export interface RunServerlessChannelParams<ChannelData> extends RunChannelParam
5
5
  channelHandlerFactory: PikkuChannelHandlerFactory;
6
6
  channelObject?: unknown;
7
7
  }
8
- export declare const runChannelConnect: ({ singletonServices, channelId, channelObject, request, response, route, createSessionServices, channelStore, channelHandlerFactory, coerceDataFromSchema, logWarningsForStatusCodes, respondWith404, bubbleErrors, }: Pick<CoreChannel<unknown, any>, "route"> & RunChannelOptions & RunServerlessChannelParams<unknown>) => Promise<void>;
8
+ export declare const runChannelConnect: ({ singletonServices, channelId, channelObject, request, response, route, createWireServices, channelStore, channelHandlerFactory, coerceDataFromSchema, logWarningsForStatusCodes, respondWith404, bubbleErrors, }: Pick<CoreChannel<unknown, any>, "route"> & RunChannelOptions & RunServerlessChannelParams<unknown>) => Promise<void>;
9
9
  export declare const runChannelDisconnect: ({ singletonServices, ...params }: RunServerlessChannelParams<unknown>) => Promise<void>;
10
10
  export declare const runChannelMessage: ({ singletonServices, ...params }: RunServerlessChannelParams<unknown>, data: unknown) => Promise<unknown>;
@@ -1,17 +1,16 @@
1
- import { closeSessionServices } from '../../../utils.js';
1
+ import { closeWireServices } from '../../../utils.js';
2
2
  import { processMessageHandlers } from '../channel-handler.js';
3
3
  import { openChannel } from '../channel-runner.js';
4
- import { createHTTPInteraction } from '../../http/http-runner.js';
4
+ import { createHTTPWire } from '../../http/http-runner.js';
5
5
  import { handleHTTPError } from '../../../handle-error.js';
6
- import { PikkuUserSessionService } from '../../../services/user-session-service.js';
6
+ import { PikkuSessionService } from '../../../services/user-session-service.js';
7
7
  import { pikkuState } from '../../../pikku-state.js';
8
8
  import { PikkuFetchHTTPRequest } from '../../http/pikku-fetch-http-request.js';
9
9
  import { runChannelLifecycleWithMiddleware } from '../channel-common.js';
10
- import { rpcService } from '../../rpc/rpc-runner.js';
11
10
  const getVariablesForChannel = ({ channelId, channelName, channelHandlerFactory, openingData, }) => {
12
- const channels = pikkuState('channel', 'channels');
11
+ const channels = pikkuState(null, 'channel', 'channels');
13
12
  const channelConfig = channels.get(channelName);
14
- const channelsMeta = pikkuState('channel', 'meta');
13
+ const channelsMeta = pikkuState(null, 'channel', 'meta');
15
14
  const meta = channelsMeta[channelName];
16
15
  if (!channelConfig) {
17
16
  throw new Error(`Channel not found: ${channelName}`);
@@ -27,16 +26,16 @@ const getVariablesForChannel = ({ channelId, channelName, channelHandlerFactory,
27
26
  meta,
28
27
  };
29
28
  };
30
- export const runChannelConnect = async ({ singletonServices, channelId, channelObject, request, response, route, createSessionServices, channelStore, channelHandlerFactory, coerceDataFromSchema = true, logWarningsForStatusCodes = [], respondWith404 = true, bubbleErrors = false, }) => {
31
- let sessionServices;
29
+ export const runChannelConnect = async ({ singletonServices, channelId, channelObject, request, response, route, createWireServices, channelStore, channelHandlerFactory, coerceDataFromSchema = true, logWarningsForStatusCodes = [], respondWith404 = true, bubbleErrors = false, }) => {
30
+ let wireServices;
32
31
  let http;
33
32
  if (request instanceof Request) {
34
- http = createHTTPInteraction(new PikkuFetchHTTPRequest(request), response);
33
+ http = createHTTPWire(new PikkuFetchHTTPRequest(request), response);
35
34
  }
36
- const userSession = new PikkuUserSessionService(channelStore, channelId);
35
+ const userSession = new PikkuSessionService(channelStore, channelId);
37
36
  const { channelConfig, openingData, meta } = await openChannel({
38
37
  channelId,
39
- createSessionServices,
38
+ createWireServices,
40
39
  request,
41
40
  route,
42
41
  singletonServices,
@@ -55,23 +54,21 @@ export const runChannelConnect = async ({ singletonServices, channelId, channelO
55
54
  channelHandlerFactory,
56
55
  channelName: channelConfig.name,
57
56
  });
58
- if (createSessionServices) {
59
- sessionServices = await createSessionServices(singletonServices, { http }, await userSession.get());
57
+ const wire = { channel, session: userSession };
58
+ if (createWireServices) {
59
+ wireServices = await createWireServices(singletonServices, wire);
60
60
  }
61
- const interaction = { channel };
62
- const getAllServices = (requiresAuth) => rpcService.injectRPCService({
61
+ const services = {
63
62
  ...singletonServices,
64
- ...sessionServices,
65
- channel,
66
- userSession,
67
- }, interaction, requiresAuth);
63
+ ...wireServices,
64
+ };
68
65
  if (channelConfig.onConnect && meta.connect) {
69
66
  await runChannelLifecycleWithMiddleware({
70
67
  channelConfig,
71
68
  meta: meta.connect,
72
69
  lifecycleConfig: channelConfig.onConnect,
73
70
  lifecycleType: 'connect',
74
- services: getAllServices(false),
71
+ services,
75
72
  channel,
76
73
  data: openingData,
77
74
  });
@@ -82,13 +79,13 @@ export const runChannelConnect = async ({ singletonServices, channelId, channelO
82
79
  handleHTTPError(e, http, channelId, singletonServices.logger, logWarningsForStatusCodes, respondWith404, bubbleErrors);
83
80
  }
84
81
  finally {
85
- if (sessionServices) {
86
- await closeSessionServices(singletonServices.logger, sessionServices);
82
+ if (wireServices) {
83
+ await closeWireServices(singletonServices.logger, wireServices);
87
84
  }
88
85
  }
89
86
  };
90
87
  export const runChannelDisconnect = async ({ singletonServices, ...params }) => {
91
- let sessionServices;
88
+ let wireServices;
92
89
  // Try to get channel from store. In serverless environments (especially with
93
90
  // serverless-offline or worker threads), disconnect can be called multiple times
94
91
  // or after the channel has already been cleaned up. If channel doesn't exist,
@@ -107,17 +104,16 @@ export const runChannelDisconnect = async ({ singletonServices, ...params }) =>
107
104
  openingData,
108
105
  channelName,
109
106
  });
110
- const userSession = new PikkuUserSessionService(params.channelStore, params.channelId);
111
- if (!sessionServices && params.createSessionServices) {
112
- sessionServices = await params.createSessionServices(singletonServices, { channel }, session);
107
+ const userSession = new PikkuSessionService(params.channelStore, params.channelId);
108
+ userSession.setInitial(session);
109
+ const wire = { channel, session: userSession };
110
+ if (!wireServices && params.createWireServices) {
111
+ wireServices = await params.createWireServices(singletonServices, wire);
113
112
  }
114
- const interaction = { channel };
115
- const getAllServices = (requiresAuth) => rpcService.injectRPCService({
113
+ const services = {
116
114
  ...singletonServices,
117
- ...sessionServices,
118
- channel,
119
- userSession,
120
- }, interaction, requiresAuth);
115
+ ...wireServices,
116
+ };
121
117
  if (channelConfig.onDisconnect && meta.disconnect) {
122
118
  try {
123
119
  await runChannelLifecycleWithMiddleware({
@@ -125,7 +121,7 @@ export const runChannelDisconnect = async ({ singletonServices, ...params }) =>
125
121
  meta: meta.disconnect,
126
122
  lifecycleConfig: channelConfig.onDisconnect,
127
123
  lifecycleType: 'disconnect',
128
- services: getAllServices(false),
124
+ services,
129
125
  channel,
130
126
  });
131
127
  }
@@ -134,32 +130,31 @@ export const runChannelDisconnect = async ({ singletonServices, ...params }) =>
134
130
  }
135
131
  }
136
132
  await params.channelStore.removeChannels([channel.channelId]);
137
- if (sessionServices) {
138
- await closeSessionServices(singletonServices.logger, sessionServices);
133
+ if (wireServices) {
134
+ await closeWireServices(singletonServices.logger, wireServices);
139
135
  }
140
136
  };
141
137
  export const runChannelMessage = async ({ singletonServices, ...params }, data) => {
142
- let sessionServices;
138
+ let wireServices;
143
139
  const { openingData, channelName, session } = await params.channelStore.getChannelAndSession(params.channelId);
144
140
  const { channel, channelHandler, channelConfig } = getVariablesForChannel({
145
141
  ...params,
146
142
  openingData,
147
143
  channelName,
148
144
  });
149
- const userSession = new PikkuUserSessionService(params.channelStore, params.channelId);
150
- if (params.createSessionServices) {
151
- sessionServices = await params.createSessionServices(singletonServices, { channel }, session);
145
+ const userSession = new PikkuSessionService(params.channelStore, params.channelId);
146
+ userSession.setInitial(session);
147
+ const wire = { channel, session: userSession };
148
+ if (params.createWireServices) {
149
+ wireServices = await params.createWireServices(singletonServices, wire);
152
150
  }
153
- const interaction = { channel };
154
- const getAllServices = () => rpcService.injectRPCService({
151
+ const services = {
155
152
  ...singletonServices,
156
- ...sessionServices,
157
- channel,
158
- userSession,
159
- }, interaction);
153
+ ...wireServices,
154
+ };
160
155
  let response;
161
156
  try {
162
- const onMessage = processMessageHandlers(getAllServices(), channelConfig, channelHandler);
157
+ const onMessage = processMessageHandlers(services, channelConfig, channelHandler, userSession);
163
158
  response = await onMessage(data);
164
159
  }
165
160
  catch (e) {
@@ -167,8 +162,8 @@ export const runChannelMessage = async ({ singletonServices, ...params }, data)
167
162
  return { error: e.message || 'Unknown error' };
168
163
  }
169
164
  finally {
170
- if (sessionServices) {
171
- await closeSessionServices(singletonServices.logger, sessionServices);
165
+ if (wireServices) {
166
+ await closeWireServices(singletonServices.logger, wireServices);
172
167
  }
173
168
  }
174
169
  return response;
@@ -12,10 +12,11 @@ const defaultJSONRenderer = (_services, data) => {
12
12
  */
13
13
  export async function executeCLIViaChannel({ programName, pikkuWS, args = process.argv.slice(2), renderers = {}, defaultRenderer, }) {
14
14
  // Get CLI metadata from state
15
- const allCLIMeta = pikkuState('cli', 'meta');
16
- if (!allCLIMeta) {
15
+ const cliMeta = pikkuState(null, 'cli', 'meta');
16
+ if (!cliMeta || !('programs' in cliMeta)) {
17
17
  throw new Error('[PKU342] CLI metadata not found. No CLI wirings were registered. See https://pikku.dev/docs/pikku-cli/errors/pku342 for more information.');
18
18
  }
19
+ const allCLIMeta = cliMeta;
19
20
  const programMeta = allCLIMeta.programs[programName];
20
21
  if (!programMeta) {
21
22
  console.error(`Error: CLI program "${programName}" not found`);
@@ -1,6 +1,6 @@
1
1
  import { CorePikkuMiddleware, CoreUserSession } from '../../types/core.types.js';
2
2
  import { CoreCLI, CorePikkuCLIRender, CoreCLICommandConfig } from './cli.types.js';
3
- import type { CoreSingletonServices, CoreServices, CreateSessionServices, CreateConfig, CreateSingletonServices } from '../../types/core.types.js';
3
+ import type { CoreSingletonServices, CoreServices, CreateWireServices, CreateConfig, CreateSingletonServices } from '../../types/core.types.js';
4
4
  /**
5
5
  * CLI command execution error - thrown when CLI execution fails
6
6
  * Should be caught by the wrapper to call process.exit()
@@ -16,12 +16,12 @@ export declare const wireCLI: <Commands extends Record<string, CoreCLICommandCon
16
16
  /**
17
17
  * Executes a CLI command for a specific program
18
18
  */
19
- export declare function runCLICommand({ program, commandPath, data, singletonServices, createSessionServices, }: {
19
+ export declare function runCLICommand({ program, commandPath, data, singletonServices, createWireServices, }: {
20
20
  program: string;
21
21
  commandPath: string[];
22
22
  data: Record<string, any>;
23
23
  singletonServices: CoreSingletonServices;
24
- createSessionServices?: CreateSessionServices;
24
+ createWireServices?: CreateWireServices;
25
25
  }): Promise<any>;
26
26
  /**
27
27
  * Factory function for CLI-specific renderers
@@ -33,10 +33,10 @@ export declare const pikkuCLIRender: <Data, Services extends CoreSingletonServic
33
33
  *
34
34
  * @throws {CLIError} When CLI execution fails - should be caught by wrapper to call process.exit()
35
35
  */
36
- export declare function executeCLI({ programName, args, createConfig, createSingletonServices, createSessionServices, }: {
36
+ export declare function executeCLI({ programName, args, createConfig, createSingletonServices, createWireServices, }: {
37
37
  programName: string;
38
38
  args?: string[];
39
39
  createConfig: CreateConfig<any, any>;
40
40
  createSingletonServices: CreateSingletonServices<any, any>;
41
- createSessionServices?: CreateSessionServices<any, any, any>;
41
+ createWireServices?: CreateWireServices<any, any, any>;
42
42
  }): Promise<void>;
@@ -1,10 +1,7 @@
1
1
  import { NotFoundError } from '../../errors/errors.js';
2
2
  import { addFunction, runPikkuFunc } from '../../function/function-runner.js';
3
3
  import { pikkuState } from '../../pikku-state.js';
4
- import { PikkuWiringTypes, } from '../../types/core.types.js';
5
- import { closeSessionServices } from '../../utils.js';
6
- import { rpcService } from '../rpc/rpc-runner.js';
7
- import { PikkuUserSessionService } from '../../services/user-session-service.js';
4
+ import { PikkuSessionService } from '../../services/user-session-service.js';
8
5
  import { LocalVariablesService } from '../../services/local-variables.js';
9
6
  import { generateCommandHelp, parseCLIArguments } from './command-parser.js';
10
7
  /**
@@ -30,12 +27,12 @@ const defaultJSONRenderer = (_services, data) => {
30
27
  */
31
28
  export const wireCLI = (cli) => {
32
29
  // Get the existing metadata that was generated during inspection
33
- const cliMeta = pikkuState('cli', 'meta') || {};
30
+ const cliMeta = pikkuState(null, 'cli', 'meta') || {};
34
31
  if (!cliMeta.programs?.[cli.program]) {
35
32
  throw new Error(`CLI metadata not found for program '${cli.program}'. Did you run 'pikku all'?`);
36
33
  }
37
34
  // Get existing programs state and add this program
38
- const programs = pikkuState('cli', 'programs') || {};
35
+ const programs = pikkuState(null, 'cli', 'programs') || {};
39
36
  programs[cli.program] = {
40
37
  defaultRenderer: (cli.render ||
41
38
  defaultJSONRenderer),
@@ -43,7 +40,7 @@ export const wireCLI = (cli) => {
43
40
  renderers: {},
44
41
  tags: cli.tags,
45
42
  };
46
- pikkuState('cli', 'programs', programs);
43
+ pikkuState(null, 'cli', 'programs', programs);
47
44
  // Register all command functions recursively
48
45
  registerCLICommands(cli.commands, [], cli.options || {}, cli.program);
49
46
  };
@@ -75,7 +72,7 @@ function unwrapFunc(command) {
75
72
  */
76
73
  function registerCLICommands(commands, path = [], inheritedOptions = {}, program) {
77
74
  // Get the CLI metadata to find actual function names
78
- const cliMeta = pikkuState('cli', 'meta').programs[program];
75
+ const cliMeta = pikkuState(null, 'cli', 'meta').programs[program];
79
76
  for (const [name, command] of Object.entries(commands)) {
80
77
  const fullPath = [...path, name];
81
78
  const commandId = fullPath.join('.');
@@ -99,7 +96,7 @@ function registerCLICommands(commands, path = [], inheritedOptions = {}, program
99
96
  const commandOptions = typeof command === 'object' ? command.options || {} : {};
100
97
  const mergedOptions = { ...inheritedOptions, ...commandOptions };
101
98
  // Store the options and middleware in program state for use during execution
102
- const programs = pikkuState('cli', 'programs');
99
+ const programs = pikkuState(null, 'cli', 'programs');
103
100
  if (programs[program]) {
104
101
  if (!programs[program].commandOptions) {
105
102
  programs[program].commandOptions = {};
@@ -130,10 +127,10 @@ function registerCLICommands(commands, path = [], inheritedOptions = {}, program
130
127
  * Plucks only the data that the function expects based on its schema
131
128
  */
132
129
  function pluckCLIData(mergedData, funcName, availableOptions) {
133
- const funcMeta = pikkuState('function', 'meta')[funcName];
130
+ const funcMeta = pikkuState(null, 'function', 'meta')[funcName];
134
131
  const schemaName = funcMeta?.inputSchemaName;
135
132
  const schema = schemaName
136
- ? pikkuState('misc', 'schemas').get(schemaName)
133
+ ? pikkuState(null, 'misc', 'schemas').get(schemaName)
137
134
  : null;
138
135
  if (schema && schema.properties) {
139
136
  // If we have a schema, only include fields that are in the schema
@@ -157,9 +154,9 @@ function pluckCLIData(mergedData, funcName, availableOptions) {
157
154
  /**
158
155
  * Executes a CLI command for a specific program
159
156
  */
160
- export async function runCLICommand({ program, commandPath, data, singletonServices, createSessionServices, }) {
157
+ export async function runCLICommand({ program, commandPath, data, singletonServices, createWireServices, }) {
161
158
  // Get the command metadata to find the function name
162
- const cliMeta = pikkuState('cli', 'meta');
159
+ const cliMeta = pikkuState(null, 'cli', 'meta');
163
160
  const programMeta = cliMeta.programs?.[program];
164
161
  if (!programMeta) {
165
162
  throw new NotFoundError(`Program not found: ${program}`);
@@ -178,7 +175,7 @@ export async function runCLICommand({ program, commandPath, data, singletonServi
178
175
  }
179
176
  const funcName = currentCommand.pikkuFuncName;
180
177
  // Get program-specific data
181
- const programs = pikkuState('cli', 'programs') || {};
178
+ const programs = pikkuState(null, 'cli', 'programs') || {};
182
179
  const programData = programs[program];
183
180
  // Combine program middleware + command middleware from the hierarchy
184
181
  const allWireMiddleware = [
@@ -217,39 +214,28 @@ export async function runCLICommand({ program, commandPath, data, singletonServi
217
214
  },
218
215
  state: 'open',
219
216
  };
220
- const userSession = new PikkuUserSessionService();
221
- let sessionServices;
222
- const interaction = {
217
+ const userSession = new PikkuSessionService();
218
+ const wire = {
223
219
  cli: {
224
220
  program,
225
221
  command: commandPath,
226
222
  data: pluckedData,
227
223
  channel,
228
224
  },
229
- };
230
- const getAllServices = async (session) => {
231
- // Create session-specific services for handling the command
232
- sessionServices = await createSessionServices?.(singletonServices, interaction, session);
233
- return rpcService.injectRPCService({
234
- ...singletonServices,
235
- ...sessionServices,
236
- userSession,
237
- channel,
238
- }, interaction, false);
225
+ session: userSession,
239
226
  };
240
227
  try {
241
- const result = await runPikkuFunc(PikkuWiringTypes.cli, commandId, funcName, {
228
+ const result = await runPikkuFunc('cli', commandId, funcName, {
242
229
  singletonServices,
243
- getAllServices,
230
+ createWireServices,
244
231
  data: pluckedData,
245
232
  auth: false,
246
- userSession,
247
233
  inheritedMiddleware: currentCommand.middleware,
248
234
  wireMiddleware: allWireMiddleware,
249
235
  inheritedPermissions: currentCommand.permissions,
250
236
  wirePermissions: undefined,
251
237
  tags: programData?.tags,
252
- interaction,
238
+ wire,
253
239
  });
254
240
  // Apply renderer one final time with the final output (if renderer exists)
255
241
  if (renderer) {
@@ -260,10 +246,6 @@ export async function runCLICommand({ program, commandPath, data, singletonServi
260
246
  finally {
261
247
  // Close the channel
262
248
  channel.close();
263
- // Clean up session services
264
- if (sessionServices) {
265
- await closeSessionServices(singletonServices.logger, sessionServices);
266
- }
267
249
  }
268
250
  }
269
251
  /**
@@ -278,13 +260,13 @@ export const pikkuCLIRender = (renderer) => {
278
260
  *
279
261
  * @throws {CLIError} When CLI execution fails - should be caught by wrapper to call process.exit()
280
262
  */
281
- export async function executeCLI({ programName, args, createConfig, createSingletonServices, createSessionServices, }) {
263
+ export async function executeCLI({ programName, args, createConfig, createSingletonServices, createWireServices, }) {
282
264
  if (!args) {
283
265
  throw new Error('CLI arguments are required, this is to satisfy release diffs');
284
266
  }
285
267
  try {
286
268
  // Get CLI metadata from state
287
- const allCLIMeta = pikkuState('cli', 'meta');
269
+ const allCLIMeta = pikkuState(null, 'cli', 'meta');
288
270
  if (!allCLIMeta) {
289
271
  throw new Error('[PKU342] CLI metadata not found. No CLI wirings were registered. See https://pikku.dev/docs/pikku-cli/errors/pku342 for more information.');
290
272
  }
@@ -333,7 +315,7 @@ export async function executeCLI({ programName, args, createConfig, createSingle
333
315
  commandPath: parsed.commandPath,
334
316
  data,
335
317
  singletonServices,
336
- createSessionServices,
318
+ createWireServices,
337
319
  });
338
320
  }
339
321
  catch (error) {
@@ -1,4 +1,4 @@
1
- import { CorePikkuMiddleware, CoreSingletonServices, CoreUserSession, PikkuDocs, CoreServices, MiddlewareMetadata, PermissionMetadata } from '../../types/core.types.js';
1
+ import { CorePikkuMiddleware, CoreSingletonServices, CoreUserSession, CoreServices, MiddlewareMetadata, PermissionMetadata } from '../../types/core.types.js';
2
2
  import { CorePikkuFunctionConfig, CorePikkuPermission, CorePikkuFunction, CorePikkuFunctionSessionless } from '../../function/functions.types.js';
3
3
  import { PikkuChannel } from '../channel/channel.types.js';
4
4
  /**
@@ -27,7 +27,7 @@ export interface CLIPositional {
27
27
  variadic?: boolean;
28
28
  }
29
29
  /**
30
- * CLI interaction context
30
+ * CLI wire context
31
31
  */
32
32
  export type PikkuCLI = {
33
33
  program: string;
@@ -55,8 +55,9 @@ export interface CLICommandMeta {
55
55
  positionals: CLIPositional[];
56
56
  options: Record<string, CLIOption>;
57
57
  renderName?: string;
58
+ summary?: string;
58
59
  description?: string;
59
- docs?: PikkuDocs;
60
+ errors?: string[];
60
61
  tags?: string[];
61
62
  subcommands?: Record<string, CLICommandMeta>;
62
63
  middleware?: MiddlewareMetadata[];
@@ -99,7 +100,7 @@ export type CorePikkuCLIRender<Data, Services extends CoreSingletonServices = Co
99
100
  /**
100
101
  * Extract input parameters from a Pikku function config type
101
102
  */
102
- export type ExtractFunctionInput<Func> = Func extends CorePikkuFunctionConfig<infer FuncType, any, any> ? FuncType extends CorePikkuFunction<infer Input, any, any, any, any> | CorePikkuFunctionSessionless<infer Input, any, any, any, any> ? Input : never : never;
103
+ export type ExtractFunctionInput<Func> = Func extends CorePikkuFunctionConfig<infer FuncType, any, any> ? FuncType extends CorePikkuFunction<infer Input, any, any, any> | CorePikkuFunctionSessionless<infer Input, any, any, any> ? Input : never : never;
103
104
  /**
104
105
  * Strip < > [ ] characters from a string
105
106
  */
@@ -131,14 +132,15 @@ export type ValidateParameters<Params extends string, Input> = AllParamsValid<Ex
131
132
  /**
132
133
  * Extract output type from a Pikku function config type
133
134
  */
134
- export type ExtractFunctionOutput<Func> = Func extends CorePikkuFunctionConfig<infer FuncType, any, any> ? FuncType extends CorePikkuFunction<any, infer Output, any, any, any> | CorePikkuFunctionSessionless<any, infer Output, any, any, any> ? Output : never : never;
135
+ export type ExtractFunctionOutput<Func> = Func extends CorePikkuFunctionConfig<infer FuncType, any, any> ? FuncType extends CorePikkuFunction<any, infer Output, any, any> | CorePikkuFunctionSessionless<any, infer Output, any, any> ? Output : never : never;
135
136
  /**
136
137
  * CLI command configuration that infers options from function input type.
137
138
  * This is a helper type for creating type-safe CLI commands.
138
139
  */
139
- export type CoreCLICommandConfig<FuncConfig, PikkuMiddleware extends CorePikkuMiddleware<any> = CorePikkuMiddleware<any>, PikkuCLIRender extends CorePikkuCLIRender<any, any, any> = CorePikkuCLIRender<any, any>, Params extends string = string> = {
140
+ export type CoreCLICommandConfig<FuncConfig, PikkuMiddleware extends CorePikkuMiddleware<any, any> = CorePikkuMiddleware<any, any>, PikkuCLIRender extends CorePikkuCLIRender<any, any, any> = CorePikkuCLIRender<any, any>, Params extends string = string> = {
140
141
  parameters?: ValidateParameters<Params, ExtractFunctionInput<FuncConfig>>;
141
142
  func?: FuncConfig;
143
+ title?: string;
142
144
  description?: string;
143
145
  render?: PikkuCLIRender;
144
146
  options?: {
@@ -157,7 +159,7 @@ export type CoreCLICommandConfig<FuncConfig, PikkuMiddleware extends CorePikkuMi
157
159
  /**
158
160
  * CLI command definition
159
161
  */
160
- export interface CoreCLICommand<In, Out, PikkuFunctionConfig extends CorePikkuFunctionConfig<CorePikkuFunction<In, Out, any, any, any> | CorePikkuFunctionSessionless<In, Out, any, any, any>>, PikkuPermission extends CorePikkuPermission<any, any, any>, PikkuMiddleware extends CorePikkuMiddleware, Options = any, Subcommands extends Record<string, CoreCLICommandConfig<any, any, any>> = Record<string, CoreCLICommandConfig<any, any, any>>> {
162
+ export interface CoreCLICommand<In, Out, PikkuFunctionConfig extends CorePikkuFunctionConfig<CorePikkuFunction<In, Out, any, any> | CorePikkuFunctionSessionless<In, Out, any, any>>, PikkuPermission extends CorePikkuPermission<any, any, any>, PikkuMiddleware extends CorePikkuMiddleware, Options = any, Subcommands extends Record<string, CoreCLICommandConfig<any, any, any>> = Record<string, CoreCLICommandConfig<any, any, any>>> {
161
163
  parameters?: string;
162
164
  func: PikkuFunctionConfig;
163
165
  render?: CorePikkuCLIRender<Out>;
@@ -166,18 +168,20 @@ export interface CoreCLICommand<In, Out, PikkuFunctionConfig extends CorePikkuFu
166
168
  middleware?: PikkuMiddleware[];
167
169
  permissions?: Record<string, PikkuPermission | PikkuPermission[]>;
168
170
  auth?: boolean;
169
- docs?: PikkuDocs;
171
+ summary?: string;
172
+ errors?: string[];
173
+ tags?: string[];
170
174
  subcommands?: Subcommands;
171
175
  isDefault?: boolean;
172
176
  }
173
177
  /**
174
178
  * Shorthand command definition (just a function)
175
179
  */
176
- export type CLICommandShorthand<In, Out, PikkuFunctionConfig extends CorePikkuFunctionConfig<CorePikkuFunction<In, Out, any, any, any> | CorePikkuFunctionSessionless<In, Out, any, any, any>>> = PikkuFunctionConfig;
180
+ export type CLICommandShorthand<In, Out, PikkuFunctionConfig extends CorePikkuFunctionConfig<CorePikkuFunction<In, Out, any, any> | CorePikkuFunctionSessionless<In, Out, any, any>>> = PikkuFunctionConfig;
177
181
  /**
178
182
  * Command definition (either full or shorthand)
179
183
  */
180
- export type CLICommandDefinition<In, Out, PikkuFunctionConfig extends CorePikkuFunctionConfig<CorePikkuFunction<In, Out, any, any, any> | CorePikkuFunctionSessionless<In, Out, any, any, any>>, PikkuPermission extends CorePikkuPermission<any, any, any>, PikkuMiddleware extends CorePikkuMiddleware, Options = any, Subcommands extends Record<string, CoreCLICommandConfig<any, any, any>> = Record<string, CoreCLICommandConfig<any, any, any>>> = CoreCLICommand<In, Out, PikkuFunctionConfig, PikkuPermission, PikkuMiddleware, Options, Subcommands> | CLICommandShorthand<In, Out, PikkuFunctionConfig>;
184
+ export type CLICommandDefinition<In, Out, PikkuFunctionConfig extends CorePikkuFunctionConfig<CorePikkuFunction<In, Out, any, any> | CorePikkuFunctionSessionless<In, Out, any, any>>, PikkuPermission extends CorePikkuPermission<any, any, any>, PikkuMiddleware extends CorePikkuMiddleware, Options = any, Subcommands extends Record<string, CoreCLICommandConfig<any, any, any>> = Record<string, CoreCLICommandConfig<any, any, any>>> = CoreCLICommand<In, Out, PikkuFunctionConfig, PikkuPermission, PikkuMiddleware, Options, Subcommands> | CLICommandShorthand<In, Out, PikkuFunctionConfig>;
181
185
  /**
182
186
  * CLI wiring configuration
183
187
  */
@@ -188,7 +192,8 @@ export interface CoreCLI<Commands extends Record<string, CoreCLICommandConfig<an
188
192
  options?: CLIOptions<Options>;
189
193
  middleware?: PikkuMiddleware[];
190
194
  render?: PikkuCLIRender;
191
- docs?: PikkuDocs;
195
+ summary?: string;
196
+ errors?: string[];
192
197
  tags?: string[];
193
198
  }
194
199
  /**