@sdeverywhere/plugin-check 0.3.20 → 0.3.22
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/bin/sde-check.js +8 -14
- package/dist/index.cjs +265 -103
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +48 -5
- package/dist/index.d.ts +48 -5
- package/dist/index.js +253 -91
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
- package/template-bundle/src/bundle.ts +0 -12
- package/template-report/index.html +22 -0
- package/template-report/src/{baselines → bundles}/unused.txt +1 -1
- package/template-report/src/env.d.ts +3 -1
- package/template-report/src/index.ts +277 -73
package/bin/sde-check.js
CHANGED
|
@@ -11,8 +11,7 @@ import { join as joinPath } from 'path'
|
|
|
11
11
|
function printUsage() {
|
|
12
12
|
console.log()
|
|
13
13
|
console.log('Usage:')
|
|
14
|
-
console.log('
|
|
15
|
-
// console.log(' sim-check baseline --clear-all\tremove all bundles from the `baselines` directory')
|
|
14
|
+
console.log(' sde-check save-current-bundle\t\tcopy the latest bundle to the `bundles` directory')
|
|
16
15
|
console.log()
|
|
17
16
|
}
|
|
18
17
|
|
|
@@ -31,19 +30,14 @@ function timestamp() {
|
|
|
31
30
|
}
|
|
32
31
|
|
|
33
32
|
const args = process.argv.slice(2)
|
|
34
|
-
if (args.length !== 2 || args[0] !== '
|
|
35
|
-
printUsage()
|
|
36
|
-
process.exit(1)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (args[1] !== '--save') {
|
|
33
|
+
if (args.length !== 2 || args[0] !== 'save-current-bundle') {
|
|
40
34
|
printUsage()
|
|
41
35
|
process.exit(1)
|
|
42
36
|
}
|
|
43
37
|
|
|
44
38
|
// TODO: For now we make a number of assumptions (e.g., that the bundle will be copied to
|
|
45
|
-
// the `
|
|
46
|
-
// will contain the current timestamp); should make these configurable
|
|
39
|
+
// the `bundles` directory under the current working directory, that the bundle filename
|
|
40
|
+
// will contain the current timestamp); we should make these configurable
|
|
47
41
|
const prepDir = joinPath(process.cwd(), 'sde-prep')
|
|
48
42
|
const srcBundleFile = joinPath(prepDir, 'check-bundle.js')
|
|
49
43
|
if (!existsSync(srcBundleFile)) {
|
|
@@ -51,10 +45,10 @@ if (!existsSync(srcBundleFile)) {
|
|
|
51
45
|
process.exit(1)
|
|
52
46
|
}
|
|
53
47
|
|
|
54
|
-
const
|
|
55
|
-
if (!existsSync(
|
|
56
|
-
mkdirSync(
|
|
48
|
+
const bundlesDir = joinPath(process.cwd(), 'bundles')
|
|
49
|
+
if (!existsSync(bundlesDir)) {
|
|
50
|
+
mkdirSync(bundlesDir, { recursive: true })
|
|
57
51
|
}
|
|
58
52
|
|
|
59
|
-
const dstBundleFile = joinPath(
|
|
53
|
+
const dstBundleFile = joinPath(bundlesDir, `${timestamp()}.js`)
|
|
60
54
|
copyFileSync(srcBundleFile, dstBundleFile)
|
package/dist/index.cjs
CHANGED
|
@@ -27,25 +27,66 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
27
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
28
|
|
|
29
29
|
// src/index.ts
|
|
30
|
-
var
|
|
31
|
-
__export(
|
|
30
|
+
var index_exports = {};
|
|
31
|
+
__export(index_exports, {
|
|
32
32
|
checkPlugin: () => checkPlugin
|
|
33
33
|
});
|
|
34
|
-
module.exports = __toCommonJS(
|
|
34
|
+
module.exports = __toCommonJS(index_exports);
|
|
35
35
|
|
|
36
|
-
// ../../node_modules/.pnpm/tsup@8.
|
|
37
|
-
var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.src
|
|
36
|
+
// ../../node_modules/.pnpm/tsup@8.5.1_postcss@8.5.6_typescript@5.2.2/node_modules/tsup/assets/cjs_shims.js
|
|
37
|
+
var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
|
|
38
38
|
var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
|
|
39
39
|
|
|
40
40
|
// src/plugin.ts
|
|
41
|
-
var
|
|
42
|
-
var
|
|
43
|
-
var
|
|
44
|
-
var
|
|
41
|
+
var import_node_fs2 = require("fs");
|
|
42
|
+
var import_promises3 = require("fs/promises");
|
|
43
|
+
var import_node_path4 = require("path");
|
|
44
|
+
var import_url3 = require("url");
|
|
45
45
|
var import_vite = require("vite");
|
|
46
|
-
var import_chokidar = __toESM(require("chokidar"), 1);
|
|
47
46
|
var import_check_core3 = require("@sdeverywhere/check-core");
|
|
48
47
|
|
|
48
|
+
// src/bundle-file-ops.ts
|
|
49
|
+
var import_promises = require("fs/promises");
|
|
50
|
+
var import_node_path = require("path");
|
|
51
|
+
async function downloadBundle(url, name, lastModified, bundlesDir) {
|
|
52
|
+
const response = await fetch(url);
|
|
53
|
+
if (!response.ok) {
|
|
54
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
55
|
+
}
|
|
56
|
+
const bundleContent = await response.text();
|
|
57
|
+
const nameParts = name.split("/");
|
|
58
|
+
const filePath = (0, import_node_path.join)(bundlesDir, ...nameParts) + ".js";
|
|
59
|
+
await (0, import_promises.mkdir)((0, import_node_path.dirname)(filePath), { recursive: true });
|
|
60
|
+
await (0, import_promises.writeFile)(filePath, bundleContent, "utf8");
|
|
61
|
+
if (lastModified) {
|
|
62
|
+
const mtime = new Date(lastModified);
|
|
63
|
+
await (0, import_promises.utimes)(filePath, mtime, mtime);
|
|
64
|
+
}
|
|
65
|
+
return filePath;
|
|
66
|
+
}
|
|
67
|
+
async function copyBundle(url, newName, bundlesDir) {
|
|
68
|
+
let srcPath;
|
|
69
|
+
if (url === "current") {
|
|
70
|
+
const sdePrepDir = (0, import_node_path.join)(bundlesDir, "..", "sde-prep");
|
|
71
|
+
srcPath = (0, import_node_path.join)(sdePrepDir, "check-bundle.js");
|
|
72
|
+
} else if (url.startsWith("file://")) {
|
|
73
|
+
srcPath = new URL(url).pathname;
|
|
74
|
+
} else {
|
|
75
|
+
throw new Error(`Cannot copy bundle with URL: ${url}`);
|
|
76
|
+
}
|
|
77
|
+
const bundleContent = await (0, import_promises.readFile)(srcPath, "utf8");
|
|
78
|
+
const stats = await (0, import_promises.stat)(srcPath);
|
|
79
|
+
const sourceLastModified = stats.mtime;
|
|
80
|
+
const nameParts = newName.split("/");
|
|
81
|
+
const filePath = (0, import_node_path.join)(bundlesDir, ...nameParts) + ".js";
|
|
82
|
+
await (0, import_promises.mkdir)((0, import_node_path.dirname)(filePath), { recursive: true });
|
|
83
|
+
await (0, import_promises.writeFile)(filePath, bundleContent, "utf8");
|
|
84
|
+
if (sourceLastModified) {
|
|
85
|
+
await (0, import_promises.utimes)(filePath, sourceLastModified, sourceLastModified);
|
|
86
|
+
}
|
|
87
|
+
return filePath;
|
|
88
|
+
}
|
|
89
|
+
|
|
49
90
|
// src/run-suite.ts
|
|
50
91
|
var import_perf_hooks = require("perf_hooks");
|
|
51
92
|
var import_picocolors = __toESM(require("picocolors"), 1);
|
|
@@ -147,13 +188,13 @@ ${group.name}`);
|
|
|
147
188
|
context.log("info", "");
|
|
148
189
|
return allPassed;
|
|
149
190
|
}
|
|
150
|
-
function
|
|
191
|
+
function stat2(label, n) {
|
|
151
192
|
return `${label}=${n.toFixed(1)}ms`;
|
|
152
193
|
}
|
|
153
194
|
function printPerfReportLine(context, perfReport) {
|
|
154
|
-
const avg =
|
|
155
|
-
const min =
|
|
156
|
-
const max =
|
|
195
|
+
const avg = stat2("avg", perfReport.avgTime);
|
|
196
|
+
const min = stat2("min", perfReport.minTime);
|
|
197
|
+
const max = stat2("max", perfReport.maxTime);
|
|
157
198
|
context.log("info", ` ${avg} ${min} ${max}`);
|
|
158
199
|
}
|
|
159
200
|
function printPerfStats(context, comparisonConfig, report) {
|
|
@@ -303,7 +344,9 @@ async function createViteConfigForBundle(context, modelSpec) {
|
|
|
303
344
|
replacement: "threads",
|
|
304
345
|
customResolver: async function(source, importer, options) {
|
|
305
346
|
const customResolver = (0, import_plugin_node_resolve.nodeResolve)({ browser: false });
|
|
306
|
-
const
|
|
347
|
+
const resolveIdHook = customResolver.resolveId;
|
|
348
|
+
const resolveIdFn = typeof resolveIdHook === "function" ? resolveIdHook : resolveIdHook.handler;
|
|
349
|
+
const resolved = await resolveIdFn.call(this, source, importer, options);
|
|
307
350
|
if (source === "threads/worker") {
|
|
308
351
|
return resolved.id.replace("worker.mjs", "dist-esm/worker/index.js");
|
|
309
352
|
} else {
|
|
@@ -367,29 +410,116 @@ let __non_webpack_require__ = () => {
|
|
|
367
410
|
}
|
|
368
411
|
|
|
369
412
|
// src/vite-config-for-report.ts
|
|
370
|
-
var
|
|
371
|
-
var
|
|
372
|
-
var
|
|
413
|
+
var import_node_fs = require("fs");
|
|
414
|
+
var import_node_path3 = require("path");
|
|
415
|
+
var import_node_url2 = require("url");
|
|
373
416
|
var import_plugin_replace = __toESM(require("@rollup/plugin-replace"), 1);
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
417
|
+
|
|
418
|
+
// src/vite-local-bundles-plugin.ts
|
|
419
|
+
var import_promises2 = require("fs/promises");
|
|
420
|
+
var import_node_path2 = require("path");
|
|
421
|
+
var import_node_url = require("url");
|
|
422
|
+
var import_chokidar = __toESM(require("chokidar"), 1);
|
|
423
|
+
function localBundlesPlugin(bundlesDir) {
|
|
424
|
+
return {
|
|
425
|
+
name: "sde-local-bundles",
|
|
426
|
+
configureServer(server) {
|
|
427
|
+
const watcher = import_chokidar.default.watch(bundlesDir, {
|
|
428
|
+
// Don't send initial "file added" events
|
|
429
|
+
ignoreInitial: true,
|
|
430
|
+
// XXX: Include a delay, otherwise on macOS we sometimes get multiple
|
|
431
|
+
// change events when a file is saved just once
|
|
432
|
+
awaitWriteFinish: {
|
|
433
|
+
stabilityThreshold: 200
|
|
434
|
+
},
|
|
435
|
+
// Watch up to 10 levels deep
|
|
436
|
+
depth: 10
|
|
437
|
+
});
|
|
438
|
+
watcher.on("all", () => {
|
|
439
|
+
server.ws.send("bundles-changed", {});
|
|
440
|
+
});
|
|
441
|
+
server.httpServer?.on("close", () => {
|
|
442
|
+
watcher.close();
|
|
443
|
+
});
|
|
444
|
+
server.ws.on("list-bundles", async (_, client) => {
|
|
445
|
+
try {
|
|
446
|
+
const bundles = await scanBundlesRecursively(bundlesDir, bundlesDir);
|
|
447
|
+
client.send("list-bundles-success", { bundles });
|
|
448
|
+
} catch (error) {
|
|
449
|
+
console.error(`[sde-local-bundles] Failed to list bundles:`, error);
|
|
450
|
+
client.send("list-bundles-error", { error: error.message });
|
|
451
|
+
}
|
|
452
|
+
});
|
|
453
|
+
server.ws.on("download-bundle", async (data, client) => {
|
|
454
|
+
const { url, name, lastModified } = data;
|
|
455
|
+
try {
|
|
456
|
+
console.log(`[sde-local-bundles] Downloading bundle: name=${name} url=${url}`);
|
|
457
|
+
const filePath = await downloadBundle(url, name, lastModified, bundlesDir);
|
|
458
|
+
console.log(`[sde-local-bundles] Downloaded bundle to ${filePath}`);
|
|
459
|
+
client.send("download-bundle-success", { name, filePath: `${name}.js` });
|
|
460
|
+
} catch (error) {
|
|
461
|
+
console.error(`[sde-local-bundles] Failed to download bundle:`, error);
|
|
462
|
+
client.send("download-bundle-error", { name, error: error.message });
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
server.ws.on("copy-bundle", async (data, client) => {
|
|
466
|
+
const { url, name, newName } = data;
|
|
467
|
+
try {
|
|
468
|
+
console.log(`[sde-local-bundles] Copying bundle: src=${name} dst=${newName}`);
|
|
469
|
+
const filePath = await copyBundle(url, newName, bundlesDir);
|
|
470
|
+
console.log(`[sde-local-bundles] Copied bundle to ${filePath}`);
|
|
471
|
+
client.send("copy-bundle-success", { name: newName, filePath: `${newName}.js` });
|
|
472
|
+
} catch (error) {
|
|
473
|
+
console.error(`[sde-local-bundles] Failed to copy bundle:`, error);
|
|
474
|
+
client.send("copy-bundle-error", { name, error: error.message });
|
|
475
|
+
}
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
async function scanBundlesRecursively(dir, baseDir) {
|
|
481
|
+
const bundles = [];
|
|
482
|
+
const entries = await (0, import_promises2.readdir)(dir, { withFileTypes: true });
|
|
483
|
+
for (const entry of entries) {
|
|
484
|
+
const fullPath = (0, import_node_path2.join)(dir, entry.name);
|
|
485
|
+
if (entry.isDirectory()) {
|
|
486
|
+
const subBundles = await scanBundlesRecursively(fullPath, baseDir);
|
|
487
|
+
bundles.push(...subBundles);
|
|
488
|
+
} else if (entry.isFile() && entry.name.endsWith(".js")) {
|
|
489
|
+
const stats = await (0, import_promises2.stat)(fullPath);
|
|
490
|
+
const relativePath = (0, import_node_path2.relative)(baseDir, fullPath);
|
|
491
|
+
const name = relativePath.replace(/\.js$/, "").split(import_node_path2.sep).join("/");
|
|
492
|
+
bundles.push({
|
|
493
|
+
name,
|
|
494
|
+
url: (0, import_node_url.pathToFileURL)(fullPath).toString(),
|
|
495
|
+
lastModified: stats.mtime.toISOString()
|
|
496
|
+
});
|
|
497
|
+
}
|
|
381
498
|
}
|
|
382
|
-
|
|
383
|
-
|
|
499
|
+
return bundles;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// src/vite-config-for-report.ts
|
|
503
|
+
var __filename3 = (0, import_node_url2.fileURLToPath)(importMetaUrl);
|
|
504
|
+
var __dirname2 = (0, import_node_path3.dirname)(__filename3);
|
|
505
|
+
function createViteConfigForReport(mode, options, projDir, prepDir, currentBundleSpec, baselineBundleSpec, testConfigPath, suiteSummary) {
|
|
506
|
+
const root = (0, import_node_path3.resolve)(__dirname2, "..", "template-report");
|
|
507
|
+
const bundlesDir = (0, import_node_path3.resolve)(projDir, "bundles");
|
|
508
|
+
if (!(0, import_node_fs.existsSync)(bundlesDir)) {
|
|
509
|
+
(0, import_node_fs.mkdirSync)(bundlesDir, { recursive: true });
|
|
510
|
+
}
|
|
511
|
+
const templateSrcDir = (0, import_node_path3.resolve)(root, "src");
|
|
512
|
+
const relProjDir = (0, import_node_path3.relative)(templateSrcDir, projDir);
|
|
384
513
|
const relProjDirPath = relProjDir.replaceAll("\\", "/");
|
|
385
|
-
const
|
|
514
|
+
const bundlesPath = `${relProjDirPath}/bundles/*.js`;
|
|
515
|
+
const currentBundleLastModified = (0, import_node_fs.statSync)(currentBundleSpec.path).mtime.toISOString();
|
|
386
516
|
let reportPath;
|
|
387
517
|
if (options?.reportPath) {
|
|
388
518
|
reportPath = options.reportPath;
|
|
389
519
|
} else {
|
|
390
|
-
reportPath = (0,
|
|
520
|
+
reportPath = (0, import_node_path3.join)(prepDir, "check-report");
|
|
391
521
|
}
|
|
392
|
-
const outDir = (0,
|
|
522
|
+
const outDir = (0, import_node_path3.relative)(root, reportPath);
|
|
393
523
|
const suiteSummaryJson = suiteSummary ? JSON.stringify(suiteSummary) : "";
|
|
394
524
|
const alias = (find, replacement) => {
|
|
395
525
|
return {
|
|
@@ -414,7 +544,7 @@ function createViteConfigForReport(options, projDir, prepDir, currentBundleName,
|
|
|
414
544
|
// Use a custom cache directory under `prepDir`, as otherwise Vite will use
|
|
415
545
|
// `packages/plugin-check/template-report/node_modules/.vite`, and we want to
|
|
416
546
|
// avoid generating files in `template-report` (which should be read-only)
|
|
417
|
-
cacheDir: (0,
|
|
547
|
+
cacheDir: (0, import_node_path3.join)(prepDir, ".vite-check-report"),
|
|
418
548
|
// Load static files from `static` (instead of the default `public`)
|
|
419
549
|
// publicDir: 'static',
|
|
420
550
|
// Don't clear the screen in dev mode so that we can see builder output
|
|
@@ -461,9 +591,9 @@ function createViteConfigForReport(options, projDir, prepDir, currentBundleName,
|
|
|
461
591
|
alias: [
|
|
462
592
|
// Use the configured "baseline" bundle if defined, otherwise use the "empty" bundle
|
|
463
593
|
// (which will cause comparison tests to be skipped)
|
|
464
|
-
alias("@_baseline_bundle_",
|
|
594
|
+
alias("@_baseline_bundle_", baselineBundleSpec?.path || "/src/empty-bundle.ts"),
|
|
465
595
|
// Use the configured "current" bundle
|
|
466
|
-
alias("@_current_bundle_",
|
|
596
|
+
alias("@_current_bundle_", currentBundleSpec.path),
|
|
467
597
|
// Use the configured test config file
|
|
468
598
|
alias("@_test_config_", testConfigPath),
|
|
469
599
|
// Make the overlay use the `messages.html` file that is written to the prep directory
|
|
@@ -483,10 +613,14 @@ function createViteConfigForReport(options, projDir, prepDir, currentBundleName,
|
|
|
483
613
|
define: {
|
|
484
614
|
// Inject the summary JSON into the build
|
|
485
615
|
__SUITE_SUMMARY_JSON__: JSON.stringify(suiteSummaryJson),
|
|
486
|
-
// Inject the baseline
|
|
487
|
-
__BASELINE_NAME__: JSON.stringify(
|
|
488
|
-
// Inject the current
|
|
489
|
-
__CURRENT_NAME__: JSON.stringify(
|
|
616
|
+
// Inject the baseline bundle name
|
|
617
|
+
__BASELINE_NAME__: JSON.stringify(baselineBundleSpec?.name || ""),
|
|
618
|
+
// Inject the current bundle name
|
|
619
|
+
__CURRENT_NAME__: JSON.stringify(currentBundleSpec.name),
|
|
620
|
+
// Inject the last modified time of the current bundle
|
|
621
|
+
__CURRENT_BUNDLE_LAST_MODIFIED__: JSON.stringify(currentBundleLastModified),
|
|
622
|
+
// Inject the remote bundles URL
|
|
623
|
+
__REMOTE_BUNDLES_URL__: JSON.stringify(options?.remoteBundlesUrl || "")
|
|
490
624
|
},
|
|
491
625
|
plugins: [
|
|
492
626
|
// Inject special values into the generated JS
|
|
@@ -498,15 +632,18 @@ function createViteConfigForReport(options, projDir, prepDir, currentBundleName,
|
|
|
498
632
|
delimiters: ["", ""],
|
|
499
633
|
values: {
|
|
500
634
|
// Inject the path for baseline bundles
|
|
501
|
-
// XXX: Note that we use './
|
|
635
|
+
// XXX: Note that we use './bundles/*.txt' instead of something special
|
|
502
636
|
// like './__BASELINE_BUNDLES_PATH__' because sometimes Vite's dependency
|
|
503
637
|
// scanner sees the latter (instead of the injected path) and reports
|
|
504
638
|
// an error since the path does not exist. As a workaround, we use
|
|
505
|
-
// './
|
|
506
|
-
// '.../template-report/src/
|
|
507
|
-
"./
|
|
639
|
+
// './bundles/*.txt', which gets interpreted as the valid path
|
|
640
|
+
// '.../template-report/src/bundles/*.txt' (see `bundles/unused.txt`).
|
|
641
|
+
"./bundles/*.txt": bundlesPath
|
|
508
642
|
}
|
|
509
|
-
})
|
|
643
|
+
}),
|
|
644
|
+
// When local development mode is active, enable the local bundles plugin that
|
|
645
|
+
// allows the report app to access the local bundles directory
|
|
646
|
+
...mode === "watch" ? [localBundlesPlugin(bundlesDir)] : []
|
|
510
647
|
],
|
|
511
648
|
build: {
|
|
512
649
|
// Write output files to the configured directory (instead of the default `dist`);
|
|
@@ -545,19 +682,19 @@ function createViteConfigForReport(options, projDir, prepDir, currentBundleName,
|
|
|
545
682
|
}
|
|
546
683
|
|
|
547
684
|
// src/vite-config-for-tests.ts
|
|
548
|
-
var
|
|
549
|
-
var
|
|
685
|
+
var import_path2 = require("path");
|
|
686
|
+
var import_url2 = require("url");
|
|
550
687
|
var import_plugin_replace2 = __toESM(require("@rollup/plugin-replace"), 1);
|
|
551
|
-
var __filename4 = (0,
|
|
552
|
-
var __dirname3 = (0,
|
|
553
|
-
function createViteConfigForTests(projDir, prepDir
|
|
554
|
-
const root = (0,
|
|
555
|
-
const templateSrcDir = (0,
|
|
556
|
-
const relProjDir = (0,
|
|
688
|
+
var __filename4 = (0, import_url2.fileURLToPath)(importMetaUrl);
|
|
689
|
+
var __dirname3 = (0, import_path2.dirname)(__filename4);
|
|
690
|
+
function createViteConfigForTests(mode, projDir, prepDir) {
|
|
691
|
+
const root = (0, import_path2.resolve)(__dirname3, "..", "template-tests");
|
|
692
|
+
const templateSrcDir = (0, import_path2.resolve)(root, "src");
|
|
693
|
+
const relProjDir = (0, import_path2.relative)(templateSrcDir, projDir);
|
|
557
694
|
const relProjDirPath = relProjDir.replaceAll("\\", "/");
|
|
558
695
|
const yamlCheckGlobPatterns = `['${relProjDirPath}/**/checks/*.yaml', '${relProjDirPath}/**/*.check.yaml']`;
|
|
559
696
|
const yamlComparisonGlobPatterns = `['${relProjDirPath}/**/comparisons/*.yaml']`;
|
|
560
|
-
const outDir = (0,
|
|
697
|
+
const outDir = (0, import_path2.relative)(root, prepDir);
|
|
561
698
|
return {
|
|
562
699
|
// Don't use an external config file
|
|
563
700
|
configFile: false,
|
|
@@ -621,26 +758,12 @@ var CheckPlugin = class {
|
|
|
621
758
|
}
|
|
622
759
|
async watch(config) {
|
|
623
760
|
if (this.options?.testConfigPath === void 0) {
|
|
624
|
-
await this.genTestConfig(
|
|
761
|
+
await this.genTestConfig("watch", config);
|
|
625
762
|
}
|
|
626
|
-
const testOptions = this.resolveTestOptions(config);
|
|
627
|
-
const viteConfig = this.createViteConfigForReport(config, testOptions, void 0);
|
|
763
|
+
const testOptions = await this.resolveTestOptions("watch", config);
|
|
764
|
+
const viteConfig = await this.createViteConfigForReport("watch", config, testOptions, void 0);
|
|
628
765
|
const server = await (0, import_vite.createServer)(viteConfig);
|
|
629
766
|
await server.listen();
|
|
630
|
-
const baselinesDir = "baselines";
|
|
631
|
-
const watcher = import_chokidar.default.watch(baselinesDir, {
|
|
632
|
-
// Watch paths are resolved relative to the project root directory
|
|
633
|
-
cwd: config.rootDir,
|
|
634
|
-
// Don't send initial "file added" events
|
|
635
|
-
ignoreInitial: true,
|
|
636
|
-
// XXX: Include a delay, otherwise on macOS we sometimes get multiple
|
|
637
|
-
// change events when a file is saved just once
|
|
638
|
-
awaitWriteFinish: {
|
|
639
|
-
stabilityThreshold: 200
|
|
640
|
-
}
|
|
641
|
-
});
|
|
642
|
-
watcher.on("add", () => server.restart());
|
|
643
|
-
watcher.on("unlink", () => server.restart());
|
|
644
767
|
}
|
|
645
768
|
// TODO: Note that this plugin runs as a `postBuild` step because it currently
|
|
646
769
|
// needs to run after other plugins, and those plugins need to run after the
|
|
@@ -650,7 +773,7 @@ var CheckPlugin = class {
|
|
|
650
773
|
async postBuild(context, modelSpec) {
|
|
651
774
|
const firstBuild = this.firstBuild;
|
|
652
775
|
this.firstBuild = false;
|
|
653
|
-
if (this.options?.current === void 0) {
|
|
776
|
+
if (this.options?.current?.path === void 0 && this.options?.current?.url === void 0) {
|
|
654
777
|
if (context.config.mode === "development") {
|
|
655
778
|
await this.copyPreviousBundle(context.config);
|
|
656
779
|
}
|
|
@@ -660,50 +783,57 @@ var CheckPlugin = class {
|
|
|
660
783
|
if (this.options?.testConfigPath === void 0) {
|
|
661
784
|
if (context.config.mode === "production" || firstBuild) {
|
|
662
785
|
context.log("info", "Generating model check test configuration...");
|
|
663
|
-
await this.genTestConfig(context.config
|
|
786
|
+
await this.genTestConfig("bundle", context.config);
|
|
664
787
|
}
|
|
665
788
|
}
|
|
666
789
|
if (context.config.mode === "production") {
|
|
667
|
-
const testOptions = this.resolveTestOptions(context.config);
|
|
790
|
+
const testOptions = await this.resolveTestOptions("bundle", context.config);
|
|
668
791
|
return this.runChecks(context, testOptions);
|
|
669
792
|
} else {
|
|
670
793
|
return true;
|
|
671
794
|
}
|
|
672
795
|
}
|
|
673
796
|
async copyPreviousBundle(config) {
|
|
674
|
-
const currentBundleFile = (0,
|
|
675
|
-
if ((0,
|
|
676
|
-
const
|
|
677
|
-
if (!(0,
|
|
678
|
-
await (0,
|
|
797
|
+
const currentBundleFile = (0, import_node_path4.join)(config.prepDir, "check-bundle.js");
|
|
798
|
+
if ((0, import_node_fs2.existsSync)(currentBundleFile)) {
|
|
799
|
+
const bundlesDir = (0, import_node_path4.join)(config.rootDir, "bundles");
|
|
800
|
+
if (!(0, import_node_fs2.existsSync)(bundlesDir)) {
|
|
801
|
+
await (0, import_promises3.mkdir)(bundlesDir, { recursive: true });
|
|
679
802
|
}
|
|
680
|
-
const previousBundleFile = (0,
|
|
681
|
-
await (0,
|
|
803
|
+
const previousBundleFile = (0, import_node_path4.join)(bundlesDir, "previous.js");
|
|
804
|
+
await (0, import_promises3.copyFile)(currentBundleFile, previousBundleFile);
|
|
682
805
|
}
|
|
683
806
|
}
|
|
684
807
|
async genCurrentBundle(context, modelSpec) {
|
|
685
808
|
const viteConfig = await createViteConfigForBundle(context, modelSpec);
|
|
686
809
|
await (0, import_vite.build)(viteConfig);
|
|
687
810
|
}
|
|
688
|
-
async genTestConfig(
|
|
811
|
+
async genTestConfig(mode, config) {
|
|
689
812
|
const rootDir = config.rootDir;
|
|
690
813
|
const prepDir = config.prepDir;
|
|
691
|
-
const viteConfig = createViteConfigForTests(rootDir, prepDir
|
|
814
|
+
const viteConfig = createViteConfigForTests(mode, rootDir, prepDir);
|
|
692
815
|
await (0, import_vite.build)(viteConfig);
|
|
693
816
|
}
|
|
694
817
|
async runChecks(context, testOptions) {
|
|
695
818
|
context.log("info", "Running model checks...");
|
|
696
|
-
|
|
819
|
+
async function importBundleModule(bundleSpec) {
|
|
820
|
+
return import(relativeToSourcePath(bundleSpec.path));
|
|
821
|
+
}
|
|
822
|
+
const moduleR = await importBundleModule(testOptions.currentBundleSpec);
|
|
697
823
|
const bundleR = moduleR.createBundle();
|
|
698
|
-
const bundleNameR = testOptions.
|
|
824
|
+
const bundleNameR = testOptions.currentBundleSpec.name;
|
|
699
825
|
let bundleL;
|
|
700
826
|
let bundleNameL;
|
|
701
|
-
if (
|
|
702
|
-
const moduleL = await
|
|
827
|
+
if (testOptions.baselineBundleSpec !== void 0) {
|
|
828
|
+
const moduleL = await importBundleModule(testOptions.baselineBundleSpec);
|
|
703
829
|
const rawBundleL = moduleL.createBundle();
|
|
704
830
|
if (rawBundleL.version === bundleR.version) {
|
|
705
831
|
bundleL = rawBundleL;
|
|
706
|
-
bundleNameL =
|
|
832
|
+
bundleNameL = testOptions.baselineBundleSpec.name || "base";
|
|
833
|
+
} else {
|
|
834
|
+
console.warn(
|
|
835
|
+
`WARNING: Bundle version mismatch (baseline=${rawBundleL.version} current=${bundleR.version}); check tests will be run but comparisons will be skipped`
|
|
836
|
+
);
|
|
707
837
|
}
|
|
708
838
|
}
|
|
709
839
|
const testConfigModule = await import(relativeToSourcePath(testOptions.testConfigPath));
|
|
@@ -720,47 +850,79 @@ var CheckPlugin = class {
|
|
|
720
850
|
false
|
|
721
851
|
);
|
|
722
852
|
context.log("info", "Building model check report");
|
|
723
|
-
const viteConfig = this.createViteConfigForReport(context.config, testOptions, result.suiteSummary);
|
|
853
|
+
const viteConfig = await this.createViteConfigForReport("bundle", context.config, testOptions, result.suiteSummary);
|
|
724
854
|
await (0, import_vite.build)(viteConfig);
|
|
725
855
|
return result.allChecksPassed;
|
|
726
856
|
}
|
|
727
|
-
resolveTestOptions(config) {
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
857
|
+
async resolveTestOptions(mode, config) {
|
|
858
|
+
async function resolveBundle(bundle) {
|
|
859
|
+
if (bundle?.url !== void 0) {
|
|
860
|
+
const localBundlePath = await downloadBundle(
|
|
861
|
+
bundle.url,
|
|
862
|
+
bundle.name,
|
|
863
|
+
// TODO: We don't know the last modified time of the remote bundle here, so we use
|
|
864
|
+
// undefined (which means the local file will be created with the current timestamp)
|
|
865
|
+
void 0,
|
|
866
|
+
(0, import_node_path4.join)(config.rootDir, "bundles")
|
|
867
|
+
);
|
|
868
|
+
return {
|
|
869
|
+
name: bundle.name,
|
|
870
|
+
path: localBundlePath
|
|
871
|
+
};
|
|
872
|
+
} else if (bundle?.path !== void 0) {
|
|
873
|
+
return {
|
|
874
|
+
name: bundle.name,
|
|
875
|
+
path: bundle.path
|
|
876
|
+
};
|
|
877
|
+
} else {
|
|
878
|
+
return {
|
|
879
|
+
name: bundle?.name || "current",
|
|
880
|
+
path: (0, import_node_path4.join)(config.prepDir, "check-bundle.js")
|
|
881
|
+
};
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
const currentBundleSpec = await resolveBundle(this.options?.current);
|
|
885
|
+
let baselineBundleSpec;
|
|
886
|
+
if (mode === "bundle" && this.options?.baseline) {
|
|
887
|
+
try {
|
|
888
|
+
baselineBundleSpec = await resolveBundle(this.options.baseline);
|
|
889
|
+
} catch (e) {
|
|
890
|
+
const name = this.options.baseline.name;
|
|
891
|
+
const loc = this.options.baseline.url || this.options.baseline.path;
|
|
892
|
+
console.warn(
|
|
893
|
+
`WARNING: Failed to load '${name}' bundle from '${loc}'; check tests will be run but comparisons will be skipped. Cause:`,
|
|
894
|
+
e
|
|
895
|
+
);
|
|
896
|
+
}
|
|
736
897
|
}
|
|
737
898
|
let testConfigPath;
|
|
738
899
|
if (this.options?.testConfigPath === void 0) {
|
|
739
|
-
testConfigPath = (0,
|
|
900
|
+
testConfigPath = (0, import_node_path4.join)(config.prepDir, "check-tests.js");
|
|
740
901
|
} else {
|
|
741
902
|
testConfigPath = this.options.testConfigPath;
|
|
742
903
|
}
|
|
743
904
|
return {
|
|
744
|
-
|
|
745
|
-
|
|
905
|
+
currentBundleSpec,
|
|
906
|
+
baselineBundleSpec,
|
|
746
907
|
testConfigPath
|
|
747
908
|
};
|
|
748
909
|
}
|
|
749
|
-
createViteConfigForReport(config, testOptions, suiteSummary) {
|
|
910
|
+
async createViteConfigForReport(mode, config, testOptions, suiteSummary) {
|
|
750
911
|
return createViteConfigForReport(
|
|
912
|
+
mode,
|
|
751
913
|
this.options,
|
|
752
914
|
config.rootDir,
|
|
753
915
|
config.prepDir,
|
|
754
|
-
testOptions.
|
|
755
|
-
testOptions.
|
|
916
|
+
testOptions.currentBundleSpec,
|
|
917
|
+
testOptions.baselineBundleSpec,
|
|
756
918
|
testOptions.testConfigPath,
|
|
757
919
|
suiteSummary
|
|
758
920
|
);
|
|
759
921
|
}
|
|
760
922
|
};
|
|
761
923
|
function relativeToSourcePath(filePath) {
|
|
762
|
-
const srcDir = (0,
|
|
763
|
-
const relPath = (0,
|
|
924
|
+
const srcDir = (0, import_node_path4.dirname)((0, import_url3.fileURLToPath)(importMetaUrl));
|
|
925
|
+
const relPath = (0, import_node_path4.relative)(srcDir, filePath);
|
|
764
926
|
return relPath.replaceAll("\\", "/");
|
|
765
927
|
}
|
|
766
928
|
// Annotate the CommonJS export names for ESM import in node:
|