@cortexa/core 0.7.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 (39) hide show
  1. package/LICENSE +191 -0
  2. package/README.md +423 -0
  3. package/dist/chunk-6VDDIS65.js +21 -0
  4. package/dist/chunk-6VDDIS65.js.map +1 -0
  5. package/dist/chunk-T4NUBJ7T.js +13 -0
  6. package/dist/chunk-T4NUBJ7T.js.map +1 -0
  7. package/dist/cli/chunk-7HYSAZX4.js +15 -0
  8. package/dist/cli/chunk-7HYSAZX4.js.map +1 -0
  9. package/dist/cli/chunk-HVMZ6P54.js +23 -0
  10. package/dist/cli/chunk-HVMZ6P54.js.map +1 -0
  11. package/dist/cli/index.js +5921 -0
  12. package/dist/cli/index.js.map +1 -0
  13. package/dist/cli/mongodb-WTT5HVQH.js +145 -0
  14. package/dist/cli/mongodb-WTT5HVQH.js.map +1 -0
  15. package/dist/cli/mongodb-stream-Q5OBFWZP.js +93 -0
  16. package/dist/cli/mongodb-stream-Q5OBFWZP.js.map +1 -0
  17. package/dist/cli/mssql-KG7P3R2I.js +79 -0
  18. package/dist/cli/mssql-KG7P3R2I.js.map +1 -0
  19. package/dist/cli/mysql-stream-Z2MZS2KF.js +195 -0
  20. package/dist/cli/mysql-stream-Z2MZS2KF.js.map +1 -0
  21. package/dist/cli/postgres-stream-S4CRICEA.js +237 -0
  22. package/dist/cli/postgres-stream-S4CRICEA.js.map +1 -0
  23. package/dist/index.cjs +5733 -0
  24. package/dist/index.cjs.map +1 -0
  25. package/dist/index.d.cts +670 -0
  26. package/dist/index.d.ts +670 -0
  27. package/dist/index.js +4805 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/mongodb-M5UGJZTC.js +143 -0
  30. package/dist/mongodb-M5UGJZTC.js.map +1 -0
  31. package/dist/mongodb-stream-Q23UHLTM.js +92 -0
  32. package/dist/mongodb-stream-Q23UHLTM.js.map +1 -0
  33. package/dist/mssql-I27XEHQ2.js +77 -0
  34. package/dist/mssql-I27XEHQ2.js.map +1 -0
  35. package/dist/mysql-stream-YCNLPPPG.js +194 -0
  36. package/dist/mysql-stream-YCNLPPPG.js.map +1 -0
  37. package/dist/postgres-stream-A7EVYUX2.js +236 -0
  38. package/dist/postgres-stream-A7EVYUX2.js.map +1 -0
  39. package/package.json +105 -0
@@ -0,0 +1,237 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ computeBackoff,
4
+ resolveReconnectOptions
5
+ } from "./chunk-HVMZ6P54.js";
6
+ import {
7
+ createLogger
8
+ } from "./chunk-7HYSAZX4.js";
9
+
10
+ // src/behavioral/streams/postgres-stream.ts
11
+ var logger = createLogger({ name: "postgres-stream" });
12
+ var PostgresStream = class {
13
+ connectionConfig;
14
+ connector;
15
+ running;
16
+ service;
17
+ slotName;
18
+ reconnectOpts;
19
+ reconnectAttempts;
20
+ lastOnChange;
21
+ constructor(connectionConfig, connector, reconnect) {
22
+ this.connectionConfig = connectionConfig;
23
+ this.connector = connector;
24
+ this.running = false;
25
+ this.service = null;
26
+ this.slotName = "";
27
+ this.reconnectOpts = resolveReconnectOptions(reconnect);
28
+ this.reconnectAttempts = 0;
29
+ this.lastOnChange = null;
30
+ }
31
+ async start(onChange) {
32
+ this.lastOnChange = onChange;
33
+ this.reconnectAttempts = 0;
34
+ await this.connectStream(onChange);
35
+ }
36
+ async connectStream(onChange) {
37
+ const { LogicalReplicationService, PgoutputPlugin } = await import("pg-logical-replication");
38
+ const dbName = await this.connector.getDatabaseName();
39
+ this.slotName = `metis_${dbName.replace(/[^a-z0-9_]/gi, "_")}`;
40
+ await this.ensureReplicationSlot();
41
+ await this.ensurePublication();
42
+ const connectionOptions = this.buildConnectionOptions();
43
+ const service = new LogicalReplicationService(connectionOptions, {
44
+ acknowledge: { auto: true, timeoutSeconds: 10 }
45
+ });
46
+ if (!service) {
47
+ throw new Error("Failed to create LogicalReplicationService");
48
+ }
49
+ this.service = service;
50
+ const plugin = new PgoutputPlugin({
51
+ protoVersion: 1,
52
+ publicationNames: ["metis_pub"]
53
+ });
54
+ this.service.on("data", (lsn, log) => {
55
+ const event = log;
56
+ try {
57
+ let change;
58
+ if (event.tag === "insert") {
59
+ change = this.mapWalInsert(event);
60
+ } else if (event.tag === "update") {
61
+ change = this.mapWalUpdate(event);
62
+ } else if (event.tag === "delete") {
63
+ change = this.mapWalDelete(event);
64
+ }
65
+ if (change) {
66
+ this.reconnectAttempts = 0;
67
+ onChange(change);
68
+ }
69
+ } catch (err) {
70
+ const message = err instanceof Error ? err.message : String(err);
71
+ logger.error({ err: message, lsn }, "Failed to process WAL event");
72
+ }
73
+ });
74
+ this.service.on("error", (err) => {
75
+ const message = err instanceof Error ? err.message : String(err);
76
+ logger.error({ err: message }, "Replication stream error");
77
+ this.attemptReconnect();
78
+ });
79
+ this.service.subscribe(plugin, this.slotName).catch((err) => {
80
+ const message = err instanceof Error ? err.message : String(err);
81
+ logger.error({ err: message }, "Replication subscribe failed");
82
+ });
83
+ this.running = true;
84
+ logger.info({ slotName: this.slotName }, "PostgreSQL WAL stream started");
85
+ }
86
+ attemptReconnect() {
87
+ if (!this.lastOnChange || this.reconnectAttempts >= this.reconnectOpts.maxAttempts) {
88
+ logger.error({ attempts: this.reconnectAttempts }, "Max reconnection attempts reached, stream stopped");
89
+ this.running = false;
90
+ return;
91
+ }
92
+ const delay = computeBackoff(this.reconnectAttempts, this.reconnectOpts);
93
+ this.reconnectAttempts++;
94
+ logger.info({ attempt: this.reconnectAttempts, delayMs: delay }, "Reconnecting WAL stream");
95
+ setTimeout(() => {
96
+ if (!this.lastOnChange) return;
97
+ this.connectStream(this.lastOnChange).catch((err) => {
98
+ const message = err instanceof Error ? err.message : String(err);
99
+ logger.error({ err: message }, "Reconnection failed");
100
+ this.attemptReconnect();
101
+ });
102
+ }, delay);
103
+ }
104
+ async stop() {
105
+ if (this.service) {
106
+ await this.service.stop();
107
+ this.service.removeAllListeners();
108
+ this.service = null;
109
+ }
110
+ this.running = false;
111
+ logger.info("PostgreSQL WAL stream stopped");
112
+ }
113
+ async cleanup() {
114
+ await this.stop();
115
+ if (this.slotName) {
116
+ try {
117
+ await this.connector.query(
118
+ "SELECT pg_drop_replication_slot($1)",
119
+ [this.slotName]
120
+ );
121
+ logger.info({ slotName: this.slotName }, "Replication slot dropped");
122
+ } catch (err) {
123
+ const message = err instanceof Error ? err.message : String(err);
124
+ logger.error({ err: message, slotName: this.slotName }, "Failed to drop replication slot");
125
+ }
126
+ }
127
+ }
128
+ isRunning() {
129
+ return this.running;
130
+ }
131
+ mapWalInsert(event) {
132
+ const primaryKey = this.extractPrimaryKey(event.relation, event.new);
133
+ return {
134
+ tableName: event.relation.name,
135
+ tableSchema: event.relation.schema,
136
+ operation: "INSERT",
137
+ primaryKey,
138
+ newData: event.new,
139
+ detectedAt: /* @__PURE__ */ new Date()
140
+ };
141
+ }
142
+ mapWalUpdate(event) {
143
+ const primaryKey = this.extractPrimaryKey(event.relation, event.new);
144
+ const changedColumns = this.computeChangedColumns(event.old, event.new);
145
+ return {
146
+ tableName: event.relation.name,
147
+ tableSchema: event.relation.schema,
148
+ operation: "UPDATE",
149
+ primaryKey,
150
+ newData: event.new,
151
+ oldData: event.old,
152
+ changedColumns,
153
+ detectedAt: /* @__PURE__ */ new Date()
154
+ };
155
+ }
156
+ mapWalDelete(event) {
157
+ const primaryKey = this.extractPrimaryKey(event.relation, event.old);
158
+ return {
159
+ tableName: event.relation.name,
160
+ tableSchema: event.relation.schema,
161
+ operation: "DELETE",
162
+ primaryKey,
163
+ oldData: event.old,
164
+ detectedAt: /* @__PURE__ */ new Date()
165
+ };
166
+ }
167
+ extractPrimaryKey(relation, data) {
168
+ const pkColumn = relation.columns.find((col) => (col.flags & 1) !== 0);
169
+ if (pkColumn) {
170
+ const value = data[pkColumn.name];
171
+ if (typeof value === "number" || typeof value === "string") {
172
+ return value;
173
+ }
174
+ return String(value);
175
+ }
176
+ if (data.id !== void 0) {
177
+ const id = data.id;
178
+ if (typeof id === "number" || typeof id === "string") {
179
+ return id;
180
+ }
181
+ return String(id);
182
+ }
183
+ return "unknown";
184
+ }
185
+ computeChangedColumns(oldData, newData) {
186
+ if (!oldData) {
187
+ return Object.keys(newData);
188
+ }
189
+ const changed = [];
190
+ for (const key of Object.keys(newData)) {
191
+ if (oldData[key] !== newData[key]) {
192
+ changed.push(key);
193
+ }
194
+ }
195
+ return changed;
196
+ }
197
+ async ensureReplicationSlot() {
198
+ const result = await this.connector.query(
199
+ "SELECT slot_name FROM pg_replication_slots WHERE slot_name = $1",
200
+ [this.slotName]
201
+ );
202
+ if (result.rowCount === 0) {
203
+ await this.connector.query(
204
+ "SELECT pg_create_logical_replication_slot($1, 'pgoutput')",
205
+ [this.slotName]
206
+ );
207
+ logger.info({ slotName: this.slotName }, "Created replication slot");
208
+ }
209
+ }
210
+ async ensurePublication() {
211
+ const result = await this.connector.query(
212
+ "SELECT pubname FROM pg_publication WHERE pubname = 'metis_pub'"
213
+ );
214
+ if (result.rowCount === 0) {
215
+ await this.connector.query(
216
+ "CREATE PUBLICATION metis_pub FOR ALL TABLES"
217
+ );
218
+ logger.info("Created publication metis_pub");
219
+ }
220
+ }
221
+ buildConnectionOptions() {
222
+ if (this.connectionConfig.url) {
223
+ return { connectionString: this.connectionConfig.url };
224
+ }
225
+ return {
226
+ host: this.connectionConfig.host,
227
+ port: this.connectionConfig.port,
228
+ database: this.connectionConfig.database,
229
+ user: this.connectionConfig.user,
230
+ password: this.connectionConfig.password
231
+ };
232
+ }
233
+ };
234
+ export {
235
+ PostgresStream
236
+ };
237
+ //# sourceMappingURL=postgres-stream-S4CRICEA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/behavioral/streams/postgres-stream.ts"],"sourcesContent":["import type { ConnectionConfig } from '../../core/config.js';\nimport type { DatabaseConnector } from '../../connectors/types.js';\nimport type { RawChange } from '../types.js';\nimport type { ChangeStream, ReconnectOptions } from './types.js';\nimport { resolveReconnectOptions, computeBackoff } from './types.js';\nimport { createLogger } from '../../core/logger.js';\n\ninterface WalRelation {\n schema: string;\n name: string;\n columns: Array<{ name: string; typeOid: number; flags: number; typeMod: number }>;\n}\n\ninterface WalInsertEvent {\n tag: 'insert';\n relation: WalRelation;\n new: Record<string, unknown>;\n}\n\ninterface WalUpdateEvent {\n tag: 'update';\n relation: WalRelation;\n old?: Record<string, unknown>;\n new: Record<string, unknown>;\n}\n\ninterface WalDeleteEvent {\n tag: 'delete';\n relation: WalRelation;\n old: Record<string, unknown>;\n}\n\ntype WalEvent = WalInsertEvent | WalUpdateEvent | WalDeleteEvent;\n\nconst logger = createLogger({ name: 'postgres-stream' });\n\nexport class PostgresStream implements ChangeStream {\n private readonly connectionConfig: ConnectionConfig;\n private readonly connector: DatabaseConnector;\n private running: boolean;\n private service: { subscribe: (plugin: unknown, slotName: string) => Promise<void>; stop: () => Promise<void>; on: (event: string, listener: (...args: unknown[]) => void) => void; removeAllListeners: () => void } | null;\n private slotName: string;\n private reconnectOpts: Required<ReconnectOptions>;\n private reconnectAttempts: number;\n private lastOnChange: ((change: RawChange) => void) | null;\n\n constructor(connectionConfig: ConnectionConfig, connector: DatabaseConnector, reconnect?: ReconnectOptions) {\n this.connectionConfig = connectionConfig;\n this.connector = connector;\n this.running = false;\n this.service = null;\n this.slotName = '';\n this.reconnectOpts = resolveReconnectOptions(reconnect);\n this.reconnectAttempts = 0;\n this.lastOnChange = null;\n }\n\n async start(onChange: (change: RawChange) => void): Promise<void> {\n this.lastOnChange = onChange;\n this.reconnectAttempts = 0;\n await this.connectStream(onChange);\n }\n\n private async connectStream(onChange: (change: RawChange) => void): Promise<void> {\n const { LogicalReplicationService, PgoutputPlugin } = await import('pg-logical-replication');\n\n const dbName = await this.connector.getDatabaseName();\n this.slotName = `metis_${dbName.replace(/[^a-z0-9_]/gi, '_')}`;\n\n await this.ensureReplicationSlot();\n await this.ensurePublication();\n\n const connectionOptions = this.buildConnectionOptions();\n\n const service = new LogicalReplicationService(connectionOptions, {\n acknowledge: { auto: true, timeoutSeconds: 10 },\n }) as unknown as typeof this.service;\n\n if (!service) {\n throw new Error('Failed to create LogicalReplicationService');\n }\n\n this.service = service;\n\n const plugin = new PgoutputPlugin({\n protoVersion: 1,\n publicationNames: ['metis_pub'],\n });\n\n this.service.on('data', (lsn: unknown, log: unknown) => {\n const event = log as WalEvent;\n try {\n let change: RawChange | undefined;\n if (event.tag === 'insert') {\n change = this.mapWalInsert(event as WalInsertEvent);\n } else if (event.tag === 'update') {\n change = this.mapWalUpdate(event as WalUpdateEvent);\n } else if (event.tag === 'delete') {\n change = this.mapWalDelete(event as WalDeleteEvent);\n }\n\n if (change) {\n this.reconnectAttempts = 0; // Reset on successful data\n onChange(change);\n }\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n logger.error({ err: message, lsn }, 'Failed to process WAL event');\n }\n });\n\n this.service.on('error', (err: unknown) => {\n const message = err instanceof Error ? err.message : String(err);\n logger.error({ err: message }, 'Replication stream error');\n this.attemptReconnect();\n });\n\n this.service.subscribe(plugin, this.slotName).catch((err: unknown) => {\n const message = err instanceof Error ? err.message : String(err);\n logger.error({ err: message }, 'Replication subscribe failed');\n });\n\n this.running = true;\n logger.info({ slotName: this.slotName }, 'PostgreSQL WAL stream started');\n }\n\n private attemptReconnect(): void {\n if (!this.lastOnChange || this.reconnectAttempts >= this.reconnectOpts.maxAttempts) {\n logger.error({ attempts: this.reconnectAttempts }, 'Max reconnection attempts reached, stream stopped');\n this.running = false;\n return;\n }\n\n const delay = computeBackoff(this.reconnectAttempts, this.reconnectOpts);\n this.reconnectAttempts++;\n logger.info({ attempt: this.reconnectAttempts, delayMs: delay }, 'Reconnecting WAL stream');\n\n setTimeout(() => {\n if (!this.lastOnChange) return;\n this.connectStream(this.lastOnChange).catch((err: unknown) => {\n const message = err instanceof Error ? err.message : String(err);\n logger.error({ err: message }, 'Reconnection failed');\n this.attemptReconnect();\n });\n }, delay);\n }\n\n async stop(): Promise<void> {\n if (this.service) {\n await this.service.stop();\n this.service.removeAllListeners();\n this.service = null;\n }\n this.running = false;\n logger.info('PostgreSQL WAL stream stopped');\n }\n\n async cleanup(): Promise<void> {\n await this.stop();\n\n if (this.slotName) {\n try {\n await this.connector.query(\n 'SELECT pg_drop_replication_slot($1)',\n [this.slotName]\n );\n logger.info({ slotName: this.slotName }, 'Replication slot dropped');\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n logger.error({ err: message, slotName: this.slotName }, 'Failed to drop replication slot');\n }\n }\n }\n\n isRunning(): boolean {\n return this.running;\n }\n\n mapWalInsert(event: WalInsertEvent): RawChange {\n const primaryKey = this.extractPrimaryKey(event.relation, event.new);\n\n return {\n tableName: event.relation.name,\n tableSchema: event.relation.schema,\n operation: 'INSERT',\n primaryKey,\n newData: event.new as Record<string, unknown>,\n detectedAt: new Date(),\n };\n }\n\n mapWalUpdate(event: WalUpdateEvent): RawChange {\n const primaryKey = this.extractPrimaryKey(event.relation, event.new);\n const changedColumns = this.computeChangedColumns(event.old, event.new);\n\n return {\n tableName: event.relation.name,\n tableSchema: event.relation.schema,\n operation: 'UPDATE',\n primaryKey,\n newData: event.new as Record<string, unknown>,\n oldData: event.old as Record<string, unknown> | undefined,\n changedColumns,\n detectedAt: new Date(),\n };\n }\n\n mapWalDelete(event: WalDeleteEvent): RawChange {\n const primaryKey = this.extractPrimaryKey(event.relation, event.old);\n\n return {\n tableName: event.relation.name,\n tableSchema: event.relation.schema,\n operation: 'DELETE',\n primaryKey,\n oldData: event.old as Record<string, unknown>,\n detectedAt: new Date(),\n };\n }\n\n private extractPrimaryKey(\n relation: WalRelation,\n data: Record<string, unknown>\n ): string | number {\n const pkColumn = relation.columns.find((col) => (col.flags & 1) !== 0);\n\n if (pkColumn) {\n const value = data[pkColumn.name];\n if (typeof value === 'number' || typeof value === 'string') {\n return value;\n }\n return String(value);\n }\n\n if (data.id !== undefined) {\n const id = data.id;\n if (typeof id === 'number' || typeof id === 'string') {\n return id;\n }\n return String(id);\n }\n\n return 'unknown';\n }\n\n private computeChangedColumns(\n oldData: Record<string, unknown> | undefined,\n newData: Record<string, unknown>\n ): string[] {\n if (!oldData) {\n return Object.keys(newData);\n }\n\n const changed: string[] = [];\n for (const key of Object.keys(newData)) {\n if (oldData[key] !== newData[key]) {\n changed.push(key);\n }\n }\n return changed;\n }\n\n private async ensureReplicationSlot(): Promise<void> {\n const result = await this.connector.query(\n \"SELECT slot_name FROM pg_replication_slots WHERE slot_name = $1\",\n [this.slotName]\n );\n\n if (result.rowCount === 0) {\n await this.connector.query(\n \"SELECT pg_create_logical_replication_slot($1, 'pgoutput')\",\n [this.slotName]\n );\n logger.info({ slotName: this.slotName }, 'Created replication slot');\n }\n }\n\n private async ensurePublication(): Promise<void> {\n const result = await this.connector.query(\n \"SELECT pubname FROM pg_publication WHERE pubname = 'metis_pub'\"\n );\n\n if (result.rowCount === 0) {\n await this.connector.query(\n 'CREATE PUBLICATION metis_pub FOR ALL TABLES'\n );\n logger.info('Created publication metis_pub');\n }\n }\n\n private buildConnectionOptions(): Record<string, unknown> {\n if (this.connectionConfig.url) {\n return { connectionString: this.connectionConfig.url };\n }\n\n return {\n host: this.connectionConfig.host,\n port: this.connectionConfig.port,\n database: this.connectionConfig.database,\n user: this.connectionConfig.user,\n password: this.connectionConfig.password,\n };\n }\n}\n"],"mappings":"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","names":[]}