@ingram-tech/nk-db 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,14 @@
1
+ /** SQLSTATE `23505` — `unique_violation`. */
2
+ export declare const PG_UNIQUE_VIOLATION = "23505";
3
+ /**
4
+ * True when `error`, or anything in its `.cause` chain, is a Postgres error
5
+ * whose SQLSTATE equals `code`.
6
+ *
7
+ * Prefer `INSERT … ON CONFLICT` over catch-and-branch where you can (it avoids
8
+ * the pooled-connection-destroy footgun — see `docs/db-package.md`), but use
9
+ * this for the cases that genuinely must inspect the failure.
10
+ */
11
+ export declare const isPgError: (error: unknown, code: string) => boolean;
12
+ /** Convenience for the most common check: a `23505` unique violation. */
13
+ export declare const isUniqueViolation: (error: unknown) => boolean;
14
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAKA,6CAA6C;AAC7C,eAAO,MAAM,mBAAmB,UAAU,CAAC;AAE3C;;;;;;;GAOG;AACH,eAAO,MAAM,SAAS,GAAI,OAAO,OAAO,EAAE,MAAM,MAAM,KAAG,OASxD,CAAC;AAEF,yEAAyE;AACzE,eAAO,MAAM,iBAAiB,GAAI,OAAO,OAAO,KAAG,OACb,CAAC"}
package/dist/errors.js ADDED
@@ -0,0 +1,27 @@
1
+ // Inspect Postgres driver errors by SQLSTATE without hand-rolling the `.cause`
2
+ // chain walk at every call site. `pg` puts the SQLSTATE on `error.code`, but
3
+ // wrappers (Drizzle, our own helpers) often re-throw with the original error
4
+ // nested under `.cause`, so a flat `err.code === …` check silently misses it.
5
+ /** SQLSTATE `23505` — `unique_violation`. */
6
+ export const PG_UNIQUE_VIOLATION = "23505";
7
+ /**
8
+ * True when `error`, or anything in its `.cause` chain, is a Postgres error
9
+ * whose SQLSTATE equals `code`.
10
+ *
11
+ * Prefer `INSERT … ON CONFLICT` over catch-and-branch where you can (it avoids
12
+ * the pooled-connection-destroy footgun — see `docs/db-package.md`), but use
13
+ * this for the cases that genuinely must inspect the failure.
14
+ */
15
+ export const isPgError = (error, code) => {
16
+ let current = error;
17
+ while (current !== null && current !== undefined) {
18
+ if (typeof current === "object" && "code" in current && current.code === code) {
19
+ return true;
20
+ }
21
+ current = current instanceof Error ? current.cause : undefined;
22
+ }
23
+ return false;
24
+ };
25
+ /** Convenience for the most common check: a `23505` unique violation. */
26
+ export const isUniqueViolation = (error) => isPgError(error, PG_UNIQUE_VIOLATION);
27
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,6EAA6E;AAC7E,6EAA6E;AAC7E,8EAA8E;AAE9E,6CAA6C;AAC7C,MAAM,CAAC,MAAM,mBAAmB,GAAG,OAAO,CAAC;AAE3C;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAc,EAAE,IAAY,EAAW,EAAE;IAClE,IAAI,OAAO,GAAY,KAAK,CAAC;IAC7B,OAAO,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAClD,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,MAAM,IAAI,OAAO,IAAI,OAAO,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;YAC/E,OAAO,IAAI,CAAC;QACb,CAAC;QACD,OAAO,GAAG,OAAO,YAAY,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAChE,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC,CAAC;AAEF,yEAAyE;AACzE,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,KAAc,EAAW,EAAE,CAC5D,SAAS,CAAC,KAAK,EAAE,mBAAmB,CAAC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  export { pgNumericToNumber, pgTimestampToIso } from "./coerce.js";
2
2
  export { createDb, withRlsTransaction } from "./drizzle.js";
3
+ export { isPgError, isUniqueViolation, PG_UNIQUE_VIOLATION } from "./errors.js";
3
4
  export { type DbEnv, dbEnv, getDatabaseUrl, isConfigured } from "./keys.js";
4
5
  export { type CreatePoolConfig, createPool } from "./pool.js";
5
- export { createQueries, type PoolQueries, type Queries } from "./queries.js";
6
+ export { createQueries, parseMaybeRow, parseOneRow, parseRows, type PoolQueries, type Queries, type RowsResult, } from "./queries.js";
6
7
  export { RLS_CLAIMS_SETTING, RLS_DEFAULT_ROLE, type ResolvedRlsConfig, type RlsClaims, type RlsOptions, resolveRlsConfig, rlsPreamble, } from "./rls.js";
7
8
  export { configureTimestampsAsStrings } from "./types.js";
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC5E,OAAO,EAAE,KAAK,gBAAgB,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,KAAK,WAAW,EAAE,KAAK,OAAO,EAAE,MAAM,cAAc,CAAC;AAC7E,OAAO,EACN,kBAAkB,EAClB,gBAAgB,EAChB,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACd,KAAK,UAAU,EACf,gBAAgB,EAChB,WAAW,GACX,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,4BAA4B,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAChF,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC5E,OAAO,EAAE,KAAK,gBAAgB,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EACN,aAAa,EACb,aAAa,EACb,WAAW,EACX,SAAS,EACT,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,UAAU,GACf,MAAM,cAAc,CAAC;AACtB,OAAO,EACN,kBAAkB,EAClB,gBAAgB,EAChB,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACd,KAAK,UAAU,EACf,gBAAgB,EAChB,WAAW,GACX,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,4BAA4B,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -3,9 +3,10 @@
3
3
  // production bundle.
4
4
  export { pgNumericToNumber, pgTimestampToIso } from "./coerce.js";
5
5
  export { createDb, withRlsTransaction } from "./drizzle.js";
6
+ export { isPgError, isUniqueViolation, PG_UNIQUE_VIOLATION } from "./errors.js";
6
7
  export { dbEnv, getDatabaseUrl, isConfigured } from "./keys.js";
7
8
  export { createPool } from "./pool.js";
8
- export { createQueries } from "./queries.js";
9
+ export { createQueries, parseMaybeRow, parseOneRow, parseRows, } from "./queries.js";
9
10
  export { RLS_CLAIMS_SETTING, RLS_DEFAULT_ROLE, resolveRlsConfig, rlsPreamble, } from "./rls.js";
10
11
  export { configureTimestampsAsStrings } from "./types.js";
11
12
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,8EAA8E;AAC9E,qBAAqB;AAErB,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAc,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC5E,OAAO,EAAyB,UAAU,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAkC,MAAM,cAAc,CAAC;AAC7E,OAAO,EACN,kBAAkB,EAClB,gBAAgB,EAIhB,gBAAgB,EAChB,WAAW,GACX,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,4BAA4B,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,8EAA8E;AAC9E,qBAAqB;AAErB,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAChF,OAAO,EAAc,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC5E,OAAO,EAAyB,UAAU,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EACN,aAAa,EACb,aAAa,EACb,WAAW,EACX,SAAS,GAIT,MAAM,cAAc,CAAC;AACtB,OAAO,EACN,kBAAkB,EAClB,gBAAgB,EAIhB,gBAAgB,EAChB,WAAW,GACX,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,4BAA4B,EAAE,MAAM,YAAY,CAAC"}
package/dist/queries.d.ts CHANGED
@@ -1,15 +1,53 @@
1
1
  import type { Pool, QueryResultRow } from "pg";
2
+ import { z } from "zod";
2
3
  import { type RlsClaims, type RlsOptions } from "./rls.js";
4
+ /**
5
+ * A raw result shaped like pg's `QueryResult` or Drizzle's `tx.execute()` output
6
+ * — just the `rows`. Consumed by {@link parseRows} / {@link parseMaybeRow} /
7
+ * {@link parseOneRow}, which validate that array against a Zod schema.
8
+ */
9
+ export interface RowsResult {
10
+ rows: readonly unknown[];
11
+ }
3
12
  export interface Queries {
4
- /** Run a query and return all rows. */
5
- query: <T extends QueryResultRow = QueryResultRow>(text: string, params?: unknown[]) => Promise<T[]>;
13
+ /**
14
+ * Run a query and return all rows. Pass a Zod row `schema` as the third
15
+ * argument to validate (and coerce) every row instead of trusting a `<T>`
16
+ * cast — the schema is also where `numeric`/timestamp coercion belongs
17
+ * (`z.coerce.number()`, an ISO transform), per the no-`as`-on-external-input
18
+ * rule.
19
+ */
20
+ query: {
21
+ <T extends QueryResultRow = QueryResultRow>(text: string, params?: unknown[]): Promise<T[]>;
22
+ <S extends z.ZodType>(text: string, params: unknown[] | undefined, schema: S): Promise<z.output<S>[]>;
23
+ };
6
24
  /** Run a query expected to return at most one row; `null` when none. */
7
- maybeOne: <T extends QueryResultRow = QueryResultRow>(text: string, params?: unknown[]) => Promise<T | null>;
25
+ maybeOne: {
26
+ <T extends QueryResultRow = QueryResultRow>(text: string, params?: unknown[]): Promise<T | null>;
27
+ <S extends z.ZodType>(text: string, params: unknown[] | undefined, schema: S): Promise<z.output<S> | null>;
28
+ };
8
29
  /** Run a query that must return exactly one row; throws otherwise. */
9
- one: <T extends QueryResultRow = QueryResultRow>(text: string, params?: unknown[]) => Promise<T>;
30
+ one: {
31
+ <T extends QueryResultRow = QueryResultRow>(text: string, params?: unknown[]): Promise<T>;
32
+ <S extends z.ZodType>(text: string, params: unknown[] | undefined, schema: S): Promise<z.output<S>>;
33
+ };
10
34
  /** Run a write and return the affected row count. */
11
35
  execute: (text: string, params?: unknown[]) => Promise<number>;
12
36
  }
37
+ /**
38
+ * Validate the `rows` of a raw result (a pg `QueryResult` or the output of
39
+ * Drizzle's `tx.execute()`) against a Zod row schema, returning the parsed rows.
40
+ *
41
+ * This is the result-side counterpart to {@link Queries.query}'s `schema` arg,
42
+ * for the Drizzle RLS path: inside `withRlsTransaction`, `tx.execute()` hands
43
+ * back an untyped `{ rows }`, and this gives it the same validated/coerced
44
+ * result the pool helpers have. The schema doubles as the coercion layer.
45
+ */
46
+ export declare const parseRows: <S extends z.ZodType>(result: RowsResult, schema: S) => z.output<S>[];
47
+ /** Like {@link parseRows} but for at most one row; `null` when none. */
48
+ export declare const parseMaybeRow: <S extends z.ZodType>(result: RowsResult, schema: S) => z.output<S> | null;
49
+ /** Like {@link parseRows} but requires exactly one row; throws otherwise. */
50
+ export declare const parseOneRow: <S extends z.ZodType>(result: RowsResult, schema: S) => z.output<S>;
13
51
  export interface PoolQueries extends Queries {
14
52
  /**
15
53
  * Run `fn` inside a single transaction on a dedicated client (`begin` /
@@ -1 +1 @@
1
- {"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../src/queries.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAc,cAAc,EAAE,MAAM,IAAI,CAAC;AAC3D,OAAO,EACN,KAAK,SAAS,EACd,KAAK,UAAU,EAGf,MAAM,UAAU,CAAC;AAKlB,MAAM,WAAW,OAAO;IACvB,uCAAuC;IACvC,KAAK,EAAE,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc,EAChD,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,OAAO,EAAE,KACd,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;IAClB,wEAAwE;IACxE,QAAQ,EAAE,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc,EACnD,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,OAAO,EAAE,KACd,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACvB,sEAAsE;IACtE,GAAG,EAAE,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc,EAC9C,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,OAAO,EAAE,KACd,OAAO,CAAC,CAAC,CAAC,CAAC;IAChB,qDAAqD;IACrD,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAC/D;AAoCD,MAAM,WAAW,WAAY,SAAQ,OAAO;IAC3C;;;;;OAKG;IACH,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IAC3D;;;;;;;OAOG;IACH,OAAO,EAAE,CAAC,CAAC,EACV,MAAM,EAAE,SAAS,EACjB,EAAE,EAAE,CAAC,EAAE,EAAE,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,EAC/B,OAAO,CAAC,EAAE,UAAU,KAChB,OAAO,CAAC,CAAC,CAAC,CAAC;CAChB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,IAAI,KAAG,WAkC1C,CAAC"}
1
+ {"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../src/queries.ts"],"names":[],"mappings":"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"}
package/dist/queries.js CHANGED
@@ -1,29 +1,58 @@
1
1
  import { resolveRlsConfig, rlsPreamble, } from "./rls.js";
2
2
  const bind = (executor) => {
3
- const query = async (text, params = []) => {
3
+ async function query(text, params = [], schema) {
4
4
  const result = await executor.query(text, params);
5
- return result.rows;
6
- };
7
- const maybeOne = async (text, params = []) => {
8
- const rows = await query(text, params);
9
- return rows[0] ?? null;
10
- };
11
- const one = async (text, params = []) => {
12
- const rows = await query(text, params);
13
- const row = rows[0];
14
- if (!row)
5
+ return schema ? result.rows.map((row) => schema.parse(row)) : result.rows;
6
+ }
7
+ async function maybeOne(text, params = [], schema) {
8
+ const result = await executor.query(text, params);
9
+ const first = result.rows[0];
10
+ if (first === undefined)
11
+ return null;
12
+ return schema ? schema.parse(first) : first;
13
+ }
14
+ async function one(text, params = [], schema) {
15
+ const result = await executor.query(text, params);
16
+ if (result.rows.length === 0) {
15
17
  throw new Error("Expected exactly one row, got none");
16
- if (rows.length > 1) {
17
- throw new Error(`Expected exactly one row, got ${rows.length}`);
18
18
  }
19
- return row;
20
- };
19
+ if (result.rows.length > 1) {
20
+ throw new Error(`Expected exactly one row, got ${result.rows.length}`);
21
+ }
22
+ const row = result.rows[0];
23
+ return schema ? schema.parse(row) : row;
24
+ }
21
25
  const execute = async (text, params = []) => {
22
26
  const result = await executor.query(text, params);
23
27
  return result.rowCount ?? 0;
24
28
  };
25
29
  return { query, maybeOne, one, execute };
26
30
  };
31
+ /**
32
+ * Validate the `rows` of a raw result (a pg `QueryResult` or the output of
33
+ * Drizzle's `tx.execute()`) against a Zod row schema, returning the parsed rows.
34
+ *
35
+ * This is the result-side counterpart to {@link Queries.query}'s `schema` arg,
36
+ * for the Drizzle RLS path: inside `withRlsTransaction`, `tx.execute()` hands
37
+ * back an untyped `{ rows }`, and this gives it the same validated/coerced
38
+ * result the pool helpers have. The schema doubles as the coercion layer.
39
+ */
40
+ export const parseRows = (result, schema) => result.rows.map((row) => schema.parse(row));
41
+ /** Like {@link parseRows} but for at most one row; `null` when none. */
42
+ export const parseMaybeRow = (result, schema) => {
43
+ const first = result.rows[0];
44
+ return first === undefined ? null : schema.parse(first);
45
+ };
46
+ /** Like {@link parseRows} but requires exactly one row; throws otherwise. */
47
+ export const parseOneRow = (result, schema) => {
48
+ if (result.rows.length === 0) {
49
+ throw new Error("Expected exactly one row, got none");
50
+ }
51
+ if (result.rows.length > 1) {
52
+ throw new Error(`Expected exactly one row, got ${result.rows.length}`);
53
+ }
54
+ return schema.parse(result.rows[0]);
55
+ };
27
56
  /**
28
57
  * Bind the raw-SQL helpers (`query` / `one` / `maybeOne` / `execute` / `withTx`)
29
58
  * to a pool. Signatures match what apps hand-rolled, so adopting
@@ -1 +1 @@
1
- {"version":3,"file":"queries.js","sourceRoot":"","sources":["../src/queries.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"queries.js","sourceRoot":"","sources":["../src/queries.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ingram-tech/nk-db",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "The Ingram Postgres data layer: one TLS-aware pg pool, raw-SQL helpers, Drizzle wiring, and a PGlite (no-Docker) dev/test harness for Next.js sites.",
5
5
  "license": "MIT",
6
6
  "type": "module",