@web-ts-toolkit/json-frame 0.40.1 → 0.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +75 -16
- package/index.d.mts +115 -29
- package/index.d.ts +115 -29
- package/index.js +661 -292
- package/index.mjs +660 -292
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -30,6 +30,7 @@ var index_exports = {};
|
|
|
30
30
|
__export(index_exports, {
|
|
31
31
|
AmbiguousOrientError: () => AmbiguousOrientError,
|
|
32
32
|
ExportKeyCollisionError: () => ExportKeyCollisionError,
|
|
33
|
+
JSON_FRAME_MAX_DEPTH: () => JSON_FRAME_MAX_DEPTH,
|
|
33
34
|
JsonFrameError: () => JsonFrameError,
|
|
34
35
|
JsonFrameOptionError: () => JsonFrameOptionError,
|
|
35
36
|
JsonFrameParseError: () => JsonFrameParseError,
|
|
@@ -40,7 +41,38 @@ __export(index_exports, {
|
|
|
40
41
|
module.exports = __toCommonJS(index_exports);
|
|
41
42
|
|
|
42
43
|
// src/errors.ts
|
|
44
|
+
var DIAGNOSTIC_KEY_LIMIT = 5;
|
|
43
45
|
var freezeCopy = (values) => Object.freeze([...values]);
|
|
46
|
+
var summarizeDiagnosticValue = (value) => {
|
|
47
|
+
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
50
|
+
if (Array.isArray(value)) {
|
|
51
|
+
return Object.freeze({ kind: "array", length: value.length });
|
|
52
|
+
}
|
|
53
|
+
if (typeof value === "object") {
|
|
54
|
+
const keys = Object.keys(value);
|
|
55
|
+
return Object.freeze({
|
|
56
|
+
kind: "object",
|
|
57
|
+
keyCount: keys.length,
|
|
58
|
+
keys: freezeCopy(keys.slice(0, DIAGNOSTIC_KEY_LIMIT)),
|
|
59
|
+
truncated: keys.length > DIAGNOSTIC_KEY_LIMIT
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
if (typeof value === "undefined") {
|
|
63
|
+
return Object.freeze({ kind: "undefined" });
|
|
64
|
+
}
|
|
65
|
+
if (typeof value === "symbol") {
|
|
66
|
+
return Object.freeze({ kind: "symbol" });
|
|
67
|
+
}
|
|
68
|
+
if (typeof value === "bigint") {
|
|
69
|
+
return Object.freeze({ kind: "bigint" });
|
|
70
|
+
}
|
|
71
|
+
if (typeof value === "function") {
|
|
72
|
+
return Object.freeze({ kind: "function" });
|
|
73
|
+
}
|
|
74
|
+
return Object.freeze({ kind: "object", keyCount: 0, keys: freezeCopy([]), truncated: false });
|
|
75
|
+
};
|
|
44
76
|
var JsonFrameError = class extends Error {
|
|
45
77
|
constructor(message, context = {}) {
|
|
46
78
|
super(message);
|
|
@@ -50,7 +82,9 @@ var JsonFrameError = class extends Error {
|
|
|
50
82
|
this.path = context.path;
|
|
51
83
|
this.row = context.row;
|
|
52
84
|
this.column = context.column;
|
|
53
|
-
|
|
85
|
+
if ("value" in context) {
|
|
86
|
+
this.value = summarizeDiagnosticValue(context.value);
|
|
87
|
+
}
|
|
54
88
|
}
|
|
55
89
|
};
|
|
56
90
|
var JsonFrameParseError = class extends JsonFrameError {
|
|
@@ -99,25 +133,494 @@ var ExportKeyCollisionError = class extends JsonFrameError {
|
|
|
99
133
|
}
|
|
100
134
|
};
|
|
101
135
|
|
|
136
|
+
// src/frame/column.ts
|
|
137
|
+
var INT32_MIN = -2147483648;
|
|
138
|
+
var INT32_MAX = 2147483647;
|
|
139
|
+
var freezeArray = (values) => Object.freeze([...values]);
|
|
140
|
+
var freezeColumnInfo = (info) => Object.freeze({ ...info });
|
|
141
|
+
var DATETIME_PATTERN = /^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})(?:[T ](?<hour>\d{2}):(?<minute>\d{2}):(?<second>\d{2})(?:\.(?<fraction>\d{1,9}))?)?$/;
|
|
142
|
+
var columnOperationCounters = {
|
|
143
|
+
materializeColumnCalls: 0,
|
|
144
|
+
materializedCells: 0,
|
|
145
|
+
scalarReads: 0,
|
|
146
|
+
rebuiltCells: 0,
|
|
147
|
+
nullableChecks: 0
|
|
148
|
+
};
|
|
149
|
+
var hasCategoricalMetadata = (field) => field.constraints?.enum !== void 0 || field.ordered === true || field.extDtype === "category";
|
|
150
|
+
var mapTableSchemaFieldType = (field) => {
|
|
151
|
+
if (hasCategoricalMetadata(field)) {
|
|
152
|
+
return "categorical";
|
|
153
|
+
}
|
|
154
|
+
switch (field.type) {
|
|
155
|
+
case "boolean":
|
|
156
|
+
return "boolean";
|
|
157
|
+
case "integer":
|
|
158
|
+
case "year":
|
|
159
|
+
return "integer";
|
|
160
|
+
case "number":
|
|
161
|
+
return "float";
|
|
162
|
+
case "date":
|
|
163
|
+
case "datetime":
|
|
164
|
+
return "datetime";
|
|
165
|
+
case "string":
|
|
166
|
+
return "string";
|
|
167
|
+
case "any":
|
|
168
|
+
return "unknown";
|
|
169
|
+
default:
|
|
170
|
+
return "unknown";
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
var inferColumnType = (values) => {
|
|
174
|
+
let nullable = false;
|
|
175
|
+
let sawBoolean = false;
|
|
176
|
+
let sawString = false;
|
|
177
|
+
let sawInteger = false;
|
|
178
|
+
let sawFloat = false;
|
|
179
|
+
let sawStructured = false;
|
|
180
|
+
for (const value of values) {
|
|
181
|
+
if (value === null) {
|
|
182
|
+
nullable = true;
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
if (typeof value === "boolean") {
|
|
186
|
+
sawBoolean = true;
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
if (typeof value === "string") {
|
|
190
|
+
sawString = true;
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
if (typeof value === "number") {
|
|
194
|
+
if (Number.isInteger(value)) {
|
|
195
|
+
sawInteger = true;
|
|
196
|
+
} else {
|
|
197
|
+
sawFloat = true;
|
|
198
|
+
}
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
sawStructured = true;
|
|
202
|
+
}
|
|
203
|
+
const nonNullKinds = [sawBoolean, sawString, sawInteger || sawFloat, sawStructured].filter(Boolean).length;
|
|
204
|
+
if (nonNullKinds === 0) {
|
|
205
|
+
return freezeColumnInfo({ type: "unknown", nullable });
|
|
206
|
+
}
|
|
207
|
+
if (sawStructured || nonNullKinds > 1 || sawBoolean && (sawString || sawInteger || sawFloat)) {
|
|
208
|
+
return freezeColumnInfo({ type: "mixed", nullable });
|
|
209
|
+
}
|
|
210
|
+
if (sawString) {
|
|
211
|
+
return freezeColumnInfo({ type: "string", nullable });
|
|
212
|
+
}
|
|
213
|
+
if (sawBoolean) {
|
|
214
|
+
return freezeColumnInfo({ type: "boolean", nullable });
|
|
215
|
+
}
|
|
216
|
+
if (sawFloat) {
|
|
217
|
+
return freezeColumnInfo({ type: "float", nullable });
|
|
218
|
+
}
|
|
219
|
+
return freezeColumnInfo({ type: "integer", nullable });
|
|
220
|
+
};
|
|
221
|
+
var isPandasNaiveIsoDatetime = (value) => {
|
|
222
|
+
const match = DATETIME_PATTERN.exec(value);
|
|
223
|
+
if (match?.groups === void 0) {
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
const year = Number(match.groups.year);
|
|
227
|
+
const month = Number(match.groups.month);
|
|
228
|
+
const day = Number(match.groups.day);
|
|
229
|
+
const hour = match.groups.hour === void 0 ? 0 : Number(match.groups.hour);
|
|
230
|
+
const minute = match.groups.minute === void 0 ? 0 : Number(match.groups.minute);
|
|
231
|
+
const second = match.groups.second === void 0 ? 0 : Number(match.groups.second);
|
|
232
|
+
if (month < 1 || month > 12 || hour > 23 || minute > 59 || second > 59) {
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
const normalized = new Date(Date.UTC(year, month - 1, day, hour, minute, second));
|
|
236
|
+
return normalized.getUTCFullYear() === year && normalized.getUTCMonth() === month - 1 && normalized.getUTCDate() === day && normalized.getUTCHours() === hour && normalized.getUTCMinutes() === minute && normalized.getUTCSeconds() === second;
|
|
237
|
+
};
|
|
238
|
+
var isScalarCategory = (value) => typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
239
|
+
var isJsonContainer = (value) => {
|
|
240
|
+
if (Array.isArray(value)) {
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
if (value === null || typeof value !== "object") {
|
|
244
|
+
return false;
|
|
245
|
+
}
|
|
246
|
+
const prototype = Object.getPrototypeOf(value);
|
|
247
|
+
return prototype === Object.prototype || prototype === null;
|
|
248
|
+
};
|
|
249
|
+
var isColumnValueCompatible = (type, value) => {
|
|
250
|
+
if (value === null) {
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
253
|
+
switch (type) {
|
|
254
|
+
case "integer":
|
|
255
|
+
return typeof value === "number" && Number.isInteger(value);
|
|
256
|
+
case "float":
|
|
257
|
+
return typeof value === "number";
|
|
258
|
+
case "string":
|
|
259
|
+
return typeof value === "string";
|
|
260
|
+
case "boolean":
|
|
261
|
+
return typeof value === "boolean";
|
|
262
|
+
case "datetime":
|
|
263
|
+
return typeof value === "string" && isPandasNaiveIsoDatetime(value);
|
|
264
|
+
case "categorical":
|
|
265
|
+
return isScalarCategory(value);
|
|
266
|
+
case "mixed":
|
|
267
|
+
case "unknown":
|
|
268
|
+
return typeof value === "string" || typeof value === "number" || typeof value === "boolean" || isJsonContainer(value);
|
|
269
|
+
default: {
|
|
270
|
+
const exhaustive = type;
|
|
271
|
+
return exhaustive;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
var getColumnCellPath = (orient, column, columnIndex, rowIndex, rowLabel) => {
|
|
276
|
+
switch (orient) {
|
|
277
|
+
case "records":
|
|
278
|
+
return `$[${rowIndex}][${JSON.stringify(column)}]`;
|
|
279
|
+
case "values":
|
|
280
|
+
return `$[${rowIndex}][${columnIndex}]`;
|
|
281
|
+
case "split":
|
|
282
|
+
return `$.data[${rowIndex}][${columnIndex}]`;
|
|
283
|
+
case "table":
|
|
284
|
+
return `$.data[${rowIndex}][${JSON.stringify(column)}]`;
|
|
285
|
+
case "index":
|
|
286
|
+
return `$[${JSON.stringify(String(rowLabel))}][${JSON.stringify(column)}]`;
|
|
287
|
+
case "columns":
|
|
288
|
+
return `$[${JSON.stringify(column)}][${JSON.stringify(String(rowLabel))}]`;
|
|
289
|
+
default:
|
|
290
|
+
return `$.data[${rowIndex}][${JSON.stringify(column)}]`;
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
var validateColumnValuesForType = ({
|
|
294
|
+
column,
|
|
295
|
+
columnIndex,
|
|
296
|
+
values,
|
|
297
|
+
type,
|
|
298
|
+
orient,
|
|
299
|
+
index
|
|
300
|
+
}) => {
|
|
301
|
+
for (let rowIndex = 0; rowIndex < values.length; rowIndex += 1) {
|
|
302
|
+
const value = values[rowIndex];
|
|
303
|
+
if (isColumnValueCompatible(type, value)) {
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
306
|
+
throw new JsonFrameValidationError("Column cells are incompatible with the declared logical type.", {
|
|
307
|
+
...orient === void 0 ? {} : { orient },
|
|
308
|
+
path: getColumnCellPath(orient, column, columnIndex, rowIndex, index?.[rowIndex]),
|
|
309
|
+
row: rowIndex,
|
|
310
|
+
column,
|
|
311
|
+
value
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
var packColumn = (values, info, packThreshold) => {
|
|
316
|
+
if (packThreshold === 0 || values.length < packThreshold || info.nullable) {
|
|
317
|
+
return freezeArray(values);
|
|
318
|
+
}
|
|
319
|
+
if (info.type === "integer") {
|
|
320
|
+
const packed = new Int32Array(values.length);
|
|
321
|
+
for (let index = 0; index < values.length; index += 1) {
|
|
322
|
+
const value = values[index];
|
|
323
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value < INT32_MIN || value > INT32_MAX) {
|
|
324
|
+
return freezeArray(values);
|
|
325
|
+
}
|
|
326
|
+
packed[index] = value;
|
|
327
|
+
}
|
|
328
|
+
return packed;
|
|
329
|
+
}
|
|
330
|
+
if (info.type === "float") {
|
|
331
|
+
const packed = new Float64Array(values.length);
|
|
332
|
+
for (let index = 0; index < values.length; index += 1) {
|
|
333
|
+
const value = values[index];
|
|
334
|
+
if (typeof value !== "number") {
|
|
335
|
+
return freezeArray(values);
|
|
336
|
+
}
|
|
337
|
+
packed[index] = value;
|
|
338
|
+
}
|
|
339
|
+
return packed;
|
|
340
|
+
}
|
|
341
|
+
return freezeArray(values);
|
|
342
|
+
};
|
|
343
|
+
var hasNullValue = (values) => {
|
|
344
|
+
columnOperationCounters.nullableChecks += values.length;
|
|
345
|
+
for (const value of values) {
|
|
346
|
+
if (value === null) {
|
|
347
|
+
return true;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return false;
|
|
351
|
+
};
|
|
352
|
+
var validateExplicitColumnTypes = (columns, columnTypes) => {
|
|
353
|
+
if (columnTypes === void 0) {
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
const knownColumns = new Set(columns);
|
|
357
|
+
for (const column of Object.keys(columnTypes)) {
|
|
358
|
+
if (!knownColumns.has(column)) {
|
|
359
|
+
throw new JsonFrameOptionError(
|
|
360
|
+
"`options.columnTypes` keys must match parsed column names.",
|
|
361
|
+
`columnTypes.${column}`,
|
|
362
|
+
columnTypes[column]
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
var resolveSchemaTypeByColumn = (frame) => {
|
|
368
|
+
if (frame.tableSchema === void 0) {
|
|
369
|
+
return /* @__PURE__ */ new Map();
|
|
370
|
+
}
|
|
371
|
+
const schemaTypes = /* @__PURE__ */ new Map();
|
|
372
|
+
for (const field of frame.tableSchema.fields) {
|
|
373
|
+
if (frame.columns.includes(field.name)) {
|
|
374
|
+
schemaTypes.set(field.name, mapTableSchemaFieldType(field));
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
return schemaTypes;
|
|
378
|
+
};
|
|
379
|
+
var materializeColumn = (column) => {
|
|
380
|
+
columnOperationCounters.materializeColumnCalls += 1;
|
|
381
|
+
columnOperationCounters.materializedCells += column.length;
|
|
382
|
+
return Array.isArray(column) ? freezeArray(column) : freezeArray(Array.from(column));
|
|
383
|
+
};
|
|
384
|
+
var getStoredColumnValue = (column, position) => {
|
|
385
|
+
columnOperationCounters.scalarReads += 1;
|
|
386
|
+
return column[position];
|
|
387
|
+
};
|
|
388
|
+
var rebuildStoredColumn = (column, positions) => {
|
|
389
|
+
const rebuilt = new Array(positions.length);
|
|
390
|
+
for (let index = 0; index < positions.length; index += 1) {
|
|
391
|
+
rebuilt[index] = getStoredColumnValue(column, positions[index]);
|
|
392
|
+
}
|
|
393
|
+
columnOperationCounters.rebuiltCells += positions.length;
|
|
394
|
+
return rebuilt;
|
|
395
|
+
};
|
|
396
|
+
var materializeFrameData = (columns, data) => {
|
|
397
|
+
const materialized = /* @__PURE__ */ new Map();
|
|
398
|
+
for (const column of columns) {
|
|
399
|
+
const stored = data.get(column);
|
|
400
|
+
if (stored === void 0) {
|
|
401
|
+
throw new JsonFrameValidationError("Stored frame data is missing a declared column.", {
|
|
402
|
+
path: "$",
|
|
403
|
+
column
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
materialized.set(column, materializeColumn(stored));
|
|
407
|
+
}
|
|
408
|
+
return materialized;
|
|
409
|
+
};
|
|
410
|
+
var buildFrameState = (frame, options) => {
|
|
411
|
+
validateExplicitColumnTypes(frame.columns, options.columnTypes);
|
|
412
|
+
const schemaTypes = resolveSchemaTypeByColumn(frame);
|
|
413
|
+
const data = /* @__PURE__ */ new Map();
|
|
414
|
+
const columnInfo = /* @__PURE__ */ new Map();
|
|
415
|
+
for (let columnIndex = 0; columnIndex < frame.columns.length; columnIndex += 1) {
|
|
416
|
+
const column = frame.columns[columnIndex];
|
|
417
|
+
const values = frame.data.get(column);
|
|
418
|
+
if (values === void 0) {
|
|
419
|
+
throw new JsonFrameValidationError("Parsed frame data is missing a declared column.", {
|
|
420
|
+
orient: frame.orient,
|
|
421
|
+
column
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
const inferred = inferColumnType(values);
|
|
425
|
+
const resolvedType = schemaTypes.get(column) ?? options.columnTypes?.[column] ?? inferred.type;
|
|
426
|
+
if (schemaTypes.has(column) === false && options.columnTypes?.[column] !== void 0) {
|
|
427
|
+
validateColumnValuesForType({
|
|
428
|
+
column,
|
|
429
|
+
columnIndex,
|
|
430
|
+
values,
|
|
431
|
+
type: resolvedType,
|
|
432
|
+
orient: frame.orient,
|
|
433
|
+
index: frame.index
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
const info = freezeColumnInfo({ type: resolvedType, nullable: inferred.nullable });
|
|
437
|
+
columnInfo.set(column, info);
|
|
438
|
+
data.set(column, packColumn(values, info, options.packThreshold));
|
|
439
|
+
}
|
|
440
|
+
return {
|
|
441
|
+
columns: freezeArray(frame.columns),
|
|
442
|
+
index: freezeArray(frame.index),
|
|
443
|
+
indexKind: frame.indexKind,
|
|
444
|
+
data,
|
|
445
|
+
columnInfo,
|
|
446
|
+
...frame.tableSchema === void 0 ? {} : { tableSchema: frame.tableSchema },
|
|
447
|
+
...frame.tableIndexField === void 0 ? {} : { tableIndexField: frame.tableIndexField }
|
|
448
|
+
};
|
|
449
|
+
};
|
|
450
|
+
var createFrameStateFromRebuiltData = (frame, options) => {
|
|
451
|
+
const data = /* @__PURE__ */ new Map();
|
|
452
|
+
const columnInfo = /* @__PURE__ */ new Map();
|
|
453
|
+
for (const column of frame.columns) {
|
|
454
|
+
const values = frame.data.get(column);
|
|
455
|
+
if (values === void 0) {
|
|
456
|
+
throw new JsonFrameValidationError("Rebuilt frame data is missing a declared column.", {
|
|
457
|
+
path: "$",
|
|
458
|
+
column
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
const sourceInfo = frame.columnInfo.get(column);
|
|
462
|
+
if (sourceInfo === void 0) {
|
|
463
|
+
throw new JsonFrameValidationError("Rebuilt frame metadata is missing a declared column.", {
|
|
464
|
+
path: "$",
|
|
465
|
+
column
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
const info = freezeColumnInfo({
|
|
469
|
+
type: sourceInfo.type,
|
|
470
|
+
nullable: sourceInfo.nullable && hasNullValue(values)
|
|
471
|
+
});
|
|
472
|
+
columnInfo.set(column, info);
|
|
473
|
+
data.set(column, packColumn(values, info, options.packThreshold));
|
|
474
|
+
}
|
|
475
|
+
return {
|
|
476
|
+
columns: freezeArray(frame.columns),
|
|
477
|
+
index: freezeArray(frame.index),
|
|
478
|
+
indexKind: frame.indexKind,
|
|
479
|
+
data,
|
|
480
|
+
columnInfo,
|
|
481
|
+
...frame.tableSchema === void 0 ? {} : { tableSchema: frame.tableSchema },
|
|
482
|
+
...frame.tableIndexField === void 0 ? {} : { tableIndexField: frame.tableIndexField }
|
|
483
|
+
};
|
|
484
|
+
};
|
|
485
|
+
var createFrameState = (frame, options) => buildFrameState(frame, options);
|
|
486
|
+
|
|
487
|
+
// src/json.ts
|
|
488
|
+
var JSON_FRAME_MAX_DEPTH = 1e3;
|
|
489
|
+
var IDENTIFIER_PATTERN = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
490
|
+
var rootPath = (path) => ({ type: "root", path });
|
|
491
|
+
var isPlainObject = (value) => {
|
|
492
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
493
|
+
return false;
|
|
494
|
+
}
|
|
495
|
+
const prototype = Object.getPrototypeOf(value);
|
|
496
|
+
return prototype === Object.prototype || prototype === null;
|
|
497
|
+
};
|
|
498
|
+
var pathToString = (path) => {
|
|
499
|
+
const segments = [];
|
|
500
|
+
let current = path;
|
|
501
|
+
while (current !== void 0 && current.type !== "root") {
|
|
502
|
+
segments.push(current);
|
|
503
|
+
current = current.parent;
|
|
504
|
+
}
|
|
505
|
+
let formatted = current?.type === "root" ? current.path : "$";
|
|
506
|
+
for (let index = segments.length - 1; index >= 0; index -= 1) {
|
|
507
|
+
const segment = segments[index];
|
|
508
|
+
if (segment.type === "index") {
|
|
509
|
+
formatted += `[${segment.index}]`;
|
|
510
|
+
} else if (segment.type === "property") {
|
|
511
|
+
formatted += IDENTIFIER_PATTERN.test(segment.key) ? `.${segment.key}` : `[${JSON.stringify(segment.key)}]`;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
return formatted;
|
|
515
|
+
};
|
|
516
|
+
var childIndexPath = (parent, index) => ({ parent, type: "index", index });
|
|
517
|
+
var childPropertyPath = (parent, key) => ({ parent, type: "property", key });
|
|
518
|
+
var throwValidation = (message, path, value, orient) => {
|
|
519
|
+
throw new JsonFrameValidationError(message, {
|
|
520
|
+
...orient === void 0 ? {} : { orient },
|
|
521
|
+
path: pathToString(path),
|
|
522
|
+
value
|
|
523
|
+
});
|
|
524
|
+
};
|
|
525
|
+
var cloneScalar = (value, path, orient) => {
|
|
526
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") {
|
|
527
|
+
return value;
|
|
528
|
+
}
|
|
529
|
+
if (typeof value === "number") {
|
|
530
|
+
if (!Number.isFinite(value)) {
|
|
531
|
+
throwValidation("Numbers must be finite JSON values.", path, value, orient);
|
|
532
|
+
}
|
|
533
|
+
return value;
|
|
534
|
+
}
|
|
535
|
+
if (typeof value === "undefined" || typeof value === "function" || typeof value === "symbol" || typeof value === "bigint") {
|
|
536
|
+
throwValidation("Input must contain only JSON-compatible values.", path, value, orient);
|
|
537
|
+
}
|
|
538
|
+
return void 0;
|
|
539
|
+
};
|
|
540
|
+
var createFrame = (source, path, depth, ancestors, orient) => {
|
|
541
|
+
const scalar = cloneScalar(source, path, orient);
|
|
542
|
+
if (scalar !== void 0) {
|
|
543
|
+
return { value: scalar };
|
|
544
|
+
}
|
|
545
|
+
if (depth > JSON_FRAME_MAX_DEPTH) {
|
|
546
|
+
throwValidation(
|
|
547
|
+
`JSON input exceeds the maximum supported nesting depth of ${JSON_FRAME_MAX_DEPTH}.`,
|
|
548
|
+
path,
|
|
549
|
+
source,
|
|
550
|
+
orient
|
|
551
|
+
);
|
|
552
|
+
}
|
|
553
|
+
if (Array.isArray(source)) {
|
|
554
|
+
if (ancestors.has(source)) {
|
|
555
|
+
throwValidation("Input contains a cyclic array.", path, source, orient);
|
|
556
|
+
}
|
|
557
|
+
const target2 = [];
|
|
558
|
+
ancestors.add(source);
|
|
559
|
+
return { value: target2, frame: { kind: "array", source, target: target2, path, depth, index: 0 } };
|
|
560
|
+
}
|
|
561
|
+
if (!isPlainObject(source)) {
|
|
562
|
+
throwValidation("Input objects must be plain JSON objects or arrays.", path, source, orient);
|
|
563
|
+
}
|
|
564
|
+
const objectSource = source;
|
|
565
|
+
if (ancestors.has(objectSource)) {
|
|
566
|
+
throwValidation("Input contains a cyclic object.", path, objectSource, orient);
|
|
567
|
+
}
|
|
568
|
+
const target = /* @__PURE__ */ Object.create(null);
|
|
569
|
+
ancestors.add(objectSource);
|
|
570
|
+
return {
|
|
571
|
+
value: target,
|
|
572
|
+
frame: { kind: "object", source: objectSource, target, keys: Object.keys(objectSource), path, depth, index: 0 }
|
|
573
|
+
};
|
|
574
|
+
};
|
|
575
|
+
var cloneJsonCompatible = (value, orient, path = "$") => {
|
|
576
|
+
const ancestors = /* @__PURE__ */ new Set();
|
|
577
|
+
const root = createFrame(value, rootPath(path), 0, ancestors, orient);
|
|
578
|
+
const stack = root.frame === void 0 ? [] : [root.frame];
|
|
579
|
+
while (stack.length > 0) {
|
|
580
|
+
const frame = stack[stack.length - 1];
|
|
581
|
+
if (frame.kind === "array") {
|
|
582
|
+
if (frame.index >= frame.source.length) {
|
|
583
|
+
ancestors.delete(frame.source);
|
|
584
|
+
stack.pop();
|
|
585
|
+
continue;
|
|
586
|
+
}
|
|
587
|
+
const index = frame.index;
|
|
588
|
+
frame.index += 1;
|
|
589
|
+
const childPath2 = childIndexPath(frame.path, index);
|
|
590
|
+
if (!(index in frame.source)) {
|
|
591
|
+
throwValidation("Sparse arrays are not valid JSON input.", childPath2, frame.source, orient);
|
|
592
|
+
}
|
|
593
|
+
const child2 = createFrame(frame.source[index], childPath2, frame.depth + 1, ancestors, orient);
|
|
594
|
+
frame.target.push(child2.value);
|
|
595
|
+
if (child2.frame !== void 0) {
|
|
596
|
+
stack.push(child2.frame);
|
|
597
|
+
}
|
|
598
|
+
continue;
|
|
599
|
+
}
|
|
600
|
+
if (frame.index >= frame.keys.length) {
|
|
601
|
+
ancestors.delete(frame.source);
|
|
602
|
+
stack.pop();
|
|
603
|
+
continue;
|
|
604
|
+
}
|
|
605
|
+
const key = frame.keys[frame.index];
|
|
606
|
+
frame.index += 1;
|
|
607
|
+
const childPath = childPropertyPath(frame.path, key);
|
|
608
|
+
const child = createFrame(frame.source[key], childPath, frame.depth + 1, ancestors, orient);
|
|
609
|
+
frame.target[key] = child.value;
|
|
610
|
+
if (child.frame !== void 0) {
|
|
611
|
+
stack.push(child.frame);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
return root.value;
|
|
615
|
+
};
|
|
616
|
+
|
|
102
617
|
// src/export/payload.ts
|
|
103
618
|
var createRecord = () => /* @__PURE__ */ Object.create(null);
|
|
104
|
-
var
|
|
105
|
-
|
|
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) => {
|
|
619
|
+
var appendPath = (path, key) => `${path}[${JSON.stringify(key)}]`;
|
|
620
|
+
var cloneSchemaField = (field, name = field.name, path = "$.schema.fields[]") => {
|
|
118
621
|
const cloned = createRecord();
|
|
119
622
|
for (const [key, value] of Object.entries(field)) {
|
|
120
|
-
cloned[key] = key === "name" ? name : value === void 0 ? void 0 :
|
|
623
|
+
cloned[key] = key === "name" ? name : value === void 0 ? void 0 : cloneJsonCompatible(value, "table", appendPath(path, key));
|
|
121
624
|
}
|
|
122
625
|
return cloned;
|
|
123
626
|
};
|
|
@@ -128,10 +631,12 @@ var cloneSchema = (schema, fields, primaryKey) => {
|
|
|
128
631
|
if (key === "fields" || key === "primaryKey") {
|
|
129
632
|
continue;
|
|
130
633
|
}
|
|
131
|
-
cloned[key] = value === void 0 ? void 0 :
|
|
634
|
+
cloned[key] = value === void 0 ? void 0 : cloneJsonCompatible(value, "table", appendPath("$.schema", key));
|
|
132
635
|
}
|
|
133
636
|
}
|
|
134
|
-
cloned.fields = fields.map(
|
|
637
|
+
cloned.fields = fields.map(
|
|
638
|
+
(field, index) => cloneSchemaField(field, field.name, `$.schema.fields[${index}]`)
|
|
639
|
+
);
|
|
135
640
|
if (primaryKey !== void 0) {
|
|
136
641
|
cloned.primaryKey = [...primaryKey];
|
|
137
642
|
}
|
|
@@ -145,8 +650,9 @@ var mapColumnTypeToSchemaField = (name, info) => {
|
|
|
145
650
|
case "float":
|
|
146
651
|
return "number";
|
|
147
652
|
case "string":
|
|
148
|
-
case "categorical":
|
|
149
653
|
return "string";
|
|
654
|
+
case "categorical":
|
|
655
|
+
return "any";
|
|
150
656
|
case "boolean":
|
|
151
657
|
return "boolean";
|
|
152
658
|
case "datetime":
|
|
@@ -232,6 +738,22 @@ var resolveIndexFieldName = (state, options) => {
|
|
|
232
738
|
}
|
|
233
739
|
return indexField;
|
|
234
740
|
};
|
|
741
|
+
var assertUniqueTableIndexLabels = (index, indexField) => {
|
|
742
|
+
const seen = /* @__PURE__ */ new Map();
|
|
743
|
+
for (let rowIndex = 0; rowIndex < index.length; rowIndex += 1) {
|
|
744
|
+
const label = index[rowIndex];
|
|
745
|
+
if (seen.has(label)) {
|
|
746
|
+
throw new JsonFrameValidationError("Cannot export duplicate index labels as a table primary key.", {
|
|
747
|
+
orient: "table",
|
|
748
|
+
path: `$.data[${rowIndex}][${JSON.stringify(indexField)}]`,
|
|
749
|
+
row: rowIndex,
|
|
750
|
+
column: indexField,
|
|
751
|
+
value: label
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
seen.set(label, rowIndex);
|
|
755
|
+
}
|
|
756
|
+
};
|
|
235
757
|
var resolveIndexKeys = (state, orient) => {
|
|
236
758
|
const seenKeys = /* @__PURE__ */ new Map();
|
|
237
759
|
const keys = [];
|
|
@@ -301,19 +823,32 @@ var exportSplit = (state, materialized) => ({
|
|
|
301
823
|
});
|
|
302
824
|
var exportTable = (state, materialized, columnInfo, options) => {
|
|
303
825
|
const indexField = resolveIndexFieldName(state, options);
|
|
826
|
+
if (indexField !== void 0) {
|
|
827
|
+
assertUniqueTableIndexLabels(state.index, indexField);
|
|
828
|
+
}
|
|
304
829
|
const indexTemplate = getIndexFieldTemplate(state);
|
|
305
830
|
const dataTemplates = getDataFieldTemplates(state);
|
|
306
831
|
const fields = [];
|
|
307
832
|
if (indexField !== void 0) {
|
|
308
833
|
fields.push(
|
|
309
|
-
indexTemplate === void 0 ? { name: indexField, type: inferIndexFieldType(state.index) } : cloneSchemaField(indexTemplate, indexField)
|
|
834
|
+
indexTemplate === void 0 ? { name: indexField, type: inferIndexFieldType(state.index) } : cloneSchemaField(indexTemplate, indexField, "$.schema.fields[0]")
|
|
310
835
|
);
|
|
311
836
|
}
|
|
312
837
|
for (let columnIndex = 0; columnIndex < state.columns.length; columnIndex += 1) {
|
|
313
838
|
const column = state.columns[columnIndex];
|
|
314
839
|
const template = dataTemplates[columnIndex];
|
|
840
|
+
if (template === void 0) {
|
|
841
|
+
validateColumnValuesForType({
|
|
842
|
+
column,
|
|
843
|
+
columnIndex,
|
|
844
|
+
values: materialized.get(column) ?? [],
|
|
845
|
+
type: columnInfo.get(column).type,
|
|
846
|
+
orient: "table",
|
|
847
|
+
index: state.index
|
|
848
|
+
});
|
|
849
|
+
}
|
|
315
850
|
fields.push(
|
|
316
|
-
template === void 0 ? mapColumnTypeToSchemaField(column, columnInfo.get(column)) : cloneSchemaField(template, column)
|
|
851
|
+
template === void 0 ? mapColumnTypeToSchemaField(column, columnInfo.get(column)) : cloneSchemaField(template, column, `$.schema.fields[${fields.length}]`)
|
|
317
852
|
);
|
|
318
853
|
}
|
|
319
854
|
const data = [];
|
|
@@ -333,185 +868,6 @@ var exportTable = (state, materialized, columnInfo, options) => {
|
|
|
333
868
|
};
|
|
334
869
|
};
|
|
335
870
|
|
|
336
|
-
// src/frame/column.ts
|
|
337
|
-
var INT32_MIN = -2147483648;
|
|
338
|
-
var INT32_MAX = 2147483647;
|
|
339
|
-
var freezeArray = (values) => Object.freeze([...values]);
|
|
340
|
-
var freezeColumnInfo = (info) => Object.freeze({ ...info });
|
|
341
|
-
var hasCategoricalMetadata = (field) => field.constraints?.enum !== void 0 || field.ordered === true || field.extDtype === "category";
|
|
342
|
-
var mapTableSchemaFieldType = (field) => {
|
|
343
|
-
if (hasCategoricalMetadata(field)) {
|
|
344
|
-
return "categorical";
|
|
345
|
-
}
|
|
346
|
-
switch (field.type) {
|
|
347
|
-
case "boolean":
|
|
348
|
-
return "boolean";
|
|
349
|
-
case "integer":
|
|
350
|
-
case "year":
|
|
351
|
-
return "integer";
|
|
352
|
-
case "number":
|
|
353
|
-
return "float";
|
|
354
|
-
case "date":
|
|
355
|
-
case "datetime":
|
|
356
|
-
return "datetime";
|
|
357
|
-
case "string":
|
|
358
|
-
return "string";
|
|
359
|
-
case "any":
|
|
360
|
-
return "unknown";
|
|
361
|
-
default:
|
|
362
|
-
return "unknown";
|
|
363
|
-
}
|
|
364
|
-
};
|
|
365
|
-
var inferColumnType = (values) => {
|
|
366
|
-
let nullable = false;
|
|
367
|
-
let sawBoolean = false;
|
|
368
|
-
let sawString = false;
|
|
369
|
-
let sawInteger = false;
|
|
370
|
-
let sawFloat = false;
|
|
371
|
-
let sawStructured = false;
|
|
372
|
-
for (const value of values) {
|
|
373
|
-
if (value === null) {
|
|
374
|
-
nullable = true;
|
|
375
|
-
continue;
|
|
376
|
-
}
|
|
377
|
-
if (typeof value === "boolean") {
|
|
378
|
-
sawBoolean = true;
|
|
379
|
-
continue;
|
|
380
|
-
}
|
|
381
|
-
if (typeof value === "string") {
|
|
382
|
-
sawString = true;
|
|
383
|
-
continue;
|
|
384
|
-
}
|
|
385
|
-
if (typeof value === "number") {
|
|
386
|
-
if (Number.isInteger(value)) {
|
|
387
|
-
sawInteger = true;
|
|
388
|
-
} else {
|
|
389
|
-
sawFloat = true;
|
|
390
|
-
}
|
|
391
|
-
continue;
|
|
392
|
-
}
|
|
393
|
-
sawStructured = true;
|
|
394
|
-
}
|
|
395
|
-
const nonNullKinds = [sawBoolean, sawString, sawInteger || sawFloat, sawStructured].filter(Boolean).length;
|
|
396
|
-
if (nonNullKinds === 0) {
|
|
397
|
-
return freezeColumnInfo({ type: "unknown", nullable });
|
|
398
|
-
}
|
|
399
|
-
if (sawStructured || nonNullKinds > 1 || sawBoolean && (sawString || sawInteger || sawFloat)) {
|
|
400
|
-
return freezeColumnInfo({ type: "mixed", nullable });
|
|
401
|
-
}
|
|
402
|
-
if (sawString) {
|
|
403
|
-
return freezeColumnInfo({ type: "string", nullable });
|
|
404
|
-
}
|
|
405
|
-
if (sawBoolean) {
|
|
406
|
-
return freezeColumnInfo({ type: "boolean", nullable });
|
|
407
|
-
}
|
|
408
|
-
if (sawFloat) {
|
|
409
|
-
return freezeColumnInfo({ type: "float", nullable });
|
|
410
|
-
}
|
|
411
|
-
return freezeColumnInfo({ type: "integer", nullable });
|
|
412
|
-
};
|
|
413
|
-
var packColumn = (values, info, packThreshold) => {
|
|
414
|
-
if (packThreshold === 0 || values.length < packThreshold || info.nullable) {
|
|
415
|
-
return freezeArray(values);
|
|
416
|
-
}
|
|
417
|
-
if (info.type === "integer") {
|
|
418
|
-
const packed = new Int32Array(values.length);
|
|
419
|
-
for (let index = 0; index < values.length; index += 1) {
|
|
420
|
-
const value = values[index];
|
|
421
|
-
if (typeof value !== "number" || !Number.isInteger(value) || value < INT32_MIN || value > INT32_MAX) {
|
|
422
|
-
return freezeArray(values);
|
|
423
|
-
}
|
|
424
|
-
packed[index] = value;
|
|
425
|
-
}
|
|
426
|
-
return packed;
|
|
427
|
-
}
|
|
428
|
-
if (info.type === "float") {
|
|
429
|
-
const packed = new Float64Array(values.length);
|
|
430
|
-
for (let index = 0; index < values.length; index += 1) {
|
|
431
|
-
const value = values[index];
|
|
432
|
-
if (typeof value !== "number") {
|
|
433
|
-
return freezeArray(values);
|
|
434
|
-
}
|
|
435
|
-
packed[index] = value;
|
|
436
|
-
}
|
|
437
|
-
return packed;
|
|
438
|
-
}
|
|
439
|
-
return freezeArray(values);
|
|
440
|
-
};
|
|
441
|
-
var validateExplicitColumnTypes = (columns, columnTypes) => {
|
|
442
|
-
if (columnTypes === void 0) {
|
|
443
|
-
return;
|
|
444
|
-
}
|
|
445
|
-
const knownColumns = new Set(columns);
|
|
446
|
-
for (const column of Object.keys(columnTypes)) {
|
|
447
|
-
if (!knownColumns.has(column)) {
|
|
448
|
-
throw new JsonFrameOptionError(
|
|
449
|
-
"`options.columnTypes` keys must match parsed column names.",
|
|
450
|
-
`columnTypes.${column}`,
|
|
451
|
-
columnTypes[column]
|
|
452
|
-
);
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
};
|
|
456
|
-
var resolveSchemaTypeByColumn = (frame) => {
|
|
457
|
-
if (frame.tableSchema === void 0) {
|
|
458
|
-
return /* @__PURE__ */ new Map();
|
|
459
|
-
}
|
|
460
|
-
const schemaTypes = /* @__PURE__ */ new Map();
|
|
461
|
-
for (const field of frame.tableSchema.fields) {
|
|
462
|
-
if (frame.columns.includes(field.name)) {
|
|
463
|
-
schemaTypes.set(field.name, mapTableSchemaFieldType(field));
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
return schemaTypes;
|
|
467
|
-
};
|
|
468
|
-
var materializeColumn = (column) => Array.isArray(column) ? freezeArray(column) : freezeArray(Array.from(column));
|
|
469
|
-
var materializeFrameData = (columns, data) => {
|
|
470
|
-
const materialized = /* @__PURE__ */ new Map();
|
|
471
|
-
for (const column of columns) {
|
|
472
|
-
const stored = data.get(column);
|
|
473
|
-
if (stored === void 0) {
|
|
474
|
-
throw new JsonFrameValidationError("Stored frame data is missing a declared column.", {
|
|
475
|
-
path: "$",
|
|
476
|
-
column
|
|
477
|
-
});
|
|
478
|
-
}
|
|
479
|
-
materialized.set(column, materializeColumn(stored));
|
|
480
|
-
}
|
|
481
|
-
return materialized;
|
|
482
|
-
};
|
|
483
|
-
var buildFrameState = (frame, options) => {
|
|
484
|
-
validateExplicitColumnTypes(frame.columns, options.columnTypes);
|
|
485
|
-
const schemaTypes = resolveSchemaTypeByColumn(frame);
|
|
486
|
-
const data = /* @__PURE__ */ new Map();
|
|
487
|
-
const columnInfo = /* @__PURE__ */ new Map();
|
|
488
|
-
for (const column of frame.columns) {
|
|
489
|
-
const values = frame.data.get(column);
|
|
490
|
-
if (values === void 0) {
|
|
491
|
-
throw new JsonFrameValidationError("Parsed frame data is missing a declared column.", {
|
|
492
|
-
orient: frame.orient,
|
|
493
|
-
column
|
|
494
|
-
});
|
|
495
|
-
}
|
|
496
|
-
const inferred = inferColumnType(values);
|
|
497
|
-
const resolvedType = schemaTypes.get(column) ?? options.columnTypes?.[column] ?? inferred.type;
|
|
498
|
-
const info = freezeColumnInfo({ type: resolvedType, nullable: inferred.nullable });
|
|
499
|
-
columnInfo.set(column, info);
|
|
500
|
-
data.set(column, packColumn(values, info, options.packThreshold));
|
|
501
|
-
}
|
|
502
|
-
return {
|
|
503
|
-
columns: freezeArray(frame.columns),
|
|
504
|
-
index: freezeArray(frame.index),
|
|
505
|
-
indexKind: frame.indexKind,
|
|
506
|
-
data,
|
|
507
|
-
columnInfo,
|
|
508
|
-
...frame.tableSchema === void 0 ? {} : { tableSchema: frame.tableSchema },
|
|
509
|
-
...frame.tableIndexField === void 0 ? {} : { tableIndexField: frame.tableIndexField }
|
|
510
|
-
};
|
|
511
|
-
};
|
|
512
|
-
var createFrameStateFromData = (frame, options) => buildFrameState(frame, options);
|
|
513
|
-
var createFrameState = (frame, options) => buildFrameState(frame, options);
|
|
514
|
-
|
|
515
871
|
// src/frame/DataFrame.ts
|
|
516
872
|
var hasOwn = Object.prototype.hasOwnProperty;
|
|
517
873
|
var frameStateByInstance = /* @__PURE__ */ new WeakMap();
|
|
@@ -531,7 +887,7 @@ var cloneSchema2 = (schema, fields, primaryKey) => {
|
|
|
531
887
|
}
|
|
532
888
|
return Object.freeze(cloned);
|
|
533
889
|
};
|
|
534
|
-
var _state, _packThreshold, _DataFrame_instances, assertRowPosition_fn, materializedData_fn, createRow_fn,
|
|
890
|
+
var _state, _packThreshold, _DataFrame_instances, assertRowPosition_fn, materializedData_fn, createRow_fn, columnInfoOverrides_fn, rebuild_fn, selectSchema_fn, renameSchema_fn, resetIndexSchema_fn;
|
|
535
891
|
var DataFrame = class {
|
|
536
892
|
constructor(state, packThreshold) {
|
|
537
893
|
__privateAdd(this, _DataFrame_instances);
|
|
@@ -593,18 +949,22 @@ var DataFrame = class {
|
|
|
593
949
|
}
|
|
594
950
|
row(position) {
|
|
595
951
|
__privateMethod(this, _DataFrame_instances, assertRowPosition_fn).call(this, position);
|
|
596
|
-
return __privateMethod(this, _DataFrame_instances, createRow_fn).call(this,
|
|
952
|
+
return __privateMethod(this, _DataFrame_instances, createRow_fn).call(this, position);
|
|
597
953
|
}
|
|
598
954
|
rows() {
|
|
599
|
-
const
|
|
600
|
-
const rows = __privateGet(this, _state).index.map((_, position) => __privateMethod(this, _DataFrame_instances, createRow_fn).call(this, materialized, position));
|
|
955
|
+
const rows = __privateGet(this, _state).index.map((_, position) => __privateMethod(this, _DataFrame_instances, createRow_fn).call(this, position));
|
|
601
956
|
return freezeArray2(rows);
|
|
602
957
|
}
|
|
603
958
|
filter(predicate) {
|
|
604
|
-
|
|
959
|
+
if (typeof predicate !== "function") {
|
|
960
|
+
throw new JsonFrameValidationError("`filter` predicate must be a function.", {
|
|
961
|
+
path: "$.predicate",
|
|
962
|
+
value: predicate
|
|
963
|
+
});
|
|
964
|
+
}
|
|
605
965
|
const keptPositions = [];
|
|
606
966
|
for (let position = 0; position < this.length; position += 1) {
|
|
607
|
-
if (predicate(__privateMethod(this, _DataFrame_instances, createRow_fn).call(this,
|
|
967
|
+
if (predicate(__privateMethod(this, _DataFrame_instances, createRow_fn).call(this, position), __privateGet(this, _state).index[position], position)) {
|
|
608
968
|
keptPositions.push(position);
|
|
609
969
|
}
|
|
610
970
|
}
|
|
@@ -621,11 +981,16 @@ var DataFrame = class {
|
|
|
621
981
|
});
|
|
622
982
|
}
|
|
623
983
|
sort(compare) {
|
|
624
|
-
|
|
984
|
+
if (typeof compare !== "function") {
|
|
985
|
+
throw new JsonFrameValidationError("`sort` compare must be a function.", {
|
|
986
|
+
path: "$.compare",
|
|
987
|
+
value: compare
|
|
988
|
+
});
|
|
989
|
+
}
|
|
625
990
|
const ordering = __privateGet(this, _state).index.map((indexLabel, position) => ({
|
|
626
991
|
indexLabel,
|
|
627
992
|
position,
|
|
628
|
-
row: __privateMethod(this, _DataFrame_instances, createRow_fn).call(this,
|
|
993
|
+
row: __privateMethod(this, _DataFrame_instances, createRow_fn).call(this, position)
|
|
629
994
|
}));
|
|
630
995
|
ordering.sort((left, right) => {
|
|
631
996
|
const result = compare(left.row, right.row, left.indexLabel, right.indexLabel, left.position, right.position);
|
|
@@ -673,7 +1038,26 @@ var DataFrame = class {
|
|
|
673
1038
|
});
|
|
674
1039
|
}
|
|
675
1040
|
rename(mapping) {
|
|
676
|
-
|
|
1041
|
+
if (mapping === null || typeof mapping !== "object" || Array.isArray(mapping)) {
|
|
1042
|
+
throw new JsonFrameValidationError("`rename` mapping must be a non-array object.", {
|
|
1043
|
+
path: "$.mapping",
|
|
1044
|
+
value: mapping
|
|
1045
|
+
});
|
|
1046
|
+
}
|
|
1047
|
+
const nextColumns = __privateGet(this, _state).columns.map((column) => {
|
|
1048
|
+
if (!hasOwn.call(mapping, column)) {
|
|
1049
|
+
return column;
|
|
1050
|
+
}
|
|
1051
|
+
const renamedColumn = mapping[column];
|
|
1052
|
+
if (typeof renamedColumn !== "string") {
|
|
1053
|
+
throw new JsonFrameValidationError("`rename` mapping values must be strings for existing columns.", {
|
|
1054
|
+
path: `$.mapping[${JSON.stringify(column)}]`,
|
|
1055
|
+
column,
|
|
1056
|
+
value: renamedColumn
|
|
1057
|
+
});
|
|
1058
|
+
}
|
|
1059
|
+
return renamedColumn;
|
|
1060
|
+
});
|
|
677
1061
|
const seen = /* @__PURE__ */ new Set();
|
|
678
1062
|
for (let position = 0; position < nextColumns.length; position += 1) {
|
|
679
1063
|
const column = nextColumns[position];
|
|
@@ -719,19 +1103,35 @@ assertRowPosition_fn = function(position) {
|
|
|
719
1103
|
materializedData_fn = function() {
|
|
720
1104
|
return materializeFrameData(__privateGet(this, _state).columns, __privateGet(this, _state).data);
|
|
721
1105
|
};
|
|
722
|
-
createRow_fn = function(
|
|
1106
|
+
createRow_fn = function(position) {
|
|
723
1107
|
const row = /* @__PURE__ */ Object.create(null);
|
|
724
1108
|
for (const column of __privateGet(this, _state).columns) {
|
|
725
|
-
|
|
1109
|
+
const stored = __privateGet(this, _state).data.get(column);
|
|
1110
|
+
if (stored === void 0) {
|
|
1111
|
+
throw new JsonFrameValidationError("Stored frame data is missing a declared column.", {
|
|
1112
|
+
path: "$",
|
|
1113
|
+
column
|
|
1114
|
+
});
|
|
1115
|
+
}
|
|
1116
|
+
row[column] = getStoredColumnValue(stored, position);
|
|
726
1117
|
}
|
|
727
1118
|
return Object.freeze(row);
|
|
728
1119
|
};
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
1120
|
+
columnInfoOverrides_fn = function(columns, sourceColumns) {
|
|
1121
|
+
const columnInfo = /* @__PURE__ */ new Map();
|
|
1122
|
+
for (let position = 0; position < columns.length; position += 1) {
|
|
1123
|
+
const column = columns[position];
|
|
1124
|
+
const sourceColumn = sourceColumns[position];
|
|
1125
|
+
const sourceInfo = __privateGet(this, _state).columnInfo.get(sourceColumn);
|
|
1126
|
+
if (sourceInfo === void 0) {
|
|
1127
|
+
throw new JsonFrameValidationError("Stored frame metadata is missing a declared column.", {
|
|
1128
|
+
path: "$",
|
|
1129
|
+
column: sourceColumn
|
|
1130
|
+
});
|
|
1131
|
+
}
|
|
1132
|
+
columnInfo.set(column, sourceInfo);
|
|
1133
|
+
}
|
|
1134
|
+
return columnInfo;
|
|
735
1135
|
};
|
|
736
1136
|
rebuild_fn = function({
|
|
737
1137
|
columns,
|
|
@@ -741,31 +1141,31 @@ rebuild_fn = function({
|
|
|
741
1141
|
indexKind,
|
|
742
1142
|
schema
|
|
743
1143
|
}) {
|
|
744
|
-
const materialized = __privateMethod(this, _DataFrame_instances, materializedData_fn).call(this);
|
|
745
1144
|
const nextData = /* @__PURE__ */ new Map();
|
|
1145
|
+
const nextColumnInfo = __privateMethod(this, _DataFrame_instances, columnInfoOverrides_fn).call(this, columns, sourceColumns);
|
|
746
1146
|
for (let columnIndex = 0; columnIndex < columns.length; columnIndex += 1) {
|
|
747
1147
|
const column = columns[columnIndex];
|
|
748
|
-
const
|
|
749
|
-
if (
|
|
1148
|
+
const sourceStoredColumn = __privateGet(this, _state).data.get(sourceColumns[columnIndex]);
|
|
1149
|
+
if (sourceStoredColumn === void 0) {
|
|
750
1150
|
throw new JsonFrameValidationError("Stored frame data is missing a declared column.", {
|
|
751
1151
|
path: "$",
|
|
752
1152
|
column
|
|
753
1153
|
});
|
|
754
1154
|
}
|
|
755
|
-
nextData.set(column,
|
|
1155
|
+
nextData.set(column, rebuildStoredColumn(sourceStoredColumn, positions));
|
|
756
1156
|
}
|
|
757
|
-
const state =
|
|
1157
|
+
const state = createFrameStateFromRebuiltData(
|
|
758
1158
|
{
|
|
759
1159
|
columns,
|
|
760
1160
|
index,
|
|
761
1161
|
indexKind,
|
|
762
1162
|
data: nextData,
|
|
1163
|
+
columnInfo: nextColumnInfo,
|
|
763
1164
|
...schema.tableSchema === void 0 ? {} : { tableSchema: schema.tableSchema },
|
|
764
1165
|
...schema.tableIndexField === void 0 ? {} : { tableIndexField: schema.tableIndexField }
|
|
765
1166
|
},
|
|
766
1167
|
{
|
|
767
|
-
packThreshold: __privateGet(this, _packThreshold)
|
|
768
|
-
columnTypes: __privateMethod(this, _DataFrame_instances, columnTypeOverrides_fn).call(this, columns, sourceColumns)
|
|
1168
|
+
packThreshold: __privateGet(this, _packThreshold)
|
|
769
1169
|
}
|
|
770
1170
|
);
|
|
771
1171
|
return createDataFrame(state, __privateGet(this, _packThreshold));
|
|
@@ -933,11 +1333,11 @@ var normalizeFromOrientOptions = (options) => {
|
|
|
933
1333
|
|
|
934
1334
|
// src/parse/parse.ts
|
|
935
1335
|
var hasOwn2 = Object.prototype.hasOwnProperty;
|
|
936
|
-
var
|
|
1336
|
+
var IDENTIFIER_PATTERN2 = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
937
1337
|
var freezeArray3 = (values) => Object.freeze([...values]);
|
|
938
|
-
var appendPropertyPath = (path, key) =>
|
|
1338
|
+
var appendPropertyPath = (path, key) => IDENTIFIER_PATTERN2.test(key) ? `${path}.${key}` : `${path}[${JSON.stringify(key)}]`;
|
|
939
1339
|
var appendIndexPath = (path, index) => `${path}[${index}]`;
|
|
940
|
-
var
|
|
1340
|
+
var isPlainObject2 = (value) => {
|
|
941
1341
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
942
1342
|
return false;
|
|
943
1343
|
}
|
|
@@ -957,6 +1357,18 @@ var assertSupportedIndexLabel = (value, orient, path) => {
|
|
|
957
1357
|
value
|
|
958
1358
|
});
|
|
959
1359
|
};
|
|
1360
|
+
var assertUniqueTablePrimaryKeyLabel = (seen, label, row, column, path) => {
|
|
1361
|
+
if (seen.has(label)) {
|
|
1362
|
+
throw new JsonFrameValidationError("Table primary-key values must be unique.", {
|
|
1363
|
+
orient: "table",
|
|
1364
|
+
path,
|
|
1365
|
+
row,
|
|
1366
|
+
column,
|
|
1367
|
+
value: label
|
|
1368
|
+
});
|
|
1369
|
+
}
|
|
1370
|
+
seen.set(label, row);
|
|
1371
|
+
};
|
|
960
1372
|
var assertUniqueStringColumns = (values, orient, path) => {
|
|
961
1373
|
const columns = [];
|
|
962
1374
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -1014,52 +1426,6 @@ var finalizeFrame = ({
|
|
|
1014
1426
|
...tableIndexField === void 0 ? {} : { tableIndexField }
|
|
1015
1427
|
};
|
|
1016
1428
|
};
|
|
1017
|
-
var validateJsonCompatible = (value, path = "$", stack = /* @__PURE__ */ new Set()) => {
|
|
1018
|
-
if (value === null || typeof value === "string" || typeof value === "boolean") {
|
|
1019
|
-
return value;
|
|
1020
|
-
}
|
|
1021
|
-
if (typeof value === "number") {
|
|
1022
|
-
if (!Number.isFinite(value)) {
|
|
1023
|
-
throw new JsonFrameValidationError("Numbers must be finite JSON values.", { path, value });
|
|
1024
|
-
}
|
|
1025
|
-
return value;
|
|
1026
|
-
}
|
|
1027
|
-
if (typeof value === "undefined" || typeof value === "function" || typeof value === "symbol" || typeof value === "bigint") {
|
|
1028
|
-
throw new JsonFrameValidationError("Input must contain only JSON-compatible values.", { path, value });
|
|
1029
|
-
}
|
|
1030
|
-
if (Array.isArray(value)) {
|
|
1031
|
-
if (stack.has(value)) {
|
|
1032
|
-
throw new JsonFrameValidationError("Input contains a cyclic array.", { path, value });
|
|
1033
|
-
}
|
|
1034
|
-
stack.add(value);
|
|
1035
|
-
const normalized2 = [];
|
|
1036
|
-
for (let index = 0; index < value.length; index += 1) {
|
|
1037
|
-
if (!(index in value)) {
|
|
1038
|
-
stack.delete(value);
|
|
1039
|
-
throw new JsonFrameValidationError("Sparse arrays are not valid JSON input.", {
|
|
1040
|
-
path: appendIndexPath(path, index),
|
|
1041
|
-
value
|
|
1042
|
-
});
|
|
1043
|
-
}
|
|
1044
|
-
normalized2.push(validateJsonCompatible(value[index], appendIndexPath(path, index), stack));
|
|
1045
|
-
}
|
|
1046
|
-
stack.delete(value);
|
|
1047
|
-
return normalized2;
|
|
1048
|
-
}
|
|
1049
|
-
if (!isPlainObject(value)) {
|
|
1050
|
-
throw new JsonFrameValidationError("Input objects must be plain JSON objects or arrays.", { path, value });
|
|
1051
|
-
}
|
|
1052
|
-
if (stack.has(value)) {
|
|
1053
|
-
throw new JsonFrameValidationError("Input contains a cyclic object.", { path, value });
|
|
1054
|
-
}
|
|
1055
|
-
stack.add(value);
|
|
1056
|
-
const normalized = /* @__PURE__ */ Object.create(null);
|
|
1057
|
-
for (const [key, entryValue] of Object.entries(value)) {
|
|
1058
|
-
normalized[key] = validateJsonCompatible(entryValue, appendPropertyPath(path, key), stack);
|
|
1059
|
-
}
|
|
1060
|
-
stack.delete(value);
|
|
1061
|
-
return normalized;
|
|
1062
|
-
};
|
|
1063
1429
|
var detectOrient = (value) => {
|
|
1064
1430
|
if (Array.isArray(value)) {
|
|
1065
1431
|
if (value.length === 0) {
|
|
@@ -1071,7 +1437,7 @@ var detectOrient = (value) => {
|
|
|
1071
1437
|
if (value.every((entry) => Array.isArray(entry))) {
|
|
1072
1438
|
return "values";
|
|
1073
1439
|
}
|
|
1074
|
-
if (value.every((entry) =>
|
|
1440
|
+
if (value.every((entry) => isPlainObject2(entry))) {
|
|
1075
1441
|
return "records";
|
|
1076
1442
|
}
|
|
1077
1443
|
throw new JsonFrameValidationError("Auto detection requires a non-empty array of row objects or row arrays.", {
|
|
@@ -1079,20 +1445,20 @@ var detectOrient = (value) => {
|
|
|
1079
1445
|
value
|
|
1080
1446
|
});
|
|
1081
1447
|
}
|
|
1082
|
-
if (!
|
|
1448
|
+
if (!isPlainObject2(value)) {
|
|
1083
1449
|
throw new JsonFrameValidationError("Auto detection requires a JSON array or object payload.", {
|
|
1084
1450
|
path: "$",
|
|
1085
1451
|
value
|
|
1086
1452
|
});
|
|
1087
1453
|
}
|
|
1088
|
-
if (
|
|
1454
|
+
if (isPlainObject2(value.schema) && Array.isArray(value.data)) {
|
|
1089
1455
|
return "table";
|
|
1090
1456
|
}
|
|
1091
1457
|
if (Array.isArray(value.columns) && Array.isArray(value.data) && (value.index === void 0 || Array.isArray(value.index))) {
|
|
1092
1458
|
return "split";
|
|
1093
1459
|
}
|
|
1094
1460
|
const keys = Object.keys(value);
|
|
1095
|
-
if (keys.length === 0 || keys.every((key) =>
|
|
1461
|
+
if (keys.length === 0 || keys.every((key) => isPlainObject2(value[key]))) {
|
|
1096
1462
|
throw new AmbiguousOrientError("Auto detection cannot distinguish between index and columns payloads.", [
|
|
1097
1463
|
"index",
|
|
1098
1464
|
"columns"
|
|
@@ -1114,7 +1480,7 @@ var parseRecords = (value, orient) => {
|
|
|
1114
1480
|
for (let rowIndex = 0; rowIndex < value.length; rowIndex += 1) {
|
|
1115
1481
|
const row = value[rowIndex];
|
|
1116
1482
|
const rowPath = appendIndexPath("$", rowIndex);
|
|
1117
|
-
if (!
|
|
1483
|
+
if (!isPlainObject2(row)) {
|
|
1118
1484
|
throw new JsonFrameValidationError("`records` rows must be JSON objects.", {
|
|
1119
1485
|
orient,
|
|
1120
1486
|
path: rowPath,
|
|
@@ -1143,7 +1509,7 @@ var parseRecords = (value, orient) => {
|
|
|
1143
1509
|
});
|
|
1144
1510
|
};
|
|
1145
1511
|
var parseIndex = (value, orient) => {
|
|
1146
|
-
if (!
|
|
1512
|
+
if (!isPlainObject2(value)) {
|
|
1147
1513
|
throw new JsonFrameValidationError("`index` payloads must be objects keyed by index label.", {
|
|
1148
1514
|
orient,
|
|
1149
1515
|
path: "$",
|
|
@@ -1158,7 +1524,7 @@ var parseIndex = (value, orient) => {
|
|
|
1158
1524
|
const indexLabel = index[rowIndex];
|
|
1159
1525
|
const row = value[indexLabel];
|
|
1160
1526
|
const rowPath = appendPropertyPath("$", indexLabel);
|
|
1161
|
-
if (!
|
|
1527
|
+
if (!isPlainObject2(row)) {
|
|
1162
1528
|
throw new JsonFrameValidationError("`index` payload rows must be JSON objects.", {
|
|
1163
1529
|
orient,
|
|
1164
1530
|
path: rowPath,
|
|
@@ -1186,7 +1552,7 @@ var parseIndex = (value, orient) => {
|
|
|
1186
1552
|
});
|
|
1187
1553
|
};
|
|
1188
1554
|
var parseColumns = (value, orient) => {
|
|
1189
|
-
if (!
|
|
1555
|
+
if (!isPlainObject2(value)) {
|
|
1190
1556
|
throw new JsonFrameValidationError("`columns` payloads must be objects keyed by column label.", {
|
|
1191
1557
|
orient,
|
|
1192
1558
|
path: "$",
|
|
@@ -1208,7 +1574,7 @@ var parseColumns = (value, orient) => {
|
|
|
1208
1574
|
for (const column of columns) {
|
|
1209
1575
|
const columnValue = value[column];
|
|
1210
1576
|
const columnPath = appendPropertyPath("$", column);
|
|
1211
|
-
if (!
|
|
1577
|
+
if (!isPlainObject2(columnValue)) {
|
|
1212
1578
|
throw new JsonFrameValidationError("`columns` payload values must be objects keyed by index label.", {
|
|
1213
1579
|
orient,
|
|
1214
1580
|
path: columnPath,
|
|
@@ -1287,7 +1653,7 @@ var parseValues = (value, options, orient) => {
|
|
|
1287
1653
|
});
|
|
1288
1654
|
};
|
|
1289
1655
|
var parseSplit = (value, orient) => {
|
|
1290
|
-
if (!
|
|
1656
|
+
if (!isPlainObject2(value)) {
|
|
1291
1657
|
throw new JsonFrameValidationError("`split` payloads must be objects.", { orient, path: "$", value });
|
|
1292
1658
|
}
|
|
1293
1659
|
if (!Array.isArray(value.columns)) {
|
|
@@ -1362,7 +1728,7 @@ var parseSplit = (value, orient) => {
|
|
|
1362
1728
|
});
|
|
1363
1729
|
};
|
|
1364
1730
|
var cloneConstraints = (value, orient, path) => {
|
|
1365
|
-
if (!
|
|
1731
|
+
if (!isPlainObject2(value)) {
|
|
1366
1732
|
throw new JsonFrameValidationError("Table Schema field constraints must be an object when present.", {
|
|
1367
1733
|
orient,
|
|
1368
1734
|
path,
|
|
@@ -1404,7 +1770,7 @@ var cloneConstraints = (value, orient, path) => {
|
|
|
1404
1770
|
var cloneTableField = (value, index) => {
|
|
1405
1771
|
const orient = "table";
|
|
1406
1772
|
const path = appendIndexPath("$.schema.fields", index);
|
|
1407
|
-
if (!
|
|
1773
|
+
if (!isPlainObject2(value)) {
|
|
1408
1774
|
throw new JsonFrameValidationError("Table Schema fields must be objects.", {
|
|
1409
1775
|
orient,
|
|
1410
1776
|
path,
|
|
@@ -1451,7 +1817,7 @@ var cloneTableField = (value, index) => {
|
|
|
1451
1817
|
};
|
|
1452
1818
|
var cloneTableSchema = (value) => {
|
|
1453
1819
|
const orient = "table";
|
|
1454
|
-
if (!
|
|
1820
|
+
if (!isPlainObject2(value)) {
|
|
1455
1821
|
throw new JsonFrameValidationError("`table.schema` must be an object.", {
|
|
1456
1822
|
orient,
|
|
1457
1823
|
path: "$.schema",
|
|
@@ -1527,7 +1893,7 @@ var cloneTableSchema = (value) => {
|
|
|
1527
1893
|
return Object.freeze(cloned);
|
|
1528
1894
|
};
|
|
1529
1895
|
var parseTable = (value, orient) => {
|
|
1530
|
-
if (!
|
|
1896
|
+
if (!isPlainObject2(value)) {
|
|
1531
1897
|
throw new JsonFrameValidationError("`table` payloads must be objects.", { orient, path: "$", value });
|
|
1532
1898
|
}
|
|
1533
1899
|
const schema = cloneTableSchema(value.schema);
|
|
@@ -1552,10 +1918,11 @@ var parseTable = (value, orient) => {
|
|
|
1552
1918
|
const fieldNames = new Set(schema.fields.map((field) => field.name));
|
|
1553
1919
|
const index = [];
|
|
1554
1920
|
const indexKind = primaryKey === void 0 ? "synthetic" : "source";
|
|
1921
|
+
const seenPrimaryKeyLabels = /* @__PURE__ */ new Map();
|
|
1555
1922
|
for (let rowIndex = 0; rowIndex < value.data.length; rowIndex += 1) {
|
|
1556
1923
|
const row = value.data[rowIndex];
|
|
1557
1924
|
const rowPath = appendIndexPath("$.data", rowIndex);
|
|
1558
|
-
if (!
|
|
1925
|
+
if (!isPlainObject2(row)) {
|
|
1559
1926
|
throw new JsonFrameValidationError("`table.data` rows must be objects.", {
|
|
1560
1927
|
orient,
|
|
1561
1928
|
path: rowPath,
|
|
@@ -1585,9 +1952,10 @@ var parseTable = (value, orient) => {
|
|
|
1585
1952
|
value: row
|
|
1586
1953
|
});
|
|
1587
1954
|
} else {
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
);
|
|
1955
|
+
const primaryKeyPath = appendPropertyPath(rowPath, primaryKey);
|
|
1956
|
+
const indexLabel = assertSupportedIndexLabel(row[primaryKey], orient, primaryKeyPath);
|
|
1957
|
+
assertUniqueTablePrimaryKeyLabel(seenPrimaryKeyLabels, indexLabel, rowIndex, primaryKey, primaryKeyPath);
|
|
1958
|
+
index.push(indexLabel);
|
|
1591
1959
|
}
|
|
1592
1960
|
for (const column of columns) {
|
|
1593
1961
|
data.get(column).push(hasOwn2.call(row, column) ? row[column] : null);
|
|
@@ -1617,7 +1985,7 @@ var parseInput = (input, options) => {
|
|
|
1617
1985
|
throw error;
|
|
1618
1986
|
}
|
|
1619
1987
|
})();
|
|
1620
|
-
const jsonValue =
|
|
1988
|
+
const jsonValue = cloneJsonCompatible(parsedValue);
|
|
1621
1989
|
const orient = options.orient === "auto" ? detectOrient(jsonValue) : options.orient;
|
|
1622
1990
|
switch (orient) {
|
|
1623
1991
|
case "records":
|
|
@@ -1649,6 +2017,7 @@ function fromOrient(input, options) {
|
|
|
1649
2017
|
0 && (module.exports = {
|
|
1650
2018
|
AmbiguousOrientError,
|
|
1651
2019
|
ExportKeyCollisionError,
|
|
2020
|
+
JSON_FRAME_MAX_DEPTH,
|
|
1652
2021
|
JsonFrameError,
|
|
1653
2022
|
JsonFrameOptionError,
|
|
1654
2023
|
JsonFrameParseError,
|