@kequtech/tenon-orm 0.4.3 → 0.4.5
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 +22 -0
- package/README.md +10 -8
- package/dist/cli.js +12 -7
- package/dist/config/connection.d.ts +3 -0
- package/dist/config/connection.js +22 -0
- package/dist/config/init.js +2 -5
- package/dist/config/load.d.ts +2 -2
- package/dist/config/load.js +29 -36
- package/dist/config/validate.d.ts +3 -0
- package/dist/config/validate.js +28 -0
- package/dist/config.d.ts +7 -2
- package/dist/connection.d.ts +4 -1
- package/dist/connection.js +1 -1
- package/dist/database.d.ts +3 -7
- package/dist/database.js +23 -15
- package/dist/generation/render.js +5 -4
- package/dist/index.d.ts +0 -1
- package/dist/inspection/options.js +3 -13
- package/dist/inspection/types.d.ts +1 -1
- package/dist/types.d.ts +1 -1
- package/docs/agent-guide.md +2 -3
- package/docs/configuration.md +148 -83
- package/docs/connections.md +63 -32
- package/docs/human-guide.md +10 -6
- package/docs/query-inspection.md +2 -2
- package/docs/reference.md +34 -23
- package/docs/schema-types.md +31 -23
- package/package.json +2 -2
package/docs/reference.md
CHANGED
|
@@ -10,12 +10,19 @@ Requires Node.js 24+, PostgreSQL 16+, and ESM. TypeScript consumers need TypeScr
|
|
|
10
10
|
development typings. Install `@kequtech/tenon-orm`; pgclear is included as a runtime dependency.
|
|
11
11
|
|
|
12
12
|
```text
|
|
13
|
-
createTenon(
|
|
13
|
+
createTenon(config: TenonConfig): Database
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
`connection`
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
Pass one database config directly. Its `connection` holds a PostgreSQL URI, pgclear pool-option
|
|
17
|
+
values, or an application-owned pool. Its optional `onQuery` callback observes runtime queries.
|
|
18
|
+
`ConnectionOptions` aliases pgclear `PoolOptions`; a supplied pool retains application ownership.
|
|
19
|
+
Unknown config keys reject. Connection validation and pool creation wait until the first query,
|
|
20
|
+
transaction, or native-pool access. Closing an unused instance needs no credentials.
|
|
21
|
+
|
|
22
|
+
`tenon init` generates a named `main` config with plain environment reads and no eager credential
|
|
23
|
+
check. Import it and call `createTenon(main)`. Runtime does not discover files. For multiple databases,
|
|
24
|
+
export one config per database and select the matching export in the CLI with `--database`.
|
|
25
|
+
See [shared configuration](configuration.md) for the complete setup.
|
|
19
26
|
|
|
20
27
|
The returned `Database` provides:
|
|
21
28
|
|
|
@@ -37,7 +44,7 @@ handling, timeout bounds, and lifecycle examples. Runtime `search_path` is indep
|
|
|
37
44
|
|
|
38
45
|
### Driver updates
|
|
39
46
|
|
|
40
|
-
The dependency range is `@kequtech/pgclear: ^0.3.
|
|
47
|
+
The dependency range is `@kequtech/pgclear: ^0.3.3`. Compatible patches may be updated independently;
|
|
41
48
|
see [driver updates](connections.md#update-the-driver). Tenon re-exports `builtin`, `json`, `param`,
|
|
42
49
|
`defaultCodecs`, and `createTemporalCodecs`, with the driver's `Codec`, `CodecRegistry`, `Parameter`,
|
|
43
50
|
`PgArray`, `TemporalConstructors`, and `TemporalInput` types.
|
|
@@ -280,21 +287,23 @@ prepared statements, and dedicated notification listeners.
|
|
|
280
287
|
|
|
281
288
|
## Troubleshooting
|
|
282
289
|
|
|
283
|
-
| Symptom
|
|
284
|
-
|
|
|
285
|
-
| Missing shared configuration
|
|
286
|
-
|
|
|
287
|
-
|
|
|
288
|
-
| `
|
|
289
|
-
| `
|
|
290
|
-
| `
|
|
291
|
-
|
|
|
292
|
-
|
|
|
293
|
-
|
|
|
294
|
-
|
|
|
295
|
-
|
|
|
296
|
-
|
|
|
297
|
-
|
|
|
290
|
+
| Symptom | Response |
|
|
291
|
+
| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
292
|
+
| Missing shared configuration | Run `tenon init` or select an existing config with `--config`. Generation, checking, and inspection require it. |
|
|
293
|
+
| Multiple databases or unknown database export | Select a named config with `--database name`. Use `--config path` when it belongs to another file. |
|
|
294
|
+
| Missing or empty config connection | Set the environment variable read by that database's config before using it. Imports alone need no credentials. |
|
|
295
|
+
| `DATABASE_URL is required` | Supply the variable for migration commands without config. Tenon does not load `.env` files. |
|
|
296
|
+
| `PGCLEAR_ENCODE` | Check inputs: objects/arrays need `json`/`param`; direct undefined, unsafe integers, nonfinite numbers, and invalid Dates reject. JSON still rejects bigint. |
|
|
297
|
+
| `CardinalityError` | Check the expected row count and predicate. To choose one of several rows, author deterministic `ORDER BY ... LIMIT 1`. |
|
|
298
|
+
| `TENON_AFFECTED_ROWS_MISMATCH` | The guarded operation rolled back. Inspect `actual` and the predicate; retain the intended bound. |
|
|
299
|
+
| `TENON_AFFECTED_ROWS_UNSUPPORTED` | The final command lacks a supported write count. Use guards on INSERT/UPDATE/DELETE/MERGE; result modes check returned rows. |
|
|
300
|
+
| Empty assignments | All selected fields were missing/undefined. Skip the update or branch to an expression-only statement. |
|
|
301
|
+
| Duplicate result columns | Alias columns uniquely, especially in joins. The driver rejects duplicate object keys. |
|
|
302
|
+
| SQLSTATE `42P18` / `42P08` during inspection | Add the intended parameter cast or Describe OID hints. Inspection binds no values. |
|
|
303
|
+
| Checker reports `unchecked` | Follow the diagnostic. Runtime fragments and optional patches can execute correctly yet remain unsupported by source recovery. |
|
|
304
|
+
| Missing/stale generated output | Check schema, namespace, registry, driver version, and path. Regenerate, review, and commit intended output. |
|
|
305
|
+
| Migration history conflict | Restore original applied files. Add new changes in a forward migration. Checksums include down SQL too. |
|
|
306
|
+
| Tooling lock wait | Check concurrent migration/DDL work, use direct or session pooling, and configure server timeouts. |
|
|
298
307
|
|
|
299
308
|
After a guarded query rejects, savepoint cleanup has finished. An unguarded server error normally
|
|
300
309
|
aborts a transaction. A timeout or lost connection does not itself establish whether a commit
|
|
@@ -302,12 +311,14 @@ happened; review the transaction contract before adding retries.
|
|
|
302
311
|
|
|
303
312
|
## Command reference
|
|
304
313
|
|
|
305
|
-
All commands accept `--config path`.
|
|
314
|
+
All commands accept `--config path`. Commands using a database config also accept `--database name`
|
|
315
|
+
to select its export. A file with one config is selected automatically; multiple configs require an
|
|
316
|
+
explicit selection. `generate`, `check`, and `describe` require
|
|
306
317
|
[shared configuration](configuration.md) and use its connection/codecs. Migration and baseline
|
|
307
318
|
commands use config when present and fall back to `DATABASE_URL` only when no config is found.
|
|
308
319
|
`init` creates config without importing application code; `new` uses the configured migration
|
|
309
|
-
directory without opening a database; `--help` loads no config.
|
|
310
|
-
|
|
320
|
+
directory without opening a database; `--help` loads no config. Config modules may read environment variables, but Tenon loads no `.env`
|
|
321
|
+
files automatically.
|
|
311
322
|
Configured paths resolve from the config file; CLI path flags resolve from the working directory.
|
|
312
323
|
Unsupported command flags reject.
|
|
313
324
|
|
package/docs/schema-types.md
CHANGED
|
@@ -131,22 +131,22 @@ well typed; PostgreSQL still enforces constraints.
|
|
|
131
131
|
These are the default driver representations. SQL NULL is `null`; nullable generated columns add
|
|
132
132
|
null to their type. Input encoding and output decoding are separate choices.
|
|
133
133
|
|
|
134
|
-
| PostgreSQL value | Default read
|
|
135
|
-
| ----------------------------------------------------------- |
|
|
136
|
-
| smallint, integer, serial, oid | `number`
|
|
137
|
-
| bigint, bigserial, `count(*)` | Exact `string`
|
|
138
|
-
| numeric/decimal | `string`
|
|
139
|
-
| real, double precision | `number`
|
|
140
|
-
| boolean | `boolean`
|
|
141
|
-
| text, UUID, other textual types | `string`
|
|
142
|
-
| enum | Catalog label union
|
|
143
|
-
| date, timestamp, timestamptz | `string`
|
|
144
|
-
| time, interval | `string`
|
|
145
|
-
| timetz | `string`
|
|
146
|
-
| json/jsonb | `unknown`
|
|
147
|
-
| bytea | `Uint8Array`
|
|
148
|
-
| Supported built-in arrays | Recursive readonly `PgArray<T>`
|
|
149
|
-
| Unrecognized types and dynamic enum/domain/extension arrays | Wire-text `string`
|
|
134
|
+
| PostgreSQL value | Default read | Plain write input |
|
|
135
|
+
| ----------------------------------------------------------- | ---------------------------------------------------- | ------------------------------------------------------------- |
|
|
136
|
+
| smallint, integer, serial, oid | `number` | `number` |
|
|
137
|
+
| bigint, bigserial, `count(*)` | Exact `string` | Exact string or bigint |
|
|
138
|
+
| numeric/decimal | `string` | String or bigint |
|
|
139
|
+
| real, double precision | `number` | Finite number |
|
|
140
|
+
| boolean | `boolean` | Boolean |
|
|
141
|
+
| text, UUID, other textual types | `string` | String |
|
|
142
|
+
| enum | Catalog label union when its decoder remains default | Label union |
|
|
143
|
+
| date, timestamp, timestamptz | `string` | String, Date, or supported Temporal value |
|
|
144
|
+
| time, interval | `string` | String or supported Temporal value |
|
|
145
|
+
| timetz | `string` | String |
|
|
146
|
+
| json/jsonb | `unknown` | Encoded JSON string; use `json(value)` for a parameter |
|
|
147
|
+
| bytea | `Uint8Array` | Uint8Array |
|
|
148
|
+
| Supported built-in arrays | Recursive readonly `PgArray<T>` | Encoded PostgreSQL array text; use `param` for an array value |
|
|
149
|
+
| Unrecognized types and dynamic enum/domain/extension arrays | Wire-text `string` | Encoded string or explicit parameter |
|
|
150
150
|
|
|
151
151
|
Generated inputs conservatively describe column-compatible representations; an explicit `Parameter`
|
|
152
152
|
is accepted for every writable column. PostgreSQL checks ranges and text formats. Plain undefined,
|
|
@@ -163,17 +163,22 @@ both become null. For raw JSON text or Date/bigint outputs, configure codecs.
|
|
|
163
163
|
|
|
164
164
|
## Custom codecs
|
|
165
165
|
|
|
166
|
-
Configure the registry
|
|
166
|
+
Configure the registry in `tenon.config.ts` so runtime queries and generated declarations use the
|
|
167
|
+
same representations:
|
|
167
168
|
|
|
168
169
|
```ts
|
|
169
|
-
import { builtin,
|
|
170
|
+
import { builtin, defaultCodecs, type TenonConfig } from '@kequtech/tenon-orm';
|
|
170
171
|
|
|
171
172
|
const codecs = defaultCodecs.with(builtin.int8BigInt).with(builtin.timestamptzDate);
|
|
172
|
-
const
|
|
173
|
+
export const main = {
|
|
174
|
+
connection: { connectionString: process.env.DATABASE_URL, codecs },
|
|
175
|
+
generate: { out: 'src/generated-schema.d.ts' },
|
|
176
|
+
} satisfies TenonConfig;
|
|
173
177
|
```
|
|
174
178
|
|
|
175
|
-
Int8 now reads as bigint, and timestamptz reads as a millisecond-precision Date.
|
|
176
|
-
|
|
179
|
+
Int8 now reads as bigint, and timestamptz reads as a millisecond-precision Date. Run `tenon generate`
|
|
180
|
+
with this config to update declarations. Scalar overrides affect derived built-in arrays; explicit
|
|
181
|
+
array overrides win. Date and
|
|
177
182
|
Temporal output codecs reject infinity and values outside their supported ranges.
|
|
178
183
|
|
|
179
184
|
For Temporal, import `createTemporalCodecs` from Tenon and supply a native or compatible polyfill
|
|
@@ -195,8 +200,11 @@ configuration needs the corresponding Temporal library declarations.
|
|
|
195
200
|
|
|
196
201
|
A custom text codec can declare `text.typescript` to describe its non-NULL output. Generation and
|
|
197
202
|
checking consume the registry's metadata. An unidentified decoder warns and becomes `unknown`;
|
|
198
|
-
a declared representation is trusted, not runtime validation.
|
|
199
|
-
|
|
203
|
+
a declared representation is trusted, not runtime validation. Generated enum rows retain catalog label
|
|
204
|
+
unions when that enum's decoder remains default, including when unrelated Date, bigint, or other
|
|
205
|
+
codecs change. A custom enum decoder uses its own declared output type, or `unknown` with a warning
|
|
206
|
+
when unidentified; declaring `string` does not establish that it preserves catalog labels. Enum write
|
|
207
|
+
inputs retain catalog choices regardless of the output decoder.
|
|
200
208
|
|
|
201
209
|
Place the registry in shared `connection.codecs` so runtime, CLI generation, inspection, and source
|
|
202
210
|
checking use it consistently. Programmatic inspection/checking inherit `connection.codecs` too. Relative type-import
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kequtech/tenon-orm",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.5",
|
|
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",
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"printWidth": 100
|
|
72
72
|
},
|
|
73
73
|
"dependencies": {
|
|
74
|
-
"@kequtech/pgclear": "^0.3.
|
|
74
|
+
"@kequtech/pgclear": "^0.3.3",
|
|
75
75
|
"typescript": "~6.0.2"
|
|
76
76
|
}
|
|
77
77
|
}
|