@typesql/postgres 0.0.3 → 0.0.4

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @typesql/postgres
2
2
 
3
+ ## 0.0.4
4
+
5
+ ### Patch Changes
6
+
7
+ - Queries have `executeCount()`, which resolves to the affected row count: an `Executor` may resolve to `{ rows, rowCount }` instead of the rows, as the `executor()` of `@typesql/pg`, `@typesql/postgres` and `@typesql/kysely` now do.
8
+
9
+ - `execute(db, q)` resolves to 0 instead of `null` for statements without a count, such as DDL, and `PostgresJsRows["count"]` is `number | null`.
10
+
11
+ - `createSql(executor, { rowKeys: "camelCase" })` (and the adapters' `createSql(client, { rowKeys: "camelCase" })`) camelCases the top-level row keys the way Kysely's `CamelCasePlugin` does, in the row types and in the rows `execute*` and the `query`/`one`/`maybeOne`/`many` helpers return, leaving JSON values untouched.
12
+
13
+ - The type maps declare what parameters accept (`PgParamTypeMap`, `PostgresJsParamTypeMap`), so `int8`/`numeric` parameters take numbers and bigints and timestamp parameters take strings; postgres.js timestamp parameters also take epoch milliseconds.
14
+
15
+ - Updated dependencies:
16
+ - @typesql/core@0.0.4
17
+
3
18
  ## 0.0.3
4
19
 
5
20
  ### Patch Changes
package/README.md CHANGED
@@ -42,16 +42,17 @@ const counts = await query(dbBig, big("SELECT author_id, count(*) AS n FROM post
42
42
 
43
43
  | Export | |
44
44
  |---|---|
45
- | `createSql<DB>()` | core's `createSql<DB, PostgresJsTypeMap>()` |
46
- | `createBigIntSql<DB>()` | core's `createSql<DB, PostgresJsBigIntTypeMap>()`, for `types: { bigint: postgres.BigInt }` |
45
+ | `createSql<DB>(db?, options?)` | core's `createSql<DB, PostgresJsTypeMap>()`; `{ rowKeys: "camelCase" }` camelCases the row keys |
46
+ | `createBigIntSql<DB>(db?, options?)` | core's `createSql<DB, PostgresJsBigIntTypeMap>()`, for `types: { bigint: postgres.BigInt }` |
47
47
  | `query(db, q)` | `Promise<Row[]>` (a plain array, result metadata stripped) |
48
48
  | `one(db, q)` | `Promise<Row>`; `RowCountError` unless exactly one row |
49
49
  | `maybeOne(db, q)` | `Promise<Row \| null>`; `RowCountError` on more than one row |
50
50
  | `many(db, q)` | `Promise<[Row, ...Row[]]>`; `RowCountError` on zero rows |
51
- | `execute(db, q)` | `Promise<number>`, the affected row count |
51
+ | `execute(db, q)` | `Promise<number>`, the affected row count (0 for DDL) |
52
+ | `executor(db)` | an `Executor` for `q.execute()` and `q.executeCount()` (reports `.count`); `createSql<DB>(db)` binds one |
52
53
  | `transaction(db, fn)` | `db.begin(fn)` |
53
54
  | `migrate(db, m)` | runs `m.statements` (e.g. from core's `migrations()`) in one transaction |
54
- | `PostgresJsTypeMap`, `PostgresJsBigIntTypeMap` | the type maps |
55
+ | `PostgresJsTypeMap`, `PostgresJsBigIntTypeMap`, `PostgresJsParamTypeMap` | the type maps (rows), and what parameters also accept |
55
56
  | `RowCountError`, `PostgresJsQueryable`, `PostgresJsTransactable`, `PostgresJsRows`, `MigrationSource` | errors and parameter types |
56
57
 
57
58
  Queries run with `db.unsafe(text, values)`, so the text reaches the server unchanged and values
@@ -73,3 +74,8 @@ postgres.js parses only a few types by default; everything else is the text Post
73
74
 
74
75
  Arrays map element-wise. Details in the
75
76
  [Adapters guide](https://github.com/ismailkarsli/typesql/blob/main/packages/docs/guide/adapters.md).
77
+
78
+ Parameters accept the row type and what postgres.js serializes for the type
79
+ (`PostgresJsParamTypeMap`): `number | bigint | string` for `int8`, `numeric` and `money`,
80
+ `Date | string | number` (epoch ms) for dates and timestamps, `string` for `interval`,
81
+ `Uint8Array` for `bytea`.
package/dist/client.d.ts CHANGED
@@ -1,7 +1,10 @@
1
- import type { Executor, Query, RowType } from "@typesql/core";
2
- /** The shape of a resolved `sql.unsafe()` result the helpers rely on: an array with `count`. */
1
+ import { type Executor, type Query, type RowType } from "@typesql/core";
2
+ /**
3
+ * The shape of a resolved `sql.unsafe()` result the helpers rely on: an array with `count`
4
+ * (`null` for statements without a count, such as DDL).
5
+ */
3
6
  export type PostgresJsRows = readonly unknown[] & {
4
- readonly count: number;
7
+ readonly count: number | null;
5
8
  };
6
9
  /**
7
10
  * Anything with postgres.js' `unsafe(query, parameters)` method: the `Sql` instance,
@@ -24,7 +27,10 @@ export declare class RowCountError extends Error {
24
27
  constructor(code: "NO_ROWS" | "TOO_MANY_ROWS", expected: string, actual: number, text: string);
25
28
  }
26
29
  type AnyQuery = Query<unknown, readonly unknown[]>;
27
- /** An `Executor` for core's `q.execute()`: runs queries through `sql.unsafe` and resolves to the rows. */
30
+ /**
31
+ * An `Executor` for core's `q.execute()`: runs queries through `sql.unsafe` and resolves to
32
+ * `{ rows, rowCount }` (postgres.js' `.count`, so `q.executeCount()` works).
33
+ */
28
34
  export declare function executor(sql: PostgresJsQueryable): Executor;
29
35
  /** Run a query and return all rows (a plain array, without postgres.js' result metadata). */
30
36
  export declare function query<Q extends AnyQuery>(sql: PostgresJsQueryable, q: Q): Promise<RowType<Q>[]>;
@@ -34,7 +40,7 @@ export declare function one<Q extends AnyQuery>(sql: PostgresJsQueryable, q: Q):
34
40
  export declare function maybeOne<Q extends AnyQuery>(sql: PostgresJsQueryable, q: Q): Promise<RowType<Q> | null>;
35
41
  /** At least one row, otherwise throws `RowCountError`. */
36
42
  export declare function many<Q extends AnyQuery>(sql: PostgresJsQueryable, q: Q): Promise<[RowType<Q>, ...RowType<Q>[]]>;
37
- /** Run a statement for its side effect and return the affected row count (postgres.js' `.count`). */
43
+ /** Run a statement for its side effect and return the affected row count (postgres.js' `.count`, 0 when it is `null`). */
38
44
  export declare function execute(sql: PostgresJsQueryable, q: AnyQuery): Promise<number>;
39
45
  /**
40
46
  * Run `fn` inside `sql.begin()`: postgres.js issues BEGIN, runs the callback with a
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/client.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { mapRows } from "@typesql/core";
1
2
  /** Thrown by `one`, `maybeOne` and `many` when the row count does not match. */
2
3
  export class RowCountError extends Error {
3
4
  code;
@@ -16,14 +17,20 @@ export class RowCountError extends Error {
16
17
  function run(sql, q) {
17
18
  return sql.unsafe(q.text, Array.from(q.values));
18
19
  }
19
- /** An `Executor` for core's `q.execute()`: runs queries through `sql.unsafe` and resolves to the rows. */
20
+ /**
21
+ * An `Executor` for core's `q.execute()`: runs queries through `sql.unsafe` and resolves to
22
+ * `{ rows, rowCount }` (postgres.js' `.count`, so `q.executeCount()` works).
23
+ */
20
24
  export function executor(sql) {
21
- return async (text, values) => Array.from(await sql.unsafe(text, Array.from(values)));
25
+ return async (text, values) => {
26
+ const result = await sql.unsafe(text, Array.from(values));
27
+ return { rows: Array.from(result), rowCount: result.count ?? null };
28
+ };
22
29
  }
23
30
  /** Run a query and return all rows (a plain array, without postgres.js' result metadata). */
24
31
  export async function query(sql, q) {
25
32
  const result = await run(sql, q);
26
- return Array.from(result);
33
+ return mapRows(q, Array.from(result));
27
34
  }
28
35
  /** Exactly one row, otherwise throws `RowCountError`. */
29
36
  export async function one(sql, q) {
@@ -47,10 +54,10 @@ export async function many(sql, q) {
47
54
  throw new RowCountError("NO_ROWS", "at least 1", 0, q.text);
48
55
  return rows;
49
56
  }
50
- /** Run a statement for its side effect and return the affected row count (postgres.js' `.count`). */
57
+ /** Run a statement for its side effect and return the affected row count (postgres.js' `.count`, 0 when it is `null`). */
51
58
  export async function execute(sql, q) {
52
59
  const result = await run(sql, q);
53
- return result.count;
60
+ return result.count ?? 0;
54
61
  }
55
62
  /**
56
63
  * Run `fn` inside `sql.begin()`: postgres.js issues BEGIN, runs the callback with a
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -2,13 +2,24 @@ import { type Sql } from "@typesql/core";
2
2
  import { type PostgresJsQueryable } from "./client.js";
3
3
  import type { PostgresJsBigIntTypeMap, PostgresJsTypeMap } from "./type-map.js";
4
4
  export { NoResultError, type Executor } from "@typesql/core";
5
- export type { PostgresJsTypeMap, PostgresJsBigIntTypeMap } from "./type-map.js";
5
+ export type { PostgresJsTypeMap, PostgresJsBigIntTypeMap, PostgresJsParamTypeMap } from "./type-map.js";
6
6
  export { query, one, maybeOne, many, execute, executor, transaction, migrate, type MigrationSource, RowCountError, type PostgresJsQueryable, type PostgresJsRows, type PostgresJsTransactable, } from "./client.js";
7
7
  /**
8
8
  * `createSql<DB>()` from core, pre-bound to `PostgresJsTypeMap` (default parsers: `int8` and `count(*)` are `string`).
9
9
  * With a postgres.js `sql` instance, the queries' `execute*` methods run on it.
10
+ * `{ rowKeys: "camelCase" }` camelCases the rows' keys, in the types and at runtime.
10
11
  */
11
- export declare function createSql<DB>(sql?: PostgresJsQueryable): Sql<DB, PostgresJsTypeMap>;
12
+ export declare function createSql<DB>(sql: PostgresJsQueryable | undefined, options: {
13
+ readonly rowKeys: "camelCase";
14
+ }): Sql<DB, PostgresJsTypeMap, "camelCase">;
15
+ export declare function createSql<DB>(sql?: PostgresJsQueryable, options?: {
16
+ readonly rowKeys?: "preserve";
17
+ }): Sql<DB, PostgresJsTypeMap>;
12
18
  /** For `postgres({ types: { bigint: postgres.BigInt } })` connections: `int8` and `count(*)` are `bigint`. */
13
- export declare function createBigIntSql<DB>(sql?: PostgresJsQueryable): Sql<DB, PostgresJsBigIntTypeMap>;
19
+ export declare function createBigIntSql<DB>(sql: PostgresJsQueryable | undefined, options: {
20
+ readonly rowKeys: "camelCase";
21
+ }): Sql<DB, PostgresJsBigIntTypeMap, "camelCase">;
22
+ export declare function createBigIntSql<DB>(sql?: PostgresJsQueryable, options?: {
23
+ readonly rowKeys?: "preserve";
24
+ }): Sql<DB, PostgresJsBigIntTypeMap>;
14
25
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,KAAK,GAAG,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,EAAY,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,KAAK,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEhF,OAAO,EAAE,aAAa,EAAE,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC7D,YAAY,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EACL,KAAK,EACL,GAAG,EACH,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,WAAW,EACX,OAAO,EACP,KAAK,eAAe,EACpB,aAAa,EACb,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,sBAAsB,GAC5B,MAAM,aAAa,CAAC;AAErB;;;GAGG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,mBAAmB,GAAG,GAAG,CAAC,EAAE,EAAE,iBAAiB,CAAC,CAEnF;AAED,8GAA8G;AAC9G,wBAAgB,eAAe,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,mBAAmB,GAAG,GAAG,CAAC,EAAE,EAAE,uBAAuB,CAAC,CAE/F"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4C,KAAK,GAAG,EAAmB,MAAM,eAAe,CAAC;AACpG,OAAO,EAAY,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,KAAK,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEhF,OAAO,EAAE,aAAa,EAAE,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC7D,YAAY,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACxG,OAAO,EACL,KAAK,EACL,GAAG,EACH,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,WAAW,EACX,OAAO,EACP,KAAK,eAAe,EACpB,aAAa,EACb,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,sBAAsB,GAC5B,MAAM,aAAa,CAAC;AAErB;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,GAAG,EAAE,mBAAmB,GAAG,SAAS,EAAE,OAAO,EAAE;IAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;CAAE,GAAG,GAAG,CAAC,EAAE,EAAE,iBAAiB,EAAE,WAAW,CAAC,CAAC;AACzJ,wBAAgB,SAAS,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,mBAAmB,EAAE,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,UAAU,CAAA;CAAE,GAAG,GAAG,CAAC,EAAE,EAAE,iBAAiB,CAAC,CAAC;AAKlI,8GAA8G;AAC9G,wBAAgB,eAAe,CAAC,EAAE,EAAE,GAAG,EAAE,mBAAmB,GAAG,SAAS,EAAE,OAAO,EAAE;IAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;CAAE,GAAG,GAAG,CAAC,EAAE,EAAE,uBAAuB,EAAE,WAAW,CAAC,CAAC;AACrK,wBAAgB,eAAe,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,mBAAmB,EAAE,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,UAAU,CAAA;CAAE,GAAG,GAAG,CAAC,EAAE,EAAE,uBAAuB,CAAC,CAAC"}
package/dist/index.js CHANGED
@@ -2,15 +2,10 @@ import { createSql as createCoreSql } from "@typesql/core";
2
2
  import { executor } from "./client.js";
3
3
  export { NoResultError } from "@typesql/core";
4
4
  export { query, one, maybeOne, many, execute, executor, transaction, migrate, RowCountError, } from "./client.js";
5
- /**
6
- * `createSql<DB>()` from core, pre-bound to `PostgresJsTypeMap` (default parsers: `int8` and `count(*)` are `string`).
7
- * With a postgres.js `sql` instance, the queries' `execute*` methods run on it.
8
- */
9
- export function createSql(sql) {
10
- return createCoreSql(sql && executor(sql));
5
+ export function createSql(sql, options) {
6
+ return createCoreSql(sql && executor(sql), options);
11
7
  }
12
- /** For `postgres({ types: { bigint: postgres.BigInt } })` connections: `int8` and `count(*)` are `bigint`. */
13
- export function createBigIntSql(sql) {
14
- return createCoreSql(sql && executor(sql));
8
+ export function createBigIntSql(sql, options) {
9
+ return createCoreSql(sql && executor(sql), options);
15
10
  }
16
11
  //# 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,OAAO,EAAE,SAAS,IAAI,aAAa,EAAY,MAAM,eAAe,CAAC;AACrE,OAAO,EAAE,QAAQ,EAA4B,MAAM,aAAa,CAAC;AAGjE,OAAO,EAAE,aAAa,EAAiB,MAAM,eAAe,CAAC;AAE7D,OAAO,EACL,KAAK,EACL,GAAG,EACH,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,WAAW,EACX,OAAO,EAEP,aAAa,GAId,MAAM,aAAa,CAAC;AAErB;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAK,GAAyB;IACrD,OAAO,aAAa,CAAwB,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;AACpE,CAAC;AAED,8GAA8G;AAC9G,MAAM,UAAU,eAAe,CAAK,GAAyB;IAC3D,OAAO,aAAa,CAA8B,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1E,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,IAAI,aAAa,EAA2C,MAAM,eAAe,CAAC;AACpG,OAAO,EAAE,QAAQ,EAA4B,MAAM,aAAa,CAAC;AAGjE,OAAO,EAAE,aAAa,EAAiB,MAAM,eAAe,CAAC;AAE7D,OAAO,EACL,KAAK,EACL,GAAG,EACH,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,WAAW,EACX,OAAO,EAEP,aAAa,GAId,MAAM,aAAa,CAAC;AASrB,MAAM,UAAU,SAAS,CAAK,GAAyB,EAAE,OAAoB;IAC3E,OAAO,aAAa,CAAwB,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC,EAAE,OAA4C,CAAC,CAAC;AAClH,CAAC;AAKD,MAAM,UAAU,eAAe,CAAK,GAAyB,EAAE,OAAoB;IACjF,OAAO,aAAa,CAA8B,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC,EAAE,OAA4C,CAAC,CAAC;AACxH,CAAC"}
@@ -1,4 +1,4 @@
1
- import type { DefaultTypeMap } from "@typesql/core";
1
+ import type { DefaultParamTypeMap, DefaultTypeMap } from "@typesql/core";
2
2
  /**
3
3
  * Canonical Postgres type name → TS type as postgres.js 3.x returns it with its default
4
4
  * parsers. Verified against `postgres/src/types.js` (3.4.9), which parses only:
@@ -22,6 +22,8 @@ import type { DefaultTypeMap } from "@typesql/core";
22
22
  * element-type[] mapping is exact (int8[] → string[], timestamptz[] → Date[], ...).
23
23
  */
24
24
  export interface PostgresJsTypeMap extends Omit<DefaultTypeMap, "bytea" | "interval" | "point" | "circle" | "record" | "void"> {
25
+ /** What parameters accept on top of the row types. */
26
+ $params: PostgresJsParamTypeMap;
25
27
  bytea: Buffer;
26
28
  /** No default parser: the Postgres text form, e.g. `"1 day 02:00:00"`. */
27
29
  interval: string;
@@ -34,6 +36,25 @@ export interface PostgresJsTypeMap extends Omit<DefaultTypeMap, "bytea" | "inter
34
36
  /** `void`-returning functions (`pg_sleep`) yield an empty string. */
35
37
  void: string;
36
38
  }
39
+ /**
40
+ * TS types postgres.js parameters accept on top of the row type
41
+ * (`PostgresJsTypeMap["$params"]`). Verified against `postgres/src/types.js` and `Bind` in
42
+ * `connection.js` (3.4.9): a value is serialized by the serializer of the parameter type the
43
+ * server reports, and types without one (int8, numeric, money, interval, …) with `'' + x`.
44
+ *
45
+ * int8, numeric, money number | bigint | string
46
+ * date, timestamp, timestamptz Date | string | number: serialized as `new Date(x).toISOString()`,
47
+ * so a string must be one JS `Date` parses, a number is epoch ms
48
+ * interval string
49
+ * bytea Uint8Array, besides `Buffer`
50
+ *
51
+ * `bool` takes only booleans: its serializer sends `'f'` for anything but `true`.
52
+ */
53
+ export interface PostgresJsParamTypeMap extends Omit<DefaultParamTypeMap, "date" | "timestamp" | "timestamptz"> {
54
+ date: Date | string | number;
55
+ timestamp: Date | string | number;
56
+ timestamptz: Date | string | number;
57
+ }
37
58
  /**
38
59
  * Type map for connections created with `postgres({ types: { bigint: postgres.BigInt } })`,
39
60
  * which registers a parser for int8 (20) that returns JS `bigint`. `count(*)`, `sum(int4)`
@@ -1 +1 @@
1
- {"version":3,"file":"type-map.d.ts","sourceRoot":"","sources":["../src/type-map.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,cAAc,EAAE,OAAO,GAAG,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC5H,KAAK,EAAE,MAAM,CAAC;IACd,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,CAAC;IACjB,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;GAKG;AACH,MAAM,WAAW,uBAAwB,SAAQ,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC;IAC9E,IAAI,EAAE,MAAM,CAAC;CACd"}
1
+ {"version":3,"file":"type-map.d.ts","sourceRoot":"","sources":["../src/type-map.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEzE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,cAAc,EAAE,OAAO,GAAG,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC5H,sDAAsD;IACtD,OAAO,EAAE,sBAAsB,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,CAAC;IACjB,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,sBAAuB,SAAQ,IAAI,CAAC,mBAAmB,EAAE,MAAM,GAAG,WAAW,GAAG,aAAa,CAAC;IAC7G,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;IAC7B,SAAS,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;IAClC,WAAW,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;CACrC;AAED;;;;;GAKG;AACH,MAAM,WAAW,uBAAwB,SAAQ,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC;IAC9E,IAAI,EAAE,MAAM,CAAC;CACd"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typesql/postgres",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "description": "postgres.js adapter for typesql.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -28,7 +28,7 @@
28
28
  "access": "public"
29
29
  },
30
30
  "dependencies": {
31
- "@typesql/core": "0.0.3"
31
+ "@typesql/core": "0.0.4"
32
32
  },
33
33
  "peerDependencies": {
34
34
  "postgres": ">=3"
package/src/client.ts CHANGED
@@ -1,7 +1,10 @@
1
- import type { Executor, Query, RowType } from "@typesql/core";
1
+ import { mapRows, type Executor, type Query, type RowType } from "@typesql/core";
2
2
 
3
- /** The shape of a resolved `sql.unsafe()` result the helpers rely on: an array with `count`. */
4
- export type PostgresJsRows = readonly unknown[] & { readonly count: number };
3
+ /**
4
+ * The shape of a resolved `sql.unsafe()` result the helpers rely on: an array with `count`
5
+ * (`null` for statements without a count, such as DDL).
6
+ */
7
+ export type PostgresJsRows = readonly unknown[] & { readonly count: number | null };
5
8
 
6
9
  /**
7
10
  * Anything with postgres.js' `unsafe(query, parameters)` method: the `Sql` instance,
@@ -35,15 +38,21 @@ function run(sql: PostgresJsQueryable, q: AnyQuery): PromiseLike<PostgresJsRows>
35
38
  return sql.unsafe(q.text, Array.from(q.values));
36
39
  }
37
40
 
38
- /** An `Executor` for core's `q.execute()`: runs queries through `sql.unsafe` and resolves to the rows. */
41
+ /**
42
+ * An `Executor` for core's `q.execute()`: runs queries through `sql.unsafe` and resolves to
43
+ * `{ rows, rowCount }` (postgres.js' `.count`, so `q.executeCount()` works).
44
+ */
39
45
  export function executor(sql: PostgresJsQueryable): Executor {
40
- return async (text, values) => Array.from(await sql.unsafe(text, Array.from(values)));
46
+ return async (text, values) => {
47
+ const result = await sql.unsafe(text, Array.from(values));
48
+ return { rows: Array.from(result), rowCount: result.count ?? null };
49
+ };
41
50
  }
42
51
 
43
52
  /** Run a query and return all rows (a plain array, without postgres.js' result metadata). */
44
53
  export async function query<Q extends AnyQuery>(sql: PostgresJsQueryable, q: Q): Promise<RowType<Q>[]> {
45
54
  const result = await run(sql, q);
46
- return Array.from(result) as RowType<Q>[];
55
+ return mapRows(q, Array.from(result));
47
56
  }
48
57
 
49
58
  /** Exactly one row, otherwise throws `RowCountError`. */
@@ -69,10 +78,10 @@ export async function many<Q extends AnyQuery>(sql: PostgresJsQueryable, q: Q):
69
78
  return rows as [RowType<Q>, ...RowType<Q>[]];
70
79
  }
71
80
 
72
- /** Run a statement for its side effect and return the affected row count (postgres.js' `.count`). */
81
+ /** Run a statement for its side effect and return the affected row count (postgres.js' `.count`, 0 when it is `null`). */
73
82
  export async function execute(sql: PostgresJsQueryable, q: AnyQuery): Promise<number> {
74
83
  const result = await run(sql, q);
75
- return result.count;
84
+ return result.count ?? 0;
76
85
  }
77
86
 
78
87
  /**
package/src/index.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { createSql as createCoreSql, type Sql } from "@typesql/core";
1
+ import { createSql as createCoreSql, type RowKeys, type Sql, type SqlOptions } from "@typesql/core";
2
2
  import { executor, type PostgresJsQueryable } from "./client.js";
3
3
  import type { PostgresJsBigIntTypeMap, PostgresJsTypeMap } from "./type-map.js";
4
4
 
5
5
  export { NoResultError, type Executor } from "@typesql/core";
6
- export type { PostgresJsTypeMap, PostgresJsBigIntTypeMap } from "./type-map.js";
6
+ export type { PostgresJsTypeMap, PostgresJsBigIntTypeMap, PostgresJsParamTypeMap } from "./type-map.js";
7
7
  export {
8
8
  query,
9
9
  one,
@@ -23,12 +23,17 @@ export {
23
23
  /**
24
24
  * `createSql<DB>()` from core, pre-bound to `PostgresJsTypeMap` (default parsers: `int8` and `count(*)` are `string`).
25
25
  * With a postgres.js `sql` instance, the queries' `execute*` methods run on it.
26
+ * `{ rowKeys: "camelCase" }` camelCases the rows' keys, in the types and at runtime.
26
27
  */
27
- export function createSql<DB>(sql?: PostgresJsQueryable): Sql<DB, PostgresJsTypeMap> {
28
- return createCoreSql<DB, PostgresJsTypeMap>(sql && executor(sql));
28
+ export function createSql<DB>(sql: PostgresJsQueryable | undefined, options: { readonly rowKeys: "camelCase" }): Sql<DB, PostgresJsTypeMap, "camelCase">;
29
+ export function createSql<DB>(sql?: PostgresJsQueryable, options?: { readonly rowKeys?: "preserve" }): Sql<DB, PostgresJsTypeMap>;
30
+ export function createSql<DB>(sql?: PostgresJsQueryable, options?: SqlOptions): Sql<DB, PostgresJsTypeMap, RowKeys> {
31
+ return createCoreSql<DB, PostgresJsTypeMap>(sql && executor(sql), options as { readonly rowKeys: "camelCase" });
29
32
  }
30
33
 
31
34
  /** For `postgres({ types: { bigint: postgres.BigInt } })` connections: `int8` and `count(*)` are `bigint`. */
32
- export function createBigIntSql<DB>(sql?: PostgresJsQueryable): Sql<DB, PostgresJsBigIntTypeMap> {
33
- return createCoreSql<DB, PostgresJsBigIntTypeMap>(sql && executor(sql));
35
+ export function createBigIntSql<DB>(sql: PostgresJsQueryable | undefined, options: { readonly rowKeys: "camelCase" }): Sql<DB, PostgresJsBigIntTypeMap, "camelCase">;
36
+ export function createBigIntSql<DB>(sql?: PostgresJsQueryable, options?: { readonly rowKeys?: "preserve" }): Sql<DB, PostgresJsBigIntTypeMap>;
37
+ export function createBigIntSql<DB>(sql?: PostgresJsQueryable, options?: SqlOptions): Sql<DB, PostgresJsBigIntTypeMap, RowKeys> {
38
+ return createCoreSql<DB, PostgresJsBigIntTypeMap>(sql && executor(sql), options as { readonly rowKeys: "camelCase" });
34
39
  }
package/src/type-map.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { DefaultTypeMap } from "@typesql/core";
1
+ import type { DefaultParamTypeMap, DefaultTypeMap } from "@typesql/core";
2
2
 
3
3
  /**
4
4
  * Canonical Postgres type name → TS type as postgres.js 3.x returns it with its default
@@ -23,6 +23,8 @@ import type { DefaultTypeMap } from "@typesql/core";
23
23
  * element-type[] mapping is exact (int8[] → string[], timestamptz[] → Date[], ...).
24
24
  */
25
25
  export interface PostgresJsTypeMap extends Omit<DefaultTypeMap, "bytea" | "interval" | "point" | "circle" | "record" | "void"> {
26
+ /** What parameters accept on top of the row types. */
27
+ $params: PostgresJsParamTypeMap;
26
28
  bytea: Buffer;
27
29
  /** No default parser: the Postgres text form, e.g. `"1 day 02:00:00"`. */
28
30
  interval: string;
@@ -36,6 +38,26 @@ export interface PostgresJsTypeMap extends Omit<DefaultTypeMap, "bytea" | "inter
36
38
  void: string;
37
39
  }
38
40
 
41
+ /**
42
+ * TS types postgres.js parameters accept on top of the row type
43
+ * (`PostgresJsTypeMap["$params"]`). Verified against `postgres/src/types.js` and `Bind` in
44
+ * `connection.js` (3.4.9): a value is serialized by the serializer of the parameter type the
45
+ * server reports, and types without one (int8, numeric, money, interval, …) with `'' + x`.
46
+ *
47
+ * int8, numeric, money number | bigint | string
48
+ * date, timestamp, timestamptz Date | string | number: serialized as `new Date(x).toISOString()`,
49
+ * so a string must be one JS `Date` parses, a number is epoch ms
50
+ * interval string
51
+ * bytea Uint8Array, besides `Buffer`
52
+ *
53
+ * `bool` takes only booleans: its serializer sends `'f'` for anything but `true`.
54
+ */
55
+ export interface PostgresJsParamTypeMap extends Omit<DefaultParamTypeMap, "date" | "timestamp" | "timestamptz"> {
56
+ date: Date | string | number;
57
+ timestamp: Date | string | number;
58
+ timestamptz: Date | string | number;
59
+ }
60
+
39
61
  /**
40
62
  * Type map for connections created with `postgres({ types: { bigint: postgres.BigInt } })`,
41
63
  * which registers a parser for int8 (20) that returns JS `bigint`. `count(*)`, `sum(int4)`