@forzalabs/remora 1.1.15 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -147,7 +147,7 @@ var require_has_flag = __commonJS({
147
147
  var require_supports_colors = __commonJS({
148
148
  "../../node_modules/logform/node_modules/@colors/colors/lib/system/supports-colors.js"(exports2, module2) {
149
149
  "use strict";
150
- var os2 = require("os");
150
+ var os3 = require("os");
151
151
  var hasFlag = require_has_flag();
152
152
  var env = process.env;
153
153
  var forceColor = void 0;
@@ -185,7 +185,7 @@ var require_supports_colors = __commonJS({
185
185
  }
186
186
  var min = forceColor ? 1 : 0;
187
187
  if (process.platform === "win32") {
188
- var osRelease = os2.release().split(".");
188
+ var osRelease = os3.release().split(".");
189
189
  if (Number(process.versions.node.split(".")[0]) >= 8 && Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
190
190
  return Number(osRelease[2]) >= 14931 ? 3 : 2;
191
191
  }
@@ -5429,7 +5429,7 @@ var require_winston_transport = __commonJS({
5429
5429
  var require_console = __commonJS({
5430
5430
  "../../packages/logger/node_modules/winston/lib/winston/transports/console.js"(exports2, module2) {
5431
5431
  "use strict";
5432
- var os2 = require("os");
5432
+ var os3 = require("os");
5433
5433
  var { LEVEL, MESSAGE } = require_triple_beam();
5434
5434
  var TransportStream = require_winston_transport();
5435
5435
  module2.exports = class Console extends TransportStream {
@@ -5443,7 +5443,7 @@ var require_console = __commonJS({
5443
5443
  this.name = options.name || "console";
5444
5444
  this.stderrLevels = this._stringArrayToSet(options.stderrLevels);
5445
5445
  this.consoleWarnLevels = this._stringArrayToSet(options.consoleWarnLevels);
5446
- this.eol = typeof options.eol === "string" ? options.eol : os2.EOL;
5446
+ this.eol = typeof options.eol === "string" ? options.eol : os3.EOL;
5447
5447
  this.forceConsole = options.forceConsole || false;
5448
5448
  this._consoleLog = console.log.bind(console);
5449
5449
  this._consoleWarn = console.warn.bind(console);
@@ -9655,15 +9655,15 @@ var require_index_cjs = __commonJS({
9655
9655
  };
9656
9656
  }
9657
9657
  function wrapConversion(toModel, graph) {
9658
- const path23 = [graph[toModel].parent, toModel];
9658
+ const path24 = [graph[toModel].parent, toModel];
9659
9659
  let fn = convert$1[graph[toModel].parent][toModel];
9660
9660
  let cur = graph[toModel].parent;
9661
9661
  while (graph[cur].parent) {
9662
- path23.unshift(graph[cur].parent);
9662
+ path24.unshift(graph[cur].parent);
9663
9663
  fn = link(convert$1[graph[cur].parent][cur], fn);
9664
9664
  cur = graph[cur].parent;
9665
9665
  }
9666
- fn.conversion = path23;
9666
+ fn.conversion = path24;
9667
9667
  return fn;
9668
9668
  }
9669
9669
  function route(fromModel) {
@@ -10293,7 +10293,7 @@ var require_node2 = __commonJS({
10293
10293
  var require_tail_file = __commonJS({
10294
10294
  "../../packages/logger/node_modules/winston/lib/winston/tail-file.js"(exports2, module2) {
10295
10295
  "use strict";
10296
- var fs24 = require("fs");
10296
+ var fs25 = require("fs");
10297
10297
  var { StringDecoder } = require("string_decoder");
10298
10298
  var { Stream } = require_readable();
10299
10299
  function noop() {
@@ -10314,7 +10314,7 @@ var require_tail_file = __commonJS({
10314
10314
  stream.emit("end");
10315
10315
  stream.emit("close");
10316
10316
  };
10317
- fs24.open(options.file, "a+", "0644", (err, fd) => {
10317
+ fs25.open(options.file, "a+", "0644", (err, fd) => {
10318
10318
  if (err) {
10319
10319
  if (!iter) {
10320
10320
  stream.emit("error", err);
@@ -10326,10 +10326,10 @@ var require_tail_file = __commonJS({
10326
10326
  }
10327
10327
  (function read() {
10328
10328
  if (stream.destroyed) {
10329
- fs24.close(fd, noop);
10329
+ fs25.close(fd, noop);
10330
10330
  return;
10331
10331
  }
10332
- return fs24.read(fd, buffer, 0, buffer.length, pos, (error, bytes) => {
10332
+ return fs25.read(fd, buffer, 0, buffer.length, pos, (error, bytes) => {
10333
10333
  if (error) {
10334
10334
  if (!iter) {
10335
10335
  stream.emit("error", error);
@@ -10388,15 +10388,15 @@ var require_tail_file = __commonJS({
10388
10388
  var require_file = __commonJS({
10389
10389
  "../../packages/logger/node_modules/winston/lib/winston/transports/file.js"(exports2, module2) {
10390
10390
  "use strict";
10391
- var fs24 = require("fs");
10392
- var path23 = require("path");
10391
+ var fs25 = require("fs");
10392
+ var path24 = require("path");
10393
10393
  var asyncSeries = require_series();
10394
10394
  var zlib2 = require("zlib");
10395
10395
  var { MESSAGE } = require_triple_beam();
10396
10396
  var { Stream, PassThrough } = require_readable();
10397
10397
  var TransportStream = require_winston_transport();
10398
10398
  var debug2 = require_node2()("winston:file");
10399
- var os2 = require("os");
10399
+ var os3 = require("os");
10400
10400
  var tailFile = require_tail_file();
10401
10401
  module2.exports = class File extends TransportStream {
10402
10402
  /**
@@ -10419,14 +10419,14 @@ var require_file = __commonJS({
10419
10419
  this._onError = this._onError.bind(this);
10420
10420
  if (options.filename || options.dirname) {
10421
10421
  throwIf("filename or dirname", "stream");
10422
- this._basename = this.filename = options.filename ? path23.basename(options.filename) : "winston.log";
10423
- this.dirname = options.dirname || path23.dirname(options.filename);
10422
+ this._basename = this.filename = options.filename ? path24.basename(options.filename) : "winston.log";
10423
+ this.dirname = options.dirname || path24.dirname(options.filename);
10424
10424
  this.options = options.options || { flags: "a" };
10425
10425
  } else if (options.stream) {
10426
10426
  console.warn("options.stream will be removed in winston@4. Use winston.transports.Stream");
10427
10427
  throwIf("stream", "filename", "maxsize");
10428
10428
  this._dest = this._stream.pipe(this._setupStream(options.stream));
10429
- this.dirname = path23.dirname(this._dest.path);
10429
+ this.dirname = path24.dirname(this._dest.path);
10430
10430
  } else {
10431
10431
  throw new Error("Cannot log to file without filename or stream.");
10432
10432
  }
@@ -10434,7 +10434,7 @@ var require_file = __commonJS({
10434
10434
  this.rotationFormat = options.rotationFormat || false;
10435
10435
  this.zippedArchive = options.zippedArchive || false;
10436
10436
  this.maxFiles = options.maxFiles || null;
10437
- this.eol = typeof options.eol === "string" ? options.eol : os2.EOL;
10437
+ this.eol = typeof options.eol === "string" ? options.eol : os3.EOL;
10438
10438
  this.tailable = options.tailable || false;
10439
10439
  this.lazy = options.lazy || false;
10440
10440
  this._size = 0;
@@ -10589,11 +10589,11 @@ var require_file = __commonJS({
10589
10589
  options = {};
10590
10590
  }
10591
10591
  options = normalizeQuery(options);
10592
- const file = path23.join(this.dirname, this.filename);
10592
+ const file = path24.join(this.dirname, this.filename);
10593
10593
  let buff = "";
10594
10594
  let results = [];
10595
10595
  let row = 0;
10596
- const stream = fs24.createReadStream(file, {
10596
+ const stream = fs25.createReadStream(file, {
10597
10597
  encoding: "utf8"
10598
10598
  });
10599
10599
  stream.on("error", (err) => {
@@ -10694,7 +10694,7 @@ var require_file = __commonJS({
10694
10694
  * TODO: Refactor me.
10695
10695
  */
10696
10696
  stream(options = {}) {
10697
- const file = path23.join(this.dirname, this.filename);
10697
+ const file = path24.join(this.dirname, this.filename);
10698
10698
  const stream = new Stream();
10699
10699
  const tail = {
10700
10700
  file,
@@ -10744,8 +10744,8 @@ var require_file = __commonJS({
10744
10744
  */
10745
10745
  stat(callback) {
10746
10746
  const target = this._getFile();
10747
- const fullpath = path23.join(this.dirname, target);
10748
- fs24.stat(fullpath, (err, stat) => {
10747
+ const fullpath = path24.join(this.dirname, target);
10748
+ fs25.stat(fullpath, (err, stat) => {
10749
10749
  if (err && err.code === "ENOENT") {
10750
10750
  debug2("ENOENT\xA0ok", fullpath);
10751
10751
  this.filename = target;
@@ -10848,9 +10848,9 @@ var require_file = __commonJS({
10848
10848
  * @returns {WritableStream} Stream that writes to disk for the active file.
10849
10849
  */
10850
10850
  _createStream(source) {
10851
- const fullpath = path23.join(this.dirname, this.filename);
10851
+ const fullpath = path24.join(this.dirname, this.filename);
10852
10852
  debug2("create stream start", fullpath, this.options);
10853
- const dest = fs24.createWriteStream(fullpath, this.options).on("error", (err) => debug2(err)).on("close", () => debug2("close", dest.path, dest.bytesWritten)).on("open", () => {
10853
+ const dest = fs25.createWriteStream(fullpath, this.options).on("error", (err) => debug2(err)).on("close", () => debug2("close", dest.path, dest.bytesWritten)).on("open", () => {
10854
10854
  debug2("file open ok", fullpath);
10855
10855
  this.emit("open", fullpath);
10856
10856
  source.pipe(dest);
@@ -10873,16 +10873,16 @@ var require_file = __commonJS({
10873
10873
  */
10874
10874
  _incFile(callback) {
10875
10875
  debug2("_incFile", this.filename);
10876
- const ext = path23.extname(this._basename);
10877
- const basename = path23.basename(this._basename, ext);
10876
+ const ext = path24.extname(this._basename);
10877
+ const basename = path24.basename(this._basename, ext);
10878
10878
  const tasks = [];
10879
10879
  if (this.zippedArchive) {
10880
10880
  tasks.push(
10881
10881
  function(cb) {
10882
10882
  const num = this._created > 0 && !this.tailable ? this._created : "";
10883
10883
  this._compressFile(
10884
- path23.join(this.dirname, `${basename}${num}${ext}`),
10885
- path23.join(this.dirname, `${basename}${num}${ext}.gz`),
10884
+ path24.join(this.dirname, `${basename}${num}${ext}`),
10885
+ path24.join(this.dirname, `${basename}${num}${ext}.gz`),
10886
10886
  cb
10887
10887
  );
10888
10888
  }.bind(this)
@@ -10907,8 +10907,8 @@ var require_file = __commonJS({
10907
10907
  * @private
10908
10908
  */
10909
10909
  _getFile() {
10910
- const ext = path23.extname(this._basename);
10911
- const basename = path23.basename(this._basename, ext);
10910
+ const ext = path24.extname(this._basename);
10911
+ const basename = path24.basename(this._basename, ext);
10912
10912
  const isRotation = this.rotationFormat ? this.rotationFormat() : this._created;
10913
10913
  return !this.tailable && this._created ? `${basename}${isRotation}${ext}` : `${basename}${ext}`;
10914
10914
  }
@@ -10928,8 +10928,8 @@ var require_file = __commonJS({
10928
10928
  const isOldest = oldest !== 0 ? oldest : "";
10929
10929
  const isZipped = this.zippedArchive ? ".gz" : "";
10930
10930
  const filePath = `${basename}${isOldest}${ext}${isZipped}`;
10931
- const target = path23.join(this.dirname, filePath);
10932
- fs24.unlink(target, callback);
10931
+ const target = path24.join(this.dirname, filePath);
10932
+ fs25.unlink(target, callback);
10933
10933
  }
10934
10934
  /**
10935
10935
  * Roll files forward based on integer, up to maxFiles. e.g. if base if
@@ -10951,20 +10951,20 @@ var require_file = __commonJS({
10951
10951
  for (let x = this.maxFiles - 1; x > 1; x--) {
10952
10952
  tasks.push(function(i, cb) {
10953
10953
  let fileName = `${basename}${i - 1}${ext}${isZipped}`;
10954
- const tmppath = path23.join(this.dirname, fileName);
10955
- fs24.exists(tmppath, (exists) => {
10954
+ const tmppath = path24.join(this.dirname, fileName);
10955
+ fs25.exists(tmppath, (exists) => {
10956
10956
  if (!exists) {
10957
10957
  return cb(null);
10958
10958
  }
10959
10959
  fileName = `${basename}${i}${ext}${isZipped}`;
10960
- fs24.rename(tmppath, path23.join(this.dirname, fileName), cb);
10960
+ fs25.rename(tmppath, path24.join(this.dirname, fileName), cb);
10961
10961
  });
10962
10962
  }.bind(this, x));
10963
10963
  }
10964
10964
  asyncSeries(tasks, () => {
10965
- fs24.rename(
10966
- path23.join(this.dirname, `${basename}${ext}${isZipped}`),
10967
- path23.join(this.dirname, `${basename}1${ext}${isZipped}`),
10965
+ fs25.rename(
10966
+ path24.join(this.dirname, `${basename}${ext}${isZipped}`),
10967
+ path24.join(this.dirname, `${basename}1${ext}${isZipped}`),
10968
10968
  callback
10969
10969
  );
10970
10970
  });
@@ -10978,22 +10978,22 @@ var require_file = __commonJS({
10978
10978
  * @private
10979
10979
  */
10980
10980
  _compressFile(src, dest, callback) {
10981
- fs24.access(src, fs24.F_OK, (err) => {
10981
+ fs25.access(src, fs25.F_OK, (err) => {
10982
10982
  if (err) {
10983
10983
  return callback();
10984
10984
  }
10985
10985
  var gzip = zlib2.createGzip();
10986
- var inp = fs24.createReadStream(src);
10987
- var out = fs24.createWriteStream(dest);
10986
+ var inp = fs25.createReadStream(src);
10987
+ var out = fs25.createWriteStream(dest);
10988
10988
  out.on("finish", () => {
10989
- fs24.unlink(src, callback);
10989
+ fs25.unlink(src, callback);
10990
10990
  });
10991
10991
  inp.pipe(gzip).pipe(out);
10992
10992
  });
10993
10993
  }
10994
10994
  _createLogDirIfNotExist(dirPath) {
10995
- if (!fs24.existsSync(dirPath)) {
10996
- fs24.mkdirSync(dirPath, { recursive: true });
10995
+ if (!fs25.existsSync(dirPath)) {
10996
+ fs25.mkdirSync(dirPath, { recursive: true });
10997
10997
  }
10998
10998
  }
10999
10999
  };
@@ -11077,9 +11077,9 @@ var require_http = __commonJS({
11077
11077
  };
11078
11078
  const auth = options.params.auth || null;
11079
11079
  delete options.params.auth;
11080
- const path23 = options.params.path || null;
11080
+ const path24 = options.params.path || null;
11081
11081
  delete options.params.path;
11082
- this._request(options, auth, path23, (err, res, body) => {
11082
+ this._request(options, auth, path24, (err, res, body) => {
11083
11083
  if (res && res.statusCode !== 200) {
11084
11084
  err = new Error(`Invalid HTTP Status Code: ${res.statusCode}`);
11085
11085
  }
@@ -11107,12 +11107,12 @@ var require_http = __commonJS({
11107
11107
  method: "stream",
11108
11108
  params: options
11109
11109
  };
11110
- const path23 = options.params.path || null;
11110
+ const path24 = options.params.path || null;
11111
11111
  delete options.params.path;
11112
11112
  const auth = options.params.auth || null;
11113
11113
  delete options.params.auth;
11114
11114
  let buff = "";
11115
- const req = this._request(options, auth, path23);
11115
+ const req = this._request(options, auth, path24);
11116
11116
  stream.destroy = () => req.destroy();
11117
11117
  req.on("data", (data) => {
11118
11118
  data = (buff + data).split(/\n+/);
@@ -11138,14 +11138,14 @@ var require_http = __commonJS({
11138
11138
  * @param {string} path - request path
11139
11139
  * @param {function} callback - Continuation to respond to when complete.
11140
11140
  */
11141
- _request(options, auth, path23, callback) {
11141
+ _request(options, auth, path24, callback) {
11142
11142
  options = options || {};
11143
11143
  auth = auth || this.auth;
11144
- path23 = path23 || this.path || "";
11144
+ path24 = path24 || this.path || "";
11145
11145
  if (this.batch) {
11146
- this._doBatch(options, callback, auth, path23);
11146
+ this._doBatch(options, callback, auth, path24);
11147
11147
  } else {
11148
- this._doRequest(options, callback, auth, path23);
11148
+ this._doRequest(options, callback, auth, path24);
11149
11149
  }
11150
11150
  }
11151
11151
  /**
@@ -11155,18 +11155,18 @@ var require_http = __commonJS({
11155
11155
  * @param {Object?} auth - authentication options
11156
11156
  * @param {string} path - request path
11157
11157
  */
11158
- _doBatch(options, callback, auth, path23) {
11158
+ _doBatch(options, callback, auth, path24) {
11159
11159
  this.batchOptions.push(options);
11160
11160
  if (this.batchOptions.length === 1) {
11161
11161
  const me = this;
11162
11162
  this.batchCallback = callback;
11163
11163
  this.batchTimeoutID = setTimeout(function() {
11164
11164
  me.batchTimeoutID = -1;
11165
- me._doBatchRequest(me.batchCallback, auth, path23);
11165
+ me._doBatchRequest(me.batchCallback, auth, path24);
11166
11166
  }, this.batchInterval);
11167
11167
  }
11168
11168
  if (this.batchOptions.length === this.batchCount) {
11169
- this._doBatchRequest(this.batchCallback, auth, path23);
11169
+ this._doBatchRequest(this.batchCallback, auth, path24);
11170
11170
  }
11171
11171
  }
11172
11172
  /**
@@ -11175,14 +11175,14 @@ var require_http = __commonJS({
11175
11175
  * @param {Object?} auth - authentication options
11176
11176
  * @param {string} path - request path
11177
11177
  */
11178
- _doBatchRequest(callback, auth, path23) {
11178
+ _doBatchRequest(callback, auth, path24) {
11179
11179
  if (this.batchTimeoutID > 0) {
11180
11180
  clearTimeout(this.batchTimeoutID);
11181
11181
  this.batchTimeoutID = -1;
11182
11182
  }
11183
11183
  const batchOptionsCopy = this.batchOptions.slice();
11184
11184
  this.batchOptions = [];
11185
- this._doRequest(batchOptionsCopy, callback, auth, path23);
11185
+ this._doRequest(batchOptionsCopy, callback, auth, path24);
11186
11186
  }
11187
11187
  /**
11188
11188
  * Make a request to a winstond server or any http server which can
@@ -11192,7 +11192,7 @@ var require_http = __commonJS({
11192
11192
  * @param {Object?} auth - authentication options
11193
11193
  * @param {string} path - request path
11194
11194
  */
11195
- _doRequest(options, callback, auth, path23) {
11195
+ _doRequest(options, callback, auth, path24) {
11196
11196
  const headers = Object.assign({}, this.headers);
11197
11197
  if (auth && auth.bearer) {
11198
11198
  headers.Authorization = `Bearer ${auth.bearer}`;
@@ -11202,7 +11202,7 @@ var require_http = __commonJS({
11202
11202
  method: "POST",
11203
11203
  host: this.host,
11204
11204
  port: this.port,
11205
- path: `/${path23.replace(/^\//, "")}`,
11205
+ path: `/${path24.replace(/^\//, "")}`,
11206
11206
  headers,
11207
11207
  auth: auth && auth.username && auth.password ? `${auth.username}:${auth.password}` : "",
11208
11208
  agent: this.agent
@@ -11237,7 +11237,7 @@ var require_stream3 = __commonJS({
11237
11237
  "use strict";
11238
11238
  var isStream = require_is_stream();
11239
11239
  var { MESSAGE } = require_triple_beam();
11240
- var os2 = require("os");
11240
+ var os3 = require("os");
11241
11241
  var TransportStream = require_winston_transport();
11242
11242
  module2.exports = class Stream extends TransportStream {
11243
11243
  /**
@@ -11253,7 +11253,7 @@ var require_stream3 = __commonJS({
11253
11253
  this._stream = options.stream;
11254
11254
  this._stream.setMaxListeners(Infinity);
11255
11255
  this.isObjectMode = options.stream._writableState.objectMode;
11256
- this.eol = typeof options.eol === "string" ? options.eol : os2.EOL;
11256
+ this.eol = typeof options.eol === "string" ? options.eol : os3.EOL;
11257
11257
  }
11258
11258
  /**
11259
11259
  * Core logging method exposed to Winston.
@@ -11636,7 +11636,7 @@ var require_exception_stream = __commonJS({
11636
11636
  var require_exception_handler = __commonJS({
11637
11637
  "../../packages/logger/node_modules/winston/lib/winston/exception-handler.js"(exports2, module2) {
11638
11638
  "use strict";
11639
- var os2 = require("os");
11639
+ var os3 = require("os");
11640
11640
  var asyncForEach = require_forEach();
11641
11641
  var debug2 = require_node2()("winston:exception");
11642
11642
  var once = require_one_time();
@@ -11731,8 +11731,8 @@ var require_exception_handler = __commonJS({
11731
11731
  */
11732
11732
  getOsInfo() {
11733
11733
  return {
11734
- loadavg: os2.loadavg(),
11735
- uptime: os2.uptime()
11734
+ loadavg: os3.loadavg(),
11735
+ uptime: os3.uptime()
11736
11736
  };
11737
11737
  }
11738
11738
  /**
@@ -11874,7 +11874,7 @@ var require_rejection_stream = __commonJS({
11874
11874
  var require_rejection_handler = __commonJS({
11875
11875
  "../../packages/logger/node_modules/winston/lib/winston/rejection-handler.js"(exports2, module2) {
11876
11876
  "use strict";
11877
- var os2 = require("os");
11877
+ var os3 = require("os");
11878
11878
  var asyncForEach = require_forEach();
11879
11879
  var debug2 = require_node2()("winston:rejection");
11880
11880
  var once = require_one_time();
@@ -11971,8 +11971,8 @@ var require_rejection_handler = __commonJS({
11971
11971
  */
11972
11972
  getOsInfo() {
11973
11973
  return {
11974
- loadavg: os2.loadavg(),
11975
- uptime: os2.uptime()
11974
+ loadavg: os3.loadavg(),
11975
+ uptime: os3.uptime()
11976
11976
  };
11977
11977
  }
11978
11978
  /**
@@ -13357,6 +13357,10 @@ var Logger = class {
13357
13357
  console.info(message);
13358
13358
  FileLogService_default.write("INFO", String(message));
13359
13359
  };
13360
+ this.warn = (message) => {
13361
+ console.warn(message);
13362
+ FileLogService_default.write("WARN", String(message));
13363
+ };
13360
13364
  this.flush = () => FileLogService_default.flush();
13361
13365
  this.close = () => FileLogService_default.close();
13362
13366
  this.error = (error) => {
@@ -13500,7 +13504,7 @@ var import_promises = __toESM(require("fs/promises"), 1);
13500
13504
 
13501
13505
  // ../../packages/constants/src/Constants.ts
13502
13506
  var CONSTANTS = {
13503
- cliVersion: "1.1.15",
13507
+ cliVersion: "1.2.1",
13504
13508
  backendVersion: 1,
13505
13509
  backendPort: 5088,
13506
13510
  workerVersion: 2,
@@ -15098,8 +15102,8 @@ var HttpClientClass = class {
15098
15102
  throw new Error(err.message ?? "An error occurred on GET.");
15099
15103
  }
15100
15104
  };
15101
- this.getWorkerUrl = (path23) => {
15102
- const cleanPath = path23.startsWith("/") ? path23.substring(1) : path23;
15105
+ this.getWorkerUrl = (path24) => {
15106
+ const cleanPath = path24.startsWith("/") ? path24.substring(1) : path24;
15103
15107
  return `${this.workerHost}/${cleanPath}`;
15104
15108
  };
15105
15109
  this.workerHost = ProcessENVManager_default.getEnvVariable("REMORA_WORKER_HOST") || "http://worker:5069";
@@ -16672,7 +16676,7 @@ var LicenceManager = new LicenceManagerClass();
16672
16676
  var LicenceManager_default = LicenceManager;
16673
16677
 
16674
16678
  // ../../packages/executors/src/ConsumerExecutor.ts
16675
- var import_path17 = __toESM(require("path"));
16679
+ var import_path18 = __toESM(require("path"));
16676
16680
  var import_fs11 = __toESM(require("fs"));
16677
16681
  var import_readline6 = __toESM(require("readline"));
16678
16682
  var import_promises8 = __toESM(require("fs/promises"));
@@ -17058,6 +17062,11 @@ var AutoMapperEngineClass = class {
17058
17062
  var AutoMapperEngine = new AutoMapperEngineClass();
17059
17063
  var AutoMapperEngine_default = AutoMapperEngine;
17060
17064
 
17065
+ // ../../packages/engines/src/producer/ProducerEngine.ts
17066
+ var fs15 = __toESM(require("fs"), 1);
17067
+ var os = __toESM(require("os"), 1);
17068
+ var import_path14 = __toESM(require("path"), 1);
17069
+
17061
17070
  // ../../packages/engines/src/transform/TypeCaster.ts
17062
17071
  var import_dayjs = __toESM(require("dayjs"), 1);
17063
17072
  var import_customParseFormat = __toESM(require("dayjs/plugin/customParseFormat"), 1);
@@ -17177,12 +17186,12 @@ var noopTracker = { _operations: {}, measure: () => {
17177
17186
  }, getOperations: () => ({}) };
17178
17187
  var ProducerEngineClass = class {
17179
17188
  constructor() {
17180
- this.readFile = async (producer, options) => {
17189
+ this.readFile = async (producer, options, sourceOverride) => {
17181
17190
  Affirm_default(producer, "Invalid producer");
17182
17191
  Affirm_default(options, "Invalid options");
17183
17192
  if (options.readmode === "lines")
17184
17193
  Affirm_default(options.lines, "Invalid lines");
17185
- const source = Environment_default.getSource(producer.source);
17194
+ const source = sourceOverride ?? Environment_default.getSource(producer.source);
17186
17195
  Affirm_default(source, `No source found for producer "${producer.name}" with name "${producer.source}"`);
17187
17196
  const driver = await DriverFactory_default.instantiateSource(source);
17188
17197
  Affirm_default(driver, `No driver found for producer "${producer.name}" with driver type "${source.engine}"`);
@@ -17256,8 +17265,22 @@ var ProducerEngineClass = class {
17256
17265
  case "local":
17257
17266
  case "aws-s3":
17258
17267
  case "delta-share": {
17259
- const fileData = await this.readFile(producer, { readmode: "lines", lines: { from: 0, to: sampleSize } });
17260
- rawData = fileData.data;
17268
+ const { compressionType } = producer.settings;
17269
+ let tempDir = null;
17270
+ try {
17271
+ let effectiveProducer = producer;
17272
+ let effectiveSource = source;
17273
+ if (compressionType) {
17274
+ tempDir = fs15.mkdtempSync(import_path14.default.join(os.tmpdir(), "remora-sample-"));
17275
+ const decompressedFileKey = await this._decompressForSampling(producer, source, tempDir);
17276
+ effectiveProducer = { ...producer, settings: { ...producer.settings, fileKey: decompressedFileKey, compressionType: void 0 } };
17277
+ effectiveSource = { ...source, authentication: { ...source.authentication, path: tempDir } };
17278
+ }
17279
+ const fileData = await this.readFile(effectiveProducer, { readmode: "lines", lines: { from: 0, to: sampleSize } }, effectiveSource);
17280
+ rawData = fileData.data;
17281
+ } finally {
17282
+ if (tempDir) fs15.rmSync(tempDir, { recursive: true, force: true });
17283
+ }
17261
17284
  break;
17262
17285
  }
17263
17286
  default:
@@ -17342,13 +17365,54 @@ var ProducerEngineClass = class {
17342
17365
  }
17343
17366
  return dimensions;
17344
17367
  };
17368
+ this._decompressForSampling = async (producer, source, tempDir) => {
17369
+ const { fileKey, compressionType } = producer.settings;
17370
+ const sourcePath = source.authentication["path"];
17371
+ switch (compressionType?.toUpperCase()) {
17372
+ case "GZ": {
17373
+ const decompressedName = fileKey.replace(/\.gz$/i, "");
17374
+ const outputPath = import_path14.default.join(tempDir, decompressedName);
17375
+ const outputDir = import_path14.default.dirname(outputPath);
17376
+ if (!fs15.existsSync(outputDir)) fs15.mkdirSync(outputDir, { recursive: true });
17377
+ await ParseCompression_default.decompressToFile(compressionType, fileKey, sourcePath, outputPath);
17378
+ return decompressedName;
17379
+ }
17380
+ case "ZIP":
17381
+ case "TAR": {
17382
+ const extractDir = import_path14.default.join(tempDir, "extracted");
17383
+ await ParseCompression_default.decompressToFile(compressionType, fileKey, sourcePath, extractDir);
17384
+ const files = this._findFilesRecursive(extractDir);
17385
+ Affirm_default(files.length > 0, `No files found after decompressing "${fileKey}"`);
17386
+ const firstFile = files[0];
17387
+ const relativePath = import_path14.default.relative(extractDir, firstFile);
17388
+ const destPath = import_path14.default.join(tempDir, relativePath);
17389
+ const destDir = import_path14.default.dirname(destPath);
17390
+ if (!fs15.existsSync(destDir)) fs15.mkdirSync(destDir, { recursive: true });
17391
+ fs15.renameSync(firstFile, destPath);
17392
+ return relativePath;
17393
+ }
17394
+ default:
17395
+ throw new Error(`Unsupported compression type "${compressionType}" for producer "${producer.name}"`);
17396
+ }
17397
+ };
17398
+ this._findFilesRecursive = (dir) => {
17399
+ const results = [];
17400
+ for (const entry of fs15.readdirSync(dir)) {
17401
+ const fullPath = import_path14.default.join(dir, entry);
17402
+ if (fs15.statSync(fullPath).isDirectory())
17403
+ results.push(...this._findFilesRecursive(fullPath));
17404
+ else
17405
+ results.push(fullPath);
17406
+ }
17407
+ return results;
17408
+ };
17345
17409
  }
17346
17410
  };
17347
17411
  var ProducerEngine = new ProducerEngineClass();
17348
17412
  var ProducerEngine_default = ProducerEngine;
17349
17413
 
17350
17414
  // ../../packages/engines/src/ai/DeveloperEngine.ts
17351
- var import_path14 = __toESM(require("path"), 1);
17415
+ var import_path15 = __toESM(require("path"), 1);
17352
17416
  var import_promises6 = __toESM(require("fs/promises"), 1);
17353
17417
  var import_dayjs2 = __toESM(require("dayjs"), 1);
17354
17418
  var import_customParseFormat2 = __toESM(require("dayjs/plugin/customParseFormat"), 1);
@@ -17375,7 +17439,7 @@ var DeveloperEngineClass = class {
17375
17439
  _version: producer._version ?? 1
17376
17440
  };
17377
17441
  mappedProducer["$schema"] = producer["$schema"];
17378
- const producerPath = import_path14.default.join(process.cwd(), "remora", "producers", `${producer.name}.json`);
17442
+ const producerPath = import_path15.default.join(process.cwd(), "remora", "producers", `${producer.name}.json`);
17379
17443
  await import_promises6.default.writeFile(producerPath, JSON.stringify(mappedProducer, null, 4), "utf-8");
17380
17444
  return { producer: mappedProducer, fields: typeDefinitions };
17381
17445
  };
@@ -17634,8 +17698,8 @@ var DeveloperEngineClass = class {
17634
17698
  Affirm_default(fileType, "Producer must have a fileType setting for mock data generation");
17635
17699
  const mockRecords = this.generateMockRecords(producer.dimensions, records);
17636
17700
  const basePath = source.authentication.path || process.cwd();
17637
- const filePath = import_path14.default.join(basePath, fileKey.replace("%", "mock"));
17638
- await import_promises6.default.mkdir(import_path14.default.dirname(filePath), { recursive: true });
17701
+ const filePath = import_path15.default.join(basePath, fileKey.replace("%", "mock"));
17702
+ await import_promises6.default.mkdir(import_path15.default.dirname(filePath), { recursive: true });
17639
17703
  const content = this.formatMockData(mockRecords, fileType, delimiter);
17640
17704
  await import_promises6.default.writeFile(filePath, content, "utf-8");
17641
17705
  return { filePath, recordCount: records };
@@ -18482,6 +18546,112 @@ var TransformationEngineClass = class {
18482
18546
  var TransformationEngine = new TransformationEngineClass();
18483
18547
  var TransformationEngine_default = TransformationEngine;
18484
18548
 
18549
+ // ../../packages/engines/src/transform/DataValidationEngine.ts
18550
+ var DataValidationEngineClass = class {
18551
+ constructor() {
18552
+ this.applyValidations = (value, validations, fieldKey) => {
18553
+ for (const validation of validations) {
18554
+ const passed = this.evaluateRule(value, validation.rule);
18555
+ if (!passed) {
18556
+ return {
18557
+ valid: false,
18558
+ message: this.buildMessage(value, validation.rule, fieldKey),
18559
+ onFail: validation.onFail
18560
+ };
18561
+ }
18562
+ }
18563
+ return { valid: true };
18564
+ };
18565
+ this.evaluateRule = (value, rule) => {
18566
+ if ("required" in rule)
18567
+ return Algo_default.hasVal(value);
18568
+ if ("min" in rule) {
18569
+ if (!Algo_default.hasVal(value)) return true;
18570
+ const num = Number(value);
18571
+ return !isNaN(num) && num >= rule.min;
18572
+ }
18573
+ if ("max" in rule) {
18574
+ if (!Algo_default.hasVal(value)) return true;
18575
+ const num = Number(value);
18576
+ return !isNaN(num) && num <= rule.max;
18577
+ }
18578
+ if ("regex" in rule) {
18579
+ if (!Algo_default.hasVal(value)) return true;
18580
+ return new RegExp(rule.regex).test(String(value));
18581
+ }
18582
+ if ("min_length" in rule) {
18583
+ if (!Algo_default.hasVal(value)) return true;
18584
+ return String(value).length >= rule.min_length;
18585
+ }
18586
+ if ("max_length" in rule) {
18587
+ if (!Algo_default.hasVal(value)) return true;
18588
+ return String(value).length <= rule.max_length;
18589
+ }
18590
+ if ("in" in rule) {
18591
+ return rule.in.includes(value);
18592
+ }
18593
+ if ("not_in" in rule) {
18594
+ return !rule.not_in.includes(value);
18595
+ }
18596
+ return true;
18597
+ };
18598
+ this.buildMessage = (value, rule, fieldKey) => {
18599
+ const preview = Algo_default.hasVal(value) ? JSON.stringify(value) : "null/undefined";
18600
+ if ("required" in rule) return `Field "${fieldKey}" is required but got ${preview}`;
18601
+ if ("min" in rule) return `Field "${fieldKey}" value ${preview} is below minimum ${rule.min}`;
18602
+ if ("max" in rule) return `Field "${fieldKey}" value ${preview} exceeds maximum ${rule.max}`;
18603
+ if ("regex" in rule) return `Field "${fieldKey}" value ${preview} does not match pattern "${rule.regex}"`;
18604
+ if ("min_length" in rule) return `Field "${fieldKey}" value ${preview} is shorter than minimum length ${rule.min_length}`;
18605
+ if ("max_length" in rule) return `Field "${fieldKey}" value ${preview} exceeds maximum length ${rule.max_length}`;
18606
+ if ("in" in rule) return `Field "${fieldKey}" value ${preview} is not in the allowed values`;
18607
+ if ("not_in" in rule) return `Field "${fieldKey}" value ${preview} is in the disallowed values`;
18608
+ return `Field "${fieldKey}" failed validation`;
18609
+ };
18610
+ this.evaluateDatasetValidations = (validations, context) => {
18611
+ const results = [];
18612
+ for (const validation of validations) {
18613
+ const result = this.evaluateDatasetRule(validation, context);
18614
+ if (result) results.push(result);
18615
+ }
18616
+ return results;
18617
+ };
18618
+ this.extractUniqueFieldKeys = (validations) => {
18619
+ return validations.filter((v) => "unique_fields" in v.rule).flatMap((v) => v.rule.unique_fields);
18620
+ };
18621
+ this.hasRule = (validations, ruleKey) => {
18622
+ return validations.some((v) => ruleKey in v.rule);
18623
+ };
18624
+ this.evaluateDatasetRule = (validation, context) => {
18625
+ const { rule, onFail } = validation;
18626
+ const { rowCount, hasDuplicateRows, duplicateFields } = context;
18627
+ if ("not_empty" in rule) {
18628
+ if (rowCount === 0)
18629
+ return { message: "Dataset is empty", onFail };
18630
+ }
18631
+ if ("min_rows" in rule) {
18632
+ if (rowCount < rule.min_rows)
18633
+ return { message: `Dataset has ${rowCount} rows, expected at least ${rule.min_rows}`, onFail };
18634
+ }
18635
+ if ("max_rows" in rule) {
18636
+ if (rowCount > rule.max_rows)
18637
+ return { message: `Dataset has ${rowCount} rows, expected at most ${rule.max_rows}`, onFail };
18638
+ }
18639
+ if ("no_duplicates" in rule) {
18640
+ if (hasDuplicateRows)
18641
+ return { message: "Dataset contains duplicate rows", onFail };
18642
+ }
18643
+ if ("unique_fields" in rule) {
18644
+ const failedFields = rule.unique_fields.filter((f) => duplicateFields.includes(f));
18645
+ if (failedFields.length > 0)
18646
+ return { message: `Duplicate values found in field(s): ${failedFields.join(", ")}`, onFail };
18647
+ }
18648
+ return null;
18649
+ };
18650
+ }
18651
+ };
18652
+ var DataValidationEngine = new DataValidationEngineClass();
18653
+ var DataValidationEngine_default = DataValidationEngine;
18654
+
18485
18655
  // ../../packages/engines/src/usage/DataframeManager.ts
18486
18656
  var DataframeManagerClass = class {
18487
18657
  fill(points, from, to, onlyLastValue, maintainLastValue) {
@@ -18710,10 +18880,10 @@ var UsageManager = new UsageManagerClass();
18710
18880
  var UsageManager_default = UsageManager;
18711
18881
 
18712
18882
  // ../../packages/executors/src/OutputExecutor.ts
18713
- var fs17 = __toESM(require("fs"));
18883
+ var fs18 = __toESM(require("fs"));
18714
18884
 
18715
18885
  // ../../packages/executors/src/ExecutorScope.ts
18716
- var import_path15 = __toESM(require("path"));
18886
+ var import_path16 = __toESM(require("path"));
18717
18887
  var import_fs10 = __toESM(require("fs"));
18718
18888
  var import_promises7 = __toESM(require("fs/promises"));
18719
18889
  var ExecutorScopeClass2 = class {
@@ -18721,7 +18891,7 @@ var ExecutorScopeClass2 = class {
18721
18891
  this.WORKERS_FOLDER = "workers";
18722
18892
  this.PRODUCERS_FOLDER = "producers";
18723
18893
  this.getWorkerPath = (scope, workerId) => {
18724
- return import_path15.default.join(
18894
+ return import_path16.default.join(
18725
18895
  Constants_default.defaults.REMORA_PATH,
18726
18896
  Constants_default.defaults.PRODUCER_TEMP_FOLDER,
18727
18897
  // A specific execution sits entirely in this folder, so at the end it's safe to delete it entirely
@@ -18731,7 +18901,7 @@ var ExecutorScopeClass2 = class {
18731
18901
  );
18732
18902
  };
18733
18903
  this.getProducerPath = (scope, producer, sourceFileKey) => {
18734
- return import_path15.default.join(
18904
+ return import_path16.default.join(
18735
18905
  Constants_default.defaults.REMORA_PATH,
18736
18906
  Constants_default.defaults.PRODUCER_TEMP_FOLDER,
18737
18907
  // A specific execution sits entirely in this folder, so at the end it's safe to delete it entirely
@@ -18742,7 +18912,7 @@ var ExecutorScopeClass2 = class {
18742
18912
  );
18743
18913
  };
18744
18914
  this.getMainPath = (scope) => {
18745
- return import_path15.default.join(
18915
+ return import_path16.default.join(
18746
18916
  Constants_default.defaults.REMORA_PATH,
18747
18917
  Constants_default.defaults.PRODUCER_TEMP_FOLDER,
18748
18918
  scope.folder,
@@ -18750,7 +18920,7 @@ var ExecutorScopeClass2 = class {
18750
18920
  );
18751
18921
  };
18752
18922
  this.clearScope = async (scope) => {
18753
- const scopePath = import_path15.default.join(
18923
+ const scopePath = import_path16.default.join(
18754
18924
  Constants_default.defaults.REMORA_PATH,
18755
18925
  Constants_default.defaults.PRODUCER_TEMP_FOLDER,
18756
18926
  scope.folder
@@ -18760,7 +18930,7 @@ var ExecutorScopeClass2 = class {
18760
18930
  }
18761
18931
  };
18762
18932
  this.ensurePath = (fileUri) => {
18763
- const dir = import_path15.default.dirname(fileUri);
18933
+ const dir = import_path16.default.dirname(fileUri);
18764
18934
  if (!import_fs10.default.existsSync(dir))
18765
18935
  import_fs10.default.mkdirSync(dir, { recursive: true });
18766
18936
  if (!import_fs10.default.existsSync(fileUri))
@@ -18772,7 +18942,7 @@ var ExecutorScope2 = new ExecutorScopeClass2();
18772
18942
  var ExecutorScope_default2 = ExecutorScope2;
18773
18943
 
18774
18944
  // ../../packages/executors/src/OutputExecutor.ts
18775
- var import_path16 = __toESM(require("path"));
18945
+ var import_path17 = __toESM(require("path"));
18776
18946
  var OutputExecutorClass = class {
18777
18947
  constructor() {
18778
18948
  this._getInternalRecordFormat = (consumer) => {
@@ -18818,13 +18988,13 @@ var OutputExecutorClass = class {
18818
18988
  for (const output of consumer.outputs) {
18819
18989
  const destination = Environment_default.getSource(output.exportDestination);
18820
18990
  const driver = await DriverFactory_default.instantiateDestination(destination);
18821
- const currentPath = import_path16.default.dirname(ExecutorScope_default2.getMainPath(scope));
18991
+ const currentPath = import_path17.default.dirname(ExecutorScope_default2.getMainPath(scope));
18822
18992
  const destinationName = this._composeFileName(consumer, output, this._getExtension(output));
18823
18993
  Logger_default.log(`Exporting consumer "${consumer.name}" to "${output.exportDestination}" as ${output.format} (${destinationName})`);
18824
- const filenameArray = fs17.readdirSync(currentPath).filter((filename) => filename.includes(".dataset"));
18994
+ const filenameArray = fs18.readdirSync(currentPath).filter((filename) => filename.includes(".dataset"));
18825
18995
  for (const filename in filenameArray) {
18826
18996
  const destinationPath = this.getCompletedPath(destinationName, filename);
18827
- const startingPath = import_path16.default.join(currentPath, filenameArray[filename]);
18997
+ const startingPath = import_path17.default.join(currentPath, filenameArray[filename]);
18828
18998
  if (output.format === internalFormat) {
18829
18999
  results.push(await driver.move(startingPath, destinationPath));
18830
19000
  } else {
@@ -18884,8 +19054,8 @@ var OutputExecutor_default = OutputExecutor;
18884
19054
  var ConsumerExecutorClass = class {
18885
19055
  constructor() {
18886
19056
  this._getWorkPath = (consumer, executionId) => {
18887
- const execFolder = import_path17.default.join(consumer.name, executionId);
18888
- const workPath = import_path17.default.join("./remora", Constants_default.defaults.PRODUCER_TEMP_FOLDER, execFolder, ".dataset");
19057
+ const execFolder = import_path18.default.join(consumer.name, executionId);
19058
+ const workPath = import_path18.default.join("./remora", Constants_default.defaults.PRODUCER_TEMP_FOLDER, execFolder, ".dataset");
18889
19059
  return workPath;
18890
19060
  };
18891
19061
  this._clearWorkPath = async (workPath) => {
@@ -18896,7 +19066,7 @@ var ConsumerExecutorClass = class {
18896
19066
  } catch (error) {
18897
19067
  }
18898
19068
  try {
18899
- const dir = import_path17.default.dirname(workPath);
19069
+ const dir = import_path18.default.dirname(workPath);
18900
19070
  if (import_fs11.default.existsSync(dir)) {
18901
19071
  await import_promises8.default.rmdir(dir);
18902
19072
  }
@@ -18904,7 +19074,7 @@ var ConsumerExecutorClass = class {
18904
19074
  }
18905
19075
  };
18906
19076
  this._ensurePath = (pathUri) => {
18907
- const dir = import_path17.default.dirname(pathUri);
19077
+ const dir = import_path18.default.dirname(pathUri);
18908
19078
  if (!import_fs11.default.existsSync(dir))
18909
19079
  import_fs11.default.mkdirSync(dir, { recursive: true });
18910
19080
  if (!import_fs11.default.existsSync(pathUri))
@@ -18971,6 +19141,32 @@ var ConsumerExecutorClass = class {
18971
19141
  }
18972
19142
  }
18973
19143
  }
19144
+ for (const field of fields) {
19145
+ const { cField } = field;
19146
+ const fieldKey = cField.alias ?? cField.key;
19147
+ if (cField.validate && cField.validate.length > 0) {
19148
+ const result = DataValidationEngine_default.applyValidations(record[fieldKey], cField.validate, fieldKey);
19149
+ if (!result.valid) {
19150
+ const errorMessage = `Validation failed for field "${fieldKey}" (index: ${recordIndex}): ${result.message}`;
19151
+ switch (result.onFail) {
19152
+ case "set_default":
19153
+ record[fieldKey] = cField.default;
19154
+ break;
19155
+ case "skip":
19156
+ return null;
19157
+ case "warn":
19158
+ Logger_default.warn(errorMessage);
19159
+ break;
19160
+ case "fail":
19161
+ default: {
19162
+ const err = new Error(errorMessage);
19163
+ Logger_default.error(err);
19164
+ throw err;
19165
+ }
19166
+ }
19167
+ }
19168
+ }
19169
+ }
18974
19170
  try {
18975
19171
  for (const dimension of dimensions) {
18976
19172
  const field = fields.find((x) => x.cField.key === dimension.name);
@@ -19211,6 +19407,48 @@ var ConsumerExecutorClass = class {
19211
19407
  return false;
19212
19408
  }
19213
19409
  };
19410
+ this.processDatasetValidation = async (consumer, datasetPath) => {
19411
+ const validations = consumer.validate;
19412
+ if (!validations || validations.length === 0) return [];
19413
+ const internalRecordFormat = OutputExecutor_default._getInternalRecordFormat(consumer);
19414
+ const internalFields = ConsumerManager_default.getExpandedFields(consumer);
19415
+ let rowCount = 0;
19416
+ const seenRows = /* @__PURE__ */ new Set();
19417
+ const fieldValueSets = /* @__PURE__ */ new Map();
19418
+ let hasDuplicateRows = false;
19419
+ const duplicateFields = [];
19420
+ const uniqueFieldKeys = DataValidationEngine_default.extractUniqueFieldKeys(validations);
19421
+ const checkDuplicateRows = DataValidationEngine_default.hasRule(validations, "no_duplicates");
19422
+ for (const fieldKey of uniqueFieldKeys) {
19423
+ fieldValueSets.set(fieldKey, /* @__PURE__ */ new Set());
19424
+ }
19425
+ const reader = import_fs11.default.createReadStream(datasetPath);
19426
+ const lineReader = import_readline6.default.createInterface({ input: reader, crlfDelay: Infinity });
19427
+ for await (const line of lineReader) {
19428
+ rowCount++;
19429
+ if (checkDuplicateRows) {
19430
+ if (seenRows.has(line))
19431
+ hasDuplicateRows = true;
19432
+ else
19433
+ seenRows.add(line);
19434
+ }
19435
+ if (uniqueFieldKeys.length > 0) {
19436
+ const record = internalRecordFormat === "CSV" || internalRecordFormat === "TXT" ? LineParser_default._internalParseCSV(line, internalFields) : LineParser_default._internalParseJSON(line);
19437
+ for (const fieldKey of uniqueFieldKeys) {
19438
+ const valueSet = fieldValueSets.get(fieldKey);
19439
+ const val = String(record[fieldKey] ?? "");
19440
+ if (valueSet.has(val)) {
19441
+ if (!duplicateFields.includes(fieldKey))
19442
+ duplicateFields.push(fieldKey);
19443
+ } else {
19444
+ valueSet.add(val);
19445
+ }
19446
+ }
19447
+ }
19448
+ }
19449
+ lineReader.close();
19450
+ return DataValidationEngine_default.evaluateDatasetValidations(validations, { rowCount, hasDuplicateRows, duplicateFields });
19451
+ };
19214
19452
  /**
19215
19453
  * Compares two values, handling numbers, strings, and dates
19216
19454
  * Returns: negative if a < b, positive if a > b, 0 if equal
@@ -19232,7 +19470,7 @@ var ConsumerExecutor = new ConsumerExecutorClass();
19232
19470
  var ConsumerExecutor_default = ConsumerExecutor;
19233
19471
 
19234
19472
  // ../../packages/executors/src/ProducerExecutor.ts
19235
- var import_path18 = __toESM(require("path"));
19473
+ var import_path19 = __toESM(require("path"));
19236
19474
  var ProducerExecutorClass = class {
19237
19475
  constructor() {
19238
19476
  this.ready = async (producer, scope) => {
@@ -19256,7 +19494,7 @@ var ProducerExecutorClass = class {
19256
19494
  counter = performance.now();
19257
19495
  for (const dimension of dimensions) {
19258
19496
  if (dimension.prodDimension.sourceFilename === true)
19259
- record[dimension.name] = import_path18.default.basename(chunk.fileUri);
19497
+ record[dimension.name] = import_path19.default.basename(chunk.fileUri);
19260
19498
  const maskType = ProducerManager_default.getMask(dimension.prodDimension);
19261
19499
  if (Algo_default.hasVal(maskType))
19262
19500
  record[dimension.name] = CryptoEngine_default.hashValue(maskType, record[dimension.name]?.toString(), dimension.prodDimension.type);
@@ -19290,7 +19528,7 @@ var ExecutorPerformance_default = ExecutorPerformance;
19290
19528
  var import_os = __toESM(require("os"));
19291
19529
  var import_fs12 = __toESM(require("fs"));
19292
19530
  var import_promises9 = __toESM(require("fs/promises"));
19293
- var import_path19 = __toESM(require("path"));
19531
+ var import_path20 = __toESM(require("path"));
19294
19532
  var import_workerpool = __toESM(require("workerpool"));
19295
19533
 
19296
19534
  // ../../packages/executors/src/ExecutorProgress.ts
@@ -19348,7 +19586,7 @@ var ExecutorProgress = class {
19348
19586
  var ExecutorProgress_default = ExecutorProgress;
19349
19587
 
19350
19588
  // ../../packages/executors/src/ExecutorWriter.ts
19351
- var fs19 = __toESM(require("fs"));
19589
+ var fs20 = __toESM(require("fs"));
19352
19590
  var import_readline7 = __toESM(require("readline"));
19353
19591
  var ExecutorWriter = class {
19354
19592
  constructor() {
@@ -19365,11 +19603,11 @@ var ExecutorWriter = class {
19365
19603
  };
19366
19604
  this.splitBySize = async (scope, sourcePath) => {
19367
19605
  const maxOutputFileSize = scope.limitFileSize * this.FAKE_GB;
19368
- const readStream = fs19.createReadStream(sourcePath);
19606
+ const readStream = fs20.createReadStream(sourcePath);
19369
19607
  const reader = import_readline7.default.createInterface({ input: readStream, crlfDelay: Infinity });
19370
19608
  let writerIndex = 0;
19371
19609
  let destPath = this.getCompletedPath(sourcePath, writerIndex);
19372
- let writeStream = fs19.createWriteStream(destPath, { flags: "a" });
19610
+ let writeStream = fs20.createWriteStream(destPath, { flags: "a" });
19373
19611
  for await (const line of reader) {
19374
19612
  if (readStream.bytesRead > maxOutputFileSize * (writerIndex + 1)) {
19375
19613
  writeStream.end();
@@ -19379,7 +19617,7 @@ var ExecutorWriter = class {
19379
19617
  });
19380
19618
  writerIndex++;
19381
19619
  destPath = this.getCompletedPath(sourcePath, writerIndex);
19382
- writeStream = fs19.createWriteStream(destPath, { flags: "a" });
19620
+ writeStream = fs20.createWriteStream(destPath, { flags: "a" });
19383
19621
  }
19384
19622
  writeStream.write(line + "\n");
19385
19623
  }
@@ -19388,7 +19626,7 @@ var ExecutorWriter = class {
19388
19626
  writeStream.on("finish", resolve);
19389
19627
  writeStream.on("error", reject);
19390
19628
  });
19391
- await fs19.promises.unlink(sourcePath);
19629
+ await fs20.promises.unlink(sourcePath);
19392
19630
  };
19393
19631
  /**
19394
19632
  * Manage the Writestream for main.dataset
@@ -19458,7 +19696,7 @@ var ExecutorOrchestratorClass = class {
19458
19696
  };
19459
19697
  const workerPath = this._getWorkerPath();
19460
19698
  Logger_default.log(`Initializing worker pool from ${workerPath} (heap limit: ${Constants_default.defaults.MIN_RUNTIME_HEAP_MB}MB)`);
19461
- return import_workerpool.default.pool(import_path19.default.join(workerPath, "ExecutorWorker.js"), options);
19699
+ return import_workerpool.default.pool(import_path20.default.join(workerPath, "ExecutorWorker.js"), options);
19462
19700
  };
19463
19701
  this.launch = async (request) => {
19464
19702
  Affirm_default(request, "Invalid options");
@@ -19468,7 +19706,7 @@ var ExecutorOrchestratorClass = class {
19468
19706
  const tracker = new ExecutorPerformance_default();
19469
19707
  const _progress = new ExecutorProgress_default(logProgress);
19470
19708
  const { usageId } = UsageManager_default.startUsage(consumer, details);
19471
- const scope = { id: usageId, folder: `${consumer.name}_${usageId}`, workersId: [], limitFileSize: consumer.MaximumFileSize };
19709
+ const scope = { id: usageId, folder: `${consumer.name}_${usageId}`, workersId: [], limitFileSize: consumer.maximumFileSize };
19472
19710
  const pool = this.createPool();
19473
19711
  try {
19474
19712
  const start = performance.now();
@@ -19563,6 +19801,30 @@ var ExecutorOrchestratorClass = class {
19563
19801
  postOperation.totalOutputCount = unifiedOutputCount;
19564
19802
  Logger_default.log(`[${usageId}] Pivot complete: ${unifiedOutputCount} rows in ${Math.round(performance.now() - counter)}ms`);
19565
19803
  }
19804
+ if (consumer.validate && consumer.validate.length > 0) {
19805
+ Logger_default.log(`[${usageId}] Running dataset-level validations`);
19806
+ counter = performance.now();
19807
+ const validationResults = await ConsumerExecutor_default.processDatasetValidation(consumer, ExecutorScope_default2.getMainPath(scope));
19808
+ tracker.measure("dataset-validation", performance.now() - counter);
19809
+ for (const result of validationResults) {
19810
+ if (result.onFail === "fail") {
19811
+ const err = new Error(`Dataset validation failed for consumer "${consumer.name}": ${result.message}`);
19812
+ Logger_default.error(err);
19813
+ throw err;
19814
+ } else if (result.onFail === "warn") {
19815
+ Logger_default.warn(`Dataset validation warning for consumer "${consumer.name}": ${result.message}`);
19816
+ }
19817
+ }
19818
+ Logger_default.log(`[${usageId}] Dataset validations complete in ${Math.round(performance.now() - counter)}ms`);
19819
+ }
19820
+ if (scope.limitFileSize) {
19821
+ Logger_default.log(`[${usageId}] Splitting output by size limit (${scope.limitFileSize})`);
19822
+ counter = performance.now();
19823
+ const writer = new ExecutorWriter_default();
19824
+ await writer.splitBySize(scope, ExecutorScope_default2.getMainPath(scope));
19825
+ tracker.measure("split-by-size", performance.now() - counter);
19826
+ Logger_default.log(`[${usageId}] Split complete in ${Math.round(performance.now() - counter)}ms`);
19827
+ }
19566
19828
  counter = performance.now();
19567
19829
  Logger_default.log(`[${usageId}] Exporting results to ${consumer.outputs.length} output(s)`);
19568
19830
  const exportRes = await OutputExecutor_default.exportResult(consumer, ConsumerManager_default.getExpandedFields(consumer), scope);
@@ -19670,20 +19932,19 @@ var ExecutorOrchestratorClass = class {
19670
19932
  this._getWorkerPath = () => {
19671
19933
  const currentDir = __dirname;
19672
19934
  if (ProcessENVManager_default.getEnvVariable("NODE_ENV") === "dev" || ProcessENVManager_default.getEnvVariable("NODE_ENV") === "development")
19673
- return import_path19.default.resolve("./.build/workers");
19935
+ return import_path20.default.resolve("./.build/workers");
19674
19936
  const forcedPath = ProcessENVManager_default.getEnvVariable("REMORA_WORKERS_PATH");
19675
19937
  if (forcedPath && forcedPath.length > 0)
19676
- return import_path19.default.join(__dirname, forcedPath);
19938
+ return import_path20.default.join(__dirname, forcedPath);
19677
19939
  if (!currentDir.includes(".build")) {
19678
- return import_path19.default.join(__dirname, "../workers");
19940
+ return import_path20.default.join(__dirname, "../workers");
19679
19941
  } else {
19680
- return import_path19.default.resolve("./.build/workers");
19942
+ return import_path20.default.resolve("./.build/workers");
19681
19943
  }
19682
19944
  };
19683
19945
  this.reconcileExecutorThreadsResults = async (scope, executorResults, tracker) => {
19684
19946
  const mainPath = ExecutorScope_default2.getMainPath(scope);
19685
19947
  ConsumerExecutor_default._ensurePath(mainPath);
19686
- const writer = new ExecutorWriter_default();
19687
19948
  if (executorResults.length > 1) {
19688
19949
  Logger_default.log(`[${scope.id}] Merging ${executorResults.length} worker output files into ${mainPath}`);
19689
19950
  const perf = performance.now();
@@ -19699,10 +19960,6 @@ var ExecutorOrchestratorClass = class {
19699
19960
  Logger_default.log(`[${scope.id}] Single worker \u2014 renaming output to ${mainPath}`);
19700
19961
  await import_promises9.default.rename(executorResults[0].resultUri, mainPath);
19701
19962
  }
19702
- if (scope.limitFileSize) {
19703
- Logger_default.log(`[${scope.id}] Splitting output by size limit (${scope.limitFileSize})`);
19704
- await writer.splitBySize(scope, mainPath);
19705
- }
19706
19963
  return mainPath;
19707
19964
  };
19708
19965
  this.performCleanupOperations = async (scope, tracker) => {
@@ -19889,19 +20146,19 @@ var discover = async (producerName) => {
19889
20146
  // src/actions/create_producer.ts
19890
20147
  var import_chalk8 = __toESM(require("chalk"));
19891
20148
  var import_fs13 = __toESM(require("fs"));
19892
- var import_path20 = __toESM(require("path"));
20149
+ var import_path21 = __toESM(require("path"));
19893
20150
  var create_producer = async (name) => {
19894
20151
  try {
19895
20152
  if (!import_fs13.default.existsSync("./remora/producers")) {
19896
20153
  throw new Error(import_chalk8.default.red("Missing directory: ") + import_chalk8.default.yellow("./remora/producers"));
19897
20154
  }
19898
20155
  const defaultProducerTemplate = import_fs13.default.readFileSync(
19899
- import_path20.default.join(DOCUMENTATION_DIR, "default_resources/producer.json"),
20156
+ import_path21.default.join(DOCUMENTATION_DIR, "default_resources/producer.json"),
19900
20157
  "utf-8"
19901
20158
  );
19902
20159
  const defaultProducer = JSON.parse(defaultProducerTemplate);
19903
20160
  defaultProducer.name = name;
19904
- const producerPath = import_path20.default.join("remora/producers", `${name}.json`);
20161
+ const producerPath = import_path21.default.join("remora/producers", `${name}.json`);
19905
20162
  import_fs13.default.writeFileSync(producerPath, JSON.stringify(defaultProducer, null, 4));
19906
20163
  console.log(import_chalk8.default.green(`\u2705 Created producer config at ${producerPath}`));
19907
20164
  console.log(import_chalk8.default.blue("Remember to:"));
@@ -19918,20 +20175,20 @@ var create_producer = async (name) => {
19918
20175
  // src/actions/create_consumer.ts
19919
20176
  var import_chalk9 = __toESM(require("chalk"));
19920
20177
  var import_fs14 = __toESM(require("fs"));
19921
- var import_path21 = __toESM(require("path"));
20178
+ var import_path22 = __toESM(require("path"));
19922
20179
  var create_consumer = async (name, producerName) => {
19923
20180
  try {
19924
20181
  if (!import_fs14.default.existsSync("./remora/consumers")) {
19925
20182
  throw new Error(import_chalk9.default.red("Missing directory: ") + import_chalk9.default.yellow("./remora/consumers"));
19926
20183
  }
19927
20184
  const defaultConsumerTemplate = import_fs14.default.readFileSync(
19928
- import_path21.default.join(DOCUMENTATION_DIR, "default_resources/consumer.json"),
20185
+ import_path22.default.join(DOCUMENTATION_DIR, "default_resources/consumer.json"),
19929
20186
  "utf-8"
19930
20187
  );
19931
20188
  const defaultConsumer = JSON.parse(defaultConsumerTemplate);
19932
20189
  defaultConsumer.name = name;
19933
20190
  if (producerName) {
19934
- const producerPath = import_path21.default.join("remora/producers", `${producerName}.json`);
20191
+ const producerPath = import_path22.default.join("remora/producers", `${producerName}.json`);
19935
20192
  if (!import_fs14.default.existsSync(producerPath)) {
19936
20193
  throw new Error(import_chalk9.default.red("Producer not found: ") + import_chalk9.default.yellow(producerPath));
19937
20194
  }
@@ -19952,7 +20209,7 @@ var create_consumer = async (name, producerName) => {
19952
20209
  defaultConsumer.filters = void 0;
19953
20210
  defaultConsumer.metadata = void 0;
19954
20211
  }
19955
- const consumerPath = import_path21.default.join("remora/consumers", `${name}.json`);
20212
+ const consumerPath = import_path22.default.join("remora/consumers", `${name}.json`);
19956
20213
  import_fs14.default.writeFileSync(consumerPath, JSON.stringify(defaultConsumer, null, 4));
19957
20214
  console.log(import_chalk9.default.green(`\u2705 Created consumer config at ${consumerPath}`));
19958
20215
  if (!producerName) {
@@ -19977,7 +20234,7 @@ var create_consumer = async (name, producerName) => {
19977
20234
  var import_chalk10 = __toESM(require("chalk"));
19978
20235
  var import_ora5 = __toESM(require("ora"));
19979
20236
  var import_fs15 = __toESM(require("fs"));
19980
- var import_path22 = __toESM(require("path"));
20237
+ var import_path23 = __toESM(require("path"));
19981
20238
  var automap = async (producerName, schemaNames) => {
19982
20239
  try {
19983
20240
  compile();
@@ -20002,12 +20259,12 @@ var automap = async (producerName, schemaNames) => {
20002
20259
  const sampleStrings = sampleData.map((item) => JSON.stringify(item));
20003
20260
  const mapResult = await AutoMapperEngine_default.map(sampleStrings, schemas, producer.settings.fileKey, [source]);
20004
20261
  for (const producer2 of mapResult.producers) {
20005
- const producerPath = import_path22.default.join("remora/producers", `${producer2.name}.json`);
20262
+ const producerPath = import_path23.default.join("remora/producers", `${producer2.name}.json`);
20006
20263
  import_fs15.default.writeFileSync(producerPath, JSON.stringify(producer2, null, 4));
20007
20264
  console.log(import_chalk10.default.blue(`Created producer: ${producer2.name}`));
20008
20265
  }
20009
20266
  for (const consumer of mapResult.consumers) {
20010
- const consumerPath = import_path22.default.join("remora/consumers", `${consumer.name}.json`);
20267
+ const consumerPath = import_path23.default.join("remora/consumers", `${consumer.name}.json`);
20011
20268
  import_fs15.default.writeFileSync(consumerPath, JSON.stringify(consumer, null, 4));
20012
20269
  console.log(import_chalk10.default.blue(`Created consumer: ${consumer.name}`));
20013
20270
  }