Files
2026-07-12 10:17:17 -04:00

96 lines
3.6 KiB
Markdown

# PB 0.39.1 JS Migration Quirks
Collected during SPQ-v2 Phase 4 implementation (2026-07-07).
## API Rule Validation Ordering Bug
**Symptom:** `listRule` / `viewRule` / `createRule` that reference custom fields fail with `invalid left operand "foo" - unknown field "foo"` even when the field IS in the schema.
**Root cause:** PB 0.39 validates API rules against its internal schema snapshot at rule-set time. If you create a collection AND set rules in the same `migrate()` call, the rules validator is running against the PRE-COMMIT snapshot (which doesn't have the new fields yet).
**What does NOT work (all three tried, all failed):**
1. Saving with empty rules, then setting rules on the same object + `app.save()` again — FAILS
2. Saving with empty rules, then `app.findCollectionByNameOrId()`, setting rules on fetched object + `app.save()` — FAILS
3. Separate migration file (M27 — after M25/M26 committed) — STILL FAILS
**The rules validator always runs against the pre-commit snapshot.** The only workaround for single-shop deployments: use empty rules (`''`) and rely on frontend filtering + `createRule: null` for write protection on server-side hook-only collections.
**When you need scoped rules:** Use the PocketBase admin UI after deployment, not JS migrations.
## Missing Field Constructors
| Wanted | Use Instead |
|--------|-------------|
| `DateTimeField` | `TextField` — store ISO strings |
| `DateField` | `TextField` — store ISO strings |
Available constructors (confirmed working in PB 0.39.1):
- `TextField`
- `EmailField`
- `SelectField`
- `JSONField`
- `BoolField`
- `NumberField` (likely, not confirmed)
## JS Runtime Support
PB 0.39.1 uses Goja (Go-based ES runtime). Confirmed working:
-`const`, `let`, `var`
- ✅ Template literals `` `hello ${world}` ``
- ✅ Arrow functions `(x) => x + 1`
-`Object.keys()`, `Array.forEach()`, `JSON.stringify()`
-`new Collection({ name, type, schema: [...] })`
-`new Record(collection, data)`
## Hook Event Names
| Correct API (PB 0.39) | Names that DON'T exist |
|------------------------|------------------------|
| `app.onRecordCreateRequest((e) => { ... })` | — |
| `app.onRecordUpdateRequest((e) => { ... })` | `onRecordBeforeUpdateRequest`, `onRecordAfterUpdateRequest` |
| `app.onRecordDeleteRequest((e) => { ... })` | — |
Only the three "Request" hooks exist — there are no "Before"/"After" variants.
## Record Access in Hooks
- `e.record` — the record being saved (in update hooks, this is the NEW data)
- `e.oldRecord` — available in update hooks, the current DB state before the update
- `e.dao` — data access object for querying other collections
- `e.httpContext` — access to the HTTP request (query params, headers)
## Creating Records Inside Hooks
```js
var collection = app.findCollectionByNameOrId('myCollection');
var record = new Record(collection, {
field1: 'value1',
field2: 'value2',
});
e.dao.saveRecord(record);
```
## Public Share-Token Access Pattern
To detect if a request is using the public share-token path (vs. authenticated API):
```js
var shareToken = e.httpContext?.request?.query?.get('shareToken') || '';
if (shareToken) {
// This is a public (unauthenticated) update via share link
// Enforce expiry, restrict fields, etc.
}
```
## Mailer API (for sending email in hooks)
```js
var mailer = app.getMailer();
await mailer.send({
to: [{ address: 'user@example.com', name: 'Name' }],
subject: 'Subject',
html: '<p>HTML body</p>',
});
```
Requires SMTP env vars set on the PB container (PB will crash on startup without valid `PB_SMTP_*` vars once mailer is used).