argustack 0.1.8 → 0.1.9

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 (88) hide show
  1. package/dist/adapters/db/client.d.ts +13 -0
  2. package/dist/adapters/db/client.d.ts.map +1 -0
  3. package/dist/adapters/db/client.js +70 -0
  4. package/dist/adapters/db/client.js.map +1 -0
  5. package/dist/adapters/db/index.d.ts +4 -0
  6. package/dist/adapters/db/index.d.ts.map +1 -0
  7. package/dist/adapters/db/index.js +3 -0
  8. package/dist/adapters/db/index.js.map +1 -0
  9. package/dist/adapters/db/mapper.d.ts +31 -0
  10. package/dist/adapters/db/mapper.d.ts.map +1 -0
  11. package/dist/adapters/db/mapper.js +55 -0
  12. package/dist/adapters/db/mapper.js.map +1 -0
  13. package/dist/adapters/db/provider.d.ts +24 -0
  14. package/dist/adapters/db/provider.d.ts.map +1 -0
  15. package/dist/adapters/db/provider.js +159 -0
  16. package/dist/adapters/db/provider.js.map +1 -0
  17. package/dist/adapters/db/sql-validator.d.ts +10 -0
  18. package/dist/adapters/db/sql-validator.d.ts.map +1 -0
  19. package/dist/adapters/db/sql-validator.js +41 -0
  20. package/dist/adapters/db/sql-validator.js.map +1 -0
  21. package/dist/adapters/postgres/schema.d.ts.map +1 -1
  22. package/dist/adapters/postgres/schema.js +55 -0
  23. package/dist/adapters/postgres/schema.js.map +1 -1
  24. package/dist/adapters/postgres/storage.d.ts +3 -0
  25. package/dist/adapters/postgres/storage.d.ts.map +1 -1
  26. package/dist/adapters/postgres/storage.js +51 -0
  27. package/dist/adapters/postgres/storage.js.map +1 -1
  28. package/dist/cli/index.js +2 -1
  29. package/dist/cli/index.js.map +1 -1
  30. package/dist/cli/init/generators.d.ts.map +1 -1
  31. package/dist/cli/init/generators.js +1 -1
  32. package/dist/cli/init/generators.js.map +1 -1
  33. package/dist/cli/init/index.d.ts.map +1 -1
  34. package/dist/cli/init/index.js +13 -2
  35. package/dist/cli/init/index.js.map +1 -1
  36. package/dist/cli/init/setup-db.d.ts.map +1 -1
  37. package/dist/cli/init/setup-db.js +128 -12
  38. package/dist/cli/init/setup-db.js.map +1 -1
  39. package/dist/cli/init/setup-git.d.ts.map +1 -1
  40. package/dist/cli/init/setup-git.js +5 -1
  41. package/dist/cli/init/setup-git.js.map +1 -1
  42. package/dist/cli/init/setup-jira.d.ts.map +1 -1
  43. package/dist/cli/init/setup-jira.js +5 -2
  44. package/dist/cli/init/setup-jira.js.map +1 -1
  45. package/dist/cli/init/types.d.ts +2 -0
  46. package/dist/cli/init/types.d.ts.map +1 -1
  47. package/dist/cli/init/types.js.map +1 -1
  48. package/dist/cli/sync.d.ts +1 -0
  49. package/dist/cli/sync.d.ts.map +1 -1
  50. package/dist/cli/sync.js +48 -1
  51. package/dist/cli/sync.js.map +1 -1
  52. package/dist/core/ports/db-provider.d.ts +33 -0
  53. package/dist/core/ports/db-provider.d.ts.map +1 -0
  54. package/dist/core/ports/db-provider.js +2 -0
  55. package/dist/core/ports/db-provider.js.map +1 -0
  56. package/dist/core/ports/index.d.ts +1 -0
  57. package/dist/core/ports/index.d.ts.map +1 -1
  58. package/dist/core/ports/storage.d.ts +5 -0
  59. package/dist/core/ports/storage.d.ts.map +1 -1
  60. package/dist/core/types/config.d.ts.map +1 -1
  61. package/dist/core/types/config.js +5 -2
  62. package/dist/core/types/config.js.map +1 -1
  63. package/dist/core/types/database.d.ts +37 -0
  64. package/dist/core/types/database.d.ts.map +1 -0
  65. package/dist/core/types/database.js +2 -0
  66. package/dist/core/types/database.js.map +1 -0
  67. package/dist/core/types/index.d.ts +1 -0
  68. package/dist/core/types/index.d.ts.map +1 -1
  69. package/dist/mcp/server.d.ts.map +1 -1
  70. package/dist/mcp/server.js +2 -0
  71. package/dist/mcp/server.js.map +1 -1
  72. package/dist/mcp/tools/database.d.ts +4 -0
  73. package/dist/mcp/tools/database.d.ts.map +1 -0
  74. package/dist/mcp/tools/database.js +254 -0
  75. package/dist/mcp/tools/database.js.map +1 -0
  76. package/dist/mcp/tools/estimate.d.ts +10 -0
  77. package/dist/mcp/tools/estimate.d.ts.map +1 -1
  78. package/dist/mcp/tools/estimate.js +3 -3
  79. package/dist/mcp/tools/estimate.js.map +1 -1
  80. package/dist/use-cases/pull-db.d.ts +25 -0
  81. package/dist/use-cases/pull-db.d.ts.map +1 -0
  82. package/dist/use-cases/pull-db.js +59 -0
  83. package/dist/use-cases/pull-db.js.map +1 -0
  84. package/package.json +2 -1
  85. package/dist/cli/init.d.ts +0 -24
  86. package/dist/cli/init.d.ts.map +0 -1
  87. package/dist/cli/init.js +0 -957
  88. package/dist/cli/init.js.map +0 -1
@@ -0,0 +1,13 @@
1
+ import type { Knex } from 'knex';
2
+ import type { DbEngine } from '../../core/types/database.js';
3
+ export interface DbConnectionConfig {
4
+ engine: DbEngine;
5
+ host: string;
6
+ port: number;
7
+ user: string;
8
+ password: string;
9
+ database: string;
10
+ name: string;
11
+ }
12
+ export declare function createKnexClient(config: DbConnectionConfig): Knex;
13
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/adapters/db/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAEjC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAK7D,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,QAAQ,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAyCD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI,CA+BjE"}
@@ -0,0 +1,70 @@
1
+ import knex from 'knex';
2
+ const STATEMENT_TIMEOUT_MS = 30_000;
3
+ const POOL_IDLE_TIMEOUT_MS = 10_000;
4
+ const ENGINE_TO_KNEX_CLIENT = {
5
+ postgresql: 'pg',
6
+ mysql: 'mysql2',
7
+ mssql: 'tedious',
8
+ sqlite: 'better-sqlite3',
9
+ oracledb: 'oracledb',
10
+ };
11
+ function buildAfterCreate(engine) {
12
+ return function afterCreate(conn, done) {
13
+ if (engine === 'postgresql') {
14
+ conn.query('SET default_transaction_read_only = true', (err) => {
15
+ if (err) {
16
+ done(err, conn);
17
+ return;
18
+ }
19
+ conn.query(`SET statement_timeout = '${String(STATEMENT_TIMEOUT_MS)}'`, (err2) => {
20
+ done(err2, conn);
21
+ });
22
+ });
23
+ }
24
+ else if (engine === 'mysql') {
25
+ conn.query('SET SESSION TRANSACTION READ ONLY', (err) => {
26
+ if (err) {
27
+ done(err, conn);
28
+ return;
29
+ }
30
+ conn.query(`SET SESSION max_execution_time = ${String(STATEMENT_TIMEOUT_MS)}`, (err2) => {
31
+ done(err2, conn);
32
+ });
33
+ });
34
+ }
35
+ else {
36
+ done(null, conn);
37
+ }
38
+ };
39
+ }
40
+ export function createKnexClient(config) {
41
+ const client = ENGINE_TO_KNEX_CLIENT[config.engine];
42
+ if (config.engine === 'sqlite') {
43
+ return knex({
44
+ client,
45
+ connection: { filename: config.database, options: { readonly: true } },
46
+ useNullAsDefault: true,
47
+ pool: { min: 0, max: 1 },
48
+ });
49
+ }
50
+ return knex({
51
+ client,
52
+ connection: {
53
+ host: config.host,
54
+ port: config.port,
55
+ user: config.user,
56
+ password: config.password,
57
+ database: config.database,
58
+ ssl: config.host !== 'localhost' && config.host !== '127.0.0.1'
59
+ ? { rejectUnauthorized: false }
60
+ : false,
61
+ },
62
+ pool: {
63
+ min: 0,
64
+ max: 2,
65
+ idleTimeoutMillis: POOL_IDLE_TIMEOUT_MS,
66
+ afterCreate: buildAfterCreate(config.engine),
67
+ },
68
+ });
69
+ }
70
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/adapters/db/client.ts"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,MAAM,CAAC;AAGxB,MAAM,oBAAoB,GAAG,MAAM,CAAC;AACpC,MAAM,oBAAoB,GAAG,MAAM,CAAC;AAYpC,MAAM,qBAAqB,GAA6B;IACtD,UAAU,EAAE,IAAI;IAChB,KAAK,EAAE,QAAQ;IACf,KAAK,EAAE,SAAS;IAChB,MAAM,EAAE,gBAAgB;IACxB,QAAQ,EAAE,UAAU;CACrB,CAAC;AAEF,SAAS,gBAAgB,CAAC,MAAgB;IACxC,OAAO,SAAS,WAAW,CACzB,IAAkE,EAClE,IAA2C;QAE3C,IAAI,MAAM,KAAK,YAAY,EAAE,CAAC;YAC5B,IAAI,CAAC,KAAK,CAAC,0CAA0C,EAAE,CAAC,GAAG,EAAE,EAAE;gBAC7D,IAAI,GAAG,EAAE,CAAC;oBACR,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;oBAChB,OAAO;gBACT,CAAC;gBACD,IAAI,CAAC,KAAK,CAAC,4BAA4B,MAAM,CAAC,oBAAoB,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE;oBAC/E,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBACnB,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;YAC9B,IAAI,CAAC,KAAK,CAAC,mCAAmC,EAAE,CAAC,GAAG,EAAE,EAAE;gBACtD,IAAI,GAAG,EAAE,CAAC;oBACR,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;oBAChB,OAAO;gBACT,CAAC;gBACD,IAAI,CAAC,KAAK,CAAC,oCAAoC,MAAM,CAAC,oBAAoB,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE;oBACtF,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBACnB,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAA0B;IACzD,MAAM,MAAM,GAAG,qBAAqB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAEpD,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;YACV,MAAM;YACN,UAAU,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE;YACtE,gBAAgB,EAAE,IAAI;YACtB,IAAI,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE;SACzB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,IAAI,CAAC;QACV,MAAM;QACN,UAAU,EAAE;YACV,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,GAAG,EAAE,MAAM,CAAC,IAAI,KAAK,WAAW,IAAI,MAAM,CAAC,IAAI,KAAK,WAAW;gBAC7D,CAAC,CAAC,EAAE,kBAAkB,EAAE,KAAK,EAAE;gBAC/B,CAAC,CAAC,KAAK;SACV;QACD,IAAI,EAAE;YACJ,GAAG,EAAE,CAAC;YACN,GAAG,EAAE,CAAC;YACN,iBAAiB,EAAE,oBAAoB;YACvC,WAAW,EAAE,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC;SAC7C;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { DbProvider } from './provider.js';
2
+ export { type DbConnectionConfig } from './client.js';
3
+ export { validateSql, type SqlValidationResult } from './sql-validator.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/db/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { DbProvider } from './provider.js';
2
+ export { validateSql } from './sql-validator.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/db/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,EAAE,WAAW,EAA4B,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,31 @@
1
+ import type { DbTable, DbColumn, DbForeignKey, DbIndex } from '../../core/types/database.js';
2
+ export interface RawTableRow {
3
+ table_schema: string;
4
+ table_name: string;
5
+ }
6
+ export interface RawColumnRow {
7
+ table_name: string;
8
+ column_name: string;
9
+ data_type: string;
10
+ is_nullable: string;
11
+ column_default: string | null;
12
+ ordinal_position: number;
13
+ }
14
+ export interface RawForeignKeyRow {
15
+ table_name: string;
16
+ column_name: string;
17
+ referenced_table: string;
18
+ referenced_column: string;
19
+ }
20
+ export interface RawIndexRow {
21
+ table_name: string;
22
+ index_name: string;
23
+ column_name: string;
24
+ is_unique: boolean;
25
+ is_primary: boolean;
26
+ }
27
+ export declare function mapTableRow(row: RawTableRow, sourceName: string): Omit<DbTable, 'columns'>;
28
+ export declare function mapColumnRow(row: RawColumnRow, primaryKeys: Set<string>): DbColumn;
29
+ export declare function mapForeignKeyRow(row: RawForeignKeyRow): DbForeignKey;
30
+ export declare function mapIndexRows(rows: RawIndexRow[]): DbIndex[];
31
+ //# sourceMappingURL=mapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapper.d.ts","sourceRoot":"","sources":["../../../src/adapters/db/mapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAE7F,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAQ1F;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,YAAY,EAAE,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,QAAQ,CAWlF;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,gBAAgB,GAAG,YAAY,CAOpE;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,OAAO,EAAE,CAyB3D"}
@@ -0,0 +1,55 @@
1
+ export function mapTableRow(row, sourceName) {
2
+ return {
3
+ sourceName,
4
+ schema: row.table_schema,
5
+ name: row.table_name,
6
+ rowCount: null,
7
+ sizeBytes: null,
8
+ };
9
+ }
10
+ export function mapColumnRow(row, primaryKeys) {
11
+ const key = `${row.table_name}.${row.column_name}`;
12
+ return {
13
+ tableName: row.table_name,
14
+ name: row.column_name,
15
+ dataType: row.data_type,
16
+ nullable: row.is_nullable === 'YES',
17
+ defaultValue: row.column_default,
18
+ isPrimaryKey: primaryKeys.has(key),
19
+ ordinalPosition: row.ordinal_position,
20
+ };
21
+ }
22
+ export function mapForeignKeyRow(row) {
23
+ return {
24
+ tableName: row.table_name,
25
+ columnName: row.column_name,
26
+ referencedTable: row.referenced_table,
27
+ referencedColumn: row.referenced_column,
28
+ };
29
+ }
30
+ export function mapIndexRows(rows) {
31
+ const grouped = new Map();
32
+ for (const row of rows) {
33
+ const key = `${row.table_name}.${row.index_name}`;
34
+ const existing = grouped.get(key);
35
+ if (existing) {
36
+ existing.columns.push(row.column_name);
37
+ }
38
+ else {
39
+ grouped.set(key, {
40
+ tableName: row.table_name,
41
+ columns: [row.column_name],
42
+ isUnique: row.is_unique,
43
+ isPrimary: row.is_primary,
44
+ });
45
+ }
46
+ }
47
+ return Array.from(grouped.entries()).map(([key, val]) => ({
48
+ tableName: val.tableName,
49
+ indexName: key.split('.')[1] ?? key,
50
+ columns: val.columns,
51
+ isUnique: val.isUnique,
52
+ isPrimary: val.isPrimary,
53
+ }));
54
+ }
55
+ //# sourceMappingURL=mapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapper.js","sourceRoot":"","sources":["../../../src/adapters/db/mapper.ts"],"names":[],"mappings":"AA+BA,MAAM,UAAU,WAAW,CAAC,GAAgB,EAAE,UAAkB;IAC9D,OAAO;QACL,UAAU;QACV,MAAM,EAAE,GAAG,CAAC,YAAY;QACxB,IAAI,EAAE,GAAG,CAAC,UAAU;QACpB,QAAQ,EAAE,IAAI;QACd,SAAS,EAAE,IAAI;KAChB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,GAAiB,EAAE,WAAwB;IACtE,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;IACnD,OAAO;QACL,SAAS,EAAE,GAAG,CAAC,UAAU;QACzB,IAAI,EAAE,GAAG,CAAC,WAAW;QACrB,QAAQ,EAAE,GAAG,CAAC,SAAS;QACvB,QAAQ,EAAE,GAAG,CAAC,WAAW,KAAK,KAAK;QACnC,YAAY,EAAE,GAAG,CAAC,cAAc;QAChC,YAAY,EAAE,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC;QAClC,eAAe,EAAE,GAAG,CAAC,gBAAgB;KACtC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAqB;IACpD,OAAO;QACL,SAAS,EAAE,GAAG,CAAC,UAAU;QACzB,UAAU,EAAE,GAAG,CAAC,WAAW;QAC3B,eAAe,EAAE,GAAG,CAAC,gBAAgB;QACrC,gBAAgB,EAAE,GAAG,CAAC,iBAAiB;KACxC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAmB;IAC9C,MAAM,OAAO,GAAG,IAAI,GAAG,EAA2F,CAAC;IAEnH,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;QAClD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE;gBACf,SAAS,EAAE,GAAG,CAAC,UAAU;gBACzB,OAAO,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC;gBAC1B,QAAQ,EAAE,GAAG,CAAC,SAAS;gBACvB,SAAS,EAAE,GAAG,CAAC,UAAU;aAC1B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;QACxD,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,SAAS,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG;QACnC,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,SAAS,EAAE,GAAG,CAAC,SAAS;KACzB,CAAC,CAAC,CAAC;AACN,CAAC"}
@@ -0,0 +1,24 @@
1
+ import type { IDbProvider } from '../../core/ports/db-provider.js';
2
+ import type { QueryResult } from '../../core/ports/storage.js';
3
+ import type { DbSchemaBatch, DbEngine } from '../../core/types/database.js';
4
+ import { type DbConnectionConfig } from './client.js';
5
+ export declare class DbProvider implements IDbProvider {
6
+ readonly name: string;
7
+ readonly engine: DbEngine;
8
+ private knex;
9
+ private readonly config;
10
+ constructor(config: DbConnectionConfig);
11
+ connect(): Promise<void>;
12
+ introspect(): AsyncGenerator<DbSchemaBatch>;
13
+ query(sql: string): Promise<QueryResult>;
14
+ getTableCount(): Promise<number>;
15
+ disconnect(): Promise<void>;
16
+ private requireConnection;
17
+ private applyRowLimit;
18
+ private queryTables;
19
+ private queryColumns;
20
+ private queryPrimaryKeys;
21
+ private queryForeignKeys;
22
+ private queryIndexes;
23
+ }
24
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../src/adapters/db/provider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAW,MAAM,8BAA8B,CAAC;AACrF,OAAO,EAAoB,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AA6BxE,qBAAa,UAAW,YAAW,WAAW;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,OAAO,CAAC,IAAI,CAAqB;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;gBAEhC,MAAM,EAAE,kBAAkB;IAMhC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAKvB,UAAU,IAAI,cAAc,CAAC,aAAa,CAAC;IAkC5C,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAgBxC,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAchC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAOjC,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,aAAa;YASP,WAAW;YAgCX,YAAY;YAkBZ,gBAAgB;YAkBhB,gBAAgB;YAkBhB,YAAY;CAU3B"}
@@ -0,0 +1,159 @@
1
+ import { createKnexClient } from './client.js';
2
+ import { validateSql } from './sql-validator.js';
3
+ import { mapTableRow, mapColumnRow, mapForeignKeyRow, mapIndexRows, } from './mapper.js';
4
+ const MAX_ROWS = 1000;
5
+ function extractRows(result) {
6
+ if (Array.isArray(result)) {
7
+ return result;
8
+ }
9
+ const obj = result;
10
+ if (Array.isArray(obj['rows'])) {
11
+ return obj['rows'];
12
+ }
13
+ if (Array.isArray(obj[0])) {
14
+ return obj[0];
15
+ }
16
+ return [];
17
+ }
18
+ export class DbProvider {
19
+ name;
20
+ engine;
21
+ knex = null;
22
+ config;
23
+ constructor(config) {
24
+ this.config = config;
25
+ this.name = config.name || `${config.engine}:${config.database}`;
26
+ this.engine = config.engine;
27
+ }
28
+ async connect() {
29
+ this.knex = createKnexClient(this.config);
30
+ await this.knex.raw('SELECT 1');
31
+ }
32
+ async *introspect() {
33
+ const db = this.requireConnection();
34
+ const sourceName = this.config.name || this.config.database;
35
+ const tables = await this.queryTables(db);
36
+ const primaryKeys = await this.queryPrimaryKeys(db);
37
+ const allColumns = await this.queryColumns(db);
38
+ const foreignKeys = await this.queryForeignKeys(db);
39
+ const indexes = await this.queryIndexes(db);
40
+ const columnsByTable = new Map();
41
+ for (const col of allColumns) {
42
+ const existing = columnsByTable.get(col.table_name) ?? [];
43
+ existing.push(col);
44
+ columnsByTable.set(col.table_name, existing);
45
+ }
46
+ const pkSet = new Set(primaryKeys.map((pk) => `${pk.table_name}.${pk.column_name}`));
47
+ const dbTables = tables.map((t) => {
48
+ const mapped = mapTableRow(t, sourceName);
49
+ const cols = columnsByTable.get(t.table_name) ?? [];
50
+ return {
51
+ ...mapped,
52
+ columns: cols.map((c) => mapColumnRow(c, pkSet)),
53
+ };
54
+ });
55
+ const dbForeignKeys = foreignKeys.map(mapForeignKeyRow);
56
+ const dbIndexes = mapIndexRows(indexes);
57
+ yield { tables: dbTables, foreignKeys: dbForeignKeys, indexes: dbIndexes };
58
+ }
59
+ async query(sql) {
60
+ const db = this.requireConnection();
61
+ const validation = validateSql(sql);
62
+ if (!validation.valid) {
63
+ throw new Error(`Query rejected: ${validation.reason}`);
64
+ }
65
+ const limitedSql = this.applyRowLimit(sql);
66
+ const result = await db.raw(limitedSql);
67
+ const rows = extractRows(result);
68
+ return { rows: rows.slice(0, MAX_ROWS) };
69
+ }
70
+ async getTableCount() {
71
+ const db = this.requireConnection();
72
+ if (this.engine === 'postgresql' || this.engine === 'mysql') {
73
+ const result = await db.raw(`SELECT COUNT(*) as count FROM information_schema.tables WHERE table_schema NOT IN ('information_schema', 'pg_catalog', 'mysql', 'performance_schema', 'sys')`);
74
+ const rows = extractRows(result);
75
+ return Number(rows[0]?.count ?? 0);
76
+ }
77
+ return 0;
78
+ }
79
+ async disconnect() {
80
+ if (this.knex) {
81
+ await this.knex.destroy();
82
+ this.knex = null;
83
+ }
84
+ }
85
+ requireConnection() {
86
+ if (!this.knex) {
87
+ throw new Error('Not connected. Call connect() first.');
88
+ }
89
+ return this.knex;
90
+ }
91
+ applyRowLimit(sql) {
92
+ const upper = sql.toUpperCase().trim();
93
+ if (upper.includes('LIMIT')) {
94
+ return sql;
95
+ }
96
+ const clean = sql.replace(/;\s*$/, '');
97
+ return `${clean} LIMIT ${String(MAX_ROWS)}`;
98
+ }
99
+ async queryTables(db) {
100
+ if (this.engine === 'postgresql') {
101
+ const result = await db.raw(`SELECT table_schema, table_name FROM information_schema.tables WHERE table_schema NOT IN ('information_schema', 'pg_catalog') AND table_type = 'BASE TABLE' ORDER BY table_schema, table_name`);
102
+ return extractRows(result);
103
+ }
104
+ if (this.engine === 'mysql') {
105
+ const result = await db.raw(`SELECT table_schema, table_name FROM information_schema.tables WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE' ORDER BY table_name`);
106
+ return extractRows(result);
107
+ }
108
+ if (this.engine === 'mssql') {
109
+ const result = await db.raw(`SELECT TABLE_SCHEMA as table_schema, TABLE_NAME as table_name FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_SCHEMA, TABLE_NAME`);
110
+ return extractRows(result);
111
+ }
112
+ if (this.engine === 'sqlite') {
113
+ const result = await db.raw(`SELECT 'main' as table_schema, name as table_name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%' ORDER BY name`);
114
+ return extractRows(result);
115
+ }
116
+ return [];
117
+ }
118
+ async queryColumns(db) {
119
+ if (this.engine === 'postgresql') {
120
+ const result = await db.raw(`SELECT table_name, column_name, data_type, is_nullable, column_default, ordinal_position FROM information_schema.columns WHERE table_schema NOT IN ('information_schema', 'pg_catalog') ORDER BY table_name, ordinal_position`);
121
+ return extractRows(result);
122
+ }
123
+ if (this.engine === 'mysql') {
124
+ const result = await db.raw(`SELECT table_name, column_name, data_type, is_nullable, column_default, ordinal_position FROM information_schema.columns WHERE table_schema = DATABASE() ORDER BY table_name, ordinal_position`);
125
+ return extractRows(result);
126
+ }
127
+ return [];
128
+ }
129
+ async queryPrimaryKeys(db) {
130
+ if (this.engine === 'postgresql') {
131
+ const result = await db.raw(`SELECT kcu.table_name, kcu.column_name FROM information_schema.table_constraints tc JOIN information_schema.key_column_usage kcu ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema WHERE tc.constraint_type = 'PRIMARY KEY' AND tc.table_schema NOT IN ('information_schema', 'pg_catalog')`);
132
+ return extractRows(result);
133
+ }
134
+ if (this.engine === 'mysql') {
135
+ const result = await db.raw(`SELECT TABLE_NAME as table_name, COLUMN_NAME as column_name FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA = DATABASE() AND CONSTRAINT_NAME = 'PRIMARY'`);
136
+ return extractRows(result);
137
+ }
138
+ return [];
139
+ }
140
+ async queryForeignKeys(db) {
141
+ if (this.engine === 'postgresql') {
142
+ const result = await db.raw(`SELECT kcu.table_name, kcu.column_name, ccu.table_name AS referenced_table, ccu.column_name AS referenced_column FROM information_schema.table_constraints tc JOIN information_schema.key_column_usage kcu ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema JOIN information_schema.constraint_column_usage ccu ON ccu.constraint_name = tc.constraint_name AND ccu.table_schema = tc.table_schema WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_schema NOT IN ('information_schema', 'pg_catalog')`);
143
+ return extractRows(result);
144
+ }
145
+ if (this.engine === 'mysql') {
146
+ const result = await db.raw(`SELECT TABLE_NAME as table_name, COLUMN_NAME as column_name, REFERENCED_TABLE_NAME as referenced_table, REFERENCED_COLUMN_NAME as referenced_column FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA = DATABASE() AND REFERENCED_TABLE_NAME IS NOT NULL`);
147
+ return extractRows(result);
148
+ }
149
+ return [];
150
+ }
151
+ async queryIndexes(db) {
152
+ if (this.engine === 'postgresql') {
153
+ const result = await db.raw(`SELECT t.relname as table_name, i.relname as index_name, a.attname as column_name, ix.indisunique as is_unique, ix.indisprimary as is_primary FROM pg_class t JOIN pg_index ix ON t.oid = ix.indrelid JOIN pg_class i ON i.oid = ix.indexrelid JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey) JOIN pg_namespace n ON n.oid = t.relnamespace WHERE n.nspname NOT IN ('pg_catalog', 'information_schema') ORDER BY t.relname, i.relname`);
154
+ return extractRows(result);
155
+ }
156
+ return [];
157
+ }
158
+ }
159
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../../src/adapters/db/provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export interface SqlValidationResult {
2
+ valid: boolean;
3
+ reason?: string;
4
+ }
5
+ /**
6
+ * Validate that a SQL string is read-only.
7
+ * Only SELECT, EXPLAIN, SHOW, DESCRIBE, and WITH...SELECT are allowed.
8
+ */
9
+ export declare function validateSql(sql: string): SqlValidationResult;
10
+ //# sourceMappingURL=sql-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql-validator.d.ts","sourceRoot":"","sources":["../../../src/adapters/db/sql-validator.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,mBAAmB,CAkC5D"}
@@ -0,0 +1,41 @@
1
+ const FORBIDDEN_KEYWORDS = new Set([
2
+ 'INSERT', 'UPDATE', 'DELETE', 'DROP', 'ALTER', 'TRUNCATE',
3
+ 'CREATE', 'GRANT', 'REVOKE', 'EXEC', 'EXECUTE', 'CALL',
4
+ 'MERGE', 'UPSERT', 'REPLACE', 'LOCK', 'UNLOCK',
5
+ ]);
6
+ const ALLOWED_FIRST_KEYWORDS = new Set([
7
+ 'SELECT', 'EXPLAIN', 'SHOW', 'DESCRIBE', 'DESC', 'WITH',
8
+ ]);
9
+ /**
10
+ * Validate that a SQL string is read-only.
11
+ * Only SELECT, EXPLAIN, SHOW, DESCRIBE, and WITH...SELECT are allowed.
12
+ */
13
+ export function validateSql(sql) {
14
+ const trimmed = sql.trim();
15
+ if (!trimmed) {
16
+ return { valid: false, reason: 'Empty query' };
17
+ }
18
+ const upperSql = trimmed.toUpperCase();
19
+ const firstWord = upperSql.split(/[\s(]+/)[0];
20
+ if (!firstWord || !ALLOWED_FIRST_KEYWORDS.has(firstWord)) {
21
+ return { valid: false, reason: `Statement must start with SELECT, EXPLAIN, SHOW, or DESCRIBE. Got: ${firstWord ?? '(empty)'}` };
22
+ }
23
+ if (firstWord === 'WITH') {
24
+ const withoutCtes = upperSql.replace(/WITH\s+[\s\S]*?\)\s*/g, '');
25
+ const afterWith = withoutCtes.trim().split(/[\s(]+/)[0];
26
+ if (afterWith !== 'SELECT') {
27
+ return { valid: false, reason: 'WITH clause must be followed by SELECT' };
28
+ }
29
+ }
30
+ for (const keyword of FORBIDDEN_KEYWORDS) {
31
+ const pattern = new RegExp(`\\b${keyword}\\b`, 'i');
32
+ if (pattern.test(trimmed)) {
33
+ return { valid: false, reason: `Forbidden keyword: ${keyword}` };
34
+ }
35
+ }
36
+ if (/;\s*\S/.test(trimmed)) {
37
+ return { valid: false, reason: 'Multiple statements not allowed' };
38
+ }
39
+ return { valid: true };
40
+ }
41
+ //# sourceMappingURL=sql-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql-validator.js","sourceRoot":"","sources":["../../../src/adapters/db/sql-validator.ts"],"names":[],"mappings":"AAAA,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC;IACjC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU;IACzD,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IACtD,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ;CAC/C,CAAC,CAAC;AAEH,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC;IACrC,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM;CACxD,CAAC,CAAC;AAOH;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAE3B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;IACjD,CAAC;IAED,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IACvC,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAE9C,IAAI,CAAC,SAAS,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;QACzD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,sEAAsE,SAAS,IAAI,SAAS,EAAE,EAAE,CAAC;IAClI,CAAC;IAED,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;QACzB,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAC;QAClE,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QACxD,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;YAC3B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,wCAAwC,EAAE,CAAC;QAC5E,CAAC;IACH,CAAC;IAED,KAAK,MAAM,OAAO,IAAI,kBAAkB,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,MAAM,OAAO,KAAK,EAAE,GAAG,CAAC,CAAC;QACpD,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC1B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,sBAAsB,OAAO,EAAE,EAAE,CAAC;QACnE,CAAC;IACH,CAAC;IAED,IAAI,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,iCAAiC,EAAE,CAAC;IACrE,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACzB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/adapters/postgres/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAEzB;;GAEG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CA2Q/D"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/adapters/postgres/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAEzB;;GAEG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAsU/D"}
@@ -210,6 +210,56 @@ export async function ensureSchema(pool) {
210
210
  await pool.query(`ALTER TABLE commits ADD COLUMN IF NOT EXISTS search_vector tsvector`);
211
211
  await pool.query(`ALTER TABLE pull_requests ADD COLUMN IF NOT EXISTS search_vector tsvector`);
212
212
  await pool.query(`ALTER TABLE releases ADD COLUMN IF NOT EXISTS search_vector tsvector`);
213
+ await pool.query(`
214
+ CREATE TABLE IF NOT EXISTS db_tables (
215
+ id SERIAL PRIMARY KEY,
216
+ source_name TEXT NOT NULL,
217
+ table_schema TEXT,
218
+ table_name TEXT NOT NULL,
219
+ row_count BIGINT,
220
+ size_bytes BIGINT,
221
+ pulled_at TIMESTAMP DEFAULT NOW(),
222
+ UNIQUE(source_name, table_schema, table_name)
223
+ )
224
+ `);
225
+ await pool.query(`
226
+ CREATE TABLE IF NOT EXISTS db_columns (
227
+ id SERIAL PRIMARY KEY,
228
+ source_name TEXT NOT NULL,
229
+ table_schema TEXT,
230
+ table_name TEXT NOT NULL,
231
+ column_name TEXT NOT NULL,
232
+ data_type TEXT,
233
+ is_nullable BOOLEAN DEFAULT TRUE,
234
+ default_value TEXT,
235
+ is_primary_key BOOLEAN DEFAULT FALSE,
236
+ ordinal_position INTEGER,
237
+ UNIQUE(source_name, table_schema, table_name, column_name)
238
+ )
239
+ `);
240
+ await pool.query(`
241
+ CREATE TABLE IF NOT EXISTS db_foreign_keys (
242
+ id SERIAL PRIMARY KEY,
243
+ source_name TEXT NOT NULL,
244
+ table_name TEXT NOT NULL,
245
+ column_name TEXT NOT NULL,
246
+ referenced_table TEXT NOT NULL,
247
+ referenced_column TEXT NOT NULL,
248
+ UNIQUE(source_name, table_name, column_name, referenced_table, referenced_column)
249
+ )
250
+ `);
251
+ await pool.query(`
252
+ CREATE TABLE IF NOT EXISTS db_indexes (
253
+ id SERIAL PRIMARY KEY,
254
+ source_name TEXT NOT NULL,
255
+ table_name TEXT NOT NULL,
256
+ index_name TEXT NOT NULL,
257
+ columns TEXT[],
258
+ is_unique BOOLEAN DEFAULT FALSE,
259
+ is_primary BOOLEAN DEFAULT FALSE,
260
+ UNIQUE(source_name, table_name, index_name)
261
+ )
262
+ `);
213
263
  const indexes = [
214
264
  'CREATE INDEX IF NOT EXISTS idx_issues_project ON issues(project_key)',
215
265
  'CREATE INDEX IF NOT EXISTS idx_issues_status ON issues(status)',
@@ -247,6 +297,11 @@ export async function ensureSchema(pool) {
247
297
  'CREATE INDEX IF NOT EXISTS idx_releases_repo ON releases(repo_full_name)',
248
298
  'CREATE INDEX IF NOT EXISTS idx_releases_tag ON releases(tag_name)',
249
299
  'CREATE INDEX IF NOT EXISTS idx_releases_search ON releases USING GIN(search_vector)',
300
+ 'CREATE INDEX IF NOT EXISTS idx_db_tables_source ON db_tables(source_name)',
301
+ 'CREATE INDEX IF NOT EXISTS idx_db_columns_source ON db_columns(source_name)',
302
+ 'CREATE INDEX IF NOT EXISTS idx_db_columns_table ON db_columns(source_name, table_name)',
303
+ 'CREATE INDEX IF NOT EXISTS idx_db_fk_source ON db_foreign_keys(source_name)',
304
+ 'CREATE INDEX IF NOT EXISTS idx_db_indexes_source ON db_indexes(source_name)',
250
305
  ];
251
306
  for (const idx of indexes) {
252
307
  await pool.query(idx);
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/adapters/postgres/schema.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAa;IAC9C,MAAM,IAAI,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAE1D,MAAM,IAAI,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoChB,CAAC,CAAC;IAEH,MAAM,IAAI,CAAC,KAAK,CAAC;;;;;;;;;;GAUhB,CAAC,CAAC;IAEH,MAAM,IAAI,CAAC,KAAK,CAAC;;;;;;;;;;GAUhB,CAAC,CAAC;IAEH,MAAM,IAAI,CAAC,KAAK,CAAC;;;;;;;;;;GAUhB,CAAC,CAAC;IAEH,MAAM,IAAI,CAAC,KAAK,CAAC;;;;;;;;GAQhB,CAAC,CAAC;IAEH,MAAM,IAAI,CAAC,KAAK,CAAC;;;;;;;;;;;;GAYhB,CAAC,CAAC;IAEH,MAAM,IAAI,CAAC,KAAK,CAAC;;;;;;;;;GAShB,CAAC,CAAC;IAEH,MAAM,IAAI,CAAC,KAAK,CAAC;;;;;;GAMhB,CAAC,CAAC;IAEH,MAAM,IAAI,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBhB,CAAC,CAAC;IAEH,MAAM,IAAI,CAAC,KAAK,CAAC;;;;;;;;;;;GAWhB,CAAC,CAAC;IAEH,MAAM,IAAI,CAAC,KAAK,CAAC;;;;;;;;;;;;;GAahB,CAAC,CAAC;IAEH,MAAM,IAAI,CAAC,KAAK,CAAC;;;;;;;;;;GAUhB,CAAC,CAAC;IAEH,MAAM,IAAI,CAAC,KAAK,CAAC;;;;;;;GAOhB,CAAC,CAAC;IAEH,MAAM,IAAI,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;GAiBhB,CAAC,CAAC;IAEH,MAAM,IAAI,CAAC,KAAK,CAAC,uEAAuE,CAAC,CAAC;IAC1F,MAAM,IAAI,CAAC,KAAK,CAAC,wEAAwE,CAAC,CAAC;IAC3F,MAAM,IAAI,CAAC,KAAK,CAAC,gEAAgE,CAAC,CAAC;IACnF,MAAM,IAAI,CAAC,KAAK,CAAC,8DAA8D,CAAC,CAAC;IACjF,MAAM,IAAI,CAAC,KAAK,CAAC,8DAA8D,CAAC,CAAC;IACjF,MAAM,IAAI,CAAC,KAAK,CAAC,oEAAoE,CAAC,CAAC;IACvF,MAAM,IAAI,CAAC,KAAK,CAAC,qEAAqE,CAAC,CAAC;IACxF,MAAM,IAAI,CAAC,KAAK,CAAC,2EAA2E,CAAC,CAAC;IAC9F,MAAM,IAAI,CAAC,KAAK,CAAC,sEAAsE,CAAC,CAAC;IAEzF,MAAM,OAAO,GAAG;QACd,sEAAsE;QACtE,gEAAgE;QAChE,kEAAkE;QAClE,oEAAoE;QACpE,kEAAkE;QAClE,kEAAkE;QAClE,iFAAiF;QACjF,iFAAiF;QACjF,yEAAyE;QACzE,0EAA0E;QAC1E,8EAA8E;QAC9E,0EAA0E;QAC1E,wEAAwE;QACxE,wEAAwE;QACxE,kEAAkE;QAClE,sEAAsE;QACtE,mEAAmE;QACnE,mFAAmF;QACnF,+EAA+E;QAC/E,6EAA6E;QAC7E,kFAAkF;QAClF,0EAA0E;QAC1E,kEAAkE;QAClE,oEAAoE;QACpE,uEAAuE;QACvE,yEAAyE;QACzE,iFAAiF;QACjF,qFAAqF;QACrF,uFAAuF;QACvF,yFAAyF;QACzF,mFAAmF;QACnF,qEAAqE;QACrE,0EAA0E;QAC1E,0EAA0E;QAC1E,mEAAmE;QACnE,qFAAqF;KACtF,CAAC;IAEF,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/adapters/postgres/schema.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ import type { IStorage, QueryResult } from '../../core/ports/storage.js';
2
2
  import type { IssueBatch } from '../../core/types/index.js';
3
3
  import type { CommitBatch } from '../../core/types/git.js';
4
4
  import type { GitHubBatch, Release } from '../../core/types/github.js';
5
+ import type { DbSchemaBatch } from '../../core/types/database.js';
5
6
  import { type DbConfig } from './connection.js';
6
7
  /**
7
8
  * PostgreSQL adapter — implements IStorage.
@@ -27,6 +28,8 @@ export declare class PostgresStorage implements IStorage {
27
28
  similarity: number;
28
29
  }[]>;
29
30
  query(sql: string, params: unknown[]): Promise<QueryResult>;
31
+ saveDbSchemaBatch(batch: DbSchemaBatch, sourceName: string): Promise<void>;
32
+ deleteDbSchema(sourceName: string): Promise<void>;
30
33
  close(): Promise<void>;
31
34
  }
32
35
  //# sourceMappingURL=storage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/adapters/postgres/storage.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAG5D;;;;GAIG;AACH,qBAAa,eAAgB,YAAW,QAAQ;IAC9C,QAAQ,CAAC,IAAI,gBAAgB;IAC7B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAU;gBAEnB,MAAM,EAAE,QAAQ;IAItB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAsH3C,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAyDlD,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAWzD,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAW1D,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAmHlD,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA8ChD,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAW5D,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAWxD,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAOhE,cAAc,CAClB,MAAM,EAAE,MAAM,EAAE,EAChB,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAyBhD,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC;IAK3D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/adapters/postgres/storage.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAG5D;;;;GAIG;AACH,qBAAa,eAAgB,YAAW,QAAQ;IAC9C,QAAQ,CAAC,IAAI,gBAAgB;IAC7B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAU;gBAEnB,MAAM,EAAE,QAAQ;IAItB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAsH3C,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAyDlD,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAWzD,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAW1D,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAmHlD,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA8ChD,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAW5D,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAWxD,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAOhE,cAAc,CAClB,MAAM,EAAE,MAAM,EAAE,EAChB,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAyBhD,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC;IAK3D,iBAAiB,CAAC,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA6D1E,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}