@aiao/rxdb-adapter-electron 0.0.0-stage → 0.0.28
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/LICENSE +21 -0
- package/README.md +394 -2
- package/dist/RxDBAdapterElectron.d.ts +61 -0
- package/dist/RxDBAdapterElectron.d.ts.map +1 -0
- package/dist/electron-adapter.interface.d.ts +23 -0
- package/dist/electron-adapter.interface.d.ts.map +1 -0
- package/dist/electron-file-host.d.ts +52 -0
- package/dist/electron-file-host.d.ts.map +1 -0
- package/dist/electron-sqlite-host.d.ts +65 -0
- package/dist/electron-sqlite-host.d.ts.map +1 -0
- package/dist/host.d.ts +19 -0
- package/dist/host.d.ts.map +1 -0
- package/dist/host.js +768 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +36 -0
- package/dist/node-sqlite-engine.d.ts +97 -0
- package/dist/node-sqlite-engine.d.ts.map +1 -0
- package/dist/pglite/RxDBAdapterElectronPGlite.d.ts +96 -0
- package/dist/pglite/RxDBAdapterElectronPGlite.d.ts.map +1 -0
- package/dist/pglite/desktop-pglite-client.d.ts +144 -0
- package/dist/pglite/desktop-pglite-client.d.ts.map +1 -0
- package/dist/pglite/desktop-pglite-results.d.ts +14 -0
- package/dist/pglite/desktop-pglite-results.d.ts.map +1 -0
- package/dist/pglite/electron-pglite-backup-error.d.ts +32 -0
- package/dist/pglite/electron-pglite-backup-error.d.ts.map +1 -0
- package/dist/pglite/pglite-adapter.interface.d.ts +68 -0
- package/dist/pglite/pglite-adapter.interface.d.ts.map +1 -0
- package/dist/pglite/restore-electron-pglite-database.d.ts +68 -0
- package/dist/pglite/restore-electron-pglite-database.d.ts.map +1 -0
- package/dist/pglite-host/electron-pglite-host.d.ts +129 -0
- package/dist/pglite-host/electron-pglite-host.d.ts.map +1 -0
- package/dist/pglite-host/pglite-host-data-dir.d.ts +75 -0
- package/dist/pglite-host/pglite-host-data-dir.d.ts.map +1 -0
- package/dist/pglite-host/pglite-host-lock.d.ts +48 -0
- package/dist/pglite-host/pglite-host-lock.d.ts.map +1 -0
- package/dist/pglite-host/pglite-host-restore.d.ts +38 -0
- package/dist/pglite-host/pglite-host-restore.d.ts.map +1 -0
- package/dist/pglite-host/pglite-host-runtime.d.ts +90 -0
- package/dist/pglite-host/pglite-host-runtime.d.ts.map +1 -0
- package/dist/pglite-host.d.ts +17 -0
- package/dist/pglite-host.d.ts.map +1 -0
- package/dist/pglite-host.js +738 -0
- package/dist/pglite.d.ts +22 -0
- package/dist/pglite.d.ts.map +1 -0
- package/dist/pglite.js +493 -0
- package/dist/sqlite-script.d.ts +26 -0
- package/dist/sqlite-script.d.ts.map +1 -0
- package/package.json +94 -3
- package/src/RxDBAdapterElectron.ts +105 -0
- package/src/electron-adapter.interface.ts +25 -0
- package/src/electron-file-host.ts +758 -0
- package/src/electron-sqlite-host.ts +301 -0
- package/src/host.ts +64 -0
- package/src/index.ts +71 -0
- package/src/node-sqlite-engine.ts +631 -0
- package/src/pglite/RxDBAdapterElectronPGlite.ts +152 -0
- package/src/pglite/desktop-pglite-client.ts +614 -0
- package/src/pglite/desktop-pglite-results.ts +24 -0
- package/src/pglite/electron-pglite-backup-error.ts +128 -0
- package/src/pglite/pglite-adapter.interface.ts +78 -0
- package/src/pglite/restore-electron-pglite-database.ts +429 -0
- package/src/pglite-host/electron-pglite-host.ts +829 -0
- package/src/pglite-host/pglite-host-data-dir.ts +224 -0
- package/src/pglite-host/pglite-host-lock.ts +154 -0
- package/src/pglite-host/pglite-host-restore.ts +460 -0
- package/src/pglite-host/pglite-host-runtime.ts +166 -0
- package/src/pglite-host.ts +50 -0
- package/src/pglite.ts +51 -0
- package/src/sqlite-script.ts +134 -0
|
@@ -0,0 +1,738 @@
|
|
|
1
|
+
import { DESKTOP_PGLITE_DEFAULT_BEGIN_TIMEOUT_MS as e, DESKTOP_PGLITE_EXCLUDED_FILES as t, DESKTOP_PGLITE_EXCLUDED_FILES as n, DESKTOP_PGLITE_MAX_BEGIN_TIMEOUT_MS as r, DESKTOP_PGLITE_MAX_DATA_CHUNK_BYTES as i, DESKTOP_PGLITE_MAX_DATA_CHUNK_BYTES as a, DESKTOP_PGLITE_PROTOCOL_VERSION as o, DESKTOP_PGLITE_PROTOCOL_VERSION as s, RxDBAdapterDesktopError as c, RxDBAdapterDesktopError as l, assertValidDesktopDatabaseName as u, isDesktopPgliteRequestKind as d, parseDesktopPgliteRequest as f, parseDesktopPgliteRequest as p } from "@aiao/rxdb-adapter-sqlite-core/desktop-host";
|
|
2
|
+
import { randomUUID as m } from "node:crypto";
|
|
3
|
+
import { DatabaseSync as h } from "node:sqlite";
|
|
4
|
+
import { lstat as g, mkdir as _, open as v, readdir as y, rm as b } from "node:fs/promises";
|
|
5
|
+
import { basename as x, dirname as S, join as C } from "node:path";
|
|
6
|
+
import { mkdirSync as w } from "node:fs";
|
|
7
|
+
//#region src/pglite-host/pglite-host-data-dir.ts
|
|
8
|
+
var T = /* @__PURE__ */ new Map([
|
|
9
|
+
["ENOSPC", "disk_full"],
|
|
10
|
+
["EDQUOT", "disk_full"],
|
|
11
|
+
["EACCES", "permission_denied"],
|
|
12
|
+
["EPERM", "permission_denied"],
|
|
13
|
+
["EROFS", "permission_denied"],
|
|
14
|
+
["ENOENT", "file_not_found"]
|
|
15
|
+
]), E = (e) => {
|
|
16
|
+
let t = e?.code;
|
|
17
|
+
return typeof t == "string" ? t : void 0;
|
|
18
|
+
}, D = (e, t) => {
|
|
19
|
+
if (e instanceof l) return e;
|
|
20
|
+
let n = T.get(E(e) ?? "") ?? "host_internal_error";
|
|
21
|
+
return new l(n, t, { cause: e });
|
|
22
|
+
}, O = async (e) => (await y(e)).filter((e) => !n.has(e)).sort();
|
|
23
|
+
async function* k(e, t, n) {
|
|
24
|
+
let r = await v(e, "r");
|
|
25
|
+
try {
|
|
26
|
+
let e = 0;
|
|
27
|
+
for (; e < t;) {
|
|
28
|
+
let i = new Uint8Array(Math.min(a, t - e)), { bytesRead: o } = await r.read(i, 0, i.length, e);
|
|
29
|
+
if (o <= 0) throw new l("host_internal_error", `data file shrank while being read: ${n}`);
|
|
30
|
+
yield {
|
|
31
|
+
type: "data",
|
|
32
|
+
bytes: o === i.length ? i : i.slice(0, o)
|
|
33
|
+
}, e += o;
|
|
34
|
+
}
|
|
35
|
+
} finally {
|
|
36
|
+
await r.close();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async function* A(e, t) {
|
|
40
|
+
for (let n of await O(e)) {
|
|
41
|
+
let r = C(e, n), i = t === "" ? n : `${t}/${n}`, a = await g(r);
|
|
42
|
+
if (a.isDirectory()) {
|
|
43
|
+
yield {
|
|
44
|
+
type: "entry",
|
|
45
|
+
header: {
|
|
46
|
+
path: i,
|
|
47
|
+
kind: "directory",
|
|
48
|
+
size: 0
|
|
49
|
+
}
|
|
50
|
+
}, yield* A(r, i);
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (!a.isFile()) throw new l("host_internal_error", `unsupported file type in the data directory: ${i}`);
|
|
54
|
+
yield {
|
|
55
|
+
type: "entry",
|
|
56
|
+
header: {
|
|
57
|
+
path: i,
|
|
58
|
+
kind: "file",
|
|
59
|
+
size: a.size
|
|
60
|
+
}
|
|
61
|
+
}, yield* k(r, a.size, i);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async function* ee(e) {
|
|
65
|
+
try {
|
|
66
|
+
yield* A(e, "");
|
|
67
|
+
} catch (e) {
|
|
68
|
+
throw D(e, "failed to read the PGlite data directory");
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
var j = async (e) => {
|
|
72
|
+
try {
|
|
73
|
+
return (await y(e)).length === 0;
|
|
74
|
+
} catch (e) {
|
|
75
|
+
let t = E(e);
|
|
76
|
+
if (t === "ENOENT") return !0;
|
|
77
|
+
if (t === "ENOTDIR") return !1;
|
|
78
|
+
throw D(e, "failed to inspect the restore target");
|
|
79
|
+
}
|
|
80
|
+
}, M = async (e) => {
|
|
81
|
+
try {
|
|
82
|
+
return (await g(C(e, "PG_VERSION"))).isFile();
|
|
83
|
+
} catch (e) {
|
|
84
|
+
if (E(e) === "ENOENT") return !1;
|
|
85
|
+
throw D(e, "failed to inspect the PGlite data directory");
|
|
86
|
+
}
|
|
87
|
+
}, N = async (e, t) => {
|
|
88
|
+
let n = await v(e, t);
|
|
89
|
+
try {
|
|
90
|
+
await n.sync();
|
|
91
|
+
} finally {
|
|
92
|
+
await n.close();
|
|
93
|
+
}
|
|
94
|
+
}, P = async (e) => {
|
|
95
|
+
process.platform !== "win32" && await N(e, "r");
|
|
96
|
+
}, F = async (e) => {
|
|
97
|
+
for (let t of await y(e)) {
|
|
98
|
+
let n = C(e, t);
|
|
99
|
+
(await g(n)).isDirectory() ? await F(n) : await N(n, "r+");
|
|
100
|
+
}
|
|
101
|
+
await P(e);
|
|
102
|
+
}, I = async (e) => {
|
|
103
|
+
try {
|
|
104
|
+
await F(e), await P(S(e));
|
|
105
|
+
} catch (e) {
|
|
106
|
+
throw D(e, "failed to persist the restored PGlite data directory");
|
|
107
|
+
}
|
|
108
|
+
}, L = async (e) => {
|
|
109
|
+
try {
|
|
110
|
+
await b(e, {
|
|
111
|
+
recursive: !0,
|
|
112
|
+
force: !0,
|
|
113
|
+
maxRetries: 3
|
|
114
|
+
});
|
|
115
|
+
} catch (e) {
|
|
116
|
+
throw D(e, "failed to remove the PGlite data directory");
|
|
117
|
+
}
|
|
118
|
+
}, R = (e) => C(S(e), `.${x(e)}.rxdb-lock`), z = "\n PRAGMA busy_timeout = 0;\n PRAGMA locking_mode = EXCLUSIVE;\n PRAGMA journal_mode = DELETE;\n PRAGMA synchronous = FULL;\n BEGIN EXCLUSIVE;\n CREATE TABLE IF NOT EXISTS holder (id INTEGER PRIMARY KEY, pid INTEGER NOT NULL);\n CREATE TABLE IF NOT EXISTS restore_marker (id INTEGER PRIMARY KEY, created_at TEXT NOT NULL);\n", B = /* @__PURE__ */ new Map([
|
|
119
|
+
[3, "permission_denied"],
|
|
120
|
+
[5, "database_busy"],
|
|
121
|
+
[6, "database_busy"],
|
|
122
|
+
[8, "permission_denied"],
|
|
123
|
+
[13, "disk_full"],
|
|
124
|
+
[23, "permission_denied"]
|
|
125
|
+
]), V = (e, t, n) => {
|
|
126
|
+
let r = e?.errcode, i = typeof r == "number" ? B.get(r & 255) : void 0;
|
|
127
|
+
return new l(i ?? t, n, { cause: e });
|
|
128
|
+
}, H = (e, t) => {
|
|
129
|
+
try {
|
|
130
|
+
w(S(e), {
|
|
131
|
+
recursive: !0,
|
|
132
|
+
mode: 448
|
|
133
|
+
});
|
|
134
|
+
} catch (e) {
|
|
135
|
+
throw D(e, "failed to create the parent of the PGlite data directory");
|
|
136
|
+
}
|
|
137
|
+
try {
|
|
138
|
+
return new h(e);
|
|
139
|
+
} catch (e) {
|
|
140
|
+
throw V(e, "open_failed", `failed to open the lock of PGlite data directory "${x(t)}"`);
|
|
141
|
+
}
|
|
142
|
+
}, U = (e) => {
|
|
143
|
+
let t = H(R(e), e);
|
|
144
|
+
try {
|
|
145
|
+
t.exec(z), t.prepare("INSERT OR REPLACE INTO holder (id, pid) VALUES (1, ?)").run(process.pid), t.exec("COMMIT");
|
|
146
|
+
} catch (n) {
|
|
147
|
+
throw t.close(), V(n, "open_failed", `failed to lock PGlite data directory "${x(e)}"`);
|
|
148
|
+
}
|
|
149
|
+
let n = !1, r = (e, t) => {
|
|
150
|
+
try {
|
|
151
|
+
return e();
|
|
152
|
+
} catch (e) {
|
|
153
|
+
throw V(e, "host_internal_error", t);
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
return {
|
|
157
|
+
hasMarker: () => r(() => t.prepare("SELECT 1 FROM restore_marker LIMIT 1").get() !== void 0, "failed to read the restore marker"),
|
|
158
|
+
markRestoring: () => r(() => {
|
|
159
|
+
t.prepare("INSERT OR REPLACE INTO restore_marker (id, created_at) VALUES (1, ?)").run((/* @__PURE__ */ new Date()).toISOString());
|
|
160
|
+
}, "failed to persist the restore marker"),
|
|
161
|
+
clearRestoring: () => r(() => {
|
|
162
|
+
t.exec("DELETE FROM restore_marker");
|
|
163
|
+
}, "failed to remove the restore marker"),
|
|
164
|
+
release: () => {
|
|
165
|
+
n || (n = !0, t.close());
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
}, W = (e) => ({
|
|
169
|
+
rows: e.rows,
|
|
170
|
+
fields: e.fields.map((e) => ({
|
|
171
|
+
name: e.name,
|
|
172
|
+
dataTypeID: e.dataTypeID
|
|
173
|
+
})),
|
|
174
|
+
affectedRows: e.affectedRows
|
|
175
|
+
}), G = async (e) => {
|
|
176
|
+
try {
|
|
177
|
+
return await e();
|
|
178
|
+
} catch (e) {
|
|
179
|
+
throw e instanceof l ? e : new l("statement_failed", e instanceof Error ? e.message : String(e), { cause: e });
|
|
180
|
+
}
|
|
181
|
+
}, K = Symbol("transaction begin timed out"), q = async (e, t) => {
|
|
182
|
+
let n;
|
|
183
|
+
try {
|
|
184
|
+
return await Promise.race([e, new Promise((e) => {
|
|
185
|
+
n = setTimeout(() => e(K), t);
|
|
186
|
+
})]);
|
|
187
|
+
} finally {
|
|
188
|
+
clearTimeout(n);
|
|
189
|
+
}
|
|
190
|
+
}, J = async (e, t) => {
|
|
191
|
+
let n, r = new Promise((e, t) => {
|
|
192
|
+
n = {
|
|
193
|
+
resolve: e,
|
|
194
|
+
reject: t
|
|
195
|
+
};
|
|
196
|
+
});
|
|
197
|
+
r.catch(() => void 0);
|
|
198
|
+
let i, a = new Promise((e) => {
|
|
199
|
+
i = e;
|
|
200
|
+
}), o = e.transaction(async (e) => {
|
|
201
|
+
i(e), await r;
|
|
202
|
+
});
|
|
203
|
+
o.catch(() => void 0);
|
|
204
|
+
let s = await q(a, t);
|
|
205
|
+
if (s === K) throw n.reject(new l("transaction_unavailable", "the begin that opened this transaction timed out")), new l("transaction_unavailable", `waited ${t}ms for the PGlite connection but another transaction still holds it`);
|
|
206
|
+
return {
|
|
207
|
+
tx: s,
|
|
208
|
+
settle: n,
|
|
209
|
+
finished: o
|
|
210
|
+
};
|
|
211
|
+
}, Y = /* @__PURE__ */ new Set([
|
|
212
|
+
"EEXIST",
|
|
213
|
+
"ENOENT",
|
|
214
|
+
"ENOTDIR"
|
|
215
|
+
]), X = (e, t) => new l("database_corrupted", e, t), te = (e) => e instanceof l ? e : Y.has(E(e) ?? "") ? X("the archive does not describe a valid directory tree", { cause: e }) : D(e, "failed to write the restored PGlite data directory"), Z = (e, t) => new l("protocol_violation", `${t} is not allowed while the restore is ${e.stage}`), Q = (e, t, n) => {
|
|
216
|
+
if (e.stage !== t) throw Z(e, n);
|
|
217
|
+
}, ne = async (e, t) => {
|
|
218
|
+
let n = e.file;
|
|
219
|
+
if (n === void 0) throw X("a data chunk arrived without a file entry");
|
|
220
|
+
if (n.written + t.byteLength > n.size) throw X(`the data of "${n.path}" exceeds its declared size`);
|
|
221
|
+
await n.handle.writeFile(t), n.written += t.byteLength, !(n.written < n.size) && (e.file = void 0, await n.handle.close());
|
|
222
|
+
}, re = async (e, t) => {
|
|
223
|
+
if (e.file !== void 0) throw X(`the data of "${e.file.path}" is incomplete`);
|
|
224
|
+
let n = C(e.directory, ...t.path.split("/"));
|
|
225
|
+
if (t.kind === "directory") {
|
|
226
|
+
await _(n, { mode: 448 });
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
let r = await v(n, "wx", 384);
|
|
230
|
+
if (t.size === 0) {
|
|
231
|
+
await r.close();
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
e.file = {
|
|
235
|
+
handle: r,
|
|
236
|
+
path: t.path,
|
|
237
|
+
size: t.size,
|
|
238
|
+
written: 0
|
|
239
|
+
};
|
|
240
|
+
}, ie = (e) => {
|
|
241
|
+
let t = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Map(), r = async (n, r) => {
|
|
242
|
+
if (await e.isInUse(n) || t.has(n)) throw new l("database_busy", `"${n}" is open or being restored in this host`);
|
|
243
|
+
t.add(n);
|
|
244
|
+
try {
|
|
245
|
+
return U(r);
|
|
246
|
+
} catch (e) {
|
|
247
|
+
throw t.delete(n), e;
|
|
248
|
+
}
|
|
249
|
+
}, i = (e, n) => {
|
|
250
|
+
t.delete(e), n.release();
|
|
251
|
+
}, a = async (e, t, n) => {
|
|
252
|
+
try {
|
|
253
|
+
await L(t), n.clearRestoring();
|
|
254
|
+
} catch (t) {
|
|
255
|
+
throw new l("cleanup_pending", `the incomplete restore of "${e}" could not be removed; run pg.restore.cleanup to retry`, { cause: t });
|
|
256
|
+
}
|
|
257
|
+
}, o = async (t, a) => {
|
|
258
|
+
let o = t.storage.dataDirectoryName, s = e.resolveDataDirectory(o), c = await r(o, s);
|
|
259
|
+
try {
|
|
260
|
+
if (c.hasMarker()) throw new l("restore_incomplete", `a restore of "${o}" did not finish; run pg.restore.cleanup first`);
|
|
261
|
+
if (!await j(s)) throw new l("target_not_empty", `"${o}" already holds data`);
|
|
262
|
+
} catch (e) {
|
|
263
|
+
throw i(o, c), e;
|
|
264
|
+
}
|
|
265
|
+
let u = m();
|
|
266
|
+
return n.set(u, {
|
|
267
|
+
id: u,
|
|
268
|
+
owner: a,
|
|
269
|
+
dataDirectoryName: o,
|
|
270
|
+
directory: s,
|
|
271
|
+
lock: c,
|
|
272
|
+
stage: "begun",
|
|
273
|
+
marked: !1,
|
|
274
|
+
file: void 0,
|
|
275
|
+
runtime: void 0,
|
|
276
|
+
tail: Promise.resolve(),
|
|
277
|
+
finished: !1
|
|
278
|
+
}), {
|
|
279
|
+
kind: "pg.restore.begin",
|
|
280
|
+
result: { restoreId: u }
|
|
281
|
+
};
|
|
282
|
+
}, s = async (t) => {
|
|
283
|
+
let n = t.storage.dataDirectoryName, o = e.resolveDataDirectory(n), s = await r(n, o);
|
|
284
|
+
try {
|
|
285
|
+
return s.hasMarker() ? (await a(n, o, s), {
|
|
286
|
+
kind: "pg.restore.cleanup",
|
|
287
|
+
result: { cleaned: !0 }
|
|
288
|
+
}) : {
|
|
289
|
+
kind: "pg.restore.cleanup",
|
|
290
|
+
result: { cleaned: !1 }
|
|
291
|
+
};
|
|
292
|
+
} finally {
|
|
293
|
+
i(n, s);
|
|
294
|
+
}
|
|
295
|
+
}, c = (e, t) => {
|
|
296
|
+
let r = n.get(e);
|
|
297
|
+
if (r === void 0) throw new l("transaction_not_found", `restore ${e} is unknown or already finished`);
|
|
298
|
+
if (r.owner !== t) throw new l("permission_denied", `restore ${e} belongs to another window`);
|
|
299
|
+
return r;
|
|
300
|
+
}, u = (e, t) => {
|
|
301
|
+
let n = e.tail.then(() => {
|
|
302
|
+
if (e.finished) throw new l("transaction_not_found", `restore ${e.id} is already finished`);
|
|
303
|
+
return t();
|
|
304
|
+
});
|
|
305
|
+
return e.tail = n.then(() => void 0, () => void 0), n;
|
|
306
|
+
}, d = async (e) => {
|
|
307
|
+
let { file: t, runtime: n } = e;
|
|
308
|
+
e.file = void 0, e.runtime = void 0, await t?.handle.close().catch(() => void 0), await n?.close().catch(() => void 0);
|
|
309
|
+
}, f = async (e, t) => {
|
|
310
|
+
try {
|
|
311
|
+
await t();
|
|
312
|
+
} catch (t) {
|
|
313
|
+
throw t instanceof l && t.code === "protocol_violation" || (e.stage = "failed", await d(e)), t;
|
|
314
|
+
}
|
|
315
|
+
}, p = (e) => {
|
|
316
|
+
e.finished = !0, n.delete(e.id), i(e.dataDirectoryName, e.lock);
|
|
317
|
+
}, h = async (e) => {
|
|
318
|
+
Q(e, "begun", "pg.restore.prepare"), e.lock.markRestoring(), e.marked = !0;
|
|
319
|
+
try {
|
|
320
|
+
await _(e.directory, {
|
|
321
|
+
recursive: !0,
|
|
322
|
+
mode: 448
|
|
323
|
+
});
|
|
324
|
+
} catch (e) {
|
|
325
|
+
throw D(e, "failed to create the restore target");
|
|
326
|
+
}
|
|
327
|
+
e.stage = "prepared";
|
|
328
|
+
}, g = async (e, t) => {
|
|
329
|
+
Q(e, "prepared", "pg.restore.write");
|
|
330
|
+
try {
|
|
331
|
+
await (t.type === "data" ? ne(e, t.bytes) : re(e, t.header));
|
|
332
|
+
} catch (e) {
|
|
333
|
+
throw te(e);
|
|
334
|
+
}
|
|
335
|
+
}, v = async (t) => {
|
|
336
|
+
let n;
|
|
337
|
+
try {
|
|
338
|
+
return n = await e.createRuntime(t), await n.query("SELECT 1"), n;
|
|
339
|
+
} catch (e) {
|
|
340
|
+
throw await n?.close().catch(() => void 0), X("the restored data directory cannot be opened", { cause: e });
|
|
341
|
+
}
|
|
342
|
+
}, y = async (e) => {
|
|
343
|
+
if (Q(e, "prepared", "pg.restore.open"), e.file !== void 0) throw X(`the data of "${e.file.path}" is incomplete`);
|
|
344
|
+
if (!await M(e.directory)) throw X("the archive has no PG_VERSION");
|
|
345
|
+
e.runtime = await v(e.dataDirectoryName), e.stage = "opened";
|
|
346
|
+
}, b = (e, t) => {
|
|
347
|
+
let n = e.runtime;
|
|
348
|
+
if (n === void 0) throw Z(e, t);
|
|
349
|
+
return n;
|
|
350
|
+
}, x = async (e, t) => {
|
|
351
|
+
let n = b(e, t.kind);
|
|
352
|
+
return W(await G(() => n.query(t.sql, [...t.params])));
|
|
353
|
+
}, S = async (e) => {
|
|
354
|
+
let t = b(e, "pg.restore.persist");
|
|
355
|
+
e.runtime = void 0;
|
|
356
|
+
try {
|
|
357
|
+
await t.close();
|
|
358
|
+
} catch (e) {
|
|
359
|
+
throw D(e, "failed to close the restored PGlite instance");
|
|
360
|
+
}
|
|
361
|
+
await I(e.directory), e.stage = "persisted";
|
|
362
|
+
}, C = (e) => {
|
|
363
|
+
Q(e, "persisted", "pg.restore.commit"), e.lock.clearRestoring(), p(e);
|
|
364
|
+
}, w = async (e) => {
|
|
365
|
+
try {
|
|
366
|
+
await d(e), e.marked && await a(e.dataDirectoryName, e.directory, e.lock);
|
|
367
|
+
} finally {
|
|
368
|
+
p(e);
|
|
369
|
+
}
|
|
370
|
+
}, T = (e) => u(e, async () => {
|
|
371
|
+
await d(e), p(e);
|
|
372
|
+
}).catch(() => void 0), E = async (e, t) => {
|
|
373
|
+
switch (t.kind) {
|
|
374
|
+
case "pg.restore.prepare": return await f(e, () => h(e)), { kind: "pg.restore.prepare" };
|
|
375
|
+
case "pg.restore.write": return await f(e, () => g(e, t.item)), { kind: "pg.restore.write" };
|
|
376
|
+
case "pg.restore.open": return await f(e, () => y(e)), { kind: "pg.restore.open" };
|
|
377
|
+
case "pg.restore.query": return {
|
|
378
|
+
kind: "pg.restore.query",
|
|
379
|
+
result: await x(e, t)
|
|
380
|
+
};
|
|
381
|
+
case "pg.restore.persist": return await f(e, () => S(e)), { kind: "pg.restore.persist" };
|
|
382
|
+
case "pg.restore.commit": return await f(e, async () => C(e)), { kind: "pg.restore.commit" };
|
|
383
|
+
case "pg.restore.abort": return await w(e), { kind: "pg.restore.abort" };
|
|
384
|
+
default: throw new l("protocol_violation", `unsupported restore request kind: ${String(t.kind)}`);
|
|
385
|
+
}
|
|
386
|
+
}, O = async (e, t) => {
|
|
387
|
+
let n = c(e.restoreId, t);
|
|
388
|
+
return u(n, () => E(n, e));
|
|
389
|
+
};
|
|
390
|
+
return {
|
|
391
|
+
get openCount() {
|
|
392
|
+
return n.size;
|
|
393
|
+
},
|
|
394
|
+
isReserved: (e) => t.has(e),
|
|
395
|
+
handle: async (e, t) => {
|
|
396
|
+
switch (e.kind) {
|
|
397
|
+
case "pg.restore.begin": return o(e, t);
|
|
398
|
+
case "pg.restore.cleanup": return s(e);
|
|
399
|
+
default: return O(e, t);
|
|
400
|
+
}
|
|
401
|
+
},
|
|
402
|
+
releaseOwner: async (e) => {
|
|
403
|
+
await Promise.all([...n.values()].filter((t) => t.owner === e).map(T));
|
|
404
|
+
},
|
|
405
|
+
closeAll: async () => {
|
|
406
|
+
await Promise.all([...n.values()].map(T));
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
}, ae = "desktop-pglite://app-scope", $ = Object.freeze([
|
|
410
|
+
"rxdb_change_notify",
|
|
411
|
+
"rxdb_branch_notify",
|
|
412
|
+
"rxdb_migration_notify"
|
|
413
|
+
]), oe = (e) => e instanceof l ? {
|
|
414
|
+
kind: "error",
|
|
415
|
+
code: e.code,
|
|
416
|
+
message: e.detail
|
|
417
|
+
} : {
|
|
418
|
+
kind: "error",
|
|
419
|
+
code: "host_internal_error",
|
|
420
|
+
message: e instanceof Error ? e.message : String(e)
|
|
421
|
+
}, se = (e, t) => new l("open_failed", `the application could not open a PGlite runtime for ${e}`, { cause: t });
|
|
422
|
+
function ce(e) {
|
|
423
|
+
let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Map(), o, c = async (e) => {
|
|
424
|
+
for (; a.has(e);) await a.get(e);
|
|
425
|
+
return t.has(e);
|
|
426
|
+
}, u = e.backup, d = u === void 0 ? void 0 : {
|
|
427
|
+
options: u,
|
|
428
|
+
extensions: [...new Set(u.extensions)].sort(),
|
|
429
|
+
restores: ie({
|
|
430
|
+
createRuntime: (t) => e.createRuntime(t),
|
|
431
|
+
resolveDataDirectory: (e) => u.resolveDataDirectory(e),
|
|
432
|
+
isInUse: c
|
|
433
|
+
})
|
|
434
|
+
}, f = (t, n, r) => {
|
|
435
|
+
try {
|
|
436
|
+
e.postNotify({
|
|
437
|
+
kind: "pg.notify",
|
|
438
|
+
sessionId: t,
|
|
439
|
+
channel: n,
|
|
440
|
+
payload: r
|
|
441
|
+
});
|
|
442
|
+
} catch (t) {
|
|
443
|
+
e.onDeliveryError?.(t);
|
|
444
|
+
}
|
|
445
|
+
}, h = (e) => {
|
|
446
|
+
if (d === void 0) return;
|
|
447
|
+
let t = U(d.options.resolveDataDirectory(e)), n;
|
|
448
|
+
try {
|
|
449
|
+
n = t.hasMarker();
|
|
450
|
+
} catch (e) {
|
|
451
|
+
throw t.release(), e;
|
|
452
|
+
}
|
|
453
|
+
if (!n) return t;
|
|
454
|
+
throw t.release(), new l("restore_incomplete", `a restore of "${e}" did not finish; run pg.restore.cleanup before connecting`);
|
|
455
|
+
}, g = async (e, t) => {
|
|
456
|
+
for (let n of $) await e.listen(n, (e) => {
|
|
457
|
+
for (let r of t) f(r, n, e);
|
|
458
|
+
});
|
|
459
|
+
}, _ = async (t, n) => {
|
|
460
|
+
let r;
|
|
461
|
+
try {
|
|
462
|
+
r = await e.createRuntime(t);
|
|
463
|
+
} catch (e) {
|
|
464
|
+
throw se(t, e);
|
|
465
|
+
}
|
|
466
|
+
try {
|
|
467
|
+
await g(r, n);
|
|
468
|
+
} catch (e) {
|
|
469
|
+
throw await r.close().catch(() => void 0), se(t, e);
|
|
470
|
+
}
|
|
471
|
+
return r;
|
|
472
|
+
}, v = async (e, t) => {
|
|
473
|
+
let n = h(e);
|
|
474
|
+
try {
|
|
475
|
+
return {
|
|
476
|
+
runtime: await _(e, t),
|
|
477
|
+
lock: n
|
|
478
|
+
};
|
|
479
|
+
} catch (e) {
|
|
480
|
+
throw n?.release(), e;
|
|
481
|
+
}
|
|
482
|
+
}, y = (e) => {
|
|
483
|
+
let t = /* @__PURE__ */ new Set();
|
|
484
|
+
return {
|
|
485
|
+
sessions: t,
|
|
486
|
+
pending: 0,
|
|
487
|
+
ready: v(e, t)
|
|
488
|
+
};
|
|
489
|
+
}, b = async (e) => {
|
|
490
|
+
let { runtime: t, lock: n } = await e.ready;
|
|
491
|
+
try {
|
|
492
|
+
await t.close();
|
|
493
|
+
} finally {
|
|
494
|
+
n?.release();
|
|
495
|
+
}
|
|
496
|
+
}, x = async (e, n) => {
|
|
497
|
+
t.delete(e);
|
|
498
|
+
let r = b(n), i = r.then(() => void 0, () => void 0);
|
|
499
|
+
a.set(e, i);
|
|
500
|
+
try {
|
|
501
|
+
await r;
|
|
502
|
+
} finally {
|
|
503
|
+
a.get(e) === i && a.delete(e);
|
|
504
|
+
}
|
|
505
|
+
}, S = (e, t) => {
|
|
506
|
+
let r = n.get(e);
|
|
507
|
+
if (!r) throw new l("session_closed", `session ${e} is not open on this host`);
|
|
508
|
+
if (r.owner !== t) throw new l("permission_denied", `session ${e} belongs to another window`);
|
|
509
|
+
return r;
|
|
510
|
+
}, C = async (e) => {
|
|
511
|
+
let n = t.get(e.dataDirectoryName);
|
|
512
|
+
if (!n) throw new l("host_internal_error", `session references a released instance for ${e.dataDirectoryName}`);
|
|
513
|
+
return (await n.ready).runtime;
|
|
514
|
+
}, w = (e, t) => {
|
|
515
|
+
let n = r.get(e);
|
|
516
|
+
if (!n || n.sessionId !== t) throw new l("transaction_not_found", `transaction ${e} is unknown, already finished, or not owned by session ${t}`);
|
|
517
|
+
return n;
|
|
518
|
+
}, T = async (e, t) => {
|
|
519
|
+
let n = r.get(e);
|
|
520
|
+
if (!n) return;
|
|
521
|
+
r.delete(e), t ? n.settle.reject(t) : n.settle.resolve();
|
|
522
|
+
let i = await n.finished.then(() => void 0, (e) => e);
|
|
523
|
+
if (!(t || i === void 0)) return i instanceof l ? i : new l("statement_failed", i instanceof Error ? i.message : String(i), { cause: i });
|
|
524
|
+
}, E = async (e, r) => {
|
|
525
|
+
let { dataDirectoryName: i } = e.storage;
|
|
526
|
+
for (; a.has(i);) await a.get(i);
|
|
527
|
+
if (d?.restores.isReserved(i)) throw new l("restore_in_progress", `"${i}" is being restored`);
|
|
528
|
+
let o = t.get(i) ?? y(i);
|
|
529
|
+
t.set(i, o), o.pending += 1;
|
|
530
|
+
try {
|
|
531
|
+
await o.ready;
|
|
532
|
+
} catch (e) {
|
|
533
|
+
throw t.get(i) === o && t.delete(i), e;
|
|
534
|
+
} finally {
|
|
535
|
+
--o.pending;
|
|
536
|
+
}
|
|
537
|
+
let c = m();
|
|
538
|
+
return o.sessions.add(c), n.set(c, {
|
|
539
|
+
dataDirectoryName: i,
|
|
540
|
+
owner: r
|
|
541
|
+
}), {
|
|
542
|
+
kind: "pg.open",
|
|
543
|
+
result: {
|
|
544
|
+
sessionId: c,
|
|
545
|
+
resolvedLocation: `${ae}/${i}`,
|
|
546
|
+
protocolVersion: s
|
|
547
|
+
}
|
|
548
|
+
};
|
|
549
|
+
}, D = async (e) => {
|
|
550
|
+
let r = n.get(e);
|
|
551
|
+
if (!r) return;
|
|
552
|
+
n.delete(e);
|
|
553
|
+
let i = t.get(r.dataDirectoryName);
|
|
554
|
+
i && (i.sessions.delete(e), !(i.sessions.size > 0 || i.pending > 0) && await x(r.dataDirectoryName, i));
|
|
555
|
+
}, O = async (e, t) => {
|
|
556
|
+
let n = [...r.entries()].filter(([, t]) => t.sessionId === e).map(([e]) => e);
|
|
557
|
+
for (let e of n) await T(e, new l("transaction_not_found", t));
|
|
558
|
+
return n.length;
|
|
559
|
+
}, k = async (e, t) => {
|
|
560
|
+
let n = await J(await C(S(e.sessionId, t)), e.timeout), i = m();
|
|
561
|
+
return r.set(i, {
|
|
562
|
+
...n,
|
|
563
|
+
sessionId: e.sessionId
|
|
564
|
+
}), {
|
|
565
|
+
kind: "pg.begin",
|
|
566
|
+
result: { transactionId: i }
|
|
567
|
+
};
|
|
568
|
+
}, A = async (e, t) => {
|
|
569
|
+
let n = S(e.sessionId, t), r = [...e.params];
|
|
570
|
+
if (e.transactionId !== void 0) {
|
|
571
|
+
let t = w(e.transactionId, e.sessionId);
|
|
572
|
+
return {
|
|
573
|
+
kind: "pg.query",
|
|
574
|
+
result: W(await G(() => t.tx.query(e.sql, r)))
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
let i = await C(n);
|
|
578
|
+
return {
|
|
579
|
+
kind: "pg.query",
|
|
580
|
+
result: W(await G(() => i.query(e.sql, r)))
|
|
581
|
+
};
|
|
582
|
+
}, j = async (e, t) => {
|
|
583
|
+
let n = S(e.sessionId, t), r = e.transactionId === void 0 ? await C(n) : w(e.transactionId, e.sessionId).tx;
|
|
584
|
+
return {
|
|
585
|
+
kind: "pg.exec",
|
|
586
|
+
result: (await G(() => r.exec(e.sql))).map(W)
|
|
587
|
+
};
|
|
588
|
+
}, N = async (e, t) => {
|
|
589
|
+
S(e.sessionId, t), w(e.transactionId, e.sessionId);
|
|
590
|
+
let n = e.kind === "pg.rollback" ? new l("write_aborted", "rollback requested") : null, r = await T(e.transactionId, n);
|
|
591
|
+
if (r) throw r;
|
|
592
|
+
return { kind: e.kind };
|
|
593
|
+
}, P = async (e, t) => {
|
|
594
|
+
let n = await C(S(e.sessionId, t)), r = (await G(() => n.query("SELECT version() AS version"))).rows[0]?.version;
|
|
595
|
+
if (typeof r != "string") throw new l("host_internal_error", "PostgreSQL did not report a version string");
|
|
596
|
+
return {
|
|
597
|
+
kind: "pg.version",
|
|
598
|
+
result: r
|
|
599
|
+
};
|
|
600
|
+
}, F = () => {
|
|
601
|
+
if (d === void 0) throw new l("unsupported_operation", "this host was created without backup support");
|
|
602
|
+
return d;
|
|
603
|
+
}, I = async (e) => {
|
|
604
|
+
let t;
|
|
605
|
+
try {
|
|
606
|
+
t = await e.options.createProbeRuntime();
|
|
607
|
+
} catch (e) {
|
|
608
|
+
throw new l("open_failed", "the application could not start the PGlite probe runtime", { cause: e });
|
|
609
|
+
}
|
|
610
|
+
try {
|
|
611
|
+
let n = (await G(() => t.query("SHOW server_version"))).rows[0]?.server_version;
|
|
612
|
+
if (typeof n != "string" || n === "") throw new l("host_internal_error", "PostgreSQL did not report server_version");
|
|
613
|
+
return {
|
|
614
|
+
serverVersion: n,
|
|
615
|
+
extensions: e.extensions
|
|
616
|
+
};
|
|
617
|
+
} finally {
|
|
618
|
+
await t.close().catch(() => void 0);
|
|
619
|
+
}
|
|
620
|
+
}, L = async (e) => {
|
|
621
|
+
let t = o ??= I(e);
|
|
622
|
+
try {
|
|
623
|
+
return {
|
|
624
|
+
kind: "pg.engine",
|
|
625
|
+
result: await t
|
|
626
|
+
};
|
|
627
|
+
} catch (e) {
|
|
628
|
+
throw o === t && (o = void 0), e;
|
|
629
|
+
}
|
|
630
|
+
}, R = async (e, t, n) => {
|
|
631
|
+
let r = S(t.sessionId, n), a = e.options.resolveDataDirectory(r.dataDirectoryName), o = await J(await C(r), t.timeout);
|
|
632
|
+
try {
|
|
633
|
+
if (await G(() => o.tx.query("CHECKPOINT")), !await M(a)) throw new l("host_internal_error", `resolveDataDirectory does not point at the data directory of "${r.dataDirectoryName}"`);
|
|
634
|
+
} catch (e) {
|
|
635
|
+
throw o.settle.reject(new l("write_aborted", "the snapshot was aborted")), await o.finished.catch(() => void 0), e;
|
|
636
|
+
}
|
|
637
|
+
let s = m();
|
|
638
|
+
return i.set(s, {
|
|
639
|
+
sessionId: t.sessionId,
|
|
640
|
+
iterator: ee(a),
|
|
641
|
+
held: o
|
|
642
|
+
}), {
|
|
643
|
+
kind: "pg.backup.begin",
|
|
644
|
+
result: { backupId: s }
|
|
645
|
+
};
|
|
646
|
+
}, z = (e, t) => {
|
|
647
|
+
let n = i.get(e);
|
|
648
|
+
if (!n || n.sessionId !== t) throw new l("transaction_not_found", `backup ${e} is unknown, already finished, or not owned by session ${t}`);
|
|
649
|
+
return n;
|
|
650
|
+
}, B = async (e) => {
|
|
651
|
+
let t = i.get(e);
|
|
652
|
+
if (t) {
|
|
653
|
+
i.delete(e);
|
|
654
|
+
try {
|
|
655
|
+
await t.iterator.return(void 0);
|
|
656
|
+
} finally {
|
|
657
|
+
t.held.settle.resolve(), await t.held.finished.catch(() => void 0);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}, V = async (e, t) => {
|
|
661
|
+
S(e.sessionId, t);
|
|
662
|
+
let n = z(e.backupId, e.sessionId), r;
|
|
663
|
+
try {
|
|
664
|
+
r = await n.iterator.next();
|
|
665
|
+
} catch (t) {
|
|
666
|
+
throw await B(e.backupId), t;
|
|
667
|
+
}
|
|
668
|
+
return {
|
|
669
|
+
kind: "pg.backup.next",
|
|
670
|
+
result: r.done ? { type: "end" } : r.value
|
|
671
|
+
};
|
|
672
|
+
}, H = async (e, t) => (S(e.sessionId, t), z(e.backupId, e.sessionId), await B(e.backupId), { kind: "pg.backup.end" }), K = async (e, t) => {
|
|
673
|
+
let n = F();
|
|
674
|
+
switch (e.kind) {
|
|
675
|
+
case "pg.engine": return L(n);
|
|
676
|
+
case "pg.backup.begin": return R(n, e, t);
|
|
677
|
+
case "pg.backup.next": return V(e, t);
|
|
678
|
+
case "pg.backup.end": return H(e, t);
|
|
679
|
+
default: return n.restores.handle(e, t);
|
|
680
|
+
}
|
|
681
|
+
}, q = async (e, t) => {
|
|
682
|
+
let n = [...i.entries()].filter(([, t]) => t.sessionId === e).map(([e]) => e);
|
|
683
|
+
for (let e of n) await B(e).catch(() => void 0);
|
|
684
|
+
let r = await O(e, t);
|
|
685
|
+
return await D(e), r;
|
|
686
|
+
}, Y = async (e, t) => (S(e.sessionId, t), await q(e.sessionId, `session ${e.sessionId} was closed`), { kind: "pg.close" }), X = (e, t) => {
|
|
687
|
+
switch (e.kind) {
|
|
688
|
+
case "pg.handshake": return Promise.resolve({
|
|
689
|
+
kind: "pg.handshake",
|
|
690
|
+
result: { protocolVersion: s }
|
|
691
|
+
});
|
|
692
|
+
case "pg.open": return E(e, t);
|
|
693
|
+
case "pg.query": return A(e, t);
|
|
694
|
+
case "pg.exec": return j(e, t);
|
|
695
|
+
case "pg.begin": return k(e, t);
|
|
696
|
+
case "pg.commit":
|
|
697
|
+
case "pg.rollback": return N(e, t);
|
|
698
|
+
case "pg.version": return P(e, t);
|
|
699
|
+
case "pg.close": return Y(e, t);
|
|
700
|
+
default: return K(e, t);
|
|
701
|
+
}
|
|
702
|
+
};
|
|
703
|
+
return {
|
|
704
|
+
handle: async (e, t) => {
|
|
705
|
+
try {
|
|
706
|
+
return await X(p(e), t);
|
|
707
|
+
} catch (e) {
|
|
708
|
+
return oe(e);
|
|
709
|
+
}
|
|
710
|
+
},
|
|
711
|
+
get openSessionCount() {
|
|
712
|
+
return n.size;
|
|
713
|
+
},
|
|
714
|
+
get openInstanceCount() {
|
|
715
|
+
return t.size;
|
|
716
|
+
},
|
|
717
|
+
get openTransactionCount() {
|
|
718
|
+
return r.size;
|
|
719
|
+
},
|
|
720
|
+
get openBackupCount() {
|
|
721
|
+
return i.size;
|
|
722
|
+
},
|
|
723
|
+
get openRestoreCount() {
|
|
724
|
+
return d === void 0 ? 0 : d.restores.openCount;
|
|
725
|
+
},
|
|
726
|
+
releaseOwner: async (e) => {
|
|
727
|
+
let t = [...n.entries()].filter(([, t]) => t.owner === e).map(([e]) => e), r = 0;
|
|
728
|
+
for (let n of t) r += await q(n, `owner ${e} is gone`);
|
|
729
|
+
return await d?.restores.releaseOwner(e), r;
|
|
730
|
+
},
|
|
731
|
+
closeAll: async () => {
|
|
732
|
+
for (let e of [...n.keys()]) await q(e, "the host is shutting down");
|
|
733
|
+
await d?.restores.closeAll();
|
|
734
|
+
}
|
|
735
|
+
};
|
|
736
|
+
}
|
|
737
|
+
//#endregion
|
|
738
|
+
export { e as DESKTOP_PGLITE_DEFAULT_BEGIN_TIMEOUT_MS, t as DESKTOP_PGLITE_EXCLUDED_FILES, r as DESKTOP_PGLITE_MAX_BEGIN_TIMEOUT_MS, i as DESKTOP_PGLITE_MAX_DATA_CHUNK_BYTES, o as DESKTOP_PGLITE_PROTOCOL_VERSION, $ as DESKTOP_PGLITE_WATCH_CHANNELS, c as RxDBAdapterDesktopError, u as assertValidDesktopDatabaseName, ce as createElectronPgliteHost, d as isDesktopPgliteRequestKind, f as parseDesktopPgliteRequest };
|