devflare 1.0.0-next.29 → 1.0.0-next.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bridge/client.d.ts +14 -0
- package/dist/bridge/client.d.ts.map +1 -1
- package/dist/bridge/gateway-runtime.d.ts +1 -1
- package/dist/bridge/gateway-runtime.d.ts.map +1 -1
- package/dist/bridge/proxy.d.ts.map +1 -1
- package/dist/bridge/server.d.ts.map +1 -1
- package/dist/bridge/v2/value-serialization.d.ts +3 -1
- package/dist/bridge/v2/value-serialization.d.ts.map +1 -1
- package/dist/browser.js +2 -2
- package/dist/cli/index.js +1 -1
- package/dist/{dev-f2zhzajr.js → dev-ymkq3thq.js} +1 -1
- package/dist/{index-a6cbcsyp.js → index-6sj0v0dk.js} +66 -22
- package/dist/{index-kecy9p48.js → index-85yjb686.js} +1 -1
- package/dist/{index-vfh0ctjw.js → index-qz6nbwpw.js} +1 -1
- package/dist/{index-g7142jcz.js → index-sqkbyw0c.js} +1 -1
- package/dist/{index-y59hnmd0.js → index-t9y0sve5.js} +25 -2
- package/dist/{index-35bmgpfw.js → index-za0r01bx.js} +17 -2
- package/dist/index.js +3 -3
- package/dist/runtime/index.js +3 -3
- package/dist/shims/local-hyperdrive.d.ts +12 -0
- package/dist/shims/local-hyperdrive.d.ts.map +1 -0
- package/dist/shims/local-worker-loader.d.ts.map +1 -1
- package/dist/sveltekit/index.js +5 -24
- package/dist/sveltekit/local-bindings.d.ts.map +1 -1
- package/dist/test/index.js +82 -48
- package/dist/test/utilities/platform.d.ts +3 -0
- package/dist/test/utilities/platform.d.ts.map +1 -1
- package/dist/test/utilities/r2.d.ts +0 -10
- package/dist/test/utilities/r2.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/bridge/client.d.ts
CHANGED
|
@@ -50,6 +50,7 @@ export declare class BridgeClient {
|
|
|
50
50
|
private wsProxies;
|
|
51
51
|
private pendingWsOpens;
|
|
52
52
|
private outgoingStreams;
|
|
53
|
+
private eventListeners;
|
|
53
54
|
private connectPromise;
|
|
54
55
|
private isConnected;
|
|
55
56
|
constructor(options?: BridgeClientOptions);
|
|
@@ -72,6 +73,18 @@ export declare class BridgeClient {
|
|
|
72
73
|
private cleanupPending;
|
|
73
74
|
/** Call an RPC method */
|
|
74
75
|
call(method: string, params: unknown[], timeoutMs?: number): Promise<unknown>;
|
|
76
|
+
/**
|
|
77
|
+
* Subscribe to bridge `event` notifications for a topic.
|
|
78
|
+
*
|
|
79
|
+
* Pass `'*'` to receive every event regardless of topic. Returns an
|
|
80
|
+
* unsubscribe function; calling it removes this listener. Subscriptions
|
|
81
|
+
* survive auto-reconnect and are only dropped on an explicit disconnect().
|
|
82
|
+
*
|
|
83
|
+
* NOTE: no gateway currently emits `event` frames, so listeners will not
|
|
84
|
+
* fire until an event producer is wired on the gateway side. The subscriber
|
|
85
|
+
* surface is provided so consumers can register ahead of that work.
|
|
86
|
+
*/
|
|
87
|
+
on(topic: string, cb: (data: unknown) => void): () => void;
|
|
75
88
|
/** Create a proxied WebSocket to a Durable Object */
|
|
76
89
|
createWsProxy(binding: string, id: string, url: string, headers?: [string, string][]): Promise<{
|
|
77
90
|
wid: number;
|
|
@@ -90,6 +103,7 @@ export declare class BridgeClient {
|
|
|
90
103
|
*/
|
|
91
104
|
private handleV2BinaryFrame;
|
|
92
105
|
private handleEvent;
|
|
106
|
+
private dispatchEvent;
|
|
93
107
|
private handleStreamPull;
|
|
94
108
|
private pumpStream;
|
|
95
109
|
private handleStreamChunk;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/bridge/client.ts"],"names":[],"mappings":"AAqEA,KAAK,oBAAoB,GAAG,KAAK,GAAG,EAAE,MAAM,KAAK,SAAS,CAAA;AA6C1D,wBAAsB,iCAAiC,CACtD,gBAAgB,GAAE,OAA8B,GAC9C,OAAO,CAAC,oBAAoB,CAAC,CAK/B;AAMD,MAAM,WAAW,mBAAmB;IACnC,0DAA0D;IAC1D,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,mCAAmC;IACnC,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,4BAA4B;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,+BAA+B;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,WAAW;IAC3B,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;IACjC,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IAC9B,OAAO,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAA;CACtC;AAED,MAAM,WAAW,YAAY;IAC5B,UAAU,EAAE,+BAA+B,CAAC,UAAU,CAAC,CAAA;IACvD,MAAM,EAAE,UAAU,EAAE,CAAA;IACpB,eAAe,EAAE,MAAM,CAAA;IACvB,0DAA0D;IAC1D,WAAW,EAAE;QACZ,OAAO,EAAE,MAAM,IAAI,CAAA;QACnB,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;KAC9B,GAAG,IAAI,CAAA;IACR,kEAAkE;IAClE,KAAK,EAAE,OAAO,CAAA;IACd,8CAA8C;IAC9C,MAAM,EAAE,OAAO,CAAA;CACf;AAED,MAAM,WAAW,aAAa;IAC7B,QAAQ,EAAE,SAAS,CAAA;IACnB,SAAS,EAAE,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,KAAK,IAAI,CAAA;IAC9C,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;CACjD;AAED,MAAM,WAAW,aAAa;IAC7B,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CAC9B;AAMD,qBAAa,YAAY;IACxB,OAAO,CAAC,EAAE,CAAyB;IACnC,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,GAAG,CAAQ;IACnB,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAAQ;IAC9B,OAAO,CAAC,cAAc,CAAQ;IAE9B,OAAO,CAAC,aAAa,CAAkC;IACvD,OAAO,CAAC,SAAS,CAAmC;IACpD,OAAO,CAAC,cAAc,CAAmC;IACzD,OAAO,CAAC,eAAe,CAA+B;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/bridge/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
* module. All symbols are declared with `function`/`const` so they are
|
|
5
5
|
* hoisted in both embedding sites.
|
|
6
6
|
*/
|
|
7
|
-
export declare const GATEWAY_RUNTIME_JS = "\nconst RAW_EMAIL = 'EmailMessage::raw'\n\nfunction arrayBufferToBase64(buffer) {\n\tconst bytes = new Uint8Array(buffer)\n\tlet binary = ''\n\tfor (let i = 0; i < bytes.byteLength; i++) binary += String.fromCharCode(bytes[i])\n\treturn btoa(binary)\n}\n\nfunction base64ToArrayBuffer(base64) {\n\tconst binary = atob(base64)\n\tconst bytes = new Uint8Array(binary.length)\n\tfor (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i)\n\treturn bytes.buffer\n}\n\nfunction serializeR2Object(obj) {\n\tif (!obj) return null\n\treturn {\n\t\t__type: 'R2Object',\n\t\tkey: obj.key,\n\t\tversion: obj.version,\n\t\tsize: obj.size,\n\t\tetag: obj.etag,\n\t\thttpEtag: obj.httpEtag,\n\t\tchecksums: obj.checksums,\n\t\tuploaded: obj.uploaded?.toISOString(),\n\t\thttpMetadata: obj.httpMetadata,\n\t\tcustomMetadata: obj.customMetadata,\n\t\trange: obj.range,\n\t\tstorageClass: obj.storageClass\n\t}\n}\n\nfunction serializeR2ObjectBody(obj, bodyData) {\n\tif (!obj) return null\n\treturn {\n\t\t__type: 'R2ObjectBody',\n\t\tkey: obj.key,\n\t\tversion: obj.version,\n\t\tsize: obj.size,\n\t\tetag: obj.etag,\n\t\thttpEtag: obj.httpEtag,\n\t\tchecksums: obj.checksums,\n\t\tuploaded: obj.uploaded?.toISOString(),\n\t\thttpMetadata: obj.httpMetadata,\n\t\tcustomMetadata: obj.customMetadata,\n\t\trange: obj.range,\n\t\tstorageClass: obj.storageClass,\n\t\tbodyData\n\t}\n}\n\nfunction serializeR2Objects(result) {\n\tif (!result) return null\n\treturn {\n\t\tobjects: result.objects.map(serializeR2Object),\n\t\ttruncated: result.truncated,\n\t\tcursor: result.cursor,\n\t\tdelimitedPrefixes: result.delimitedPrefixes\n\t}\n}\n\nasync function serializeResponse(response) {\n\tlet body = null\n\tif (response.body) {\n\t\tconst bytes = await response.arrayBuffer()\n\t\tif (bytes.byteLength > 0) {\n\t\t\tbody = { type: 'bytes', data: arrayBufferToBase64(bytes) }\n\t\t}\n\t}\n\treturn {\n\t\tstatus: response.status,\n\t\tstatusText: response.statusText,\n\t\theaders: [...response.headers.entries()],\n\t\tbody\n\t}\n}\n\nfunction deserializeRequest(serializedReq) {\n\treturn new Request(serializedReq.url, {\n\t\tmethod: serializedReq.method,\n\t\theaders: serializedReq.headers,\n\t\tbody: serializedReq.body?.type === 'bytes'\n\t\t\t? base64ToArrayBuffer(serializedReq.body.data)\n\t\t\t: undefined,\n\t\tredirect: serializedReq.redirect\n\t})\n}\n\nfunction createEmailMessageRaw(raw) {\n\tif (typeof raw === 'string' || raw instanceof ReadableStream) {\n\t\treturn raw\n\t}\n\tif (raw instanceof ArrayBuffer || raw instanceof Uint8Array) {\n\t\treturn new Response(raw).body\n\t}\n\tthrow new Error('Unsupported EmailMessage raw payload')\n}\n\nfunction isDurableObjectNamespace(binding) {\n\treturn !!binding\n\t\t&& typeof binding.idFromName === 'function'\n\t\t&& typeof binding.idFromString === 'function'\n\t\t&& typeof binding.newUniqueId === 'function'\n}\n\n/**\n * Execute an RPC method against the gateway's bindings.\n *\n * Method format: \"binding.operation\". Operations must be namespaced by\n * binding kind (e.g. \"kv.get\", \"r2.head\", \"d1.stmt.first\", \"do.fetch\",\n * \"service.fetch\", \"queue.send\", \"email.send\", \"ai.run\"). Bare verbs and the legacy\n * \"stmt.*\" / \"stub.*\" sub-prefixes were removed in B3-final and now throw.\n * Method vocabulary must stay in sync with the canonical server in\n * src/bridge/server.ts.\n */\nasync function executeRpcMethod(method, params, env, _ctx) {\n\tconst parts = method.split('.')\n\tif (parts.length < 2) throw new Error('Invalid method format: ' + method)\n\n\tconst bindingName = parts[0]\n\tconst operation = parts.slice(1).join('.')\n\tconst binding = env[bindingName]\n\n\tif (!binding) throw new Error('Binding not found: ' + bindingName)\n\n\tconst isNamespaced =\n\t\toperation.indexOf('kv.') === 0 ||\n\t\toperation.indexOf('r2.') === 0 ||\n\t\toperation.indexOf('d1.') === 0 ||\n\t\toperation.indexOf('do.') === 0 ||\n\t\toperation.indexOf('service.') === 0 ||\n\t\toperation.indexOf('queue.') === 0 ||\n\t\toperation.indexOf('email.') === 0 ||\n\t\toperation.indexOf('ai.') === 0 ||\n\t\toperation.indexOf('workflow.') === 0 ||\n\t\toperation.indexOf('var.') === 0\n\tif (!isNamespaced) {\n\t\tthrow new Error(createUnsupportedBridgeOperationErrorMessage(bindingName, operation))\n\t}\n\n\t// KV\n\tif (operation === 'kv.get') return binding.get(params[0], params[1])\n\tif (operation === 'kv.put') return binding.put(params[0], params[1], params[2])\n\tif (operation === 'kv.delete') return binding.delete(params[0])\n\tif (operation === 'kv.list') return binding.list(params[0])\n\tif (operation === 'kv.getWithMetadata') return binding.getWithMetadata(params[0], params[1])\n\n\t// DO get (returns DOStub reference)\n\tif (operation === 'do.get') {\n\t\treturn { __type: 'DOStub', binding: bindingName, id: params[0] }\n\t}\n\n\t// R2\n\tif (operation === 'r2.head') return serializeR2Object(await binding.head(params[0]))\n\tif (operation === 'r2.get') {\n\t\tconst obj = await binding.get(params[0], params[1])\n\t\tif (!obj) return null\n\t\tconst body = await obj.arrayBuffer()\n\t\treturn serializeR2ObjectBody(obj, arrayBufferToBase64(body))\n\t}\n\tif (operation === 'r2.put') {\n\t\tlet value = params[1]\n\t\tif (value && typeof value === 'object') {\n\t\t\tif (value.__type === 'ArrayBuffer' || value.__type === 'Uint8Array') {\n\t\t\t\tvalue = base64ToArrayBuffer(value.data)\n\t\t\t}\n\t\t}\n\t\treturn serializeR2Object(await binding.put(params[0], value, params[2]))\n\t}\n\tif (operation === 'r2.delete') return binding.delete(params[0])\n\tif (operation === 'r2.list') return serializeR2Objects(await binding.list(params[0]))\n\n\t// D1\n\tif (operation === 'd1.exec') return binding.exec(params[0])\n\tif (operation === 'd1.batch') {\n\t\tconst statements = params[0].map((s) => binding.prepare(s.sql).bind(...(s.bindings || [])))\n\t\treturn binding.batch(statements)\n\t}\n\tif (operation.indexOf('d1.stmt.') === 0) {\n\t\tconst mode = operation.split('.')[2]\n\t\tconst [sql, ...rest] = params\n\t\tlet bindings = rest\n\t\tlet extraParam\n\t\tif (mode === 'first' || mode === 'raw') {\n\t\t\textraParam = rest[rest.length - 1]\n\t\t\tbindings = rest.slice(0, -1)\n\t\t}\n\t\tlet stmt = binding.prepare(sql)\n\t\tif (bindings.length > 0) stmt = stmt.bind(...bindings)\n\t\tif (mode === 'first') {\n\t\t\tif (typeof extraParam === 'string' && extraParam.length > 0) return stmt.first(extraParam)\n\t\t\treturn stmt.first()\n\t\t}\n\t\tif (mode === 'all') return stmt.all()\n\t\tif (mode === 'run') return stmt.run()\n\t\tif (mode === 'raw') return stmt.raw(extraParam)\n\t\tthrow new Error('Unknown stmt mode: ' + mode)\n\t}\n\n\t// Durable Objects\n\tif (operation === 'do.idFromName') {\n\t\tconst id = binding.idFromName(params[0])\n\t\treturn { __type: 'DOId', hex: id.toString() }\n\t}\n\tif (operation === 'do.idFromString') {\n\t\tconst id = binding.idFromString(params[0])\n\t\treturn { __type: 'DOId', hex: id.toString() }\n\t}\n\tif (operation === 'do.newUniqueId') {\n\t\tconst id = binding.newUniqueId(params[0])\n\t\treturn { __type: 'DOId', hex: id.toString() }\n\t}\n\tif (operation === 'do.fetch') {\n\t\tconst [, serializedId, serializedReq] = params\n\t\tconst id = binding.idFromString(serializedId.hex)\n\t\tconst stub = binding.get(id)\n\t\tconst response = await stub.fetch(new Request(serializedReq.url, {\n\t\t\tmethod: serializedReq.method,\n\t\t\theaders: serializedReq.headers,\n\t\t\tbody: serializedReq.body?.type === 'bytes'\n\t\t\t\t? base64ToArrayBuffer(serializedReq.body.data)\n\t\t\t\t: undefined\n\t\t}))\n\t\treturn serializeResponse(response)\n\t}\n\tif (operation === 'do.rpc') {\n\t\tconst [, serializedId, methodName, args] = params\n\t\tconst id = binding.idFromString(serializedId.hex)\n\t\tconst stub = binding.get(id)\n\t\tconst response = await stub.fetch(new Request('http://do/_rpc', {\n\t\t\tmethod: 'POST',\n\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\tbody: JSON.stringify({ method: methodName, params: args })\n\t\t}))\n\t\tconst result = await response.json()\n\t\tif (!result.ok) throw new Error(result.error?.message || 'RPC failed')\n\t\treturn result.result\n\t}\n\n\t// Service Bindings\n\tif (operation === 'service.fetch') {\n\t\tif (!binding || typeof binding.fetch !== 'function') {\n\t\t\tthrow new Error('Service binding ' + bindingName + ' does not support fetch()')\n\t\t}\n\t\tconst response = await binding.fetch(deserializeRequest(params[0]))\n\t\treturn serializeResponse(response)\n\t}\n\tif (operation === 'service.rpc') {\n\t\tconst methodName = params[0]\n\t\tif (typeof methodName !== 'string') {\n\t\t\tthrow new Error('Service binding ' + bindingName + ' RPC method name must be a string')\n\t\t}\n\t\tconst args = Array.isArray(params[1]) ? params[1] : []\n\t\tconst method = binding && binding[methodName]\n\t\tif (typeof method !== 'function') {\n\t\t\tthrow new Error('Service binding ' + bindingName + ' does not support ' + methodName + '()')\n\t\t}\n\t\treturn method.apply(binding, args)\n\t}\n\n\t// Queues\n\tif (operation === 'queue.send') return binding.send(params[0], params[1])\n\tif (operation === 'queue.sendBatch') return binding.sendBatch(params[0], params[1])\n\n\t// Send Email\n\tif (operation === 'email.send') {\n\t\tif (binding && typeof binding.send === 'function') {\n\t\t\tconst message = params[0]\n\t\t\tif (message && typeof message === 'object' && 'from' in message && 'to' in message && 'raw' in message) {\n\t\t\t\treturn binding.send({\n\t\t\t\t\tfrom: message.from,\n\t\t\t\t\tto: message.to,\n\t\t\t\t\t[RAW_EMAIL]: createEmailMessageRaw(message.raw)\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn binding.send(message)\n\t\t}\n\t\treturn { ok: true, simulated: true }\n\t}\n\n\t// Workflows\n\tif (operation === 'workflow.create') {\n\t\treturn serializeWorkflowInstance(await binding.create(params[0]))\n\t}\n\tif (operation === 'workflow.get') {\n\t\treturn serializeWorkflowInstance(await binding.get(params[0]))\n\t}\n\tif (operation === 'workflow.status') {\n\t\treturn (await binding.get(params[0])).status()\n\t}\n\tif (operation === 'workflow.pause') {\n\t\treturn (await binding.get(params[0])).pause()\n\t}\n\tif (operation === 'workflow.resume') {\n\t\treturn (await binding.get(params[0])).resume()\n\t}\n\tif (operation === 'workflow.terminate') {\n\t\treturn (await binding.get(params[0])).terminate()\n\t}\n\tif (operation === 'workflow.restart') {\n\t\treturn (await binding.get(params[0])).restart()\n\t}\n\tif (operation === 'workflow.sendEvent') {\n\t\treturn (await binding.get(params[0])).sendEvent(params[1])\n\t}\n\n\t// AI / generic run()\n\tif (operation === 'ai.run') {\n\t\tif (typeof binding.run !== 'function') {\n\t\t\tthrow new Error('Binding ' + bindingName + ' does not support run(): ' + method)\n\t\t}\n\t\treturn binding.run(params[0], params[1])\n\t}\n\n\tthrow new Error('Unknown operation: ' + method)\n}\n\nfunction createUnsupportedBridgeOperationErrorMessage(bindingName, operation) {\n\tconst base = \"[devflare][bridge] Unsupported bridge operation '\" + operation + \"' for binding '\" + bindingName + \"'.\"\n\tif (operation === 'fetch') {\n\t\treturn base + ' Devflare could not dispatch fetch() for this binding through the local bridge. '\n\t\t\t+ 'Expected Cloudflare API: env.' + bindingName + '.fetch(request). '\n\t\t\t+ 'If this came from SvelteKit platform.env, make sure the binding is declared as a service binding; '\n\t\t\t+ 'this is a Devflare local bridge issue when service bindings fall back to a bare fetch operation.'\n\t}\n\tif (operation === 'toString') {\n\t\treturn base + ' A platform.env value was coerced to a string through the bridge. '\n\t\t\t+ 'For SvelteKit local dev, declared vars should be plain string values and missing env names should read as undefined.'\n\t}\n\treturn base + ' Bare verbs and the legacy stmt.*/stub.* sub-prefixes are not supported; '\n\t\t+ 'use the namespaced form (e.g. kv.get, r2.put, d1.stmt.first, do.fetch, service.fetch).'\n}\n\nfunction serializeWorkflowInstance(instance) {\n\treturn {\n\t\t__type: 'WorkflowInstance',\n\t\tid: instance.id\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// WebSocket bridge (shared with src/bridge/server.ts in shape)\n// ---------------------------------------------------------------------------\n// NOTE: wsProxies is intentionally created per handleBridgeWebSocket call so\n// state never leaks across connections or across gateway-script regenerations.\n\nasync function handleBridgeRpcCall(msg, ws, env, ctx) {\n\ttry {\n\t\tconst result = await executeRpcMethod(msg.method, msg.params, env, ctx)\n\t\tws.send(JSON.stringify({ t: 'rpc.ok', id: msg.id, result }))\n\t} catch (error) {\n\t\tws.send(JSON.stringify({\n\t\t\tt: 'rpc.err',\n\t\t\tid: msg.id,\n\t\t\terror: {\n\t\t\t\tcode: error?.code || 'INTERNAL_ERROR',\n\t\t\t\tmessage: error?.message || String(error)\n\t\t\t}\n\t\t}))\n\t}\n}\n\nasync function handleBridgeWsOpen(msg, ws, env, wsProxies) {\n\ttry {\n\t\tconst binding = env[msg.target.binding]\n\t\tconst id = binding.idFromString(msg.target.id)\n\t\tconst stub = binding.get(id)\n\n\t\tconst headers = new Headers(msg.target.headers || [])\n\t\theaders.set('Upgrade', 'websocket')\n\n\t\tconst response = await stub.fetch(new Request(msg.target.url, { method: 'GET', headers }))\n\t\tconst doWs = response.webSocket\n\n\t\tif (!doWs) {\n\t\t\tws.send(JSON.stringify({\n\t\t\t\tt: 'rpc.err',\n\t\t\t\tid: 'ws_' + msg.wid,\n\t\t\t\terror: { code: 'WS_FAILED', message: 'No WebSocket returned' }\n\t\t\t}))\n\t\t\treturn\n\t\t}\n\n\t\tdoWs.accept()\n\t\twsProxies.set(msg.wid, { doWs })\n\n\t\tdoWs.addEventListener('message', (event) => {\n\t\t\tconst isText = typeof event.data === 'string'\n\t\t\tconst data = isText ? event.data : arrayBufferToBase64(event.data)\n\t\t\tws.send(JSON.stringify({ t: 'ws.data', wid: msg.wid, data, isText }))\n\t\t})\n\n\t\tdoWs.addEventListener('close', (event) => {\n\t\t\tws.send(JSON.stringify({ t: 'ws.close', wid: msg.wid, code: event.code, reason: event.reason }))\n\t\t\twsProxies.delete(msg.wid)\n\t\t})\n\n\t\tws.send(JSON.stringify({ t: 'ws.opened', wid: msg.wid }))\n\t} catch (error) {\n\t\tws.send(JSON.stringify({\n\t\t\tt: 'rpc.err',\n\t\t\tid: 'ws_' + msg.wid,\n\t\t\terror: { code: 'WS_FAILED', message: error.message }\n\t\t}))\n\t}\n}\n\nfunction handleBridgeWsClose(msg, wsProxies) {\n\tconst proxy = wsProxies.get(msg.wid)\n\tif (proxy) {\n\t\tproxy.doWs.close(msg.code, msg.reason)\n\t\twsProxies.delete(msg.wid)\n\t}\n}\n\nasync function handleBridgeJsonMessage(data, ws, env, ctx, wsProxies) {\n\tconst msg = JSON.parse(data)\n\tswitch (msg.t) {\n\t\tcase 'hello':\n\t\t\t// v2 handshake \u2014 acknowledge with welcome echoing the negotiated\n\t\t\t// capability intersection. Capabilities advertised by the gateway\n\t\t\t// are kept in sync with src/bridge/client.ts (BRIDGE_CLIENT_CAPABILITIES).\n\t\t\tws.send(JSON.stringify({\n\t\t\t\tt: 'welcome',\n\t\t\t\tprotocolVersion: 2,\n\t\t\t\tcapabilities: ['streams', 'ws-relay', 'http-transfer']\n\t\t\t\t\t.filter((c) => Array.isArray(msg.capabilities) && msg.capabilities.includes(c))\n\t\t\t\t\t.sort()\n\t\t\t}))\n\t\t\tbreak\n\t\tcase 'rpc.call':\n\t\t\tawait handleBridgeRpcCall(msg, ws, env, ctx)\n\t\t\tbreak\n\t\tcase 'ws.open':\n\t\t\tawait handleBridgeWsOpen(msg, ws, env, wsProxies)\n\t\t\tbreak\n\t\tcase 'ws.close':\n\t\t\thandleBridgeWsClose(msg, wsProxies)\n\t\t\tbreak\n\t}\n}\n\nfunction handleBridgeWebSocket(request, env, ctx) {\n\tconst { 0: client, 1: server } = new WebSocketPair()\n\tserver.accept()\n\n\t// Per-connection state: recreated for every bridge client so reloads and\n\t// concurrent clients never share WS proxy entries.\n\tconst wsProxies = new Map()\n\n\tserver.addEventListener('message', async (event) => {\n\t\ttry {\n\t\t\tif (typeof event.data === 'string') {\n\t\t\t\tawait handleBridgeJsonMessage(event.data, server, env, ctx, wsProxies)\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error('[Gateway] Error:', error)\n\t\t}\n\t})\n\n\tserver.addEventListener('close', () => {\n\t\tfor (const proxy of wsProxies.values()) {\n\t\t\t// Best-effort cleanup: the DO-side WS may already be closed or in an\n\t\t\t// invalid state; any throw here would abort sibling closes. Surface\n\t\t\t// the swallowed error when DEVFLARE_DEBUG_BRIDGE is enabled.\n\t\t\ttry { proxy.doWs.close() } catch (error) {\n\t\t\t\tif (globalThis.DEVFLARE_DEBUG_BRIDGE) {\n\t\t\t\t\tconsole.warn('[devflare:bridge] proxy.doWs.close() failed', error)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\twsProxies.clear()\n\t})\n\n\treturn new Response(null, { status: 101, webSocket: client })\n}\n\n// ---------------------------------------------------------------------------\n// HTTP transfer for R2 bodies (shared with src/bridge/server.ts in shape)\n// ---------------------------------------------------------------------------\n\nasync function handleHttpTransfer(request, env, url) {\n\tconst transferIdEncoded = url.pathname.split('/').pop()\n\tconst transferId = decodeURIComponent(transferIdEncoded || '')\n\tconst [binding, ...keyParts] = transferId.split(':')\n\tconst key = keyParts.join(':')\n\tconst bucket = env[binding]\n\n\tif (!bucket) return new Response('Bucket not found: ' + binding, { status: 404 })\n\n\tif (request.method === 'PUT' || request.method === 'POST') {\n\t\tconst result = await bucket.put(key, request.body)\n\t\treturn new Response(JSON.stringify(serializeR2Object(result)), {\n\t\t\theaders: { 'Content-Type': 'application/json' }\n\t\t})\n\t}\n\n\tif (request.method === 'GET') {\n\t\tconst object = await bucket.get(key)\n\t\tif (!object) return new Response('Not found', { status: 404 })\n\t\treturn new Response(object.body, {\n\t\t\theaders: {\n\t\t\t\t'Content-Type': object.httpMetadata?.contentType || 'application/octet-stream',\n\t\t\t\t'Content-Length': String(object.size)\n\t\t\t}\n\t\t})\n\t}\n\n\treturn new Response('Method not allowed', { status: 405 })\n}\n";
|
|
7
|
+
export declare const GATEWAY_RUNTIME_JS = "\nconst RAW_EMAIL = 'EmailMessage::raw'\n\nfunction arrayBufferToBase64(buffer) {\n\tconst bytes = new Uint8Array(buffer)\n\tlet binary = ''\n\tfor (let i = 0; i < bytes.byteLength; i++) binary += String.fromCharCode(bytes[i])\n\treturn btoa(binary)\n}\n\nfunction base64ToArrayBuffer(base64) {\n\tconst binary = atob(base64)\n\tconst bytes = new Uint8Array(binary.length)\n\tfor (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i)\n\treturn bytes.buffer\n}\n\nfunction serializeR2Object(obj) {\n\tif (!obj) return null\n\treturn {\n\t\t__type: 'R2Object',\n\t\tkey: obj.key,\n\t\tversion: obj.version,\n\t\tsize: obj.size,\n\t\tetag: obj.etag,\n\t\thttpEtag: obj.httpEtag,\n\t\tchecksums: obj.checksums,\n\t\tuploaded: obj.uploaded?.toISOString(),\n\t\thttpMetadata: obj.httpMetadata,\n\t\tcustomMetadata: obj.customMetadata,\n\t\trange: obj.range,\n\t\tstorageClass: obj.storageClass\n\t}\n}\n\nfunction serializeR2ObjectBody(obj, bodyData) {\n\tif (!obj) return null\n\treturn {\n\t\t__type: 'R2ObjectBody',\n\t\tkey: obj.key,\n\t\tversion: obj.version,\n\t\tsize: obj.size,\n\t\tetag: obj.etag,\n\t\thttpEtag: obj.httpEtag,\n\t\tchecksums: obj.checksums,\n\t\tuploaded: obj.uploaded?.toISOString(),\n\t\thttpMetadata: obj.httpMetadata,\n\t\tcustomMetadata: obj.customMetadata,\n\t\trange: obj.range,\n\t\tstorageClass: obj.storageClass,\n\t\tbodyData\n\t}\n}\n\nfunction serializeR2Objects(result) {\n\tif (!result) return null\n\treturn {\n\t\tobjects: result.objects.map(serializeR2Object),\n\t\ttruncated: result.truncated,\n\t\tcursor: result.cursor,\n\t\tdelimitedPrefixes: result.delimitedPrefixes\n\t}\n}\n\nasync function serializeResponse(response) {\n\tlet body = null\n\tif (response.body) {\n\t\tconst bytes = await response.arrayBuffer()\n\t\tif (bytes.byteLength > 0) {\n\t\t\tbody = { type: 'bytes', data: arrayBufferToBase64(bytes) }\n\t\t}\n\t}\n\treturn {\n\t\tstatus: response.status,\n\t\tstatusText: response.statusText,\n\t\theaders: [...response.headers.entries()],\n\t\tbody\n\t}\n}\n\nfunction deserializeRequest(serializedReq) {\n\treturn new Request(serializedReq.url, {\n\t\tmethod: serializedReq.method,\n\t\theaders: serializedReq.headers,\n\t\tbody: serializedReq.body?.type === 'bytes'\n\t\t\t? base64ToArrayBuffer(serializedReq.body.data)\n\t\t\t: undefined,\n\t\tredirect: serializedReq.redirect\n\t})\n}\n\nfunction createEmailMessageRaw(raw) {\n\tif (typeof raw === 'string' || raw instanceof ReadableStream) {\n\t\treturn raw\n\t}\n\tif (raw instanceof ArrayBuffer || raw instanceof Uint8Array) {\n\t\treturn new Response(raw).body\n\t}\n\tthrow new Error('Unsupported EmailMessage raw payload')\n}\n\nfunction isDurableObjectNamespace(binding) {\n\treturn !!binding\n\t\t&& typeof binding.idFromName === 'function'\n\t\t&& typeof binding.idFromString === 'function'\n\t\t&& typeof binding.newUniqueId === 'function'\n}\n\n/**\n * Resolve a (possibly jurisdiction-scoped) DurableObjectNamespace.\n * Forwards the jurisdiction faithfully when the binding supports it\n * (real Cloudflare), and degrades to the plain binding otherwise\n * (miniflare/workerd local emulation, which does not pin jurisdictions).\n */\nfunction resolveDoNamespace(binding, jurisdiction) {\n\tif (jurisdiction && typeof binding.jurisdiction === 'function') {\n\t\treturn binding.jurisdiction(jurisdiction)\n\t}\n\treturn binding\n}\n\n/**\n * Execute an RPC method against the gateway's bindings.\n *\n * Method format: \"binding.operation\". Operations must be namespaced by\n * binding kind (e.g. \"kv.get\", \"r2.head\", \"d1.stmt.first\", \"do.fetch\",\n * \"service.fetch\", \"queue.send\", \"email.send\", \"ai.run\"). Bare verbs and the legacy\n * \"stmt.*\" / \"stub.*\" sub-prefixes were removed in B3-final and now throw.\n * Method vocabulary must stay in sync with the canonical server in\n * src/bridge/server.ts.\n */\nasync function executeRpcMethod(method, params, env, _ctx) {\n\tconst parts = method.split('.')\n\tif (parts.length < 2) throw new Error('Invalid method format: ' + method)\n\n\tconst bindingName = parts[0]\n\tconst operation = parts.slice(1).join('.')\n\tconst binding = env[bindingName]\n\n\tif (!binding) throw new Error('Binding not found: ' + bindingName)\n\n\tconst isNamespaced =\n\t\toperation.indexOf('kv.') === 0 ||\n\t\toperation.indexOf('r2.') === 0 ||\n\t\toperation.indexOf('d1.') === 0 ||\n\t\toperation.indexOf('do.') === 0 ||\n\t\toperation.indexOf('service.') === 0 ||\n\t\toperation.indexOf('queue.') === 0 ||\n\t\toperation.indexOf('email.') === 0 ||\n\t\toperation.indexOf('ai.') === 0 ||\n\t\toperation.indexOf('workflow.') === 0 ||\n\t\toperation.indexOf('var.') === 0\n\tif (!isNamespaced) {\n\t\tthrow new Error(createUnsupportedBridgeOperationErrorMessage(bindingName, operation))\n\t}\n\n\t// KV\n\tif (operation === 'kv.get') return binding.get(params[0], params[1])\n\tif (operation === 'kv.put') return binding.put(params[0], params[1], params[2])\n\tif (operation === 'kv.delete') return binding.delete(params[0])\n\tif (operation === 'kv.list') return binding.list(params[0])\n\tif (operation === 'kv.getWithMetadata') return binding.getWithMetadata(params[0], params[1])\n\n\t// DO get (returns DOStub reference)\n\tif (operation === 'do.get') {\n\t\treturn { __type: 'DOStub', binding: bindingName, id: params[0] }\n\t}\n\n\t// R2\n\tif (operation === 'r2.head') return serializeR2Object(await binding.head(params[0]))\n\tif (operation === 'r2.get') {\n\t\tconst obj = await binding.get(params[0], params[1])\n\t\tif (!obj) return null\n\t\tconst body = await obj.arrayBuffer()\n\t\treturn serializeR2ObjectBody(obj, arrayBufferToBase64(body))\n\t}\n\tif (operation === 'r2.put') {\n\t\tlet value = params[1]\n\t\tif (value && typeof value === 'object') {\n\t\t\tif (value.__type === 'ArrayBuffer' || value.__type === 'Uint8Array') {\n\t\t\t\tvalue = base64ToArrayBuffer(value.data)\n\t\t\t}\n\t\t}\n\t\treturn serializeR2Object(await binding.put(params[0], value, params[2]))\n\t}\n\tif (operation === 'r2.delete') return binding.delete(params[0])\n\tif (operation === 'r2.list') return serializeR2Objects(await binding.list(params[0]))\n\n\t// D1\n\tif (operation === 'd1.exec') return binding.exec(params[0])\n\tif (operation === 'd1.batch') {\n\t\tconst statements = params[0].map((s) => binding.prepare(s.sql).bind(...(s.bindings || [])))\n\t\treturn binding.batch(statements)\n\t}\n\tif (operation.indexOf('d1.stmt.') === 0) {\n\t\tconst mode = operation.split('.')[2]\n\t\tconst [sql, ...rest] = params\n\t\tlet bindings = rest\n\t\tlet extraParam\n\t\tif (mode === 'first' || mode === 'raw') {\n\t\t\textraParam = rest[rest.length - 1]\n\t\t\tbindings = rest.slice(0, -1)\n\t\t}\n\t\tlet stmt = binding.prepare(sql)\n\t\tif (bindings.length > 0) stmt = stmt.bind(...bindings)\n\t\tif (mode === 'first') {\n\t\t\tif (typeof extraParam === 'string' && extraParam.length > 0) return stmt.first(extraParam)\n\t\t\treturn stmt.first()\n\t\t}\n\t\tif (mode === 'all') return stmt.all()\n\t\tif (mode === 'run') return stmt.run()\n\t\tif (mode === 'raw') return stmt.raw(extraParam)\n\t\tthrow new Error('Unknown stmt mode: ' + mode)\n\t}\n\n\t// Durable Objects\n\tif (operation === 'do.idFromName') {\n\t\tconst ns = resolveDoNamespace(binding, params[1])\n\t\tconst id = ns.idFromName(params[0])\n\t\treturn { __type: 'DOId', hex: id.toString() }\n\t}\n\tif (operation === 'do.idFromString') {\n\t\tconst id = binding.idFromString(params[0])\n\t\treturn { __type: 'DOId', hex: id.toString() }\n\t}\n\tif (operation === 'do.newUniqueId') {\n\t\tconst ns = resolveDoNamespace(binding, params[1])\n\t\tconst id = ns.newUniqueId(params[0])\n\t\treturn { __type: 'DOId', hex: id.toString() }\n\t}\n\tif (operation === 'do.fetch') {\n\t\tconst [, serializedId, serializedReq] = params\n\t\tconst id = binding.idFromString(serializedId.hex)\n\t\tconst stub = binding.get(id)\n\t\tconst response = await stub.fetch(new Request(serializedReq.url, {\n\t\t\tmethod: serializedReq.method,\n\t\t\theaders: serializedReq.headers,\n\t\t\tbody: serializedReq.body?.type === 'bytes'\n\t\t\t\t? base64ToArrayBuffer(serializedReq.body.data)\n\t\t\t\t: undefined\n\t\t}))\n\t\treturn serializeResponse(response)\n\t}\n\tif (operation === 'do.rpc') {\n\t\tconst [, serializedId, methodName, args] = params\n\t\tconst id = binding.idFromString(serializedId.hex)\n\t\tconst stub = binding.get(id)\n\t\tconst response = await stub.fetch(new Request('http://do/_rpc', {\n\t\t\tmethod: 'POST',\n\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\tbody: JSON.stringify({ method: methodName, params: args })\n\t\t}))\n\t\tconst result = await response.json()\n\t\tif (!result.ok) throw new Error(result.error?.message || 'RPC failed')\n\t\treturn result.result\n\t}\n\n\t// Service Bindings\n\tif (operation === 'service.fetch') {\n\t\tif (!binding || typeof binding.fetch !== 'function') {\n\t\t\tthrow new Error('Service binding ' + bindingName + ' does not support fetch()')\n\t\t}\n\t\tconst response = await binding.fetch(deserializeRequest(params[0]))\n\t\treturn serializeResponse(response)\n\t}\n\tif (operation === 'service.rpc') {\n\t\tconst methodName = params[0]\n\t\tif (typeof methodName !== 'string') {\n\t\t\tthrow new Error('Service binding ' + bindingName + ' RPC method name must be a string')\n\t\t}\n\t\tconst args = Array.isArray(params[1]) ? params[1] : []\n\t\tconst method = binding && binding[methodName]\n\t\tif (typeof method !== 'function') {\n\t\t\tthrow new Error('Service binding ' + bindingName + ' does not support ' + methodName + '()')\n\t\t}\n\t\treturn method.apply(binding, args)\n\t}\n\n\t// Queues\n\tif (operation === 'queue.send') return binding.send(params[0], params[1])\n\tif (operation === 'queue.sendBatch') return binding.sendBatch(params[0], params[1])\n\n\t// Send Email\n\tif (operation === 'email.send') {\n\t\tif (binding && typeof binding.send === 'function') {\n\t\t\tconst message = params[0]\n\t\t\tif (message && typeof message === 'object' && 'from' in message && 'to' in message && 'raw' in message) {\n\t\t\t\treturn binding.send({\n\t\t\t\t\tfrom: message.from,\n\t\t\t\t\tto: message.to,\n\t\t\t\t\t[RAW_EMAIL]: createEmailMessageRaw(message.raw)\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn binding.send(message)\n\t\t}\n\t\treturn { ok: true, simulated: true }\n\t}\n\n\t// Workflows\n\tif (operation === 'workflow.create') {\n\t\treturn serializeWorkflowInstance(await binding.create(params[0]))\n\t}\n\tif (operation === 'workflow.get') {\n\t\treturn serializeWorkflowInstance(await binding.get(params[0]))\n\t}\n\tif (operation === 'workflow.status') {\n\t\treturn (await binding.get(params[0])).status()\n\t}\n\tif (operation === 'workflow.pause') {\n\t\treturn (await binding.get(params[0])).pause()\n\t}\n\tif (operation === 'workflow.resume') {\n\t\treturn (await binding.get(params[0])).resume()\n\t}\n\tif (operation === 'workflow.terminate') {\n\t\treturn (await binding.get(params[0])).terminate()\n\t}\n\tif (operation === 'workflow.restart') {\n\t\treturn (await binding.get(params[0])).restart()\n\t}\n\tif (operation === 'workflow.sendEvent') {\n\t\treturn (await binding.get(params[0])).sendEvent(params[1])\n\t}\n\n\t// AI / generic run()\n\tif (operation === 'ai.run') {\n\t\tif (typeof binding.run !== 'function') {\n\t\t\tthrow new Error('Binding ' + bindingName + ' does not support run(): ' + method)\n\t\t}\n\t\treturn binding.run(params[0], params[1])\n\t}\n\n\tthrow new Error('Unknown operation: ' + method)\n}\n\nfunction createUnsupportedBridgeOperationErrorMessage(bindingName, operation) {\n\tconst base = \"[devflare][bridge] Unsupported bridge operation '\" + operation + \"' for binding '\" + bindingName + \"'.\"\n\tif (operation === 'fetch') {\n\t\treturn base + ' Devflare could not dispatch fetch() for this binding through the local bridge. '\n\t\t\t+ 'Expected Cloudflare API: env.' + bindingName + '.fetch(request). '\n\t\t\t+ 'If this came from SvelteKit platform.env, make sure the binding is declared as a service binding; '\n\t\t\t+ 'this is a Devflare local bridge issue when service bindings fall back to a bare fetch operation.'\n\t}\n\tif (operation === 'toString') {\n\t\treturn base + ' A platform.env value was coerced to a string through the bridge. '\n\t\t\t+ 'For SvelteKit local dev, declared vars should be plain string values and missing env names should read as undefined.'\n\t}\n\treturn base + ' Bare verbs and the legacy stmt.*/stub.* sub-prefixes are not supported; '\n\t\t+ 'use the namespaced form (e.g. kv.get, r2.put, d1.stmt.first, do.fetch, service.fetch).'\n}\n\nfunction serializeWorkflowInstance(instance) {\n\treturn {\n\t\t__type: 'WorkflowInstance',\n\t\tid: instance.id\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// WebSocket bridge (shared with src/bridge/server.ts in shape)\n// ---------------------------------------------------------------------------\n// NOTE: wsProxies is intentionally created per handleBridgeWebSocket call so\n// state never leaks across connections or across gateway-script regenerations.\n\nasync function handleBridgeRpcCall(msg, ws, env, ctx) {\n\ttry {\n\t\tconst result = await executeRpcMethod(msg.method, msg.params, env, ctx)\n\t\tws.send(JSON.stringify({ t: 'rpc.ok', id: msg.id, result }))\n\t} catch (error) {\n\t\tws.send(JSON.stringify({\n\t\t\tt: 'rpc.err',\n\t\t\tid: msg.id,\n\t\t\terror: {\n\t\t\t\tcode: error?.code || 'INTERNAL_ERROR',\n\t\t\t\tmessage: error?.message || String(error)\n\t\t\t}\n\t\t}))\n\t}\n}\n\nasync function handleBridgeWsOpen(msg, ws, env, wsProxies) {\n\ttry {\n\t\tconst binding = env[msg.target.binding]\n\t\tconst id = binding.idFromString(msg.target.id)\n\t\tconst stub = binding.get(id)\n\n\t\tconst headers = new Headers(msg.target.headers || [])\n\t\theaders.set('Upgrade', 'websocket')\n\n\t\tconst response = await stub.fetch(new Request(msg.target.url, { method: 'GET', headers }))\n\t\tconst doWs = response.webSocket\n\n\t\tif (!doWs) {\n\t\t\tws.send(JSON.stringify({\n\t\t\t\tt: 'rpc.err',\n\t\t\t\tid: 'ws_' + msg.wid,\n\t\t\t\terror: { code: 'WS_FAILED', message: 'No WebSocket returned' }\n\t\t\t}))\n\t\t\treturn\n\t\t}\n\n\t\tdoWs.accept()\n\t\twsProxies.set(msg.wid, { doWs })\n\n\t\tdoWs.addEventListener('message', (event) => {\n\t\t\tconst isText = typeof event.data === 'string'\n\t\t\tconst data = isText ? event.data : arrayBufferToBase64(event.data)\n\t\t\tws.send(JSON.stringify({ t: 'ws.data', wid: msg.wid, data, isText }))\n\t\t})\n\n\t\tdoWs.addEventListener('close', (event) => {\n\t\t\tws.send(JSON.stringify({ t: 'ws.close', wid: msg.wid, code: event.code, reason: event.reason }))\n\t\t\twsProxies.delete(msg.wid)\n\t\t})\n\n\t\tws.send(JSON.stringify({ t: 'ws.opened', wid: msg.wid }))\n\t} catch (error) {\n\t\tws.send(JSON.stringify({\n\t\t\tt: 'rpc.err',\n\t\t\tid: 'ws_' + msg.wid,\n\t\t\terror: { code: 'WS_FAILED', message: error.message }\n\t\t}))\n\t}\n}\n\nfunction handleBridgeWsClose(msg, wsProxies) {\n\tconst proxy = wsProxies.get(msg.wid)\n\tif (proxy) {\n\t\tproxy.doWs.close(msg.code, msg.reason)\n\t\twsProxies.delete(msg.wid)\n\t}\n}\n\nasync function handleBridgeJsonMessage(data, ws, env, ctx, wsProxies) {\n\tconst msg = JSON.parse(data)\n\tswitch (msg.t) {\n\t\tcase 'hello':\n\t\t\t// v2 handshake \u2014 acknowledge with welcome echoing the negotiated\n\t\t\t// capability intersection. Capabilities advertised by the gateway\n\t\t\t// are kept in sync with src/bridge/client.ts (BRIDGE_CLIENT_CAPABILITIES).\n\t\t\tws.send(JSON.stringify({\n\t\t\t\tt: 'welcome',\n\t\t\t\tprotocolVersion: 2,\n\t\t\t\tcapabilities: ['streams', 'ws-relay', 'http-transfer']\n\t\t\t\t\t.filter((c) => Array.isArray(msg.capabilities) && msg.capabilities.includes(c))\n\t\t\t\t\t.sort()\n\t\t\t}))\n\t\t\tbreak\n\t\tcase 'rpc.call':\n\t\t\tawait handleBridgeRpcCall(msg, ws, env, ctx)\n\t\t\tbreak\n\t\tcase 'ws.open':\n\t\t\tawait handleBridgeWsOpen(msg, ws, env, wsProxies)\n\t\t\tbreak\n\t\tcase 'ws.close':\n\t\t\thandleBridgeWsClose(msg, wsProxies)\n\t\t\tbreak\n\t}\n}\n\nfunction handleBridgeWebSocket(request, env, ctx) {\n\tconst { 0: client, 1: server } = new WebSocketPair()\n\tserver.accept()\n\n\t// Per-connection state: recreated for every bridge client so reloads and\n\t// concurrent clients never share WS proxy entries.\n\tconst wsProxies = new Map()\n\n\tserver.addEventListener('message', async (event) => {\n\t\ttry {\n\t\t\tif (typeof event.data === 'string') {\n\t\t\t\tawait handleBridgeJsonMessage(event.data, server, env, ctx, wsProxies)\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error('[Gateway] Error:', error)\n\t\t}\n\t})\n\n\tserver.addEventListener('close', () => {\n\t\tfor (const proxy of wsProxies.values()) {\n\t\t\t// Best-effort cleanup: the DO-side WS may already be closed or in an\n\t\t\t// invalid state; any throw here would abort sibling closes. Surface\n\t\t\t// the swallowed error when DEVFLARE_DEBUG_BRIDGE is enabled.\n\t\t\ttry { proxy.doWs.close() } catch (error) {\n\t\t\t\tif (globalThis.DEVFLARE_DEBUG_BRIDGE) {\n\t\t\t\t\tconsole.warn('[devflare:bridge] proxy.doWs.close() failed', error)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\twsProxies.clear()\n\t})\n\n\treturn new Response(null, { status: 101, webSocket: client })\n}\n\n// ---------------------------------------------------------------------------\n// HTTP transfer for R2 bodies (shared with src/bridge/server.ts in shape)\n// ---------------------------------------------------------------------------\n\nasync function handleHttpTransfer(request, env, url) {\n\tconst transferIdEncoded = url.pathname.split('/').pop()\n\tconst transferId = decodeURIComponent(transferIdEncoded || '')\n\tconst [binding, ...keyParts] = transferId.split(':')\n\tconst key = keyParts.join(':')\n\tconst bucket = env[binding]\n\n\tif (!bucket) return new Response('Bucket not found: ' + binding, { status: 404 })\n\n\tif (request.method === 'PUT' || request.method === 'POST') {\n\t\tconst result = await bucket.put(key, request.body)\n\t\treturn new Response(JSON.stringify(serializeR2Object(result)), {\n\t\t\theaders: { 'Content-Type': 'application/json' }\n\t\t})\n\t}\n\n\tif (request.method === 'GET') {\n\t\tconst object = await bucket.get(key)\n\t\tif (!object) return new Response('Not found', { status: 404 })\n\t\treturn new Response(object.body, {\n\t\t\theaders: {\n\t\t\t\t'Content-Type': object.httpMetadata?.contentType || 'application/octet-stream',\n\t\t\t\t'Content-Length': String(object.size)\n\t\t\t}\n\t\t})\n\t}\n\n\treturn new Response('Method not allowed', { status: 405 })\n}\n";
|
|
8
8
|
//# sourceMappingURL=gateway-runtime.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway-runtime.d.ts","sourceRoot":"","sources":["../../src/bridge/gateway-runtime.ts"],"names":[],"mappings":"AAcA;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,
|
|
1
|
+
{"version":3,"file":"gateway-runtime.d.ts","sourceRoot":"","sources":["../../src/bridge/gateway-runtime.ts"],"names":[],"mappings":"AAcA;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,mpkBAghB9B,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/bridge/proxy.ts"],"names":[],"mappings":"AAMA,OAAO,EAAa,KAAK,YAAY,EAAE,MAAM,UAAU,CAAA;AAavD,MAAM,WAAW,eAAe;IAC/B,0DAA0D;IAC1D,MAAM,CAAC,EAAE,YAAY,CAAA;IACrB,qCAAqC;IACrC,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,uEAAuE;IACvE,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,wEAAwE;IACxE,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAA;CAC9C;
|
|
1
|
+
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/bridge/proxy.ts"],"names":[],"mappings":"AAMA,OAAO,EAAa,KAAK,YAAY,EAAE,MAAM,UAAU,CAAA;AAavD,MAAM,WAAW,eAAe;IAC/B,0DAA0D;IAC1D,MAAM,CAAC,EAAE,YAAY,CAAA;IACrB,qCAAqC;IACrC,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,uEAAuE;IACvE,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,wEAAwE;IACxE,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAA;CAC9C;AAqmBD,mDAAmD;AACnD,MAAM,MAAM,WAAW,GACpB,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,OAAO,GACP,IAAI,GACJ,SAAS,GACT,WAAW,GACX,UAAU,GACV,QAAQ,GACR,KAAK,CAAA;AAER,MAAM,WAAW,YAAY;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAAA;CAC1B;AAKD;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,eAAe,GAAG;IAAE,KAAK,CAAC,EAAE,YAAY,CAAA;CAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAoFhH;AAoFD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAO5C,CAAA;AAEF;;GAEG;AACH,wBAAgB,OAAO,CAAC,OAAO,GAAE,eAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAG9E;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAIzD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/bridge/server.ts"],"names":[],"mappings":"AAuCA,MAAM,WAAW,UAAU;IAE1B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACtB;;IAiBM,KAAK,UAAU,OAAO,OAAO,UAAU,OAAO,gBAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC;;;AA8KzF,wBAAsB,gBAAgB,CACrC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,OAAO,EAAE,EACjB,GAAG,EAAE,UAAU,EACf,GAAG,EAAE,gBAAgB,GACnB,OAAO,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/bridge/server.ts"],"names":[],"mappings":"AAuCA,MAAM,WAAW,UAAU;IAE1B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACtB;;IAiBM,KAAK,UAAU,OAAO,OAAO,UAAU,OAAO,gBAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC;;;AA8KzF,wBAAsB,gBAAgB,CACrC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,OAAO,EAAE,EACjB,GAAG,EAAE,UAAU,EACf,GAAG,EAAE,gBAAgB,GACnB,OAAO,CAAC,OAAO,CAAC,CA+JlB"}
|
|
@@ -90,7 +90,9 @@ export type SerializedSpecial = {
|
|
|
90
90
|
stack?: string;
|
|
91
91
|
};
|
|
92
92
|
/** Serialize a value that may contain special types */
|
|
93
|
-
export declare function serializeValue(value: unknown
|
|
93
|
+
export declare function serializeValue(value: unknown, options?: {
|
|
94
|
+
httpThreshold?: number;
|
|
95
|
+
}): Promise<{
|
|
94
96
|
value: unknown;
|
|
95
97
|
streams: StreamRef[];
|
|
96
98
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"value-serialization.d.ts","sourceRoot":"","sources":["../../../src/bridge/v2/value-serialization.ts"],"names":[],"mappings":"AAgBA,8BAA8B;AAC9B,MAAM,WAAW,iBAAiB;IACjC,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAA;IAC3B,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IACrB,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAA;IACxC,EAAE,CAAC,EAAE,OAAO,CAAA;CACZ;AAED,+BAA+B;AAC/B,MAAM,WAAW,kBAAkB;IAClC,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAA;IAC3B,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IACrB,SAAS,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;CAC3B;AAED,0DAA0D;AAC1D,MAAM,MAAM,OAAO,GAChB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAA;AAElC;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,EAAG,MAAe,CAAA;AAEzC,4FAA4F;AAC5F,MAAM,WAAW,cAAc;IAC9B,MAAM,EAAE,OAAO,UAAU,CAAA;IACzB,GAAG,EAAE,MAAM,CAAA;CACX;AAMD,oCAAoC;AACpC,wBAAsB,gBAAgB,CACrC,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,GAClC,OAAO,CAAC;IAAE,UAAU,EAAE,iBAAiB,CAAC;IAAC,OAAO,EAAE,SAAS,EAAE,CAAA;CAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"value-serialization.d.ts","sourceRoot":"","sources":["../../../src/bridge/v2/value-serialization.ts"],"names":[],"mappings":"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"}
|
package/dist/browser.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
env,
|
|
6
6
|
vars
|
|
7
|
-
} from "./index-
|
|
7
|
+
} from "./index-qz6nbwpw.js";
|
|
8
8
|
import {
|
|
9
9
|
durableObject,
|
|
10
10
|
getDurableObjectOptions
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
getClient,
|
|
16
16
|
initEnv,
|
|
17
17
|
setBindingHints
|
|
18
|
-
} from "./index-
|
|
18
|
+
} from "./index-6sj0v0dk.js";
|
|
19
19
|
import"./index-hpwa6vsw.js";
|
|
20
20
|
import {
|
|
21
21
|
defineConfig,
|
package/dist/cli/index.js
CHANGED
|
@@ -434,7 +434,7 @@ var DEFAULT_BRIDGE_PORT = 8686;
|
|
|
434
434
|
// src/bridge/v2/value-serialization.ts
|
|
435
435
|
async function serializeRequest(request, options) {
|
|
436
436
|
const streams = [];
|
|
437
|
-
const threshold = options?.httpThreshold ??
|
|
437
|
+
const threshold = options?.httpThreshold ?? HTTP_TRANSFER_THRESHOLD;
|
|
438
438
|
const headers = [];
|
|
439
439
|
request.headers.forEach((value, key) => {
|
|
440
440
|
headers.push([key, value]);
|
|
@@ -443,7 +443,7 @@ async function serializeRequest(request, options) {
|
|
|
443
443
|
if (request.body) {
|
|
444
444
|
const bytes = await request.arrayBuffer();
|
|
445
445
|
if (bytes.byteLength > threshold) {
|
|
446
|
-
throw new Error("
|
|
446
|
+
throw new Error("Request body exceeds the bridge inline limit (~512 KB) and large request-body streaming is not yet supported over the local bridge. " + "Send the payload in smaller chunks or via an R2 binding for now.");
|
|
447
447
|
} else if (bytes.byteLength > 0) {
|
|
448
448
|
body = { type: "bytes", data: base64Encode(new Uint8Array(bytes)) };
|
|
449
449
|
}
|
|
@@ -482,7 +482,7 @@ function deserializeRequest(serialized, getStream) {
|
|
|
482
482
|
}
|
|
483
483
|
async function serializeResponse(response, options) {
|
|
484
484
|
const streams = [];
|
|
485
|
-
const threshold = options?.httpThreshold ??
|
|
485
|
+
const threshold = options?.httpThreshold ?? HTTP_TRANSFER_THRESHOLD;
|
|
486
486
|
const headers = [];
|
|
487
487
|
response.headers.forEach((value, key) => {
|
|
488
488
|
headers.push([key, value]);
|
|
@@ -491,7 +491,19 @@ async function serializeResponse(response, options) {
|
|
|
491
491
|
if (response.body) {
|
|
492
492
|
const bytes = await response.arrayBuffer();
|
|
493
493
|
if (bytes.byteLength > threshold) {
|
|
494
|
-
|
|
494
|
+
const sid = nextStreamId();
|
|
495
|
+
const payload = new Uint8Array(bytes);
|
|
496
|
+
const frameSize = HTTP_TRANSFER_THRESHOLD;
|
|
497
|
+
const stream = new ReadableStream({
|
|
498
|
+
start(controller) {
|
|
499
|
+
for (let offset = 0;offset < payload.byteLength; offset += frameSize) {
|
|
500
|
+
controller.enqueue(payload.slice(offset, Math.min(offset + frameSize, payload.byteLength)));
|
|
501
|
+
}
|
|
502
|
+
controller.close();
|
|
503
|
+
}
|
|
504
|
+
});
|
|
505
|
+
streams.push({ sid, stream });
|
|
506
|
+
body = { type: "stream", sid };
|
|
495
507
|
} else if (bytes.byteLength > 0) {
|
|
496
508
|
body = { type: "bytes", data: base64Encode(new Uint8Array(bytes)) };
|
|
497
509
|
}
|
|
@@ -526,22 +538,22 @@ function deserializeResponse(serialized, getStream) {
|
|
|
526
538
|
headers: serialized.headers
|
|
527
539
|
});
|
|
528
540
|
}
|
|
529
|
-
async function serializeValue(value) {
|
|
541
|
+
async function serializeValue(value, options) {
|
|
530
542
|
const streams = [];
|
|
531
|
-
const result = await serializeValueInternal(value, streams);
|
|
543
|
+
const result = await serializeValueInternal(value, streams, options);
|
|
532
544
|
return { value: result, streams };
|
|
533
545
|
}
|
|
534
|
-
async function serializeValueInternal(value, streams) {
|
|
546
|
+
async function serializeValueInternal(value, streams, options) {
|
|
535
547
|
if (value === null || value === undefined) {
|
|
536
548
|
return value;
|
|
537
549
|
}
|
|
538
550
|
if (value instanceof Request) {
|
|
539
|
-
const { serialized, streams: reqStreams } = await serializeRequest(value);
|
|
551
|
+
const { serialized, streams: reqStreams } = await serializeRequest(value, options);
|
|
540
552
|
streams.push(...reqStreams);
|
|
541
553
|
return { __type: "Request", ...serialized };
|
|
542
554
|
}
|
|
543
555
|
if (value instanceof Response) {
|
|
544
|
-
const { serialized, streams: resStreams } = await serializeResponse(value);
|
|
556
|
+
const { serialized, streams: resStreams } = await serializeResponse(value, options);
|
|
545
557
|
streams.push(...resStreams);
|
|
546
558
|
return { __type: "Response", ...serialized };
|
|
547
559
|
}
|
|
@@ -576,8 +588,8 @@ async function serializeValueInternal(value, streams) {
|
|
|
576
588
|
const entries = [];
|
|
577
589
|
for (const [k, v] of value.entries()) {
|
|
578
590
|
entries.push([
|
|
579
|
-
await serializeValueInternal(k, streams),
|
|
580
|
-
await serializeValueInternal(v, streams)
|
|
591
|
+
await serializeValueInternal(k, streams, options),
|
|
592
|
+
await serializeValueInternal(v, streams, options)
|
|
581
593
|
]);
|
|
582
594
|
}
|
|
583
595
|
return { __devflare: "map", entries };
|
|
@@ -585,17 +597,17 @@ async function serializeValueInternal(value, streams) {
|
|
|
585
597
|
if (value instanceof Set) {
|
|
586
598
|
const values = [];
|
|
587
599
|
for (const v of value.values()) {
|
|
588
|
-
values.push(await serializeValueInternal(v, streams));
|
|
600
|
+
values.push(await serializeValueInternal(v, streams, options));
|
|
589
601
|
}
|
|
590
602
|
return { __devflare: "set", values };
|
|
591
603
|
}
|
|
592
604
|
if (Array.isArray(value)) {
|
|
593
|
-
return Promise.all(value.map((v) => serializeValueInternal(v, streams)));
|
|
605
|
+
return Promise.all(value.map((v) => serializeValueInternal(v, streams, options)));
|
|
594
606
|
}
|
|
595
607
|
if (typeof value === "object") {
|
|
596
608
|
const result = {};
|
|
597
609
|
for (const [k, v] of Object.entries(value)) {
|
|
598
|
-
result[k] = await serializeValueInternal(v, streams);
|
|
610
|
+
result[k] = await serializeValueInternal(v, streams, options);
|
|
599
611
|
}
|
|
600
612
|
return result;
|
|
601
613
|
}
|
|
@@ -1263,6 +1275,7 @@ class BridgeClient {
|
|
|
1263
1275
|
wsProxies = new Map;
|
|
1264
1276
|
pendingWsOpens = new Map;
|
|
1265
1277
|
outgoingStreams = new Map;
|
|
1278
|
+
eventListeners = new Map;
|
|
1266
1279
|
connectPromise = null;
|
|
1267
1280
|
isConnected = false;
|
|
1268
1281
|
constructor(options = {}) {
|
|
@@ -1352,6 +1365,7 @@ class BridgeClient {
|
|
|
1352
1365
|
this.ws = null;
|
|
1353
1366
|
this.isConnected = false;
|
|
1354
1367
|
this.cleanupPending(new Error("Bridge disconnected"));
|
|
1368
|
+
this.eventListeners.clear();
|
|
1355
1369
|
}
|
|
1356
1370
|
close() {
|
|
1357
1371
|
this.disconnect();
|
|
@@ -1428,6 +1442,22 @@ class BridgeClient {
|
|
|
1428
1442
|
clearTimeout(timeoutHandle);
|
|
1429
1443
|
}
|
|
1430
1444
|
}
|
|
1445
|
+
on(topic, cb) {
|
|
1446
|
+
let set = this.eventListeners.get(topic);
|
|
1447
|
+
if (!set) {
|
|
1448
|
+
set = new Set;
|
|
1449
|
+
this.eventListeners.set(topic, set);
|
|
1450
|
+
}
|
|
1451
|
+
set.add(cb);
|
|
1452
|
+
return () => {
|
|
1453
|
+
const current = this.eventListeners.get(topic);
|
|
1454
|
+
if (!current)
|
|
1455
|
+
return;
|
|
1456
|
+
current.delete(cb);
|
|
1457
|
+
if (current.size === 0)
|
|
1458
|
+
this.eventListeners.delete(topic);
|
|
1459
|
+
};
|
|
1460
|
+
}
|
|
1431
1461
|
async createWsProxy(binding, id, url, headers) {
|
|
1432
1462
|
await this.ensureConnected();
|
|
1433
1463
|
const wid = nextWsId();
|
|
@@ -1571,7 +1601,21 @@ class BridgeClient {
|
|
|
1571
1601
|
break;
|
|
1572
1602
|
}
|
|
1573
1603
|
}
|
|
1574
|
-
handleEvent(
|
|
1604
|
+
handleEvent(msg) {
|
|
1605
|
+
this.dispatchEvent(this.eventListeners.get(msg.topic), msg.data, msg.topic);
|
|
1606
|
+
this.dispatchEvent(this.eventListeners.get("*"), msg.data, msg.topic);
|
|
1607
|
+
}
|
|
1608
|
+
dispatchEvent(listeners, data, topic) {
|
|
1609
|
+
if (!listeners)
|
|
1610
|
+
return;
|
|
1611
|
+
for (const cb of [...listeners]) {
|
|
1612
|
+
try {
|
|
1613
|
+
cb(data);
|
|
1614
|
+
} catch (error) {
|
|
1615
|
+
bridgeLog.warn(`event listener for topic "${topic}" threw`, error);
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1575
1619
|
handleStreamPull(msg) {
|
|
1576
1620
|
const streamRef = this.outgoingStreams.get(msg.sid);
|
|
1577
1621
|
if (!streamRef)
|
|
@@ -1817,14 +1861,14 @@ function createD1StatementProxy(client, bindingName, sql, bindings) {
|
|
|
1817
1861
|
function createDOProxy(client, bindingName, proxyOptions = {}) {
|
|
1818
1862
|
return {
|
|
1819
1863
|
idFromName(name) {
|
|
1820
|
-
return createDOIdProxy(client, bindingName, { type: "name", value: name });
|
|
1864
|
+
return createDOIdProxy(client, bindingName, { type: "name", value: name, jurisdiction: proxyOptions.jurisdiction });
|
|
1821
1865
|
},
|
|
1822
1866
|
idFromString(hexId) {
|
|
1823
|
-
return createDOIdProxy(client, bindingName, { type: "hex", value: hexId });
|
|
1867
|
+
return createDOIdProxy(client, bindingName, { type: "hex", value: hexId, jurisdiction: proxyOptions.jurisdiction });
|
|
1824
1868
|
},
|
|
1825
1869
|
newUniqueId(options) {
|
|
1826
1870
|
const tempId = crypto.randomUUID().replace(/-/g, "");
|
|
1827
|
-
return createDOIdProxy(client, bindingName, { type: "unique", value: tempId, options });
|
|
1871
|
+
return createDOIdProxy(client, bindingName, { type: "unique", value: tempId, options, jurisdiction: proxyOptions.jurisdiction });
|
|
1828
1872
|
},
|
|
1829
1873
|
get(id) {
|
|
1830
1874
|
const idProxy = id;
|
|
@@ -1835,7 +1879,7 @@ function createDOProxy(client, bindingName, proxyOptions = {}) {
|
|
|
1835
1879
|
return this.get(id);
|
|
1836
1880
|
},
|
|
1837
1881
|
jurisdiction(jurisdiction) {
|
|
1838
|
-
return createDOProxy(client, bindingName, proxyOptions);
|
|
1882
|
+
return createDOProxy(client, bindingName, { ...proxyOptions, jurisdiction });
|
|
1839
1883
|
}
|
|
1840
1884
|
};
|
|
1841
1885
|
}
|
|
@@ -1860,13 +1904,13 @@ function createDOStubProxy(client, bindingName, idInfo, proxyOptions = {}) {
|
|
|
1860
1904
|
return resolvedId;
|
|
1861
1905
|
switch (idInfo.type) {
|
|
1862
1906
|
case "name":
|
|
1863
|
-
resolvedId = await client.call(`${bindingName}.do.idFromName`, [idInfo.value]);
|
|
1907
|
+
resolvedId = await client.call(`${bindingName}.do.idFromName`, [idInfo.value, idInfo.jurisdiction]);
|
|
1864
1908
|
break;
|
|
1865
1909
|
case "hex":
|
|
1866
1910
|
resolvedId = { __type: "DOId", hex: idInfo.value };
|
|
1867
1911
|
break;
|
|
1868
1912
|
case "unique":
|
|
1869
|
-
resolvedId = await client.call(`${bindingName}.do.newUniqueId`, [idInfo.options]);
|
|
1913
|
+
resolvedId = await client.call(`${bindingName}.do.newUniqueId`, [idInfo.options, idInfo.jurisdiction]);
|
|
1870
1914
|
break;
|
|
1871
1915
|
}
|
|
1872
1916
|
return resolvedId;
|
|
@@ -1939,7 +1983,7 @@ function createDOStubProxy(client, bindingName, idInfo, proxyOptions = {}) {
|
|
|
1939
1983
|
return Promise.resolve();
|
|
1940
1984
|
},
|
|
1941
1985
|
startTls() {
|
|
1942
|
-
throw new Error("startTls not supported on
|
|
1986
|
+
throw new Error("startTls() is not supported on a Durable Object WebSocket connection. " + "StartTLS applies to raw TCP sockets (cloudflare:sockets connect()), not " + "WebSocket-tunneled DO connections, whose transport is already secured by the connection itself.");
|
|
1943
1987
|
}
|
|
1944
1988
|
};
|
|
1945
1989
|
},
|
|
@@ -1362,7 +1362,7 @@ async function runInit(parsed, logger, options) {
|
|
|
1362
1362
|
return runInitCommand(parsed, logger, options);
|
|
1363
1363
|
}
|
|
1364
1364
|
async function runDev(parsed, logger, options) {
|
|
1365
|
-
const { runDevCommand } = await import("./dev-
|
|
1365
|
+
const { runDevCommand } = await import("./dev-ymkq3thq.js");
|
|
1366
1366
|
return runDevCommand(parsed, logger, options);
|
|
1367
1367
|
}
|
|
1368
1368
|
async function runBuild(parsed, logger, options) {
|
|
@@ -56,6 +56,29 @@ function extractBindingHints(config) {
|
|
|
56
56
|
return hints;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
// src/shims/local-hyperdrive.ts
|
|
60
|
+
var HYPERDRIVE_CONNECT_MESSAGE = "Local Hyperdrive does not implement the raw socket connect(). " + "Use the populated connection fields (connectionString, or host/port/user/password/database) " + "with your Node database driver, or run a createTestContext()/Miniflare-backed test " + "(Miniflare establishes real Hyperdrive socket connections) for socket-level behavior.";
|
|
61
|
+
function defaultPortForDatabaseUrl(url) {
|
|
62
|
+
if (url.port) {
|
|
63
|
+
return Number(url.port);
|
|
64
|
+
}
|
|
65
|
+
return url.protocol === "mysql:" ? 3306 : 5432;
|
|
66
|
+
}
|
|
67
|
+
function createLocalHyperdrive(connectionString) {
|
|
68
|
+
const url = new URL(connectionString);
|
|
69
|
+
return {
|
|
70
|
+
connectionString,
|
|
71
|
+
host: url.hostname,
|
|
72
|
+
port: defaultPortForDatabaseUrl(url),
|
|
73
|
+
user: decodeURIComponent(url.username),
|
|
74
|
+
password: decodeURIComponent(url.password),
|
|
75
|
+
database: decodeURIComponent(url.pathname.replace(/^\//, "")),
|
|
76
|
+
connect() {
|
|
77
|
+
throw new Error(HYPERDRIVE_CONNECT_MESSAGE);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
59
82
|
// src/shims/local-worker-loader.ts
|
|
60
83
|
var activeWorkerLoaderRuntimes = new Set;
|
|
61
84
|
function getModuleSource(module, mainModule) {
|
|
@@ -107,7 +130,7 @@ function createLocalWorkerStub(codeProvider) {
|
|
|
107
130
|
return fetcher;
|
|
108
131
|
},
|
|
109
132
|
getDurableObjectClass() {
|
|
110
|
-
throw new Error("Worker Loader local shim
|
|
133
|
+
throw new Error("Worker Loader local shim cannot materialise a dynamic Durable Object class. getDurableObjectClass() returns an opaque facet-spawning reference that workerd only exposes inside the runtime. Use createTestContext() (a real Miniflare worker) for Durable Object behavior, or createMockWorkerLoader({ stub }) to inject a stub.");
|
|
111
134
|
}
|
|
112
135
|
};
|
|
113
136
|
}
|
|
@@ -129,4 +152,4 @@ async function disposeLocalWorkerLoaderBindings() {
|
|
|
129
152
|
}));
|
|
130
153
|
}
|
|
131
154
|
|
|
132
|
-
export { extractBindingHints, createLocalWorkerLoaderBinding, disposeLocalWorkerLoaderBindings };
|
|
155
|
+
export { extractBindingHints, createLocalHyperdrive, createLocalWorkerLoaderBinding, disposeLocalWorkerLoaderBindings };
|
|
@@ -154,6 +154,19 @@ function isDurableObjectNamespace(binding) {
|
|
|
154
154
|
&& typeof binding.newUniqueId === 'function'
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
+
/**
|
|
158
|
+
* Resolve a (possibly jurisdiction-scoped) DurableObjectNamespace.
|
|
159
|
+
* Forwards the jurisdiction faithfully when the binding supports it
|
|
160
|
+
* (real Cloudflare), and degrades to the plain binding otherwise
|
|
161
|
+
* (miniflare/workerd local emulation, which does not pin jurisdictions).
|
|
162
|
+
*/
|
|
163
|
+
function resolveDoNamespace(binding, jurisdiction) {
|
|
164
|
+
if (jurisdiction && typeof binding.jurisdiction === 'function') {
|
|
165
|
+
return binding.jurisdiction(jurisdiction)
|
|
166
|
+
}
|
|
167
|
+
return binding
|
|
168
|
+
}
|
|
169
|
+
|
|
157
170
|
/**
|
|
158
171
|
* Execute an RPC method against the gateway's bindings.
|
|
159
172
|
*
|
|
@@ -250,7 +263,8 @@ async function executeRpcMethod(method, params, env, _ctx) {
|
|
|
250
263
|
|
|
251
264
|
// Durable Objects
|
|
252
265
|
if (operation === 'do.idFromName') {
|
|
253
|
-
const
|
|
266
|
+
const ns = resolveDoNamespace(binding, params[1])
|
|
267
|
+
const id = ns.idFromName(params[0])
|
|
254
268
|
return { __type: 'DOId', hex: id.toString() }
|
|
255
269
|
}
|
|
256
270
|
if (operation === 'do.idFromString') {
|
|
@@ -258,7 +272,8 @@ async function executeRpcMethod(method, params, env, _ctx) {
|
|
|
258
272
|
return { __type: 'DOId', hex: id.toString() }
|
|
259
273
|
}
|
|
260
274
|
if (operation === 'do.newUniqueId') {
|
|
261
|
-
const
|
|
275
|
+
const ns = resolveDoNamespace(binding, params[1])
|
|
276
|
+
const id = ns.newUniqueId(params[0])
|
|
262
277
|
return { __type: 'DOId', hex: id.toString() }
|
|
263
278
|
}
|
|
264
279
|
if (operation === 'do.fetch') {
|
package/dist/index.js
CHANGED
|
@@ -4,19 +4,19 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
parseArgs,
|
|
6
6
|
runCli
|
|
7
|
-
} from "./index-
|
|
7
|
+
} from "./index-sqkbyw0c.js";
|
|
8
8
|
import"./index-627srx16.js";
|
|
9
9
|
import"./index-stgn34cr.js";
|
|
10
10
|
import"./index-3t6rypgc.js";
|
|
11
11
|
import {
|
|
12
12
|
env,
|
|
13
13
|
vars
|
|
14
|
-
} from "./index-
|
|
14
|
+
} from "./index-qz6nbwpw.js";
|
|
15
15
|
import {
|
|
16
16
|
durableObject,
|
|
17
17
|
getDurableObjectOptions
|
|
18
18
|
} from "./index-a855bdsx.js";
|
|
19
|
-
import"./index-
|
|
19
|
+
import"./index-6sj0v0dk.js";
|
|
20
20
|
import"./index-hpwa6vsw.js";
|
|
21
21
|
import {
|
|
22
22
|
compileConfig,
|
package/dist/runtime/index.js
CHANGED
|
@@ -19,8 +19,8 @@ import {
|
|
|
19
19
|
resolveFetchHandler,
|
|
20
20
|
sequence,
|
|
21
21
|
vars
|
|
22
|
-
} from "../index-
|
|
23
|
-
import"../index-
|
|
22
|
+
} from "../index-85yjb686.js";
|
|
23
|
+
import"../index-qz6nbwpw.js";
|
|
24
24
|
import {
|
|
25
25
|
durableObject,
|
|
26
26
|
getDurableObjectOptions
|
|
@@ -56,7 +56,7 @@ import {
|
|
|
56
56
|
hasContext,
|
|
57
57
|
runWithContext,
|
|
58
58
|
runWithEventContext
|
|
59
|
-
} from "../index-
|
|
59
|
+
} from "../index-6sj0v0dk.js";
|
|
60
60
|
import {
|
|
61
61
|
clearLocalSendEmailBindings,
|
|
62
62
|
setLocalSendEmailBindings
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const HYPERDRIVE_CONNECT_MESSAGE: string;
|
|
2
|
+
/**
|
|
3
|
+
* Creates a Hyperdrive binding around a local database connection string.
|
|
4
|
+
*
|
|
5
|
+
* The connection fields are real and usable with any Node database client. The
|
|
6
|
+
* Cloudflare `connect()` raw socket is intentionally not implemented — it would
|
|
7
|
+
* require faithfully reproducing `cloudflare:sockets` semantics (TLS, startTls(),
|
|
8
|
+
* half-open, SocketInfo) over node:net, which is exactly the kind of fake that
|
|
9
|
+
* fails silently. It throws a clear, actionable error instead.
|
|
10
|
+
*/
|
|
11
|
+
export declare function createLocalHyperdrive(connectionString: string): Hyperdrive;
|
|
12
|
+
//# sourceMappingURL=local-hyperdrive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-hyperdrive.d.ts","sourceRoot":"","sources":["../../src/shims/local-hyperdrive.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,0BAA0B,QAImD,CAAA;AAU1F;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,gBAAgB,EAAE,MAAM,GAAG,UAAU,CAc1E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-worker-loader.d.ts","sourceRoot":"","sources":["../../src/shims/local-worker-loader.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"local-worker-loader.d.ts","sourceRoot":"","sources":["../../src/shims/local-worker-loader.ts"],"names":[],"mappings":"AAkFA,wBAAgB,8BAA8B,IAAI,YAAY,CAY7D;AAED,wBAAsB,gCAAgC,IAAI,OAAO,CAAC,IAAI,CAAC,CAOtE"}
|
package/dist/sveltekit/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import"../index-
|
|
1
|
+
import"../index-za0r01bx.js";
|
|
2
2
|
import {
|
|
3
|
+
createLocalHyperdrive,
|
|
3
4
|
createLocalWorkerLoaderBinding,
|
|
4
5
|
extractBindingHints
|
|
5
|
-
} from "../index-
|
|
6
|
+
} from "../index-t9y0sve5.js";
|
|
6
7
|
import {
|
|
7
8
|
createLocalImagesBinding,
|
|
8
9
|
createLocalMediaBinding
|
|
@@ -16,7 +17,7 @@ import {
|
|
|
16
17
|
getClient,
|
|
17
18
|
runWithEventContext,
|
|
18
19
|
setBindingHints
|
|
19
|
-
} from "../index-
|
|
20
|
+
} from "../index-6sj0v0dk.js";
|
|
20
21
|
import {
|
|
21
22
|
createLocalSendEmailBinding
|
|
22
23
|
} from "../index-hpwa6vsw.js";
|
|
@@ -31,32 +32,12 @@ import"../index-c8p4njqy.js";
|
|
|
31
32
|
import"../index-q8f4kawk.js";
|
|
32
33
|
import"../index-37x76zdn.js";
|
|
33
34
|
// src/sveltekit/local-bindings.ts
|
|
34
|
-
function defaultPortForDatabaseUrl(url) {
|
|
35
|
-
if (url.port) {
|
|
36
|
-
return Number(url.port);
|
|
37
|
-
}
|
|
38
|
-
return url.protocol === "mysql:" ? 3306 : 5432;
|
|
39
|
-
}
|
|
40
|
-
function createLocalHyperdriveBinding(connectionString) {
|
|
41
|
-
const url = new URL(connectionString);
|
|
42
|
-
return {
|
|
43
|
-
connectionString,
|
|
44
|
-
host: url.hostname,
|
|
45
|
-
port: defaultPortForDatabaseUrl(url),
|
|
46
|
-
user: decodeURIComponent(url.username),
|
|
47
|
-
password: decodeURIComponent(url.password),
|
|
48
|
-
database: decodeURIComponent(url.pathname.replace(/^\//, "")),
|
|
49
|
-
connect() {
|
|
50
|
-
throw new Error("Devflare local Hyperdrive exposes connectionString for local database clients. Raw socket connect() is not implemented in the SvelteKit Node adapter path.");
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
35
|
function buildLocalHyperdriveBindings(config) {
|
|
55
36
|
const bindings = {};
|
|
56
37
|
for (const [name, binding] of Object.entries(config.bindings?.hyperdrive ?? {})) {
|
|
57
38
|
const normalized = normalizeHyperdriveBinding(binding);
|
|
58
39
|
if (normalized.localConnectionString) {
|
|
59
|
-
bindings[name] =
|
|
40
|
+
bindings[name] = createLocalHyperdrive(normalized.localConnectionString);
|
|
60
41
|
}
|
|
61
42
|
}
|
|
62
43
|
return bindings;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-bindings.d.ts","sourceRoot":"","sources":["../../src/sveltekit/local-bindings.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,cAAc,EACnB,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"local-bindings.d.ts","sourceRoot":"","sources":["../../src/sveltekit/local-bindings.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,cAAc,EACnB,MAAM,WAAW,CAAA;AAuBlB,wBAAgB,2BAA2B,CAC1C,MAAM,EAAE,cAAc,EACtB,GAAG,EAAE,MAAM,GACT,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAwBzB;AAED,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACpC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAoCzB"}
|
package/dist/test/index.js
CHANGED
|
@@ -14,12 +14,12 @@ import {
|
|
|
14
14
|
invokeFetchModule,
|
|
15
15
|
matchFetchRoute,
|
|
16
16
|
resolveFetchHandler
|
|
17
|
-
} from "../index-
|
|
17
|
+
} from "../index-85yjb686.js";
|
|
18
18
|
import {
|
|
19
19
|
__clearTestContext,
|
|
20
20
|
__setTestContext,
|
|
21
21
|
env
|
|
22
|
-
} from "../index-
|
|
22
|
+
} from "../index-qz6nbwpw.js";
|
|
23
23
|
import"../index-a855bdsx.js";
|
|
24
24
|
import {
|
|
25
25
|
buildHyperdrivesConfig,
|
|
@@ -38,10 +38,11 @@ import {
|
|
|
38
38
|
import"../index-aqrwyy57.js";
|
|
39
39
|
import"../index-vhqww6tt.js";
|
|
40
40
|
import {
|
|
41
|
+
createLocalHyperdrive,
|
|
41
42
|
createLocalWorkerLoaderBinding,
|
|
42
43
|
disposeLocalWorkerLoaderBindings,
|
|
43
44
|
extractBindingHints
|
|
44
|
-
} from "../index-
|
|
45
|
+
} from "../index-t9y0sve5.js";
|
|
45
46
|
import {
|
|
46
47
|
buildLocalBindingShimServiceConfig
|
|
47
48
|
} from "../index-dm9q84c7.js";
|
|
@@ -60,7 +61,7 @@ import {
|
|
|
60
61
|
runWithContext,
|
|
61
62
|
runWithEventContext,
|
|
62
63
|
setBindingHints
|
|
63
|
-
} from "../index-
|
|
64
|
+
} from "../index-6sj0v0dk.js";
|
|
64
65
|
import {
|
|
65
66
|
createLocalSendEmailBinding,
|
|
66
67
|
wrapEnvSendEmailBindings
|
|
@@ -1058,8 +1059,37 @@ function createMockD1(mockResultsOrOptions = []) {
|
|
|
1058
1059
|
};
|
|
1059
1060
|
}
|
|
1060
1061
|
// src/test/utilities/r2.ts
|
|
1062
|
+
async function coerceToString(value) {
|
|
1063
|
+
if (typeof value === "string") {
|
|
1064
|
+
return value;
|
|
1065
|
+
}
|
|
1066
|
+
if (value === null) {
|
|
1067
|
+
return "";
|
|
1068
|
+
}
|
|
1069
|
+
if (value instanceof ArrayBuffer) {
|
|
1070
|
+
return new TextDecoder().decode(value);
|
|
1071
|
+
}
|
|
1072
|
+
if (ArrayBuffer.isView(value)) {
|
|
1073
|
+
return new TextDecoder().decode(value);
|
|
1074
|
+
}
|
|
1075
|
+
if (value instanceof Blob) {
|
|
1076
|
+
return await value.text();
|
|
1077
|
+
}
|
|
1078
|
+
const reader = value.getReader();
|
|
1079
|
+
const chunks = [];
|
|
1080
|
+
let done = false;
|
|
1081
|
+
while (!done) {
|
|
1082
|
+
const result = await reader.read();
|
|
1083
|
+
done = result.done;
|
|
1084
|
+
if (result.value) {
|
|
1085
|
+
chunks.push(new TextDecoder().decode(result.value));
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
return chunks.join("");
|
|
1089
|
+
}
|
|
1061
1090
|
function createMockR2() {
|
|
1062
1091
|
const store = new Map;
|
|
1092
|
+
const uploads = new Map;
|
|
1063
1093
|
const createR2Object = (key, content, metadata) => {
|
|
1064
1094
|
const encoder = new TextEncoder;
|
|
1065
1095
|
const data = encoder.encode(content);
|
|
@@ -1098,28 +1128,7 @@ function createMockR2() {
|
|
|
1098
1128
|
};
|
|
1099
1129
|
return {
|
|
1100
1130
|
async put(key, value, options) {
|
|
1101
|
-
|
|
1102
|
-
if (typeof value === "string") {
|
|
1103
|
-
content = value;
|
|
1104
|
-
} else if (value instanceof ArrayBuffer) {
|
|
1105
|
-
content = new TextDecoder().decode(value);
|
|
1106
|
-
} else if (value instanceof Blob) {
|
|
1107
|
-
content = await value.text();
|
|
1108
|
-
} else if (value === null) {
|
|
1109
|
-
content = "";
|
|
1110
|
-
} else {
|
|
1111
|
-
const reader = value.getReader();
|
|
1112
|
-
const chunks = [];
|
|
1113
|
-
let done = false;
|
|
1114
|
-
while (!done) {
|
|
1115
|
-
const result = await reader.read();
|
|
1116
|
-
done = result.done;
|
|
1117
|
-
if (result.value) {
|
|
1118
|
-
chunks.push(new TextDecoder().decode(result.value));
|
|
1119
|
-
}
|
|
1120
|
-
}
|
|
1121
|
-
content = chunks.join("");
|
|
1122
|
-
}
|
|
1131
|
+
const content = await coerceToString(value);
|
|
1123
1132
|
store.set(key, { content });
|
|
1124
1133
|
return createR2Object(key, content);
|
|
1125
1134
|
},
|
|
@@ -1162,12 +1171,54 @@ function createMockR2() {
|
|
|
1162
1171
|
};
|
|
1163
1172
|
},
|
|
1164
1173
|
async createMultipartUpload(key, options) {
|
|
1165
|
-
|
|
1174
|
+
const uploadId = crypto.randomUUID();
|
|
1175
|
+
uploads.set(uploadId, { key, parts: new Map, options });
|
|
1176
|
+
return createMultipart(key, uploadId);
|
|
1166
1177
|
},
|
|
1167
|
-
|
|
1168
|
-
|
|
1178
|
+
resumeMultipartUpload(key, uploadId) {
|
|
1179
|
+
if (!uploads.has(uploadId)) {
|
|
1180
|
+
uploads.set(uploadId, { key, parts: new Map });
|
|
1181
|
+
}
|
|
1182
|
+
return createMultipart(key, uploadId);
|
|
1169
1183
|
}
|
|
1170
1184
|
};
|
|
1185
|
+
function createMultipart(key, uploadId) {
|
|
1186
|
+
const requireEntry = () => {
|
|
1187
|
+
const entry = uploads.get(uploadId);
|
|
1188
|
+
if (!entry) {
|
|
1189
|
+
throw new Error(`Mock R2 multipart upload "${uploadId}" for key "${key}" is not active (it was aborted or completed).`);
|
|
1190
|
+
}
|
|
1191
|
+
return entry;
|
|
1192
|
+
};
|
|
1193
|
+
return {
|
|
1194
|
+
key,
|
|
1195
|
+
uploadId,
|
|
1196
|
+
async uploadPart(partNumber, value, _options) {
|
|
1197
|
+
const entry = requireEntry();
|
|
1198
|
+
const str = await coerceToString(value);
|
|
1199
|
+
entry.parts.set(partNumber, str);
|
|
1200
|
+
return { partNumber, etag: `"${key}-part-${partNumber}-etag"` };
|
|
1201
|
+
},
|
|
1202
|
+
async abort() {
|
|
1203
|
+
uploads.delete(uploadId);
|
|
1204
|
+
},
|
|
1205
|
+
async complete(uploadedParts) {
|
|
1206
|
+
const entry = requireEntry();
|
|
1207
|
+
const ordered = [...uploadedParts].sort((a, b) => a.partNumber - b.partNumber);
|
|
1208
|
+
const content = ordered.map((part) => {
|
|
1209
|
+
const chunk = entry.parts.get(part.partNumber);
|
|
1210
|
+
if (chunk === undefined) {
|
|
1211
|
+
throw new Error(`Mock R2 multipart complete() references part ${part.partNumber} that was never uploaded for upload "${uploadId}".`);
|
|
1212
|
+
}
|
|
1213
|
+
return chunk;
|
|
1214
|
+
}).join("");
|
|
1215
|
+
const metadata = entry.options?.customMetadata;
|
|
1216
|
+
store.set(key, { content, metadata });
|
|
1217
|
+
uploads.delete(uploadId);
|
|
1218
|
+
return createR2Object(key, content, metadata);
|
|
1219
|
+
}
|
|
1220
|
+
};
|
|
1221
|
+
}
|
|
1171
1222
|
}
|
|
1172
1223
|
// src/test/utilities/queue.ts
|
|
1173
1224
|
function createMockQueue() {
|
|
@@ -1234,25 +1285,8 @@ function createMockSecretsStoreSecret(value) {
|
|
|
1234
1285
|
}
|
|
1235
1286
|
};
|
|
1236
1287
|
}
|
|
1237
|
-
function defaultPortForDatabaseUrl(url) {
|
|
1238
|
-
if (url.port) {
|
|
1239
|
-
return Number(url.port);
|
|
1240
|
-
}
|
|
1241
|
-
return url.protocol === "mysql:" ? 3306 : 5432;
|
|
1242
|
-
}
|
|
1243
1288
|
function createMockHyperdrive(connectionString) {
|
|
1244
|
-
|
|
1245
|
-
return {
|
|
1246
|
-
connectionString,
|
|
1247
|
-
host: url.hostname,
|
|
1248
|
-
port: defaultPortForDatabaseUrl(url),
|
|
1249
|
-
user: decodeURIComponent(url.username),
|
|
1250
|
-
password: decodeURIComponent(url.password),
|
|
1251
|
-
database: decodeURIComponent(url.pathname.replace(/^\//, "")),
|
|
1252
|
-
connect() {
|
|
1253
|
-
throw new Error("Mock Hyperdrive connect() is not implemented. Use connectionString with your database client, or run a Miniflare-backed test for socket behavior.");
|
|
1254
|
-
}
|
|
1255
|
-
};
|
|
1289
|
+
return createLocalHyperdrive(connectionString);
|
|
1256
1290
|
}
|
|
1257
1291
|
function createDefaultWorkerStub() {
|
|
1258
1292
|
return {
|
|
@@ -1260,7 +1294,7 @@ function createDefaultWorkerStub() {
|
|
|
1260
1294
|
throw new Error("Mock WorkerLoader stub has no entrypoint. Pass createMockWorkerLoader({ stub }) for behavior.");
|
|
1261
1295
|
},
|
|
1262
1296
|
getDurableObjectClass() {
|
|
1263
|
-
throw new Error("Mock WorkerLoader stub
|
|
1297
|
+
throw new Error("Mock WorkerLoader stub cannot materialise a Durable Object class. " + "getDurableObjectClass() returns an opaque facet-spawning reference that workerd " + "only exposes inside the runtime. Pass createMockWorkerLoader({ stub }) to inject a stub, " + "or use createTestContext() (a real Miniflare worker) for Durable Object behavior.");
|
|
1264
1298
|
}
|
|
1265
1299
|
};
|
|
1266
1300
|
}
|
|
@@ -13,6 +13,9 @@ export declare function createMockVersionMetadata(metadata?: Partial<WorkerVersi
|
|
|
13
13
|
export declare function createMockSecretsStoreSecret(value: string): SecretsStoreSecret;
|
|
14
14
|
/**
|
|
15
15
|
* Creates a Hyperdrive binding around a local database connection string.
|
|
16
|
+
*
|
|
17
|
+
* Connection fields are usable with any Node database client; the raw socket
|
|
18
|
+
* `connect()` is a documented limitation that throws a clear, actionable error.
|
|
16
19
|
*/
|
|
17
20
|
export declare function createMockHyperdrive(connectionString: string): Hyperdrive;
|
|
18
21
|
export interface MockWorkerLoaderOptions {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../../src/test/utilities/platform.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../../src/test/utilities/platform.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,oBAAoB;IACpC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,CAAA;CAChB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,oBAAyB,GAAG,SAAS,CAkBjF;AAMD,wBAAgB,yBAAyB,CACxC,QAAQ,GAAE,OAAO,CAAC,qBAAqB,CAAM,GAC3C,qBAAqB,CAMvB;AAMD;;GAEG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB,CAM9E;AAMD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,gBAAgB,EAAE,MAAM,GAAG,UAAU,CAEzE;AAMD,MAAM,WAAW,uBAAuB;IACvC,IAAI,CAAC,EAAE,UAAU,CAAA;CACjB;AAuBD;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,uBAA4B,GAAG,YAAY,CAc1F;AAMD,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,GAAG,GAAG,CAAA;AAEnD,MAAM,MAAM,kBAAkB,GAAG,CAChC,KAAK,EAAE,cAAc,EACrB,IAAI,CAAC,EAAE,WAAW,KACd,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;AAQjC;;GAEG;AACH,wBAAgB,yBAAyB,CACxC,OAAO,GAAE,kBAAkD,GACzD,OAAO,CAMT;AAMD,MAAM,WAAW,4BAA4B;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,CAAA;CACtD;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAC1C,OAAO,GAAE,4BAAiC,GACxC,iBAAiB,CAWnB"}
|
|
@@ -1,12 +1,2 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Creates a mock R2Bucket for testing
|
|
3
|
-
*
|
|
4
|
-
* @example
|
|
5
|
-
* ```ts
|
|
6
|
-
* const r2 = createMockR2()
|
|
7
|
-
* await r2.put('file.txt', 'content')
|
|
8
|
-
* const obj = await r2.get('file.txt')
|
|
9
|
-
* ```
|
|
10
|
-
*/
|
|
11
1
|
export declare function createMockR2(): R2Bucket;
|
|
12
2
|
//# sourceMappingURL=r2.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"r2.d.ts","sourceRoot":"","sources":["../../../src/test/utilities/r2.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"r2.d.ts","sourceRoot":"","sources":["../../../src/test/utilities/r2.ts"],"names":[],"mappings":"AAqDA,wBAAgB,YAAY,IAAI,QAAQ,CA6KvC"}
|
package/package.json
CHANGED