Demos
Every page of this documentation shows fragments. These are the projects those fragments are cut from: complete, running, and read straight out of the repository rather than copied into a page.
Pick one, open any file, and run the ones that do not need a native binary.
38 demos, all of them running code in this repository.
demos/one-declaration4 filesmain.ts
/**
* Six lines in. Everything else out.
*
* This demo writes ONE entity and then asks four different consumers what they
* make of it — the SQL dialect, the wire, the io projection, the validator. Nobody
* wrote any of the four. Run it and read the arrows.
*/
import { Card, entity, primary, text, number, created, Visibility } from '@fougere/schema';
import { toTable, createTableSQL } from '@fougere/adapter-sql';
// ─────────────────────────────────────────────────────────────────────────────
// WHAT YOU WRITE
// ─────────────────────────────────────────────────────────────────────────────
class Reading extends entity({
id: primary(),
station: text({ min: 2, max: 40 }),
celsius: number({ min: -90, max: 60 }),
recordedAt: created(),
}) {}
// ─────────────────────────────────────────────────────────────────────────────
const B = (s: string) => `\x1b[1m${s}\x1b[0m`;
const D = (s: string) => `\x1b[2m${s}\x1b[0m`;
const G = (s: string) => `\x1b[32m${s}\x1b[0m`;
const R = (s: string) => `\x1b[31m${s}\x1b[0m`;
function section(arrow: string, title: string, who: string) {
console.log(`\n${D(' ' + arrow)} ${B(title)}\n ${D(who)}\n`);
}
console.log(`
${G('🌿 fougere')} one declaration
${B('class Reading extends entity({')}
${B(' id: primary(),')}
${B(" station: text({ min: 2, max: 40 }),")}
${B(' celsius: number({ min: -90, max: 60 }),')}
${B(' recordedAt: created(),')}
${B('}) {}')}
`);
// ── 1. the database ──────────────────────────────────────────────────────────
section('→', 'The table', 'schema-sql, sqlite dialect — nobody wrote this DDL');
const ddl = createTableSQL(toTable('reading', Reading as never), 'sqlite');
console.log(ddl.replace(/, (constraint)/g, ',\n $1').replace(/\(("id")/, '(\n $1').replace(/, ("station"|"celsius"|"recorded_at")/g, ',\n $1'));
console.log(D(`
The bounds became CHECK constraints. So raw SQL, another process, or a
human at a prompt meets "at least 2 characters" too — not just this app.`));
// ── 2. the wire ──────────────────────────────────────────────────────────────
section('→', 'The identity card', 'what crosses to another language — plain JSON Schema');
const card = Card.fromSchema(Reading as never, 'reading').descriptor;
console.log(JSON.stringify(card, null, 2).split('\n').map((l) => ' ' + l).join('\n'));
console.log(D(`
${JSON.stringify(card).length} bytes, and any validator on earth reads it. This is the
document demos/rust-frond publishes — a Frond written in Rust, consumed
from TypeScript, with no shared code.`));
// ── 3. the io projection ─────────────────────────────────────────────────────
section('→', 'What a client may send, and what it gets back', 'the boundary axis — nobody listed these');
const may = Object.keys(Visibility.of(Reading.getFields() as never).input);
const gets = Object.keys(Visibility.of(Reading.getFields() as never).output);
console.log(` ${D('a client may send ')} ${may.join(', ')}`);
console.log(` ${D('a client receives ')} ${gets.join(', ')}`);
console.log(D(`
Nobody wrote "a client cannot supply an id". primary() and created() say it,
and the facade reads them.`));
// ── 4. the validator ─────────────────────────────────────────────────────────────
section('→', 'The validator', 'the same verdict in the browser, at the façade, and across a split');
for (const [label, input] of [
['{ station: "x", celsius: 200 }', { station: 'x', celsius: 200 }],
['{ station: "harbour", celsius: 12.1 }', { station: 'harbour', celsius: 12.1 }],
] as const) {
const verdict = Reading.validate(input);
console.log(` ${D(label.padEnd(38))} ${verdict.success
? G('accepted')
: R(verdict.errors.map((e) => `${e.path}: ${e.message}`).join(' · '))}`);
}
console.log(`
${B('Four consumers, one declaration.')} ${D('None of the four was written by hand, and')}
${D('none can drift from the others — there is nothing to keep in sync.')}
`);
Each demo also runs locally, which is the only way to see the ones that hold a database:
git clone https://github.com/chok/fougere.git
cd fougere && pnpm install && pnpm run build
pnpm -C demos/nuxt-blog dev