@devasign/verify 1.3.2 → 1.5.0

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.
Files changed (2) hide show
  1. package/dist/cli.js +168 -109
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -86,15 +86,15 @@ var require_visit = __commonJS({
86
86
  visit.BREAK = BREAK;
87
87
  visit.SKIP = SKIP;
88
88
  visit.REMOVE = REMOVE;
89
- function visit_(key, node, visitor, path8) {
90
- let ctrl = callVisitor(key, node, visitor, path8);
89
+ function visit_(key, node, visitor, path9) {
90
+ let ctrl = callVisitor(key, node, visitor, path9);
91
91
  if (identity.isNode(ctrl) || identity.isPair(ctrl))
92
- return replaceNode(key, path8, ctrl), visit_(key, ctrl, visitor, path8);
92
+ return replaceNode(key, path9, ctrl), visit_(key, ctrl, visitor, path9);
93
93
  if (typeof ctrl != "symbol") {
94
94
  if (identity.isCollection(node)) {
95
- path8 = Object.freeze(path8.concat(node));
95
+ path9 = Object.freeze(path9.concat(node));
96
96
  for (let i = 0; i < node.items.length; ++i) {
97
- let ci = visit_(i, node.items[i], visitor, path8);
97
+ let ci = visit_(i, node.items[i], visitor, path9);
98
98
  if (typeof ci == "number")
99
99
  i = ci - 1;
100
100
  else {
@@ -104,12 +104,12 @@ var require_visit = __commonJS({
104
104
  }
105
105
  }
106
106
  } else if (identity.isPair(node)) {
107
- path8 = Object.freeze(path8.concat(node));
108
- let ck = visit_("key", node.key, visitor, path8);
107
+ path9 = Object.freeze(path9.concat(node));
108
+ let ck = visit_("key", node.key, visitor, path9);
109
109
  if (ck === BREAK)
110
110
  return BREAK;
111
111
  ck === REMOVE && (node.key = null);
112
- let cv = visit_("value", node.value, visitor, path8);
112
+ let cv = visit_("value", node.value, visitor, path9);
113
113
  if (cv === BREAK)
114
114
  return BREAK;
115
115
  cv === REMOVE && (node.value = null);
@@ -124,15 +124,15 @@ var require_visit = __commonJS({
124
124
  visitAsync.BREAK = BREAK;
125
125
  visitAsync.SKIP = SKIP;
126
126
  visitAsync.REMOVE = REMOVE;
127
- async function visitAsync_(key, node, visitor, path8) {
128
- let ctrl = await callVisitor(key, node, visitor, path8);
127
+ async function visitAsync_(key, node, visitor, path9) {
128
+ let ctrl = await callVisitor(key, node, visitor, path9);
129
129
  if (identity.isNode(ctrl) || identity.isPair(ctrl))
130
- return replaceNode(key, path8, ctrl), visitAsync_(key, ctrl, visitor, path8);
130
+ return replaceNode(key, path9, ctrl), visitAsync_(key, ctrl, visitor, path9);
131
131
  if (typeof ctrl != "symbol") {
132
132
  if (identity.isCollection(node)) {
133
- path8 = Object.freeze(path8.concat(node));
133
+ path9 = Object.freeze(path9.concat(node));
134
134
  for (let i = 0; i < node.items.length; ++i) {
135
- let ci = await visitAsync_(i, node.items[i], visitor, path8);
135
+ let ci = await visitAsync_(i, node.items[i], visitor, path9);
136
136
  if (typeof ci == "number")
137
137
  i = ci - 1;
138
138
  else {
@@ -142,12 +142,12 @@ var require_visit = __commonJS({
142
142
  }
143
143
  }
144
144
  } else if (identity.isPair(node)) {
145
- path8 = Object.freeze(path8.concat(node));
146
- let ck = await visitAsync_("key", node.key, visitor, path8);
145
+ path9 = Object.freeze(path9.concat(node));
146
+ let ck = await visitAsync_("key", node.key, visitor, path9);
147
147
  if (ck === BREAK)
148
148
  return BREAK;
149
149
  ck === REMOVE && (node.key = null);
150
- let cv = await visitAsync_("value", node.value, visitor, path8);
150
+ let cv = await visitAsync_("value", node.value, visitor, path9);
151
151
  if (cv === BREAK)
152
152
  return BREAK;
153
153
  cv === REMOVE && (node.value = null);
@@ -170,22 +170,22 @@ var require_visit = __commonJS({
170
170
  Seq: visitor.Collection
171
171
  }, visitor) : visitor;
172
172
  }
173
- function callVisitor(key, node, visitor, path8) {
173
+ function callVisitor(key, node, visitor, path9) {
174
174
  if (typeof visitor == "function")
175
- return visitor(key, node, path8);
175
+ return visitor(key, node, path9);
176
176
  if (identity.isMap(node))
177
- return visitor.Map?.(key, node, path8);
177
+ return visitor.Map?.(key, node, path9);
178
178
  if (identity.isSeq(node))
179
- return visitor.Seq?.(key, node, path8);
179
+ return visitor.Seq?.(key, node, path9);
180
180
  if (identity.isPair(node))
181
- return visitor.Pair?.(key, node, path8);
181
+ return visitor.Pair?.(key, node, path9);
182
182
  if (identity.isScalar(node))
183
- return visitor.Scalar?.(key, node, path8);
183
+ return visitor.Scalar?.(key, node, path9);
184
184
  if (identity.isAlias(node))
185
- return visitor.Alias?.(key, node, path8);
185
+ return visitor.Alias?.(key, node, path9);
186
186
  }
187
- function replaceNode(key, path8, node) {
188
- let parent = path8[path8.length - 1];
187
+ function replaceNode(key, path9, node) {
188
+ let parent = path9[path9.length - 1];
189
189
  if (identity.isCollection(parent))
190
190
  parent.items[key] = node;
191
191
  else if (identity.isPair(parent))
@@ -639,10 +639,10 @@ var require_Collection = __commonJS({
639
639
  "node_modules/yaml/dist/nodes/Collection.js"(exports) {
640
640
  "use strict";
641
641
  var createNode = require_createNode(), identity = require_identity(), Node = require_Node();
642
- function collectionFromPath(schema, path8, value) {
642
+ function collectionFromPath(schema, path9, value) {
643
643
  let v = value;
644
- for (let i = path8.length - 1; i >= 0; --i) {
645
- let k = path8[i];
644
+ for (let i = path9.length - 1; i >= 0; --i) {
645
+ let k = path9[i];
646
646
  if (typeof k == "number" && Number.isInteger(k) && k >= 0) {
647
647
  let a = [];
648
648
  a[k] = v, v = a;
@@ -659,7 +659,7 @@ var require_Collection = __commonJS({
659
659
  sourceObjects: /* @__PURE__ */ new Map()
660
660
  });
661
661
  }
662
- var isEmptyPath = (path8) => path8 == null || typeof path8 == "object" && !!path8[Symbol.iterator]().next().done, Collection = class extends Node.NodeBase {
662
+ var isEmptyPath = (path9) => path9 == null || typeof path9 == "object" && !!path9[Symbol.iterator]().next().done, Collection = class extends Node.NodeBase {
663
663
  constructor(type, schema) {
664
664
  super(type), Object.defineProperty(this, "schema", {
665
665
  value: schema,
@@ -682,11 +682,11 @@ var require_Collection = __commonJS({
682
682
  * be a Pair instance or a `{ key, value }` object, which may not have a key
683
683
  * that already exists in the map.
684
684
  */
685
- addIn(path8, value) {
686
- if (isEmptyPath(path8))
685
+ addIn(path9, value) {
686
+ if (isEmptyPath(path9))
687
687
  this.add(value);
688
688
  else {
689
- let [key, ...rest] = path8, node = this.get(key, !0);
689
+ let [key, ...rest] = path9, node = this.get(key, !0);
690
690
  if (identity.isCollection(node))
691
691
  node.addIn(rest, value);
692
692
  else if (node === void 0 && this.schema)
@@ -699,8 +699,8 @@ var require_Collection = __commonJS({
699
699
  * Removes a value from the collection.
700
700
  * @returns `true` if the item was found and removed.
701
701
  */
702
- deleteIn(path8) {
703
- let [key, ...rest] = path8;
702
+ deleteIn(path9) {
703
+ let [key, ...rest] = path9;
704
704
  if (rest.length === 0)
705
705
  return this.delete(key);
706
706
  let node = this.get(key, !0);
@@ -713,8 +713,8 @@ var require_Collection = __commonJS({
713
713
  * scalar values from their surrounding node; to disable set `keepScalar` to
714
714
  * `true` (collections are always returned intact).
715
715
  */
716
- getIn(path8, keepScalar) {
717
- let [key, ...rest] = path8, node = this.get(key, !0);
716
+ getIn(path9, keepScalar) {
717
+ let [key, ...rest] = path9, node = this.get(key, !0);
718
718
  return rest.length === 0 ? !keepScalar && identity.isScalar(node) ? node.value : node : identity.isCollection(node) ? node.getIn(rest, keepScalar) : void 0;
719
719
  }
720
720
  hasAllNullValues(allowScalar) {
@@ -728,8 +728,8 @@ var require_Collection = __commonJS({
728
728
  /**
729
729
  * Checks if the collection includes a value with the key `key`.
730
730
  */
731
- hasIn(path8) {
732
- let [key, ...rest] = path8;
731
+ hasIn(path9) {
732
+ let [key, ...rest] = path9;
733
733
  if (rest.length === 0)
734
734
  return this.has(key);
735
735
  let node = this.get(key, !0);
@@ -739,8 +739,8 @@ var require_Collection = __commonJS({
739
739
  * Sets a value in this collection. For `!!set`, `value` needs to be a
740
740
  * boolean to add/remove the item from the set.
741
741
  */
742
- setIn(path8, value) {
743
- let [key, ...rest] = path8;
742
+ setIn(path9, value) {
743
+ let [key, ...rest] = path9;
744
744
  if (rest.length === 0)
745
745
  this.set(key, value);
746
746
  else {
@@ -2613,8 +2613,8 @@ var require_Document = __commonJS({
2613
2613
  assertCollection(this.contents) && this.contents.add(value);
2614
2614
  }
2615
2615
  /** Adds a value to the document. */
2616
- addIn(path8, value) {
2617
- assertCollection(this.contents) && this.contents.addIn(path8, value);
2616
+ addIn(path9, value) {
2617
+ assertCollection(this.contents) && this.contents.addIn(path9, value);
2618
2618
  }
2619
2619
  /**
2620
2620
  * Create a new `Alias` node, ensuring that the target `node` has the required anchor.
@@ -2675,8 +2675,8 @@ var require_Document = __commonJS({
2675
2675
  * Removes a value from the document.
2676
2676
  * @returns `true` if the item was found and removed.
2677
2677
  */
2678
- deleteIn(path8) {
2679
- return Collection.isEmptyPath(path8) ? this.contents == null ? !1 : (this.contents = null, !0) : assertCollection(this.contents) ? this.contents.deleteIn(path8) : !1;
2678
+ deleteIn(path9) {
2679
+ return Collection.isEmptyPath(path9) ? this.contents == null ? !1 : (this.contents = null, !0) : assertCollection(this.contents) ? this.contents.deleteIn(path9) : !1;
2680
2680
  }
2681
2681
  /**
2682
2682
  * Returns item at `key`, or `undefined` if not found. By default unwraps
@@ -2691,8 +2691,8 @@ var require_Document = __commonJS({
2691
2691
  * scalar values from their surrounding node; to disable set `keepScalar` to
2692
2692
  * `true` (collections are always returned intact).
2693
2693
  */
2694
- getIn(path8, keepScalar) {
2695
- return Collection.isEmptyPath(path8) ? !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents : identity.isCollection(this.contents) ? this.contents.getIn(path8, keepScalar) : void 0;
2694
+ getIn(path9, keepScalar) {
2695
+ return Collection.isEmptyPath(path9) ? !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents : identity.isCollection(this.contents) ? this.contents.getIn(path9, keepScalar) : void 0;
2696
2696
  }
2697
2697
  /**
2698
2698
  * Checks if the document includes a value with the key `key`.
@@ -2703,8 +2703,8 @@ var require_Document = __commonJS({
2703
2703
  /**
2704
2704
  * Checks if the document includes a value at `path`.
2705
2705
  */
2706
- hasIn(path8) {
2707
- return Collection.isEmptyPath(path8) ? this.contents !== void 0 : identity.isCollection(this.contents) ? this.contents.hasIn(path8) : !1;
2706
+ hasIn(path9) {
2707
+ return Collection.isEmptyPath(path9) ? this.contents !== void 0 : identity.isCollection(this.contents) ? this.contents.hasIn(path9) : !1;
2708
2708
  }
2709
2709
  /**
2710
2710
  * Sets a value in this document. For `!!set`, `value` needs to be a
@@ -2717,8 +2717,8 @@ var require_Document = __commonJS({
2717
2717
  * Sets a value in this document. For `!!set`, `value` needs to be a
2718
2718
  * boolean to add/remove the item from the set.
2719
2719
  */
2720
- setIn(path8, value) {
2721
- Collection.isEmptyPath(path8) ? this.contents = value : this.contents == null ? this.contents = Collection.collectionFromPath(this.schema, Array.from(path8), value) : assertCollection(this.contents) && this.contents.setIn(path8, value);
2720
+ setIn(path9, value) {
2721
+ Collection.isEmptyPath(path9) ? this.contents = value : this.contents == null ? this.contents = Collection.collectionFromPath(this.schema, Array.from(path9), value) : assertCollection(this.contents) && this.contents.setIn(path9, value);
2722
2722
  }
2723
2723
  /**
2724
2724
  * Change the YAML version and schema used by the document.
@@ -4113,9 +4113,9 @@ var require_cst_visit = __commonJS({
4113
4113
  visit.BREAK = BREAK;
4114
4114
  visit.SKIP = SKIP;
4115
4115
  visit.REMOVE = REMOVE;
4116
- visit.itemAtPath = (cst, path8) => {
4116
+ visit.itemAtPath = (cst, path9) => {
4117
4117
  let item = cst;
4118
- for (let [field, index] of path8) {
4118
+ for (let [field, index] of path9) {
4119
4119
  let tok = item?.[field];
4120
4120
  if (tok && "items" in tok)
4121
4121
  item = tok.items[index];
@@ -4124,21 +4124,21 @@ var require_cst_visit = __commonJS({
4124
4124
  }
4125
4125
  return item;
4126
4126
  };
4127
- visit.parentCollection = (cst, path8) => {
4128
- let parent = visit.itemAtPath(cst, path8.slice(0, -1)), field = path8[path8.length - 1][0], coll = parent?.[field];
4127
+ visit.parentCollection = (cst, path9) => {
4128
+ let parent = visit.itemAtPath(cst, path9.slice(0, -1)), field = path9[path9.length - 1][0], coll = parent?.[field];
4129
4129
  if (coll && "items" in coll)
4130
4130
  return coll;
4131
4131
  throw new Error("Parent collection not found");
4132
4132
  };
4133
- function _visit(path8, item, visitor) {
4134
- let ctrl = visitor(item, path8);
4133
+ function _visit(path9, item, visitor) {
4134
+ let ctrl = visitor(item, path9);
4135
4135
  if (typeof ctrl == "symbol")
4136
4136
  return ctrl;
4137
4137
  for (let field of ["key", "value"]) {
4138
4138
  let token = item[field];
4139
4139
  if (token && "items" in token) {
4140
4140
  for (let i = 0; i < token.items.length; ++i) {
4141
- let ci = _visit(Object.freeze(path8.concat([[field, i]])), token.items[i], visitor);
4141
+ let ci = _visit(Object.freeze(path9.concat([[field, i]])), token.items[i], visitor);
4142
4142
  if (typeof ci == "number")
4143
4143
  i = ci - 1;
4144
4144
  else {
@@ -4147,10 +4147,10 @@ var require_cst_visit = __commonJS({
4147
4147
  ci === REMOVE && (token.items.splice(i, 1), i -= 1);
4148
4148
  }
4149
4149
  }
4150
- typeof ctrl == "function" && field === "key" && (ctrl = ctrl(item, path8));
4150
+ typeof ctrl == "function" && field === "key" && (ctrl = ctrl(item, path9));
4151
4151
  }
4152
4152
  }
4153
- return typeof ctrl == "function" ? ctrl(item, path8) : ctrl;
4153
+ return typeof ctrl == "function" ? ctrl(item, path9) : ctrl;
4154
4154
  }
4155
4155
  exports.visit = visit;
4156
4156
  }
@@ -5584,7 +5584,7 @@ async function detectSetup(root, opts = {}) {
5584
5584
  ...new Set(
5585
5585
  paths.filter((p) => /^[^/]+\/[^/]+\/package\.json$/.test(p)).reduce((acc, p) => acc.concat(manifestNames(readText(root, p))), Object.keys(deps))
5586
5586
  )
5587
- ].sort() : void 0, langCounts = /* @__PURE__ */ new Map();
5587
+ ].sort() : pkgText == null ? [] : void 0, langCounts = /* @__PURE__ */ new Map();
5588
5588
  for (let p of paths) {
5589
5589
  let lang = LANG_BY_EXT[p.split(".").pop()?.toLowerCase() || ""];
5590
5590
  lang && langCounts.set(lang, (langCounts.get(lang) || 0) + 1);
@@ -5713,11 +5713,11 @@ function staticTokenSource(token) {
5713
5713
  }
5714
5714
 
5715
5715
  // src/run.ts
5716
- import { appendFileSync as appendFileSync2, existsSync as existsSync5, writeFileSync as writeFileSync3 } from "node:fs";
5717
- import path7 from "node:path";
5716
+ import { appendFileSync as appendFileSync2, existsSync as existsSync6, writeFileSync as writeFileSync3 } from "node:fs";
5717
+ import path8 from "node:path";
5718
5718
 
5719
5719
  // src/types.ts
5720
- var CLI_VERSION = "1.3.2";
5720
+ var CLI_VERSION = "1.5.0";
5721
5721
 
5722
5722
  // src/api.ts
5723
5723
  var ApiError = class extends Error {
@@ -5733,11 +5733,11 @@ var ApiError = class extends Error {
5733
5733
  this.fetchImpl = fetchImpl;
5734
5734
  this.baseUrl = baseUrl.replace(/\/+$/, "");
5735
5735
  }
5736
- async request(method, path8, body, attempts = 3) {
5736
+ async request(method, path9, body, attempts = 3) {
5737
5737
  let lastErr;
5738
5738
  for (let i = 0; i < attempts; i++)
5739
5739
  try {
5740
- let res = await this.fetchImpl(`${this.baseUrl}${path8}`, {
5740
+ let res = await this.fetchImpl(`${this.baseUrl}${path9}`, {
5741
5741
  method,
5742
5742
  headers: {
5743
5743
  Authorization: `Bearer ${await this.token()}`,
@@ -5887,10 +5887,65 @@ function readContext(opts = {}) {
5887
5887
  };
5888
5888
  }
5889
5889
 
5890
+ // src/module-type.ts
5891
+ import { existsSync as existsSync2, readFileSync as readFileSync4 } from "node:fs";
5892
+ import path3 from "node:path";
5893
+ var SCOPED_EXT = /\.[jt]sx?$/, ESM_SYNTAX = /^[ \t]*(?:import|export)(?:[ \t]+[A-Za-z_$*{"']|[ \t]*[{*"'])/m, CJS_SYNTAX = /(?:^|[^.\w$])require[ \t]*\(|^[ \t]*(?:module\.exports\b|exports\.[A-Za-z_$])/m;
5894
+ function stripNonCode(source) {
5895
+ return source.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/^[ \t]*\/\/.*$/gm, "").replace(/`(?:\\[\s\S]|[^\\`])*`/g, "``");
5896
+ }
5897
+ function detectModuleSyntax(source) {
5898
+ let code = stripNonCode(source);
5899
+ return ESM_SYNTAX.test(code) ? "module" : CJS_SYNTAX.test(code) ? "commonjs" : null;
5900
+ }
5901
+ function inheritedModuleType(root, dirRel) {
5902
+ let stop = path3.resolve(root);
5903
+ for (let dir = path3.resolve(root, dirRel); ; dir = path3.dirname(dir)) {
5904
+ let manifest = path3.join(dir, "package.json");
5905
+ if (existsSync2(manifest))
5906
+ try {
5907
+ return JSON.parse(readFileSync4(manifest, "utf8")).type === "module" ? "module" : "commonjs";
5908
+ } catch {
5909
+ return "commonjs";
5910
+ }
5911
+ if (dir === stop || path3.dirname(dir) === dir) return "commonjs";
5912
+ }
5913
+ }
5914
+ var posixDir = (p) => path3.posix.dirname(p.split(path3.sep).join("/"));
5915
+ function scopeOf(root, dir, decided) {
5916
+ for (let d = dir; d && d !== "." && d !== "/"; d = path3.posix.dirname(d)) {
5917
+ let shim = decided.get(d);
5918
+ if (shim) return shim;
5919
+ }
5920
+ return inheritedModuleType(root, dir);
5921
+ }
5922
+ function planModuleTypeShims(root, tests) {
5923
+ let wanted = /* @__PURE__ */ new Map();
5924
+ for (let t of tests) {
5925
+ if (t.origin !== "generated" || !SCOPED_EXT.test(t.path)) continue;
5926
+ let dir = posixDir(t.path), needs = t.runner === "playwright" ? inheritedModuleType(root, dir) : t.content ? detectModuleSyntax(t.content) : null;
5927
+ if (!needs) continue;
5928
+ let counts = wanted.get(dir) ?? /* @__PURE__ */ new Map();
5929
+ counts.set(needs, (counts.get(needs) ?? 0) + 1), wanted.set(dir, counts);
5930
+ }
5931
+ let decided = /* @__PURE__ */ new Map(), shims = [];
5932
+ for (let dir of [...wanted.keys()].sort((a, b) => a.split("/").length - b.split("/").length || a.localeCompare(b))) {
5933
+ let counts = wanted.get(dir), type = (counts.get("module") ?? 0) >= (counts.get("commonjs") ?? 0) ? "module" : "commonjs";
5934
+ scopeOf(root, dir, decided) !== type && (decided.set(dir, type), shims.push({ dir, type }));
5935
+ }
5936
+ return shims;
5937
+ }
5938
+ function writeModuleTypeShims(ws, tests) {
5939
+ let shims = planModuleTypeShims(ws.root, tests);
5940
+ for (let s of shims) ws.write(path3.posix.join(s.dir, "package.json"), `${JSON.stringify({ type: s.type })}
5941
+ `);
5942
+ return shims;
5943
+ }
5944
+
5890
5945
  // src/runners/index.ts
5891
5946
  import { createRequire } from "node:module";
5892
- import { existsSync as existsSync2 } from "node:fs";
5893
- import path4 from "node:path";
5947
+ import { existsSync as existsSync3 } from "node:fs";
5948
+ import path5 from "node:path";
5894
5949
 
5895
5950
  // src/classify.ts
5896
5951
  var ASSERTION = {
@@ -6009,7 +6064,7 @@ function firstErrorLine(out) {
6009
6064
  // src/exec.ts
6010
6065
  import { spawn } from "node:child_process";
6011
6066
  import { mkdirSync, writeFileSync } from "node:fs";
6012
- import path3 from "node:path";
6067
+ import path4 from "node:path";
6013
6068
  var MAX_CAPTURE = 5 * 1024 * 1024, DRAIN_MS = 2e3;
6014
6069
  async function runCommand(opts) {
6015
6070
  let started = Date.now();
@@ -6039,7 +6094,7 @@ async function runCommand(opts) {
6039
6094
  let full = { ...result, stdout, stderr, output, durationMs: Date.now() - started };
6040
6095
  if (opts.logFile)
6041
6096
  try {
6042
- mkdirSync(path3.dirname(opts.logFile), { recursive: !0 }), writeFileSync(opts.logFile, `$ ${opts.cmd} ${opts.args.join(" ")}
6097
+ mkdirSync(path4.dirname(opts.logFile), { recursive: !0 }), writeFileSync(opts.logFile, `$ ${opts.cmd} ${opts.args.join(" ")}
6043
6098
 
6044
6099
  ${output}
6045
6100
 
@@ -6061,8 +6116,8 @@ function tsxLoader() {
6061
6116
  return require2.resolve("tsx/esm");
6062
6117
  }
6063
6118
  function bin(root, name) {
6064
- let p = path4.join(root, "node_modules", ".bin", name);
6065
- return existsSync2(p) ? p : null;
6119
+ let p = path5.join(root, "node_modules", ".bin", name);
6120
+ return existsSync3(p) ? p : null;
6066
6121
  }
6067
6122
  function commandForFile(runner, file, root) {
6068
6123
  switch (runner) {
@@ -6073,7 +6128,7 @@ function commandForFile(runner, file, root) {
6073
6128
  case "pytest":
6074
6129
  return { cmd: "python3", args: ["-m", "pytest", "-q", "-p", "no:cacheprovider", file] };
6075
6130
  case "go":
6076
- return { cmd: "go", args: ["test", "./" + path4.posix.dirname(file) + "/", "-run", ".", "-count=1"] };
6131
+ return { cmd: "go", args: ["test", "./" + path5.posix.dirname(file) + "/", "-run", ".", "-count=1"] };
6077
6132
  case "node-test":
6078
6133
  case "bundled":
6079
6134
  default:
@@ -6086,7 +6141,7 @@ async function runFileTests(args) {
6086
6141
  let max = Math.max(1, args.maxAttempts(t)), attempts = [], attemptRefs = [];
6087
6142
  log.group(`${t.origin} ${t.level} ${t.path} (${t.runner})`);
6088
6143
  for (let n = 1; n <= max; n++) {
6089
- let { cmd, args: argv } = commandForFile(t.runner, t.path, args.ws.root), logFile = path4.join(args.ws.artifactsDir, "logs", `${t.id}-${n}.log`), r = await runCommand({ cmd, args: argv, cwd: args.ws.root, timeoutMs: args.timeoutMs, logFile, onLine: (l) => console.log(` ${l}`) }), c = classifyAttempt(t.runner, r), ref = `log:${t.id}:${n}`;
6144
+ let { cmd, args: argv } = commandForFile(t.runner, t.path, args.ws.root), logFile = path5.join(args.ws.artifactsDir, "logs", `${t.id}-${n}.log`), r = await runCommand({ cmd, args: argv, cwd: args.ws.root, timeoutMs: args.timeoutMs, logFile, onLine: (l) => console.log(` ${l}`) }), c = classifyAttempt(t.runner, r), ref = `log:${t.id}:${n}`;
6090
6145
  if (args.artifacts.push({ clientRef: ref, kind: "log", path: logFile, displayPath: args.ws.relative(logFile), contentType: "text/plain", testId: t.id, criterionIds: t.criterionIds, attempt: n }), attempts.push({ n, status: c.status, durationMs: r.durationMs, error: c.error, artifactIds: [] }), attemptRefs.push([ref]), log.info(`attempt ${n}/${max}: ${c.status}${c.error ? ` \u2014 ${c.error}` : ""}`), c.status === "pass" && n === 1 || c.status === "pass" && n > 1 || c.status === "error" && max > 1 && n === 1 && /could not start|ENOENT|Cannot find module|Cannot find package|Failed to (?:load url|resolve import)/.test(c.error || "")) break;
6091
6146
  }
6092
6147
  log.endGroup();
@@ -6112,23 +6167,23 @@ async function runFileTests(args) {
6112
6167
 
6113
6168
  // src/runners/playwright.ts
6114
6169
  import { createRequire as createRequire2 } from "node:module";
6115
- import { existsSync as existsSync3, readdirSync as readdirSync2, readFileSync as readFileSync4, statSync as statSync3 } from "node:fs";
6170
+ import { existsSync as existsSync4, readdirSync as readdirSync2, readFileSync as readFileSync5, statSync as statSync3 } from "node:fs";
6116
6171
  import { homedir } from "node:os";
6117
- import path5 from "node:path";
6172
+ import path6 from "node:path";
6118
6173
  var require3 = createRequire2(import.meta.url);
6119
6174
  function playwrightCli(root) {
6120
- let local = path5.join(root, "node_modules", "@playwright", "test", "cli.js");
6121
- return existsSync3(local) ? { cmd: process.execPath, args: [local], ours: !1 } : { cmd: process.execPath, args: [require3.resolve("@playwright/test/cli")], ours: !0 };
6175
+ let local = path6.join(root, "node_modules", "@playwright", "test", "cli.js");
6176
+ return existsSync4(local) ? { cmd: process.execPath, args: [local], ours: !1 } : { cmd: process.execPath, args: [require3.resolve("@playwright/test/cli")], ours: !0 };
6122
6177
  }
6123
6178
  function ourPlaywrightDir() {
6124
- return path5.dirname(require3.resolve("@playwright/test/package.json"));
6179
+ return path6.dirname(require3.resolve("@playwright/test/package.json"));
6125
6180
  }
6126
6181
  function generatePlaywrightConfig(a) {
6127
6182
  let j = (v) => JSON.stringify(v);
6128
6183
  return [
6129
6184
  "// Generated by @devasign/verify \u2014 disposable; the repository's own config is untouched.",
6130
6185
  'import { defineConfig } from "@playwright/test";',
6131
- a.baseConfigRel ? `import __base from ${j(path5.resolve(a.root, a.baseConfigRel))};` : "const __base: any = {};",
6186
+ a.baseConfigRel ? `import __base from ${j(path6.resolve(a.root, a.baseConfigRel))};` : "const __base: any = {};",
6132
6187
  "const b: any = (__base as any)?.default ?? __base ?? {};",
6133
6188
  "// One browser project only: recordings once, and no browsers we did not install.",
6134
6189
  "// Project fields win over config fields in Playwright, so the customer's own",
@@ -6170,8 +6225,8 @@ function flattenSpecs(report) {
6170
6225
  return out;
6171
6226
  }
6172
6227
  function pathsMatch(reportFile, planned) {
6173
- let a = reportFile.split(path5.sep).join("/"), b = planned.split(path5.sep).join("/");
6174
- return a === b || a.endsWith("/" + b) || b.endsWith("/" + a) || path5.posix.basename(a) === path5.posix.basename(b);
6228
+ let a = reportFile.split(path6.sep).join("/"), b = planned.split(path6.sep).join("/");
6229
+ return a === b || a.endsWith("/" + b) || b.endsWith("/" + a) || path6.posix.basename(a) === path6.posix.basename(b);
6175
6230
  }
6176
6231
  function stripAnsi(s) {
6177
6232
  return s.replace(/\u001b\[[0-9;]*m/g, "");
@@ -6199,7 +6254,7 @@ function mapReport(report, tests, ws, artifacts, overallOutput) {
6199
6254
  let refs = [], videoRef = null, screenshotPath = null;
6200
6255
  for (let att of r.attachments || []) {
6201
6256
  let kind = KIND_BY_ATTACHMENT[att.name || ""];
6202
- if (!kind || !att.path || !existsSync3(att.path)) continue;
6257
+ if (!kind || !att.path || !existsSync4(att.path)) continue;
6203
6258
  let ref = `${kind}:${t.id}:${n}:${refs.length}`;
6204
6259
  artifacts.push({ clientRef: ref, kind, path: att.path, displayPath: ws.relative(att.path), contentType: att.contentType || TYPE_BY_KIND[kind], testId: t.id, criterionIds: t.criterionIds, attempt: n }), refs.push(ref), kind === "video" && (videoRef = ref), kind === "screenshot" && !screenshotPath && (screenshotPath = att.path);
6205
6260
  }
@@ -6228,14 +6283,15 @@ function mapReport(report, tests, ws, artifacts, overallOutput) {
6228
6283
  status,
6229
6284
  attempts,
6230
6285
  durationMs: attempts.reduce((s, a) => s + a.durationMs, 0),
6231
- error: status === "pass" ? void 0 : attempts[attempts.length - 1]?.error,
6286
+ // Not the last attempt: in a multi-test file that can be a sibling that passed.
6287
+ error: attempts.find((a) => a.status === status)?.error,
6232
6288
  artifactIds: []
6233
6289
  });
6234
6290
  }
6235
6291
  return results;
6236
6292
  }
6237
6293
  function playwrightBrowsersRoot(env = process.env, home = homedir()) {
6238
- return env.PLAYWRIGHT_BROWSERS_PATH ? env.PLAYWRIGHT_BROWSERS_PATH : process.platform === "darwin" ? path5.join(home, "Library", "Caches", "ms-playwright") : process.platform === "win32" ? path5.join(env.LOCALAPPDATA || home, "ms-playwright") : path5.join(home, ".cache", "ms-playwright");
6294
+ return env.PLAYWRIGHT_BROWSERS_PATH ? env.PLAYWRIGHT_BROWSERS_PATH : process.platform === "darwin" ? path6.join(home, "Library", "Caches", "ms-playwright") : process.platform === "win32" ? path6.join(env.LOCALAPPDATA || home, "ms-playwright") : path6.join(home, ".cache", "ms-playwright");
6239
6295
  }
6240
6296
  function hasChromium(root, read = readdirSync2) {
6241
6297
  try {
@@ -6249,37 +6305,37 @@ async function ensureBrowsers(root, ws) {
6249
6305
  return log.info("Chromium already installed; skipping download"), { ok: !0, log: "cached" };
6250
6306
  let cli = playwrightCli(root), args = [...cli.args, "install", ...process.platform === "linux" ? ["--with-deps"] : [], "chromium"];
6251
6307
  log.info("installing Chromium for Playwright");
6252
- let r = await runCommand({ cmd: cli.cmd, args, cwd: root, timeoutMs: 10 * 6e4, logFile: path5.join(ws.artifactsDir, "logs", "playwright-install.log") });
6308
+ let r = await runCommand({ cmd: cli.cmd, args, cwd: root, timeoutMs: 10 * 6e4, logFile: path6.join(ws.artifactsDir, "logs", "playwright-install.log") });
6253
6309
  return { ok: r.code === 0, log: r.output };
6254
6310
  }
6255
6311
  async function runPlaywright(args) {
6256
- let { ws } = args, outputDir = path5.join(ws.artifactsDir, "pw", args.configName.replace(/\.config\.ts$/, "")), reportFile = path5.join(outputDir, "report.json"), cli = playwrightCli(ws.root);
6312
+ let { ws } = args, outputDir = path6.join(ws.artifactsDir, "pw", args.configName.replace(/\.config\.ts$/, "")), reportFile = path6.join(outputDir, "report.json"), cli = playwrightCli(ws.root);
6257
6313
  if (cli.ours) {
6258
6314
  ws.linkPackage("@playwright/test", ourPlaywrightDir());
6259
- let pw = path5.join(ourPlaywrightDir(), "..", "..", "playwright");
6260
- existsSync3(pw) && ws.linkPackage("playwright", path5.resolve(pw));
6315
+ let pw = path6.join(ourPlaywrightDir(), "..", "..", "playwright");
6316
+ existsSync4(pw) && ws.linkPackage("playwright", path6.resolve(pw));
6261
6317
  }
6262
- let testDir = args.tests.every((t) => t.origin === "generated") ? path5.join(ws.testsDir, "e2e") : ws.root, cfgSource = generatePlaywrightConfig({ root: ws.root, baseConfigRel: args.baseConfigRel, testDir, outputDir, reportFile, retries: args.retries, webServer: webServerFromYml(args.yml) }), cfgPath = ws.write(path5.join(".devasign", args.configName), cfgSource), files = args.tests.map((t) => path5.resolve(ws.root, t.path));
6318
+ let testDir = args.tests.every((t) => t.origin === "generated") ? path6.join(ws.testsDir, "e2e") : ws.root, cfgSource = generatePlaywrightConfig({ root: ws.root, baseConfigRel: args.baseConfigRel, testDir, outputDir, reportFile, retries: args.retries, webServer: webServerFromYml(args.yml) }), cfgPath = ws.write(path6.join(".devasign", args.configName), cfgSource), files = args.tests.map((t) => path6.resolve(ws.root, t.path));
6263
6319
  log.group(`playwright ${args.configName}: ${files.length} file(s)`);
6264
- let r = await runCommand({ cmd: cli.cmd, args: [...cli.args, "test", "--config", cfgPath, ...files], cwd: ws.root, timeoutMs: args.timeoutMs, logFile: path5.join(ws.artifactsDir, "logs", `${args.configName}.log`), onLine: (l) => console.log(` ${l}`) });
6320
+ let r = await runCommand({ cmd: cli.cmd, args: [...cli.args, "test", "--config", cfgPath, ...files], cwd: ws.root, timeoutMs: args.timeoutMs, logFile: path6.join(ws.artifactsDir, "logs", `${args.configName}.log`), onLine: (l) => console.log(` ${l}`) });
6265
6321
  log.endGroup();
6266
6322
  let report = {};
6267
- if (existsSync3(reportFile) && statSync3(reportFile).size > 0)
6323
+ if (existsSync4(reportFile) && statSync3(reportFile).size > 0)
6268
6324
  try {
6269
- report = JSON.parse(readFileSync4(reportFile, "utf8"));
6325
+ report = JSON.parse(readFileSync5(reportFile, "utf8"));
6270
6326
  } catch (err) {
6271
6327
  log.warn(`could not parse the Playwright JSON report: ${err instanceof Error ? err.message : String(err)}`);
6272
6328
  }
6273
6329
  let logRef = `log:pw:${args.configName}`;
6274
- args.artifacts.push({ clientRef: logRef, kind: "log", path: path5.join(ws.artifactsDir, "logs", `${args.configName}.log`), displayPath: ws.relative(path5.join(ws.artifactsDir, "logs", `${args.configName}.log`)), contentType: "text/plain", criterionIds: [] });
6330
+ args.artifacts.push({ clientRef: logRef, kind: "log", path: path6.join(ws.artifactsDir, "logs", `${args.configName}.log`), displayPath: ws.relative(path6.join(ws.artifactsDir, "logs", `${args.configName}.log`)), contentType: "text/plain", criterionIds: [] });
6275
6331
  let results = mapReport(report, args.tests, ws, args.artifacts, r.output);
6276
6332
  for (let res of results) res.artifactIds = [logRef];
6277
6333
  return { results, output: r.output, code: r.code };
6278
6334
  }
6279
6335
 
6280
6336
  // src/workspace.ts
6281
- import { existsSync as existsSync4, mkdirSync as mkdirSync2, rmSync, symlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
6282
- import path6 from "node:path";
6337
+ import { existsSync as existsSync5, mkdirSync as mkdirSync2, rmSync, symlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
6338
+ import path7 from "node:path";
6283
6339
  var DEVASIGN_DIR = ".devasign", Workspace = class {
6284
6340
  root;
6285
6341
  dir;
@@ -6288,19 +6344,19 @@ var DEVASIGN_DIR = ".devasign", Workspace = class {
6288
6344
  created = [];
6289
6345
  preexistingDir;
6290
6346
  constructor(root) {
6291
- this.root = path6.resolve(root), this.dir = path6.join(this.root, DEVASIGN_DIR), this.artifactsDir = path6.join(this.dir, "artifacts"), this.testsDir = path6.join(this.dir, "tests"), this.preexistingDir = existsSync4(this.dir);
6347
+ this.root = path7.resolve(root), this.dir = path7.join(this.root, DEVASIGN_DIR), this.artifactsDir = path7.join(this.dir, "artifacts"), this.testsDir = path7.join(this.dir, "tests"), this.preexistingDir = existsSync5(this.dir);
6292
6348
  for (let sub of ["tests", "artifacts", "node_modules", "playwright.config.ts", "playwright.existing.config.ts"])
6293
- rmSync(path6.join(this.dir, sub), { recursive: !0, force: !0 });
6349
+ rmSync(path7.join(this.dir, sub), { recursive: !0, force: !0 });
6294
6350
  }
6295
6351
  /** Absolute path for a repo-relative path, refusing anything outside `.devasign/`. */
6296
6352
  resolveOwned(rel) {
6297
- let full = path6.resolve(this.root, rel);
6298
- if (!full.startsWith(this.dir + path6.sep)) throw new Error(`refusing to write outside ${DEVASIGN_DIR}/: ${rel}`);
6353
+ let full = path7.resolve(this.root, rel);
6354
+ if (!full.startsWith(this.dir + path7.sep)) throw new Error(`refusing to write outside ${DEVASIGN_DIR}/: ${rel}`);
6299
6355
  return full;
6300
6356
  }
6301
6357
  write(rel, content) {
6302
6358
  let full = this.resolveOwned(rel);
6303
- return mkdirSync2(path6.dirname(full), { recursive: !0 }), writeFileSync2(full, content), this.created.push(full), full;
6359
+ return mkdirSync2(path7.dirname(full), { recursive: !0 }), writeFileSync2(full, content), this.created.push(full), full;
6304
6360
  }
6305
6361
  ensureDir(rel) {
6306
6362
  let full = this.resolveOwned(rel);
@@ -6308,16 +6364,16 @@ var DEVASIGN_DIR = ".devasign", Workspace = class {
6308
6364
  }
6309
6365
  /** Expose a package from our own install to files under `.devasign/` (never into the repo's node_modules). */
6310
6366
  linkPackage(name, target) {
6311
- let link = this.resolveOwned(path6.join(DEVASIGN_DIR, "node_modules", name));
6312
- existsSync4(link) || (mkdirSync2(path6.dirname(link), { recursive: !0 }), symlinkSync(target, link, "junction"), this.created.push(link));
6367
+ let link = this.resolveOwned(path7.join(DEVASIGN_DIR, "node_modules", name));
6368
+ existsSync5(link) || (mkdirSync2(path7.dirname(link), { recursive: !0 }), symlinkSync(target, link, "junction"), this.created.push(link));
6313
6369
  }
6314
6370
  relative(full) {
6315
- return path6.relative(this.root, full).split(path6.sep).join("/");
6371
+ return path7.relative(this.root, full).split(path7.sep).join("/");
6316
6372
  }
6317
6373
  /** Remove what we created. A pre-existing `.devasign/` (hooks, config) stays. */
6318
6374
  cleanup() {
6319
6375
  for (let p of [...this.created].reverse()) rmSync(p, { recursive: !0, force: !0 });
6320
- for (let sub of ["tests", "artifacts", "node_modules"]) rmSync(path6.join(this.dir, sub), { recursive: !0, force: !0 });
6376
+ for (let sub of ["tests", "artifacts", "node_modules"]) rmSync(path7.join(this.dir, sub), { recursive: !0, force: !0 });
6321
6377
  this.preexistingDir || rmSync(this.dir, { recursive: !0, force: !0 }), this.created = [];
6322
6378
  }
6323
6379
  };
@@ -6355,9 +6411,11 @@ async function executePlan(plan, ws, opts) {
6355
6411
  let full = ws.write(t.path, t.content);
6356
6412
  artifacts.push({ clientRef: `test_file:${t.id}`, kind: "test_file", path: full, displayPath: t.path, contentType: "text/plain", testId: t.id, criterionIds: t.criterionIds });
6357
6413
  }
6414
+ for (let s of writeModuleTypeShims(ws, plan.tests))
6415
+ log.info(`${s.dir}: declared "type": "${s.type}" so the tests relocated there load as they were written`);
6358
6416
  for (let t of plan.tests)
6359
- t.origin === "existing" && !existsSync5(path7.resolve(ws.root, t.path)) && results.push({ id: `r-${t.id}`, testId: t.id, criterionIds: t.criterionIds, test: t.path, runner: t.runner, level: t.level, origin: t.origin, status: "error", attempts: [], durationMs: 0, error: "existing test not found in the checkout", artifactIds: [] });
6360
- let runnable = plan.tests.filter((t) => !(t.origin === "existing" && !existsSync5(path7.resolve(ws.root, t.path)))), pw = runnable.filter((t) => t.runner === "playwright"), others = runnable.filter((t) => t.runner !== "playwright");
6417
+ t.origin === "existing" && !existsSync6(path8.resolve(ws.root, t.path)) && results.push({ id: `r-${t.id}`, testId: t.id, criterionIds: t.criterionIds, test: t.path, runner: t.runner, level: t.level, origin: t.origin, status: "error", attempts: [], durationMs: 0, error: "existing test not found in the checkout", artifactIds: [] });
6418
+ let runnable = plan.tests.filter((t) => !(t.origin === "existing" && !existsSync6(path8.resolve(ws.root, t.path)))), pw = runnable.filter((t) => t.runner === "playwright"), others = runnable.filter((t) => t.runner !== "playwright");
6361
6419
  if (results.push(...await runFileTests({ tests: others, ws, maxAttempts: (t) => t.origin === "generated" ? 1 + plan.retries.generated : 1, timeoutMs: opts.testTimeoutMs, artifacts })), pw.length) {
6362
6420
  let repoCfg = opts.setup?.frameworks.find((f) => f.name === "playwright")?.configPath ?? null;
6363
6421
  if (doctor = preflight({ tests: pw, setup: opts.setup, yml: opts.yml, repoHasPlaywrightConfig: !!repoCfg, env: process.env, nodeVersion: process.version }), doctor) {
@@ -6385,7 +6443,7 @@ function summaryTable(plan, results) {
6385
6443
  return ["| Criterion | Test | Outcome | Notes |", "|---|---|---|---|", ...plan.criteria.map((c) => {
6386
6444
  let mine = results.filter((r) => r.criterionIds.includes(c.id)), u = unverifiable.get(c.id);
6387
6445
  if (mine.length) {
6388
- let tests = mine.map((r) => `${r.level} ${r.origin} \`${cell(r.test)}\``).join("<br>"), outcome = mine.map((r) => `${r.status} (${r.attempts.length} attempt${r.attempts.length === 1 ? "" : "s"})`).join("<br>");
6446
+ let tests = mine.map((r) => `${r.level} ${r.origin} \`${cell(r.test)}\``).join("<br>"), outcome = mine.map((r) => `${r.status} (${r.attempts.length} ${r.runner === "playwright" ? "result" : "attempt"}${r.attempts.length === 1 ? "" : "s"})`).join("<br>");
6389
6447
  return `| ${c.id}. ${cell(c.text)} | ${tests} | ${outcome} | |`;
6390
6448
  }
6391
6449
  let note = u ? `${cell(u.reason)}${u.fixUrl ? ` \u2014 [configure app start](${u.fixUrl})` : ""}` : "no test planned";
@@ -6423,9 +6481,10 @@ async function run(opts) {
6423
6481
  plan = resolved.plan, runId = resolved.runId, log.info(`plan ${plan.planId}: ${plan.tests.length} test(s) for ${plan.criteria.length} criteria (run ${runId})`), setOutput("run-id", runId);
6424
6482
  }
6425
6483
  announceUnverifiable(plan);
6426
- let failOn = opts.failOn ?? plan.failOn ?? "never";
6484
+ let failOn = opts.failOn ?? plan.failOn ?? "never", bootYml = yml ?? plan.verifyConfig ?? null;
6485
+ !yml && plan.verifyConfig && log.info("no verify block in this checkout's .devasign.yml; starting the app with the one the plan was made from");
6427
6486
  try {
6428
- let { results, artifacts, doctor } = await executePlan(plan, ws, { yml, testTimeoutMs: opts.testTimeoutMs, setup }), finalResults = results;
6487
+ let { results, artifacts, doctor } = await executePlan(plan, ws, { yml: bootYml, testTimeoutMs: opts.testTimeoutMs, setup }), finalResults = results;
6429
6488
  if (api && ctx) {
6430
6489
  let ids = await uploadArtifacts(api, runId, artifacts, plan.uploadLimits, fetchImpl);
6431
6490
  if (finalResults = resolveArtifactRefs(results, ids), doctor?.logArtifactId === void 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devasign/verify",
3
- "version": "1.3.2",
3
+ "version": "1.5.0",
4
4
  "description": "Runs DevAsign's generated acceptance tests inside your CI and reports per-criterion evidence.",
5
5
  "license": "GPL-3.0-or-later",
6
6
  "type": "module",