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 +5 -1
- package/esm/connect.js +5 -1
- package/esm/manager.js +5 -2
- package/esm/test-client.js +46 -1
- package/manager.d.ts +2 -2
- package/manager.js +5 -2
- package/package.json +7 -7
- package/test-client.d.ts +19 -3
- package/test-client.js +46 -1
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
|
|
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
|
|
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, {
|
|
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);
|
package/esm/test-client.js
CHANGED
|
@@ -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.
|
|
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, {
|
|
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.
|
|
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.
|
|
64
|
-
"@launchql/env": "^2.4.
|
|
65
|
-
"@launchql/server-utils": "^2.4.
|
|
66
|
-
"@launchql/types": "^2.
|
|
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.
|
|
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": "
|
|
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
|
-
|
|
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.
|
|
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;
|