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