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,188 +0,0 @@
1
- import { writeFileSync, unlinkSync } from 'node:fs'
2
- import { tmpdir } from 'node:os'
3
- import { join } from 'node:path'
4
-
5
- import { PGlite } from '@electric-sql/pglite'
6
- import { loadModule } from 'pgsql-parser'
7
- import postgres from 'postgres'
8
- import { describe, it, expect, beforeAll, afterEach } from 'vitest'
9
-
10
- import { execDumpFile } from './cli.js'
11
- import { getConfig } from './config.js'
12
- import { startPgProxy } from './pg-proxy.js'
13
-
14
- import type { Server } from 'node:net'
15
- import type { AddressInfo } from 'node:net'
16
-
17
- // generate a pg_dump-style SQL file with COPY data
18
- function generateDump(opts: {
19
- tables: number
20
- rowsPerTable: number
21
- columnsPerTable: number
22
- }): string {
23
- const lines: string[] = []
24
- lines.push('-- pg_dump style output')
25
- lines.push('SET statement_timeout = 0;')
26
- lines.push("SET client_encoding = 'UTF8';")
27
- lines.push('')
28
-
29
- for (let t = 0; t < opts.tables; t++) {
30
- const tableName = `test_table_${t}`
31
- const cols = Array.from({ length: opts.columnsPerTable }, (_, i) => `col_${i} TEXT`)
32
- lines.push(`CREATE TABLE ${tableName} (id SERIAL PRIMARY KEY, ${cols.join(', ')});`)
33
- lines.push('')
34
-
35
- // COPY block
36
- const colNames = Array.from({ length: opts.columnsPerTable }, (_, i) => `col_${i}`)
37
- lines.push(`COPY ${tableName} (id, ${colNames.join(', ')}) FROM stdin;`)
38
-
39
- for (let r = 0; r < opts.rowsPerTable; r++) {
40
- const vals = Array.from({ length: opts.columnsPerTable }, (_, i) => {
41
- if (r % 17 === 0 && i === 0) return '\\N'
42
- if (r % 13 === 0 && i === 1) return `value with tab\\there`
43
- if (r % 11 === 0 && i === 2) return `O'Brien's "quoted" value\\nwith newline`
44
- return `row_${r}_col_${i}_${'x'.repeat(20)}`
45
- })
46
- lines.push(`${r + 1}\t${vals.join('\t')}`)
47
- }
48
- lines.push('\\.')
49
- lines.push('')
50
- }
51
-
52
- return lines.join('\n')
53
- }
54
-
55
- describe('restore stress', () => {
56
- let tmpFile: string
57
-
58
- beforeAll(async () => {
59
- await loadModule()
60
- })
61
-
62
- afterEach(() => {
63
- try {
64
- unlinkSync(tmpFile)
65
- } catch {}
66
- })
67
-
68
- it('direct: 5 tables x 500 rows', async () => {
69
- const dump = generateDump({ tables: 5, rowsPerTable: 500, columnsPerTable: 5 })
70
- tmpFile = join(tmpdir(), `orez-stress-${Date.now()}.sql`)
71
- writeFileSync(tmpFile, dump)
72
-
73
- const db = new PGlite({ relaxedDurability: true })
74
- await db.waitReady
75
-
76
- const { executed, skipped } = await execDumpFile(db, tmpFile)
77
-
78
- for (let t = 0; t < 5; t++) {
79
- const result = await db.query(`SELECT count(*) as cnt FROM test_table_${t}`)
80
- expect(Number(result.rows[0].cnt)).toBe(500)
81
- }
82
-
83
- console.log(`direct: ${executed} executed, ${skipped} skipped`)
84
- await db.close()
85
- }, 60_000)
86
-
87
- it('direct: 2 tables x 5000 rows (memory pressure)', async () => {
88
- const dump = generateDump({ tables: 2, rowsPerTable: 5000, columnsPerTable: 5 })
89
- tmpFile = join(tmpdir(), `orez-stress-large-${Date.now()}.sql`)
90
- writeFileSync(tmpFile, dump)
91
-
92
- const db = new PGlite({ relaxedDurability: true })
93
- await db.waitReady
94
-
95
- const { executed, skipped } = await execDumpFile(db, tmpFile)
96
-
97
- for (let t = 0; t < 2; t++) {
98
- const result = await db.query(`SELECT count(*) as cnt FROM test_table_${t}`)
99
- expect(Number(result.rows[0].cnt)).toBe(5000)
100
- }
101
-
102
- console.log(`large direct: ${executed} executed, ${skipped} skipped`)
103
- await db.close()
104
- }, 120_000)
105
-
106
- it('wire: 3 tables x 1000 rows through pg proxy', async () => {
107
- const dump = generateDump({ tables: 3, rowsPerTable: 1000, columnsPerTable: 5 })
108
- tmpFile = join(tmpdir(), `orez-stress-wire-${Date.now()}.sql`)
109
- writeFileSync(tmpFile, dump)
110
-
111
- const db = new PGlite({ relaxedDurability: true })
112
- await db.waitReady
113
-
114
- const config = { ...getConfig(), pgPort: 0 }
115
- const server: Server = await startPgProxy(db, config)
116
- const port = (server.address() as AddressInfo).port
117
-
118
- try {
119
- const sql = postgres({
120
- host: '127.0.0.1',
121
- port,
122
- user: 'user',
123
- password: 'password',
124
- database: 'postgres',
125
- max: 1,
126
- })
127
-
128
- const wireDb = { exec: (query: string) => sql.unsafe(query) as Promise<unknown> }
129
- const { executed, skipped } = await execDumpFile(wireDb, tmpFile)
130
-
131
- for (let t = 0; t < 3; t++) {
132
- const result =
133
- await sql`SELECT count(*) as cnt FROM test_table_${sql.unsafe(String(t))}`
134
- // use direct db to verify
135
- }
136
-
137
- // verify via direct PGlite
138
- for (let t = 0; t < 3; t++) {
139
- const result = await db.query(`SELECT count(*) as cnt FROM test_table_${t}`)
140
- expect(Number(result.rows[0].cnt)).toBe(1000)
141
- }
142
-
143
- console.log(`wire: ${executed} executed, ${skipped} skipped`)
144
- await sql.end()
145
- } finally {
146
- server.close()
147
- await db.close()
148
- }
149
- }, 120_000)
150
-
151
- it('wire: 2 tables x 3000 rows (memory pressure via proxy)', async () => {
152
- const dump = generateDump({ tables: 2, rowsPerTable: 3000, columnsPerTable: 8 })
153
- tmpFile = join(tmpdir(), `orez-stress-wire-large-${Date.now()}.sql`)
154
- writeFileSync(tmpFile, dump)
155
-
156
- const db = new PGlite({ relaxedDurability: true })
157
- await db.waitReady
158
-
159
- const config = { ...getConfig(), pgPort: 0 }
160
- const server: Server = await startPgProxy(db, config)
161
- const port = (server.address() as AddressInfo).port
162
-
163
- try {
164
- const sql = postgres({
165
- host: '127.0.0.1',
166
- port,
167
- user: 'user',
168
- password: 'password',
169
- database: 'postgres',
170
- max: 1,
171
- })
172
-
173
- const wireDb = { exec: (query: string) => sql.unsafe(query) as Promise<unknown> }
174
- const { executed, skipped } = await execDumpFile(wireDb, tmpFile)
175
-
176
- for (let t = 0; t < 2; t++) {
177
- const result = await db.query(`SELECT count(*) as cnt FROM test_table_${t}`)
178
- expect(Number(result.rows[0].cnt)).toBe(3000)
179
- }
180
-
181
- console.log(`wire large: ${executed} executed, ${skipped} skipped`)
182
- await sql.end()
183
- } finally {
184
- server.close()
185
- await db.close()
186
- }
187
- }, 180_000)
188
- })
package/src/s3-local.ts DELETED
@@ -1,203 +0,0 @@
1
- /**
2
- * minimal local s3-compatible server.
3
- * handles GET/PUT/DELETE/HEAD for object storage.
4
- */
5
-
6
- import {
7
- existsSync,
8
- mkdirSync,
9
- readFileSync,
10
- readdirSync,
11
- writeFileSync,
12
- unlinkSync,
13
- statSync,
14
- } from 'node:fs'
15
- import {
16
- createServer,
17
- type Server,
18
- type IncomingMessage,
19
- type ServerResponse,
20
- } from 'node:http'
21
- import { join, dirname, extname } from 'node:path'
22
-
23
- import { log } from './log.js'
24
-
25
- export interface S3LocalConfig {
26
- port: number
27
- dataDir: string
28
- }
29
-
30
- const MIME_TYPES: Record<string, string> = {
31
- '.jpg': 'image/jpeg',
32
- '.jpeg': 'image/jpeg',
33
- '.png': 'image/png',
34
- '.gif': 'image/gif',
35
- '.webp': 'image/webp',
36
- '.svg': 'image/svg+xml',
37
- '.json': 'application/json',
38
- '.txt': 'text/plain',
39
- '.pdf': 'application/pdf',
40
- '.mp4': 'video/mp4',
41
- '.mp3': 'audio/mpeg',
42
- }
43
-
44
- function corsHeaders(): Record<string, string> {
45
- return {
46
- 'Access-Control-Allow-Origin': '*',
47
- 'Access-Control-Allow-Methods': 'GET, PUT, DELETE, HEAD, OPTIONS',
48
- 'Access-Control-Allow-Headers': '*',
49
- 'Access-Control-Expose-Headers': 'ETag, Content-Length',
50
- }
51
- }
52
-
53
- export function startS3Local(config: S3LocalConfig): Promise<Server> {
54
- const storageDir = join(config.dataDir, 's3')
55
- mkdirSync(storageDir, { recursive: true })
56
-
57
- const server = createServer((req: IncomingMessage, res: ServerResponse) => {
58
- const headers = corsHeaders()
59
-
60
- if (req.method === 'OPTIONS') {
61
- res.writeHead(200, headers)
62
- res.end()
63
- return
64
- }
65
-
66
- const url = new URL(req.url || '/', `http://localhost:${config.port}`)
67
-
68
- // sanitize path to prevent traversal
69
- const normalized = url.pathname
70
- .split('/')
71
- .filter((s) => s && s !== '..' && s !== '.')
72
- .join('/')
73
- const filePath = join(storageDir, normalized)
74
- if (!filePath.startsWith(storageDir)) {
75
- res.writeHead(403, headers)
76
- res.end()
77
- return
78
- }
79
-
80
- try {
81
- switch (req.method) {
82
- case 'GET': {
83
- // S3 ListObjectsV2: GET /?list-type=2&prefix=...&max-keys=...
84
- if (url.searchParams.get('list-type') === '2') {
85
- const prefix = url.searchParams.get('prefix') || ''
86
- const maxKeys = parseInt(url.searchParams.get('max-keys') || '1000')
87
- const baseDir = join(storageDir, prefix)
88
- const keys: string[] = []
89
-
90
- function walkList(dir: string) {
91
- if (keys.length >= maxKeys) return
92
- let entries
93
- try {
94
- entries = readdirSync(dir, { withFileTypes: true })
95
- } catch {
96
- return
97
- }
98
- for (const entry of entries) {
99
- if (keys.length >= maxKeys) break
100
- const full = join(dir, entry.name)
101
- if (entry.isDirectory()) {
102
- walkList(full)
103
- } else {
104
- const rel = full.slice(storageDir.length + 1)
105
- keys.push(rel)
106
- }
107
- }
108
- }
109
- walkList(baseDir)
110
-
111
- const keysXml = keys
112
- .map((k) => `<Contents><Key>${k}</Key></Contents>`)
113
- .join('')
114
- const xml = `<?xml version="1.0" encoding="UTF-8"?><ListBucketResult><KeyCount>${keys.length}</KeyCount>${keysXml}</ListBucketResult>`
115
- res.writeHead(200, { ...headers, 'Content-Type': 'application/xml' })
116
- res.end(xml)
117
- return
118
- }
119
-
120
- if (!existsSync(filePath) || statSync(filePath).isDirectory()) {
121
- res.writeHead(404, {
122
- ...headers,
123
- 'Content-Type': 'application/xml',
124
- })
125
- res.end('<Error><Code>NoSuchKey</Code></Error>')
126
- return
127
- }
128
- const data = readFileSync(filePath)
129
- const ext = extname(filePath)
130
- const contentType = MIME_TYPES[ext] || 'application/octet-stream'
131
- res.writeHead(200, {
132
- ...headers,
133
- 'Content-Type': contentType,
134
- 'Content-Length': data.length.toString(),
135
- ETag: `"${Buffer.from(data).length}"`,
136
- })
137
- res.end(data)
138
- break
139
- }
140
-
141
- case 'PUT': {
142
- const chunks: Buffer[] = []
143
- req.on('data', (chunk: Buffer) => chunks.push(chunk))
144
- req.on('end', () => {
145
- mkdirSync(dirname(filePath), { recursive: true })
146
- const body = Buffer.concat(chunks)
147
- writeFileSync(filePath, body)
148
- res.writeHead(200, {
149
- ...headers,
150
- ETag: `"${body.length}"`,
151
- })
152
- res.end()
153
- })
154
- break
155
- }
156
-
157
- case 'DELETE': {
158
- if (existsSync(filePath)) {
159
- unlinkSync(filePath)
160
- }
161
- res.writeHead(204, headers)
162
- res.end()
163
- break
164
- }
165
-
166
- case 'HEAD': {
167
- if (!existsSync(filePath) || statSync(filePath).isDirectory()) {
168
- res.writeHead(404, headers)
169
- res.end()
170
- return
171
- }
172
- const stat = statSync(filePath)
173
- const ext2 = extname(filePath)
174
- res.writeHead(200, {
175
- ...headers,
176
- 'Content-Type': MIME_TYPES[ext2] || 'application/octet-stream',
177
- 'Content-Length': stat.size.toString(),
178
- })
179
- res.end()
180
- break
181
- }
182
-
183
- default:
184
- res.writeHead(405, headers)
185
- res.end()
186
- }
187
- } catch {
188
- res.writeHead(500, {
189
- ...headers,
190
- 'Content-Type': 'application/xml',
191
- })
192
- res.end('<Error><Code>InternalError</Code></Error>')
193
- }
194
- })
195
-
196
- return new Promise((resolve, reject) => {
197
- server.listen(config.port, '127.0.0.1', () => {
198
- log.s3(`listening on port ${config.port}`)
199
- resolve(server)
200
- })
201
- server.on('error', reject)
202
- })
203
- }
@@ -1,120 +0,0 @@
1
- // esm loader hooks — intercept @rocicorp/zero-sqlite3 with bedrock-sqlite wasm.
2
- //
3
- // NOTE: this file is currently UNUSED. orez uses in-place CJS patching via
4
- // src/sqlite-mode/apply-mode.ts instead. this file is kept for potential future
5
- // use with Node.js ESM loader hooks (--import flag).
6
- //
7
- // __BEDROCK_PATH__ is replaced at runtime by orez before writing to tmpdir.
8
-
9
- const SHIM_URL = 'orez-sqlite-shim://shim'
10
- const BEDROCK_PATH = '__BEDROCK_PATH__'
11
- // __JOURNAL_MODE__ would be replaced at runtime (delete for wasm, wal2 for native)
12
- const JOURNAL_MODE = '__JOURNAL_MODE__'
13
-
14
- export function resolve(specifier, context, nextResolve) {
15
- if (
16
- specifier === '@rocicorp/zero-sqlite3' ||
17
- specifier.startsWith('@rocicorp/zero-sqlite3/')
18
- ) {
19
- return { url: SHIM_URL, shortCircuit: true }
20
- }
21
- return nextResolve(specifier, context)
22
- }
23
-
24
- export function load(url, context, nextLoad) {
25
- if (url === SHIM_URL) {
26
- // journal mode differs between native and wasm:
27
- // - native: wal2 for better concurrency
28
- // - wasm: delete for compatibility (wal2 can corrupt wasm vfs)
29
- const journalMode = JOURNAL_MODE === '__JOURNAL_MODE__' ? 'delete' : JOURNAL_MODE
30
-
31
- return {
32
- format: 'module',
33
- shortCircuit: true,
34
- source: `
35
- // orez sqlite shim - wraps bedrock-sqlite for zero-cache compatibility
36
- // journal_mode: ${journalMode}
37
-
38
- // catch uncaught exceptions from bedrock-sqlite wasm clearly
39
- process.on('uncaughtException', (err) => {
40
- console.error('[orez-shim] UNCAUGHT EXCEPTION:', err?.message || err);
41
- console.error('[orez-shim] code:', err?.code, 'name:', err?.name);
42
- console.error('[orez-shim] stack:', err?.stack?.split('\\n').slice(0, 5).join('\\n'));
43
- process.exit(1);
44
- });
45
-
46
- import { createRequire } from 'node:module';
47
- const require = createRequire('${BEDROCK_PATH}');
48
- const mod = require('${BEDROCK_PATH}');
49
- const OrigDatabase = mod.Database;
50
- const SqliteError = mod.SqliteError;
51
-
52
- function Database(...args) {
53
- const db = new OrigDatabase(...args);
54
- try {
55
- db.pragma('journal_mode = ${journalMode}');
56
- db.pragma('busy_timeout = 30000');
57
- db.pragma('synchronous = normal');
58
- } catch(e) {}
59
- return db;
60
- }
61
-
62
- Database.prototype = OrigDatabase.prototype;
63
- Database.prototype.constructor = Database;
64
- Object.keys(OrigDatabase).forEach(k => { Database[k] = OrigDatabase[k]; });
65
-
66
- // api polyfills for better-sqlite3 compatibility
67
- Database.prototype.unsafeMode = function() { return this; };
68
- if (!Database.prototype.defaultSafeIntegers) {
69
- Database.prototype.defaultSafeIntegers = function() { return this; };
70
- }
71
- if (!Database.prototype.serialize) {
72
- Database.prototype.serialize = function() { throw new Error('not supported in wasm'); };
73
- }
74
- if (!Database.prototype.backup) {
75
- Database.prototype.backup = function() { throw new Error('not supported in wasm'); };
76
- }
77
-
78
- // wrap pragma to skip optimize (can corrupt wasm vfs) and swallow sqlite errors
79
- const origPragma = OrigDatabase.prototype.pragma;
80
- Database.prototype.pragma = function(str, opts) {
81
- if (str && str.trim().toLowerCase().startsWith('optimize')) return [];
82
- try { return origPragma.call(this, str, opts); }
83
- catch(e) { if (e && (e.code === 'SQLITE_CORRUPT' || e.code === 'SQLITE_IOERR')) return []; throw e; }
84
- };
85
-
86
- // wrap close to swallow wasm errors during shutdown
87
- const origClose = OrigDatabase.prototype.close;
88
- Database.prototype.close = function() {
89
- try { return origClose.call(this); }
90
- catch(e) { console.error('[orez-shim] close error (swallowed):', e?.message || e); }
91
- };
92
-
93
- // statement prototype polyfills
94
- const tmpDb = new OrigDatabase(':memory:');
95
- const tmpStmt = tmpDb.prepare('SELECT 1');
96
- const SP = Object.getPrototypeOf(tmpStmt);
97
- if (!SP.safeIntegers) SP.safeIntegers = function() { return this; };
98
- SP.scanStatus = function() { return undefined; };
99
- SP.scanStatusV2 = function() { return []; };
100
- SP.scanStatusReset = function() {};
101
- tmpDb.close();
102
-
103
- // scanstat constants for query planner compatibility
104
- Database.SQLITE_SCANSTAT_NLOOP = 0;
105
- Database.SQLITE_SCANSTAT_NVISIT = 1;
106
- Database.SQLITE_SCANSTAT_EST = 2;
107
- Database.SQLITE_SCANSTAT_NAME = 3;
108
- Database.SQLITE_SCANSTAT_EXPLAIN = 4;
109
- Database.SQLITE_SCANSTAT_SELECTID = 5;
110
- Database.SQLITE_SCANSTAT_PARENTID = 6;
111
- Database.SQLITE_SCANSTAT_NCYCLE = 7;
112
- Database.SQLITE_SCANSTAT_COMPLEX = 8;
113
-
114
- export default Database;
115
- export { SqliteError };
116
- `,
117
- }
118
- }
119
- return nextLoad(url, context)
120
- }
@@ -1,4 +0,0 @@
1
- // --import entrypoint that registers the esm loader hooks.
2
- // __HOOKS_URL__ is replaced at runtime by orez before writing to tmpdir.
3
- import { register } from 'node:module'
4
- register('__HOOKS_URL__', import.meta.url)