orez 0.1.36 → 0.1.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-entry.js +0 -0
- package/dist/cli.js +7 -1
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -11
- package/dist/index.js.map +1 -1
- package/dist/pg-proxy.d.ts.map +1 -1
- package/dist/pg-proxy.js +8 -4
- package/dist/pg-proxy.js.map +1 -1
- package/dist/pglite-manager.d.ts +12 -0
- package/dist/pglite-manager.d.ts.map +1 -1
- package/dist/pglite-manager.js +81 -0
- package/dist/pglite-manager.js.map +1 -1
- package/dist/recovery.js +2 -2
- package/dist/recovery.js.map +1 -1
- package/dist/replication/change-tracker.js +9 -9
- package/dist/replication/change-tracker.js.map +1 -1
- package/dist/replication/handler.d.ts +12 -0
- package/dist/replication/handler.d.ts.map +1 -1
- package/dist/replication/handler.js +32 -4
- package/dist/replication/handler.js.map +1 -1
- package/dist/worker/browser-build-config.d.ts +59 -0
- package/dist/worker/browser-build-config.d.ts.map +1 -0
- package/dist/worker/browser-build-config.js +101 -0
- package/dist/worker/browser-build-config.js.map +1 -0
- package/dist/worker/browser-embed.d.ts +58 -0
- package/dist/worker/browser-embed.d.ts.map +1 -0
- package/dist/worker/browser-embed.js +195 -0
- package/dist/worker/browser-embed.js.map +1 -0
- package/dist/worker/cf-patches.d.ts +20 -0
- package/dist/worker/cf-patches.d.ts.map +1 -0
- package/dist/worker/cf-patches.js +94 -0
- package/dist/worker/cf-patches.js.map +1 -0
- package/dist/worker/index.d.ts +12 -0
- package/dist/worker/index.d.ts.map +1 -0
- package/dist/worker/index.js +105 -0
- package/dist/worker/index.js.map +1 -0
- package/dist/worker/shims/fastify.d.ts +80 -0
- package/dist/worker/shims/fastify.d.ts.map +1 -0
- package/dist/worker/shims/fastify.js +223 -0
- package/dist/worker/shims/fastify.js.map +1 -0
- package/dist/worker/shims/http-service.d.ts +104 -0
- package/dist/worker/shims/http-service.d.ts.map +1 -0
- package/dist/worker/shims/http-service.js +198 -0
- package/dist/worker/shims/http-service.js.map +1 -0
- package/dist/worker/shims/node-stub.d.ts +147 -0
- package/dist/worker/shims/node-stub.d.ts.map +1 -0
- package/dist/worker/shims/node-stub.js +204 -0
- package/dist/worker/shims/node-stub.js.map +1 -0
- package/dist/worker/shims/postgres.d.ts +115 -0
- package/dist/worker/shims/postgres.d.ts.map +1 -0
- package/dist/worker/shims/postgres.js +1167 -0
- package/dist/worker/shims/postgres.js.map +1 -0
- package/dist/worker/shims/sqlite-browser.d.ts +54 -0
- package/dist/worker/shims/sqlite-browser.d.ts.map +1 -0
- package/dist/worker/shims/sqlite-browser.js +144 -0
- package/dist/worker/shims/sqlite-browser.js.map +1 -0
- package/dist/worker/shims/sqlite.d.ts +126 -0
- package/dist/worker/shims/sqlite.d.ts.map +1 -0
- package/dist/worker/shims/sqlite.js +599 -0
- package/dist/worker/shims/sqlite.js.map +1 -0
- package/dist/worker/shims/stream-browser.d.ts +9 -0
- package/dist/worker/shims/stream-browser.d.ts.map +1 -0
- package/dist/worker/shims/stream-browser.js +13 -0
- package/dist/worker/shims/stream-browser.js.map +1 -0
- package/dist/worker/shims/ws-browser.d.ts +50 -0
- package/dist/worker/shims/ws-browser.d.ts.map +1 -0
- package/dist/worker/shims/ws-browser.js +105 -0
- package/dist/worker/shims/ws-browser.js.map +1 -0
- package/dist/worker/shims/ws.d.ts +62 -0
- package/dist/worker/shims/ws.d.ts.map +1 -0
- package/dist/worker/shims/ws.js +310 -0
- package/dist/worker/shims/ws.js.map +1 -0
- package/dist/worker/types.d.ts +57 -0
- package/dist/worker/types.d.ts.map +1 -0
- package/dist/worker/types.js +9 -0
- package/dist/worker/types.js.map +1 -0
- package/dist/worker/zero-cache-embed-cf.d.ts +63 -0
- package/dist/worker/zero-cache-embed-cf.d.ts.map +1 -0
- package/dist/worker/zero-cache-embed-cf.js +268 -0
- package/dist/worker/zero-cache-embed-cf.js.map +1 -0
- package/dist/worker/zero-cache-embed.d.ts +66 -0
- package/dist/worker/zero-cache-embed.d.ts.map +1 -0
- package/dist/worker/zero-cache-embed.js +200 -0
- package/dist/worker/zero-cache-embed.js.map +1 -0
- package/package.json +62 -3
- package/src/cli-entry.ts +0 -0
- package/src/cli.ts +8 -1
- package/src/config.ts +2 -0
- package/src/index.ts +15 -10
- package/src/integration/integration.test.ts +1 -1
- package/src/integration/restore-live-stress.test.ts +2 -2
- package/src/pg-proxy.ts +9 -4
- package/src/pglite-manager.ts +111 -0
- package/src/recovery.ts +2 -2
- package/src/replication/change-tracker.test.ts +1 -1
- package/src/replication/change-tracker.ts +9 -9
- package/src/replication/handler.test.ts +37 -0
- package/src/replication/handler.ts +46 -4
- package/src/wasm-sqlite.test.ts +2 -1
- package/src/worker/browser-build-config.test.ts +59 -0
- package/src/worker/browser-build-config.ts +105 -0
- package/src/worker/browser-embed.ts +306 -0
- package/src/worker/cf-patches.ts +114 -0
- package/src/worker/embed-integration.test.ts +321 -0
- package/src/worker/index.ts +138 -0
- package/src/worker/shims/fastify.test.ts +255 -0
- package/src/worker/shims/fastify.ts +292 -0
- package/src/worker/shims/http-service.test.ts +355 -0
- package/src/worker/shims/http-service.ts +293 -0
- package/src/worker/shims/node-stub.ts +223 -0
- package/src/worker/shims/postgres.test.ts +364 -0
- package/src/worker/shims/postgres.ts +1419 -0
- package/src/worker/shims/sqlite-browser.test.ts +233 -0
- package/src/worker/shims/sqlite-browser.ts +178 -0
- package/src/worker/shims/sqlite.test.ts +641 -0
- package/src/worker/shims/sqlite.ts +731 -0
- package/src/worker/shims/ws-browser.test.ts +184 -0
- package/src/worker/shims/ws-browser.ts +125 -0
- package/src/worker/shims/ws.test.ts +288 -0
- package/src/worker/shims/ws.ts +367 -0
- package/src/worker/types.ts +75 -0
- package/src/worker/worker-integration.test.ts +223 -0
- package/src/worker/worker.test.ts +136 -0
- package/src/worker/zero-cache-embed-cf.ts +367 -0
- package/src/worker/zero-cache-embed.ts +277 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fastify shim for cloudflare workers.
|
|
3
|
+
*
|
|
4
|
+
* minimal fastify replacement that captures route registrations and
|
|
5
|
+
* exposes them via inject() for request processing. zero-cache's
|
|
6
|
+
* HttpService creates a Fastify instance, registers routes, and calls
|
|
7
|
+
* listen(). on CF Workers we skip listen() and route DO fetch()
|
|
8
|
+
* through inject().
|
|
9
|
+
*
|
|
10
|
+
* supports { websocket: true } routes: when a handoff event arrives on
|
|
11
|
+
* the server, matches against websocket routes and calls the handler
|
|
12
|
+
* with the socket directly. this enables the serving-replicator's
|
|
13
|
+
* in-process WebSocket connection to the change-streamer.
|
|
14
|
+
*
|
|
15
|
+
* usage with bundler alias:
|
|
16
|
+
* alias: { 'fastify': './src/worker/shims/fastify.js' }
|
|
17
|
+
*/
|
|
18
|
+
import EventEmitter from 'node:events';
|
|
19
|
+
import { WebSocketServer as WsServerShim } from './ws.js';
|
|
20
|
+
interface FastifyRequest {
|
|
21
|
+
headers: Record<string, string | undefined>;
|
|
22
|
+
url: string;
|
|
23
|
+
method: string;
|
|
24
|
+
body?: unknown;
|
|
25
|
+
query?: Record<string, string>;
|
|
26
|
+
params?: Record<string, string>;
|
|
27
|
+
}
|
|
28
|
+
interface FastifyReply {
|
|
29
|
+
code(statusCode: number): FastifyReply;
|
|
30
|
+
header(name: string, value: string): FastifyReply;
|
|
31
|
+
send(payload?: unknown): void;
|
|
32
|
+
type(contentType: string): FastifyReply;
|
|
33
|
+
status(statusCode: number): FastifyReply;
|
|
34
|
+
}
|
|
35
|
+
type RouteHandler = (request: FastifyRequest, reply: FastifyReply) => unknown | Promise<unknown>;
|
|
36
|
+
interface InjectOptions {
|
|
37
|
+
method: string;
|
|
38
|
+
url: string;
|
|
39
|
+
headers?: Record<string, string>;
|
|
40
|
+
payload?: string | null;
|
|
41
|
+
}
|
|
42
|
+
interface InjectResult {
|
|
43
|
+
statusCode: number;
|
|
44
|
+
headers: Record<string, string>;
|
|
45
|
+
body: string;
|
|
46
|
+
}
|
|
47
|
+
declare class FakeHttpServer extends EventEmitter {
|
|
48
|
+
#private;
|
|
49
|
+
address(): {
|
|
50
|
+
address: string;
|
|
51
|
+
port: number;
|
|
52
|
+
family: "IPv4";
|
|
53
|
+
};
|
|
54
|
+
/** match the onMessageType pattern from zero-cache processes.js */
|
|
55
|
+
onMessageType(type: string, handler: (msg: unknown, sendHandle?: unknown) => void): this;
|
|
56
|
+
listen(): void;
|
|
57
|
+
close(): void;
|
|
58
|
+
}
|
|
59
|
+
declare class FastifyShim {
|
|
60
|
+
#private;
|
|
61
|
+
server: FakeHttpServer;
|
|
62
|
+
websocketServer: WsServerShim;
|
|
63
|
+
constructor();
|
|
64
|
+
get(path: string, optsOrHandler: any, handler?: any): void;
|
|
65
|
+
post(path: string, handler: RouteHandler): void;
|
|
66
|
+
put(path: string, handler: RouteHandler): void;
|
|
67
|
+
delete(path: string, handler: RouteHandler): void;
|
|
68
|
+
register(_plugin: unknown, _opts?: unknown): this;
|
|
69
|
+
ready(): Promise<void>;
|
|
70
|
+
listen(_opts?: {
|
|
71
|
+
host?: string;
|
|
72
|
+
port?: number;
|
|
73
|
+
}): Promise<string>;
|
|
74
|
+
close(): Promise<void>;
|
|
75
|
+
inject(opts: InjectOptions): Promise<InjectResult>;
|
|
76
|
+
}
|
|
77
|
+
declare function Fastify(_opts?: unknown): FastifyShim;
|
|
78
|
+
export default Fastify;
|
|
79
|
+
export type { FastifyRequest, FastifyReply, FastifyShim };
|
|
80
|
+
//# sourceMappingURL=fastify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fastify.d.ts","sourceRoot":"","sources":["../../../src/worker/shims/fastify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,YAAY,MAAM,aAAa,CAAA;AAEtC,OAAO,EAAuB,eAAe,IAAI,YAAY,EAAE,MAAM,SAAS,CAAA;AAI9E,UAAU,cAAc;IACtB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;IAC3C,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAChC;AAED,UAAU,YAAY;IACpB,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY,CAAA;IACtC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,CAAA;IACjD,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IAC7B,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,YAAY,CAAA;IACvC,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY,CAAA;CACzC;AAED,KAAK,YAAY,GAAG,CAClB,OAAO,EAAE,cAAc,EACvB,KAAK,EAAE,YAAY,KAChB,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;AAE/B,UAAU,aAAa;IACrB,MAAM,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB;AAED,UAAU,YAAY;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,IAAI,EAAE,MAAM,CAAA;CACb;AAMD,cAAM,cAAe,SAAQ,YAAY;;IAGvC,OAAO;;;;;IAIP,mEAAmE;IACnE,aAAa,CACX,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,OAAO,KAAK,IAAI,GACpD,IAAI;IASP,MAAM;IAGN,KAAK;CAGN;AAkBD,cAAM,WAAW;;IACf,MAAM,EAAE,cAAc,CAAA;IACtB,eAAe,EAAE,YAAY,CAAA;;IA8C7B,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,GAAG;IAanD,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY;IAGxC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY;IAGvC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY;IAK1C,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,IAAI;IAK3C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAKtB,MAAM,CAAC,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAKjE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAKtB,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;CAwEzD;AAYD,iBAAS,OAAO,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,WAAW,CAK7C;AAED,eAAe,OAAO,CAAA;AACtB,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,WAAW,EAAE,CAAA"}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fastify shim for cloudflare workers.
|
|
3
|
+
*
|
|
4
|
+
* minimal fastify replacement that captures route registrations and
|
|
5
|
+
* exposes them via inject() for request processing. zero-cache's
|
|
6
|
+
* HttpService creates a Fastify instance, registers routes, and calls
|
|
7
|
+
* listen(). on CF Workers we skip listen() and route DO fetch()
|
|
8
|
+
* through inject().
|
|
9
|
+
*
|
|
10
|
+
* supports { websocket: true } routes: when a handoff event arrives on
|
|
11
|
+
* the server, matches against websocket routes and calls the handler
|
|
12
|
+
* with the socket directly. this enables the serving-replicator's
|
|
13
|
+
* in-process WebSocket connection to the change-streamer.
|
|
14
|
+
*
|
|
15
|
+
* usage with bundler alias:
|
|
16
|
+
* alias: { 'fastify': './src/worker/shims/fastify.js' }
|
|
17
|
+
*/
|
|
18
|
+
import EventEmitter from 'node:events';
|
|
19
|
+
import { WebSocket as WsShim, WebSocketServer as WsServerShim } from './ws.js';
|
|
20
|
+
// -- fake http.Server replacement --
|
|
21
|
+
// uses EventEmitter with onMessageType for zero-cache's
|
|
22
|
+
// installWebSocketHandoff non-Server branch.
|
|
23
|
+
class FakeHttpServer extends EventEmitter {
|
|
24
|
+
#address = { address: '0.0.0.0', port: 0, family: 'IPv4' };
|
|
25
|
+
address() {
|
|
26
|
+
return this.#address;
|
|
27
|
+
}
|
|
28
|
+
/** match the onMessageType pattern from zero-cache processes.js */
|
|
29
|
+
onMessageType(type, handler) {
|
|
30
|
+
this.on('message', (data, sendHandle) => {
|
|
31
|
+
if (Array.isArray(data) && data.length === 2 && data[0] === type) {
|
|
32
|
+
handler(data[1], sendHandle);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
return this;
|
|
36
|
+
}
|
|
37
|
+
listen() {
|
|
38
|
+
/* no-op on CF */
|
|
39
|
+
}
|
|
40
|
+
close() {
|
|
41
|
+
/* no-op on CF */
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// use the real WebSocketServer from the WS shim — it wraps raw sockets
|
|
45
|
+
// in a proper WebSocket class with ping/pong/on/emit etc.
|
|
46
|
+
// -- route pattern matching --
|
|
47
|
+
// converts fastify route patterns like "/replication/:version/changes"
|
|
48
|
+
// to regex for matching incoming URLs
|
|
49
|
+
function patternToRegex(pattern) {
|
|
50
|
+
const escaped = pattern
|
|
51
|
+
.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
52
|
+
.replace(/:(\w+)/g, '(?<$1>[^/]+)');
|
|
53
|
+
return new RegExp(`^${escaped}$`);
|
|
54
|
+
}
|
|
55
|
+
// -- fastify shim instance --
|
|
56
|
+
class FastifyShim {
|
|
57
|
+
server;
|
|
58
|
+
websocketServer;
|
|
59
|
+
#routes = new Map();
|
|
60
|
+
#wsRoutes = [];
|
|
61
|
+
#readyResolvers = [];
|
|
62
|
+
constructor() {
|
|
63
|
+
this.server = new FakeHttpServer();
|
|
64
|
+
this.websocketServer = new WsServerShim();
|
|
65
|
+
this.#installWsHandoffHandler();
|
|
66
|
+
}
|
|
67
|
+
// listen for in-process WebSocket handoff events on the server.
|
|
68
|
+
// when the WS shim creates an in-process connection, it emits a handoff
|
|
69
|
+
// event. we match the URL against registered { websocket: true } routes
|
|
70
|
+
// and call the handler with the socket.
|
|
71
|
+
#installWsHandoffHandler() {
|
|
72
|
+
this.server.onMessageType('handoff', (msg, socket) => {
|
|
73
|
+
if (!socket || !msg?.message?.url)
|
|
74
|
+
return;
|
|
75
|
+
const url = msg.message.url;
|
|
76
|
+
const parsedUrl = new URL(url, 'http://localhost');
|
|
77
|
+
const pathname = parsedUrl.pathname;
|
|
78
|
+
for (const route of this.#wsRoutes) {
|
|
79
|
+
if (route.pattern.test(pathname)) {
|
|
80
|
+
const req = {
|
|
81
|
+
url,
|
|
82
|
+
headers: msg.message.headers || {},
|
|
83
|
+
method: msg.message.method || 'GET',
|
|
84
|
+
};
|
|
85
|
+
// wrap socket through handleUpgrade so it gets the full WS API
|
|
86
|
+
// (ping, on, once, terminate, etc.) needed by zero-cache's streamOut
|
|
87
|
+
this.websocketServer.handleUpgrade(req, socket, Buffer.from(new Uint8Array(0)), (ws) => {
|
|
88
|
+
route.handler(ws, req);
|
|
89
|
+
});
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
// route registration — supports optional { websocket: true } option
|
|
96
|
+
get(path, optsOrHandler, handler) {
|
|
97
|
+
if (typeof optsOrHandler === 'function') {
|
|
98
|
+
this.#routes.set(`GET:${path}`, optsOrHandler);
|
|
99
|
+
}
|
|
100
|
+
else if (optsOrHandler?.websocket && handler) {
|
|
101
|
+
// websocket route — register for handoff matching
|
|
102
|
+
this.#wsRoutes.push({
|
|
103
|
+
pattern: patternToRegex(path),
|
|
104
|
+
handler,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
else if (handler) {
|
|
108
|
+
this.#routes.set(`GET:${path}`, handler);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
post(path, handler) {
|
|
112
|
+
this.#routes.set(`POST:${path}`, handler);
|
|
113
|
+
}
|
|
114
|
+
put(path, handler) {
|
|
115
|
+
this.#routes.set(`PUT:${path}`, handler);
|
|
116
|
+
}
|
|
117
|
+
delete(path, handler) {
|
|
118
|
+
this.#routes.set(`DELETE:${path}`, handler);
|
|
119
|
+
}
|
|
120
|
+
// plugin registration (no-op — zero-cache registers @fastify/websocket here)
|
|
121
|
+
register(_plugin, _opts) {
|
|
122
|
+
return this;
|
|
123
|
+
}
|
|
124
|
+
// lifecycle
|
|
125
|
+
async ready() {
|
|
126
|
+
for (const resolve of this.#readyResolvers)
|
|
127
|
+
resolve();
|
|
128
|
+
this.#readyResolvers = [];
|
|
129
|
+
}
|
|
130
|
+
async listen(_opts) {
|
|
131
|
+
await this.ready();
|
|
132
|
+
return '0.0.0.0:0';
|
|
133
|
+
}
|
|
134
|
+
async close() {
|
|
135
|
+
// no-op on CF
|
|
136
|
+
}
|
|
137
|
+
// inject — process a request through registered routes
|
|
138
|
+
async inject(opts) {
|
|
139
|
+
const method = opts.method.toUpperCase();
|
|
140
|
+
const urlObj = new URL(opts.url, 'http://localhost');
|
|
141
|
+
const pathname = urlObj.pathname;
|
|
142
|
+
// find matching route
|
|
143
|
+
const handler = this.#routes.get(`${method}:${pathname}`);
|
|
144
|
+
if (!handler) {
|
|
145
|
+
return { statusCode: 404, headers: {}, body: 'Not Found' };
|
|
146
|
+
}
|
|
147
|
+
// build fake request
|
|
148
|
+
const request = {
|
|
149
|
+
headers: opts.headers || {},
|
|
150
|
+
url: opts.url,
|
|
151
|
+
method,
|
|
152
|
+
body: opts.payload ? tryParseJson(opts.payload) : undefined,
|
|
153
|
+
query: Object.fromEntries(urlObj.searchParams),
|
|
154
|
+
params: {},
|
|
155
|
+
};
|
|
156
|
+
// build fake reply
|
|
157
|
+
let statusCode = 200;
|
|
158
|
+
const headers = {};
|
|
159
|
+
let body = '';
|
|
160
|
+
let sent = false;
|
|
161
|
+
const reply = {
|
|
162
|
+
code(code) {
|
|
163
|
+
statusCode = code;
|
|
164
|
+
return reply;
|
|
165
|
+
},
|
|
166
|
+
status(code) {
|
|
167
|
+
statusCode = code;
|
|
168
|
+
return reply;
|
|
169
|
+
},
|
|
170
|
+
header(name, value) {
|
|
171
|
+
headers[name.toLowerCase()] = value;
|
|
172
|
+
return reply;
|
|
173
|
+
},
|
|
174
|
+
type(contentType) {
|
|
175
|
+
headers['content-type'] = contentType;
|
|
176
|
+
return reply;
|
|
177
|
+
},
|
|
178
|
+
send(payload) {
|
|
179
|
+
sent = true;
|
|
180
|
+
if (payload === undefined || payload === null) {
|
|
181
|
+
body = '';
|
|
182
|
+
}
|
|
183
|
+
else if (typeof payload === 'string') {
|
|
184
|
+
body = payload;
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
body = JSON.stringify(payload);
|
|
188
|
+
if (!headers['content-type']) {
|
|
189
|
+
headers['content-type'] = 'application/json';
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
try {
|
|
195
|
+
const result = await handler(request, reply);
|
|
196
|
+
// if handler returned a value and didn't call reply.send()
|
|
197
|
+
if (!sent && result !== undefined) {
|
|
198
|
+
reply.send(result);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
catch (err) {
|
|
202
|
+
statusCode = 500;
|
|
203
|
+
body = String(err);
|
|
204
|
+
}
|
|
205
|
+
return { statusCode, headers, body };
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
function tryParseJson(str) {
|
|
209
|
+
try {
|
|
210
|
+
return JSON.parse(str);
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
return str;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
// -- default export matching fastify's API --
|
|
217
|
+
function Fastify(_opts) {
|
|
218
|
+
const instance = new FastifyShim();
|
|
219
|
+
globalThis.__orez_fastify_instance = instance;
|
|
220
|
+
return instance;
|
|
221
|
+
}
|
|
222
|
+
export default Fastify;
|
|
223
|
+
//# sourceMappingURL=fastify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fastify.js","sourceRoot":"","sources":["../../../src/worker/shims/fastify.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/** handler for a WebSocket connection routed from a DO */
|
|
2
|
+
export type WebSocketHandler = (server: WebSocket, request: Request, url: URL) => void | Promise<void>;
|
|
3
|
+
/** minimal interface for what we need from fastify (avoids hard dep) */
|
|
4
|
+
export interface InjectableFastify {
|
|
5
|
+
inject(opts: {
|
|
6
|
+
method: string;
|
|
7
|
+
url: string;
|
|
8
|
+
headers?: Record<string, string>;
|
|
9
|
+
payload?: string | null;
|
|
10
|
+
}): Promise<{
|
|
11
|
+
statusCode: number;
|
|
12
|
+
headers: Record<string, string>;
|
|
13
|
+
body: string;
|
|
14
|
+
}>;
|
|
15
|
+
ready(): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
/** route match result */
|
|
18
|
+
interface RouteMatch {
|
|
19
|
+
handler: WebSocketHandler;
|
|
20
|
+
pattern: string;
|
|
21
|
+
}
|
|
22
|
+
/** result of preparing a WebSocket upgrade (before CF Response creation) */
|
|
23
|
+
export interface WebSocketUpgradeResult {
|
|
24
|
+
client: WebSocket;
|
|
25
|
+
server: WebSocket;
|
|
26
|
+
handler: WebSocketHandler;
|
|
27
|
+
request: Request;
|
|
28
|
+
url: URL;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* the http service adapter. manages routing between Fastify inject()
|
|
32
|
+
* for regular HTTP and DO-native WebSocket pairs for upgrade requests.
|
|
33
|
+
*/
|
|
34
|
+
export declare class HttpServiceAdapter {
|
|
35
|
+
private fastify;
|
|
36
|
+
private wsRoutes;
|
|
37
|
+
private wsPatterns;
|
|
38
|
+
private initialized;
|
|
39
|
+
/**
|
|
40
|
+
* register a WebSocket route handler.
|
|
41
|
+
* supports exact paths and simple patterns with wildcard segments.
|
|
42
|
+
*
|
|
43
|
+
* call before initialize() so routes are ready when requests arrive.
|
|
44
|
+
*
|
|
45
|
+
* examples:
|
|
46
|
+
* addWsRoute('/replication/v1/changes', handler) -- exact
|
|
47
|
+
* addWsRoute('/replication/v[star]/changes', handler) -- wildcard (use *)
|
|
48
|
+
*/
|
|
49
|
+
addWsRoute(path: string, handler: WebSocketHandler): void;
|
|
50
|
+
/**
|
|
51
|
+
* initialize with a fastify instance. call after route registration
|
|
52
|
+
* (e.g., after zero-cache's init callback has run) but before handling requests.
|
|
53
|
+
* calls fastify.ready() to finalize route compilation.
|
|
54
|
+
*/
|
|
55
|
+
initialize(fastify: InjectableFastify): Promise<void>;
|
|
56
|
+
/** whether the adapter is ready to handle requests */
|
|
57
|
+
get isReady(): boolean;
|
|
58
|
+
/**
|
|
59
|
+
* handle an incoming request from a DO's fetch() method.
|
|
60
|
+
* routes WebSocket upgrades to DO-native WebSocket handlers,
|
|
61
|
+
* everything else to Fastify inject().
|
|
62
|
+
*/
|
|
63
|
+
handleRequest(request: Request): Promise<Response>;
|
|
64
|
+
/**
|
|
65
|
+
* route a regular HTTP request through Fastify's inject() mechanism.
|
|
66
|
+
* this works for all non-WebSocket routes (health, keepalive, statz, etc.).
|
|
67
|
+
*/
|
|
68
|
+
private handleHttp;
|
|
69
|
+
/**
|
|
70
|
+
* handle a WebSocket upgrade request using DO-native WebSocket pairs.
|
|
71
|
+
*
|
|
72
|
+
* creates a WebSocketPair, accepts the server side, and passes it
|
|
73
|
+
* to the matched route handler. returns the 101 response with the
|
|
74
|
+
* client side for the DO runtime to manage.
|
|
75
|
+
*
|
|
76
|
+
* note: WebSocketPair is a CF Workers global. in non-CF environments
|
|
77
|
+
* this will throw — callers should polyfill or avoid ws routes.
|
|
78
|
+
*/
|
|
79
|
+
private handleWebSocket;
|
|
80
|
+
/**
|
|
81
|
+
* prepare a WebSocket upgrade: match route, create pair, accept server side.
|
|
82
|
+
* separated from handleWebSocket so tests can verify the setup logic without
|
|
83
|
+
* needing the CF runtime's special Response(101) support.
|
|
84
|
+
*
|
|
85
|
+
* returns null if no route matches, a Response if WebSocketPair unavailable,
|
|
86
|
+
* or a WebSocketUpgradeResult with the pair + handler ready to invoke.
|
|
87
|
+
*/
|
|
88
|
+
prepareWebSocketUpgrade(request: Request, url: URL): WebSocketUpgradeResult | Response | null;
|
|
89
|
+
/**
|
|
90
|
+
* match a pathname against registered WebSocket routes.
|
|
91
|
+
* checks exact matches first, then pattern matches.
|
|
92
|
+
*/
|
|
93
|
+
matchWsRoute(pathname: string): RouteMatch | null;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* factory function — creates a pre-configured adapter with the standard
|
|
97
|
+
* zero-cache WebSocket routes registered.
|
|
98
|
+
*
|
|
99
|
+
* handlers are placeholders that will be replaced during Phase 3 integration
|
|
100
|
+
* when we wire up the actual zero-cache WebSocket protocol handlers.
|
|
101
|
+
*/
|
|
102
|
+
export declare function createHttpServiceAdapter(): HttpServiceAdapter;
|
|
103
|
+
export {};
|
|
104
|
+
//# sourceMappingURL=http-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-service.d.ts","sourceRoot":"","sources":["../../../src/worker/shims/http-service.ts"],"names":[],"mappings":"AA0BA,0DAA0D;AAC1D,MAAM,MAAM,gBAAgB,GAAG,CAC7B,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,GAAG,KACL,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;AAEzB,wEAAwE;AACxE,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,IAAI,EAAE;QACX,MAAM,EAAE,MAAM,CAAA;QACd,GAAG,EAAE,MAAM,CAAA;QACX,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAChC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KACxB,GAAG,OAAO,CAAC;QACV,UAAU,EAAE,MAAM,CAAA;QAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAC/B,IAAI,EAAE,MAAM,CAAA;KACb,CAAC,CAAA;IACF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AAED,yBAAyB;AACzB,UAAU,UAAU;IAClB,OAAO,EAAE,gBAAgB,CAAA;IACzB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,4EAA4E;AAC5E,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,SAAS,CAAA;IACjB,MAAM,EAAE,SAAS,CAAA;IACjB,OAAO,EAAE,gBAAgB,CAAA;IACzB,OAAO,EAAE,OAAO,CAAA;IAChB,GAAG,EAAE,GAAG,CAAA;CACT;AAED;;;GAGG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,QAAQ,CAA2C;IAC3D,OAAO,CAAC,UAAU,CAIX;IACP,OAAO,CAAC,WAAW,CAAQ;IAE3B;;;;;;;;;OASG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAWzD;;;;OAIG;IACG,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAM3D,sDAAsD;IACtD,IAAI,OAAO,IAAI,OAAO,CAErB;IAED;;;;OAIG;IACG,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;IAgBxD;;;OAGG;YACW,UAAU;IA8BxB;;;;;;;;;OASG;IACH,OAAO,CAAC,eAAe;IA2CvB;;;;;;;OAOG;IACH,uBAAuB,CACrB,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,GAAG,GACP,sBAAsB,GAAG,QAAQ,GAAG,IAAI;IAqB3C;;;OAGG;IACH,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;CAgBlD;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,IAAI,kBAAkB,CAS7D"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
// NOTE THIS IS NOT OREZ NODE THIS IS NOT A GOOD REFERENCE BECAUSE ITS OUR EARLY GUESS AT WHAT COULD WORK
|
|
2
|
+
// DO NOT STUDY THIS, THE OTHER STUFF IN SRC IS WHERE YOU EANT TO LOOK
|
|
3
|
+
/**
|
|
4
|
+
* the http service adapter. manages routing between Fastify inject()
|
|
5
|
+
* for regular HTTP and DO-native WebSocket pairs for upgrade requests.
|
|
6
|
+
*/
|
|
7
|
+
export class HttpServiceAdapter {
|
|
8
|
+
fastify = null;
|
|
9
|
+
wsRoutes = new Map();
|
|
10
|
+
wsPatterns = [];
|
|
11
|
+
initialized = false;
|
|
12
|
+
/**
|
|
13
|
+
* register a WebSocket route handler.
|
|
14
|
+
* supports exact paths and simple patterns with wildcard segments.
|
|
15
|
+
*
|
|
16
|
+
* call before initialize() so routes are ready when requests arrive.
|
|
17
|
+
*
|
|
18
|
+
* examples:
|
|
19
|
+
* addWsRoute('/replication/v1/changes', handler) -- exact
|
|
20
|
+
* addWsRoute('/replication/v[star]/changes', handler) -- wildcard (use *)
|
|
21
|
+
*/
|
|
22
|
+
addWsRoute(path, handler) {
|
|
23
|
+
if (path.includes('*')) {
|
|
24
|
+
// convert glob-style pattern to regex
|
|
25
|
+
const escaped = path.replace(/[.+?^${}()|[\]\\]/g, '\\$&');
|
|
26
|
+
const regex = new RegExp('^' + escaped.replace(/\*/g, '[^/]+') + '$');
|
|
27
|
+
this.wsPatterns.push({ regex, pattern: path, handler });
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
this.wsRoutes.set(path, handler);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* initialize with a fastify instance. call after route registration
|
|
35
|
+
* (e.g., after zero-cache's init callback has run) but before handling requests.
|
|
36
|
+
* calls fastify.ready() to finalize route compilation.
|
|
37
|
+
*/
|
|
38
|
+
async initialize(fastify) {
|
|
39
|
+
this.fastify = fastify;
|
|
40
|
+
await fastify.ready();
|
|
41
|
+
this.initialized = true;
|
|
42
|
+
}
|
|
43
|
+
/** whether the adapter is ready to handle requests */
|
|
44
|
+
get isReady() {
|
|
45
|
+
return this.initialized;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* handle an incoming request from a DO's fetch() method.
|
|
49
|
+
* routes WebSocket upgrades to DO-native WebSocket handlers,
|
|
50
|
+
* everything else to Fastify inject().
|
|
51
|
+
*/
|
|
52
|
+
async handleRequest(request) {
|
|
53
|
+
if (!this.initialized) {
|
|
54
|
+
return new Response('service not ready', { status: 503 });
|
|
55
|
+
}
|
|
56
|
+
const url = new URL(request.url);
|
|
57
|
+
// websocket upgrade — route to DO native handler
|
|
58
|
+
if (request.headers.get('upgrade')?.toLowerCase() === 'websocket') {
|
|
59
|
+
return this.handleWebSocket(request, url);
|
|
60
|
+
}
|
|
61
|
+
// regular HTTP — fastify inject
|
|
62
|
+
return this.handleHttp(request, url);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* route a regular HTTP request through Fastify's inject() mechanism.
|
|
66
|
+
* this works for all non-WebSocket routes (health, keepalive, statz, etc.).
|
|
67
|
+
*/
|
|
68
|
+
async handleHttp(request, url) {
|
|
69
|
+
if (!this.fastify) {
|
|
70
|
+
return new Response('fastify not initialized', { status: 503 });
|
|
71
|
+
}
|
|
72
|
+
// build headers object from request
|
|
73
|
+
const headers = {};
|
|
74
|
+
request.headers.forEach((value, key) => {
|
|
75
|
+
headers[key] = value;
|
|
76
|
+
});
|
|
77
|
+
// read body for non-GET/HEAD requests
|
|
78
|
+
let payload = null;
|
|
79
|
+
if (request.method !== 'GET' && request.method !== 'HEAD' && request.body) {
|
|
80
|
+
payload = await request.text();
|
|
81
|
+
}
|
|
82
|
+
const result = await this.fastify.inject({
|
|
83
|
+
method: request.method,
|
|
84
|
+
url: url.pathname + url.search,
|
|
85
|
+
headers,
|
|
86
|
+
payload,
|
|
87
|
+
});
|
|
88
|
+
return new Response(result.body, {
|
|
89
|
+
status: result.statusCode,
|
|
90
|
+
headers: result.headers,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* handle a WebSocket upgrade request using DO-native WebSocket pairs.
|
|
95
|
+
*
|
|
96
|
+
* creates a WebSocketPair, accepts the server side, and passes it
|
|
97
|
+
* to the matched route handler. returns the 101 response with the
|
|
98
|
+
* client side for the DO runtime to manage.
|
|
99
|
+
*
|
|
100
|
+
* note: WebSocketPair is a CF Workers global. in non-CF environments
|
|
101
|
+
* this will throw — callers should polyfill or avoid ws routes.
|
|
102
|
+
*/
|
|
103
|
+
handleWebSocket(request, url) {
|
|
104
|
+
const result = this.prepareWebSocketUpgrade(request, url);
|
|
105
|
+
if (!result) {
|
|
106
|
+
return new Response('no websocket handler for path', { status: 404 });
|
|
107
|
+
}
|
|
108
|
+
if (result instanceof Response) {
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
// invoke handler (fire-and-forget; handler manages the connection lifecycle)
|
|
112
|
+
// errors in the handler should close the socket, not crash the DO
|
|
113
|
+
Promise.resolve(result.handler(result.server, result.request, result.url)).catch((err) => {
|
|
114
|
+
try {
|
|
115
|
+
result.server.close(1011, String(err));
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
// socket may already be closed
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
// return 101 with client socket for DO runtime.
|
|
122
|
+
// CF Workers Response constructor accepts status 101 + webSocket property.
|
|
123
|
+
// standard fetch spec rejects status 101, so we try CF-style first and
|
|
124
|
+
// fall back to a plain 101-like response for non-CF environments.
|
|
125
|
+
try {
|
|
126
|
+
return new Response(null, {
|
|
127
|
+
status: 101,
|
|
128
|
+
// @ts-expect-error — webSocket is a CF Workers Response extension
|
|
129
|
+
webSocket: result.client,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
// non-CF runtime (Node.js, vitest) — status 101 not allowed.
|
|
134
|
+
// return a marker response that callers can detect.
|
|
135
|
+
const resp = new Response(null, { status: 200 });
|
|
136
|
+
resp.__orez_websocket = result.client;
|
|
137
|
+
resp.__orez_ws_upgrade = true;
|
|
138
|
+
return resp;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* prepare a WebSocket upgrade: match route, create pair, accept server side.
|
|
143
|
+
* separated from handleWebSocket so tests can verify the setup logic without
|
|
144
|
+
* needing the CF runtime's special Response(101) support.
|
|
145
|
+
*
|
|
146
|
+
* returns null if no route matches, a Response if WebSocketPair unavailable,
|
|
147
|
+
* or a WebSocketUpgradeResult with the pair + handler ready to invoke.
|
|
148
|
+
*/
|
|
149
|
+
prepareWebSocketUpgrade(request, url) {
|
|
150
|
+
const match = this.matchWsRoute(url.pathname);
|
|
151
|
+
if (!match) {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
// WebSocketPair is a CF Workers runtime global
|
|
155
|
+
const WsPair = globalThis.WebSocketPair;
|
|
156
|
+
if (!WsPair) {
|
|
157
|
+
return new Response('WebSocketPair not available in this runtime', { status: 500 });
|
|
158
|
+
}
|
|
159
|
+
const pair = new WsPair();
|
|
160
|
+
const [client, server] = Object.values(pair);
|
|
161
|
+
server.accept();
|
|
162
|
+
return { client, server, handler: match.handler, request, url };
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* match a pathname against registered WebSocket routes.
|
|
166
|
+
* checks exact matches first, then pattern matches.
|
|
167
|
+
*/
|
|
168
|
+
matchWsRoute(pathname) {
|
|
169
|
+
// exact match first
|
|
170
|
+
const exact = this.wsRoutes.get(pathname);
|
|
171
|
+
if (exact) {
|
|
172
|
+
return { handler: exact, pattern: pathname };
|
|
173
|
+
}
|
|
174
|
+
// pattern match
|
|
175
|
+
for (const { regex, pattern, handler } of this.wsPatterns) {
|
|
176
|
+
if (regex.test(pathname)) {
|
|
177
|
+
return { handler, pattern };
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* factory function — creates a pre-configured adapter with the standard
|
|
185
|
+
* zero-cache WebSocket routes registered.
|
|
186
|
+
*
|
|
187
|
+
* handlers are placeholders that will be replaced during Phase 3 integration
|
|
188
|
+
* when we wire up the actual zero-cache WebSocket protocol handlers.
|
|
189
|
+
*/
|
|
190
|
+
export function createHttpServiceAdapter() {
|
|
191
|
+
const adapter = new HttpServiceAdapter();
|
|
192
|
+
// register known zero-cache websocket route patterns.
|
|
193
|
+
// actual handlers will be set during integration (Phase 3).
|
|
194
|
+
// these patterns match zero-cache's replication endpoints.
|
|
195
|
+
// for now, register the patterns so path matching works.
|
|
196
|
+
return adapter;
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=http-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-service.js","sourceRoot":"","sources":["../../../src/worker/shims/http-service.ts"],"names":[],"mappings":"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"}
|