@hyperfrontend/features 0.1.0 → 0.2.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 (159) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/_dependencies/@hyperfrontend/builder/bundle/dependencies/index.cjs.js +1 -0
  3. package/_dependencies/@hyperfrontend/builder/bundle/dependencies/index.esm.js +1 -0
  4. package/_dependencies/@hyperfrontend/builder/bundle/dependencies/worker/index.cjs.js +1 -0
  5. package/_dependencies/@hyperfrontend/builder/bundle/dependencies/worker/index.esm.js +1 -0
  6. package/_dependencies/@hyperfrontend/builder/bundle/index.cjs.js +12 -10
  7. package/_dependencies/@hyperfrontend/builder/bundle/index.esm.js +14 -12
  8. package/_dependencies/@hyperfrontend/builder/bundle/rollup/index.cjs.js +2 -0
  9. package/_dependencies/@hyperfrontend/builder/bundle/rollup/index.esm.js +2 -0
  10. package/_dependencies/@hyperfrontend/builder/bundle/rollup/worker/index.cjs.js +2 -0
  11. package/_dependencies/@hyperfrontend/builder/bundle/rollup/worker/index.esm.js +2 -0
  12. package/_dependencies/@hyperfrontend/builder/index.cjs.js +87 -53
  13. package/_dependencies/@hyperfrontend/builder/index.esm.js +89 -55
  14. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/promise/index.cjs.js +4 -0
  15. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/promise/index.esm.js +3 -1
  16. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/reflect/index.cjs.js +10 -0
  17. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/reflect/index.esm.js +6 -0
  18. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/timers/index.cjs.js +5 -0
  19. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/timers/index.esm.js +5 -1
  20. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/typed-arrays/index.cjs.js +2 -2
  21. package/_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/typed-arrays/index.esm.js +2 -2
  22. package/_dependencies/@hyperfrontend/network-protocol/browser/channel/index.cjs.js +5 -19
  23. package/_dependencies/@hyperfrontend/network-protocol/browser/channel/index.esm.js +1 -15
  24. package/_dependencies/@hyperfrontend/network-protocol/browser/data/index.cjs.js +15 -23
  25. package/_dependencies/@hyperfrontend/network-protocol/browser/data/index.esm.js +7 -15
  26. package/_dependencies/@hyperfrontend/network-protocol/browser/packet/index.cjs.js +6 -14
  27. package/_dependencies/@hyperfrontend/network-protocol/browser/packet/index.esm.js +7 -15
  28. package/_dependencies/@hyperfrontend/network-protocol/browser/receiver/index.cjs.js +4 -18
  29. package/_dependencies/@hyperfrontend/network-protocol/browser/receiver/index.esm.js +1 -15
  30. package/_dependencies/@hyperfrontend/network-protocol/browser/sender/index.cjs.js +5 -19
  31. package/_dependencies/@hyperfrontend/network-protocol/browser/sender/index.esm.js +2 -16
  32. package/_dependencies/@hyperfrontend/network-protocol/browser/v1/index.cjs.js +16 -24
  33. package/_dependencies/@hyperfrontend/network-protocol/browser/v1/index.esm.js +7 -15
  34. package/_dependencies/@hyperfrontend/network-protocol/browser/v2/index.cjs.js +16 -24
  35. package/_dependencies/@hyperfrontend/network-protocol/browser/v2/index.esm.js +7 -15
  36. package/_dependencies/@hyperfrontend/network-protocol/node/channel/index.cjs.js +3 -17
  37. package/_dependencies/@hyperfrontend/network-protocol/node/channel/index.esm.js +1 -15
  38. package/_dependencies/@hyperfrontend/network-protocol/node/data/index.cjs.js +6 -14
  39. package/_dependencies/@hyperfrontend/network-protocol/node/data/index.esm.js +7 -15
  40. package/_dependencies/@hyperfrontend/network-protocol/node/packet/index.cjs.js +6 -14
  41. package/_dependencies/@hyperfrontend/network-protocol/node/packet/index.esm.js +7 -15
  42. package/_dependencies/@hyperfrontend/network-protocol/node/receiver/index.cjs.js +3 -17
  43. package/_dependencies/@hyperfrontend/network-protocol/node/receiver/index.esm.js +1 -15
  44. package/_dependencies/@hyperfrontend/network-protocol/node/sender/index.cjs.js +2 -16
  45. package/_dependencies/@hyperfrontend/network-protocol/node/sender/index.esm.js +2 -16
  46. package/_dependencies/@hyperfrontend/network-protocol/node/v1/index.cjs.js +6 -14
  47. package/_dependencies/@hyperfrontend/network-protocol/node/v1/index.esm.js +7 -15
  48. package/_dependencies/@hyperfrontend/network-protocol/node/v2/index.cjs.js +6 -14
  49. package/_dependencies/@hyperfrontend/network-protocol/node/v2/index.esm.js +7 -15
  50. package/_dependencies/@hyperfrontend/nexus/index.cjs.js +49 -19
  51. package/_dependencies/@hyperfrontend/nexus/index.esm.js +49 -19
  52. package/_dependencies/@hyperfrontend/project-scope/core/fs/index.cjs.js +62 -0
  53. package/_dependencies/@hyperfrontend/project-scope/core/fs/index.esm.js +60 -2
  54. package/_shared/generators/feature/generate-feature-module/index.esm.js +11 -6
  55. package/_shared/generators/metadata/generate-metadata/index.esm.js +1 -0
  56. package/_shared/shared/control/index.cjs.js +12 -2
  57. package/_shared/shared/control/index.esm.js +12 -2
  58. package/_shared/shared/request/index.cjs.js +91 -0
  59. package/_shared/shared/request/index.esm.js +88 -0
  60. package/_shared/shared/shutdown/index.esm.js +12 -0
  61. package/bin/hf.js +643 -70
  62. package/bundle/host/index.iife.js +290 -4041
  63. package/bundle/host/index.iife.min.js +1 -1
  64. package/bundle/host/index.umd.js +290 -4041
  65. package/bundle/host/index.umd.min.js +1 -1
  66. package/bundle/hostee/index.iife.js +215 -2893
  67. package/bundle/hostee/index.iife.min.js +1 -1
  68. package/bundle/hostee/index.umd.js +215 -2893
  69. package/bundle/hostee/index.umd.min.js +1 -1
  70. package/cli/args.d.ts +2 -0
  71. package/cli/args.d.ts.map +1 -1
  72. package/cli/commands/build.d.ts +8 -5
  73. package/cli/commands/build.d.ts.map +1 -1
  74. package/cli/commands/dev.d.ts +7 -2
  75. package/cli/commands/dev.d.ts.map +1 -1
  76. package/cli/config/resolve.d.ts +3 -1
  77. package/cli/config/resolve.d.ts.map +1 -1
  78. package/cli/index.cjs.js +643 -70
  79. package/cli/index.d.ts +21 -10
  80. package/cli/index.esm.js +591 -60
  81. package/cli/usage.d.ts +1 -1
  82. package/cli/usage.d.ts.map +1 -1
  83. package/generators/feature/generate-feature-module.d.ts.map +1 -1
  84. package/generators/index.cjs.js +435 -42
  85. package/generators/index.d.ts +9 -8
  86. package/generators/index.esm.js +404 -30
  87. package/generators/metadata/generate-metadata.d.ts +4 -4
  88. package/generators/metadata/generate-metadata.d.ts.map +1 -1
  89. package/generators/shell/connector-types.d.ts +19 -0
  90. package/generators/shell/connector-types.d.ts.map +1 -0
  91. package/generators/shell/generate-shell.d.ts +5 -4
  92. package/generators/shell/generate-shell.d.ts.map +1 -1
  93. package/generators/shell/schema-type.d.ts +20 -0
  94. package/generators/shell/schema-type.d.ts.map +1 -0
  95. package/generators/shell/source-literal.d.ts +28 -0
  96. package/generators/shell/source-literal.d.ts.map +1 -1
  97. package/host/create-shell.d.ts +4 -1
  98. package/host/create-shell.d.ts.map +1 -1
  99. package/host/display-modes/dialog.d.ts +1 -1
  100. package/host/display-modes/dialog.d.ts.map +1 -1
  101. package/host/display-modes/embedded.d.ts +1 -1
  102. package/host/display-modes/embedded.d.ts.map +1 -1
  103. package/host/index.cjs.js +150 -30
  104. package/host/index.d.ts +53 -38
  105. package/host/index.d.ts.map +1 -1
  106. package/host/index.esm.js +129 -9
  107. package/host/lifecycle.d.ts.map +1 -1
  108. package/host/plugins.d.ts +1 -34
  109. package/host/plugins.d.ts.map +1 -1
  110. package/host/types.d.ts +49 -0
  111. package/host/types.d.ts.map +1 -1
  112. package/hostee/index.cjs.js +54 -9
  113. package/hostee/index.d.ts +41 -1
  114. package/hostee/index.d.ts.map +1 -1
  115. package/hostee/index.esm.js +51 -6
  116. package/hostee/lifecycle.d.ts.map +1 -1
  117. package/hostee/types.d.ts +40 -0
  118. package/hostee/types.d.ts.map +1 -1
  119. package/index.cjs.js +32 -1
  120. package/index.d.ts +89 -3
  121. package/index.d.ts.map +1 -1
  122. package/index.esm.js +32 -1
  123. package/nx/executors/build/index.cjs.js +14975 -137
  124. package/nx/executors/build/index.esm.js +14935 -115
  125. package/nx/executors/serve/executor.d.ts.map +1 -1
  126. package/nx/executors/serve/index.cjs.js +6594 -80
  127. package/nx/executors/serve/index.esm.js +6529 -44
  128. package/nx/generators/feature/index.cjs.js +8751 -108
  129. package/nx/generators/feature/index.esm.js +8711 -81
  130. package/package.json +15 -5
  131. package/server/debug-ui/index.d.ts +2 -0
  132. package/server/debug-ui/index.d.ts.map +1 -0
  133. package/server/debug-ui/index.html +15 -0
  134. package/server/debug-ui/index.iife.js +427 -0
  135. package/server/debug-ui/index.iife.min.js +1 -0
  136. package/server/dev-server.d.ts.map +1 -1
  137. package/server/index.cjs.js +78 -10
  138. package/server/index.esm.js +78 -11
  139. package/server/module-dir.d.ts +17 -0
  140. package/server/module-dir.d.ts.map +1 -0
  141. package/server/module-dir.stub.d.ts +15 -0
  142. package/server/module-dir.stub.d.ts.map +1 -0
  143. package/shared/contract.d.ts +1 -1
  144. package/shared/contract.d.ts.map +1 -1
  145. package/shared/control.d.ts +4 -0
  146. package/shared/control.d.ts.map +1 -1
  147. package/shared/invert-contract.d.ts +20 -0
  148. package/shared/invert-contract.d.ts.map +1 -0
  149. package/shared/request.d.ts +68 -0
  150. package/shared/request.d.ts.map +1 -0
  151. package/{nx/shared → shared}/shutdown.d.ts +3 -2
  152. package/shared/shutdown.d.ts.map +1 -0
  153. package/shared/types.d.ts +72 -1
  154. package/shared/types.d.ts.map +1 -1
  155. package/_shared/nx/shared/context/index.cjs.js +0 -18
  156. package/_shared/nx/shared/context/index.esm.js +0 -16
  157. package/nx/shared/shutdown.d.ts.map +0 -1
  158. package/server/debug-ui/bootstrap.d.ts +0 -2
  159. package/server/debug-ui/bootstrap.d.ts.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperfrontend/features",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "SDK, CLI, and dev server for building, embedding, and orchestrating hyperfrontend micro-frontend features.",
5
5
  "license": "MIT",
6
6
  "sideEffects": false,
@@ -160,8 +160,12 @@
160
160
  "generators/feature/generate-feature-module.d.ts.map",
161
161
  "generators/metadata/generate-metadata.d.ts",
162
162
  "generators/metadata/generate-metadata.d.ts.map",
163
+ "generators/shell/connector-types.d.ts",
164
+ "generators/shell/connector-types.d.ts.map",
163
165
  "generators/shell/generate-shell.d.ts",
164
166
  "generators/shell/generate-shell.d.ts.map",
167
+ "generators/shell/schema-type.d.ts",
168
+ "generators/shell/schema-type.d.ts.map",
165
169
  "generators/shell/source-literal.d.ts",
166
170
  "generators/shell/source-literal.d.ts.map",
167
171
  "host/create-shell.d.ts",
@@ -219,14 +223,10 @@
219
223
  "nx/shared/context.d.ts.map",
220
224
  "nx/shared/flags.d.ts",
221
225
  "nx/shared/flags.d.ts.map",
222
- "nx/shared/shutdown.d.ts",
223
- "nx/shared/shutdown.d.ts.map",
224
226
  "server/config.d.ts",
225
227
  "server/config.d.ts.map",
226
228
  "server/debug-ui/app.d.ts",
227
229
  "server/debug-ui/app.d.ts.map",
228
- "server/debug-ui/bootstrap.d.ts",
229
- "server/debug-ui/bootstrap.d.ts.map",
230
230
  "server/debug-ui/controls.d.ts",
231
231
  "server/debug-ui/controls.d.ts.map",
232
232
  "server/debug-ui/message-log.d.ts",
@@ -235,6 +235,10 @@
235
235
  "server/debug-ui/styles.d.ts.map",
236
236
  "server/dev-server.d.ts",
237
237
  "server/dev-server.d.ts.map",
238
+ "server/module-dir.d.ts",
239
+ "server/module-dir.d.ts.map",
240
+ "server/module-dir.stub.d.ts",
241
+ "server/module-dir.stub.d.ts.map",
238
242
  "server/static-handler.d.ts",
239
243
  "server/static-handler.d.ts.map",
240
244
  "shared/contract.d.ts",
@@ -243,8 +247,14 @@
243
247
  "shared/control.d.ts.map",
244
248
  "shared/event-emitter.d.ts",
245
249
  "shared/event-emitter.d.ts.map",
250
+ "shared/invert-contract.d.ts",
251
+ "shared/invert-contract.d.ts.map",
252
+ "shared/request.d.ts",
253
+ "shared/request.d.ts.map",
246
254
  "shared/sdk-info.d.ts",
247
255
  "shared/sdk-info.d.ts.map",
256
+ "shared/shutdown.d.ts",
257
+ "shared/shutdown.d.ts.map",
248
258
  "shared/types.d.ts",
249
259
  "shared/types.d.ts.map",
250
260
  "!**/*.js.map"
@@ -0,0 +1,2 @@
1
+
2
+ export { };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../../libs/features/src/server/debug-ui/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,15 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>hyperfrontend · debug</title>
7
+ </head>
8
+ <body style="margin: 0; background: #1e1e1e">
9
+ <div id="hf-debug-root"></div>
10
+ <script>
11
+ window.__HF_DEBUG_MANIFEST__ = HF_MANIFEST_PLACEHOLDER
12
+ </script>
13
+ <script src="/__debug/index.iife.min.js"></script>
14
+ </body>
15
+ </html>
@@ -0,0 +1,427 @@
1
+ (function () {
2
+ 'use strict';
3
+
4
+ const _Object = globalThis.Object;
5
+ const freeze = _Object.freeze;
6
+ const assign = _Object.assign;
7
+
8
+ const _URL = globalThis.URL;
9
+ const _Reflect$1 = globalThis.Reflect;
10
+ const createURL = (url, base) => _Reflect$1.construct(_URL, [url, base]);
11
+ typeof _URL.createObjectURL === 'function'
12
+ ? _URL.createObjectURL.bind(_URL)
13
+ : () => {
14
+ throw new Error('URL.createObjectURL is not available in this environment');
15
+ };
16
+ typeof _URL.revokeObjectURL === 'function'
17
+ ? _URL.revokeObjectURL.bind(_URL)
18
+ : () => {
19
+ throw new Error('URL.revokeObjectURL is not available in this environment');
20
+ };
21
+
22
+ const _Array = globalThis.Array;
23
+ const isArray = _Array.isArray;
24
+ const from = _Array.from;
25
+
26
+ const _Set = globalThis.Set;
27
+ const _Reflect = globalThis.Reflect;
28
+ const createSet = (iterable) => _Reflect.construct(_Set, iterable ? [iterable] : []);
29
+
30
+ function nonEmptyStrings(values) {
31
+ return values.filter((value) => ![undefined, null, ''].includes(value) && value.trim() !== '');
32
+ }
33
+
34
+ function uniqueStrings(values) {
35
+ return from(createSet(values));
36
+ }
37
+
38
+ function createElement(tagName, config) {
39
+ const element = document.createElement(tagName);
40
+ if (config?.inlineStyle) {
41
+ assign(element.style, config.inlineStyle);
42
+ }
43
+ const classList = [];
44
+ if (config?.classNames && isArray(config.classNames)) {
45
+ classList.push(...config.classNames);
46
+ }
47
+ if (config?.className) {
48
+ classList.push(config.className);
49
+ }
50
+ element.classList.add(...nonEmptyStrings(uniqueStrings(classList)));
51
+ let isVisible = false;
52
+ const addChild = (child) => {
53
+ if (!child)
54
+ return;
55
+ const childElement = 'ref' in child ? child.ref : child;
56
+ if (!element.contains(childElement)) {
57
+ element.appendChild(childElement);
58
+ }
59
+ };
60
+ const attachTo = (parent) => {
61
+ if (!parent)
62
+ return;
63
+ const parentElement = 'ref' in parent ? parent.ref : parent;
64
+ if (!parentElement.contains(element)) {
65
+ parentElement.appendChild(element);
66
+ }
67
+ };
68
+ const getTransition = (duration) => {
69
+ return duration ? `opacity ${(duration / 1000).toFixed(1)}s` : 'none';
70
+ };
71
+ const show = (duration) => {
72
+ element.style.transition = getTransition(duration);
73
+ element.style.opacity = '1';
74
+ isVisible = true;
75
+ };
76
+ const hide = (duration) => {
77
+ element.style.transition = getTransition(duration);
78
+ element.style.opacity = '0';
79
+ isVisible = false;
80
+ };
81
+ const removeChild = (child) => {
82
+ if (!child)
83
+ return;
84
+ const childElement = 'ref' in child ? child.ref : child;
85
+ if (element.contains(childElement)) {
86
+ element.removeChild(childElement);
87
+ }
88
+ };
89
+ const detachFromParent = () => {
90
+ const parent = element.parentElement;
91
+ if (parent) {
92
+ parent.removeChild(element);
93
+ }
94
+ };
95
+ return {
96
+ get addChild() {
97
+ return addChild;
98
+ },
99
+ get attachTo() {
100
+ return attachTo;
101
+ },
102
+ get show() {
103
+ return show;
104
+ },
105
+ get hide() {
106
+ return hide;
107
+ },
108
+ get removeChild() {
109
+ return removeChild;
110
+ },
111
+ get detachFromParent() {
112
+ return detachFromParent;
113
+ },
114
+ get ref() {
115
+ return element;
116
+ },
117
+ get visible() {
118
+ return isVisible;
119
+ },
120
+ };
121
+ }
122
+
123
+ function span(config) {
124
+ return createElement('span', config);
125
+ }
126
+ function div(config) {
127
+ return createElement('div', config);
128
+ }
129
+ function button(config) {
130
+ return createElement('button', config);
131
+ }
132
+ function input(config) {
133
+ return createElement('input', config);
134
+ }
135
+ function label(config) {
136
+ return createElement('label', config);
137
+ }
138
+
139
+ const DisplayMode = freeze({
140
+ Embedded: 'embedded',
141
+ Dialog: 'dialog',
142
+ Popup: 'popup',
143
+ Standalone: 'standalone',
144
+ });
145
+
146
+ const palette = {
147
+ background: '#1e1e1e',
148
+ panel: '#252526',
149
+ text: '#d4d4d4',
150
+ muted: '#858585',
151
+ border: '#3c3c3c',
152
+ incoming: '#4ec9b0',
153
+ outgoing: '#dcdcaa',
154
+ online: '#4caf50',
155
+ offline: '#f44336',
156
+ };
157
+ const rootStyle = {
158
+ display: 'flex',
159
+ flexDirection: 'column',
160
+ gap: '12px',
161
+ height: '100vh',
162
+ boxSizing: 'border-box',
163
+ padding: '12px',
164
+ background: palette.background,
165
+ color: palette.text,
166
+ fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',
167
+ fontSize: '13px',
168
+ };
169
+ const panelStyle = {
170
+ border: `1px solid ${palette.border}`,
171
+ borderRadius: '4px',
172
+ background: palette.panel,
173
+ padding: '10px',
174
+ };
175
+ const toolbarStyle = {
176
+ display: 'flex',
177
+ flexWrap: 'wrap',
178
+ alignItems: 'center',
179
+ gap: '10px',
180
+ };
181
+ const controlStyle = {
182
+ background: palette.background,
183
+ color: palette.text,
184
+ border: `1px solid ${palette.border}`,
185
+ borderRadius: '3px',
186
+ padding: '4px 6px',
187
+ font: 'inherit',
188
+ };
189
+ const labelStyle = {
190
+ display: 'inline-flex',
191
+ alignItems: 'center',
192
+ gap: '4px',
193
+ color: palette.muted,
194
+ };
195
+ const logStyle = {
196
+ flex: '1',
197
+ overflowY: 'auto',
198
+ margin: '0',
199
+ whiteSpace: 'pre-wrap',
200
+ wordBreak: 'break-word',
201
+ };
202
+ function statusDotStyle(connected) {
203
+ return {
204
+ width: '10px',
205
+ height: '10px',
206
+ borderRadius: '50%',
207
+ background: connected ? palette.online : palette.offline,
208
+ };
209
+ }
210
+ function messageEntryStyle(direction) {
211
+ return {
212
+ borderLeft: `3px solid ${direction === 'incoming' ? palette.incoming : palette.outgoing}`,
213
+ padding: '2px 8px',
214
+ margin: '4px 0',
215
+ };
216
+ }
217
+
218
+ const DISPLAY_MODES = [DisplayMode.Embedded, DisplayMode.Dialog, DisplayMode.Popup, DisplayMode.Standalone];
219
+ const PROTOCOLS = ['none', 'v1', 'v2'];
220
+ function buildSelect(values, current, onChange) {
221
+ const select = createElement('select', { inlineStyle: controlStyle }).ref;
222
+ values.forEach((value) => {
223
+ const option = createElement('option').ref;
224
+ option.value = value;
225
+ option.textContent = value;
226
+ if (value === current) {
227
+ option.selected = true;
228
+ }
229
+ select.appendChild(option);
230
+ });
231
+ select.addEventListener('change', () => onChange(select.value));
232
+ return select;
233
+ }
234
+ function labelled(caption, control) {
235
+ const wrapper = label({ inlineStyle: labelStyle });
236
+ const text = span();
237
+ text.ref.textContent = caption;
238
+ wrapper.addChild(text);
239
+ wrapper.addChild(control);
240
+ return wrapper.ref;
241
+ }
242
+ function createControls(options) {
243
+ let width = options.width;
244
+ let height = options.height;
245
+ const panel = div({ inlineStyle: { ...panelStyle, ...toolbarStyle } });
246
+ const dot = div({ inlineStyle: statusDotStyle(false) });
247
+ const statusText = span();
248
+ statusText.ref.textContent = 'disconnected';
249
+ const status = div({ inlineStyle: labelStyle });
250
+ status.addChild(dot);
251
+ status.addChild(statusText);
252
+ panel.addChild(status);
253
+ const modeSelect = buildSelect(DISPLAY_MODES, options.displayMode, options.onDisplayModeChange);
254
+ panel.addChild(labelled('mode', modeSelect));
255
+ const emitResize = () => options.onResize({ width, height });
256
+ const widthInput = buildNumberInput(width, (value) => {
257
+ width = value;
258
+ emitResize();
259
+ });
260
+ const heightInput = buildNumberInput(height, (value) => {
261
+ height = value;
262
+ emitResize();
263
+ });
264
+ panel.addChild(labelled('w', widthInput));
265
+ panel.addChild(labelled('h', heightInput));
266
+ const protocolSelect = buildSelect(PROTOCOLS, options.protocol, options.onProtocolChange);
267
+ panel.addChild(labelled('security', protocolSelect));
268
+ return {
269
+ element: panel.ref,
270
+ setConnected: (connected) => {
271
+ dot.ref.style.background = connected ? palette.online : palette.offline;
272
+ statusText.ref.textContent = connected ? 'connected' : 'disconnected';
273
+ },
274
+ };
275
+ }
276
+ function buildNumberInput(value, onChange) {
277
+ const field = input({ inlineStyle: { ...controlStyle, width: '70px' } }).ref;
278
+ field.type = 'number';
279
+ field.value = `${value}`;
280
+ field.addEventListener('input', () => onChange(Number(field.value)));
281
+ return field;
282
+ }
283
+
284
+ const _JSON = globalThis.JSON;
285
+ const stringify = _JSON.stringify;
286
+
287
+ const VIEWS = ['raw', 'decrypted', 'pretty'];
288
+ function formatPayload(message, view) {
289
+ if (view === 'raw') {
290
+ return stringify(message.raw);
291
+ }
292
+ if (view === 'decrypted') {
293
+ return message.decrypted === undefined ? '(encrypted — no decrypted payload)' : stringify(message.decrypted);
294
+ }
295
+ return stringify(message.decrypted ?? message.raw, null, 2);
296
+ }
297
+ function renderEntry(message, view) {
298
+ const entry = div({ inlineStyle: messageEntryStyle(message.direction) });
299
+ const heading = div({ inlineStyle: { color: palette.muted, marginBottom: '2px' } });
300
+ heading.ref.textContent = `${message.direction === 'incoming' ? '◀ in' : '▶ out'}${message.channel ? ` · ${message.channel}` : ''}`;
301
+ const body = div();
302
+ body.ref.textContent = formatPayload(message, view);
303
+ entry.addChild(heading);
304
+ entry.addChild(body);
305
+ return entry.ref;
306
+ }
307
+ function createMessageLog() {
308
+ const messages = [];
309
+ let view = 'pretty';
310
+ const element = div({ inlineStyle: { ...panelStyle, display: 'flex', flexDirection: 'column', flex: '1', minHeight: '0' } });
311
+ const toolbar = div({ inlineStyle: toolbarStyle });
312
+ const title = div({ inlineStyle: labelStyle });
313
+ title.ref.textContent = 'Messages';
314
+ toolbar.addChild(title);
315
+ const body = div({ inlineStyle: logStyle });
316
+ const render = () => {
317
+ body.ref.textContent = '';
318
+ messages.forEach((message) => body.addChild(renderEntry(message, view)));
319
+ };
320
+ VIEWS.forEach((candidate) => {
321
+ const toggle = button({ inlineStyle: controlStyle });
322
+ toggle.ref.type = 'button';
323
+ toggle.ref.textContent = candidate;
324
+ toggle.ref.addEventListener('click', () => {
325
+ view = candidate;
326
+ render();
327
+ });
328
+ toolbar.addChild(toggle);
329
+ });
330
+ element.addChild(toolbar);
331
+ element.addChild(body);
332
+ return {
333
+ element: element.ref,
334
+ append: (message) => {
335
+ messages.push(message);
336
+ body.addChild(renderEntry(message, view));
337
+ },
338
+ setView: (next) => {
339
+ view = next;
340
+ render();
341
+ },
342
+ clear: () => {
343
+ messages.length = 0;
344
+ render();
345
+ },
346
+ };
347
+ }
348
+
349
+ const DEFAULT_WIDTH = 480;
350
+ const DEFAULT_HEIGHT = 360;
351
+ function originOf(url) {
352
+ try {
353
+ return createURL(url).origin;
354
+ }
355
+ catch {
356
+ return null;
357
+ }
358
+ }
359
+ function mountDebugUi(root, manifest, deps = {}) {
360
+ const view = deps.window ?? window;
361
+ assign(root.style, rootStyle);
362
+ const iframe = createElement('iframe', {
363
+ inlineStyle: { border: 'none', width: `${DEFAULT_WIDTH}px`, height: `${DEFAULT_HEIGHT}px`, background: '#fff' },
364
+ }).ref;
365
+ const firstApp = manifest.apps[0];
366
+ if (firstApp !== undefined) {
367
+ iframe.src = firstApp.url;
368
+ }
369
+ let securityReadout;
370
+ if (manifest.debug.securityView) {
371
+ const security = div({ inlineStyle: labelStyle });
372
+ const readout = span();
373
+ readout.ref.textContent = 'protocol: none';
374
+ security.addChild(readout);
375
+ securityReadout = readout.ref;
376
+ root.appendChild(security.ref);
377
+ }
378
+ const controls = createControls({
379
+ displayMode: DisplayMode.Embedded,
380
+ width: DEFAULT_WIDTH,
381
+ height: DEFAULT_HEIGHT,
382
+ protocol: 'none',
383
+ onDisplayModeChange: (mode) => iframe.setAttribute('data-display-mode', mode),
384
+ onResize: ({ width, height }) => {
385
+ iframe.style.width = `${width}px`;
386
+ iframe.style.height = `${height}px`;
387
+ },
388
+ onProtocolChange: (protocol) => {
389
+ if (securityReadout !== undefined) {
390
+ securityReadout.textContent = `protocol: ${protocol}`;
391
+ }
392
+ },
393
+ });
394
+ root.appendChild(controls.element);
395
+ const stage = div({ inlineStyle: { ...panelStyle, flex: '1', display: 'flex', minHeight: '0', overflow: 'auto' } });
396
+ stage.ref.appendChild(iframe);
397
+ root.appendChild(stage.ref);
398
+ let log;
399
+ if (manifest.debug.messageLog) {
400
+ log = createMessageLog();
401
+ root.appendChild(log.element);
402
+ }
403
+ const allowedOrigins = manifest.apps.map((app) => originOf(app.url)).filter((origin) => origin !== null);
404
+ const onMessage = (event) => {
405
+ if (!allowedOrigins.includes(event.origin)) {
406
+ return;
407
+ }
408
+ controls.setConnected(true);
409
+ log?.append({ direction: 'incoming', raw: event.data });
410
+ };
411
+ view.addEventListener('message', onMessage);
412
+ return {
413
+ element: root,
414
+ cleanup: () => {
415
+ view.removeEventListener('message', onMessage);
416
+ root.textContent = '';
417
+ },
418
+ };
419
+ }
420
+
421
+ const root = document.getElementById('hf-debug-root');
422
+ const manifest = window.__HF_DEBUG_MANIFEST__;
423
+ if (root !== null && manifest !== undefined) {
424
+ mountDebugUi(root, manifest);
425
+ }
426
+
427
+ })();
@@ -0,0 +1 @@
1
+ !function(){"use strict";const e=globalThis.Object,t=e.freeze,n=e.assign,i=globalThis.URL,o=globalThis.Reflect;"function"==typeof i.createObjectURL&&i.createObjectURL.bind(i),"function"==typeof i.revokeObjectURL&&i.revokeObjectURL.bind(i);const d=globalThis.Array,r=d.isArray,l=d.from,a=globalThis.Set,c=globalThis.Reflect;function s(e){return l((t=e,c.construct(a,t?[t]:[])));var t}function p(e,t){const i=document.createElement(e);t?.inlineStyle&&n(i.style,t.inlineStyle);const o=[];var d;t?.classNames&&r(t.classNames)&&o.push(...t.classNames),t?.className&&o.push(t.className),i.classList.add(...(d=s(o),d.filter(e=>![void 0,null,""].includes(e)&&""!==e.trim())));let l=!1;const a=e=>{if(!e)return;const t="ref"in e?e.ref:e;i.contains(t)||i.appendChild(t)},c=e=>{if(!e)return;const t="ref"in e?e.ref:e;t.contains(i)||t.appendChild(i)},p=e=>e?`opacity ${(e/1e3).toFixed(1)}s`:"none",u=e=>{i.style.transition=p(e),i.style.opacity="1",l=!0},f=e=>{i.style.transition=p(e),i.style.opacity="0",l=!1},h=e=>{if(!e)return;const t="ref"in e?e.ref:e;i.contains(t)&&i.removeChild(t)},g=()=>{const e=i.parentElement;e&&e.removeChild(i)};return{get addChild(){return a},get attachTo(){return c},get show(){return u},get hide(){return f},get removeChild(){return h},get detachFromParent(){return g},get ref(){return i},get visible(){return l}}}function u(e){return p("span",e)}function f(e){return p("div",e)}const h=t({Embedded:"embedded",Dialog:"dialog",Popup:"popup",Standalone:"standalone"}),g="#1e1e1e",y="#d4d4d4",x="#858585",m="#3c3c3c",C="#4ec9b0",b="#dcdcaa",v="#4caf50",w="#f44336",S={display:"flex",flexDirection:"column",gap:"12px",height:"100vh",boxSizing:"border-box",padding:"12px",background:g,color:y,fontFamily:"ui-monospace, SFMono-Regular, Menlo, monospace",fontSize:"13px"},E={border:`1px solid ${m}`,borderRadius:"4px",background:"#252526",padding:"10px"},R={display:"flex",flexWrap:"wrap",alignItems:"center",gap:"10px"},L={background:g,color:y,border:`1px solid ${m}`,borderRadius:"3px",padding:"4px 6px",font:"inherit"},k={display:"inline-flex",alignItems:"center",gap:"4px",color:x},$={flex:"1",overflowY:"auto",margin:"0",whiteSpace:"pre-wrap",wordBreak:"break-word"};const T=[h.Embedded,h.Dialog,h.Popup,h.Standalone],M=["none","v1","v2"];function N(e,t,n){const i=p("select",{inlineStyle:L}).ref;return e.forEach(e=>{const n=p("option").ref;n.value=e,n.textContent=e,e===t&&(n.selected=!0),i.appendChild(n)}),i.addEventListener("change",()=>n(i.value)),i}function D(e,t){const n=p("label",{inlineStyle:k});const i=u();return i.ref.textContent=e,n.addChild(i),n.addChild(t),n.ref}function F(e,t){const n=(i={inlineStyle:{...L,width:"70px"}},p("input",i)).ref;var i;return n.type="number",n.value=`${e}`,n.addEventListener("input",()=>t(Number(n.value))),n}const O=globalThis.JSON.stringify,U=["raw","decrypted","pretty"];function _(e,t){const n=f({inlineStyle:(i=e.direction,{borderLeft:`3px solid ${"incoming"===i?C:b}`,padding:"2px 8px",margin:"4px 0"})});var i;const o=f({inlineStyle:{color:x,marginBottom:"2px"}});o.ref.textContent=`${"incoming"===e.direction?"◀ in":"▶ out"}${e.channel?` · ${e.channel}`:""}`;const d=f();return d.ref.textContent=function(e,t){return"raw"===t?O(e.raw):"decrypted"===t?void 0===e.decrypted?"(encrypted — no decrypted payload)":O(e.decrypted):O(e.decrypted??e.raw,null,2)}(e,t),n.addChild(o),n.addChild(d),n.ref}function j(){const e=[];let t="pretty";const n=f({inlineStyle:{...E,display:"flex",flexDirection:"column",flex:"1",minHeight:"0"}}),i=f({inlineStyle:R}),o=f({inlineStyle:k});o.ref.textContent="Messages",i.addChild(o);const d=f({inlineStyle:$}),r=()=>{d.ref.textContent="",e.forEach(e=>d.addChild(_(e,t)))};return U.forEach(e=>{const n=p("button",{inlineStyle:L});n.ref.type="button",n.ref.textContent=e,n.ref.addEventListener("click",()=>{t=e,r()}),i.addChild(n)}),n.addChild(i),n.addChild(d),{element:n.ref,append:n=>{e.push(n),d.addChild(_(n,t))},setView:e=>{t=e,r()},clear:()=>{e.length=0,r()}}}function z(e){try{return((e,t)=>o.construct(i,[e,t]))(e).origin}catch{return null}}const P=document.getElementById("hf-debug-root"),A=window.__HF_DEBUG_MANIFEST__;null!==P&&void 0!==A&&function(e,t,i={}){const o=i.window??window;n(e.style,S);const d=p("iframe",{inlineStyle:{border:"none",width:"480px",height:"360px",background:"#fff"}}).ref,r=t.apps[0];let l;if(void 0!==r&&(d.src=r.url),t.debug.securityView){const t=f({inlineStyle:k}),n=u();n.ref.textContent="protocol: none",t.addChild(n),l=n.ref,e.appendChild(t.ref)}const a=function(e){let t=e.width,n=e.height;const i=f({inlineStyle:{...E,...R}}),o=f({inlineStyle:(d=!1,{width:"10px",height:"10px",borderRadius:"50%",background:d?v:w})});var d;const r=u();r.ref.textContent="disconnected";const l=f({inlineStyle:k});l.addChild(o),l.addChild(r),i.addChild(l);const a=N(T,e.displayMode,e.onDisplayModeChange);i.addChild(D("mode",a));const c=()=>e.onResize({width:t,height:n}),s=F(t,e=>{t=e,c()}),p=F(n,e=>{n=e,c()});i.addChild(D("w",s)),i.addChild(D("h",p));const h=N(M,e.protocol,e.onProtocolChange);return i.addChild(D("security",h)),{element:i.ref,setConnected:e=>{o.ref.style.background=e?v:w,r.ref.textContent=e?"connected":"disconnected"}}}({displayMode:h.Embedded,width:480,height:360,protocol:"none",onDisplayModeChange:e=>d.setAttribute("data-display-mode",e),onResize:({width:e,height:t})=>{d.style.width=`${e}px`,d.style.height=`${t}px`},onProtocolChange:e=>{void 0!==l&&(l.textContent=`protocol: ${e}`)}});e.appendChild(a.element);const c=f({inlineStyle:{...E,flex:"1",display:"flex",minHeight:"0",overflow:"auto"}});let s;c.ref.appendChild(d),e.appendChild(c.ref),t.debug.messageLog&&(s=j(),e.appendChild(s.element));const g=t.apps.map(e=>z(e.url)).filter(e=>null!==e),y=e=>{g.includes(e.origin)&&(a.setConnected(!0),s?.append({direction:"incoming",raw:e.data}))};o.addEventListener("message",y)}(P,A)}();
@@ -1 +1 @@
1
- {"version":3,"file":"dev-server.d.ts","sourceRoot":"","sources":["../../../../../../../libs/features/src/server/dev-server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AACxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AACnE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAezD,0CAA0C;AAC1C,MAAM,WAAW,YAAY;IAC3B,kDAAkD;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,iDAAiD;IACjD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,6CAA6C;IAC7C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACrB;AAED,mDAAmD;AACnD,MAAM,WAAW,cAAc;IAC7B,kDAAkD;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,6CAA6C;IAC7C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACrB;AAED,wFAAwF;AACxF,MAAM,WAAW,WAAW;IAC1B,8CAA8C;IAC9C,QAAQ,CAAC,IAAI,EAAE,SAAS,cAAc,EAAE,CAAA;IACxC,qCAAqC;IACrC,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAA;CACjC;AAED,2EAA2E;AAC3E,MAAM,WAAW,eAAe;IAC9B,sCAAsC;IACtC,QAAQ,CAAC,IAAI,EAAE,SAAS,YAAY,EAAE,CAAA;IACtC,4CAA4C;IAC5C,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAA;IAC9B,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,4DAA4D;IAC5D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AAED,kFAAkF;AAClF,MAAM,WAAW,aAAc,SAAQ,iBAAiB;IACtD,qDAAqD;IACrD,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,KAAK,IAAI,KAAK,MAAM,CAAA;IAChG,+GAA+G;IAC/G,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAC5B;AAsHD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,iBAAiB,EAAE,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,eAAe,CAAC,CA6BlH"}
1
+ {"version":3,"file":"dev-server.d.ts","sourceRoot":"","sources":["../../../../../../../libs/features/src/server/dev-server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AACxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AACnE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAgBzD,0CAA0C;AAC1C,MAAM,WAAW,YAAY;IAC3B,kDAAkD;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,iDAAiD;IACjD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,6CAA6C;IAC7C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACrB;AAED,mDAAmD;AACnD,MAAM,WAAW,cAAc;IAC7B,kDAAkD;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,6CAA6C;IAC7C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACrB;AAED,wFAAwF;AACxF,MAAM,WAAW,WAAW;IAC1B,8CAA8C;IAC9C,QAAQ,CAAC,IAAI,EAAE,SAAS,cAAc,EAAE,CAAA;IACxC,qCAAqC;IACrC,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAA;CACjC;AAED,2EAA2E;AAC3E,MAAM,WAAW,eAAe;IAC9B,sCAAsC;IACtC,QAAQ,CAAC,IAAI,EAAE,SAAS,YAAY,EAAE,CAAA;IACtC,4CAA4C;IAC5C,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAA;IAC9B,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,4DAA4D;IAC5D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AAED,kFAAkF;AAClF,MAAM,WAAW,aAAc,SAAQ,iBAAiB;IACtD,qDAAqD;IACrD,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,KAAK,IAAI,KAAK,MAAM,CAAA;IAChG,+GAA+G;IAC/G,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAC5B;AAqKD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,iBAAiB,EAAE,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,eAAe,CAAC,CA8BlH"}
@@ -11,6 +11,7 @@ const index_cjs_js$6 = require('../_dependencies/@hyperfrontend/immutable-api-ut
11
11
  const index_cjs_js$5 = require('../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/promise/index.cjs.js');
12
12
  const index_cjs_js$4 = require('../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/object/index.cjs.js');
13
13
 
14
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
14
15
  // note: Resolution order — JSON first, then JS, then TS.
15
16
  const CONFIG_EXTENSIONS = ['.json', '.js', '.mjs', '.cjs', '.ts', '.cts', '.mts'];
16
17
  /** Base name (no extension) of the dev-server config file. */
@@ -263,6 +264,29 @@ async function resolveDevConfig(options) {
263
264
  };
264
265
  }
265
266
 
267
+ /**
268
+ * Directory of the currently-running module under either module system.
269
+ *
270
+ * The CommonJS build (and any CommonJS host) exposes `__dirname`; the
271
+ * ES-module build derives the directory from `import.meta.url`. Both formats
272
+ * ship beside the `debug-ui` assets, so the result anchors asset
273
+ * self-location wherever the package is installed or embedded.
274
+ *
275
+ * @returns Absolute directory path of the running module.
276
+ *
277
+ * @example Anchoring an asset lookup beside the running module
278
+ * ```typescript
279
+ * const assetDir = join(currentModuleDir(), 'debug-ui')
280
+ * ```
281
+ */
282
+ function currentModuleDir() {
283
+ // why: `typeof` guards the CommonJS-only global so the ES-module build falls through to `import.meta.url` instead of crashing on an undefined identifier.
284
+ if (typeof __dirname !== 'undefined') {
285
+ return __dirname;
286
+ }
287
+ return node_path.dirname(node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs.js', document.baseURI).href))));
288
+ }
289
+
266
290
  // note: Minimal MIME table for the asset types a compiled feature/debug-UI bundle ships; anything else falls back to octet-stream.
267
291
  const CONTENT_TYPES = index_cjs_js$4.freeze({
268
292
  '.html': 'text/html; charset=utf-8',
@@ -371,23 +395,66 @@ function createStaticHandler(root, deps = {}) {
371
395
  return (req, res) => serveFile(root, req.url ?? '/', res, deps);
372
396
  }
373
397
 
374
- // note: Path prefix the control server serves the compiled debug-UI assets under; the page loads `/__debug/bootstrap.js`.
398
+ // note: Path prefix the control server serves the compiled debug-UI assets under; the page loads `/__debug/index.iife.min.js`.
375
399
  const DEBUG_PREFIX = '/__debug';
376
400
  // note: Placeholder the debug-UI HTML embeds; the control server swaps it for the live JSON manifest at request time.
377
401
  const MANIFEST_TOKEN = 'HF_MANIFEST_PLACEHOLDER';
378
402
  /**
379
- * Resolves the directory the compiled debug-UI assets ship in, located beside
380
- * this module via `__dirname` so the server finds them wherever the package is
381
- * installed.
403
+ * Probes a single directory for the shipped debug-UI assets, checking both a
404
+ * sibling `debug-ui` folder (running from the `server/` output) and a nested
405
+ * `server/debug-ui` folder (running from another package entry, such as the
406
+ * CLI bin at the package root).
407
+ *
408
+ * @param dir - Candidate directory expected to hold the assets.
409
+ * @param isFile - File probe used to confirm the assets exist.
410
+ * @returns The `debug-ui` asset directory, or `undefined` when it is not here.
411
+ */
412
+ function probeAssetDir(dir, isFile) {
413
+ const sibling = node_path.join(dir, 'debug-ui');
414
+ if (isFile(node_path.join(sibling, 'index.html'))) {
415
+ return sibling;
416
+ }
417
+ const nested = node_path.join(dir, 'server', 'debug-ui');
418
+ return isFile(node_path.join(nested, 'index.html')) ? nested : undefined;
419
+ }
420
+ /**
421
+ * Locates the debug-UI assets by ascending from a start directory toward the
422
+ * filesystem root, returning the first ancestor holding a `debug-ui` folder.
423
+ *
424
+ * @param startDir - Directory the ascent begins from.
425
+ * @param isFile - File probe used to confirm the assets exist.
426
+ * @returns The `debug-ui` asset directory, or `undefined` when no ancestor holds one.
427
+ */
428
+ function ascendForAssets(startDir, isFile) {
429
+ let dir = startDir;
430
+ let parent = node_path.dirname(dir);
431
+ // how: probe each level then step up; the final probe covers the filesystem root, where parent === dir
432
+ while (parent !== dir) {
433
+ const found = probeAssetDir(dir, isFile);
434
+ if (found !== undefined) {
435
+ return found;
436
+ }
437
+ dir = parent;
438
+ parent = node_path.dirname(dir);
439
+ }
440
+ return probeAssetDir(dir, isFile);
441
+ }
442
+ /**
443
+ * Resolves the directory the compiled debug-UI assets ship in by ascending
444
+ * from the running module (located via `__dirname` in CommonJS or
445
+ * `import.meta.url` in ESM). The ascent finds the assets wherever the package
446
+ * lives — the built dist, an installed `node_modules` copy, or embedded
447
+ * inside a consumer's bundle output.
382
448
  *
449
+ * @param isFile - File probe used to confirm the assets exist.
383
450
  * @returns The absolute debug-UI asset directory.
384
451
  */
385
- function defaultAssetRoot() {
386
- /* istanbul ignore if -- @preserve the ESM build has no __dirname; the shipped CommonJS build and the test runner always define it */
387
- if (typeof __dirname === 'undefined') {
388
- throw index_cjs_js$1.createError('@hyperfrontend/features dev server self-location requires the CommonJS build; inject `assetRoot` otherwise.');
452
+ function defaultAssetRoot(isFile) {
453
+ const located = ascendForAssets(currentModuleDir(), isFile);
454
+ if (located === undefined) {
455
+ throw index_cjs_js$1.createError('@hyperfrontend/features dev server could not locate the bundled debug-UI assets beside the running module; inject `assetRoot` to point at a directory containing the debug-UI `index.html`.');
389
456
  }
390
- return node_path.join(__dirname, 'debug-ui');
457
+ return located;
391
458
  }
392
459
  /**
393
460
  * Reads the listening port from a server, throwing if the address is unexpectedly absent.
@@ -498,7 +565,6 @@ function controlHandler(manifest, assetRoot, deps) {
498
565
  */
499
566
  async function startDevServer(config, deps = {}) {
500
567
  const createServer = deps.createServer ?? node_http.createServer;
501
- const assetRoot = deps.assetRoot ?? defaultAssetRoot();
502
568
  const servers = [];
503
569
  const apps = [];
504
570
  for (const app of config.apps) {
@@ -510,6 +576,8 @@ async function startDevServer(config, deps = {}) {
510
576
  const manifest = { apps: apps.map((app) => ({ name: app.name, url: app.url })), debug: config.debug };
511
577
  let debugUrl;
512
578
  if (config.debug.enabled) {
579
+ // why: resolved only when the debug UI is enabled so consumers with it disabled never pay for (or fail on) asset self-location.
580
+ const assetRoot = deps.assetRoot ?? defaultAssetRoot(deps.isFile ?? index_cjs_js.isFile);
513
581
  const control = createServer(controlHandler(manifest, assetRoot, deps));
514
582
  const port = await listen(control, config.debugPort);
515
583
  servers.push(control);