@flakiness/sdk 2.2.2 → 2.3.1

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/README.md CHANGED
@@ -10,6 +10,8 @@ The Flakiness SDK provides a comprehensive set of tools for creating and managin
10
10
  npm i @flakiness/sdk @flakiness/flakiness-report
11
11
  ```
12
12
 
13
+ Requires Node.js 22+.
14
+
13
15
  ## Quick Start
14
16
 
15
17
  Here's a minimal example of creating a Flakiness JSON Report:
@@ -96,6 +98,7 @@ Use this entry point when you need to process or manipulate reports in browser-b
96
98
  ### Working with Reports
97
99
  - **`readReport()`** - Read a Flakiness report and its attachments from disk
98
100
  - **`showReport()`** - Start a local server and open the report in your browser
101
+ - **`showReportCommand()`** - Build a shell command for opening the report later with the Flakiness CLI
99
102
  - **`uploadReport()`** - Upload reports and attachments to Flakiness.io
100
103
  - **`writeReport()`** - Write reports to disk in the standard Flakiness report format
101
104
 
@@ -125,4 +128,3 @@ Use this entry point when you need to process or manipulate reports in browser-b
125
128
  ```
126
129
 
127
130
  If neither method is available, the upload is skipped with a `'skipped'` status.
128
-
package/lib/browser.js CHANGED
@@ -13,7 +13,7 @@ __export(reportUtilsBrowser_exports, {
13
13
  visitTests: () => visitTests
14
14
  });
15
15
 
16
- // node_modules/.pnpm/@flakiness+flakiness-report@0.27.0_zod@4.3.5/node_modules/@flakiness/flakiness-report/lib/flakinessReport.js
16
+ // node_modules/.pnpm/@flakiness+flakiness-report@0.28.0_zod@4.3.5/node_modules/@flakiness/flakiness-report/lib/flakinessReport.js
17
17
  var FlakinessReport;
18
18
  ((FlakinessReport22) => {
19
19
  FlakinessReport22.CATEGORY_PLAYWRIGHT = "playwright";
@@ -23,7 +23,7 @@ var FlakinessReport;
23
23
  FlakinessReport22.STREAM_STDERR = 2;
24
24
  })(FlakinessReport || (FlakinessReport = {}));
25
25
 
26
- // node_modules/.pnpm/@flakiness+flakiness-report@0.27.0_zod@4.3.5/node_modules/@flakiness/flakiness-report/lib/schema.js
26
+ // node_modules/.pnpm/@flakiness+flakiness-report@0.28.0_zod@4.3.5/node_modules/@flakiness/flakiness-report/lib/schema.js
27
27
  import z from "zod/v4";
28
28
  var Schema;
29
29
  ((Schema2) => {
@@ -138,8 +138,15 @@ var Schema;
138
138
  samples: z.array(Schema2.SystemUtilizationSample)
139
139
  });
140
140
  Schema2.UtilizationTelemetry = z.tuple([Schema2.DurationMS, z.number().min(0).max(100)]);
141
+ Schema2.Source = z.object({
142
+ filePath: Schema2.GitFilePath,
143
+ text: z.string(),
144
+ lineOffset: z.number().optional(),
145
+ contentType: z.string().optional()
146
+ });
141
147
  Schema2.FlakinessProject = z.string();
142
148
  Schema2.Report = z.object({
149
+ sources: z.array(Schema2.Source).optional(),
143
150
  flakinessProject: Schema2.FlakinessProject.optional(),
144
151
  category: z.string().min(1).max(100),
145
152
  commitId: Schema2.CommitId,
package/lib/index.js CHANGED
@@ -679,7 +679,7 @@ function createEnvironment(options) {
679
679
  };
680
680
  }
681
681
 
682
- // node_modules/.pnpm/@flakiness+flakiness-report@0.27.0_zod@4.3.5/node_modules/@flakiness/flakiness-report/lib/flakinessReport.js
682
+ // node_modules/.pnpm/@flakiness+flakiness-report@0.28.0_zod@4.3.5/node_modules/@flakiness/flakiness-report/lib/flakinessReport.js
683
683
  var FlakinessReport;
684
684
  ((FlakinessReport22) => {
685
685
  FlakinessReport22.CATEGORY_PLAYWRIGHT = "playwright";
@@ -689,7 +689,7 @@ var FlakinessReport;
689
689
  FlakinessReport22.STREAM_STDERR = 2;
690
690
  })(FlakinessReport || (FlakinessReport = {}));
691
691
 
692
- // node_modules/.pnpm/@flakiness+flakiness-report@0.27.0_zod@4.3.5/node_modules/@flakiness/flakiness-report/lib/schema.js
692
+ // node_modules/.pnpm/@flakiness+flakiness-report@0.28.0_zod@4.3.5/node_modules/@flakiness/flakiness-report/lib/schema.js
693
693
  import z from "zod/v4";
694
694
  var Schema;
695
695
  ((Schema2) => {
@@ -804,8 +804,15 @@ var Schema;
804
804
  samples: z.array(Schema2.SystemUtilizationSample)
805
805
  });
806
806
  Schema2.UtilizationTelemetry = z.tuple([Schema2.DurationMS, z.number().min(0).max(100)]);
807
+ Schema2.Source = z.object({
808
+ filePath: Schema2.GitFilePath,
809
+ text: z.string(),
810
+ lineOffset: z.number().optional(),
811
+ contentType: z.string().optional()
812
+ });
807
813
  Schema2.FlakinessProject = z.string();
808
814
  Schema2.Report = z.object({
815
+ sources: z.array(Schema2.Source).optional(),
809
816
  flakinessProject: Schema2.FlakinessProject.optional(),
810
817
  category: z.string().min(1).max(100),
811
818
  commitId: Schema2.CommitId,
@@ -1279,7 +1286,7 @@ async function listFilesRecursively(dir, result = []) {
1279
1286
  }
1280
1287
 
1281
1288
  // src/showReport.ts
1282
- import chalk from "chalk";
1289
+ import { styleText } from "node:util";
1283
1290
  import open from "open";
1284
1291
 
1285
1292
  // src/staticServer.ts
@@ -1442,7 +1449,7 @@ async function showReport(reportFolder, options) {
1442
1449
  const url = new URL(reportViewerUrl);
1443
1450
  url.searchParams.set("port", String(server.port()));
1444
1451
  url.searchParams.set("token", token);
1445
- console.log(chalk.cyan(`
1452
+ console.log(styleText("cyan", `
1446
1453
  Serving Flakiness report at ${url.toString()}
1447
1454
  Press Ctrl+C to quit.`));
1448
1455
  await open(url.toString());
@@ -1450,24 +1457,123 @@ async function showReport(reportFolder, options) {
1450
1457
  });
1451
1458
  }
1452
1459
 
1460
+ // src/showReportCommand.ts
1461
+ import fs7 from "node:fs";
1462
+ import path3 from "node:path";
1463
+ import which from "which";
1464
+ var DEFAULT_REPORT_FOLDER = "flakiness-report";
1465
+ var FLAKINESS_CLI_COMMANDS = {
1466
+ GLOBAL: "flakiness",
1467
+ PNPM: "pnpm dlx flakiness",
1468
+ NPM: "npx flakiness"
1469
+ };
1470
+ function showReportCommand(reportFolder) {
1471
+ const userCwd = path3.resolve(process.env.INIT_CWD || process.cwd());
1472
+ const flakinessCLI = detectFlakinessCLIFromEnv() ?? detectFlakinessCLIFromFilesystem(userCwd) ?? detectFlakinessCLIFromPath() ?? FLAKINESS_CLI_COMMANDS.NPM;
1473
+ const absoluteReportFolder = path3.resolve(reportFolder);
1474
+ const reportFolderArg = formatReportFolderArg(absoluteReportFolder, userCwd);
1475
+ return `${flakinessCLI} show${reportFolderArg ? ` ${reportFolderArg}` : ""}`;
1476
+ }
1477
+ function detectFlakinessCLIFromEnv() {
1478
+ const userAgent = process.env.npm_config_user_agent ?? "";
1479
+ if (userAgent.startsWith("pnpm/"))
1480
+ return FLAKINESS_CLI_COMMANDS.PNPM;
1481
+ if (userAgent.startsWith("npm/"))
1482
+ return FLAKINESS_CLI_COMMANDS.NPM;
1483
+ const execPath = process.env.npm_execpath ?? "";
1484
+ const execName = execPath ? path3.basename(execPath).toLowerCase() : "";
1485
+ if (execName.startsWith("pnpm"))
1486
+ return FLAKINESS_CLI_COMMANDS.PNPM;
1487
+ return void 0;
1488
+ }
1489
+ function detectFlakinessCLIFromFilesystem(userCwd) {
1490
+ for (const dir of ancestorDirectories(userCwd)) {
1491
+ const packageManager = parsePackageJSON(dir);
1492
+ if (packageManager === "pnpm")
1493
+ return FLAKINESS_CLI_COMMANDS.PNPM;
1494
+ if (packageManager === "npm" || packageManager === "other")
1495
+ return FLAKINESS_CLI_COMMANDS.NPM;
1496
+ if (fs7.existsSync(path3.join(dir, "pnpm-lock.yaml")))
1497
+ return FLAKINESS_CLI_COMMANDS.PNPM;
1498
+ if (fs7.existsSync(path3.join(dir, "pnpm-workspace.yaml")))
1499
+ return FLAKINESS_CLI_COMMANDS.PNPM;
1500
+ }
1501
+ return void 0;
1502
+ }
1503
+ function detectFlakinessCLIFromPath() {
1504
+ if (which.sync("flakiness", { nothrow: true }))
1505
+ return FLAKINESS_CLI_COMMANDS.GLOBAL;
1506
+ if (which.sync("npx", { nothrow: true }))
1507
+ return FLAKINESS_CLI_COMMANDS.NPM;
1508
+ if (which.sync("pnpm", { nothrow: true }))
1509
+ return FLAKINESS_CLI_COMMANDS.PNPM;
1510
+ return void 0;
1511
+ }
1512
+ function parsePackageJSON(dir) {
1513
+ const packageJsonPath = path3.join(dir, "package.json");
1514
+ if (!fs7.existsSync(packageJsonPath))
1515
+ return void 0;
1516
+ try {
1517
+ const packageJson = JSON.parse(fs7.readFileSync(packageJsonPath, "utf8"));
1518
+ if (typeof packageJson.packageManager !== "string")
1519
+ return void 0;
1520
+ if (packageJson.packageManager.startsWith("pnpm@"))
1521
+ return "pnpm";
1522
+ if (packageJson.packageManager.startsWith("npm@"))
1523
+ return "npm";
1524
+ return "other";
1525
+ } catch {
1526
+ return void 0;
1527
+ }
1528
+ }
1529
+ function ancestorDirectories(startDir) {
1530
+ const directories = [];
1531
+ let current = path3.resolve(startDir);
1532
+ while (true) {
1533
+ directories.push(current);
1534
+ const parent = path3.dirname(current);
1535
+ if (parent === current)
1536
+ return directories;
1537
+ current = parent;
1538
+ }
1539
+ }
1540
+ function formatReportFolderArg(reportFolder, userCwd) {
1541
+ if (isSamePath(reportFolder, path3.resolve(userCwd, DEFAULT_REPORT_FOLDER)))
1542
+ return "";
1543
+ const relativePath = path3.relative(userCwd, reportFolder) || ".";
1544
+ return quoteShellArgument(relativePath);
1545
+ }
1546
+ function isSamePath(left, right) {
1547
+ const normalizedLeft = path3.resolve(left);
1548
+ const normalizedRight = path3.resolve(right);
1549
+ if (process.platform === "win32")
1550
+ return normalizedLeft.toLowerCase() === normalizedRight.toLowerCase();
1551
+ return normalizedLeft === normalizedRight;
1552
+ }
1553
+ function quoteShellArgument(argument) {
1554
+ if (/^[A-Za-z0-9_./:@%+=,-]+$/u.test(argument))
1555
+ return argument;
1556
+ return JSON.stringify(argument);
1557
+ }
1558
+
1453
1559
  // src/writeReport.ts
1454
- import fs7 from "fs";
1455
- import path3 from "path";
1560
+ import fs8 from "fs";
1561
+ import path4 from "path";
1456
1562
  async function writeReport(report, attachments, outputFolder) {
1457
- const reportPath = path3.join(outputFolder, "report.json");
1458
- const attachmentsFolder = path3.join(outputFolder, "attachments");
1459
- await fs7.promises.rm(outputFolder, { recursive: true, force: true });
1460
- await fs7.promises.mkdir(outputFolder, { recursive: true });
1461
- await fs7.promises.writeFile(reportPath, JSON.stringify(report), "utf-8");
1563
+ const reportPath = path4.join(outputFolder, "report.json");
1564
+ const attachmentsFolder = path4.join(outputFolder, "attachments");
1565
+ await fs8.promises.rm(outputFolder, { recursive: true, force: true });
1566
+ await fs8.promises.mkdir(outputFolder, { recursive: true });
1567
+ await fs8.promises.writeFile(reportPath, JSON.stringify(report), "utf-8");
1462
1568
  if (attachments.length)
1463
- await fs7.promises.mkdir(attachmentsFolder);
1569
+ await fs8.promises.mkdir(attachmentsFolder);
1464
1570
  const movedAttachments = [];
1465
1571
  for (const attachment of attachments) {
1466
- const attachmentPath = path3.join(attachmentsFolder, attachment.id);
1572
+ const attachmentPath = path4.join(attachmentsFolder, attachment.id);
1467
1573
  if (attachment.type === "file")
1468
- await fs7.promises.cp(attachment.path, attachmentPath);
1574
+ await fs8.promises.cp(attachment.path, attachmentPath);
1469
1575
  else if (attachment.type === "buffer")
1470
- await fs7.promises.writeFile(attachmentPath, attachment.body);
1576
+ await fs8.promises.writeFile(attachmentPath, attachment.body);
1471
1577
  movedAttachments.push({
1472
1578
  type: "file",
1473
1579
  contentType: attachment.contentType,
@@ -1486,6 +1592,7 @@ export {
1486
1592
  reportUtils_exports as ReportUtils,
1487
1593
  readReport,
1488
1594
  showReport,
1595
+ showReportCommand,
1489
1596
  uploadReport,
1490
1597
  writeReport
1491
1598
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flakiness/sdk",
3
- "version": "2.2.2",
3
+ "version": "2.3.1",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
@@ -24,12 +24,16 @@
24
24
  "keywords": [],
25
25
  "author": "Degu Labs, Inc",
26
26
  "license": "MIT",
27
+ "engines": {
28
+ "node": ">=22"
29
+ },
27
30
  "devDependencies": {
28
- "@flakiness/flakiness-report": "^0.27.0",
29
- "@flakiness/playwright": "^1.3.2",
31
+ "@flakiness/flakiness-report": "^0.28.0",
32
+ "@flakiness/playwright": "^1.3.3",
30
33
  "@playwright/test": "^1.58.2",
31
34
  "@types/debug": "^4.1.12",
32
35
  "@types/node": "^25.0.3",
36
+ "@types/which": "^3.0.4",
33
37
  "esbuild": "^0.27.0",
34
38
  "kubik": "^0.24.0",
35
39
  "tsx": "^4.21.0",
@@ -39,14 +43,16 @@
39
43
  "@flakiness/flakiness-report": ">=0.26.0 <1.0.0"
40
44
  },
41
45
  "dependencies": {
42
- "chalk": "^5.6.2",
43
46
  "debug": "^4.4.3",
44
47
  "open": "^10.2.0",
45
48
  "stable-hash": "^0.0.6",
49
+ "which": "^6.0.1",
46
50
  "zod": "^4.3.5"
47
51
  },
48
52
  "scripts": {
49
53
  "minor": "./version.mjs minor",
50
- "patch": "./version.mjs patch"
54
+ "patch": "./version.mjs patch",
55
+ "test": "pnpm playwright test",
56
+ "build": "kubik ./build.mts"
51
57
  }
52
58
  }
@@ -6,6 +6,7 @@ export { GithubOIDC } from './githubOIDC.js';
6
6
  export * as ReportUtils from './reportUtils.js';
7
7
  export { readReport } from './readReport.js';
8
8
  export { showReport } from './showReport.js';
9
+ export { showReportCommand } from './showReportCommand.js';
9
10
  export { uploadReport } from './uploadReport.js';
10
11
  export { writeReport } from './writeReport.js';
11
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAC;AAGhD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAC;AAGhD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Builds a command that opens a Flakiness report with the Flakiness CLI.
3
+ *
4
+ * The command is tailored for the shell directory from which the current process
5
+ * was originally invoked. This matters when package managers like pnpm change the
6
+ * working directory while running scripts.
7
+ *
8
+ * @param {string} reportFolder - Absolute or relative path to the report folder.
9
+ *
10
+ * @returns {string} A shell command such as `pnpm dlx flakiness show`.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const command = showReportCommand('./flakiness-report');
15
+ * // Returns: "npx flakiness show"
16
+ * ```
17
+ */
18
+ export declare function showReportCommand(reportFolder: string): string;
19
+ //# sourceMappingURL=showReportCommand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"showReportCommand.d.ts","sourceRoot":"","sources":["../../src/showReportCommand.ts"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAM9D"}
@@ -11,7 +11,9 @@
11
11
  *
12
12
  * @example
13
13
  * ```typescript
14
- * const clean = stripAnsi(chalk.red('Error: test failed'));
14
+ * import { styleText } from 'node:util';
15
+ *
16
+ * const clean = stripAnsi(styleText('red', 'Error: test failed'));
15
17
  * // Returns: 'Error: test failed' (without color codes)
16
18
  * ```
17
19
  */
@@ -1 +1 @@
1
- {"version":3,"file":"stripAnsi.d.ts","sourceRoot":"","sources":["../../src/stripAnsi.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7C"}
1
+ {"version":3,"file":"stripAnsi.d.ts","sourceRoot":"","sources":["../../src/stripAnsi.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7C"}