@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.
@@ -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.5.0",
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
- * the NASCO POD feed writes five transaction types — and the bound stops a generated config
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: quoted, with `"`, `\n` and `\r` escaped - or the
33758
- * unquoted null marker when there is no value.
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 === 34) {
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) === 34) {
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
- /** One field's text, or null for the unquoted marker. Only a quoted token carries a value. */
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: the NASCO POD files are CRLF on
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, quoted and
56876
- * delimited exactly as the rows under them — so the header parses with the same reader the data
56877
- * does. Null for a JSON/API output, where a record already carries its own field names, for 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 CSVParser_default.stringifyRow(DatasetSchema_default.names(dsSchema), this._getDelimiter(output));
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) => {