@crvy/rprtr 0.0.8 → 0.0.9

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/CHANGELOG.md CHANGED
@@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.0.9] - 2026-06-05
9
+
10
+ ### Fixed
11
+
12
+ - Remove file watcher that interfered with live updates
8
13
  ## [0.0.8] - 2026-06-05
9
14
 
10
15
  ### Fixed
@@ -14,7 +14,7 @@ import {
14
14
  } from "./chunk-EJRLZZ22.js";
15
15
 
16
16
  // src/server/app.ts
17
- import { dirname as dirname3, join as join4 } from "path";
17
+ import { dirname as dirname3, join as join3 } from "path";
18
18
  import { fileURLToPath } from "url";
19
19
  import pLimit from "p-limit";
20
20
 
@@ -210,123 +210,15 @@ function handleSync(ctx) {
210
210
  broadcastToBrowsers(ctx.wsClients, { type: "sync", data: ctx.reportData });
211
211
  }
212
212
 
213
- // src/server/report-watch.ts
214
- import { readdir as readdir2, stat as stat2 } from "fs/promises";
215
- import { join as join2 } from "path";
216
- var OFFLINE_REPORT_FILE_PATTERN2 = /^crvy-rprtr(?:-\d+)?\.json$/;
217
- function createDebouncedRefresh(reload, delayMs = 50) {
218
- let timer = null;
219
- return () => {
220
- if (timer !== null) {
221
- clearTimeout(timer);
222
- }
223
- timer = setTimeout(() => {
224
- timer = null;
225
- void reload();
226
- }, delayMs);
227
- };
228
- }
229
- function isFileNotFound2(error) {
230
- return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
231
- }
232
- async function describeFile(filePath, label) {
233
- try {
234
- const fileStats = await stat2(filePath);
235
- return `${label}:${fileStats.size}:${fileStats.mtimeMs}`;
236
- } catch (error) {
237
- if (isFileNotFound2(error)) {
238
- return null;
239
- }
240
- throw error;
241
- }
242
- }
243
- async function createOfflineFingerprint(offlineReportDir) {
244
- if (!await isDirectory(offlineReportDir)) {
245
- return "offline:missing";
246
- }
247
- try {
248
- const entries = await readdir2(offlineReportDir, { withFileTypes: true });
249
- const relevantEntries = entries.filter(
250
- (entry) => entry.isFile() && (entry.name === "report.json" || OFFLINE_REPORT_FILE_PATTERN2.test(entry.name))
251
- ).sort((left, right) => left.name.localeCompare(right.name));
252
- const parts = await Promise.all(
253
- relevantEntries.map((entry) => describeFile(join2(offlineReportDir, entry.name), entry.name))
254
- );
255
- return `offline:${parts.filter((part) => part !== null).join("|")}`;
256
- } catch (error) {
257
- const errorMsg = error instanceof Error ? error.message : String(error);
258
- console.warn(`[Server] Unable to scan ${offlineReportDir}: ${errorMsg}`);
259
- return "offline:error";
260
- }
261
- }
262
- async function createScreenshotFingerprint(screenshotDir, relativePath = "") {
263
- const directoryPath = relativePath === "" ? screenshotDir : join2(screenshotDir, relativePath);
264
- if (!await isDirectory(directoryPath)) {
265
- return relativePath === "" ? ["screenshots:missing"] : [];
266
- }
267
- try {
268
- const entries = await readdir2(directoryPath, { withFileTypes: true });
269
- const parts = await Promise.all(
270
- entries.sort((left, right) => left.name.localeCompare(right.name)).map((entry) => {
271
- const entryRelativePath = relativePath === "" ? entry.name : join2(relativePath, entry.name);
272
- if (entry.isDirectory()) {
273
- return createScreenshotFingerprint(screenshotDir, entryRelativePath);
274
- }
275
- return describeFile(join2(screenshotDir, entryRelativePath), entryRelativePath);
276
- })
277
- );
278
- return parts.flat().filter((part) => part !== null);
279
- } catch (error) {
280
- if (isFileNotFound2(error)) {
281
- return relativePath === "" ? ["screenshots:missing"] : [];
282
- }
283
- const errorMsg = error instanceof Error ? error.message : String(error);
284
- console.warn(`[Server] Unable to scan ${directoryPath}: ${errorMsg}`);
285
- return relativePath === "" ? ["screenshots:error"] : [];
286
- }
287
- }
288
- async function createArtifactsFingerprint(options) {
289
- const [offlineFingerprint, screenshotFingerprint] = await Promise.all([
290
- createOfflineFingerprint(options.offlineReportDir),
291
- createScreenshotFingerprint(options.screenshotDir)
292
- ]);
293
- return `${offlineFingerprint}::${screenshotFingerprint.join("|")}`;
294
- }
295
- async function watchReportArtifacts(options) {
296
- let fingerprint = await createArtifactsFingerprint(options);
297
- let isPolling = false;
298
- const interval = setInterval(() => {
299
- if (isPolling) {
300
- return;
301
- }
302
- isPolling = true;
303
- void createArtifactsFingerprint(options).then((nextFingerprint) => {
304
- if (nextFingerprint === fingerprint) {
305
- return;
306
- }
307
- fingerprint = nextFingerprint;
308
- options.scheduleRefresh();
309
- }).catch((error) => {
310
- const errorMsg = error instanceof Error ? error.message : String(error);
311
- console.warn(`[Server] Artifact refresh poll failed: ${errorMsg}`);
312
- }).finally(() => {
313
- isPolling = false;
314
- });
315
- }, 100);
316
- return () => {
317
- clearInterval(interval);
318
- };
319
- }
320
-
321
213
  // src/server/routes.ts
322
214
  import { existsSync } from "fs";
323
- import { dirname as dirname2, join as join3 } from "path";
215
+ import { dirname as dirname2, join as join2 } from "path";
324
216
  var LIVE_UPDATES_WEBSOCKET_PATH = "/";
325
217
  function isWebSocketUpgradeRequest(req) {
326
218
  return new URL(req.url).pathname === LIVE_UPDATES_WEBSOCKET_PATH && req.headers.get("upgrade")?.toLowerCase() === "websocket";
327
219
  }
328
220
  async function handleRoot(ctx) {
329
- const html = await respondWithFile(join3(ctx.staticDir, "index.html"), "text/html");
221
+ const html = await respondWithFile(join2(ctx.staticDir, "index.html"), "text/html");
330
222
  return html ?? new Response("Not Found", { status: 404 });
331
223
  }
332
224
  async function handleAppCss() {
@@ -345,7 +237,7 @@ function handleApiReport(ctx) {
345
237
  }
346
238
  var APPROVAL_TARGET_ERROR = "Could not resolve approval target";
347
239
  function actualPathFromUrl(ctx, actualUrl) {
348
- return actualUrl.startsWith("/screenshots/") ? join3(ctx.reportData.screenshotDir, actualUrl.slice("/screenshots/".length)) : actualUrl;
240
+ return actualUrl.startsWith("/screenshots/") ? join2(ctx.reportData.screenshotDir, actualUrl.slice("/screenshots/".length)) : actualUrl;
349
241
  }
350
242
  function reporterTitlePath(test) {
351
243
  const testFile = test.location?.file;
@@ -489,7 +381,7 @@ async function handleScreenshots(ctx, req) {
489
381
  }
490
382
  async function handleDist(ctx, req) {
491
383
  const path = new URL(req.url).pathname.slice("/dist/".length);
492
- const filePath = join3(ctx.staticDir, path);
384
+ const filePath = join2(ctx.staticDir, path);
493
385
  const contentType = filePath.endsWith(".css") ? "text/css" : filePath.endsWith(".js") ? "application/javascript" : filePath.endsWith(".svelte") ? "text/plain" : "application/octet-stream";
494
386
  const file = await respondWithFile(filePath, contentType);
495
387
  return file ?? new Response("Not Found", { status: 404 });
@@ -592,10 +484,6 @@ async function loadOfflineReports(offlineReportDir, reportData) {
592
484
  screenshotsBaseUrl: "/screenshots/"
593
485
  });
594
486
  }
595
- function resetReloadableReportData(reportData) {
596
- reportData.tests = {};
597
- reportData.isUpdateMode = false;
598
- }
599
487
  async function handleParsedWebSocketMessage(ctx, msg) {
600
488
  switch (msg.type) {
601
489
  case "test-begin": {
@@ -647,16 +535,16 @@ async function resolveStaticDir(staticDir) {
647
535
  const currentDir = dirname3(fileURLToPath(import.meta.url));
648
536
  const candidates = staticDir === void 0 ? [
649
537
  currentDir,
650
- join4(currentDir, "dist"),
651
- join4(currentDir, "..", "dist"),
652
- join4(currentDir, "..", "..", "dist"),
653
- join4(currentDir, ".."),
654
- join4(currentDir, "..", "..")
655
- ] : [staticDir, join4(staticDir, "dist")];
538
+ join3(currentDir, "dist"),
539
+ join3(currentDir, "..", "dist"),
540
+ join3(currentDir, "..", "..", "dist"),
541
+ join3(currentDir, ".."),
542
+ join3(currentDir, "..", "..")
543
+ ] : [staticDir, join3(staticDir, "dist")];
656
544
  const resolvedCandidates = await Promise.all(
657
545
  candidates.map(async (candidate) => ({
658
546
  candidate,
659
- exists: await fileExists(join4(candidate, "index.html"))
547
+ exists: await fileExists(join3(candidate, "index.html"))
660
548
  }))
661
549
  );
662
550
  const resolved = resolvedCandidates.find(({ exists }) => exists);
@@ -667,7 +555,7 @@ async function resolveStaticDir(staticDir) {
667
555
  }
668
556
  async function resolveReportPath(reportPath) {
669
557
  if (await isDirectory(reportPath)) {
670
- return { reportFile: join4(reportPath, "report.json"), offlineReportDir: reportPath };
558
+ return { reportFile: join3(reportPath, "report.json"), offlineReportDir: reportPath };
671
559
  }
672
560
  return { reportFile: reportPath, offlineReportDir: dirname3(reportPath) };
673
561
  }
@@ -700,22 +588,13 @@ async function createServerApp(options = {}) {
700
588
  const getHandlerContext = () => createHandlerContext(reportData, wsClients, currentRunIds, saveReport);
701
589
  const handleRequest = (req) => handleHttpRequest(routesContext, req);
702
590
  const handleWebSocketMessage = createWebSocketMessageHandler(getHandlerContext);
703
- const reloadFromDisk = async () => {
704
- resetReloadableReportData(reportData);
705
- await loadReport(reportFile, reportData);
706
- await loadOfflineReports(offlineReportDir, reportData);
707
- broadcastToBrowsers(wsClients, { type: "sync", data: reportData });
708
- };
709
- await reloadFromDisk();
710
- const close = await watchReportArtifacts({
711
- offlineReportDir,
712
- screenshotDir: reportData.screenshotDir,
713
- scheduleRefresh: createDebouncedRefresh(reloadFromDisk)
714
- });
591
+ await loadReport(reportFile, reportData);
592
+ await loadOfflineReports(offlineReportDir, reportData);
715
593
  return {
716
594
  port,
717
595
  wsClients,
718
- close,
596
+ close: () => {
597
+ },
719
598
  handleRequest,
720
599
  handleWebSocketMessage
721
600
  };
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  startServer
4
- } from "./chunk-XU5VQ3FZ.js";
4
+ } from "./chunk-TS64TROX.js";
5
5
  import "./chunk-EJRLZZ22.js";
6
6
 
7
7
  // src/cli.ts
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/server/app.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAI/C,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,8BAA8B,CAAC,EAAE,MAAM,CAAA;IACvC,sCAAsC,CAAC,EAAE,MAAM,CAAA;CAChD;AAUD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAA;IAChC,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,aAAa,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;IAClD,sBAAsB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3D;AAmMD,wBAAsB,eAAe,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,SAAS,CAAC,CAwCrF"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/server/app.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAI/C,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,8BAA8B,CAAC,EAAE,MAAM,CAAA;IACvC,sCAAsC,CAAC,EAAE,MAAM,CAAA;CAChD;AAUD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAA;IAChC,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,aAAa,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;IAClD,sBAAsB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3D;AA8LD,wBAAsB,eAAe,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,SAAS,CAAC,CA6BrF"}
package/dist/server.cjs CHANGED
@@ -35,7 +35,7 @@ __export(server_exports, {
35
35
  module.exports = __toCommonJS(server_exports);
36
36
 
37
37
  // src/server/app.ts
38
- var import_path6 = require("path");
38
+ var import_path5 = require("path");
39
39
  var import_url = require("url");
40
40
  var import_p_limit = __toESM(require("p-limit"), 1);
41
41
 
@@ -562,121 +562,13 @@ function handleSync(ctx) {
562
562
  broadcastToBrowsers(ctx.wsClients, { type: "sync", data: ctx.reportData });
563
563
  }
564
564
 
565
- // src/server/report-watch.ts
566
- var import_promises3 = require("fs/promises");
567
- var import_path3 = require("path");
568
- var OFFLINE_REPORT_FILE_PATTERN2 = /^crvy-rprtr(?:-\d+)?\.json$/;
569
- function createDebouncedRefresh(reload, delayMs = 50) {
570
- let timer = null;
571
- return () => {
572
- if (timer !== null) {
573
- clearTimeout(timer);
574
- }
575
- timer = setTimeout(() => {
576
- timer = null;
577
- void reload();
578
- }, delayMs);
579
- };
580
- }
581
- function isFileNotFound2(error) {
582
- return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
583
- }
584
- async function describeFile(filePath, label) {
585
- try {
586
- const fileStats = await (0, import_promises3.stat)(filePath);
587
- return `${label}:${fileStats.size}:${fileStats.mtimeMs}`;
588
- } catch (error) {
589
- if (isFileNotFound2(error)) {
590
- return null;
591
- }
592
- throw error;
593
- }
594
- }
595
- async function createOfflineFingerprint(offlineReportDir) {
596
- if (!await isDirectory(offlineReportDir)) {
597
- return "offline:missing";
598
- }
599
- try {
600
- const entries = await (0, import_promises3.readdir)(offlineReportDir, { withFileTypes: true });
601
- const relevantEntries = entries.filter(
602
- (entry) => entry.isFile() && (entry.name === "report.json" || OFFLINE_REPORT_FILE_PATTERN2.test(entry.name))
603
- ).sort((left, right) => left.name.localeCompare(right.name));
604
- const parts = await Promise.all(
605
- relevantEntries.map((entry) => describeFile((0, import_path3.join)(offlineReportDir, entry.name), entry.name))
606
- );
607
- return `offline:${parts.filter((part) => part !== null).join("|")}`;
608
- } catch (error) {
609
- const errorMsg = error instanceof Error ? error.message : String(error);
610
- console.warn(`[Server] Unable to scan ${offlineReportDir}: ${errorMsg}`);
611
- return "offline:error";
612
- }
613
- }
614
- async function createScreenshotFingerprint(screenshotDir, relativePath = "") {
615
- const directoryPath = relativePath === "" ? screenshotDir : (0, import_path3.join)(screenshotDir, relativePath);
616
- if (!await isDirectory(directoryPath)) {
617
- return relativePath === "" ? ["screenshots:missing"] : [];
618
- }
619
- try {
620
- const entries = await (0, import_promises3.readdir)(directoryPath, { withFileTypes: true });
621
- const parts = await Promise.all(
622
- entries.sort((left, right) => left.name.localeCompare(right.name)).map((entry) => {
623
- const entryRelativePath = relativePath === "" ? entry.name : (0, import_path3.join)(relativePath, entry.name);
624
- if (entry.isDirectory()) {
625
- return createScreenshotFingerprint(screenshotDir, entryRelativePath);
626
- }
627
- return describeFile((0, import_path3.join)(screenshotDir, entryRelativePath), entryRelativePath);
628
- })
629
- );
630
- return parts.flat().filter((part) => part !== null);
631
- } catch (error) {
632
- if (isFileNotFound2(error)) {
633
- return relativePath === "" ? ["screenshots:missing"] : [];
634
- }
635
- const errorMsg = error instanceof Error ? error.message : String(error);
636
- console.warn(`[Server] Unable to scan ${directoryPath}: ${errorMsg}`);
637
- return relativePath === "" ? ["screenshots:error"] : [];
638
- }
639
- }
640
- async function createArtifactsFingerprint(options) {
641
- const [offlineFingerprint, screenshotFingerprint] = await Promise.all([
642
- createOfflineFingerprint(options.offlineReportDir),
643
- createScreenshotFingerprint(options.screenshotDir)
644
- ]);
645
- return `${offlineFingerprint}::${screenshotFingerprint.join("|")}`;
646
- }
647
- async function watchReportArtifacts(options) {
648
- let fingerprint = await createArtifactsFingerprint(options);
649
- let isPolling = false;
650
- const interval = setInterval(() => {
651
- if (isPolling) {
652
- return;
653
- }
654
- isPolling = true;
655
- void createArtifactsFingerprint(options).then((nextFingerprint) => {
656
- if (nextFingerprint === fingerprint) {
657
- return;
658
- }
659
- fingerprint = nextFingerprint;
660
- options.scheduleRefresh();
661
- }).catch((error) => {
662
- const errorMsg = error instanceof Error ? error.message : String(error);
663
- console.warn(`[Server] Artifact refresh poll failed: ${errorMsg}`);
664
- }).finally(() => {
665
- isPolling = false;
666
- });
667
- }, 100);
668
- return () => {
669
- clearInterval(interval);
670
- };
671
- }
672
-
673
565
  // src/server/routes.ts
674
566
  var import_fs = require("fs");
675
- var import_path5 = require("path");
567
+ var import_path4 = require("path");
676
568
 
677
569
  // src/snapshot-path-resolver.ts
678
570
  var import_crypto = require("crypto");
679
- var import_path4 = require("path");
571
+ var import_path3 = require("path");
680
572
  var DEFAULT_SCREENSHOT_TEMPLATE = "{snapshotDir}/{testFileDir}/{testFileName}-snapshots/{arg}{-projectName}{-snapshotSuffix}{ext}";
681
573
  var WINDOWS_FILESYSTEM_FRIENDLY_LENGTH = 60;
682
574
  function isUnsafeFilePathCharacter(character) {
@@ -711,16 +603,16 @@ function trimLongString(value, length = WINDOWS_FILESYSTEM_FRIENDLY_LENGTH) {
711
603
  const end = length - middle.length - start;
712
604
  return value.slice(0, start) + middle + value.slice(-end);
713
605
  }
714
- function sanitizeFilePathBeforeExtension(filePath, extension = (0, import_path4.extname)(filePath)) {
606
+ function sanitizeFilePathBeforeExtension(filePath, extension = (0, import_path3.extname)(filePath)) {
715
607
  const base = filePath.slice(0, filePath.length - extension.length);
716
608
  return sanitizeForFilePath(base) + extension;
717
609
  }
718
610
  function addSuffixToFilePath(filePath, suffix) {
719
- const extension = (0, import_path4.extname)(filePath);
611
+ const extension = (0, import_path3.extname)(filePath);
720
612
  return filePath.slice(0, filePath.length - extension.length) + suffix + extension;
721
613
  }
722
614
  function normalizedSnapshotDir(config) {
723
- return (0, import_path4.resolve)(config.configDir, config.snapshotDir);
615
+ return (0, import_path3.resolve)(config.configDir, config.snapshotDir);
724
616
  }
725
617
  function templateValue(template, token, value) {
726
618
  return template.replace(
@@ -730,8 +622,8 @@ function templateValue(template, token, value) {
730
622
  }
731
623
  function applyTemplate(input, nameArgument, extension) {
732
624
  const template = input.config.toHaveScreenshotPathTemplate ?? input.config.snapshotPathTemplate ?? DEFAULT_SCREENSHOT_TEMPLATE;
733
- const relativeTestFilePath = (0, import_path4.relative)(input.config.testDir, input.testFile);
734
- const parsed = (0, import_path4.parse)(relativeTestFilePath);
625
+ const relativeTestFilePath = (0, import_path3.relative)(input.config.testDir, input.testFile);
626
+ const parsed = (0, import_path3.parse)(relativeTestFilePath);
735
627
  const tokens = [
736
628
  ["testDir", input.config.testDir],
737
629
  ["snapshotDir", normalizedSnapshotDir(input.config)],
@@ -749,16 +641,16 @@ function applyTemplate(input, nameArgument, extension) {
749
641
  (currentTemplate, [token, value]) => templateValue(currentTemplate, token, value),
750
642
  template
751
643
  );
752
- return (0, import_path4.resolve)(input.config.configDir, snapshotPath);
644
+ return (0, import_path3.resolve)(input.config.configDir, snapshotPath);
753
645
  }
754
- function removeExtension(filePath, extension = (0, import_path4.extname)(filePath)) {
646
+ function removeExtension(filePath, extension = (0, import_path3.extname)(filePath)) {
755
647
  return filePath.slice(0, filePath.length - extension.length);
756
648
  }
757
649
  function snapshotNameParts(declaredName) {
758
- const extension = (0, import_path4.extname)(declaredName) || ".png";
650
+ const extension = (0, import_path3.extname)(declaredName) || ".png";
759
651
  return {
760
652
  extension,
761
- filePath: (0, import_path4.extname)(declaredName) === "" ? `${declaredName}${extension}` : declaredName
653
+ filePath: (0, import_path3.extname)(declaredName) === "" ? `${declaredName}${extension}` : declaredName
762
654
  };
763
655
  }
764
656
  function filePathForOccurrence(filePath, occurrenceIndex) {
@@ -782,7 +674,7 @@ function resolveStringCallTarget(input, declaration) {
782
674
  function resolveArrayCallTarget(input, declaration) {
783
675
  const { extension, filePath } = snapshotNameParts(declaration.declaredName);
784
676
  const occurrenceFilePath = filePathForOccurrence(filePath, declaration.occurrenceIndex);
785
- const nameArgument = (0, import_path4.join)((0, import_path4.dirname)(occurrenceFilePath), (0, import_path4.basename)(occurrenceFilePath, extension));
677
+ const nameArgument = (0, import_path3.join)((0, import_path3.dirname)(occurrenceFilePath), (0, import_path3.basename)(occurrenceFilePath, extension));
786
678
  return createResolvedBaselineTarget(input, declaration, nameArgument, extension);
787
679
  }
788
680
  function resolveNamedTarget(input, declaration) {
@@ -818,7 +710,7 @@ function resolveTarget(input, declaration) {
818
710
  case "unnamed": {
819
711
  const anonymousFileName = anonymousName(input.reporterTitlePath, declaration.occurrenceIndex);
820
712
  const extension = ".png";
821
- const nameArgument = (0, import_path4.join)((0, import_path4.dirname)(anonymousFileName), (0, import_path4.basename)(anonymousFileName, extension));
713
+ const nameArgument = (0, import_path3.join)((0, import_path3.dirname)(anonymousFileName), (0, import_path3.basename)(anonymousFileName, extension));
822
714
  return createResolvedBaselineTarget(input, declaration, nameArgument, extension);
823
715
  }
824
716
  }
@@ -836,7 +728,7 @@ function isWebSocketUpgradeRequest(req) {
836
728
  return new URL(req.url).pathname === LIVE_UPDATES_WEBSOCKET_PATH && req.headers.get("upgrade")?.toLowerCase() === "websocket";
837
729
  }
838
730
  async function handleRoot(ctx) {
839
- const html = await respondWithFile((0, import_path5.join)(ctx.staticDir, "index.html"), "text/html");
731
+ const html = await respondWithFile((0, import_path4.join)(ctx.staticDir, "index.html"), "text/html");
840
732
  return html ?? new Response("Not Found", { status: 404 });
841
733
  }
842
734
  async function handleAppCss() {
@@ -855,7 +747,7 @@ function handleApiReport(ctx) {
855
747
  }
856
748
  var APPROVAL_TARGET_ERROR = "Could not resolve approval target";
857
749
  function actualPathFromUrl(ctx, actualUrl) {
858
- return actualUrl.startsWith("/screenshots/") ? (0, import_path5.join)(ctx.reportData.screenshotDir, actualUrl.slice("/screenshots/".length)) : actualUrl;
750
+ return actualUrl.startsWith("/screenshots/") ? (0, import_path4.join)(ctx.reportData.screenshotDir, actualUrl.slice("/screenshots/".length)) : actualUrl;
859
751
  }
860
752
  function reporterTitlePath(test) {
861
753
  const testFile = test.location?.file;
@@ -873,8 +765,8 @@ function resolveApprovalTarget(ctx, test, retry, imageName) {
873
765
  declarations: [declaration],
874
766
  config: {
875
767
  configDir: ctx.approvalRouting.configDir,
876
- testDir: ctx.approvalRouting.playwrightTestDir ?? (0, import_path5.dirname)(testFile),
877
- snapshotDir: ctx.approvalRouting.playwrightSnapshotDir ?? (0, import_path5.dirname)(testFile),
768
+ testDir: ctx.approvalRouting.playwrightTestDir ?? (0, import_path4.dirname)(testFile),
769
+ snapshotDir: ctx.approvalRouting.playwrightSnapshotDir ?? (0, import_path4.dirname)(testFile),
878
770
  projectName: test.browser,
879
771
  snapshotSuffix: process.platform,
880
772
  snapshotPathTemplate: ctx.approvalRouting.playwrightSnapshotPathTemplate,
@@ -999,7 +891,7 @@ async function handleScreenshots(ctx, req) {
999
891
  }
1000
892
  async function handleDist(ctx, req) {
1001
893
  const path = new URL(req.url).pathname.slice("/dist/".length);
1002
- const filePath = (0, import_path5.join)(ctx.staticDir, path);
894
+ const filePath = (0, import_path4.join)(ctx.staticDir, path);
1003
895
  const contentType = filePath.endsWith(".css") ? "text/css" : filePath.endsWith(".js") ? "application/javascript" : filePath.endsWith(".svelte") ? "text/plain" : "application/octet-stream";
1004
896
  const file = await respondWithFile(filePath, contentType);
1005
897
  return file ?? new Response("Not Found", { status: 404 });
@@ -1103,10 +995,6 @@ async function loadOfflineReports(offlineReportDir, reportData) {
1103
995
  screenshotsBaseUrl: "/screenshots/"
1104
996
  });
1105
997
  }
1106
- function resetReloadableReportData(reportData) {
1107
- reportData.tests = {};
1108
- reportData.isUpdateMode = false;
1109
- }
1110
998
  async function handleParsedWebSocketMessage(ctx, msg) {
1111
999
  switch (msg.type) {
1112
1000
  case "test-begin": {
@@ -1155,19 +1043,19 @@ function createWebSocketMessageHandler(getHandlerContext) {
1155
1043
  };
1156
1044
  }
1157
1045
  async function resolveStaticDir(staticDir) {
1158
- const currentDir = (0, import_path6.dirname)((0, import_url.fileURLToPath)(import_meta.url));
1046
+ const currentDir = (0, import_path5.dirname)((0, import_url.fileURLToPath)(import_meta.url));
1159
1047
  const candidates = staticDir === void 0 ? [
1160
1048
  currentDir,
1161
- (0, import_path6.join)(currentDir, "dist"),
1162
- (0, import_path6.join)(currentDir, "..", "dist"),
1163
- (0, import_path6.join)(currentDir, "..", "..", "dist"),
1164
- (0, import_path6.join)(currentDir, ".."),
1165
- (0, import_path6.join)(currentDir, "..", "..")
1166
- ] : [staticDir, (0, import_path6.join)(staticDir, "dist")];
1049
+ (0, import_path5.join)(currentDir, "dist"),
1050
+ (0, import_path5.join)(currentDir, "..", "dist"),
1051
+ (0, import_path5.join)(currentDir, "..", "..", "dist"),
1052
+ (0, import_path5.join)(currentDir, ".."),
1053
+ (0, import_path5.join)(currentDir, "..", "..")
1054
+ ] : [staticDir, (0, import_path5.join)(staticDir, "dist")];
1167
1055
  const resolvedCandidates = await Promise.all(
1168
1056
  candidates.map(async (candidate) => ({
1169
1057
  candidate,
1170
- exists: await fileExists((0, import_path6.join)(candidate, "index.html"))
1058
+ exists: await fileExists((0, import_path5.join)(candidate, "index.html"))
1171
1059
  }))
1172
1060
  );
1173
1061
  const resolved = resolvedCandidates.find(({ exists }) => exists);
@@ -1178,9 +1066,9 @@ async function resolveStaticDir(staticDir) {
1178
1066
  }
1179
1067
  async function resolveReportPath(reportPath) {
1180
1068
  if (await isDirectory(reportPath)) {
1181
- return { reportFile: (0, import_path6.join)(reportPath, "report.json"), offlineReportDir: reportPath };
1069
+ return { reportFile: (0, import_path5.join)(reportPath, "report.json"), offlineReportDir: reportPath };
1182
1070
  }
1183
- return { reportFile: reportPath, offlineReportDir: (0, import_path6.dirname)(reportPath) };
1071
+ return { reportFile: reportPath, offlineReportDir: (0, import_path5.dirname)(reportPath) };
1184
1072
  }
1185
1073
  function createRoutesContext(reportData, staticDir, saveReport, options) {
1186
1074
  return {
@@ -1211,22 +1099,13 @@ async function createServerApp(options = {}) {
1211
1099
  const getHandlerContext = () => createHandlerContext(reportData, wsClients, currentRunIds, saveReport);
1212
1100
  const handleRequest = (req) => handleHttpRequest(routesContext, req);
1213
1101
  const handleWebSocketMessage = createWebSocketMessageHandler(getHandlerContext);
1214
- const reloadFromDisk = async () => {
1215
- resetReloadableReportData(reportData);
1216
- await loadReport(reportFile, reportData);
1217
- await loadOfflineReports(offlineReportDir, reportData);
1218
- broadcastToBrowsers(wsClients, { type: "sync", data: reportData });
1219
- };
1220
- await reloadFromDisk();
1221
- const close = await watchReportArtifacts({
1222
- offlineReportDir,
1223
- screenshotDir: reportData.screenshotDir,
1224
- scheduleRefresh: createDebouncedRefresh(reloadFromDisk)
1225
- });
1102
+ await loadReport(reportFile, reportData);
1103
+ await loadOfflineReports(offlineReportDir, reportData);
1226
1104
  return {
1227
1105
  port,
1228
1106
  wsClients,
1229
- close,
1107
+ close: () => {
1108
+ },
1230
1109
  handleRequest,
1231
1110
  handleWebSocketMessage
1232
1111
  };
package/dist/server.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  startServer
3
- } from "./chunk-XU5VQ3FZ.js";
3
+ } from "./chunk-TS64TROX.js";
4
4
  import "./chunk-EJRLZZ22.js";
5
5
  export {
6
6
  startServer
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crvy/rprtr",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "description": "Playwright reporter with visual regression UI for comparing and approving screenshot tests",
5
5
  "keywords": [
6
6
  "crvy",
@@ -1,9 +0,0 @@
1
- export declare function createDebouncedRefresh(reload: () => Promise<void>, delayMs?: number): () => void;
2
- interface ReportWatchOptions {
3
- offlineReportDir: string;
4
- screenshotDir: string;
5
- scheduleRefresh: () => void;
6
- }
7
- export declare function watchReportArtifacts(options: ReportWatchOptions): Promise<() => void>;
8
- export {};
9
- //# sourceMappingURL=report-watch.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"report-watch.d.ts","sourceRoot":"","sources":["../../src/server/report-watch.ts"],"names":[],"mappings":"AAOA,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,SAAK,GAAG,MAAM,IAAI,CAa5F;AAED,UAAU,kBAAkB;IAC1B,gBAAgB,EAAE,MAAM,CAAA;IACxB,aAAa,EAAE,MAAM,CAAA;IACrB,eAAe,EAAE,MAAM,IAAI,CAAA;CAC5B;AAsFD,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,CAgC3F"}