@fossil-lang/wasm 0.3.0-alpha.7 → 0.3.0-alpha.9

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
@@ -2,7 +2,10 @@
2
2
 
3
3
  JS/TS wrapper around the `fossil-wasm` Rust crate's wasm-bindgen artefacts. Provides:
4
4
 
5
- - `initFossilWasm({ wasmUrl })` — consumer-controlled `.wasm` URL loader (memoised).
5
+ - `openProgram(uri, { host, text })` — one program open for an editor, and the
6
+ call a host with an editor makes. See below.
7
+ - `initFossilWasm()` — boots the module (memoised). Its `.wasm` ships in this
8
+ package and the host's bundler emits it as an asset; the host copies nothing.
6
9
  - `tokenize(text)` — calls the Rust lexer, returns `TokenRow[]`. The Rust lexer
7
10
  is the only lexer: no host reimplements one and drifts from the grammar.
8
11
  - `semanticLegend()` — returns the LSP semantic-tokens legend.
@@ -10,6 +13,29 @@ JS/TS wrapper around the `fossil-wasm` Rust crate's wasm-bindgen artefacts. Prov
10
13
  itself is native-only (stdio over crossbeam), so the browser gets this
11
14
  equivalent dispatch surface over the same `fossil-ide` functions.
12
15
 
16
+ ## One program in one editor: `openProgram`
17
+
18
+ ```typescript
19
+ import { openProgram } from '@fossil-lang/wasm';
20
+ import { fossil } from '@fossil-lang/codemirror-fossil';
21
+
22
+ const program = await openProgram('job.fossil', { host, text }); // host: SourceHost
23
+ const extensions = fossil({ ...program, onNavigate });
24
+
25
+ program.registerDescriptor(descriptor); // a host-introspected source, before a check
26
+ const sources = await program.sources(text); // what introspection DESCRIBEs
27
+ ```
28
+
29
+ It boots the module, opens `uri` in its own workspace, and reads the documents
30
+ the text names through `host`. The answer carries `fossil()`'s option names —
31
+ `uri`, `tokenize`, `tokenKinds`, `check`, `hover`, `complete`, `definition` —
32
+ and every one that answers about the program takes the text and pushes it
33
+ first, comparing against what it last pushed so the common case costs a string
34
+ comparison. `check` and `sources` also run `resolveDocuments`, which reads
35
+ nothing when nothing is missing. That is the whole protocol an editor host used
36
+ to write by hand; `workspace` is the `FossilPlayground` underneath, for a
37
+ question this surface does not ask, and `close()` frees it.
38
+
13
39
  ## Documents and sources: fossil resolves, the host reads
14
40
 
15
41
  A program names shape documents (`io.shex("@vocab/person.shex")`) and data
@@ -41,47 +67,50 @@ const rows = pg.check();
41
67
  locator, catalogue row, reader option. Introspection DESCRIBEs these and
42
68
  registers each descriptor under `key` with `registerInferredDescriptor`.
43
69
 
44
- ## Why explicit `init({ wasmUrl })` and not auto-load?
45
-
46
- We use `wasm-bindgen --target web` (NOT `--target bundler`). This means consumers
47
- control the `.wasm` URL resolution — works in Vite, Next.js, Webpack, Rspack, or
48
- plain `new URL(...)` in a Web Worker context. `--target bundler` was rejected
49
- because its output assumes the consumer's bundler resolves `.wasm` ESM imports,
50
- which a republished library cannot assume of a host's Vite/Next/Webpack config.
51
-
52
- ## Consumer patterns
53
-
54
- ### Vite host
70
+ ## Loading: the `.wasm` is an asset of this package
55
71
 
56
72
  ```typescript
57
73
  import { initFossilWasm, tokenize } from '@fossil-lang/wasm';
58
- import wasmUrl from '@fossil-lang/wasm/pkg/fossil_wasm_bg.wasm?url';
59
74
 
60
- await initFossilWasm({ wasmUrl });
75
+ await initFossilWasm();
61
76
  const tokens = tokenize('User := io.csv("data/people.csv")');
62
77
  ```
63
78
 
64
- ### Next.js host (in a Client Component)
79
+ That is the whole host flow, in Vite, Next.js (webpack or Turbopack), a Web
80
+ Worker or any bundler that understands `new URL('…', import.meta.url)`. The glue
81
+ (`wasm-bindgen --target web`) locates `fossil_wasm_bg.wasm` with exactly that
82
+ expression, the bundler copies the file into its output under a hashed name and
83
+ rewrites the URL, and the browser fetches it from there. No copy script, no
84
+ `public/` directory, no URL to keep in sync with a version.
85
+
86
+ **Vite dev server, package installed from npm:** Vite's dependency optimizer
87
+ pre-bundles the package into `node_modules/.vite/deps/` without its `.wasm`, and
88
+ the URL then answers with `index.html`. Keep the three packages out of it —
89
+ `vite build` needs nothing:
90
+
91
+ ```js
92
+ // vite.config.js
93
+ export default { optimizeDeps: { exclude: ['@fossil-lang/wasm', '@fossil-lang/executor', '@fossil-lang/corpus'] } };
94
+ ```
65
95
 
66
- ```typescript
67
- 'use client';
68
- import { initFossilWasm, tokenize } from '@fossil-lang/wasm';
96
+ A workspace-linked package is never pre-bundled, which is why the playground needs
97
+ no such line. Next.js needs none in either `next dev` or `next build`, webpack or
98
+ Turbopack.
69
99
 
70
- // Put fossil_wasm_bg.wasm in public/wasm/ at build time (next.config.mjs copies it)
71
- useEffect(() => {
72
- void initFossilWasm({ wasmUrl: '/wasm/fossil_wasm_bg.wasm' });
73
- }, []);
74
- ```
100
+ `--target bundler` was rejected because it emits `import … from '*.wasm'` (the
101
+ ESM-integration proposal), which each bundler gates behind its own experimental
102
+ flag. `new URL(…, import.meta.url)` is the pattern they all support by default.
75
103
 
76
- ### Web Worker
104
+ **Without a bundler**, pass the module yourself — `initFossilWasm(wasm)` takes the
105
+ glue's `InitInput` (`BufferSource`, `Response`, `URL`, `WebAssembly.Module`). Node
106
+ is the case: its `fetch` rejects `file://`, so hand it the bytes:
77
107
 
78
108
  ```typescript
79
- // inside a Worker module:
80
- import { initFossilWasm, FossilPlayground } from '@fossil-lang/wasm';
81
- import wasmUrl from '@fossil-lang/wasm/pkg/fossil_wasm_bg.wasm?url';
109
+ import { readFile } from 'node:fs/promises';
110
+ import { createRequire } from 'node:module';
82
111
 
83
- await initFossilWasm({ wasmUrl });
84
- const pg = new FossilPlayground();
112
+ const path = createRequire(import.meta.url).resolve('@fossil-lang/wasm/pkg/fossil_wasm_bg.wasm');
113
+ await initFossilWasm(await readFile(path));
85
114
  ```
86
115
 
87
116
  ## Build
package/dist/index.d.ts CHANGED
@@ -3,10 +3,13 @@
3
3
  *
4
4
  * Public API (one of the @fossil-lang/* packages; `git ls-files packages` is
5
5
  * the list):
6
- * - {@link initFossilWasm} — consumer-controlled .wasm URL loader (memoised).
6
+ * - {@link initFossilWasm} — boots the module; its `.wasm` is a bundler asset (memoised).
7
7
  * - {@link tokenize} — calls the Rust lexer, returns TokenRow[].
8
8
  * - {@link tokenKinds} — the legend for TokenRow.kind: variant names by index.
9
9
  * - {@link semanticLegend} — returns the LSP SemanticTokensLegend.
10
+ * - {@link openProgram} — one program open for an editor: the workspace, the push-before-ask
11
+ * discipline and the document resolution a host would otherwise write, shaped to spread into
12
+ * `@fossil-lang/codemirror-fossil`'s `fossil()`. What a host with one editor calls.
10
13
  * - {@link FossilPlayground} — Workspace API class: open / update / close,
11
14
  * `check`, the three position queries (`hover`, `completions`,
12
15
  * `gotoDefinition`) an editor draws its IDE surface from, and the documents
@@ -15,16 +18,18 @@
15
18
  *
16
19
  * Consumer pattern (wasm-bindgen --target web):
17
20
  *
18
- * import { initFossilWasm, tokenize } from '@fossil-lang/wasm';
19
- * import wasmUrl from '@fossil-lang/wasm/pkg/fossil_wasm_bg.wasm?url'; // Vite
21
+ * import { openProgram } from '@fossil-lang/wasm';
22
+ * import { fossil } from '@fossil-lang/codemirror-fossil';
20
23
  *
21
- * await initFossilWasm({ wasmUrl });
22
- * const tokens = tokenize('User := io.csv("data/people.csv")');
24
+ * const program = await openProgram('job.fossil', { host, text });
25
+ * const extensions = fossil({ ...program, onNavigate });
23
26
  */
24
27
  export { initFossilWasm } from './load.js';
25
- export type { InitFossilWasmOpts } from './load.js';
28
+ export type { InitInput } from './load.js';
26
29
  export { start_lsp_worker, tokenize, tokenKinds, semanticLegend, FossilPlayground, refs, providers, } from './client.js';
27
30
  export type { FileHandle } from './client.js';
31
+ export { openProgram } from './program.js';
32
+ export type { FossilProgram, OpenProgramOptions } from './program.js';
28
33
  /** One external reference a program makes — the typed lineage returned by
29
34
  * {@link refs}. Mirrors `fossil_lineage::SourceRefInfo` (the SAME struct the
30
35
  * native `fossil refs` emits). `connection` is the `@conn` alias the reference
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAQH,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,YAAY,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAEpD,OAAO,EACL,gBAAgB,EAChB,QAAQ,EACR,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,IAAI,EACJ,SAAS,GACV,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C;;;;4EAI4E;AAC5E,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;CACzB;AAED;;oEAEoE;AACpE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;CAClC;AAED;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,QAAQ,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;8EAE8E;AAC9E,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,GAAG,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1C;AAED;;;wDAGwD;AACxD,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,QAAQ,CAAC;CACjB;AAED;;;;;;;;;;;;;;aAca;AACb,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;gCAMgC;AAChC,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,QAAQ,CAAC;CACjB;AAYD;;;;;;;;;GASG;AACH,MAAM,MAAM,iBAAiB,GACzB,QAAQ,GACR,SAAS,GACT,OAAO,GACP,MAAM,GACN,MAAM,GACN,WAAW,GACX,MAAM,GACN,QAAQ,GACR,SAAS,CAAC;AAEd,kDAAkD;AAClD,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,iBAAiB,CAAC;CAC9B;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;;OAKG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,2EAA2E;IAC3E,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B;;;;;;OAMG;IACH,eAAe,EAAE,MAAM,CAAC;CACzB;AAKD,YAAY,EACV,QAAQ,EACR,oBAAoB,EACpB,UAAU,EACV,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,aAAa,GACd,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAQH,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,YAAY,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE3C,OAAO,EACL,gBAAgB,EAChB,QAAQ,EACR,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,IAAI,EACJ,SAAS,GACV,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEtE;;;;4EAI4E;AAC5E,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;CACzB;AAED;;oEAEoE;AACpE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;CAClC;AAED;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,QAAQ,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;8EAE8E;AAC9E,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,GAAG,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1C;AAED;;;wDAGwD;AACxD,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,QAAQ,CAAC;CACjB;AAED;;;;;;;;;;;;;;aAca;AACb,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;gCAMgC;AAChC,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,QAAQ,CAAC;CACjB;AAYD;;;;;;;;;GASG;AACH,MAAM,MAAM,iBAAiB,GACzB,QAAQ,GACR,SAAS,GACT,OAAO,GACP,MAAM,GACN,MAAM,GACN,WAAW,GACX,MAAM,GACN,QAAQ,GACR,SAAS,CAAC;AAEd,kDAAkD;AAClD,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,iBAAiB,CAAC;CAC9B;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;;OAKG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,2EAA2E;IAC3E,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B;;;;;;OAMG;IACH,eAAe,EAAE,MAAM,CAAC;CACzB;AAKD,YAAY,EACV,QAAQ,EACR,oBAAoB,EACpB,UAAU,EACV,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,aAAa,GACd,MAAM,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -3,10 +3,13 @@
3
3
  *
4
4
  * Public API (one of the @fossil-lang/* packages; `git ls-files packages` is
5
5
  * the list):
6
- * - {@link initFossilWasm} — consumer-controlled .wasm URL loader (memoised).
6
+ * - {@link initFossilWasm} — boots the module; its `.wasm` is a bundler asset (memoised).
7
7
  * - {@link tokenize} — calls the Rust lexer, returns TokenRow[].
8
8
  * - {@link tokenKinds} — the legend for TokenRow.kind: variant names by index.
9
9
  * - {@link semanticLegend} — returns the LSP SemanticTokensLegend.
10
+ * - {@link openProgram} — one program open for an editor: the workspace, the push-before-ask
11
+ * discipline and the document resolution a host would otherwise write, shaped to spread into
12
+ * `@fossil-lang/codemirror-fossil`'s `fossil()`. What a host with one editor calls.
10
13
  * - {@link FossilPlayground} — Workspace API class: open / update / close,
11
14
  * `check`, the three position queries (`hover`, `completions`,
12
15
  * `gotoDefinition`) an editor draws its IDE surface from, and the documents
@@ -15,11 +18,11 @@
15
18
  *
16
19
  * Consumer pattern (wasm-bindgen --target web):
17
20
  *
18
- * import { initFossilWasm, tokenize } from '@fossil-lang/wasm';
19
- * import wasmUrl from '@fossil-lang/wasm/pkg/fossil_wasm_bg.wasm?url'; // Vite
21
+ * import { openProgram } from '@fossil-lang/wasm';
22
+ * import { fossil } from '@fossil-lang/codemirror-fossil';
20
23
  *
21
- * await initFossilWasm({ wasmUrl });
22
- * const tokens = tokenize('User := io.csv("data/people.csv")');
24
+ * const program = await openProgram('job.fossil', { host, text });
25
+ * const extensions = fossil({ ...program, onNavigate });
23
26
  */
24
27
  // The wasm-bindgen glue (`../pkg/fossil_wasm.js`) is imported ONLY from leaf
25
28
  // modules — `load.ts` (init) and `client.ts` (the lexer / LSP / Workspace API) —
@@ -29,4 +32,5 @@
29
32
  // codemirror tokenizer hit on the main thread). This entry only re-exports.
30
33
  export { initFossilWasm } from './load.js';
31
34
  export { start_lsp_worker, tokenize, tokenKinds, semanticLegend, FossilPlayground, refs, providers, } from './client.js';
35
+ export { openProgram } from './program.js';
32
36
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,6EAA6E;AAC7E,iFAAiF;AACjF,iFAAiF;AACjF,2EAA2E;AAC3E,yEAAyE;AACzE,4EAA4E;AAC5E,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAG3C,OAAO,EACL,gBAAgB,EAChB,QAAQ,EACR,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,IAAI,EACJ,SAAS,GACV,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,6EAA6E;AAC7E,iFAAiF;AACjF,iFAAiF;AACjF,2EAA2E;AAC3E,yEAAyE;AACzE,4EAA4E;AAC5E,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAG3C,OAAO,EACL,gBAAgB,EAChB,QAAQ,EACR,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,IAAI,EACJ,SAAS,GACV,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC"}
package/dist/load.d.ts CHANGED
@@ -1,27 +1,19 @@
1
- /** Options for {@link initFossilWasm}. */
2
- export interface InitFossilWasmOpts {
3
- /**
4
- * URL or path to `fossil_wasm_bg.wasm`. Consumers control resolution:
5
- * - Vite: `import wasmUrl from '@fossil-lang/wasm/pkg/fossil_wasm_bg.wasm?url'`
6
- * - Next.js: serve from `public/` and pass the static URL (e.g. `'/wasm/fossil_wasm_bg.wasm'`)
7
- * - Web Worker: `new URL('@fossil-lang/wasm/pkg/fossil_wasm_bg.wasm', import.meta.url)`
8
- * - Node test: a `file://` URL resolved from `import.meta.url`
9
- *
10
- * Accepts `string` (a URL string), `URL`, a `Request`, or a `Response` —
11
- * matching `wasm-bindgen --target web`'s init signature.
12
- */
13
- wasmUrl: string | URL | Request | Response;
14
- }
1
+ import type { InitInput } from '../pkg/fossil_wasm.js';
2
+ export type { InitInput };
15
3
  /**
16
4
  * Boot the fossil-wasm module. MUST be awaited before calling any of
17
5
  * {@link tokenize}, {@link semanticLegend}, or instantiating
18
6
  * {@link FossilPlayground}. Memoised — subsequent calls return the same promise.
19
7
  *
20
- * With `wasm-bindgen --target web`, consumers control
21
- * the `.wasm` URL — this avoids tying library users to a specific bundler's
22
- * `.wasm` import magic. See `packages/wasm/README.md` for consumer patterns.
8
+ * **Called with nothing, the module finds its own `.wasm`.** The glue resolves
9
+ * `new URL('fossil_wasm_bg.wasm', import.meta.url)`, which is the pattern Vite,
10
+ * webpack 5 and Turbopack all recognise and emit as an asset — so a bundled host
11
+ * writes `await initFossilWasm()` and copies nothing.
12
+ *
13
+ * `wasm` is for the host with no bundler to do that: Node, whose `fetch` rejects
14
+ * `file://`, hands the bytes (`BufferSource`) or a `Response`.
23
15
  */
24
- export declare function initFossilWasm(opts: InitFossilWasmOpts): Promise<unknown>;
16
+ export declare function initFossilWasm(wasm?: InitInput): Promise<unknown>;
25
17
  /**
26
18
  * For tests + hot-reload — reset the memoised promise. NOT exported from the
27
19
  * package index (test-internal helper).
@@ -1 +1 @@
1
- {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../src/load.ts"],"names":[],"mappings":"AAMA,0CAA0C;AAC1C,MAAM,WAAW,kBAAkB;IACjC;;;;;;;;;OASG;IACH,OAAO,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,GAAG,QAAQ,CAAC;CAC5C;AAID;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC,CASzE;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAEtC"}
1
+ {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../src/load.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,YAAY,EAAE,SAAS,EAAE,CAAC;AAI1B;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAMjE;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAEtC"}
package/dist/load.js CHANGED
@@ -1,7 +1,6 @@
1
1
  // '../pkg/fossil_wasm.js' is a wasm-bindgen --target web output emitted by `pnpm run build:wasm`.
2
- // It is gitignored (per 08-01 .gitignore + repo .gitignore `packages/wasm/pkg/`) but always present at build time.
3
- // The accompanying fossil_wasm.d.ts is consumed via the file's `/* @ts-self-types="./fossil_wasm.d.ts" */` pragma —
4
- // TS 5.6 resolves the `import` to that side-channel `.d.ts` automatically (no `@ts-expect-error` needed).
2
+ // It is gitignored (repo .gitignore `packages/wasm/pkg/`) but always present at build time and in
3
+ // the published tarball. Its `.d.ts` is consumed via the file's `/* @ts-self-types */` pragma.
5
4
  import init from '../pkg/fossil_wasm.js';
6
5
  let _initPromise = null;
7
6
  /**
@@ -9,17 +8,18 @@ let _initPromise = null;
9
8
  * {@link tokenize}, {@link semanticLegend}, or instantiating
10
9
  * {@link FossilPlayground}. Memoised — subsequent calls return the same promise.
11
10
  *
12
- * With `wasm-bindgen --target web`, consumers control
13
- * the `.wasm` URL — this avoids tying library users to a specific bundler's
14
- * `.wasm` import magic. See `packages/wasm/README.md` for consumer patterns.
11
+ * **Called with nothing, the module finds its own `.wasm`.** The glue resolves
12
+ * `new URL('fossil_wasm_bg.wasm', import.meta.url)`, which is the pattern Vite,
13
+ * webpack 5 and Turbopack all recognise and emit as an asset — so a bundled host
14
+ * writes `await initFossilWasm()` and copies nothing.
15
+ *
16
+ * `wasm` is for the host with no bundler to do that: Node, whose `fetch` rejects
17
+ * `file://`, hands the bytes (`BufferSource`) or a `Response`.
15
18
  */
16
- export function initFossilWasm(opts) {
19
+ export function initFossilWasm(wasm) {
17
20
  if (!_initPromise) {
18
- // wasm-bindgen 0.2.120 init() prefers the `{ module_or_path }` object form;
19
- // passing the URL/Request/Response/BufferSource as a positional argument
20
- // still works but logs a deprecation warning ("pass a single object
21
- // instead"). We use the object form to stay on the maintained path.
22
- _initPromise = init({ module_or_path: opts.wasmUrl });
21
+ // The object form: the positional one still works but logs a deprecation warning.
22
+ _initPromise = init(wasm === undefined ? undefined : { module_or_path: wasm });
23
23
  }
24
24
  return _initPromise;
25
25
  }
package/dist/load.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"load.js","sourceRoot":"","sources":["../src/load.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,mHAAmH;AACnH,oHAAoH;AACpH,0GAA0G;AAC1G,OAAO,IAAI,MAAM,uBAAuB,CAAC;AAiBzC,IAAI,YAAY,GAA4B,IAAI,CAAC;AAEjD;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAAC,IAAwB;IACrD,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,4EAA4E;QAC5E,yEAAyE;QACzE,oEAAoE;QACpE,oEAAoE;QACpE,YAAY,GAAG,IAAI,CAAC,EAAE,cAAc,EAAE,IAAI,CAAC,OAAgB,EAAE,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe;IAC7B,YAAY,GAAG,IAAI,CAAC;AACtB,CAAC"}
1
+ {"version":3,"file":"load.js","sourceRoot":"","sources":["../src/load.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,kGAAkG;AAClG,+FAA+F;AAC/F,OAAO,IAAI,MAAM,uBAAuB,CAAC;AAKzC,IAAI,YAAY,GAA4B,IAAI,CAAC;AAEjD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,cAAc,CAAC,IAAgB;IAC7C,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,kFAAkF;QAClF,YAAY,GAAG,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe;IAC7B,YAAY,GAAG,IAAI,CAAC;AACtB,CAAC"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * One program, open in a workspace, answering an editor — what every host of the checker wrote by
3
+ * hand before this existed.
4
+ *
5
+ * `FossilPlayground` is the workspace and it is right that it stays general: it holds any number
6
+ * of files and answers about each. What a host with ONE program in ONE editor needs on top of it
7
+ * is always the same protocol, and two copies of it had already diverged in their comments:
8
+ *
9
+ * 1. **Push before you ask.** Four callers at four rates — the debounced linter, hover on pointer
10
+ * rest, completion on nearly every keystroke, goto-def on a key — share one workspace, and all
11
+ * four answer about the text of the last `updateFile`. So every entry point takes the text and
12
+ * pushes it first, and a string comparison against what was last pushed makes that free in the
13
+ * common case. `updateFile` is the one call that bumps the Salsa revision; calling it per
14
+ * mouse-move would invalidate the memoised check the squiggles came from for nothing.
15
+ * 2. **Read what the program names before you check it.** The compiler performs no IO. An edit
16
+ * can name a shape document the workspace has not read, so a check first runs
17
+ * `resolveDocuments` over the host's {@link SourceHost} — which reads nothing when nothing is
18
+ * missing.
19
+ *
20
+ * The result is shaped for `@fossil-lang/codemirror-fossil`'s `fossil()`: `tokenize`,
21
+ * `tokenKinds`, `uri`, `check`, `hover`, `complete` and `definition` are exactly its option
22
+ * names, so a host spreads it and adds what is its own to decide:
23
+ *
24
+ * ```ts
25
+ * const program = await openProgram('job.fossil', { host, text });
26
+ * const extensions = fossil({ ...program, onNavigate });
27
+ * ```
28
+ *
29
+ * One workspace rather than one per rate, for the reason `fossil()`'s own header gives: a second
30
+ * workspace for the position queries would answer from a different revision than the squiggles on
31
+ * screen. The position methods take a SHARED borrow on the Rust side, so they nest inside a live
32
+ * check rather than poisoning it.
33
+ */
34
+ import { type ProgramSource, type SourceHost } from '@fossil-lang/types';
35
+ import { FossilPlayground, tokenize, tokenKinds } from './client.js';
36
+ import type { CheckRow, CompletionRow, DefinitionRow, HoverRow, InferredDescriptorJson } from './index.js';
37
+ import { type InitInput } from './load.js';
38
+ /** What {@link openProgram} takes beside the key. */
39
+ export interface OpenProgramOptions {
40
+ /** The host's one capability: the connection map, and signing what the program names. */
41
+ host: SourceHost;
42
+ /** The buffer's text at open. Defaults to empty; every entry point takes the text anyway. */
43
+ text?: string;
44
+ /** How a signed document is read. Defaults to the global `fetch`. */
45
+ fetch?: typeof fetch;
46
+ /** The module's `.wasm`, for a host with no bundler — see {@link initFossilWasm}. */
47
+ wasm?: InitInput;
48
+ }
49
+ /**
50
+ * A program open in its own workspace. Every member that answers about the program takes the
51
+ * current text, and pushes it first — see the module header for why that repetition is the design.
52
+ */
53
+ export interface FossilProgram {
54
+ /** The key the program is open under — `CheckRow.uri` and `DefinitionRow.uri` carry it. */
55
+ readonly uri: string;
56
+ /** The compiler's lexer, for highlighting. Needs no workspace, and is here so the spread works. */
57
+ readonly tokenize: typeof tokenize;
58
+ /** The legend for a token's `kind`. */
59
+ readonly tokenKinds: typeof tokenKinds;
60
+ /**
61
+ * Push the text, read every document it names that the workspace lacks, and check. No debounce:
62
+ * `fossil()`'s linter waits out its own delay AND waits for this to return before it schedules
63
+ * again, which is what an LSP client does with `didChange`.
64
+ */
65
+ check(text: string): Promise<CheckRow[]>;
66
+ /** The type under the cursor, and the type the target shape demands of it — or `null`. */
67
+ hover(text: string, line: number, character: number): HoverRow | null;
68
+ /** The candidates at the cursor, narrowed by the receiver's type. */
69
+ complete(text: string, line: number, character: number): CompletionRow[];
70
+ /** Where the name under the cursor is defined. Often in the shape document: read `uri`. */
71
+ definition(text: string, line: number, character: number): DefinitionRow[];
72
+ /**
73
+ * The data sources the program reads, as fossil resolved them — what introspection DESCRIBEs.
74
+ * Resolves the documents first, because a source's locator goes through the connection map.
75
+ */
76
+ sources(text: string): Promise<ProgramSource[]>;
77
+ /**
78
+ * A host-introspected input schema, registered under the URI the program wrote. The compiler
79
+ * never introspects a source itself; push this before the check that should see it.
80
+ */
81
+ registerDescriptor(descriptor: InferredDescriptorJson): void;
82
+ /** The workspace underneath, for the rare question this surface does not ask. */
83
+ readonly workspace: FossilPlayground;
84
+ /** Free the workspace. Every member fails after it. */
85
+ close(): void;
86
+ }
87
+ /**
88
+ * Boot the module, open `uri` in a fresh workspace, and read the documents its text names.
89
+ *
90
+ * One call and the answer goes straight into `fossil()`. The boot is memoised, so a second program
91
+ * in the same tab costs a workspace and nothing else.
92
+ */
93
+ export declare function openProgram(uri: string, options: OpenProgramOptions): Promise<FossilProgram>;
94
+ //# sourceMappingURL=program.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,EAAoB,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAE3F,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,KAAK,EACV,QAAQ,EACR,aAAa,EACb,aAAa,EACb,QAAQ,EACR,sBAAsB,EACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAE3D,qDAAqD;AACrD,MAAM,WAAW,kBAAkB;IACjC,yFAAyF;IACzF,IAAI,EAAE,UAAU,CAAC;IACjB,6FAA6F;IAC7F,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,qFAAqF;IACrF,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,2FAA2F;IAC3F,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,mGAAmG;IACnG,QAAQ,CAAC,QAAQ,EAAE,OAAO,QAAQ,CAAC;IACnC,uCAAuC;IACvC,QAAQ,CAAC,UAAU,EAAE,OAAO,UAAU,CAAC;IACvC;;;;OAIG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IACzC,0FAA0F;IAC1F,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;IACtE,qEAAqE;IACrE,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,aAAa,EAAE,CAAC;IACzE,2FAA2F;IAC3F,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,aAAa,EAAE,CAAC;IAC3E;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IAChD;;;OAGG;IACH,kBAAkB,CAAC,UAAU,EAAE,sBAAsB,GAAG,IAAI,CAAC;IAC7D,iFAAiF;IACjF,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACrC,uDAAuD;IACvD,KAAK,IAAI,IAAI,CAAC;CACf;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,aAAa,CAAC,CAoDlG"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * One program, open in a workspace, answering an editor — what every host of the checker wrote by
3
+ * hand before this existed.
4
+ *
5
+ * `FossilPlayground` is the workspace and it is right that it stays general: it holds any number
6
+ * of files and answers about each. What a host with ONE program in ONE editor needs on top of it
7
+ * is always the same protocol, and two copies of it had already diverged in their comments:
8
+ *
9
+ * 1. **Push before you ask.** Four callers at four rates — the debounced linter, hover on pointer
10
+ * rest, completion on nearly every keystroke, goto-def on a key — share one workspace, and all
11
+ * four answer about the text of the last `updateFile`. So every entry point takes the text and
12
+ * pushes it first, and a string comparison against what was last pushed makes that free in the
13
+ * common case. `updateFile` is the one call that bumps the Salsa revision; calling it per
14
+ * mouse-move would invalidate the memoised check the squiggles came from for nothing.
15
+ * 2. **Read what the program names before you check it.** The compiler performs no IO. An edit
16
+ * can name a shape document the workspace has not read, so a check first runs
17
+ * `resolveDocuments` over the host's {@link SourceHost} — which reads nothing when nothing is
18
+ * missing.
19
+ *
20
+ * The result is shaped for `@fossil-lang/codemirror-fossil`'s `fossil()`: `tokenize`,
21
+ * `tokenKinds`, `uri`, `check`, `hover`, `complete` and `definition` are exactly its option
22
+ * names, so a host spreads it and adds what is its own to decide:
23
+ *
24
+ * ```ts
25
+ * const program = await openProgram('job.fossil', { host, text });
26
+ * const extensions = fossil({ ...program, onNavigate });
27
+ * ```
28
+ *
29
+ * One workspace rather than one per rate, for the reason `fossil()`'s own header gives: a second
30
+ * workspace for the position queries would answer from a different revision than the squiggles on
31
+ * screen. The position methods take a SHARED borrow on the Rust side, so they nest inside a live
32
+ * check rather than poisoning it.
33
+ */
34
+ import { resolveDocuments } from '@fossil-lang/types';
35
+ import { FossilPlayground, tokenize, tokenKinds } from './client.js';
36
+ import { initFossilWasm } from './load.js';
37
+ /**
38
+ * Boot the module, open `uri` in a fresh workspace, and read the documents its text names.
39
+ *
40
+ * One call and the answer goes straight into `fossil()`. The boot is memoised, so a second program
41
+ * in the same tab costs a workspace and nothing else.
42
+ */
43
+ export async function openProgram(uri, options) {
44
+ const { host, text = '', fetch: fetchImpl = globalThis.fetch, wasm } = options;
45
+ await initFossilWasm(wasm);
46
+ const workspace = new FossilPlayground();
47
+ const handle = workspace.openFile(uri, text);
48
+ let pushed = text;
49
+ const sync = (next) => {
50
+ if (next === pushed)
51
+ return;
52
+ workspace.updateFile(handle, next);
53
+ pushed = next;
54
+ };
55
+ const settle = async (next) => {
56
+ sync(next);
57
+ await resolveDocuments(workspace.workspace(handle), host, fetchImpl);
58
+ };
59
+ await settle(text);
60
+ return {
61
+ uri,
62
+ tokenize,
63
+ tokenKinds,
64
+ async check(next) {
65
+ await settle(next);
66
+ return workspace.check();
67
+ },
68
+ hover(next, line, character) {
69
+ sync(next);
70
+ return workspace.hover(handle, line, character);
71
+ },
72
+ complete(next, line, character) {
73
+ sync(next);
74
+ return workspace.completions(handle, line, character);
75
+ },
76
+ definition(next, line, character) {
77
+ sync(next);
78
+ return workspace.gotoDefinition(handle, line, character);
79
+ },
80
+ async sources(next) {
81
+ await settle(next);
82
+ return workspace.sources(handle);
83
+ },
84
+ registerDescriptor(descriptor) {
85
+ workspace.registerInferredDescriptor(descriptor);
86
+ },
87
+ workspace,
88
+ close() {
89
+ workspace.free();
90
+ },
91
+ };
92
+ }
93
+ //# sourceMappingURL=program.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"program.js","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,EAAE,gBAAgB,EAAuC,MAAM,oBAAoB,CAAC;AAE3F,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAQrE,OAAO,EAAE,cAAc,EAAkB,MAAM,WAAW,CAAC;AAqD3D;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAW,EAAE,OAA2B;IACxE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,GAAG,UAAU,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IAC/E,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;IAE3B,MAAM,SAAS,GAAG,IAAI,gBAAgB,EAAE,CAAC;IACzC,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC7C,IAAI,MAAM,GAAG,IAAI,CAAC;IAElB,MAAM,IAAI,GAAG,CAAC,IAAY,EAAQ,EAAE;QAClC,IAAI,IAAI,KAAK,MAAM;YAAE,OAAO;QAC5B,SAAS,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACnC,MAAM,GAAG,IAAI,CAAC;IAChB,CAAC,CAAC;IACF,MAAM,MAAM,GAAG,KAAK,EAAE,IAAY,EAAiB,EAAE;QACnD,IAAI,CAAC,IAAI,CAAC,CAAC;QACX,MAAM,gBAAgB,CAAC,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IACvE,CAAC,CAAC;IAEF,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;IAEnB,OAAO;QACL,GAAG;QACH,QAAQ;QACR,UAAU;QACV,KAAK,CAAC,KAAK,CAAC,IAAI;YACd,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;YACnB,OAAO,SAAS,CAAC,KAAK,EAAE,CAAC;QAC3B,CAAC;QACD,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS;YACzB,IAAI,CAAC,IAAI,CAAC,CAAC;YACX,OAAO,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QAClD,CAAC;QACD,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS;YAC5B,IAAI,CAAC,IAAI,CAAC,CAAC;YACX,OAAO,SAAS,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QACxD,CAAC;QACD,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS;YAC9B,IAAI,CAAC,IAAI,CAAC,CAAC;YACX,OAAO,SAAS,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QAC3D,CAAC;QACD,KAAK,CAAC,OAAO,CAAC,IAAI;YAChB,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;YACnB,OAAO,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC;QACD,kBAAkB,CAAC,UAAU;YAC3B,SAAS,CAAC,0BAA0B,CAAC,UAAU,CAAC,CAAC;QACnD,CAAC;QACD,SAAS;QACT,KAAK;YACH,SAAS,CAAC,IAAI,EAAE,CAAC;QACnB,CAAC;KACF,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fossil-lang/wasm",
3
- "version": "0.3.0-alpha.7",
3
+ "version": "0.3.0-alpha.9",
4
4
  "description": "JS/TS wrapper around the fossil-wasm wasm-bindgen artifacts (--target web). Exposes initFossilWasm + tokenize + semanticLegend + FossilPlayground class for downstream @fossil-lang/* packages.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -33,7 +33,7 @@
33
33
  ],
34
34
  "sideEffects": false,
35
35
  "dependencies": {
36
- "@fossil-lang/types": "0.3.0-alpha.7"
36
+ "@fossil-lang/types": "0.3.0-alpha.9"
37
37
  },
38
38
  "devDependencies": {
39
39
  "typescript": "^5.6.0",