# Coming from PocketBase

> locosdk keeps PocketBase's storage, wire and rule language, so a PocketBase app moves with golo schema import and keeps its database as is.

locosdk is a native Bun and SQLite backend that copies PocketBase at the edges. It copies the features apps use, not all of PocketBase. The filter and rule language is the one thing copied whole. The reference is PocketBase v0.40.6.

## What stays the same

- **Storage, byte for byte.** `_collections`, one table per collection, the same column types, ids and date format. A `pb_data/data.db` opens as is, and what locosdk writes PocketBase reads back. Password hashes and tokens verify both ways.
- **The REST wire.** The same routes, query parameters, record shape and error shape. A client that talks to PocketBase talks to locosdk.
- **The rule and filter language.** The same grammar, operators, modifiers, macros and functions, compiled to SQL that answers the same ids as PocketBase on the same data.
- **Hooks by the same names.** `onRecordCreateRequest`, `onRecordAfterUpdateSuccess`, `onMailerSend`, `onBackupCreate`… with `e.next()`, as in PocketBase's JavaScript hooks.
- **Backups.** A PocketBase backup zip restores into a locosdk app.

## What changes on purpose

| PocketBase | locosdk |
|---|---|
| the admin's collection editor and migration files | `schema.ts`: additive changes apply at boot, a destructive one needs a migration |
| the settings in the database | `createApp` options and `schema.ts`. An auth option edited in the database is reset at the next boot |
| typegen for the client | record types inferred from `schema.ts` |
| hooks in a JavaScript VM | plain TypeScript in the app's process: no VM, crons just run |
| auth token 5 days | 12 hours. Rate limit `*:auth` 5 per 3 s (PocketBase: 2) |
| `sendmail` when SMTP is off | SMTP always; no fallback |

Smaller differences in the rule compiler: a group must stand where an operand starts (PocketBase silently reads `a = (b = 1)` as `(b = 1)`; locosdk refuses it), strings round trip exactly through `filter()`, and the same input always gives the same SQL.

## Move an app

```sh
bunx golo schema import pb_data/data.db --out schema.ts
```

- The input is a `data.db` or the collections export of the PocketBase admin. Only `_collections` is read, never a record. The database is opened read only.
- The output is the `schema.ts` a person writes by hand: builders, collections in source order, an option only where it differs from the builder's default, rules, indexes verbatim, views with typed fields, relation targets by name, auth options that differ from the defaults. Secrets are never written.
- A custom mail template becomes a reference in one `templates` block at the top of the file, with an empty body to fill from the source. The boot refuses an empty body, so an unfilled template fails loudly and never overwrites the source's.
- `// unsupported: …` lines (also on stderr) mark what the model cannot express: an unknown field type, an option the model lacks, OAuth2 turned on. `--strict` exits 1 when there is any.
- `// note: …` lines never fail: a collection id that a fresh database derives differently, a template to fill.

Stop PocketBase, so its write ahead log is folded into the file. Then copy `pb_data/data.db` to `data/app.db` and `pb_data/storage/` to `data/storage/`, and boot. The import is tested this way: the app boots on a copy of the source database, refuses nothing, and leaves every table and every auth option as it was.

## The features, measured on real apps

**In:** records (list, filter, sort, `fields`, `expand`, `skipTotal`, pages up to 1000, getOne, getFirst, create, update, delete), rules on every action, view collections over any SELECT, every common field type with its options, password auth, JWT and refresh, codes by email, two factors, password reset, email change, auth alerts, superusers, batch, hooks, custom routes, crons, raw SQL, mail with attachments, files on disk or S3 with protected files, `/api/health`, the auth rate limit behind a trusted proxy, backups, the read only collections API, schema import.

**Not here yet:** the auto backup failure mail, a superuser IP filter on backup downloads, a boot time syntax check of the two factor rule.

**Skipped until an app asks:** realtime subscriptions (the data layer refetches on a write counter instead), image thumbs, email verification flows, impersonation, listing auth methods, the logs API, batch upsert, expand deeper than one level, OAuth2 sign in.

> **Note.** The admin UI of PocketBase is not part of locosdk. The app's own screens, built on `locosdk/ui`, are the admin.
