@typesql/pg 0.2.5 → 0.2.6

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,14 @@
1
1
  # @typesql/pg
2
2
 
3
+ ## 0.2.6
4
+
5
+ ### Patch Changes
6
+
7
+ - Execute sql.prepare() queries as named prepared statements cached per connection by node-postgres.
8
+
9
+ - Updated dependencies:
10
+ - @typesql/core@0.7.3
11
+
3
12
  ## 0.2.5
4
13
 
5
14
  ### Patch Changes
package/README.md CHANGED
@@ -46,6 +46,15 @@ npx typesql introspect --url postgres://localhost/app --out src/db/schema.ts
46
46
  - [From a live database](https://typesql.karsli.net/guide/introspect): `typesql introspect` options
47
47
  - [Type mapping](https://typesql.karsli.net/reference/type-mapping#node-postgres): the TypeScript type of every Postgres type
48
48
 
49
+ ## Prepared statements
50
+
51
+ ```ts
52
+ const findUser = sql.prepare("SELECT id, email FROM users WHERE id = $1");
53
+ const user = await findUser(7).executeTakeFirst();
54
+ ```
55
+
56
+ Reuse `findUser` with new values. TypeSQL assembles the SQL once and node-postgres caches a named statement per connection; the name is derived from the final SQL text. All `execute*` methods work. Named parameters and fixed fragments are supported too. Inside a transaction, use `tx.prepare(...)` to bind it to that transaction.
57
+
49
58
  ## License
50
59
 
51
60
  [MIT](LICENSE)
package/dist/client.d.ts CHANGED
@@ -7,10 +7,16 @@ export interface PgResult {
7
7
  }
8
8
  /**
9
9
  * Anything with node-postgres' `query(text, values)` method: `Pool`, `Client`, `PoolClient`,
10
- * or a fake in tests. Only the `(text, values?) → Promise<{ rows, rowCount }>` form is used.
10
+ * or a fake in tests. Prepared queries use the named query config form.
11
11
  */
12
12
  export interface PgQueryable {
13
- query(text: string, values?: unknown[]): Promise<PgResult>;
13
+ query(text: string | PgQueryConfig, values?: unknown[]): Promise<PgResult>;
14
+ }
15
+ /** A named node-postgres statement. Names are derived from the final SQL text. */
16
+ export interface PgQueryConfig {
17
+ readonly name: string;
18
+ readonly text: string;
19
+ readonly values: unknown[];
14
20
  }
15
21
  /** A client checked out of a pool (`pg.PoolClient`): queryable and releasable. */
16
22
  export interface PgTransactionClient extends PgQueryable {
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvE,+DAA+D;AAC/D,MAAM,WAAW,QAAQ;IACxB,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC3B,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CAC3D;AAED,kFAAkF;AAClF,MAAM,WAAW,mBAAoB,SAAQ,WAAW;IACvD,OAAO,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,IAAI,CAAC;CACrC;AAED,6CAA6C;AAC7C,MAAM,WAAW,UAAU,CAC1B,CAAC,SAAS,mBAAmB,GAAG,mBAAmB;IAEnD,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,QAAQ,CAMtD;AA+DD,6DAA6D;AAC7D,eAAO,MAAM,MAAM,EAAE,SAAS,CAAC,WAAW,CAA6B,CAAC;AAExE,oGAAoG;AACpG,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AAED;;;;GAIG;AACH,wBAAsB,OAAO,CAAC,CAAC,SAAS,mBAAmB,EAC1D,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,EACnB,CAAC,EAAE,eAAe,GAChB,OAAO,CAAC,IAAI,CAAC,CAIf"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvE,+DAA+D;AAC/D,MAAM,WAAW,QAAQ;IACxB,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC3B,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CAC3E;AAED,kFAAkF;AAClF,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;CAC3B;AAED,kFAAkF;AAClF,MAAM,WAAW,mBAAoB,SAAQ,WAAW;IACvD,OAAO,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,IAAI,CAAC;CACrC;AAED,6CAA6C;AAC7C,MAAM,WAAW,UAAU,CAC1B,CAAC,SAAS,mBAAmB,GAAG,mBAAmB;IAEnD,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,QAAQ,CAsBtD;AA+DD,6DAA6D;AAC7D,eAAO,MAAM,MAAM,EAAE,SAAS,CAAC,WAAW,CAA6B,CAAC;AAExE,oGAAoG;AACpG,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AAED;;;;GAIG;AACH,wBAAsB,OAAO,CAAC,CAAC,SAAS,mBAAmB,EAC1D,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,EACnB,CAAC,EAAE,eAAe,GAChB,OAAO,CAAC,IAAI,CAAC,CAIf"}
package/dist/client.js CHANGED
@@ -1,14 +1,28 @@
1
+ import { createHash } from "node:crypto";
1
2
  import { runTransaction } from "@typesql/core/adapter";
2
3
  /**
3
4
  * An `Executor` for core's `q.execute()`: runs queries on `client` and resolves to
4
5
  * `{ rows, rowCount }` (pg's `rowCount`, so `q.executeCount()` works).
5
6
  */
6
7
  export function executor(client) {
7
- return async (text, values) => {
8
+ return Object.assign(async (text, values) => {
8
9
  // `pg` requires a mutable array (`QueryConfigValues<I>` matches `Array<U>` only).
9
10
  const { rows, rowCount } = await client.query(text, Array.from(values));
10
11
  return { rows, rowCount };
11
- };
12
+ }, {
13
+ prepare: (text) => {
14
+ // Keep names stable across factories and connections, within PostgreSQL's 63-byte limit.
15
+ const name = `typesql_${createHash("sha256").update(text).digest("hex").slice(0, 48)}`;
16
+ return async (text, values) => {
17
+ const { rows, rowCount } = await client.query({
18
+ name,
19
+ text,
20
+ values: Array.from(values),
21
+ });
22
+ return { rows, rowCount };
23
+ };
24
+ },
25
+ });
12
26
  }
13
27
  function isPool(client) {
14
28
  // `pg.Client` has `connect()` too (it opens the socket), and `processID`; a `PoolClient` has `release()`.
@@ -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
@@ -1,7 +1,7 @@
1
1
  import type { RowKeys, TransactionalSql } from "@typesql/core";
2
2
  import { type PgQueryable } from "./client.js";
3
3
  import type { PgTypeMap } from "./type-map.js";
4
- export { executor, type MigrationSource, migrate, type PgPoolLike, type PgQueryable, type PgResult, type PgTransactionClient, } from "./client.js";
4
+ export { executor, type MigrationSource, migrate, type PgPoolLike, type PgQueryable, type PgQueryConfig, type PgResult, type PgTransactionClient, } from "./client.js";
5
5
  export type { PgInterval, PgParamTypeMap, PgTypeMap } from "./type-map.js";
6
6
  /** What `createSql<DB>(client)` returns: core's `Sql` under `PgTypeMap`, with `transaction(fn)`. */
7
7
  export type PgSql<DB, Keys extends RowKeys = "preserve"> = TransactionalSql<DB, PgTypeMap, Keys>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAc,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAE3E,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C,OAAO,EACN,QAAQ,EACR,KAAK,eAAe,EACpB,OAAO,EACP,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,mBAAmB,GACxB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE3E,oGAAoG;AACpG,MAAM,MAAM,KAAK,CAAC,EAAE,EAAE,IAAI,SAAS,OAAO,GAAG,UAAU,IAAI,gBAAgB,CAC1E,EAAE,EACF,SAAS,EACT,IAAI,CACJ,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAC3B,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,OAAO,EAAE;IAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;CAAE,GACxC,KAAK,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;AAC1B,wBAAgB,SAAS,CAAC,EAAE,EAC3B,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,UAAU,CAAA;CAAE,GACzC,KAAK,CAAC,EAAE,CAAC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAc,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAE3E,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C,OAAO,EACN,QAAQ,EACR,KAAK,eAAe,EACpB,OAAO,EACP,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,QAAQ,EACb,KAAK,mBAAmB,GACxB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE3E,oGAAoG;AACpG,MAAM,MAAM,KAAK,CAAC,EAAE,EAAE,IAAI,SAAS,OAAO,GAAG,UAAU,IAAI,gBAAgB,CAC1E,EAAE,EACF,SAAS,EACT,IAAI,CACJ,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAC3B,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,OAAO,EAAE;IAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;CAAE,GACxC,KAAK,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;AAC1B,wBAAgB,SAAS,CAAC,EAAE,EAC3B,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,UAAU,CAAA;CAAE,GACzC,KAAK,CAAC,EAAE,CAAC,CAAC"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAoB,MAAM,aAAa,CAAC;AAGvD,OAAO,EACN,QAAQ,EAER,OAAO,GAKP,MAAM,aAAa,CAAC;AAwBrB,MAAM,UAAU,SAAS,CACxB,MAAoB,EACpB,OAAoB;IAEpB,OAAO,sBAAsB,CAC5B,MAAM,EACN,MAAM,EACN,OAAO,CACP,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAoB,MAAM,aAAa,CAAC;AAGvD,OAAO,EACN,QAAQ,EAER,OAAO,GAMP,MAAM,aAAa,CAAC;AAwBrB,MAAM,UAAU,SAAS,CACxB,MAAoB,EACpB,OAAoB;IAEpB,OAAO,sBAAsB,CAC5B,MAAM,EACN,MAAM,EACN,OAAO,CACP,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typesql/pg",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
4
4
  "description": "node-postgres (pg) adapter for TypeSQL, with `typesql introspect` to generate a schema from a live database.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -35,7 +35,7 @@
35
35
  "access": "public"
36
36
  },
37
37
  "dependencies": {
38
- "@typesql/core": "0.7.2"
38
+ "@typesql/core": "0.7.3"
39
39
  },
40
40
  "peerDependencies": {
41
41
  "pg": ">=8"
package/src/client.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { createHash } from "node:crypto";
1
2
  import type { Executor } from "@typesql/core";
2
3
  import { runTransaction, type SqlDriver } from "@typesql/core/adapter";
3
4
 
@@ -9,10 +10,17 @@ export interface PgResult {
9
10
 
10
11
  /**
11
12
  * Anything with node-postgres' `query(text, values)` method: `Pool`, `Client`, `PoolClient`,
12
- * or a fake in tests. Only the `(text, values?) → Promise<{ rows, rowCount }>` form is used.
13
+ * or a fake in tests. Prepared queries use the named query config form.
13
14
  */
14
15
  export interface PgQueryable {
15
- query(text: string, values?: unknown[]): Promise<PgResult>;
16
+ query(text: string | PgQueryConfig, values?: unknown[]): Promise<PgResult>;
17
+ }
18
+
19
+ /** A named node-postgres statement. Names are derived from the final SQL text. */
20
+ export interface PgQueryConfig {
21
+ readonly name: string;
22
+ readonly text: string;
23
+ readonly values: unknown[];
16
24
  }
17
25
 
18
26
  /** A client checked out of a pool (`pg.PoolClient`): queryable and releasable. */
@@ -32,11 +40,27 @@ export interface PgPoolLike<
32
40
  * `{ rows, rowCount }` (pg's `rowCount`, so `q.executeCount()` works).
33
41
  */
34
42
  export function executor(client: PgQueryable): Executor {
35
- return async (text, values) => {
36
- // `pg` requires a mutable array (`QueryConfigValues<I>` matches `Array<U>` only).
37
- const { rows, rowCount } = await client.query(text, Array.from(values));
38
- return { rows, rowCount };
39
- };
43
+ return Object.assign(
44
+ async (text: string, values: readonly unknown[]) => {
45
+ // `pg` requires a mutable array (`QueryConfigValues<I>` matches `Array<U>` only).
46
+ const { rows, rowCount } = await client.query(text, Array.from(values));
47
+ return { rows, rowCount };
48
+ },
49
+ {
50
+ prepare: (text: string): Executor => {
51
+ // Keep names stable across factories and connections, within PostgreSQL's 63-byte limit.
52
+ const name = `typesql_${createHash("sha256").update(text).digest("hex").slice(0, 48)}`;
53
+ return async (text, values) => {
54
+ const { rows, rowCount } = await client.query({
55
+ name,
56
+ text,
57
+ values: Array.from(values),
58
+ });
59
+ return { rows, rowCount };
60
+ };
61
+ },
62
+ },
63
+ );
40
64
  }
41
65
 
42
66
  function isPool(client: PgQueryable): client is PgQueryable & PgPoolLike {
package/src/index.ts CHANGED
@@ -9,6 +9,7 @@ export {
9
9
  migrate,
10
10
  type PgPoolLike,
11
11
  type PgQueryable,
12
+ type PgQueryConfig,
12
13
  type PgResult,
13
14
  type PgTransactionClient,
14
15
  } from "./client.js";