orez 0.2.27 → 0.2.30
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/dist/cf-do/worker.d.ts +3 -0
- package/dist/cf-do/worker.d.ts.map +1 -1
- package/dist/cf-do/worker.js +37 -15
- package/dist/cf-do/worker.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/package.json +3 -4
- package/src/admin/admin-data.test.ts +0 -348
- package/src/admin/http-proxy.ts +0 -252
- package/src/admin/log-store.ts +0 -192
- package/src/admin/server.ts +0 -471
- package/src/admin/ui.ts +0 -1322
- package/src/bench/proxy-throughput.bench.ts +0 -343
- package/src/bench/serial-mutations.bench.ts +0 -270
- package/src/browser.ts +0 -203
- package/src/cf-do/.wrangler/cache/cf.json +0 -1
- package/src/cf-do/.wrangler/state/v3/cache/miniflare-CacheObject/metadata.sqlite +0 -0
- package/src/cf-do/.wrangler/state/v3/cache/miniflare-CacheObject/metadata.sqlite-shm +0 -0
- package/src/cf-do/.wrangler/state/v3/cache/miniflare-CacheObject/metadata.sqlite-wal +0 -0
- package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/0ffaabee41a60e04dd0eb7db3073f0a40139e6a97ccd26823967acb652b89a7b.sqlite +0 -0
- package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/metadata.sqlite +0 -0
- package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/metadata.sqlite-shm +0 -0
- package/src/cf-do/.wrangler/state/v3/do/zero-do-ZeroDO/metadata.sqlite-wal +0 -0
- package/src/cf-do/.wrangler/tmp/bundle-0z4CpE/middleware-insertion-facade.js +0 -11
- package/src/cf-do/.wrangler/tmp/bundle-0z4CpE/middleware-loader.entry.ts +0 -134
- package/src/cf-do/.wrangler/tmp/bundle-vYmw0E/middleware-insertion-facade.js +0 -11
- package/src/cf-do/.wrangler/tmp/bundle-vYmw0E/middleware-loader.entry.ts +0 -134
- package/src/cf-do/.wrangler/tmp/dev-cbILNo/worker.js +0 -1059
- package/src/cf-do/.wrangler/tmp/dev-cbILNo/worker.js.map +0 -8
- package/src/cf-do/.wrangler/tmp/dev-qbho19/worker.js +0 -1059
- package/src/cf-do/.wrangler/tmp/dev-qbho19/worker.js.map +0 -8
- package/src/cf-do/ARCHITECTURE.md +0 -93
- package/src/cf-do/CHAT_E2E.md +0 -213
- package/src/cf-do/watermark.test.ts +0 -103
- package/src/cf-do/watermark.ts +0 -118
- package/src/cf-do/worker.ts +0 -1041
- package/src/cf-do/wrangler.toml +0 -11
- package/src/cf-pglite/README.md +0 -19
- package/src/change-tracking.ts +0 -25
- package/src/child-process.test.ts +0 -147
- package/src/child-process.ts +0 -90
- package/src/cli-entry.ts +0 -72
- package/src/cli.test.ts +0 -40
- package/src/cli.ts +0 -1214
- package/src/config.ts +0 -150
- package/src/do-sql-tracking.test.ts +0 -19
- package/src/do-sql-tracking.ts +0 -19
- package/src/index.ts +0 -1215
- package/src/integration/integration.test.ts +0 -517
- package/src/integration/native-binary.guard.test.ts +0 -13
- package/src/integration/native-startup.test.ts +0 -44
- package/src/integration/replication-latency.test.ts +0 -428
- package/src/integration/restore-live-stress.test.ts +0 -433
- package/src/integration/restore-reset.test.ts +0 -400
- package/src/integration/restore.test.ts +0 -274
- package/src/integration/test-permissions.ts +0 -147
- package/src/load-config.ts +0 -46
- package/src/log.ts +0 -96
- package/src/mutex.ts +0 -47
- package/src/pg-proxy-browser.singledb.test.ts +0 -233
- package/src/pg-proxy-browser.ts +0 -2022
- package/src/pg-proxy-do-backend.test.ts +0 -3890
- package/src/pg-proxy-do-backend.ts +0 -7191
- package/src/pg-proxy.ts +0 -1087
- package/src/pg-sqlite-compiler/README.md +0 -53
- package/src/pg-sqlite-compiler/catalog/seed.ts +0 -524
- package/src/pg-sqlite-compiler/fixtures/pgsqlite/arithmetic.json +0 -307
- package/src/pg-sqlite-compiler/fixtures/pgsqlite/array.json +0 -377
- package/src/pg-sqlite-compiler/fixtures/pgsqlite/cast.json +0 -12
- package/src/pg-sqlite-compiler/fixtures/pgsqlite/catalog.json +0 -447
- package/src/pg-sqlite-compiler/fixtures/pgsqlite/create-table.json +0 -32
- package/src/pg-sqlite-compiler/fixtures/pgsqlite/datetime.json +0 -397
- package/src/pg-sqlite-compiler/fixtures/pgsqlite/enum.json +0 -337
- package/src/pg-sqlite-compiler/fixtures/pgsqlite/insert.json +0 -337
- package/src/pg-sqlite-compiler/fixtures/pgsqlite/json.json +0 -537
- package/src/pg-sqlite-compiler/fixtures/pgsqlite/misc.json +0 -1837
- package/src/pg-sqlite-compiler/index.ts +0 -73
- package/src/pg-sqlite-compiler/integration.test.ts +0 -136
- package/src/pg-sqlite-compiler/passes/ast-utils.ts +0 -113
- package/src/pg-sqlite-compiler/passes/catalog.ts +0 -65
- package/src/pg-sqlite-compiler/passes/datetime.ts +0 -74
- package/src/pg-sqlite-compiler/passes/index.ts +0 -49
- package/src/pg-sqlite-compiler/passes/types.ts +0 -156
- package/src/pg-sqlite-compiler/smoke.test.ts +0 -69
- package/src/pg-sqlite-compiler/test/catalog.test.ts +0 -171
- package/src/pg-sqlite-compiler/test/corpus.test.ts +0 -161
- package/src/pg-sqlite-compiler/test/datetime.oracle.test.ts +0 -102
- package/src/pg-sqlite-compiler/test/oracle.ts +0 -237
- package/src/pg-sqlite-compiler/test/types.test.ts +0 -109
- package/src/pg-sqlite-compiler/types.ts +0 -63
- package/src/pglite-ipc.test.ts +0 -116
- package/src/pglite-ipc.ts +0 -266
- package/src/pglite-manager.ts +0 -557
- package/src/pglite-web-proxy.test.ts +0 -57
- package/src/pglite-web-proxy.ts +0 -221
- package/src/pglite-web-worker.ts +0 -152
- package/src/pglite-worker-thread.ts +0 -253
- package/src/port.ts +0 -25
- package/src/process-title.ts +0 -9
- package/src/recovery.ts +0 -155
- package/src/replication/change-tracker.test.ts +0 -357
- package/src/replication/change-tracker.ts +0 -279
- package/src/replication/handler.test.ts +0 -511
- package/src/replication/handler.ts +0 -1190
- package/src/replication/pgoutput-encoder.test.ts +0 -697
- package/src/replication/pgoutput-encoder.ts +0 -373
- package/src/replication/tcp-replication.test.ts +0 -876
- package/src/replication/zero-compat.test.ts +0 -1150
- package/src/restore-stress.test.ts +0 -188
- package/src/s3-local.ts +0 -203
- package/src/shim/hooks.mjs +0 -120
- package/src/shim/register.mjs +0 -4
- package/src/sqlite-mode/apply-mode.ts +0 -224
- package/src/sqlite-mode/index.ts +0 -15
- package/src/sqlite-mode/native-binary.ts +0 -89
- package/src/sqlite-mode/package-resolve.ts +0 -17
- package/src/sqlite-mode/resolve-mode.ts +0 -80
- package/src/sqlite-mode/shim-template.ts +0 -159
- package/src/sqlite-mode/sqlite-mode.test.ts +0 -427
- package/src/sqlite-mode/types.ts +0 -30
- package/src/vite-plugin.ts +0 -67
- package/src/wasm-sqlite.test.ts +0 -537
- package/src/worker/browser-admin.ts +0 -52
- package/src/worker/browser-build-config.test.ts +0 -71
- package/src/worker/browser-build-config.ts +0 -109
- package/src/worker/browser-embed-admin.test.ts +0 -75
- package/src/worker/browser-embed.ts +0 -345
- package/src/worker/cf-patches.ts +0 -384
- package/src/worker/embed-integration.test.ts +0 -321
- package/src/worker/index.ts +0 -138
- package/src/worker/shims/fastify.test.ts +0 -255
- package/src/worker/shims/fastify.ts +0 -306
- package/src/worker/shims/http-service.test.ts +0 -355
- package/src/worker/shims/http-service.ts +0 -293
- package/src/worker/shims/node-stub.ts +0 -290
- package/src/worker/shims/oxfmt.ts +0 -3
- package/src/worker/shims/postgres-browser.ts +0 -59
- package/src/worker/shims/postgres-socket.test.ts +0 -576
- package/src/worker/shims/postgres-socket.ts +0 -310
- package/src/worker/shims/postgres.test.ts +0 -364
- package/src/worker/shims/postgres.ts +0 -1454
- package/src/worker/shims/sqlite-browser.test.ts +0 -233
- package/src/worker/shims/sqlite-browser.ts +0 -175
- package/src/worker/shims/sqlite.test.ts +0 -786
- package/src/worker/shims/sqlite.ts +0 -978
- package/src/worker/shims/stream-browser.ts +0 -15
- package/src/worker/shims/ws-browser.test.ts +0 -205
- package/src/worker/shims/ws-browser.ts +0 -248
- package/src/worker/shims/ws.test.ts +0 -288
- package/src/worker/shims/ws.ts +0 -467
- package/src/worker/shims/zero-process-env.ts +0 -11
- package/src/worker/types.ts +0 -75
- package/src/worker/worker-integration.test.ts +0 -223
- package/src/worker/worker.test.ts +0 -136
- package/src/worker/zero-cache-embed-cf.ts +0 -463
- package/src/worker/zero-cache-embed.ts +0 -277
package/src/worker/shims/ws.ts
DELETED
|
@@ -1,467 +0,0 @@
|
|
|
1
|
-
// NOTE THIS IS NOT OREZ NODE THIS IS NOT A GOOD REFERENCE BECAUSE ITS OUR EARLY GUESS AT WHAT COULD WORK
|
|
2
|
-
// DO NOT STUDY THIS, THE OTHER STUFF IN SRC IS WHERE YOU EANT TO LOOK
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* ws (websocket) shim for cloudflare workers.
|
|
6
|
-
*
|
|
7
|
-
* wraps CF Workers WebSocket (from WebSocketPair) to implement the
|
|
8
|
-
* ws npm package API that zero-cache uses. enables bundler aliasing
|
|
9
|
-
* so zero-cache's WebSocket handling works with CF durable WebSockets.
|
|
10
|
-
*
|
|
11
|
-
* usage with bundler alias:
|
|
12
|
-
* alias: { 'ws': './src/worker/shims/ws.js' }
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import EventEmitter from 'node:events'
|
|
16
|
-
import { Duplex } from 'node:stream'
|
|
17
|
-
|
|
18
|
-
// -- readyState constants --
|
|
19
|
-
const CONNECTING = 0
|
|
20
|
-
const OPEN = 1
|
|
21
|
-
const CLOSING = 2
|
|
22
|
-
const CLOSED = 3
|
|
23
|
-
|
|
24
|
-
// -- CF WebSocket interface (minimal) --
|
|
25
|
-
interface CFWebSocket {
|
|
26
|
-
send(data: string | ArrayBuffer | ArrayBufferView): void
|
|
27
|
-
close(code?: number, reason?: string): void
|
|
28
|
-
addEventListener(type: string, handler: (event: any) => void): void
|
|
29
|
-
removeEventListener(type: string, handler: (event: any) => void): void
|
|
30
|
-
readyState: number
|
|
31
|
-
accept?(): void
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function debugWS(event: Record<string, unknown>): void {
|
|
35
|
-
try {
|
|
36
|
-
const log = (globalThis as any).__orez_ws_debug_log
|
|
37
|
-
if (typeof log === 'function') log(event)
|
|
38
|
-
} catch {
|
|
39
|
-
// debug logging must never affect websocket behavior
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function summarizeWSData(data: unknown): Record<string, unknown> {
|
|
44
|
-
if (typeof data === 'string') {
|
|
45
|
-
return {
|
|
46
|
-
dataType: 'string',
|
|
47
|
-
bytes: data.length,
|
|
48
|
-
text: data.length > 300 ? `${data.slice(0, 300)}...` : data,
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
if (typeof Buffer !== 'undefined' && Buffer.isBuffer(data)) {
|
|
52
|
-
return { dataType: 'buffer', bytes: data.byteLength }
|
|
53
|
-
}
|
|
54
|
-
if (data instanceof ArrayBuffer) {
|
|
55
|
-
return { dataType: 'arraybuffer', bytes: data.byteLength }
|
|
56
|
-
}
|
|
57
|
-
if (ArrayBuffer.isView(data)) {
|
|
58
|
-
return { dataType: data.constructor.name, bytes: data.byteLength }
|
|
59
|
-
}
|
|
60
|
-
return { dataType: typeof data }
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// -- WebSocket shim --
|
|
64
|
-
// wraps a CF WebSocket to match the ws package WebSocket API
|
|
65
|
-
|
|
66
|
-
class WebSocket extends EventEmitter {
|
|
67
|
-
static readonly CONNECTING = CONNECTING
|
|
68
|
-
static readonly OPEN = OPEN
|
|
69
|
-
static readonly CLOSING = CLOSING
|
|
70
|
-
static readonly CLOSED = CLOSED
|
|
71
|
-
|
|
72
|
-
readonly CONNECTING = CONNECTING
|
|
73
|
-
readonly OPEN = OPEN
|
|
74
|
-
readonly CLOSING = CLOSING
|
|
75
|
-
readonly CLOSED = CLOSED
|
|
76
|
-
|
|
77
|
-
#ws!: CFWebSocket
|
|
78
|
-
#url: string
|
|
79
|
-
#listeners = new Map<string, (event: any) => void>()
|
|
80
|
-
|
|
81
|
-
constructor(urlOrSocket: string | CFWebSocket, _protocols?: unknown, _opts?: unknown) {
|
|
82
|
-
super()
|
|
83
|
-
|
|
84
|
-
if (typeof urlOrSocket === 'string') {
|
|
85
|
-
this.#url = urlOrSocket
|
|
86
|
-
// check for in-process connections (fastify shim uses port 0 or 1)
|
|
87
|
-
const parsedUrl = new URL(urlOrSocket, 'http://localhost')
|
|
88
|
-
const isInProcess =
|
|
89
|
-
parsedUrl.port === '0' ||
|
|
90
|
-
parsedUrl.port === '1' ||
|
|
91
|
-
parsedUrl.hostname === 'localhost'
|
|
92
|
-
|
|
93
|
-
if (isInProcess) {
|
|
94
|
-
// in-process: connect via fastify server's handoff mechanism
|
|
95
|
-
// try all registered fastify instances via tryHandoff, stop at first match
|
|
96
|
-
const instances: any[] = (globalThis as any).__orez_fastify_instances || []
|
|
97
|
-
const fallbackInstance = (globalThis as any).__orez_fastify_instance
|
|
98
|
-
if (instances.length > 0 || fallbackInstance?.server) {
|
|
99
|
-
// create paired message channels for bidirectional communication
|
|
100
|
-
// the client-side WS (this) and serverWs are cross-linked so
|
|
101
|
-
// ping/pong, messages, and close propagate between them
|
|
102
|
-
const clientSide = this
|
|
103
|
-
const serverWs: any = {
|
|
104
|
-
readyState: 1,
|
|
105
|
-
_listeners: {} as Record<string, Function[]>,
|
|
106
|
-
send: (data: string | ArrayBuffer) => {
|
|
107
|
-
// deliver to client side
|
|
108
|
-
// wrap in event object — zero-cache handleMessage reads event.data
|
|
109
|
-
queueMicrotask(() => clientSide.emit('message', { data }))
|
|
110
|
-
},
|
|
111
|
-
close: (code?: number, reason?: string) => {
|
|
112
|
-
serverWs.readyState = 3
|
|
113
|
-
queueMicrotask(() => clientSide.emit('close', code || 1000, reason || ''))
|
|
114
|
-
},
|
|
115
|
-
ping: () => {
|
|
116
|
-
// ping from server → deliver 'ping' event to client
|
|
117
|
-
// (expectPingsForLiveness listens for 'ping', not 'pong')
|
|
118
|
-
queueMicrotask(() => clientSide.emit('ping'))
|
|
119
|
-
},
|
|
120
|
-
addEventListener: (type: string, handler: Function) => {
|
|
121
|
-
if (!serverWs._listeners[type]) serverWs._listeners[type] = []
|
|
122
|
-
serverWs._listeners[type].push(handler)
|
|
123
|
-
},
|
|
124
|
-
removeEventListener: (type: string, handler: Function) => {
|
|
125
|
-
const arr = serverWs._listeners[type]
|
|
126
|
-
if (arr) {
|
|
127
|
-
const idx = arr.indexOf(handler)
|
|
128
|
-
if (idx >= 0) arr.splice(idx, 1)
|
|
129
|
-
}
|
|
130
|
-
},
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// client-side internal ws — forwards send() to server,
|
|
134
|
-
// receives messages from server via addEventListener.
|
|
135
|
-
// addEventListener MUST work because WebSocket#setupListeners registers here.
|
|
136
|
-
const clientWsListeners: Record<string, Function[]> = {}
|
|
137
|
-
this.#ws = {
|
|
138
|
-
accept: () => {},
|
|
139
|
-
send: (data: string | ArrayBuffer) => {
|
|
140
|
-
const handlers = serverWs._listeners['message'] || []
|
|
141
|
-
for (const h of handlers) h({ data })
|
|
142
|
-
},
|
|
143
|
-
close: (code?: number, reason?: string) => {
|
|
144
|
-
const handlers = serverWs._listeners['close'] || []
|
|
145
|
-
for (const h of handlers) h({ code, reason })
|
|
146
|
-
},
|
|
147
|
-
addEventListener: (type: string, handler: Function) => {
|
|
148
|
-
if (!clientWsListeners[type]) clientWsListeners[type] = []
|
|
149
|
-
clientWsListeners[type].push(handler)
|
|
150
|
-
},
|
|
151
|
-
removeEventListener: (type: string, handler: Function) => {
|
|
152
|
-
const arr = clientWsListeners[type]
|
|
153
|
-
if (arr) {
|
|
154
|
-
const idx = arr.indexOf(handler)
|
|
155
|
-
if (idx >= 0) arr.splice(idx, 1)
|
|
156
|
-
}
|
|
157
|
-
},
|
|
158
|
-
get readyState() {
|
|
159
|
-
return 1
|
|
160
|
-
},
|
|
161
|
-
} as CFWebSocket
|
|
162
|
-
|
|
163
|
-
// wire server → client: when server sends data, deliver to client's
|
|
164
|
-
// addEventListener handlers AND emit on the WebSocket instance
|
|
165
|
-
const origServerSend = serverWs.send
|
|
166
|
-
serverWs.send = (data: string | ArrayBuffer) => {
|
|
167
|
-
const handlers = clientWsListeners['message'] || []
|
|
168
|
-
for (const h of handlers) h({ data })
|
|
169
|
-
queueMicrotask(() => clientSide.emit('message', { data }))
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// try handoff against all fastify instances, stop at first match
|
|
173
|
-
const path = parsedUrl.pathname + parsedUrl.search
|
|
174
|
-
const handoffMsg = {
|
|
175
|
-
message: { url: path, headers: {}, method: 'GET' },
|
|
176
|
-
head: new Uint8Array(0),
|
|
177
|
-
}
|
|
178
|
-
queueMicrotask(() => {
|
|
179
|
-
let handled = false
|
|
180
|
-
for (const inst of instances) {
|
|
181
|
-
if (inst?.tryHandoff?.(handoffMsg, serverWs)) {
|
|
182
|
-
handled = true
|
|
183
|
-
break
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
// fallback: if no instance handled it and we have a fallback, emit directly
|
|
187
|
-
if (!handled && fallbackInstance?.server) {
|
|
188
|
-
fallbackInstance.server.emit('message', ['handoff', handoffMsg], serverWs)
|
|
189
|
-
}
|
|
190
|
-
this.emit('open')
|
|
191
|
-
})
|
|
192
|
-
} else {
|
|
193
|
-
// no fastify instance — emit close immediately
|
|
194
|
-
queueMicrotask(() => this.emit('close', 1006, 'no fastify server'))
|
|
195
|
-
}
|
|
196
|
-
} else if (typeof globalThis.WebSocket === 'function') {
|
|
197
|
-
// real outbound WebSocket for external connections
|
|
198
|
-
const nativeWs = new globalThis.WebSocket(urlOrSocket) as any
|
|
199
|
-
this.#ws = {
|
|
200
|
-
accept: () => {},
|
|
201
|
-
send: (data: string | ArrayBuffer) => nativeWs.send(data),
|
|
202
|
-
close: (code?: number, reason?: string) => nativeWs.close(code, reason),
|
|
203
|
-
addEventListener: (type: string, handler: (event: any) => void) =>
|
|
204
|
-
nativeWs.addEventListener(type, handler),
|
|
205
|
-
removeEventListener: (type: string, handler: (event: any) => void) =>
|
|
206
|
-
nativeWs.removeEventListener(type, handler),
|
|
207
|
-
get readyState() {
|
|
208
|
-
return nativeWs.readyState
|
|
209
|
-
},
|
|
210
|
-
} as CFWebSocket
|
|
211
|
-
nativeWs.addEventListener('open', () => this.emit('open'))
|
|
212
|
-
nativeWs.addEventListener('message', (ev: MessageEvent) =>
|
|
213
|
-
this.emit('message', ev.data)
|
|
214
|
-
)
|
|
215
|
-
nativeWs.addEventListener('close', (ev: CloseEvent) =>
|
|
216
|
-
this.emit('close', ev.code, ev.reason)
|
|
217
|
-
)
|
|
218
|
-
nativeWs.addEventListener('error', (ev: Event) =>
|
|
219
|
-
this.emit('error', new Error('WebSocket error'))
|
|
220
|
-
)
|
|
221
|
-
} else {
|
|
222
|
-
throw new Error(
|
|
223
|
-
'ws shim: outbound WebSocket connections not yet supported. ' +
|
|
224
|
-
'use the CF Workers fetch API for outbound WebSocket.'
|
|
225
|
-
)
|
|
226
|
-
}
|
|
227
|
-
} else {
|
|
228
|
-
this.#ws = urlOrSocket
|
|
229
|
-
this.#url = ''
|
|
230
|
-
debugWS({ event: 'wrap-cf-socket', readyState: this.#ws.readyState })
|
|
231
|
-
this.#setupListeners()
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
get url(): string {
|
|
236
|
-
return this.#url
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
get readyState(): number {
|
|
240
|
-
return this.#ws.readyState
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
send(
|
|
244
|
-
data: string | Buffer | ArrayBuffer | ArrayBufferView,
|
|
245
|
-
cb?: (err?: Error) => void
|
|
246
|
-
): void {
|
|
247
|
-
try {
|
|
248
|
-
debugWS({ event: 'send', url: this.#url, ...summarizeWSData(data) })
|
|
249
|
-
if (typeof data === 'string') {
|
|
250
|
-
this.#ws.send(data)
|
|
251
|
-
} else if (Buffer.isBuffer(data)) {
|
|
252
|
-
this.#ws.send(new Uint8Array(data.buffer, data.byteOffset, data.byteLength))
|
|
253
|
-
} else if (data instanceof ArrayBuffer) {
|
|
254
|
-
this.#ws.send(data)
|
|
255
|
-
} else if (ArrayBuffer.isView(data)) {
|
|
256
|
-
this.#ws.send(new Uint8Array(data.buffer, data.byteOffset, data.byteLength))
|
|
257
|
-
} else {
|
|
258
|
-
this.#ws.send(String(data))
|
|
259
|
-
}
|
|
260
|
-
cb?.()
|
|
261
|
-
} catch (err) {
|
|
262
|
-
cb?.(err as Error)
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
close(code?: number, reason?: string): void {
|
|
267
|
-
try {
|
|
268
|
-
this.#ws.close(code, reason)
|
|
269
|
-
} catch {
|
|
270
|
-
// socket may already be closed
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
terminate(): void {
|
|
275
|
-
// real ws.terminate() destroys the socket without a close frame.
|
|
276
|
-
// CF Workers don't expose raw socket destroy, so close with 1000.
|
|
277
|
-
this.close(1000)
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
ping(_data?: unknown, _mask?: boolean, _cb?: () => void): void {
|
|
281
|
-
// forward ping to underlying socket if it supports it (in-process pairs)
|
|
282
|
-
if (typeof (this.#ws as any).ping === 'function') {
|
|
283
|
-
;(this.#ws as any).ping()
|
|
284
|
-
}
|
|
285
|
-
// also emit pong locally (CF WebSockets handle ping/pong at platform level)
|
|
286
|
-
this.emit('pong')
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
// standard EventTarget-style addEventListener (used by Connection)
|
|
290
|
-
// for 'message' events, wrap the handler so EventEmitter-style (data, isBinary)
|
|
291
|
-
// args get converted to DOM-style { data } events. streamOut uses
|
|
292
|
-
// addEventListener('message', ({data}) => ...) which needs DOM-style events.
|
|
293
|
-
#adapterMap = new WeakMap<Function, Function>()
|
|
294
|
-
|
|
295
|
-
addEventListener(type: string, handler: (event: any) => void): void {
|
|
296
|
-
if (type === 'message') {
|
|
297
|
-
const wrapper = (data: any, isBinary?: boolean) => {
|
|
298
|
-
// if already a DOM-style event object with .data, pass through
|
|
299
|
-
if (data && typeof data === 'object' && 'data' in data) {
|
|
300
|
-
handler(data)
|
|
301
|
-
} else {
|
|
302
|
-
handler({ data, isBinary })
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
this.#adapterMap.set(handler, wrapper)
|
|
306
|
-
this.on(type, wrapper)
|
|
307
|
-
} else {
|
|
308
|
-
this.on(type, handler)
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
removeEventListener(type: string, handler: (event: any) => void): void {
|
|
313
|
-
if (type === 'message') {
|
|
314
|
-
const wrapper = this.#adapterMap.get(handler)
|
|
315
|
-
if (wrapper) {
|
|
316
|
-
this.off(type, wrapper as any)
|
|
317
|
-
this.#adapterMap.delete(handler)
|
|
318
|
-
} else {
|
|
319
|
-
this.off(type, handler)
|
|
320
|
-
}
|
|
321
|
-
} else {
|
|
322
|
-
this.off(type, handler)
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
#setupListeners(): void {
|
|
327
|
-
// match ws npm package event signatures:
|
|
328
|
-
// message: (data: Buffer|string, isBinary: boolean)
|
|
329
|
-
// close: (code: number, reason: string)
|
|
330
|
-
// error: (err: Error)
|
|
331
|
-
const onMessage = (event: any) => {
|
|
332
|
-
const data = event.data
|
|
333
|
-
debugWS({ event: 'message', url: this.#url, ...summarizeWSData(data) })
|
|
334
|
-
this.emit('message', data, typeof data !== 'string')
|
|
335
|
-
}
|
|
336
|
-
const onClose = (event: any) => {
|
|
337
|
-
debugWS({
|
|
338
|
-
event: 'close',
|
|
339
|
-
url: this.#url,
|
|
340
|
-
code: event.code ?? 1000,
|
|
341
|
-
reason: event.reason ?? '',
|
|
342
|
-
})
|
|
343
|
-
this.emit('close', event.code ?? 1000, event.reason ?? '')
|
|
344
|
-
}
|
|
345
|
-
const onError = (event: any) => {
|
|
346
|
-
debugWS({
|
|
347
|
-
event: 'error',
|
|
348
|
-
url: this.#url,
|
|
349
|
-
message: event?.message ?? event?.error?.message ?? 'WebSocket error',
|
|
350
|
-
})
|
|
351
|
-
this.emit('error', event.error ?? new Error(event.message ?? 'WebSocket error'))
|
|
352
|
-
}
|
|
353
|
-
const onOpen = () => {
|
|
354
|
-
debugWS({ event: 'open', url: this.#url })
|
|
355
|
-
this.emit('open')
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
this.#ws.addEventListener('message', onMessage)
|
|
359
|
-
this.#ws.addEventListener('close', onClose)
|
|
360
|
-
this.#ws.addEventListener('error', onError)
|
|
361
|
-
this.#ws.addEventListener('open', onOpen)
|
|
362
|
-
|
|
363
|
-
this.#listeners.set('message', onMessage)
|
|
364
|
-
this.#listeners.set('close', onClose)
|
|
365
|
-
this.#listeners.set('error', onError)
|
|
366
|
-
this.#listeners.set('open', onOpen)
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
// -- WebSocketServer shim --
|
|
371
|
-
// zero-cache uses WebSocketServer with { noServer: true } for handleUpgrade
|
|
372
|
-
|
|
373
|
-
class WebSocketServer extends EventEmitter {
|
|
374
|
-
constructor(_opts?: { noServer?: boolean }) {
|
|
375
|
-
super()
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
close(cb?: (err?: Error) => void): void {
|
|
379
|
-
// no-op — browser embed has no real server to close
|
|
380
|
-
cb?.()
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
/**
|
|
384
|
-
* handle a WebSocket upgrade. on CF Workers the upgrade is already done
|
|
385
|
-
* (WebSocketPair), so this just wraps the CF WebSocket in our shim.
|
|
386
|
-
*
|
|
387
|
-
* @param message - the HTTP request (IncomingMessage-like object)
|
|
388
|
-
* @param socket - the underlying socket (CF WebSocket on CF Workers)
|
|
389
|
-
* @param head - upgrade head buffer
|
|
390
|
-
* @param callback - receives the wrapped WebSocket
|
|
391
|
-
*/
|
|
392
|
-
handleUpgrade(
|
|
393
|
-
_message: unknown,
|
|
394
|
-
socket: CFWebSocket | unknown,
|
|
395
|
-
_head: unknown,
|
|
396
|
-
callback: (ws: WebSocket) => void
|
|
397
|
-
): void {
|
|
398
|
-
// wrap the CF WebSocket in our shim
|
|
399
|
-
debugWS({ event: 'handle-upgrade' })
|
|
400
|
-
const ws = new WebSocket(socket as CFWebSocket)
|
|
401
|
-
callback(ws)
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
// -- createWebSocketStream --
|
|
406
|
-
// creates a Node.js Duplex stream from a WebSocket.
|
|
407
|
-
// used by zero-cache's Connection class for streaming messages.
|
|
408
|
-
|
|
409
|
-
function createWebSocketStream(
|
|
410
|
-
ws: WebSocket,
|
|
411
|
-
_opts?: { decodeStrings?: boolean }
|
|
412
|
-
): Duplex {
|
|
413
|
-
const duplex = new Duplex({
|
|
414
|
-
objectMode: false,
|
|
415
|
-
decodeStrings: false,
|
|
416
|
-
|
|
417
|
-
read() {
|
|
418
|
-
// data is pushed from ws message events
|
|
419
|
-
},
|
|
420
|
-
|
|
421
|
-
write(
|
|
422
|
-
chunk: Buffer | string,
|
|
423
|
-
_encoding: string,
|
|
424
|
-
callback: (err?: Error | null) => void
|
|
425
|
-
) {
|
|
426
|
-
try {
|
|
427
|
-
ws.send(typeof chunk === 'string' ? chunk : chunk.toString(), callback)
|
|
428
|
-
} catch (err) {
|
|
429
|
-
callback(err as Error)
|
|
430
|
-
}
|
|
431
|
-
},
|
|
432
|
-
|
|
433
|
-
destroy(err: Error | null, callback: (err?: Error | null) => void) {
|
|
434
|
-
ws.close()
|
|
435
|
-
callback(err)
|
|
436
|
-
},
|
|
437
|
-
})
|
|
438
|
-
|
|
439
|
-
// pipe ws messages into the readable side
|
|
440
|
-
ws.on('message', (event: any) => {
|
|
441
|
-
const data = event?.data ?? event
|
|
442
|
-
if (typeof data === 'string') {
|
|
443
|
-
duplex.push(data)
|
|
444
|
-
} else if (data instanceof ArrayBuffer) {
|
|
445
|
-
duplex.push(Buffer.from(data))
|
|
446
|
-
} else if (ArrayBuffer.isView(data)) {
|
|
447
|
-
duplex.push(Buffer.from(data.buffer, data.byteOffset, data.byteLength))
|
|
448
|
-
} else {
|
|
449
|
-
duplex.push(String(data))
|
|
450
|
-
}
|
|
451
|
-
})
|
|
452
|
-
|
|
453
|
-
ws.on('close', () => {
|
|
454
|
-
duplex.push(null) // signal end of readable
|
|
455
|
-
duplex.destroy()
|
|
456
|
-
})
|
|
457
|
-
|
|
458
|
-
ws.on('error', (event: any) => {
|
|
459
|
-
const err = event?.error ?? new Error(event?.message ?? 'WebSocket error')
|
|
460
|
-
duplex.destroy(err)
|
|
461
|
-
})
|
|
462
|
-
|
|
463
|
-
return duplex
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
export default WebSocket
|
|
467
|
-
export { WebSocket, WebSocketServer, createWebSocketStream }
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
const globalProcess = ((globalThis as any).process ??= {})
|
|
2
|
-
|
|
3
|
-
globalProcess.env ??= {}
|
|
4
|
-
globalProcess.pid ??= 1
|
|
5
|
-
globalProcess.argv ??= []
|
|
6
|
-
globalProcess.kill ??= () => true
|
|
7
|
-
|
|
8
|
-
globalProcess.env.SINGLE_PROCESS = '1'
|
|
9
|
-
globalProcess.env.NODE_ENV ??= 'development'
|
|
10
|
-
|
|
11
|
-
export {}
|
package/src/worker/types.ts
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* orez/worker types.
|
|
3
|
-
*
|
|
4
|
-
* interfaces for the embeddable orez worker that runs PGlite + change
|
|
5
|
-
* tracking without Node.js dependencies. designed for CF Workers/DO
|
|
6
|
-
* but usable in any JS runtime (browser, vitest, bun, deno).
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import type { Mutex } from '../mutex.js'
|
|
10
|
-
import type { ChangeRecord } from '../replication/change-tracker.js'
|
|
11
|
-
import type { ReplicationWriter } from '../replication/handler.js'
|
|
12
|
-
import type { PGlite, PGliteOptions, Results } from '@electric-sql/pglite'
|
|
13
|
-
|
|
14
|
-
/** options for creating an orez worker */
|
|
15
|
-
export interface OrezWorkerOptions {
|
|
16
|
-
/**
|
|
17
|
-
* pre-created PGlite instance. when provided, orez wraps it
|
|
18
|
-
* without managing its lifecycle (caller is responsible for closing).
|
|
19
|
-
*/
|
|
20
|
-
pglite?: PGlite
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* PGlite constructor options. used when `pglite` is not provided.
|
|
24
|
-
* in CF Workers, pass wasmModule/fsBundle/loadDataDir here.
|
|
25
|
-
*/
|
|
26
|
-
pgliteOptions?: PGliteOptions
|
|
27
|
-
|
|
28
|
-
/** publication names to track. defaults to all public tables. */
|
|
29
|
-
publications?: string[]
|
|
30
|
-
|
|
31
|
-
/** log level (default: 'warn') */
|
|
32
|
-
logLevel?: 'error' | 'warn' | 'info' | 'debug'
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/** the orez worker instance */
|
|
36
|
-
export interface OrezWorker {
|
|
37
|
-
/** the underlying PGlite instance */
|
|
38
|
-
readonly db: PGlite
|
|
39
|
-
|
|
40
|
-
/** mutex for serializing PGlite access */
|
|
41
|
-
readonly mutex: Mutex
|
|
42
|
-
|
|
43
|
-
/** run a parameterized query */
|
|
44
|
-
query<T extends Record<string, unknown> = Record<string, unknown>>(
|
|
45
|
-
sql: string,
|
|
46
|
-
params?: unknown[]
|
|
47
|
-
): Promise<Results<T>>
|
|
48
|
-
|
|
49
|
-
/** execute raw SQL (DDL, multi-statement) */
|
|
50
|
-
exec(sql: string): Promise<void>
|
|
51
|
-
|
|
52
|
-
/** install/reinstall change tracking triggers on all published tables */
|
|
53
|
-
installChangeTracking(): Promise<void>
|
|
54
|
-
|
|
55
|
-
/** get changes since a watermark */
|
|
56
|
-
getChangesSince(watermark: number, limit?: number): Promise<ChangeRecord[]>
|
|
57
|
-
|
|
58
|
-
/** get current watermark value */
|
|
59
|
-
getCurrentWatermark(): Promise<number>
|
|
60
|
-
|
|
61
|
-
/** purge consumed changes up to watermark */
|
|
62
|
-
purgeChanges(watermark: number): Promise<number>
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* start streaming replication to a writer.
|
|
66
|
-
* runs until the writer is closed or the worker is shut down.
|
|
67
|
-
*/
|
|
68
|
-
startReplication(writer: ReplicationWriter): Promise<void>
|
|
69
|
-
|
|
70
|
-
/** whether this worker owns the PGlite instance (manages its lifecycle) */
|
|
71
|
-
readonly ownsInstance: boolean
|
|
72
|
-
|
|
73
|
-
/** close the worker. if ownsInstance, also closes PGlite. */
|
|
74
|
-
close(): Promise<void>
|
|
75
|
-
}
|