Skip to content

Commit f4421de

Browse files
committed
feat: string offloading support
Strings longer than maxStringLength (default 32768) are offloaded to blob storage on upload, and resolved back to string on read. - New config option: maxStringLength - BlobManager handles _bt:'string' upload (UTF-8) and download (TextDecoder) - DexieCloudConfig extended with maxStringLength
1 parent cf3d7fc commit f4421de

File tree

4 files changed

+29
-6
lines changed

4 files changed

+29
-6
lines changed

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/blob.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,15 @@ function uint8ArrayToBase64(data: Uint8Array): string {
109109
return btoa(binary);
110110
}
111111

112+
/** Default max string length before offloading */
113+
export const DEFAULT_MAX_STRING_LENGTH = 32768;
114+
112115
export class BlobManager {
113116
constructor(
114117
private dbUrl: string,
115118
private http: HttpAdapter,
116-
private mode: BlobHandling = 'auto'
119+
private mode: BlobHandling = 'auto',
120+
private maxStringLength: number = DEFAULT_MAX_STRING_LENGTH
117121
) {}
118122

119123
/**
@@ -214,6 +218,13 @@ export class BlobManager {
214218
}
215219

216220
private async _walkForUpload(val: any, token: string): Promise<any> {
221+
// Check long strings
222+
if (typeof val === 'string' && val.length > this.maxStringLength && this.maxStringLength !== Infinity) {
223+
const bytes = new TextEncoder().encode(val);
224+
const ref = await this.upload(bytes, token, 'text/plain;charset=utf-8');
225+
return { _bt: 'string', ref, size: bytes.length } as BlobRef;
226+
}
227+
217228
if (isInlineBlob(val)) {
218229
const bytes = base64ToUint8Array(val.v);
219230
// Only offload to blob storage if the binary meets the size threshold.
@@ -249,6 +260,11 @@ export class BlobManager {
249260

250261
private async _walkForRead(val: any, token: string): Promise<any> {
251262
if (isBlobRef(val)) {
263+
// String type: download and decode UTF-8 back to string
264+
if (val._bt === 'string') {
265+
const { data } = await this.download(val.ref, token);
266+
return new TextDecoder().decode(data);
267+
}
252268
const { data, contentType } = await this.download(val.ref, token);
253269
return {
254270
_bt: val._bt,

src/client.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export class DexieCloudClient {
4343

4444
// Use dbUrl if provided, otherwise fall back to serviceUrl
4545
const dbUrl = fullConfig.dbUrl ?? fullConfig.serviceUrl;
46-
this.blobs = new BlobManager(dbUrl, this.http, fullConfig.blobHandling ?? 'auto');
46+
this.blobs = new BlobManager(dbUrl, this.http, fullConfig.blobHandling ?? 'auto', fullConfig.maxStringLength ?? 32768);
4747
// Pass BlobManager to DataManager so create/get/list auto-process blobs
4848
this.data = new DataManager(dbUrl, this.http, this.blobs);
4949
}

src/types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ export interface DexieCloudConfig {
1818

1919
/** Blob handling mode: 'auto' (default) or 'lazy' */
2020
blobHandling?: BlobHandling;
21+
22+
/** Maximum string length before offloading to blob storage.
23+
* Strings longer than this are uploaded as blobs during write.
24+
* Set to Infinity to disable string offloading.
25+
* @default 32768
26+
*/
27+
maxStringLength?: number;
2128

2229
/** Optional custom fetch implementation */
2330
fetch?: typeof globalThis.fetch;

0 commit comments

Comments
 (0)