@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/dist/index.js
CHANGED
|
@@ -1,12 +1,53 @@
|
|
|
1
1
|
// src/plugin.ts
|
|
2
2
|
import { existsSync as existsSync3 } from "fs";
|
|
3
|
-
import { copyFile, mkdir } from "fs/promises";
|
|
4
|
-
import { dirname as
|
|
3
|
+
import { copyFile, mkdir as mkdir2 } from "fs/promises";
|
|
4
|
+
import { dirname as dirname5, join as joinPath5, relative as relative5 } from "path";
|
|
5
5
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
6
6
|
import { build, createServer } from "vite";
|
|
7
|
-
import chokidar from "chokidar";
|
|
8
7
|
import { createConfig } from "@sdeverywhere/check-core";
|
|
9
8
|
|
|
9
|
+
// src/bundle-file-ops.ts
|
|
10
|
+
import { mkdir, readFile, stat, utimes, writeFile } from "fs/promises";
|
|
11
|
+
import { dirname, join as joinPath } from "path";
|
|
12
|
+
async function downloadBundle(url, name, lastModified, bundlesDir) {
|
|
13
|
+
const response = await fetch(url);
|
|
14
|
+
if (!response.ok) {
|
|
15
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
16
|
+
}
|
|
17
|
+
const bundleContent = await response.text();
|
|
18
|
+
const nameParts = name.split("/");
|
|
19
|
+
const filePath = joinPath(bundlesDir, ...nameParts) + ".js";
|
|
20
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
21
|
+
await writeFile(filePath, bundleContent, "utf8");
|
|
22
|
+
if (lastModified) {
|
|
23
|
+
const mtime = new Date(lastModified);
|
|
24
|
+
await utimes(filePath, mtime, mtime);
|
|
25
|
+
}
|
|
26
|
+
return filePath;
|
|
27
|
+
}
|
|
28
|
+
async function copyBundle(url, newName, bundlesDir) {
|
|
29
|
+
let srcPath;
|
|
30
|
+
if (url === "current") {
|
|
31
|
+
const sdePrepDir = joinPath(bundlesDir, "..", "sde-prep");
|
|
32
|
+
srcPath = joinPath(sdePrepDir, "check-bundle.js");
|
|
33
|
+
} else if (url.startsWith("file://")) {
|
|
34
|
+
srcPath = new URL(url).pathname;
|
|
35
|
+
} else {
|
|
36
|
+
throw new Error(`Cannot copy bundle with URL: ${url}`);
|
|
37
|
+
}
|
|
38
|
+
const bundleContent = await readFile(srcPath, "utf8");
|
|
39
|
+
const stats = await stat(srcPath);
|
|
40
|
+
const sourceLastModified = stats.mtime;
|
|
41
|
+
const nameParts = newName.split("/");
|
|
42
|
+
const filePath = joinPath(bundlesDir, ...nameParts) + ".js";
|
|
43
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
44
|
+
await writeFile(filePath, bundleContent, "utf8");
|
|
45
|
+
if (sourceLastModified) {
|
|
46
|
+
await utimes(filePath, sourceLastModified, sourceLastModified);
|
|
47
|
+
}
|
|
48
|
+
return filePath;
|
|
49
|
+
}
|
|
50
|
+
|
|
10
51
|
// src/run-suite.ts
|
|
11
52
|
import { performance } from "perf_hooks";
|
|
12
53
|
import pico from "picocolors";
|
|
@@ -114,13 +155,13 @@ ${group.name}`);
|
|
|
114
155
|
context.log("info", "");
|
|
115
156
|
return allPassed;
|
|
116
157
|
}
|
|
117
|
-
function
|
|
158
|
+
function stat2(label, n) {
|
|
118
159
|
return `${label}=${n.toFixed(1)}ms`;
|
|
119
160
|
}
|
|
120
161
|
function printPerfReportLine(context, perfReport) {
|
|
121
|
-
const avg =
|
|
122
|
-
const min =
|
|
123
|
-
const max =
|
|
162
|
+
const avg = stat2("avg", perfReport.avgTime);
|
|
163
|
+
const min = stat2("min", perfReport.minTime);
|
|
164
|
+
const max = stat2("max", perfReport.maxTime);
|
|
124
165
|
context.log("info", ` ${avg} ${min} ${max}`);
|
|
125
166
|
}
|
|
126
167
|
function printPerfStats(context, comparisonConfig, report) {
|
|
@@ -134,12 +175,12 @@ function printPerfStats(context, comparisonConfig, report) {
|
|
|
134
175
|
|
|
135
176
|
// src/vite-config-for-bundle.ts
|
|
136
177
|
import { existsSync, readFileSync, statSync } from "fs";
|
|
137
|
-
import { basename, dirname, join as
|
|
178
|
+
import { basename, dirname as dirname2, join as joinPath2, relative, resolve as resolvePath } from "path";
|
|
138
179
|
import { fileURLToPath } from "url";
|
|
139
180
|
import { nodeResolve } from "@rollup/plugin-node-resolve";
|
|
140
181
|
import { encodeImplVars } from "@sdeverywhere/check-core";
|
|
141
182
|
var __filename2 = fileURLToPath(import.meta.url);
|
|
142
|
-
var __dirname2 =
|
|
183
|
+
var __dirname2 = dirname2(__filename2);
|
|
143
184
|
function injectModelSpec(context, modelSpec) {
|
|
144
185
|
const prepDir = context.config.prepDir;
|
|
145
186
|
const inputSpecs = [];
|
|
@@ -168,7 +209,7 @@ function injectModelSpec(context, modelSpec) {
|
|
|
168
209
|
};
|
|
169
210
|
});
|
|
170
211
|
function readJsonListing() {
|
|
171
|
-
const path =
|
|
212
|
+
const path = joinPath2(prepDir, "build", "processed.json");
|
|
172
213
|
if (existsSync(path)) {
|
|
173
214
|
const json = readFileSync(path, "utf8");
|
|
174
215
|
return JSON.parse(json);
|
|
@@ -180,7 +221,7 @@ function injectModelSpec(context, modelSpec) {
|
|
|
180
221
|
const varInstances = listing.varInstances || {};
|
|
181
222
|
const encodedImplVars = encodeImplVars(varInstances);
|
|
182
223
|
function stagedFileSize(filename) {
|
|
183
|
-
const path =
|
|
224
|
+
const path = joinPath2(prepDir, "staged", "model", filename);
|
|
184
225
|
if (existsSync(path)) {
|
|
185
226
|
return statSync(path).size;
|
|
186
227
|
} else {
|
|
@@ -235,7 +276,7 @@ async function createViteConfigForBundle(context, modelSpec) {
|
|
|
235
276
|
const root = resolvePath(__dirname2, "..", "template-bundle");
|
|
236
277
|
const prepDir = context.config.prepDir;
|
|
237
278
|
const outDir = relative(root, prepDir);
|
|
238
|
-
const modelWorkerPath =
|
|
279
|
+
const modelWorkerPath = joinPath2(prepDir, "staged", "model", "worker.js?raw");
|
|
239
280
|
return {
|
|
240
281
|
// Don't use an external config file
|
|
241
282
|
configFile: false,
|
|
@@ -270,7 +311,9 @@ async function createViteConfigForBundle(context, modelSpec) {
|
|
|
270
311
|
replacement: "threads",
|
|
271
312
|
customResolver: async function(source, importer, options) {
|
|
272
313
|
const customResolver = nodeResolve({ browser: false });
|
|
273
|
-
const
|
|
314
|
+
const resolveIdHook = customResolver.resolveId;
|
|
315
|
+
const resolveIdFn = typeof resolveIdHook === "function" ? resolveIdHook : resolveIdHook.handler;
|
|
316
|
+
const resolved = await resolveIdFn.call(this, source, importer, options);
|
|
274
317
|
if (source === "threads/worker") {
|
|
275
318
|
return resolved.id.replace("worker.mjs", "dist-esm/worker/index.js");
|
|
276
319
|
} else {
|
|
@@ -334,29 +377,116 @@ let __non_webpack_require__ = () => {
|
|
|
334
377
|
}
|
|
335
378
|
|
|
336
379
|
// src/vite-config-for-report.ts
|
|
337
|
-
import { existsSync as existsSync2, mkdirSync } from "fs";
|
|
338
|
-
import { dirname as
|
|
380
|
+
import { existsSync as existsSync2, mkdirSync, statSync as statSync2 } from "fs";
|
|
381
|
+
import { dirname as dirname3, relative as relative3, join as joinPath4, resolve as resolvePath2 } from "path";
|
|
339
382
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
340
383
|
import replace from "@rollup/plugin-replace";
|
|
384
|
+
|
|
385
|
+
// src/vite-local-bundles-plugin.ts
|
|
386
|
+
import { readdir, stat as stat3 } from "fs/promises";
|
|
387
|
+
import { join as joinPath3, relative as relative2, sep } from "path";
|
|
388
|
+
import { pathToFileURL } from "url";
|
|
389
|
+
import chokidar from "chokidar";
|
|
390
|
+
function localBundlesPlugin(bundlesDir) {
|
|
391
|
+
return {
|
|
392
|
+
name: "sde-local-bundles",
|
|
393
|
+
configureServer(server) {
|
|
394
|
+
const watcher = chokidar.watch(bundlesDir, {
|
|
395
|
+
// Don't send initial "file added" events
|
|
396
|
+
ignoreInitial: true,
|
|
397
|
+
// XXX: Include a delay, otherwise on macOS we sometimes get multiple
|
|
398
|
+
// change events when a file is saved just once
|
|
399
|
+
awaitWriteFinish: {
|
|
400
|
+
stabilityThreshold: 200
|
|
401
|
+
},
|
|
402
|
+
// Watch up to 10 levels deep
|
|
403
|
+
depth: 10
|
|
404
|
+
});
|
|
405
|
+
watcher.on("all", () => {
|
|
406
|
+
server.ws.send("bundles-changed", {});
|
|
407
|
+
});
|
|
408
|
+
server.httpServer?.on("close", () => {
|
|
409
|
+
watcher.close();
|
|
410
|
+
});
|
|
411
|
+
server.ws.on("list-bundles", async (_, client) => {
|
|
412
|
+
try {
|
|
413
|
+
const bundles = await scanBundlesRecursively(bundlesDir, bundlesDir);
|
|
414
|
+
client.send("list-bundles-success", { bundles });
|
|
415
|
+
} catch (error) {
|
|
416
|
+
console.error(`[sde-local-bundles] Failed to list bundles:`, error);
|
|
417
|
+
client.send("list-bundles-error", { error: error.message });
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
server.ws.on("download-bundle", async (data, client) => {
|
|
421
|
+
const { url, name, lastModified } = data;
|
|
422
|
+
try {
|
|
423
|
+
console.log(`[sde-local-bundles] Downloading bundle: name=${name} url=${url}`);
|
|
424
|
+
const filePath = await downloadBundle(url, name, lastModified, bundlesDir);
|
|
425
|
+
console.log(`[sde-local-bundles] Downloaded bundle to ${filePath}`);
|
|
426
|
+
client.send("download-bundle-success", { name, filePath: `${name}.js` });
|
|
427
|
+
} catch (error) {
|
|
428
|
+
console.error(`[sde-local-bundles] Failed to download bundle:`, error);
|
|
429
|
+
client.send("download-bundle-error", { name, error: error.message });
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
server.ws.on("copy-bundle", async (data, client) => {
|
|
433
|
+
const { url, name, newName } = data;
|
|
434
|
+
try {
|
|
435
|
+
console.log(`[sde-local-bundles] Copying bundle: src=${name} dst=${newName}`);
|
|
436
|
+
const filePath = await copyBundle(url, newName, bundlesDir);
|
|
437
|
+
console.log(`[sde-local-bundles] Copied bundle to ${filePath}`);
|
|
438
|
+
client.send("copy-bundle-success", { name: newName, filePath: `${newName}.js` });
|
|
439
|
+
} catch (error) {
|
|
440
|
+
console.error(`[sde-local-bundles] Failed to copy bundle:`, error);
|
|
441
|
+
client.send("copy-bundle-error", { name, error: error.message });
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
async function scanBundlesRecursively(dir, baseDir) {
|
|
448
|
+
const bundles = [];
|
|
449
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
450
|
+
for (const entry of entries) {
|
|
451
|
+
const fullPath = joinPath3(dir, entry.name);
|
|
452
|
+
if (entry.isDirectory()) {
|
|
453
|
+
const subBundles = await scanBundlesRecursively(fullPath, baseDir);
|
|
454
|
+
bundles.push(...subBundles);
|
|
455
|
+
} else if (entry.isFile() && entry.name.endsWith(".js")) {
|
|
456
|
+
const stats = await stat3(fullPath);
|
|
457
|
+
const relativePath = relative2(baseDir, fullPath);
|
|
458
|
+
const name = relativePath.replace(/\.js$/, "").split(sep).join("/");
|
|
459
|
+
bundles.push({
|
|
460
|
+
name,
|
|
461
|
+
url: pathToFileURL(fullPath).toString(),
|
|
462
|
+
lastModified: stats.mtime.toISOString()
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
return bundles;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// src/vite-config-for-report.ts
|
|
341
470
|
var __filename3 = fileURLToPath2(import.meta.url);
|
|
342
|
-
var __dirname3 =
|
|
343
|
-
function createViteConfigForReport(options, projDir, prepDir,
|
|
471
|
+
var __dirname3 = dirname3(__filename3);
|
|
472
|
+
function createViteConfigForReport(mode, options, projDir, prepDir, currentBundleSpec, baselineBundleSpec, testConfigPath, suiteSummary) {
|
|
344
473
|
const root = resolvePath2(__dirname3, "..", "template-report");
|
|
345
|
-
const
|
|
346
|
-
if (!existsSync2(
|
|
347
|
-
mkdirSync(
|
|
474
|
+
const bundlesDir = resolvePath2(projDir, "bundles");
|
|
475
|
+
if (!existsSync2(bundlesDir)) {
|
|
476
|
+
mkdirSync(bundlesDir, { recursive: true });
|
|
348
477
|
}
|
|
349
478
|
const templateSrcDir = resolvePath2(root, "src");
|
|
350
|
-
const relProjDir =
|
|
479
|
+
const relProjDir = relative3(templateSrcDir, projDir);
|
|
351
480
|
const relProjDirPath = relProjDir.replaceAll("\\", "/");
|
|
352
|
-
const
|
|
481
|
+
const bundlesPath = `${relProjDirPath}/bundles/*.js`;
|
|
482
|
+
const currentBundleLastModified = statSync2(currentBundleSpec.path).mtime.toISOString();
|
|
353
483
|
let reportPath;
|
|
354
484
|
if (options?.reportPath) {
|
|
355
485
|
reportPath = options.reportPath;
|
|
356
486
|
} else {
|
|
357
|
-
reportPath =
|
|
487
|
+
reportPath = joinPath4(prepDir, "check-report");
|
|
358
488
|
}
|
|
359
|
-
const outDir =
|
|
489
|
+
const outDir = relative3(root, reportPath);
|
|
360
490
|
const suiteSummaryJson = suiteSummary ? JSON.stringify(suiteSummary) : "";
|
|
361
491
|
const alias = (find, replacement) => {
|
|
362
492
|
return {
|
|
@@ -381,7 +511,7 @@ function createViteConfigForReport(options, projDir, prepDir, currentBundleName,
|
|
|
381
511
|
// Use a custom cache directory under `prepDir`, as otherwise Vite will use
|
|
382
512
|
// `packages/plugin-check/template-report/node_modules/.vite`, and we want to
|
|
383
513
|
// avoid generating files in `template-report` (which should be read-only)
|
|
384
|
-
cacheDir:
|
|
514
|
+
cacheDir: joinPath4(prepDir, ".vite-check-report"),
|
|
385
515
|
// Load static files from `static` (instead of the default `public`)
|
|
386
516
|
// publicDir: 'static',
|
|
387
517
|
// Don't clear the screen in dev mode so that we can see builder output
|
|
@@ -428,9 +558,9 @@ function createViteConfigForReport(options, projDir, prepDir, currentBundleName,
|
|
|
428
558
|
alias: [
|
|
429
559
|
// Use the configured "baseline" bundle if defined, otherwise use the "empty" bundle
|
|
430
560
|
// (which will cause comparison tests to be skipped)
|
|
431
|
-
alias("@_baseline_bundle_",
|
|
561
|
+
alias("@_baseline_bundle_", baselineBundleSpec?.path || "/src/empty-bundle.ts"),
|
|
432
562
|
// Use the configured "current" bundle
|
|
433
|
-
alias("@_current_bundle_",
|
|
563
|
+
alias("@_current_bundle_", currentBundleSpec.path),
|
|
434
564
|
// Use the configured test config file
|
|
435
565
|
alias("@_test_config_", testConfigPath),
|
|
436
566
|
// Make the overlay use the `messages.html` file that is written to the prep directory
|
|
@@ -450,10 +580,14 @@ function createViteConfigForReport(options, projDir, prepDir, currentBundleName,
|
|
|
450
580
|
define: {
|
|
451
581
|
// Inject the summary JSON into the build
|
|
452
582
|
__SUITE_SUMMARY_JSON__: JSON.stringify(suiteSummaryJson),
|
|
453
|
-
// Inject the baseline
|
|
454
|
-
__BASELINE_NAME__: JSON.stringify(
|
|
455
|
-
// Inject the current
|
|
456
|
-
__CURRENT_NAME__: JSON.stringify(
|
|
583
|
+
// Inject the baseline bundle name
|
|
584
|
+
__BASELINE_NAME__: JSON.stringify(baselineBundleSpec?.name || ""),
|
|
585
|
+
// Inject the current bundle name
|
|
586
|
+
__CURRENT_NAME__: JSON.stringify(currentBundleSpec.name),
|
|
587
|
+
// Inject the last modified time of the current bundle
|
|
588
|
+
__CURRENT_BUNDLE_LAST_MODIFIED__: JSON.stringify(currentBundleLastModified),
|
|
589
|
+
// Inject the remote bundles URL
|
|
590
|
+
__REMOTE_BUNDLES_URL__: JSON.stringify(options?.remoteBundlesUrl || "")
|
|
457
591
|
},
|
|
458
592
|
plugins: [
|
|
459
593
|
// Inject special values into the generated JS
|
|
@@ -465,15 +599,18 @@ function createViteConfigForReport(options, projDir, prepDir, currentBundleName,
|
|
|
465
599
|
delimiters: ["", ""],
|
|
466
600
|
values: {
|
|
467
601
|
// Inject the path for baseline bundles
|
|
468
|
-
// XXX: Note that we use './
|
|
602
|
+
// XXX: Note that we use './bundles/*.txt' instead of something special
|
|
469
603
|
// like './__BASELINE_BUNDLES_PATH__' because sometimes Vite's dependency
|
|
470
604
|
// scanner sees the latter (instead of the injected path) and reports
|
|
471
605
|
// an error since the path does not exist. As a workaround, we use
|
|
472
|
-
// './
|
|
473
|
-
// '.../template-report/src/
|
|
474
|
-
"./
|
|
606
|
+
// './bundles/*.txt', which gets interpreted as the valid path
|
|
607
|
+
// '.../template-report/src/bundles/*.txt' (see `bundles/unused.txt`).
|
|
608
|
+
"./bundles/*.txt": bundlesPath
|
|
475
609
|
}
|
|
476
|
-
})
|
|
610
|
+
}),
|
|
611
|
+
// When local development mode is active, enable the local bundles plugin that
|
|
612
|
+
// allows the report app to access the local bundles directory
|
|
613
|
+
...mode === "watch" ? [localBundlesPlugin(bundlesDir)] : []
|
|
477
614
|
],
|
|
478
615
|
build: {
|
|
479
616
|
// Write output files to the configured directory (instead of the default `dist`);
|
|
@@ -512,19 +649,19 @@ function createViteConfigForReport(options, projDir, prepDir, currentBundleName,
|
|
|
512
649
|
}
|
|
513
650
|
|
|
514
651
|
// src/vite-config-for-tests.ts
|
|
515
|
-
import { dirname as
|
|
652
|
+
import { dirname as dirname4, relative as relative4, resolve as resolvePath3 } from "path";
|
|
516
653
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
517
654
|
import replace2 from "@rollup/plugin-replace";
|
|
518
655
|
var __filename4 = fileURLToPath3(import.meta.url);
|
|
519
|
-
var __dirname4 =
|
|
520
|
-
function createViteConfigForTests(projDir, prepDir
|
|
656
|
+
var __dirname4 = dirname4(__filename4);
|
|
657
|
+
function createViteConfigForTests(mode, projDir, prepDir) {
|
|
521
658
|
const root = resolvePath3(__dirname4, "..", "template-tests");
|
|
522
659
|
const templateSrcDir = resolvePath3(root, "src");
|
|
523
|
-
const relProjDir =
|
|
660
|
+
const relProjDir = relative4(templateSrcDir, projDir);
|
|
524
661
|
const relProjDirPath = relProjDir.replaceAll("\\", "/");
|
|
525
662
|
const yamlCheckGlobPatterns = `['${relProjDirPath}/**/checks/*.yaml', '${relProjDirPath}/**/*.check.yaml']`;
|
|
526
663
|
const yamlComparisonGlobPatterns = `['${relProjDirPath}/**/comparisons/*.yaml']`;
|
|
527
|
-
const outDir =
|
|
664
|
+
const outDir = relative4(root, prepDir);
|
|
528
665
|
return {
|
|
529
666
|
// Don't use an external config file
|
|
530
667
|
configFile: false,
|
|
@@ -588,26 +725,12 @@ var CheckPlugin = class {
|
|
|
588
725
|
}
|
|
589
726
|
async watch(config) {
|
|
590
727
|
if (this.options?.testConfigPath === void 0) {
|
|
591
|
-
await this.genTestConfig(
|
|
728
|
+
await this.genTestConfig("watch", config);
|
|
592
729
|
}
|
|
593
|
-
const testOptions = this.resolveTestOptions(config);
|
|
594
|
-
const viteConfig = this.createViteConfigForReport(config, testOptions, void 0);
|
|
730
|
+
const testOptions = await this.resolveTestOptions("watch", config);
|
|
731
|
+
const viteConfig = await this.createViteConfigForReport("watch", config, testOptions, void 0);
|
|
595
732
|
const server = await createServer(viteConfig);
|
|
596
733
|
await server.listen();
|
|
597
|
-
const baselinesDir = "baselines";
|
|
598
|
-
const watcher = chokidar.watch(baselinesDir, {
|
|
599
|
-
// Watch paths are resolved relative to the project root directory
|
|
600
|
-
cwd: config.rootDir,
|
|
601
|
-
// Don't send initial "file added" events
|
|
602
|
-
ignoreInitial: true,
|
|
603
|
-
// XXX: Include a delay, otherwise on macOS we sometimes get multiple
|
|
604
|
-
// change events when a file is saved just once
|
|
605
|
-
awaitWriteFinish: {
|
|
606
|
-
stabilityThreshold: 200
|
|
607
|
-
}
|
|
608
|
-
});
|
|
609
|
-
watcher.on("add", () => server.restart());
|
|
610
|
-
watcher.on("unlink", () => server.restart());
|
|
611
734
|
}
|
|
612
735
|
// TODO: Note that this plugin runs as a `postBuild` step because it currently
|
|
613
736
|
// needs to run after other plugins, and those plugins need to run after the
|
|
@@ -617,7 +740,7 @@ var CheckPlugin = class {
|
|
|
617
740
|
async postBuild(context, modelSpec) {
|
|
618
741
|
const firstBuild = this.firstBuild;
|
|
619
742
|
this.firstBuild = false;
|
|
620
|
-
if (this.options?.current === void 0) {
|
|
743
|
+
if (this.options?.current?.path === void 0 && this.options?.current?.url === void 0) {
|
|
621
744
|
if (context.config.mode === "development") {
|
|
622
745
|
await this.copyPreviousBundle(context.config);
|
|
623
746
|
}
|
|
@@ -627,24 +750,24 @@ var CheckPlugin = class {
|
|
|
627
750
|
if (this.options?.testConfigPath === void 0) {
|
|
628
751
|
if (context.config.mode === "production" || firstBuild) {
|
|
629
752
|
context.log("info", "Generating model check test configuration...");
|
|
630
|
-
await this.genTestConfig(context.config
|
|
753
|
+
await this.genTestConfig("bundle", context.config);
|
|
631
754
|
}
|
|
632
755
|
}
|
|
633
756
|
if (context.config.mode === "production") {
|
|
634
|
-
const testOptions = this.resolveTestOptions(context.config);
|
|
757
|
+
const testOptions = await this.resolveTestOptions("bundle", context.config);
|
|
635
758
|
return this.runChecks(context, testOptions);
|
|
636
759
|
} else {
|
|
637
760
|
return true;
|
|
638
761
|
}
|
|
639
762
|
}
|
|
640
763
|
async copyPreviousBundle(config) {
|
|
641
|
-
const currentBundleFile =
|
|
764
|
+
const currentBundleFile = joinPath5(config.prepDir, "check-bundle.js");
|
|
642
765
|
if (existsSync3(currentBundleFile)) {
|
|
643
|
-
const
|
|
644
|
-
if (!existsSync3(
|
|
645
|
-
await
|
|
766
|
+
const bundlesDir = joinPath5(config.rootDir, "bundles");
|
|
767
|
+
if (!existsSync3(bundlesDir)) {
|
|
768
|
+
await mkdir2(bundlesDir, { recursive: true });
|
|
646
769
|
}
|
|
647
|
-
const previousBundleFile =
|
|
770
|
+
const previousBundleFile = joinPath5(bundlesDir, "previous.js");
|
|
648
771
|
await copyFile(currentBundleFile, previousBundleFile);
|
|
649
772
|
}
|
|
650
773
|
}
|
|
@@ -652,25 +775,32 @@ var CheckPlugin = class {
|
|
|
652
775
|
const viteConfig = await createViteConfigForBundle(context, modelSpec);
|
|
653
776
|
await build(viteConfig);
|
|
654
777
|
}
|
|
655
|
-
async genTestConfig(
|
|
778
|
+
async genTestConfig(mode, config) {
|
|
656
779
|
const rootDir = config.rootDir;
|
|
657
780
|
const prepDir = config.prepDir;
|
|
658
|
-
const viteConfig = createViteConfigForTests(rootDir, prepDir
|
|
781
|
+
const viteConfig = createViteConfigForTests(mode, rootDir, prepDir);
|
|
659
782
|
await build(viteConfig);
|
|
660
783
|
}
|
|
661
784
|
async runChecks(context, testOptions) {
|
|
662
785
|
context.log("info", "Running model checks...");
|
|
663
|
-
|
|
786
|
+
async function importBundleModule(bundleSpec) {
|
|
787
|
+
return import(relativeToSourcePath(bundleSpec.path));
|
|
788
|
+
}
|
|
789
|
+
const moduleR = await importBundleModule(testOptions.currentBundleSpec);
|
|
664
790
|
const bundleR = moduleR.createBundle();
|
|
665
|
-
const bundleNameR = testOptions.
|
|
791
|
+
const bundleNameR = testOptions.currentBundleSpec.name;
|
|
666
792
|
let bundleL;
|
|
667
793
|
let bundleNameL;
|
|
668
|
-
if (
|
|
669
|
-
const moduleL = await
|
|
794
|
+
if (testOptions.baselineBundleSpec !== void 0) {
|
|
795
|
+
const moduleL = await importBundleModule(testOptions.baselineBundleSpec);
|
|
670
796
|
const rawBundleL = moduleL.createBundle();
|
|
671
797
|
if (rawBundleL.version === bundleR.version) {
|
|
672
798
|
bundleL = rawBundleL;
|
|
673
|
-
bundleNameL =
|
|
799
|
+
bundleNameL = testOptions.baselineBundleSpec.name || "base";
|
|
800
|
+
} else {
|
|
801
|
+
console.warn(
|
|
802
|
+
`WARNING: Bundle version mismatch (baseline=${rawBundleL.version} current=${bundleR.version}); check tests will be run but comparisons will be skipped`
|
|
803
|
+
);
|
|
674
804
|
}
|
|
675
805
|
}
|
|
676
806
|
const testConfigModule = await import(relativeToSourcePath(testOptions.testConfigPath));
|
|
@@ -687,47 +817,79 @@ var CheckPlugin = class {
|
|
|
687
817
|
false
|
|
688
818
|
);
|
|
689
819
|
context.log("info", "Building model check report");
|
|
690
|
-
const viteConfig = this.createViteConfigForReport(context.config, testOptions, result.suiteSummary);
|
|
820
|
+
const viteConfig = await this.createViteConfigForReport("bundle", context.config, testOptions, result.suiteSummary);
|
|
691
821
|
await build(viteConfig);
|
|
692
822
|
return result.allChecksPassed;
|
|
693
823
|
}
|
|
694
|
-
resolveTestOptions(config) {
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
824
|
+
async resolveTestOptions(mode, config) {
|
|
825
|
+
async function resolveBundle(bundle) {
|
|
826
|
+
if (bundle?.url !== void 0) {
|
|
827
|
+
const localBundlePath = await downloadBundle(
|
|
828
|
+
bundle.url,
|
|
829
|
+
bundle.name,
|
|
830
|
+
// TODO: We don't know the last modified time of the remote bundle here, so we use
|
|
831
|
+
// undefined (which means the local file will be created with the current timestamp)
|
|
832
|
+
void 0,
|
|
833
|
+
joinPath5(config.rootDir, "bundles")
|
|
834
|
+
);
|
|
835
|
+
return {
|
|
836
|
+
name: bundle.name,
|
|
837
|
+
path: localBundlePath
|
|
838
|
+
};
|
|
839
|
+
} else if (bundle?.path !== void 0) {
|
|
840
|
+
return {
|
|
841
|
+
name: bundle.name,
|
|
842
|
+
path: bundle.path
|
|
843
|
+
};
|
|
844
|
+
} else {
|
|
845
|
+
return {
|
|
846
|
+
name: bundle?.name || "current",
|
|
847
|
+
path: joinPath5(config.prepDir, "check-bundle.js")
|
|
848
|
+
};
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
const currentBundleSpec = await resolveBundle(this.options?.current);
|
|
852
|
+
let baselineBundleSpec;
|
|
853
|
+
if (mode === "bundle" && this.options?.baseline) {
|
|
854
|
+
try {
|
|
855
|
+
baselineBundleSpec = await resolveBundle(this.options.baseline);
|
|
856
|
+
} catch (e) {
|
|
857
|
+
const name = this.options.baseline.name;
|
|
858
|
+
const loc = this.options.baseline.url || this.options.baseline.path;
|
|
859
|
+
console.warn(
|
|
860
|
+
`WARNING: Failed to load '${name}' bundle from '${loc}'; check tests will be run but comparisons will be skipped. Cause:`,
|
|
861
|
+
e
|
|
862
|
+
);
|
|
863
|
+
}
|
|
703
864
|
}
|
|
704
865
|
let testConfigPath;
|
|
705
866
|
if (this.options?.testConfigPath === void 0) {
|
|
706
|
-
testConfigPath =
|
|
867
|
+
testConfigPath = joinPath5(config.prepDir, "check-tests.js");
|
|
707
868
|
} else {
|
|
708
869
|
testConfigPath = this.options.testConfigPath;
|
|
709
870
|
}
|
|
710
871
|
return {
|
|
711
|
-
|
|
712
|
-
|
|
872
|
+
currentBundleSpec,
|
|
873
|
+
baselineBundleSpec,
|
|
713
874
|
testConfigPath
|
|
714
875
|
};
|
|
715
876
|
}
|
|
716
|
-
createViteConfigForReport(config, testOptions, suiteSummary) {
|
|
877
|
+
async createViteConfigForReport(mode, config, testOptions, suiteSummary) {
|
|
717
878
|
return createViteConfigForReport(
|
|
879
|
+
mode,
|
|
718
880
|
this.options,
|
|
719
881
|
config.rootDir,
|
|
720
882
|
config.prepDir,
|
|
721
|
-
testOptions.
|
|
722
|
-
testOptions.
|
|
883
|
+
testOptions.currentBundleSpec,
|
|
884
|
+
testOptions.baselineBundleSpec,
|
|
723
885
|
testOptions.testConfigPath,
|
|
724
886
|
suiteSummary
|
|
725
887
|
);
|
|
726
888
|
}
|
|
727
889
|
};
|
|
728
890
|
function relativeToSourcePath(filePath) {
|
|
729
|
-
const srcDir =
|
|
730
|
-
const relPath =
|
|
891
|
+
const srcDir = dirname5(fileURLToPath4(import.meta.url));
|
|
892
|
+
const relPath = relative5(srcDir, filePath);
|
|
731
893
|
return relPath.replaceAll("\\", "/");
|
|
732
894
|
}
|
|
733
895
|
export {
|