@forzalabs/remora 2.0.2 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1238,8 +1238,8 @@ var require_levels = __commonJS({
1238
1238
  var require_align = __commonJS({
1239
1239
  "../../node_modules/logform/align.js"(exports2, module2) {
1240
1240
  "use strict";
1241
- var format3 = require_format();
1242
- module2.exports = format3((info) => {
1241
+ var format4 = require_format();
1242
+ module2.exports = format4((info) => {
1243
1243
  info.message = ` ${info.message}`;
1244
1244
  return info;
1245
1245
  });
@@ -1250,9 +1250,9 @@ var require_align = __commonJS({
1250
1250
  var require_errors = __commonJS({
1251
1251
  "../../node_modules/logform/errors.js"(exports2, module2) {
1252
1252
  "use strict";
1253
- var format3 = require_format();
1253
+ var format4 = require_format();
1254
1254
  var { LEVEL, MESSAGE } = require_triple_beam();
1255
- module2.exports = format3((einfo, { stack, cause }) => {
1255
+ module2.exports = format4((einfo, { stack, cause }) => {
1256
1256
  if (einfo instanceof Error) {
1257
1257
  const info = Object.assign({}, einfo, {
1258
1258
  level: einfo.level,
@@ -1388,7 +1388,7 @@ var require_cli2 = __commonJS({
1388
1388
  var require_combine = __commonJS({
1389
1389
  "../../node_modules/logform/combine.js"(exports2, module2) {
1390
1390
  "use strict";
1391
- var format3 = require_format();
1391
+ var format4 = require_format();
1392
1392
  function cascade(formats) {
1393
1393
  if (!formats.every(isValidFormat)) {
1394
1394
  return;
@@ -1415,7 +1415,7 @@ var require_combine = __commonJS({
1415
1415
  return true;
1416
1416
  }
1417
1417
  module2.exports = (...formats) => {
1418
- const combinedFormat = format3(cascade(formats));
1418
+ const combinedFormat = format4(cascade(formats));
1419
1419
  const instance = combinedFormat();
1420
1420
  instance.Format = combinedFormat.Format;
1421
1421
  return instance;
@@ -2024,7 +2024,7 @@ ${originalIndentation}`;
2024
2024
  var require_json = __commonJS({
2025
2025
  "../../node_modules/logform/json.js"(exports2, module2) {
2026
2026
  "use strict";
2027
- var format3 = require_format();
2027
+ var format4 = require_format();
2028
2028
  var { MESSAGE } = require_triple_beam();
2029
2029
  var stringify = require_safe_stable_stringify();
2030
2030
  function replacer(key, value) {
@@ -2032,7 +2032,7 @@ var require_json = __commonJS({
2032
2032
  return value.toString();
2033
2033
  return value;
2034
2034
  }
2035
- module2.exports = format3((info, opts) => {
2035
+ module2.exports = format4((info, opts) => {
2036
2036
  const jsonStringify = stringify.configure(opts);
2037
2037
  info[MESSAGE] = jsonStringify(info, opts.replacer || replacer, opts.space);
2038
2038
  return info;
@@ -2044,8 +2044,8 @@ var require_json = __commonJS({
2044
2044
  var require_label = __commonJS({
2045
2045
  "../../node_modules/logform/label.js"(exports2, module2) {
2046
2046
  "use strict";
2047
- var format3 = require_format();
2048
- module2.exports = format3((info, opts) => {
2047
+ var format4 = require_format();
2048
+ module2.exports = format4((info, opts) => {
2049
2049
  if (opts.message) {
2050
2050
  info.message = `[${opts.label}] ${info.message}`;
2051
2051
  return info;
@@ -2060,10 +2060,10 @@ var require_label = __commonJS({
2060
2060
  var require_logstash = __commonJS({
2061
2061
  "../../node_modules/logform/logstash.js"(exports2, module2) {
2062
2062
  "use strict";
2063
- var format3 = require_format();
2063
+ var format4 = require_format();
2064
2064
  var { MESSAGE } = require_triple_beam();
2065
2065
  var jsonStringify = require_safe_stable_stringify();
2066
- module2.exports = format3((info) => {
2066
+ module2.exports = format4((info) => {
2067
2067
  const logstash = {};
2068
2068
  if (info.message) {
2069
2069
  logstash["@message"] = info.message;
@@ -2084,7 +2084,7 @@ var require_logstash = __commonJS({
2084
2084
  var require_metadata = __commonJS({
2085
2085
  "../../node_modules/logform/metadata.js"(exports2, module2) {
2086
2086
  "use strict";
2087
- var format3 = require_format();
2087
+ var format4 = require_format();
2088
2088
  function fillExcept(info, fillExceptKeys, metadataKey) {
2089
2089
  const savedKeys = fillExceptKeys.reduce((acc, key) => {
2090
2090
  acc[key] = info[key];
@@ -2109,7 +2109,7 @@ var require_metadata = __commonJS({
2109
2109
  }, {});
2110
2110
  return info;
2111
2111
  }
2112
- module2.exports = format3((info, opts = {}) => {
2112
+ module2.exports = format4((info, opts = {}) => {
2113
2113
  let metadataKey = "metadata";
2114
2114
  if (opts.key) {
2115
2115
  metadataKey = opts.key;
@@ -2253,9 +2253,9 @@ var require_ms = __commonJS({
2253
2253
  var require_ms2 = __commonJS({
2254
2254
  "../../node_modules/logform/ms.js"(exports2, module2) {
2255
2255
  "use strict";
2256
- var format3 = require_format();
2256
+ var format4 = require_format();
2257
2257
  var ms2 = require_ms();
2258
- module2.exports = format3((info) => {
2258
+ module2.exports = format4((info) => {
2259
2259
  const curr = +/* @__PURE__ */ new Date();
2260
2260
  exports2.diff = curr - (exports2.prevTime || curr);
2261
2261
  exports2.prevTime = curr;
@@ -2270,9 +2270,9 @@ var require_pretty_print = __commonJS({
2270
2270
  "../../node_modules/logform/pretty-print.js"(exports2, module2) {
2271
2271
  "use strict";
2272
2272
  var inspect = require("util").inspect;
2273
- var format3 = require_format();
2273
+ var format4 = require_format();
2274
2274
  var { LEVEL, MESSAGE, SPLAT } = require_triple_beam();
2275
- module2.exports = format3((info, opts = {}) => {
2275
+ module2.exports = format4((info, opts = {}) => {
2276
2276
  const stripped = Object.assign({}, info);
2277
2277
  delete stripped[LEVEL];
2278
2278
  delete stripped[MESSAGE];
@@ -2306,10 +2306,10 @@ var require_printf = __commonJS({
2306
2306
  var require_simple = __commonJS({
2307
2307
  "../../node_modules/logform/simple.js"(exports2, module2) {
2308
2308
  "use strict";
2309
- var format3 = require_format();
2309
+ var format4 = require_format();
2310
2310
  var { MESSAGE } = require_triple_beam();
2311
2311
  var jsonStringify = require_safe_stable_stringify();
2312
- module2.exports = format3((info) => {
2312
+ module2.exports = format4((info) => {
2313
2313
  const stringifiedRest = jsonStringify(Object.assign({}, info, {
2314
2314
  level: void 0,
2315
2315
  message: void 0,
@@ -2431,14 +2431,14 @@ function assign(origObj) {
2431
2431
  }
2432
2432
  return origObj;
2433
2433
  }
2434
- function parse(dateStr, format3, i18n) {
2434
+ function parse(dateStr, format4, i18n) {
2435
2435
  if (i18n === void 0) {
2436
2436
  i18n = {};
2437
2437
  }
2438
- if (typeof format3 !== "string") {
2438
+ if (typeof format4 !== "string") {
2439
2439
  throw new Error("Invalid format in fecha parse");
2440
2440
  }
2441
- format3 = globalMasks[format3] || format3;
2441
+ format4 = globalMasks[format4] || format4;
2442
2442
  if (dateStr.length > 1e3) {
2443
2443
  return null;
2444
2444
  }
@@ -2456,7 +2456,7 @@ function parse(dateStr, format3, i18n) {
2456
2456
  };
2457
2457
  var parseInfo = [];
2458
2458
  var literals = [];
2459
- var newFormat = format3.replace(literal, function($0, $1) {
2459
+ var newFormat = format4.replace(literal, function($0, $1) {
2460
2460
  literals.push(regexEscape($1));
2461
2461
  return "@@@";
2462
2462
  });
@@ -2818,8 +2818,8 @@ var require_timestamp = __commonJS({
2818
2818
  "../../node_modules/logform/timestamp.js"(exports2, module2) {
2819
2819
  "use strict";
2820
2820
  var fecha2 = (init_fecha(), __toCommonJS(fecha_exports));
2821
- var format3 = require_format();
2822
- module2.exports = format3((info, opts = {}) => {
2821
+ var format4 = require_format();
2822
+ module2.exports = format4((info, opts = {}) => {
2823
2823
  if (opts.format) {
2824
2824
  info.timestamp = typeof opts.format === "function" ? opts.format() : fecha2.format(/* @__PURE__ */ new Date(), opts.format);
2825
2825
  }
@@ -2839,9 +2839,9 @@ var require_uncolorize = __commonJS({
2839
2839
  "../../node_modules/logform/uncolorize.js"(exports2, module2) {
2840
2840
  "use strict";
2841
2841
  var colors = require_safe();
2842
- var format3 = require_format();
2842
+ var format4 = require_format();
2843
2843
  var { MESSAGE } = require_triple_beam();
2844
- module2.exports = format3((info, opts) => {
2844
+ module2.exports = format4((info, opts) => {
2845
2845
  if (opts.level !== false) {
2846
2846
  info.level = colors.strip(info.level);
2847
2847
  }
@@ -2860,10 +2860,10 @@ var require_uncolorize = __commonJS({
2860
2860
  var require_logform = __commonJS({
2861
2861
  "../../node_modules/logform/index.js"(exports2) {
2862
2862
  "use strict";
2863
- var format3 = exports2.format = require_format();
2863
+ var format4 = exports2.format = require_format();
2864
2864
  exports2.levels = require_levels();
2865
2865
  function exposeFormat(name, requireFormat) {
2866
- Object.defineProperty(format3, name, {
2866
+ Object.defineProperty(format4, name, {
2867
2867
  get() {
2868
2868
  return requireFormat();
2869
2869
  },
@@ -2928,17 +2928,17 @@ var require_logform = __commonJS({
2928
2928
  var require_common = __commonJS({
2929
2929
  "../../node_modules/winston/lib/winston/common.js"(exports2) {
2930
2930
  "use strict";
2931
- var { format: format3 } = require("util");
2931
+ var { format: format4 } = require("util");
2932
2932
  exports2.warn = {
2933
2933
  deprecated(prop) {
2934
2934
  return () => {
2935
- throw new Error(format3("{ %s } was removed in winston@3.0.0.", prop));
2935
+ throw new Error(format4("{ %s } was removed in winston@3.0.0.", prop));
2936
2936
  };
2937
2937
  },
2938
2938
  useFormat(prop) {
2939
2939
  return () => {
2940
2940
  throw new Error([
2941
- format3("{ %s } was removed in winston@3.0.0.", prop),
2941
+ format4("{ %s } was removed in winston@3.0.0.", prop),
2942
2942
  "Use a custom winston.format = winston.format(function) instead."
2943
2943
  ].join("\n"));
2944
2944
  };
@@ -4203,14 +4203,14 @@ var require_from = __commonJS({
4203
4203
  return (hint === "string" ? String : Number)(input);
4204
4204
  }
4205
4205
  var ERR_INVALID_ARG_TYPE = require_errors2().codes.ERR_INVALID_ARG_TYPE;
4206
- function from(Readable7, iterable, opts) {
4206
+ function from(Readable8, iterable, opts) {
4207
4207
  var iterator;
4208
4208
  if (iterable && typeof iterable.next === "function") {
4209
4209
  iterator = iterable;
4210
4210
  } else if (iterable && iterable[Symbol.asyncIterator]) iterator = iterable[Symbol.asyncIterator]();
4211
4211
  else if (iterable && iterable[Symbol.iterator]) iterator = iterable[Symbol.iterator]();
4212
4212
  else throw new ERR_INVALID_ARG_TYPE("iterable", ["Iterable"], iterable);
4213
- var readable = new Readable7(_objectSpread({
4213
+ var readable = new Readable8(_objectSpread({
4214
4214
  objectMode: true
4215
4215
  }, opts));
4216
4216
  var reading = false;
@@ -4250,9 +4250,9 @@ var require_from = __commonJS({
4250
4250
  var require_stream_readable = __commonJS({
4251
4251
  "../../node_modules/readable-stream/lib/_stream_readable.js"(exports2, module2) {
4252
4252
  "use strict";
4253
- module2.exports = Readable7;
4253
+ module2.exports = Readable8;
4254
4254
  var Duplex;
4255
- Readable7.ReadableState = ReadableState;
4255
+ Readable8.ReadableState = ReadableState;
4256
4256
  var EE = require("events").EventEmitter;
4257
4257
  var EElistenerCount = function EElistenerCount2(emitter, type) {
4258
4258
  return emitter.listeners(type).length;
@@ -4287,7 +4287,7 @@ var require_stream_readable = __commonJS({
4287
4287
  var StringDecoder;
4288
4288
  var createReadableStreamAsyncIterator;
4289
4289
  var from;
4290
- require_inherits()(Readable7, Stream);
4290
+ require_inherits()(Readable8, Stream);
4291
4291
  var errorOrDestroy = destroyImpl.errorOrDestroy;
4292
4292
  var kProxyEvents = ["error", "close", "destroy", "pause", "resume"];
4293
4293
  function prependListener(emitter, event, fn) {
@@ -4331,9 +4331,9 @@ var require_stream_readable = __commonJS({
4331
4331
  this.encoding = options.encoding;
4332
4332
  }
4333
4333
  }
4334
- function Readable7(options) {
4334
+ function Readable8(options) {
4335
4335
  Duplex = Duplex || require_stream_duplex();
4336
- if (!(this instanceof Readable7)) return new Readable7(options);
4336
+ if (!(this instanceof Readable8)) return new Readable8(options);
4337
4337
  var isDuplex = this instanceof Duplex;
4338
4338
  this._readableState = new ReadableState(options, this, isDuplex);
4339
4339
  this.readable = true;
@@ -4343,7 +4343,7 @@ var require_stream_readable = __commonJS({
4343
4343
  }
4344
4344
  Stream.call(this);
4345
4345
  }
4346
- Object.defineProperty(Readable7.prototype, "destroyed", {
4346
+ Object.defineProperty(Readable8.prototype, "destroyed", {
4347
4347
  // making it explicit this property is not enumerable
4348
4348
  // because otherwise some prototype manipulation in
4349
4349
  // userland will fail
@@ -4361,12 +4361,12 @@ var require_stream_readable = __commonJS({
4361
4361
  this._readableState.destroyed = value;
4362
4362
  }
4363
4363
  });
4364
- Readable7.prototype.destroy = destroyImpl.destroy;
4365
- Readable7.prototype._undestroy = destroyImpl.undestroy;
4366
- Readable7.prototype._destroy = function(err2, cb) {
4364
+ Readable8.prototype.destroy = destroyImpl.destroy;
4365
+ Readable8.prototype._undestroy = destroyImpl.undestroy;
4366
+ Readable8.prototype._destroy = function(err2, cb) {
4367
4367
  cb(err2);
4368
4368
  };
4369
- Readable7.prototype.push = function(chunk, encoding) {
4369
+ Readable8.prototype.push = function(chunk, encoding) {
4370
4370
  var state2 = this._readableState;
4371
4371
  var skipChunkCheck;
4372
4372
  if (!state2.objectMode) {
@@ -4383,7 +4383,7 @@ var require_stream_readable = __commonJS({
4383
4383
  }
4384
4384
  return readableAddChunk(this, chunk, encoding, false, skipChunkCheck);
4385
4385
  };
4386
- Readable7.prototype.unshift = function(chunk) {
4386
+ Readable8.prototype.unshift = function(chunk) {
4387
4387
  return readableAddChunk(this, chunk, null, true, false);
4388
4388
  };
4389
4389
  function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) {
@@ -4444,10 +4444,10 @@ var require_stream_readable = __commonJS({
4444
4444
  }
4445
4445
  return er2;
4446
4446
  }
4447
- Readable7.prototype.isPaused = function() {
4447
+ Readable8.prototype.isPaused = function() {
4448
4448
  return this._readableState.flowing === false;
4449
4449
  };
4450
- Readable7.prototype.setEncoding = function(enc) {
4450
+ Readable8.prototype.setEncoding = function(enc) {
4451
4451
  if (!StringDecoder) StringDecoder = require_string_decoder().StringDecoder;
4452
4452
  var decoder = new StringDecoder(enc);
4453
4453
  this._readableState.decoder = decoder;
@@ -4493,7 +4493,7 @@ var require_stream_readable = __commonJS({
4493
4493
  }
4494
4494
  return state2.length;
4495
4495
  }
4496
- Readable7.prototype.read = function(n4) {
4496
+ Readable8.prototype.read = function(n4) {
4497
4497
  debug("read", n4);
4498
4498
  n4 = parseInt(n4, 10);
4499
4499
  var state2 = this._readableState;
@@ -4602,10 +4602,10 @@ var require_stream_readable = __commonJS({
4602
4602
  }
4603
4603
  state2.readingMore = false;
4604
4604
  }
4605
- Readable7.prototype._read = function(n4) {
4605
+ Readable8.prototype._read = function(n4) {
4606
4606
  errorOrDestroy(this, new ERR_METHOD_NOT_IMPLEMENTED("_read()"));
4607
4607
  };
4608
- Readable7.prototype.pipe = function(dest, pipeOpts) {
4608
+ Readable8.prototype.pipe = function(dest, pipeOpts) {
4609
4609
  var src = this;
4610
4610
  var state2 = this._readableState;
4611
4611
  switch (state2.pipesCount) {
@@ -4708,7 +4708,7 @@ var require_stream_readable = __commonJS({
4708
4708
  }
4709
4709
  };
4710
4710
  }
4711
- Readable7.prototype.unpipe = function(dest) {
4711
+ Readable8.prototype.unpipe = function(dest) {
4712
4712
  var state2 = this._readableState;
4713
4713
  var unpipeInfo = {
4714
4714
  hasUnpiped: false
@@ -4742,7 +4742,7 @@ var require_stream_readable = __commonJS({
4742
4742
  dest.emit("unpipe", this, unpipeInfo);
4743
4743
  return this;
4744
4744
  };
4745
- Readable7.prototype.on = function(ev, fn) {
4745
+ Readable8.prototype.on = function(ev, fn) {
4746
4746
  var res = Stream.prototype.on.call(this, ev, fn);
4747
4747
  var state2 = this._readableState;
4748
4748
  if (ev === "data") {
@@ -4763,15 +4763,15 @@ var require_stream_readable = __commonJS({
4763
4763
  }
4764
4764
  return res;
4765
4765
  };
4766
- Readable7.prototype.addListener = Readable7.prototype.on;
4767
- Readable7.prototype.removeListener = function(ev, fn) {
4766
+ Readable8.prototype.addListener = Readable8.prototype.on;
4767
+ Readable8.prototype.removeListener = function(ev, fn) {
4768
4768
  var res = Stream.prototype.removeListener.call(this, ev, fn);
4769
4769
  if (ev === "readable") {
4770
4770
  process.nextTick(updateReadableListening, this);
4771
4771
  }
4772
4772
  return res;
4773
4773
  };
4774
- Readable7.prototype.removeAllListeners = function(ev) {
4774
+ Readable8.prototype.removeAllListeners = function(ev) {
4775
4775
  var res = Stream.prototype.removeAllListeners.apply(this, arguments);
4776
4776
  if (ev === "readable" || ev === void 0) {
4777
4777
  process.nextTick(updateReadableListening, this);
@@ -4791,7 +4791,7 @@ var require_stream_readable = __commonJS({
4791
4791
  debug("readable nexttick read 0");
4792
4792
  self2.read(0);
4793
4793
  }
4794
- Readable7.prototype.resume = function() {
4794
+ Readable8.prototype.resume = function() {
4795
4795
  var state2 = this._readableState;
4796
4796
  if (!state2.flowing) {
4797
4797
  debug("resume");
@@ -4817,7 +4817,7 @@ var require_stream_readable = __commonJS({
4817
4817
  flow(stream);
4818
4818
  if (state2.flowing && !state2.reading) stream.read(0);
4819
4819
  }
4820
- Readable7.prototype.pause = function() {
4820
+ Readable8.prototype.pause = function() {
4821
4821
  debug("call pause flowing=%j", this._readableState.flowing);
4822
4822
  if (this._readableState.flowing !== false) {
4823
4823
  debug("pause");
@@ -4832,7 +4832,7 @@ var require_stream_readable = __commonJS({
4832
4832
  debug("flow", state2.flowing);
4833
4833
  while (state2.flowing && stream.read() !== null) ;
4834
4834
  }
4835
- Readable7.prototype.wrap = function(stream) {
4835
+ Readable8.prototype.wrap = function(stream) {
4836
4836
  var _this = this;
4837
4837
  var state2 = this._readableState;
4838
4838
  var paused = false;
@@ -4877,14 +4877,14 @@ var require_stream_readable = __commonJS({
4877
4877
  return this;
4878
4878
  };
4879
4879
  if (typeof Symbol === "function") {
4880
- Readable7.prototype[Symbol.asyncIterator] = function() {
4880
+ Readable8.prototype[Symbol.asyncIterator] = function() {
4881
4881
  if (createReadableStreamAsyncIterator === void 0) {
4882
4882
  createReadableStreamAsyncIterator = require_async_iterator();
4883
4883
  }
4884
4884
  return createReadableStreamAsyncIterator(this);
4885
4885
  };
4886
4886
  }
4887
- Object.defineProperty(Readable7.prototype, "readableHighWaterMark", {
4887
+ Object.defineProperty(Readable8.prototype, "readableHighWaterMark", {
4888
4888
  // making it explicit this property is not enumerable
4889
4889
  // because otherwise some prototype manipulation in
4890
4890
  // userland will fail
@@ -4893,7 +4893,7 @@ var require_stream_readable = __commonJS({
4893
4893
  return this._readableState.highWaterMark;
4894
4894
  }
4895
4895
  });
4896
- Object.defineProperty(Readable7.prototype, "readableBuffer", {
4896
+ Object.defineProperty(Readable8.prototype, "readableBuffer", {
4897
4897
  // making it explicit this property is not enumerable
4898
4898
  // because otherwise some prototype manipulation in
4899
4899
  // userland will fail
@@ -4902,7 +4902,7 @@ var require_stream_readable = __commonJS({
4902
4902
  return this._readableState && this._readableState.buffer;
4903
4903
  }
4904
4904
  });
4905
- Object.defineProperty(Readable7.prototype, "readableFlowing", {
4905
+ Object.defineProperty(Readable8.prototype, "readableFlowing", {
4906
4906
  // making it explicit this property is not enumerable
4907
4907
  // because otherwise some prototype manipulation in
4908
4908
  // userland will fail
@@ -4916,8 +4916,8 @@ var require_stream_readable = __commonJS({
4916
4916
  }
4917
4917
  }
4918
4918
  });
4919
- Readable7._fromList = fromList;
4920
- Object.defineProperty(Readable7.prototype, "readableLength", {
4919
+ Readable8._fromList = fromList;
4920
+ Object.defineProperty(Readable8.prototype, "readableLength", {
4921
4921
  // making it explicit this property is not enumerable
4922
4922
  // because otherwise some prototype manipulation in
4923
4923
  // userland will fail
@@ -4963,11 +4963,11 @@ var require_stream_readable = __commonJS({
4963
4963
  }
4964
4964
  }
4965
4965
  if (typeof Symbol === "function") {
4966
- Readable7.from = function(iterable, opts) {
4966
+ Readable8.from = function(iterable, opts) {
4967
4967
  if (from === void 0) {
4968
4968
  from = require_from();
4969
4969
  }
4970
- return from(Readable7, iterable, opts);
4970
+ return from(Readable8, iterable, opts);
4971
4971
  };
4972
4972
  }
4973
4973
  function indexOf(xs2, x2) {
@@ -4989,9 +4989,9 @@ var require_stream_duplex = __commonJS({
4989
4989
  return keys2;
4990
4990
  };
4991
4991
  module2.exports = Duplex;
4992
- var Readable7 = require_stream_readable();
4992
+ var Readable8 = require_stream_readable();
4993
4993
  var Writable2 = require_stream_writable();
4994
- require_inherits()(Duplex, Readable7);
4994
+ require_inherits()(Duplex, Readable8);
4995
4995
  {
4996
4996
  keys = objectKeys(Writable2.prototype);
4997
4997
  for (v3 = 0; v3 < keys.length; v3++) {
@@ -5004,7 +5004,7 @@ var require_stream_duplex = __commonJS({
5004
5004
  var v3;
5005
5005
  function Duplex(options) {
5006
5006
  if (!(this instanceof Duplex)) return new Duplex(options);
5007
- Readable7.call(this, options);
5007
+ Readable8.call(this, options);
5008
5008
  Writable2.call(this, options);
5009
5009
  this.allowHalfOpen = true;
5010
5010
  if (options) {
@@ -6546,7 +6546,7 @@ var require_pipeline = __commonJS({
6546
6546
  if (typeof streams[streams.length - 1] !== "function") return noop;
6547
6547
  return streams.pop();
6548
6548
  }
6549
- function pipeline5() {
6549
+ function pipeline6() {
6550
6550
  for (var _len = arguments.length, streams = new Array(_len), _key = 0; _key < _len; _key++) {
6551
6551
  streams[_key] = arguments[_key];
6552
6552
  }
@@ -6569,7 +6569,7 @@ var require_pipeline = __commonJS({
6569
6569
  });
6570
6570
  return streams.reduce(pipe);
6571
6571
  }
6572
- module2.exports = pipeline5;
6572
+ module2.exports = pipeline6;
6573
6573
  }
6574
6574
  });
6575
6575
 
@@ -7807,15 +7807,15 @@ var require_index_cjs = __commonJS({
7807
7807
  };
7808
7808
  }
7809
7809
  function wrapConversion(toModel, graph) {
7810
- const path20 = [graph[toModel].parent, toModel];
7810
+ const path21 = [graph[toModel].parent, toModel];
7811
7811
  let fn = convert$1[graph[toModel].parent][toModel];
7812
7812
  let cur = graph[toModel].parent;
7813
7813
  while (graph[cur].parent) {
7814
- path20.unshift(graph[cur].parent);
7814
+ path21.unshift(graph[cur].parent);
7815
7815
  fn = link(convert$1[graph[cur].parent][cur], fn);
7816
7816
  cur = graph[cur].parent;
7817
7817
  }
7818
- fn.conversion = path20;
7818
+ fn.conversion = path21;
7819
7819
  return fn;
7820
7820
  }
7821
7821
  function route(fromModel) {
@@ -8445,7 +8445,7 @@ var require_node2 = __commonJS({
8445
8445
  var require_tail_file = __commonJS({
8446
8446
  "../../node_modules/winston/lib/winston/tail-file.js"(exports2, module2) {
8447
8447
  "use strict";
8448
- var fs23 = require("fs");
8448
+ var fs24 = require("fs");
8449
8449
  var { StringDecoder } = require("string_decoder");
8450
8450
  var { Stream } = require_readable();
8451
8451
  function noop() {
@@ -8466,7 +8466,7 @@ var require_tail_file = __commonJS({
8466
8466
  stream.emit("end");
8467
8467
  stream.emit("close");
8468
8468
  };
8469
- fs23.open(options.file, "a+", "0644", (err2, fd) => {
8469
+ fs24.open(options.file, "a+", "0644", (err2, fd) => {
8470
8470
  if (err2) {
8471
8471
  if (!iter) {
8472
8472
  stream.emit("error", err2);
@@ -8478,10 +8478,10 @@ var require_tail_file = __commonJS({
8478
8478
  }
8479
8479
  (function read() {
8480
8480
  if (stream.destroyed) {
8481
- fs23.close(fd, noop);
8481
+ fs24.close(fd, noop);
8482
8482
  return;
8483
8483
  }
8484
- return fs23.read(fd, buffer, 0, buffer.length, pos, (error, bytes) => {
8484
+ return fs24.read(fd, buffer, 0, buffer.length, pos, (error, bytes) => {
8485
8485
  if (error) {
8486
8486
  if (!iter) {
8487
8487
  stream.emit("error", error);
@@ -8540,8 +8540,8 @@ var require_tail_file = __commonJS({
8540
8540
  var require_file = __commonJS({
8541
8541
  "../../node_modules/winston/lib/winston/transports/file.js"(exports2, module2) {
8542
8542
  "use strict";
8543
- var fs23 = require("fs");
8544
- var path20 = require("path");
8543
+ var fs24 = require("fs");
8544
+ var path21 = require("path");
8545
8545
  var asyncSeries = require_series();
8546
8546
  var zlib3 = require("zlib");
8547
8547
  var { MESSAGE } = require_triple_beam();
@@ -8571,14 +8571,14 @@ var require_file = __commonJS({
8571
8571
  this._onError = this._onError.bind(this);
8572
8572
  if (options.filename || options.dirname) {
8573
8573
  throwIf("filename or dirname", "stream");
8574
- this._basename = this.filename = options.filename ? path20.basename(options.filename) : "winston.log";
8575
- this.dirname = options.dirname || path20.dirname(options.filename);
8574
+ this._basename = this.filename = options.filename ? path21.basename(options.filename) : "winston.log";
8575
+ this.dirname = options.dirname || path21.dirname(options.filename);
8576
8576
  this.options = options.options || { flags: "a" };
8577
8577
  } else if (options.stream) {
8578
8578
  console.warn("options.stream will be removed in winston@4. Use winston.transports.Stream");
8579
8579
  throwIf("stream", "filename", "maxsize");
8580
8580
  this._dest = this._stream.pipe(this._setupStream(options.stream));
8581
- this.dirname = path20.dirname(this._dest.path);
8581
+ this.dirname = path21.dirname(this._dest.path);
8582
8582
  } else {
8583
8583
  throw new Error("Cannot log to file without filename or stream.");
8584
8584
  }
@@ -8741,11 +8741,11 @@ var require_file = __commonJS({
8741
8741
  options = {};
8742
8742
  }
8743
8743
  options = normalizeQuery(options);
8744
- const file = path20.join(this.dirname, this.filename);
8744
+ const file = path21.join(this.dirname, this.filename);
8745
8745
  let buff = "";
8746
8746
  let results = [];
8747
8747
  let row = 0;
8748
- const stream = fs23.createReadStream(file, {
8748
+ const stream = fs24.createReadStream(file, {
8749
8749
  encoding: "utf8"
8750
8750
  });
8751
8751
  stream.on("error", (err2) => {
@@ -8846,7 +8846,7 @@ var require_file = __commonJS({
8846
8846
  * TODO: Refactor me.
8847
8847
  */
8848
8848
  stream(options = {}) {
8849
- const file = path20.join(this.dirname, this.filename);
8849
+ const file = path21.join(this.dirname, this.filename);
8850
8850
  const stream = new Stream();
8851
8851
  const tail = {
8852
8852
  file,
@@ -8896,8 +8896,8 @@ var require_file = __commonJS({
8896
8896
  */
8897
8897
  stat(callback) {
8898
8898
  const target = this._getFile();
8899
- const fullpath = path20.join(this.dirname, target);
8900
- fs23.stat(fullpath, (err2, stat) => {
8899
+ const fullpath = path21.join(this.dirname, target);
8900
+ fs24.stat(fullpath, (err2, stat) => {
8901
8901
  if (err2 && err2.code === "ENOENT") {
8902
8902
  debug("ENOENT\xA0ok", fullpath);
8903
8903
  this.filename = target;
@@ -9000,9 +9000,9 @@ var require_file = __commonJS({
9000
9000
  * @returns {WritableStream} Stream that writes to disk for the active file.
9001
9001
  */
9002
9002
  _createStream(source) {
9003
- const fullpath = path20.join(this.dirname, this.filename);
9003
+ const fullpath = path21.join(this.dirname, this.filename);
9004
9004
  debug("create stream start", fullpath, this.options);
9005
- const dest = fs23.createWriteStream(fullpath, this.options).on("error", (err2) => debug(err2)).on("close", () => debug("close", dest.path, dest.bytesWritten)).on("open", () => {
9005
+ const dest = fs24.createWriteStream(fullpath, this.options).on("error", (err2) => debug(err2)).on("close", () => debug("close", dest.path, dest.bytesWritten)).on("open", () => {
9006
9006
  debug("file open ok", fullpath);
9007
9007
  this.emit("open", fullpath);
9008
9008
  source.pipe(dest);
@@ -9025,16 +9025,16 @@ var require_file = __commonJS({
9025
9025
  */
9026
9026
  _incFile(callback) {
9027
9027
  debug("_incFile", this.filename);
9028
- const ext = path20.extname(this._basename);
9029
- const basename = path20.basename(this._basename, ext);
9028
+ const ext = path21.extname(this._basename);
9029
+ const basename = path21.basename(this._basename, ext);
9030
9030
  const tasks = [];
9031
9031
  if (this.zippedArchive) {
9032
9032
  tasks.push(
9033
9033
  function(cb) {
9034
9034
  const num = this._created > 0 && !this.tailable ? this._created : "";
9035
9035
  this._compressFile(
9036
- path20.join(this.dirname, `${basename}${num}${ext}`),
9037
- path20.join(this.dirname, `${basename}${num}${ext}.gz`),
9036
+ path21.join(this.dirname, `${basename}${num}${ext}`),
9037
+ path21.join(this.dirname, `${basename}${num}${ext}.gz`),
9038
9038
  cb
9039
9039
  );
9040
9040
  }.bind(this)
@@ -9059,8 +9059,8 @@ var require_file = __commonJS({
9059
9059
  * @private
9060
9060
  */
9061
9061
  _getFile() {
9062
- const ext = path20.extname(this._basename);
9063
- const basename = path20.basename(this._basename, ext);
9062
+ const ext = path21.extname(this._basename);
9063
+ const basename = path21.basename(this._basename, ext);
9064
9064
  const isRotation = this.rotationFormat ? this.rotationFormat() : this._created;
9065
9065
  return !this.tailable && this._created ? `${basename}${isRotation}${ext}` : `${basename}${ext}`;
9066
9066
  }
@@ -9080,8 +9080,8 @@ var require_file = __commonJS({
9080
9080
  const isOldest = oldest !== 0 ? oldest : "";
9081
9081
  const isZipped = this.zippedArchive ? ".gz" : "";
9082
9082
  const filePath = `${basename}${isOldest}${ext}${isZipped}`;
9083
- const target = path20.join(this.dirname, filePath);
9084
- fs23.unlink(target, callback);
9083
+ const target = path21.join(this.dirname, filePath);
9084
+ fs24.unlink(target, callback);
9085
9085
  }
9086
9086
  /**
9087
9087
  * Roll files forward based on integer, up to maxFiles. e.g. if base if
@@ -9103,20 +9103,20 @@ var require_file = __commonJS({
9103
9103
  for (let x2 = this.maxFiles - 1; x2 > 1; x2--) {
9104
9104
  tasks.push(function(i6, cb) {
9105
9105
  let fileName = `${basename}${i6 - 1}${ext}${isZipped}`;
9106
- const tmppath = path20.join(this.dirname, fileName);
9107
- fs23.exists(tmppath, (exists) => {
9106
+ const tmppath = path21.join(this.dirname, fileName);
9107
+ fs24.exists(tmppath, (exists) => {
9108
9108
  if (!exists) {
9109
9109
  return cb(null);
9110
9110
  }
9111
9111
  fileName = `${basename}${i6}${ext}${isZipped}`;
9112
- fs23.rename(tmppath, path20.join(this.dirname, fileName), cb);
9112
+ fs24.rename(tmppath, path21.join(this.dirname, fileName), cb);
9113
9113
  });
9114
9114
  }.bind(this, x2));
9115
9115
  }
9116
9116
  asyncSeries(tasks, () => {
9117
- fs23.rename(
9118
- path20.join(this.dirname, `${basename}${ext}${isZipped}`),
9119
- path20.join(this.dirname, `${basename}1${ext}${isZipped}`),
9117
+ fs24.rename(
9118
+ path21.join(this.dirname, `${basename}${ext}${isZipped}`),
9119
+ path21.join(this.dirname, `${basename}1${ext}${isZipped}`),
9120
9120
  callback
9121
9121
  );
9122
9122
  });
@@ -9130,22 +9130,22 @@ var require_file = __commonJS({
9130
9130
  * @private
9131
9131
  */
9132
9132
  _compressFile(src, dest, callback) {
9133
- fs23.access(src, fs23.F_OK, (err2) => {
9133
+ fs24.access(src, fs24.F_OK, (err2) => {
9134
9134
  if (err2) {
9135
9135
  return callback();
9136
9136
  }
9137
9137
  var gzip = zlib3.createGzip();
9138
- var inp = fs23.createReadStream(src);
9139
- var out = fs23.createWriteStream(dest);
9138
+ var inp = fs24.createReadStream(src);
9139
+ var out = fs24.createWriteStream(dest);
9140
9140
  out.on("finish", () => {
9141
- fs23.unlink(src, callback);
9141
+ fs24.unlink(src, callback);
9142
9142
  });
9143
9143
  inp.pipe(gzip).pipe(out);
9144
9144
  });
9145
9145
  }
9146
9146
  _createLogDirIfNotExist(dirPath) {
9147
- if (!fs23.existsSync(dirPath)) {
9148
- fs23.mkdirSync(dirPath, { recursive: true });
9147
+ if (!fs24.existsSync(dirPath)) {
9148
+ fs24.mkdirSync(dirPath, { recursive: true });
9149
9149
  }
9150
9150
  }
9151
9151
  };
@@ -9229,9 +9229,9 @@ var require_http = __commonJS({
9229
9229
  };
9230
9230
  const auth = options.params.auth || null;
9231
9231
  delete options.params.auth;
9232
- const path20 = options.params.path || null;
9232
+ const path21 = options.params.path || null;
9233
9233
  delete options.params.path;
9234
- this._request(options, auth, path20, (err2, res, body) => {
9234
+ this._request(options, auth, path21, (err2, res, body) => {
9235
9235
  if (res && res.statusCode !== 200) {
9236
9236
  err2 = new Error(`Invalid HTTP Status Code: ${res.statusCode}`);
9237
9237
  }
@@ -9259,12 +9259,12 @@ var require_http = __commonJS({
9259
9259
  method: "stream",
9260
9260
  params: options
9261
9261
  };
9262
- const path20 = options.params.path || null;
9262
+ const path21 = options.params.path || null;
9263
9263
  delete options.params.path;
9264
9264
  const auth = options.params.auth || null;
9265
9265
  delete options.params.auth;
9266
9266
  let buff = "";
9267
- const req = this._request(options, auth, path20);
9267
+ const req = this._request(options, auth, path21);
9268
9268
  stream.destroy = () => req.destroy();
9269
9269
  req.on("data", (data) => {
9270
9270
  data = (buff + data).split(/\n+/);
@@ -9290,14 +9290,14 @@ var require_http = __commonJS({
9290
9290
  * @param {string} path - request path
9291
9291
  * @param {function} callback - Continuation to respond to when complete.
9292
9292
  */
9293
- _request(options, auth, path20, callback) {
9293
+ _request(options, auth, path21, callback) {
9294
9294
  options = options || {};
9295
9295
  auth = auth || this.auth;
9296
- path20 = path20 || this.path || "";
9296
+ path21 = path21 || this.path || "";
9297
9297
  if (this.batch) {
9298
- this._doBatch(options, callback, auth, path20);
9298
+ this._doBatch(options, callback, auth, path21);
9299
9299
  } else {
9300
- this._doRequest(options, callback, auth, path20);
9300
+ this._doRequest(options, callback, auth, path21);
9301
9301
  }
9302
9302
  }
9303
9303
  /**
@@ -9307,18 +9307,18 @@ var require_http = __commonJS({
9307
9307
  * @param {Object?} auth - authentication options
9308
9308
  * @param {string} path - request path
9309
9309
  */
9310
- _doBatch(options, callback, auth, path20) {
9310
+ _doBatch(options, callback, auth, path21) {
9311
9311
  this.batchOptions.push(options);
9312
9312
  if (this.batchOptions.length === 1) {
9313
9313
  const me3 = this;
9314
9314
  this.batchCallback = callback;
9315
9315
  this.batchTimeoutID = setTimeout(function() {
9316
9316
  me3.batchTimeoutID = -1;
9317
- me3._doBatchRequest(me3.batchCallback, auth, path20);
9317
+ me3._doBatchRequest(me3.batchCallback, auth, path21);
9318
9318
  }, this.batchInterval);
9319
9319
  }
9320
9320
  if (this.batchOptions.length === this.batchCount) {
9321
- this._doBatchRequest(this.batchCallback, auth, path20);
9321
+ this._doBatchRequest(this.batchCallback, auth, path21);
9322
9322
  }
9323
9323
  }
9324
9324
  /**
@@ -9327,14 +9327,14 @@ var require_http = __commonJS({
9327
9327
  * @param {Object?} auth - authentication options
9328
9328
  * @param {string} path - request path
9329
9329
  */
9330
- _doBatchRequest(callback, auth, path20) {
9330
+ _doBatchRequest(callback, auth, path21) {
9331
9331
  if (this.batchTimeoutID > 0) {
9332
9332
  clearTimeout(this.batchTimeoutID);
9333
9333
  this.batchTimeoutID = -1;
9334
9334
  }
9335
9335
  const batchOptionsCopy = this.batchOptions.slice();
9336
9336
  this.batchOptions = [];
9337
- this._doRequest(batchOptionsCopy, callback, auth, path20);
9337
+ this._doRequest(batchOptionsCopy, callback, auth, path21);
9338
9338
  }
9339
9339
  /**
9340
9340
  * Make a request to a winstond server or any http server which can
@@ -9344,7 +9344,7 @@ var require_http = __commonJS({
9344
9344
  * @param {Object?} auth - authentication options
9345
9345
  * @param {string} path - request path
9346
9346
  */
9347
- _doRequest(options, callback, auth, path20) {
9347
+ _doRequest(options, callback, auth, path21) {
9348
9348
  const headers = Object.assign({}, this.headers);
9349
9349
  if (auth && auth.bearer) {
9350
9350
  headers.Authorization = `Bearer ${auth.bearer}`;
@@ -9354,7 +9354,7 @@ var require_http = __commonJS({
9354
9354
  method: "POST",
9355
9355
  host: this.host,
9356
9356
  port: this.port,
9357
- path: `/${path20.replace(/^\//, "")}`,
9357
+ path: `/${path21.replace(/^\//, "")}`,
9358
9358
  headers,
9359
9359
  auth: auth && auth.username && auth.password ? `${auth.username}:${auth.password}` : "",
9360
9360
  agent: this.agent
@@ -10323,7 +10323,7 @@ var require_logger = __commonJS({
10323
10323
  */
10324
10324
  configure({
10325
10325
  silent,
10326
- format: format3,
10326
+ format: format4,
10327
10327
  defaultMeta,
10328
10328
  levels,
10329
10329
  level = "info",
@@ -10342,7 +10342,7 @@ var require_logger = __commonJS({
10342
10342
  this.clear();
10343
10343
  }
10344
10344
  this.silent = silent;
10345
- this.format = format3 || this.format || require_json()();
10345
+ this.format = format4 || this.format || require_json()();
10346
10346
  this.defaultMeta = defaultMeta || null;
10347
10347
  this.levels = levels || this.levels || config.npm.levels;
10348
10348
  this.level = level;
@@ -11164,18 +11164,32 @@ ${stack}` : base;
11164
11164
  });
11165
11165
 
11166
11166
  // ../../packages/logger/src/logger/Logger.ts
11167
- var import_chalk, MAX_CAUSE_DEPTH, Logger, logger, Logger_default;
11167
+ var import_util, import_chalk, MAX_CAUSE_DEPTH, LOG_RECORD_VERSION, MAX_FIELD_CHARS, ANSI_PATTERN, nativeConsole, Logger, logger, Logger_default;
11168
11168
  var init_Logger = __esm({
11169
11169
  "../../packages/logger/src/logger/Logger.ts"() {
11170
+ import_util = require("util");
11171
+ init_src();
11170
11172
  import_chalk = __toESM(require("chalk"), 1);
11171
11173
  init_FileLogService();
11172
11174
  MAX_CAUSE_DEPTH = 10;
11175
+ LOG_RECORD_VERSION = 1;
11176
+ MAX_FIELD_CHARS = 3e4;
11177
+ ANSI_PATTERN = /\u001B\[[0-9;]*m/g;
11178
+ nativeConsole = {
11179
+ log: console.log.bind(console),
11180
+ info: console.info.bind(console),
11181
+ warn: console.warn.bind(console),
11182
+ error: console.error.bind(console)
11183
+ };
11173
11184
  Logger = class {
11174
11185
  constructor() {
11175
11186
  // Counts lines written to the console. In-place TTY renderers (the CLI progress bar) read it to
11176
11187
  // detect that something else has printed since their last frame, so they redraw on a new line
11177
11188
  // instead of moving the cursor up and overwriting a log message.
11178
11189
  this._consoleWrites = 0;
11190
+ // Whether console.* has been redirected into this logger. Once per process, and one-way: our
11191
+ // own writes use `nativeConsole`, so there is nothing to restore it for.
11192
+ this._consoleCaptured = false;
11179
11193
  this.setLevel = (level) => this._level = level;
11180
11194
  this.enableFileLogging = (folder, file) => {
11181
11195
  this._fileLoggingFolder = folder;
@@ -11209,9 +11223,28 @@ var init_Logger = __esm({
11209
11223
  this._level = "debug";
11210
11224
  if (fileLoggingFolder && process.env.NODE_ENV !== "development") {
11211
11225
  this.enableFileLogging(fileLoggingFolder);
11212
- console.error("Enabled file logger.");
11226
+ nativeConsole.error("Enabled file logger.");
11213
11227
  }
11214
11228
  };
11229
+ /**
11230
+ * Routes `console.*` through this logger, so code that never heard of it still writes one line
11231
+ * per record. Call once from a deployed process entrypoint; a no-op under the `text` format,
11232
+ * where a human is reading the console and Node's own formatting is the better rendering.
11233
+ *
11234
+ * Interception rather than a sweep of the call sites: the requirement is about the STREAM, not
11235
+ * about our code — an express handler, a driver and a dependency all write to the same stdout,
11236
+ * and a rule enforced at the call sites is a rule that the next `console.error` breaks.
11237
+ */
11238
+ this.captureConsole = () => {
11239
+ if (this._consoleCaptured) return;
11240
+ if (this.consoleFormat() !== "json") return;
11241
+ this._consoleCaptured = true;
11242
+ console.log = (...args) => this.info((0, import_util.format)(...args));
11243
+ console.info = console.log;
11244
+ console.debug = (...args) => this.log((0, import_util.format)(...args));
11245
+ console.warn = (...args) => this.warn((0, import_util.format)(...args));
11246
+ console.error = (...args) => args.length === 1 && args[0] instanceof Error ? this.error(args[0]) : this.error((0, import_util.format)(...args));
11247
+ };
11215
11248
  // The file sink replaces the console only for the CLI: there a human is watching the progress bar
11216
11249
  // and can read the log file afterwards. Anywhere else that file sits on an ephemeral container
11217
11250
  // layer nobody reads, and stdout is the only sink reaching the log driver (ECS -> CloudWatch), so
@@ -11222,18 +11255,15 @@ var init_Logger = __esm({
11222
11255
  if (myLevel !== "debug") return;
11223
11256
  FileLogService_default.write("DEBUG", String(message));
11224
11257
  if (this.isConsoleSuppressed()) return;
11225
- console.log(import_chalk.default.cyanBright("DEBUG"), message);
11226
- this._consoleWrites++;
11258
+ this.writeConsole("debug", message);
11227
11259
  };
11228
11260
  this.info = (message) => {
11229
11261
  FileLogService_default.write("INFO", String(message));
11230
11262
  if (this.isConsoleSuppressed()) return;
11231
- console.info(message);
11232
- this._consoleWrites++;
11263
+ this.writeConsole("info", message);
11233
11264
  };
11234
11265
  this.warn = (message) => {
11235
- console.warn(message);
11236
- this._consoleWrites++;
11266
+ this.writeConsole("warn", message);
11237
11267
  FileLogService_default.write("WARN", String(message));
11238
11268
  };
11239
11269
  this.flush = () => FileLogService_default.flush();
@@ -11251,11 +11281,88 @@ var init_Logger = __esm({
11251
11281
  message = String(error);
11252
11282
  }
11253
11283
  const suppressed = this.isConsoleSuppressed();
11254
- console.error(message);
11255
- this._consoleWrites++;
11284
+ this.writeConsole("error", message, suppressed ? void 0 : stack);
11256
11285
  FileLogService_default.write("ERROR", message, stack);
11257
- if (stack && !suppressed)
11258
- console.error(stack);
11286
+ };
11287
+ /**
11288
+ * How console records are rendered: `text` for a human at a terminal, `json` for a log pipeline.
11289
+ *
11290
+ * Deployed processes default to `json` because there ONE RECORD MUST BE ONE LINE: the awslogs
11291
+ * driver turns every newline on stdout into its own CloudWatch event, so a stack trace arrived as
11292
+ * thirty separate events, none of them carrying the message they belonged to, interleaved with
11293
+ * whatever the other threads were writing. `REMORA_LOG_FORMAT` overrides the default either way.
11294
+ * Same rule as StateEmitter, whose records share the stream.
11295
+ */
11296
+ this.consoleFormat = () => {
11297
+ const configured = process.env.REMORA_LOG_FORMAT?.toLowerCase();
11298
+ if (configured === "json" || configured === "text")
11299
+ return configured;
11300
+ return process.env.REMORA_RUNTIME_CONTEXT === "cli" ? "text" : "json";
11301
+ };
11302
+ /**
11303
+ * The one place anything of ours reaches the console.
11304
+ *
11305
+ * `stack` belongs to the record it explains: a second line in text mode, a field of the same JSON
11306
+ * object in json mode — never a record of its own, which is how it would lose its message.
11307
+ */
11308
+ this.writeConsole = (level, message, stack) => {
11309
+ this._consoleWrites++;
11310
+ if (this.consoleFormat() === "json")
11311
+ return this.writeJson(level, message, stack);
11312
+ this.writeText(level, message, stack);
11313
+ };
11314
+ this.writeText = (level, message, stack) => {
11315
+ if (level === "debug")
11316
+ nativeConsole.log(import_chalk.default.cyanBright("DEBUG"), message);
11317
+ else if (level === "info")
11318
+ nativeConsole.info(message);
11319
+ else if (level === "warn")
11320
+ nativeConsole.warn(message);
11321
+ else
11322
+ nativeConsole.error(message);
11323
+ if (stack)
11324
+ nativeConsole.error(stack);
11325
+ };
11326
+ /**
11327
+ * One JSON object, one line, one log event. Written straight to the stream rather than through
11328
+ * `console`, which reformats and re-wraps what it is given.
11329
+ */
11330
+ this.writeJson = (level, message, stack) => {
11331
+ const record = {
11332
+ remora: "log",
11333
+ v: LOG_RECORD_VERSION,
11334
+ ts: DSTE_default.now().toISOString(),
11335
+ level,
11336
+ message: this.asField(message),
11337
+ ...stack ? { stack: this.asField(stack) } : {}
11338
+ };
11339
+ const stream = level === "warn" || level === "error" ? process.stderr : process.stdout;
11340
+ stream.write(`${this.stringify(record)}
11341
+ `);
11342
+ };
11343
+ /** A loggable value as one clamped, colour-free string. */
11344
+ this.asField = (value) => {
11345
+ const plain = this.asText(value).replace(ANSI_PATTERN, "");
11346
+ if (plain.length <= MAX_FIELD_CHARS)
11347
+ return plain;
11348
+ return `${plain.slice(0, MAX_FIELD_CHARS)}\u2026[+${plain.length - MAX_FIELD_CHARS} chars]`;
11349
+ };
11350
+ this.asText = (value) => {
11351
+ if (typeof value === "string")
11352
+ return value;
11353
+ if (value instanceof Error)
11354
+ return value.stack ?? value.message;
11355
+ if (typeof value === "object" && value !== null)
11356
+ return this.stringify(value);
11357
+ return String(value);
11358
+ };
11359
+ /** JSON.stringify that cannot throw: a circular or unserializable value still has to be logged. */
11360
+ this.stringify = (value) => {
11361
+ try {
11362
+ return JSON.stringify(value);
11363
+ } catch {
11364
+ return String(value);
11365
+ }
11259
11366
  };
11260
11367
  // Node's Error.stack omits `cause` — only util.inspect renders it, and we log strings rather
11261
11368
  // than Error objects. Without unwrapping here the root reason of a wrapped error is lost on any
@@ -11575,7 +11682,7 @@ var CONSTANTS, Constants_default;
11575
11682
  var init_Constants = __esm({
11576
11683
  "../../packages/constants/src/Constants.ts"() {
11577
11684
  CONSTANTS = {
11578
- cliVersion: "2.0.2",
11685
+ cliVersion: "2.1.0",
11579
11686
  backendVersion: 1,
11580
11687
  backendPort: 5088,
11581
11688
  workerVersion: 2,
@@ -11632,7 +11739,12 @@ var init_Constants = __esm({
11632
11739
  * whole run, so the entire work list is submitted at once and needs an upper bound. A queued
11633
11740
  * task holds references, not copies, so this bounds the work list rather than memory.
11634
11741
  */
11635
- MAX_WORKER_QUEUE_SIZE: 1e5
11742
+ MAX_WORKER_QUEUE_SIZE: 1e5,
11743
+ /**
11744
+ * Rows a sample may ask for out of the pipeline. A sample is a look at the data, never an
11745
+ * export of it — `remora sample -s` and the preview's Data tab are both held to this.
11746
+ */
11747
+ MAX_SAMPLE_ROWS: 100
11636
11748
  }
11637
11749
  };
11638
11750
  Constants_default = CONSTANTS;
@@ -12619,10 +12731,10 @@ var init_Validator = __esm({
12619
12731
  errors.push(`There are outputs with the same type. (duplicates type: ${duplicatesTypes.join(" and ")})`);
12620
12732
  }
12621
12733
  for (const output of consumer.outputs) {
12622
- const format3 = output.format.toUpperCase();
12623
- if (format3 === "CSV" || format3 === "JSON" || format3 === "PARQUET" || format3 === "TXT") {
12734
+ const format4 = output.format.toUpperCase();
12735
+ if (format4 === "CSV" || format4 === "JSON" || format4 === "PARQUET" || format4 === "TXT") {
12624
12736
  if (!output.exportDestination)
12625
- errors.push(`A static file output must have an export destination set (${format3})`);
12737
+ errors.push(`A static file output must have an export destination set (${format4})`);
12626
12738
  else if (!Environment_default.getSource(output.exportDestination))
12627
12739
  errors.push(`The export destination "${output.exportDestination}" was not found in the sources.`);
12628
12740
  }
@@ -12694,14 +12806,14 @@ var init_Validator = __esm({
12694
12806
  const errors = [];
12695
12807
  const positionalFormats = ["CSV", "TXT", "PARQUET"];
12696
12808
  for (const output of (consumer.outputs ?? []).filter((x2) => x2.omitNull === true)) {
12697
- const format3 = output.format.toUpperCase();
12698
- if (positionalFormats.includes(format3)) {
12699
- errors.push(`The ${format3} output of consumer "${consumer.name}" declares "omitNull", which only applies to JSON/API output: a positional column can't be omitted from a row.`);
12809
+ const format4 = output.format.toUpperCase();
12810
+ if (positionalFormats.includes(format4)) {
12811
+ errors.push(`The ${format4} output of consumer "${consumer.name}" declares "omitNull", which only applies to JSON/API output: a positional column can't be omitted from a row.`);
12700
12812
  continue;
12701
12813
  }
12702
12814
  const positional = (consumer.outputs ?? []).filter((x2) => positionalFormats.includes(x2.format.toUpperCase()));
12703
12815
  if (positional.length > 0)
12704
- errors.push(`The ${format3} output of consumer "${consumer.name}" declares "omitNull", but the consumer also writes ${positional.map((x2) => x2.format.toUpperCase()).join(" and ")}. Every output is serialized from one record, so omitting fields would break the positional one \u2014 split them into two consumers.`);
12816
+ errors.push(`The ${format4} output of consumer "${consumer.name}" declares "omitNull", but the consumer also writes ${positional.map((x2) => x2.format.toUpperCase()).join(" and ")}. Every output is serialized from one record, so omitting fields would break the positional one \u2014 split them into two consumers.`);
12705
12817
  }
12706
12818
  return errors;
12707
12819
  };
@@ -12780,7 +12892,7 @@ var init_Validator = __esm({
12780
12892
  */
12781
12893
  this.detectOnFinishRecursion = (consumer) => {
12782
12894
  const errors = [];
12783
- const path20 = [];
12895
+ const path21 = [];
12784
12896
  const targetsOf = (cons) => {
12785
12897
  const names = [];
12786
12898
  for (const output of cons.outputs ?? []) {
@@ -12792,17 +12904,17 @@ var init_Validator = __esm({
12792
12904
  return names;
12793
12905
  };
12794
12906
  const walk = (name) => {
12795
- if (path20.some((x2) => x2.toLowerCase() === name.toLowerCase())) {
12796
- errors.push(`Consumer "${consumer.name}" has a cyclic run-consumer (onSuccess/onError) chain: ${[...path20, name].join(" -> ")}`);
12907
+ if (path21.some((x2) => x2.toLowerCase() === name.toLowerCase())) {
12908
+ errors.push(`Consumer "${consumer.name}" has a cyclic run-consumer (onSuccess/onError) chain: ${[...path21, name].join(" -> ")}`);
12797
12909
  return true;
12798
12910
  }
12799
12911
  const cons = Environment_default.getConsumer(name);
12800
12912
  if (!cons) return false;
12801
- path20.push(name);
12913
+ path21.push(name);
12802
12914
  for (const target of targetsOf(cons)) {
12803
12915
  if (walk(target)) return true;
12804
12916
  }
12805
- path20.pop();
12917
+ path21.pop();
12806
12918
  return false;
12807
12919
  };
12808
12920
  walk(consumer.name);
@@ -14852,14 +14964,14 @@ var init_readFile = __esm({
14852
14964
  import_promises3 = require("fs/promises");
14853
14965
  filePromises = {};
14854
14966
  fileIntercept = {};
14855
- readFile2 = (path20, options) => {
14856
- if (fileIntercept[path20] !== void 0) {
14857
- return fileIntercept[path20];
14967
+ readFile2 = (path21, options) => {
14968
+ if (fileIntercept[path21] !== void 0) {
14969
+ return fileIntercept[path21];
14858
14970
  }
14859
- if (!filePromises[path20] || options?.ignoreCache) {
14860
- filePromises[path20] = (0, import_promises3.readFile)(path20, "utf8");
14971
+ if (!filePromises[path21] || options?.ignoreCache) {
14972
+ filePromises[path21] = (0, import_promises3.readFile)(path21, "utf8");
14861
14973
  }
14862
- return filePromises[path20];
14974
+ return filePromises[path21];
14863
14975
  };
14864
14976
  }
14865
14977
  });
@@ -14971,8 +15083,8 @@ var init_externalDataInterceptor = __esm({
14971
15083
  getFileRecord() {
14972
15084
  return fileIntercept;
14973
15085
  },
14974
- interceptFile(path20, contents) {
14975
- fileIntercept[path20] = Promise.resolve(contents);
15086
+ interceptFile(path21, contents) {
15087
+ fileIntercept[path21] = Promise.resolve(contents);
14976
15088
  },
14977
15089
  getTokenRecord() {
14978
15090
  return tokenIntercept;
@@ -17754,17 +17866,17 @@ var init_split_header = __esm({
17754
17866
  });
17755
17867
 
17756
17868
  // ../../node_modules/@smithy/core/dist-es/submodules/serde/value/NumericValue.js
17757
- var format2, NumericValue;
17869
+ var format3, NumericValue;
17758
17870
  var init_NumericValue = __esm({
17759
17871
  "../../node_modules/@smithy/core/dist-es/submodules/serde/value/NumericValue.js"() {
17760
- format2 = /^-?\d*(\.\d+)?$/;
17872
+ format3 = /^-?\d*(\.\d+)?$/;
17761
17873
  NumericValue = class _NumericValue {
17762
17874
  string;
17763
17875
  type;
17764
17876
  constructor(string, type) {
17765
17877
  this.string = string;
17766
17878
  this.type = type;
17767
- if (!format2.test(string)) {
17879
+ if (!format3.test(string)) {
17768
17880
  throw new Error(`@smithy/core/serde - NumericValue must only contain [0-9], at most one decimal point ".", and an optional negation prefix "-".`);
17769
17881
  }
17770
17882
  }
@@ -17776,7 +17888,7 @@ var init_NumericValue = __esm({
17776
17888
  return false;
17777
17889
  }
17778
17890
  const _nv = object;
17779
- return _NumericValue.prototype.isPrototypeOf(object) || _nv.type === "bigDecimal" && format2.test(_nv.string);
17891
+ return _NumericValue.prototype.isPrototypeOf(object) || _nv.type === "bigDecimal" && format3.test(_nv.string);
17780
17892
  }
17781
17893
  };
17782
17894
  }
@@ -18052,8 +18164,8 @@ var init_createConfigValueProvider = __esm({
18052
18164
  return endpoint.url.href;
18053
18165
  }
18054
18166
  if ("hostname" in endpoint) {
18055
- const { protocol, hostname, port, path: path20 } = endpoint;
18056
- return `${protocol}//${hostname}${port ? ":" + port : ""}${path20}`;
18167
+ const { protocol, hostname, port, path: path21 } = endpoint;
18168
+ return `${protocol}//${hostname}${port ? ":" + port : ""}${path21}`;
18057
18169
  }
18058
18170
  }
18059
18171
  return endpoint;
@@ -18428,18 +18540,18 @@ var getAttrPathList;
18428
18540
  var init_getAttrPathList = __esm({
18429
18541
  "../../node_modules/@smithy/core/dist-es/submodules/endpoints/util-endpoints/lib/getAttrPathList.js"() {
18430
18542
  init_types2();
18431
- getAttrPathList = (path20) => {
18432
- const parts = path20.split(".");
18543
+ getAttrPathList = (path21) => {
18544
+ const parts = path21.split(".");
18433
18545
  const pathList = [];
18434
18546
  for (const part of parts) {
18435
18547
  const squareBracketIndex = part.indexOf("[");
18436
18548
  if (squareBracketIndex !== -1) {
18437
18549
  if (part.indexOf("]") !== part.length - 1) {
18438
- throw new EndpointError(`Path: '${path20}' does not end with ']'`);
18550
+ throw new EndpointError(`Path: '${path21}' does not end with ']'`);
18439
18551
  }
18440
18552
  const arrayIndex = part.slice(squareBracketIndex + 1, -1);
18441
18553
  if (Number.isNaN(parseInt(arrayIndex))) {
18442
- throw new EndpointError(`Invalid array index: '${arrayIndex}' in path: '${path20}'`);
18554
+ throw new EndpointError(`Invalid array index: '${arrayIndex}' in path: '${path21}'`);
18443
18555
  }
18444
18556
  if (squareBracketIndex !== 0) {
18445
18557
  pathList.push(part.slice(0, squareBracketIndex));
@@ -18460,9 +18572,9 @@ var init_getAttr = __esm({
18460
18572
  "../../node_modules/@smithy/core/dist-es/submodules/endpoints/util-endpoints/lib/getAttr.js"() {
18461
18573
  init_types2();
18462
18574
  init_getAttrPathList();
18463
- getAttr = (value, path20) => getAttrPathList(path20).reduce((acc, index) => {
18575
+ getAttr = (value, path21) => getAttrPathList(path21).reduce((acc, index) => {
18464
18576
  if (typeof acc !== "object") {
18465
- throw new EndpointError(`Index '${index}' in '${path20}' not found in '${JSON.stringify(value)}'`);
18577
+ throw new EndpointError(`Index '${index}' in '${path21}' not found in '${JSON.stringify(value)}'`);
18466
18578
  } else if (Array.isArray(acc)) {
18467
18579
  const i6 = parseInt(index);
18468
18580
  return acc[i6 < 0 ? acc.length + i6 : i6];
@@ -18523,8 +18635,8 @@ var init_parseURL = __esm({
18523
18635
  return value;
18524
18636
  }
18525
18637
  if (typeof value === "object" && "hostname" in value) {
18526
- const { hostname: hostname2, port, protocol: protocol2 = "", path: path20 = "", query = {} } = value;
18527
- const url = new URL(`${protocol2}//${hostname2}${port ? `:${port}` : ""}${path20}`);
18638
+ const { hostname: hostname2, port, protocol: protocol2 = "", path: path21 = "", query = {} } = value;
18639
+ const url = new URL(`${protocol2}//${hostname2}${port ? `:${port}` : ""}${path21}`);
18528
18640
  url.search = Object.entries(query).map(([k7, v3]) => `${k7}=${v3}`).join("&");
18529
18641
  return url;
18530
18642
  }
@@ -20868,11 +20980,11 @@ var init_HttpBindingProtocol = __esm({
20868
20980
  const opTraits = translateTraits(operationSchema.traits);
20869
20981
  if (opTraits.http) {
20870
20982
  request.method = opTraits.http[0];
20871
- const [path20, search] = opTraits.http[1].split("?");
20983
+ const [path21, search] = opTraits.http[1].split("?");
20872
20984
  if (request.path == "/") {
20873
- request.path = path20;
20985
+ request.path = path21;
20874
20986
  } else {
20875
- request.path += path20;
20987
+ request.path += path21;
20876
20988
  }
20877
20989
  const traitSearchParams = new URLSearchParams(search ?? "");
20878
20990
  for (const [key, value] of traitSearchParams) {
@@ -21241,8 +21353,8 @@ var init_FromStringShapeDeserializer = __esm({
21241
21353
  return (this.serdeContext?.base64Decoder ?? fromBase64)(data);
21242
21354
  }
21243
21355
  if (ns2.isTimestampSchema()) {
21244
- const format3 = determineTimestampFormat(ns2, this.settings);
21245
- switch (format3) {
21356
+ const format4 = determineTimestampFormat(ns2, this.settings);
21357
+ switch (format4) {
21246
21358
  case 5:
21247
21359
  return _parseRfc3339DateTimeWithOffset(data);
21248
21360
  case 6:
@@ -21364,8 +21476,8 @@ var init_ToStringShapeSerializer = __esm({
21364
21476
  if (!(value instanceof Date)) {
21365
21477
  throw new Error(`@smithy/core/protocols - received non-Date value ${value} when schema expected Date in ${ns2.getName(true)}`);
21366
21478
  }
21367
- const format3 = determineTimestampFormat(ns2, this.settings);
21368
- switch (format3) {
21479
+ const format4 = determineTimestampFormat(ns2, this.settings);
21480
+ switch (format4) {
21369
21481
  case 5:
21370
21482
  this.stringBuffer = value.toISOString().replace(".000Z", "Z");
21371
21483
  break;
@@ -24585,12 +24697,12 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
24585
24697
  const password = request.password ?? "";
24586
24698
  auth = `${username}:${password}`;
24587
24699
  }
24588
- let path20 = request.path;
24700
+ let path21 = request.path;
24589
24701
  if (queryString) {
24590
- path20 += `?${queryString}`;
24702
+ path21 += `?${queryString}`;
24591
24703
  }
24592
24704
  if (request.fragment) {
24593
- path20 += `#${request.fragment}`;
24705
+ path21 += `#${request.fragment}`;
24594
24706
  }
24595
24707
  let hostname = request.hostname ?? "";
24596
24708
  if (hostname[0] === "[" && hostname.endsWith("]")) {
@@ -24602,7 +24714,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
24602
24714
  headers: request.headers,
24603
24715
  host: hostname,
24604
24716
  method: request.method,
24605
- path: path20,
24717
+ path: path21,
24606
24718
  port: request.port,
24607
24719
  agent,
24608
24720
  auth
@@ -25511,10 +25623,10 @@ ${longDate}
25511
25623
  ${credentialScope}
25512
25624
  ${toHex(hashedRequest)}`;
25513
25625
  }
25514
- getCanonicalPath({ path: path20 }) {
25626
+ getCanonicalPath({ path: path21 }) {
25515
25627
  if (this.uriEscapePath) {
25516
25628
  const normalizedPathSegments = [];
25517
- for (const pathSegment of path20.split("/")) {
25629
+ for (const pathSegment of path21.split("/")) {
25518
25630
  if (pathSegment?.length === 0)
25519
25631
  continue;
25520
25632
  if (pathSegment === ".")
@@ -25525,11 +25637,11 @@ ${toHex(hashedRequest)}`;
25525
25637
  normalizedPathSegments.push(pathSegment);
25526
25638
  }
25527
25639
  }
25528
- const normalizedPath = `${path20?.startsWith("/") ? "/" : ""}${normalizedPathSegments.join("/")}${normalizedPathSegments.length > 0 && path20?.endsWith("/") ? "/" : ""}`;
25640
+ const normalizedPath = `${path21?.startsWith("/") ? "/" : ""}${normalizedPathSegments.join("/")}${normalizedPathSegments.length > 0 && path21?.endsWith("/") ? "/" : ""}`;
25529
25641
  const doubleEncoded = escapeUri(normalizedPath);
25530
25642
  return doubleEncoded.replace(/%2F/g, "/");
25531
25643
  }
25532
- return path20;
25644
+ return path21;
25533
25645
  }
25534
25646
  validateResolvedCredentials(credentials) {
25535
25647
  if (typeof credentials !== "object" || typeof credentials.accessKeyId !== "string" || typeof credentials.secretAccessKey !== "string") {
@@ -26599,8 +26711,8 @@ var init_JsonShapeDeserializer = __esm({
26599
26711
  return value;
26600
26712
  }
26601
26713
  if (ns2.isTimestampSchema() && value != null) {
26602
- const format3 = determineTimestampFormat(ns2, this.settings);
26603
- switch (format3) {
26714
+ const format4 = determineTimestampFormat(ns2, this.settings);
26715
+ switch (format4) {
26604
26716
  case 5:
26605
26717
  return parseRfc3339DateTimeWithOffset(value);
26606
26718
  case 6:
@@ -26824,8 +26936,8 @@ var init_JsonShapeSerializer = __esm({
26824
26936
  return (this.serdeContext?.base64Encoder ?? toBase64)(value);
26825
26937
  }
26826
26938
  if (value instanceof Date && (ns2.isTimestampSchema() || ns2.isDocumentSchema())) {
26827
- const format3 = determineTimestampFormat(ns2, this.settings);
26828
- switch (format3) {
26939
+ const format4 = determineTimestampFormat(ns2, this.settings);
26940
+ switch (format4) {
26829
26941
  case 5:
26830
26942
  return value.toISOString().replace(".000Z", "Z");
26831
26943
  case 6:
@@ -27453,8 +27565,8 @@ var init_QueryShapeSerializer = __esm({
27453
27565
  } else if (ns2.isTimestampSchema()) {
27454
27566
  if (value instanceof Date) {
27455
27567
  this.writeKey(prefix2);
27456
- const format3 = determineTimestampFormat(ns2, this.settings);
27457
- switch (format3) {
27568
+ const format4 = determineTimestampFormat(ns2, this.settings);
27569
+ switch (format4) {
27458
27570
  case 5:
27459
27571
  this.writeValue(value.toISOString().replace(".000Z", "Z"));
27460
27572
  break;
@@ -41889,11 +42001,13 @@ var init_src6 = __esm({
41889
42001
  });
41890
42002
 
41891
42003
  // ../../packages/drivers/src/DeltaShareDriver.ts
41892
- var fs9, import_promises7, MAX_LIMIT_HINT, DeltaShareSourceDriver, DeltaShareDriver_default;
42004
+ var fs9, import_promises7, import_stream, import_promises8, MAX_LIMIT_HINT, PARQUET_BATCH_ROWS, DeltaShareSourceDriver, DeltaShareDriver_default;
41893
42005
  var init_DeltaShareDriver = __esm({
41894
42006
  "../../packages/drivers/src/DeltaShareDriver.ts"() {
41895
42007
  fs9 = __toESM(require("fs"), 1);
41896
42008
  import_promises7 = __toESM(require("fs/promises"), 1);
42009
+ import_stream = require("stream");
42010
+ import_promises8 = require("stream/promises");
41897
42011
  init_src();
41898
42012
  init_src4();
41899
42013
  init_src2();
@@ -41901,6 +42015,7 @@ var init_DeltaShareDriver = __esm({
41901
42015
  init_DeltaSharePredicate();
41902
42016
  init_OidcTokenProvider();
41903
42017
  MAX_LIMIT_HINT = 2147483647;
42018
+ PARQUET_BATCH_ROWS = 5e4;
41904
42019
  DeltaShareSourceDriver = class {
41905
42020
  constructor() {
41906
42021
  this._query = "{prefix}/shares/{share}/schemas/{schema}/tables/{table}/query";
@@ -41910,6 +42025,9 @@ var init_DeltaShareDriver = __esm({
41910
42025
  // Column Delta types per table, for the predicate's literals. A table's schema does not change
41911
42026
  // under a run, and only a read with something to push ever asks for it.
41912
42027
  this._columnTypes = /* @__PURE__ */ new Map();
42028
+ // Rows held as objects at once. A run leaves this at PARQUET_BATCH_ROWS; the tests lower it so a
42029
+ // fixture small enough to read whole still splits its row groups the way a real part file does.
42030
+ this._batchRows = PARQUET_BATCH_ROWS;
41913
42031
  this.init = async (source) => {
41914
42032
  Affirm_default(source, "Invalid source");
41915
42033
  const { authentication } = source;
@@ -41970,12 +42088,11 @@ var init_DeltaShareDriver = __esm({
41970
42088
  Affirm_default(request, "Invalid download request");
41971
42089
  const table = this._resolveTable(request.fileKey);
41972
42090
  const deltaFiles = await this._getAllFilesInTable(table, request.disableHistory);
41973
- const hyparquet = await import("hyparquet");
41974
42091
  const lines = [];
41975
- for (const deltaFile of deltaFiles) {
41976
- const parquetRecords = await this._readParquetObjects(deltaFile);
41977
- lines.push(...parquetRecords.map((x2) => JSON.stringify(hyparquet.toJson(x2))));
41978
- }
42092
+ for (const deltaFile of deltaFiles)
42093
+ for await (const batch of this._readRemoteParquetBatches(deltaFile))
42094
+ for (const record of batch)
42095
+ lines.push(JSON.stringify(record));
41979
42096
  Logger_default.log(`Delta Share readAll: ${lines.length} record(s) from ${deltaFiles.length} file(s) of table "${table}"`);
41980
42097
  return lines;
41981
42098
  };
@@ -41985,22 +42102,41 @@ var init_DeltaShareDriver = __esm({
41985
42102
  Affirm_default(request.options.lineFrom !== void 0 && request.options.lineTo !== void 0, "Missing read range");
41986
42103
  const table = this._resolveTable(request.fileKey);
41987
42104
  const deltaFiles = await this._getAllFilesInTable(table, request.disableHistory);
41988
- const hyparquet = await import("hyparquet");
41989
42105
  const { options: { lineFrom, lineTo } } = request;
42106
+ const lines = await this._collectLinesInRange(deltaFiles, { from: lineFrom, to: lineTo });
42107
+ Logger_default.log(`Delta Share readLinesInRange [${lineFrom}, ${lineTo}) on table "${table}": ${lines.length} record(s)`);
42108
+ return lines;
42109
+ };
42110
+ /**
42111
+ * The records of the given range, serialized. Reading stops the moment the range is filled: a
42112
+ * part file holds hundreds of thousands of rows and a preview asks for a handful of them, so
42113
+ * decoding past `to` is both slow and the memory the batching above exists to avoid.
42114
+ */
42115
+ this._collectLinesInRange = async (deltaFiles, range2) => {
42116
+ if (range2.to <= range2.from)
42117
+ return [];
41990
42118
  const lines = [];
41991
42119
  let index = 0;
41992
42120
  for (const deltaFile of deltaFiles) {
41993
- const parquetRecords = await this._readParquetObjects(deltaFile);
41994
- for (const record of parquetRecords) {
41995
- if (index >= lineFrom && index < lineTo)
41996
- lines.push(JSON.stringify(hyparquet.toJson(record)));
41997
- index++;
41998
- if (index >= lineTo) break;
42121
+ for await (const batch of this._readRemoteParquetBatches(deltaFile)) {
42122
+ index = this._pushRecordsInRange(lines, batch, index, range2);
42123
+ if (index >= range2.to)
42124
+ return lines;
41999
42125
  }
42000
42126
  }
42001
- Logger_default.log(`Delta Share readLinesInRange [${lineFrom}, ${lineTo}) on table "${table}": ${lines.length} record(s)`);
42002
42127
  return lines;
42003
42128
  };
42129
+ // The index the batch ends on, so the next batch carries on counting where this one stopped.
42130
+ this._pushRecordsInRange = (lines, batch, index, range2) => {
42131
+ for (const record of batch) {
42132
+ if (index >= range2.from && index < range2.to)
42133
+ lines.push(JSON.stringify(record));
42134
+ index++;
42135
+ if (index >= range2.to)
42136
+ break;
42137
+ }
42138
+ return index;
42139
+ };
42004
42140
  this.exist = async (_producer) => {
42005
42141
  void _producer;
42006
42142
  let nextPageToken;
@@ -42144,20 +42280,48 @@ var init_DeltaShareDriver = __esm({
42144
42280
  return "(unparseable url)";
42145
42281
  }
42146
42282
  };
42147
- this._readParquetObjects = async (deltaFile) => {
42283
+ // Split out so the batch loop above stays one level of nesting, and so both failures name the file
42284
+ this._readParquetMetadata = async (file, label) => {
42148
42285
  const hyparquet = await import("hyparquet");
42149
- const { compressors: compressors2 } = await Promise.resolve().then(() => (init_src6(), src_exports));
42150
- const byteLength = deltaFile.file.deltaSingleAction.add?.size ?? deltaFile.file.deltaSingleAction.remove?.size;
42151
- const startedMs = Date.now();
42152
- let records;
42153
42286
  try {
42154
- const file = await hyparquet.asyncBufferFromUrl({ url: deltaFile.file.url, byteLength });
42155
- records = await hyparquet.parquetReadObjects({ file, compressors: compressors2 });
42287
+ return await hyparquet.parquetMetadataAsync(file);
42156
42288
  } catch (error) {
42157
- throw new Error(`Delta Share failed reading parquet from ${this._redactUrl(deltaFile.file.url)} (${byteLength ?? "?"} bytes)`, { cause: error });
42289
+ throw new Error(`Delta Share failed reading the parquet footer of ${label}`, { cause: error });
42290
+ }
42291
+ };
42292
+ this._readParquetBatch = async (options, label) => {
42293
+ const hyparquet = await import("hyparquet");
42294
+ try {
42295
+ return await hyparquet.parquetReadObjects(options);
42296
+ } catch (error) {
42297
+ throw new Error(`Delta Share failed reading parquet rows [${options.rowStart}, ${options.rowEnd}) of ${label}`, { cause: error });
42158
42298
  }
42159
- Logger_default.log(`Delta Share read ${records.length} record(s) from ${this._redactUrl(deltaFile.file.url)} (${byteLength ?? "?"} bytes) in ${Date.now() - startedMs}ms`);
42160
- return records;
42299
+ };
42300
+ // Reads straight from the pre-signed URL. Only for the bounded readers (preview, sample): every
42301
+ // batch refetches the row group, which is why `ready` stages the file locally instead.
42302
+ this._readRemoteParquetBatches = (deltaFile) => {
42303
+ const byteLength = deltaFile.file.deltaSingleAction.add?.size ?? deltaFile.file.deltaSingleAction.remove?.size;
42304
+ const label = `${this._redactUrl(deltaFile.file.url)} (${byteLength ?? "?"} bytes)`;
42305
+ const open = async () => {
42306
+ const hyparquet = await import("hyparquet");
42307
+ return await hyparquet.asyncBufferFromUrl({ url: deltaFile.file.url, byteLength });
42308
+ };
42309
+ return this._streamParquetBatchesFrom(open, label);
42310
+ };
42311
+ /**
42312
+ * Copies a part file to local disk, streamed, so nothing but the socket buffer is ever in memory.
42313
+ * `ready` re-reads the file once per batch and re-reading it over HTTP would refetch the same
42314
+ * bytes every time.
42315
+ */
42316
+ this._downloadParquet = async (deltaFile, localPath) => {
42317
+ const startedMs = Date.now();
42318
+ const res = await this._fetch(deltaFile.file.url, { method: "GET" }, `parquet download of ${this._redactUrl(deltaFile.file.url)}`);
42319
+ if (!res.ok)
42320
+ throw new Error(`Error downloading parquet from the delta share: ${res.status} ${res.statusText} (${this._redactUrl(deltaFile.file.url)})`);
42321
+ Affirm_default(res.body, `Empty response body downloading parquet from ${this._redactUrl(deltaFile.file.url)}`);
42322
+ await (0, import_promises8.pipeline)(import_stream.Readable.fromWeb(res.body), fs9.createWriteStream(localPath));
42323
+ const { size } = await import_promises7.default.stat(localPath);
42324
+ Logger_default.log(`Delta Share staged ${this._redactUrl(deltaFile.file.url)} (${size} bytes) in ${Date.now() - startedMs}ms`);
42161
42325
  };
42162
42326
  this._serializeDatasetValue = (value) => {
42163
42327
  if (value === null || value === void 0)
@@ -42171,17 +42335,41 @@ var init_DeltaShareDriver = __esm({
42171
42335
  this._getDeltaFileKey = (table, index) => {
42172
42336
  return `${this._resolveSchema()}/${table}/part-${index}.parquet`;
42173
42337
  };
42174
- this._writeDatasetFile = async (localPath, records, delimiter) => {
42175
- if (records.length === 0)
42176
- return false;
42177
- const header = Object.keys(records[0]);
42178
- const lines = [
42179
- CSVParser_default.stringifyRow(header, delimiter),
42180
- ...records.map((record) => CSVParser_default.stringifyRow(header.map((column) => this._serializeDatasetValue(record[column])), delimiter))
42181
- ];
42182
- await import_promises7.default.writeFile(localPath, `${lines.join("\n")}
42183
- `);
42184
- return true;
42338
+ /**
42339
+ * Writes the batches out as one CSV dataset file and reports how many records landed. Rows are
42340
+ * written as they arrive rather than joined into one string first: a file's worth of lines, and
42341
+ * the single string joining them, were each as large as the records themselves.
42342
+ *
42343
+ * The header is taken from the first record and reused for every later one, so a file whose rows
42344
+ * disagree on their columns still produces a rectangular dataset.
42345
+ */
42346
+ this._writeDatasetFile = async (localPath, batches, delimiter) => {
42347
+ const stream = fs9.createWriteStream(localPath);
42348
+ let header = null;
42349
+ let records = 0;
42350
+ try {
42351
+ for await (const batch of batches) {
42352
+ for (const record of batch) {
42353
+ if (!header) {
42354
+ header = Object.keys(record);
42355
+ await this._writeLine(stream, CSVParser_default.stringifyRow(header, delimiter));
42356
+ }
42357
+ await this._writeLine(stream, CSVParser_default.stringifyRow(header.map((column) => this._serializeDatasetValue(record[column])), delimiter));
42358
+ records++;
42359
+ }
42360
+ }
42361
+ } finally {
42362
+ await new Promise((resolve) => stream.end(resolve));
42363
+ }
42364
+ return records;
42365
+ };
42366
+ // A false from write() means the buffer is full; waiting for the drain just then keeps the queued
42367
+ // rows bounded instead of letting them pile up faster than the disk takes them.
42368
+ this._writeLine = async (stream, line) => {
42369
+ if (stream.write(`${line}
42370
+ `))
42371
+ return;
42372
+ await new Promise((resolve) => stream.once("drain", resolve));
42185
42373
  };
42186
42374
  /**
42187
42375
  * Every file the share reports for this table. `jsonPredicateHints` lets the server skip the
@@ -42245,30 +42433,22 @@ var init_DeltaShareDriver = __esm({
42245
42433
  const table = this._resolveTable(producer.settings.fileKey);
42246
42434
  const hints = await this._buildHints(producer, table, request.pushdown);
42247
42435
  const deltaFiles = await this._getAllFilesInTable(table, producer.settings.disableHistory, hints);
42248
- const hyparquet = await import("hyparquet");
42249
42436
  const delimiter = producer.settings.delimiter ?? ",";
42250
42437
  const files = [];
42251
42438
  let records = 0;
42252
42439
  let skipped = 0;
42253
42440
  for (const [index, deltaFile] of deltaFiles.entries()) {
42254
42441
  onProgress?.(index / deltaFiles.length);
42255
- const parquetRecords = await this._readParquetObjects(deltaFile);
42256
- if (parquetRecords.length === 0) {
42257
- skipped++;
42258
- Logger_default.log(`Delta Share ready: file ${index + 1}/${deltaFiles.length} of table "${table}" holds no records, skipping`);
42259
- continue;
42260
- }
42261
42442
  const sourceFileKey = this._getDeltaFileKey(table, index);
42262
42443
  const localPath = ExecutorScope_default.getProducerPath(scope, producer, sourceFileKey);
42263
42444
  ExecutorScope_default.ensurePath(localPath);
42264
- const jsonRecords = parquetRecords.map((record) => hyparquet.toJson(record));
42265
- const written = await this._writeDatasetFile(localPath, jsonRecords, delimiter);
42266
- if (written) {
42445
+ const written = await this._stageDeltaFile(deltaFile, localPath, delimiter);
42446
+ if (written > 0) {
42267
42447
  files.push({ fullUri: localPath, fileSize: fs9.statSync(localPath).size });
42268
- records += jsonRecords.length;
42448
+ records += written;
42269
42449
  } else {
42270
42450
  skipped++;
42271
- Logger_default.log(`Delta Share ready: nothing written for ${sourceFileKey}, discarding the staged file`);
42451
+ Logger_default.log(`Delta Share ready: file ${index + 1}/${deltaFiles.length} of table "${table}" (${sourceFileKey}) holds no records, discarding the staged file`);
42272
42452
  await import_promises7.default.unlink(localPath).catch(() => {
42273
42453
  });
42274
42454
  }
@@ -42279,6 +42459,57 @@ var init_DeltaShareDriver = __esm({
42279
42459
  Logger_default.log(`Delta Share ready: staged ${records} record(s) into ${files.length} dataset file(s) (${bytes} bytes) for producer "${producer.name}" from table "${table}"${skippedNote}`);
42280
42460
  return { files, filteredAtSource: !!hints?.jsonPredicateHints };
42281
42461
  };
42462
+ /**
42463
+ * One part file turned into one CSV dataset file, downloaded then converted a batch at a time so
42464
+ * that neither step's memory grows with the file. The download is dropped either way — it is the
42465
+ * dataset file the run reads from here on.
42466
+ */
42467
+ this._stageDeltaFile = async (deltaFile, localPath, delimiter) => {
42468
+ const downloadPath = `${localPath}.parquet`;
42469
+ await this._downloadParquet(deltaFile, downloadPath);
42470
+ try {
42471
+ const open = async () => {
42472
+ const hyparquet = await import("hyparquet");
42473
+ return await hyparquet.asyncBufferFromFile(downloadPath);
42474
+ };
42475
+ return await this._writeDatasetFile(localPath, this._streamParquetBatchesFrom(open, this._redactUrl(deltaFile.file.url)), delimiter);
42476
+ } finally {
42477
+ await import_promises7.default.unlink(downloadPath).catch(() => {
42478
+ });
42479
+ }
42480
+ };
42481
+ }
42482
+ /**
42483
+ * The rows of a part file, `_batchRows` at a time and already JSON-safe.
42484
+ *
42485
+ * hyparquet decodes a whole row group's columns per read either way, but only the requested rows
42486
+ * are turned into objects — and the objects are what dominates — so a row group larger than a
42487
+ * batch is read in several passes. Every pass re-reads the group's bytes, which is why `ready`
42488
+ * stages the file on disk first and only the small readers below stream it from its URL.
42489
+ */
42490
+ async *_streamParquetBatches(file, label) {
42491
+ const hyparquet = await import("hyparquet");
42492
+ const { compressors: compressors2 } = await Promise.resolve().then(() => (init_src6(), src_exports));
42493
+ const startedMs = Date.now();
42494
+ const metadata = await this._readParquetMetadata(file, label);
42495
+ let records = 0;
42496
+ let groupStart = 0;
42497
+ for (const rowGroup of metadata.row_groups) {
42498
+ const groupRows = Number(rowGroup.num_rows);
42499
+ const groupEnd = groupStart + groupRows;
42500
+ for (let rowStart = groupStart; rowStart < groupEnd; rowStart += this._batchRows) {
42501
+ const rowEnd = Math.min(rowStart + this._batchRows, groupEnd);
42502
+ const batch = await this._readParquetBatch({ file, metadata, compressors: compressors2, rowStart, rowEnd }, label);
42503
+ records += batch.length;
42504
+ yield batch.map((record) => hyparquet.toJson(record));
42505
+ }
42506
+ groupStart = groupEnd;
42507
+ }
42508
+ Logger_default.log(`Delta Share read ${records} record(s) from ${label} in ${Date.now() - startedMs}ms`);
42509
+ }
42510
+ // The buffer is opened inside the generator so nothing is fetched until the first batch is pulled
42511
+ async *_streamParquetBatchesFrom(open, label) {
42512
+ yield* this._streamParquetBatches(await open(), label);
42282
42513
  }
42283
42514
  };
42284
42515
  DeltaShareDriver_default = DeltaShareSourceDriver;
@@ -42802,8 +43033,8 @@ var init_HttpClient = __esm({
42802
43033
  throw new Error(err2.message ?? "An error occurred on GET.");
42803
43034
  }
42804
43035
  };
42805
- this.getWorkerUrl = (path20) => {
42806
- const cleanPath = path20.startsWith("/") ? path20.substring(1) : path20;
43036
+ this.getWorkerUrl = (path21) => {
43037
+ const cleanPath = path21.startsWith("/") ? path21.substring(1) : path21;
42807
43038
  return `${this.workerHost}/${cleanPath}`;
42808
43039
  };
42809
43040
  this.workerHost = ProcessENVManager_default.getEnvVariable("REMORA_WORKER_HOST") || "http://worker:5069";
@@ -42825,12 +43056,12 @@ var init_src7 = __esm({
42825
43056
  });
42826
43057
 
42827
43058
  // ../../packages/drivers/src/DriverHelper.ts
42828
- var import_stream, import_readline, import_promises8, import_fs9, DriverHelper, DriverHelper_default;
43059
+ var import_stream2, import_readline, import_promises9, import_fs9, DriverHelper, DriverHelper_default;
42829
43060
  var init_DriverHelper = __esm({
42830
43061
  "../../packages/drivers/src/DriverHelper.ts"() {
42831
- import_stream = require("stream");
43062
+ import_stream2 = require("stream");
42832
43063
  import_readline = require("readline");
42833
- import_promises8 = require("stream/promises");
43064
+ import_promises9 = require("stream/promises");
42834
43065
  import_fs9 = require("fs");
42835
43066
  init_src2();
42836
43067
  init_src();
@@ -42847,7 +43078,7 @@ var init_DriverHelper = __esm({
42847
43078
  let leftoverData = "";
42848
43079
  let globalIndex = 0;
42849
43080
  let lineCount = 0;
42850
- const headerValidationTransform = new import_stream.Transform({
43081
+ const headerValidationTransform = new import_stream2.Transform({
42851
43082
  transform(chunk, encoding, callback) {
42852
43083
  const chunkStr = leftoverData + chunk.toString();
42853
43084
  const lines = chunkStr.split("\n");
@@ -42923,7 +43154,7 @@ var init_DriverHelper = __esm({
42923
43154
  };
42924
43155
  const writeOptions = append ? { flags: "a" } : {};
42925
43156
  const writeStream = (0, import_fs9.createWriteStream)(destinationPath, writeOptions);
42926
- await (0, import_promises8.pipeline)(stream, headerValidationTransform, writeStream);
43157
+ await (0, import_promises9.pipeline)(stream, headerValidationTransform, writeStream);
42927
43158
  return lineCount;
42928
43159
  },
42929
43160
  appendObjectsToUnifiedFile: async (options) => {
@@ -42949,32 +43180,32 @@ var init_DriverHelper = __esm({
42949
43180
  },
42950
43181
  quickReadFile: async (filePath, lineCount) => {
42951
43182
  const fileStream = (0, import_fs9.createReadStream)(filePath);
42952
- const rl7 = (0, import_readline.createInterface)({ input: fileStream, crlfDelay: Infinity });
43183
+ const rl8 = (0, import_readline.createInterface)({ input: fileStream, crlfDelay: Infinity });
42953
43184
  const lines = [];
42954
43185
  let counter = 0;
42955
- for await (const line of rl7) {
43186
+ for await (const line of rl8) {
42956
43187
  lines.push(line);
42957
43188
  counter++;
42958
43189
  if (counter >= lineCount) {
42959
43190
  break;
42960
43191
  }
42961
43192
  }
42962
- rl7.close();
43193
+ rl8.close();
42963
43194
  fileStream.close();
42964
43195
  return lines;
42965
43196
  },
42966
43197
  quickReadStream: async (stream, lineCount) => {
42967
- const rl7 = (0, import_readline.createInterface)({ input: stream, crlfDelay: Infinity });
43198
+ const rl8 = (0, import_readline.createInterface)({ input: stream, crlfDelay: Infinity });
42968
43199
  const lines = [];
42969
43200
  let counter = 0;
42970
- for await (const line of rl7) {
43201
+ for await (const line of rl8) {
42971
43202
  lines.push(line);
42972
43203
  counter++;
42973
43204
  if (counter >= lineCount) {
42974
43205
  break;
42975
43206
  }
42976
43207
  }
42977
- rl7.close();
43208
+ rl8.close();
42978
43209
  return lines;
42979
43210
  }
42980
43211
  };
@@ -43233,11 +43464,11 @@ var init_LocalSourceDriver = __esm({
43233
43464
  });
43234
43465
 
43235
43466
  // ../../packages/drivers/src/files/LocalDestinationDriver.ts
43236
- var fs11, import_promises9, import_readline3, import_path10, LocalDestinationDriver;
43467
+ var fs11, import_promises10, import_readline3, import_path10, LocalDestinationDriver;
43237
43468
  var init_LocalDestinationDriver = __esm({
43238
43469
  "../../packages/drivers/src/files/LocalDestinationDriver.ts"() {
43239
43470
  fs11 = __toESM(require("fs"), 1);
43240
- import_promises9 = __toESM(require("fs/promises"), 1);
43471
+ import_promises10 = __toESM(require("fs/promises"), 1);
43241
43472
  import_readline3 = __toESM(require("readline"), 1);
43242
43473
  import_path10 = __toESM(require("path"), 1);
43243
43474
  init_src();
@@ -43272,8 +43503,8 @@ var init_LocalDestinationDriver = __esm({
43272
43503
  this.move = async (fromPath, toName) => {
43273
43504
  try {
43274
43505
  const toFilePath = import_path10.default.join(this._path, toName);
43275
- await import_promises9.default.copyFile(fromPath, toFilePath);
43276
- await import_promises9.default.unlink(fromPath);
43506
+ await import_promises10.default.copyFile(fromPath, toFilePath);
43507
+ await import_promises10.default.unlink(fromPath);
43277
43508
  return { bucket: "", key: toFilePath, res: true };
43278
43509
  } catch (error) {
43279
43510
  Logger_default.error(error);
@@ -43309,14 +43540,14 @@ var init_LocalDestinationDriver = __esm({
43309
43540
  });
43310
43541
 
43311
43542
  // ../../packages/drivers/src/s3/S3SourceDriver.ts
43312
- var import_client_s32, import_stream2, import_promises10, import_readline4, import_path11, import_fs10, import_xlsx2, S3SourceDriver;
43543
+ var import_client_s32, import_stream3, import_promises11, import_readline4, import_path11, import_fs10, import_xlsx2, S3SourceDriver;
43313
43544
  var init_S3SourceDriver = __esm({
43314
43545
  "../../packages/drivers/src/s3/S3SourceDriver.ts"() {
43315
43546
  import_client_s32 = require("@aws-sdk/client-s3");
43316
43547
  init_src();
43317
43548
  init_AwsCredentials();
43318
- import_stream2 = require("stream");
43319
- import_promises10 = require("stream/promises");
43549
+ import_stream3 = require("stream");
43550
+ import_promises11 = require("stream/promises");
43320
43551
  import_readline4 = __toESM(require("readline"), 1);
43321
43552
  import_path11 = __toESM(require("path"), 1);
43322
43553
  import_fs10 = __toESM(require("fs"), 1);
@@ -43584,7 +43815,7 @@ var init_S3SourceDriver = __esm({
43584
43815
  }
43585
43816
  const totalBytes = response.ContentLength ?? 0;
43586
43817
  let stagedBytes = 0;
43587
- const meter = new import_stream2.Transform({
43818
+ const meter = new import_stream3.Transform({
43588
43819
  transform(chunk, _encoding, done) {
43589
43820
  stagedBytes += chunk.length;
43590
43821
  if (totalBytes > 0)
@@ -43593,7 +43824,7 @@ var init_S3SourceDriver = __esm({
43593
43824
  }
43594
43825
  });
43595
43826
  const writeStream = import_fs10.default.createWriteStream(localPath);
43596
- await (0, import_promises10.pipeline)(response.Body, meter, writeStream);
43827
+ await (0, import_promises11.pipeline)(response.Body, meter, writeStream);
43597
43828
  report(1);
43598
43829
  };
43599
43830
  if (fileKey.includes("%")) {
@@ -43748,7 +43979,7 @@ var init_S3DestinationDriver = __esm({
43748
43979
  });
43749
43980
 
43750
43981
  // ../../packages/drivers/src/DriverFactory.ts
43751
- var DriverFactoryClass, DriverFactory, DriverFactory_default;
43982
+ var STAGEABLE_ENGINES, DriverFactoryClass, DriverFactory, DriverFactory_default;
43752
43983
  var init_DriverFactory = __esm({
43753
43984
  "../../packages/drivers/src/DriverFactory.ts"() {
43754
43985
  init_RedshiftDriver();
@@ -43758,8 +43989,11 @@ var init_DriverFactory = __esm({
43758
43989
  init_LocalDestinationDriver();
43759
43990
  init_S3SourceDriver();
43760
43991
  init_S3DestinationDriver();
43992
+ STAGEABLE_ENGINES = ["local", "aws-s3", "delta-share"];
43761
43993
  DriverFactoryClass = class {
43762
43994
  constructor() {
43995
+ /** Whether a run can stage a producer from this engine — see `STAGEABLE_ENGINES`. */
43996
+ this.canStage = (engine) => STAGEABLE_ENGINES.includes(engine);
43763
43997
  this.instantiateSource = async (source) => {
43764
43998
  switch (source.engine) {
43765
43999
  case "aws-redshift": {
@@ -43839,6 +44073,7 @@ var init_ProducerManager = __esm({
43839
44073
  init_src4();
43840
44074
  init_src3();
43841
44075
  init_src5();
44076
+ init_CryptoEngine();
43842
44077
  ProducerManagerClass = class {
43843
44078
  constructor() {
43844
44079
  this.getColumns = (producer) => {
@@ -43893,6 +44128,46 @@ var init_ProducerManager = __esm({
43893
44128
  return true;
43894
44129
  return FixedWidthParser_default.matchesSelector(line, resolved.selector, resolved.range);
43895
44130
  };
44131
+ /**
44132
+ * The post-parse work a producer implies for every record it produces: which keys carry the
44133
+ * source file name, and which carry a mask.
44134
+ *
44135
+ * Resolved once per chunk, never per line — `getMask` resolves a secret and validates the value,
44136
+ * and neither depends on the record. Empty for almost every producer, which is the case worth
44137
+ * keeping fast.
44138
+ */
44139
+ this.compileFills = (dimensions) => {
44140
+ Affirm_default(dimensions, "Invalid producer dimensions");
44141
+ const fills = [];
44142
+ for (const dimension of dimensions) {
44143
+ const { prodDimension } = dimension;
44144
+ const mask = this.getMask(prodDimension);
44145
+ const sourceFilename = prodDimension.sourceFilename === true;
44146
+ if (!sourceFilename && !Algo_default.hasVal(mask))
44147
+ continue;
44148
+ fills.push({ key: dimension.name, mask, sourceFilename, type: prodDimension.type });
44149
+ }
44150
+ return fills;
44151
+ };
44152
+ /**
44153
+ * Applies the compiled fills to one parsed record, in place.
44154
+ *
44155
+ * The one place a producer dimension's mask is ever applied, on purpose: a run reaches it through
44156
+ * `ProducerExecutor.processLine` and a sample through `ProducerEngine`, and a masked dimension
44157
+ * that came back in the clear from one of the two would be a `hash` the project declared and the
44158
+ * screen ignored — a disclosure, not a display bug.
44159
+ */
44160
+ this.applyFills = (record, fills, sourceFilename) => {
44161
+ if (!fills?.length)
44162
+ return record;
44163
+ for (const fill2 of fills) {
44164
+ if (fill2.sourceFilename)
44165
+ record[fill2.key] = sourceFilename;
44166
+ if (Algo_default.hasVal(fill2.mask))
44167
+ record[fill2.key] = CryptoEngine_default.hashValue(fill2.mask, record[fill2.key]?.toString(), fill2.type);
44168
+ }
44169
+ return record;
44170
+ };
43896
44171
  }
43897
44172
  };
43898
44173
  ProducerManager = new ProducerManagerClass();
@@ -43929,7 +44204,7 @@ var init_TypeCaster = __esm({
43929
44204
  * - Parsing dates (type 'date'/'datetime') from string with tokens: yyyy, mm, dd
43930
44205
  * - Formatting dates when casting to string with same tokens
43931
44206
  */
43932
- cast(value, type, format3) {
44207
+ cast(value, type, format4) {
43933
44208
  if (!Algo_default.hasVal(value)) return value;
43934
44209
  switch (type) {
43935
44210
  case "boolean": {
@@ -43940,8 +44215,8 @@ var init_TypeCaster = __esm({
43940
44215
  case "date": {
43941
44216
  let dateValue = null;
43942
44217
  try {
43943
- if (format3 && typeof value === "string")
43944
- dateValue = this.parseDate(value, format3, true).toDate();
44218
+ if (format4 && typeof value === "string")
44219
+ dateValue = this.parseDate(value, format4, true).toDate();
43945
44220
  else
43946
44221
  dateValue = new Date(value);
43947
44222
  return dateValue.toISOString();
@@ -43949,7 +44224,7 @@ var init_TypeCaster = __esm({
43949
44224
  dateValue = new Date(value);
43950
44225
  if (!isNaN(dateValue))
43951
44226
  return dateValue.toISOString();
43952
- throw new Error(`Error casting "${value}" to date with format "${format3}": ${error}`);
44227
+ throw new Error(`Error casting "${value}" to date with format "${format4}": ${error}`);
43953
44228
  }
43954
44229
  }
43955
44230
  case "number": {
@@ -43976,13 +44251,13 @@ var init_TypeCaster = __esm({
43976
44251
  * advancedFormat plugin, and then unpadded for `DDD`, while a positional ordinal date is always
43977
44252
  * 3 digits wide; the token is therefore rendered here rather than handed to dayjs.
43978
44253
  */
43979
- formatDate(value, format3) {
44254
+ formatDate(value, format4) {
43980
44255
  const date2 = import_dayjs.default.utc(value);
43981
- if (!DAY_OF_YEAR_TOKEN.test(this._stripLiterals(format3)))
43982
- return date2.format(format3);
44256
+ if (!DAY_OF_YEAR_TOKEN.test(this._stripLiterals(format4)))
44257
+ return date2.format(format4);
43983
44258
  const startOfYear = import_dayjs.default.utc(`${String(date2.year()).padStart(4, "0")}-01-01`, "YYYY-MM-DD", true);
43984
44259
  const dayOfYear = date2.diff(startOfYear, "day") + 1;
43985
- return date2.format(format3.replace(/D{3,4}/g, `[${String(dayOfYear).padStart(3, "0")}]`));
44260
+ return date2.format(format4.replace(/D{3,4}/g, `[${String(dayOfYear).padStart(3, "0")}]`));
43986
44261
  }
43987
44262
  /**
43988
44263
  * Parses a date string with a dayjs format, as UTC. Single entry point for every date parse, so
@@ -43991,13 +44266,13 @@ var init_TypeCaster = __esm({
43991
44266
  * ever FORMAT with are rejected outright — non-strict parsing would otherwise read `2007305` as
43992
44267
  * 2007-01-05 rather than 2007-11-01 and report no error at all.
43993
44268
  */
43994
- parseDate(value, format3, strict = true) {
43995
- if (DAY_OF_YEAR_TOKEN.test(this._stripLiterals(format3)))
43996
- return this._parseDayOfYear(value, format3);
43997
- this._assertParsableFormat(format3);
43998
- const parsed = import_dayjs.default.utc(value, format3, strict);
44269
+ parseDate(value, format4, strict = true) {
44270
+ if (DAY_OF_YEAR_TOKEN.test(this._stripLiterals(format4)))
44271
+ return this._parseDayOfYear(value, format4);
44272
+ this._assertParsableFormat(format4);
44273
+ const parsed = import_dayjs.default.utc(value, format4, strict);
43999
44274
  if (!parsed.isValid())
44000
- throw new Error(`Cannot parse "${value}" with input format "${format3}"`);
44275
+ throw new Error(`Cannot parse "${value}" with input format "${format4}"`);
44001
44276
  return parsed;
44002
44277
  }
44003
44278
  /**
@@ -44006,61 +44281,61 @@ var init_TypeCaster = __esm({
44006
44281
  * walked token by token against the format — every token of such a format has a fixed width, so
44007
44282
  * a plain cursor is enough — and the date is then built from the year plus the ordinal offset.
44008
44283
  */
44009
- _parseDayOfYear(value, format3) {
44284
+ _parseDayOfYear(value, format4) {
44010
44285
  const parts = {};
44011
44286
  let cursor = 0;
44012
44287
  let index = 0;
44013
- while (index < format3.length) {
44014
- if (format3[index] === "[") {
44015
- const close = format3.indexOf("]", index);
44288
+ while (index < format4.length) {
44289
+ if (format4[index] === "[") {
44290
+ const close = format4.indexOf("]", index);
44016
44291
  if (close < 0)
44017
- throw new Error(`Unterminated "[" literal in date format "${format3}"`);
44018
- const literal2 = format3.slice(index + 1, close);
44292
+ throw new Error(`Unterminated "[" literal in date format "${format4}"`);
44293
+ const literal2 = format4.slice(index + 1, close);
44019
44294
  if (value.slice(cursor, cursor + literal2.length) !== literal2)
44020
- throw new Error(`Cannot parse "${value}" with input format "${format3}": expected "${literal2}" at character ${cursor + 1}`);
44295
+ throw new Error(`Cannot parse "${value}" with input format "${format4}": expected "${literal2}" at character ${cursor + 1}`);
44021
44296
  cursor += literal2.length;
44022
44297
  index = close + 1;
44023
44298
  continue;
44024
44299
  }
44025
- const match = DATE_PARSE_TOKENS.find((x2) => format3.startsWith(x2.token, index));
44300
+ const match = DATE_PARSE_TOKENS.find((x2) => format4.startsWith(x2.token, index));
44026
44301
  if (!match) {
44027
- if (/[A-Za-z]/.test(format3[index]))
44028
- throw new Error(`Date format "${format3}" mixes a day-of-year token with "${format3[index]}", which can't be parsed alongside it. Use YYYY/YY, DDD/DDDD, HH, mm, ss and SSS only.`);
44029
- if (value[cursor] !== format3[index])
44030
- throw new Error(`Cannot parse "${value}" with input format "${format3}": expected "${format3[index]}" at character ${cursor + 1}`);
44302
+ if (/[A-Za-z]/.test(format4[index]))
44303
+ throw new Error(`Date format "${format4}" mixes a day-of-year token with "${format4[index]}", which can't be parsed alongside it. Use YYYY/YY, DDD/DDDD, HH, mm, ss and SSS only.`);
44304
+ if (value[cursor] !== format4[index])
44305
+ throw new Error(`Cannot parse "${value}" with input format "${format4}": expected "${format4[index]}" at character ${cursor + 1}`);
44031
44306
  cursor++;
44032
44307
  index++;
44033
44308
  continue;
44034
44309
  }
44035
44310
  const digits = value.slice(cursor, cursor + match.width);
44036
44311
  if (digits.length !== match.width || !/^\d+$/.test(digits))
44037
- throw new Error(`Cannot parse "${value}" with input format "${format3}": expected ${match.width} digit(s) for "${match.token}" at character ${cursor + 1}`);
44312
+ throw new Error(`Cannot parse "${value}" with input format "${format4}": expected ${match.width} digit(s) for "${match.token}" at character ${cursor + 1}`);
44038
44313
  parts[match.token] = Number(digits);
44039
44314
  cursor += match.width;
44040
44315
  index += match.token.length;
44041
44316
  }
44042
44317
  if (cursor !== value.length)
44043
- throw new Error(`Cannot parse "${value}" with input format "${format3}": ${value.length - cursor} unexpected trailing character(s)`);
44318
+ throw new Error(`Cannot parse "${value}" with input format "${format4}": ${value.length - cursor} unexpected trailing character(s)`);
44044
44319
  const year2 = Algo_default.hasVal(parts["YYYY"]) ? parts["YYYY"] : parts["YY"];
44045
44320
  const dayOfYear = Algo_default.hasVal(parts["DDDD"]) ? parts["DDDD"] : parts["DDD"];
44046
44321
  if (!Algo_default.hasVal(year2))
44047
- throw new Error(`Date format "${format3}" declares a day of year but no year, so the date is ambiguous.`);
44322
+ throw new Error(`Date format "${format4}" declares a day of year but no year, so the date is ambiguous.`);
44048
44323
  const startOfYear = import_dayjs.default.utc(`${String(year2).padStart(4, "0")}-01-01`, "YYYY-MM-DD", true);
44049
44324
  if (!startOfYear.isValid())
44050
- throw new Error(`Cannot parse "${value}" with input format "${format3}": "${year2}" is not a valid year`);
44325
+ throw new Error(`Cannot parse "${value}" with input format "${format4}": "${year2}" is not a valid year`);
44051
44326
  const parsed = startOfYear.add(dayOfYear - 1, "day").add(parts["HH"] ?? 0, "hour").add(parts["mm"] ?? 0, "minute").add(parts["ss"] ?? 0, "second").add(parts["SSS"] ?? 0, "millisecond");
44052
44327
  if (dayOfYear < 1 || parsed.year() !== startOfYear.year())
44053
- throw new Error(`Cannot parse "${value}" with input format "${format3}": day of year ${dayOfYear} is outside year ${year2} (which has ${startOfYear.add(1, "year").diff(startOfYear, "day")} days)`);
44328
+ throw new Error(`Cannot parse "${value}" with input format "${format4}": day of year ${dayOfYear} is outside year ${year2} (which has ${startOfYear.add(1, "year").diff(startOfYear, "day")} days)`);
44054
44329
  return parsed;
44055
44330
  }
44056
- _assertParsableFormat(format3) {
44057
- const stripped = this._stripLiterals(format3);
44331
+ _assertParsableFormat(format4) {
44332
+ const stripped = this._stripLiterals(format4);
44058
44333
  const offending = FORMAT_ONLY_TOKENS.find((token2) => stripped.includes(token2));
44059
44334
  if (offending)
44060
- throw new Error(`Date format "${format3}" uses the token "${offending}", which dayjs can only write, never read: parsing would silently produce the wrong date. Use a parseable token, or bracket it as a literal ("[${offending}]") if it is part of the text.`);
44335
+ throw new Error(`Date format "${format4}" uses the token "${offending}", which dayjs can only write, never read: parsing would silently produce the wrong date. Use a parseable token, or bracket it as a literal ("[${offending}]") if it is part of the text.`);
44061
44336
  }
44062
- _stripLiterals(format3) {
44063
- return String(format3 ?? "").replace(/\[[^\]]*\]/g, "");
44337
+ _stripLiterals(format4) {
44338
+ return String(format4 ?? "").replace(/\[[^\]]*\]/g, "");
44064
44339
  }
44065
44340
  };
44066
44341
  TypeCaster = new TypeCasterClass();
@@ -44307,7 +44582,8 @@ var init_ProducerEngine = __esm({
44307
44582
  }
44308
44583
  };
44309
44584
  }
44310
- const fileData = await this.readFile(effectiveProducer, { readmode: "lines", lines: { from: 0, to: sampleSize } }, effectiveSource);
44585
+ const headerLines = ParseHelper_default.hasHeaderLine(effectiveProducer.settings.fileType, effectiveProducer.settings.hasHeaderRow) ? 1 : 0;
44586
+ const fileData = await this.readFile(effectiveProducer, { readmode: "lines", lines: { from: 0, to: sampleSize + headerLines } }, effectiveSource);
44311
44587
  rawData = fileData.data;
44312
44588
  } finally {
44313
44589
  if (scope)
@@ -44326,13 +44602,15 @@ var init_ProducerEngine = __esm({
44326
44602
  if (!rawData || rawData.length === 0) return [];
44327
44603
  const firstItem = rawData[0];
44328
44604
  const isLineData = typeof firstItem === "string";
44605
+ const fills = discover ? [] : ProducerManager_default.compileFills(this._fillDimensions(producer));
44606
+ const sourceFilename = import_path13.default.basename(producer.settings.fileKey ?? producer.settings.sqlTable ?? "");
44329
44607
  if (isLineData) {
44330
44608
  const lines = rawData;
44331
44609
  const dimensions = this.deriveDimensions(lines[0], producer, discover);
44332
44610
  const { fileType, hasHeaderRow } = producer.settings;
44333
44611
  const dataLines = ParseHelper_default.hasHeaderLine(fileType, hasHeaderRow) ? lines.slice(1) : lines;
44334
44612
  const recordSelector = ProducerManager_default.resolveRecordSelector(producer);
44335
- return dataLines.filter((line) => line.trim().length > 0).filter((line) => ProducerManager_default.shouldReadLine(line, recordSelector)).flatMap((line) => LineParser_default.parseAll(line, producer, dimensions, noopTracker));
44613
+ return dataLines.filter((line) => line.trim().length > 0).filter((line) => ProducerManager_default.shouldReadLine(line, recordSelector)).flatMap((line) => LineParser_default.parseAll(line, producer, dimensions, noopTracker)).map((record) => ProducerManager_default.applyFills(record, fills, sourceFilename));
44336
44614
  }
44337
44615
  if (discover) {
44338
44616
  return rawData.map((item) => ({ ...item }));
@@ -44343,9 +44621,15 @@ var init_ProducerEngine = __esm({
44343
44621
  const key = dim.alias ?? dim.name;
44344
44622
  record[dim.name] = TypeCaster_default.cast(item[key], dim.type, dim.format);
44345
44623
  }
44346
- return record;
44624
+ return ProducerManager_default.applyFills(record, fills, sourceFilename);
44347
44625
  });
44348
44626
  };
44627
+ /**
44628
+ * The producer's declared dimensions in the shape `compileFills` reads them in. Declaration
44629
+ * order, because a fill is addressed by key and never by position — unlike the executor
44630
+ * dimensions of a run, whose index is reconciled against the file's own header.
44631
+ */
44632
+ this._fillDimensions = (producer) => producer.dimensions.map((prodDimension, index) => ({ index, name: prodDimension.name, prodDimension }));
44349
44633
  /**
44350
44634
  * Builds the executor dimensions of a producer. There are two shapes of source: a FIXED file has
44351
44635
  * no header, so its layout comes from the positions declared on the dimensions; every other file
@@ -44443,7 +44727,7 @@ var init_ProducerEngine = __esm({
44443
44727
  });
44444
44728
 
44445
44729
  // ../../packages/engines/src/ai/DeveloperEngine.ts
44446
- var import_path14, import_promises11, import_dayjs2, import_customParseFormat2, DeveloperEngineClass, DeveloperEngine, DeveloperEngine_default;
44730
+ var import_path14, import_promises12, import_dayjs2, import_customParseFormat2, DeveloperEngineClass, DeveloperEngine, DeveloperEngine_default;
44447
44731
  var init_DeveloperEngine = __esm({
44448
44732
  "../../packages/engines/src/ai/DeveloperEngine.ts"() {
44449
44733
  init_src();
@@ -44451,7 +44735,7 @@ var init_DeveloperEngine = __esm({
44451
44735
  init_src4();
44452
44736
  init_src8();
44453
44737
  import_path14 = __toESM(require("path"), 1);
44454
- import_promises11 = __toESM(require("fs/promises"), 1);
44738
+ import_promises12 = __toESM(require("fs/promises"), 1);
44455
44739
  import_dayjs2 = __toESM(require("dayjs"), 1);
44456
44740
  import_customParseFormat2 = __toESM(require("dayjs/plugin/customParseFormat"), 1);
44457
44741
  import_dayjs2.default.extend(import_customParseFormat2.default);
@@ -44481,8 +44765,8 @@ var init_DeveloperEngine = __esm({
44481
44765
  };
44482
44766
  mappedProducer["$schema"] = producer["$schema"];
44483
44767
  const producerPath = Environment_default.resolveResourceFilePath("producers", producer.name);
44484
- await import_promises11.default.mkdir(import_path14.default.dirname(producerPath), { recursive: true });
44485
- await import_promises11.default.writeFile(producerPath, JSON.stringify(mappedProducer, null, 4), "utf-8");
44768
+ await import_promises12.default.mkdir(import_path14.default.dirname(producerPath), { recursive: true });
44769
+ await import_promises12.default.writeFile(producerPath, JSON.stringify(mappedProducer, null, 4), "utf-8");
44486
44770
  return { producer: mappedProducer, fields: typeDefinitions };
44487
44771
  };
44488
44772
  // Discover-only precondition: sampling real data requires a configured, readable file.
@@ -46813,9 +47097,10 @@ var init_MockDataFactory = __esm({
46813
47097
  if (type === "number") {
46814
47098
  const first = bounds?.min ?? 1;
46815
47099
  const last = first + poolSize - 1;
47100
+ const ceiling = bounds?.max;
46816
47101
  Affirm_default(
46817
- bounds?.max === void 0 || bounds.max >= last,
46818
- `Key "${norm}" has a synth range of ${first}-${bounds.max}, which holds fewer than the ${poolSize} distinct values it has to generate; widen it or generate fewer records`
47102
+ ceiling === void 0 || ceiling >= last,
47103
+ `Key "${norm}" has a synth range of ${first}-${ceiling}, which holds fewer than the ${poolSize} distinct values it has to generate; widen it or generate fewer records`
46819
47104
  );
46820
47105
  for (let i6 = 0; i6 < poolSize; i6++) pool.push(first + i6);
46821
47106
  return pool;
@@ -47018,10 +47303,10 @@ var init_MockDataFactory = __esm({
47018
47303
  });
47019
47304
 
47020
47305
  // ../../packages/engines/src/mock/SyntheticInputEngine.ts
47021
- var import_promises12, import_os, import_path15, import_dayjs4, import_customParseFormat3, import_utc3, POOL_CAP, SyntheticInputEngineClass, SyntheticInputEngine;
47306
+ var import_promises13, import_os, import_path15, import_dayjs4, import_customParseFormat3, import_utc3, POOL_CAP, SyntheticInputEngineClass, SyntheticInputEngine;
47022
47307
  var init_SyntheticInputEngine = __esm({
47023
47308
  "../../packages/engines/src/mock/SyntheticInputEngine.ts"() {
47024
- import_promises12 = __toESM(require("fs/promises"), 1);
47309
+ import_promises13 = __toESM(require("fs/promises"), 1);
47025
47310
  import_os = __toESM(require("os"), 1);
47026
47311
  import_path15 = __toESM(require("path"), 1);
47027
47312
  import_dayjs4 = __toESM(require("dayjs"), 1);
@@ -47047,7 +47332,7 @@ var init_SyntheticInputEngine = __esm({
47047
47332
  for (const cs2 of [...BUILTIN_CODE_SETS, ...codeSets]) codeSetMap.set(cs2.name.toLowerCase(), cs2);
47048
47333
  const producerMap = new Map(producers.map((p5) => [p5.name, p5]));
47049
47334
  const refTargets = this._collectReferences(producers, producerMap);
47050
- const dir = await import_promises12.default.mkdtemp(import_path15.default.join(import_os.default.tmpdir(), "remora-synth-"));
47335
+ const dir = await import_promises13.default.mkdtemp(import_path15.default.join(import_os.default.tmpdir(), "remora-synth-"));
47051
47336
  const poolSize = Math.min(Math.max(opts.records, 1), POOL_CAP);
47052
47337
  const registry = new MockKeyRegistry();
47053
47338
  const specs = producers.flatMap((p5) => this._specs(p5, codeSetMap, producerMap, refTargets));
@@ -47064,7 +47349,7 @@ var init_SyntheticInputEngine = __esm({
47064
47349
  return { inputs, dir };
47065
47350
  };
47066
47351
  this.cleanup = async (bundle) => {
47067
- if (bundle?.dir) await import_promises12.default.rm(bundle.dir, { recursive: true, force: true });
47352
+ if (bundle?.dir) await import_promises13.default.rm(bundle.dir, { recursive: true, force: true });
47068
47353
  };
47069
47354
  this._assertOpts = (opts) => {
47070
47355
  Affirm_default(opts, "Invalid options");
@@ -47114,8 +47399,8 @@ var init_SyntheticInputEngine = __esm({
47114
47399
  lines.push(JSON.stringify(row) + "\n");
47115
47400
  }
47116
47401
  const filePath = import_path15.default.join(dir, `${producer.name}.jsonl`);
47117
- await import_promises12.default.writeFile(filePath, lines.join(""), "utf-8");
47118
- const { size } = await import_promises12.default.stat(filePath);
47402
+ await import_promises13.default.writeFile(filePath, lines.join(""), "utf-8");
47403
+ const { size } = await import_promises13.default.stat(filePath);
47119
47404
  return { path: filePath, fileSize: size };
47120
47405
  };
47121
47406
  // Distinct structured code sets referenced by these specs -> their records (deduped by name).
@@ -47226,7 +47511,7 @@ var init_SyntheticInputEngine = __esm({
47226
47511
  // True when a date bound names a day rather than an instant — neither the value nor the dimension's
47227
47512
  // format carries a time. Both have to agree: the value alone can't tell `"20240131"` from a compact
47228
47513
  // `YYYYMMDDHHmmss` instant, and the format alone can't tell that an ISO value overrode it.
47229
- this._isDayGranular = (value, format3) => !/[T ]\d{1,2}:/.test(value) && !/[HhmsSAa]/.test(format3 ?? "");
47514
+ this._isDayGranular = (value, format4) => !/[T ]\d{1,2}:/.test(value) && !/[HhmsSAa]/.test(format4 ?? "");
47230
47515
  /**
47231
47516
  * One bound in the units the generator works in: the number itself, a count of characters for a
47232
47517
  * `string`, or epoch milliseconds for a `datetime`. A date bound is read with the dimension's own
@@ -48155,23 +48440,23 @@ var init_Diagnostics = __esm({
48155
48440
  return [.../* @__PURE__ */ new Set([...inputs, ...chained])];
48156
48441
  };
48157
48442
  this._walk = (start, next, onCycle) => {
48158
- const path20 = [];
48443
+ const path21 = [];
48159
48444
  const onPath = /* @__PURE__ */ new Set();
48160
48445
  const stack = [{ name: start, done: false }];
48161
48446
  const visited = /* @__PURE__ */ new Set();
48162
48447
  while (stack.length > 0) {
48163
48448
  const frame = stack.pop();
48164
48449
  if (frame.done) {
48165
- onPath.delete(path20.pop());
48450
+ onPath.delete(path21.pop());
48166
48451
  continue;
48167
48452
  }
48168
48453
  if (onPath.has(frame.name)) {
48169
- path20.slice(path20.indexOf(frame.name)).forEach((name) => onCycle.add(name));
48454
+ path21.slice(path21.indexOf(frame.name)).forEach((name) => onCycle.add(name));
48170
48455
  continue;
48171
48456
  }
48172
48457
  if (visited.has(frame.name)) continue;
48173
48458
  visited.add(frame.name);
48174
- path20.push(frame.name);
48459
+ path21.push(frame.name);
48175
48460
  onPath.add(frame.name);
48176
48461
  stack.push({ name: frame.name, done: true });
48177
48462
  const successors = next.get(frame.name) ?? [];
@@ -48514,7 +48799,7 @@ var init_LineageRenderer = __esm({
48514
48799
  });
48515
48800
 
48516
48801
  // ../../packages/engines/src/lineage/ResourceView.ts
48517
- var VISIBLE_AUTH_KEYS, MAX_TABLE_ROWS, MAX_RAW_BYTES, MAX_CELL_CHARS, ResourceViewClass, ResourceView, ResourceView_default;
48802
+ var VISIBLE_AUTH_KEYS, MAX_TABLE_ROWS, MAX_RAW_BYTES, MAX_CELL_CHARS, MAX_NOTE_CHARS, ResourceViewClass, ResourceView, ResourceView_default;
48518
48803
  var init_ResourceView = __esm({
48519
48804
  "../../packages/engines/src/lineage/ResourceView.ts"() {
48520
48805
  init_src();
@@ -48553,6 +48838,7 @@ var init_ResourceView = __esm({
48553
48838
  MAX_TABLE_ROWS = 500;
48554
48839
  MAX_RAW_BYTES = 256 * 1024;
48555
48840
  MAX_CELL_CHARS = 200;
48841
+ MAX_NOTE_CHARS = 240;
48556
48842
  ResourceViewClass = class {
48557
48843
  constructor() {
48558
48844
  /**
@@ -48724,7 +49010,7 @@ var init_ResourceView = __esm({
48724
49010
  { key: "classification", label: "Classification" }
48725
49011
  ];
48726
49012
  const rows = dimensions.map((dimension) => [
48727
- { value: dimension.name },
49013
+ { value: dimension.name, note: this._note(dimension.description) },
48728
49014
  { value: this._text(dimension.type) },
48729
49015
  positioned ? { value: this._position(dimension.position) } : { value: this._text(dimension.alias), muted: !dimension.alias },
48730
49016
  { value: !!dimension.pk, muted: !dimension.pk },
@@ -48736,7 +49022,7 @@ var init_ResourceView = __esm({
48736
49022
  };
48737
49023
  this._measuresTable = (producer) => {
48738
49024
  const rows = (producer.measures ?? []).map((measure) => [
48739
- { value: measure.name },
49025
+ { value: measure.name, note: this._note(measure.description) },
48740
49026
  { value: measure.sql }
48741
49027
  ]);
48742
49028
  return this._table("Measures", [
@@ -48802,7 +49088,7 @@ var init_ResourceView = __esm({
48802
49088
  };
48803
49089
  this._consumerFieldsTable = (env2, consumer) => {
48804
49090
  const rows = (consumer.fields ?? []).map((field) => [
48805
- { value: field.key },
49091
+ { value: field.key, note: this._note(field.description) },
48806
49092
  { value: this._text(field.alias), muted: !field.alias },
48807
49093
  { value: this._text(field.from), link: field.from ? this._inputLink(env2, field.from) : void 0, muted: !field.from },
48808
49094
  { value: this._text(field.transform ? Object.keys(field.transform) : null), muted: !field.transform },
@@ -48848,8 +49134,8 @@ var init_ResourceView = __esm({
48848
49134
  if (!source || origin.path.length < 2) return { value: "declared here", muted: true };
48849
49135
  return { value: `${source.resource}.${source.field}`, link: source.node };
48850
49136
  };
48851
- this._pathText = (path20) => {
48852
- return path20.map((step) => `${step.resource}.${step.field}`).join(" \u2192 ");
49137
+ this._pathText = (path21) => {
49138
+ return path21.map((step) => `${step.resource}.${step.field}`).join(" \u2192 ");
48853
49139
  };
48854
49140
  this._consumerOutputsTable = (env2, consumer) => {
48855
49141
  const declared = new Set((env2.sources ?? []).map((x2) => x2.name));
@@ -48891,7 +49177,7 @@ var init_ResourceView = __esm({
48891
49177
  const required = new Set(schema.required ?? []);
48892
49178
  const properties = Object.entries(schema.properties ?? {});
48893
49179
  const rows = properties.map(([property, definition]) => [
48894
- { value: property },
49180
+ { value: property, note: this._note(this._schemaKeyword(definition, "description")) },
48895
49181
  { value: this._schemaType(definition) },
48896
49182
  { value: required.has(property), muted: !required.has(property) },
48897
49183
  { value: this._text(this._schemaKeyword(definition, "format")), muted: !this._schemaKeyword(definition, "format") }
@@ -48997,6 +49283,15 @@ var init_ResourceView = __esm({
48997
49283
  const minutes = Math.floor(elapsedMS / 6e4);
48998
49284
  return `${minutes}m ${Math.round(elapsedMS % 6e4 / 1e3)}s`;
48999
49285
  };
49286
+ /**
49287
+ * A description as the secondary line of a cell. Blank prose is the same as none, so a field
49288
+ * documented with a stray space does not cost the row a line.
49289
+ */
49290
+ this._note = (description) => {
49291
+ const text = (description ?? "").trim();
49292
+ if (!text) return void 0;
49293
+ return text.length > MAX_NOTE_CHARS ? `${text.slice(0, MAX_NOTE_CHARS)}\u2026` : text;
49294
+ };
49000
49295
  /** Anything that is not already a scalar becomes readable text; absent becomes `null`. */
49001
49296
  this._text = (value) => {
49002
49297
  if (value === void 0 || value === null) return null;
@@ -49601,7 +49896,7 @@ var init_OpsHeartbeat = __esm({
49601
49896
  "../../packages/engines/src/ops/OpsHeartbeat.ts"() {
49602
49897
  init_src2();
49603
49898
  init_OpsService();
49604
- DEFAULT_INTERVAL_MS = 6e4;
49899
+ DEFAULT_INTERVAL_MS = 3e5;
49605
49900
  MIN_INTERVAL_MS = 5e3;
49606
49901
  MAX_INTERVAL_MS = 36e5;
49607
49902
  OpsHeartbeatClass = class {
@@ -49641,11 +49936,24 @@ var init_OpsHeartbeat = __esm({
49641
49936
  Logger_default.error(error);
49642
49937
  }
49643
49938
  };
49939
+ /**
49940
+ * Resolve the configured interval, in milliseconds. A value that is unusable or out of range is
49941
+ * reported rather than silently replaced: an operator who set an interval and got a different
49942
+ * one has no other way to find out.
49943
+ */
49644
49944
  this.resolveInterval = () => {
49645
- const configured = Number(process.env.REMORA_STATE_INTERVAL_MS);
49646
- if (!Number.isFinite(configured) || configured <= 0)
49945
+ const raw = process.env.REMORA_STATE_INTERVAL_MS;
49946
+ if (!raw)
49947
+ return DEFAULT_INTERVAL_MS;
49948
+ const configured = Number(raw);
49949
+ if (!Number.isFinite(configured) || configured <= 0) {
49950
+ Logger_default.warn(`REMORA_STATE_INTERVAL_MS is not a positive number of milliseconds ("${raw}"); using ${DEFAULT_INTERVAL_MS}ms.`);
49647
49951
  return DEFAULT_INTERVAL_MS;
49648
- return Math.min(Math.max(configured, MIN_INTERVAL_MS), MAX_INTERVAL_MS);
49952
+ }
49953
+ const clamped = Math.min(Math.max(configured, MIN_INTERVAL_MS), MAX_INTERVAL_MS);
49954
+ if (clamped !== configured)
49955
+ Logger_default.warn(`REMORA_STATE_INTERVAL_MS of ${configured}ms is outside ${MIN_INTERVAL_MS}ms..${MAX_INTERVAL_MS}ms; using ${clamped}ms.`);
49956
+ return clamped;
49649
49957
  };
49650
49958
  }
49651
49959
  };
@@ -49879,17 +50187,30 @@ var init_LocalUsageDB = __esm({
49879
50187
  }
49880
50188
  };
49881
50189
  /**
49882
- * The recorded runs, newest first. Only the tail of the file is decoded: a reader wants the recent
50190
+ * The recorded runs, newest first — the newest `limit` of the rows `keep` accepts.
50191
+ *
50192
+ * Decoded from the end and stopped as soon as that many are held: a reader wants the recent
49883
50193
  * executions, and decoding ten thousand rows to show ten of them is work nobody asked for.
49884
50194
  *
50195
+ * `keep` is applied BEFORE the limit, which is the only way "the newest N runs of this kind" can
50196
+ * mean it: filtering afterwards lets the rows a caller does not want displace the ones it does,
50197
+ * so one sample recorded here would silently push a real run out of a history someone is reading.
50198
+ *
49885
50199
  * Never throws. A missing file reads as no history, and so does a half-written one — this store is
49886
50200
  * appended to while it is being read, so failing on that would make it unreadable during a run.
49887
50201
  */
49888
- this.list = (limit = MAX_LISTED_ROWS) => {
50202
+ this.list = (limit = MAX_LISTED_ROWS, keep) => {
49889
50203
  try {
49890
50204
  if (!(0, import_fs12.existsSync)(CLI_DB_PATH))
49891
50205
  return [];
49892
- return this._getRows().slice(-Math.max(1, limit)).map((line) => this._fromLine(line)).reverse();
50206
+ const rows = this._getRows();
50207
+ const wanted = Math.max(1, limit);
50208
+ const found = [];
50209
+ for (let index = rows.length - 1; index >= 0 && found.length < wanted; index--) {
50210
+ const usage = this._fromLine(rows[index]);
50211
+ if (!keep || keep(usage)) found.push(usage);
50212
+ }
50213
+ return found;
49893
50214
  } catch (error) {
49894
50215
  this._handleError("list", error);
49895
50216
  return [];
@@ -50070,9 +50391,10 @@ var init_UsageManager = __esm({
50070
50391
  });
50071
50392
 
50072
50393
  // ../../packages/engines/src/ops/RunOverlay.ts
50073
- var MAX_RUNS, MAX_OPERATIONS, RunOverlayClass, RunOverlay;
50394
+ var import_crypto4, MAX_RUNS, MAX_OPERATIONS, RunOverlayClass, RunOverlay;
50074
50395
  var init_RunOverlay = __esm({
50075
50396
  "../../packages/engines/src/ops/RunOverlay.ts"() {
50397
+ import_crypto4 = __toESM(require("crypto"), 1);
50076
50398
  init_src();
50077
50399
  init_LineageEngine();
50078
50400
  init_LocalUsageDB();
@@ -50081,6 +50403,8 @@ var init_RunOverlay = __esm({
50081
50403
  MAX_OPERATIONS = 40;
50082
50404
  RunOverlayClass = class {
50083
50405
  constructor() {
50406
+ /** The last store token read, and the overlay token it resolved to. */
50407
+ this._signed = { store: null, overlay: "" };
50084
50408
  /**
50085
50409
  * The recent executions and their aggregates. ONE read of the store answers both, so a page
50086
50410
  * showing a graph, a run list and a timing breakdown costs one file read rather than three.
@@ -50091,20 +50415,40 @@ var init_RunOverlay = __esm({
50091
50415
  this.read = (limit = MAX_RUNS) => {
50092
50416
  Affirm_default(limit > 0, "Run overlay limit must be greater than zero");
50093
50417
  if (!UsageManager_default.recordsLocally()) return { runs: [], metrics: {} };
50094
- const stats = LocalUsageDB_default.list(limit).filter((stat) => stat?.consumer);
50418
+ const stats = LocalUsageDB_default.list(limit, (stat) => !!stat?.consumer && stat.invokedBy !== "SAMPLE");
50095
50419
  return { runs: stats.map((stat) => this._run(stat)), metrics: this._metrics(stats) };
50096
50420
  };
50097
50421
  /**
50098
- * A token that changes when the run store does. Empty when there is nothing to read.
50422
+ * A token that changes when the OVERLAY does. Empty when there is nothing to read.
50099
50423
  *
50100
50424
  * A run finishing changes no configuration file, so the config hash cannot notice it — this is
50101
- * the second half of what the preview polls, and it is cheap for the same reason the hash is
50102
- * affordable: it reads metadata, not records.
50425
+ * the second half of what the preview polls.
50426
+ *
50427
+ * It signs the painted runs rather than the store, because the two do not move together: a
50428
+ * sample is recorded like any other execution and then filtered out of `read`, so the store's
50429
+ * own token changes while the picture does not. Signing the store there announced a project
50430
+ * change for every sample — and a page told its resource changed drops the sample it is showing,
50431
+ * which is exactly the rows someone had just asked for.
50432
+ *
50433
+ * Still cheap to poll: the store's mtime/size gates the read, so the rows are decoded only after
50434
+ * something has actually been written, never once a second.
50103
50435
  */
50104
50436
  this.signature = () => {
50105
50437
  if (!UsageManager_default.recordsLocally()) return "";
50106
- return LocalUsageDB_default.signature();
50438
+ const store = LocalUsageDB_default.signature();
50439
+ if (store === this._signed.store) return this._signed.overlay;
50440
+ const overlay = this._token(this.read());
50441
+ this._signed = { store, overlay };
50442
+ return overlay;
50107
50443
  };
50444
+ /**
50445
+ * A token over the whole overlay, runs and metrics alike.
50446
+ *
50447
+ * Everything it carries, not the newest row and a count: `endUsage` updates a row in place and a
50448
+ * finish action writes runs of its own, so a narrower token would miss a transition the graph
50449
+ * exists to show.
50450
+ */
50451
+ this._token = (overlay) => import_crypto4.default.createHash("sha256").update(JSON.stringify(overlay)).digest("hex");
50108
50452
  this._run = (stat) => {
50109
50453
  const startedAt = this._iso(stat.startedAt);
50110
50454
  return {
@@ -50350,63 +50694,6 @@ var init_PushdownEngine = __esm({
50350
50694
  }
50351
50695
  });
50352
50696
 
50353
- // ../../packages/engines/src/producer/SampleEngine.ts
50354
- var MAX_CHAIN_DEPTH2, SampleEngineClass, SampleEngine;
50355
- var init_SampleEngine = __esm({
50356
- "../../packages/engines/src/producer/SampleEngine.ts"() {
50357
- init_src();
50358
- init_src4();
50359
- init_ProducerEngine();
50360
- MAX_CHAIN_DEPTH2 = 20;
50361
- SampleEngineClass = class {
50362
- constructor() {
50363
- /**
50364
- * @param resourceName a producer or consumer name, as declared.
50365
- * @throws when the name is neither, or when the source cannot be read.
50366
- */
50367
- this.read = async (resourceName, size = 10) => {
50368
- Affirm_default(resourceName, "Missing resource name to sample");
50369
- Affirm_default(size > 0, "Sample size must be greater than 0");
50370
- const producer = Environment_default.getProducer(resourceName);
50371
- if (producer)
50372
- return { kind: "producer", name: resourceName, records: await ProducerEngine_default.readSampleData(producer, size, false) };
50373
- const consumer = Environment_default.getConsumer(resourceName);
50374
- Affirm_default(consumer, `Resource "${resourceName}" not found. Please check if it exists as a producer or consumer.`);
50375
- return { kind: "consumer", name: resourceName, records: await this._readConsumer(consumer, size, []) };
50376
- };
50377
- /**
50378
- * A consumer has no data of its own until it runs, so what it shows is its FIRST input, projected
50379
- * through its field list — near enough to answer "what will come out of this" without a run.
50380
- */
50381
- this._readConsumer = async (consumer, size, visited) => {
50382
- Affirm_default(!visited.includes(consumer.name), `Consumer "${consumer.name}" reads itself through ${visited.join(" \u2192 ")}`);
50383
- Affirm_default(visited.length < MAX_CHAIN_DEPTH2, `Consumer chain from "${visited[0]}" is more than ${MAX_CHAIN_DEPTH2} deep`);
50384
- const input = consumer.producers[0];
50385
- Affirm_default(input, `Consumer "${consumer.name}" has no producers configured`);
50386
- const producer = Environment_default.getProducer(input.name);
50387
- if (!producer) {
50388
- const upstream = Environment_default.getConsumer(input.name);
50389
- Affirm_default(upstream, `Producer or consumer "${input.name}" not found for consumer "${consumer.name}"`);
50390
- return this._readConsumer(upstream, size, [...visited, consumer.name]);
50391
- }
50392
- const records = await ProducerEngine_default.readSampleData(producer, size, false);
50393
- if (consumer.fields.some((field) => field.key === "*")) return records;
50394
- return records.map((record) => this._project(consumer, record));
50395
- };
50396
- this._project = (consumer, record) => {
50397
- const projected = {};
50398
- for (const field of consumer.fields) {
50399
- if (field.key === "*") continue;
50400
- projected[field.alias || field.key] = record[field.key];
50401
- }
50402
- return projected;
50403
- };
50404
- }
50405
- };
50406
- SampleEngine = new SampleEngineClass();
50407
- }
50408
- });
50409
-
50410
50697
  // ../../packages/engines/src/transform/LookupRegistry.ts
50411
50698
  var LookupRegistryClass, LookupRegistry, LookupRegistry_default;
50412
50699
  var init_LookupRegistry = __esm({
@@ -50443,12 +50730,12 @@ var init_LookupRegistry = __esm({
50443
50730
  });
50444
50731
 
50445
50732
  // ../../packages/engines/src/transform/LookupKey.ts
50446
- var import_crypto4, DELIMITER, idFor, LookupKey, LookupKey_default;
50733
+ var import_crypto5, DELIMITER, idFor, LookupKey, LookupKey_default;
50447
50734
  var init_LookupKey = __esm({
50448
50735
  "../../packages/engines/src/transform/LookupKey.ts"() {
50449
- import_crypto4 = __toESM(require("crypto"), 1);
50736
+ import_crypto5 = __toESM(require("crypto"), 1);
50450
50737
  DELIMITER = String.fromCharCode(0);
50451
- idFor = (ref) => import_crypto4.default.createHash("sha1").update([ref.consumer, ref.key, ref.value].join(DELIMITER)).digest("hex").slice(0, 16);
50738
+ idFor = (ref) => import_crypto5.default.createHash("sha1").update([ref.consumer, ref.key, ref.value].join(DELIMITER)).digest("hex").slice(0, 16);
50452
50739
  LookupKey = { idFor };
50453
50740
  LookupKey_default = LookupKey;
50454
50741
  }
@@ -50475,8 +50762,8 @@ var init_TransformationEngine = __esm({
50475
50762
  return result;
50476
50763
  }
50477
50764
  if ("cast" in transformations) {
50478
- const { cast, format: format3 } = transformations;
50479
- const casted = TypeCaster_default.cast(value, cast, format3);
50765
+ const { cast, format: format4 } = transformations;
50766
+ const casted = TypeCaster_default.cast(value, cast, format4);
50480
50767
  if (cast === "number" && isNaN(casted))
50481
50768
  throw new Error(`Cannot cast non-numeric value in field '${field.key}'`);
50482
50769
  if (cast === "datetime" && casted instanceof Date && isNaN(casted.getTime()))
@@ -51085,7 +51372,6 @@ var init_src10 = __esm({
51085
51372
  init_ProducerEngine();
51086
51373
  init_ProducerManager();
51087
51374
  init_PushdownEngine();
51088
- init_SampleEngine();
51089
51375
  init_TransformationEngine();
51090
51376
  init_TypeCaster();
51091
51377
  init_LookupRegistry();
@@ -51255,14 +51541,14 @@ var init_OutputExecutor = __esm({
51255
51541
  });
51256
51542
 
51257
51543
  // ../../packages/executors/src/ConsumerExecutor.ts
51258
- var import_path18, import_fs13, import_readline6, import_promises13, import_crypto5, LIMIT_SCAN_BYTES, NEWLINE_BYTE, ConsumerExecutorClass, ConsumerExecutor, ConsumerExecutor_default;
51544
+ var import_path18, import_fs13, import_readline6, import_promises14, import_crypto6, LIMIT_SCAN_BYTES, NEWLINE_BYTE, ConsumerExecutorClass, ConsumerExecutor, ConsumerExecutor_default;
51259
51545
  var init_ConsumerExecutor = __esm({
51260
51546
  "../../packages/executors/src/ConsumerExecutor.ts"() {
51261
51547
  import_path18 = __toESM(require("path"));
51262
51548
  import_fs13 = __toESM(require("fs"));
51263
51549
  import_readline6 = __toESM(require("readline"));
51264
- import_promises13 = __toESM(require("fs/promises"));
51265
- import_crypto5 = __toESM(require("crypto"));
51550
+ import_promises14 = __toESM(require("fs/promises"));
51551
+ import_crypto6 = __toESM(require("crypto"));
51266
51552
  init_src10();
51267
51553
  init_src10();
51268
51554
  init_src10();
@@ -51448,8 +51734,8 @@ var init_ConsumerExecutor = __esm({
51448
51734
  reader.destroy();
51449
51735
  });
51450
51736
  }
51451
- await import_promises13.default.unlink(datasetPath);
51452
- await import_promises13.default.rename(tempWorkPath, datasetPath);
51737
+ await import_promises14.default.unlink(datasetPath);
51738
+ await import_promises14.default.rename(tempWorkPath, datasetPath);
51453
51739
  return processedLineCount;
51454
51740
  };
51455
51741
  /**
@@ -51467,7 +51753,7 @@ var init_ConsumerExecutor = __esm({
51467
51753
  this.processLimit = async (datasetPath, limit) => {
51468
51754
  Affirm_default(datasetPath, "Invalid dataset path");
51469
51755
  Affirm_default(limit > 0, `Invalid record limit ${limit}`);
51470
- const handle = await import_promises13.default.open(datasetPath, "r+");
51756
+ const handle = await import_promises14.default.open(datasetPath, "r+");
51471
51757
  try {
51472
51758
  const buffer = Buffer.allocUnsafe(LIMIT_SCAN_BYTES);
51473
51759
  let newlines = 0;
@@ -51501,7 +51787,7 @@ var init_ConsumerExecutor = __esm({
51501
51787
  let newLineCount = 0;
51502
51788
  const seen = /* @__PURE__ */ new Set();
51503
51789
  for await (const line of lineReader) {
51504
- const hash = import_crypto5.default.createHash("sha1").update(line).digest("base64");
51790
+ const hash = import_crypto6.default.createHash("sha1").update(line).digest("base64");
51505
51791
  if (!seen.has(hash)) {
51506
51792
  seen.add(hash);
51507
51793
  if (!writer.write(line + "\n"))
@@ -51521,8 +51807,8 @@ var init_ConsumerExecutor = __esm({
51521
51807
  reader.destroy();
51522
51808
  });
51523
51809
  }
51524
- await import_promises13.default.unlink(datasetPath);
51525
- await import_promises13.default.rename(tempWorkPath, datasetPath);
51810
+ await import_promises14.default.unlink(datasetPath);
51811
+ await import_promises14.default.rename(tempWorkPath, datasetPath);
51526
51812
  return newLineCount;
51527
51813
  };
51528
51814
  this.processDistinctOn = async (consumer, datasetPath) => {
@@ -51566,8 +51852,8 @@ var init_ConsumerExecutor = __esm({
51566
51852
  reader.destroy();
51567
51853
  });
51568
51854
  }
51569
- await import_promises13.default.unlink(datasetPath);
51570
- await import_promises13.default.rename(tempWorkPath, datasetPath);
51855
+ await import_promises14.default.unlink(datasetPath);
51856
+ await import_promises14.default.rename(tempWorkPath, datasetPath);
51571
51857
  return winners.size;
51572
51858
  };
51573
51859
  this.processPivot = async (consumer, datasetPath) => {
@@ -51673,12 +51959,12 @@ var init_ConsumerExecutor = __esm({
51673
51959
  reader.destroy();
51674
51960
  });
51675
51961
  }
51676
- await import_promises13.default.unlink(datasetPath);
51677
- await import_promises13.default.rename(tempWorkPath, datasetPath);
51962
+ await import_promises14.default.unlink(datasetPath);
51963
+ await import_promises14.default.rename(tempWorkPath, datasetPath);
51678
51964
  return outputCount;
51679
51965
  };
51680
- this._parseLine = (line, format3, fields) => {
51681
- return format3 === "CSV" ? LineParser_default._internalParseCSV(line, fields) : LineParser_default._internalParseJSON(line);
51966
+ this._parseLine = (line, format4, fields) => {
51967
+ return format4 === "CSV" ? LineParser_default._internalParseCSV(line, fields) : LineParser_default._internalParseJSON(line);
51682
51968
  };
51683
51969
  /**
51684
51970
  * Determines if the new record should replace the existing record based on the resolution strategy
@@ -51777,8 +52063,6 @@ var init_ProducerExecutor = __esm({
51777
52063
  init_src8();
51778
52064
  init_src4();
51779
52065
  init_src10();
51780
- init_src();
51781
- init_src10();
51782
52066
  init_src10();
51783
52067
  import_path19 = __toESM(require("path"));
51784
52068
  init_src2();
@@ -51809,20 +52093,14 @@ var init_ProducerExecutor = __esm({
51809
52093
  * the source file name or a mask, and what that file name is. None of it depends on the line, so
51810
52094
  * it is compiled once per chunk instead of rebuilt per line — including the mask's own
51811
52095
  * validation, which used to run once per dimension per line.
52096
+ *
52097
+ * The fills themselves come from `ProducerManager`, which is also where the sample path gets
52098
+ * them: one producer stage, reached from two places.
51812
52099
  */
51813
52100
  this.compileLine = (dimensions, chunk) => {
51814
52101
  Affirm_default(dimensions, "Invalid producer dimensions");
51815
52102
  Affirm_default(chunk, "Invalid chunk");
51816
- const fills = [];
51817
- for (const dimension of dimensions) {
51818
- const { prodDimension } = dimension;
51819
- const mask = ProducerManager_default.getMask(prodDimension);
51820
- const sourceFilename = prodDimension.sourceFilename === true;
51821
- if (!sourceFilename && !Algo_default.hasVal(mask))
51822
- continue;
51823
- fills.push({ key: dimension.name, mask, sourceFilename, type: prodDimension.type });
51824
- }
51825
- return { fills, sourceFilename: import_path19.default.basename(chunk.fileUri) };
52103
+ return { fills: ProducerManager_default.compileFills(dimensions), sourceFilename: import_path19.default.basename(chunk.fileUri) };
51826
52104
  };
51827
52105
  /**
51828
52106
  * The record(s) one source line produces. Almost always exactly one — a producer with a group
@@ -51843,14 +52121,8 @@ var init_ProducerExecutor = __esm({
51843
52121
  if (plan.fills.length === 0)
51844
52122
  return records;
51845
52123
  counter = performance.now();
51846
- for (const record of records) {
51847
- for (const fill2 of plan.fills) {
51848
- if (fill2.sourceFilename)
51849
- record[fill2.key] = plan.sourceFilename;
51850
- if (Algo_default.hasVal(fill2.mask))
51851
- record[fill2.key] = CryptoEngine_default.hashValue(fill2.mask, record[fill2.key]?.toString(), fill2.type);
51852
- }
51853
- }
52124
+ for (const record of records)
52125
+ ProducerManager_default.applyFills(record, plan.fills, plan.sourceFilename);
51854
52126
  tracker.measure("process-line:dimensions-filename-mask", performance.now() - counter);
51855
52127
  return records;
51856
52128
  };
@@ -52161,11 +52433,11 @@ var init_OrchestratorHelper = __esm({
52161
52433
  });
52162
52434
 
52163
52435
  // ../../packages/executors/src/LookupResolver.ts
52164
- var import_fs15, import_promises14, import_path21, import_readline9, LookupResolverClass, LookupResolver, LookupResolver_default;
52436
+ var import_fs15, import_promises15, import_path21, import_readline9, LookupResolverClass, LookupResolver, LookupResolver_default;
52165
52437
  var init_LookupResolver = __esm({
52166
52438
  "../../packages/executors/src/LookupResolver.ts"() {
52167
52439
  import_fs15 = __toESM(require("fs"));
52168
- import_promises14 = __toESM(require("fs/promises"));
52440
+ import_promises15 = __toESM(require("fs/promises"));
52169
52441
  import_path21 = __toESM(require("path"));
52170
52442
  import_readline9 = __toESM(require("readline"));
52171
52443
  init_src();
@@ -52206,11 +52478,11 @@ var init_LookupResolver = __esm({
52206
52478
  this.cache.set(id, await this.buildDict(lookupConsumer, capturePath, ref));
52207
52479
  }
52208
52480
  ExecutorScope_default.ensurePath(outPath);
52209
- await import_promises14.default.writeFile(outPath, JSON.stringify(this.cache.get(id)));
52481
+ await import_promises15.default.writeFile(outPath, JSON.stringify(this.cache.get(id)));
52210
52482
  manifest.push({ id, consumer: ref.consumer, key: ref.key, value: ref.value, path: import_path21.default.resolve(outPath) });
52211
52483
  }
52212
52484
  for (const capturePath of captureByConsumer.values())
52213
- await import_promises14.default.rm(capturePath, { force: true });
52485
+ await import_promises15.default.rm(capturePath, { force: true });
52214
52486
  return manifest;
52215
52487
  };
52216
52488
  // Runs the source consumer through the real pipeline, capturing its merged output before cleanup.
@@ -52228,7 +52500,7 @@ var init_LookupResolver = __esm({
52228
52500
  };
52229
52501
  // Projects the captured dataset to a { code: value } dict, bounded by MAX_LOOKUP_ROWS.
52230
52502
  this.buildDict = async (lookupConsumer, capturePath, ref) => {
52231
- const format3 = OutputExecutor_default._getInternalRecordFormat(lookupConsumer);
52503
+ const format4 = OutputExecutor_default._getInternalRecordFormat(lookupConsumer);
52232
52504
  const visibleFields = ConsumerManager_default.getExpandedFields(lookupConsumer).filter((f7) => !f7.cField.hidden);
52233
52505
  const finalKeys = visibleFields.map((f7) => f7.finalKey);
52234
52506
  Affirm_default(finalKeys.includes(ref.key), `code_lookup key column "${ref.key}" is not in the output of consumer "${ref.consumer}"`);
@@ -52241,7 +52513,7 @@ var init_LookupResolver = __esm({
52241
52513
  if (!line.length) continue;
52242
52514
  rowsRead++;
52243
52515
  Affirm_default(rowsRead <= Constants_default.defaults.MAX_LOOKUP_ROWS, `code_lookup table from consumer "${ref.consumer}" exceeds MAX_LOOKUP_ROWS (${Constants_default.defaults.MAX_LOOKUP_ROWS})`);
52244
- const record = this.parseLine(line, format3, visibleFields);
52516
+ const record = this.parseLine(line, format4, visibleFields);
52245
52517
  const code = String(record[ref.key]);
52246
52518
  if (code in dict && !warnedDup) {
52247
52519
  Logger_default.warn(`code_lookup: duplicate key(s) in consumer "${ref.consumer}" for "${ref.key}"; last value wins`);
@@ -52252,8 +52524,8 @@ var init_LookupResolver = __esm({
52252
52524
  Logger_default.log(`[lookup] Built table "${ref.consumer}" (${ref.key}->${ref.value}): ${Object.keys(dict).length} entr(ies) from ${rowsRead} row(s)`);
52253
52525
  return dict;
52254
52526
  };
52255
- this.parseLine = (line, format3, visibleFields) => {
52256
- if (format3 === "CSV") return LineParser_default._internalParseCSV(line, visibleFields, ",");
52527
+ this.parseLine = (line, format4, visibleFields) => {
52528
+ if (format4 === "CSV") return LineParser_default._internalParseCSV(line, visibleFields, ",");
52257
52529
  return JSON.parse(line);
52258
52530
  };
52259
52531
  this.getCapturePath = (scope, consumerName) => {
@@ -52280,11 +52552,11 @@ var init_LookupResolver = __esm({
52280
52552
  });
52281
52553
 
52282
52554
  // ../../packages/executors/src/ConsumerInputResolver.ts
52283
- var import_fs16, import_promises15, import_path22, ConsumerInputResolverClass, ConsumerInputResolver, ConsumerInputResolver_default;
52555
+ var import_fs16, import_promises16, import_path22, ConsumerInputResolverClass, ConsumerInputResolver, ConsumerInputResolver_default;
52284
52556
  var init_ConsumerInputResolver = __esm({
52285
52557
  "../../packages/executors/src/ConsumerInputResolver.ts"() {
52286
52558
  import_fs16 = __toESM(require("fs"));
52287
- import_promises15 = __toESM(require("fs/promises"));
52559
+ import_promises16 = __toESM(require("fs/promises"));
52288
52560
  import_path22 = __toESM(require("path"));
52289
52561
  init_src();
52290
52562
  init_src3();
@@ -52315,7 +52587,7 @@ var init_ConsumerInputResolver = __esm({
52315
52587
  const capturePath = ExecutorScope_default.getConsumerInputPath(scope, name);
52316
52588
  ExecutorScope_default.ensurePath(capturePath);
52317
52589
  await this.runUpstreamConsumer(upstream, capturePath, stack, request);
52318
- const { size } = await import_promises15.default.stat(capturePath);
52590
+ const { size } = await import_promises16.default.stat(capturePath);
52319
52591
  this.cache.set(name, { consumer: name, path: import_path22.default.resolve(capturePath), fileSize: size });
52320
52592
  }
52321
52593
  manifest.set(name, this.cache.get(name));
@@ -52378,11 +52650,11 @@ var ExecutorOrchestrator_exports = {};
52378
52650
  __export(ExecutorOrchestrator_exports, {
52379
52651
  default: () => ExecutorOrchestrator_default
52380
52652
  });
52381
- var import_fs17, import_promises16, import_path23, import_readline10, import_workerpool, import_promises17, ExecutorOrchestratorClass, ExecutorOrchestrator, ExecutorOrchestrator_default;
52653
+ var import_fs17, import_promises17, import_path23, import_readline10, import_workerpool, import_promises18, ExecutorOrchestratorClass, ExecutorOrchestrator, ExecutorOrchestrator_default;
52382
52654
  var init_ExecutorOrchestrator = __esm({
52383
52655
  "../../packages/executors/src/ExecutorOrchestrator.ts"() {
52384
52656
  import_fs17 = __toESM(require("fs"));
52385
- import_promises16 = __toESM(require("fs/promises"));
52657
+ import_promises17 = __toESM(require("fs/promises"));
52386
52658
  import_path23 = __toESM(require("path"));
52387
52659
  import_readline10 = __toESM(require("readline"));
52388
52660
  import_workerpool = __toESM(require("workerpool"));
@@ -52400,7 +52672,7 @@ var init_ExecutorOrchestrator = __esm({
52400
52672
  init_src();
52401
52673
  init_src10();
52402
52674
  init_ExecutorWriter();
52403
- import_promises17 = require("stream/promises");
52675
+ import_promises18 = require("stream/promises");
52404
52676
  init_src2();
52405
52677
  init_ExecutorProgress2();
52406
52678
  init_src5();
@@ -52618,7 +52890,8 @@ var init_ExecutorOrchestrator = __esm({
52618
52890
  } catch (error) {
52619
52891
  Logger_default.log(`[${usageId}] Consumer "${consumer.name}" failed: ${Helper_default.asError(error).message} | ${OrchestratorHelper_default.formatMemoryUsage()}`);
52620
52892
  Logger_default.error(error);
52621
- await ConsumerOnFinishManager_default.onConsumerError(consumer, usageId, this.makeOnFinishRunner(consumer, request, usageId));
52893
+ if (!request.skipExport)
52894
+ await ConsumerOnFinishManager_default.onConsumerError(consumer, usageId, this.makeOnFinishRunner(consumer, request, usageId));
52622
52895
  Logger_default.log(`[${usageId}] Running cleanup after failure`);
52623
52896
  await this.performCleanupOperations(scope, tracker);
52624
52897
  UsageManager_default.failUsage(usageId, Helper_default.asError(error).message);
@@ -52916,10 +53189,10 @@ var init_ExecutorOrchestrator = __esm({
52916
53189
  * format has no header row, so each row is reprojected. Without a captureFormat it's a verbatim copy.
52917
53190
  */
52918
53191
  this.captureDataset = async (consumer, fields, sourcePath, targetPath, captureFormat) => {
52919
- await import_promises16.default.mkdir(import_path23.default.dirname(targetPath), { recursive: true });
53192
+ await import_promises17.default.mkdir(import_path23.default.dirname(targetPath), { recursive: true });
52920
53193
  const internalFormat = OutputExecutor_default._getInternalRecordFormat(consumer);
52921
53194
  if (captureFormat !== "JSONL" || internalFormat !== "CSV") {
52922
- await import_promises16.default.copyFile(sourcePath, targetPath);
53195
+ await import_promises17.default.copyFile(sourcePath, targetPath);
52923
53196
  return;
52924
53197
  }
52925
53198
  const visibleFields = fields.filter((field) => !field.cField.hidden);
@@ -53022,22 +53295,22 @@ var init_ExecutorOrchestrator = __esm({
53022
53295
  startRow: prod.settings.startRow,
53023
53296
  startColumn: prod.settings.startColumn
53024
53297
  });
53025
- await (0, import_promises17.pipeline)(
53298
+ await (0, import_promises18.pipeline)(
53026
53299
  xlsCsvStream,
53027
53300
  import_fs17.default.createWriteStream(decodedPath)
53028
53301
  );
53029
- const fileStats = await import_promises16.default.stat(decodedPath);
53302
+ const fileStats = await import_promises17.default.stat(decodedPath);
53030
53303
  decodedFiles.push({ fullUri: decodedPath, fileSize: fileStats.size });
53031
53304
  decodedCount++;
53032
53305
  reportFile();
53033
53306
  continue;
53034
53307
  }
53035
53308
  if (inferredType === "XML") {
53036
- const fileContent = await import_promises16.default.readFile(file.fullUri, "utf-8");
53309
+ const fileContent = await import_promises17.default.readFile(file.fullUri, "utf-8");
53037
53310
  const jsonData = XMLParser_default.xmlToJson(fileContent);
53038
53311
  const records = normalizeXmlRows(jsonData);
53039
53312
  if (records.length === 0) {
53040
- await import_promises16.default.writeFile(decodedPath, "", "utf-8");
53313
+ await import_promises17.default.writeFile(decodedPath, "", "utf-8");
53041
53314
  } else {
53042
53315
  const columns = [];
53043
53316
  for (const record of records) {
@@ -53053,9 +53326,9 @@ var init_ExecutorOrchestrator = __esm({
53053
53326
  const row = columns.map((column) => csvSafeValue(record[column]));
53054
53327
  lines.push(CSVParser_default.stringifyRow(row));
53055
53328
  }
53056
- await import_promises16.default.writeFile(decodedPath, lines.join("\n"), "utf-8");
53329
+ await import_promises17.default.writeFile(decodedPath, lines.join("\n"), "utf-8");
53057
53330
  }
53058
- const fileStats = await import_promises16.default.stat(decodedPath);
53331
+ const fileStats = await import_promises17.default.stat(decodedPath);
53059
53332
  decodedFiles.push({ fullUri: decodedPath, fileSize: fileStats.size });
53060
53333
  decodedCount++;
53061
53334
  reportFile();
@@ -53083,20 +53356,20 @@ var init_ExecutorOrchestrator = __esm({
53083
53356
  Logger_default.log(`[${scope.id}] Merging ${executorResults.length} worker output files into ${mainPath}`);
53084
53357
  const perf = performance.now();
53085
53358
  for (const workerResult of executorResults) {
53086
- await (0, import_promises17.pipeline)(
53359
+ await (0, import_promises18.pipeline)(
53087
53360
  import_fs17.default.createReadStream(workerResult.resultUri),
53088
53361
  import_fs17.default.createWriteStream(mainPath, { flags: "a" })
53089
53362
  );
53090
- await import_promises16.default.unlink(workerResult.resultUri);
53363
+ await import_promises17.default.unlink(workerResult.resultUri);
53091
53364
  }
53092
53365
  tracker.measure("merge-workers", performance.now() - perf);
53093
53366
  Logger_default.log(`[${scope.id}] Merge complete in ${Math.round(performance.now() - perf)}ms`);
53094
53367
  } else if (executorResults.length === 1) {
53095
53368
  Logger_default.log(`[${scope.id}] Single worker \u2014 renaming output to ${mainPath}`);
53096
- await import_promises16.default.rename(executorResults[0].resultUri, mainPath);
53369
+ await import_promises17.default.rename(executorResults[0].resultUri, mainPath);
53097
53370
  } else {
53098
53371
  Logger_default.log(`[${scope.id}] No worker output \u2014 writing an empty dataset to ${mainPath}`);
53099
- await import_promises16.default.writeFile(mainPath, "");
53372
+ await import_promises17.default.writeFile(mainPath, "");
53100
53373
  }
53101
53374
  return mainPath;
53102
53375
  };
@@ -53514,6 +53787,7 @@ var runExecutorTask = async (workerData) => {
53514
53787
  Logger_default.initFromEnv();
53515
53788
  if (workerData.loggerConfig)
53516
53789
  Logger_default.initFromConfig(workerData.loggerConfig);
53790
+ Logger_default.captureConsole();
53517
53791
  const envLoadMS = prepareEnvironment();
53518
53792
  try {
53519
53793
  const {
@@ -53571,6 +53845,163 @@ init_src4();
53571
53845
  init_OutputExecutor();
53572
53846
  init_ProducerExecutor();
53573
53847
 
53848
+ // ../../packages/executors/src/SampleRunner.ts
53849
+ var import_fs18 = __toESM(require("fs"));
53850
+ var import_promises19 = __toESM(require("fs/promises"));
53851
+ var import_path24 = __toESM(require("path"));
53852
+ var import_readline11 = __toESM(require("readline"));
53853
+ init_src();
53854
+ init_src3();
53855
+ init_src4();
53856
+ init_src8();
53857
+ init_src10();
53858
+ init_src7();
53859
+ init_src2();
53860
+ init_ExecutorOrchestrator();
53861
+ var MAX_WALK_DEPTH = 20;
53862
+ var SAMPLE_USER = { user: { _id: "sample", name: "sample", type: "licence" } };
53863
+ var SampleRunnerClass = class {
53864
+ constructor() {
53865
+ /**
53866
+ * @param resourceName a producer or consumer name, as declared.
53867
+ * @param rows the most rows to return, capped at `MAX_SAMPLE_ROWS`.
53868
+ * @throws when the name is neither, when a source cannot be read, or when the pipeline itself
53869
+ * fails — a consumer whose transformation throws is a sample that reports the reason.
53870
+ */
53871
+ this.read = async (resourceName, rows = 10, details) => {
53872
+ Affirm_default(resourceName, "Missing resource name to sample");
53873
+ Affirm_default(rows > 0, "Sample size must be greater than 0");
53874
+ const size = Math.min(rows, Constants_default.defaults.MAX_SAMPLE_ROWS);
53875
+ const producer = Environment_default.getProducer(resourceName);
53876
+ if (producer) {
53877
+ const records = await ProducerEngine_default.readSampleData(producer, size, false);
53878
+ return {
53879
+ kind: "producer",
53880
+ name: resourceName,
53881
+ records,
53882
+ note: `${records.length} row(s) read from the source now, with this producer's dimensions, types and masks applied.`
53883
+ };
53884
+ }
53885
+ const consumer = Environment_default.getConsumer(resourceName);
53886
+ Affirm_default(consumer, `Resource "${resourceName}" not found. Please check if it exists as a producer or consumer.`);
53887
+ return this._runConsumer(consumer, size, details);
53888
+ };
53889
+ /**
53890
+ * Runs the consumer for real and reads back what it produced.
53891
+ *
53892
+ * The output is captured instead of exported, so nothing reaches the consumer's destination and
53893
+ * no onSuccess action fires: looking at data must never be indistinguishable from publishing it.
53894
+ */
53895
+ this._runConsumer = async (consumer, size, details) => {
53896
+ this._assertStageable(consumer);
53897
+ const capturePath = import_path24.default.resolve(import_path24.default.join(ExecutorScope_default.getBasePath(), `sample_${consumer.name}_${Helper_default.uuid()}.jsonl`));
53898
+ ExecutorScope_default.ensurePath(capturePath);
53899
+ try {
53900
+ const result = await ExecutorOrchestrator_default.launch({
53901
+ consumer,
53902
+ // `SAMPLE`, so the run it records is distinguishable from one the project did. The
53903
+ // executor treats it like any other invocation; only `RunOverlay` reads the marker.
53904
+ details: { ...details ?? SAMPLE_USER, invokedBy: "SAMPLE" },
53905
+ // The rows asked for, bounded the way `remora run -l` bounds them — pushed to the
53906
+ // source and stopped early per worker wherever nothing downstream can drop a record.
53907
+ options: { limit: size },
53908
+ // Nothing reaches the destination and no finish action fires; the merged dataset
53909
+ // comes back through the same capture the lookup and consumer-input runs use.
53910
+ skipExport: true,
53911
+ captureMainDatasetTo: capturePath,
53912
+ captureFormat: "JSONL"
53913
+ });
53914
+ const captured = await this._readCapture(capturePath, size);
53915
+ const records = captured.map((record) => this._inFieldOrder(consumer, record));
53916
+ Logger_default.log(`[sample] Consumer "${consumer.name}": ${records.length} row(s) from ${result.inputCount} input line(s)`);
53917
+ return {
53918
+ kind: "consumer",
53919
+ name: consumer.name,
53920
+ records,
53921
+ note: `${records.length} row(s) from the real pipeline \u2014 filters, transformations, masking and validation all applied, exactly as in a run. Nothing was written to the destination.`
53922
+ };
53923
+ } finally {
53924
+ await import_promises19.default.rm(capturePath, { force: true });
53925
+ }
53926
+ };
53927
+ /**
53928
+ * Refuses, naming the source, when a run could not read one of this consumer's producers.
53929
+ *
53930
+ * `RedshiftDriver.ready` and `HttpApiSourceDriver.ready` are unimplemented, so the pipeline
53931
+ * cannot reach those sources at all. Checked up front because the alternative is a run that
53932
+ * spins up a worker pool and then surfaces "Not implemented yet" from three layers down, which
53933
+ * names neither the producer nor the source that caused it.
53934
+ */
53935
+ this._assertStageable = (consumer) => {
53936
+ for (const producer of this._inputProducers(consumer)) {
53937
+ const source = Environment_default.getSource(producer.source);
53938
+ Affirm_default(source, `Producer "${producer.name}" of consumer "${consumer.name}" has no source "${producer.source}"`);
53939
+ if (!DriverFactory_default.canStage(source.engine))
53940
+ throw new Error(`Cannot sample consumer "${consumer.name}": its producer "${producer.name}" reads source "${source.name}", and a "${source.engine}" source cannot be run through the pipeline yet. Sample the producer "${producer.name}" instead to see its rows.`);
53941
+ }
53942
+ };
53943
+ /**
53944
+ * Every producer a run of this consumer would stage — its own, plus those of the consumers it
53945
+ * reads as input or consults as a code_lookup table, since each of those is executed too.
53946
+ */
53947
+ this._inputProducers = (consumer, visited = []) => {
53948
+ Affirm_default(!visited.includes(consumer.name), `Consumer "${consumer.name}" reads itself through ${visited.join(" \u2192 ")}`);
53949
+ Affirm_default(visited.length < MAX_WALK_DEPTH, `Consumer chain from "${visited[0]}" is more than ${MAX_WALK_DEPTH} deep`);
53950
+ const seen = [...visited, consumer.name];
53951
+ const upstream = [
53952
+ ...consumer.producers.map((entry) => entry.name),
53953
+ ...ConsumerManager_default.collectLookupRefs(ConsumerManager_default.getExpandedFields(consumer)).map((ref) => ref.consumer)
53954
+ ];
53955
+ return upstream.flatMap((name) => {
53956
+ const producer = Environment_default.getProducer(name);
53957
+ if (producer) return [producer];
53958
+ const nested = Environment_default.getConsumer(name);
53959
+ Affirm_default(nested, `Producer or consumer "${name}" not found for consumer "${consumer.name}"`);
53960
+ return this._inputProducers(nested, seen);
53961
+ });
53962
+ };
53963
+ /**
53964
+ * One row's keys in the order the consumer DECLARES its fields.
53965
+ *
53966
+ * A record comes out of a worker keyed in the order the producer's dimensions were read, which is
53967
+ * the source's layout and not the consumer's — so a consumer declaring country, plan, is_active
53968
+ * over a producer that stores is_active first would be shown its own columns in someone else's
53969
+ * order. Invisible in an exported JSON object; the whole shape of the table here.
53970
+ *
53971
+ * Anything the record carries that the field list does not name is appended rather than dropped:
53972
+ * a column that turns up unexpectedly is exactly the one worth seeing.
53973
+ */
53974
+ this._inFieldOrder = (consumer, record) => {
53975
+ const declared = ConsumerManager_default.getExpandedFields(consumer).filter((field) => !field.cField.hidden).map((field) => field.finalKey);
53976
+ const ordered = {};
53977
+ for (const key of declared) {
53978
+ if (key in record) ordered[key] = record[key];
53979
+ }
53980
+ for (const key of Object.keys(record)) {
53981
+ if (!(key in ordered)) ordered[key] = record[key];
53982
+ }
53983
+ return ordered;
53984
+ };
53985
+ /** The captured dataset, which `captureFormat: 'JSONL'` guarantees is one JSON object per line. */
53986
+ this._readCapture = async (capturePath, size) => {
53987
+ if (!import_fs18.default.existsSync(capturePath)) return [];
53988
+ const records = [];
53989
+ const lines = import_readline11.default.createInterface({ input: import_fs18.default.createReadStream(capturePath), crlfDelay: Infinity });
53990
+ try {
53991
+ for await (const line of lines) {
53992
+ if (!line.length) continue;
53993
+ records.push(JSON.parse(line));
53994
+ if (records.length >= size) break;
53995
+ }
53996
+ } finally {
53997
+ lines.close();
53998
+ }
53999
+ return records;
54000
+ };
54001
+ }
54002
+ };
54003
+ var SampleRunner = new SampleRunnerClass();
54004
+
53574
54005
  // src/workers/ExecutorWorker.ts
53575
54006
  registerExecutorWorker();
53576
54007
  /*! Bundled license information: