@pikku/skills 0.12.52 → 0.12.54
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 +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-admin-to-fabric/SKILL.md +7 -21
- 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 +1 -1
- package/skills/pikku-architect/references/plan-defects.md +2 -0
- package/skills/pikku-auth/SKILL.md +15 -36
- package/skills/pikku-auth/references/better-auth.md +22 -45
- 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-blueprint-to-fabric/SKILL.md +6 -21
- package/skills/pikku-blueprint-to-fabric/scripts/inventory.mjs +1 -1
- package/skills/pikku-build/SKILL.md +29 -26
- package/skills/pikku-build/references/app.md +60 -41
- package/skills/pikku-build/references/design.md +31 -19
- package/skills/pikku-build/references/feature.md +14 -0
- package/skills/pikku-build/references/mocks.md +23 -0
- package/skills/pikku-build/references/multi-app.md +9 -2
- package/skills/pikku-build/references/native-app.md +9 -0
- package/skills/pikku-build/references/openapi.md +7 -0
- package/skills/pikku-build/references/platform.md +20 -10
- package/skills/pikku-build/references/quick.md +14 -4
- package/skills/pikku-build/references/scenarios.md +12 -1
- package/skills/pikku-build/references/ship.md +6 -1
- package/skills/pikku-build/references/theming.md +74 -125
- package/skills/pikku-changes/SKILL.md +6 -6
- package/skills/pikku-concepts/SKILL.md +8 -17
- package/skills/pikku-concepts/references/concept-mapping.md +18 -0
- 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/uws.md +1 -1
- package/skills/pikku-deploy/references/ws.md +3 -3
- package/skills/pikku-emails/SKILL.md +3 -9
- package/skills/pikku-fabric/SKILL.md +7 -295
- package/skills/pikku-fabric/references/database.md +128 -0
- package/skills/pikku-fabric/references/debugging.md +9 -5
- package/skills/pikku-fabric/references/deploy.md +179 -0
- package/skills/pikku-guide/SKILL.md +10 -10
- 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 +16 -3
- package/skills/pikku-i18n/references/rtl.md +18 -38
- package/skills/pikku-knowledge/SKILL.md +9 -10
- package/skills/pikku-kysely/SKILL.md +3 -21
- package/skills/pikku-list-query/SKILL.md +2 -2
- package/skills/pikku-meta/references/audit.md +9 -0
- 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 +2 -2
- package/skills/pikku-react/references/client.md +1 -34
- 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 +10 -9
- package/skills/pikku-scenario/SKILL.md +11 -17
- package/skills/pikku-scenario/references/persona-run.md +11 -1
- package/skills/pikku-scenario/references/personas.md +7 -1
- 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.md +10 -0
- package/skills/pikku-services/references/config.md +6 -0
- package/skills/pikku-services/references/services.md +8 -1
- package/skills/pikku-software-archaeology/SKILL.md +9 -15
- package/skills/pikku-software-archaeology/references/blueprint.schema.json +7 -7
- 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 +8 -6
- package/skills/pikku-auth/references/permissions.md +0 -261
- package/skills/pikku-mantine/SKILL.md +0 -80
- package/skills/pikku-wiring/references/realtime-other-routes.md +0 -23
|
@@ -6,9 +6,7 @@ installGroups: [fabric]
|
|
|
6
6
|
|
|
7
7
|
# Pikku Fabric
|
|
8
8
|
|
|
9
|
-
##
|
|
10
|
-
|
|
11
|
-
Use this skill as an execution checklist, not reference material.
|
|
9
|
+
## Operating procedure
|
|
12
10
|
|
|
13
11
|
1. **Run structural validation first.** Before any edit, run:
|
|
14
12
|
```bash
|
|
@@ -25,20 +23,18 @@ Fabric is a serverless deployment platform for Pikku apps. Every Fabric app runs
|
|
|
25
23
|
|
|
26
24
|
## Before you start
|
|
27
25
|
|
|
28
|
-
Always run project discovery first:
|
|
29
|
-
|
|
30
26
|
```bash
|
|
31
27
|
yarn pikku meta context --json
|
|
32
28
|
```
|
|
33
29
|
|
|
34
|
-
Run `pikku meta` before grepping or editing a Fabric app
|
|
30
|
+
Run `pikku meta` before grepping or editing a Fabric app:
|
|
35
31
|
|
|
36
32
|
- `pikku meta context --json` for the project map: functions, wires, workflows, capabilities, and source files.
|
|
37
33
|
- `pikku meta clients --json` before frontend/RPC work.
|
|
38
34
|
- `pikku meta functions --json` to list function ids, then `pikku meta functions get <id> --json` for one function.
|
|
39
35
|
- `pikku meta schemas --json` to list schema names. Only request a full schema body with `pikku meta schemas get <name> --json` when you need it.
|
|
40
36
|
|
|
41
|
-
Do not load every schema body by default
|
|
37
|
+
Do not load every schema body by default.
|
|
42
38
|
|
|
43
39
|
For database work:
|
|
44
40
|
|
|
@@ -46,127 +42,9 @@ For database work:
|
|
|
46
42
|
- Use `pikku meta schemas` for code-level JSON Schema contracts, not database introspection.
|
|
47
43
|
- Do not inspect database credentials or connect to the database directly; Fabric already exposes the safe introspection surface.
|
|
48
44
|
|
|
49
|
-
## Database
|
|
50
|
-
|
|
51
|
-
Fabric apps use SQLite, accessed via Kysely with the libSQL HTTP adapter. NOT PostgreSQL, NOT D1.
|
|
52
|
-
|
|
53
|
-
### Setup in `services.ts`
|
|
54
|
-
|
|
55
|
-
```typescript
|
|
56
|
-
import { Kysely, CamelCasePlugin } from 'kysely'
|
|
57
|
-
import { LibsqlWebDialect } from '@pikku/kysely-sqlite'
|
|
58
|
-
import type { DB } from '#pikku/db/schema.gen.js'
|
|
59
|
-
|
|
60
|
-
const databaseUrl = await variables.get('DATABASE_URL')
|
|
61
|
-
let kysely: Kysely<DB>
|
|
62
|
-
if (databaseUrl) {
|
|
63
|
-
kysely = new Kysely<DB>({
|
|
64
|
-
dialect: new LibsqlWebDialect({ url: databaseUrl }),
|
|
65
|
-
plugins: [new CamelCasePlugin()],
|
|
66
|
-
})
|
|
67
|
-
} else if (existingServices?.kysely) {
|
|
68
|
-
kysely = existingServices.kysely as Kysely<DB>
|
|
69
|
-
} else {
|
|
70
|
-
throw new Error('kysely not provided and DATABASE_URL is unset')
|
|
71
|
-
}
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
Fabric injects `DATABASE_URL` as a variable binding when the stage starts. In local dev, `pikku db migrate` uses a local `dev.db` SQLite file.
|
|
75
|
-
|
|
76
|
-
### Migrations
|
|
77
|
-
|
|
78
|
-
Migrations are plain `.sql` files at the **project root**, in a directory named
|
|
79
|
-
for the engine — `db/sqlite/` for SQLite/libSQL stages, `db/postgres/` for
|
|
80
|
-
Postgres ones. Never `db/migrations/`, and never under `packages/functions/`:
|
|
81
|
-
the deploy pipeline stages `db/<engine>/*.sql` from the root and applies them
|
|
82
|
-
after upload, so a migration anywhere else is silently never run.
|
|
83
|
-
|
|
84
|
-
```
|
|
85
|
-
db/sqlite/
|
|
86
|
-
0001-init.sql
|
|
87
|
-
0002-add-users.sql
|
|
88
|
-
```
|
|
45
|
+
## Database
|
|
89
46
|
|
|
90
|
-
|
|
91
|
-
correct a mistake with a new forward migration, never by editing or renaming one
|
|
92
|
-
that has already run (the recorded hash will no longer match).
|
|
93
|
-
|
|
94
|
-
**Forward-only rule.** Once a migration exists on the base branch (or any stage
|
|
95
|
-
has applied it), never edit, rename or delete it — add a NEW numbered migration
|
|
96
|
-
that makes the change. A stage records a migration by name and never re-runs it,
|
|
97
|
-
so an edit never reaches a database that already applied it. Two guards enforce
|
|
98
|
-
this:
|
|
99
|
-
|
|
100
|
-
- `pikku fabric validate` reports `migration-modified-after-base-*` (error) for
|
|
101
|
-
any `db/<engine>/*.sql` that exists on the base ref (default `origin/main`, else `main`, `origin/master`, `master`,
|
|
102
|
-
compared at the branch's merge-base; override with `--migrations-base <ref>`
|
|
103
|
-
or `PIKKU_MIGRATIONS_BASE`) but was modified, deleted or renamed in the working
|
|
104
|
-
tree. New files are fine. It is skipped outside a git repo or with no base ref.
|
|
105
|
-
In CI use a full clone (`fetch-depth: 0`) so the base ref exists.
|
|
106
|
-
- `pikku fabric deploy apply` runs the migration-history checks first and
|
|
107
|
-
refuses to create a deployment if any fail. It compares against the stage
|
|
108
|
-
being deployed and the production (`main`) stage's applied ledger, and against
|
|
109
|
-
the base ref — a branch stage can be reset at will, but main's history reaches
|
|
110
|
-
production. Findings: `migration-applied-file-missing-*`, `migration-drift-*`,
|
|
111
|
-
`migration-gap`, `migration-modified-after-base-*`. Unlike `validate`, a check
|
|
112
|
-
that cannot run refuses too: an unreadable ledger (`migration-drift-unchecked`)
|
|
113
|
-
or a base ref that does not resolve (`migration-base-unresolved`). There is no
|
|
114
|
-
override flag — fix the history.
|
|
115
|
-
|
|
116
|
-
Fix a finding by restoring the file (`git checkout origin/main -- db/sqlite/<file>`)
|
|
117
|
-
and putting the change in a new migration.
|
|
118
|
-
|
|
119
|
-
Run migrations: `pikku db migrate`. It also regenerates `.pikku/db/schema.gen.ts`
|
|
120
|
-
(Kysely types) and `.pikku/db/zod.gen.ts` — there is no separate types step.
|
|
121
|
-
|
|
122
|
-
**NEVER hand-edit the generated schema** — write a migration and re-run.
|
|
123
|
-
|
|
124
|
-
### Dev seed data
|
|
125
|
-
|
|
126
|
-
Alongside the migrations sits `db/<engine>-dev-seed.sql` — `db/sqlite-dev-seed.sql`
|
|
127
|
-
or `db/postgres-dev-seed.sql`. There is no seed command. `pikku db reset` is the
|
|
128
|
-
only thing that applies it: wipe, migrate, seed. `--no-seed` stops after the
|
|
129
|
-
migration, for working on an empty-state or onboarding flow the test data hides.
|
|
130
|
-
|
|
131
|
-
Because reset always arrives at a database it has just wiped, **the seed file is
|
|
132
|
-
plain `INSERT`s** — no `INSERT OR IGNORE`, no `ON CONFLICT DO NOTHING`, no
|
|
133
|
-
`IF NOT EXISTS`. Nothing applies it twice, so it never has to defend itself. If
|
|
134
|
-
you find yourself reaching for an idempotent form, that's a sign the data wants
|
|
135
|
-
to be a migration instead.
|
|
136
|
-
|
|
137
|
-
This is **local dev data only**: enough rows that a fresh dev database isn't an
|
|
138
|
-
empty app. Nothing else ever runs it. A deployed stage applies `db/<engine>/*.sql`
|
|
139
|
-
and stops there — the one exception is a disposable stage deployed with
|
|
140
|
-
`pikku fabric deploy apply <branch> --reset` (see Deploy), which is never
|
|
141
|
-
production. Local reset refuses `NODE_ENV=production` and refuses a database
|
|
142
|
-
outside the runtime directory.
|
|
143
|
-
|
|
144
|
-
So the test is not "is this row realistic?", it is **"would the app be broken
|
|
145
|
-
without it in production?"** If yes, it is configuration and belongs in a
|
|
146
|
-
migration, however much it looks like sample data. A venue and its rooms, a
|
|
147
|
-
product catalogue, a tenant, a country list, the organization the whole
|
|
148
|
-
deployment hangs off — all configuration. Accounts and role grants are
|
|
149
|
-
provisioning: the fabric plugin's `personas`, or a migration. What is left
|
|
150
|
-
over is the seed's job — the bookings, orders and messages a demo needs and a real
|
|
151
|
-
environment starts without.
|
|
152
|
-
|
|
153
|
-
Get this wrong and it hides: the app is perfect locally, where reset has just
|
|
154
|
-
run, and every deployed environment comes up with empty tables. The signature is
|
|
155
|
-
a stage whose pages return 200 — the shell renders fine — while its first data
|
|
156
|
-
read throws `no result` or a foreign-key violation on a row the seed was
|
|
157
|
-
silently supplying.
|
|
158
|
-
|
|
159
|
-
A Better Auth app has a second constraint: the plugins you enable (`pikkuBan()`,
|
|
160
|
-
`pikkuActor()`, …) each declare columns, and `pikku db migrate` refuses to run while
|
|
161
|
-
the applied schema is missing any of them. `pikku db generate` writes the
|
|
162
|
-
migration that closes the gap.
|
|
163
|
-
|
|
164
|
-
### Column conventions
|
|
165
|
-
|
|
166
|
-
- Use `SERIAL`/`INTEGER PRIMARY KEY AUTOINCREMENT` for IDs
|
|
167
|
-
- Use `TEXT` for strings, `INTEGER` for booleans (0/1) and timestamps (Unix ms)
|
|
168
|
-
- Use `CHECK` constraints sparingly — prefer app-level validation
|
|
169
|
-
- Table and column names: snake_case in SQL, camelCase in TypeScript (via `CamelCasePlugin`)
|
|
47
|
+
Fabric apps use SQLite via Kysely and the libSQL HTTP adapter, not PostgreSQL or D1. `DATABASE_URL` is injected as a variable binding when the stage starts; locally `pikku db migrate` uses a `dev.db` file. Migrations are `.sql` files in `db/sqlite/` at the project root, numbered, gap-free and forward-only; never hand-edit `.pikku/db/schema.gen.ts`. Read `references/database.md` for the `services.ts` setup, the migration guards, dev seed rules and column conventions.
|
|
170
48
|
|
|
171
49
|
## Deploy Provider
|
|
172
50
|
|
|
@@ -370,173 +248,7 @@ those values.
|
|
|
370
248
|
|
|
371
249
|
## Deploy
|
|
372
250
|
|
|
373
|
-
|
|
374
|
-
pikku fabric login # opens a browser; needs a human, wait for it
|
|
375
|
-
pikku fabric init https://github.com/<owner>/<repo>
|
|
376
|
-
pikku fabric validate # must pass clean
|
|
377
|
-
pikku fabric deploy apply --production -y
|
|
378
|
-
```
|
|
379
|
-
|
|
380
|
-
`init` and `link` import into whichever organization your session is in. When
|
|
381
|
-
you belong to several — a personal one and a company one, say — name the target
|
|
382
|
-
with `--organization`, taking a slug, a display name or an id:
|
|
383
|
-
|
|
384
|
-
```bash
|
|
385
|
-
pikku fabric link --organization vlandor
|
|
386
|
-
```
|
|
387
|
-
|
|
388
|
-
You have to be a member of the organization you name, and its GitHub account
|
|
389
|
-
has to be connected already: importing a `github.com/<owner>/<repo>` repo needs
|
|
390
|
-
the Fabric GitHub App installed on `<owner>` _and_ linked to that organization,
|
|
391
|
-
or the import refuses by name.
|
|
392
|
-
|
|
393
|
-
The branch is positional and defaults to the checked-out one, and `-y` is the
|
|
394
|
-
short form of `--auto-approve`, so a one-shot deploy is:
|
|
395
|
-
|
|
396
|
-
```bash
|
|
397
|
-
pikku fabric deploy apply -y # the branch you are standing on
|
|
398
|
-
pikku fabric deploy apply my-branch -y # a named one
|
|
399
|
-
```
|
|
400
|
-
|
|
401
|
-
`-y` answers the prompts and nothing more. It does **not** approve migrations
|
|
402
|
-
that drop or rewrite data — that stays `--allow-destructive`, typed out on
|
|
403
|
-
purpose.
|
|
404
|
-
|
|
405
|
-
### Rebuilding a disposable stage: `--reset`
|
|
406
|
-
|
|
407
|
-
A non-production stage whose migration history or schema has drifted (an app's
|
|
408
|
-
`develop` branch) can be wiped and rebuilt in one deploy:
|
|
409
|
-
|
|
410
|
-
```bash
|
|
411
|
-
pikku fabric deploy apply develop --reset # asks first, naming app + stage
|
|
412
|
-
pikku fabric deploy apply develop --reset -y # prints the warning, skips the prompt
|
|
413
|
-
```
|
|
414
|
-
|
|
415
|
-
It is the deployed counterpart of `pikku db reset`: **all data on that stage is
|
|
416
|
-
deleted**, every migration is re-applied and `db/<engine>-dev-seed.sql` is
|
|
417
|
-
loaded. It is refused for `--production`, for `main`, and with `--deployment-id`
|
|
418
|
-
(it only applies to a deploy it creates). It needs a fabric server that reports
|
|
419
|
-
the reset back on the deployment; against one that does not, the command fails
|
|
420
|
-
naming the deployment it created without a reset, and wipes nothing. `-y` does
|
|
421
|
-
not imply `--allow-destructive`.
|
|
422
|
-
|
|
423
|
-
Inferring the branch is safe because the git safety check refuses any branch
|
|
424
|
-
without an upstream or out of sync with it, so it cannot ship an unpushed
|
|
425
|
-
commit; the branch it picked is printed before the build starts. A detached
|
|
426
|
-
HEAD is refused by name rather than travelling on as a branch called `HEAD`.
|
|
427
|
-
|
|
428
|
-
There is no `deploy plan` subcommand — `apply` runs the same auth, git-safety
|
|
429
|
-
and ref resolution itself, and fabric produces the real plan server-side.
|
|
430
|
-
|
|
431
|
-
`apply` confirms before deploying, and with no TTY to ask — CI, an agent shell —
|
|
432
|
-
it refuses rather than hangs. `--auto-approve` (`-y`) supplies that confirmation;
|
|
433
|
-
drop it only when a human is at a real terminal.
|
|
434
|
-
|
|
435
|
-
`apply` waits for a terminal state and exits non-zero unless the deployment went
|
|
436
|
-
live. `--detach` opts out — it queues the deploy, prints the deployment id and
|
|
437
|
-
returns 0, which tells you nothing about whether it worked:
|
|
438
|
-
|
|
439
|
-
| exit | meaning |
|
|
440
|
-
| ---- | ----------------------------------------------------------------------- |
|
|
441
|
-
| 0 | live (or queued, under `--detach`) |
|
|
442
|
-
| 1 | the command could not run — not logged in, unsafe git state, bad flags |
|
|
443
|
-
| 2 | the deployment failed, errored, timed out server-side, or was cancelled |
|
|
444
|
-
| 3 | the deployment is blocked and nothing the CLI can do will unblock it |
|
|
445
|
-
| 4 | the wait hit `--timeout` with the deployment still in flight |
|
|
446
|
-
|
|
447
|
-
On a failure or timeout, `apply` prints the tail of the builder's own log (and
|
|
448
|
-
carries `buildLog` / `imageBuildLog` on the `--json` result). Read it before
|
|
449
|
-
touching code: `fabric logs` serves the running stage, not the build. When the
|
|
450
|
-
builder recorded nothing, the CLI says so — that is usually fabric-side, so run
|
|
451
|
-
`pikku fabric smoke` before assuming the project is broken.
|
|
452
|
-
|
|
453
|
-
Fabric parks every deploy at a gate after the plan phase (`status: suspended`).
|
|
454
|
-
Why it parked is the whole story, and it is `statusReason`, not `status`:
|
|
455
|
-
|
|
456
|
-
- `awaiting_approval` — the plan is fine, a human has to publish it.
|
|
457
|
-
`-y` does that; without it you get exit 3 and the command to run.
|
|
458
|
-
One exception: if fabric marked any pending migration **destructive** — a
|
|
459
|
-
drop, a truncate, a rewrite — `-y` alone declines and exits 3,
|
|
460
|
-
because a standing yes was given before anyone knew the plan dropped a table.
|
|
461
|
-
The CLI lists the migrations and fabric's reasons; `--allow-destructive`
|
|
462
|
-
accepts them for that deploy, and `-y` implies it.
|
|
463
|
-
- `needs_config` — a declared secret or variable has no value covering the
|
|
464
|
-
stage. The CLI names them. `-y` will **not** force this through;
|
|
465
|
-
set the values and re-attach — `pikku fabric secrets set <name>` for a
|
|
466
|
-
declared secret, `pikku fabric variables set <name> --value <v>` for a declared
|
|
467
|
-
variable. They are separate stores: a secret is sealed to the stage and cannot
|
|
468
|
-
be read back, a variable is stored plainly and can (`variables get`). `set`
|
|
469
|
-
reads the value as JSON when it parses, so `--value true` is the boolean on a
|
|
470
|
-
stage exactly as it is from `.env`, and `--value '"true"'` is the string.
|
|
471
|
-
- `needs_attention` — the plan is red. Nothing to approve.
|
|
472
|
-
|
|
473
|
-
The wait defaults to a 900s ceiling; `--timeout <seconds>` moves it. On timeout
|
|
474
|
-
it prints the deployment id and the re-attach command rather than lying about
|
|
475
|
-
the outcome.
|
|
476
|
-
|
|
477
|
-
Splitting kick-off from waiting across two CI jobs is the reason
|
|
478
|
-
`--deployment-id` exists, and what `--detach` is for — the first job here has to
|
|
479
|
-
return the id and exit rather than wait:
|
|
480
|
-
|
|
481
|
-
```bash
|
|
482
|
-
id=$(pikku fabric deploy apply --production -y --detach --json | jq -r 'select(.event=="result").deploymentId')
|
|
483
|
-
# …later, in another job…
|
|
484
|
-
pikku fabric deploy apply --deployment-id "$id" -y
|
|
485
|
-
```
|
|
486
|
-
|
|
487
|
-
`--deployment-id` skips the git safety check entirely (the deployment already
|
|
488
|
-
pins a sha, and the checkout is allowed to have moved on) and refuses to be
|
|
489
|
-
combined with a branch or `--production`, which would let the two disagree.
|
|
490
|
-
|
|
491
|
-
Under `--json`, the wait emits one NDJSON event per line — `created`/`attached`,
|
|
492
|
-
`status` on each transition, `blocked`, `approved` — and the last line is the
|
|
493
|
-
terminal result object, tagged `"event": "result"`.
|
|
494
|
-
|
|
495
|
-
`init` adopts a **GitHub** repo, and adoption goes through the Pikku Fabric
|
|
496
|
-
GitHub App — the app has to be installed on the account or org that owns the
|
|
497
|
-
repo, and if it is installed with "selected repositories" this one must be in
|
|
498
|
-
the selection. There is no CLI flag that works around a missing installation:
|
|
499
|
-
`init` returns "Connect the GitHub account '<owner>'". Send the user to install
|
|
500
|
-
it, or create the project in the console instead (which provisions a Fabric-hosted
|
|
501
|
-
git repo you push to) and clone it — the remote links the checkout, or put
|
|
502
|
-
the id in `fabric.projectId` in `pikku.config.json`.
|
|
503
|
-
|
|
504
|
-
Deploy refuses to run unless the target branch equals its upstream — the guard
|
|
505
|
-
compares `main` against `main@{upstream}`. So the remote you pushed to must be
|
|
506
|
-
the one the branch tracks; a stale `origin` left over from scaffolding blocks
|
|
507
|
-
the deploy with "local HEAD … ≠ remote …" even though your code is pushed.
|
|
508
|
-
`git branch --set-upstream-to=<remote>/main main` before deploying.
|
|
509
|
-
|
|
510
|
-
### The first user on a deployed stage
|
|
511
|
-
|
|
512
|
-
When sign-up is off, the first account has to come from outside the app.
|
|
513
|
-
`pikku fabric user add <email>` is the CLI form of the console's Add user:
|
|
514
|
-
|
|
515
|
-
```bash
|
|
516
|
-
pikku fabric user add ada@example.com --name Ada # prompts; blank generates one
|
|
517
|
-
pikku fabric user add ada@example.com --password '<pw>' -b staging
|
|
518
|
-
```
|
|
519
|
-
|
|
520
|
-
It mints a short-lived operator token for the stage and calls the stage's own
|
|
521
|
-
`admin:createUser`, so the stage must wire `@pikku/addon-admin` as `admin` —
|
|
522
|
-
a 404 is refused by name and nothing is created. A generated password is printed
|
|
523
|
-
once; one you passed is never echoed. With no TTY, pass `--password` or pipe it.
|
|
524
|
-
|
|
525
|
-
### Opening a private stage
|
|
526
|
-
|
|
527
|
-
A non-production stage is private: without a link it answers "This preview is
|
|
528
|
-
private". `pikku fabric stage link` prints the link that opens it:
|
|
529
|
-
|
|
530
|
-
```bash
|
|
531
|
-
pikku fabric stage link access -b develop --route /login # use the stage
|
|
532
|
-
pikku fabric stage link changes -b develop # use it with the changes panel
|
|
533
|
-
pikku fabric stage visibility public -b develop # or: private
|
|
534
|
-
```
|
|
535
|
-
|
|
536
|
-
A stage has one live link of each kind, so asking again returns the same one
|
|
537
|
-
until it expires. A `changes` link turns the panel on first; if that needs a
|
|
538
|
-
deploy, the command says so. `visibility public` opens the stage to anyone with
|
|
539
|
-
its URL — hand out an `access` link instead when that is all you need.
|
|
251
|
+
Flow: `pikku fabric login` (needs a human), `pikku fabric init <github url>`, `pikku fabric validate` (must pass clean), then `pikku fabric deploy apply --production -y`. `apply` waits for a terminal state and exits non-zero unless the deployment went live. Read `references/deploy.md` for organization targeting, `--reset`, exit codes, the approval gate (`awaiting_approval`, `needs_config`, `needs_attention`), CI splitting, the upstream guard, the first user and private stage links.
|
|
540
252
|
|
|
541
253
|
## Versioning
|
|
542
254
|
|
|
@@ -560,7 +272,7 @@ a **login screen** but no dev actor switcher, and it is not a style nit: a sandb
|
|
|
560
272
|
reviewer has no seed password, so without the control they are locked out of the
|
|
561
273
|
app they were asked to look at.
|
|
562
274
|
|
|
563
|
-
Satisfy it with `<DevActorSwitcher
|
|
275
|
+
Satisfy it with the starter template's `<DevActorSwitcher />`, or with your
|
|
564
276
|
own UI built on `useDevActors()` or `signInAsPersona()` from `@pikku/react` —
|
|
565
277
|
validate accepts any of those call sites as evidence, so custom rendering
|
|
566
278
|
passes. Either way the server needs `personaSignIn` on `pikkuActor`; see
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Fabric database: SQLite via libSQL
|
|
2
|
+
|
|
3
|
+
## Contents
|
|
4
|
+
|
|
5
|
+
- Setup in `services.ts`
|
|
6
|
+
- Migrations
|
|
7
|
+
- Dev seed data
|
|
8
|
+
- Column conventions
|
|
9
|
+
|
|
10
|
+
Fabric apps use SQLite, accessed via Kysely with the libSQL HTTP adapter. NOT PostgreSQL, NOT D1.
|
|
11
|
+
|
|
12
|
+
## Setup in `services.ts`
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
import { Kysely, CamelCasePlugin } from 'kysely'
|
|
16
|
+
import { LibsqlWebDialect } from '@pikku/kysely-sqlite'
|
|
17
|
+
import type { DB } from '#pikku/db/schema.gen.js'
|
|
18
|
+
|
|
19
|
+
const databaseUrl = await variables.get('DATABASE_URL')
|
|
20
|
+
let kysely: Kysely<DB>
|
|
21
|
+
if (databaseUrl) {
|
|
22
|
+
kysely = new Kysely<DB>({
|
|
23
|
+
dialect: new LibsqlWebDialect({ url: databaseUrl }),
|
|
24
|
+
plugins: [new CamelCasePlugin()],
|
|
25
|
+
})
|
|
26
|
+
} else if (existingServices?.kysely) {
|
|
27
|
+
kysely = existingServices.kysely as Kysely<DB>
|
|
28
|
+
} else {
|
|
29
|
+
throw new Error('kysely not provided and DATABASE_URL is unset')
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Fabric injects `DATABASE_URL` as a variable binding when the stage starts. In local dev, `pikku db migrate` uses a local `dev.db` SQLite file.
|
|
34
|
+
|
|
35
|
+
## Migrations
|
|
36
|
+
|
|
37
|
+
Migrations are plain `.sql` files at the **project root**, in a directory named
|
|
38
|
+
for the engine — `db/sqlite/` for SQLite/libSQL stages, `db/postgres/` for
|
|
39
|
+
Postgres ones. Never `db/migrations/`, and never under `packages/functions/`:
|
|
40
|
+
the deploy pipeline stages `db/<engine>/*.sql` from the root and applies them
|
|
41
|
+
after upload, so a migration anywhere else is silently never run.
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
db/sqlite/
|
|
45
|
+
0001-init.sql
|
|
46
|
+
0002-add-users.sql
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Numbers must be consecutive and gap-free, and an applied migration is frozen —
|
|
50
|
+
correct a mistake with a new forward migration, never by editing or renaming one
|
|
51
|
+
that has already run (the recorded hash will no longer match).
|
|
52
|
+
|
|
53
|
+
**Forward-only rule.** Once a migration exists on the base branch (or any stage
|
|
54
|
+
has applied it), never edit, rename or delete it — add a NEW numbered migration
|
|
55
|
+
that makes the change. A stage records a migration by name and never re-runs it,
|
|
56
|
+
so an edit never reaches a database that already applied it. Two guards enforce
|
|
57
|
+
this:
|
|
58
|
+
|
|
59
|
+
- `pikku fabric validate` reports `migration-modified-after-base-*` (error) for
|
|
60
|
+
any `db/<engine>/*.sql` that exists on the base ref (default `origin/main`, else `main`, `origin/master`, `master`,
|
|
61
|
+
compared at the branch's merge-base; override with `--migrations-base <ref>`
|
|
62
|
+
or `PIKKU_MIGRATIONS_BASE`) but was modified, deleted or renamed in the working
|
|
63
|
+
tree. New files are fine. It is skipped outside a git repo or with no base ref.
|
|
64
|
+
In CI use a full clone (`fetch-depth: 0`) so the base ref exists.
|
|
65
|
+
- `pikku fabric deploy apply` runs the migration-history checks first and
|
|
66
|
+
refuses to create a deployment if any fail. It compares against the stage
|
|
67
|
+
being deployed and the production (`main`) stage's applied ledger, and against
|
|
68
|
+
the base ref — a branch stage can be reset at will, but main's history reaches
|
|
69
|
+
production. Findings: `migration-applied-file-missing-*`, `migration-drift-*`,
|
|
70
|
+
`migration-gap`, `migration-modified-after-base-*`. Unlike `validate`, a check
|
|
71
|
+
that cannot run refuses too: an unreadable ledger (`migration-drift-unchecked`)
|
|
72
|
+
or a base ref that does not resolve (`migration-base-unresolved`). There is no
|
|
73
|
+
override flag — fix the history.
|
|
74
|
+
|
|
75
|
+
Fix a finding by restoring the file (`git checkout origin/main -- db/sqlite/<file>`)
|
|
76
|
+
and putting the change in a new migration.
|
|
77
|
+
|
|
78
|
+
Run migrations: `pikku db migrate`. It also regenerates `.pikku/db/schema.gen.ts`
|
|
79
|
+
(Kysely types) and `.pikku/db/zod.gen.ts` — there is no separate types step.
|
|
80
|
+
|
|
81
|
+
**NEVER hand-edit the generated schema** — write a migration and re-run.
|
|
82
|
+
|
|
83
|
+
## Dev seed data
|
|
84
|
+
|
|
85
|
+
Alongside the migrations sits `db/<engine>-dev-seed.sql` — `db/sqlite-dev-seed.sql`
|
|
86
|
+
or `db/postgres-dev-seed.sql`. There is no seed command. `pikku db reset` is the
|
|
87
|
+
only thing that applies it: wipe, migrate, seed. `--no-seed` stops after the
|
|
88
|
+
migration, for working on an empty-state or onboarding flow the test data hides.
|
|
89
|
+
|
|
90
|
+
Because reset always arrives at a database it has just wiped, **the seed file is
|
|
91
|
+
plain `INSERT`s** — no `INSERT OR IGNORE`, no `ON CONFLICT DO NOTHING`, no
|
|
92
|
+
`IF NOT EXISTS`. Nothing applies it twice, so it never has to defend itself. If
|
|
93
|
+
you find yourself reaching for an idempotent form, that's a sign the data wants
|
|
94
|
+
to be a migration instead.
|
|
95
|
+
|
|
96
|
+
This is **local dev data only**: enough rows that a fresh dev database isn't an
|
|
97
|
+
empty app. Nothing else ever runs it. A deployed stage applies `db/<engine>/*.sql`
|
|
98
|
+
and stops there — the one exception is a disposable stage deployed with
|
|
99
|
+
`pikku fabric deploy apply <branch> --reset` (see `deploy.md`), which is never
|
|
100
|
+
production. Local reset refuses `NODE_ENV=production` and refuses a database
|
|
101
|
+
outside the runtime directory.
|
|
102
|
+
|
|
103
|
+
So the test is not "is this row realistic?", it is **"would the app be broken
|
|
104
|
+
without it in production?"** If yes, it is configuration and belongs in a
|
|
105
|
+
migration, however much it looks like sample data. A venue and its rooms, a
|
|
106
|
+
product catalogue, a tenant, a country list, the organization the whole
|
|
107
|
+
deployment hangs off — all configuration. Accounts and role grants are
|
|
108
|
+
provisioning: the fabric plugin's `personas`, or a migration. What is left
|
|
109
|
+
over is the seed's job — the bookings, orders and messages a demo needs and a real
|
|
110
|
+
environment starts without.
|
|
111
|
+
|
|
112
|
+
Get this wrong and it hides: the app is perfect locally, where reset has just
|
|
113
|
+
run, and every deployed environment comes up with empty tables. The signature is
|
|
114
|
+
a stage whose pages return 200 — the shell renders fine — while its first data
|
|
115
|
+
read throws `no result` or a foreign-key violation on a row the seed was
|
|
116
|
+
silently supplying.
|
|
117
|
+
|
|
118
|
+
A Better Auth app has a second constraint: the plugins you enable (`pikkuBan()`,
|
|
119
|
+
`pikkuActor()`, …) each declare columns, and `pikku db migrate` refuses to run while
|
|
120
|
+
the applied schema is missing any of them. `pikku db generate` writes the
|
|
121
|
+
migration that closes the gap.
|
|
122
|
+
|
|
123
|
+
## Column conventions
|
|
124
|
+
|
|
125
|
+
- Use `SERIAL`/`INTEGER PRIMARY KEY AUTOINCREMENT` for IDs
|
|
126
|
+
- Use `TEXT` for strings, `INTEGER` for booleans (0/1) and timestamps (Unix ms)
|
|
127
|
+
- Use `CHECK` constraints sparingly — prefer app-level validation
|
|
128
|
+
- Table and column names: snake_case in SQL, camelCase in TypeScript (via `CamelCasePlugin`)
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
# Debugging a deployed Fabric stage
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## Contents
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
- Operating procedure
|
|
6
|
+
- The loop (errors, trace, metrics, logs, status)
|
|
7
|
+
- Known gaps
|
|
8
|
+
- What not to do
|
|
9
|
+
|
|
10
|
+
## Operating procedure
|
|
6
11
|
|
|
7
12
|
1. Reproduce locally first. If it fails locally too, debug it there — the
|
|
8
13
|
deployed stage adds cost and latency to every iteration.
|
|
@@ -92,9 +97,8 @@ deploy stuck in flight, explains a whole class of "my fix did nothing".
|
|
|
92
97
|
not conclude "nothing happened in the last 15 minutes" from it. Narrow by
|
|
93
98
|
`--level`, or by `--function` via `errors`, instead.
|
|
94
99
|
- **`--follow` is a 2-second client-side poll, not a server stream** — despite
|
|
95
|
-
its own help text reading "Stream new logs (SSE)".
|
|
96
|
-
|
|
97
|
-
dedups against what it already printed, so it behaves like `tail -f`, but new
|
|
100
|
+
its own help text reading "Stream new logs (SSE)". The backend does not push
|
|
101
|
+
natively. It dedups against what it already printed, so it behaves like `tail -f`, but new
|
|
98
102
|
entries can appear up to ~2s late and it holds the process open until killed.
|
|
99
103
|
|
|
100
104
|
## What NOT to do
|