@web-ts-toolkit/json-frame 0.34.3 → 0.36.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/index.mjs CHANGED
@@ -0,0 +1,1625 @@
1
+ var __typeError = (msg) => {
2
+ throw TypeError(msg);
3
+ };
4
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
5
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
6
+ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
7
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
8
+ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
9
+
10
+ // src/errors.ts
11
+ var freezeCopy = (values) => Object.freeze([...values]);
12
+ var JsonFrameError = class extends Error {
13
+ constructor(message, context = {}) {
14
+ super(message);
15
+ Object.setPrototypeOf(this, new.target.prototype);
16
+ this.name = "JsonFrameError";
17
+ this.orient = context.orient;
18
+ this.path = context.path;
19
+ this.row = context.row;
20
+ this.column = context.column;
21
+ this.value = context.value;
22
+ }
23
+ };
24
+ var JsonFrameParseError = class extends JsonFrameError {
25
+ constructor(message, cause) {
26
+ super(message);
27
+ this.name = "JsonFrameParseError";
28
+ this.cause = cause;
29
+ }
30
+ };
31
+ var JsonFrameOptionError = class extends JsonFrameError {
32
+ constructor(message, option, value) {
33
+ super(message, { value });
34
+ this.name = "JsonFrameOptionError";
35
+ this.option = option;
36
+ }
37
+ };
38
+ var JsonFrameValidationError = class extends JsonFrameError {
39
+ constructor(message, context = {}) {
40
+ super(message, context);
41
+ this.name = "JsonFrameValidationError";
42
+ this.orient = context.orient;
43
+ }
44
+ };
45
+ var AmbiguousOrientError = class extends JsonFrameError {
46
+ constructor(message, candidates) {
47
+ super(message);
48
+ this.name = "AmbiguousOrientError";
49
+ this.candidates = freezeCopy(candidates);
50
+ }
51
+ };
52
+ var UnsupportedFeatureError = class extends JsonFrameError {
53
+ constructor(message, feature, context = {}) {
54
+ super(message, context);
55
+ this.name = "UnsupportedFeatureError";
56
+ this.feature = feature;
57
+ this.orient = context.orient;
58
+ }
59
+ };
60
+ var ExportKeyCollisionError = class extends JsonFrameError {
61
+ constructor(message, orient, key, labels) {
62
+ super(message, { orient });
63
+ this.name = "ExportKeyCollisionError";
64
+ this.orient = orient;
65
+ this.key = key;
66
+ this.labels = freezeCopy(labels);
67
+ }
68
+ };
69
+
70
+ // src/export/payload.ts
71
+ var createRecord = () => /* @__PURE__ */ Object.create(null);
72
+ var cloneJsonValue = (value) => {
73
+ if (Array.isArray(value)) {
74
+ return value.map((entry) => cloneJsonValue(entry));
75
+ }
76
+ if (value !== null && typeof value === "object") {
77
+ const cloned = createRecord();
78
+ for (const [key, entryValue] of Object.entries(value)) {
79
+ cloned[key] = cloneJsonValue(entryValue);
80
+ }
81
+ return cloned;
82
+ }
83
+ return value;
84
+ };
85
+ var cloneSchemaField = (field, name = field.name) => {
86
+ const cloned = createRecord();
87
+ for (const [key, value] of Object.entries(field)) {
88
+ cloned[key] = key === "name" ? name : value === void 0 ? void 0 : cloneJsonValue(value);
89
+ }
90
+ return cloned;
91
+ };
92
+ var cloneSchema = (schema, fields, primaryKey) => {
93
+ const cloned = createRecord();
94
+ if (schema !== void 0) {
95
+ for (const [key, value] of Object.entries(schema)) {
96
+ if (key === "fields" || key === "primaryKey") {
97
+ continue;
98
+ }
99
+ cloned[key] = value === void 0 ? void 0 : cloneJsonValue(value);
100
+ }
101
+ }
102
+ cloned.fields = fields.map((field) => cloneSchemaField(field));
103
+ if (primaryKey !== void 0) {
104
+ cloned.primaryKey = [...primaryKey];
105
+ }
106
+ return cloned;
107
+ };
108
+ var mapColumnTypeToSchemaField = (name, info) => {
109
+ const type = (() => {
110
+ switch (info.type) {
111
+ case "integer":
112
+ return "integer";
113
+ case "float":
114
+ return "number";
115
+ case "string":
116
+ case "categorical":
117
+ return "string";
118
+ case "boolean":
119
+ return "boolean";
120
+ case "datetime":
121
+ return "datetime";
122
+ case "mixed":
123
+ case "unknown":
124
+ return "any";
125
+ default: {
126
+ const exhaustive = info.type;
127
+ throw new JsonFrameValidationError("Unsupported logical column type for table export.", {
128
+ path: "$.columnInfo",
129
+ column: name,
130
+ value: exhaustive
131
+ });
132
+ }
133
+ }
134
+ })();
135
+ return info.type === "categorical" ? { name, type, extDtype: "category" } : { name, type };
136
+ };
137
+ var inferIndexFieldType = (index) => {
138
+ let sawString = false;
139
+ let sawInteger = false;
140
+ let sawFloat = false;
141
+ for (const label of index) {
142
+ if (typeof label === "string") {
143
+ sawString = true;
144
+ continue;
145
+ }
146
+ if (Number.isInteger(label)) {
147
+ sawInteger = true;
148
+ continue;
149
+ }
150
+ sawFloat = true;
151
+ }
152
+ if (sawString && (sawInteger || sawFloat)) {
153
+ return "any";
154
+ }
155
+ if (sawString) {
156
+ return "string";
157
+ }
158
+ if (sawFloat) {
159
+ return "number";
160
+ }
161
+ if (sawInteger) {
162
+ return "integer";
163
+ }
164
+ return "string";
165
+ };
166
+ var getIndexFieldTemplate = (state) => {
167
+ if (state.tableSchema === void 0 || state.tableIndexField === void 0) {
168
+ return void 0;
169
+ }
170
+ return state.tableSchema.fields.find((field) => field.name === state.tableIndexField);
171
+ };
172
+ var getDataFieldTemplates = (state) => {
173
+ if (state.tableSchema === void 0) {
174
+ return [];
175
+ }
176
+ const fieldsByName = new Map(state.tableSchema.fields.map((field) => [field.name, field]));
177
+ return state.columns.map((column) => fieldsByName.get(column)).filter((field) => field !== void 0);
178
+ };
179
+ var resolveIndexFieldName = (state, options) => {
180
+ if (options !== void 0 && (Array.isArray(options) || typeof options !== "object" || options === null)) {
181
+ throw new JsonFrameOptionError("`toTable` options must be an object when provided.", "options", options);
182
+ }
183
+ if (options?.indexField !== void 0 && typeof options.indexField !== "string") {
184
+ throw new JsonFrameOptionError(
185
+ "`toTable` options.indexField must be a string when provided.",
186
+ "indexField",
187
+ options.indexField
188
+ );
189
+ }
190
+ if (state.indexKind === "synthetic") {
191
+ return void 0;
192
+ }
193
+ const indexField = options?.indexField ?? state.tableIndexField ?? "index";
194
+ if (state.columns.includes(indexField)) {
195
+ throw new JsonFrameValidationError("Table export index field name must not collide with a data column.", {
196
+ path: "$.schema.fields",
197
+ column: indexField,
198
+ value: indexField
199
+ });
200
+ }
201
+ return indexField;
202
+ };
203
+ var resolveIndexKeys = (state, orient) => {
204
+ const seenKeys = /* @__PURE__ */ new Map();
205
+ const keys = [];
206
+ for (const label of state.index) {
207
+ const key = String(label);
208
+ const priorLabel = seenKeys.get(key);
209
+ if (priorLabel !== void 0) {
210
+ throw new ExportKeyCollisionError(
211
+ `Cannot export distinct rows to orient="${orient}" because index labels collide after stringification.`,
212
+ orient,
213
+ key,
214
+ [priorLabel, label]
215
+ );
216
+ }
217
+ seenKeys.set(key, label);
218
+ keys.push(key);
219
+ }
220
+ return keys;
221
+ };
222
+ var exportRecords = (state, materialized) => {
223
+ const rows = [];
224
+ for (let rowIndex = 0; rowIndex < state.index.length; rowIndex += 1) {
225
+ const row = createRecord();
226
+ for (const column of state.columns) {
227
+ row[column] = materialized.get(column)[rowIndex];
228
+ }
229
+ rows.push(row);
230
+ }
231
+ return rows;
232
+ };
233
+ var exportIndex = (state, materialized) => {
234
+ const keys = resolveIndexKeys(state, "index");
235
+ const rows = createRecord();
236
+ for (let rowIndex = 0; rowIndex < state.index.length; rowIndex += 1) {
237
+ const row = createRecord();
238
+ for (const column of state.columns) {
239
+ row[column] = materialized.get(column)[rowIndex];
240
+ }
241
+ rows[keys[rowIndex]] = row;
242
+ }
243
+ return rows;
244
+ };
245
+ var exportColumns = (state, materialized) => {
246
+ const keys = resolveIndexKeys(state, "columns");
247
+ const columns = createRecord();
248
+ for (const column of state.columns) {
249
+ const values = createRecord();
250
+ const entries = materialized.get(column);
251
+ for (let rowIndex = 0; rowIndex < state.index.length; rowIndex += 1) {
252
+ values[keys[rowIndex]] = entries[rowIndex];
253
+ }
254
+ columns[column] = values;
255
+ }
256
+ return columns;
257
+ };
258
+ var exportValues = (state, materialized) => {
259
+ const rows = [];
260
+ for (let rowIndex = 0; rowIndex < state.index.length; rowIndex += 1) {
261
+ rows.push(state.columns.map((column) => materialized.get(column)[rowIndex]));
262
+ }
263
+ return rows;
264
+ };
265
+ var exportSplit = (state, materialized) => ({
266
+ columns: [...state.columns],
267
+ index: [...state.index],
268
+ data: exportValues(state, materialized)
269
+ });
270
+ var exportTable = (state, materialized, columnInfo, options) => {
271
+ const indexField = resolveIndexFieldName(state, options);
272
+ const indexTemplate = getIndexFieldTemplate(state);
273
+ const dataTemplates = getDataFieldTemplates(state);
274
+ const fields = [];
275
+ if (indexField !== void 0) {
276
+ fields.push(
277
+ indexTemplate === void 0 ? { name: indexField, type: inferIndexFieldType(state.index) } : cloneSchemaField(indexTemplate, indexField)
278
+ );
279
+ }
280
+ for (let columnIndex = 0; columnIndex < state.columns.length; columnIndex += 1) {
281
+ const column = state.columns[columnIndex];
282
+ const template = dataTemplates[columnIndex];
283
+ fields.push(
284
+ template === void 0 ? mapColumnTypeToSchemaField(column, columnInfo.get(column)) : cloneSchemaField(template, column)
285
+ );
286
+ }
287
+ const data = [];
288
+ for (let rowIndex = 0; rowIndex < state.index.length; rowIndex += 1) {
289
+ const row = createRecord();
290
+ if (indexField !== void 0) {
291
+ row[indexField] = state.index[rowIndex];
292
+ }
293
+ for (const column of state.columns) {
294
+ row[column] = materialized.get(column)[rowIndex];
295
+ }
296
+ data.push(row);
297
+ }
298
+ return {
299
+ schema: cloneSchema(state.tableSchema, fields, indexField === void 0 ? void 0 : [indexField]),
300
+ data
301
+ };
302
+ };
303
+
304
+ // src/frame/column.ts
305
+ var INT32_MIN = -2147483648;
306
+ var INT32_MAX = 2147483647;
307
+ var freezeArray = (values) => Object.freeze([...values]);
308
+ var freezeColumnInfo = (info) => Object.freeze({ ...info });
309
+ var hasCategoricalMetadata = (field) => field.constraints?.enum !== void 0 || field.ordered === true || field.extDtype === "category";
310
+ var mapTableSchemaFieldType = (field) => {
311
+ if (hasCategoricalMetadata(field)) {
312
+ return "categorical";
313
+ }
314
+ switch (field.type) {
315
+ case "boolean":
316
+ return "boolean";
317
+ case "integer":
318
+ case "year":
319
+ return "integer";
320
+ case "number":
321
+ return "float";
322
+ case "date":
323
+ case "datetime":
324
+ return "datetime";
325
+ case "string":
326
+ return "string";
327
+ case "any":
328
+ return "unknown";
329
+ default:
330
+ return "unknown";
331
+ }
332
+ };
333
+ var inferColumnType = (values) => {
334
+ let nullable = false;
335
+ let sawBoolean = false;
336
+ let sawString = false;
337
+ let sawInteger = false;
338
+ let sawFloat = false;
339
+ let sawStructured = false;
340
+ for (const value of values) {
341
+ if (value === null) {
342
+ nullable = true;
343
+ continue;
344
+ }
345
+ if (typeof value === "boolean") {
346
+ sawBoolean = true;
347
+ continue;
348
+ }
349
+ if (typeof value === "string") {
350
+ sawString = true;
351
+ continue;
352
+ }
353
+ if (typeof value === "number") {
354
+ if (Number.isInteger(value)) {
355
+ sawInteger = true;
356
+ } else {
357
+ sawFloat = true;
358
+ }
359
+ continue;
360
+ }
361
+ sawStructured = true;
362
+ }
363
+ const nonNullKinds = [sawBoolean, sawString, sawInteger || sawFloat, sawStructured].filter(Boolean).length;
364
+ if (nonNullKinds === 0) {
365
+ return freezeColumnInfo({ type: "unknown", nullable });
366
+ }
367
+ if (sawStructured || nonNullKinds > 1 || sawBoolean && (sawString || sawInteger || sawFloat)) {
368
+ return freezeColumnInfo({ type: "mixed", nullable });
369
+ }
370
+ if (sawString) {
371
+ return freezeColumnInfo({ type: "string", nullable });
372
+ }
373
+ if (sawBoolean) {
374
+ return freezeColumnInfo({ type: "boolean", nullable });
375
+ }
376
+ if (sawFloat) {
377
+ return freezeColumnInfo({ type: "float", nullable });
378
+ }
379
+ return freezeColumnInfo({ type: "integer", nullable });
380
+ };
381
+ var packColumn = (values, info, packThreshold) => {
382
+ if (packThreshold === 0 || values.length < packThreshold || info.nullable) {
383
+ return freezeArray(values);
384
+ }
385
+ if (info.type === "integer") {
386
+ const packed = new Int32Array(values.length);
387
+ for (let index = 0; index < values.length; index += 1) {
388
+ const value = values[index];
389
+ if (typeof value !== "number" || !Number.isInteger(value) || value < INT32_MIN || value > INT32_MAX) {
390
+ return freezeArray(values);
391
+ }
392
+ packed[index] = value;
393
+ }
394
+ return packed;
395
+ }
396
+ if (info.type === "float") {
397
+ const packed = new Float64Array(values.length);
398
+ for (let index = 0; index < values.length; index += 1) {
399
+ const value = values[index];
400
+ if (typeof value !== "number") {
401
+ return freezeArray(values);
402
+ }
403
+ packed[index] = value;
404
+ }
405
+ return packed;
406
+ }
407
+ return freezeArray(values);
408
+ };
409
+ var validateExplicitColumnTypes = (columns, columnTypes) => {
410
+ if (columnTypes === void 0) {
411
+ return;
412
+ }
413
+ const knownColumns = new Set(columns);
414
+ for (const column of Object.keys(columnTypes)) {
415
+ if (!knownColumns.has(column)) {
416
+ throw new JsonFrameOptionError(
417
+ "`options.columnTypes` keys must match parsed column names.",
418
+ `columnTypes.${column}`,
419
+ columnTypes[column]
420
+ );
421
+ }
422
+ }
423
+ };
424
+ var resolveSchemaTypeByColumn = (frame) => {
425
+ if (frame.tableSchema === void 0) {
426
+ return /* @__PURE__ */ new Map();
427
+ }
428
+ const schemaTypes = /* @__PURE__ */ new Map();
429
+ for (const field of frame.tableSchema.fields) {
430
+ if (frame.columns.includes(field.name)) {
431
+ schemaTypes.set(field.name, mapTableSchemaFieldType(field));
432
+ }
433
+ }
434
+ return schemaTypes;
435
+ };
436
+ var materializeColumn = (column) => Array.isArray(column) ? freezeArray(column) : freezeArray(Array.from(column));
437
+ var materializeFrameData = (columns, data) => {
438
+ const materialized = /* @__PURE__ */ new Map();
439
+ for (const column of columns) {
440
+ const stored = data.get(column);
441
+ if (stored === void 0) {
442
+ throw new JsonFrameValidationError("Stored frame data is missing a declared column.", {
443
+ path: "$",
444
+ column
445
+ });
446
+ }
447
+ materialized.set(column, materializeColumn(stored));
448
+ }
449
+ return materialized;
450
+ };
451
+ var buildFrameState = (frame, options) => {
452
+ validateExplicitColumnTypes(frame.columns, options.columnTypes);
453
+ const schemaTypes = resolveSchemaTypeByColumn(frame);
454
+ const data = /* @__PURE__ */ new Map();
455
+ const columnInfo = /* @__PURE__ */ new Map();
456
+ for (const column of frame.columns) {
457
+ const values = frame.data.get(column);
458
+ if (values === void 0) {
459
+ throw new JsonFrameValidationError("Parsed frame data is missing a declared column.", {
460
+ orient: frame.orient,
461
+ column
462
+ });
463
+ }
464
+ const inferred = inferColumnType(values);
465
+ const resolvedType = schemaTypes.get(column) ?? options.columnTypes?.[column] ?? inferred.type;
466
+ const info = freezeColumnInfo({ type: resolvedType, nullable: inferred.nullable });
467
+ columnInfo.set(column, info);
468
+ data.set(column, packColumn(values, info, options.packThreshold));
469
+ }
470
+ return {
471
+ columns: freezeArray(frame.columns),
472
+ index: freezeArray(frame.index),
473
+ indexKind: frame.indexKind,
474
+ data,
475
+ columnInfo,
476
+ ...frame.tableSchema === void 0 ? {} : { tableSchema: frame.tableSchema },
477
+ ...frame.tableIndexField === void 0 ? {} : { tableIndexField: frame.tableIndexField }
478
+ };
479
+ };
480
+ var createFrameStateFromData = (frame, options) => buildFrameState(frame, options);
481
+ var createFrameState = (frame, options) => buildFrameState(frame, options);
482
+
483
+ // src/frame/DataFrame.ts
484
+ var hasOwn = Object.prototype.hasOwnProperty;
485
+ var frameStateByInstance = /* @__PURE__ */ new WeakMap();
486
+ var freezeArray2 = (values) => Object.freeze([...values]);
487
+ var cloneField = (field, name = field.name) => Object.freeze({ ...field, name });
488
+ var cloneSchema2 = (schema, fields, primaryKey) => {
489
+ const cloned = /* @__PURE__ */ Object.create(null);
490
+ for (const [key, value] of Object.entries(schema)) {
491
+ if (key === "fields" || key === "primaryKey") {
492
+ continue;
493
+ }
494
+ cloned[key] = value;
495
+ }
496
+ cloned.fields = freezeArray2(fields);
497
+ if (primaryKey !== void 0) {
498
+ cloned.primaryKey = freezeArray2(primaryKey);
499
+ }
500
+ return Object.freeze(cloned);
501
+ };
502
+ var _state, _packThreshold, _DataFrame_instances, assertRowPosition_fn, materializedData_fn, createRow_fn, columnTypeOverrides_fn, rebuild_fn, selectSchema_fn, renameSchema_fn, resetIndexSchema_fn;
503
+ var DataFrame = class {
504
+ constructor(state, packThreshold) {
505
+ __privateAdd(this, _DataFrame_instances);
506
+ __privateAdd(this, _state);
507
+ __privateAdd(this, _packThreshold);
508
+ __privateSet(this, _state, state);
509
+ __privateSet(this, _packThreshold, packThreshold);
510
+ frameStateByInstance.set(this, state);
511
+ }
512
+ get columns() {
513
+ return freezeArray2(__privateGet(this, _state).columns);
514
+ }
515
+ get index() {
516
+ return freezeArray2(__privateGet(this, _state).index);
517
+ }
518
+ get columnInfo() {
519
+ return new Map(__privateGet(this, _state).columnInfo);
520
+ }
521
+ get length() {
522
+ return __privateGet(this, _state).index.length;
523
+ }
524
+ toRecords() {
525
+ return exportRecords(__privateGet(this, _state), __privateMethod(this, _DataFrame_instances, materializedData_fn).call(this));
526
+ }
527
+ toIndex() {
528
+ return exportIndex(__privateGet(this, _state), __privateMethod(this, _DataFrame_instances, materializedData_fn).call(this));
529
+ }
530
+ toColumns() {
531
+ return exportColumns(__privateGet(this, _state), __privateMethod(this, _DataFrame_instances, materializedData_fn).call(this));
532
+ }
533
+ toValues() {
534
+ return exportValues(__privateGet(this, _state), __privateMethod(this, _DataFrame_instances, materializedData_fn).call(this));
535
+ }
536
+ toSplit() {
537
+ return exportSplit(__privateGet(this, _state), __privateMethod(this, _DataFrame_instances, materializedData_fn).call(this));
538
+ }
539
+ toTable(options) {
540
+ return exportTable(__privateGet(this, _state), __privateMethod(this, _DataFrame_instances, materializedData_fn).call(this), __privateGet(this, _state).columnInfo, options);
541
+ }
542
+ toJSONString(orient, options) {
543
+ switch (orient) {
544
+ case "records":
545
+ return JSON.stringify(this.toRecords());
546
+ case "index":
547
+ return JSON.stringify(this.toIndex());
548
+ case "columns":
549
+ return JSON.stringify(this.toColumns());
550
+ case "values":
551
+ return JSON.stringify(this.toValues());
552
+ case "split":
553
+ return JSON.stringify(this.toSplit());
554
+ case "table":
555
+ return JSON.stringify(this.toTable(options));
556
+ default: {
557
+ const exhaustive = orient;
558
+ throw new JsonFrameValidationError("Unsupported export orient.", { value: exhaustive });
559
+ }
560
+ }
561
+ }
562
+ row(position) {
563
+ __privateMethod(this, _DataFrame_instances, assertRowPosition_fn).call(this, position);
564
+ return __privateMethod(this, _DataFrame_instances, createRow_fn).call(this, __privateMethod(this, _DataFrame_instances, materializedData_fn).call(this), position);
565
+ }
566
+ rows() {
567
+ const materialized = __privateMethod(this, _DataFrame_instances, materializedData_fn).call(this);
568
+ const rows = __privateGet(this, _state).index.map((_, position) => __privateMethod(this, _DataFrame_instances, createRow_fn).call(this, materialized, position));
569
+ return freezeArray2(rows);
570
+ }
571
+ filter(predicate) {
572
+ const materialized = __privateMethod(this, _DataFrame_instances, materializedData_fn).call(this);
573
+ const keptPositions = [];
574
+ for (let position = 0; position < this.length; position += 1) {
575
+ if (predicate(__privateMethod(this, _DataFrame_instances, createRow_fn).call(this, materialized, position), __privateGet(this, _state).index[position], position)) {
576
+ keptPositions.push(position);
577
+ }
578
+ }
579
+ return __privateMethod(this, _DataFrame_instances, rebuild_fn).call(this, {
580
+ columns: __privateGet(this, _state).columns,
581
+ sourceColumns: __privateGet(this, _state).columns,
582
+ positions: keptPositions,
583
+ index: keptPositions.map((position) => __privateGet(this, _state).index[position]),
584
+ indexKind: __privateGet(this, _state).indexKind,
585
+ schema: {
586
+ tableSchema: __privateGet(this, _state).tableSchema,
587
+ tableIndexField: __privateGet(this, _state).tableIndexField
588
+ }
589
+ });
590
+ }
591
+ sort(compare) {
592
+ const materialized = __privateMethod(this, _DataFrame_instances, materializedData_fn).call(this);
593
+ const ordering = __privateGet(this, _state).index.map((indexLabel, position) => ({
594
+ indexLabel,
595
+ position,
596
+ row: __privateMethod(this, _DataFrame_instances, createRow_fn).call(this, materialized, position)
597
+ }));
598
+ ordering.sort((left, right) => {
599
+ const result = compare(left.row, right.row, left.indexLabel, right.indexLabel, left.position, right.position);
600
+ return (Number.isNaN(result) ? 0 : result) || left.position - right.position;
601
+ });
602
+ return __privateMethod(this, _DataFrame_instances, rebuild_fn).call(this, {
603
+ columns: __privateGet(this, _state).columns,
604
+ sourceColumns: __privateGet(this, _state).columns,
605
+ positions: ordering.map(({ position }) => position),
606
+ index: ordering.map(({ indexLabel }) => indexLabel),
607
+ indexKind: __privateGet(this, _state).indexKind,
608
+ schema: {
609
+ tableSchema: __privateGet(this, _state).tableSchema,
610
+ tableIndexField: __privateGet(this, _state).tableIndexField
611
+ }
612
+ });
613
+ }
614
+ select(...columns) {
615
+ const seen = /* @__PURE__ */ new Set();
616
+ for (const column of columns) {
617
+ if (!__privateGet(this, _state).data.has(column)) {
618
+ throw new JsonFrameValidationError("Selected columns must exist in the frame.", {
619
+ path: "$.columns",
620
+ column,
621
+ value: column
622
+ });
623
+ }
624
+ if (seen.has(column)) {
625
+ throw new JsonFrameValidationError("Selected columns must be unique.", {
626
+ path: "$.columns",
627
+ column,
628
+ value: column
629
+ });
630
+ }
631
+ seen.add(column);
632
+ }
633
+ const selectedSchema = __privateMethod(this, _DataFrame_instances, selectSchema_fn).call(this, columns);
634
+ return __privateMethod(this, _DataFrame_instances, rebuild_fn).call(this, {
635
+ columns,
636
+ sourceColumns: columns,
637
+ positions: __privateGet(this, _state).index.map((_, position) => position),
638
+ index: __privateGet(this, _state).index,
639
+ indexKind: __privateGet(this, _state).indexKind,
640
+ schema: selectedSchema
641
+ });
642
+ }
643
+ rename(mapping) {
644
+ const nextColumns = __privateGet(this, _state).columns.map((column) => hasOwn.call(mapping, column) ? mapping[column] : column);
645
+ const seen = /* @__PURE__ */ new Set();
646
+ for (let position = 0; position < nextColumns.length; position += 1) {
647
+ const column = nextColumns[position];
648
+ if (seen.has(column)) {
649
+ throw new JsonFrameValidationError("Renamed columns must remain unique.", {
650
+ path: "$.columns",
651
+ column,
652
+ value: column
653
+ });
654
+ }
655
+ seen.add(column);
656
+ }
657
+ const renamedSchema = __privateMethod(this, _DataFrame_instances, renameSchema_fn).call(this, mapping);
658
+ return __privateMethod(this, _DataFrame_instances, rebuild_fn).call(this, {
659
+ columns: nextColumns,
660
+ sourceColumns: __privateGet(this, _state).columns,
661
+ positions: __privateGet(this, _state).index.map((_, position) => position),
662
+ index: __privateGet(this, _state).index,
663
+ indexKind: __privateGet(this, _state).indexKind,
664
+ schema: renamedSchema
665
+ });
666
+ }
667
+ resetIndex() {
668
+ const resetSchema = __privateMethod(this, _DataFrame_instances, resetIndexSchema_fn).call(this);
669
+ return __privateMethod(this, _DataFrame_instances, rebuild_fn).call(this, {
670
+ columns: __privateGet(this, _state).columns,
671
+ sourceColumns: __privateGet(this, _state).columns,
672
+ positions: __privateGet(this, _state).index.map((_, position) => position),
673
+ index: __privateGet(this, _state).index.map((_, position) => position),
674
+ indexKind: "synthetic",
675
+ schema: resetSchema
676
+ });
677
+ }
678
+ };
679
+ _state = new WeakMap();
680
+ _packThreshold = new WeakMap();
681
+ _DataFrame_instances = new WeakSet();
682
+ assertRowPosition_fn = function(position) {
683
+ if (!Number.isInteger(position) || position < 0 || position >= this.length) {
684
+ throw new RangeError(`Row position must be an integer in [0, ${this.length}).`);
685
+ }
686
+ };
687
+ materializedData_fn = function() {
688
+ return materializeFrameData(__privateGet(this, _state).columns, __privateGet(this, _state).data);
689
+ };
690
+ createRow_fn = function(materialized, position) {
691
+ const row = /* @__PURE__ */ Object.create(null);
692
+ for (const column of __privateGet(this, _state).columns) {
693
+ row[column] = materialized.get(column)[position];
694
+ }
695
+ return Object.freeze(row);
696
+ };
697
+ columnTypeOverrides_fn = function(columns, sourceColumns) {
698
+ return Object.freeze(
699
+ Object.fromEntries(
700
+ columns.map((column, position) => [column, __privateGet(this, _state).columnInfo.get(sourceColumns[position]).type])
701
+ )
702
+ );
703
+ };
704
+ rebuild_fn = function({
705
+ columns,
706
+ sourceColumns,
707
+ positions,
708
+ index,
709
+ indexKind,
710
+ schema
711
+ }) {
712
+ const materialized = __privateMethod(this, _DataFrame_instances, materializedData_fn).call(this);
713
+ const nextData = /* @__PURE__ */ new Map();
714
+ for (let columnIndex = 0; columnIndex < columns.length; columnIndex += 1) {
715
+ const column = columns[columnIndex];
716
+ const sourceColumn = materialized.get(sourceColumns[columnIndex]);
717
+ if (sourceColumn === void 0) {
718
+ throw new JsonFrameValidationError("Stored frame data is missing a declared column.", {
719
+ path: "$",
720
+ column
721
+ });
722
+ }
723
+ nextData.set(column, freezeArray2(positions.map((position) => sourceColumn[position])));
724
+ }
725
+ const state = createFrameStateFromData(
726
+ {
727
+ columns,
728
+ index,
729
+ indexKind,
730
+ data: nextData,
731
+ ...schema.tableSchema === void 0 ? {} : { tableSchema: schema.tableSchema },
732
+ ...schema.tableIndexField === void 0 ? {} : { tableIndexField: schema.tableIndexField }
733
+ },
734
+ {
735
+ packThreshold: __privateGet(this, _packThreshold),
736
+ columnTypes: __privateMethod(this, _DataFrame_instances, columnTypeOverrides_fn).call(this, columns, sourceColumns)
737
+ }
738
+ );
739
+ return createDataFrame(state, __privateGet(this, _packThreshold));
740
+ };
741
+ selectSchema_fn = function(columns) {
742
+ if (__privateGet(this, _state).tableSchema === void 0) {
743
+ return {};
744
+ }
745
+ const fieldByName = new Map(__privateGet(this, _state).tableSchema.fields.map((field) => [field.name, field]));
746
+ const fields = [];
747
+ if (__privateGet(this, _state).tableIndexField !== void 0) {
748
+ const indexField = fieldByName.get(__privateGet(this, _state).tableIndexField);
749
+ if (indexField !== void 0) {
750
+ fields.push(cloneField(indexField));
751
+ }
752
+ }
753
+ for (const column of columns) {
754
+ const field = fieldByName.get(column);
755
+ if (field !== void 0) {
756
+ fields.push(cloneField(field));
757
+ }
758
+ }
759
+ return {
760
+ tableSchema: cloneSchema2(__privateGet(this, _state).tableSchema, fields, __privateGet(this, _state).tableSchema.primaryKey),
761
+ ...__privateGet(this, _state).tableIndexField === void 0 ? {} : { tableIndexField: __privateGet(this, _state).tableIndexField }
762
+ };
763
+ };
764
+ renameSchema_fn = function(mapping) {
765
+ if (__privateGet(this, _state).tableSchema === void 0) {
766
+ return {};
767
+ }
768
+ const fields = __privateGet(this, _state).tableSchema.fields.map((field) => {
769
+ if (!__privateGet(this, _state).columns.includes(field.name)) {
770
+ return cloneField(field);
771
+ }
772
+ return cloneField(field, hasOwn.call(mapping, field.name) ? mapping[field.name] : field.name);
773
+ });
774
+ return {
775
+ tableSchema: cloneSchema2(__privateGet(this, _state).tableSchema, fields, __privateGet(this, _state).tableSchema.primaryKey),
776
+ ...__privateGet(this, _state).tableIndexField === void 0 ? {} : { tableIndexField: __privateGet(this, _state).tableIndexField }
777
+ };
778
+ };
779
+ resetIndexSchema_fn = function() {
780
+ if (__privateGet(this, _state).tableSchema === void 0) {
781
+ return {};
782
+ }
783
+ if (__privateGet(this, _state).tableIndexField === void 0) {
784
+ return {
785
+ tableSchema: cloneSchema2(
786
+ __privateGet(this, _state).tableSchema,
787
+ __privateGet(this, _state).tableSchema.fields.map((field) => cloneField(field))
788
+ )
789
+ };
790
+ }
791
+ const fields = __privateGet(this, _state).tableSchema.fields.filter((field) => field.name !== __privateGet(this, _state).tableIndexField).map((field) => cloneField(field));
792
+ return {
793
+ tableSchema: cloneSchema2(__privateGet(this, _state).tableSchema, fields)
794
+ };
795
+ };
796
+ var InternalDataFrame = class extends DataFrame {
797
+ constructor(state, packThreshold) {
798
+ super(state, packThreshold);
799
+ }
800
+ };
801
+ var createDataFrame = (state, packThreshold) => new InternalDataFrame(state, packThreshold);
802
+
803
+ // src/options.ts
804
+ var RESOLVED_ORIENTS = [
805
+ "records",
806
+ "index",
807
+ "columns",
808
+ "values",
809
+ "split",
810
+ "table"
811
+ ];
812
+ var ORIENTS = ["auto", ...RESOLVED_ORIENTS];
813
+ var COLUMN_TYPES = [
814
+ "integer",
815
+ "float",
816
+ "string",
817
+ "boolean",
818
+ "datetime",
819
+ "categorical",
820
+ "mixed",
821
+ "unknown"
822
+ ];
823
+ var DEFAULT_PACK_THRESHOLD = 256;
824
+ var isOrient = (value) => typeof value === "string" && ORIENTS.includes(value);
825
+ var isColumnType = (value) => typeof value === "string" && COLUMN_TYPES.includes(value);
826
+ var normalizeFromOrientOptions = (options) => {
827
+ if (options == null) {
828
+ return {
829
+ orient: "auto",
830
+ packThreshold: DEFAULT_PACK_THRESHOLD
831
+ };
832
+ }
833
+ if (Array.isArray(options) || typeof options !== "object") {
834
+ throw new JsonFrameOptionError("`fromOrient` options must be an object when provided.", "options", options);
835
+ }
836
+ const orient = options.orient ?? "auto";
837
+ if (!isOrient(orient)) {
838
+ throw new JsonFrameOptionError(
839
+ "`options.orient` must be one of auto, records, index, columns, values, split, or table.",
840
+ "orient",
841
+ orient
842
+ );
843
+ }
844
+ const packThreshold = options.packThreshold ?? DEFAULT_PACK_THRESHOLD;
845
+ if (!Number.isFinite(packThreshold) || !Number.isInteger(packThreshold) || packThreshold < 0) {
846
+ throw new JsonFrameOptionError(
847
+ "`options.packThreshold` must be a finite non-negative integer.",
848
+ "packThreshold",
849
+ packThreshold
850
+ );
851
+ }
852
+ let columns;
853
+ if (options.columns !== void 0) {
854
+ if (!Array.isArray(options.columns)) {
855
+ throw new JsonFrameOptionError("`options.columns` must be an array of strings.", "columns", options.columns);
856
+ }
857
+ const seen = /* @__PURE__ */ new Set();
858
+ columns = options.columns.map((column) => {
859
+ if (typeof column !== "string") {
860
+ throw new JsonFrameOptionError("`options.columns` must contain only strings.", "columns", column);
861
+ }
862
+ if (seen.has(column)) {
863
+ throw new JsonFrameOptionError("`options.columns` must not contain duplicates.", "columns", column);
864
+ }
865
+ seen.add(column);
866
+ return column;
867
+ });
868
+ }
869
+ let columnTypes;
870
+ if (options.columnTypes !== void 0) {
871
+ if (Array.isArray(options.columnTypes) || typeof options.columnTypes !== "object" || options.columnTypes === null) {
872
+ throw new JsonFrameOptionError(
873
+ "`options.columnTypes` must be an object keyed by column name.",
874
+ "columnTypes",
875
+ options.columnTypes
876
+ );
877
+ }
878
+ const entries = Object.entries(options.columnTypes);
879
+ columnTypes = Object.freeze(
880
+ Object.fromEntries(
881
+ entries.map(([column, type]) => {
882
+ if (!isColumnType(type)) {
883
+ throw new JsonFrameOptionError(
884
+ "`options.columnTypes` values must be valid JSON Frame logical column types.",
885
+ `columnTypes.${column}`,
886
+ type
887
+ );
888
+ }
889
+ return [column, type];
890
+ })
891
+ )
892
+ );
893
+ }
894
+ return {
895
+ orient,
896
+ packThreshold,
897
+ ...columns === void 0 ? {} : { columns: Object.freeze([...columns]) },
898
+ ...columnTypes === void 0 ? {} : { columnTypes }
899
+ };
900
+ };
901
+
902
+ // src/parse/parse.ts
903
+ var hasOwn2 = Object.prototype.hasOwnProperty;
904
+ var IDENTIFIER_PATTERN = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
905
+ var freezeArray3 = (values) => Object.freeze([...values]);
906
+ var appendPropertyPath = (path, key) => IDENTIFIER_PATTERN.test(key) ? `${path}.${key}` : `${path}[${JSON.stringify(key)}]`;
907
+ var appendIndexPath = (path, index) => `${path}[${index}]`;
908
+ var isPlainObject = (value) => {
909
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
910
+ return false;
911
+ }
912
+ const prototype = Object.getPrototypeOf(value);
913
+ return prototype === Object.prototype || prototype === null;
914
+ };
915
+ var assertSupportedIndexLabel = (value, orient, path) => {
916
+ if (typeof value === "string") {
917
+ return value;
918
+ }
919
+ if (typeof value === "number" && Number.isFinite(value)) {
920
+ return value;
921
+ }
922
+ throw new JsonFrameValidationError("Index labels must be strings or finite numbers.", {
923
+ orient,
924
+ path,
925
+ value
926
+ });
927
+ };
928
+ var assertUniqueStringColumns = (values, orient, path) => {
929
+ const columns = [];
930
+ const seen = /* @__PURE__ */ new Set();
931
+ for (let index = 0; index < values.length; index += 1) {
932
+ const value = values[index];
933
+ const entryPath = appendIndexPath(path, index);
934
+ if (typeof value !== "string") {
935
+ throw new JsonFrameValidationError("Column labels must be strings.", {
936
+ orient,
937
+ path: entryPath,
938
+ value
939
+ });
940
+ }
941
+ if (seen.has(value)) {
942
+ throw new JsonFrameValidationError("Column labels must be unique.", {
943
+ orient,
944
+ path: entryPath,
945
+ column: value,
946
+ value
947
+ });
948
+ }
949
+ seen.add(value);
950
+ columns.push(value);
951
+ }
952
+ return freezeArray3(columns);
953
+ };
954
+ var initializeData = (columns) => new Map(columns.map((column) => [column, []]));
955
+ var finalizeFrame = ({
956
+ orient,
957
+ columns,
958
+ index,
959
+ indexKind,
960
+ data,
961
+ tableSchema,
962
+ tableIndexField
963
+ }) => {
964
+ const finalizedData = /* @__PURE__ */ new Map();
965
+ for (const column of columns) {
966
+ const values = data.get(column);
967
+ if (values === void 0) {
968
+ throw new JsonFrameValidationError("Parsed frame data is missing a declared column.", {
969
+ orient,
970
+ column
971
+ });
972
+ }
973
+ finalizedData.set(column, freezeArray3(values));
974
+ }
975
+ return {
976
+ orient,
977
+ columns: freezeArray3(columns),
978
+ index: freezeArray3(index),
979
+ indexKind,
980
+ data: finalizedData,
981
+ ...tableSchema === void 0 ? {} : { tableSchema },
982
+ ...tableIndexField === void 0 ? {} : { tableIndexField }
983
+ };
984
+ };
985
+ var validateJsonCompatible = (value, path = "$", stack = /* @__PURE__ */ new Set()) => {
986
+ if (value === null || typeof value === "string" || typeof value === "boolean") {
987
+ return value;
988
+ }
989
+ if (typeof value === "number") {
990
+ if (!Number.isFinite(value)) {
991
+ throw new JsonFrameValidationError("Numbers must be finite JSON values.", { path, value });
992
+ }
993
+ return value;
994
+ }
995
+ if (typeof value === "undefined" || typeof value === "function" || typeof value === "symbol" || typeof value === "bigint") {
996
+ throw new JsonFrameValidationError("Input must contain only JSON-compatible values.", { path, value });
997
+ }
998
+ if (Array.isArray(value)) {
999
+ if (stack.has(value)) {
1000
+ throw new JsonFrameValidationError("Input contains a cyclic array.", { path, value });
1001
+ }
1002
+ stack.add(value);
1003
+ const normalized2 = [];
1004
+ for (let index = 0; index < value.length; index += 1) {
1005
+ if (!(index in value)) {
1006
+ stack.delete(value);
1007
+ throw new JsonFrameValidationError("Sparse arrays are not valid JSON input.", {
1008
+ path: appendIndexPath(path, index),
1009
+ value
1010
+ });
1011
+ }
1012
+ normalized2.push(validateJsonCompatible(value[index], appendIndexPath(path, index), stack));
1013
+ }
1014
+ stack.delete(value);
1015
+ return normalized2;
1016
+ }
1017
+ if (!isPlainObject(value)) {
1018
+ throw new JsonFrameValidationError("Input objects must be plain JSON objects or arrays.", { path, value });
1019
+ }
1020
+ if (stack.has(value)) {
1021
+ throw new JsonFrameValidationError("Input contains a cyclic object.", { path, value });
1022
+ }
1023
+ stack.add(value);
1024
+ const normalized = /* @__PURE__ */ Object.create(null);
1025
+ for (const [key, entryValue] of Object.entries(value)) {
1026
+ normalized[key] = validateJsonCompatible(entryValue, appendPropertyPath(path, key), stack);
1027
+ }
1028
+ stack.delete(value);
1029
+ return normalized;
1030
+ };
1031
+ var detectOrient = (value) => {
1032
+ if (Array.isArray(value)) {
1033
+ if (value.length === 0) {
1034
+ throw new AmbiguousOrientError(
1035
+ "Auto detection cannot distinguish between empty records and empty values payloads.",
1036
+ ["records", "values"]
1037
+ );
1038
+ }
1039
+ if (value.every((entry) => Array.isArray(entry))) {
1040
+ return "values";
1041
+ }
1042
+ if (value.every((entry) => isPlainObject(entry))) {
1043
+ return "records";
1044
+ }
1045
+ throw new JsonFrameValidationError("Auto detection requires a non-empty array of row objects or row arrays.", {
1046
+ path: "$",
1047
+ value
1048
+ });
1049
+ }
1050
+ if (!isPlainObject(value)) {
1051
+ throw new JsonFrameValidationError("Auto detection requires a JSON array or object payload.", {
1052
+ path: "$",
1053
+ value
1054
+ });
1055
+ }
1056
+ if (isPlainObject(value.schema) && Array.isArray(value.data)) {
1057
+ return "table";
1058
+ }
1059
+ if (Array.isArray(value.columns) && Array.isArray(value.data) && (value.index === void 0 || Array.isArray(value.index))) {
1060
+ return "split";
1061
+ }
1062
+ const keys = Object.keys(value);
1063
+ if (keys.length === 0 || keys.every((key) => isPlainObject(value[key]))) {
1064
+ throw new AmbiguousOrientError("Auto detection cannot distinguish between index and columns payloads.", [
1065
+ "index",
1066
+ "columns"
1067
+ ]);
1068
+ }
1069
+ throw new JsonFrameValidationError("Auto detection could not resolve the payload orient.", {
1070
+ path: "$",
1071
+ value
1072
+ });
1073
+ };
1074
+ var parseRecords = (value, orient) => {
1075
+ if (!Array.isArray(value)) {
1076
+ throw new JsonFrameValidationError("`records` payloads must be arrays.", { orient, path: "$", value });
1077
+ }
1078
+ const columns = [];
1079
+ const knownColumns = /* @__PURE__ */ new Set();
1080
+ const data = /* @__PURE__ */ new Map();
1081
+ const index = [];
1082
+ for (let rowIndex = 0; rowIndex < value.length; rowIndex += 1) {
1083
+ const row = value[rowIndex];
1084
+ const rowPath = appendIndexPath("$", rowIndex);
1085
+ if (!isPlainObject(row)) {
1086
+ throw new JsonFrameValidationError("`records` rows must be JSON objects.", {
1087
+ orient,
1088
+ path: rowPath,
1089
+ row: rowIndex,
1090
+ value: row
1091
+ });
1092
+ }
1093
+ for (const column of Object.keys(row)) {
1094
+ if (!knownColumns.has(column)) {
1095
+ knownColumns.add(column);
1096
+ columns.push(column);
1097
+ data.set(column, Array(rowIndex).fill(null));
1098
+ }
1099
+ }
1100
+ for (const column of columns) {
1101
+ data.get(column).push(hasOwn2.call(row, column) ? row[column] : null);
1102
+ }
1103
+ index.push(rowIndex);
1104
+ }
1105
+ return finalizeFrame({
1106
+ orient,
1107
+ columns,
1108
+ index,
1109
+ indexKind: "synthetic",
1110
+ data
1111
+ });
1112
+ };
1113
+ var parseIndex = (value, orient) => {
1114
+ if (!isPlainObject(value)) {
1115
+ throw new JsonFrameValidationError("`index` payloads must be objects keyed by index label.", {
1116
+ orient,
1117
+ path: "$",
1118
+ value
1119
+ });
1120
+ }
1121
+ const columns = [];
1122
+ const knownColumns = /* @__PURE__ */ new Set();
1123
+ const data = /* @__PURE__ */ new Map();
1124
+ const index = Object.keys(value);
1125
+ for (let rowIndex = 0; rowIndex < index.length; rowIndex += 1) {
1126
+ const indexLabel = index[rowIndex];
1127
+ const row = value[indexLabel];
1128
+ const rowPath = appendPropertyPath("$", indexLabel);
1129
+ if (!isPlainObject(row)) {
1130
+ throw new JsonFrameValidationError("`index` payload rows must be JSON objects.", {
1131
+ orient,
1132
+ path: rowPath,
1133
+ row: rowIndex,
1134
+ value: row
1135
+ });
1136
+ }
1137
+ for (const column of Object.keys(row)) {
1138
+ if (!knownColumns.has(column)) {
1139
+ knownColumns.add(column);
1140
+ columns.push(column);
1141
+ data.set(column, Array(rowIndex).fill(null));
1142
+ }
1143
+ }
1144
+ for (const column of columns) {
1145
+ data.get(column).push(hasOwn2.call(row, column) ? row[column] : null);
1146
+ }
1147
+ }
1148
+ return finalizeFrame({
1149
+ orient,
1150
+ columns,
1151
+ index,
1152
+ indexKind: "source",
1153
+ data
1154
+ });
1155
+ };
1156
+ var parseColumns = (value, orient) => {
1157
+ if (!isPlainObject(value)) {
1158
+ throw new JsonFrameValidationError("`columns` payloads must be objects keyed by column label.", {
1159
+ orient,
1160
+ path: "$",
1161
+ value
1162
+ });
1163
+ }
1164
+ const columns = Object.keys(value);
1165
+ const data = /* @__PURE__ */ new Map();
1166
+ if (columns.length === 0) {
1167
+ return finalizeFrame({
1168
+ orient,
1169
+ columns,
1170
+ index: [],
1171
+ indexKind: "source",
1172
+ data
1173
+ });
1174
+ }
1175
+ let index;
1176
+ for (const column of columns) {
1177
+ const columnValue = value[column];
1178
+ const columnPath = appendPropertyPath("$", column);
1179
+ if (!isPlainObject(columnValue)) {
1180
+ throw new JsonFrameValidationError("`columns` payload values must be objects keyed by index label.", {
1181
+ orient,
1182
+ path: columnPath,
1183
+ column,
1184
+ value: columnValue
1185
+ });
1186
+ }
1187
+ const keys = Object.keys(columnValue);
1188
+ if (index === void 0) {
1189
+ index = freezeArray3(keys);
1190
+ } else if (keys.length !== index.length || keys.some((key, indexPosition) => key !== index[indexPosition])) {
1191
+ throw new JsonFrameValidationError("Every `columns` payload column must expose the same ordered index keys.", {
1192
+ orient,
1193
+ path: columnPath,
1194
+ column,
1195
+ value: columnValue
1196
+ });
1197
+ }
1198
+ data.set(
1199
+ column,
1200
+ keys.map((indexKey) => columnValue[indexKey])
1201
+ );
1202
+ }
1203
+ return finalizeFrame({
1204
+ orient,
1205
+ columns,
1206
+ index: index ?? [],
1207
+ indexKind: "source",
1208
+ data
1209
+ });
1210
+ };
1211
+ var parseValues = (value, options, orient) => {
1212
+ if (options.columns === void 0) {
1213
+ throw new JsonFrameOptionError(
1214
+ '`options.columns` is required for `orient="values"` input.',
1215
+ "columns",
1216
+ options.columns
1217
+ );
1218
+ }
1219
+ if (!Array.isArray(value)) {
1220
+ throw new JsonFrameValidationError("`values` payloads must be arrays of arrays.", { orient, path: "$", value });
1221
+ }
1222
+ const columns = [...options.columns];
1223
+ const data = initializeData(columns);
1224
+ const index = [];
1225
+ for (let rowIndex = 0; rowIndex < value.length; rowIndex += 1) {
1226
+ const row = value[rowIndex];
1227
+ const rowPath = appendIndexPath("$", rowIndex);
1228
+ if (!Array.isArray(row)) {
1229
+ throw new JsonFrameValidationError("`values` rows must be arrays.", {
1230
+ orient,
1231
+ path: rowPath,
1232
+ row: rowIndex,
1233
+ value: row
1234
+ });
1235
+ }
1236
+ if (row.length !== columns.length) {
1237
+ throw new JsonFrameValidationError("`values` row widths must match `options.columns`.", {
1238
+ orient,
1239
+ path: rowPath,
1240
+ row: rowIndex,
1241
+ value: row
1242
+ });
1243
+ }
1244
+ for (let columnIndex = 0; columnIndex < columns.length; columnIndex += 1) {
1245
+ data.get(columns[columnIndex]).push(row[columnIndex]);
1246
+ }
1247
+ index.push(rowIndex);
1248
+ }
1249
+ return finalizeFrame({
1250
+ orient,
1251
+ columns,
1252
+ index,
1253
+ indexKind: "synthetic",
1254
+ data
1255
+ });
1256
+ };
1257
+ var parseSplit = (value, orient) => {
1258
+ if (!isPlainObject(value)) {
1259
+ throw new JsonFrameValidationError("`split` payloads must be objects.", { orient, path: "$", value });
1260
+ }
1261
+ if (!Array.isArray(value.columns)) {
1262
+ throw new JsonFrameValidationError("`split.columns` must be an array of unique strings.", {
1263
+ orient,
1264
+ path: "$.columns",
1265
+ value: value.columns
1266
+ });
1267
+ }
1268
+ if (!Array.isArray(value.data)) {
1269
+ throw new JsonFrameValidationError("`split.data` must be an array of row arrays.", {
1270
+ orient,
1271
+ path: "$.data",
1272
+ value: value.data
1273
+ });
1274
+ }
1275
+ const columns = assertUniqueStringColumns(value.columns, orient, "$.columns");
1276
+ const data = initializeData(columns);
1277
+ const index = [];
1278
+ const indexKind = Array.isArray(value.index) ? "source" : "synthetic";
1279
+ if (Array.isArray(value.index)) {
1280
+ for (let indexPosition = 0; indexPosition < value.index.length; indexPosition += 1) {
1281
+ index.push(
1282
+ assertSupportedIndexLabel(
1283
+ value.index[indexPosition],
1284
+ orient,
1285
+ appendIndexPath("$.index", indexPosition)
1286
+ )
1287
+ );
1288
+ }
1289
+ }
1290
+ const rows = value.data;
1291
+ if (indexKind === "source" && index.length !== rows.length) {
1292
+ throw new JsonFrameValidationError("`split.index` length must match `split.data` length.", {
1293
+ orient,
1294
+ path: "$.index",
1295
+ value: value.index
1296
+ });
1297
+ }
1298
+ for (let rowIndex = 0; rowIndex < rows.length; rowIndex += 1) {
1299
+ const row = rows[rowIndex];
1300
+ const rowPath = appendIndexPath("$.data", rowIndex);
1301
+ if (!Array.isArray(row)) {
1302
+ throw new JsonFrameValidationError("`split.data` rows must be arrays.", {
1303
+ orient,
1304
+ path: rowPath,
1305
+ row: rowIndex,
1306
+ value: row
1307
+ });
1308
+ }
1309
+ if (row.length !== columns.length) {
1310
+ throw new JsonFrameValidationError("`split.data` row widths must match `split.columns`.", {
1311
+ orient,
1312
+ path: rowPath,
1313
+ row: rowIndex,
1314
+ value: row
1315
+ });
1316
+ }
1317
+ for (let columnIndex = 0; columnIndex < columns.length; columnIndex += 1) {
1318
+ data.get(columns[columnIndex]).push(row[columnIndex]);
1319
+ }
1320
+ if (indexKind === "synthetic") {
1321
+ index.push(rowIndex);
1322
+ }
1323
+ }
1324
+ return finalizeFrame({
1325
+ orient,
1326
+ columns,
1327
+ index,
1328
+ indexKind,
1329
+ data
1330
+ });
1331
+ };
1332
+ var cloneConstraints = (value, orient, path) => {
1333
+ if (!isPlainObject(value)) {
1334
+ throw new JsonFrameValidationError("Table Schema field constraints must be an object when present.", {
1335
+ orient,
1336
+ path,
1337
+ value
1338
+ });
1339
+ }
1340
+ const cloned = /* @__PURE__ */ Object.create(null);
1341
+ for (const [key, entryValue] of Object.entries(value)) {
1342
+ if (key === "enum") {
1343
+ if (!Array.isArray(entryValue)) {
1344
+ throw new JsonFrameValidationError("Table Schema `constraints.enum` must be an array of scalar JSON values.", {
1345
+ orient,
1346
+ path: appendPropertyPath(path, key),
1347
+ value: entryValue
1348
+ });
1349
+ }
1350
+ cloned[key] = freezeArray3(
1351
+ entryValue.map((enumValue, index) => {
1352
+ const enumPath = appendIndexPath(appendPropertyPath(path, key), index);
1353
+ if (enumValue === null || typeof enumValue === "string" || typeof enumValue === "boolean") {
1354
+ return enumValue;
1355
+ }
1356
+ if (typeof enumValue === "number" && Number.isFinite(enumValue)) {
1357
+ return enumValue;
1358
+ }
1359
+ throw new JsonFrameValidationError("Table Schema `constraints.enum` must contain only scalar JSON values.", {
1360
+ orient,
1361
+ path: enumPath,
1362
+ value: enumValue
1363
+ });
1364
+ })
1365
+ );
1366
+ continue;
1367
+ }
1368
+ cloned[key] = entryValue;
1369
+ }
1370
+ return Object.freeze(cloned);
1371
+ };
1372
+ var cloneTableField = (value, index) => {
1373
+ const orient = "table";
1374
+ const path = appendIndexPath("$.schema.fields", index);
1375
+ if (!isPlainObject(value)) {
1376
+ throw new JsonFrameValidationError("Table Schema fields must be objects.", {
1377
+ orient,
1378
+ path,
1379
+ value
1380
+ });
1381
+ }
1382
+ if (typeof value.name !== "string") {
1383
+ throw new JsonFrameValidationError("Table Schema field names must be strings.", {
1384
+ orient,
1385
+ path: appendPropertyPath(path, "name"),
1386
+ value: value.name
1387
+ });
1388
+ }
1389
+ if (typeof value.type !== "string") {
1390
+ throw new JsonFrameValidationError("Table Schema field types must be strings.", {
1391
+ orient,
1392
+ path: appendPropertyPath(path, "type"),
1393
+ value: value.type
1394
+ });
1395
+ }
1396
+ if (value.ordered !== void 0 && typeof value.ordered !== "boolean") {
1397
+ throw new JsonFrameValidationError("Table Schema `ordered` must be boolean when present.", {
1398
+ orient,
1399
+ path: appendPropertyPath(path, "ordered"),
1400
+ value: value.ordered
1401
+ });
1402
+ }
1403
+ const stringKeys = ["format", "extDtype", "tz", "freq"];
1404
+ for (const key of stringKeys) {
1405
+ const entryValue = value[key];
1406
+ if (entryValue !== void 0 && typeof entryValue !== "string") {
1407
+ throw new JsonFrameValidationError(`Table Schema \`${key}\` must be a string when present.`, {
1408
+ orient,
1409
+ path: appendPropertyPath(path, key),
1410
+ value: entryValue
1411
+ });
1412
+ }
1413
+ }
1414
+ const cloned = /* @__PURE__ */ Object.create(null);
1415
+ for (const [key, entryValue] of Object.entries(value)) {
1416
+ cloned[key] = key === "constraints" && entryValue !== void 0 ? cloneConstraints(entryValue, orient, appendPropertyPath(path, key)) : entryValue;
1417
+ }
1418
+ return Object.freeze(cloned);
1419
+ };
1420
+ var cloneTableSchema = (value) => {
1421
+ const orient = "table";
1422
+ if (!isPlainObject(value)) {
1423
+ throw new JsonFrameValidationError("`table.schema` must be an object.", {
1424
+ orient,
1425
+ path: "$.schema",
1426
+ value
1427
+ });
1428
+ }
1429
+ if (!Array.isArray(value.fields)) {
1430
+ throw new JsonFrameValidationError("`table.schema.fields` must be an array.", {
1431
+ orient,
1432
+ path: "$.schema.fields",
1433
+ value: value.fields
1434
+ });
1435
+ }
1436
+ const fields = freezeArray3(value.fields.map((field, index) => cloneTableField(field, index)));
1437
+ const seenFieldNames = /* @__PURE__ */ new Set();
1438
+ for (const field of fields) {
1439
+ if (seenFieldNames.has(field.name)) {
1440
+ throw new JsonFrameValidationError("Table Schema field names must be unique.", {
1441
+ orient,
1442
+ path: "$.schema.fields",
1443
+ column: field.name,
1444
+ value: field.name
1445
+ });
1446
+ }
1447
+ seenFieldNames.add(field.name);
1448
+ }
1449
+ let primaryKey;
1450
+ if (value.primaryKey !== void 0) {
1451
+ if (!Array.isArray(value.primaryKey)) {
1452
+ throw new JsonFrameValidationError("`table.schema.primaryKey` must be an array of strings when present.", {
1453
+ orient,
1454
+ path: "$.schema.primaryKey",
1455
+ value: value.primaryKey
1456
+ });
1457
+ }
1458
+ primaryKey = freezeArray3(
1459
+ value.primaryKey.map((entryValue, index) => {
1460
+ if (typeof entryValue !== "string") {
1461
+ throw new JsonFrameValidationError("`table.schema.primaryKey` entries must be strings.", {
1462
+ orient,
1463
+ path: appendIndexPath("$.schema.primaryKey", index),
1464
+ value: entryValue
1465
+ });
1466
+ }
1467
+ return entryValue;
1468
+ })
1469
+ );
1470
+ }
1471
+ if (primaryKey !== void 0 && primaryKey.length > 1) {
1472
+ throw new UnsupportedFeatureError("MultiIndex table payloads are not supported.", "multi-index", {
1473
+ orient,
1474
+ path: "$.schema.primaryKey",
1475
+ value: primaryKey
1476
+ });
1477
+ }
1478
+ if (value.pandas_version !== void 0 && typeof value.pandas_version !== "string") {
1479
+ throw new JsonFrameValidationError("`table.schema.pandas_version` must be a string when present.", {
1480
+ orient,
1481
+ path: "$.schema.pandas_version",
1482
+ value: value.pandas_version
1483
+ });
1484
+ }
1485
+ const cloned = /* @__PURE__ */ Object.create(null);
1486
+ for (const [key, entryValue] of Object.entries(value)) {
1487
+ if (key === "fields") {
1488
+ cloned[key] = fields;
1489
+ } else if (key === "primaryKey") {
1490
+ cloned[key] = primaryKey;
1491
+ } else {
1492
+ cloned[key] = entryValue;
1493
+ }
1494
+ }
1495
+ return Object.freeze(cloned);
1496
+ };
1497
+ var parseTable = (value, orient) => {
1498
+ if (!isPlainObject(value)) {
1499
+ throw new JsonFrameValidationError("`table` payloads must be objects.", { orient, path: "$", value });
1500
+ }
1501
+ const schema = cloneTableSchema(value.schema);
1502
+ if (!Array.isArray(value.data)) {
1503
+ throw new JsonFrameValidationError("`table.data` must be an array of row objects.", {
1504
+ orient,
1505
+ path: "$.data",
1506
+ value: value.data
1507
+ });
1508
+ }
1509
+ const primaryKey = schema.primaryKey?.[0];
1510
+ if (primaryKey !== void 0 && !schema.fields.some((field) => field.name === primaryKey)) {
1511
+ throw new JsonFrameValidationError("`table.schema.primaryKey` must reference a declared field.", {
1512
+ orient,
1513
+ path: "$.schema.primaryKey",
1514
+ column: primaryKey,
1515
+ value: schema.primaryKey
1516
+ });
1517
+ }
1518
+ const columns = schema.fields.filter((field) => field.name !== primaryKey).map((field) => field.name);
1519
+ const data = initializeData(columns);
1520
+ const fieldNames = new Set(schema.fields.map((field) => field.name));
1521
+ const index = [];
1522
+ const indexKind = primaryKey === void 0 ? "synthetic" : "source";
1523
+ for (let rowIndex = 0; rowIndex < value.data.length; rowIndex += 1) {
1524
+ const row = value.data[rowIndex];
1525
+ const rowPath = appendIndexPath("$.data", rowIndex);
1526
+ if (!isPlainObject(row)) {
1527
+ throw new JsonFrameValidationError("`table.data` rows must be objects.", {
1528
+ orient,
1529
+ path: rowPath,
1530
+ row: rowIndex,
1531
+ value: row
1532
+ });
1533
+ }
1534
+ for (const key of Object.keys(row)) {
1535
+ if (!fieldNames.has(key)) {
1536
+ throw new JsonFrameValidationError("`table.data` rows must not include fields missing from `schema.fields`.", {
1537
+ orient,
1538
+ path: appendPropertyPath(rowPath, key),
1539
+ row: rowIndex,
1540
+ column: key,
1541
+ value: row[key]
1542
+ });
1543
+ }
1544
+ }
1545
+ if (primaryKey === void 0) {
1546
+ index.push(rowIndex);
1547
+ } else if (!hasOwn2.call(row, primaryKey)) {
1548
+ throw new JsonFrameValidationError("`table.data` rows must include the primary-key field.", {
1549
+ orient,
1550
+ path: rowPath,
1551
+ row: rowIndex,
1552
+ column: primaryKey,
1553
+ value: row
1554
+ });
1555
+ } else {
1556
+ index.push(
1557
+ assertSupportedIndexLabel(row[primaryKey], orient, appendPropertyPath(rowPath, primaryKey))
1558
+ );
1559
+ }
1560
+ for (const column of columns) {
1561
+ data.get(column).push(hasOwn2.call(row, column) ? row[column] : null);
1562
+ }
1563
+ }
1564
+ return finalizeFrame({
1565
+ orient,
1566
+ columns,
1567
+ index,
1568
+ indexKind,
1569
+ data,
1570
+ tableSchema: schema,
1571
+ ...primaryKey === void 0 ? {} : { tableIndexField: primaryKey }
1572
+ });
1573
+ };
1574
+ var parseInput = (input, options) => {
1575
+ const parsedValue = (() => {
1576
+ if (typeof input !== "string") {
1577
+ return input;
1578
+ }
1579
+ try {
1580
+ return JSON.parse(input);
1581
+ } catch (error) {
1582
+ if (error instanceof SyntaxError) {
1583
+ throw new JsonFrameParseError("Failed to parse JSON input.", error);
1584
+ }
1585
+ throw error;
1586
+ }
1587
+ })();
1588
+ const jsonValue = validateJsonCompatible(parsedValue);
1589
+ const orient = options.orient === "auto" ? detectOrient(jsonValue) : options.orient;
1590
+ switch (orient) {
1591
+ case "records":
1592
+ return parseRecords(jsonValue, orient);
1593
+ case "index":
1594
+ return parseIndex(jsonValue, orient);
1595
+ case "columns":
1596
+ return parseColumns(jsonValue, orient);
1597
+ case "values":
1598
+ return parseValues(jsonValue, options, orient);
1599
+ case "split":
1600
+ return parseSplit(jsonValue, orient);
1601
+ case "table":
1602
+ return parseTable(jsonValue, orient);
1603
+ default: {
1604
+ const exhaustive = orient;
1605
+ throw new JsonFrameValidationError("Unsupported orient.", { value: exhaustive });
1606
+ }
1607
+ }
1608
+ };
1609
+
1610
+ // src/api.ts
1611
+ function fromOrient(input, options) {
1612
+ const normalized = normalizeFromOrientOptions(options);
1613
+ const parsed = parseInput(input, normalized);
1614
+ return createDataFrame(createFrameState(parsed, normalized), normalized.packThreshold);
1615
+ }
1616
+ export {
1617
+ AmbiguousOrientError,
1618
+ ExportKeyCollisionError,
1619
+ JsonFrameError,
1620
+ JsonFrameOptionError,
1621
+ JsonFrameParseError,
1622
+ JsonFrameValidationError,
1623
+ UnsupportedFeatureError,
1624
+ fromOrient
1625
+ };