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