@absolutejs/absolute 0.16.8 → 0.16.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -17,6 +17,55 @@ var MILLISECONDS_IN_A_DAY = MILLISECONDS_IN_A_SECOND * SECONDS_IN_A_MINUTE * MIN
17
17
  var TWO_THIRDS = 2 / 3;
18
18
  var DEFAULT_PORT = 3000;
19
19
 
20
+ // src/utils/logger.ts
21
+ var colors = {
22
+ reset: "\x1B[0m",
23
+ bold: "\x1B[1m",
24
+ dim: "\x1B[2m",
25
+ cyan: "\x1B[36m",
26
+ green: "\x1B[32m",
27
+ yellow: "\x1B[33m",
28
+ red: "\x1B[31m",
29
+ blue: "\x1B[34m",
30
+ magenta: "\x1B[35m",
31
+ white: "\x1B[37m"
32
+ };
33
+ var frameworkColors = {
34
+ react: colors.blue,
35
+ vue: colors.green,
36
+ svelte: colors.yellow,
37
+ angular: colors.magenta,
38
+ html: colors.white,
39
+ htmx: colors.white,
40
+ css: colors.cyan,
41
+ assets: colors.dim
42
+ };
43
+ var MONTHS = [
44
+ "Jan",
45
+ "Feb",
46
+ "Mar",
47
+ "Apr",
48
+ "May",
49
+ "Jun",
50
+ "Jul",
51
+ "Aug",
52
+ "Sep",
53
+ "Oct",
54
+ "Nov",
55
+ "Dec"
56
+ ];
57
+ var formatTimestamp = () => {
58
+ const now = new Date;
59
+ const month = MONTHS[now.getMonth()];
60
+ const day = now.getDate().toString().padStart(2, "0");
61
+ let hours = now.getHours();
62
+ const minutes = now.getMinutes().toString().padStart(2, "0");
63
+ const seconds = now.getSeconds().toString().padStart(2, "0");
64
+ const ampm = hours >= 12 ? "PM" : "AM";
65
+ hours = hours % 12 || 12;
66
+ return `${month} ${day} ${hours}:${minutes}:${seconds} ${ampm}`;
67
+ };
68
+
20
69
  // src/cli/interactive.ts
21
70
  import { openSync } from "fs";
22
71
  import { ReadStream } from "tty";
@@ -68,12 +117,12 @@ var createInteractiveHandler = (actions) => {
68
117
  const handleLine = async (line) => {
69
118
  const trimmed = line.trim();
70
119
  if (trimmed === "") {
71
- needsPrompt = true;
120
+ renderLine("");
72
121
  return;
73
122
  }
74
123
  if (trimmed === "$") {
75
124
  shellMode = true;
76
- needsPrompt = true;
125
+ renderLine("");
77
126
  return;
78
127
  }
79
128
  if (trimmed.startsWith("$")) {
@@ -82,39 +131,47 @@ var createInteractiveHandler = (actions) => {
82
131
  try {
83
132
  await actions.shell(cmd);
84
133
  } catch {}
85
- needsPrompt = true;
134
+ renderLine("");
86
135
  return;
87
136
  }
88
137
  }
89
138
  const wordAction = WORD_COMMANDS[trimmed.toLowerCase()];
90
139
  if (wordAction) {
91
140
  await actions[wordAction]();
92
- needsPrompt = true;
141
+ if (wordAction === "restart") {
142
+ needsPrompt = true;
143
+ } else {
144
+ renderLine("");
145
+ }
93
146
  return;
94
147
  }
95
148
  if (trimmed.length === 1) {
96
149
  const shortcutAction = SHORTCUTS[trimmed];
97
150
  if (shortcutAction) {
98
151
  await actions[shortcutAction]();
99
- needsPrompt = true;
152
+ if (shortcutAction === "restart") {
153
+ needsPrompt = true;
154
+ } else {
155
+ renderLine("");
156
+ }
100
157
  return;
101
158
  }
102
159
  }
103
160
  console.log(`\x1B[31mUnknown command: ${trimmed}\x1B[0m (press h + enter for help)`);
104
- needsPrompt = true;
161
+ renderLine("");
105
162
  };
106
163
  const handleShellLine = async (line) => {
107
164
  const trimmed = line.trim();
108
165
  if (trimmed === "") {
109
166
  shellMode = false;
110
- needsPrompt = true;
167
+ renderLine("");
111
168
  return;
112
169
  }
113
170
  try {
114
171
  await actions.shell(trimmed);
115
172
  } catch {}
116
173
  shellMode = false;
117
- needsPrompt = true;
174
+ renderLine("");
118
175
  };
119
176
  const handleArrow = (arrow) => {
120
177
  if (arrow === "A" && history.length > 0) {
@@ -229,7 +286,13 @@ var createInteractiveHandler = (actions) => {
229
286
  }
230
287
  process.stdin.pause();
231
288
  };
232
- return { dispose };
289
+ const clearPrompt = () => {
290
+ process.stdout.write("\r\x1B[2K");
291
+ };
292
+ const showPrompt = () => {
293
+ renderLine(buffer);
294
+ };
295
+ return { clearPrompt, dispose, showPrompt };
233
296
  };
234
297
 
235
298
  // src/cli/utils.ts
@@ -308,11 +371,12 @@ var killStaleProcesses = (port) => {
308
371
  process.kill(pid, "SIGTERM");
309
372
  } catch {}
310
373
  }
311
- console.log(`\x1B[33m[cli] Killed ${pids.length} stale ${pids.length === 1 ? "process" : "processes"} on port ${port}.\x1B[0m`);
374
+ console.log(`\x1B[2m${formatTimestamp()}\x1B[0m \x1B[33m[cli]\x1B[0m \x1B[33mKilled ${pids.length} stale ${pids.length === 1 ? "process" : "processes"} on port ${port}.\x1B[0m`);
312
375
  } catch {}
313
376
  };
314
377
 
315
378
  // src/cli/scripts/dev.ts
379
+ var cliTag = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[cli]\x1B[0m ${color}${message}\x1B[0m`;
316
380
  var dev = async (serverEntry) => {
317
381
  const port = Number(env.PORT) || DEFAULT_PORT;
318
382
  killStaleProcesses(port);
@@ -323,6 +387,7 @@ var dev = async (serverEntry) => {
323
387
  let paused = false;
324
388
  let cleaning = false;
325
389
  let interactive = null;
390
+ let serverReady = false;
326
391
  const spawnServer = () => {
327
392
  const proc = Bun.spawn(["bun", "--hot", "--no-clear-screen", serverEntry], {
328
393
  cwd: process.cwd(),
@@ -341,7 +406,18 @@ var dev = async (serverEntry) => {
341
406
  reader.read().then(({ done, value }) => {
342
407
  if (done)
343
408
  return;
409
+ if (serverReady)
410
+ interactive?.clearPrompt();
344
411
  dest.write(value);
412
+ if (!serverReady) {
413
+ const chunk = Buffer.from(value).toString();
414
+ if (chunk.includes("Local:")) {
415
+ serverReady = true;
416
+ interactive?.showPrompt();
417
+ }
418
+ } else {
419
+ interactive?.showPrompt();
420
+ }
345
421
  pump();
346
422
  }).catch(() => {});
347
423
  };
@@ -369,7 +445,8 @@ var dev = async (serverEntry) => {
369
445
  process.exit(exitCode);
370
446
  };
371
447
  const restartServer = async () => {
372
- console.log("\x1B[36m[cli] Restarting server...\x1B[0m");
448
+ serverReady = false;
449
+ console.log(cliTag("\x1B[36m", "Restarting server..."));
373
450
  const old = serverProcess;
374
451
  if (paused) {
375
452
  sendSignal("SIGCONT");
@@ -380,7 +457,7 @@ var dev = async (serverEntry) => {
380
457
  } catch {}
381
458
  serverProcess = spawnServer();
382
459
  await old.exited;
383
- console.log("\x1B[32m[cli] Server restarted.\x1B[0m");
460
+ console.log(cliTag("\x1B[32m", "Server restarted."));
384
461
  };
385
462
  const sendSignal = (signal) => {
386
463
  try {
@@ -395,11 +472,11 @@ var dev = async (serverEntry) => {
395
472
  if (paused) {
396
473
  sendSignal("SIGCONT");
397
474
  paused = false;
398
- console.log("\x1B[32m[cli] Server resumed.\x1B[0m");
475
+ console.log(cliTag("\x1B[32m", "Server resumed."));
399
476
  } else {
400
477
  sendSignal("SIGSTOP");
401
478
  paused = true;
402
- console.log("\x1B[33m[cli] Server paused.\x1B[0m \x1B[90m[paused]\x1B[0m");
479
+ console.log(`${cliTag("\x1B[33m", "Server paused.")} \x1B[90m[paused]\x1B[0m`);
403
480
  }
404
481
  };
405
482
  const runShellCommand = async (command) => {
@@ -416,9 +493,9 @@ var dev = async (serverEntry) => {
416
493
  stdout: "ignore",
417
494
  stderr: "ignore"
418
495
  });
419
- console.log(`\x1B[36m[cli] Opening ${url}\x1B[0m`);
496
+ console.log(cliTag("\x1B[36m", `Opening ${url}`));
420
497
  } catch {
421
- console.log(`\x1B[33m[cli] Could not open browser. Visit ${url}\x1B[0m`);
498
+ console.log(cliTag("\x1B[33m", `Could not open browser. Visit ${url}`));
422
499
  }
423
500
  };
424
501
  interactive = createInteractiveHandler({
@@ -451,23 +528,186 @@ var dev = async (serverEntry) => {
451
528
  await cleanup(0);
452
529
  return;
453
530
  }
454
- console.error(`\x1B[31m[cli] Server exited (code ${exitCode}), restarting...\x1B[0m`);
531
+ console.error(cliTag("\x1B[31m", `Server exited (code ${exitCode}), restarting...`));
455
532
  serverProcess = spawnServer();
456
533
  }
457
534
  };
458
535
  await monitorServer();
459
536
  };
460
537
 
538
+ // src/cli/cache.ts
539
+ import { mkdir } from "fs/promises";
540
+ import { join } from "path";
541
+ var {Glob } = globalThis.Bun;
542
+ var CACHE_DIR = ".absolutejs";
543
+ var MAX_FILES_PER_BATCH = 200;
544
+ var hashFile = async (path) => {
545
+ const buffer = await Bun.file(path).arrayBuffer();
546
+ return Bun.hash(buffer).toString(36);
547
+ };
548
+ var hashFiles = async (paths) => {
549
+ const entries = await Promise.all(paths.map(async (path) => [path, await hashFile(path)]));
550
+ return Object.fromEntries(entries);
551
+ };
552
+ var hashConfigs = async (configFiles) => {
553
+ const hashes = await Promise.all(configFiles.map(async (file) => {
554
+ try {
555
+ return await hashFile(file);
556
+ } catch {
557
+ return "missing";
558
+ }
559
+ }));
560
+ return hashes.join(":");
561
+ };
562
+ var loadCache = async (tool) => {
563
+ try {
564
+ const path = join(CACHE_DIR, `${tool}.cache.json`);
565
+ const data = await Bun.file(path).json();
566
+ return data;
567
+ } catch {
568
+ return null;
569
+ }
570
+ };
571
+ var saveCache = async (tool, data) => {
572
+ await mkdir(CACHE_DIR, { recursive: true });
573
+ const path = join(CACHE_DIR, `${tool}.cache.json`);
574
+ await Bun.write(path, JSON.stringify(data, null, "\t"));
575
+ };
576
+ var getChangedFiles = async (adapter) => {
577
+ const allFiles = [];
578
+ for (const pattern of adapter.fileGlobs) {
579
+ const glob = new Glob(pattern);
580
+ for await (const file of glob.scan({
581
+ cwd: ".",
582
+ dot: false
583
+ })) {
584
+ const ignored = adapter.ignorePatterns.some((pat) => {
585
+ const globPat = new Glob(pat);
586
+ return globPat.match(file);
587
+ });
588
+ if (!ignored) {
589
+ allFiles.push(file);
590
+ }
591
+ }
592
+ }
593
+ const [fileHashes, configHash, existing] = await Promise.all([
594
+ hashFiles(allFiles),
595
+ hashConfigs(adapter.configFiles),
596
+ loadCache(adapter.name)
597
+ ]);
598
+ const newCache = { configHash, files: fileHashes };
599
+ if (!existing || existing.configHash !== configHash) {
600
+ return { changed: allFiles, cache: newCache };
601
+ }
602
+ const changed = allFiles.filter((file) => fileHashes[file] !== existing.files[file]);
603
+ return { changed, cache: newCache };
604
+ };
605
+ var runTool = async (adapter, args) => {
606
+ const { changed, cache } = await getChangedFiles(adapter);
607
+ const totalFiles = Object.keys(cache.files).length;
608
+ if (changed.length === 0) {
609
+ console.log("\x1B[32m\u2713\x1B[0m All files passed (cached)");
610
+ return;
611
+ }
612
+ console.log(`Checking ${changed.length}/${totalFiles} file(s)...`);
613
+ const batches = [];
614
+ for (let idx = 0;idx < changed.length; idx += MAX_FILES_PER_BATCH) {
615
+ batches.push(changed.slice(idx, idx + MAX_FILES_PER_BATCH));
616
+ }
617
+ const failedFiles = new Set;
618
+ for (const batch of batches) {
619
+ const command = adapter.buildCommand(batch, args);
620
+ const proc = Bun.spawn(command, {
621
+ stdout: "inherit",
622
+ stderr: "inherit"
623
+ });
624
+ const exitCode = await proc.exited;
625
+ if (exitCode !== 0) {
626
+ for (const file of batch) {
627
+ failedFiles.add(file);
628
+ }
629
+ }
630
+ }
631
+ for (const file of failedFiles) {
632
+ delete cache.files[file];
633
+ }
634
+ await saveCache(adapter.name, cache);
635
+ if (failedFiles.size > 0) {
636
+ process.exit(1);
637
+ }
638
+ console.log("\x1B[32m\u2713\x1B[0m Passed");
639
+ };
640
+
641
+ // src/cli/scripts/eslint.ts
642
+ var eslintAdapter = {
643
+ name: "eslint",
644
+ fileGlobs: [
645
+ "**/*.ts",
646
+ "**/*.tsx",
647
+ "**/*.js",
648
+ "**/*.mjs",
649
+ "**/*.json",
650
+ "**/*.svelte"
651
+ ],
652
+ ignorePatterns: [
653
+ "node_modules/**",
654
+ "dist/**",
655
+ "**/compiled/**",
656
+ "build/**",
657
+ ".absolutejs/**"
658
+ ],
659
+ configFiles: ["eslint.config.mjs"],
660
+ buildCommand: (files, args) => ["bun", "eslint", ...args, ...files]
661
+ };
662
+ var eslint = async (args) => {
663
+ await runTool(eslintAdapter, args);
664
+ };
665
+
666
+ // src/cli/scripts/prettier.ts
667
+ var prettierAdapter = {
668
+ name: "prettier",
669
+ fileGlobs: [
670
+ "**/*.ts",
671
+ "**/*.tsx",
672
+ "**/*.js",
673
+ "**/*.mjs",
674
+ "**/*.json",
675
+ "**/*.svelte",
676
+ "**/*.vue",
677
+ "**/*.html",
678
+ "**/*.css"
679
+ ],
680
+ ignorePatterns: [
681
+ "node_modules/**",
682
+ "dist/**",
683
+ "build/**",
684
+ ".absolutejs/**",
685
+ "*.min.js"
686
+ ],
687
+ configFiles: [".prettierrc.json"],
688
+ buildCommand: (files, args) => ["bun", "prettier", ...args, ...files]
689
+ };
690
+ var prettier = async (args) => {
691
+ await runTool(prettierAdapter, args);
692
+ };
693
+
461
694
  // src/cli/index.ts
462
695
  var command = process.argv[2];
696
+ var args = process.argv.slice(3);
463
697
  if (command === "dev") {
464
- const serverEntry = process.argv[3] ?? DEFAULT_SERVER_ENTRY;
698
+ const serverEntry = args[0] ?? DEFAULT_SERVER_ENTRY;
465
699
  await dev(serverEntry);
700
+ } else if (command === "eslint") {
701
+ await eslint(args);
702
+ } else if (command === "prettier") {
703
+ await prettier(args);
466
704
  } else {
467
705
  const message = command ? `Unknown command: ${command}` : "No command specified";
468
706
  console.error(message);
469
707
  console.error("Usage: absolutejs <command>");
470
708
  console.error("Commands:");
471
- console.error(" dev [entry] Start development server");
709
+ console.error(" dev [entry] Start development server");
710
+ console.error(" eslint Run ESLint (cached)");
711
+ console.error(" prettier Run Prettier check (cached)");
472
712
  process.exit(1);
473
713
  }
package/dist/index.js CHANGED
@@ -1542,14 +1542,30 @@ var frameworkColors = {
1542
1542
  css: colors.cyan,
1543
1543
  assets: colors.dim
1544
1544
  };
1545
+ var MONTHS = [
1546
+ "Jan",
1547
+ "Feb",
1548
+ "Mar",
1549
+ "Apr",
1550
+ "May",
1551
+ "Jun",
1552
+ "Jul",
1553
+ "Aug",
1554
+ "Sep",
1555
+ "Oct",
1556
+ "Nov",
1557
+ "Dec"
1558
+ ];
1545
1559
  var formatTimestamp = () => {
1546
1560
  const now = new Date;
1561
+ const month = MONTHS[now.getMonth()];
1562
+ const day = now.getDate().toString().padStart(2, "0");
1547
1563
  let hours = now.getHours();
1548
1564
  const minutes = now.getMinutes().toString().padStart(2, "0");
1549
1565
  const seconds = now.getSeconds().toString().padStart(2, "0");
1550
1566
  const ampm = hours >= 12 ? "PM" : "AM";
1551
1567
  hours = hours % 12 || 12;
1552
- return `${hours}:${minutes}:${seconds} ${ampm}`;
1568
+ return `${month} ${day} ${hours}:${minutes}:${seconds} ${ampm}`;
1553
1569
  };
1554
1570
  var formatPath = (filePath) => {
1555
1571
  const cwd = process.cwd();
@@ -3797,5 +3813,5 @@ export {
3797
3813
  BUN_BUILD_WARNING_SUPPRESSION
3798
3814
  };
3799
3815
 
3800
- //# debugId=AC20DDC75B328D9A64756E2164756E21
3816
+ //# debugId=2BF1125B1D79B27A64756E2164756E21
3801
3817
  //# sourceMappingURL=index.js.map