elit 3.0.1 → 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.
- package/dist/build.d.ts +4 -12
- package/dist/build.d.ts.map +1 -0
- package/dist/chokidar.d.ts +7 -9
- package/dist/chokidar.d.ts.map +1 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +17 -4
- package/dist/config.d.ts +29 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/dom.d.ts +7 -14
- package/dist/dom.d.ts.map +1 -0
- package/dist/el.d.ts +19 -191
- package/dist/el.d.ts.map +1 -0
- package/dist/fs.d.ts +35 -35
- package/dist/fs.d.ts.map +1 -0
- package/dist/hmr.d.ts +3 -3
- package/dist/hmr.d.ts.map +1 -0
- package/dist/http.d.ts +20 -22
- package/dist/http.d.ts.map +1 -0
- package/dist/https.d.ts +12 -15
- package/dist/https.d.ts.map +1 -0
- package/dist/index.d.ts +10 -629
- package/dist/index.d.ts.map +1 -0
- package/dist/mime-types.d.ts +9 -9
- package/dist/mime-types.d.ts.map +1 -0
- package/dist/path.d.ts +22 -19
- package/dist/path.d.ts.map +1 -0
- package/dist/router.d.ts +10 -17
- package/dist/router.d.ts.map +1 -0
- package/dist/runtime.d.ts +5 -6
- package/dist/runtime.d.ts.map +1 -0
- package/dist/server.d.ts +105 -7
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +14 -2
- package/dist/server.mjs +14 -2
- package/dist/state.d.ts +21 -27
- package/dist/state.d.ts.map +1 -0
- package/dist/style.d.ts +14 -55
- package/dist/style.d.ts.map +1 -0
- package/dist/types.d.ts +26 -240
- package/dist/types.d.ts.map +1 -0
- package/dist/ws.d.ts +14 -17
- package/dist/ws.d.ts.map +1 -0
- package/dist/wss.d.ts +16 -16
- package/dist/wss.d.ts.map +1 -0
- package/package.json +3 -2
- package/src/build.ts +337 -0
- package/src/chokidar.ts +401 -0
- package/src/cli.ts +638 -0
- package/src/config.ts +205 -0
- package/src/dom.ts +817 -0
- package/src/el.ts +164 -0
- package/src/fs.ts +727 -0
- package/src/hmr.ts +137 -0
- package/src/http.ts +775 -0
- package/src/https.ts +411 -0
- package/src/index.ts +14 -0
- package/src/mime-types.ts +222 -0
- package/src/path.ts +493 -0
- package/src/router.ts +237 -0
- package/src/runtime.ts +97 -0
- package/src/server.ts +1290 -0
- package/src/state.ts +468 -0
- package/src/style.ts +524 -0
- package/{dist/types-Du6kfwTm.d.ts → src/types.ts} +58 -141
- package/src/ws.ts +506 -0
- package/src/wss.ts +241 -0
- package/dist/build.d.mts +0 -20
- package/dist/chokidar.d.mts +0 -134
- package/dist/dom.d.mts +0 -87
- package/dist/el.d.mts +0 -207
- package/dist/fs.d.mts +0 -255
- package/dist/hmr.d.mts +0 -38
- package/dist/http.d.mts +0 -163
- package/dist/https.d.mts +0 -108
- package/dist/index.d.mts +0 -629
- package/dist/mime-types.d.mts +0 -48
- package/dist/path.d.mts +0 -163
- package/dist/router.d.mts +0 -47
- package/dist/runtime.d.mts +0 -97
- package/dist/server.d.mts +0 -7
- package/dist/state.d.mts +0 -111
- package/dist/style.d.mts +0 -159
- package/dist/types-C0nGi6MX.d.mts +0 -346
- package/dist/types.d.mts +0 -452
- package/dist/ws.d.mts +0 -195
- 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
|
+
};
|