@pikku/skills 0.12.47 → 0.12.49
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-addon/SKILL.md +6 -0
- package/skills/pikku-build/references/app.md +2 -1
- package/skills/pikku-build/references/quick.md +2 -1
- package/skills/pikku-fabric/SKILL.md +16 -0
- package/skills/pikku-kysely/SKILL.md +19 -0
- package/skills/pikku-wiring/references/trigger.md +19 -6
package/package.json
CHANGED
|
@@ -292,8 +292,14 @@ Author the DDL per dialect:
|
|
|
292
292
|
```text
|
|
293
293
|
db/sqlite/0001-labels.sql
|
|
294
294
|
db/postgres/0001-labels.sql
|
|
295
|
+
db/mysql/0001-labels.sql
|
|
295
296
|
```
|
|
296
297
|
|
|
298
|
+
`db/mysql` is the one that needs a server to publish: MySQL has no embedded
|
|
299
|
+
engine, so `pikku all` applies the SQL to a scratch database on the server named
|
|
300
|
+
by `db.mysqlUrl` in the addon's `pikku.config.json`, and refuses to build
|
|
301
|
+
without one. Use `varchar(n)` for a key column — MySQL rejects `TEXT` there.
|
|
302
|
+
|
|
297
303
|
`pikku all` publishes `<outDir>/db/pikku-db-meta.gen.json` on every build — per
|
|
298
304
|
dialect, the SQL verbatim plus a table/column map — and writes it **empty** when
|
|
299
305
|
the addon has no tables, because a consumer reads an absent file as a package
|
|
@@ -436,7 +436,8 @@ covered_. A stack of half-milestones cannot be reviewed and cannot be handed
|
|
|
436
436
|
over, and an uncovered function is a half-milestone whether or not the note says
|
|
437
437
|
`built`.
|
|
438
438
|
|
|
439
|
-
1. **Migration.** SQL in `db/sqlite/` at the project root
|
|
439
|
+
1. **Migration.** SQL in `db/sqlite/` at the project root (`db/postgres/` or
|
|
440
|
+
`db/mysql/` when `createConfig` sets `postgresUrl` or `mysqlUrl`), numbered on from the
|
|
440
441
|
ones already there. Apply with `bunx --bun pikku db migrate`, which also
|
|
441
442
|
regenerates the Kysely types your functions import. **Neither `pikku all` nor
|
|
442
443
|
restarting `pikku dev` applies a migration** — so a new column reads as
|
|
@@ -103,7 +103,8 @@ codegen depends on; without it your first `db migrate` fails with
|
|
|
103
103
|
|
|
104
104
|
Then, in this order — it is the order codegen depends on:
|
|
105
105
|
|
|
106
|
-
1. **Migration** — SQL in `db/sqlite
|
|
106
|
+
1. **Migration** — SQL in `db/sqlite/` (or `db/postgres/`, `db/mysql/` when
|
|
107
|
+
`createConfig` sets `postgresUrl` or `mysqlUrl`), numbered on from what is there. Apply
|
|
107
108
|
with `bunx --bun pikku db migrate`, which regenerates the Kysely types.
|
|
108
109
|
2. **Seed** — rows in `db/sqlite-dev-seed.sql`. There is no seed command:
|
|
109
110
|
`bunx --bun pikku db reset` wipes, migrates and seeds in one go, and is the
|
|
@@ -522,6 +522,22 @@ It mints a short-lived operator token for the stage and calls the stage's own
|
|
|
522
522
|
a 404 is refused by name and nothing is created. A generated password is printed
|
|
523
523
|
once; one you passed is never echoed. With no TTY, pass `--password` or pipe it.
|
|
524
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.
|
|
540
|
+
|
|
525
541
|
## Versioning
|
|
526
542
|
|
|
527
543
|
Functions with `expose: true` are versioned via `versions.pikku.json`. When you change a function's input or output schema, you must bump its version number — otherwise `pikku all` will report a breaking change and callers' generated clients become stale.
|
|
@@ -305,6 +305,25 @@ than the CamelCasePlugin, because it exists to back the stores below. Reach for
|
|
|
305
305
|
`createNodeSqliteKysely` / `createBunSqliteKysely` for the instance your
|
|
306
306
|
functions query.
|
|
307
307
|
|
|
308
|
+
### MySQL and `pikku db`
|
|
309
|
+
|
|
310
|
+
`mysqlUrl` in `createConfig` makes MySQL the third dialect the `pikku db`
|
|
311
|
+
commands drive, with migrations in `db/mysql/` and the seed in
|
|
312
|
+
`db/mysql-dev-seed.sql`. It behaves like the other two with four differences:
|
|
313
|
+
|
|
314
|
+
- **No embedded engine.** Commands that need a throwaway database create and drop
|
|
315
|
+
a `pikku_scratch_<hex>` one on your server, so the account needs `CREATE` and
|
|
316
|
+
`DROP`.
|
|
317
|
+
- **DDL is not transactional.** A migration that fails halfway is replayed from
|
|
318
|
+
the top, so write migrations that are safe to run twice.
|
|
319
|
+
- **Inline `REFERENCES` is discarded** — declare foreign keys as
|
|
320
|
+
`FOREIGN KEY (...) REFERENCES ...` or none exists.
|
|
321
|
+
- **A key column cannot be `TEXT`**, nor can a `TEXT` column have a literal
|
|
322
|
+
default. Use `varchar(n)`, or `DEFAULT ('...')` for an expression default.
|
|
323
|
+
|
|
324
|
+
`db.schema` is refused (a MySQL schema is a database), and a standalone bundle
|
|
325
|
+
cannot target MySQL yet.
|
|
326
|
+
|
|
308
327
|
### Available Services
|
|
309
328
|
|
|
310
329
|
Each database variant exports these services with a prefix (`Pg`, `MySQL`, `SQLite`, or base `Kysely`):
|
|
@@ -107,17 +107,30 @@ subscribe to its events as `<source>:<event>`:
|
|
|
107
107
|
- The route is `POST /webhooks/<name>` unless `method`/`route` say otherwise.
|
|
108
108
|
`method` may be a list, e.g. `['get', 'post']` for a provider that verifies
|
|
109
109
|
the URL with a GET and delivers events with a POST, or `['head', 'post']`
|
|
110
|
-
for one that checks the URL with a HEAD.
|
|
111
|
-
It needs no session.
|
|
110
|
+
for one that checks the URL with a HEAD. A HEAD is answered with a `200`
|
|
111
|
+
before `verify` or `receive` run. It needs no session.
|
|
112
112
|
- `events` maps each event name to a schema. An event that fails its schema is
|
|
113
113
|
logged and dropped; so is one no `wireTrigger` listens for. Both still get a
|
|
114
114
|
`200`, so the provider does not retry forever.
|
|
115
|
-
- `receive(services, { body, headers, method, url, query })` gets the
|
|
116
|
-
bytes** and only parses them: it returns `{ events: [{ name, id?, data }] }
|
|
117
|
-
|
|
115
|
+
- `receive(services, { body, headers, method, url, query }, { http })` gets the
|
|
116
|
+
**raw bytes** and only parses them: it returns `{ events: [{ name, id?, data }] }`.
|
|
117
|
+
A handshake returns nothing and answers through `http.response`
|
|
118
|
+
(`http.response.header('x-hook-secret', secret)`,
|
|
119
|
+
`http.response.json({ challenge })`), which is sent only then. Throwing
|
|
118
120
|
rejects the request with the error's status (`UnauthorizedError` → 401).
|
|
119
121
|
Omitted, the JSON body becomes one event dispatched to a trigger named just
|
|
120
122
|
`<source>`.
|
|
123
|
+
- A named `receive` is declared with `pikkuWebhookReceive` from `#pikku/trigger`
|
|
124
|
+
(`#pikku/addon/trigger` in an addon), never `pikkuSessionlessFunc`: it is
|
|
125
|
+
public, typed to the request, and never callable as an RPC. The inspector
|
|
126
|
+
rejects any other wrapper. `parseJson` from `#pikku/utils`
|
|
127
|
+
(`#pikku/addon/utils`) parses the bytes and answers a body that is not JSON
|
|
128
|
+
with a 400:
|
|
129
|
+
|
|
130
|
+
```ts snippet:pikkuWebhookReceive
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
|
|
121
134
|
- Every accepted event is queued on `pikku-incoming-webhooks` and run by a
|
|
122
135
|
generated worker, so the provider is answered quickly and a failing trigger is
|
|
123
136
|
retried by the queue. This needs a `queueService` and an
|
|
@@ -150,7 +163,7 @@ subscribe to its events as `<source>:<event>`:
|
|
|
150
163
|
`timingSafeStringEqual` in `@pikku/core/hmac`.
|
|
151
164
|
|
|
152
165
|
A request with a body that fails is refused with a 401. A bodiless request
|
|
153
|
-
that fails (a
|
|
166
|
+
that fails (a validation token in the query) still reaches
|
|
154
167
|
`receive` so it can answer the handshake, but any events it returns are
|
|
155
168
|
refused. A handshake that hands over the secret (Asana) stores it with
|
|
156
169
|
`credentialService.set` under the same credential name.
|