@xfcfam/xf-sql-postgres 0.1.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.
Files changed (31) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +114 -0
  3. package/dist/index.d.ts +16 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +17 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/src/api/A.d.ts +17 -0
  8. package/dist/src/api/A.d.ts.map +1 -0
  9. package/dist/src/api/A.js +17 -0
  10. package/dist/src/api/A.js.map +1 -0
  11. package/dist/src/business/B.d.ts +17 -0
  12. package/dist/src/business/B.d.ts.map +1 -0
  13. package/dist/src/business/B.js +17 -0
  14. package/dist/src/business/B.js.map +1 -0
  15. package/dist/src/repository/R.d.ts +17 -0
  16. package/dist/src/repository/R.d.ts.map +1 -0
  17. package/dist/src/repository/R.js +17 -0
  18. package/dist/src/repository/R.js.map +1 -0
  19. package/dist/src/repository/base/PostgresDatabaseRepository.d.ts +91 -0
  20. package/dist/src/repository/base/PostgresDatabaseRepository.d.ts.map +1 -0
  21. package/dist/src/repository/base/PostgresDatabaseRepository.js +88 -0
  22. package/dist/src/repository/base/PostgresDatabaseRepository.js.map +1 -0
  23. package/dist/src/repository/general/PostgresDatabaseRepository.d.ts +91 -0
  24. package/dist/src/repository/general/PostgresDatabaseRepository.d.ts.map +1 -0
  25. package/dist/src/repository/general/PostgresDatabaseRepository.js +88 -0
  26. package/dist/src/repository/general/PostgresDatabaseRepository.js.map +1 -0
  27. package/dist/src/repository/utils/PostgresErrorUtils.d.ts +48 -0
  28. package/dist/src/repository/utils/PostgresErrorUtils.d.ts.map +1 -0
  29. package/dist/src/repository/utils/PostgresErrorUtils.js +102 -0
  30. package/dist/src/repository/utils/PostgresErrorUtils.js.map +1 -0
  31. package/package.json +57 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Israel Sanjurjo and the XF contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,114 @@
1
+ # `@xfcfam/xf-sql-postgres`
2
+
3
+ PostgreSQL dialect adapter for [`@xfcfam/xf-sql`](https://www.npmjs.com/package/@xfcfam/xf-sql).
4
+ Encapsulates `kysely`'s `PostgresDialect` over the [`pg`](https://node-postgres.com)
5
+ driver and ships the SQLSTATE → typed-Exception translation so the
6
+ Business Layer never sees `pg` errors.
7
+
8
+ Peer dependencies: [`@xfcfam/xf`](https://www.npmjs.com/package/@xfcfam/xf),
9
+ [`@xfcfam/xf-sql`](https://www.npmjs.com/package/@xfcfam/xf-sql),
10
+ [`kysely`](https://kysely.dev).
11
+ Runtime dependency: `pg`.
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ pnpm add @xfcfam/xf @xfcfam/xf-sql @xfcfam/xf-sql-postgres kysely pg
17
+ ```
18
+
19
+ ## What ships here
20
+
21
+ | Export | Role |
22
+ |---|---|
23
+ | `PostgresDatabaseRepository<Schema>` | Ready-to-use Access Layer Generalization. Extends `TransactionalDatabaseRepository` from `@xfcfam/xf-sql`. Wires `PostgresDialect` + `pg.Pool`. Overrides `translateError` with the SQLSTATE mapping. |
24
+ | `PostgresOptions` | Constructor options: `connectionString`, optional `pool: pg.PoolConfig`. |
25
+ | `PostgresErrorUtils` | Static utility class. `translate(err)` maps any `pg`/Kysely error to the corresponding `@xfcfam/xf-sql` Exception. Constants for the SQLSTATEs it recognises (`SQLSTATE_UNIQUE_VIOLATION`, …). |
26
+
27
+ ## Quick usage
28
+
29
+ ```typescript
30
+ import { PostgresDatabaseRepository } from '@xfcfam/xf-sql-postgres'
31
+ import { UniqueViolationException, ConnectionException } from '@xfcfam/xf-sql'
32
+
33
+ interface Schema {
34
+ users: {
35
+ id: number
36
+ name: string
37
+ email: string
38
+ created_at: Date
39
+ }
40
+ }
41
+
42
+ export class UsersDb extends PostgresDatabaseRepository<Schema> {
43
+ constructor() {
44
+ super({
45
+ connectionString: process.env.DATABASE_URL!,
46
+ pool: { max: 10, idleTimeoutMillis: 30_000 },
47
+ })
48
+ }
49
+ async init() { await super.init() }
50
+ async terminate() { await super.terminate() }
51
+
52
+ getUser(id: number) {
53
+ return this.exec(() =>
54
+ this.db.selectFrom('users').where('id', '=', id).selectAll().executeTakeFirstOrThrow()
55
+ )
56
+ }
57
+
58
+ async createUser(input: { name: string; email: string }) {
59
+ try {
60
+ return await this.exec(() =>
61
+ this.db
62
+ .insertInto('users')
63
+ .values({ ...input, created_at: new Date() })
64
+ .returningAll()
65
+ .executeTakeFirstOrThrow()
66
+ )
67
+ } catch (err) {
68
+ if (err instanceof UniqueViolationException && err.column === 'email') {
69
+ throw new DomainError('Email already registered')
70
+ }
71
+ throw err
72
+ }
73
+ }
74
+
75
+ async transferOrder(orderId: number, newOwner: number) {
76
+ // transaction() commits on success, rolls back on throw.
77
+ return this.transaction(async (trx) => {
78
+ await trx.updateTable('orders').set({ owner_id: newOwner }).where('id', '=', orderId).execute()
79
+ await trx.insertInto('order_audit').values({ order_id: orderId, action: 'transfer' }).execute()
80
+ })
81
+ }
82
+ }
83
+ ```
84
+
85
+ ## SQLSTATE → Exception mapping
86
+
87
+ The default `translateError` covers the most common PostgreSQL error
88
+ codes. Anything not in this table is returned unchanged (so
89
+ implementer-specific exceptions still propagate cleanly).
90
+
91
+ | SQLSTATE | Postgres condition | Translates to |
92
+ |---|---|---|
93
+ | `23505` | unique_violation | `UniqueViolationException` |
94
+ | `23503` | foreign_key_violation | `ForeignKeyViolationException` |
95
+ | `23514` | check_violation | `CheckViolationException` |
96
+ | `23502` | not_null_violation | `NotNullViolationException` |
97
+ | `40P01` | deadlock_detected | `DeadlockException` |
98
+ | `ECONNREFUSED`, `ENOTFOUND`, `ETIMEDOUT`, `ECONNRESET`, `EHOSTUNREACH`, `EAI_AGAIN` | transport-level (not a SQLSTATE) | `ConnectionException` |
99
+ | anything else | — | passed through untouched |
100
+
101
+ When the driver attaches `table`, `column`, `constraint` to the
102
+ error, these are forwarded to the Exception so the Business Layer can
103
+ branch on them without parsing strings.
104
+
105
+ ## Documentation
106
+
107
+ - Specification — [xfcfam.org](https://xfcfam.org)
108
+ - Kysely docs — [kysely.dev](https://kysely.dev)
109
+ - Postgres SQLSTATE codes — [postgresql.org docs](https://www.postgresql.org/docs/current/errcodes-appendix.html)
110
+ - Source — [github.com/xfcfam/lib-npm](https://github.com/xfcfam/lib-npm)
111
+
112
+ ## License
113
+
114
+ MIT.
@@ -0,0 +1,16 @@
1
+ /**
2
+ * `@xfcfam/xf-sql-postgres` — PostgreSQL dialect adapter for
3
+ * `@xfcfam/xf-sql`.
4
+ *
5
+ * Encapsulates `kysely`'s `PostgresDialect` over the `pg` driver
6
+ * behind a single XF-canonical class (`PostgresDatabaseRepository`)
7
+ * and ships the SQLSTATE → `@xfcfam/xf-sql` Exception translation
8
+ * (`PostgresErrorUtils`).
9
+ *
10
+ * Peer dependencies: `@xfcfam/xf`, `@xfcfam/xf-sql`, `kysely`.
11
+ * Runtime dependency: `pg`.
12
+ */
13
+ export { PostgresDatabaseRepository } from './src/repository/general/PostgresDatabaseRepository.js';
14
+ export type { PostgresOptions } from './src/repository/general/PostgresDatabaseRepository.js';
15
+ export { PostgresErrorUtils } from './src/repository/utils/PostgresErrorUtils.js';
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,0BAA0B,EAAE,MAAM,wDAAwD,CAAA;AACnG,YAAY,EAAE,eAAe,EAAE,MAAM,wDAAwD,CAAA;AAG7F,OAAO,EAAE,kBAAkB,EAAE,MAAM,8CAA8C,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * `@xfcfam/xf-sql-postgres` — PostgreSQL dialect adapter for
3
+ * `@xfcfam/xf-sql`.
4
+ *
5
+ * Encapsulates `kysely`'s `PostgresDialect` over the `pg` driver
6
+ * behind a single XF-canonical class (`PostgresDatabaseRepository`)
7
+ * and ships the SQLSTATE → `@xfcfam/xf-sql` Exception translation
8
+ * (`PostgresErrorUtils`).
9
+ *
10
+ * Peer dependencies: `@xfcfam/xf`, `@xfcfam/xf-sql`, `kysely`.
11
+ * Runtime dependency: `pg`.
12
+ */
13
+ // ── Access — base ─────────────────────────────────────────
14
+ export { PostgresDatabaseRepository } from './src/repository/general/PostgresDatabaseRepository.js';
15
+ // ── Access — utils ────────────────────────────────────────
16
+ export { PostgresErrorUtils } from './src/repository/utils/PostgresErrorUtils.js';
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,6DAA6D;AAC7D,OAAO,EAAE,0BAA0B,EAAE,MAAM,wDAAwD,CAAA;AAGnG,6DAA6D;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,8CAA8C,CAAA"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Interaction Layer Injection — placeholder.
3
+ *
4
+ * `A` is the canonical injection of the Interaction Layer. `@xfcfam/xf-sql-postgres`
5
+ * is a library that contributes Generalizations and Transfer objects;
6
+ * it does not own any Logical of this layer, so its own `A` declares
7
+ * no static slots. The class is kept structurally complete (private
8
+ * constructor + empty `init` / `terminate`) so the artefact passes XF
9
+ * validation. It is NOT exported from the package — consumers import
10
+ * `A` from their own artefact.
11
+ */
12
+ export declare class A {
13
+ private constructor();
14
+ static init(): Promise<void>;
15
+ static terminate(): Promise<void>;
16
+ }
17
+ //# sourceMappingURL=A.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"A.d.ts","sourceRoot":"","sources":["../../../src/api/A.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,qBAAa,CAAC;IACZ,OAAO;WACM,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;WACrB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;CACxC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Interaction Layer Injection — placeholder.
3
+ *
4
+ * `A` is the canonical injection of the Interaction Layer. `@xfcfam/xf-sql-postgres`
5
+ * is a library that contributes Generalizations and Transfer objects;
6
+ * it does not own any Logical of this layer, so its own `A` declares
7
+ * no static slots. The class is kept structurally complete (private
8
+ * constructor + empty `init` / `terminate`) so the artefact passes XF
9
+ * validation. It is NOT exported from the package — consumers import
10
+ * `A` from their own artefact.
11
+ */
12
+ export class A {
13
+ constructor() { }
14
+ static async init() { }
15
+ static async terminate() { }
16
+ }
17
+ //# sourceMappingURL=A.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"A.js","sourceRoot":"","sources":["../../../src/api/A.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,OAAO,CAAC;IACZ,gBAAuB,CAAC;IACxB,MAAM,CAAC,KAAK,CAAC,IAAI,KAAmB,CAAC;IACrC,MAAM,CAAC,KAAK,CAAC,SAAS,KAAmB,CAAC;CAC3C"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Business Layer Injection — placeholder.
3
+ *
4
+ * `B` is the canonical injection of the Business Layer. `@xfcfam/xf-sql-postgres`
5
+ * is a library that contributes Generalizations and Transfer objects;
6
+ * it does not own any Logical of this layer, so its own `B` declares
7
+ * no static slots. The class is kept structurally complete (private
8
+ * constructor + empty `init` / `terminate`) so the artefact passes XF
9
+ * validation. It is NOT exported from the package — consumers import
10
+ * `B` from their own artefact.
11
+ */
12
+ export declare class B {
13
+ private constructor();
14
+ static init(): Promise<void>;
15
+ static terminate(): Promise<void>;
16
+ }
17
+ //# sourceMappingURL=B.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"B.d.ts","sourceRoot":"","sources":["../../../src/business/B.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,qBAAa,CAAC;IACZ,OAAO;WACM,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;WACrB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;CACxC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Business Layer Injection — placeholder.
3
+ *
4
+ * `B` is the canonical injection of the Business Layer. `@xfcfam/xf-sql-postgres`
5
+ * is a library that contributes Generalizations and Transfer objects;
6
+ * it does not own any Logical of this layer, so its own `B` declares
7
+ * no static slots. The class is kept structurally complete (private
8
+ * constructor + empty `init` / `terminate`) so the artefact passes XF
9
+ * validation. It is NOT exported from the package — consumers import
10
+ * `B` from their own artefact.
11
+ */
12
+ export class B {
13
+ constructor() { }
14
+ static async init() { }
15
+ static async terminate() { }
16
+ }
17
+ //# sourceMappingURL=B.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"B.js","sourceRoot":"","sources":["../../../src/business/B.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,OAAO,CAAC;IACZ,gBAAuB,CAAC;IACxB,MAAM,CAAC,KAAK,CAAC,IAAI,KAAmB,CAAC;IACrC,MAAM,CAAC,KAAK,CAAC,SAAS,KAAmB,CAAC;CAC3C"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Access Layer Injection — placeholder.
3
+ *
4
+ * `R` is the canonical injection of the Access Layer. `@xfcfam/xf-sql-postgres`
5
+ * is a library that contributes Generalizations and Transfer objects;
6
+ * it does not own any Logical of this layer, so its own `R` declares
7
+ * no static slots. The class is kept structurally complete (private
8
+ * constructor + empty `init` / `terminate`) so the artefact passes XF
9
+ * validation. It is NOT exported from the package — consumers import
10
+ * `R` from their own artefact.
11
+ */
12
+ export declare class R {
13
+ private constructor();
14
+ static init(): Promise<void>;
15
+ static terminate(): Promise<void>;
16
+ }
17
+ //# sourceMappingURL=R.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"R.d.ts","sourceRoot":"","sources":["../../../src/repository/R.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,qBAAa,CAAC;IACZ,OAAO;WACM,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;WACrB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;CACxC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Access Layer Injection — placeholder.
3
+ *
4
+ * `R` is the canonical injection of the Access Layer. `@xfcfam/xf-sql-postgres`
5
+ * is a library that contributes Generalizations and Transfer objects;
6
+ * it does not own any Logical of this layer, so its own `R` declares
7
+ * no static slots. The class is kept structurally complete (private
8
+ * constructor + empty `init` / `terminate`) so the artefact passes XF
9
+ * validation. It is NOT exported from the package — consumers import
10
+ * `R` from their own artefact.
11
+ */
12
+ export class R {
13
+ constructor() { }
14
+ static async init() { }
15
+ static async terminate() { }
16
+ }
17
+ //# sourceMappingURL=R.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"R.js","sourceRoot":"","sources":["../../../src/repository/R.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,OAAO,CAAC;IACZ,gBAAuB,CAAC;IACxB,MAAM,CAAC,KAAK,CAAC,IAAI,KAAmB,CAAC;IACrC,MAAM,CAAC,KAAK,CAAC,SAAS,KAAmB,CAAC;CAC3C"}
@@ -0,0 +1,91 @@
1
+ import { TransactionalDatabaseRepository } from '@xfarch/xf-sql';
2
+ import { type PoolConfig } from 'pg';
3
+ /**
4
+ * Configuration accepted by {@link PostgresDatabaseRepository}'s
5
+ * constructor.
6
+ *
7
+ * Either provide a `connectionString` (the simplest path), a full
8
+ * `pg.PoolConfig`, or both — they are merged with the connection
9
+ * string taking precedence for connection coordinates.
10
+ */
11
+ export interface PostgresOptions {
12
+ /** Postgres connection string (`postgres://user:pass@host:port/db?…`). */
13
+ connectionString?: string;
14
+ /** Extra `pg.PoolConfig` fields: `max`, `idleTimeoutMillis`, `ssl`, … */
15
+ pool?: PoolConfig;
16
+ }
17
+ /**
18
+ * Ready-to-use Generalization for the Access Layer when the backing
19
+ * store is **PostgreSQL**.
20
+ *
21
+ * Wraps `kysely`'s `PostgresDialect` over the `pg` driver behind a
22
+ * single XF-canonical class. The implementer's concrete Logical
23
+ * extends this and exposes domain-meaningful methods that compose
24
+ * queries against `this.db`. Transactions via `this.transaction(...)`,
25
+ * one-shot error translation via `this.exec(...)`.
26
+ *
27
+ * The default `translateError` maps Postgres SQLSTATE codes to the
28
+ * typed Exceptions exported from `@xfarch/xf-sql`
29
+ * (`UniqueViolationException`, `ForeignKeyViolationException`,
30
+ * `CheckViolationException`, `NotNullViolationException`,
31
+ * `DeadlockException`) and transport-level errors (`ECONNREFUSED`,
32
+ * `ETIMEDOUT`, …) to `ConnectionException`. The implementer's
33
+ * Business Layer never sees `pg` types.
34
+ *
35
+ * @typeParam Schema Implementer-defined TypeScript interface mapping
36
+ * table names to their column shapes.
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * import { PostgresDatabaseRepository } from '@xfarch/xf-sql-postgres'
41
+ * import { UniqueViolationException } from '@xfarch/xf-sql'
42
+ *
43
+ * interface Schema {
44
+ * users: { id: number; name: string; email: string; created_at: Date }
45
+ * }
46
+ *
47
+ * export class UsersDb extends PostgresDatabaseRepository<Schema> {
48
+ * constructor() {
49
+ * super({
50
+ * connectionString: process.env.DATABASE_URL!,
51
+ * pool: { max: 10, idleTimeoutMillis: 30_000 },
52
+ * })
53
+ * }
54
+ * async init() { await super.init() } // ← required
55
+ * async terminate() { await super.terminate() } // ← required
56
+ *
57
+ * getUser(id: number) {
58
+ * return this.exec(() =>
59
+ * this.db.selectFrom('users').where('id', '=', id).selectAll().executeTakeFirstOrThrow()
60
+ * )
61
+ * }
62
+ *
63
+ * async createUser(input: { name: string; email: string }) {
64
+ * try {
65
+ * return await this.exec(() =>
66
+ * this.db.insertInto('users').values({ ...input, created_at: new Date() }).returningAll().executeTakeFirstOrThrow()
67
+ * )
68
+ * } catch (err) {
69
+ * if (err instanceof UniqueViolationException && err.column === 'email') {
70
+ * throw new DomainError('Email already registered')
71
+ * }
72
+ * throw err
73
+ * }
74
+ * }
75
+ * }
76
+ * ```
77
+ */
78
+ export declare abstract class PostgresDatabaseRepository<Schema = unknown> extends TransactionalDatabaseRepository<Schema> {
79
+ constructor(options: PostgresOptions);
80
+ /**
81
+ * Translate `pg` / Kysely driver errors into the typed Exceptions
82
+ * exported from `@xfarch/xf-sql`. Delegates to
83
+ * {@link PostgresErrorUtils.translate}.
84
+ *
85
+ * Subclasses may override to layer additional mappings on top, but
86
+ * should `return super.translateError(err)` for unrecognised
87
+ * errors so the base policy still applies.
88
+ */
89
+ protected translateError(err: unknown): unknown;
90
+ }
91
+ //# sourceMappingURL=PostgresDatabaseRepository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostgresDatabaseRepository.d.ts","sourceRoot":"","sources":["../../../../src/repository/base/PostgresDatabaseRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,+BAA+B,EAAE,MAAM,gBAAgB,CAAA;AAEhE,OAAO,EAAQ,KAAK,UAAU,EAAE,MAAM,IAAI,CAAA;AAG1C;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,yEAAyE;IACzE,IAAI,CAAC,EAAE,UAAU,CAAA;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AACH,8BAAsB,0BAA0B,CAAC,MAAM,GAAG,OAAO,CAC/D,SAAQ,+BAA+B,CAAC,MAAM,CAAC;gBAEnC,OAAO,EAAE,eAAe;IASpC;;;;;;;;OAQG;cACgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO;CAGzD"}
@@ -0,0 +1,88 @@
1
+ import { TransactionalDatabaseRepository } from '@xfarch/xf-sql';
2
+ import { PostgresDialect } from 'kysely';
3
+ import { Pool } from 'pg';
4
+ import { PostgresErrorUtils } from '../utils/PostgresErrorUtils.js';
5
+ /**
6
+ * Ready-to-use Generalization for the Access Layer when the backing
7
+ * store is **PostgreSQL**.
8
+ *
9
+ * Wraps `kysely`'s `PostgresDialect` over the `pg` driver behind a
10
+ * single XF-canonical class. The implementer's concrete Logical
11
+ * extends this and exposes domain-meaningful methods that compose
12
+ * queries against `this.db`. Transactions via `this.transaction(...)`,
13
+ * one-shot error translation via `this.exec(...)`.
14
+ *
15
+ * The default `translateError` maps Postgres SQLSTATE codes to the
16
+ * typed Exceptions exported from `@xfarch/xf-sql`
17
+ * (`UniqueViolationException`, `ForeignKeyViolationException`,
18
+ * `CheckViolationException`, `NotNullViolationException`,
19
+ * `DeadlockException`) and transport-level errors (`ECONNREFUSED`,
20
+ * `ETIMEDOUT`, …) to `ConnectionException`. The implementer's
21
+ * Business Layer never sees `pg` types.
22
+ *
23
+ * @typeParam Schema Implementer-defined TypeScript interface mapping
24
+ * table names to their column shapes.
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * import { PostgresDatabaseRepository } from '@xfarch/xf-sql-postgres'
29
+ * import { UniqueViolationException } from '@xfarch/xf-sql'
30
+ *
31
+ * interface Schema {
32
+ * users: { id: number; name: string; email: string; created_at: Date }
33
+ * }
34
+ *
35
+ * export class UsersDb extends PostgresDatabaseRepository<Schema> {
36
+ * constructor() {
37
+ * super({
38
+ * connectionString: process.env.DATABASE_URL!,
39
+ * pool: { max: 10, idleTimeoutMillis: 30_000 },
40
+ * })
41
+ * }
42
+ * async init() { await super.init() } // ← required
43
+ * async terminate() { await super.terminate() } // ← required
44
+ *
45
+ * getUser(id: number) {
46
+ * return this.exec(() =>
47
+ * this.db.selectFrom('users').where('id', '=', id).selectAll().executeTakeFirstOrThrow()
48
+ * )
49
+ * }
50
+ *
51
+ * async createUser(input: { name: string; email: string }) {
52
+ * try {
53
+ * return await this.exec(() =>
54
+ * this.db.insertInto('users').values({ ...input, created_at: new Date() }).returningAll().executeTakeFirstOrThrow()
55
+ * )
56
+ * } catch (err) {
57
+ * if (err instanceof UniqueViolationException && err.column === 'email') {
58
+ * throw new DomainError('Email already registered')
59
+ * }
60
+ * throw err
61
+ * }
62
+ * }
63
+ * }
64
+ * ```
65
+ */
66
+ export class PostgresDatabaseRepository extends TransactionalDatabaseRepository {
67
+ constructor(options) {
68
+ const poolConfig = { ...options.pool };
69
+ if (options.connectionString !== undefined) {
70
+ poolConfig.connectionString = options.connectionString;
71
+ }
72
+ const pool = new Pool(poolConfig);
73
+ super({ dialect: new PostgresDialect({ pool }) });
74
+ }
75
+ /**
76
+ * Translate `pg` / Kysely driver errors into the typed Exceptions
77
+ * exported from `@xfarch/xf-sql`. Delegates to
78
+ * {@link PostgresErrorUtils.translate}.
79
+ *
80
+ * Subclasses may override to layer additional mappings on top, but
81
+ * should `return super.translateError(err)` for unrecognised
82
+ * errors so the base policy still applies.
83
+ */
84
+ translateError(err) {
85
+ return PostgresErrorUtils.translate(err);
86
+ }
87
+ }
88
+ //# sourceMappingURL=PostgresDatabaseRepository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostgresDatabaseRepository.js","sourceRoot":"","sources":["../../../../src/repository/base/PostgresDatabaseRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,+BAA+B,EAAE,MAAM,gBAAgB,CAAA;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAA;AACxC,OAAO,EAAE,IAAI,EAAmB,MAAM,IAAI,CAAA;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AAiBnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AACH,MAAM,OAAgB,0BACpB,SAAQ,+BAAuC;IAE/C,YAAY,OAAwB;QAClC,MAAM,UAAU,GAAe,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,CAAA;QAClD,IAAI,OAAO,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;YAC3C,UAAU,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAA;QACxD,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,CAAA;QACjC,KAAK,CAAC,EAAE,OAAO,EAAE,IAAI,eAAe,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAA;IACnD,CAAC;IAED;;;;;;;;OAQG;IACgB,cAAc,CAAC,GAAY;QAC5C,OAAO,kBAAkB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;IAC1C,CAAC;CACF"}
@@ -0,0 +1,91 @@
1
+ import { TransactionalDatabaseRepository } from '@xfcfam/xf-sql';
2
+ import { type PoolConfig } from 'pg';
3
+ /**
4
+ * Configuration accepted by {@link PostgresDatabaseRepository}'s
5
+ * constructor.
6
+ *
7
+ * Either provide a `connectionString` (the simplest path), a full
8
+ * `pg.PoolConfig`, or both — they are merged with the connection
9
+ * string taking precedence for connection coordinates.
10
+ */
11
+ export interface PostgresOptions {
12
+ /** Postgres connection string (`postgres://user:pass@host:port/db?…`). */
13
+ connectionString?: string;
14
+ /** Extra `pg.PoolConfig` fields: `max`, `idleTimeoutMillis`, `ssl`, … */
15
+ pool?: PoolConfig;
16
+ }
17
+ /**
18
+ * Ready-to-use Generalization for the Access Layer when the backing
19
+ * store is **PostgreSQL**.
20
+ *
21
+ * Wraps `kysely`'s `PostgresDialect` over the `pg` driver behind a
22
+ * single XF-canonical class. The implementer's concrete Logical
23
+ * extends this and exposes domain-meaningful methods that compose
24
+ * queries against `this.db`. Transactions via `this.transaction(...)`,
25
+ * one-shot error translation via `this.exec(...)`.
26
+ *
27
+ * The default `translateError` maps Postgres SQLSTATE codes to the
28
+ * typed Exceptions exported from `@xfcfam/xf-sql`
29
+ * (`UniqueViolationException`, `ForeignKeyViolationException`,
30
+ * `CheckViolationException`, `NotNullViolationException`,
31
+ * `DeadlockException`) and transport-level errors (`ECONNREFUSED`,
32
+ * `ETIMEDOUT`, …) to `ConnectionException`. The implementer's
33
+ * Business Layer never sees `pg` types.
34
+ *
35
+ * @typeParam Schema Implementer-defined TypeScript interface mapping
36
+ * table names to their column shapes.
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * import { PostgresDatabaseRepository } from '@xfcfam/xf-sql-postgres'
41
+ * import { UniqueViolationException } from '@xfcfam/xf-sql'
42
+ *
43
+ * interface Schema {
44
+ * users: { id: number; name: string; email: string; created_at: Date }
45
+ * }
46
+ *
47
+ * export class UsersDb extends PostgresDatabaseRepository<Schema> {
48
+ * constructor() {
49
+ * super({
50
+ * connectionString: process.env.DATABASE_URL!,
51
+ * pool: { max: 10, idleTimeoutMillis: 30_000 },
52
+ * })
53
+ * }
54
+ * async init() { await super.init() } // ← required
55
+ * async terminate() { await super.terminate() } // ← required
56
+ *
57
+ * getUser(id: number) {
58
+ * return this.exec(() =>
59
+ * this.db.selectFrom('users').where('id', '=', id).selectAll().executeTakeFirstOrThrow()
60
+ * )
61
+ * }
62
+ *
63
+ * async createUser(input: { name: string; email: string }) {
64
+ * try {
65
+ * return await this.exec(() =>
66
+ * this.db.insertInto('users').values({ ...input, created_at: new Date() }).returningAll().executeTakeFirstOrThrow()
67
+ * )
68
+ * } catch (err) {
69
+ * if (err instanceof UniqueViolationException && err.column === 'email') {
70
+ * throw new DomainError('Email already registered')
71
+ * }
72
+ * throw err
73
+ * }
74
+ * }
75
+ * }
76
+ * ```
77
+ */
78
+ export declare abstract class PostgresDatabaseRepository<Schema = unknown> extends TransactionalDatabaseRepository<Schema> {
79
+ constructor(options: PostgresOptions);
80
+ /**
81
+ * Translate `pg` / Kysely driver errors into the typed Exceptions
82
+ * exported from `@xfcfam/xf-sql`. Delegates to
83
+ * {@link PostgresErrorUtils.translate}.
84
+ *
85
+ * Subclasses may override to layer additional mappings on top, but
86
+ * should `return super.translateError(err)` for unrecognised
87
+ * errors so the base policy still applies.
88
+ */
89
+ protected translateError(err: unknown): unknown;
90
+ }
91
+ //# sourceMappingURL=PostgresDatabaseRepository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostgresDatabaseRepository.d.ts","sourceRoot":"","sources":["../../../../src/repository/general/PostgresDatabaseRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,+BAA+B,EAAE,MAAM,gBAAgB,CAAA;AAEhE,OAAO,EAAQ,KAAK,UAAU,EAAE,MAAM,IAAI,CAAA;AAG1C;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,yEAAyE;IACzE,IAAI,CAAC,EAAE,UAAU,CAAA;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AACH,8BAAsB,0BAA0B,CAAC,MAAM,GAAG,OAAO,CAC/D,SAAQ,+BAA+B,CAAC,MAAM,CAAC;gBAEnC,OAAO,EAAE,eAAe;IASpC;;;;;;;;OAQG;cACgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO;CAGzD"}
@@ -0,0 +1,88 @@
1
+ import { TransactionalDatabaseRepository } from '@xfcfam/xf-sql';
2
+ import { PostgresDialect } from 'kysely';
3
+ import { Pool } from 'pg';
4
+ import { PostgresErrorUtils } from '../utils/PostgresErrorUtils.js';
5
+ /**
6
+ * Ready-to-use Generalization for the Access Layer when the backing
7
+ * store is **PostgreSQL**.
8
+ *
9
+ * Wraps `kysely`'s `PostgresDialect` over the `pg` driver behind a
10
+ * single XF-canonical class. The implementer's concrete Logical
11
+ * extends this and exposes domain-meaningful methods that compose
12
+ * queries against `this.db`. Transactions via `this.transaction(...)`,
13
+ * one-shot error translation via `this.exec(...)`.
14
+ *
15
+ * The default `translateError` maps Postgres SQLSTATE codes to the
16
+ * typed Exceptions exported from `@xfcfam/xf-sql`
17
+ * (`UniqueViolationException`, `ForeignKeyViolationException`,
18
+ * `CheckViolationException`, `NotNullViolationException`,
19
+ * `DeadlockException`) and transport-level errors (`ECONNREFUSED`,
20
+ * `ETIMEDOUT`, …) to `ConnectionException`. The implementer's
21
+ * Business Layer never sees `pg` types.
22
+ *
23
+ * @typeParam Schema Implementer-defined TypeScript interface mapping
24
+ * table names to their column shapes.
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * import { PostgresDatabaseRepository } from '@xfcfam/xf-sql-postgres'
29
+ * import { UniqueViolationException } from '@xfcfam/xf-sql'
30
+ *
31
+ * interface Schema {
32
+ * users: { id: number; name: string; email: string; created_at: Date }
33
+ * }
34
+ *
35
+ * export class UsersDb extends PostgresDatabaseRepository<Schema> {
36
+ * constructor() {
37
+ * super({
38
+ * connectionString: process.env.DATABASE_URL!,
39
+ * pool: { max: 10, idleTimeoutMillis: 30_000 },
40
+ * })
41
+ * }
42
+ * async init() { await super.init() } // ← required
43
+ * async terminate() { await super.terminate() } // ← required
44
+ *
45
+ * getUser(id: number) {
46
+ * return this.exec(() =>
47
+ * this.db.selectFrom('users').where('id', '=', id).selectAll().executeTakeFirstOrThrow()
48
+ * )
49
+ * }
50
+ *
51
+ * async createUser(input: { name: string; email: string }) {
52
+ * try {
53
+ * return await this.exec(() =>
54
+ * this.db.insertInto('users').values({ ...input, created_at: new Date() }).returningAll().executeTakeFirstOrThrow()
55
+ * )
56
+ * } catch (err) {
57
+ * if (err instanceof UniqueViolationException && err.column === 'email') {
58
+ * throw new DomainError('Email already registered')
59
+ * }
60
+ * throw err
61
+ * }
62
+ * }
63
+ * }
64
+ * ```
65
+ */
66
+ export class PostgresDatabaseRepository extends TransactionalDatabaseRepository {
67
+ constructor(options) {
68
+ const poolConfig = { ...options.pool };
69
+ if (options.connectionString !== undefined) {
70
+ poolConfig.connectionString = options.connectionString;
71
+ }
72
+ const pool = new Pool(poolConfig);
73
+ super({ dialect: new PostgresDialect({ pool }) });
74
+ }
75
+ /**
76
+ * Translate `pg` / Kysely driver errors into the typed Exceptions
77
+ * exported from `@xfcfam/xf-sql`. Delegates to
78
+ * {@link PostgresErrorUtils.translate}.
79
+ *
80
+ * Subclasses may override to layer additional mappings on top, but
81
+ * should `return super.translateError(err)` for unrecognised
82
+ * errors so the base policy still applies.
83
+ */
84
+ translateError(err) {
85
+ return PostgresErrorUtils.translate(err);
86
+ }
87
+ }
88
+ //# sourceMappingURL=PostgresDatabaseRepository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostgresDatabaseRepository.js","sourceRoot":"","sources":["../../../../src/repository/general/PostgresDatabaseRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,+BAA+B,EAAE,MAAM,gBAAgB,CAAA;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAA;AACxC,OAAO,EAAE,IAAI,EAAmB,MAAM,IAAI,CAAA;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AAiBnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AACH,MAAM,OAAgB,0BACpB,SAAQ,+BAAuC;IAE/C,YAAY,OAAwB;QAClC,MAAM,UAAU,GAAe,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,CAAA;QAClD,IAAI,OAAO,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;YAC3C,UAAU,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAA;QACxD,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,CAAA;QACjC,KAAK,CAAC,EAAE,OAAO,EAAE,IAAI,eAAe,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAA;IACnD,CAAC;IAED;;;;;;;;OAQG;IACgB,cAAc,CAAC,GAAY;QAC5C,OAAO,kBAAkB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;IAC1C,CAAC;CACF"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Static utility component that translates Postgres / `pg` driver
3
+ * errors into the typed Exceptions exported from `@xfcfam/xf-sql`.
4
+ *
5
+ * The translation is based on the SQLSTATE code attached to the
6
+ * error by `pg` (see
7
+ * [Postgres docs](https://www.postgresql.org/docs/current/errcodes-appendix.html)).
8
+ *
9
+ * Non-instantiable. All members are static.
10
+ */
11
+ export declare class PostgresErrorUtils {
12
+ private constructor();
13
+ /** Class 23 — integrity constraint violation: unique. */
14
+ static readonly SQLSTATE_UNIQUE_VIOLATION = "23505";
15
+ /** Class 23 — integrity constraint violation: foreign key. */
16
+ static readonly SQLSTATE_FOREIGN_KEY_VIOLATION = "23503";
17
+ /** Class 23 — integrity constraint violation: check. */
18
+ static readonly SQLSTATE_CHECK_VIOLATION = "23514";
19
+ /** Class 23 — integrity constraint violation: not null. */
20
+ static readonly SQLSTATE_NOT_NULL_VIOLATION = "23502";
21
+ /** Class 40 — transaction rollback: deadlock detected. */
22
+ static readonly SQLSTATE_DEADLOCK_DETECTED = "40P01";
23
+ /**
24
+ * Translate any `pg` / Kysely error to the corresponding `@xfcfam/xf-sql`
25
+ * Exception. Returns the input unchanged when:
26
+ *
27
+ * - The error is already a `DatabaseException` (already translated).
28
+ * - The error has no SQLSTATE `code` and isn't a recognised
29
+ * transport-level failure.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * try {
34
+ * await this.db.insertInto('users').values(input).execute()
35
+ * } catch (err) {
36
+ * throw PostgresErrorUtils.translate(err)
37
+ * }
38
+ * ```
39
+ *
40
+ * (`PostgresDatabaseRepository` overrides `translateError` to call
41
+ * this automatically — you don't need to wrap manually if you
42
+ * extend it.)
43
+ */
44
+ static translate(err: unknown): unknown;
45
+ private static isErrorLike;
46
+ private static isTransportCode;
47
+ }
48
+ //# sourceMappingURL=PostgresErrorUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostgresErrorUtils.d.ts","sourceRoot":"","sources":["../../../../src/repository/utils/PostgresErrorUtils.ts"],"names":[],"mappings":"AA2BA;;;;;;;;;GASG;AACH,qBAAa,kBAAkB;IAC7B,OAAO;IAEP,yDAAyD;IACzD,MAAM,CAAC,QAAQ,CAAC,yBAAyB,WAAe;IACxD,8DAA8D;IAC9D,MAAM,CAAC,QAAQ,CAAC,8BAA8B,WAAU;IACxD,wDAAwD;IACxD,MAAM,CAAC,QAAQ,CAAC,wBAAwB,WAAgB;IACxD,2DAA2D;IAC3D,MAAM,CAAC,QAAQ,CAAC,2BAA2B,WAAa;IACxD,0DAA0D;IAC1D,MAAM,CAAC,QAAQ,CAAC,0BAA0B,WAAc;IAExD;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO;IAkDvC,OAAO,CAAC,MAAM,CAAC,WAAW;IAI1B,OAAO,CAAC,MAAM,CAAC,eAAe;CAW/B"}
@@ -0,0 +1,102 @@
1
+ import { DatabaseException, ConnectionException, UniqueViolationException, ForeignKeyViolationException, CheckViolationException, NotNullViolationException, DeadlockException, } from '@xfcfam/xf-sql';
2
+ /**
3
+ * Static utility component that translates Postgres / `pg` driver
4
+ * errors into the typed Exceptions exported from `@xfcfam/xf-sql`.
5
+ *
6
+ * The translation is based on the SQLSTATE code attached to the
7
+ * error by `pg` (see
8
+ * [Postgres docs](https://www.postgresql.org/docs/current/errcodes-appendix.html)).
9
+ *
10
+ * Non-instantiable. All members are static.
11
+ */
12
+ export class PostgresErrorUtils {
13
+ constructor() { }
14
+ /** Class 23 — integrity constraint violation: unique. */
15
+ static SQLSTATE_UNIQUE_VIOLATION = '23505';
16
+ /** Class 23 — integrity constraint violation: foreign key. */
17
+ static SQLSTATE_FOREIGN_KEY_VIOLATION = '23503';
18
+ /** Class 23 — integrity constraint violation: check. */
19
+ static SQLSTATE_CHECK_VIOLATION = '23514';
20
+ /** Class 23 — integrity constraint violation: not null. */
21
+ static SQLSTATE_NOT_NULL_VIOLATION = '23502';
22
+ /** Class 40 — transaction rollback: deadlock detected. */
23
+ static SQLSTATE_DEADLOCK_DETECTED = '40P01';
24
+ /**
25
+ * Translate any `pg` / Kysely error to the corresponding `@xfcfam/xf-sql`
26
+ * Exception. Returns the input unchanged when:
27
+ *
28
+ * - The error is already a `DatabaseException` (already translated).
29
+ * - The error has no SQLSTATE `code` and isn't a recognised
30
+ * transport-level failure.
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * try {
35
+ * await this.db.insertInto('users').values(input).execute()
36
+ * } catch (err) {
37
+ * throw PostgresErrorUtils.translate(err)
38
+ * }
39
+ * ```
40
+ *
41
+ * (`PostgresDatabaseRepository` overrides `translateError` to call
42
+ * this automatically — you don't need to wrap manually if you
43
+ * extend it.)
44
+ */
45
+ static translate(err) {
46
+ if (err instanceof DatabaseException)
47
+ return err;
48
+ if (!PostgresErrorUtils.isErrorLike(err))
49
+ return err;
50
+ const message = err.message ?? 'Database error';
51
+ // Connection-level errors do not have a SQLSTATE; pg sets `code`
52
+ // to a Node errno like 'ECONNREFUSED' or 'ENOTFOUND'.
53
+ if (PostgresErrorUtils.isTransportCode(err.code)) {
54
+ return new ConnectionException(message, { cause: err });
55
+ }
56
+ switch (err.code) {
57
+ case PostgresErrorUtils.SQLSTATE_UNIQUE_VIOLATION:
58
+ return new UniqueViolationException(message, {
59
+ ...(err.constraint !== undefined ? { constraint: err.constraint } : {}),
60
+ ...(err.table !== undefined ? { table: err.table } : {}),
61
+ ...(err.column !== undefined ? { column: err.column } : {}),
62
+ cause: err,
63
+ });
64
+ case PostgresErrorUtils.SQLSTATE_FOREIGN_KEY_VIOLATION:
65
+ return new ForeignKeyViolationException(message, {
66
+ ...(err.constraint !== undefined ? { constraint: err.constraint } : {}),
67
+ ...(err.table !== undefined ? { table: err.table } : {}),
68
+ cause: err,
69
+ });
70
+ case PostgresErrorUtils.SQLSTATE_CHECK_VIOLATION:
71
+ return new CheckViolationException(message, {
72
+ ...(err.constraint !== undefined ? { constraint: err.constraint } : {}),
73
+ ...(err.table !== undefined ? { table: err.table } : {}),
74
+ cause: err,
75
+ });
76
+ case PostgresErrorUtils.SQLSTATE_NOT_NULL_VIOLATION:
77
+ return new NotNullViolationException(message, {
78
+ ...(err.table !== undefined ? { table: err.table } : {}),
79
+ ...(err.column !== undefined ? { column: err.column } : {}),
80
+ cause: err,
81
+ });
82
+ case PostgresErrorUtils.SQLSTATE_DEADLOCK_DETECTED:
83
+ return new DeadlockException(message, { cause: err });
84
+ default:
85
+ return err;
86
+ }
87
+ }
88
+ static isErrorLike(err) {
89
+ return typeof err === 'object' && err !== null;
90
+ }
91
+ static isTransportCode(code) {
92
+ if (code === undefined)
93
+ return false;
94
+ return (code === 'ECONNREFUSED' ||
95
+ code === 'ENOTFOUND' ||
96
+ code === 'ETIMEDOUT' ||
97
+ code === 'ECONNRESET' ||
98
+ code === 'EHOSTUNREACH' ||
99
+ code === 'EAI_AGAIN');
100
+ }
101
+ }
102
+ //# sourceMappingURL=PostgresErrorUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostgresErrorUtils.js","sourceRoot":"","sources":["../../../../src/repository/utils/PostgresErrorUtils.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@xfcfam/xf-sql-postgres",
3
+ "version": "0.1.0",
4
+ "description": "PostgreSQL dialect adapter for @xfcfam/xf-sql. Encapsulates kysely's PostgresDialect and the `pg` driver. Translates Postgres SQLSTATE codes into the typed Exceptions of @xfcfam/xf-sql.",
5
+ "author": "XF Contributors",
6
+ "license": "MIT",
7
+ "homepage": "https://xfcfam.org",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/xfcfam/lib-npm",
11
+ "directory": "packages/xf-sql-postgres"
12
+ },
13
+ "keywords": [
14
+ "xf",
15
+ "cfam",
16
+ "sql",
17
+ "postgres",
18
+ "postgresql",
19
+ "kysely",
20
+ "pg"
21
+ ],
22
+ "type": "module",
23
+ "main": "./dist/index.js",
24
+ "types": "./dist/index.d.ts",
25
+ "exports": {
26
+ ".": {
27
+ "import": "./dist/index.js",
28
+ "types": "./dist/index.d.ts"
29
+ }
30
+ },
31
+ "files": [
32
+ "dist"
33
+ ],
34
+ "publishConfig": {
35
+ "access": "public"
36
+ },
37
+ "peerDependencies": {
38
+ "@xfcfam/xf-sql": "^0.1.0",
39
+ "@xfcfam/xf": "^0.2.0"
40
+ },
41
+ "dependencies": {
42
+ "pg": "^8.11.0"
43
+ },
44
+ "devDependencies": {
45
+ "typescript": "^5.4.0",
46
+ "vitest": "^2.0.0",
47
+ "kysely": "^0.27.0",
48
+ "@types/pg": "^8.11.0"
49
+ },
50
+ "scripts": {
51
+ "build": "tsc",
52
+ "typecheck": "tsc --noEmit",
53
+ "clean": "rm -rf dist",
54
+ "test": "vitest run",
55
+ "test:watch": "vitest"
56
+ }
57
+ }