elit 3.0.0 → 3.0.2

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 (87) hide show
  1. package/dist/build.d.ts +4 -12
  2. package/dist/build.d.ts.map +1 -0
  3. package/dist/chokidar.d.ts +7 -9
  4. package/dist/chokidar.d.ts.map +1 -0
  5. package/dist/cli.d.ts +6 -0
  6. package/dist/cli.d.ts.map +1 -0
  7. package/dist/cli.js +17 -4
  8. package/dist/config.d.ts +29 -0
  9. package/dist/config.d.ts.map +1 -0
  10. package/dist/dom.d.ts +7 -14
  11. package/dist/dom.d.ts.map +1 -0
  12. package/dist/el.d.ts +19 -191
  13. package/dist/el.d.ts.map +1 -0
  14. package/dist/fs.d.ts +35 -35
  15. package/dist/fs.d.ts.map +1 -0
  16. package/dist/hmr.d.ts +3 -3
  17. package/dist/hmr.d.ts.map +1 -0
  18. package/dist/http.d.ts +20 -22
  19. package/dist/http.d.ts.map +1 -0
  20. package/dist/https.d.ts +12 -15
  21. package/dist/https.d.ts.map +1 -0
  22. package/dist/index.d.ts +10 -629
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/mime-types.d.ts +9 -9
  25. package/dist/mime-types.d.ts.map +1 -0
  26. package/dist/path.d.ts +22 -19
  27. package/dist/path.d.ts.map +1 -0
  28. package/dist/router.d.ts +10 -17
  29. package/dist/router.d.ts.map +1 -0
  30. package/dist/runtime.d.ts +5 -6
  31. package/dist/runtime.d.ts.map +1 -0
  32. package/dist/server.d.ts +105 -7
  33. package/dist/server.d.ts.map +1 -0
  34. package/dist/server.js +14 -2
  35. package/dist/server.mjs +14 -2
  36. package/dist/state.d.ts +21 -27
  37. package/dist/state.d.ts.map +1 -0
  38. package/dist/style.d.ts +14 -55
  39. package/dist/style.d.ts.map +1 -0
  40. package/dist/types.d.ts +26 -240
  41. package/dist/types.d.ts.map +1 -0
  42. package/dist/ws.d.ts +14 -17
  43. package/dist/ws.d.ts.map +1 -0
  44. package/dist/wss.d.ts +16 -16
  45. package/dist/wss.d.ts.map +1 -0
  46. package/package.json +3 -2
  47. package/src/build.ts +337 -0
  48. package/src/chokidar.ts +401 -0
  49. package/src/cli.ts +638 -0
  50. package/src/config.ts +205 -0
  51. package/src/dom.ts +817 -0
  52. package/src/el.ts +164 -0
  53. package/src/fs.ts +727 -0
  54. package/src/hmr.ts +137 -0
  55. package/src/http.ts +775 -0
  56. package/src/https.ts +411 -0
  57. package/src/index.ts +14 -0
  58. package/src/mime-types.ts +222 -0
  59. package/src/path.ts +493 -0
  60. package/src/router.ts +237 -0
  61. package/src/runtime.ts +97 -0
  62. package/src/server.ts +1290 -0
  63. package/src/state.ts +468 -0
  64. package/src/style.ts +524 -0
  65. package/{dist/types-Du6kfwTm.d.ts → src/types.ts} +58 -141
  66. package/src/ws.ts +506 -0
  67. package/src/wss.ts +241 -0
  68. package/dist/build.d.mts +0 -20
  69. package/dist/chokidar.d.mts +0 -134
  70. package/dist/dom.d.mts +0 -87
  71. package/dist/el.d.mts +0 -207
  72. package/dist/fs.d.mts +0 -255
  73. package/dist/hmr.d.mts +0 -38
  74. package/dist/http.d.mts +0 -163
  75. package/dist/https.d.mts +0 -108
  76. package/dist/index.d.mts +0 -629
  77. package/dist/mime-types.d.mts +0 -48
  78. package/dist/path.d.mts +0 -163
  79. package/dist/router.d.mts +0 -47
  80. package/dist/runtime.d.mts +0 -97
  81. package/dist/server.d.mts +0 -7
  82. package/dist/state.d.mts +0 -111
  83. package/dist/style.d.mts +0 -159
  84. package/dist/types-C0nGi6MX.d.mts +0 -346
  85. package/dist/types.d.mts +0 -452
  86. package/dist/ws.d.mts +0 -195
  87. package/dist/wss.d.mts +0 -108
package/src/fs.ts ADDED
@@ -0,0 +1,727 @@
1
+ /**
2
+ * File System module with unified API across runtimes
3
+ * Compatible with Node.js 'fs' module API
4
+ * - Node.js: uses 'fs' module
5
+ * - Bun: uses Bun.file() and native APIs
6
+ * - Deno: uses Deno.readFile(), etc.
7
+ */
8
+
9
+ import { runtime, isNode, isBun, isDeno } from './runtime';
10
+
11
+ /**
12
+ * Helper: Check if runtime is Bun or Deno (eliminates duplication in Deno API calls)
13
+ */
14
+ const isBunOrDeno = isBun || isDeno;
15
+
16
+ /**
17
+ * Helper: Parse options from string or object (eliminates duplication in options parsing)
18
+ */
19
+ function parseOptions<T>(options: T | string | undefined, defaultValue: T): T {
20
+ return typeof options === 'string' ? { encoding: options } as T : options || defaultValue;
21
+ }
22
+
23
+ /**
24
+ * Helper: Decode content with optional encoding (eliminates duplication in read operations)
25
+ */
26
+ function decodeContent(content: ArrayBuffer | Uint8Array, encoding?: string | null): string | Buffer {
27
+ if (encoding) {
28
+ return new TextDecoder(encoding).decode(content);
29
+ }
30
+ return Buffer.from(content instanceof ArrayBuffer ? new Uint8Array(content) : content);
31
+ }
32
+
33
+ /**
34
+ * Helper: Convert data to Uint8Array (eliminates duplication in write operations)
35
+ */
36
+ function dataToUint8Array(data: string | Buffer | Uint8Array): Uint8Array {
37
+ if (typeof data === 'string') {
38
+ return new TextEncoder().encode(data);
39
+ }
40
+ if (data instanceof Buffer) {
41
+ return new Uint8Array(data);
42
+ }
43
+ return data;
44
+ }
45
+
46
+ /**
47
+ * Helper: Process directory entries (eliminates duplication in readdir operations)
48
+ */
49
+ function processDenoEntries(iterator: any, withFileTypes?: boolean): any[] {
50
+ const entries: any[] = [];
51
+ for (const entry of iterator) {
52
+ if (withFileTypes) {
53
+ entries.push(createDirentFromDenoEntry(entry));
54
+ } else {
55
+ entries.push(entry.name);
56
+ }
57
+ }
58
+ return entries;
59
+ }
60
+
61
+ /**
62
+ * Helper: Process directory entries async (eliminates duplication in async readdir)
63
+ */
64
+ async function processDenoEntriesAsync(iterator: any, withFileTypes?: boolean): Promise<any[]> {
65
+ const entries: any[] = [];
66
+ for await (const entry of iterator) {
67
+ if (withFileTypes) {
68
+ entries.push(createDirentFromDenoEntry(entry));
69
+ } else {
70
+ entries.push(entry.name);
71
+ }
72
+ }
73
+ return entries;
74
+ }
75
+
76
+ // Pre-load fs module for Node.js
77
+ let fs: any, fsPromises: any;
78
+ if (isNode) {
79
+ fs = require('fs');
80
+ fsPromises = require('fs/promises');
81
+ }
82
+
83
+ /**
84
+ * File encoding types
85
+ */
86
+ export type BufferEncoding =
87
+ | 'ascii' | 'utf8' | 'utf-8' | 'utf16le' | 'ucs2' | 'ucs-2'
88
+ | 'base64' | 'base64url' | 'latin1' | 'binary' | 'hex';
89
+
90
+ /**
91
+ * Read file options
92
+ */
93
+ export interface ReadFileOptions {
94
+ encoding?: BufferEncoding | null;
95
+ flag?: string;
96
+ signal?: AbortSignal;
97
+ }
98
+
99
+ /**
100
+ * Write file options
101
+ */
102
+ export interface WriteFileOptions {
103
+ encoding?: BufferEncoding | null;
104
+ mode?: number;
105
+ flag?: string;
106
+ signal?: AbortSignal;
107
+ }
108
+
109
+ /**
110
+ * Mkdir options
111
+ */
112
+ export interface MkdirOptions {
113
+ recursive?: boolean;
114
+ mode?: number;
115
+ }
116
+
117
+ /**
118
+ * Readdir options
119
+ */
120
+ export interface ReaddirOptions {
121
+ encoding?: BufferEncoding | null;
122
+ withFileTypes?: boolean;
123
+ recursive?: boolean;
124
+ }
125
+
126
+ /**
127
+ * File stats
128
+ */
129
+ export interface Stats {
130
+ isFile(): boolean;
131
+ isDirectory(): boolean;
132
+ isBlockDevice(): boolean;
133
+ isCharacterDevice(): boolean;
134
+ isSymbolicLink(): boolean;
135
+ isFIFO(): boolean;
136
+ isSocket(): boolean;
137
+ dev: number;
138
+ ino: number;
139
+ mode: number;
140
+ nlink: number;
141
+ uid: number;
142
+ gid: number;
143
+ rdev: number;
144
+ size: number;
145
+ blksize: number;
146
+ blocks: number;
147
+ atimeMs: number;
148
+ mtimeMs: number;
149
+ ctimeMs: number;
150
+ birthtimeMs: number;
151
+ atime: Date;
152
+ mtime: Date;
153
+ ctime: Date;
154
+ birthtime: Date;
155
+ }
156
+
157
+ /**
158
+ * Directory entry
159
+ */
160
+ export interface Dirent {
161
+ name: string;
162
+ isFile(): boolean;
163
+ isDirectory(): boolean;
164
+ isBlockDevice(): boolean;
165
+ isCharacterDevice(): boolean;
166
+ isSymbolicLink(): boolean;
167
+ isFIFO(): boolean;
168
+ isSocket(): boolean;
169
+ }
170
+
171
+ /**
172
+ * Read file (async)
173
+ */
174
+ export async function readFile(path: string, options?: ReadFileOptions | BufferEncoding): Promise<string | Buffer> {
175
+ const opts = parseOptions<ReadFileOptions>(options, {});
176
+
177
+ if (isNode) {
178
+ return fsPromises.readFile(path, opts);
179
+ } else if (isBun) {
180
+ // @ts-ignore
181
+ const file = Bun.file(path);
182
+ const content = await file.arrayBuffer();
183
+ return decodeContent(content, opts.encoding);
184
+ } else if (isDeno) {
185
+ // @ts-ignore
186
+ const content = await Deno.readFile(path);
187
+ return decodeContent(content, opts.encoding);
188
+ }
189
+
190
+ throw new Error('Unsupported runtime');
191
+ }
192
+
193
+ /**
194
+ * Read file (sync)
195
+ */
196
+ export function readFileSync(path: string, options?: ReadFileOptions | BufferEncoding): string | Buffer {
197
+ const opts = parseOptions<ReadFileOptions>(options, {});
198
+
199
+ if (isNode) {
200
+ return fs.readFileSync(path, opts);
201
+ } else if (isBun) {
202
+ // @ts-ignore
203
+ const file = Bun.file(path);
204
+ const content = file.arrayBuffer();
205
+ return decodeContent(content as ArrayBuffer, opts.encoding);
206
+ } else if (isDeno) {
207
+ // @ts-ignore
208
+ const content = Deno.readFileSync(path);
209
+ return decodeContent(content, opts.encoding);
210
+ }
211
+
212
+ throw new Error('Unsupported runtime');
213
+ }
214
+
215
+ /**
216
+ * Write file (async)
217
+ */
218
+ export async function writeFile(path: string, data: string | Buffer | Uint8Array, options?: WriteFileOptions | BufferEncoding): Promise<void> {
219
+ const opts = parseOptions<WriteFileOptions>(options, {});
220
+
221
+ if (isNode) {
222
+ return fsPromises.writeFile(path, data, opts);
223
+ } else if (isBun) {
224
+ // @ts-ignore
225
+ await Bun.write(path, data);
226
+ } else if (isDeno) {
227
+ // @ts-ignore
228
+ await Deno.writeFile(path, dataToUint8Array(data));
229
+ }
230
+ }
231
+
232
+ /**
233
+ * Write file (sync)
234
+ */
235
+ export function writeFileSync(path: string, data: string | Buffer | Uint8Array, options?: WriteFileOptions | BufferEncoding): void {
236
+ const opts = parseOptions<WriteFileOptions>(options, {});
237
+
238
+ if (isNode) {
239
+ fs.writeFileSync(path, data, opts);
240
+ } else if (isBun) {
241
+ // @ts-ignore
242
+ Bun.write(path, data);
243
+ } else if (isDeno) {
244
+ // @ts-ignore
245
+ Deno.writeFileSync(path, dataToUint8Array(data));
246
+ }
247
+ }
248
+
249
+ /**
250
+ * Append file (async)
251
+ */
252
+ export async function appendFile(path: string, data: string | Buffer, options?: WriteFileOptions | BufferEncoding): Promise<void> {
253
+ const opts = parseOptions<WriteFileOptions>(options, {});
254
+
255
+ if (isNode) {
256
+ return fsPromises.appendFile(path, data, opts);
257
+ } else {
258
+ if (await exists(path)) {
259
+ const existing = await readFile(path);
260
+ const combined = Buffer.isBuffer(existing)
261
+ ? Buffer.concat([existing, Buffer.isBuffer(data) ? data : Buffer.from(data)])
262
+ : existing + (Buffer.isBuffer(data) ? data.toString() : data);
263
+ await writeFile(path, combined, opts);
264
+ } else {
265
+ await writeFile(path, data, opts);
266
+ }
267
+ }
268
+ }
269
+
270
+ /**
271
+ * Append file (sync)
272
+ */
273
+ export function appendFileSync(path: string, data: string | Buffer, options?: WriteFileOptions | BufferEncoding): void {
274
+ const opts = parseOptions<WriteFileOptions>(options, {});
275
+
276
+ if (isNode) {
277
+ fs.appendFileSync(path, data, opts);
278
+ } else {
279
+ if (existsSync(path)) {
280
+ const existing = readFileSync(path);
281
+ const combined = Buffer.isBuffer(existing)
282
+ ? Buffer.concat([existing, Buffer.isBuffer(data) ? data : Buffer.from(data)])
283
+ : existing + (Buffer.isBuffer(data) ? data.toString() : data);
284
+ writeFileSync(path, combined, opts);
285
+ } else {
286
+ writeFileSync(path, data, opts);
287
+ }
288
+ }
289
+ }
290
+
291
+ /**
292
+ * Check if file/directory exists (async)
293
+ */
294
+ export async function exists(path: string): Promise<boolean> {
295
+ try {
296
+ await stat(path);
297
+ return true;
298
+ } catch {
299
+ return false;
300
+ }
301
+ }
302
+
303
+ /**
304
+ * Check if file/directory exists (sync)
305
+ */
306
+ export function existsSync(path: string): boolean {
307
+ try {
308
+ statSync(path);
309
+ return true;
310
+ } catch {
311
+ return false;
312
+ }
313
+ }
314
+
315
+ /**
316
+ * Get file stats (async)
317
+ */
318
+ export async function stat(path: string): Promise<Stats> {
319
+ if (isNode) {
320
+ return fsPromises.stat(path);
321
+ } else if (isBun) {
322
+ // @ts-ignore
323
+ const file = Bun.file(path);
324
+ const size = file.size;
325
+ const exists = await file.exists();
326
+
327
+ if (!exists) {
328
+ throw new Error(`ENOENT: no such file or directory, stat '${path}'`);
329
+ }
330
+
331
+ // Create a Stats-like object
332
+ return createStatsObject(path, size, false);
333
+ } else if (isDeno) {
334
+ // @ts-ignore
335
+ const info = await Deno.stat(path);
336
+ return createStatsFromDenoFileInfo(info);
337
+ }
338
+
339
+ throw new Error('Unsupported runtime');
340
+ }
341
+
342
+ /**
343
+ * Get file stats (sync)
344
+ */
345
+ export function statSync(path: string): Stats {
346
+ if (isNode) {
347
+ return fs.statSync(path);
348
+ } else if (isBun) {
349
+ // @ts-ignore
350
+ const file = Bun.file(path);
351
+ const size = file.size;
352
+
353
+ // Bun doesn't have sync exists check, so we try to read
354
+ try {
355
+ file.arrayBuffer();
356
+ } catch {
357
+ throw new Error(`ENOENT: no such file or directory, stat '${path}'`);
358
+ }
359
+
360
+ return createStatsObject(path, size, false);
361
+ } else if (isDeno) {
362
+ // @ts-ignore
363
+ const info = Deno.statSync(path);
364
+ return createStatsFromDenoFileInfo(info);
365
+ }
366
+
367
+ throw new Error('Unsupported runtime');
368
+ }
369
+
370
+ /**
371
+ * Create directory (async)
372
+ */
373
+ export async function mkdir(path: string, options?: MkdirOptions | number): Promise<void> {
374
+ const opts = typeof options === 'number' ? { mode: options } as MkdirOptions : options || {};
375
+
376
+ if (isNode) {
377
+ await fsPromises.mkdir(path, opts);
378
+ } else if (isBun) {
379
+ // @ts-ignore
380
+ await Deno.mkdir(path, { recursive: opts.recursive });
381
+ } else if (isDeno) {
382
+ // @ts-ignore
383
+ await Deno.mkdir(path, { recursive: opts.recursive });
384
+ }
385
+ }
386
+
387
+ /**
388
+ * Create directory (sync)
389
+ */
390
+ export function mkdirSync(path: string, options?: MkdirOptions | number): void {
391
+ const opts = typeof options === 'number' ? { mode: options } as MkdirOptions : options || {};
392
+
393
+ if (isNode) {
394
+ fs.mkdirSync(path, opts);
395
+ } else if (isBun) {
396
+ // @ts-ignore
397
+ Deno.mkdirSync(path, { recursive: opts.recursive });
398
+ } else if (isDeno) {
399
+ // @ts-ignore
400
+ Deno.mkdirSync(path, { recursive: opts.recursive });
401
+ }
402
+ }
403
+
404
+ /**
405
+ * Read directory (async)
406
+ */
407
+ export async function readdir(path: string, options?: ReaddirOptions | BufferEncoding): Promise<string[] | Dirent[]> {
408
+ const opts = parseOptions<ReaddirOptions>(options, {});
409
+
410
+ if (isNode) {
411
+ return fsPromises.readdir(path, opts);
412
+ } else if (isBunOrDeno) {
413
+ // @ts-ignore
414
+ return processDenoEntriesAsync(Deno.readDir(path), opts.withFileTypes);
415
+ }
416
+
417
+ throw new Error('Unsupported runtime');
418
+ }
419
+
420
+ /**
421
+ * Read directory (sync)
422
+ */
423
+ export function readdirSync(path: string, options?: ReaddirOptions | BufferEncoding): string[] | Dirent[] {
424
+ const opts = parseOptions<ReaddirOptions>(options, {});
425
+
426
+ if (isNode) {
427
+ return fs.readdirSync(path, opts);
428
+ } else if (isBunOrDeno) {
429
+ // @ts-ignore
430
+ return processDenoEntries(Deno.readDirSync(path), opts.withFileTypes);
431
+ }
432
+
433
+ throw new Error('Unsupported runtime');
434
+ }
435
+
436
+ /**
437
+ * Remove file (async)
438
+ */
439
+ export async function unlink(path: string): Promise<void> {
440
+ if (isNode) {
441
+ return fsPromises.unlink(path);
442
+ } else if (isBun) {
443
+ // @ts-ignore
444
+ await Deno.remove(path);
445
+ } else if (isDeno) {
446
+ // @ts-ignore
447
+ await Deno.remove(path);
448
+ }
449
+ }
450
+
451
+ /**
452
+ * Remove file (sync)
453
+ */
454
+ export function unlinkSync(path: string): void {
455
+ if (isNode) {
456
+ fs.unlinkSync(path);
457
+ } else if (isBun) {
458
+ // @ts-ignore
459
+ Deno.removeSync(path);
460
+ } else if (isDeno) {
461
+ // @ts-ignore
462
+ Deno.removeSync(path);
463
+ }
464
+ }
465
+
466
+ /**
467
+ * Remove directory (async)
468
+ */
469
+ export async function rmdir(path: string, options?: { recursive?: boolean }): Promise<void> {
470
+ if (isNode) {
471
+ return fsPromises.rmdir(path, options);
472
+ } else if (isBun) {
473
+ // @ts-ignore
474
+ await Deno.remove(path, { recursive: options?.recursive });
475
+ } else if (isDeno) {
476
+ // @ts-ignore
477
+ await Deno.remove(path, { recursive: options?.recursive });
478
+ }
479
+ }
480
+
481
+ /**
482
+ * Remove directory (sync)
483
+ */
484
+ export function rmdirSync(path: string, options?: { recursive?: boolean }): void {
485
+ if (isNode) {
486
+ fs.rmdirSync(path, options);
487
+ } else if (isBun) {
488
+ // @ts-ignore
489
+ Deno.removeSync(path, { recursive: options?.recursive });
490
+ } else if (isDeno) {
491
+ // @ts-ignore
492
+ Deno.removeSync(path, { recursive: options?.recursive });
493
+ }
494
+ }
495
+
496
+ /**
497
+ * Rename/move file (async)
498
+ */
499
+ export async function rename(oldPath: string, newPath: string): Promise<void> {
500
+ if (isNode) {
501
+ return fsPromises.rename(oldPath, newPath);
502
+ } else if (isBun) {
503
+ // @ts-ignore
504
+ await Deno.rename(oldPath, newPath);
505
+ } else if (isDeno) {
506
+ // @ts-ignore
507
+ await Deno.rename(oldPath, newPath);
508
+ }
509
+ }
510
+
511
+ /**
512
+ * Rename/move file (sync)
513
+ */
514
+ export function renameSync(oldPath: string, newPath: string): void {
515
+ if (isNode) {
516
+ fs.renameSync(oldPath, newPath);
517
+ } else if (isBun) {
518
+ // @ts-ignore
519
+ Deno.renameSync(oldPath, newPath);
520
+ } else if (isDeno) {
521
+ // @ts-ignore
522
+ Deno.renameSync(oldPath, newPath);
523
+ }
524
+ }
525
+
526
+ /**
527
+ * Copy file (async)
528
+ */
529
+ export async function copyFile(src: string, dest: string, flags?: number): Promise<void> {
530
+ if (isNode) {
531
+ return fsPromises.copyFile(src, dest, flags);
532
+ } else if (isBun) {
533
+ // @ts-ignore
534
+ await Deno.copyFile(src, dest);
535
+ } else if (isDeno) {
536
+ // @ts-ignore
537
+ await Deno.copyFile(src, dest);
538
+ }
539
+ }
540
+
541
+ /**
542
+ * Copy file (sync)
543
+ */
544
+ export function copyFileSync(src: string, dest: string, flags?: number): void {
545
+ if (isNode) {
546
+ fs.copyFileSync(src, dest, flags);
547
+ } else if (isBun) {
548
+ // @ts-ignore
549
+ Deno.copyFileSync(src, dest);
550
+ } else if (isDeno) {
551
+ // @ts-ignore
552
+ Deno.copyFileSync(src, dest);
553
+ }
554
+ }
555
+
556
+ /**
557
+ * Resolve pathname to absolute path (async)
558
+ */
559
+ export async function realpath(path: string, options?: { encoding?: BufferEncoding }): Promise<string> {
560
+ if (isNode) {
561
+ return fsPromises.realpath(path, options);
562
+ } else if (isBun) {
563
+ // Bun supports fs.promises.realpath
564
+ const fs = require('fs/promises');
565
+ return fs.realpath(path, options);
566
+ } else if (isDeno) {
567
+ // @ts-ignore
568
+ return await Deno.realPath(path);
569
+ }
570
+ return path;
571
+ }
572
+
573
+ /**
574
+ * Resolve pathname to absolute path (sync)
575
+ */
576
+ export function realpathSync(path: string, options?: { encoding?: BufferEncoding }): string {
577
+ if (isNode) {
578
+ return fs.realpathSync(path, options);
579
+ } else if (isBun) {
580
+ // Bun supports fs.realpathSync
581
+ const fs = require('fs');
582
+ return fs.realpathSync(path, options);
583
+ } else if (isDeno) {
584
+ // @ts-ignore
585
+ return Deno.realPathSync(path);
586
+ }
587
+ return path;
588
+ }
589
+
590
+ /**
591
+ * Helper: Create Stats object
592
+ */
593
+ function createStatsObject(_path: string, size: number, isDir: boolean): Stats {
594
+ const now = Date.now();
595
+ return {
596
+ isFile: () => !isDir,
597
+ isDirectory: () => isDir,
598
+ isBlockDevice: () => false,
599
+ isCharacterDevice: () => false,
600
+ isSymbolicLink: () => false,
601
+ isFIFO: () => false,
602
+ isSocket: () => false,
603
+ dev: 0,
604
+ ino: 0,
605
+ mode: isDir ? 16877 : 33188,
606
+ nlink: 1,
607
+ uid: 0,
608
+ gid: 0,
609
+ rdev: 0,
610
+ size,
611
+ blksize: 4096,
612
+ blocks: Math.ceil(size / 512),
613
+ atimeMs: now,
614
+ mtimeMs: now,
615
+ ctimeMs: now,
616
+ birthtimeMs: now,
617
+ atime: new Date(now),
618
+ mtime: new Date(now),
619
+ ctime: new Date(now),
620
+ birthtime: new Date(now),
621
+ };
622
+ }
623
+
624
+ /**
625
+ * Helper: Create Stats from Deno FileInfo
626
+ */
627
+ function createStatsFromDenoFileInfo(info: any): Stats {
628
+ return {
629
+ isFile: () => info.isFile,
630
+ isDirectory: () => info.isDirectory,
631
+ isBlockDevice: () => false,
632
+ isCharacterDevice: () => false,
633
+ isSymbolicLink: () => info.isSymlink || false,
634
+ isFIFO: () => false,
635
+ isSocket: () => false,
636
+ dev: info.dev || 0,
637
+ ino: info.ino || 0,
638
+ mode: info.mode || 0,
639
+ nlink: info.nlink || 1,
640
+ uid: info.uid || 0,
641
+ gid: info.gid || 0,
642
+ rdev: 0,
643
+ size: info.size,
644
+ blksize: info.blksize || 4096,
645
+ blocks: info.blocks || Math.ceil(info.size / 512),
646
+ atimeMs: info.atime?.getTime() || Date.now(),
647
+ mtimeMs: info.mtime?.getTime() || Date.now(),
648
+ ctimeMs: info.birthtime?.getTime() || Date.now(),
649
+ birthtimeMs: info.birthtime?.getTime() || Date.now(),
650
+ atime: info.atime || new Date(),
651
+ mtime: info.mtime || new Date(),
652
+ ctime: info.birthtime || new Date(),
653
+ birthtime: info.birthtime || new Date(),
654
+ };
655
+ }
656
+
657
+ /**
658
+ * Helper: Create Dirent from Deno DirEntry
659
+ */
660
+ function createDirentFromDenoEntry(entry: any): Dirent {
661
+ return {
662
+ name: entry.name,
663
+ isFile: () => entry.isFile,
664
+ isDirectory: () => entry.isDirectory,
665
+ isBlockDevice: () => false,
666
+ isCharacterDevice: () => false,
667
+ isSymbolicLink: () => entry.isSymlink || false,
668
+ isFIFO: () => false,
669
+ isSocket: () => false,
670
+ };
671
+ }
672
+
673
+ /**
674
+ * Get current runtime
675
+ */
676
+ export function getRuntime(): 'node' | 'bun' | 'deno' {
677
+ return runtime;
678
+ }
679
+
680
+ /**
681
+ * Promises API (re-export for compatibility)
682
+ */
683
+ export const promises = {
684
+ readFile,
685
+ writeFile,
686
+ appendFile,
687
+ stat,
688
+ mkdir,
689
+ readdir,
690
+ unlink,
691
+ rmdir,
692
+ rename,
693
+ copyFile,
694
+ realpath,
695
+ };
696
+
697
+ /**
698
+ * Default export
699
+ */
700
+ export default {
701
+ readFile,
702
+ readFileSync,
703
+ writeFile,
704
+ writeFileSync,
705
+ appendFile,
706
+ appendFileSync,
707
+ exists,
708
+ existsSync,
709
+ stat,
710
+ statSync,
711
+ mkdir,
712
+ mkdirSync,
713
+ readdir,
714
+ readdirSync,
715
+ unlink,
716
+ unlinkSync,
717
+ rmdir,
718
+ rmdirSync,
719
+ rename,
720
+ renameSync,
721
+ copyFile,
722
+ copyFileSync,
723
+ realpath,
724
+ realpathSync,
725
+ promises,
726
+ getRuntime,
727
+ };