@pikku/skills 0.12.58 → 0.12.60
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.
- package/dist/skills.gen.js +2 -2
- package/package.json +10 -7
- package/skills/pikku-a11y/SKILL.md +5 -3
- package/skills/pikku-addon/SKILL.md +8 -9
- package/skills/pikku-addon/references/addon-package-manifest.md +53 -0
- package/skills/pikku-agent/SKILL.md +16 -13
- package/skills/pikku-agent/references/runner-vercel.md +1 -1
- package/skills/pikku-architect/SKILL.md +7 -10
- package/skills/pikku-auth/SKILL.md +16 -20
- package/skills/pikku-auth/references/better-auth.md +74 -37
- package/skills/pikku-auth/references/sessions.md +8 -0
- package/skills/pikku-build/SKILL.md +36 -68
- package/skills/pikku-build/references/app.md +27 -828
- package/skills/pikku-build/references/feature.md +3 -5
- package/skills/pikku-build/references/phase-1-what-it-is.md +167 -0
- package/skills/pikku-build/references/phase-2-people-and-apps.md +133 -0
- package/skills/pikku-build/references/phase-3-plan.md +62 -0
- package/skills/pikku-build/references/phase-4-build.md +253 -0
- package/skills/pikku-build/references/phase-5-prove-and-ship.md +148 -0
- package/skills/pikku-build/references/platform.md +5 -6
- package/skills/pikku-build/references/quick.md +2 -2
- package/skills/pikku-build/references/ship.md +11 -5
- package/skills/pikku-changes/SKILL.md +13 -7
- package/skills/pikku-concepts/SKILL.md +26 -258
- package/skills/pikku-concepts/references/cli.md +63 -0
- package/skills/pikku-concepts/references/functions.md +117 -0
- package/skills/pikku-concepts/references/language.md +5 -5
- package/skills/pikku-concepts/references/packages.md +6 -4
- package/skills/pikku-concepts/references/testing.md +14 -0
- package/skills/pikku-convert-screen/SKILL.md +7 -1
- package/skills/pikku-deploy/SKILL.md +29 -30
- package/skills/pikku-deploy/references/ws.md +1 -1
- package/skills/pikku-emails/SKILL.md +7 -3
- package/skills/pikku-guide/SKILL.md +7 -10
- package/skills/pikku-i18n/SKILL.md +18 -19
- package/skills/pikku-i18n/references/messages.md +6 -8
- package/skills/pikku-knowledge/SKILL.md +42 -45
- package/skills/pikku-kysely/SKILL.md +50 -13
- package/skills/pikku-list-query/SKILL.md +27 -14
- package/skills/pikku-meta/SKILL.md +13 -16
- package/skills/pikku-meta/references/audit.md +1 -45
- package/skills/pikku-meta/references/versioning.md +1 -1
- package/skills/pikku-middleware/SKILL.md +23 -13
- package/skills/pikku-middleware/references/middleware-patterns.md +2 -2
- package/skills/pikku-n8n-import/SKILL.md +7 -8
- package/skills/pikku-permissions/SKILL.md +14 -8
- package/skills/pikku-react/SKILL.md +7 -6
- package/skills/pikku-realtime/SKILL.md +16 -11
- package/skills/pikku-report/SKILL.md +8 -10
- package/skills/pikku-scenario/SKILL.md +8 -12
- package/skills/pikku-scenario/references/steps.md +3 -4
- package/skills/pikku-scenario/references/virtual-users.md +1 -1
- package/skills/pikku-seo/SKILL.md +16 -8
- package/skills/pikku-service-backends/SKILL.md +26 -28
- package/skills/pikku-services/SKILL.md +8 -9
- package/skills/pikku-services/references/services.md +1 -1
- package/skills/pikku-software-archaeology/README.md +12 -1
- package/skills/pikku-software-archaeology/SKILL.md +9 -2
- package/skills/pikku-software-archaeology/references/pikku-mapping.md +1 -1
- package/skills/pikku-software-archaeology/references/sources/express.md +75 -0
- package/skills/pikku-software-archaeology/references/sources/laravel.md +77 -0
- package/skills/pikku-software-archaeology/references/sources/nestjs.md +73 -0
- package/skills/pikku-software-archaeology/references/sources/rails.md +72 -0
- package/skills/pikku-software-archaeology/references/tests-to-scenarios.md +72 -0
- package/skills/pikku-tailwind/SKILL.md +15 -16
- package/skills/pikku-theme/SKILL.md +15 -17
- package/skills/pikku-ui/SKILL.md +4 -3
- package/skills/pikku-webhook/SKILL.md +10 -11
- package/skills/pikku-wiring/SKILL.md +45 -47
- package/skills/pikku-wiring/references/channel.md +1 -1
- package/skills/pikku-wiring/references/scheduler.md +1 -1
- package/skills/pikku-wiring/references/trigger.md +24 -1
- package/skills/pikku-workflow/SKILL.md +7 -8
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# The Pikku CLI commands
|
|
2
|
+
|
|
3
|
+
`pikku doc` is the API surface — the `#pikku/*` exports. It does **not** list
|
|
4
|
+
commands, so this table is where they exist. `pikku <command> --help` has the
|
|
5
|
+
flags; the "Read" column is the skill that teaches the thing, where one does.
|
|
6
|
+
|
|
7
|
+
**Generating**
|
|
8
|
+
|
|
9
|
+
| Command | What it does | Read |
|
|
10
|
+
| ------------------------------------------ | ---------------------------------------------------- | ----------------------------- |
|
|
11
|
+
| `all` | Everything: types, schemas, wirings, clients | this skill |
|
|
12
|
+
| `bootstrap` | Type files only (the setup phase) | this skill |
|
|
13
|
+
| `schemas` | JSON Schemas for function input/output types | this skill |
|
|
14
|
+
| `fetch` / `websocket` / `rpc` / `realtime` | One client each, when you do not want `all` | `pikku-wiring`, `pikku-react` |
|
|
15
|
+
| `react-query` / `tanstack-start` | React Query hooks; the TanStack Start `makeApi` shim | `pikku-react` |
|
|
16
|
+
| `queue-service` | The queue service wrapper | `pikku-wiring` |
|
|
17
|
+
| `openapi` | An OpenAPI spec from the HTTP routes | — |
|
|
18
|
+
| `nextjs` | Next.js backend and HTTP wrappers | `pikku-deploy` |
|
|
19
|
+
| `new` | Scaffold a function or wiring | `pikku-wiring` |
|
|
20
|
+
| `enable` | Turn a Pikku feature on | `pikku-build` |
|
|
21
|
+
| `import` | Import workflows from another system | `pikku-n8n-import` |
|
|
22
|
+
|
|
23
|
+
**Running**
|
|
24
|
+
|
|
25
|
+
| Command | What it does | Read |
|
|
26
|
+
| --------------------------------- | ------------------------------------------------------------------------------ | -------------------------------------------- |
|
|
27
|
+
| `dev` | Local dev server, all services wired, watch + HMR | `pikku-build` |
|
|
28
|
+
| `serve` | Bundled bun/node runner — no watch, no codegen | `pikku-deploy` |
|
|
29
|
+
| `watch` | Regenerate on file change, without a server | — |
|
|
30
|
+
| `scenario list\|run` | Scenarios as e2e tests and health checks | `pikku-scenario` |
|
|
31
|
+
| `virtual-user run` | A declared virtual user, model-driven, against a stage | `pikku-scenario`, virtual-user-run reference |
|
|
32
|
+
| `virtual-user list\|sync\|secret` | Who is declared; what an environment will provision; minting their credentials | `pikku-scenario`, virtual-user-run reference |
|
|
33
|
+
| `db` | Local development database | `pikku-kysely` |
|
|
34
|
+
|
|
35
|
+
**Inspecting and evolving**
|
|
36
|
+
|
|
37
|
+
| Command | What it does | Read |
|
|
38
|
+
| ---------------------- | ----------------------------------------------------------------------- | ---------------------------- |
|
|
39
|
+
| `doc` | The installed API surface | this skill |
|
|
40
|
+
| `meta` / `info` | What the project declares, machine- and human-readable | `pikku-meta` |
|
|
41
|
+
| `validate` | Every check that applies — app structure, an addon's published file set | `pikku-build`, `pikku-addon` |
|
|
42
|
+
| `versions` / `release` | Contract hashes, breaking-change detection, versioned releases | `pikku-meta` |
|
|
43
|
+
| `audit` / `update` | Advisories; which `@pikku/*` can move and what peers that needs | `pikku-meta` |
|
|
44
|
+
| `scopes` / `roles` | Declared authorization scopes; roles from `defineSystemRole` | `pikku-auth` |
|
|
45
|
+
| `knowledge` | The knowledge base — what this app is, in its users' language | `pikku-knowledge` |
|
|
46
|
+
| `emails` | Email template generation | `pikku-emails` |
|
|
47
|
+
|
|
48
|
+
**Shipping, and the CLI itself**
|
|
49
|
+
|
|
50
|
+
| Command | What it does | Read |
|
|
51
|
+
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -------------- |
|
|
52
|
+
| `deploy` | Deploy to cloud infrastructure | `pikku-deploy` |
|
|
53
|
+
| `binary` | Compile an entrypoint to a native binary (`bun build --compile`) | — |
|
|
54
|
+
| `dist` | Copy what `tsc` cannot emit — `.gen.json` meta, hand-authored `.d.ts` — into the build output. Run it after `tsc`, as a package's build script | — |
|
|
55
|
+
| `login` / `logout` / `whoami` | The CLI's session against a pikku server | — |
|
|
56
|
+
| `skills` | Install these skills into an agent (Claude Code, opencode, pi) | — |
|
|
57
|
+
|
|
58
|
+
`-c/--config`, `--log-level`, `--json` and the filter flags are **global
|
|
59
|
+
options**, not commands — they attach to the generating commands above.
|
|
60
|
+
|
|
61
|
+
A dash means no skill covers it beyond this line. `--help` is then the whole of
|
|
62
|
+
it — which is a reason to read `--help` rather than to assume the command does
|
|
63
|
+
what its name suggests.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Functions and schemas
|
|
2
|
+
|
|
3
|
+
## Functions
|
|
4
|
+
|
|
5
|
+
Three main function types:
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
// Requires authentication — receives session in wire context.
|
|
9
|
+
// input/output are Zod schemas; the data + return types are inferred from them.
|
|
10
|
+
const updateTodo = pikkuFunc({
|
|
11
|
+
input: UpdateTodoInput,
|
|
12
|
+
output: TodoOutput,
|
|
13
|
+
func: async (services, data, wire) => {
|
|
14
|
+
const { session } = wire
|
|
15
|
+
return services.todoStore.update(data.id, data)
|
|
16
|
+
},
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
// No authentication required
|
|
20
|
+
const listTodos = pikkuSessionlessFunc({
|
|
21
|
+
input: ListTodosInput,
|
|
22
|
+
output: TodoListOutput,
|
|
23
|
+
func: async (services, data) => {
|
|
24
|
+
return { todos: services.todoStore.list(data.filters) }
|
|
25
|
+
},
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
// No input or output (for scheduled tasks, lifecycle hooks)
|
|
29
|
+
const cleanup = pikkuVoidFunc(async (services) => {
|
|
30
|
+
services.todoStore.cleanOldItems()
|
|
31
|
+
})
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Services can be destructured inline in the `func` signature (e.g. `async ({ logger, todoStore }, { title }) => ...`). Full config options:
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
pikkuFunc({
|
|
38
|
+
// Identity and documentation — prose, so it follows `metaLocale` in
|
|
39
|
+
// pikku.config.json (default `en`). The identifier does not; see
|
|
40
|
+
// "What Language You Write In".
|
|
41
|
+
title?: string, // Human-readable name
|
|
42
|
+
description?: string, // What the function does
|
|
43
|
+
version?: number, // Contract version (see pikku-meta)
|
|
44
|
+
override?: string, // Logical name override, so several exports share a versioned base
|
|
45
|
+
tags?: string[], // For grouping and middleware targeting
|
|
46
|
+
|
|
47
|
+
// Contract
|
|
48
|
+
input?: ZodSchema, // Input validation schema
|
|
49
|
+
output?: ZodSchema, // Output validation schema
|
|
50
|
+
errors?: Array<typeof PikkuError>, // Errors this function may throw
|
|
51
|
+
|
|
52
|
+
// Reachability
|
|
53
|
+
expose?: boolean, // Allow external RPC calls (see pikku-wiring)
|
|
54
|
+
remote?: boolean, // Allow remote RPC calls
|
|
55
|
+
mcp?: boolean, // Expose as MCP tool (see pikku-wiring)
|
|
56
|
+
readonly?: boolean, // Declares the function performs no writes
|
|
57
|
+
deploy?: 'serverless' | 'server' | 'auto',
|
|
58
|
+
|
|
59
|
+
// Authorization — see pikku-auth
|
|
60
|
+
auth?: boolean, // Override default auth requirement
|
|
61
|
+
scopes?: ScopeId[], // AND-ed, checked before permissions; session required
|
|
62
|
+
permissions?: PermissionGroup, // OR-ed pool
|
|
63
|
+
permissionsInBody?: boolean, // Last resort; needs allow.permissionsInBody in config
|
|
64
|
+
middleware?: PikkuMiddleware[], // See pikku-middleware
|
|
65
|
+
|
|
66
|
+
// Agent tooling — see pikku-agent
|
|
67
|
+
approvalRequired?: boolean,
|
|
68
|
+
approvalDescription?: (services, data) => Promise<string>,
|
|
69
|
+
|
|
70
|
+
// Workflow step behavior — see pikku-workflow
|
|
71
|
+
workflowQueued?: boolean, // Dispatch via queue instead of inline
|
|
72
|
+
workflowRetries?: number,
|
|
73
|
+
workflowTimeout?: string, // e.g. '30s', '5m'
|
|
74
|
+
|
|
75
|
+
audit?: boolean | { durability?: 'best-effort' | 'transactional' },
|
|
76
|
+
|
|
77
|
+
func: async (services, data, wire) => { ... },
|
|
78
|
+
})
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`scopes` is the one option `pikkuSessionlessFunc` does not accept, and the
|
|
82
|
+
omission is deliberate: scopes are AND-ed and fail closed, so an anonymous
|
|
83
|
+
caller holds none and satisfies none — a sessionless function with scopes would
|
|
84
|
+
reject every caller it exists to serve. Gate those with `permissions`, which
|
|
85
|
+
receive the optional session and may pass anonymous.
|
|
86
|
+
|
|
87
|
+
**Generics XOR `input`/`output` — never both.** A function's data and return
|
|
88
|
+
types come from _one_ source: either the `input`/`output` schemas (preferred —
|
|
89
|
+
they double as runtime validation and OpenAPI) or type generics
|
|
90
|
+
(`pikkuFunc<In, Out>({ ... })`). Passing both makes the two disagree and forces
|
|
91
|
+
`as any` casts. Do not annotate the `func` return type inline either — let the
|
|
92
|
+
`output` schema (or the generic) be the single source of truth for the type.
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
// Correct — schema-based (no generics, no inline return type)
|
|
96
|
+
pikkuFunc({ input: MyInput, output: MyOutput, func: async (s, d) => { ... } })
|
|
97
|
+
// Correct — generic-based (no input/output)
|
|
98
|
+
pikkuFunc<MyIn, MyOut>({ func: async (s, d) => { ... } })
|
|
99
|
+
// WRONG — mixing the two
|
|
100
|
+
pikkuFunc<MyIn, MyOut>({ input: MyInput as any, func: async (s, d) => { ... } })
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Schemas (Validation)
|
|
104
|
+
|
|
105
|
+
Pikku uses Standard Schema — works with Zod, Valibot, ArkType:
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
import { z } from 'zod'
|
|
109
|
+
|
|
110
|
+
const CreateTodoInputSchema = z.object({
|
|
111
|
+
title: z.string().min(1).max(200),
|
|
112
|
+
priority: z.enum(['low', 'medium', 'high']).optional(),
|
|
113
|
+
tags: z.array(z.string()).optional(),
|
|
114
|
+
})
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Schemas serve triple duty: runtime validation, TypeScript types, and OpenAPI documentation.
|
|
@@ -31,10 +31,10 @@ identifier is a migration, not an edit.
|
|
|
31
31
|
{ "metaLocale": "de" }
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
Meta is the one part of a project
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
Meta is the one part of a project that is read back to a human. A team
|
|
35
|
+
reviewing their own functions, features and scenario reports is reading meta
|
|
36
|
+
and nothing else, so a team whose working language is German should be able to
|
|
37
|
+
read it in German. That is the entire reason
|
|
38
38
|
the field exists.
|
|
39
39
|
|
|
40
40
|
Read it before you author meta, and write descriptions, titles and templates in
|
|
@@ -79,7 +79,7 @@ settings, each on its own axis:
|
|
|
79
79
|
// apps/app/src/i18n/active.json — what a first-time visitor opens in
|
|
80
80
|
{ "defaultLocale": "de" }
|
|
81
81
|
|
|
82
|
-
// pikku.config.json — the language the team reads their
|
|
82
|
+
// pikku.config.json — the language the team reads their meta in
|
|
83
83
|
{ "metaLocale": "de" }
|
|
84
84
|
```
|
|
85
85
|
|
|
@@ -4,14 +4,16 @@
|
|
|
4
4
|
|
|
5
5
|
| Package | Use Case |
|
|
6
6
|
| ----------------------------- | ------------------------------------- |
|
|
7
|
-
| `@pikku/express
|
|
7
|
+
| `@pikku/express` | Express standalone server |
|
|
8
8
|
| `@pikku/express-middleware` | Express as middleware in existing app |
|
|
9
|
-
| `@pikku/fastify
|
|
9
|
+
| `@pikku/fastify` | Fastify standalone |
|
|
10
10
|
| `@pikku/fastify-plugin` | Fastify plugin |
|
|
11
11
|
| `@pikku/next` | Next.js API routes |
|
|
12
|
-
| `@pikku/
|
|
12
|
+
| `@pikku/lambda` | AWS Lambda handlers |
|
|
13
13
|
| `@pikku/cloudflare` | Cloudflare Workers |
|
|
14
|
-
| `@pikku/uws
|
|
14
|
+
| `@pikku/uws` | uWebSockets.js (high perf) |
|
|
15
|
+
| `@pikku/ws` | `ws` WebSocket server |
|
|
16
|
+
| `@pikku/azure-functions` | Azure Functions |
|
|
15
17
|
| `@pikku/modelcontextprotocol` | MCP server |
|
|
16
18
|
|
|
17
19
|
## Service Packages
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Testing
|
|
2
|
+
|
|
3
|
+
Functions are easily testable because they're pure:
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
const mockServices = {
|
|
7
|
+
logger: new MockLogger(),
|
|
8
|
+
todoStore: new MockTodoStore(),
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Call function directly — no HTTP, no framework
|
|
12
|
+
const result = await listTodos.func(mockServices, { userId: 'test' })
|
|
13
|
+
expect(result.todos).toHaveLength(3)
|
|
14
|
+
```
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pikku-convert-screen
|
|
3
|
-
description:
|
|
3
|
+
description: >-
|
|
4
|
+
Rebuild an old screen, page or feature (from an old console, another repo, screenshots or a
|
|
5
|
+
description) in the current app: extract what it does as plain business logic, no layout or code
|
|
6
|
+
detail, then design it fresh in the current design system. TRIGGER on "convert this screen", "port
|
|
7
|
+
the old console page", "we had this before, bring it back", "redesign X from the old console". DO
|
|
8
|
+
NOT TRIGGER for whole-repo reverse engineering (use pikku-software-archaeology) or restyling a
|
|
9
|
+
screen already in the app.
|
|
4
10
|
installGroups: [core]
|
|
5
11
|
---
|
|
6
12
|
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pikku-deploy
|
|
3
3
|
description: >-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
`
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
Pikku app. DO NOT TRIGGER when: defining functions or wirings with no runtime-specific code.
|
|
4
|
+
Deploying a Pikku app to a runtime: Express, Fastify, uWebSockets.js, `ws`, Next.js, AWS Lambda,
|
|
5
|
+
Cloudflare Workers, Azure Functions. Covers the shared bootstrap, choosing a runtime, which accept
|
|
6
|
+
RunHTTPWiringOptions, scheduled tasks per runtime, CORS and health checks. TRIGGER when: writing
|
|
7
|
+
or debugging `start.ts`, a worker entry or Lambda handler, importing
|
|
8
|
+
@pikku/express|fastify|uws|ws|next|lambda|cloudflare|azure-functions, or asked how to serve, host
|
|
9
|
+
or deploy a Pikku app. DO NOT TRIGGER when: defining functions or wirings with no runtime-specific
|
|
10
|
+
code.
|
|
12
11
|
installGroups: [core]
|
|
13
12
|
---
|
|
14
13
|
|
|
@@ -35,23 +34,23 @@ Two families, and the difference decides how you write the entry file.
|
|
|
35
34
|
**Long-running servers** own a process. Services are built once at startup and
|
|
36
35
|
live in module scope for the life of the server.
|
|
37
36
|
|
|
38
|
-
| Runtime
|
|
39
|
-
|
|
|
40
|
-
| Express
|
|
41
|
-
| Fastify
|
|
42
|
-
| uWebSockets.js | `@pikku/uws`
|
|
43
|
-
| ws
|
|
37
|
+
| Runtime | Package | Reach for it when |
|
|
38
|
+
| -------------- | ---------------- | ---------------------------------------------------------------------- |
|
|
39
|
+
| Express | `@pikku/express` | An existing Express app, or you want static assets and upload handling |
|
|
40
|
+
| Fastify | `@pikku/fastify` | An existing Fastify app, or you want its stricter defaults |
|
|
41
|
+
| uWebSockets.js | `@pikku/uws` | Highest throughput, HTTP and WebSocket on one port |
|
|
42
|
+
| ws | `@pikku/ws` | WebSocket only, attached to an `http.Server` you own |
|
|
44
43
|
|
|
45
44
|
**Per-invocation runtimes** are handed a request and torn down. Services are
|
|
46
45
|
cached in module scope across warm invocations, and the deploy codegen writes
|
|
47
46
|
that caching for you.
|
|
48
47
|
|
|
49
|
-
| Runtime
|
|
50
|
-
|
|
|
51
|
-
| AWS Lambda
|
|
52
|
-
| Cloudflare Workers | `@pikku/cloudflare`
|
|
53
|
-
| Azure Functions
|
|
54
|
-
| Next.js
|
|
48
|
+
| Runtime | Package | Reach for it when |
|
|
49
|
+
| ------------------ | ------------------------ | ------------------------------------------------------- |
|
|
50
|
+
| AWS Lambda | `@pikku/lambda` | API Gateway, EventBridge, SQS |
|
|
51
|
+
| Cloudflare Workers | `@pikku/cloudflare` | Edge, Durable Objects for channels |
|
|
52
|
+
| Azure Functions | `@pikku/azure-functions` | Azure hosting — note channels are not implemented |
|
|
53
|
+
| Next.js | `@pikku/next` | Pikku behind Next routes, or RPC from Server Components |
|
|
55
54
|
|
|
56
55
|
Then read the reference for the one you picked: `references/express.md`,
|
|
57
56
|
`references/fastify.md`, `references/uws.md`, `references/ws.md`,
|
|
@@ -84,16 +83,16 @@ hand-written handlers are for the cases the deploy codegen does not cover.
|
|
|
84
83
|
`maxBodySize`, `respondWith404`, `coerceDataFromSchema` and `bubbleErrors` reach
|
|
85
84
|
the request only on the runtimes that thread them through.
|
|
86
85
|
|
|
87
|
-
| Runtime
|
|
88
|
-
|
|
|
89
|
-
| Express
|
|
90
|
-
| Fastify
|
|
91
|
-
| uWS
|
|
92
|
-
| ws
|
|
93
|
-
| Next.js
|
|
94
|
-
| Lambda
|
|
95
|
-
| Cloudflare | Partially — `runFetch(request, hibernation, options)` | The platform's limit
|
|
96
|
-
| Azure
|
|
86
|
+
| Runtime | Accepts options | Where an oversized body is actually stopped |
|
|
87
|
+
| ---------- | ----------------------------------------------------- | ----------------------------------------------------- |
|
|
88
|
+
| Express | `init(httpOptions)` | The `express.json` parser limit, fed by `maxBodySize` |
|
|
89
|
+
| Fastify | `init(httpOptions)` | Fastify's own `bodyLimit`, set from `maxBodySize` |
|
|
90
|
+
| uWS | HTTP handler only | The handler counts bytes itself and answers `413` |
|
|
91
|
+
| ws | Yes, on the handler | `maxPayload` on the `WebSocketServer` |
|
|
92
|
+
| Next.js | Only via your own `PikkuNextJS` handler | Next's own limits |
|
|
93
|
+
| Lambda | **No** | API Gateway's payload limit |
|
|
94
|
+
| Cloudflare | Partially — `runFetch(request, hibernation, options)` | The platform's limit |
|
|
95
|
+
| Azure | **No** | Azure's request limits |
|
|
97
96
|
|
|
98
97
|
On Fastify, leaving `maxBodySize` unset keeps Fastify's stricter 1MB default
|
|
99
98
|
rather than loosening it to Pikku's 10MB fallback. On uWS the chunks are dropped
|
|
@@ -16,7 +16,7 @@ the upgrade and message plumbing to them.
|
|
|
16
16
|
|
|
17
17
|
```typescript
|
|
18
18
|
import { DEFAULT_WS_MAX_PAYLOAD, pikkuWebsocketHandler } from '@pikku/ws'
|
|
19
|
-
import { stopSingletonServices } from '@pikku/core'
|
|
19
|
+
import { stopSingletonServices } from '@pikku/core/utils'
|
|
20
20
|
import { Server } from 'http'
|
|
21
21
|
import { WebSocketServer } from 'ws'
|
|
22
22
|
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pikku-emails
|
|
3
3
|
description: >-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
Pikku's file-based email templates: html/subject/text templates, locales, partials, theme, `pikku
|
|
5
|
+
emails generate`, rendering and sending via EmailService. TRIGGER when: code uses
|
|
6
|
+
renderEmailTemplate, EmailTemplateName, EmailService, SendTemplateEmailInput, LocalEmailService or
|
|
7
|
+
imports .pikku/email/pikku-emails.gen; the project has an emails/ directory or emailTemplatesDir
|
|
8
|
+
in pikku.config.json; or the user adds, edits or translates a transactional email (verification,
|
|
9
|
+
reset, invitation, receipt). DO NOT TRIGGER for app UI i18n (use pikku-i18n) or sign-in flows in
|
|
10
|
+
general (use pikku-auth).
|
|
7
11
|
installGroups: [core]
|
|
8
12
|
---
|
|
9
13
|
|
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pikku-guide
|
|
3
3
|
description: >-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
pages, docs with screenshots, "document the app", or complains that the /docs pages are bad,
|
|
12
|
-
thin, or all videos. DO NOT TRIGGER when: user asks about API reference docs, README files, the
|
|
13
|
-
Pikku framework's own documentation site, or writing the scenarios themselves (use pikku-scenario).
|
|
4
|
+
Write, rewrite or regenerate a project's end-user guide from the scenario suite (`pikku scenario
|
|
5
|
+
guide`): hand-written markdown with `pikku:guide` markers that pull in scenario screenshots and
|
|
6
|
+
recordings. Covers planning, markers, capture, seed data, `.guide.lock`, `document: false`, and
|
|
7
|
+
traps that leave a guide empty, refused or all videos. TRIGGER when: asked for a user guide, help
|
|
8
|
+
pages, docs with screenshots, "document the app", or the /docs pages are bad, thin or all videos.
|
|
9
|
+
DO NOT TRIGGER for API reference, READMEs, the Pikku framework's own docs, or writing scenarios
|
|
10
|
+
(use pikku-scenario).
|
|
14
11
|
installGroups: [core]
|
|
15
12
|
---
|
|
16
13
|
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pikku-i18n
|
|
3
3
|
description: >-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
or
|
|
10
|
-
messages thrown from functions, or log output — none of those are display strings.
|
|
4
|
+
Writing user-facing text in a Pikku frontend or making it speak another language: Paraglide JS
|
|
5
|
+
message functions from per-locale JSON, adding a language, generated enum-label maps
|
|
6
|
+
(@pikku/paraglide), and RTL support (Arabic, Hebrew, Farsi, Urdu). TRIGGER when: writing display
|
|
7
|
+
text in a frontend, making copy translatable, adding a language, labelling an enum/status/role
|
|
8
|
+
value, or supporting RTL. DO NOT TRIGGER for backend functions, error messages thrown from
|
|
9
|
+
functions, or log output.
|
|
11
10
|
installGroups: [client]
|
|
12
11
|
---
|
|
13
12
|
|
|
@@ -22,11 +21,11 @@ type-checks them, so an i18n mistake blocks the build rather than the release.
|
|
|
22
21
|
|
|
23
22
|
## Pick the reference
|
|
24
23
|
|
|
25
|
-
| You are…
|
|
26
|
-
|
|
|
27
|
-
| Writing copy, wiring Paraglide, or adding a language
|
|
28
|
-
| Labelling an enum, status, kind or role value
|
|
29
|
-
| Adding Arabic (or Hebrew, Farsi, Urdu), or writing layout styles | `references/rtl.md`
|
|
24
|
+
| You are… | Read |
|
|
25
|
+
| ---------------------------------------------------------------- | --------------------------- |
|
|
26
|
+
| Writing copy, wiring Paraglide, or adding a language | `references/messages.md` |
|
|
27
|
+
| Labelling an enum, status, kind or role value | `references/enum-labels.md` |
|
|
28
|
+
| Adding Arabic (or Hebrew, Farsi, Urdu), or writing layout styles | `references/rtl.md` |
|
|
30
29
|
|
|
31
30
|
## Three axes, and a brief usually means only one
|
|
32
31
|
|
|
@@ -34,14 +33,14 @@ type-checks them, so an i18n mistake blocks the build rather than the release.
|
|
|
34
33
|
codebase. Reading it as one about the codebase is the most expensive mistake
|
|
35
34
|
available here.
|
|
36
35
|
|
|
37
|
-
| Axis
|
|
38
|
-
|
|
|
39
|
-
| **Identifiers** | Function, component, type and file names; tables and columns
|
|
40
|
-
| **Meta**
|
|
41
|
-
| **Product UI**
|
|
36
|
+
| Axis | What it covers | What sets it |
|
|
37
|
+
| --------------- | ------------------------------------------------------------------------ | ------------------------------------------ |
|
|
38
|
+
| **Identifiers** | Function, component, type and file names; tables and columns | Nothing — always English |
|
|
39
|
+
| **Meta** | `description` / `name` / `title` authored in code, read back to the team | `metaLocale` in `pikku.config.json` |
|
|
40
|
+
| **Product UI** | Every string the app shows a user | `messages/<locale>.json` + `defaultLocale` |
|
|
42
41
|
|
|
43
42
|
`baseLocale` stays `en` whatever language the product speaks — it names the
|
|
44
|
-
message
|
|
43
|
+
message _source_ catalogue every other locale is derived from, not the language
|
|
45
44
|
the app is in. Set `defaultLocale` instead.
|
|
46
45
|
|
|
47
46
|
## Direction is one setting, not per-component work
|
|
@@ -59,7 +58,7 @@ is what makes an RTL language just another locale file.
|
|
|
59
58
|
`m['enum__' + x]()`, no key-string resolver. A computed key cannot be
|
|
60
59
|
type-checked or tree-shaken, so a renamed message degrades to silent runtime
|
|
61
60
|
text. Where the key is genuinely dynamic, map the discriminant to a message
|
|
62
|
-
|
|
61
|
+
_function_ — the map is checked, a string is not.
|
|
63
62
|
- **Do not `asI18n()` a hardcoded English string.** `asI18n` exists to pass
|
|
64
63
|
opaque server data (a name, a slug, an id) through the i18n gate. An enum value
|
|
65
64
|
goes through its generated label map.
|
|
@@ -29,11 +29,11 @@ is a statement about **one** of three separate things, and reading it as a
|
|
|
29
29
|
statement about the codebase is the single most expensive mistake available in
|
|
30
30
|
this skill. Three axes:
|
|
31
31
|
|
|
32
|
-
| Axis | What it covers
|
|
33
|
-
| --------------- |
|
|
34
|
-
| **Identifiers** | Function, component, type and file names; database tables and columns
|
|
35
|
-
| **Meta** | `description` / `name` / `title` / `template` authored inside the code,
|
|
36
|
-
| **Product UI** | Every string the app shows a user
|
|
32
|
+
| Axis | What it covers | What sets it |
|
|
33
|
+
| --------------- | --------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
|
|
34
|
+
| **Identifiers** | Function, component, type and file names; database tables and columns | Nothing — always English, no setting |
|
|
35
|
+
| **Meta** | `description` / `name` / `title` / `template` authored inside the code, read back to the team | `metaLocale` in `pikku.config.json`, default `en` |
|
|
36
|
+
| **Product UI** | Every string the app shows a user | `messages/<locale>.json` + `defaultLocale` — **this axis only** |
|
|
37
37
|
|
|
38
38
|
A non-English product moves the third row and nothing else.
|
|
39
39
|
|
|
@@ -63,7 +63,7 @@ So a German medical portal is **three** settings, not one:
|
|
|
63
63
|
// apps/app/src/i18n/active.json — what a visitor opens in
|
|
64
64
|
{ "defaultLocale": "de" }
|
|
65
65
|
|
|
66
|
-
// pikku.config.json — the language the team reads their
|
|
66
|
+
// pikku.config.json — the language the team reads their meta in
|
|
67
67
|
{ "metaLocale": "de" }
|
|
68
68
|
```
|
|
69
69
|
|
|
@@ -221,8 +221,6 @@ The wrapper alternative — a module that walks the namespace and pipes each mes
|
|
|
221
221
|
- Don't edit or commit anything under `src/paraglide/` — it's regenerated; change `messages/*.json` instead.
|
|
222
222
|
- **Don't wrap `m`.** No re-export module, no branding layer, no resolver. Components import `m` from `../paraglide/messages.js` and call it. `@pikku/react`'s `I18nString` is declared as `string & { readonly __brand: 'LocalizedString' }` — deliberately identical to Paraglide's own `LocalizedString` — so `m.some__key()` satisfies the template's `I18nNode` gate natively. A wrapper adds nothing and costs per-message tree-shaking.
|
|
223
223
|
|
|
224
|
-
`packages/console` is the one place in this repo that still wraps it, in `src/i18n/messages.ts`, to keep the debug mask (`█`) it carried over from i18next. That wrapper is a leftover, not a pattern — the generated-locale approach above is how a new app gets the same masking without touching every export. Don't copy it.
|
|
225
|
-
|
|
226
224
|
The `mKey`/`mList` runtime resolvers that used to live beside it are **gone**, and must not come back. `mList` resolved indexed `prefix.0` keys that no longer exist; `mKey` took a computed string, which is exactly the type safety Paraglide exists to provide. Where a key really is dynamic, map the discriminant to a message _function_ and call it — the map is type-checked, a string is not.
|
|
227
225
|
|
|
228
226
|
- Don't re-resolve messages by string key or re-implement `{param}` interpolation. A key-string resolver turns a missing key back into silent runtime text, surrendering the type safety that is the entire reason to use Paraglide.
|