@pikku/skills 0.12.22 → 0.12.26

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 (106) hide show
  1. package/CHANGELOG.md +134 -0
  2. package/dist/skills.gen.js +1 -1
  3. package/package.json +1 -1
  4. package/skills/pikku-a11y/SKILL.md +59 -0
  5. package/skills/pikku-addon/SKILL.md +2 -2
  6. package/skills/pikku-agent/SKILL.md +67 -316
  7. package/skills/pikku-agent/references/agents.md +299 -0
  8. package/skills/{pikku-ai-vercel/SKILL.md → pikku-agent/references/runner-vercel.md} +2 -24
  9. package/skills/{pikku-ai-voice/SKILL.md → pikku-agent/references/voice.md} +1 -22
  10. package/skills/pikku-architect/SKILL.md +265 -0
  11. package/skills/pikku-auth/SKILL.md +89 -0
  12. package/skills/{pikku-better-auth/SKILL.md → pikku-auth/references/better-auth.md} +126 -34
  13. package/skills/{pikku-jose/SKILL.md → pikku-auth/references/jose.md} +1 -23
  14. package/skills/{pikku-machine-auth/SKILL.md → pikku-auth/references/machine-auth.md} +0 -23
  15. package/skills/pikku-auth/references/permissions.md +261 -0
  16. package/skills/{pikku-security/SKILL.md → pikku-auth/references/sessions.md} +0 -20
  17. package/skills/pikku-build/SKILL.md +88 -0
  18. package/skills/{pikku-build-app/SKILL.md → pikku-build/references/app.md} +76 -24
  19. package/skills/{pikku-feature/SKILL.md → pikku-build/references/feature.md} +1 -8
  20. package/skills/{pikku-build-app → pikku-build}/references/multi-app.md +56 -1
  21. package/skills/{pikku-build-platform/SKILL.md → pikku-build/references/platform.md} +22 -37
  22. package/skills/{pikku-template-clone/SKILL.md → pikku-build/references/post-clone.md} +0 -6
  23. package/skills/{pikku-build-quick/SKILL.md → pikku-build/references/quick.md} +4 -20
  24. package/skills/{pikku-build-app → pikku-build}/references/ship.md +9 -3
  25. package/skills/pikku-concepts/SKILL.md +72 -7
  26. package/skills/pikku-concepts/references/concept-mapping.md +8 -8
  27. package/skills/pikku-deploy/SKILL.md +158 -0
  28. package/skills/{pikku-deploy-azure/SKILL.md → pikku-deploy/references/azure.md} +18 -50
  29. package/skills/pikku-deploy/references/cloudflare.md +104 -0
  30. package/skills/pikku-deploy/references/express.md +92 -0
  31. package/skills/{pikku-deploy-fastify/SKILL.md → pikku-deploy/references/fastify.md} +8 -32
  32. package/skills/{pikku-deploy-lambda/SKILL.md → pikku-deploy/references/lambda.md} +6 -27
  33. package/skills/{pikku-deploy-nextjs/SKILL.md → pikku-deploy/references/nextjs.md} +9 -33
  34. package/skills/pikku-deploy/references/uws.md +72 -0
  35. package/skills/pikku-deploy/references/ws.md +75 -0
  36. package/skills/pikku-emails/SKILL.md +3 -2
  37. package/skills/pikku-fabric/SKILL.md +47 -20
  38. package/skills/{pikku-fabric-debug/SKILL.md → pikku-fabric/references/debugging.md} +0 -6
  39. package/skills/pikku-i18n/SKILL.md +62 -207
  40. package/skills/{pikku-paraglide/SKILL.md → pikku-i18n/references/enum-labels.md} +0 -6
  41. package/skills/pikku-i18n/references/messages.md +218 -0
  42. package/skills/{pikku-rtl/SKILL.md → pikku-i18n/references/rtl.md} +3 -9
  43. package/skills/pikku-knowledge/SKILL.md +15 -0
  44. package/skills/pikku-kysely/SKILL.md +13 -13
  45. package/skills/pikku-list-query/SKILL.md +163 -0
  46. package/skills/pikku-meta/SKILL.md +58 -130
  47. package/skills/{pikku-deps/SKILL.md → pikku-meta/references/audit.md} +1 -17
  48. package/skills/pikku-meta/references/meta.md +114 -0
  49. package/skills/{pikku-versioning/SKILL.md → pikku-meta/references/versioning.md} +0 -26
  50. package/skills/pikku-middleware/SKILL.md +5 -5
  51. package/skills/pikku-n8n-import/SKILL.md +0 -1
  52. package/skills/pikku-permissions/SKILL.md +75 -229
  53. package/skills/pikku-react/SKILL.md +50 -298
  54. package/skills/pikku-react/references/client.md +313 -0
  55. package/skills/{pikku-react-query/SKILL.md → pikku-react/references/react-query.md} +2 -22
  56. package/skills/{pikku-workflows-client/SKILL.md → pikku-react/references/workflows.md} +1 -22
  57. package/skills/pikku-realtime/SKILL.md +110 -251
  58. package/skills/pikku-scenario/SKILL.md +60 -45
  59. package/skills/pikku-scenario/references/persona-run.md +148 -0
  60. package/skills/pikku-seo/SKILL.md +133 -0
  61. package/skills/pikku-service-backends/SKILL.md +154 -0
  62. package/skills/pikku-service-backends/references/aws.md +106 -0
  63. package/skills/pikku-service-backends/references/backblaze.md +57 -0
  64. package/skills/pikku-service-backends/references/mongodb.md +90 -0
  65. package/skills/pikku-service-backends/references/redis.md +75 -0
  66. package/skills/pikku-service-backends/references/schema.md +63 -0
  67. package/skills/pikku-services/SKILL.md +68 -291
  68. package/skills/{pikku-audit/SKILL.md → pikku-services/references/audit.md} +0 -22
  69. package/skills/{pikku-config/SKILL.md → pikku-services/references/config.md} +1 -25
  70. package/skills/{pikku-pino/SKILL.md → pikku-services/references/pino.md} +0 -20
  71. package/skills/pikku-services/references/services.md +272 -0
  72. package/skills/pikku-software-archaeology/README.md +5 -1
  73. package/skills/pikku-software-archaeology/SKILL.md +16 -2
  74. package/skills/{pikku-product-second-opinion/example/sample-report.md → pikku-software-archaeology/example/second-opinion-sample-report.md} +1 -1
  75. package/skills/pikku-software-archaeology/references/blueprint.schema.json +1 -1
  76. package/skills/pikku-software-archaeology/references/pikku-mapping.md +3 -3
  77. package/skills/{pikku-product-second-opinion/SKILL.md → pikku-software-archaeology/references/second-opinion.md} +4 -9
  78. package/skills/pikku-webhook/SKILL.md +224 -0
  79. package/skills/pikku-wiring/SKILL.md +180 -0
  80. package/skills/{pikku-websocket/SKILL.md → pikku-wiring/references/channel.md} +2 -35
  81. package/skills/{pikku-cli/SKILL.md → pikku-wiring/references/cli.md} +1 -33
  82. package/skills/{pikku-gateway-slack/SKILL.md → pikku-wiring/references/gateway-slack.md} +0 -23
  83. package/skills/{pikku-http/SKILL.md → pikku-wiring/references/http.md} +3 -39
  84. package/skills/{pikku-mcp/SKILL.md → pikku-wiring/references/mcp.md} +0 -33
  85. package/skills/{pikku-queue/SKILL.md → pikku-wiring/references/queue.md} +1 -33
  86. package/skills/pikku-wiring/references/realtime.md +265 -0
  87. package/skills/{pikku-rpc/SKILL.md → pikku-wiring/references/rpc.md} +0 -32
  88. package/skills/{pikku-schedule/SKILL.md → pikku-wiring/references/scheduler.md} +1 -35
  89. package/skills/{pikku-trigger/SKILL.md → pikku-wiring/references/trigger.md} +0 -43
  90. package/skills/pikku-workflow/SKILL.md +39 -2
  91. package/skills/pikku-aws/SKILL.md +0 -161
  92. package/skills/pikku-backblaze/SKILL.md +0 -104
  93. package/skills/pikku-deploy-cloudflare/SKILL.md +0 -123
  94. package/skills/pikku-deploy-express/SKILL.md +0 -122
  95. package/skills/pikku-deploy-uws/SKILL.md +0 -144
  96. package/skills/pikku-mongodb/SKILL.md +0 -113
  97. package/skills/pikku-product-second-opinion/README.md +0 -43
  98. package/skills/pikku-redis/SKILL.md +0 -99
  99. package/skills/pikku-schema-ajv/SKILL.md +0 -83
  100. package/skills/pikku-schema-cfworker/SKILL.md +0 -82
  101. package/skills/pikku-ws/SKILL.md +0 -87
  102. /package/skills/{pikku-build-app → pikku-build}/references/theming.md +0 -0
  103. /package/skills/{pikku-product-second-opinion/references/report-template.md → pikku-software-archaeology/references/second-opinion-report-template.md} +0 -0
  104. /package/skills/{pikku-cli/references/complete-example.md → pikku-wiring/references/cli-complete-example.md} +0 -0
  105. /package/skills/{pikku-http → pikku-wiring}/references/http-options.md +0 -0
  106. /package/skills/{pikku-realtime/references/other-routes.md → pikku-wiring/references/realtime-other-routes.md} +0 -0
@@ -1,31 +1,11 @@
1
- ---
2
- name: pikku-deploy-fastify
3
- description: >-
4
- Use when deploying a Pikku app with Fastify. Covers PikkuFastifyServer standalone and
5
- pikkuFastifyPlugin for existing Fastify apps. TRIGGER when: code imports @pikku/fastify or
6
- @pikku/fastify-plugin, user mentions Fastify deployment, or start.ts creates a
7
- PikkuFastifyServer. DO NOT TRIGGER when: just defining functions/wirings without
8
- Fastify-specific code.
9
- ---
10
-
11
- # Pikku Fastify Deployment
12
-
13
- ## Agent Operating Procedure
14
-
15
- Use this skill as an execution checklist, not reference material.
16
-
17
- 1. Discover before editing. Run the relevant `pikku meta ... --json` command and inspect only the focused output you need.
18
- 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.
19
- 3. Make the smallest source change that satisfies the task. Keep generated files generated, and avoid hand-editing SDKs, schema output, or typegen.
20
- 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.
21
- 5. If validation fails, fix the source cause and rerun validation. Do not paper over generated errors by editing generated files.
22
-
23
- ## Standalone Server
1
+ # Fastify
24
2
 
25
3
  ```bash
26
4
  yarn add @pikku/fastify
27
5
  ```
28
6
 
7
+ ## Standalone server
8
+
29
9
  ```typescript
30
10
  import { PikkuFastifyServer } from '@pikku/fastify'
31
11
  import './.pikku/pikku-bootstrap.gen.js'
@@ -43,16 +23,12 @@ await appServer.init()
43
23
  await appServer.start()
44
24
  ```
45
25
 
46
- **Constructor:** `new PikkuFastifyServer(config, logger)`
47
-
48
- **Config extends CoreConfig with:** `port`, `hostname`, `healthCheckPath?`
49
-
50
- **Methods:** `init(httpOptions?: RunHTTPWiringOptions)`, `start()`, `stop()`, `enableExitOnSigInt()`
51
-
52
- **Property:** `app: FastifyInstance` — Direct access to Fastify instance.
26
+ The config extends `CoreConfig` with `port`, `hostname` and an optional
27
+ `healthCheckPath`. `app: FastifyInstance` is exposed for direct access.
53
28
 
54
- `enableCors` exists on the class but **throws `Method not implemented.`** — unlike
55
- the Express server. Register `@fastify/cors` on `app` yourself before `init()`.
29
+ `enableCors` exists on the class but **throws `Method not implemented.`** —
30
+ unlike the Express server. Register `@fastify/cors` on `app` yourself before
31
+ `init()`.
56
32
 
57
33
  Unlike the Express server, the health check is registered by `init()`, not the
58
34
  constructor, so nothing answers before `init` runs. `init` also passes
@@ -1,30 +1,10 @@
1
- ---
2
- name: pikku-deploy-lambda
3
- description: >-
4
- Use when deploying a Pikku app to AWS Lambda. Covers HTTP handlers, scheduled tasks, SQS queue
5
- workers, WebSocket via API Gateway, and cold start caching. TRIGGER when: code imports
6
- @pikku/lambda, user mentions Lambda/serverless/AWS deployment, or handler files export
7
- Lambda-typed functions. DO NOT TRIGGER when: just defining functions/wirings without
8
- Lambda-specific code.
9
- ---
10
-
11
- # Pikku AWS Lambda Deployment
12
-
13
- ## Agent Operating Procedure
14
-
15
- Use this skill as an execution checklist, not reference material.
16
-
17
- 1. Discover before editing. Run the relevant `pikku meta ... --json` command and inspect only the focused output you need.
18
- 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.
19
- 3. Make the smallest source change that satisfies the task. Keep generated files generated, and avoid hand-editing SDKs, schema output, or typegen.
20
- 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.
21
- 5. If validation fails, fix the source cause and rerun validation. Do not paper over generated errors by editing generated files.
1
+ # AWS Lambda
22
2
 
23
3
  ```bash
24
4
  yarn add @pikku/lambda
25
5
  ```
26
6
 
27
- ## Cold Start Pattern
7
+ ## Cold start pattern
28
8
 
29
9
  Cache singleton services across Lambda invocations:
30
10
 
@@ -53,7 +33,7 @@ named exports (`handler`, `queue`, `scheduled`, or `connect`/`disconnect`/
53
33
  `default`) that `serverless.yml` references. Hand-written handlers are for cases
54
34
  the codegen does not cover.
55
35
 
56
- ## HTTP Handler
36
+ ## HTTP handler
57
37
 
58
38
  Pick the entry point that matches the API Gateway payload version — they take
59
39
  different event types and are not interchangeable:
@@ -91,7 +71,7 @@ carried.
91
71
  Neither takes `RunHTTPWiringOptions` — there is no `maxBodySize` or
92
72
  `respondWith404` knob here; API Gateway's own payload limit is the bound.
93
73
 
94
- ## Scheduled Tasks
74
+ ## Scheduled tasks
95
75
 
96
76
  ```typescript
97
77
  import type { ScheduledHandler } from 'aws-lambda'
@@ -113,7 +93,7 @@ Reach for `runScheduledTask({ name })` from `@pikku/core/scheduler` directly
113
93
  only when one Lambda genuinely bundles several tasks that must fire on separate
114
94
  schedules.
115
95
 
116
- ## SQS Queue Worker
96
+ ## SQS queue worker
117
97
 
118
98
  ```typescript
119
99
  import type { SQSHandler } from 'aws-lambda'
@@ -181,8 +161,7 @@ is a separate invocation, so nothing survives in memory between `$connect` and
181
161
  `LambdaEventHubService` handles cross-connection messaging and takes
182
162
  `(logger, event, channelStore, eventHubStore)` — the `event` is needed to derive
183
163
  the API Gateway Management endpoint, so it is constructed per invocation, not
184
- once at cold start. It also needs an `EventHubStore` alongside the channel
185
- store.
164
+ once at cold start. It also needs an `EventHubStore` alongside the channel store.
186
165
 
187
166
  Two behaviours to design around: **binary payloads throw** (`Binary data is not
188
167
  supported on serverless lambdas`), and any `PostToConnection` failure removes
@@ -1,29 +1,10 @@
1
- ---
2
- name: pikku-deploy-nextjs
3
- description: >-
4
- Use when deploying a Pikku app with Next.js. Covers API route handlers, server-side data
5
- fetching, and RPC calls from Server Components. TRIGGER when: code imports @pikku/next, user
6
- mentions Next.js integration, or app/api route files use pikkuAPIRequest. DO NOT TRIGGER when:
7
- just defining functions/wirings without Next.js-specific code.
8
- ---
9
-
10
- # Pikku Next.js Deployment
11
-
12
- ## Agent Operating Procedure
13
-
14
- Use this skill as an execution checklist, not reference material.
15
-
16
- 1. Discover before editing. Run the relevant `pikku meta ... --json` command and inspect only the focused output you need.
17
- 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.
18
- 3. Make the smallest source change that satisfies the task. Keep generated files generated, and avoid hand-editing SDKs, schema output, or typegen.
19
- 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.
20
- 5. If validation fails, fix the source cause and rerun validation. Do not paper over generated errors by editing generated files.
1
+ # Next.js
21
2
 
22
3
  ```bash
23
4
  yarn add @pikku/next
24
5
  ```
25
6
 
26
- ## API Route Handler
7
+ ## API route handler
27
8
 
28
9
  The CLI generates a typed wrapper. Use it in a catch-all route:
29
10
 
@@ -49,7 +30,7 @@ choose. It also passes no `RunHTTPWiringOptions`: to set `maxBodySize` or
49
30
  `respondWith404` you need your own handler over `new PikkuNextJS(...)` calling
50
31
  `apiRequest(req, options)`.
51
32
 
52
- ## Server-Side Data Fetching
33
+ ## Server-side data fetching
53
34
 
54
35
  Use the generated `pikku()` helper in Server Components or Server Actions:
55
36
 
@@ -69,12 +50,9 @@ const config = await staticGet('/config')
69
50
  const result = await rpc('calculateTax', { amount: 100, region: 'US' })
70
51
  ```
71
52
 
72
- **Dynamic vs Static:**
73
-
74
- - `get`, `post`, `patch`, `del`, `rpc` — read `next/headers` cookies and headers,
75
- so they force the component dynamic
76
- - `staticGet`, `staticPost`, `staticRPC` — no request context, safe for
77
- precompile/ISR
53
+ `get`, `post`, `patch`, `del` and `rpc` read `next/headers` cookies and headers,
54
+ so they force the component dynamic. `staticGet`, `staticPost` and `staticRPC`
55
+ have no request context and are safe for precompile/ISR.
78
56
 
79
57
  The static variants pass `skipUserSession: true`, so a wiring that expects a
80
58
  session sees none. That is the real difference — not just where they can run.
@@ -85,7 +63,7 @@ Both paths run with `bubbleErrors: true`, so a failing wiring **throws** in your
85
63
  Server Component rather than resolving to an error status. Wrap the call, or let
86
64
  the Next.js error boundary take it.
87
65
 
88
- ## How It Works
66
+ ## How it works
89
67
 
90
68
  `PikkuNextJS` lazy-initializes on first request:
91
69
 
@@ -95,8 +73,6 @@ import { PikkuNextJS } from '@pikku/next'
95
73
  const pikku = new PikkuNextJS(createConfig, createSingletonServices)
96
74
  ```
97
75
 
98
- **Constructor:** `new PikkuNextJS(createConfig | undefined, createSingletonServices)`
99
-
100
76
  Both arguments are positional and `createConfig` is only optional in the sense
101
77
  that passing `undefined` substitutes an empty config —
102
78
  `createSingletonServices` is required.
@@ -113,8 +89,8 @@ route definitions.
113
89
  - **`PikkuNextJSWorkerRPC({ fetcher })`** — same surface as `PikkuNextJS`, but
114
90
  every call is dispatched through a `Fetcher` (a Cloudflare service binding, a
115
91
  local HTTP client, a fabric dispatcher) instead of loading function code
116
- in-process. Use it to keep functions out of the SSR bundle. A non-2xx
117
- response throws with the status and body text.
92
+ in-process. Use it to keep functions out of the SSR bundle. A non-2xx response
93
+ throws with the status and body text.
118
94
  - **`toNextJsAuthHandler(auth)`** — wraps a better-auth instance or handler
119
95
  function for an auth route. The three-argument form
120
96
  `(pikkuAuthFactory, createConfig, createSingletonServices)` resolves a Pikku
@@ -0,0 +1,72 @@
1
+ # uWebSockets.js
2
+
3
+ Highest-throughput option among Pikku's runtimes. Handles both HTTP and
4
+ WebSocket automatically.
5
+
6
+ ```bash
7
+ yarn add @pikku/uws
8
+ ```
9
+
10
+ ```typescript
11
+ import { PikkuUWSServer } from '@pikku/uws'
12
+ import './.pikku/pikku-bootstrap.gen.js'
13
+ import { createConfig, createSingletonServices } from './services.js'
14
+
15
+ const config = await createConfig()
16
+ const singletonServices = await createSingletonServices(config)
17
+
18
+ const appServer = new PikkuUWSServer(
19
+ { ...config, hostname: 'localhost', port: 4002 },
20
+ singletonServices.logger
21
+ )
22
+ appServer.enableExitOnSigInt()
23
+ await appServer.init()
24
+ await appServer.start()
25
+ ```
26
+
27
+ The config extends `CoreConfig` with `port`, `hostname` and an optional
28
+ `healthCheckPath`. `app: uWS.App` is exposed for direct access.
29
+
30
+ ## What the server does and does not give you
31
+
32
+ `init()` registers three things in order: the health check (`healthCheckPath`,
33
+ default `/health-check`), a catch-all `app.any('/*')` HTTP handler, and a
34
+ catch-all `app.ws('/*')` websocket handler. Nothing is registered by the
35
+ constructor, so nothing answers before `init` runs.
36
+
37
+ **There is no `enableCors`, no static assets and no `content` support** — unlike
38
+ the Express server. The class is explicitly a prototyping convenience; for
39
+ anything that needs extra handlers, use `@pikku/uws-handler` directly and treat
40
+ `pikku-uws-server.ts` as the template (that is what its own JSDoc says).
41
+
42
+ `httpOptions` reaches the HTTP handler only. The websocket handler is
43
+ constructed with a fixed `{ logger, logRoutes: true }`, so per-request options
44
+ do not apply to the upgrade path. `loadSchemas` is also never passed by the
45
+ server, so schemas compile lazily on first use rather than at startup — pass
46
+ `loadSchemas: true` in `httpOptions` if you want the startup cost paid up front.
47
+
48
+ `stop()` closes the listen socket and then waits a fixed 2 seconds for
49
+ connections to drain. Called before `start()`, it throws a bare **string**, not
50
+ an `Error`, so `catch (e) { e.message }` reads `undefined`.
51
+
52
+ ## Body limits
53
+
54
+ uWS hands over raw chunks with no limit of its own, so the handler counts the
55
+ bytes itself. A request over `maxBodySize` (default `DEFAULT_MAX_BODY_SIZE`) is
56
+ answered `413` with a `PayloadTooLargeError` body, and the chunks are dropped
57
+ rather than concatenated — an oversized request never accumulates in memory. A
58
+ `content-length` header that already exceeds the limit short-circuits before any
59
+ data arrives.
60
+
61
+ ## Handlers directly (own uWS app)
62
+
63
+ ```typescript
64
+ import { pikkuHTTPHandler, pikkuWebsocketHandler } from '@pikku/uws-handler'
65
+
66
+ app.any('/*', pikkuHTTPHandler({ logger, logRoutes: true, loadSchemas: true }))
67
+ app.ws('/*', pikkuWebsocketHandler({ logger, logRoutes: true }))
68
+ ```
69
+
70
+ Both take `{ logger, logRoutes?, loadSchemas? } & RunHTTPWiringOptions`.
71
+
72
+ For a WebSocket-only server on the `ws` library instead, see `ws.md`.
@@ -0,0 +1,75 @@
1
+ # ws (WebSocket only)
2
+
3
+ `@pikku/ws` connects Pikku's channel system to a Node.js WebSocket server built
4
+ on the [ws](https://github.com/websockets/ws) library. Use it for a
5
+ WebSocket-only server; for HTTP and WebSocket on one port see `uws.md`, and when
6
+ the WebSocket server shares a port with an existing HTTP app see `express.md` or
7
+ `fastify.md`.
8
+
9
+ ```bash
10
+ yarn add @pikku/ws ws
11
+ ```
12
+
13
+ The package exports one function, `pikkuWebsocketHandler` — there is no server
14
+ class. You own the `http.Server` and the `WebSocketServer`; the handler attaches
15
+ the upgrade and message plumbing to them.
16
+
17
+ ```typescript
18
+ import { DEFAULT_WS_MAX_PAYLOAD, pikkuWebsocketHandler } from '@pikku/ws'
19
+ import { stopSingletonServices } from '@pikku/core'
20
+ import { Server } from 'http'
21
+ import { WebSocketServer } from 'ws'
22
+
23
+ import './.pikku/pikku-bootstrap.gen.js'
24
+ import { createConfig, createSingletonServices } from './services.js'
25
+
26
+ const config = await createConfig()
27
+ const singletonServices = await createSingletonServices(config)
28
+
29
+ const server = new Server()
30
+ const wss = new WebSocketServer({
31
+ noServer: true,
32
+ maxPayload: DEFAULT_WS_MAX_PAYLOAD,
33
+ })
34
+
35
+ pikkuWebsocketHandler({
36
+ server,
37
+ wss,
38
+ logger: singletonServices.logger,
39
+ logRoutes: true, // print the wired channels at startup
40
+ loadSchemas: true, // compile input schemas up front
41
+ })
42
+
43
+ server.listen(4002, 'localhost')
44
+
45
+ process.on('SIGINT', async () => {
46
+ await stopSingletonServices()
47
+ wss.close()
48
+ server.close()
49
+ process.exit(0)
50
+ })
51
+ ```
52
+
53
+ ## `noServer: true` is required, not stylistic
54
+
55
+ The handler listens for the HTTP server's own `upgrade` event, opens the channel
56
+ — running Pikku's middleware chain, auth and CORS against the upgrade request
57
+ first — and only then calls `wss.handleUpgrade`. A `WebSocketServer` bound to the
58
+ server directly would take the socket before any of that ran.
59
+
60
+ An upgrade the channel rejects gets the socket destroyed, and an auth failure is
61
+ written as a real HTTP response on the raw socket rather than a silent drop.
62
+
63
+ ## Services and the event hub
64
+
65
+ Services come from the bootstrap import and the global singleton registry, which
66
+ is why nothing is passed in. The event hub is taken from
67
+ `singletonServices.eventHub` when it is a `LocalEventHubService`, and a local one
68
+ is created otherwise — so a single-process app gets pub/sub for free, while a
69
+ multi-instance deployment must register a distributed hub.
70
+
71
+ The options type also extends `RunHTTPWiringOptions`, so per-request settings
72
+ such as `respondWith404`, `coerceDataFromSchema` and `bubbleErrors` are accepted
73
+ here too.
74
+
75
+ On shutdown, call `stopSingletonServices()` then close `wss` and `server`.
@@ -9,8 +9,8 @@ description: >-
9
9
  or emailTemplatesDir in pikku.config.json. TRIGGER when: user asks to add/edit a transactional
10
10
  email (verification, password reset, invitation, receipt), wire email sending, or translate an
11
11
  email. DO NOT TRIGGER when: user asks about i18n for the app UI (use pikku-i18n) or auth flows
12
- in general (use pikku-better-auth).
13
- installGroups: [fabric]
12
+ in general (use pikku-auth).
13
+ installGroups: [core]
14
14
  ---
15
15
 
16
16
  # Pikku Emails
@@ -187,6 +187,7 @@ async send(input: SendEmailInput) {
187
187
  const r = renderEmailTemplate(input.template as RenderEmailInput<EmailTemplateName>)
188
188
  return this.delegate.send({
189
189
  to: input.to, from: input.from, subject: r.subject, html: r.html,
190
+ attachments: input.attachments,
190
191
  ...(r.text ? { text: r.text } : {}),
191
192
  })
192
193
  }
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: pikku-fabric
3
- description: 'Build and convert apps for the Pikku Fabric platform. Covers SQLite/libSQL database setup with Kysely, fabric project layout, deploy provider config, `fabric.config.json`, and the pikku-verify workflow. TRIGGER when: user is working on a Fabric-hosted Pikku project, converting an app to Fabric format, or asking about Fabric deployment, database, or project conventions. TRIGGER when: user asks about a `pikku fabric validate` finding, including app-missing-actor-quick-login. DO NOT TRIGGER when: user is working on a generic (non-Fabric) Pikku deployment — use pikku-deploy-cloudflare, pikku-deploy-fastify, etc. instead.'
3
+ description: 'Build, convert and debug apps on the Pikku Fabric platform. Covers SQLite/libSQL database setup with Kysely, fabric project layout, deploy provider config, `fabric.config.json`, the pikku-verify workflow, and reading logs, traces and metrics from a deployed stage. TRIGGER when: user is working on a Fabric-hosted Pikku project, converting an app to Fabric format, asking about Fabric deployment, database or project conventions, asking about a `pikku fabric validate` finding including app-missing-actor-quick-login, or a deployed stage is erroring, timing out or behaving differently than local ("why is prod failing", "check the logs"). DO NOT TRIGGER when: user is working on a generic (non-Fabric) Pikku deployment — use pikku-deploy instead — or the failure reproduces locally, which is where to debug it.'
4
4
  installGroups: [fabric]
5
5
  ---
6
6
 
@@ -21,7 +21,7 @@ Use this skill as an execution checklist, not reference material.
21
21
  5. 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
22
  6. If validation fails, fix the source cause and rerun validation. Do not paper over generated errors by editing generated files.
23
23
 
24
- Fabric is a serverless deployment platform for Pikku apps. Every Fabric app runs on Cloudflare Workers with a SQLite database (via libSQL/Turso). This skill covers what's unique to Fabric. For general Pikku concepts, function authoring, HTTP wiring, and more, see `pikku-concepts`, `pikku-http`, `pikku-services`, etc.
24
+ Fabric is a serverless deployment platform for Pikku apps. Every Fabric app runs on Cloudflare Workers with a SQLite database (via libSQL/Turso). This skill covers what's unique to Fabric. For general Pikku concepts, function authoring, HTTP wiring, and more, see `pikku-concepts`, `pikku-wiring`, `pikku-services`, etc.
25
25
 
26
26
  ## Before you start
27
27
 
@@ -291,24 +291,40 @@ reload).
291
291
  pikku fabric login # opens a browser; needs a human, wait for it
292
292
  pikku fabric init https://github.com/<owner>/<repo>
293
293
  pikku fabric validate # must pass clean
294
- pikku fabric deploy apply --production --sync --auto-approve
294
+ pikku fabric deploy apply --production -y
295
295
  ```
296
296
 
297
+ The branch is positional and defaults to the checked-out one, and `-y` is the
298
+ short form of `--auto-approve`, so a one-shot deploy is:
299
+
300
+ ```bash
301
+ pikku fabric deploy apply -y # the branch you are standing on
302
+ pikku fabric deploy apply my-branch -y # a named one
303
+ ```
304
+
305
+ `-y` answers the prompts and nothing more. It does **not** approve migrations
306
+ that drop or rewrite data — that stays `--allow-destructive`, typed out on
307
+ purpose.
308
+
309
+ Inferring the branch is safe because the git safety check refuses any branch
310
+ without an upstream or out of sync with it, so it cannot ship an unpushed
311
+ commit; the branch it picked is printed before the build starts. A detached
312
+ HEAD is refused by name rather than travelling on as a branch called `HEAD`.
313
+
297
314
  There is no `deploy plan` subcommand — `apply` runs the same auth, git-safety
298
315
  and ref resolution itself, and fabric produces the real plan server-side.
299
316
 
300
317
  `apply` confirms before deploying, and with no TTY to ask — CI, an agent shell —
301
- it refuses rather than hangs. `--auto-approve` supplies that confirmation; drop
302
- it only when a human is at a real terminal.
318
+ it refuses rather than hangs. `--auto-approve` (`-y`) supplies that confirmation;
319
+ drop it only when a human is at a real terminal.
303
320
 
304
- By default `apply` queues the deploy, prints the deployment id and returns. That
305
- tells you nothing about whether it worked. `--sync` waits for a terminal state
306
- and exits non-zero unless the deployment went live, which is the only form worth
307
- running in CI:
321
+ `apply` waits for a terminal state and exits non-zero unless the deployment went
322
+ live. `--detach` opts out — it queues the deploy, prints the deployment id and
323
+ returns 0, which tells you nothing about whether it worked:
308
324
 
309
325
  | exit | meaning |
310
326
  | ---- | ----------------------------------------------------------------------- |
311
- | 0 | live (or queued, without `--sync`) |
327
+ | 0 | live (or queued, under `--detach`) |
312
328
  | 1 | the command could not run — not logged in, unsafe git state, bad flags |
313
329
  | 2 | the deployment failed, errored, timed out server-side, or was cancelled |
314
330
  | 3 | the deployment is blocked and nothing the CLI can do will unblock it |
@@ -318,14 +334,14 @@ Fabric parks every deploy at a gate after the plan phase (`status: suspended`).
318
334
  Why it parked is the whole story, and it is `statusReason`, not `status`:
319
335
 
320
336
  - `awaiting_approval` — the plan is fine, a human has to publish it.
321
- `--auto-approve` does that; without it you get exit 3 and the command to run.
337
+ `-y` does that; without it you get exit 3 and the command to run.
322
338
  One exception: if fabric marked any pending migration **destructive** — a
323
- drop, a truncate, a rewrite — `--auto-approve` alone declines and exits 3,
339
+ drop, a truncate, a rewrite — `-y` alone declines and exits 3,
324
340
  because a standing yes was given before anyone knew the plan dropped a table.
325
341
  The CLI lists the migrations and fabric's reasons; `--allow-destructive`
326
- accepts them for that deploy.
342
+ accepts them for that deploy, and `-y` implies it.
327
343
  - `needs_config` — a declared secret or variable has no value covering the
328
- stage. The CLI names them. `--auto-approve` will **not** force this through;
344
+ stage. The CLI names them. `-y` will **not** force this through;
329
345
  set the values and re-attach — `pikku fabric secrets set <name>` for a
330
346
  declared secret, `pikku fabric variables set <name> --value <v>` for a declared
331
347
  variable. They are separate stores: a secret is sealed to the stage and cannot
@@ -334,24 +350,25 @@ Why it parked is the whole story, and it is `statusReason`, not `status`:
334
350
  stage exactly as it is from `.env`, and `--value '"true"'` is the string.
335
351
  - `needs_attention` — the plan is red. Nothing to approve.
336
352
 
337
- `--sync` defaults to a 900s ceiling; `--timeout <seconds>` moves it. On timeout
353
+ The wait defaults to a 900s ceiling; `--timeout <seconds>` moves it. On timeout
338
354
  it prints the deployment id and the re-attach command rather than lying about
339
355
  the outcome.
340
356
 
341
357
  Splitting kick-off from waiting across two CI jobs is the reason
342
- `--deployment-id` exists:
358
+ `--deployment-id` exists, and what `--detach` is for — the first job here has to
359
+ return the id and exit rather than wait:
343
360
 
344
361
  ```bash
345
- id=$(pikku fabric deploy apply --production --auto-approve --json | jq -r 'select(.event=="result").deploymentId')
362
+ id=$(pikku fabric deploy apply --production -y --detach --json | jq -r 'select(.event=="result").deploymentId')
346
363
  # …later, in another job…
347
- pikku fabric deploy apply --deployment-id "$id" --sync --auto-approve
364
+ pikku fabric deploy apply --deployment-id "$id" -y
348
365
  ```
349
366
 
350
367
  `--deployment-id` skips the git safety check entirely (the deployment already
351
368
  pins a sha, and the checkout is allowed to have moved on) and refuses to be
352
- combined with `--branch`/`--production`, which would let the two disagree.
369
+ combined with a branch or `--production`, which would let the two disagree.
353
370
 
354
- Under `--json`, `--sync` emits one NDJSON event per line — `created`/`attached`,
371
+ Under `--json`, the wait emits one NDJSON event per line — `created`/`attached`,
355
372
  `status` on each transition, `blocked`, `approved` — and the last line is the
356
373
  terminal result object, tagged `"event": "result"`.
357
374
 
@@ -440,3 +457,13 @@ Fix every `error` and `warn` in the output before continuing. Then:
440
457
  6. **Add `pikkufabric.config.json`** at project root with `projectId`, `production.domain`, and `frontends` (production is always `main`, so there is no `production.branch`).
441
458
  7. **Run `pikku all`** — verify codegen succeeds and there are no type errors.
442
459
  8. **Run `pikku fabric validate`** once more to confirm no structural issues remain.
460
+
461
+ ## A deployed stage misbehaving
462
+
463
+ Reproduce locally first — a deployed stage adds cost and latency to every
464
+ iteration, and a failure that reproduces locally is a local debugging problem.
465
+ When it only happens deployed, read `references/debugging.md`: start from
466
+ `errors` rather than `logs` (they are already filtered and carry the traceId),
467
+ follow one trace end to end before forming a theory, and confirm the fix against
468
+ the same stage. A deploy that *failed* is a build or config problem and belongs
469
+ above, not there.
@@ -1,9 +1,3 @@
1
- ---
2
- name: pikku-fabric-debug
3
- description: 'Debug a deployed Fabric stage from the CLI — read logs, find recent errors, follow a single request end-to-end by traceId, and check request/error/latency metrics. TRIGGER when: a deployed Fabric app is erroring, timing out, or behaving differently than local; the user asks "why is prod failing", "check the logs", "what happened to this request"; or a deploy succeeded but the app misbehaves. DO NOT TRIGGER when: the failure reproduces locally (debug it locally), the deploy itself failed (use pikku-fabric — that is a build/config problem, not a runtime one), or the project is not deployed to Fabric.'
4
- installGroups: [fabric]
5
- ---
6
-
7
1
  # Debugging a deployed Fabric stage
8
2
 
9
3
  ## Agent Operating Procedure