orez 0.9.7 → 0.10.1

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 (249) hide show
  1. package/README.md +27 -19
  2. package/dist/config.d.ts +0 -4
  3. package/dist/config.d.ts.map +1 -1
  4. package/dist/config.js +0 -1
  5. package/dist/config.js.map +1 -1
  6. package/dist/index.d.ts +0 -1
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +5 -43
  9. package/dist/index.js.map +1 -1
  10. package/package.json +7 -71
  11. package/dist/cf-deploy/bundle.d.ts +0 -21
  12. package/dist/cf-deploy/bundle.d.ts.map +0 -1
  13. package/dist/cf-deploy/bundle.js +0 -347
  14. package/dist/cf-deploy/bundle.js.map +0 -1
  15. package/dist/cf-deploy/config.d.ts +0 -52
  16. package/dist/cf-deploy/config.d.ts.map +0 -1
  17. package/dist/cf-deploy/config.js +0 -23
  18. package/dist/cf-deploy/config.js.map +0 -1
  19. package/dist/cf-deploy/index.d.ts +0 -11
  20. package/dist/cf-deploy/index.d.ts.map +0 -1
  21. package/dist/cf-deploy/index.js +0 -17
  22. package/dist/cf-deploy/index.js.map +0 -1
  23. package/dist/cf-deploy/leaves.d.ts +0 -19
  24. package/dist/cf-deploy/leaves.d.ts.map +0 -1
  25. package/dist/cf-deploy/leaves.js +0 -109
  26. package/dist/cf-deploy/leaves.js.map +0 -1
  27. package/dist/cf-deploy/migration.d.ts +0 -40
  28. package/dist/cf-deploy/migration.d.ts.map +0 -1
  29. package/dist/cf-deploy/migration.js +0 -891
  30. package/dist/cf-deploy/migration.js.map +0 -1
  31. package/dist/cf-deploy/nativeMigrations.d.ts +0 -24
  32. package/dist/cf-deploy/nativeMigrations.d.ts.map +0 -1
  33. package/dist/cf-deploy/nativeMigrations.js +0 -185
  34. package/dist/cf-deploy/nativeMigrations.js.map +0 -1
  35. package/dist/cf-deploy/prune.d.ts +0 -14
  36. package/dist/cf-deploy/prune.d.ts.map +0 -1
  37. package/dist/cf-deploy/prune.js +0 -235
  38. package/dist/cf-deploy/prune.js.map +0 -1
  39. package/dist/cf-deploy/shims.d.ts +0 -13
  40. package/dist/cf-deploy/shims.d.ts.map +0 -1
  41. package/dist/cf-deploy/shims.js +0 -737
  42. package/dist/cf-deploy/shims.js.map +0 -1
  43. package/dist/cf-deploy/smoke.d.ts +0 -15
  44. package/dist/cf-deploy/smoke.d.ts.map +0 -1
  45. package/dist/cf-deploy/smoke.js +0 -141
  46. package/dist/cf-deploy/smoke.js.map +0 -1
  47. package/dist/cf-deploy/sources.d.ts +0 -9
  48. package/dist/cf-deploy/sources.d.ts.map +0 -1
  49. package/dist/cf-deploy/sources.js +0 -276
  50. package/dist/cf-deploy/sources.js.map +0 -1
  51. package/dist/cf-deploy/wrangler.d.ts +0 -6
  52. package/dist/cf-deploy/wrangler.d.ts.map +0 -1
  53. package/dist/cf-deploy/wrangler.js +0 -168
  54. package/dist/cf-deploy/wrangler.js.map +0 -1
  55. package/dist/cf-do/application-sql.d.ts +0 -49
  56. package/dist/cf-do/application-sql.d.ts.map +0 -1
  57. package/dist/cf-do/application-sql.js +0 -124
  58. package/dist/cf-do/application-sql.js.map +0 -1
  59. package/dist/cf-do/cdc.d.ts +0 -155
  60. package/dist/cf-do/cdc.d.ts.map +0 -1
  61. package/dist/cf-do/cdc.js +0 -719
  62. package/dist/cf-do/cdc.js.map +0 -1
  63. package/dist/cf-do/cursor-pull.d.ts +0 -27
  64. package/dist/cf-do/cursor-pull.d.ts.map +0 -1
  65. package/dist/cf-do/cursor-pull.js +0 -78
  66. package/dist/cf-do/cursor-pull.js.map +0 -1
  67. package/dist/cf-do/row-undo.d.ts +0 -36
  68. package/dist/cf-do/row-undo.d.ts.map +0 -1
  69. package/dist/cf-do/row-undo.js +0 -221
  70. package/dist/cf-do/row-undo.js.map +0 -1
  71. package/dist/cf-do/tx-journal.d.ts +0 -119
  72. package/dist/cf-do/tx-journal.d.ts.map +0 -1
  73. package/dist/cf-do/tx-journal.js +0 -718
  74. package/dist/cf-do/tx-journal.js.map +0 -1
  75. package/dist/cf-do/watermark.d.ts +0 -29
  76. package/dist/cf-do/watermark.d.ts.map +0 -1
  77. package/dist/cf-do/watermark.js +0 -105
  78. package/dist/cf-do/watermark.js.map +0 -1
  79. package/dist/cf-do/worker.d.ts +0 -287
  80. package/dist/cf-do/worker.d.ts.map +0 -1
  81. package/dist/cf-do/worker.js +0 -1961
  82. package/dist/cf-do/worker.js.map +0 -1
  83. package/dist/do-sql-tracking.d.ts +0 -104
  84. package/dist/do-sql-tracking.d.ts.map +0 -1
  85. package/dist/do-sql-tracking.js +0 -255
  86. package/dist/do-sql-tracking.js.map +0 -1
  87. package/dist/pg-proxy-do-backend.d.ts +0 -211
  88. package/dist/pg-proxy-do-backend.d.ts.map +0 -1
  89. package/dist/pg-proxy-do-backend.js +0 -7884
  90. package/dist/pg-proxy-do-backend.js.map +0 -1
  91. package/dist/pg-sqlite-compiler/catalog/seed.d.ts +0 -67
  92. package/dist/pg-sqlite-compiler/catalog/seed.d.ts.map +0 -1
  93. package/dist/pg-sqlite-compiler/catalog/seed.js +0 -436
  94. package/dist/pg-sqlite-compiler/catalog/seed.js.map +0 -1
  95. package/dist/pg-sqlite-compiler/compiler.d.ts +0 -17
  96. package/dist/pg-sqlite-compiler/compiler.d.ts.map +0 -1
  97. package/dist/pg-sqlite-compiler/compiler.js +0 -86
  98. package/dist/pg-sqlite-compiler/compiler.js.map +0 -1
  99. package/dist/pg-sqlite-compiler/index.d.ts +0 -2
  100. package/dist/pg-sqlite-compiler/index.d.ts.map +0 -1
  101. package/dist/pg-sqlite-compiler/index.js +0 -13
  102. package/dist/pg-sqlite-compiler/index.js.map +0 -1
  103. package/dist/pg-sqlite-compiler/passes/array.d.ts +0 -3
  104. package/dist/pg-sqlite-compiler/passes/array.d.ts.map +0 -1
  105. package/dist/pg-sqlite-compiler/passes/array.js +0 -223
  106. package/dist/pg-sqlite-compiler/passes/array.js.map +0 -1
  107. package/dist/pg-sqlite-compiler/passes/ast-utils.d.ts +0 -48
  108. package/dist/pg-sqlite-compiler/passes/ast-utils.d.ts.map +0 -1
  109. package/dist/pg-sqlite-compiler/passes/ast-utils.js +0 -93
  110. package/dist/pg-sqlite-compiler/passes/ast-utils.js.map +0 -1
  111. package/dist/pg-sqlite-compiler/passes/catalog.d.ts +0 -34
  112. package/dist/pg-sqlite-compiler/passes/catalog.d.ts.map +0 -1
  113. package/dist/pg-sqlite-compiler/passes/catalog.js +0 -30
  114. package/dist/pg-sqlite-compiler/passes/catalog.js.map +0 -1
  115. package/dist/pg-sqlite-compiler/passes/datetime.d.ts +0 -23
  116. package/dist/pg-sqlite-compiler/passes/datetime.d.ts.map +0 -1
  117. package/dist/pg-sqlite-compiler/passes/datetime.js +0 -55
  118. package/dist/pg-sqlite-compiler/passes/datetime.js.map +0 -1
  119. package/dist/pg-sqlite-compiler/passes/dml-cte.d.ts +0 -22
  120. package/dist/pg-sqlite-compiler/passes/dml-cte.d.ts.map +0 -1
  121. package/dist/pg-sqlite-compiler/passes/dml-cte.js +0 -161
  122. package/dist/pg-sqlite-compiler/passes/dml-cte.js.map +0 -1
  123. package/dist/pg-sqlite-compiler/passes/index.d.ts +0 -24
  124. package/dist/pg-sqlite-compiler/passes/index.d.ts.map +0 -1
  125. package/dist/pg-sqlite-compiler/passes/index.js +0 -52
  126. package/dist/pg-sqlite-compiler/passes/index.js.map +0 -1
  127. package/dist/pg-sqlite-compiler/passes/json-functions.d.ts +0 -3
  128. package/dist/pg-sqlite-compiler/passes/json-functions.d.ts.map +0 -1
  129. package/dist/pg-sqlite-compiler/passes/json-functions.js +0 -57
  130. package/dist/pg-sqlite-compiler/passes/json-functions.js.map +0 -1
  131. package/dist/pg-sqlite-compiler/passes/row-json.d.ts +0 -3
  132. package/dist/pg-sqlite-compiler/passes/row-json.d.ts.map +0 -1
  133. package/dist/pg-sqlite-compiler/passes/row-json.js +0 -230
  134. package/dist/pg-sqlite-compiler/passes/row-json.js.map +0 -1
  135. package/dist/pg-sqlite-compiler/passes/schema.d.ts +0 -4
  136. package/dist/pg-sqlite-compiler/passes/schema.d.ts.map +0 -1
  137. package/dist/pg-sqlite-compiler/passes/schema.js +0 -128
  138. package/dist/pg-sqlite-compiler/passes/schema.js.map +0 -1
  139. package/dist/pg-sqlite-compiler/passes/string-functions.d.ts +0 -11
  140. package/dist/pg-sqlite-compiler/passes/string-functions.d.ts.map +0 -1
  141. package/dist/pg-sqlite-compiler/passes/string-functions.js +0 -37
  142. package/dist/pg-sqlite-compiler/passes/string-functions.js.map +0 -1
  143. package/dist/pg-sqlite-compiler/passes/types.d.ts +0 -41
  144. package/dist/pg-sqlite-compiler/passes/types.d.ts.map +0 -1
  145. package/dist/pg-sqlite-compiler/passes/types.js +0 -115
  146. package/dist/pg-sqlite-compiler/passes/types.js.map +0 -1
  147. package/dist/pg-sqlite-compiler/passes/unsupported.d.ts +0 -3
  148. package/dist/pg-sqlite-compiler/passes/unsupported.d.ts.map +0 -1
  149. package/dist/pg-sqlite-compiler/passes/unsupported.js +0 -57
  150. package/dist/pg-sqlite-compiler/passes/unsupported.js.map +0 -1
  151. package/dist/pg-sqlite-compiler/test/oracle.d.ts +0 -34
  152. package/dist/pg-sqlite-compiler/test/oracle.d.ts.map +0 -1
  153. package/dist/pg-sqlite-compiler/test/oracle.js +0 -204
  154. package/dist/pg-sqlite-compiler/test/oracle.js.map +0 -1
  155. package/dist/pg-sqlite-compiler/types.d.ts +0 -66
  156. package/dist/pg-sqlite-compiler/types.d.ts.map +0 -1
  157. package/dist/pg-sqlite-compiler/types.js +0 -2
  158. package/dist/pg-sqlite-compiler/types.js.map +0 -1
  159. package/dist/sync-browser-host/generated/sqlite3-browser.wasm +0 -0
  160. package/dist/sync-browser-host/generated/sync_wasm.js +0 -922
  161. package/dist/sync-browser-host/generated/sync_wasm_bg.wasm +0 -0
  162. package/dist/sync-browser-host/host.d.ts +0 -10
  163. package/dist/sync-browser-host/host.d.ts.map +0 -1
  164. package/dist/sync-browser-host/host.js +0 -496
  165. package/dist/sync-browser-host/host.js.map +0 -1
  166. package/dist/sync-browser-host/idb-snapshot.d.ts +0 -11
  167. package/dist/sync-browser-host/idb-snapshot.d.ts.map +0 -1
  168. package/dist/sync-browser-host/idb-snapshot.js +0 -122
  169. package/dist/sync-browser-host/idb-snapshot.js.map +0 -1
  170. package/dist/sync-browser-host/index.d.ts +0 -5
  171. package/dist/sync-browser-host/index.d.ts.map +0 -1
  172. package/dist/sync-browser-host/index.js +0 -5
  173. package/dist/sync-browser-host/index.js.map +0 -1
  174. package/dist/sync-browser-host/message-port.d.ts +0 -7
  175. package/dist/sync-browser-host/message-port.d.ts.map +0 -1
  176. package/dist/sync-browser-host/message-port.js +0 -188
  177. package/dist/sync-browser-host/message-port.js.map +0 -1
  178. package/dist/sync-browser-host/sqlite-adapter.d.ts +0 -67
  179. package/dist/sync-browser-host/sqlite-adapter.d.ts.map +0 -1
  180. package/dist/sync-browser-host/sqlite-adapter.js +0 -145
  181. package/dist/sync-browser-host/sqlite-adapter.js.map +0 -1
  182. package/dist/sync-browser-host/types.d.ts +0 -52
  183. package/dist/sync-browser-host/types.d.ts.map +0 -1
  184. package/dist/sync-browser-host/types.js +0 -2
  185. package/dist/sync-browser-host/types.js.map +0 -1
  186. package/dist/sync-cf-host.d.ts +0 -2
  187. package/dist/sync-cf-host.d.ts.map +0 -1
  188. package/dist/sync-cf-host.js +0 -2
  189. package/dist/sync-cf-host.js.map +0 -1
  190. package/dist/sync-executor.d.ts +0 -2
  191. package/dist/sync-executor.d.ts.map +0 -1
  192. package/dist/sync-executor.js +0 -2
  193. package/dist/sync-executor.js.map +0 -1
  194. package/dist/wake.d.ts +0 -22
  195. package/dist/wake.d.ts.map +0 -1
  196. package/dist/wake.js +0 -114
  197. package/dist/wake.js.map +0 -1
  198. package/dist/worker/cf-do-shim.d.ts +0 -55
  199. package/dist/worker/cf-do-shim.d.ts.map +0 -1
  200. package/dist/worker/cf-do-shim.js +0 -58
  201. package/dist/worker/cf-do-shim.js.map +0 -1
  202. package/dist/worker/cf-patches.d.ts +0 -43
  203. package/dist/worker/cf-patches.d.ts.map +0 -1
  204. package/dist/worker/cf-patches.js +0 -840
  205. package/dist/worker/cf-patches.js.map +0 -1
  206. package/dist/worker/local-sql-backend.d.ts +0 -35
  207. package/dist/worker/local-sql-backend.d.ts.map +0 -1
  208. package/dist/worker/local-sql-backend.js +0 -217
  209. package/dist/worker/local-sql-backend.js.map +0 -1
  210. package/dist/worker/zero-cache-embed-cf.d.ts +0 -92
  211. package/dist/worker/zero-cache-embed-cf.d.ts.map +0 -1
  212. package/dist/worker/zero-cache-embed-cf.js +0 -764
  213. package/dist/worker/zero-cache-embed-cf.js.map +0 -1
  214. package/dist/worker/zero-sql-write-circuit.d.ts +0 -46
  215. package/dist/worker/zero-sql-write-circuit.d.ts.map +0 -1
  216. package/dist/worker/zero-sql-write-circuit.js +0 -161
  217. package/dist/worker/zero-sql-write-circuit.js.map +0 -1
  218. package/dist/zero-http/encrypted-column-codec.d.ts +0 -46
  219. package/dist/zero-http/encrypted-column-codec.d.ts.map +0 -1
  220. package/dist/zero-http/encrypted-column-codec.js +0 -676
  221. package/dist/zero-http/encrypted-column-codec.js.map +0 -1
  222. package/dist/zero-http/encrypted-column-conformance.d.ts +0 -7
  223. package/dist/zero-http/encrypted-column-conformance.d.ts.map +0 -1
  224. package/dist/zero-http/encrypted-column-conformance.js +0 -161
  225. package/dist/zero-http/encrypted-column-conformance.js.map +0 -1
  226. package/dist/zero-http/fixture-schema.d.ts +0 -127
  227. package/dist/zero-http/fixture-schema.d.ts.map +0 -1
  228. package/dist/zero-http/fixture-schema.js +0 -56
  229. package/dist/zero-http/fixture-schema.js.map +0 -1
  230. package/dist/zero-http/mount.d.ts +0 -71
  231. package/dist/zero-http/mount.d.ts.map +0 -1
  232. package/dist/zero-http/mount.js +0 -594
  233. package/dist/zero-http/mount.js.map +0 -1
  234. package/dist/zero-http/payload-codec.d.ts +0 -91
  235. package/dist/zero-http/payload-codec.d.ts.map +0 -1
  236. package/dist/zero-http/payload-codec.js +0 -10
  237. package/dist/zero-http/payload-codec.js.map +0 -1
  238. package/dist/zero-http/server.d.ts +0 -16
  239. package/dist/zero-http/server.d.ts.map +0 -1
  240. package/dist/zero-http/server.js +0 -270
  241. package/dist/zero-http/server.js.map +0 -1
  242. package/dist/zero-http/test-harness.d.ts +0 -32
  243. package/dist/zero-http/test-harness.d.ts.map +0 -1
  244. package/dist/zero-http/test-harness.js +0 -77
  245. package/dist/zero-http/test-harness.js.map +0 -1
  246. package/dist/zero-http/transport.d.ts +0 -71
  247. package/dist/zero-http/transport.d.ts.map +0 -1
  248. package/dist/zero-http/transport.js +0 -1106
  249. package/dist/zero-http/transport.js.map +0 -1
@@ -1,840 +0,0 @@
1
- /**
2
- * zero-cache CF Workers overlay.
3
- *
4
- * copies @rocicorp/zero's compiled `out/` tree into a generated overlay and
5
- * applies CF Worker patches there. the installed package in node_modules is
6
- * never modified.
7
- *
8
- * eleven patches:
9
- * 1. worker-urls.js — replace file:// URLs with zero-worker:// identifiers
10
- * 2. server worker entrypoints — disable CLI auto-start blocks
11
- * 3. worker state — localize log contexts and disable process-global telemetry
12
- * 4. processes.js — replace dynamic import() with static worker module lookup
13
- * 5. process lifecycle — stop and join a cancelled in-process worker tree
14
- * 6. write-worker-client.js — run zero-cache's replica writer in-process
15
- * 7. custom/fetch.js — route mutate/query fetches by logical DO identity
16
- * 8. initial-sync.js — cap DO batch parameter counts
17
- * 9. litestream commands.js — retain the durable replica on restart
18
- * 10. change-streamer-service.js — keep cleanup alive after no-subscriber ticks
19
- * 11. pgsql-parser — load libpg-query as a precompiled Worker wasm module
20
- *
21
- * usage in a worker build script:
22
- *
23
- * import { prepareZeroCacheForCF } from 'orez/worker/cf-patches'
24
- * import { getBrowserAliases } from 'orez/worker/browser-build-config'
25
- *
26
- * const zero = prepareZeroCacheForCF({ nodeModulesPath: './node_modules' })
27
- * const alias = getBrowserAliases(zero)
28
- *
29
- * idempotent: safe to run multiple times. the overlay directory is recreated.
30
- */
31
- import { cpSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, symlinkSync, writeFileSync, } from 'node:fs';
32
- import { dirname, resolve } from 'node:path';
33
- import { applyChangeLogCleanupRetryPatch } from '../zero-changelog-cleanup-patch.js';
34
- import { applyLitestreamRestoreGuard } from '../zero-litestream-patch.js';
35
- import { applyZeroMainArgvPatch, applyZeroWorkerArgvPatch, } from '../zero-worker-argv-patch.js';
36
- const ZERO_CACHE_WORKERS = [
37
- 'main',
38
- 'change-streamer',
39
- 'reaper',
40
- 'replicator',
41
- 'syncer',
42
- ];
43
- const CF_ZERO_VERSION = '1.7.0';
44
- // the stable prefix of every zero-cache worker's import-time auto-start guard.
45
- // flipping the condition to `false` neutralizes the call without depending on
46
- // the (version-volatile) runWorker(...) arguments that follow it.
47
- const WORKER_AUTOSTART_PREFIX = 'if (!singleProcessMode()) exitAfter(';
48
- const WORKER_AUTOSTART_DISABLED = 'if (false) /* orez-disable-autostart */ exitAfter(';
49
- export function prepareZeroCacheForCF(input) {
50
- const options = typeof input === 'string' ? { nodeModulesPath: input } : input;
51
- const nodeModulesPath = resolve(options.nodeModulesPath);
52
- const outDir = resolve(options.outDir ?? resolve(nodeModulesPath, '..', '.orez', 'zero-cache-cf'));
53
- const sourceZeroPackage = resolve(nodeModulesPath, '@rocicorp', 'zero');
54
- const sourceZeroOut = resolve(nodeModulesPath, '@rocicorp', 'zero', 'out');
55
- const sourceZeroPackageJson = resolve(sourceZeroPackage, 'package.json');
56
- const zeroOutDir = resolve(outDir, '@rocicorp', 'zero', 'out');
57
- const zcBase = resolve(zeroOutDir, 'zero-cache', 'src');
58
- if (!existsSync(sourceZeroOut)) {
59
- throw new Error(`@rocicorp/zero compiled out/ directory not found at ${sourceZeroOut}`);
60
- }
61
- const installedZeroVersion = JSON.parse(readFileSync(sourceZeroPackageJson, 'utf8')).version;
62
- if (installedZeroVersion !== CF_ZERO_VERSION) {
63
- throw new Error(`orez CF overlay supports @rocicorp/zero ${CF_ZERO_VERSION}, found ${String(installedZeroVersion)}`);
64
- }
65
- rmSync(outDir, { recursive: true, force: true });
66
- mkdirSync(dirname(zeroOutDir), { recursive: true });
67
- cpSync(sourceZeroOut, zeroOutDir, { recursive: true, dereference: true });
68
- if (existsSync(sourceZeroPackageJson)) {
69
- cpSync(sourceZeroPackageJson, resolve(outDir, '@rocicorp', 'zero', 'package.json'));
70
- }
71
- const overlayNodeModules = resolve(outDir, 'node_modules');
72
- linkPackageDependencies(dirname(dirname(realpathSync(sourceZeroPackage))), overlayNodeModules, {
73
- '@rocicorp/zero': resolve(outDir, '@rocicorp', 'zero'),
74
- });
75
- linkPackageDependencies(resolve(nodeModulesPath, '.bun', 'node_modules'), overlayNodeModules, {});
76
- patchWorkerUrls(zcBase);
77
- patchWorkerEntrypoints(zcBase);
78
- patchInstanceIsolation(zcBase);
79
- patchProcesses(zcBase);
80
- patchStartupShutdown(zcBase);
81
- patchWriteWorkerClient(zcBase);
82
- patchCustomFetch(zcBase);
83
- patchInitialSyncBatchParams(zcBase);
84
- patchLitestreamRestore(zcBase);
85
- patchChangeLogCleanupRetry(zcBase);
86
- const parserAliases = patchPgsqlParserWasm(nodeModulesPath, outDir);
87
- const packageAliases = getPackageAliases(nodeModulesPath);
88
- return {
89
- nodeModulesPath,
90
- outDir,
91
- zeroOutDir,
92
- zeroCacheSrcDir: zcBase,
93
- aliases: {
94
- '@rocicorp/zero/out/zero-cache/src/server/runner/run-worker.js': resolve(zeroOutDir, 'zero-cache', 'src', 'server', 'runner', 'run-worker.js'),
95
- '@rocicorp/zero/out/zero-cache/src/types/processes.js': resolve(zeroOutDir, 'zero-cache', 'src', 'types', 'processes.js'),
96
- ...packageAliases,
97
- ...parserAliases,
98
- },
99
- };
100
- }
101
- function patchWorkerUrls(zcBase) {
102
- const workerUrlsPath = resolve(zcBase, 'server', 'worker-urls.js');
103
- if (!existsSync(workerUrlsPath)) {
104
- throw new Error(`orez CF overlay: worker-urls.js missing at ${workerUrlsPath}`);
105
- }
106
- const content = readFileSync(workerUrlsPath, 'utf-8');
107
- // skip only when the verified Zero 1.7 worker graph is already present.
108
- if (content.includes('zero-worker://') && content.includes('SHADOW_SYNCER_URL')) {
109
- return;
110
- }
111
- writeFileSync(workerUrlsPath, `// patched by orez for CF Workers (replaces file:// URLs with identifiers)
112
- const u = (n) => new URL("zero-worker://" + n);
113
- export const MAIN_URL = u("main");
114
- export const CHANGE_STREAMER_URL = u("change-streamer");
115
- export const REAPER_URL = u("reaper");
116
- export const REPLICATOR_URL = u("replicator");
117
- export const SHADOW_SYNCER_URL = u("shadow-syncer");
118
- export const SYNCER_URL = u("syncer");
119
- // write-worker is spawned via 'new Worker()' (node:worker_threads), not via
120
- // childWorker() — it uses its own URL → worker resolution path. we still expose
121
- // it here so write-worker-client.js can import it without throwing.
122
- export const WRITE_WORKER_URL = u("write-worker");
123
- `);
124
- console.log('[orez] patched zero-cache worker-urls.js');
125
- }
126
- function patchWorkerEntrypoints(zcBase) {
127
- for (const entrypoint of ZERO_CACHE_WORKERS) {
128
- const entrypointPath = resolve(zcBase, 'server', `${entrypoint}.js`);
129
- if (!existsSync(entrypointPath)) {
130
- throw new Error(`orez CF overlay: worker entrypoint missing at ${entrypointPath}`);
131
- }
132
- const code = readFileSync(entrypointPath, 'utf-8');
133
- if (code.includes('orez-disable-autostart')) {
134
- continue;
135
- }
136
- // every entrypoint auto-starts itself at import time via
137
- // if (!singleProcessMode()) exitAfter(lc, () => runWorker(...))
138
- // the runWorker(...) call shape varies per worker and across zero versions
139
- // (1.6 added the `lc` arg to exitAfter, kept `...process.argv.slice(2)` on
140
- // some workers, and wrapped change-streamer's runWorker in a `.catch()` that
141
- // publishes startup errors). matching the whole call is brittle, so we only
142
- // touch the stable guard prefix: flipping the condition to `false` turns the
143
- // entire statement into dead code regardless of its arguments. CF embeds run
144
- // runWorker explicitly via childWorker, so nothing is lost.
145
- if (!code.includes(WORKER_AUTOSTART_PREFIX)) {
146
- throw new Error(`orez CF overlay: auto-start guard missing in ${entrypoint}.js`);
147
- }
148
- const next = code.split(WORKER_AUTOSTART_PREFIX).join(WORKER_AUTOSTART_DISABLED);
149
- writeFileSync(entrypointPath, next);
150
- console.log(`[orez] patched zero-cache ${entrypoint}.js (disabled auto-start)`);
151
- }
152
- }
153
- function patchInstanceIsolation(zcBase) {
154
- for (const entrypoint of ZERO_CACHE_WORKERS) {
155
- const entrypointPath = resolve(zcBase, 'server', `${entrypoint}.js`);
156
- let code = readFileSync(entrypointPath, 'utf8');
157
- if (code.includes('orez-instance-local-log-context'))
158
- continue;
159
- const declaration = 'var lc = new LogContext("info", {}, consoleLogSink);';
160
- const assignment = '\tlc = createLogContext(';
161
- if (code.split(declaration).length - 1 !== 1) {
162
- throw new Error(`orez CF overlay: expected one log context declaration in ${entrypoint}.js`);
163
- }
164
- if (code.split(assignment).length - 1 !== 1) {
165
- throw new Error(`orez CF overlay: expected one log context assignment in ${entrypoint}.js`);
166
- }
167
- code = code
168
- .replace(declaration, '/* orez-instance-local-log-context */\nconst lc = new LogContext("info", {}, consoleLogSink);')
169
- .replace(assignment, '\tconst lc = createLogContext(');
170
- writeFileSync(entrypointPath, code);
171
- }
172
- const eventsPath = resolve(zcBase, 'observability', 'events.js');
173
- const otelPath = resolve(zcBase, 'server', 'otel-start.js');
174
- const anonymousPath = resolve(zcBase, 'server', 'anonymous-otel-start.js');
175
- const dotenvPath = resolve(zcBase, '..', '..', 'shared', 'src', 'dotenv.js');
176
- for (const path of [eventsPath, otelPath, anonymousPath, dotenvPath]) {
177
- if (!existsSync(path)) {
178
- throw new Error(`orez CF overlay: telemetry module missing at ${path}`);
179
- }
180
- }
181
- writeFileSync(eventsPath, `// orez-instance-isolated-events: CF embeds do not share process event sinks.\nfunction initEventSink() {}\nasync function publishCriticalEvent(lc, event) {\n lc.info?.(\`ZeroEvent: \${event.type}\`, event);\n}\nfunction makeErrorDetails(value) {\n const error = value instanceof Error ? value : new Error(String(value));\n return { name: error.name, message: error.message, stack: error.stack };\n}\nexport { initEventSink, makeErrorDetails, publishCriticalEvent };\n`);
182
- writeFileSync(otelPath, `// orez-instance-isolated-otel: process-global OTel is disabled in CF embeds.\nfunction startOtelAuto() {}\nexport { startOtelAuto };\n`);
183
- writeFileSync(anonymousPath, `// orez-instance-isolated-anonymous-telemetry: process singleton disabled in CF embeds.\nconst noop = () => {};\nexport { noop as recordConnectionAttempted, noop as recordConnectionSuccess, noop as recordMutation, noop as recordQuery, noop as recordRowsSynced, noop as setActiveClientGroupsGetter, noop as setActiveUsersGetter, noop as startAnonymousTelemetry };\n`);
184
- writeFileSync(dotenvPath, '// orez-cf-dotenv-disabled: env is passed explicitly.\n');
185
- }
186
- function patchProcesses(zcBase) {
187
- const processesPath = resolve(zcBase, 'types', 'processes.js');
188
- if (!existsSync(processesPath)) {
189
- throw new Error(`orez CF overlay: processes.js missing at ${processesPath}`);
190
- }
191
- let code = readFileSync(processesPath, 'utf-8');
192
- const proxyGetAnchor = 'return Reflect.get(target, prop, receiver);';
193
- const proxyGetReplacement = 'const value = Reflect.get(target, prop, target); ' +
194
- 'if (typeof value !== "function") return value; ' +
195
- 'return (...args) => { const result = value.apply(target, args); ' +
196
- 'return result === target ? receiver : result; };';
197
- const patchProcessWrapperProxy = (source) => {
198
- const anchorCount = source.split(proxyGetAnchor).length - 1;
199
- if (anchorCount === 1)
200
- return source.replace(proxyGetAnchor, proxyGetReplacement);
201
- if (anchorCount === 0 && source.includes(proxyGetReplacement))
202
- return source;
203
- throw new Error('orez CF overlay: process wrapper proxy anchor missing');
204
- };
205
- if (code.includes('__zc_workers')) {
206
- for (const marker of [
207
- 'abandonOrezZeroWorkers',
208
- 'waitForOrezZeroWorkersStopped',
209
- '__orez_latched_signal',
210
- '__orez_track_worker',
211
- ]) {
212
- if (!code.includes(marker)) {
213
- throw new Error(`orez CF overlay: existing processes patch missing ${marker}`);
214
- }
215
- }
216
- applyZeroWorkerArgvPatch(processesPath);
217
- applyZeroMainArgvPatch(resolve(zcBase, 'server', 'main.js'));
218
- code = readFileSync(processesPath, 'utf-8');
219
- const patched = patchProcessWrapperProxy(code);
220
- if (patched !== code)
221
- writeFileSync(processesPath, patched);
222
- return;
223
- }
224
- applyZeroWorkerArgvPatch(processesPath);
225
- applyZeroMainArgvPatch(resolve(zcBase, 'server', 'main.js'));
226
- code = readFileSync(processesPath, 'utf-8');
227
- // add static imports of all zero-cache worker modules at the top.
228
- // these are relative to processes.js location in @rocicorp/zero.
229
- // NOTE: mutator.js and write-worker.js don't export a default `runWorker`
230
- // (mutator runs via auto-run guard, write-worker spawns via node:worker_threads
231
- // not via childWorker()), so they're not in the lookup table.
232
- const workerImports = `\
233
- // patched by orez for CF Workers (static imports replace dynamic import())
234
- import { default as __zc_main } from "../server/main.js";
235
- import { default as __zc_change_streamer } from "../server/change-streamer.js";
236
- import { default as __zc_reaper } from "../server/reaper.js";
237
- import { default as __zc_replicator } from "../server/replicator.js";
238
- import { default as __zc_syncer } from "../server/syncer.js";
239
- const __zc_workers = {
240
- "main": __zc_main,
241
- "change-streamer": __zc_change_streamer,
242
- "reaper": __zc_reaper,
243
- "replicator": __zc_replicator,
244
- "syncer": __zc_syncer,
245
- };
246
- const __orez_shutdown_signals = new Set(["SIGINT", "SIGTERM", "SIGQUIT", "SIGABRT"]);
247
- const __orez_latched_signal = Symbol("orez-latched-signal");
248
- const __orez_worker_executions = new Map();
249
- function __orez_track_worker(task, execution) {
250
- let active = __orez_worker_executions.get(task);
251
- if (!active) __orez_worker_executions.set(task, active = new Set());
252
- active.add(execution);
253
- void execution.finally(() => {
254
- active.delete(execution);
255
- if (active.size === 0 && __orez_worker_executions.get(task) === active) {
256
- __orez_worker_executions.delete(task);
257
- }
258
- }).catch(() => {});
259
- return execution;
260
- }
261
- function abandonOrezZeroWorkers(task) {
262
- __orez_worker_executions.delete(task);
263
- }
264
- async function waitForOrezZeroWorkersStopped(task) {
265
- for (;;) {
266
- const active = __orez_worker_executions.get(task);
267
- if (!active?.size) return;
268
- await Promise.allSettled([...active]);
269
- }
270
- }
271
- `;
272
- // replace the dynamic import in childWorker with a synchronous lookup.
273
- // original: import(moduleUrl.href).then(async ({ default: runWorker }) => ...
274
- // patched: lookup __zc_workers by name, then continue as before
275
- const dynamicImportPattern = 'import(moduleUrl.href).then(async ({ default: runWorker })';
276
- const staticLookup = '((async () => { ' +
277
- 'const _name = moduleUrl.hostname || moduleUrl.pathname.split("/").pop()?.replace(".js",""); ' +
278
- 'const _debug = env.OREZ_DEBUG_WIRE === "1"; ' +
279
- 'const _task = env.ZERO_TASK_ID || _name; ' +
280
- 'if (_debug) { ' +
281
- 'console.debug("[orez-zc-worker] start", _task, _name, args); ' +
282
- 'child.on("message", (msg) => console.debug("[orez-zc-worker] message", _task, _name, msg)); ' +
283
- 'child.on("error", (err) => console.error("[orez-zc-worker] error", _task, _name, err)); ' +
284
- 'child.on("close", (code, signal) => console.debug("[orez-zc-worker] close", _task, _name, code, signal)); ' +
285
- '} ' +
286
- 'const runWorkerImpl = __zc_workers[_name]; ' +
287
- 'if (!runWorkerImpl) throw new Error("orez: unknown zero-cache worker: " + _name + " (available: " + Object.keys(__zc_workers).join(", ") + ")"); ' +
288
- 'const runWorker = (...runArgs) => __orez_track_worker(_task, Promise.resolve().then(() => runWorkerImpl(...runArgs))); ' +
289
- 'return { default: runWorker, name: _name }; ' +
290
- '})()).then(async ({ default: runWorker, name })';
291
- if (!code.includes(dynamicImportPattern)) {
292
- throw new Error('orez CF overlay: dynamic import anchor missing in processes.js');
293
- }
294
- code = patchProcessWrapperProxy(code.replace(dynamicImportPattern, staticLookup));
295
- const signalKill = 'const kill = (dest) => (signal = "SIGTERM") => dest.emit(signal, signal);';
296
- const latchedSignalKill = `const kill = (dest) => (signal = "SIGTERM") => {
297
- dest[__orez_latched_signal] = signal;
298
- dest.emit(signal, signal);
299
- };`;
300
- if (!code.includes(signalKill)) {
301
- throw new Error('orez CF overlay: in-process signal anchor missing');
302
- }
303
- code = code.replace(signalKill, latchedSignalKill);
304
- const wrapSwitch = 'switch (prop) {';
305
- const wrapSwitchReplacement = `switch (prop) {
306
- case "on":
307
- case "once": return (type, handler) => {
308
- target[prop](type, handler);
309
- if (__orez_shutdown_signals.has(type) && target[__orez_latched_signal] === type) {
310
- queueMicrotask(() => {
311
- if (prop === "once") target.off(type, handler);
312
- handler(type);
313
- });
314
- }
315
- return receiver;
316
- };`;
317
- if (code.split(wrapSwitch).length - 1 !== 1) {
318
- throw new Error('orez CF overlay: process wrapper switch anchor missing');
319
- }
320
- code = code.replace(wrapSwitch, wrapSwitchReplacement);
321
- const exportAnchor = 'export { childWorker, parentWorker, singleProcessMode };';
322
- if (!code.includes(exportAnchor)) {
323
- throw new Error('orez CF overlay: process export anchor missing');
324
- }
325
- code = code.replace(exportAnchor, 'export { abandonOrezZeroWorkers, childWorker, parentWorker, singleProcessMode, waitForOrezZeroWorkersStopped };');
326
- code = workerImports + code;
327
- writeFileSync(processesPath, code);
328
- console.log('[orez] patched zero-cache processes.js (static worker imports)');
329
- }
330
- function patchStartupShutdown(zcBase) {
331
- const lifecyclePath = resolve(zcBase, 'services', 'life-cycle.js');
332
- if (!existsSync(lifecyclePath)) {
333
- throw new Error(`orez CF overlay: life-cycle.js missing at ${lifecyclePath}`);
334
- }
335
- const marker = 'OrezZeroStartupStoppedError';
336
- let code = readFileSync(lifecyclePath, 'utf-8');
337
- if (code.includes(marker)) {
338
- if (!code.includes('if (stopPromise) await stopPromise')) {
339
- throw new Error('orez CF overlay: existing lifecycle patch does not join shutdown');
340
- }
341
- patchMainStartupShutdown(zcBase);
342
- return;
343
- }
344
- const previous = `\tasync allWorkersReady() {
345
- \t\tawait Promise.all(this.#ready);
346
- \t}`;
347
- const patched = `\tasync allWorkersReady() {
348
- \t\tawait Promise.race([
349
- \t\t\tPromise.all(this.#ready),
350
- \t\t\tthis.#runningState.stopped().then(() => {
351
- \t\t\t\tconst error = new Error("zero-cache startup stopped before workers became ready");
352
- \t\t\t\terror.name = "${marker}";
353
- \t\t\t\tthrow error;
354
- \t\t\t}),
355
- \t\t]);
356
- \t}`;
357
- if (!code.includes(previous)) {
358
- throw new Error('orez CF overlay: allWorkersReady lifecycle anchor missing');
359
- }
360
- code = code.replace(previous, patched);
361
- const runUntilKilledStart = `async function runUntilKilled(lc, parent, ...services) {
362
- \tif (services.length === 0) return;
363
- \tfor (const signal of [...GRACEFUL_SHUTDOWN, ...FORCEFUL_SHUTDOWN]) parent.once(signal, () => {
364
- \t\tconst GRACEFUL_SIGNALS = GRACEFUL_SHUTDOWN;
365
- \t\tservices.forEach(async (svc) => {
366
- \t\t\tif (GRACEFUL_SIGNALS.includes(signal) && svc.drain) {
367
- \t\t\t\tlc.info?.(\`draining \${svc.constructor.name} \${svc.id} (\${signal})\`);
368
- \t\t\t\tawait svc.drain();
369
- \t\t\t}
370
- \t\t\tlc.info?.(\`stopping \${svc.constructor.name} \${svc.id} (\${signal})\`);
371
- \t\t\tawait svc.stop();
372
- \t\t});
373
- \t});`;
374
- const joinedRunUntilKilledStart = `async function runUntilKilled(lc, parent, ...services) {
375
- \tif (services.length === 0) return;
376
- \tlet stopPromise;
377
- \tfor (const signal of [...GRACEFUL_SHUTDOWN, ...FORCEFUL_SHUTDOWN]) parent.once(signal, () => {
378
- \t\tconst GRACEFUL_SIGNALS = GRACEFUL_SHUTDOWN;
379
- \t\tstopPromise ??= Promise.all(services.map(async (svc) => {
380
- \t\t\tif (GRACEFUL_SIGNALS.includes(signal) && svc.drain) {
381
- \t\t\t\tlc.info?.(\`draining \${svc.constructor.name} \${svc.id} (\${signal})\`);
382
- \t\t\t\tawait svc.drain();
383
- \t\t\t}
384
- \t\t\tlc.info?.(\`stopping \${svc.constructor.name} \${svc.id} (\${signal})\`);
385
- \t\t\tawait svc.stop();
386
- \t\t}));
387
- \t});`;
388
- if (!code.includes(runUntilKilledStart)) {
389
- throw new Error('orez CF overlay: runUntilKilled shutdown anchor missing');
390
- }
391
- code = code.replace(runUntilKilledStart, joinedRunUntilKilledStart);
392
- const serviceStopped = '\t\tconst svc = await Promise.race(services.map((svc) => svc.run().then(() => svc)));\n\t\tlc.info?.(`${svc.constructor.name} (${svc.id}) stopped`);';
393
- const serviceCleanupJoined = '\t\tconst svc = await Promise.race(services.map((svc) => svc.run().then(() => svc)));\n\t\tif (stopPromise) await stopPromise;\n\t\tlc.info?.(`${svc.constructor.name} (${svc.id}) stopped`);';
394
- if (!code.includes(serviceStopped)) {
395
- throw new Error('orez CF overlay: runUntilKilled completion anchor missing');
396
- }
397
- code = code.replace(serviceStopped, serviceCleanupJoined);
398
- writeFileSync(lifecyclePath, code);
399
- patchMainStartupShutdown(zcBase);
400
- console.log('[orez] patched zero-cache startup shutdown');
401
- }
402
- function patchMainStartupShutdown(zcBase) {
403
- const mainPath = resolve(zcBase, 'server', 'main.js');
404
- let code = readFileSync(mainPath, 'utf-8');
405
- const marker = '__orezAwaitStartup';
406
- if (code.includes(marker))
407
- return;
408
- const manager = '\tconst processes = new ProcessManager(lc, parent);';
409
- const managerWithBarrier = `${manager}
410
- \tconst ${marker} = (promise) => Promise.race([promise, processes.done().then(() => {
411
- \t\tconst error = new Error("zero-cache startup stopped before workers became ready");
412
- \t\terror.name = "OrezZeroStartupStoppedError";
413
- \t\tthrow error;
414
- \t})]);`;
415
- if (!code.includes(manager)) {
416
- throw new Error('orez CF overlay: main process manager anchor missing');
417
- }
418
- code = code.replace(manager, managerWithBarrier);
419
- const startupAwaits = [
420
- [
421
- 'await restoreReplica(lc, config, null)',
422
- `${marker}(restoreReplica(lc, config, null))`,
423
- ],
424
- ['await changeStreamerReady', `${marker}(changeStreamerReady)`],
425
- ['await backupReady', `${marker}(backupReady)`],
426
- ['await reaperReady', `${marker}(reaperReady)`],
427
- ['await shadowReady', `${marker}(shadowReady)`],
428
- ['await replicaReady', `${marker}(replicaReady)`],
429
- ];
430
- for (const [previousAwait, nextAwait] of startupAwaits) {
431
- const count = code.split(previousAwait).length - 1;
432
- if (count !== 1) {
433
- throw new Error(`orez CF overlay: expected one main startup await anchor for ${previousAwait}`);
434
- }
435
- code = code.replace(previousAwait, `await ${nextAwait}`);
436
- }
437
- writeFileSync(mainPath, code);
438
- }
439
- function patchWriteWorkerClient(zcBase) {
440
- const clientPath = resolve(zcBase, 'services', 'replicator', 'write-worker-client.js');
441
- if (!existsSync(clientPath)) {
442
- throw new Error(`orez CF overlay: write-worker-client.js missing at ${clientPath}`);
443
- }
444
- let code = readFileSync(clientPath, 'utf-8');
445
- if (code.includes('orez-inline-write-worker') &&
446
- code.includes('orezRole=replica-writer')) {
447
- return;
448
- }
449
- if (!code.includes('orez-inline-write-worker') &&
450
- !code.includes('import { Worker } from "node:worker_threads";')) {
451
- throw new Error('orez CF overlay: node:worker_threads anchor missing in write-worker-client.js');
452
- }
453
- writeFileSync(clientPath, `// patched by orez for CF Workers (orez-inline-write-worker)
454
- import { must } from "../../../../shared/src/must.js";
455
- import { Database } from "../../../../zqlite/src/db.js";
456
- import { createLogContext } from "../../server/logging.js";
457
- import { StatementRunner } from "../../db/statements.js";
458
- import { getSubscriptionState } from "./schema/replication-state.js";
459
- import { ChangeProcessor } from "./change-processor.js";
460
-
461
- function applyPragmas(db, pragmas) {
462
- db.pragma(\`busy_timeout = \${pragmas.busyTimeout}\`);
463
- db.pragma(\`analysis_limit = \${pragmas.analysisLimit}\`);
464
- if (pragmas.walAutocheckpoint !== void 0) {
465
- db.pragma(\`wal_autocheckpoint = \${pragmas.walAutocheckpoint}\`);
466
- }
467
- }
468
-
469
- // re-exported to keep this module's surface identical to upstream
470
- // write-worker-client.js (write-worker.js imports it). orez runs the writer
471
- // inline so the thread boundary that uses it is gone, but a complete export
472
- // surface keeps the bundler from choking if it pulls write-worker.js in.
473
- function serializeError(err) {
474
- if (!(err instanceof Error)) return {
475
- name: "Error",
476
- message: String(err),
477
- details: err && typeof err === "object" ? { ...err } : void 0
478
- };
479
- const details = Object.fromEntries(Object.getOwnPropertyNames(err).filter((key) => ![
480
- "name",
481
- "message",
482
- "stack",
483
- "cause"
484
- ].includes(key)).map((key) => [key, err[key]]));
485
- const cause = err.cause instanceof Error ? serializeError(err.cause) : err.cause === void 0 ? void 0 : String(err.cause);
486
- return {
487
- name: err.name,
488
- message: err.message,
489
- stack: err.stack,
490
- cause,
491
- details: Object.keys(details).length ? details : void 0
492
- };
493
- }
494
-
495
- function createAPI(onWriteError) {
496
- let db;
497
- let runner;
498
- let processor;
499
- let mode;
500
- let lc;
501
-
502
- function createProcessor() {
503
- processor = new ChangeProcessor(must(runner), must(mode), (_lc, err) => {
504
- onWriteError(err instanceof Error ? err : new Error(String(err)));
505
- });
506
- }
507
-
508
- return {
509
- init(dbPath, cpMode, pragmas, logConfig) {
510
- lc = createLogContext({ log: logConfig }, "write-worker");
511
- const separator = dbPath.includes("?") ? "&" : "?";
512
- db = new Database(lc, dbPath + separator + "orezRole=replica-writer");
513
- applyPragmas(db, pragmas);
514
- runner = new StatementRunner(db);
515
- mode = cpMode;
516
- createProcessor();
517
- },
518
- getSubscriptionState() {
519
- return getSubscriptionState(must(runner));
520
- },
521
- processMessage(downstream) {
522
- return must(processor).processMessage(must(lc), downstream);
523
- },
524
- abort() {
525
- must(processor).abort(must(lc));
526
- createProcessor();
527
- },
528
- stop() {
529
- db?.close();
530
- db = void 0;
531
- runner = void 0;
532
- processor = void 0;
533
- },
534
- };
535
- }
536
-
537
- class ThreadWriteWorkerClient {
538
- #api;
539
- #errorHandler = () => {};
540
- #writeError = null;
541
-
542
- constructor() {
543
- this.#api = createAPI((err) => {
544
- this.#writeError = err;
545
- this.#errorHandler(err);
546
- });
547
- }
548
-
549
- async #call(method, args) {
550
- if (this.#writeError) throw this.#writeError;
551
- try {
552
- const result = this.#api[method](...args);
553
- if (this.#writeError) throw this.#writeError;
554
- return result;
555
- } catch (err) {
556
- throw err instanceof Error ? err : new Error(String(err));
557
- }
558
- }
559
-
560
- init(dbPath, mode, pragmas, logConfig) {
561
- return this.#call("init", [dbPath, mode, pragmas, logConfig]);
562
- }
563
-
564
- getSubscriptionState() {
565
- return this.#call("getSubscriptionState", []);
566
- }
567
-
568
- processMessage(downstream) {
569
- return this.#call("processMessage", [downstream]);
570
- }
571
-
572
- abort() {
573
- if (!this.#writeError) {
574
- try {
575
- this.#api.abort();
576
- } catch {
577
- }
578
- }
579
- }
580
-
581
- async stop() {
582
- await this.#call("stop", []);
583
- }
584
-
585
- onError(handler) {
586
- this.#errorHandler = handler;
587
- }
588
- }
589
-
590
- export { ThreadWriteWorkerClient, applyPragmas, serializeError };
591
- `);
592
- console.log('[orez] patched zero-cache write-worker-client.js (inline writer)');
593
- }
594
- function patchCustomFetch(zcBase) {
595
- const customFetchPath = resolve(zcBase, 'custom', 'fetch.js');
596
- if (!existsSync(customFetchPath)) {
597
- throw new Error(`orez CF overlay: custom/fetch.js missing at ${customFetchPath}`);
598
- }
599
- let code = readFileSync(customFetchPath, 'utf8');
600
- if (code.includes('__orezFetchCFInstanceAPI')) {
601
- if (code.includes('fetchCFInstanceAPI as __orezFetchCFInstanceAPI') &&
602
- code.includes('await __orezFetchCFInstanceAPI(finalUrl, {')) {
603
- return;
604
- }
605
- throw new Error('orez CF overlay: custom fetch patch is incomplete');
606
- }
607
- const anchor = 'const response = await fetch(finalUrl, {';
608
- const count = code.split(anchor).length - 1;
609
- if (count !== 1) {
610
- throw new Error(`orez CF overlay: expected one custom fetch anchor, found ${count}`);
611
- }
612
- code =
613
- 'import { fetchCFInstanceAPI as __orezFetchCFInstanceAPI } from "orez/worker/cf-instance-runtime";\n' +
614
- code.replace(anchor, 'const response = await __orezFetchCFInstanceAPI(finalUrl, {');
615
- writeFileSync(customFetchPath, code);
616
- console.log('[orez] patched zero-cache custom fetch (instance-routed API host)');
617
- }
618
- // zero-cache's initial sync prepares a fixed 50-row multi-row INSERT per
619
- // copied table (insertSql + `,${valuesSql}`.repeat(49)). better-sqlite3
620
- // accepts thousands of bound parameters, but Cloudflare DO SQLite caps a
621
- // statement at 100 — the prepare alone throws "too many SQL variables" for
622
- // any table wider than 2 columns, killing initial sync before the first row.
623
- // derive the batch row count from the column count under a 96-param budget.
624
- //
625
- // upstream also buffers 10,000 rows before calling its synchronous flush().
626
- // on a DO every sql.exec in one synchronous turn is coalesced into one implicit
627
- // transaction. a single COPY chunk can therefore submit roughly 10k
628
- // application rows (about 21k including indexes) before the storage engine can
629
- // flush. keep each stream callback's storage burst small; postgres COPY still
630
- // streams the whole table.
631
- function patchInitialSyncBatchParams(zcBase) {
632
- const initialSyncPath = resolve(zcBase, 'services', 'change-source', 'pg', 'initial-sync.js');
633
- if (!existsSync(initialSyncPath)) {
634
- throw new Error(`orez CF overlay: initial-sync.js missing at ${initialSyncPath}`);
635
- }
636
- let code = readFileSync(initialSyncPath, 'utf-8');
637
- if (code.includes('orezRowsPerBatch'))
638
- return;
639
- const bufferAnchor = 'var MAX_BUFFERED_ROWS = 1e4;';
640
- const bufferAnchorCount = code.split(bufferAnchor).length - 1;
641
- if (bufferAnchorCount !== 1) {
642
- throw new Error(`orez CF overlay: expected 1 initial-sync buffer anchor, found ${bufferAnchorCount}`);
643
- }
644
- code = code.replace(bufferAnchor, 'var MAX_BUFFERED_ROWS = 256; /* orez-cf-storage-burst-cap */');
645
- // each pattern appears once in copyBinary and once in copyText
646
- const replacements = [
647
- [
648
- 'const insertBatchStmt = to.prepare(insertSql + `,${valuesSql}`.repeat(49));',
649
- 'const orezRowsPerBatch = Math.max(1, Math.floor(96 / Math.max(1, columnNames.length)));\n\tconst insertBatchStmt = to.prepare(insertSql + `,${valuesSql}`.repeat(orezRowsPerBatch - 1));',
650
- ],
651
- [
652
- 'const valuesPerBatch = valuesPerRow * 50;',
653
- 'const valuesPerBatch = valuesPerRow * orezRowsPerBatch;',
654
- ],
655
- [
656
- 'for (; pendingRows > 50; pendingRows -= 50) insertBatchStmt.run(pendingValues.slice(l, l += valuesPerBatch));',
657
- 'for (; pendingRows > orezRowsPerBatch; pendingRows -= orezRowsPerBatch) insertBatchStmt.run(pendingValues.slice(l, l += valuesPerBatch));',
658
- ],
659
- ];
660
- for (const [from, to] of replacements) {
661
- const count = code.split(from).length - 1;
662
- if (count !== 2) {
663
- throw new Error(`orez CF overlay: expected 2 initial-sync batch anchors, found ${count}`);
664
- }
665
- code = code.replaceAll(from, to);
666
- }
667
- writeFileSync(initialSyncPath, code);
668
- console.log('[orez] patched zero-cache initial-sync.js (DO bound-parameter cap batches)');
669
- }
670
- // the dedicated change-streamer calls restoreReplica() on every start; with no
671
- // litestream backup configured it throws ("Missing --litestream-executable")
672
- // and "recovers" by wiping + fully resyncing the replica — on workerd that
673
- // discards the durable DO-sqlite replica on EVERY embed cold boot, turning each
674
- // idle-teardown wake into a full resync. the node path patches this in-place
675
- // via disableZeroLitestreamRestore(); the CF overlay needs the same guard here.
676
- function patchLitestreamRestore(zcBase) {
677
- const commandsPath = resolve(zcBase, 'services', 'litestream', 'commands.js');
678
- if (!existsSync(commandsPath)) {
679
- throw new Error(`orez CF overlay: litestream commands.js missing at ${commandsPath}`);
680
- }
681
- applyLitestreamRestoreGuard(commandsPath);
682
- console.log('[orez] patched zero-cache litestream commands.js (no-op restore)');
683
- }
684
- function patchChangeLogCleanupRetry(zcBase) {
685
- const servicePath = resolve(zcBase, 'services', 'change-streamer', 'change-streamer-service.js');
686
- if (!existsSync(servicePath)) {
687
- throw new Error(`orez CF overlay: change-streamer service missing at ${servicePath}`);
688
- }
689
- applyChangeLogCleanupRetryPatch(servicePath);
690
- console.log('[orez] patched zero-cache changeLog cleanup retry');
691
- }
692
- function patchPgsqlParserWasm(nodeModulesPath, outDir) {
693
- const sourcePackagePath = findPackageRoot(nodeModulesPath, 'libpg-query');
694
- if (!sourcePackagePath) {
695
- throw new Error('orez CF overlay: libpg-query package is missing');
696
- }
697
- const targetPackagePath = resolve(outDir, 'node_modules', 'libpg-query');
698
- const parserIndexPath = resolve(targetPackagePath, 'wasm', 'index.js');
699
- const wasmPath = resolve(targetPackagePath, 'wasm', 'libpg-query.wasm');
700
- rmSync(targetPackagePath, { recursive: true, force: true });
701
- mkdirSync(dirname(targetPackagePath), { recursive: true });
702
- cpSync(sourcePackagePath, targetPackagePath, { recursive: true, dereference: true });
703
- if (!existsSync(parserIndexPath) || !existsSync(wasmPath)) {
704
- throw new Error('orez CF overlay: libpg-query wasm files are missing');
705
- }
706
- let code = readFileSync(parserIndexPath, 'utf-8');
707
- if (code.includes('orez-libpg-query-wasm-binary') &&
708
- code.includes('__orezLibPgQueryInit')) {
709
- return {
710
- 'libpg-query': targetPackagePath,
711
- 'libpg-query/wasm': parserIndexPath,
712
- 'libpg-query/wasm/index.js': parserIndexPath,
713
- };
714
- }
715
- if (code.includes('orez-libpg-query-wasm-binary')) {
716
- throw new Error('orez CF overlay: libpg-query wasm loader has an unsupported older patch');
717
- }
718
- const pattern = 'const initPromise = PgQueryModule().then((module) => {';
719
- if (!code.includes(pattern)) {
720
- throw new Error('orez CF overlay: PgQueryModule init anchor missing in libpg-query wasm index');
721
- }
722
- // workerd forbids compiling wasm from bytes at runtime (WebAssembly.instantiate
723
- // on raw bytes throws "Wasm code generation disallowed by embedder"), so we do
724
- // NOT embed the parser bytes and hand them to Emscripten. instead import the
725
- // parser wasm as a module — the CF bundler attaches it as a CompiledWasm worker
726
- // module (it lives next to this overlay at wasm/libpg-query.wasm) — and give
727
- // Emscripten a ready instance through its standard instantiateWasm hook.
728
- const replacement = `\
729
- // orez-libpg-query-wasm-binary: precompiled parser wasm module for CF Workers.
730
- import __orezLibPgQueryWasmModule from 'libpg-query/wasm/libpg-query.wasm';
731
- try {
732
- const g = globalThis;
733
- if (g.self && !g.self.location) g.self.location = { href: 'https://orez.local/libpg-query.js' };
734
- if (!g.location) g.location = { href: 'https://orez.local/libpg-query.js' };
735
- }
736
- catch {
737
- }
738
- const __orezLibPgQueryPreviousProcessType = globalThis.process?.type;
739
- if (globalThis.process && !globalThis.process.type) globalThis.process.type = 'renderer';
740
- const __orezLibPgQueryInit = PgQueryModule({
741
- instantiateWasm(imports, receiveInstance) {
742
- const instance = new WebAssembly.Instance(__orezLibPgQueryWasmModule, imports);
743
- receiveInstance(instance, __orezLibPgQueryWasmModule);
744
- return instance.exports;
745
- },
746
- });
747
- if (globalThis.process && __orezLibPgQueryPreviousProcessType === undefined) {
748
- delete globalThis.process.type;
749
- }
750
- else if (globalThis.process) {
751
- globalThis.process.type = __orezLibPgQueryPreviousProcessType;
752
- }
753
- const initPromise = __orezLibPgQueryInit.then((module) => {`;
754
- code = code.replace(pattern, replacement);
755
- writeFileSync(parserIndexPath, code);
756
- console.log('[orez] patched libpg-query wasm loader (precompiled wasm module)');
757
- return {
758
- 'libpg-query': targetPackagePath,
759
- 'libpg-query/wasm': parserIndexPath,
760
- 'libpg-query/wasm/index.js': parserIndexPath,
761
- };
762
- }
763
- function findPackageRoot(nodeModulesPath, packageName) {
764
- const candidates = [
765
- resolve(nodeModulesPath, packageName),
766
- resolve(nodeModulesPath, '.bun', 'node_modules', packageName),
767
- ...findBunPackageCandidates(nodeModulesPath, packageName),
768
- ];
769
- for (const candidate of candidates) {
770
- if (existsSync(resolve(candidate, 'package.json'))) {
771
- return candidate;
772
- }
773
- }
774
- return null;
775
- }
776
- function findBunPackageCandidates(nodeModulesPath, packageName) {
777
- const bunDir = resolve(nodeModulesPath, '.bun');
778
- if (!existsSync(bunDir))
779
- return [];
780
- const packageKey = packageName.replace('/', '+');
781
- return readdirSync(bunDir)
782
- .filter((entry) => entry === packageKey || entry.startsWith(`${packageKey}@`))
783
- .map((entry) => resolve(bunDir, entry, 'node_modules', packageName));
784
- }
785
- function getPackageAliases(nodeModulesPath) {
786
- const aliases = {};
787
- const packageAliases = {
788
- 'postgres-real': 'postgres',
789
- 'readable-stream': 'readable-stream',
790
- '@pgsql/types': '@pgsql/types',
791
- '@opentelemetry/semantic-conventions': '@opentelemetry/semantic-conventions',
792
- };
793
- for (const [alias, packageName] of Object.entries(packageAliases)) {
794
- const packageRoot = findPackageRoot(nodeModulesPath, packageName);
795
- if (packageRoot)
796
- aliases[alias] = packageRoot;
797
- }
798
- return aliases;
799
- }
800
- function linkPackageDependencies(sourceRoot, targetRoot, overrides) {
801
- if (!existsSync(sourceRoot))
802
- return;
803
- mkdirSync(targetRoot, { recursive: true });
804
- for (const entry of readdirSync(sourceRoot)) {
805
- if (entry.startsWith('.'))
806
- continue;
807
- const sourceEntry = resolve(sourceRoot, entry);
808
- const sourceEntryStat = lstatSync(sourceEntry);
809
- if (!sourceEntryStat.isDirectory() && !sourceEntryStat.isSymbolicLink()) {
810
- continue;
811
- }
812
- if (entry.startsWith('@')) {
813
- const targetScope = resolve(targetRoot, entry);
814
- mkdirSync(targetScope, { recursive: true });
815
- for (const scopedEntry of readdirSync(sourceEntry)) {
816
- const packageName = `${entry}/${scopedEntry}`;
817
- const sourcePackage = resolve(sourceEntry, scopedEntry);
818
- const targetPackage = resolve(targetScope, scopedEntry);
819
- linkPackage(overrides[packageName] ?? sourcePackage, targetPackage, Boolean(overrides[packageName]));
820
- }
821
- continue;
822
- }
823
- linkPackage(overrides[entry] ?? sourceEntry, resolve(targetRoot, entry), false);
824
- }
825
- for (const [packageName, target] of Object.entries(overrides)) {
826
- const targetPackage = resolve(targetRoot, ...packageName.split('/'));
827
- linkPackage(target, targetPackage, true);
828
- }
829
- }
830
- function linkPackage(source, target, replace) {
831
- if (replace) {
832
- rmSync(target, { recursive: true, force: true });
833
- }
834
- else if (existsSync(target)) {
835
- return;
836
- }
837
- mkdirSync(dirname(target), { recursive: true });
838
- symlinkSync(source, target, 'dir');
839
- }
840
- //# sourceMappingURL=cf-patches.js.map