@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
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PostgresEventStore = void 0;
|
|
4
|
+
const core_1 = require("@hexaijs/core");
|
|
5
|
+
const DEFAULT_TABLE_NAME = "hexai__events";
|
|
6
|
+
const COLUMNS_PER_EVENT = 3;
|
|
7
|
+
class PostgresEventStore {
|
|
8
|
+
client;
|
|
9
|
+
tableName;
|
|
10
|
+
constructor(client, config = {}) {
|
|
11
|
+
this.client = client;
|
|
12
|
+
this.tableName = config.tableName ?? DEFAULT_TABLE_NAME;
|
|
13
|
+
}
|
|
14
|
+
async store(event) {
|
|
15
|
+
const serialized = event.serialize();
|
|
16
|
+
const result = await this.client.query(`INSERT INTO ${this.tableName} (message_type, headers, payload)
|
|
17
|
+
VALUES ($1, $2, $3)
|
|
18
|
+
RETURNING position`, [
|
|
19
|
+
event.getMessageType(),
|
|
20
|
+
JSON.stringify(serialized.headers),
|
|
21
|
+
JSON.stringify(serialized.payload),
|
|
22
|
+
]);
|
|
23
|
+
return {
|
|
24
|
+
position: +result.rows[0].position,
|
|
25
|
+
event,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
async storeAll(events) {
|
|
29
|
+
if (events.length === 0) {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
const values = [];
|
|
33
|
+
const placeholders = [];
|
|
34
|
+
events.forEach((event, index) => {
|
|
35
|
+
const serialized = event.serialize();
|
|
36
|
+
const offset = index * COLUMNS_PER_EVENT;
|
|
37
|
+
placeholders.push(`($${offset + 1}, $${offset + 2}, $${offset + 3})`);
|
|
38
|
+
values.push(event.getMessageType(), JSON.stringify(serialized.headers), JSON.stringify(serialized.payload));
|
|
39
|
+
});
|
|
40
|
+
const result = await this.client.query(`INSERT INTO ${this.tableName} (message_type, headers, payload)
|
|
41
|
+
VALUES ${placeholders.join(", ")}
|
|
42
|
+
RETURNING position`, values);
|
|
43
|
+
return result.rows.map((row, index) => ({
|
|
44
|
+
position: +row.position,
|
|
45
|
+
event: events[index],
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
async fetch(afterPosition, limit) {
|
|
49
|
+
const lastPosition = await this.getLastPosition();
|
|
50
|
+
let query = `
|
|
51
|
+
SELECT position, message_type, headers, payload
|
|
52
|
+
FROM ${this.tableName}
|
|
53
|
+
WHERE position > $1
|
|
54
|
+
ORDER BY position ASC
|
|
55
|
+
`;
|
|
56
|
+
const params = [afterPosition];
|
|
57
|
+
if (limit !== undefined) {
|
|
58
|
+
query += ` LIMIT $2`;
|
|
59
|
+
params.push(limit);
|
|
60
|
+
}
|
|
61
|
+
const result = await this.client.query(query, params);
|
|
62
|
+
const events = result.rows.map((row) => this.deserializeRow(row));
|
|
63
|
+
return {
|
|
64
|
+
events,
|
|
65
|
+
lastPosition,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
async getLastPosition() {
|
|
69
|
+
const result = await this.client.query(`SELECT MAX(position) as max FROM ${this.tableName}`);
|
|
70
|
+
return +(result.rows[0].max ?? 0);
|
|
71
|
+
}
|
|
72
|
+
deserializeRow(row) {
|
|
73
|
+
const headers = row.headers;
|
|
74
|
+
const payload = row.payload;
|
|
75
|
+
const event = core_1.Message.from(payload, headers);
|
|
76
|
+
return {
|
|
77
|
+
position: +row.position,
|
|
78
|
+
event,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
exports.PostgresEventStore = PostgresEventStore;
|
|
83
|
+
//# sourceMappingURL=postgres-event-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres-event-store.js","sourceRoot":"","sources":["../src/postgres-event-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as pg from "pg";
|
|
2
|
+
import { UnitOfWork } from "@hexaijs/core";
|
|
3
|
+
import { ClientCleanUp, ClientFactory, PostgresTransactionOptions } from "./types";
|
|
4
|
+
export declare class PostgresUnitOfWork implements UnitOfWork<pg.Client, PostgresTransactionOptions> {
|
|
5
|
+
private clientFactory;
|
|
6
|
+
private clientCleanUp?;
|
|
7
|
+
private transactionStorage;
|
|
8
|
+
constructor(clientFactory: ClientFactory, clientCleanUp?: ClientCleanUp | undefined);
|
|
9
|
+
getClient(): pg.Client;
|
|
10
|
+
wrap<T = unknown>(fn: (client: pg.Client) => Promise<T>, options?: Partial<PostgresTransactionOptions>): Promise<T>;
|
|
11
|
+
private getCurrentTransaction;
|
|
12
|
+
private resolveOptions;
|
|
13
|
+
private resolveTransaction;
|
|
14
|
+
private createTransaction;
|
|
15
|
+
private executeInContext;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=postgres-unit-of-work.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres-unit-of-work.d.ts","sourceRoot":"","sources":["../src/postgres-unit-of-work.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAEzB,OAAO,EAAe,UAAU,EAAE,MAAM,eAAe,CAAC;AAExD,OAAO,EACH,aAAa,EACb,aAAa,EACb,0BAA0B,EAC7B,MAAM,SAAS,CAAC;AAGjB,qBAAa,kBAAmB,YAAW,UAAU,CACjD,EAAE,CAAC,MAAM,EACT,0BAA0B,CAC7B;IAIO,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,aAAa,CAAC;IAJ1B,OAAO,CAAC,kBAAkB,CAAgD;gBAG9D,aAAa,EAAE,aAAa,EAC5B,aAAa,CAAC,EAAE,aAAa,YAAA;IAGlC,SAAS,IAAI,EAAE,CAAC,MAAM;IAUvB,IAAI,CAAC,CAAC,GAAG,OAAO,EAClB,EAAE,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EACrC,OAAO,GAAE,OAAO,CAAC,0BAA0B,CAAM,GAClD,OAAO,CAAC,CAAC,CAAC;IASb,OAAO,CAAC,qBAAqB;IAI7B,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,kBAAkB;IAS1B,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,gBAAgB;CAQ3B"}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PostgresUnitOfWork = void 0;
|
|
4
|
+
const node_async_hooks_1 = require("node:async_hooks");
|
|
5
|
+
const core_1 = require("@hexaijs/core");
|
|
6
|
+
const types_1 = require("./types");
|
|
7
|
+
const helpers_1 = require("./helpers");
|
|
8
|
+
class PostgresUnitOfWork {
|
|
9
|
+
clientFactory;
|
|
10
|
+
clientCleanUp;
|
|
11
|
+
transactionStorage = new node_async_hooks_1.AsyncLocalStorage();
|
|
12
|
+
constructor(clientFactory, clientCleanUp) {
|
|
13
|
+
this.clientFactory = clientFactory;
|
|
14
|
+
this.clientCleanUp = clientCleanUp;
|
|
15
|
+
}
|
|
16
|
+
getClient() {
|
|
17
|
+
const current = this.getCurrentTransaction();
|
|
18
|
+
if (!current) {
|
|
19
|
+
throw new Error("Unit of work not started");
|
|
20
|
+
}
|
|
21
|
+
return current.getClient();
|
|
22
|
+
}
|
|
23
|
+
async wrap(fn, options = {}) {
|
|
24
|
+
const resolvedOptions = this.resolveOptions(options);
|
|
25
|
+
const transaction = this.resolveTransaction(resolvedOptions);
|
|
26
|
+
return this.executeInContext(transaction, (tx) => tx.execute(fn, resolvedOptions));
|
|
27
|
+
}
|
|
28
|
+
getCurrentTransaction() {
|
|
29
|
+
return this.transactionStorage.getStore() ?? null;
|
|
30
|
+
}
|
|
31
|
+
resolveOptions(options) {
|
|
32
|
+
return {
|
|
33
|
+
propagation: core_1.Propagation.EXISTING,
|
|
34
|
+
...options,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
resolveTransaction(options) {
|
|
38
|
+
if (options.propagation === core_1.Propagation.NEW) {
|
|
39
|
+
return this.createTransaction();
|
|
40
|
+
}
|
|
41
|
+
return this.getCurrentTransaction() ?? this.createTransaction();
|
|
42
|
+
}
|
|
43
|
+
createTransaction() {
|
|
44
|
+
return new PostgresTransaction(this.clientFactory, this.clientCleanUp);
|
|
45
|
+
}
|
|
46
|
+
executeInContext(transaction, callback) {
|
|
47
|
+
return this.transactionStorage.run(transaction, () => callback(transaction));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
exports.PostgresUnitOfWork = PostgresUnitOfWork;
|
|
51
|
+
class PostgresTransaction {
|
|
52
|
+
clientFactory;
|
|
53
|
+
clientCleanUp;
|
|
54
|
+
initialized = false;
|
|
55
|
+
closed = false;
|
|
56
|
+
abortError;
|
|
57
|
+
nestingDepth = 0;
|
|
58
|
+
options;
|
|
59
|
+
client;
|
|
60
|
+
savepoints = [];
|
|
61
|
+
constructor(clientFactory, clientCleanUp) {
|
|
62
|
+
this.clientFactory = clientFactory;
|
|
63
|
+
this.clientCleanUp = clientCleanUp;
|
|
64
|
+
}
|
|
65
|
+
async execute(fn, options) {
|
|
66
|
+
this.options = options;
|
|
67
|
+
await this.ensureStarted();
|
|
68
|
+
const executor = this.resolveExecutor(options.propagation);
|
|
69
|
+
return executor === this
|
|
70
|
+
? this.runWithLifecycle(fn)
|
|
71
|
+
: executor.execute(fn, options);
|
|
72
|
+
}
|
|
73
|
+
getClient() {
|
|
74
|
+
return this.client;
|
|
75
|
+
}
|
|
76
|
+
async ensureStarted() {
|
|
77
|
+
if (this.initialized) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
this.initialized = true;
|
|
81
|
+
await this.initializeClient();
|
|
82
|
+
await this.beginTransaction();
|
|
83
|
+
}
|
|
84
|
+
async initializeClient() {
|
|
85
|
+
const client = await this.clientFactory();
|
|
86
|
+
if (!("query" in client)) {
|
|
87
|
+
throw new Error("Client factory must return a pg.Client");
|
|
88
|
+
}
|
|
89
|
+
await (0, helpers_1.ensureConnection)(client);
|
|
90
|
+
this.client = client;
|
|
91
|
+
}
|
|
92
|
+
async beginTransaction() {
|
|
93
|
+
await this.client.query("BEGIN");
|
|
94
|
+
const isolationLevel = this.options.isolationLevel ?? types_1.IsolationLevel.READ_COMMITTED;
|
|
95
|
+
if (isolationLevel !== types_1.IsolationLevel.READ_COMMITTED) {
|
|
96
|
+
await this.client.query(`SET TRANSACTION ISOLATION LEVEL ${isolationLevel}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
async runWithLifecycle(fn) {
|
|
100
|
+
try {
|
|
101
|
+
return await this.executeWithNesting(fn);
|
|
102
|
+
}
|
|
103
|
+
catch (e) {
|
|
104
|
+
console.error(`Transaction aborting, error in transaction:`);
|
|
105
|
+
console.error(e);
|
|
106
|
+
this.markAsAborted(e);
|
|
107
|
+
throw e;
|
|
108
|
+
}
|
|
109
|
+
finally {
|
|
110
|
+
await this.finalizeIfRoot();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
async executeWithNesting(fn) {
|
|
114
|
+
this.nestingDepth++;
|
|
115
|
+
try {
|
|
116
|
+
return await fn(this.client);
|
|
117
|
+
}
|
|
118
|
+
finally {
|
|
119
|
+
this.nestingDepth--;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
markAsAborted(error) {
|
|
123
|
+
this.abortError = error;
|
|
124
|
+
}
|
|
125
|
+
async finalizeIfRoot() {
|
|
126
|
+
if (this.nestingDepth === 0) {
|
|
127
|
+
await (this.isAborted() ? this.rollback() : this.commit());
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
resolveExecutor(propagation) {
|
|
131
|
+
if (this.nestingDepth === 0) {
|
|
132
|
+
return this;
|
|
133
|
+
}
|
|
134
|
+
return propagation === core_1.Propagation.NESTED
|
|
135
|
+
? this.createSavepoint()
|
|
136
|
+
: (this.findActiveSavepoint() ?? this);
|
|
137
|
+
}
|
|
138
|
+
createSavepoint() {
|
|
139
|
+
const savepoint = new Savepoint(`sp_${this.savepoints.length + 1}`, this.client, () => this.removeSavepoint());
|
|
140
|
+
this.savepoints.push(savepoint);
|
|
141
|
+
return savepoint;
|
|
142
|
+
}
|
|
143
|
+
findActiveSavepoint() {
|
|
144
|
+
for (let i = this.savepoints.length - 1; i >= 0; i--) {
|
|
145
|
+
if (!this.savepoints[i].isClosed()) {
|
|
146
|
+
return this.savepoints[i];
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
removeSavepoint() {
|
|
151
|
+
this.savepoints.pop();
|
|
152
|
+
}
|
|
153
|
+
async commit() {
|
|
154
|
+
if (this.closed) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
this.closed = true;
|
|
158
|
+
await this.client.query("COMMIT");
|
|
159
|
+
await this.clientCleanUp?.(this.client);
|
|
160
|
+
}
|
|
161
|
+
async rollback() {
|
|
162
|
+
if (this.closed) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
this.closed = true;
|
|
166
|
+
try {
|
|
167
|
+
await this.client.query("ROLLBACK");
|
|
168
|
+
}
|
|
169
|
+
catch (e) {
|
|
170
|
+
if (e instanceof Error &&
|
|
171
|
+
e.message.includes("Client was closed and is not queryable")) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
throw e;
|
|
175
|
+
}
|
|
176
|
+
await this.clientCleanUp?.(this.client);
|
|
177
|
+
}
|
|
178
|
+
isAborted() {
|
|
179
|
+
return this.abortError !== undefined && !this.closed;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
class Savepoint {
|
|
183
|
+
name;
|
|
184
|
+
client;
|
|
185
|
+
onClose;
|
|
186
|
+
initialized = false;
|
|
187
|
+
closed = false;
|
|
188
|
+
abortError;
|
|
189
|
+
nestingDepth = 0;
|
|
190
|
+
constructor(name, client, onClose) {
|
|
191
|
+
this.name = name;
|
|
192
|
+
this.client = client;
|
|
193
|
+
this.onClose = onClose;
|
|
194
|
+
}
|
|
195
|
+
async execute(fn) {
|
|
196
|
+
await this.ensureStarted();
|
|
197
|
+
return this.runWithLifecycle(fn);
|
|
198
|
+
}
|
|
199
|
+
isClosed() {
|
|
200
|
+
return this.closed;
|
|
201
|
+
}
|
|
202
|
+
async ensureStarted() {
|
|
203
|
+
if (this.initialized) {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
this.initialized = true;
|
|
207
|
+
await this.client.query(`SAVEPOINT ${this.name}`);
|
|
208
|
+
}
|
|
209
|
+
async runWithLifecycle(fn) {
|
|
210
|
+
this.nestingDepth++;
|
|
211
|
+
try {
|
|
212
|
+
return await fn(this.client);
|
|
213
|
+
}
|
|
214
|
+
catch (e) {
|
|
215
|
+
this.markAsAborted(e);
|
|
216
|
+
throw e;
|
|
217
|
+
}
|
|
218
|
+
finally {
|
|
219
|
+
this.nestingDepth--;
|
|
220
|
+
await this.finalizeIfRoot();
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
markAsAborted(error) {
|
|
224
|
+
this.abortError = error;
|
|
225
|
+
}
|
|
226
|
+
async finalizeIfRoot() {
|
|
227
|
+
if (this.nestingDepth === 0) {
|
|
228
|
+
await (this.isAborted() ? this.rollback() : this.commit());
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
async commit() {
|
|
232
|
+
if (this.closed) {
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
this.closed = true;
|
|
236
|
+
await this.client.query(`RELEASE SAVEPOINT ${this.name}`);
|
|
237
|
+
this.onClose();
|
|
238
|
+
}
|
|
239
|
+
async rollback() {
|
|
240
|
+
if (this.closed) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
this.closed = true;
|
|
244
|
+
await this.client.query(`ROLLBACK TO SAVEPOINT ${this.name}`);
|
|
245
|
+
this.onClose();
|
|
246
|
+
}
|
|
247
|
+
isAborted() {
|
|
248
|
+
return this.abortError !== undefined && !this.closed;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
//# sourceMappingURL=postgres-unit-of-work.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres-unit-of-work.js","sourceRoot":"","sources":["../src/postgres-unit-of-work.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-hexai-migrations.d.ts","sourceRoot":"","sources":["../src/run-hexai-migrations.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAI1C,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,iBAMtE"}
|
|
@@ -0,0 +1,17 @@
|
|
|
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
|
+
exports.runHexaiMigrations = runHexaiMigrations;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const run_migrations_1 = require("./run-migrations");
|
|
9
|
+
const MIGRATIONS_DIR = node_path_1.default.join(__dirname + "/../migrations");
|
|
10
|
+
async function runHexaiMigrations(dbUrl) {
|
|
11
|
+
await (0, run_migrations_1.runMigrations)({
|
|
12
|
+
dir: MIGRATIONS_DIR,
|
|
13
|
+
url: dbUrl,
|
|
14
|
+
namespace: "hexai",
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=run-hexai-migrations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-hexai-migrations.js","sourceRoot":"","sources":["../src/run-hexai-migrations.ts"],"names":[],"mappings":";;;;;AAOA,gDAMC;AAbD,0DAA6B;AAE7B,qDAAiD;AAGjD,MAAM,cAAc,GAAG,mBAAI,CAAC,IAAI,CAAC,SAAS,GAAG,gBAAgB,CAAC,CAAC;AAExD,KAAK,UAAU,kBAAkB,CAAC,KAA8B;IACnE,MAAM,IAAA,8BAAa,EAAC;QAChB,GAAG,EAAE,cAAc;QACnB,GAAG,EAAE,KAAK;QACV,SAAS,EAAE,OAAO;KACrB,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { PostgresConfig } from "./config";
|
|
2
|
+
export interface MigrationOptions {
|
|
3
|
+
url: PostgresConfig | string;
|
|
4
|
+
dir: string;
|
|
5
|
+
namespace?: string;
|
|
6
|
+
direction?: "up" | "down";
|
|
7
|
+
count?: number;
|
|
8
|
+
dryRun?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function runMigrations({ namespace, url, dir, direction, count, dryRun, }: MigrationOptions): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=run-migrations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-migrations.d.ts","sourceRoot":"","sources":["../src/run-migrations.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAW1C,MAAM,WAAW,gBAAgB;IAC7B,GAAG,EAAE,cAAc,GAAG,MAAM,CAAC;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CACpB;AAwID,wBAAsB,aAAa,CAAC,EAChC,SAAS,EACT,GAAG,EACH,GAAG,EACH,SAAgB,EAChB,KAAK,EACL,MAAc,GACjB,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA4ClC"}
|
|
@@ -0,0 +1,202 @@
|
|
|
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.runMigrations = runMigrations;
|
|
40
|
+
const fs = __importStar(require("node:fs/promises"));
|
|
41
|
+
const path = __importStar(require("node:path"));
|
|
42
|
+
const pg = __importStar(require("pg"));
|
|
43
|
+
const node_pg_migrate_1 = __importDefault(require("node-pg-migrate"));
|
|
44
|
+
/**
|
|
45
|
+
* Extracts numeric prefix from migration filename for proper sorting.
|
|
46
|
+
* Handles both simple numeric prefixes (1_initial) and timestamps (1734567890123_initial).
|
|
47
|
+
*/
|
|
48
|
+
function extractNumericPrefix(filename) {
|
|
49
|
+
const match = filename.match(/^(\d+)/);
|
|
50
|
+
return match ? parseInt(match[1], 10) : 0;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Ensures backward compatibility with existing tables that have 'applied_at' column
|
|
54
|
+
* by renaming it to 'run_on' (node-pg-migrate's expected column name)
|
|
55
|
+
*/
|
|
56
|
+
async function ensureTableCompatibility(client, tableName) {
|
|
57
|
+
// Check if table exists
|
|
58
|
+
const tableExists = await client.query(`
|
|
59
|
+
SELECT 1 FROM information_schema.tables
|
|
60
|
+
WHERE table_name = $1
|
|
61
|
+
`, [tableName]);
|
|
62
|
+
if (tableExists.rows.length === 0)
|
|
63
|
+
return;
|
|
64
|
+
// Check if applied_at column exists (old schema)
|
|
65
|
+
const hasAppliedAt = await client.query(`
|
|
66
|
+
SELECT 1 FROM information_schema.columns
|
|
67
|
+
WHERE table_name = $1 AND column_name = 'applied_at'
|
|
68
|
+
`, [tableName]);
|
|
69
|
+
if (hasAppliedAt.rows.length > 0) {
|
|
70
|
+
await client.query(`
|
|
71
|
+
ALTER TABLE "${tableName}"
|
|
72
|
+
RENAME COLUMN applied_at TO run_on
|
|
73
|
+
`);
|
|
74
|
+
console.log(`Migrated table ${tableName}: applied_at → run_on`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Detects whether the migrations directory contains SQL-based migrations
|
|
79
|
+
* (directories with migration.sql files) or JavaScript-based migrations.
|
|
80
|
+
*/
|
|
81
|
+
async function isSqlMigrationFormat(dir) {
|
|
82
|
+
try {
|
|
83
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
84
|
+
for (const entry of entries) {
|
|
85
|
+
if (entry.isDirectory()) {
|
|
86
|
+
const sqlPath = path.join(dir, entry.name, "migration.sql");
|
|
87
|
+
try {
|
|
88
|
+
await fs.access(sqlPath);
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
// Not a SQL migration directory
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Runs SQL-based migrations (directories with migration.sql files)
|
|
104
|
+
*/
|
|
105
|
+
async function runSqlMigrations(client, dir, migrationsTable, dryRun) {
|
|
106
|
+
// Ensure migrations table exists
|
|
107
|
+
await client.query(`
|
|
108
|
+
CREATE TABLE IF NOT EXISTS "${migrationsTable}" (
|
|
109
|
+
id SERIAL PRIMARY KEY,
|
|
110
|
+
name VARCHAR(255) NOT NULL,
|
|
111
|
+
run_on TIMESTAMP NOT NULL DEFAULT NOW()
|
|
112
|
+
)
|
|
113
|
+
`);
|
|
114
|
+
// Get applied migrations
|
|
115
|
+
const appliedResult = await client.query(`SELECT name FROM "${migrationsTable}" ORDER BY run_on ASC`);
|
|
116
|
+
const appliedMigrations = new Set(appliedResult.rows.map((r) => r.name));
|
|
117
|
+
// Get migration directories
|
|
118
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
119
|
+
const migrationDirs = entries
|
|
120
|
+
.filter((e) => e.isDirectory())
|
|
121
|
+
.map((e) => e.name)
|
|
122
|
+
.sort((a, b) => extractNumericPrefix(a) - extractNumericPrefix(b));
|
|
123
|
+
// Find migrations to apply
|
|
124
|
+
const migrationsToApply = [];
|
|
125
|
+
for (const migrationDir of migrationDirs) {
|
|
126
|
+
if (appliedMigrations.has(migrationDir)) {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
const sqlPath = path.join(dir, migrationDir, "migration.sql");
|
|
130
|
+
try {
|
|
131
|
+
const sql = await fs.readFile(sqlPath, "utf-8");
|
|
132
|
+
migrationsToApply.push({ name: migrationDir, sql });
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
// Skip directories without migration.sql
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (migrationsToApply.length === 0) {
|
|
139
|
+
console.log("No migrations to run!");
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
console.log(`> Migrating files:`);
|
|
143
|
+
for (const migration of migrationsToApply) {
|
|
144
|
+
console.log(`> - ${migration.name}`);
|
|
145
|
+
}
|
|
146
|
+
if (dryRun) {
|
|
147
|
+
console.log("Dry run - no migrations applied");
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
// Apply migrations
|
|
151
|
+
for (const migration of migrationsToApply) {
|
|
152
|
+
console.log(`### MIGRATION ${migration.name} (UP) ###`);
|
|
153
|
+
await client.query(migration.sql);
|
|
154
|
+
await client.query(`INSERT INTO "${migrationsTable}" (name) VALUES ($1)`, [migration.name]);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
async function runMigrations({ namespace, url, dir, direction = "up", count, dryRun = false, }) {
|
|
158
|
+
const migrationsTable = namespace
|
|
159
|
+
? `hexai__migrations_${namespace}`
|
|
160
|
+
: "hexai__migrations";
|
|
161
|
+
const client = new pg.Client(url);
|
|
162
|
+
try {
|
|
163
|
+
await client.connect();
|
|
164
|
+
await ensureTableCompatibility(client, migrationsTable);
|
|
165
|
+
// Check if this is SQL-based migrations or JavaScript-based
|
|
166
|
+
const isSqlFormat = await isSqlMigrationFormat(dir);
|
|
167
|
+
if (isSqlFormat) {
|
|
168
|
+
// Run SQL-based migrations
|
|
169
|
+
await runSqlMigrations(client, dir, migrationsTable, dryRun);
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
// Run JavaScript-based migrations using node-pg-migrate
|
|
173
|
+
await client.end();
|
|
174
|
+
await (0, node_pg_migrate_1.default)({
|
|
175
|
+
databaseUrl: url.toString(),
|
|
176
|
+
dir,
|
|
177
|
+
direction,
|
|
178
|
+
count,
|
|
179
|
+
migrationsTable,
|
|
180
|
+
dryRun,
|
|
181
|
+
singleTransaction: true,
|
|
182
|
+
log: (msg) => {
|
|
183
|
+
// Filter out timestamp warnings for backward compatibility
|
|
184
|
+
// with migration files using simple numeric prefixes (e.g., 1_initial.js)
|
|
185
|
+
if (!msg.startsWith("Can't determine timestamp for")) {
|
|
186
|
+
console.log(msg);
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
});
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
finally {
|
|
194
|
+
try {
|
|
195
|
+
await client.end();
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
// Client already closed
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=run-migrations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-migrations.js","sourceRoot":"","sources":["../src/run-migrations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/test-fixtures/config.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,aAAa;;;EAGxB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
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
|
+
exports.getTestConfig = void 0;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const config_1 = require("../config");
|
|
9
|
+
const config_2 = require("@hexaijs/utils/config");
|
|
10
|
+
exports.getTestConfig = (0, config_2.defineConfig)({
|
|
11
|
+
db: (0, config_1.postgresConfig)("HEXAI_DB"),
|
|
12
|
+
migrationsDir: node_path_1.default.join(__dirname + "/../migrations"),
|
|
13
|
+
});
|
|
14
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/test-fixtures/config.ts"],"names":[],"mappings":";;;;;;AAAA,0DAA6B;AAE7B,qCAA0C;AAC1C,kDAAqD;AAExC,QAAA,aAAa,GAAG,IAAA,qBAAY,EAAC;IACtC,EAAE,EAAE,IAAA,uBAAc,EAAC,UAAU,CAAC;IAC9B,aAAa,EAAE,mBAAI,CAAC,IAAI,CAAC,SAAS,GAAG,gBAAgB,CAAC;CACzD,CAAC,CAAC"}
|