@kequtech/tenon-orm 0.4.2 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -22,17 +22,41 @@ Supply `DATABASE_URL` through your environment setup. For a local example databa
22
22
  export DATABASE_URL=postgresql://postgres:postgres@localhost:5432/your_database
23
23
  ```
24
24
 
25
- Tenon does not create the database or load `.env` files. Create one shared database module:
25
+ Tenon does not create the database or load `.env` files. Create shared configuration:
26
+
27
+ ```sh
28
+ npx tenon init
29
+ ```
30
+
31
+ The command writes `tenon.config.ts` without opening a database or overwriting existing config:
32
+
33
+ ```ts
34
+ // tenon.config.ts
35
+ import type { TenonConfig } from '@kequtech/tenon-orm';
36
+
37
+ const connectionString = process.env.DATABASE_URL;
38
+ if (!connectionString) throw new Error('DATABASE_URL is required');
39
+ export default {
40
+ connection: { connectionString },
41
+ migrations: { directory: 'migrations', namespace: 'public' },
42
+ generate: { out: 'src/generated-schema.d.ts' },
43
+ check: { project: 'tsconfig.json' },
44
+ } satisfies TenonConfig;
45
+ ```
46
+
47
+ Use it in the application too:
26
48
 
27
49
  ```ts
28
50
  // src/db.ts
29
51
  import { createTenon } from '@kequtech/tenon-orm';
52
+ import config from '../tenon.config.ts';
30
53
 
31
- const connection = process.env.DATABASE_URL;
32
- if (!connection) throw new Error('DATABASE_URL is required');
33
- export const db = createTenon({ connection });
54
+ export const db = createTenon({ connection: config.connection });
34
55
  ```
35
56
 
57
+ These `.ts` imports use Node.js 24+ TypeScript support. See
58
+ [shared configuration](configuration.md) for import conventions, custom codecs, discovery, and overrides.
59
+
36
60
  Reuse `db` across requests. Call `await db.close()` when a standalone script finishes or a server
37
61
  shuts down. See [connections](connections.md) for pool options and application-owned pools.
38
62
 
@@ -166,35 +190,26 @@ savepoints, and retry limits. For object-based inserts and patches, see [writing
166
190
  ## Generate types
167
191
 
168
192
  Generation is optional. It reads the migrated database and writes table read/insert/update types.
169
- Run it through the configured instance so the types use the same value conversions as your queries:
170
-
171
- ```ts
172
- // scripts/generate-types.ts
173
- import { parseArgs } from 'node:util';
174
- import { db } from '../src/db.ts';
193
+ The CLI uses the shared connection and codecs from `tenon.config.ts`:
175
194
 
176
- const { values } = parseArgs({ options: { check: { type: 'boolean', default: false } } });
177
- try {
178
- await db.generateTypes({ out: 'src/generated-schema.d.ts', check: values.check });
179
- } finally {
180
- await db.close();
181
- }
195
+ ```sh
196
+ npx tenon generate
197
+ npx tenon generate --check
182
198
  ```
183
199
 
184
- This script runs directly on Node.js 24+ using its TypeScript support. For this execution path,
185
- `src/db.ts` must be runnable without build-time transformations or extension rewriting. If your
186
- project compiles scripts, use its normal runner and import conventions instead. To typecheck `.ts`
187
- imports with `noEmit`, enable `allowImportingTsExtensions`; emitting projects can use
188
- `rewriteRelativeImportExtensions`.
200
+ The second command checks committed output without rewriting it. The namespace comes from
201
+ `generate.namespace`, then `migrations.namespace`, then `public`, independently of runtime
202
+ `search_path`. Generate after migrations have committed.
189
203
 
190
- Add these scripts to your existing `package.json`:
204
+ Add these commands to your existing `package.json`:
191
205
 
192
206
  ```json
193
207
  {
194
208
  "scripts": {
195
- "db:generate": "node scripts/generate-types.ts",
196
- "db:check-types": "npm run db:generate -- --check",
197
- "db:migrate": "tenon migrate && npm run db:generate"
209
+ "db:generate": "tenon generate",
210
+ "db:check-types": "tenon generate --check",
211
+ "db:check": "tenon check",
212
+ "db:migrate": "tenon migrate && tenon generate"
198
213
  }
199
214
  }
200
215
  ```
@@ -10,8 +10,10 @@ you intend to [transfer migration ownership](adoption-guide.md#transfer-migratio
10
10
  npx tenon new add_user_display_name
11
11
  ```
12
12
 
13
- `new` works offline. It creates the next numeric pair in `migrations/`, starting at `0001` in an empty
14
- directory. For a directory whose latest migration is `0001`:
13
+ `new` opens no database connection. It creates the next numeric pair in the configured migration
14
+ directory, defaulting to `migrations/`, and starts at `0001` in an empty directory. As with other
15
+ commands, importing your config may require its environment values. For a directory whose latest
16
+ migration is `0001`:
15
17
 
16
18
  ```sql
17
19
  -- migrations/0002_add_user_display_name.up.sql
@@ -23,7 +25,8 @@ ALTER TABLE public.users ADD COLUMN display_name text;
23
25
  ALTER TABLE public.users DROP COLUMN display_name;
24
26
  ```
25
27
 
26
- Set `DATABASE_URL` through your environment, then run:
28
+ Configure `connection` and migration directory/namespace in [shared configuration](configuration.md).
29
+ Without config, migration commands retain the `DATABASE_URL` workflow. Then run:
27
30
 
28
31
  ```sh
29
32
  npx tenon status
@@ -82,8 +85,12 @@ may not be recoverable. Use the application's backup and recovery procedure when
82
85
 
83
86
  ## Directory, schema, and locking
84
87
 
85
- Defaults are `--directory migrations` and `--namespace public`. For a custom schema, use the same
86
- options consistently:
88
+ Set `migrations: { directory: 'db/migrations', namespace: 'app' }` in shared configuration to use
89
+ the same defaults for creation, status, migration, and rollback. Generation inherits that namespace
90
+ unless `generate.namespace` is set. Without configured values, defaults are directory `migrations`
91
+ and namespace `public`.
92
+
93
+ CLI flags override the config for an individual command:
87
94
 
88
95
  ```sh
89
96
  npx tenon new add_setting --directory db/migrations
@@ -95,7 +102,7 @@ npx tenon rollback --directory db/migrations --namespace app --steps 1
95
102
  The namespace selects history location, migration search path, and lock scope. During a file,
96
103
  `search_path` is `<namespace>, pg_catalog`; qualify cross-schema names explicitly. The runner creates
97
104
  the namespace when applying pending migrations. It does not configure runtime application queries.
98
- Pass the matching namespace to type generation when generating that schema.
105
+ Keep generation on the same namespace, through the shared default or an explicit override.
99
106
 
100
107
  Migration and adoption operations use an exclusive session advisory lock for this database and
101
108
  namespace. Status and generation use a shared lock. Different namespaces have independent lock
@@ -4,13 +4,13 @@
4
4
  metadata. It can catch a missing result property, an int8 result declared as number, or an unsupported
5
5
  bound input. It is optional; normal execution still trusts `sql<Row>` annotations.
6
6
 
7
- The checker reads source without importing the application, evaluating input expressions, binding
8
- values, or executing application SQL. PostgreSQL still parses/analyzes each recovered statement,
7
+ The CLI imports the selected configuration module; the checker then reads query source without
8
+ importing those modules, evaluating input expressions, binding values, or executing application SQL. PostgreSQL still parses/analyzes each recovered statement,
9
9
  which can take locks. Use a representative migrated development/test database.
10
10
 
11
11
  ## Run a check
12
12
 
13
- Set `DATABASE_URL`, then select a project, file, or one query:
13
+ Create [shared configuration](configuration.md), then select a project, file, or one query:
14
14
 
15
15
  ```sh
16
16
  npx tenon check
@@ -23,15 +23,16 @@ A one-based line selects the complete query containing it, including multiline t
23
23
  variable declaration line. A line with no query or multiple queries fails. A fragment alone is not
24
24
  a complete query target.
25
25
 
26
- The checker discovers `tsconfig.json` from the target's directory or current working directory.
27
- Use `--project` for another config or project directory; targets must belong to that project.
26
+ The CLI uses `check.project`, defaulting to `tsconfig.json` beside the shared config. Use `--project`
27
+ for another TypeScript config or project directory; targets must belong to that project. Configured
28
+ paths resolve from the shared config; CLI targets and path flags resolve from the working directory.
28
29
  It uses the bundled TypeScript 6 compiler and the project's imports, aliases, indexed access,
29
30
  `Pick`, unions, and path mappings. `strictNullChecks` is required. Invalid configuration and compiler
30
31
  errors in selected files fail the report.
31
32
 
32
33
  Match runtime role, search path, timezone, and codecs. Session/timeout flags are the same as
33
- [Describe](query-inspection.md#cli). CLI checks use default codecs; use the programmatic API for
34
- a custom registry.
34
+ [Describe](query-inspection.md#cli). CLI checks inherit the shared connection
35
+ and codec registry. Inspection-only session settings and flags override runtime startup settings.
35
36
 
36
37
  ## What gets checked
37
38
 
@@ -166,7 +167,9 @@ if (!report.ok) process.exitCode = 1;
166
167
  ```
167
168
 
168
169
  The report has `ok`, `project`, `queries`, `diagnostics`, and available inspection `context`. Options
169
- also accept `session`, `timeouts`, `codecs`, and `readTypes`. `connection` is a URI.
170
+ also accept `session`, `timeouts`, `codecs`, and `readTypes`. `connection` is a URI or pool-option
171
+ values; its `codecs` are inherited unless the explicit inspection `codecs` argument is supplied.
172
+ The programmatic API does not discover shared configuration.
170
173
 
171
174
  For a custom codec, pass the same registry as runtime queries. A text codec may declare its output:
172
175
 
@@ -193,7 +196,7 @@ registry representation. It cannot replace known metadata or claim JSON members
193
196
  decoding. Expressions resolve from the tsconfig directory. A codec declaration is trusted output
194
197
  metadata, not data validation.
195
198
 
196
- Custom configuration belongs in an application-owned checking script; the checker does not load
197
- application configuration automatically. Generated-file freshness remains a separate
198
- `db.generateTypes({ out, check: true })` operation. For behavior tests, see
199
+ The CLI loads the shared configuration for custom codecs; no checking script is required. An
200
+ application-owned script may still call the programmatic API with explicit options. Generated-file
201
+ freshness remains a separate `tenon generate --check` operation. For behavior tests, see
199
202
  [query inspection and testing](query-inspection.md).
@@ -7,10 +7,11 @@ compare TypeScript source annotations instead, use [query checking](query-checki
7
7
  ## Inspect completed SQL
8
8
 
9
9
  ```ts
10
+ // scripts/inspect-query.ts
10
11
  import { describeQuery, sql } from '@kequtech/tenon-orm';
12
+ import config from '../tenon.config.ts';
11
13
 
12
- const connection = process.env.DATABASE_URL;
13
- if (!connection) throw new Error('DATABASE_URL is required');
14
+ const connection = config.connection;
14
15
 
15
16
  const query = sql<{ id: number; total: string }>`
16
17
  SELECT ${42}::integer AS id, count(*) AS total FROM pg_catalog.pg_class
@@ -28,8 +29,8 @@ and analyzes the statement, which can take locks.
28
29
 
29
30
  ## Session and timeouts
30
31
 
31
- Inspection opens and closes its own short-lived session. `connection` must be a PostgreSQL URI;
32
- it does not inherit a runtime pool or transaction:
32
+ Inspection opens and closes its own short-lived session. `connection` accepts a PostgreSQL URI or pgclear pool-option values;
33
+ it does not reuse a runtime pool or transaction:
33
34
 
34
35
  ```ts
35
36
  const description = await describeQuery({
@@ -83,7 +84,8 @@ members remain unknown.
83
84
 
84
85
  ## Custom codecs
85
86
 
86
- Pass the runtime registry as `codecs` to report its read representations; omission uses defaults:
87
+ Programmatic inspection inherits `connection.codecs` when connection-option values are supplied.
88
+ With a URI, pass the runtime registry as `codecs`; omission uses defaults:
87
89
 
88
90
  ```ts
89
91
  import { builtin, defaultCodecs } from '@kequtech/tenon-orm';
@@ -157,11 +159,12 @@ npx tenon describe query.sql
157
159
  npx tenon describe query.sql --search-path app,public --time-zone UTC
158
160
  ```
159
161
 
160
- The CLI reads `DATABASE_URL` and prints JSON using default codecs. Session flags are `--role`,
162
+ The CLI requires [shared configuration](configuration.md) and prints JSON using its connection
163
+ and codec registry. Pass `--config path` to select a specific module. Session flags are `--role`,
161
164
  `--search-path`, and `--time-zone`; timeout flags are `--connect-timeout-ms`,
162
165
  `--statement-timeout-ms`, and `--lock-timeout-ms`. Unsupported flags, including `--namespace` and
163
166
  `--check`, reject.
164
167
 
165
168
  Exit 0 means inspection succeeded, even with unresolved findings. Input, connection, timeout, or
166
169
  PostgreSQL analysis failures exit 1. The inspected statement is never executed. Generated-file
167
- freshness uses `db.generateTypes({ out, check: true })`, a separate operation.
170
+ freshness uses `tenon generate --check`, a separate operation.
package/docs/reference.md CHANGED
@@ -23,7 +23,6 @@ The returned `Database` provides:
23
23
  | ------------------------ | ---------------------------------------------------------------------------------------- |
24
24
  | `query(query, options?)` | Execute a Tenon `SqlQuery` and apply result/count options |
25
25
  | `transaction(callback)` | Commit on callback success, roll back on an escaping error; return the callback's result |
26
- | `generateTypes(options)` | Write or check schema declarations using this instance's pool/codecs |
27
26
  | `native` | The underlying pgclear pool |
28
27
  | `close({ timeoutMs? }?)` | Disable the wrapper and close an owned pool; default grace 5,000 ms |
29
28
 
@@ -206,16 +205,17 @@ Use codes and structured fields rather than matching message text. Retain unexpe
206
205
 
207
206
  ## Generated types and checking
208
207
 
209
- ```text
210
- db.generateTypes({ out, namespace?, check?, onWarning? }): Promise<void>
211
- generateDefinitions({ connection, namespace?, onWarning? }): Promise<string>
208
+ ```sh
209
+ tenon generate
210
+ tenon generate --check
212
211
  ```
213
212
 
214
- `out` is required for file generation. Namespace defaults to `public`; `check` defaults to false.
215
- Generation inherits the database registry. Missing/stale output rejects under `check: true` without
216
- writing. See [schema types and values](schema-types.md) for file guarantees, generated shapes,
217
- value mappings, codecs, and domain validation. The standalone `tenon generate` command was removed;
218
- use an application script.
213
+ Generation uses [shared configuration](configuration.md) for its connection/codecs, output path,
214
+ and namespace. Missing/stale output rejects under `--check` without writing. See
215
+ [schema types and values](schema-types.md) for file guarantees, generated shapes, and value mappings.
216
+ `generateDefinitions({ connection, namespace?, onWarning? }): Promise<string>` returns source text
217
+ without file handling for custom tooling. Database instances expose query execution and lifecycle
218
+ methods; generation is a CLI tool.
219
219
 
220
220
  ### Application aliases
221
221
 
@@ -234,15 +234,16 @@ Generated types account for defaults, identity/computed columns, domains, and nu
234
234
 
235
235
  ## Choosing a validation tool
236
236
 
237
- Use the intended development/test schema and role. TypeScript itself needs no connection.
237
+ Use the intended development/test schema and role through shared configuration. TypeScript itself
238
+ needs no connection.
238
239
 
239
- | Tool | Question answered | Main limit |
240
- | ---------------------------------------- | ------------------------------------------------------------------------------ | --------------------------------------------------------------- |
241
- | `tsc --noEmit` | Does application code satisfy TypeScript contracts? | Does not inspect SQL/schema |
242
- | `tenon check [file.ts[:line]]` | Does recoverable SQL contradict declared input/result types? | Unsupported sites fail; inconclusive properties remain unproven |
243
- | `tenon describe query.sql` | What metadata does PostgreSQL report for finished SQL? | Does not compare annotations or bind values |
244
- | `db.generateTypes({ out, check: true })` | Does committed output match generation now? | Does not check queries or replace migration status |
245
- | Database tests | Do exercised queries produce correct rows, effects, permissions, and rollback? | Cover only tested inputs and paths |
240
+ | Tool | Question answered | Main limit |
241
+ | ------------------------------ | ------------------------------------------------------------------------------ | --------------------------------------------------------------- |
242
+ | `tsc --noEmit` | Does application code satisfy TypeScript contracts? | Does not inspect SQL/schema |
243
+ | `tenon check [file.ts[:line]]` | Does recoverable SQL contradict declared input/result types? | Unsupported sites fail; inconclusive properties remain unproven |
244
+ | `tenon describe query.sql` | What metadata does PostgreSQL report for finished SQL? | Does not compare annotations or bind values |
245
+ | `tenon generate --check` | Does committed output match generation now? | Does not check queries or replace migration status |
246
+ | Database tests | Do exercised queries produce correct rows, effects, permissions, and rollback? | Cover only tested inputs and paths |
246
247
 
247
248
  After schema changes, migrate the test database, regenerate/review declarations, and run typechecks,
248
249
  applicable source checks, and database tests. In CI, check generated output without replacing it.
@@ -255,7 +256,7 @@ take locks. Neither proves actual bound values or write effects.
255
256
  The bundled TypeScript compiler loads only through that path or the check command.
256
257
 
257
258
  Options are `{ connection, target?, project?, session?, timeouts?, codecs?, readTypes? }`.
258
- Connection is a URI. The report contains `ok`, `project`, `queries`, `diagnostics`, and available
259
+ Connection is a URI or pool-option values; connection codecs are inherited unless `codecs` is explicit. The report contains `ok`, `project`, `queries`, `diagnostics`, and available
259
260
  inspection `context`. Mismatches, unchecked sites, and no sites fail; unproven findings alone do not.
260
261
  See [query checking](query-checking.md) for selection, supported composition, and custom decoders.
261
262
 
@@ -265,7 +266,7 @@ See [query checking](query-checking.md) for selection, supported composition, an
265
266
  describeQuery({ connection, query, session?, timeouts?, codecs? }): Promise<QueryDescription>
266
267
  ```
267
268
 
268
- Connection is a URI; query is finished SQL text or `{ text, parameterTypes? }`. A `SqlQuery` fits
269
+ Connection is a URI or pool-option values; query is finished SQL text or `{ text, parameterTypes? }`. A `SqlQuery` fits
269
270
  because it has `text`; values and its row annotation are not checked. The report includes
270
271
  `parameters`, `columns`, `rowType`, `issues`, and `context`. It uses a separate session with bounded
271
272
  timeouts. See [query inspection](query-inspection.md) for fields and finding codes.
@@ -281,7 +282,8 @@ prepared statements, and dedicated notification listeners.
281
282
 
282
283
  | Symptom | Response |
283
284
  | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
284
- | `DATABASE_URL is required` | Supply the variable to CLI commands. No `.env` files are loaded automatically. Application configuration is explicit. |
285
+ | Missing shared configuration | Run `tenon init` or select an existing config with `--config`. Generation, checking, and inspection require it. |
286
+ | `DATABASE_URL is required` | Supply the variable for migration commands without config, or from your shared config module. No `.env` files are loaded automatically. |
285
287
  | `PGCLEAR_ENCODE` | Check inputs: objects/arrays need `json`/`param`; direct undefined, unsafe integers, nonfinite numbers, and invalid Dates reject. JSON still rejects bigint. |
286
288
  | `CardinalityError` | Check the expected row count and predicate. To choose one of several rows, author deterministic `ORDER BY ... LIMIT 1`. |
287
289
  | `TENON_AFFECTED_ROWS_MISMATCH` | The guarded operation rolled back. Inspect `actual` and the predicate; retain the intended bound. |
@@ -300,15 +302,23 @@ happened; review the transaction contract before adding retries.
300
302
 
301
303
  ## Command reference
302
304
 
303
- All database commands read `DATABASE_URL`. `new` and `--help` work offline. No environment files
304
- are loaded. Paths resolve from the working directory; unsupported command flags reject.
305
+ All commands accept `--config path`. `generate`, `check`, and `describe` require
306
+ [shared configuration](configuration.md) and use its connection/codecs. Migration and baseline
307
+ commands use config when present and fall back to `DATABASE_URL` only when no config is found.
308
+ `init` creates config without importing application code; `new` uses the configured migration
309
+ directory without opening a database; `--help` loads no config.
310
+ Config modules may read environment variables, but Tenon loads no `.env` files automatically.
311
+ Configured paths resolve from the config file; CLI path flags resolve from the working directory.
312
+ Unsupported command flags reject.
305
313
 
306
314
  ```text
315
+ tenon init [--config path]
307
316
  tenon new <name> [--directory migrations]
317
+ tenon generate [--out path] [--namespace schema] [--check]
308
318
  tenon migrate [--directory migrations] [--namespace public]
309
319
  tenon status [--directory migrations] [--namespace public]
310
320
  tenon rollback [--directory migrations] [--namespace public] [--steps 1]
311
- tenon baseline capture [--directory migrations] [--namespace public] [--schema name ...]
321
+ tenon baseline capture [--directory migrations] [--namespace public] [--schema name ...] [--connection native-uri]
312
322
  tenon baseline adopt [--directory migrations] [--namespace public]
313
323
  tenon check [file.ts[:line]] [--project tsconfig.json] [--json]
314
324
  [--role name] [--search-path value] [--time-zone value]
@@ -317,15 +327,17 @@ tenon describe <query.sql> [--role name] [--search-path value] [--time-zone valu
317
327
  [--connect-timeout-ms 3000] [--statement-timeout-ms 5000] [--lock-timeout-ms 1000]
318
328
  ```
319
329
 
320
- | Command | Output and behavior |
321
- | ---------------------- | ----------------------------------------------------------------- |
322
- | `new` | Paths of the new empty up/down pair; fill before applying |
323
- | `migrate` / `rollback` | Completed IDs or “nothing to do”; each file commits independently |
324
- | `status` | JSON `{ applied, pending }`; validates history |
325
- | `baseline capture` | Writes a reviewed schema-only baseline using native `pg_dump` |
326
- | `baseline adopt` | Records baseline history without executing its SQL |
327
- | `check` | Diagnostics/counts, or a structured report with `--json` |
328
- | `describe` | JSON metadata, including unresolved findings |
330
+ | Command | Output and behavior |
331
+ | ---------------------- | --------------------------------------------------------------------------------------- |
332
+ | `init` | Creates a minimal TypeScript or JavaScript config, refusing to overwrite existing files |
333
+ | `new` | Paths of the new empty up/down pair; fill before applying |
334
+ | `migrate` / `rollback` | Completed IDs or “nothing to do”; each file commits independently |
335
+ | `status` | JSON `{ applied, pending }`; validates history |
336
+ | `baseline capture` | Writes a reviewed schema-only baseline using native `pg_dump` |
337
+ | `baseline adopt` | Records baseline history without executing its SQL |
338
+ | `generate` | Writes output atomically; `--check` rejects missing/stale output without writing |
339
+ | `check` | Diagnostics/counts, or a structured report with `--json` |
340
+ | `describe` | JSON metadata, including unresolved findings |
329
341
 
330
342
  Successful commands exit 0. Invalid input or a failed operation exits 1. `check` also exits 1 for
331
343
  mismatches, unchecked sites, or no sites; unproven findings alone do not fail. `describe` can exit 0
@@ -6,33 +6,35 @@ the selected columns, joins, and expressions.
6
6
 
7
7
  ## Generate and check a file
8
8
 
9
- Use the application's configured database instance, after migrations have committed:
9
+ Configure `generate.out` in [shared configuration](configuration.md), then run after migrations
10
+ have committed:
10
11
 
11
- ```ts
12
- await db.generateTypes({ out: 'src/generated-schema.d.ts' });
13
- await db.generateTypes({ out: 'src/generated-schema.d.ts', check: true });
12
+ ```sh
13
+ npx tenon generate
14
+ npx tenon generate --check
14
15
  ```
15
16
 
16
- The first call writes declarations. The second rejects if they are missing or stale, without
17
- rewriting them. Use it in CI to verify committed output. The
18
- [getting-started script](human-guide.md#generate-types) provides a complete command-line wrapper.
17
+ The first command writes declarations. The second rejects missing or stale output without rewriting
18
+ it. Both use the configured connection and codecs. Relative configured paths resolve from the config
19
+ file; `--out` paths resolve from the working directory. The generation namespace comes from
20
+ `generate.namespace`, then `migrations.namespace`, then `public`; `--namespace` overrides it. It is
21
+ independent of runtime `search_path`.
19
22
 
20
- `namespace` defaults to `public`, independently of runtime `search_path`. Pass it explicitly for a
21
- different schema. Paths resolve from the working directory. Keep exact output unchanged and exclude
22
- it from automatic formatting.
23
+ Keep exact output unchanged and exclude it from automatic formatting. See
24
+ [getting started](human-guide.md#generate-types) for npm commands.
23
25
 
24
- Generation uses the instance's pool and codecs. It is available on `db`, outside callback
25
- transactions. It uses a repeatable-read catalog snapshot and shares the migration advisory lock;
26
- use a direct or session-pooled connection. It needs no migration files or Tenon history.
26
+ Generation runs outside callback transactions. It uses a repeatable-read catalog snapshot and
27
+ shares the migration advisory lock; use a direct or session-pooled connection. It needs no migration
28
+ files or Tenon history.
27
29
 
28
- Tenon creates parent directories and replaces the entire output file atomically. With `check: true`,
29
- it creates no directories, writes no files, and includes a bounded diff for stale output. An optional
30
- `onWarning(message)` can be synchronous or asynchronous; the default is `console.warn`. Warning
31
- handler failures reject generation before output changes. Other filesystem errors propagate.
30
+ Tenon creates parent directories and replaces the entire output file atomically. With `--check`,
31
+ it creates no directories, writes no files, and includes a bounded diff for stale output. The CLI
32
+ prints warnings to stderr. Generation failures preserve the existing file; filesystem errors propagate.
32
33
 
33
34
  For source text without file handling, use
34
35
  `generateDefinitions({ connection, namespace?, onWarning? }): Promise<string>`. Pass the configured
35
- pool or connection options to retain runtime read mappings.
36
+ pool or connection options to retain runtime read mappings. Its optional `onWarning` callback may
37
+ be synchronous or asynchronous and defaults to `console.warn`; callback failures reject generation.
36
38
 
37
39
  ## Read the generated types
38
40
 
@@ -196,10 +198,11 @@ checking consume the registry's metadata. An unidentified decoder warns and beco
196
198
  a declared representation is trusted, not runtime validation. Under a custom registry, enum output
197
199
  may remain string because a decoder can transform labels; enum write inputs retain catalog choices.
198
200
 
199
- Use the same registry for execution, generation, inspection, and source checking. Relative type-import
201
+ Place the registry in shared `connection.codecs` so runtime, CLI generation, inspection, and source
202
+ checking use it consistently. Programmatic inspection/checking inherit `connection.codecs` too. Relative type-import
200
203
  expressions resolve from the generated file for saved declarations and from the tsconfig directory
201
- for checking. Prefer a package or configured alias that resolves in both places. Tenon does not
202
- execute referenced modules. See [custom-codec checking](query-checking.md#programmatic-use-and-custom-codecs).
204
+ for checking. Prefer a package or configured alias that resolves in both places. Resolving these
205
+ type expressions does not execute their referenced modules. See [custom-codec checking](query-checking.md#programmatic-use-and-custom-codecs).
203
206
 
204
207
  Catalog queries use default result decoding on the same borrowed session, so application codecs do
205
208
  not alter Tenon's metadata inputs. Output codec choices do not select input encoders.
@@ -256,7 +259,7 @@ application's authentication and authorization checks.
256
259
 
257
260
  ## What freshness checks establish
258
261
 
259
- `check: true` compares the exact generated file with output from this database and codec registry.
262
+ `tenon generate --check` compares the exact generated file with output from this database and codec registry.
260
263
  It does not check query annotations, pending migrations, functions, privileges, or every database
261
264
  object. A driver or generator update can change output without schema drift. Review generated diffs
262
265
  after upgrades. Generated text and schema-summary formatting are not version-stable schema
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kequtech/tenon-orm",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "license": "ISC",
5
5
  "type": "module",
6
6
  "description": "A PostgreSQL ORM designed for coding agents, with explicit SQL, typed queries, and migrations",