Compare commits

...

10 Commits

@ -0,0 +1,3 @@
{
"extends": "@joepie91/eslint-config"
}

@ -1,3 +1,9 @@
## 2.0.2 (November 25, 2020)
- __Patch:__ Now works on newer Node.js versions, by replacing the internal `create-error` usage with `error-chain`.
- __Patch:__ Various error parsing robustness improvements.
- __Patch:__ Gulp and Babel were removed, as pretty much everything supports ES2015 by now.
## 2.0.1 (July 25, 2017)
* __Patch:__ Made the error message for composite UNIQUE constraint violations slightly more readable, by wrapping multiple columns and values in a set of brackets.

@ -1,18 +0,0 @@
var gulp = require("gulp");
var presetES2015 = require("@joepie91/gulp-preset-es2015");
var source = ["src/**/*.js"]
gulp.task('babel', function() {
return gulp.src(source)
.pipe(presetES2015({
basePath: __dirname
}))
.pipe(gulp.dest("lib/"));
});
gulp.task("watch", function () {
gulp.watch(source, ["babel"]);
});
gulp.task("default", ["babel", "watch"]);

@ -1,3 +1,3 @@
'use strict';
module.exports = require("./lib");
module.exports = require("./src");

@ -0,0 +1,2 @@
error: invalid input syntax for type timestamp with time zone: "{}"
insert into "transaction_events" ("field", "operator_id", "origin", "transaction_id", "type", "value") values ($1, DEFAULT, $2, $3, $4, $5), ($6, DEFAULT, $7, $8, $9, $10), ($11, DEFAULT, $12, $13, $14, $15), ($16, DEFAULT, $17, $18, $19, $20), ($21, DEFAULT, $22, $23, $24, $25), ($26, DEFAULT, $27, $28, $29, $30), ($31, DEFAULT, $32, $33, $34, $35), ($36, DEFAULT, $37, $38, $39, $40), ($41, DEFAULT, $42, $43, $44, $45), ($46, DEFAULT, $47, $48, $49, $50), ($51, DEFAULT, $52, $53, $54, $55), ($56, DEFAULT, $57, $58, $59, $60), ($61, DEFAULT, $62, $63, $64, $65), ($66, DEFAULT, $67, $68, $69, $70), ($71, DEFAULT, $72, $73, $74, DEFAULT) returning * - invalid input syntax for type json

@ -1,6 +1,6 @@
{
"name": "database-error",
"version": "2.0.1",
"version": "2.0.2",
"description": "Turns errors from database libraries into more useful error objects",
"main": "index.js",
"scripts": {
@ -22,15 +22,15 @@
"author": "Sven Slootweg",
"license": "WTFPL",
"dependencies": {
"create-error": "^0.3.1",
"debug": "^4.1.1",
"error-chain": "^0.1.2",
"pg-error-codes": "^1.0.0"
},
"devDependencies": {
"@joepie91/gulp-preset-es2015": "^1.0.1",
"babel-preset-es2015": "^6.6.0",
"bluebird": "^3.4.6",
"gulp": "^3.9.1",
"knex": "^0.12.6",
"pg": "^6.1.0"
"@joepie91/eslint-config": "^1.1.0",
"bluebird": "^3.5.1",
"eslint": "^7.14.0",
"knex": "^0.12.9",
"pg": "^6.4.2"
}
}

@ -1,5 +1,5 @@
'use strict';
const createError = require("create-error");
const { create } = require("error-chain");
module.exports = createError("DatabaseError");
module.exports = create("DatabaseError");

@ -1,13 +1,13 @@
'use strict';
const createError = require("create-error");
const { create } = require("error-chain");
const pgErrorCodes = require("pg-error-codes");
const DatabaseError = require("../database-error.js");
const getColumns = require("../get-columns");
const getValues = require("../get-values");
let CheckConstraintViolationError = createError(DatabaseError, "CheckConstraintViolationError");
let CheckConstraintViolationError = create("CheckConstraintViolationError", { inheritsFrom: DatabaseError });
let messageRegex = /^(.+) - new row for relation "([^"]+)" violates check constraint "([^"]+)"$/;
@ -18,7 +18,7 @@ module.exports = {
return (
// PostgreSQL (via `pg`):
(error.length != null && error.file != null && error.line != null && error.routine != null && error.code === "23514")
)
);
},
convert: function convertError(error) {
let messageMatch = messageRegex.exec(error.message);
@ -27,7 +27,7 @@ module.exports = {
throw new Error("Encountered unknown error format");
}
let [_, query, table, constraint] = messageMatch;
let [_, query, _table, _constraint] = messageMatch;
let columns = getColumns(query);
@ -36,7 +36,7 @@ module.exports = {
if (columns != null) {
/* This is the naming convention that Knex uses for .enum() in PostgreSQL */
offendingColumn = columns.find(column => {
return error.constraint === `${error.table}_${column}_check`
return error.constraint === `${error.table}_${column}_check`;
});
message = `Value violates the '${error.constraint}' constraint for the '${offendingColumn}' column in the '${error.table}' table`;

@ -1,12 +1,12 @@
'use strict';
const createError = require("create-error");
const { create } = require("error-chain");
const pgErrorCodes = require("pg-error-codes");
const DatabaseError = require("../database-error.js");
const getTable = require("../get-table");
let EnumError = createError(DatabaseError, "EnumError");
let EnumError = create("EnumError", { inheritsFrom: DatabaseError });
let messageRegex = /^(.+) - invalid input value for enum ([^:]+): "([^"]+)"$/;
@ -17,7 +17,7 @@ module.exports = {
return (
// PostgreSQL (via `pg`):
(error.length != null && error.file != null && error.line != null && error.routine != null && error.code === "22P02" && error.message.includes("invalid input value for enum"))
)
);
},
convert: function convertError(error) {
let messageMatch = messageRegex.exec(error.message);

@ -1,10 +1,10 @@
'use strict';
const createError = require("create-error");
const { create } = require("error-chain");
const pgErrorCodes = require("pg-error-codes");
const DatabaseError = require("../database-error.js");
let ForeignKeyConstraintViolationError = createError(DatabaseError, "ForeignKeyConstraintViolationError");
let ForeignKeyConstraintViolationError = create("ForeignKeyConstraintViolationError", { inheritsFrom: DatabaseError });
let detailsRegex = /^Key \(([^\)]+)\)=\(([^\)]+)\) is not present in table "([^"]+)"\.$/;
@ -15,7 +15,7 @@ module.exports = {
return (
// PostgreSQL (via `pg`):
(error.length != null && error.file != null && error.line != null && error.routine != null && error.code === "23503")
)
);
},
convert: function convertError(error) {
let [_, column, value, foreignTable] = detailsRegex.exec(error.detail);

@ -1,15 +1,15 @@
'use strict';
const createError = require("create-error");
const { create } = require("error-chain");
const pgErrorCodes = require("pg-error-codes");
const DatabaseError = require("../database-error.js");
const getTable = require("../get-table");
let InvalidTypeError = createError(DatabaseError, "InvalidTypeError");
let InvalidTypeError = create("InvalidTypeError", { inheritsFrom: DatabaseError });
/* NOTE: error messages vary. Eg. for boolean-type columns, it states "for type boolean", but for integer-type columns, it starts "for integer". */
let messageRegex = /^(.+) - invalid input syntax for(?: type)? ([^:]+): "([^"]+)"$/;
let messageRegex = /^(?:(.+) - )?invalid input syntax for(?: type)? ([^:]+)(?:: "(.+)")?$/;
module.exports = {
error: InvalidTypeError,
@ -18,13 +18,14 @@ module.exports = {
return (
// PostgreSQL (via `pg`):
(error.length != null && error.file != null && error.line != null && error.routine != null && error.code === "22P02" && error.message.includes("invalid input syntax for"))
)
);
},
convert: function convertError(error) {
let messageMatch = messageRegex.exec(error.message);
if (messageMatch == null) {
throw new Error("Encountered unknown error format");
/* TODO: Update other error parsing modules to display the original error message here as well. */
throw new Error(`Encountered unknown error format for error message: ${error.message}`);
}
let [_, query, expectedType, value] = messageMatch;
@ -32,10 +33,11 @@ module.exports = {
let message;
/* TODO: `value` can be undefined! */
if (table != null) {
message = `Value '${value}' is of the wrong type for a '${expectedType}'-type column (in table '${table}')`;
message = `Value <${value}> is of the wrong type for a '${expectedType}'-type column (in table '${table}')`;
} else {
message = `Value '${value}' is of the wrong type for a '${expectedType}'-type column '${enumType}'`;
message = `Value <${value}> is of the wrong type for a '${expectedType}'-type column`;
}
return new InvalidTypeError(message, {

@ -1,12 +1,12 @@
'use strict';
const createError = require("create-error");
const { create } = require("error-chain");
const pgErrorCodes = require("pg-error-codes");
const DatabaseError = require("../database-error.js");
const getValues = require("../get-values");
let NotNullConstraintViolationError = createError(DatabaseError, "NotNullConstraintViolationError");
let NotNullConstraintViolationError = create("NotNullConstraintViolationError", { inheritsFrom: DatabaseError });
let messageRegex = /^(.+) - null value in column "([^"]+)" violates not-null constraint$/;
@ -17,10 +17,10 @@ module.exports = {
return (
// PostgreSQL (via `pg`):
(error.length != null && error.file != null && error.line != null && error.routine != null && error.code === "23502")
)
);
},
convert: function convertError(error) {
let [_, query, column] = messageRegex.exec(error.message);
let [_, query, _column] = messageRegex.exec(error.message);
return new NotNullConstraintViolationError(`Missing required value for column '${error.column}' in table '${error.table}'`, {
originalError: error,

@ -1,14 +1,13 @@
'use strict';
const createError = require("create-error");
const { create } = require("error-chain");
const pgErrorCodes = require("pg-error-codes");
const DatabaseError = require("../database-error.js");
const getTable = require("../get-table");
let UndefinedColumnError = createError(DatabaseError, "UndefinedColumnError");
let UndefinedColumnError = create("UndefinedColumnError", { inheritsFrom: DatabaseError });
let messageRegex = /^(.+) - column "([^"]+)" of relation "([^"]+)" does not exist$/;
let messageRegex = /^(.+) - column "([^"]+)" (?:of relation "([^"]+)" )?does not exist$/;
module.exports = {
error: UndefinedColumnError,
@ -17,7 +16,7 @@ module.exports = {
return (
// PostgreSQL (via `pg`):
(error.length != null && error.file != null && error.line != null && error.routine != null && error.code === "42703")
)
);
},
convert: function convertError(error) {
let messageMatch = messageRegex.exec(error.message);
@ -28,7 +27,16 @@ module.exports = {
let [_, query, column, table] = messageMatch;
return new UndefinedColumnError(`The '${column}' column does not exist in the '${table}' table`, {
let errorMessage;
if (table != null) {
errorMessage = `The '${column}' column does not exist in the '${table}' table`;
} else {
/* TODO: Maybe try to extract this from the query... somehow? */
errorMessage = `The '${column}' column does not exist in (unknown table)`;
}
return new UndefinedColumnError(errorMessage, {
originalError: error,
pgCode: error.code,
code: pgErrorCodes[error.code],

@ -1,11 +1,11 @@
'use strict';
const createError = require("create-error");
const { create } = require("error-chain");
const pgErrorCodes = require("pg-error-codes");
const DatabaseError = require("../database-error.js");
const splitValues = require("../split-values");
let UniqueConstraintViolationError = createError(DatabaseError, "UniqueConstraintViolationError");
let UniqueConstraintViolationError = create("UniqueConstraintViolationError", { inheritsFrom: DatabaseError });
let detailsRegex = /Key \(([^\)]+)\)=\(([^\)]+)\) already exists\./;
@ -16,7 +16,7 @@ module.exports = {
return (
// PostgreSQL (via `pg`):
(error.length != null && error.file != null && error.line != null && error.routine != null && error.code === "23505")
)
);
},
convert: function convertError(error) {
let [_, columnValue, valueValue] = detailsRegex.exec(error.detail);

@ -5,11 +5,11 @@ let updateRegex = /^update "[^"]+" set (.+) where/;
let updateColumnRegex = /^"([^"]+)"/;
module.exports = function getColumns(query) {
let match, columns;
let match;
if (match = insertRegex.exec(query)) {
return match[1].split(",").map((columnName) => {
return columnName.trim().slice(1, -1)
return columnName.trim().slice(1, -1);
});
} else if (match = updateRegex.exec(query)) {
return match[1].split(",").map((statement) => {

@ -1,6 +1,6 @@
'use strict';
let detailsRegex = /^Failing row contains \(([^\)]+)\).$/;
let detailsRegex = /^Failing row contains \((.+)\).$/;
module.exports = function getValues(detail) {
let detailsMatch = detailsRegex.exec(detail);

@ -1,6 +1,7 @@
'use strict';
const createError = require("create-error");
const debug = require("debug")("database-error");
const DatabaseError = require("./database-error");
@ -14,12 +15,13 @@ let handlers = [
require("./errors/invalid-type"),
require("./errors/undefined-column"),
require("./errors/not-null-constraint-violation"),
]
];
function convertError(error) {
let handler = handlers.find(handler => handler.check(error));
if (handler != null) {
debug(`Converting error with message: ${error.message}`);
return handler.convert(error);
} else {
throw new UnknownError("The specified error is not of a recognized type");
@ -49,4 +51,4 @@ module.exports = Object.assign({
rethrow: rethrowBetterError,
UnknownError: UnknownError,
DatabaseError: DatabaseError
}, errorTypes)
}, errorTypes);

@ -1,7 +1,5 @@
'use strict';
const Promise = require("bluebird");
module.exports = {
up: function createCheckConstraintViolationTable(knex, errorHandler) {
return knex.schema.createTable("check_constraint_violation", (table) => {

@ -12,13 +12,13 @@ let tables = [
require("./not-null-constraint-violation")
];
let noop = function noop(err) {
let noop = function noop(_err) {
// Do nothing.
}
};
let rethrow = function rethrowError(err) {
throw err;
}
};
module.exports = {
up: function createTables(knex) {
@ -39,4 +39,4 @@ module.exports = {
return table.down(knex, errorHandler);
});
}
}
};

@ -21,6 +21,6 @@ module.exports = function attemptForeignKeyConstraintViolation(knex) {
}, {
user_id: 567213,
body: "Baz"
}])
}]);
});
};

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save