Spaces:
Runtime error
Runtime error
File size: 2,276 Bytes
46252cd | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | import { QueryFailedError } from 'typeorm';
/**
* Cross-dialect unique-constraint-violation check by driver code/message, for the two dialects we ship
* (sqlite dev, postgres prod). Lets insert-or-converge (RMW) paths distinguish a real duplicate from an
* unrelated failure without depending on a specific driver. Add another branch if a third driver is ever
* supported.
*/
export function isUniqueViolation(err: unknown): boolean {
if (!(err instanceof QueryFailedError)) return false;
const driver = err.driverError as { code?: string; message?: string } | undefined;
const code = driver?.code ?? '';
const message = driver?.message ?? err.message ?? '';
return code === '23505' /* postgres */ || /UNIQUE constraint failed|SQLITE_CONSTRAINT/i.test(message);
}
/**
* Cross-dialect "the table does not exist" check. Used to keep a table-clearing DELETE tolerant of a
* genuinely-absent table while STILL surfacing every other failure (lock, I/O, syntax) — the opposite of
* a blind `.catch(() => {})`. Postgres has a precise code (42P01 undefined_table). SQLite is matched by
* MESSAGE only: its generic `SQLITE_ERROR` code (errno 1) is shared with syntax and other real errors, so
* a code check would over-swallow. The message is read from both the driver error and the wrapped
* QueryFailedError so a future TypeORM change to the nesting fails toward the regex still matching.
*/
export function isMissingTableError(err: unknown): boolean {
if (err instanceof QueryFailedError) {
const driver = err.driverError as { code?: string; message?: string } | undefined;
if (driver?.code === '42P01') return true; // postgres undefined_table
const message = `${driver?.message ?? ''} ${err.message ?? ''}`;
return /no such table/i.test(message);
}
// better-sqlite3 validates SQL at prepare() time, and TypeORM's BetterSqlite3QueryRunner creates the
// statement OUTSIDE its try/catch — so a missing-table error surfaces as the RAW SqliteError, never
// wrapped in QueryFailedError. Recognize that exact shape (class name + message); a plain Error whose
// text happens to mention a missing table must still NOT classify.
return err instanceof Error && err.name === 'SqliteError' && /no such table/i.test(err.message);
}
|