@slonik/pg-driver 43.0.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/README.md ADDED
@@ -0,0 +1,6 @@
1
+ # Slonik Driver for `pg`
2
+
3
+ ```ts
4
+ import {
5
+ createPgDriverFactory,
6
+ } from '@slonik/pg-driver';
@@ -0,0 +1,3 @@
1
+ import { type DriverFactory } from '@slonik/driver';
2
+ export declare const createPgDriverFactory: () => DriverFactory;
3
+ //# sourceMappingURL=createPgDriverFactory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createPgDriverFactory.d.ts","sourceRoot":"","sources":["../../src/factories/createPgDriverFactory.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,aAAa,EAEnB,MAAM,gBAAgB,CAAC;AAqPxB,eAAO,MAAM,qBAAqB,QAAO,aAgIxC,CAAC"}
@@ -0,0 +1,274 @@
1
+ "use strict";
2
+ /* eslint-disable canonical/id-match */
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.createPgDriverFactory = void 0;
8
+ const driver_1 = require("@slonik/driver");
9
+ const errors_1 = require("@slonik/errors");
10
+ const utilities_1 = require("@slonik/utilities");
11
+ const node_stream_1 = require("node:stream");
12
+ // eslint-disable-next-line no-restricted-imports
13
+ const pg_1 = require("pg");
14
+ const pg_query_stream_1 = __importDefault(require("pg-query-stream"));
15
+ const pg_types_1 = require("pg-types");
16
+ const postgres_array_1 = require("postgres-array");
17
+ const createTypeOverrides = async (connection, typeParsers) => {
18
+ const typeNames = typeParsers.map((typeParser) => {
19
+ return typeParser.name;
20
+ });
21
+ const postgresTypes = (await connection.query(`
22
+ SELECT
23
+ oid,
24
+ typarray,
25
+ typname
26
+ FROM pg_type
27
+ WHERE typname = ANY($1::text[])
28
+ `, [typeNames])).rows;
29
+ const parsers = {};
30
+ for (const typeParser of typeParsers) {
31
+ const postgresType = postgresTypes.find((maybeTargetPostgresType) => {
32
+ return maybeTargetPostgresType.typname === typeParser.name;
33
+ });
34
+ if (!postgresType) {
35
+ throw new Error('Database type "' + typeParser.name + '" not found.');
36
+ }
37
+ parsers[postgresType.oid] = (value) => {
38
+ return typeParser.parse(value);
39
+ };
40
+ if (postgresType.typarray) {
41
+ parsers[postgresType.typarray] = (arrayValue) => {
42
+ return (0, postgres_array_1.parse)(arrayValue).map((value) => {
43
+ return typeParser.parse(value);
44
+ });
45
+ };
46
+ }
47
+ }
48
+ return (oid) => {
49
+ if (parsers[oid]) {
50
+ return parsers[oid];
51
+ }
52
+ return (0, pg_types_1.getTypeParser)(oid);
53
+ };
54
+ };
55
+ const createClientConfiguration = (clientConfiguration) => {
56
+ const connectionOptions = (0, utilities_1.parseDsn)(clientConfiguration.connectionUri);
57
+ const poolConfiguration = {
58
+ application_name: connectionOptions.applicationName,
59
+ database: connectionOptions.databaseName,
60
+ host: connectionOptions.host,
61
+ options: connectionOptions.options,
62
+ password: connectionOptions.password,
63
+ port: connectionOptions.port,
64
+ ssl: false,
65
+ user: connectionOptions.username,
66
+ };
67
+ if (clientConfiguration.ssl) {
68
+ poolConfiguration.ssl = clientConfiguration.ssl;
69
+ }
70
+ else if (connectionOptions.sslMode === 'disable') {
71
+ poolConfiguration.ssl = false;
72
+ }
73
+ else if (connectionOptions.sslMode === 'require') {
74
+ poolConfiguration.ssl = true;
75
+ }
76
+ else if (connectionOptions.sslMode === 'no-verify') {
77
+ poolConfiguration.ssl = {
78
+ rejectUnauthorized: false,
79
+ };
80
+ }
81
+ if (clientConfiguration.connectionTimeout !== 'DISABLE_TIMEOUT') {
82
+ if (clientConfiguration.connectionTimeout === 0) {
83
+ poolConfiguration.connectionTimeoutMillis = 1;
84
+ }
85
+ else {
86
+ poolConfiguration.connectionTimeoutMillis =
87
+ clientConfiguration.connectionTimeout;
88
+ }
89
+ }
90
+ if (clientConfiguration.statementTimeout !== 'DISABLE_TIMEOUT') {
91
+ if (clientConfiguration.statementTimeout === 0) {
92
+ poolConfiguration.statement_timeout = 1;
93
+ }
94
+ else {
95
+ poolConfiguration.statement_timeout =
96
+ clientConfiguration.statementTimeout;
97
+ }
98
+ }
99
+ if (clientConfiguration.idleInTransactionSessionTimeout !== 'DISABLE_TIMEOUT') {
100
+ if (clientConfiguration.idleInTransactionSessionTimeout === 0) {
101
+ poolConfiguration.idle_in_transaction_session_timeout = 1;
102
+ }
103
+ else {
104
+ poolConfiguration.idle_in_transaction_session_timeout =
105
+ clientConfiguration.idleInTransactionSessionTimeout;
106
+ }
107
+ }
108
+ return poolConfiguration;
109
+ };
110
+ const queryTypeOverrides = async (pgClientConfiguration, driverConfiguration) => {
111
+ const client = new pg_1.Client(pgClientConfiguration);
112
+ await client.connect();
113
+ const typeOverrides = await createTypeOverrides(client, driverConfiguration.typeParsers);
114
+ await client.end();
115
+ return typeOverrides;
116
+ };
117
+ const isErrorWithCode = (error) => {
118
+ return 'code' in error;
119
+ };
120
+ // query is not available for connection-level errors.
121
+ // TODO evaluate if we can remove query from the error object.
122
+ // I suspect we should not be even using InputSyntaxError as one of the error types.
123
+ // @see https://github.com/gajus/slonik/issues/557
124
+ const wrapError = (error, query) => {
125
+ if (error.message.toLowerCase().includes('connection terminated unexpectedly')) {
126
+ return new errors_1.BackendTerminatedUnexpectedlyError(error);
127
+ }
128
+ if (error.message.toLowerCase().includes('connection terminated')) {
129
+ return new errors_1.BackendTerminatedError(error);
130
+ }
131
+ if (!isErrorWithCode(error)) {
132
+ return error;
133
+ }
134
+ if (error.code === '22P02') {
135
+ return new errors_1.InvalidInputError(error.message);
136
+ }
137
+ if (error.code === '25P03') {
138
+ return new errors_1.IdleTransactionTimeoutError(error);
139
+ }
140
+ if (error.code === '57P01') {
141
+ return new errors_1.BackendTerminatedError(error);
142
+ }
143
+ if (error.code === '57014' &&
144
+ // The code alone is not enough to distinguish between a statement timeout and a statement cancellation.
145
+ error.message.includes('canceling statement due to user request')) {
146
+ return new errors_1.StatementCancelledError(error);
147
+ }
148
+ if (error.code === '57014') {
149
+ return new errors_1.StatementTimeoutError(error);
150
+ }
151
+ if (error.code === '23502') {
152
+ return new errors_1.NotNullIntegrityConstraintViolationError(error);
153
+ }
154
+ if (error.code === '23503') {
155
+ return new errors_1.ForeignKeyIntegrityConstraintViolationError(error);
156
+ }
157
+ if (error.code === '23505') {
158
+ return new errors_1.UniqueIntegrityConstraintViolationError(error);
159
+ }
160
+ if (error.code === '23514') {
161
+ return new errors_1.CheckIntegrityConstraintViolationError(error);
162
+ }
163
+ if (error.code === '42601') {
164
+ if (!query) {
165
+ return new errors_1.UnexpectedStateError('Expected query to be provided');
166
+ }
167
+ return new errors_1.InputSyntaxError(error, query);
168
+ }
169
+ return error;
170
+ };
171
+ const createPgDriverFactory = () => {
172
+ return (0, driver_1.createDriverFactory)(async ({ driverConfiguration }) => {
173
+ const clientConfiguration = createClientConfiguration(driverConfiguration);
174
+ // eslint-disable-next-line require-atomic-updates
175
+ clientConfiguration.types = {
176
+ getTypeParser: await queryTypeOverrides(clientConfiguration, driverConfiguration),
177
+ };
178
+ return {
179
+ createPoolClient: async ({ clientEventEmitter }) => {
180
+ const client = new pg_1.Client(clientConfiguration);
181
+ // We will see this triggered when the connection is terminated, e.g.
182
+ // "terminates transactions that are idle beyond idleInTransactionSessionTimeout" test.
183
+ const onError = (error) => {
184
+ clientEventEmitter.emit('error', wrapError(error, null));
185
+ };
186
+ const onNotice = (notice) => {
187
+ if (notice.message) {
188
+ clientEventEmitter.emit('notice', {
189
+ message: notice.message,
190
+ });
191
+ }
192
+ };
193
+ client.on('error', onError);
194
+ client.on('notice', onNotice);
195
+ return {
196
+ connect: async () => {
197
+ await client.connect();
198
+ },
199
+ end: async () => {
200
+ await client.end();
201
+ client.removeListener('error', onError);
202
+ client.removeListener('notice', onNotice);
203
+ },
204
+ query: async (sql, values) => {
205
+ let result;
206
+ try {
207
+ result = await client.query(sql, values);
208
+ }
209
+ catch (error) {
210
+ throw wrapError(error, {
211
+ sql,
212
+ values: values,
213
+ });
214
+ }
215
+ if (Array.isArray(result)) {
216
+ throw new errors_1.InvalidInputError('Must not use multiple statements in a single query.');
217
+ }
218
+ return {
219
+ command: result.command,
220
+ fields: result.fields.map((field) => {
221
+ return {
222
+ dataTypeId: field.dataTypeID,
223
+ name: field.name,
224
+ };
225
+ }),
226
+ rowCount: result.rowCount,
227
+ rows: result.rows,
228
+ };
229
+ },
230
+ stream: (sql, values) => {
231
+ const stream = client.query(new pg_query_stream_1.default(sql, values));
232
+ let fields = [];
233
+ // `rowDescription` will not fire if the query produces a syntax error.
234
+ // Also, `rowDescription` won't fire until client starts consuming the stream.
235
+ // This is why we cannot simply await for `rowDescription` event before starting to pipe the stream.
236
+ // @ts-expect-error – https://github.com/brianc/node-postgres/issues/3015
237
+ client.connection.once('rowDescription', (rowDescription) => {
238
+ fields = rowDescription.fields.map((field) => {
239
+ return {
240
+ dataTypeId: field.dataTypeID,
241
+ name: field.name,
242
+ };
243
+ });
244
+ });
245
+ const transform = new node_stream_1.Transform({
246
+ objectMode: true,
247
+ async transform(datum, enc, callback) {
248
+ if (!fields) {
249
+ callback(new Error('Fields not available'));
250
+ return;
251
+ }
252
+ // eslint-disable-next-line @babel/no-invalid-this
253
+ this.push({
254
+ fields,
255
+ row: datum,
256
+ });
257
+ callback();
258
+ },
259
+ });
260
+ stream.on('error', (error) => {
261
+ transform.emit('error', wrapError(error, {
262
+ sql,
263
+ values: values,
264
+ }));
265
+ });
266
+ return stream.pipe(transform);
267
+ },
268
+ };
269
+ },
270
+ };
271
+ });
272
+ };
273
+ exports.createPgDriverFactory = createPgDriverFactory;
274
+ //# sourceMappingURL=createPgDriverFactory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createPgDriverFactory.js","sourceRoot":"","sources":["../../src/factories/createPgDriverFactory.ts"],"names":[],"mappings":";AAAA,uCAAuC;;;;;;AAEvC,2CAMwB;AACxB,2CAawB;AAGxB,iDAA6C;AAC7C,6CAAwC;AACxC,iDAAiD;AACjD,2BAIY;AACZ,sEAA0C;AAC1C,uCAAgE;AAChE,mDAAqD;AAWrD,MAAM,mBAAmB,GAAG,KAAK,EAC/B,UAAkB,EAClB,WAAwC,EAChB,EAAE;IAC1B,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE;QAC/C,OAAO,UAAU,CAAC,IAAI,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,CACpB,MAAM,UAAU,CAAC,KAAK,CACpB;;;;;;;OAOC,EACD,CAAC,SAAS,CAAC,CACZ,CACF,CAAC,IAAsB,CAAC;IAEzB,MAAM,OAAO,GAAG,EAAE,CAAC;IAEnB,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,uBAAuB,EAAE,EAAE;YAClE,OAAO,uBAAuB,CAAC,OAAO,KAAK,UAAU,CAAC,IAAI,CAAC;QAC7D,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,iBAAiB,GAAG,UAAU,CAAC,IAAI,GAAG,cAAc,CAAC,CAAC;QACxE,CAAC;QAED,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE;YACpC,OAAO,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC,CAAC;QAEF,IAAI,YAAY,CAAC,QAAQ,EAAE,CAAC;YAC1B,OAAO,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE;gBAC9C,OAAO,IAAA,sBAAU,EAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;oBAC1C,OAAO,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBACjC,CAAC,CAAC,CAAC;YACL,CAAC,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAW,EAAE,EAAE;QACrB,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACjB,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;QAED,OAAO,IAAA,wBAAmB,EAAC,GAAG,CAAC,CAAC;IAClC,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,yBAAyB,GAAG,CAChC,mBAAwC,EACL,EAAE;IACrC,MAAM,iBAAiB,GAAG,IAAA,oBAAQ,EAAC,mBAAmB,CAAC,aAAa,CAAC,CAAC;IAEtE,MAAM,iBAAiB,GAAsC;QAC3D,gBAAgB,EAAE,iBAAiB,CAAC,eAAe;QACnD,QAAQ,EAAE,iBAAiB,CAAC,YAAY;QACxC,IAAI,EAAE,iBAAiB,CAAC,IAAI;QAC5B,OAAO,EAAE,iBAAiB,CAAC,OAAO;QAClC,QAAQ,EAAE,iBAAiB,CAAC,QAAQ;QACpC,IAAI,EAAE,iBAAiB,CAAC,IAAI;QAC5B,GAAG,EAAE,KAAK;QACV,IAAI,EAAE,iBAAiB,CAAC,QAAQ;KACjC,CAAC;IAEF,IAAI,mBAAmB,CAAC,GAAG,EAAE,CAAC;QAC5B,iBAAiB,CAAC,GAAG,GAAG,mBAAmB,CAAC,GAAG,CAAC;IAClD,CAAC;SAAM,IAAI,iBAAiB,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QACnD,iBAAiB,CAAC,GAAG,GAAG,KAAK,CAAC;IAChC,CAAC;SAAM,IAAI,iBAAiB,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QACnD,iBAAiB,CAAC,GAAG,GAAG,IAAI,CAAC;IAC/B,CAAC;SAAM,IAAI,iBAAiB,CAAC,OAAO,KAAK,WAAW,EAAE,CAAC;QACrD,iBAAiB,CAAC,GAAG,GAAG;YACtB,kBAAkB,EAAE,KAAK;SAC1B,CAAC;IACJ,CAAC;IAED,IAAI,mBAAmB,CAAC,iBAAiB,KAAK,iBAAiB,EAAE,CAAC;QAChE,IAAI,mBAAmB,CAAC,iBAAiB,KAAK,CAAC,EAAE,CAAC;YAChD,iBAAiB,CAAC,uBAAuB,GAAG,CAAC,CAAC;QAChD,CAAC;aAAM,CAAC;YACN,iBAAiB,CAAC,uBAAuB;gBACvC,mBAAmB,CAAC,iBAAiB,CAAC;QAC1C,CAAC;IACH,CAAC;IAED,IAAI,mBAAmB,CAAC,gBAAgB,KAAK,iBAAiB,EAAE,CAAC;QAC/D,IAAI,mBAAmB,CAAC,gBAAgB,KAAK,CAAC,EAAE,CAAC;YAC/C,iBAAiB,CAAC,iBAAiB,GAAG,CAAC,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,iBAAiB,CAAC,iBAAiB;gBACjC,mBAAmB,CAAC,gBAAgB,CAAC;QACzC,CAAC;IACH,CAAC;IAED,IACE,mBAAmB,CAAC,+BAA+B,KAAK,iBAAiB,EACzE,CAAC;QACD,IAAI,mBAAmB,CAAC,+BAA+B,KAAK,CAAC,EAAE,CAAC;YAC9D,iBAAiB,CAAC,mCAAmC,GAAG,CAAC,CAAC;QAC5D,CAAC;aAAM,CAAC;YACN,iBAAiB,CAAC,mCAAmC;gBACnD,mBAAmB,CAAC,+BAA+B,CAAC;QACxD,CAAC;IACH,CAAC;IAED,OAAO,iBAAiB,CAAC;AAC3B,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,KAAK,EAC9B,qBAAwD,EACxD,mBAAwC,EAChB,EAAE;IAC1B,MAAM,MAAM,GAAG,IAAI,WAAM,CAAC,qBAAqB,CAAC,CAAC;IAEjD,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;IAEvB,MAAM,aAAa,GAAG,MAAM,mBAAmB,CAC7C,MAAM,EACN,mBAAmB,CAAC,WAAW,CAChC,CAAC;IAEF,MAAM,MAAM,CAAC,GAAG,EAAE,CAAC;IAEnB,OAAO,aAAa,CAAC;AACvB,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,KAAY,EAA0B,EAAE;IAC/D,OAAO,MAAM,IAAI,KAAK,CAAC;AACzB,CAAC,CAAC;AAEF,sDAAsD;AACtD,8DAA8D;AAC9D,oFAAoF;AACpF,kDAAkD;AAClD,MAAM,SAAS,GAAG,CAAC,KAAY,EAAE,KAAmB,EAAE,EAAE;IACtD,IACE,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC,EAC1E,CAAC;QACD,OAAO,IAAI,2CAAkC,CAAC,KAAK,CAAC,CAAC;IACvD,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC,EAAE,CAAC;QAClE,OAAO,IAAI,+BAAsB,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC3B,OAAO,IAAI,0BAAiB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC9C,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC3B,OAAO,IAAI,oCAA2B,CAAC,KAAK,CAAC,CAAC;IAChD,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC3B,OAAO,IAAI,+BAAsB,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC;IAED,IACE,KAAK,CAAC,IAAI,KAAK,OAAO;QACtB,wGAAwG;QACxG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,yCAAyC,CAAC,EACjE,CAAC;QACD,OAAO,IAAI,gCAAuB,CAAC,KAAK,CAAC,CAAC;IAC5C,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC3B,OAAO,IAAI,8BAAqB,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC3B,OAAO,IAAI,iDAAwC,CAAC,KAAK,CAAC,CAAC;IAC7D,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC3B,OAAO,IAAI,oDAA2C,CAAC,KAAK,CAAC,CAAC;IAChE,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC3B,OAAO,IAAI,gDAAuC,CAAC,KAAK,CAAC,CAAC;IAC5D,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC3B,OAAO,IAAI,+CAAsC,CAAC,KAAK,CAAC,CAAC;IAC3D,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC3B,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,IAAI,6BAAoB,CAAC,+BAA+B,CAAC,CAAC;QACnE,CAAC;QAED,OAAO,IAAI,yBAAgB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC5C,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEK,MAAM,qBAAqB,GAAG,GAAkB,EAAE;IACvD,OAAO,IAAA,4BAAmB,EAAC,KAAK,EAAE,EAAE,mBAAmB,EAAE,EAAE,EAAE;QAC3D,MAAM,mBAAmB,GAAG,yBAAyB,CAAC,mBAAmB,CAAC,CAAC;QAE3E,kDAAkD;QAClD,mBAAmB,CAAC,KAAK,GAAG;YAC1B,aAAa,EAAE,MAAM,kBAAkB,CACrC,mBAAmB,EACnB,mBAAmB,CACpB;SACF,CAAC;QAEF,OAAO;YACL,gBAAgB,EAAE,KAAK,EAAE,EAAE,kBAAkB,EAAE,EAAE,EAAE;gBACjD,MAAM,MAAM,GAAG,IAAI,WAAM,CAAC,mBAAmB,CAAC,CAAC;gBAE/C,qEAAqE;gBACrE,uFAAuF;gBACvF,MAAM,OAAO,GAAG,CAAC,KAAK,EAAE,EAAE;oBACxB,kBAAkB,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;gBAC3D,CAAC,CAAC;gBAEF,MAAM,QAAQ,GAAG,CAAC,MAAM,EAAE,EAAE;oBAC1B,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;wBACnB,kBAAkB,CAAC,IAAI,CAAC,QAAQ,EAAE;4BAChC,OAAO,EAAE,MAAM,CAAC,OAAO;yBACxB,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC,CAAC;gBAEF,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBAC5B,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;gBAE9B,OAAO;oBACL,OAAO,EAAE,KAAK,IAAI,EAAE;wBAClB,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;oBACzB,CAAC;oBACD,GAAG,EAAE,KAAK,IAAI,EAAE;wBACd,MAAM,MAAM,CAAC,GAAG,EAAE,CAAC;wBAEnB,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;wBACxC,MAAM,CAAC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;oBAC5C,CAAC;oBACD,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE;wBAC3B,IAAI,MAAM,CAAC;wBAEX,IAAI,CAAC;4BACH,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,MAAmB,CAAC,CAAC;wBACxD,CAAC;wBAAC,OAAO,KAAK,EAAE,CAAC;4BACf,MAAM,SAAS,CAAC,KAAK,EAAE;gCACrB,GAAG;gCACH,MAAM,EAAE,MAA6C;6BACtD,CAAC,CAAC;wBACL,CAAC;wBAED,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;4BAC1B,MAAM,IAAI,0BAAiB,CACzB,qDAAqD,CACtD,CAAC;wBACJ,CAAC;wBAED,OAAO;4BACL,OAAO,EAAE,MAAM,CAAC,OAAwB;4BACxC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;gCAClC,OAAO;oCACL,UAAU,EAAE,KAAK,CAAC,UAAU;oCAC5B,IAAI,EAAE,KAAK,CAAC,IAAI;iCACjB,CAAC;4BACJ,CAAC,CAAC;4BACF,QAAQ,EAAE,MAAM,CAAC,QAAQ;4BACzB,IAAI,EAAE,MAAM,CAAC,IAAI;yBAClB,CAAC;oBACJ,CAAC;oBACD,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;wBACtB,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CACzB,IAAI,yBAAW,CAAC,GAAG,EAAE,MAAmB,CAAC,CAC1C,CAAC;wBAEF,IAAI,MAAM,GAAqB,EAAE,CAAC;wBAElC,uEAAuE;wBACvE,8EAA8E;wBAC9E,oGAAoG;wBACpG,yEAAyE;wBACzE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,cAAc,EAAE,EAAE;4BAC1D,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;gCAC3C,OAAO;oCACL,UAAU,EAAE,KAAK,CAAC,UAAU;oCAC5B,IAAI,EAAE,KAAK,CAAC,IAAI;iCACjB,CAAC;4BACJ,CAAC,CAAC,CAAC;wBACL,CAAC,CAAC,CAAC;wBAEH,MAAM,SAAS,GAAG,IAAI,uBAAS,CAAC;4BAC9B,UAAU,EAAE,IAAI;4BAChB,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,EAAE,QAAQ;gCAClC,IAAI,CAAC,MAAM,EAAE,CAAC;oCACZ,QAAQ,CAAC,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC,CAAC;oCAE5C,OAAO;gCACT,CAAC;gCAED,kDAAkD;gCAClD,IAAI,CAAC,IAAI,CAAC;oCACR,MAAM;oCACN,GAAG,EAAE,KAAK;iCACX,CAAC,CAAC;gCAEH,QAAQ,EAAE,CAAC;4BACb,CAAC;yBACF,CAAC,CAAC;wBAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;4BAC3B,SAAS,CAAC,IAAI,CACZ,OAAO,EACP,SAAS,CAAC,KAAK,EAAE;gCACf,GAAG;gCACH,MAAM,EAAE,MAAoC;6BAC7C,CAAC,CACH,CAAC;wBACJ,CAAC,CAAC,CAAC;wBAEH,OAAO,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;oBAChC,CAAC;iBACF,CAAC;YACJ,CAAC;SACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAhIW,QAAA,qBAAqB,yBAgIhC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=createPgDriverFactory.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createPgDriverFactory.test.d.ts","sourceRoot":"","sources":["../../src/factories/createPgDriverFactory.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const ava_1 = __importDefault(require("ava"));
7
+ (0, ava_1.default)('ok', (t) => {
8
+ t.pass();
9
+ });
10
+ //# sourceMappingURL=createPgDriverFactory.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createPgDriverFactory.test.js","sourceRoot":"","sources":["../../src/factories/createPgDriverFactory.test.ts"],"names":[],"mappings":";;;;;AAAA,8CAAuB;AAEvB,IAAA,aAAI,EAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE;IACf,CAAC,CAAC,IAAI,EAAE,CAAC;AACX,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { createPgDriverFactory } from './factories/createPgDriverFactory';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createPgDriverFactory = void 0;
4
+ var createPgDriverFactory_1 = require("./factories/createPgDriverFactory");
5
+ Object.defineProperty(exports, "createPgDriverFactory", { enumerable: true, get: function () { return createPgDriverFactory_1.createPgDriverFactory; } });
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,2EAA0E;AAAjE,8HAAA,qBAAqB,OAAA"}
package/package.json ADDED
@@ -0,0 +1,97 @@
1
+ {
2
+ "author": {
3
+ "email": "gajus@gajus.com",
4
+ "name": "Gajus Kuizinas",
5
+ "url": "http://gajus.com"
6
+ },
7
+ "ava": {
8
+ "extensions": [
9
+ "ts"
10
+ ],
11
+ "files": [
12
+ "src/**/*.test.ts"
13
+ ],
14
+ "require": [
15
+ "ts-node/register/transpile-only"
16
+ ]
17
+ },
18
+ "dependencies": {
19
+ "@slonik/driver": "^43.0.6",
20
+ "@slonik/errors": "^43.0.6",
21
+ "@slonik/sql-tag": "^43.0.6",
22
+ "@slonik/types": "^43.0.6",
23
+ "@slonik/utilities": "^43.0.6",
24
+ "pg-query-stream": "^4.5.5",
25
+ "pg-types": "^4.0.2",
26
+ "pg": "^8.11.5",
27
+ "postgres-array": "^3.0.2"
28
+ },
29
+ "description": "A Node.js PostgreSQL client with strict types, detailed logging and assertions.",
30
+ "devDependencies": {
31
+ "@types/pg": "^8.11.6",
32
+ "@types/node": "^18.15.3",
33
+ "ava": "^5.3.1",
34
+ "cspell": "^8.6.0",
35
+ "eslint": "^8.57.0",
36
+ "eslint-config-canonical": "^42.8.1",
37
+ "nyc": "^15.1.0",
38
+ "ts-node": "^10.9.1",
39
+ "typescript": "^5.4.3"
40
+ },
41
+ "engines": {
42
+ "node": ">=18"
43
+ },
44
+ "files": [
45
+ "./src",
46
+ "./dist"
47
+ ],
48
+ "keywords": [
49
+ "postgresql",
50
+ "promise",
51
+ "types"
52
+ ],
53
+ "license": "BSD-3-Clause",
54
+ "main": "./dist/index.js",
55
+ "exports": {
56
+ ".": {
57
+ "require": "./dist/index.js",
58
+ "types": "./dist/index.d.ts"
59
+ }
60
+ },
61
+ "name": "@slonik/pg-driver",
62
+ "nyc": {
63
+ "all": true,
64
+ "exclude": [
65
+ "**/*.d.ts"
66
+ ],
67
+ "include": [
68
+ "src/**/*.ts"
69
+ ],
70
+ "reporter": [
71
+ "html",
72
+ "text-summary"
73
+ ],
74
+ "require": [
75
+ "ts-node/register/transpile-only"
76
+ ],
77
+ "silent": true,
78
+ "sourceMap": false
79
+ },
80
+ "peerDependencies": {
81
+ "zod": "^3"
82
+ },
83
+ "repository": {
84
+ "type": "git",
85
+ "url": "https://github.com/gajus/slonik"
86
+ },
87
+ "scripts": {
88
+ "build": "rm -fr ./dist && tsc --project ./tsconfig.json",
89
+ "lint": "npm run lint:cspell && npm run lint:eslint && npm run lint:tsc",
90
+ "lint:cspell": "cspell . --no-progress --gitignore",
91
+ "lint:eslint": "eslint --cache ./src",
92
+ "lint:tsc": "tsc --noEmit",
93
+ "test": "nyc ava --verbose --serial"
94
+ },
95
+ "types": "./dist/index.d.ts",
96
+ "version": "43.0.6"
97
+ }
@@ -0,0 +1,5 @@
1
+ import test from 'ava';
2
+
3
+ test('ok', (t) => {
4
+ t.pass();
5
+ });
@@ -0,0 +1,382 @@
1
+ /* eslint-disable canonical/id-match */
2
+
3
+ import {
4
+ createDriverFactory,
5
+ type DriverCommand,
6
+ type DriverConfiguration,
7
+ type DriverFactory,
8
+ type DriverTypeParser,
9
+ } from '@slonik/driver';
10
+ import {
11
+ BackendTerminatedError,
12
+ BackendTerminatedUnexpectedlyError,
13
+ CheckIntegrityConstraintViolationError,
14
+ ForeignKeyIntegrityConstraintViolationError,
15
+ IdleTransactionTimeoutError,
16
+ InputSyntaxError,
17
+ InvalidInputError,
18
+ NotNullIntegrityConstraintViolationError,
19
+ StatementCancelledError,
20
+ StatementTimeoutError,
21
+ UnexpectedStateError,
22
+ UniqueIntegrityConstraintViolationError,
23
+ } from '@slonik/errors';
24
+ import { type PrimitiveValueExpression } from '@slonik/sql-tag';
25
+ import { type Field, type Query } from '@slonik/types';
26
+ import { parseDsn } from '@slonik/utilities';
27
+ import { Transform } from 'node:stream';
28
+ // eslint-disable-next-line no-restricted-imports
29
+ import {
30
+ Client,
31
+ type ClientConfig as NativePostgresClientConfiguration,
32
+ type DatabaseError,
33
+ } from 'pg';
34
+ import QueryStream from 'pg-query-stream';
35
+ import { getTypeParser as getNativeTypeParser } from 'pg-types';
36
+ import { parse as parseArray } from 'postgres-array';
37
+
38
+ type PostgresType = {
39
+ oid: string;
40
+ typarray: string;
41
+ typname: string;
42
+ };
43
+
44
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
45
+ type TypeOverrides = (oid: number) => any;
46
+
47
+ const createTypeOverrides = async (
48
+ connection: Client,
49
+ typeParsers: readonly DriverTypeParser[],
50
+ ): Promise<TypeOverrides> => {
51
+ const typeNames = typeParsers.map((typeParser) => {
52
+ return typeParser.name;
53
+ });
54
+
55
+ const postgresTypes = (
56
+ await connection.query(
57
+ `
58
+ SELECT
59
+ oid,
60
+ typarray,
61
+ typname
62
+ FROM pg_type
63
+ WHERE typname = ANY($1::text[])
64
+ `,
65
+ [typeNames],
66
+ )
67
+ ).rows as PostgresType[];
68
+
69
+ const parsers = {};
70
+
71
+ for (const typeParser of typeParsers) {
72
+ const postgresType = postgresTypes.find((maybeTargetPostgresType) => {
73
+ return maybeTargetPostgresType.typname === typeParser.name;
74
+ });
75
+
76
+ if (!postgresType) {
77
+ throw new Error('Database type "' + typeParser.name + '" not found.');
78
+ }
79
+
80
+ parsers[postgresType.oid] = (value) => {
81
+ return typeParser.parse(value);
82
+ };
83
+
84
+ if (postgresType.typarray) {
85
+ parsers[postgresType.typarray] = (arrayValue) => {
86
+ return parseArray(arrayValue).map((value) => {
87
+ return typeParser.parse(value);
88
+ });
89
+ };
90
+ }
91
+ }
92
+
93
+ return (oid: number) => {
94
+ if (parsers[oid]) {
95
+ return parsers[oid];
96
+ }
97
+
98
+ return getNativeTypeParser(oid);
99
+ };
100
+ };
101
+
102
+ const createClientConfiguration = (
103
+ clientConfiguration: DriverConfiguration,
104
+ ): NativePostgresClientConfiguration => {
105
+ const connectionOptions = parseDsn(clientConfiguration.connectionUri);
106
+
107
+ const poolConfiguration: NativePostgresClientConfiguration = {
108
+ application_name: connectionOptions.applicationName,
109
+ database: connectionOptions.databaseName,
110
+ host: connectionOptions.host,
111
+ options: connectionOptions.options,
112
+ password: connectionOptions.password,
113
+ port: connectionOptions.port,
114
+ ssl: false,
115
+ user: connectionOptions.username,
116
+ };
117
+
118
+ if (clientConfiguration.ssl) {
119
+ poolConfiguration.ssl = clientConfiguration.ssl;
120
+ } else if (connectionOptions.sslMode === 'disable') {
121
+ poolConfiguration.ssl = false;
122
+ } else if (connectionOptions.sslMode === 'require') {
123
+ poolConfiguration.ssl = true;
124
+ } else if (connectionOptions.sslMode === 'no-verify') {
125
+ poolConfiguration.ssl = {
126
+ rejectUnauthorized: false,
127
+ };
128
+ }
129
+
130
+ if (clientConfiguration.connectionTimeout !== 'DISABLE_TIMEOUT') {
131
+ if (clientConfiguration.connectionTimeout === 0) {
132
+ poolConfiguration.connectionTimeoutMillis = 1;
133
+ } else {
134
+ poolConfiguration.connectionTimeoutMillis =
135
+ clientConfiguration.connectionTimeout;
136
+ }
137
+ }
138
+
139
+ if (clientConfiguration.statementTimeout !== 'DISABLE_TIMEOUT') {
140
+ if (clientConfiguration.statementTimeout === 0) {
141
+ poolConfiguration.statement_timeout = 1;
142
+ } else {
143
+ poolConfiguration.statement_timeout =
144
+ clientConfiguration.statementTimeout;
145
+ }
146
+ }
147
+
148
+ if (
149
+ clientConfiguration.idleInTransactionSessionTimeout !== 'DISABLE_TIMEOUT'
150
+ ) {
151
+ if (clientConfiguration.idleInTransactionSessionTimeout === 0) {
152
+ poolConfiguration.idle_in_transaction_session_timeout = 1;
153
+ } else {
154
+ poolConfiguration.idle_in_transaction_session_timeout =
155
+ clientConfiguration.idleInTransactionSessionTimeout;
156
+ }
157
+ }
158
+
159
+ return poolConfiguration;
160
+ };
161
+
162
+ const queryTypeOverrides = async (
163
+ pgClientConfiguration: NativePostgresClientConfiguration,
164
+ driverConfiguration: DriverConfiguration,
165
+ ): Promise<TypeOverrides> => {
166
+ const client = new Client(pgClientConfiguration);
167
+
168
+ await client.connect();
169
+
170
+ const typeOverrides = await createTypeOverrides(
171
+ client,
172
+ driverConfiguration.typeParsers,
173
+ );
174
+
175
+ await client.end();
176
+
177
+ return typeOverrides;
178
+ };
179
+
180
+ const isErrorWithCode = (error: Error): error is DatabaseError => {
181
+ return 'code' in error;
182
+ };
183
+
184
+ // query is not available for connection-level errors.
185
+ // TODO evaluate if we can remove query from the error object.
186
+ // I suspect we should not be even using InputSyntaxError as one of the error types.
187
+ // @see https://github.com/gajus/slonik/issues/557
188
+ const wrapError = (error: Error, query: Query | null) => {
189
+ if (
190
+ error.message.toLowerCase().includes('connection terminated unexpectedly')
191
+ ) {
192
+ return new BackendTerminatedUnexpectedlyError(error);
193
+ }
194
+
195
+ if (error.message.toLowerCase().includes('connection terminated')) {
196
+ return new BackendTerminatedError(error);
197
+ }
198
+
199
+ if (!isErrorWithCode(error)) {
200
+ return error;
201
+ }
202
+
203
+ if (error.code === '22P02') {
204
+ return new InvalidInputError(error.message);
205
+ }
206
+
207
+ if (error.code === '25P03') {
208
+ return new IdleTransactionTimeoutError(error);
209
+ }
210
+
211
+ if (error.code === '57P01') {
212
+ return new BackendTerminatedError(error);
213
+ }
214
+
215
+ if (
216
+ error.code === '57014' &&
217
+ // The code alone is not enough to distinguish between a statement timeout and a statement cancellation.
218
+ error.message.includes('canceling statement due to user request')
219
+ ) {
220
+ return new StatementCancelledError(error);
221
+ }
222
+
223
+ if (error.code === '57014') {
224
+ return new StatementTimeoutError(error);
225
+ }
226
+
227
+ if (error.code === '23502') {
228
+ return new NotNullIntegrityConstraintViolationError(error);
229
+ }
230
+
231
+ if (error.code === '23503') {
232
+ return new ForeignKeyIntegrityConstraintViolationError(error);
233
+ }
234
+
235
+ if (error.code === '23505') {
236
+ return new UniqueIntegrityConstraintViolationError(error);
237
+ }
238
+
239
+ if (error.code === '23514') {
240
+ return new CheckIntegrityConstraintViolationError(error);
241
+ }
242
+
243
+ if (error.code === '42601') {
244
+ if (!query) {
245
+ return new UnexpectedStateError('Expected query to be provided');
246
+ }
247
+
248
+ return new InputSyntaxError(error, query);
249
+ }
250
+
251
+ return error;
252
+ };
253
+
254
+ export const createPgDriverFactory = (): DriverFactory => {
255
+ return createDriverFactory(async ({ driverConfiguration }) => {
256
+ const clientConfiguration = createClientConfiguration(driverConfiguration);
257
+
258
+ // eslint-disable-next-line require-atomic-updates
259
+ clientConfiguration.types = {
260
+ getTypeParser: await queryTypeOverrides(
261
+ clientConfiguration,
262
+ driverConfiguration,
263
+ ),
264
+ };
265
+
266
+ return {
267
+ createPoolClient: async ({ clientEventEmitter }) => {
268
+ const client = new Client(clientConfiguration);
269
+
270
+ // We will see this triggered when the connection is terminated, e.g.
271
+ // "terminates transactions that are idle beyond idleInTransactionSessionTimeout" test.
272
+ const onError = (error) => {
273
+ clientEventEmitter.emit('error', wrapError(error, null));
274
+ };
275
+
276
+ const onNotice = (notice) => {
277
+ if (notice.message) {
278
+ clientEventEmitter.emit('notice', {
279
+ message: notice.message,
280
+ });
281
+ }
282
+ };
283
+
284
+ client.on('error', onError);
285
+ client.on('notice', onNotice);
286
+
287
+ return {
288
+ connect: async () => {
289
+ await client.connect();
290
+ },
291
+ end: async () => {
292
+ await client.end();
293
+
294
+ client.removeListener('error', onError);
295
+ client.removeListener('notice', onNotice);
296
+ },
297
+ query: async (sql, values) => {
298
+ let result;
299
+
300
+ try {
301
+ result = await client.query(sql, values as unknown[]);
302
+ } catch (error) {
303
+ throw wrapError(error, {
304
+ sql,
305
+ values: values as readonly PrimitiveValueExpression[],
306
+ });
307
+ }
308
+
309
+ if (Array.isArray(result)) {
310
+ throw new InvalidInputError(
311
+ 'Must not use multiple statements in a single query.',
312
+ );
313
+ }
314
+
315
+ return {
316
+ command: result.command as DriverCommand,
317
+ fields: result.fields.map((field) => {
318
+ return {
319
+ dataTypeId: field.dataTypeID,
320
+ name: field.name,
321
+ };
322
+ }),
323
+ rowCount: result.rowCount,
324
+ rows: result.rows,
325
+ };
326
+ },
327
+ stream: (sql, values) => {
328
+ const stream = client.query(
329
+ new QueryStream(sql, values as unknown[]),
330
+ );
331
+
332
+ let fields: readonly Field[] = [];
333
+
334
+ // `rowDescription` will not fire if the query produces a syntax error.
335
+ // Also, `rowDescription` won't fire until client starts consuming the stream.
336
+ // This is why we cannot simply await for `rowDescription` event before starting to pipe the stream.
337
+ // @ts-expect-error – https://github.com/brianc/node-postgres/issues/3015
338
+ client.connection.once('rowDescription', (rowDescription) => {
339
+ fields = rowDescription.fields.map((field) => {
340
+ return {
341
+ dataTypeId: field.dataTypeID,
342
+ name: field.name,
343
+ };
344
+ });
345
+ });
346
+
347
+ const transform = new Transform({
348
+ objectMode: true,
349
+ async transform(datum, enc, callback) {
350
+ if (!fields) {
351
+ callback(new Error('Fields not available'));
352
+
353
+ return;
354
+ }
355
+
356
+ // eslint-disable-next-line @babel/no-invalid-this
357
+ this.push({
358
+ fields,
359
+ row: datum,
360
+ });
361
+
362
+ callback();
363
+ },
364
+ });
365
+
366
+ stream.on('error', (error) => {
367
+ transform.emit(
368
+ 'error',
369
+ wrapError(error, {
370
+ sql,
371
+ values: values as PrimitiveValueExpression[],
372
+ }),
373
+ );
374
+ });
375
+
376
+ return stream.pipe(transform);
377
+ },
378
+ };
379
+ },
380
+ };
381
+ });
382
+ };
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export { createPgDriverFactory } from './factories/createPgDriverFactory';