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,223 +0,0 @@
1
- /**
2
- * integration test for orez/worker.
3
- *
4
- * tests the full pipeline available without zero-cache:
5
- * PGlite → change tracking → replication encoding → InProcessWriter
6
- *
7
- * mirrors the existing integration test patterns but uses the worker
8
- * API instead of startZeroLite(). validates that the worker entry
9
- * point produces the same replication stream that zero-cache expects.
10
- */
11
-
12
- import { describe, it, expect, beforeEach, afterEach } from 'vitest'
13
-
14
- import { InProcessWriter } from '../replication/handler.js'
15
- import { resetReplicationState, signalReplicationChange } from '../replication/handler.js'
16
- import { createOrezWorker } from './index'
17
-
18
- import type { OrezWorker } from './types'
19
-
20
- // extract pgoutput message types from CopyData(XLogData(...)) buffers
21
- function extractPayloadTypes(buf: Uint8Array): number[] {
22
- const types: number[] = []
23
- let pos = 0
24
- while (pos < buf.length) {
25
- if (buf[pos] !== 0x64) break // CopyData
26
- const view = new DataView(buf.buffer, buf.byteOffset + pos + 1)
27
- const len = view.getInt32(0)
28
- // XLogData starts at pos+5, payload type at pos+5+1+8+8+8 = pos+30
29
- if (pos + 30 < buf.length) {
30
- types.push(buf[pos + 30])
31
- }
32
- pos += 1 + len
33
- }
34
- return types
35
- }
36
-
37
- describe('orez/worker integration', { timeout: 30000 }, () => {
38
- let worker: OrezWorker
39
-
40
- beforeEach(async () => {
41
- resetReplicationState()
42
- worker = await createOrezWorker({
43
- pgliteOptions: { dataDir: 'memory://' },
44
- })
45
- // create test table
46
- await worker.exec(`
47
- CREATE TABLE public.foo (
48
- id TEXT PRIMARY KEY,
49
- value TEXT,
50
- num INTEGER
51
- )
52
- `)
53
- // reinstall triggers after table creation
54
- await worker.installChangeTracking()
55
- })
56
-
57
- afterEach(async () => {
58
- resetReplicationState()
59
- await worker.close()
60
- })
61
-
62
- it('change tracking captures insert/update/delete cycle', async () => {
63
- await worker.query('INSERT INTO foo (id, value, num) VALUES ($1, $2, $3)', [
64
- 'row1',
65
- 'hello',
66
- 42,
67
- ])
68
- await worker.query('UPDATE foo SET value = $1 WHERE id = $2', ['updated', 'row1'])
69
- await worker.query('DELETE FROM foo WHERE id = $1', ['row1'])
70
-
71
- const changes = await worker.getChangesSince(0)
72
- expect(changes).toHaveLength(3)
73
- expect(changes[0].op).toBe('INSERT')
74
- expect(changes[0].row_data).toMatchObject({ id: 'row1', value: 'hello', num: 42 })
75
- expect(changes[1].op).toBe('UPDATE')
76
- expect(changes[1].row_data).toMatchObject({ id: 'row1', value: 'updated' })
77
- expect(changes[1].old_data).toMatchObject({ id: 'row1', value: 'hello' })
78
- expect(changes[2].op).toBe('DELETE')
79
- expect(changes[2].old_data).toMatchObject({ id: 'row1', value: 'updated' })
80
- })
81
-
82
- it('InProcessWriter receives pgoutput stream from replication', async () => {
83
- const received: Uint8Array[] = []
84
- const writer = new InProcessWriter((data) => received.push(new Uint8Array(data)))
85
-
86
- // start replication in background
87
- const replPromise = worker.startReplication(writer)
88
-
89
- // wait for handler to set up
90
- await new Promise((r) => setTimeout(r, 200))
91
-
92
- // insert data
93
- await worker.query('INSERT INTO foo (id, value, num) VALUES ($1, $2, $3)', [
94
- 'streamed-1',
95
- 'live',
96
- 99,
97
- ])
98
- signalReplicationChange()
99
-
100
- // wait for replication to deliver
101
- await new Promise((r) => setTimeout(r, 1500))
102
-
103
- // close writer to stop replication
104
- writer.close()
105
- await replPromise.catch(() => {}) // may reject on close
106
-
107
- // should have received pgoutput messages
108
- expect(received.length).toBeGreaterThan(0)
109
-
110
- // extract message types from all received buffers
111
- const allTypes = received.flatMap(extractPayloadTypes)
112
-
113
- // first message is CopyBothResponse (0x57), then pgoutput messages
114
- // check we got the core pgoutput types
115
- expect(allTypes).toContain(0x42) // BEGIN
116
- expect(allTypes).toContain(0x52) // RELATION
117
- expect(allTypes).toContain(0x49) // INSERT
118
- expect(allTypes).toContain(0x43) // COMMIT
119
- })
120
-
121
- it('watermarks advance monotonically', async () => {
122
- const watermarks: number[] = []
123
-
124
- for (let i = 0; i < 5; i++) {
125
- await worker.query('INSERT INTO foo (id, value, num) VALUES ($1, $2, $3)', [
126
- `wm-${i}`,
127
- `val-${i}`,
128
- i,
129
- ])
130
- watermarks.push(await worker.getCurrentWatermark())
131
- }
132
-
133
- // each watermark should be strictly greater than the previous
134
- for (let i = 1; i < watermarks.length; i++) {
135
- expect(watermarks[i]).toBeGreaterThan(watermarks[i - 1])
136
- }
137
-
138
- // getChangesSince with earlier watermark returns only newer changes
139
- const midpoint = watermarks[2]
140
- const laterChanges = await worker.getChangesSince(midpoint)
141
- expect(laterChanges).toHaveLength(2)
142
- expect(laterChanges[0].row_data).toMatchObject({ id: 'wm-3' })
143
- expect(laterChanges[1].row_data).toMatchObject({ id: 'wm-4' })
144
- })
145
-
146
- it('purge removes consumed changes', async () => {
147
- for (let i = 0; i < 10; i++) {
148
- await worker.query('INSERT INTO foo (id, value, num) VALUES ($1, $2, $3)', [
149
- `purge-${i}`,
150
- 'x',
151
- i,
152
- ])
153
- }
154
-
155
- const allChanges = await worker.getChangesSince(0)
156
- expect(allChanges).toHaveLength(10)
157
-
158
- // purge first 7
159
- const purged = await worker.purgeChanges(allChanges[6].watermark)
160
- expect(purged).toBe(7)
161
-
162
- // only 3 remain
163
- const remaining = await worker.getChangesSince(0)
164
- expect(remaining).toHaveLength(3)
165
- })
166
-
167
- it('multiple tables each get tracked', async () => {
168
- await worker.exec(`
169
- CREATE TABLE public.bar (
170
- id TEXT PRIMARY KEY,
171
- foo_id TEXT
172
- )
173
- `)
174
- await worker.installChangeTracking()
175
-
176
- await worker.query('INSERT INTO foo VALUES ($1, $2, $3)', ['f1', 'a', 1])
177
- await worker.query('INSERT INTO bar VALUES ($1, $2)', ['b1', 'f1'])
178
-
179
- const changes = await worker.getChangesSince(0)
180
- expect(changes).toHaveLength(2)
181
- expect(changes[0].table_name).toBe('public.foo')
182
- expect(changes[1].table_name).toBe('public.bar')
183
- })
184
-
185
- it('replication stream contains correct data for multiple operations', async () => {
186
- const received: Uint8Array[] = []
187
- const writer = new InProcessWriter((data) => received.push(new Uint8Array(data)))
188
-
189
- const replPromise = worker.startReplication(writer)
190
- await new Promise((r) => setTimeout(r, 200))
191
-
192
- // insert
193
- await worker.query('INSERT INTO foo VALUES ($1, $2, $3)', ['r1', 'initial', 1])
194
- signalReplicationChange()
195
- await new Promise((r) => setTimeout(r, 800))
196
-
197
- // update
198
- await worker.query('UPDATE foo SET value = $1 WHERE id = $2', ['modified', 'r1'])
199
- signalReplicationChange()
200
- await new Promise((r) => setTimeout(r, 800))
201
-
202
- // delete
203
- await worker.query('DELETE FROM foo WHERE id = $1', ['r1'])
204
- signalReplicationChange()
205
- await new Promise((r) => setTimeout(r, 800))
206
-
207
- writer.close()
208
- await replPromise.catch(() => {})
209
-
210
- const allTypes = received.flatMap(extractPayloadTypes)
211
-
212
- // should have all three operation types
213
- expect(allTypes).toContain(0x49) // INSERT
214
- expect(allTypes).toContain(0x55) // UPDATE
215
- expect(allTypes).toContain(0x44) // DELETE
216
-
217
- // should have BEGIN/COMMIT pairs
218
- const begins = allTypes.filter((t) => t === 0x42).length
219
- const commits = allTypes.filter((t) => t === 0x43).length
220
- expect(begins).toBe(commits)
221
- expect(begins).toBeGreaterThanOrEqual(1)
222
- })
223
- })
@@ -1,136 +0,0 @@
1
- import { PGlite } from '@electric-sql/pglite'
2
- import { describe, it, expect, beforeEach, afterEach } from 'vitest'
3
-
4
- import { createOrezWorker } from './index'
5
-
6
- import type { OrezWorker } from './types'
7
-
8
- describe('orez/worker', () => {
9
- let worker: OrezWorker
10
-
11
- beforeEach(async () => {
12
- worker = await createOrezWorker({
13
- pgliteOptions: { dataDir: 'memory://' },
14
- })
15
- })
16
-
17
- afterEach(async () => {
18
- await worker.close()
19
- })
20
-
21
- it('creates worker with pgliteOptions', () => {
22
- expect(worker.db).toBeDefined()
23
- expect(worker.ownsInstance).toBe(true)
24
- })
25
-
26
- it('creates worker with pre-existing PGlite', async () => {
27
- const pglite = new PGlite()
28
- await pglite.waitReady
29
- const w = await createOrezWorker({ pglite })
30
- expect(w.db).toBe(pglite)
31
- expect(w.ownsInstance).toBe(false)
32
- await w.close()
33
- // pglite should still be open since worker doesn't own it
34
- expect(pglite.closed).toBe(false)
35
- await pglite.close()
36
- })
37
-
38
- it('throws without pglite or pgliteOptions', async () => {
39
- await expect(createOrezWorker({})).rejects.toThrow(
40
- 'provide either pglite or pgliteOptions'
41
- )
42
- })
43
-
44
- it('exec and query work', async () => {
45
- await worker.exec(`
46
- CREATE TABLE public.items (
47
- id SERIAL PRIMARY KEY,
48
- name TEXT NOT NULL
49
- )
50
- `)
51
- await worker.installChangeTracking()
52
- await worker.query('INSERT INTO public.items (name) VALUES ($1)', ['hello'])
53
- const result = await worker.query<{ id: number; name: string }>(
54
- 'SELECT * FROM public.items'
55
- )
56
- expect(result.rows).toHaveLength(1)
57
- expect(result.rows[0].name).toBe('hello')
58
- })
59
-
60
- it('change tracking captures mutations', async () => {
61
- await worker.exec(`
62
- CREATE TABLE public.things (
63
- id TEXT PRIMARY KEY,
64
- val INTEGER
65
- )
66
- `)
67
- // reinstall after creating table so triggers are on the new table
68
- await worker.installChangeTracking()
69
-
70
- await worker.exec(`INSERT INTO public.things VALUES ('a', 1)`)
71
- await worker.exec(`UPDATE public.things SET val = 2 WHERE id = 'a'`)
72
- await worker.exec(`DELETE FROM public.things WHERE id = 'a'`)
73
-
74
- const changes = await worker.getChangesSince(0)
75
- expect(changes).toHaveLength(3)
76
- expect(changes[0].op).toBe('INSERT')
77
- expect(changes[0].table_name).toBe('public.things')
78
- expect(changes[0].row_data).toMatchObject({ id: 'a', val: 1 })
79
- expect(changes[1].op).toBe('UPDATE')
80
- expect(changes[1].row_data).toMatchObject({ id: 'a', val: 2 })
81
- expect(changes[1].old_data).toMatchObject({ id: 'a', val: 1 })
82
- expect(changes[2].op).toBe('DELETE')
83
- expect(changes[2].old_data).toMatchObject({ id: 'a', val: 2 })
84
- })
85
-
86
- it('watermark tracking works', async () => {
87
- await worker.exec(`
88
- CREATE TABLE public.wm_test (id TEXT PRIMARY KEY)
89
- `)
90
- await worker.installChangeTracking()
91
-
92
- const wm0 = await worker.getCurrentWatermark()
93
- expect(wm0).toBe(0)
94
-
95
- await worker.exec(`INSERT INTO public.wm_test VALUES ('x')`)
96
- const wm1 = await worker.getCurrentWatermark()
97
- expect(wm1).toBeGreaterThan(0)
98
-
99
- await worker.exec(`INSERT INTO public.wm_test VALUES ('y')`)
100
- const wm2 = await worker.getCurrentWatermark()
101
- expect(wm2).toBeGreaterThan(wm1)
102
-
103
- // getChangesSince with wm1 should only return the second insert
104
- const changes = await worker.getChangesSince(wm1)
105
- expect(changes).toHaveLength(1)
106
- expect(changes[0].row_data).toMatchObject({ id: 'y' })
107
- })
108
-
109
- it('purgeChanges removes old entries', async () => {
110
- await worker.exec(`CREATE TABLE public.purge_test (id TEXT PRIMARY KEY)`)
111
- await worker.installChangeTracking()
112
-
113
- await worker.exec(`INSERT INTO public.purge_test VALUES ('a')`)
114
- await worker.exec(`INSERT INTO public.purge_test VALUES ('b')`)
115
- await worker.exec(`INSERT INTO public.purge_test VALUES ('c')`)
116
-
117
- const allChanges = await worker.getChangesSince(0)
118
- expect(allChanges).toHaveLength(3)
119
-
120
- // purge up to second change
121
- const purged = await worker.purgeChanges(allChanges[1].watermark)
122
- expect(purged).toBe(2)
123
-
124
- // only third change remains
125
- const remaining = await worker.getChangesSince(0)
126
- expect(remaining).toHaveLength(1)
127
- expect(remaining[0].row_data).toMatchObject({ id: 'c' })
128
- })
129
-
130
- it('close shuts down owned instance', async () => {
131
- const w = await createOrezWorker({ pgliteOptions: { dataDir: 'memory://' } })
132
- expect(w.db.closed).toBe(false)
133
- await w.close()
134
- expect(w.db.closed).toBe(true)
135
- })
136
- })