feat: writes, procedures, Fastify and Express adapters, documentation

This commit is contained in:
2026-11-02 01:25:49 +01:00
parent 4b276f21e3
commit 6801f257fb
35 changed files with 3109 additions and 182 deletions
+20
View File
@@ -0,0 +1,20 @@
import { SqlRenderer } from '../dist/index.js';
/** A dialect with one table and canned rows, for adapter and wiring tests without a database. */
export function fakeDialect(rows = [{ id: 1, name: 'one' }]) {
const statements = [];
return {
statements,
name: 'fake',
capabilities: { returning: true, estimatedCount: false, rowSecurity: false },
renderer: new SqlRenderer(),
async introspect() {
const col = (name, type) => ({ name, type, nativeType: type, nullable: false, generated: false });
return { functions: [], tables: [{ schema: 'app', name: 'items', kind: 'table', primaryKey: ['id'], foreignKeys: [], columns: [col('id', 'integer'), col('name', 'text')] }] };
},
async transaction(fn) {
return fn({ async query(sql) { statements.push(sql); return sql.startsWith('SELECT COUNT') ? [{ n: rows.length }] : rows.map((r) => ({ r })); } });
},
mapError: () => null,
};
}
+20
View File
@@ -0,0 +1,20 @@
import { test } from 'node:test';
import assert from 'node:assert/strict';
import http from 'node:http';
import { createREST, nodeListener } from '../dist/index.js';
import { fakeDialect } from './fake-dialect.mjs';
test('the node listener serves under its prefix and refuses bad bodies', async () => {
const rest = createREST({ db: fakeDialect(), expose: { schemas: ['app'] } });
const server = http.createServer(nodeListener(rest, { prefix: '/api' })).listen(0);
const base = `http://127.0.0.1:${server.address().port}`;
try {
assert.equal((await fetch(`${base}/api/items`)).status, 200);
assert.equal((await fetch(`${base}/items`)).status, 404);
const bad = await fetch(`${base}/api/items`, { method: 'POST', body: '{nope' });
assert.equal(bad.status, 400);
assert.deepEqual(await bad.json(), { error: 'bad_body' });
} finally {
server.close();
}
});