@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
@@ -48,11 +48,18 @@ export type RPCInvoke = <Name extends keyof RPCMap>(
48
48
  }
49
49
  ) => Promise<RPCMap[Name]['output']>
50
50
 
51
+ // Import WorkflowMap for workflow typing
52
+ import type { WorkflowMap } from '../workflow/pikku-workflow-map.gen.js'
53
+
51
54
  export type TypedPikkuRPC = {
52
55
  depth: number;
53
56
  global: boolean;
54
57
  invoke: RPCInvoke;
55
- invokeExposed: (name: string, data: any) => Promise<any>
58
+ invokeExposed: (name: string, data: any) => Promise<any>;
59
+ startWorkflow: <Name extends keyof WorkflowMap>(
60
+ name: Name,
61
+ input: WorkflowMap[Name]['input']
62
+ ) => Promise<{ runId: string }>;
56
63
  }
57
64
  `
58
65
  }
@@ -79,8 +86,24 @@ function generateRPCs(
79
86
  const output = functionMeta.outputs ? functionMeta.outputs[0] : undefined
80
87
 
81
88
  // Store the input and output types for RPCHandler
82
- const inputType = input ? typesMap.getTypeMeta(input).uniqueName : 'null'
83
- const outputType = output ? typesMap.getTypeMeta(output).uniqueName : 'null'
89
+ // Use 'any' for types not in typesMap (e.g., inline types in generated workflow workers)
90
+ let inputType = 'null'
91
+ if (input) {
92
+ try {
93
+ inputType = typesMap.getTypeMeta(input).uniqueName
94
+ } catch {
95
+ inputType = 'any'
96
+ }
97
+ }
98
+
99
+ let outputType = 'null'
100
+ if (output) {
101
+ try {
102
+ outputType = typesMap.getTypeMeta(output).uniqueName
103
+ } catch {
104
+ outputType = 'any'
105
+ }
106
+ }
84
107
 
85
108
  requiredTypes.add(inputType)
86
109
  requiredTypes.add(outputType)
@@ -0,0 +1,24 @@
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
+
5
+ export const pikkuWorkflowMap: any = pikkuSessionlessFunc<void, void>({
6
+ func: async ({ logger, config, getInspectorState }) => {
7
+ const visitState = await getInspectorState()
8
+ const { workflowMapDeclarationFile, packageMappings } = config
9
+ const { workflows, functions: functionState } = visitState
10
+ const { typesMap } = functionState
11
+
12
+ await writeFileInDir(
13
+ logger,
14
+ workflowMapDeclarationFile,
15
+ serializeWorkflowMap(
16
+ workflowMapDeclarationFile,
17
+ packageMappings,
18
+ typesMap,
19
+ functionState.meta,
20
+ workflows.meta
21
+ )
22
+ )
23
+ },
24
+ })
@@ -0,0 +1,22 @@
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
+
6
+ export const pikkuWorkflowTypes: any = pikkuSessionlessFunc<void, void>({
7
+ func: async ({ logger, config }) => {
8
+ const { workflowTypesFile, functionTypesFile, packageMappings } = config
9
+
10
+ const functionTypesImportPath = getFileImportRelativePath(
11
+ workflowTypesFile,
12
+ functionTypesFile,
13
+ packageMappings
14
+ )
15
+
16
+ await writeFileInDir(
17
+ logger,
18
+ workflowTypesFile,
19
+ serializeWorkflowTypes(functionTypesImportPath)
20
+ )
21
+ },
22
+ })
@@ -0,0 +1,123 @@
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
+
13
+ export const pikkuWorkflow: any = pikkuSessionlessFunc<
14
+ void,
15
+ boolean | undefined
16
+ >({
17
+ func: async ({ logger, config, getInspectorState }) => {
18
+ const visitState = await getInspectorState()
19
+ const {
20
+ workflowsWiringFile,
21
+ workflowsWiringMetaFile,
22
+ workflowMapDeclarationFile,
23
+ workflowTypesFile,
24
+ functionTypesFile,
25
+ typesDeclarationFile,
26
+ packageMappings,
27
+ } = config
28
+ const { workflows, functions: functionState } = visitState
29
+ const { typesMap } = functionState
30
+
31
+ // Validate that workflowService service is configured if workflows are defined
32
+ const hasWorkflows = Object.keys(workflows.meta).length > 0
33
+ if (hasWorkflows) {
34
+ const hasWorkflowState =
35
+ visitState.serviceAggregation.allSingletonServices.includes(
36
+ 'workflowService'
37
+ )
38
+ if (!hasWorkflowState) {
39
+ logger.critical(
40
+ ErrorCode.WORKFLOW_ORCHESTRATOR_NOT_CONFIGURED,
41
+ 'Workflows detected but workflowService service not configured. Please add workflowService to your singleton services'
42
+ )
43
+ throw new Error(
44
+ 'WorkflowState service not configured but workflows are defined'
45
+ )
46
+ }
47
+ }
48
+
49
+ // Write workflow metadata
50
+ await writeFileInDir(
51
+ logger,
52
+ workflowsWiringMetaFile,
53
+ serializeWorkflowMeta(workflows.meta)
54
+ )
55
+
56
+ // Write workflow wirings (imports)
57
+ await writeFileInDir(
58
+ logger,
59
+ workflowsWiringFile,
60
+ serializeFileImports(
61
+ 'wireWorkflow',
62
+ workflowsWiringFile,
63
+ workflows.files,
64
+ packageMappings
65
+ )
66
+ )
67
+
68
+ // Write workflow types
69
+ const functionTypesImportPath = getFileImportRelativePath(
70
+ workflowTypesFile,
71
+ functionTypesFile,
72
+ packageMappings
73
+ )
74
+ await writeFileInDir(
75
+ logger,
76
+ workflowTypesFile,
77
+ serializeWorkflowTypes(functionTypesImportPath)
78
+ )
79
+
80
+ // Write workflow map (type-safe client API)
81
+ await writeFileInDir(
82
+ logger,
83
+ workflowMapDeclarationFile,
84
+ serializeWorkflowMap(
85
+ workflowMapDeclarationFile,
86
+ packageMappings,
87
+ typesMap,
88
+ functionState.meta,
89
+ workflows.meta
90
+ )
91
+ )
92
+
93
+ if (config.workflows) {
94
+ if (config.workflows.singleQueue) {
95
+ const workflowPath = join(config.rootDir, config.workflows.path)
96
+ const pathToPikkuTypes = getFileImportRelativePath(
97
+ workflowPath,
98
+ typesDeclarationFile,
99
+ packageMappings
100
+ )
101
+ await writeFileInDir(
102
+ logger,
103
+ workflowPath,
104
+ serializeWorkflowWorkers(pathToPikkuTypes)
105
+ )
106
+ } else if (workflows.files.size > 0) {
107
+ logger.critical(
108
+ ErrorCode.WORKFLOW_MULTI_QUEUE_NOT_SUPPORTED,
109
+ 'Multi-queue workflows are not supported when workflows.singleQueue is false. Please enable singleQueue in your configuration.'
110
+ )
111
+ return false
112
+ }
113
+ }
114
+
115
+ return true
116
+ },
117
+ middleware: [
118
+ logCommandInfoAndTime({
119
+ commandStart: 'Finding Workflows',
120
+ commandEnd: 'Found Workflows',
121
+ }),
122
+ ],
123
+ })
@@ -0,0 +1,123 @@
1
+ import type { WorkflowsMeta } from '@pikku/core/workflow'
2
+ import { serializeImportMap } from '../../../utils/serialize-import-map.js'
3
+ import { TypesMap } from '@pikku/inspector'
4
+ import { FunctionsMeta } from '@pikku/core'
5
+ import { generateCustomTypes } from '../../../utils/custom-types-generator.js'
6
+
7
+ export const serializeWorkflowMap = (
8
+ relativeToPath: string,
9
+ packageMappings: Record<string, string>,
10
+ typesMap: TypesMap,
11
+ functionsMeta: FunctionsMeta,
12
+ workflowsMeta: WorkflowsMeta
13
+ ) => {
14
+ const requiredTypes = new Set<string>()
15
+ const serializedCustomTypes = generateCustomTypes(typesMap, requiredTypes)
16
+ const serializedWorkflows = generateWorkflows(
17
+ workflowsMeta,
18
+ functionsMeta,
19
+ typesMap,
20
+ requiredTypes
21
+ )
22
+
23
+ const serializedImportMap = serializeImportMap(
24
+ relativeToPath,
25
+ packageMappings,
26
+ typesMap,
27
+ requiredTypes
28
+ )
29
+
30
+ return `/**
31
+ * This provides the structure needed for TypeScript to be aware of workflows and their input/output types
32
+ */
33
+
34
+ ${serializedImportMap}
35
+ ${serializedCustomTypes}
36
+
37
+ interface WorkflowHandler<I, O> {
38
+ input: I;
39
+ output: O;
40
+ }
41
+
42
+ ${serializedWorkflows}
43
+
44
+ /**
45
+ * Type-safe workflow client API
46
+ */
47
+ export type WorkflowClient<Name extends keyof WorkflowMap> = {
48
+ /**
49
+ * Start a new workflow run
50
+ */
51
+ start: (input: WorkflowMap[Name]['input']) => Promise<{ runId: string }>;
52
+
53
+ /**
54
+ * Get a workflow run by ID
55
+ */
56
+ getRun: <output extends keyof WorkflowMap[Name]>(runId: string) => Promise<WorkflowMap[Name][output]>;
57
+
58
+ /**
59
+ * Cancel a running workflow
60
+ */
61
+ cancelRun: (runId: string) => Promise<boolean>;
62
+ }
63
+
64
+ /**
65
+ * Map of all registered workflows with type-safe client APIs
66
+ */
67
+ export type TypedWorkflowClients = {
68
+ [Name in keyof WorkflowMap]: WorkflowClient<Name>;
69
+ }
70
+ `
71
+ }
72
+
73
+ function generateWorkflows(
74
+ workflowsMeta: WorkflowsMeta,
75
+ functionsMeta: FunctionsMeta,
76
+ typesMap: TypesMap,
77
+ requiredTypes: Set<string>
78
+ ) {
79
+ // Initialize an object to collect workflows
80
+ const workflowsObj: Record<
81
+ string,
82
+ { inputType: string; outputType: string }
83
+ > = {}
84
+
85
+ // Iterate through workflow metadata
86
+ for (const [workflowName, { pikkuFuncName }] of Object.entries(
87
+ workflowsMeta
88
+ )) {
89
+ const functionMeta = functionsMeta[pikkuFuncName]
90
+ if (!functionMeta) {
91
+ throw new Error(
92
+ `Function ${workflowName} not found in functionsMeta. Please check your configuration.`
93
+ )
94
+ }
95
+
96
+ const input = functionMeta.inputs ? functionMeta.inputs[0] : undefined
97
+ const output = functionMeta.outputs ? functionMeta.outputs[0] : undefined
98
+
99
+ // Store the input and output types for WorkflowHandler
100
+ const inputType = input ? typesMap.getTypeMeta(input).uniqueName : 'void'
101
+ const outputType = output ? typesMap.getTypeMeta(output).uniqueName : 'void'
102
+
103
+ requiredTypes.add(inputType)
104
+ requiredTypes.add(outputType)
105
+
106
+ // Add workflow entry
107
+ workflowsObj[workflowName] = {
108
+ inputType,
109
+ outputType,
110
+ }
111
+ }
112
+
113
+ // Build the Workflows object as a string
114
+ let workflowsStr = 'export type WorkflowMap = {\n'
115
+
116
+ for (const [workflowName, handler] of Object.entries(workflowsObj)) {
117
+ workflowsStr += ` readonly '${workflowName}': WorkflowHandler<${handler.inputType}, ${handler.outputType}>,\n`
118
+ }
119
+
120
+ workflowsStr += '};\n'
121
+
122
+ return workflowsStr
123
+ }
@@ -0,0 +1,16 @@
1
+ import { WorkflowsMeta } from '@pikku/core/workflow'
2
+
3
+ export const serializeWorkflowMeta = (workflowsMeta: WorkflowsMeta) => {
4
+ const serializedOutput: string[] = []
5
+ serializedOutput.push("import { pikkuState } from '@pikku/core'")
6
+ serializedOutput.push(
7
+ `pikkuState('workflows', 'meta', ${JSON.stringify(workflowsMeta, null, 2)})`
8
+ )
9
+ const workflowsMetaValues = Object.values(workflowsMeta)
10
+ if (workflowsMetaValues.length > 0) {
11
+ serializedOutput.push(
12
+ `export type WorkflowNames = '${workflowsMetaValues.map((w) => w.workflowName).join("' | '")}'`
13
+ )
14
+ }
15
+ return serializedOutput.join('\n')
16
+ }
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Generates type definitions for workflow wirings
3
+ */
4
+ export const serializeWorkflowTypes = (functionTypesImportPath: string) => {
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,60 @@
1
+ /**
2
+ * Generate queue workers and RPC functions for workflow steps and orchestrator
3
+ */
4
+ export const serializeWorkflowWorkers = (pathToPikkuTypes: string) => {
5
+ return `/**
6
+ * Auto-generated workflow queue workers and RPC functions
7
+ * Do not edit manually - regenerate with 'npx pikku'
8
+ */
9
+ import { pikkuSessionlessFunc, wireQueueWorker } from '${pathToPikkuTypes}'
10
+
11
+ /**
12
+ * Worker input types for generated queue workers
13
+ */
14
+ export type WorkflowStepInput = {
15
+ runId: string
16
+ stepName: string
17
+ rpcName: string
18
+ data: any
19
+ }
20
+
21
+ export const pikkuWorkflowWorker = pikkuSessionlessFunc<
22
+ WorkflowStepInput,
23
+ void
24
+ >({
25
+ func: async ({ workflowService, rpc }, { runId, stepName, rpcName, data }) => {
26
+ await workflowService!.executeWorkflowStep(runId, stepName, rpcName, data, rpc)
27
+ }
28
+ })
29
+
30
+ export const pikkuWorkflowOrchestrator = pikkuSessionlessFunc<
31
+ { runId: string },
32
+ void
33
+ >({
34
+ func: async ({ workflowService, rpc }, { runId }) => {
35
+ await workflowService!.orchestrateWorkflow(runId, rpc)
36
+ }
37
+ })
38
+
39
+ export const pikkuWorkflowSleeper = pikkuSessionlessFunc<
40
+ { runId: string, stepId: string },
41
+ void
42
+ >({
43
+ func: async ({ workflowService }, { runId, stepId }) => {
44
+ await workflowService!.executeWorkflowSleep(runId, stepId)
45
+ },
46
+ name: 'pikkuWorkflowStepSleeper',
47
+ internal: true,
48
+ })
49
+
50
+ wireQueueWorker({
51
+ queueName: 'pikku-workflow-step-worker',
52
+ func: pikkuWorkflowWorker,
53
+ })
54
+
55
+ wireQueueWorker({
56
+ queueName: 'pikku-workflow-orchestrator',
57
+ func: pikkuWorkflowOrchestrator,
58
+ })
59
+ `
60
+ }
@@ -78,7 +78,7 @@ export class CLILoggerForwarder implements Logger {
78
78
  }
79
79
 
80
80
  critical(code: ErrorCode, message: string) {
81
- const url = `https://pikku.dev/docs/cli-errors/${code.toLowerCase()}`
81
+ const url = `https://pikku.dev/docs/pikku-cli/errors/${code.toLowerCase()}`
82
82
  const formattedMessage = `[${code}] ${message}\n → ${url}`
83
83
  this.error(formattedMessage)
84
84
  }
@@ -11,7 +11,7 @@ const logo = `
11
11
  |_| |_|_| _)_| _)____/
12
12
  `
13
13
 
14
- const BASE_ERROR_URL = 'https://pikku.dev/errors'
14
+ const BASE_ERROR_URL = 'https://pikku.dev/docs/pikku-cli/errors'
15
15
 
16
16
  export class CLILogger implements Logger {
17
17
  private silent: boolean
@@ -8,6 +8,7 @@ export interface CommandSummaryStats {
8
8
  queueWorkers?: number
9
9
  mcpEndpoints?: number
10
10
  cliCommands?: number
11
+ workflows?: number
11
12
  [key: string]: number | undefined
12
13
  }
13
14
 
@@ -66,19 +67,20 @@ export class CommandSummary {
66
67
 
67
68
  // Stats
68
69
  const statLabels: Record<keyof CommandSummaryStats, string> = {
69
- httpRoutes: 'HTTP routes',
70
- channels: 'WebSocket channels',
71
- functions: 'functions',
72
- scheduledTasks: 'scheduled tasks',
73
- queueWorkers: 'queue workers',
74
- mcpEndpoints: 'MCP endpoints',
75
- cliCommands: 'CLI commands',
70
+ httpRoutes: 'HTTP route',
71
+ channels: 'WebSocket channel',
72
+ functions: 'Function',
73
+ scheduledTasks: 'Scheduled task',
74
+ queueWorkers: 'Queue worker',
75
+ mcpEndpoints: 'MCP endpoint',
76
+ cliCommands: 'CLI command',
77
+ workflows: 'Workflow',
76
78
  }
77
79
 
78
80
  for (const [key, label] of Object.entries(statLabels)) {
79
81
  const value = this.stats[key]
80
82
  if (value !== undefined && value > 0) {
81
- lines.push(chalk.gray(` • ${value} ${label}`))
83
+ lines.push(chalk.gray(` • ${value} ${label}${value > 1 ? 's' : ''}`))
82
84
  }
83
85
  }
84
86
 
@@ -66,11 +66,9 @@ const _getPikkuCLIConfig = async (
66
66
  },
67
67
  ignoreFiles: config.ignoreFiles ??
68
68
  extendedConfig.ignoreFiles ?? [
69
- '**/*.gen.ts',
70
69
  '**/*.test.ts',
71
70
  '**/*.spec.ts',
72
71
  '**/node_modules/**',
73
- '**/.pikku/**',
74
72
  '**/dist/**',
75
73
  ],
76
74
  schema: {
@@ -89,11 +87,9 @@ const _getPikkuCLIConfig = async (
89
87
  ? resolve(configDir, config.rootDir)
90
88
  : configDir,
91
89
  ignoreFiles: config.ignoreFiles ?? [
92
- '**/*.gen.ts',
93
90
  '**/*.test.ts',
94
91
  '**/*.spec.ts',
95
92
  '**/node_modules/**',
96
- '**/.pikku/**',
97
93
  '**/dist/**',
98
94
  ],
99
95
  schema: {
@@ -111,6 +107,7 @@ const _getPikkuCLIConfig = async (
111
107
  const rpcDir = join(result.outDir, 'rpc')
112
108
  const schedulerDir = join(result.outDir, 'scheduler')
113
109
  const queueDir = join(result.outDir, 'queue')
110
+ const workflowDir = join(result.outDir, 'workflow')
114
111
  const mcpDir = join(result.outDir, 'mcp')
115
112
  const cliDir = join(result.outDir, 'cli')
116
113
  const middlewareDir = join(result.outDir, 'middleware')
@@ -209,6 +206,17 @@ const _getPikkuCLIConfig = async (
209
206
  )
210
207
  }
211
208
 
209
+ // RPC config defaults
210
+ if (!result.rpc) {
211
+ result.rpc = {}
212
+ }
213
+ if (!result.rpc.remoteRpcWorkersPath) {
214
+ result.rpc.remoteRpcWorkersPath = join(
215
+ rpcDir,
216
+ 'pikku-remote-rpc-workers.gen.ts'
217
+ )
218
+ }
219
+
212
220
  // Scheduler
213
221
  if (!result.schedulersWiringFile) {
214
222
  result.schedulersWiringFile = join(
@@ -252,6 +260,38 @@ const _getPikkuCLIConfig = async (
252
260
  result.queueTypesFile = join(queueDir, 'pikku-queue-types.gen.ts')
253
261
  }
254
262
 
263
+ // Workflows
264
+ if (!result.workflowsWiringFile) {
265
+ result.workflowsWiringFile = join(
266
+ workflowDir,
267
+ 'pikku-workflow-wirings.gen.ts'
268
+ )
269
+ }
270
+ if (!result.workflowsWiringMetaFile) {
271
+ result.workflowsWiringMetaFile = join(
272
+ workflowDir,
273
+ 'pikku-workflow-wirings-meta.gen.ts'
274
+ )
275
+ }
276
+ if (!result.workflowsWorkersFile) {
277
+ result.workflowsWorkersFile = join(
278
+ workflowDir,
279
+ 'pikku-workflow-workers.gen.ts'
280
+ )
281
+ }
282
+ if (!result.workflowMapDeclarationFile) {
283
+ result.workflowMapDeclarationFile = join(
284
+ workflowDir,
285
+ 'pikku-workflow-map.gen.d.ts'
286
+ )
287
+ }
288
+ if (!result.workflowTypesFile) {
289
+ result.workflowTypesFile = join(
290
+ workflowDir,
291
+ 'pikku-workflow-types.gen.ts'
292
+ )
293
+ }
294
+
255
295
  // Services
256
296
  if (!result.servicesFile) {
257
297
  result.servicesFile = join(result.outDir, 'pikku-services.gen.ts')