@directus/api
Version:
Directus is a real-time API and App dashboard for managing SQL database content
105 lines (103 loc) • 3.24 kB
JavaScript
import { useEnv } from "@directus/env";
import { ErrorCode, createError } from "@directus/errors";
//#region src/utils/error-tracker.ts
const MAX_IMPORT_ERRORS = useEnv()["MAX_IMPORT_ERRORS"];
function createErrorTracker() {
let genericError;
const fieldErrors = /* @__PURE__ */ new Map();
let capturedErrorCount = 0;
let isLimitReached = false;
function convertToRanges(rows, minRangeSize = 4) {
const sorted = Array.from(new Set(rows)).sort((a, b) => a - b);
const result = [];
if (sorted.length === 0) return [];
let start = sorted[0];
let prev = sorted[0];
let count = 1;
const nonConsecutive = [];
const flush = () => {
if (count >= minRangeSize) result.push({
type: "range",
start,
end: prev
});
else for (let i = start; i <= prev; i++) nonConsecutive.push(i);
};
for (let i = 1; i < sorted.length; i++) {
const current = sorted[i];
if (current === prev + 1) {
prev = current;
count++;
} else {
flush();
start = prev = current;
count = 1;
}
}
flush();
if (nonConsecutive.length > 0) result.push({
type: "lines",
rows: nonConsecutive
});
return result;
}
function addCapturedError(err, rowNumber) {
const field = err.extensions?.field;
if (field) {
const type = err.extensions?.type;
const substring = err.extensions?.substring;
const valid = err.extensions?.valid;
const invalid = err.extensions?.invalid;
let key = type ? `${field}|${type}` : field;
if (substring !== void 0) key += `|substring:${substring}`;
if (valid !== void 0) key += `|valid:${JSON.stringify(valid)}`;
if (invalid !== void 0) key += `|invalid:${JSON.stringify(invalid)}`;
if (!fieldErrors.has(err.code)) fieldErrors.set(err.code, /* @__PURE__ */ new Map());
const errorsByCode = fieldErrors.get(err.code);
if (!errorsByCode.has(key)) errorsByCode.set(key, {
message: err.message,
rowNumbers: []
});
errorsByCode.get(key).rowNumbers.push(rowNumber);
} else genericError = err;
capturedErrorCount++;
if (capturedErrorCount >= MAX_IMPORT_ERRORS) isLimitReached = true;
}
function hasGenericError() {
return genericError !== void 0;
}
function buildFinalErrors() {
if (genericError) return [genericError];
return Array.from(fieldErrors.entries()).flatMap(([code, fieldMap]) => Array.from(fieldMap.entries()).map(([compositeKey, errorData]) => {
const parts = compositeKey.split("|");
const field = parts[0];
const type = parts[1];
const extensions = {};
for (let i = 2; i < parts.length; i++) {
const [paramType, paramValue] = parts[i]?.split(":", 2) ?? [];
if (!paramType || paramValue === void 0) continue;
try {
extensions[paramType] = JSON.parse(paramValue);
} catch {
extensions[paramType] = paramValue;
}
}
return new (createError(code, errorData.message, 400))({
field,
type,
...extensions,
rows: convertToRanges(errorData.rowNumbers)
});
}));
}
return {
addCapturedError,
buildFinalErrors,
getCount: () => capturedErrorCount,
hasErrors: () => capturedErrorCount > 0 || hasGenericError(),
shouldStop: () => isLimitReached || hasGenericError(),
hasGenericError
};
}
//#endregion
export { createErrorTracker };