@pikku/cli 0.12.91 → 0.12.92

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 (222) hide show
  1. package/LICENSE +106 -0
  2. package/console-app/assets/{index-CpkvmAGb.js → index-DDpIMCpy.js} +149 -149
  3. package/console-app/index.html +1 -1
  4. package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +1 -1
  5. package/dist/.pikku/channel/pikku-channel-types.gen.d.ts +1 -1
  6. package/dist/.pikku/channel/pikku-channel-types.gen.js +1 -1
  7. package/dist/.pikku/cli/pikku-cli-channel.js +6 -1
  8. package/dist/.pikku/cli/pikku-cli-client.gen.d.ts +1 -1
  9. package/dist/.pikku/cli/pikku-cli-client.gen.js +1 -1
  10. package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.d.ts +1 -1
  11. package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.js +1 -1
  12. package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.json +15 -0
  13. package/dist/.pikku/cli/pikku-cli-types.gen.d.ts +1 -1
  14. package/dist/.pikku/cli/pikku-cli-types.gen.js +1 -1
  15. package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.js +1 -1
  16. package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.json +21 -0
  17. package/dist/.pikku/cli/pikku-cli-wirings.gen.d.ts +1 -1
  18. package/dist/.pikku/cli/pikku-cli-wirings.gen.js +1 -1
  19. package/dist/.pikku/cli/pikku-cli.gen.d.ts +1 -1
  20. package/dist/.pikku/cli/pikku-cli.gen.js +1 -1
  21. package/dist/.pikku/console/pikku-node-types.gen.d.ts +1 -1
  22. package/dist/.pikku/function/pikku-function-types.gen.d.ts +1 -1
  23. package/dist/.pikku/function/pikku-function-types.gen.js +1 -1
  24. package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
  25. package/dist/.pikku/function/pikku-functions-meta.gen.json +35 -40
  26. package/dist/.pikku/function/pikku-functions.gen.js +1 -3
  27. package/dist/.pikku/http/pikku-http-types.gen.d.ts +1 -1
  28. package/dist/.pikku/http/pikku-http-types.gen.js +1 -1
  29. package/dist/.pikku/mcp/pikku-mcp-types.gen.d.ts +1 -1
  30. package/dist/.pikku/mcp/pikku-mcp-types.gen.js +1 -1
  31. package/dist/.pikku/pikku-bootstrap-scenarios.gen.d.ts +2 -1
  32. package/dist/.pikku/pikku-bootstrap-scenarios.gen.js +2 -1
  33. package/dist/.pikku/pikku-bootstrap.gen.d.ts +1 -1
  34. package/dist/.pikku/pikku-bootstrap.gen.js +1 -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 +1 -1
  38. package/dist/.pikku/pikku-types.gen.d.ts +1 -1
  39. package/dist/.pikku/pikku-types.gen.js +1 -1
  40. package/dist/.pikku/queue/pikku-queue-types.gen.d.ts +1 -1
  41. package/dist/.pikku/queue/pikku-queue-types.gen.js +1 -1
  42. package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.js +1 -1
  43. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.d.ts +1 -1
  44. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.js +1 -1
  45. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.js +1 -1
  46. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.json +1 -1
  47. package/dist/.pikku/scenarios/pikku-scenario-functions-meta.gen.js +1 -1
  48. package/dist/.pikku/scenarios/pikku-scenario-functions.gen.d.ts +1 -1
  49. package/dist/.pikku/scenarios/pikku-scenario-wirings-meta.gen.js +1 -1
  50. package/dist/.pikku/scenarios/pikku-scenario-wirings.gen.d.ts +1 -1
  51. package/dist/.pikku/scenarios/schemas/register.gen.d.ts +4 -0
  52. package/dist/.pikku/scenarios/schemas/register.gen.js +4 -0
  53. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.d.ts +1 -1
  54. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.js +1 -1
  55. package/dist/.pikku/schemas/register.gen.js +5 -3
  56. package/dist/.pikku/schemas/schemas/FabricSecretsListOutput.schema.json +1 -1
  57. package/dist/.pikku/schemas/schemas/FabricSecretsRotateInput.schema.json +1 -0
  58. package/dist/.pikku/schemas/schemas/FabricSecretsRotateOutput.schema.json +1 -0
  59. package/dist/.pikku/schemas/schemas/FabricSecretsSetOutput.schema.json +1 -1
  60. package/dist/.pikku/schemas/schemas/PikkuCLIConfig.schema.json +1 -1
  61. package/dist/.pikku/schemas/schemas/ScenarioRunInput.schema.json +1 -1
  62. package/dist/.pikku/scopes/pikku-scope-types.gen.d.ts +1 -1
  63. package/dist/.pikku/scopes/pikku-scope-types.gen.js +1 -1
  64. package/dist/.pikku/scopes/pikku-scopes.gen.d.ts +1 -1
  65. package/dist/.pikku/secrets/pikku-secret-types.gen.d.ts +1 -1
  66. package/dist/.pikku/secrets/pikku-secret-types.gen.js +1 -1
  67. package/dist/.pikku/secrets/pikku-secrets.gen.d.ts +1 -1
  68. package/dist/.pikku/secrets/pikku-secrets.gen.js +1 -1
  69. package/dist/.pikku/trigger/pikku-trigger-types.gen.d.ts +1 -1
  70. package/dist/.pikku/trigger/pikku-trigger-types.gen.js +1 -1
  71. package/dist/.pikku/variables/pikku-variable-types.gen.d.ts +1 -1
  72. package/dist/.pikku/variables/pikku-variable-types.gen.js +1 -1
  73. package/dist/.pikku/variables/pikku-variables.gen.d.ts +1 -1
  74. package/dist/.pikku/variables/pikku-variables.gen.js +1 -1
  75. package/dist/.pikku/workflow/meta/allWorkflow.gen.json +2 -8
  76. package/dist/.pikku/workflow/pikku-scenario-actors.gen.d.ts +1 -1
  77. package/dist/.pikku/workflow/pikku-scenario-actors.gen.js +1 -1
  78. package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +1 -1
  79. package/dist/.pikku/workflow/pikku-workflow-types.gen.js +1 -1
  80. package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +1 -1
  81. package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +1 -1
  82. package/dist/bin/pikku-bin.mjs +2 -2
  83. package/dist/src/cli.wiring.js +6 -0
  84. package/dist/src/deploy/analyzer/analyzer.js +22 -5
  85. package/dist/src/deploy/build-pipeline.js +5 -1
  86. package/dist/src/fabric/fabric-commands.d.ts +37 -9
  87. package/dist/src/fabric/fabric-commands.js +12 -0
  88. package/dist/src/fabric/functions/domains-add.function.d.ts +4 -4
  89. package/dist/src/fabric/functions/secrets-list.function.d.ts +16 -4
  90. package/dist/src/fabric/functions/secrets-list.function.js +12 -10
  91. package/dist/src/fabric/functions/secrets-rotate.function.d.ts +24 -0
  92. package/dist/src/fabric/functions/secrets-rotate.function.js +36 -0
  93. package/dist/src/fabric/functions/secrets-set.function.d.ts +8 -4
  94. package/dist/src/fabric/functions/secrets-set.function.js +18 -7
  95. package/dist/src/fabric/lib/http.d.ts +7 -1
  96. package/dist/src/fabric/lib/sealed-box.d.ts +16 -0
  97. package/dist/src/fabric/lib/sealed-box.js +72 -0
  98. package/dist/src/functions/commands/dev.js +9 -0
  99. package/dist/src/functions/commands/pikku-command-bootstrap.js +1 -0
  100. package/dist/src/functions/commands/scenario-browser.d.ts +17 -2
  101. package/dist/src/functions/commands/scenario-browser.js +16 -8
  102. package/dist/src/functions/commands/scenario-environment.d.ts +32 -0
  103. package/dist/src/functions/commands/scenario-environment.js +61 -0
  104. package/dist/src/functions/commands/scenario.d.ts +6 -0
  105. package/dist/src/functions/commands/scenario.js +14 -9
  106. package/dist/src/functions/commands/skills.js +27 -61
  107. package/dist/src/functions/db/db-codegen.d.ts +6 -0
  108. package/dist/src/functions/db/db-codegen.js +9 -0
  109. package/dist/src/functions/db/db-migrator.js +14 -0
  110. package/dist/src/functions/db/local-db.d.ts +8 -0
  111. package/dist/src/functions/db/local-db.js +24 -2
  112. package/dist/src/functions/db/migration-identifiers.d.ts +58 -0
  113. package/dist/src/functions/db/migration-identifiers.js +262 -0
  114. package/dist/src/functions/db/migration-provenance.d.ts +35 -0
  115. package/dist/src/functions/db/migration-provenance.js +80 -0
  116. package/dist/src/functions/db/schema-sql.d.ts +43 -0
  117. package/dist/src/functions/db/schema-sql.js +135 -0
  118. package/dist/src/functions/db/sqlite/sqlite-kysely.js +22 -2
  119. package/dist/src/functions/wirings/functions/schemas.js +13 -1
  120. package/dist/src/functions/wirings/rpc/pikku-command-rpc.js +6 -1
  121. package/dist/src/functions/wirings/scenarios/register-scenario-instrumentation.d.ts +10 -0
  122. package/dist/src/functions/wirings/scenarios/register-scenario-instrumentation.js +102 -0
  123. package/dist/src/functions/wirings/scenarios/scenario-partition.d.ts +13 -0
  124. package/dist/src/functions/wirings/scenarios/scenario-partition.js +15 -2
  125. package/dist/src/functions/wirings/scenarios/scenario-schema-partition.d.ts +33 -0
  126. package/dist/src/functions/wirings/scenarios/scenario-schema-partition.js +49 -0
  127. package/dist/src/functions/workflows/all.workflow.js +2 -7
  128. package/dist/src/utils/file-writer.js +14 -2
  129. package/dist/src/utils/pikku-cli-config.d.ts +14 -0
  130. package/dist/src/utils/pikku-cli-config.js +34 -0
  131. package/dist/src/utils/remove-legacy-scaffold-file.d.ts +14 -0
  132. package/dist/src/utils/remove-legacy-scaffold-file.js +23 -0
  133. package/dist/src/utils/serialize-schemas.d.ts +3 -1
  134. package/dist/src/utils/serialize-schemas.js +39 -4
  135. package/dist/tsconfig.tsbuildinfo +1 -1
  136. package/package.json +9 -9
  137. package/dist/.pikku/schemas/schemas/PikkuScenarioFunctionsOutput.schema.json +0 -1
  138. package/dist/src/functions/wirings/scenarios/pikku-command-scenario-functions.d.ts +0 -1
  139. package/dist/src/functions/wirings/scenarios/pikku-command-scenario-functions.js +0 -31
  140. package/dist/src/functions/wirings/scenarios/serialize-scenario-functions.d.ts +0 -10
  141. package/dist/src/functions/wirings/scenarios/serialize-scenario-functions.js +0 -104
  142. package/skills/pikku-addon/SKILL.md +0 -243
  143. package/skills/pikku-addon/references/addon-package-manifest.md +0 -63
  144. package/skills/pikku-ai-agent/SKILL.md +0 -231
  145. package/skills/pikku-ai-vercel/SKILL.md +0 -82
  146. package/skills/pikku-ai-voice/SKILL.md +0 -88
  147. package/skills/pikku-audit/SKILL.md +0 -175
  148. package/skills/pikku-aws/SKILL.md +0 -111
  149. package/skills/pikku-backblaze/SKILL.md +0 -71
  150. package/skills/pikku-better-auth/SKILL.md +0 -298
  151. package/skills/pikku-cli/SKILL.md +0 -198
  152. package/skills/pikku-cli/references/complete-example.md +0 -82
  153. package/skills/pikku-concepts/SKILL.md +0 -250
  154. package/skills/pikku-concepts/references/concept-mapping.md +0 -556
  155. package/skills/pikku-concepts/references/packages.md +0 -29
  156. package/skills/pikku-config/SKILL.md +0 -212
  157. package/skills/pikku-cron/SKILL.md +0 -214
  158. package/skills/pikku-deploy-azure/SKILL.md +0 -71
  159. package/skills/pikku-deploy-cloudflare/SKILL.md +0 -82
  160. package/skills/pikku-deploy-express/SKILL.md +0 -86
  161. package/skills/pikku-deploy-fastify/SKILL.md +0 -73
  162. package/skills/pikku-deploy-lambda/SKILL.md +0 -110
  163. package/skills/pikku-deploy-nextjs/SKILL.md +0 -78
  164. package/skills/pikku-deploy-uws/SKILL.md +0 -88
  165. package/skills/pikku-deps/SKILL.md +0 -98
  166. package/skills/pikku-emails/SKILL.md +0 -163
  167. package/skills/pikku-fabric/SKILL.md +0 -318
  168. package/skills/pikku-fabric-debug/SKILL.md +0 -112
  169. package/skills/pikku-feature/SKILL.md +0 -258
  170. package/skills/pikku-gateway-slack/SKILL.md +0 -115
  171. package/skills/pikku-http/SKILL.md +0 -220
  172. package/skills/pikku-http/references/http-options.md +0 -55
  173. package/skills/pikku-i18n/SKILL.md +0 -137
  174. package/skills/pikku-info/SKILL.md +0 -100
  175. package/skills/pikku-jose/SKILL.md +0 -105
  176. package/skills/pikku-kysely/SKILL.md +0 -219
  177. package/skills/pikku-machine-auth/SKILL.md +0 -183
  178. package/skills/pikku-mcp/SKILL.md +0 -241
  179. package/skills/pikku-middleware/SKILL.md +0 -231
  180. package/skills/pikku-middleware/references/middleware-patterns.md +0 -61
  181. package/skills/pikku-mongodb/SKILL.md +0 -105
  182. package/skills/pikku-n8n-import/SKILL.md +0 -109
  183. package/skills/pikku-n8n-import/SPEC.md +0 -84
  184. package/skills/pikku-n8n-import/references/addon-mapping.md +0 -121
  185. package/skills/pikku-n8n-import/references/code-translation.md +0 -121
  186. package/skills/pikku-n8n-import/references/loops-and-control.md +0 -87
  187. package/skills/pikku-paraglide/SKILL.md +0 -117
  188. package/skills/pikku-permissions/SKILL.md +0 -192
  189. package/skills/pikku-pino/SKILL.md +0 -79
  190. package/skills/pikku-product-second-opinion/README.md +0 -43
  191. package/skills/pikku-product-second-opinion/SKILL.md +0 -158
  192. package/skills/pikku-product-second-opinion/example/sample-report.md +0 -90
  193. package/skills/pikku-product-second-opinion/references/report-template.md +0 -73
  194. package/skills/pikku-queue/SKILL.md +0 -240
  195. package/skills/pikku-react/SKILL.md +0 -212
  196. package/skills/pikku-react-query/SKILL.md +0 -242
  197. package/skills/pikku-realtime/SKILL.md +0 -236
  198. package/skills/pikku-realtime/references/other-routes.md +0 -23
  199. package/skills/pikku-redis/SKILL.md +0 -90
  200. package/skills/pikku-rpc/SKILL.md +0 -171
  201. package/skills/pikku-rtl/SKILL.md +0 -219
  202. package/skills/pikku-scenario/SKILL.md +0 -382
  203. package/skills/pikku-schedule/SKILL.md +0 -57
  204. package/skills/pikku-schema-ajv/SKILL.md +0 -62
  205. package/skills/pikku-schema-cfworker/SKILL.md +0 -63
  206. package/skills/pikku-security/SKILL.md +0 -108
  207. package/skills/pikku-services/SKILL.md +0 -248
  208. package/skills/pikku-services/references/audit-wire-service.md +0 -34
  209. package/skills/pikku-software-archaeology/README.md +0 -70
  210. package/skills/pikku-software-archaeology/SKILL.md +0 -186
  211. package/skills/pikku-software-archaeology/references/blueprint.schema.json +0 -625
  212. package/skills/pikku-software-archaeology/references/pikku-mapping.md +0 -49
  213. package/skills/pikku-software-archaeology/scripts/validate.mjs +0 -173
  214. package/skills/pikku-tag-middleware/SKILL.md +0 -13
  215. package/skills/pikku-template-clone/SKILL.md +0 -40
  216. package/skills/pikku-trigger/SKILL.md +0 -181
  217. package/skills/pikku-versioning/SKILL.md +0 -173
  218. package/skills/pikku-websocket/SKILL.md +0 -243
  219. package/skills/pikku-workflow/SKILL.md +0 -172
  220. package/skills/pikku-workflow/references/workflow-reference.md +0 -63
  221. package/skills/pikku-workflows-client/SKILL.md +0 -150
  222. package/skills/pikku-ws/SKILL.md +0 -47
@@ -1,240 +0,0 @@
1
- ---
2
- name: pikku-queue
3
- description: >-
4
- Use when adding background job processing, async task queues, or distributed workers to a Pikku
5
- app. Covers wireQueueWorker, job enqueuing, progress tracking, retries, BullMQ and PgBoss
6
- adapters. TRIGGER when: code uses wireQueueWorker, user asks about background jobs, task queues,
7
- async processing, BullMQ, PgBoss, or job retries. DO NOT TRIGGER when: user asks about scheduled
8
- cron tasks (use pikku-cron) or event-driven triggers (use pikku-trigger).
9
- installGroups: [core]
10
- ---
11
-
12
- # Pikku Queue Wiring
13
-
14
- ## Agent Operating Procedure
15
-
16
- Use this skill as an execution checklist, not reference material.
17
-
18
- 1. Discover before editing. Prefer OpenCode tools such as `pikku-meta` when available; otherwise run the relevant `pikku meta ... --json` command and inspect only the focused output you need.
19
- 2. Identify the source files that own the behavior. Do not start by reading generated output, `.pikku`, `node_modules`, vendored packages, or broad build artifacts.
20
- 3. Make the smallest source change that satisfies the task. Keep generated files generated, and avoid hand-editing SDKs, schema output, or typegen.
21
- 4. Validate with the narrowest relevant command first, then run `pikku-verify` or `pikku all` when functions, wirings, schemas, or generated clients may have changed.
22
- 5. If validation fails, fix the source cause and rerun validation. Do not paper over generated errors by editing generated files.
23
-
24
- Wire Pikku functions as background queue workers. Supports job control (progress, retry, discard), configurable concurrency, and type-safe job publishing.
25
-
26
- ## Before You Start
27
-
28
- ```bash
29
- pikku info functions --verbose # See existing functions and their types
30
- pikku info tags --verbose # Understand project organization
31
- ```
32
-
33
- See `pikku-concepts` for the core mental model.
34
-
35
- ## API Reference
36
-
37
- ### `wireQueueWorker(config)`
38
-
39
- ```typescript
40
- import { wireQueueWorker } from '@pikku/core/queue'
41
-
42
- wireQueueWorker({
43
- name: string, // Queue name (unique identifier)
44
- func: PikkuFunc, // Worker function
45
- config?: {
46
- batchSize?: number, // Process N jobs at once
47
- removeOnComplete?: number | boolean, // Clean up completed jobs
48
- },
49
- })
50
- ```
51
-
52
- ### Wire Object (`wire.queue`)
53
-
54
- Inside queue worker functions:
55
-
56
- ```typescript
57
- wire.queue.updateProgress(percent: number) // Report progress (0-100)
58
- wire.queue.discard(reason: string) // Silently discard job
59
- wire.queue.fail(reason: string) // Mark job as failed
60
- ```
61
-
62
- ### Job Publishing
63
-
64
- ```typescript
65
- const jobId = await queue.add(queueName, data, options?)
66
- ```
67
-
68
- Options:
69
-
70
- ```typescript
71
- {
72
- priority?: number, // Higher = processed first
73
- delay?: number, // Delay in ms before processing
74
- attempts?: number, // Max retry attempts
75
- backoff?: {
76
- type: 'exponential' | 'fixed',
77
- delay: number, // Base delay in ms
78
- },
79
- }
80
- ```
81
-
82
- ## Usage Patterns
83
-
84
- ### Basic Queue Worker
85
-
86
- ```typescript
87
- const processReminder = pikkuSessionlessFunc({
88
- title: 'Process Reminder',
89
- func: async ({ db, emailService }, { todoId, userId }) => {
90
- const todo = await db.getTodo(todoId)
91
- await emailService.sendReminder(userId, todo)
92
- return { sent: true }
93
- },
94
- })
95
-
96
- wireQueueWorker({
97
- name: 'todo-reminders',
98
- func: processReminder,
99
- })
100
- ```
101
-
102
- ### Job Control (Progress, Discard, Fail)
103
-
104
- ```typescript
105
- const processReminder = pikkuSessionlessFunc({
106
- title: 'Process Reminder',
107
- func: async ({ db }, { todoId }, wire) => {
108
- await wire.queue.updateProgress(25)
109
-
110
- const todo = await db.getTodo(todoId)
111
- if (!todo) {
112
- await wire.queue.discard('Todo not found')
113
- return
114
- }
115
-
116
- if (todo.completed) {
117
- await wire.queue.fail('Todo already completed')
118
- return
119
- }
120
-
121
- await wire.queue.updateProgress(100)
122
- return { sent: true }
123
- },
124
- })
125
- ```
126
-
127
- ### Retries & Configuration
128
-
129
- ```typescript
130
- wireQueueWorker({
131
- name: 'todo-reminders',
132
- func: processReminder,
133
- config: {
134
- batchSize: 5,
135
- removeOnComplete: 100,
136
- },
137
- })
138
-
139
- // Enqueue with retry options
140
- const jobId = await queue.add(
141
- 'todo-reminders',
142
- {
143
- todoId: 'abc-123',
144
- userId: 'user-456',
145
- },
146
- {
147
- priority: 10,
148
- delay: 5000,
149
- attempts: 3,
150
- backoff: { type: 'exponential', delay: 1000 },
151
- }
152
- )
153
- ```
154
-
155
- ### Type-Safe Queue Publishing
156
-
157
- After `npx pikku all`:
158
-
159
- ```typescript
160
- import { PikkuQueue } from '.pikku/pikku-queue.gen.js'
161
-
162
- const queue = new PikkuQueue(queueService)
163
-
164
- const jobId = await queue.add('todo-reminders', {
165
- todoId: 'abc-123',
166
- userId: 'user-456',
167
- })
168
-
169
- const job = await queue.getJob('todo-reminders', jobId)
170
- const status = await job.status() // 'waiting' | 'active' | 'completed' | 'failed'
171
- const result = await job.waitForCompletion(30_000)
172
- ```
173
-
174
- ### Queue Adapters
175
-
176
- **BullMQ** (Redis-based):
177
-
178
- ```typescript
179
- import { BullMQQueueService } from '@pikku/queue-bullmq'
180
-
181
- const queueService = new BullMQQueueService({
182
- connection: { host: 'localhost', port: 6379 },
183
- })
184
- ```
185
-
186
- **PgBoss** (PostgreSQL-based):
187
-
188
- ```typescript
189
- import { PgBossQueueService } from '@pikku/queue-pg-boss'
190
-
191
- const queueService = new PgBossQueueService({
192
- connectionString: 'postgres://...',
193
- })
194
- ```
195
-
196
- ## Complete Example
197
-
198
- ```typescript
199
- // functions/email.functions.ts
200
- export const sendWelcomeEmail = pikkuSessionlessFunc({
201
- title: 'Send Welcome Email',
202
- func: async ({ emailService, db }, { userId }, wire) => {
203
- await wire.queue.updateProgress(10)
204
-
205
- const user = await db.getUser(userId)
206
- if (!user) {
207
- await wire.queue.discard('User not found')
208
- return
209
- }
210
-
211
- await wire.queue.updateProgress(50)
212
- await emailService.send({
213
- to: user.email,
214
- subject: 'Welcome!',
215
- template: 'welcome',
216
- data: { name: user.name },
217
- })
218
-
219
- await wire.queue.updateProgress(100)
220
- return { sent: true, email: user.email }
221
- },
222
- })
223
-
224
- // wirings/queue.wiring.ts
225
- wireQueueWorker({
226
- name: 'welcome-emails',
227
- func: sendWelcomeEmail,
228
- config: { removeOnComplete: 100 },
229
- })
230
-
231
- // Enqueue from another function
232
- export const registerUser = pikkuSessionlessFunc({
233
- title: 'Register User',
234
- func: async ({ db, queue }, { email, name }) => {
235
- const user = await db.createUser({ email, name })
236
- await queue.add('welcome-emails', { userId: user.id })
237
- return { user }
238
- },
239
- })
240
- ```
@@ -1,212 +0,0 @@
1
- ---
2
- name: pikku-react
3
- description: 'Set up @pikku/react in a React app: PikkuProvider context, createPikku factory, and the usePikkuRPC / usePikkuFetch hooks for direct (non-React-Query) calls. TRIGGER when: the user is bootstrapping a React frontend that talks to a Pikku backend, asks how to wire `PikkuProvider`, or needs to make one-off RPC calls outside of useQuery/useMutation. DO NOT TRIGGER when: the user is asking about useQuery/useMutation hooks (use pikku-react-query) or about workflows (use pikku-workflows-client).'
4
- installGroups: [core]
5
- ---
6
-
7
- # Pikku React
8
-
9
- ## Agent Operating Procedure
10
-
11
- Use this skill as an execution checklist, not reference material.
12
-
13
- 1. Discover before editing. Prefer OpenCode tools such as `pikku-meta` when available; otherwise run the relevant `pikku meta ... --json` command and inspect only the focused output you need.
14
- 2. Identify the source files that own the behavior. Do not start by reading generated output, `.pikku`, `node_modules`, vendored packages, or broad build artifacts.
15
- 3. Make the smallest source change that satisfies the task. Keep generated files generated, and avoid hand-editing SDKs, schema output, or typegen.
16
- 4. Validate with the narrowest relevant command first, then run `pikku-verify` or `pikku all` when functions, wirings, schemas, or generated clients may have changed.
17
- 5. If validation fails, fix the source cause and rerun validation. Do not paper over generated errors by editing generated files.
18
-
19
- `@pikku/react` is the smallest possible binding: a Context provider plus
20
- two hooks. It does **not** depend on React Query — that's a separate
21
- opt-in via the generated `api.gen.ts`. Use this skill when setting up the
22
- provider or making direct RPC calls.
23
-
24
- ## What ships
25
-
26
- ```tsx
27
- import {
28
- PikkuProvider,
29
- createPikku,
30
- usePikkuFetch,
31
- usePikkuRPC,
32
- usePikkuRealtime,
33
- } from '@pikku/react'
34
- ```
35
-
36
- Five exports. `usePikkuRealtime` is only valid when you wired a
37
- `PikkuRealtime` class via `createPikku` — see step 3 below.
38
-
39
- ## Resolving the server URL
40
-
41
- Every client (`createPikku`, realtime, the auth client) resolves its base
42
- through one shared helper in `src/lib/env.ts`. Write this once:
43
-
44
- ```ts
45
- // Endpoints come from env, never hardcoded.
46
- export function apiUrl(): string {
47
- // SSR: the client hooks only run in the browser, so a placeholder is fine.
48
- if (import.meta.env.SSR) {
49
- return import.meta.env.VITE_API_URL ?? '/__api'
50
- }
51
- return import.meta.env.VITE_API_URL ?? `${window.location.origin}/api`
52
- }
53
- ```
54
-
55
- **Never fall back to `http://localhost:3000`.** `import.meta.env.VITE_API_URL`
56
- is substituted by Vite at *build* time, so any deploy that supplies the URL as
57
- a *runtime* env var or platform binding leaves it `undefined` in the shipped
58
- bundle — the fallback is then the only branch that ever runs in the browser. A
59
- localhost fallback means every request from a deployed app goes to the user's
60
- own machine. `origin + '/api'` is same-origin, needs no build-time knowledge of
61
- the domain, and is correct wherever the app is served from.
62
-
63
- For local dev, set `VITE_API_URL`, or proxy `/api` → your backend in
64
- `vite.config.ts` under `server.proxy`. One `/api` entry also covers
65
- `/api/auth/*`; only add more entries for root-level routes outside `/api`.
66
-
67
- ## Setup at the app root
68
-
69
- ```tsx
70
- import { createPikku, PikkuProvider } from '@pikku/react'
71
- import { PikkuFetch } from './pikku/pikku-fetch.gen'
72
- import { PikkuRPC } from './pikku/pikku-rpc.gen'
73
- import { apiUrl } from './lib/env'
74
-
75
- const pikku = createPikku(PikkuFetch, PikkuRPC, {
76
- serverUrl: apiUrl(),
77
- })
78
-
79
- createRoot(document.getElementById('root')!).render(
80
- <PikkuProvider pikku={pikku}>
81
- <App />
82
- </PikkuProvider>
83
- )
84
- ```
85
-
86
- If the project also exposes realtime events (see **pikku-realtime**), pass
87
- the `PikkuRealtime` class as the third argument and the instance gets a
88
- `realtime` field too:
89
-
90
- ```tsx
91
- import { PikkuRealtime } from './pikku/realtime.gen'
92
-
93
- const pikku = createPikku(PikkuFetch, PikkuRPC, PikkuRealtime, {
94
- serverUrl: apiUrl(),
95
- })
96
- // pikku.fetch / pikku.rpc / pikku.realtime — all share the same fetch
97
- // (server URL + auth configured once).
98
- ```
99
-
100
- The generated classes come from your `pikku.config.json`:
101
-
102
- | config field | generated file |
103
- | ---------------------------- | ----------------------------------------------------- |
104
- | `clientFiles.fetchFile` | typed HTTP client (`PikkuFetch` class) |
105
- | `clientFiles.rpcWiringsFile` | RPC client (`PikkuRPC` class) calling all exposed fns |
106
- | `clientFiles.realtimeFile` | `PikkuRealtime` (websocket events + SSE + channels) |
107
-
108
- If a file isn't being generated, that field is missing from the config —
109
- add it and re-run `pikku all`.
110
-
111
- `createPikku(...)` accepts the same `CorePikkuFetchOptions` as `PikkuFetch`
112
- plus `serverUrl`. Auth headers, request interceptors, etc. are configured
113
- on the fetch instance — RPC and realtime inherit them automatically.
114
-
115
- ## Calling an RPC directly (no React Query)
116
-
117
- Inside a component:
118
-
119
- ```tsx
120
- import { usePikkuRPC } from '@pikku/react'
121
-
122
- function Logout() {
123
- const rpc = usePikkuRPC()
124
- return <button onClick={() => rpc.invoke('logoutUser', {})}>Sign out</button>
125
- }
126
- ```
127
-
128
- `rpc.invoke(name, data)` is typed against `FlattenedRPCMap` — `name` must
129
- be an exposed function id, `data` matches the input schema, return value
130
- matches the output schema.
131
-
132
- You also have `rpc.<funcName>(data)` if the generated RPC client builds
133
- direct methods (project-dependent).
134
-
135
- ## Calling fetch directly
136
-
137
- ```tsx
138
- const fetch = usePikkuFetch()
139
- const data = await fetch.get('/some-rest-route', { searchParams: {...} })
140
- ```
141
-
142
- Use this only when the function is wired via HTTP (REST shape) and you
143
- need a path-style call. For RPC calls, `usePikkuRPC()` is cleaner.
144
-
145
- ## Realtime subscriptions
146
-
147
- If you wired a `PikkuRealtime` class into `createPikku`, use
148
- `usePikkuRealtime()` to grab the shared instance:
149
-
150
- ```tsx
151
- import { usePikkuRealtime } from '@pikku/react'
152
- import type { PikkuRealtime } from './pikku/realtime.gen'
153
-
154
- function TodoList() {
155
- const realtime = usePikkuRealtime<PikkuRealtime>()
156
- useEffect(() => {
157
- return realtime.subscribe('todo-created', ({ todo }) => {
158
- /* ... */
159
- })
160
- }, [realtime])
161
- // ...
162
- }
163
- ```
164
-
165
- The hook throws if no `PikkuRealtime` was wired — that's how you know to
166
- add it to `createPikku(...)`. Full event-hub setup, publishing, and SSE
167
- helpers live in **pikku-realtime**.
168
-
169
- ## When to reach for what
170
-
171
- | Need | Use |
172
- | ----------------------------------- | --------------------------------------------- |
173
- | Render data, dedupe + cache | **usePikkuQuery** (react-query) |
174
- | Trigger a write, wait for result | **usePikkuMutation** (react-query) |
175
- | Paginate | **usePikkuInfiniteQuery** (react-query) |
176
- | One-off call from an event handler | `usePikkuRPC()` direct |
177
- | Hit a REST endpoint (not RPC) | `usePikkuFetch()` |
178
- | Run a workflow | **pikku-workflows-client** |
179
- | Subscribe to events / SSE / channel | `usePikkuRealtime()` (see **pikku-realtime**) |
180
-
181
- The first three live in your generated `api.gen.ts` (see the
182
- **pikku-react-query** skill). This skill covers the bottom four rows.
183
-
184
- ## Authentication
185
-
186
- Auth is handled at the `PikkuFetch` layer — pass options to `createPikku`
187
- or set headers on the fetch instance after creation. Common pattern:
188
-
189
- ```tsx
190
- const pikku = createPikku(PikkuFetch, PikkuRPC, {
191
- serverUrl: apiUrl(),
192
- fetchOptions: {
193
- onRequest: (req) => {
194
- const token = localStorage.getItem('token')
195
- if (token) req.headers.set('Authorization', `Bearer ${token}`)
196
- },
197
- },
198
- })
199
- ```
200
-
201
- Exact option names depend on the `@pikku/fetch` version — read
202
- `PikkuFetch`'s constructor type if unsure.
203
-
204
- ## What NOT to do
205
-
206
- - Don't instantiate `PikkuFetch`/`PikkuRPC` inside a component — `createPikku`
207
- goes once at the app root, the instance flows through Context.
208
- - Don't call `usePikkuRPC()` outside a `<PikkuProvider>` — it throws.
209
- - Don't write a custom RPC client. The generated one already covers every
210
- exposed function with full types.
211
- - Don't hardcode user-facing strings. Every display string goes through an
212
- i18n token — see **pikku-i18n** for the setup (it's English-only by default).
@@ -1,242 +0,0 @@
1
- ---
2
- name: pikku-react-query
3
- description: 'Use the Pikku auto-generated React Query hooks (`usePikkuQuery`, `usePikkuMutation`, `usePikkuInfiniteQuery`) to call backend RPC functions from a React frontend with full type safety. TRIGGER when: writing React components that need to call a Pikku function, fetch data, mutate data, or paginate; user mentions React Query, useQuery, useMutation, or building a frontend that talks to a Pikku backend. DO NOT TRIGGER when: working on the backend (use pikku-rpc / pikku-feature) or wiring a non-React frontend.'
4
- installGroups: [core]
5
- ---
6
-
7
- # Pikku React Query Hooks
8
-
9
- ## Agent Operating Procedure
10
-
11
- Use this skill as an execution checklist, not reference material.
12
-
13
- 1. Discover before editing. Prefer OpenCode tools such as `pikku-meta` when available; otherwise run the relevant `pikku meta ... --json` command and inspect only the focused output you need.
14
- 2. Identify the source files that own the behavior. Do not start by reading generated output, `.pikku`, `node_modules`, vendored packages, or broad build artifacts.
15
- 3. Make the smallest source change that satisfies the task. Keep generated files generated, and avoid hand-editing SDKs, schema output, or typegen.
16
- 4. Validate with the narrowest relevant command first, then run `pikku-verify` or `pikku all` when functions, wirings, schemas, or generated clients may have changed.
17
- 5. If validation fails, fix the source cause and rerun validation. Do not paper over generated errors by editing generated files.
18
-
19
- Pikku generates a typed React Query layer from your backend `expose: true`
20
- functions. You don''t write `useQuery`/`useMutation` against `fetch`
21
- yourself — you call hooks named after RPCs and get full type inference for
22
- input + output.
23
-
24
- ## Discover what's available on the client
25
-
26
- Before writing a hook, get the full client surface in one call:
27
-
28
- ```bash
29
- yarn pikku meta clients --json
30
- ```
31
-
32
- Returns RPCs, workflows, and channels with descriptions and type names:
33
-
34
- ```json
35
- {
36
- "rpcs": [
37
- { "name": "createTodo", "description": "Create a todo",
38
- "readonly": false, "input": "CreateTodoInput", "output": "CreateTodoOutput" },
39
- { "name": "listTodos", "description": "List all todos",
40
- "readonly": true, "input": null, "output": "ListTodosOutput" }
41
- ],
42
- "workflows": [...],
43
- "channels": [...]
44
- }
45
- ```
46
-
47
- The `name` is the RPC identifier; pass it to the hooks below. Input/output
48
- shapes are inferred automatically — the hook is typed against
49
- `FlattenedRPCMap[name]['input' | 'output']`. Use `description` to pick the
50
- right RPC; use `readonly` to choose `usePikkuQuery` vs `usePikkuMutation`.
51
-
52
- ## Setup (once per app)
53
-
54
- In your app entry (e.g. `main.tsx`):
55
-
56
- ```tsx
57
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
58
- import { PikkuProvider, createPikku } from '@pikku/react'
59
- import { PikkuFetch } from './pikku/pikku-fetch.gen'
60
- import { PikkuRPC } from './pikku/pikku-rpc.gen'
61
-
62
- import { apiUrl } from './lib/env'
63
-
64
- const queryClient = new QueryClient()
65
- const pikku = createPikku(PikkuFetch, PikkuRPC, {
66
- serverUrl: apiUrl(),
67
- })
68
-
69
- <QueryClientProvider client={queryClient}>
70
- <PikkuProvider pikku={pikku}>
71
- <App />
72
- </PikkuProvider>
73
- </QueryClientProvider>
74
- ```
75
-
76
- The two generated files come from `pikku.config.json`'s
77
- `clientFiles.fetchFile` and `clientFiles.rpcWiringsFile`. Hooks live in
78
- the file at `clientFiles.reactQueryFile` (typically `api.gen.ts`).
79
-
80
- `apiUrl()` is the shared server-URL helper — see **pikku-react**. Never
81
- inline `?? 'http://localhost:3000'`: a deploy that supplies the URL as a
82
- runtime binding leaves `import.meta.env.VITE_API_URL` undefined in the
83
- bundle, so the fallback is the branch that actually runs.
84
-
85
- ## TanStack Start (SSR)
86
-
87
- Under Start the provider mounts in `routes/__root.tsx` rather than
88
- `main.tsx`, and the same module is evaluated on the server. Three things
89
- differ:
90
-
91
- 1. **`apiUrl()` must have an SSR branch.** `window` is undefined during
92
- render; return the build-time var or a placeholder (the client hooks
93
- only fire in the browser).
94
- 2. **Build auth clients lazily.** Better Auth validates its baseURL with
95
- `new URL(...)` at construction, so a module-scope `createAuthClient`
96
- crashes SSR on the placeholder. Memoize it behind a getter:
97
-
98
- ```ts
99
- let _authClient: ReturnType<typeof createAuthClient> | undefined
100
- export const authClient = () =>
101
- (_authClient ??= createAuthClient({ baseURL: `${apiUrl()}/auth` }))
102
- ```
103
-
104
- 3. **The auth baseURL needs the `/auth` suffix.** Better Auth only
105
- appends its default `/api/auth` when the baseURL carries no path.
106
- `apiUrl()` already ends in `/api`, so a bare `apiUrl()` leaves the
107
- client calling `/api/get-session` and 404ing.
108
-
109
- Server functions that need typed RPC access use the generated shim:
110
-
111
- ```bash
112
- pikku tanstack-start # emits the makeApi server-function shim
113
- ```
114
-
115
- ## The hooks
116
-
117
- All hooks are imported from your generated `api.gen.ts`:
118
-
119
- ```tsx
120
- import {
121
- usePikkuQuery,
122
- usePikkuMutation,
123
- usePikkuInfiniteQuery,
124
- } from './pikku/api.gen'
125
- ```
126
-
127
- ### `usePikkuQuery(name, data, options?)`
128
-
129
- For RPCs that **read** data. Cacheable. The hook is typed against the RPC's
130
- input + output.
131
-
132
- ```tsx
133
- export function TodoList() {
134
- const { data, isLoading, error } = usePikkuQuery('listTodos', {})
135
-
136
- if (isLoading) return <p>Loading…</p>
137
- if (error) return <p>{error.message}</p>
138
- return (
139
- <ul>
140
- {data?.todos.map((t) => (
141
- <li key={t.id}>{t.title}</li>
142
- ))}
143
- </ul>
144
- )
145
- }
146
- ```
147
-
148
- The query key is `[name, data]` automatically — no manual key wrangling.
149
- Pass standard `useQuery` options through (`staleTime`, `enabled`, etc.).
150
-
151
- ### `usePikkuMutation(name, options?)`
152
-
153
- For RPCs that **write**. Returns a React Query mutation object.
154
-
155
- ```tsx
156
- export function CreateTodoForm() {
157
- const queryClient = useQueryClient()
158
- const mutation = usePikkuMutation('createTodo', {
159
- onSuccess: () => queryClient.invalidateQueries({ queryKey: ['listTodos'] }),
160
- })
161
-
162
- const onSubmit = (e: React.FormEvent<HTMLFormElement>) => {
163
- e.preventDefault()
164
- const title = (
165
- e.currentTarget.elements.namedItem('title') as HTMLInputElement
166
- ).value
167
- mutation.mutate({ title })
168
- }
169
-
170
- return (
171
- <form onSubmit={onSubmit}>
172
- <input name="title" />
173
- <button type="submit" disabled={mutation.isPending}>
174
- {mutation.isPending ? 'Adding…' : 'Add'}
175
- </button>
176
- </form>
177
- )
178
- }
179
- ```
180
-
181
- The input passed to `mutation.mutate(...)` is type-checked against the RPC's
182
- input schema. After success, **invalidate** any list/get queries that should
183
- refetch.
184
-
185
- ### `usePikkuInfiniteQuery(name, data, options?)`
186
-
187
- Only available for RPCs whose output has a `nextCursor?: string | null`
188
- field — typically a list endpoint with pagination. The hook auto-feeds
189
- `nextCursor` into the next page's request.
190
-
191
- ```tsx
192
- const { data, fetchNextPage, hasNextPage, isFetchingNextPage } =
193
- usePikkuInfiniteQuery('listTodos', { limit: 20 })
194
-
195
- const todos = data?.pages.flatMap((p) => p.rows) ?? []
196
- ```
197
-
198
- If the hook isn't generated for an RPC, the RPC's output doesn't include
199
- `nextCursor` — paginate it on the backend or use `usePikkuQuery` with
200
- manual cursor state.
201
-
202
- ## Workflow hooks
203
-
204
- When the project has workflows (`capabilities.workflow: true`), three
205
- extra hooks are generated. See the **pikku-workflows-client** skill.
206
-
207
- ## Calling RPCs without React Query
208
-
209
- For one-off calls (event handlers outside of state, side effects), use
210
- `usePikkuRPC()` from `@pikku/react`:
211
-
212
- ```tsx
213
- const rpc = usePikkuRPC()
214
- const handleClick = async () => {
215
- const result = await rpc.invoke('createTodo', { title: 'inline' })
216
- }
217
- ```
218
-
219
- But prefer the React Query hooks for anything that touches render state —
220
- caching, retries, dedup, and dev-tools come for free.
221
-
222
- ## Common patterns
223
-
224
- - **Optimistic updates**: pass `onMutate` to `usePikkuMutation` to update
225
- the cache before the server responds. Standard React Query pattern;
226
- Pikku doesn't add anything special.
227
- - **Conditional fetching**: pass `enabled: !!someValue` to skip a query
228
- until you have the input.
229
- - **Refetch on focus**: enabled by default in React Query; disable with
230
- `refetchOnWindowFocus: false` in options.
231
-
232
- ## What NOT to do
233
-
234
- - Don't import the RPC client directly and call it inside `useEffect` —
235
- use the hooks. They handle dedup, caching, and unmount safely.
236
- - Don't hand-write `useQuery({ queryKey: ['listTodos'], queryFn: ... })`
237
- — `usePikkuQuery('listTodos', {})` does it correctly with one line.
238
- - Don't construct hook names dynamically. Hook names = RPC names known at
239
- generation time.
240
- - Don't bypass the type system with `as any` — if a hook's types don't
241
- match what you expect, the backend's input/output schemas are wrong;
242
- fix those first.