UNPKG

@dpkit/table

Version:

Data Package implementation in TypeScript.

151 lines 19.9 kB
import { col, lit } from "nodejs-polars"; import { matchField } from "../field/index.js"; import { inspectField } from "../field/index.js"; import { inspectRows } from "../row/index.js"; import { getPolarsSchema } from "../schema/index.js"; import { processFields } from "./process.js"; export async function inspectTable(table, options) { const { schema, sampleRows = 100, invalidRowsLimit = 100 } = options ?? {}; const errors = []; if (schema) { const sample = await table.head(sampleRows).collect(); const polarsSchema = getPolarsSchema(sample.schema); const matchErrors = inspectFieldsMatch({ schema, polarsSchema }); errors.push(...matchErrors); const fieldErrors = await inspectFields(table, schema, polarsSchema, invalidRowsLimit); errors.push(...fieldErrors); } return errors; } function inspectFieldsMatch(props) { const { schema, polarsSchema } = props; const errors = []; const fieldsMatch = schema.fieldsMatch ?? "exact"; const fields = schema.fields; const polarsFields = polarsSchema.fields; const names = fields.map(field => field.name); const polarsNames = polarsFields.map(field => field.name); const extraFields = polarsFields.length - fields.length; const missingFields = fields.length - polarsFields.length; const extraNames = arrayDiff(polarsNames, names); const missingNames = arrayDiff(names, polarsNames); if (fieldsMatch === "exact") { if (extraFields > 0) { errors.push({ type: "fields/extra", fieldNames: extraNames, }); } if (missingFields > 0) { errors.push({ type: "fields/missing", fieldNames: missingNames, }); } } if (fieldsMatch === "equal") { if (extraNames.length > 0) { errors.push({ type: "fields/extra", fieldNames: extraNames, }); } if (missingNames.length > 0) { errors.push({ type: "fields/missing", fieldNames: missingNames, }); } } if (fieldsMatch === "subset") { if (missingNames.length > 0) { errors.push({ type: "fields/missing", fieldNames: missingNames, }); } } if (fieldsMatch === "superset") { if (extraNames.length > 0) { errors.push({ type: "fields/extra", fieldNames: extraNames, }); } } if (fieldsMatch === "partial") { if (missingNames.length === fields.length) { errors.push({ type: "fields/missing", fieldNames: missingNames, }); } } return errors; } async function inspectFields(table, schema, polarsSchema, invalidRowsLimit) { const errors = []; const targetNames = []; const sources = Object.entries(processFields(schema, polarsSchema, { dontParse: true })).map(([name, expr]) => { return expr.alias(`source:${name}`); }); const targets = Object.entries(processFields(schema, polarsSchema, { dontParse: false })).map(([name, expr]) => { const targetName = `target:${name}`; targetNames.push(targetName); return expr.alias(targetName); }); let errorTable = table .withRowCount() .select([ col("row_nr").add(1), lit(false).alias("error"), ...sources, ...targets, ]); for (const [index, field] of schema.fields.entries()) { const polarsField = matchField(index, field, schema, polarsSchema); if (polarsField) { const fieldResult = inspectField(field, { errorTable, polarsField }); errorTable = fieldResult.errorTable; errors.push(...fieldResult.errors); } } const rowsResult = inspectRows(schema, errorTable); errorTable = rowsResult.errorTable; errors.push(...rowsResult.errors); const errorFrame = await errorTable .filter(col("error").eq(true)) .head(invalidRowsLimit) .drop(targetNames) .collect(); for (const record of errorFrame.toRecords()) { for (const [key, value] of Object.entries(record)) { const [kind, type, name] = key.split(":"); if (kind === "error" && value === true && type && name) { const rowNumber = record.row_nr; // Cell-level errors if (type.startsWith("cell/")) { errors.push({ rowNumber, type: type, fieldName: name, cell: (record[`source:${name}`] ?? "").toString(), }); } // Row-level errors if (type.startsWith("row/")) { errors.push({ rowNumber, type: type, fieldNames: name.split(","), }); } } } } return errors; } function arrayDiff(a, b) { return a.filter(x => !b.includes(x)); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5zcGVjdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RhYmxlL2luc3BlY3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsTUFBTSxlQUFlLENBQUE7QUFFeEMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLG1CQUFtQixDQUFBO0FBQzlDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQTtBQUNoRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0saUJBQWlCLENBQUE7QUFDN0MsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLG9CQUFvQixDQUFBO0FBR3BELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxjQUFjLENBQUE7QUFFNUMsTUFBTSxDQUFDLEtBQUssVUFBVSxZQUFZLENBQ2hDLEtBQVksRUFDWixPQUlDO0lBRUQsTUFBTSxFQUFFLE1BQU0sRUFBRSxVQUFVLEdBQUcsR0FBRyxFQUFFLGdCQUFnQixHQUFHLEdBQUcsRUFBRSxHQUFHLE9BQU8sSUFBSSxFQUFFLENBQUE7SUFDMUUsTUFBTSxNQUFNLEdBQWlCLEVBQUUsQ0FBQTtJQUUvQixJQUFJLE1BQU0sRUFBRSxDQUFDO1FBQ1gsTUFBTSxNQUFNLEdBQUcsTUFBTSxLQUFLLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFBO1FBQ3JELE1BQU0sWUFBWSxHQUFHLGVBQWUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUE7UUFFbkQsTUFBTSxXQUFXLEdBQUcsa0JBQWtCLENBQUMsRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQTtRQUNoRSxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsV0FBVyxDQUFDLENBQUE7UUFFM0IsTUFBTSxXQUFXLEdBQUcsTUFBTSxhQUFhLENBQ3JDLEtBQUssRUFDTCxNQUFNLEVBQ04sWUFBWSxFQUNaLGdCQUFnQixDQUNqQixD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QyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQTtBQUN0QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBTY2hlbWEgfSBmcm9tIFwiQGRwa2l0L2NvcmVcIlxuaW1wb3J0IHsgY29sLCBsaXQgfSBmcm9tIFwibm9kZWpzLXBvbGFyc1wiXG5pbXBvcnQgdHlwZSB7IFRhYmxlRXJyb3IgfSBmcm9tIFwiLi4vZXJyb3IvaW5kZXgudHNcIlxuaW1wb3J0IHsgbWF0Y2hGaWVsZCB9IGZyb20gXCIuLi9maWVsZC9pbmRleC50c1wiXG5pbXBvcnQgeyBpbnNwZWN0RmllbGQgfSBmcm9tIFwiLi4vZmllbGQvaW5kZXgudHNcIlxuaW1wb3J0IHsgaW5zcGVjdFJvd3MgfSBmcm9tIFwiLi4vcm93L2luZGV4LnRzXCJcbmltcG9ydCB7IGdldFBvbGFyc1NjaGVtYSB9IGZyb20gXCIuLi9zY2hlbWEvaW5kZXgudHNcIlxuaW1wb3J0IHR5cGUgeyBQb2xhcnNTY2hlbWEgfSBmcm9tIFwiLi4vc2NoZW1hL2luZGV4LnRzXCJcbmltcG9ydCB0eXBlIHsgVGFibGUgfSBmcm9tIFwiLi9UYWJsZS50c1wiXG5pbXBvcnQgeyBwcm9jZXNzRmllbGRzIH0gZnJvbSBcIi4vcHJvY2Vzcy50c1wiXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbnNwZWN0VGFibGUoXG4gIHRhYmxlOiBUYWJsZSxcbiAgb3B0aW9ucz86IHtcbiAgICBzY2hlbWE/OiBTY2hlbWFcbiAgICBzYW1wbGVSb3dzPzogbnVtYmVyXG4gICAgaW52YWxpZFJvd3NMaW1pdD86IG51bWJlclxuICB9LFxuKSB7XG4gIGNvbnN0IHsgc2NoZW1hLCBzYW1wbGVSb3dzID0gMTAwLCBpbnZhbGlkUm93c0xpbWl0ID0gMTAwIH0gPSBvcHRpb25zID8/IHt9XG4gIGNvbnN0IGVycm9yczogVGFibGVFcnJvcltdID0gW11cblxuICBpZiAoc2NoZW1hKSB7XG4gICAgY29uc3Qgc2FtcGxlID0gYXdhaXQgdGFibGUuaGVhZChzYW1wbGVSb3dzKS5jb2xsZWN0KClcbiAgICBjb25zdCBwb2xhcnNTY2hlbWEgPSBnZXRQb2xhcnNTY2hlbWEoc2FtcGxlLnNjaGVtYSlcblxuICAgIGNvbnN0IG1hdGNoRXJyb3JzID0gaW5zcGVjdEZpZWxkc01hdGNoKHsgc2NoZW1hLCBwb2xhcnNTY2hlbWEgfSlcbiAgICBlcnJvcnMucHVzaCguLi5tYXRjaEVycm9ycylcblxuICAgIGNvbnN0IGZpZWxkRXJyb3JzID0gYXdhaXQgaW5zcGVjdEZpZWxkcyhcbiAgICAgIHRhYmxlLFxuICAgICAgc2NoZW1hLFxuICAgICAgcG9sYXJzU2NoZW1hLFxuICAgICAgaW52YWxpZFJvd3NMaW1pdCxcbiAgICApXG4gICAgZXJyb3JzLnB1c2goLi4uZmllbGRFcnJvcnMpXG4gIH1cblxuICByZXR1cm4gZXJyb3JzXG59XG5cbmZ1bmN0aW9uIGluc3BlY3RGaWVsZHNNYXRjaChwcm9wczoge1xuICBzY2hlbWE6IFNjaGVtYVxuICBwb2xhcnNTY2hlbWE6IFBvbGFyc1NjaGVtYVxufSkge1xuICBjb25zdCB7IHNjaGVtYSwgcG9sYXJzU2NoZW1hIH0gPSBwcm9wc1xuXG4gIGNvbnN0IGVycm9yczogVGFibGVFcnJvcltdID0gW11cbiAgY29uc3QgZmllbGRzTWF0Y2ggPSBzY2hlbWEuZmllbGRzTWF0Y2ggPz8gXCJleGFjdFwiXG5cbiAgY29uc3QgZmllbGRzID0gc2NoZW1hLmZpZWxkc1xuICBjb25zdCBwb2xhcnNGaWVsZHMgPSBwb2xhcnNTY2hlbWEuZmllbGRzXG5cbiAgY29uc3QgbmFtZXMgPSBmaWVsZHMubWFwKGZpZWxkID0+IGZpZWxkLm5hbWUpXG4gIGNvbnN0IHBvbGFyc05hbWVzID0gcG9sYXJzRmllbGRzLm1hcChmaWVsZCA9PiBmaWVsZC5uYW1lKVxuXG4gIGNvbnN0IGV4dHJhRmllbGRzID0gcG9sYXJzRmllbGRzLmxlbmd0aCAtIGZpZWxkcy5sZW5ndGhcbiAgY29uc3QgbWlzc2luZ0ZpZWxkcyA9IGZpZWxkcy5sZW5ndGggLSBwb2xhcnNGaWVsZHMubGVuZ3RoXG5cbiAgY29uc3QgZXh0cmFOYW1lcyA9IGFycmF5RGlmZihwb2xhcnNOYW1lcywgbmFtZXMpXG4gIGNvbnN0IG1pc3NpbmdOYW1lcyA9IGFycmF5RGlmZihuYW1lcywgcG9sYXJzTmFtZXMpXG5cbiAgaWYgKGZpZWxkc01hdGNoID09PSBcImV4YWN0XCIpIHtcbiAgICBpZiAoZXh0cmFGaWVsZHMgPiAwKSB7XG4gICAgICBlcnJvcnMucHVzaCh7XG4gICAgICAgIHR5cGU6IFwiZmllbGRzL2V4dHJhXCIsXG4gICAgICAgIGZpZWxkTmFtZXM6IGV4dHJhTmFtZXMsXG4gICAgICB9KVxuICAgIH1cblxuICAgIGlmIChtaXNzaW5nRmllbGRzID4gMCkge1xuICAgICAgZXJyb3JzLnB1c2goe1xuICAgICAgICB0eXBlOiBcImZpZWxkcy9taXNzaW5nXCIsXG4gICAgICAgIGZpZWxkTmFtZXM6IG1pc3NpbmdOYW1lcyxcbiAgICAgIH0pXG4gICAgfVxuICB9XG5cbiAgaWYgKGZpZWxkc01hdGNoID09PSBcImVxdWFsXCIpIHtcbiAgICBpZiAoZXh0cmFOYW1lcy5sZW5ndGggPiAwKSB7XG4gICAgICBlcnJvcnMucHVzaCh7XG4gICAgICAgIHR5cGU6IFwiZmllbGRzL2V4dHJhXCIsXG4gICAgICAgIGZpZWxkTmFtZXM6IGV4dHJhTmFtZXMsXG4gICAgICB9KVxuICAgIH1cblxuICAgIGlmIChtaXNzaW5nTmFtZXMubGVuZ3RoID4gMCkge1xuICAgICAgZXJyb3JzLnB1c2goe1xuICAgICAgICB0eXBlOiBcImZpZWxkcy9taXNzaW5nXCIsXG4gICAgICAgIGZpZWxkTmFtZXM6IG1pc3NpbmdOYW1lcyxcbiAgICAgIH0pXG4gICAgfVxuICB9XG5cbiAgaWYgKGZpZWxkc01hdGNoID09PSBcInN1YnNldFwiKSB7XG4gICAgaWYgKG1pc3NpbmdOYW1lcy5sZW5ndGggPiAwKSB7XG4gICAgICBlcnJvcnMucHVzaCh7XG4gICAgICAgIHR5cGU6IFwiZmllbGRzL21pc3NpbmdcIixcbiAgICAgICAgZmllbGROYW1lczogbWlzc2luZ05hbWVzLFxuICAgICAgfSlcbiAgICB9XG4gIH1cblxuICBpZiAoZmllbGRzTWF0Y2ggPT09IFwic3VwZXJzZXRcIikge1xuICAgIGlmIChleHRyYU5hbWVzLmxlbmd0aCA+IDApIHtcbiAgICAgIGVycm9ycy5wdXNoKHtcbiAgICAgICAgdHlwZTogXCJmaWVsZHMvZXh0cmFcIixcbiAgICAgICAgZmllbGROYW1lczogZXh0cmFOYW1lcyxcbiAgICAgIH0pXG4gICAgfVxuICB9XG5cbiAgaWYgKGZpZWxkc01hdGNoID09PSBcInBhcnRpYWxcIikge1xuICAgIGlmIChtaXNzaW5nTmFtZXMubGVuZ3RoID09PSBmaWVsZHMubGVuZ3RoKSB7XG4gICAgICBlcnJvcnMucHVzaCh7XG4gICAgICAgIHR5cGU6IFwiZmllbGRzL21pc3NpbmdcIixcbiAgICAgICAgZmllbGROYW1lczogbWlzc2luZ05hbWVzLFxuICAgICAgfSlcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZXJyb3JzXG59XG5cbmFzeW5jIGZ1bmN0aW9uIGluc3BlY3RGaWVsZHMoXG4gIHRhYmxlOiBUYWJsZSxcbiAgc2NoZW1hOiBTY2hlbWEsXG4gIHBvbGFyc1NjaGVtYTogUG9sYXJzU2NoZW1hLFxuICBpbnZhbGlkUm93c0xpbWl0OiBudW1iZXIsXG4pIHtcbiAgY29uc3QgZXJyb3JzOiBUYWJsZUVycm9yW10gPSBbXVxuICBjb25zdCB0YXJnZXROYW1lczogc3RyaW5nW10gPSBbXVxuXG4gIGNvbnN0IHNvdXJjZXMgPSBPYmplY3QuZW50cmllcyhcbiAgICBwcm9jZXNzRmllbGRzKHNjaGVtYSwgcG9sYXJzU2NoZW1hLCB7IGRvbnRQYXJzZTogdHJ1ZSB9KSxcbiAgKS5tYXAoKFtuYW1lLCBleHByXSkgPT4ge1xuICAgIHJldHVybiBleHByLmFsaWFzKGBzb3VyY2U6JHtuYW1lfWApXG4gIH0pXG5cbiAgY29uc3QgdGFyZ2V0cyA9IE9iamVjdC5lbnRyaWVzKFxuICAgIHByb2Nlc3NGaWVsZHMoc2NoZW1hLCBwb2xhcnNTY2hlbWEsIHsgZG9udFBhcnNlOiBmYWxzZSB9KSxcbiAgKS5tYXAoKFtuYW1lLCBleHByXSkgPT4ge1xuICAgIGNvbnN0IHRhcmdldE5hbWUgPSBgdGFyZ2V0OiR7bmFtZX1gXG4gICAgdGFyZ2V0TmFtZXMucHVzaCh0YXJnZXROYW1lKVxuICAgIHJldHVybiBleHByLmFsaWFzKHRhcmdldE5hbWUpXG4gIH0pXG5cbiAgbGV0IGVycm9yVGFibGUgPSB0YWJsZVxuICAgIC53aXRoUm93Q291bnQoKVxuICAgIC5zZWxlY3QoW1xuICAgICAgY29sKFwicm93X25yXCIpLmFkZCgxKSxcbiAgICAgIGxpdChmYWxzZSkuYWxpYXMoXCJlcnJvclwiKSxcbiAgICAgIC4uLnNvdXJjZXMsXG4gICAgICAuLi50YXJnZXRzLFxuICAgIF0pXG5cbiAgZm9yIChjb25zdCBbaW5kZXgsIGZpZWxkXSBvZiBzY2hlbWEuZmllbGRzLmVudHJpZXMoKSkge1xuICAgIGNvbnN0IHBvbGFyc0ZpZWxkID0gbWF0Y2hGaWVsZChpbmRleCwgZmllbGQsIHNjaGVtYSwgcG9sYXJzU2NoZW1hKVxuICAgIGlmIChwb2xhcnNGaWVsZCkge1xuICAgICAgY29uc3QgZmllbGRSZXN1bHQgPSBpbnNwZWN0RmllbGQoZmllbGQsIHsgZXJyb3JUYWJsZSwgcG9sYXJzRmllbGQgfSlcbiAgICAgIGVycm9yVGFibGUgPSBmaWVsZFJlc3VsdC5lcnJvclRhYmxlXG4gICAgICBlcnJvcnMucHVzaCguLi5maWVsZFJlc3VsdC5lcnJvcnMpXG4gICAgfVxuICB9XG5cbiAgY29uc3Qgcm93c1Jlc3VsdCA9IGluc3BlY3RSb3dzKHNjaGVtYSwgZXJyb3JUYWJsZSlcbiAgZXJyb3JUYWJsZSA9IHJvd3NSZXN1bHQuZXJyb3JUYWJsZVxuICBlcnJvcnMucHVzaCguLi5yb3dzUmVzdWx0LmVycm9ycylcblxuICBjb25zdCBlcnJvckZyYW1lID0gYXdhaXQgZXJyb3JUYWJsZVxuICAgIC5maWx0ZXIoY29sKFwiZXJyb3JcIikuZXEodHJ1ZSkpXG4gICAgLmhlYWQoaW52YWxpZFJvd3NMaW1pdClcbiAgICAuZHJvcCh0YXJnZXROYW1lcylcbiAgICAuY29sbGVjdCgpXG5cbiAgZm9yIChjb25zdCByZWNvcmQgb2YgZXJyb3JGcmFtZS50b1JlY29yZHMoKSBhcyBhbnlbXSkge1xuICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKHJlY29yZCkpIHtcbiAgICAgIGNvbnN0IFtraW5kLCB0eXBlLCBuYW1lXSA9IGtleS5zcGxpdChcIjpcIilcblxuICAgICAgaWYgKGtpbmQgPT09IFwiZXJyb3JcIiAmJiB2YWx1ZSA9PT0gdHJ1ZSAmJiB0eXBlICYmIG5hbWUpIHtcbiAgICAgICAgY29uc3Qgcm93TnVtYmVyID0gcmVjb3JkLnJvd19uclxuXG4gICAgICAgIC8vIENlbGwtbGV2ZWwgZXJyb3JzXG4gICAgICAgIGlmICh0eXBlLnN0YXJ0c1dpdGgoXCJjZWxsL1wiKSkge1xuICAgICAgICAgIGVycm9ycy5wdXNoKHtcbiAgICAgICAgICAgIHJvd051bWJlcixcbiAgICAgICAgICAgIHR5cGU6IHR5cGUgYXMgYW55LFxuICAgICAgICAgICAgZmllbGROYW1lOiBuYW1lIGFzIGFueSxcbiAgICAgICAgICAgIGNlbGw6IChyZWNvcmRbYHNvdXJjZToke25hbWV9YF0gPz8gXCJcIikudG9TdHJpbmcoKSxcbiAgICAgICAgICB9KVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gUm93LWxldmVsIGVycm9yc1xuICAgICAgICBpZiAodHlwZS5zdGFydHNXaXRoKFwicm93L1wiKSkge1xuICAgICAgICAgIGVycm9ycy5wdXNoKHtcbiAgICAgICAgICAgIHJvd051bWJlcixcbiAgICAgICAgICAgIHR5cGU6IHR5cGUgYXMgYW55LFxuICAgICAgICAgICAgZmllbGROYW1lczogbmFtZS5zcGxpdChcIixcIiksXG4gICAgICAgICAgfSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBlcnJvcnNcbn1cblxuZnVuY3Rpb24gYXJyYXlEaWZmKGE6IHN0cmluZ1tdLCBiOiBzdHJpbmdbXSkge1xuICByZXR1cm4gYS5maWx0ZXIoeCA9PiAhYi5pbmNsdWRlcyh4KSlcbn1cbiJdfQ==