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