@pikku/cli 0.10.2 → 0.11.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.
Files changed (165) hide show
  1. package/.pikku/channel/pikku-channel-types.gen.ts +1 -1
  2. package/.pikku/channel/pikku-channels-map.gen.d.ts +4 -1
  3. package/.pikku/channel/pikku-channels-meta.gen.ts +1 -1
  4. package/.pikku/channel/pikku-channels.gen.ts +1 -1
  5. package/.pikku/cli/pikku-cli-types.gen.ts +1 -1
  6. package/.pikku/cli/pikku-cli-wirings-meta.gen.ts +5 -2
  7. package/.pikku/cli/pikku-cli-wirings.gen.ts +1 -1
  8. package/.pikku/function/pikku-function-types.gen.ts +1 -1
  9. package/.pikku/function/pikku-functions-meta.gen.ts +110 -1
  10. package/.pikku/function/pikku-functions-meta.min.gen.ts +26 -1
  11. package/.pikku/function/pikku-functions.gen.ts +9 -1
  12. package/.pikku/http/pikku-http-types.gen.ts +1 -1
  13. package/.pikku/http/pikku-http-wirings-map.gen.d.ts +4 -1
  14. package/.pikku/http/pikku-http-wirings-meta.gen.ts +1 -1
  15. package/.pikku/http/pikku-http-wirings.gen.ts +1 -1
  16. package/.pikku/mcp/pikku-mcp-types.gen.ts +1 -1
  17. package/.pikku/mcp/pikku-mcp-wirings-meta.gen.ts +1 -1
  18. package/.pikku/mcp/pikku-mcp-wirings.gen.ts +1 -1
  19. package/.pikku/pikku-bootstrap.gen.ts +4 -1
  20. package/.pikku/pikku-services.gen.ts +6 -1
  21. package/.pikku/pikku-types.gen.ts +1 -1
  22. package/.pikku/pikku-websocket.gen.ts +1 -1
  23. package/.pikku/queue/pikku-queue-types.gen.ts +1 -1
  24. package/.pikku/queue/pikku-queue-workers-wirings-map.gen.d.ts +4 -1
  25. package/.pikku/queue/pikku-queue-workers-wirings-meta.gen.ts +7 -2
  26. package/.pikku/queue/pikku-queue-workers-wirings.gen.ts +1 -1
  27. package/.pikku/rpc/pikku-remote-rpc-workers.gen.ts +27 -0
  28. package/.pikku/rpc/pikku-rpc-wirings-map.gen.d.ts +12 -2
  29. package/.pikku/rpc/pikku-rpc-wirings-map.internal.gen.d.ts +17 -2
  30. package/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.ts +7 -2
  31. package/.pikku/scheduler/pikku-scheduler-types.gen.ts +1 -1
  32. package/.pikku/scheduler/pikku-schedulers-wirings-meta.gen.ts +1 -1
  33. package/.pikku/scheduler/pikku-schedulers-wirings.gen.ts +1 -1
  34. package/.pikku/schemas/register.gen.ts +13 -1
  35. package/.pikku/schemas/schemas/PikkuCLIConfig.schema.json +1 -1
  36. package/.pikku/schemas/schemas/PikkuPublicRPCOutput.schema.json +1 -0
  37. package/.pikku/schemas/schemas/PikkuRemoteRPCOutput.schema.json +1 -0
  38. package/.pikku/schemas/schemas/PikkuWorkflowOutput.schema.json +1 -0
  39. package/.pikku/workflow/pikku-workflow-map.gen.d.ts +62 -0
  40. package/.pikku/workflow/pikku-workflow-types.gen.ts +92 -0
  41. package/.pikku/workflow/pikku-workflow-wirings-meta.gen.ts +5 -0
  42. package/.pikku/workflow/pikku-workflow-wirings.gen.ts +4 -0
  43. package/CHANGELOG.md +8 -0
  44. package/cli.schema.json +1 -1
  45. package/dist/.pikku/channel/pikku-channel-types.gen.d.ts +1 -1
  46. package/dist/.pikku/channel/pikku-channel-types.gen.js +1 -1
  47. package/dist/.pikku/channel/pikku-channels-meta.gen.js +1 -1
  48. package/dist/.pikku/channel/pikku-channels.gen.d.ts +1 -1
  49. package/dist/.pikku/channel/pikku-channels.gen.js +1 -1
  50. package/dist/.pikku/cli/pikku-cli-types.gen.d.ts +1 -1
  51. package/dist/.pikku/cli/pikku-cli-types.gen.js +1 -1
  52. package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.js +5 -2
  53. package/dist/.pikku/cli/pikku-cli-wirings.gen.d.ts +1 -1
  54. package/dist/.pikku/cli/pikku-cli-wirings.gen.js +1 -1
  55. package/dist/.pikku/function/pikku-function-types.gen.d.ts +1 -1
  56. package/dist/.pikku/function/pikku-function-types.gen.js +1 -1
  57. package/dist/.pikku/function/pikku-functions-meta.gen.js +110 -1
  58. package/dist/.pikku/function/pikku-functions-meta.min.gen.js +26 -1
  59. package/dist/.pikku/function/pikku-functions.gen.js +9 -1
  60. package/dist/.pikku/http/pikku-http-types.gen.d.ts +1 -1
  61. package/dist/.pikku/http/pikku-http-types.gen.js +1 -1
  62. package/dist/.pikku/http/pikku-http-wirings-meta.gen.js +1 -1
  63. package/dist/.pikku/http/pikku-http-wirings.gen.d.ts +1 -1
  64. package/dist/.pikku/http/pikku-http-wirings.gen.js +1 -1
  65. package/dist/.pikku/mcp/pikku-mcp-types.gen.d.ts +1 -1
  66. package/dist/.pikku/mcp/pikku-mcp-types.gen.js +1 -1
  67. package/dist/.pikku/mcp/pikku-mcp-wirings-meta.gen.js +1 -1
  68. package/dist/.pikku/mcp/pikku-mcp-wirings.gen.d.ts +1 -1
  69. package/dist/.pikku/mcp/pikku-mcp-wirings.gen.js +1 -1
  70. package/dist/.pikku/pikku-bootstrap.gen.d.ts +4 -1
  71. package/dist/.pikku/pikku-bootstrap.gen.js +4 -1
  72. package/dist/.pikku/pikku-services.gen.d.ts +8 -2
  73. package/dist/.pikku/pikku-services.gen.js +7 -1
  74. package/dist/.pikku/pikku-types.gen.d.ts +1 -1
  75. package/dist/.pikku/pikku-types.gen.js +1 -1
  76. package/dist/.pikku/pikku-websocket.gen.d.ts +1 -1
  77. package/dist/.pikku/pikku-websocket.gen.js +1 -1
  78. package/dist/.pikku/queue/pikku-queue-types.gen.d.ts +1 -1
  79. package/dist/.pikku/queue/pikku-queue-types.gen.js +1 -1
  80. package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.js +7 -2
  81. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.d.ts +1 -1
  82. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.js +1 -1
  83. package/dist/.pikku/rpc/pikku-remote-rpc-workers.gen.d.ts +17 -0
  84. package/dist/.pikku/rpc/pikku-remote-rpc-workers.gen.js +22 -0
  85. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.js +7 -2
  86. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.d.ts +1 -1
  87. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.js +1 -1
  88. package/dist/.pikku/scheduler/pikku-schedulers-wirings-meta.gen.js +1 -1
  89. package/dist/.pikku/scheduler/pikku-schedulers-wirings.gen.d.ts +1 -1
  90. package/dist/.pikku/scheduler/pikku-schedulers-wirings.gen.js +1 -1
  91. package/dist/.pikku/schemas/register.gen.js +7 -1
  92. package/dist/.pikku/schemas/schemas/PikkuCLIConfig.schema.json +1 -1
  93. package/dist/.pikku/schemas/schemas/PikkuPublicRPCOutput.schema.json +1 -0
  94. package/dist/.pikku/schemas/schemas/PikkuRemoteInternalRPCInput.schema.json +1 -0
  95. package/dist/.pikku/schemas/schemas/PikkuRemoteRPCOutput.schema.json +1 -0
  96. package/dist/.pikku/schemas/schemas/PikkuWorkflowOutput.schema.json +1 -0
  97. package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +58 -0
  98. package/dist/.pikku/workflow/pikku-workflow-types.gen.js +28 -0
  99. package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.d.ts +1 -0
  100. package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +5 -0
  101. package/dist/.pikku/workflow/pikku-workflow-wirings.gen.d.ts +4 -0
  102. package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +5 -0
  103. package/dist/src/functions/commands/all.js +20 -0
  104. package/dist/src/functions/commands/bootstrap.js +1 -0
  105. package/dist/src/functions/wirings/cli/serialize-channel-cli-client.js +15 -22
  106. package/dist/src/functions/wirings/queue/pikku-queue.js +9 -1
  107. package/dist/src/functions/wirings/queue/serialize-queue-map.d.ts +2 -2
  108. package/dist/src/functions/wirings/queue/serialize-queue-meta.d.ts +2 -2
  109. package/dist/src/functions/wirings/rpc/pikku-command-public-rpc.d.ts +1 -0
  110. package/dist/src/functions/wirings/rpc/pikku-command-public-rpc.js +23 -0
  111. package/dist/src/functions/wirings/rpc/pikku-command-remote-rpc.d.ts +1 -0
  112. package/dist/src/functions/wirings/rpc/pikku-command-remote-rpc.js +23 -0
  113. package/dist/src/functions/wirings/rpc/serialize-public-rpc.d.ts +4 -0
  114. package/dist/src/functions/wirings/rpc/serialize-public-rpc.js +30 -0
  115. package/dist/src/functions/wirings/rpc/serialize-remote-rpc.d.ts +4 -0
  116. package/dist/src/functions/wirings/rpc/serialize-remote-rpc.js +30 -0
  117. package/dist/src/functions/wirings/rpc/serialize-rpc-wrapper.js +2 -2
  118. package/dist/src/functions/wirings/rpc/serialize-typed-rpc-map.js +27 -3
  119. package/dist/src/functions/wirings/workflow/pikku-command-workflow-map.d.ts +1 -0
  120. package/dist/src/functions/wirings/workflow/pikku-command-workflow-map.js +12 -0
  121. package/dist/src/functions/wirings/workflow/pikku-command-workflow-types.d.ts +1 -0
  122. package/dist/src/functions/wirings/workflow/pikku-command-workflow-types.js +11 -0
  123. package/dist/src/functions/wirings/workflow/pikku-command-workflow.d.ts +1 -0
  124. package/dist/src/functions/wirings/workflow/pikku-command-workflow.js +55 -0
  125. package/dist/src/functions/wirings/workflow/serialize-workflow-map.d.ts +4 -0
  126. package/dist/src/functions/wirings/workflow/serialize-workflow-map.js +79 -0
  127. package/dist/src/functions/wirings/workflow/serialize-workflow-meta.d.ts +2 -0
  128. package/dist/src/functions/wirings/workflow/serialize-workflow-meta.js +10 -0
  129. package/dist/src/functions/wirings/workflow/serialize-workflow-types.d.ts +4 -0
  130. package/dist/src/functions/wirings/workflow/serialize-workflow-types.js +95 -0
  131. package/dist/src/functions/wirings/workflow/serialize-workflow-workers.d.ts +4 -0
  132. package/dist/src/functions/wirings/workflow/serialize-workflow-workers.js +60 -0
  133. package/dist/src/services/cli-logger-forwarder.service.js +1 -1
  134. package/dist/src/services/cli-logger.service.js +1 -1
  135. package/dist/src/utils/command-summary.d.ts +1 -0
  136. package/dist/src/utils/command-summary.js +9 -8
  137. package/dist/src/utils/pikku-cli-config.js +24 -4
  138. package/dist/src/utils/schema-generator.js +28 -7
  139. package/dist/tsconfig.tsbuildinfo +1 -1
  140. package/package.json +3 -3
  141. package/src/functions/commands/all.ts +28 -0
  142. package/src/functions/commands/bootstrap.ts +1 -0
  143. package/src/functions/wirings/cli/serialize-channel-cli-client.ts +15 -22
  144. package/src/functions/wirings/queue/pikku-queue.ts +10 -1
  145. package/src/functions/wirings/queue/serialize-queue-map.ts +3 -3
  146. package/src/functions/wirings/queue/serialize-queue-meta.ts +2 -2
  147. package/src/functions/wirings/rpc/pikku-command-public-rpc.ts +32 -0
  148. package/src/functions/wirings/rpc/pikku-command-remote-rpc.ts +35 -0
  149. package/src/functions/wirings/rpc/serialize-public-rpc.ts +30 -0
  150. package/src/functions/wirings/rpc/serialize-remote-rpc.ts +30 -0
  151. package/src/functions/wirings/rpc/serialize-rpc-wrapper.ts +2 -2
  152. package/src/functions/wirings/rpc/serialize-typed-rpc-map.ts +26 -3
  153. package/src/functions/wirings/workflow/pikku-command-workflow-map.ts +24 -0
  154. package/src/functions/wirings/workflow/pikku-command-workflow-types.ts +22 -0
  155. package/src/functions/wirings/workflow/pikku-command-workflow.ts +123 -0
  156. package/src/functions/wirings/workflow/serialize-workflow-map.ts +123 -0
  157. package/src/functions/wirings/workflow/serialize-workflow-meta.ts +16 -0
  158. package/src/functions/wirings/workflow/serialize-workflow-types.ts +95 -0
  159. package/src/functions/wirings/workflow/serialize-workflow-workers.ts +60 -0
  160. package/src/services/cli-logger-forwarder.service.ts +1 -1
  161. package/src/services/cli-logger.service.ts +1 -1
  162. package/src/utils/command-summary.ts +10 -8
  163. package/src/utils/pikku-cli-config.ts +44 -4
  164. package/src/utils/schema-generator.ts +25 -7
  165. package/types/config.d.ts +45 -0
@@ -23,6 +23,7 @@ export const all = pikkuVoidFunc({
23
23
  await rpc.invoke('pikkuChannelTypes', null);
24
24
  await rpc.invoke('pikkuSchedulerTypes', null);
25
25
  await rpc.invoke('pikkuQueueTypes', null);
26
+ await rpc.invoke('pikkuWorkflowTypes', null);
26
27
  await rpc.invoke('pikkuMCPTypes', null);
27
28
  await rpc.invoke('pikkuCLITypes', null);
28
29
  const hasFunctionRegistrations = await rpc.invoke('pikkuFunctions', null);
@@ -69,6 +70,22 @@ export const all = pikkuVoidFunc({
69
70
  if (scheduler) {
70
71
  allImports.push(config.schedulersWiringMetaFile, config.schedulersWiringFile);
71
72
  }
73
+ // Generate Workflows
74
+ const workflows = await rpc.invoke('pikkuWorkflow', null);
75
+ // Generate Remote RPC Workers (must be before queue discovery so wireQueueWorker calls are picked up)
76
+ const remoteRPC = await rpc.invoke('pikkuRemoteRPC', null);
77
+ // Reinspect to pick up generated workflow workers and remote RPC workers BEFORE generating maps
78
+ if (workflows || remoteRPC) {
79
+ await getInspectorState(true);
80
+ }
81
+ if (workflows) {
82
+ await rpc.invoke('pikkuWorkflowMap', null);
83
+ allImports.push(config.workflowsWiringMetaFile, config.workflowsWiringFile);
84
+ }
85
+ if (remoteRPC && config.rpc?.remoteRpcWorkersPath) {
86
+ // Only add to imports if we actually generated the file
87
+ allImports.push(config.rpc.remoteRpcWorkersPath);
88
+ }
72
89
  // Generate Queues
73
90
  const queues = await rpc.invoke('pikkuQueue', null);
74
91
  if (queues) {
@@ -131,6 +148,9 @@ export const all = pikkuVoidFunc({
131
148
  if (totalCommands > 0)
132
149
  summary.set('cliCommands', totalCommands);
133
150
  }
151
+ if (state.workflows?.meta) {
152
+ summary.set('workflows', Object.keys(state.workflows.meta).length);
153
+ }
134
154
  // Display summary (unless in silent mode)
135
155
  if (!logger.isSilent()) {
136
156
  console.log(summary.format());
@@ -13,6 +13,7 @@ export const bootstrap = pikkuVoidFunc({
13
13
  await rpc.invoke('pikkuChannelTypes', null);
14
14
  await rpc.invoke('pikkuSchedulerTypes', null);
15
15
  await rpc.invoke('pikkuQueueTypes', null);
16
+ await rpc.invoke('pikkuWorkflowTypes', null);
16
17
  await rpc.invoke('pikkuMCPTypes', null);
17
18
  await rpc.invoke('pikkuCLITypes', null);
18
19
  // Check for critical errors and exit if any were logged
@@ -99,29 +99,10 @@ ${rendererImports}
99
99
  * Executes CLI commands over a WebSocket connection
100
100
  */
101
101
  export async function ${capitalizedName}CLIClient(
102
- url: string,
102
+ ws: WebSocket,
103
103
  args?: string[]
104
104
  ): Promise<void> {
105
- // Get WebSocket implementation (browser or Node.js)
106
- let WebSocketImpl: any
107
- if (typeof WebSocket !== 'undefined') {
108
- WebSocketImpl = WebSocket
109
- } else {
110
- // Node.js environment - dynamically import 'ws'
111
- try {
112
- const wsModule = await import('ws')
113
- WebSocketImpl = wsModule.default
114
- } catch (e) {
115
- throw new Error(
116
- 'No WebSocket implementation found. In Node.js environments, you need to:\\n' +
117
- '1. Install the "ws" package: npm install ws\\n' +
118
- 'Learn more: https://www.npmjs.com/package/ws'
119
- )
120
- }
121
- }
122
-
123
- // Create WebSocket connection
124
- const ws = new WebSocketImpl(url) as WebSocket
105
+ // Create Pikku WebSocket wrapper
125
106
  const pikkuWS = new CorePikkuWebsocket(ws)
126
107
 
127
108
  // Register renderers for CLI commands
@@ -141,7 +122,19 @@ export default ${capitalizedName}CLIClient
141
122
  // For direct execution (if this file is run directly)
142
123
  if (import.meta.url === \`file://\${process.argv[1]}\`) {
143
124
  const url = process.env.PIKKU_WS_URL || 'ws://localhost:4002${finalChannelRoute}'
144
- ${capitalizedName}CLIClient(url, process.argv.slice(2)).catch(error => {
125
+
126
+ // Create WebSocket instance
127
+ let WebSocketImpl: any
128
+ if (typeof WebSocket !== 'undefined') {
129
+ WebSocketImpl = WebSocket
130
+ } else {
131
+ // Node.js environment - dynamically import 'ws'
132
+ const wsModule = await import('ws')
133
+ WebSocketImpl = wsModule.default
134
+ }
135
+
136
+ const ws = new WebSocketImpl(url) as WebSocket
137
+ ${capitalizedName}CLIClient(ws, process.argv.slice(2)).catch(error => {
145
138
  console.error('Fatal channel CLI error:', error)
146
139
  // TODO: We get an error code even when it exists cleanly, investigate
147
140
  // process.exit(1)
@@ -8,7 +8,15 @@ export const pikkuQueue = pikkuSessionlessFunc({
8
8
  const visitState = await getInspectorState();
9
9
  const { queueWorkersWiringFile, queueWorkersWiringMetaFile, packageMappings, } = config;
10
10
  const { queueWorkers } = visitState;
11
- await writeFileInDir(logger, queueWorkersWiringMetaFile, serializeQueueMeta(queueWorkers.meta));
11
+ // Add remote RPC worker to queue metadata if it exists
12
+ const queueMeta = { ...queueWorkers.meta };
13
+ if (config.rpc?.remoteRpcWorkersPath) {
14
+ queueMeta['pikku-remote-internal-rpc'] = {
15
+ pikkuFuncName: 'pikkuRemoteInternalRPC',
16
+ queueName: 'pikku-remote-internal-rpc',
17
+ };
18
+ }
19
+ await writeFileInDir(logger, queueWorkersWiringMetaFile, serializeQueueMeta(queueMeta));
12
20
  await writeFileInDir(logger, queueWorkersWiringFile, serializeFileImports('addQueueWorkers', queueWorkersWiringFile, queueWorkers.files, packageMappings));
13
21
  return true;
14
22
  },
@@ -1,4 +1,4 @@
1
- import type { queueWorkersMeta } from '@pikku/core/queue';
1
+ import type { QueueWorkersMeta } from '@pikku/core/queue';
2
2
  import { TypesMap } from '@pikku/inspector';
3
3
  import { FunctionsMeta } from '@pikku/core';
4
- export declare const serializeQueueMap: (relativeToPath: string, packageMappings: Record<string, string>, typesMap: TypesMap, functionsMeta: FunctionsMeta, queueWorkersMeta: queueWorkersMeta) => string;
4
+ export declare const serializeQueueMap: (relativeToPath: string, packageMappings: Record<string, string>, typesMap: TypesMap, functionsMeta: FunctionsMeta, queueWorkersMeta: QueueWorkersMeta) => string;
@@ -1,2 +1,2 @@
1
- import { queueWorkersMeta } from '@pikku/core/queue';
2
- export declare const serializeQueueMeta: (queueWorkersMeta: queueWorkersMeta) => string;
1
+ import { QueueWorkersMeta } from '@pikku/core/queue';
2
+ export declare const serializeQueueMeta: (queueWorkersMeta: QueueWorkersMeta) => string;
@@ -0,0 +1 @@
1
+ export declare const pikkuPublicRPC: any;
@@ -0,0 +1,23 @@
1
+ import { pikkuSessionlessFunc } from '../../../../.pikku/pikku-types.gen.js';
2
+ import { getFileImportRelativePath } from '../../../utils/file-import-path.js';
3
+ import { writeFileInDir } from '../../../utils/file-writer.js';
4
+ import { logCommandInfoAndTime } from '../../../middleware/log-command-info-and-time.js';
5
+ import { serializePublicRPC } from './serialize-public-rpc.js';
6
+ import { join } from 'path';
7
+ export const pikkuPublicRPC = pikkuSessionlessFunc({
8
+ func: async ({ logger, config }) => {
9
+ if (config.rpc?.publicRpcPath) {
10
+ const publicRpcPath = join(config.rootDir, config.rpc.publicRpcPath);
11
+ const pathToPikkuTypes = getFileImportRelativePath(publicRpcPath, config.typesDeclarationFile, config.packageMappings);
12
+ await writeFileInDir(logger, publicRpcPath, serializePublicRPC(pathToPikkuTypes));
13
+ return true;
14
+ }
15
+ return false;
16
+ },
17
+ middleware: [
18
+ logCommandInfoAndTime({
19
+ commandStart: 'Generating Public RPC Endpoint',
20
+ commandEnd: 'Generated Public RPC Endpoint',
21
+ }),
22
+ ],
23
+ });
@@ -0,0 +1 @@
1
+ export declare const pikkuRemoteRPC: any;
@@ -0,0 +1,23 @@
1
+ import { pikkuSessionlessFunc } from '../../../../.pikku/pikku-types.gen.js';
2
+ import { getFileImportRelativePath } from '../../../utils/file-import-path.js';
3
+ import { writeFileInDir } from '../../../utils/file-writer.js';
4
+ import { logCommandInfoAndTime } from '../../../middleware/log-command-info-and-time.js';
5
+ import { serializeRemoteRPC } from './serialize-remote-rpc.js';
6
+ import { join } from 'path';
7
+ export const pikkuRemoteRPC = pikkuSessionlessFunc({
8
+ func: async ({ logger, config }) => {
9
+ if (config.rpc?.remoteRpcWorkersPath) {
10
+ const remoteRpcPath = join(config.rootDir, config.rpc.remoteRpcWorkersPath);
11
+ const pathToPikkuTypes = getFileImportRelativePath(remoteRpcPath, config.typesDeclarationFile, config.packageMappings);
12
+ await writeFileInDir(logger, remoteRpcPath, serializeRemoteRPC(pathToPikkuTypes));
13
+ return true;
14
+ }
15
+ return false;
16
+ },
17
+ middleware: [
18
+ logCommandInfoAndTime({
19
+ commandStart: 'Generating Remote RPC Workers',
20
+ commandEnd: 'Generated Remote RPC Workers',
21
+ }),
22
+ ],
23
+ });
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Generate public RPC HTTP endpoint
3
+ */
4
+ export declare const serializePublicRPC: (pathToPikkuTypes: string) => string;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Generate public RPC HTTP endpoint
3
+ */
4
+ export const serializePublicRPC = (pathToPikkuTypes) => {
5
+ return `/**
6
+ * Auto-generated public RPC HTTP endpoint
7
+ * Do not edit manually - regenerate with 'npx pikku'
8
+ */
9
+ import { pikkuSessionlessFunc, wireHTTP } from '${pathToPikkuTypes}'
10
+
11
+ /**
12
+ * Public RPC endpoint that invokes any exposed RPC by name
13
+ * This is used for public HTTP access to exposed server functions
14
+ */
15
+ export const rpcCaller = pikkuSessionlessFunc<
16
+ { name: string, data?: any },
17
+ any
18
+ >({
19
+ func: async ({ rpc }, { name, data }) => {
20
+ return await (rpc.invokeExposed as any)(name, data)
21
+ },
22
+ })
23
+
24
+ wireHTTP({
25
+ route: '/rpc',
26
+ method: 'post',
27
+ func: rpcCaller,
28
+ })
29
+ `;
30
+ };
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Generate remote internal RPC queue worker and HTTP endpoint
3
+ */
4
+ export declare const serializeRemoteRPC: (pathToPikkuTypes: string) => string;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Generate remote internal RPC queue worker and HTTP endpoint
3
+ */
4
+ export const serializeRemoteRPC = (pathToPikkuTypes) => {
5
+ return `/**
6
+ * Auto-generated remote internal RPC queue worker and HTTP endpoint
7
+ * Do not edit manually - regenerate with 'npx pikku'
8
+ */
9
+ import { pikkuSessionlessFunc, wireQueueWorker } from '${pathToPikkuTypes}'
10
+
11
+ /**
12
+ * Generic remote RPC worker that invokes any internal RPC by name
13
+ * This is used for executing internal RPCs via a queue or HTTP (e.g., scheduled tasks, background jobs, internal services)
14
+ */
15
+ export const pikkuRemoteInternalRPC = pikkuSessionlessFunc<
16
+ { rpcName: string, data?: any },
17
+ any
18
+ >({
19
+ func: async ({ rpc }, { rpcName, data }) => {
20
+ return await (rpc.invoke as any)(rpcName, data)
21
+ },
22
+ internal: true,
23
+ })
24
+
25
+ wireQueueWorker({
26
+ queueName: 'pikku-remote-internal-rpc',
27
+ func: pikkuRemoteInternalRPC,
28
+ })
29
+ `;
30
+ };
@@ -53,13 +53,13 @@ export class PikkuRPC {
53
53
  * Invokes a remote procedure call on the server.
54
54
  * This is a generic method that routes to the appropriate server function
55
55
  * based on the function name and passes the provided data.
56
- *
56
+ *
57
57
  * @param name - The name of the server function to invoke
58
58
  * @param data - The data to pass to the server function
59
59
  * @returns A promise that resolves with the function's return value
60
60
  */
61
61
  invoke: RPCInvoke = async (name, data) => {
62
- return await this.pikkuFetch.post('/rpc', { name, data })
62
+ return await this.pikkuFetch.post('/rpc' as any, { name, data }) as any
63
63
  }
64
64
  }
65
65
 
@@ -27,11 +27,18 @@ export type RPCInvoke = <Name extends keyof RPCMap>(
27
27
  }
28
28
  ) => Promise<RPCMap[Name]['output']>
29
29
 
30
+ // Import WorkflowMap for workflow typing
31
+ import type { WorkflowMap } from '../workflow/pikku-workflow-map.gen.js'
32
+
30
33
  export type TypedPikkuRPC = {
31
34
  depth: number;
32
35
  global: boolean;
33
36
  invoke: RPCInvoke;
34
- invokeExposed: (name: string, data: any) => Promise<any>
37
+ invokeExposed: (name: string, data: any) => Promise<any>;
38
+ startWorkflow: <Name extends keyof WorkflowMap>(
39
+ name: Name,
40
+ input: WorkflowMap[Name]['input']
41
+ ) => Promise<{ runId: string }>;
35
42
  }
36
43
  `;
37
44
  };
@@ -47,8 +54,25 @@ function generateRPCs(rpcMeta, functionsMeta, typesMap, requiredTypes) {
47
54
  const input = functionMeta.inputs ? functionMeta.inputs[0] : undefined;
48
55
  const output = functionMeta.outputs ? functionMeta.outputs[0] : undefined;
49
56
  // Store the input and output types for RPCHandler
50
- const inputType = input ? typesMap.getTypeMeta(input).uniqueName : 'null';
51
- const outputType = output ? typesMap.getTypeMeta(output).uniqueName : 'null';
57
+ // Use 'any' for types not in typesMap (e.g., inline types in generated workflow workers)
58
+ let inputType = 'null';
59
+ if (input) {
60
+ try {
61
+ inputType = typesMap.getTypeMeta(input).uniqueName;
62
+ }
63
+ catch {
64
+ inputType = 'any';
65
+ }
66
+ }
67
+ let outputType = 'null';
68
+ if (output) {
69
+ try {
70
+ outputType = typesMap.getTypeMeta(output).uniqueName;
71
+ }
72
+ catch {
73
+ outputType = 'any';
74
+ }
75
+ }
52
76
  requiredTypes.add(inputType);
53
77
  requiredTypes.add(outputType);
54
78
  // Add RPC entry
@@ -0,0 +1 @@
1
+ export declare const pikkuWorkflowMap: any;
@@ -0,0 +1,12 @@
1
+ import { pikkuSessionlessFunc } from '../../../../.pikku/pikku-types.gen.js';
2
+ import { writeFileInDir } from '../../../utils/file-writer.js';
3
+ import { serializeWorkflowMap } from './serialize-workflow-map.js';
4
+ export const pikkuWorkflowMap = pikkuSessionlessFunc({
5
+ func: async ({ logger, config, getInspectorState }) => {
6
+ const visitState = await getInspectorState();
7
+ const { workflowMapDeclarationFile, packageMappings } = config;
8
+ const { workflows, functions: functionState } = visitState;
9
+ const { typesMap } = functionState;
10
+ await writeFileInDir(logger, workflowMapDeclarationFile, serializeWorkflowMap(workflowMapDeclarationFile, packageMappings, typesMap, functionState.meta, workflows.meta));
11
+ },
12
+ });
@@ -0,0 +1 @@
1
+ export declare const pikkuWorkflowTypes: any;
@@ -0,0 +1,11 @@
1
+ import { pikkuSessionlessFunc } from '../../../../.pikku/pikku-types.gen.js';
2
+ import { writeFileInDir } from '../../../utils/file-writer.js';
3
+ import { serializeWorkflowTypes } from './serialize-workflow-types.js';
4
+ import { getFileImportRelativePath } from '../../../utils/file-import-path.js';
5
+ export const pikkuWorkflowTypes = pikkuSessionlessFunc({
6
+ func: async ({ logger, config }) => {
7
+ const { workflowTypesFile, functionTypesFile, packageMappings } = config;
8
+ const functionTypesImportPath = getFileImportRelativePath(workflowTypesFile, functionTypesFile, packageMappings);
9
+ await writeFileInDir(logger, workflowTypesFile, serializeWorkflowTypes(functionTypesImportPath));
10
+ },
11
+ });
@@ -0,0 +1 @@
1
+ export declare const pikkuWorkflow: any;
@@ -0,0 +1,55 @@
1
+ import { pikkuSessionlessFunc } from '../../../../.pikku/pikku-types.gen.js';
2
+ import { ErrorCode } from '@pikku/inspector';
3
+ import { serializeFileImports } from '../../../utils/file-imports-serializer.js';
4
+ import { writeFileInDir } from '../../../utils/file-writer.js';
5
+ import { logCommandInfoAndTime } from '../../../middleware/log-command-info-and-time.js';
6
+ import { serializeWorkflowMeta } from './serialize-workflow-meta.js';
7
+ import { serializeWorkflowTypes } from './serialize-workflow-types.js';
8
+ import { serializeWorkflowMap } from './serialize-workflow-map.js';
9
+ import { serializeWorkflowWorkers } from './serialize-workflow-workers.js';
10
+ import { getFileImportRelativePath } from '../../../utils/file-import-path.js';
11
+ import { join } from 'path';
12
+ export const pikkuWorkflow = pikkuSessionlessFunc({
13
+ func: async ({ logger, config, getInspectorState }) => {
14
+ const visitState = await getInspectorState();
15
+ const { workflowsWiringFile, workflowsWiringMetaFile, workflowMapDeclarationFile, workflowTypesFile, functionTypesFile, typesDeclarationFile, packageMappings, } = config;
16
+ const { workflows, functions: functionState } = visitState;
17
+ const { typesMap } = functionState;
18
+ // Validate that workflowService service is configured if workflows are defined
19
+ const hasWorkflows = Object.keys(workflows.meta).length > 0;
20
+ if (hasWorkflows) {
21
+ const hasWorkflowState = visitState.serviceAggregation.allSingletonServices.includes('workflowService');
22
+ if (!hasWorkflowState) {
23
+ logger.critical(ErrorCode.WORKFLOW_ORCHESTRATOR_NOT_CONFIGURED, 'Workflows detected but workflowService service not configured. Please add workflowService to your singleton services');
24
+ throw new Error('WorkflowState service not configured but workflows are defined');
25
+ }
26
+ }
27
+ // Write workflow metadata
28
+ await writeFileInDir(logger, workflowsWiringMetaFile, serializeWorkflowMeta(workflows.meta));
29
+ // Write workflow wirings (imports)
30
+ await writeFileInDir(logger, workflowsWiringFile, serializeFileImports('wireWorkflow', workflowsWiringFile, workflows.files, packageMappings));
31
+ // Write workflow types
32
+ const functionTypesImportPath = getFileImportRelativePath(workflowTypesFile, functionTypesFile, packageMappings);
33
+ await writeFileInDir(logger, workflowTypesFile, serializeWorkflowTypes(functionTypesImportPath));
34
+ // Write workflow map (type-safe client API)
35
+ await writeFileInDir(logger, workflowMapDeclarationFile, serializeWorkflowMap(workflowMapDeclarationFile, packageMappings, typesMap, functionState.meta, workflows.meta));
36
+ if (config.workflows) {
37
+ if (config.workflows.singleQueue) {
38
+ const workflowPath = join(config.rootDir, config.workflows.path);
39
+ const pathToPikkuTypes = getFileImportRelativePath(workflowPath, typesDeclarationFile, packageMappings);
40
+ await writeFileInDir(logger, workflowPath, serializeWorkflowWorkers(pathToPikkuTypes));
41
+ }
42
+ else if (workflows.files.size > 0) {
43
+ logger.critical(ErrorCode.WORKFLOW_MULTI_QUEUE_NOT_SUPPORTED, 'Multi-queue workflows are not supported when workflows.singleQueue is false. Please enable singleQueue in your configuration.');
44
+ return false;
45
+ }
46
+ }
47
+ return true;
48
+ },
49
+ middleware: [
50
+ logCommandInfoAndTime({
51
+ commandStart: 'Finding Workflows',
52
+ commandEnd: 'Found Workflows',
53
+ }),
54
+ ],
55
+ });
@@ -0,0 +1,4 @@
1
+ import type { WorkflowsMeta } from '@pikku/core/workflow';
2
+ import { TypesMap } from '@pikku/inspector';
3
+ import { FunctionsMeta } from '@pikku/core';
4
+ export declare const serializeWorkflowMap: (relativeToPath: string, packageMappings: Record<string, string>, typesMap: TypesMap, functionsMeta: FunctionsMeta, workflowsMeta: WorkflowsMeta) => string;
@@ -0,0 +1,79 @@
1
+ import { serializeImportMap } from '../../../utils/serialize-import-map.js';
2
+ import { generateCustomTypes } from '../../../utils/custom-types-generator.js';
3
+ export const serializeWorkflowMap = (relativeToPath, packageMappings, typesMap, functionsMeta, workflowsMeta) => {
4
+ const requiredTypes = new Set();
5
+ const serializedCustomTypes = generateCustomTypes(typesMap, requiredTypes);
6
+ const serializedWorkflows = generateWorkflows(workflowsMeta, functionsMeta, typesMap, requiredTypes);
7
+ const serializedImportMap = serializeImportMap(relativeToPath, packageMappings, typesMap, requiredTypes);
8
+ return `/**
9
+ * This provides the structure needed for TypeScript to be aware of workflows and their input/output types
10
+ */
11
+
12
+ ${serializedImportMap}
13
+ ${serializedCustomTypes}
14
+
15
+ interface WorkflowHandler<I, O> {
16
+ input: I;
17
+ output: O;
18
+ }
19
+
20
+ ${serializedWorkflows}
21
+
22
+ /**
23
+ * Type-safe workflow client API
24
+ */
25
+ export type WorkflowClient<Name extends keyof WorkflowMap> = {
26
+ /**
27
+ * Start a new workflow run
28
+ */
29
+ start: (input: WorkflowMap[Name]['input']) => Promise<{ runId: string }>;
30
+
31
+ /**
32
+ * Get a workflow run by ID
33
+ */
34
+ getRun: <output extends keyof WorkflowMap[Name]>(runId: string) => Promise<WorkflowMap[Name][output]>;
35
+
36
+ /**
37
+ * Cancel a running workflow
38
+ */
39
+ cancelRun: (runId: string) => Promise<boolean>;
40
+ }
41
+
42
+ /**
43
+ * Map of all registered workflows with type-safe client APIs
44
+ */
45
+ export type TypedWorkflowClients = {
46
+ [Name in keyof WorkflowMap]: WorkflowClient<Name>;
47
+ }
48
+ `;
49
+ };
50
+ function generateWorkflows(workflowsMeta, functionsMeta, typesMap, requiredTypes) {
51
+ // Initialize an object to collect workflows
52
+ const workflowsObj = {};
53
+ // Iterate through workflow metadata
54
+ for (const [workflowName, { pikkuFuncName }] of Object.entries(workflowsMeta)) {
55
+ const functionMeta = functionsMeta[pikkuFuncName];
56
+ if (!functionMeta) {
57
+ throw new Error(`Function ${workflowName} not found in functionsMeta. Please check your configuration.`);
58
+ }
59
+ const input = functionMeta.inputs ? functionMeta.inputs[0] : undefined;
60
+ const output = functionMeta.outputs ? functionMeta.outputs[0] : undefined;
61
+ // Store the input and output types for WorkflowHandler
62
+ const inputType = input ? typesMap.getTypeMeta(input).uniqueName : 'void';
63
+ const outputType = output ? typesMap.getTypeMeta(output).uniqueName : 'void';
64
+ requiredTypes.add(inputType);
65
+ requiredTypes.add(outputType);
66
+ // Add workflow entry
67
+ workflowsObj[workflowName] = {
68
+ inputType,
69
+ outputType,
70
+ };
71
+ }
72
+ // Build the Workflows object as a string
73
+ let workflowsStr = 'export type WorkflowMap = {\n';
74
+ for (const [workflowName, handler] of Object.entries(workflowsObj)) {
75
+ workflowsStr += ` readonly '${workflowName}': WorkflowHandler<${handler.inputType}, ${handler.outputType}>,\n`;
76
+ }
77
+ workflowsStr += '};\n';
78
+ return workflowsStr;
79
+ }
@@ -0,0 +1,2 @@
1
+ import { WorkflowsMeta } from '@pikku/core/workflow';
2
+ export declare const serializeWorkflowMeta: (workflowsMeta: WorkflowsMeta) => string;
@@ -0,0 +1,10 @@
1
+ export const serializeWorkflowMeta = (workflowsMeta) => {
2
+ const serializedOutput = [];
3
+ serializedOutput.push("import { pikkuState } from '@pikku/core'");
4
+ serializedOutput.push(`pikkuState('workflows', 'meta', ${JSON.stringify(workflowsMeta, null, 2)})`);
5
+ const workflowsMetaValues = Object.values(workflowsMeta);
6
+ if (workflowsMetaValues.length > 0) {
7
+ serializedOutput.push(`export type WorkflowNames = '${workflowsMetaValues.map((w) => w.workflowName).join("' | '")}'`);
8
+ }
9
+ return serializedOutput.join('\n');
10
+ };
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Generates type definitions for workflow wirings
3
+ */
4
+ export declare const serializeWorkflowTypes: (functionTypesImportPath: string) => string;
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Generates type definitions for workflow wirings
3
+ */
4
+ export const serializeWorkflowTypes = (functionTypesImportPath) => {
5
+ return `/**
6
+ * Workflow-specific type definitions for tree-shaking optimization
7
+ */
8
+
9
+ import { CoreWorkflow, wireWorkflow as wireWorkflowCore, PikkuWorkflowInteraction, WorkflowStepOptions } from '@pikku/core/workflow'
10
+ import { CorePikkuFunctionConfig, CorePikkuFunctionSessionless } from '@pikku/core'
11
+ import type { PikkuPermission, PikkuMiddleware } from '${functionTypesImportPath}'
12
+ import type { UserSession, SingletonServices } from '../../types/application-types.d.js'
13
+ import type { TypedPikkuRPC, RPCMap } from '../rpc/pikku-rpc-wirings-map.internal.gen.d.js'
14
+
15
+ /**
16
+ * Type definition for workflows that orchestrate multi-step processes.
17
+ * Workflows support both inline and remote execution modes with step caching.
18
+ */
19
+ type WorkflowWiring = CoreWorkflow<
20
+ CorePikkuFunctionConfig<PikkuFunctionWorkflow<any, any>, PikkuPermission<any>, PikkuMiddleware>
21
+ >
22
+
23
+ /**
24
+ * Typed workflow interaction with RPC awareness
25
+ * Provides type-safe workflow.do() for RPC steps
26
+ */
27
+ export interface TypedWorkflow extends PikkuWorkflowInteraction {
28
+ /**
29
+ * Execute a workflow step with RPC invocation (typed based on available RPCs)
30
+ * @template K - RPC name from the RPC map
31
+ */
32
+ do<K extends keyof RPCMap>(
33
+ stepName: string,
34
+ rpcName: K,
35
+ data: RPCMap[K]['input'],
36
+ options?: WorkflowStepOptions
37
+ ): Promise<RPCMap[K]['output']>
38
+
39
+ /**
40
+ * Execute a workflow step with inline function
41
+ * @template T - Return type of the inline function
42
+ */
43
+ do<T>(
44
+ stepName: string,
45
+ fn: () => T | Promise<T>,
46
+ options?: WorkflowStepOptions
47
+ ): Promise<T>
48
+ }
49
+
50
+ /**
51
+ * Workflow function type with typed workflow service
52
+ * Includes the workflow interaction object with typed RPC methods
53
+ */
54
+ export type PikkuFunctionWorkflow<
55
+ In = unknown,
56
+ Out = never
57
+ > = CorePikkuFunctionSessionless<
58
+ In,
59
+ Out,
60
+ null,
61
+ SingletonServices & {
62
+ rpc: TypedPikkuRPC
63
+ workflow: TypedWorkflow
64
+ },
65
+ UserSession
66
+ >
67
+
68
+ /**
69
+ * Creates a workflow function with typed input and output.
70
+ * Workflow functions have access to the workflow interaction object for step execution.
71
+ *
72
+ * @template In - Input type for the workflow
73
+ * @template Out - Output type for the workflow
74
+ * @param func - Function definition, either direct function or configuration object
75
+ * @returns The normalized configuration object
76
+ */
77
+ export const pikkuWorkflowFunc = <In, Out = unknown>(
78
+ func:
79
+ | PikkuFunctionWorkflow<In, Out>
80
+ | CorePikkuFunctionConfig<PikkuFunctionWorkflow<In, Out>, PikkuPermission<In>, PikkuMiddleware>
81
+ ) => {
82
+ return typeof func === 'function' ? { func } : func
83
+ }
84
+
85
+ /**
86
+ * Registers a workflow with the Pikku framework.
87
+ * Workflows can run in 'inline' (synchronous) or 'remote' (queue-based) execution modes.
88
+ *
89
+ * @param workflow - Workflow definition with name, execution mode, and handler function
90
+ */
91
+ export const wireWorkflow = (workflow: WorkflowWiring) => {
92
+ wireWorkflowCore(workflow as any)
93
+ }
94
+ `;
95
+ };
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Generate queue workers and RPC functions for workflow steps and orchestrator
3
+ */
4
+ export declare const serializeWorkflowWorkers: (pathToPikkuTypes: string) => string;