@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.
- package/CHANGELOG.md +5 -0
- package/README.md +10 -1
- package/dist/check.js +4 -2
- package/dist/cli.js +101 -28
- package/dist/config/init.d.ts +2 -0
- package/dist/config/init.js +34 -0
- package/dist/config/load.d.ts +7 -0
- package/dist/config/load.js +159 -0
- package/dist/config.d.ts +25 -0
- package/dist/config.js +1 -0
- package/dist/connection.d.ts +5 -0
- package/dist/database.js +0 -5
- package/dist/describe.js +3 -1
- package/dist/generate.d.ts +0 -11
- package/dist/generate.js +1 -26
- package/dist/generation/output.js +2 -2
- package/dist/index.d.ts +3 -2
- package/dist/inspection/cli.d.ts +3 -4
- package/dist/inspection/cli.js +3 -13
- package/dist/inspection/connection.js +23 -19
- package/dist/inspection/options.d.ts +5 -7
- package/dist/inspection/options.js +49 -22
- package/dist/inspection/types.d.ts +3 -2
- package/dist/migrations/history.d.ts +1 -1
- package/dist/migrations/history.js +3 -2
- package/dist/types.d.ts +0 -3
- package/dist/validation.d.ts +2 -0
- package/dist/validation.js +6 -0
- package/docs/adoption-guide.md +9 -3
- package/docs/agent-guide.md +13 -15
- package/docs/configuration.md +146 -0
- package/docs/connections.md +7 -5
- package/docs/human-guide.md +40 -25
- package/docs/migrations.md +13 -6
- package/docs/query-checking.md +14 -11
- package/docs/query-inspection.md +10 -7
- package/docs/reference.md +44 -32
- package/docs/schema-types.md +25 -22
- package/package.json +1 -1
package/docs/human-guide.md
CHANGED
|
@@ -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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
} finally {
|
|
180
|
-
await db.close();
|
|
181
|
-
}
|
|
195
|
+
```sh
|
|
196
|
+
npx tenon generate
|
|
197
|
+
npx tenon generate --check
|
|
182
198
|
```
|
|
183
199
|
|
|
184
|
-
|
|
185
|
-
`
|
|
186
|
-
|
|
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
|
|
204
|
+
Add these commands to your existing `package.json`:
|
|
191
205
|
|
|
192
206
|
```json
|
|
193
207
|
{
|
|
194
208
|
"scripts": {
|
|
195
|
-
"db:generate": "
|
|
196
|
-
"db:check-types": "
|
|
197
|
-
"db:
|
|
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
|
```
|
package/docs/migrations.md
CHANGED
|
@@ -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`
|
|
14
|
-
directory
|
|
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
|
-
|
|
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
|
-
|
|
86
|
-
|
|
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
|
-
|
|
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
|
package/docs/query-checking.md
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
|
27
|
-
|
|
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
|
|
34
|
-
|
|
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
|
-
|
|
197
|
-
application
|
|
198
|
-
|
|
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).
|
package/docs/query-inspection.md
CHANGED
|
@@ -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 =
|
|
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`
|
|
32
|
-
it does not
|
|
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
|
-
|
|
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
|
|
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 `
|
|
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
|
-
```
|
|
210
|
-
|
|
211
|
-
|
|
208
|
+
```sh
|
|
209
|
+
tenon generate
|
|
210
|
+
tenon generate --check
|
|
212
211
|
```
|
|
213
212
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
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
|
|
237
|
+
Use the intended development/test schema and role through shared configuration. TypeScript itself
|
|
238
|
+
needs no connection.
|
|
238
239
|
|
|
239
|
-
| Tool
|
|
240
|
-
|
|
|
241
|
-
| `tsc --noEmit`
|
|
242
|
-
| `tenon check [file.ts[:line]]`
|
|
243
|
-
| `tenon describe query.sql`
|
|
244
|
-
| `
|
|
245
|
-
| Database tests
|
|
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
|
-
|
|
|
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
|
|
304
|
-
|
|
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
|
-
| `
|
|
323
|
-
| `
|
|
324
|
-
| `
|
|
325
|
-
| `
|
|
326
|
-
| `baseline
|
|
327
|
-
| `
|
|
328
|
-
| `
|
|
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
|
package/docs/schema-types.md
CHANGED
|
@@ -6,33 +6,35 @@ the selected columns, joins, and expressions.
|
|
|
6
6
|
|
|
7
7
|
## Generate and check a file
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Configure `generate.out` in [shared configuration](configuration.md), then run after migrations
|
|
10
|
+
have committed:
|
|
10
11
|
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
```sh
|
|
13
|
+
npx tenon generate
|
|
14
|
+
npx tenon generate --check
|
|
14
15
|
```
|
|
15
16
|
|
|
16
|
-
The first
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
21
|
-
|
|
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
|
|
25
|
-
|
|
26
|
-
|
|
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
|
|
29
|
-
it creates no directories, writes no files, and includes a bounded diff for stale output.
|
|
30
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
|
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
|