feat: one install and one import per database; server dialects open their pool from a URL; nodeListener answers a throwing context; 0.5.0
This commit is contained in:
+4
-6
@@ -3,12 +3,10 @@
|
||||
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';
|
||||
import { createREST, postgres } from '@crudy/restloom-postgres';
|
||||
|
||||
const rest = createREST({
|
||||
db: postgres(new pg.Pool({ connectionString: process.env.DATABASE_URL })),
|
||||
db: postgres(process.env.DATABASE_URL),
|
||||
expose: { schemas: ['app'] },
|
||||
});
|
||||
|
||||
@@ -22,11 +20,11 @@ The examples below use this `rest`.
|
||||
|
||||
## Node, without a framework
|
||||
|
||||
`nodeListener` from the core serves `node:http` with nothing else installed. It mounts the API under `prefix` and answers `404 not_found` outside it, reads JSON bodies up to 1 MiB (`maxBodyBytes`), and builds each request's context with `context`:
|
||||
`nodeListener` from the core serves `node:http` with nothing else installed. It mounts the API under `prefix` and answers `404 not_found` outside it, reads JSON bodies up to 1 MiB (`maxBodyBytes`), and builds each request's context with `context`. A `context` that throws a `RestError` refuses the request with it; any other error answers `500 internal`:
|
||||
|
||||
```ts
|
||||
import http from 'node:http';
|
||||
import { nodeListener } from '@crudy/restloom';
|
||||
import { nodeListener } from '@crudy/restloom-postgres';
|
||||
|
||||
const api = nodeListener(rest, { prefix: '/api', context: (req) => userFrom(req) });
|
||||
http.createServer(api).listen(3000);
|
||||
|
||||
+10
-8
@@ -9,15 +9,16 @@ A dialect is the package that knows one database: how to read its catalog, how t
|
||||
| `@crudy/restloom-mssql` | SQL Server 2022+ | `JSON_OBJECT`, `STRING_AGG` | `OUTPUT` | no | security policies | scalar and table functions |
|
||||
| `@crudy/restloom-sqlite` | SQLite 3.44+ (better-sqlite3) | `json_object`, `json_group_array` | `RETURNING` | no | no | none |
|
||||
|
||||
The PostgreSQL, MySQL and SQL Server packages bring their driver and open their own connection from a URL. To tune it, pass the driver's pool options instead, or a pool you already have: a `pg` Pool, a `mysql2/promise` Pool or a connected `mssql` ConnectionPool. The SQLite package takes a database object, so it runs on `better-sqlite3` in Node or on sql.js in a browser; install the one you use.
|
||||
|
||||
Every dialect passes the same conformance suite, so a request answers the same rows on each. Regular expressions (`match`, `imatch`) need Postgres or MySQL, and array filters (`ov`, `cs`, `cd`) Postgres array columns; elsewhere they answer `unsupported`. Where else the dialects differ, the sections below say how.
|
||||
|
||||
## Postgres
|
||||
|
||||
```ts
|
||||
import pg from 'pg';
|
||||
import { postgres } from '@crudy/restloom-postgres';
|
||||
|
||||
const db = postgres(new pg.Pool({ connectionString: process.env.DATABASE_URL }));
|
||||
const db = postgres(process.env.DATABASE_URL);
|
||||
```
|
||||
|
||||
- **Transactions:** every request is one transaction, `READ ONLY` for reads, with `SET LOCAL statement_timeout` from `limits.timeoutMs`.
|
||||
@@ -28,10 +29,9 @@ const db = postgres(new pg.Pool({ connectionString: process.env.DATABASE_URL }))
|
||||
## MySQL
|
||||
|
||||
```ts
|
||||
import { createPool } from 'mysql2/promise';
|
||||
import { mysql } from '@crudy/restloom-mysql';
|
||||
|
||||
const db = mysql(createPool({ uri: process.env.DATABASE_URL }));
|
||||
const db = mysql(process.env.DATABASE_URL);
|
||||
```
|
||||
|
||||
- **Schemas:** MySQL's schemas are its databases: `expose: { schemas: ['shop'] }`.
|
||||
@@ -44,10 +44,9 @@ const db = mysql(createPool({ uri: process.env.DATABASE_URL }));
|
||||
## SQL Server
|
||||
|
||||
```ts
|
||||
import sql from 'mssql';
|
||||
import { mssql } from '@crudy/restloom-mssql';
|
||||
|
||||
const db = mssql(await new sql.ConnectionPool(process.env.DATABASE_URL).connect());
|
||||
const db = mssql(process.env.DATABASE_URL);
|
||||
```
|
||||
|
||||
- **Version:** SQL Server 2022 or later, for `JSON_OBJECT`.
|
||||
@@ -59,6 +58,10 @@ const db = mssql(await new sql.ConnectionPool(process.env.DATABASE_URL).connect(
|
||||
|
||||
## SQLite
|
||||
|
||||
```sh
|
||||
npm install @crudy/restloom-sqlite better-sqlite3
|
||||
```
|
||||
|
||||
```ts
|
||||
import Database from 'better-sqlite3';
|
||||
import { sqlite } from '@crudy/restloom-sqlite';
|
||||
@@ -77,7 +80,6 @@ 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 {
|
||||
@@ -86,7 +88,7 @@ class Renderer extends PostgresRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
const db = postgres(new pg.Pool({ connectionString: process.env.DATABASE_URL }), { renderer: new Renderer() });
|
||||
const db = postgres(process.env.DATABASE_URL, { renderer: new Renderer() });
|
||||
```
|
||||
|
||||
The pieces are listed in [writing a dialect](./writing-a-dialect.md).
|
||||
|
||||
+12
-12
@@ -2,29 +2,29 @@
|
||||
|
||||
## Install
|
||||
|
||||
Install the core, the package for your database, and its driver:
|
||||
Install the package for your database. It brings the core and the database driver with it, except for SQLite, which also needs `better-sqlite3`:
|
||||
|
||||
```sh
|
||||
npm install @crudy/restloom @crudy/restloom-postgres pg
|
||||
npm install @crudy/restloom-postgres
|
||||
```
|
||||
|
||||
| Database | Package | Driver |
|
||||
|---|---|---|
|
||||
| PostgreSQL 13+ | `@crudy/restloom-postgres` | `pg` |
|
||||
| MySQL 8.0+ | `@crudy/restloom-mysql` | `mysql2` |
|
||||
| SQL Server 2022+ | `@crudy/restloom-mssql` | `mssql` |
|
||||
| SQLite 3.44+ | `@crudy/restloom-sqlite` | `better-sqlite3` |
|
||||
| Database | Package |
|
||||
|---|---|
|
||||
| PostgreSQL 13+ | `@crudy/restloom-postgres` |
|
||||
| MySQL 8.0+ | `@crudy/restloom-mysql` |
|
||||
| SQL Server 2022+ | `@crudy/restloom-mssql` |
|
||||
| SQLite 3.44+ | `@crudy/restloom-sqlite` |
|
||||
|
||||
Each of them exports the whole core, so everything is imported from that one package. The examples in these pages use `@crudy/restloom-postgres`; with another database, import from its package instead.
|
||||
|
||||
## Serve a schema
|
||||
|
||||
```ts
|
||||
import http from 'node:http';
|
||||
import pg from 'pg';
|
||||
import { createREST, nodeListener } from '@crudy/restloom';
|
||||
import { postgres } from '@crudy/restloom-postgres';
|
||||
import { createREST, nodeListener, postgres } from '@crudy/restloom-postgres';
|
||||
|
||||
const rest = createREST({
|
||||
db: postgres(new pg.Pool({ connectionString: process.env.DATABASE_URL })),
|
||||
db: postgres(process.env.DATABASE_URL),
|
||||
expose: { schemas: ['app'] },
|
||||
});
|
||||
|
||||
|
||||
+2
-2
@@ -52,7 +52,7 @@ resources: {
|
||||
`sensitive` replaces the whole pattern, for every resource. Start from `DEFAULT_SENSITIVE` to add words rather than lose the defaults:
|
||||
|
||||
```ts
|
||||
import { createREST, DEFAULT_SENSITIVE } from '@crudy/restloom';
|
||||
import { createREST, DEFAULT_SENSITIVE } from '@crudy/restloom-postgres';
|
||||
|
||||
createREST({
|
||||
db, // from a database package, see Dialects
|
||||
@@ -64,7 +64,7 @@ createREST({
|
||||
## Hooks
|
||||
|
||||
```ts
|
||||
import { createREST, RestError } from '@crudy/restloom';
|
||||
import { createREST, RestError } from '@crudy/restloom-postgres';
|
||||
|
||||
createREST({
|
||||
db, // from a database package, see Dialects
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ procedures: {
|
||||
For an API that writes everywhere, set `write` once, beside `expose`:
|
||||
|
||||
```ts
|
||||
import { createREST } from '@crudy/restloom';
|
||||
import { createREST } from '@crudy/restloom-postgres';
|
||||
|
||||
createREST({
|
||||
db, // from a database package, see Dialects
|
||||
|
||||
Reference in New Issue
Block a user