@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.
- package/README.md +283 -68
- package/dist/{chunk-XTDK7ME5.js → chunk-S4DTUQII.js} +246 -19
- package/dist/chunk-S4DTUQII.js.map +1 -0
- package/dist/core/index.d.ts +423 -3
- package/dist/core/index.js +23 -2
- package/dist/core/index.js.map +1 -0
- package/dist/index.d.ts +2 -3
- package/dist/index.js +29 -5
- package/dist/index.js.map +1 -0
- package/package.json +7 -183
- package/.turbo/turbo-build.log +0 -81
- package/.turbo/turbo-lint.log +0 -40
- package/.turbo/turbo-typecheck.log +0 -4
- package/TESTING.md +0 -124
- package/dist/adapter-MMD-iHNx.d.ts +0 -424
- package/dist/adapters/tier-1/angular.d.ts +0 -60
- package/dist/adapters/tier-1/angular.js +0 -2
- package/dist/adapters/tier-1/index.d.ts +0 -7
- package/dist/adapters/tier-1/index.js +0 -7
- package/dist/adapters/tier-1/qwik.d.ts +0 -55
- package/dist/adapters/tier-1/qwik.js +0 -2
- package/dist/adapters/tier-1/react.d.ts +0 -67
- package/dist/adapters/tier-1/react.js +0 -2
- package/dist/adapters/tier-1/solid.d.ts +0 -45
- package/dist/adapters/tier-1/solid.js +0 -2
- package/dist/adapters/tier-1/svelte.d.ts +0 -48
- package/dist/adapters/tier-1/svelte.js +0 -2
- package/dist/adapters/tier-1/vue.d.ts +0 -47
- package/dist/adapters/tier-1/vue.js +0 -2
- package/dist/adapters/tier-2/index.d.ts +0 -7
- package/dist/adapters/tier-2/index.js +0 -7
- package/dist/adapters/tier-2/inferno.d.ts +0 -31
- package/dist/adapters/tier-2/inferno.js +0 -2
- package/dist/adapters/tier-2/lit.d.ts +0 -34
- package/dist/adapters/tier-2/lit.js +0 -2
- package/dist/adapters/tier-2/marko.d.ts +0 -59
- package/dist/adapters/tier-2/marko.js +0 -2
- package/dist/adapters/tier-2/mithril.d.ts +0 -31
- package/dist/adapters/tier-2/mithril.js +0 -2
- package/dist/adapters/tier-2/preact.d.ts +0 -33
- package/dist/adapters/tier-2/preact.js +0 -2
- package/dist/adapters/tier-2/stencil.d.ts +0 -52
- package/dist/adapters/tier-2/stencil.js +0 -2
- package/dist/adapters/tier-3/alpine.d.ts +0 -73
- package/dist/adapters/tier-3/alpine.js +0 -2
- package/dist/adapters/tier-3/hotwire.d.ts +0 -71
- package/dist/adapters/tier-3/hotwire.js +0 -2
- package/dist/adapters/tier-3/htmx.d.ts +0 -88
- package/dist/adapters/tier-3/htmx.js +0 -2
- package/dist/adapters/tier-3/index.d.ts +0 -7
- package/dist/adapters/tier-3/index.js +0 -7
- package/dist/adapters/tier-3/petite-vue.d.ts +0 -56
- package/dist/adapters/tier-3/petite-vue.js +0 -2
- package/dist/adapters/tier-3/stimulus.d.ts +0 -63
- package/dist/adapters/tier-3/stimulus.js +0 -2
- package/dist/adapters/tier-3/vanilla.d.ts +0 -63
- package/dist/adapters/tier-3/vanilla.js +0 -2
- package/dist/chunk-2SNQ6PTM.js +0 -217
- package/dist/chunk-3D4XMIZI.js +0 -136
- package/dist/chunk-3HU6GSQ4.js +0 -125
- package/dist/chunk-4PZDNFL7.js +0 -148
- package/dist/chunk-5IBLFTYL.js +0 -114
- package/dist/chunk-64JZJ7OK.js +0 -142
- package/dist/chunk-7ZJI3QU2.js +0 -132
- package/dist/chunk-CE4FJHQJ.js +0 -133
- package/dist/chunk-DTCAUBH5.js +0 -87
- package/dist/chunk-NTASPOHG.js +0 -106
- package/dist/chunk-OI2AMQLG.js +0 -152
- package/dist/chunk-Q7HUE44H.js +0 -106
- package/dist/chunk-QH3LOWXU.js +0 -155
- package/dist/chunk-QIVAK6BH.js +0 -103
- package/dist/chunk-V34XPVGK.js +0 -103
- package/dist/chunk-VK7ZPMO7.js +0 -221
- package/dist/chunk-X6CNUW6T.js +0 -136
- package/dist/chunk-YFGSHW5S.js +0 -121
- package/dist/chunk-ZAJVSE7J.js +0 -90
- package/docs/ADAPTERS.md +0 -946
- package/docs/PATTERNS.md +0 -836
- package/src/adapters/tier-1/angular.ts +0 -223
- package/src/adapters/tier-1/index.ts +0 -12
- package/src/adapters/tier-1/qwik.ts +0 -177
- package/src/adapters/tier-1/react.ts +0 -330
- package/src/adapters/tier-1/solid.ts +0 -222
- package/src/adapters/tier-1/svelte.ts +0 -211
- package/src/adapters/tier-1/vue.ts +0 -234
- package/src/adapters/tier-2/index.ts +0 -12
- package/src/adapters/tier-2/inferno.ts +0 -149
- package/src/adapters/tier-2/lit.ts +0 -191
- package/src/adapters/tier-2/marko.ts +0 -199
- package/src/adapters/tier-2/mithril.ts +0 -152
- package/src/adapters/tier-2/preact.ts +0 -133
- package/src/adapters/tier-2/stencil.ts +0 -214
- package/src/adapters/tier-3/alpine.ts +0 -218
- package/src/adapters/tier-3/hotwire.ts +0 -254
- package/src/adapters/tier-3/htmx.ts +0 -263
- package/src/adapters/tier-3/index.ts +0 -12
- package/src/adapters/tier-3/petite-vue.ts +0 -163
- package/src/adapters/tier-3/stimulus.ts +0 -233
- package/src/adapters/tier-3/vanilla.ts +0 -252
- package/src/ambient.d.ts +0 -310
- package/src/core/adapter.ts +0 -366
- package/src/core/index.ts +0 -56
- package/src/core/registry.ts +0 -518
- package/src/core/types.ts +0 -461
- package/src/htmx.ts +0 -134
- package/src/index.ts +0 -263
- package/test/__mocks__/stencil-core.ts +0 -19
- package/test/__mocks__/stencil-hydrate.ts +0 -15
- package/test/adapters/tier-1.test.ts +0 -206
- package/test/adapters/tier-2.test.ts +0 -175
- package/test/adapters/tier-3.test.ts +0 -284
- package/test/contracts/adapter.contract.ts +0 -293
- package/test/core/core.test.ts +0 -310
- package/test/errors/error-handling.test.ts +0 -454
- package/test/integration/htmx.integration.test.ts +0 -246
- package/test/integration/react.integration.test.ts +0 -271
- package/test/integration/registry.integration.test.ts +0 -308
- package/tsconfig.json +0 -22
- package/tsup.config.ts +0 -93
- package/vitest.config.ts +0 -101
package/test/core/core.test.ts
DELETED
|
@@ -1,310 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @flightdev/ui - Core Module Tests
|
|
3
|
-
*
|
|
4
|
-
* Tests for the core infrastructure: types and base adapter.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { describe, it, expect, beforeEach, beforeAll } from 'vitest';
|
|
8
|
-
|
|
9
|
-
// ============================================================================
|
|
10
|
-
// Type Tests
|
|
11
|
-
// ============================================================================
|
|
12
|
-
|
|
13
|
-
import type { AdapterCapabilities } from '../../src/core/types.js';
|
|
14
|
-
|
|
15
|
-
import { DEFAULT_CAPABILITIES, TIER_INFO } from '../../src/core/types.js';
|
|
16
|
-
|
|
17
|
-
describe('Core Types', () => {
|
|
18
|
-
describe('DEFAULT_CAPABILITIES', () => {
|
|
19
|
-
it('has all required capability flags', () => {
|
|
20
|
-
expect(DEFAULT_CAPABILITIES).toHaveProperty('streaming');
|
|
21
|
-
expect(DEFAULT_CAPABILITIES).toHaveProperty('partialHydration');
|
|
22
|
-
expect(DEFAULT_CAPABILITIES).toHaveProperty('islands');
|
|
23
|
-
expect(DEFAULT_CAPABILITIES).toHaveProperty('resumable');
|
|
24
|
-
expect(DEFAULT_CAPABILITIES).toHaveProperty('ssg');
|
|
25
|
-
expect(DEFAULT_CAPABILITIES).toHaveProperty('csr');
|
|
26
|
-
expect(DEFAULT_CAPABILITIES).toHaveProperty('serverComponents');
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it('all capabilities are booleans', () => {
|
|
30
|
-
for (const [key, value] of Object.entries(DEFAULT_CAPABILITIES)) {
|
|
31
|
-
expect(typeof value, `${key} should be boolean`).toBe('boolean');
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it('defaults are conservative (false)', () => {
|
|
36
|
-
expect(DEFAULT_CAPABILITIES.streaming).toBe(false);
|
|
37
|
-
expect(DEFAULT_CAPABILITIES.serverComponents).toBe(false);
|
|
38
|
-
expect(DEFAULT_CAPABILITIES.resumable).toBe(false);
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
describe('TIER_INFO', () => {
|
|
43
|
-
it('has info for all three tiers', () => {
|
|
44
|
-
expect(TIER_INFO['tier-1']).toBeDefined();
|
|
45
|
-
expect(TIER_INFO['tier-2']).toBeDefined();
|
|
46
|
-
expect(TIER_INFO['tier-3']).toBeDefined();
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('each tier has name and description', () => {
|
|
50
|
-
for (const tier of ['tier-1', 'tier-2', 'tier-3'] as const) {
|
|
51
|
-
expect(TIER_INFO[tier].name).toBeDefined();
|
|
52
|
-
expect(TIER_INFO[tier].description).toBeDefined();
|
|
53
|
-
expect(typeof TIER_INFO[tier].name).toBe('string');
|
|
54
|
-
expect(typeof TIER_INFO[tier].description).toBe('string');
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
// ============================================================================
|
|
61
|
-
// Base Adapter Tests
|
|
62
|
-
// ============================================================================
|
|
63
|
-
|
|
64
|
-
import { BaseUIAdapter, isV2Adapter } from '../../src/core/adapter.js';
|
|
65
|
-
import type { Component, RenderResult } from '../../src/core/types.js';
|
|
66
|
-
|
|
67
|
-
// Create a testable subclass to access protected methods
|
|
68
|
-
class TestableAdapter extends BaseUIAdapter {
|
|
69
|
-
readonly id = 'test';
|
|
70
|
-
readonly name = 'Test Adapter';
|
|
71
|
-
readonly framework = 'test-framework';
|
|
72
|
-
readonly tier = 'tier-2' as const;
|
|
73
|
-
|
|
74
|
-
// Expose protected methods for testing
|
|
75
|
-
public testGenerateId = () => this.generateId();
|
|
76
|
-
public testEscapeHtml = (html: string) => this.escapeHtml(html);
|
|
77
|
-
public testSerializeProps = (props?: Record<string, unknown>) => this.serializeProps(props);
|
|
78
|
-
public testCreateTiming = (startTime: number) => this.createTiming(startTime);
|
|
79
|
-
|
|
80
|
-
async renderToString(component: Component): Promise<RenderResult> {
|
|
81
|
-
const html = `<div>${(component.props as { text?: string })?.text ?? 'default'}</div>`;
|
|
82
|
-
return {
|
|
83
|
-
html,
|
|
84
|
-
hydrationData: { props: component.props },
|
|
85
|
-
timing: this.createTiming(performance.now() - 1),
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
getHydrationScript(): string {
|
|
90
|
-
return '<script>/* hydration */</script>';
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
getClientEntry(): string {
|
|
94
|
-
return 'export function hydrate() {}';
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
describe('BaseUIAdapter', () => {
|
|
99
|
-
let adapter: TestableAdapter;
|
|
100
|
-
|
|
101
|
-
beforeEach(() => {
|
|
102
|
-
adapter = new TestableAdapter();
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
describe('Identity', () => {
|
|
106
|
-
it('has required identity properties', () => {
|
|
107
|
-
expect(adapter.id).toBe('test');
|
|
108
|
-
expect(adapter.name).toBe('Test Adapter');
|
|
109
|
-
expect(adapter.framework).toBe('test-framework');
|
|
110
|
-
expect(adapter.tier).toBe('tier-2');
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
describe('Capabilities', () => {
|
|
115
|
-
it('has default capabilities', () => {
|
|
116
|
-
expect(adapter.capabilities).toBeDefined();
|
|
117
|
-
expect(adapter.capabilities.streaming).toBe(false);
|
|
118
|
-
});
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
describe('Helper Methods', () => {
|
|
122
|
-
it('generateId returns unique IDs', () => {
|
|
123
|
-
const id1 = adapter.testGenerateId();
|
|
124
|
-
const id2 = adapter.testGenerateId();
|
|
125
|
-
|
|
126
|
-
expect(id1).toBeDefined();
|
|
127
|
-
expect(id2).toBeDefined();
|
|
128
|
-
expect(id1).not.toBe(id2);
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
it('escapeHtml escapes special characters', () => {
|
|
132
|
-
const escaped = adapter.testEscapeHtml('<script>alert("xss")</script>');
|
|
133
|
-
|
|
134
|
-
expect(escaped).not.toContain('<script>');
|
|
135
|
-
expect(escaped).toContain('<');
|
|
136
|
-
expect(escaped).toContain('>');
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
it('serializeProps returns JSON string', () => {
|
|
140
|
-
const serialized = adapter.testSerializeProps({ name: 'test', count: 42 });
|
|
141
|
-
|
|
142
|
-
expect(typeof serialized).toBe('string');
|
|
143
|
-
expect(JSON.parse(serialized)).toEqual({ name: 'test', count: 42 });
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
it('serializeProps handles undefined', () => {
|
|
147
|
-
const serialized = adapter.testSerializeProps(undefined);
|
|
148
|
-
|
|
149
|
-
expect(serialized).toBe('{}');
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
it('createTiming returns timing object', () => {
|
|
153
|
-
const timing = adapter.testCreateTiming(performance.now() - 100);
|
|
154
|
-
|
|
155
|
-
expect(timing).toBeDefined();
|
|
156
|
-
expect(typeof timing.total).toBe('number');
|
|
157
|
-
expect(timing.total).toBeGreaterThanOrEqual(0);
|
|
158
|
-
});
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
describe('Render', () => {
|
|
162
|
-
it('renderToString returns RenderResult', async () => {
|
|
163
|
-
const result = await adapter.renderToString({
|
|
164
|
-
component: () => { },
|
|
165
|
-
props: { text: 'Hello' },
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
expect(result.html).toContain('Hello');
|
|
169
|
-
expect(result.hydrationData).toBeDefined();
|
|
170
|
-
expect(result.timing).toBeDefined();
|
|
171
|
-
});
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
describe('Islands (Default)', () => {
|
|
175
|
-
it('createIsland is defined', () => {
|
|
176
|
-
expect(typeof adapter.createIsland).toBe('function');
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
it('createIsland returns island object', () => {
|
|
180
|
-
const island = adapter.createIsland('my-comp', { prop: 'value' });
|
|
181
|
-
|
|
182
|
-
expect(island.id).toBeDefined();
|
|
183
|
-
expect(island.component).toBe('my-comp');
|
|
184
|
-
expect(island.props).toEqual({ prop: 'value' });
|
|
185
|
-
expect(island.placeholder).toBeDefined();
|
|
186
|
-
});
|
|
187
|
-
});
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
// ============================================================================
|
|
191
|
-
// Adapter Utilities Tests
|
|
192
|
-
// ============================================================================
|
|
193
|
-
|
|
194
|
-
describe('isV2Adapter', () => {
|
|
195
|
-
it('returns true for V2 adapters', () => {
|
|
196
|
-
const v2Adapter = {
|
|
197
|
-
id: 'test',
|
|
198
|
-
name: 'Test',
|
|
199
|
-
framework: 'test',
|
|
200
|
-
tier: 'tier-1',
|
|
201
|
-
capabilities: { ...DEFAULT_CAPABILITIES },
|
|
202
|
-
renderToString: async () => ({ html: '' }),
|
|
203
|
-
getHydrationScript: () => '',
|
|
204
|
-
getClientEntry: () => '',
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
expect(isV2Adapter(v2Adapter)).toBe(true);
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
it('returns false for V1 adapters', () => {
|
|
211
|
-
const v1Adapter = {
|
|
212
|
-
name: 'test',
|
|
213
|
-
framework: 'test',
|
|
214
|
-
renderToString: async () => ({ html: '' }),
|
|
215
|
-
getHydrationScript: () => '',
|
|
216
|
-
getClientEntry: () => '',
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
// V1 adapters don't have 'tier' or 'capabilities'
|
|
220
|
-
expect(isV2Adapter(v1Adapter)).toBe(false);
|
|
221
|
-
});
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
// ============================================================================
|
|
225
|
-
// Registry Tests
|
|
226
|
-
// ============================================================================
|
|
227
|
-
|
|
228
|
-
import { adapterRegistry, registerBuiltinAdapters } from '../../src/core/registry.js';
|
|
229
|
-
|
|
230
|
-
describe('AdapterRegistry', () => {
|
|
231
|
-
beforeAll(() => {
|
|
232
|
-
registerBuiltinAdapters();
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
describe('Registration', () => {
|
|
236
|
-
it('registerBuiltinAdapters registers all adapters', () => {
|
|
237
|
-
// Check Tier 1
|
|
238
|
-
expect(adapterRegistry.has('react')).toBe(true);
|
|
239
|
-
expect(adapterRegistry.has('vue')).toBe(true);
|
|
240
|
-
expect(adapterRegistry.has('angular')).toBe(true);
|
|
241
|
-
|
|
242
|
-
// Check Tier 2
|
|
243
|
-
expect(adapterRegistry.has('preact')).toBe(true);
|
|
244
|
-
expect(adapterRegistry.has('lit')).toBe(true);
|
|
245
|
-
|
|
246
|
-
// Check Tier 3
|
|
247
|
-
expect(adapterRegistry.has('htmx')).toBe(true);
|
|
248
|
-
expect(adapterRegistry.has('alpine')).toBe(true);
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
it('lists adapters by tier', () => {
|
|
252
|
-
const tier1 = adapterRegistry.listByTier('tier-1');
|
|
253
|
-
expect(tier1).toContain('react');
|
|
254
|
-
expect(tier1).toContain('vue');
|
|
255
|
-
expect(tier1).toContain('angular');
|
|
256
|
-
expect(tier1).toContain('svelte');
|
|
257
|
-
expect(tier1).toContain('solid');
|
|
258
|
-
expect(tier1).toContain('qwik');
|
|
259
|
-
expect(tier1.length).toBe(6);
|
|
260
|
-
|
|
261
|
-
const tier2 = adapterRegistry.listByTier('tier-2');
|
|
262
|
-
expect(tier2).toContain('preact');
|
|
263
|
-
expect(tier2).toContain('lit');
|
|
264
|
-
expect(tier2.length).toBe(6);
|
|
265
|
-
|
|
266
|
-
const tier3 = adapterRegistry.listByTier('tier-3');
|
|
267
|
-
expect(tier3).toContain('htmx');
|
|
268
|
-
expect(tier3).toContain('alpine');
|
|
269
|
-
expect(tier3.length).toBe(6);
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
it('total adapters is 18', () => {
|
|
273
|
-
const tier1 = adapterRegistry.listByTier('tier-1');
|
|
274
|
-
const tier2 = adapterRegistry.listByTier('tier-2');
|
|
275
|
-
const tier3 = adapterRegistry.listByTier('tier-3');
|
|
276
|
-
|
|
277
|
-
expect(tier1.length + tier2.length + tier3.length).toBe(18);
|
|
278
|
-
});
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
describe('Retrieval', () => {
|
|
282
|
-
it('get returns adapter instance', async () => {
|
|
283
|
-
const adapter = await adapterRegistry.get('react');
|
|
284
|
-
expect(adapter).toBeDefined();
|
|
285
|
-
expect(adapter?.id).toBe('react');
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
it('get returns undefined for unknown adapter', async () => {
|
|
289
|
-
const adapter = await adapterRegistry.get('unknown-adapter');
|
|
290
|
-
expect(adapter).toBeUndefined();
|
|
291
|
-
});
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
describe('Query', () => {
|
|
295
|
-
it('listByCapability returns adapters with capability', () => {
|
|
296
|
-
const streaming = adapterRegistry.listByCapability('streaming');
|
|
297
|
-
expect(streaming).toContain('react');
|
|
298
|
-
expect(streaming).toContain('vue');
|
|
299
|
-
expect(streaming).toContain('solid');
|
|
300
|
-
expect(streaming).toContain('qwik');
|
|
301
|
-
expect(streaming).toContain('marko');
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
it('listByCapability filters correctly', () => {
|
|
305
|
-
const resumable = adapterRegistry.listByCapability('resumable');
|
|
306
|
-
expect(resumable).toContain('qwik');
|
|
307
|
-
expect(resumable).not.toContain('react');
|
|
308
|
-
});
|
|
309
|
-
});
|
|
310
|
-
});
|