@web-ts-toolkit/json-frame 0.43.0 → 0.48.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/README.md +117 -6
- package/index.d.mts +130 -12
- package/index.d.ts +130 -12
- package/index.js +500 -201
- package/index.mjs +500 -201
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -41,7 +41,8 @@ __export(index_exports, {
|
|
|
41
41
|
module.exports = __toCommonJS(index_exports);
|
|
42
42
|
|
|
43
43
|
// src/errors.ts
|
|
44
|
-
var
|
|
44
|
+
var JSON_FRAME_DIAGNOSTIC_KEY_LIMIT = 5;
|
|
45
|
+
var JSON_FRAME_DIAGNOSTIC_KEY_TEXT_BUDGET = 200;
|
|
45
46
|
var freezeCopy = (values) => Object.freeze([...values]);
|
|
46
47
|
var summarizeDiagnosticValue = (value) => {
|
|
47
48
|
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
@@ -52,11 +53,27 @@ var summarizeDiagnosticValue = (value) => {
|
|
|
52
53
|
}
|
|
53
54
|
if (typeof value === "object") {
|
|
54
55
|
const keys = Object.keys(value);
|
|
56
|
+
const head = keys.slice(0, JSON_FRAME_DIAGNOSTIC_KEY_LIMIT);
|
|
57
|
+
const preview = [];
|
|
58
|
+
let remaining = JSON_FRAME_DIAGNOSTIC_KEY_TEXT_BUDGET;
|
|
59
|
+
let textTruncated = false;
|
|
60
|
+
for (const key of head) {
|
|
61
|
+
if (key.length <= remaining) {
|
|
62
|
+
preview.push(key);
|
|
63
|
+
remaining -= key.length;
|
|
64
|
+
} else {
|
|
65
|
+
if (remaining > 0) {
|
|
66
|
+
preview.push(key.slice(0, remaining));
|
|
67
|
+
}
|
|
68
|
+
textTruncated = true;
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
55
72
|
return Object.freeze({
|
|
56
73
|
kind: "object",
|
|
57
74
|
keyCount: keys.length,
|
|
58
|
-
keys: freezeCopy(
|
|
59
|
-
truncated: keys.length >
|
|
75
|
+
keys: freezeCopy(preview),
|
|
76
|
+
truncated: keys.length > JSON_FRAME_DIAGNOSTIC_KEY_LIMIT || textTruncated
|
|
60
77
|
});
|
|
61
78
|
}
|
|
62
79
|
if (typeof value === "undefined") {
|
|
@@ -139,6 +156,7 @@ var INT32_MAX = 2147483647;
|
|
|
139
156
|
var freezeArray = (values) => Object.freeze([...values]);
|
|
140
157
|
var freezeColumnInfo = (info) => Object.freeze({ ...info });
|
|
141
158
|
var DATETIME_PATTERN = /^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})(?:[T ](?<hour>\d{2}):(?<minute>\d{2}):(?<second>\d{2})(?:\.(?<fraction>\d{1,9}))?)?$/;
|
|
159
|
+
var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
142
160
|
var columnOperationCounters = {
|
|
143
161
|
materializeColumnCalls: 0,
|
|
144
162
|
materializedCells: 0,
|
|
@@ -232,8 +250,9 @@ var isPandasNaiveIsoDatetime = (value) => {
|
|
|
232
250
|
if (month < 1 || month > 12 || hour > 23 || minute > 59 || second > 59) {
|
|
233
251
|
return false;
|
|
234
252
|
}
|
|
235
|
-
const
|
|
236
|
-
|
|
253
|
+
const leapYear = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
254
|
+
const daysInMonth = month === 2 && leapYear ? 29 : DAYS_IN_MONTH[month - 1];
|
|
255
|
+
return day >= 1 && day <= daysInMonth;
|
|
237
256
|
};
|
|
238
257
|
var isScalarCategory = (value) => typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
239
258
|
var isJsonContainer = (value) => {
|
|
@@ -312,6 +331,28 @@ var validateColumnValuesForType = ({
|
|
|
312
331
|
});
|
|
313
332
|
}
|
|
314
333
|
};
|
|
334
|
+
var validateStoredColumnValuesForType = ({
|
|
335
|
+
column,
|
|
336
|
+
columnIndex,
|
|
337
|
+
stored,
|
|
338
|
+
type,
|
|
339
|
+
orient,
|
|
340
|
+
index
|
|
341
|
+
}) => {
|
|
342
|
+
for (let rowIndex = 0; rowIndex < stored.length; rowIndex += 1) {
|
|
343
|
+
const value = stored[rowIndex];
|
|
344
|
+
if (isColumnValueCompatible(type, value)) {
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
347
|
+
throw new JsonFrameValidationError("Column cells are incompatible with the declared logical type.", {
|
|
348
|
+
...orient === void 0 ? {} : { orient },
|
|
349
|
+
path: getColumnCellPath(orient, column, columnIndex, rowIndex, index?.[rowIndex]),
|
|
350
|
+
row: rowIndex,
|
|
351
|
+
column,
|
|
352
|
+
value
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
};
|
|
315
356
|
var packColumn = (values, info, packThreshold) => {
|
|
316
357
|
if (packThreshold === 0 || values.length < packThreshold || info.nullable) {
|
|
317
358
|
return freezeArray(values);
|
|
@@ -323,6 +364,9 @@ var packColumn = (values, info, packThreshold) => {
|
|
|
323
364
|
if (typeof value !== "number" || !Number.isInteger(value) || value < INT32_MIN || value > INT32_MAX) {
|
|
324
365
|
return freezeArray(values);
|
|
325
366
|
}
|
|
367
|
+
if (Object.is(value, -0)) {
|
|
368
|
+
return freezeArray(values);
|
|
369
|
+
}
|
|
326
370
|
packed[index] = value;
|
|
327
371
|
}
|
|
328
372
|
return packed;
|
|
@@ -369,18 +413,14 @@ var resolveSchemaTypeByColumn = (frame) => {
|
|
|
369
413
|
return /* @__PURE__ */ new Map();
|
|
370
414
|
}
|
|
371
415
|
const schemaTypes = /* @__PURE__ */ new Map();
|
|
416
|
+
const columnNames = new Set(frame.columns);
|
|
372
417
|
for (const field of frame.tableSchema.fields) {
|
|
373
|
-
if (
|
|
418
|
+
if (columnNames.has(field.name)) {
|
|
374
419
|
schemaTypes.set(field.name, mapTableSchemaFieldType(field));
|
|
375
420
|
}
|
|
376
421
|
}
|
|
377
422
|
return schemaTypes;
|
|
378
423
|
};
|
|
379
|
-
var materializeColumn = (column) => {
|
|
380
|
-
columnOperationCounters.materializeColumnCalls += 1;
|
|
381
|
-
columnOperationCounters.materializedCells += column.length;
|
|
382
|
-
return Array.isArray(column) ? freezeArray(column) : freezeArray(Array.from(column));
|
|
383
|
-
};
|
|
384
424
|
var getStoredColumnValue = (column, position) => {
|
|
385
425
|
columnOperationCounters.scalarReads += 1;
|
|
386
426
|
return column[position];
|
|
@@ -393,20 +433,6 @@ var rebuildStoredColumn = (column, positions) => {
|
|
|
393
433
|
columnOperationCounters.rebuiltCells += positions.length;
|
|
394
434
|
return rebuilt;
|
|
395
435
|
};
|
|
396
|
-
var materializeFrameData = (columns, data) => {
|
|
397
|
-
const materialized = /* @__PURE__ */ new Map();
|
|
398
|
-
for (const column of columns) {
|
|
399
|
-
const stored = data.get(column);
|
|
400
|
-
if (stored === void 0) {
|
|
401
|
-
throw new JsonFrameValidationError("Stored frame data is missing a declared column.", {
|
|
402
|
-
path: "$",
|
|
403
|
-
column
|
|
404
|
-
});
|
|
405
|
-
}
|
|
406
|
-
materialized.set(column, materializeColumn(stored));
|
|
407
|
-
}
|
|
408
|
-
return materialized;
|
|
409
|
-
};
|
|
410
436
|
var buildFrameState = (frame, options) => {
|
|
411
437
|
validateExplicitColumnTypes(frame.columns, options.columnTypes);
|
|
412
438
|
const schemaTypes = resolveSchemaTypeByColumn(frame);
|
|
@@ -422,8 +448,9 @@ var buildFrameState = (frame, options) => {
|
|
|
422
448
|
});
|
|
423
449
|
}
|
|
424
450
|
const inferred = inferColumnType(values);
|
|
425
|
-
const
|
|
426
|
-
|
|
451
|
+
const explicitType = options.columnTypes !== void 0 && Object.prototype.hasOwnProperty.call(options.columnTypes, column) ? options.columnTypes[column] : void 0;
|
|
452
|
+
const resolvedType = schemaTypes.get(column) ?? explicitType ?? inferred.type;
|
|
453
|
+
if (schemaTypes.has(column) === false && explicitType !== void 0) {
|
|
427
454
|
validateColumnValuesForType({
|
|
428
455
|
column,
|
|
429
456
|
columnIndex,
|
|
@@ -522,6 +549,16 @@ var throwValidation = (message, path, value, orient) => {
|
|
|
522
549
|
value
|
|
523
550
|
});
|
|
524
551
|
};
|
|
552
|
+
var createNodeBudget = (maxNodes, orient) => {
|
|
553
|
+
let remaining = maxNodes;
|
|
554
|
+
return (value, path) => {
|
|
555
|
+
if (remaining === void 0) return;
|
|
556
|
+
if (remaining === 0) {
|
|
557
|
+
throwValidation(`JSON traversal exceeds maxNodes budget of ${maxNodes}.`, path, value, orient);
|
|
558
|
+
}
|
|
559
|
+
remaining -= 1;
|
|
560
|
+
};
|
|
561
|
+
};
|
|
525
562
|
var cloneScalar = (value, path, orient) => {
|
|
526
563
|
if (value === null || typeof value === "string" || typeof value === "boolean") {
|
|
527
564
|
return value;
|
|
@@ -537,7 +574,8 @@ var cloneScalar = (value, path, orient) => {
|
|
|
537
574
|
}
|
|
538
575
|
return void 0;
|
|
539
576
|
};
|
|
540
|
-
var createFrame = (source, path, depth, ancestors, orient) => {
|
|
577
|
+
var createFrame = (source, path, depth, ancestors, orient, charge) => {
|
|
578
|
+
charge(source, path);
|
|
541
579
|
const scalar = cloneScalar(source, path, orient);
|
|
542
580
|
if (scalar !== void 0) {
|
|
543
581
|
return { value: scalar };
|
|
@@ -572,9 +610,80 @@ var createFrame = (source, path, depth, ancestors, orient) => {
|
|
|
572
610
|
frame: { kind: "object", source: objectSource, target, keys: Object.keys(objectSource), path, depth, index: 0 }
|
|
573
611
|
};
|
|
574
612
|
};
|
|
575
|
-
var
|
|
613
|
+
var createValidateFrame = (source, path, depth, ancestors, orient, charge) => {
|
|
614
|
+
charge(source, path);
|
|
615
|
+
const scalar = cloneScalar(source, path, orient);
|
|
616
|
+
if (scalar !== void 0) {
|
|
617
|
+
return void 0;
|
|
618
|
+
}
|
|
619
|
+
if (depth > JSON_FRAME_MAX_DEPTH) {
|
|
620
|
+
throwValidation(
|
|
621
|
+
`JSON input exceeds the maximum supported nesting depth of ${JSON_FRAME_MAX_DEPTH}.`,
|
|
622
|
+
path,
|
|
623
|
+
source,
|
|
624
|
+
orient
|
|
625
|
+
);
|
|
626
|
+
}
|
|
627
|
+
if (Array.isArray(source)) {
|
|
628
|
+
if (ancestors.has(source)) {
|
|
629
|
+
throwValidation("Input contains a cyclic array.", path, source, orient);
|
|
630
|
+
}
|
|
631
|
+
ancestors.add(source);
|
|
632
|
+
return { kind: "array", source, path, depth, index: 0 };
|
|
633
|
+
}
|
|
634
|
+
if (!isPlainObject(source)) {
|
|
635
|
+
throwValidation("Input objects must be plain JSON objects or arrays.", path, source, orient);
|
|
636
|
+
}
|
|
637
|
+
const objectSource = source;
|
|
638
|
+
if (ancestors.has(objectSource)) {
|
|
639
|
+
throwValidation("Input contains a cyclic object.", path, objectSource, orient);
|
|
640
|
+
}
|
|
641
|
+
ancestors.add(objectSource);
|
|
642
|
+
return { kind: "object", source: objectSource, keys: Object.keys(objectSource), path, depth, index: 0 };
|
|
643
|
+
};
|
|
644
|
+
var assertJsonCompatible = (value, orient, path = "$", maxNodes) => {
|
|
576
645
|
const ancestors = /* @__PURE__ */ new Set();
|
|
577
|
-
const
|
|
646
|
+
const charge = createNodeBudget(maxNodes, orient);
|
|
647
|
+
const root = createValidateFrame(value, rootPath(path), 0, ancestors, orient, charge);
|
|
648
|
+
const stack = root === void 0 ? [] : [root];
|
|
649
|
+
while (stack.length > 0) {
|
|
650
|
+
const frame = stack[stack.length - 1];
|
|
651
|
+
if (frame.kind === "array") {
|
|
652
|
+
if (frame.index >= frame.source.length) {
|
|
653
|
+
ancestors.delete(frame.source);
|
|
654
|
+
stack.pop();
|
|
655
|
+
continue;
|
|
656
|
+
}
|
|
657
|
+
const index = frame.index;
|
|
658
|
+
frame.index += 1;
|
|
659
|
+
const childPath2 = childIndexPath(frame.path, index);
|
|
660
|
+
if (!(index in frame.source)) {
|
|
661
|
+
throwValidation("Sparse arrays are not valid JSON input.", childPath2, frame.source, orient);
|
|
662
|
+
}
|
|
663
|
+
const child2 = createValidateFrame(frame.source[index], childPath2, frame.depth + 1, ancestors, orient, charge);
|
|
664
|
+
if (child2 !== void 0) {
|
|
665
|
+
stack.push(child2);
|
|
666
|
+
}
|
|
667
|
+
continue;
|
|
668
|
+
}
|
|
669
|
+
if (frame.index >= frame.keys.length) {
|
|
670
|
+
ancestors.delete(frame.source);
|
|
671
|
+
stack.pop();
|
|
672
|
+
continue;
|
|
673
|
+
}
|
|
674
|
+
const key = frame.keys[frame.index];
|
|
675
|
+
frame.index += 1;
|
|
676
|
+
const childPath = childPropertyPath(frame.path, key);
|
|
677
|
+
const child = createValidateFrame(frame.source[key], childPath, frame.depth + 1, ancestors, orient, charge);
|
|
678
|
+
if (child !== void 0) {
|
|
679
|
+
stack.push(child);
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
};
|
|
683
|
+
var cloneJsonCompatible = (value, orient, path = "$", maxNodes) => {
|
|
684
|
+
const ancestors = /* @__PURE__ */ new Set();
|
|
685
|
+
const charge = createNodeBudget(maxNodes, orient);
|
|
686
|
+
const root = createFrame(value, rootPath(path), 0, ancestors, orient, charge);
|
|
578
687
|
const stack = root.frame === void 0 ? [] : [root.frame];
|
|
579
688
|
while (stack.length > 0) {
|
|
580
689
|
const frame = stack[stack.length - 1];
|
|
@@ -590,7 +699,7 @@ var cloneJsonCompatible = (value, orient, path = "$") => {
|
|
|
590
699
|
if (!(index in frame.source)) {
|
|
591
700
|
throwValidation("Sparse arrays are not valid JSON input.", childPath2, frame.source, orient);
|
|
592
701
|
}
|
|
593
|
-
const child2 = createFrame(frame.source[index], childPath2, frame.depth + 1, ancestors, orient);
|
|
702
|
+
const child2 = createFrame(frame.source[index], childPath2, frame.depth + 1, ancestors, orient, charge);
|
|
594
703
|
frame.target.push(child2.value);
|
|
595
704
|
if (child2.frame !== void 0) {
|
|
596
705
|
stack.push(child2.frame);
|
|
@@ -605,7 +714,7 @@ var cloneJsonCompatible = (value, orient, path = "$") => {
|
|
|
605
714
|
const key = frame.keys[frame.index];
|
|
606
715
|
frame.index += 1;
|
|
607
716
|
const childPath = childPropertyPath(frame.path, key);
|
|
608
|
-
const child = createFrame(frame.source[key], childPath, frame.depth + 1, ancestors, orient);
|
|
717
|
+
const child = createFrame(frame.source[key], childPath, frame.depth + 1, ancestors, orient, charge);
|
|
609
718
|
frame.target[key] = child.value;
|
|
610
719
|
if (child.frame !== void 0) {
|
|
611
720
|
stack.push(child.frame);
|
|
@@ -614,6 +723,142 @@ var cloneJsonCompatible = (value, orient, path = "$") => {
|
|
|
614
723
|
return root.value;
|
|
615
724
|
};
|
|
616
725
|
|
|
726
|
+
// src/options.ts
|
|
727
|
+
var RESOLVED_ORIENTS = [
|
|
728
|
+
"records",
|
|
729
|
+
"index",
|
|
730
|
+
"columns",
|
|
731
|
+
"values",
|
|
732
|
+
"split",
|
|
733
|
+
"table"
|
|
734
|
+
];
|
|
735
|
+
var ORIENTS = ["auto", ...RESOLVED_ORIENTS];
|
|
736
|
+
var COLUMN_TYPES = [
|
|
737
|
+
"integer",
|
|
738
|
+
"float",
|
|
739
|
+
"string",
|
|
740
|
+
"boolean",
|
|
741
|
+
"datetime",
|
|
742
|
+
"categorical",
|
|
743
|
+
"mixed",
|
|
744
|
+
"unknown"
|
|
745
|
+
];
|
|
746
|
+
var DEFAULT_PACK_THRESHOLD = 256;
|
|
747
|
+
var validateMaxNodes = (maxNodes) => {
|
|
748
|
+
if (maxNodes === void 0) return void 0;
|
|
749
|
+
if (typeof maxNodes !== "number" || !Number.isSafeInteger(maxNodes) || maxNodes <= 0) {
|
|
750
|
+
throw new JsonFrameOptionError("`options.maxNodes` must be a positive safe integer.", "maxNodes", maxNodes);
|
|
751
|
+
}
|
|
752
|
+
return maxNodes;
|
|
753
|
+
};
|
|
754
|
+
var normalizeToTableOptions = (options, method = "toTable") => {
|
|
755
|
+
if (options === void 0) return {};
|
|
756
|
+
if (Array.isArray(options) || typeof options !== "object" || options === null) {
|
|
757
|
+
throw new JsonFrameOptionError(`\`${method}\` options must be an object when provided.`, "options", options);
|
|
758
|
+
}
|
|
759
|
+
const indexField = options.indexField;
|
|
760
|
+
if (indexField !== void 0 && typeof indexField !== "string") {
|
|
761
|
+
throw new JsonFrameOptionError(
|
|
762
|
+
`\`${method}\` options.indexField must be a string when provided.`,
|
|
763
|
+
"indexField",
|
|
764
|
+
indexField
|
|
765
|
+
);
|
|
766
|
+
}
|
|
767
|
+
return indexField === void 0 ? {} : { indexField };
|
|
768
|
+
};
|
|
769
|
+
var normalizeToJSONStringOptions = (options) => {
|
|
770
|
+
const tableOptions = normalizeToTableOptions(options, "toJSONString");
|
|
771
|
+
const maxNodes = validateMaxNodes(options?.maxNodes);
|
|
772
|
+
return { ...tableOptions, ...maxNodes === void 0 ? {} : { maxNodes } };
|
|
773
|
+
};
|
|
774
|
+
var isOrient = (value) => typeof value === "string" && ORIENTS.includes(value);
|
|
775
|
+
var isColumnType = (value) => typeof value === "string" && COLUMN_TYPES.includes(value);
|
|
776
|
+
var normalizeFromOrientOptions = (options) => {
|
|
777
|
+
if (options == null) {
|
|
778
|
+
return {
|
|
779
|
+
orient: "auto",
|
|
780
|
+
packThreshold: DEFAULT_PACK_THRESHOLD
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
if (Array.isArray(options) || typeof options !== "object") {
|
|
784
|
+
throw new JsonFrameOptionError("`fromOrient` options must be an object when provided.", "options", options);
|
|
785
|
+
}
|
|
786
|
+
const orient = options.orient ?? "auto";
|
|
787
|
+
if (!isOrient(orient)) {
|
|
788
|
+
throw new JsonFrameOptionError(
|
|
789
|
+
"`options.orient` must be one of auto, records, index, columns, values, split, or table.",
|
|
790
|
+
"orient",
|
|
791
|
+
orient
|
|
792
|
+
);
|
|
793
|
+
}
|
|
794
|
+
const maxNodes = validateMaxNodes(options.maxNodes);
|
|
795
|
+
const packThreshold = options.packThreshold ?? DEFAULT_PACK_THRESHOLD;
|
|
796
|
+
if (!Number.isFinite(packThreshold) || !Number.isInteger(packThreshold) || packThreshold < 0) {
|
|
797
|
+
throw new JsonFrameOptionError(
|
|
798
|
+
"`options.packThreshold` must be a finite non-negative integer.",
|
|
799
|
+
"packThreshold",
|
|
800
|
+
packThreshold
|
|
801
|
+
);
|
|
802
|
+
}
|
|
803
|
+
let columns;
|
|
804
|
+
if (options.columns !== void 0) {
|
|
805
|
+
if (!Array.isArray(options.columns)) {
|
|
806
|
+
throw new JsonFrameOptionError("`options.columns` must be an array of strings.", "columns", options.columns);
|
|
807
|
+
}
|
|
808
|
+
const seen = /* @__PURE__ */ new Set();
|
|
809
|
+
const validated = [];
|
|
810
|
+
const source = options.columns;
|
|
811
|
+
for (let position = 0; position < source.length; position += 1) {
|
|
812
|
+
if (!Object.prototype.hasOwnProperty.call(source, position)) {
|
|
813
|
+
throw new JsonFrameOptionError(
|
|
814
|
+
"`options.columns` must not contain holes; every position must be a string label.",
|
|
815
|
+
"columns",
|
|
816
|
+
source
|
|
817
|
+
);
|
|
818
|
+
}
|
|
819
|
+
const column = source[position];
|
|
820
|
+
if (typeof column !== "string") {
|
|
821
|
+
throw new JsonFrameOptionError("`options.columns` must contain only strings.", "columns", column);
|
|
822
|
+
}
|
|
823
|
+
if (seen.has(column)) {
|
|
824
|
+
throw new JsonFrameOptionError("`options.columns` must not contain duplicates.", "columns", column);
|
|
825
|
+
}
|
|
826
|
+
seen.add(column);
|
|
827
|
+
validated.push(column);
|
|
828
|
+
}
|
|
829
|
+
columns = validated;
|
|
830
|
+
}
|
|
831
|
+
let columnTypes;
|
|
832
|
+
if (options.columnTypes !== void 0) {
|
|
833
|
+
if (Array.isArray(options.columnTypes) || typeof options.columnTypes !== "object" || options.columnTypes === null) {
|
|
834
|
+
throw new JsonFrameOptionError(
|
|
835
|
+
"`options.columnTypes` must be an object keyed by column name.",
|
|
836
|
+
"columnTypes",
|
|
837
|
+
options.columnTypes
|
|
838
|
+
);
|
|
839
|
+
}
|
|
840
|
+
const normalized = /* @__PURE__ */ Object.create(null);
|
|
841
|
+
for (const [column, type] of Object.entries(options.columnTypes)) {
|
|
842
|
+
if (!isColumnType(type)) {
|
|
843
|
+
throw new JsonFrameOptionError(
|
|
844
|
+
"`options.columnTypes` values must be valid JSON Frame logical column types.",
|
|
845
|
+
`columnTypes.${column}`,
|
|
846
|
+
type
|
|
847
|
+
);
|
|
848
|
+
}
|
|
849
|
+
normalized[column] = type;
|
|
850
|
+
}
|
|
851
|
+
columnTypes = Object.freeze(normalized);
|
|
852
|
+
}
|
|
853
|
+
return {
|
|
854
|
+
orient,
|
|
855
|
+
packThreshold,
|
|
856
|
+
...maxNodes === void 0 ? {} : { maxNodes },
|
|
857
|
+
...columns === void 0 ? {} : { columns: Object.freeze([...columns]) },
|
|
858
|
+
...columnTypes === void 0 ? {} : { columnTypes }
|
|
859
|
+
};
|
|
860
|
+
};
|
|
861
|
+
|
|
617
862
|
// src/export/payload.ts
|
|
618
863
|
var createRecord = () => /* @__PURE__ */ Object.create(null);
|
|
619
864
|
var appendPath = (path, key) => `${path}[${JSON.stringify(key)}]`;
|
|
@@ -705,30 +950,46 @@ var getIndexFieldTemplate = (state) => {
|
|
|
705
950
|
if (state.tableSchema === void 0 || state.tableIndexField === void 0) {
|
|
706
951
|
return void 0;
|
|
707
952
|
}
|
|
708
|
-
|
|
953
|
+
const fields = state.tableSchema.fields;
|
|
954
|
+
if (new Set(fields.map((field) => field.name)).size === fields.length) {
|
|
955
|
+
return fields.find((field) => field.name === state.tableIndexField);
|
|
956
|
+
}
|
|
957
|
+
if (fields.length === state.columns.length + 1 && fields[0].name === state.tableIndexField) {
|
|
958
|
+
return fields[0];
|
|
959
|
+
}
|
|
960
|
+
return fields.find((field) => field.name === state.tableIndexField);
|
|
709
961
|
};
|
|
710
962
|
var getDataFieldTemplates = (state) => {
|
|
711
963
|
if (state.tableSchema === void 0) {
|
|
712
964
|
return [];
|
|
713
965
|
}
|
|
714
|
-
const
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
if (options !== void 0 && (Array.isArray(options) || typeof options !== "object" || options === null)) {
|
|
719
|
-
throw new JsonFrameOptionError("`toTable` options must be an object when provided.", "options", options);
|
|
966
|
+
const fields = state.tableSchema.fields;
|
|
967
|
+
if (new Set(fields.map((field) => field.name)).size === fields.length) {
|
|
968
|
+
const fieldsByName = new Map(fields.map((field) => [field.name, field]));
|
|
969
|
+
return state.columns.map((column) => fieldsByName.get(column)).filter((field) => field !== void 0);
|
|
720
970
|
}
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
);
|
|
971
|
+
let dataSlice;
|
|
972
|
+
if (state.tableIndexField !== void 0 && fields.length === state.columns.length + 1 && fields[0].name === state.tableIndexField) {
|
|
973
|
+
dataSlice = fields.slice(1);
|
|
974
|
+
} else if (state.tableIndexField !== void 0) {
|
|
975
|
+
const indexPosition = fields.findIndex((field) => field.name === state.tableIndexField);
|
|
976
|
+
dataSlice = indexPosition === -1 ? fields : [...fields.slice(0, indexPosition), ...fields.slice(indexPosition + 1)];
|
|
977
|
+
} else {
|
|
978
|
+
dataSlice = fields;
|
|
727
979
|
}
|
|
980
|
+
const dataByName = new Map(dataSlice.map((field) => [field.name, field]));
|
|
981
|
+
const ordered = state.columns.map((column) => dataByName.get(column)).filter((field) => field !== void 0);
|
|
982
|
+
if (ordered.length === state.columns.length) {
|
|
983
|
+
return ordered;
|
|
984
|
+
}
|
|
985
|
+
return dataSlice.length === state.columns.length ? [...dataSlice] : ordered;
|
|
986
|
+
};
|
|
987
|
+
var resolveIndexFieldName = (state, options) => {
|
|
988
|
+
const normalized = normalizeToTableOptions(options);
|
|
728
989
|
if (state.indexKind === "synthetic") {
|
|
729
990
|
return void 0;
|
|
730
991
|
}
|
|
731
|
-
const indexField =
|
|
992
|
+
const indexField = normalized.indexField ?? state.tableIndexField ?? "index";
|
|
732
993
|
if (state.columns.includes(indexField)) {
|
|
733
994
|
throw new JsonFrameValidationError("Table export index field name must not collide with a data column.", {
|
|
734
995
|
path: "$.schema.fields",
|
|
@@ -773,55 +1034,73 @@ var resolveIndexKeys = (state, orient) => {
|
|
|
773
1034
|
}
|
|
774
1035
|
return keys;
|
|
775
1036
|
};
|
|
776
|
-
var
|
|
1037
|
+
var getStoredColumn = (state, column) => {
|
|
1038
|
+
const stored = state.data.get(column);
|
|
1039
|
+
if (stored === void 0) {
|
|
1040
|
+
throw new JsonFrameValidationError("Stored frame data is missing a declared column.", {
|
|
1041
|
+
path: "$",
|
|
1042
|
+
column
|
|
1043
|
+
});
|
|
1044
|
+
}
|
|
1045
|
+
return stored;
|
|
1046
|
+
};
|
|
1047
|
+
var resolveStoredColumns = (state) => state.columns.map((column) => getStoredColumn(state, column));
|
|
1048
|
+
var exportRecords = (state) => {
|
|
1049
|
+
const storedColumns = resolveStoredColumns(state);
|
|
777
1050
|
const rows = [];
|
|
778
1051
|
for (let rowIndex = 0; rowIndex < state.index.length; rowIndex += 1) {
|
|
779
1052
|
const row = createRecord();
|
|
780
|
-
for (
|
|
781
|
-
row[
|
|
1053
|
+
for (let columnIndex = 0; columnIndex < state.columns.length; columnIndex += 1) {
|
|
1054
|
+
row[state.columns[columnIndex]] = getStoredColumnValue(storedColumns[columnIndex], rowIndex);
|
|
782
1055
|
}
|
|
783
1056
|
rows.push(row);
|
|
784
1057
|
}
|
|
785
1058
|
return rows;
|
|
786
1059
|
};
|
|
787
|
-
var exportIndex = (state
|
|
1060
|
+
var exportIndex = (state) => {
|
|
788
1061
|
const keys = resolveIndexKeys(state, "index");
|
|
1062
|
+
const storedColumns = resolveStoredColumns(state);
|
|
789
1063
|
const rows = createRecord();
|
|
790
1064
|
for (let rowIndex = 0; rowIndex < state.index.length; rowIndex += 1) {
|
|
791
1065
|
const row = createRecord();
|
|
792
|
-
for (
|
|
793
|
-
row[
|
|
1066
|
+
for (let columnIndex = 0; columnIndex < state.columns.length; columnIndex += 1) {
|
|
1067
|
+
row[state.columns[columnIndex]] = getStoredColumnValue(storedColumns[columnIndex], rowIndex);
|
|
794
1068
|
}
|
|
795
1069
|
rows[keys[rowIndex]] = row;
|
|
796
1070
|
}
|
|
797
1071
|
return rows;
|
|
798
1072
|
};
|
|
799
|
-
var exportColumns = (state
|
|
1073
|
+
var exportColumns = (state) => {
|
|
800
1074
|
const keys = resolveIndexKeys(state, "columns");
|
|
801
1075
|
const columns = createRecord();
|
|
802
1076
|
for (const column of state.columns) {
|
|
1077
|
+
const stored = getStoredColumn(state, column);
|
|
803
1078
|
const values = createRecord();
|
|
804
|
-
const entries = materialized.get(column);
|
|
805
1079
|
for (let rowIndex = 0; rowIndex < state.index.length; rowIndex += 1) {
|
|
806
|
-
values[keys[rowIndex]] =
|
|
1080
|
+
values[keys[rowIndex]] = getStoredColumnValue(stored, rowIndex);
|
|
807
1081
|
}
|
|
808
1082
|
columns[column] = values;
|
|
809
1083
|
}
|
|
810
1084
|
return columns;
|
|
811
1085
|
};
|
|
812
|
-
var exportValues = (state
|
|
1086
|
+
var exportValues = (state) => {
|
|
1087
|
+
const storedColumns = resolveStoredColumns(state);
|
|
813
1088
|
const rows = [];
|
|
814
1089
|
for (let rowIndex = 0; rowIndex < state.index.length; rowIndex += 1) {
|
|
815
|
-
|
|
1090
|
+
const row = new Array(storedColumns.length);
|
|
1091
|
+
for (let columnIndex = 0; columnIndex < storedColumns.length; columnIndex += 1) {
|
|
1092
|
+
row[columnIndex] = getStoredColumnValue(storedColumns[columnIndex], rowIndex);
|
|
1093
|
+
}
|
|
1094
|
+
rows.push(row);
|
|
816
1095
|
}
|
|
817
1096
|
return rows;
|
|
818
1097
|
};
|
|
819
|
-
var exportSplit = (state
|
|
1098
|
+
var exportSplit = (state) => ({
|
|
820
1099
|
columns: [...state.columns],
|
|
821
1100
|
index: [...state.index],
|
|
822
|
-
data: exportValues(state
|
|
1101
|
+
data: exportValues(state)
|
|
823
1102
|
});
|
|
824
|
-
var exportTable = (state,
|
|
1103
|
+
var exportTable = (state, columnInfo, options) => {
|
|
825
1104
|
const indexField = resolveIndexFieldName(state, options);
|
|
826
1105
|
if (indexField !== void 0) {
|
|
827
1106
|
assertUniqueTableIndexLabels(state.index, indexField);
|
|
@@ -834,14 +1113,15 @@ var exportTable = (state, materialized, columnInfo, options) => {
|
|
|
834
1113
|
indexTemplate === void 0 ? { name: indexField, type: inferIndexFieldType(state.index) } : cloneSchemaField(indexTemplate, indexField, "$.schema.fields[0]")
|
|
835
1114
|
);
|
|
836
1115
|
}
|
|
1116
|
+
const storedColumns = resolveStoredColumns(state);
|
|
837
1117
|
for (let columnIndex = 0; columnIndex < state.columns.length; columnIndex += 1) {
|
|
838
1118
|
const column = state.columns[columnIndex];
|
|
839
1119
|
const template = dataTemplates[columnIndex];
|
|
840
1120
|
if (template === void 0) {
|
|
841
|
-
|
|
1121
|
+
validateStoredColumnValuesForType({
|
|
842
1122
|
column,
|
|
843
1123
|
columnIndex,
|
|
844
|
-
|
|
1124
|
+
stored: storedColumns[columnIndex],
|
|
845
1125
|
type: columnInfo.get(column).type,
|
|
846
1126
|
orient: "table",
|
|
847
1127
|
index: state.index
|
|
@@ -857,8 +1137,8 @@ var exportTable = (state, materialized, columnInfo, options) => {
|
|
|
857
1137
|
if (indexField !== void 0) {
|
|
858
1138
|
row[indexField] = state.index[rowIndex];
|
|
859
1139
|
}
|
|
860
|
-
for (
|
|
861
|
-
row[
|
|
1140
|
+
for (let columnIndex = 0; columnIndex < state.columns.length; columnIndex += 1) {
|
|
1141
|
+
row[state.columns[columnIndex]] = getStoredColumnValue(storedColumns[columnIndex], rowIndex);
|
|
862
1142
|
}
|
|
863
1143
|
data.push(row);
|
|
864
1144
|
}
|
|
@@ -887,7 +1167,57 @@ var cloneSchema2 = (schema, fields, primaryKey) => {
|
|
|
887
1167
|
}
|
|
888
1168
|
return Object.freeze(cloned);
|
|
889
1169
|
};
|
|
890
|
-
var
|
|
1170
|
+
var partitionSchemaFields = (state) => {
|
|
1171
|
+
const empty = {
|
|
1172
|
+
indexTemplate: void 0,
|
|
1173
|
+
dataByColumn: /* @__PURE__ */ new Map(),
|
|
1174
|
+
dataInColumnOrder: []
|
|
1175
|
+
};
|
|
1176
|
+
if (state.tableSchema === void 0) {
|
|
1177
|
+
return empty;
|
|
1178
|
+
}
|
|
1179
|
+
const fields = state.tableSchema.fields;
|
|
1180
|
+
if (state.tableIndexField === void 0) {
|
|
1181
|
+
const byName = new Map(fields.map((field) => [field.name, field]));
|
|
1182
|
+
const ordered2 = state.columns.map((column) => byName.get(column)).filter((field) => field !== void 0);
|
|
1183
|
+
return {
|
|
1184
|
+
indexTemplate: void 0,
|
|
1185
|
+
dataByColumn: new Map(ordered2.map((field, index) => [state.columns[index], field])),
|
|
1186
|
+
dataInColumnOrder: ordered2
|
|
1187
|
+
};
|
|
1188
|
+
}
|
|
1189
|
+
const names = fields.map((field) => field.name);
|
|
1190
|
+
const unique = new Set(names).size === names.length;
|
|
1191
|
+
if (unique) {
|
|
1192
|
+
const byName = new Map(fields.map((field) => [field.name, field]));
|
|
1193
|
+
const indexTemplate2 = byName.get(state.tableIndexField);
|
|
1194
|
+
const ordered2 = state.columns.map((column) => byName.get(column)).filter((field) => field !== void 0);
|
|
1195
|
+
return {
|
|
1196
|
+
indexTemplate: indexTemplate2,
|
|
1197
|
+
dataByColumn: new Map(ordered2.map((field, index) => [state.columns[index], field])),
|
|
1198
|
+
dataInColumnOrder: ordered2
|
|
1199
|
+
};
|
|
1200
|
+
}
|
|
1201
|
+
let indexTemplate;
|
|
1202
|
+
let dataSlice;
|
|
1203
|
+
if (fields.length === state.columns.length + 1 && fields[0].name === state.tableIndexField) {
|
|
1204
|
+
indexTemplate = fields[0];
|
|
1205
|
+
dataSlice = fields.slice(1);
|
|
1206
|
+
} else {
|
|
1207
|
+
const indexPosition = fields.findIndex((field) => field.name === state.tableIndexField);
|
|
1208
|
+
indexTemplate = indexPosition === -1 ? void 0 : fields[indexPosition];
|
|
1209
|
+
dataSlice = indexPosition === -1 ? fields : [...fields.slice(0, indexPosition), ...fields.slice(indexPosition + 1)];
|
|
1210
|
+
}
|
|
1211
|
+
const dataByName = new Map(dataSlice.map((field) => [field.name, field]));
|
|
1212
|
+
const ordered = state.columns.map((column) => dataByName.get(column)).filter((field) => field !== void 0);
|
|
1213
|
+
const dataInColumnOrder = ordered.length === state.columns.length ? ordered : dataSlice.length === state.columns.length ? [...dataSlice] : ordered;
|
|
1214
|
+
return {
|
|
1215
|
+
indexTemplate,
|
|
1216
|
+
dataByColumn: new Map(dataInColumnOrder.map((field, index) => [state.columns[index], field])),
|
|
1217
|
+
dataInColumnOrder
|
|
1218
|
+
};
|
|
1219
|
+
};
|
|
1220
|
+
var _state, _packThreshold, _DataFrame_instances, assertRowPosition_fn, createRow_fn, columnInfoOverrides_fn, rebuild_fn, selectSchema_fn, renameSchema_fn, resetIndexSchema_fn;
|
|
891
1221
|
var DataFrame = class {
|
|
892
1222
|
constructor(state, packThreshold) {
|
|
893
1223
|
__privateAdd(this, _DataFrame_instances);
|
|
@@ -910,42 +1240,82 @@ var DataFrame = class {
|
|
|
910
1240
|
return __privateGet(this, _state).index.length;
|
|
911
1241
|
}
|
|
912
1242
|
toRecords() {
|
|
913
|
-
return exportRecords(__privateGet(this, _state)
|
|
1243
|
+
return exportRecords(__privateGet(this, _state));
|
|
914
1244
|
}
|
|
915
1245
|
toIndex() {
|
|
916
|
-
return exportIndex(__privateGet(this, _state)
|
|
1246
|
+
return exportIndex(__privateGet(this, _state));
|
|
917
1247
|
}
|
|
918
1248
|
toColumns() {
|
|
919
|
-
return exportColumns(__privateGet(this, _state)
|
|
1249
|
+
return exportColumns(__privateGet(this, _state));
|
|
920
1250
|
}
|
|
921
1251
|
toValues() {
|
|
922
|
-
return exportValues(__privateGet(this, _state)
|
|
1252
|
+
return exportValues(__privateGet(this, _state));
|
|
923
1253
|
}
|
|
924
1254
|
toSplit() {
|
|
925
|
-
return exportSplit(__privateGet(this, _state)
|
|
1255
|
+
return exportSplit(__privateGet(this, _state));
|
|
926
1256
|
}
|
|
927
1257
|
toTable(options) {
|
|
928
|
-
return exportTable(__privateGet(this, _state),
|
|
929
|
-
}
|
|
1258
|
+
return exportTable(__privateGet(this, _state), __privateGet(this, _state).columnInfo, options);
|
|
1259
|
+
}
|
|
1260
|
+
/**
|
|
1261
|
+
* Serialize the selected orient after validating the complete exported
|
|
1262
|
+
* payload with the shared bounded traversal.
|
|
1263
|
+
*
|
|
1264
|
+
* Depth is measured from the exported payload root, including orient
|
|
1265
|
+
* wrappers (`split`/`table` nest cells one level deeper than
|
|
1266
|
+
* `records`/`values`/`index`/`columns`). A cell accepted at ingestion may be
|
|
1267
|
+
* rejected here when a deeper output layout pushes it past
|
|
1268
|
+
* `JSON_FRAME_MAX_DEPTH`. Cycles, over-depth containers, sparse arrays, and
|
|
1269
|
+
* non-JSON values introduced through caller-mutable nested cells fail with
|
|
1270
|
+
* path-bearing `JsonFrameValidationError` carrying the selected orient.
|
|
1271
|
+
*
|
|
1272
|
+
* Validation performs one full traversal without cloning, then native
|
|
1273
|
+
* serialization performs a second pass. Repeated references are visited per
|
|
1274
|
+
* occurrence (detached semantics), so both passes expand aliases exactly as
|
|
1275
|
+
* `JSON.stringify()` does. Optional maxNodes bounds validation occurrences
|
|
1276
|
+
* (root, wrappers, metadata and scalars included), independently per call;
|
|
1277
|
+
* no default quota or inherited ingestion budget applies. It does not bound
|
|
1278
|
+
* payload construction, key allocation, bytes, or native hooks. Validation
|
|
1279
|
+
* reads own enumerable properties and array elements, invoking
|
|
1280
|
+
* caller-installed getters/`Proxy` traps, and native serialization may
|
|
1281
|
+
* additionally invoke `toJSON` hooks. Hooks are caller responsibility; the
|
|
1282
|
+
* package does not sandbox arbitrary JavaScript.
|
|
1283
|
+
*/
|
|
930
1284
|
toJSONString(orient, options) {
|
|
1285
|
+
const normalized = normalizeToJSONStringOptions(options);
|
|
1286
|
+
let payload;
|
|
931
1287
|
switch (orient) {
|
|
932
|
-
case "records":
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
case "
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
case "
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
1288
|
+
case "records": {
|
|
1289
|
+
payload = this.toRecords();
|
|
1290
|
+
break;
|
|
1291
|
+
}
|
|
1292
|
+
case "index": {
|
|
1293
|
+
payload = this.toIndex();
|
|
1294
|
+
break;
|
|
1295
|
+
}
|
|
1296
|
+
case "columns": {
|
|
1297
|
+
payload = this.toColumns();
|
|
1298
|
+
break;
|
|
1299
|
+
}
|
|
1300
|
+
case "values": {
|
|
1301
|
+
payload = this.toValues();
|
|
1302
|
+
break;
|
|
1303
|
+
}
|
|
1304
|
+
case "split": {
|
|
1305
|
+
payload = this.toSplit();
|
|
1306
|
+
break;
|
|
1307
|
+
}
|
|
1308
|
+
case "table": {
|
|
1309
|
+
payload = this.toTable(normalized);
|
|
1310
|
+
break;
|
|
1311
|
+
}
|
|
944
1312
|
default: {
|
|
945
1313
|
const exhaustive = orient;
|
|
946
1314
|
throw new JsonFrameValidationError("Unsupported export orient.", { value: exhaustive });
|
|
947
1315
|
}
|
|
948
1316
|
}
|
|
1317
|
+
assertJsonCompatible(payload, orient, "$", normalized.maxNodes);
|
|
1318
|
+
return JSON.stringify(payload);
|
|
949
1319
|
}
|
|
950
1320
|
row(position) {
|
|
951
1321
|
__privateMethod(this, _DataFrame_instances, assertRowPosition_fn).call(this, position);
|
|
@@ -1070,7 +1440,7 @@ var DataFrame = class {
|
|
|
1070
1440
|
}
|
|
1071
1441
|
seen.add(column);
|
|
1072
1442
|
}
|
|
1073
|
-
const renamedSchema = __privateMethod(this, _DataFrame_instances, renameSchema_fn).call(this, mapping);
|
|
1443
|
+
const renamedSchema = __privateMethod(this, _DataFrame_instances, renameSchema_fn).call(this, mapping, nextColumns);
|
|
1074
1444
|
return __privateMethod(this, _DataFrame_instances, rebuild_fn).call(this, {
|
|
1075
1445
|
columns: nextColumns,
|
|
1076
1446
|
sourceColumns: __privateGet(this, _state).columns,
|
|
@@ -1100,9 +1470,6 @@ assertRowPosition_fn = function(position) {
|
|
|
1100
1470
|
throw new RangeError(`Row position must be an integer in [0, ${this.length}).`);
|
|
1101
1471
|
}
|
|
1102
1472
|
};
|
|
1103
|
-
materializedData_fn = function() {
|
|
1104
|
-
return materializeFrameData(__privateGet(this, _state).columns, __privateGet(this, _state).data);
|
|
1105
|
-
};
|
|
1106
1473
|
createRow_fn = function(position) {
|
|
1107
1474
|
const row = /* @__PURE__ */ Object.create(null);
|
|
1108
1475
|
for (const column of __privateGet(this, _state).columns) {
|
|
@@ -1174,16 +1541,13 @@ selectSchema_fn = function(columns) {
|
|
|
1174
1541
|
if (__privateGet(this, _state).tableSchema === void 0) {
|
|
1175
1542
|
return {};
|
|
1176
1543
|
}
|
|
1177
|
-
const
|
|
1544
|
+
const { indexTemplate, dataByColumn } = partitionSchemaFields(__privateGet(this, _state));
|
|
1178
1545
|
const fields = [];
|
|
1179
|
-
if (__privateGet(this, _state).tableIndexField !== void 0) {
|
|
1180
|
-
|
|
1181
|
-
if (indexField !== void 0) {
|
|
1182
|
-
fields.push(cloneField(indexField));
|
|
1183
|
-
}
|
|
1546
|
+
if (__privateGet(this, _state).tableIndexField !== void 0 && indexTemplate !== void 0) {
|
|
1547
|
+
fields.push(cloneField(indexTemplate));
|
|
1184
1548
|
}
|
|
1185
1549
|
for (const column of columns) {
|
|
1186
|
-
const field =
|
|
1550
|
+
const field = dataByColumn.get(column);
|
|
1187
1551
|
if (field !== void 0) {
|
|
1188
1552
|
fields.push(cloneField(field));
|
|
1189
1553
|
}
|
|
@@ -1193,15 +1557,36 @@ selectSchema_fn = function(columns) {
|
|
|
1193
1557
|
...__privateGet(this, _state).tableIndexField === void 0 ? {} : { tableIndexField: __privateGet(this, _state).tableIndexField }
|
|
1194
1558
|
};
|
|
1195
1559
|
};
|
|
1196
|
-
renameSchema_fn = function(mapping) {
|
|
1560
|
+
renameSchema_fn = function(mapping, nextColumns) {
|
|
1197
1561
|
if (__privateGet(this, _state).tableSchema === void 0) {
|
|
1198
1562
|
return {};
|
|
1199
1563
|
}
|
|
1200
|
-
const
|
|
1201
|
-
|
|
1202
|
-
|
|
1564
|
+
const names = __privateGet(this, _state).tableSchema.fields.map((field) => field.name);
|
|
1565
|
+
const collidesWithIndex = __privateGet(this, _state).tableIndexField !== void 0 && nextColumns.includes(__privateGet(this, _state).tableIndexField);
|
|
1566
|
+
if (new Set(names).size === names.length && !collidesWithIndex) {
|
|
1567
|
+
const columnNames = new Set(__privateGet(this, _state).columns);
|
|
1568
|
+
const fields2 = __privateGet(this, _state).tableSchema.fields.map((field) => {
|
|
1569
|
+
if (!columnNames.has(field.name)) {
|
|
1570
|
+
return cloneField(field);
|
|
1571
|
+
}
|
|
1572
|
+
return cloneField(field, hasOwn.call(mapping, field.name) ? mapping[field.name] : field.name);
|
|
1573
|
+
});
|
|
1574
|
+
return {
|
|
1575
|
+
tableSchema: cloneSchema2(__privateGet(this, _state).tableSchema, fields2, __privateGet(this, _state).tableSchema.primaryKey),
|
|
1576
|
+
...__privateGet(this, _state).tableIndexField === void 0 ? {} : { tableIndexField: __privateGet(this, _state).tableIndexField }
|
|
1577
|
+
};
|
|
1578
|
+
}
|
|
1579
|
+
const { indexTemplate, dataInColumnOrder } = partitionSchemaFields(__privateGet(this, _state));
|
|
1580
|
+
const fields = [];
|
|
1581
|
+
if (__privateGet(this, _state).tableIndexField !== void 0 && indexTemplate !== void 0) {
|
|
1582
|
+
fields.push(cloneField(indexTemplate));
|
|
1583
|
+
}
|
|
1584
|
+
__privateGet(this, _state).columns.forEach((column, position) => {
|
|
1585
|
+
const template = dataInColumnOrder[position];
|
|
1586
|
+
if (template === void 0) {
|
|
1587
|
+
return;
|
|
1203
1588
|
}
|
|
1204
|
-
|
|
1589
|
+
fields.push(cloneField(template, hasOwn.call(mapping, column) ? mapping[column] : column));
|
|
1205
1590
|
});
|
|
1206
1591
|
return {
|
|
1207
1592
|
tableSchema: cloneSchema2(__privateGet(this, _state).tableSchema, fields, __privateGet(this, _state).tableSchema.primaryKey),
|
|
@@ -1220,7 +1605,8 @@ resetIndexSchema_fn = function() {
|
|
|
1220
1605
|
)
|
|
1221
1606
|
};
|
|
1222
1607
|
}
|
|
1223
|
-
const
|
|
1608
|
+
const { dataInColumnOrder } = partitionSchemaFields(__privateGet(this, _state));
|
|
1609
|
+
const fields = dataInColumnOrder.length === __privateGet(this, _state).columns.length ? dataInColumnOrder.map((field) => cloneField(field)) : __privateGet(this, _state).tableSchema.fields.filter((field) => field.name !== __privateGet(this, _state).tableIndexField).map((field) => cloneField(field));
|
|
1224
1610
|
return {
|
|
1225
1611
|
tableSchema: cloneSchema2(__privateGet(this, _state).tableSchema, fields)
|
|
1226
1612
|
};
|
|
@@ -1232,105 +1618,6 @@ var InternalDataFrame = class extends DataFrame {
|
|
|
1232
1618
|
};
|
|
1233
1619
|
var createDataFrame = (state, packThreshold) => new InternalDataFrame(state, packThreshold);
|
|
1234
1620
|
|
|
1235
|
-
// src/options.ts
|
|
1236
|
-
var RESOLVED_ORIENTS = [
|
|
1237
|
-
"records",
|
|
1238
|
-
"index",
|
|
1239
|
-
"columns",
|
|
1240
|
-
"values",
|
|
1241
|
-
"split",
|
|
1242
|
-
"table"
|
|
1243
|
-
];
|
|
1244
|
-
var ORIENTS = ["auto", ...RESOLVED_ORIENTS];
|
|
1245
|
-
var COLUMN_TYPES = [
|
|
1246
|
-
"integer",
|
|
1247
|
-
"float",
|
|
1248
|
-
"string",
|
|
1249
|
-
"boolean",
|
|
1250
|
-
"datetime",
|
|
1251
|
-
"categorical",
|
|
1252
|
-
"mixed",
|
|
1253
|
-
"unknown"
|
|
1254
|
-
];
|
|
1255
|
-
var DEFAULT_PACK_THRESHOLD = 256;
|
|
1256
|
-
var isOrient = (value) => typeof value === "string" && ORIENTS.includes(value);
|
|
1257
|
-
var isColumnType = (value) => typeof value === "string" && COLUMN_TYPES.includes(value);
|
|
1258
|
-
var normalizeFromOrientOptions = (options) => {
|
|
1259
|
-
if (options == null) {
|
|
1260
|
-
return {
|
|
1261
|
-
orient: "auto",
|
|
1262
|
-
packThreshold: DEFAULT_PACK_THRESHOLD
|
|
1263
|
-
};
|
|
1264
|
-
}
|
|
1265
|
-
if (Array.isArray(options) || typeof options !== "object") {
|
|
1266
|
-
throw new JsonFrameOptionError("`fromOrient` options must be an object when provided.", "options", options);
|
|
1267
|
-
}
|
|
1268
|
-
const orient = options.orient ?? "auto";
|
|
1269
|
-
if (!isOrient(orient)) {
|
|
1270
|
-
throw new JsonFrameOptionError(
|
|
1271
|
-
"`options.orient` must be one of auto, records, index, columns, values, split, or table.",
|
|
1272
|
-
"orient",
|
|
1273
|
-
orient
|
|
1274
|
-
);
|
|
1275
|
-
}
|
|
1276
|
-
const packThreshold = options.packThreshold ?? DEFAULT_PACK_THRESHOLD;
|
|
1277
|
-
if (!Number.isFinite(packThreshold) || !Number.isInteger(packThreshold) || packThreshold < 0) {
|
|
1278
|
-
throw new JsonFrameOptionError(
|
|
1279
|
-
"`options.packThreshold` must be a finite non-negative integer.",
|
|
1280
|
-
"packThreshold",
|
|
1281
|
-
packThreshold
|
|
1282
|
-
);
|
|
1283
|
-
}
|
|
1284
|
-
let columns;
|
|
1285
|
-
if (options.columns !== void 0) {
|
|
1286
|
-
if (!Array.isArray(options.columns)) {
|
|
1287
|
-
throw new JsonFrameOptionError("`options.columns` must be an array of strings.", "columns", options.columns);
|
|
1288
|
-
}
|
|
1289
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1290
|
-
columns = options.columns.map((column) => {
|
|
1291
|
-
if (typeof column !== "string") {
|
|
1292
|
-
throw new JsonFrameOptionError("`options.columns` must contain only strings.", "columns", column);
|
|
1293
|
-
}
|
|
1294
|
-
if (seen.has(column)) {
|
|
1295
|
-
throw new JsonFrameOptionError("`options.columns` must not contain duplicates.", "columns", column);
|
|
1296
|
-
}
|
|
1297
|
-
seen.add(column);
|
|
1298
|
-
return column;
|
|
1299
|
-
});
|
|
1300
|
-
}
|
|
1301
|
-
let columnTypes;
|
|
1302
|
-
if (options.columnTypes !== void 0) {
|
|
1303
|
-
if (Array.isArray(options.columnTypes) || typeof options.columnTypes !== "object" || options.columnTypes === null) {
|
|
1304
|
-
throw new JsonFrameOptionError(
|
|
1305
|
-
"`options.columnTypes` must be an object keyed by column name.",
|
|
1306
|
-
"columnTypes",
|
|
1307
|
-
options.columnTypes
|
|
1308
|
-
);
|
|
1309
|
-
}
|
|
1310
|
-
const entries = Object.entries(options.columnTypes);
|
|
1311
|
-
columnTypes = Object.freeze(
|
|
1312
|
-
Object.fromEntries(
|
|
1313
|
-
entries.map(([column, type]) => {
|
|
1314
|
-
if (!isColumnType(type)) {
|
|
1315
|
-
throw new JsonFrameOptionError(
|
|
1316
|
-
"`options.columnTypes` values must be valid JSON Frame logical column types.",
|
|
1317
|
-
`columnTypes.${column}`,
|
|
1318
|
-
type
|
|
1319
|
-
);
|
|
1320
|
-
}
|
|
1321
|
-
return [column, type];
|
|
1322
|
-
})
|
|
1323
|
-
)
|
|
1324
|
-
);
|
|
1325
|
-
}
|
|
1326
|
-
return {
|
|
1327
|
-
orient,
|
|
1328
|
-
packThreshold,
|
|
1329
|
-
...columns === void 0 ? {} : { columns: Object.freeze([...columns]) },
|
|
1330
|
-
...columnTypes === void 0 ? {} : { columnTypes }
|
|
1331
|
-
};
|
|
1332
|
-
};
|
|
1333
|
-
|
|
1334
1621
|
// src/parse/parse.ts
|
|
1335
1622
|
var hasOwn2 = Object.prototype.hasOwnProperty;
|
|
1336
1623
|
var IDENTIFIER_PATTERN2 = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
@@ -1672,6 +1959,13 @@ var parseSplit = (value, orient) => {
|
|
|
1672
1959
|
}
|
|
1673
1960
|
const columns = assertUniqueStringColumns(value.columns, orient, "$.columns");
|
|
1674
1961
|
const data = initializeData(columns);
|
|
1962
|
+
if (value.index !== void 0 && !Array.isArray(value.index)) {
|
|
1963
|
+
throw new JsonFrameValidationError("`split.index` must be an array of index labels when present.", {
|
|
1964
|
+
orient,
|
|
1965
|
+
path: "$.index",
|
|
1966
|
+
value: value.index
|
|
1967
|
+
});
|
|
1968
|
+
}
|
|
1675
1969
|
const index = [];
|
|
1676
1970
|
const indexKind = Array.isArray(value.index) ? "source" : "synthetic";
|
|
1677
1971
|
if (Array.isArray(value.index)) {
|
|
@@ -1985,7 +2279,12 @@ var parseInput = (input, options) => {
|
|
|
1985
2279
|
throw error;
|
|
1986
2280
|
}
|
|
1987
2281
|
})();
|
|
1988
|
-
const jsonValue = cloneJsonCompatible(
|
|
2282
|
+
const jsonValue = cloneJsonCompatible(
|
|
2283
|
+
parsedValue,
|
|
2284
|
+
options.orient === "auto" ? void 0 : options.orient,
|
|
2285
|
+
"$",
|
|
2286
|
+
options.maxNodes
|
|
2287
|
+
);
|
|
1989
2288
|
const orient = options.orient === "auto" ? detectOrient(jsonValue) : options.orient;
|
|
1990
2289
|
switch (orient) {
|
|
1991
2290
|
case "records":
|