@johnhenry/packfile 0.0.0 → 0.0.1

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
@@ -197,7 +197,7 @@ Uses SHA-256 hashing (same as file ETags) for consistent cache keys.
197
197
  import { fromArchive, toArchive, createRouter } from '@johnhenry/packfile/browser';
198
198
  ```
199
199
 
200
- The browser bundle provides `fromArchive`, `toArchive`, and `createRouter`, using the `wbn` package directly (no Node APIs required) and Web Crypto for hashing -- same wire format as the Node entrypoint, so an archive built by one is directly readable by the other.
200
+ The browser bundle provides `fromArchive`, `toArchive`, and `createRouter`, using the `wbn` package directly (no Node APIs required) and Web Crypto for hashing -- same wire format as the Node entrypoint, so an archive built by one is directly readable by the other. **`toArchive()` here returns an `ArrayBuffer`, not the `Buffer` the Node `.` entry's `toArchive()` returns** (or a `Uint8Array` when called with `{ compressed: false }`) -- there is no `Buffer` in a browser. Types for this subpath are declared in `browser.d.ts` (see `./browser`'s `types` condition in `package.json`).
201
201
 
202
202
  ```js
203
203
  const archive = await fetch('/app.wbn').then(r => r.arrayBuffer());
@@ -405,6 +405,15 @@ import { compressObject, deCompressObject } from '@johnhenry/packfile/compressio
405
405
  | `./blob-preview` | `lib/blob-preview.mjs` | `createBlobPreview` — host a `FilesMap` client-side via `blob:` URLs, no server |
406
406
  | `./web-bundle` | `lib/web-bundle.mjs` | Lower-level Web Bundle primitives: `toWebBundle`, `fromWebBundle`, `createWebBundleRouter` — the engine `toArchive`/`fromArchive` are built on, with a real `baseURL`/headers/IWA-signing exposed |
407
407
 
408
+ TypeScript types: `.`, `./browser`, and `./blob-preview` each have a `types`
409
+ condition and a real `.d.ts` file (`types.d.ts`, `browser.d.ts`,
410
+ `blob-preview.d.ts`). The remaining subpaths (`./compat`, `./cache`,
411
+ `./hash`, `./compression`, `./web-bundle`) do not yet -- importing from one
412
+ of those in TypeScript will type-check as `any`, not a compile error, but
413
+ also not real type safety. (`./browser` and `./blob-preview` were fixed in
414
+ [#5](https://github.com/johnhenry/packfile/issues/5); the others are open,
415
+ unfixed instances of the same gap.)
416
+
408
417
  ## Security model
409
418
 
410
419
  **What packfile guarantees:**
@@ -0,0 +1,86 @@
1
+ import { FilesMap } from "./types";
2
+
3
+ export { FilesMap };
4
+
5
+ // Note: `blob-preview.d.ts` describes the `./blob-preview` entry point
6
+ // (`lib/blob-preview.mjs`), whose only export is `createBlobPreview`.
7
+
8
+ /** Why a reference was left unrewritten (see README "What this does and
9
+ * does not solve"): either the target path doesn't exist in the given
10
+ * `FilesMap` ("missing"), or resolving it would require a file that's
11
+ * still mid-finalization -- a genuine reference cycle ("cycle"). */
12
+ export type UnresolvedReferenceReason = "missing" | "cycle";
13
+
14
+ export type UnresolvedReferenceInfo = {
15
+ reason: UnresolvedReferenceReason;
16
+ targetPath: string;
17
+ fromPath: string;
18
+ };
19
+
20
+ export type CreateBlobPreviewOptions = {
21
+ /** The entry-point path, must exist in `files`. Default `"index.html"`. */
22
+ rootPath?: string;
23
+ /** Throw instead of warning when a relative reference can't be resolved
24
+ * (missing file, or a reference-cycle closing edge). Default `false`. */
25
+ strict?: boolean;
26
+ /** Called instead of the default `console.warn` for every reference this
27
+ * module leaves unrewritten because it couldn't (or, for cycles,
28
+ * shouldn't) be resolved. Ignored when `strict` is set (which throws
29
+ * instead). */
30
+ onUnresolvedReference?: (info: UnresolvedReferenceInfo) => void;
31
+ };
32
+
33
+ /**
34
+ * A registry of in-memory JS files, each backed by its own `blob:` URL.
35
+ *
36
+ * This is a duplicate of `@johnhenry/andbox`'s own `VirtualModuleRegistry`
37
+ * interface (from `createVirtualModuleRegistry()`, which `createBlobPreview`
38
+ * uses internally for JS specifier resolution), not an import of it: as of
39
+ * this writing `@johnhenry/andbox`'s `package.json` has no `types`
40
+ * condition of its own (the same class of bug this file's sibling
41
+ * `browser.d.ts` fixes for this package -- see packfile issue #5), so
42
+ * `import("@johnhenry/andbox").VirtualModuleRegistry` does not resolve for
43
+ * a consumer of *this* package under `moduleResolution: "nodenext"`/
44
+ * `"bundler"`. Duplicated here deliberately so this package's own types
45
+ * stay resolvable regardless of that separate, upstream issue; keep this
46
+ * in sync with `@johnhenry/andbox`'s `src/index.d.ts` if it changes.
47
+ */
48
+ export interface VirtualModuleRegistry {
49
+ /** Get the `blob:` URL registered for a path, or `null` if unknown. */
50
+ resolve(path: string): string | null;
51
+ /** Resolve a module specifier the way `import` would, from the point of
52
+ * view of a given importing file: import-map resolution first, then a
53
+ * relative-path fallback, then `null` if neither matched. */
54
+ resolveSpecifier(specifier: string, parentPath?: string): string | null;
55
+ /** Register (or replace) a file at runtime. Returns the new blob URL. */
56
+ define(path: string, source: string): string;
57
+ /** Whether a path is registered. */
58
+ has(path: string): boolean;
59
+ /** All registered paths. */
60
+ paths(): string[];
61
+ /** Revoke every blob URL this registry has ever minted. */
62
+ dispose(): void;
63
+ /** Whether `dispose()` has been called. */
64
+ isDisposed(): boolean;
65
+ }
66
+
67
+ export type BlobPreview = {
68
+ /** `blob:` URL for `rootPath`. */
69
+ entryUrl: string;
70
+ /** Look up the `blob:` URL minted for a given packaged path. */
71
+ resolve(path: string): string | null;
72
+ /** Revokes every `blob:` URL this call minted. */
73
+ dispose(): void;
74
+ /** The underlying andbox registry, for advanced JS-specifier resolution. */
75
+ registry: VirtualModuleRegistry;
76
+ };
77
+
78
+ /**
79
+ * Turn a packfile `FilesMap` into a set of `blob:` URLs suitable for hosting
80
+ * inside a browser tab/iframe with no server. For trusted/your-own content
81
+ * only -- see README's "What this does and does not solve".
82
+ */
83
+ export function createBlobPreview(
84
+ files: FilesMap,
85
+ options?: CreateBlobPreviewOptions
86
+ ): Promise<BlobPreview>;
package/browser.d.ts ADDED
@@ -0,0 +1,86 @@
1
+ import { FileEntry, FilesMap, RouterOptions, RouteHandler } from "./types";
2
+
3
+ export { FileEntry, FilesMap, RouterOptions, RouteHandler };
4
+
5
+ // Note: `browser.d.ts` describes the `./browser` entry point (`browser.mjs`),
6
+ // not the main `.` entry (see `types.d.ts` for that). `createRouter` is the
7
+ // exact same implementation as the `.` entry's (both import
8
+ // `./lib/create-router.mjs`), so its types are reused unchanged. `toArchive`
9
+ // and `fromArchive`, however, are a *separate* implementation from the Node
10
+ // entry's (`lib/to-archive.mjs`/`lib/from-archive.mjs`) -- same wire format,
11
+ // but different runtime types, because there is no `Buffer` in a browser:
12
+ //
13
+ // - `toArchive()`'s options key is `compressed` here, not `compress` (the
14
+ // Node entry's key) -- a real, pre-existing naming inconsistency between
15
+ // the two entrypoints, not a typo introduced by this file. There is also
16
+ // no `compressionLevel` option here (browser.mjs's own comment notes
17
+ // `CompressionStream` has no level parameter to plumb one through to).
18
+ // - `toArchive()` returns a `Uint8Array` when called with
19
+ // `{ compressed: false }` (the raw, uncompressed Web Bundle from
20
+ // `wbn`'s `BundleBuilder.createBundle()`), and an `ArrayBuffer` when
21
+ // compression runs (the default): `compressObject()`
22
+ // (`lib/compression.browser.mjs`) pipes through `CompressionStream` and
23
+ // resolves via `Response#arrayBuffer()`. The Node entry's `toArchive()`,
24
+ // by contrast, always returns a `Buffer`. Don't assume this matches the
25
+ // Node types -- confirmed by reading both implementations, not guessed.
26
+ // - `fromArchive()`'s `buffer` parameter is `ArrayBuffer | Uint8Array`, not
27
+ // `Buffer | ArrayBuffer | Uint8Array` like the Node entry -- there is no
28
+ // `Buffer` global to accept in a browser build.
29
+
30
+ export type BrowserToArchiveOptions = {
31
+ /** Default `true`. When `false`, skips compression and returns the raw
32
+ * Web Bundle bytes as a `Uint8Array` instead of an `ArrayBuffer`. */
33
+ compressed?: boolean;
34
+ };
35
+
36
+ export type BrowserFromArchiveOptions = {
37
+ /** Default `true`. Set `false` if `buffer` is an uncompressed Web Bundle. */
38
+ compressed?: boolean;
39
+ };
40
+
41
+ /**
42
+ * Serializes a file Map to a (by default gzip-compressed) Web Bundle.
43
+ * Returns an `ArrayBuffer` when compressed (the default); returns the raw
44
+ * `Uint8Array` bundle directly when called with `{ compressed: false }`.
45
+ * Same wire format as the Node `.` entry's `toArchive()`, which always
46
+ * returns a `Buffer` -- the two are readable by each other regardless.
47
+ *
48
+ * Declared as overloads (rather than a single `Promise<ArrayBuffer |
49
+ * Uint8Array>` signature) so a literal `{ compressed: false }` narrows the
50
+ * return type precisely instead of forcing every caller to deal with the
51
+ * union.
52
+ */
53
+ export function toArchive(
54
+ map: Map<string, FileEntry>,
55
+ options?: { compressed?: true }
56
+ ): Promise<ArrayBuffer>;
57
+ export function toArchive(
58
+ map: Map<string, FileEntry>,
59
+ options: { compressed: false }
60
+ ): Promise<Uint8Array>;
61
+ export function toArchive(
62
+ map: Map<string, FileEntry>,
63
+ options?: BrowserToArchiveOptions
64
+ ): Promise<ArrayBuffer | Uint8Array>;
65
+
66
+ /**
67
+ * Deserializes a (by default gzip-compressed) Web Bundle back into a
68
+ * `Map<string, FileEntry>`. Accepts an `ArrayBuffer` or `Uint8Array` --
69
+ * there is no `Buffer` global in a browser build.
70
+ */
71
+ export function fromArchive(
72
+ buffer: ArrayBuffer | Uint8Array,
73
+ options?: BrowserFromArchiveOptions
74
+ ): Promise<Map<string, FileEntry>>;
75
+
76
+ /**
77
+ * Returns a `(input, ctx?) => Promise<Response>` handler that serves files
78
+ * from a `Map`/`LazyFileMap`. `input` may be a path string or a `Request`.
79
+ * The returned function also has itself assigned to `.fetch`. Identical
80
+ * implementation to the `.` entry's `createRouter` (both import
81
+ * `./lib/create-router.mjs`).
82
+ */
83
+ export function createRouter(
84
+ files: FilesMap,
85
+ options?: RouterOptions
86
+ ): RouteHandler;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@johnhenry/packfile",
3
- "version": "0.0.0",
3
+ "version": "0.0.1",
4
4
  "type": "module",
5
5
  "main": "index.mjs",
6
6
  "types": "./types.d.ts",
@@ -24,6 +24,7 @@
24
24
  },
25
25
  "scripts": {
26
26
  "test": "node --test test.mjs",
27
+ "typecheck": "tsc --project test/types-fixture/tsconfig.json",
27
28
  "demo:compile": "node demo/compile.mjs",
28
29
  "demo:server": "node demo/server.mjs",
29
30
  "demo:browser": "npx serve ."
@@ -38,6 +39,7 @@
38
39
  },
39
40
  "devDependencies": {
40
41
  "theres-waldo": "^0.0.0",
42
+ "typescript": "^7.0.2",
41
43
  "wbn-sign": "^0.3.1"
42
44
  },
43
45
  "exports": {
@@ -45,21 +47,29 @@
45
47
  "types": "./types.d.ts",
46
48
  "default": "./index.mjs"
47
49
  },
48
- "./browser": "./browser.mjs",
50
+ "./browser": {
51
+ "types": "./browser.d.ts",
52
+ "default": "./browser.mjs"
53
+ },
49
54
  "./compat": "./compat.mjs",
50
55
  "./cache": "./cache.mjs",
51
56
  "./hash": "./lib/hash.mjs",
52
57
  "./compression": "./lib/compression.mjs",
53
- "./blob-preview": "./lib/blob-preview.mjs",
58
+ "./blob-preview": {
59
+ "types": "./blob-preview.d.ts",
60
+ "default": "./lib/blob-preview.mjs"
61
+ },
54
62
  "./web-bundle": "./lib/web-bundle.mjs"
55
63
  },
56
64
  "files": [
57
65
  "index.mjs",
58
66
  "browser.mjs",
67
+ "browser.d.ts",
59
68
  "compat.mjs",
60
69
  "cache.mjs",
61
70
  "packfile.mjs",
62
71
  "lib/",
72
+ "blob-preview.d.ts",
63
73
  "types.d.ts",
64
74
  "types.ts",
65
75
  "README.md",