Skip to content
This repository was archived by the owner on Sep 19, 2025. It is now read-only.

Commit 05aee78

Browse files
authored
Switch from parameter-passing to using a facet (#15)
* Switch from parameter-passing to faceting * Update README * Ensure that all imports of VirtualTypeScript environment are type-only
1 parent 9728ec7 commit 05aee78

17 files changed

Lines changed: 115 additions & 114 deletions

README.md

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,13 @@ const compilerOpts = {};
6767
const env = createVirtualTypeScriptEnvironment(system, [], ts, compilerOpts);
6868
```
6969

70-
2. Install the sync extension:
70+
2. Install the facet and the sync extension:
7171

72-
This extension powers the rest: when you make changes in your
73-
editor, this mirrors them to the TypeScript environment using
72+
The facet configures the rest of the extensions
73+
with the right path and environment.
74+
75+
When you make changes in your
76+
editor, the sync extension mirrors them to the TypeScript environment using
7477
`createFile` and `updateFile` in the TypeScript compiler.
7578

7679
_Note, also, that we're supplying a path._ These extensions
@@ -81,7 +84,7 @@ as well as the `env` parameter which should be your TypeScript
8184
environment.
8285

8386
```ts
84-
import { tsSync } from "@valtown/codemirror-ts";
87+
import { tsSync, tsFacet } from "@valtown/codemirror-ts";
8588

8689
let env = "index.ts";
8790

@@ -92,7 +95,8 @@ let editor = new EditorView({
9295
typescript: true,
9396
jsx: true,
9497
}),
95-
tsSync({ env, path }),
98+
tsFacet.of({ env, path }),
99+
tsSync(),
96100
],
97101
parent: document.querySelector("#editor"),
98102
});
@@ -105,7 +109,7 @@ like this and added to the `extensions` array in the setup
105109
of your CodeMirror instance.
106110

107111
```ts
108-
tsLinter({ env, path });
112+
tsLinter();
109113
```
110114

111115
This uses the [@codemirror/lint](https://codemirror.net/docs/ref/#lint)
@@ -122,7 +126,7 @@ sources, we expose a [`CompletionSource`](https://codemirror.net/docs/ref/#autoc
122126

123127
```ts
124128
autocompletion({
125-
override: [tsAutocomplete({ env, path })],
129+
override: [tsAutocomplete()],
126130
});
127131
```
128132

@@ -135,10 +139,7 @@ a `CompletionContext` parameter._
135139
The hover definition can be used like the following:
136140

137141
```ts
138-
tsHover({
139-
env,
140-
path,
141-
});
142+
tsHover();
142143
```
143144

144145
Which automatically uses a default renderer. However, you can
@@ -147,8 +148,6 @@ to render custom UI if you want to, using the `renderTooltip` option.
147148

148149
```ts
149150
tsHover({
150-
env,
151-
path,
152151
renderTooltip: (info: HoverInfo) => {
153152
const div = document.createElement("div");
154153
if (info.quickInfo?.displayParts) {
@@ -236,15 +235,13 @@ that accept the `worker` instead of `env` as an argument.
236235

237236
```ts
238237
[
239-
tsSyncWorker({ worker, path }),
240-
tsLinterWorker({ worker, path }),
238+
tsFacetWorker.of({ worker, path }),
239+
tsSyncWorker(),
240+
tsLinterWorker(),
241241
autocompletion({
242-
override: [tsAutocompleteWorker({ worker, path })],
243-
}),
244-
tsHoverWorker({
245-
worker,
246-
path,
242+
override: [tsAutocompleteWorker()],
247243
}),
244+
tsHoverWorker(),
248245
];
249246
```
250247

demo/index.ts

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import {
1616
tsAutocompleteWorker,
1717
tsSync,
1818
tsSyncWorker,
19+
tsFacet,
20+
tsFacetWorker,
1921
} from "../src/index.js";
2022
import * as Comlink from "comlink";
2123
import { WorkerShape } from "../src/worker.js";
@@ -47,15 +49,13 @@ increment('not a number');`,
4749
typescript: true,
4850
jsx: true,
4951
}),
50-
tsSync({ env, path }),
51-
tsLinter({ env, path }),
52+
tsFacet.of({ env, path }),
53+
tsSync(),
54+
tsLinter(),
5255
autocompletion({
53-
override: [tsAutocomplete({ env, path })],
54-
}),
55-
tsHover({
56-
env,
57-
path,
56+
override: [tsAutocomplete()],
5857
}),
58+
tsHover(),
5959
],
6060
parent: document.querySelector("#editor")!,
6161
});
@@ -85,15 +85,13 @@ increment('not a number');`,
8585
typescript: true,
8686
jsx: true,
8787
}),
88-
tsSyncWorker({ worker, path }),
89-
tsLinterWorker({ worker, path }),
88+
tsFacetWorker.of({ worker, path }),
89+
tsSyncWorker(),
90+
tsLinterWorker(),
9091
autocompletion({
91-
override: [tsAutocompleteWorker({ worker, path })],
92-
}),
93-
tsHoverWorker({
94-
worker,
95-
path,
92+
override: [tsAutocompleteWorker()],
9693
}),
94+
tsHoverWorker(),
9795
],
9896
parent: document.querySelector("#editor-worker")!,
9997
});

src/autocomplete/tsAutocomplete.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,22 @@ import type {
33
CompletionResult,
44
CompletionSource,
55
} from "@codemirror/autocomplete";
6-
import { type VirtualTypeScriptEnvironment } from "@typescript/vfs";
76
import { getAutocompletion } from "./getAutocompletion.js";
7+
import { tsFacet } from "../facet/tsFacet.js";
88

99
/**
1010
* Create a `CompletionSource` that queries
1111
* the _on-thread_ TypeScript environments for autocompletions
1212
* at this character.
1313
*/
14-
export function tsAutocomplete({
15-
path,
16-
env,
17-
}: {
18-
path: string;
19-
env: VirtualTypeScriptEnvironment;
20-
}): CompletionSource {
14+
export function tsAutocomplete(): CompletionSource {
2115
return async (
2216
context: CompletionContext,
2317
): Promise<CompletionResult | null> => {
18+
const config = context.state.facet(tsFacet);
19+
if (!config) return null;
2420
return getAutocompletion({
25-
env,
26-
path,
21+
...config,
2722
context,
2823
});
2924
};

src/autocomplete/tsAutocompleteWorker.ts

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,20 @@ import type {
33
CompletionContext,
44
CompletionSource,
55
} from "@codemirror/autocomplete";
6-
import { type WorkerShape } from "../worker.js";
6+
import { tsFacetWorker } from "../index.js";
77

88
/**
99
* Create a `CompletionSource` that queries
1010
* the TypeScript environment in a web worker.
1111
*/
12-
export function tsAutocompleteWorker({
13-
path,
14-
worker,
15-
}: {
16-
path: string;
17-
worker: WorkerShape;
18-
}): CompletionSource {
12+
export function tsAutocompleteWorker(): CompletionSource {
1913
return async (
2014
context: CompletionContext,
2115
): Promise<CompletionResult | null> => {
22-
return worker.getAutocompletion({
23-
path,
16+
const config = context.state.facet(tsFacetWorker);
17+
if (!config) return null;
18+
return config.worker.getAutocompletion({
19+
path: config.path,
2420
// Reduce this object so that it's serializable.
2521
context: {
2622
pos: context.pos,

src/facet/tsFacet.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { combineConfig, Facet } from "@codemirror/state";
2+
import { type VirtualTypeScriptEnvironment } from "@typescript/vfs";
3+
4+
export const tsFacet = Facet.define<
5+
{
6+
path: string;
7+
env: VirtualTypeScriptEnvironment;
8+
},
9+
{
10+
path: string;
11+
env: VirtualTypeScriptEnvironment;
12+
} | null
13+
>({
14+
combine(configs) {
15+
return combineConfig(configs, {});
16+
},
17+
});

src/facet/tsFacetWorker.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { combineConfig, Facet } from "@codemirror/state";
2+
import { type WorkerShape } from "../worker.js";
3+
4+
export const tsFacetWorker = Facet.define<
5+
{
6+
path: string;
7+
worker: WorkerShape;
8+
},
9+
{
10+
path: string;
11+
worker: WorkerShape;
12+
} | null
13+
>({
14+
combine(configs) {
15+
return combineConfig(configs, {});
16+
},
17+
});

src/hover/getHover.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { type QuickInfo, type DefinitionInfo } from "typescript";
2-
import { VirtualTypeScriptEnvironment } from "@typescript/vfs";
2+
import { type VirtualTypeScriptEnvironment } from "@typescript/vfs";
33

44
/**
55
* This information is passed to the API consumer to allow

src/hover/tsHover.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,19 @@
11
import { hoverTooltip, Tooltip } from "@codemirror/view";
2-
import { type VirtualTypeScriptEnvironment } from "@typescript/vfs";
32
import { getHover } from "./getHover.js";
43
import { defaultRenderer, TooltipRenderer } from "./renderTooltip.js";
4+
import { tsFacet } from "../facet/tsFacet.js";
55

66
export function tsHover({
7-
env,
8-
path,
97
renderTooltip = defaultRenderer,
108
}: {
11-
env: VirtualTypeScriptEnvironment;
12-
path: string;
139
renderTooltip?: TooltipRenderer;
14-
}) {
10+
} = {}) {
1511
return hoverTooltip(async (view, pos): Promise<Tooltip | null> => {
12+
const config = view.state.facet(tsFacet);
13+
if (!config) return null;
14+
1615
const hoverData = getHover({
17-
env,
18-
path,
16+
...config,
1917
pos,
2018
});
2119

src/hover/tsHoverWorker.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
import { hoverTooltip, Tooltip } from "@codemirror/view";
2-
import { type WorkerShape } from "../worker.js";
32
import { defaultRenderer, type TooltipRenderer } from "./renderTooltip.js";
3+
import { tsFacetWorker } from "../index.js";
44

55
export function tsHoverWorker({
6-
worker,
7-
path,
86
renderTooltip = defaultRenderer,
97
}: {
10-
worker: WorkerShape;
11-
path: string;
128
renderTooltip?: TooltipRenderer;
13-
}) {
9+
} = {}) {
1410
return hoverTooltip(async (view, pos): Promise<Tooltip | null> => {
15-
const hoverData = await worker.getHover({
16-
path,
11+
const config = view.state.facet(tsFacetWorker);
12+
if (!config) return null;
13+
const hoverData = await config.worker.getHover({
14+
path: config.path,
1715
pos,
1816
});
1917

src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,6 @@ export * from "./lint/getLints.js";
1212
export * from "./hover/tsHover.js";
1313
export * from "./hover/tsHoverWorker.js";
1414
export * from "./hover/getHover.js";
15+
16+
export * from "./facet/tsFacet.js";
17+
export * from "./facet/tsFacetWorker.js";

0 commit comments

Comments
 (0)