@kequtech/tenon-orm 0.2.2 → 0.3.0

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.
Files changed (51) hide show
  1. package/CHANGELOG.md +43 -42
  2. package/README.md +4 -4
  3. package/dist/affected-rows.js +6 -6
  4. package/dist/baseline.js +4 -4
  5. package/dist/client.js +1 -1
  6. package/dist/connection.d.ts +15 -22
  7. package/dist/connection.js +122 -25
  8. package/dist/database.js +10 -17
  9. package/dist/driver/types.d.ts +1 -1
  10. package/dist/driver/types.js +11 -11
  11. package/dist/generate.js +7 -7
  12. package/dist/generation/catalog.d.ts +2 -2
  13. package/dist/generation/catalog.js +4 -4
  14. package/dist/generation/schema-summary.d.ts +3 -3
  15. package/dist/generation/schema-summary.js +11 -11
  16. package/dist/generation/table-types.js +1 -1
  17. package/dist/index.d.ts +1 -2
  18. package/dist/inspection/catalog.d.ts +4 -3
  19. package/dist/inspection/catalog.js +13 -10
  20. package/dist/inspection/connection.d.ts +2 -2
  21. package/dist/inspection/connection.js +22 -22
  22. package/dist/inspection/protocol.d.ts +7 -0
  23. package/dist/inspection/protocol.js +45 -0
  24. package/dist/inspection/result.d.ts +1 -1
  25. package/dist/inspection/result.js +6 -6
  26. package/dist/inspection/types.d.ts +2 -2
  27. package/dist/migrations/connection.d.ts +3 -2
  28. package/dist/migrations/connection.js +18 -20
  29. package/dist/migrations/history.d.ts +4 -4
  30. package/dist/migrations/history.js +5 -5
  31. package/dist/migrations.js +7 -7
  32. package/dist/query-options.js +4 -4
  33. package/dist/query.js +2 -2
  34. package/dist/transaction.d.ts +2 -2
  35. package/dist/transaction.js +19 -14
  36. package/dist/types.d.ts +2 -2
  37. package/docs/adoption-guide.md +30 -27
  38. package/docs/agent-guide.md +53 -48
  39. package/docs/human-guide.md +21 -20
  40. package/docs/mutations.md +13 -10
  41. package/docs/query-inspection.md +12 -14
  42. package/docs/reference.md +130 -132
  43. package/package.json +3 -2
  44. package/dist/driver/array.d.ts +0 -5
  45. package/dist/driver/array.js +0 -70
  46. package/dist/driver/lifecycle.d.ts +0 -15
  47. package/dist/driver/lifecycle.js +0 -57
  48. package/dist/driver/listener.d.ts +0 -3
  49. package/dist/driver/listener.js +0 -63
  50. package/dist/driver/session.d.ts +0 -8
  51. package/dist/driver/session.js +0 -92
@@ -1,63 +0,0 @@
1
- import { createConnection } from 'node:net';
2
- function closedError() {
3
- return Object.assign(new Error('The owned PostgreSQL listener is closed.'), {
4
- code: 'CONNECTION_ENDED',
5
- });
6
- }
7
- /** Prevent an owned LISTEN client's queued reconnect from reopening it after shutdown. */
8
- export function guardListenerShutdown(sql) {
9
- const options = sql.options;
10
- const listen = sql.listen;
11
- const sockets = new Set();
12
- let closed = false;
13
- let hostIndex = 0;
14
- function track(socket) {
15
- // TLS adoption removes raw socket listeners; prune those closed transports on reconnect.
16
- for (const previous of sockets)
17
- if (previous.destroyed)
18
- sockets.delete(previous);
19
- sockets.add(socket);
20
- socket.once('close', () => sockets.delete(socket));
21
- if (closed) {
22
- socket.destroy();
23
- throw closedError();
24
- }
25
- return socket;
26
- }
27
- sql.listen = (...args) => {
28
- if (closed)
29
- return Promise.reject(closedError());
30
- const previous = options.socket;
31
- // Postgres.js synchronously clones these options for its dedicated max:1 listener.
32
- // Restore immediately so ordinary queries retain their native transport configuration.
33
- options.socket = (settings) => {
34
- if (closed)
35
- throw closedError();
36
- if (previous)
37
- return Promise.resolve(previous(settings)).then(track);
38
- const host = settings.host[hostIndex];
39
- const port = settings.port[hostIndex];
40
- const socket = createConnection(settings.path ? { path: settings.path } : { host, port });
41
- if (!settings.path) {
42
- hostIndex = (hostIndex + 1) % settings.port.length;
43
- // The driver's TLS negotiation uses this metadata for SNI and verification.
44
- Object.assign(socket, { host, port });
45
- }
46
- // Node buffers startup writes while connecting; the driver retains its connect timeout,
47
- // authentication, TLS negotiation and reconnect handling.
48
- return track(socket);
49
- };
50
- try {
51
- return listen(...args);
52
- }
53
- finally {
54
- options.socket = previous;
55
- }
56
- };
57
- return () => {
58
- closed = true;
59
- for (const socket of sockets)
60
- socket.destroy();
61
- sockets.clear();
62
- };
63
- }
@@ -1,8 +0,0 @@
1
- import type postgres from 'postgres';
2
- import type { SqlConnection } from '../connection.js';
3
- /** Pin a healthy session for transactions and advisory locks, with explicit failure cleanup. */
4
- export declare function reserveConnection(sql: postgres.Sql, initial?: 'SELECT 1' | 'BEGIN'): Promise<{
5
- sql: SqlConnection;
6
- check: () => void;
7
- release(discard?: boolean): Promise<void>;
8
- }>;
@@ -1,92 +0,0 @@
1
- import { prepareArrays } from './array.js';
2
- import { observeConnections } from './lifecycle.js';
3
- let nextLease = 0;
4
- /** Pin a healthy session for transactions and advisory locks, with explicit failure cleanup. */
5
- export async function reserveConnection(sql, initial = 'SELECT 1') {
6
- await prepareArrays(sql);
7
- const state = observeConnections(sql);
8
- // Warm a connection before reserve(): 3.4.9 can strand a cold reserve after reconnect.
9
- await sql `SELECT 1`;
10
- let abandoned = false;
11
- let rejectAcquisition;
12
- const closed = new Promise((_, reject) => {
13
- rejectAcquisition = reject;
14
- });
15
- state.acquiring.add(rejectAcquisition);
16
- const pending = sql.reserve();
17
- void pending.then((client) => {
18
- if (abandoned)
19
- client.release();
20
- }, () => { });
21
- let client;
22
- try {
23
- client = await Promise.race([pending, closed]);
24
- }
25
- catch (error) {
26
- abandoned = true;
27
- throw error;
28
- }
29
- finally {
30
- state.acquiring.delete(rejectAcquisition);
31
- }
32
- let rejectClosed;
33
- const closedSession = new Promise((_, reject) => {
34
- rejectClosed = reject;
35
- });
36
- void closedSession.catch(() => { });
37
- const watch = {
38
- closed: closedSession,
39
- reject: rejectClosed,
40
- check() {
41
- if (watch.failure)
42
- throw watch.failure;
43
- },
44
- };
45
- const safe = {
46
- async unsafe(text, input = [], options) {
47
- watch.check();
48
- // Driver dispatch runs in the next microtask, before another socket event.
49
- const query = client.unsafe(text, input, options).execute();
50
- return Promise.race([query, watch.closed]);
51
- },
52
- array: client.array,
53
- typed: client.typed,
54
- };
55
- const connection = {
56
- sql: safe,
57
- check: watch.check,
58
- async release(discard = false) {
59
- for (const [id, active] of state.active)
60
- if (active === watch)
61
- state.active.delete(id);
62
- if (watch.failure)
63
- return; // The driver already removed the closed session.
64
- if (discard) {
65
- // Failed recovery must not return an unknown transaction/lock state to the pool.
66
- try {
67
- await client.unsafe('SELECT pg_terminate_backend(pg_backend_pid())').execute();
68
- }
69
- catch {
70
- /* The backend closes itself. */
71
- }
72
- return;
73
- }
74
- client.release();
75
- },
76
- };
77
- // Capture the connection on BEGIN itself when opening a transaction.
78
- const marker = `${initial} /* tenon_session_${++nextLease} */`;
79
- const stopCapture = state.capture(marker, watch);
80
- try {
81
- await safe.unsafe(marker, [], { simple: false, prepare: false });
82
- watch.check();
83
- return connection;
84
- }
85
- catch (error) {
86
- await connection.release(true);
87
- throw error;
88
- }
89
- finally {
90
- stopCapture();
91
- }
92
- }