@flightdev/ui 2.0.1 → 4.0.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 (120) hide show
  1. package/README.md +283 -68
  2. package/dist/{chunk-XTDK7ME5.js → chunk-S4DTUQII.js} +246 -19
  3. package/dist/chunk-S4DTUQII.js.map +1 -0
  4. package/dist/core/index.d.ts +423 -3
  5. package/dist/core/index.js +23 -2
  6. package/dist/core/index.js.map +1 -0
  7. package/dist/index.d.ts +2 -3
  8. package/dist/index.js +29 -5
  9. package/dist/index.js.map +1 -0
  10. package/package.json +7 -183
  11. package/.turbo/turbo-build.log +0 -81
  12. package/.turbo/turbo-lint.log +0 -40
  13. package/.turbo/turbo-typecheck.log +0 -4
  14. package/TESTING.md +0 -124
  15. package/dist/adapter-MMD-iHNx.d.ts +0 -424
  16. package/dist/adapters/tier-1/angular.d.ts +0 -60
  17. package/dist/adapters/tier-1/angular.js +0 -2
  18. package/dist/adapters/tier-1/index.d.ts +0 -7
  19. package/dist/adapters/tier-1/index.js +0 -7
  20. package/dist/adapters/tier-1/qwik.d.ts +0 -55
  21. package/dist/adapters/tier-1/qwik.js +0 -2
  22. package/dist/adapters/tier-1/react.d.ts +0 -67
  23. package/dist/adapters/tier-1/react.js +0 -2
  24. package/dist/adapters/tier-1/solid.d.ts +0 -45
  25. package/dist/adapters/tier-1/solid.js +0 -2
  26. package/dist/adapters/tier-1/svelte.d.ts +0 -48
  27. package/dist/adapters/tier-1/svelte.js +0 -2
  28. package/dist/adapters/tier-1/vue.d.ts +0 -47
  29. package/dist/adapters/tier-1/vue.js +0 -2
  30. package/dist/adapters/tier-2/index.d.ts +0 -7
  31. package/dist/adapters/tier-2/index.js +0 -7
  32. package/dist/adapters/tier-2/inferno.d.ts +0 -31
  33. package/dist/adapters/tier-2/inferno.js +0 -2
  34. package/dist/adapters/tier-2/lit.d.ts +0 -34
  35. package/dist/adapters/tier-2/lit.js +0 -2
  36. package/dist/adapters/tier-2/marko.d.ts +0 -59
  37. package/dist/adapters/tier-2/marko.js +0 -2
  38. package/dist/adapters/tier-2/mithril.d.ts +0 -31
  39. package/dist/adapters/tier-2/mithril.js +0 -2
  40. package/dist/adapters/tier-2/preact.d.ts +0 -33
  41. package/dist/adapters/tier-2/preact.js +0 -2
  42. package/dist/adapters/tier-2/stencil.d.ts +0 -52
  43. package/dist/adapters/tier-2/stencil.js +0 -2
  44. package/dist/adapters/tier-3/alpine.d.ts +0 -73
  45. package/dist/adapters/tier-3/alpine.js +0 -2
  46. package/dist/adapters/tier-3/hotwire.d.ts +0 -71
  47. package/dist/adapters/tier-3/hotwire.js +0 -2
  48. package/dist/adapters/tier-3/htmx.d.ts +0 -88
  49. package/dist/adapters/tier-3/htmx.js +0 -2
  50. package/dist/adapters/tier-3/index.d.ts +0 -7
  51. package/dist/adapters/tier-3/index.js +0 -7
  52. package/dist/adapters/tier-3/petite-vue.d.ts +0 -56
  53. package/dist/adapters/tier-3/petite-vue.js +0 -2
  54. package/dist/adapters/tier-3/stimulus.d.ts +0 -63
  55. package/dist/adapters/tier-3/stimulus.js +0 -2
  56. package/dist/adapters/tier-3/vanilla.d.ts +0 -63
  57. package/dist/adapters/tier-3/vanilla.js +0 -2
  58. package/dist/chunk-2SNQ6PTM.js +0 -217
  59. package/dist/chunk-3D4XMIZI.js +0 -136
  60. package/dist/chunk-3HU6GSQ4.js +0 -125
  61. package/dist/chunk-4PZDNFL7.js +0 -148
  62. package/dist/chunk-5IBLFTYL.js +0 -114
  63. package/dist/chunk-64JZJ7OK.js +0 -142
  64. package/dist/chunk-7ZJI3QU2.js +0 -132
  65. package/dist/chunk-CE4FJHQJ.js +0 -133
  66. package/dist/chunk-DTCAUBH5.js +0 -87
  67. package/dist/chunk-NTASPOHG.js +0 -106
  68. package/dist/chunk-OI2AMQLG.js +0 -152
  69. package/dist/chunk-Q7HUE44H.js +0 -106
  70. package/dist/chunk-QH3LOWXU.js +0 -155
  71. package/dist/chunk-QIVAK6BH.js +0 -103
  72. package/dist/chunk-V34XPVGK.js +0 -103
  73. package/dist/chunk-VK7ZPMO7.js +0 -221
  74. package/dist/chunk-X6CNUW6T.js +0 -136
  75. package/dist/chunk-YFGSHW5S.js +0 -121
  76. package/dist/chunk-ZAJVSE7J.js +0 -90
  77. package/docs/ADAPTERS.md +0 -946
  78. package/docs/PATTERNS.md +0 -836
  79. package/src/adapters/tier-1/angular.ts +0 -223
  80. package/src/adapters/tier-1/index.ts +0 -12
  81. package/src/adapters/tier-1/qwik.ts +0 -177
  82. package/src/adapters/tier-1/react.ts +0 -330
  83. package/src/adapters/tier-1/solid.ts +0 -222
  84. package/src/adapters/tier-1/svelte.ts +0 -211
  85. package/src/adapters/tier-1/vue.ts +0 -234
  86. package/src/adapters/tier-2/index.ts +0 -12
  87. package/src/adapters/tier-2/inferno.ts +0 -149
  88. package/src/adapters/tier-2/lit.ts +0 -191
  89. package/src/adapters/tier-2/marko.ts +0 -199
  90. package/src/adapters/tier-2/mithril.ts +0 -152
  91. package/src/adapters/tier-2/preact.ts +0 -133
  92. package/src/adapters/tier-2/stencil.ts +0 -214
  93. package/src/adapters/tier-3/alpine.ts +0 -218
  94. package/src/adapters/tier-3/hotwire.ts +0 -254
  95. package/src/adapters/tier-3/htmx.ts +0 -263
  96. package/src/adapters/tier-3/index.ts +0 -12
  97. package/src/adapters/tier-3/petite-vue.ts +0 -163
  98. package/src/adapters/tier-3/stimulus.ts +0 -233
  99. package/src/adapters/tier-3/vanilla.ts +0 -252
  100. package/src/ambient.d.ts +0 -310
  101. package/src/core/adapter.ts +0 -366
  102. package/src/core/index.ts +0 -56
  103. package/src/core/registry.ts +0 -518
  104. package/src/core/types.ts +0 -461
  105. package/src/htmx.ts +0 -134
  106. package/src/index.ts +0 -263
  107. package/test/__mocks__/stencil-core.ts +0 -19
  108. package/test/__mocks__/stencil-hydrate.ts +0 -15
  109. package/test/adapters/tier-1.test.ts +0 -206
  110. package/test/adapters/tier-2.test.ts +0 -175
  111. package/test/adapters/tier-3.test.ts +0 -284
  112. package/test/contracts/adapter.contract.ts +0 -293
  113. package/test/core/core.test.ts +0 -310
  114. package/test/errors/error-handling.test.ts +0 -454
  115. package/test/integration/htmx.integration.test.ts +0 -246
  116. package/test/integration/react.integration.test.ts +0 -271
  117. package/test/integration/registry.integration.test.ts +0 -308
  118. package/tsconfig.json +0 -22
  119. package/tsup.config.ts +0 -93
  120. package/vitest.config.ts +0 -101
@@ -1,330 +0,0 @@
1
- /**
2
- * @flightdev/ui - React Adapter (Tier 1)
3
- *
4
- * Full-featured React 18+ SSR adapter with streaming and hydration support.
5
- *
6
- * @module @flightdev/ui/react
7
- * @version 2.0.0
8
- */
9
-
10
- import { BaseUIAdapter } from '../../core/adapter.js';
11
- import type {
12
- AdapterCapabilities,
13
- Component,
14
- RenderContext,
15
- RenderResult,
16
- StreamingOptions,
17
- StreamingRenderResult,
18
- } from '../../core/types.js';
19
-
20
- // ============================================================================
21
- // Types
22
- // ============================================================================
23
-
24
- export interface ReactAdapterOptions {
25
- /** Enable streaming SSR with renderToPipeableStream */
26
- streaming?: boolean;
27
-
28
- /** Enable React Server Components support */
29
- serverComponents?: boolean;
30
-
31
- /** Custom error handler for streaming */
32
- onError?: (error: Error) => void;
33
-
34
- /** Custom shell ready handler */
35
- onShellReady?: () => void;
36
- }
37
-
38
- // ============================================================================
39
- // React Adapter
40
- // ============================================================================
41
-
42
- export class ReactAdapter extends BaseUIAdapter {
43
- readonly id = 'react';
44
- readonly name = 'React';
45
- readonly framework = 'react';
46
- readonly frameworkVersion = '18+';
47
- readonly tier = 'tier-1' as const;
48
-
49
- override readonly capabilities: AdapterCapabilities = {
50
- streaming: true,
51
- partialHydration: true,
52
- islands: true,
53
- resumable: false, // React 19 has some resumability features
54
- ssg: true,
55
- csr: true,
56
- serverComponents: true,
57
- };
58
-
59
- constructor(private options: ReactAdapterOptions = {}) {
60
- super();
61
- }
62
-
63
- async renderToString(
64
- component: Component,
65
- _context?: RenderContext
66
- ): Promise<RenderResult> {
67
- const startTime = performance.now();
68
-
69
- // Dynamic imports for React SSR
70
- const { renderToString } = await import('react-dom/server');
71
- const { createElement } = await import('react');
72
-
73
- // Create React element
74
- const element = createElement(
75
- component.component as React.ComponentType,
76
- (component.props ?? {}) as Record<string, unknown>,
77
- component.children as React.ReactNode
78
- );
79
-
80
- const html = renderToString(element);
81
-
82
- return {
83
- html,
84
- hydrationData: {
85
- props: component.props,
86
- componentId: component.id ?? this.generateId(),
87
- },
88
- timing: this.createTiming(startTime),
89
- };
90
- }
91
-
92
- /**
93
- * Render to stream using React 18+ streaming SSR.
94
- *
95
- * Uses `renderToReadableStream` (Web Streams API) which works in:
96
- * - Node.js 18+ (with Web Streams support)
97
- * - Deno
98
- * - Cloudflare Workers
99
- * - Vercel Edge Runtime
100
- * - Other edge runtimes
101
- *
102
- * Falls back to `renderToPipeableStream` for Node.js environments
103
- * that require traditional streams.
104
- */
105
- renderToStream(
106
- component: Component,
107
- _context?: RenderContext,
108
- options?: StreamingOptions
109
- ): StreamingRenderResult {
110
- let aborted = false;
111
- let abortController: AbortController | null = null;
112
- let resolvePromise: () => void;
113
- let rejectPromise: (error: Error) => void;
114
-
115
- const done = new Promise<void>((resolve, reject) => {
116
- resolvePromise = resolve;
117
- rejectPromise = reject;
118
- });
119
-
120
- const stream = new ReadableStream<Uint8Array>({
121
- start: async (controller) => {
122
- try {
123
- // Use renderToReadableStream - the Web Streams API version
124
- // This is the recommended approach for modern Node.js and edge runtimes
125
- const { renderToReadableStream } = await import('react-dom/server');
126
- const { createElement } = await import('react');
127
-
128
- // Create React element
129
- const element = createElement(
130
- component.component as React.ComponentType,
131
- (component.props ?? {}) as Record<string, unknown>,
132
- component.children as React.ReactNode
133
- );
134
-
135
- // Create abort controller for cancellation
136
- abortController = new AbortController();
137
-
138
- // Render to ReadableStream
139
- const reactStream = await renderToReadableStream(element, {
140
- signal: abortController.signal,
141
- onError(error: unknown) {
142
- const err = error instanceof Error ? error : new Error(String(error));
143
- options?.onError?.(err);
144
- // Don't reject here - let the stream handle it
145
- },
146
- });
147
-
148
- // Notify shell is ready
149
- options?.onShellReady?.();
150
-
151
- // Get reader from React's stream
152
- const reader = reactStream.getReader();
153
-
154
- // Read and forward chunks
155
- const pump = async (): Promise<void> => {
156
- try {
157
- while (true) {
158
- if (aborted) {
159
- await reader.cancel();
160
- controller.close();
161
- resolvePromise();
162
- return;
163
- }
164
-
165
- const { done: readerDone, value } = await reader.read();
166
-
167
- if (readerDone) {
168
- controller.close();
169
- options?.onAllReady?.();
170
- resolvePromise();
171
- return;
172
- }
173
-
174
- if (value) {
175
- controller.enqueue(value);
176
- }
177
- }
178
- } catch (error) {
179
- const err = error instanceof Error ? error : new Error(String(error));
180
- options?.onError?.(err);
181
- controller.error(err);
182
- rejectPromise(err);
183
- }
184
- };
185
-
186
- // Start pumping data
187
- await pump();
188
-
189
- } catch (error) {
190
- const err = error instanceof Error ? error : new Error(String(error));
191
-
192
- // Check if renderToReadableStream is not available (older Node.js)
193
- if (err.message.includes('renderToReadableStream')) {
194
- // Fallback to synchronous render for environments without Web Streams
195
- await this.fallbackStreamRender(component, controller, options, resolvePromise, rejectPromise);
196
- return;
197
- }
198
-
199
- options?.onShellError?.(err);
200
- options?.onError?.(err);
201
- controller.error(err);
202
- rejectPromise(err);
203
- }
204
- },
205
- });
206
-
207
- return {
208
- stream,
209
- done,
210
- abort: () => {
211
- aborted = true;
212
- abortController?.abort();
213
- resolvePromise();
214
- },
215
- };
216
- }
217
-
218
- /**
219
- * Fallback render for environments without Web Streams support.
220
- * Uses renderToString and emits as a single chunk.
221
- */
222
- private async fallbackStreamRender(
223
- component: Component,
224
- controller: ReadableStreamDefaultController<Uint8Array>,
225
- options: StreamingOptions | undefined,
226
- resolvePromise: () => void,
227
- rejectPromise: (error: Error) => void
228
- ): Promise<void> {
229
- try {
230
- const { renderToString } = await import('react-dom/server');
231
- const { createElement } = await import('react');
232
-
233
- const element = createElement(
234
- component.component as React.ComponentType,
235
- (component.props ?? {}) as Record<string, unknown>,
236
- component.children as React.ReactNode
237
- );
238
-
239
- options?.onShellReady?.();
240
-
241
- const html = renderToString(element);
242
- const encoded = new TextEncoder().encode(html);
243
-
244
- controller.enqueue(encoded);
245
- controller.close();
246
- options?.onAllReady?.();
247
- resolvePromise();
248
- } catch (error) {
249
- const err = error instanceof Error ? error : new Error(String(error));
250
- options?.onError?.(err);
251
- controller.error(err);
252
- rejectPromise(err);
253
- }
254
- }
255
-
256
- override getHydrationScript(result: RenderResult): string {
257
- const data = this.serializeProps(result.hydrationData);
258
- return `
259
- <script type="module">
260
- window.__FLIGHT_DATA__ = ${data};
261
- window.__FLIGHT_ADAPTER__ = 'react';
262
-
263
- import { hydrateRoot } from 'react-dom/client';
264
-
265
- const container = document.getElementById('app');
266
- const App = window.__FLIGHT_APP__;
267
-
268
- if (container && App) {
269
- const { props } = window.__FLIGHT_DATA__;
270
- import('react').then(({ createElement }) => {
271
- hydrateRoot(container, createElement(App, props));
272
- });
273
- }
274
- </script>
275
- `.trim();
276
- }
277
-
278
- override getClientEntry(): string {
279
- return `
280
- import { hydrateRoot, createRoot } from 'react-dom/client';
281
- import { createElement } from 'react';
282
-
283
- export function hydrate() {
284
- const container = document.getElementById('app');
285
- const App = window.__FLIGHT_APP__;
286
- const data = window.__FLIGHT_DATA__ ?? {};
287
-
288
- if (!container || !App) {
289
- console.warn('[Flight/React] Missing container or App');
290
- return;
291
- }
292
-
293
- // Check if we have SSR content to hydrate
294
- if (container.innerHTML.trim()) {
295
- hydrateRoot(container, createElement(App, data.props));
296
- } else {
297
- // Fallback to client-side render
298
- createRoot(container).render(createElement(App, data.props));
299
- }
300
- }
301
-
302
- export function render(App, container, props = {}) {
303
- const root = createRoot(container);
304
- root.render(createElement(App, props));
305
- return root;
306
- }
307
- `.trim();
308
- }
309
- }
310
-
311
- // ============================================================================
312
- // Factory Function
313
- // ============================================================================
314
-
315
- /**
316
- * Create a React UI adapter.
317
- *
318
- * @example
319
- * ```typescript
320
- * import { react } from '@flightdev/ui/react';
321
- * import { defineUI } from '@flightdev/ui';
322
- *
323
- * export default defineUI(react({ streaming: true }));
324
- * ```
325
- */
326
- export function react(options?: ReactAdapterOptions): ReactAdapter {
327
- return new ReactAdapter(options);
328
- }
329
-
330
- export default react;
@@ -1,222 +0,0 @@
1
- /**
2
- * @flightdev/ui - Solid Adapter (Tier 1)
3
- *
4
- * Full-featured SolidJS SSR adapter with streaming and hydration support.
5
- *
6
- * @module @flightdev/ui/solid
7
- * @version 2.0.0
8
- */
9
-
10
- import { BaseUIAdapter } from '../../core/adapter.js';
11
- import type {
12
- AdapterCapabilities,
13
- Component,
14
- RenderContext,
15
- RenderResult,
16
- StreamingOptions,
17
- StreamingRenderResult,
18
- } from '../../core/types.js';
19
-
20
- // ============================================================================
21
- // Types
22
- // ============================================================================
23
-
24
- export interface SolidAdapterOptions {
25
- /** Enable streaming SSR */
26
- streaming?: boolean;
27
-
28
- /** Render timeout in milliseconds */
29
- timeout?: number;
30
- }
31
-
32
- // ============================================================================
33
- // Solid Adapter
34
- // ============================================================================
35
-
36
- export class SolidAdapter extends BaseUIAdapter {
37
- readonly id = 'solid';
38
- readonly name = 'Solid';
39
- readonly framework = 'solid';
40
- readonly frameworkVersion = '1.8+';
41
- readonly tier = 'tier-1' as const;
42
-
43
- override readonly capabilities: AdapterCapabilities = {
44
- streaming: true,
45
- partialHydration: true,
46
- islands: true,
47
- resumable: false,
48
- ssg: true,
49
- csr: true,
50
- serverComponents: false,
51
- };
52
-
53
- constructor(private options: SolidAdapterOptions = {}) {
54
- super();
55
- }
56
-
57
- async renderToString(
58
- component: Component,
59
- _context?: RenderContext
60
- ): Promise<RenderResult> {
61
- const startTime = performance.now();
62
-
63
- const { renderToString } = await import('solid-js/web');
64
-
65
- const SolidComponent = component.component as () => unknown;
66
- const props = component.props ?? {};
67
-
68
- // Create a function that returns the component with props
69
- const App = () => SolidComponent() as object;
70
-
71
- const html = await renderToString(() => SolidComponent() as object);
72
-
73
- return {
74
- html,
75
- hydrationData: {
76
- props,
77
- componentId: component.id ?? this.generateId(),
78
- },
79
- timing: this.createTiming(startTime),
80
- };
81
- }
82
-
83
- renderToStream(
84
- component: Component,
85
- _context?: RenderContext,
86
- options?: StreamingOptions
87
- ): StreamingRenderResult {
88
- let aborted = false;
89
- let resolvePromise: () => void;
90
- let rejectPromise: (error: Error) => void;
91
-
92
- const done = new Promise<void>((resolve, reject) => {
93
- resolvePromise = resolve;
94
- rejectPromise = reject;
95
- });
96
-
97
- const stream = new ReadableStream<Uint8Array>({
98
- async start(controller) {
99
- try {
100
- const { renderToStream: solidRenderToStream } = await import('solid-js/web');
101
-
102
- const SolidComponent = component.component as () => object;
103
- const App = () => SolidComponent();
104
-
105
- const { readable } = solidRenderToStream(() => SolidComponent());
106
- const reader = readable.getReader();
107
-
108
- options?.onShellReady?.();
109
-
110
- while (true) {
111
- const { done: readerDone, value } = await reader.read();
112
-
113
- if (aborted) {
114
- reader.cancel();
115
- break;
116
- }
117
-
118
- if (readerDone) {
119
- controller.close();
120
- resolvePromise();
121
- options?.onAllReady?.();
122
- break;
123
- }
124
-
125
- // Convert string to Uint8Array if needed
126
- const chunk = typeof value === 'string'
127
- ? new TextEncoder().encode(value)
128
- : value;
129
-
130
- controller.enqueue(chunk);
131
- }
132
- } catch (error) {
133
- const err = error instanceof Error ? error : new Error(String(error));
134
- options?.onError?.(err);
135
- controller.error(err);
136
- rejectPromise(err);
137
- }
138
- },
139
- });
140
-
141
- return {
142
- stream,
143
- done,
144
- abort() {
145
- aborted = true;
146
- resolvePromise();
147
- },
148
- };
149
- }
150
-
151
- override getHydrationScript(result: RenderResult): string {
152
- const data = this.serializeProps(result.hydrationData);
153
- return `
154
- <script type="module">
155
- window.__FLIGHT_DATA__ = ${data};
156
- window.__FLIGHT_ADAPTER__ = 'solid';
157
-
158
- import { hydrate } from 'solid-js/web';
159
-
160
- const App = window.__FLIGHT_APP__;
161
- const container = document.getElementById('app');
162
-
163
- if (App && container) {
164
- hydrate(() => App(window.__FLIGHT_DATA__.props), container);
165
- }
166
- </script>
167
- `.trim();
168
- }
169
-
170
- override getClientEntry(): string {
171
- return `
172
- import { hydrate, render } from 'solid-js/web';
173
-
174
- export function hydrateApp() {
175
- const container = document.getElementById('app');
176
- const App = window.__FLIGHT_APP__;
177
- const data = window.__FLIGHT_DATA__ ?? {};
178
-
179
- if (!container || !App) {
180
- console.warn('[Flight/Solid] Missing container or App');
181
- return;
182
- }
183
-
184
- // Check if we have SSR content to hydrate
185
- if (container.innerHTML.trim()) {
186
- return hydrate(() => App(data.props), container);
187
- } else {
188
- // Fallback to client-side render
189
- return render(() => App(data.props), container);
190
- }
191
- }
192
-
193
- export function renderApp(App, container, props = {}) {
194
- return render(() => App(props), container);
195
- }
196
-
197
- // Export for Flight
198
- export { hydrateApp as hydrate };
199
- `.trim();
200
- }
201
- }
202
-
203
- // ============================================================================
204
- // Factory Function
205
- // ============================================================================
206
-
207
- /**
208
- * Create a Solid UI adapter.
209
- *
210
- * @example
211
- * ```typescript
212
- * import { solid } from '@flightdev/ui/solid';
213
- * import { defineUI } from '@flightdev/ui';
214
- *
215
- * export default defineUI(solid({ streaming: true }));
216
- * ```
217
- */
218
- export function solid(options?: SolidAdapterOptions): SolidAdapter {
219
- return new SolidAdapter(options);
220
- }
221
-
222
- export default solid;