From 1391c21c1fb4e9386875435fbdbf1341c02a4ca8 Mon Sep 17 00:00:00 2001 From: Marc Villain Date: Tue, 3 Nov 2026 12:43:11 +0100 Subject: [PATCH] docs: every example imports what it uses --- docs/adapters.md | 19 ++++++++++++++++++- docs/dialects.md | 6 ++++-- docs/security.md | 6 ++++-- docs/writes.md | 4 +++- docs/writing-a-dialect.md | 2 ++ 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/docs/adapters.md b/docs/adapters.md index d21d8e3..e18c681 100644 --- a/docs/adapters.md +++ b/docs/adapters.md @@ -3,10 +3,21 @@ The core answers a plain request object, so it fits any framework: ```ts +import pg from 'pg'; +import { createREST } from '@crudy/restloom'; +import { postgres } from '@crudy/restloom-postgres'; + +const rest = createREST({ + db: postgres(new pg.Pool({ connectionString: process.env.DATABASE_URL })), + expose: { schemas: ['app'] }, +}); + const response = await rest.handle({ method, path, query, headers, body, context }); // { status, headers, body } ``` +The examples below use this `rest`. + `handle` never throws: every failure is a response. `path` is the path below where the API is mounted (`/todos/4`), `query` a `URLSearchParams`, `body` the parsed JSON. ## Node, without a framework @@ -15,7 +26,7 @@ const response = await rest.handle({ method, path, query, headers, body, context ```ts import http from 'node:http'; -import { createREST, nodeListener } from '@crudy/restloom'; +import { nodeListener } from '@crudy/restloom'; const api = nodeListener(rest, { prefix: '/api', context: (req) => userFrom(req) }); http.createServer(api).listen(3000); @@ -24,6 +35,8 @@ http.createServer(api).listen(3000); To serve other pages from the same server, hand only the API's paths to it: ```ts +import http from 'node:http'; + http.createServer((req, res) => (req.url?.startsWith('/api/') ? api(req, res) : site(req, res))).listen(3000); ``` @@ -36,8 +49,10 @@ npm install @crudy/restloom-fastify ``` ```ts +import Fastify from 'fastify'; import { restloom } from '@crudy/restloom-fastify'; +const app = Fastify(); await app.register(restloom(rest, { context: (req) => req.user }), { prefix: '/api' }); ``` @@ -50,8 +65,10 @@ npm install @crudy/restloom-express ``` ```ts +import express from 'express'; import { restloom } from '@crudy/restloom-express'; +const app = express(); app.use('/api', express.json(), restloom(rest, { context: (req) => req.user })); ``` diff --git a/docs/dialects.md b/docs/dialects.md index a7c5e2e..54c27ff 100644 --- a/docs/dialects.md +++ b/docs/dialects.md @@ -14,9 +14,10 @@ Every dialect passes the same conformance suite, so a request answers the same r ## Postgres ```ts +import pg from 'pg'; import { postgres } from '@crudy/restloom-postgres'; -const db = postgres(pool); +const db = postgres(new pg.Pool({ connectionString: process.env.DATABASE_URL })); ``` - **Transactions:** every request is one transaction, `READ ONLY` for reads, with `SET LOCAL statement_timeout` from `limits.timeoutMs`. @@ -76,6 +77,7 @@ const db = sqlite(new Database('app.db')); Every piece of SQL comes from one overridable method of the dialect's renderer. To change one, subclass it and pass it in: ```ts +import pg from 'pg'; import { PostgresRenderer, postgres } from '@crudy/restloom-postgres'; class Renderer extends PostgresRenderer { @@ -84,7 +86,7 @@ class Renderer extends PostgresRenderer { } } -const db = postgres(pool, { renderer: new Renderer() }); +const db = postgres(new pg.Pool({ connectionString: process.env.DATABASE_URL }), { renderer: new Renderer() }); ``` The pieces are listed in [writing a dialect](./writing-a-dialect.md). diff --git a/docs/security.md b/docs/security.md index d902caf..46d9886 100644 --- a/docs/security.md +++ b/docs/security.md @@ -55,7 +55,7 @@ resources: { import { createREST, DEFAULT_SENSITIVE } from '@crudy/restloom'; createREST({ - db, + db, // from a database package, see Dialects expose: { schemas: ['app'] }, sensitive: new RegExp(`${DEFAULT_SENSITIVE.source}|(^|_)(iban|ssn)(_|$)`, 'i'), }); @@ -64,8 +64,10 @@ createREST({ ## Hooks ```ts +import { createREST, RestError } from '@crudy/restloom'; + createREST({ - db, + db, // from a database package, see Dialects expose: { schemas: ['app'] }, hooks: { authorize(request, target) { /* throw a RestError to refuse */ }, diff --git a/docs/writes.md b/docs/writes.md index 87f6169..e36f4b4 100644 --- a/docs/writes.md +++ b/docs/writes.md @@ -28,8 +28,10 @@ procedures: { For an API that writes everywhere, set `write` once, beside `expose`: ```ts +import { createREST } from '@crudy/restloom'; + createREST({ - db, + db, // from a database package, see Dialects expose: { schemas: ['app'] }, write: true, resources: { diff --git a/docs/writing-a-dialect.md b/docs/writing-a-dialect.md index ab9acaf..c1b8ca9 100644 --- a/docs/writing-a-dialect.md +++ b/docs/writing-a-dialect.md @@ -3,6 +3,8 @@ A dialect implements one interface: ```ts +import type { Catalog, RestError, SqlRenderer, Tx } from '@crudy/restloom'; + interface Dialect { name: string; capabilities: { returning: boolean; estimatedCount: boolean; rowSecurity: boolean; procedures: boolean };