@loradb/lora-wasm 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -37,19 +37,24 @@ npm run test:browser
37
37
  npm run pack:dry
38
38
  ```
39
39
 
40
- ## Two execution modes
40
+ ## Execution modes
41
41
 
42
- ### 1. In-process (Node / scripts)
42
+ ### 1. Default: Worker first, main-thread fallback
43
43
 
44
44
  `lora-wasm` is **async-only** — the sole initialization pattern is
45
45
  `createDatabase()`, which bootstraps the WASM module on first call.
46
46
  There is no synchronous constructor and no `Database.create()`
47
47
  static; `Database` is a type-only export.
48
48
 
49
+ In browser-like hosts, `createDatabase()` tries to spawn the packaged module
50
+ Worker first and pings it before returning. If the Worker cannot be created or
51
+ fails during startup, the package emits one `console.warn` and falls back to
52
+ the in-process WASM engine so the app can still run.
53
+
49
54
  ```ts
50
55
  import { createDatabase, isNode } from "lora-wasm";
51
56
 
52
- const db = await createDatabase();
57
+ const db = await createDatabase(); // Worker-backed in browsers when possible
53
58
  await db.execute("CREATE (:Person {name: $n})", { n: "Alice" });
54
59
 
55
60
  const r = await db.execute("MATCH (n:Person) RETURN n");
@@ -58,7 +63,36 @@ for (const row of r.rows) {
58
63
  }
59
64
  ```
60
65
 
61
- ### 2. Non-blocking Web Worker (browser)
66
+ To force the in-process engine:
67
+
68
+ ```ts
69
+ const db = await createDatabase({ runtime: "main-thread" });
70
+ ```
71
+
72
+ To require Worker startup instead of falling back:
73
+
74
+ ```ts
75
+ const db = await createDatabase({ runtime: "worker" });
76
+ ```
77
+
78
+ To disable the fallback warning:
79
+
80
+ ```ts
81
+ const db = await createDatabase({ warnOnFallback: false });
82
+ ```
83
+
84
+ ### 2. Explicit main-thread WASM
85
+
86
+ ```ts
87
+ import { createMainThreadDatabase } from "lora-wasm";
88
+
89
+ const db = await createMainThreadDatabase();
90
+ ```
91
+
92
+ ### 3. Custom Web Worker
93
+
94
+ Use this when you need to control the Worker URL, lifecycle, bundler entry, or
95
+ pooling strategy.
62
96
 
63
97
  ```ts
64
98
  import { createWorkerDatabase } from "lora-wasm/worker-client";
@@ -75,11 +109,42 @@ const { rows } = await db.execute("MATCH (n) RETURN n.n AS n");
75
109
  The worker entry (`ts/worker.ts`) hosts the WASM module. The main thread only
76
110
  posts messages, so long-running queries never block the event loop / UI.
77
111
 
78
- ### 3. In-process but typed like the worker (advanced)
112
+ ### 4. In-process but typed like the worker (advanced)
79
113
 
80
114
  The same `createWorkerDatabase` signature accepts any `WorkerLike` object —
81
115
  useful for tests and for swapping execution backends behind the same API.
82
116
 
117
+ ## Snapshots
118
+
119
+ WASM has no filesystem access, so `saveSnapshot()` defaults to a `Uint8Array`.
120
+ It also accepts typed formats: `"base64"` returns base64 text, `"blob"` returns
121
+ a `Blob`, and `"download"` triggers a browser download from the main thread.
122
+
123
+ `loadSnapshot` accepts a `WasmSnapshotSource`: `Uint8Array`, `ArrayBuffer`,
124
+ `Blob`/`File`, `Response`, web `ReadableStream`, string URL, or `URL`. It does
125
+ not include Node `Buffer`; use `Uint8Array` bytes when running the WASM package
126
+ from Node.
127
+
128
+ ```ts
129
+ import { createDatabase } from "lora-wasm";
130
+
131
+ const db = await createDatabase();
132
+ await db.execute("CREATE (:Person {name: 'Alice'})");
133
+
134
+ const bytes = await db.saveSnapshotToBytes();
135
+ const sameBytes = await db.saveSnapshot("binary");
136
+ const blob = await db.saveSnapshot({ format: "blob" });
137
+ await db.saveSnapshot({ format: "download", filename: "graph.lorasnap" });
138
+
139
+ await db.loadSnapshot(bytes);
140
+ await db.loadSnapshot(blob);
141
+ await db.loadSnapshot(new Response(bytes).body!);
142
+ await db.loadSnapshot(new URL("/graph.lorasnap", location.href));
143
+ ```
144
+
145
+ `loadSnapshotFromBytes(bytes)` remains available for the narrow
146
+ `Uint8Array`-only path.
147
+
83
148
  ## Typed value model
84
149
 
85
150
  | TS type | Runtime shape |
@@ -140,8 +205,7 @@ public surface — consumers can swap backends without rewriting types.
140
205
  millisecond-granular, so the nanosecond field on returned values is
141
206
  zero below the millisecond boundary.
142
207
  - Engine errors cross the worker boundary as `LoraError` with a
143
- narrowed `code`; the engine does not currently stream query progress
144
- or offer cancellation.
208
+ narrowed `code`; the engine does not currently offer query cancellation.
145
209
 
146
210
  ## Feasibility assessment
147
211
 
package/dist/index.d.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  /**
2
2
  * lora-wasm — typed WebAssembly bindings for the Lora graph engine.
3
3
  *
4
- * This entry targets Node.js (ESM) and any bundler host whose resolver maps
5
- * `node:module` through. Browser consumers should prefer the Worker-backed
6
- * API exposed in `worker-client.ts` to keep the main thread responsive.
4
+ * This entry targets Node.js (ESM) and browser bundlers. In browser-like
5
+ * hosts, `createDatabase()` tries to start the packaged Web Worker first so
6
+ * query work stays off the main thread. If that fails, it warns once and
7
+ * falls back to the in-process WASM engine.
7
8
  *
8
9
  * **Initialization is async-only.** The one canonical entry point is
9
10
  * `createDatabase()`; the WASM module is bootstrapped inside it before the
@@ -16,8 +17,11 @@
16
17
  */
17
18
  import type { LoraParams, LoraValue, QueryResult } from "./types.js";
18
19
  import { WasmDatabase } from "./loader-node.js";
20
+ import type { WorkerDatabase } from "./worker-client.js";
21
+ import type { WasmSnapshotSource } from "./snapshot.js";
19
22
  export * from "./types.js";
20
- export { createWorkerDatabase, type WorkerDatabase } from "./worker-client.js";
23
+ export { createWorkerDatabase, type WorkerDatabase, type WorkerLike, } from "./worker-client.js";
24
+ export type { WasmSnapshotSaveFormat, WasmSnapshotSaveOptions, WasmSnapshotSource, } from "./snapshot.js";
21
25
  /**
22
26
  * Metadata returned by `saveSnapshotToBytes` / `loadSnapshotFromBytes`.
23
27
  * Mirrors the Rust `SnapshotMeta` struct and matches the shape used by
@@ -30,6 +34,34 @@ export interface SnapshotMeta {
30
34
  relationshipCount: number;
31
35
  walLsn: number | null;
32
36
  }
37
+ export interface CreateDatabaseOptions {
38
+ /**
39
+ * Select where the WASM engine runs.
40
+ *
41
+ * - `"auto"` tries a Web Worker first when available, then falls back to
42
+ * the main thread.
43
+ * - `"worker"` requires a Web Worker and rejects if startup fails.
44
+ * - `"main-thread"` skips Worker startup and runs the engine in-process.
45
+ *
46
+ * Defaults to `"auto"`.
47
+ */
48
+ runtime?: "auto" | "worker" | "main-thread";
49
+ /**
50
+ * Emit `console.warn` if worker startup fails and the factory falls back to
51
+ * the main-thread WASM engine in `"auto"` mode. Defaults to `true`.
52
+ */
53
+ warnOnFallback?: boolean;
54
+ }
55
+ export type TransactionMode = "read_write" | "read_only" | "readwrite" | "readonly" | "rw" | "ro";
56
+ export interface TransactionStatement {
57
+ query: string;
58
+ params?: LoraParams | null;
59
+ }
60
+ export interface RowStream<T extends Record<string, LoraValue> = Record<string, LoraValue>> extends AsyncIterableIterator<T> {
61
+ columns(): string[] | Promise<string[]>;
62
+ toArray(): Promise<T[]>;
63
+ close(): void;
64
+ }
33
65
  /**
34
66
  * In-memory Lora graph database running on the WASM engine.
35
67
  *
@@ -42,6 +74,9 @@ declare class DatabaseImpl {
42
74
  #private;
43
75
  constructor(inner: InstanceType<typeof WasmDatabase>);
44
76
  execute<T extends Record<string, LoraValue> = Record<string, LoraValue>>(query: string, params?: LoraParams): Promise<QueryResult<T>>;
77
+ stream<T extends Record<string, LoraValue> = Record<string, LoraValue>>(query: string, params?: LoraParams): RowStream<T>;
78
+ rows<T extends Record<string, LoraValue> = Record<string, LoraValue>>(query: string, params?: LoraParams): RowStream<T>;
79
+ transaction<T extends Record<string, LoraValue> = Record<string, LoraValue>>(statements: TransactionStatement[], mode?: TransactionMode): Promise<Array<QueryResult<T>>>;
45
80
  clear(): Promise<void>;
46
81
  nodeCount(): Promise<number>;
47
82
  relationshipCount(): Promise<number>;
@@ -52,11 +87,32 @@ declare class DatabaseImpl {
52
87
  * them back to `loadSnapshotFromBytes` on a future database instance.
53
88
  */
54
89
  saveSnapshotToBytes(): Promise<Uint8Array>;
90
+ saveSnapshot(): Promise<Uint8Array>;
91
+ saveSnapshot(format: "binary"): Promise<Uint8Array>;
92
+ saveSnapshot(format: "base64"): Promise<string>;
93
+ saveSnapshot(format: "blob"): Promise<Blob>;
94
+ saveSnapshot(format: "download"): Promise<void>;
95
+ saveSnapshot(options: {
96
+ format: "binary";
97
+ }): Promise<Uint8Array>;
98
+ saveSnapshot(options: {
99
+ format: "base64";
100
+ }): Promise<string>;
101
+ saveSnapshot(options: {
102
+ format: "blob";
103
+ mimeType?: string;
104
+ }): Promise<Blob>;
105
+ saveSnapshot(options: {
106
+ format: "download";
107
+ filename?: string;
108
+ mimeType?: string;
109
+ }): Promise<void>;
55
110
  /**
56
111
  * Replace the current graph state with a snapshot decoded from `bytes`.
57
112
  * Returns metadata describing the restored snapshot.
58
113
  */
59
114
  loadSnapshotFromBytes(bytes: Uint8Array): Promise<SnapshotMeta>;
115
+ loadSnapshot(source: WasmSnapshotSource): Promise<SnapshotMeta>;
60
116
  /** Release the underlying wasm handle. Subsequent calls will throw. */
61
117
  dispose(): void;
62
118
  }
@@ -66,14 +122,15 @@ declare class DatabaseImpl {
66
122
  * Exported as a type only — there is no runtime `Database` value. To obtain
67
123
  * an instance, always use `createDatabase()`.
68
124
  */
69
- export type Database = DatabaseImpl;
125
+ export type Database = DatabaseImpl | WorkerDatabase;
70
126
  /**
71
127
  * Create and initialize a new in-memory LoraDB instance on the WASM engine.
72
128
  *
73
- * **This is the only supported initialization pattern** for `lora-wasm`.
74
- * Synchronous construction is not available — the async factory bootstraps
75
- * the WASM module on first call and guarantees the engine is ready before
76
- * the first query.
129
+ * In browser-like hosts this factory tries the packaged Web Worker first,
130
+ * pings it, and returns the worker-backed database when startup succeeds.
131
+ * If worker construction or bootstrap fails it warns once and falls back to
132
+ * the main-thread WASM engine. Pass `{ runtime: "main-thread" }` to force the
133
+ * in-process engine, or `{ runtime: "worker" }` to require a Worker.
77
134
  *
78
135
  * ```ts
79
136
  * import { createDatabase } from "lora-wasm";
@@ -82,9 +139,10 @@ export type Database = DatabaseImpl;
82
139
  * const res = await db.execute("MATCH (n) RETURN count(n) AS n");
83
140
  * ```
84
141
  *
85
- * For heavy browser workloads, use `createWorkerDatabase()` from
86
- * `lora-wasm/worker-client` instead — it keeps the main thread responsive
87
- * by running the engine in a Web Worker.
142
+ * Use `createMainThreadDatabase()` when you explicitly want the in-process
143
+ * WASM engine, or `createWorkerDatabase(worker)` when you need to supply a
144
+ * custom Worker instance.
88
145
  */
89
- export declare function createDatabase(): Promise<Database>;
146
+ export declare function createMainThreadDatabase(): Promise<DatabaseImpl>;
147
+ export declare function createDatabase(options?: CreateDatabaseOptions): Promise<Database>;
90
148
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../ts/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,SAAS,EACT,WAAW,EACZ,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,YAAY,EAAoB,MAAM,kBAAkB,CAAC;AAElE,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,oBAAoB,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAE/E;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AASD;;;;;;;GAOG;AACH,cAAM,YAAY;;gBAGJ,KAAK,EAAE,YAAY,CAAC,OAAO,YAAY,CAAC;IAI9C,OAAO,CACX,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAC/D,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IASxD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAItB,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC;IAI5B,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;IAI1C;;;;;OAKG;IACG,mBAAmB,IAAI,OAAO,CAAC,UAAU,CAAC;IAQhD;;;OAGG;IACG,qBAAqB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC;IAQrE,uEAAuE;IACvE,OAAO,IAAI,IAAI;CAGhB;AAED;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,YAAY,CAAC;AAEpC;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,QAAQ,CAAC,CAGxD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../ts/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,9 +1,10 @@
1
1
  /**
2
2
  * lora-wasm — typed WebAssembly bindings for the Lora graph engine.
3
3
  *
4
- * This entry targets Node.js (ESM) and any bundler host whose resolver maps
5
- * `node:module` through. Browser consumers should prefer the Worker-backed
6
- * API exposed in `worker-client.ts` to keep the main thread responsive.
4
+ * This entry targets Node.js (ESM) and browser bundlers. In browser-like
5
+ * hosts, `createDatabase()` tries to start the packaged Web Worker first so
6
+ * query work stays off the main thread. If that fails, it warns once and
7
+ * falls back to the in-process WASM engine.
7
8
  *
8
9
  * **Initialization is async-only.** The one canonical entry point is
9
10
  * `createDatabase()`; the WASM module is bootstrapped inside it before the
@@ -16,8 +17,70 @@
16
17
  */
17
18
  import { wrapError } from "./types.js";
18
19
  import { WasmDatabase, init as wasmInit } from "./loader-node.js";
20
+ import { createWorkerDatabase } from "./worker-client.js";
21
+ import { downloadSnapshotBytes, resolveSnapshotSaveFormat, snapshotBytesToBase64, snapshotBytesToBlob, snapshotSourceToBytes, } from "./snapshot.js";
19
22
  export * from "./types.js";
20
- export { createWorkerDatabase } from "./worker-client.js";
23
+ export { createWorkerDatabase, } from "./worker-client.js";
24
+ class NativeRowStream {
25
+ #inner;
26
+ #closed = false;
27
+ constructor(inner) {
28
+ this.#inner = inner;
29
+ }
30
+ [Symbol.asyncIterator]() {
31
+ return this;
32
+ }
33
+ columns() {
34
+ try {
35
+ return this.#inner.columns();
36
+ }
37
+ catch (err) {
38
+ throw wrapError(err);
39
+ }
40
+ }
41
+ async next() {
42
+ if (this.#closed) {
43
+ return { done: true, value: undefined };
44
+ }
45
+ try {
46
+ const row = this.#inner.next();
47
+ if (row === null) {
48
+ this.#closed = true;
49
+ return { done: true, value: undefined };
50
+ }
51
+ return { done: false, value: row };
52
+ }
53
+ catch (err) {
54
+ this.#closed = true;
55
+ throw wrapError(err);
56
+ }
57
+ }
58
+ async return() {
59
+ this.close();
60
+ return { done: true, value: undefined };
61
+ }
62
+ async toArray() {
63
+ const rows = [];
64
+ for (;;) {
65
+ const next = await this.next();
66
+ if (next.done) {
67
+ return rows;
68
+ }
69
+ rows.push(next.value);
70
+ }
71
+ }
72
+ close() {
73
+ if (this.#closed)
74
+ return;
75
+ this.#closed = true;
76
+ try {
77
+ this.#inner.close();
78
+ }
79
+ catch (err) {
80
+ throw wrapError(err);
81
+ }
82
+ }
83
+ }
21
84
  let bootstrapped = false;
22
85
  function ensureBootstrapped() {
23
86
  if (bootstrapped)
@@ -47,6 +110,27 @@ class DatabaseImpl {
47
110
  throw wrapError(err);
48
111
  }
49
112
  }
113
+ stream(query, params) {
114
+ try {
115
+ const native = this.#inner;
116
+ return new NativeRowStream(native.openStream(query, params ?? null));
117
+ }
118
+ catch (err) {
119
+ throw wrapError(err);
120
+ }
121
+ }
122
+ rows(query, params) {
123
+ return this.stream(query, params);
124
+ }
125
+ async transaction(statements, mode = "read_write") {
126
+ try {
127
+ const native = this.#inner;
128
+ return native.transaction(statements, mode);
129
+ }
130
+ catch (err) {
131
+ throw wrapError(err);
132
+ }
133
+ }
50
134
  async clear() {
51
135
  this.#inner.clear();
52
136
  }
@@ -70,6 +154,20 @@ class DatabaseImpl {
70
154
  throw wrapError(err);
71
155
  }
72
156
  }
157
+ async saveSnapshot(target) {
158
+ const options = resolveSnapshotSaveFormat(target);
159
+ const bytes = await this.saveSnapshotToBytes();
160
+ switch (options.format) {
161
+ case "binary":
162
+ return bytes;
163
+ case "base64":
164
+ return snapshotBytesToBase64(bytes);
165
+ case "blob":
166
+ return snapshotBytesToBlob(bytes, options.mimeType);
167
+ case "download":
168
+ return downloadSnapshotBytes(bytes, options.filename, options.mimeType);
169
+ }
170
+ }
73
171
  /**
74
172
  * Replace the current graph state with a snapshot decoded from `bytes`.
75
173
  * Returns metadata describing the restored snapshot.
@@ -82,18 +180,50 @@ class DatabaseImpl {
82
180
  throw wrapError(err);
83
181
  }
84
182
  }
183
+ async loadSnapshot(source) {
184
+ try {
185
+ return this.#inner.loadSnapshotFromBytes(await snapshotSourceToBytes(source));
186
+ }
187
+ catch (err) {
188
+ throw wrapError(err);
189
+ }
190
+ }
85
191
  /** Release the underlying wasm handle. Subsequent calls will throw. */
86
192
  dispose() {
87
193
  this.#inner.free();
88
194
  }
89
195
  }
196
+ let warnedWorkerFallback = false;
197
+ function requestedRuntime(options) {
198
+ return options?.runtime ?? "auto";
199
+ }
200
+ function shouldTryDefaultWorker(options) {
201
+ const runtime = requestedRuntime(options);
202
+ return runtime !== "main-thread" && typeof Worker !== "undefined";
203
+ }
204
+ function shouldFallbackToMainThread(options) {
205
+ return requestedRuntime(options) === "auto";
206
+ }
207
+ function warnWorkerFallback(err, options) {
208
+ if (options?.warnOnFallback === false || warnedWorkerFallback)
209
+ return;
210
+ warnedWorkerFallback = true;
211
+ const detail = err instanceof Error ? err.message : String(err);
212
+ console.warn(`[lora-wasm] Web Worker startup failed; falling back to main-thread WASM. ${detail}`);
213
+ }
214
+ function createDefaultWorker() {
215
+ return new Worker(new URL("./worker.js", import.meta.url), {
216
+ type: "module",
217
+ });
218
+ }
90
219
  /**
91
220
  * Create and initialize a new in-memory LoraDB instance on the WASM engine.
92
221
  *
93
- * **This is the only supported initialization pattern** for `lora-wasm`.
94
- * Synchronous construction is not available — the async factory bootstraps
95
- * the WASM module on first call and guarantees the engine is ready before
96
- * the first query.
222
+ * In browser-like hosts this factory tries the packaged Web Worker first,
223
+ * pings it, and returns the worker-backed database when startup succeeds.
224
+ * If worker construction or bootstrap fails it warns once and falls back to
225
+ * the main-thread WASM engine. Pass `{ runtime: "main-thread" }` to force the
226
+ * in-process engine, or `{ runtime: "worker" }` to require a Worker.
97
227
  *
98
228
  * ```ts
99
229
  * import { createDatabase } from "lora-wasm";
@@ -102,12 +232,39 @@ class DatabaseImpl {
102
232
  * const res = await db.execute("MATCH (n) RETURN count(n) AS n");
103
233
  * ```
104
234
  *
105
- * For heavy browser workloads, use `createWorkerDatabase()` from
106
- * `lora-wasm/worker-client` instead — it keeps the main thread responsive
107
- * by running the engine in a Web Worker.
235
+ * Use `createMainThreadDatabase()` when you explicitly want the in-process
236
+ * WASM engine, or `createWorkerDatabase(worker)` when you need to supply a
237
+ * custom Worker instance.
108
238
  */
109
- export async function createDatabase() {
239
+ export async function createMainThreadDatabase() {
110
240
  ensureBootstrapped();
111
241
  return new DatabaseImpl(new WasmDatabase());
112
242
  }
243
+ export async function createDatabase(options = {}) {
244
+ if (shouldTryDefaultWorker(options)) {
245
+ let worker = null;
246
+ try {
247
+ worker = createDefaultWorker();
248
+ const db = createWorkerDatabase(worker);
249
+ await db.nodeCount();
250
+ return db;
251
+ }
252
+ catch (err) {
253
+ try {
254
+ worker?.terminate();
255
+ }
256
+ catch {
257
+ // best-effort cleanup after a failed worker startup
258
+ }
259
+ if (!shouldFallbackToMainThread(options)) {
260
+ throw wrapError(err);
261
+ }
262
+ warnWorkerFallback(err, options);
263
+ }
264
+ }
265
+ if (requestedRuntime(options) === "worker") {
266
+ throw wrapError(new Error("WORKER_ERROR: Web Worker is not available"));
267
+ }
268
+ return createMainThreadDatabase();
269
+ }
113
270
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../ts/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAOH,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAElE,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,oBAAoB,EAAuB,MAAM,oBAAoB,CAAC;AAe/E,IAAI,YAAY,GAAG,KAAK,CAAC;AACzB,SAAS,kBAAkB;IACzB,IAAI,YAAY;QAAE,OAAO;IACzB,QAAQ,EAAE,CAAC;IACX,YAAY,GAAG,IAAI,CAAC;AACtB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,YAAY;IACP,MAAM,CAAoC;IAEnD,YAAY,KAAwC;QAClD,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,OAAO,CAEX,KAAa,EAAE,MAAmB;QAClC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,MAAM,IAAI,IAAI,CAAY,CAAC,CAAC;YACpE,OAAO,GAAqB,CAAC;QAC/B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,SAAS;QACb,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,iBAAiB;QACrB,OAAO,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC;IACzC,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,mBAAmB;QACvB,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC;QAC3C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,qBAAqB,CAAC,KAAiB;QAC3C,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,MAAM,CAAC,qBAAqB,CAAC,KAAK,CAAiB,CAAC;QAClE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,uEAAuE;IACvE,OAAO;QACL,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACrB,CAAC;CACF;AAUD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,kBAAkB,EAAE,CAAC;IACrB,OAAO,IAAI,YAAY,CAAC,IAAI,YAAY,EAAE,CAAC,CAAC;AAC9C,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../ts/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAOH,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE1D,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,eAAe,CAAC;AAMvB,cAAc,YAAY,CAAC;AAC3B,OAAO,EACL,oBAAoB,GAGrB,MAAM,oBAAoB,CAAC;AAkE5B,MAAM,eAAe;IAGV,MAAM,CAAoB;IACnC,OAAO,GAAG,KAAK,CAAC;IAEhB,YAAY,KAAwB;QAClC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,CAAC,MAAM,CAAC,aAAa,CAAC;QACpB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,EAAc,CAAC;QAC3C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QAC1C,CAAC;QACD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,EAAc,CAAC;YAC3C,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;gBACjB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;gBACpB,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;YAC1C,CAAC;YACD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;QACrC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACpB,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM;QACV,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,IAAI,GAAQ,EAAE,CAAC;QACrB,SAAS,CAAC;YACR,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;YAC/B,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,OAAO,IAAI,CAAC;YACd,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO;QACzB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACtB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;CACF;AAED,IAAI,YAAY,GAAG,KAAK,CAAC;AACzB,SAAS,kBAAkB;IACzB,IAAI,YAAY;QAAE,OAAO;IACzB,QAAQ,EAAE,CAAC;IACX,YAAY,GAAG,IAAI,CAAC;AACtB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,YAAY;IACP,MAAM,CAAoC;IAEnD,YAAY,KAAwC;QAClD,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,OAAO,CAEX,KAAa,EAAE,MAAmB;QAClC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,MAAM,IAAI,IAAI,CAAY,CAAC,CAAC;YACpE,OAAO,GAAqB,CAAC;QAC/B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,MAAM,CACJ,KAAa,EACb,MAAmB;QAEnB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,MAEnB,CAAC;YACF,OAAO,IAAI,eAAe,CAAI,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC;QAC1E,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,IAAI,CACF,KAAa,EACb,MAAmB;QAEnB,OAAO,IAAI,CAAC,MAAM,CAAI,KAAK,EAAE,MAAM,CAAC,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,WAAW,CAGf,UAAkC,EAClC,OAAwB,YAAY;QAEpC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,MAEnB,CAAC;YACF,OAAO,MAAM,CAAC,WAAW,CAAC,UAAU,EAAE,IAAI,CAA0B,CAAC;QACvE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,SAAS;QACb,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,iBAAiB;QACrB,OAAO,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC;IACzC,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,mBAAmB;QACvB,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC;QAC3C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAWD,KAAK,CAAC,YAAY,CAChB,MAAoE;QAEpE,MAAM,OAAO,GAAG,yBAAyB,CAAC,MAAM,CAAC,CAAC;QAClD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAE/C,QAAQ,OAAO,CAAC,MAAM,EAAE,CAAC;YACvB,KAAK,QAAQ;gBACX,OAAO,KAAK,CAAC;YACf,KAAK,QAAQ;gBACX,OAAO,qBAAqB,CAAC,KAAK,CAAC,CAAC;YACtC,KAAK,MAAM;gBACT,OAAO,mBAAmB,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;YACtD,KAAK,UAAU;gBACb,OAAO,qBAAqB,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC5E,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,qBAAqB,CAAC,KAAiB;QAC3C,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,MAAM,CAAC,qBAAqB,CAAC,KAAK,CAAiB,CAAC;QAClE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,MAA0B;QAC3C,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,MAAM,CAAC,qBAAqB,CACtC,MAAM,qBAAqB,CAAC,MAAM,CAAC,CACpB,CAAC;QACpB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,uEAAuE;IACvE,OAAO;QACL,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACrB,CAAC;CACF;AAUD,IAAI,oBAAoB,GAAG,KAAK,CAAC;AAEjC,SAAS,gBAAgB,CAAC,OAA+B;IACvD,OAAO,OAAO,EAAE,OAAO,IAAI,MAAM,CAAC;AACpC,CAAC;AAED,SAAS,sBAAsB,CAAC,OAA+B;IAC7D,MAAM,OAAO,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC1C,OAAO,OAAO,KAAK,aAAa,IAAI,OAAO,MAAM,KAAK,WAAW,CAAC;AACpE,CAAC;AAED,SAAS,0BAA0B,CAAC,OAA+B;IACjE,OAAO,gBAAgB,CAAC,OAAO,CAAC,KAAK,MAAM,CAAC;AAC9C,CAAC;AAED,SAAS,kBAAkB,CAAC,GAAY,EAAE,OAA+B;IACvE,IAAI,OAAO,EAAE,cAAc,KAAK,KAAK,IAAI,oBAAoB;QAAE,OAAO;IACtE,oBAAoB,GAAG,IAAI,CAAC;IAC5B,MAAM,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAChE,OAAO,CAAC,IAAI,CACV,4EAA4E,MAAM,EAAE,CACrF,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB;IAC1B,OAAO,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QACzD,IAAI,EAAE,QAAQ;KACf,CAAe,CAAC;AACnB,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB;IAC5C,kBAAkB,EAAE,CAAC;IACrB,OAAO,IAAI,YAAY,CAAC,IAAI,YAAY,EAAE,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,UAAiC,EAAE;IAEnC,IAAI,sBAAsB,CAAC,OAAO,CAAC,EAAE,CAAC;QACpC,IAAI,MAAM,GAAsB,IAAI,CAAC;QACrC,IAAI,CAAC;YACH,MAAM,GAAG,mBAAmB,EAAE,CAAC;YAC/B,MAAM,EAAE,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;YACxC,MAAM,EAAE,CAAC,SAAS,EAAE,CAAC;YACrB,OAAO,EAAE,CAAC;QACZ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC;gBACH,MAAM,EAAE,SAAS,EAAE,CAAC;YACtB,CAAC;YAAC,MAAM,CAAC;gBACP,oDAAoD;YACtD,CAAC;YACD,IAAI,CAAC,0BAA0B,CAAC,OAAO,CAAC,EAAE,CAAC;gBACzC,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;YACvB,CAAC;YACD,kBAAkB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IACD,IAAI,gBAAgB,CAAC,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC3C,MAAM,SAAS,CAAC,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,wBAAwB,EAAE,CAAC;AACpC,CAAC"}
@@ -0,0 +1,22 @@
1
+ export type WasmSnapshotSource = string | URL | Uint8Array | ArrayBuffer | Blob | Response | ReadableStream<Uint8Array | ArrayBuffer>;
2
+ export type WasmSnapshotSaveFormat = "binary" | "base64" | "blob" | "download";
3
+ export type WasmSnapshotSaveOptions = {
4
+ format: "binary";
5
+ } | {
6
+ format: "base64";
7
+ } | {
8
+ format: "blob";
9
+ mimeType?: string;
10
+ } | {
11
+ format: "download";
12
+ filename?: string;
13
+ mimeType?: string;
14
+ };
15
+ export type WasmSnapshotSaveTarget = WasmSnapshotSaveFormat | WasmSnapshotSaveOptions | undefined;
16
+ export declare function bytesToUint8Array(bytes: Uint8Array | ArrayBuffer): Uint8Array;
17
+ export declare function snapshotBytesToBase64(bytes: Uint8Array): string;
18
+ export declare function snapshotBytesToBlob(bytes: Uint8Array, mimeType?: string): Blob;
19
+ export declare function downloadSnapshotBytes(bytes: Uint8Array, filename?: string, mimeType?: string): void;
20
+ export declare function resolveSnapshotSaveFormat(target: WasmSnapshotSaveTarget): WasmSnapshotSaveOptions;
21
+ export declare function snapshotSourceToBytes(source: WasmSnapshotSource): Promise<Uint8Array>;
22
+ //# sourceMappingURL=snapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../ts/snapshot.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAC1B,MAAM,GACN,GAAG,GACH,UAAU,GACV,WAAW,GACX,IAAI,GACJ,QAAQ,GACR,cAAc,CAAC,UAAU,GAAG,WAAW,CAAC,CAAC;AAC7C,MAAM,MAAM,sBAAsB,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;AAC/E,MAAM,MAAM,uBAAuB,GAC/B;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,GACpB;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,GACpB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACjE,MAAM,MAAM,sBAAsB,GAC9B,sBAAsB,GACtB,uBAAuB,GACvB,SAAS,CAAC;AAKd,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,GAAG,UAAU,CAK7E;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAe/D;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,UAAU,EACjB,QAAQ,SAA6B,GACpC,IAAI,CAIN;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,UAAU,EACjB,QAAQ,SAA4B,EACpC,QAAQ,SAA6B,GACpC,IAAI,CAsCN;AAED,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,sBAAsB,GAC7B,uBAAuB,CAQzB;AAED,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,UAAU,CAAC,CAkBrB"}
@@ -0,0 +1,107 @@
1
+ const DEFAULT_SNAPSHOT_MIME_TYPE = "application/octet-stream";
2
+ const DEFAULT_SNAPSHOT_FILENAME = "lora-snapshot.bin";
3
+ export function bytesToUint8Array(bytes) {
4
+ if (bytes instanceof Uint8Array) {
5
+ return bytes;
6
+ }
7
+ return new Uint8Array(bytes);
8
+ }
9
+ export function snapshotBytesToBase64(bytes) {
10
+ const buffer = globalThis.Buffer;
11
+ if (buffer) {
12
+ return buffer.from(bytes).toString("base64");
13
+ }
14
+ const chunkSize = 0x8000;
15
+ let binary = "";
16
+ for (let offset = 0; offset < bytes.byteLength; offset += chunkSize) {
17
+ const chunk = bytes.subarray(offset, offset + chunkSize);
18
+ binary += String.fromCharCode(...chunk);
19
+ }
20
+ return btoa(binary);
21
+ }
22
+ export function snapshotBytesToBlob(bytes, mimeType = DEFAULT_SNAPSHOT_MIME_TYPE) {
23
+ const copy = new Uint8Array(bytes.byteLength);
24
+ copy.set(bytes);
25
+ return new Blob([copy.buffer], { type: mimeType });
26
+ }
27
+ export function downloadSnapshotBytes(bytes, filename = DEFAULT_SNAPSHOT_FILENAME, mimeType = DEFAULT_SNAPSHOT_MIME_TYPE) {
28
+ const doc = globalThis.document;
29
+ const urlApi = globalThis.URL;
30
+ if (!doc || !urlApi?.createObjectURL) {
31
+ throw new Error("LORA_ERROR: snapshot download requires a browser document");
32
+ }
33
+ const url = urlApi.createObjectURL(snapshotBytesToBlob(bytes, mimeType));
34
+ const anchor = doc.createElement("a");
35
+ anchor.href = url;
36
+ anchor.download = filename;
37
+ if (anchor.style) {
38
+ anchor.style.display = "none";
39
+ }
40
+ doc.body?.appendChild(anchor);
41
+ try {
42
+ anchor.click();
43
+ }
44
+ finally {
45
+ anchor.remove?.();
46
+ setTimeout(() => urlApi.revokeObjectURL(url), 0);
47
+ }
48
+ }
49
+ export function resolveSnapshotSaveFormat(target) {
50
+ if (target === undefined) {
51
+ return { format: "binary" };
52
+ }
53
+ if (typeof target === "string") {
54
+ return { format: target };
55
+ }
56
+ return target;
57
+ }
58
+ export async function snapshotSourceToBytes(source) {
59
+ if (source instanceof Uint8Array || source instanceof ArrayBuffer) {
60
+ return bytesToUint8Array(source);
61
+ }
62
+ if (typeof Blob !== "undefined" && source instanceof Blob) {
63
+ return new Uint8Array(await source.arrayBuffer());
64
+ }
65
+ if (typeof Response !== "undefined" && source instanceof Response) {
66
+ return responseToBytes(source);
67
+ }
68
+ if (isReadableStream(source)) {
69
+ return readableStreamToBytes(source);
70
+ }
71
+ return responseToBytes(await fetch(source));
72
+ }
73
+ function isReadableStream(source) {
74
+ return typeof source.getReader === "function";
75
+ }
76
+ async function readableStreamToBytes(stream) {
77
+ const reader = stream.getReader();
78
+ const chunks = [];
79
+ let total = 0;
80
+ try {
81
+ for (;;) {
82
+ const { done, value } = await reader.read();
83
+ if (done) {
84
+ const merged = new Uint8Array(total);
85
+ let offset = 0;
86
+ for (const chunk of chunks) {
87
+ merged.set(chunk, offset);
88
+ offset += chunk.byteLength;
89
+ }
90
+ return merged;
91
+ }
92
+ const chunk = bytesToUint8Array(value);
93
+ chunks.push(chunk);
94
+ total += chunk.byteLength;
95
+ }
96
+ }
97
+ finally {
98
+ reader.releaseLock();
99
+ }
100
+ }
101
+ async function responseToBytes(response) {
102
+ if (!response.ok) {
103
+ throw new Error(`LORA_ERROR: snapshot fetch failed (${response.status} ${response.statusText})`);
104
+ }
105
+ return new Uint8Array(await response.arrayBuffer());
106
+ }
107
+ //# sourceMappingURL=snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../ts/snapshot.ts"],"names":[],"mappings":"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"}