callman-core 1.19.0 → 1.20.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/dist/host/db/connectionMapping.d.ts +4 -0
- package/dist/host/db/connectionMapping.d.ts.map +1 -1
- package/dist/host/db/connectionMapping.js +4 -0
- package/dist/host/db/connectionMapping.js.map +1 -1
- package/dist/host/db/pgClientConfig.d.ts +11 -0
- package/dist/host/db/pgClientConfig.d.ts.map +1 -0
- package/dist/host/db/pgClientConfig.js +83 -0
- package/dist/host/db/pgClientConfig.js.map +1 -0
- package/dist/host/db/pgSessionManager.d.ts +18 -0
- package/dist/host/db/pgSessionManager.d.ts.map +1 -0
- package/dist/host/db/pgSessionManager.js +162 -0
- package/dist/host/db/pgSessionManager.js.map +1 -0
- package/dist/host/db/postgresAdapter.d.ts.map +1 -1
- package/dist/host/db/postgresAdapter.js +7 -36
- package/dist/host/db/postgresAdapter.js.map +1 -1
- package/dist/host/db/queryExecutor.d.ts +4 -0
- package/dist/host/db/queryExecutor.d.ts.map +1 -1
- package/dist/host/db/queryExecutor.js +40 -2
- package/dist/host/db/queryExecutor.js.map +1 -1
- package/dist/host/db/sqlState.d.ts +2 -0
- package/dist/host/db/sqlState.d.ts.map +1 -0
- package/dist/host/db/sqlState.js +14 -0
- package/dist/host/db/sqlState.js.map +1 -0
- package/dist/host/db/types.d.ts +13 -0
- package/dist/host/db/types.d.ts.map +1 -1
- package/dist/host/index.d.ts +3 -0
- package/dist/host/index.d.ts.map +1 -1
- package/dist/host/index.js +7 -0
- package/dist/host/index.js.map +1 -1
- package/dist/scenario-runner/adapters/connection-config.d.ts +4 -0
- package/dist/scenario-runner/adapters/connection-config.d.ts.map +1 -1
- package/dist/scenario-runner/adapters/db-executor.d.ts +7 -1
- package/dist/scenario-runner/adapters/db-executor.d.ts.map +1 -1
- package/dist/scenario-runner/adapters/db-executor.js +106 -1
- package/dist/scenario-runner/adapters/db-executor.js.map +1 -1
- package/dist/scenario-runner/adapters/index.d.ts +1 -1
- package/dist/scenario-runner/adapters/index.d.ts.map +1 -1
- package/dist/scenario-runner/adapters/index.js +8 -1
- package/dist/scenario-runner/adapters/index.js.map +1 -1
- package/dist/scenario-runner/adapters/types.d.ts +8 -0
- package/dist/scenario-runner/adapters/types.d.ts.map +1 -1
- package/dist/scenario-runner/condition.d.ts +1 -0
- package/dist/scenario-runner/condition.d.ts.map +1 -1
- package/dist/scenario-runner/condition.js +127 -2
- package/dist/scenario-runner/condition.js.map +1 -1
- package/dist/scenario-runner/conditionTypes.d.ts +1 -1
- package/dist/scenario-runner/conditionTypes.d.ts.map +1 -1
- package/dist/scenario-runner/runScenario.d.ts.map +1 -1
- package/dist/scenario-runner/runScenario.js +42 -1
- package/dist/scenario-runner/runScenario.js.map +1 -1
- package/dist/scenario-runner/types.d.ts +27 -0
- package/dist/scenario-runner/types.d.ts.map +1 -1
- package/dist-cjs/host/db/connectionMapping.js +4 -0
- package/dist-cjs/host/db/connectionMapping.js.map +1 -1
- package/dist-cjs/host/db/pgClientConfig.js +90 -0
- package/dist-cjs/host/db/pgClientConfig.js.map +1 -0
- package/dist-cjs/host/db/pgSessionManager.js +170 -0
- package/dist-cjs/host/db/pgSessionManager.js.map +1 -0
- package/dist-cjs/host/db/postgresAdapter.js +7 -36
- package/dist-cjs/host/db/postgresAdapter.js.map +1 -1
- package/dist-cjs/host/db/queryExecutor.js +40 -2
- package/dist-cjs/host/db/queryExecutor.js.map +1 -1
- package/dist-cjs/host/db/sqlState.js +18 -0
- package/dist-cjs/host/db/sqlState.js.map +1 -0
- package/dist-cjs/host/index.js +16 -1
- package/dist-cjs/host/index.js.map +1 -1
- package/dist-cjs/scenario-runner/adapters/db-executor.js +108 -2
- package/dist-cjs/scenario-runner/adapters/db-executor.js.map +1 -1
- package/dist-cjs/scenario-runner/adapters/index.js +10 -1
- package/dist-cjs/scenario-runner/adapters/index.js.map +1 -1
- package/dist-cjs/scenario-runner/condition.js +129 -3
- package/dist-cjs/scenario-runner/condition.js.map +1 -1
- package/dist-cjs/scenario-runner/runScenario.js +42 -1
- package/dist-cjs/scenario-runner/runScenario.js.map +1 -1
- package/package.json +1 -1
|
@@ -12,6 +12,10 @@ export interface DatabaseConnectionConfigLike {
|
|
|
12
12
|
ssl?: boolean;
|
|
13
13
|
instanceName?: string;
|
|
14
14
|
trustServerCertificate?: boolean;
|
|
15
|
+
sslMode?: "disable" | "require" | "verify-ca" | "verify-full";
|
|
16
|
+
caCert?: string;
|
|
17
|
+
clientCert?: string;
|
|
18
|
+
clientKey?: string;
|
|
15
19
|
}
|
|
16
20
|
export declare const databaseConfigToDbConnection: (input: {
|
|
17
21
|
id?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connectionMapping.d.ts","sourceRoot":"","sources":["../../../src/host/db/connectionMapping.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,YAAY,CAAC;AAEjE,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,YAAY,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAUrF,MAAM,WAAW,4BAA4B;IAC3C,cAAc,EAAE,UAAU,GAAG,kBAAkB,CAAC;IAChD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sBAAsB,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"connectionMapping.d.ts","sourceRoot":"","sources":["../../../src/host/db/connectionMapping.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,YAAY,CAAC;AAEjE,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,YAAY,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAUrF,MAAM,WAAW,4BAA4B;IAC3C,cAAc,EAAE,UAAU,GAAG,kBAAkB,CAAC;IAChD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAIjC,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,aAAa,CAAC;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,4BAA4B,GAAI,OAAO;IAClD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,cAAc,CAAC;IACzB,MAAM,EAAE,4BAA4B,CAAC;CACtC,KAAG,YAmBF,CAAC"}
|
|
@@ -26,5 +26,9 @@ export const databaseConfigToDbConnection = (input) => ({
|
|
|
26
26
|
password: input.config.password ?? "",
|
|
27
27
|
ssl: input.config.ssl,
|
|
28
28
|
trustServerCertificate: input.config.trustServerCertificate,
|
|
29
|
+
sslMode: input.config.sslMode,
|
|
30
|
+
caCert: input.config.caCert,
|
|
31
|
+
clientCert: input.config.clientCert,
|
|
32
|
+
clientKey: input.config.clientKey,
|
|
29
33
|
});
|
|
30
34
|
//# sourceMappingURL=connectionMapping.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connectionMapping.js","sourceRoot":"","sources":["../../../src/host/db/connectionMapping.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,wEAAwE;AACxE,yEAAyE;AACzE,8EAA8E;AAC9E,8EAA8E;AAC9E,oBAAoB;AAMpB,MAAM,gBAAgB,GAA6C;IACjE,OAAO,EAAE,OAAO;IAChB,UAAU,EAAE,UAAU;IACtB,KAAK,EAAE,OAAO;IACd,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,OAAO;CACf,CAAC;
|
|
1
|
+
{"version":3,"file":"connectionMapping.js","sourceRoot":"","sources":["../../../src/host/db/connectionMapping.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,wEAAwE;AACxE,yEAAyE;AACzE,8EAA8E;AAC9E,8EAA8E;AAC9E,oBAAoB;AAMpB,MAAM,gBAAgB,GAA6C;IACjE,OAAO,EAAE,OAAO;IAChB,UAAU,EAAE,UAAU;IACtB,KAAK,EAAE,OAAO;IACd,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,OAAO;CACf,CAAC;AAuBF,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,KAK5C,EAAgB,EAAE,CAAC,CAAC;IACnB,EAAE,EAAE,KAAK,CAAC,EAAE,IAAI,qBAAqB;IACrC,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE;IACtB,IAAI,EAAE,gBAAgB,CAAC,KAAK,CAAC,QAAQ,CAAC;IACtC,cAAc,EAAE,KAAK,CAAC,MAAM,CAAC,cAAc;IAC3C,gBAAgB,EAAE,KAAK,CAAC,MAAM,CAAC,gBAAgB;IAC/C,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE;IAC7B,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC;IAC5B,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,QAAQ;IAC/B,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,WAAW;IACrC,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,YAAY;IACvC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE;IACrC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE;IACrC,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG;IACrB,sBAAsB,EAAE,KAAK,CAAC,MAAM,CAAC,sBAAsB;IAC3D,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO;IAC7B,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM;IAC3B,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,UAAU;IACnC,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,SAAS;CAClC,CAAC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { DbConnection } from "./types.js";
|
|
2
|
+
export declare const buildPgSslConfig: (connection: DbConnection) => Record<string, unknown> | undefined;
|
|
3
|
+
export declare const buildPgClientConfig: (connection: DbConnection) => Record<string, unknown>;
|
|
4
|
+
export declare const normalizePgValue: (value: unknown) => unknown;
|
|
5
|
+
export declare const runPgQuery: (client: {
|
|
6
|
+
query: (text: string, params?: unknown[]) => Promise<unknown>;
|
|
7
|
+
}, query: string, params?: unknown[]) => Promise<{
|
|
8
|
+
rows: unknown[];
|
|
9
|
+
rowCount: number;
|
|
10
|
+
}>;
|
|
11
|
+
//# sourceMappingURL=pgClientConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pgClientConfig.d.ts","sourceRoot":"","sources":["../../../src/host/db/pgClientConfig.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAQ/C,eAAO,MAAM,gBAAgB,GAC3B,YAAY,YAAY,KACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAyB5B,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,YAAY,YAAY,KACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAcxB,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,OAAO,OAAO,KAAG,OAU/C,CAAC;AAOJ,eAAO,MAAM,UAAU,GACrB,QAAQ;IAAE,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CAAE,EACzE,OAAO,MAAM,EACb,SAAQ,OAAO,EAAO,KACrB,OAAO,CAAC;IAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAc/C,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// Shared pg client construction + query execution for the one-shot adapter
|
|
2
|
+
// (postgresAdapter) and the run-scoped session manager (pgSessionManager),
|
|
3
|
+
// so TLS handling and result normalization can never drift between them.
|
|
4
|
+
import { stripTrailingSqlTerminator } from "./sqlNormalize.js";
|
|
5
|
+
// TLS material for a Postgres connection. `sslMode` semantics follow
|
|
6
|
+
// libpq: "require" encrypts without verification, "verify-ca" verifies the
|
|
7
|
+
// chain against `caCert` but not the hostname, "verify-full" verifies both.
|
|
8
|
+
// When `sslMode` is absent the legacy boolean `ssl` keeps its historical
|
|
9
|
+
// behavior (encrypt, no verification) so existing connections don't break.
|
|
10
|
+
export const buildPgSslConfig = (connection) => {
|
|
11
|
+
const mode = connection.sslMode;
|
|
12
|
+
if (!mode) {
|
|
13
|
+
return connection.ssl ? { rejectUnauthorized: false } : undefined;
|
|
14
|
+
}
|
|
15
|
+
if (mode === "disable") {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
const material = {};
|
|
19
|
+
if (connection.caCert?.trim())
|
|
20
|
+
material.ca = connection.caCert;
|
|
21
|
+
if (connection.clientCert?.trim())
|
|
22
|
+
material.cert = connection.clientCert;
|
|
23
|
+
if (connection.clientKey?.trim())
|
|
24
|
+
material.key = connection.clientKey;
|
|
25
|
+
if (mode === "require") {
|
|
26
|
+
return { ...material, rejectUnauthorized: false };
|
|
27
|
+
}
|
|
28
|
+
if (mode === "verify-ca") {
|
|
29
|
+
// Verify the chain but skip hostname verification (libpq verify-ca).
|
|
30
|
+
return {
|
|
31
|
+
...material,
|
|
32
|
+
rejectUnauthorized: true,
|
|
33
|
+
checkServerIdentity: () => undefined,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
// verify-full: chain + hostname.
|
|
37
|
+
return { ...material, rejectUnauthorized: true };
|
|
38
|
+
};
|
|
39
|
+
export const buildPgClientConfig = (connection) => {
|
|
40
|
+
const ssl = buildPgSslConfig(connection);
|
|
41
|
+
if (connection.connectionString?.trim()) {
|
|
42
|
+
return { connectionString: connection.connectionString.trim(), ssl, connectionTimeoutMillis: 8000 };
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
host: connection.host,
|
|
46
|
+
port: connection.port,
|
|
47
|
+
database: connection.database,
|
|
48
|
+
user: connection.username,
|
|
49
|
+
password: connection.password,
|
|
50
|
+
ssl,
|
|
51
|
+
connectionTimeoutMillis: 8000,
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
export const normalizePgValue = (value) => JSON.parse(JSON.stringify(value, (_key, entry) => {
|
|
55
|
+
if (typeof entry === "bigint")
|
|
56
|
+
return entry.toString();
|
|
57
|
+
if (entry instanceof Date)
|
|
58
|
+
return entry.toISOString();
|
|
59
|
+
if (Buffer.isBuffer(entry) || entry instanceof Uint8Array) {
|
|
60
|
+
return Buffer.from(entry).toString("hex");
|
|
61
|
+
}
|
|
62
|
+
return entry;
|
|
63
|
+
}));
|
|
64
|
+
// Run one query on an already-connected client. Params are OMITTED when
|
|
65
|
+
// empty so node-pg keeps the simple protocol — that is what allows
|
|
66
|
+
// multi-statement setup/teardown scripts (`INSERT …; INSERT …;`) and
|
|
67
|
+
// `DO $$ … $$` blocks in a db node with no bind params. A multi-statement
|
|
68
|
+
// script returns the LAST statement's rows (matches psql's display).
|
|
69
|
+
export const runPgQuery = async (client, query, params = []) => {
|
|
70
|
+
const finalQuery = stripTrailingSqlTerminator(query, "postgres");
|
|
71
|
+
const result = params.length > 0
|
|
72
|
+
? await client.query(finalQuery, params)
|
|
73
|
+
: await client.query(finalQuery);
|
|
74
|
+
const last = Array.isArray(result) ? result[result.length - 1] : result;
|
|
75
|
+
const rawRows = last?.rows;
|
|
76
|
+
const rows = Array.isArray(rawRows) ? rawRows.map(normalizePgValue) : [];
|
|
77
|
+
const rowCount = last?.rowCount;
|
|
78
|
+
return {
|
|
79
|
+
rows,
|
|
80
|
+
rowCount: typeof rowCount === "number" ? rowCount : rows.length,
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
//# sourceMappingURL=pgClientConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pgClientConfig.js","sourceRoot":"","sources":["../../../src/host/db/pgClientConfig.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { DbConnection } from "./types.js";
|
|
2
|
+
export type PgSessionTransactionMode = "none" | "rollback" | "commit";
|
|
3
|
+
export declare const __setPgSessionDriverForTests: (driver: any | null) => void;
|
|
4
|
+
export interface PgSessionExecuteInput {
|
|
5
|
+
connection: DbConnection;
|
|
6
|
+
runId: string;
|
|
7
|
+
transactionMode: PgSessionTransactionMode;
|
|
8
|
+
query: string;
|
|
9
|
+
params?: unknown[];
|
|
10
|
+
}
|
|
11
|
+
export declare const executePostgresQueryInSession: (input: PgSessionExecuteInput) => Promise<{
|
|
12
|
+
rows: unknown[];
|
|
13
|
+
rowCount: number;
|
|
14
|
+
}>;
|
|
15
|
+
export declare const releasePostgresSessionsForRun: (runId: string, outcome: "commit" | "rollback") => Promise<void>;
|
|
16
|
+
export declare const closeAllPostgresSessions: () => Promise<void>;
|
|
17
|
+
export declare const __getPgSessionCountForTests: () => number;
|
|
18
|
+
//# sourceMappingURL=pgSessionManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pgSessionManager.d.ts","sourceRoot":"","sources":["../../../src/host/db/pgSessionManager.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C,MAAM,MAAM,wBAAwB,GAAG,MAAM,GAAG,UAAU,GAAG,QAAQ,CAAC;AA0BtE,eAAO,MAAM,4BAA4B,GAAI,QAAQ,GAAG,GAAG,IAAI,KAAG,IAEjE,CAAC;AA4FF,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,YAAY,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,wBAAwB,CAAC;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;CACpB;AAED,eAAO,MAAM,6BAA6B,GACxC,OAAO,qBAAqB,KAC3B,OAAO,CAAC;IAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CA+B/C,CAAC;AAKF,eAAO,MAAM,6BAA6B,GACxC,OAAO,MAAM,EACb,SAAS,QAAQ,GAAG,UAAU,KAC7B,OAAO,CAAC,IAAI,CAYd,CAAC;AAGF,eAAO,MAAM,wBAAwB,QAAa,OAAO,CAAC,IAAI,CAQ7D,CAAC;AAGF,eAAO,MAAM,2BAA2B,QAAO,MAAuB,CAAC"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
// Run-scoped PostgreSQL sessions for scenario db nodes (`useSession`).
|
|
2
|
+
//
|
|
3
|
+
// One live `pg` Client per (runId, connection identity). All session-joined
|
|
4
|
+
// nodes of a run share that client, so `BEGIN`, temp tables, GUCs and
|
|
5
|
+
// advisory locks survive between nodes — the foundation of the
|
|
6
|
+
// seed → call function → assert → ROLLBACK stored-function testing pattern.
|
|
7
|
+
//
|
|
8
|
+
// Modeled on callman-backend's kafka-client-pool: lazy open, per-session
|
|
9
|
+
// serialization, idle sweeper, explicit shutdown hook. Postgres-only by
|
|
10
|
+
// design — other providers reject `useSession` at the host driver.
|
|
11
|
+
import { loadOptionalModule } from "../lazy.js";
|
|
12
|
+
import { buildPgClientConfig, runPgQuery } from "./pgClientConfig.js";
|
|
13
|
+
const IDLE_SWEEP_INTERVAL_MS = 60_000;
|
|
14
|
+
const IDLE_SESSION_TTL_MS = 5 * 60_000;
|
|
15
|
+
const sessions = new Map();
|
|
16
|
+
let sweeper = null;
|
|
17
|
+
const unwrap = (mod) => (mod && mod.default && !mod.Client ? mod.default : mod);
|
|
18
|
+
// Test seam mirroring postgresAdapter's — lets unit tests inject a fake
|
|
19
|
+
// driver without a live server.
|
|
20
|
+
let pgDriverOverride = null;
|
|
21
|
+
export const __setPgSessionDriverForTests = (driver) => {
|
|
22
|
+
pgDriverOverride = driver;
|
|
23
|
+
};
|
|
24
|
+
const loadPgDriver = async () => {
|
|
25
|
+
if (pgDriverOverride)
|
|
26
|
+
return pgDriverOverride;
|
|
27
|
+
try {
|
|
28
|
+
return unwrap(await loadOptionalModule("pg"));
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
throw new Error("PostgreSQL driver (`pg`) is not installed. Install `pg` to use PostgreSQL sessions.");
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
// Connection identity participates in the key so two different connections
|
|
35
|
+
// in one run never share a client, even if their `id`s degenerate to the
|
|
36
|
+
// same normalized placeholder.
|
|
37
|
+
const sessionKey = (runId, connection) => [
|
|
38
|
+
runId,
|
|
39
|
+
connection.id,
|
|
40
|
+
connection.connectionString ?? "",
|
|
41
|
+
connection.host,
|
|
42
|
+
String(connection.port),
|
|
43
|
+
connection.database ?? "",
|
|
44
|
+
connection.username,
|
|
45
|
+
].join("::");
|
|
46
|
+
const ensureSweeper = () => {
|
|
47
|
+
if (sweeper)
|
|
48
|
+
return;
|
|
49
|
+
sweeper = setInterval(() => {
|
|
50
|
+
const now = Date.now();
|
|
51
|
+
for (const [key, entry] of sessions) {
|
|
52
|
+
if (now - entry.lastUsedAtMs > IDLE_SESSION_TTL_MS) {
|
|
53
|
+
sessions.delete(key);
|
|
54
|
+
void destroyEntry(entry, "rollback");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (sessions.size === 0 && sweeper) {
|
|
58
|
+
clearInterval(sweeper);
|
|
59
|
+
sweeper = null;
|
|
60
|
+
}
|
|
61
|
+
}, IDLE_SWEEP_INTERVAL_MS);
|
|
62
|
+
// Never keep the host process alive just for the sweeper.
|
|
63
|
+
sweeper.unref?.();
|
|
64
|
+
};
|
|
65
|
+
const destroyEntry = async (entry, outcome) => {
|
|
66
|
+
try {
|
|
67
|
+
const client = await entry.clientPromise;
|
|
68
|
+
if (entry.transactionOpen && !entry.poisoned) {
|
|
69
|
+
try {
|
|
70
|
+
await client.query(outcome === "commit" ? "COMMIT" : "ROLLBACK");
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// The transaction dies with the connection either way.
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
await client.end();
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// Best-effort teardown.
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
// Client never connected — nothing to tear down.
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
const openEntry = (runId, connection) => {
|
|
88
|
+
const entry = {
|
|
89
|
+
clientPromise: (async () => {
|
|
90
|
+
const { Client } = await loadPgDriver();
|
|
91
|
+
const client = new Client(buildPgClientConfig(connection));
|
|
92
|
+
await client.connect();
|
|
93
|
+
// Socket-level errors surface here (killed backend, network drop);
|
|
94
|
+
// mark the session so the next query fails fast with the cause.
|
|
95
|
+
client.on?.("error", (error) => {
|
|
96
|
+
entry.poisoned =
|
|
97
|
+
error instanceof Error ? error.message : "PostgreSQL session connection lost";
|
|
98
|
+
});
|
|
99
|
+
return client;
|
|
100
|
+
})(),
|
|
101
|
+
chain: Promise.resolve(),
|
|
102
|
+
transactionOpen: false,
|
|
103
|
+
poisoned: null,
|
|
104
|
+
lastUsedAtMs: Date.now(),
|
|
105
|
+
runId,
|
|
106
|
+
};
|
|
107
|
+
return entry;
|
|
108
|
+
};
|
|
109
|
+
export const executePostgresQueryInSession = async (input) => {
|
|
110
|
+
const key = sessionKey(input.runId, input.connection);
|
|
111
|
+
let entry = sessions.get(key);
|
|
112
|
+
if (!entry) {
|
|
113
|
+
entry = openEntry(input.runId, input.connection);
|
|
114
|
+
sessions.set(key, entry);
|
|
115
|
+
ensureSweeper();
|
|
116
|
+
}
|
|
117
|
+
const run = entry.chain.then(async () => {
|
|
118
|
+
if (entry.poisoned) {
|
|
119
|
+
throw new Error(`PostgreSQL session is unusable: ${entry.poisoned}`);
|
|
120
|
+
}
|
|
121
|
+
const client = await entry.clientPromise;
|
|
122
|
+
if (input.transactionMode !== "none" && !entry.transactionOpen) {
|
|
123
|
+
await client.query("BEGIN");
|
|
124
|
+
entry.transactionOpen = true;
|
|
125
|
+
}
|
|
126
|
+
return runPgQuery(client, input.query, input.params ?? []);
|
|
127
|
+
});
|
|
128
|
+
// The chain must survive a failed query (SQL errors are normal in
|
|
129
|
+
// expectError flows) — swallow for chaining purposes only.
|
|
130
|
+
entry.chain = run.then(() => undefined, () => undefined).then(() => {
|
|
131
|
+
entry.lastUsedAtMs = Date.now();
|
|
132
|
+
});
|
|
133
|
+
return run;
|
|
134
|
+
};
|
|
135
|
+
// Close every session belonging to `runId` — COMMIT/ROLLBACK per the run
|
|
136
|
+
// outcome, then end the client. Queued statements finish (or fail) first
|
|
137
|
+
// thanks to the serialization chain.
|
|
138
|
+
export const releasePostgresSessionsForRun = async (runId, outcome) => {
|
|
139
|
+
const owned = [];
|
|
140
|
+
for (const [key, entry] of sessions) {
|
|
141
|
+
if (entry.runId === runId)
|
|
142
|
+
owned.push([key, entry]);
|
|
143
|
+
}
|
|
144
|
+
await Promise.all(owned.map(async ([key, entry]) => {
|
|
145
|
+
sessions.delete(key);
|
|
146
|
+
await entry.chain;
|
|
147
|
+
await destroyEntry(entry, outcome);
|
|
148
|
+
}));
|
|
149
|
+
};
|
|
150
|
+
// Shutdown hook for hosts (backend process exit, CLI end, electron quit).
|
|
151
|
+
export const closeAllPostgresSessions = async () => {
|
|
152
|
+
const all = Array.from(sessions.values());
|
|
153
|
+
sessions.clear();
|
|
154
|
+
if (sweeper) {
|
|
155
|
+
clearInterval(sweeper);
|
|
156
|
+
sweeper = null;
|
|
157
|
+
}
|
|
158
|
+
await Promise.all(all.map((entry) => destroyEntry(entry, "rollback")));
|
|
159
|
+
};
|
|
160
|
+
// Introspection for tests.
|
|
161
|
+
export const __getPgSessionCountForTests = () => sessions.size;
|
|
162
|
+
//# sourceMappingURL=pgSessionManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pgSessionManager.js","sourceRoot":"","sources":["../../../src/host/db/pgSessionManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgresAdapter.d.ts","sourceRoot":"","sources":["../../../src/host/db/postgresAdapter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"postgresAdapter.d.ts","sourceRoot":"","sources":["../../../src/host/db/postgresAdapter.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAO/C,eAAO,MAAM,2BAA2B,GAAI,QAAQ,GAAG,GAAG,IAAI,KAAG,IAEhE,CAAC;AAeF,eAAO,MAAM,sBAAsB,GAAU,YAAY,YAAY,KAAG,OAAO,CAAC,IAAI,CASnF,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,YAAY,YAAY,EACxB,OAAO,MAAM,EACb,SAAQ,OAAO,EAAO,KACrB,OAAO,CAAC;IAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAS/C,CAAC"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// PostgreSQL adapter. Ported from `pmanfrontend/electron/db/postgresAdapter.ts`
|
|
2
|
-
// with lazy `pg` loading via `loadOptionalModule`.
|
|
2
|
+
// with lazy `pg` loading via `loadOptionalModule`. Client config (incl. TLS
|
|
3
|
+
// modes) and query execution are shared with the session manager through
|
|
4
|
+
// pgClientConfig.ts.
|
|
3
5
|
import { loadOptionalModule } from "../lazy.js";
|
|
4
|
-
import {
|
|
6
|
+
import { buildPgClientConfig, runPgQuery } from "./pgClientConfig.js";
|
|
5
7
|
const unwrap = (mod) => (mod && mod.default && !mod.Client ? mod.default : mod);
|
|
6
8
|
// Test-only seam (see mongoAdapter).
|
|
7
9
|
let pgDriverOverride = null;
|
|
@@ -19,34 +21,9 @@ const loadPgDriver = async () => {
|
|
|
19
21
|
throw new Error("PostgreSQL driver (`pg`) is not installed. Install `pg` to use PostgreSQL connections.");
|
|
20
22
|
}
|
|
21
23
|
};
|
|
22
|
-
const buildClientConfig = (connection) => {
|
|
23
|
-
const ssl = connection.ssl ? { rejectUnauthorized: false } : undefined;
|
|
24
|
-
if (connection.connectionString?.trim()) {
|
|
25
|
-
return { connectionString: connection.connectionString.trim(), ssl, connectionTimeoutMillis: 8000 };
|
|
26
|
-
}
|
|
27
|
-
return {
|
|
28
|
-
host: connection.host,
|
|
29
|
-
port: connection.port,
|
|
30
|
-
database: connection.database,
|
|
31
|
-
user: connection.username,
|
|
32
|
-
password: connection.password,
|
|
33
|
-
ssl,
|
|
34
|
-
connectionTimeoutMillis: 8000,
|
|
35
|
-
};
|
|
36
|
-
};
|
|
37
|
-
const normalizePgValue = (value) => JSON.parse(JSON.stringify(value, (_key, entry) => {
|
|
38
|
-
if (typeof entry === "bigint")
|
|
39
|
-
return entry.toString();
|
|
40
|
-
if (entry instanceof Date)
|
|
41
|
-
return entry.toISOString();
|
|
42
|
-
if (Buffer.isBuffer(entry) || entry instanceof Uint8Array) {
|
|
43
|
-
return Buffer.from(entry).toString("hex");
|
|
44
|
-
}
|
|
45
|
-
return entry;
|
|
46
|
-
}));
|
|
47
24
|
export const testPostgresConnection = async (connection) => {
|
|
48
25
|
const { Client } = await loadPgDriver();
|
|
49
|
-
const client = new Client(
|
|
26
|
+
const client = new Client(buildPgClientConfig(connection));
|
|
50
27
|
await client.connect();
|
|
51
28
|
try {
|
|
52
29
|
await client.query("SELECT 1");
|
|
@@ -57,16 +34,10 @@ export const testPostgresConnection = async (connection) => {
|
|
|
57
34
|
};
|
|
58
35
|
export const executePostgresQuery = async (connection, query, params = []) => {
|
|
59
36
|
const { Client } = await loadPgDriver();
|
|
60
|
-
const client = new Client(
|
|
37
|
+
const client = new Client(buildPgClientConfig(connection));
|
|
61
38
|
await client.connect();
|
|
62
39
|
try {
|
|
63
|
-
|
|
64
|
-
const result = await client.query(finalQuery, params);
|
|
65
|
-
const rows = Array.isArray(result.rows) ? result.rows.map(normalizePgValue) : [];
|
|
66
|
-
return {
|
|
67
|
-
rows,
|
|
68
|
-
rowCount: typeof result.rowCount === "number" ? result.rowCount : rows.length,
|
|
69
|
-
};
|
|
40
|
+
return await runPgQuery(client, query, params);
|
|
70
41
|
}
|
|
71
42
|
finally {
|
|
72
43
|
await client.end();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgresAdapter.js","sourceRoot":"","sources":["../../../src/host/db/postgresAdapter.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,
|
|
1
|
+
{"version":3,"file":"postgresAdapter.js","sourceRoot":"","sources":["../../../src/host/db/postgresAdapter.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,4EAA4E;AAC5E,yEAAyE;AACzE,qBAAqB;AAErB,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhD,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtE,MAAM,MAAM,GAAG,CAAC,GAAQ,EAAO,EAAE,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AAE1F,qCAAqC;AACrC,IAAI,gBAAgB,GAAQ,IAAI,CAAC;AACjC,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,MAAkB,EAAQ,EAAE;IACtE,gBAAgB,GAAG,MAAM,CAAC;AAC5B,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,KAAK,IAAkB,EAAE;IAC5C,IAAI,gBAAgB,EAAE,CAAC;QACrB,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IACD,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,MAAM,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,wFAAwF,CACzF,CAAC;IACJ,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,sBAAsB,GAAG,KAAK,EAAE,UAAwB,EAAiB,EAAE;IACtF,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,YAAY,EAAE,CAAC;IACxC,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC,CAAC;IAC3D,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;IACvB,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACjC,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,GAAG,EAAE,CAAC;IACrB,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,KAAK,EACvC,UAAwB,EACxB,KAAa,EACb,SAAoB,EAAE,EAC0B,EAAE;IAClD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,YAAY,EAAE,CAAC;IACxC,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC,CAAC;IAC3D,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;IACvB,IAAI,CAAC;QACH,OAAO,MAAM,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IACjD,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,GAAG,EAAE,CAAC;IACrB,CAAC;AACH,CAAC,CAAC"}
|
|
@@ -3,6 +3,10 @@ export declare const executeResolvedDbQuery: (input: {
|
|
|
3
3
|
connection: DbConnectionInput;
|
|
4
4
|
resolvedQuery: string;
|
|
5
5
|
params?: unknown[];
|
|
6
|
+
session?: {
|
|
7
|
+
runId: string;
|
|
8
|
+
transactionMode: "none" | "rollback" | "commit";
|
|
9
|
+
};
|
|
6
10
|
}) => Promise<{
|
|
7
11
|
rows: unknown[];
|
|
8
12
|
rowCount: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queryExecutor.d.ts","sourceRoot":"","sources":["../../../src/host/db/queryExecutor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"queryExecutor.d.ts","sourceRoot":"","sources":["../../../src/host/db/queryExecutor.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAEV,iBAAiB,EACjB,sBAAsB,EACtB,sBAAsB,EACtB,qBAAqB,EACtB,MAAM,YAAY,CAAC;AA8BpB,eAAO,MAAM,sBAAsB,GAAI,OAAO;IAC5C,UAAU,EAAE,iBAAiB,CAAC;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,GAAG,UAAU,GAAG,QAAQ,CAAA;KAAE,CAAC;CAC9E,KAAG,OAAO,CAAC;IAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAmBhD,CAAC;AA6BF,eAAO,MAAM,gBAAgB,GAC3B,iBAAiB,iBAAiB,KACjC,OAAO,CAAC,sBAAsB,CA4BhC,CAAC;AAEF,eAAO,MAAM,YAAY,GACvB,SAAS,qBAAqB,KAC7B,OAAO,CAAC,sBAAsB,CAyEhC,CAAC"}
|
|
@@ -7,6 +7,8 @@ import { executeMongoQuery, testMongoConnection } from "./mongoAdapter.js";
|
|
|
7
7
|
import { executeMysqlQuery, testMysqlConnection } from "./mysqlAdapter.js";
|
|
8
8
|
import { executeOracleQuery, testOracleConnection } from "./oracleAdapter.js";
|
|
9
9
|
import { executePostgresQuery, testPostgresConnection } from "./postgresAdapter.js";
|
|
10
|
+
import { executePostgresQueryInSession } from "./pgSessionManager.js";
|
|
11
|
+
import { extractSqlState } from "./sqlState.js";
|
|
10
12
|
import { resolveTemplate } from "./templateResolver.js";
|
|
11
13
|
import { executeMssqlQuery, testMssqlConnection } from "./mssqlAdapter.js";
|
|
12
14
|
const executeAgainstConnection = async (connection, resolvedQuery, params = []) => {
|
|
@@ -27,7 +29,27 @@ const executeAgainstConnection = async (connection, resolvedQuery, params = [])
|
|
|
27
29
|
// right driver, WITHOUT re-resolving templates. This is the canonical entry for
|
|
28
30
|
// the scenario / `databaseExecutor` path (core's scenario runner resolves the
|
|
29
31
|
// template before calling the host), so hosts must not duplicate adapter logic.
|
|
30
|
-
|
|
32
|
+
//
|
|
33
|
+
// `session` (additive) routes the query through the run-scoped Postgres
|
|
34
|
+
// session instead of a one-shot client — see pgSessionManager. Only Postgres
|
|
35
|
+
// supports sessions; other providers fail with an actionable message so a
|
|
36
|
+
// `useSession` node never silently runs autocommit.
|
|
37
|
+
export const executeResolvedDbQuery = (input) => {
|
|
38
|
+
const connection = normalizeConnectionInput(input.connection);
|
|
39
|
+
if (input.session) {
|
|
40
|
+
if (connection.type !== "postgres") {
|
|
41
|
+
return Promise.reject(new Error(`Scenario DB sessions are only supported for PostgreSQL connections (got "${connection.type}"). Disable 'Run in scenario transaction' on this node.`));
|
|
42
|
+
}
|
|
43
|
+
return executePostgresQueryInSession({
|
|
44
|
+
connection,
|
|
45
|
+
runId: input.session.runId,
|
|
46
|
+
transactionMode: input.session.transactionMode,
|
|
47
|
+
query: input.resolvedQuery,
|
|
48
|
+
params: input.params ?? [],
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
return executeAgainstConnection(connection, input.resolvedQuery, input.params ?? []);
|
|
52
|
+
};
|
|
31
53
|
const normalizeConnectionInput = (connectionInput) => ({
|
|
32
54
|
id: connectionInput.id?.trim() || "runtime-connection",
|
|
33
55
|
name: connectionInput.name.trim(),
|
|
@@ -46,6 +68,10 @@ const normalizeConnectionInput = (connectionInput) => ({
|
|
|
46
68
|
password: connectionInput.password,
|
|
47
69
|
ssl: connectionInput.ssl,
|
|
48
70
|
trustServerCertificate: connectionInput.trustServerCertificate,
|
|
71
|
+
sslMode: connectionInput.sslMode,
|
|
72
|
+
caCert: connectionInput.caCert,
|
|
73
|
+
clientCert: connectionInput.clientCert,
|
|
74
|
+
clientKey: connectionInput.clientKey,
|
|
49
75
|
});
|
|
50
76
|
// Connectivity check for a draft/saved connection. Ported from the desktop
|
|
51
77
|
// host so consumers (Electron `db:test-connection`) don't reimplement it.
|
|
@@ -104,7 +130,18 @@ export const executeQuery = async (payload) => {
|
|
|
104
130
|
}
|
|
105
131
|
try {
|
|
106
132
|
const resolvedQuery = resolveTemplate(payload.query, payload.context ?? {});
|
|
107
|
-
|
|
133
|
+
if (payload.session && connection.type !== "postgres") {
|
|
134
|
+
throw new Error(`Scenario DB sessions are only supported for PostgreSQL connections (got "${connection.type}"). Disable 'Run in scenario transaction' on this node.`);
|
|
135
|
+
}
|
|
136
|
+
const result = payload.session
|
|
137
|
+
? await executePostgresQueryInSession({
|
|
138
|
+
connection,
|
|
139
|
+
runId: payload.session.runId,
|
|
140
|
+
transactionMode: payload.session.transactionMode,
|
|
141
|
+
query: resolvedQuery,
|
|
142
|
+
params: payload.params ?? [],
|
|
143
|
+
})
|
|
144
|
+
: await executeAgainstConnection(connection, resolvedQuery, payload.params ?? []);
|
|
108
145
|
return {
|
|
109
146
|
success: true,
|
|
110
147
|
phase: payload.phase,
|
|
@@ -135,6 +172,7 @@ export const executeQuery = async (payload) => {
|
|
|
135
172
|
durationMs: Math.round(performance.now() - startedAt),
|
|
136
173
|
executedAt: new Date().toISOString(),
|
|
137
174
|
error: error instanceof Error ? error.message : String(error),
|
|
175
|
+
...(extractSqlState(error) ? { sqlState: extractSqlState(error) } : {}),
|
|
138
176
|
};
|
|
139
177
|
}
|
|
140
178
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queryExecutor.js","sourceRoot":"","sources":["../../../src/host/db/queryExecutor.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,+EAA+E;AAC/E,gFAAgF;AAChF,wEAAwE;AAExE,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACpF,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAS3E,MAAM,wBAAwB,GAAG,KAAK,EACpC,UAAwB,EACxB,aAAqB,EACrB,SAAoB,EAAE,EAC0B,EAAE;IAClD,QAAQ,UAAU,CAAC,IAAI,EAAE,CAAC;QACxB,KAAK,OAAO;YACV,OAAO,iBAAiB,CAAC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC;QAClE,KAAK,UAAU;YACb,OAAO,oBAAoB,CAAC,UAAU,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC;QACjE,KAAK,OAAO;YACV,OAAO,iBAAiB,CAAC,UAAU,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC;QAC9D,KAAK,OAAO;YACV,OAAO,iBAAiB,CAAC,UAAU,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC;QAC9D;YACE,OAAO,kBAAkB,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IACzD,CAAC;AACH,CAAC,CAAC;AAEF,8EAA8E;AAC9E,gFAAgF;AAChF,8EAA8E;AAC9E,gFAAgF;AAChF,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"queryExecutor.js","sourceRoot":"","sources":["../../../src/host/db/queryExecutor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlState.d.ts","sourceRoot":"","sources":["../../../src/host/db/sqlState.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,eAAe,GAAI,OAAO,OAAO,KAAG,MAAM,GAAG,SAOzD,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// SQLSTATE extraction shared by the scenario db-executor, the host query
|
|
2
|
+
// executor, and desktop adapters. Postgres SQLSTATE is 5 alphanumeric chars;
|
|
3
|
+
// `pg` errors expose it as `.code`. `.sqlState` is checked first so hosts
|
|
4
|
+
// can attach it explicitly without colliding with Node's `error.code`
|
|
5
|
+
// values (e.g. ECONNREFUSED).
|
|
6
|
+
export const extractSqlState = (error) => {
|
|
7
|
+
if (!error || typeof error !== "object")
|
|
8
|
+
return undefined;
|
|
9
|
+
const candidate = error.sqlState ?? error.code;
|
|
10
|
+
return typeof candidate === "string" && /^[0-9A-Z]{5}$/.test(candidate)
|
|
11
|
+
? candidate
|
|
12
|
+
: undefined;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=sqlState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlState.js","sourceRoot":"","sources":["../../../src/host/db/sqlState.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,6EAA6E;AAC7E,0EAA0E;AAC1E,sEAAsE;AACtE,8BAA8B;AAC9B,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,KAAc,EAAsB,EAAE;IACpE,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC1D,MAAM,SAAS,GACZ,KAAgC,CAAC,QAAQ,IAAK,KAA4B,CAAC,IAAI,CAAC;IACnF,OAAO,OAAO,SAAS,KAAK,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC;QACrE,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC,CAAC"}
|
package/dist/host/db/types.d.ts
CHANGED
|
@@ -16,6 +16,10 @@ export interface DbConnection {
|
|
|
16
16
|
password: string;
|
|
17
17
|
ssl?: boolean;
|
|
18
18
|
trustServerCertificate?: boolean;
|
|
19
|
+
sslMode?: "disable" | "require" | "verify-ca" | "verify-full";
|
|
20
|
+
caCert?: string;
|
|
21
|
+
clientCert?: string;
|
|
22
|
+
clientKey?: string;
|
|
19
23
|
}
|
|
20
24
|
export interface DbConnectionInput {
|
|
21
25
|
id?: string;
|
|
@@ -32,6 +36,10 @@ export interface DbConnectionInput {
|
|
|
32
36
|
password: string;
|
|
33
37
|
ssl?: boolean;
|
|
34
38
|
trustServerCertificate?: boolean;
|
|
39
|
+
sslMode?: "disable" | "require" | "verify-ca" | "verify-full";
|
|
40
|
+
caCert?: string;
|
|
41
|
+
clientCert?: string;
|
|
42
|
+
clientKey?: string;
|
|
35
43
|
}
|
|
36
44
|
export interface DbTemplateContext {
|
|
37
45
|
response?: unknown | null;
|
|
@@ -45,6 +53,10 @@ export interface ExecuteDbQueryPayload {
|
|
|
45
53
|
params?: unknown[];
|
|
46
54
|
phase: DbQueryPhase;
|
|
47
55
|
context?: DbTemplateContext;
|
|
56
|
+
session?: {
|
|
57
|
+
runId: string;
|
|
58
|
+
transactionMode: "none" | "rollback" | "commit";
|
|
59
|
+
};
|
|
48
60
|
}
|
|
49
61
|
export interface DbQueryExecutionResult {
|
|
50
62
|
success: boolean;
|
|
@@ -59,6 +71,7 @@ export interface DbQueryExecutionResult {
|
|
|
59
71
|
durationMs: number;
|
|
60
72
|
executedAt: string;
|
|
61
73
|
error?: string;
|
|
74
|
+
sqlState?: string;
|
|
62
75
|
}
|
|
63
76
|
export interface DbConnectionTestResult {
|
|
64
77
|
success: boolean;
|