@forzalabs/remora 2.5.0 → 2.6.1
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/LICENCE.md +52 -17
- package/README.md +11 -1
- package/RELEASE_NOTES.md +157 -0
- package/docs/Remora - Code Sets.md +1 -1
- package/docs/Remora - Consumers.md +19 -11
- package/index.js +43 -19
- package/json_schemas/consumer-schema.json +1 -1
- package/package.json +2 -2
- package/workers/ExecutorWorker.js +43 -19
- package/CHANGELOG.md +0 -537
|
@@ -11809,7 +11809,7 @@ var CONSTANTS, Constants_default;
|
|
|
11809
11809
|
var init_Constants = __esm({
|
|
11810
11810
|
"../../packages/constants/src/Constants.ts"() {
|
|
11811
11811
|
CONSTANTS = {
|
|
11812
|
-
cliVersion: "2.
|
|
11812
|
+
cliVersion: "2.6.1",
|
|
11813
11813
|
backendVersion: 1,
|
|
11814
11814
|
backendPort: 5088,
|
|
11815
11815
|
workerVersion: 2,
|
|
@@ -11937,7 +11937,7 @@ var init_Constants = __esm({
|
|
|
11937
11937
|
/**
|
|
11938
11938
|
* Record layouts one FIXED output may write into a single file, which is also how many write
|
|
11939
11939
|
* streams its block-ordering pass holds open. A copybook of this size is already unusual —
|
|
11940
|
-
*
|
|
11940
|
+
* a POD-style transaction feed may write five transaction types — and the bound stops a generated config
|
|
11941
11941
|
* from opening a descriptor per distinct value of the wrong field.
|
|
11942
11942
|
*/
|
|
11943
11943
|
MAX_FIXED_LAYOUTS: 64,
|
|
@@ -33745,21 +33745,29 @@ var init_CSVParser = __esm({
|
|
|
33745
33745
|
});
|
|
33746
33746
|
|
|
33747
33747
|
// ../../packages/parsing/src/DatasetCodec.ts
|
|
33748
|
-
var NULL_FIELD, NEEDS_ESCAPE, DatasetCodecClass, DatasetCodec, DatasetCodec_default;
|
|
33748
|
+
var NULL_FIELD, EMPTY_FIELD, NEEDS_ESCAPE, QUOTE_CODE, QUOTE_TESTS, DatasetCodecClass, DatasetCodec, DatasetCodec_default;
|
|
33749
33749
|
var init_DatasetCodec = __esm({
|
|
33750
33750
|
"../../packages/parsing/src/DatasetCodec.ts"() {
|
|
33751
33751
|
init_src();
|
|
33752
33752
|
NULL_FIELD = "";
|
|
33753
|
+
EMPTY_FIELD = '""';
|
|
33753
33754
|
NEEDS_ESCAPE = /["\n\r]/;
|
|
33755
|
+
QUOTE_CODE = 34;
|
|
33756
|
+
QUOTE_TESTS = /* @__PURE__ */ new Map([[",", /^\s|\s$|[",\n\r]/]]);
|
|
33754
33757
|
DatasetCodecClass = class {
|
|
33755
33758
|
constructor() {
|
|
33756
33759
|
/**
|
|
33757
|
-
* One value as an internal positional field
|
|
33758
|
-
*
|
|
33760
|
+
* One value as an internal positional field. Bare where it can be, quoted where it must be -
|
|
33761
|
+
* around the delimiter, a quote, a line break or an edge space - or the unquoted null marker
|
|
33762
|
+
* when there is no value. The delimiter is a parameter rather than a comma because `redelimit`
|
|
33763
|
+
* re-encodes a staged line with the export's own: a tab is safe bare in the staged file and is
|
|
33764
|
+
* not once that file is re-emitted tab-delimited.
|
|
33759
33765
|
*/
|
|
33760
|
-
this.encodeField = (value) => {
|
|
33766
|
+
this.encodeField = (value, delimiter = ",") => {
|
|
33761
33767
|
if (value === null || value === void 0) return NULL_FIELD;
|
|
33762
33768
|
const text = typeof value === "string" ? value : String(value);
|
|
33769
|
+
if (text === "") return EMPTY_FIELD;
|
|
33770
|
+
if (!this._quoteTest(delimiter).test(text)) return text;
|
|
33763
33771
|
if (!NEEDS_ESCAPE.test(text)) return `"${text}"`;
|
|
33764
33772
|
return `"${text.replaceAll('"', '""').replaceAll("\r", "\\r").replaceAll("\n", "\\n")}"`;
|
|
33765
33773
|
};
|
|
@@ -33771,7 +33779,7 @@ var init_DatasetCodec = __esm({
|
|
|
33771
33779
|
for (let index = 0; index < values.length; index++) {
|
|
33772
33780
|
if (index > 0)
|
|
33773
33781
|
row += delimiter;
|
|
33774
|
-
row += this.encodeField(values[index]);
|
|
33782
|
+
row += this.encodeField(values[index], delimiter);
|
|
33775
33783
|
}
|
|
33776
33784
|
return row;
|
|
33777
33785
|
};
|
|
@@ -33791,26 +33799,26 @@ var init_DatasetCodec = __esm({
|
|
|
33791
33799
|
let index = 0;
|
|
33792
33800
|
while (index < length) {
|
|
33793
33801
|
const char = line.charCodeAt(index);
|
|
33794
|
-
if (char ===
|
|
33802
|
+
if (char === QUOTE_CODE) {
|
|
33795
33803
|
if (!inQuotes) {
|
|
33796
33804
|
inQuotes = true;
|
|
33797
33805
|
hasQuotes = true;
|
|
33798
33806
|
fieldStart = index + 1;
|
|
33799
|
-
} else if (line.charCodeAt(index + 1) ===
|
|
33807
|
+
} else if (line.charCodeAt(index + 1) === QUOTE_CODE) {
|
|
33800
33808
|
index++;
|
|
33801
33809
|
} else {
|
|
33802
33810
|
inQuotes = false;
|
|
33803
33811
|
fieldEnd = index;
|
|
33804
33812
|
}
|
|
33805
33813
|
} else if (char === delimiterCode && !inQuotes) {
|
|
33806
|
-
fields.push(this._field(line, fieldStart, fieldEnd, hasQuotes));
|
|
33814
|
+
fields.push(this._field(line, fieldStart, hasQuotes ? fieldEnd : index, hasQuotes));
|
|
33807
33815
|
fieldStart = index + 1;
|
|
33808
33816
|
fieldEnd = 0;
|
|
33809
33817
|
hasQuotes = false;
|
|
33810
33818
|
}
|
|
33811
33819
|
index++;
|
|
33812
33820
|
}
|
|
33813
|
-
fields.push(this._field(line, fieldStart, fieldEnd, hasQuotes));
|
|
33821
|
+
fields.push(this._field(line, fieldStart, hasQuotes ? fieldEnd : length, hasQuotes));
|
|
33814
33822
|
return fields;
|
|
33815
33823
|
};
|
|
33816
33824
|
/**
|
|
@@ -33821,9 +33829,24 @@ var init_DatasetCodec = __esm({
|
|
|
33821
33829
|
Affirm_default(delimiter, "Invalid delimiter");
|
|
33822
33830
|
return this.encodeRow(this.decodeRow(line), delimiter);
|
|
33823
33831
|
};
|
|
33824
|
-
/**
|
|
33832
|
+
/**
|
|
33833
|
+
* The quoting test for one delimiter, built on first use. The four characters escaped into the
|
|
33834
|
+
* class are the ones a character class reads as syntax; anything else stands for itself there.
|
|
33835
|
+
*/
|
|
33836
|
+
this._quoteTest = (delimiter) => {
|
|
33837
|
+
let test = QUOTE_TESTS.get(delimiter);
|
|
33838
|
+
if (!test) {
|
|
33839
|
+
test = new RegExp(`^\\s|\\s$|["\\n\\r${delimiter.replace(/[\\\]^-]/g, "\\$&")}]`);
|
|
33840
|
+
QUOTE_TESTS.set(delimiter, test);
|
|
33841
|
+
}
|
|
33842
|
+
return test;
|
|
33843
|
+
};
|
|
33844
|
+
/**
|
|
33845
|
+
* One field's text, or null for the unquoted empty marker. A bare token carries its value as it
|
|
33846
|
+
* stands - nothing bare can hold a quote, so there is nothing to unescape in it.
|
|
33847
|
+
*/
|
|
33825
33848
|
this._field = (line, start, end, hasQuotes) => {
|
|
33826
|
-
if (!hasQuotes) return null;
|
|
33849
|
+
if (!hasQuotes) return start === end ? null : line.slice(start, end);
|
|
33827
33850
|
const raw = line.slice(start, end);
|
|
33828
33851
|
return raw.indexOf('"') === -1 ? raw : raw.replaceAll('""', '"');
|
|
33829
33852
|
};
|
|
@@ -34275,7 +34298,7 @@ var init_FixedWidthWriter = __esm({
|
|
|
34275
34298
|
* `lf` output needs nothing here and a `crlf` one needs the `\r` that turns that newline into a
|
|
34276
34299
|
* CRLF — which is exactly what a CRLF file looks like to anything that splits on `\n`.
|
|
34277
34300
|
*
|
|
34278
|
-
* A real positional feed picks one terminator and holds it:
|
|
34301
|
+
* A real positional feed picks one terminator and holds it: some are CRLF on
|
|
34279
34302
|
* every line including the last, and `lf` is the default everywhere else.
|
|
34280
34303
|
*/
|
|
34281
34304
|
this.lineSuffix = (output) => {
|
|
@@ -56687,7 +56710,7 @@ var init_OutputExecutor = __esm({
|
|
|
56687
56710
|
for (let index = 0; index < visibleKeys.length; index++) {
|
|
56688
56711
|
if (index > 0)
|
|
56689
56712
|
row += delimiter;
|
|
56690
|
-
row += DatasetCodec_default.encodeField(record[visibleKeys[index]]);
|
|
56713
|
+
row += DatasetCodec_default.encodeField(record[visibleKeys[index]], delimiter);
|
|
56691
56714
|
}
|
|
56692
56715
|
return row;
|
|
56693
56716
|
};
|
|
@@ -56872,9 +56895,10 @@ var init_OutputExecutor = __esm({
|
|
|
56872
56895
|
return resultList[0];
|
|
56873
56896
|
};
|
|
56874
56897
|
/**
|
|
56875
|
-
* The header line of a positional export: the visible field names, in column order,
|
|
56876
|
-
*
|
|
56877
|
-
* does. Null for a JSON/API output, where a
|
|
56898
|
+
* The header line of a positional export: the visible field names, in column order, written
|
|
56899
|
+
* through the SAME codec as the rows under them — so a name is quoted on the same rule a value
|
|
56900
|
+
* is, and the header parses with the reader the data does. Null for a JSON/API output, where a
|
|
56901
|
+
* record already carries its own field names, for a
|
|
56878
56902
|
* FIXED one, where a name does not fit the column it describes and the receiver reads by
|
|
56879
56903
|
* position anyway, and for an output that turns the header off.
|
|
56880
56904
|
*
|
|
@@ -56883,7 +56907,7 @@ var init_OutputExecutor = __esm({
|
|
|
56883
56907
|
this._composeHeader = (output, dsSchema) => {
|
|
56884
56908
|
if (output.header === false) return null;
|
|
56885
56909
|
if (output.format !== "CSV" && output.format !== "TXT") return null;
|
|
56886
|
-
return
|
|
56910
|
+
return DatasetCodec_default.encodeRow(DatasetSchema_default.names(dsSchema), this._getDelimiter(output));
|
|
56887
56911
|
};
|
|
56888
56912
|
/** The delimiter the exported file is written with. Only TXT configures it; CSV is a comma. */
|
|
56889
56913
|
this._getDelimiter = (output) => {
|