@pikku/cli 0.12.16 → 0.12.19

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 (127) hide show
  1. package/cli.schema.json +1 -1
  2. package/console-app/assets/{index-DvrDbftC.css → index-BpY2pSuA.css} +10 -1
  3. package/console-app/assets/index-DAQHIRK3.js +717 -0
  4. package/console-app/index.html +2 -2
  5. package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +1 -1
  6. package/dist/.pikku/channel/pikku-channel-types.gen.d.ts +1 -1
  7. package/dist/.pikku/channel/pikku-channel-types.gen.js +1 -1
  8. package/dist/.pikku/cli/pikku-cli-channel.js +6 -1
  9. package/dist/.pikku/cli/pikku-cli-client.gen.d.ts +1 -1
  10. package/dist/.pikku/cli/pikku-cli-client.gen.js +1 -1
  11. package/dist/.pikku/cli/pikku-cli-types.gen.d.ts +1 -1
  12. package/dist/.pikku/cli/pikku-cli-types.gen.js +1 -1
  13. package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.js +1 -1
  14. package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.json +7 -1
  15. package/dist/.pikku/cli/pikku-cli-wirings.gen.d.ts +1 -1
  16. package/dist/.pikku/cli/pikku-cli-wirings.gen.js +1 -1
  17. package/dist/.pikku/cli/pikku-cli.gen.d.ts +1 -1
  18. package/dist/.pikku/cli/pikku-cli.gen.js +1 -1
  19. package/dist/.pikku/console/pikku-node-types.gen.d.ts +1 -1
  20. package/dist/.pikku/function/pikku-function-types.gen.d.ts +1 -1
  21. package/dist/.pikku/function/pikku-function-types.gen.js +1 -1
  22. package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
  23. package/dist/.pikku/function/pikku-functions-meta.gen.json +204 -67
  24. package/dist/.pikku/function/pikku-functions.gen.js +1 -1
  25. package/dist/.pikku/http/pikku-http-types.gen.d.ts +1 -1
  26. package/dist/.pikku/http/pikku-http-types.gen.js +1 -1
  27. package/dist/.pikku/http/pikku-http-wirings-meta.gen.js +1 -1
  28. package/dist/.pikku/http/pikku-http-wirings-meta.gen.json +62 -1
  29. package/dist/.pikku/http/pikku-http-wirings.gen.d.ts +2 -1
  30. package/dist/.pikku/http/pikku-http-wirings.gen.js +2 -1
  31. package/dist/.pikku/mcp/pikku-mcp-types.gen.d.ts +1 -1
  32. package/dist/.pikku/mcp/pikku-mcp-types.gen.js +1 -1
  33. package/dist/.pikku/pikku-bootstrap.gen.d.ts +2 -1
  34. package/dist/.pikku/pikku-bootstrap.gen.js +2 -1
  35. package/dist/.pikku/pikku-meta-service.gen.d.ts +1 -1
  36. package/dist/.pikku/pikku-meta-service.gen.js +1 -1
  37. package/dist/.pikku/pikku-services.gen.d.ts +6 -6
  38. package/dist/.pikku/pikku-services.gen.js +4 -4
  39. package/dist/.pikku/pikku-types.gen.d.ts +1 -1
  40. package/dist/.pikku/pikku-types.gen.js +1 -1
  41. package/dist/.pikku/queue/pikku-queue-types.gen.d.ts +1 -1
  42. package/dist/.pikku/queue/pikku-queue-types.gen.js +1 -1
  43. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.js +1 -1
  44. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.json +15 -8
  45. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.d.ts +1 -1
  46. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.js +1 -1
  47. package/dist/.pikku/schemas/register.gen.js +21 -3
  48. package/dist/.pikku/schemas/schemas/GraphStarterInput.schema.json +1 -0
  49. package/dist/.pikku/schemas/schemas/GraphStarterOutput.schema.json +1 -0
  50. package/dist/.pikku/schemas/schemas/PikkuCLIConfig.schema.json +1 -1
  51. package/dist/.pikku/schemas/schemas/WorkflowRunStatus.schema.json +1 -0
  52. package/dist/.pikku/schemas/schemas/WorkflowRunnerInput.schema.json +1 -0
  53. package/dist/.pikku/schemas/schemas/WorkflowStarterInput.schema.json +1 -0
  54. package/dist/.pikku/schemas/schemas/WorkflowStarterOutput.schema.json +1 -0
  55. package/dist/.pikku/schemas/schemas/WorkflowStatusCheckerInput.schema.json +1 -0
  56. package/dist/.pikku/schemas/schemas/WorkflowStatusStreamFullInput.schema.json +1 -0
  57. package/dist/.pikku/schemas/schemas/WorkflowStatusStreamInput.schema.json +1 -0
  58. package/dist/.pikku/secrets/pikku-secret-types.gen.d.ts +1 -1
  59. package/dist/.pikku/secrets/pikku-secret-types.gen.js +1 -1
  60. package/dist/.pikku/secrets/pikku-secrets.gen.d.ts +1 -1
  61. package/dist/.pikku/secrets/pikku-secrets.gen.js +1 -1
  62. package/dist/.pikku/trigger/pikku-trigger-types.gen.d.ts +1 -1
  63. package/dist/.pikku/trigger/pikku-trigger-types.gen.js +1 -1
  64. package/dist/.pikku/variables/pikku-variable-types.gen.d.ts +1 -1
  65. package/dist/.pikku/variables/pikku-variable-types.gen.js +1 -1
  66. package/dist/.pikku/variables/pikku-variables.gen.d.ts +1 -1
  67. package/dist/.pikku/variables/pikku-variables.gen.js +1 -1
  68. package/dist/.pikku/workflow/meta/allWorkflow.gen.json +442 -0
  69. package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +1 -1
  70. package/dist/.pikku/workflow/pikku-workflow-types.gen.js +1 -1
  71. package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +5 -2
  72. package/dist/.pikku/workflow/pikku-workflow-wirings.gen.d.ts +2 -4
  73. package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +5 -2
  74. package/dist/src/cli.wiring.js +5 -0
  75. package/dist/src/deploy/analyzer/analyzer.d.ts +1 -0
  76. package/dist/src/deploy/analyzer/analyzer.js +18 -15
  77. package/dist/src/deploy/codegen/per-unit-codegen.js +3 -3
  78. package/dist/src/functions/commands/all.js +2 -186
  79. package/dist/src/functions/commands/bootstrap.js +10 -10
  80. package/dist/src/functions/commands/console.js +1 -1
  81. package/dist/src/functions/commands/watch.js +1 -1
  82. package/dist/src/functions/wirings/rpc/pikku-command-react-query.d.ts +1 -0
  83. package/dist/src/functions/wirings/rpc/pikku-command-react-query.js +33 -0
  84. package/dist/src/functions/wirings/rpc/serialize-react-query-hooks.d.ts +1 -0
  85. package/dist/src/functions/wirings/rpc/serialize-react-query-hooks.js +108 -0
  86. package/dist/src/functions/wirings/rpc/serialize-rpc-wrapper.js +3 -3
  87. package/dist/src/functions/wirings/rpc/serialize-typed-rpc-map.js +6 -4
  88. package/dist/src/functions/wirings/workflow/serialize-workflow-routes.js +126 -27
  89. package/dist/src/functions/workflows/all.workflow.d.ts +1 -0
  90. package/dist/src/functions/workflows/all.workflow.js +212 -0
  91. package/dist/src/scaffold/rpc-remote.gen.js +1 -1
  92. package/dist/src/scaffold/workflow-routes.gen.d.ts +84 -0
  93. package/dist/src/scaffold/workflow-routes.gen.js +197 -0
  94. package/dist/src/services.js +2 -0
  95. package/dist/src/utils/pikku-cli-config.js +1 -0
  96. package/dist/tsconfig.tsbuildinfo +1 -1
  97. package/package.json +4 -6
  98. package/console-app/assets/index-CzMWJFqj.js +0 -700
  99. package/dist/.pikku/agent/pikku-agent-wirings-meta.gen.d.ts +0 -1
  100. package/dist/.pikku/agent/pikku-agent-wirings-meta.gen.js +0 -6
  101. package/dist/.pikku/agent/pikku-agent-wirings-meta.gen.json +0 -3
  102. package/dist/.pikku/agent/pikku-agent-wirings.gen.d.ts +0 -4
  103. package/dist/.pikku/agent/pikku-agent-wirings.gen.js +0 -4
  104. package/dist/.pikku/channel/pikku-channels-meta.gen.d.ts +0 -1
  105. package/dist/.pikku/channel/pikku-channels-meta.gen.js +0 -6
  106. package/dist/.pikku/channel/pikku-channels-meta.gen.json +0 -1
  107. package/dist/.pikku/channel/pikku-channels.gen.d.ts +0 -4
  108. package/dist/.pikku/channel/pikku-channels.gen.js +0 -5
  109. package/dist/.pikku/mcp/pikku-mcp-wirings-meta.gen.d.ts +0 -1
  110. package/dist/.pikku/mcp/pikku-mcp-wirings-meta.gen.js +0 -8
  111. package/dist/.pikku/mcp/pikku-mcp-wirings-meta.gen.json +0 -5
  112. package/dist/.pikku/mcp/pikku-mcp-wirings.gen.d.ts +0 -4
  113. package/dist/.pikku/mcp/pikku-mcp-wirings.gen.js +0 -5
  114. package/dist/.pikku/pikku-websocket.gen.d.ts +0 -45
  115. package/dist/.pikku/pikku-websocket.gen.js +0 -63
  116. package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.d.ts +0 -1
  117. package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.js +0 -6
  118. package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.json +0 -1
  119. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.d.ts +0 -4
  120. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.js +0 -5
  121. package/dist/.pikku/rpc/pikku-remote-rpc-workers.gen.d.ts +0 -17
  122. package/dist/.pikku/rpc/pikku-remote-rpc-workers.gen.js +0 -25
  123. package/dist/.pikku/scheduler/pikku-schedulers-wirings-meta.gen.d.ts +0 -1
  124. package/dist/.pikku/scheduler/pikku-schedulers-wirings-meta.gen.js +0 -6
  125. package/dist/.pikku/scheduler/pikku-schedulers-wirings-meta.gen.json +0 -1
  126. package/dist/.pikku/scheduler/pikku-schedulers-wirings.gen.d.ts +0 -4
  127. package/dist/.pikku/scheduler/pikku-schedulers-wirings.gen.js +0 -5
@@ -1,191 +1,7 @@
1
- import { existsSync } from 'fs';
2
1
  import { pikkuVoidFunc } from '#pikku';
3
- const scaffoldFiles = (config) => {
4
- const files = [];
5
- if (config.scaffold?.rpc && config.publicRpcFile)
6
- files.push({ file: config.publicRpcFile, generator: 'pikkuPublicRPC' });
7
- if (config.scaffold?.console && config.consoleFunctionsFile)
8
- files.push({
9
- file: config.consoleFunctionsFile,
10
- generator: 'pikkuConsoleFunctions',
11
- });
12
- if (config.scaffold?.agent && config.publicAgentFile)
13
- files.push({
14
- file: config.publicAgentFile,
15
- generator: 'pikkuPublicAgent',
16
- });
17
- return files;
18
- };
19
2
  export const all = pikkuVoidFunc({
20
3
  remote: true,
21
- func: async ({ logger, config, getInspectorState }, _data, { rpc }) => {
22
- const allImports = [];
23
- let typesDeclarationFileExists = true;
24
- if (!existsSync(config.outDir)) {
25
- logger.debug(`• .pikku directory not found, running bootstrap first...`);
26
- await getInspectorState(false, false, true);
27
- await rpc.invoke('pikkuFunctionTypes', null);
28
- await rpc.invoke('pikkuFunctionTypesSplit', null);
29
- await rpc.invoke('pikkuHTTPTypes', null);
30
- await rpc.invoke('pikkuChannelTypes', null);
31
- await rpc.invoke('pikkuSchedulerTypes', null);
32
- await rpc.invoke('pikkuQueueTypes', null);
33
- await rpc.invoke('pikkuWorkflow', null);
34
- await rpc.invoke('pikkuMCPTypes', null);
35
- await rpc.invoke('pikkuAIAgentTypes', null);
36
- await rpc.invoke('pikkuCLITypes', null);
37
- await getInspectorState(true);
38
- }
39
- if (!existsSync(config.typesDeclarationFile)) {
40
- typesDeclarationFileExists = false;
41
- }
42
- const missingScaffolds = scaffoldFiles(config).filter((s) => !existsSync(s.file));
43
- if (missingScaffolds.length > 0) {
44
- for (const { generator } of missingScaffolds) {
45
- await rpc.invoke(generator, null);
46
- }
47
- }
48
- await rpc.invoke('pikkuFunctionTypes', null);
49
- if (!typesDeclarationFileExists || missingScaffolds.length > 0) {
50
- logger.debug(`• Type file or scaffolds first created, inspecting again...`);
51
- await getInspectorState(true);
52
- }
53
- await rpc.invoke('pikkuFunctionTypesSplit', null);
54
- await rpc.invoke('pikkuTriggerTypes', null);
55
- await rpc.invoke('pikkuAIAgentTypes', null);
56
- if (!config.addon) {
57
- await rpc.invoke('pikkuHTTPTypes', null);
58
- await rpc.invoke('pikkuChannelTypes', null);
59
- await rpc.invoke('pikkuSchedulerTypes', null);
60
- await rpc.invoke('pikkuQueueTypes', null);
61
- await rpc.invoke('pikkuMCPTypes', null);
62
- await rpc.invoke('pikkuCLITypes', null);
63
- }
64
- const middleware = await rpc.invoke('pikkuMiddleware', null);
65
- if (middleware) {
66
- allImports.push(config.middlewareFile);
67
- }
68
- const permissions = await rpc.invoke('pikkuPermissions', null);
69
- if (permissions) {
70
- allImports.push(config.permissionsFile);
71
- }
72
- await rpc.invoke('pikkuServices', null);
73
- const hasPackageFactories = await rpc.invoke('pikkuPackage', null);
74
- if (hasPackageFactories) {
75
- allImports.push(config.packageFile);
76
- }
77
- const hasInternalRPCs = await rpc.invoke('pikkuRPC', null);
78
- const agents = await rpc.invoke('pikkuAIAgent', null);
79
- if (agents) {
80
- allImports.push(config.agentWiringMetaFile, config.agentWiringsFile);
81
- if (config.scaffold?.agent) {
82
- await rpc.invoke('pikkuPublicAgent', null);
83
- }
84
- }
85
- await rpc.invoke('pikkuPublicRPC', null);
86
- await rpc.invoke('pikkuConsoleFunctions', null);
87
- await rpc.invoke('pikkuNodeTypes', null);
88
- await rpc.invoke('pikkuSecretDefinitionTypes', null);
89
- await rpc.invoke('pikkuSecrets', null);
90
- await rpc.invoke('pikkuCredentials', null);
91
- await rpc.invoke('pikkuVariableDefinitionTypes', null);
92
- await rpc.invoke('pikkuVariables', null);
93
- await rpc.invoke('pikkuAddonTypes', null);
94
- if (hasInternalRPCs) {
95
- allImports.push(config.rpcInternalWiringMetaFile);
96
- }
97
- if (agents || !config.addon) {
98
- await getInspectorState(true);
99
- }
100
- const schemas = await rpc.invoke('pikkuSchemas', null);
101
- if (schemas) {
102
- allImports.push(`${config.schemaDirectory}/register.gen.ts`);
103
- }
104
- await rpc.invoke('pikkuRPCInternalMap', null);
105
- await rpc.invoke('pikkuRPCExposedMap', null);
106
- const workflows = await rpc.invoke('pikkuWorkflow', null);
107
- let remoteRPC = false;
108
- let workflowRoutes = false;
109
- if (!config.addon) {
110
- remoteRPC = await rpc.invoke('pikkuRemoteRPC', null);
111
- if (workflows) {
112
- workflowRoutes = await rpc.invoke('pikkuWorkflowRoutes', null);
113
- }
114
- }
115
- if (workflows || remoteRPC || workflowRoutes) {
116
- await getInspectorState(true);
117
- await rpc.invoke('pikkuSchemas', null);
118
- }
119
- if (!config.addon) {
120
- const http = await rpc.invoke('pikkuHTTP', null);
121
- if (http) {
122
- await rpc.invoke('pikkuHTTPMap', null);
123
- await rpc.invoke('pikkuFetch', null);
124
- await rpc.invoke('pikkuRPCClient', null);
125
- allImports.push(config.httpWiringMetaFile, config.httpWiringsFile);
126
- }
127
- const scheduler = await rpc.invoke('pikkuScheduler', null);
128
- if (scheduler) {
129
- allImports.push(config.schedulersWiringMetaFile, config.schedulersWiringFile);
130
- }
131
- const triggers = await rpc.invoke('pikkuTrigger', null);
132
- if (triggers) {
133
- allImports.push(config.triggersWiringMetaFile, config.triggerSourcesMetaFile, config.triggersWiringFile);
134
- }
135
- }
136
- const hasFunctionRegistrations = await rpc.invoke('pikkuFunctions', null);
137
- allImports.push(config.functionsMetaFile);
138
- if (hasFunctionRegistrations) {
139
- allImports.push(config.functionsFile);
140
- }
141
- if (workflows) {
142
- allImports.push(config.workflowsWiringFile);
143
- }
144
- if (!config.addon) {
145
- const queues = await rpc.invoke('pikkuQueue', null);
146
- if (queues) {
147
- await rpc.invoke('pikkuQueueMap', null);
148
- await rpc.invoke('pikkuQueueService', null);
149
- allImports.push(config.queueWorkersWiringMetaFile, config.queueWorkersWiringFile);
150
- }
151
- const channels = await rpc.invoke('pikkuChannels', null);
152
- if (channels) {
153
- await rpc.invoke('pikkuChannelsMap', null);
154
- await rpc.invoke('pikkuWebSocketTyped', null);
155
- allImports.push(config.channelsWiringMetaFile, config.channelsWiringFile);
156
- }
157
- const gateways = await rpc.invoke('pikkuGateway', null);
158
- if (gateways) {
159
- allImports.push(config.gatewaysWiringFile);
160
- }
161
- const mcp = await rpc.invoke('pikkuMCP', null);
162
- if (mcp) {
163
- await rpc.invoke('pikkuMCPJSON', null);
164
- allImports.push(config.mcpWiringsMetaFile, config.mcpWiringsFile);
165
- }
166
- const cli = await rpc.invoke('pikkuCLI', null);
167
- if (cli) {
168
- await rpc.invoke('pikkuCLIEntry', null);
169
- allImports.push(config.cliWiringMetaFile, config.cliWiringsFile);
170
- }
171
- }
172
- await rpc.invoke('pikkuNodesMeta', null);
173
- if (config.clientFiles?.nextBackendFile ||
174
- config.clientFiles?.nextHTTPFile) {
175
- await rpc.invoke('pikkuNext', null);
176
- }
177
- if (config.openAPI) {
178
- logger.debug(`• OpenAPI requires a reinspection to pickup new generated types..`);
179
- await getInspectorState(true);
180
- await rpc.invoke('pikkuOpenAPI', null);
181
- }
182
- try {
183
- await rpc.invoke('pikkuVersionsUpdate', null);
184
- }
185
- catch {
186
- logger.warn(`Run 'pikku versions init' to enable contract versioning.`);
187
- }
188
- await rpc.invoke('pikkuBootstrap', { allImports });
189
- await rpc.invoke('pikkuSummary', null);
4
+ func: async (services, _data, { rpc }) => {
5
+ await services.workflowService.runToCompletion('allWorkflow', {}, rpc);
190
6
  },
191
7
  });
@@ -3,16 +3,16 @@ export const bootstrap = pikkuVoidFunc({
3
3
  remote: true,
4
4
  func: async ({ logger, getInspectorState }, _data, { rpc }) => {
5
5
  await getInspectorState(false, false, true);
6
- await rpc.invoke('pikkuFunctionTypes', null);
7
- await rpc.invoke('pikkuFunctionTypesSplit', null);
8
- await rpc.invoke('pikkuHTTPTypes', null);
9
- await rpc.invoke('pikkuChannelTypes', null);
10
- await rpc.invoke('pikkuSchedulerTypes', null);
11
- await rpc.invoke('pikkuQueueTypes', null);
12
- await rpc.invoke('pikkuWorkflow', null);
13
- await rpc.invoke('pikkuMCPTypes', null);
14
- await rpc.invoke('pikkuAIAgentTypes', null);
15
- await rpc.invoke('pikkuCLITypes', null);
6
+ await rpc.invoke('pikkuFunctionTypes');
7
+ await rpc.invoke('pikkuFunctionTypesSplit');
8
+ await rpc.invoke('pikkuHTTPTypes');
9
+ await rpc.invoke('pikkuChannelTypes');
10
+ await rpc.invoke('pikkuSchedulerTypes');
11
+ await rpc.invoke('pikkuQueueTypes');
12
+ await rpc.invoke('pikkuWorkflow');
13
+ await rpc.invoke('pikkuMCPTypes');
14
+ await rpc.invoke('pikkuAIAgentTypes');
15
+ await rpc.invoke('pikkuCLITypes');
16
16
  if (logger.hasCriticalErrors()) {
17
17
  process.exit(1);
18
18
  }
@@ -88,7 +88,7 @@ export const consoleCommand = pikkuSessionlessFunc({
88
88
  const handle = async () => {
89
89
  try {
90
90
  const start = Date.now();
91
- await rpc.invoke('all', null);
91
+ await rpc.invoke('all');
92
92
  logger.info({
93
93
  message: `✓ Generated in ${Date.now() - start}ms`,
94
94
  type: 'timing',
@@ -26,7 +26,7 @@ export const watch = pikkuSessionlessFunc({
26
26
  const handle = async () => {
27
27
  try {
28
28
  const start = Date.now();
29
- await rpc.invoke('all', null);
29
+ await rpc.invoke('all');
30
30
  logger.info({
31
31
  message: `✓ Generated in ${Date.now() - start}ms`,
32
32
  type: 'timing',
@@ -0,0 +1 @@
1
+ export declare const pikkuReactQuery: import("#pikku").PikkuFunctionConfig<void, void, "session" | "rpc", import("#pikku").PikkuFunctionSessionless<void, void, "session" | "rpc", import("#pikku").Services> | import("#pikku").PikkuFunction<void, void, "session" | "rpc", import("#pikku").Services>, undefined, undefined>;
@@ -0,0 +1,33 @@
1
+ import { pikkuSessionlessFunc } from '#pikku';
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 { serializeReactQueryHooks } from './serialize-react-query-hooks.js';
6
+ export const pikkuReactQuery = pikkuSessionlessFunc({
7
+ func: async ({ logger, config, getInspectorState }) => {
8
+ const reactQueryFile = config.clientFiles?.reactQueryFile;
9
+ const { rpcMapDeclarationFile, workflowMapDeclarationFile, packageMappings, } = config;
10
+ if (!reactQueryFile) {
11
+ logger.debug({
12
+ message: "Skipping generating React Query hooks since reactQueryFile isn't set in the pikku config.",
13
+ type: 'skip',
14
+ });
15
+ return;
16
+ }
17
+ const { workflows } = await getInspectorState();
18
+ const hasWorkflows = Object.keys(workflows?.meta ?? {}).length > 0;
19
+ const rpcMapPath = getFileImportRelativePath(reactQueryFile, rpcMapDeclarationFile, packageMappings);
20
+ let workflowMapPath;
21
+ if (hasWorkflows) {
22
+ workflowMapPath = getFileImportRelativePath(reactQueryFile, workflowMapDeclarationFile, packageMappings);
23
+ }
24
+ const content = serializeReactQueryHooks(rpcMapPath, workflowMapPath);
25
+ await writeFileInDir(logger, reactQueryFile, content);
26
+ },
27
+ middleware: [
28
+ logCommandInfoAndTime({
29
+ commandStart: 'Generating React Query hooks',
30
+ commandEnd: 'Generated React Query hooks',
31
+ }),
32
+ ],
33
+ });
@@ -0,0 +1 @@
1
+ export declare const serializeReactQueryHooks: (rpcMapPath: string, workflowMapPath?: string) => string;
@@ -0,0 +1,108 @@
1
+ export const serializeReactQueryHooks = (rpcMapPath, workflowMapPath) => {
2
+ const workflowImport = workflowMapPath
3
+ ? `\nimport type { FlattenedWorkflowMap } from '${workflowMapPath}'`
4
+ : '';
5
+ const workflowHooks = workflowMapPath
6
+ ? `
7
+ export const useRunWorkflow = <Name extends keyof FlattenedWorkflowMap>(
8
+ name: Name,
9
+ options?: Omit<UseMutationOptions<FlattenedWorkflowMap[Name]['output'], Error, FlattenedWorkflowMap[Name]['input']>, 'mutationFn'>
10
+ ) => {
11
+ const rpc = usePikkuRPC<{ runWorkflow: <N extends keyof FlattenedWorkflowMap>(name: N, input: FlattenedWorkflowMap[N]['input']) => Promise<FlattenedWorkflowMap[N]['output']> }>()
12
+ return useMutation<FlattenedWorkflowMap[Name]['output'], Error, FlattenedWorkflowMap[Name]['input']>({
13
+ mutationFn: (input) => rpc.runWorkflow(name, input),
14
+ ...options,
15
+ })
16
+ }
17
+
18
+ export const useStartWorkflow = <Name extends keyof FlattenedWorkflowMap>(
19
+ name: Name,
20
+ options?: Omit<UseMutationOptions<{ runId: string }, Error, FlattenedWorkflowMap[Name]['input']>, 'mutationFn'>
21
+ ) => {
22
+ const rpc = usePikkuRPC<{ startWorkflow: <N extends keyof FlattenedWorkflowMap>(name: N, input: FlattenedWorkflowMap[N]['input']) => Promise<{ runId: string }> }>()
23
+ return useMutation<{ runId: string }, Error, FlattenedWorkflowMap[Name]['input']>({
24
+ mutationFn: (input) => rpc.startWorkflow(name, input),
25
+ ...options,
26
+ })
27
+ }
28
+
29
+ type WorkflowRunStatus = {
30
+ id: string
31
+ status: 'running' | 'suspended' | 'completed' | 'failed' | 'cancelled'
32
+ output?: unknown
33
+ error?: { message?: string }
34
+ }
35
+
36
+ export const useWorkflowStatus = (
37
+ workflowName: keyof FlattenedWorkflowMap & string,
38
+ runId?: string,
39
+ options?: Omit<UseQueryOptions<WorkflowRunStatus, Error>, 'queryKey' | 'queryFn' | 'enabled'>
40
+ ) => {
41
+ const rpc = usePikkuRPC<{ workflowStatus: (name: string, runId: string) => Promise<WorkflowRunStatus> }>()
42
+ return useQuery<WorkflowRunStatus, Error>({
43
+ queryKey: ['workflowStatus', workflowName, runId],
44
+ queryFn: () => {
45
+ if (!runId) throw new Error('runId is required')
46
+ return rpc.workflowStatus(workflowName, runId)
47
+ },
48
+ enabled: !!runId,
49
+ ...options,
50
+ })
51
+ }
52
+ `
53
+ : '';
54
+ return `import { useQuery, useInfiniteQuery, useMutation, type UseQueryOptions, type UseInfiniteQueryOptions, type UseMutationOptions, type InfiniteData } from '@tanstack/react-query'
55
+ import { usePikkuRPC } from '@pikku/react'
56
+ import type { FlattenedRPCMap } from '${rpcMapPath}'${workflowImport}
57
+
58
+ type RPCInvoke = <Name extends keyof FlattenedRPCMap>(name: Name, data: FlattenedRPCMap[Name]['input']) => Promise<FlattenedRPCMap[Name]['output']>
59
+
60
+ export const usePikkuQuery = <Name extends keyof FlattenedRPCMap>(
61
+ name: Name,
62
+ data: FlattenedRPCMap[Name]['input'],
63
+ options?: Omit<UseQueryOptions<FlattenedRPCMap[Name]['output'], Error>, 'queryKey' | 'queryFn'>
64
+ ) => {
65
+ const rpc = usePikkuRPC<{ invoke: RPCInvoke }>()
66
+ return useQuery<FlattenedRPCMap[Name]['output'], Error>({
67
+ queryKey: [name, data],
68
+ queryFn: () => rpc.invoke(name, data),
69
+ ...options,
70
+ })
71
+ }
72
+
73
+ export const usePikkuMutation = <Name extends keyof FlattenedRPCMap>(
74
+ name: Name,
75
+ options?: Omit<UseMutationOptions<FlattenedRPCMap[Name]['output'], Error, FlattenedRPCMap[Name]['input']>, 'mutationFn'>
76
+ ) => {
77
+ const rpc = usePikkuRPC<{ invoke: RPCInvoke }>()
78
+ return useMutation<FlattenedRPCMap[Name]['output'], Error, FlattenedRPCMap[Name]['input']>({
79
+ mutationFn: (data) => rpc.invoke(name, data),
80
+ ...options,
81
+ })
82
+ }
83
+
84
+ type PaginatedKeys = {
85
+ [K in keyof FlattenedRPCMap]: FlattenedRPCMap[K]['output'] extends { nextCursor?: string | null } ? K : never
86
+ }[keyof FlattenedRPCMap]
87
+
88
+ type InfiniteOpts<Name extends PaginatedKeys> = Omit<
89
+ UseInfiniteQueryOptions<FlattenedRPCMap[Name]['output'], Error, InfiniteData<FlattenedRPCMap[Name]['output'], string | undefined>, readonly unknown[], string | undefined>,
90
+ 'queryKey' | 'queryFn' | 'getNextPageParam' | 'initialPageParam'
91
+ >
92
+
93
+ export const usePikkuInfiniteQuery = <Name extends PaginatedKeys>(
94
+ name: Name,
95
+ data: Omit<FlattenedRPCMap[Name]['input'], 'nextCursor'>,
96
+ options?: InfiniteOpts<Name>
97
+ ) => {
98
+ const rpc = usePikkuRPC<{ invoke: RPCInvoke }>()
99
+ return useInfiniteQuery({
100
+ queryKey: [name, data] as const,
101
+ queryFn: ({ pageParam }: { pageParam: string | undefined }) => rpc.invoke(name, { ...data, nextCursor: pageParam } as FlattenedRPCMap[Name]['input']),
102
+ initialPageParam: undefined as string | undefined,
103
+ getNextPageParam: (lastPage: FlattenedRPCMap[Name]['output']) => (lastPage as { nextCursor?: string }).nextCursor ?? undefined,
104
+ ...options,
105
+ })
106
+ }
107
+ ${workflowHooks}`;
108
+ };
@@ -59,9 +59,9 @@ export class PikkuRPC {
59
59
  * @param data - The data to pass to the server function
60
60
  * @returns A promise that resolves with the function's return value
61
61
  */
62
- invoke: RPCInvoke = async (rpcName, data) => {
63
- return await this.pikkuFetch.post(\`${globalHTTPPrefix}/rpc/\${String(rpcName)}\` as never, { rpcName: String(rpcName), data }) as any
64
- }
62
+ invoke = ((rpcName: string, data?: unknown) => {
63
+ return this.pikkuFetch.post(\`${globalHTTPPrefix}/rpc/\${String(rpcName)}\` as never, { rpcName: String(rpcName), data }) as any
64
+ }) as RPCInvoke
65
65
 
66
66
  /**
67
67
  * Starts a workflow by name with the given input.
@@ -41,13 +41,15 @@ ${addonImports}
41
41
  ${mergedRPCMap}
42
42
 
43
43
  export type RPCInvoke = <Name extends keyof FlattenedRPCMap>(
44
- name: Name,
45
- data: FlattenedRPCMap[Name]['input']
44
+ ...args: FlattenedRPCMap[Name]['input'] extends void | null
45
+ ? [name: Name]
46
+ : [name: Name, data: FlattenedRPCMap[Name]['input']]
46
47
  ) => Promise<FlattenedRPCMap[Name]['output']>
47
48
 
48
49
  export type RPCRemote = <Name extends keyof FlattenedRPCMap>(
49
- name: Name,
50
- data: FlattenedRPCMap[Name]['input']
50
+ ...args: FlattenedRPCMap[Name]['input'] extends void | null
51
+ ? [name: Name]
52
+ : [name: Name, data: FlattenedRPCMap[Name]['input']]
51
53
  ) => Promise<FlattenedRPCMap[Name]['output']>
52
54
 
53
55
  ${workflowMapPath ? `import type { FlattenedWorkflowMap } from '${workflowMapPath}'` : `type FlattenedWorkflowMap = {}`}
@@ -15,6 +15,10 @@ function assertWorkflowService(workflowService: unknown): asserts workflowServic
15
15
  if (!workflowService) throw new MissingServiceError('workflowService is required')
16
16
  }
17
17
 
18
+ function assertWorkflowRunService(workflowRunService: unknown): asserts workflowRunService {
19
+ if (!workflowRunService) throw new MissingServiceError('workflowRunService is required')
20
+ }
21
+
18
22
  export const workflowStarter = pikkuSessionlessFunc<
19
23
  { workflowName: string; data?: unknown },
20
24
  { runId: string }
@@ -49,48 +53,137 @@ export const workflowStatusChecker = pikkuSessionlessFunc<
49
53
  },
50
54
  })
51
55
 
56
+ /**
57
+ * Minimal workflow status stream — sends step names and statuses only.
58
+ * Use this for user-facing frontends where internal details should not be exposed.
59
+ */
52
60
  export const workflowStatusStream = pikkuSessionlessFunc<
53
61
  { workflowName: string; runId: string },
54
- WorkflowRunStatus
62
+ unknown
55
63
  >({
56
64
  auth: ${authFlag},
57
- func: async ({ workflowService }, { runId }, { channel }) => {
58
- assertWorkflowService(workflowService)
65
+ func: async ({ workflowRunService }, { runId }, { channel }) => {
66
+ assertWorkflowRunService(workflowRunService)
67
+ if (!channel) return
68
+
59
69
  const terminalStatuses = new Set(['completed', 'failed', 'cancelled'])
60
- const pollIntervalMs = 1000
61
- const maxWaitMs = 300_000
70
+ let lastHash = ''
62
71
 
63
- const startTime = Date.now()
64
- let lastStatusJson = ''
72
+ const poll = async () => {
73
+ const run = await workflowRunService.getRun(runId)
74
+ if (!run) {
75
+ channel.close()
76
+ return false
77
+ }
65
78
 
66
- while (Date.now() - startTime < maxWaitMs) {
67
- const status = await workflowService.getRunStatus(runId)
68
- if (!status) throw new Error(\`Run not found: \${runId}\`)
79
+ const steps = await workflowRunService.getRunSteps(runId)
69
80
 
70
- const statusJson = JSON.stringify(status)
71
- if (statusJson !== lastStatusJson) {
72
- lastStatusJson = statusJson
73
- if (channel) {
74
- channel.send(status)
75
- }
81
+ const hash = JSON.stringify({
82
+ s: run.status,
83
+ steps: steps.map((s: { stepName: string; status: string }) => [s.stepName, s.status]),
84
+ })
85
+
86
+ if (hash !== lastHash) {
87
+ lastHash = hash
88
+ channel.send({
89
+ type: 'update',
90
+ status: run.status,
91
+ steps: steps.map((s: { stepName: string; status: string }) => ({
92
+ stepName: s.stepName,
93
+ status: s.status,
94
+ })),
95
+ })
96
+ }
97
+
98
+ if (terminalStatuses.has(run.status)) {
99
+ channel.send({ type: 'done' })
100
+ channel.close()
101
+ return false
76
102
  }
103
+ return true
104
+ }
105
+
106
+ const shouldContinue = await poll()
107
+ if (!shouldContinue) return
77
108
 
78
- if (terminalStatuses.has(status.status)) {
79
- if (channel) {
80
- channel.close()
109
+ await new Promise<void>((resolve) => {
110
+ const interval = setInterval(async () => {
111
+ const cont = await poll()
112
+ if (!cont) {
113
+ clearInterval(interval)
114
+ resolve()
81
115
  }
82
- return status
116
+ }, 500)
117
+ })
118
+ },
119
+ })
120
+
121
+ /**
122
+ * Full workflow status stream — includes output, error, and child run IDs.
123
+ * Use this for admin consoles and internal tooling.
124
+ */
125
+ export const workflowStatusStreamFull = pikkuSessionlessFunc<
126
+ { workflowName: string; runId: string },
127
+ unknown
128
+ >({
129
+ auth: ${authFlag},
130
+ func: async ({ workflowRunService }, { runId }, { channel }) => {
131
+ assertWorkflowRunService(workflowRunService)
132
+ if (!channel) return
133
+
134
+ const terminalStatuses = new Set(['completed', 'failed', 'cancelled'])
135
+ let lastHash = ''
136
+
137
+ const poll = async () => {
138
+ const run = await workflowRunService.getRun(runId)
139
+ if (!run) {
140
+ channel.close()
141
+ return false
83
142
  }
84
143
 
85
- await new Promise((r) => setTimeout(r, pollIntervalMs))
86
- }
144
+ const steps = await workflowRunService.getRunSteps(runId)
145
+
146
+ const hash = JSON.stringify({
147
+ s: run.status,
148
+ o: run.output,
149
+ steps: steps.map((s: { stepName: string; status: string }) => [s.stepName, s.status]),
150
+ })
87
151
 
88
- // Timeout return last known status
89
- const finalStatus = await workflowService.getRunStatus(runId)
90
- if (channel) {
91
- channel.close()
152
+ if (hash !== lastHash) {
153
+ lastHash = hash
154
+ channel.send({
155
+ type: 'update',
156
+ status: run.status,
157
+ output: run.output,
158
+ error: run.error,
159
+ steps: steps.map((s: { stepName: string; status: string; childRunId?: string }) => ({
160
+ stepName: s.stepName,
161
+ status: s.status,
162
+ ...(s.childRunId ? { childRunId: s.childRunId } : {}),
163
+ })),
164
+ })
165
+ }
166
+
167
+ if (terminalStatuses.has(run.status)) {
168
+ channel.send({ type: 'done' })
169
+ channel.close()
170
+ return false
171
+ }
172
+ return true
92
173
  }
93
- return finalStatus as WorkflowRunStatus
174
+
175
+ const shouldContinue = await poll()
176
+ if (!shouldContinue) return
177
+
178
+ await new Promise<void>((resolve) => {
179
+ const interval = setInterval(async () => {
180
+ const cont = await poll()
181
+ if (!cont) {
182
+ clearInterval(interval)
183
+ resolve()
184
+ }
185
+ }, 500)
186
+ })
94
187
  },
95
188
  })
96
189
 
@@ -128,6 +221,12 @@ wireHTTPRoutes({
128
221
  sse: true,
129
222
  func: workflowStatusStream,
130
223
  },
224
+ workflowStatusStreamFull: {
225
+ route: '/workflow/:workflowName/status/:runId/stream/full',
226
+ method: 'get',
227
+ sse: true,
228
+ func: workflowStatusStreamFull,
229
+ },
131
230
  graphStart: {
132
231
  route: '/workflow/:workflowName/graph/:nodeId',
133
232
  method: 'post',
@@ -0,0 +1 @@
1
+ export declare const allWorkflow: import("../../../.pikku/pikku-types.gen.js").PikkuFunctionConfig<void, void, "workflow">;