@prisma/adapter-pg 6.13.0-dev.2 → 6.13.0-dev.20

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/index.d.mts CHANGED
@@ -1,19 +1,67 @@
1
+ import type { ConnectionInfo } from '@prisma/driver-adapter-utils';
2
+ import type { IsolationLevel } from '@prisma/driver-adapter-utils';
1
3
  import pg from 'pg';
2
4
  import type { SqlDriverAdapter } from '@prisma/driver-adapter-utils';
3
5
  import type { SqlMigrationAwareDriverAdapterFactory } from '@prisma/driver-adapter-utils';
6
+ import type { SqlQuery } from '@prisma/driver-adapter-utils';
7
+ import type { SqlQueryable } from '@prisma/driver-adapter-utils';
8
+ import type { SqlResultSet } from '@prisma/driver-adapter-utils';
9
+ import type { Transaction } from '@prisma/driver-adapter-utils';
10
+
11
+ declare class PgQueryable<ClientT extends StdClient | TransactionClient> implements SqlQueryable {
12
+ protected readonly client: ClientT;
13
+ readonly provider = "postgres";
14
+ readonly adapterName: string;
15
+ constructor(client: ClientT);
16
+ /**
17
+ * Execute a query given as SQL, interpolating the given parameters.
18
+ */
19
+ queryRaw(query: SqlQuery): Promise<SqlResultSet>;
20
+ /**
21
+ * Execute a query given as SQL, interpolating the given parameters and
22
+ * returning the number of affected rows.
23
+ * Note: Queryable expects a u64, but napi.rs only supports u32.
24
+ */
25
+ executeRaw(query: SqlQuery): Promise<number>;
26
+ /**
27
+ * Run a query against the database, returning the result set.
28
+ * Should the query fail due to a connection error, the connection is
29
+ * marked as unhealthy.
30
+ */
31
+ private performIO;
32
+ protected onError(error: any): never;
33
+ }
4
34
 
5
35
  export declare class PrismaPg implements SqlMigrationAwareDriverAdapterFactory {
6
- private readonly config;
7
36
  private readonly options?;
8
37
  readonly provider = "postgres";
9
38
  readonly adapterName: string;
10
- constructor(config: pg.PoolConfig, options?: PrismaPgOptions | undefined);
11
- connect(): Promise<SqlDriverAdapter>;
12
- connectToShadowDb(): Promise<SqlDriverAdapter>;
39
+ private readonly config;
40
+ private externalPool;
41
+ constructor(poolOrConfig: pg.Pool | pg.PoolConfig, options?: PrismaPgOptions | undefined);
42
+ connect(): Promise<PrismaPgAdapter>;
43
+ connectToShadowDb(): Promise<PrismaPgAdapter>;
44
+ }
45
+
46
+ declare class PrismaPgAdapter extends PgQueryable<StdClient> implements SqlDriverAdapter {
47
+ private options?;
48
+ private readonly release?;
49
+ constructor(client: StdClient, options?: PrismaPgOptions | undefined, release?: (() => Promise<void>) | undefined);
50
+ startTransaction(isolationLevel?: IsolationLevel): Promise<Transaction>;
51
+ executeScript(script: string): Promise<void>;
52
+ getConnectionInfo(): ConnectionInfo;
53
+ dispose(): Promise<void>;
54
+ underlyingDriver(): pg.Pool;
13
55
  }
14
56
 
15
57
  declare type PrismaPgOptions = {
16
58
  schema?: string;
59
+ disposeExternalPool?: boolean;
60
+ onPoolError?: (err: Error) => void;
17
61
  };
18
62
 
63
+ declare type StdClient = pg.Pool;
64
+
65
+ declare type TransactionClient = pg.PoolClient;
66
+
19
67
  export { }
package/dist/index.d.ts CHANGED
@@ -1,19 +1,67 @@
1
+ import type { ConnectionInfo } from '@prisma/driver-adapter-utils';
2
+ import type { IsolationLevel } from '@prisma/driver-adapter-utils';
1
3
  import pg from 'pg';
2
4
  import type { SqlDriverAdapter } from '@prisma/driver-adapter-utils';
3
5
  import type { SqlMigrationAwareDriverAdapterFactory } from '@prisma/driver-adapter-utils';
6
+ import type { SqlQuery } from '@prisma/driver-adapter-utils';
7
+ import type { SqlQueryable } from '@prisma/driver-adapter-utils';
8
+ import type { SqlResultSet } from '@prisma/driver-adapter-utils';
9
+ import type { Transaction } from '@prisma/driver-adapter-utils';
10
+
11
+ declare class PgQueryable<ClientT extends StdClient | TransactionClient> implements SqlQueryable {
12
+ protected readonly client: ClientT;
13
+ readonly provider = "postgres";
14
+ readonly adapterName: string;
15
+ constructor(client: ClientT);
16
+ /**
17
+ * Execute a query given as SQL, interpolating the given parameters.
18
+ */
19
+ queryRaw(query: SqlQuery): Promise<SqlResultSet>;
20
+ /**
21
+ * Execute a query given as SQL, interpolating the given parameters and
22
+ * returning the number of affected rows.
23
+ * Note: Queryable expects a u64, but napi.rs only supports u32.
24
+ */
25
+ executeRaw(query: SqlQuery): Promise<number>;
26
+ /**
27
+ * Run a query against the database, returning the result set.
28
+ * Should the query fail due to a connection error, the connection is
29
+ * marked as unhealthy.
30
+ */
31
+ private performIO;
32
+ protected onError(error: any): never;
33
+ }
4
34
 
5
35
  export declare class PrismaPg implements SqlMigrationAwareDriverAdapterFactory {
6
- private readonly config;
7
36
  private readonly options?;
8
37
  readonly provider = "postgres";
9
38
  readonly adapterName: string;
10
- constructor(config: pg.PoolConfig, options?: PrismaPgOptions | undefined);
11
- connect(): Promise<SqlDriverAdapter>;
12
- connectToShadowDb(): Promise<SqlDriverAdapter>;
39
+ private readonly config;
40
+ private externalPool;
41
+ constructor(poolOrConfig: pg.Pool | pg.PoolConfig, options?: PrismaPgOptions | undefined);
42
+ connect(): Promise<PrismaPgAdapter>;
43
+ connectToShadowDb(): Promise<PrismaPgAdapter>;
44
+ }
45
+
46
+ declare class PrismaPgAdapter extends PgQueryable<StdClient> implements SqlDriverAdapter {
47
+ private options?;
48
+ private readonly release?;
49
+ constructor(client: StdClient, options?: PrismaPgOptions | undefined, release?: (() => Promise<void>) | undefined);
50
+ startTransaction(isolationLevel?: IsolationLevel): Promise<Transaction>;
51
+ executeScript(script: string): Promise<void>;
52
+ getConnectionInfo(): ConnectionInfo;
53
+ dispose(): Promise<void>;
54
+ underlyingDriver(): pg.Pool;
13
55
  }
14
56
 
15
57
  declare type PrismaPgOptions = {
16
58
  schema?: string;
59
+ disposeExternalPool?: boolean;
60
+ onPoolError?: (err: Error) => void;
17
61
  };
18
62
 
63
+ declare type StdClient = pg.Pool;
64
+
65
+ declare type TransactionClient = pg.PoolClient;
66
+
19
67
  export { }
package/dist/index.js CHANGED
@@ -373,7 +373,63 @@ function fixArrayBufferValues(values) {
373
373
  }
374
374
 
375
375
  // src/errors.ts
376
+ var TLS_ERRORS = /* @__PURE__ */ new Set([
377
+ "UNABLE_TO_GET_ISSUER_CERT",
378
+ "UNABLE_TO_GET_CRL",
379
+ "UNABLE_TO_DECRYPT_CERT_SIGNATURE",
380
+ "UNABLE_TO_DECRYPT_CRL_SIGNATURE",
381
+ "UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY",
382
+ "CERT_SIGNATURE_FAILURE",
383
+ "CRL_SIGNATURE_FAILURE",
384
+ "CERT_NOT_YET_VALID",
385
+ "CERT_HAS_EXPIRED",
386
+ "CRL_NOT_YET_VALID",
387
+ "CRL_HAS_EXPIRED",
388
+ "ERROR_IN_CERT_NOT_BEFORE_FIELD",
389
+ "ERROR_IN_CERT_NOT_AFTER_FIELD",
390
+ "ERROR_IN_CRL_LAST_UPDATE_FIELD",
391
+ "ERROR_IN_CRL_NEXT_UPDATE_FIELD",
392
+ "DEPTH_ZERO_SELF_SIGNED_CERT",
393
+ "SELF_SIGNED_CERT_IN_CHAIN",
394
+ "UNABLE_TO_GET_ISSUER_CERT_LOCALLY",
395
+ "UNABLE_TO_VERIFY_LEAF_SIGNATURE",
396
+ "CERT_CHAIN_TOO_LONG",
397
+ "CERT_REVOKED",
398
+ "INVALID_CA",
399
+ "INVALID_PURPOSE",
400
+ "CERT_UNTRUSTED",
401
+ "CERT_REJECTED",
402
+ "HOSTNAME_MISMATCH",
403
+ "ERR_TLS_CERT_ALTNAME_FORMAT",
404
+ "ERR_TLS_CERT_ALTNAME_INVALID"
405
+ ]);
406
+ var SOCKET_ERRORS = /* @__PURE__ */ new Set(["ENOTFOUND", "ECONNREFUSED", "ECONNRESET", "ETIMEDOUT"]);
376
407
  function convertDriverError(error) {
408
+ if (isSocketError(error)) {
409
+ switch (error.code) {
410
+ case "ENOTFOUND":
411
+ case "ECONNREFUSED":
412
+ return {
413
+ kind: "DatabaseNotReachable",
414
+ host: error.address ?? error.hostname,
415
+ port: error.port
416
+ };
417
+ case "ECONNRESET":
418
+ return {
419
+ kind: "ConnectionClosed"
420
+ };
421
+ case "ETIMEDOUT":
422
+ return {
423
+ kind: "SocketTimeout"
424
+ };
425
+ }
426
+ }
427
+ if (isTlsError(error)) {
428
+ return {
429
+ kind: "TlsConnectionError",
430
+ reason: error.message
431
+ };
432
+ }
377
433
  if (!isDbError(error)) {
378
434
  throw error;
379
435
  }
@@ -468,6 +524,20 @@ function convertDriverError(error) {
468
524
  function isDbError(error) {
469
525
  return typeof error.code === "string" && typeof error.message === "string" && typeof error.severity === "string" && (typeof error.detail === "string" || error.detail === void 0) && (typeof error.column === "string" || error.column === void 0) && (typeof error.hint === "string" || error.hint === void 0);
470
526
  }
527
+ function isSocketError(error) {
528
+ return typeof error.code === "string" && typeof error.syscall === "string" && typeof error.errno === "number" && SOCKET_ERRORS.has(error.code);
529
+ }
530
+ function isTlsError(error) {
531
+ if (typeof error.code === "string") {
532
+ return TLS_ERRORS.has(error.code);
533
+ }
534
+ switch (error.message) {
535
+ case "The server does not support SSL connections":
536
+ case "There was an error establishing an SSL connection":
537
+ return true;
538
+ }
539
+ return false;
540
+ }
471
541
 
472
542
  // src/pg.ts
473
543
  var types2 = import_pg2.default.types;
@@ -620,27 +690,55 @@ var PrismaPgAdapter = class extends PgQueryable {
620
690
  };
621
691
  }
622
692
  async dispose() {
623
- await this.release?.();
624
- return await this.client.end();
693
+ return this.release?.();
694
+ }
695
+ underlyingDriver() {
696
+ return this.client;
625
697
  }
626
698
  };
627
699
  var PrismaPgAdapterFactory = class {
628
- constructor(config, options) {
629
- this.config = config;
700
+ constructor(poolOrConfig, options) {
630
701
  this.options = options;
702
+ if (poolOrConfig instanceof import_pg2.default.Pool) {
703
+ this.externalPool = poolOrConfig;
704
+ this.config = poolOrConfig.options;
705
+ } else {
706
+ this.externalPool = null;
707
+ this.config = poolOrConfig;
708
+ }
631
709
  }
632
710
  provider = "postgres";
633
711
  adapterName = name;
712
+ config;
713
+ externalPool;
634
714
  async connect() {
635
- return new PrismaPgAdapter(new import_pg2.default.Pool(this.config), this.options, async () => {
715
+ const client = this.externalPool ?? new import_pg2.default.Pool(this.config);
716
+ const onIdleClientError = (err) => {
717
+ debug(`Error from idle pool client: ${err.message} %O`, err);
718
+ this.options?.onPoolError?.(err);
719
+ };
720
+ client.on("error", onIdleClientError);
721
+ return new PrismaPgAdapter(client, this.options, async () => {
722
+ if (this.externalPool) {
723
+ if (this.options?.disposeExternalPool) {
724
+ await this.externalPool.end();
725
+ this.externalPool = null;
726
+ } else {
727
+ this.externalPool.removeListener("error", onIdleClientError);
728
+ }
729
+ } else {
730
+ await client.end();
731
+ }
636
732
  });
637
733
  }
638
734
  async connectToShadowDb() {
639
735
  const conn = await this.connect();
640
736
  const database = `prisma_migrate_shadow_db_${globalThis.crypto.randomUUID()}`;
641
737
  await conn.executeScript(`CREATE DATABASE "${database}"`);
642
- return new PrismaPgAdapter(new import_pg2.default.Pool({ ...this.config, database }), void 0, async () => {
738
+ const client = new import_pg2.default.Pool({ ...this.config, database });
739
+ return new PrismaPgAdapter(client, void 0, async () => {
643
740
  await conn.executeScript(`DROP DATABASE "${database}"`);
741
+ await client.end();
644
742
  });
645
743
  }
646
744
  };
package/dist/index.mjs CHANGED
@@ -337,7 +337,63 @@ function fixArrayBufferValues(values) {
337
337
  }
338
338
 
339
339
  // src/errors.ts
340
+ var TLS_ERRORS = /* @__PURE__ */ new Set([
341
+ "UNABLE_TO_GET_ISSUER_CERT",
342
+ "UNABLE_TO_GET_CRL",
343
+ "UNABLE_TO_DECRYPT_CERT_SIGNATURE",
344
+ "UNABLE_TO_DECRYPT_CRL_SIGNATURE",
345
+ "UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY",
346
+ "CERT_SIGNATURE_FAILURE",
347
+ "CRL_SIGNATURE_FAILURE",
348
+ "CERT_NOT_YET_VALID",
349
+ "CERT_HAS_EXPIRED",
350
+ "CRL_NOT_YET_VALID",
351
+ "CRL_HAS_EXPIRED",
352
+ "ERROR_IN_CERT_NOT_BEFORE_FIELD",
353
+ "ERROR_IN_CERT_NOT_AFTER_FIELD",
354
+ "ERROR_IN_CRL_LAST_UPDATE_FIELD",
355
+ "ERROR_IN_CRL_NEXT_UPDATE_FIELD",
356
+ "DEPTH_ZERO_SELF_SIGNED_CERT",
357
+ "SELF_SIGNED_CERT_IN_CHAIN",
358
+ "UNABLE_TO_GET_ISSUER_CERT_LOCALLY",
359
+ "UNABLE_TO_VERIFY_LEAF_SIGNATURE",
360
+ "CERT_CHAIN_TOO_LONG",
361
+ "CERT_REVOKED",
362
+ "INVALID_CA",
363
+ "INVALID_PURPOSE",
364
+ "CERT_UNTRUSTED",
365
+ "CERT_REJECTED",
366
+ "HOSTNAME_MISMATCH",
367
+ "ERR_TLS_CERT_ALTNAME_FORMAT",
368
+ "ERR_TLS_CERT_ALTNAME_INVALID"
369
+ ]);
370
+ var SOCKET_ERRORS = /* @__PURE__ */ new Set(["ENOTFOUND", "ECONNREFUSED", "ECONNRESET", "ETIMEDOUT"]);
340
371
  function convertDriverError(error) {
372
+ if (isSocketError(error)) {
373
+ switch (error.code) {
374
+ case "ENOTFOUND":
375
+ case "ECONNREFUSED":
376
+ return {
377
+ kind: "DatabaseNotReachable",
378
+ host: error.address ?? error.hostname,
379
+ port: error.port
380
+ };
381
+ case "ECONNRESET":
382
+ return {
383
+ kind: "ConnectionClosed"
384
+ };
385
+ case "ETIMEDOUT":
386
+ return {
387
+ kind: "SocketTimeout"
388
+ };
389
+ }
390
+ }
391
+ if (isTlsError(error)) {
392
+ return {
393
+ kind: "TlsConnectionError",
394
+ reason: error.message
395
+ };
396
+ }
341
397
  if (!isDbError(error)) {
342
398
  throw error;
343
399
  }
@@ -432,6 +488,20 @@ function convertDriverError(error) {
432
488
  function isDbError(error) {
433
489
  return typeof error.code === "string" && typeof error.message === "string" && typeof error.severity === "string" && (typeof error.detail === "string" || error.detail === void 0) && (typeof error.column === "string" || error.column === void 0) && (typeof error.hint === "string" || error.hint === void 0);
434
490
  }
491
+ function isSocketError(error) {
492
+ return typeof error.code === "string" && typeof error.syscall === "string" && typeof error.errno === "number" && SOCKET_ERRORS.has(error.code);
493
+ }
494
+ function isTlsError(error) {
495
+ if (typeof error.code === "string") {
496
+ return TLS_ERRORS.has(error.code);
497
+ }
498
+ switch (error.message) {
499
+ case "The server does not support SSL connections":
500
+ case "There was an error establishing an SSL connection":
501
+ return true;
502
+ }
503
+ return false;
504
+ }
435
505
 
436
506
  // src/pg.ts
437
507
  var types2 = pg2.types;
@@ -584,27 +654,55 @@ var PrismaPgAdapter = class extends PgQueryable {
584
654
  };
585
655
  }
586
656
  async dispose() {
587
- await this.release?.();
588
- return await this.client.end();
657
+ return this.release?.();
658
+ }
659
+ underlyingDriver() {
660
+ return this.client;
589
661
  }
590
662
  };
591
663
  var PrismaPgAdapterFactory = class {
592
- constructor(config, options) {
593
- this.config = config;
664
+ constructor(poolOrConfig, options) {
594
665
  this.options = options;
666
+ if (poolOrConfig instanceof pg2.Pool) {
667
+ this.externalPool = poolOrConfig;
668
+ this.config = poolOrConfig.options;
669
+ } else {
670
+ this.externalPool = null;
671
+ this.config = poolOrConfig;
672
+ }
595
673
  }
596
674
  provider = "postgres";
597
675
  adapterName = name;
676
+ config;
677
+ externalPool;
598
678
  async connect() {
599
- return new PrismaPgAdapter(new pg2.Pool(this.config), this.options, async () => {
679
+ const client = this.externalPool ?? new pg2.Pool(this.config);
680
+ const onIdleClientError = (err) => {
681
+ debug(`Error from idle pool client: ${err.message} %O`, err);
682
+ this.options?.onPoolError?.(err);
683
+ };
684
+ client.on("error", onIdleClientError);
685
+ return new PrismaPgAdapter(client, this.options, async () => {
686
+ if (this.externalPool) {
687
+ if (this.options?.disposeExternalPool) {
688
+ await this.externalPool.end();
689
+ this.externalPool = null;
690
+ } else {
691
+ this.externalPool.removeListener("error", onIdleClientError);
692
+ }
693
+ } else {
694
+ await client.end();
695
+ }
600
696
  });
601
697
  }
602
698
  async connectToShadowDb() {
603
699
  const conn = await this.connect();
604
700
  const database = `prisma_migrate_shadow_db_${globalThis.crypto.randomUUID()}`;
605
701
  await conn.executeScript(`CREATE DATABASE "${database}"`);
606
- return new PrismaPgAdapter(new pg2.Pool({ ...this.config, database }), void 0, async () => {
702
+ const client = new pg2.Pool({ ...this.config, database });
703
+ return new PrismaPgAdapter(client, void 0, async () => {
607
704
  await conn.executeScript(`DROP DATABASE "${database}"`);
705
+ await client.end();
608
706
  });
609
707
  }
610
708
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prisma/adapter-pg",
3
- "version": "6.13.0-dev.2",
3
+ "version": "6.13.0-dev.20",
4
4
  "description": "Prisma's driver adapter for \"pg\"",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -33,7 +33,7 @@
33
33
  "dependencies": {
34
34
  "postgres-array": "3.0.4",
35
35
  "pg": "^8.11.3",
36
- "@prisma/driver-adapter-utils": "6.13.0-dev.2"
36
+ "@prisma/driver-adapter-utils": "6.13.0-dev.20"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@swc/core": "1.11.5",