orez 0.2.26 → 0.2.29

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 (172) hide show
  1. package/dist/cf-do/worker.d.ts.map +1 -1
  2. package/dist/cf-do/worker.js +9 -1
  3. package/dist/cf-do/worker.js.map +1 -1
  4. package/dist/pg-proxy-do-backend.d.ts +2 -0
  5. package/dist/pg-proxy-do-backend.d.ts.map +1 -1
  6. package/dist/pg-proxy-do-backend.js +49 -7
  7. package/dist/pg-proxy-do-backend.js.map +1 -1
  8. package/dist/pg-sqlite-compiler/catalog/seed.d.ts +67 -0
  9. package/dist/pg-sqlite-compiler/catalog/seed.d.ts.map +1 -0
  10. package/dist/pg-sqlite-compiler/catalog/seed.js +436 -0
  11. package/dist/pg-sqlite-compiler/catalog/seed.js.map +1 -0
  12. package/dist/pg-sqlite-compiler/index.d.ts +12 -0
  13. package/dist/pg-sqlite-compiler/index.d.ts.map +1 -0
  14. package/dist/pg-sqlite-compiler/index.js +59 -0
  15. package/dist/pg-sqlite-compiler/index.js.map +1 -0
  16. package/dist/pg-sqlite-compiler/passes/ast-utils.d.ts +48 -0
  17. package/dist/pg-sqlite-compiler/passes/ast-utils.d.ts.map +1 -0
  18. package/dist/pg-sqlite-compiler/passes/ast-utils.js +93 -0
  19. package/dist/pg-sqlite-compiler/passes/ast-utils.js.map +1 -0
  20. package/dist/pg-sqlite-compiler/passes/catalog.d.ts +34 -0
  21. package/dist/pg-sqlite-compiler/passes/catalog.d.ts.map +1 -0
  22. package/dist/pg-sqlite-compiler/passes/catalog.js +30 -0
  23. package/dist/pg-sqlite-compiler/passes/catalog.js.map +1 -0
  24. package/dist/pg-sqlite-compiler/passes/datetime.d.ts +21 -0
  25. package/dist/pg-sqlite-compiler/passes/datetime.d.ts.map +1 -0
  26. package/dist/pg-sqlite-compiler/passes/datetime.js +53 -0
  27. package/dist/pg-sqlite-compiler/passes/datetime.js.map +1 -0
  28. package/dist/pg-sqlite-compiler/passes/index.d.ts +21 -0
  29. package/dist/pg-sqlite-compiler/passes/index.d.ts.map +1 -0
  30. package/dist/pg-sqlite-compiler/passes/index.js +39 -0
  31. package/dist/pg-sqlite-compiler/passes/index.js.map +1 -0
  32. package/dist/pg-sqlite-compiler/passes/types.d.ts +41 -0
  33. package/dist/pg-sqlite-compiler/passes/types.d.ts.map +1 -0
  34. package/dist/pg-sqlite-compiler/passes/types.js +103 -0
  35. package/dist/pg-sqlite-compiler/passes/types.js.map +1 -0
  36. package/dist/pg-sqlite-compiler/test/oracle.d.ts +34 -0
  37. package/dist/pg-sqlite-compiler/test/oracle.d.ts.map +1 -0
  38. package/dist/pg-sqlite-compiler/test/oracle.js +204 -0
  39. package/dist/pg-sqlite-compiler/test/oracle.js.map +1 -0
  40. package/dist/pg-sqlite-compiler/types.d.ts +55 -0
  41. package/dist/pg-sqlite-compiler/types.d.ts.map +1 -0
  42. package/dist/pg-sqlite-compiler/types.js +2 -0
  43. package/dist/pg-sqlite-compiler/types.js.map +1 -0
  44. package/package.json +8 -4
  45. package/src/admin/admin-data.test.ts +0 -348
  46. package/src/admin/http-proxy.ts +0 -252
  47. package/src/admin/log-store.ts +0 -192
  48. package/src/admin/server.ts +0 -471
  49. package/src/admin/ui.ts +0 -1322
  50. package/src/bench/proxy-throughput.bench.ts +0 -343
  51. package/src/bench/serial-mutations.bench.ts +0 -270
  52. package/src/browser.ts +0 -203
  53. package/src/cf-do/.wrangler/cache/cf.json +0 -1
  54. package/src/cf-do/.wrangler/state/v3/cache/miniflare-CacheObject/metadata.sqlite +0 -0
  55. package/src/cf-do/.wrangler/state/v3/cache/miniflare-CacheObject/metadata.sqlite-shm +0 -0
  56. package/src/cf-do/.wrangler/state/v3/cache/miniflare-CacheObject/metadata.sqlite-wal +0 -0
  57. package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/0f0f3bdf0abda097eb6f1246db4657d9fc622081362d894d82c1a1ce067b05b6.sqlite +0 -0
  58. package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/1ddd3a4a48a11b51658444f5458a1fb175194b1d5b6a5bda20ef3fe3205b900c.sqlite +0 -0
  59. package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/204a39120310d37e972c5914cfd71ad55c151bdb9e8ed289a5f8c5b052dd60e4.sqlite +0 -0
  60. package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/3835f242df9728adba3d127a238793fd054ed3e51df3f60749ee744c469bf2a2.sqlite +0 -0
  61. package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/4aa9c80eb716cf55b8995ccf7afab0b36c683e6da07d7c37a3f9c570136036df.sqlite +0 -0
  62. package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/533e2fd1d6ea46e7a9a0017916ef341802d438d72583462755f2c1f8225e9bf2.sqlite +0 -0
  63. package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/5ffa1aced1225ecaeac6366f7586aa3de92761cdff8711d81fbd81f248076abd.sqlite +0 -0
  64. package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/686c3a9f0d7e59ed2ab607efd4b76d779c97cafeb3818380033bf7c7eb86c819.sqlite +0 -0
  65. package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/6e8214e8dcfadd0deb52d64e5e9ca85c6b329ace11193909845995396914c473.sqlite +0 -0
  66. package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/78d9ec9ff873d3fe3507ff53c2a6f6dfc408b4268eb0db3f2a146c0678965366.sqlite +0 -0
  67. package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/7eff9f0ed7e27ad0d3f9d923de0682fab1928591172c1ba336c5f79a134a5d85.sqlite +0 -0
  68. package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/836cda5b995b25867d722ed4f4c2292167e80351a3c6038db626648eb247dd8b.sqlite +0 -0
  69. package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/91ef63b112209ab30172763acd8a0935106c248f7f1bcae5545ce37a9f201551.sqlite +0 -0
  70. package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/a66ea4293a5f5938bc6d116edfa2522bb85bc37aea3541fbc09c3b613b9b32c0.sqlite +0 -0
  71. package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/ceb2ab26b80590840b65651deb6e948d3bf81565c6751f3a58752cf4bf4aecae.sqlite +0 -0
  72. package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/metadata.sqlite +0 -0
  73. package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/metadata.sqlite-shm +0 -0
  74. package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/metadata.sqlite-wal +0 -0
  75. package/src/cf-do/ARCHITECTURE.md +0 -83
  76. package/src/cf-do/watermark.test.ts +0 -103
  77. package/src/cf-do/watermark.ts +0 -118
  78. package/src/cf-do/worker.ts +0 -1033
  79. package/src/cf-do/wrangler.toml +0 -11
  80. package/src/cf-pglite/README.md +0 -19
  81. package/src/change-tracking.ts +0 -25
  82. package/src/child-process.test.ts +0 -147
  83. package/src/child-process.ts +0 -90
  84. package/src/cli-entry.ts +0 -72
  85. package/src/cli.test.ts +0 -38
  86. package/src/cli.ts +0 -1214
  87. package/src/config.ts +0 -150
  88. package/src/do-sql-tracking.test.ts +0 -19
  89. package/src/do-sql-tracking.ts +0 -19
  90. package/src/index.ts +0 -1215
  91. package/src/integration/integration.test.ts +0 -517
  92. package/src/integration/native-binary.guard.test.ts +0 -13
  93. package/src/integration/native-startup.test.ts +0 -44
  94. package/src/integration/replication-latency.test.ts +0 -428
  95. package/src/integration/restore-live-stress.test.ts +0 -433
  96. package/src/integration/restore-reset.test.ts +0 -400
  97. package/src/integration/restore.test.ts +0 -274
  98. package/src/integration/test-permissions.ts +0 -147
  99. package/src/load-config.ts +0 -46
  100. package/src/log.ts +0 -96
  101. package/src/mutex.ts +0 -47
  102. package/src/pg-proxy-browser.singledb.test.ts +0 -233
  103. package/src/pg-proxy-browser.ts +0 -2022
  104. package/src/pg-proxy-do-backend.test.ts +0 -3890
  105. package/src/pg-proxy-do-backend.ts +0 -7157
  106. package/src/pg-proxy.ts +0 -1087
  107. package/src/pglite-ipc.test.ts +0 -116
  108. package/src/pglite-ipc.ts +0 -266
  109. package/src/pglite-manager.ts +0 -557
  110. package/src/pglite-web-proxy.test.ts +0 -57
  111. package/src/pglite-web-proxy.ts +0 -221
  112. package/src/pglite-web-worker.ts +0 -152
  113. package/src/pglite-worker-thread.ts +0 -253
  114. package/src/port.ts +0 -25
  115. package/src/process-title.ts +0 -9
  116. package/src/recovery.ts +0 -155
  117. package/src/replication/change-tracker.test.ts +0 -357
  118. package/src/replication/change-tracker.ts +0 -279
  119. package/src/replication/handler.test.ts +0 -511
  120. package/src/replication/handler.ts +0 -1190
  121. package/src/replication/pgoutput-encoder.test.ts +0 -697
  122. package/src/replication/pgoutput-encoder.ts +0 -373
  123. package/src/replication/tcp-replication.test.ts +0 -876
  124. package/src/replication/zero-compat.test.ts +0 -1150
  125. package/src/restore-stress.test.ts +0 -188
  126. package/src/s3-local.ts +0 -203
  127. package/src/shim/hooks.mjs +0 -120
  128. package/src/shim/register.mjs +0 -4
  129. package/src/sqlite-mode/apply-mode.ts +0 -224
  130. package/src/sqlite-mode/index.ts +0 -15
  131. package/src/sqlite-mode/native-binary.ts +0 -89
  132. package/src/sqlite-mode/package-resolve.ts +0 -17
  133. package/src/sqlite-mode/resolve-mode.ts +0 -80
  134. package/src/sqlite-mode/shim-template.ts +0 -159
  135. package/src/sqlite-mode/sqlite-mode.test.ts +0 -427
  136. package/src/sqlite-mode/types.ts +0 -30
  137. package/src/vite-plugin.ts +0 -67
  138. package/src/wasm-sqlite.test.ts +0 -537
  139. package/src/worker/browser-admin.ts +0 -52
  140. package/src/worker/browser-build-config.test.ts +0 -71
  141. package/src/worker/browser-build-config.ts +0 -109
  142. package/src/worker/browser-embed-admin.test.ts +0 -75
  143. package/src/worker/browser-embed.ts +0 -345
  144. package/src/worker/cf-patches.ts +0 -384
  145. package/src/worker/embed-integration.test.ts +0 -321
  146. package/src/worker/index.ts +0 -138
  147. package/src/worker/shims/fastify.test.ts +0 -255
  148. package/src/worker/shims/fastify.ts +0 -306
  149. package/src/worker/shims/http-service.test.ts +0 -355
  150. package/src/worker/shims/http-service.ts +0 -293
  151. package/src/worker/shims/node-stub.ts +0 -290
  152. package/src/worker/shims/oxfmt.ts +0 -3
  153. package/src/worker/shims/postgres-browser.ts +0 -59
  154. package/src/worker/shims/postgres-socket.test.ts +0 -576
  155. package/src/worker/shims/postgres-socket.ts +0 -310
  156. package/src/worker/shims/postgres.test.ts +0 -364
  157. package/src/worker/shims/postgres.ts +0 -1454
  158. package/src/worker/shims/sqlite-browser.test.ts +0 -233
  159. package/src/worker/shims/sqlite-browser.ts +0 -175
  160. package/src/worker/shims/sqlite.test.ts +0 -786
  161. package/src/worker/shims/sqlite.ts +0 -978
  162. package/src/worker/shims/stream-browser.ts +0 -15
  163. package/src/worker/shims/ws-browser.test.ts +0 -205
  164. package/src/worker/shims/ws-browser.ts +0 -248
  165. package/src/worker/shims/ws.test.ts +0 -288
  166. package/src/worker/shims/ws.ts +0 -467
  167. package/src/worker/shims/zero-process-env.ts +0 -11
  168. package/src/worker/types.ts +0 -75
  169. package/src/worker/worker-integration.test.ts +0 -223
  170. package/src/worker/worker.test.ts +0 -136
  171. package/src/worker/zero-cache-embed-cf.ts +0 -463
  172. package/src/worker/zero-cache-embed.ts +0 -277
@@ -1,116 +0,0 @@
1
- import { describe, test, expect, beforeAll, afterAll } from 'vitest'
2
-
3
- import { PGliteWorkerProxy } from './pglite-ipc.js'
4
-
5
- describe('PGliteWorkerProxy', () => {
6
- let proxy: PGliteWorkerProxy
7
-
8
- beforeAll(async () => {
9
- proxy = new PGliteWorkerProxy({
10
- dataDir: 'memory://',
11
- name: 'test',
12
- withExtensions: false,
13
- debug: 0,
14
- pgliteOptions: {},
15
- })
16
- await proxy.waitReady
17
- }, 30_000)
18
-
19
- afterAll(async () => {
20
- await proxy.close()
21
- })
22
-
23
- test('exec creates table', async () => {
24
- await proxy.exec(`
25
- CREATE TABLE test_items (
26
- id SERIAL PRIMARY KEY,
27
- name TEXT NOT NULL
28
- )
29
- `)
30
- })
31
-
32
- test('query returns rows', async () => {
33
- await proxy.exec(`INSERT INTO test_items (name) VALUES ('hello')`)
34
- await proxy.exec(`INSERT INTO test_items (name) VALUES ('world')`)
35
-
36
- const result = await proxy.query<{ id: number; name: string }>(
37
- 'SELECT * FROM test_items ORDER BY id'
38
- )
39
- expect(result.rows).toHaveLength(2)
40
- expect(result.rows[0].name).toBe('hello')
41
- expect(result.rows[1].name).toBe('world')
42
- })
43
-
44
- test('query with params', async () => {
45
- const result = await proxy.query<{ name: string }>(
46
- 'SELECT name FROM test_items WHERE name = $1',
47
- ['world']
48
- )
49
- expect(result.rows).toHaveLength(1)
50
- expect(result.rows[0].name).toBe('world')
51
- })
52
-
53
- test('exec returns affectedRows', async () => {
54
- const result = await proxy.exec(`DELETE FROM test_items WHERE name = 'hello'`)
55
- expect(result[0].affectedRows).toBe(1)
56
- })
57
-
58
- test('execProtocolRaw handles wire protocol', async () => {
59
- // simple query message: SELECT 1 as num
60
- const query = 'SELECT 1 as num\0'
61
- const encoder = new TextEncoder()
62
- const queryBytes = encoder.encode(query)
63
- const buf = new Uint8Array(5 + queryBytes.length)
64
- buf[0] = 0x51 // 'Q' simple query
65
- new DataView(buf.buffer).setInt32(1, 4 + queryBytes.length)
66
- buf.set(queryBytes, 5)
67
-
68
- const result = await proxy.execProtocolRaw(buf)
69
- expect(result).toBeInstanceOf(Uint8Array)
70
- expect(result.length).toBeGreaterThan(0)
71
- // should contain a ReadyForQuery message (0x5a)
72
- let hasRfq = false
73
- for (let i = 0; i < result.length; i++) {
74
- if (result[i] === 0x5a) {
75
- hasRfq = true
76
- break
77
- }
78
- }
79
- expect(hasRfq).toBe(true)
80
- })
81
-
82
- test('listen receives notifications', async () => {
83
- const received: string[] = []
84
- const unsub = await proxy.listen('test_channel', (payload) => {
85
- received.push(payload)
86
- })
87
-
88
- await proxy.exec(`NOTIFY test_channel, 'hello'`)
89
- // give notification time to propagate
90
- await new Promise((r) => setTimeout(r, 100))
91
-
92
- expect(received).toContain('hello')
93
- await unsub()
94
- })
95
-
96
- test('error propagation with SQL code', async () => {
97
- await expect(proxy.exec('SELECT * FROM nonexistent_table')).rejects.toThrow()
98
- })
99
-
100
- test('rejects requests after worker exits', async () => {
101
- const local = new PGliteWorkerProxy({
102
- dataDir: 'memory://',
103
- name: 'exit-test',
104
- withExtensions: false,
105
- debug: 0,
106
- pgliteOptions: {},
107
- })
108
- await local.waitReady
109
-
110
- await (local as any).worker.terminate()
111
-
112
- await expect(local.query('SELECT 1')).rejects.toThrow(
113
- /worker exited|worker is closed/
114
- )
115
- })
116
- })
package/src/pglite-ipc.ts DELETED
@@ -1,266 +0,0 @@
1
- /**
2
- * PGlite worker proxy — runs in the main thread, proxies calls to a
3
- * worker thread running the actual PGlite instance.
4
- *
5
- * implements the PGlite interface surface used throughout orez:
6
- * execProtocolRaw, query, exec, listen, close.
7
- *
8
- * ArrayBuffers are transferred (not copied) for execProtocolRaw to
9
- * keep IPC overhead near-zero for wire protocol data.
10
- */
11
-
12
- import { existsSync } from 'node:fs'
13
- import { resolve } from 'node:path'
14
- import { Worker } from 'node:worker_threads'
15
-
16
- import { log } from './log.js'
17
- import { signalReplicationChange } from './replication/handler.js'
18
-
19
- import type { WorkerInitConfig } from './pglite-worker-thread.js'
20
-
21
- interface PendingRequest {
22
- resolve: (value: any) => void
23
- reject: (error: Error) => void
24
- }
25
-
26
- const WRITE_PREFIXES = ['insert', 'update', 'delete', 'copy', 'truncate']
27
- // shard-internal tables that the replication handler filters out.
28
- // signaling for these just causes spurious wakeups + mutex contention.
29
- // pre-lowercased so we don't call toLowerCase() per iteration
30
- const SHARD_INTERNAL_TABLES = ['"replicas"', '"mutations"', '"replicationstate"']
31
- function isReplicatedWrite(sql: string): boolean {
32
- const q = sql.trimStart().toLowerCase()
33
- if (!WRITE_PREFIXES.some((p) => q.startsWith(p))) return false
34
- // skip shard-internal writes (zero-cache manages these, not replicated)
35
- for (const t of SHARD_INTERNAL_TABLES) {
36
- if (q.includes(t)) return false
37
- }
38
- return true
39
- }
40
-
41
- // resolve worker file path — .ts in dev/test (vitest), .js when compiled
42
- function resolveWorkerPath(): string {
43
- const dir = import.meta.dirname
44
- const tsPath = resolve(dir, 'pglite-worker-thread.ts')
45
- if (existsSync(tsPath)) return tsPath
46
- return resolve(dir, 'pglite-worker-thread.js')
47
- }
48
-
49
- export class PGliteWorkerProxy {
50
- private worker: Worker
51
- private pending = new Map<number, PendingRequest>()
52
- private nextId = 1
53
- private notificationCallbacks = new Map<string, Set<(payload: string) => void>>()
54
- private closed = false
55
- private failure: Error | null = null
56
- readonly name: string
57
-
58
- /** resolves when the worker's PGlite instance is ready */
59
- readonly waitReady: Promise<void>
60
-
61
- constructor(config: WorkerInitConfig) {
62
- this.name = config.name
63
- const workerPath = resolveWorkerPath()
64
-
65
- this.worker = new Worker(workerPath, {
66
- workerData: config,
67
- name: `pglite-${config.name}`,
68
- })
69
-
70
- // set up waitReady promise, then install message handler once ready
71
- let onReady: () => void
72
- this.waitReady = new Promise<void>((resolveReady, rejectReady) => {
73
- onReady = () => {
74
- log.debug.pglite(`worker ${config.name} ready`)
75
- resolveReady()
76
- }
77
-
78
- const onMessage = (msg: { type: string; id?: number; message?: string }) => {
79
- if (msg.type === 'ready') {
80
- this.worker.off('message', onMessage)
81
- this.installMessageHandler()
82
- onReady()
83
- } else if (msg.type === 'error' && msg.id === 0) {
84
- rejectReady(new Error(msg.message))
85
- }
86
- }
87
-
88
- this.worker.on('message', onMessage)
89
- this.worker.once('error', rejectReady)
90
- })
91
-
92
- // handle unexpected worker crashes
93
- this.worker.on('error', (err) => {
94
- const failure = new Error(`worker crashed: ${err.message}`)
95
- log.pglite(`worker ${config.name} error: ${err.message}`)
96
- this.failPending(failure)
97
- })
98
-
99
- this.worker.on('exit', (code) => {
100
- if (this.closed) return
101
- if (code !== 0) {
102
- const failure = new Error(`worker exited with code ${code}`)
103
- log.pglite(`worker ${config.name} exited with code ${code}`)
104
- this.failPending(failure)
105
- return
106
- }
107
- this.failPending(new Error('worker exited unexpectedly'))
108
- })
109
- }
110
-
111
- private failPending(error: Error) {
112
- if (!this.failure) this.failure = error
113
- for (const [, req] of this.pending) {
114
- req.reject(error)
115
- }
116
- this.pending.clear()
117
- }
118
-
119
- private installMessageHandler() {
120
- this.worker.on(
121
- 'message',
122
- (msg: { type: string; id?: number; [key: string]: any }) => {
123
- if (msg.type === 'notification') {
124
- const callbacks = this.notificationCallbacks.get(msg.channel)
125
- if (callbacks) {
126
- for (const cb of callbacks) {
127
- try {
128
- cb(msg.payload)
129
- } catch {}
130
- }
131
- }
132
- return
133
- }
134
-
135
- const req = this.pending.get(msg.id!)
136
- if (!req) return
137
- this.pending.delete(msg.id!)
138
-
139
- if (msg.type === 'error') {
140
- const err = new Error(msg.message) as Error & { code?: string }
141
- if (msg.code) err.code = msg.code
142
- req.reject(err)
143
- } else {
144
- req.resolve(msg)
145
- }
146
- }
147
- )
148
- }
149
-
150
- private send(msg: Record<string, unknown>, transfer?: ArrayBuffer[]): Promise<any> {
151
- if (this.failure) return Promise.reject(this.failure)
152
- if (this.closed) return Promise.reject(new Error('worker is closed'))
153
-
154
- const id = this.nextId++
155
- msg.id = id
156
- return new Promise((resolve, reject) => {
157
- this.pending.set(id, { resolve, reject })
158
- try {
159
- if (transfer?.length) {
160
- this.worker.postMessage(msg, transfer)
161
- } else {
162
- this.worker.postMessage(msg)
163
- }
164
- } catch (err) {
165
- this.pending.delete(id)
166
- reject(err instanceof Error ? err : new Error(String(err)))
167
- }
168
- })
169
- }
170
-
171
- async execProtocolRaw(
172
- data: Uint8Array,
173
- options?: { syncToFs?: boolean; throwOnError?: boolean }
174
- ): Promise<Uint8Array> {
175
- // copy to a transferable buffer then transfer (avoids copying in the worker)
176
- const buf = new ArrayBuffer(data.byteLength)
177
- new Uint8Array(buf).set(data)
178
- const result = await this.send({ type: 'execProtocolRaw', data: buf, options }, [buf])
179
- return new Uint8Array(result.data)
180
- }
181
-
182
- /**
183
- * execute multiple wire protocol messages in a single IPC round-trip.
184
- * each message is executed sequentially in the worker, and all results
185
- * are concatenated and returned. eliminates N-1 postMessage round-trips
186
- * for extended protocol pipelines (Parse→Bind→Execute→Sync).
187
- */
188
- async execProtocolRawBatch(
189
- messages: Uint8Array[],
190
- options?: { syncToFs?: boolean; throwOnError?: boolean }
191
- ): Promise<Uint8Array> {
192
- const buffers: ArrayBuffer[] = []
193
- for (const msg of messages) {
194
- const buf = new ArrayBuffer(msg.byteLength)
195
- new Uint8Array(buf).set(msg)
196
- buffers.push(buf)
197
- }
198
- const result = await this.send(
199
- { type: 'execProtocolRawBatch', buffers, options },
200
- buffers
201
- )
202
- return new Uint8Array(result.data)
203
- }
204
-
205
- async query<T = any>(
206
- sql: string,
207
- params?: any[]
208
- ): Promise<{ rows: T[]; affectedRows?: number }> {
209
- const result = await this.send({ type: 'query', sql, params })
210
- if (this.name === 'postgres' && isReplicatedWrite(sql)) {
211
- signalReplicationChange()
212
- }
213
- return { rows: result.rows ?? [], affectedRows: result.affectedRows }
214
- }
215
-
216
- async exec(sql: string): Promise<{ affectedRows?: number }[]> {
217
- const result = await this.send({ type: 'exec', sql })
218
- if (this.name === 'postgres' && isReplicatedWrite(sql)) {
219
- signalReplicationChange()
220
- }
221
- return result.results ?? []
222
- }
223
-
224
- async listen(
225
- channel: string,
226
- callback: (payload: string) => void
227
- ): Promise<() => Promise<void>> {
228
- let callbacks = this.notificationCallbacks.get(channel)
229
- if (!callbacks) {
230
- callbacks = new Set()
231
- this.notificationCallbacks.set(channel, callbacks)
232
- }
233
- callbacks.add(callback)
234
-
235
- const result = await this.send({ type: 'listen', channel })
236
- const listenId = result.id
237
-
238
- return async () => {
239
- callbacks!.delete(callback)
240
- if (callbacks!.size === 0) {
241
- this.notificationCallbacks.delete(channel)
242
- }
243
- await this.send({ type: 'unlisten', listenId }).catch(() => {})
244
- }
245
- }
246
-
247
- /**
248
- * dump the PGlite data directory as a tar blob.
249
- * used to create read replicas from an existing instance.
250
- */
251
- async dumpDataDir(): Promise<ArrayBuffer> {
252
- const result = await this.send({ type: 'dumpDataDir' })
253
- return result.data as ArrayBuffer
254
- }
255
-
256
- async close(): Promise<void> {
257
- try {
258
- await this.send({ type: 'close' })
259
- } catch {
260
- // worker may already be gone
261
- }
262
- this.closed = true
263
- this.failPending(new Error('worker is closed'))
264
- await this.worker.terminate()
265
- }
266
- }