@testsmith/api-spector 0.8.8 → 0.8.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.
@@ -2400,7 +2400,11 @@ async function publishVerification(cfg, input) {
2400
2400
  contractId: input.contractId,
2401
2401
  providerVersion: input.providerVersion,
2402
2402
  success: input.success,
2403
- ...input.buildUrl ? { buildUrl: input.buildUrl } : {}
2403
+ ...input.buildUrl ? { buildUrl: input.buildUrl } : {},
2404
+ // Full per-interaction detail (a ContractReport) so the cloud can show WHY
2405
+ // a verification failed, not just pass/fail. Optional — omitted when no
2406
+ // report is supplied.
2407
+ ...input.results !== void 0 ? { results: input.results } : {}
2404
2408
  });
2405
2409
  if (!r.ok) fail(r, "Publish verification failed");
2406
2410
  }
@@ -2,7 +2,7 @@
2
2
  "use strict";
3
3
  const promises = require("node:fs/promises");
4
4
  const path = require("node:path");
5
- const brokerClient = require("./chunks/broker-client-Bmt4seb8.js");
5
+ const brokerClient = require("./chunks/broker-client-170x6Jx9.js");
6
6
  const escape = require("./chunks/escape-DDVAlOvZ.js");
7
7
  const crypto = require("node:crypto");
8
8
  const undici = require("undici");
@@ -803,12 +803,21 @@ async function cmdPublishVerification(args) {
803
803
  const success = successArg === "true" || successArg === "1";
804
804
  const buildUrl = str(args["build-url"]);
805
805
  const consumerVersion = str(args["consumer-version"]);
806
+ let results;
807
+ const reportPath = str(args["report"]);
808
+ if (reportPath) {
809
+ try {
810
+ results = JSON.parse(await promises.readFile(path.resolve(reportPath), "utf8"));
811
+ } catch (e) {
812
+ die(`Could not read --report ${reportPath}: ${e instanceof Error ? e.message : String(e)}`);
813
+ }
814
+ }
806
815
  const cfg = brokerClient.brokerConfigFromEnv();
807
816
  const contracts = await brokerClient.fetchContracts(cfg, { consumer, provider });
808
817
  const match = consumerVersion ? contracts.find((c) => c.consumerVersion === consumerVersion) : contracts[contracts.length - 1];
809
818
  if (!match) die(`No published contract for ${consumer} -> ${provider}${consumerVersion ? "@" + consumerVersion : ""}.`);
810
- await brokerClient.publishVerification(cfg, { contractId: match.id, providerVersion, success, buildUrl });
811
- console.log(` Published verification: ${provider}@${providerVersion.slice(0, 7)} -> ${consumer}@${match.consumerVersion} = ${success ? "passed" : "FAILED"}`);
819
+ await brokerClient.publishVerification(cfg, { contractId: match.id, providerVersion, success, buildUrl, results });
820
+ console.log(` Published verification: ${provider}@${providerVersion.slice(0, 7)} -> ${consumer}@${match.consumerVersion} = ${success ? "passed" : "FAILED"}${results ? " (+ report)" : ""}`);
812
821
  }
813
822
  async function main() {
814
823
  const [, , sub, ...rest] = process.argv;
package/out/main/flow.js CHANGED
@@ -268,7 +268,7 @@ async function main() {
268
268
  const envName = args.environment ?? args.env;
269
269
  const env = environments.selectEnvironment(workspace, environments$1, envName);
270
270
  const verbose = Boolean(args.verbose);
271
- const version = `v${"0.8.8"}`;
271
+ const version = `v${"0.8.9"}`;
272
272
  console.log("");
273
273
  console.log(cliCommon.color(" API Flow Runner" + (version ? ` ${version}` : ""), cliCommon.C.bold, cliCommon.C.white));
274
274
  console.log(cliCommon.color(` Flow: ${flow.name}`, cliCommon.C.gray));
package/out/main/index.js CHANGED
@@ -31,7 +31,7 @@ require("node:os");
31
31
  require("@grpc/grpc-js");
32
32
  require("@grpc/proto-loader");
33
33
  require("./chunks/escape-DDVAlOvZ.js");
34
- require("./chunks/broker-client-Bmt4seb8.js");
34
+ require("./chunks/broker-client-170x6Jx9.js");
35
35
  require("simple-git");
36
36
  require("./chunks/recorder-BkO8G_mB.js");
37
37
  require("fs/promises");
@@ -50,7 +50,7 @@ function isNewer(a, b) {
50
50
  return a2 > b2;
51
51
  }
52
52
  async function checkForUpdate() {
53
- const current = "0.8.8";
53
+ const current = "0.8.9";
54
54
  try {
55
55
  const res = await fetch(REGISTRY_URL, { signal: AbortSignal.timeout(4e3) });
56
56
  if (!res.ok) return null;
package/out/main/perf.js CHANGED
@@ -191,7 +191,7 @@ async function main() {
191
191
  targetLabel = `flow: ${flow.name}`;
192
192
  }
193
193
  const load = perfRun.deriveLoad(plan);
194
- const version = `v${"0.8.8"}`;
194
+ const version = `v${"0.8.9"}`;
195
195
  console.log("");
196
196
  console.log(cliCommon.color(" API Performance" + (version ? ` ${version}` : ""), cliCommon.C.bold, cliCommon.C.white));
197
197
  console.log(cliCommon.color(` Plan: ${plan.name}`, cliCommon.C.gray));
@@ -49,7 +49,7 @@ const os = require("node:os");
49
49
  const grpc = require("@grpc/grpc-js");
50
50
  const protoLoader = require("@grpc/proto-loader");
51
51
  const escape = require("./chunks/escape-DDVAlOvZ.js");
52
- const brokerClient = require("./chunks/broker-client-Bmt4seb8.js");
52
+ const brokerClient = require("./chunks/broker-client-170x6Jx9.js");
53
53
  const simpleGit = require("simple-git");
54
54
  const recorder = require("./chunks/recorder-BkO8G_mB.js");
55
55
  require("fs/promises");
@@ -7415,6 +7415,31 @@ function registerContractHandlers(ipc) {
7415
7415
  return { file };
7416
7416
  });
7417
7417
  }
7418
+ const BRANCH_REF_FORMAT = "%(refname)|%(refname:short)|%(HEAD)|%(upstream:short)|%(upstream:track)";
7419
+ function parseBranchRefs(raw, current) {
7420
+ const branches = [];
7421
+ for (const line of raw.split("\n")) {
7422
+ if (!line.trim()) continue;
7423
+ const [fullRef, shortName, head, upstream, track] = line.split("|");
7424
+ if (!shortName || shortName.endsWith("/HEAD")) continue;
7425
+ const isRemote = fullRef.startsWith("refs/remotes/");
7426
+ let ahead;
7427
+ let behind;
7428
+ const aheadM = /ahead (\d+)/.exec(track ?? "");
7429
+ const behindM = /behind (\d+)/.exec(track ?? "");
7430
+ if (aheadM) ahead = Number(aheadM[1]);
7431
+ if (behindM) behind = Number(behindM[1]);
7432
+ branches.push({
7433
+ name: shortName,
7434
+ current: !isRemote && (head === "*" || shortName === current),
7435
+ remote: isRemote,
7436
+ upstream: upstream || void 0,
7437
+ ahead,
7438
+ behind
7439
+ });
7440
+ }
7441
+ return branches;
7442
+ }
7418
7443
  function git() {
7419
7444
  const dir = getWorkspaceDir();
7420
7445
  if (!dir) throw new Error("No workspace open");
@@ -7507,34 +7532,12 @@ function registerGitHandlers(ipc) {
7507
7532
  handle.handleIpc(ipc, handle.IPC.git.branches, async () => {
7508
7533
  const raw = await git().raw([
7509
7534
  "for-each-ref",
7510
- "--format=%(refname:short)|%(HEAD)|%(upstream:short)|%(upstream:track)",
7535
+ `--format=${BRANCH_REF_FORMAT}`,
7511
7536
  "refs/heads",
7512
7537
  "refs/remotes"
7513
7538
  ]);
7514
7539
  const current = (await git().branch()).current;
7515
- const branches = [];
7516
- for (const line of raw.split("\n")) {
7517
- if (!line.trim()) continue;
7518
- const [shortName, head, upstream, track] = line.split("|");
7519
- if (!shortName || shortName.endsWith("/HEAD")) continue;
7520
- const isRemote = shortName.startsWith("origin/") || shortName.includes("/");
7521
- const looksLocal = !isRemote;
7522
- let ahead;
7523
- let behind;
7524
- const aheadM = /ahead (\d+)/.exec(track);
7525
- const behindM = /behind (\d+)/.exec(track);
7526
- if (aheadM) ahead = Number(aheadM[1]);
7527
- if (behindM) behind = Number(behindM[1]);
7528
- branches.push({
7529
- name: shortName,
7530
- current: looksLocal && (head === "*" || shortName === current),
7531
- remote: isRemote,
7532
- upstream: upstream || void 0,
7533
- ahead,
7534
- behind
7535
- });
7536
- }
7537
- return branches;
7540
+ return parseBranchRefs(raw, current);
7538
7541
  });
7539
7542
  handle.handleIpc(ipc, handle.IPC.git.checkout, async (_e, branch, create) => {
7540
7543
  if (create) {
@@ -551,7 +551,7 @@ async function main() {
551
551
  } else if (!envName && workspace.settings?.defaultEnvironment && !env) {
552
552
  console.warn(cliCommon.color(`Warning: default environment "${workspace.settings.defaultEnvironment}" not found. Running without environment.`, cliCommon.C.yellow));
553
553
  }
554
- const version = `v${"0.8.8"}`;
554
+ const version = `v${"0.8.9"}`;
555
555
  console.log("");
556
556
  console.log(cliCommon.color(" API Test Runner" + (version ? ` ${version}` : ""), cliCommon.C.bold, cliCommon.C.white));
557
557
  console.log(cliCommon.color(` Workspace: ${wsPath}`, cliCommon.C.gray));
@@ -1,5 +1,5 @@
1
1
  import { l as linter, E as EditorView, L as LanguageSupport, i as LRLanguage, s as styleTags, m as indentNodeProp, n as delimitedIndent, p as foldNodeProp, q as foldInside, S as StateField, u as LRParser, v as StateEffect, w as tags, a as reactExports, j as jsxRuntimeExports, e as ReactCodeMirror, o as oneDark, d as json } from "./codemirror-BKmwMUlV.js";
2
- import { u as useT, a as useStore, b as useActiveEnvironment, i as isSubscriptionQuery } from "./index-fV0So_bF.js";
2
+ import { u as useT, a as useStore, b as useActiveEnvironment, i as isSubscriptionQuery } from "./index-D_-cF6J0.js";
3
3
  import "./ajv-CJPwFjiP.js";
4
4
  function devAssert(condition, message) {
5
5
  const booleanCondition = Boolean(condition);
@@ -1,5 +1,5 @@
1
1
  import { a as reactExports, j as jsxRuntimeExports, e as ReactCodeMirror, o as oneDark, x as xml } from "./codemirror-BKmwMUlV.js";
2
- import { u as useT, c as btnPrimaryCls, d as commentKeymap } from "./index-fV0So_bF.js";
2
+ import { u as useT, c as btnPrimaryCls, d as commentKeymap } from "./index-D_-cF6J0.js";
3
3
  import "./ajv-CJPwFjiP.js";
4
4
  const SOAP_11_CONTENT_TYPE = "text/xml; charset=utf-8";
5
5
  const SOAP_12_CONTENT_TYPE = "application/soap+xml; charset=utf-8";
@@ -1,4 +1,4 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./GraphQLEditor-TklsnkDw.js","./codemirror-BKmwMUlV.js","./ajv-CJPwFjiP.js","./SoapEditor-CllZqWyv.js"])))=>i.map(i=>d[i]);
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./GraphQLEditor-CR3JSOwU.js","./codemirror-BKmwMUlV.js","./ajv-CJPwFjiP.js","./SoapEditor-eAhSrhoc.js"])))=>i.map(i=>d[i]);
2
2
  import { r as requireReact, g as getDefaultExportFromCjs, R as React, a as reactExports, b as autocompletion, h as hoverTooltip, j as jsxRuntimeExports, k as keymap, t as toggleComment, D as Decoration, E as EditorView, V as ViewPlugin, c as RangeSetBuilder, x as xml, d as json, e as ReactCodeMirror, o as oneDark, f as javascript } from "./codemirror-BKmwMUlV.js";
3
3
  import { r as requireAjv } from "./ajv-CJPwFjiP.js";
4
4
  var client = { exports: {} };
@@ -12087,7 +12087,7 @@ function reIdFolderTree(root2, mapRequestId) {
12087
12087
  root2.folders.forEach((sub) => reIdFolderTree(sub, mapRequestId));
12088
12088
  }
12089
12089
  function cloneAndReId(folder2, mapRequestId) {
12090
- const cloned = structuredClone(folder2);
12090
+ const cloned = JSON.parse(JSON.stringify(folder2));
12091
12091
  reIdFolderTree(cloned, mapRequestId);
12092
12092
  return cloned;
12093
12093
  }
@@ -28935,8 +28935,8 @@ function jsonWithComments() {
28935
28935
  function xmlWithComments() {
28936
28936
  return [xml(), commentKeymap];
28937
28937
  }
28938
- const GraphQLEditor = reactExports.lazy(() => __vitePreload(() => import("./GraphQLEditor-TklsnkDw.js"), true ? __vite__mapDeps([0,1,2]) : void 0, import.meta.url).then((m) => ({ default: m.GraphQLEditor })));
28939
- const SoapEditor = reactExports.lazy(() => __vitePreload(() => import("./SoapEditor-CllZqWyv.js"), true ? __vite__mapDeps([3,1,2]) : void 0, import.meta.url).then((m) => ({ default: m.SoapEditor })));
28938
+ const GraphQLEditor = reactExports.lazy(() => __vitePreload(() => import("./GraphQLEditor-CR3JSOwU.js"), true ? __vite__mapDeps([0,1,2]) : void 0, import.meta.url).then((m) => ({ default: m.GraphQLEditor })));
28939
+ const SoapEditor = reactExports.lazy(() => __vitePreload(() => import("./SoapEditor-eAhSrhoc.js"), true ? __vite__mapDeps([3,1,2]) : void 0, import.meta.url).then((m) => ({ default: m.SoapEditor })));
28940
28940
  function BodyTab({ request: request2, onChange }) {
28941
28941
  const t = useT();
28942
28942
  const editorFallback = /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-4 text-xs text-surface-500", children: t("Loading editor…") });
@@ -38617,6 +38617,12 @@ function renderInline(text, keyBase) {
38617
38617
  return /* @__PURE__ */ jsxRuntimeExports.jsx(React.Fragment, { children: part }, key);
38618
38618
  });
38619
38619
  }
38620
+ function splitRow(line) {
38621
+ let s = line.trim();
38622
+ if (s.startsWith("|")) s = s.slice(1);
38623
+ if (s.endsWith("|")) s = s.slice(0, -1);
38624
+ return s.split("|").map((c) => c.trim());
38625
+ }
38620
38626
  function renderMarkdown(md) {
38621
38627
  const lines = md.replaceAll("\r\n", "\n").split("\n");
38622
38628
  const blocks = [];
@@ -38675,6 +38681,22 @@ function renderMarkdown(md) {
38675
38681
  );
38676
38682
  continue;
38677
38683
  }
38684
+ if (line.includes("|") && i + 1 < lines.length && /^\s*\|?\s*:?-+:?\s*(\|\s*:?-+:?\s*)+\|?\s*$/.test(lines[i + 1])) {
38685
+ const header2 = splitRow(line);
38686
+ i += 2;
38687
+ const rows = [];
38688
+ while (i < lines.length && lines[i].includes("|") && lines[i].trim() !== "") {
38689
+ rows.push(splitRow(lines[i]));
38690
+ i++;
38691
+ }
38692
+ blocks.push(
38693
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "overflow-x-auto my-1", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("table", { className: "border-collapse text-xs", children: [
38694
+ /* @__PURE__ */ jsxRuntimeExports.jsx("thead", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("tr", { children: header2.map((c, ci) => /* @__PURE__ */ jsxRuntimeExports.jsx("th", { className: "border border-surface-700 bg-surface-800 px-2 py-1 text-left font-semibold text-surface-200 whitespace-nowrap", children: renderInline(c, k()) }, ci)) }) }),
38695
+ /* @__PURE__ */ jsxRuntimeExports.jsx("tbody", { children: rows.map((r, ri) => /* @__PURE__ */ jsxRuntimeExports.jsx("tr", { children: header2.map((_, ci) => /* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "border border-surface-700 px-2 py-1 align-top text-surface-300", children: renderInline(r[ci] ?? "", k()) }, ci)) }, ri)) })
38696
+ ] }) }, k())
38697
+ );
38698
+ continue;
38699
+ }
38678
38700
  if (/^\s*[-*+]\s+/.test(line)) {
38679
38701
  const items = [];
38680
38702
  while (i < lines.length && /^\s*[-*+]\s+/.test(lines[i])) {
@@ -45646,7 +45668,7 @@ function WelcomeScreen() {
45646
45668
  )
45647
45669
  ] }),
45648
45670
  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-surface-400 text-sm max-w-sm", children: t("Local-first API testing with Robot Framework & Playwright code generation. Secrets stay on your machine.") }),
45649
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] mt-3", style: { color: "var(--text-muted)" }, children: t("version :version", { version: "0.8.8" }) })
45671
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] mt-3", style: { color: "var(--text-muted)" }, children: t("version :version", { version: "0.8.9" }) })
45650
45672
  ] }),
45651
45673
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-3 w-64", children: [
45652
45674
  /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -50534,7 +50556,7 @@ function toCSV(ds) {
50534
50556
  function parseCSV(text) {
50535
50557
  const lines = text.trim().split(/\r?\n/).filter(Boolean);
50536
50558
  if (lines.length === 0) return { columns: [], rows: [] };
50537
- function splitRow(line) {
50559
+ function splitRow2(line) {
50538
50560
  const cells = [];
50539
50561
  let cur = "";
50540
50562
  let inQuote = false;
@@ -50555,8 +50577,8 @@ function parseCSV(text) {
50555
50577
  cells.push(cur.trim());
50556
50578
  return cells;
50557
50579
  }
50558
- const columns = splitRow(lines[0]);
50559
- const rows = lines.slice(1).map(splitRow);
50580
+ const columns = splitRow2(lines[0]);
50581
+ const rows = lines.slice(1).map(splitRow2);
50560
50582
  return { columns, rows };
50561
50583
  }
50562
50584
  function DataSetEditor({ ds, onChange, exportName, scopeLabel = "collection" }) {
@@ -57178,7 +57200,7 @@ function App() {
57178
57200
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { color: "#6aa3c8" }, children: "Spector" }),
57179
57201
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ml-2 text-[10px] font-normal opacity-50", children: [
57180
57202
  "v",
57181
- "0.8.8"
57203
+ "0.8.9"
57182
57204
  ] }),
57183
57205
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "mx-2 opacity-30", children: "·" }),
57184
57206
  /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -5,7 +5,7 @@
5
5
  <meta charset="UTF-8" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>API Spector</title>
8
- <script type="module" crossorigin src="./assets/index-fV0So_bF.js"></script>
8
+ <script type="module" crossorigin src="./assets/index-D_-cF6J0.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="./assets/codemirror-BKmwMUlV.js">
10
10
  <link rel="modulepreload" crossorigin href="./assets/ajv-CJPwFjiP.js">
11
11
  <link rel="stylesheet" crossorigin href="./assets/index-Dj6OhE3D.css">
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@testsmith/api-spector",
3
3
  "productName": "API Spector",
4
- "version": "0.8.8",
4
+ "version": "0.8.9",
5
5
  "description": "Local-first API testing tool to inspect, test and mock APIs",
6
6
  "repository": {
7
7
  "type": "git",