orez 0.9.7 → 0.10.0
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/README.md +27 -19
- package/dist/config.d.ts +0 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +0 -1
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -43
- package/dist/index.js.map +1 -1
- package/package.json +7 -71
- package/dist/cf-deploy/bundle.d.ts +0 -21
- package/dist/cf-deploy/bundle.d.ts.map +0 -1
- package/dist/cf-deploy/bundle.js +0 -347
- package/dist/cf-deploy/bundle.js.map +0 -1
- package/dist/cf-deploy/config.d.ts +0 -52
- package/dist/cf-deploy/config.d.ts.map +0 -1
- package/dist/cf-deploy/config.js +0 -23
- package/dist/cf-deploy/config.js.map +0 -1
- package/dist/cf-deploy/index.d.ts +0 -11
- package/dist/cf-deploy/index.d.ts.map +0 -1
- package/dist/cf-deploy/index.js +0 -17
- package/dist/cf-deploy/index.js.map +0 -1
- package/dist/cf-deploy/leaves.d.ts +0 -19
- package/dist/cf-deploy/leaves.d.ts.map +0 -1
- package/dist/cf-deploy/leaves.js +0 -109
- package/dist/cf-deploy/leaves.js.map +0 -1
- package/dist/cf-deploy/migration.d.ts +0 -40
- package/dist/cf-deploy/migration.d.ts.map +0 -1
- package/dist/cf-deploy/migration.js +0 -891
- package/dist/cf-deploy/migration.js.map +0 -1
- package/dist/cf-deploy/nativeMigrations.d.ts +0 -24
- package/dist/cf-deploy/nativeMigrations.d.ts.map +0 -1
- package/dist/cf-deploy/nativeMigrations.js +0 -185
- package/dist/cf-deploy/nativeMigrations.js.map +0 -1
- package/dist/cf-deploy/prune.d.ts +0 -14
- package/dist/cf-deploy/prune.d.ts.map +0 -1
- package/dist/cf-deploy/prune.js +0 -235
- package/dist/cf-deploy/prune.js.map +0 -1
- package/dist/cf-deploy/shims.d.ts +0 -13
- package/dist/cf-deploy/shims.d.ts.map +0 -1
- package/dist/cf-deploy/shims.js +0 -737
- package/dist/cf-deploy/shims.js.map +0 -1
- package/dist/cf-deploy/smoke.d.ts +0 -15
- package/dist/cf-deploy/smoke.d.ts.map +0 -1
- package/dist/cf-deploy/smoke.js +0 -141
- package/dist/cf-deploy/smoke.js.map +0 -1
- package/dist/cf-deploy/sources.d.ts +0 -9
- package/dist/cf-deploy/sources.d.ts.map +0 -1
- package/dist/cf-deploy/sources.js +0 -276
- package/dist/cf-deploy/sources.js.map +0 -1
- package/dist/cf-deploy/wrangler.d.ts +0 -6
- package/dist/cf-deploy/wrangler.d.ts.map +0 -1
- package/dist/cf-deploy/wrangler.js +0 -168
- package/dist/cf-deploy/wrangler.js.map +0 -1
- package/dist/cf-do/application-sql.d.ts +0 -49
- package/dist/cf-do/application-sql.d.ts.map +0 -1
- package/dist/cf-do/application-sql.js +0 -124
- package/dist/cf-do/application-sql.js.map +0 -1
- package/dist/cf-do/cdc.d.ts +0 -155
- package/dist/cf-do/cdc.d.ts.map +0 -1
- package/dist/cf-do/cdc.js +0 -719
- package/dist/cf-do/cdc.js.map +0 -1
- package/dist/cf-do/cursor-pull.d.ts +0 -27
- package/dist/cf-do/cursor-pull.d.ts.map +0 -1
- package/dist/cf-do/cursor-pull.js +0 -78
- package/dist/cf-do/cursor-pull.js.map +0 -1
- package/dist/cf-do/row-undo.d.ts +0 -36
- package/dist/cf-do/row-undo.d.ts.map +0 -1
- package/dist/cf-do/row-undo.js +0 -221
- package/dist/cf-do/row-undo.js.map +0 -1
- package/dist/cf-do/tx-journal.d.ts +0 -119
- package/dist/cf-do/tx-journal.d.ts.map +0 -1
- package/dist/cf-do/tx-journal.js +0 -718
- package/dist/cf-do/tx-journal.js.map +0 -1
- package/dist/cf-do/watermark.d.ts +0 -29
- package/dist/cf-do/watermark.d.ts.map +0 -1
- package/dist/cf-do/watermark.js +0 -105
- package/dist/cf-do/watermark.js.map +0 -1
- package/dist/cf-do/worker.d.ts +0 -287
- package/dist/cf-do/worker.d.ts.map +0 -1
- package/dist/cf-do/worker.js +0 -1961
- package/dist/cf-do/worker.js.map +0 -1
- package/dist/do-sql-tracking.d.ts +0 -104
- package/dist/do-sql-tracking.d.ts.map +0 -1
- package/dist/do-sql-tracking.js +0 -255
- package/dist/do-sql-tracking.js.map +0 -1
- package/dist/pg-proxy-do-backend.d.ts +0 -211
- package/dist/pg-proxy-do-backend.d.ts.map +0 -1
- package/dist/pg-proxy-do-backend.js +0 -7884
- package/dist/pg-proxy-do-backend.js.map +0 -1
- package/dist/pg-sqlite-compiler/catalog/seed.d.ts +0 -67
- package/dist/pg-sqlite-compiler/catalog/seed.d.ts.map +0 -1
- package/dist/pg-sqlite-compiler/catalog/seed.js +0 -436
- package/dist/pg-sqlite-compiler/catalog/seed.js.map +0 -1
- package/dist/pg-sqlite-compiler/compiler.d.ts +0 -17
- package/dist/pg-sqlite-compiler/compiler.d.ts.map +0 -1
- package/dist/pg-sqlite-compiler/compiler.js +0 -86
- package/dist/pg-sqlite-compiler/compiler.js.map +0 -1
- package/dist/pg-sqlite-compiler/index.d.ts +0 -2
- package/dist/pg-sqlite-compiler/index.d.ts.map +0 -1
- package/dist/pg-sqlite-compiler/index.js +0 -13
- package/dist/pg-sqlite-compiler/index.js.map +0 -1
- package/dist/pg-sqlite-compiler/passes/array.d.ts +0 -3
- package/dist/pg-sqlite-compiler/passes/array.d.ts.map +0 -1
- package/dist/pg-sqlite-compiler/passes/array.js +0 -223
- package/dist/pg-sqlite-compiler/passes/array.js.map +0 -1
- package/dist/pg-sqlite-compiler/passes/ast-utils.d.ts +0 -48
- package/dist/pg-sqlite-compiler/passes/ast-utils.d.ts.map +0 -1
- package/dist/pg-sqlite-compiler/passes/ast-utils.js +0 -93
- package/dist/pg-sqlite-compiler/passes/ast-utils.js.map +0 -1
- package/dist/pg-sqlite-compiler/passes/catalog.d.ts +0 -34
- package/dist/pg-sqlite-compiler/passes/catalog.d.ts.map +0 -1
- package/dist/pg-sqlite-compiler/passes/catalog.js +0 -30
- package/dist/pg-sqlite-compiler/passes/catalog.js.map +0 -1
- package/dist/pg-sqlite-compiler/passes/datetime.d.ts +0 -23
- package/dist/pg-sqlite-compiler/passes/datetime.d.ts.map +0 -1
- package/dist/pg-sqlite-compiler/passes/datetime.js +0 -55
- package/dist/pg-sqlite-compiler/passes/datetime.js.map +0 -1
- package/dist/pg-sqlite-compiler/passes/dml-cte.d.ts +0 -22
- package/dist/pg-sqlite-compiler/passes/dml-cte.d.ts.map +0 -1
- package/dist/pg-sqlite-compiler/passes/dml-cte.js +0 -161
- package/dist/pg-sqlite-compiler/passes/dml-cte.js.map +0 -1
- package/dist/pg-sqlite-compiler/passes/index.d.ts +0 -24
- package/dist/pg-sqlite-compiler/passes/index.d.ts.map +0 -1
- package/dist/pg-sqlite-compiler/passes/index.js +0 -52
- package/dist/pg-sqlite-compiler/passes/index.js.map +0 -1
- package/dist/pg-sqlite-compiler/passes/json-functions.d.ts +0 -3
- package/dist/pg-sqlite-compiler/passes/json-functions.d.ts.map +0 -1
- package/dist/pg-sqlite-compiler/passes/json-functions.js +0 -57
- package/dist/pg-sqlite-compiler/passes/json-functions.js.map +0 -1
- package/dist/pg-sqlite-compiler/passes/row-json.d.ts +0 -3
- package/dist/pg-sqlite-compiler/passes/row-json.d.ts.map +0 -1
- package/dist/pg-sqlite-compiler/passes/row-json.js +0 -230
- package/dist/pg-sqlite-compiler/passes/row-json.js.map +0 -1
- package/dist/pg-sqlite-compiler/passes/schema.d.ts +0 -4
- package/dist/pg-sqlite-compiler/passes/schema.d.ts.map +0 -1
- package/dist/pg-sqlite-compiler/passes/schema.js +0 -128
- package/dist/pg-sqlite-compiler/passes/schema.js.map +0 -1
- package/dist/pg-sqlite-compiler/passes/string-functions.d.ts +0 -11
- package/dist/pg-sqlite-compiler/passes/string-functions.d.ts.map +0 -1
- package/dist/pg-sqlite-compiler/passes/string-functions.js +0 -37
- package/dist/pg-sqlite-compiler/passes/string-functions.js.map +0 -1
- package/dist/pg-sqlite-compiler/passes/types.d.ts +0 -41
- package/dist/pg-sqlite-compiler/passes/types.d.ts.map +0 -1
- package/dist/pg-sqlite-compiler/passes/types.js +0 -115
- package/dist/pg-sqlite-compiler/passes/types.js.map +0 -1
- package/dist/pg-sqlite-compiler/passes/unsupported.d.ts +0 -3
- package/dist/pg-sqlite-compiler/passes/unsupported.d.ts.map +0 -1
- package/dist/pg-sqlite-compiler/passes/unsupported.js +0 -57
- package/dist/pg-sqlite-compiler/passes/unsupported.js.map +0 -1
- package/dist/pg-sqlite-compiler/test/oracle.d.ts +0 -34
- package/dist/pg-sqlite-compiler/test/oracle.d.ts.map +0 -1
- package/dist/pg-sqlite-compiler/test/oracle.js +0 -204
- package/dist/pg-sqlite-compiler/test/oracle.js.map +0 -1
- package/dist/pg-sqlite-compiler/types.d.ts +0 -66
- package/dist/pg-sqlite-compiler/types.d.ts.map +0 -1
- package/dist/pg-sqlite-compiler/types.js +0 -2
- package/dist/pg-sqlite-compiler/types.js.map +0 -1
- package/dist/sync-browser-host/generated/sqlite3-browser.wasm +0 -0
- package/dist/sync-browser-host/generated/sync_wasm.js +0 -922
- package/dist/sync-browser-host/generated/sync_wasm_bg.wasm +0 -0
- package/dist/sync-browser-host/host.d.ts +0 -10
- package/dist/sync-browser-host/host.d.ts.map +0 -1
- package/dist/sync-browser-host/host.js +0 -496
- package/dist/sync-browser-host/host.js.map +0 -1
- package/dist/sync-browser-host/idb-snapshot.d.ts +0 -11
- package/dist/sync-browser-host/idb-snapshot.d.ts.map +0 -1
- package/dist/sync-browser-host/idb-snapshot.js +0 -122
- package/dist/sync-browser-host/idb-snapshot.js.map +0 -1
- package/dist/sync-browser-host/index.d.ts +0 -5
- package/dist/sync-browser-host/index.d.ts.map +0 -1
- package/dist/sync-browser-host/index.js +0 -5
- package/dist/sync-browser-host/index.js.map +0 -1
- package/dist/sync-browser-host/message-port.d.ts +0 -7
- package/dist/sync-browser-host/message-port.d.ts.map +0 -1
- package/dist/sync-browser-host/message-port.js +0 -188
- package/dist/sync-browser-host/message-port.js.map +0 -1
- package/dist/sync-browser-host/sqlite-adapter.d.ts +0 -67
- package/dist/sync-browser-host/sqlite-adapter.d.ts.map +0 -1
- package/dist/sync-browser-host/sqlite-adapter.js +0 -145
- package/dist/sync-browser-host/sqlite-adapter.js.map +0 -1
- package/dist/sync-browser-host/types.d.ts +0 -52
- package/dist/sync-browser-host/types.d.ts.map +0 -1
- package/dist/sync-browser-host/types.js +0 -2
- package/dist/sync-browser-host/types.js.map +0 -1
- package/dist/sync-cf-host.d.ts +0 -2
- package/dist/sync-cf-host.d.ts.map +0 -1
- package/dist/sync-cf-host.js +0 -2
- package/dist/sync-cf-host.js.map +0 -1
- package/dist/sync-executor.d.ts +0 -2
- package/dist/sync-executor.d.ts.map +0 -1
- package/dist/sync-executor.js +0 -2
- package/dist/sync-executor.js.map +0 -1
- package/dist/wake.d.ts +0 -22
- package/dist/wake.d.ts.map +0 -1
- package/dist/wake.js +0 -114
- package/dist/wake.js.map +0 -1
- package/dist/worker/cf-do-shim.d.ts +0 -55
- package/dist/worker/cf-do-shim.d.ts.map +0 -1
- package/dist/worker/cf-do-shim.js +0 -58
- package/dist/worker/cf-do-shim.js.map +0 -1
- package/dist/worker/cf-patches.d.ts +0 -43
- package/dist/worker/cf-patches.d.ts.map +0 -1
- package/dist/worker/cf-patches.js +0 -840
- package/dist/worker/cf-patches.js.map +0 -1
- package/dist/worker/local-sql-backend.d.ts +0 -35
- package/dist/worker/local-sql-backend.d.ts.map +0 -1
- package/dist/worker/local-sql-backend.js +0 -217
- package/dist/worker/local-sql-backend.js.map +0 -1
- package/dist/worker/zero-cache-embed-cf.d.ts +0 -92
- package/dist/worker/zero-cache-embed-cf.d.ts.map +0 -1
- package/dist/worker/zero-cache-embed-cf.js +0 -764
- package/dist/worker/zero-cache-embed-cf.js.map +0 -1
- package/dist/worker/zero-sql-write-circuit.d.ts +0 -46
- package/dist/worker/zero-sql-write-circuit.d.ts.map +0 -1
- package/dist/worker/zero-sql-write-circuit.js +0 -161
- package/dist/worker/zero-sql-write-circuit.js.map +0 -1
- package/dist/zero-http/encrypted-column-codec.d.ts +0 -46
- package/dist/zero-http/encrypted-column-codec.d.ts.map +0 -1
- package/dist/zero-http/encrypted-column-codec.js +0 -676
- package/dist/zero-http/encrypted-column-codec.js.map +0 -1
- package/dist/zero-http/encrypted-column-conformance.d.ts +0 -7
- package/dist/zero-http/encrypted-column-conformance.d.ts.map +0 -1
- package/dist/zero-http/encrypted-column-conformance.js +0 -161
- package/dist/zero-http/encrypted-column-conformance.js.map +0 -1
- package/dist/zero-http/fixture-schema.d.ts +0 -127
- package/dist/zero-http/fixture-schema.d.ts.map +0 -1
- package/dist/zero-http/fixture-schema.js +0 -56
- package/dist/zero-http/fixture-schema.js.map +0 -1
- package/dist/zero-http/mount.d.ts +0 -71
- package/dist/zero-http/mount.d.ts.map +0 -1
- package/dist/zero-http/mount.js +0 -594
- package/dist/zero-http/mount.js.map +0 -1
- package/dist/zero-http/payload-codec.d.ts +0 -91
- package/dist/zero-http/payload-codec.d.ts.map +0 -1
- package/dist/zero-http/payload-codec.js +0 -10
- package/dist/zero-http/payload-codec.js.map +0 -1
- package/dist/zero-http/server.d.ts +0 -16
- package/dist/zero-http/server.d.ts.map +0 -1
- package/dist/zero-http/server.js +0 -270
- package/dist/zero-http/server.js.map +0 -1
- package/dist/zero-http/test-harness.d.ts +0 -32
- package/dist/zero-http/test-harness.d.ts.map +0 -1
- package/dist/zero-http/test-harness.js +0 -77
- package/dist/zero-http/test-harness.js.map +0 -1
- package/dist/zero-http/transport.d.ts +0 -71
- package/dist/zero-http/transport.d.ts.map +0 -1
- package/dist/zero-http/transport.js +0 -1106
- 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
|