@syncular/server-cloudflare 0.0.1 → 0.0.2-127

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,24 @@
1
+ # @syncular/server-cloudflare
2
+
3
+ Cloudflare Workers and Durable Objects adapters for running Syncular on the edge, plus Cloudflare R2 blob storage helpers.
4
+
5
+ This package is intentionally dialect-agnostic. You pair it with a database dialect (e.g. D1/SQLite or Neon/Postgres) and the matching Syncular server dialect.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install @syncular/server-cloudflare
11
+ ```
12
+
13
+ ## Documentation
14
+
15
+ - Cloudflare adapter: https://syncular.dev/docs/server/cloudflare-adapter
16
+ - Dialects: https://syncular.dev/docs/server/dialects
17
+ - Blob storage: https://syncular.dev/docs/build/blob-storage
18
+
19
+ ## Links
20
+
21
+ - GitHub: https://github.com/syncular/syncular
22
+ - Issues: https://github.com/syncular/syncular/issues
23
+
24
+ > Status: Alpha. APIs and storage layouts may change between releases.
@@ -58,6 +58,7 @@ export declare abstract class SyncDurableObject<E extends object = Record<string
58
58
  Bindings: E;
59
59
  }>, env: E, upgradeWebSocket: UpgradeWebSocket<WebSocket>): void | Promise<void>;
60
60
  private getApp;
61
+ private closeUntrackedSockets;
61
62
  /** Handle incoming HTTP requests (and WebSocket upgrades). */
62
63
  fetch(request: Request): Promise<Response>;
63
64
  /** Dispatch incoming WebSocket messages to Hono event handlers. */
@@ -1 +1 @@
1
- {"version":3,"file":"durable-object.d.ts","sourceRoot":"","sources":["../src/durable-object.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,gBAAgB,EAAY,MAAM,SAAS,CAAC;AAgE1D;;;;GAIG;AACH,8BAAsB,iBAAiB,CACrC,CAAC,SAAS,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAE1C,SAAS,CAAC,GAAG,EAAE,kBAAkB,CAAC;IAClC,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC;IAEjB,OAAO,CAAC,GAAG,CAAsC;IACjD,OAAO,CAAC,WAAW,CAA8B;IACjD,OAAO,CAAC,kBAAkB,CAA8B;IAExD,YAAY,GAAG,EAAE,kBAAkB,EAAE,GAAG,EAAE,CAAC,EAI1C;IAED;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CACZ,GAAG,EAAE,IAAI,CAAC;QAAE,QAAQ,EAAE,CAAC,CAAA;KAAE,CAAC,EAC1B,GAAG,EAAE,CAAC,EACN,gBAAgB,EAAE,gBAAgB,CAAC,SAAS,CAAC,GAC5C,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;YAEV,MAAM;IAcpB,8DAA8D;IACxD,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAG/C;IAED,mEAAmE;IAC7D,gBAAgB,CACpB,EAAE,EAAE,SAAS,EACb,OAAO,EAAE,MAAM,GAAG,WAAW,GAC5B,OAAO,CAAC,IAAI,CAAC,CAOf;IAED,8DAA8D;IACxD,cAAc,CAClB,EAAE,EAAE,SAAS,EACb,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,OAAO,GACjB,OAAO,CAAC,IAAI,CAAC,CAQf;IAED,8DAA8D;IACxD,cAAc,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAOlE;CACF;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,MAAM,EACrD,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC,EAC7B,OAAO,CAAC,EAAE;IACR;;;OAGG;IACH,SAAS,CAAC,EAAE,CACV,EAAE,EAAE,sBAAsB,EAC1B,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,CAAC,KACH,eAAe,CAAC;CACtB,GACA,eAAe,CAAC,CAAC,CAAC,CAiBpB"}
1
+ {"version":3,"file":"durable-object.d.ts","sourceRoot":"","sources":["../src/durable-object.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,gBAAgB,EAAY,MAAM,SAAS,CAAC;AA4E1D;;;;GAIG;AACH,8BAAsB,iBAAiB,CACrC,CAAC,SAAS,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAE1C,SAAS,CAAC,GAAG,EAAE,kBAAkB,CAAC;IAClC,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC;IAEjB,OAAO,CAAC,GAAG,CAAsC;IACjD,OAAO,CAAC,WAAW,CAA8B;IACjD,OAAO,CAAC,kBAAkB,CAA8B;IAExD,YAAY,GAAG,EAAE,kBAAkB,EAAE,GAAG,EAAE,CAAC,EAK1C;IAED;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CACZ,GAAG,EAAE,IAAI,CAAC;QAAE,QAAQ,EAAE,CAAC,CAAA;KAAE,CAAC,EAC1B,GAAG,EAAE,CAAC,EACN,gBAAgB,EAAE,gBAAgB,CAAC,SAAS,CAAC,GAC5C,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;YAEV,MAAM;IAcpB,OAAO,CAAC,qBAAqB;IAQ7B,8DAA8D;IACxD,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAG/C;IAED,mEAAmE;IAC7D,gBAAgB,CACpB,EAAE,EAAE,SAAS,EACb,OAAO,EAAE,MAAM,GAAG,WAAW,GAC5B,OAAO,CAAC,IAAI,CAAC,CAUf;IAED,8DAA8D;IACxD,cAAc,CAClB,EAAE,EAAE,SAAS,EACb,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,OAAO,GACjB,OAAO,CAAC,IAAI,CAAC,CAWf;IAED,8DAA8D;IACxD,cAAc,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAUlE;CACF;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,MAAM,EACrD,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC,EAC7B,OAAO,CAAC,EAAE;IACR;;;OAGG;IACH,SAAS,CAAC,EAAE,CACV,EAAE,EAAE,sBAAsB,EAC1B,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,CAAC,KACH,eAAe,CAAC;CACtB,GACA,eAAe,CAAC,CAAC,CAAC,CAiBpB"}
@@ -36,11 +36,21 @@
36
36
  */
37
37
  import { Hono } from 'hono';
38
38
  import { defineWebSocketHelper, WSContext } from 'hono/ws';
39
+ const STALE_SOCKET_CLOSE_CODE = 1012;
40
+ const STALE_SOCKET_CLOSE_REASON = 'WebSocket session expired; reconnect required';
39
41
  /**
40
42
  * WeakMap from server-side WebSocket → tag with event handlers.
41
43
  * Populated on upgrade, read in webSocketMessage/webSocketClose.
42
44
  */
43
45
  const socketTags = new WeakMap();
46
+ function closeStaleSocket(ws) {
47
+ try {
48
+ ws.close(STALE_SOCKET_CLOSE_CODE, STALE_SOCKET_CLOSE_REASON);
49
+ }
50
+ catch {
51
+ // ignore
52
+ }
53
+ }
44
54
  function createWSContext(ws) {
45
55
  return new WSContext({
46
56
  send(data) {
@@ -94,6 +104,7 @@ export class SyncDurableObject {
94
104
  this.ctx = ctx;
95
105
  this.env = env;
96
106
  this.doUpgradeWebSocket = createDOUpgradeWebSocket(ctx);
107
+ this.closeUntrackedSockets();
97
108
  }
98
109
  async getApp() {
99
110
  if (this.app)
@@ -107,6 +118,14 @@ export class SyncDurableObject {
107
118
  await this.initPromise;
108
119
  return this.app;
109
120
  }
121
+ closeUntrackedSockets() {
122
+ const sockets = this.ctx.getWebSockets();
123
+ for (const ws of sockets) {
124
+ if (socketTags.has(ws))
125
+ continue;
126
+ closeStaleSocket(ws);
127
+ }
128
+ }
110
129
  /** Handle incoming HTTP requests (and WebSocket upgrades). */
111
130
  async fetch(request) {
112
131
  const app = await this.getApp();
@@ -115,8 +134,10 @@ export class SyncDurableObject {
115
134
  /** Dispatch incoming WebSocket messages to Hono event handlers. */
116
135
  async webSocketMessage(ws, message) {
117
136
  const tag = socketTags.get(ws);
118
- if (!tag?.events.onMessage)
137
+ if (!tag?.events.onMessage) {
138
+ closeStaleSocket(ws);
119
139
  return;
140
+ }
120
141
  const wsCtx = createWSContext(ws);
121
142
  const evt = new MessageEvent('message', { data: message });
122
143
  tag.events.onMessage(evt, wsCtx);
@@ -124,8 +145,10 @@ export class SyncDurableObject {
124
145
  /** Dispatch WebSocket close events to Hono event handlers. */
125
146
  async webSocketClose(ws, code, reason, _wasClean) {
126
147
  const tag = socketTags.get(ws);
127
- if (!tag?.events.onClose)
148
+ if (!tag?.events.onClose) {
149
+ socketTags.delete(ws);
128
150
  return;
151
+ }
129
152
  const wsCtx = createWSContext(ws);
130
153
  const evt = new CloseEvent('close', { code, reason });
131
154
  tag.events.onClose(evt, wsCtx);
@@ -134,8 +157,10 @@ export class SyncDurableObject {
134
157
  /** Dispatch WebSocket error events to Hono event handlers. */
135
158
  async webSocketError(ws, _error) {
136
159
  const tag = socketTags.get(ws);
137
- if (!tag?.events.onError)
160
+ if (!tag?.events.onError) {
161
+ closeStaleSocket(ws);
138
162
  return;
163
+ }
139
164
  const wsCtx = createWSContext(ws);
140
165
  const evt = new Event('error');
141
166
  tag.events.onError(evt, wsCtx);
@@ -1 +1 @@
1
- {"version":3,"file":"durable-object.js","sourceRoot":"","sources":["../src/durable-object.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"durable-object.js","sourceRoot":"","sources":["../src/durable-object.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -12,7 +12,7 @@
12
12
  * - D1 + SQLite: `@syncular/dialect-d1` + `@syncular/server-dialect-sqlite`
13
13
  * - Neon + Postgres: `@syncular/dialect-neon` + `@syncular/server-dialect-postgres`
14
14
  */
15
- export * from './durable-object';
16
- export * from './r2';
17
- export * from './worker';
15
+ export * from './durable-object.js';
16
+ export * from './r2.js';
17
+ export * from './worker.js';
18
18
  //# sourceMappingURL=index.js.map
package/dist/r2.d.ts CHANGED
@@ -73,10 +73,18 @@ export interface BlobStorageAdapter {
73
73
  * Store blob data directly (for adapters that support direct storage).
74
74
  */
75
75
  put?(hash: string, data: Uint8Array, metadata?: Record<string, unknown>): Promise<void>;
76
+ /**
77
+ * Store blob data directly from a stream.
78
+ */
79
+ putStream?(hash: string, stream: ReadableStream<Uint8Array>, metadata?: Record<string, unknown>): Promise<void>;
76
80
  /**
77
81
  * Get blob data directly (for adapters that support direct retrieval).
78
82
  */
79
83
  get?(hash: string): Promise<Uint8Array | null>;
84
+ /**
85
+ * Get blob data directly as a stream.
86
+ */
87
+ getStream?(hash: string): Promise<ReadableStream<Uint8Array> | null>;
80
88
  }
81
89
  /**
82
90
  * Token signer interface for creating/verifying upload/download tokens.
package/dist/r2.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"r2.d.ts","sourceRoot":"","sources":["../src/r2.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"r2.d.ts","sourceRoot":"","sources":["../src/r2.ts"],"names":[],"mappings":"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"}
package/dist/r2.js CHANGED
@@ -75,6 +75,105 @@ export function createR2BlobStorageAdapter(options) {
75
75
  const hex = hash.startsWith('sha256:') ? hash.slice(7) : hash;
76
76
  return `${keyPrefix}${hex}`;
77
77
  }
78
+ function resolveMimeType(metadata) {
79
+ return typeof metadata?.mimeType === 'string'
80
+ ? metadata.mimeType
81
+ : 'application/octet-stream';
82
+ }
83
+ function resolveChecksum(hash, metadata) {
84
+ if (metadata?.disableChecksum === true) {
85
+ return undefined;
86
+ }
87
+ const explicitChecksum = metadata?.checksumSha256;
88
+ if (typeof explicitChecksum === 'string' &&
89
+ /^[0-9a-f]{64}$/i.test(explicitChecksum)) {
90
+ return explicitChecksum.toLowerCase();
91
+ }
92
+ return hash.startsWith('sha256:') ? hash.slice(7) : undefined;
93
+ }
94
+ function resolveContentLength(metadata) {
95
+ const candidates = [
96
+ metadata?.contentLength,
97
+ metadata?.byteLength,
98
+ metadata?.size,
99
+ ];
100
+ for (const candidate of candidates) {
101
+ if (typeof candidate !== 'number')
102
+ continue;
103
+ if (!Number.isFinite(candidate) || candidate < 0)
104
+ continue;
105
+ return candidate;
106
+ }
107
+ return undefined;
108
+ }
109
+ async function streamToBytes(stream) {
110
+ const reader = stream.getReader();
111
+ try {
112
+ const chunks = [];
113
+ let total = 0;
114
+ while (true) {
115
+ const { done, value } = await reader.read();
116
+ if (done)
117
+ break;
118
+ if (!value)
119
+ continue;
120
+ chunks.push(value);
121
+ total += value.length;
122
+ }
123
+ const output = new Uint8Array(total);
124
+ let offset = 0;
125
+ for (const chunk of chunks) {
126
+ output.set(chunk, offset);
127
+ offset += chunk.length;
128
+ }
129
+ return output;
130
+ }
131
+ finally {
132
+ reader.releaseLock();
133
+ }
134
+ }
135
+ async function putStreamInternal(hash, stream, metadata) {
136
+ const key = getKey(hash);
137
+ const mimeType = resolveMimeType(metadata);
138
+ const checksum = resolveChecksum(hash, metadata);
139
+ const contentLength = resolveContentLength(metadata);
140
+ if (typeof contentLength === 'number' && contentLength >= 0) {
141
+ if (typeof FixedLengthStream !== 'undefined') {
142
+ const fixedLength = new FixedLengthStream(contentLength);
143
+ await Promise.all([
144
+ stream.pipeTo(fixedLength.writable),
145
+ bucket.put(key, fixedLength.readable, {
146
+ httpMetadata: { contentType: mimeType },
147
+ sha256: checksum,
148
+ }),
149
+ ]);
150
+ return;
151
+ }
152
+ const bufferedBody = await streamToBytes(stream);
153
+ if (bufferedBody.byteLength !== contentLength) {
154
+ throw new Error(`Blob content length mismatch: expected ${contentLength}, got ${bufferedBody.byteLength}`);
155
+ }
156
+ await bucket.put(key, bufferedBody, {
157
+ httpMetadata: { contentType: mimeType },
158
+ sha256: checksum,
159
+ });
160
+ return;
161
+ }
162
+ const bufferedBody = await streamToBytes(stream);
163
+ await bucket.put(key, bufferedBody, {
164
+ httpMetadata: {
165
+ contentType: mimeType,
166
+ },
167
+ sha256: checksum,
168
+ });
169
+ }
170
+ async function getStreamInternal(hash) {
171
+ const key = getKey(hash);
172
+ const object = await bucket.get(key);
173
+ if (!object)
174
+ return null;
175
+ return object.body;
176
+ }
78
177
  return {
79
178
  name: 'r2',
80
179
  async signUpload(opts) {
@@ -117,22 +216,49 @@ export function createR2BlobStorageAdapter(options) {
117
216
  },
118
217
  async put(hash, data, metadata) {
119
218
  const key = getKey(hash);
120
- const mimeType = typeof metadata?.mimeType === 'string'
121
- ? metadata.mimeType
122
- : 'application/octet-stream';
219
+ const mimeType = resolveMimeType(metadata);
220
+ const checksum = resolveChecksum(hash, metadata);
123
221
  await bucket.put(key, data, {
124
222
  httpMetadata: {
125
223
  contentType: mimeType,
126
224
  },
127
- sha256: hash.startsWith('sha256:') ? hash.slice(7) : undefined,
225
+ sha256: checksum,
128
226
  });
129
227
  },
228
+ async putStream(hash, stream, metadata) {
229
+ await putStreamInternal(hash, stream, metadata);
230
+ },
130
231
  async get(hash) {
131
- const key = getKey(hash);
132
- const object = await bucket.get(key);
133
- if (!object)
232
+ const stream = await getStreamInternal(hash);
233
+ if (!stream)
134
234
  return null;
135
- return new Uint8Array(await object.arrayBuffer());
235
+ const reader = stream.getReader();
236
+ try {
237
+ const chunks = [];
238
+ let total = 0;
239
+ while (true) {
240
+ const { done, value } = await reader.read();
241
+ if (done)
242
+ break;
243
+ if (!value)
244
+ continue;
245
+ chunks.push(value);
246
+ total += value.length;
247
+ }
248
+ const out = new Uint8Array(total);
249
+ let offset = 0;
250
+ for (const chunk of chunks) {
251
+ out.set(chunk, offset);
252
+ offset += chunk.length;
253
+ }
254
+ return out;
255
+ }
256
+ finally {
257
+ reader.releaseLock();
258
+ }
259
+ },
260
+ async getStream(hash) {
261
+ return getStreamInternal(hash);
136
262
  },
137
263
  };
138
264
  }
package/dist/r2.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"r2.js","sourceRoot":"","sources":["../src/r2.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"r2.js","sourceRoot":"","sources":["../src/r2.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAqIH;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAc,EAAmB;IACrE,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAElC,KAAK,UAAU,QAAQ,CAAC,IAAY,EAAmB;QACrD,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CACvC,KAAK,EACL,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EACtB,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,EACjC,KAAK,EACL,CAAC,MAAM,CAAC,CACT,CAAC;QACF,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CACxC,MAAM,EACN,GAAG,EACH,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CACrB,CAAC;QACF,OAAO,WAAW,CAAC,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;IAAA,CAC/C;IAED,OAAO;QACL,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE;YAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YACrC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;YAC3B,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,CAAC;YACpC,OAAO,GAAG,OAAO,IAAI,GAAG,EAAE,CAAC;QAAA,CAC5B;QAED,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE;YAClB,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACxC,IAAI,CAAC,OAAO,IAAI,CAAC,GAAG;gBAAE,OAAO,IAAI,CAAC;YAElC,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC5C,IAAI,GAAG,KAAK,WAAW;gBAAE,OAAO,IAAI,CAAC;YAErC,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAIpC,CAAC;gBAEF,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS;oBAAE,OAAO,IAAI,CAAC;gBAE7C,OAAO,IAAI,CAAC;YACd,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;QAAA,CACF;KACF,CAAC;AAAA,CACH;AAED,SAAS,WAAW,CAAC,MAAkB,EAAU;IAC/C,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;SACtB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;SAC3C,IAAI,CAAC,EAAE,CAAC,CAAC;AAAA,CACb;AAaD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,0BAA0B,CACxC,OAAoC,EAChB;IACpB,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;IAEjE,6CAA6C;IAC7C,MAAM,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAErD,SAAS,MAAM,CAAC,IAAY,EAAU;QACpC,6CAA6C;QAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC9D,OAAO,GAAG,SAAS,GAAG,GAAG,EAAE,CAAC;IAAA,CAC7B;IAED,SAAS,eAAe,CAAC,QAAkC,EAAU;QACnE,OAAO,OAAO,QAAQ,EAAE,QAAQ,KAAK,QAAQ;YAC3C,CAAC,CAAC,QAAQ,CAAC,QAAQ;YACnB,CAAC,CAAC,0BAA0B,CAAC;IAAA,CAChC;IAED,SAAS,eAAe,CACtB,IAAY,EACZ,QAAkC,EACd;QACpB,IAAI,QAAQ,EAAE,eAAe,KAAK,IAAI,EAAE,CAAC;YACvC,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,gBAAgB,GAAG,QAAQ,EAAE,cAAc,CAAC;QAClD,IACE,OAAO,gBAAgB,KAAK,QAAQ;YACpC,iBAAiB,CAAC,IAAI,CAAC,gBAAgB,CAAC,EACxC,CAAC;YACD,OAAO,gBAAgB,CAAC,WAAW,EAAE,CAAC;QACxC,CAAC;QAED,OAAO,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAAA,CAC/D;IAED,SAAS,oBAAoB,CAC3B,QAAkC,EACd;QACpB,MAAM,UAAU,GAAG;YACjB,QAAQ,EAAE,aAAa;YACvB,QAAQ,EAAE,UAAU;YACpB,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,IAAI,OAAO,SAAS,KAAK,QAAQ;gBAAE,SAAS;YAC5C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,GAAG,CAAC;gBAAE,SAAS;YAC3D,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,SAAS,CAAC;IAAA,CAClB;IAED,KAAK,UAAU,aAAa,CAC1B,MAAkC,EACb;QACrB,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;QAClC,IAAI,CAAC;YACH,MAAM,MAAM,GAAiB,EAAE,CAAC;YAChC,IAAI,KAAK,GAAG,CAAC,CAAC;YACd,OAAO,IAAI,EAAE,CAAC;gBACZ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;gBAC5C,IAAI,IAAI;oBAAE,MAAM;gBAChB,IAAI,CAAC,KAAK;oBAAE,SAAS;gBACrB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACnB,KAAK,IAAI,KAAK,CAAC,MAAM,CAAC;YACxB,CAAC;YAED,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;YACrC,IAAI,MAAM,GAAG,CAAC,CAAC;YACf,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC;YACzB,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,CAAC;IAAA,CACF;IAED,KAAK,UAAU,iBAAiB,CAC9B,IAAY,EACZ,MAAkC,EAClC,QAAkC,EACnB;QACf,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,QAAQ,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;QAC3C,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACjD,MAAM,aAAa,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;QAErD,IAAI,OAAO,aAAa,KAAK,QAAQ,IAAI,aAAa,IAAI,CAAC,EAAE,CAAC;YAC5D,IAAI,OAAO,iBAAiB,KAAK,WAAW,EAAE,CAAC;gBAC7C,MAAM,WAAW,GAAG,IAAI,iBAAiB,CAAC,aAAa,CAAC,CAAC;gBACzD,MAAM,OAAO,CAAC,GAAG,CAAC;oBAChB,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC;oBACnC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,WAAW,CAAC,QAAQ,EAAE;wBACpC,YAAY,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE;wBACvC,MAAM,EAAE,QAAQ;qBACjB,CAAC;iBACH,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,MAAM,YAAY,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC;YACjD,IAAI,YAAY,CAAC,UAAU,KAAK,aAAa,EAAE,CAAC;gBAC9C,MAAM,IAAI,KAAK,CACb,0CAA0C,aAAa,SAAS,YAAY,CAAC,UAAU,EAAE,CAC1F,CAAC;YACJ,CAAC;YACD,MAAM,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,YAAY,EAAE;gBAClC,YAAY,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE;gBACvC,MAAM,EAAE,QAAQ;aACjB,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,MAAM,YAAY,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC;QACjD,MAAM,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,YAAY,EAAE;YAClC,YAAY,EAAE;gBACZ,WAAW,EAAE,QAAQ;aACtB;YACD,MAAM,EAAE,QAAQ;SACjB,CAAC,CAAC;IAAA,CACJ;IAED,KAAK,UAAU,iBAAiB,CAC9B,IAAY,EACgC;QAC5C,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QACzB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QACzB,OAAO,MAAM,CAAC,IAAyC,CAAC;IAAA,CACzD;IAED,OAAO;QACL,IAAI,EAAE,IAAI;QAEV,KAAK,CAAC,UAAU,CAAC,IAA2B,EAA6B;YACvE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;YACrD,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,IAAI,CAClC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,EAChD,IAAI,CAAC,SAAS,CACf,CAAC;YAEF,8CAA8C;YAC9C,MAAM,GAAG,GAAG,GAAG,iBAAiB,UAAU,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;YAEpH,OAAO;gBACL,GAAG;gBACH,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE;oBACP,cAAc,EAAE,IAAI,CAAC,QAAQ;oBAC7B,gBAAgB,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;iBACpC;aACF,CAAC;QAAA,CACH;QAED,KAAK,CAAC,YAAY,CAAC,IAA6B,EAAmB;YACjE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;YACrD,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,IAAI,CAClC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,EAClD,IAAI,CAAC,SAAS,CACf,CAAC;YAEF,OAAO,GAAG,iBAAiB,UAAU,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;QAAA,CAClH;QAED,KAAK,CAAC,MAAM,CAAC,IAAY,EAAoB;YAC3C,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YACzB,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACpC,OAAO,IAAI,KAAK,IAAI,CAAC;QAAA,CACtB;QAED,KAAK,CAAC,MAAM,CAAC,IAAY,EAAiB;YACxC,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YACzB,MAAM,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAAA,CAC1B;QAED,KAAK,CAAC,WAAW,CACf,IAAY,EACyC;YACrD,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YACzB,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACpC,IAAI,CAAC,IAAI;gBAAE,OAAO,IAAI,CAAC;YAEvB,OAAO;gBACL,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,QAAQ,EAAE,IAAI,CAAC,YAAY,EAAE,WAAW;aACzC,CAAC;QAAA,CACH;QAED,KAAK,CAAC,GAAG,CACP,IAAY,EACZ,IAAgB,EAChB,QAAkC,EACnB;YACf,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YACzB,MAAM,QAAQ,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;YAC3C,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YACjD,MAAM,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE;gBAC1B,YAAY,EAAE;oBACZ,WAAW,EAAE,QAAQ;iBACtB;gBACD,MAAM,EAAE,QAAQ;aACjB,CAAC,CAAC;QAAA,CACJ;QAED,KAAK,CAAC,SAAS,CACb,IAAY,EACZ,MAAkC,EAClC,QAAkC,EACnB;YACf,MAAM,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;QAAA,CACjD;QAED,KAAK,CAAC,GAAG,CAAC,IAAY,EAA8B;YAClD,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAC7C,IAAI,CAAC,MAAM;gBAAE,OAAO,IAAI,CAAC;YAEzB,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;YAClC,IAAI,CAAC;gBACH,MAAM,MAAM,GAAiB,EAAE,CAAC;gBAChC,IAAI,KAAK,GAAG,CAAC,CAAC;gBACd,OAAO,IAAI,EAAE,CAAC;oBACZ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;oBAC5C,IAAI,IAAI;wBAAE,MAAM;oBAChB,IAAI,CAAC,KAAK;wBAAE,SAAS;oBACrB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBACnB,KAAK,IAAI,KAAK,CAAC,MAAM,CAAC;gBACxB,CAAC;gBACD,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;gBAClC,IAAI,MAAM,GAAG,CAAC,CAAC;gBACf,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;oBAC3B,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;oBACvB,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC;gBACzB,CAAC;gBACD,OAAO,GAAG,CAAC;YACb,CAAC;oBAAS,CAAC;gBACT,MAAM,CAAC,WAAW,EAAE,CAAC;YACvB,CAAC;QAAA,CACF;QAED,KAAK,CAAC,SAAS,CAAC,IAAY,EAA8C;YACxE,OAAO,iBAAiB,CAAC,IAAI,CAAC,CAAC;QAAA,CAChC;KACF,CAAC;AAAA,CACH"}
package/package.json CHANGED
@@ -1,6 +1,28 @@
1
1
  {
2
2
  "name": "@syncular/server-cloudflare",
3
- "version": "0.0.1",
3
+ "version": "0.0.2-127",
4
+ "description": "Cloudflare Workers adapter for the Syncular server",
5
+ "license": "MIT",
6
+ "author": "Benjamin Kniffler",
7
+ "homepage": "https://syncular.dev",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/syncular/syncular.git",
11
+ "directory": "packages/server-cloudflare"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/syncular/syncular/issues"
15
+ },
16
+ "keywords": [
17
+ "sync",
18
+ "offline-first",
19
+ "realtime",
20
+ "database",
21
+ "typescript",
22
+ "cloudflare",
23
+ "workers",
24
+ "edge"
25
+ ],
4
26
  "private": false,
5
27
  "publishConfig": {
6
28
  "access": "public"
@@ -38,14 +60,15 @@
38
60
  },
39
61
  "scripts": {
40
62
  "tsgo": "tsgo --noEmit",
41
- "build": "rm -rf dist && tsgo"
63
+ "build": "tsgo",
64
+ "release": "bunx syncular-publish"
42
65
  },
43
66
  "peerDependencies": {
44
67
  "hono": "^4.0.0"
45
68
  },
46
69
  "devDependencies": {
47
- "@cloudflare/workers-types": "^4.20260207.0",
48
- "@syncular/config": "workspace:*"
70
+ "@cloudflare/workers-types": "*",
71
+ "@syncular/config": "0.0.0"
49
72
  },
50
73
  "files": [
51
74
  "dist",
@@ -0,0 +1,65 @@
1
+ import { describe, expect, test } from 'bun:test';
2
+ import type { Hono } from 'hono';
3
+ import type { UpgradeWebSocket } from 'hono/ws';
4
+ import { SyncDurableObject } from './durable-object';
5
+
6
+ const staleSocketCloseCode = 1012;
7
+ const staleSocketCloseReason = 'WebSocket session expired; reconnect required';
8
+
9
+ class TestSyncDurableObject extends SyncDurableObject<Record<string, never>> {
10
+ async setup(
11
+ _app: Hono<{ Bindings: Record<string, never> }>,
12
+ _env: Record<string, never>,
13
+ _upgradeWebSocket: UpgradeWebSocket<WebSocket>
14
+ ): Promise<void> {}
15
+ }
16
+
17
+ function createSocketTracker(): {
18
+ socket: WebSocket;
19
+ closes: Array<{ code: number | undefined; reason: string | undefined }>;
20
+ } {
21
+ const closes: Array<{
22
+ code: number | undefined;
23
+ reason: string | undefined;
24
+ }> = [];
25
+ const socket = {
26
+ close(code?: number, reason?: string) {
27
+ closes.push({ code, reason });
28
+ },
29
+ } as WebSocket;
30
+ return { socket, closes };
31
+ }
32
+
33
+ function createState(sockets: WebSocket[]): DurableObjectState {
34
+ return {
35
+ acceptWebSocket() {},
36
+ getWebSockets() {
37
+ return sockets;
38
+ },
39
+ } as DurableObjectState;
40
+ }
41
+
42
+ describe('SyncDurableObject stale websocket handling', () => {
43
+ test('closes untracked sockets on construction (hibernation wake-up path)', () => {
44
+ const tracked = createSocketTracker();
45
+ const state = createState([tracked.socket]);
46
+
47
+ new TestSyncDurableObject(state, {});
48
+
49
+ expect(tracked.closes).toEqual([
50
+ { code: staleSocketCloseCode, reason: staleSocketCloseReason },
51
+ ]);
52
+ });
53
+
54
+ test('closes unknown sockets when receiving websocket messages', async () => {
55
+ const state = createState([]);
56
+ const durableObject = new TestSyncDurableObject(state, {});
57
+ const tracked = createSocketTracker();
58
+
59
+ await durableObject.webSocketMessage(tracked.socket, 'hello');
60
+
61
+ expect(tracked.closes).toEqual([
62
+ { code: staleSocketCloseCode, reason: staleSocketCloseReason },
63
+ ]);
64
+ });
65
+ });
@@ -47,12 +47,24 @@ interface WebSocketTag {
47
47
  events: WSEvents<WebSocket>;
48
48
  }
49
49
 
50
+ const STALE_SOCKET_CLOSE_CODE = 1012;
51
+ const STALE_SOCKET_CLOSE_REASON =
52
+ 'WebSocket session expired; reconnect required';
53
+
50
54
  /**
51
55
  * WeakMap from server-side WebSocket → tag with event handlers.
52
56
  * Populated on upgrade, read in webSocketMessage/webSocketClose.
53
57
  */
54
58
  const socketTags = new WeakMap<WebSocket, WebSocketTag>();
55
59
 
60
+ function closeStaleSocket(ws: WebSocket): void {
61
+ try {
62
+ ws.close(STALE_SOCKET_CLOSE_CODE, STALE_SOCKET_CLOSE_REASON);
63
+ } catch {
64
+ // ignore
65
+ }
66
+ }
67
+
56
68
  function createWSContext(ws: WebSocket): WSContext<WebSocket> {
57
69
  return new WSContext<WebSocket>({
58
70
  send(data) {
@@ -119,6 +131,7 @@ export abstract class SyncDurableObject<
119
131
  this.ctx = ctx;
120
132
  this.env = env;
121
133
  this.doUpgradeWebSocket = createDOUpgradeWebSocket(ctx);
134
+ this.closeUntrackedSockets();
122
135
  }
123
136
 
124
137
  /**
@@ -147,6 +160,14 @@ export abstract class SyncDurableObject<
147
160
  return this.app!;
148
161
  }
149
162
 
163
+ private closeUntrackedSockets(): void {
164
+ const sockets = this.ctx.getWebSockets();
165
+ for (const ws of sockets) {
166
+ if (socketTags.has(ws)) continue;
167
+ closeStaleSocket(ws);
168
+ }
169
+ }
170
+
150
171
  /** Handle incoming HTTP requests (and WebSocket upgrades). */
151
172
  async fetch(request: Request): Promise<Response> {
152
173
  const app = await this.getApp();
@@ -159,7 +180,10 @@ export abstract class SyncDurableObject<
159
180
  message: string | ArrayBuffer
160
181
  ): Promise<void> {
161
182
  const tag = socketTags.get(ws);
162
- if (!tag?.events.onMessage) return;
183
+ if (!tag?.events.onMessage) {
184
+ closeStaleSocket(ws);
185
+ return;
186
+ }
163
187
 
164
188
  const wsCtx = createWSContext(ws);
165
189
  const evt = new MessageEvent('message', { data: message });
@@ -174,7 +198,10 @@ export abstract class SyncDurableObject<
174
198
  _wasClean: boolean
175
199
  ): Promise<void> {
176
200
  const tag = socketTags.get(ws);
177
- if (!tag?.events.onClose) return;
201
+ if (!tag?.events.onClose) {
202
+ socketTags.delete(ws);
203
+ return;
204
+ }
178
205
 
179
206
  const wsCtx = createWSContext(ws);
180
207
  const evt = new CloseEvent('close', { code, reason });
@@ -185,7 +212,10 @@ export abstract class SyncDurableObject<
185
212
  /** Dispatch WebSocket error events to Hono event handlers. */
186
213
  async webSocketError(ws: WebSocket, _error: unknown): Promise<void> {
187
214
  const tag = socketTags.get(ws);
188
- if (!tag?.events.onError) return;
215
+ if (!tag?.events.onError) {
216
+ closeStaleSocket(ws);
217
+ return;
218
+ }
189
219
 
190
220
  const wsCtx = createWSContext(ws);
191
221
  const evt = new Event('error');
package/src/r2.test.ts ADDED
@@ -0,0 +1,120 @@
1
+ import { describe, expect, test } from 'bun:test';
2
+ import {
3
+ type BlobStorageAdapter,
4
+ type BlobTokenSigner,
5
+ createR2BlobStorageAdapter,
6
+ } from './r2';
7
+
8
+ function createBodyStream(
9
+ chunks: readonly Uint8Array[]
10
+ ): ReadableStream<Uint8Array> {
11
+ return new ReadableStream<Uint8Array>({
12
+ start(controller) {
13
+ for (const chunk of chunks) {
14
+ controller.enqueue(chunk);
15
+ }
16
+ controller.close();
17
+ },
18
+ });
19
+ }
20
+
21
+ async function consumeStream(
22
+ stream: ReadableStream<Uint8Array>
23
+ ): Promise<void> {
24
+ const reader = stream.getReader();
25
+ try {
26
+ while (true) {
27
+ const { done } = await reader.read();
28
+ if (done) break;
29
+ }
30
+ } finally {
31
+ reader.releaseLock();
32
+ }
33
+ }
34
+
35
+ function createTokenSigner(): BlobTokenSigner {
36
+ return {
37
+ async sign() {
38
+ return 'token';
39
+ },
40
+ async verify() {
41
+ return null;
42
+ },
43
+ };
44
+ }
45
+
46
+ function createAdapterWithCapturedPuts(
47
+ captured: Array<{ body: unknown; options: unknown }>
48
+ ): BlobStorageAdapter {
49
+ const bucket = {
50
+ async put(_key: string, body: unknown, options?: unknown) {
51
+ captured.push({ body, options });
52
+ if (body instanceof ReadableStream) {
53
+ await consumeStream(body as ReadableStream<Uint8Array>);
54
+ }
55
+ return {} as R2Object;
56
+ },
57
+ async get() {
58
+ return null;
59
+ },
60
+ async head() {
61
+ return null;
62
+ },
63
+ async delete() {},
64
+ } as unknown as R2Bucket;
65
+
66
+ return createR2BlobStorageAdapter({
67
+ bucket,
68
+ baseUrl: '/api/sync',
69
+ tokenSigner: createTokenSigner(),
70
+ });
71
+ }
72
+
73
+ describe('createR2BlobStorageAdapter.putStream', () => {
74
+ test('buffers unknown-length streams before upload', async () => {
75
+ const puts: Array<{ body: unknown; options: unknown }> = [];
76
+ const adapter = createAdapterWithCapturedPuts(puts);
77
+
78
+ await adapter.putStream?.(
79
+ 'sha256:abc123',
80
+ createBodyStream([new Uint8Array([1, 2]), new Uint8Array([3, 4])])
81
+ );
82
+
83
+ expect(puts).toHaveLength(1);
84
+ expect(puts[0]?.body).toBeInstanceOf(Uint8Array);
85
+ expect(Array.from(puts[0]?.body as Uint8Array)).toEqual([1, 2, 3, 4]);
86
+ });
87
+
88
+ test('uses fixed-length stream when byteLength is provided', async () => {
89
+ const puts: Array<{ body: unknown; options: unknown }> = [];
90
+ const adapter = createAdapterWithCapturedPuts(puts);
91
+
92
+ await adapter.putStream?.(
93
+ 'sha256:def456',
94
+ createBodyStream([new Uint8Array([9, 8, 7, 6])]),
95
+ { byteLength: 4 }
96
+ );
97
+
98
+ expect(puts).toHaveLength(1);
99
+ if (typeof FixedLengthStream !== 'undefined') {
100
+ expect(puts[0]?.body).toBeInstanceOf(ReadableStream);
101
+ } else {
102
+ expect(puts[0]?.body).toBeInstanceOf(Uint8Array);
103
+ }
104
+ });
105
+
106
+ test('omits checksum when disableChecksum metadata is set', async () => {
107
+ const puts: Array<{ body: unknown; options: unknown }> = [];
108
+ const adapter = createAdapterWithCapturedPuts(puts);
109
+
110
+ await adapter.putStream?.(
111
+ 'sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef',
112
+ createBodyStream([new Uint8Array([1, 2, 3])]),
113
+ { disableChecksum: true }
114
+ );
115
+
116
+ expect(puts).toHaveLength(1);
117
+ const options = puts[0]?.options as { sha256?: string };
118
+ expect(options.sha256).toBeUndefined();
119
+ });
120
+ });
package/src/r2.ts CHANGED
@@ -92,10 +92,24 @@ export interface BlobStorageAdapter {
92
92
  metadata?: Record<string, unknown>
93
93
  ): Promise<void>;
94
94
 
95
+ /**
96
+ * Store blob data directly from a stream.
97
+ */
98
+ putStream?(
99
+ hash: string,
100
+ stream: ReadableStream<Uint8Array>,
101
+ metadata?: Record<string, unknown>
102
+ ): Promise<void>;
103
+
95
104
  /**
96
105
  * Get blob data directly (for adapters that support direct retrieval).
97
106
  */
98
107
  get?(hash: string): Promise<Uint8Array | null>;
108
+
109
+ /**
110
+ * Get blob data directly as a stream.
111
+ */
112
+ getStream?(hash: string): Promise<ReadableStream<Uint8Array> | null>;
99
113
  }
100
114
 
101
115
  /**
@@ -228,6 +242,128 @@ export function createR2BlobStorageAdapter(
228
242
  return `${keyPrefix}${hex}`;
229
243
  }
230
244
 
245
+ function resolveMimeType(metadata?: Record<string, unknown>): string {
246
+ return typeof metadata?.mimeType === 'string'
247
+ ? metadata.mimeType
248
+ : 'application/octet-stream';
249
+ }
250
+
251
+ function resolveChecksum(
252
+ hash: string,
253
+ metadata?: Record<string, unknown>
254
+ ): string | undefined {
255
+ if (metadata?.disableChecksum === true) {
256
+ return undefined;
257
+ }
258
+
259
+ const explicitChecksum = metadata?.checksumSha256;
260
+ if (
261
+ typeof explicitChecksum === 'string' &&
262
+ /^[0-9a-f]{64}$/i.test(explicitChecksum)
263
+ ) {
264
+ return explicitChecksum.toLowerCase();
265
+ }
266
+
267
+ return hash.startsWith('sha256:') ? hash.slice(7) : undefined;
268
+ }
269
+
270
+ function resolveContentLength(
271
+ metadata?: Record<string, unknown>
272
+ ): number | undefined {
273
+ const candidates = [
274
+ metadata?.contentLength,
275
+ metadata?.byteLength,
276
+ metadata?.size,
277
+ ];
278
+ for (const candidate of candidates) {
279
+ if (typeof candidate !== 'number') continue;
280
+ if (!Number.isFinite(candidate) || candidate < 0) continue;
281
+ return candidate;
282
+ }
283
+ return undefined;
284
+ }
285
+
286
+ async function streamToBytes(
287
+ stream: ReadableStream<Uint8Array>
288
+ ): Promise<Uint8Array> {
289
+ const reader = stream.getReader();
290
+ try {
291
+ const chunks: Uint8Array[] = [];
292
+ let total = 0;
293
+ while (true) {
294
+ const { done, value } = await reader.read();
295
+ if (done) break;
296
+ if (!value) continue;
297
+ chunks.push(value);
298
+ total += value.length;
299
+ }
300
+
301
+ const output = new Uint8Array(total);
302
+ let offset = 0;
303
+ for (const chunk of chunks) {
304
+ output.set(chunk, offset);
305
+ offset += chunk.length;
306
+ }
307
+ return output;
308
+ } finally {
309
+ reader.releaseLock();
310
+ }
311
+ }
312
+
313
+ async function putStreamInternal(
314
+ hash: string,
315
+ stream: ReadableStream<Uint8Array>,
316
+ metadata?: Record<string, unknown>
317
+ ): Promise<void> {
318
+ const key = getKey(hash);
319
+ const mimeType = resolveMimeType(metadata);
320
+ const checksum = resolveChecksum(hash, metadata);
321
+ const contentLength = resolveContentLength(metadata);
322
+
323
+ if (typeof contentLength === 'number' && contentLength >= 0) {
324
+ if (typeof FixedLengthStream !== 'undefined') {
325
+ const fixedLength = new FixedLengthStream(contentLength);
326
+ await Promise.all([
327
+ stream.pipeTo(fixedLength.writable),
328
+ bucket.put(key, fixedLength.readable, {
329
+ httpMetadata: { contentType: mimeType },
330
+ sha256: checksum,
331
+ }),
332
+ ]);
333
+ return;
334
+ }
335
+
336
+ const bufferedBody = await streamToBytes(stream);
337
+ if (bufferedBody.byteLength !== contentLength) {
338
+ throw new Error(
339
+ `Blob content length mismatch: expected ${contentLength}, got ${bufferedBody.byteLength}`
340
+ );
341
+ }
342
+ await bucket.put(key, bufferedBody, {
343
+ httpMetadata: { contentType: mimeType },
344
+ sha256: checksum,
345
+ });
346
+ return;
347
+ }
348
+
349
+ const bufferedBody = await streamToBytes(stream);
350
+ await bucket.put(key, bufferedBody, {
351
+ httpMetadata: {
352
+ contentType: mimeType,
353
+ },
354
+ sha256: checksum,
355
+ });
356
+ }
357
+
358
+ async function getStreamInternal(
359
+ hash: string
360
+ ): Promise<ReadableStream<Uint8Array> | null> {
361
+ const key = getKey(hash);
362
+ const object = await bucket.get(key);
363
+ if (!object) return null;
364
+ return object.body as ReadableStream<Uint8Array> | null;
365
+ }
366
+
231
367
  return {
232
368
  name: 'r2',
233
369
 
@@ -291,25 +427,53 @@ export function createR2BlobStorageAdapter(
291
427
  metadata?: Record<string, unknown>
292
428
  ): Promise<void> {
293
429
  const key = getKey(hash);
294
- const mimeType =
295
- typeof metadata?.mimeType === 'string'
296
- ? metadata.mimeType
297
- : 'application/octet-stream';
298
-
430
+ const mimeType = resolveMimeType(metadata);
431
+ const checksum = resolveChecksum(hash, metadata);
299
432
  await bucket.put(key, data, {
300
433
  httpMetadata: {
301
434
  contentType: mimeType,
302
435
  },
303
- sha256: hash.startsWith('sha256:') ? hash.slice(7) : undefined,
436
+ sha256: checksum,
304
437
  });
305
438
  },
306
439
 
440
+ async putStream(
441
+ hash: string,
442
+ stream: ReadableStream<Uint8Array>,
443
+ metadata?: Record<string, unknown>
444
+ ): Promise<void> {
445
+ await putStreamInternal(hash, stream, metadata);
446
+ },
447
+
307
448
  async get(hash: string): Promise<Uint8Array | null> {
308
- const key = getKey(hash);
309
- const object = await bucket.get(key);
310
- if (!object) return null;
449
+ const stream = await getStreamInternal(hash);
450
+ if (!stream) return null;
451
+
452
+ const reader = stream.getReader();
453
+ try {
454
+ const chunks: Uint8Array[] = [];
455
+ let total = 0;
456
+ while (true) {
457
+ const { done, value } = await reader.read();
458
+ if (done) break;
459
+ if (!value) continue;
460
+ chunks.push(value);
461
+ total += value.length;
462
+ }
463
+ const out = new Uint8Array(total);
464
+ let offset = 0;
465
+ for (const chunk of chunks) {
466
+ out.set(chunk, offset);
467
+ offset += chunk.length;
468
+ }
469
+ return out;
470
+ } finally {
471
+ reader.releaseLock();
472
+ }
473
+ },
311
474
 
312
- return new Uint8Array(await object.arrayBuffer());
475
+ async getStream(hash: string): Promise<ReadableStream<Uint8Array> | null> {
476
+ return getStreamInternal(hash);
313
477
  },
314
478
  };
315
479
  }