Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | 1x 12x 12x 117x 116x 116x 116x 117x 117x 117x 117x 12x 12x 12x 12x 7x 7x 5x 4x 4x 7x 12x 12x | /**
* `postgres.js` adapter for `pgrls-test`.
*
* Usage:
*
* ```ts
* import postgres from 'postgres';
* import { PgrlsTestClient, postgresJsDriver } from 'pgrls-test';
*
* const sql = postgres(process.env.DATABASE_URL);
* const client = new PgrlsTestClient(postgresJsDriver(sql));
* ```
*
* The adapter exists because `postgres.js`'s primary API is
* tagged-template literals (`sql\`SELECT * FROM x\``), which
* doesn't fit the "execute this raw SQL string with these
* positional params" shape `pgrls-test` needs. Internally we
* use `sql.unsafe(text, params)` — postgres.js's escape hatch
* for exactly that. Users keep their existing `postgres()`
* connection pool and tagged-template usage everywhere else;
* the escape hatch is confined to this adapter.
*
* `postgres` is a peer dependency. Users who don't use it
* never pull it in.
*/
import type { Driver, QueryResult } from './types.js';
/**
* Subset of `postgres.Sql` the adapter needs. Defined
* structurally so we don't have to `import postgres from
* 'postgres'` at module-load time (that would make `postgres`
* a runtime dep instead of a peer dep).
*
* `postgres.js`'s `unsafe(text, params)` returns a
* `PendingQuery<Row[]>` — awaiting it yields an array of rows
* with `command` and `count` properties attached. Modeling
* that shape here.
*/
export interface PostgresJsSql {
unsafe<TRow = Record<string, unknown>>(
text: string,
params?: readonly unknown[],
): Promise<PostgresJsResult<TRow>>;
}
/**
* Result shape postgres.js returns from `sql.unsafe(...)`.
*
* The result IS the array of rows (numerically indexed) but
* also has `command` and `count` properties tacked on — a
* postgres.js convention. We treat it as both via a hybrid
* type.
*/
export type PostgresJsResult<TRow> = readonly TRow[] & {
command?: string;
count?: number;
};
/**
* Wrap a `postgres.Sql` instance (or any object satisfying
* `PostgresJsSql`) into the `Driver` shape the rest of
* `pgrls-test` consumes.
*/
export function postgresJsDriver(sql: PostgresJsSql): Driver {
return {
async query(sqlText: string, params?: readonly unknown[]): Promise<QueryResult> {
const result = await sql.unsafe<Record<string, unknown>>(sqlText, params);
// postgres.js's result is an array-like with `command`
// and `count` extras. Spread into a plain array so
// callers can't mutate the underlying driver state, and
// surface command/count under the QueryResult shape.
const rows: Record<string, unknown>[] = Array.from(result);
return {
rows,
command: (result.command ?? '').toUpperCase(),
// For SELECT and RETURNING-bearing DML, count is the
// number of rows. For plain UPDATE/DELETE/INSERT, count
// is the affected-row count. Map an explicit `undefined`
// (defensive — postgres.js sets it on every result) to
// rows.length as the safest fallback.
rowCount: result.count ?? rows.length,
};
},
async rollback(): Promise<void> {
// ROLLBACK accepted in any transaction state, including
// an aborted one.
await sql.unsafe('ROLLBACK');
},
isInsufficientPrivilege(error: unknown): boolean {
// postgres.js wraps server errors as `PostgresError`
// instances with `code` set to the 5-char SQLSTATE.
// 42501 is insufficient_privilege.
return (
typeof error === 'object' &&
error !== null &&
'code' in error &&
(error as { code?: unknown }).code === '42501'
);
},
};
}
|