@esportsplus/template 0.16.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 (90) hide show
  1. package/.editorconfig +9 -0
  2. package/.gitattributes +2 -0
  3. package/.github/dependabot.yml +25 -0
  4. package/.github/workflows/bump.yml +9 -0
  5. package/.github/workflows/dependabot.yml +12 -0
  6. package/.github/workflows/publish.yml +16 -0
  7. package/README.md +385 -0
  8. package/build/attributes.d.ts +5 -0
  9. package/build/attributes.js +212 -0
  10. package/build/compiler/codegen.d.ts +21 -0
  11. package/build/compiler/codegen.js +303 -0
  12. package/build/compiler/constants.d.ts +16 -0
  13. package/build/compiler/constants.js +19 -0
  14. package/build/compiler/index.d.ts +14 -0
  15. package/build/compiler/index.js +61 -0
  16. package/build/compiler/parser.d.ts +19 -0
  17. package/build/compiler/parser.js +164 -0
  18. package/build/compiler/plugins/tsc.d.ts +3 -0
  19. package/build/compiler/plugins/tsc.js +4 -0
  20. package/build/compiler/plugins/vite.d.ts +13 -0
  21. package/build/compiler/plugins/vite.js +8 -0
  22. package/build/compiler/ts-analyzer.d.ts +4 -0
  23. package/build/compiler/ts-analyzer.js +63 -0
  24. package/build/compiler/ts-parser.d.ts +24 -0
  25. package/build/compiler/ts-parser.js +67 -0
  26. package/build/constants.d.ts +12 -0
  27. package/build/constants.js +25 -0
  28. package/build/event/index.d.ts +10 -0
  29. package/build/event/index.js +90 -0
  30. package/build/event/onconnect.d.ts +3 -0
  31. package/build/event/onconnect.js +15 -0
  32. package/build/event/onresize.d.ts +3 -0
  33. package/build/event/onresize.js +26 -0
  34. package/build/event/ontick.d.ts +6 -0
  35. package/build/event/ontick.js +41 -0
  36. package/build/html.d.ts +9 -0
  37. package/build/html.js +7 -0
  38. package/build/index.d.ts +8 -0
  39. package/build/index.js +12 -0
  40. package/build/render.d.ts +3 -0
  41. package/build/render.js +8 -0
  42. package/build/slot/array.d.ts +25 -0
  43. package/build/slot/array.js +189 -0
  44. package/build/slot/cleanup.d.ts +4 -0
  45. package/build/slot/cleanup.js +23 -0
  46. package/build/slot/effect.d.ts +12 -0
  47. package/build/slot/effect.js +85 -0
  48. package/build/slot/index.d.ts +7 -0
  49. package/build/slot/index.js +14 -0
  50. package/build/slot/render.d.ts +2 -0
  51. package/build/slot/render.js +44 -0
  52. package/build/svg.d.ts +5 -0
  53. package/build/svg.js +14 -0
  54. package/build/types.d.ts +23 -0
  55. package/build/types.js +1 -0
  56. package/build/utilities.d.ts +7 -0
  57. package/build/utilities.js +31 -0
  58. package/package.json +43 -0
  59. package/src/attributes.ts +313 -0
  60. package/src/compiler/codegen.ts +492 -0
  61. package/src/compiler/constants.ts +25 -0
  62. package/src/compiler/index.ts +87 -0
  63. package/src/compiler/parser.ts +242 -0
  64. package/src/compiler/plugins/tsc.ts +6 -0
  65. package/src/compiler/plugins/vite.ts +10 -0
  66. package/src/compiler/ts-analyzer.ts +89 -0
  67. package/src/compiler/ts-parser.ts +112 -0
  68. package/src/constants.ts +44 -0
  69. package/src/event/index.ts +130 -0
  70. package/src/event/onconnect.ts +22 -0
  71. package/src/event/onresize.ts +37 -0
  72. package/src/event/ontick.ts +59 -0
  73. package/src/html.ts +18 -0
  74. package/src/index.ts +19 -0
  75. package/src/llm.txt +403 -0
  76. package/src/render.ts +13 -0
  77. package/src/slot/array.ts +257 -0
  78. package/src/slot/cleanup.ts +37 -0
  79. package/src/slot/effect.ts +114 -0
  80. package/src/slot/index.ts +17 -0
  81. package/src/slot/render.ts +61 -0
  82. package/src/svg.ts +27 -0
  83. package/src/types.ts +40 -0
  84. package/src/utilities.ts +53 -0
  85. package/storage/compiler-architecture-2026-01-13.md +420 -0
  86. package/test/dist/test.js +1912 -0
  87. package/test/dist/test.js.map +1 -0
  88. package/test/index.ts +648 -0
  89. package/test/vite.config.ts +23 -0
  90. package/tsconfig.json +8 -0
package/test/index.ts ADDED
@@ -0,0 +1,648 @@
1
+ /**
2
+ * Extensive compiler integration tests
3
+ * Tests both reactivity and template compilers working together
4
+ */
5
+ import { html, reactive } from '@esportsplus/frontend';
6
+
7
+
8
+ // ============================================================================
9
+ // Test 1: Primitive Signals in Templates
10
+ // ============================================================================
11
+
12
+ function testPrimitiveSignals() {
13
+ let count = reactive(0),
14
+ enabled = reactive(true),
15
+ message = reactive('Hello'),
16
+ price = reactive(19.99);
17
+
18
+ // Template with primitive expressions
19
+ let view = html`
20
+ <div class="counter">
21
+ <span class="count">${count}</span>
22
+ <span class="enabled">${enabled}</span>
23
+ <span class="message">${message}</span>
24
+ <span class="price">${price}</span>
25
+ </div>
26
+ `;
27
+
28
+ // Increment/decrement operations
29
+ count++;
30
+ count--;
31
+ count += 5;
32
+ count -= 2;
33
+ count *= 2;
34
+
35
+ // Boolean toggle
36
+ enabled = !enabled;
37
+
38
+ // String operations
39
+ message = message + ' World';
40
+
41
+ return { count, enabled, message, price, view };
42
+ }
43
+
44
+
45
+ // ============================================================================
46
+ // Test 2: Computed Values in Templates
47
+ // ============================================================================
48
+
49
+ function testComputedValues() {
50
+ let firstName = reactive('John'),
51
+ lastName = reactive('Doe'),
52
+ items = reactive([1, 2, 3, 4, 5] as number[]);
53
+
54
+ // Computed values
55
+ let fullName = reactive(() => `${firstName} ${lastName}`),
56
+ itemCount = reactive(() => items.length),
57
+ doubled = reactive(() => items.map(x => x * 2)),
58
+ total = reactive(() => items.reduce((a, b) => a + b, 0));
59
+
60
+ let view = html`
61
+ <div class="computed">
62
+ <h1>${fullName}</h1>
63
+ <p>Items: ${itemCount}</p>
64
+ <p>Total: ${total}</p>
65
+ <ul>
66
+ ${() => doubled.map(n => html`<li>${n}</li>`)}
67
+ </ul>
68
+ </div>
69
+ `;
70
+
71
+ // Trigger reactivity
72
+ firstName = 'Jane';
73
+ items.push(6);
74
+
75
+ return { doubled, firstName, fullName, itemCount, items, lastName, total, view };
76
+ }
77
+
78
+
79
+ // ============================================================================
80
+ // Test 3: Reactive Arrays in Templates
81
+ // ============================================================================
82
+
83
+ function testReactiveArrays() {
84
+ let numbers = reactive([1, 2, 3] as number[]),
85
+ strings = reactive(['a', 'b', 'c'] as string[]),
86
+ mixed = reactive([1, 'two', 3, 'four'] as (number | string)[]);
87
+
88
+ // Array with reactive rendering
89
+ let view = html`
90
+ <div class="arrays">
91
+ <section>
92
+ <h2>Numbers</h2>
93
+ ${html.reactive(numbers, (n) => html`<span class="num">${n}</span>`)}
94
+ </section>
95
+ <section>
96
+ <h2>Strings</h2>
97
+ ${html.reactive(strings, (s) => html`<span class="str">${s}</span>`)}
98
+ </section>
99
+ <section>
100
+ <h2>Mixed</h2>
101
+ ${html.reactive(mixed, (m) => html`<span class="mix">${m}</span>`)}
102
+ </section>
103
+ </div>
104
+ `;
105
+
106
+ // Array mutations
107
+ numbers.push(4);
108
+ numbers.unshift(0);
109
+ numbers[2] = 99;
110
+
111
+ strings.pop();
112
+ strings.shift();
113
+ strings.splice(0, 0, 'inserted');
114
+
115
+ // Length access (reactive)
116
+ let numLen = numbers.length,
117
+ strLen = strings.length;
118
+
119
+ return { mixed, numLen, numbers, strLen, strings, view };
120
+ }
121
+
122
+
123
+ // ============================================================================
124
+ // Test 4: Reactive Objects in Templates
125
+ // ============================================================================
126
+
127
+ function testReactiveObjects() {
128
+ // Simple reactive object
129
+ let user = reactive({
130
+ age: 25,
131
+ email: 'john@example.com',
132
+ name: 'John'
133
+ });
134
+
135
+ // Reactive object with computed
136
+ let product = reactive({
137
+ discount: 0.1,
138
+ finalPrice: () => product.price * (1 - product.discount),
139
+ price: 100
140
+ });
141
+
142
+ // Nested data in reactive object
143
+ let config = reactive({
144
+ debug: false,
145
+ features: {
146
+ darkMode: true,
147
+ notifications: false
148
+ },
149
+ theme: 'light'
150
+ });
151
+
152
+ let view = html`
153
+ <div class="objects">
154
+ <section class="user">
155
+ <h2>${user.name}</h2>
156
+ <p>Age: ${user.age}</p>
157
+ <p>Email: ${user.email}</p>
158
+ </section>
159
+ <section class="product">
160
+ <p>Price: $${product.price}</p>
161
+ <p>Discount: ${() => product.discount * 100}%</p>
162
+ <p>Final: $${product.finalPrice}</p>
163
+ </section>
164
+ <section class="config">
165
+ <p>Theme: ${config.theme}</p>
166
+ <p>Debug: ${config.debug}</p>
167
+ </section>
168
+ </div>
169
+ `;
170
+
171
+ // Object mutations
172
+ user.name = 'Jane';
173
+ user.age++;
174
+
175
+ product.price = 150;
176
+ product.discount = 0.2;
177
+
178
+ config.theme = 'dark';
179
+ config.debug = true;
180
+
181
+ return { config, product, user, view };
182
+ }
183
+
184
+
185
+ // ============================================================================
186
+ // Test 5: Complex Nested Reactivity
187
+ // ============================================================================
188
+
189
+ function testComplexNested() {
190
+ let state = reactive({
191
+ counts: reactive([0, 0, 0] as number[]),
192
+ currentIndex: 0,
193
+ increment: () => {
194
+ state.counts[state.currentIndex]++;
195
+ },
196
+ items: reactive([
197
+ { id: 1, name: 'Item 1', selected: false },
198
+ { id: 2, name: 'Item 2', selected: true },
199
+ { id: 3, name: 'Item 3', selected: false }
200
+ ] as { id: number; name: string; selected: boolean }[]),
201
+ selectedCount: () => state.items.filter(i => i.selected).length,
202
+ total: () => state.counts.reduce((a, b) => a + b, 0)
203
+ });
204
+
205
+ let view = html`
206
+ <div class="complex">
207
+ <header>
208
+ <span>Total: ${state.total}</span>
209
+ <span>Selected: ${state.selectedCount}</span>
210
+ </header>
211
+ <main>
212
+ ${html.reactive(state.items, (item) => html`
213
+ <div class="item ${() => item.selected ? 'selected' : ''}">
214
+ <span>${item.name}</span>
215
+ <input type="checkbox" checked=${() => item.selected} />
216
+ </div>
217
+ `)}
218
+ </main>
219
+ <footer>
220
+ ${html.reactive(state.counts, (count, i) => html`
221
+ <button onclick=${() => { state.currentIndex = i; state.increment(); }}>
222
+ Count ${i}: ${count}
223
+ </button>
224
+ `)}
225
+ </footer>
226
+ </div>
227
+ `;
228
+
229
+ // Trigger updates
230
+ state.items[0].selected = true;
231
+ state.counts[0] = 5;
232
+ state.currentIndex = 1;
233
+
234
+ return { state, view };
235
+ }
236
+
237
+
238
+ // ============================================================================
239
+ // Test 6: Conditional Rendering with Reactivity
240
+ // ============================================================================
241
+
242
+ function testConditionalRendering() {
243
+ let showDetails = reactive(false),
244
+ status = reactive<'loading' | 'error' | 'success'>('loading'),
245
+ user = reactive<{ name: string } | null>(null);
246
+
247
+ let view = html`
248
+ <div class="conditional">
249
+ ${() => showDetails ? html`<details>Expanded content</details>` : html`<summary>Click to expand</summary>`}
250
+
251
+ ${() => {
252
+ if (status === 'loading') {
253
+ return html`<div class="loading">Loading...</div>`;
254
+ }
255
+
256
+ if (status === 'error') {
257
+ return html`<div class="error">Error occurred</div>`;
258
+ }
259
+
260
+ return html`<div class="success">Success!</div>`;
261
+ }}
262
+
263
+ ${() => user ? html`<span>Welcome, ${user.name}</span>` : html`<span>Please log in</span>`}
264
+ </div>
265
+ `;
266
+
267
+ // Toggle states
268
+ showDetails = true;
269
+ status = 'success';
270
+ user = { name: 'Alice' };
271
+
272
+ return { showDetails, status, user, view };
273
+ }
274
+
275
+
276
+ // ============================================================================
277
+ // Test 7: Event Handlers with Reactive State
278
+ // ============================================================================
279
+
280
+ function testEventHandlers() {
281
+ let clicks = reactive(0),
282
+ inputValue = reactive(''),
283
+ items = reactive([] as string[]);
284
+
285
+ let view = html`
286
+ <div class="events">
287
+ <button onclick=${() => clicks++}>
288
+ Clicked ${clicks} times
289
+ </button>
290
+
291
+ <input
292
+ type="text"
293
+ value=${inputValue}
294
+ oninput=${(e: Event) => { inputValue = (e.target as HTMLInputElement).value; }}
295
+ />
296
+
297
+ <button onclick=${() => {
298
+ if (inputValue) {
299
+ items.push(inputValue);
300
+ inputValue = '';
301
+ }
302
+ }}>
303
+ Add Item
304
+ </button>
305
+
306
+ <ul>
307
+ ${html.reactive(items, (item, index) => html`
308
+ <li>
309
+ ${item}
310
+ <button onclick=${() => items.splice(index, 1)}>Remove</button>
311
+ </li>
312
+ `)}
313
+ </ul>
314
+ </div>
315
+ `;
316
+
317
+ // Simulate interactions
318
+ clicks++;
319
+ clicks++;
320
+ inputValue = 'Test item';
321
+ items.push('First');
322
+ items.push('Second');
323
+
324
+ return { clicks, inputValue, items, view };
325
+ }
326
+
327
+
328
+ // ============================================================================
329
+ // Test 8: Attribute Bindings with Reactivity
330
+ // ============================================================================
331
+
332
+ function testAttributeBindings() {
333
+ let isDisabled = reactive(false),
334
+ classes = reactive('primary'),
335
+ styles = reactive('color: red'),
336
+ href = reactive('https://example.com'),
337
+ dataValue = reactive(42);
338
+
339
+ let view = html`
340
+ <div class="attributes">
341
+ <button
342
+ class=${classes}
343
+ disabled=${isDisabled}
344
+ data-value=${dataValue}
345
+ style=${styles}
346
+ >
347
+ Dynamic Button
348
+ </button>
349
+
350
+ <a href=${href} target="_blank">Dynamic Link</a>
351
+
352
+ <input
353
+ type="text"
354
+ class=${() => isDisabled ? 'disabled-input' : 'active-input'}
355
+ placeholder=${() => `Value: ${dataValue}`}
356
+ />
357
+ </div>
358
+ `;
359
+
360
+ // Update attributes
361
+ isDisabled = true;
362
+ classes = 'secondary active';
363
+ styles = 'color: blue; font-weight: bold';
364
+ href = 'https://updated.com';
365
+ dataValue = 100;
366
+
367
+ return { classes, dataValue, href, isDisabled, styles, view };
368
+ }
369
+
370
+
371
+ // ============================================================================
372
+ // Test 9: Mixed Reactive Types in Single Template
373
+ // ============================================================================
374
+
375
+ function testMixedReactiveTypes() {
376
+ // All types in one component
377
+ let primitive = reactive(0),
378
+ computed = reactive(() => primitive * 2),
379
+ array = reactive([1, 2, 3] as number[]),
380
+ object = reactive({
381
+ count: 0,
382
+ double: () => object.count * 2,
383
+ name: 'Test'
384
+ });
385
+
386
+ let view = html`
387
+ <div class="mixed">
388
+ <section>
389
+ <h3>Primitive: ${primitive}</h3>
390
+ <h3>Computed: ${computed}</h3>
391
+ </section>
392
+
393
+ <section>
394
+ <h3>Object Name: ${object.name}</h3>
395
+ <h3>Object Count: ${object.count}</h3>
396
+ <h3>Object Double: ${object.double}</h3>
397
+ </section>
398
+
399
+ <section>
400
+ <h3>Array Length: ${() => array.length}</h3>
401
+ ${html.reactive(array, (n) => html`<span>${n}</span>`)}
402
+ </section>
403
+
404
+ <section>
405
+ <button onclick=${() => {
406
+ primitive++;
407
+ object.count++;
408
+ array.push(array.length + 1);
409
+ }}>
410
+ Increment All
411
+ </button>
412
+ </section>
413
+ </div>
414
+ `;
415
+
416
+ // Trigger all types
417
+ primitive = 5;
418
+ object.name = 'Updated';
419
+ object.count = 10;
420
+ array.push(4, 5, 6);
421
+
422
+ return { array, computed, object, primitive, view };
423
+ }
424
+
425
+
426
+ // ============================================================================
427
+ // Test 10: Typed Reactive with Generics
428
+ // ============================================================================
429
+
430
+ interface Todo {
431
+ completed: boolean;
432
+ id: number;
433
+ text: string;
434
+ }
435
+
436
+ interface AppState {
437
+ addTodo: (text: string) => void;
438
+ completedCount: () => number;
439
+ filter: 'all' | 'active' | 'completed';
440
+ filteredTodos: () => Todo[];
441
+ nextId: number;
442
+ todos: Todo[];
443
+ toggleTodo: (id: number) => void;
444
+ }
445
+
446
+ function testTypedReactive() {
447
+ let state = reactive<AppState>({
448
+ addTodo: (text: string) => {
449
+ state.todos.push({
450
+ completed: false,
451
+ id: state.nextId++,
452
+ text
453
+ });
454
+ },
455
+ completedCount: () => state.todos.filter(t => t.completed).length,
456
+ filter: 'all',
457
+ filteredTodos: () => {
458
+ if (state.filter === 'active') {
459
+ return state.todos.filter(t => !t.completed);
460
+ }
461
+
462
+ if (state.filter === 'completed') {
463
+ return state.todos.filter(t => t.completed);
464
+ }
465
+
466
+ return state.todos;
467
+ },
468
+ nextId: 1,
469
+ todos: [],
470
+ toggleTodo: (id: number) => {
471
+ let todo = state.todos.find(t => t.id === id);
472
+
473
+ if (todo) {
474
+ todo.completed = !todo.completed;
475
+ }
476
+ }
477
+ });
478
+
479
+ let view = html`
480
+ <div class="todo-app">
481
+ <header>
482
+ <h1>Todos (${state.completedCount} completed)</h1>
483
+ <nav>
484
+ <button
485
+ class=${() => state.filter === 'all' ? 'active' : ''}
486
+ onclick=${() => { state.filter = 'all'; }}
487
+ >All</button>
488
+ <button
489
+ class=${() => state.filter === 'active' ? 'active' : ''}
490
+ onclick=${() => { state.filter = 'active'; }}
491
+ >Active</button>
492
+ <button
493
+ class=${() => state.filter === 'completed' ? 'active' : ''}
494
+ onclick=${() => { state.filter = 'completed'; }}
495
+ >Completed</button>
496
+ </nav>
497
+ </header>
498
+
499
+ <main>
500
+ ${() => state.filteredTodos().map(todo => html`
501
+ <div class="todo ${todo.completed ? 'completed' : ''}">
502
+ <input
503
+ type="checkbox"
504
+ checked=${todo.completed}
505
+ onchange=${() => state.toggleTodo(todo.id)}
506
+ />
507
+ <span>${todo.text}</span>
508
+ </div>
509
+ `)}
510
+ </main>
511
+ </div>
512
+ `;
513
+
514
+ // Add some todos
515
+ state.addTodo('Learn TypeScript');
516
+ state.addTodo('Build app');
517
+ state.addTodo('Write tests');
518
+ state.toggleTodo(1);
519
+
520
+ return { state, view };
521
+ }
522
+
523
+
524
+ // ============================================================================
525
+ // Test 11: Deeply Nested Templates with Reactivity
526
+ // ============================================================================
527
+
528
+ function testDeeplyNested() {
529
+ let level1 = reactive({
530
+ items: reactive([
531
+ {
532
+ children: reactive([
533
+ { name: 'Leaf 1', value: reactive(1) },
534
+ { name: 'Leaf 2', value: reactive(2) }
535
+ ] as { name: string; value: number }[]),
536
+ name: 'Child 1'
537
+ },
538
+ {
539
+ children: reactive([
540
+ { name: 'Leaf 3', value: reactive(3) }
541
+ ] as { name: string; value: number }[]),
542
+ name: 'Child 2'
543
+ }
544
+ ] as { children: { name: string; value: number }[]; name: string }[]),
545
+ name: 'Root'
546
+ });
547
+
548
+ let view = html`
549
+ <div class="tree">
550
+ <h1>${level1.name}</h1>
551
+ ${html.reactive(level1.items, (item) => html`
552
+ <div class="branch">
553
+ <h2>${item.name}</h2>
554
+ ${html.reactive(item.children, (child) => html`
555
+ <div class="leaf">
556
+ <span>${child.name}: ${child.value}</span>
557
+ <button onclick=${() => child.value++}>+</button>
558
+ </div>
559
+ `)}
560
+ </div>
561
+ `)}
562
+ </div>
563
+ `;
564
+
565
+ // Mutate nested values
566
+ level1.items[0].children[0].value++;
567
+ level1.items.push({
568
+ children: reactive([{ name: 'Leaf 4', value: reactive(4) }]),
569
+ name: 'Child 3'
570
+ });
571
+
572
+ return { level1, view };
573
+ }
574
+
575
+
576
+ // ============================================================================
577
+ // Test 12: Static vs Dynamic Content
578
+ // ============================================================================
579
+
580
+ function testStaticVsDynamic() {
581
+ let dynamicText = reactive('Dynamic'),
582
+ dynamicNum = reactive(42),
583
+ dynamicBool = reactive(true);
584
+
585
+ // Mix of static and dynamic content
586
+ let view = html`
587
+ <div class="static-dynamic">
588
+ <p>Static text here</p>
589
+ <p>${dynamicText} text here</p>
590
+
591
+ <span>Static number: 100</span>
592
+ <span>Dynamic number: ${dynamicNum}</span>
593
+
594
+ <div class="static-class">Static class</div>
595
+ <div class="${() => dynamicBool ? 'dynamic-true' : 'dynamic-false'}">Dynamic class</div>
596
+
597
+ <a href="https://static.com">Static link</a>
598
+ <a href=${() => dynamicBool ? 'https://true.com' : 'https://false.com'}>Dynamic link</a>
599
+
600
+ <input type="text" value="static" />
601
+ <input type="text" value=${dynamicText} />
602
+ </div>
603
+ `;
604
+
605
+ dynamicText = 'Updated';
606
+ dynamicNum = 100;
607
+ dynamicBool = false;
608
+
609
+ return { dynamicBool, dynamicNum, dynamicText, view };
610
+ }
611
+
612
+
613
+ // ============================================================================
614
+ // Run All Tests
615
+ // ============================================================================
616
+
617
+ export const tests = {
618
+ testAttributeBindings,
619
+ testComplexNested,
620
+ testComputedValues,
621
+ testConditionalRendering,
622
+ testDeeplyNested,
623
+ testEventHandlers,
624
+ testMixedReactiveTypes,
625
+ testPrimitiveSignals,
626
+ testReactiveArrays,
627
+ testReactiveObjects,
628
+ testStaticVsDynamic,
629
+ testTypedReactive
630
+ };
631
+
632
+ // Execute all tests to verify compilation
633
+ export const results = Object.entries(tests).map(([name, fn]) => {
634
+ try {
635
+ let result = fn();
636
+
637
+ console.log(`✓ ${name} passed`);
638
+
639
+ return { name, result, status: 'passed' };
640
+ }
641
+ catch (error) {
642
+ console.error(`✗ ${name} failed:`, error);
643
+
644
+ return { error, name, status: 'failed' };
645
+ }
646
+ });
647
+
648
+ console.log(`\nTests completed: ${results.filter(r => r.status === 'passed').length}/${results.length} passed`);
@@ -0,0 +1,23 @@
1
+ import path from 'path';
2
+ import { defineConfig } from 'vite';
3
+ import compiler from '@esportsplus/frontend/compiler/vite';
4
+
5
+
6
+ export default defineConfig({
7
+ build: {
8
+ lib: {
9
+ entry: path.resolve(__dirname, 'index.ts'),
10
+ fileName: 'test',
11
+ formats: ['es']
12
+ },
13
+ minify: false,
14
+ outDir: path.resolve(__dirname, 'dist'),
15
+ rollupOptions: {
16
+ external: []
17
+ },
18
+ sourcemap: true
19
+ },
20
+ plugins: [
21
+ compiler({ root: path.resolve(__dirname, '..') })
22
+ ]
23
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "@esportsplus/typescript/tsconfig.package.json",
3
+ "compilerOptions": {
4
+ "plugins": [
5
+ { "transform": "@esportsplus/reactivity/compiler/tsc" }
6
+ ]
7
+ }
8
+ }