pgsql-test 2.10.0 → 2.11.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.
package/connect.js CHANGED
@@ -68,10 +68,14 @@ const getConnections = async (cn = {}, seedAdapters = [seed_1.seed.launchql()])
68
68
  throw error;
69
69
  }
70
70
  }
71
- const db = manager.getClient({
71
+ const dbConfig = {
72
72
  ...config,
73
73
  user: connOpts.connection.user,
74
74
  password: connOpts.connection.password
75
+ };
76
+ const db = manager.getClient(dbConfig, {
77
+ auth: connOpts.auth,
78
+ roles: connOpts.roles
75
79
  });
76
80
  db.setContext({ role: (0, roles_1.getDefaultRole)(connOpts) });
77
81
  return { pg, db, teardown, manager, admin };
package/esm/connect.js CHANGED
@@ -64,10 +64,14 @@ export const getConnections = async (cn = {}, seedAdapters = [seed.launchql()])
64
64
  throw error;
65
65
  }
66
66
  }
67
- const db = manager.getClient({
67
+ const dbConfig = {
68
68
  ...config,
69
69
  user: connOpts.connection.user,
70
70
  password: connOpts.connection.password
71
+ };
72
+ const db = manager.getClient(dbConfig, {
73
+ auth: connOpts.auth,
74
+ roles: connOpts.roles
71
75
  });
72
76
  db.setContext({ role: getDefaultRole(connOpts) });
73
77
  return { pg, db, teardown, manager, admin };
package/esm/manager.js CHANGED
@@ -68,11 +68,14 @@ export class PgTestConnector {
68
68
  }
69
69
  return this.pgPools.get(key);
70
70
  }
71
- getClient(config) {
71
+ getClient(config, opts = {}) {
72
72
  if (this.shuttingDown) {
73
73
  throw new Error('PgTestConnector is shutting down; no new clients allowed');
74
74
  }
75
- const client = new PgTestClient(config, { trackConnect: (p) => this.registerConnect(p) });
75
+ const client = new PgTestClient(config, {
76
+ trackConnect: (p) => this.registerConnect(p),
77
+ ...opts
78
+ });
76
79
  this.clients.add(client);
77
80
  const key = this.dbKey(config);
78
81
  this.seenDbConfigs.set(key, config);
@@ -1,11 +1,15 @@
1
1
  import { Client } from 'pg';
2
+ import { getRoleName } from './roles';
2
3
  export class PgTestClient {
3
4
  config;
4
5
  client;
6
+ opts;
5
7
  ctxStmts = '';
8
+ contextSettings = {};
6
9
  _ended = false;
7
10
  connectPromise = null;
8
11
  constructor(config, opts = {}) {
12
+ this.opts = opts;
9
13
  this.config = config;
10
14
  this.client = new Client({
11
15
  host: this.config.host,
@@ -56,12 +60,53 @@ export class PgTestClient {
56
60
  await this.commit();
57
61
  }
58
62
  setContext(ctx) {
59
- this.ctxStmts = Object.entries(ctx)
63
+ Object.assign(this.contextSettings, ctx);
64
+ this.ctxStmts = Object.entries(this.contextSettings)
60
65
  .map(([key, val]) => val === null
61
66
  ? `SELECT set_config('${key}', NULL, true);`
62
67
  : `SELECT set_config('${key}', '${val}', true);`)
63
68
  .join('\n');
64
69
  }
70
+ /**
71
+ * Set authentication context for the current session.
72
+ * Configures role and user ID using cascading defaults from options → opts.auth → RoleMapping.
73
+ */
74
+ auth(options = {}) {
75
+ const role = options.role ?? this.opts.auth?.role ?? getRoleName('authenticated', this.opts);
76
+ const userIdKey = options.userIdKey ?? this.opts.auth?.userIdKey ?? 'jwt.claims.user_id';
77
+ const userId = options.userId ?? this.opts.auth?.userId ?? null;
78
+ this.setContext({
79
+ role,
80
+ [userIdKey]: userId !== null ? String(userId) : null
81
+ });
82
+ }
83
+ /**
84
+ * Commit current transaction to make data visible to other connections, then start fresh transaction.
85
+ * Maintains test isolation by creating a savepoint and reapplying session context.
86
+ */
87
+ async publish() {
88
+ await this.commit(); // make data visible to other sessions
89
+ await this.begin(); // fresh tx
90
+ await this.savepoint(); // keep rollback harness
91
+ await this.ctxQuery(); // reapply all setContext()
92
+ }
93
+ /**
94
+ * Clear all session context variables and reset to default anonymous role.
95
+ */
96
+ clearContext() {
97
+ const defaultRole = getRoleName('anonymous', this.opts);
98
+ const nulledSettings = {};
99
+ Object.keys(this.contextSettings).forEach(key => {
100
+ nulledSettings[key] = null;
101
+ });
102
+ nulledSettings.role = defaultRole;
103
+ this.ctxStmts = Object.entries(nulledSettings)
104
+ .map(([key, val]) => val === null
105
+ ? `SELECT set_config('${key}', NULL, true);`
106
+ : `SELECT set_config('${key}', '${val}', true);`)
107
+ .join('\n');
108
+ this.contextSettings = { role: defaultRole };
109
+ }
65
110
  async any(query, values) {
66
111
  const result = await this.query(query, values);
67
112
  return result.rows;
package/manager.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Pool } from 'pg';
2
2
  import { PgConfig } from 'pg-env';
3
- import { PgTestClient } from './test-client';
3
+ import { PgTestClient, PgTestClientOpts } from './test-client';
4
4
  export declare class PgTestConnector {
5
5
  private static instance;
6
6
  private readonly clients;
@@ -17,7 +17,7 @@ export declare class PgTestConnector {
17
17
  private registerConnect;
18
18
  private awaitPendingConnects;
19
19
  getPool(config: PgConfig): Pool;
20
- getClient(config: PgConfig): PgTestClient;
20
+ getClient(config: PgConfig, opts?: Partial<PgTestClientOpts>): PgTestClient;
21
21
  closeAll(): Promise<void>;
22
22
  close(): void;
23
23
  drop(config: PgConfig): void;
package/manager.js CHANGED
@@ -71,11 +71,14 @@ class PgTestConnector {
71
71
  }
72
72
  return this.pgPools.get(key);
73
73
  }
74
- getClient(config) {
74
+ getClient(config, opts = {}) {
75
75
  if (this.shuttingDown) {
76
76
  throw new Error('PgTestConnector is shutting down; no new clients allowed');
77
77
  }
78
- const client = new test_client_1.PgTestClient(config, { trackConnect: (p) => this.registerConnect(p) });
78
+ const client = new test_client_1.PgTestClient(config, {
79
+ trackConnect: (p) => this.registerConnect(p),
80
+ ...opts
81
+ });
79
82
  this.clients.add(client);
80
83
  const key = this.dbKey(config);
81
84
  this.seenDbConfigs.set(key, config);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pgsql-test",
3
- "version": "2.10.0",
3
+ "version": "2.11.0",
4
4
  "author": "Dan Lynch <pyramation@gmail.com>",
5
5
  "description": "pgsql-test offers isolated, role-aware, and rollback-friendly PostgreSQL environments for integration tests — giving developers realistic test coverage without external state pollution",
6
6
  "main": "index.js",
@@ -60,14 +60,14 @@
60
60
  "@types/pg-copy-streams": "^1.2.5"
61
61
  },
62
62
  "dependencies": {
63
- "@launchql/core": "^2.11.0",
64
- "@launchql/env": "^2.4.0",
65
- "@launchql/server-utils": "^2.4.0",
66
- "@launchql/types": "^2.5.0",
63
+ "@launchql/core": "^2.11.1",
64
+ "@launchql/env": "^2.4.1",
65
+ "@launchql/server-utils": "^2.4.1",
66
+ "@launchql/types": "^2.6.0",
67
67
  "pg": "^8.16.0",
68
- "pg-cache": "^1.3.0",
68
+ "pg-cache": "^1.3.1",
69
69
  "pg-copy-streams": "^6.0.6",
70
70
  "pg-env": "^1.1.0"
71
71
  },
72
- "gitHead": "f7d2375e14a9f45ebb00d58ab87c0efd6bd50618"
72
+ "gitHead": "6b7bfcdaef0133012fd4b0cbe2aea185d77de3ed"
73
73
  }
package/test-client.d.ts CHANGED
@@ -1,13 +1,16 @@
1
1
  import { Client, QueryResult } from 'pg';
2
2
  import { PgConfig } from 'pg-env';
3
- type PgTestClientOpts = {
3
+ import { AuthOptions, PgTestConnectionOptions } from '@launchql/types';
4
+ export type PgTestClientOpts = {
4
5
  deferConnect?: boolean;
5
6
  trackConnect?: (p: Promise<any>) => void;
6
- };
7
+ } & Partial<PgTestConnectionOptions>;
7
8
  export declare class PgTestClient {
8
9
  config: PgConfig;
9
10
  client: Client;
11
+ private opts;
10
12
  private ctxStmts;
13
+ private contextSettings;
11
14
  private _ended;
12
15
  private connectPromise;
13
16
  constructor(config: PgConfig, opts?: PgTestClientOpts);
@@ -20,6 +23,20 @@ export declare class PgTestClient {
20
23
  beforeEach(): Promise<void>;
21
24
  afterEach(): Promise<void>;
22
25
  setContext(ctx: Record<string, string | null>): void;
26
+ /**
27
+ * Set authentication context for the current session.
28
+ * Configures role and user ID using cascading defaults from options → opts.auth → RoleMapping.
29
+ */
30
+ auth(options?: AuthOptions): void;
31
+ /**
32
+ * Commit current transaction to make data visible to other connections, then start fresh transaction.
33
+ * Maintains test isolation by creating a savepoint and reapplying session context.
34
+ */
35
+ publish(): Promise<void>;
36
+ /**
37
+ * Clear all session context variables and reset to default anonymous role.
38
+ */
39
+ clearContext(): void;
23
40
  any<T = any>(query: string, values?: any[]): Promise<T[]>;
24
41
  one<T = any>(query: string, values?: any[]): Promise<T>;
25
42
  oneOrNone<T = any>(query: string, values?: any[]): Promise<T | null>;
@@ -30,4 +47,3 @@ export declare class PgTestClient {
30
47
  query<T = any>(query: string, values?: any[]): Promise<QueryResult<T>>;
31
48
  ctxQuery(): Promise<void>;
32
49
  }
33
- export {};
package/test-client.js CHANGED
@@ -2,13 +2,17 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PgTestClient = void 0;
4
4
  const pg_1 = require("pg");
5
+ const roles_1 = require("./roles");
5
6
  class PgTestClient {
6
7
  config;
7
8
  client;
9
+ opts;
8
10
  ctxStmts = '';
11
+ contextSettings = {};
9
12
  _ended = false;
10
13
  connectPromise = null;
11
14
  constructor(config, opts = {}) {
15
+ this.opts = opts;
12
16
  this.config = config;
13
17
  this.client = new pg_1.Client({
14
18
  host: this.config.host,
@@ -59,12 +63,53 @@ class PgTestClient {
59
63
  await this.commit();
60
64
  }
61
65
  setContext(ctx) {
62
- this.ctxStmts = Object.entries(ctx)
66
+ Object.assign(this.contextSettings, ctx);
67
+ this.ctxStmts = Object.entries(this.contextSettings)
63
68
  .map(([key, val]) => val === null
64
69
  ? `SELECT set_config('${key}', NULL, true);`
65
70
  : `SELECT set_config('${key}', '${val}', true);`)
66
71
  .join('\n');
67
72
  }
73
+ /**
74
+ * Set authentication context for the current session.
75
+ * Configures role and user ID using cascading defaults from options → opts.auth → RoleMapping.
76
+ */
77
+ auth(options = {}) {
78
+ const role = options.role ?? this.opts.auth?.role ?? (0, roles_1.getRoleName)('authenticated', this.opts);
79
+ const userIdKey = options.userIdKey ?? this.opts.auth?.userIdKey ?? 'jwt.claims.user_id';
80
+ const userId = options.userId ?? this.opts.auth?.userId ?? null;
81
+ this.setContext({
82
+ role,
83
+ [userIdKey]: userId !== null ? String(userId) : null
84
+ });
85
+ }
86
+ /**
87
+ * Commit current transaction to make data visible to other connections, then start fresh transaction.
88
+ * Maintains test isolation by creating a savepoint and reapplying session context.
89
+ */
90
+ async publish() {
91
+ await this.commit(); // make data visible to other sessions
92
+ await this.begin(); // fresh tx
93
+ await this.savepoint(); // keep rollback harness
94
+ await this.ctxQuery(); // reapply all setContext()
95
+ }
96
+ /**
97
+ * Clear all session context variables and reset to default anonymous role.
98
+ */
99
+ clearContext() {
100
+ const defaultRole = (0, roles_1.getRoleName)('anonymous', this.opts);
101
+ const nulledSettings = {};
102
+ Object.keys(this.contextSettings).forEach(key => {
103
+ nulledSettings[key] = null;
104
+ });
105
+ nulledSettings.role = defaultRole;
106
+ this.ctxStmts = Object.entries(nulledSettings)
107
+ .map(([key, val]) => val === null
108
+ ? `SELECT set_config('${key}', NULL, true);`
109
+ : `SELECT set_config('${key}', '${val}', true);`)
110
+ .join('\n');
111
+ this.contextSettings = { role: defaultRole };
112
+ }
68
113
  async any(query, values) {
69
114
  const result = await this.query(query, values);
70
115
  return result.rows;