From 398ed0cfb67ee876b3134148aeb6858b75db47c3 Mon Sep 17 00:00:00 2001 From: Basile Vernouillet Date: Mon, 1 Jun 2026 11:55:22 +0200 Subject: [PATCH 1/6] =?UTF-8?q?docs:=20restructure=20docs=20around=20Di?= =?UTF-8?q?=C3=A1taxis=20+=20add=20migration=20guide?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reorganize the docs site into the four Diátaxis sections (Tutorials, How-to Guides, Reference, Explanation), reclassify existing pages, and fill the missing Explanation content. - Add how-to/migrate-from-pocketbase-typegen guide - Move pages into tutorials/, how-to/, reference/, explanation/ and re-order the sidebar accordingly - Split expand-types into a reference page + a new explanation page - Add explanation pages: how pbkit works, the generated files, relations and expand paths, why a generated SDK - Reframe Quick Start as a guided tutorial ("Your first typed SDK") - Update all internal links and nav to the new paths Co-Authored-By: Claude Opus 4.8 (1M context) --- apps/docs/astro.config.mjs | 28 +-- .../docs/explanation/generated-files.md | 54 ++++ .../docs/explanation/how-pbkit-works.md | 66 +++++ .../docs/explanation/relations-and-expand.md | 55 ++++ .../docs/explanation/why-a-generated-sdk.md | 71 ++++++ .../docs/generated-output/expand-types.md | 63 ----- .../docs/getting-started/quick-start.md | 94 ------- .../add-tanstack-query.md} | 4 +- .../zod.md => how-to/add-zod-schemas.md} | 4 +- .../configure-collections.md} | 2 +- .../installation.md => how-to/install.md} | 6 +- .../how-to/migrate-from-pocketbase-typegen.md | 238 ++++++++++++++++++ .../authoring.md => how-to/write-a-plugin.md} | 4 +- apps/docs/src/content/docs/index.md | 2 +- .../docs/{cli/usage.md => reference/cli.md} | 2 +- .../configuration.md} | 8 +- .../content/docs/reference/expand-types.md | 61 +++++ .../field-type-mapping.md | 4 +- .../sdk.md => reference/generated-sdk.md} | 2 +- .../types.md => reference/generated-types.md} | 4 +- .../programmatic-api.md} | 2 +- .../content/docs/tutorials/your-first-sdk.md | 116 +++++++++ 22 files changed, 693 insertions(+), 197 deletions(-) create mode 100644 apps/docs/src/content/docs/explanation/generated-files.md create mode 100644 apps/docs/src/content/docs/explanation/how-pbkit-works.md create mode 100644 apps/docs/src/content/docs/explanation/relations-and-expand.md create mode 100644 apps/docs/src/content/docs/explanation/why-a-generated-sdk.md delete mode 100644 apps/docs/src/content/docs/generated-output/expand-types.md delete mode 100644 apps/docs/src/content/docs/getting-started/quick-start.md rename apps/docs/src/content/docs/{plugins/tanstack-query.md => how-to/add-tanstack-query.md} (99%) rename apps/docs/src/content/docs/{plugins/zod.md => how-to/add-zod-schemas.md} (99%) rename apps/docs/src/content/docs/{configuration/collections.md => how-to/configure-collections.md} (98%) rename apps/docs/src/content/docs/{getting-started/installation.md => how-to/install.md} (68%) create mode 100644 apps/docs/src/content/docs/how-to/migrate-from-pocketbase-typegen.md rename apps/docs/src/content/docs/{plugins/authoring.md => how-to/write-a-plugin.md} (98%) rename apps/docs/src/content/docs/{cli/usage.md => reference/cli.md} (98%) rename apps/docs/src/content/docs/{configuration/pbkit-config.md => reference/configuration.md} (91%) create mode 100644 apps/docs/src/content/docs/reference/expand-types.md rename apps/docs/src/content/docs/{generated-output => reference}/field-type-mapping.md (98%) rename apps/docs/src/content/docs/{generated-output/sdk.md => reference/generated-sdk.md} (99%) rename apps/docs/src/content/docs/{generated-output/types.md => reference/generated-types.md} (98%) rename apps/docs/src/content/docs/{api/programmatic.md => reference/programmatic-api.md} (99%) create mode 100644 apps/docs/src/content/docs/tutorials/your-first-sdk.md diff --git a/apps/docs/astro.config.mjs b/apps/docs/astro.config.mjs index 91a0e73..da94980 100644 --- a/apps/docs/astro.config.mjs +++ b/apps/docs/astro.config.mjs @@ -21,36 +21,28 @@ export default defineConfig({ plugins: [ lucode({ navLinks: [ - { label: "Docs", link: "/getting-started/installation/" }, - { label: "API", link: "/api/programmatic/" }, + { label: "Docs", link: "/tutorials/your-first-sdk/" }, + { label: "Reference", link: "/reference/cli/" }, ], }), ], sidebar: [ { label: "Home", link: "/" }, { - label: "Getting Started", - autogenerate: { directory: "getting-started" }, + label: "Tutorials", + autogenerate: { directory: "tutorials" }, }, { - label: "Configuration", - autogenerate: { directory: "configuration" }, + label: "How-to Guides", + autogenerate: { directory: "how-to" }, }, { - label: "Generated Output", - autogenerate: { directory: "generated-output" }, + label: "Reference", + autogenerate: { directory: "reference" }, }, { - label: "CLI", - autogenerate: { directory: "cli" }, - }, - { - label: "Plugins", - autogenerate: { directory: "plugins" }, - }, - { - label: "API", - autogenerate: { directory: "api" }, + label: "Explanation", + autogenerate: { directory: "explanation" }, }, ], editLink: { diff --git a/apps/docs/src/content/docs/explanation/generated-files.md b/apps/docs/src/content/docs/explanation/generated-files.md new file mode 100644 index 0000000..ff1b35a --- /dev/null +++ b/apps/docs/src/content/docs/explanation/generated-files.md @@ -0,0 +1,54 @@ +--- +title: The generated files +description: What types.gen.ts, client.gen.ts, and sdk.gen.ts each do, and why pbkit splits them. +sidebar: + order: 2 +--- + +A default run writes three files into your `output` directory. They are split by +responsibility, and knowing which is which tells you what to import and what to +leave alone. + +| File | Responsibility | You import from it | +|---|---|---| +| `types.gen.ts` | Pure TypeScript types — no runtime code | Yes, for type annotations | +| `client.gen.ts` | A single configured PocketBase client instance | Rarely — directly only for advanced cases | +| `sdk.gen.ts` | Typed CRUD functions that use the client | Yes, for every data call | + +## Why three files instead of one + +The split mirrors the boundary between **types** and **runtime code**. + +`types.gen.ts` contains only `type`/`interface` declarations, so it is erased at +build time and can be imported with `import type` from anywhere — including +environments where you would never want a PocketBase client (shared packages, +edge configs, test fixtures). + +`client.gen.ts` is the one place a concrete client is instantiated, using your +`sdk.baseUrl`. Isolating it means there is exactly one client to configure or +replace, and the type-only file stays free of runtime imports. + +`sdk.gen.ts` is the runtime surface you actually call. It depends on both of the +other files: it uses the types for its signatures and the client to make +requests. Each function also accepts a per-call `client` override, so you are +never locked into the singleton — see +[Generated SDK](/reference/generated-sdk#crud-functions). + +Plugins add their own `*.gen.ts` files (such as `tanstack.gen.ts` or +`zod.gen.ts`) alongside these, following the same convention. + +## Treat them as build artifacts + +The `output` directory is **cleared and rewritten on every run**. That has two +consequences: + +- **Never edit a `.gen.ts` file by hand** — your changes will be lost on the next + generate. Put custom logic in your own modules that import from the generated SDK. +- **Re-generate whenever the schema changes.** The files are a snapshot of the + schema at generation time; the [`--watch`](/reference/cli#watch-mode) flag keeps + them current during development. + +Whether you commit the generated files or generate them in CI is your choice. +Committing them makes diffs reviewable and builds reproducible without a live +PocketBase; generating in CI keeps them guaranteed-fresh. Either works because +generation is deterministic for a given schema. diff --git a/apps/docs/src/content/docs/explanation/how-pbkit-works.md b/apps/docs/src/content/docs/explanation/how-pbkit-works.md new file mode 100644 index 0000000..5bcf0a8 --- /dev/null +++ b/apps/docs/src/content/docs/explanation/how-pbkit-works.md @@ -0,0 +1,66 @@ +--- +title: How pbkit works +description: The pipeline pbkit runs to turn a PocketBase schema into typed code, and why it is shaped that way. +sidebar: + order: 1 +--- + +pbkit is a code generator. Every run follows the same three-stage pipeline: +**parse → represent → generate**. Understanding these stages explains most of +pbkit's behaviour and configuration. + +## The pipeline + +``` +schema source ──► parse ──► Schema IR ──► generate ──► .gen.ts files +(URL / JSON / (normalized (types, client, + SQLite) collections sdk, + plugins) + + relations) +``` + +### 1. Parse + +pbkit reads your schema from whatever source you configure in `input` — a live +PocketBase API, an exported JSON file, or (programmatically) a SQLite database. +Each source has a different raw shape, so each has its own parser +(`parseApi`, `parseJson`, `parseSqlite`). + +### 2. The Schema IR + +All parsers produce the same output: a **Schema Intermediate Representation +(IR)**. This is a normalized, source-agnostic description of your collections, +their fields, and the relations between them. + +The IR is the heart of pbkit. Because every generator and every plugin consumes +the IR rather than raw PocketBase data, they don't care where the schema came +from — generating from a live API and from an exported JSON file produce +identical output. The IR is also what plugins receive as `ctx.ir`, which is why +a plugin can work without knowing anything about API tokens or file paths. + +### 3. Generate + +The generators walk the IR and emit code: + +- the **types** generator produces `types.gen.ts` +- the **SDK** generator produces `client.gen.ts` and `sdk.gen.ts` +- each **plugin** produces its own files (e.g. `tanstack.gen.ts`, `zod.gen.ts`) + +Finally, pbkit clears the `output` directory and writes all files. The directory +is rewritten on every run — see [The generated files](/explanation/generated-files) +for why that is safe and how you should treat the output. + +## Why a generator instead of a runtime library? + +pbkit could have been a runtime library that infers types from your schema at +runtime. It is a generator instead because generated code is **plain, readable +TypeScript you can open and inspect**, it has **zero runtime cost** beyond the +official PocketBase SDK, and your editor gets **full autocomplete** with no +type-level gymnastics. The trade-off is that generated code can drift from your +schema — which is why you re-run `pbkit generate` whenever the schema changes +(or use [`--watch`](/reference/cli#watch-mode)). + +## Where this shows up + +- The `input` options map directly to the parse stage — see [Configuration](/reference/configuration#input). +- `types.*` and `sdk.*` options tune the generate stage. +- Plugins hook into the generate stage with access to the IR — see [Write a plugin](/how-to/write-a-plugin). diff --git a/apps/docs/src/content/docs/explanation/relations-and-expand.md b/apps/docs/src/content/docs/explanation/relations-and-expand.md new file mode 100644 index 0000000..bdedbe3 --- /dev/null +++ b/apps/docs/src/content/docs/explanation/relations-and-expand.md @@ -0,0 +1,55 @@ +--- +title: Relations and expand paths +description: How pbkit models relations as a graph and derives typed expand paths from it. +sidebar: + order: 3 +--- + +PocketBase lets you fetch related records in a single request through the +`expand` query parameter. pbkit turns this into a typed experience by computing, +ahead of time, every expand path a collection can legally use. This page +explains how those paths are derived; for the resulting types and how to use +them, see [Expand types](/reference/expand-types). + +## Relations form a graph + +When pbkit builds the [Schema IR](/explanation/how-pbkit-works#2-the-schema-ir), +it records each relation field as an edge between two collections. The result is +a directed graph: collections are nodes, relation fields are edges. + +For example: + +- `articles` → `author` (to `users`) and `categories` (to `categories`) +- `comments` → `article` (to `articles`) and `author` (to `users`) + +## Expand paths are walks through the graph + +A valid expand path is simply a walk along these edges starting from a +collection. From `comments` you can expand `article`, and from there `article`'s +own relations — `article.author`, `article.categories` — and so on. + +pbkit enumerates these walks up to a maximum length and emits them as a union: + +```ts +export type CommentsExpand = "article" | "article.author" | "article.categories" | "author" +``` + +This is why expand autocomplete only ever offers paths that actually exist in +your schema — they are computed from the graph, not guessed. + +## Why depth is bounded + +The graph can be deep, and following every walk to its end would produce huge, +mostly-useless unions. So traversal stops at `types.expandDepth` levels +(default: `2`). Lower it to `1` for direct relations only; raise it if you +routinely expand deeply nested relations. This is a deliberate trade-off between +type completeness and the size and noise of the generated unions. + +## Why cycles don't break generation + +Relations frequently form cycles — `users` may reference `articles` which +reference `users` again. A naive walk would recurse forever. pbkit detects when +a walk revisits a collection it is already inside and stops there, so a cyclic +schema still produces a finite set of paths. The depth bound is the second +safeguard: even without an explicit cycle, traversal can never exceed +`expandDepth`. diff --git a/apps/docs/src/content/docs/explanation/why-a-generated-sdk.md b/apps/docs/src/content/docs/explanation/why-a-generated-sdk.md new file mode 100644 index 0000000..16e2971 --- /dev/null +++ b/apps/docs/src/content/docs/explanation/why-a-generated-sdk.md @@ -0,0 +1,71 @@ +--- +title: Why a generated SDK +description: The reasoning behind generating CRUD functions instead of typing the PocketBase client. +sidebar: + order: 4 +--- + +The most common way to get types onto PocketBase is to generate type +declarations and cast the client — `pb.collection("articles")` returns a typed +service. pbkit takes a different approach: it generates **standalone functions** +like `getArticle()` and `listArticles()`. This page explains why. + +## The two models + +With a typed-client tool, you keep PocketBase's method API and bolt types on top: + +```ts +const pb = new PocketBase(url) as TypedPocketBase +const article = await pb.collection("articles").getOne("id") +``` + +With pbkit, the collection name and method are baked into a named function: + +```ts +const article = await getArticle("id") +``` + +(See [Migrating from pocketbase-typegen](/how-to/migrate-from-pocketbase-typegen) +for a full mapping between the two.) + +## What generating functions buys you + +**Discoverability.** Typing `getA…` surfaces `getArticle`, `getArticles` and +friends through normal autocomplete. There is no string collection name to +remember or mistype — a wrong name is a missing import, caught immediately. + +**Tighter types per operation.** A generated `createArticle` takes +`ArticlesCreate`, while `updateArticle` takes `ArticlesUpdate`. A single typed +`collection()` service tends to share one record type across create, update, and +read, which is looser than what each operation actually accepts. pbkit splits +these because PocketBase treats them differently — see +[Generated types](/reference/generated-types). + +**Typed expand without generics.** Because each function knows its collection, +its `expand` option is typed to that collection's +[expand paths](/explanation/relations-and-expand) automatically. The typed-client +model usually requires you to pass the expanded shape as a generic by hand. + +**A place to add capabilities.** Generating the call site lets pbkit thread +extra options through every operation — a per-call `client` override and a custom +`fetch` for SSR frameworks — uniformly. These live in `sdk.gen.ts` rather than +being patched onto the PocketBase client. + +## The trade-offs + +This approach is not free: + +- **More generated code.** A function per operation per collection is more output + than a single set of type declarations. pbkit keeps it readable and lets you + [disable operations or whole collections](/how-to/configure-collections) to + trim it. +- **A generation step in the loop.** You re-run `pbkit generate` when the schema + changes. This is the same trade-off any generator makes — discussed in + [How pbkit works](/explanation/how-pbkit-works#why-a-generator-instead-of-a-runtime-library). +- **Less direct.** You call generated wrappers, not the raw SDK. When you need the + underlying client, it is still there in `client.gen.ts`, and any function + accepts a `client` override. + +If you only want types and prefer to keep calling `pb.collection(...)`, you can +set [`sdk.enabled: false`](/reference/generated-sdk#disable-sdk-generation) and +use the generated types directly. diff --git a/apps/docs/src/content/docs/generated-output/expand-types.md b/apps/docs/src/content/docs/generated-output/expand-types.md deleted file mode 100644 index a65beb0..0000000 --- a/apps/docs/src/content/docs/generated-output/expand-types.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Expand Types -description: How pbkit generates typed expand paths for relation fields. -sidebar: - order: 3 ---- - -PocketBase supports expanding relations via the `expand` query parameter. pbkit generates `XxxExpand` types so you get autocomplete for valid expand paths. - -## How it works - -For each collection with relation fields, pbkit walks the relation graph up to `types.expandDepth` (default: 2) and generates a union of all valid paths. - -### Example - -Given these collections: - -- `articles` → has `author` (relation to `users`) and `categories` (relation to `categories`) -- `comments` → has `article` (relation to `articles`) and `author` (relation to `users`) - -The generated expand types are: - -```ts -// Direct relations -export type ArticlesExpand = "author" | "categories" - -// Direct + nested relations (depth 2) -export type CommentsExpand = "article" | "article.author" | "article.categories" | "author" -``` - -## Controlling depth - -Use `types.expandDepth` to control how deep the traversal goes: - -```ts -export default { - input: "https://my-pb.example.com", - output: "./src/generated", - types: { - expandDepth: 1, // only direct relations, no nested paths - }, -} -``` - -With `expandDepth: 1`, `CommentsExpand` would only be `"article" | "author"`. - -## Using expand types - -The expand parameter in SDK functions is typed when the collection has expand paths: - -```ts -import { getArticle } from "./generated/sdk.gen" -import type { ArticlesExpand } from "./generated/types.gen" - -// Autocomplete suggests "author" or "categories" -const result = await getArticle("ID", { - expand: "author" as ArticlesExpand, -}) -``` - -## Circular references - -pbkit detects circular references in the relation graph and stops traversal to avoid infinite loops. If `users` references `articles` and `articles` references `users`, the traversal won't recurse infinitely. diff --git a/apps/docs/src/content/docs/getting-started/quick-start.md b/apps/docs/src/content/docs/getting-started/quick-start.md deleted file mode 100644 index 77246b1..0000000 --- a/apps/docs/src/content/docs/getting-started/quick-start.md +++ /dev/null @@ -1,94 +0,0 @@ ---- -title: Quick Start -description: Generate a typed SDK from your PocketBase schema in under a minute. -sidebar: - order: 2 ---- - -## 1. Create a config file - -Create `pbkit.config.ts` in your project root: - -```ts -// pbkit.config.ts -export default { - input: "https://my-pb.example.com", - output: "./src/generated", - sdk: { - baseUrl: "https://my-pb.example.com", - }, -} -``` - -You can also point to an exported JSON schema: - -```ts -export default { - input: "./pb_schema.json", - output: "./src/generated", - sdk: { - baseUrl: "https://my-pb.example.com", - }, -} -``` - -## 2. Generate - -```bash -bunx pbkit generate -``` - -This creates generated files in `./src/generated`: - -- `types.gen.ts` — TypeScript interfaces -- `client.gen.ts` — PocketBase client singleton -- `sdk.gen.ts` — Typed CRUD functions - -## 3. Use the generated SDK - -```ts -import { getArticle, listArticles, createArticle } from "./generated/sdk.gen" -import type { ArticlesCreate, ArticlesRecord } from "./generated/types.gen" - -// Get a single record -const article: ArticlesRecord = await getArticle("RECORD_ID") - -// Expand relations with autocomplete -const withAuthor = await getArticle("RECORD_ID", { - expand: "author", -}) - -// List with pagination -const page = await listArticles({ page: 1, perPage: 20 }) - -// Create -const draft: ArticlesCreate = { - title: "Hello", - status: "draft", - author: "USER_ID", -} - -const newArticle = await createArticle(draft) -``` - -By default the generated SDK uses the `client` exported from `client.gen.ts`. -Pass a client override when you need a different PocketBase instance: - -```ts -import PocketBase from "pocketbase" -import { getArticle } from "./generated/sdk.gen" - -const pb = new PocketBase("https://my-pb.example.com") - -await getArticle("RECORD_ID", undefined, { client: pb }) -``` - -## Watch mode - -To auto-regenerate when your schema changes: - -```bash -bunx pbkit generate --watch -``` - -This polls the API every 10 seconds. Press `Ctrl+C` to stop. diff --git a/apps/docs/src/content/docs/plugins/tanstack-query.md b/apps/docs/src/content/docs/how-to/add-tanstack-query.md similarity index 99% rename from apps/docs/src/content/docs/plugins/tanstack-query.md rename to apps/docs/src/content/docs/how-to/add-tanstack-query.md index 942146a..002624f 100644 --- a/apps/docs/src/content/docs/plugins/tanstack-query.md +++ b/apps/docs/src/content/docs/how-to/add-tanstack-query.md @@ -1,8 +1,8 @@ --- -title: TanStack Query Plugin +title: Add TanStack Query description: Generate queryOptions, mutationOptions, and query key helpers for TanStack Query. sidebar: - order: 1 + order: 3 --- The `@karnak19/pbkit-tanstack` package provides a plugin that generates framework-agnostic TanStack Query options and query key helpers. diff --git a/apps/docs/src/content/docs/plugins/zod.md b/apps/docs/src/content/docs/how-to/add-zod-schemas.md similarity index 99% rename from apps/docs/src/content/docs/plugins/zod.md rename to apps/docs/src/content/docs/how-to/add-zod-schemas.md index 159be8d..30334ee 100644 --- a/apps/docs/src/content/docs/plugins/zod.md +++ b/apps/docs/src/content/docs/how-to/add-zod-schemas.md @@ -1,8 +1,8 @@ --- -title: Zod Plugin +title: Add Zod schemas description: Generate Zod schemas from PocketBase collection definitions. sidebar: - order: 2 + order: 4 --- The `@karnak19/pbkit-zod` package provides a plugin that generates [Zod](https://zod.dev) schemas from your PocketBase collections, preserving field constraints as validations. diff --git a/apps/docs/src/content/docs/configuration/collections.md b/apps/docs/src/content/docs/how-to/configure-collections.md similarity index 98% rename from apps/docs/src/content/docs/configuration/collections.md rename to apps/docs/src/content/docs/how-to/configure-collections.md index 54d81c9..a8d80ba 100644 --- a/apps/docs/src/content/docs/configuration/collections.md +++ b/apps/docs/src/content/docs/how-to/configure-collections.md @@ -1,5 +1,5 @@ --- -title: Collection Configuration +title: Configure collections description: Exclude collections and control which CRUD operations are generated. sidebar: order: 2 diff --git a/apps/docs/src/content/docs/getting-started/installation.md b/apps/docs/src/content/docs/how-to/install.md similarity index 68% rename from apps/docs/src/content/docs/getting-started/installation.md rename to apps/docs/src/content/docs/how-to/install.md index 3e83b77..c8c4216 100644 --- a/apps/docs/src/content/docs/getting-started/installation.md +++ b/apps/docs/src/content/docs/how-to/install.md @@ -1,5 +1,5 @@ --- -title: Installation +title: Install pbkit description: How to install pbkit in your project. sidebar: order: 1 @@ -34,5 +34,5 @@ Usage: ## Next steps -- Follow the [Quick Start](/getting-started/quick-start) guide to generate your first SDK -- Read the [configuration reference](/configuration/pbkit-config) for all available options +- Follow [Your first typed SDK](/tutorials/your-first-sdk) to generate your first SDK +- Read the [configuration reference](/reference/configuration) for all available options diff --git a/apps/docs/src/content/docs/how-to/migrate-from-pocketbase-typegen.md b/apps/docs/src/content/docs/how-to/migrate-from-pocketbase-typegen.md new file mode 100644 index 0000000..fc9a3f7 --- /dev/null +++ b/apps/docs/src/content/docs/how-to/migrate-from-pocketbase-typegen.md @@ -0,0 +1,238 @@ +--- +title: Migrating from pocketbase-typegen +description: A step-by-step guide to moving an existing project from pocketbase-typegen to pbkit. +sidebar: + order: 6 +--- + +[pocketbase-typegen](https://github.com/patmood/pocketbase-typegen) generates a +single types file that you apply to the PocketBase JS SDK by casting your client +to `TypedPocketBase`. pbkit generates the same types **and** a ready-to-use SDK +of typed CRUD functions, so you call `getArticle("id")` instead of +`pb.collection("articles").getOne("id")`. + +This guide walks through the migration one piece at a time. By the end you will +have removed pocketbase-typegen, generated pbkit output, and updated your call +sites. + +## What changes + +| Concept | pocketbase-typegen | pbkit | +|---|---|---| +| Output | one `pocketbase-types.ts` | `types.gen.ts`, `client.gen.ts`, `sdk.gen.ts` | +| Configuration | CLI flags | a `pbkit.config.ts` file | +| Data access | cast `pb` to `TypedPocketBase`, call `pb.collection(...)` | import generated functions | +| Expanding relations | manual generic parameters | typed `expand` option | + +## Step 1: Swap the dependencies + +Remove pocketbase-typegen and add pbkit. Keep `pocketbase` — both tools rely on +the official SDK at runtime. + +```bash +bun remove pocketbase-typegen +bun add @karnak19/pbkit pocketbase +``` + +## Step 2: Replace CLI flags with a config file + +pocketbase-typegen is configured entirely through CLI flags, usually in a +`package.json` script: + +```jsonc +// package.json (before) +{ + "scripts": { + "typegen": "pocketbase-typegen --url https://my-pb.example.com --email admin@example.com --password secret --out ./src/pocketbase-types.ts" + } +} +``` + +pbkit reads a `pbkit.config.ts` instead. Create one in your project root, mapping +your old flags to config options: + +```ts +// pbkit.config.ts +import type { PbkitConfig } from "@karnak19/pbkit" + +export default { + input: { url: "https://my-pb.example.com", token: "ADMIN_AUTH_TOKEN" }, + output: "./src/generated", + sdk: { + baseUrl: "https://my-pb.example.com", + }, +} satisfies PbkitConfig +``` + +Use the table below to translate your input source: + +| pocketbase-typegen flag | pbkit `input` | +|---|---| +| `--url ... --email ... --password ...` | `{ url: "...", token: "..." }` | +| `--url ...` (public schema) | `"https://my-pb.example.com"` | +| `--json ./pb_schema.json` | `"./pb_schema.json"` | +| `--db ./pb_data/data.db` | *not supported — see note below* | + +> **Note on `--db`:** pbkit does not read the SQLite database file directly. If +> you were generating from `--db`, switch to either a live URL or an +> [exported JSON schema](https://pocketbase.io/docs/collections/#importing-collections) +> (`input: "./pb_schema.json"`). + +The `--out` flag maps to `output`, but note the difference: `--out` was a single +**file**, while pbkit's `output` is a **directory** that is cleared and rewritten +on each run. See the [Configuration Reference](/reference/configuration) for +all options. + +Update your script to call pbkit: + +```jsonc +// package.json (after) +{ + "scripts": { + "generate": "pbkit generate" + } +} +``` + +## Step 3: Generate + +```bash +bunx pbkit generate +``` + +This writes three files into `./src/generated`: + +- `types.gen.ts` — TypeScript interfaces +- `client.gen.ts` — a PocketBase client singleton +- `sdk.gen.ts` — typed CRUD functions + +## Step 4: Update type imports + +The generated type names differ. Use this mapping to update imports: + +| pocketbase-typegen | pbkit | Notes | +|---|---|---| +| `XxxResponse` | `XxxRecord` | the full record returned by the API | +| `XxxRecord` | `XxxCreate` / `XxxUpdate` | the input shape; pbkit splits create vs. update | +| `Collections` enum | `CollectionName` union | string literal union instead of an enum | +| `XxxStatusOptions` enum | inline string union | e.g. `"draft" \| "published"` directly on the field | +| `BaseSystemFields` | `BaseRecord` | base system fields | +| `AuthSystemFields` | `AuthRecord` | auth-collection system fields | + +For example, where you previously wrote: + +```ts +// before +import { ArticlesResponse, ArticlesRecord, Collections } from "./pocketbase-types" + +const article: ArticlesResponse = await pb.collection("articles").getOne("id") +const draft: ArticlesRecord = { title: "Hello" } +``` + +you now write: + +```ts +// after +import type { ArticlesRecord, ArticlesCreate } from "./generated/types.gen" + +const article: ArticlesRecord = await getArticle("id") +const draft: ArticlesCreate = { title: "Hello", status: "draft", author: "USER_ID" } +``` + +See [Generated Types](/reference/generated-types) for the full shape of each type. + +## Step 5: Replace `pb.collection(...)` calls + +This is the largest change. pocketbase-typegen relies on casting your client to +`TypedPocketBase` and calling methods on `pb.collection(...)`. pbkit generates a +dedicated function per operation, so you can delete the cast entirely. + +| pocketbase-typegen | pbkit | +|---|---| +| `pb.collection("articles").getOne(id)` | `getArticle(id)` | +| `pb.collection("articles").getFirstListItem(filter)` | `getFirstArticle(filter)` | +| `pb.collection("articles").getList(page, perPage)` | `listArticles({ page, perPage })` | +| `pb.collection("articles").getFullList()` | `getFullListArticles()` | +| `pb.collection("articles").create(data)` | `createArticle(data)` | +| `pb.collection("articles").update(id, data)` | `updateArticle(id, data)` | +| `pb.collection("articles").delete(id)` | `deleteArticle(id)` | + +Before: + +```ts +import PocketBase from "pocketbase" +import { TypedPocketBase, Collections } from "./pocketbase-types" + +const pb = new PocketBase("https://my-pb.example.com") as TypedPocketBase + +const article = await pb.collection("articles").getOne("RECORD_ID") +const page = await pb.collection(Collections.Articles).getList(1, 20) +const created = await pb.collection("articles").create({ title: "Hello" }) +``` + +After: + +```ts +import { getArticle, listArticles, createArticle } from "./generated/sdk.gen" + +const article = await getArticle("RECORD_ID") +const page = await listArticles({ page: 1, perPage: 20 }) +const created = await createArticle({ title: "Hello", status: "draft", author: "USER_ID" }) +``` + +The generated functions use the `client` from `client.gen.ts` (configured by +`sdk.baseUrl`) by default. To target a different instance for a single call, pass +`{ client }` as the last argument. See the [Generated SDK](/reference/generated-sdk) +reference for full signatures. + +## Expanding relations + +pocketbase-typegen requires you to type expanded relations manually through a +generic parameter: + +```ts +// before +const article = await pb + .collection("articles") + .getOne>("RECORD_ID", { expand: "author" }) + +article.expand?.author.email +``` + +pbkit types the `expand` option directly from the schema, so you get +autocomplete and no manual generics: + +```ts +// after +const article = await getArticle("RECORD_ID", { expand: "author" }) +``` + +See [Expand Types](/explanation/relations-and-expand) for how expand paths are typed. + +## Authentication + +Auth-collection methods move from `pb.collection(...)` to dedicated functions: + +```ts +// before +await pb.collection("users").authWithPassword("user@example.com", "password") + +// after +import { authUserWithPassword } from "./generated/sdk.gen" +await authUserWithPassword("user@example.com", "password") +``` + +The full set of auth, password-reset, and verification functions is listed under +[Generated SDK → Auth functions](/reference/generated-sdk#auth-functions). + +## Verify the migration + +1. Run `bunx pbkit generate` and confirm the three files appear in your `output` directory. +2. Run your type checker (`bunx tsc --noEmit`) and resolve any remaining imports of the old `pocketbase-types` file. +3. Delete the old `pocketbase-types.ts`. + +## Next steps + +- [Configuration Reference](/reference/configuration) — every available option +- [Per-collection configuration](/how-to/configure-collections) — exclude collections or disable operations +- [Add TanStack Query](/how-to/add-tanstack-query) — generate TanStack Query options or Zod schemas diff --git a/apps/docs/src/content/docs/plugins/authoring.md b/apps/docs/src/content/docs/how-to/write-a-plugin.md similarity index 98% rename from apps/docs/src/content/docs/plugins/authoring.md rename to apps/docs/src/content/docs/how-to/write-a-plugin.md index d6cf2b0..b30619f 100644 --- a/apps/docs/src/content/docs/plugins/authoring.md +++ b/apps/docs/src/content/docs/how-to/write-a-plugin.md @@ -1,8 +1,8 @@ --- -title: Plugin Authoring +title: Write a plugin description: How to write a custom pbkit plugin. sidebar: - order: 2 + order: 5 --- pbkit plugins receive the parsed schema and return generated files. A plugin is an object implementing the `PbkitPlugin` interface. diff --git a/apps/docs/src/content/docs/index.md b/apps/docs/src/content/docs/index.md index 579839e..0cb3ca3 100644 --- a/apps/docs/src/content/docs/index.md +++ b/apps/docs/src/content/docs/index.md @@ -6,7 +6,7 @@ hero: tagline: Generate fully typed TypeScript SDKs from your PocketBase schema. actions: - text: Get Started - link: /pbkit/getting-started/installation + link: /pbkit/tutorials/your-first-sdk icon: right-arrow variant: primary - text: View on GitHub diff --git a/apps/docs/src/content/docs/cli/usage.md b/apps/docs/src/content/docs/reference/cli.md similarity index 98% rename from apps/docs/src/content/docs/cli/usage.md rename to apps/docs/src/content/docs/reference/cli.md index ac51490..5813d8b 100644 --- a/apps/docs/src/content/docs/cli/usage.md +++ b/apps/docs/src/content/docs/reference/cli.md @@ -1,5 +1,5 @@ --- -title: CLI Usage +title: CLI description: pbkit command-line interface reference. sidebar: order: 1 diff --git a/apps/docs/src/content/docs/configuration/pbkit-config.md b/apps/docs/src/content/docs/reference/configuration.md similarity index 91% rename from apps/docs/src/content/docs/configuration/pbkit-config.md rename to apps/docs/src/content/docs/reference/configuration.md index ac4e8f1..70b45f8 100644 --- a/apps/docs/src/content/docs/configuration/pbkit-config.md +++ b/apps/docs/src/content/docs/reference/configuration.md @@ -1,8 +1,8 @@ --- -title: Configuration Reference +title: Configuration description: All options available in pbkit.config.ts. sidebar: - order: 1 + order: 2 --- `pbkit.config.ts` is the main configuration file. It must export a `PbkitConfig` object as the default export. @@ -99,7 +99,7 @@ sdk: { ## `collections` -Per-collection configuration. See the [Collections](/configuration/collections) page for details. +Per-collection configuration. See [Configure collections](/how-to/configure-collections) for details. ```ts collections: { @@ -110,7 +110,7 @@ collections: { ## `plugins` -Array of pbkit plugins. See the [Plugins](/plugins/tanstack-query) section. +Array of pbkit plugins. See [Add TanStack Query](/how-to/add-tanstack-query) and [Add Zod schemas](/how-to/add-zod-schemas). ```ts plugins: [] diff --git a/apps/docs/src/content/docs/reference/expand-types.md b/apps/docs/src/content/docs/reference/expand-types.md new file mode 100644 index 0000000..6815024 --- /dev/null +++ b/apps/docs/src/content/docs/reference/expand-types.md @@ -0,0 +1,61 @@ +--- +title: Expand types +description: The XxxExpand types generated for relation fields and how to control them. +sidebar: + order: 6 +--- + +For each collection that has relation fields, pbkit generates an `XxxExpand` +type: a union of every valid `expand` path. This gives you autocomplete and +compile-time checking for the `expand` option in SDK calls. + +For the concept behind how these paths are computed, see +[Relations and expand paths](/explanation/relations-and-expand). + +## Generated type + +Given an `articles` collection with `author` (relation to `users`) and +`categories` (relation to `categories`), and a `comments` collection with +`article` and `author` relations: + +```ts +// Direct relations +export type ArticlesExpand = "author" | "categories" + +// Direct + nested relations (depth 2) +export type CommentsExpand = "article" | "article.author" | "article.categories" | "author" +``` + +An `XxxExpand` type is only generated when the collection has at least one +relation field. + +## Depth + +The maximum path depth is controlled by `types.expandDepth` (default: `2`): + +```ts +export default { + input: "https://my-pb.example.com", + output: "./src/generated", + types: { + expandDepth: 1, // only direct relations, no nested paths + }, +} +``` + +With `expandDepth: 1`, `CommentsExpand` would be only `"article" | "author"`. + +## Usage + +The `expand` option on SDK functions is typed to the collection's `XxxExpand` +type, so valid paths autocomplete: + +```ts +import { getArticle } from "./generated/sdk.gen" + +const article = await getArticle("RECORD_ID", { + expand: "author", +}) +``` + +See [Generated SDK](/reference/generated-sdk#typed-expand) for the full signatures. diff --git a/apps/docs/src/content/docs/generated-output/field-type-mapping.md b/apps/docs/src/content/docs/reference/field-type-mapping.md similarity index 98% rename from apps/docs/src/content/docs/generated-output/field-type-mapping.md rename to apps/docs/src/content/docs/reference/field-type-mapping.md index cbdfca4..f3ad9d1 100644 --- a/apps/docs/src/content/docs/generated-output/field-type-mapping.md +++ b/apps/docs/src/content/docs/reference/field-type-mapping.md @@ -1,8 +1,8 @@ --- -title: Field Type Mapping +title: Field type mapping description: How PocketBase field types map to TypeScript types. sidebar: - order: 4 + order: 5 --- pbkit maps each PocketBase field type to a TypeScript type. The mapping is used in both `Record` and `Create` types. diff --git a/apps/docs/src/content/docs/generated-output/sdk.md b/apps/docs/src/content/docs/reference/generated-sdk.md similarity index 99% rename from apps/docs/src/content/docs/generated-output/sdk.md rename to apps/docs/src/content/docs/reference/generated-sdk.md index 0e0d8ad..5ef9b08 100644 --- a/apps/docs/src/content/docs/generated-output/sdk.md +++ b/apps/docs/src/content/docs/reference/generated-sdk.md @@ -2,7 +2,7 @@ title: Generated SDK description: Typed CRUD functions wrapping the PocketBase JS SDK. sidebar: - order: 2 + order: 4 --- pbkit generates `sdk.gen.ts` with fully typed functions for every non-excluded collection. diff --git a/apps/docs/src/content/docs/generated-output/types.md b/apps/docs/src/content/docs/reference/generated-types.md similarity index 98% rename from apps/docs/src/content/docs/generated-output/types.md rename to apps/docs/src/content/docs/reference/generated-types.md index 661a5c5..02e5a66 100644 --- a/apps/docs/src/content/docs/generated-output/types.md +++ b/apps/docs/src/content/docs/reference/generated-types.md @@ -1,8 +1,8 @@ --- -title: Generated Types +title: Generated types description: TypeScript interfaces generated for each PocketBase collection. sidebar: - order: 1 + order: 3 --- pbkit generates `types.gen.ts` containing TypeScript types for every non-excluded collection. diff --git a/apps/docs/src/content/docs/api/programmatic.md b/apps/docs/src/content/docs/reference/programmatic-api.md similarity index 99% rename from apps/docs/src/content/docs/api/programmatic.md rename to apps/docs/src/content/docs/reference/programmatic-api.md index 7f38e08..77e6c24 100644 --- a/apps/docs/src/content/docs/api/programmatic.md +++ b/apps/docs/src/content/docs/reference/programmatic-api.md @@ -2,7 +2,7 @@ title: Programmatic API description: Use pbkit's API directly in your own tooling. sidebar: - order: 1 + order: 7 --- You can use pbkit programmatically instead of the CLI. Import functions directly from `@karnak19/pbkit`. diff --git a/apps/docs/src/content/docs/tutorials/your-first-sdk.md b/apps/docs/src/content/docs/tutorials/your-first-sdk.md new file mode 100644 index 0000000..526b022 --- /dev/null +++ b/apps/docs/src/content/docs/tutorials/your-first-sdk.md @@ -0,0 +1,116 @@ +--- +title: Your first typed SDK +description: Generate a fully typed SDK from your PocketBase schema, then read a record, list records, and create one. +sidebar: + order: 1 +--- + +In this tutorial you will point pbkit at a PocketBase instance, generate a typed +SDK, and use it to read, list, and create records. It takes about a minute and +assumes pbkit is already installed — if not, follow [Install pbkit](/how-to/install) first. + +By the end you will understand the three files pbkit generates and how to call them. + +## 1. Create a config file + +Create `pbkit.config.ts` in your project root: + +```ts +// pbkit.config.ts +export default { + input: "https://my-pb.example.com", + output: "./src/generated", + sdk: { + baseUrl: "https://my-pb.example.com", + }, +} +``` + +You can also point to an exported JSON schema: + +```ts +export default { + input: "./pb_schema.json", + output: "./src/generated", + sdk: { + baseUrl: "https://my-pb.example.com", + }, +} +``` + +## 2. Generate + +```bash +bunx pbkit generate +``` + +This creates generated files in `./src/generated`: + +- `types.gen.ts` — TypeScript interfaces +- `client.gen.ts` — PocketBase client singleton +- `sdk.gen.ts` — Typed CRUD functions + +## 3. Use the generated SDK + +```ts +import { getArticle, listArticles, createArticle } from "./generated/sdk.gen" +import type { ArticlesCreate, ArticlesRecord } from "./generated/types.gen" + +// Get a single record +const article: ArticlesRecord = await getArticle("RECORD_ID") + +// Expand relations with autocomplete +const withAuthor = await getArticle("RECORD_ID", { + expand: "author", +}) + +// List with pagination +const page = await listArticles({ page: 1, perPage: 20 }) + +// Create +const draft: ArticlesCreate = { + title: "Hello", + status: "draft", + author: "USER_ID", +} + +const newArticle = await createArticle(draft) +``` + +That's it — you have a fully typed SDK with autocomplete and compile-time checks, +generated entirely from your schema. + +## What just happened? + +pbkit read your schema and wrote three files into `./src/generated`: + +| File | What it is | +|---|---| +| `types.gen.ts` | TypeScript interfaces for every collection (`ArticlesRecord`, `ArticlesCreate`, …) | +| `client.gen.ts` | A PocketBase client initialized with your `sdk.baseUrl` | +| `sdk.gen.ts` | The typed CRUD functions you imported (`getArticle`, `listArticles`, `createArticle`, …) | + +By default the SDK functions talk to the `client` exported from `client.gen.ts`. +You only ever import from `sdk.gen.ts` and `types.gen.ts` — never edit these +files by hand, since they are overwritten on every run. + +For why pbkit splits the output this way, see +[The generated files](/explanation/generated-files). + +## Keep your SDK in sync + +Whenever your PocketBase schema changes, run `bunx pbkit generate` again. During +active development you can leave it watching: + +```bash +bunx pbkit generate --watch +``` + +This polls the schema every 10 seconds and regenerates on changes. Press +`Ctrl+C` to stop. + +## Next steps + +- [Migrate from pocketbase-typegen](/how-to/migrate-from-pocketbase-typegen) — moving an existing project +- [Configuration reference](/reference/configuration) — every available option +- [Add TanStack Query](/how-to/add-tanstack-query) or [Zod schemas](/how-to/add-zod-schemas) via plugins From 93a1be482cb17011cbb592a8a099765405a7eda0 Mon Sep 17 00:00:00 2001 From: Basile Vernouillet Date: Mon, 1 Jun 2026 12:00:35 +0200 Subject: [PATCH 2/6] docs(skill): add pocketbase-typegen migration section to pbkit skill Mirror the new migration guide in the agent-facing skill: dependency swap, CLI-flag mapping, type-name mapping, call-site mapping, and a workflow note to migrate rather than run pbkit alongside typegen. Co-Authored-By: Claude Opus 4.8 (1M context) --- skills/pbkit/SKILL.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/skills/pbkit/SKILL.md b/skills/pbkit/SKILL.md index 0bf41a3..40ae5d2 100644 --- a/skills/pbkit/SKILL.md +++ b/skills/pbkit/SKILL.md @@ -301,6 +301,16 @@ export default { - `input` is not always a URL — it can be a local JSON file. Do not infer baseUrl from `input`. - Leave `sdk.baseUrl` empty when the app uses multiple PB clients — rely on `{ client }` overrides per call. +## Migrating from pocketbase-typegen + +When a project already uses [pocketbase-typegen](https://github.com/patmood/pocketbase-typegen), pbkit replaces both the generated types and the `TypedPocketBase` cast with generated SDK functions. + +- Swap dependencies: remove `pocketbase-typegen`, add `@karnak19/pbkit`. Keep `pocketbase`. +- Replace CLI flags with `pbkit.config.ts`. Flag mapping: `--url/--email/--password` → `input: { url, token }`; `--url` (public) → `input: ""`; `--json ` → `input: ""`. `--db ` is **not** supported via config — switch to a URL or exported JSON. `--out ` → `output: ""` (a directory, cleared on each run). +- Type name mapping: `XxxResponse` → `XxxRecord`; `XxxRecord` (input shape) → `XxxCreate` / `XxxUpdate`; `Collections` enum → `CollectionName` union; per-field `XxxStatusOptions` enums → inline string literal unions; `BaseSystemFields` → `BaseRecord`; `AuthSystemFields` → `AuthRecord`. +- Call-site mapping: `pb.collection("articles").getOne(id)` → `getArticle(id)`; `.getFirstListItem(filter)` → `getFirstArticle(filter)`; `.getList(page, perPage)` → `listArticles({ page, perPage })`; `.getFullList()` → `getFullListArticles()`; `.create(data)` → `createArticle(data)`; `.update(id, data)` → `updateArticle(id, data)`; `.delete(id)` → `deleteArticle(id)`. Auth: `pb.collection("users").authWithPassword(...)` → `authUserWithPassword(...)`. +- Expand no longer needs manual generics — the `expand` option is typed from the schema. Delete the `TypedPocketBase` cast and the old `pocketbase-types.ts` once imports are updated. + ## Agent Workflow 1. Check for an existing `pbkit.config.ts` before adding a new one. @@ -310,3 +320,4 @@ export default { 5. Run `bunx pbkit generate` or `npx pbkit generate` after changing config or schema inputs. 6. Import from generated files (`.gen.ts` suffix) instead of recreating PocketBase access wrappers by hand. 7. For multi-client setups, leave `sdk.baseUrl` empty and pass `{ client }` override to SDK functions as needed. +8. If the project uses `pocketbase-typegen`, follow the migration mapping above rather than adding pbkit alongside it. From 6cdc12e8411bf708d8b2c6b8e597034c975b5614 Mon Sep 17 00:00:00 2001 From: Basile Vernouillet Date: Mon, 1 Jun 2026 12:04:43 +0200 Subject: [PATCH 3/6] =?UTF-8?q?docs:=20address=20AI=20review=20=E2=80=94?= =?UTF-8?q?=20fix=20function=20name=20and=20link=20target?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - why-a-generated-sdk: getArticles is not generated; use getFirstArticle (SDK produces get/getFirst and list/getFullList) - migration guide: point "Expand types" link to /reference/expand-types so link text matches the target page title Co-Authored-By: Claude Opus 4.8 (1M context) --- apps/docs/src/content/docs/explanation/why-a-generated-sdk.md | 2 +- .../src/content/docs/how-to/migrate-from-pocketbase-typegen.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/docs/src/content/docs/explanation/why-a-generated-sdk.md b/apps/docs/src/content/docs/explanation/why-a-generated-sdk.md index 16e2971..097b865 100644 --- a/apps/docs/src/content/docs/explanation/why-a-generated-sdk.md +++ b/apps/docs/src/content/docs/explanation/why-a-generated-sdk.md @@ -30,7 +30,7 @@ for a full mapping between the two.) ## What generating functions buys you -**Discoverability.** Typing `getA…` surfaces `getArticle`, `getArticles` and +**Discoverability.** Typing `getA…` surfaces `getArticle`, `getFirstArticle` and friends through normal autocomplete. There is no string collection name to remember or mistype — a wrong name is a missing import, caught immediately. diff --git a/apps/docs/src/content/docs/how-to/migrate-from-pocketbase-typegen.md b/apps/docs/src/content/docs/how-to/migrate-from-pocketbase-typegen.md index fc9a3f7..8ded8ea 100644 --- a/apps/docs/src/content/docs/how-to/migrate-from-pocketbase-typegen.md +++ b/apps/docs/src/content/docs/how-to/migrate-from-pocketbase-typegen.md @@ -207,7 +207,7 @@ autocomplete and no manual generics: const article = await getArticle("RECORD_ID", { expand: "author" }) ``` -See [Expand Types](/explanation/relations-and-expand) for how expand paths are typed. +See [Expand types](/reference/expand-types) for how expand paths are typed. ## Authentication From 6d8202c4757cbf0c8d39bd353dc0d6fb8cce2d2b Mon Sep 17 00:00:00 2001 From: Basile Vernouillet Date: Mon, 1 Jun 2026 12:07:38 +0200 Subject: [PATCH 4/6] docs: address second review round on migration guide - Install pbkit as a devDependency (build-time tool); keep pocketbase as a runtime dependency - Explain the superuser auth token (pbkit takes a token, not email/password); read it from an env var instead of hardcoding - Link both plugin pages (TanStack Query and Zod) in Next steps Co-Authored-By: Claude Opus 4.8 (1M context) --- .../how-to/migrate-from-pocketbase-typegen.md | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/apps/docs/src/content/docs/how-to/migrate-from-pocketbase-typegen.md b/apps/docs/src/content/docs/how-to/migrate-from-pocketbase-typegen.md index 8ded8ea..5b44a2f 100644 --- a/apps/docs/src/content/docs/how-to/migrate-from-pocketbase-typegen.md +++ b/apps/docs/src/content/docs/how-to/migrate-from-pocketbase-typegen.md @@ -26,12 +26,14 @@ sites. ## Step 1: Swap the dependencies -Remove pocketbase-typegen and add pbkit. Keep `pocketbase` — both tools rely on -the official SDK at runtime. +Remove pocketbase-typegen and add pbkit. pbkit is a build-time code generator, so +install it as a dev dependency — like pocketbase-typegen was. Keep `pocketbase` +itself as a regular dependency, since your app uses its SDK at runtime. ```bash bun remove pocketbase-typegen -bun add @karnak19/pbkit pocketbase +bun add -d @karnak19/pbkit +bun add pocketbase ``` ## Step 2: Replace CLI flags with a config file @@ -56,7 +58,7 @@ your old flags to config options: import type { PbkitConfig } from "@karnak19/pbkit" export default { - input: { url: "https://my-pb.example.com", token: "ADMIN_AUTH_TOKEN" }, + input: { url: "https://my-pb.example.com", token: process.env.PB_ADMIN_TOKEN }, output: "./src/generated", sdk: { baseUrl: "https://my-pb.example.com", @@ -73,6 +75,14 @@ Use the table below to translate your input source: | `--json ./pb_schema.json` | `"./pb_schema.json"` | | `--db ./pb_data/data.db` | *not supported — see note below* | +> **Note on the token:** Unlike pocketbase-typegen, pbkit does not take an email +> and password — it expects a superuser auth `token`. Obtain one by authenticating +> as a superuser against your instance +> (`POST /api/collections/_superusers/auth-with-password`); the response's `token` +> field is the value to use. A token is only needed for non-public schemas — if +> `GET /api/collections` is publicly readable, pass just the URL. Avoid committing +> the token: load it from an environment variable instead. + > **Note on `--db`:** pbkit does not read the SQLite database file directly. If > you were generating from `--db`, switch to either a live URL or an > [exported JSON schema](https://pocketbase.io/docs/collections/#importing-collections) @@ -235,4 +245,4 @@ The full set of auth, password-reset, and verification functions is listed under - [Configuration Reference](/reference/configuration) — every available option - [Per-collection configuration](/how-to/configure-collections) — exclude collections or disable operations -- [Add TanStack Query](/how-to/add-tanstack-query) — generate TanStack Query options or Zod schemas +- [Add TanStack Query](/how-to/add-tanstack-query) or [Zod schemas](/how-to/add-zod-schemas) via plugins From 90fd421a7eac998a23f5ee159e1941977fd8bc85 Mon Sep 17 00:00:00 2001 From: Basile Vernouillet Date: Mon, 1 Jun 2026 12:09:53 +0200 Subject: [PATCH 5/6] docs(skill): install pbkit as devDependency in migration section Propagate the devDependency fix from the migration guide to the condensed SKILL.md summary so agents following it don't install the code generator as a runtime dependency. Co-Authored-By: Claude Opus 4.8 (1M context) --- skills/pbkit/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skills/pbkit/SKILL.md b/skills/pbkit/SKILL.md index 40ae5d2..e6eb809 100644 --- a/skills/pbkit/SKILL.md +++ b/skills/pbkit/SKILL.md @@ -305,7 +305,7 @@ export default { When a project already uses [pocketbase-typegen](https://github.com/patmood/pocketbase-typegen), pbkit replaces both the generated types and the `TypedPocketBase` cast with generated SDK functions. -- Swap dependencies: remove `pocketbase-typegen`, add `@karnak19/pbkit`. Keep `pocketbase`. +- Swap dependencies: remove `pocketbase-typegen`, add `-d @karnak19/pbkit` (build-time tool → devDependency). Keep `pocketbase` as a runtime dependency. - Replace CLI flags with `pbkit.config.ts`. Flag mapping: `--url/--email/--password` → `input: { url, token }`; `--url` (public) → `input: ""`; `--json ` → `input: ""`. `--db ` is **not** supported via config — switch to a URL or exported JSON. `--out ` → `output: ""` (a directory, cleared on each run). - Type name mapping: `XxxResponse` → `XxxRecord`; `XxxRecord` (input shape) → `XxxCreate` / `XxxUpdate`; `Collections` enum → `CollectionName` union; per-field `XxxStatusOptions` enums → inline string literal unions; `BaseSystemFields` → `BaseRecord`; `AuthSystemFields` → `AuthRecord`. - Call-site mapping: `pb.collection("articles").getOne(id)` → `getArticle(id)`; `.getFirstListItem(filter)` → `getFirstArticle(filter)`; `.getList(page, perPage)` → `listArticles({ page, perPage })`; `.getFullList()` → `getFullListArticles()`; `.create(data)` → `createArticle(data)`; `.update(id, data)` → `updateArticle(id, data)`; `.delete(id)` → `deleteArticle(id)`. Auth: `pb.collection("users").authWithPassword(...)` → `authUserWithPassword(...)`. From 00c98d2bd13d8b904dc1cd3408f051f74a2d4c39 Mon Sep 17 00:00:00 2001 From: Basile Vernouillet Date: Mon, 1 Jun 2026 12:11:45 +0200 Subject: [PATCH 6/6] docs: install all pbkit packages as devDependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apply the build-time/devDependency split consistently across the install guide, plugin how-tos, and the skill: - pbkit, pbkit-tanstack, pbkit-zod are generation-time tools → -d - pocketbase, @tanstack/query-core, zod are imported by generated code at runtime → regular dependencies Co-Authored-By: Claude Opus 4.8 (1M context) --- .../src/content/docs/how-to/add-tanstack-query.md | 6 +++++- .../src/content/docs/how-to/add-zod-schemas.md | 6 +++++- apps/docs/src/content/docs/how-to/install.md | 6 +++++- skills/pbkit/SKILL.md | 15 ++++++++++----- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/apps/docs/src/content/docs/how-to/add-tanstack-query.md b/apps/docs/src/content/docs/how-to/add-tanstack-query.md index 002624f..14b10c0 100644 --- a/apps/docs/src/content/docs/how-to/add-tanstack-query.md +++ b/apps/docs/src/content/docs/how-to/add-tanstack-query.md @@ -9,8 +9,12 @@ The `@karnak19/pbkit-tanstack` package provides a plugin that generates framewor ## Install +The plugin runs at generation time, so it is a dev dependency. +`@tanstack/query-core` is imported by the generated code at runtime. + ```bash -bun add @karnak19/pbkit-tanstack @tanstack/query-core +bun add -d @karnak19/pbkit-tanstack +bun add @tanstack/query-core ``` ## Setup diff --git a/apps/docs/src/content/docs/how-to/add-zod-schemas.md b/apps/docs/src/content/docs/how-to/add-zod-schemas.md index 30334ee..9a9d77b 100644 --- a/apps/docs/src/content/docs/how-to/add-zod-schemas.md +++ b/apps/docs/src/content/docs/how-to/add-zod-schemas.md @@ -9,8 +9,12 @@ The `@karnak19/pbkit-zod` package provides a plugin that generates [Zod](https:/ ## Install +The plugin runs at generation time, so it is a dev dependency. `zod` is imported +by the generated schemas at runtime. + ```bash -bun add @karnak19/pbkit-zod zod +bun add -d @karnak19/pbkit-zod +bun add zod ``` ## Setup diff --git a/apps/docs/src/content/docs/how-to/install.md b/apps/docs/src/content/docs/how-to/install.md index c8c4216..38a824c 100644 --- a/apps/docs/src/content/docs/how-to/install.md +++ b/apps/docs/src/content/docs/how-to/install.md @@ -12,8 +12,12 @@ sidebar: ## Install +pbkit is a build-time code generator, so install it as a dev dependency. Keep +`pocketbase` as a regular dependency — your app uses its SDK at runtime. + ```bash -bun add @karnak19/pbkit pocketbase +bun add -d @karnak19/pbkit +bun add pocketbase ``` ## Verify diff --git a/skills/pbkit/SKILL.md b/skills/pbkit/SKILL.md index e6eb809..ff482de 100644 --- a/skills/pbkit/SKILL.md +++ b/skills/pbkit/SKILL.md @@ -20,25 +20,30 @@ Use pbkit when a project needs type-safe TypeScript access to a PocketBase backe ## Install ```bash -bun add @karnak19/pbkit pocketbase +bun add -d @karnak19/pbkit +bun add pocketbase ``` -`pocketbase` is a peer/runtime dependency for projects that use generated SDK functions. +pbkit is a build-time code generator, so install it as a devDependency. `pocketbase` is a peer/runtime dependency for projects that use generated SDK functions, so it stays a regular dependency. For TanStack Query generation: ```bash -bun add @karnak19/pbkit-tanstack @tanstack/query-core +bun add -d @karnak19/pbkit-tanstack +bun add @tanstack/query-core ``` -Install the framework adapter used by the app as well, such as `@tanstack/react-query`, `@tanstack/solid-query`, `@tanstack/svelte-query`, or `@tanstack/vue-query`. +The plugin is build-time (devDependency); `@tanstack/query-core` is imported by generated code at runtime. Install the framework adapter used by the app as well, such as `@tanstack/react-query`, `@tanstack/solid-query`, `@tanstack/svelte-query`, or `@tanstack/vue-query`. For Zod schema generation: ```bash -bun add @karnak19/pbkit-zod zod +bun add -d @karnak19/pbkit-zod +bun add zod ``` +The plugin is build-time (devDependency); `zod` is imported by the generated schemas at runtime. + ## Configuration Create `pbkit.config.ts` in the project root (also supports `.js` and `.mjs`):