@effindomv2/fui-as 0.1.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 (137) hide show
  1. package/LICENSE.md +7 -0
  2. package/browser/src/common-harness/host-imports.ts +430 -0
  3. package/browser/src/common-harness/interop.ts +39 -0
  4. package/browser/src/common-harness/managed-harness-bitmap-host.ts +92 -0
  5. package/browser/src/common-harness/managed-harness-fetch-host.ts +201 -0
  6. package/browser/src/common-harness/managed-harness-file-host.ts +1101 -0
  7. package/browser/src/common-harness/managed-harness-file-payloads.ts +143 -0
  8. package/browser/src/common-harness/managed-harness-file-types.ts +106 -0
  9. package/browser/src/common-harness/managed-harness-session.ts +15 -0
  10. package/browser/src/common-harness/managed-harness.ts +1323 -0
  11. package/browser/src/common-harness/managed-history.ts +168 -0
  12. package/browser/src/common-harness/persisted-restore-policy.ts +50 -0
  13. package/browser/src/common-harness/persisted-ui-state-controller.ts +309 -0
  14. package/browser/src/common-harness/text-session-bridge.ts +452 -0
  15. package/browser/src/common-harness/types.ts +205 -0
  16. package/browser/src/common-harness/ui-chrome.ts +191 -0
  17. package/browser/src/common-harness/ui-imports.ts +529 -0
  18. package/browser/src/common-harness/wasm-module-cache.ts +47 -0
  19. package/browser/src/common-harness.ts +27 -0
  20. package/browser/src/file-processing-worker.ts +89 -0
  21. package/browser/src/host-events.ts +97 -0
  22. package/browser/src/host-services.ts +203 -0
  23. package/browser/src/index.ts +62 -0
  24. package/browser/src/persisted-ui-state.ts +206 -0
  25. package/browser/src/routed-harness.ts +198 -0
  26. package/browser/src/worker-bootstrap.ts +483 -0
  27. package/browser/src/worker-manager.ts +230 -0
  28. package/browser/src/worker-types.ts +50 -0
  29. package/package.json +89 -0
  30. package/scripts/build-demo-as.sh +91 -0
  31. package/scripts/build.sh +325 -0
  32. package/scripts/generate-host-events.ts +175 -0
  33. package/scripts/generate-host-services.ts +157 -0
  34. package/src/Fui.ts +205 -0
  35. package/src/FuiExports.ts +55 -0
  36. package/src/FuiPrimitives.ts +15 -0
  37. package/src/FuiWorker.ts +3 -0
  38. package/src/FuiWorkerExports.ts +6 -0
  39. package/src/bindings/ui.ts +531 -0
  40. package/src/color.ts +86 -0
  41. package/src/controls/AntiSelectionArea.ts +23 -0
  42. package/src/controls/Button.ts +750 -0
  43. package/src/controls/Checkbox.ts +181 -0
  44. package/src/controls/ContextMenu.ts +885 -0
  45. package/src/controls/ControlTemplateSet.ts +37 -0
  46. package/src/controls/Dialog.ts +355 -0
  47. package/src/controls/Dropdown.ts +856 -0
  48. package/src/controls/Form.ts +110 -0
  49. package/src/controls/NavLink.ts +211 -0
  50. package/src/controls/Popup.ts +129 -0
  51. package/src/controls/ProgressBar.ts +180 -0
  52. package/src/controls/RadioButton.ts +135 -0
  53. package/src/controls/RadioGroup.ts +244 -0
  54. package/src/controls/SelectionArea.ts +75 -0
  55. package/src/controls/Slider.ts +471 -0
  56. package/src/controls/Switch.ts +132 -0
  57. package/src/controls/TextArea.ts +20 -0
  58. package/src/controls/TextInput.ts +7 -0
  59. package/src/controls/index.ts +18 -0
  60. package/src/controls/internal/ButtonPresenter.ts +95 -0
  61. package/src/controls/internal/CheckboxIndicatorPresenter.ts +93 -0
  62. package/src/controls/internal/DropdownChevronPresenter.ts +67 -0
  63. package/src/controls/internal/DropdownFieldPresenter.ts +110 -0
  64. package/src/controls/internal/DropdownOptionRowPresenter.ts +82 -0
  65. package/src/controls/internal/PopupPresenter.ts +198 -0
  66. package/src/controls/internal/PressableIndicatorPresenter.ts +32 -0
  67. package/src/controls/internal/PressableLabeledControl.ts +221 -0
  68. package/src/controls/internal/RadioIndicatorPresenter.ts +73 -0
  69. package/src/controls/internal/SliderPresenter.ts +157 -0
  70. package/src/controls/internal/SwitchIndicatorPresenter.ts +72 -0
  71. package/src/controls/internal/TextInputCore.ts +695 -0
  72. package/src/controls/internal/TextInputPresenter.ts +72 -0
  73. package/src/controls/templating.ts +54 -0
  74. package/src/core/Action.ts +94 -0
  75. package/src/core/Actions.ts +37 -0
  76. package/src/core/Animation.ts +412 -0
  77. package/src/core/Application.ts +328 -0
  78. package/src/core/Assets.ts +264 -0
  79. package/src/core/AttachedProperties.ts +32 -0
  80. package/src/core/Bitmap.ts +70 -0
  81. package/src/core/BoundCallback.ts +104 -0
  82. package/src/core/Callbacks.ts +17 -0
  83. package/src/core/ContextMenuManager.ts +466 -0
  84. package/src/core/DebugApi.ts +30 -0
  85. package/src/core/Disposable.ts +10 -0
  86. package/src/core/DragDropManager.ts +179 -0
  87. package/src/core/DragGesture.ts +184 -0
  88. package/src/core/DynamicAssetIds.ts +24 -0
  89. package/src/core/Errors.ts +48 -0
  90. package/src/core/EventRouter.ts +408 -0
  91. package/src/core/ExternalDropManager.ts +122 -0
  92. package/src/core/Fetch.ts +264 -0
  93. package/src/core/FetchFfi.ts +15 -0
  94. package/src/core/File.ts +1002 -0
  95. package/src/core/FocusAdornerManager.ts +263 -0
  96. package/src/core/FocusVisibility.ts +36 -0
  97. package/src/core/FrameScheduler.ts +28 -0
  98. package/src/core/KeyboardScroll.ts +161 -0
  99. package/src/core/KeyboardScrollTracker.ts +386 -0
  100. package/src/core/Logger.ts +80 -0
  101. package/src/core/Navigation.ts +13 -0
  102. package/src/core/Node.ts +1708 -0
  103. package/src/core/PersistedState.ts +102 -0
  104. package/src/core/PersistedUiState.ts +142 -0
  105. package/src/core/Platform.ts +219 -0
  106. package/src/core/Signal.ts +89 -0
  107. package/src/core/Theme.ts +365 -0
  108. package/src/core/Timers.ts +129 -0
  109. package/src/core/ToolTip.ts +122 -0
  110. package/src/core/ToolTipManager.ts +459 -0
  111. package/src/core/Transitions.ts +34 -0
  112. package/src/core/Typography.ts +204 -0
  113. package/src/core/Worker.ts +196 -0
  114. package/src/core/bind.ts +37 -0
  115. package/src/core/event_exports.ts +596 -0
  116. package/src/core/ffi.ts +728 -0
  117. package/src/host-services/runtime.ts +25 -0
  118. package/src/nodes/FlexBox.ts +789 -0
  119. package/src/nodes/GradientStop.ts +9 -0
  120. package/src/nodes/Grid.ts +183 -0
  121. package/src/nodes/Image.ts +189 -0
  122. package/src/nodes/Portal.ts +14 -0
  123. package/src/nodes/RichText.ts +312 -0
  124. package/src/nodes/ScrollBar.ts +570 -0
  125. package/src/nodes/ScrollBox.ts +415 -0
  126. package/src/nodes/ScrollState.ts +10 -0
  127. package/src/nodes/ScrollView.ts +511 -0
  128. package/src/nodes/Svg.ts +142 -0
  129. package/src/nodes/Text.ts +145 -0
  130. package/src/nodes/TextCore.ts +558 -0
  131. package/src/nodes/VirtualList.ts +431 -0
  132. package/src/nodes/helpers.ts +25 -0
  133. package/src/nodes/index.ts +14 -0
  134. package/src/tsconfig.json +7 -0
  135. package/src/worker/Worker.ts +169 -0
  136. package/src/worker/WorkerJob.ts +65 -0
  137. package/src/worker/ffi.ts +23 -0
@@ -0,0 +1,230 @@
1
+ import type {
2
+ WorkerBootstrapInboundMessage,
3
+ WorkerBootstrapOutboundMessage,
4
+ WorkerHostServicesBundleConfig,
5
+ WorkerManifest,
6
+ } from './worker-types';
7
+
8
+ interface WorkerHarnessExports {
9
+ __fui_on_worker_progress(workerId: number, textPtr: number, textLen: number): void;
10
+ __fui_on_worker_complete(workerId: number, textPtr: number, textLen: number): void;
11
+ __fui_on_worker_error(workerId: number, textPtr: number, textLen: number): void;
12
+ }
13
+
14
+ export interface WorkerHarnessSession {
15
+ readonly exports: WorkerHarnessExports;
16
+ readonly memory: WebAssembly.Memory;
17
+ readonly textBufferPtr: number;
18
+ readonly textBufferSize: number;
19
+ }
20
+
21
+ interface WorkerTextSession {
22
+ readonly memory: WebAssembly.Memory;
23
+ readonly textBufferPtr: number;
24
+ readonly textBufferSize: number;
25
+ }
26
+
27
+ interface WorkerRecord {
28
+ worker: Worker | null;
29
+ cancelled: boolean;
30
+ }
31
+
32
+ export interface WorkerManager {
33
+ startString(workerId: number, entryName: string, input: string): void;
34
+ cancel(workerId: number): void;
35
+ terminateAll(): void;
36
+ }
37
+
38
+ interface WorkerManagerOptions {
39
+ readonly scriptBaseUrl: string;
40
+ readonly getCurrentSession: () => WorkerHarnessSession | null;
41
+ readonly getCurrentWorkerHostServices: () => WorkerHostServicesBundleConfig | undefined;
42
+ readonly writeTextCallbackPayload: (session: WorkerTextSession, text: string, context: string) => number;
43
+ }
44
+
45
+ function describeError(error: unknown): string {
46
+ return error instanceof Error ? error.message : String(error);
47
+ }
48
+
49
+ function validateManifest(value: unknown): WorkerManifest {
50
+ if (typeof value !== 'object' || value === null) {
51
+ throw new Error('Malformed worker manifest: expected an object.');
52
+ }
53
+ const candidate = value as { version?: unknown; entries?: unknown; };
54
+ if (candidate.version !== 1) {
55
+ throw new Error('Malformed worker manifest: expected version 1.');
56
+ }
57
+ if (typeof candidate.entries !== 'object' || candidate.entries === null) {
58
+ throw new Error('Malformed worker manifest: expected an entries object.');
59
+ }
60
+ for (const [entryName, entryUrl] of Object.entries(candidate.entries as Record<string, unknown>)) {
61
+ if (typeof entryName !== 'string' || entryName.length === 0 || typeof entryUrl !== 'string' || entryUrl.length === 0) {
62
+ throw new Error('Malformed worker manifest: each entry must map a non-empty name to a non-empty URL.');
63
+ }
64
+ }
65
+ return candidate as WorkerManifest;
66
+ }
67
+
68
+ export function createWorkerManager(options: WorkerManagerOptions): WorkerManager {
69
+ const workerBootstrapUrl = new URL('./worker-bootstrap.js', options.scriptBaseUrl).toString();
70
+ const workerManifestUrl = new URL('./worker-manifest.json', options.scriptBaseUrl).toString();
71
+ const records = new Map<number, WorkerRecord>();
72
+ let manifestPromise: Promise<WorkerManifest> | null = null;
73
+
74
+ function emitToSession(workerId: number, kind: 'progress' | 'complete' | 'error', text: string): void {
75
+ const session = options.getCurrentSession();
76
+ if (session === null) {
77
+ return;
78
+ }
79
+ try {
80
+ const textLength = options.writeTextCallbackPayload(session, text, `Worker ${kind} payload`);
81
+ const textPtr = textLength > 0 ? session.textBufferPtr : 0;
82
+ if (kind === 'progress') {
83
+ session.exports.__fui_on_worker_progress(workerId, textPtr, textLength);
84
+ return;
85
+ }
86
+ if (kind === 'complete') {
87
+ session.exports.__fui_on_worker_complete(workerId, textPtr, textLength);
88
+ return;
89
+ }
90
+ session.exports.__fui_on_worker_error(workerId, textPtr, textLength);
91
+ } catch (error: unknown) {
92
+ console.error(`[fui-worker] failed to deliver ${kind} payload for worker ${String(workerId)}: ${describeError(error)}`);
93
+ if (kind !== 'error') {
94
+ emitToSession(workerId, 'error', `Worker ${kind} delivery failed: ${describeError(error)}`);
95
+ }
96
+ }
97
+ }
98
+
99
+ function finishWorker(workerId: number): void {
100
+ const record = records.get(workerId);
101
+ if (record === undefined) {
102
+ return;
103
+ }
104
+ record.worker?.terminate();
105
+ records.delete(workerId);
106
+ }
107
+
108
+ function handleWorkerMessage(workerId: number, message: WorkerBootstrapOutboundMessage): void {
109
+ const record = records.get(workerId);
110
+ if (record === undefined) {
111
+ return;
112
+ }
113
+ if (message.type === 'progress') {
114
+ if (!record.cancelled) {
115
+ emitToSession(workerId, 'progress', message.text);
116
+ }
117
+ return;
118
+ }
119
+ if (message.type === 'complete') {
120
+ emitToSession(workerId, 'complete', message.text);
121
+ finishWorker(workerId);
122
+ return;
123
+ }
124
+ emitToSession(workerId, 'error', message.text);
125
+ finishWorker(workerId);
126
+ }
127
+
128
+ function loadManifest(): Promise<WorkerManifest> {
129
+ if (manifestPromise !== null) {
130
+ return manifestPromise;
131
+ }
132
+ manifestPromise = fetch(workerManifestUrl, {
133
+ cache: 'no-store',
134
+ credentials: 'same-origin',
135
+ }).then(async (response) => {
136
+ if (!response.ok) {
137
+ throw new Error(`Failed to load worker manifest from ${workerManifestUrl}.`);
138
+ }
139
+ return validateManifest(await response.json());
140
+ });
141
+ return manifestPromise;
142
+ }
143
+
144
+ async function startWorkerAsync(workerId: number, entryName: string, input: string): Promise<void> {
145
+ const record = records.get(workerId);
146
+ if (record === undefined) {
147
+ return;
148
+ }
149
+ try {
150
+ const manifest = await loadManifest();
151
+ if (records.get(workerId) !== record) {
152
+ return;
153
+ }
154
+ const workerModuleUrl = manifest.entries[entryName];
155
+ if (typeof workerModuleUrl !== 'string' || workerModuleUrl.length === 0) {
156
+ emitToSession(workerId, 'error', `Unknown worker entry "${entryName}".`);
157
+ finishWorker(workerId);
158
+ return;
159
+ }
160
+ const worker = new Worker(workerBootstrapUrl);
161
+ if (records.get(workerId) !== record) {
162
+ worker.terminate();
163
+ return;
164
+ }
165
+ record.worker = worker;
166
+ worker.addEventListener('message', (event: MessageEvent<WorkerBootstrapOutboundMessage>) => {
167
+ handleWorkerMessage(workerId, event.data);
168
+ });
169
+ worker.addEventListener('error', (event: ErrorEvent) => {
170
+ const active = records.get(workerId);
171
+ if (active === undefined) {
172
+ return;
173
+ }
174
+ emitToSession(workerId, 'error', event.message.length > 0 ? event.message : 'Worker bootstrap crashed.');
175
+ finishWorker(workerId);
176
+ });
177
+ const message: WorkerBootstrapInboundMessage = {
178
+ type: 'start',
179
+ workerId,
180
+ wasmUrl: new URL(workerModuleUrl, workerManifestUrl).toString(),
181
+ entryName,
182
+ input,
183
+ workerHostServices: options.getCurrentWorkerHostServices(),
184
+ };
185
+ worker.postMessage(message);
186
+ if (record.cancelled) {
187
+ worker.postMessage({
188
+ type: 'cancel',
189
+ workerId,
190
+ });
191
+ }
192
+ } catch (error: unknown) {
193
+ emitToSession(workerId, 'error', describeError(error));
194
+ finishWorker(workerId);
195
+ }
196
+ }
197
+
198
+ return {
199
+ startString(workerId: number, entryName: string, input: string): void {
200
+ if (records.has(workerId)) {
201
+ emitToSession(workerId, 'error', 'Worker already started.');
202
+ return;
203
+ }
204
+ records.set(workerId, {
205
+ worker: null,
206
+ cancelled: false,
207
+ });
208
+ void startWorkerAsync(workerId, entryName, input);
209
+ },
210
+ cancel(workerId: number): void {
211
+ const record = records.get(workerId);
212
+ if (record === undefined) {
213
+ return;
214
+ }
215
+ record.cancelled = true;
216
+ if (record.worker !== null) {
217
+ record.worker.postMessage({
218
+ type: 'cancel',
219
+ workerId,
220
+ });
221
+ }
222
+ },
223
+ terminateAll(): void {
224
+ for (const record of records.values()) {
225
+ record.worker?.terminate();
226
+ }
227
+ records.clear();
228
+ },
229
+ };
230
+ }
@@ -0,0 +1,50 @@
1
+ export interface WorkerManifest {
2
+ readonly version: 1;
3
+ readonly entries: Readonly<Record<string, string>>;
4
+ }
5
+
6
+ export interface WorkerHostServicesBundleConfig {
7
+ readonly scriptUrl: string;
8
+ readonly exportName: string;
9
+ }
10
+
11
+ export interface WorkerBootstrapStartMessage {
12
+ readonly type: "start";
13
+ readonly workerId: number;
14
+ readonly wasmUrl: string;
15
+ readonly entryName: string;
16
+ readonly input: string;
17
+ readonly workerHostServices?: WorkerHostServicesBundleConfig;
18
+ }
19
+
20
+ export interface WorkerBootstrapCancelMessage {
21
+ readonly type: "cancel";
22
+ readonly workerId: number;
23
+ }
24
+
25
+ export type WorkerBootstrapInboundMessage =
26
+ | WorkerBootstrapStartMessage
27
+ | WorkerBootstrapCancelMessage;
28
+
29
+ export interface WorkerBootstrapProgressMessage {
30
+ readonly type: "progress";
31
+ readonly workerId: number;
32
+ readonly text: string;
33
+ }
34
+
35
+ export interface WorkerBootstrapCompleteMessage {
36
+ readonly type: "complete";
37
+ readonly workerId: number;
38
+ readonly text: string;
39
+ }
40
+
41
+ export interface WorkerBootstrapErrorMessage {
42
+ readonly type: "error";
43
+ readonly workerId: number;
44
+ readonly text: string;
45
+ }
46
+
47
+ export type WorkerBootstrapOutboundMessage =
48
+ | WorkerBootstrapProgressMessage
49
+ | WorkerBootstrapCompleteMessage
50
+ | WorkerBootstrapErrorMessage;
package/package.json ADDED
@@ -0,0 +1,89 @@
1
+ {
2
+ "name": "@effindomv2/fui-as",
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "license": "BSL-1.1",
6
+ "description": "EffinDom v2 AssemblyScript SDK and browser harness",
7
+ "type": "module",
8
+ "publishConfig": {
9
+ "access": "public"
10
+ },
11
+ "types": "./src/Fui.ts",
12
+ "engines": {
13
+ "node": ">=18"
14
+ },
15
+ "exports": {
16
+ ".": {
17
+ "types": "./src/Fui.ts",
18
+ "default": "./src/Fui.ts"
19
+ },
20
+ "./primitives": {
21
+ "types": "./src/FuiPrimitives.ts",
22
+ "default": "./src/FuiPrimitives.ts"
23
+ },
24
+ "./worker": {
25
+ "types": "./src/FuiWorker.ts",
26
+ "default": "./src/FuiWorker.ts"
27
+ },
28
+ "./worker-exports": {
29
+ "types": "./src/FuiWorkerExports.ts",
30
+ "default": "./src/FuiWorkerExports.ts"
31
+ },
32
+ "./exports": {
33
+ "types": "./src/FuiExports.ts",
34
+ "default": "./src/FuiExports.ts"
35
+ },
36
+ "./browser": {
37
+ "types": "./browser/src/index.ts",
38
+ "default": "./browser/src/index.ts"
39
+ },
40
+ "./browser/common-harness": {
41
+ "types": "./browser/src/common-harness.ts",
42
+ "default": "./browser/src/common-harness.ts"
43
+ },
44
+ "./browser/routed-harness": {
45
+ "types": "./browser/src/routed-harness.ts",
46
+ "default": "./browser/src/routed-harness.ts"
47
+ },
48
+ "./browser/host-events": {
49
+ "types": "./browser/src/host-events.ts",
50
+ "default": "./browser/src/host-events.ts"
51
+ },
52
+ "./browser/host-services": {
53
+ "types": "./browser/src/host-services.ts",
54
+ "default": "./browser/src/host-services.ts"
55
+ },
56
+ "./browser/worker-types": {
57
+ "types": "./browser/src/worker-types.ts",
58
+ "default": "./browser/src/worker-types.ts"
59
+ }
60
+ },
61
+ "files": [
62
+ "src",
63
+ "browser/src",
64
+ "scripts"
65
+ ],
66
+ "scripts": {
67
+ "build": "bash scripts/build.sh",
68
+ "build:only": "bash scripts/build.sh",
69
+ "build:full": "bash scripts/build.sh",
70
+ "build:demo:as": "bash scripts/build-demo-as.sh",
71
+ "test:unit": "asp --verbose -c as-pect.config.mjs -a as-pect.asconfig.json",
72
+ "test:integration": "npm run build:full && playwright test -c playwright.config.ts",
73
+ "typecheck": "tsc -p tsconfig.json --noEmit"
74
+ },
75
+ "dependencies": {
76
+ "@effindomv2/runtime": "0.1.0"
77
+ },
78
+ "devDependencies": {
79
+ "@assemblyscript/loader": "^0.28.17",
80
+ "@as-pect/assembly": "8.1.0",
81
+ "@as-pect/cli": "8.1.0",
82
+ "@as-pect/core": "8.1.0",
83
+ "@playwright/test": "1.59.1",
84
+ "@types/node": "^24.10.1",
85
+ "assemblyscript": "0.28.17",
86
+ "esbuild": "^0.27.7",
87
+ "typescript": "^5.9.3"
88
+ }
89
+ }
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
4
+
5
+ PACKAGE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
6
+ REPO_ROOT="$(cd "${PACKAGE_DIR}/../.." && pwd)"
7
+ DEMO_OUT_DIR="${REPO_ROOT}/public/v2/fui-as/demo"
8
+ HELLO_OUT_DIR="${REPO_ROOT}/public/v2/fui-as/demo-hello-world"
9
+ HOST_SERVICE_GENERATOR_BUILD="${PACKAGE_DIR}/build/generate-host-services.mjs"
10
+ HOST_EVENT_GENERATOR_BUILD="${PACKAGE_DIR}/build/generate-host-events.mjs"
11
+ BUILD_TARGET="${1:-all}"
12
+
13
+ mkdir -p "${PACKAGE_DIR}/build" "${DEMO_OUT_DIR}" "${HELLO_OUT_DIR}"
14
+ cd "${PACKAGE_DIR}"
15
+
16
+ build_demo_app() {
17
+ local entry_file="$1"
18
+ local wasm_out="$2"
19
+
20
+ npx asc "${entry_file}" --config asconfig.json --target release
21
+ cp "${PACKAGE_DIR}/build/app.wasm" "${wasm_out}"
22
+ if [ -f "${PACKAGE_DIR}/build/app.wasm.map" ]; then
23
+ cp "${PACKAGE_DIR}/build/app.wasm.map" "${wasm_out}.map"
24
+ fi
25
+ }
26
+
27
+ generate_host_services() {
28
+ local definition_file="$1"
29
+ local export_name="$2"
30
+ local output_file="$3"
31
+
32
+ npx esbuild "${PACKAGE_DIR}/scripts/generate-host-services.ts" \
33
+ --bundle \
34
+ --format=esm \
35
+ --platform=node \
36
+ --target=node20 \
37
+ --packages=external \
38
+ --outfile="${HOST_SERVICE_GENERATOR_BUILD}"
39
+
40
+ node "${HOST_SERVICE_GENERATOR_BUILD}" "${definition_file}" "${export_name}" "${output_file}"
41
+ }
42
+
43
+ generate_host_events() {
44
+ local definition_file="$1"
45
+ local export_name="$2"
46
+ local output_file="$3"
47
+
48
+ npx esbuild "${PACKAGE_DIR}/scripts/generate-host-events.ts" \
49
+ --bundle \
50
+ --format=esm \
51
+ --platform=node \
52
+ --target=node20 \
53
+ --packages=external \
54
+ --outfile="${HOST_EVENT_GENERATOR_BUILD}"
55
+
56
+ node "${HOST_EVENT_GENERATOR_BUILD}" "${definition_file}" "${export_name}" "${output_file}"
57
+ }
58
+
59
+ generate_host_services "demo/src/host-services.ts" "demoHostServices" "demo/src/generated/HostServices.ts"
60
+ generate_host_events "demo/src/host-events.ts" "demoHostEvents" "demo/src/generated/HostEvents.ts"
61
+ generate_host_services "demo/src/worker-host-services.ts" "demoWorkerHostServices" "demo/src/generated/WorkerHostServices.ts"
62
+
63
+ case "${BUILD_TARGET}" in
64
+ all)
65
+ build_demo_app "demo/src/dashboard.ts" "${DEMO_OUT_DIR}/demo.wasm"
66
+ build_demo_app "demo/src/routes/demo_home.ts" "${DEMO_OUT_DIR}/home.wasm"
67
+ build_demo_app "demo/src/routes/demo_advanced_controls.ts" "${DEMO_OUT_DIR}/advanced-controls.wasm"
68
+ build_demo_app "demo/src/routes/templated-controls.ts" "${DEMO_OUT_DIR}/templated-controls.wasm"
69
+ build_demo_app "demo-hello-world/src/App.ts" "${HELLO_OUT_DIR}/app.wasm"
70
+ ;;
71
+ dashboard)
72
+ build_demo_app "demo/src/dashboard.ts" "${DEMO_OUT_DIR}/demo.wasm"
73
+ ;;
74
+ home)
75
+ build_demo_app "demo/src/routes/demo_home.ts" "${DEMO_OUT_DIR}/home.wasm"
76
+ ;;
77
+ advanced-controls|advanced)
78
+ build_demo_app "demo/src/routes/demo_advanced_controls.ts" "${DEMO_OUT_DIR}/advanced-controls.wasm"
79
+ ;;
80
+ templated-controls|templated)
81
+ build_demo_app "demo/src/routes/templated-controls.ts" "${DEMO_OUT_DIR}/templated-controls.wasm"
82
+ ;;
83
+ hello-world|hello)
84
+ build_demo_app "demo-hello-world/src/App.ts" "${HELLO_OUT_DIR}/app.wasm"
85
+ ;;
86
+ *)
87
+ echo "Unknown build target: ${BUILD_TARGET}" >&2
88
+ echo "Usage: bash scripts/build-demo-as.sh [all|dashboard|home|advanced-controls|templated-controls|hello-world]" >&2
89
+ exit 1
90
+ ;;
91
+ esac