@brass-build/client 0.3.0 → 0.4.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.
Files changed (128) hide show
  1. package/AGENTS.md +26 -5
  2. package/CHANGELOG.md +50 -2
  3. package/README.md +233 -77
  4. package/dist/acting-organization.d.ts +131 -0
  5. package/dist/acting-organization.d.ts.map +1 -0
  6. package/dist/acting-organization.js +278 -0
  7. package/dist/acting-organization.js.map +1 -0
  8. package/dist/api-headers.js +7 -7
  9. package/dist/api-headers.js.map +1 -1
  10. package/dist/call-service.d.ts +74 -0
  11. package/dist/call-service.d.ts.map +1 -0
  12. package/dist/call-service.js +253 -0
  13. package/dist/call-service.js.map +1 -0
  14. package/dist/client.d.ts +28 -0
  15. package/dist/client.d.ts.map +1 -1
  16. package/dist/client.js +555 -11
  17. package/dist/client.js.map +1 -1
  18. package/dist/document-contents.d.ts +15 -0
  19. package/dist/document-contents.d.ts.map +1 -0
  20. package/dist/document-contents.js +88 -0
  21. package/dist/document-contents.js.map +1 -0
  22. package/dist/document-streams.d.ts +4 -2
  23. package/dist/document-streams.d.ts.map +1 -1
  24. package/dist/document-streams.js +6 -0
  25. package/dist/document-streams.js.map +1 -1
  26. package/dist/documents.d.ts +45 -1
  27. package/dist/documents.d.ts.map +1 -1
  28. package/dist/documents.js +305 -22
  29. package/dist/documents.js.map +1 -1
  30. package/dist/export-guest.d.ts.map +1 -1
  31. package/dist/export-guest.js +5 -0
  32. package/dist/export-guest.js.map +1 -1
  33. package/dist/handle-types.d.ts +23 -0
  34. package/dist/handle-types.d.ts.map +1 -1
  35. package/dist/handles.d.ts +1 -1
  36. package/dist/handles.d.ts.map +1 -1
  37. package/dist/handles.js +1 -1
  38. package/dist/handles.js.map +1 -1
  39. package/dist/hosted-ui.d.ts +10 -0
  40. package/dist/hosted-ui.d.ts.map +1 -1
  41. package/dist/hosted-ui.js +115 -30
  42. package/dist/hosted-ui.js.map +1 -1
  43. package/dist/importer.d.ts.map +1 -1
  44. package/dist/importer.js +17 -6
  45. package/dist/importer.js.map +1 -1
  46. package/dist/index.d.ts +8 -3
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +25 -1
  49. package/dist/index.js.map +1 -1
  50. package/dist/internal.d.ts +1 -0
  51. package/dist/internal.d.ts.map +1 -1
  52. package/dist/internal.js +1 -0
  53. package/dist/internal.js.map +1 -1
  54. package/dist/mutate-batching.js +2 -2
  55. package/dist/mutate-batching.js.map +1 -1
  56. package/dist/open-document.d.ts +1 -1
  57. package/dist/open-document.d.ts.map +1 -1
  58. package/dist/open-document.js +69 -34
  59. package/dist/open-document.js.map +1 -1
  60. package/dist/presence.d.ts +10 -0
  61. package/dist/presence.d.ts.map +1 -1
  62. package/dist/presence.js.map +1 -1
  63. package/dist/session-toolbar.d.ts +9 -0
  64. package/dist/session-toolbar.d.ts.map +1 -1
  65. package/dist/session-toolbar.js +60 -12
  66. package/dist/session-toolbar.js.map +1 -1
  67. package/dist/tail-ops.js +2 -2
  68. package/dist/tail-ops.js.map +1 -1
  69. package/dist/types.d.ts +0 -42
  70. package/dist/types.d.ts.map +1 -1
  71. package/dist/undo.d.ts +1 -1
  72. package/dist/undo.d.ts.map +1 -1
  73. package/dist/undo.js +1 -1
  74. package/dist/undo.js.map +1 -1
  75. package/dist/version-bar.d.ts.map +1 -1
  76. package/dist/version-bar.js +52 -2
  77. package/dist/version-bar.js.map +1 -1
  78. package/dist/version.d.ts +2 -2
  79. package/dist/version.js +1 -1
  80. package/dist/wasm-ready-gate.d.ts +13 -0
  81. package/dist/wasm-ready-gate.d.ts.map +1 -0
  82. package/dist/wasm-ready-gate.js +28 -0
  83. package/dist/wasm-ready-gate.js.map +1 -0
  84. package/dist/wasm-runtime.browser.d.ts +11 -0
  85. package/dist/wasm-runtime.browser.d.ts.map +1 -0
  86. package/dist/wasm-runtime.browser.js +44 -0
  87. package/dist/wasm-runtime.browser.js.map +1 -0
  88. package/dist/wasm-runtime.d.ts +6 -0
  89. package/dist/wasm-runtime.d.ts.map +1 -0
  90. package/dist/wasm-runtime.js +20 -0
  91. package/dist/wasm-runtime.js.map +1 -0
  92. package/docs/app-manifest.md +335 -5
  93. package/docs/custom-chrome.md +3 -0
  94. package/docs/presence.md +12 -0
  95. package/docs/services.md +265 -0
  96. package/docs/text-fields.md +191 -0
  97. package/package.json +4 -5
  98. package/src/acting-organization.ts +396 -0
  99. package/src/api-headers.ts +7 -7
  100. package/src/call-service.ts +354 -0
  101. package/src/client.ts +618 -13
  102. package/src/document-contents.ts +104 -0
  103. package/src/document-streams.ts +15 -1
  104. package/src/documents.ts +340 -20
  105. package/src/export-guest.ts +5 -0
  106. package/src/handle-types.ts +35 -0
  107. package/src/handles.ts +1 -1
  108. package/src/hosted-ui.ts +155 -29
  109. package/src/importer.ts +17 -6
  110. package/src/index.ts +43 -4
  111. package/src/internal.ts +4 -0
  112. package/src/mutate-batching.ts +2 -2
  113. package/src/open-document.ts +79 -38
  114. package/src/presence.ts +6 -0
  115. package/src/session-toolbar.ts +80 -12
  116. package/src/tail-ops.ts +2 -2
  117. package/src/types.ts +6 -4
  118. package/src/undo.ts +1 -1
  119. package/src/version-bar.ts +53 -2
  120. package/src/version.ts +1 -1
  121. package/src/wasm-ready-gate.ts +30 -0
  122. package/src/wasm-runtime.browser.ts +48 -0
  123. package/src/wasm-runtime.ts +21 -0
  124. package/dist/vite.d.ts +0 -31
  125. package/dist/vite.d.ts.map +0 -1
  126. package/dist/vite.js +0 -161
  127. package/dist/vite.js.map +0 -1
  128. package/src/vite.ts +0 -214
@@ -0,0 +1,21 @@
1
+ // The node half of the WASM runtime seam. Node resolves each WASM-shipping
2
+ // dependency to its own node build, which readies its module as it is
3
+ // imported, so there is nothing to await and `ensureWasmReady` is the same
4
+ // call answering immediately.
5
+ //
6
+ // This is the half every importer names, so a build that applies no
7
+ // substitution at all (tsc, a node-targeting esbuild, the test runner) is
8
+ // already correct, and the browser half's `import.meta.url` asset resolution
9
+ // never reaches a bundler targeting node. `package.json`'s `browser` map
10
+ // swaps in the browser half for a bundler building this package for one, and
11
+ // `ensureWasmReady` exists so a caller awaits readiness the same way whichever
12
+ // half it got.
13
+
14
+ export * from 'loro-crdt';
15
+
16
+ /** Resolve once every WASM module this package needs is ready to run. Already
17
+ * true here: a node build readies its module during import, so the callers
18
+ * that await it on the browser half wait for nothing on this one. */
19
+ export function ensureWasmReady(): Promise<void> {
20
+ return Promise.resolve();
21
+ }
package/dist/vite.d.ts DELETED
@@ -1,31 +0,0 @@
1
- interface ViteAliasEntry {
2
- find: string | RegExp;
3
- replacement: string;
4
- }
5
- interface ViteBuildOptions {
6
- target?: string | string[] | false;
7
- }
8
- interface ViteUserConfig {
9
- build?: ViteBuildOptions;
10
- environments?: {
11
- client?: {
12
- build?: ViteBuildOptions;
13
- };
14
- };
15
- resolve?: {
16
- alias?: Record<string, string> | readonly ViteAliasEntry[];
17
- };
18
- optimizeDeps?: {
19
- exclude?: string[];
20
- esbuildOptions?: {
21
- target?: string | string[];
22
- };
23
- };
24
- }
25
- interface VitePlugin {
26
- name: string;
27
- config(config: ViteUserConfig): Promise<ViteUserConfig>;
28
- }
29
- export declare function brassVite(): VitePlugin;
30
- export {};
31
- //# sourceMappingURL=vite.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"AA+CA,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,gBAAgB;IACxB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,KAAK,CAAC;CACpC;AAED,UAAU,cAAc;IACtB,KAAK,CAAC,EAAE,gBAAgB,CAAC;IAGzB,YAAY,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE;YAAE,KAAK,CAAC,EAAE,gBAAgB,CAAA;SAAE,CAAA;KAAE,CAAC;IACzD,OAAO,CAAC,EAAE;QACR,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,cAAc,EAAE,CAAC;KAC5D,CAAC;IACF,YAAY,CAAC,EAAE;QACb,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QACnB,cAAc,CAAC,EAAE;YAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;SAAE,CAAC;KACjD,CAAC;CACH;AAED,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CACzD;AAoGD,wBAAgB,SAAS,IAAI,UAAU,CAwCtC"}
package/dist/vite.js DELETED
@@ -1,161 +0,0 @@
1
- // Vite plugin encapsulating the bundler config the SDK's WASM runtime
2
- // needs, so users never name the underlying WASM dep in their own
3
- // `vite.config.ts`.
4
- //
5
- // Vite's dep-prebundling targets older browsers by default and fails on the
6
- // WASM dep's top-level await (`Top-level await is not available in the
7
- // configured target environment for loro-crdt/bundler/loro_wasm.js`). The
8
- // plugin excludes the dep from prebundling (leaving it for the build-time
9
- // WASM loaders) and bumps the prebundle target to es2022.
10
- //
11
- // `vite-plugin-wasm` remains the caller's responsibility: it must land before
12
- // `brassVite()` in the plugin list.
13
- // Every WASM-shipping dep the SDK pulls in, and the entry that loads it
14
- // asynchronously. Add an entry rather than replacing the list: a consumer who
15
- // has two installed during a migration window needs both handled, and this is
16
- // the one place any of them is named, so an app's own config never is.
17
- //
18
- // A default browser entry fetches its module with a SYNCHRONOUS
19
- // XMLHttpRequest while it evaluates, so an app freezes its main thread for the
20
- // whole download before it paints, whether or not anyone opens a document, and
21
- // the freeze grows with the reader's latency rather than with the app. An
22
- // `asyncEntry` hands the same module to the bundler's own asset pipeline,
23
- // which loads it asynchronously and leaves the main thread free. Selecting one
24
- // emits a top-level await, so it is reachable only on a build target that
25
- // accepts one, and the synchronous entry is what keeps every other target
26
- // building.
27
- const WASM_DEPS = [
28
- { specifier: 'loro-crdt', asyncEntry: 'loro-crdt/bundler' },
29
- ];
30
- // A specifier matched whole. A string `find` matches by prefix, which would
31
- // also catch the async entry the alias points AT and resolve it to itself.
32
- const wholeSpecifier = (specifier) => new RegExp(`^${specifier.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}$`);
33
- // Vite 8 prebundles with rolldown, which handles top-level await on its own
34
- // and deprecates `optimizeDeps.esbuildOptions`. Setting it there does nothing
35
- // except print a deprecation warning naming this plugin, on every `vite dev`
36
- // and every `vite build` a consumer runs. Read from the running Vite rather
37
- // than from the consumer's manifest, and treat an unreadable version as an
38
- // older Vite, where the target bump is what makes the WASM dep load at all.
39
- //
40
- // The specifier is held in a variable so `tsc` does not resolve it. Vite is
41
- // neither a dependency nor a peer dependency here (the config shapes above are
42
- // declared for the same reason), so a literal specifier fails the build
43
- // wherever Vite is absent, which includes `npm install` in this package
44
- // itself. At runtime the import reaches the Vite running the build.
45
- const VITE_PACKAGE = 'vite';
46
- async function viteMajor() {
47
- try {
48
- const { version } = (await import(VITE_PACKAGE));
49
- const major = Number.parseInt(version ?? '', 10);
50
- return Number.isFinite(major) ? major : null;
51
- }
52
- catch {
53
- return null;
54
- }
55
- }
56
- // Browser versions that first shipped top-level await, by the engine names
57
- // esbuild accepts in a target string. A target naming an engine absent here is
58
- // read as unsupported.
59
- const TOP_LEVEL_AWAIT_SINCE = {
60
- chrome: 89,
61
- edge: 89,
62
- firefox: 89,
63
- safari: 15,
64
- ios: 15,
65
- opera: 75,
66
- node: 14.8,
67
- es: 2022,
68
- hermes: Number.POSITIVE_INFINITY,
69
- ie: Number.POSITIVE_INFINITY,
70
- };
71
- // Vite's own named targets. `modules` (the Vite 5 / 6 default) resolves to
72
- // browsers predating top-level await; `baseline-widely-available` (the Vite 7 /
73
- // 8 default) resolves to ones that carry it.
74
- const NAMED_TARGET_SUPPORT = {
75
- esnext: true,
76
- 'baseline-widely-available': true,
77
- modules: false,
78
- };
79
- function targetSupportsTopLevelAwait(target) {
80
- const t = target.trim().toLowerCase();
81
- const named = NAMED_TARGET_SUPPORT[t];
82
- if (named !== undefined)
83
- return named;
84
- const parsed = /^([a-z]+)([\d.]+)$/.exec(t);
85
- if (!parsed)
86
- return false;
87
- const since = TOP_LEVEL_AWAIT_SINCE[parsed[1]];
88
- if (since === undefined)
89
- return false;
90
- const version = Number.parseFloat(parsed[2]);
91
- return Number.isFinite(version) && version >= since;
92
- }
93
- // Whether the build this plugin is configuring can carry a top-level await.
94
- // An unreadable or unrecognised target answers `false`, so the worst a wrong
95
- // reading costs is the synchronous entry a consumer already has.
96
- function buildAcceptsTopLevelAwait(config, major) {
97
- const target = config.environments?.client?.build?.target ?? config.build?.target;
98
- // No explicit target: the answer is Vite's own default, which carries
99
- // top-level await from Vite 7 (`baseline-widely-available`) and not before
100
- // (`modules`).
101
- if (target === undefined)
102
- return major !== null && major >= 7;
103
- if (target === false)
104
- return false;
105
- const targets = Array.isArray(target) ? target : [target];
106
- return targets.length > 0 && targets.every(targetSupportsTopLevelAwait);
107
- }
108
- // A consumer who already resolves the WASM dep themselves owns that decision,
109
- // so the plugin adds nothing that would take it over.
110
- function aliasesWasmDep(config) {
111
- const alias = config.resolve?.alias;
112
- if (!alias)
113
- return false;
114
- const specifiers = WASM_DEPS.map((dep) => dep.specifier);
115
- if (Array.isArray(alias)) {
116
- return alias.some((entry) => specifiers.some((specifier) => typeof entry.find === 'string'
117
- ? entry.find === specifier
118
- : entry.find.test(specifier)));
119
- }
120
- return Object.keys(alias).some((key) => specifiers.includes(key));
121
- }
122
- export function brassVite() {
123
- return {
124
- name: 'brass-build:vite',
125
- async config(config) {
126
- const major = await viteMajor();
127
- const useAsyncEntry = buildAcceptsTopLevelAwait(config, major) && !aliasesWasmDep(config);
128
- const existingExclude = config.optimizeDeps?.exclude ?? [];
129
- const exclude = Array.from(new Set([
130
- ...existingExclude,
131
- ...WASM_DEPS.map((dep) => dep.specifier),
132
- ...(useAsyncEntry ? WASM_DEPS.map((dep) => dep.asyncEntry) : []),
133
- ]));
134
- const resolve = useAsyncEntry
135
- ? {
136
- resolve: {
137
- alias: WASM_DEPS.map((dep) => ({
138
- find: wholeSpecifier(dep.specifier),
139
- replacement: dep.asyncEntry,
140
- })),
141
- },
142
- }
143
- : {};
144
- if (major !== null && major >= 8) {
145
- return { ...resolve, optimizeDeps: { exclude } };
146
- }
147
- const existingTarget = config.optimizeDeps?.esbuildOptions?.target;
148
- // Don't downgrade if a consumer has already pinned a newer
149
- // target; only raise from the Vite default (which lacks TLA).
150
- const target = existingTarget ?? 'es2022';
151
- return {
152
- ...resolve,
153
- optimizeDeps: {
154
- exclude,
155
- esbuildOptions: { target },
156
- },
157
- };
158
- },
159
- };
160
- }
161
- //# sourceMappingURL=vite.js.map
package/dist/vite.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"vite.js","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"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"}
package/src/vite.ts DELETED
@@ -1,214 +0,0 @@
1
- // Vite plugin encapsulating the bundler config the SDK's WASM runtime
2
- // needs, so users never name the underlying WASM dep in their own
3
- // `vite.config.ts`.
4
- //
5
- // Vite's dep-prebundling targets older browsers by default and fails on the
6
- // WASM dep's top-level await (`Top-level await is not available in the
7
- // configured target environment for loro-crdt/bundler/loro_wasm.js`). The
8
- // plugin excludes the dep from prebundling (leaving it for the build-time
9
- // WASM loaders) and bumps the prebundle target to es2022.
10
- //
11
- // `vite-plugin-wasm` remains the caller's responsibility: it must land before
12
- // `brassVite()` in the plugin list.
13
-
14
- // Every WASM-shipping dep the SDK pulls in, and the entry that loads it
15
- // asynchronously. Add an entry rather than replacing the list: a consumer who
16
- // has two installed during a migration window needs both handled, and this is
17
- // the one place any of them is named, so an app's own config never is.
18
- //
19
- // A default browser entry fetches its module with a SYNCHRONOUS
20
- // XMLHttpRequest while it evaluates, so an app freezes its main thread for the
21
- // whole download before it paints, whether or not anyone opens a document, and
22
- // the freeze grows with the reader's latency rather than with the app. An
23
- // `asyncEntry` hands the same module to the bundler's own asset pipeline,
24
- // which loads it asynchronously and leaves the main thread free. Selecting one
25
- // emits a top-level await, so it is reachable only on a build target that
26
- // accepts one, and the synchronous entry is what keeps every other target
27
- // building.
28
- const WASM_DEPS: readonly { specifier: string; asyncEntry: string }[] = [
29
- { specifier: 'loro-crdt', asyncEntry: 'loro-crdt/bundler' },
30
- ];
31
-
32
- // A specifier matched whole. A string `find` matches by prefix, which would
33
- // also catch the async entry the alias points AT and resolve it to itself.
34
- const wholeSpecifier = (specifier: string): RegExp =>
35
- new RegExp(`^${specifier.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}$`);
36
-
37
- // The shape this plugin reads and returns, declared here rather than imported
38
- // so the SDK does not depend on Vite to describe its own plugin.
39
- //
40
- // Each field has to be at least as WIDE as Vite's own, because Vite passes its
41
- // `UserConfig` into the `config` hook and a hook declared over a narrower
42
- // config is not assignable to Vite's `Plugin`. `target` is the one that bites:
43
- // esbuild types it `string | string[]`, so declaring it `string` makes
44
- // `plugins: [brassVite()]` fail to type-check in a consumer's own
45
- // `vite.config.ts` (verified against Vite 5, 6 and 7; Vite 8 narrowed its own
46
- // type and hid it). The plugin only ever passes the value through, so the
47
- // wider type costs nothing here.
48
- interface ViteAliasEntry {
49
- find: string | RegExp;
50
- replacement: string;
51
- }
52
-
53
- interface ViteBuildOptions {
54
- target?: string | string[] | false;
55
- }
56
-
57
- interface ViteUserConfig {
58
- build?: ViteBuildOptions;
59
- // Vite 8 lets a consumer set the browser build's target per environment, and
60
- // that value, not the top-level one, is what the client bundle is built to.
61
- environments?: { client?: { build?: ViteBuildOptions } };
62
- resolve?: {
63
- alias?: Record<string, string> | readonly ViteAliasEntry[];
64
- };
65
- optimizeDeps?: {
66
- exclude?: string[];
67
- esbuildOptions?: { target?: string | string[] };
68
- };
69
- }
70
-
71
- interface VitePlugin {
72
- name: string;
73
- config(config: ViteUserConfig): Promise<ViteUserConfig>;
74
- }
75
-
76
- // Vite 8 prebundles with rolldown, which handles top-level await on its own
77
- // and deprecates `optimizeDeps.esbuildOptions`. Setting it there does nothing
78
- // except print a deprecation warning naming this plugin, on every `vite dev`
79
- // and every `vite build` a consumer runs. Read from the running Vite rather
80
- // than from the consumer's manifest, and treat an unreadable version as an
81
- // older Vite, where the target bump is what makes the WASM dep load at all.
82
- //
83
- // The specifier is held in a variable so `tsc` does not resolve it. Vite is
84
- // neither a dependency nor a peer dependency here (the config shapes above are
85
- // declared for the same reason), so a literal specifier fails the build
86
- // wherever Vite is absent, which includes `npm install` in this package
87
- // itself. At runtime the import reaches the Vite running the build.
88
- const VITE_PACKAGE = 'vite';
89
-
90
- async function viteMajor(): Promise<number | null> {
91
- try {
92
- const { version } = (await import(VITE_PACKAGE)) as { version?: string };
93
- const major = Number.parseInt(version ?? '', 10);
94
- return Number.isFinite(major) ? major : null;
95
- } catch {
96
- return null;
97
- }
98
- }
99
-
100
- // Browser versions that first shipped top-level await, by the engine names
101
- // esbuild accepts in a target string. A target naming an engine absent here is
102
- // read as unsupported.
103
- const TOP_LEVEL_AWAIT_SINCE: Readonly<Record<string, number>> = {
104
- chrome: 89,
105
- edge: 89,
106
- firefox: 89,
107
- safari: 15,
108
- ios: 15,
109
- opera: 75,
110
- node: 14.8,
111
- es: 2022,
112
- hermes: Number.POSITIVE_INFINITY,
113
- ie: Number.POSITIVE_INFINITY,
114
- };
115
-
116
- // Vite's own named targets. `modules` (the Vite 5 / 6 default) resolves to
117
- // browsers predating top-level await; `baseline-widely-available` (the Vite 7 /
118
- // 8 default) resolves to ones that carry it.
119
- const NAMED_TARGET_SUPPORT: Readonly<Record<string, boolean>> = {
120
- esnext: true,
121
- 'baseline-widely-available': true,
122
- modules: false,
123
- };
124
-
125
- function targetSupportsTopLevelAwait(target: string): boolean {
126
- const t = target.trim().toLowerCase();
127
- const named = NAMED_TARGET_SUPPORT[t];
128
- if (named !== undefined) return named;
129
- const parsed = /^([a-z]+)([\d.]+)$/.exec(t);
130
- if (!parsed) return false;
131
- const since = TOP_LEVEL_AWAIT_SINCE[parsed[1] as string];
132
- if (since === undefined) return false;
133
- const version = Number.parseFloat(parsed[2] as string);
134
- return Number.isFinite(version) && version >= since;
135
- }
136
-
137
- // Whether the build this plugin is configuring can carry a top-level await.
138
- // An unreadable or unrecognised target answers `false`, so the worst a wrong
139
- // reading costs is the synchronous entry a consumer already has.
140
- function buildAcceptsTopLevelAwait(
141
- config: ViteUserConfig,
142
- major: number | null,
143
- ): boolean {
144
- const target = config.environments?.client?.build?.target ?? config.build?.target;
145
- // No explicit target: the answer is Vite's own default, which carries
146
- // top-level await from Vite 7 (`baseline-widely-available`) and not before
147
- // (`modules`).
148
- if (target === undefined) return major !== null && major >= 7;
149
- if (target === false) return false;
150
- const targets = Array.isArray(target) ? target : [target];
151
- return targets.length > 0 && targets.every(targetSupportsTopLevelAwait);
152
- }
153
-
154
- // A consumer who already resolves the WASM dep themselves owns that decision,
155
- // so the plugin adds nothing that would take it over.
156
- function aliasesWasmDep(config: ViteUserConfig): boolean {
157
- const alias = config.resolve?.alias;
158
- if (!alias) return false;
159
- const specifiers = WASM_DEPS.map((dep) => dep.specifier);
160
- if (Array.isArray(alias)) {
161
- return alias.some((entry) =>
162
- specifiers.some((specifier) =>
163
- typeof entry.find === 'string'
164
- ? entry.find === specifier
165
- : entry.find.test(specifier),
166
- ),
167
- );
168
- }
169
- return Object.keys(alias as Record<string, string>).some((key) =>
170
- specifiers.includes(key),
171
- );
172
- }
173
-
174
- export function brassVite(): VitePlugin {
175
- return {
176
- name: 'brass-build:vite',
177
- async config(config) {
178
- const major = await viteMajor();
179
- const useAsyncEntry = buildAcceptsTopLevelAwait(config, major) && !aliasesWasmDep(config);
180
- const existingExclude = config.optimizeDeps?.exclude ?? [];
181
- const exclude = Array.from(
182
- new Set([
183
- ...existingExclude,
184
- ...WASM_DEPS.map((dep) => dep.specifier),
185
- ...(useAsyncEntry ? WASM_DEPS.map((dep) => dep.asyncEntry) : []),
186
- ]),
187
- );
188
- const resolve = useAsyncEntry
189
- ? {
190
- resolve: {
191
- alias: WASM_DEPS.map((dep) => ({
192
- find: wholeSpecifier(dep.specifier),
193
- replacement: dep.asyncEntry,
194
- })) as ViteAliasEntry[],
195
- },
196
- }
197
- : {};
198
- if (major !== null && major >= 8) {
199
- return { ...resolve, optimizeDeps: { exclude } };
200
- }
201
- const existingTarget = config.optimizeDeps?.esbuildOptions?.target;
202
- // Don't downgrade if a consumer has already pinned a newer
203
- // target; only raise from the Vite default (which lacks TLA).
204
- const target = existingTarget ?? 'es2022';
205
- return {
206
- ...resolve,
207
- optimizeDeps: {
208
- exclude,
209
- esbuildOptions: { target },
210
- },
211
- };
212
- },
213
- };
214
- }