@pikku/skills 0.12.52 → 0.12.55
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/README.md +1 -1
- package/dist/skills.gen.js +2 -2
- package/dist/snippets.js +1 -1
- package/package.json +1 -1
- package/skills/pikku-a11y/SKILL.md +22 -15
- package/skills/pikku-addon/SKILL.md +5 -5
- package/skills/pikku-addon/references/addon-package-manifest.md +7 -0
- package/skills/pikku-addon/references/openapi.md +11 -0
- package/skills/pikku-agent/SKILL.md +6 -6
- package/skills/pikku-agent/references/agents.md +8 -1
- package/skills/pikku-agent/references/runner-vercel.md +2 -2
- package/skills/pikku-agent/references/voice.md +7 -1
- package/skills/pikku-architect/SKILL.md +2 -2
- package/skills/pikku-architect/references/plan-defects.md +9 -7
- package/skills/pikku-auth/SKILL.md +15 -36
- package/skills/pikku-auth/references/better-auth.md +106 -133
- package/skills/pikku-auth/references/jose.md +6 -0
- package/skills/pikku-auth/references/machine-auth.md +6 -0
- package/skills/pikku-auth/references/sessions.md +6 -0
- package/skills/pikku-build/SKILL.md +37 -34
- package/skills/pikku-build/references/app.md +113 -99
- package/skills/pikku-build/references/design.md +43 -31
- package/skills/pikku-build/references/feature.md +17 -3
- package/skills/pikku-build/references/mocks.md +29 -0
- package/skills/pikku-build/references/multi-app.md +25 -18
- package/skills/pikku-build/references/native-app.md +9 -0
- package/skills/pikku-build/references/openapi.md +41 -34
- package/skills/pikku-build/references/platform.md +23 -14
- package/skills/pikku-build/references/post-clone.md +1 -1
- package/skills/pikku-build/references/quick.md +76 -39
- package/skills/pikku-build/references/scenarios.md +28 -16
- package/skills/pikku-build/references/ship.md +19 -16
- package/skills/pikku-build/references/theming.md +76 -127
- package/skills/pikku-changes/SKILL.md +7 -10
- package/skills/pikku-concepts/SKILL.md +34 -44
- package/skills/pikku-concepts/references/concept-mapping.md +18 -0
- package/skills/pikku-concepts/references/language.md +6 -6
- package/skills/pikku-convert-screen/SKILL.md +45 -0
- package/skills/pikku-deploy/references/cloudflare.md +8 -0
- package/skills/pikku-deploy/references/lambda.md +8 -0
- package/skills/pikku-deploy/references/nextjs.md +1 -1
- package/skills/pikku-deploy/references/uws.md +1 -1
- package/skills/pikku-deploy/references/ws.md +3 -3
- package/skills/pikku-emails/SKILL.md +3 -9
- package/skills/pikku-guide/SKILL.md +28 -27
- package/skills/pikku-i18n/SKILL.md +7 -7
- package/skills/pikku-i18n/references/enum-labels.md +9 -0
- package/skills/pikku-i18n/references/messages.md +21 -9
- package/skills/pikku-i18n/references/rtl.md +18 -38
- package/skills/pikku-knowledge/SKILL.md +12 -13
- package/skills/pikku-kysely/SKILL.md +3 -21
- package/skills/pikku-list-query/SKILL.md +2 -2
- package/skills/pikku-meta/references/audit.md +10 -1
- package/skills/pikku-meta/references/meta.md +6 -0
- package/skills/pikku-meta/references/versioning.md +10 -0
- package/skills/pikku-middleware/SKILL.md +7 -16
- package/skills/pikku-n8n-import/SKILL.md +9 -1
- package/skills/pikku-n8n-import/references/addon-mapping.md +6 -0
- package/skills/pikku-n8n-import/references/code-translation.md +7 -0
- package/skills/pikku-permissions/SKILL.md +41 -10
- package/skills/pikku-permissions/references/scopes.md +59 -0
- package/skills/pikku-react/SKILL.md +20 -22
- package/skills/pikku-react/references/client.md +2 -70
- package/skills/pikku-react/references/react-query.md +11 -0
- package/skills/pikku-react/references/workflows.md +11 -0
- package/skills/pikku-realtime/SKILL.md +9 -3
- package/skills/pikku-report/SKILL.md +17 -16
- package/skills/pikku-scenario/SKILL.md +72 -81
- package/skills/pikku-scenario/references/browser.md +5 -5
- package/skills/pikku-scenario/references/coverage.md +4 -4
- package/skills/pikku-scenario/references/steps.md +31 -30
- package/skills/pikku-scenario/references/{persona-run.md → virtual-user-run.md} +47 -42
- package/skills/pikku-scenario/references/virtual-users.md +114 -0
- package/skills/pikku-seo/SKILL.md +12 -16
- package/skills/pikku-service-backends/SKILL.md +0 -10
- package/skills/pikku-service-backends/references/aws.md +6 -0
- package/skills/pikku-service-backends/references/mongodb.md +7 -0
- package/skills/pikku-service-backends/references/redis.md +6 -0
- package/skills/pikku-services/references/audit-wire-service.md +2 -2
- package/skills/pikku-services/references/audit.md +10 -1
- package/skills/pikku-services/references/config.md +6 -0
- package/skills/pikku-services/references/services.md +9 -2
- package/skills/pikku-software-archaeology/SKILL.md +21 -27
- package/skills/pikku-software-archaeology/references/blueprint.schema.json +16 -16
- package/skills/pikku-software-archaeology/references/pikku-mapping.md +3 -3
- package/skills/pikku-software-archaeology/references/second-opinion.md +13 -1
- package/skills/pikku-tailwind/SKILL.md +111 -0
- package/skills/pikku-theme/SKILL.md +187 -0
- package/skills/pikku-theme/references/from-a-reference.md +44 -0
- package/skills/pikku-theme/references/presets.md +40 -0
- package/skills/pikku-ui/SKILL.md +41 -0
- package/skills/pikku-wiring/SKILL.md +13 -12
- package/skills/pikku-wiring/references/channel.md +7 -1
- package/skills/pikku-wiring/references/cli.md +7 -1
- package/skills/pikku-wiring/references/gateway-slack.md +6 -0
- package/skills/pikku-wiring/references/http.md +10 -3
- package/skills/pikku-wiring/references/mcp.md +8 -0
- package/skills/pikku-wiring/references/queue.md +6 -0
- package/skills/pikku-wiring/references/realtime.md +34 -4
- package/skills/pikku-wiring/references/rpc.md +6 -0
- package/skills/pikku-wiring/references/scheduler.md +6 -0
- package/skills/pikku-wiring/references/trigger.md +8 -0
- package/skills/pikku-workflow/SKILL.md +9 -7
- package/skills/pikku-admin-to-fabric/SKILL.md +0 -212
- package/skills/pikku-auth/references/permissions.md +0 -261
- package/skills/pikku-blueprint-to-fabric/SKILL.md +0 -377
- package/skills/pikku-blueprint-to-fabric/scripts/inventory.mjs +0 -367
- package/skills/pikku-fabric/SKILL.md +0 -619
- package/skills/pikku-fabric/references/debugging.md +0 -110
- package/skills/pikku-mantine/SKILL.md +0 -80
- package/skills/pikku-scenario/references/personas.md +0 -117
- package/skills/pikku-wiring/references/realtime-other-routes.md +0 -23
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Integration stub → Pikku addon
|
|
2
2
|
|
|
3
|
+
## Contents
|
|
4
|
+
|
|
5
|
+
- Inputs
|
|
6
|
+
- Per entry, in order
|
|
7
|
+
- Never
|
|
8
|
+
|
|
3
9
|
Translate n8n integration nodes (`gmailTool`, `slackTool`, `googleSheetsTool`, plain
|
|
4
10
|
`gmail` / `slack` action nodes, etc.) that the importer left as throwing stubs into
|
|
5
11
|
real `ref('<addonRpc>')` references pointing at functions in **installed**
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# n8n Code node → Pikku function
|
|
2
2
|
|
|
3
|
+
## Contents
|
|
4
|
+
|
|
5
|
+
- Process
|
|
6
|
+
- Rubric
|
|
7
|
+
- Example
|
|
8
|
+
- Report
|
|
9
|
+
|
|
3
10
|
Replace a Code-node stub's `throw new Error(...)` body with a faithful TypeScript
|
|
4
11
|
reimplementation. The original JS is preserved verbatim in the JSDoc above the
|
|
5
12
|
function. Keep the signature and JSDoc intact; only widen the Zod input/output if
|
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pikku-permissions
|
|
3
3
|
description: >-
|
|
4
|
-
Use when deciding WHO may call a function
|
|
5
|
-
TRIGGER when: writing or reviewing any function that touches a row a user owns, gating an action on a role, building the permissions half of a contract in build PHASE 2,
|
|
6
|
-
DO NOT TRIGGER when: the question is how
|
|
4
|
+
Use when deciding WHO may call a function: resource ownership, role gates, admin-only actions, or any "only their own rows" rule. Covers the `permissions` field, `pikkuPermission`, `pikkuAuth`, scopes and `defineScope`, `addGlobalPermission`, the three gates, `permissionsInBody`, and where ownership belongs versus where it does not.
|
|
5
|
+
TRIGGER when: writing or reviewing any function that touches a row a user owns, gating an action on a role, building the permissions half of a contract in build PHASE 2, about to write an `if` in a function body that decides whether the caller is allowed, or hitting `MissingScopeError`.
|
|
6
|
+
DO NOT TRIGGER when: the question is how a caller proves who they are, such as sign-in, sessions, tokens, API keys or seeding a virtual user (use pikku-auth), or how to shape a paginated list (use pikku-list-query).
|
|
7
7
|
installGroups: [core]
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# Pikku Permissions
|
|
11
11
|
|
|
12
|
+
## First: is the caller a machine with a token?
|
|
13
|
+
|
|
14
|
+
Then this is NOT a permissions problem. Resolve the token in `addHTTPMiddleware('*')`
|
|
15
|
+
middleware that calls `setSession`, make the function a `pikkuFunc`, and gate it with
|
|
16
|
+
`scopes` (pikku-auth, `../pikku-auth/references/machine-auth.md`). A `permissions` check that verifies a
|
|
17
|
+
bearer token and returns `true` is authentication wearing an authorization hat, and it
|
|
18
|
+
leaves the function sessionless. The only exception is a bootstrap endpoint whose caller
|
|
19
|
+
has no identity yet (a shared-secret registration, a login): it is sessionless and
|
|
20
|
+
declares its gate here.
|
|
21
|
+
|
|
12
22
|
## The rule
|
|
13
23
|
|
|
14
24
|
**Authorization goes in the `permissions` field. Never in the `func` body.**
|
|
@@ -107,11 +117,32 @@ gets straight through if the function itself is open.
|
|
|
107
117
|
## Scopes
|
|
108
118
|
|
|
109
119
|
`scopes: ['admin:invoices:void']` is an AND gate checked BEFORE permissions and before
|
|
110
|
-
input validation.
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
`
|
|
114
|
-
|
|
120
|
+
input validation. A function naming an undeclared scope fails codegen rather than gating on
|
|
121
|
+
nothing. A grant satisfies a scope if it is that scope, an ancestor, or a wildcard. Most
|
|
122
|
+
apps need roles, not scopes; reach for these only when the plan asked for granular grants.
|
|
123
|
+
The `defineScope` tree, grant matching and the sessionless restriction are in
|
|
124
|
+
[references/scopes.md](references/scopes.md).
|
|
125
|
+
|
|
126
|
+
## Global permissions
|
|
127
|
+
|
|
128
|
+
`addGlobalPermission([isEmployee])` (from `#pikku/auth`) is an app-wide baseline every
|
|
129
|
+
function must additionally pass. It is an independent AND gate: it can only narrow access,
|
|
130
|
+
never grant what a function's own `permissions` would deny. Multiple calls accumulate and
|
|
131
|
+
are AND'd.
|
|
132
|
+
|
|
133
|
+
## The three gates
|
|
134
|
+
|
|
135
|
+
All must pass, in this order:
|
|
136
|
+
|
|
137
|
+
1. **Scopes** (`scopes`) — AND'd, checked before input validation, fails closed.
|
|
138
|
+
2. **Global permissions** (`addGlobalPermission`) — AND'd together, a baseline that only narrows.
|
|
139
|
+
3. **The function's own `permissions`** — OR'd groups of AND'd entries.
|
|
140
|
+
|
|
141
|
+
They are independent: a broad global (e.g. `isEmployee`) can never satisfy an admin-only
|
|
142
|
+
function's own requirement. Wire-, tag- and HTTP-route-level permissions
|
|
143
|
+
(`addHTTPPermission`, `addTagPermission`, a `permissions` field on a wiring) no longer
|
|
144
|
+
exist; tags are organizational only. Use tag/HTTP middleware for cross-cutting request
|
|
145
|
+
handling, not authorization.
|
|
115
146
|
|
|
116
147
|
## The one sanctioned exception
|
|
117
148
|
|
|
@@ -122,5 +153,5 @@ the auditor the openness is deliberate. Anything expressible as a permission mus
|
|
|
122
153
|
|
|
123
154
|
## After changes
|
|
124
155
|
|
|
125
|
-
`pikku all` — regenerates
|
|
126
|
-
wrong fails here, not at runtime.
|
|
156
|
+
`pikku all --tsc` — regenerates, then verifies the checker types. A permission whose
|
|
157
|
+
signature is wrong fails here, not at runtime.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Scopes
|
|
2
|
+
|
|
3
|
+
Scopes answer "what was this session granted?" before permissions ask "may this user do
|
|
4
|
+
this to this resource?". They are AND-ed: every scope listed must be held. Because they
|
|
5
|
+
are checked first and fail closed, a scope can only ever narrow access.
|
|
6
|
+
|
|
7
|
+
## Declaring the tree
|
|
8
|
+
|
|
9
|
+
Declare the scope tree once with `defineScope`. The body is a no-op that tree-shakes
|
|
10
|
+
away; the CLI reads the call by AST and generates a `ScopeId` union, so a function naming
|
|
11
|
+
an undeclared scope fails the build.
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
// src/scopes.ts
|
|
15
|
+
import { defineScope } from '#pikku/scopes'
|
|
16
|
+
|
|
17
|
+
defineScope({
|
|
18
|
+
admin: {
|
|
19
|
+
displayName: 'Administration',
|
|
20
|
+
description: 'Administrative access',
|
|
21
|
+
scopes: {
|
|
22
|
+
invoices: {
|
|
23
|
+
description: 'Invoice management',
|
|
24
|
+
scopes: {
|
|
25
|
+
create: { description: 'Create invoices' },
|
|
26
|
+
void: { description: 'Void invoices' },
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
billing: {},
|
|
32
|
+
})
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Every node is grantable, keyed by segment: the above yields `admin`, `admin:invoices`,
|
|
36
|
+
`admin:invoices:create`, `admin:invoices:void` and `billing`. Scopes may be declared
|
|
37
|
+
across more than one file; the declarations merge.
|
|
38
|
+
|
|
39
|
+
## Using them
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
export const voidInvoice = pikkuFunc({
|
|
43
|
+
scopes: ['admin:invoices:void'],
|
|
44
|
+
permissions: { owner: isInvoiceOwner },
|
|
45
|
+
func: async ({ kysely }, { invoiceId }) => { ... },
|
|
46
|
+
})
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
A grant satisfies a required scope if it is the scope itself, an ancestor of it, or a
|
|
50
|
+
wildcard at any level: a session holding `admin` satisfies `admin:invoices:void`, and so
|
|
51
|
+
does `admin:*`. A missing scope throws `MissingScopeError` naming the first one that
|
|
52
|
+
failed.
|
|
53
|
+
|
|
54
|
+
## Not on sessionless functions
|
|
55
|
+
|
|
56
|
+
`scopes` requires a session and is unavailable on `pikkuSessionlessFunc`: scopes fail
|
|
57
|
+
closed, an anonymous caller holds none, and a sessionless function with scopes would
|
|
58
|
+
reject every caller it exists to serve. Gate those with `permissions`, which receive the
|
|
59
|
+
optional session and may pass anonymous.
|
|
@@ -3,12 +3,10 @@ name: pikku-react
|
|
|
3
3
|
description: >-
|
|
4
4
|
Use when a React frontend talks to a Pikku backend — PikkuProvider and createPikku at the app
|
|
5
5
|
root, the generated React Query hooks (usePikkuQuery, usePikkuMutation, usePikkuInfiniteQuery),
|
|
6
|
-
direct usePikkuRPC / usePikkuFetch calls, realtime subscriptions, agent and workflow hooks
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
backend (use pikku-wiring), defining the workflow itself (use pikku-workflow), or writing
|
|
11
|
-
user-facing copy (use pikku-i18n).
|
|
6
|
+
direct usePikkuRPC / usePikkuFetch calls, realtime subscriptions, and agent and workflow hooks. TRIGGER when: writing a React component that fetches or mutates backend
|
|
7
|
+
data, wiring PikkuProvider, paginating, running or tracking a workflow from the client. DO NOT TRIGGER when: working on the
|
|
8
|
+
backend (use pikku-wiring), defining the workflow itself (use pikku-workflow), rendering fetched values such as
|
|
9
|
+
dates (use pikku-tailwind), or writing user-facing copy (use pikku-i18n).
|
|
12
10
|
installGroups: [client]
|
|
13
11
|
---
|
|
14
12
|
|
|
@@ -21,25 +19,25 @@ stops.
|
|
|
21
19
|
|
|
22
20
|
## Pick the reference
|
|
23
21
|
|
|
24
|
-
| You are…
|
|
25
|
-
|
|
|
26
|
-
| Wiring the app root, resolving the server URL, authenticating, or subscribing to realtime | `references/client.md`
|
|
27
|
-
| Fetching, mutating or paginating data
|
|
28
|
-
| Starting a workflow and showing its progress
|
|
22
|
+
| You are… | Read |
|
|
23
|
+
| ----------------------------------------------------------------------------------------- | --------------------------- |
|
|
24
|
+
| Wiring the app root, resolving the server URL, authenticating, or subscribing to realtime | `references/client.md` |
|
|
25
|
+
| Fetching, mutating or paginating data | `references/react-query.md` |
|
|
26
|
+
| Starting a workflow and showing its progress | `references/workflows.md` |
|
|
29
27
|
|
|
30
28
|
## Reach for what
|
|
31
29
|
|
|
32
|
-
| Need
|
|
33
|
-
|
|
|
34
|
-
| Render data, dedupe and cache
|
|
35
|
-
| Trigger a write and wait for the result
|
|
36
|
-
| Paginate
|
|
37
|
-
| One-off call from an event handler
|
|
38
|
-
| Hit a REST endpoint rather than an RPC
|
|
39
|
-
| Talk to one named AI agent
|
|
40
|
-
| Run one named workflow
|
|
41
|
-
| A workflow long enough to need progress UI | `references/workflows.md`
|
|
42
|
-
| Subscribe to events, SSE or a channel
|
|
30
|
+
| Need | Use |
|
|
31
|
+
| ------------------------------------------ | -------------------------------------------------------- |
|
|
32
|
+
| Render data, dedupe and cache | `usePikkuQuery` |
|
|
33
|
+
| Trigger a write and wait for the result | `usePikkuMutation` |
|
|
34
|
+
| Paginate | `usePikkuInfiniteQuery` |
|
|
35
|
+
| One-off call from an event handler | `usePikkuRPC()` |
|
|
36
|
+
| Hit a REST endpoint rather than an RPC | `usePikkuFetch()` |
|
|
37
|
+
| Talk to one named AI agent | `usePikkuAgent(name)` → `.run` / `.stream` / `.approve` |
|
|
38
|
+
| Run one named workflow | `usePikkuWorkflow(name)` → `.start` / `.run` / `.status` |
|
|
39
|
+
| A workflow long enough to need progress UI | `references/workflows.md` |
|
|
40
|
+
| Subscribe to events, SSE or a channel | `usePikkuRealtime()` |
|
|
43
41
|
|
|
44
42
|
A workflow that finishes in a moment can be awaited; one that does not needs
|
|
45
43
|
start-plus-observe, or the component holds a pending state with nothing to show.
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# Pikku React
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
What is here:
|
|
5
4
|
|
|
6
5
|
- [What ships](#what-ships)
|
|
@@ -174,8 +173,8 @@ helpers live in **pikku-wiring**.
|
|
|
174
173
|
| Hit a REST endpoint (not RPC) | `usePikkuFetch()` |
|
|
175
174
|
| Run one named workflow | `usePikkuWorkflow('name')` → `.start/.run/.status` |
|
|
176
175
|
| Talk to one named AI agent | `usePikkuAgent('name')` → `.run/.stream/.approve` |
|
|
177
|
-
| Longer-running workflow UX | `references/workflows.md`
|
|
178
|
-
| Subscribe to events / SSE / channel | `usePikkuRealtime()` (see **pikku-wiring**)
|
|
176
|
+
| Longer-running workflow UX | `references/workflows.md` |
|
|
177
|
+
| Subscribe to events / SSE / channel | `usePikkuRealtime()` (see **pikku-wiring**) |
|
|
179
178
|
|
|
180
179
|
The first three live in your generated `api.gen.ts` (see the
|
|
181
180
|
`references/react-query.md`). This reference covers the rest.
|
|
@@ -240,73 +239,6 @@ pikku.fetch.setHeader('x-tenant', tenantId)
|
|
|
240
239
|
`authHeaders.jwt` becomes `Authorization: Bearer …` and `authHeaders.apiKey`
|
|
241
240
|
becomes `X-API-KEY`; setting a JWT takes precedence over an API key.
|
|
242
241
|
|
|
243
|
-
### Dev actor sign-in (`useDevActors`)
|
|
244
|
-
|
|
245
|
-
The dev-only "Sign in as …" control: one click signs in as a declared scenario
|
|
246
|
-
persona with no password, so the app can be reviewed as each kind of user.
|
|
247
|
-
`pikku fabric validate` **requires** any frontend with a login screen to ship one
|
|
248
|
-
(`app-missing-actor-quick-login-<app>`) — without it a reviewer is locked out of
|
|
249
|
-
their own sandbox.
|
|
250
|
-
|
|
251
|
-
```tsx
|
|
252
|
-
import { useDevActors } from '@pikku/react'
|
|
253
|
-
|
|
254
|
-
const { actors, signInAs, pendingId, isPending, error } = useDevActors({
|
|
255
|
-
apiUrl: apiUrl(),
|
|
256
|
-
app: appSlug,
|
|
257
|
-
onSignedIn: () => navigate({ to: '/' }),
|
|
258
|
-
})
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
- **It is UI-free**, so render it however you like. For the default rendering use
|
|
262
|
-
`<DevActorSwitcher />` from `@pikku/mantine/dev` — a separate entry point from
|
|
263
|
-
`@pikku/mantine/core`, whose contract is "drop-in alias for `@mantine/core`"
|
|
264
|
-
and so must not export components Mantine has no counterpart for.
|
|
265
|
-
- **No credential reaches the bundle.** It lists from `/auth/sign-in/personas`
|
|
266
|
-
and `signInAs(id)` posts only the persona id to `/auth/sign-in/persona`. The
|
|
267
|
-
server decides who is offered and who may sign in, and offers nobody in
|
|
268
|
-
production — see **pikku-scenario** for `personaSignIn`.
|
|
269
|
-
- **It takes `onSignedIn` rather than a router**, since every app lands
|
|
270
|
-
somewhere different.
|
|
271
|
-
- `listDevActors()` and `signInAsPersona()` are exported too, for a non-React
|
|
272
|
-
caller. The endpoint only
|
|
273
|
-
signs in rows flagged `actor: true`, so it can never impersonate a real user —
|
|
274
|
-
see **pikku-auth**.
|
|
275
|
-
|
|
276
|
-
Do not hand-write the list-and-sign-in pair per app; that copy-paste is exactly
|
|
277
|
-
what this replaced.
|
|
278
|
-
|
|
279
|
-
### Linking from a Mantine element: `renderRoot`, not `component`
|
|
280
|
-
|
|
281
|
-
Handing TanStack's `Link` to a Mantine element as `component={Link}` compiles,
|
|
282
|
-
renders, and navigates — and silently unties the type. Mantine's polymorphic
|
|
283
|
-
`component` prop widens the router generic to `AnyRouter`, so `to` and
|
|
284
|
-
`params` stop being checked against your actual routes. Renaming a route then
|
|
285
|
-
breaks the running app instead of the build, which is the one thing the typed
|
|
286
|
-
router exists to prevent.
|
|
287
|
-
|
|
288
|
-
Wrap the typed `Link` once and reach it through `renderRoot`, which passes the
|
|
289
|
-
props through without re-typing the element:
|
|
290
|
-
|
|
291
|
-
```tsx
|
|
292
|
-
// components/links.tsx — one wrapper the whole app links through
|
|
293
|
-
import { Link } from '@tanstack/react-router'
|
|
294
|
-
|
|
295
|
-
export const AssessmentLink = (props: { assessmentId: string; children: React.ReactNode }) => (
|
|
296
|
-
<Link to="/assessments/$assessmentId" params={{ assessmentId: props.assessmentId }}>
|
|
297
|
-
{props.children}
|
|
298
|
-
</Link>
|
|
299
|
-
)
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
```tsx
|
|
303
|
-
<Button renderRoot={(p) => <AssessmentLink assessmentId={id} {...p} />}>
|
|
304
|
-
Open
|
|
305
|
-
</Button>
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
The wrapper is where `to` and `params` are checked, and it is checked once.
|
|
309
|
-
|
|
310
242
|
## What NOT to do
|
|
311
243
|
|
|
312
244
|
- Don't instantiate `PikkuFetch`/`PikkuRPC` inside a component — `createPikku`
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Pikku React Query Hooks
|
|
2
2
|
|
|
3
|
+
## Contents
|
|
4
|
+
|
|
5
|
+
- [Discover what's available on the client](#discover-whats-available-on-the-client)
|
|
6
|
+
- [Setup (once per app)](#setup-once-per-app)
|
|
7
|
+
- [TanStack Start (SSR)](#tanstack-start-ssr)
|
|
8
|
+
- [The hooks](#the-hooks)
|
|
9
|
+
- [Workflow hooks](#workflow-hooks)
|
|
10
|
+
- [Calling RPCs without React Query](#calling-rpcs-without-react-query)
|
|
11
|
+
- [Common patterns](#common-patterns)
|
|
12
|
+
- [What NOT to do](#what-not-to-do)
|
|
13
|
+
|
|
3
14
|
|
|
4
15
|
## Discover what's available on the client
|
|
5
16
|
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Pikku Workflows — Client Hooks
|
|
2
2
|
|
|
3
|
+
## Contents
|
|
4
|
+
|
|
5
|
+
- [Discover what workflows exist](#discover-what-workflows-exist)
|
|
6
|
+
- [Setup](#setup)
|
|
7
|
+
- [useRunWorkflow(name, options?) — run and wait](#userunworkflowname-options--run-and-wait)
|
|
8
|
+
- [useStartWorkflow(name, options?) — fire-and-poll](#usestartworkflowname-options--fire-and-poll)
|
|
9
|
+
- [useWorkflowStatus(workflowName, runId, options?) — observe](#useworkflowstatusworkflowname-runid-options--observe)
|
|
10
|
+
- [Putting it together — start + observe](#putting-it-together--start--observe)
|
|
11
|
+
- [Backend: streaming richer progress](#backend-streaming-richer-progress)
|
|
12
|
+
- [What NOT to do](#what-not-to-do)
|
|
13
|
+
|
|
3
14
|
|
|
4
15
|
## Discover what workflows exist
|
|
5
16
|
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pikku-realtime
|
|
3
3
|
description: >-
|
|
4
|
-
Use when making
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
Use when making a view live in a Pikku app — a board, shared list, dashboard, ticker, bidding
|
|
5
|
+
room, live count — or when adding two-way chat or presence. Covers the default event-hub SSE path
|
|
6
|
+
(`eventHub.publish` on the backend, `PikkuRealtime.subscribeToTopic` on the client) and the
|
|
7
|
+
two-way WebSocket channel. TRIGGER when: the user wants live updates, realtime, "update without
|
|
8
|
+
refresh", a live board/feed/ticker/room, presence or chat, or data that more than one signed-in
|
|
9
|
+
user can change should reflect to others. DO NOT TRIGGER when: a one-shot query/refetch is enough
|
|
10
|
+
(data only one user changes, or a manual refresh is acceptable), for background jobs (use
|
|
11
|
+
pikku-workflow, or pikku-wiring's queue and scheduler references), or for the full wiring
|
|
12
|
+
reference of channels, SSE routes and the `/events` scaffold (use pikku-wiring).
|
|
7
13
|
installGroups: [core, client]
|
|
8
14
|
---
|
|
9
15
|
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pikku-report
|
|
3
3
|
description: >-
|
|
4
|
-
Use when pikku itself cost you time — wrong generated types, a check that passes when it
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
Use when pikku itself cost you time — wrong generated types, a check that passes when it should
|
|
5
|
+
not, output that is quietly wrong, a skill that misled you — or when the user asks you to report
|
|
6
|
+
a framework bug or file a finding. Owns `pikku cloud report` (a finding is about pikku, not the
|
|
7
|
+
app), the product-vs-harness kinds, the workaround-first ladder, and asking the user at hand-over
|
|
8
|
+
whether to send what was filed. TRIGGER when: the framework fought you, codegen produced
|
|
9
|
+
something broken, a skill told you to run something that does not exist, the user says "report
|
|
10
|
+
this to pikku" / "file a finding", or you are handing over a build. DO NOT TRIGGER when: the bug
|
|
11
|
+
is in the app you are building (fix it there), you are debugging a deployed stage,
|
|
12
|
+
or you are tempted to patch pikku's source (never do that from an app).
|
|
12
13
|
installGroups: [core]
|
|
13
14
|
---
|
|
14
15
|
|
|
15
|
-
# Report a finding to
|
|
16
|
+
# Report a finding to Pikku Studio Cloud
|
|
16
17
|
|
|
17
18
|
A finding is about **pikku**, not about the app you are building. It is how the
|
|
18
19
|
framework learns what cost its users time — the bug, the misleading skill, the
|
|
@@ -20,7 +21,7 @@ silence where a check should have complained.
|
|
|
20
21
|
|
|
21
22
|
File each one the moment it happens. Nothing leaves the machine until the user
|
|
22
23
|
says so at hand-over, and nothing is written to the repository. The command is
|
|
23
|
-
spelled `pikku
|
|
24
|
+
spelled `pikku cloud report` — there is no top-level report command.
|
|
24
25
|
|
|
25
26
|
## Report at the moment it happens
|
|
26
27
|
|
|
@@ -61,7 +62,7 @@ baseline noise that was already failing before you started.
|
|
|
61
62
|
- `--kind harness` — a skill misled you: it told you to run something that does
|
|
62
63
|
not exist, described a flag that is spelled differently, or contradicted what
|
|
63
64
|
the CLI actually did. Pass `--skill <name>` and `--passage "<the line or
|
|
64
|
-
section>"`. This is the most useful kind to file, because it is fixable
|
|
65
|
+
section>"`. This is the most useful kind to file, because it is fixable
|
|
65
66
|
immediately — so file it even when the cost was small.
|
|
66
67
|
|
|
67
68
|
## The command
|
|
@@ -74,7 +75,7 @@ follows it. Quote the heredoc delimiter (`<<'EOF'`, never `<<EOF`) so the shell
|
|
|
74
75
|
leaves the body alone.
|
|
75
76
|
|
|
76
77
|
```bash
|
|
77
|
-
pikku
|
|
78
|
+
pikku cloud report --stdin <<'EOF'
|
|
78
79
|
{
|
|
79
80
|
"title": "<one-line title>",
|
|
80
81
|
"kind": "product",
|
|
@@ -87,7 +88,7 @@ pikku fabric report --stdin <<'EOF'
|
|
|
87
88
|
EOF
|
|
88
89
|
```
|
|
89
90
|
|
|
90
|
-
The same fields exist as flags for a finding short enough to type; `pikku
|
|
91
|
+
The same fields exist as flags for a finding short enough to type; `pikku cloud
|
|
91
92
|
report --help` lists them. Whichever path you use, the rules below are checked
|
|
92
93
|
before anything is sent:
|
|
93
94
|
|
|
@@ -115,7 +116,7 @@ The last thing in the hand-over — after the app runs, and is deployed if they
|
|
|
115
116
|
chose to — is:
|
|
116
117
|
|
|
117
118
|
```bash
|
|
118
|
-
pikku
|
|
119
|
+
pikku cloud report
|
|
119
120
|
```
|
|
120
121
|
|
|
121
122
|
With no finding, it lists what this build filed. What happens next depends on
|
|
@@ -129,12 +130,12 @@ what the user said before, which the CLI keeps on their machine:
|
|
|
129
130
|
**Never**. Then run it again with their answer:
|
|
130
131
|
|
|
131
132
|
```bash
|
|
132
|
-
pikku
|
|
133
|
+
pikku cloud report --consent yes|no|always|never
|
|
133
134
|
```
|
|
134
135
|
|
|
135
136
|
Yes sends and No discards what is held now; Always and Never are saved and the
|
|
136
137
|
question is not asked again. If nobody answers, leave them held and say that
|
|
137
|
-
`pikku
|
|
138
|
+
`pikku cloud report` sends them later.
|
|
138
139
|
|
|
139
140
|
Findings are anonymous: no account, no project. The receipt printed when you
|
|
140
141
|
filed each one is exactly what leaves the machine. A send that fails keeps what
|