gofront 1.3.1 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/cli-core.js +150 -47
- package/src/test-runner.js +8 -2
package/package.json
CHANGED
package/src/cli-core.js
CHANGED
|
@@ -222,8 +222,22 @@ export function parseTestArgs(argv) {
|
|
|
222
222
|
};
|
|
223
223
|
}
|
|
224
224
|
|
|
225
|
-
export function handleTest(targetDir, options = {}) {
|
|
226
|
-
|
|
225
|
+
export function handleTest(targetDir = ".", options = {}) {
|
|
226
|
+
let testTarget = targetDir;
|
|
227
|
+
try {
|
|
228
|
+
const project = detectProject(targetDir);
|
|
229
|
+
const targetPath = resolve(targetDir);
|
|
230
|
+
if (
|
|
231
|
+
statSync(targetPath).isDirectory() &&
|
|
232
|
+
targetPath === project.projectRoot &&
|
|
233
|
+
project.srcDir !== project.projectRoot
|
|
234
|
+
) {
|
|
235
|
+
testTarget = statSync(project.srcDir).isDirectory()
|
|
236
|
+
? project.srcDir
|
|
237
|
+
: dirname(project.srcDir);
|
|
238
|
+
}
|
|
239
|
+
} catch {}
|
|
240
|
+
return runTests(testTarget, options);
|
|
227
241
|
}
|
|
228
242
|
|
|
229
243
|
// ── Project detection ─────────────────────────────────────────
|
|
@@ -257,7 +271,17 @@ function resolveSrcDir(projectRoot, config) {
|
|
|
257
271
|
return join(projectRoot, "src");
|
|
258
272
|
}
|
|
259
273
|
if (existsSync(join(projectRoot, "main.go"))) {
|
|
260
|
-
|
|
274
|
+
try {
|
|
275
|
+
const entries = readdirSync(projectRoot);
|
|
276
|
+
const srcFiles = entries.filter(
|
|
277
|
+
(e) =>
|
|
278
|
+
(e.endsWith(".go") || e.endsWith(".templ")) &&
|
|
279
|
+
!e.endsWith("_test.go"),
|
|
280
|
+
);
|
|
281
|
+
if (srcFiles.length === 1 && srcFiles[0] === "main.go") {
|
|
282
|
+
return join(projectRoot, "main.go");
|
|
283
|
+
}
|
|
284
|
+
} catch {}
|
|
261
285
|
}
|
|
262
286
|
return projectRoot;
|
|
263
287
|
}
|
|
@@ -539,6 +563,117 @@ export function parseDevArgs(argv) {
|
|
|
539
563
|
};
|
|
540
564
|
}
|
|
541
565
|
|
|
566
|
+
function buildDevOnce(
|
|
567
|
+
{ srcDir, isDir, outputFile, sourceMap, devServer },
|
|
568
|
+
changedFile = null,
|
|
569
|
+
) {
|
|
570
|
+
try {
|
|
571
|
+
const startMs = performance.now();
|
|
572
|
+
const result = runCompile(srcDir, isDir, {
|
|
573
|
+
outputFile,
|
|
574
|
+
sourceMap: sourceMap ?? true,
|
|
575
|
+
});
|
|
576
|
+
mkdirSync(dirname(outputFile), { recursive: true });
|
|
577
|
+
writeFileSync(outputFile, `${result.js}\n`);
|
|
578
|
+
const elapsedMs = (performance.now() - startMs).toFixed(0);
|
|
579
|
+
const note = changedFile ? ` — ${changedFile} changed` : "";
|
|
580
|
+
console.error(`gofront: OK — wrote ${outputFile} (${elapsedMs}ms${note})`);
|
|
581
|
+
devServer.notify();
|
|
582
|
+
} catch (e) {
|
|
583
|
+
console.error("gofront: ERROR");
|
|
584
|
+
for (const line of e.message.split("\n")) console.error(` ${line}`);
|
|
585
|
+
devServer.notifyError(e);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
function createSrcWatcher(watchTarget, onCss, onRebuild) {
|
|
590
|
+
try {
|
|
591
|
+
return watch(watchTarget, { recursive: true }, (_event, filename) => {
|
|
592
|
+
if (!filename) return;
|
|
593
|
+
if (filename.endsWith(".css")) {
|
|
594
|
+
onCss(filename);
|
|
595
|
+
} else if (filename.endsWith(".go") || filename.endsWith(".templ")) {
|
|
596
|
+
onRebuild(filename);
|
|
597
|
+
}
|
|
598
|
+
});
|
|
599
|
+
} catch {
|
|
600
|
+
return null;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
function createServeWatcher(serveDir, watchTarget, onCss, onHtml) {
|
|
605
|
+
if (!existsSync(serveDir) || resolve(serveDir) === resolve(watchTarget)) {
|
|
606
|
+
return null;
|
|
607
|
+
}
|
|
608
|
+
try {
|
|
609
|
+
return watch(serveDir, { recursive: true }, (_event, filename) => {
|
|
610
|
+
if (!filename) return;
|
|
611
|
+
if (filename.endsWith(".css")) {
|
|
612
|
+
onCss(filename);
|
|
613
|
+
} else if (filename.endsWith(".html")) {
|
|
614
|
+
onHtml();
|
|
615
|
+
}
|
|
616
|
+
});
|
|
617
|
+
} catch {
|
|
618
|
+
return null;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
function setupDevWatchers(config) {
|
|
623
|
+
let debounce = null;
|
|
624
|
+
let cssDebounce = null;
|
|
625
|
+
let htmlDebounce = null;
|
|
626
|
+
|
|
627
|
+
const handleCss = (filename) => {
|
|
628
|
+
try {
|
|
629
|
+
copyAssets(config.project.projectRoot, config.assetConfig);
|
|
630
|
+
} catch {}
|
|
631
|
+
config.devServer.notifyCss(filename);
|
|
632
|
+
};
|
|
633
|
+
|
|
634
|
+
const watchers = [];
|
|
635
|
+
const srcWatcher = createSrcWatcher(
|
|
636
|
+
config.watchTarget,
|
|
637
|
+
(fn) => {
|
|
638
|
+
clearTimeout(cssDebounce);
|
|
639
|
+
cssDebounce = setTimeout(() => handleCss(fn), 50);
|
|
640
|
+
},
|
|
641
|
+
(fn) => {
|
|
642
|
+
clearTimeout(debounce);
|
|
643
|
+
debounce = setTimeout(() => buildDevOnce(config, fn), 80);
|
|
644
|
+
},
|
|
645
|
+
);
|
|
646
|
+
if (srcWatcher) watchers.push(srcWatcher);
|
|
647
|
+
|
|
648
|
+
const serveWatcher = createServeWatcher(
|
|
649
|
+
config.serveDir,
|
|
650
|
+
config.watchTarget,
|
|
651
|
+
(fn) => {
|
|
652
|
+
clearTimeout(cssDebounce);
|
|
653
|
+
cssDebounce = setTimeout(() => handleCss(fn), 50);
|
|
654
|
+
},
|
|
655
|
+
() => {
|
|
656
|
+
clearTimeout(htmlDebounce);
|
|
657
|
+
htmlDebounce = setTimeout(() => config.devServer.notify(), 50);
|
|
658
|
+
},
|
|
659
|
+
);
|
|
660
|
+
if (serveWatcher) watchers.push(serveWatcher);
|
|
661
|
+
|
|
662
|
+
return {
|
|
663
|
+
watchers,
|
|
664
|
+
close: () => {
|
|
665
|
+
clearTimeout(debounce);
|
|
666
|
+
clearTimeout(cssDebounce);
|
|
667
|
+
clearTimeout(htmlDebounce);
|
|
668
|
+
for (const w of watchers) {
|
|
669
|
+
try {
|
|
670
|
+
w?.close();
|
|
671
|
+
} catch {}
|
|
672
|
+
}
|
|
673
|
+
},
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
|
|
542
677
|
export async function handleDev(targetDir = ".", options = {}) {
|
|
543
678
|
const project = detectProject(targetDir);
|
|
544
679
|
const port = options.port ?? project.port ?? 3000;
|
|
@@ -567,51 +702,19 @@ export async function handleDev(targetDir = ".", options = {}) {
|
|
|
567
702
|
initialError = err;
|
|
568
703
|
}
|
|
569
704
|
|
|
570
|
-
let
|
|
705
|
+
let watcherController = null;
|
|
571
706
|
if (options.watch !== false) {
|
|
572
707
|
const watchTarget = isDir ? srcDir : dirname(srcDir);
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
mkdirSync(dirname(outputFile), { recursive: true });
|
|
584
|
-
writeFileSync(outputFile, `${result.js}\n`);
|
|
585
|
-
const elapsedMs = (performance.now() - startMs).toFixed(0);
|
|
586
|
-
const note = changedFile ? ` — ${changedFile} changed` : "";
|
|
587
|
-
console.error(
|
|
588
|
-
`gofront: OK — wrote ${outputFile} (${elapsedMs}ms${note})`,
|
|
589
|
-
);
|
|
590
|
-
devServer.notify();
|
|
591
|
-
} catch (e) {
|
|
592
|
-
console.error(`gofront: ERROR`);
|
|
593
|
-
for (const line of e.message.split("\n")) console.error(` ${line}`);
|
|
594
|
-
devServer.notifyError(e);
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
function handleCss(filename) {
|
|
599
|
-
try {
|
|
600
|
-
copyAssets(project.projectRoot, options.assetConfig);
|
|
601
|
-
} catch {}
|
|
602
|
-
devServer.notifyCss(filename);
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
watcher = watch(watchTarget, { recursive: true }, (_event, filename) => {
|
|
606
|
-
if (!filename) return;
|
|
607
|
-
if (filename.endsWith(".css")) {
|
|
608
|
-
clearTimeout(cssDebounce);
|
|
609
|
-
cssDebounce = setTimeout(() => handleCss(filename), 50);
|
|
610
|
-
return;
|
|
611
|
-
}
|
|
612
|
-
if (!filename.endsWith(".go") && !filename.endsWith(".templ")) return;
|
|
613
|
-
clearTimeout(debounce);
|
|
614
|
-
debounce = setTimeout(() => buildOnce(filename), 80);
|
|
708
|
+
watcherController = setupDevWatchers({
|
|
709
|
+
watchTarget,
|
|
710
|
+
srcDir,
|
|
711
|
+
isDir,
|
|
712
|
+
outputFile,
|
|
713
|
+
sourceMap: options.sourceMap,
|
|
714
|
+
devServer,
|
|
715
|
+
project,
|
|
716
|
+
serveDir,
|
|
717
|
+
assetConfig: options.assetConfig,
|
|
615
718
|
});
|
|
616
719
|
}
|
|
617
720
|
|
|
@@ -623,7 +726,7 @@ export async function handleDev(targetDir = ".", options = {}) {
|
|
|
623
726
|
outputFile,
|
|
624
727
|
initialError,
|
|
625
728
|
close: async () => {
|
|
626
|
-
|
|
729
|
+
watcherController?.close();
|
|
627
730
|
await devServer.close();
|
|
628
731
|
},
|
|
629
732
|
};
|
package/src/test-runner.js
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
// Handles test function discovery, test harness emission, and subprocess execution.
|
|
3
3
|
|
|
4
4
|
import { spawn } from "node:child_process";
|
|
5
|
+
import { statSync } from "node:fs";
|
|
5
6
|
import { createRequire } from "node:module";
|
|
6
|
-
import { basename, join, resolve } from "node:path";
|
|
7
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
7
8
|
import { pathToFileURL } from "node:url";
|
|
8
9
|
import { compilePackageTests, gwFilesIn } from "./compiler.js";
|
|
9
10
|
|
|
@@ -266,7 +267,12 @@ function spawnTestRunner(resolvedDir, harnessJs, testCount, options) {
|
|
|
266
267
|
}
|
|
267
268
|
|
|
268
269
|
export async function runTests(targetDir, options = {}) {
|
|
269
|
-
|
|
270
|
+
let resolvedDir = resolve(targetDir);
|
|
271
|
+
try {
|
|
272
|
+
if (statSync(resolvedDir).isFile()) {
|
|
273
|
+
resolvedDir = dirname(resolvedDir);
|
|
274
|
+
}
|
|
275
|
+
} catch {}
|
|
270
276
|
const { jsdomPath } = validateTestOptions(options, resolvedDir);
|
|
271
277
|
|
|
272
278
|
const allFiles = gwFilesIn(resolvedDir, { includeTests: true });
|