elit 2.0.1 → 3.0.1

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 (82) hide show
  1. package/README.md +275 -128
  2. package/dist/build.d.mts +10 -1
  3. package/dist/build.d.ts +10 -1
  4. package/dist/build.js +670 -1
  5. package/dist/build.mjs +641 -1
  6. package/dist/chokidar.d.mts +134 -0
  7. package/dist/chokidar.d.ts +134 -0
  8. package/dist/chokidar.js +240 -0
  9. package/dist/chokidar.mjs +221 -0
  10. package/dist/cli.js +2792 -495
  11. package/dist/dom.d.mts +10 -3
  12. package/dist/dom.d.ts +10 -3
  13. package/dist/dom.js +676 -1
  14. package/dist/dom.mjs +647 -1
  15. package/dist/el.d.mts +16 -36
  16. package/dist/el.d.ts +16 -36
  17. package/dist/el.js +789 -1
  18. package/dist/el.mjs +583 -1
  19. package/dist/fs.d.mts +255 -0
  20. package/dist/fs.d.ts +255 -0
  21. package/dist/fs.js +513 -0
  22. package/dist/fs.mjs +469 -0
  23. package/dist/hmr.js +112 -1
  24. package/dist/hmr.mjs +91 -1
  25. package/dist/http.d.mts +163 -0
  26. package/dist/http.d.ts +163 -0
  27. package/dist/http.js +632 -0
  28. package/dist/http.mjs +605 -0
  29. package/dist/https.d.mts +108 -0
  30. package/dist/https.d.ts +108 -0
  31. package/dist/https.js +907 -0
  32. package/dist/https.mjs +901 -0
  33. package/dist/index.d.mts +613 -33
  34. package/dist/index.d.ts +613 -33
  35. package/dist/index.js +2589 -1
  36. package/dist/index.mjs +2312 -1
  37. package/dist/mime-types.d.mts +48 -0
  38. package/dist/mime-types.d.ts +48 -0
  39. package/dist/mime-types.js +197 -0
  40. package/dist/mime-types.mjs +166 -0
  41. package/dist/path.d.mts +163 -0
  42. package/dist/path.d.ts +163 -0
  43. package/dist/path.js +350 -0
  44. package/dist/path.mjs +310 -0
  45. package/dist/router.d.mts +3 -1
  46. package/dist/router.d.ts +3 -1
  47. package/dist/router.js +830 -1
  48. package/dist/router.mjs +801 -1
  49. package/dist/runtime.d.mts +97 -0
  50. package/dist/runtime.d.ts +97 -0
  51. package/dist/runtime.js +43 -0
  52. package/dist/runtime.mjs +15 -0
  53. package/dist/server.d.mts +5 -1
  54. package/dist/server.d.ts +5 -1
  55. package/dist/server.js +3267 -1
  56. package/dist/server.mjs +3241 -1
  57. package/dist/state.d.mts +3 -1
  58. package/dist/state.d.ts +3 -1
  59. package/dist/state.js +1036 -1
  60. package/dist/state.mjs +992 -1
  61. package/dist/style.d.mts +47 -1
  62. package/dist/style.d.ts +47 -1
  63. package/dist/style.js +551 -1
  64. package/dist/style.mjs +483 -1
  65. package/dist/{types-DOAdFFJB.d.ts → types-C0nGi6MX.d.mts} +29 -13
  66. package/dist/{types-DOAdFFJB.d.mts → types-Du6kfwTm.d.ts} +29 -13
  67. package/dist/types.d.mts +452 -3
  68. package/dist/types.d.ts +452 -3
  69. package/dist/types.js +18 -1
  70. package/dist/ws.d.mts +195 -0
  71. package/dist/ws.d.ts +195 -0
  72. package/dist/ws.js +380 -0
  73. package/dist/ws.mjs +358 -0
  74. package/dist/wss.d.mts +108 -0
  75. package/dist/wss.d.ts +108 -0
  76. package/dist/wss.js +1306 -0
  77. package/dist/wss.mjs +1300 -0
  78. package/package.json +53 -6
  79. package/dist/client.d.mts +0 -9
  80. package/dist/client.d.ts +0 -9
  81. package/dist/client.js +0 -1
  82. package/dist/client.mjs +0 -1
package/dist/cli.js CHANGED
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env node
2
- #!/usr/bin/env node
3
2
  "use strict";
4
3
  var __create = Object.create;
5
4
  var __defProp = Object.defineProperty;
@@ -7,9 +6,16 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
8
7
  var __getProtoOf = Object.getPrototypeOf;
9
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __esm = (fn, res) => function __init() {
10
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
+ };
10
12
  var __commonJS = (cb, mod) => function __require() {
11
13
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
12
14
  };
15
+ var __export = (target, all) => {
16
+ for (var name in all)
17
+ __defProp(target, name, { get: all[name], enumerable: true });
18
+ };
13
19
  var __copyProps = (to, from, except, desc) => {
14
20
  if (from && typeof from === "object" || typeof from === "function") {
15
21
  for (let key of __getOwnPropNames(from))
@@ -26,13 +32,1387 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
26
32
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
33
  mod
28
34
  ));
35
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
36
+
37
+ // src/runtime.ts
38
+ var runtime, isNode, isBun, isDeno;
39
+ var init_runtime = __esm({
40
+ "src/runtime.ts"() {
41
+ "use strict";
42
+ runtime = (() => {
43
+ if (typeof Deno !== "undefined") return "deno";
44
+ if (typeof Bun !== "undefined") return "bun";
45
+ return "node";
46
+ })();
47
+ isNode = runtime === "node";
48
+ isBun = runtime === "bun";
49
+ isDeno = runtime === "deno";
50
+ }
51
+ });
52
+
53
+ // src/fs.ts
54
+ var fs_exports = {};
55
+ __export(fs_exports, {
56
+ appendFile: () => appendFile,
57
+ appendFileSync: () => appendFileSync,
58
+ copyFile: () => copyFile,
59
+ copyFileSync: () => copyFileSync,
60
+ default: () => fs_default,
61
+ exists: () => exists,
62
+ existsSync: () => existsSync,
63
+ getRuntime: () => getRuntime,
64
+ mkdir: () => mkdir,
65
+ mkdirSync: () => mkdirSync,
66
+ promises: () => promises,
67
+ readFile: () => readFile,
68
+ readFileSync: () => readFileSync,
69
+ readdir: () => readdir,
70
+ readdirSync: () => readdirSync,
71
+ realpath: () => realpath,
72
+ realpathSync: () => realpathSync,
73
+ rename: () => rename,
74
+ renameSync: () => renameSync,
75
+ rmdir: () => rmdir,
76
+ rmdirSync: () => rmdirSync,
77
+ stat: () => stat,
78
+ statSync: () => statSync,
79
+ unlink: () => unlink,
80
+ unlinkSync: () => unlinkSync,
81
+ writeFile: () => writeFile,
82
+ writeFileSync: () => writeFileSync
83
+ });
84
+ function parseOptions(options, defaultValue) {
85
+ return typeof options === "string" ? { encoding: options } : options || defaultValue;
86
+ }
87
+ function decodeContent(content, encoding) {
88
+ if (encoding) {
89
+ return new TextDecoder(encoding).decode(content);
90
+ }
91
+ return Buffer.from(content instanceof ArrayBuffer ? new Uint8Array(content) : content);
92
+ }
93
+ function dataToUint8Array(data) {
94
+ if (typeof data === "string") {
95
+ return new TextEncoder().encode(data);
96
+ }
97
+ if (data instanceof Buffer) {
98
+ return new Uint8Array(data);
99
+ }
100
+ return data;
101
+ }
102
+ function processDenoEntries(iterator, withFileTypes) {
103
+ const entries = [];
104
+ for (const entry of iterator) {
105
+ if (withFileTypes) {
106
+ entries.push(createDirentFromDenoEntry(entry));
107
+ } else {
108
+ entries.push(entry.name);
109
+ }
110
+ }
111
+ return entries;
112
+ }
113
+ async function processDenoEntriesAsync(iterator, withFileTypes) {
114
+ const entries = [];
115
+ for await (const entry of iterator) {
116
+ if (withFileTypes) {
117
+ entries.push(createDirentFromDenoEntry(entry));
118
+ } else {
119
+ entries.push(entry.name);
120
+ }
121
+ }
122
+ return entries;
123
+ }
124
+ async function readFile(path, options) {
125
+ const opts = parseOptions(options, {});
126
+ if (isNode) {
127
+ return fsPromises.readFile(path, opts);
128
+ } else if (isBun) {
129
+ const file = Bun.file(path);
130
+ const content = await file.arrayBuffer();
131
+ return decodeContent(content, opts.encoding);
132
+ } else if (isDeno) {
133
+ const content = await Deno.readFile(path);
134
+ return decodeContent(content, opts.encoding);
135
+ }
136
+ throw new Error("Unsupported runtime");
137
+ }
138
+ function readFileSync(path, options) {
139
+ const opts = parseOptions(options, {});
140
+ if (isNode) {
141
+ return fs.readFileSync(path, opts);
142
+ } else if (isBun) {
143
+ const file = Bun.file(path);
144
+ const content = file.arrayBuffer();
145
+ return decodeContent(content, opts.encoding);
146
+ } else if (isDeno) {
147
+ const content = Deno.readFileSync(path);
148
+ return decodeContent(content, opts.encoding);
149
+ }
150
+ throw new Error("Unsupported runtime");
151
+ }
152
+ async function writeFile(path, data, options) {
153
+ const opts = parseOptions(options, {});
154
+ if (isNode) {
155
+ return fsPromises.writeFile(path, data, opts);
156
+ } else if (isBun) {
157
+ await Bun.write(path, data);
158
+ } else if (isDeno) {
159
+ await Deno.writeFile(path, dataToUint8Array(data));
160
+ }
161
+ }
162
+ function writeFileSync(path, data, options) {
163
+ const opts = parseOptions(options, {});
164
+ if (isNode) {
165
+ fs.writeFileSync(path, data, opts);
166
+ } else if (isBun) {
167
+ Bun.write(path, data);
168
+ } else if (isDeno) {
169
+ Deno.writeFileSync(path, dataToUint8Array(data));
170
+ }
171
+ }
172
+ async function appendFile(path, data, options) {
173
+ const opts = parseOptions(options, {});
174
+ if (isNode) {
175
+ return fsPromises.appendFile(path, data, opts);
176
+ } else {
177
+ if (await exists(path)) {
178
+ const existing = await readFile(path);
179
+ const combined = Buffer.isBuffer(existing) ? Buffer.concat([existing, Buffer.isBuffer(data) ? data : Buffer.from(data)]) : existing + (Buffer.isBuffer(data) ? data.toString() : data);
180
+ await writeFile(path, combined, opts);
181
+ } else {
182
+ await writeFile(path, data, opts);
183
+ }
184
+ }
185
+ }
186
+ function appendFileSync(path, data, options) {
187
+ const opts = parseOptions(options, {});
188
+ if (isNode) {
189
+ fs.appendFileSync(path, data, opts);
190
+ } else {
191
+ if (existsSync(path)) {
192
+ const existing = readFileSync(path);
193
+ const combined = Buffer.isBuffer(existing) ? Buffer.concat([existing, Buffer.isBuffer(data) ? data : Buffer.from(data)]) : existing + (Buffer.isBuffer(data) ? data.toString() : data);
194
+ writeFileSync(path, combined, opts);
195
+ } else {
196
+ writeFileSync(path, data, opts);
197
+ }
198
+ }
199
+ }
200
+ async function exists(path) {
201
+ try {
202
+ await stat(path);
203
+ return true;
204
+ } catch {
205
+ return false;
206
+ }
207
+ }
208
+ function existsSync(path) {
209
+ try {
210
+ statSync(path);
211
+ return true;
212
+ } catch {
213
+ return false;
214
+ }
215
+ }
216
+ async function stat(path) {
217
+ if (isNode) {
218
+ return fsPromises.stat(path);
219
+ } else if (isBun) {
220
+ const file = Bun.file(path);
221
+ const size = file.size;
222
+ const exists2 = await file.exists();
223
+ if (!exists2) {
224
+ throw new Error(`ENOENT: no such file or directory, stat '${path}'`);
225
+ }
226
+ return createStatsObject(path, size, false);
227
+ } else if (isDeno) {
228
+ const info = await Deno.stat(path);
229
+ return createStatsFromDenoFileInfo(info);
230
+ }
231
+ throw new Error("Unsupported runtime");
232
+ }
233
+ function statSync(path) {
234
+ if (isNode) {
235
+ return fs.statSync(path);
236
+ } else if (isBun) {
237
+ const file = Bun.file(path);
238
+ const size = file.size;
239
+ try {
240
+ file.arrayBuffer();
241
+ } catch {
242
+ throw new Error(`ENOENT: no such file or directory, stat '${path}'`);
243
+ }
244
+ return createStatsObject(path, size, false);
245
+ } else if (isDeno) {
246
+ const info = Deno.statSync(path);
247
+ return createStatsFromDenoFileInfo(info);
248
+ }
249
+ throw new Error("Unsupported runtime");
250
+ }
251
+ async function mkdir(path, options) {
252
+ const opts = typeof options === "number" ? { mode: options } : options || {};
253
+ if (isNode) {
254
+ await fsPromises.mkdir(path, opts);
255
+ } else if (isBun) {
256
+ await Deno.mkdir(path, { recursive: opts.recursive });
257
+ } else if (isDeno) {
258
+ await Deno.mkdir(path, { recursive: opts.recursive });
259
+ }
260
+ }
261
+ function mkdirSync(path, options) {
262
+ const opts = typeof options === "number" ? { mode: options } : options || {};
263
+ if (isNode) {
264
+ fs.mkdirSync(path, opts);
265
+ } else if (isBun) {
266
+ Deno.mkdirSync(path, { recursive: opts.recursive });
267
+ } else if (isDeno) {
268
+ Deno.mkdirSync(path, { recursive: opts.recursive });
269
+ }
270
+ }
271
+ async function readdir(path, options) {
272
+ const opts = parseOptions(options, {});
273
+ if (isNode) {
274
+ return fsPromises.readdir(path, opts);
275
+ } else if (isBunOrDeno) {
276
+ return processDenoEntriesAsync(Deno.readDir(path), opts.withFileTypes);
277
+ }
278
+ throw new Error("Unsupported runtime");
279
+ }
280
+ function readdirSync(path, options) {
281
+ const opts = parseOptions(options, {});
282
+ if (isNode) {
283
+ return fs.readdirSync(path, opts);
284
+ } else if (isBunOrDeno) {
285
+ return processDenoEntries(Deno.readDirSync(path), opts.withFileTypes);
286
+ }
287
+ throw new Error("Unsupported runtime");
288
+ }
289
+ async function unlink(path) {
290
+ if (isNode) {
291
+ return fsPromises.unlink(path);
292
+ } else if (isBun) {
293
+ await Deno.remove(path);
294
+ } else if (isDeno) {
295
+ await Deno.remove(path);
296
+ }
297
+ }
298
+ function unlinkSync(path) {
299
+ if (isNode) {
300
+ fs.unlinkSync(path);
301
+ } else if (isBun) {
302
+ Deno.removeSync(path);
303
+ } else if (isDeno) {
304
+ Deno.removeSync(path);
305
+ }
306
+ }
307
+ async function rmdir(path, options) {
308
+ if (isNode) {
309
+ return fsPromises.rmdir(path, options);
310
+ } else if (isBun) {
311
+ await Deno.remove(path, { recursive: options?.recursive });
312
+ } else if (isDeno) {
313
+ await Deno.remove(path, { recursive: options?.recursive });
314
+ }
315
+ }
316
+ function rmdirSync(path, options) {
317
+ if (isNode) {
318
+ fs.rmdirSync(path, options);
319
+ } else if (isBun) {
320
+ Deno.removeSync(path, { recursive: options?.recursive });
321
+ } else if (isDeno) {
322
+ Deno.removeSync(path, { recursive: options?.recursive });
323
+ }
324
+ }
325
+ async function rename(oldPath, newPath) {
326
+ if (isNode) {
327
+ return fsPromises.rename(oldPath, newPath);
328
+ } else if (isBun) {
329
+ await Deno.rename(oldPath, newPath);
330
+ } else if (isDeno) {
331
+ await Deno.rename(oldPath, newPath);
332
+ }
333
+ }
334
+ function renameSync(oldPath, newPath) {
335
+ if (isNode) {
336
+ fs.renameSync(oldPath, newPath);
337
+ } else if (isBun) {
338
+ Deno.renameSync(oldPath, newPath);
339
+ } else if (isDeno) {
340
+ Deno.renameSync(oldPath, newPath);
341
+ }
342
+ }
343
+ async function copyFile(src, dest, flags) {
344
+ if (isNode) {
345
+ return fsPromises.copyFile(src, dest, flags);
346
+ } else if (isBun) {
347
+ await Deno.copyFile(src, dest);
348
+ } else if (isDeno) {
349
+ await Deno.copyFile(src, dest);
350
+ }
351
+ }
352
+ function copyFileSync(src, dest, flags) {
353
+ if (isNode) {
354
+ fs.copyFileSync(src, dest, flags);
355
+ } else if (isBun) {
356
+ Deno.copyFileSync(src, dest);
357
+ } else if (isDeno) {
358
+ Deno.copyFileSync(src, dest);
359
+ }
360
+ }
361
+ async function realpath(path, options) {
362
+ if (isNode) {
363
+ return fsPromises.realpath(path, options);
364
+ } else if (isBun) {
365
+ const fs2 = require("fs/promises");
366
+ return fs2.realpath(path, options);
367
+ } else if (isDeno) {
368
+ return await Deno.realPath(path);
369
+ }
370
+ return path;
371
+ }
372
+ function realpathSync(path, options) {
373
+ if (isNode) {
374
+ return fs.realpathSync(path, options);
375
+ } else if (isBun) {
376
+ const fs2 = require("fs");
377
+ return fs2.realpathSync(path, options);
378
+ } else if (isDeno) {
379
+ return Deno.realPathSync(path);
380
+ }
381
+ return path;
382
+ }
383
+ function createStatsObject(_path, size, isDir) {
384
+ const now = Date.now();
385
+ return {
386
+ isFile: () => !isDir,
387
+ isDirectory: () => isDir,
388
+ isBlockDevice: () => false,
389
+ isCharacterDevice: () => false,
390
+ isSymbolicLink: () => false,
391
+ isFIFO: () => false,
392
+ isSocket: () => false,
393
+ dev: 0,
394
+ ino: 0,
395
+ mode: isDir ? 16877 : 33188,
396
+ nlink: 1,
397
+ uid: 0,
398
+ gid: 0,
399
+ rdev: 0,
400
+ size,
401
+ blksize: 4096,
402
+ blocks: Math.ceil(size / 512),
403
+ atimeMs: now,
404
+ mtimeMs: now,
405
+ ctimeMs: now,
406
+ birthtimeMs: now,
407
+ atime: new Date(now),
408
+ mtime: new Date(now),
409
+ ctime: new Date(now),
410
+ birthtime: new Date(now)
411
+ };
412
+ }
413
+ function createStatsFromDenoFileInfo(info) {
414
+ return {
415
+ isFile: () => info.isFile,
416
+ isDirectory: () => info.isDirectory,
417
+ isBlockDevice: () => false,
418
+ isCharacterDevice: () => false,
419
+ isSymbolicLink: () => info.isSymlink || false,
420
+ isFIFO: () => false,
421
+ isSocket: () => false,
422
+ dev: info.dev || 0,
423
+ ino: info.ino || 0,
424
+ mode: info.mode || 0,
425
+ nlink: info.nlink || 1,
426
+ uid: info.uid || 0,
427
+ gid: info.gid || 0,
428
+ rdev: 0,
429
+ size: info.size,
430
+ blksize: info.blksize || 4096,
431
+ blocks: info.blocks || Math.ceil(info.size / 512),
432
+ atimeMs: info.atime?.getTime() || Date.now(),
433
+ mtimeMs: info.mtime?.getTime() || Date.now(),
434
+ ctimeMs: info.birthtime?.getTime() || Date.now(),
435
+ birthtimeMs: info.birthtime?.getTime() || Date.now(),
436
+ atime: info.atime || /* @__PURE__ */ new Date(),
437
+ mtime: info.mtime || /* @__PURE__ */ new Date(),
438
+ ctime: info.birthtime || /* @__PURE__ */ new Date(),
439
+ birthtime: info.birthtime || /* @__PURE__ */ new Date()
440
+ };
441
+ }
442
+ function createDirentFromDenoEntry(entry) {
443
+ return {
444
+ name: entry.name,
445
+ isFile: () => entry.isFile,
446
+ isDirectory: () => entry.isDirectory,
447
+ isBlockDevice: () => false,
448
+ isCharacterDevice: () => false,
449
+ isSymbolicLink: () => entry.isSymlink || false,
450
+ isFIFO: () => false,
451
+ isSocket: () => false
452
+ };
453
+ }
454
+ function getRuntime() {
455
+ return runtime;
456
+ }
457
+ var isBunOrDeno, fs, fsPromises, promises, fs_default;
458
+ var init_fs = __esm({
459
+ "src/fs.ts"() {
460
+ "use strict";
461
+ init_runtime();
462
+ isBunOrDeno = isBun || isDeno;
463
+ if (isNode) {
464
+ fs = require("fs");
465
+ fsPromises = require("fs/promises");
466
+ }
467
+ promises = {
468
+ readFile,
469
+ writeFile,
470
+ appendFile,
471
+ stat,
472
+ mkdir,
473
+ readdir,
474
+ unlink,
475
+ rmdir,
476
+ rename,
477
+ copyFile,
478
+ realpath
479
+ };
480
+ fs_default = {
481
+ readFile,
482
+ readFileSync,
483
+ writeFile,
484
+ writeFileSync,
485
+ appendFile,
486
+ appendFileSync,
487
+ exists,
488
+ existsSync,
489
+ stat,
490
+ statSync,
491
+ mkdir,
492
+ mkdirSync,
493
+ readdir,
494
+ readdirSync,
495
+ unlink,
496
+ unlinkSync,
497
+ rmdir,
498
+ rmdirSync,
499
+ rename,
500
+ renameSync,
501
+ copyFile,
502
+ copyFileSync,
503
+ realpath,
504
+ realpathSync,
505
+ promises,
506
+ getRuntime
507
+ };
508
+ }
509
+ });
510
+
511
+ // src/path.ts
512
+ var path_exports = {};
513
+ __export(path_exports, {
514
+ basename: () => basename,
515
+ default: () => path_default,
516
+ delimiter: () => delimiter,
517
+ dirname: () => dirname,
518
+ extname: () => extname,
519
+ format: () => format,
520
+ getRuntime: () => getRuntime2,
521
+ isAbsolute: () => isAbsolute,
522
+ join: () => join,
523
+ normalize: () => normalize,
524
+ parse: () => parse,
525
+ posix: () => posix,
526
+ relative: () => relative,
527
+ resolve: () => resolve,
528
+ sep: () => sep,
529
+ toNamespacedPath: () => toNamespacedPath,
530
+ win32: () => win32
531
+ });
532
+ function getSeparator(isWin) {
533
+ return isWin ? "\\" : "/";
534
+ }
535
+ function getCwd() {
536
+ if (isNode || isBun) {
537
+ return process.cwd();
538
+ } else if (isDeno) {
539
+ return Deno.cwd();
540
+ }
541
+ return "/";
542
+ }
543
+ function findLastSeparator(path) {
544
+ return Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\"));
545
+ }
546
+ function createPathOps(isWin) {
547
+ return {
548
+ sep: getSeparator(isWin),
549
+ delimiter: isWin ? ";" : ":",
550
+ normalize: (path) => normalizePath(path, isWin),
551
+ join: (...paths) => joinPaths(paths, isWin),
552
+ resolve: (...paths) => resolvePaths(paths, isWin),
553
+ isAbsolute: (path) => isWin ? isAbsoluteWin(path) : isAbsolutePosix(path),
554
+ relative: (from, to) => relativePath(from, to, isWin),
555
+ dirname: (path) => getDirname(path, isWin),
556
+ basename: (path, ext) => getBasename(path, ext, isWin),
557
+ extname: (path) => getExtname(path),
558
+ parse: (path) => parsePath(path, isWin),
559
+ format: (pathObject) => formatPath(pathObject, isWin)
560
+ };
561
+ }
562
+ function isAbsolutePosix(path) {
563
+ return path.length > 0 && path[0] === "/";
564
+ }
565
+ function isAbsoluteWin(path) {
566
+ const len = path.length;
567
+ if (len === 0) return false;
568
+ const code = path.charCodeAt(0);
569
+ if (code === 47 || code === 92) {
570
+ return true;
571
+ }
572
+ if (code >= 65 && code <= 90 || code >= 97 && code <= 122) {
573
+ if (len > 2 && path.charCodeAt(1) === 58) {
574
+ const code2 = path.charCodeAt(2);
575
+ if (code2 === 47 || code2 === 92) {
576
+ return true;
577
+ }
578
+ }
579
+ }
580
+ return false;
581
+ }
582
+ function normalizePath(path, isWin) {
583
+ if (path.length === 0) return ".";
584
+ const separator = getSeparator(isWin);
585
+ const isAbsolute2 = isWin ? isAbsoluteWin(path) : isAbsolutePosix(path);
586
+ const trailingSeparator = path[path.length - 1] === separator || isWin && path[path.length - 1] === "/";
587
+ let normalized = path.replace(isWin ? /[\/\\]+/g : /\/+/g, separator);
588
+ const parts = normalized.split(separator);
589
+ const result = [];
590
+ for (let i = 0; i < parts.length; i++) {
591
+ const part = parts[i];
592
+ if (part === "" || part === ".") {
593
+ if (i === 0 && isAbsolute2) result.push("");
594
+ continue;
595
+ }
596
+ if (part === "..") {
597
+ if (result.length > 0 && result[result.length - 1] !== "..") {
598
+ if (!(result.length === 1 && result[0] === "")) {
599
+ result.pop();
600
+ }
601
+ } else if (!isAbsolute2) {
602
+ result.push("..");
603
+ }
604
+ } else {
605
+ result.push(part);
606
+ }
607
+ }
608
+ let final = result.join(separator);
609
+ if (final.length === 0) {
610
+ return isAbsolute2 ? separator : ".";
611
+ }
612
+ if (trailingSeparator && final[final.length - 1] !== separator) {
613
+ final += separator;
614
+ }
615
+ return final;
616
+ }
617
+ function joinPaths(paths, isWin) {
618
+ if (paths.length === 0) return ".";
619
+ const separator = getSeparator(isWin);
620
+ let joined = "";
621
+ for (let i = 0; i < paths.length; i++) {
622
+ const path = paths[i];
623
+ if (path && path.length > 0) {
624
+ if (joined.length === 0) {
625
+ joined = path;
626
+ } else {
627
+ joined += separator + path;
628
+ }
629
+ }
630
+ }
631
+ if (joined.length === 0) return ".";
632
+ return normalizePath(joined, isWin);
633
+ }
634
+ function resolvePaths(paths, isWin) {
635
+ const separator = getSeparator(isWin);
636
+ let resolved = "";
637
+ let isAbsolute2 = false;
638
+ for (let i = paths.length - 1; i >= 0 && !isAbsolute2; i--) {
639
+ const path = paths[i];
640
+ if (path && path.length > 0) {
641
+ resolved = path + (resolved.length > 0 ? separator + resolved : "");
642
+ isAbsolute2 = isWin ? isAbsoluteWin(resolved) : isAbsolutePosix(resolved);
643
+ }
644
+ }
645
+ if (!isAbsolute2) {
646
+ const cwd = getCwd();
647
+ resolved = cwd + (resolved.length > 0 ? separator + resolved : "");
648
+ }
649
+ return normalizePath(resolved, isWin);
650
+ }
651
+ function relativePath(from, to, isWin) {
652
+ from = resolvePaths([from], isWin);
653
+ to = resolvePaths([to], isWin);
654
+ if (from === to) return "";
655
+ const separator = getSeparator(isWin);
656
+ const fromParts = from.split(separator).filter((p) => p.length > 0);
657
+ const toParts = to.split(separator).filter((p) => p.length > 0);
658
+ let commonLength = 0;
659
+ const minLength = Math.min(fromParts.length, toParts.length);
660
+ for (let i = 0; i < minLength; i++) {
661
+ if (fromParts[i] === toParts[i]) {
662
+ commonLength++;
663
+ } else {
664
+ break;
665
+ }
666
+ }
667
+ const upCount = fromParts.length - commonLength;
668
+ const result = [];
669
+ for (let i = 0; i < upCount; i++) {
670
+ result.push("..");
671
+ }
672
+ for (let i = commonLength; i < toParts.length; i++) {
673
+ result.push(toParts[i]);
674
+ }
675
+ return result.join(separator) || ".";
676
+ }
677
+ function getDirname(path, isWin) {
678
+ if (path.length === 0) return ".";
679
+ const separator = getSeparator(isWin);
680
+ const normalized = normalizePath(path, isWin);
681
+ const lastSepIndex = normalized.lastIndexOf(separator);
682
+ if (lastSepIndex === -1) return ".";
683
+ if (lastSepIndex === 0) return separator;
684
+ return normalized.slice(0, lastSepIndex);
685
+ }
686
+ function getBasename(path, ext, isWin) {
687
+ if (path.length === 0) return "";
688
+ const lastSepIndex = isWin ? findLastSeparator(path) : path.lastIndexOf("/");
689
+ let base = lastSepIndex === -1 ? path : path.slice(lastSepIndex + 1);
690
+ if (ext && base.endsWith(ext)) {
691
+ base = base.slice(0, base.length - ext.length);
692
+ }
693
+ return base;
694
+ }
695
+ function getExtname(path) {
696
+ const lastDotIndex = path.lastIndexOf(".");
697
+ const lastSepIndex = findLastSeparator(path);
698
+ if (lastDotIndex === -1 || lastDotIndex < lastSepIndex || lastDotIndex === path.length - 1) {
699
+ return "";
700
+ }
701
+ return path.slice(lastDotIndex);
702
+ }
703
+ function parsePath(path, isWin) {
704
+ let root = "";
705
+ if (isWin) {
706
+ if (path.length >= 2 && path[1] === ":") {
707
+ root = path.slice(0, 2);
708
+ if (path.length > 2 && (path[2] === "\\" || path[2] === "/")) {
709
+ root += "\\";
710
+ }
711
+ } else if (path[0] === "\\" || path[0] === "/") {
712
+ root = "\\";
713
+ }
714
+ } else {
715
+ if (path[0] === "/") {
716
+ root = "/";
717
+ }
718
+ }
719
+ const dir = getDirname(path, isWin);
720
+ const base = getBasename(path, void 0, isWin);
721
+ const ext = getExtname(path);
722
+ const name = ext ? base.slice(0, base.length - ext.length) : base;
723
+ return { root, dir, base, ext, name };
724
+ }
725
+ function formatPath(pathObject, isWin) {
726
+ const separator = getSeparator(isWin);
727
+ const dir = pathObject.dir || pathObject.root || "";
728
+ const base = pathObject.base || (pathObject.name || "") + (pathObject.ext || "");
729
+ if (!dir) return base;
730
+ if (dir === pathObject.root) return dir + base;
731
+ return dir + separator + base;
732
+ }
733
+ function normalize(path) {
734
+ return normalizePath(path, isWindows);
735
+ }
736
+ function join(...paths) {
737
+ return joinPaths(paths, isWindows);
738
+ }
739
+ function resolve(...paths) {
740
+ return resolvePaths(paths, isWindows);
741
+ }
742
+ function isAbsolute(path) {
743
+ return isWindows ? win32.isAbsolute(path) : posix.isAbsolute(path);
744
+ }
745
+ function relative(from, to) {
746
+ return relativePath(from, to, isWindows);
747
+ }
748
+ function dirname(path) {
749
+ return getDirname(path, isWindows);
750
+ }
751
+ function basename(path, ext) {
752
+ return getBasename(path, ext, isWindows);
753
+ }
754
+ function extname(path) {
755
+ return getExtname(path);
756
+ }
757
+ function parse(path) {
758
+ return parsePath(path, isWindows);
759
+ }
760
+ function format(pathObject) {
761
+ return formatPath(pathObject, isWindows);
762
+ }
763
+ function toNamespacedPath(path) {
764
+ if (!isWindows || path.length === 0) return path;
765
+ const resolved = resolve(path);
766
+ if (resolved.length >= 3) {
767
+ if (resolved[0] === "\\") {
768
+ if (resolved[1] === "\\" && resolved[2] !== "?") {
769
+ return "\\\\?\\UNC\\" + resolved.slice(2);
770
+ }
771
+ } else if (resolved[1] === ":" && resolved[2] === "\\") {
772
+ return "\\\\?\\" + resolved;
773
+ }
774
+ }
775
+ return path;
776
+ }
777
+ function getRuntime2() {
778
+ return runtime;
779
+ }
780
+ var isWindows, sep, delimiter, posix, win32, path_default;
781
+ var init_path = __esm({
782
+ "src/path.ts"() {
783
+ "use strict";
784
+ init_runtime();
785
+ isWindows = (() => {
786
+ if (isNode) {
787
+ return process.platform === "win32";
788
+ } else if (isDeno) {
789
+ return Deno.build.os === "windows";
790
+ }
791
+ return typeof process !== "undefined" && process.platform === "win32";
792
+ })();
793
+ sep = isWindows ? "\\" : "/";
794
+ delimiter = isWindows ? ";" : ":";
795
+ posix = createPathOps(false);
796
+ win32 = createPathOps(true);
797
+ path_default = {
798
+ sep,
799
+ delimiter,
800
+ normalize,
801
+ join,
802
+ resolve,
803
+ isAbsolute,
804
+ relative,
805
+ dirname,
806
+ basename,
807
+ extname,
808
+ parse,
809
+ format,
810
+ toNamespacedPath,
811
+ posix,
812
+ win32,
813
+ getRuntime: getRuntime2
814
+ };
815
+ }
816
+ });
817
+
818
+ // src/http.ts
819
+ var http_exports = {};
820
+ __export(http_exports, {
821
+ Agent: () => Agent,
822
+ ClientRequest: () => ClientRequest,
823
+ IncomingMessage: () => IncomingMessage,
824
+ METHODS: () => METHODS,
825
+ STATUS_CODES: () => STATUS_CODES,
826
+ Server: () => Server,
827
+ ServerResponse: () => ServerResponse,
828
+ createServer: () => createServer,
829
+ default: () => http_default,
830
+ get: () => get,
831
+ getRuntime: () => getRuntime3,
832
+ request: () => request
833
+ });
834
+ function queueCallback(callback) {
835
+ if (callback) queueMicrotask(callback);
836
+ }
837
+ function headersToInit(headers) {
838
+ const result = {};
839
+ for (const key in headers) {
840
+ const value = headers[key];
841
+ result[key] = Array.isArray(value) ? value.join(", ") : String(value);
842
+ }
843
+ return result;
844
+ }
845
+ function createAddress(port, address, family = "IPv4") {
846
+ return { port, family, address };
847
+ }
848
+ function createErrorResponse() {
849
+ return new Response("Internal Server Error", { status: 500 });
850
+ }
851
+ function emitListeningWithCallback(server, callback) {
852
+ server._listening = true;
853
+ server.emit("listening");
854
+ queueCallback(callback);
855
+ }
856
+ function closeAndEmit(server, callback) {
857
+ server._listening = false;
858
+ server.emit("close");
859
+ if (callback) queueMicrotask(() => callback());
860
+ }
861
+ function createServer(optionsOrListener, requestListener) {
862
+ return new Server(typeof optionsOrListener === "function" ? optionsOrListener : requestListener);
863
+ }
864
+ function request(url, options, callback) {
865
+ const urlString = typeof url === "string" ? url : url.toString();
866
+ const req = new ClientRequest(urlString, options);
867
+ if (isNode) {
868
+ const urlObj = new URL(urlString);
869
+ const client = urlObj.protocol === "https:" ? https : http;
870
+ const nodeReq = client.request(urlString, {
871
+ method: options?.method || "GET",
872
+ headers: options?.headers,
873
+ timeout: options?.timeout,
874
+ signal: options?.signal
875
+ }, (res) => {
876
+ const incomingMessage = new IncomingMessage(res);
877
+ if (callback) callback(incomingMessage);
878
+ req.emit("response", incomingMessage);
879
+ });
880
+ nodeReq.on("error", (error) => req.emit("error", error));
881
+ nodeReq.end();
882
+ } else {
883
+ queueMicrotask(async () => {
884
+ try {
885
+ const response = await fetch(urlString, {
886
+ method: options?.method || "GET",
887
+ headers: options?.headers,
888
+ signal: options?.signal
889
+ });
890
+ const fetchRequest = new Request(urlString);
891
+ const incomingMessage = new IncomingMessage(fetchRequest);
892
+ incomingMessage.statusCode = response.status;
893
+ incomingMessage.statusMessage = response.statusText;
894
+ if (callback) callback(incomingMessage);
895
+ req.emit("response", incomingMessage);
896
+ } catch (error) {
897
+ req.emit("error", error);
898
+ }
899
+ });
900
+ }
901
+ return req;
902
+ }
903
+ function get(url, options, callback) {
904
+ return request(url, { ...options, method: "GET" }, callback);
905
+ }
906
+ function getRuntime3() {
907
+ return runtime;
908
+ }
909
+ var import_node_events, http, https, METHODS, STATUS_CODES, IncomingMessage, ServerResponse, Server, ClientRequest, Agent, http_default;
910
+ var init_http = __esm({
911
+ "src/http.ts"() {
912
+ "use strict";
913
+ import_node_events = require("events");
914
+ init_runtime();
915
+ if (isNode && typeof process !== "undefined") {
916
+ try {
917
+ http = require("http");
918
+ https = require("https");
919
+ } catch (e) {
920
+ http = require("http");
921
+ https = require("https");
922
+ }
923
+ }
924
+ METHODS = [
925
+ "GET",
926
+ "POST",
927
+ "PUT",
928
+ "DELETE",
929
+ "PATCH",
930
+ "HEAD",
931
+ "OPTIONS",
932
+ "CONNECT",
933
+ "TRACE"
934
+ ];
935
+ STATUS_CODES = {
936
+ 100: "Continue",
937
+ 101: "Switching Protocols",
938
+ 102: "Processing",
939
+ 200: "OK",
940
+ 201: "Created",
941
+ 202: "Accepted",
942
+ 203: "Non-Authoritative Information",
943
+ 204: "No Content",
944
+ 205: "Reset Content",
945
+ 206: "Partial Content",
946
+ 300: "Multiple Choices",
947
+ 301: "Moved Permanently",
948
+ 302: "Found",
949
+ 303: "See Other",
950
+ 304: "Not Modified",
951
+ 307: "Temporary Redirect",
952
+ 308: "Permanent Redirect",
953
+ 400: "Bad Request",
954
+ 401: "Unauthorized",
955
+ 402: "Payment Required",
956
+ 403: "Forbidden",
957
+ 404: "Not Found",
958
+ 405: "Method Not Allowed",
959
+ 406: "Not Acceptable",
960
+ 407: "Proxy Authentication Required",
961
+ 408: "Request Timeout",
962
+ 409: "Conflict",
963
+ 410: "Gone",
964
+ 411: "Length Required",
965
+ 412: "Precondition Failed",
966
+ 413: "Payload Too Large",
967
+ 414: "URI Too Long",
968
+ 415: "Unsupported Media Type",
969
+ 416: "Range Not Satisfiable",
970
+ 417: "Expectation Failed",
971
+ 418: "I'm a teapot",
972
+ 422: "Unprocessable Entity",
973
+ 425: "Too Early",
974
+ 426: "Upgrade Required",
975
+ 428: "Precondition Required",
976
+ 429: "Too Many Requests",
977
+ 431: "Request Header Fields Too Large",
978
+ 451: "Unavailable For Legal Reasons",
979
+ 500: "Internal Server Error",
980
+ 501: "Not Implemented",
981
+ 502: "Bad Gateway",
982
+ 503: "Service Unavailable",
983
+ 504: "Gateway Timeout",
984
+ 505: "HTTP Version Not Supported",
985
+ 506: "Variant Also Negotiates",
986
+ 507: "Insufficient Storage",
987
+ 508: "Loop Detected",
988
+ 510: "Not Extended",
989
+ 511: "Network Authentication Required"
990
+ };
991
+ IncomingMessage = class extends import_node_events.EventEmitter {
992
+ constructor(req) {
993
+ super();
994
+ this.httpVersion = "1.1";
995
+ this.rawHeaders = [];
996
+ this._req = req;
997
+ if (isNode) {
998
+ this.method = req.method;
999
+ this.url = req.url;
1000
+ this.headers = req.headers;
1001
+ this.statusCode = req.statusCode;
1002
+ this.statusMessage = req.statusMessage;
1003
+ this.httpVersion = req.httpVersion;
1004
+ this.rawHeaders = req.rawHeaders;
1005
+ this.socket = req.socket;
1006
+ } else {
1007
+ this.method = req.method;
1008
+ const urlObj = new URL(req.url);
1009
+ this.url = urlObj.pathname + urlObj.search;
1010
+ this.headers = req.headers;
1011
+ this.rawHeaders = [];
1012
+ }
1013
+ }
1014
+ async text() {
1015
+ if (isNode) {
1016
+ return new Promise((resolve2, reject) => {
1017
+ const chunks = [];
1018
+ this._req.on("data", (chunk) => chunks.push(chunk));
1019
+ this._req.on("end", () => resolve2(Buffer.concat(chunks).toString("utf8")));
1020
+ this._req.on("error", reject);
1021
+ });
1022
+ }
1023
+ return this._req.text();
1024
+ }
1025
+ async json() {
1026
+ if (isNode) {
1027
+ const text = await this.text();
1028
+ return JSON.parse(text);
1029
+ }
1030
+ return this._req.json();
1031
+ }
1032
+ };
1033
+ ServerResponse = class extends import_node_events.EventEmitter {
1034
+ constructor(_req, nodeRes) {
1035
+ super();
1036
+ this.statusCode = 200;
1037
+ this.statusMessage = "OK";
1038
+ this.headersSent = false;
1039
+ this._body = "";
1040
+ this._finished = false;
1041
+ this._nodeRes = nodeRes;
1042
+ this._headers = /* @__PURE__ */ Object.create(null);
1043
+ }
1044
+ setHeader(name, value) {
1045
+ if (this.headersSent) {
1046
+ throw new Error("Cannot set headers after they are sent");
1047
+ }
1048
+ if (isNode && this._nodeRes) {
1049
+ this._nodeRes.setHeader(name, value);
1050
+ }
1051
+ this._headers[name.toLowerCase()] = value;
1052
+ return this;
1053
+ }
1054
+ getHeader(name) {
1055
+ if (isNode && this._nodeRes) {
1056
+ return this._nodeRes.getHeader(name);
1057
+ }
1058
+ return this._headers[name.toLowerCase()];
1059
+ }
1060
+ getHeaders() {
1061
+ if (isNode && this._nodeRes) {
1062
+ return this._nodeRes.getHeaders();
1063
+ }
1064
+ return { ...this._headers };
1065
+ }
1066
+ getHeaderNames() {
1067
+ if (isNode && this._nodeRes) {
1068
+ return this._nodeRes.getHeaderNames();
1069
+ }
1070
+ return Object.keys(this._headers);
1071
+ }
1072
+ hasHeader(name) {
1073
+ if (isNode && this._nodeRes) {
1074
+ return this._nodeRes.hasHeader(name);
1075
+ }
1076
+ return name.toLowerCase() in this._headers;
1077
+ }
1078
+ removeHeader(name) {
1079
+ if (this.headersSent) {
1080
+ throw new Error("Cannot remove headers after they are sent");
1081
+ }
1082
+ if (isNode && this._nodeRes) {
1083
+ this._nodeRes.removeHeader(name);
1084
+ }
1085
+ delete this._headers[name.toLowerCase()];
1086
+ }
1087
+ writeHead(statusCode, statusMessage, headers) {
1088
+ if (this.headersSent) {
1089
+ throw new Error("Cannot write headers after they are sent");
1090
+ }
1091
+ this.statusCode = statusCode;
1092
+ if (typeof statusMessage === "string") {
1093
+ this.statusMessage = statusMessage;
1094
+ if (headers) {
1095
+ for (const key in headers) {
1096
+ this.setHeader(key, headers[key]);
1097
+ }
1098
+ }
1099
+ } else if (statusMessage) {
1100
+ for (const key in statusMessage) {
1101
+ this.setHeader(key, statusMessage[key]);
1102
+ }
1103
+ }
1104
+ if (isNode && this._nodeRes) {
1105
+ if (typeof statusMessage === "string") {
1106
+ this._nodeRes.writeHead(statusCode, statusMessage, headers);
1107
+ } else {
1108
+ this._nodeRes.writeHead(statusCode, statusMessage);
1109
+ }
1110
+ }
1111
+ this.headersSent = true;
1112
+ return this;
1113
+ }
1114
+ write(chunk, encoding, callback) {
1115
+ if (typeof encoding === "function") {
1116
+ callback = encoding;
1117
+ encoding = "utf8";
1118
+ }
1119
+ if (!this.headersSent) {
1120
+ this.writeHead(this.statusCode);
1121
+ }
1122
+ if (isNode && this._nodeRes) {
1123
+ return this._nodeRes.write(chunk, encoding, callback);
1124
+ }
1125
+ this._body += chunk;
1126
+ queueCallback(callback);
1127
+ return true;
1128
+ }
1129
+ end(chunk, encoding, callback) {
1130
+ if (this._finished) {
1131
+ return this;
1132
+ }
1133
+ if (typeof chunk === "function") {
1134
+ callback = chunk;
1135
+ chunk = void 0;
1136
+ } else if (typeof encoding === "function") {
1137
+ callback = encoding;
1138
+ encoding = "utf8";
1139
+ }
1140
+ if (chunk !== void 0) {
1141
+ this.write(chunk, encoding);
1142
+ }
1143
+ if (!this.headersSent) {
1144
+ this.writeHead(this.statusCode);
1145
+ }
1146
+ this._finished = true;
1147
+ if (isNode && this._nodeRes) {
1148
+ this._nodeRes.end(callback);
1149
+ this.emit("finish");
1150
+ } else {
1151
+ const response = new Response(this._body, {
1152
+ status: this.statusCode,
1153
+ statusText: this.statusMessage,
1154
+ headers: headersToInit(this._headers)
1155
+ });
1156
+ if (this._resolve) {
1157
+ this._resolve(response);
1158
+ }
1159
+ queueCallback(callback);
1160
+ }
1161
+ return this;
1162
+ }
1163
+ _setResolver(resolve2) {
1164
+ this._resolve = resolve2;
1165
+ }
1166
+ };
1167
+ Server = class extends import_node_events.EventEmitter {
1168
+ constructor(requestListener) {
1169
+ super();
1170
+ this._listening = false;
1171
+ this.requestListener = requestListener;
1172
+ }
1173
+ listen(...args) {
1174
+ let port = 3e3;
1175
+ let hostname = "0.0.0.0";
1176
+ let callback;
1177
+ const firstArg = args[0];
1178
+ if (typeof firstArg === "number") {
1179
+ port = firstArg;
1180
+ const secondArg = args[1];
1181
+ if (typeof secondArg === "string") {
1182
+ hostname = secondArg;
1183
+ callback = args[2] || args[3];
1184
+ } else if (typeof secondArg === "function") {
1185
+ callback = secondArg;
1186
+ }
1187
+ } else if (firstArg && typeof firstArg === "object") {
1188
+ port = firstArg.port || 3e3;
1189
+ hostname = firstArg.hostname || "0.0.0.0";
1190
+ callback = args[1];
1191
+ }
1192
+ const self = this;
1193
+ if (isNode) {
1194
+ this.nativeServer = http.createServer((req, res) => {
1195
+ const incomingMessage = new IncomingMessage(req);
1196
+ const serverResponse = new ServerResponse(incomingMessage, res);
1197
+ if (self.requestListener) {
1198
+ self.requestListener(incomingMessage, serverResponse);
1199
+ } else {
1200
+ self.emit("request", incomingMessage, serverResponse);
1201
+ }
1202
+ });
1203
+ this.nativeServer.on("upgrade", (req, socket, head) => {
1204
+ self.emit("upgrade", req, socket, head);
1205
+ });
1206
+ this.nativeServer.listen(port, hostname, () => {
1207
+ this._listening = true;
1208
+ this.emit("listening");
1209
+ if (callback) callback();
1210
+ });
1211
+ this.nativeServer.on("error", (err) => this.emit("error", err));
1212
+ this.nativeServer.on("close", () => {
1213
+ this._listening = false;
1214
+ this.emit("close");
1215
+ });
1216
+ } else if (isBun) {
1217
+ this.nativeServer = Bun.serve({
1218
+ port,
1219
+ hostname,
1220
+ fetch: (req) => {
1221
+ const urlObj = new URL(req.url);
1222
+ const pathname = urlObj.pathname + urlObj.search;
1223
+ let statusCode = 200;
1224
+ let statusMessage = "OK";
1225
+ let body = "";
1226
+ const headers = /* @__PURE__ */ Object.create(null);
1227
+ let responseReady = false;
1228
+ const incomingMessage = {
1229
+ method: req.method,
1230
+ url: pathname,
1231
+ headers: req.headers,
1232
+ httpVersion: "1.1",
1233
+ rawHeaders: [],
1234
+ _req: req,
1235
+ text: () => req.text(),
1236
+ json: () => req.json()
1237
+ };
1238
+ const serverResponse = {
1239
+ statusCode: 200,
1240
+ statusMessage: "OK",
1241
+ headersSent: false,
1242
+ _headers: headers,
1243
+ setHeader(name, value) {
1244
+ headers[name.toLowerCase()] = Array.isArray(value) ? value.join(", ") : String(value);
1245
+ return this;
1246
+ },
1247
+ getHeader(name) {
1248
+ return headers[name.toLowerCase()];
1249
+ },
1250
+ getHeaders() {
1251
+ return { ...headers };
1252
+ },
1253
+ writeHead(status, arg2, arg3) {
1254
+ statusCode = status;
1255
+ this.statusCode = status;
1256
+ this.headersSent = true;
1257
+ if (typeof arg2 === "string") {
1258
+ statusMessage = arg2;
1259
+ this.statusMessage = arg2;
1260
+ if (arg3) {
1261
+ for (const key in arg3) {
1262
+ headers[key.toLowerCase()] = arg3[key];
1263
+ }
1264
+ }
1265
+ } else if (arg2) {
1266
+ for (const key in arg2) {
1267
+ headers[key.toLowerCase()] = arg2[key];
1268
+ }
1269
+ }
1270
+ return this;
1271
+ },
1272
+ write(chunk) {
1273
+ if (!this.headersSent) {
1274
+ this.writeHead(statusCode);
1275
+ }
1276
+ body += chunk;
1277
+ return true;
1278
+ },
1279
+ end(chunk) {
1280
+ if (chunk !== void 0) {
1281
+ this.write(chunk);
1282
+ }
1283
+ if (!this.headersSent) {
1284
+ this.writeHead(statusCode);
1285
+ }
1286
+ responseReady = true;
1287
+ return this;
1288
+ }
1289
+ };
1290
+ if (self.requestListener) {
1291
+ self.requestListener(incomingMessage, serverResponse);
1292
+ }
1293
+ if (responseReady) {
1294
+ return new Response(body, {
1295
+ status: statusCode,
1296
+ statusText: statusMessage,
1297
+ headers
1298
+ });
1299
+ }
1300
+ return new Promise((resolve2) => {
1301
+ serverResponse.end = (chunk) => {
1302
+ if (chunk !== void 0) {
1303
+ body += chunk;
1304
+ }
1305
+ resolve2(new Response(body, {
1306
+ status: statusCode,
1307
+ statusText: statusMessage,
1308
+ headers
1309
+ }));
1310
+ };
1311
+ });
1312
+ },
1313
+ error: createErrorResponse
1314
+ });
1315
+ emitListeningWithCallback(this, callback);
1316
+ } else if (isDeno) {
1317
+ this.nativeServer = Deno.serve({
1318
+ port,
1319
+ hostname,
1320
+ handler: (req) => {
1321
+ return new Promise((resolve2) => {
1322
+ const incomingMessage = new IncomingMessage(req);
1323
+ const serverResponse = new ServerResponse();
1324
+ serverResponse._setResolver(resolve2);
1325
+ if (self.requestListener) {
1326
+ self.requestListener(incomingMessage, serverResponse);
1327
+ } else {
1328
+ self.emit("request", incomingMessage, serverResponse);
1329
+ }
1330
+ });
1331
+ },
1332
+ onError: (error) => {
1333
+ this.emit("error", error);
1334
+ return createErrorResponse();
1335
+ }
1336
+ });
1337
+ emitListeningWithCallback(this, callback);
1338
+ }
1339
+ return this;
1340
+ }
1341
+ close(callback) {
1342
+ if (!this.nativeServer) {
1343
+ if (callback) queueMicrotask(() => callback());
1344
+ return this;
1345
+ }
1346
+ if (isNode) {
1347
+ this.nativeServer.close(callback);
1348
+ } else if (isBun) {
1349
+ this.nativeServer.stop();
1350
+ closeAndEmit(this, callback);
1351
+ } else if (isDeno) {
1352
+ this.nativeServer.shutdown();
1353
+ closeAndEmit(this, callback);
1354
+ }
1355
+ return this;
1356
+ }
1357
+ address() {
1358
+ if (!this.nativeServer) return null;
1359
+ if (isNode) {
1360
+ const addr = this.nativeServer.address();
1361
+ if (!addr) return null;
1362
+ if (typeof addr === "string") {
1363
+ return createAddress(0, addr, "unix");
1364
+ }
1365
+ return addr;
1366
+ } else if (isBun) {
1367
+ return createAddress(this.nativeServer.port, this.nativeServer.hostname);
1368
+ } else if (isDeno) {
1369
+ const addr = this.nativeServer.addr;
1370
+ return createAddress(addr.port, addr.hostname);
1371
+ }
1372
+ return null;
1373
+ }
1374
+ get listening() {
1375
+ return this._listening;
1376
+ }
1377
+ };
1378
+ ClientRequest = class extends import_node_events.EventEmitter {
1379
+ constructor(_url, _options = {}) {
1380
+ super();
1381
+ }
1382
+ write(_chunk) {
1383
+ return true;
1384
+ }
1385
+ end(callback) {
1386
+ queueCallback(callback);
1387
+ }
1388
+ };
1389
+ Agent = class {
1390
+ constructor(options) {
1391
+ this.options = options;
1392
+ }
1393
+ };
1394
+ http_default = {
1395
+ createServer,
1396
+ request,
1397
+ get,
1398
+ Server,
1399
+ IncomingMessage,
1400
+ ServerResponse,
1401
+ Agent,
1402
+ ClientRequest,
1403
+ METHODS,
1404
+ STATUS_CODES,
1405
+ getRuntime: getRuntime3
1406
+ };
1407
+ }
1408
+ });
29
1409
 
30
1410
  // package.json
31
1411
  var require_package = __commonJS({
32
1412
  "package.json"(exports2, module2) {
33
1413
  module2.exports = {
34
1414
  name: "elit",
35
- version: "2.0.0",
1415
+ version: "3.0.1",
36
1416
  description: "Optimized lightweight library for creating DOM elements with reactive state",
37
1417
  main: "dist/index.js",
38
1418
  module: "dist/index.mjs",
@@ -85,12 +1465,59 @@ var require_package = __commonJS({
85
1465
  types: "./dist/build.d.ts",
86
1466
  import: "./dist/build.mjs",
87
1467
  require: "./dist/build.js"
1468
+ },
1469
+ "./http": {
1470
+ types: "./dist/http.d.ts",
1471
+ import: "./dist/http.mjs",
1472
+ require: "./dist/http.js"
1473
+ },
1474
+ "./https": {
1475
+ types: "./dist/https.d.ts",
1476
+ import: "./dist/https.mjs",
1477
+ require: "./dist/https.js"
1478
+ },
1479
+ "./ws": {
1480
+ types: "./dist/ws.d.ts",
1481
+ import: "./dist/ws.mjs",
1482
+ require: "./dist/ws.js"
1483
+ },
1484
+ "./fs": {
1485
+ types: "./dist/fs.d.ts",
1486
+ import: "./dist/fs.mjs",
1487
+ require: "./dist/fs.js"
1488
+ },
1489
+ "./mime-types": {
1490
+ types: "./dist/mime-types.d.ts",
1491
+ import: "./dist/mime-types.mjs",
1492
+ require: "./dist/mime-types.js"
1493
+ },
1494
+ "./chokidar": {
1495
+ types: "./dist/chokidar.d.ts",
1496
+ import: "./dist/chokidar.mjs",
1497
+ require: "./dist/chokidar.js"
1498
+ },
1499
+ "./path": {
1500
+ types: "./dist/path.d.ts",
1501
+ import: "./dist/path.mjs",
1502
+ require: "./dist/path.js"
1503
+ },
1504
+ "./wss": {
1505
+ types: "./dist/wss.d.ts",
1506
+ import: "./dist/wss.mjs",
1507
+ require: "./dist/wss.js"
1508
+ },
1509
+ "./runtime": {
1510
+ types: "./dist/runtime.d.ts",
1511
+ import: "./dist/runtime.mjs",
1512
+ require: "./dist/runtime.js"
88
1513
  }
89
1514
  },
90
1515
  scripts: {
91
1516
  build: "tsup",
92
1517
  dev: "tsup --watch",
93
1518
  typecheck: "tsc --noEmit",
1519
+ benchmark: "node benchmark/server-benchmark.js",
1520
+ "benchmark:router": "node benchmark/router-benchmark.js",
94
1521
  "docs:dev": "npm run --prefix docs dev",
95
1522
  "docs:build": "npm run --prefix docs build",
96
1523
  "docs:preview": "npm run --prefix docs preview",
@@ -129,18 +1556,18 @@ var require_package = __commonJS({
129
1556
  bugs: {
130
1557
  url: "https://github.com/d-osc/elit/issues"
131
1558
  },
132
- homepage: "https://github.com/d-osc/elit#readme",
1559
+ homepage: "https://d-osc.github.io/elit/",
133
1560
  dependencies: {
134
- chokidar: "^4.0.3",
135
1561
  esbuild: "^0.24.2",
136
- "mime-types": "^2.1.35",
137
- open: "^11.0.0",
138
- ws: "^8.18.0"
1562
+ open: "^11.0.0"
139
1563
  },
140
1564
  devDependencies: {
1565
+ "@types/express": "^5.0.6",
141
1566
  "@types/mime-types": "^2.1.4",
142
1567
  "@types/node": "^22.0.0",
143
1568
  "@types/ws": "^8.5.13",
1569
+ express: "^5.2.1",
1570
+ elysia: "^1.4.19",
144
1571
  terser: "^5.44.1",
145
1572
  tsup: "^8.0.0",
146
1573
  typescript: "^5.3.0"
@@ -155,8 +1582,31 @@ var require_package = __commonJS({
155
1582
  });
156
1583
 
157
1584
  // src/config.ts
158
- var import_fs = require("fs");
159
- var import_path = require("path");
1585
+ init_fs();
1586
+ init_path();
1587
+ function readFileAsString(filePath) {
1588
+ const contentBuffer = readFileSync(filePath, "utf-8");
1589
+ return typeof contentBuffer === "string" ? contentBuffer : contentBuffer.toString("utf-8");
1590
+ }
1591
+ function removeQuotes(value) {
1592
+ const trimmed = value.trim();
1593
+ if (trimmed.startsWith('"') && trimmed.endsWith('"') || trimmed.startsWith("'") && trimmed.endsWith("'")) {
1594
+ return trimmed.slice(1, -1);
1595
+ }
1596
+ return trimmed;
1597
+ }
1598
+ async function importConfigModule(configPath) {
1599
+ const { pathToFileURL } = await import("url");
1600
+ const configModule = await import(pathToFileURL(configPath).href);
1601
+ return configModule.default || configModule;
1602
+ }
1603
+ async function safeCleanup(filePath) {
1604
+ try {
1605
+ const { unlinkSync: unlinkSync2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
1606
+ unlinkSync2(filePath);
1607
+ } catch {
1608
+ }
1609
+ }
160
1610
  var CONFIG_FILES = [
161
1611
  "elit.config.ts",
162
1612
  "elit.config.js",
@@ -173,9 +1623,9 @@ function loadEnv(mode = "development", cwd = process.cwd()) {
173
1623
  `.env`
174
1624
  ];
175
1625
  for (const file of envFiles) {
176
- const filePath = (0, import_path.resolve)(cwd, file);
177
- if ((0, import_fs.existsSync)(filePath)) {
178
- const content = (0, import_fs.readFileSync)(filePath, "utf-8");
1626
+ const filePath = resolve(cwd, file);
1627
+ if (existsSync(filePath)) {
1628
+ const content = readFileAsString(filePath);
179
1629
  const lines = content.split("\n");
180
1630
  for (const line of lines) {
181
1631
  const trimmed = line.trim();
@@ -183,10 +1633,7 @@ function loadEnv(mode = "development", cwd = process.cwd()) {
183
1633
  const match = trimmed.match(/^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/);
184
1634
  if (match) {
185
1635
  const [, key, value] = match;
186
- let cleanValue = value.trim();
187
- if (cleanValue.startsWith('"') && cleanValue.endsWith('"') || cleanValue.startsWith("'") && cleanValue.endsWith("'")) {
188
- cleanValue = cleanValue.slice(1, -1);
189
- }
1636
+ const cleanValue = removeQuotes(value);
190
1637
  if (!(key in env)) {
191
1638
  env[key] = cleanValue;
192
1639
  }
@@ -194,70 +1641,759 @@ function loadEnv(mode = "development", cwd = process.cwd()) {
194
1641
  }
195
1642
  }
196
1643
  }
197
- return env;
198
- }
199
- async function loadConfig(cwd = process.cwd()) {
200
- for (const configFile of CONFIG_FILES) {
201
- const configPath = (0, import_path.resolve)(cwd, configFile);
202
- if ((0, import_fs.existsSync)(configPath)) {
203
- try {
204
- return await loadConfigFile(configPath);
205
- } catch (error) {
206
- console.error(`Error loading config file: ${configFile}`);
207
- console.error(error);
208
- throw error;
1644
+ return env;
1645
+ }
1646
+ async function loadConfig(cwd = process.cwd()) {
1647
+ for (const configFile of CONFIG_FILES) {
1648
+ const configPath = resolve(cwd, configFile);
1649
+ if (existsSync(configPath)) {
1650
+ try {
1651
+ return await loadConfigFile(configPath);
1652
+ } catch (error) {
1653
+ console.error(`Error loading config file: ${configFile}`);
1654
+ console.error(error);
1655
+ throw error;
1656
+ }
1657
+ }
1658
+ }
1659
+ return null;
1660
+ }
1661
+ async function loadConfigFile(configPath) {
1662
+ const ext = configPath.split(".").pop();
1663
+ if (ext === "json") {
1664
+ const content = readFileAsString(configPath);
1665
+ return JSON.parse(content);
1666
+ } else if (ext === "ts") {
1667
+ try {
1668
+ const { build: build2 } = await import("esbuild");
1669
+ const { tmpdir } = await import("os");
1670
+ const { join: join2, dirname: dirname2 } = await Promise.resolve().then(() => (init_path(), path_exports));
1671
+ const tempFile = join2(tmpdir(), `elit-config-${Date.now()}.mjs`);
1672
+ const configDir = dirname2(configPath);
1673
+ await build2({
1674
+ entryPoints: [configPath],
1675
+ bundle: true,
1676
+ format: "esm",
1677
+ platform: "node",
1678
+ outfile: tempFile,
1679
+ write: true,
1680
+ target: "es2020",
1681
+ // Bundle everything including elit/* so config can use elit modules
1682
+ // Only mark Node.js built-ins as external
1683
+ external: ["node:*"],
1684
+ // Use the config directory as the working directory for resolution
1685
+ absWorkingDir: configDir
1686
+ });
1687
+ const config = await importConfigModule(tempFile);
1688
+ await safeCleanup(tempFile);
1689
+ return config;
1690
+ } catch (error) {
1691
+ console.error("Failed to load TypeScript config file.");
1692
+ console.error("You can use a .js, .mjs, or .json config file instead.");
1693
+ throw error;
1694
+ }
1695
+ } else {
1696
+ return await importConfigModule(configPath);
1697
+ }
1698
+ }
1699
+ function mergeConfig(config, cliArgs) {
1700
+ if (!config) {
1701
+ return cliArgs;
1702
+ }
1703
+ return {
1704
+ ...config,
1705
+ ...Object.fromEntries(
1706
+ Object.entries(cliArgs).filter(([_, v]) => v !== void 0)
1707
+ )
1708
+ };
1709
+ }
1710
+
1711
+ // src/server.ts
1712
+ init_http();
1713
+
1714
+ // src/https.ts
1715
+ var import_events = require("events");
1716
+ init_runtime();
1717
+ function queueCallback2(callback) {
1718
+ if (callback) queueMicrotask(callback);
1719
+ }
1720
+ function loadHttpClasses() {
1721
+ const httpModule = (init_http(), __toCommonJS(http_exports));
1722
+ return {
1723
+ IncomingMessage: httpModule.IncomingMessage,
1724
+ ServerResponse: httpModule.ServerResponse
1725
+ };
1726
+ }
1727
+ var https2;
1728
+ var ClientRequest2 = class extends import_events.EventEmitter {
1729
+ constructor(_url, _options = {}) {
1730
+ super();
1731
+ }
1732
+ write(_chunk) {
1733
+ return true;
1734
+ }
1735
+ end(callback) {
1736
+ queueCallback2(callback);
1737
+ }
1738
+ };
1739
+ function request2(url, options, callback) {
1740
+ const urlString = typeof url === "string" ? url : url.toString();
1741
+ const req = new ClientRequest2(urlString, options);
1742
+ if (isNode) {
1743
+ const { IncomingMessage: IncomingMessage3 } = loadHttpClasses();
1744
+ if (!https2) https2 = require("https");
1745
+ const nodeReq = https2.request(urlString, {
1746
+ method: options?.method || "GET",
1747
+ headers: options?.headers,
1748
+ timeout: options?.timeout,
1749
+ signal: options?.signal
1750
+ }, (res) => {
1751
+ const incomingMessage = new IncomingMessage3(res);
1752
+ if (callback) callback(incomingMessage);
1753
+ req.emit("response", incomingMessage);
1754
+ });
1755
+ nodeReq.on("error", (error) => req.emit("error", error));
1756
+ nodeReq.end();
1757
+ } else {
1758
+ const { IncomingMessage: IncomingMessage3 } = loadHttpClasses();
1759
+ queueMicrotask(async () => {
1760
+ try {
1761
+ const response = await fetch(urlString, {
1762
+ method: options?.method || "GET",
1763
+ headers: options?.headers,
1764
+ signal: options?.signal
1765
+ });
1766
+ const fetchRequest = new Request(urlString);
1767
+ const incomingMessage = new IncomingMessage3(fetchRequest);
1768
+ incomingMessage.statusCode = response.status;
1769
+ incomingMessage.statusMessage = response.statusText;
1770
+ if (callback) callback(incomingMessage);
1771
+ req.emit("response", incomingMessage);
1772
+ } catch (error) {
1773
+ req.emit("error", error);
1774
+ }
1775
+ });
1776
+ }
1777
+ return req;
1778
+ }
1779
+
1780
+ // src/ws.ts
1781
+ var import_events2 = require("events");
1782
+ init_runtime();
1783
+ var CLOSE_CODES = {
1784
+ NORMAL: 1e3,
1785
+ GOING_AWAY: 1001,
1786
+ PROTOCOL_ERROR: 1002,
1787
+ UNSUPPORTED_DATA: 1003,
1788
+ NO_STATUS: 1005,
1789
+ ABNORMAL: 1006,
1790
+ INVALID_DATA: 1007,
1791
+ POLICY_VIOLATION: 1008,
1792
+ MESSAGE_TOO_BIG: 1009,
1793
+ EXTENSION_REQUIRED: 1010,
1794
+ INTERNAL_ERROR: 1011,
1795
+ SERVICE_RESTART: 1012,
1796
+ TRY_AGAIN_LATER: 1013,
1797
+ BAD_GATEWAY: 1014,
1798
+ TLS_HANDSHAKE_FAIL: 1015
1799
+ };
1800
+ function queueCallback3(callback, error) {
1801
+ if (callback) {
1802
+ queueMicrotask(() => callback(error));
1803
+ }
1804
+ }
1805
+ function createNativeWebSocket(url, protocols) {
1806
+ if (runtime === "node" && typeof globalThis.WebSocket === "undefined") {
1807
+ throw new Error("WebSocket is not available. Please use Node.js 18+ or install ws package.");
1808
+ }
1809
+ return new globalThis.WebSocket(url, protocols);
1810
+ }
1811
+ var WebSocket = class extends import_events2.EventEmitter {
1812
+ constructor(address, protocols, _options) {
1813
+ super();
1814
+ this.readyState = 0 /* CONNECTING */;
1815
+ this.protocol = "";
1816
+ this.extensions = "";
1817
+ this.binaryType = "nodebuffer";
1818
+ this.url = typeof address === "string" ? address : address.toString();
1819
+ const protocolsArray = Array.isArray(protocols) ? protocols : protocols ? [protocols] : void 0;
1820
+ this._socket = createNativeWebSocket(this.url, protocolsArray);
1821
+ this._setupNativeSocket();
1822
+ }
1823
+ _setupNativeSocket() {
1824
+ this._socket.onopen = () => {
1825
+ this.readyState = 1 /* OPEN */;
1826
+ this.emit("open");
1827
+ };
1828
+ this._socket.onmessage = (event) => {
1829
+ const isBinary = event.data instanceof ArrayBuffer || event.data instanceof Blob;
1830
+ this.emit("message", event.data, isBinary);
1831
+ };
1832
+ this._socket.onclose = (event) => {
1833
+ this.readyState = 3 /* CLOSED */;
1834
+ this.emit("close", event.code, event.reason);
1835
+ };
1836
+ this._socket.onerror = () => {
1837
+ this.emit("error", new Error("WebSocket error"));
1838
+ };
1839
+ }
1840
+ /**
1841
+ * Send data through WebSocket
1842
+ */
1843
+ send(data, options, callback) {
1844
+ const cb = typeof options === "function" ? options : callback;
1845
+ if (this.readyState !== 1 /* OPEN */) {
1846
+ return queueCallback3(cb, new Error("WebSocket is not open"));
1847
+ }
1848
+ try {
1849
+ this._socket.send(data);
1850
+ queueCallback3(cb);
1851
+ } catch (error) {
1852
+ queueCallback3(cb, error);
1853
+ }
1854
+ }
1855
+ /**
1856
+ * Close the WebSocket connection
1857
+ */
1858
+ close(code, reason) {
1859
+ if (this.readyState === 3 /* CLOSED */ || this.readyState === 2 /* CLOSING */) {
1860
+ return;
1861
+ }
1862
+ this.readyState = 2 /* CLOSING */;
1863
+ this._socket.close(code, typeof reason === "string" ? reason : reason?.toString());
1864
+ }
1865
+ /**
1866
+ * Pause the socket (no-op for native WebSocket)
1867
+ */
1868
+ pause() {
1869
+ }
1870
+ /**
1871
+ * Resume the socket (no-op for native WebSocket)
1872
+ */
1873
+ resume() {
1874
+ }
1875
+ /**
1876
+ * Send a ping frame (no-op for native WebSocket)
1877
+ */
1878
+ ping(_data, _mask, callback) {
1879
+ queueCallback3(callback);
1880
+ }
1881
+ /**
1882
+ * Send a pong frame (no-op for native WebSocket)
1883
+ */
1884
+ pong(_data, _mask, callback) {
1885
+ queueCallback3(callback);
1886
+ }
1887
+ /**
1888
+ * Terminate the connection
1889
+ */
1890
+ terminate() {
1891
+ this._socket.close();
1892
+ this.readyState = 3 /* CLOSED */;
1893
+ }
1894
+ /**
1895
+ * Get buffered amount
1896
+ */
1897
+ get bufferedAmount() {
1898
+ return this._socket.bufferedAmount || 0;
1899
+ }
1900
+ };
1901
+ var WebSocketServer = class extends import_events2.EventEmitter {
1902
+ constructor(options, callback) {
1903
+ super();
1904
+ this.clients = /* @__PURE__ */ new Set();
1905
+ this.options = options || {};
1906
+ this.path = options?.path || "/";
1907
+ if (runtime === "node") {
1908
+ if (options?.server) {
1909
+ this._httpServer = options.server;
1910
+ this._setupUpgradeHandler();
1911
+ } else if (options?.noServer) {
1912
+ } else {
1913
+ const http2 = require("http");
1914
+ this._httpServer = http2.createServer();
1915
+ this._setupUpgradeHandler();
1916
+ if (options?.port) {
1917
+ this._httpServer.listen(options.port, options.host, callback);
1918
+ }
1919
+ }
1920
+ } else {
1921
+ queueCallback3(callback);
1922
+ }
1923
+ }
1924
+ _setupUpgradeHandler() {
1925
+ this._httpServer.on("upgrade", (request3, socket, head) => {
1926
+ console.log("[WebSocket] Upgrade request:", request3.url, "Expected:", this.path);
1927
+ if (this.path && this.path !== "/" && request3.url !== this.path) {
1928
+ console.log("[WebSocket] Path mismatch, ignoring");
1929
+ return;
1930
+ }
1931
+ this.handleUpgrade(request3, socket, head, (client) => {
1932
+ console.log("[WebSocket] Client connected");
1933
+ this.emit("connection", client, request3);
1934
+ });
1935
+ });
1936
+ }
1937
+ /**
1938
+ * Handle HTTP upgrade for WebSocket
1939
+ */
1940
+ handleUpgrade(request3, socket, _head, callback) {
1941
+ const key = request3.headers["sec-websocket-key"];
1942
+ if (!key) {
1943
+ socket.end("HTTP/1.1 400 Bad Request\r\n\r\n");
1944
+ return;
1945
+ }
1946
+ const crypto = require("crypto");
1947
+ const acceptKey = crypto.createHash("sha1").update(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").digest("base64");
1948
+ const headers = [
1949
+ "HTTP/1.1 101 Switching Protocols",
1950
+ "Upgrade: websocket",
1951
+ "Connection: Upgrade",
1952
+ `Sec-WebSocket-Accept: ${acceptKey}`,
1953
+ "",
1954
+ ""
1955
+ ];
1956
+ socket.write(headers.join("\r\n"));
1957
+ const client = this._createClientFromSocket(socket);
1958
+ if (this.options.clientTracking !== false) {
1959
+ this.clients.add(client);
1960
+ client.on("close", () => {
1961
+ this.clients.delete(client);
1962
+ });
1963
+ }
1964
+ callback(client);
1965
+ }
1966
+ _createClientFromSocket(socket) {
1967
+ const client = Object.create(WebSocket.prototype);
1968
+ import_events2.EventEmitter.call(client);
1969
+ client.readyState = 1 /* OPEN */;
1970
+ client.url = "ws://localhost";
1971
+ client.protocol = "";
1972
+ client.extensions = "";
1973
+ client.binaryType = "nodebuffer";
1974
+ client._socket = socket;
1975
+ socket.on("data", (data) => {
1976
+ try {
1977
+ const message = this._parseFrame(data);
1978
+ if (message) {
1979
+ client.emit("message", message, false);
1980
+ }
1981
+ } catch (error) {
1982
+ client.emit("error", error);
1983
+ }
1984
+ });
1985
+ socket.on("end", () => {
1986
+ client.readyState = 3 /* CLOSED */;
1987
+ client.emit("close", CLOSE_CODES.NORMAL, "");
1988
+ });
1989
+ socket.on("error", (error) => {
1990
+ client.emit("error", error);
1991
+ });
1992
+ client.send = (data, _options, callback) => {
1993
+ try {
1994
+ const frame = this._createFrame(data);
1995
+ socket.write(frame);
1996
+ queueCallback3(callback);
1997
+ } catch (error) {
1998
+ queueCallback3(callback, error);
1999
+ }
2000
+ };
2001
+ client.close = (_code, _reason) => {
2002
+ socket.end();
2003
+ client.readyState = 3 /* CLOSED */;
2004
+ };
2005
+ return client;
2006
+ }
2007
+ _parseFrame(data) {
2008
+ if (data.length < 2) return null;
2009
+ const firstByte = data[0];
2010
+ const secondByte = data[1];
2011
+ const opcode = firstByte & 15;
2012
+ const isMasked = (secondByte & 128) === 128;
2013
+ let payloadLength = secondByte & 127;
2014
+ let offset = 2;
2015
+ if (payloadLength === 126) {
2016
+ payloadLength = data.readUInt16BE(2);
2017
+ offset = 4;
2018
+ } else if (payloadLength === 127) {
2019
+ payloadLength = Number(data.readBigUInt64BE(2));
2020
+ offset = 10;
2021
+ }
2022
+ let payload = data.subarray(offset);
2023
+ if (isMasked) {
2024
+ const maskKey = data.subarray(offset, offset + 4);
2025
+ payload = data.subarray(offset + 4, offset + 4 + payloadLength);
2026
+ for (let i = 0; i < payload.length; i++) {
2027
+ payload[i] ^= maskKey[i % 4];
2028
+ }
2029
+ }
2030
+ if (opcode === 1) {
2031
+ return payload.toString("utf8");
2032
+ }
2033
+ return null;
2034
+ }
2035
+ _createFrame(data) {
2036
+ const payload = typeof data === "string" ? Buffer.from(data) : data;
2037
+ const payloadLength = Buffer.isBuffer(payload) ? payload.length : 0;
2038
+ let frame;
2039
+ let offset = 2;
2040
+ if (payloadLength < 126) {
2041
+ frame = Buffer.allocUnsafe(2 + payloadLength);
2042
+ frame[1] = payloadLength;
2043
+ } else if (payloadLength < 65536) {
2044
+ frame = Buffer.allocUnsafe(4 + payloadLength);
2045
+ frame[1] = 126;
2046
+ frame.writeUInt16BE(payloadLength, 2);
2047
+ offset = 4;
2048
+ } else {
2049
+ frame = Buffer.allocUnsafe(10 + payloadLength);
2050
+ frame[1] = 127;
2051
+ frame.writeBigUInt64BE(BigInt(payloadLength), 2);
2052
+ offset = 10;
2053
+ }
2054
+ frame[0] = 129;
2055
+ if (Buffer.isBuffer(payload)) {
2056
+ payload.copy(frame, offset);
2057
+ }
2058
+ return frame;
2059
+ }
2060
+ /**
2061
+ * Close the server
2062
+ */
2063
+ close(callback) {
2064
+ this.clients.forEach((client) => client.close());
2065
+ this.clients.clear();
2066
+ if (this._httpServer) {
2067
+ this._httpServer.close(callback);
2068
+ } else {
2069
+ this.emit("close");
2070
+ queueCallback3(callback);
2071
+ }
2072
+ }
2073
+ /**
2074
+ * Check if server should handle request
2075
+ */
2076
+ shouldHandle(request3) {
2077
+ if (this.path && request3.url !== this.path) {
2078
+ return false;
2079
+ }
2080
+ return true;
2081
+ }
2082
+ /**
2083
+ * Get server address
2084
+ */
2085
+ address() {
2086
+ if (this._httpServer && this._httpServer.address) {
2087
+ return this._httpServer.address();
2088
+ }
2089
+ return null;
2090
+ }
2091
+ };
2092
+
2093
+ // src/chokidar.ts
2094
+ var import_events3 = require("events");
2095
+ init_runtime();
2096
+ function normalizePath2(path) {
2097
+ return path.replace(/\\/g, "/");
2098
+ }
2099
+ function emitEvent(watcher, eventType, path) {
2100
+ watcher.emit(eventType, path);
2101
+ watcher.emit("all", eventType, path);
2102
+ }
2103
+ function matchesAnyPattern(path, patterns) {
2104
+ return patterns.some((pattern) => matchesPattern(path, pattern));
2105
+ }
2106
+ function handleRenameEvent(watcher, fullPath, fs2) {
2107
+ try {
2108
+ fs2.statSync(fullPath);
2109
+ emitEvent(watcher, "add", fullPath);
2110
+ } catch {
2111
+ emitEvent(watcher, "unlink", fullPath);
2112
+ }
2113
+ }
2114
+ function setupFsWatch(watcher, baseDir, patterns, fs2) {
2115
+ try {
2116
+ const nativeWatcher = fs2.watch(baseDir, { recursive: true }, (eventType, filename) => {
2117
+ if (!filename) return;
2118
+ const fullPath = normalizePath2(`${baseDir}/${filename}`);
2119
+ if (!matchesAnyPattern(fullPath, patterns)) return;
2120
+ if (eventType === "rename") {
2121
+ handleRenameEvent(watcher, fullPath, fs2);
2122
+ } else if (eventType === "change") {
2123
+ emitEvent(watcher, "change", fullPath);
2124
+ }
2125
+ });
2126
+ watcher._setWatcher(nativeWatcher);
2127
+ watcher["_watched"].add(baseDir);
2128
+ queueMicrotask(() => watcher.emit("ready"));
2129
+ } catch (error) {
2130
+ watcher.emit("error", error);
2131
+ }
2132
+ }
2133
+ var FSWatcher = class extends import_events3.EventEmitter {
2134
+ constructor(options) {
2135
+ super();
2136
+ this._closed = false;
2137
+ this._watched = /* @__PURE__ */ new Set();
2138
+ this.options = options || {};
2139
+ }
2140
+ /**
2141
+ * Add paths to be watched
2142
+ */
2143
+ add(paths) {
2144
+ if (this._closed) {
2145
+ throw new Error("Watcher has been closed");
2146
+ }
2147
+ const pathArray = Array.isArray(paths) ? paths : [paths];
2148
+ if (runtime === "node") {
2149
+ if (this._watcher) {
2150
+ this._watcher.add(pathArray);
2151
+ }
2152
+ } else {
2153
+ pathArray.forEach((path) => this._watched.add(path));
2154
+ }
2155
+ return this;
2156
+ }
2157
+ /**
2158
+ * Stop watching paths
2159
+ */
2160
+ unwatch(paths) {
2161
+ if (this._closed) {
2162
+ return this;
2163
+ }
2164
+ const pathArray = Array.isArray(paths) ? paths : [paths];
2165
+ if (runtime === "node") {
2166
+ if (this._watcher) {
2167
+ this._watcher.unwatch(pathArray);
2168
+ }
2169
+ } else {
2170
+ pathArray.forEach((path) => this._watched.delete(path));
2171
+ }
2172
+ return this;
2173
+ }
2174
+ /**
2175
+ * Close the watcher
2176
+ */
2177
+ async close() {
2178
+ if (this._closed) {
2179
+ return;
2180
+ }
2181
+ this._closed = true;
2182
+ if (runtime === "node") {
2183
+ if (this._watcher) {
2184
+ await this._watcher.close();
2185
+ }
2186
+ }
2187
+ this.removeAllListeners();
2188
+ }
2189
+ /**
2190
+ * Get watched paths
2191
+ */
2192
+ getWatched() {
2193
+ if (runtime === "node" && this._watcher) {
2194
+ return this._watcher.getWatched();
2195
+ }
2196
+ const result = {};
2197
+ this._watched.forEach((path) => {
2198
+ const dir = path.substring(0, path.lastIndexOf("/")) || ".";
2199
+ const file = path.substring(path.lastIndexOf("/") + 1);
2200
+ if (!result[dir]) {
2201
+ result[dir] = [];
209
2202
  }
2203
+ result[dir].push(file);
2204
+ });
2205
+ return result;
2206
+ }
2207
+ /**
2208
+ * Internal method to set native watcher
2209
+ * @internal
2210
+ */
2211
+ _setWatcher(watcher) {
2212
+ this._watcher = watcher;
2213
+ }
2214
+ };
2215
+ function getBaseDirectory(pattern) {
2216
+ const parts = pattern.split(/[\\\/]/);
2217
+ let baseDir = "";
2218
+ for (const part of parts) {
2219
+ if (part.includes("*") || part.includes("?")) {
2220
+ break;
210
2221
  }
2222
+ baseDir = baseDir ? `${baseDir}/${part}` : part;
211
2223
  }
212
- return null;
2224
+ return baseDir || ".";
213
2225
  }
214
- async function loadConfigFile(configPath) {
215
- const ext = configPath.split(".").pop();
216
- if (ext === "json") {
217
- const content = (0, import_fs.readFileSync)(configPath, "utf-8");
218
- return JSON.parse(content);
219
- } else {
220
- if (ext === "ts") {
2226
+ function matchesPattern(filePath, pattern) {
2227
+ const regexPattern = normalizePath2(pattern).replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*").replace(/\?/g, ".");
2228
+ const regex = new RegExp(`^${regexPattern}$`);
2229
+ const normalizedPath = normalizePath2(filePath);
2230
+ return regex.test(normalizedPath);
2231
+ }
2232
+ function watch(paths, options) {
2233
+ const watcher = new FSWatcher(options);
2234
+ const pathArray = Array.isArray(paths) ? paths : [paths];
2235
+ const watchMap = /* @__PURE__ */ new Map();
2236
+ pathArray.forEach((path) => {
2237
+ const baseDir = getBaseDirectory(path);
2238
+ if (!watchMap.has(baseDir)) {
2239
+ watchMap.set(baseDir, []);
2240
+ }
2241
+ watchMap.get(baseDir).push(path);
2242
+ });
2243
+ if (runtime === "node") {
2244
+ const fs2 = require("fs");
2245
+ watchMap.forEach((patterns, baseDir) => setupFsWatch(watcher, baseDir, patterns, fs2));
2246
+ } else if (runtime === "bun") {
2247
+ const fs2 = require("fs");
2248
+ watchMap.forEach((patterns, baseDir) => setupFsWatch(watcher, baseDir, patterns, fs2));
2249
+ } else if (runtime === "deno") {
2250
+ const baseDirs = Array.from(watchMap.keys());
2251
+ const allPatterns = Array.from(watchMap.values()).flat();
2252
+ (async () => {
221
2253
  try {
222
- const { pathToFileURL } = await import("url");
223
- const configModule = await import(pathToFileURL(configPath).href);
224
- return configModule.default || configModule;
225
- } catch {
226
- console.error("TypeScript config files require tsx or ts-node to be installed.");
227
- console.error("Install with: npm install -D tsx");
228
- console.error("Or use a .js or .json config file instead.");
229
- throw new Error("Cannot load TypeScript config without tsx/ts-node");
2254
+ const denoWatcher = Deno.watchFs(baseDirs);
2255
+ for await (const event of denoWatcher) {
2256
+ if (watcher["_closed"]) break;
2257
+ for (const path of event.paths) {
2258
+ const normalizedPath = normalizePath2(path);
2259
+ if (!matchesAnyPattern(normalizedPath, allPatterns)) continue;
2260
+ switch (event.kind) {
2261
+ case "create":
2262
+ emitEvent(watcher, "add", path);
2263
+ break;
2264
+ case "modify":
2265
+ emitEvent(watcher, "change", path);
2266
+ break;
2267
+ case "remove":
2268
+ emitEvent(watcher, "unlink", path);
2269
+ break;
2270
+ }
2271
+ }
2272
+ }
2273
+ } catch (error) {
2274
+ if (!watcher["_closed"]) {
2275
+ watcher.emit("error", error);
2276
+ }
230
2277
  }
231
- } else {
232
- const { pathToFileURL } = await import("url");
233
- const configModule = await import(pathToFileURL(configPath).href);
234
- return configModule.default || configModule;
235
- }
2278
+ })();
2279
+ pathArray.forEach((path) => watcher.add(path));
2280
+ queueMicrotask(() => watcher.emit("ready"));
236
2281
  }
2282
+ return watcher;
237
2283
  }
238
- function mergeConfig(config, cliArgs) {
239
- if (!config) {
240
- return cliArgs;
2284
+
2285
+ // src/server.ts
2286
+ init_fs();
2287
+ init_path();
2288
+
2289
+ // src/mime-types.ts
2290
+ init_runtime();
2291
+ var MIME_TYPES = {
2292
+ // Text
2293
+ "txt": "text/plain",
2294
+ "html": "text/html",
2295
+ "htm": "text/html",
2296
+ "css": "text/css",
2297
+ "js": "text/javascript",
2298
+ "mjs": "text/javascript",
2299
+ "json": "application/json",
2300
+ "xml": "application/xml",
2301
+ "csv": "text/csv",
2302
+ "md": "text/markdown",
2303
+ "markdown": "text/x-markdown",
2304
+ // Images
2305
+ "png": "image/png",
2306
+ "jpg": "image/jpeg",
2307
+ "jpeg": "image/jpeg",
2308
+ "gif": "image/gif",
2309
+ "svg": "image/svg+xml",
2310
+ "webp": "image/webp",
2311
+ "ico": "image/x-icon",
2312
+ "bmp": "image/bmp",
2313
+ "tiff": "image/tiff",
2314
+ "tif": "image/tiff",
2315
+ // Audio
2316
+ "mp3": "audio/mpeg",
2317
+ "wav": "audio/wav",
2318
+ "ogg": "audio/ogg",
2319
+ "aac": "audio/aac",
2320
+ "m4a": "audio/mp4",
2321
+ "flac": "audio/flac",
2322
+ // Video
2323
+ "mp4": "video/mp4",
2324
+ "webm": "video/webm",
2325
+ "avi": "video/x-msvideo",
2326
+ "mov": "video/quicktime",
2327
+ "mkv": "video/x-matroska",
2328
+ "flv": "video/x-flv",
2329
+ // Application
2330
+ "pdf": "application/pdf",
2331
+ "zip": "application/zip",
2332
+ "gz": "application/gzip",
2333
+ "tar": "application/x-tar",
2334
+ "rar": "application/x-rar-compressed",
2335
+ "7z": "application/x-7z-compressed",
2336
+ // Documents
2337
+ "doc": "application/msword",
2338
+ "docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
2339
+ "xls": "application/vnd.ms-excel",
2340
+ "xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
2341
+ "ppt": "application/vnd.ms-powerpoint",
2342
+ "pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
2343
+ // Fonts
2344
+ "woff": "font/woff",
2345
+ "woff2": "font/woff2",
2346
+ "ttf": "font/ttf",
2347
+ "otf": "font/otf",
2348
+ "eot": "application/vnd.ms-fontobject",
2349
+ // Web
2350
+ "wasm": "application/wasm",
2351
+ "manifest": "application/manifest+json",
2352
+ // Binary
2353
+ "bin": "application/octet-stream",
2354
+ "exe": "application/x-msdownload",
2355
+ "dll": "application/x-msdownload",
2356
+ // TypeScript/Modern JS
2357
+ "ts": "text/typescript",
2358
+ "tsx": "text/tsx",
2359
+ "jsx": "text/jsx"
2360
+ };
2361
+ var TYPE_TO_EXTENSIONS = {};
2362
+ for (const ext in MIME_TYPES) {
2363
+ const type = MIME_TYPES[ext];
2364
+ if (!TYPE_TO_EXTENSIONS[type]) {
2365
+ TYPE_TO_EXTENSIONS[type] = [];
241
2366
  }
242
- return {
243
- ...config,
244
- ...Object.fromEntries(
245
- Object.entries(cliArgs).filter(([_, v]) => v !== void 0)
246
- )
247
- };
2367
+ TYPE_TO_EXTENSIONS[type].push(ext);
2368
+ }
2369
+ function getExtension(path) {
2370
+ const match = /\.([^./\\]+)$/.exec(path);
2371
+ return match ? match[1].toLowerCase() : "";
2372
+ }
2373
+ function lookup(path) {
2374
+ const ext = getExtension(path) || path.toLowerCase();
2375
+ return MIME_TYPES[ext] || false;
248
2376
  }
249
2377
 
250
2378
  // src/server.ts
251
- var import_http = require("http");
252
- var import_https = require("https");
253
- var import_ws = require("ws");
254
- var import_chokidar = require("chokidar");
255
- var import_promises = require("fs/promises");
256
- var import_path2 = require("path");
257
- var import_mime_types = require("mime-types");
258
- var import_esbuild = require("esbuild");
2379
+ init_runtime();
259
2380
 
260
2381
  // src/dom.ts
2382
+ function resolveElement(rootElement) {
2383
+ return typeof rootElement === "string" ? document.getElementById(rootElement.replace("#", "")) : rootElement;
2384
+ }
2385
+ function ensureElement(el, rootElement) {
2386
+ if (!el) {
2387
+ throw new Error(`Element not found: ${rootElement}`);
2388
+ }
2389
+ return el;
2390
+ }
2391
+ function shouldSkipChild(child) {
2392
+ return child == null || child === false;
2393
+ }
2394
+ function isPrimitiveJson(json2) {
2395
+ return json2 == null || typeof json2 === "boolean" || typeof json2 === "string" || typeof json2 === "number";
2396
+ }
261
2397
  var DomNode = class {
262
2398
  constructor() {
263
2399
  this.elementCache = /* @__PURE__ */ new WeakMap();
@@ -309,11 +2445,11 @@ var DomNode = class {
309
2445
  const renderChildren = (target) => {
310
2446
  for (let i = 0; i < len; i++) {
311
2447
  const child = children[i];
312
- if (child == null || child === false) continue;
2448
+ if (shouldSkipChild(child)) continue;
313
2449
  if (Array.isArray(child)) {
314
2450
  for (let j = 0, cLen = child.length; j < cLen; j++) {
315
2451
  const c = child[j];
316
- c != null && c !== false && this.renderToDOM(c, target);
2452
+ !shouldSkipChild(c) && this.renderToDOM(c, target);
317
2453
  }
318
2454
  } else {
319
2455
  this.renderToDOM(child, target);
@@ -330,10 +2466,8 @@ var DomNode = class {
330
2466
  parent.appendChild(el);
331
2467
  }
332
2468
  render(rootElement, vNode) {
333
- const el = typeof rootElement === "string" ? document.getElementById(rootElement.replace("#", "")) : rootElement;
334
- if (!el) {
335
- throw new Error(`Element not found: ${rootElement}`);
336
- }
2469
+ const el = ensureElement(resolveElement(rootElement), rootElement);
2470
+ el.innerHTML = "";
337
2471
  if (vNode.children && vNode.children.length > 500) {
338
2472
  const fragment = document.createDocumentFragment();
339
2473
  this.renderToDOM(vNode, fragment);
@@ -344,10 +2478,7 @@ var DomNode = class {
344
2478
  return el;
345
2479
  }
346
2480
  batchRender(rootElement, vNodes) {
347
- const el = typeof rootElement === "string" ? document.getElementById(rootElement.replace("#", "")) : rootElement;
348
- if (!el) {
349
- throw new Error(`Element not found: ${rootElement}`);
350
- }
2481
+ const el = ensureElement(resolveElement(rootElement), rootElement);
351
2482
  const len = vNodes.length;
352
2483
  if (len > 3e3) {
353
2484
  const fragment = document.createDocumentFragment();
@@ -376,10 +2507,7 @@ var DomNode = class {
376
2507
  return el;
377
2508
  }
378
2509
  renderChunked(rootElement, vNodes, chunkSize = 5e3, onProgress) {
379
- const el = typeof rootElement === "string" ? document.getElementById(rootElement.replace("#", "")) : rootElement;
380
- if (!el) {
381
- throw new Error(`Element not found: ${rootElement}`);
382
- }
2510
+ const el = ensureElement(resolveElement(rootElement), rootElement);
383
2511
  const len = vNodes.length;
384
2512
  let index = 0;
385
2513
  const renderChunk = () => {
@@ -489,7 +2617,7 @@ var DomNode = class {
489
2617
  const end = Math.min(items.length, Math.ceil((scrollTop + viewportHeight) / itemHeight) + bufferSize);
490
2618
  return { start, end };
491
2619
  };
492
- const render = () => {
2620
+ const render2 = () => {
493
2621
  const { start, end } = getVisibleRange();
494
2622
  const wrapper = document.createElement("div");
495
2623
  wrapper.style.cssText = `height:${totalHeight}px;position:relative`;
@@ -504,12 +2632,12 @@ var DomNode = class {
504
2632
  };
505
2633
  const scrollHandler = () => {
506
2634
  scrollTop = container.scrollTop;
507
- requestAnimationFrame(render);
2635
+ requestAnimationFrame(render2);
508
2636
  };
509
2637
  container.addEventListener("scroll", scrollHandler);
510
- render();
2638
+ render2();
511
2639
  return {
512
- render,
2640
+ render: render2,
513
2641
  destroy: () => {
514
2642
  container.removeEventListener("scroll", scrollHandler);
515
2643
  container.innerHTML = "";
@@ -586,10 +2714,10 @@ var DomNode = class {
586
2714
  if (pretty && hasComplexChildren) {
587
2715
  html += newLine;
588
2716
  for (const child of resolvedChildren) {
589
- if (child == null || child === false) continue;
2717
+ if (shouldSkipChild(child)) continue;
590
2718
  if (Array.isArray(child)) {
591
2719
  for (const c of child) {
592
- if (c != null && c !== false) {
2720
+ if (!shouldSkipChild(c)) {
593
2721
  html += this.renderToString(c, { pretty, indent: indent + 1 });
594
2722
  }
595
2723
  }
@@ -600,10 +2728,10 @@ var DomNode = class {
600
2728
  html += indentStr;
601
2729
  } else {
602
2730
  for (const child of resolvedChildren) {
603
- if (child == null || child === false) continue;
2731
+ if (shouldSkipChild(child)) continue;
604
2732
  if (Array.isArray(child)) {
605
2733
  for (const c of child) {
606
- if (c != null && c !== false) {
2734
+ if (!shouldSkipChild(c)) {
607
2735
  html += this.renderToString(c, { pretty: false, indent: 0 });
608
2736
  }
609
2737
  }
@@ -744,17 +2872,14 @@ var DomNode = class {
744
2872
  }
745
2873
  return currentValue;
746
2874
  }
747
- jsonToVNode(json) {
748
- if (this.isState(json)) {
749
- return this.createReactiveChild(json, (v) => v);
2875
+ jsonToVNode(json2) {
2876
+ if (this.isState(json2)) {
2877
+ return this.createReactiveChild(json2, (v) => v);
750
2878
  }
751
- if (json == null || typeof json === "boolean") {
752
- return json;
2879
+ if (isPrimitiveJson(json2)) {
2880
+ return json2;
753
2881
  }
754
- if (typeof json === "string" || typeof json === "number") {
755
- return json;
756
- }
757
- const { tag, attributes = {}, children } = json;
2882
+ const { tag, attributes = {}, children } = json2;
758
2883
  const props = {};
759
2884
  for (const key in attributes) {
760
2885
  const value = attributes[key];
@@ -790,17 +2915,14 @@ var DomNode = class {
790
2915
  }
791
2916
  return { tagName: tag, props, children: childrenArray };
792
2917
  }
793
- vNodeJsonToVNode(json) {
794
- if (this.isState(json)) {
795
- return this.createReactiveChild(json, (v) => v);
796
- }
797
- if (json == null || typeof json === "boolean") {
798
- return json;
2918
+ vNodeJsonToVNode(json2) {
2919
+ if (this.isState(json2)) {
2920
+ return this.createReactiveChild(json2, (v) => v);
799
2921
  }
800
- if (typeof json === "string" || typeof json === "number") {
801
- return json;
2922
+ if (isPrimitiveJson(json2)) {
2923
+ return json2;
802
2924
  }
803
- const { tagName, props = {}, children = [] } = json;
2925
+ const { tagName, props = {}, children = [] } = json2;
804
2926
  const resolvedProps = {};
805
2927
  for (const key in props) {
806
2928
  const value = props[key];
@@ -819,57 +2941,28 @@ var DomNode = class {
819
2941
  }
820
2942
  return { tagName, props: resolvedProps, children: childrenArray };
821
2943
  }
822
- renderJson(rootElement, json) {
823
- const vNode = this.jsonToVNode(json);
2944
+ renderJson(rootElement, json2) {
2945
+ const vNode = this.jsonToVNode(json2);
824
2946
  if (!vNode || typeof vNode !== "object" || !("tagName" in vNode)) {
825
2947
  throw new Error("Invalid JSON structure");
826
2948
  }
827
2949
  return this.render(rootElement, vNode);
828
2950
  }
829
- renderVNode(rootElement, json) {
830
- const vNode = this.vNodeJsonToVNode(json);
2951
+ renderVNode(rootElement, json2) {
2952
+ const vNode = this.vNodeJsonToVNode(json2);
831
2953
  if (!vNode || typeof vNode !== "object" || !("tagName" in vNode)) {
832
2954
  throw new Error("Invalid VNode JSON structure");
833
2955
  }
834
2956
  return this.render(rootElement, vNode);
835
2957
  }
836
- renderJsonToString(json, options = {}) {
837
- const vNode = this.jsonToVNode(json);
2958
+ renderJsonToString(json2, options = {}) {
2959
+ const vNode = this.jsonToVNode(json2);
838
2960
  return this.renderToString(vNode, options);
839
2961
  }
840
- renderVNodeToString(json, options = {}) {
841
- const vNode = this.vNodeJsonToVNode(json);
2962
+ renderVNodeToString(json2, options = {}) {
2963
+ const vNode = this.vNodeJsonToVNode(json2);
842
2964
  return this.renderToString(vNode, options);
843
2965
  }
844
- // Server-side rendering - Render complete HTML document VNode to document
845
- renderServer(vNode) {
846
- if (typeof vNode !== "object" || vNode === null || !("tagName" in vNode)) throw new Error("renderServer requires a VNode with html tag");
847
- if (vNode.tagName !== "html") throw new Error("renderServer requires a VNode with html tag as root");
848
- const htmlVNode = vNode;
849
- let headVNode = null, bodyVNode = null;
850
- for (const child of htmlVNode.children || []) {
851
- if (typeof child === "object" && child !== null && "tagName" in child) {
852
- if (child.tagName === "head") headVNode = child;
853
- if (child.tagName === "body") bodyVNode = child;
854
- }
855
- }
856
- if (htmlVNode.props) for (const k in htmlVNode.props) {
857
- const v = htmlVNode.props[k];
858
- if (v !== void 0 && v !== null && v !== false) document.documentElement.setAttribute(k, String(v));
859
- }
860
- if (headVNode) {
861
- document.head.innerHTML = "";
862
- for (const child of headVNode.children || []) this.renderToDOM(child, document.head);
863
- }
864
- if (bodyVNode) {
865
- document.body.innerHTML = "";
866
- if (bodyVNode.props) for (const k in bodyVNode.props) {
867
- const v = bodyVNode.props[k];
868
- if (v !== void 0 && v !== null && v !== false) document.body.setAttribute(k, String(v));
869
- }
870
- for (const child of bodyVNode.children || []) this.renderToDOM(child, document.body);
871
- }
872
- }
873
2966
  // Generate complete HTML document as string (for SSR)
874
2967
  renderToHTMLDocument(vNode, options = {}) {
875
2968
  const { title = "", meta = [], links = [], scripts = [], styles = [], lang = "en", head = "", bodyAttrs = {}, pretty = false } = options;
@@ -922,8 +3015,49 @@ var DomNode = class {
922
3015
  }
923
3016
  };
924
3017
  var dom = new DomNode();
3018
+ var render = dom.render.bind(dom);
3019
+ var renderToString = dom.renderToString.bind(dom);
925
3020
 
926
3021
  // src/server.ts
3022
+ var json = (res, data, status = 200) => (res.writeHead(status, { "Content-Type": "application/json" }), res.end(JSON.stringify(data)));
3023
+ var sendError = (res, code, msg) => {
3024
+ res.writeHead(code, { "Content-Type": "text/plain" });
3025
+ res.end(msg);
3026
+ };
3027
+ var send404 = (res, msg = "Not Found") => sendError(res, 404, msg);
3028
+ var send403 = (res, msg = "Forbidden") => sendError(res, 403, msg);
3029
+ var send500 = (res, msg = "Internal Server Error") => sendError(res, 500, msg);
3030
+ var createElitImportMap = (basePath = "", mode = "dev") => {
3031
+ const srcPath = mode === "dev" ? basePath ? `${basePath}/node_modules/elit/src` : "/node_modules/elit/src" : basePath ? `${basePath}/dist` : "/dist";
3032
+ const fileExt = mode === "dev" ? ".ts" : ".mjs";
3033
+ return `<script type="importmap">{"imports":{"elit":"${srcPath}/index${fileExt}","elit/":"${srcPath}/","elit/dom":"${srcPath}/dom${fileExt}","elit/state":"${srcPath}/state${fileExt}","elit/style":"${srcPath}/style${fileExt}","elit/el":"${srcPath}/el${fileExt}","elit/router":"${srcPath}/router${fileExt}","elit/hmr":"${srcPath}/hmr${fileExt}","elit/types":"${srcPath}/types${fileExt}"}}</script>`;
3034
+ };
3035
+ var createHMRScript = (port, wsPath) => `<script>(function(){let ws;let retries=0;let maxRetries=5;function connect(){ws=new WebSocket('ws://'+window.location.hostname+':${port}${wsPath}');ws.onopen=()=>{console.log('[Elit HMR] Connected');retries=0};ws.onmessage=(e)=>{const d=JSON.parse(e.data);if(d.type==='update'){console.log('[Elit HMR] File updated:',d.path);window.location.reload()}else if(d.type==='reload'){console.log('[Elit HMR] Reloading...');window.location.reload()}else if(d.type==='error')console.error('[Elit HMR] Error:',d.error)};ws.onclose=()=>{if(retries<maxRetries){retries++;setTimeout(connect,1000*retries)}else if(retries===maxRetries){console.log('[Elit HMR] Connection closed. Start dev server to reconnect.')}};ws.onerror=()=>{ws.close()}}connect()})();</script>`;
3036
+ var rewriteRelativePaths = (html, basePath) => {
3037
+ if (!basePath) return html;
3038
+ html = html.replace(/(<script[^>]+src=["'])(?!https?:\/\/|\/)(\.\/)?([^"']+)(["'])/g, `$1${basePath}/$3$4`);
3039
+ html = html.replace(/(<link[^>]+href=["'])(?!https?:\/\/|\/)(\.\/)?([^"']+)(["'])/g, `$1${basePath}/$3$4`);
3040
+ return html;
3041
+ };
3042
+ var normalizeBasePath = (basePath) => basePath && basePath !== "/" ? basePath : "";
3043
+ async function findSpecialDir(startDir, targetDir) {
3044
+ let currentDir = startDir;
3045
+ const maxLevels = 5;
3046
+ for (let i = 0; i < maxLevels; i++) {
3047
+ const targetPath = resolve(currentDir, targetDir);
3048
+ try {
3049
+ const stats = await stat(targetPath);
3050
+ if (stats.isDirectory()) {
3051
+ return currentDir;
3052
+ }
3053
+ } catch {
3054
+ }
3055
+ const parentDir = resolve(currentDir, "..");
3056
+ if (parentDir === currentDir) break;
3057
+ currentDir = parentDir;
3058
+ }
3059
+ return null;
3060
+ }
927
3061
  function rewritePath(path, pathRewrite) {
928
3062
  if (!pathRewrite) return path;
929
3063
  for (const [from, to] of Object.entries(pathRewrite)) {
@@ -944,34 +3078,49 @@ function createProxyHandler(proxyConfigs) {
944
3078
  try {
945
3079
  const targetUrl = new URL(target);
946
3080
  const isHttps = targetUrl.protocol === "https:";
947
- const requestLib = isHttps ? import_https.request : import_http.request;
3081
+ const requestLib = isHttps ? request2 : request;
948
3082
  let proxyPath = rewritePath(url, pathRewrite);
949
- const proxyReqOptions = {
950
- hostname: targetUrl.hostname,
951
- port: targetUrl.port || (isHttps ? 443 : 80),
952
- path: proxyPath,
953
- method: req.method,
954
- headers: {
955
- ...req.headers,
956
- ...headers || {}
3083
+ const proxyUrl = `${isHttps ? "https" : "http"}://${targetUrl.hostname}:${targetUrl.port || (isHttps ? 443 : 80)}${proxyPath}`;
3084
+ const proxyReqHeaders = {};
3085
+ for (const [key, value] of Object.entries(req.headers)) {
3086
+ if (value !== void 0) {
3087
+ proxyReqHeaders[key] = value;
957
3088
  }
958
- };
3089
+ }
3090
+ if (headers) {
3091
+ for (const [key, value] of Object.entries(headers)) {
3092
+ if (value !== void 0) {
3093
+ proxyReqHeaders[key] = value;
3094
+ }
3095
+ }
3096
+ }
959
3097
  if (changeOrigin) {
960
- proxyReqOptions.headers.host = targetUrl.host;
3098
+ proxyReqHeaders.host = targetUrl.host;
961
3099
  }
962
- delete proxyReqOptions.headers["host"];
963
- const proxyReq = requestLib(proxyReqOptions, (proxyRes) => {
964
- res.writeHead(proxyRes.statusCode || 200, proxyRes.headers);
965
- proxyRes.pipe(res);
3100
+ delete proxyReqHeaders["host"];
3101
+ const proxyReqOptions = {
3102
+ method: req.method,
3103
+ headers: proxyReqHeaders
3104
+ };
3105
+ const proxyReq = requestLib(proxyUrl, proxyReqOptions, (proxyRes) => {
3106
+ const outgoingHeaders = {};
3107
+ for (const [key, value] of Object.entries(proxyRes.headers)) {
3108
+ if (value !== void 0) {
3109
+ outgoingHeaders[key] = value;
3110
+ }
3111
+ }
3112
+ res.writeHead(proxyRes.statusCode || 200, outgoingHeaders);
3113
+ proxyRes.on("data", (chunk) => res.write(chunk));
3114
+ proxyRes.on("end", () => res.end());
966
3115
  });
967
3116
  proxyReq.on("error", (error) => {
968
3117
  console.error("[Proxy] Error proxying %s to %s:", url, target, error.message);
969
3118
  if (!res.headersSent) {
970
- res.writeHead(502, { "Content-Type": "application/json" });
971
- res.end(JSON.stringify({ error: "Bad Gateway", message: "Proxy error" }));
3119
+ json(res, { error: "Bad Gateway", message: "Proxy error" }, 502);
972
3120
  }
973
3121
  });
974
- req.pipe(proxyReq);
3122
+ req.on("data", (chunk) => proxyReq.write(chunk));
3123
+ req.on("end", () => proxyReq.end());
975
3124
  return true;
976
3125
  } catch (error) {
977
3126
  console.error("[Proxy] Invalid proxy configuration for %s:", path, error);
@@ -1017,10 +3166,10 @@ var SharedState = class {
1017
3166
  }
1018
3167
  broadcast() {
1019
3168
  const message = JSON.stringify({ type: "state:update", key: this.key, value: this._value, timestamp: Date.now() });
1020
- this.listeners.forEach((ws) => ws.readyState === import_ws.WebSocket.OPEN && ws.send(message));
3169
+ this.listeners.forEach((ws) => ws.readyState === 1 /* OPEN */ && ws.send(message));
1021
3170
  }
1022
3171
  sendTo(ws) {
1023
- if (ws.readyState === import_ws.WebSocket.OPEN) {
3172
+ if (ws.readyState === 1 /* OPEN */) {
1024
3173
  ws.send(JSON.stringify({ type: "state:init", key: this.key, value: this._value, timestamp: Date.now() }));
1025
3174
  }
1026
3175
  }
@@ -1086,13 +3235,14 @@ var defaultOptions = {
1086
3235
  ignore: ["node_modules/**", "dist/**", ".git/**", "**/*.d.ts"],
1087
3236
  logging: true,
1088
3237
  middleware: [],
1089
- worker: []
3238
+ worker: [],
3239
+ mode: "dev"
1090
3240
  };
1091
3241
  function createDevServer(options) {
1092
3242
  const config = { ...defaultOptions, ...options };
1093
3243
  const wsClients = /* @__PURE__ */ new Set();
1094
3244
  const stateManager = new StateManager();
1095
- const clientsToNormalize = config.clients?.length ? config.clients : config.root ? [{ root: config.root, basePath: config.basePath || "", ssr: config.ssr, proxy: config.proxy }] : null;
3245
+ const clientsToNormalize = config.clients?.length ? config.clients : config.root ? [{ root: config.root, basePath: config.basePath || "", index: config.index, ssr: config.ssr, api: config.api, proxy: config.proxy, mode: config.mode }] : null;
1096
3246
  if (!clientsToNormalize) throw new Error('DevServerOptions must include either "clients" array or "root" directory');
1097
3247
  const normalizedClients = clientsToNormalize.map((client) => {
1098
3248
  let basePath = client.basePath || "";
@@ -1101,22 +3251,28 @@ function createDevServer(options) {
1101
3251
  while (basePath.endsWith("/")) basePath = basePath.slice(0, -1);
1102
3252
  basePath = basePath ? "/" + basePath : "";
1103
3253
  }
3254
+ let indexPath = client.index;
3255
+ if (indexPath) {
3256
+ indexPath = indexPath.replace(/^\.\//, "/");
3257
+ if (!indexPath.startsWith("/")) {
3258
+ indexPath = "/" + indexPath;
3259
+ }
3260
+ }
1104
3261
  return {
1105
3262
  root: client.root,
1106
3263
  basePath,
3264
+ index: indexPath,
1107
3265
  ssr: client.ssr,
1108
- proxyHandler: client.proxy ? createProxyHandler(client.proxy) : void 0
3266
+ api: client.api,
3267
+ proxyHandler: client.proxy ? createProxyHandler(client.proxy) : void 0,
3268
+ mode: client.mode || "dev"
1109
3269
  };
1110
3270
  });
1111
3271
  const globalProxyHandler = config.proxy ? createProxyHandler(config.proxy) : null;
1112
- const server = (0, import_http.createServer)(async (req, res) => {
3272
+ const server = createServer(async (req, res) => {
1113
3273
  const originalUrl = req.url || "/";
1114
3274
  const matchedClient = normalizedClients.find((c) => c.basePath && originalUrl.startsWith(c.basePath)) || normalizedClients.find((c) => !c.basePath);
1115
- if (!matchedClient) {
1116
- res.writeHead(404, { "Content-Type": "text/plain" });
1117
- res.end("404 Not Found");
1118
- return;
1119
- }
3275
+ if (!matchedClient) return send404(res, "404 Not Found");
1120
3276
  if (matchedClient.proxyHandler) {
1121
3277
  try {
1122
3278
  const proxied = await matchedClient.proxyHandler(req, res);
@@ -1140,42 +3296,52 @@ function createDevServer(options) {
1140
3296
  }
1141
3297
  }
1142
3298
  const url = matchedClient.basePath ? originalUrl.slice(matchedClient.basePath.length) || "/" : originalUrl;
3299
+ if (matchedClient.api && url.startsWith("/api")) {
3300
+ const handled = await matchedClient.api.handle(req, res);
3301
+ if (handled) return;
3302
+ }
1143
3303
  if (config.api && url.startsWith("/api")) {
1144
3304
  const handled = await config.api.handle(req, res);
1145
3305
  if (handled) return;
1146
3306
  }
1147
- let filePath = url === "/" ? "/index.html" : url;
3307
+ let filePath;
3308
+ if (url === "/" && matchedClient.ssr && !matchedClient.index) {
3309
+ return serveSSR(res, matchedClient);
3310
+ } else {
3311
+ filePath = url === "/" ? matchedClient.index || "/index.html" : url;
3312
+ }
1148
3313
  filePath = filePath.split("?")[0];
1149
3314
  if (config.logging && filePath === "/src/pages") {
1150
3315
  console.log(`[DEBUG] Request for /src/pages received`);
1151
3316
  }
1152
3317
  if (filePath.includes("\0")) {
1153
3318
  if (config.logging) console.log(`[403] Rejected path with null byte: ${filePath}`);
1154
- res.writeHead(403, { "Content-Type": "text/plain" });
1155
- res.end("403 Forbidden");
1156
- return;
3319
+ return send403(res, "403 Forbidden");
1157
3320
  }
1158
3321
  const isDistRequest = filePath.startsWith("/dist/");
3322
+ const isNodeModulesRequest = filePath.startsWith("/node_modules/");
1159
3323
  let normalizedPath;
1160
- const tempPath = (0, import_path2.normalize)(filePath).replace(/\\/g, "/").replace(/^\/+/, "");
3324
+ const tempPath = normalize(filePath).replace(/\\/g, "/").replace(/^\/+/, "");
1161
3325
  if (tempPath.includes("..")) {
1162
3326
  if (config.logging) console.log(`[403] Path traversal attempt: ${filePath}`);
1163
- res.writeHead(403, { "Content-Type": "text/plain" });
1164
- res.end("403 Forbidden");
1165
- return;
3327
+ return send403(res, "403 Forbidden");
1166
3328
  }
1167
3329
  normalizedPath = tempPath;
1168
- const rootDir = await (0, import_promises.realpath)((0, import_path2.resolve)(matchedClient.root));
1169
- const baseDir = isDistRequest ? await (0, import_promises.realpath)((0, import_path2.resolve)(matchedClient.root, "..")) : rootDir;
3330
+ const rootDir = await realpath(resolve(matchedClient.root));
3331
+ let baseDir = rootDir;
3332
+ if (isDistRequest || isNodeModulesRequest) {
3333
+ const targetDir = isDistRequest ? "dist" : "node_modules";
3334
+ const foundDir = await findSpecialDir(matchedClient.root, targetDir);
3335
+ baseDir = foundDir ? await realpath(foundDir) : rootDir;
3336
+ }
1170
3337
  let fullPath;
1171
3338
  try {
1172
- fullPath = await (0, import_promises.realpath)((0, import_path2.resolve)((0, import_path2.join)(baseDir, normalizedPath)));
1173
- if (!fullPath.startsWith(baseDir.endsWith(import_path2.sep) ? baseDir : baseDir + import_path2.sep)) {
1174
- if (config.logging) console.log(`[403] File access outside of root: ${fullPath}`);
1175
- res.writeHead(403, { "Content-Type": "text/plain" });
1176
- res.end("403 Forbidden");
1177
- return;
3339
+ const unresolvedPath = resolve(join(baseDir, normalizedPath));
3340
+ if (!unresolvedPath.startsWith(baseDir.endsWith(sep) ? baseDir : baseDir + sep)) {
3341
+ if (config.logging) console.log(`[403] File access outside of root (before symlink): ${unresolvedPath}`);
3342
+ return send403(res, "403 Forbidden");
1178
3343
  }
3344
+ fullPath = await realpath(unresolvedPath);
1179
3345
  if (config.logging && filePath === "/src/pages") {
1180
3346
  console.log(`[DEBUG] Initial resolve succeeded: ${fullPath}`);
1181
3347
  }
@@ -1187,12 +3353,10 @@ function createDevServer(options) {
1187
3353
  if (normalizedPath.endsWith(".js")) {
1188
3354
  const tsPath = normalizedPath.replace(/\.js$/, ".ts");
1189
3355
  try {
1190
- const tsFullPath = await (0, import_promises.realpath)((0, import_path2.resolve)((0, import_path2.join)(baseDir, tsPath)));
1191
- if (!tsFullPath.startsWith(baseDir.endsWith(import_path2.sep) ? baseDir : baseDir + import_path2.sep)) {
3356
+ const tsFullPath = await realpath(resolve(join(baseDir, tsPath)));
3357
+ if (!tsFullPath.startsWith(baseDir.endsWith(sep) ? baseDir : baseDir + sep)) {
1192
3358
  if (config.logging) console.log(`[403] Fallback TS path outside of root: ${tsFullPath}`);
1193
- res.writeHead(403, { "Content-Type": "text/plain" });
1194
- res.end("403 Forbidden");
1195
- return;
3359
+ return send403(res, "403 Forbidden");
1196
3360
  }
1197
3361
  resolvedPath = tsFullPath;
1198
3362
  } catch {
@@ -1200,19 +3364,19 @@ function createDevServer(options) {
1200
3364
  }
1201
3365
  if (!resolvedPath && !normalizedPath.includes(".")) {
1202
3366
  try {
1203
- resolvedPath = await (0, import_promises.realpath)((0, import_path2.resolve)((0, import_path2.join)(baseDir, normalizedPath + ".ts")));
3367
+ resolvedPath = await realpath(resolve(join(baseDir, normalizedPath + ".ts")));
1204
3368
  if (config.logging) console.log(`[DEBUG] Found: ${normalizedPath}.ts`);
1205
3369
  } catch {
1206
3370
  try {
1207
- resolvedPath = await (0, import_promises.realpath)((0, import_path2.resolve)((0, import_path2.join)(baseDir, normalizedPath + ".js")));
3371
+ resolvedPath = await realpath(resolve(join(baseDir, normalizedPath + ".js")));
1208
3372
  if (config.logging) console.log(`[DEBUG] Found: ${normalizedPath}.js`);
1209
3373
  } catch {
1210
3374
  try {
1211
- resolvedPath = await (0, import_promises.realpath)((0, import_path2.resolve)((0, import_path2.join)(baseDir, normalizedPath, "index.ts")));
3375
+ resolvedPath = await realpath(resolve(join(baseDir, normalizedPath, "index.ts")));
1212
3376
  if (config.logging) console.log(`[DEBUG] Found: ${normalizedPath}/index.ts`);
1213
3377
  } catch {
1214
3378
  try {
1215
- resolvedPath = await (0, import_promises.realpath)((0, import_path2.resolve)((0, import_path2.join)(baseDir, normalizedPath, "index.js")));
3379
+ resolvedPath = await realpath(resolve(join(baseDir, normalizedPath, "index.js")));
1216
3380
  if (config.logging) console.log(`[DEBUG] Found: ${normalizedPath}/index.js`);
1217
3381
  } catch {
1218
3382
  if (config.logging) console.log(`[DEBUG] Not found: all attempts failed for ${normalizedPath}`);
@@ -1222,134 +3386,173 @@ function createDevServer(options) {
1222
3386
  }
1223
3387
  }
1224
3388
  if (!resolvedPath) {
1225
- res.writeHead(404, { "Content-Type": "text/plain" });
1226
- res.end("404 Not Found");
3389
+ if (!res.headersSent) {
3390
+ if (filePath === "/index.html" && matchedClient.ssr) {
3391
+ return serveSSR(res, matchedClient);
3392
+ }
3393
+ if (config.logging) console.log(`[404] ${filePath}`);
3394
+ return send404(res, "404 Not Found");
3395
+ }
1227
3396
  return;
1228
3397
  }
1229
3398
  fullPath = resolvedPath;
1230
3399
  }
1231
3400
  try {
1232
- const stats = await (0, import_promises.stat)(fullPath);
3401
+ const stats = await stat(fullPath);
1233
3402
  if (stats.isDirectory()) {
1234
3403
  if (config.logging) console.log(`[DEBUG] Path is directory: ${fullPath}, trying index files...`);
1235
3404
  let indexPath;
1236
3405
  try {
1237
- indexPath = await (0, import_promises.realpath)((0, import_path2.resolve)((0, import_path2.join)(fullPath, "index.ts")));
3406
+ indexPath = await realpath(resolve(join(fullPath, "index.ts")));
1238
3407
  if (config.logging) console.log(`[DEBUG] Found index.ts in directory`);
1239
3408
  } catch {
1240
3409
  try {
1241
- indexPath = await (0, import_promises.realpath)((0, import_path2.resolve)((0, import_path2.join)(fullPath, "index.js")));
3410
+ indexPath = await realpath(resolve(join(fullPath, "index.js")));
1242
3411
  if (config.logging) console.log(`[DEBUG] Found index.js in directory`);
1243
3412
  } catch {
1244
3413
  if (config.logging) console.log(`[DEBUG] No index file found in directory`);
1245
- res.writeHead(404, { "Content-Type": "text/plain" });
1246
- res.end("404 Not Found");
1247
- return;
3414
+ if (matchedClient.ssr) {
3415
+ return serveSSR(res, matchedClient);
3416
+ }
3417
+ return send404(res, "404 Not Found");
1248
3418
  }
1249
3419
  }
1250
3420
  fullPath = indexPath;
1251
3421
  }
1252
3422
  } catch (statError) {
1253
- res.writeHead(404, { "Content-Type": "text/plain" });
1254
- res.end("404 Not Found");
1255
- return;
1256
- }
1257
- const parentDir = await (0, import_promises.realpath)((0, import_path2.resolve)(matchedClient.root, ".."));
1258
- const isInRoot = fullPath.startsWith(rootDir + import_path2.sep) || fullPath === rootDir;
1259
- const isInParent = isDistRequest && (fullPath.startsWith(parentDir + import_path2.sep) || fullPath === parentDir);
1260
- if (!isInRoot && !isInParent) {
1261
- if (config.logging) console.log(`[403] Path outside allowed directories: ${filePath}`);
1262
- res.writeHead(403, { "Content-Type": "text/plain" });
1263
- res.end("403 Forbidden");
1264
- return;
3423
+ if (config.logging) console.log(`[404] ${filePath}`);
3424
+ return send404(res, "404 Not Found");
1265
3425
  }
1266
3426
  try {
1267
- const stats = await (0, import_promises.stat)(fullPath);
3427
+ const stats = await stat(fullPath);
1268
3428
  if (stats.isDirectory()) {
1269
3429
  try {
1270
- const indexPath = await (0, import_promises.realpath)((0, import_path2.resolve)((0, import_path2.join)(fullPath, "index.html")));
1271
- if (!indexPath.startsWith(rootDir + import_path2.sep) && indexPath !== rootDir) {
1272
- res.writeHead(403, { "Content-Type": "text/plain" });
1273
- res.end("403 Forbidden");
1274
- return;
3430
+ const indexPath = await realpath(resolve(join(fullPath, "index.html")));
3431
+ if (!indexPath.startsWith(rootDir + sep) && indexPath !== rootDir) {
3432
+ return send403(res, "403 Forbidden");
1275
3433
  }
1276
- await (0, import_promises.stat)(indexPath);
3434
+ await stat(indexPath);
1277
3435
  return serveFile(indexPath, res, matchedClient);
1278
3436
  } catch {
1279
- res.writeHead(404, { "Content-Type": "text/plain" });
1280
- res.end("404 Not Found");
1281
- return;
3437
+ return send404(res, "404 Not Found");
1282
3438
  }
1283
3439
  }
1284
3440
  await serveFile(fullPath, res, matchedClient);
1285
3441
  } catch (error) {
1286
- if (config.logging) console.log(`[404] ${filePath}`);
1287
- res.writeHead(404, { "Content-Type": "text/plain" });
1288
- res.end("404 Not Found");
3442
+ if (!res.headersSent) {
3443
+ if (config.logging) console.log(`[404] ${filePath}`);
3444
+ send404(res, "404 Not Found");
3445
+ }
1289
3446
  }
1290
3447
  });
1291
3448
  async function serveFile(filePath, res, client) {
1292
3449
  try {
1293
- const rootDir = await (0, import_promises.realpath)((0, import_path2.resolve)(client.root));
1294
- const parentDir = await (0, import_promises.realpath)((0, import_path2.resolve)(client.root, ".."));
3450
+ const rootDir = await realpath(resolve(client.root));
3451
+ const unresolvedPath = resolve(filePath);
3452
+ const isNodeModules = filePath.includes("/node_modules/") || filePath.includes("\\node_modules\\");
3453
+ const isDist = filePath.includes("/dist/") || filePath.includes("\\dist\\");
3454
+ const projectRoot = await realpath(resolve(client.root, ".."));
3455
+ const isInProjectRoot = unresolvedPath.startsWith(projectRoot + sep) || unresolvedPath === projectRoot;
3456
+ if (!unresolvedPath.startsWith(rootDir + sep) && unresolvedPath !== rootDir && !isInProjectRoot) {
3457
+ if (!isNodeModules && !isDist) {
3458
+ if (config.logging) console.log(`[403] Attempted to serve file outside allowed directories: ${filePath}`);
3459
+ return send403(res, "403 Forbidden");
3460
+ }
3461
+ }
1295
3462
  let resolvedPath;
1296
3463
  try {
1297
- resolvedPath = await (0, import_promises.realpath)((0, import_path2.resolve)(filePath));
3464
+ resolvedPath = await realpath(unresolvedPath);
1298
3465
  } catch {
1299
3466
  if (filePath.endsWith("index.html") && client.ssr) {
1300
3467
  return serveSSR(res, client);
1301
3468
  }
1302
- res.writeHead(404, { "Content-Type": "text/plain" });
1303
- res.end("404 Not Found");
1304
- return;
1305
- }
1306
- const isInRoot = resolvedPath.startsWith(rootDir + import_path2.sep) || resolvedPath === rootDir;
1307
- const isInParentDist = resolvedPath.startsWith(parentDir + import_path2.sep + "dist" + import_path2.sep);
1308
- if (!isInRoot && !isInParentDist) {
1309
- if (config.logging) console.log(`[403] Attempted to serve file outside allowed directories: ${filePath}`);
1310
- res.writeHead(403, { "Content-Type": "text/plain" });
1311
- res.end("403 Forbidden");
1312
- return;
3469
+ return send404(res, "404 Not Found");
1313
3470
  }
1314
- let content = await (0, import_promises.readFile)(resolvedPath);
1315
- const ext = (0, import_path2.extname)(resolvedPath);
1316
- let mimeType = (0, import_mime_types.lookup)(resolvedPath) || "application/octet-stream";
3471
+ let content = await readFile(resolvedPath);
3472
+ const ext = extname(resolvedPath);
3473
+ let mimeType = lookup(resolvedPath) || "application/octet-stream";
1317
3474
  if (ext === ".ts" || ext === ".tsx") {
1318
3475
  try {
1319
- const result = await (0, import_esbuild.build)({
1320
- stdin: {
1321
- contents: content.toString(),
3476
+ let transpiled;
3477
+ if (isDeno) {
3478
+ const result = await Deno.emit(resolvedPath, {
3479
+ check: false,
3480
+ compilerOptions: {
3481
+ sourceMap: true,
3482
+ inlineSourceMap: true,
3483
+ target: "ES2020",
3484
+ module: "esnext"
3485
+ },
3486
+ sources: {
3487
+ [resolvedPath]: content.toString()
3488
+ }
3489
+ });
3490
+ transpiled = result.files[resolvedPath.replace(/\.tsx?$/, ".js")] || "";
3491
+ } else if (isBun) {
3492
+ const transpiler = new Bun.Transpiler({
1322
3493
  loader: ext === ".tsx" ? "tsx" : "ts",
1323
- resolveDir: (0, import_path2.resolve)(resolvedPath, ".."),
1324
- sourcefile: resolvedPath
1325
- },
1326
- format: "esm",
1327
- target: "es2020",
1328
- write: false,
1329
- bundle: false,
1330
- sourcemap: "inline"
1331
- });
1332
- content = Buffer.from(result.outputFiles[0].text);
3494
+ target: "browser"
3495
+ });
3496
+ transpiled = transpiler.transformSync(content.toString());
3497
+ } else {
3498
+ const { build: build2 } = await import("esbuild");
3499
+ const result = await build2({
3500
+ stdin: {
3501
+ contents: content.toString(),
3502
+ loader: ext === ".tsx" ? "tsx" : "ts",
3503
+ resolveDir: resolve(resolvedPath, ".."),
3504
+ sourcefile: resolvedPath
3505
+ },
3506
+ format: "esm",
3507
+ target: "es2020",
3508
+ write: false,
3509
+ bundle: false,
3510
+ sourcemap: "inline"
3511
+ });
3512
+ transpiled = result.outputFiles[0].text;
3513
+ }
3514
+ transpiled = transpiled.replace(
3515
+ /from\s+["']([^"']+)\.ts(x?)["']/g,
3516
+ (_, path, tsx) => `from "${path}.js${tsx}"`
3517
+ );
3518
+ transpiled = transpiled.replace(
3519
+ /import\s+["']([^"']+)\.ts(x?)["']/g,
3520
+ (_, path, tsx) => `import "${path}.js${tsx}"`
3521
+ );
3522
+ content = Buffer.from(transpiled);
1333
3523
  mimeType = "application/javascript";
1334
3524
  } catch (error) {
1335
- res.writeHead(500, { "Content-Type": "text/plain" });
1336
- res.end(`TypeScript compilation error:
1337
- ${error}`);
1338
3525
  if (config.logging) console.error("[500] TypeScript compilation error:", error);
1339
- return;
3526
+ return send500(res, `TypeScript compilation error:
3527
+ ${error}`);
1340
3528
  }
1341
3529
  }
1342
3530
  if (ext === ".html") {
1343
- const elitPath = client.basePath ? `${client.basePath}/dist/client.mjs` : "/dist/client.mjs";
1344
- const importMap = `<script type="importmap">
1345
- {
1346
- "imports": {
1347
- "elit": "${elitPath}"
1348
- }
1349
- }
1350
- </script>`;
1351
- const hmrScript = `<script>(function(){const ws=new WebSocket('ws://${config.host}:${config.port}${client.basePath}');ws.onopen=()=>console.log('[Elit HMR] Connected');ws.onmessage=(e)=>{const d=JSON.parse(e.data);if(d.type==='update'){console.log('[Elit HMR] File updated:',d.path);window.location.reload()}else if(d.type==='reload'){console.log('[Elit HMR] Reloading...');window.location.reload()}else if(d.type==='error')console.error('[Elit HMR] Error:',d.error)};ws.onclose=()=>{console.log('[Elit HMR] Disconnected - Retrying...');setTimeout(()=>window.location.reload(),1000)};ws.onerror=(e)=>console.error('[Elit HMR] WebSocket error:',e)})();</script>`;
3531
+ const wsPath = normalizeBasePath(client.basePath);
3532
+ const hmrScript = createHMRScript(config.port, wsPath);
1352
3533
  let html = content.toString();
3534
+ let ssrStyles = "";
3535
+ if (client.ssr) {
3536
+ try {
3537
+ const result = client.ssr();
3538
+ let ssrHtml;
3539
+ if (typeof result === "string") {
3540
+ ssrHtml = result;
3541
+ } else if (typeof result === "object" && result !== null && "tagName" in result) {
3542
+ ssrHtml = dom.renderToString(result);
3543
+ } else {
3544
+ ssrHtml = String(result);
3545
+ }
3546
+ const styleMatches = ssrHtml.match(/<style[^>]*>[\s\S]*?<\/style>/g);
3547
+ if (styleMatches) {
3548
+ ssrStyles = styleMatches.join("\n");
3549
+ }
3550
+ } catch (error) {
3551
+ if (config.logging) console.error("[Warning] Failed to extract styles from SSR:", error);
3552
+ }
3553
+ }
3554
+ const basePath = normalizeBasePath(client.basePath);
3555
+ html = rewriteRelativePaths(html, basePath);
1353
3556
  if (client.basePath && client.basePath !== "/") {
1354
3557
  const baseTag = `<base href="${client.basePath}/">`;
1355
3558
  if (!html.includes("<base")) {
@@ -1365,7 +3568,10 @@ ${error}`);
1365
3568
  }
1366
3569
  }
1367
3570
  }
1368
- html = html.includes("</head>") ? html.replace("</head>", `${importMap}</head>`) : html;
3571
+ const elitImportMap = createElitImportMap(basePath, client.mode);
3572
+ const headInjection = ssrStyles ? `${ssrStyles}
3573
+ ${elitImportMap}` : elitImportMap;
3574
+ html = html.includes("</head>") ? html.replace("</head>", `${headInjection}</head>`) : html;
1369
3575
  html = html.includes("</body>") ? html.replace("</body>", `${hmrScript}</body>`) : html + hmrScript;
1370
3576
  content = Buffer.from(html);
1371
3577
  }
@@ -1386,19 +3592,16 @@ ${error}`);
1386
3592
  res.writeHead(200, headers);
1387
3593
  res.end(content);
1388
3594
  }
1389
- if (config.logging) console.log(`[200] ${(0, import_path2.relative)(client.root, filePath)}`);
3595
+ if (config.logging) console.log(`[200] ${relative(client.root, filePath)}`);
1390
3596
  } catch (error) {
1391
- res.writeHead(500, { "Content-Type": "text/plain" });
1392
- res.end("500 Internal Server Error");
1393
3597
  if (config.logging) console.error("[500] Error reading file:", error);
3598
+ send500(res, "500 Internal Server Error");
1394
3599
  }
1395
3600
  }
1396
3601
  function serveSSR(res, client) {
1397
3602
  try {
1398
3603
  if (!client.ssr) {
1399
- res.writeHead(500, { "Content-Type": "text/plain" });
1400
- res.end("SSR function not configured");
1401
- return;
3604
+ return send500(res, "SSR function not configured");
1402
3605
  }
1403
3606
  const result = client.ssr();
1404
3607
  let html;
@@ -1414,24 +3617,30 @@ ${error}`);
1414
3617
  } else {
1415
3618
  html = String(result);
1416
3619
  }
1417
- const hmrScript = `<script>(function(){const ws=new WebSocket('ws://${config.host}:${config.port}${client.basePath}');ws.onopen=()=>console.log('[Elit HMR] Connected');ws.onmessage=(e)=>{const d=JSON.parse(e.data);if(d.type==='update'){console.log('[Elit HMR] File updated:',d.path);window.location.reload()}else if(d.type==='reload'){console.log('[Elit HMR] Reloading...');window.location.reload()}else if(d.type==='error')console.error('[Elit HMR] Error:',d.error)};ws.onclose=()=>{console.log('[Elit HMR] Disconnected - Retrying...');setTimeout(()=>window.location.reload(),1000)};ws.onerror=(e)=>console.error('[Elit HMR] WebSocket error:',e)})();</script>`;
3620
+ const basePath = normalizeBasePath(client.basePath);
3621
+ html = rewriteRelativePaths(html, basePath);
3622
+ const hmrScript = createHMRScript(config.port, basePath);
3623
+ const elitImportMap = createElitImportMap(basePath, client.mode);
3624
+ html = html.includes("</head>") ? html.replace("</head>", `${elitImportMap}</head>`) : html;
1418
3625
  html = html.includes("</body>") ? html.replace("</body>", `${hmrScript}</body>`) : html + hmrScript;
1419
3626
  res.writeHead(200, { "Content-Type": "text/html", "Cache-Control": "no-cache, no-store, must-revalidate" });
1420
3627
  res.end(html);
1421
3628
  if (config.logging) console.log(`[200] SSR rendered`);
1422
3629
  } catch (error) {
1423
- res.writeHead(500, { "Content-Type": "text/plain" });
1424
- res.end("500 SSR Error");
1425
3630
  if (config.logging) console.error("[500] SSR Error:", error);
3631
+ send500(res, "500 SSR Error");
1426
3632
  }
1427
3633
  }
1428
- const wss = new import_ws.WebSocketServer({ server });
1429
- wss.on("connection", (ws) => {
3634
+ const wss = new WebSocketServer({ server });
3635
+ if (config.logging) {
3636
+ console.log("[HMR] WebSocket server initialized");
3637
+ }
3638
+ wss.on("connection", (ws, req) => {
1430
3639
  wsClients.add(ws);
1431
3640
  const message = { type: "connected", timestamp: Date.now() };
1432
3641
  ws.send(JSON.stringify(message));
1433
3642
  if (config.logging) {
1434
- console.log("[HMR] Client connected");
3643
+ console.log("[HMR] Client connected from", req.socket.remoteAddress);
1435
3644
  }
1436
3645
  ws.on("message", (data) => {
1437
3646
  try {
@@ -1467,17 +3676,17 @@ ${error}`);
1467
3676
  });
1468
3677
  });
1469
3678
  const watchPaths = normalizedClients.flatMap(
1470
- (client) => config.watch.map((pattern) => (0, import_path2.join)(client.root, pattern))
3679
+ (client) => config.watch.map((pattern) => join(client.root, pattern))
1471
3680
  );
1472
- const watcher = (0, import_chokidar.watch)(watchPaths, {
1473
- ignored: config.ignore,
3681
+ const watcher = watch(watchPaths, {
3682
+ ignored: (path) => config.ignore.some((pattern) => path.includes(pattern.replace("/**", "").replace("**/", ""))),
1474
3683
  ignoreInitial: true,
1475
3684
  persistent: true
1476
3685
  });
1477
3686
  watcher.on("change", (path) => {
1478
3687
  if (config.logging) console.log(`[HMR] File changed: ${path}`);
1479
3688
  const message = JSON.stringify({ type: "update", path, timestamp: Date.now() });
1480
- wsClients.forEach((client) => client.readyState === import_ws.WebSocket.OPEN && client.send(message));
3689
+ wsClients.forEach((client) => client.readyState === 1 /* OPEN */ && client.send(message));
1481
3690
  });
1482
3691
  watcher.on("add", (path) => config.logging && console.log(`[HMR] File added: ${path}`));
1483
3692
  watcher.on("unlink", (path) => config.logging && console.log(`[HMR] File removed: ${path}`));
@@ -1524,10 +3733,10 @@ ${error}`);
1524
3733
  wss.close();
1525
3734
  wsClients.forEach((client) => client.close());
1526
3735
  wsClients.clear();
1527
- return new Promise((resolve4) => {
3736
+ return new Promise((resolve2) => {
1528
3737
  server.close(() => {
1529
3738
  if (config.logging) console.log("[Server] Closed");
1530
- resolve4();
3739
+ resolve2();
1531
3740
  });
1532
3741
  });
1533
3742
  };
@@ -1543,9 +3752,47 @@ ${error}`);
1543
3752
  }
1544
3753
 
1545
3754
  // src/build.ts
1546
- var import_esbuild2 = require("esbuild");
1547
- var import_fs2 = require("fs");
1548
- var import_path3 = require("path");
3755
+ init_fs();
3756
+ init_path();
3757
+ init_runtime();
3758
+ function ensureDir(dirPath) {
3759
+ try {
3760
+ mkdirSync(dirPath, { recursive: true });
3761
+ } catch (error) {
3762
+ }
3763
+ }
3764
+ function calculateBuildMetrics(startTime, outputPath) {
3765
+ const buildTime = Date.now() - startTime;
3766
+ const stats = statSync(outputPath);
3767
+ return { buildTime, size: stats.size };
3768
+ }
3769
+ function readFileAsString2(filePath) {
3770
+ const contentBuffer = readFileSync(filePath, "utf-8");
3771
+ return typeof contentBuffer === "string" ? contentBuffer : contentBuffer.toString("utf-8");
3772
+ }
3773
+ function getMinifyOptions(minify) {
3774
+ return minify ? {
3775
+ minifyWhitespace: true,
3776
+ minifyIdentifiers: true,
3777
+ minifySyntax: true,
3778
+ legalComments: "none",
3779
+ mangleProps: /^_/,
3780
+ keepNames: false
3781
+ } : {};
3782
+ }
3783
+ function logBuildInfo(config, outputPath) {
3784
+ console.log("\n\u{1F528} Building...");
3785
+ console.log(` Entry: ${config.entry}`);
3786
+ console.log(` Output: ${outputPath}`);
3787
+ console.log(` Format: ${config.format}`);
3788
+ console.log(` Target: ${config.target}`);
3789
+ }
3790
+ function logBuildSuccess(buildTime, size) {
3791
+ console.log(`
3792
+ \u2705 Build successful!`);
3793
+ console.log(` Time: ${buildTime}ms`);
3794
+ console.log(` Size: ${formatBytes(size)}`);
3795
+ }
1549
3796
  var defaultOptions2 = {
1550
3797
  outDir: "dist",
1551
3798
  minify: true,
@@ -1556,42 +3803,35 @@ var defaultOptions2 = {
1556
3803
  logging: true,
1557
3804
  external: []
1558
3805
  };
1559
- async function build2(options) {
3806
+ async function build(options) {
1560
3807
  const config = { ...defaultOptions2, ...options };
1561
3808
  const startTime = Date.now();
1562
3809
  if (!config.entry) {
1563
3810
  throw new Error("Entry file is required");
1564
3811
  }
1565
- const entryPath = (0, import_path3.resolve)(config.entry);
1566
- const outDir = (0, import_path3.resolve)(config.outDir);
3812
+ const entryPath = resolve(config.entry);
3813
+ const outDir = resolve(config.outDir);
1567
3814
  let outFile = config.outFile;
1568
3815
  if (!outFile) {
1569
- const baseName = (0, import_path3.basename)(config.entry, (0, import_path3.extname)(config.entry));
3816
+ const baseName = basename(config.entry, extname(config.entry));
1570
3817
  const ext = config.format === "cjs" ? ".cjs" : ".js";
1571
3818
  outFile = baseName + ext;
1572
3819
  }
1573
- const outputPath = (0, import_path3.join)(outDir, outFile);
1574
- try {
1575
- (0, import_fs2.mkdirSync)(outDir, { recursive: true });
1576
- } catch (error) {
1577
- }
3820
+ const outputPath = join(outDir, outFile);
3821
+ ensureDir(outDir);
1578
3822
  if (config.logging) {
1579
- console.log("\n\u{1F528} Building...");
1580
- console.log(` Entry: ${config.entry}`);
1581
- console.log(` Output: ${outputPath}`);
1582
- console.log(` Format: ${config.format}`);
1583
- console.log(` Target: ${config.target}`);
3823
+ logBuildInfo(config, outputPath);
1584
3824
  }
1585
3825
  const browserOnlyPlugin = {
1586
3826
  name: "browser-only",
1587
- setup(build3) {
1588
- build3.onResolve({ filter: /^(node:.*|fs|path|http|https|url|os|child_process|net|tls|crypto|stream|util|events|buffer|zlib|readline|process|assert|constants|dns|domain|punycode|querystring|repl|string_decoder|sys|timers|tty|v8|vm)$/ }, () => {
3827
+ setup(build2) {
3828
+ build2.onResolve({ filter: /^(node:.*|fs|path|http|https|url|os|child_process|net|tls|crypto|stream|util|events|buffer|zlib|readline|process|assert|constants|dns|domain|punycode|querystring|repl|string_decoder|sys|timers|tty|v8|vm)$/ }, () => {
1589
3829
  return { path: "node-builtin", external: true, sideEffects: false };
1590
3830
  });
1591
- build3.onResolve({ filter: /^(chokidar|esbuild|mime-types|open|ws|fs\/promises)$/ }, () => {
3831
+ build2.onResolve({ filter: /^(chokidar|esbuild|mime-types|open|ws|fs\/promises)$/ }, () => {
1592
3832
  return { path: "server-dep", external: true, sideEffects: false };
1593
3833
  });
1594
- build3.onLoad({ filter: /[\\/](server|config|cli)\.ts$/ }, () => {
3834
+ build2.onLoad({ filter: /[\\/](server|config|cli)\.ts$/ }, () => {
1595
3835
  return {
1596
3836
  contents: "export {}",
1597
3837
  loader: "js"
@@ -1615,54 +3855,83 @@ async function build2(options) {
1615
3855
  define["import.meta.env.DEV"] = JSON.stringify(config.env.MODE !== "production");
1616
3856
  define["import.meta.env.PROD"] = JSON.stringify(config.env.MODE === "production");
1617
3857
  }
1618
- const result = await (0, import_esbuild2.build)({
1619
- entryPoints: [entryPath],
1620
- bundle: true,
1621
- outfile: outputPath,
1622
- format: config.format,
1623
- target: config.target,
1624
- minify: config.minify,
1625
- sourcemap: config.sourcemap,
1626
- external: config.external,
1627
- treeShaking: config.treeshake,
1628
- globalName: config.globalName,
1629
- platform,
1630
- plugins,
1631
- define,
1632
- logLevel: config.logging ? "info" : "silent",
1633
- metafile: true,
1634
- // Additional optimizations
1635
- ...config.minify && {
1636
- minifyWhitespace: true,
1637
- minifyIdentifiers: true,
1638
- minifySyntax: true,
1639
- legalComments: "none",
1640
- mangleProps: /^_/,
1641
- // Mangle properties starting with _
1642
- keepNames: false
3858
+ let result;
3859
+ let buildTime;
3860
+ let size;
3861
+ if (runtime === "node") {
3862
+ const { build: esbuild } = await import("esbuild");
3863
+ result = await esbuild({
3864
+ entryPoints: [entryPath],
3865
+ bundle: true,
3866
+ outfile: outputPath,
3867
+ format: config.format,
3868
+ target: config.target,
3869
+ minify: config.minify,
3870
+ sourcemap: config.sourcemap,
3871
+ external: config.external,
3872
+ treeShaking: config.treeshake,
3873
+ globalName: config.globalName,
3874
+ platform,
3875
+ plugins,
3876
+ define,
3877
+ logLevel: config.logging ? "info" : "silent",
3878
+ metafile: true,
3879
+ // Additional optimizations
3880
+ ...getMinifyOptions(config.minify)
3881
+ });
3882
+ ({ buildTime, size } = calculateBuildMetrics(startTime, outputPath));
3883
+ } else if (runtime === "bun") {
3884
+ result = await Bun.build({
3885
+ entrypoints: [entryPath],
3886
+ outdir: outDir,
3887
+ target: "bun",
3888
+ format: config.format === "cjs" ? "cjs" : "esm",
3889
+ minify: config.minify,
3890
+ sourcemap: config.sourcemap ? "external" : "none",
3891
+ external: config.external,
3892
+ naming: outFile,
3893
+ define
3894
+ });
3895
+ if (!result.success) {
3896
+ throw new Error("Bun build failed: " + JSON.stringify(result.logs));
1643
3897
  }
1644
- });
1645
- const buildTime = Date.now() - startTime;
1646
- const stats = (0, import_fs2.statSync)(outputPath);
1647
- const size = stats.size;
3898
+ ({ buildTime, size } = calculateBuildMetrics(startTime, outputPath));
3899
+ } else {
3900
+ result = await Deno.emit(entryPath, {
3901
+ bundle: "module",
3902
+ check: false,
3903
+ compilerOptions: {
3904
+ target: config.target,
3905
+ module: config.format === "cjs" ? "commonjs" : "esnext",
3906
+ sourceMap: config.sourcemap
3907
+ }
3908
+ });
3909
+ const bundledCode = result.files["deno:///bundle.js"];
3910
+ if (bundledCode) {
3911
+ await Deno.writeTextFile(outputPath, bundledCode);
3912
+ }
3913
+ ({ buildTime, size } = calculateBuildMetrics(startTime, outputPath));
3914
+ }
1648
3915
  if (config.logging) {
1649
- console.log(`
1650
- \u2705 Build successful!`);
1651
- console.log(` Time: ${buildTime}ms`);
1652
- console.log(` Size: ${formatBytes(size)}`);
1653
- if (result.metafile) {
3916
+ logBuildSuccess(buildTime, size);
3917
+ if (runtime === "node" && result.metafile) {
1654
3918
  const inputs = Object.keys(result.metafile.inputs).length;
1655
3919
  console.log(` Files: ${inputs} input(s)`);
1656
3920
  const outputKeys = Object.keys(result.metafile.outputs);
1657
3921
  if (outputKeys.length > 0) {
1658
3922
  const mainOutput = result.metafile.outputs[outputKeys[0]];
1659
3923
  if (mainOutput && mainOutput.inputs) {
1660
- const sortedInputs = Object.entries(mainOutput.inputs).sort(([, a], [, b]) => b.bytesInOutput - a.bytesInOutput).slice(0, 5);
3924
+ const sortedInputs = Object.entries(mainOutput.inputs).sort(([, a], [, b]) => {
3925
+ const aBytes = a.bytesInOutput || 0;
3926
+ const bBytes = b.bytesInOutput || 0;
3927
+ return bBytes - aBytes;
3928
+ }).slice(0, 5);
1661
3929
  if (sortedInputs.length > 0) {
1662
3930
  console.log("\n \u{1F4CA} Top 5 largest modules:");
1663
3931
  sortedInputs.forEach(([file, info]) => {
1664
3932
  const fileName = file.split(/[/\\]/).pop() || file;
1665
- console.log(` ${fileName.padEnd(30)} ${formatBytes(info.bytesInOutput)}`);
3933
+ const infoBytes = info.bytesInOutput || 0;
3934
+ console.log(` ${fileName.padEnd(30)} ${formatBytes(infoBytes)}`);
1666
3935
  });
1667
3936
  }
1668
3937
  }
@@ -1679,19 +3948,19 @@ async function build2(options) {
1679
3948
  console.log("\n\u{1F4E6} Copying files...");
1680
3949
  }
1681
3950
  for (const copyItem of config.copy) {
1682
- const fromPath = (0, import_path3.resolve)(copyItem.from);
1683
- const toPath = (0, import_path3.resolve)(outDir, copyItem.to);
1684
- const targetDir = (0, import_path3.dirname)(toPath);
1685
- if (!(0, import_fs2.existsSync)(targetDir)) {
1686
- (0, import_fs2.mkdirSync)(targetDir, { recursive: true });
3951
+ const fromPath = resolve(copyItem.from);
3952
+ const toPath = resolve(outDir, copyItem.to);
3953
+ const targetDir = dirname(toPath);
3954
+ if (!existsSync(targetDir)) {
3955
+ ensureDir(targetDir);
1687
3956
  }
1688
- if ((0, import_fs2.existsSync)(fromPath)) {
3957
+ if (existsSync(fromPath)) {
1689
3958
  if (copyItem.transform) {
1690
- const content = (0, import_fs2.readFileSync)(fromPath, "utf-8");
3959
+ const content = readFileAsString2(fromPath);
1691
3960
  const transformed = copyItem.transform(content, config);
1692
- (0, import_fs2.writeFileSync)(toPath, transformed);
3961
+ writeFileSync(toPath, transformed);
1693
3962
  } else {
1694
- (0, import_fs2.copyFileSync)(fromPath, toPath);
3963
+ copyFileSync(fromPath, toPath);
1695
3964
  }
1696
3965
  if (config.logging) {
1697
3966
  console.log(` \u2713 ${copyItem.from} \u2192 ${copyItem.to}`);
@@ -1726,6 +3995,50 @@ function formatBytes(bytes) {
1726
3995
 
1727
3996
  // src/cli.ts
1728
3997
  var COMMANDS = ["dev", "build", "preview", "help", "version"];
3998
+ function setupShutdownHandlers(closeFunc) {
3999
+ const shutdown = async () => {
4000
+ console.log("\n[Server] Shutting down...");
4001
+ await closeFunc();
4002
+ process.exit(0);
4003
+ };
4004
+ process.on("SIGINT", shutdown);
4005
+ process.on("SIGTERM", shutdown);
4006
+ }
4007
+ async function executeBuild(options) {
4008
+ try {
4009
+ await build(options);
4010
+ } catch (error) {
4011
+ process.exit(1);
4012
+ }
4013
+ }
4014
+ function validateEntry(entry, buildIndex) {
4015
+ if (!entry) {
4016
+ if (buildIndex !== void 0) {
4017
+ console.error(`Error: Entry file is required for build #${buildIndex + 1}`);
4018
+ } else {
4019
+ console.error("Error: Entry file is required");
4020
+ console.error("Specify in config file or use --entry <file>");
4021
+ }
4022
+ process.exit(1);
4023
+ }
4024
+ }
4025
+ function ensureEnv(options, env) {
4026
+ if (!options.env) {
4027
+ options.env = env;
4028
+ }
4029
+ }
4030
+ function parseArgs(args, handlers, options) {
4031
+ for (let i = 0; i < args.length; i++) {
4032
+ const arg = args[i];
4033
+ const handler = handlers[arg];
4034
+ if (handler) {
4035
+ const index = { current: i };
4036
+ handler(options, args[i + 1], index);
4037
+ i = index.current;
4038
+ }
4039
+ }
4040
+ return options;
4041
+ }
1729
4042
  async function main() {
1730
4043
  const args = process.argv.slice(2);
1731
4044
  const command = args[0] || "help";
@@ -1760,14 +4073,9 @@ async function runDev(args) {
1760
4073
  if (!options.root && (!options.clients || options.clients.length === 0)) {
1761
4074
  options.root = process.cwd();
1762
4075
  }
4076
+ options.mode = "dev";
1763
4077
  const devServer = createDevServer(options);
1764
- const shutdown = async () => {
1765
- console.log("\n[Server] Shutting down...");
1766
- await devServer.close();
1767
- process.exit(0);
1768
- };
1769
- process.on("SIGINT", shutdown);
1770
- process.on("SIGTERM", shutdown);
4078
+ setupShutdownHandlers(() => devServer.close());
1771
4079
  }
1772
4080
  async function runBuild(args) {
1773
4081
  const cliOptions = parseBuildArgs(args);
@@ -1778,34 +4086,19 @@ async function runBuild(args) {
1778
4086
  const builds = Array.isArray(config.build) ? config.build : [config.build];
1779
4087
  if (Object.keys(cliOptions).length > 0) {
1780
4088
  const options = mergeConfig(builds[0] || {}, cliOptions);
1781
- if (!options.env) {
1782
- options.env = env;
1783
- }
1784
- if (!options.entry) {
1785
- console.error("Error: Entry file is required");
1786
- console.error("Specify in config file or use --entry <file>");
1787
- process.exit(1);
1788
- }
1789
- try {
1790
- await build2(options);
1791
- } catch (error) {
1792
- process.exit(1);
1793
- }
4089
+ ensureEnv(options, env);
4090
+ validateEntry(options.entry);
4091
+ await executeBuild(options);
1794
4092
  } else {
1795
4093
  console.log(`Building ${builds.length} ${builds.length === 1 ? "entry" : "entries"}...
1796
4094
  `);
1797
4095
  for (let i = 0; i < builds.length; i++) {
1798
4096
  const buildConfig = builds[i];
1799
- if (!buildConfig.env) {
1800
- buildConfig.env = env;
1801
- }
1802
- if (!buildConfig.entry) {
1803
- console.error(`Error: Entry file is required for build #${i + 1}`);
1804
- process.exit(1);
1805
- }
4097
+ ensureEnv(buildConfig, env);
4098
+ validateEntry(buildConfig.entry, i);
1806
4099
  console.log(`[${i + 1}/${builds.length}] Building ${buildConfig.entry}...`);
1807
4100
  try {
1808
- await build2(buildConfig);
4101
+ await build(buildConfig);
1809
4102
  } catch (error) {
1810
4103
  console.error(`Build #${i + 1} failed`);
1811
4104
  process.exit(1);
@@ -1819,19 +4112,9 @@ async function runBuild(args) {
1819
4112
  }
1820
4113
  } else {
1821
4114
  const options = cliOptions;
1822
- if (!options.env) {
1823
- options.env = env;
1824
- }
1825
- if (!options.entry) {
1826
- console.error("Error: Entry file is required");
1827
- console.error("Specify in config file or use --entry <file>");
1828
- process.exit(1);
1829
- }
1830
- try {
1831
- await build2(options);
1832
- } catch (error) {
1833
- process.exit(1);
1834
- }
4115
+ ensureEnv(options, env);
4116
+ validateEntry(options.entry);
4117
+ await executeBuild(options);
1835
4118
  }
1836
4119
  }
1837
4120
  async function runPreview(args) {
@@ -1862,6 +4145,7 @@ async function runPreview(args) {
1862
4145
  const defaultOutDir = Array.isArray(buildConfig) ? buildConfig[0]?.outDir : buildConfig?.outDir;
1863
4146
  options.root = mergedOptions.root || defaultOutDir || "dist";
1864
4147
  options.basePath = mergedOptions.basePath;
4148
+ options.index = mergedOptions.index;
1865
4149
  console.log("Starting preview server...");
1866
4150
  console.log(` Root: ${options.root}`);
1867
4151
  }
@@ -1883,115 +4167,128 @@ async function runPreview(args) {
1883
4167
  if (mergedOptions.ssr) {
1884
4168
  options.ssr = mergedOptions.ssr;
1885
4169
  }
4170
+ options.mode = "preview";
1886
4171
  const devServer = createDevServer(options);
1887
- const shutdown = async () => {
1888
- console.log("\n[Server] Shutting down...");
1889
- await devServer.close();
1890
- process.exit(0);
1891
- };
1892
- process.on("SIGINT", shutdown);
1893
- process.on("SIGTERM", shutdown);
4172
+ setupShutdownHandlers(() => devServer.close());
1894
4173
  }
1895
4174
  function parseDevArgs(args) {
1896
4175
  const options = {};
1897
- for (let i = 0; i < args.length; i++) {
1898
- const arg = args[i];
1899
- const next = args[i + 1];
1900
- switch (arg) {
1901
- case "-p":
1902
- case "--port":
1903
- options.port = parseInt(next, 10);
1904
- i++;
1905
- break;
1906
- case "-h":
1907
- case "--host":
1908
- options.host = next;
1909
- i++;
1910
- break;
1911
- case "-r":
1912
- case "--root":
1913
- options.root = next;
1914
- i++;
1915
- break;
1916
- case "--no-open":
1917
- options.open = false;
1918
- break;
1919
- case "--silent":
1920
- options.logging = false;
1921
- break;
4176
+ const handlers = {
4177
+ "-p": (opts, value, index) => {
4178
+ opts.port = parseInt(value, 10);
4179
+ index.current++;
4180
+ },
4181
+ "--port": (opts, value, index) => {
4182
+ opts.port = parseInt(value, 10);
4183
+ index.current++;
4184
+ },
4185
+ "-h": (opts, value, index) => {
4186
+ opts.host = value;
4187
+ index.current++;
4188
+ },
4189
+ "--host": (opts, value, index) => {
4190
+ opts.host = value;
4191
+ index.current++;
4192
+ },
4193
+ "-r": (opts, value, index) => {
4194
+ opts.root = value;
4195
+ index.current++;
4196
+ },
4197
+ "--root": (opts, value, index) => {
4198
+ opts.root = value;
4199
+ index.current++;
4200
+ },
4201
+ "--no-open": (opts) => {
4202
+ opts.open = false;
4203
+ },
4204
+ "--silent": (opts) => {
4205
+ opts.logging = false;
1922
4206
  }
1923
- }
1924
- return options;
4207
+ };
4208
+ return parseArgs(args, handlers, options);
1925
4209
  }
1926
4210
  function parseBuildArgs(args) {
1927
4211
  const options = {};
1928
- for (let i = 0; i < args.length; i++) {
1929
- const arg = args[i];
1930
- const next = args[i + 1];
1931
- switch (arg) {
1932
- case "-e":
1933
- case "--entry":
1934
- options.entry = next;
1935
- i++;
1936
- break;
1937
- case "-o":
1938
- case "--out-dir":
1939
- options.outDir = next;
1940
- i++;
1941
- break;
1942
- case "--no-minify":
1943
- options.minify = false;
1944
- break;
1945
- case "--sourcemap":
1946
- options.sourcemap = true;
1947
- break;
1948
- case "-f":
1949
- case "--format":
1950
- options.format = next;
1951
- i++;
1952
- break;
1953
- case "--silent":
1954
- options.logging = false;
1955
- break;
4212
+ const handlers = {
4213
+ "-e": (opts, value, index) => {
4214
+ opts.entry = value;
4215
+ index.current++;
4216
+ },
4217
+ "--entry": (opts, value, index) => {
4218
+ opts.entry = value;
4219
+ index.current++;
4220
+ },
4221
+ "-o": (opts, value, index) => {
4222
+ opts.outDir = value;
4223
+ index.current++;
4224
+ },
4225
+ "--out-dir": (opts, value, index) => {
4226
+ opts.outDir = value;
4227
+ index.current++;
4228
+ },
4229
+ "--no-minify": (opts) => {
4230
+ opts.minify = false;
4231
+ },
4232
+ "--sourcemap": (opts) => {
4233
+ opts.sourcemap = true;
4234
+ },
4235
+ "-f": (opts, value, index) => {
4236
+ opts.format = value;
4237
+ index.current++;
4238
+ },
4239
+ "--format": (opts, value, index) => {
4240
+ opts.format = value;
4241
+ index.current++;
4242
+ },
4243
+ "--silent": (opts) => {
4244
+ opts.logging = false;
1956
4245
  }
1957
- }
1958
- return options;
4246
+ };
4247
+ return parseArgs(args, handlers, options);
1959
4248
  }
1960
4249
  function parsePreviewArgs(args) {
1961
4250
  const options = {};
1962
- for (let i = 0; i < args.length; i++) {
1963
- const arg = args[i];
1964
- const next = args[i + 1];
1965
- switch (arg) {
1966
- case "-p":
1967
- case "--port":
1968
- options.port = parseInt(next, 10);
1969
- i++;
1970
- break;
1971
- case "-h":
1972
- case "--host":
1973
- options.host = next;
1974
- i++;
1975
- break;
1976
- case "-r":
1977
- case "--root":
1978
- options.root = next;
1979
- i++;
1980
- break;
1981
- case "-b":
1982
- case "--base-path":
1983
- options.basePath = next;
1984
- i++;
1985
- break;
1986
- case "--no-open":
1987
- options.open = false;
1988
- break;
1989
- case "--silent":
1990
- options.logging = false;
1991
- break;
4251
+ const handlers = {
4252
+ "-p": (opts, value, index) => {
4253
+ opts.port = parseInt(value, 10);
4254
+ index.current++;
4255
+ },
4256
+ "--port": (opts, value, index) => {
4257
+ opts.port = parseInt(value, 10);
4258
+ index.current++;
4259
+ },
4260
+ "-h": (opts, value, index) => {
4261
+ opts.host = value;
4262
+ index.current++;
4263
+ },
4264
+ "--host": (opts, value, index) => {
4265
+ opts.host = value;
4266
+ index.current++;
4267
+ },
4268
+ "-r": (opts, value, index) => {
4269
+ opts.root = value;
4270
+ index.current++;
4271
+ },
4272
+ "--root": (opts, value, index) => {
4273
+ opts.root = value;
4274
+ index.current++;
4275
+ },
4276
+ "-b": (opts, value, index) => {
4277
+ opts.basePath = value;
4278
+ index.current++;
4279
+ },
4280
+ "--base-path": (opts, value, index) => {
4281
+ opts.basePath = value;
4282
+ index.current++;
4283
+ },
4284
+ "--no-open": (opts) => {
4285
+ opts.open = false;
4286
+ },
4287
+ "--silent": (opts) => {
4288
+ opts.logging = false;
1992
4289
  }
1993
- }
1994
- return options;
4290
+ };
4291
+ return parseArgs(args, handlers, options);
1995
4292
  }
1996
4293
  function printHelp() {
1997
4294
  console.log(`