@voltro/sql-postgres 0.33.0 → 0.35.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.
- package/CHANGELOG.md +1968 -0
- package/dist/index.d.ts +146 -9
- package/dist/index.js +412 -209
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,39 +1,47 @@
|
|
|
1
1
|
import { PgClient as e, PgClient as t } from "@effect/sql-pg";
|
|
2
|
-
import { Config as n,
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
2
|
+
import { Config as n, Duration as r, Effect as i, Fiber as a, Layer as o, ManagedRuntime as s, Metric as c, Redacted as l, Schedule as u, Stream as d } from "effect";
|
|
3
|
+
import f from "pg";
|
|
4
|
+
import { DEFAULT_ACQUIRE_TIMEOUT_MS as p, EagerCardinalityError as m, attachEagerLoads as h, attributionFields as g, attributionKey as ee, beginLocalWrite as te, bulkInsertLimitsFor as ne, chunkRowsForInsert as re, compileEagerJson as ie, compilePredicate as _, compileRawFragment as ae, compileSelect as oe, encodeRowForSchema as v, endLocalWrite as se, externalChangeEvent as ce, hasEagerLoads as le, isTableReactive as y, makeEagerFallbackReporter as ue, observeDbOp as b, raiseChangeListenerCeiling as de, recordsTable as fe, registerPendingAttribution as x, requireTable as S, resolveEchoAttribution as C, runRetryingTransaction as w, runStoreTransaction as T, runWriteRecorders as pe, stampGeneratedId as E, stampGeneratedIds as me, withCapturedAttribution as D } from "@voltro/database";
|
|
5
|
+
import { EventEmitter as he } from "node:events";
|
|
6
|
+
import { createLogger as ge } from "@voltro/logger";
|
|
7
|
+
import { SqlClient as O, TransactionConnection as k } from "@effect/sql/SqlClient";
|
|
8
|
+
//#region src/sqlLayer.ts
|
|
9
|
+
var A = (e) => {
|
|
10
|
+
let t = e.acquireTimeoutMs ?? p;
|
|
11
|
+
return t > 0 ? t : void 0;
|
|
12
|
+
}, j = (e) => e ? { rejectUnauthorized: !1 } : !1, M = /^[A-Za-z_][A-Za-z0-9_]*$/, N = (e) => {
|
|
13
|
+
let t = A(e);
|
|
14
|
+
return {
|
|
15
|
+
host: n.succeed(e.host),
|
|
16
|
+
port: n.succeed(e.port),
|
|
17
|
+
username: n.succeed(e.username),
|
|
18
|
+
password: n.succeed(l.make(e.password)),
|
|
19
|
+
database: n.succeed(e.database),
|
|
20
|
+
...e.maxConnections === void 0 ? {} : { maxConnections: n.succeed(e.maxConnections) },
|
|
21
|
+
...e.ssl === void 0 ? {} : { ssl: n.succeed(j(e.ssl)) },
|
|
22
|
+
...t === void 0 ? {} : { connectTimeout: n.succeed(r.millis(t)) }
|
|
23
|
+
};
|
|
24
|
+
}, P = (t) => {
|
|
25
|
+
if (t.schema === void 0 && t.statementTimeoutMs === void 0) return e.layerConfig(N(t));
|
|
26
|
+
let n = {};
|
|
19
27
|
if (t.schema !== void 0) {
|
|
20
|
-
if (!
|
|
21
|
-
|
|
28
|
+
if (!M.test(t.schema)) throw Error(`DB_SCHEMA '${t.schema}' is not a valid postgres identifier (expected ${M}).`);
|
|
29
|
+
n = { options: `-c search_path="${t.schema}"` };
|
|
22
30
|
}
|
|
23
|
-
let a =
|
|
31
|
+
let r = A(t), a = i.acquireRelease(i.sync(() => new f.Pool({
|
|
24
32
|
host: t.host,
|
|
25
33
|
port: t.port,
|
|
26
34
|
user: t.username,
|
|
27
35
|
password: t.password,
|
|
28
36
|
database: t.database,
|
|
29
37
|
...t.maxConnections === void 0 ? {} : { max: t.maxConnections },
|
|
30
|
-
...t.ssl === void 0 ? {} : { ssl:
|
|
38
|
+
...t.ssl === void 0 ? {} : { ssl: j(t.ssl) },
|
|
31
39
|
...t.statementTimeoutMs === void 0 ? {} : { statement_timeout: t.statementTimeoutMs },
|
|
32
|
-
connectionTimeoutMillis:
|
|
33
|
-
...
|
|
34
|
-
})), (e) =>
|
|
40
|
+
...r === void 0 ? {} : { connectionTimeoutMillis: r },
|
|
41
|
+
...n
|
|
42
|
+
})), (e) => i.promise(() => e.end()));
|
|
35
43
|
return e.layerFromPool({ acquire: a });
|
|
36
|
-
},
|
|
44
|
+
}, F = (e) => {
|
|
37
45
|
let t = e.get("sslmode");
|
|
38
46
|
if (t !== null) {
|
|
39
47
|
if (t === "require") return !0;
|
|
@@ -46,19 +54,20 @@ var R = (e) => e ? { rejectUnauthorized: !1 } : !1, z = /^[A-Za-z_][A-Za-z0-9_]*
|
|
|
46
54
|
if (n === "false" || n === "0") return !1;
|
|
47
55
|
throw Error(`DB_URL '?ssl=${n}' is not supported by the postgres dialect — use 'true'/'1' or 'false'/'0'.`);
|
|
48
56
|
}
|
|
49
|
-
},
|
|
50
|
-
let t = e.schema === void 0 ? {} : { schema: e.schema };
|
|
57
|
+
}, I = (e) => {
|
|
58
|
+
let t = e.schema === void 0 ? {} : { schema: e.schema }, n = e.acquireTimeoutMs === void 0 ? {} : { acquireTimeoutMs: e.acquireTimeoutMs };
|
|
51
59
|
if (e.url) {
|
|
52
|
-
let
|
|
60
|
+
let r = new URL(e.url), i = e.ssl ?? F(r.searchParams);
|
|
53
61
|
return {
|
|
54
|
-
host:
|
|
55
|
-
port:
|
|
56
|
-
username: decodeURIComponent(
|
|
57
|
-
password: decodeURIComponent(
|
|
58
|
-
database:
|
|
62
|
+
host: r.hostname || "localhost",
|
|
63
|
+
port: r.port ? Number(r.port) : 5432,
|
|
64
|
+
username: decodeURIComponent(r.username || "app"),
|
|
65
|
+
password: decodeURIComponent(r.password || "app"),
|
|
66
|
+
database: r.pathname.replace(/^\//, "") || "app",
|
|
59
67
|
...e.maxConnections === void 0 ? {} : { maxConnections: e.maxConnections },
|
|
60
68
|
...e.statementTimeoutMs === void 0 ? {} : { statementTimeoutMs: e.statementTimeoutMs },
|
|
61
|
-
...
|
|
69
|
+
...i === void 0 ? {} : { ssl: i },
|
|
70
|
+
...n,
|
|
62
71
|
...t
|
|
63
72
|
};
|
|
64
73
|
}
|
|
@@ -71,170 +80,271 @@ var R = (e) => e ? { rejectUnauthorized: !1 } : !1, z = /^[A-Za-z_][A-Za-z0-9_]*
|
|
|
71
80
|
...e.maxConnections === void 0 ? {} : { maxConnections: e.maxConnections },
|
|
72
81
|
...e.statementTimeoutMs === void 0 ? {} : { statementTimeoutMs: e.statementTimeoutMs },
|
|
73
82
|
...e.ssl === void 0 ? {} : { ssl: e.ssl },
|
|
83
|
+
...n,
|
|
74
84
|
...t
|
|
75
85
|
};
|
|
76
|
-
},
|
|
86
|
+
}, L = (e) => P(I(e)), R = /* @__PURE__ */ new Set(["40001", "40P01"]), _e = (e) => {
|
|
77
87
|
let t = e;
|
|
78
88
|
for (let e = 0; e < 5 && typeof t == "object" && t; e++) {
|
|
79
89
|
let e = t.code;
|
|
80
90
|
if (typeof e == "string") return e;
|
|
81
91
|
t = t.cause;
|
|
82
92
|
}
|
|
83
|
-
},
|
|
84
|
-
let t =
|
|
85
|
-
return t !== void 0 &&
|
|
86
|
-
},
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
},
|
|
93
|
+
}, z = (e) => {
|
|
94
|
+
let t = _e(e);
|
|
95
|
+
return t !== void 0 && R.has(t);
|
|
96
|
+
}, B = (e) => z(e) ? "retry" : "noRetry", V = c.counter("voltro_cdc_oversized_total", { description: "Change events whose row images exceeded the postgres NOTIFY payload cap, by what re-hydration recovered (rehydrated = row re-read · tombstone = delete, primary key only · unrecovered = content lost to taps)." }), ve = {
|
|
97
|
+
rehydrated: c.tagged(V, "outcome", "rehydrated"),
|
|
98
|
+
tombstone: c.tagged(V, "outcome", "tombstone"),
|
|
99
|
+
unrecovered: c.tagged(V, "outcome", "unrecovered")
|
|
100
|
+
}, H = (e) => {
|
|
101
|
+
i.runSync(c.increment(ve[e]));
|
|
102
|
+
}, ye = {
|
|
103
|
+
rehydrateTimeoutMs: 5e3,
|
|
104
|
+
rehydrateRetries: 2
|
|
105
|
+
}, U = (e) => {
|
|
106
|
+
let t = process.env[e];
|
|
107
|
+
if (t === void 0 || t.trim() === "") return;
|
|
108
|
+
let n = Number(t);
|
|
109
|
+
return Number.isFinite(n) && n >= 0 ? n : void 0;
|
|
110
|
+
}, W = (e) => {
|
|
111
|
+
let t = ye, n = e ?? {};
|
|
112
|
+
return {
|
|
113
|
+
rehydrateTimeoutMs: Math.max(1, n.rehydrateTimeoutMs ?? U("VOLTRO_CDC_REHYDRATE_TIMEOUT_MS") ?? t.rehydrateTimeoutMs),
|
|
114
|
+
rehydrateRetries: Math.max(0, n.rehydrateRetries ?? U("VOLTRO_CDC_REHYDRATE_RETRIES") ?? t.rehydrateRetries)
|
|
115
|
+
};
|
|
116
|
+
}, be = (e) => i.suspend(() => {
|
|
117
|
+
let t = e.notification, n = t.id, a = {
|
|
118
|
+
table: t.table,
|
|
119
|
+
op: t.op
|
|
120
|
+
}, o = (e) => ({
|
|
121
|
+
event: {
|
|
122
|
+
...a,
|
|
123
|
+
old: null,
|
|
124
|
+
new: null,
|
|
125
|
+
oversized: "unrecovered"
|
|
126
|
+
},
|
|
127
|
+
outcome: "unrecovered",
|
|
128
|
+
reason: e
|
|
129
|
+
});
|
|
130
|
+
if (typeof n != "string" && typeof n != "number") return H("unrecovered"), i.succeed(o("no-key"));
|
|
131
|
+
if (t.op === "delete") {
|
|
132
|
+
H("tombstone");
|
|
133
|
+
let e = {
|
|
134
|
+
event: {
|
|
135
|
+
...a,
|
|
136
|
+
old: { id: n },
|
|
137
|
+
new: null,
|
|
138
|
+
oversized: "tombstone"
|
|
139
|
+
},
|
|
140
|
+
outcome: "tombstone"
|
|
141
|
+
};
|
|
142
|
+
return i.succeed(e);
|
|
143
|
+
}
|
|
144
|
+
let s = u.exponential(r.millis(50), 2).pipe(u.intersect(u.recurs(e.tunables.rehydrateRetries)));
|
|
145
|
+
return e.fetchRow({
|
|
146
|
+
schema: t.schema,
|
|
147
|
+
table: t.table,
|
|
148
|
+
key: n
|
|
149
|
+
}).pipe(i.retry(s), i.timeout(r.millis(e.tunables.rehydrateTimeoutMs)), i.map((e) => e === null ? (H("unrecovered"), o("row-gone")) : (H("rehydrated"), {
|
|
150
|
+
event: {
|
|
151
|
+
...a,
|
|
152
|
+
old: null,
|
|
153
|
+
new: e,
|
|
154
|
+
oversized: "rehydrated"
|
|
155
|
+
},
|
|
156
|
+
outcome: "rehydrated"
|
|
157
|
+
})), i.catchAllCause(() => (H("unrecovered"), i.succeed(o("read-failed")))));
|
|
158
|
+
}), xe = (e) => {
|
|
159
|
+
let t = /* @__PURE__ */ new Set();
|
|
160
|
+
return (n, r) => {
|
|
161
|
+
if (r.outcome === "unrecovered") {
|
|
162
|
+
e.error("cdc: oversized change could not be recovered — every tap (search, analytics, cdc-out, history) will miss this row; subscriptions re-query and are unaffected", {
|
|
163
|
+
table: n.table,
|
|
164
|
+
op: n.op,
|
|
165
|
+
reason: r.reason,
|
|
166
|
+
...r.reason === "no-key" ? { remedy: "run `voltro db apply` — this database's change-notify function predates the key" } : {}
|
|
167
|
+
});
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
t.has(n.table) || (t.add(n.table), e.warn("cdc: rows on this table exceed the postgres NOTIFY payload cap (8000 bytes) — their change events are re-read from the database before delivery. Counted as voltro_cdc_oversized_total.", {
|
|
171
|
+
table: n.table,
|
|
172
|
+
outcome: r.outcome,
|
|
173
|
+
note: r.outcome === "tombstone" ? "a delete of an oversized row delivers the primary key only — the pre-image is unrecoverable" : "the re-read returns the row as it is NOW, not the image at commit"
|
|
174
|
+
}));
|
|
175
|
+
};
|
|
176
|
+
}, G = ["json"], K = ge({ scope: "voltro:postgres" }), q = async (e) => {
|
|
177
|
+
let t = e.tracerLayer ? o.mergeAll(e.sqlLayer, e.tracerLayer) : e.sqlLayer, n = s.make(t), r = await n.runPromise(O), i = e.changeStrategy ?? "inline", a = new Se(r, n, i, e.cdcChannel ?? "framework_changes", W({
|
|
178
|
+
...e.cdcRehydrateTimeoutMs === void 0 ? {} : { rehydrateTimeoutMs: e.cdcRehydrateTimeoutMs },
|
|
179
|
+
...e.cdcRehydrateRetries === void 0 ? {} : { rehydrateRetries: e.cdcRehydrateRetries }
|
|
180
|
+
}));
|
|
181
|
+
return i === "cdc" && await a.startCdcConsumer(), a;
|
|
182
|
+
}, Se = class {
|
|
93
183
|
sql;
|
|
94
184
|
runtime;
|
|
95
185
|
changeStrategy;
|
|
96
186
|
cdcChannel;
|
|
97
|
-
|
|
187
|
+
cdcRehydrate;
|
|
188
|
+
emitter = new he();
|
|
98
189
|
cdcFiber = null;
|
|
99
190
|
inflightTxns = 0;
|
|
100
|
-
|
|
101
|
-
|
|
191
|
+
reportOversized = xe(K);
|
|
192
|
+
reportEagerFallback = ue(K);
|
|
193
|
+
constructor(e, t, n, r, i = W()) {
|
|
194
|
+
this.sql = e, this.runtime = t, this.changeStrategy = n, this.cdcChannel = r, this.cdcRehydrate = i, de(this.emitter);
|
|
195
|
+
}
|
|
196
|
+
txnSpec(e, t, n) {
|
|
197
|
+
return {
|
|
198
|
+
label: e,
|
|
199
|
+
dialect: "postgres",
|
|
200
|
+
withTransaction: (e) => this.sql.withTransaction(e),
|
|
201
|
+
runPromiseExit: (e) => this.runtime.runPromiseExit(e),
|
|
202
|
+
isRetryable: z,
|
|
203
|
+
span: {
|
|
204
|
+
name: t,
|
|
205
|
+
attributes: {
|
|
206
|
+
"db.system": "postgresql",
|
|
207
|
+
"db.operation": n
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
};
|
|
102
211
|
}
|
|
103
212
|
withNamespace(e) {
|
|
104
|
-
return e === null ? this : new
|
|
213
|
+
return e === null ? this : new Ce(this, e);
|
|
105
214
|
}
|
|
106
215
|
async runInNamespace(e, t) {
|
|
216
|
+
let n = this.sql;
|
|
107
217
|
this.inflightTxns++;
|
|
108
|
-
let n = T(), i = Z(), a = this.sql, o = this.sql.withTransaction(r.flatMap(r.serviceOption(h), (o) => {
|
|
109
|
-
if (s.isNone(o)) return r.fail(/* @__PURE__ */ Error("PostgresDataStore.runInNamespace: TransactionConnection missing."));
|
|
110
|
-
let c = o.value, l = r.provideService(a`SET LOCAL search_path TO ${a(e)}`, h, c), u = new Q(this, c, n);
|
|
111
|
-
return r.flatMap(l, () => r.tryPromise({
|
|
112
|
-
try: () => i(() => t(u)).then((e) => ({
|
|
113
|
-
result: e,
|
|
114
|
-
view: u
|
|
115
|
-
})),
|
|
116
|
-
catch: (e) => e
|
|
117
|
-
}));
|
|
118
|
-
})).pipe(r.withSpan("store.namespace", { attributes: {
|
|
119
|
-
"db.system": "postgresql",
|
|
120
|
-
"db.operation": "namespace.transaction"
|
|
121
|
-
} }));
|
|
122
218
|
try {
|
|
123
|
-
|
|
124
|
-
|
|
219
|
+
return await T({
|
|
220
|
+
...this.txnSpec("PostgresDataStore.runInNamespace", "store.namespace", "namespace.transaction"),
|
|
221
|
+
prepare: (t) => i.provideService(n`SET LOCAL search_path TO ${n(e)}`, k, t),
|
|
222
|
+
work: t,
|
|
223
|
+
makeView: (e, t) => new J(this, e, t)
|
|
224
|
+
});
|
|
125
225
|
} finally {
|
|
126
226
|
this.inflightTxns--;
|
|
127
227
|
}
|
|
128
228
|
}
|
|
129
229
|
__postgresReplicationFriend = { runEffect: (e) => this.runtime.runPromise(e) };
|
|
130
|
-
async executeQuery(e, t) {
|
|
131
|
-
let
|
|
132
|
-
return this.runtime.runPromise(
|
|
230
|
+
async executeQuery(e, t, n = null) {
|
|
231
|
+
let r = oe(e, this.sql, n), a = t ? i.provideService(r, k, t) : r;
|
|
232
|
+
return b("postgres", "select", () => this.runtime.runPromise(a));
|
|
133
233
|
}
|
|
134
|
-
async executeInsert(e, t, n,
|
|
135
|
-
t =
|
|
136
|
-
let o = this.sql, s = o`INSERT INTO ${o(e)} ${o.insert(
|
|
234
|
+
async executeInsert(e, t, n, r, a) {
|
|
235
|
+
t = E(e, t);
|
|
236
|
+
let o = this.sql, s = o`INSERT INTO ${o(e)} ${o.insert(v(t, e, G))} RETURNING *`, c = n ? i.provideService(s, k, n) : s, l = (await this.runtime.runPromise(c))[0];
|
|
137
237
|
if (!l) throw Error(`PostgresDataStore.insert: no row returned for table '${e}'`);
|
|
138
238
|
return await this.routeEvent({
|
|
139
239
|
table: e,
|
|
140
240
|
op: "insert",
|
|
141
241
|
old: null,
|
|
142
242
|
new: l
|
|
143
|
-
},
|
|
243
|
+
}, r, n, a), l;
|
|
144
244
|
}
|
|
145
|
-
async executeUpdate(e, t, n,
|
|
146
|
-
let s = this.sql, c = s`UPDATE ${s(e)} SET ${s.update(
|
|
245
|
+
async executeUpdate(e, t, n, r, a, o) {
|
|
246
|
+
let s = this.sql, c = s`UPDATE ${s(e)} SET ${s.update(v(n, e, G))} WHERE ${s("id")} = ${t} RETURNING *`, l = r ? i.provideService(c, k, r) : c, u = (await this.runtime.runPromise(l))[0];
|
|
147
247
|
return u ? (await this.routeEvent({
|
|
148
248
|
table: e,
|
|
149
249
|
op: "update",
|
|
150
250
|
old: null,
|
|
151
251
|
new: u
|
|
152
|
-
}, a,
|
|
252
|
+
}, a, r, o), u) : null;
|
|
153
253
|
}
|
|
154
|
-
async executeUpsert(e, t, n,
|
|
155
|
-
let
|
|
254
|
+
async executeUpsert(e, t, n, r, a, o) {
|
|
255
|
+
let s = this.sql;
|
|
156
256
|
if (typeof n.update == "function") {
|
|
157
|
-
let o = n.update,
|
|
158
|
-
let
|
|
159
|
-
return this.runtime.runPromise(
|
|
257
|
+
let o = n.update, c = n.conflictColumns.map((e) => s`${s(e)} = ${t[e]}`), l = (n) => {
|
|
258
|
+
let r = s`SELECT * FROM ${s(e)} WHERE ${s.and(c)} LIMIT 1 FOR UPDATE`;
|
|
259
|
+
return this.runtime.runPromise(i.flatMap(i.provideService(r, k, n), (r) => i.promise(() => r[0] ? this.executeUpdate(e, r[0].id, o(r[0]), n, a).then((e) => e) : this.executeInsert(e, t, n, a))));
|
|
160
260
|
};
|
|
161
|
-
if (
|
|
261
|
+
if (r) return l(r);
|
|
162
262
|
this.inflightTxns++;
|
|
163
263
|
try {
|
|
164
|
-
|
|
165
|
-
|
|
264
|
+
return await w({
|
|
265
|
+
...this.txnSpec("PostgresDataStore.upsert", "store.upsert", "upsert.transaction"),
|
|
266
|
+
body: (e) => l(e)
|
|
267
|
+
});
|
|
166
268
|
} finally {
|
|
167
269
|
this.inflightTxns--;
|
|
168
270
|
}
|
|
169
271
|
}
|
|
170
|
-
let
|
|
171
|
-
if (!
|
|
272
|
+
let c = n.conflictColumns.map((e) => s`${s(e)}`), l = Object.keys(t).filter((e) => t[e] !== void 0), u = n.update === void 0 ? l.filter((e) => e !== "id" && !n.conflictColumns.includes(e)) : n.update, d = u.length > 0 ? s.csv(u.map((e) => s`${s(e)} = EXCLUDED.${s(e)}`)) : s`${s(n.conflictColumns[0])} = EXCLUDED.${s(n.conflictColumns[0])}`, f = s`INSERT INTO ${s(e)} ${s.insert(v(t, e, G))} ON CONFLICT (${s.csv(c)}) DO UPDATE SET ${d} RETURNING *`, p = r ? i.provideService(f, k, r) : f, m = (await this.runtime.runPromise(p))[0];
|
|
273
|
+
if (!m) throw Error(`PostgresDataStore.upsert: no row returned for table '${e}'`);
|
|
172
274
|
{
|
|
173
|
-
let n = t.id !== void 0 && t.id ===
|
|
275
|
+
let n = t.id !== void 0 && t.id === m.id ? "insert" : "update";
|
|
174
276
|
await this.routeEvent({
|
|
175
277
|
table: e,
|
|
176
278
|
op: n,
|
|
177
279
|
old: null,
|
|
178
|
-
new:
|
|
179
|
-
}, a,
|
|
280
|
+
new: m
|
|
281
|
+
}, a, r, o);
|
|
180
282
|
}
|
|
181
|
-
return
|
|
283
|
+
return m;
|
|
182
284
|
}
|
|
183
|
-
async executeInsertIgnore(e, t, n,
|
|
184
|
-
t =
|
|
185
|
-
let s = this.sql, c = n.conflictColumns.map((e) => s`${s(e)}`), l = s`INSERT INTO ${s(e)} ${s.insert(
|
|
285
|
+
async executeInsertIgnore(e, t, n, r, a, o) {
|
|
286
|
+
t = E(e, t);
|
|
287
|
+
let s = this.sql, c = n.conflictColumns.map((e) => s`${s(e)}`), l = s`INSERT INTO ${s(e)} ${s.insert(v(t, e, G))} ON CONFLICT (${s.csv(c)}) DO NOTHING RETURNING *`, u = r ? i.provideService(l, k, r) : l, d = (await this.runtime.runPromise(u))[0];
|
|
186
288
|
if (d) return await this.routeEvent({
|
|
187
289
|
table: e,
|
|
188
290
|
op: "insert",
|
|
189
291
|
old: null,
|
|
190
292
|
new: d
|
|
191
|
-
}, a,
|
|
192
|
-
let f = n.conflictColumns.map((e) => s`${s(e)} = ${t[e]}`), p = s`SELECT * FROM ${s(e)} WHERE ${s.and(f)} LIMIT 1`, m =
|
|
193
|
-
if (!
|
|
194
|
-
return
|
|
195
|
-
}
|
|
196
|
-
async executeInsertMany(e, t, n,
|
|
197
|
-
if (t =
|
|
198
|
-
let o = this.sql, s =
|
|
293
|
+
}, a, r, o), d;
|
|
294
|
+
let f = n.conflictColumns.map((e) => s`${s(e)} = ${t[e]}`), p = s`SELECT * FROM ${s(e)} WHERE ${s.and(f)} LIMIT 1`, m = r ? i.provideService(p, k, r) : p, h = await this.runtime.runPromise(m);
|
|
295
|
+
if (!h[0]) throw Error(`PostgresDataStore.insertIgnore: the insert was skipped as a conflict, but no existing row matches conflictColumns [${n.conflictColumns.join(", ")}] on '${e}'. A DIFFERENT unique constraint fired — a second unique index, or the primary key when you named something else. insertIgnore models ONE conflict target: name the columns of the constraint that actually collides, or handle the unique violation yourself.`);
|
|
296
|
+
return h[0];
|
|
297
|
+
}
|
|
298
|
+
async executeInsertMany(e, t, n, r, a) {
|
|
299
|
+
if (t = me(e, t), t.length === 0) return [];
|
|
300
|
+
let o = this.sql, s = re(t.map((t) => v(t, e, G)), ne("postgres")), c = (t) => o`INSERT INTO ${o(e)} ${o.insert(t)} RETURNING *`, l;
|
|
301
|
+
if (s.length === 1) {
|
|
302
|
+
let e = c(s[0]), t = n ? i.provideService(e, k, n) : e;
|
|
303
|
+
l = await this.runtime.runPromise(t);
|
|
304
|
+
} else if (n) {
|
|
305
|
+
let e = [];
|
|
306
|
+
for (let t of s) e.push(...await this.runtime.runPromise(i.provideService(c(t), k, n)));
|
|
307
|
+
l = e;
|
|
308
|
+
} else l = await this.runtime.runPromise(o.withTransaction(i.map(i.forEach(s, c, { concurrency: 1 }), (e) => e.flat())));
|
|
199
309
|
for (let t of l) await this.routeEvent({
|
|
200
310
|
table: e,
|
|
201
311
|
op: "insert",
|
|
202
312
|
old: null,
|
|
203
313
|
new: t
|
|
204
|
-
},
|
|
314
|
+
}, r, n, a);
|
|
205
315
|
return l;
|
|
206
316
|
}
|
|
207
|
-
async executePatchJson(e, t, n,
|
|
208
|
-
let c = this.sql, l = n.split("."), u = l[0], d = l.slice(1), f = JSON.stringify(
|
|
209
|
-
return
|
|
317
|
+
async executePatchJson(e, t, n, r, a, o, s) {
|
|
318
|
+
let c = this.sql, l = n.split("."), u = l[0], d = l.slice(1), f = JSON.stringify(r ?? null), p = d.length === 0 ? c`${c(u)} = COALESCE(${c(u)}, '{}'::jsonb) || ${f}::jsonb` : c`${c(u)} = jsonb_set(COALESCE(${c(u)}, '{}'::jsonb), ${`{${d.join(",")}}`}, ${f}::jsonb, true)`, m = c`UPDATE ${c(e)} SET ${p} WHERE ${c("id")} = ${t} RETURNING *`, h = a ? i.provideService(m, k, a) : m, g = (await this.runtime.runPromise(h))[0];
|
|
319
|
+
return g ? (await this.routeEvent({
|
|
210
320
|
table: e,
|
|
211
321
|
op: "update",
|
|
212
322
|
old: null,
|
|
213
|
-
new:
|
|
214
|
-
}, o, a, s),
|
|
323
|
+
new: g
|
|
324
|
+
}, o, a, s), g) : null;
|
|
215
325
|
}
|
|
216
|
-
async executeDelete(e, t, n,
|
|
217
|
-
let o = this.sql, s = o`DELETE FROM ${o(e)} WHERE ${o("id")} = ${t} RETURNING *`, c = n ?
|
|
326
|
+
async executeDelete(e, t, n, r, a) {
|
|
327
|
+
let o = this.sql, s = o`DELETE FROM ${o(e)} WHERE ${o("id")} = ${t} RETURNING *`, c = n ? i.provideService(s, k, n) : s, l = (await this.runtime.runPromise(c))[0];
|
|
218
328
|
return l ? (await this.routeEvent({
|
|
219
329
|
table: e,
|
|
220
330
|
op: "delete",
|
|
221
331
|
old: l,
|
|
222
332
|
new: null
|
|
223
|
-
},
|
|
333
|
+
}, r, n, a), !0) : !1;
|
|
224
334
|
}
|
|
225
335
|
async appendInTxn(e, t, n) {
|
|
226
|
-
let
|
|
227
|
-
await this.runtime.runPromise(n ?
|
|
336
|
+
let r = this.sql, a = r`INSERT INTO ${r(e)} ${r.insert(v(t, e, G))}`;
|
|
337
|
+
await this.runtime.runPromise(n ? i.provideService(a, k, n) : a);
|
|
228
338
|
}
|
|
229
|
-
async maxInTxn(e, t, n,
|
|
230
|
-
let a = this.sql, o = Object.entries(n).map(([e, t]) => a`${a(e)} = ${t}`), s = a`SELECT MAX(${a(t)}) AS ${a("m")} FROM ${a(e)} WHERE ${a.and(o)}`, c = (await this.runtime.runPromise(
|
|
339
|
+
async maxInTxn(e, t, n, r) {
|
|
340
|
+
let a = this.sql, o = Object.entries(n).map(([e, t]) => a`${a(e)} = ${t}`), s = a`SELECT MAX(${a(t)}) AS ${a("m")} FROM ${a(e)} WHERE ${a.and(o)}`, c = (await this.runtime.runPromise(r ? i.provideService(s, k, r) : s))[0]?.m;
|
|
231
341
|
return c == null ? null : Number(c);
|
|
232
342
|
}
|
|
233
343
|
async routeEvent(e, t, n = null, r) {
|
|
234
344
|
if (e = {
|
|
235
|
-
...
|
|
345
|
+
...g(r),
|
|
236
346
|
...e
|
|
237
|
-
},
|
|
347
|
+
}, fe(e.table) && await pe({
|
|
238
348
|
append: (e, t) => this.appendInTxn(e, t, n),
|
|
239
349
|
maxOf: (e, t, r) => this.maxInTxn(e, t, r, n)
|
|
240
350
|
}, {
|
|
@@ -244,10 +354,10 @@ var R = (e) => e ? { rejectUnauthorized: !1 } : !1, z = /^[A-Za-z_][A-Za-z0-9_]*
|
|
|
244
354
|
prev: e.old,
|
|
245
355
|
traceId: e.traceId,
|
|
246
356
|
subjectId: e.subjectId
|
|
247
|
-
}),
|
|
357
|
+
}), y(e.table)) {
|
|
248
358
|
if (this.changeStrategy === "cdc") {
|
|
249
359
|
let t = (e.op === "delete" ? e.old : e.new)?.id;
|
|
250
|
-
t != null &&
|
|
360
|
+
t != null && x(ee(e.table, e.op, t), {
|
|
251
361
|
...e.traceId === void 0 ? {} : { traceId: e.traceId },
|
|
252
362
|
...e.subjectId === void 0 ? {} : { subjectId: e.subjectId }
|
|
253
363
|
});
|
|
@@ -260,79 +370,94 @@ var R = (e) => e ? { rejectUnauthorized: !1 } : !1, z = /^[A-Za-z_][A-Za-z0-9_]*
|
|
|
260
370
|
return this.runWithEager(e, null);
|
|
261
371
|
}
|
|
262
372
|
raw(e, t) {
|
|
263
|
-
let n =
|
|
264
|
-
return this.runtime.runPromise(n);
|
|
265
|
-
}
|
|
266
|
-
async runWithEager(e, t) {
|
|
267
|
-
if (!
|
|
268
|
-
let
|
|
269
|
-
if (
|
|
270
|
-
let e = t ?
|
|
271
|
-
return
|
|
272
|
-
} catch (
|
|
273
|
-
if (
|
|
274
|
-
|
|
373
|
+
let n = ae(e, this.sql);
|
|
374
|
+
return b("postgres", "raw", () => this.runtime.runPromise(n));
|
|
375
|
+
}
|
|
376
|
+
async runWithEager(e, t, n = null) {
|
|
377
|
+
if (!le(e)) return this.executeQuery(e, t, n);
|
|
378
|
+
let r = n === null ? ie(e, this.sql, "postgres") : null;
|
|
379
|
+
if (r !== null) try {
|
|
380
|
+
let e = t ? i.provideService(r.fragment, k, t) : r.fragment, n = await b("postgres", "select", () => this.runtime.runPromise(e));
|
|
381
|
+
return r.decode(n);
|
|
382
|
+
} catch (t) {
|
|
383
|
+
if (t instanceof m) throw t;
|
|
384
|
+
this.reportEagerFallback({
|
|
385
|
+
dialect: "postgres",
|
|
386
|
+
table: e.table,
|
|
387
|
+
reason: "execute-failed",
|
|
388
|
+
error: t
|
|
389
|
+
});
|
|
275
390
|
}
|
|
276
|
-
|
|
391
|
+
else this.reportEagerFallback({
|
|
392
|
+
dialect: "postgres",
|
|
393
|
+
table: e.table,
|
|
394
|
+
reason: "not-compilable"
|
|
395
|
+
});
|
|
396
|
+
return h(await this.executeQuery(e, t, n), e.eager, e.sourceTable ?? S(e.table), (e) => this.executeQuery(e, t, n));
|
|
277
397
|
}
|
|
278
398
|
getInternalRunWithEager() {
|
|
279
399
|
return (e, t) => this.runWithEager(e, t);
|
|
280
400
|
}
|
|
281
|
-
async
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
401
|
+
async queryInNamespace(e, t) {
|
|
402
|
+
return this.runWithEager(t, null, e);
|
|
403
|
+
}
|
|
404
|
+
async localWrite(e, t, n) {
|
|
405
|
+
return b("postgres", e, async () => {
|
|
406
|
+
if (this.changeStrategy !== "cdc") return D(n);
|
|
407
|
+
te(t);
|
|
408
|
+
try {
|
|
409
|
+
return await D(n);
|
|
410
|
+
} finally {
|
|
411
|
+
se(t);
|
|
412
|
+
}
|
|
413
|
+
});
|
|
289
414
|
}
|
|
290
415
|
insert(e, t) {
|
|
291
|
-
return this.localWrite(e, (n) => this.executeInsert(e, t, null, null, n));
|
|
416
|
+
return this.localWrite("insert", e, (n) => this.executeInsert(e, t, null, null, n));
|
|
292
417
|
}
|
|
293
418
|
insertMany(e, t) {
|
|
294
|
-
return this.localWrite(e, (n) => this.executeInsertMany(e, t, null, null, n));
|
|
419
|
+
return this.localWrite("insert", e, (n) => this.executeInsertMany(e, t, null, null, n));
|
|
295
420
|
}
|
|
296
421
|
patchJson(e, t, n, r) {
|
|
297
|
-
return this.localWrite(e, (i) => this.executePatchJson(e, t, n, r, null, null, i));
|
|
422
|
+
return this.localWrite("update", e, (i) => this.executePatchJson(e, t, n, r, null, null, i));
|
|
298
423
|
}
|
|
299
424
|
update(e, t, n) {
|
|
300
|
-
return this.localWrite(e, (r) => this.executeUpdate(e, t, n, null, null, r));
|
|
425
|
+
return this.localWrite("update", e, (r) => this.executeUpdate(e, t, n, null, null, r));
|
|
301
426
|
}
|
|
302
427
|
delete(e, t) {
|
|
303
|
-
return this.localWrite(e, (n) => this.executeDelete(e, t, null, null, n));
|
|
428
|
+
return this.localWrite("delete", e, (n) => this.executeDelete(e, t, null, null, n));
|
|
304
429
|
}
|
|
305
430
|
async updateMany(e, t, n) {
|
|
306
|
-
return this.localWrite(e, (r) => this.executeUpdateMany(e, t, n, null, null, r));
|
|
431
|
+
return this.localWrite("update", e, (r) => this.executeUpdateMany(e, t, n, null, null, r));
|
|
307
432
|
}
|
|
308
433
|
async deleteMany(e, t) {
|
|
309
|
-
return this.localWrite(e, (n) => this.executeDeleteMany(e, t, null, null, n));
|
|
434
|
+
return this.localWrite("delete", e, (n) => this.executeDeleteMany(e, t, null, null, n));
|
|
310
435
|
}
|
|
311
|
-
async executeUpdateMany(e, t, n,
|
|
312
|
-
let s = this.sql, c =
|
|
436
|
+
async executeUpdateMany(e, t, n, r, a, o) {
|
|
437
|
+
let s = this.sql, c = _(n.where, s), l = s`UPDATE ${s(e)} SET ${s.update(v(t, e, G))} WHERE ${c} RETURNING *`, u = r ? i.provideService(l, k, r) : l, d = await this.runtime.runPromise(u);
|
|
313
438
|
for (let t of d) await this.routeEvent({
|
|
314
439
|
table: e,
|
|
315
440
|
op: "update",
|
|
316
441
|
old: null,
|
|
317
442
|
new: t
|
|
318
|
-
}, a,
|
|
443
|
+
}, a, r, o);
|
|
319
444
|
return d.length;
|
|
320
445
|
}
|
|
321
|
-
async executeDeleteMany(e, t, n,
|
|
322
|
-
let o = this.sql, s =
|
|
446
|
+
async executeDeleteMany(e, t, n, r, a) {
|
|
447
|
+
let o = this.sql, s = _(t.where, o), c = o`DELETE FROM ${o(e)} WHERE ${s} RETURNING *`, l = n ? i.provideService(c, k, n) : c, u = await this.runtime.runPromise(l);
|
|
323
448
|
for (let t of u) await this.routeEvent({
|
|
324
449
|
table: e,
|
|
325
450
|
op: "delete",
|
|
326
451
|
old: t,
|
|
327
452
|
new: null
|
|
328
|
-
},
|
|
453
|
+
}, r, n, a);
|
|
329
454
|
return u.length;
|
|
330
455
|
}
|
|
331
456
|
upsert(e, t, n) {
|
|
332
|
-
return this.localWrite(e, (r) => this.executeUpsert(e, t, n, null, null, r));
|
|
457
|
+
return this.localWrite("upsert", e, (r) => this.executeUpsert(e, t, n, null, null, r));
|
|
333
458
|
}
|
|
334
459
|
insertIgnore(e, t, n) {
|
|
335
|
-
return this.localWrite(e, (r) => this.executeInsertIgnore(e, t, n, null, null, r));
|
|
460
|
+
return this.localWrite("upsert", e, (r) => this.executeInsertIgnore(e, t, n, null, null, r));
|
|
336
461
|
}
|
|
337
462
|
emitChange(e) {
|
|
338
463
|
this.emitter.emit("change", e);
|
|
@@ -368,28 +493,13 @@ var R = (e) => e ? { rejectUnauthorized: !1 } : !1, z = /^[A-Za-z_][A-Za-z0-9_]*
|
|
|
368
493
|
return this.executeInsertIgnore.bind(this);
|
|
369
494
|
}
|
|
370
495
|
async transactional(e) {
|
|
371
|
-
this.inflightTxns
|
|
372
|
-
let t = Z(), n = 0, i = r.suspend(() => {
|
|
373
|
-
let i = ++n;
|
|
374
|
-
return this.sql.withTransaction(r.flatMap(r.serviceOption(h), (n) => {
|
|
375
|
-
if (s.isNone(n)) return r.fail(/* @__PURE__ */ Error("PostgresDataStore.transactional: TransactionConnection unexpectedly missing inside withTransaction."));
|
|
376
|
-
let a = new Q(this, n.value);
|
|
377
|
-
return r.tryPromise({
|
|
378
|
-
try: () => t(() => e(a)).then((e) => ({
|
|
379
|
-
result: e,
|
|
380
|
-
view: a,
|
|
381
|
-
attempt: i
|
|
382
|
-
})),
|
|
383
|
-
catch: (e) => e
|
|
384
|
-
});
|
|
385
|
-
}));
|
|
386
|
-
}), a = l.exponential("10 millis").pipe(l.compose(l.recurs(3)), l.whileInput(K)), o = i.pipe(r.retry(a), r.withSpan("store.transactional", { attributes: {
|
|
387
|
-
"db.system": "postgresql",
|
|
388
|
-
"db.operation": "transaction"
|
|
389
|
-
} }));
|
|
496
|
+
this.inflightTxns++;
|
|
390
497
|
try {
|
|
391
|
-
|
|
392
|
-
|
|
498
|
+
return await T({
|
|
499
|
+
...this.txnSpec("PostgresDataStore.transactional", "store.transactional", "transaction"),
|
|
500
|
+
work: e,
|
|
501
|
+
makeView: (e, t) => new J(this, e, t)
|
|
502
|
+
});
|
|
393
503
|
} finally {
|
|
394
504
|
this.inflightTxns--;
|
|
395
505
|
}
|
|
@@ -403,14 +513,10 @@ var R = (e) => e ? { rejectUnauthorized: !1 } : !1, z = /^[A-Za-z_][A-Za-z0-9_]*
|
|
|
403
513
|
return this.changeStrategy === "cdc" ? "fleet" : "local";
|
|
404
514
|
}
|
|
405
515
|
injectExternalChange(e) {
|
|
406
|
-
if (!
|
|
516
|
+
if (!y(e.table)) return;
|
|
407
517
|
let t = (e.op === "delete" ? e.old : e.new)?.id;
|
|
408
|
-
|
|
409
|
-
this.emitter.emit("change",
|
|
410
|
-
...t,
|
|
411
|
-
...e,
|
|
412
|
-
origin: "injected"
|
|
413
|
-
});
|
|
518
|
+
C(e.table, e.op, t, (t) => {
|
|
519
|
+
this.emitter.emit("change", ce(e, t));
|
|
414
520
|
});
|
|
415
521
|
}
|
|
416
522
|
run(e) {
|
|
@@ -420,28 +526,55 @@ var R = (e) => e ? { rejectUnauthorized: !1 } : !1, z = /^[A-Za-z_][A-Za-z0-9_]*
|
|
|
420
526
|
if (this.inflightTxns > 0) {
|
|
421
527
|
let t = Date.now() + e;
|
|
422
528
|
for (; this.inflightTxns > 0 && Date.now() < t;) await new Promise((e) => setTimeout(e, 25));
|
|
423
|
-
this.inflightTxns > 0 &&
|
|
529
|
+
this.inflightTxns > 0 && K.warn("close: grace period expired with in-flight transactions — forcing dispose", {
|
|
424
530
|
gracePeriodMs: e,
|
|
425
531
|
inflight: this.inflightTxns
|
|
426
532
|
});
|
|
427
533
|
}
|
|
428
|
-
this.cdcFiber &&= (await this.runtime.runPromise(
|
|
534
|
+
this.cdcFiber &&= (await this.runtime.runPromise(a.interrupt(this.cdcFiber)), null), await this.runtime.dispose();
|
|
429
535
|
}
|
|
430
536
|
async ping() {
|
|
431
537
|
await this.runtime.runPromise(this.sql`SELECT 1`);
|
|
432
538
|
}
|
|
539
|
+
readRowAsCdcJson(e, t, n) {
|
|
540
|
+
let r = this.sql, a = e === void 0 || e === "" ? r`${r(t)}` : r`${r(e)}.${r(t)}`;
|
|
541
|
+
return r`
|
|
542
|
+
SELECT row_to_json(t)::text AS ${r("payload")} FROM ${a} t WHERE t.${r("id")} = ${n} LIMIT 1
|
|
543
|
+
`.pipe(i.map((e) => {
|
|
544
|
+
let t = e[0]?.payload;
|
|
545
|
+
return t == null ? null : JSON.parse(t);
|
|
546
|
+
}));
|
|
547
|
+
}
|
|
433
548
|
async startCdcConsumer() {
|
|
434
|
-
let e = (await this.runtime.runPromise(t.PgClient)).listen(this.cdcChannel), n = (e) => {
|
|
549
|
+
let e = (await this.runtime.runPromise(t.PgClient)).listen(this.cdcChannel), n = (e) => i.suspend(() => {
|
|
550
|
+
let t;
|
|
435
551
|
try {
|
|
436
|
-
|
|
437
|
-
this.injectExternalChange(t);
|
|
552
|
+
t = JSON.parse(e);
|
|
438
553
|
} catch (e) {
|
|
439
|
-
|
|
554
|
+
return K.warn("cdc: bad payload", { channel: this.cdcChannel }, e), i.void;
|
|
440
555
|
}
|
|
441
|
-
|
|
442
|
-
|
|
556
|
+
if (t.oversized !== !0) {
|
|
557
|
+
let e = {
|
|
558
|
+
table: t.table,
|
|
559
|
+
op: t.op,
|
|
560
|
+
old: t.old,
|
|
561
|
+
new: t.new
|
|
562
|
+
};
|
|
563
|
+
return i.sync(() => {
|
|
564
|
+
this.injectExternalChange(e);
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
return y(t.table) ? be({
|
|
568
|
+
notification: t,
|
|
569
|
+
fetchRow: ({ schema: e, table: t, key: n }) => this.readRowAsCdcJson(e, t, n),
|
|
570
|
+
tunables: this.cdcRehydrate
|
|
571
|
+
}).pipe(i.map((e) => {
|
|
572
|
+
this.reportOversized(t, e), this.injectExternalChange(e.event);
|
|
573
|
+
})) : i.void;
|
|
574
|
+
});
|
|
575
|
+
this.cdcFiber = this.runtime.runFork(e.pipe(d.runForEach(n)));
|
|
443
576
|
}
|
|
444
|
-
},
|
|
577
|
+
}, J = class {
|
|
445
578
|
parent;
|
|
446
579
|
txn;
|
|
447
580
|
attr;
|
|
@@ -496,14 +629,14 @@ var R = (e) => e ? { rejectUnauthorized: !1 } : !1, z = /^[A-Za-z_][A-Za-z0-9_]*
|
|
|
496
629
|
this.events.length = 0;
|
|
497
630
|
}
|
|
498
631
|
}
|
|
499
|
-
},
|
|
632
|
+
}, Ce = class {
|
|
500
633
|
parent;
|
|
501
634
|
namespace;
|
|
502
635
|
constructor(e, t) {
|
|
503
636
|
this.parent = e, this.namespace = t;
|
|
504
637
|
}
|
|
505
638
|
query(e) {
|
|
506
|
-
return this.parent.
|
|
639
|
+
return this.parent.queryInNamespace(this.namespace, e);
|
|
507
640
|
}
|
|
508
641
|
insert(e, t) {
|
|
509
642
|
return this.parent.runInNamespace(this.namespace, (n) => n.insert(e, t));
|
|
@@ -550,39 +683,109 @@ var R = (e) => e ? { rejectUnauthorized: !1 } : !1, z = /^[A-Za-z_][A-Za-z0-9_]*
|
|
|
550
683
|
return r === void 0 ? Promise.reject(/* @__PURE__ */ Error("PostgresNamespaceView.raw: underlying store has no raw()")) : r(e, t);
|
|
551
684
|
});
|
|
552
685
|
}
|
|
553
|
-
},
|
|
686
|
+
}, Y = (e) => e.__postgresReplicationFriend ?? null, we = (e, t) => {
|
|
554
687
|
let [n, r] = e.split("/"), [i, a] = t.split("/");
|
|
555
688
|
if (!n || !r || !i || !a) throw Error(`postgres LSN compare: invalid format (${e} vs ${t})`);
|
|
556
689
|
let o = parseInt(n, 16), s = parseInt(r, 16), c = parseInt(i, 16);
|
|
557
690
|
return o === c ? s - parseInt(a, 16) : o - c;
|
|
558
|
-
},
|
|
691
|
+
}, Te = () => ({
|
|
559
692
|
async capturePrimaryPosition(e) {
|
|
560
|
-
let t =
|
|
693
|
+
let t = Y(e);
|
|
561
694
|
if (t === null) throw Error("postgresReplicationAdapter: primary is not a PostgresDataStore (missing __postgresReplicationFriend). Pass the postgres store directly.");
|
|
562
|
-
return t.runEffect(
|
|
563
|
-
let e = (yield* (yield*
|
|
564
|
-
return typeof e == "string" ? e : yield*
|
|
695
|
+
return t.runEffect(i.gen(function* () {
|
|
696
|
+
let e = (yield* (yield* O)`SELECT pg_current_wal_lsn()::text AS lsn`)[0]?.lsn;
|
|
697
|
+
return typeof e == "string" ? e : yield* i.die("postgres did not return a WAL LSN");
|
|
565
698
|
}));
|
|
566
699
|
},
|
|
567
700
|
async probeReplicaPosition(e) {
|
|
568
|
-
let t =
|
|
701
|
+
let t = Y(e);
|
|
569
702
|
if (t === null) throw Error("postgresReplicationAdapter: replica is not a PostgresDataStore.");
|
|
570
|
-
return t.runEffect(
|
|
571
|
-
let e = (yield* (yield*
|
|
703
|
+
return t.runEffect(i.gen(function* () {
|
|
704
|
+
let e = (yield* (yield* O)`
|
|
572
705
|
SELECT COALESCE(pg_last_wal_replay_lsn()::text, pg_current_wal_lsn()::text) AS lsn
|
|
573
706
|
`)[0]?.lsn;
|
|
574
|
-
return typeof e == "string" ? e : yield*
|
|
707
|
+
return typeof e == "string" ? e : yield* i.die("postgres did not return a replay LSN");
|
|
575
708
|
}));
|
|
576
709
|
},
|
|
577
710
|
compare(e, t) {
|
|
578
|
-
return
|
|
579
|
-
}
|
|
580
|
-
}),
|
|
711
|
+
return we(t, e) >= 0 ? "caught-up" : "behind";
|
|
712
|
+
}
|
|
713
|
+
}), X = (e) => `"${e.replace(/"/g, "\"\"")}"`, Ee = (e) => e.replace(/\\/g, "\\\\").replace(/\t/g, "\\t").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\v/g, "\\v").replace(/\f/g, "\\f").replace(/[\b]/g, "\\b"), De = (e) => {
|
|
714
|
+
let t = "";
|
|
715
|
+
for (let n of e) t += n.toString(16).padStart(2, "0");
|
|
716
|
+
return t;
|
|
717
|
+
}, Z = (e) => `{${e.map((e) => e == null ? "NULL" : Array.isArray(e) ? Z(e) : typeof e == "number" || typeof e == "bigint" ? String(e) : typeof e == "boolean" ? e ? "t" : "f" : `"${(e instanceof Date ? e.toISOString() : String(e)).replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`).join(",")}}`, Q = (e, t) => e == null ? null : typeof e == "string" ? e : typeof e == "number" || typeof e == "bigint" ? String(e) : typeof e == "boolean" ? e ? "t" : "f" : e instanceof Date ? e.toISOString() : e instanceof Uint8Array ? `\\x${De(e)}` : Array.isArray(e) && t === "array" ? Z(e) : JSON.stringify(e), $ = (e, t, n = {}) => t.map((t) => {
|
|
718
|
+
let r = Q(e[t], n[t]);
|
|
719
|
+
return r === null ? "\\N" : Ee(r);
|
|
720
|
+
}).join(" "), Oe = class {
|
|
721
|
+
text;
|
|
722
|
+
chunks;
|
|
723
|
+
done;
|
|
724
|
+
settled = !1;
|
|
725
|
+
rowCount = 0;
|
|
726
|
+
constructor(e, t, n) {
|
|
727
|
+
this.text = e, this.chunks = t, this.done = n;
|
|
728
|
+
}
|
|
729
|
+
settle(e) {
|
|
730
|
+
this.settled || (this.settled = !0, this.done(e, this.rowCount));
|
|
731
|
+
}
|
|
732
|
+
submit(e) {
|
|
733
|
+
e.query(this.text);
|
|
734
|
+
}
|
|
735
|
+
handleCopyInResponse(e) {
|
|
736
|
+
for (let t of this.chunks) e.sendCopyFromChunk(t);
|
|
737
|
+
e.endCopyFrom();
|
|
738
|
+
}
|
|
739
|
+
handleCommandComplete(e) {
|
|
740
|
+
let t = /COPY (\d+)/.exec(e?.text ?? "");
|
|
741
|
+
t && (this.rowCount = Number(t[1]));
|
|
742
|
+
}
|
|
743
|
+
handleRowDescription() {}
|
|
744
|
+
handleDataRow() {}
|
|
745
|
+
handleError(e) {
|
|
746
|
+
this.settle(e);
|
|
747
|
+
}
|
|
748
|
+
handleReadyForQuery() {
|
|
749
|
+
this.settle(void 0);
|
|
750
|
+
}
|
|
751
|
+
}, ke = (e) => ({
|
|
752
|
+
...e.url ? { connectionString: e.url } : {
|
|
753
|
+
host: e.host ?? "localhost",
|
|
754
|
+
port: e.port ?? 5432,
|
|
755
|
+
user: e.username ?? "postgres",
|
|
756
|
+
password: e.password ?? "",
|
|
757
|
+
database: e.database ?? "postgres"
|
|
758
|
+
},
|
|
759
|
+
...e.ssl === !0 ? { ssl: { rejectUnauthorized: !1 } } : {}
|
|
760
|
+
}), Ae = 64 * 1024, je = (e) => {
|
|
761
|
+
let t, n, r = () => t ? Promise.resolve(t) : (n ??= (async () => {
|
|
762
|
+
let n = new f.Client(ke(e));
|
|
763
|
+
return await n.connect(), t = n, n;
|
|
764
|
+
})(), n);
|
|
765
|
+
return {
|
|
766
|
+
dialect: "postgres",
|
|
767
|
+
copyInto: async ({ table: e, columns: t, columnTypes: n, rows: i }) => {
|
|
768
|
+
if (i.length === 0) return 0;
|
|
769
|
+
let a = await r(), o = `COPY ${X(e)} (${t.map(X).join(", ")}) FROM STDIN`, s = [], c = "";
|
|
770
|
+
for (let e of i) c += $(e, t, n ?? {}), c += "\n", c.length >= Ae && (s.push(Buffer.from(c, "utf8")), c = "");
|
|
771
|
+
return c.length > 0 && s.push(Buffer.from(c, "utf8")), await new Promise((e, t) => {
|
|
772
|
+
let n = new Oe(o, s, (n, r) => {
|
|
773
|
+
n ? t(n) : e(r);
|
|
774
|
+
});
|
|
775
|
+
a.query(n);
|
|
776
|
+
});
|
|
777
|
+
},
|
|
778
|
+
close: async () => {
|
|
779
|
+
let e = t;
|
|
780
|
+
t = void 0, n = void 0, e && await e.end().catch(() => void 0);
|
|
781
|
+
}
|
|
782
|
+
};
|
|
783
|
+
}, Me = {
|
|
581
784
|
id: "postgres",
|
|
582
|
-
makeSqlLayer: (e) =>
|
|
583
|
-
makeStore: (e) =>
|
|
785
|
+
makeSqlLayer: (e) => L(e),
|
|
786
|
+
makeStore: (e) => q(e),
|
|
584
787
|
compileContains: (e, t, n) => n`${e} ILIKE ${`%${t.replace(/[\\%_]/g, (e) => `\\${e}`)}%`} ESCAPE '\\'`,
|
|
585
|
-
retryFilter:
|
|
788
|
+
retryFilter: B
|
|
586
789
|
};
|
|
587
790
|
//#endregion
|
|
588
|
-
export { e as PgClient,
|
|
791
|
+
export { e as PgClient, I as connectionFromConfig, $ as encodeCopyRow, Q as encodeCopyValue, je as makePgCopySession, q as makePostgresDataStore, P as makePostgresSqlLayer, L as makePostgresSqlLayerFromConfig, Me as postgresDialect, Te as postgresReplicationAdapter, B as postgresRetryFilter };
|