@flakiness/sdk 0.145.0 → 0.145.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.
@@ -2,15 +2,15 @@
2
2
  import { ReportUtils as ReportUtils2 } from "@flakiness/report";
3
3
  import { Multimap } from "@flakiness/shared/common/multimap.js";
4
4
  import chalk2 from "chalk";
5
- import fs7 from "fs";
6
- import path6 from "path";
5
+ import fs6 from "fs";
6
+ import path5 from "path";
7
7
 
8
8
  // src/cli/cmd-show-report.ts
9
9
  import chalk from "chalk";
10
10
  import open from "open";
11
- import path5 from "path";
11
+ import path4 from "path";
12
12
 
13
- // src/flakinessConfig.ts
13
+ // src/flakinessProjectConfig.ts
14
14
  import fs2 from "fs";
15
15
  import path2 from "path";
16
16
 
@@ -317,7 +317,7 @@ function createEnvironments(projects) {
317
317
  return result;
318
318
  }
319
319
 
320
- // src/flakinessConfig.ts
320
+ // src/flakinessProjectConfig.ts
321
321
  function createConfigPath(dir) {
322
322
  return path2.join(dir, ".flakiness", "config.json");
323
323
  }
@@ -340,7 +340,7 @@ function computeConfigPath() {
340
340
  return createConfigPath(process.cwd());
341
341
  }
342
342
  }
343
- var FlakinessConfig = class _FlakinessConfig {
343
+ var FlakinessProjectConfig = class _FlakinessProjectConfig {
344
344
  constructor(_configPath, _config) {
345
345
  this._configPath = _configPath;
346
346
  this._config = _config;
@@ -349,20 +349,10 @@ var FlakinessConfig = class _FlakinessConfig {
349
349
  const configPath = ensureConfigPath();
350
350
  const data = await fs2.promises.readFile(configPath, "utf-8").catch((e) => void 0);
351
351
  const json = data ? JSON.parse(data) : {};
352
- return new _FlakinessConfig(configPath, json);
353
- }
354
- static async projectOrDie(session) {
355
- const config = await _FlakinessConfig.load();
356
- const projectPublicId = config.projectPublicId();
357
- if (!projectPublicId)
358
- throw new Error(`Please link to flakiness project with 'npx flakiness link'`);
359
- const project = await session.api.project.getProject.GET({ projectPublicId }).catch((e) => void 0);
360
- if (!project)
361
- throw new Error(`Failed to fetch linked project; please re-link with 'npx flakiness link'`);
362
- return project;
352
+ return new _FlakinessProjectConfig(configPath, json);
363
353
  }
364
354
  static createEmpty() {
365
- return new _FlakinessConfig(ensureConfigPath(), {});
355
+ return new _FlakinessProjectConfig(ensureConfigPath(), {});
366
356
  }
367
357
  path() {
368
358
  return this._configPath;
@@ -370,6 +360,9 @@ var FlakinessConfig = class _FlakinessConfig {
370
360
  projectPublicId() {
371
361
  return this._config.projectPublicId;
372
362
  }
363
+ reportViewerEndpoint() {
364
+ return this._config.customReportViewerEndpoint ?? "https://report.flakiness.io";
365
+ }
373
366
  setProjectPublicId(projectId) {
374
367
  this._config.projectPublicId = projectId;
375
368
  }
@@ -379,72 +372,8 @@ var FlakinessConfig = class _FlakinessConfig {
379
372
  }
380
373
  };
381
374
 
382
- // src/flakinessSession.ts
383
- import fs3 from "fs/promises";
384
- import os2 from "os";
385
- import path3 from "path";
386
-
387
- // src/serverapi.ts
388
- import { TypedHTTP } from "@flakiness/shared/common/typedHttp.js";
389
- function createServerAPI(endpoint, options) {
390
- endpoint += "/api/";
391
- const fetcher = options?.auth ? (url, init) => fetch(url, {
392
- ...init,
393
- headers: {
394
- ...init.headers,
395
- "Authorization": `Bearer ${options.auth}`
396
- }
397
- }) : fetch;
398
- if (options?.retries)
399
- return TypedHTTP.createClient(endpoint, (url, init) => retryWithBackoff(() => fetcher(url, init), options.retries));
400
- return TypedHTTP.createClient(endpoint, fetcher);
401
- }
402
-
403
- // src/flakinessSession.ts
404
- var CONFIG_DIR = (() => {
405
- const configDir = process.platform === "darwin" ? path3.join(os2.homedir(), "Library", "Application Support", "flakiness") : process.platform === "win32" ? path3.join(os2.homedir(), "AppData", "Roaming", "flakiness") : path3.join(os2.homedir(), ".config", "flakiness");
406
- return configDir;
407
- })();
408
- var CONFIG_PATH = path3.join(CONFIG_DIR, "config.json");
409
- var FlakinessSession = class _FlakinessSession {
410
- constructor(_config) {
411
- this._config = _config;
412
- this.api = createServerAPI(this._config.endpoint, { auth: this._config.token });
413
- }
414
- static async loadOrDie() {
415
- const session = await _FlakinessSession.load();
416
- if (!session)
417
- throw new Error(`Please login first with 'npx flakiness login'`);
418
- return session;
419
- }
420
- static async load() {
421
- const data = await fs3.readFile(CONFIG_PATH, "utf-8").catch((e) => void 0);
422
- if (!data)
423
- return void 0;
424
- const json = JSON.parse(data);
425
- return new _FlakinessSession(json);
426
- }
427
- static async remove() {
428
- await fs3.unlink(CONFIG_PATH).catch((e) => void 0);
429
- }
430
- api;
431
- endpoint() {
432
- return this._config.endpoint;
433
- }
434
- path() {
435
- return CONFIG_PATH;
436
- }
437
- sessionToken() {
438
- return this._config.token;
439
- }
440
- async save() {
441
- await fs3.mkdir(CONFIG_DIR, { recursive: true });
442
- await fs3.writeFile(CONFIG_PATH, JSON.stringify(this._config, null, 2));
443
- }
444
- };
445
-
446
375
  // src/localReportServer.ts
447
- import { TypedHTTP as TypedHTTP3 } from "@flakiness/shared/common/typedHttp.js";
376
+ import { TypedHTTP as TypedHTTP2 } from "@flakiness/shared/common/typedHttp.js";
448
377
  import { randomUUIDBase62 } from "@flakiness/shared/node/nodeutils.js";
449
378
  import { createTypedHttpExpressMiddleware } from "@flakiness/shared/node/typedHttpExpress.js";
450
379
  import bodyParser from "body-parser";
@@ -455,9 +384,9 @@ import "express-async-errors";
455
384
  import http2 from "http";
456
385
 
457
386
  // src/localReportApi.ts
458
- import { TypedHTTP as TypedHTTP2 } from "@flakiness/shared/common/typedHttp.js";
459
- import fs4 from "fs";
460
- import path4 from "path";
387
+ import { TypedHTTP } from "@flakiness/shared/common/typedHttp.js";
388
+ import fs3 from "fs";
389
+ import path3 from "path";
461
390
  import { z } from "zod/v4";
462
391
 
463
392
  // src/localGit.ts
@@ -512,7 +441,7 @@ var ReportInfo = class {
512
441
  attachmentIdToPath = /* @__PURE__ */ new Map();
513
442
  commits = [];
514
443
  async refresh() {
515
- const report = await fs4.promises.readFile(this._options.reportPath, "utf-8").then((x) => JSON.parse(x)).catch((e) => void 0);
444
+ const report = await fs3.promises.readFile(this._options.reportPath, "utf-8").then((x) => JSON.parse(x)).catch((e) => void 0);
516
445
  if (!report) {
517
446
  this.report = void 0;
518
447
  this.commits = [];
@@ -522,7 +451,7 @@ var ReportInfo = class {
522
451
  if (JSON.stringify(report) === JSON.stringify(this.report))
523
452
  return;
524
453
  this.report = report;
525
- this.commits = await listLocalCommits(path4.dirname(this._options.reportPath), report.commitId, 100);
454
+ this.commits = await listLocalCommits(path3.dirname(this._options.reportPath), report.commitId, 100);
526
455
  const attachmentsDir = this._options.attachmentsFolder;
527
456
  const { attachmentIdToPath, missingAttachments } = await resolveAttachmentPaths(report, attachmentsDir);
528
457
  if (missingAttachments.length) {
@@ -535,7 +464,7 @@ var ReportInfo = class {
535
464
  this.attachmentIdToPath = attachmentIdToPath;
536
465
  }
537
466
  };
538
- var t = TypedHTTP2.Router.create();
467
+ var t = TypedHTTP.Router.create();
539
468
  var localReportRouter = {
540
469
  ping: t.get({
541
470
  handler: async () => {
@@ -555,9 +484,9 @@ var localReportRouter = {
555
484
  handler: async ({ ctx, input }) => {
556
485
  const idx = ctx.reportInfo.attachmentIdToPath.get(input.attachmentId);
557
486
  if (!idx)
558
- throw TypedHTTP2.HttpError.withCode("NOT_FOUND");
559
- const buffer = await fs4.promises.readFile(idx.path);
560
- return TypedHTTP2.ok(buffer, idx.contentType);
487
+ throw TypedHTTP.HttpError.withCode("NOT_FOUND");
488
+ const buffer = await fs3.promises.readFile(idx.path);
489
+ return TypedHTTP.ok(buffer, idx.contentType);
561
490
  }
562
491
  }),
563
492
  json: t.get({
@@ -585,7 +514,7 @@ var LocalReportServer = class _LocalReportServer {
585
514
  app.use(bodyParser.json({ limit: 256 * 1024 }));
586
515
  app.use((req, res, next) => {
587
516
  if (!req.path.startsWith("/" + authToken))
588
- throw TypedHTTP3.HttpError.withCode("UNAUTHORIZED");
517
+ throw TypedHTTP2.HttpError.withCode("UNAUTHORIZED");
589
518
  res.setHeader("Access-Control-Allow-Headers", "*");
590
519
  res.setHeader("Access-Control-Allow-Origin", options.endpoint);
591
520
  res.setHeader("Access-Control-Allow-Methods", "*");
@@ -606,7 +535,7 @@ var LocalReportServer = class _LocalReportServer {
606
535
  createRootContext: async ({ req, res, input }) => ({ reportInfo })
607
536
  }));
608
537
  app.use((err2, req, res, next) => {
609
- if (err2 instanceof TypedHTTP3.HttpError)
538
+ if (err2 instanceof TypedHTTP2.HttpError)
610
539
  return res.status(err2.status).send({ error: err2.message });
611
540
  logHTTPServer(err2);
612
541
  res.status(500).send({ error: "Internal Server Error" });
@@ -637,35 +566,37 @@ var LocalReportServer = class _LocalReportServer {
637
566
 
638
567
  // src/cli/cmd-show-report.ts
639
568
  async function cmdShowReport(reportFolder) {
640
- const reportPath = path5.join(reportFolder, "report.json");
641
- const session = await FlakinessSession.load();
642
- const config = await FlakinessConfig.load();
569
+ const reportPath = path4.join(reportFolder, "report.json");
570
+ const config = await FlakinessProjectConfig.load();
643
571
  const projectPublicId = config.projectPublicId();
644
- const project = projectPublicId && session ? await session.api.project.getProject.GET({ projectPublicId }).catch((e) => void 0) : void 0;
645
- const endpoint = session?.endpoint() ?? "https://flakiness.io";
572
+ const reportViewerEndpoint = config.reportViewerEndpoint();
646
573
  const server = await LocalReportServer.create({
647
- endpoint,
574
+ endpoint: reportViewerEndpoint,
648
575
  port: 9373,
649
576
  reportPath,
650
577
  attachmentsFolder: reportFolder
651
578
  });
652
- const reportEndpoint = project ? `${endpoint}/localreport/${project.org.orgSlug}/${project.projectSlug}?port=${server.port()}&token=${server.authToken()}` : `${endpoint}/localreport?port=${server.port()}&token=${server.authToken()}`;
579
+ const url = new URL(reportViewerEndpoint);
580
+ url.searchParams.set("port", String(server.port()));
581
+ url.searchParams.set("token", server.authToken());
582
+ if (projectPublicId)
583
+ url.searchParams.set("ppid", projectPublicId);
653
584
  console.log(chalk.cyan(`
654
- Serving Flakiness report at ${reportEndpoint}
585
+ Serving Flakiness report at ${url.toString()}
655
586
  Press Ctrl+C to quit.`));
656
- await open(reportEndpoint);
587
+ await open(url.toString());
657
588
  await new Promise(() => {
658
589
  });
659
590
  }
660
591
 
661
592
  // src/createTestStepSnippets.ts
662
593
  import { codeFrameColumns } from "@babel/code-frame";
663
- import fs5 from "fs";
594
+ import fs4 from "fs";
664
595
  function createTestStepSnippets(filepathToSteps) {
665
596
  for (const [filepath, steps] of filepathToSteps) {
666
597
  let source;
667
598
  try {
668
- source = fs5.readFileSync(filepath, "utf-8");
599
+ source = fs4.readFileSync(filepath, "utf-8");
669
600
  } catch (e) {
670
601
  continue;
671
602
  }
@@ -690,8 +621,26 @@ function createTestStepSnippets(filepathToSteps) {
690
621
  // src/reportUploader.ts
691
622
  import { compressTextAsync, compressTextSync } from "@flakiness/shared/node/compression.js";
692
623
  import assert2 from "assert";
693
- import fs6 from "fs";
694
- import { URL } from "url";
624
+ import fs5 from "fs";
625
+ import { URL as URL2 } from "url";
626
+
627
+ // src/serverapi.ts
628
+ import { TypedHTTP as TypedHTTP3 } from "@flakiness/shared/common/typedHttp.js";
629
+ function createServerAPI(endpoint, options) {
630
+ endpoint += "/api/";
631
+ const fetcher = options?.auth ? (url, init) => fetch(url, {
632
+ ...init,
633
+ headers: {
634
+ ...init.headers,
635
+ "Authorization": `Bearer ${options.auth}`
636
+ }
637
+ }) : fetch;
638
+ if (options?.retries)
639
+ return TypedHTTP3.createClient(endpoint, (url, init) => retryWithBackoff(() => fetcher(url, init), options.retries));
640
+ return TypedHTTP3.createClient(endpoint, fetcher);
641
+ }
642
+
643
+ // src/reportUploader.ts
695
644
  var ReportUploader = class _ReportUploader {
696
645
  static optionsFromEnv(overrides) {
697
646
  const flakinessAccessToken = overrides?.flakinessAccessToken ?? process.env["FLAKINESS_ACCESS_TOKEN"];
@@ -757,7 +706,7 @@ var ReportUpload = class {
757
706
  const response2 = await this._api.run.completeUpload.POST({
758
707
  upload_token: response.result.upload_token
759
708
  }).then((result) => ({ result, error: void 0 })).catch((e) => ({ error: e, result: void 0 }));
760
- const url = response2?.result?.report_url ? new URL(response2?.result.report_url, this._options.flakinessEndpoint).toString() : void 0;
709
+ const url = response2?.result?.report_url ? new URL2(response2?.result.report_url, this._options.flakinessEndpoint).toString() : void 0;
761
710
  return { success: true, reportUrl: url };
762
711
  }
763
712
  async _uploadReport(data, uploadUrl, syncCompression) {
@@ -788,16 +737,16 @@ var ReportUpload = class {
788
737
  url: uploadUrl,
789
738
  headers: {
790
739
  "Content-Type": attachment.contentType,
791
- "Content-Length": (await fs6.promises.stat(attachmentPath)).size + ""
740
+ "Content-Length": (await fs5.promises.stat(attachmentPath)).size + ""
792
741
  },
793
742
  method: "put"
794
743
  });
795
- fs6.createReadStream(attachmentPath).pipe(request);
744
+ fs5.createReadStream(attachmentPath).pipe(request);
796
745
  await responseDataPromise;
797
746
  }, HTTP_BACKOFF);
798
747
  return;
799
748
  }
800
- let buffer = attachment.body ? attachment.body : attachment.path ? await fs6.promises.readFile(attachment.path) : void 0;
749
+ let buffer = attachment.body ? attachment.body : attachment.path ? await fs5.promises.readFile(attachment.path) : void 0;
801
750
  assert2(buffer);
802
751
  const encoding = compressable ? "br" : void 0;
803
752
  if (compressable)
@@ -822,7 +771,7 @@ var ReportUpload = class {
822
771
 
823
772
  // src/systemUtilizationSampler.ts
824
773
  import { spawnSync as spawnSync2 } from "child_process";
825
- import os3 from "os";
774
+ import os2 from "os";
826
775
  function getAvailableMemMacOS() {
827
776
  const lines = spawnSync2("vm_stat", { encoding: "utf8" }).stdout.trim().split("\n");
828
777
  const pageSize = parseInt(lines[0].match(/page size of (\d+) bytes/)[1], 10);
@@ -843,7 +792,7 @@ function getAvailableMemMacOS() {
843
792
  function getSystemUtilization() {
844
793
  let idleTicks = 0;
845
794
  let totalTicks = 0;
846
- for (const cpu of os3.cpus()) {
795
+ for (const cpu of os2.cpus()) {
847
796
  totalTicks += cpu.times.user + cpu.times.nice + cpu.times.sys + cpu.times.irq + cpu.times.idle;
848
797
  idleTicks += cpu.times.idle;
849
798
  }
@@ -851,14 +800,14 @@ function getSystemUtilization() {
851
800
  idleTicks,
852
801
  totalTicks,
853
802
  timestamp: Date.now(),
854
- freeBytes: os3.platform() === "darwin" ? getAvailableMemMacOS() : os3.freemem()
803
+ freeBytes: os2.platform() === "darwin" ? getAvailableMemMacOS() : os2.freemem()
855
804
  };
856
805
  }
857
806
  function toFKUtilization(sample, previous) {
858
807
  const idleTicks = sample.idleTicks - previous.idleTicks;
859
808
  const totalTicks = sample.totalTicks - previous.totalTicks;
860
809
  const cpuUtilization = Math.floor((1 - idleTicks / totalTicks) * 1e4) / 100;
861
- const memoryUtilization = Math.floor((1 - sample.freeBytes / os3.totalmem()) * 1e4) / 100;
810
+ const memoryUtilization = Math.floor((1 - sample.freeBytes / os2.totalmem()) * 1e4) / 100;
862
811
  return {
863
812
  cpuUtilization,
864
813
  memoryUtilization,
@@ -873,7 +822,7 @@ var SystemUtilizationSampler = class {
873
822
  this.result = {
874
823
  samples: [],
875
824
  startTimestamp: this._lastSample.timestamp,
876
- totalMemoryBytes: os3.totalmem()
825
+ totalMemoryBytes: os2.totalmem()
877
826
  };
878
827
  this._timer = setTimeout(this._addSample.bind(this), 50);
879
828
  }
@@ -894,7 +843,7 @@ var err = (txt) => console.error(chalk2.red(`[flakiness.io] ${txt}`));
894
843
  var FlakinessReporter = class {
895
844
  constructor(_options = {}) {
896
845
  this._options = _options;
897
- this._outputFolder = path6.join(process.cwd(), this._options.outputFolder ?? process.env.FLAKINESS_OUTPUT_DIR ?? "flakiness-report");
846
+ this._outputFolder = path5.join(process.cwd(), this._options.outputFolder ?? process.env.FLAKINESS_OUTPUT_DIR ?? "flakiness-report");
898
847
  }
899
848
  _config;
900
849
  _rootSuite;
@@ -997,7 +946,7 @@ var FlakinessReporter = class {
997
946
  location: pwStep.location ? this._createLocation(context, pwStep.location) : void 0
998
947
  };
999
948
  if (pwStep.location) {
1000
- const resolvedPath = path6.resolve(pwStep.location.file);
949
+ const resolvedPath = path5.resolve(pwStep.location.file);
1001
950
  this._filepathToSteps.set(resolvedPath, step);
1002
951
  }
1003
952
  if (pwStep.error)
@@ -1046,10 +995,10 @@ var FlakinessReporter = class {
1046
995
  const environmentsMap = createEnvironments(this._config.projects);
1047
996
  if (this._options.collectBrowserVersions) {
1048
997
  try {
1049
- let playwrightPath = fs7.realpathSync(process.argv[1]);
1050
- while (path6.basename(playwrightPath) !== "test")
1051
- playwrightPath = path6.dirname(playwrightPath);
1052
- const module = await import(path6.join(playwrightPath, "index.js"));
998
+ let playwrightPath = fs6.realpathSync(process.argv[1]);
999
+ while (path5.basename(playwrightPath) !== "test")
1000
+ playwrightPath = path5.dirname(playwrightPath);
1001
+ const module = await import(path5.join(playwrightPath, "index.js"));
1053
1002
  for (const [project, env] of environmentsMap) {
1054
1003
  const { browserName = "chromium", channel, headless } = project.use;
1055
1004
  let browserType;
@@ -1116,8 +1065,8 @@ var FlakinessReporter = class {
1116
1065
  if (shouldOpen) {
1117
1066
  await cmdShowReport(this._outputFolder);
1118
1067
  } else {
1119
- const defaultOutputFolder = path6.join(process.cwd(), "flakiness-report");
1120
- const folder = defaultOutputFolder === this._outputFolder ? "" : path6.relative(process.cwd(), this._outputFolder);
1068
+ const defaultOutputFolder = path5.join(process.cwd(), "flakiness-report");
1069
+ const folder = defaultOutputFolder === this._outputFolder ? "" : path5.relative(process.cwd(), this._outputFolder);
1121
1070
  console.log(`
1122
1071
  To open last Flakiness report, install Flakiness CLI tool and run:
1123
1072
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flakiness/sdk",
3
- "version": "0.145.0",
3
+ "version": "0.145.1",
4
4
  "private": false,
5
5
  "bin": {
6
6
  "flakiness": "./lib/cli/cli.js"
@@ -50,7 +50,7 @@
50
50
  "author": "Degu Labs, Inc",
51
51
  "license": "Fair Source 100",
52
52
  "devDependencies": {
53
- "@flakiness/server": "0.145.0",
53
+ "@flakiness/server": "0.145.1",
54
54
  "@playwright/test": "^1.57.0",
55
55
  "@types/babel__code-frame": "^7.0.6",
56
56
  "@types/compression": "^1.8.1",
@@ -58,8 +58,8 @@
58
58
  },
59
59
  "dependencies": {
60
60
  "@babel/code-frame": "^7.26.2",
61
- "@flakiness/report": "0.145.0",
62
- "@flakiness/shared": "0.145.0",
61
+ "@flakiness/report": "0.145.1",
62
+ "@flakiness/shared": "0.145.1",
63
63
  "@rgrove/parse-xml": "^4.2.0",
64
64
  "body-parser": "^1.20.3",
65
65
  "chalk": "^5.6.2",