@quillmark/quiver 0.19.0 → 0.20.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/MIGRATION.md ADDED
@@ -0,0 +1,91 @@
1
+ # Migrating `@quillmark/quiver`
2
+
3
+ Upgrade notes per range. The [CHANGELOG](CHANGELOG.md) is the full record; this page is the subset that breaks a working consumer, ordered by how late you find out.
4
+
5
+ ## 0.16 → 0.19
6
+
7
+ ### Runtime, not build time
8
+
9
+ Four removals leave valid JavaScript. A consumer on plain JS, or on TypeScript reaching these through an `any`, learns about them from a `TypeError` at runtime naming neither the version nor the replacement.
10
+
11
+ **`Quiver.buildPackage(specifier, outDir)` and `Quiver.fromPackage(specifier)` are gone.** An npm-installed quiver is a directory, and resolving it belongs to the caller: the resolution base has to be your module, because under an isolated `node_modules` layout your dependencies are reachable from you and not from this package.
12
+
13
+ ```js
14
+ // 0.16
15
+ await Quiver.buildPackage('@org/my-quiver', './public/quills');
16
+ const quiver = await Quiver.fromPackage('@org/my-quiver');
17
+
18
+ // 0.19
19
+ import { createRequire } from 'node:module';
20
+ import { dirname } from 'node:path';
21
+ import { build, fromDir } from '@quillmark/quiver/node';
22
+
23
+ const root = dirname(createRequire(import.meta.url).resolve('@org/my-quiver/Quiver.yaml'));
24
+ await build(root, './public/quills');
25
+ const quiver = await fromDir(root);
26
+ ```
27
+
28
+ That resolution goes through the collection's `exports` map. A collection that declares one and does not expose `./Quiver.yaml` fails here with a module-resolution error naming neither the collection nor the convention; the fix is in the collection's `package.json`, not at your call site.
29
+
30
+ **`quiver.warm()` is gone.** It prefetched every tree into a second cache that no longer exists. `getQuill` caches and coalesces per canonical ref, so prefetching is calling it early:
31
+
32
+ ```js
33
+ const refs = quiver.quillNames().flatMap((n) => quiver.versionsOf(n).map((v) => `${n}@${v}`));
34
+ await Promise.allSettled(refs.map((r) => quiver.getQuill(r)));
35
+ ```
36
+
37
+ Skipping it costs one fetch on first open of each quill, cached from then on.
38
+
39
+ **`Quiver.fromManifest(baseUrl, bytes)` is gone**, replaced by two doors that cover more than it did. Pass the whole artifact and fetch nothing, or seed what you hold and let the URL serve the rest:
40
+
41
+ ```js
42
+ // 0.16
43
+ const quiver = await Quiver.fromManifest('/quills/my-quiver/', manifestBytes);
44
+
45
+ // 0.19 — whole artifact in hand, no filesystem, no fetch
46
+ const quiver = await Quiver.fromBuiltFiles(artifactFiles);
47
+
48
+ // 0.19 — hold the small documents, fetch the heavy ones
49
+ const quiver = await Quiver.fromBuiltUrl('/quills/my-quiver/', {
50
+ seed: new Map([
51
+ ['latest.json', pointerBytes],
52
+ [manifestName, manifestBytes]
53
+ ])
54
+ });
55
+ ```
56
+
57
+ Keys are artifact-relative, as `build` writes them. `fromManifest` took manifest bytes and skipped the pointer; the seed takes any subset of the artifact, so it covers that and the case where the bundles are in hand too.
58
+
59
+ **`quiver.resolve(ref)` is sync.** `await` on it still works, so this breaks only a call site that used the promise as one: `.then()`, `Promise.all([...])`, or a `.catch()` that now has a throw to catch instead of a rejection.
60
+
61
+ ### Rebuild every artifact
62
+
63
+ Build output moved from MD5 to SHA-256, and the loader verifies fetched bytes against the digest in their name. An artifact packed by 0.16 fails to load under 0.19. Re-run `build`; nothing in the source layout changes.
64
+
65
+ ### The compiler-caught rest
66
+
67
+ | 0.16 | 0.19 |
68
+ | ----------------------------------------------------------------- | ---------------------------------------------- |
69
+ | `Quiver.fromDir`, `Quiver.fromBuiltDir`, `Quiver.build` (statics) | free functions from `@quillmark/quiver/node` |
70
+ | `Quiver._fromLoader` | removed; construction is sealed |
71
+ | `BuildOptions` | removed; `build(src, out)` takes two arguments |
72
+ | `@quillmark/quiver/preview`, `renderQuiverSamples` | removed; `quillkit studio` answers live |
73
+ | `@quillmark/quiver/testing`, `runQuiverTests` | removed; `quillkit test` is the gate |
74
+ | `quiver` / `quillmark-quiver` bin | removed; the verbs are `quillkit`'s |
75
+ | `quiver.config.js` | `quillkit.config.js` |
76
+
77
+ The `@quillmark/wasm` peer floor is `>=0.101.0-0`. That range carries its own boundary changes, several of which a type checker also misses; the ledger is [`DOCUMENT_MODEL.md`](../svelte/prose/canon/DOCUMENT_MODEL.md) in `@quillmark/svelte`.
78
+
79
+ ### Installing the tooling
80
+
81
+ The bin left this package in 0.19. A collection that ran `quiver test` or `quillmark-quiver build` from its `scripts` installs `quillkit` and keeps depending on this package for the format its quiver is packed in:
82
+
83
+ ```sh
84
+ npm install --save-dev @quillmark/quiver @quillmark/wasm quillkit
85
+ ```
86
+
87
+ ```jsonc
88
+ {
89
+ "scripts": { "test": "quillkit test", "build": "quillkit build" }
90
+ }
91
+ ```
package/README.md CHANGED
@@ -8,17 +8,20 @@ Load and build collections of quills for rendering with `@quillmark/wasm`.
8
8
  npm install @quillmark/quiver @quillmark/wasm
9
9
  ```
10
10
 
11
+ Upgrading from an earlier version: [`MIGRATION.md`](MIGRATION.md).
12
+
11
13
  ## Loading a quiver
12
14
 
13
15
  A quiver has one authored shape, the **source layout** (`Quiver.yaml` at the package root, quills under `quills/<name>/<x.y.z>/`), published as an npm package. Browsers cannot read that layout, so `build(src, out)` packs it at deploy time and the output is served as static assets. Each loader names exactly what it reads; there is no auto-detection.
14
16
 
15
- | Loader | Reads | Import |
16
- | -------------------------- | ----------------------- | ------------------------ |
17
- | `fromDir(path)` | the source layout | `@quillmark/quiver/node` |
18
- | `fromBuiltDir(path)` | build output, off disk | `@quillmark/quiver/node` |
19
- | `Quiver.fromBuiltUrl(url)` | build output, over HTTP | `@quillmark/quiver` |
17
+ | Loader | Reads | Import |
18
+ | ------------------------------ | ------------------------- | ------------------------ |
19
+ | `fromDir(path)` | the source layout | `@quillmark/quiver/node` |
20
+ | `fromBuiltDir(path)` | build output, off disk | `@quillmark/quiver/node` |
21
+ | `Quiver.fromBuiltUrl(url)` | build output, over HTTP | `@quillmark/quiver` |
22
+ | `Quiver.fromBuiltFiles(files)` | build output, from memory | `@quillmark/quiver` |
20
23
 
21
- The filesystem factories are free functions from `/node`; the one that reaches across HTTP is a static on `Quiver`. Importing `/node` adds nothing to the class, so a bundler drops the verbs you do not call.
24
+ The filesystem factories are free functions from `/node`; the two that reach no filesystem are statics on `Quiver`. Importing `/node` adds nothing to the class, so a bundler drops the verbs you do not call.
22
25
 
23
26
  ## Consuming a quiver (Node)
24
27
 
@@ -27,19 +30,20 @@ A quiver installed from npm is a directory like any other. Resolve its root from
27
30
  ```ts
28
31
  import { createRequire } from 'node:module';
29
32
  import { dirname } from 'node:path';
30
- import { Engine, Document } from '@quillmark/wasm';
33
+ import { Engine, init } from '@quillmark/wasm';
31
34
  import { fromDir } from '@quillmark/quiver/node';
32
35
 
33
36
  const root = dirname(createRequire(import.meta.url).resolve('@org/my-quiver/Quiver.yaml'));
34
37
  const quiver = await fromDir(root);
35
38
  const engine = new Engine();
36
39
 
40
+ const { Document } = await init(); // the gate is the only door to Document
37
41
  const doc = Document.fromMarkdown(markdownString);
38
42
  const quill = await quiver.getQuill(doc.quillRef);
39
43
  const result = await engine.render(quill, doc, { format: 'pdf' });
40
44
  ```
41
45
 
42
- `getQuill(ref)` is the only way to obtain a quill from a quiver, and the only entry point most consumers need. It accepts selector refs (`"memo"`, `"memo@1"`) and canonical ones (`"memo@1.0.0"`), resolves the selector, materializes the quill via `Quill.fromTree`, and caches one instance per canonical ref for the quiver's lifetime; concurrent calls for the same ref coalesce into a single load.
46
+ `getQuill(ref)` is the only way to obtain a quill from a quiver, and the only entry point most consumers need. It accepts selector refs (`"memo"`, `"memo@1"`) and canonical ones (`"memo@1.0.0"`), resolves the selector, materializes the quill via `Quill.fromTree`, and caches one instance per canonical ref for the quiver's lifetime; concurrent calls for the same ref coalesce into a single load. It awaits `init()` itself, so instantiating the core is not a precondition of calling it.
43
47
 
44
48
  That quill is **borrowed, not owned**: every caller asking for that ref gets the same instance, so `free()` on it hands the next caller a freed handle. Code that owns its quill mints one from `(await quiver.getQuill(ref)).toTree()` and frees that.
45
49
 
@@ -66,12 +70,13 @@ await build('./node_modules/@org/my-quiver', './public/quivers/my-quiver');
66
70
 
67
71
  ```ts
68
72
  // browser runtime
69
- import { Engine, Document } from '@quillmark/wasm';
73
+ import { Engine, init } from '@quillmark/wasm';
70
74
  import { Quiver } from '@quillmark/quiver';
71
75
 
72
76
  const quiver = await Quiver.fromBuiltUrl('/quivers/my-quiver/');
73
77
  const engine = new Engine();
74
78
 
79
+ const { Document } = await init(); // the gate is the only door to Document
75
80
  const doc = Document.fromMarkdown(markdownString);
76
81
  const quill = await quiver.getQuill(doc.quillRef);
77
82
  const result = await engine.render(quill, doc, { format: 'pdf' });
@@ -90,6 +95,31 @@ import { fromBuiltDir } from '@quillmark/quiver/node';
90
95
  const quiver = await fromBuiltDir('./static/quills/my-quiver');
91
96
  ```
92
97
 
98
+ ## Server-side runtime (no filesystem)
99
+
100
+ A serverless function's packed artifact is not on a path the invocation can read, so `fromBuiltDir` cannot see it. Hand over the bytes instead, keyed by artifact-relative path as `build` writes them (`latest.json`, `manifest.<digest>.json`, `<name>@<x.y.z>.<digest>.zip`, `store/<hash>`):
101
+
102
+ ```ts
103
+ import { Quiver } from '@quillmark/quiver';
104
+
105
+ const quiver = await Quiver.fromBuiltFiles(artifactFiles); // Map<string, Uint8Array>
106
+ ```
107
+
108
+ Nothing is fetched, so nothing self-fetches over your own load balancer. The map must carry the whole artifact; a path it lacks is a `transport_error` naming that path.
109
+
110
+ Where inlining the bundles and fonts is not practical, hold the two small documents and let the host serve the rest:
111
+
112
+ ```ts
113
+ const quiver = await Quiver.fromBuiltUrl('/quills/my-quiver/', {
114
+ seed: new Map([
115
+ ['latest.json', pointerBytes],
116
+ [manifestName, manifestBytes]
117
+ ])
118
+ });
119
+ ```
120
+
121
+ The seed answers first and the URL serves what it does not carry. Seeding `latest.json` also settles which catalog the process reads at deploy time rather than at cache-revalidation time. Seeded bytes are checked against the digest in their name exactly as fetched bytes are.
122
+
93
123
  ## The `latest.json` pointer
94
124
 
95
125
  `Quiver.fromBuiltUrl(url)` first fetches `<url>/latest.json`, a stable-named pointer to the current manifest. Everything behind that pointer is content-addressed and checked against the digest in its name; the pointer itself is not, so a cache layer can serve a stale one and silently pin the client to the old catalog. It is therefore the one request fetched `no-cache` (revalidate with the origin; a 304 still serves from disk), which closes the browser-cache layer. A stale CDN edge is answered by that host's cache headers.
package/dist/quiver.d.ts CHANGED
@@ -4,11 +4,11 @@
4
4
  * Polymorphism via composition: internally stores a pluggable loader
5
5
  * (either source-backed or build-output-backed).
6
6
  *
7
- * This module is browser-safe: only `fromBuiltUrl` and the instance API live
8
- * here. The filesystem factories are free functions in `./node.js`; the class
9
- * is the same either way.
7
+ * This module is browser-safe: only `fromBuiltUrl`, `fromBuiltFiles` and the
8
+ * instance API live here. The filesystem factories are free functions in
9
+ * `./node.js`; the class is the same either way.
10
10
  */
11
- import { Quill } from '@quillmark/wasm';
11
+ import type { Quill } from '@quillmark/wasm';
12
12
  /** Loader strategy: source or build output. Package-internal. */
13
13
  export interface QuiverLoader {
14
14
  loadTree(name: string, version: string): Promise<Map<string, Uint8Array>>;
@@ -24,8 +24,8 @@ export declare class Quiver {
24
24
  readonly name: string;
25
25
  /**
26
26
  * Private constructor. A Quiver comes from a factory (`Quiver.fromBuiltUrl`,
27
- * or `fromDir` / `fromBuiltDir` from `@quillmark/quiver/node`), which is what
28
- * names the thing being read.
27
+ * `Quiver.fromBuiltFiles`, or `fromDir` / `fromBuiltDir` from
28
+ * `@quillmark/quiver/node`), which is what names the thing being read.
29
29
  */
30
30
  private constructor();
31
31
  /**
@@ -35,10 +35,37 @@ export declare class Quiver {
35
35
  * environments. `file://` URLs are rejected — to load build output from
36
36
  * disk in Node, use `fromBuiltDir(path)` from `@quillmark/quiver/node`.
37
37
  *
38
+ * `seed` answers for the artifact bytes the caller already holds, keyed by
39
+ * artifact-relative path; the URL serves the rest. Seeding `latest.json`
40
+ * settles which catalog this process reads at deploy time rather than at
41
+ * cache-revalidation time. Seeded bytes are digest-checked as fetched ones
42
+ * are.
43
+ *
38
44
  * Throws `transport_error` on network/HTTP failure, `quiver_invalid`
39
45
  * on format errors.
40
46
  */
41
- static fromBuiltUrl(url: string): Promise<Quiver>;
47
+ static fromBuiltUrl(url: string, opts?: {
48
+ seed?: ReadonlyMap<string, Uint8Array>;
49
+ }): Promise<Quiver>;
50
+ /**
51
+ * Browser-safe factory. Loads build output from the bytes themselves, keyed
52
+ * by artifact-relative path (`latest.json`, `manifest.<digest>.json`,
53
+ * `<name>@<x.y.z>.<digest>.zip`, `store/<hash>`) — the shape `build` writes
54
+ * and `fromBuiltDir` reads back.
55
+ *
56
+ * Nothing is fetched, so a runtime whose artifact is not on a path it can
57
+ * read (a serverless function, a bundler that inlines it, a test) reaches
58
+ * one without fetching its own static output back over its own load
59
+ * balancer.
60
+ *
61
+ * The map must carry the whole artifact; a missing path is a
62
+ * `transport_error` naming it. To hold part and fetch the rest, pass the map
63
+ * as `fromBuiltUrl`'s `seed`.
64
+ *
65
+ * Throws `quiver_invalid` on format errors, `transport_error` on a path the
66
+ * map does not carry.
67
+ */
68
+ static fromBuiltFiles(files: ReadonlyMap<string, Uint8Array>): Promise<Quiver>;
42
69
  /** Returns all known quill names, sorted lexicographically. */
43
70
  quillNames(): string[];
44
71
  /**
package/dist/quiver.js CHANGED
@@ -4,12 +4,12 @@
4
4
  * Polymorphism via composition: internally stores a pluggable loader
5
5
  * (either source-backed or build-output-backed).
6
6
  *
7
- * This module is browser-safe: only `fromBuiltUrl` and the instance API live
8
- * here. The filesystem factories are free functions in `./node.js`; the class
9
- * is the same either way.
7
+ * This module is browser-safe: only `fromBuiltUrl`, `fromBuiltFiles` and the
8
+ * instance API live here. The filesystem factories are free functions in
9
+ * `./node.js`; the class is the same either way.
10
10
  */
11
11
  import { QuiverError } from './errors.js';
12
- import { Quill } from '@quillmark/wasm';
12
+ import { init } from '@quillmark/wasm';
13
13
  import { parseQuillRef } from './ref.js';
14
14
  import { matchesSemverSelector, chooseHighestVersion } from './semver.js';
15
15
  /**
@@ -31,8 +31,8 @@ export class Quiver {
31
31
  #quillCache = new Map();
32
32
  /**
33
33
  * Private constructor. A Quiver comes from a factory (`Quiver.fromBuiltUrl`,
34
- * or `fromDir` / `fromBuiltDir` from `@quillmark/quiver/node`), which is what
35
- * names the thing being read.
34
+ * `Quiver.fromBuiltFiles`, or `fromDir` / `fromBuiltDir` from
35
+ * `@quillmark/quiver/node`), which is what names the thing being read.
36
36
  */
37
37
  constructor(name, catalog, loader) {
38
38
  this.name = name;
@@ -49,17 +49,49 @@ export class Quiver {
49
49
  * environments. `file://` URLs are rejected — to load build output from
50
50
  * disk in Node, use `fromBuiltDir(path)` from `@quillmark/quiver/node`.
51
51
  *
52
+ * `seed` answers for the artifact bytes the caller already holds, keyed by
53
+ * artifact-relative path; the URL serves the rest. Seeding `latest.json`
54
+ * settles which catalog this process reads at deploy time rather than at
55
+ * cache-revalidation time. Seeded bytes are digest-checked as fetched ones
56
+ * are.
57
+ *
52
58
  * Throws `transport_error` on network/HTTP failure, `quiver_invalid`
53
59
  * on format errors.
54
60
  */
55
- static async fromBuiltUrl(url) {
61
+ static async fromBuiltUrl(url, opts) {
56
62
  if (url.startsWith('file://')) {
57
63
  throw new QuiverError('transport_error', `Quiver.fromBuiltUrl requires an http(s):// or origin-relative URL; got "${url}". For local build output, use import { fromBuiltDir } from '@quillmark/quiver/node'.`);
58
64
  }
59
65
  const { HttpTransport } = await import('./transports/http-transport.js');
60
66
  const { loadBuiltQuiver } = await import('./built-loader.js');
61
- const transport = new HttpTransport(url);
62
- return loadBuiltQuiver(transport);
67
+ const http = new HttpTransport(url);
68
+ if (opts?.seed === undefined)
69
+ return loadBuiltQuiver(http);
70
+ const { MemoryTransport } = await import('./transports/memory-transport.js');
71
+ return loadBuiltQuiver(new MemoryTransport(opts.seed, http));
72
+ }
73
+ /**
74
+ * Browser-safe factory. Loads build output from the bytes themselves, keyed
75
+ * by artifact-relative path (`latest.json`, `manifest.<digest>.json`,
76
+ * `<name>@<x.y.z>.<digest>.zip`, `store/<hash>`) — the shape `build` writes
77
+ * and `fromBuiltDir` reads back.
78
+ *
79
+ * Nothing is fetched, so a runtime whose artifact is not on a path it can
80
+ * read (a serverless function, a bundler that inlines it, a test) reaches
81
+ * one without fetching its own static output back over its own load
82
+ * balancer.
83
+ *
84
+ * The map must carry the whole artifact; a missing path is a
85
+ * `transport_error` naming it. To hold part and fetch the rest, pass the map
86
+ * as `fromBuiltUrl`'s `seed`.
87
+ *
88
+ * Throws `quiver_invalid` on format errors, `transport_error` on a path the
89
+ * map does not carry.
90
+ */
91
+ static async fromBuiltFiles(files) {
92
+ const { MemoryTransport } = await import('./transports/memory-transport.js');
93
+ const { loadBuiltQuiver } = await import('./built-loader.js');
94
+ return loadBuiltQuiver(new MemoryTransport(files));
63
95
  }
64
96
  /** Returns all known quill names, sorted lexicographically. */
65
97
  quillNames() {
@@ -147,10 +179,17 @@ export class Quiver {
147
179
  *
148
180
  * Every caller arrives through `resolve` or the catalog itself, so the ref is
149
181
  * catalog-backed by construction and the loader needs no gate.
182
+ *
183
+ * `init()` is the only door to `Quill`, awaited here rather than left a
184
+ * precondition of `getQuill`. The gate is memoized, so this is one instantiation
185
+ * across every caller, overlapped with the load that pays for it.
150
186
  */
151
187
  async #materializeQuill(canonicalRef) {
152
188
  const at = canonicalRef.indexOf('@');
153
- const tree = await this.#loader.loadTree(canonicalRef.slice(0, at), canonicalRef.slice(at + 1));
189
+ const [{ Quill }, tree] = await Promise.all([
190
+ init(),
191
+ this.#loader.loadTree(canonicalRef.slice(0, at), canonicalRef.slice(at + 1))
192
+ ]);
154
193
  return Quill.fromTree(tree);
155
194
  }
156
195
  }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * MemoryTransport — built-quiver transport over bytes the caller already holds,
3
+ * falling through to another transport for what the map does not carry.
4
+ * Internal; not exported from index.ts.
5
+ *
6
+ * Browser-safe: no `node:` imports at any level.
7
+ */
8
+ import type { BuiltTransport, FetchOptions } from '../built-loader.js';
9
+ export declare class MemoryTransport implements BuiltTransport {
10
+ private readonly fallback?;
11
+ private readonly files;
12
+ constructor(files: ReadonlyMap<string, Uint8Array>, fallback?: BuiltTransport | undefined);
13
+ /** The map answers first. `FetchOptions` reaches only the fallback: a held byte has no cache to revalidate against. */
14
+ fetchBytes(relativePath: string, opts?: FetchOptions): Promise<Uint8Array>;
15
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * MemoryTransport — built-quiver transport over bytes the caller already holds,
3
+ * falling through to another transport for what the map does not carry.
4
+ * Internal; not exported from index.ts.
5
+ *
6
+ * Browser-safe: no `node:` imports at any level.
7
+ */
8
+ import { QuiverError } from '../errors.js';
9
+ /** Keys are artifact-relative, as the loader asks for them; a leading `./` or `/` is stripped. */
10
+ function normalizeKeys(files) {
11
+ const out = new Map();
12
+ for (const [key, bytes] of files) {
13
+ out.set(key.replace(/^\.?\//, ''), bytes);
14
+ }
15
+ return out;
16
+ }
17
+ export class MemoryTransport {
18
+ fallback;
19
+ files;
20
+ constructor(files, fallback) {
21
+ this.fallback = fallback;
22
+ this.files = normalizeKeys(files);
23
+ }
24
+ /** The map answers first. `FetchOptions` reaches only the fallback: a held byte has no cache to revalidate against. */
25
+ async fetchBytes(relativePath, opts) {
26
+ const bytes = this.files.get(relativePath);
27
+ if (bytes !== undefined)
28
+ return bytes;
29
+ if (this.fallback === undefined) {
30
+ throw new QuiverError('transport_error', `No bytes held for "${relativePath}". Quiver.fromBuiltFiles needs the whole artifact; to hold part and fetch the rest, pass the map as Quiver.fromBuiltUrl's \`seed\`.`);
31
+ }
32
+ return this.fallback.fetchBytes(relativePath, opts);
33
+ }
34
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quillmark/quiver",
3
- "version": "0.19.0",
3
+ "version": "0.20.0",
4
4
  "description": "A quiver of Quillmark quills: load one, pack one, hand out quills.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -38,10 +38,11 @@
38
38
  "sideEffects": false,
39
39
  "files": [
40
40
  "dist",
41
+ "MIGRATION.md",
41
42
  "NOTICE"
42
43
  ],
43
44
  "peerDependencies": {
44
- "@quillmark/wasm": ">=0.101.0-0"
45
+ "@quillmark/wasm": ">=0.103.0-0"
45
46
  },
46
47
  "dependencies": {
47
48
  "fflate": "^0.8.2",