okmodel 0.1.0 → 0.2.1

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 (181) hide show
  1. package/README.md +237 -19
  2. package/dist/adapters/capabilities.d.ts +34 -0
  3. package/dist/adapters/pg/bunsql-extra.d.ts +17 -0
  4. package/dist/adapters/pg/bunsql.d.ts +60 -0
  5. package/dist/adapters/pg/call.d.ts +2 -12
  6. package/dist/adapters/pg/nodepostgres-extra.d.ts +18 -0
  7. package/dist/adapters/pg/nodepostgres.d.ts +57 -0
  8. package/dist/adapters/pg/postgres-extra.d.ts +50 -1
  9. package/dist/adapters/pg/postgresjs.d.ts +0 -4
  10. package/dist/adapters/pg/session.d.ts +94 -0
  11. package/dist/adapters/pg/watch.d.ts +18 -0
  12. package/dist/contracts/catalog/object.d.ts +1 -0
  13. package/dist/contracts/catalog/types.d.ts +15 -8
  14. package/dist/contracts/connection.d.ts +13 -0
  15. package/dist/contracts/driver.d.ts +18 -5
  16. package/dist/contracts/error.d.ts +17 -1
  17. package/dist/contracts/generator.d.ts +63 -0
  18. package/dist/contracts/index.d.ts +2 -2
  19. package/dist/contracts/index.js +1 -1
  20. package/dist/contracts/internal.js +11 -9
  21. package/dist/contracts/location.d.ts +24 -0
  22. package/dist/contracts/rows.d.ts +15 -0
  23. package/dist/dialects/pg/archive-bind.d.ts +22 -0
  24. package/dist/dialects/pg/column.d.ts +126 -9
  25. package/dist/dialects/pg/compile.d.ts +1 -0
  26. package/dist/dialects/pg/custom.d.ts +6 -0
  27. package/dist/dialects/pg/filter-parse.d.ts +19 -0
  28. package/dist/dialects/pg/filters.d.ts +19 -0
  29. package/dist/dialects/pg/index.d.ts +11 -2
  30. package/dist/dialects/pg/index.js +159 -1063
  31. package/dist/dialects/pg/keys.d.ts +19 -3
  32. package/dist/dialects/pg/model.d.ts +223 -2
  33. package/dist/dialects/pg/operator-fit.d.ts +86 -0
  34. package/dist/dialects/pg/operators.d.ts +39 -1
  35. package/dist/dialects/pg/ops/arr-append.d.ts +9 -0
  36. package/dist/dialects/pg/ops/arr-ns.d.ts +7 -0
  37. package/dist/dialects/pg/ops/arr-remove.d.ts +9 -0
  38. package/dist/dialects/pg/ops/containedBy.d.ts +9 -0
  39. package/dist/dialects/pg/ops/contains.d.ts +8 -4
  40. package/dist/dialects/pg/ops/hasAnyKey.d.ts +8 -0
  41. package/dist/dialects/pg/ops/hasKey.d.ts +8 -0
  42. package/dist/dialects/pg/ops/json-ns.d.ts +6 -0
  43. package/dist/dialects/pg/ops/json-set.d.ts +12 -0
  44. package/dist/dialects/pg/ops/matches.d.ts +16 -0
  45. package/dist/dialects/pg/ops/overlaps.d.ts +9 -0
  46. package/dist/dialects/pg/ops/path.d.ts +13 -0
  47. package/dist/dialects/pg/preset.d.ts +76 -0
  48. package/dist/dialects/pg/relations.d.ts +59 -2
  49. package/dist/dialects/pg/schema.d.ts +109 -5
  50. package/dist/dialects/pg/table.d.ts +130 -11
  51. package/dist/dialects/pg/temporal.d.ts +9 -7
  52. package/dist/dialects/pg/tenancy.d.ts +94 -0
  53. package/dist/dialects/pg/through.d.ts +21 -0
  54. package/dist/dialects/pg/trait.d.ts +141 -0
  55. package/dist/dialects/pg/where.d.ts +37 -0
  56. package/dist/runtime/aggregate.d.ts +25 -0
  57. package/dist/runtime/archive-handle.d.ts +18 -0
  58. package/dist/runtime/archive-rules.d.ts +12 -0
  59. package/dist/runtime/archive.d.ts +73 -0
  60. package/dist/runtime/batch.d.ts +20 -0
  61. package/dist/runtime/client.d.ts +114 -5
  62. package/dist/runtime/conflict.d.ts +2 -1
  63. package/dist/runtime/exposure.d.ts +27 -0
  64. package/dist/runtime/hookm.d.ts +39 -0
  65. package/dist/runtime/ids/index.d.ts +11 -0
  66. package/dist/runtime/ids/index.js +193 -0
  67. package/dist/runtime/ids/okid-extended.d.ts +19 -0
  68. package/dist/runtime/ids/okid-generator.d.ts +21 -0
  69. package/dist/runtime/ids/okid-shared.d.ts +89 -0
  70. package/dist/runtime/ids/okid.d.ts +24 -0
  71. package/dist/runtime/ids/uuid.d.ts +21 -0
  72. package/dist/runtime/lock.d.ts +22 -0
  73. package/dist/runtime/operator-sql.d.ts +8 -0
  74. package/dist/runtime/page.d.ts +25 -0
  75. package/dist/runtime/pg/bun.d.ts +30 -0
  76. package/dist/runtime/pg/bun.js +52 -0
  77. package/dist/runtime/pg/pg.d.ts +29 -0
  78. package/dist/runtime/pg/pg.js +52 -0
  79. package/dist/runtime/pg/pglite.js +16 -17
  80. package/dist/runtime/pg/postgresjs.js +14 -24
  81. package/dist/runtime/plan.d.ts +146 -7
  82. package/dist/runtime/preset-stack.d.ts +17 -0
  83. package/dist/runtime/presets.d.ts +48 -0
  84. package/dist/runtime/read-stream.d.ts +26 -0
  85. package/dist/runtime/safety/index.d.ts +159 -0
  86. package/dist/runtime/safety/index.js +294 -0
  87. package/dist/runtime/safety-hook.d.ts +42 -0
  88. package/dist/runtime/server-check.d.ts +34 -0
  89. package/dist/runtime/tenancy/index.d.ts +37 -0
  90. package/dist/runtime/tenancy/index.js +365 -0
  91. package/dist/runtime/trait-read.d.ts +30 -0
  92. package/dist/runtime/traits/index.d.ts +128 -0
  93. package/dist/runtime/traits/index.js +509 -0
  94. package/dist/runtime/transaction.d.ts +19 -0
  95. package/dist/runtime/tx.d.ts +22 -7
  96. package/dist/runtime/types.d.ts +390 -25
  97. package/dist/runtime/validate/bind.d.ts +11 -0
  98. package/dist/runtime/validate/closed.d.ts +16 -0
  99. package/dist/runtime/validate/engine.d.ts +41 -0
  100. package/dist/runtime/validate/hook.d.ts +17 -0
  101. package/dist/runtime/validate/index.d.ts +21 -0
  102. package/dist/runtime/validate/index.js +175 -0
  103. package/dist/runtime/validate/load.d.ts +13 -0
  104. package/dist/runtime/validate/places.d.ts +41 -0
  105. package/dist/runtime/validate/rules.d.ts +108 -0
  106. package/dist/runtime/validate/surface.d.ts +102 -0
  107. package/dist/runtime/write.d.ts +30 -5
  108. package/dist/shared/{fgqgsb5z.js → 0qkxbm1f.js} +2 -2
  109. package/dist/shared/0v1g424p.js +26 -0
  110. package/dist/shared/10tjenmd.js +210 -0
  111. package/dist/shared/{tb4ze1tr.js → 1dp5knt7.js} +95 -10
  112. package/dist/shared/38crxbgn.js +229 -0
  113. package/dist/shared/3a5ne750.js +158 -0
  114. package/dist/shared/4b9da9d7.js +138 -0
  115. package/dist/shared/4e4c6vq2.js +62 -0
  116. package/dist/shared/{ckb1p0a4.js → 4jzzghr6.js} +416 -83
  117. package/dist/shared/{ycwz42az.js → 52szzakm.js} +6 -26
  118. package/dist/shared/{kynx7vbm.js → 5z4q2zda.js} +604 -21
  119. package/dist/shared/672t5vym.js +12 -0
  120. package/dist/shared/7m88x3e9.js +45 -0
  121. package/dist/shared/7mht49yd.js +1091 -0
  122. package/dist/shared/{mtkwv8wx.js → 7p2wbz7f.js} +1 -1
  123. package/dist/shared/83eaefwr.js +10 -0
  124. package/dist/shared/96ps4g1z.js +32 -0
  125. package/dist/shared/97g2jnrw.js +76 -0
  126. package/dist/shared/{xy79j5hq.js → 9k6vetvf.js} +25 -36
  127. package/dist/shared/{w8samvk1.js → a1gdp7j9.js} +1 -1
  128. package/dist/shared/a5sxz52y.js +13 -0
  129. package/dist/shared/{dynq16vb.js → b066g80h.js} +8 -6
  130. package/dist/shared/cstgkzdx.js +154 -0
  131. package/dist/shared/{ax16zpvm.js → d04j53v8.js} +6 -5
  132. package/dist/shared/{y9m15dfv.js → d2whjz4k.js} +15 -9
  133. package/dist/shared/dd4f8mnx.js +307 -0
  134. package/dist/shared/e6wg00wd.js +164 -0
  135. package/dist/shared/e7a268fy.js +195 -0
  136. package/dist/shared/{vkm3q4x1.js → eaxwrgby.js} +4 -3
  137. package/dist/shared/{7ck0dtry.js → ecdzej21.js} +160 -81
  138. package/dist/shared/{px90pf9p.js → edwqqryd.js} +21 -16
  139. package/dist/shared/{g2v6gnc8.js → eqmtn1bj.js} +57 -5
  140. package/dist/shared/g1b5zzj9.js +75 -0
  141. package/dist/shared/g9f0zqce.js +376 -0
  142. package/dist/shared/ge03bfca.js +64 -0
  143. package/dist/shared/{79ggp945.js → jns2wx4t.js} +55 -12
  144. package/dist/shared/k3ted12y.js +33 -0
  145. package/dist/shared/k7dwkhvq.js +31 -0
  146. package/dist/shared/{hd293j9g.js → kyxb62mc.js} +14 -2
  147. package/dist/shared/m9tv7xn7.js +404 -0
  148. package/dist/shared/mrq77sgw.js +55 -0
  149. package/dist/shared/mxmcdsh5.js +450 -0
  150. package/dist/shared/n442h54c.js +14 -0
  151. package/dist/shared/n47rd821.js +442 -0
  152. package/dist/shared/n4jqhpqz.js +27 -0
  153. package/dist/shared/{mkjmqjv4.js → nfzc5z0w.js} +2 -104
  154. package/dist/shared/nsva2a6b.js +42 -0
  155. package/dist/shared/ps43134h.js +69 -0
  156. package/dist/shared/{8b04d28c.js → py3nh7jy.js} +2 -2
  157. package/dist/shared/qa5dsc7z.js +86 -0
  158. package/dist/shared/{g5fhqmwe.js → qxa0yb9j.js} +6 -4
  159. package/dist/shared/r6nwkxnt.js +86 -0
  160. package/dist/shared/{4j72449d.js → rtnaqre0.js} +3 -3
  161. package/dist/shared/rwmrejjz.js +26 -0
  162. package/dist/shared/{zhc5vmgf.js → s6gqfn5j.js} +2 -2
  163. package/dist/shared/sacqha1y.js +70 -0
  164. package/dist/shared/{qk3hxfja.js → sfh4pk75.js} +5 -5
  165. package/dist/shared/{j5cn2963.js → t4tbsy9h.js} +13 -64
  166. package/dist/shared/{ngk8gj61.js → tbszx8mz.js} +15 -1
  167. package/dist/shared/v18jva5b.js +90 -0
  168. package/dist/shared/x9v1qgeb.js +201 -0
  169. package/dist/shared/xatfg0gn.js +193 -0
  170. package/dist/shared/xkz8g6by.js +225 -0
  171. package/dist/shared/{f5thc1s0.js → xrfnq5k8.js} +237 -418
  172. package/dist/shared/ytg3xf9p.js +149 -0
  173. package/dist/shared/yw5c610b.js +48 -0
  174. package/dist/shared/zd93g3rq.js +31 -0
  175. package/dist/shared/zt8y0wzb.js +132 -0
  176. package/dist/shared/{p0cbr3g2.js → zwmqxb0g.js} +1 -1
  177. package/dist/tooling/cli.js +14 -10
  178. package/dist/tooling/migrate/commands.d.ts +10 -0
  179. package/dist/tooling/migrate/engine.d.ts +36 -0
  180. package/package.json +56 -4
  181. package/dist/shared/gk7cs7sp.js +0 -566
@@ -0,0 +1,210 @@
1
+ import {
2
+ readHandle,
3
+ readCall,
4
+ attachHttp
5
+ } from "./mxmcdsh5.js";
6
+ import {
7
+ emitWhere,
8
+ emitOrder,
9
+ rejectKeys,
10
+ readLimit,
11
+ projectExpr,
12
+ cell,
13
+ indexes,
14
+ quote,
15
+ list,
16
+ isRecord,
17
+ fail
18
+ } from "./xrfnq5k8.js";
19
+ import {
20
+ OkmError2,
21
+ throwNamed2
22
+ } from "./52szzakm.js";
23
+
24
+ // src/runtime/aggregate.ts
25
+ var OPTIONS = [
26
+ "where",
27
+ "groupBy",
28
+ "count",
29
+ "sum",
30
+ "avg",
31
+ "min",
32
+ "max",
33
+ "orderBy",
34
+ "limit",
35
+ "signal",
36
+ "timeout"
37
+ ];
38
+ var NUMERIC = /^(smallint|integer|bigint|real|double precision|numeric|decimal)\b/;
39
+ var AS_NUMBER = (wire) => Number(wire);
40
+ var AS_TEXT = (wire) => wire;
41
+ var UNORDERED = /^(json|jsonb|bytea|point|line|tsvector)\b|\[\]$/;
42
+ var FUNCTIONS = [
43
+ { option: "sum", tag: "s", numeric: true },
44
+ { option: "avg", tag: "a", numeric: true },
45
+ { option: "min", tag: "n", numeric: false },
46
+ { option: "max", tag: "x", numeric: false }
47
+ ];
48
+ function build(session, table, options, mods, view) {
49
+ try {
50
+ return plan(session, table, options, mods, view);
51
+ } catch (error) {
52
+ throw error instanceof OkmError2 ? attachHttp(session.http, error) : error;
53
+ }
54
+ }
55
+ function plan(session, table, options, mods, view) {
56
+ const record = isRecord(options) ? options : {};
57
+ rejectKeys(record, OPTIONS, "aggregate");
58
+ const indexed = indexes(session.schema).get(table);
59
+ if (indexed === undefined)
60
+ fail("OKM1120", `Table ${table} is not in the schema.`);
61
+ const spec = parse(indexed, record);
62
+ if (spec.groups.length > 0 && record.limit === undefined && mods.all === undefined) {
63
+ fail("OKM1101", "aggregate() with groupBy needs a limit, or .all(reason) for every group.");
64
+ }
65
+ const orderBy = record.orderBy;
66
+ if (orderBy !== undefined) {
67
+ if (!isRecord(orderBy))
68
+ fail("OKM1120", "orderBy must be an object of fields.");
69
+ for (const field of Object.keys(orderBy)) {
70
+ if (!spec.groups.some((column) => column.field === field)) {
71
+ throwNamed2("OKM1120", field, spec.groups.map((column) => column.field), `aggregate() orders by a groupBy field. Accepted names: ${list(spec.groups.map((column) => column.field))}.`);
72
+ }
73
+ }
74
+ }
75
+ if (record.limit !== undefined)
76
+ readLimit(record.limit);
77
+ const base = readCall("find", table, {
78
+ where: record.where,
79
+ orderBy,
80
+ limit: record.limit,
81
+ signal: record.signal,
82
+ timeout: record.timeout
83
+ }, mods.all, session.scope, session.schema.model[table], session.schema, view);
84
+ const call = { ...base, op: "aggregate", build: statement(spec) };
85
+ return readHandle(session, table, call, mods, (compiled, rows) => decode(compiled, rows));
86
+ }
87
+ function parse(table, record) {
88
+ const groups = columns(table, record.groupBy, "groupBy");
89
+ const count = record.count === true;
90
+ if (record.count !== undefined && typeof record.count !== "boolean") {
91
+ fail("OKM1120", "count is true when you want a row count.");
92
+ }
93
+ const calls = [];
94
+ for (const { option, tag, numeric } of FUNCTIONS) {
95
+ for (const column of columns(table, record[option], option)) {
96
+ const fits = numeric ? NUMERIC.test(column.dataType) : !UNORDERED.test(column.dataType);
97
+ if (!fits) {
98
+ fail("OKM1124", `${option} does not apply to ${column.dataType} column ${column.field}. ${numeric ? "sum and avg take integer, real, and numeric columns." : "min and max need an ordered type."}`);
99
+ }
100
+ calls.push({ option, tag, column, decode: numeric ? sumDecode(column) : column.decode });
101
+ }
102
+ }
103
+ if (!count && calls.length === 0 && groups.length === 0) {
104
+ fail("OKM1120", "aggregate() needs count, sum, avg, min, max, or groupBy.");
105
+ }
106
+ return { groups, count, calls };
107
+ }
108
+ function sumDecode(column) {
109
+ const kind = typeof (column.decode?.("0") ?? "");
110
+ if (kind === "string")
111
+ return AS_TEXT;
112
+ if (kind === "number")
113
+ return AS_NUMBER;
114
+ return fail("OKM1124", `sum and avg need a column whose value is a number or a string. ${column.field} reads as ${kind}.`);
115
+ }
116
+ function columns(table, value, option) {
117
+ if (value === undefined)
118
+ return [];
119
+ if (!Array.isArray(value))
120
+ fail("OKM1120", `${option} must be a list of field names.`);
121
+ const out = [];
122
+ for (const name of value) {
123
+ const column = typeof name === "string" ? table.columns.get(name) : undefined;
124
+ if (typeof name !== "string" || column === undefined) {
125
+ throwNamed2("OKM1120", String(name), table.names, `Field ${String(name)} is not on ${table.model.name}. Accepted names: ${list(table.names)}.`);
126
+ }
127
+ if (column.hidden) {
128
+ fail("OKM1120", `Field ${column.field} is hidden, so ${option} cannot read it.`);
129
+ }
130
+ out.push(column);
131
+ }
132
+ return out;
133
+ }
134
+ function statement(spec) {
135
+ return (schema, table, sink, outputs, call) => {
136
+ sink.mark(`aggregate|${table.model.name}|g:${spec.groups.map((column) => column.field).join(",")}|c:${String(spec.count)}|${spec.calls.map((item) => `${item.tag}:${item.column.field}`).join(",")}|`);
137
+ sink.text("select ");
138
+ const wrote = { at: 0 };
139
+ for (const column of spec.groups) {
140
+ put(sink, outputs, wrote, projectExpr(`t.${quote(column.sql)}`, column.dataType), {
141
+ key: `g:${column.field}`,
142
+ decode: column.decode
143
+ });
144
+ }
145
+ if (spec.count)
146
+ put(sink, outputs, wrote, "count(*)::text", { key: "c:", decode: undefined });
147
+ for (const item of spec.calls) {
148
+ const ref = `t.${quote(item.column.sql)}`;
149
+ const expr = item.option === "sum" || item.option === "avg" ? `${item.option}(${ref})::text` : projectExpr(`${item.option}(${ref})`, item.column.dataType);
150
+ put(sink, outputs, wrote, expr, {
151
+ key: `${item.tag}:${item.column.field}`,
152
+ decode: item.decode
153
+ });
154
+ }
155
+ sink.text(" from ");
156
+ sink.text(quote(table.model.sql));
157
+ sink.text(" t");
158
+ emitWhere(schema, table, call.where, sink, "t", 0);
159
+ if (spec.groups.length > 0) {
160
+ sink.text(" group by ");
161
+ sink.text(spec.groups.map((column) => `t.${quote(column.sql)}`).join(", "));
162
+ if (isRecord(call.orderBy) && Object.keys(call.orderBy).length > 0) {
163
+ emitOrder(table, call.orderBy, sink, "t");
164
+ } else {
165
+ sink.text(" order by ");
166
+ sink.text(spec.groups.map((column) => `t.${quote(column.sql)} asc nulls last`).join(", "));
167
+ }
168
+ }
169
+ if (call.limit !== undefined) {
170
+ const limit = String(call.limit);
171
+ sink.text(" limit ");
172
+ sink.param(limit);
173
+ sink.mark(`l:${limit}`);
174
+ }
175
+ if (typeof call.all === "string")
176
+ sink.mark(`all:${call.all}`);
177
+ };
178
+ }
179
+ function put(sink, outputs, wrote, expr, out) {
180
+ if (wrote.at > 0)
181
+ sink.text(", ");
182
+ sink.text(expr);
183
+ outputs?.fields.push({ key: out.key, at: wrote.at, decode: out.decode });
184
+ wrote.at += 1;
185
+ }
186
+ function decode(compiled, rows) {
187
+ const items = [];
188
+ for (const row of rows) {
189
+ const item = {};
190
+ for (const field of compiled.outputs.fields) {
191
+ const value = row[field.at];
192
+ const tag = field.key.slice(0, 2);
193
+ const name = field.key.slice(2);
194
+ if (tag === "g:") {
195
+ item[name] = cell(value, field.decode);
196
+ } else if (tag === "c:") {
197
+ item.count = Number(value ?? 0);
198
+ } else {
199
+ const group = tag === "s:" ? "sum" : tag === "a:" ? "avg" : tag === "n:" ? "min" : "max";
200
+ const into = item[group] ??= {};
201
+ into[name] = cell(value, field.decode);
202
+ }
203
+ }
204
+ items.push(item);
205
+ }
206
+ return items;
207
+ }
208
+ export {
209
+ build
210
+ };
@@ -1,13 +1,17 @@
1
1
  import {
2
2
  PgSession
3
- } from "./7ck0dtry.js";
3
+ } from "./ecdzej21.js";
4
+ import {
5
+ isConnectionLost
6
+ } from "./tbszx8mz.js";
4
7
  import {
5
8
  driverErrors,
6
9
  rejectClosed,
7
10
  mapFailure,
8
11
  runCall,
9
- rowsFrom
10
- } from "./xy79j5hq.js";
12
+ rowsFrom,
13
+ resultFrom
14
+ } from "./9k6vetvf.js";
11
15
 
12
16
  // src/adapters/pg/postgres-extra.ts
13
17
  var RESET_ALL = "RESET ALL";
@@ -20,12 +24,18 @@ async function checkout(pool) {
20
24
  const local = new Set;
21
25
  const session = new PgSession(reserved, pool.counters, "reserved", local, pool.isClosed, pool.poolInflight, pool.notices, pool.named);
22
26
  let released = false;
27
+ let lost = false;
28
+ const guard = (run) => lost ? rejectClosed("The connection was lost.") : run().catch((error) => {
29
+ if (isConnectionLost(error))
30
+ lost = true;
31
+ throw error;
32
+ });
23
33
  return {
24
- execute: (text, params, options) => runCall(pool.isClosed(), options, (watch) => session.query(text, params, watch)),
25
- batch: (statements, options) => runCall(pool.isClosed(), options, async (watch) => {
26
- const { runAtomicBatch } = await import("./dynq16vb.js");
34
+ execute: (text, params, options) => guard(() => runCall(pool.isClosed(), options, (watch) => session.query(text, params, watch))),
35
+ batch: (statements, options) => guard(() => runCall(pool.isClosed(), options, async (watch) => {
36
+ const { runAtomicBatch } = await import("./b066g80h.js");
27
37
  return runAtomicBatch(session, statements, watch);
28
- }),
38
+ })),
29
39
  cancel() {
30
40
  session.cancel();
31
41
  },
@@ -34,10 +44,12 @@ async function checkout(pool) {
34
44
  return;
35
45
  released = true;
36
46
  try {
37
- await resetConnection(reserved, session.depth());
47
+ if (!lost)
48
+ await resetConnection(reserved, session.depth());
38
49
  } finally {
39
50
  pool.counters.reserved = Math.max(0, pool.counters.reserved - 1);
40
- reserved.release();
51
+ if (!lost)
52
+ reserved.release();
41
53
  }
42
54
  }
43
55
  };
@@ -112,8 +124,81 @@ function asParams(params) {
112
124
  return [];
113
125
  return params;
114
126
  }
127
+ async function holdCheckout(gate, checkout) {
128
+ try {
129
+ const connection = await checkout();
130
+ let released = false;
131
+ const release = connection.release.bind(connection);
132
+ connection.release = () => {
133
+ if (released)
134
+ return Promise.resolve();
135
+ released = true;
136
+ return release().finally(() => {
137
+ gate.leave();
138
+ });
139
+ };
140
+ return connection;
141
+ } catch (error) {
142
+ gate.leave();
143
+ throw error;
144
+ }
145
+ }
146
+ async function holdListener(gate, start) {
147
+ try {
148
+ const stop = await start();
149
+ let stopped = false;
150
+ return async () => {
151
+ if (stopped)
152
+ return;
153
+ stopped = true;
154
+ try {
155
+ await stop();
156
+ } finally {
157
+ gate.leave();
158
+ }
159
+ };
160
+ } catch (error) {
161
+ gate.leave();
162
+ throw error;
163
+ }
164
+ }
165
+ function watchQuery(pending, watch, onAbort, ctx) {
166
+ return pending.then((result) => {
167
+ finishWatch(pending, watch, onAbort, ctx);
168
+ const why = watch.reason();
169
+ if (why === "timeout" || why === "cancelled")
170
+ return classify(why, watch);
171
+ ctx.note(ctx.text);
172
+ return resultFrom(result, ctx.notices.since(ctx.start));
173
+ }, (error) => {
174
+ finishWatch(pending, watch, onAbort, ctx);
175
+ return classify(error, watch);
176
+ });
177
+ }
178
+ function finishWatch(pending, watch, onAbort, ctx) {
179
+ ctx.leave();
180
+ ctx.untrack(pending);
181
+ watch.signal.removeEventListener("abort", onAbort);
182
+ }
183
+ async function classify(error, watch) {
184
+ const errors = await driverErrors();
185
+ if (error instanceof errors.DriverError)
186
+ return Promise.reject(error);
187
+ const why = typeof error === "string" ? error : watch.reason();
188
+ if (why === "timeout") {
189
+ return Promise.reject(errors.timedOut(typeof error === "string" ? undefined : error));
190
+ }
191
+ const code = errors.errorField(error, "code");
192
+ if (why === "cancelled" || code === "57014") {
193
+ return Promise.reject(errors.cancelled(typeof error === "string" ? undefined : error));
194
+ }
195
+ return Promise.reject(errors.mapDriverError(error));
196
+ }
115
197
  export {
116
198
  checkout,
117
199
  describe,
118
- stream
200
+ holdCheckout,
201
+ holdListener,
202
+ stream,
203
+ watchQuery
119
204
  };
@@ -0,0 +1,229 @@
1
+ import {
2
+ quoteIdent2,
3
+ noticeBuffer,
4
+ WireSession,
5
+ cursorStream
6
+ } from "./cstgkzdx.js";
7
+ import {
8
+ NODE_POSTGRES_CAPABILITIES,
9
+ driverErrors,
10
+ rejectClosed,
11
+ mapFailure,
12
+ runCall
13
+ } from "./9k6vetvf.js";
14
+
15
+ // src/adapters/pg/nodepostgres.ts
16
+ import net from "node:net";
17
+ import pg from "pg";
18
+ var CANCEL_CODE = 80877102;
19
+ var identity = (value) => value;
20
+ var WIRE = {
21
+ getTypeParser() {
22
+ return identity;
23
+ }
24
+ };
25
+ function open4(config) {
26
+ const max = config.max ?? 10;
27
+ const acquireMs = config.timeouts?.acquire;
28
+ const counters = { reserved: 0, busy: 0, reservedBusy: 0, waiting: 0 };
29
+ const inflight = new Set;
30
+ const notices = noticeBuffer();
31
+ let closed = false;
32
+ const isClosed = () => closed;
33
+ const named = config.prepared === "named";
34
+ const pool = new pg.Pool({
35
+ connectionString: config.url,
36
+ max,
37
+ idleTimeoutMillis: 0,
38
+ allowExitOnIdle: true,
39
+ connectionTimeoutMillis: 5000,
40
+ application_name: "okmodel",
41
+ types: WIRE,
42
+ ...config.ssl !== undefined ? { ssl: config.ssl } : {},
43
+ ...config.searchPath !== undefined ? { options: `-c search_path=${config.searchPath}` } : {}
44
+ });
45
+ pool.on("connect", (client) => {
46
+ client.on("notice", (notice) => {
47
+ notices.push(notice);
48
+ });
49
+ });
50
+ const root = new WireSession((text, params) => send(pool, text, params, named, undefined), notices, isClosed, true, () => {
51
+ counters.busy += 1;
52
+ }, () => {
53
+ counters.busy = Math.max(0, counters.busy - 1);
54
+ }, inflight);
55
+ const held = { pool, acquireMs, counters, notices, named, isClosed };
56
+ const checkout = () => closed ? rejectClosed() : import("./qa5dsc7z.js").then((mod) => mod.checkout(held));
57
+ return {
58
+ capabilities: NODE_POSTGRES_CAPABILITIES,
59
+ execute(text, params, options) {
60
+ return runCall(closed, options, async (watch) => {
61
+ if (watch === undefined)
62
+ return root.query(text, params, undefined);
63
+ const client = await connectClient(pool, acquireMs, counters);
64
+ counters.busy += 1;
65
+ const session = new WireSession((statement, values) => send(client, statement, values, named, client), notices, isClosed, true, () => {
66
+ return;
67
+ }, () => {
68
+ return;
69
+ }, inflight);
70
+ try {
71
+ return await session.query(text, params, watch);
72
+ } finally {
73
+ counters.busy = Math.max(0, counters.busy - 1);
74
+ client.release();
75
+ }
76
+ });
77
+ },
78
+ async batch(statements, options) {
79
+ const connection = await checkout();
80
+ try {
81
+ return await connection.batch(statements, options);
82
+ } finally {
83
+ await connection.release();
84
+ }
85
+ },
86
+ reserve: () => checkout(),
87
+ stream(text, params) {
88
+ return stream(text, params);
89
+ },
90
+ listen(channel, onNotify) {
91
+ return listen(channel, onNotify);
92
+ },
93
+ cancel() {
94
+ for (const pending of inflight)
95
+ pending.cancel?.();
96
+ },
97
+ stats: () => statsOf(counters, max),
98
+ async close() {
99
+ closed = true;
100
+ await pool.end();
101
+ }
102
+ };
103
+ function stream(text, params) {
104
+ return async function* () {
105
+ const connection = await checkout();
106
+ try {
107
+ yield* cursorStream((statement, values) => connection.execute(statement, values), text, params);
108
+ } finally {
109
+ await connection.release();
110
+ }
111
+ }();
112
+ }
113
+ async function listen(channel, onNotify) {
114
+ if (closed)
115
+ return rejectClosed();
116
+ const client = await connectClient(pool, acquireMs, counters);
117
+ counters.reserved += 1;
118
+ const quoted = quoteIdent2(channel);
119
+ const onNotification = (message) => {
120
+ if (message.channel === channel)
121
+ onNotify(message.payload ?? "");
122
+ };
123
+ client.on("notification", onNotification);
124
+ try {
125
+ await client.query(`LISTEN ${quoted}`);
126
+ } catch (error) {
127
+ counters.reserved = Math.max(0, counters.reserved - 1);
128
+ client.release();
129
+ throw error;
130
+ }
131
+ let stopped = false;
132
+ return async () => {
133
+ if (stopped)
134
+ return;
135
+ stopped = true;
136
+ try {
137
+ await client.query(`UNLISTEN ${quoted}`);
138
+ } finally {
139
+ client.removeListener("notification", onNotification);
140
+ counters.reserved = Math.max(0, counters.reserved - 1);
141
+ client.release();
142
+ }
143
+ };
144
+ }
145
+ }
146
+ function send(runner, text, params, named, client) {
147
+ const query = {
148
+ text,
149
+ rowMode: "array",
150
+ types: WIRE,
151
+ ...params !== undefined && params.length > 0 ? { values: params } : {},
152
+ ...named ? { name: statementName(text) } : {}
153
+ };
154
+ const pending = runner.query(query);
155
+ if (client !== undefined)
156
+ pending.cancel = () => cancelBackend(client);
157
+ return pending;
158
+ }
159
+ var names = new Map;
160
+ function statementName(text) {
161
+ const existing = names.get(text);
162
+ if (existing !== undefined)
163
+ return existing;
164
+ const name = `okm_${String(names.size)}`;
165
+ names.set(text, name);
166
+ return name;
167
+ }
168
+ function cancelBackend(client) {
169
+ const pid = client.processID;
170
+ const secret = client.secretKey;
171
+ if (typeof pid !== "number" || typeof secret !== "number")
172
+ return;
173
+ const socket = client.host.startsWith("/") === true ? net.connect(client.host) : net.connect(client.port, client.host);
174
+ socket.unref();
175
+ socket.once("error", () => {
176
+ socket.destroy();
177
+ });
178
+ socket.once("connect", () => {
179
+ const bytes = Buffer.alloc(16);
180
+ bytes.writeInt32BE(16, 0);
181
+ bytes.writeInt32BE(CANCEL_CODE, 4);
182
+ bytes.writeInt32BE(pid, 8);
183
+ bytes.writeInt32BE(secret, 12);
184
+ socket.end(bytes);
185
+ });
186
+ }
187
+ function connectClient(pool, acquireMs, counters) {
188
+ counters.waiting += 1;
189
+ let settled = false;
190
+ return new Promise((resolve, reject) => {
191
+ let timer;
192
+ if (acquireMs !== undefined) {
193
+ timer = setTimeout(() => {
194
+ settled = true;
195
+ counters.waiting = Math.max(0, counters.waiting - 1);
196
+ driverErrors().then((errors) => {
197
+ reject(errors.acquireTimeout());
198
+ });
199
+ }, acquireMs);
200
+ }
201
+ pool.connect().then((client) => {
202
+ if (settled) {
203
+ client.release();
204
+ return;
205
+ }
206
+ if (timer !== undefined)
207
+ clearTimeout(timer);
208
+ counters.waiting = Math.max(0, counters.waiting - 1);
209
+ resolve(client);
210
+ }, (error) => {
211
+ if (settled)
212
+ return;
213
+ if (timer !== undefined)
214
+ clearTimeout(timer);
215
+ counters.waiting = Math.max(0, counters.waiting - 1);
216
+ mapFailure(error).then(reject);
217
+ });
218
+ });
219
+ }
220
+ function statsOf(counters, size) {
221
+ return {
222
+ size,
223
+ idle: Math.max(0, size - counters.reserved - counters.busy),
224
+ inflight: counters.busy + counters.reservedBusy,
225
+ waiting: counters.waiting
226
+ };
227
+ }
228
+
229
+ export { open4, send, connectClient };