@hexaijs/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.
- package/LICENSE +21 -0
- package/README.md +318 -0
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +19 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/postgres-config-spec.d.ts +32 -0
- package/dist/config/postgres-config-spec.d.ts.map +1 -0
- package/dist/config/postgres-config-spec.js +49 -0
- package/dist/config/postgres-config-spec.js.map +1 -0
- package/dist/config/postgres-config.d.ts +59 -0
- package/dist/config/postgres-config.d.ts.map +1 -0
- package/dist/config/postgres-config.js +181 -0
- package/dist/config/postgres-config.js.map +1 -0
- package/dist/helpers.d.ts +57 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/helpers.js +276 -0
- package/dist/helpers.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/postgres-event-store.d.ts +18 -0
- package/dist/postgres-event-store.d.ts.map +1 -0
- package/dist/postgres-event-store.js +83 -0
- package/dist/postgres-event-store.js.map +1 -0
- package/dist/postgres-unit-of-work.d.ts +17 -0
- package/dist/postgres-unit-of-work.d.ts.map +1 -0
- package/dist/postgres-unit-of-work.js +251 -0
- package/dist/postgres-unit-of-work.js.map +1 -0
- package/dist/run-hexai-migrations.d.ts +3 -0
- package/dist/run-hexai-migrations.d.ts.map +1 -0
- package/dist/run-hexai-migrations.js +17 -0
- package/dist/run-hexai-migrations.js.map +1 -0
- package/dist/run-migrations.d.ts +11 -0
- package/dist/run-migrations.d.ts.map +1 -0
- package/dist/run-migrations.js +202 -0
- package/dist/run-migrations.js.map +1 -0
- package/dist/test-fixtures/config.d.ts +5 -0
- package/dist/test-fixtures/config.d.ts.map +1 -0
- package/dist/test-fixtures/config.js +14 -0
- package/dist/test-fixtures/config.js.map +1 -0
- package/dist/test-fixtures/hooks.d.ts +8 -0
- package/dist/test-fixtures/hooks.d.ts.map +1 -0
- package/dist/test-fixtures/hooks.js +77 -0
- package/dist/test-fixtures/hooks.js.map +1 -0
- package/dist/test-fixtures/index.d.ts +3 -0
- package/dist/test-fixtures/index.d.ts.map +1 -0
- package/dist/test-fixtures/index.js +19 -0
- package/dist/test-fixtures/index.js.map +1 -0
- package/dist/test.d.ts +11 -0
- package/dist/test.d.ts.map +1 -0
- package/dist/test.js +41 -0
- package/dist/test.js.map +1 -0
- package/dist/types.d.ts +14 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -0
- package/migrations/01_postgres_event_store/migration.sql +10 -0
- package/package.json +67 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Sangwoo Hyun
|
|
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,318 @@
|
|
|
1
|
+
# @hexaijs/postgres
|
|
2
|
+
|
|
3
|
+
> PostgreSQL infrastructure for transaction management, event storage, and migrations
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
`@hexaijs/postgres` provides PostgreSQL implementations of the core infrastructure interfaces defined in `@hexaijs/core`. It bridges your domain layer to PostgreSQL with production-ready transaction management.
|
|
8
|
+
|
|
9
|
+
The package centers around `PostgresUnitOfWork`, which manages database transactions across your command handlers. It uses `AsyncLocalStorage` to maintain transaction context throughout async operations, ensuring all database operations within a handler share the same transaction. If your handler succeeds, the transaction commits automatically. If it throws, the transaction rolls back.
|
|
10
|
+
|
|
11
|
+
Beyond transactions, the package includes `PostgresEventStore` for storing domain events, a migration runner that integrates with `node-pg-migrate`, and configuration utilities for managing connection settings through environment variables.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @hexaijs/postgres
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Peer dependencies:**
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @hexaijs/core @hexaijs/utils pg
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Core Concepts
|
|
26
|
+
|
|
27
|
+
### PostgresUnitOfWork
|
|
28
|
+
|
|
29
|
+
The `PostgresUnitOfWork` implements `UnitOfWork` from `@hexaijs/core`. It manages transaction lifecycle and provides access to the database client.
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import * as pg from "pg";
|
|
33
|
+
import { PostgresUnitOfWork } from "@hexaijs/postgres";
|
|
34
|
+
|
|
35
|
+
// Create with a client factory
|
|
36
|
+
const pool = new pg.Pool({ connectionString: "postgres://..." });
|
|
37
|
+
const unitOfWork = new PostgresUnitOfWork(
|
|
38
|
+
() => new pg.Client({ connectionString: "postgres://..." }),
|
|
39
|
+
(client) => client.end() // cleanup function
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
// Or use a connection pool
|
|
43
|
+
const pooledUnitOfWork = new PostgresUnitOfWork(
|
|
44
|
+
async () => await pool.connect(),
|
|
45
|
+
(client) => (client as pg.PoolClient).release()
|
|
46
|
+
);
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The client factory creates a new client for each transaction. The optional cleanup function runs after the transaction completes (commit or rollback).
|
|
50
|
+
|
|
51
|
+
### Transaction Execution
|
|
52
|
+
|
|
53
|
+
Use `wrap()` to execute operations within a transaction:
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import { Propagation } from "@hexaijs/core";
|
|
57
|
+
|
|
58
|
+
// Execute within a transaction
|
|
59
|
+
const result = await unitOfWork.wrap(async (client) => {
|
|
60
|
+
await client.query("INSERT INTO orders (id, status) VALUES ($1, $2)", [orderId, "pending"]);
|
|
61
|
+
await client.query("INSERT INTO order_items (order_id, product_id) VALUES ($1, $2)", [orderId, productId]);
|
|
62
|
+
return { orderId };
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Within a command handler, access the client through `getClient()`:
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
// Inside a command handler
|
|
70
|
+
const client = ctx.getUnitOfWork().getClient();
|
|
71
|
+
await client.query("UPDATE orders SET status = $1 WHERE id = $2", ["confirmed", orderId]);
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Transaction Propagation
|
|
75
|
+
|
|
76
|
+
Control how nested operations participate in transactions using `Propagation`:
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import { Propagation } from "@hexaijs/core";
|
|
80
|
+
|
|
81
|
+
// EXISTING (default): Join current transaction, or create new if none exists
|
|
82
|
+
await unitOfWork.wrap(async () => {
|
|
83
|
+
// This joins the outer transaction
|
|
84
|
+
await unitOfWork.wrap(async (client) => {
|
|
85
|
+
// Same transaction as outer
|
|
86
|
+
}, { propagation: Propagation.EXISTING });
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// NEW: Always start a new transaction
|
|
90
|
+
await unitOfWork.wrap(async () => {
|
|
91
|
+
// This runs in a separate transaction
|
|
92
|
+
await unitOfWork.wrap(async (client) => {
|
|
93
|
+
// Independent transaction
|
|
94
|
+
}, { propagation: Propagation.NEW });
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// NESTED: Create a savepoint within the current transaction
|
|
98
|
+
await unitOfWork.wrap(async () => {
|
|
99
|
+
try {
|
|
100
|
+
await unitOfWork.wrap(async (client) => {
|
|
101
|
+
// Runs in a savepoint
|
|
102
|
+
throw new Error("Rollback this part only");
|
|
103
|
+
}, { propagation: Propagation.NESTED });
|
|
104
|
+
} catch {
|
|
105
|
+
// Savepoint rolled back, outer transaction continues
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Isolation Levels
|
|
111
|
+
|
|
112
|
+
Configure transaction isolation levels when stricter guarantees are needed:
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
import { IsolationLevel } from "@hexaijs/postgres";
|
|
116
|
+
|
|
117
|
+
await unitOfWork.wrap(async (client) => {
|
|
118
|
+
// Serializable isolation prevents phantom reads
|
|
119
|
+
const result = await client.query("SELECT * FROM inventory WHERE product_id = $1", [productId]);
|
|
120
|
+
// ...
|
|
121
|
+
}, { isolationLevel: IsolationLevel.SERIALIZABLE });
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Available levels:
|
|
125
|
+
- `IsolationLevel.READ_UNCOMMITTED`
|
|
126
|
+
- `IsolationLevel.READ_COMMITTED` (PostgreSQL default)
|
|
127
|
+
- `IsolationLevel.REPEATABLE_READ`
|
|
128
|
+
- `IsolationLevel.SERIALIZABLE`
|
|
129
|
+
|
|
130
|
+
### PostgresEventStore
|
|
131
|
+
|
|
132
|
+
The `PostgresEventStore` implements `EventStore` from `@hexaijs/core` for storing and retrieving domain events.
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
import { PostgresEventStore } from "@hexaijs/postgres";
|
|
136
|
+
import { DomainEvent } from "@hexaijs/core";
|
|
137
|
+
|
|
138
|
+
class OrderPlaced extends DomainEvent<{ orderId: string; customerId: string }> {
|
|
139
|
+
static readonly type = "order.order-placed";
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Create event store with the transaction client
|
|
143
|
+
const client = unitOfWork.getClient();
|
|
144
|
+
const eventStore = new PostgresEventStore(client);
|
|
145
|
+
|
|
146
|
+
// Store events
|
|
147
|
+
const stored = await eventStore.store(new OrderPlaced({
|
|
148
|
+
orderId: "order-123",
|
|
149
|
+
customerId: "customer-456"
|
|
150
|
+
}));
|
|
151
|
+
console.log(stored.position); // Event position in the store
|
|
152
|
+
|
|
153
|
+
// Store multiple events atomically
|
|
154
|
+
const storedEvents = await eventStore.storeAll([event1, event2, event3]);
|
|
155
|
+
|
|
156
|
+
// Fetch events for replay or projections
|
|
157
|
+
const { events, lastPosition } = await eventStore.fetch(0, 100);
|
|
158
|
+
// events: StoredEvent[] - events after position 0, up to 100
|
|
159
|
+
// lastPosition: number - highest position in store (for catchup detection)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Custom table name:
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
const eventStore = new PostgresEventStore(client, {
|
|
166
|
+
tableName: "my_bounded_context_events"
|
|
167
|
+
});
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Usage
|
|
171
|
+
|
|
172
|
+
### Running Migrations
|
|
173
|
+
|
|
174
|
+
The package provides a migration runner that supports both SQL and JavaScript migration formats.
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
import { runMigrations } from "@hexaijs/postgres";
|
|
178
|
+
|
|
179
|
+
// Run JavaScript migrations (node-pg-migrate format)
|
|
180
|
+
await runMigrations({
|
|
181
|
+
url: "postgres://user:pass@localhost:5432/mydb",
|
|
182
|
+
dir: "./migrations",
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
// With namespace (creates separate migrations table)
|
|
186
|
+
await runMigrations({
|
|
187
|
+
url: "postgres://user:pass@localhost:5432/mydb",
|
|
188
|
+
dir: "./migrations/orders",
|
|
189
|
+
namespace: "orders", // Table: hexai__migrations_orders
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// SQL-based migrations (directories with migration.sql files)
|
|
193
|
+
// migrations/
|
|
194
|
+
// 001_create_orders/
|
|
195
|
+
// migration.sql
|
|
196
|
+
// 002_add_status/
|
|
197
|
+
// migration.sql
|
|
198
|
+
await runMigrations({
|
|
199
|
+
url: dbConfig,
|
|
200
|
+
dir: "./migrations",
|
|
201
|
+
});
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Run built-in hexai migrations (creates the event store table):
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
import { runHexaiMigrations } from "@hexaijs/postgres";
|
|
208
|
+
|
|
209
|
+
await runHexaiMigrations("postgres://user:pass@localhost:5432/mydb");
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Configuration
|
|
213
|
+
|
|
214
|
+
`PostgresConfig` provides immutable configuration management:
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
import { PostgresConfig } from "@hexaijs/postgres";
|
|
218
|
+
|
|
219
|
+
// From connection URL
|
|
220
|
+
const config = PostgresConfig.fromUrl("postgres://user:pass@localhost:5432/mydb");
|
|
221
|
+
|
|
222
|
+
// From environment variables
|
|
223
|
+
// URL mode: reads MY_DB_URL
|
|
224
|
+
const config = PostgresConfig.fromEnv("MY_DB");
|
|
225
|
+
|
|
226
|
+
// Fields mode: reads MY_DB_HOST, MY_DB_PORT, MY_DB_DATABASE, MY_DB_USER, MY_DB_PASSWORD
|
|
227
|
+
const config = PostgresConfig.fromEnv("MY_DB", { mode: "fields" });
|
|
228
|
+
|
|
229
|
+
// Builder pattern for modifications (returns new instance)
|
|
230
|
+
const testConfig = config
|
|
231
|
+
.withDatabase("mydb_test")
|
|
232
|
+
.withPoolSize(5);
|
|
233
|
+
|
|
234
|
+
// Use as connection string
|
|
235
|
+
new pg.Client({ connectionString: config.toString() });
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
With `defineConfig` from `@hexaijs/utils`:
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
import { defineConfig } from "@hexaijs/utils/config";
|
|
242
|
+
import { postgresConfig } from "@hexaijs/postgres";
|
|
243
|
+
|
|
244
|
+
const getConfig = defineConfig({
|
|
245
|
+
db: postgresConfig("ORDER_DB"), // reads ORDER_DB_URL
|
|
246
|
+
readReplica: postgresConfig("REPLICA_DB", "fields"), // reads individual fields
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
const config = getConfig();
|
|
250
|
+
config.db.host; // "localhost"
|
|
251
|
+
config.db.toString(); // "postgres://..."
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Database Utilities
|
|
255
|
+
|
|
256
|
+
Helper classes for database management and testing:
|
|
257
|
+
|
|
258
|
+
```typescript
|
|
259
|
+
import { DatabaseManager, TableManager, ensureConnection } from "@hexaijs/postgres";
|
|
260
|
+
|
|
261
|
+
// Create/drop databases
|
|
262
|
+
const dbManager = new DatabaseManager("postgres://user:pass@localhost:5432/postgres");
|
|
263
|
+
await dbManager.createDatabase("my_new_db");
|
|
264
|
+
await dbManager.dropDatabase("my_old_db");
|
|
265
|
+
await dbManager.close();
|
|
266
|
+
|
|
267
|
+
// Table operations
|
|
268
|
+
const tableManager = new TableManager(client);
|
|
269
|
+
await tableManager.tableExists("orders");
|
|
270
|
+
await tableManager.truncateTable("orders");
|
|
271
|
+
await tableManager.dropAllTables();
|
|
272
|
+
|
|
273
|
+
// Ensure client is connected
|
|
274
|
+
await ensureConnection(client); // Safe to call multiple times
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Test Fixtures
|
|
278
|
+
|
|
279
|
+
The package exports test utilities from `@hexaijs/postgres/test`:
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
import { useDatabase, useClient, useTableManager } from "@hexaijs/postgres/test";
|
|
283
|
+
|
|
284
|
+
describe("OrderRepository", () => {
|
|
285
|
+
// Creates database before tests, drops after
|
|
286
|
+
const dbUrl = useDatabase("order_test_db");
|
|
287
|
+
|
|
288
|
+
// Provides connected client
|
|
289
|
+
const client = useClient("order_test_db");
|
|
290
|
+
|
|
291
|
+
it("should persist orders", async () => {
|
|
292
|
+
// Use client for assertions
|
|
293
|
+
const result = await client.query("SELECT * FROM orders");
|
|
294
|
+
expect(result.rows).toHaveLength(1);
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
## API Highlights
|
|
300
|
+
|
|
301
|
+
| Export | Description |
|
|
302
|
+
|--------|-------------|
|
|
303
|
+
| `PostgresUnitOfWork` | Transaction management with `AsyncLocalStorage` context |
|
|
304
|
+
| `PostgresEventStore` | Event store implementation with batch insert support |
|
|
305
|
+
| `PostgresConfig` | Immutable configuration with builder pattern |
|
|
306
|
+
| `postgresConfig` | Config spec for `defineConfig` integration |
|
|
307
|
+
| `runMigrations` | Migration runner for SQL and JS migrations |
|
|
308
|
+
| `runHexaiMigrations` | Runs built-in hexai migrations |
|
|
309
|
+
| `DatabaseManager` | Create/drop databases |
|
|
310
|
+
| `TableManager` | Table operations (truncate, drop, schema info) |
|
|
311
|
+
| `IsolationLevel` | Transaction isolation level enum |
|
|
312
|
+
| `ensureConnection` | Safe connection helper |
|
|
313
|
+
|
|
314
|
+
## See Also
|
|
315
|
+
|
|
316
|
+
- [@hexaijs/core](../core/README.md) - Core interfaces (`UnitOfWork`, `EventStore`, `Propagation`)
|
|
317
|
+
- [@hexaijs/sqlite](../sqlite/README.md) - SQLite implementation for testing
|
|
318
|
+
- [@hexaijs/application](../application/README.md) - Application context that provides `getUnitOfWork()`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./postgres-config"), exports);
|
|
18
|
+
__exportStar(require("./postgres-config-spec"), exports);
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,yDAAuC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ConfigSpec } from "@hexaijs/utils/config";
|
|
2
|
+
import { PostgresConfig, type FromEnvOptions } from "./postgres-config";
|
|
3
|
+
export declare class PostgresConfigSpec implements ConfigSpec<PostgresConfig> {
|
|
4
|
+
private readonly prefix;
|
|
5
|
+
private readonly mode;
|
|
6
|
+
readonly _type = "postgres";
|
|
7
|
+
constructor(prefix: string, mode?: FromEnvOptions["mode"]);
|
|
8
|
+
resolve(errors: string[]): PostgresConfig | undefined;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* PostgreSQL database configuration from environment variables.
|
|
12
|
+
* Returns a PostgresConfig instance.
|
|
13
|
+
*
|
|
14
|
+
* @param prefix - Environment variable prefix
|
|
15
|
+
* @param mode - "url" reads {PREFIX}_URL, "fields" reads individual fields
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* import { defineConfig, env } from "@hexaijs/core";
|
|
20
|
+
* import { postgresConfig } from "@hexaijs/postgres";
|
|
21
|
+
*
|
|
22
|
+
* const getConfig = defineConfig({
|
|
23
|
+
* db: postgresConfig("ORDER_DB"), // reads ORDER_DB_URL
|
|
24
|
+
* db2: postgresConfig("PG", "fields"), // reads PG_HOST, PG_PORT, etc.
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* getConfig().db.host; // "localhost"
|
|
28
|
+
* getConfig().db.toString(); // "postgres://..."
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare function postgresConfig(prefix: string, mode?: FromEnvOptions["mode"]): PostgresConfigSpec;
|
|
32
|
+
//# sourceMappingURL=postgres-config-spec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres-config-spec.d.ts","sourceRoot":"","sources":["../../src/config/postgres-config-spec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExE,qBAAa,kBAAmB,YAAW,UAAU,CAAC,cAAc,CAAC;IAI7D,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAJzB,QAAQ,CAAC,KAAK,cAAc;gBAGP,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,cAAc,CAAC,MAAM,CAAS;IAGzD,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,cAAc,GAAG,SAAS;CAQxD;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,cAAc,CAC1B,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,cAAc,CAAC,MAAM,CAAS,GACrC,kBAAkB,CAEpB"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PostgresConfigSpec = void 0;
|
|
4
|
+
exports.postgresConfig = postgresConfig;
|
|
5
|
+
const postgres_config_1 = require("./postgres-config");
|
|
6
|
+
class PostgresConfigSpec {
|
|
7
|
+
prefix;
|
|
8
|
+
mode;
|
|
9
|
+
_type = "postgres";
|
|
10
|
+
constructor(prefix, mode = "url") {
|
|
11
|
+
this.prefix = prefix;
|
|
12
|
+
this.mode = mode;
|
|
13
|
+
}
|
|
14
|
+
resolve(errors) {
|
|
15
|
+
try {
|
|
16
|
+
return postgres_config_1.PostgresConfig.fromEnv(this.prefix, { mode: this.mode });
|
|
17
|
+
}
|
|
18
|
+
catch (e) {
|
|
19
|
+
errors.push(e.message);
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.PostgresConfigSpec = PostgresConfigSpec;
|
|
25
|
+
/**
|
|
26
|
+
* PostgreSQL database configuration from environment variables.
|
|
27
|
+
* Returns a PostgresConfig instance.
|
|
28
|
+
*
|
|
29
|
+
* @param prefix - Environment variable prefix
|
|
30
|
+
* @param mode - "url" reads {PREFIX}_URL, "fields" reads individual fields
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* import { defineConfig, env } from "@hexaijs/core";
|
|
35
|
+
* import { postgresConfig } from "@hexaijs/postgres";
|
|
36
|
+
*
|
|
37
|
+
* const getConfig = defineConfig({
|
|
38
|
+
* db: postgresConfig("ORDER_DB"), // reads ORDER_DB_URL
|
|
39
|
+
* db2: postgresConfig("PG", "fields"), // reads PG_HOST, PG_PORT, etc.
|
|
40
|
+
* });
|
|
41
|
+
*
|
|
42
|
+
* getConfig().db.host; // "localhost"
|
|
43
|
+
* getConfig().db.toString(); // "postgres://..."
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
function postgresConfig(prefix, mode = "url") {
|
|
47
|
+
return new PostgresConfigSpec(prefix, mode);
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=postgres-config-spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres-config-spec.js","sourceRoot":"","sources":["../../src/config/postgres-config-spec.ts"],"names":[],"mappings":";;;AA0CA,wCAKC;AA9CD,uDAAwE;AAExE,MAAa,kBAAkB;IAIN;IACA;IAJZ,KAAK,GAAG,UAAU,CAAC;IAE5B,YACqB,MAAc,EACd,OAA+B,KAAK;QADpC,WAAM,GAAN,MAAM,CAAQ;QACd,SAAI,GAAJ,IAAI,CAAgC;IACtD,CAAC;IAEJ,OAAO,CAAC,MAAgB;QACpB,IAAI,CAAC;YACD,OAAO,gCAAc,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACpE,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,MAAM,CAAC,IAAI,CAAE,CAAW,CAAC,OAAO,CAAC,CAAC;YAClC,OAAO,SAAS,CAAC;QACrB,CAAC;IACL,CAAC;CACJ;AAhBD,gDAgBC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,SAAgB,cAAc,CAC1B,MAAc,EACd,OAA+B,KAAK;IAEpC,OAAO,IAAI,kBAAkB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAChD,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { DatabaseConfig } from "@hexaijs/utils/config";
|
|
2
|
+
export interface PoolOptions {
|
|
3
|
+
size?: number;
|
|
4
|
+
connectionTimeout?: number;
|
|
5
|
+
idleTimeout?: number;
|
|
6
|
+
}
|
|
7
|
+
export interface FromEnvOptions {
|
|
8
|
+
/**
|
|
9
|
+
* Environment variable loading mode.
|
|
10
|
+
* - "url": Load from {PREFIX}_URL (default)
|
|
11
|
+
* - "fields": Load from {PREFIX}_HOST, {PREFIX}_PORT, {PREFIX}_DATABASE, {PREFIX}_USER, {PREFIX}_PASSWORD
|
|
12
|
+
*/
|
|
13
|
+
mode?: "url" | "fields";
|
|
14
|
+
}
|
|
15
|
+
export declare class PostgresConfig implements DatabaseConfig {
|
|
16
|
+
readonly host: string;
|
|
17
|
+
readonly database: string;
|
|
18
|
+
readonly user: string;
|
|
19
|
+
readonly port: number;
|
|
20
|
+
readonly password?: string;
|
|
21
|
+
readonly pool?: PoolOptions;
|
|
22
|
+
constructor(config: {
|
|
23
|
+
database: string;
|
|
24
|
+
user?: string;
|
|
25
|
+
host?: string;
|
|
26
|
+
port?: number;
|
|
27
|
+
password?: string;
|
|
28
|
+
pool?: PoolOptions;
|
|
29
|
+
});
|
|
30
|
+
static fromUrl(value: string): PostgresConfig;
|
|
31
|
+
/**
|
|
32
|
+
* Creates a PostgresConfig from environment variables.
|
|
33
|
+
*
|
|
34
|
+
* @param prefix - Environment variable prefix
|
|
35
|
+
* @param options - Loading options (mode: "url" | "fields")
|
|
36
|
+
* @throws Error if required environment variables are not set
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* // URL mode (default): reads ASSIGNMENT_DB_URL
|
|
41
|
+
* const config = PostgresConfig.fromEnv("ASSIGNMENT_DB");
|
|
42
|
+
*
|
|
43
|
+
* // Fields mode: reads POSTGRES_HOST, POSTGRES_PORT, POSTGRES_DATABASE, POSTGRES_USER, POSTGRES_PASSWORD
|
|
44
|
+
* const config = PostgresConfig.fromEnv("POSTGRES", { mode: "fields" });
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
static fromEnv(prefix: string, options?: FromEnvOptions): PostgresConfig;
|
|
48
|
+
private static parseUrl;
|
|
49
|
+
withDatabase(database: string): PostgresConfig;
|
|
50
|
+
withUser(user: string): PostgresConfig;
|
|
51
|
+
withPassword(password: string): PostgresConfig;
|
|
52
|
+
withHost(host: string): PostgresConfig;
|
|
53
|
+
withPort(port: number): PostgresConfig;
|
|
54
|
+
withPoolSize(size: number): PostgresConfig;
|
|
55
|
+
withConnectionTimeout(connectionTimeout: number): PostgresConfig;
|
|
56
|
+
withIdleTimeout(idleTimeout: number): PostgresConfig;
|
|
57
|
+
toString(): string;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=postgres-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres-config.d.ts","sourceRoot":"","sources":["../../src/config/postgres-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,WAAW,WAAW;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC3B;;;;OAIG;IACH,IAAI,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;CAC3B;AAED,qBAAa,cAAe,YAAW,cAAc;IACjD,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,SAAgB,QAAQ,EAAE,MAAM,CAAC;IACjC,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,SAAgB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClC,SAAgB,IAAI,CAAC,EAAE,WAAW,CAAC;gBAEvB,MAAM,EAAE;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,IAAI,CAAC,EAAE,WAAW,CAAC;KACtB;WASa,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc;IAIpD;;;;;;;;;;;;;;;OAeG;WACW,OAAO,CACjB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,cAAc,GACzB,cAAc;IAiCjB,OAAO,CAAC,MAAM,CAAC,QAAQ;IAqBhB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc;IAW9C,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc;IAWtC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc;IAW9C,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc;IAWtC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc;IAWtC,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc;IAW1C,qBAAqB,CAAC,iBAAiB,EAAE,MAAM,GAAG,cAAc;IAWhE,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,cAAc;IAWpD,QAAQ,IAAI,MAAM;CA2B5B"}
|