@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.
- package/CHANGELOG.md +33 -0
- package/index.js +979 -515
- package/package.json +3 -2
- package/workers/ExecutorWorker.js +899 -468
|
@@ -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
|
|
1242
|
-
module2.exports =
|
|
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
|
|
1253
|
+
var format4 = require_format();
|
|
1254
1254
|
var { LEVEL, MESSAGE } = require_triple_beam();
|
|
1255
|
-
module2.exports =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
2048
|
-
module2.exports =
|
|
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
|
|
2063
|
+
var format4 = require_format();
|
|
2064
2064
|
var { MESSAGE } = require_triple_beam();
|
|
2065
2065
|
var jsonStringify = require_safe_stable_stringify();
|
|
2066
|
-
module2.exports =
|
|
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
|
|
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 =
|
|
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
|
|
2256
|
+
var format4 = require_format();
|
|
2257
2257
|
var ms2 = require_ms();
|
|
2258
|
-
module2.exports =
|
|
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
|
|
2273
|
+
var format4 = require_format();
|
|
2274
2274
|
var { LEVEL, MESSAGE, SPLAT } = require_triple_beam();
|
|
2275
|
-
module2.exports =
|
|
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
|
|
2309
|
+
var format4 = require_format();
|
|
2310
2310
|
var { MESSAGE } = require_triple_beam();
|
|
2311
2311
|
var jsonStringify = require_safe_stable_stringify();
|
|
2312
|
-
module2.exports =
|
|
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,
|
|
2434
|
+
function parse(dateStr, format4, i18n) {
|
|
2435
2435
|
if (i18n === void 0) {
|
|
2436
2436
|
i18n = {};
|
|
2437
2437
|
}
|
|
2438
|
-
if (typeof
|
|
2438
|
+
if (typeof format4 !== "string") {
|
|
2439
2439
|
throw new Error("Invalid format in fecha parse");
|
|
2440
2440
|
}
|
|
2441
|
-
|
|
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 =
|
|
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
|
|
2822
|
-
module2.exports =
|
|
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
|
|
2842
|
+
var format4 = require_format();
|
|
2843
2843
|
var { MESSAGE } = require_triple_beam();
|
|
2844
|
-
module2.exports =
|
|
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
|
|
2863
|
+
var format4 = exports2.format = require_format();
|
|
2864
2864
|
exports2.levels = require_levels();
|
|
2865
2865
|
function exposeFormat(name, requireFormat) {
|
|
2866
|
-
Object.defineProperty(
|
|
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:
|
|
2931
|
+
var { format: format4 } = require("util");
|
|
2932
2932
|
exports2.warn = {
|
|
2933
2933
|
deprecated(prop) {
|
|
2934
2934
|
return () => {
|
|
2935
|
-
throw new Error(
|
|
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
|
-
|
|
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(
|
|
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
|
|
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 =
|
|
4253
|
+
module2.exports = Readable8;
|
|
4254
4254
|
var Duplex;
|
|
4255
|
-
|
|
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()(
|
|
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
|
|
4334
|
+
function Readable8(options) {
|
|
4335
4335
|
Duplex = Duplex || require_stream_duplex();
|
|
4336
|
-
if (!(this instanceof
|
|
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(
|
|
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
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
4447
|
+
Readable8.prototype.isPaused = function() {
|
|
4448
4448
|
return this._readableState.flowing === false;
|
|
4449
4449
|
};
|
|
4450
|
-
|
|
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
|
-
|
|
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
|
-
|
|
4605
|
+
Readable8.prototype._read = function(n4) {
|
|
4606
4606
|
errorOrDestroy(this, new ERR_METHOD_NOT_IMPLEMENTED("_read()"));
|
|
4607
4607
|
};
|
|
4608
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
4767
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
-
|
|
4920
|
-
Object.defineProperty(
|
|
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
|
-
|
|
4966
|
+
Readable8.from = function(iterable, opts) {
|
|
4967
4967
|
if (from === void 0) {
|
|
4968
4968
|
from = require_from();
|
|
4969
4969
|
}
|
|
4970
|
-
return from(
|
|
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
|
|
4992
|
+
var Readable8 = require_stream_readable();
|
|
4993
4993
|
var Writable2 = require_stream_writable();
|
|
4994
|
-
require_inherits()(Duplex,
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
8481
|
+
fs24.close(fd, noop);
|
|
8482
8482
|
return;
|
|
8483
8483
|
}
|
|
8484
|
-
return
|
|
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
|
|
8544
|
-
var
|
|
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 ?
|
|
8575
|
-
this.dirname = options.dirname ||
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
8900
|
-
|
|
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 =
|
|
9003
|
+
const fullpath = path21.join(this.dirname, this.filename);
|
|
9004
9004
|
debug("create stream start", fullpath, this.options);
|
|
9005
|
-
const dest =
|
|
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 =
|
|
9029
|
-
const basename =
|
|
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
|
-
|
|
9037
|
-
|
|
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 =
|
|
9063
|
-
const basename =
|
|
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 =
|
|
9084
|
-
|
|
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 =
|
|
9107
|
-
|
|
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
|
-
|
|
9112
|
+
fs24.rename(tmppath, path21.join(this.dirname, fileName), cb);
|
|
9113
9113
|
});
|
|
9114
9114
|
}.bind(this, x2));
|
|
9115
9115
|
}
|
|
9116
9116
|
asyncSeries(tasks, () => {
|
|
9117
|
-
|
|
9118
|
-
|
|
9119
|
-
|
|
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
|
-
|
|
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 =
|
|
9139
|
-
var out =
|
|
9138
|
+
var inp = fs24.createReadStream(src);
|
|
9139
|
+
var out = fs24.createWriteStream(dest);
|
|
9140
9140
|
out.on("finish", () => {
|
|
9141
|
-
|
|
9141
|
+
fs24.unlink(src, callback);
|
|
9142
9142
|
});
|
|
9143
9143
|
inp.pipe(gzip).pipe(out);
|
|
9144
9144
|
});
|
|
9145
9145
|
}
|
|
9146
9146
|
_createLogDirIfNotExist(dirPath) {
|
|
9147
|
-
if (!
|
|
9148
|
-
|
|
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
|
|
9232
|
+
const path21 = options.params.path || null;
|
|
9233
9233
|
delete options.params.path;
|
|
9234
|
-
this._request(options, auth,
|
|
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
|
|
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,
|
|
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,
|
|
9293
|
+
_request(options, auth, path21, callback) {
|
|
9294
9294
|
options = options || {};
|
|
9295
9295
|
auth = auth || this.auth;
|
|
9296
|
-
|
|
9296
|
+
path21 = path21 || this.path || "";
|
|
9297
9297
|
if (this.batch) {
|
|
9298
|
-
this._doBatch(options, callback, auth,
|
|
9298
|
+
this._doBatch(options, callback, auth, path21);
|
|
9299
9299
|
} else {
|
|
9300
|
-
this._doRequest(options, callback, auth,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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: `/${
|
|
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:
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
11232
|
-
this._consoleWrites++;
|
|
11263
|
+
this.writeConsole("info", message);
|
|
11233
11264
|
};
|
|
11234
11265
|
this.warn = (message) => {
|
|
11235
|
-
|
|
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
|
-
|
|
11255
|
-
this._consoleWrites++;
|
|
11284
|
+
this.writeConsole("error", message, suppressed ? void 0 : stack);
|
|
11256
11285
|
FileLogService_default.write("ERROR", message, stack);
|
|
11257
|
-
|
|
11258
|
-
|
|
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
|
|
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
|
|
12623
|
-
if (
|
|
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 (${
|
|
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
|
|
12698
|
-
if (positionalFormats.includes(
|
|
12699
|
-
errors.push(`The ${
|
|
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 ${
|
|
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
|
|
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 (
|
|
12796
|
-
errors.push(`Consumer "${consumer.name}" has a cyclic run-consumer (onSuccess/onError) chain: ${[...
|
|
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
|
-
|
|
12913
|
+
path21.push(name);
|
|
12802
12914
|
for (const target of targetsOf(cons)) {
|
|
12803
12915
|
if (walk(target)) return true;
|
|
12804
12916
|
}
|
|
12805
|
-
|
|
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 = (
|
|
14856
|
-
if (fileIntercept[
|
|
14857
|
-
return fileIntercept[
|
|
14967
|
+
readFile2 = (path21, options) => {
|
|
14968
|
+
if (fileIntercept[path21] !== void 0) {
|
|
14969
|
+
return fileIntercept[path21];
|
|
14858
14970
|
}
|
|
14859
|
-
if (!filePromises[
|
|
14860
|
-
filePromises[
|
|
14971
|
+
if (!filePromises[path21] || options?.ignoreCache) {
|
|
14972
|
+
filePromises[path21] = (0, import_promises3.readFile)(path21, "utf8");
|
|
14861
14973
|
}
|
|
14862
|
-
return filePromises[
|
|
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(
|
|
14975
|
-
fileIntercept[
|
|
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
|
|
17869
|
+
var format3, NumericValue;
|
|
17758
17870
|
var init_NumericValue = __esm({
|
|
17759
17871
|
"../../node_modules/@smithy/core/dist-es/submodules/serde/value/NumericValue.js"() {
|
|
17760
|
-
|
|
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 (!
|
|
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" &&
|
|
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:
|
|
18056
|
-
return `${protocol}//${hostname}${port ? ":" + port : ""}${
|
|
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 = (
|
|
18432
|
-
const parts =
|
|
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: '${
|
|
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: '${
|
|
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,
|
|
18575
|
+
getAttr = (value, path21) => getAttrPathList(path21).reduce((acc, index) => {
|
|
18464
18576
|
if (typeof acc !== "object") {
|
|
18465
|
-
throw new EndpointError(`Index '${index}' in '${
|
|
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:
|
|
18527
|
-
const url = new URL(`${protocol2}//${hostname2}${port ? `:${port}` : ""}${
|
|
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 [
|
|
20983
|
+
const [path21, search] = opTraits.http[1].split("?");
|
|
20872
20984
|
if (request.path == "/") {
|
|
20873
|
-
request.path =
|
|
20985
|
+
request.path = path21;
|
|
20874
20986
|
} else {
|
|
20875
|
-
request.path +=
|
|
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
|
|
21245
|
-
switch (
|
|
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
|
|
21368
|
-
switch (
|
|
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
|
|
24700
|
+
let path21 = request.path;
|
|
24589
24701
|
if (queryString) {
|
|
24590
|
-
|
|
24702
|
+
path21 += `?${queryString}`;
|
|
24591
24703
|
}
|
|
24592
24704
|
if (request.fragment) {
|
|
24593
|
-
|
|
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:
|
|
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:
|
|
25626
|
+
getCanonicalPath({ path: path21 }) {
|
|
25515
25627
|
if (this.uriEscapePath) {
|
|
25516
25628
|
const normalizedPathSegments = [];
|
|
25517
|
-
for (const pathSegment of
|
|
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 = `${
|
|
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
|
|
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
|
|
26603
|
-
switch (
|
|
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
|
|
26828
|
-
switch (
|
|
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
|
|
27457
|
-
switch (
|
|
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
|
|
41977
|
-
|
|
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
|
|
41994
|
-
|
|
41995
|
-
if (index >=
|
|
41996
|
-
lines
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
42160
|
-
|
|
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
|
-
|
|
42175
|
-
|
|
42176
|
-
|
|
42177
|
-
|
|
42178
|
-
|
|
42179
|
-
|
|
42180
|
-
|
|
42181
|
-
|
|
42182
|
-
|
|
42183
|
-
|
|
42184
|
-
|
|
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
|
|
42265
|
-
|
|
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 +=
|
|
42448
|
+
records += written;
|
|
42269
42449
|
} else {
|
|
42270
42450
|
skipped++;
|
|
42271
|
-
Logger_default.log(`Delta Share ready:
|
|
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 = (
|
|
42806
|
-
const cleanPath =
|
|
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
|
|
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
|
-
|
|
43062
|
+
import_stream2 = require("stream");
|
|
42832
43063
|
import_readline = require("readline");
|
|
42833
|
-
|
|
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
|
|
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,
|
|
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
|
|
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
|
|
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
|
-
|
|
43193
|
+
rl8.close();
|
|
42963
43194
|
fileStream.close();
|
|
42964
43195
|
return lines;
|
|
42965
43196
|
},
|
|
42966
43197
|
quickReadStream: async (stream, lineCount) => {
|
|
42967
|
-
const
|
|
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
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
|
43276
|
-
await
|
|
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,
|
|
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
|
-
|
|
43319
|
-
|
|
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
|
|
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,
|
|
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,
|
|
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 (
|
|
43944
|
-
dateValue = this.parseDate(value,
|
|
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 "${
|
|
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,
|
|
44254
|
+
formatDate(value, format4) {
|
|
43980
44255
|
const date2 = import_dayjs.default.utc(value);
|
|
43981
|
-
if (!DAY_OF_YEAR_TOKEN.test(this._stripLiterals(
|
|
43982
|
-
return date2.format(
|
|
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(
|
|
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,
|
|
43995
|
-
if (DAY_OF_YEAR_TOKEN.test(this._stripLiterals(
|
|
43996
|
-
return this._parseDayOfYear(value,
|
|
43997
|
-
this._assertParsableFormat(
|
|
43998
|
-
const parsed = import_dayjs.default.utc(value,
|
|
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 "${
|
|
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,
|
|
44284
|
+
_parseDayOfYear(value, format4) {
|
|
44010
44285
|
const parts = {};
|
|
44011
44286
|
let cursor = 0;
|
|
44012
44287
|
let index = 0;
|
|
44013
|
-
while (index <
|
|
44014
|
-
if (
|
|
44015
|
-
const close =
|
|
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 "${
|
|
44018
|
-
const literal2 =
|
|
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 "${
|
|
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) =>
|
|
44300
|
+
const match = DATE_PARSE_TOKENS.find((x2) => format4.startsWith(x2.token, index));
|
|
44026
44301
|
if (!match) {
|
|
44027
|
-
if (/[A-Za-z]/.test(
|
|
44028
|
-
throw new Error(`Date format "${
|
|
44029
|
-
if (value[cursor] !==
|
|
44030
|
-
throw new Error(`Cannot parse "${value}" with input format "${
|
|
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 "${
|
|
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 "${
|
|
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 "${
|
|
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 "${
|
|
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 "${
|
|
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(
|
|
44057
|
-
const stripped = this._stripLiterals(
|
|
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 "${
|
|
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(
|
|
44063
|
-
return String(
|
|
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
|
|
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,
|
|
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
|
-
|
|
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
|
|
44485
|
-
await
|
|
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
|
-
|
|
46818
|
-
`Key "${norm}" has a synth range of ${first}-${
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
47118
|
-
const { size } = await
|
|
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,
|
|
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
|
|
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(
|
|
48450
|
+
onPath.delete(path21.pop());
|
|
48166
48451
|
continue;
|
|
48167
48452
|
}
|
|
48168
48453
|
if (onPath.has(frame.name)) {
|
|
48169
|
-
|
|
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
|
-
|
|
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 = (
|
|
48852
|
-
return
|
|
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 =
|
|
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
|
|
49646
|
-
if (!
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
50102
|
-
*
|
|
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
|
-
|
|
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
|
|
50733
|
+
var import_crypto5, DELIMITER, idFor, LookupKey, LookupKey_default;
|
|
50447
50734
|
var init_LookupKey = __esm({
|
|
50448
50735
|
"../../packages/engines/src/transform/LookupKey.ts"() {
|
|
50449
|
-
|
|
50736
|
+
import_crypto5 = __toESM(require("crypto"), 1);
|
|
50450
50737
|
DELIMITER = String.fromCharCode(0);
|
|
50451
|
-
idFor = (ref) =>
|
|
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:
|
|
50479
|
-
const casted = TypeCaster_default.cast(value, cast,
|
|
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,
|
|
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
|
-
|
|
51265
|
-
|
|
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
|
|
51452
|
-
await
|
|
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
|
|
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 =
|
|
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
|
|
51525
|
-
await
|
|
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
|
|
51570
|
-
await
|
|
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
|
|
51677
|
-
await
|
|
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,
|
|
51681
|
-
return
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
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,
|
|
52256
|
-
if (
|
|
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,
|
|
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
|
-
|
|
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
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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,
|
|
53298
|
+
await (0, import_promises18.pipeline)(
|
|
53026
53299
|
xlsCsvStream,
|
|
53027
53300
|
import_fs17.default.createWriteStream(decodedPath)
|
|
53028
53301
|
);
|
|
53029
|
-
const fileStats = await
|
|
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
|
|
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
|
|
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
|
|
53329
|
+
await import_promises17.default.writeFile(decodedPath, lines.join("\n"), "utf-8");
|
|
53057
53330
|
}
|
|
53058
|
-
const fileStats = await
|
|
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,
|
|
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
|
|
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
|
|
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
|
|
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:
|