@wvb/node 0.0.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/CHANGELOG.md +1 -0
- package/README.md +1 -0
- package/binding.darwin-arm64.node +0 -0
- package/index.cjs +532 -0
- package/index.d.cts +1413 -0
- package/index.d.ts +1413 -0
- package/index.js +533 -0
- package/package.json +91 -0
- package/wvb-node.darwin-arm64.node +0 -0
package/index.d.cts
ADDED
|
@@ -0,0 +1,1413 @@
|
|
|
1
|
+
/* auto-generated by NAPI-RS */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
/**
|
|
4
|
+
* A complete bundle including metadata and file data.
|
|
5
|
+
*
|
|
6
|
+
* Represents a `.wvb` bundle file loaded entirely into memory.
|
|
7
|
+
* Use this when you need to access multiple files or build new bundles.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* // Read a bundle from file
|
|
12
|
+
* const bundle = await readBundle("app.wvb");
|
|
13
|
+
*
|
|
14
|
+
* // Access files
|
|
15
|
+
* const html = bundle.getData("/index.html");
|
|
16
|
+
* if (html) {
|
|
17
|
+
* console.log(html.toString("utf-8"));
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare class Bundle {
|
|
22
|
+
/**
|
|
23
|
+
* Returns the bundle descriptor (header and index).
|
|
24
|
+
*
|
|
25
|
+
* @returns {BundleDescriptor} Bundle metadata
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* const descriptor = bundle.descriptor();
|
|
30
|
+
* const index = descriptor.index();
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
descriptor(): BundleDescriptor
|
|
34
|
+
/**
|
|
35
|
+
* Retrieves file data by path.
|
|
36
|
+
*
|
|
37
|
+
* Returns the decompressed file contents, or null if the path doesn't exist.
|
|
38
|
+
*
|
|
39
|
+
* @param {string} path - File path in the bundle (e.g., "/index.html")
|
|
40
|
+
* @returns {Buffer | null} File contents or null if not found
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* const data = bundle.getData("/index.html");
|
|
45
|
+
* if (data) {
|
|
46
|
+
* console.log(data.toString("utf-8"));
|
|
47
|
+
* }
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
getData(path: string): Buffer | null
|
|
51
|
+
/**
|
|
52
|
+
* Retrieves the checksum of file data by path.
|
|
53
|
+
*
|
|
54
|
+
* @param {string} path - File path in the bundle
|
|
55
|
+
* @returns {number | null} xxHash-32 checksum or null if not found
|
|
56
|
+
*/
|
|
57
|
+
getDataChecksum(path: string): number | null
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Builder for creating bundle files.
|
|
62
|
+
*
|
|
63
|
+
* Allows you to add files, set options, and generate a complete bundle.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* const builder = new BundleBuilder();
|
|
68
|
+
*
|
|
69
|
+
* // Add files
|
|
70
|
+
* builder.insertEntry("/index.html", Buffer.from("<html>...</html>"));
|
|
71
|
+
* builder.insertEntry("/app.js", Buffer.from("console.log('hello');"));
|
|
72
|
+
*
|
|
73
|
+
* // Build the bundle
|
|
74
|
+
* const bundle = builder.build();
|
|
75
|
+
*
|
|
76
|
+
* // Write to file
|
|
77
|
+
* await writeBundle(bundle, "app.wvb");
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export declare class BundleBuilder {
|
|
81
|
+
/**
|
|
82
|
+
* Creates a new bundle builder.
|
|
83
|
+
*
|
|
84
|
+
* @param {Version} [version] - Bundle format version (defaults to V1)
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* const builder = new BundleBuilder();
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
constructor(version?: Version | undefined | null)
|
|
92
|
+
/**
|
|
93
|
+
* Gets the bundle format version.
|
|
94
|
+
*
|
|
95
|
+
* @returns {Version} Bundle format version
|
|
96
|
+
*/
|
|
97
|
+
get version(): Version
|
|
98
|
+
/**
|
|
99
|
+
* Returns all entry paths currently in the builder.
|
|
100
|
+
*
|
|
101
|
+
* @returns {string[]} Array of file paths
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* ```typescript
|
|
105
|
+
* const paths = builder.entryPaths();
|
|
106
|
+
* console.log(paths); // ["/index.html", "/app.js"]
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
entryPaths(): Array<string>
|
|
110
|
+
/**
|
|
111
|
+
* Adds or updates a file in the bundle.
|
|
112
|
+
*
|
|
113
|
+
* If `contentType` is not provided, it will be auto-detected from the file
|
|
114
|
+
* extension and content.
|
|
115
|
+
*
|
|
116
|
+
* @param {string} path - File path (must start with "/")
|
|
117
|
+
* @param {Buffer} data - File contents
|
|
118
|
+
* @param {string} [contentType] - MIME type (auto-detected if not provided)
|
|
119
|
+
* @param {Record<string, string>} [headers] - Optional HTTP headers
|
|
120
|
+
* @returns {boolean} True if a file was replaced, false if newly added
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```typescript
|
|
124
|
+
* // Auto-detect MIME type
|
|
125
|
+
* builder.insertEntry("/index.html", Buffer.from("<html></html>"));
|
|
126
|
+
*
|
|
127
|
+
* // Specify MIME type
|
|
128
|
+
* builder.insertEntry("/data.bin", buffer, "application/octet-stream");
|
|
129
|
+
*
|
|
130
|
+
* // With custom headers
|
|
131
|
+
* builder.insertEntry("/style.css", cssBuffer, "text/css", {
|
|
132
|
+
* "Cache-Control": "max-age=3600"
|
|
133
|
+
* });
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
insertEntry(path: string, data: Buffer, contentType?: string | undefined | null, headers?: Record<string, string> | undefined | null): boolean
|
|
137
|
+
/**
|
|
138
|
+
* Removes a file from the bundle.
|
|
139
|
+
*
|
|
140
|
+
* @param {string} path - File path to remove
|
|
141
|
+
* @returns {boolean} True if the file was removed, false if not found
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```typescript
|
|
145
|
+
* builder.removeEntry("/old-file.js");
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
removeEntry(path: string): boolean
|
|
149
|
+
/**
|
|
150
|
+
* Checks if a file path exists in the builder.
|
|
151
|
+
*
|
|
152
|
+
* @param {string} path - File path to check
|
|
153
|
+
* @returns {boolean} True if the path exists
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```typescript
|
|
157
|
+
* if (builder.containsEntry("/index.html")) {
|
|
158
|
+
* console.log("index.html already added");
|
|
159
|
+
* }
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
162
|
+
containsEntry(path: string): boolean
|
|
163
|
+
/**
|
|
164
|
+
* Builds the bundle with all added files.
|
|
165
|
+
*
|
|
166
|
+
* This consumes the builder's entries and creates a complete bundle with
|
|
167
|
+
* compressed data.
|
|
168
|
+
*
|
|
169
|
+
* @param {BuildOptions} [options] - Build options
|
|
170
|
+
* @returns {Bundle} The built bundle
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```typescript
|
|
174
|
+
* const bundle = builder.build();
|
|
175
|
+
* await writeBundle(bundle, "output.wvb");
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
build(options?: BuildOptions | undefined | null): Bundle
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Bundle metadata including header and index information.
|
|
183
|
+
*
|
|
184
|
+
* A descriptor contains only the metadata without loading the actual file data,
|
|
185
|
+
* making it efficient for inspecting bundle contents.
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* ```typescript
|
|
189
|
+
* const bundle = await readBundle("app.wvb");
|
|
190
|
+
* const descriptor = bundle.descriptor();
|
|
191
|
+
* const header = descriptor.header();
|
|
192
|
+
* const index = descriptor.index();
|
|
193
|
+
* ```
|
|
194
|
+
*/
|
|
195
|
+
export declare class BundleDescriptor {
|
|
196
|
+
/**
|
|
197
|
+
* Returns the bundle header.
|
|
198
|
+
*
|
|
199
|
+
* @returns {Header} Bundle header with format metadata
|
|
200
|
+
*/
|
|
201
|
+
header(): Header
|
|
202
|
+
/**
|
|
203
|
+
* Returns the bundle index.
|
|
204
|
+
*
|
|
205
|
+
* @returns {Index} Bundle index with file metadata
|
|
206
|
+
*/
|
|
207
|
+
index(): Index
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Protocol handler for serving files from bundle sources.
|
|
212
|
+
*
|
|
213
|
+
* Serves web resources from `.wvb` bundle files, supporting:
|
|
214
|
+
* - GET and HEAD HTTP methods
|
|
215
|
+
* - HTTP Range requests for streaming
|
|
216
|
+
* - Content-Type and custom HTTP headers
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* ```typescript
|
|
220
|
+
* const source = new BundleSource({
|
|
221
|
+
* builtinDir: "./bundles/builtin",
|
|
222
|
+
* remoteDir: "./bundles/remote"
|
|
223
|
+
* });
|
|
224
|
+
*
|
|
225
|
+
* const protocol = new BundleProtocol(source);
|
|
226
|
+
*
|
|
227
|
+
* // Handle a request
|
|
228
|
+
* const response = await protocol.handle("GET", "bundle://app/index.html");
|
|
229
|
+
* console.log(`Status: ${response.status}`);
|
|
230
|
+
* console.log(`Content-Type: ${response.headers["content-type"]}`);
|
|
231
|
+
* ```
|
|
232
|
+
*/
|
|
233
|
+
export declare class BundleProtocol {
|
|
234
|
+
/**
|
|
235
|
+
* Creates a new bundle protocol handler.
|
|
236
|
+
*
|
|
237
|
+
* @param {BundleSource} source - Bundle source to serve files from
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* ```typescript
|
|
241
|
+
* const source = new BundleSource({
|
|
242
|
+
* builtinDir: "./bundles",
|
|
243
|
+
* remoteDir: "./remote"
|
|
244
|
+
* });
|
|
245
|
+
* const protocol = new BundleProtocol(source);
|
|
246
|
+
* ```
|
|
247
|
+
*/
|
|
248
|
+
constructor(source: BundleSource)
|
|
249
|
+
/**
|
|
250
|
+
* Handles an HTTP request and returns a response.
|
|
251
|
+
*
|
|
252
|
+
* Processes requests in the format `scheme://bundle_name/path/to/file`.
|
|
253
|
+
*
|
|
254
|
+
* @param {HttpMethod} method - HTTP method (GET or HEAD)
|
|
255
|
+
* @param {string} uri - Request URI (e.g., "bundle://app/index.html")
|
|
256
|
+
* @param {Record<string, string>} [headers] - Optional request headers
|
|
257
|
+
* @returns {Promise<HttpResponse>} HTTP response
|
|
258
|
+
*
|
|
259
|
+
* @example
|
|
260
|
+
* ```typescript
|
|
261
|
+
* // GET request
|
|
262
|
+
* const response = await protocol.handle("GET", "bundle://app/index.html");
|
|
263
|
+
* if (response.status === 200) {
|
|
264
|
+
* console.log(response.body.toString("utf-8"));
|
|
265
|
+
* }
|
|
266
|
+
* ```
|
|
267
|
+
*
|
|
268
|
+
* @example
|
|
269
|
+
* ```typescript
|
|
270
|
+
* // Range request for streaming
|
|
271
|
+
* const response = await protocol.handle(
|
|
272
|
+
* "GET",
|
|
273
|
+
* "bundle://app/video.mp4",
|
|
274
|
+
* { "Range": "bytes=0-1023" }
|
|
275
|
+
* );
|
|
276
|
+
* console.log(`Status: ${response.status}`); // 206 Partial Content
|
|
277
|
+
* ```
|
|
278
|
+
*/
|
|
279
|
+
handle(method: HttpMethod, uri: string, headers?: Record<string, string> | undefined | null): Promise<HttpResponse>
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Bundle source for managing multiple bundle versions.
|
|
284
|
+
*
|
|
285
|
+
* A source manages bundles in two directories:
|
|
286
|
+
* - **builtin**: Bundles shipped with the app (read-only, fallback)
|
|
287
|
+
* - **remote**: Downloaded bundles (takes priority)
|
|
288
|
+
*
|
|
289
|
+
* The source automatically handles version selection, with remote bundles
|
|
290
|
+
* taking priority over builtin ones.
|
|
291
|
+
*
|
|
292
|
+
* @example
|
|
293
|
+
* ```typescript
|
|
294
|
+
* const source = new BundleSource({
|
|
295
|
+
* builtinDir: "./bundles/builtin",
|
|
296
|
+
* remoteDir: "./bundles/remote"
|
|
297
|
+
* });
|
|
298
|
+
*
|
|
299
|
+
* // List all bundles
|
|
300
|
+
* const bundles = await source.listBundles();
|
|
301
|
+
*
|
|
302
|
+
* // Load current version
|
|
303
|
+
* const version = await source.loadVersion("app");
|
|
304
|
+
*
|
|
305
|
+
* // Fetch bundle
|
|
306
|
+
* const bundle = await source.fetch("app");
|
|
307
|
+
* ```
|
|
308
|
+
*/
|
|
309
|
+
export declare class BundleSource {
|
|
310
|
+
/**
|
|
311
|
+
* Creates a new bundle source.
|
|
312
|
+
*
|
|
313
|
+
* @param {BundleSourceConfig} config - Source configuration
|
|
314
|
+
*
|
|
315
|
+
* @example
|
|
316
|
+
* ```typescript
|
|
317
|
+
* const source = new BundleSource({
|
|
318
|
+
* builtinDir: "./builtin",
|
|
319
|
+
* remoteDir: "./remote"
|
|
320
|
+
* });
|
|
321
|
+
* ```
|
|
322
|
+
*/
|
|
323
|
+
constructor(config: BundleSourceConfig)
|
|
324
|
+
/**
|
|
325
|
+
* Lists all available bundles from both sources.
|
|
326
|
+
*
|
|
327
|
+
* Returns bundles from both builtin and remote directories, including
|
|
328
|
+
* all versions and metadata.
|
|
329
|
+
*
|
|
330
|
+
* @returns {Promise<ListBundleItem[]>} List of bundle items
|
|
331
|
+
*
|
|
332
|
+
* @example
|
|
333
|
+
* ```typescript
|
|
334
|
+
* const bundles = await source.listBundles();
|
|
335
|
+
* for (const bundle of bundles) {
|
|
336
|
+
* console.log(`${bundle.name}@${bundle.version} (${bundle.type})`);
|
|
337
|
+
* }
|
|
338
|
+
* ```
|
|
339
|
+
*/
|
|
340
|
+
listBundles(): Promise<Array<ListBundleItem>>
|
|
341
|
+
/**
|
|
342
|
+
* Loads the current version for a bundle.
|
|
343
|
+
*
|
|
344
|
+
* Returns the version from remote if available, otherwise from builtin.
|
|
345
|
+
*
|
|
346
|
+
* @param {string} bundleName - Name of the bundle
|
|
347
|
+
* @returns {Promise<BundleSourceVersion | null>} Version info or null if not found
|
|
348
|
+
*
|
|
349
|
+
* @example
|
|
350
|
+
* ```typescript
|
|
351
|
+
* const version = await source.loadVersion("app");
|
|
352
|
+
* if (version) {
|
|
353
|
+
* console.log(`Current version: ${version.version} (${version.type})`);
|
|
354
|
+
* }
|
|
355
|
+
* ```
|
|
356
|
+
*/
|
|
357
|
+
loadVersion(bundleName: string): Promise<BundleSourceVersion | null>
|
|
358
|
+
/**
|
|
359
|
+
* Updates the current version for a bundle.
|
|
360
|
+
*
|
|
361
|
+
* Changes which version is considered "current" in the manifest.
|
|
362
|
+
*
|
|
363
|
+
* @param {string} bundleName - Name of the bundle
|
|
364
|
+
* @param {string} version - Version to set as current
|
|
365
|
+
*
|
|
366
|
+
* @example
|
|
367
|
+
* ```typescript
|
|
368
|
+
* await source.updateVersion("app", "1.2.0");
|
|
369
|
+
* ```
|
|
370
|
+
*/
|
|
371
|
+
updateVersion(bundleName: string, version: string): Promise<void>
|
|
372
|
+
/**
|
|
373
|
+
* Gets the file path for a bundle.
|
|
374
|
+
*
|
|
375
|
+
* Returns the path to the `.wvb` file for the current version,
|
|
376
|
+
* preferring remote over builtin.
|
|
377
|
+
*
|
|
378
|
+
* @param {string} bundleName - Name of the bundle
|
|
379
|
+
* @returns {Promise<string>} Absolute file path
|
|
380
|
+
*
|
|
381
|
+
* @example
|
|
382
|
+
* ```typescript
|
|
383
|
+
* const path = await source.filepath("app");
|
|
384
|
+
* console.log(`Bundle at: ${path}`);
|
|
385
|
+
* ```
|
|
386
|
+
*/
|
|
387
|
+
filepath(bundleName: string): Promise<string>
|
|
388
|
+
/**
|
|
389
|
+
* Fetches and loads a bundle.
|
|
390
|
+
*
|
|
391
|
+
* Loads the entire bundle into memory for the current version.
|
|
392
|
+
*
|
|
393
|
+
* @param {string} bundleName - Name of the bundle
|
|
394
|
+
* @returns {Promise<Bundle>} Loaded bundle
|
|
395
|
+
*
|
|
396
|
+
* @example
|
|
397
|
+
* ```typescript
|
|
398
|
+
* const bundle = await source.fetch("app");
|
|
399
|
+
* const html = bundle.getData("/index.html");
|
|
400
|
+
* ```
|
|
401
|
+
*/
|
|
402
|
+
fetch(bundleName: string): Promise<Bundle>
|
|
403
|
+
/**
|
|
404
|
+
* Fetches only the bundle descriptor (metadata).
|
|
405
|
+
*
|
|
406
|
+
* Loads only header and index without file data, useful for inspection.
|
|
407
|
+
*
|
|
408
|
+
* @param {string} bundleName - Name of the bundle
|
|
409
|
+
* @returns {Promise<BundleDescriptor>} Bundle descriptor
|
|
410
|
+
*
|
|
411
|
+
* @example
|
|
412
|
+
* ```typescript
|
|
413
|
+
* const descriptor = await source.fetchDescriptor("app");
|
|
414
|
+
* const index = descriptor.index();
|
|
415
|
+
* console.log(`Files: ${Object.keys(index.entries()).length}`);
|
|
416
|
+
* ```
|
|
417
|
+
*/
|
|
418
|
+
fetchDescriptor(bundleName: string): Promise<BundleDescriptor>
|
|
419
|
+
/**
|
|
420
|
+
* Writes a bundle to the remote directory.
|
|
421
|
+
*
|
|
422
|
+
* Installs a new bundle version to the remote directory and updates
|
|
423
|
+
* the manifest.
|
|
424
|
+
*
|
|
425
|
+
* @param {string} bundleName - Name of the bundle
|
|
426
|
+
* @param {string} version - Version string
|
|
427
|
+
* @param {Bundle} bundle - Bundle to write
|
|
428
|
+
* @param {BundleManifestMetadata} metadata - Bundle metadata
|
|
429
|
+
*
|
|
430
|
+
* @example
|
|
431
|
+
* ```typescript
|
|
432
|
+
* await source.writeRemoteBundle("app", "1.2.0", bundle, {
|
|
433
|
+
* integrity: "sha3-384-...",
|
|
434
|
+
* etag: "abc123"
|
|
435
|
+
* });
|
|
436
|
+
* ```
|
|
437
|
+
*/
|
|
438
|
+
writeRemoteBundle(bundleName: string, version: string, bundle: Bundle, metadata: BundleManifestMetadata): Promise<void>
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Bundle header containing format metadata.
|
|
443
|
+
*
|
|
444
|
+
* The header is the first 17 bytes of a `.wvb` file and includes:
|
|
445
|
+
* - Magic number (🌐🎁)
|
|
446
|
+
* - Format version
|
|
447
|
+
* - Index size
|
|
448
|
+
* - Header checksum
|
|
449
|
+
*/
|
|
450
|
+
export declare class Header {
|
|
451
|
+
/**
|
|
452
|
+
* Returns the bundle format version.
|
|
453
|
+
*
|
|
454
|
+
* @returns {Version} The format version (e.g., V1)
|
|
455
|
+
*
|
|
456
|
+
* @example
|
|
457
|
+
* ```typescript
|
|
458
|
+
* const header = bundle.descriptor().header();
|
|
459
|
+
* console.log(header.version()); // Version.V1
|
|
460
|
+
* ```
|
|
461
|
+
*/
|
|
462
|
+
version(): Version
|
|
463
|
+
/**
|
|
464
|
+
* Returns the byte offset where the index section ends.
|
|
465
|
+
*
|
|
466
|
+
* This marks the start of the data section.
|
|
467
|
+
*
|
|
468
|
+
* @returns {bigint} Byte offset
|
|
469
|
+
*/
|
|
470
|
+
indexEndOffset(): bigint
|
|
471
|
+
/**
|
|
472
|
+
* Returns the size of the index section in bytes.
|
|
473
|
+
*
|
|
474
|
+
* @returns {number} Index size in bytes
|
|
475
|
+
*/
|
|
476
|
+
indexSize(): number
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Bundle index mapping file paths to their metadata.
|
|
481
|
+
*
|
|
482
|
+
* The index is stored as binary data in the bundle file and maps file paths
|
|
483
|
+
* to their metadata (offset, length, content-type, headers, etc.).
|
|
484
|
+
*/
|
|
485
|
+
export declare class Index {
|
|
486
|
+
/**
|
|
487
|
+
* Returns all index entries as a map of path to metadata.
|
|
488
|
+
*
|
|
489
|
+
* @returns {Record<string, IndexEntry>} Map of file paths to entry metadata
|
|
490
|
+
*
|
|
491
|
+
* @example
|
|
492
|
+
* ```typescript
|
|
493
|
+
* const index = bundle.descriptor().index();
|
|
494
|
+
* const entries = index.entries();
|
|
495
|
+
* for (const [path, entry] of Object.entries(entries)) {
|
|
496
|
+
* console.log(`${path}: ${entry.contentType}`);
|
|
497
|
+
* }
|
|
498
|
+
* ```
|
|
499
|
+
*/
|
|
500
|
+
entries(): Record<string, IndexEntry>
|
|
501
|
+
/**
|
|
502
|
+
* Gets the index entry for a specific file path.
|
|
503
|
+
*
|
|
504
|
+
* @param {string} path - File path in the bundle (e.g., "/index.html")
|
|
505
|
+
* @returns {IndexEntry | null} Entry metadata or null if not found
|
|
506
|
+
*
|
|
507
|
+
* @example
|
|
508
|
+
* ```typescript
|
|
509
|
+
* const entry = index.getEntry("/index.html");
|
|
510
|
+
* if (entry) {
|
|
511
|
+
* console.log(`Content-Type: ${entry.contentType}`);
|
|
512
|
+
* }
|
|
513
|
+
* ```
|
|
514
|
+
*/
|
|
515
|
+
getEntry(path: string): IndexEntry | null
|
|
516
|
+
/**
|
|
517
|
+
* Checks if a file path exists in the bundle.
|
|
518
|
+
*
|
|
519
|
+
* @param {string} path - File path to check
|
|
520
|
+
* @returns {boolean} True if the path exists
|
|
521
|
+
*
|
|
522
|
+
* @example
|
|
523
|
+
* ```typescript
|
|
524
|
+
* if (index.containsPath("/app.js")) {
|
|
525
|
+
* console.log("app.js is in the bundle");
|
|
526
|
+
* }
|
|
527
|
+
* ```
|
|
528
|
+
*/
|
|
529
|
+
containsPath(path: string): boolean
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* Protocol handler that proxies requests to localhost servers.
|
|
534
|
+
*
|
|
535
|
+
* Forwards requests to local development servers for hot-reloading workflows.
|
|
536
|
+
* Features response caching and 304 Not Modified support.
|
|
537
|
+
*
|
|
538
|
+
* @example
|
|
539
|
+
* ```typescript
|
|
540
|
+
* const protocol = new LocalProtocol({
|
|
541
|
+
* "myapp": "http://localhost:3000",
|
|
542
|
+
* "api": "http://localhost:8080"
|
|
543
|
+
* });
|
|
544
|
+
*
|
|
545
|
+
* // This proxies to http://localhost:3000/index.html
|
|
546
|
+
* const response = await protocol.handle("GET", "app://myapp/index.html");
|
|
547
|
+
* ```
|
|
548
|
+
*/
|
|
549
|
+
export declare class LocalProtocol {
|
|
550
|
+
/**
|
|
551
|
+
* Creates a new local protocol handler.
|
|
552
|
+
*
|
|
553
|
+
* @param {Record<string, string>} hosts - Map of custom hosts to localhost URLs
|
|
554
|
+
*
|
|
555
|
+
* @example
|
|
556
|
+
* ```typescript
|
|
557
|
+
* const protocol = new LocalProtocol({
|
|
558
|
+
* "myapp": "http://localhost:3000",
|
|
559
|
+
* "api": "http://localhost:8080"
|
|
560
|
+
* });
|
|
561
|
+
* ```
|
|
562
|
+
*/
|
|
563
|
+
constructor(hosts: Record<string, string>)
|
|
564
|
+
/**
|
|
565
|
+
* Handles an HTTP request by proxying to localhost.
|
|
566
|
+
*
|
|
567
|
+
* Maps custom protocol URIs to localhost URLs and forwards the request.
|
|
568
|
+
*
|
|
569
|
+
* @param {HttpMethod} method - HTTP method
|
|
570
|
+
* @param {string} uri - Request URI (e.g., "app://myapp/api/data")
|
|
571
|
+
* @param {Record<string, string>} [headers] - Optional request headers
|
|
572
|
+
* @returns {Promise<HttpResponse>} HTTP response from localhost
|
|
573
|
+
*
|
|
574
|
+
* @example
|
|
575
|
+
* ```typescript
|
|
576
|
+
* // Proxies to http://localhost:3000/api/data?foo=bar
|
|
577
|
+
* const response = await protocol.handle(
|
|
578
|
+
* "GET",
|
|
579
|
+
* "app://myapp/api/data?foo=bar"
|
|
580
|
+
* );
|
|
581
|
+
* console.log(response.status);
|
|
582
|
+
* ```
|
|
583
|
+
*
|
|
584
|
+
* @example
|
|
585
|
+
* ```typescript
|
|
586
|
+
* // POST with headers
|
|
587
|
+
* const response = await protocol.handle(
|
|
588
|
+
* "POST",
|
|
589
|
+
* "app://api/submit",
|
|
590
|
+
* { "Content-Type": "application/json" }
|
|
591
|
+
* );
|
|
592
|
+
* ```
|
|
593
|
+
*/
|
|
594
|
+
handle(method: HttpMethod, uri: string, headers?: Record<string, string> | undefined | null): Promise<HttpResponse>
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/**
|
|
598
|
+
* HTTP client for downloading bundles from a remote server.
|
|
599
|
+
*
|
|
600
|
+
* The remote client implements the bundle HTTP protocol, allowing you to:
|
|
601
|
+
* - List available bundles
|
|
602
|
+
* - Get bundle metadata
|
|
603
|
+
* - Download specific versions
|
|
604
|
+
* - Track download progress
|
|
605
|
+
*
|
|
606
|
+
* @example
|
|
607
|
+
* ```typescript
|
|
608
|
+
* const remote = new Remote("https://updates.example.com");
|
|
609
|
+
*
|
|
610
|
+
* // List all bundles
|
|
611
|
+
* const bundles = await remote.listBundles();
|
|
612
|
+
*
|
|
613
|
+
* // Get current version info
|
|
614
|
+
* const info = await remote.getInfo("app");
|
|
615
|
+
* console.log(`Latest version: ${info.version}`);
|
|
616
|
+
*
|
|
617
|
+
* // Download bundle
|
|
618
|
+
* const [bundleInfo, bundle, data] = await remote.download("app");
|
|
619
|
+
* ```
|
|
620
|
+
*/
|
|
621
|
+
export declare class Remote {
|
|
622
|
+
/**
|
|
623
|
+
* Creates a new remote client.
|
|
624
|
+
*
|
|
625
|
+
* @param {string} endpoint - Base URL of the remote server
|
|
626
|
+
* @param {RemoteOptions} [options] - Client options
|
|
627
|
+
*
|
|
628
|
+
* @example
|
|
629
|
+
* ```typescript
|
|
630
|
+
* const remote = new Remote("https://updates.example.com");
|
|
631
|
+
* ```
|
|
632
|
+
*
|
|
633
|
+
* @example
|
|
634
|
+
* ```typescript
|
|
635
|
+
* // With options
|
|
636
|
+
* const remote = new Remote("https://updates.example.com", {
|
|
637
|
+
* http: { timeout: 60000 },
|
|
638
|
+
* onDownload: (data) => {
|
|
639
|
+
* const percent = (data.downloadedBytes / data.totalBytes) * 100;
|
|
640
|
+
* console.log(`Progress: ${percent.toFixed(1)}%`);
|
|
641
|
+
* }
|
|
642
|
+
* });
|
|
643
|
+
* ```
|
|
644
|
+
*/
|
|
645
|
+
constructor(endpoint: string, options?: RemoteOptions | undefined | null)
|
|
646
|
+
/**
|
|
647
|
+
* Lists all available bundles on the server.
|
|
648
|
+
*
|
|
649
|
+
* @param {string} [channel] - Optional channel filter
|
|
650
|
+
* @returns {Promise<ListRemoteBundleInfo[]>} List of bundles
|
|
651
|
+
*
|
|
652
|
+
* @example
|
|
653
|
+
* ```typescript
|
|
654
|
+
* const bundles = await remote.listBundles();
|
|
655
|
+
* for (const bundle of bundles) {
|
|
656
|
+
* console.log(`${bundle.name}@${bundle.version}`);
|
|
657
|
+
* }
|
|
658
|
+
* ```
|
|
659
|
+
*/
|
|
660
|
+
listBundles(channel?: string | undefined | null): Promise<Array<ListRemoteBundleInfo>>
|
|
661
|
+
/**
|
|
662
|
+
* Gets bundle metadata for the current version.
|
|
663
|
+
*
|
|
664
|
+
* Fetches metadata without downloading the bundle itself.
|
|
665
|
+
*
|
|
666
|
+
* @param {string} bundleName - Name of the bundle
|
|
667
|
+
* @param {string} [channel] - Optional channel filter
|
|
668
|
+
* @returns {Promise<RemoteBundleInfo>} Bundle information
|
|
669
|
+
*
|
|
670
|
+
* @example
|
|
671
|
+
* ```typescript
|
|
672
|
+
* const info = await remote.getInfo("app");
|
|
673
|
+
* console.log(`Current version: ${info.version}`);
|
|
674
|
+
* if (info.integrity) {
|
|
675
|
+
* console.log(`Integrity: ${info.integrity}`);
|
|
676
|
+
* }
|
|
677
|
+
* ```
|
|
678
|
+
*/
|
|
679
|
+
getInfo(bundleName: string, channel?: string | undefined | null): Promise<RemoteBundleInfo>
|
|
680
|
+
/**
|
|
681
|
+
* Downloads the current version of a bundle.
|
|
682
|
+
*
|
|
683
|
+
* Returns bundle info, parsed bundle, and raw data.
|
|
684
|
+
*
|
|
685
|
+
* @param {string} bundleName - Name of the bundle
|
|
686
|
+
* @param {string} [channel] - Optional channel filter
|
|
687
|
+
* @returns {Promise<[RemoteBundleInfo, Bundle, Buffer]>} Tuple of info, bundle, and data
|
|
688
|
+
*
|
|
689
|
+
* @example
|
|
690
|
+
* ```typescript
|
|
691
|
+
* const [info, bundle, data] = await remote.download("app");
|
|
692
|
+
* console.log(`Downloaded ${info.name}@${info.version}`);
|
|
693
|
+
* console.log(`Size: ${data.length} bytes`);
|
|
694
|
+
*
|
|
695
|
+
* // Save to file
|
|
696
|
+
* await writeBundle(bundle, "app.wvb");
|
|
697
|
+
* ```
|
|
698
|
+
*/
|
|
699
|
+
download(bundleName: string, channel?: string | undefined | null): Promise<[RemoteBundleInfo, Bundle, Buffer]>
|
|
700
|
+
/**
|
|
701
|
+
* Downloads a specific version of a bundle.
|
|
702
|
+
*
|
|
703
|
+
* @param {string} bundleName - Name of the bundle
|
|
704
|
+
* @param {string} version - Specific version to download
|
|
705
|
+
* @returns {Promise<[RemoteBundleInfo, Bundle, Buffer]>} Tuple of info, bundle, and data
|
|
706
|
+
*
|
|
707
|
+
* @example
|
|
708
|
+
* ```typescript
|
|
709
|
+
* const [info, bundle, data] = await remote.downloadVersion("app", "1.0.0");
|
|
710
|
+
* console.log(`Downloaded specific version: ${info.version}`);
|
|
711
|
+
* ```
|
|
712
|
+
*/
|
|
713
|
+
downloadVersion(bundleName: string, version: string): Promise<[RemoteBundleInfo, Bundle, Buffer]>
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
/**
|
|
717
|
+
* Bundle updater for managing updates from a remote server.
|
|
718
|
+
*
|
|
719
|
+
* The updater coordinates between a local bundle source and remote server,
|
|
720
|
+
* handling update checks, downloads, integrity verification, and signature validation.
|
|
721
|
+
*
|
|
722
|
+
* @example
|
|
723
|
+
* ```typescript
|
|
724
|
+
* import { Updater, BundleSource, Remote, IntegrityPolicy, SignatureAlgorithm, VerifyingKeyFormat } from "@wvb/node";
|
|
725
|
+
*
|
|
726
|
+
* const source = new BundleSource({
|
|
727
|
+
* builtinDir: "./bundles/builtin",
|
|
728
|
+
* remoteDir: "./bundles/remote"
|
|
729
|
+
* });
|
|
730
|
+
*
|
|
731
|
+
* const remote = new Remote("https://updates.example.com");
|
|
732
|
+
*
|
|
733
|
+
* const updater = new Updater(source, remote, {
|
|
734
|
+
* channel: "stable",
|
|
735
|
+
* integrityPolicy: IntegrityPolicy.Strict,
|
|
736
|
+
* signatureVerifier: {
|
|
737
|
+
* algorithm: SignatureAlgorithm.Ed25519,
|
|
738
|
+
* key: {
|
|
739
|
+
* format: VerifyingKeyFormat.SpkiPem,
|
|
740
|
+
* data: publicKeyPem
|
|
741
|
+
* }
|
|
742
|
+
* }
|
|
743
|
+
* });
|
|
744
|
+
*
|
|
745
|
+
* // Check for updates
|
|
746
|
+
* const updateInfo = await updater.getUpdate("app");
|
|
747
|
+
* if (updateInfo.isAvailable) {
|
|
748
|
+
* console.log(`Update available: ${updateInfo.version}`);
|
|
749
|
+
* await updater.downloadUpdate("app");
|
|
750
|
+
* }
|
|
751
|
+
* ```
|
|
752
|
+
*/
|
|
753
|
+
export declare class Updater {
|
|
754
|
+
/**
|
|
755
|
+
* Creates a new updater instance.
|
|
756
|
+
*
|
|
757
|
+
* @param {BundleSource} source - Bundle source for storing downloaded bundles
|
|
758
|
+
* @param {Remote} remote - Remote client for fetching bundles
|
|
759
|
+
* @param {UpdaterOptions} [options] - Optional updater configuration
|
|
760
|
+
*
|
|
761
|
+
* @example
|
|
762
|
+
* ```typescript
|
|
763
|
+
* const updater = new Updater(source, remote, {
|
|
764
|
+
* channel: "stable",
|
|
765
|
+
* integrityPolicy: IntegrityPolicy.Strict
|
|
766
|
+
* });
|
|
767
|
+
* ```
|
|
768
|
+
*/
|
|
769
|
+
constructor(source: BundleSource, remote: Remote, options?: UpdaterOptions | undefined | null)
|
|
770
|
+
/**
|
|
771
|
+
* Lists all available bundles on the remote server.
|
|
772
|
+
*
|
|
773
|
+
* @returns {Promise<ListRemoteBundleInfo[]>} Array of remote bundle information
|
|
774
|
+
*
|
|
775
|
+
* @example
|
|
776
|
+
* ```typescript
|
|
777
|
+
* const remotes = await updater.listRemotes();
|
|
778
|
+
* for (const bundle of remotes) {
|
|
779
|
+
* console.log(`${bundle.name}: ${bundle.version}`);
|
|
780
|
+
* }
|
|
781
|
+
* ```
|
|
782
|
+
*/
|
|
783
|
+
listRemotes(): Promise<Array<ListRemoteBundleInfo>>
|
|
784
|
+
/**
|
|
785
|
+
* Checks if an update is available for a specific bundle.
|
|
786
|
+
*
|
|
787
|
+
* Compares the local version with the remote version to determine if an update exists.
|
|
788
|
+
*
|
|
789
|
+
* @param {string} bundleName - Name of the bundle to check
|
|
790
|
+
* @returns {Promise<BundleUpdateInfo>} Update information
|
|
791
|
+
*
|
|
792
|
+
* @example
|
|
793
|
+
* ```typescript
|
|
794
|
+
* const updateInfo = await updater.getUpdate("app");
|
|
795
|
+
* if (updateInfo.isAvailable) {
|
|
796
|
+
* console.log(`Update available: ${updateInfo.localVersion} → ${updateInfo.version}`);
|
|
797
|
+
* } else {
|
|
798
|
+
* console.log("Already up to date");
|
|
799
|
+
* }
|
|
800
|
+
* ```
|
|
801
|
+
*/
|
|
802
|
+
getUpdate(bundleName: string): Promise<BundleUpdateInfo>
|
|
803
|
+
/**
|
|
804
|
+
* Downloads and installs a bundle update.
|
|
805
|
+
*
|
|
806
|
+
* Downloads the specified bundle version (or the latest if not specified),
|
|
807
|
+
* verifies integrity and signature if configured, and installs it to the remote directory.
|
|
808
|
+
*
|
|
809
|
+
* @param {string} bundleName - Name of the bundle to download
|
|
810
|
+
* @param {string} [version] - Specific version to download (defaults to latest)
|
|
811
|
+
* @returns {Promise<RemoteBundleInfo>} Information about the downloaded bundle
|
|
812
|
+
*
|
|
813
|
+
* @example
|
|
814
|
+
* ```typescript
|
|
815
|
+
* // Download latest version
|
|
816
|
+
* const info = await updater.downloadUpdate("app");
|
|
817
|
+
* console.log(`Downloaded ${info.name} v${info.version}`);
|
|
818
|
+
* ```
|
|
819
|
+
*
|
|
820
|
+
* @example
|
|
821
|
+
* ```typescript
|
|
822
|
+
* // Download specific version
|
|
823
|
+
* const info = await updater.downloadUpdate("app", "1.2.3");
|
|
824
|
+
* console.log(`Downloaded ${info.name} v${info.version}`);
|
|
825
|
+
* ```
|
|
826
|
+
*/
|
|
827
|
+
downloadUpdate(bundleName: string, version?: string | undefined | null): Promise<RemoteBundleInfo>
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
/**
|
|
831
|
+
* Options for bundle header generation.
|
|
832
|
+
*
|
|
833
|
+
* @property {number} [checksumSeed] - Seed for header checksum (for testing)
|
|
834
|
+
*/
|
|
835
|
+
export interface BuildHeaderOptions {
|
|
836
|
+
checksumSeed?: number
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
/**
|
|
840
|
+
* Options for bundle index generation.
|
|
841
|
+
*
|
|
842
|
+
* @property {number} [checksumSeed] - Seed for index checksum (for testing)
|
|
843
|
+
*/
|
|
844
|
+
export interface BuildIndexOptions {
|
|
845
|
+
checksumSeed?: number
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
/**
|
|
849
|
+
* Options for building a bundle.
|
|
850
|
+
*
|
|
851
|
+
* @property {BuildHeaderOptions} [header] - Header generation options
|
|
852
|
+
* @property {BuildIndexOptions} [index] - Index generation options
|
|
853
|
+
* @property {number} [dataChecksumSeed] - Seed for data checksums (for testing)
|
|
854
|
+
*/
|
|
855
|
+
export interface BuildOptions {
|
|
856
|
+
header?: BuildHeaderOptions
|
|
857
|
+
index?: BuildIndexOptions
|
|
858
|
+
dataChecksumSeed?: number
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
/**
|
|
862
|
+
* Complete manifest data structure.
|
|
863
|
+
*
|
|
864
|
+
* The manifest tracks all bundle versions and metadata.
|
|
865
|
+
*
|
|
866
|
+
* @property {1} manifestVersion - Manifest format version (always 1)
|
|
867
|
+
* @property {Record<string, BundleManifestEntry>} entries - Bundle entries by name
|
|
868
|
+
*/
|
|
869
|
+
export interface BundleManifestData {
|
|
870
|
+
manifestVersion: 1
|
|
871
|
+
entries: Record<string, BundleManifestEntry>
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
/**
|
|
875
|
+
* Entry for a single bundle in the manifest.
|
|
876
|
+
*
|
|
877
|
+
* Contains all versions and the current active version.
|
|
878
|
+
*
|
|
879
|
+
* @property {Record<string, BundleManifestMetadata>} versions - Available versions
|
|
880
|
+
* @property {string} currentVersion - Currently active version
|
|
881
|
+
*/
|
|
882
|
+
export interface BundleManifestEntry {
|
|
883
|
+
versions: Record<string, BundleManifestMetadata>
|
|
884
|
+
currentVersion: string
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
/**
|
|
888
|
+
* Metadata for a bundle version in the manifest.
|
|
889
|
+
*
|
|
890
|
+
* Contains cache validation and integrity information.
|
|
891
|
+
*
|
|
892
|
+
* @property {string} [etag] - HTTP ETag for cache validation
|
|
893
|
+
* @property {string} [integrity] - SHA3 integrity hash for verification
|
|
894
|
+
* @property {string} [signature] - Digital signature for authentication
|
|
895
|
+
* @property {string} [lastModified] - HTTP Last-Modified timestamp
|
|
896
|
+
*/
|
|
897
|
+
export interface BundleManifestMetadata {
|
|
898
|
+
etag?: string
|
|
899
|
+
integrity?: string
|
|
900
|
+
signature?: string
|
|
901
|
+
lastModified?: string
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
/**
|
|
905
|
+
* Manifest format version.
|
|
906
|
+
*
|
|
907
|
+
* @enum {number}
|
|
908
|
+
*/
|
|
909
|
+
export declare enum BundleManifestVersion {
|
|
910
|
+
V1 = 1
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
/**
|
|
914
|
+
* Configuration for creating a bundle source.
|
|
915
|
+
*
|
|
916
|
+
* @property {string} builtinDir - Directory containing builtin bundles
|
|
917
|
+
* @property {string} remoteDir - Directory containing remote bundles
|
|
918
|
+
* @property {string} [builtinManifestFilepath] - Custom manifest path for builtin
|
|
919
|
+
* @property {string} [remoteManifestFilepath] - Custom manifest path for remote
|
|
920
|
+
*
|
|
921
|
+
* @example
|
|
922
|
+
* ```typescript
|
|
923
|
+
* const config = {
|
|
924
|
+
* builtinDir: "./bundles/builtin",
|
|
925
|
+
* remoteDir: "./bundles/remote"
|
|
926
|
+
* };
|
|
927
|
+
* const source = new BundleSource(config);
|
|
928
|
+
* ```
|
|
929
|
+
*/
|
|
930
|
+
export interface BundleSourceConfig {
|
|
931
|
+
builtinDir: string
|
|
932
|
+
remoteDir: string
|
|
933
|
+
builtinManifestFilepath?: string
|
|
934
|
+
remoteManifestFilepath?: string
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
/**
|
|
938
|
+
* The type of bundle source: builtin or remote.
|
|
939
|
+
*
|
|
940
|
+
* @enum {string}
|
|
941
|
+
*/
|
|
942
|
+
export type BundleSourceKind = /** Bundles shipped with the application (read-only| fallback) */
|
|
943
|
+
'builtin'|
|
|
944
|
+
/** Downloaded bundles (takes priority over builtin) */
|
|
945
|
+
'remote';
|
|
946
|
+
|
|
947
|
+
/**
|
|
948
|
+
* Bundle version with source kind information.
|
|
949
|
+
*
|
|
950
|
+
* Indicates which source (builtin or remote) provides a bundle version.
|
|
951
|
+
*
|
|
952
|
+
* @property {BundleSourceKind} type - The source kind
|
|
953
|
+
* @property {string} version - The version string (e.g., "1.0.0")
|
|
954
|
+
*/
|
|
955
|
+
export interface BundleSourceVersion {
|
|
956
|
+
type: BundleSourceKind
|
|
957
|
+
version: string
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
/**
|
|
961
|
+
* Information about a bundle update.
|
|
962
|
+
*
|
|
963
|
+
* @property {string} name - Bundle name
|
|
964
|
+
* @property {string} version - Remote version available
|
|
965
|
+
* @property {string} [localVersion] - Currently installed version
|
|
966
|
+
* @property {boolean} isAvailable - Whether an update is available
|
|
967
|
+
* @property {string} [etag] - ETag for caching
|
|
968
|
+
* @property {string} [integrity] - Integrity hash (e.g., "sha384-...")
|
|
969
|
+
* @property {string} [signature] - Digital signature
|
|
970
|
+
* @property {string} [lastModified] - Last modified timestamp
|
|
971
|
+
*
|
|
972
|
+
* @example
|
|
973
|
+
* ```typescript
|
|
974
|
+
* const updateInfo = await updater.getUpdate("app");
|
|
975
|
+
* if (updateInfo.isAvailable) {
|
|
976
|
+
* console.log(`Update available: ${updateInfo.localVersion} → ${updateInfo.version}`);
|
|
977
|
+
* await updater.downloadUpdate("app");
|
|
978
|
+
* }
|
|
979
|
+
* ```
|
|
980
|
+
*/
|
|
981
|
+
export interface BundleUpdateInfo {
|
|
982
|
+
name: string
|
|
983
|
+
version: string
|
|
984
|
+
localVersion?: string
|
|
985
|
+
isAvailable: boolean
|
|
986
|
+
etag?: string
|
|
987
|
+
integrity?: string
|
|
988
|
+
signature?: string
|
|
989
|
+
lastModified?: string
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
export type HttpMethod = 'get'|
|
|
993
|
+
'head'|
|
|
994
|
+
'options'|
|
|
995
|
+
'post'|
|
|
996
|
+
'put'|
|
|
997
|
+
'patch'|
|
|
998
|
+
'delete'|
|
|
999
|
+
'trace'|
|
|
1000
|
+
'connect';
|
|
1001
|
+
|
|
1002
|
+
export interface HttpOptions {
|
|
1003
|
+
defaultHeaders?: Record<string, string>
|
|
1004
|
+
userAgent?: string
|
|
1005
|
+
timeout?: number
|
|
1006
|
+
readTimeout?: number
|
|
1007
|
+
connectTimeout?: number
|
|
1008
|
+
poolIdleTimeout?: number
|
|
1009
|
+
poolMaxIdlePerHost?: number
|
|
1010
|
+
referer?: boolean
|
|
1011
|
+
tcpNodelay?: boolean
|
|
1012
|
+
hickoryDns?: boolean
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
export interface HttpResponse {
|
|
1016
|
+
status: number
|
|
1017
|
+
headers: Record<string, string>
|
|
1018
|
+
body: Buffer
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
/**
|
|
1022
|
+
* Metadata for a single file in the bundle.
|
|
1023
|
+
*
|
|
1024
|
+
* Contains information about file location, size, MIME type, and HTTP headers.
|
|
1025
|
+
*
|
|
1026
|
+
* @property {number} offset - Byte offset in the data section (compressed)
|
|
1027
|
+
* @property {number} len - Length of compressed data in bytes
|
|
1028
|
+
* @property {boolean} isEmpty - Whether the compressed data is empty
|
|
1029
|
+
* @property {string} contentType - MIME type of the file
|
|
1030
|
+
* @property {number} contentLength - Original file size before compression
|
|
1031
|
+
* @property {Record<string, string>} headers - HTTP headers for this file
|
|
1032
|
+
*/
|
|
1033
|
+
export interface IndexEntry {
|
|
1034
|
+
offset: number
|
|
1035
|
+
len: number
|
|
1036
|
+
isEmpty: boolean
|
|
1037
|
+
contentType: string
|
|
1038
|
+
contentLength: number
|
|
1039
|
+
headers: Record<string, string>
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
/**
|
|
1043
|
+
* Hash algorithm for bundle integrity verification.
|
|
1044
|
+
*
|
|
1045
|
+
* Supports SHA-2 family hash algorithms for cryptographic verification
|
|
1046
|
+
* following the Subresource Integrity specification.
|
|
1047
|
+
*
|
|
1048
|
+
* @example
|
|
1049
|
+
* ```typescript
|
|
1050
|
+
* // Integrity strings use these algorithms:
|
|
1051
|
+
* // "sha256-abc123..." - SHA-256
|
|
1052
|
+
* // "sha384-def456..." - SHA-384 (recommended)
|
|
1053
|
+
* // "sha512-ghi789..." - SHA-512
|
|
1054
|
+
* ```
|
|
1055
|
+
*/
|
|
1056
|
+
export type IntegrityAlgorithm = /** SHA-256 (256-bit hash) */
|
|
1057
|
+
'sha256'|
|
|
1058
|
+
/** SHA-384 (384-bit hash| recommended) */
|
|
1059
|
+
'sha384'|
|
|
1060
|
+
/** SHA-512 (512-bit hash) */
|
|
1061
|
+
'sha512';
|
|
1062
|
+
|
|
1063
|
+
/**
|
|
1064
|
+
* Policy for enforcing integrity verification during bundle operations.
|
|
1065
|
+
*
|
|
1066
|
+
* Controls when integrity hashes are required and how missing hashes are handled.
|
|
1067
|
+
*
|
|
1068
|
+
* @example
|
|
1069
|
+
* ```typescript
|
|
1070
|
+
* import { Updater, IntegrityPolicy } from "@wvb/node";
|
|
1071
|
+
*
|
|
1072
|
+
* // Require integrity for all bundles
|
|
1073
|
+
* const updater = new Updater(source, remote, {
|
|
1074
|
+
* integrityPolicy: IntegrityPolicy.Strict
|
|
1075
|
+
* });
|
|
1076
|
+
*
|
|
1077
|
+
* // Optional integrity (warn if missing)
|
|
1078
|
+
* const updater2 = new Updater(source, remote, {
|
|
1079
|
+
* integrityPolicy: IntegrityPolicy.Optional
|
|
1080
|
+
* });
|
|
1081
|
+
* ```
|
|
1082
|
+
*/
|
|
1083
|
+
export type IntegrityPolicy = /** Require integrity verification for all bundles. Operations fail if integrity is missing or invalid. */
|
|
1084
|
+
'strict'|
|
|
1085
|
+
/** Verify integrity if provided| but allow operations without it. */
|
|
1086
|
+
'optional'|
|
|
1087
|
+
/** Skip integrity verification entirely. */
|
|
1088
|
+
'none';
|
|
1089
|
+
|
|
1090
|
+
/**
|
|
1091
|
+
* Information about a bundle from list operations.
|
|
1092
|
+
*
|
|
1093
|
+
* @property {BundleSourceKind} type - Source kind (builtin or remote)
|
|
1094
|
+
* @property {string} name - Bundle name
|
|
1095
|
+
* @property {string} version - Version string
|
|
1096
|
+
* @property {boolean} current - Whether this is the current active version
|
|
1097
|
+
* @property {BundleManifestMetadata} metadata - Bundle metadata
|
|
1098
|
+
*/
|
|
1099
|
+
export interface ListBundleItem {
|
|
1100
|
+
type: BundleSourceKind
|
|
1101
|
+
name: string
|
|
1102
|
+
version: string
|
|
1103
|
+
current: boolean
|
|
1104
|
+
metadata: BundleManifestMetadata
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
/**
|
|
1108
|
+
* Bundle information from list operations.
|
|
1109
|
+
*
|
|
1110
|
+
* @property {string} name - Bundle name
|
|
1111
|
+
* @property {string} version - Version string
|
|
1112
|
+
*/
|
|
1113
|
+
export interface ListRemoteBundleInfo {
|
|
1114
|
+
name: string
|
|
1115
|
+
version: string
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
/**
|
|
1119
|
+
* Reads a bundle from a file asynchronously.
|
|
1120
|
+
*
|
|
1121
|
+
* @param {string} filepath - Path to the `.wvb` file
|
|
1122
|
+
* @returns {Promise<Bundle>} Parsed bundle
|
|
1123
|
+
* @throws {Error} If the file cannot be read or is not a valid bundle
|
|
1124
|
+
*
|
|
1125
|
+
* @example
|
|
1126
|
+
* ```typescript
|
|
1127
|
+
* const bundle = await readBundle("app.wvb");
|
|
1128
|
+
* const html = bundle.getData("/index.html");
|
|
1129
|
+
* ```
|
|
1130
|
+
*/
|
|
1131
|
+
export declare function readBundle(filepath: string): Promise<Bundle>
|
|
1132
|
+
|
|
1133
|
+
/**
|
|
1134
|
+
* Reads a bundle from a buffer synchronously.
|
|
1135
|
+
*
|
|
1136
|
+
* @param {Buffer} buffer - Buffer containing bundle data
|
|
1137
|
+
* @returns {Bundle} Parsed bundle
|
|
1138
|
+
* @throws {Error} If the buffer is not a valid bundle
|
|
1139
|
+
*
|
|
1140
|
+
* @example
|
|
1141
|
+
* ```typescript
|
|
1142
|
+
* import { readFileSync } from "fs";
|
|
1143
|
+
* const buffer = readFileSync("app.wvb");
|
|
1144
|
+
* const bundle = readBundleFromBuffer(buffer);
|
|
1145
|
+
* ```
|
|
1146
|
+
*/
|
|
1147
|
+
export declare function readBundleFromBuffer(buffer: Buffer): Bundle
|
|
1148
|
+
|
|
1149
|
+
/**
|
|
1150
|
+
* Complete bundle information from remote server.
|
|
1151
|
+
*
|
|
1152
|
+
* Contains version, cache validation, and integrity data.
|
|
1153
|
+
*
|
|
1154
|
+
* @property {string} name - Bundle name
|
|
1155
|
+
* @property {string} version - Version string
|
|
1156
|
+
* @property {string} [etag] - HTTP ETag for cache validation
|
|
1157
|
+
* @property {string} [integrity] - SHA3 integrity hash
|
|
1158
|
+
* @property {string} [signature] - Digital signature
|
|
1159
|
+
* @property {string} [lastModified] - Last-Modified timestamp
|
|
1160
|
+
*/
|
|
1161
|
+
export interface RemoteBundleInfo {
|
|
1162
|
+
name: string
|
|
1163
|
+
version: string
|
|
1164
|
+
etag?: string
|
|
1165
|
+
integrity?: string
|
|
1166
|
+
signature?: string
|
|
1167
|
+
lastModified?: string
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
/**
|
|
1171
|
+
* Download progress data.
|
|
1172
|
+
*
|
|
1173
|
+
* @property {number} downloadedBytes - Bytes downloaded so far
|
|
1174
|
+
* @property {number} totalBytes - Total bytes to download
|
|
1175
|
+
* @property {string} endpoint - Endpoint being downloaded from
|
|
1176
|
+
*/
|
|
1177
|
+
export interface RemoteOnDownloadData {
|
|
1178
|
+
downloadedBytes: number
|
|
1179
|
+
totalBytes: number
|
|
1180
|
+
endpoint: string
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
/**
|
|
1184
|
+
* Options for creating a remote client.
|
|
1185
|
+
*
|
|
1186
|
+
* @property {HttpOptions} [http] - HTTP client configuration
|
|
1187
|
+
* @property {(data: RemoteOnDownloadData) => void} [onDownload] - Download progress callback
|
|
1188
|
+
*
|
|
1189
|
+
* @example
|
|
1190
|
+
* ```typescript
|
|
1191
|
+
* const options = {
|
|
1192
|
+
* http: { timeout: 30000 },
|
|
1193
|
+
* onDownload: (data) => {
|
|
1194
|
+
* console.log(`Downloaded ${data.downloadedBytes}/${data.totalBytes}`);
|
|
1195
|
+
* }
|
|
1196
|
+
* };
|
|
1197
|
+
* const remote = new Remote("https://updates.example.com", options);
|
|
1198
|
+
* ```
|
|
1199
|
+
*/
|
|
1200
|
+
export interface RemoteOptions {
|
|
1201
|
+
http?: HttpOptions
|
|
1202
|
+
onDownload?: (data: RemoteOnDownloadData) => void
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
/**
|
|
1206
|
+
* Digital signature algorithm for bundle verification.
|
|
1207
|
+
*
|
|
1208
|
+
* Supports multiple signature schemes for cryptographic verification of bundle authenticity.
|
|
1209
|
+
*
|
|
1210
|
+
* @example
|
|
1211
|
+
* ```typescript
|
|
1212
|
+
* import { Updater, SignatureAlgorithm, VerifyingKeyFormat } from "@wvb/node";
|
|
1213
|
+
*
|
|
1214
|
+
* const updater = new Updater(source, remote, {
|
|
1215
|
+
* signatureVerifier: {
|
|
1216
|
+
* algorithm: SignatureAlgorithm.Ed25519,
|
|
1217
|
+
* key: {
|
|
1218
|
+
* format: VerifyingKeyFormat.SpkiPem,
|
|
1219
|
+
* data: "-----BEGIN PUBLIC KEY-----
|
|
1220
|
+
...
|
|
1221
|
+
-----END PUBLIC KEY-----"
|
|
1222
|
+
* }
|
|
1223
|
+
* }
|
|
1224
|
+
* });
|
|
1225
|
+
* ```
|
|
1226
|
+
*/
|
|
1227
|
+
export type SignatureAlgorithm = /** ECDSA with P-256 curve (secp256r1) */
|
|
1228
|
+
'ecdsaSecp256R1'|
|
|
1229
|
+
/** ECDSA with P-384 curve (secp384r1) */
|
|
1230
|
+
'ecdsaSecp384R1'|
|
|
1231
|
+
/** Ed25519 (EdDSA| recommended for modern applications) */
|
|
1232
|
+
'ed25519'|
|
|
1233
|
+
/** RSA PKCS#1 v1.5 signature scheme */
|
|
1234
|
+
'rsaPkcs1V15'|
|
|
1235
|
+
/** RSA-PSS (Probabilistic Signature Scheme) */
|
|
1236
|
+
'rsaPss';
|
|
1237
|
+
|
|
1238
|
+
/**
|
|
1239
|
+
* Configuration for signature verification.
|
|
1240
|
+
*
|
|
1241
|
+
* @property {SignatureAlgorithm} algorithm - The signature algorithm to use
|
|
1242
|
+
* @property {SignatureVerifyingKeyOptions} key - The public key configuration
|
|
1243
|
+
*
|
|
1244
|
+
* @example
|
|
1245
|
+
* ```typescript
|
|
1246
|
+
* const verifierOptions = {
|
|
1247
|
+
* algorithm: SignatureAlgorithm.Ed25519,
|
|
1248
|
+
* key: {
|
|
1249
|
+
* format: VerifyingKeyFormat.SpkiPem,
|
|
1250
|
+
* data: "-----BEGIN PUBLIC KEY-----
|
|
1251
|
+
...
|
|
1252
|
+
-----END PUBLIC KEY-----"
|
|
1253
|
+
* }
|
|
1254
|
+
* };
|
|
1255
|
+
* ```
|
|
1256
|
+
*/
|
|
1257
|
+
export interface SignatureVerifierOptions {
|
|
1258
|
+
algorithm: SignatureAlgorithm
|
|
1259
|
+
key: SignatureVerifyingKeyOptions
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
/**
|
|
1263
|
+
* Public key configuration for signature verification.
|
|
1264
|
+
*
|
|
1265
|
+
* @property {VerifyingKeyFormat} format - The format of the public key
|
|
1266
|
+
* @property {string | Uint8Array} data - The key data (string for PEM, Uint8Array for DER/Raw)
|
|
1267
|
+
*
|
|
1268
|
+
* @example
|
|
1269
|
+
* ```typescript
|
|
1270
|
+
* // PEM format (string)
|
|
1271
|
+
* const pemKey = {
|
|
1272
|
+
* format: VerifyingKeyFormat.SpkiPem,
|
|
1273
|
+
* data: "-----BEGIN PUBLIC KEY-----
|
|
1274
|
+
...
|
|
1275
|
+
-----END PUBLIC KEY-----"
|
|
1276
|
+
* };
|
|
1277
|
+
*
|
|
1278
|
+
* // DER format (binary)
|
|
1279
|
+
* const derKey = {
|
|
1280
|
+
* format: VerifyingKeyFormat.SpkiDer,
|
|
1281
|
+
* data: new Uint8Array([...])
|
|
1282
|
+
* };
|
|
1283
|
+
* ```
|
|
1284
|
+
*/
|
|
1285
|
+
export interface SignatureVerifyingKeyOptions {
|
|
1286
|
+
format: VerifyingKeyFormat
|
|
1287
|
+
data: string | Uint8Array
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
/**
|
|
1291
|
+
* Configuration options for the updater.
|
|
1292
|
+
*
|
|
1293
|
+
* @property {string} [channel] - Update channel (e.g., "stable", "beta")
|
|
1294
|
+
* @property {IntegrityPolicy} [integrityPolicy] - Policy for integrity verification
|
|
1295
|
+
* @property {Function} [integrityChecker] - Custom integrity verification function
|
|
1296
|
+
* @property {SignatureVerifierOptions | Function} [signatureVerifier] - Signature verification config or custom function
|
|
1297
|
+
*
|
|
1298
|
+
* @example
|
|
1299
|
+
* ```typescript
|
|
1300
|
+
* const updater = new Updater(source, remote, {
|
|
1301
|
+
* channel: "stable",
|
|
1302
|
+
* integrityPolicy: IntegrityPolicy.Strict,
|
|
1303
|
+
* signatureVerifier: {
|
|
1304
|
+
* algorithm: SignatureAlgorithm.Ed25519,
|
|
1305
|
+
* key: {
|
|
1306
|
+
* format: VerifyingKeyFormat.SpkiPem,
|
|
1307
|
+
* data: publicKeyPem
|
|
1308
|
+
* }
|
|
1309
|
+
* }
|
|
1310
|
+
* });
|
|
1311
|
+
* ```
|
|
1312
|
+
*
|
|
1313
|
+
* @example
|
|
1314
|
+
* ```typescript
|
|
1315
|
+
* // Custom verification functions
|
|
1316
|
+
* const updater = new Updater(source, remote, {
|
|
1317
|
+
* integrityChecker: async (data, integrity) => {
|
|
1318
|
+
* // Custom integrity verification
|
|
1319
|
+
* return true;
|
|
1320
|
+
* },
|
|
1321
|
+
* signatureVerifier: async (data, signature) => {
|
|
1322
|
+
* // Custom signature verification
|
|
1323
|
+
* return true;
|
|
1324
|
+
* }
|
|
1325
|
+
* });
|
|
1326
|
+
* ```
|
|
1327
|
+
*/
|
|
1328
|
+
export interface UpdaterOptions {
|
|
1329
|
+
channel?: string
|
|
1330
|
+
integrityPolicy?: IntegrityPolicy
|
|
1331
|
+
integrityChecker?: (data: Uint8Array, integrity: string) => Promise<boolean>
|
|
1332
|
+
signatureVerifier?: SignatureVerifierOptions | ((data: Uint8Array, signature: string) => Promise<boolean>)
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
/**
|
|
1336
|
+
* Format of the public key used for signature verification.
|
|
1337
|
+
*
|
|
1338
|
+
* Different algorithms support different key formats.
|
|
1339
|
+
*
|
|
1340
|
+
* @example
|
|
1341
|
+
* ```typescript
|
|
1342
|
+
* import { VerifyingKeyFormat } from "@wvb/node";
|
|
1343
|
+
* import fs from "fs";
|
|
1344
|
+
*
|
|
1345
|
+
* // PEM format (text)
|
|
1346
|
+
* const pemKey = fs.readFileSync("./public-key.pem", "utf8");
|
|
1347
|
+
* const config1 = {
|
|
1348
|
+
* format: VerifyingKeyFormat.SpkiPem,
|
|
1349
|
+
* data: pemKey
|
|
1350
|
+
* };
|
|
1351
|
+
*
|
|
1352
|
+
* // DER format (binary)
|
|
1353
|
+
* const derKey = fs.readFileSync("./public-key.der");
|
|
1354
|
+
* const config2 = {
|
|
1355
|
+
* format: VerifyingKeyFormat.SpkiDer,
|
|
1356
|
+
* data: derKey
|
|
1357
|
+
* };
|
|
1358
|
+
*
|
|
1359
|
+
* // Raw bytes (Ed25519 only)
|
|
1360
|
+
* const rawKey = new Uint8Array(32);
|
|
1361
|
+
* const config3 = {
|
|
1362
|
+
* format: VerifyingKeyFormat.Raw,
|
|
1363
|
+
* data: rawKey
|
|
1364
|
+
* };
|
|
1365
|
+
* ```
|
|
1366
|
+
*/
|
|
1367
|
+
export type VerifyingKeyFormat = /** SubjectPublicKeyInfo DER format (binary) */
|
|
1368
|
+
'spkiDer'|
|
|
1369
|
+
/** SubjectPublicKeyInfo PEM format (text) */
|
|
1370
|
+
'spkiPem'|
|
|
1371
|
+
/** PKCS#1 DER format (RSA only| binary) */
|
|
1372
|
+
'pkcs1Der'|
|
|
1373
|
+
/** PKCS#1 PEM format (RSA only| text) */
|
|
1374
|
+
'pkcs1Pem'|
|
|
1375
|
+
/** SEC1 format (ECDSA only| binary) */
|
|
1376
|
+
'sec1'|
|
|
1377
|
+
/** Raw key bytes (Ed25519 only| 32 bytes) */
|
|
1378
|
+
'raw';
|
|
1379
|
+
|
|
1380
|
+
export type Version = 'v1';
|
|
1381
|
+
|
|
1382
|
+
/**
|
|
1383
|
+
* Writes a bundle to a file asynchronously.
|
|
1384
|
+
*
|
|
1385
|
+
* @param {Bundle} bundle - Bundle to write
|
|
1386
|
+
* @param {string} filepath - Destination file path
|
|
1387
|
+
* @returns {Promise<number>} Number of bytes written
|
|
1388
|
+
* @throws {Error} If the file cannot be written
|
|
1389
|
+
*
|
|
1390
|
+
* @example
|
|
1391
|
+
* ```typescript
|
|
1392
|
+
* const builder = new BundleBuilder();
|
|
1393
|
+
* builder.insertEntry("/index.html", Buffer.from("<html></html>"));
|
|
1394
|
+
* const bundle = builder.build();
|
|
1395
|
+
* await writeBundle(bundle, "output.wvb");
|
|
1396
|
+
* ```
|
|
1397
|
+
*/
|
|
1398
|
+
export declare function writeBundle(bundle: Bundle, filepath: string): Promise<bigint>
|
|
1399
|
+
|
|
1400
|
+
/**
|
|
1401
|
+
* Writes a bundle to a buffer synchronously.
|
|
1402
|
+
*
|
|
1403
|
+
* @param {Bundle} bundle - Bundle to write
|
|
1404
|
+
* @returns {Buffer} Bundle data as a buffer
|
|
1405
|
+
*
|
|
1406
|
+
* @example
|
|
1407
|
+
* ```typescript
|
|
1408
|
+
* const bundle = builder.build();
|
|
1409
|
+
* const buffer = writeBundleIntoBuffer(bundle);
|
|
1410
|
+
* console.log(`Bundle size: ${buffer.length} bytes`);
|
|
1411
|
+
* ```
|
|
1412
|
+
*/
|
|
1413
|
+
export declare function writeBundleIntoBuffer(bundle: Bundle): Buffer
|