norn-cli 1.5.2 → 1.5.4

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/dist/cli.js CHANGED
@@ -8881,11 +8881,11 @@ var require_mime_types = __commonJS({
8881
8881
  }
8882
8882
  return exts[0];
8883
8883
  }
8884
- function lookup(path6) {
8885
- if (!path6 || typeof path6 !== "string") {
8884
+ function lookup(path10) {
8885
+ if (!path10 || typeof path10 !== "string") {
8886
8886
  return false;
8887
8887
  }
8888
- var extension2 = extname2("x." + path6).toLowerCase().substr(1);
8888
+ var extension2 = extname2("x." + path10).toLowerCase().substr(1);
8889
8889
  if (!extension2) {
8890
8890
  return false;
8891
8891
  }
@@ -8978,7 +8978,7 @@ var require_iterate = __commonJS({
8978
8978
  module2.exports = iterate;
8979
8979
  function iterate(list, iterator2, state, callback) {
8980
8980
  var key = state["keyedList"] ? state["keyedList"][state.index] : state.index;
8981
- state.jobs[key] = runJob(iterator2, key, list[key], function(error, output) {
8981
+ state.jobs[key] = runJob(iterator2, key, list[key], function(error, output2) {
8982
8982
  if (!(key in state.jobs)) {
8983
8983
  return;
8984
8984
  }
@@ -8986,7 +8986,7 @@ var require_iterate = __commonJS({
8986
8986
  if (error) {
8987
8987
  abort(state);
8988
8988
  } else {
8989
- state.results[key] = output;
8989
+ state.results[key] = output2;
8990
8990
  }
8991
8991
  callback(error, state.results);
8992
8992
  });
@@ -9990,13 +9990,13 @@ var require_form_data = __commonJS({
9990
9990
  "use strict";
9991
9991
  var CombinedStream = require_combined_stream();
9992
9992
  var util3 = require("util");
9993
- var path6 = require("path");
9993
+ var path10 = require("path");
9994
9994
  var http3 = require("http");
9995
- var https2 = require("https");
9995
+ var https3 = require("https");
9996
9996
  var parseUrl = require("url").parse;
9997
- var fs7 = require("fs");
9997
+ var fs11 = require("fs");
9998
9998
  var Stream = require("stream").Stream;
9999
- var crypto2 = require("crypto");
9999
+ var crypto3 = require("crypto");
10000
10000
  var mime = require_mime_types();
10001
10001
  var asynckit = require_asynckit();
10002
10002
  var setToStringTag = require_es_set_tostringtag();
@@ -10061,7 +10061,7 @@ var require_form_data = __commonJS({
10061
10061
  if (value.end != void 0 && value.end != Infinity && value.start != void 0) {
10062
10062
  callback(null, value.end + 1 - (value.start ? value.start : 0));
10063
10063
  } else {
10064
- fs7.stat(value.path, function(err, stat) {
10064
+ fs11.stat(value.path, function(err, stat) {
10065
10065
  if (err) {
10066
10066
  callback(err);
10067
10067
  return;
@@ -10118,11 +10118,11 @@ var require_form_data = __commonJS({
10118
10118
  FormData3.prototype._getContentDisposition = function(value, options) {
10119
10119
  var filename;
10120
10120
  if (typeof options.filepath === "string") {
10121
- filename = path6.normalize(options.filepath).replace(/\\/g, "/");
10121
+ filename = path10.normalize(options.filepath).replace(/\\/g, "/");
10122
10122
  } else if (options.filename || value && (value.name || value.path)) {
10123
- filename = path6.basename(options.filename || value && (value.name || value.path));
10123
+ filename = path10.basename(options.filename || value && (value.name || value.path));
10124
10124
  } else if (value && value.readable && hasOwn(value, "httpVersion")) {
10125
- filename = path6.basename(value.client._httpMessage.path || "");
10125
+ filename = path10.basename(value.client._httpMessage.path || "");
10126
10126
  }
10127
10127
  if (filename) {
10128
10128
  return 'filename="' + filename + '"';
@@ -10202,7 +10202,7 @@ var require_form_data = __commonJS({
10202
10202
  return Buffer.concat([dataBuffer, Buffer.from(this._lastBoundary())]);
10203
10203
  };
10204
10204
  FormData3.prototype._generateBoundary = function() {
10205
- this._boundary = "--------------------------" + crypto2.randomBytes(12).toString("hex");
10205
+ this._boundary = "--------------------------" + crypto3.randomBytes(12).toString("hex");
10206
10206
  };
10207
10207
  FormData3.prototype.getLengthSync = function() {
10208
10208
  var knownLength = this._overheadLength + this._valueLength;
@@ -10261,7 +10261,7 @@ var require_form_data = __commonJS({
10261
10261
  }
10262
10262
  options.headers = this.getHeaders(params.headers);
10263
10263
  if (options.protocol === "https:") {
10264
- request = https2.request(options);
10264
+ request = https3.request(options);
10265
10265
  } else {
10266
10266
  request = http3.request(options);
10267
10267
  }
@@ -11196,7 +11196,7 @@ var require_follow_redirects = __commonJS({
11196
11196
  var url2 = require("url");
11197
11197
  var URL2 = url2.URL;
11198
11198
  var http3 = require("http");
11199
- var https2 = require("https");
11199
+ var https3 = require("https");
11200
11200
  var Writable = require("stream").Writable;
11201
11201
  var assert = require("assert");
11202
11202
  var debug = require_debug();
@@ -11547,15 +11547,15 @@ var require_follow_redirects = __commonJS({
11547
11547
  var protocol = scheme + ":";
11548
11548
  var nativeProtocol = nativeProtocols[protocol] = protocols[scheme];
11549
11549
  var wrappedProtocol = exports3[scheme] = Object.create(nativeProtocol);
11550
- function request(input, options, callback) {
11551
- if (isURL(input)) {
11552
- input = spreadUrlObject(input);
11553
- } else if (isString3(input)) {
11554
- input = spreadUrlObject(parseUrl(input));
11550
+ function request(input2, options, callback) {
11551
+ if (isURL(input2)) {
11552
+ input2 = spreadUrlObject(input2);
11553
+ } else if (isString3(input2)) {
11554
+ input2 = spreadUrlObject(parseUrl(input2));
11555
11555
  } else {
11556
11556
  callback = options;
11557
- options = validateUrl(input);
11558
- input = { protocol };
11557
+ options = validateUrl(input2);
11558
+ input2 = { protocol };
11559
11559
  }
11560
11560
  if (isFunction3(options)) {
11561
11561
  callback = options;
@@ -11564,7 +11564,7 @@ var require_follow_redirects = __commonJS({
11564
11564
  options = Object.assign({
11565
11565
  maxRedirects: exports3.maxRedirects,
11566
11566
  maxBodyLength: exports3.maxBodyLength
11567
- }, input, options);
11567
+ }, input2, options);
11568
11568
  options.nativeProtocols = nativeProtocols;
11569
11569
  if (!isString3(options.host) && !isString3(options.hostname)) {
11570
11570
  options.hostname = "::1";
@@ -11573,8 +11573,8 @@ var require_follow_redirects = __commonJS({
11573
11573
  debug("options", options);
11574
11574
  return new RedirectableRequest(options, callback);
11575
11575
  }
11576
- function get(input, options, callback) {
11577
- var wrappedRequest = wrappedProtocol.request(input, options, callback);
11576
+ function get(input2, options, callback) {
11577
+ var wrappedRequest = wrappedProtocol.request(input2, options, callback);
11578
11578
  wrappedRequest.end();
11579
11579
  return wrappedRequest;
11580
11580
  }
@@ -11587,29 +11587,29 @@ var require_follow_redirects = __commonJS({
11587
11587
  }
11588
11588
  function noop2() {
11589
11589
  }
11590
- function parseUrl(input) {
11590
+ function parseUrl(input2) {
11591
11591
  var parsed;
11592
11592
  if (useNativeURL) {
11593
- parsed = new URL2(input);
11593
+ parsed = new URL2(input2);
11594
11594
  } else {
11595
- parsed = validateUrl(url2.parse(input));
11595
+ parsed = validateUrl(url2.parse(input2));
11596
11596
  if (!isString3(parsed.protocol)) {
11597
- throw new InvalidUrlError({ input });
11597
+ throw new InvalidUrlError({ input: input2 });
11598
11598
  }
11599
11599
  }
11600
11600
  return parsed;
11601
11601
  }
11602
- function resolveUrl(relative3, base) {
11603
- return useNativeURL ? new URL2(relative3, base) : parseUrl(url2.resolve(base, relative3));
11602
+ function resolveUrl(relative4, base) {
11603
+ return useNativeURL ? new URL2(relative4, base) : parseUrl(url2.resolve(base, relative4));
11604
11604
  }
11605
- function validateUrl(input) {
11606
- if (/^\[/.test(input.hostname) && !/^\[[:0-9a-f]+\]$/i.test(input.hostname)) {
11607
- throw new InvalidUrlError({ input: input.href || input });
11605
+ function validateUrl(input2) {
11606
+ if (/^\[/.test(input2.hostname) && !/^\[[:0-9a-f]+\]$/i.test(input2.hostname)) {
11607
+ throw new InvalidUrlError({ input: input2.href || input2 });
11608
11608
  }
11609
- if (/^\[/.test(input.host) && !/^\[[:0-9a-f]+\](:\d+)?$/i.test(input.host)) {
11610
- throw new InvalidUrlError({ input: input.href || input });
11609
+ if (/^\[/.test(input2.host) && !/^\[[:0-9a-f]+\](:\d+)?$/i.test(input2.host)) {
11610
+ throw new InvalidUrlError({ input: input2.href || input2 });
11611
11611
  }
11612
- return input;
11612
+ return input2;
11613
11613
  }
11614
11614
  function spreadUrlObject(urlObject, target) {
11615
11615
  var spread3 = target || {};
@@ -11681,7 +11681,7 @@ var require_follow_redirects = __commonJS({
11681
11681
  function isURL(value) {
11682
11682
  return URL2 && value instanceof URL2;
11683
11683
  }
11684
- module2.exports = wrap({ http: http3, https: https2 });
11684
+ module2.exports = wrap({ http: http3, https: https3 });
11685
11685
  module2.exports.wrap = wrap;
11686
11686
  }
11687
11687
  });
@@ -15089,7 +15089,7 @@ var require_compile = __commonJS({
15089
15089
  const schOrFunc = root.refs[ref];
15090
15090
  if (schOrFunc)
15091
15091
  return schOrFunc;
15092
- let _sch = resolve6.call(this, root, ref);
15092
+ let _sch = resolve9.call(this, root, ref);
15093
15093
  if (_sch === void 0) {
15094
15094
  const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
15095
15095
  const { schemaId } = this.opts;
@@ -15116,7 +15116,7 @@ var require_compile = __commonJS({
15116
15116
  function sameSchemaEnv(s1, s2) {
15117
15117
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
15118
15118
  }
15119
- function resolve6(root, ref) {
15119
+ function resolve9(root, ref) {
15120
15120
  let sch;
15121
15121
  while (typeof (sch = this.refs[ref]) == "string")
15122
15122
  ref = sch;
@@ -15214,27 +15214,27 @@ var require_utils = __commonJS({
15214
15214
  "use strict";
15215
15215
  var isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu);
15216
15216
  var isIPv4 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u);
15217
- function stringArrayToHexStripped(input) {
15217
+ function stringArrayToHexStripped(input2) {
15218
15218
  let acc = "";
15219
15219
  let code = 0;
15220
15220
  let i = 0;
15221
- for (i = 0; i < input.length; i++) {
15222
- code = input[i].charCodeAt(0);
15221
+ for (i = 0; i < input2.length; i++) {
15222
+ code = input2[i].charCodeAt(0);
15223
15223
  if (code === 48) {
15224
15224
  continue;
15225
15225
  }
15226
15226
  if (!(code >= 48 && code <= 57 || code >= 65 && code <= 70 || code >= 97 && code <= 102)) {
15227
15227
  return "";
15228
15228
  }
15229
- acc += input[i];
15229
+ acc += input2[i];
15230
15230
  break;
15231
15231
  }
15232
- for (i += 1; i < input.length; i++) {
15233
- code = input[i].charCodeAt(0);
15232
+ for (i += 1; i < input2.length; i++) {
15233
+ code = input2[i].charCodeAt(0);
15234
15234
  if (!(code >= 48 && code <= 57 || code >= 65 && code <= 70 || code >= 97 && code <= 102)) {
15235
15235
  return "";
15236
15236
  }
15237
- acc += input[i];
15237
+ acc += input2[i];
15238
15238
  }
15239
15239
  return acc;
15240
15240
  }
@@ -15243,29 +15243,29 @@ var require_utils = __commonJS({
15243
15243
  buffer.length = 0;
15244
15244
  return true;
15245
15245
  }
15246
- function consumeHextets(buffer, address, output) {
15246
+ function consumeHextets(buffer, address, output2) {
15247
15247
  if (buffer.length) {
15248
15248
  const hex = stringArrayToHexStripped(buffer);
15249
15249
  if (hex !== "") {
15250
15250
  address.push(hex);
15251
15251
  } else {
15252
- output.error = true;
15252
+ output2.error = true;
15253
15253
  return false;
15254
15254
  }
15255
15255
  buffer.length = 0;
15256
15256
  }
15257
15257
  return true;
15258
15258
  }
15259
- function getIPV6(input) {
15259
+ function getIPV6(input2) {
15260
15260
  let tokenCount = 0;
15261
- const output = { error: false, address: "", zone: "" };
15261
+ const output2 = { error: false, address: "", zone: "" };
15262
15262
  const address = [];
15263
15263
  const buffer = [];
15264
15264
  let endipv6Encountered = false;
15265
15265
  let endIpv6 = false;
15266
15266
  let consume = consumeHextets;
15267
- for (let i = 0; i < input.length; i++) {
15268
- const cursor = input[i];
15267
+ for (let i = 0; i < input2.length; i++) {
15268
+ const cursor = input2[i];
15269
15269
  if (cursor === "[" || cursor === "]") {
15270
15270
  continue;
15271
15271
  }
@@ -15273,20 +15273,20 @@ var require_utils = __commonJS({
15273
15273
  if (endipv6Encountered === true) {
15274
15274
  endIpv6 = true;
15275
15275
  }
15276
- if (!consume(buffer, address, output)) {
15276
+ if (!consume(buffer, address, output2)) {
15277
15277
  break;
15278
15278
  }
15279
15279
  if (++tokenCount > 7) {
15280
- output.error = true;
15280
+ output2.error = true;
15281
15281
  break;
15282
15282
  }
15283
- if (i > 0 && input[i - 1] === ":") {
15283
+ if (i > 0 && input2[i - 1] === ":") {
15284
15284
  endipv6Encountered = true;
15285
15285
  }
15286
15286
  address.push(":");
15287
15287
  continue;
15288
15288
  } else if (cursor === "%") {
15289
- if (!consume(buffer, address, output)) {
15289
+ if (!consume(buffer, address, output2)) {
15290
15290
  break;
15291
15291
  }
15292
15292
  consume = consumeIsZone;
@@ -15297,15 +15297,15 @@ var require_utils = __commonJS({
15297
15297
  }
15298
15298
  if (buffer.length) {
15299
15299
  if (consume === consumeIsZone) {
15300
- output.zone = buffer.join("");
15300
+ output2.zone = buffer.join("");
15301
15301
  } else if (endIpv6) {
15302
15302
  address.push(buffer.join(""));
15303
15303
  } else {
15304
15304
  address.push(stringArrayToHexStripped(buffer));
15305
15305
  }
15306
15306
  }
15307
- output.address = address.join("");
15308
- return output;
15307
+ output2.address = address.join("");
15308
+ return output2;
15309
15309
  }
15310
15310
  function normalizeIPv6(host) {
15311
15311
  if (findToken(host, ":") < 2) {
@@ -15331,80 +15331,80 @@ var require_utils = __commonJS({
15331
15331
  }
15332
15332
  return ind;
15333
15333
  }
15334
- function removeDotSegments(path6) {
15335
- let input = path6;
15336
- const output = [];
15334
+ function removeDotSegments(path10) {
15335
+ let input2 = path10;
15336
+ const output2 = [];
15337
15337
  let nextSlash = -1;
15338
15338
  let len = 0;
15339
- while (len = input.length) {
15339
+ while (len = input2.length) {
15340
15340
  if (len === 1) {
15341
- if (input === ".") {
15341
+ if (input2 === ".") {
15342
15342
  break;
15343
- } else if (input === "/") {
15344
- output.push("/");
15343
+ } else if (input2 === "/") {
15344
+ output2.push("/");
15345
15345
  break;
15346
15346
  } else {
15347
- output.push(input);
15347
+ output2.push(input2);
15348
15348
  break;
15349
15349
  }
15350
15350
  } else if (len === 2) {
15351
- if (input[0] === ".") {
15352
- if (input[1] === ".") {
15351
+ if (input2[0] === ".") {
15352
+ if (input2[1] === ".") {
15353
15353
  break;
15354
- } else if (input[1] === "/") {
15355
- input = input.slice(2);
15354
+ } else if (input2[1] === "/") {
15355
+ input2 = input2.slice(2);
15356
15356
  continue;
15357
15357
  }
15358
- } else if (input[0] === "/") {
15359
- if (input[1] === "." || input[1] === "/") {
15360
- output.push("/");
15358
+ } else if (input2[0] === "/") {
15359
+ if (input2[1] === "." || input2[1] === "/") {
15360
+ output2.push("/");
15361
15361
  break;
15362
15362
  }
15363
15363
  }
15364
15364
  } else if (len === 3) {
15365
- if (input === "/..") {
15366
- if (output.length !== 0) {
15367
- output.pop();
15365
+ if (input2 === "/..") {
15366
+ if (output2.length !== 0) {
15367
+ output2.pop();
15368
15368
  }
15369
- output.push("/");
15369
+ output2.push("/");
15370
15370
  break;
15371
15371
  }
15372
15372
  }
15373
- if (input[0] === ".") {
15374
- if (input[1] === ".") {
15375
- if (input[2] === "/") {
15376
- input = input.slice(3);
15373
+ if (input2[0] === ".") {
15374
+ if (input2[1] === ".") {
15375
+ if (input2[2] === "/") {
15376
+ input2 = input2.slice(3);
15377
15377
  continue;
15378
15378
  }
15379
- } else if (input[1] === "/") {
15380
- input = input.slice(2);
15379
+ } else if (input2[1] === "/") {
15380
+ input2 = input2.slice(2);
15381
15381
  continue;
15382
15382
  }
15383
- } else if (input[0] === "/") {
15384
- if (input[1] === ".") {
15385
- if (input[2] === "/") {
15386
- input = input.slice(2);
15383
+ } else if (input2[0] === "/") {
15384
+ if (input2[1] === ".") {
15385
+ if (input2[2] === "/") {
15386
+ input2 = input2.slice(2);
15387
15387
  continue;
15388
- } else if (input[2] === ".") {
15389
- if (input[3] === "/") {
15390
- input = input.slice(3);
15391
- if (output.length !== 0) {
15392
- output.pop();
15388
+ } else if (input2[2] === ".") {
15389
+ if (input2[3] === "/") {
15390
+ input2 = input2.slice(3);
15391
+ if (output2.length !== 0) {
15392
+ output2.pop();
15393
15393
  }
15394
15394
  continue;
15395
15395
  }
15396
15396
  }
15397
15397
  }
15398
15398
  }
15399
- if ((nextSlash = input.indexOf("/", 1)) === -1) {
15400
- output.push(input);
15399
+ if ((nextSlash = input2.indexOf("/", 1)) === -1) {
15400
+ output2.push(input2);
15401
15401
  break;
15402
15402
  } else {
15403
- output.push(input.slice(0, nextSlash));
15404
- input = input.slice(nextSlash);
15403
+ output2.push(input2.slice(0, nextSlash));
15404
+ input2 = input2.slice(nextSlash);
15405
15405
  }
15406
15406
  }
15407
- return output.join("");
15407
+ return output2.join("");
15408
15408
  }
15409
15409
  function normalizeComponentEncoding(component, esc) {
15410
15410
  const func = esc !== true ? escape : unescape;
@@ -15531,8 +15531,8 @@ var require_schemes = __commonJS({
15531
15531
  wsComponent.secure = void 0;
15532
15532
  }
15533
15533
  if (wsComponent.resourceName) {
15534
- const [path6, query] = wsComponent.resourceName.split("?");
15535
- wsComponent.path = path6 && path6 !== "/" ? path6 : void 0;
15534
+ const [path10, query] = wsComponent.resourceName.split("?");
15535
+ wsComponent.path = path10 && path10 !== "/" ? path10 : void 0;
15536
15536
  wsComponent.query = query;
15537
15537
  wsComponent.resourceName = void 0;
15538
15538
  }
@@ -15600,7 +15600,7 @@ var require_schemes = __commonJS({
15600
15600
  serialize: httpSerialize
15601
15601
  }
15602
15602
  );
15603
- var https2 = (
15603
+ var https3 = (
15604
15604
  /** @type {SchemeHandler} */
15605
15605
  {
15606
15606
  scheme: "https",
@@ -15649,7 +15649,7 @@ var require_schemes = __commonJS({
15649
15649
  /** @type {Record<SchemeName, SchemeHandler>} */
15650
15650
  {
15651
15651
  http: http3,
15652
- https: https2,
15652
+ https: https3,
15653
15653
  ws,
15654
15654
  wss,
15655
15655
  urn,
@@ -15691,55 +15691,55 @@ var require_fast_uri = __commonJS({
15691
15691
  }
15692
15692
  return uri;
15693
15693
  }
15694
- function resolve6(baseURI, relativeURI, options) {
15694
+ function resolve9(baseURI, relativeURI, options) {
15695
15695
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
15696
15696
  const resolved = resolveComponent(parse2(baseURI, schemelessOptions), parse2(relativeURI, schemelessOptions), schemelessOptions, true);
15697
15697
  schemelessOptions.skipEscape = true;
15698
15698
  return serialize(resolved, schemelessOptions);
15699
15699
  }
15700
- function resolveComponent(base, relative3, options, skipNormalization) {
15700
+ function resolveComponent(base, relative4, options, skipNormalization) {
15701
15701
  const target = {};
15702
15702
  if (!skipNormalization) {
15703
15703
  base = parse2(serialize(base, options), options);
15704
- relative3 = parse2(serialize(relative3, options), options);
15704
+ relative4 = parse2(serialize(relative4, options), options);
15705
15705
  }
15706
15706
  options = options || {};
15707
- if (!options.tolerant && relative3.scheme) {
15708
- target.scheme = relative3.scheme;
15709
- target.userinfo = relative3.userinfo;
15710
- target.host = relative3.host;
15711
- target.port = relative3.port;
15712
- target.path = removeDotSegments(relative3.path || "");
15713
- target.query = relative3.query;
15707
+ if (!options.tolerant && relative4.scheme) {
15708
+ target.scheme = relative4.scheme;
15709
+ target.userinfo = relative4.userinfo;
15710
+ target.host = relative4.host;
15711
+ target.port = relative4.port;
15712
+ target.path = removeDotSegments(relative4.path || "");
15713
+ target.query = relative4.query;
15714
15714
  } else {
15715
- if (relative3.userinfo !== void 0 || relative3.host !== void 0 || relative3.port !== void 0) {
15716
- target.userinfo = relative3.userinfo;
15717
- target.host = relative3.host;
15718
- target.port = relative3.port;
15719
- target.path = removeDotSegments(relative3.path || "");
15720
- target.query = relative3.query;
15715
+ if (relative4.userinfo !== void 0 || relative4.host !== void 0 || relative4.port !== void 0) {
15716
+ target.userinfo = relative4.userinfo;
15717
+ target.host = relative4.host;
15718
+ target.port = relative4.port;
15719
+ target.path = removeDotSegments(relative4.path || "");
15720
+ target.query = relative4.query;
15721
15721
  } else {
15722
- if (!relative3.path) {
15722
+ if (!relative4.path) {
15723
15723
  target.path = base.path;
15724
- if (relative3.query !== void 0) {
15725
- target.query = relative3.query;
15724
+ if (relative4.query !== void 0) {
15725
+ target.query = relative4.query;
15726
15726
  } else {
15727
15727
  target.query = base.query;
15728
15728
  }
15729
15729
  } else {
15730
- if (relative3.path[0] === "/") {
15731
- target.path = removeDotSegments(relative3.path);
15730
+ if (relative4.path[0] === "/") {
15731
+ target.path = removeDotSegments(relative4.path);
15732
15732
  } else {
15733
15733
  if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
15734
- target.path = "/" + relative3.path;
15734
+ target.path = "/" + relative4.path;
15735
15735
  } else if (!base.path) {
15736
- target.path = relative3.path;
15736
+ target.path = relative4.path;
15737
15737
  } else {
15738
- target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative3.path;
15738
+ target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative4.path;
15739
15739
  }
15740
15740
  target.path = removeDotSegments(target.path);
15741
15741
  }
15742
- target.query = relative3.query;
15742
+ target.query = relative4.query;
15743
15743
  }
15744
15744
  target.userinfo = base.userinfo;
15745
15745
  target.host = base.host;
@@ -15747,7 +15747,7 @@ var require_fast_uri = __commonJS({
15747
15747
  }
15748
15748
  target.scheme = base.scheme;
15749
15749
  }
15750
- target.fragment = relative3.fragment;
15750
+ target.fragment = relative4.fragment;
15751
15751
  return target;
15752
15752
  }
15753
15753
  function equal(uriA, uriB, options) {
@@ -15918,7 +15918,7 @@ var require_fast_uri = __commonJS({
15918
15918
  var fastUri = {
15919
15919
  SCHEMES,
15920
15920
  normalize,
15921
- resolve: resolve6,
15921
+ resolve: resolve9,
15922
15922
  resolveComponent,
15923
15923
  equal,
15924
15924
  serialize,
@@ -18738,8 +18738,8 @@ function validateAgainstSchemaDetailed(value, schemaPath, basePath, workspaceRoo
18738
18738
  if (!valid && validate2.errors) {
18739
18739
  const errors = validate2.errors.map((err) => convertAjvError(err, value));
18740
18740
  const errorStrings = validate2.errors.map((err) => {
18741
- const path6 = err.instancePath || "(root)";
18742
- return `${path6}: ${err.message}`;
18741
+ const path10 = err.instancePath || "(root)";
18742
+ return `${path10}: ${err.message}`;
18743
18743
  });
18744
18744
  return {
18745
18745
  valid: false,
@@ -18868,7 +18868,7 @@ function resolveValue(expr, responses, variables, getValueByPath2, responseIndex
18868
18868
  if (refMatch) {
18869
18869
  const responseIdx = parseInt(refMatch[1], 10);
18870
18870
  const responseIndex = responseIdx - 1;
18871
- const path6 = refMatch[2];
18871
+ const path10 = refMatch[2];
18872
18872
  if (responseIndex < 0 || responseIndex >= responses.length) {
18873
18873
  return {
18874
18874
  value: void 0,
@@ -18876,12 +18876,12 @@ function resolveValue(expr, responses, variables, getValueByPath2, responseIndex
18876
18876
  };
18877
18877
  }
18878
18878
  const response = responses[responseIndex];
18879
- const value = getValueByPath2(response, path6);
18879
+ const value = getValueByPath2(response, path10);
18880
18880
  return {
18881
18881
  value,
18882
18882
  responseIndex: responseIdx,
18883
18883
  response,
18884
- jsonPath: path6,
18884
+ jsonPath: path10,
18885
18885
  variableName: responseIndexToVariable?.get(responseIdx)
18886
18886
  };
18887
18887
  }
@@ -18898,22 +18898,22 @@ function resolveValue(expr, responses, variables, getValueByPath2, responseIndex
18898
18898
  if (varName in variables) {
18899
18899
  const varValue = variables[varName];
18900
18900
  if (typeof varValue === "object" && varValue !== null) {
18901
- const path6 = pathPart.replace(/^\./, "");
18902
- const value = getNestedValue2(varValue, path6);
18901
+ const path10 = pathPart.replace(/^\./, "");
18902
+ const value = getNestedValue2(varValue, path10);
18903
18903
  const isHttpResponse = "status" in varValue && "body" in varValue;
18904
18904
  return {
18905
18905
  value,
18906
18906
  variableName: varName,
18907
- jsonPath: path6,
18907
+ jsonPath: path10,
18908
18908
  response: isHttpResponse ? varValue : void 0
18909
18909
  };
18910
18910
  }
18911
18911
  if (typeof varValue === "string") {
18912
18912
  try {
18913
18913
  const parsed = JSON.parse(varValue);
18914
- const path6 = pathPart.replace(/^\./, "");
18915
- const value = getNestedValue2(parsed, path6);
18916
- return { value, variableName: varName, jsonPath: path6 };
18914
+ const path10 = pathPart.replace(/^\./, "");
18915
+ const value = getNestedValue2(parsed, path10);
18916
+ return { value, variableName: varName, jsonPath: path10 };
18917
18917
  } catch {
18918
18918
  return { value: void 0, error: `Cannot access path on non-object variable: ${varName}` };
18919
18919
  }
@@ -18969,11 +18969,11 @@ function resolveValue(expr, responses, variables, getValueByPath2, responseIndex
18969
18969
  }
18970
18970
  return { value: void 0, error: `Cannot resolve expression: ${trimmed}` };
18971
18971
  }
18972
- function getNestedValue2(obj, path6) {
18973
- if (!path6 || obj === null || obj === void 0) {
18972
+ function getNestedValue2(obj, path10) {
18973
+ if (!path10 || obj === null || obj === void 0) {
18974
18974
  return obj;
18975
18975
  }
18976
- const parts = path6.replace(/\[(\d+)\]/g, ".$1").split(".").filter((p) => p !== "");
18976
+ const parts = path10.replace(/\[(\d+)\]/g, ".$1").split(".").filter((p) => p !== "");
18977
18977
  let current = obj;
18978
18978
  for (const part of parts) {
18979
18979
  if (current === null || current === void 0) {
@@ -19769,16 +19769,16 @@ var init_source = __esm({
19769
19769
  });
19770
19770
 
19771
19771
  // src/cli.ts
19772
- var fs6 = __toESM(require("fs"));
19772
+ var fs10 = __toESM(require("fs"));
19773
19773
  var fsPromises = __toESM(require("fs/promises"));
19774
- var path5 = __toESM(require("path"));
19774
+ var path9 = __toESM(require("path"));
19775
19775
 
19776
19776
  // src/nornapiParser.ts
19777
- function extractPathParameters(path6) {
19777
+ function extractPathParameters(path10) {
19778
19778
  const params = [];
19779
19779
  const regex = /(?<!\{)\{([a-zA-Z_][a-zA-Z0-9_]*)\}(?!\})/g;
19780
19780
  let match;
19781
- while ((match = regex.exec(path6)) !== null) {
19781
+ while ((match = regex.exec(path10)) !== null) {
19782
19782
  params.push(match[1]);
19783
19783
  }
19784
19784
  return params;
@@ -19828,12 +19828,12 @@ function parseNornApiFile(content) {
19828
19828
  if (inEndpointsBlock) {
19829
19829
  const endpointMatch = trimmed.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\s*:\s*(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\s+(.+)$/i);
19830
19830
  if (endpointMatch) {
19831
- const path6 = endpointMatch[3].trim();
19831
+ const path10 = endpointMatch[3].trim();
19832
19832
  endpoints.push({
19833
19833
  name: endpointMatch[1],
19834
19834
  method: endpointMatch[2].toUpperCase(),
19835
- path: path6,
19836
- parameters: extractPathParameters(path6)
19835
+ path: path10,
19836
+ parameters: extractPathParameters(path10)
19837
19837
  });
19838
19838
  }
19839
19839
  continue;
@@ -20123,11 +20123,11 @@ function extractFileLevelVariables(text) {
20123
20123
  }
20124
20124
  return variables;
20125
20125
  }
20126
- function getNestedValue(obj, path6) {
20127
- if (!path6 || obj === null || obj === void 0) {
20126
+ function getNestedValue(obj, path10) {
20127
+ if (!path10 || obj === null || obj === void 0) {
20128
20128
  return obj;
20129
20129
  }
20130
- const parts = path6.replace(/\[(\d+)\]/g, ".$1").split(".").filter((p) => p !== "");
20130
+ const parts = path10.replace(/\[(\d+)\]/g, ".$1").split(".").filter((p) => p !== "");
20131
20131
  let current = obj;
20132
20132
  for (const part of parts) {
20133
20133
  if (current === null || current === void 0) {
@@ -20159,8 +20159,8 @@ function substituteVariables(text, variables) {
20159
20159
  const value = variables[varName];
20160
20160
  if (typeof value === "object" && value !== null) {
20161
20161
  if (pathPart) {
20162
- const path6 = pathPart.replace(/^\./, "");
20163
- const nestedValue = getNestedValue(value, path6);
20162
+ const path10 = pathPart.replace(/^\./, "");
20163
+ const nestedValue = getNestedValue(value, path10);
20164
20164
  return valueToString(nestedValue);
20165
20165
  }
20166
20166
  return valueToString(value);
@@ -20168,8 +20168,8 @@ function substituteVariables(text, variables) {
20168
20168
  if (pathPart && typeof value === "string") {
20169
20169
  try {
20170
20170
  const parsed = JSON.parse(value);
20171
- const path6 = pathPart.replace(/^\./, "");
20172
- const nestedValue = getNestedValue(parsed, path6);
20171
+ const path10 = pathPart.replace(/^\./, "");
20172
+ const nestedValue = getNestedValue(parsed, path10);
20173
20173
  return valueToString(nestedValue);
20174
20174
  } catch {
20175
20175
  return value;
@@ -20285,8 +20285,8 @@ async function resolveImports(text, baseDir, readFile2, alreadyImported = /* @__
20285
20285
  const namedRequestSources = /* @__PURE__ */ new Map();
20286
20286
  const sequenceSources = /* @__PURE__ */ new Map();
20287
20287
  for (const imp of imports) {
20288
- const path6 = await import("path");
20289
- const absolutePath = path6.resolve(baseDir, imp.path);
20288
+ const path10 = await import("path");
20289
+ const absolutePath = path10.resolve(baseDir, imp.path);
20290
20290
  if (importStack.has(absolutePath)) {
20291
20291
  errors.push({
20292
20292
  path: imp.path,
@@ -20333,7 +20333,7 @@ async function resolveImports(text, baseDir, readFile2, alreadyImported = /* @__
20333
20333
  }
20334
20334
  continue;
20335
20335
  }
20336
- const importDir = path6.dirname(absolutePath);
20336
+ const importDir = path10.dirname(absolutePath);
20337
20337
  const nestedResult = await resolveImports(content, importDir, readFile2, alreadyImported, importStack);
20338
20338
  errors.push(...nestedResult.errors);
20339
20339
  resolvedPaths.push(...nestedResult.resolvedPaths);
@@ -20932,9 +20932,9 @@ function isVisitable(thing) {
20932
20932
  function removeBrackets(key) {
20933
20933
  return utils_default.endsWith(key, "[]") ? key.slice(0, -2) : key;
20934
20934
  }
20935
- function renderKey(path6, key, dots) {
20936
- if (!path6) return key;
20937
- return path6.concat(key).map(function each(token, i) {
20935
+ function renderKey(path10, key, dots) {
20936
+ if (!path10) return key;
20937
+ return path10.concat(key).map(function each(token, i) {
20938
20938
  token = removeBrackets(token);
20939
20939
  return !dots && i ? "[" + token + "]" : token;
20940
20940
  }).join(dots ? "." : "");
@@ -20982,9 +20982,9 @@ function toFormData(obj, formData, options) {
20982
20982
  }
20983
20983
  return value;
20984
20984
  }
20985
- function defaultVisitor(value, key, path6) {
20985
+ function defaultVisitor(value, key, path10) {
20986
20986
  let arr = value;
20987
- if (value && !path6 && typeof value === "object") {
20987
+ if (value && !path10 && typeof value === "object") {
20988
20988
  if (utils_default.endsWith(key, "{}")) {
20989
20989
  key = metaTokens ? key : key.slice(0, -2);
20990
20990
  value = JSON.stringify(value);
@@ -21003,7 +21003,7 @@ function toFormData(obj, formData, options) {
21003
21003
  if (isVisitable(value)) {
21004
21004
  return true;
21005
21005
  }
21006
- formData.append(renderKey(path6, key, dots), convertValue(value));
21006
+ formData.append(renderKey(path10, key, dots), convertValue(value));
21007
21007
  return false;
21008
21008
  }
21009
21009
  const stack = [];
@@ -21012,10 +21012,10 @@ function toFormData(obj, formData, options) {
21012
21012
  convertValue,
21013
21013
  isVisitable
21014
21014
  });
21015
- function build(value, path6) {
21015
+ function build(value, path10) {
21016
21016
  if (utils_default.isUndefined(value)) return;
21017
21017
  if (stack.indexOf(value) !== -1) {
21018
- throw Error("Circular reference detected in " + path6.join("."));
21018
+ throw Error("Circular reference detected in " + path10.join("."));
21019
21019
  }
21020
21020
  stack.push(value);
21021
21021
  utils_default.forEach(value, function each(el, key) {
@@ -21023,11 +21023,11 @@ function toFormData(obj, formData, options) {
21023
21023
  formData,
21024
21024
  el,
21025
21025
  utils_default.isString(key) ? key.trim() : key,
21026
- path6,
21026
+ path10,
21027
21027
  exposedHelpers
21028
21028
  );
21029
21029
  if (result === true) {
21030
- build(el, path6 ? path6.concat(key) : [key]);
21030
+ build(el, path10 ? path10.concat(key) : [key]);
21031
21031
  }
21032
21032
  });
21033
21033
  stack.pop();
@@ -21239,7 +21239,7 @@ var platform_default = {
21239
21239
  // node_modules/axios/lib/helpers/toURLEncodedForm.js
21240
21240
  function toURLEncodedForm(data, options) {
21241
21241
  return toFormData_default(data, new platform_default.classes.URLSearchParams(), {
21242
- visitor: function(value, key, path6, helpers) {
21242
+ visitor: function(value, key, path10, helpers) {
21243
21243
  if (platform_default.isNode && utils_default.isBuffer(value)) {
21244
21244
  this.append(key, value.toString("base64"));
21245
21245
  return false;
@@ -21269,11 +21269,11 @@ function arrayToObject(arr) {
21269
21269
  return obj;
21270
21270
  }
21271
21271
  function formDataToJSON(formData) {
21272
- function buildPath(path6, value, target, index) {
21273
- let name = path6[index++];
21272
+ function buildPath(path10, value, target, index) {
21273
+ let name = path10[index++];
21274
21274
  if (name === "__proto__") return true;
21275
21275
  const isNumericKey = Number.isFinite(+name);
21276
- const isLast = index >= path6.length;
21276
+ const isLast = index >= path10.length;
21277
21277
  name = !name && utils_default.isArray(target) ? target.length : name;
21278
21278
  if (isLast) {
21279
21279
  if (utils_default.hasOwnProp(target, name)) {
@@ -21286,7 +21286,7 @@ function formDataToJSON(formData) {
21286
21286
  if (!target[name] || !utils_default.isObject(target[name])) {
21287
21287
  target[name] = [];
21288
21288
  }
21289
- const result = buildPath(path6, value, target[name], index);
21289
+ const result = buildPath(path10, value, target[name], index);
21290
21290
  if (result && utils_default.isArray(target[name])) {
21291
21291
  target[name] = arrayToObject(target[name]);
21292
21292
  }
@@ -21715,10 +21715,10 @@ utils_default.inherits(CanceledError, AxiosError_default, {
21715
21715
  var CanceledError_default = CanceledError;
21716
21716
 
21717
21717
  // node_modules/axios/lib/core/settle.js
21718
- function settle(resolve6, reject, response) {
21718
+ function settle(resolve9, reject, response) {
21719
21719
  const validateStatus2 = response.config.validateStatus;
21720
21720
  if (!response.status || !validateStatus2 || validateStatus2(response.status)) {
21721
- resolve6(response);
21721
+ resolve9(response);
21722
21722
  } else {
21723
21723
  reject(new AxiosError_default(
21724
21724
  "Request failed with status code " + response.status,
@@ -22341,7 +22341,7 @@ function setProxy(options, configProxy, location) {
22341
22341
  }
22342
22342
  var isHttpAdapterSupported = typeof process !== "undefined" && utils_default.kindOf(process) === "process";
22343
22343
  var wrapAsync = (asyncExecutor) => {
22344
- return new Promise((resolve6, reject) => {
22344
+ return new Promise((resolve9, reject) => {
22345
22345
  let onDone;
22346
22346
  let isDone;
22347
22347
  const done = (value, isRejected) => {
@@ -22351,7 +22351,7 @@ var wrapAsync = (asyncExecutor) => {
22351
22351
  };
22352
22352
  const _resolve = (value) => {
22353
22353
  done(value);
22354
- resolve6(value);
22354
+ resolve9(value);
22355
22355
  };
22356
22356
  const _reject = (reason) => {
22357
22357
  done(reason, true);
@@ -22403,7 +22403,7 @@ var http2Transport = {
22403
22403
  }
22404
22404
  };
22405
22405
  var http_default = isHttpAdapterSupported && function httpAdapter(config) {
22406
- return wrapAsync(async function dispatchHttpRequest(resolve6, reject, onDone) {
22406
+ return wrapAsync(async function dispatchHttpRequest(resolve9, reject, onDone) {
22407
22407
  let { data, lookup, family, httpVersion = 1, http2Options } = config;
22408
22408
  const { responseType, responseEncoding } = config;
22409
22409
  const method = config.method.toUpperCase();
@@ -22488,7 +22488,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config) {
22488
22488
  }
22489
22489
  let convertedData;
22490
22490
  if (method !== "GET") {
22491
- return settle(resolve6, reject, {
22491
+ return settle(resolve9, reject, {
22492
22492
  status: 405,
22493
22493
  statusText: "method not allowed",
22494
22494
  headers: {},
@@ -22510,7 +22510,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config) {
22510
22510
  } else if (responseType === "stream") {
22511
22511
  convertedData = import_stream4.default.Readable.from(convertedData);
22512
22512
  }
22513
- return settle(resolve6, reject, {
22513
+ return settle(resolve9, reject, {
22514
22514
  data: convertedData,
22515
22515
  status: 200,
22516
22516
  statusText: "OK",
@@ -22608,9 +22608,9 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config) {
22608
22608
  auth = urlUsername + ":" + urlPassword;
22609
22609
  }
22610
22610
  auth && headers.delete("authorization");
22611
- let path6;
22611
+ let path10;
22612
22612
  try {
22613
- path6 = buildURL(
22613
+ path10 = buildURL(
22614
22614
  parsed.pathname + parsed.search,
22615
22615
  config.params,
22616
22616
  config.paramsSerializer
@@ -22628,7 +22628,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config) {
22628
22628
  false
22629
22629
  );
22630
22630
  const options = {
22631
- path: path6,
22631
+ path: path10,
22632
22632
  method,
22633
22633
  headers: headers.toJSON(),
22634
22634
  agents: { http: config.httpAgent, https: config.httpsAgent },
@@ -22729,7 +22729,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config) {
22729
22729
  };
22730
22730
  if (responseType === "stream") {
22731
22731
  response.data = responseStream;
22732
- settle(resolve6, reject, response);
22732
+ settle(resolve9, reject, response);
22733
22733
  } else {
22734
22734
  const responseBuffer = [];
22735
22735
  let totalResponseBytes = 0;
@@ -22777,7 +22777,7 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config) {
22777
22777
  } catch (err) {
22778
22778
  return reject(AxiosError_default.from(err, null, config, response.request, response));
22779
22779
  }
22780
- settle(resolve6, reject, response);
22780
+ settle(resolve9, reject, response);
22781
22781
  });
22782
22782
  }
22783
22783
  abortEmitter.once("abort", (err) => {
@@ -22864,14 +22864,14 @@ var isURLSameOrigin_default = platform_default.hasStandardBrowserEnv ? /* @__PUR
22864
22864
  var cookies_default = platform_default.hasStandardBrowserEnv ? (
22865
22865
  // Standard browser envs support document.cookie
22866
22866
  {
22867
- write(name, value, expires, path6, domain, secure, sameSite) {
22867
+ write(name, value, expires, path10, domain, secure, sameSite) {
22868
22868
  if (typeof document === "undefined") return;
22869
22869
  const cookie = [`${name}=${encodeURIComponent(value)}`];
22870
22870
  if (utils_default.isNumber(expires)) {
22871
22871
  cookie.push(`expires=${new Date(expires).toUTCString()}`);
22872
22872
  }
22873
- if (utils_default.isString(path6)) {
22874
- cookie.push(`path=${path6}`);
22873
+ if (utils_default.isString(path10)) {
22874
+ cookie.push(`path=${path10}`);
22875
22875
  }
22876
22876
  if (utils_default.isString(domain)) {
22877
22877
  cookie.push(`domain=${domain}`);
@@ -23026,7 +23026,7 @@ var resolveConfig_default = (config) => {
23026
23026
  // node_modules/axios/lib/adapters/xhr.js
23027
23027
  var isXHRAdapterSupported = typeof XMLHttpRequest !== "undefined";
23028
23028
  var xhr_default = isXHRAdapterSupported && function(config) {
23029
- return new Promise(function dispatchXhrRequest(resolve6, reject) {
23029
+ return new Promise(function dispatchXhrRequest(resolve9, reject) {
23030
23030
  const _config = resolveConfig_default(config);
23031
23031
  let requestData = _config.data;
23032
23032
  const requestHeaders = AxiosHeaders_default.from(_config.headers).normalize();
@@ -23060,7 +23060,7 @@ var xhr_default = isXHRAdapterSupported && function(config) {
23060
23060
  request
23061
23061
  };
23062
23062
  settle(function _resolve(value) {
23063
- resolve6(value);
23063
+ resolve9(value);
23064
23064
  done();
23065
23065
  }, function _reject(err) {
23066
23066
  reject(err);
@@ -23431,8 +23431,8 @@ var factory = (env3) => {
23431
23431
  responseType = responseType || "text";
23432
23432
  let responseData = await resolvers[utils_default.findKey(resolvers, responseType) || "text"](response, config);
23433
23433
  !isStreamResponse && unsubscribe && unsubscribe();
23434
- return await new Promise((resolve6, reject) => {
23435
- settle(resolve6, reject, {
23434
+ return await new Promise((resolve9, reject) => {
23435
+ settle(resolve9, reject, {
23436
23436
  data: responseData,
23437
23437
  headers: AxiosHeaders_default.from(response.headers),
23438
23438
  status: response.status,
@@ -23828,8 +23828,8 @@ var CancelToken = class _CancelToken {
23828
23828
  throw new TypeError("executor must be a function.");
23829
23829
  }
23830
23830
  let resolvePromise;
23831
- this.promise = new Promise(function promiseExecutor(resolve6) {
23832
- resolvePromise = resolve6;
23831
+ this.promise = new Promise(function promiseExecutor(resolve9) {
23832
+ resolvePromise = resolve9;
23833
23833
  });
23834
23834
  const token = this;
23835
23835
  this.promise.then((cancel) => {
@@ -23842,9 +23842,9 @@ var CancelToken = class _CancelToken {
23842
23842
  });
23843
23843
  this.promise.then = (onfulfilled) => {
23844
23844
  let _resolve;
23845
- const promise = new Promise((resolve6) => {
23846
- token.subscribe(resolve6);
23847
- _resolve = resolve6;
23845
+ const promise = new Promise((resolve9) => {
23846
+ token.subscribe(resolve9);
23847
+ _resolve = resolve9;
23848
23848
  }).then(onfulfilled);
23849
23849
  promise.cancel = function reject() {
23850
23850
  token.unsubscribe(_resolve);
@@ -24061,6 +24061,9 @@ var {
24061
24061
  mergeConfig: mergeConfig2
24062
24062
  } = axios_default;
24063
24063
 
24064
+ // src/httpClient.ts
24065
+ var https2 = __toESM(require("https"));
24066
+
24064
24067
  // node_modules/tough-cookie/dist/index.js
24065
24068
  var import_tldts = __toESM(require_cjs(), 1);
24066
24069
  function pathMatch(reqPath, cookiePath) {
@@ -24215,10 +24218,10 @@ var safeToStringImpl = (val, seenArrays = /* @__PURE__ */ new WeakSet()) => {
24215
24218
  var safeToString = (val) => safeToStringImpl(val);
24216
24219
  function createPromiseCallback(cb) {
24217
24220
  let callback;
24218
- let resolve6;
24221
+ let resolve9;
24219
24222
  let reject;
24220
24223
  const promise = new Promise((_resolve, _reject) => {
24221
- resolve6 = _resolve;
24224
+ resolve9 = _resolve;
24222
24225
  reject = _reject;
24223
24226
  });
24224
24227
  if (typeof cb === "function") {
@@ -24234,7 +24237,7 @@ function createPromiseCallback(cb) {
24234
24237
  callback = (err, result) => {
24235
24238
  try {
24236
24239
  if (err) reject(err);
24237
- else resolve6(result);
24240
+ else resolve9(result);
24238
24241
  } catch (e) {
24239
24242
  reject(e instanceof Error ? e : new Error());
24240
24243
  }
@@ -24268,18 +24271,18 @@ var MemoryCookieStore = class extends Store {
24268
24271
  /**
24269
24272
  * @internal No doc because this is an overload that supports the implementation
24270
24273
  */
24271
- findCookie(domain, path6, key, callback) {
24274
+ findCookie(domain, path10, key, callback) {
24272
24275
  const promiseCallback = createPromiseCallback(callback);
24273
- if (domain == null || path6 == null || key == null) {
24276
+ if (domain == null || path10 == null || key == null) {
24274
24277
  return promiseCallback.resolve(void 0);
24275
24278
  }
24276
- const result = this.idx[domain]?.[path6]?.[key];
24279
+ const result = this.idx[domain]?.[path10]?.[key];
24277
24280
  return promiseCallback.resolve(result);
24278
24281
  }
24279
24282
  /**
24280
24283
  * @internal No doc because this is an overload that supports the implementation
24281
24284
  */
24282
- findCookies(domain, path6, allowSpecialUseDomain = false, callback) {
24285
+ findCookies(domain, path10, allowSpecialUseDomain = false, callback) {
24283
24286
  if (typeof allowSpecialUseDomain === "function") {
24284
24287
  callback = allowSpecialUseDomain;
24285
24288
  allowSpecialUseDomain = true;
@@ -24290,7 +24293,7 @@ var MemoryCookieStore = class extends Store {
24290
24293
  return promiseCallback.resolve([]);
24291
24294
  }
24292
24295
  let pathMatcher;
24293
- if (!path6) {
24296
+ if (!path10) {
24294
24297
  pathMatcher = function matchAll2(domainIndex) {
24295
24298
  for (const curPath in domainIndex) {
24296
24299
  const pathIndex = domainIndex[curPath];
@@ -24305,7 +24308,7 @@ var MemoryCookieStore = class extends Store {
24305
24308
  } else {
24306
24309
  pathMatcher = function matchRFC(domainIndex) {
24307
24310
  for (const cookiePath in domainIndex) {
24308
- if (pathMatch(path6, cookiePath)) {
24311
+ if (pathMatch(path10, cookiePath)) {
24309
24312
  const pathIndex = domainIndex[cookiePath];
24310
24313
  for (const key in pathIndex) {
24311
24314
  const value = pathIndex[key];
@@ -24333,14 +24336,14 @@ var MemoryCookieStore = class extends Store {
24333
24336
  */
24334
24337
  putCookie(cookie, callback) {
24335
24338
  const promiseCallback = createPromiseCallback(callback);
24336
- const { domain, path: path6, key } = cookie;
24337
- if (domain == null || path6 == null || key == null) {
24339
+ const { domain, path: path10, key } = cookie;
24340
+ if (domain == null || path10 == null || key == null) {
24338
24341
  return promiseCallback.resolve(void 0);
24339
24342
  }
24340
24343
  const domainEntry = this.idx[domain] ?? /* @__PURE__ */ Object.create(null);
24341
24344
  this.idx[domain] = domainEntry;
24342
- const pathEntry = domainEntry[path6] ?? /* @__PURE__ */ Object.create(null);
24343
- domainEntry[path6] = pathEntry;
24345
+ const pathEntry = domainEntry[path10] ?? /* @__PURE__ */ Object.create(null);
24346
+ domainEntry[path10] = pathEntry;
24344
24347
  pathEntry[key] = cookie;
24345
24348
  return promiseCallback.resolve(void 0);
24346
24349
  }
@@ -24354,20 +24357,20 @@ var MemoryCookieStore = class extends Store {
24354
24357
  /**
24355
24358
  * @internal No doc because this is an overload that supports the implementation
24356
24359
  */
24357
- removeCookie(domain, path6, key, callback) {
24360
+ removeCookie(domain, path10, key, callback) {
24358
24361
  const promiseCallback = createPromiseCallback(callback);
24359
- delete this.idx[domain]?.[path6]?.[key];
24362
+ delete this.idx[domain]?.[path10]?.[key];
24360
24363
  return promiseCallback.resolve(void 0);
24361
24364
  }
24362
24365
  /**
24363
24366
  * @internal No doc because this is an overload that supports the implementation
24364
24367
  */
24365
- removeCookies(domain, path6, callback) {
24368
+ removeCookies(domain, path10, callback) {
24366
24369
  const promiseCallback = createPromiseCallback(callback);
24367
24370
  const domainEntry = this.idx[domain];
24368
24371
  if (domainEntry) {
24369
- if (path6) {
24370
- delete domainEntry[path6];
24372
+ if (path10) {
24373
+ delete domainEntry[path10];
24371
24374
  } else {
24372
24375
  delete this.idx[domain];
24373
24376
  }
@@ -24393,8 +24396,8 @@ var MemoryCookieStore = class extends Store {
24393
24396
  domains.forEach((domain) => {
24394
24397
  const domainEntry = idx[domain] ?? {};
24395
24398
  const paths = Object.keys(domainEntry);
24396
- paths.forEach((path6) => {
24397
- const pathEntry = domainEntry[path6] ?? {};
24399
+ paths.forEach((path10) => {
24400
+ const pathEntry = domainEntry[path10] ?? {};
24398
24401
  const keys = Object.keys(pathEntry);
24399
24402
  keys.forEach((key) => {
24400
24403
  const keyEntry = pathEntry[key];
@@ -25278,18 +25281,18 @@ function cookieCompare(a, b) {
25278
25281
  cmp = (a.creationIndex || 0) - (b.creationIndex || 0);
25279
25282
  return cmp;
25280
25283
  }
25281
- function defaultPath(path6) {
25282
- if (!path6 || path6.slice(0, 1) !== "/") {
25284
+ function defaultPath(path10) {
25285
+ if (!path10 || path10.slice(0, 1) !== "/") {
25283
25286
  return "/";
25284
25287
  }
25285
- if (path6 === "/") {
25286
- return path6;
25288
+ if (path10 === "/") {
25289
+ return path10;
25287
25290
  }
25288
- const rightSlash = path6.lastIndexOf("/");
25291
+ const rightSlash = path10.lastIndexOf("/");
25289
25292
  if (rightSlash === 0) {
25290
25293
  return "/";
25291
25294
  }
25292
- return path6.slice(0, rightSlash);
25295
+ return path10.slice(0, rightSlash);
25293
25296
  }
25294
25297
  var IP_REGEX_LOWERCASE = /(?:^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$)|(?:^(?:(?:[a-f\d]{1,4}:){7}(?:[a-f\d]{1,4}|:)|(?:[a-f\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|:[a-f\d]{1,4}|:)|(?:[a-f\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-f\d]{1,4}){1,2}|:)|(?:[a-f\d]{1,4}:){4}(?:(?::[a-f\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-f\d]{1,4}){1,3}|:)|(?:[a-f\d]{1,4}:){3}(?:(?::[a-f\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-f\d]{1,4}){1,4}|:)|(?:[a-f\d]{1,4}:){2}(?:(?::[a-f\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-f\d]{1,4}){1,5}|:)|(?:[a-f\d]{1,4}:){1}(?:(?::[a-f\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-f\d]{1,4}){1,6}|:)|(?::(?:(?::[a-f\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-f\d]{1,4}){1,7}|:)))$)/;
25295
25298
  function domainMatch(domain, cookieDomain, canonicalize) {
@@ -25691,7 +25694,7 @@ var CookieJar = class _CookieJar {
25691
25694
  return promiseCallback.reject(parameterError);
25692
25695
  }
25693
25696
  const host = canonicalDomain(context.hostname);
25694
- const path6 = context.pathname || "/";
25697
+ const path10 = context.pathname || "/";
25695
25698
  const potentiallyTrustworthy = isPotentiallyTrustworthy(
25696
25699
  url2,
25697
25700
  this.allowSecureOnLocal
@@ -25722,7 +25725,7 @@ var CookieJar = class _CookieJar {
25722
25725
  return false;
25723
25726
  }
25724
25727
  }
25725
- if (!allPaths && typeof c.path === "string" && !pathMatch(path6, c.path)) {
25728
+ if (!allPaths && typeof c.path === "string" && !pathMatch(path10, c.path)) {
25726
25729
  return false;
25727
25730
  }
25728
25731
  if (c.secure && !potentiallyTrustworthy) {
@@ -25754,7 +25757,7 @@ var CookieJar = class _CookieJar {
25754
25757
  }
25755
25758
  store.findCookies(
25756
25759
  host,
25757
- allPaths ? null : path6,
25760
+ allPaths ? null : path10,
25758
25761
  this.allowSpecialUseDomain,
25759
25762
  (err, cookies) => {
25760
25763
  if (err) {
@@ -26231,8 +26234,21 @@ function isNornError(error) {
26231
26234
  return error instanceof NornError;
26232
26235
  }
26233
26236
 
26237
+ // src/httpRuntimeOptions.ts
26238
+ var verifyTlsCertificates = true;
26239
+ function setVerifyTlsCertificates(enabled) {
26240
+ verifyTlsCertificates = enabled;
26241
+ }
26242
+ function getVerifyTlsCertificates() {
26243
+ return verifyTlsCertificates;
26244
+ }
26245
+
26234
26246
  // src/httpClient.ts
26235
26247
  var sharedCookieJar = new CookieJar();
26248
+ var insecureHttpsAgent = new https2.Agent({ rejectUnauthorized: false });
26249
+ function getHttpsAgent() {
26250
+ return getVerifyTlsCertificates() ? void 0 : insecureHttpsAgent;
26251
+ }
26236
26252
  function createCookieJar() {
26237
26253
  return new CookieJar();
26238
26254
  }
@@ -26253,7 +26269,7 @@ async function sendRequest(request, retryOptions) {
26253
26269
  return sendRequestWithJar(request, sharedCookieJar, retryOptions);
26254
26270
  }
26255
26271
  function sleep(ms) {
26256
- return new Promise((resolve6) => setTimeout(resolve6, ms));
26272
+ return new Promise((resolve9) => setTimeout(resolve9, ms));
26257
26273
  }
26258
26274
  function shouldRetry(response, error) {
26259
26275
  if (error) return true;
@@ -26328,11 +26344,13 @@ async function sendRequestWithJar(request, jar, retryOptions) {
26328
26344
  const response = await axios_default({
26329
26345
  method: currentMethod,
26330
26346
  url: currentUrl,
26347
+ adapter: "http",
26331
26348
  headers,
26332
26349
  data,
26333
26350
  timeout: 3e4,
26334
26351
  maxRedirects: 0,
26335
- validateStatus: () => true
26352
+ validateStatus: () => true,
26353
+ httpsAgent: getHttpsAgent()
26336
26354
  });
26337
26355
  const setCookieHeader = response.headers["set-cookie"];
26338
26356
  if (setCookieHeader) {
@@ -26448,8 +26466,8 @@ var pwshAvailable = null;
26448
26466
  function stripAnsiCodes(str) {
26449
26467
  return str.replace(/\x1B(?:\[[0-9;]*[a-zA-Z]|\][^\x07]*(?:\x07|\x1B\\)|[a-zA-Z])/g, "");
26450
26468
  }
26451
- function tryParsePowerShellOutput(output) {
26452
- const lines = output.split("\n").map((l) => l.trimEnd());
26469
+ function tryParsePowerShellOutput(output2) {
26470
+ const lines = output2.split("\n").map((l) => l.trimEnd());
26453
26471
  const nonEmptyLines = lines.filter((l) => l.trim() !== "");
26454
26472
  if (nonEmptyLines.length === 0) {
26455
26473
  return null;
@@ -26543,8 +26561,8 @@ function parseValue(str) {
26543
26561
  }
26544
26562
  return str;
26545
26563
  }
26546
- function cleanScriptOutput(output) {
26547
- let cleaned = stripAnsiCodes(output).trim();
26564
+ function cleanScriptOutput(output2) {
26565
+ let cleaned = stripAnsiCodes(output2).trim();
26548
26566
  if (cleaned.startsWith("{") && cleaned.endsWith("}") || cleaned.startsWith("[") && cleaned.endsWith("]")) {
26549
26567
  try {
26550
26568
  const parsed = JSON.parse(cleaned);
@@ -26664,7 +26682,7 @@ async function runScript(type, scriptPath, args, workingDir, variables = {}, cap
26664
26682
  captureVar
26665
26683
  };
26666
26684
  }
26667
- return new Promise((resolve6) => {
26685
+ return new Promise((resolve9) => {
26668
26686
  const env3 = {
26669
26687
  ...process.env,
26670
26688
  // Pass variables as environment variables with NORN_ prefix
@@ -26688,7 +26706,7 @@ async function runScript(type, scriptPath, args, workingDir, variables = {}, cap
26688
26706
  stderr += data.toString();
26689
26707
  });
26690
26708
  child.on("error", (err) => {
26691
- resolve6({
26709
+ resolve9({
26692
26710
  success: false,
26693
26711
  output: cleanScriptOutput(stdout),
26694
26712
  error: `Failed to execute script: ${err.message}`,
@@ -26702,7 +26720,7 @@ async function runScript(type, scriptPath, args, workingDir, variables = {}, cap
26702
26720
  child.on("close", (code) => {
26703
26721
  const exitCode = code ?? 0;
26704
26722
  const cleanedOutput = cleanScriptOutput(stdout);
26705
- resolve6({
26723
+ resolve9({
26706
26724
  success: exitCode === 0,
26707
26725
  output: cleanedOutput,
26708
26726
  error: stderr.trim(),
@@ -26767,11 +26785,11 @@ function readJsonFile(filePath, workingDir) {
26767
26785
  };
26768
26786
  }
26769
26787
  }
26770
- function setNestedValue(obj, path6, value) {
26771
- if (!path6 || obj === null || obj === void 0 || typeof obj !== "object") {
26788
+ function setNestedValue(obj, path10, value) {
26789
+ if (!path10 || obj === null || obj === void 0 || typeof obj !== "object") {
26772
26790
  return false;
26773
26791
  }
26774
- const parts = path6.replace(/\[(\d+)\]/g, ".$1").split(".").filter((p) => p !== "");
26792
+ const parts = path10.replace(/\[(\d+)\]/g, ".$1").split(".").filter((p) => p !== "");
26775
26793
  if (parts.length === 0) {
26776
26794
  return false;
26777
26795
  }
@@ -27273,8 +27291,8 @@ function bindSequenceArguments(params, args, runtimeVariables) {
27273
27291
  }
27274
27292
  return { variables: result };
27275
27293
  }
27276
- function getVariableValueByPath(path6, variables) {
27277
- const parts = path6.split(".");
27294
+ function getVariableValueByPath(path10, variables) {
27295
+ const parts = path10.split(".");
27278
27296
  let current = variables;
27279
27297
  for (const part of parts) {
27280
27298
  if (current === null || current === void 0) {
@@ -27639,8 +27657,8 @@ function evaluateValueExpression(expr, runtimeVariables) {
27639
27657
  } else {
27640
27658
  return { value: String(varValue), error: `Cannot access path on non-object value` };
27641
27659
  }
27642
- const path6 = pathPart.replace(/^\./, "").replace(/\[(\d+)\]/g, ".$1");
27643
- const parts = path6.split(".").filter((p) => p !== "");
27660
+ const path10 = pathPart.replace(/^\./, "").replace(/\[(\d+)\]/g, ".$1");
27661
+ const parts = path10.split(".").filter((p) => p !== "");
27644
27662
  let current = dataToNavigate;
27645
27663
  for (const part of parts) {
27646
27664
  if (current === null || current === void 0) {
@@ -27719,8 +27737,8 @@ function resolveBareVariables(text, variables) {
27719
27737
  if (varName in variables) {
27720
27738
  const value = variables[varName];
27721
27739
  if (pathPart) {
27722
- const path6 = pathPart.replace(/^\./, "");
27723
- const nestedValue = getNestedValueFromObject(value, path6);
27740
+ const path10 = pathPart.replace(/^\./, "");
27741
+ const nestedValue = getNestedValueFromObject(value, path10);
27724
27742
  return valueToString2(nestedValue);
27725
27743
  }
27726
27744
  return valueToString2(value);
@@ -27740,8 +27758,8 @@ function resolveBareVariables(text, variables) {
27740
27758
  if (varName in variables) {
27741
27759
  const value = variables[varName];
27742
27760
  if (pathPart) {
27743
- const path6 = pathPart.replace(/^\./, "");
27744
- return valueToString2(getNestedValueFromObject(value, path6));
27761
+ const path10 = pathPart.replace(/^\./, "");
27762
+ return valueToString2(getNestedValueFromObject(value, path10));
27745
27763
  }
27746
27764
  return valueToString2(value);
27747
27765
  }
@@ -27778,11 +27796,11 @@ function splitExpressionParts(expr) {
27778
27796
  }
27779
27797
  return parts;
27780
27798
  }
27781
- function getNestedValueFromObject(obj, path6) {
27782
- if (!path6) {
27799
+ function getNestedValueFromObject(obj, path10) {
27800
+ if (!path10) {
27783
27801
  return obj;
27784
27802
  }
27785
- const parts = path6.split(/\.|\[(\d+)\]/).filter((p) => p !== "" && p !== void 0);
27803
+ const parts = path10.split(/\.|\[(\d+)\]/).filter((p) => p !== "" && p !== void 0);
27786
27804
  let current = obj;
27787
27805
  for (const part of parts) {
27788
27806
  if (current === null || current === void 0) {
@@ -27805,7 +27823,7 @@ function valueToString2(value) {
27805
27823
  return String(value);
27806
27824
  }
27807
27825
  function sleep2(ms) {
27808
- return new Promise((resolve6) => setTimeout(resolve6, ms));
27826
+ return new Promise((resolve9) => setTimeout(resolve9, ms));
27809
27827
  }
27810
27828
  function isIfCommand(line2) {
27811
27829
  return /^if\s+.+$/i.test(line2.trim());
@@ -28127,24 +28145,24 @@ function extractCaptureDirectives(content) {
28127
28145
  for (const line2 of content.split("\n")) {
28128
28146
  const match = line2.trim().match(captureRegex);
28129
28147
  if (match) {
28130
- let path6 = match[3] || "";
28131
- if (path6.startsWith(".")) {
28132
- path6 = path6.substring(1);
28148
+ let path10 = match[3] || "";
28149
+ if (path10.startsWith(".")) {
28150
+ path10 = path10.substring(1);
28133
28151
  }
28134
28152
  captures.push({
28135
28153
  varName: match[1],
28136
28154
  afterRequest: parseInt(match[2], 10),
28137
- path: path6
28155
+ path: path10
28138
28156
  });
28139
28157
  }
28140
28158
  }
28141
28159
  return captures;
28142
28160
  }
28143
- function getValueByPath(response, path6) {
28144
- if (!path6) {
28161
+ function getValueByPath(response, path10) {
28162
+ if (!path10) {
28145
28163
  return void 0;
28146
28164
  }
28147
- const parts = path6.replace(/\[(\d+)\]/g, ".$1").split(".").filter((p) => p !== "");
28165
+ const parts = path10.replace(/\[(\d+)\]/g, ".$1").split(".").filter((p) => p !== "");
28148
28166
  if (parts.length === 0) {
28149
28167
  return void 0;
28150
28168
  }
@@ -28448,8 +28466,8 @@ async function runSequenceWithJar(sequenceContent, fileVariables, cookieJar, wor
28448
28466
  }
28449
28467
  }
28450
28468
  if (pathPart) {
28451
- const path6 = pathPart.replace(/^\./, "");
28452
- newValue = getNestedValueFromObject(value, path6);
28469
+ const path10 = pathPart.replace(/^\./, "");
28470
+ newValue = getNestedValueFromObject(value, path10);
28453
28471
  } else {
28454
28472
  newValue = value;
28455
28473
  }
@@ -28811,8 +28829,8 @@ ${indentMultiline(userMessage)}`;
28811
28829
  if (sequenceSources) {
28812
28830
  const sourceFile = sequenceSources.get(targetName.toLowerCase());
28813
28831
  if (sourceFile) {
28814
- const path6 = await import("path");
28815
- subWorkingDir = path6.dirname(sourceFile);
28832
+ const path10 = await import("path");
28833
+ subWorkingDir = path10.dirname(sourceFile);
28816
28834
  }
28817
28835
  }
28818
28836
  const subResult = await runSequenceWithJar(
@@ -29073,12 +29091,14 @@ ${indentMultiline(userMessage)}`;
29073
29091
  } : void 0;
29074
29092
  const response = cookieJar ? await sendRequestWithJar(requestParsed, cookieJar, retryOpts) : await sendRequest(requestParsed, retryOpts);
29075
29093
  addResponse(response);
29094
+ responseIndexToVariable.set(responses.length, varName);
29076
29095
  const stepResult = {
29077
29096
  type: "request",
29078
29097
  stepIndex: stepIdx,
29079
29098
  response,
29080
29099
  requestMethod: requestParsed.method,
29081
- requestUrl: requestParsed.url
29100
+ requestUrl: requestParsed.url,
29101
+ variableName: varName
29082
29102
  };
29083
29103
  orderedSteps.push(stepResult);
29084
29104
  reportProgress(stepIdx, "namedRequest", `var ${varName} = run ${sequenceName} \u2192 ${requestParsed.method} ${requestParsed.url}`, stepResult);
@@ -29165,8 +29185,8 @@ ${indentMultiline(userMessage)}`;
29165
29185
  if (sequenceSources) {
29166
29186
  const sourceFile = sequenceSources.get(sequenceName.toLowerCase());
29167
29187
  if (sourceFile) {
29168
- const path6 = await import("path");
29169
- subWorkingDir = path6.dirname(sourceFile);
29188
+ const path10 = await import("path");
29189
+ subWorkingDir = path10.dirname(sourceFile);
29170
29190
  }
29171
29191
  }
29172
29192
  const subResult = await runSequenceWithJar(
@@ -30571,14 +30591,238 @@ function generateHtmlReportFromResponse(response, testName, options) {
30571
30591
  }
30572
30592
 
30573
30593
  // src/environmentParser.ts
30594
+ var fs7 = __toESM(require("fs"));
30595
+ var path6 = __toESM(require("path"));
30596
+
30597
+ // src/secrets/crypto.ts
30598
+ var crypto2 = __toESM(require("crypto"));
30599
+ var ENCRYPTED_SECRET_PREFIX = "ENC[";
30600
+ var ENCRYPTED_SECRET_SUFFIX = "]";
30601
+ var ENCRYPTED_SECRET_VERSION = "NORN_AGE_V1";
30602
+ var encryptedSecretRegex = /^ENC\[([A-Z0-9_]+):kid=([a-zA-Z0-9._-]+):([A-Za-z0-9_-]+)\]$/;
30603
+ function deriveEncryptionKey(sharedKey) {
30604
+ return crypto2.createHash("sha256").update(sharedKey, "utf8").digest();
30605
+ }
30606
+ function generateSharedSecretKey() {
30607
+ return crypto2.randomBytes(32).toString("base64url");
30608
+ }
30609
+ function isEncryptedSecretValue(value) {
30610
+ return value.trim().startsWith(ENCRYPTED_SECRET_PREFIX) && value.trim().endsWith(ENCRYPTED_SECRET_SUFFIX);
30611
+ }
30612
+ function parseEncryptedSecretValue(value) {
30613
+ const trimmed = value.trim();
30614
+ const match = trimmed.match(encryptedSecretRegex);
30615
+ if (!match) {
30616
+ return {
30617
+ ok: false,
30618
+ error: `Invalid encrypted secret format. Expected: ENC[${ENCRYPTED_SECRET_VERSION}:kid=<id>:<payload>]`
30619
+ };
30620
+ }
30621
+ return {
30622
+ ok: true,
30623
+ parsed: {
30624
+ version: match[1],
30625
+ kid: match[2],
30626
+ payload: match[3]
30627
+ }
30628
+ };
30629
+ }
30630
+ function encryptSecretValue(plaintext, sharedKey, kid) {
30631
+ const key = deriveEncryptionKey(sharedKey);
30632
+ const iv = crypto2.randomBytes(12);
30633
+ const cipher = crypto2.createCipheriv("aes-256-gcm", key, iv);
30634
+ const ciphertext = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
30635
+ const authTag = cipher.getAuthTag();
30636
+ const payload = Buffer.concat([iv, authTag, ciphertext]).toString("base64url");
30637
+ return `ENC[${ENCRYPTED_SECRET_VERSION}:kid=${kid}:${payload}]`;
30638
+ }
30639
+ function decryptSecretValue(encryptedValue, sharedKey) {
30640
+ const parsedResult = parseEncryptedSecretValue(encryptedValue);
30641
+ if (!parsedResult.ok) {
30642
+ throw new Error(parsedResult.error);
30643
+ }
30644
+ const { version: version2, payload } = parsedResult.parsed;
30645
+ if (version2 !== ENCRYPTED_SECRET_VERSION) {
30646
+ throw new Error(`Unsupported encrypted secret version '${version2}'. Expected '${ENCRYPTED_SECRET_VERSION}'.`);
30647
+ }
30648
+ const raw = Buffer.from(payload, "base64url");
30649
+ if (raw.length < 28) {
30650
+ throw new Error("Encrypted payload is too short.");
30651
+ }
30652
+ const iv = raw.subarray(0, 12);
30653
+ const authTag = raw.subarray(12, 28);
30654
+ const ciphertext = raw.subarray(28);
30655
+ const key = deriveEncryptionKey(sharedKey);
30656
+ const decipher = crypto2.createDecipheriv("aes-256-gcm", key, iv);
30657
+ decipher.setAuthTag(authTag);
30658
+ const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
30659
+ return decrypted.toString("utf8");
30660
+ }
30661
+
30662
+ // src/secrets/keyStore.ts
30663
+ var fs6 = __toESM(require("fs"));
30664
+ var path5 = __toESM(require("path"));
30665
+
30666
+ // src/cacheDir.ts
30574
30667
  var fs5 = __toESM(require("fs"));
30575
30668
  var path4 = __toESM(require("path"));
30669
+ var NORN_CACHE_DIR = ".norn-cache";
30670
+ var CACHE_GITIGNORE_FILE = ".gitignore";
30671
+ var CACHE_GITIGNORE_CONTENT = "*\n";
30672
+ function ensureNornCacheGitignore(cacheDir) {
30673
+ const gitignorePath = path4.join(cacheDir, CACHE_GITIGNORE_FILE);
30674
+ try {
30675
+ const hasDesiredContent = fs5.existsSync(gitignorePath) && fs5.readFileSync(gitignorePath, "utf8") === CACHE_GITIGNORE_CONTENT;
30676
+ if (hasDesiredContent) {
30677
+ return;
30678
+ }
30679
+ fs5.writeFileSync(gitignorePath, CACHE_GITIGNORE_CONTENT, "utf8");
30680
+ } catch {
30681
+ }
30682
+ }
30683
+
30684
+ // src/secrets/keyStore.ts
30685
+ var CACHE_FILE = "secret-keys.json";
30686
+ var CACHE_VERSION = 1;
30687
+ var sessionKeys = /* @__PURE__ */ new Map();
30688
+ function getSearchStartDirectory(targetPath) {
30689
+ const resolvedPath = path5.resolve(targetPath);
30690
+ try {
30691
+ const stats = fs6.statSync(resolvedPath);
30692
+ return stats.isDirectory() ? resolvedPath : path5.dirname(resolvedPath);
30693
+ } catch {
30694
+ return path5.dirname(resolvedPath);
30695
+ }
30696
+ }
30697
+ function findExistingCacheDir(targetPath) {
30698
+ let dir = getSearchStartDirectory(targetPath);
30699
+ while (true) {
30700
+ const cacheDir = path5.join(dir, NORN_CACHE_DIR);
30701
+ if (fs6.existsSync(cacheDir) && fs6.statSync(cacheDir).isDirectory()) {
30702
+ return cacheDir;
30703
+ }
30704
+ const parent = path5.dirname(dir);
30705
+ if (parent === dir) {
30706
+ return void 0;
30707
+ }
30708
+ dir = parent;
30709
+ }
30710
+ }
30711
+ function ensureCacheDir(targetPath) {
30712
+ const existing = findExistingCacheDir(targetPath);
30713
+ const cacheDir = existing ?? path5.join(getSearchStartDirectory(targetPath), NORN_CACHE_DIR);
30714
+ if (!fs6.existsSync(cacheDir)) {
30715
+ fs6.mkdirSync(cacheDir, { recursive: true });
30716
+ }
30717
+ ensureNornCacheGitignore(cacheDir);
30718
+ return cacheDir;
30719
+ }
30720
+ function getCachePath(targetPath) {
30721
+ const cacheDir = ensureCacheDir(targetPath);
30722
+ return path5.join(cacheDir, CACHE_FILE);
30723
+ }
30724
+ function readCache(targetPath) {
30725
+ const cachePath = getCachePath(targetPath);
30726
+ if (!fs6.existsSync(cachePath)) {
30727
+ return { version: CACHE_VERSION, keys: {} };
30728
+ }
30729
+ try {
30730
+ const parsed = JSON.parse(fs6.readFileSync(cachePath, "utf8"));
30731
+ if (parsed.version !== CACHE_VERSION || typeof parsed.keys !== "object" || parsed.keys === null) {
30732
+ return { version: CACHE_VERSION, keys: {} };
30733
+ }
30734
+ return parsed;
30735
+ } catch {
30736
+ return { version: CACHE_VERSION, keys: {} };
30737
+ }
30738
+ }
30739
+ function writeCache(targetPath, cache) {
30740
+ const cachePath = getCachePath(targetPath);
30741
+ fs6.writeFileSync(cachePath, JSON.stringify(cache, null, 2), { encoding: "utf8", mode: 384 });
30742
+ try {
30743
+ fs6.chmodSync(cachePath, 384);
30744
+ } catch {
30745
+ }
30746
+ }
30747
+ function kidToEnvVarSuffix(kid) {
30748
+ return kid.replace(/[^a-zA-Z0-9]/g, "_").toUpperCase();
30749
+ }
30750
+ function getEnvMappedKeys() {
30751
+ const raw = process.env.NORN_SECRET_KEYS;
30752
+ if (!raw) {
30753
+ return {};
30754
+ }
30755
+ try {
30756
+ const parsed = JSON.parse(raw);
30757
+ const mapped = {};
30758
+ for (const [key, value] of Object.entries(parsed)) {
30759
+ if (typeof value === "string" && value.trim() !== "") {
30760
+ mapped[key] = value;
30761
+ }
30762
+ }
30763
+ return mapped;
30764
+ } catch {
30765
+ return {};
30766
+ }
30767
+ }
30768
+ function resolveSecretKey(kid, targetPath) {
30769
+ const sessionValue = sessionKeys.get(kid);
30770
+ if (sessionValue) {
30771
+ return sessionValue;
30772
+ }
30773
+ const mapped = getEnvMappedKeys();
30774
+ if (mapped[kid]) {
30775
+ return mapped[kid];
30776
+ }
30777
+ const specific = process.env[`NORN_SECRET_KEY_${kidToEnvVarSuffix(kid)}`];
30778
+ if (specific && specific.trim() !== "") {
30779
+ return specific;
30780
+ }
30781
+ const cache = readCache(targetPath);
30782
+ const cached = cache.keys[kid]?.value;
30783
+ if (cached && cached.trim() !== "") {
30784
+ return cached;
30785
+ }
30786
+ const fallback = process.env.NORN_SECRET_KEY;
30787
+ if (fallback && fallback.trim() !== "") {
30788
+ return fallback;
30789
+ }
30790
+ return void 0;
30791
+ }
30792
+ function setSessionSecretKey(kid, key) {
30793
+ sessionKeys.set(kid, key);
30794
+ }
30795
+ function saveSecretKeyToCache(kid, key, targetPath) {
30796
+ const cache = readCache(targetPath);
30797
+ cache.keys[kid] = {
30798
+ value: key,
30799
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
30800
+ };
30801
+ writeCache(targetPath, cache);
30802
+ setSessionSecretKey(kid, key);
30803
+ }
30804
+ function removeSecretKeyFromCache(kid, targetPath) {
30805
+ const cache = readCache(targetPath);
30806
+ if (!cache.keys[kid]) {
30807
+ return false;
30808
+ }
30809
+ delete cache.keys[kid];
30810
+ writeCache(targetPath, cache);
30811
+ sessionKeys.delete(kid);
30812
+ return true;
30813
+ }
30814
+ function listCachedSecretKeyIds(targetPath) {
30815
+ const cache = readCache(targetPath);
30816
+ return Object.keys(cache.keys).sort();
30817
+ }
30818
+
30819
+ // src/environmentParser.ts
30576
30820
  var ENV_FILENAME = ".nornenv";
30577
30821
  var importRegex = /^import\s+["']?(.+?)["']?\s*$/;
30578
30822
  var envRegex = /^\[env:([a-zA-Z_][a-zA-Z0-9_-]*)\]$/;
30579
30823
  var varRegex = /^var\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*(.+)$/;
30580
30824
  var secretRegex = /^secret\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*(.+)$/;
30581
- function parseEnvFile(content) {
30825
+ function parseEnvFile(content, sourceFilePath) {
30582
30826
  const lines = content.split("\n");
30583
30827
  const config = {
30584
30828
  common: {},
@@ -30586,7 +30830,8 @@ function parseEnvFile(content) {
30586
30830
  secretNames: /* @__PURE__ */ new Set(),
30587
30831
  secretValues: /* @__PURE__ */ new Map(),
30588
30832
  imports: [],
30589
- misplacedImports: []
30833
+ misplacedImports: [],
30834
+ secretDeclarations: []
30590
30835
  };
30591
30836
  let currentEnv = null;
30592
30837
  let seenContent = false;
@@ -30621,6 +30866,13 @@ function parseEnvFile(content) {
30621
30866
  if (secretMatch) {
30622
30867
  const varName = secretMatch[1];
30623
30868
  const varValue = secretMatch[2].trim();
30869
+ config.secretDeclarations.push({
30870
+ name: varName,
30871
+ value: varValue,
30872
+ envName: currentEnv?.name,
30873
+ lineNumber: i,
30874
+ filePath: sourceFilePath
30875
+ });
30624
30876
  config.secretNames.add(varName);
30625
30877
  config.secretValues.set(varName, varValue);
30626
30878
  if (currentEnv) {
@@ -30644,22 +30896,22 @@ function parseEnvFile(content) {
30644
30896
  return config;
30645
30897
  }
30646
30898
  function getEnvSearchStartDirectory(targetPath) {
30647
- const resolvedPath = path4.resolve(targetPath);
30899
+ const resolvedPath = path6.resolve(targetPath);
30648
30900
  try {
30649
- const stats = fs5.statSync(resolvedPath);
30650
- return stats.isDirectory() ? resolvedPath : path4.dirname(resolvedPath);
30901
+ const stats = fs7.statSync(resolvedPath);
30902
+ return stats.isDirectory() ? resolvedPath : path6.dirname(resolvedPath);
30651
30903
  } catch {
30652
- return path4.dirname(resolvedPath);
30904
+ return path6.dirname(resolvedPath);
30653
30905
  }
30654
30906
  }
30655
30907
  function findEnvFileFromPath(filePath) {
30656
30908
  let dir = getEnvSearchStartDirectory(filePath);
30657
30909
  while (true) {
30658
- const envPath = path4.join(dir, ENV_FILENAME);
30659
- if (fs5.existsSync(envPath)) {
30910
+ const envPath = path6.join(dir, ENV_FILENAME);
30911
+ if (fs7.existsSync(envPath)) {
30660
30912
  return envPath;
30661
30913
  }
30662
- const parentDir = path4.dirname(dir);
30914
+ const parentDir = path6.dirname(dir);
30663
30915
  if (parentDir === dir) {
30664
30916
  break;
30665
30917
  }
@@ -30669,6 +30921,7 @@ function findEnvFileFromPath(filePath) {
30669
30921
  }
30670
30922
  function resolveNornenvImports(config, baseDir, entryFilePath, readFile2, importStack, alreadyImported) {
30671
30923
  const errors = [];
30924
+ const secretErrors = [];
30672
30925
  const resolvedPaths = [];
30673
30926
  const stack = importStack ?? [entryFilePath];
30674
30927
  const visited = alreadyImported ?? /* @__PURE__ */ new Set([entryFilePath]);
@@ -30683,7 +30936,7 @@ function resolveNornenvImports(config, baseDir, entryFilePath, readFile2, import
30683
30936
  }
30684
30937
  for (const imp of config.imports) {
30685
30938
  const resolvedImportPath = resolveImportPath(imp.path, baseDir);
30686
- if (!resolvedImportPath || !fs5.existsSync(resolvedImportPath)) {
30939
+ if (!resolvedImportPath || !fs7.existsSync(resolvedImportPath)) {
30687
30940
  errors.push({
30688
30941
  message: `Imported file not found: '${imp.path}'`,
30689
30942
  filePath: entryFilePath,
@@ -30699,10 +30952,10 @@ function resolveNornenvImports(config, baseDir, entryFilePath, readFile2, import
30699
30952
  });
30700
30953
  continue;
30701
30954
  }
30702
- const normalizedPath = path4.resolve(resolvedImportPath);
30955
+ const normalizedPath = path6.resolve(resolvedImportPath);
30703
30956
  if (stack.includes(normalizedPath)) {
30704
- const entryDir = path4.dirname(stack[0]);
30705
- const cycle = [...stack, normalizedPath].map((p) => path4.relative(entryDir, p) || path4.basename(p)).join(" \u2192 ");
30957
+ const entryDir = path6.dirname(stack[0]);
30958
+ const cycle = [...stack, normalizedPath].map((p) => path6.relative(entryDir, p) || path6.basename(p)).join(" \u2192 ");
30706
30959
  errors.push({
30707
30960
  message: `Circular import detected: ${cycle}`,
30708
30961
  filePath: entryFilePath,
@@ -30726,29 +30979,30 @@ function resolveNornenvImports(config, baseDir, entryFilePath, readFile2, import
30726
30979
  });
30727
30980
  continue;
30728
30981
  }
30729
- const importedConfig = parseEnvFile(importedContent);
30982
+ const importedConfig = parseEnvFile(importedContent, normalizedPath);
30730
30983
  resolvedPaths.push(normalizedPath);
30731
30984
  if (importedConfig.imports.length > 0) {
30732
30985
  const childResult = resolveNornenvImports(
30733
30986
  importedConfig,
30734
- path4.dirname(normalizedPath),
30987
+ path6.dirname(normalizedPath),
30735
30988
  normalizedPath,
30736
30989
  readFile2,
30737
30990
  [...stack, normalizedPath],
30738
30991
  visited
30739
30992
  );
30740
30993
  errors.push(...childResult.errors);
30994
+ secretErrors.push(...childResult.secretErrors);
30741
30995
  resolvedPaths.push(...childResult.resolvedPaths);
30742
30996
  mergeConfigs(config, childResult.config, entryFilePath, normalizedPath, variableOrigins, errors);
30743
30997
  } else {
30744
30998
  mergeConfigs(config, importedConfig, entryFilePath, normalizedPath, variableOrigins, errors);
30745
30999
  }
30746
31000
  }
30747
- return { config, errors, resolvedPaths };
31001
+ return { config, errors, secretErrors, resolvedPaths };
30748
31002
  }
30749
31003
  function resolveImportPath(importPath, baseDir) {
30750
31004
  const cleaned = importPath.replace(/^["']|["']$/g, "");
30751
- return path4.resolve(baseDir, cleaned);
31005
+ return path6.resolve(baseDir, cleaned);
30752
31006
  }
30753
31007
  function registerVariableOrigins(config, filePath, origins) {
30754
31008
  for (const varName of Object.keys(config.common)) {
@@ -30807,31 +31061,578 @@ function mergeConfigs(target, source, targetFilePath, sourceFilePath, variableOr
30807
31061
  for (const [name, value] of source.secretValues) {
30808
31062
  target.secretValues.set(name, value);
30809
31063
  }
31064
+ for (const declaration of source.secretDeclarations) {
31065
+ target.secretDeclarations.push({ ...declaration, filePath: declaration.filePath ?? sourceFilePath });
31066
+ }
30810
31067
  }
30811
31068
  function toDisplayPath(filePath, entryFilePath) {
30812
- const entryDir = path4.dirname(entryFilePath);
30813
- const relative3 = path4.relative(entryDir, filePath);
30814
- return relative3 && relative3 !== "" ? relative3 : path4.basename(filePath);
31069
+ const entryDir = path6.dirname(entryFilePath);
31070
+ const relative4 = path6.relative(entryDir, filePath);
31071
+ return relative4 && relative4 !== "" ? relative4 : path6.basename(filePath);
30815
31072
  }
30816
31073
  function loadAndResolveEnvFile(filePath) {
30817
- const content = fs5.readFileSync(filePath, "utf-8");
30818
- const config = parseEnvFile(content);
31074
+ const content = fs7.readFileSync(filePath, "utf-8");
31075
+ const config = parseEnvFile(content, filePath);
30819
31076
  if (config.imports.length === 0) {
30820
- return { config, errors: [], resolvedPaths: [] };
31077
+ const secretErrors = resolveEncryptedSecretValues(config, filePath);
31078
+ return { config, errors: [], secretErrors, resolvedPaths: [] };
30821
31079
  }
30822
- return resolveNornenvImports(
31080
+ const result = resolveNornenvImports(
30823
31081
  config,
30824
- path4.dirname(filePath),
31082
+ path6.dirname(filePath),
30825
31083
  filePath,
30826
- (p) => fs5.readFileSync(p, "utf-8")
31084
+ (p) => fs7.readFileSync(p, "utf-8")
30827
31085
  );
31086
+ result.secretErrors.push(...resolveEncryptedSecretValues(result.config, filePath));
31087
+ return result;
31088
+ }
31089
+ function resolveEncryptedSecretValues(config, entryFilePath) {
31090
+ const errors = [];
31091
+ for (const declaration of config.secretDeclarations) {
31092
+ if (!isEncryptedSecretValue(declaration.value)) {
31093
+ continue;
31094
+ }
31095
+ const parsed = parseEncryptedSecretValue(declaration.value);
31096
+ const filePath = declaration.filePath ?? entryFilePath;
31097
+ if (!parsed.ok) {
31098
+ errors.push({
31099
+ code: "invalid-format",
31100
+ message: parsed.error,
31101
+ filePath,
31102
+ line: declaration.lineNumber,
31103
+ variableName: declaration.name
31104
+ });
31105
+ continue;
31106
+ }
31107
+ const { kid } = parsed.parsed;
31108
+ const key = resolveSecretKey(kid, filePath);
31109
+ if (!key) {
31110
+ errors.push({
31111
+ code: "missing-key",
31112
+ message: `Missing secret key for kid '${kid}'.`,
31113
+ filePath,
31114
+ line: declaration.lineNumber,
31115
+ variableName: declaration.name,
31116
+ kid
31117
+ });
31118
+ continue;
31119
+ }
31120
+ let plaintext;
31121
+ try {
31122
+ plaintext = decryptSecretValue(declaration.value, key);
31123
+ } catch (error) {
31124
+ const message = error instanceof Error ? error.message : String(error);
31125
+ errors.push({
31126
+ code: "decrypt-failed",
31127
+ message: `Failed to decrypt secret '${declaration.name}' with kid '${kid}': ${message}`,
31128
+ filePath,
31129
+ line: declaration.lineNumber,
31130
+ variableName: declaration.name,
31131
+ kid
31132
+ });
31133
+ continue;
31134
+ }
31135
+ declaration.value = plaintext;
31136
+ if (declaration.envName) {
31137
+ const env3 = config.environments.find((e) => e.name === declaration.envName);
31138
+ if (env3) {
31139
+ env3.variables[declaration.name] = plaintext;
31140
+ }
31141
+ } else {
31142
+ config.common[declaration.name] = plaintext;
31143
+ }
31144
+ config.secretValues.set(declaration.name, plaintext);
31145
+ }
31146
+ return errors;
31147
+ }
31148
+
31149
+ // src/secrets/cliSecrets.ts
31150
+ var fs9 = __toESM(require("fs"));
31151
+ var path8 = __toESM(require("path"));
31152
+ var readline = __toESM(require("readline"));
31153
+ var import_process = require("process");
31154
+
31155
+ // src/secrets/envFileSecrets.ts
31156
+ var fs8 = __toESM(require("fs"));
31157
+ var path7 = __toESM(require("path"));
31158
+ var envRegex2 = /^\s*\[env:([a-zA-Z_][a-zA-Z0-9_-]*)\]\s*$/;
31159
+ var secretRegex2 = /^(\s*secret\s+)([a-zA-Z_][a-zA-Z0-9_]*)(\s*=\s*)(.+)$/;
31160
+ function extractSecretLines(content, filePath) {
31161
+ const lines = content.split("\n");
31162
+ const secrets = [];
31163
+ let currentEnv;
31164
+ for (let i = 0; i < lines.length; i++) {
31165
+ const line2 = lines[i];
31166
+ const trimmed = line2.trim();
31167
+ if (!trimmed || trimmed.startsWith("#")) {
31168
+ continue;
31169
+ }
31170
+ const envMatch = trimmed.match(envRegex2);
31171
+ if (envMatch) {
31172
+ currentEnv = envMatch[1];
31173
+ continue;
31174
+ }
31175
+ const secretMatch = line2.match(secretRegex2);
31176
+ if (!secretMatch) {
31177
+ continue;
31178
+ }
31179
+ const value = secretMatch[4].trim();
31180
+ const encrypted = isEncryptedSecretValue(value);
31181
+ let kid;
31182
+ if (encrypted) {
31183
+ const parsed = parseEncryptedSecretValue(value);
31184
+ if (parsed.ok) {
31185
+ kid = parsed.parsed.kid;
31186
+ }
31187
+ }
31188
+ secrets.push({
31189
+ filePath,
31190
+ lineNumber: i,
31191
+ envName: currentEnv,
31192
+ name: secretMatch[2],
31193
+ value,
31194
+ encrypted,
31195
+ kid
31196
+ });
31197
+ }
31198
+ return secrets;
31199
+ }
31200
+ function updateSecretLineValue(content, lineNumber, newValue) {
31201
+ const lines = content.split("\n");
31202
+ if (lineNumber < 0 || lineNumber >= lines.length) {
31203
+ throw new Error(`Line ${lineNumber + 1} is out of range.`);
31204
+ }
31205
+ const line2 = lines[lineNumber];
31206
+ const secretMatch = line2.match(secretRegex2);
31207
+ if (!secretMatch) {
31208
+ throw new Error(`Line ${lineNumber + 1} is not a secret declaration.`);
31209
+ }
31210
+ lines[lineNumber] = `${secretMatch[1]}${secretMatch[2]}${secretMatch[3]}${newValue}`;
31211
+ return lines.join("\n");
31212
+ }
31213
+ function findSecretLine(content, variableName, envName) {
31214
+ const secretLines = extractSecretLines(content);
31215
+ if (envName !== void 0) {
31216
+ return secretLines.find((secret) => secret.name === variableName && secret.envName === envName);
31217
+ }
31218
+ const commonMatch = secretLines.find((secret) => secret.name === variableName && secret.envName === void 0);
31219
+ if (commonMatch) {
31220
+ return commonMatch;
31221
+ }
31222
+ return secretLines.find((secret) => secret.name === variableName);
31223
+ }
31224
+ function loadSecretLine(filePath, variableName, envName) {
31225
+ const content = fs8.readFileSync(filePath, "utf8");
31226
+ const secret = findSecretLine(content, variableName, envName);
31227
+ if (!secret) {
31228
+ const envLabel = envName ? ` in [env:${envName}]` : "";
31229
+ throw new Error(`Secret '${variableName}' not found${envLabel} in ${filePath}`);
31230
+ }
31231
+ return { content, secret };
31232
+ }
31233
+ function writeSecretLine(filePath, content) {
31234
+ fs8.writeFileSync(filePath, content, "utf8");
31235
+ }
31236
+ function discoverNornenvFiles(targetPath) {
31237
+ const resolved = path7.resolve(targetPath);
31238
+ if (!fs8.existsSync(resolved)) {
31239
+ return [];
31240
+ }
31241
+ const stats = fs8.statSync(resolved);
31242
+ if (stats.isFile()) {
31243
+ return path7.basename(resolved) === ".nornenv" ? [resolved] : [];
31244
+ }
31245
+ const results = [];
31246
+ const walk = (dir) => {
31247
+ const entries = fs8.readdirSync(dir, { withFileTypes: true });
31248
+ for (const entry of entries) {
31249
+ const fullPath = path7.join(dir, entry.name);
31250
+ if (entry.isDirectory()) {
31251
+ if (entry.name === "node_modules" || entry.name === ".git" || entry.name === "dist" || entry.name === "out") {
31252
+ continue;
31253
+ }
31254
+ walk(fullPath);
31255
+ continue;
31256
+ }
31257
+ if (entry.isFile() && entry.name === ".nornenv") {
31258
+ results.push(fullPath);
31259
+ }
31260
+ }
31261
+ };
31262
+ walk(resolved);
31263
+ return results.sort();
31264
+ }
31265
+
31266
+ // src/secrets/cliSecrets.ts
31267
+ function getFlagValue(args, flag, shortFlag) {
31268
+ const longIndex = args.indexOf(flag);
31269
+ if (longIndex >= 0 && longIndex + 1 < args.length) {
31270
+ return args[longIndex + 1];
31271
+ }
31272
+ if (shortFlag) {
31273
+ const shortIndex = args.indexOf(shortFlag);
31274
+ if (shortIndex >= 0 && shortIndex + 1 < args.length) {
31275
+ return args[shortIndex + 1];
31276
+ }
31277
+ }
31278
+ return void 0;
31279
+ }
31280
+ async function promptLine(question) {
31281
+ if (!process.stdin.isTTY) {
31282
+ return void 0;
31283
+ }
31284
+ const rl = readline.createInterface({ input: import_process.stdin, output: import_process.stdout });
31285
+ try {
31286
+ const answer = await new Promise((resolve9) => {
31287
+ rl.question(question, resolve9);
31288
+ });
31289
+ const trimmed = answer.trim();
31290
+ return trimmed === "" ? void 0 : trimmed;
31291
+ } finally {
31292
+ rl.close();
31293
+ }
31294
+ }
31295
+ function uniqueUnlockableKids(errors) {
31296
+ const kids = /* @__PURE__ */ new Set();
31297
+ for (const err of errors) {
31298
+ if ((err.code === "missing-key" || err.code === "decrypt-failed") && err.kid) {
31299
+ kids.add(err.kid);
31300
+ }
31301
+ }
31302
+ return Array.from(kids).sort();
31303
+ }
31304
+ function formatSecretError(err, envFilePath) {
31305
+ if (!envFilePath) {
31306
+ return `${err.message}`;
31307
+ }
31308
+ const relative4 = path8.relative(path8.dirname(envFilePath), err.filePath);
31309
+ const fileLabel = relative4 && relative4 !== "" ? relative4 : path8.basename(err.filePath);
31310
+ const lineLabel = err.line >= 0 ? `${fileLabel}:${err.line + 1}` : fileLabel;
31311
+ return `${lineLabel} - ${err.message}`;
31312
+ }
31313
+ async function ensureKeyForKid(kid, contextPath) {
31314
+ const existing = resolveSecretKey(kid, contextPath);
31315
+ if (existing) {
31316
+ return existing;
31317
+ }
31318
+ const entered = await promptLine(`Enter shared key for kid '${kid}': `);
31319
+ if (!entered) {
31320
+ return void 0;
31321
+ }
31322
+ saveSecretKeyToCache(kid, entered, contextPath);
31323
+ return entered;
31324
+ }
31325
+ async function ensureCliSecretsUnlocked(targetPath) {
31326
+ const envFilePath = findEnvFileFromPath(targetPath);
31327
+ if (!envFilePath) {
31328
+ return { ok: true, errors: [] };
31329
+ }
31330
+ for (let attempt = 0; attempt < 5; attempt++) {
31331
+ const result = loadAndResolveEnvFile(envFilePath);
31332
+ const unlockableKids = uniqueUnlockableKids(result.secretErrors);
31333
+ if (unlockableKids.length === 0) {
31334
+ return { ok: result.secretErrors.length === 0, envFilePath, errors: result.secretErrors };
31335
+ }
31336
+ for (const kid of unlockableKids) {
31337
+ const key = await ensureKeyForKid(kid, envFilePath);
31338
+ if (!key) {
31339
+ return { ok: false, envFilePath, errors: result.secretErrors };
31340
+ }
31341
+ }
31342
+ }
31343
+ const finalResult = loadAndResolveEnvFile(envFilePath);
31344
+ return { ok: finalResult.secretErrors.length === 0, envFilePath, errors: finalResult.secretErrors };
31345
+ }
31346
+ function printSecretsHelp() {
31347
+ console.log(`
31348
+ Norn Secrets Commands
31349
+
31350
+ Usage:
31351
+ norn secrets keygen --name <kid>
31352
+ norn secrets import-key --kid <kid> [--key <value>]
31353
+ norn secrets encrypt --file <.nornenv> --var <name> [--env <env>] [--kid <kid>]
31354
+ norn secrets rotate --file <.nornenv> --var <name> [--env <env>] [--kid <kid>] [--value <plaintext>]
31355
+ norn secrets rekey [path] [--kid <newKid>]
31356
+ norn secrets audit [path]
31357
+ norn secrets keys
31358
+ norn secrets forget --kid <kid>
31359
+
31360
+ Notes:
31361
+ - Secrets are stored as ENC[NORN_AGE_V1:kid=<id>:<payload>] in .nornenv.
31362
+ - Keys are cached locally in .norn-cache/secret-keys.json (gitignored).
31363
+ - norn run auto-prompts once for missing kids when interactive.
31364
+ `);
31365
+ }
31366
+ async function handleKeygen(args) {
31367
+ const kid = getFlagValue(args, "--name", "-n");
31368
+ if (!kid) {
31369
+ console.error(`Error: Missing --name for keygen.`);
31370
+ return 1;
31371
+ }
31372
+ const key = generateSharedSecretKey();
31373
+ saveSecretKeyToCache(kid, key, process.cwd());
31374
+ console.log(`Generated shared key for kid '${kid}'.`);
31375
+ console.log(`Store this key in your team vault now:`);
31376
+ console.log(key);
31377
+ console.log(`Saved to local cache for current workspace.`);
31378
+ return 0;
31379
+ }
31380
+ async function handleImportKey(args) {
31381
+ const kid = getFlagValue(args, "--kid", "-k");
31382
+ if (!kid) {
31383
+ console.error(`Error: Missing --kid for import-key.`);
31384
+ return 1;
31385
+ }
31386
+ const directKey = getFlagValue(args, "--key");
31387
+ const key = directKey ?? await promptLine(`Enter shared key for kid '${kid}': `);
31388
+ if (!key) {
31389
+ console.error(`Error: No key provided.`);
31390
+ return 1;
31391
+ }
31392
+ saveSecretKeyToCache(kid, key, process.cwd());
31393
+ console.log(`Saved key for kid '${kid}' to local cache.`);
31394
+ return 0;
31395
+ }
31396
+ async function handleEncrypt(args) {
31397
+ const filePath = getFlagValue(args, "--file", "-f");
31398
+ const variableName = getFlagValue(args, "--var");
31399
+ const envName = getFlagValue(args, "--env");
31400
+ const explicitKid = getFlagValue(args, "--kid");
31401
+ if (!filePath || !variableName) {
31402
+ console.error(`Error: encrypt requires --file and --var.`);
31403
+ return 1;
31404
+ }
31405
+ const absoluteFilePath = path8.resolve(filePath);
31406
+ const { content, secret } = loadSecretLine(absoluteFilePath, variableName, envName);
31407
+ if (secret.encrypted) {
31408
+ console.error(`Error: Secret '${variableName}' is already encrypted. Use rotate instead.`);
31409
+ return 1;
31410
+ }
31411
+ const kid = explicitKid;
31412
+ if (!kid) {
31413
+ console.error(`Error: --kid is required when encrypting plaintext secret '${variableName}'.`);
31414
+ return 1;
31415
+ }
31416
+ const key = await ensureKeyForKid(kid, absoluteFilePath);
31417
+ if (!key) {
31418
+ console.error(`Error: Missing key for kid '${kid}'.`);
31419
+ return 1;
31420
+ }
31421
+ const encryptedValue = encryptSecretValue(secret.value, key, kid);
31422
+ const updatedContent = updateSecretLineValue(content, secret.lineNumber, encryptedValue);
31423
+ writeSecretLine(absoluteFilePath, updatedContent);
31424
+ console.log(`Encrypted secret '${variableName}' in ${absoluteFilePath}:${secret.lineNumber + 1}`);
31425
+ return 0;
31426
+ }
31427
+ async function handleRotate(args) {
31428
+ const filePath = getFlagValue(args, "--file", "-f");
31429
+ const variableName = getFlagValue(args, "--var");
31430
+ const envName = getFlagValue(args, "--env");
31431
+ const explicitKid = getFlagValue(args, "--kid");
31432
+ const explicitValue = getFlagValue(args, "--value");
31433
+ if (!filePath || !variableName) {
31434
+ console.error(`Error: rotate requires --file and --var.`);
31435
+ return 1;
31436
+ }
31437
+ const absoluteFilePath = path8.resolve(filePath);
31438
+ const { content, secret } = loadSecretLine(absoluteFilePath, variableName, envName);
31439
+ let kid = explicitKid;
31440
+ if (!kid && secret.encrypted) {
31441
+ const parsed = parseEncryptedSecretValue(secret.value);
31442
+ if (parsed.ok) {
31443
+ kid = parsed.parsed.kid;
31444
+ }
31445
+ }
31446
+ if (!kid) {
31447
+ console.error(`Error: Could not determine kid for '${variableName}'. Pass --kid.`);
31448
+ return 1;
31449
+ }
31450
+ const nextPlaintext = explicitValue ?? await promptLine(`Enter new plaintext value for '${variableName}': `);
31451
+ if (nextPlaintext === void 0) {
31452
+ console.error(`Error: No replacement value provided.`);
31453
+ return 1;
31454
+ }
31455
+ const key = await ensureKeyForKid(kid, absoluteFilePath);
31456
+ if (!key) {
31457
+ console.error(`Error: Missing key for kid '${kid}'.`);
31458
+ return 1;
31459
+ }
31460
+ const encryptedValue = encryptSecretValue(nextPlaintext, key, kid);
31461
+ const updatedContent = updateSecretLineValue(content, secret.lineNumber, encryptedValue);
31462
+ writeSecretLine(absoluteFilePath, updatedContent);
31463
+ console.log(`Rotated secret '${variableName}' in ${absoluteFilePath}:${secret.lineNumber + 1}`);
31464
+ return 0;
31465
+ }
31466
+ async function handleRekey(args) {
31467
+ const positional = args.filter((arg) => !arg.startsWith("-"));
31468
+ const targetPath = positional[0] ? path8.resolve(positional[0]) : process.cwd();
31469
+ const targetKid = getFlagValue(args, "--kid");
31470
+ const files = discoverNornenvFiles(targetPath);
31471
+ if (files.length === 0) {
31472
+ console.log(`No .nornenv files found under ${targetPath}`);
31473
+ return 0;
31474
+ }
31475
+ let updatedFiles = 0;
31476
+ let updatedSecrets = 0;
31477
+ for (const filePath of files) {
31478
+ const original = fs9.readFileSync(filePath, "utf8");
31479
+ const secretLines = extractSecretLines(original, filePath);
31480
+ if (secretLines.length === 0) {
31481
+ continue;
31482
+ }
31483
+ const replacements = /* @__PURE__ */ new Map();
31484
+ for (const secret of secretLines) {
31485
+ if (!secret.encrypted) {
31486
+ continue;
31487
+ }
31488
+ const parsed = parseEncryptedSecretValue(secret.value);
31489
+ if (!parsed.ok) {
31490
+ console.error(`Skipping malformed secret at ${filePath}:${secret.lineNumber + 1}: ${parsed.error}`);
31491
+ continue;
31492
+ }
31493
+ const sourceKid = parsed.parsed.kid;
31494
+ const decryptKey = await ensureKeyForKid(sourceKid, filePath);
31495
+ if (!decryptKey) {
31496
+ console.error(`Missing key for source kid '${sourceKid}' (${filePath}:${secret.lineNumber + 1})`);
31497
+ return 1;
31498
+ }
31499
+ let plaintext;
31500
+ try {
31501
+ plaintext = decryptSecretValue(secret.value, decryptKey);
31502
+ } catch (error) {
31503
+ const message = error instanceof Error ? error.message : String(error);
31504
+ console.error(`Failed to decrypt ${filePath}:${secret.lineNumber + 1} (${sourceKid}): ${message}`);
31505
+ return 1;
31506
+ }
31507
+ const destinationKid = targetKid ?? sourceKid;
31508
+ const encryptKey = destinationKid === sourceKid ? decryptKey : await ensureKeyForKid(destinationKid, filePath);
31509
+ if (!encryptKey) {
31510
+ console.error(`Missing key for destination kid '${destinationKid}'`);
31511
+ return 1;
31512
+ }
31513
+ replacements.set(secret.lineNumber, encryptSecretValue(plaintext, encryptKey, destinationKid));
31514
+ }
31515
+ if (replacements.size === 0) {
31516
+ continue;
31517
+ }
31518
+ let updated = original;
31519
+ const orderedLines = Array.from(replacements.keys()).sort((a, b) => a - b);
31520
+ for (const lineNumber of orderedLines) {
31521
+ const value = replacements.get(lineNumber);
31522
+ if (!value) {
31523
+ continue;
31524
+ }
31525
+ updated = updateSecretLineValue(updated, lineNumber, value);
31526
+ updatedSecrets += 1;
31527
+ }
31528
+ if (updated !== original) {
31529
+ fs9.writeFileSync(filePath, updated, "utf8");
31530
+ updatedFiles += 1;
31531
+ }
31532
+ }
31533
+ console.log(`Rekey complete. Updated ${updatedSecrets} secrets across ${updatedFiles} file(s).`);
31534
+ return 0;
31535
+ }
31536
+ async function handleAudit(args) {
31537
+ const positional = args.filter((arg) => !arg.startsWith("-"));
31538
+ const targetPath = positional[0] ? path8.resolve(positional[0]) : process.cwd();
31539
+ const files = discoverNornenvFiles(targetPath);
31540
+ if (files.length === 0) {
31541
+ console.log(`No .nornenv files found under ${targetPath}`);
31542
+ return 0;
31543
+ }
31544
+ const issues = [];
31545
+ for (const filePath of files) {
31546
+ const content = fs9.readFileSync(filePath, "utf8");
31547
+ const secrets = extractSecretLines(content, filePath);
31548
+ for (const secret of secrets) {
31549
+ if (!secret.encrypted) {
31550
+ issues.push(`${filePath}:${secret.lineNumber + 1} secret '${secret.name}' is plaintext.`);
31551
+ continue;
31552
+ }
31553
+ const parsed = parseEncryptedSecretValue(secret.value);
31554
+ if (!parsed.ok) {
31555
+ issues.push(`${filePath}:${secret.lineNumber + 1} malformed encrypted value (${parsed.error}).`);
31556
+ }
31557
+ }
31558
+ }
31559
+ if (issues.length === 0) {
31560
+ console.log(`Audit passed. All secret declarations are encrypted.`);
31561
+ return 0;
31562
+ }
31563
+ console.error(`Audit failed with ${issues.length} issue(s):`);
31564
+ for (const issue of issues) {
31565
+ console.error(` - ${issue}`);
31566
+ }
31567
+ return 1;
31568
+ }
31569
+ async function handleKeys() {
31570
+ const keys = listCachedSecretKeyIds(process.cwd());
31571
+ if (keys.length === 0) {
31572
+ console.log("No cached keys found for this workspace.");
31573
+ return 0;
31574
+ }
31575
+ console.log("Cached key ids:");
31576
+ for (const kid of keys) {
31577
+ console.log(` - ${kid}`);
31578
+ }
31579
+ return 0;
31580
+ }
31581
+ async function handleForget(args) {
31582
+ const kid = getFlagValue(args, "--kid", "-k");
31583
+ if (!kid) {
31584
+ console.error(`Error: forget requires --kid.`);
31585
+ return 1;
31586
+ }
31587
+ const removed = removeSecretKeyFromCache(kid, process.cwd());
31588
+ if (!removed) {
31589
+ console.log(`No cached key found for '${kid}'.`);
31590
+ return 0;
31591
+ }
31592
+ console.log(`Removed cached key '${kid}'.`);
31593
+ return 0;
31594
+ }
31595
+ async function handleSecretsCommand(args) {
31596
+ const [subcommand, ...rest] = args;
31597
+ switch (subcommand) {
31598
+ case "keygen":
31599
+ return handleKeygen(rest);
31600
+ case "import-key":
31601
+ return handleImportKey(rest);
31602
+ case "encrypt":
31603
+ return handleEncrypt(rest);
31604
+ case "rotate":
31605
+ return handleRotate(rest);
31606
+ case "rekey":
31607
+ return handleRekey(rest);
31608
+ case "audit":
31609
+ return handleAudit(rest);
31610
+ case "keys":
31611
+ return handleKeys();
31612
+ case "forget":
31613
+ return handleForget(rest);
31614
+ case "--help":
31615
+ case "-h":
31616
+ case void 0:
31617
+ printSecretsHelp();
31618
+ return 0;
31619
+ default:
31620
+ console.error(`Unknown secrets command: ${subcommand}`);
31621
+ printSecretsHelp();
31622
+ return 1;
31623
+ }
31624
+ }
31625
+ function printSecretResolutionErrors(errors, envFilePath) {
31626
+ for (const err of errors) {
31627
+ console.error(`Error: ${formatSecretError(err, envFilePath)}`);
31628
+ }
30828
31629
  }
30829
31630
 
30830
31631
  // src/cli.ts
30831
31632
  function formatNornenvErrorLocation(rootEnvFilePath, errorFilePath, line2) {
30832
- const baseDir = path5.dirname(rootEnvFilePath);
30833
- const relativePath = path5.relative(baseDir, errorFilePath);
30834
- const fileLabel = relativePath && relativePath !== "" ? relativePath : path5.basename(errorFilePath);
31633
+ const baseDir = path9.dirname(rootEnvFilePath);
31634
+ const relativePath = path9.relative(baseDir, errorFilePath);
31635
+ const fileLabel = relativePath && relativePath !== "" ? relativePath : path9.basename(errorFilePath);
30835
31636
  return line2 >= 0 ? `${fileLabel}:${line2 + 1}` : fileLabel;
30836
31637
  }
30837
31638
  function resolveEnvironmentForPath(targetPath, selectedEnv) {
@@ -30841,10 +31642,11 @@ function resolveEnvironmentForPath(targetPath, selectedEnv) {
30841
31642
  variables: {},
30842
31643
  secretNames: /* @__PURE__ */ new Set(),
30843
31644
  secretValues: /* @__PURE__ */ new Map(),
31645
+ secretErrors: [],
30844
31646
  availableEnvironments: []
30845
31647
  };
30846
31648
  }
30847
- const { config: envConfig, errors: importErrors } = loadAndResolveEnvFile(envFilePath);
31649
+ const { config: envConfig, errors: importErrors, secretErrors } = loadAndResolveEnvFile(envFilePath);
30848
31650
  for (const err of importErrors) {
30849
31651
  const location = formatNornenvErrorLocation(envFilePath, err.filePath, err.line);
30850
31652
  console.error(`Error in ${location}: ${err.message}`);
@@ -30865,6 +31667,7 @@ function resolveEnvironmentForPath(targetPath, selectedEnv) {
30865
31667
  variables,
30866
31668
  secretNames,
30867
31669
  secretValues,
31670
+ secretErrors: secretErrors.map((e) => e.message),
30868
31671
  availableEnvironments,
30869
31672
  envNotFound: selectedEnv
30870
31673
  };
@@ -30881,6 +31684,7 @@ function resolveEnvironmentForPath(targetPath, selectedEnv) {
30881
31684
  variables,
30882
31685
  secretNames,
30883
31686
  secretValues,
31687
+ secretErrors: secretErrors.map((e) => e.message),
30884
31688
  availableEnvironments
30885
31689
  };
30886
31690
  }
@@ -30910,10 +31714,10 @@ function generateTimestamp() {
30910
31714
  return `${year}-${month}-${day}-${hours}${minutes}${seconds}`;
30911
31715
  }
30912
31716
  function generateReportPaths(outputDir, inputFile, timestamp) {
30913
- const baseName = path5.basename(inputFile, path5.extname(inputFile));
31717
+ const baseName = path9.basename(inputFile, path9.extname(inputFile));
30914
31718
  return {
30915
- junitPath: path5.join(outputDir, `${baseName}-${timestamp}-results.xml`),
30916
- htmlPath: path5.join(outputDir, `${baseName}-${timestamp}-report.html`)
31719
+ junitPath: path9.join(outputDir, `${baseName}-${timestamp}-results.xml`),
31720
+ htmlPath: path9.join(outputDir, `${baseName}-${timestamp}-report.html`)
30917
31721
  };
30918
31722
  }
30919
31723
  function parseArgs(args) {
@@ -30924,7 +31728,8 @@ function parseArgs(args) {
30924
31728
  failOnError: true,
30925
31729
  noRedact: false,
30926
31730
  tagFilters: [],
30927
- tagsFilter: []
31731
+ tagsFilter: [],
31732
+ insecure: false
30928
31733
  };
30929
31734
  for (let i = 0; i < args.length; i++) {
30930
31735
  const arg = args[i];
@@ -30940,6 +31745,8 @@ function parseArgs(args) {
30940
31745
  options.env = args[++i];
30941
31746
  } else if (arg === "--timeout" || arg === "-t") {
30942
31747
  options.timeout = parseInt(args[++i], 10) * 1e3;
31748
+ } else if (arg === "--insecure") {
31749
+ options.insecure = true;
30943
31750
  } else if (arg === "--no-fail") {
30944
31751
  options.failOnError = false;
30945
31752
  } else if (arg === "--no-redact") {
@@ -30975,6 +31782,7 @@ function printHelp() {
30975
31782
  Norn CLI - Run HTTP requests and test sequences from .norn files
30976
31783
 
30977
31784
  Usage: norn <file.norn|directory> [options]
31785
+ norn secrets <command> [options]
30978
31786
 
30979
31787
  When given a directory, recursively discovers and runs all test sequences
30980
31788
  from .norn files within that directory and subdirectories.
@@ -30984,6 +31792,7 @@ Options:
30984
31792
  -r, --request <name> Run a specific named request (single file only)
30985
31793
  -e, --env <name> Use environment from .nornenv (e.g., dev, prod)
30986
31794
  -t, --timeout <sec> Request timeout in seconds (default: no timeout)
31795
+ --insecure Disable TLS certificate verification (dev/self-signed only)
30987
31796
  -j, --json Output results as JSON (for CI/CD)
30988
31797
  -v, --verbose Show detailed output (headers, request/response bodies)
30989
31798
  --no-fail Don't exit with error code on failed requests
@@ -31034,7 +31843,11 @@ Examples:
31034
31843
  norn tests/ -o ./reports # Generate reports for all tests
31035
31844
  norn api-tests.norn --junit results.xml # Generate JUnit report (explicit)
31036
31845
  norn api-tests.norn --html report.html # Generate HTML report (explicit)
31846
+ norn api-tests.norn --insecure # Allow self-signed/local TLS certs
31037
31847
  norn api-tests.norn --no-redact # Show all data (no redaction)
31848
+ norn secrets keygen --name team-main # Generate shared key and cache locally
31849
+ norn secrets import-key --kid team-main # Save shared key from your vault
31850
+ norn secrets audit . # Fail if plaintext secrets are committed
31038
31851
  `);
31039
31852
  }
31040
31853
  async function runSingleRequest(fileContent, variables, cookieJar, apiDefinitions, filePath, envContext) {
@@ -31172,9 +31985,9 @@ async function runSingleRequest(fileContent, variables, cookieJar, apiDefinition
31172
31985
  function discoverNornFiles(dirPath) {
31173
31986
  const files = [];
31174
31987
  function walkDir(currentPath) {
31175
- const entries = fs6.readdirSync(currentPath, { withFileTypes: true });
31988
+ const entries = fs10.readdirSync(currentPath, { withFileTypes: true });
31176
31989
  for (const entry of entries) {
31177
- const fullPath = path5.join(currentPath, entry.name);
31990
+ const fullPath = path9.join(currentPath, entry.name);
31178
31991
  if (entry.isDirectory()) {
31179
31992
  if (!entry.name.startsWith(".") && entry.name !== "node_modules") {
31180
31993
  walkDir(fullPath);
@@ -31194,7 +32007,7 @@ function countTestSequences(fileContent, tagFilterOptions) {
31194
32007
  return { total: testSequences.length, filtered };
31195
32008
  }
31196
32009
  async function loadTheoryFile(theoryPath, workingDir) {
31197
- const absolutePath = path5.resolve(workingDir, theoryPath);
32010
+ const absolutePath = path9.resolve(workingDir, theoryPath);
31198
32011
  const content = await fsPromises.readFile(absolutePath, "utf-8");
31199
32012
  return JSON.parse(content);
31200
32013
  }
@@ -31288,23 +32101,37 @@ async function runAllSequences(fileContent, variables, cookieJar, workingDir, ap
31288
32101
  return results;
31289
32102
  }
31290
32103
  async function main() {
31291
- const args = process.argv.slice(2);
32104
+ const rawArgs = process.argv.slice(2);
32105
+ if (rawArgs[0] === "secrets") {
32106
+ const exitCode = await handleSecretsCommand(rawArgs.slice(1));
32107
+ process.exit(exitCode);
32108
+ }
32109
+ const args = rawArgs[0] === "run" ? rawArgs.slice(1) : rawArgs;
31292
32110
  if (args.length === 0) {
31293
32111
  printHelp();
31294
32112
  process.exit(1);
31295
32113
  }
31296
32114
  const options = parseArgs(args);
32115
+ setVerifyTlsCertificates(!options.insecure);
32116
+ if (options.insecure) {
32117
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
32118
+ } else {
32119
+ delete process.env.NODE_TLS_REJECT_UNAUTHORIZED;
32120
+ }
31297
32121
  if (!options.file) {
31298
32122
  console.error("Error: No input file or directory specified");
31299
32123
  process.exit(1);
31300
32124
  }
31301
32125
  const colors = await initColors();
31302
- const inputPath = path5.resolve(options.file);
31303
- if (!fs6.existsSync(inputPath)) {
32126
+ if (options.insecure) {
32127
+ console.error(colors.warning("Warning: TLS certificate verification is disabled (--insecure). Use this only for local development."));
32128
+ }
32129
+ const inputPath = path9.resolve(options.file);
32130
+ if (!fs10.existsSync(inputPath)) {
31304
32131
  console.error(`Error: Path not found: ${inputPath}`);
31305
32132
  process.exit(1);
31306
32133
  }
31307
- const isDirectory = fs6.statSync(inputPath).isDirectory();
32134
+ const isDirectory = fs10.statSync(inputPath).isDirectory();
31308
32135
  let filesToRun;
31309
32136
  if (isDirectory) {
31310
32137
  filesToRun = discoverNornFiles(inputPath);
@@ -31342,6 +32169,15 @@ async function main() {
31342
32169
  }
31343
32170
  if (options.sequence || options.request) {
31344
32171
  const filePath = filesToRun[0];
32172
+ const secretUnlockResult = await ensureCliSecretsUnlocked(filePath);
32173
+ if (!secretUnlockResult.ok) {
32174
+ if (secretUnlockResult.errors.length > 0) {
32175
+ printSecretResolutionErrors(secretUnlockResult.errors, secretUnlockResult.envFilePath);
32176
+ } else {
32177
+ console.error("Unable to unlock encrypted secrets.");
32178
+ }
32179
+ process.exit(1);
32180
+ }
31345
32181
  const resolvedEnv = resolveEnvironmentForPath(filePath, options.env);
31346
32182
  const envValidationContext = buildCliEnvironmentValidationContext(resolvedEnv, options.env);
31347
32183
  if (resolvedEnv.envNotFound) {
@@ -31349,6 +32185,12 @@ async function main() {
31349
32185
  console.error(`Available environments: ${resolvedEnv.availableEnvironments.join(", ") || "none"}`);
31350
32186
  process.exit(1);
31351
32187
  }
32188
+ if (resolvedEnv.secretErrors.length > 0) {
32189
+ for (const error of resolvedEnv.secretErrors) {
32190
+ console.error(`Error: ${error}`);
32191
+ }
32192
+ process.exit(1);
32193
+ }
31352
32194
  if (!resolvedEnv.envFilePath && options.env) {
31353
32195
  console.error(colors.warning(`Warning: --env specified but no .nornenv file found`));
31354
32196
  } else if (resolvedEnv.envFilePath && options.env && options.verbose) {
@@ -31356,11 +32198,11 @@ async function main() {
31356
32198
  }
31357
32199
  mergeSecrets(combinedSecretNames, combinedSecretValues, resolvedEnv.secretNames, resolvedEnv.secretValues);
31358
32200
  const redaction2 = createRedactionOptions(combinedSecretNames, combinedSecretValues, !options.noRedact);
31359
- const fileContent = fs6.readFileSync(filePath, "utf-8");
32201
+ const fileContent = fs10.readFileSync(filePath, "utf-8");
31360
32202
  const fileVariables = extractFileLevelVariables(fileContent);
31361
32203
  const variables = { ...resolvedEnv.variables, ...fileVariables };
31362
32204
  const cookieJar = createCookieJar();
31363
- const workingDir = path5.dirname(filePath);
32205
+ const workingDir = path9.dirname(filePath);
31364
32206
  const importResult = await resolveImports(
31365
32207
  fileContent,
31366
32208
  workingDir,
@@ -31461,7 +32303,7 @@ ${fileContent}` : fileContent;
31461
32303
  let totalTestCount = 0;
31462
32304
  let filteredTestCount = 0;
31463
32305
  for (const filePath of filesToRun) {
31464
- const fileContent = fs6.readFileSync(filePath, "utf-8");
32306
+ const fileContent = fs10.readFileSync(filePath, "utf-8");
31465
32307
  const counts = countTestSequences(fileContent, tagFilterOptions);
31466
32308
  totalTestCount += counts.total;
31467
32309
  filteredTestCount += counts.filtered;
@@ -31480,6 +32322,15 @@ ${fileContent}` : fileContent;
31480
32322
  console.log("");
31481
32323
  }
31482
32324
  for (const filePath of filesToRun) {
32325
+ const secretUnlockResult = await ensureCliSecretsUnlocked(filePath);
32326
+ if (!secretUnlockResult.ok) {
32327
+ if (secretUnlockResult.errors.length > 0) {
32328
+ printSecretResolutionErrors(secretUnlockResult.errors, secretUnlockResult.envFilePath);
32329
+ } else {
32330
+ console.error("Unable to unlock encrypted secrets.");
32331
+ }
32332
+ process.exit(1);
32333
+ }
31483
32334
  const resolvedEnv = resolveEnvironmentForPath(filePath, options.env);
31484
32335
  const envValidationContext = buildCliEnvironmentValidationContext(resolvedEnv, options.env);
31485
32336
  if (resolvedEnv.envNotFound) {
@@ -31487,17 +32338,23 @@ ${fileContent}` : fileContent;
31487
32338
  console.error(`Available environments: ${resolvedEnv.availableEnvironments.join(", ") || "none"}`);
31488
32339
  process.exit(1);
31489
32340
  }
32341
+ if (resolvedEnv.secretErrors.length > 0) {
32342
+ for (const error of resolvedEnv.secretErrors) {
32343
+ console.error(`Error: ${error}`);
32344
+ }
32345
+ process.exit(1);
32346
+ }
31490
32347
  if (!resolvedEnv.envFilePath && options.env) {
31491
- const relPath = isDirectory ? path5.relative(inputPath, filePath) : path5.basename(filePath);
32348
+ const relPath = isDirectory ? path9.relative(inputPath, filePath) : path9.basename(filePath);
31492
32349
  console.error(colors.warning(`Warning: --env specified but no .nornenv file found for ${relPath}`));
31493
32350
  }
31494
32351
  mergeSecrets(combinedSecretNames, combinedSecretValues, resolvedEnv.secretNames, resolvedEnv.secretValues);
31495
32352
  const redaction2 = createRedactionOptions(combinedSecretNames, combinedSecretValues, !options.noRedact);
31496
- const fileContent = fs6.readFileSync(filePath, "utf-8");
32353
+ const fileContent = fs10.readFileSync(filePath, "utf-8");
31497
32354
  const fileVariables = extractFileLevelVariables(fileContent);
31498
32355
  const variables = { ...resolvedEnv.variables, ...fileVariables };
31499
32356
  const cookieJar = createCookieJar();
31500
- const workingDir = path5.dirname(filePath);
32357
+ const workingDir = path9.dirname(filePath);
31501
32358
  const importResult = await resolveImports(
31502
32359
  fileContent,
31503
32360
  workingDir,
@@ -31529,7 +32386,7 @@ ${fileContent}` : fileContent;
31529
32386
  continue;
31530
32387
  }
31531
32388
  if (isDirectory && options.output !== "json") {
31532
- const relPath = path5.relative(inputPath, filePath);
32389
+ const relPath = path9.relative(inputPath, filePath);
31533
32390
  console.log(colors.info(`
31534
32391
  \u2501\u2501\u2501 ${relPath} \u2501\u2501\u2501`));
31535
32392
  }
@@ -31573,7 +32430,7 @@ ${fileContent}` : fileContent;
31573
32430
  let htmlOutputPath = options.htmlOutput;
31574
32431
  if (options.outputDir) {
31575
32432
  const timestamp = generateTimestamp();
31576
- const baseName = isDirectory ? path5.basename(inputPath) : path5.basename(inputPath, path5.extname(inputPath));
32433
+ const baseName = isDirectory ? path9.basename(inputPath) : path9.basename(inputPath, path9.extname(inputPath));
31577
32434
  const generatedPaths = generateReportPaths(options.outputDir, baseName + ".norn", timestamp);
31578
32435
  if (!junitOutputPath) {
31579
32436
  junitOutputPath = generatedPaths.junitPath;
@@ -31581,12 +32438,12 @@ ${fileContent}` : fileContent;
31581
32438
  if (!htmlOutputPath) {
31582
32439
  htmlOutputPath = generatedPaths.htmlPath;
31583
32440
  }
31584
- if (!fs6.existsSync(options.outputDir)) {
31585
- fs6.mkdirSync(options.outputDir, { recursive: true });
32441
+ if (!fs10.existsSync(options.outputDir)) {
32442
+ fs10.mkdirSync(options.outputDir, { recursive: true });
31586
32443
  }
31587
32444
  }
31588
32445
  if (junitOutputPath) {
31589
- const suiteName = isDirectory ? path5.basename(inputPath) : path5.basename(inputPath, path5.extname(inputPath));
32446
+ const suiteName = isDirectory ? path9.basename(inputPath) : path9.basename(inputPath, path9.extname(inputPath));
31590
32447
  if (result.type === "request") {
31591
32448
  generateJUnitReportFromResponse(
31592
32449
  result.results[0],
@@ -31602,11 +32459,11 @@ ${fileContent}` : fileContent;
31602
32459
  console.log(colors.info(`JUnit report written to: ${junitOutputPath}`));
31603
32460
  }
31604
32461
  if (htmlOutputPath) {
31605
- const title = `Norn Test Report - ${path5.basename(inputPath)}`;
32462
+ const title = `Norn Test Report - ${path9.basename(inputPath)}`;
31606
32463
  if (result.type === "request") {
31607
32464
  generateHtmlReportFromResponse(
31608
32465
  result.results[0],
31609
- options.request || path5.basename(inputPath),
32466
+ options.request || path9.basename(inputPath),
31610
32467
  { outputPath: htmlOutputPath, redaction, title }
31611
32468
  );
31612
32469
  } else {