elit 3.3.3 → 3.3.5

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 (145) hide show
  1. package/dist/build.d.mts +1 -1
  2. package/dist/build.js +1 -0
  3. package/dist/build.js.map +1 -0
  4. package/dist/build.mjs +1 -0
  5. package/dist/build.mjs.map +1 -0
  6. package/dist/chokidar.js +1 -0
  7. package/dist/chokidar.js.map +1 -0
  8. package/dist/chokidar.mjs +1 -0
  9. package/dist/chokidar.mjs.map +1 -0
  10. package/dist/cli.js +4720 -37
  11. package/dist/config.d.mts +3 -1
  12. package/dist/config.d.ts +3 -1
  13. package/dist/config.d.ts.map +1 -1
  14. package/dist/config.js +1 -0
  15. package/dist/config.js.map +1 -0
  16. package/dist/config.mjs +1 -0
  17. package/dist/config.mjs.map +1 -0
  18. package/dist/coverage.d.mts +85 -0
  19. package/dist/coverage.d.ts +76 -0
  20. package/dist/coverage.d.ts.map +1 -0
  21. package/dist/coverage.js +1549 -0
  22. package/dist/coverage.js.map +1 -0
  23. package/dist/coverage.mjs +1520 -0
  24. package/dist/coverage.mjs.map +1 -0
  25. package/dist/database.d.mts +31 -6
  26. package/dist/database.d.ts +31 -6
  27. package/dist/database.d.ts.map +1 -1
  28. package/dist/database.js +60 -33
  29. package/dist/database.js.map +1 -0
  30. package/dist/database.mjs +60 -33
  31. package/dist/database.mjs.map +1 -0
  32. package/dist/dom.js +1 -0
  33. package/dist/dom.js.map +1 -0
  34. package/dist/dom.mjs +1 -0
  35. package/dist/dom.mjs.map +1 -0
  36. package/dist/el.js +1 -0
  37. package/dist/el.js.map +1 -0
  38. package/dist/el.mjs +1 -0
  39. package/dist/el.mjs.map +1 -0
  40. package/dist/fs.js +1 -0
  41. package/dist/fs.js.map +1 -0
  42. package/dist/fs.mjs +1 -0
  43. package/dist/fs.mjs.map +1 -0
  44. package/dist/hmr.js +1 -0
  45. package/dist/hmr.js.map +1 -0
  46. package/dist/hmr.mjs +1 -0
  47. package/dist/hmr.mjs.map +1 -0
  48. package/dist/http.js +1 -0
  49. package/dist/http.js.map +1 -0
  50. package/dist/http.mjs +1 -0
  51. package/dist/http.mjs.map +1 -0
  52. package/dist/https.d.mts +1 -1
  53. package/dist/https.js +1 -0
  54. package/dist/https.js.map +1 -0
  55. package/dist/https.mjs +1 -0
  56. package/dist/https.mjs.map +1 -0
  57. package/dist/index.d.mts +1 -1
  58. package/dist/index.js +1 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/index.mjs +1 -0
  61. package/dist/index.mjs.map +1 -0
  62. package/dist/mime-types.js +1 -0
  63. package/dist/mime-types.js.map +1 -0
  64. package/dist/mime-types.mjs +1 -0
  65. package/dist/mime-types.mjs.map +1 -0
  66. package/dist/path.js +1 -0
  67. package/dist/path.js.map +1 -0
  68. package/dist/path.mjs +1 -0
  69. package/dist/path.mjs.map +1 -0
  70. package/dist/router.js +1 -0
  71. package/dist/router.js.map +1 -0
  72. package/dist/router.mjs +1 -0
  73. package/dist/router.mjs.map +1 -0
  74. package/dist/runtime.js +1 -0
  75. package/dist/runtime.js.map +1 -0
  76. package/dist/runtime.mjs +1 -0
  77. package/dist/runtime.mjs.map +1 -0
  78. package/dist/{server-Cz3z-5ls.d.mts → server-BFTzgJpO.d.mts} +62 -1
  79. package/dist/{server-BG2CaVMh.d.ts → server-CIXtexNS.d.ts} +62 -1
  80. package/dist/server.d.mts +1 -1
  81. package/dist/server.d.ts +9 -0
  82. package/dist/server.d.ts.map +1 -1
  83. package/dist/server.js +45 -3
  84. package/dist/server.js.map +1 -0
  85. package/dist/server.mjs +45 -3
  86. package/dist/server.mjs.map +1 -0
  87. package/dist/state.d.mts +1 -1
  88. package/dist/state.js +1 -0
  89. package/dist/state.js.map +1 -0
  90. package/dist/state.mjs +1 -0
  91. package/dist/state.mjs.map +1 -0
  92. package/dist/style.js +1 -0
  93. package/dist/style.js.map +1 -0
  94. package/dist/style.mjs +1 -0
  95. package/dist/style.mjs.map +1 -0
  96. package/dist/test-globals.d.ts +184 -0
  97. package/dist/test-reporter.d.mts +77 -0
  98. package/dist/test-reporter.d.ts +73 -0
  99. package/dist/test-reporter.d.ts.map +1 -0
  100. package/dist/test-reporter.js +726 -0
  101. package/dist/test-reporter.js.map +1 -0
  102. package/dist/test-reporter.mjs +696 -0
  103. package/dist/test-reporter.mjs.map +1 -0
  104. package/dist/test-runtime.d.mts +122 -0
  105. package/dist/test-runtime.d.ts +120 -0
  106. package/dist/test-runtime.d.ts.map +1 -0
  107. package/dist/test-runtime.js +1292 -0
  108. package/dist/test-runtime.js.map +1 -0
  109. package/dist/test-runtime.mjs +1269 -0
  110. package/dist/test-runtime.mjs.map +1 -0
  111. package/dist/test.d.mts +39 -0
  112. package/dist/test.d.ts +38 -0
  113. package/dist/test.d.ts.map +1 -0
  114. package/dist/test.js +4966 -0
  115. package/dist/test.js.map +1 -0
  116. package/dist/test.mjs +4944 -0
  117. package/dist/test.mjs.map +1 -0
  118. package/dist/types.d.mts +62 -1
  119. package/dist/types.d.ts +52 -0
  120. package/dist/types.d.ts.map +1 -1
  121. package/dist/types.js +1 -0
  122. package/dist/types.js.map +1 -0
  123. package/dist/types.mjs +1 -0
  124. package/dist/types.mjs.map +1 -0
  125. package/dist/ws.d.ts.map +1 -1
  126. package/dist/ws.js +24 -2
  127. package/dist/ws.js.map +1 -0
  128. package/dist/ws.mjs +24 -2
  129. package/dist/ws.mjs.map +1 -0
  130. package/dist/wss.js +24 -2
  131. package/dist/wss.js.map +1 -0
  132. package/dist/wss.mjs +24 -2
  133. package/dist/wss.mjs.map +1 -0
  134. package/package.json +37 -5
  135. package/src/cli.ts +165 -1
  136. package/src/config.ts +3 -1
  137. package/src/coverage.ts +1479 -0
  138. package/src/database.ts +71 -35
  139. package/src/server.ts +25 -1
  140. package/src/test-globals.d.ts +184 -0
  141. package/src/test-reporter.ts +609 -0
  142. package/src/test-runtime.ts +1359 -0
  143. package/src/test.ts +368 -0
  144. package/src/types.ts +59 -0
  145. package/src/ws.ts +32 -2
package/src/database.ts CHANGED
@@ -335,20 +335,16 @@ class VM {
335
335
  }
336
336
  }
337
337
 
338
- function create(dbName: string, code: string | Function): void {
339
- const DIR = "databases";
340
- const basePath = path.join(process.cwd());
341
- const baseDir: string = path.resolve(basePath, DIR); // โฟลเดอร์ที่อนุญาต
342
- const dbPath = path.join(baseDir, `${dbName}.ts`);
338
+ function create(dbName: string, code: string | Function, options?: VMOptions): void {
339
+ const DIR = options?.dir || path.join(process.cwd(), 'databases');
340
+ const dbPath = path.join(DIR, `${dbName}.ts`);
343
341
  // Prepare the export line
344
342
  fs.appendFileSync(dbPath, code.toString(), 'utf8');
345
343
  }
346
344
 
347
- function read(dbName: string): string {
348
- const DIR = "databases";
349
- const basePath = path.join(process.cwd());
350
- const baseDir: string = path.resolve(basePath, DIR);
351
- const dbPath = path.join(baseDir, `${dbName}.ts`);
345
+ function read(dbName: string, options?: VMOptions): string {
346
+ const DIR = options?.dir || path.join(process.cwd(), 'databases');
347
+ const dbPath = path.join(DIR, `${dbName}.ts`);
352
348
 
353
349
  if (!fs.existsSync(dbPath)) {
354
350
  throw new Error(`Database '${dbName}' not found`);
@@ -357,11 +353,9 @@ function read(dbName: string): string {
357
353
  return fs.readFileSync(dbPath, 'utf8');
358
354
  }
359
355
 
360
- function remove(dbName: string, fnName: string) {
361
- const DIR = "databases";
362
- const basePath = path.join(process.cwd());
363
- const baseDir: string = path.resolve(basePath, DIR); // โฟลเดอร์ที่อนุญาต
364
- const dbPath = path.join(baseDir, `${dbName}.ts`);
356
+ function remove(dbName: string, fnName: string, options?: VMOptions) {
357
+ const DIR = options?.dir || path.join(process.cwd(), 'databases');
358
+ const dbPath = path.join(DIR, `${dbName}.ts`);
365
359
  if (!fs.existsSync(dbPath)) return false;
366
360
 
367
361
  // if no functionName provided -> remove the whole file (after backup)
@@ -454,12 +448,10 @@ function remove(dbName: string, fnName: string) {
454
448
  return `Removed ${fnName} from database ${dbName}.`;
455
449
  }
456
450
 
457
- function rename(oldName: string, newName: string): string {
458
- const DIR = "databases";
459
- const basePath = path.join(process.cwd());
460
- const baseDir: string = path.resolve(basePath, DIR); // โฟลเดอร์ที่อนุญาต
461
- const oldPath = path.join(baseDir, `${oldName}.ts`);
462
- const newPath = path.join(baseDir, `${newName}.ts`);
451
+ function rename(oldName: string, newName: string, options?: VMOptions): string {
452
+ const DIR = options?.dir || path.join(process.cwd(), 'databases');
453
+ const oldPath = path.join(DIR, `${oldName}.ts`);
454
+ const newPath = path.join(DIR, `${newName}.ts`);
463
455
 
464
456
  // Check if the source file exists
465
457
  if (!fs.existsSync(oldPath)) {
@@ -480,22 +472,18 @@ function rename(oldName: string, newName: string): string {
480
472
  }
481
473
  }
482
474
 
483
- function save(dbName: string, code: string | Function | any): void {
484
- const DIR = "databases";
485
- const basePath = path.join(process.cwd());
486
- const baseDir: string = path.resolve(basePath, DIR); // โฟลเดอร์ที่อนุญาต
487
- const dbPath = path.join(baseDir, `${dbName}.ts`);
475
+ function save(dbName: string, code: string | Function | any, options?: VMOptions): void {
476
+ const DIR = options?.dir || path.join(process.cwd(), 'databases');
477
+ const dbPath = path.join(DIR, `${dbName}.ts`);
488
478
 
489
479
  let fileContent = typeof code === 'function' ? code.toString() : code;
490
480
 
491
481
  fs.writeFileSync(dbPath, fileContent, 'utf8');
492
482
  }
493
483
 
494
- function update(dbName: string, fnName: string, code: string | Function) {
495
- const DIR = "databases";
496
- const basePath = path.join(process.cwd());
497
- const baseDir: string = path.resolve(basePath, DIR); // โฟลเดอร์ที่อนุญาต
498
- const dbPath = path.join(baseDir, `${dbName}.ts`);
484
+ function update(dbName: string, fnName: string, code: string | Function, options?: VMOptions) {
485
+ const DIR = options?.dir || path.join(process.cwd(), 'databases');
486
+ const dbPath = path.join(DIR, `${dbName}.ts`);
499
487
 
500
488
  let src;
501
489
 
@@ -710,11 +698,15 @@ async function SystemModuleResolver() {
710
698
 
711
699
  export class Database {
712
700
  private vm: VM;
701
+ private options: VMOptions;
702
+
713
703
  constructor(options?: VMOptions) {
714
- this.vm = new VM({
715
- language: 'ts', registerModules: {},
704
+ this.options = {
705
+ language: 'ts',
706
+ registerModules: {},
716
707
  ...options
717
- });
708
+ };
709
+ this.vm = new VM(this.options);
718
710
  }
719
711
 
720
712
  register(context: { [key: string]: any }) {
@@ -724,9 +716,53 @@ export class Database {
724
716
  async execute(code: string) {
725
717
  return await this.vm.run(code);
726
718
  }
719
+
720
+ // ===== Database Helper Methods =====
721
+
722
+ /**
723
+ * Create a new database file with the given code
724
+ */
725
+ create(dbName: string, code: string | Function): void {
726
+ return create(dbName, code, this.options);
727
+ }
728
+
729
+ /**
730
+ * Read the contents of a database file
731
+ */
732
+ read(dbName: string): string {
733
+ return read(dbName, this.options);
734
+ }
735
+
736
+ /**
737
+ * Remove a function or the entire database file
738
+ */
739
+ remove(dbName: string, fnName?: string): string | boolean {
740
+ return remove(dbName, fnName || "", this.options);
741
+ }
742
+
743
+ /**
744
+ * Rename a database file
745
+ */
746
+ rename(oldName: string, newName: string): string {
747
+ return rename(oldName, newName, this.options);
748
+ }
749
+
750
+ /**
751
+ * Save code to a database file (overwrites existing content)
752
+ */
753
+ save(dbName: string, code: string | Function | any): void {
754
+ return save(dbName, code, this.options);
755
+ }
756
+
757
+ /**
758
+ * Update a function in a database file
759
+ */
760
+ update(dbName: string, fnName: string, code: string | Function): string {
761
+ return update(dbName, fnName, code, this.options);
762
+ }
727
763
  }
728
764
 
729
- // Export helper functions
765
+ // Export Database class and keep helper functions for backward compatibility
730
766
  export { create, read, remove, rename, save, update };
731
767
 
732
768
 
package/src/server.ts CHANGED
@@ -174,6 +174,18 @@ export class ServerRouter {
174
174
  return query;
175
175
  }
176
176
 
177
+ /**
178
+ * List all registered routes for debugging
179
+ */
180
+ listRoutes(): Array<{ method: string; pattern: string; paramNames: string[]; handler: string }> {
181
+ return this.routes.map(route => ({
182
+ method: route.method,
183
+ pattern: route.pattern.source,
184
+ paramNames: route.paramNames,
185
+ handler: route.handler.name || '(anonymous)'
186
+ }));
187
+ }
188
+
177
189
  private async parseBody(req: IncomingMessage): Promise<any> {
178
190
  // Bun compatibility: Check if req has text() method (Bun Request)
179
191
  if (typeof (req as any).text === 'function') {
@@ -1757,7 +1769,19 @@ export default css;
1757
1769
  watcher.on('change', (path: string) => {
1758
1770
  if (config.logging) console.log(`[HMR] File changed: ${path}`);
1759
1771
  const message = JSON.stringify({ type: 'update', path, timestamp: Date.now() } as HMRMessage);
1760
- wsClients.forEach(client => client.readyState === ReadyState.OPEN && client.send(message));
1772
+ // Broadcast to all open clients with error handling
1773
+ wsClients.forEach(client => {
1774
+ if (client.readyState === ReadyState.OPEN) {
1775
+ client.send(message, {}, (err?: Error) => {
1776
+ // Silently ignore connection errors during HMR
1777
+ const code = (err as any)?.code;
1778
+ if (code === 'ECONNABORTED' || code === 'ECONNRESET' || code === 'EPIPE' || code === 'WS_NOT_OPEN') {
1779
+ // Client disconnected - will be removed from clients set by close event
1780
+ return;
1781
+ }
1782
+ });
1783
+ }
1784
+ });
1761
1785
  });
1762
1786
 
1763
1787
  watcher.on('add', (path: string) => config.logging && console.log(`[HMR] File added: ${path}`));
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Test Global Type Definitions
3
+ *
4
+ * Provides global type declarations for test globals.
5
+ *
6
+ * To use these types in your test files, add this to your tsconfig.json:
7
+ * {
8
+ * "compilerOptions": {
9
+ * "types": ["elit/test-globals"]
10
+ * }
11
+ * }
12
+ *
13
+ * Or add a triple-slash directive to your test file:
14
+ * /// <reference types="elit/test-globals" />
15
+ */
16
+
17
+ // ============================================================================
18
+ // Global Functions with Modifiers
19
+ // ============================================================================
20
+
21
+ declare function describe(name: string, fn: () => void): void;
22
+ declare namespace describe {
23
+ function skip(name: string, fn: () => void): void;
24
+ function only(name: string, fn: () => void): void;
25
+ }
26
+
27
+ declare function it(name: string, fn: () => void | Promise<void>): void;
28
+ declare namespace it {
29
+ function skip(name: string, fn: () => void | Promise<void>): void;
30
+ function only(name: string, fn: () => void | Promise<void>): void;
31
+ function todo(name: string, fn?: () => void | Promise<void>): void;
32
+ }
33
+
34
+ declare function test(name: string, fn: () => void | Promise<void>): void;
35
+ declare namespace test {
36
+ function skip(name: string, fn: () => void | Promise<void>): void;
37
+ function only(name: string, fn: () => void | Promise<void>): void;
38
+ function todo(name: string, fn?: () => void | Promise<void>): void;
39
+ }
40
+
41
+ // ============================================================================
42
+ // Expect Interface
43
+ // ============================================================================
44
+
45
+ interface TestMatchers<T> {
46
+ // Equality
47
+ toBe(value: T): void;
48
+ toEqual(value: T): void;
49
+ toStrictEqual(value: T): void;
50
+
51
+ // Truthiness
52
+ toBeTruthy(): void;
53
+ toBeFalsy(): void;
54
+
55
+ // Nullability
56
+ toBeNull(): void;
57
+ toBeUndefined(): void;
58
+ toBeDefined(): void;
59
+ toBeNaN(): void;
60
+
61
+ // Numbers
62
+ toBeGreaterThan(value: number): void;
63
+ toBeGreaterThanOrEqual(value: number): void;
64
+ toBeLessThan(value: number): void;
65
+ toBeLessThanOrEqual(value: number): void;
66
+ toBeCloseTo(value: number, precision?: number): void;
67
+ toBeFinite(): void;
68
+
69
+ // Strings
70
+ toMatch(pattern: RegExp | string): void;
71
+ toContain(value: any): void;
72
+
73
+ // Arrays
74
+ toHaveLength(length: number): void;
75
+ toContainEqual(item: any): void;
76
+
77
+ // Objects
78
+ toHaveProperty(path: string | (string | number)[], value?: any): void;
79
+ toMatchObject(properties: Record<string, any>): void;
80
+ toBeInstanceOf(classType: any): void;
81
+
82
+ // Functions
83
+ toThrow(error?: RegExp | string | Error | any): void;
84
+ toHaveReturnedWith(value: any): void;
85
+ toHaveReturnedTimes(times: number): void;
86
+ toHaveLastReturnedWith(value: any): void;
87
+
88
+ // Modifiers
89
+ not: TestMatchers<T>;
90
+ resolves: TestMatchers<T>;
91
+ rejects: TestMatchers<T>;
92
+ }
93
+
94
+ interface ExpectStatic {
95
+ <T = any>(actual: T): TestMatchers<T>;
96
+ extends(matchers: Record<string, any>): void;
97
+ any(constructor: any): any;
98
+ anything(): any;
99
+ arrayContaining(arr: any[]): any;
100
+ objectContaining(obj: Record<string, any>): any;
101
+ stringContaining(str: string): any;
102
+ stringMatching(str: RegExp | string): any;
103
+ not: {
104
+ toBe(value: any): void;
105
+ toEqual(value: any): void;
106
+ toMatchObject(properties: Record<string, any>): void;
107
+ toContain(value: any): void;
108
+ toThrow(error?: RegExp | string | Error): void;
109
+ };
110
+ addSnapshotSerializer(serializer: any): void;
111
+ assertions(expected: number): void;
112
+ hasAssertions(): void;
113
+ }
114
+
115
+ declare const expect: ExpectStatic;
116
+
117
+ // ============================================================================
118
+ // Mock Functions (vi)
119
+ // ============================================================================
120
+
121
+ interface MockFunction<T extends (...args: any[]) => any> {
122
+ (...args: Parameters<T>): ReturnType<T>;
123
+ mockImplementation(fn: T): this;
124
+ mockImplementationOnce(fn: T): this;
125
+ mockReturnThis(): this;
126
+ mockReturnValue(value: ReturnType<T>): this;
127
+ mockReturnValueOnce(value: ReturnType<T>): this;
128
+ mockResolvedValue(value: ReturnType<T> extends Promise<any> ? never : Awaited<ReturnType<T>>): this;
129
+ mockResolvedValueOnce(value: ReturnType<T> extends Promise<any> ? never : Awaited<ReturnType<T>>): this;
130
+ mockRejectedValue(value: any): this;
131
+ mockRejectedValueOnce(value: any): this;
132
+ get mock(): {
133
+ calls: Parameters<T>[];
134
+ instances: any[];
135
+ contexts: any[];
136
+ returnValues: ReturnType<T>[];
137
+ lastCall?: Parameters<T>;
138
+ };
139
+ get calls(): Parameters<T>[];
140
+ get instances(): any[];
141
+ get invocationCallOrder(): number[];
142
+ get results(): Array<{ type: 'return' | 'throw' | 'incomplete'; value: any }>;
143
+ }
144
+
145
+ interface SpyInstance {
146
+ mockRestore(): void;
147
+ mockReturnValue(value: any): this;
148
+ mockResolvedValue(value: any): this;
149
+ mockRejectedValue(value: any): this;
150
+ mockImplementation(fn: (...args: any[]) => any): this;
151
+ get calls(): any[][];
152
+ get callCount(): number;
153
+ }
154
+
155
+ interface Elitest {
156
+ fn<T extends (...args: any[]) => any>(implementation?: T): MockFunction<T>;
157
+ spyOn(object: any, method: string): SpyInstance;
158
+ clearAllMocks(): void;
159
+ resetAllMocks(): void;
160
+ restoreAllMocks(): void;
161
+ doMock(modulePath: string, mockFactory?: () => any): void;
162
+ dontMock(modulePath: string): void;
163
+ unmock(modulePath: string): void;
164
+ useFakeTimers(): void;
165
+ useRealTimers(): void;
166
+ runAllTimers(): void;
167
+ runOnlyPendingTimers(): void;
168
+ advanceTimersByTime(msToRun: number): void;
169
+ advanceTimersToNextTimer(): number;
170
+ clearAllTimers(): void;
171
+ setSystemTime(time?: number | Date): void;
172
+ getTimerCount(): number;
173
+ }
174
+
175
+ declare const vi: Elitest;
176
+
177
+ // ============================================================================
178
+ // Hooks
179
+ // ============================================================================
180
+
181
+ declare function beforeAll(fn: () => void | Promise<void>, timeout?: number): void;
182
+ declare function afterAll(fn: () => void | Promise<void>, timeout?: number): void;
183
+ declare function beforeEach(fn: () => void | Promise<void>, timeout?: number): void;
184
+ declare function afterEach(fn: () => void | Promise<void>, timeout?: number): void;