Skip to content

Commit f2197e2

Browse files
ryanrasticlaude
andcommitted
refactor(sqlite): fold signatures.ts into the dialect entry; EXCLUSIONS as plain names
signatures.ts had shrunk to a JSON loader, the EXCLUSIONS list, and type re-export shims — no logic of its own. The loader and EXCLUSIONS move into emit.ts (the dialect entry now owns ALL its data: facts, exclusions, type table, chrome); the verifier imports SIGNATURES/ EXCLUSIONS from there and its types from the shared facts module. EXCLUSIONS drops the {name, reason} shape — nothing consumed reason as data (the verifier only reads names), so reasons live as comments over a plain string list. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 7b8e1cc commit f2197e2

10 files changed

Lines changed: 85 additions & 96 deletions

File tree

src/types/sqlite/docs/index.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,17 @@
1010
// the subject argument's documented domain; every function is also a
1111
// free function; names = camelCase(sql) / operator symbol + alias).
1212
// There is no per-function policy layer: the only remaining judgment
13-
// lives in ../signatures.ts's EXCLUSIONS list and the emit rules
13+
// lives in ../emit.ts's EXCLUSIONS list and the emit rules
1414
// themselves. This keeps the 1:1 claim strict — an extraction file is
1515
// checkable against its page alone — and makes extraction fidelity
1616
// load-bearing: the receiver argument's documented domain is what
1717
// decides which typed views surface a method.
1818
//
1919
// The structural schema is shared with postgres (emission/facts.ts);
2020
// this file adds the sqlite-only refinements and the extraction
21-
// prompt. signatures.ts loads + zod-validates every JSON at module load (fs,
22-
// not import-attributes — parser-neutral across node strip-types,
23-
// swc, tsgo, tsdown) and joins facts with policy into SIGNATURES.
24-
// The property verifier (signatures.verify.test.ts) remains the
25-
// correctness oracle for every claim in these files.
21+
// prompt. ../emit.ts loads + zod-validates every JSON at module load
22+
// into SIGNATURES. The property verifier (signatures.verify.test.ts)
23+
// remains the correctness oracle for every claim in these files.
2624

2725
import z from "zod";
2826
import {

src/types/sqlite/emit.ts

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,28 @@
11
// SQLite dialect codegen entry — facts + type table + class chrome in,
22
// generated .ts files out via the unified emitter (../emission/emit.ts).
33
// All emission knowledge lives there; this file contributes DATA: the
4-
// committed facts (via signatures.ts), the sqlite type table, and the
4+
// committed per-doc-page facts (docs/<page>.json — schema and
5+
// extraction prompt in docs/index.ts), the sqlite type table, and the
56
// per-class chrome (imports/statics/heritage).
67
//
8+
// The emitted surface is derived from the facts by global rules —
9+
// - method receivers = each overload's FIRST argument's domain
10+
// ("any" ⇒ universal); args are in exact SQL call order;
11+
// - names are camelCase(sql) for functions, symbol + PG-style
12+
// alias for operators.
13+
// The only remaining judgment is EXCLUSIONS below. Every claim is
14+
// mechanically checked by signatures.verify.test.ts against the real
15+
// engine; its completeness gate ensures every pragma_function_list
16+
// entry is either defined in the facts or excluded here.
17+
//
718
// Run: node --experimental-strip-types src/types/sqlite/emit.ts
819
// [--out-dir <dir>] (codegen:check)
920

21+
import * as fs from "node:fs";
1022
import * as path from "node:path";
1123
import { pathToFileURL } from "node:url";
12-
import { SIGNATURES } from "./signatures.ts";
24+
import { DocPageSchema } from "./docs/index.ts";
25+
import { type EmitFn } from "../emission/facts.ts";
1326
import {
1427
writeGeneratedTree,
1528
chromeImportLines,
@@ -22,7 +35,60 @@ import {
2235
} from "../emission/emit.ts";
2336

2437
const HEADER =
25-
"// Auto-generated by src/types/sqlite/emit.ts from signatures.ts — do not edit.\n";
38+
"// Auto-generated by src/types/sqlite/emit.ts from docs/*.json — do not edit.\n";
39+
40+
// --- facts: one JSON per vendored doc page --------------------------------
41+
// Loaded with fs (not import attributes — parser-neutral across node
42+
// strip-types / swc / tsgo / tsdown) and zod-validated at import time:
43+
// a malformed JSON fails loudly here, before any emission.
44+
45+
const PAGES = [
46+
"lang_corefunc",
47+
"lang_mathfunc",
48+
"lang_datefunc",
49+
"lang_aggfunc",
50+
"percentile",
51+
"json1",
52+
"lang_expr",
53+
] as const;
54+
55+
export const SIGNATURES: EmitFn[] = PAGES.flatMap((page) => {
56+
const raw = fs.readFileSync(path.join(import.meta.dirname, "docs", `${page}.json`), "utf8");
57+
return DocPageSchema.parse(JSON.parse(raw)).functions;
58+
});
59+
60+
// Functions typegres refuses to surface — the completeness gate's
61+
// whitelist: every pragma_function_list entry must be either defined
62+
// in the facts or listed here.
63+
export const EXCLUSIONS: string[] = [
64+
// Window functions — typegres has no OVER-clause modeling yet (PG
65+
// doesn't either). Revisit with window support in the query builder.
66+
"row_number", "rank", "dense_rank", "percent_rank", "cume_dist", "ntile",
67+
"lag", "lead", "first_value", "last_value", "nth_value",
68+
// FTS / rtree / geopoly — only meaningful on virtual tables, which
69+
// typegres doesn't model.
70+
"bm25", "fts3_tokenizer", "fts5", "fts5_get_locale", "fts5_insttoken",
71+
"fts5_locale", "fts5_source_id", "highlight", "matchinfo", "offsets",
72+
"optimize", "snippet",
73+
"rtreecheck", "rtreedepth", "rtreenode",
74+
"geopoly_area", "geopoly_bbox", "geopoly_blob", "geopoly_ccw",
75+
"geopoly_contains_point", "geopoly_debug", "geopoly_group_bbox",
76+
"geopoly_json", "geopoly_overlap", "geopoly_regular", "geopoly_svg",
77+
"geopoly_within", "geopoly_xform",
78+
"match", // MATCH operator function — only meaningful on FTS virtual tables
79+
// Planner hints — no-ops for typing purposes; noise on the API.
80+
"likelihood", "likely", "unlikely",
81+
// Introspection / footguns.
82+
"load_extension", // loads native code — must not be reachable from a query builder
83+
"sqlite_compileoption_get", // build introspection
84+
"sqlite_compileoption_used", // build introspection
85+
"sqlite_offset", // low-level file-offset introspection
86+
"sqlite_log", // error-log side effect, returns nothing useful
87+
"subtype", // internal function-subtype plumbing
88+
// CURRENT_* keywords aren't callable syntax — the datetime functions
89+
// cover them (date('now'), time('now'), datetime('now')).
90+
"current_date", "current_time", "current_timestamp",
91+
];
2692

2793
// The sqlite type table. No `generic`/`element` entries (sqlite has
2894
// no containers or pseudotypes), so the emitter's T-threading

src/types/sqlite/generated/any.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Auto-generated by src/types/sqlite/emit.ts from signatures.ts — do not edit.
1+
// Auto-generated by src/types/sqlite/emit.ts from docs/*.json — do not edit.
22
// The generated half of the SQLite root class (hand-written core —
33
// dialect metadata, isNull/isNotNull/in — extends this in
44
// ../overrides/any.ts). Carries ONLY the universal methods (subject

src/types/sqlite/generated/blob.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Auto-generated by src/types/sqlite/emit.ts from signatures.ts — do not edit.
1+
// Auto-generated by src/types/sqlite/emit.ts from docs/*.json — do not edit.
22
// Blob<N> — the blob storage-class view: the __view brand
33
// (near-identical subclasses are otherwise structurally
44
// interchangeable, defeating nominal checks), [meta]/typname chrome,

src/types/sqlite/generated/bool.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Auto-generated by src/types/sqlite/emit.ts from signatures.ts — do not edit.
1+
// Auto-generated by src/types/sqlite/emit.ts from docs/*.json — do not edit.
22
// Bool<N> — the bool storage-class view: the __view brand
33
// (near-identical subclasses are otherwise structurally
44
// interchangeable, defeating nominal checks), [meta]/typname chrome,

src/types/sqlite/generated/integer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Auto-generated by src/types/sqlite/emit.ts from signatures.ts — do not edit.
1+
// Auto-generated by src/types/sqlite/emit.ts from docs/*.json — do not edit.
22
// Integer<N> — the integer storage-class view: the __view brand
33
// (near-identical subclasses are otherwise structurally
44
// interchangeable, defeating nominal checks), [meta]/typname chrome,

src/types/sqlite/generated/real.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Auto-generated by src/types/sqlite/emit.ts from signatures.ts — do not edit.
1+
// Auto-generated by src/types/sqlite/emit.ts from docs/*.json — do not edit.
22
// Real<N> — the real storage-class view: the __view brand
33
// (near-identical subclasses are otherwise structurally
44
// interchangeable, defeating nominal checks), [meta]/typname chrome,

src/types/sqlite/generated/text.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Auto-generated by src/types/sqlite/emit.ts from signatures.ts — do not edit.
1+
// Auto-generated by src/types/sqlite/emit.ts from docs/*.json — do not edit.
22
// Text<N> — the text storage-class view: the __view brand
33
// (near-identical subclasses are otherwise structurally
44
// interchangeable, defeating nominal checks), [meta]/typname chrome,

src/types/sqlite/signatures.ts

Lines changed: 0 additions & 78 deletions
This file was deleted.

src/types/sqlite/signatures.verify.test.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
// Property verifier for signatures.ts — checks every claimed
1+
// Property verifier for the sqlite facts (docs/*.json, loaded by
2+
// emit.ts as SIGNATURES) — checks every claimed
23
// signature against the real SQLite engine (better-sqlite3, the same
34
// build the driver uses). See plan.md.
45
//
@@ -16,7 +17,9 @@ import { describe, test, expect, beforeAll, afterAll } from "vitest";
1617
import Database from "better-sqlite3";
1718
import * as fs from "node:fs";
1819
import * as path from "node:path";
19-
import { SIGNATURES, EXCLUSIONS, type FnDef, type Overload, type ArgDef, type SqlT, type Hint } from "./signatures";
20+
import { SIGNATURES, EXCLUSIONS } from "./emit.ts";
21+
import type { EmitFn as FnDef, EmitOverload as Overload, EmitArg as ArgDef } from "../emission/facts.ts";
22+
import type { SqlT, Hint } from "./docs/index.ts";
2023

2124
let db: Database.Database;
2225
beforeAll(() => { db = new Database(":memory:"); });
@@ -120,7 +123,7 @@ describe("completeness gate", () => {
120123
(db.prepare("SELECT DISTINCT name FROM pragma_function_list").all() as { name: string }[]).map((r) => r.name),
121124
);
122125
const defined = new Set(SIGNATURES.map((f) => f.sql));
123-
const excluded = new Set(EXCLUSIONS.map((e) => e.name));
126+
const excluded = new Set(EXCLUSIONS);
124127

125128
const unaccounted = [...pragmaNames].filter((n) => !defined.has(n) && !excluded.has(n));
126129
expect(unaccounted, `pragma functions neither defined nor excluded`).toEqual([]);

0 commit comments

Comments
 (0)