@javalabs/prisma-client 1.0.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 (150) hide show
  1. package/README.md +220 -0
  2. package/dist/index.d.ts +7 -0
  3. package/dist/index.js +34 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/prisma-factory.service.d.ts +9 -0
  6. package/dist/prisma-factory.service.js +47 -0
  7. package/dist/prisma-factory.service.js.map +1 -0
  8. package/dist/prisma.module.d.ts +2 -0
  9. package/dist/prisma.module.js +23 -0
  10. package/dist/prisma.module.js.map +1 -0
  11. package/dist/prisma.service.d.ts +6 -0
  12. package/dist/prisma.service.js +27 -0
  13. package/dist/prisma.service.js.map +1 -0
  14. package/dist/scripts/create-tenant-schemas.d.ts +1 -0
  15. package/dist/scripts/create-tenant-schemas.js +117 -0
  16. package/dist/scripts/create-tenant-schemas.js.map +1 -0
  17. package/dist/scripts/data-migration/batch-migrator.d.ts +25 -0
  18. package/dist/scripts/data-migration/batch-migrator.js +333 -0
  19. package/dist/scripts/data-migration/batch-migrator.js.map +1 -0
  20. package/dist/scripts/data-migration/data-transformer.d.ts +17 -0
  21. package/dist/scripts/data-migration/data-transformer.js +242 -0
  22. package/dist/scripts/data-migration/data-transformer.js.map +1 -0
  23. package/dist/scripts/data-migration/db-connector.d.ts +7 -0
  24. package/dist/scripts/data-migration/db-connector.js +58 -0
  25. package/dist/scripts/data-migration/db-connector.js.map +1 -0
  26. package/dist/scripts/data-migration/dependency-manager.d.ts +9 -0
  27. package/dist/scripts/data-migration/dependency-manager.js +86 -0
  28. package/dist/scripts/data-migration/dependency-manager.js.map +1 -0
  29. package/dist/scripts/data-migration/dependency-resolver.d.ts +18 -0
  30. package/dist/scripts/data-migration/dependency-resolver.js +251 -0
  31. package/dist/scripts/data-migration/dependency-resolver.js.map +1 -0
  32. package/dist/scripts/data-migration/entity-discovery.d.ts +11 -0
  33. package/dist/scripts/data-migration/entity-discovery.js +152 -0
  34. package/dist/scripts/data-migration/entity-discovery.js.map +1 -0
  35. package/dist/scripts/data-migration/foreign-key-manager.d.ts +17 -0
  36. package/dist/scripts/data-migration/foreign-key-manager.js +70 -0
  37. package/dist/scripts/data-migration/foreign-key-manager.js.map +1 -0
  38. package/dist/scripts/data-migration/migration-phases.d.ts +5 -0
  39. package/dist/scripts/data-migration/migration-phases.js +55 -0
  40. package/dist/scripts/data-migration/migration-phases.js.map +1 -0
  41. package/dist/scripts/data-migration/migration-tool.d.ts +29 -0
  42. package/dist/scripts/data-migration/migration-tool.js +250 -0
  43. package/dist/scripts/data-migration/migration-tool.js.map +1 -0
  44. package/dist/scripts/data-migration/phase-generator.d.ts +15 -0
  45. package/dist/scripts/data-migration/phase-generator.js +187 -0
  46. package/dist/scripts/data-migration/phase-generator.js.map +1 -0
  47. package/dist/scripts/data-migration/schema-utils.d.ts +18 -0
  48. package/dist/scripts/data-migration/schema-utils.js +164 -0
  49. package/dist/scripts/data-migration/schema-utils.js.map +1 -0
  50. package/dist/scripts/data-migration/tenant-migrator.d.ts +15 -0
  51. package/dist/scripts/data-migration/tenant-migrator.js +110 -0
  52. package/dist/scripts/data-migration/tenant-migrator.js.map +1 -0
  53. package/dist/scripts/data-migration/typecast-manager.d.ts +5 -0
  54. package/dist/scripts/data-migration/typecast-manager.js +35 -0
  55. package/dist/scripts/data-migration/typecast-manager.js.map +1 -0
  56. package/dist/scripts/data-migration/types.d.ts +34 -0
  57. package/dist/scripts/data-migration/types.js +3 -0
  58. package/dist/scripts/data-migration/types.js.map +1 -0
  59. package/dist/scripts/data-migration.d.ts +22 -0
  60. package/dist/scripts/data-migration.js +593 -0
  61. package/dist/scripts/data-migration.js.map +1 -0
  62. package/dist/scripts/drop-database.d.ts +10 -0
  63. package/dist/scripts/drop-database.js +81 -0
  64. package/dist/scripts/drop-database.js.map +1 -0
  65. package/dist/scripts/error-handler.d.ts +12 -0
  66. package/dist/scripts/error-handler.js +82 -0
  67. package/dist/scripts/error-handler.js.map +1 -0
  68. package/dist/scripts/fix-data-types.d.ts +10 -0
  69. package/dist/scripts/fix-data-types.js +185 -0
  70. package/dist/scripts/fix-data-types.js.map +1 -0
  71. package/dist/scripts/fix-enum-values.d.ts +17 -0
  72. package/dist/scripts/fix-enum-values.js +234 -0
  73. package/dist/scripts/fix-enum-values.js.map +1 -0
  74. package/dist/scripts/fix-schema-discrepancies.d.ts +21 -0
  75. package/dist/scripts/fix-schema-discrepancies.js +240 -0
  76. package/dist/scripts/fix-schema-discrepancies.js.map +1 -0
  77. package/dist/scripts/migrate-schema-structure.d.ts +1 -0
  78. package/dist/scripts/migrate-schema-structure.js +76 -0
  79. package/dist/scripts/migrate-schema-structure.js.map +1 -0
  80. package/dist/scripts/post-migration-validator.d.ts +21 -0
  81. package/dist/scripts/post-migration-validator.js +341 -0
  82. package/dist/scripts/post-migration-validator.js.map +1 -0
  83. package/dist/scripts/pre-migration-validator.d.ts +25 -0
  84. package/dist/scripts/pre-migration-validator.js +491 -0
  85. package/dist/scripts/pre-migration-validator.js.map +1 -0
  86. package/dist/scripts/reset-database.d.ts +17 -0
  87. package/dist/scripts/reset-database.js +202 -0
  88. package/dist/scripts/reset-database.js.map +1 -0
  89. package/dist/scripts/retry-failed-migrations.d.ts +14 -0
  90. package/dist/scripts/retry-failed-migrations.js +301 -0
  91. package/dist/scripts/retry-failed-migrations.js.map +1 -0
  92. package/dist/scripts/run-migration.d.ts +1 -0
  93. package/dist/scripts/run-migration.js +525 -0
  94. package/dist/scripts/run-migration.js.map +1 -0
  95. package/dist/scripts/schema-sync.d.ts +1 -0
  96. package/dist/scripts/schema-sync.js +85 -0
  97. package/dist/scripts/schema-sync.js.map +1 -0
  98. package/dist/scripts/sync-enum-types.d.ts +13 -0
  99. package/dist/scripts/sync-enum-types.js +139 -0
  100. package/dist/scripts/sync-enum-types.js.map +1 -0
  101. package/dist/scripts/sync-enum-values.d.ts +20 -0
  102. package/dist/scripts/sync-enum-values.js +336 -0
  103. package/dist/scripts/sync-enum-values.js.map +1 -0
  104. package/dist/scripts/truncate-database.d.ts +10 -0
  105. package/dist/scripts/truncate-database.js +100 -0
  106. package/dist/scripts/truncate-database.js.map +1 -0
  107. package/dist/scripts/verify-migration-setup.d.ts +11 -0
  108. package/dist/scripts/verify-migration-setup.js +120 -0
  109. package/dist/scripts/verify-migration-setup.js.map +1 -0
  110. package/dist/tsconfig.tsbuildinfo +1 -0
  111. package/migration-config-public.json +95 -0
  112. package/migration-config.json +95 -0
  113. package/package.json +33 -0
  114. package/prisma/migrations/migration_lock.toml +3 -0
  115. package/prisma/schema.prisma +360 -0
  116. package/src/index.ts +23 -0
  117. package/src/prisma-factory.service.ts +41 -0
  118. package/src/prisma.module.ts +10 -0
  119. package/src/prisma.service.ts +17 -0
  120. package/src/scripts/create-tenant-schemas.ts +146 -0
  121. package/src/scripts/data-migration/batch-migrator.ts +569 -0
  122. package/src/scripts/data-migration/data-transformer.ts +377 -0
  123. package/src/scripts/data-migration/db-connector.ts +67 -0
  124. package/src/scripts/data-migration/dependency-resolver.ts +319 -0
  125. package/src/scripts/data-migration/entity-discovery.ts +197 -0
  126. package/src/scripts/data-migration/foreign-key-manager.ts +95 -0
  127. package/src/scripts/data-migration/migration-tool.ts +357 -0
  128. package/src/scripts/data-migration/schema-utils.ts +186 -0
  129. package/src/scripts/data-migration/tenant-migrator.ts +194 -0
  130. package/src/scripts/data-migration/typecast-manager.ts +38 -0
  131. package/src/scripts/data-migration/types.ts +40 -0
  132. package/src/scripts/drop-database.ts +105 -0
  133. package/src/scripts/dump-source-db.sh +62 -0
  134. package/src/scripts/dumps/source_dump_20250413_112626.sql +1527 -0
  135. package/src/scripts/error-handler.ts +118 -0
  136. package/src/scripts/fix-data-types.ts +242 -0
  137. package/src/scripts/fix-enum-values.ts +357 -0
  138. package/src/scripts/fix-schema-discrepancies.ts +318 -0
  139. package/src/scripts/migrate-schema-structure.ts +90 -0
  140. package/src/scripts/post-migration-validator.ts +427 -0
  141. package/src/scripts/pre-migration-validator.ts +611 -0
  142. package/src/scripts/reset-database.ts +264 -0
  143. package/src/scripts/retry-failed-migrations.ts +416 -0
  144. package/src/scripts/run-migration.ts +691 -0
  145. package/src/scripts/schema-sync.ts +129 -0
  146. package/src/scripts/sync-enum-types.ts +171 -0
  147. package/src/scripts/sync-enum-values.ts +563 -0
  148. package/src/scripts/truncate-database.ts +124 -0
  149. package/src/scripts/verify-migration-setup.ts +136 -0
  150. package/tsconfig.json +18 -0
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DatabaseConnector = void 0;
4
+ const client_1 = require("@prisma/client");
5
+ const pg = require("pg");
6
+ const dotenv = require("dotenv");
7
+ dotenv.config();
8
+ class DatabaseConnector {
9
+ static createConnections() {
10
+ const sourcePool = new pg.Pool({
11
+ connectionString: process.env.SOURCE_DATABASE_URL,
12
+ });
13
+ const targetPool = new pg.Pool({
14
+ connectionString: process.env.DATABASE_URL,
15
+ });
16
+ const sourcePrisma = new client_1.PrismaClient({
17
+ datasources: {
18
+ db: {
19
+ url: process.env.SOURCE_DATABASE_URL,
20
+ },
21
+ },
22
+ });
23
+ const targetPrisma = new client_1.PrismaClient({
24
+ datasources: {
25
+ db: {
26
+ url: process.env.DATABASE_URL,
27
+ },
28
+ },
29
+ });
30
+ return {
31
+ sourcePrisma,
32
+ targetPrisma,
33
+ sourcePool,
34
+ targetPool,
35
+ };
36
+ }
37
+ static createTenantPrismaClient(tenantId) {
38
+ return new client_1.PrismaClient({
39
+ datasources: {
40
+ db: {
41
+ url: `${process.env.DATABASE_URL}?schema=${tenantId}`,
42
+ },
43
+ },
44
+ transactionOptions: {
45
+ maxWait: 120000,
46
+ timeout: 120000,
47
+ },
48
+ });
49
+ }
50
+ static async cleanup(connections) {
51
+ await connections.sourcePrisma.$disconnect();
52
+ await connections.targetPrisma.$disconnect();
53
+ await connections.sourcePool.end();
54
+ await connections.targetPool.end();
55
+ }
56
+ }
57
+ exports.DatabaseConnector = DatabaseConnector;
58
+ //# sourceMappingURL=db-connector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-connector.js","sourceRoot":"","sources":["../../../src/scripts/data-migration/db-connector.ts"],"names":[],"mappings":";;;AAAA,2CAA8C;AAC9C,yBAAyB;AACzB,iCAAiC;AAGjC,MAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,MAAa,iBAAiB;IAC5B,MAAM,CAAC,iBAAiB;QAEtB,MAAM,UAAU,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC;YAC7B,gBAAgB,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB;SAClD,CAAC,CAAC;QAGH,MAAM,UAAU,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC;YAC7B,gBAAgB,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY;SAC3C,CAAC,CAAC;QAGH,MAAM,YAAY,GAAG,IAAI,qBAAY,CAAC;YACpC,WAAW,EAAE;gBACX,EAAE,EAAE;oBACF,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB;iBACrC;aACF;SACF,CAAC,CAAC;QAGH,MAAM,YAAY,GAAG,IAAI,qBAAY,CAAC;YACpC,WAAW,EAAE;gBACX,EAAE,EAAE;oBACF,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY;iBAC9B;aACF;SACF,CAAC,CAAC;QAEH,OAAO;YACL,YAAY;YACZ,YAAY;YACZ,UAAU;YACV,UAAU;SACX,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,wBAAwB,CAAC,QAAgB;QAC9C,OAAO,IAAI,qBAAY,CAAC;YACtB,WAAW,EAAE;gBACX,EAAE,EAAE;oBACF,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,WAAW,QAAQ,EAAE;iBACtD;aACF;YAED,kBAAkB,EAAE;gBAClB,OAAO,EAAE,MAAM;gBACf,OAAO,EAAE,MAAM;aAChB;SACF,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,WAAgC;QACnD,MAAM,WAAW,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC;QAC7C,MAAM,WAAW,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC;QAC7C,MAAM,WAAW,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC;QACnC,MAAM,WAAW,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC;IACrC,CAAC;CACF;AA3DD,8CA2DC"}
@@ -0,0 +1,9 @@
1
+ import { Pool } from "pg";
2
+ import { EntityType } from "./types";
3
+ export declare class DependencyManager {
4
+ private readonly targetPool;
5
+ private readonly logger;
6
+ constructor(targetPool: Pool);
7
+ orderEntitiesByDependency(entities: EntityType[], schemaName: string): Promise<EntityType[]>;
8
+ private buildDependencyMap;
9
+ }
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DependencyManager = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ class DependencyManager {
6
+ constructor(targetPool) {
7
+ this.targetPool = targetPool;
8
+ this.logger = new common_1.Logger("DependencyManager");
9
+ }
10
+ async orderEntitiesByDependency(entities, schemaName) {
11
+ try {
12
+ const dependencyMap = await this.buildDependencyMap(schemaName);
13
+ const graph = {};
14
+ for (const entity of entities) {
15
+ graph[entity.name] = [];
16
+ }
17
+ for (const [table, dependencies] of Object.entries(dependencyMap)) {
18
+ if (graph[table]) {
19
+ graph[table] = dependencies.filter(dep => graph[dep] !== undefined);
20
+ }
21
+ }
22
+ const visited = new Set();
23
+ const temp = new Set();
24
+ const order = [];
25
+ const visit = (node) => {
26
+ if (temp.has(node)) {
27
+ return;
28
+ }
29
+ if (!visited.has(node)) {
30
+ temp.add(node);
31
+ for (const neighbor of graph[node]) {
32
+ visit(neighbor);
33
+ }
34
+ temp.delete(node);
35
+ visited.add(node);
36
+ order.push(node);
37
+ }
38
+ };
39
+ for (const node of Object.keys(graph)) {
40
+ if (!visited.has(node)) {
41
+ visit(node);
42
+ }
43
+ }
44
+ order.reverse();
45
+ const orderedEntities = order
46
+ .map(name => entities.find(e => e.name === name))
47
+ .filter((e) => e !== undefined);
48
+ return orderedEntities;
49
+ }
50
+ catch (error) {
51
+ this.logger.error(`Error ordering entities by dependency: ${error.message}`);
52
+ return entities;
53
+ }
54
+ }
55
+ async buildDependencyMap(schemaName) {
56
+ const query = `
57
+ SELECT
58
+ tc.table_name,
59
+ ccu.table_name AS referenced_table
60
+ FROM
61
+ information_schema.table_constraints tc
62
+ JOIN information_schema.constraint_column_usage ccu
63
+ ON ccu.constraint_name = tc.constraint_name
64
+ AND ccu.table_schema = tc.table_schema
65
+ WHERE
66
+ tc.constraint_type = 'FOREIGN KEY'
67
+ AND tc.table_schema = $1
68
+ GROUP BY tc.table_name, ccu.table_name;
69
+ `;
70
+ const { rows } = await this.targetPool.query(query, [schemaName]);
71
+ const dependencyMap = {};
72
+ for (const row of rows) {
73
+ const table = row.table_name;
74
+ const referencedTable = row.referenced_table;
75
+ if (!dependencyMap[table]) {
76
+ dependencyMap[table] = [];
77
+ }
78
+ if (table !== referencedTable) {
79
+ dependencyMap[table].push(referencedTable);
80
+ }
81
+ }
82
+ return dependencyMap;
83
+ }
84
+ }
85
+ exports.DependencyManager = DependencyManager;
86
+ //# sourceMappingURL=dependency-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-manager.js","sourceRoot":"","sources":["../../../src/scripts/data-migration/dependency-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import { Pool } from "pg";
2
+ export declare class DependencyResolver {
3
+ private readonly sourcePool;
4
+ private readonly targetPool;
5
+ private readonly logger;
6
+ private dependencyGraph;
7
+ constructor(sourcePool: Pool, targetPool: Pool);
8
+ analyzeDependencies(): Promise<string[]>;
9
+ private getManualDependencies;
10
+ private getTables;
11
+ private getForeignKeys;
12
+ private inferTableFromEnum;
13
+ private inferTableFromArrayColumn;
14
+ private extractJsonReferences;
15
+ private inferTableNameFromColumn;
16
+ private parseTableComment;
17
+ private assignLevels;
18
+ }
@@ -0,0 +1,251 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DependencyResolver = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ class DependencyResolver {
6
+ constructor(sourcePool, targetPool) {
7
+ this.sourcePool = sourcePool;
8
+ this.targetPool = targetPool;
9
+ this.logger = new common_1.Logger("DependencyResolver");
10
+ this.dependencyGraph = new Map();
11
+ }
12
+ async analyzeDependencies() {
13
+ try {
14
+ const tables = await this.getTables();
15
+ for (const table of tables) {
16
+ const foreignKeys = await this.getForeignKeys(table);
17
+ const manualDependencies = this.getManualDependencies(table);
18
+ const allDependencies = [
19
+ ...new Set([...foreignKeys, ...manualDependencies]),
20
+ ];
21
+ this.dependencyGraph.set(table, {
22
+ table,
23
+ dependencies: allDependencies,
24
+ });
25
+ }
26
+ this.assignLevels();
27
+ const sortedTables = Array.from(this.dependencyGraph.values())
28
+ .sort((a, b) => (a.level || 0) - (b.level || 0))
29
+ .map((dep) => dep.table);
30
+ this.logger.log(`Migration order: ${sortedTables.join(" -> ")}`);
31
+ return sortedTables;
32
+ }
33
+ catch (error) {
34
+ this.logger.error(`Error analyzing dependencies: ${error.message}`);
35
+ throw error;
36
+ }
37
+ }
38
+ getManualDependencies(tableName) {
39
+ const manualDependencyMap = {
40
+ api_keys: ["users", "providers"],
41
+ balances: ["users"],
42
+ customers: ["users"],
43
+ global_user_transactions: ["users", "providers", "transactions"],
44
+ invoices: ["transactions"],
45
+ credit_requests: ["users", "invoices"],
46
+ notifications: ["users", "transactions"],
47
+ pending_references: ["users", "providers"],
48
+ daily_logs: ["transactions"],
49
+ transaction_updates: ["transactions"],
50
+ toku: ["transactions"],
51
+ providers: ["countries"],
52
+ users: ["countries"],
53
+ };
54
+ return manualDependencyMap[tableName] || [];
55
+ }
56
+ async getTables() {
57
+ const query = `
58
+ SELECT table_name
59
+ FROM information_schema.tables
60
+ WHERE table_schema = 'public'
61
+ AND table_type = 'BASE TABLE'
62
+ AND table_name NOT IN ('_prisma_migrations', 'schema_migrations')
63
+ `;
64
+ const result = await this.sourcePool.query(query);
65
+ return result.rows.map((row) => row.table_name);
66
+ }
67
+ async getForeignKeys(tableName) {
68
+ try {
69
+ const foreignKeyQuery = `
70
+ SELECT DISTINCT
71
+ ccu.table_name AS foreign_table_name,
72
+ kcu.column_name AS column_name
73
+ FROM
74
+ information_schema.table_constraints AS tc
75
+ JOIN information_schema.constraint_column_usage AS ccu
76
+ ON ccu.constraint_name = tc.constraint_name
77
+ JOIN information_schema.key_column_usage AS kcu
78
+ ON kcu.constraint_name = tc.constraint_name
79
+ WHERE
80
+ tc.constraint_type = 'FOREIGN KEY'
81
+ AND tc.table_name = $1
82
+ AND tc.table_schema = 'public'
83
+ `;
84
+ const implicitDependencyQuery = `
85
+ SELECT DISTINCT
86
+ c.column_name,
87
+ c.udt_name,
88
+ c.column_default,
89
+ c.data_type
90
+ FROM
91
+ information_schema.columns c
92
+ WHERE
93
+ c.table_schema = 'public'
94
+ AND c.table_name = $1
95
+ AND (
96
+ -- Common ID patterns
97
+ c.column_name LIKE '%_id'
98
+ OR c.column_name LIKE '%_ids'
99
+ OR c.column_name LIKE 'id_%'
100
+ -- Reference patterns
101
+ OR c.column_name LIKE '%_ref%'
102
+ OR c.column_name LIKE '%_key'
103
+ OR c.column_name LIKE '%_code'
104
+ -- Relationship patterns
105
+ OR c.column_name LIKE '%_by'
106
+ OR c.column_name LIKE '%_to'
107
+ OR c.column_name LIKE '%_from'
108
+ OR c.column_name LIKE 'parent_%'
109
+ OR c.column_name LIKE 'child_%'
110
+ -- JSON/JSONB columns that might contain references
111
+ OR (c.data_type IN ('json', 'jsonb') AND c.column_name LIKE '%_data')
112
+ -- Array columns that might contain IDs
113
+ OR (c.data_type = 'ARRAY' AND c.column_name LIKE '%_ids')
114
+ -- Enum columns that might indicate relationships
115
+ OR (c.udt_name LIKE 'enum_%' AND c.column_name LIKE '%_type')
116
+ )
117
+ `;
118
+ const referencedTablesQuery = `
119
+ SELECT DISTINCT
120
+ obj_description(c.table_name::regclass, 'pg_class') as table_comment
121
+ FROM
122
+ information_schema.columns c
123
+ WHERE
124
+ c.table_schema = 'public'
125
+ AND c.table_name = $1
126
+ `;
127
+ const [fkResult, implicitResult, referencedResult] = await Promise.all([
128
+ this.sourcePool.query(foreignKeyQuery, [tableName]),
129
+ this.sourcePool.query(implicitDependencyQuery, [tableName]),
130
+ this.sourcePool.query(referencedTablesQuery, [tableName]),
131
+ ]);
132
+ const allDependencies = new Set();
133
+ fkResult.rows.forEach((row) => allDependencies.add(row.foreign_table_name));
134
+ implicitResult.rows.forEach((row) => {
135
+ const columnName = row.column_name;
136
+ const potentialTable = this.inferTableNameFromColumn(columnName);
137
+ if (potentialTable) {
138
+ allDependencies.add(potentialTable);
139
+ }
140
+ });
141
+ referencedResult.rows.forEach((row) => {
142
+ if (row.table_comment) {
143
+ const referencedTables = this.parseTableComment(row.table_comment);
144
+ referencedTables.forEach((table) => allDependencies.add(table));
145
+ }
146
+ });
147
+ implicitResult.rows.forEach((row) => {
148
+ var _a;
149
+ if (row.data_type === "json" || row.data_type === "jsonb") {
150
+ const potentialRefs = this.extractJsonReferences(row.column_name);
151
+ potentialRefs.forEach((ref) => allDependencies.add(ref));
152
+ }
153
+ if ((_a = row.udt_name) === null || _a === void 0 ? void 0 : _a.startsWith("enum_")) {
154
+ const enumTable = this.inferTableFromEnum(row.udt_name);
155
+ if (enumTable)
156
+ allDependencies.add(enumTable);
157
+ }
158
+ if (row.data_type === "ARRAY") {
159
+ const arrayTable = this.inferTableFromArrayColumn(row.column_name);
160
+ if (arrayTable)
161
+ allDependencies.add(arrayTable);
162
+ }
163
+ });
164
+ return Array.from(allDependencies);
165
+ }
166
+ catch (error) {
167
+ this.logger.error(`Error getting dependencies for ${tableName}: ${error.message}`);
168
+ return [];
169
+ }
170
+ }
171
+ inferTableFromEnum(enumType) {
172
+ const parts = enumType.split("_");
173
+ if (parts.length > 1) {
174
+ return parts[1];
175
+ }
176
+ return null;
177
+ }
178
+ inferTableFromArrayColumn(columnName) {
179
+ if (columnName.endsWith("_ids")) {
180
+ return columnName.slice(0, -4) + "s";
181
+ }
182
+ return null;
183
+ }
184
+ extractJsonReferences(columnName) {
185
+ const refs = [];
186
+ const parts = columnName.split("_");
187
+ if (parts.length > 1) {
188
+ const potentialTable = parts[0] + "s";
189
+ refs.push(potentialTable);
190
+ }
191
+ return refs;
192
+ }
193
+ inferTableNameFromColumn(columnName) {
194
+ const suffixes = ["_id", "_by", "_ref", "_fk"];
195
+ let tableName = columnName;
196
+ for (const suffix of suffixes) {
197
+ if (tableName.endsWith(suffix)) {
198
+ tableName = tableName.slice(0, -suffix.length);
199
+ break;
200
+ }
201
+ }
202
+ if (!tableName.endsWith("s")) {
203
+ tableName += "s";
204
+ }
205
+ return tableName;
206
+ }
207
+ parseTableComment(comment) {
208
+ const referencesMatch = comment.match(/References:\s*([^;]+)/i);
209
+ if (referencesMatch) {
210
+ return referencesMatch[1]
211
+ .split(",")
212
+ .map((table) => table.trim())
213
+ .filter((table) => table.length > 0);
214
+ }
215
+ return [];
216
+ }
217
+ assignLevels() {
218
+ const visited = new Set();
219
+ const visiting = new Set();
220
+ const visit = (tableName, level = 0) => {
221
+ var _a;
222
+ if (visiting.has(tableName)) {
223
+ this.logger.warn(`Circular dependency detected involving table: ${tableName}`);
224
+ return level;
225
+ }
226
+ if (visited.has(tableName)) {
227
+ return ((_a = this.dependencyGraph.get(tableName)) === null || _a === void 0 ? void 0 : _a.level) || 0;
228
+ }
229
+ visiting.add(tableName);
230
+ const node = this.dependencyGraph.get(tableName);
231
+ if (!node)
232
+ return level;
233
+ let maxDepLevel = level;
234
+ for (const dep of node.dependencies) {
235
+ const depLevel = visit(dep, level + 1);
236
+ maxDepLevel = Math.max(maxDepLevel, depLevel + 1);
237
+ }
238
+ node.level = maxDepLevel;
239
+ visited.add(tableName);
240
+ visiting.delete(tableName);
241
+ return maxDepLevel;
242
+ };
243
+ for (const tableName of this.dependencyGraph.keys()) {
244
+ if (!visited.has(tableName)) {
245
+ visit(tableName);
246
+ }
247
+ }
248
+ }
249
+ }
250
+ exports.DependencyResolver = DependencyResolver;
251
+ //# sourceMappingURL=dependency-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-resolver.js","sourceRoot":"","sources":["../../../src/scripts/data-migration/dependency-resolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { Pool } from "pg";
2
+ import { EntityType } from "./types";
3
+ export declare class EntityDiscovery {
4
+ private readonly targetPool;
5
+ private readonly logger;
6
+ constructor(targetPool: Pool);
7
+ discoverEntityTypes(schemaName: string, tables: string[]): Promise<EntityType[]>;
8
+ private getPrimaryKey;
9
+ private getForeignKeys;
10
+ private findJoinTables;
11
+ }
@@ -0,0 +1,152 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EntityDiscovery = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ class EntityDiscovery {
6
+ constructor(targetPool) {
7
+ this.targetPool = targetPool;
8
+ this.logger = new common_1.Logger("EntityDiscovery");
9
+ }
10
+ async discoverEntityTypes(schemaName, tables) {
11
+ try {
12
+ const entityTypes = [];
13
+ for (const tableName of tables) {
14
+ const primaryKey = await this.getPrimaryKey(schemaName, tableName);
15
+ if (!primaryKey) {
16
+ this.logger.warn(`No primary key found for table ${tableName}, skipping`);
17
+ continue;
18
+ }
19
+ const foreignKeys = await this.getForeignKeys(schemaName, tableName);
20
+ const providerForeignKey = foreignKeys.find(fk => fk.column_name.includes('provider_id') ||
21
+ fk.foreign_table_name === 'providers');
22
+ const entity = {
23
+ name: tableName,
24
+ idField: primaryKey,
25
+ foreignKey: providerForeignKey === null || providerForeignKey === void 0 ? void 0 : providerForeignKey.column_name,
26
+ };
27
+ if (!entity.foreignKey) {
28
+ const joinTables = await this.findJoinTables(schemaName, tableName, 'providers');
29
+ if (joinTables.length > 0) {
30
+ const joinTable = joinTables[0];
31
+ entity.joinTable = joinTable.join_table;
32
+ entity.joinField = joinTable.source_column;
33
+ entity.joinForeignKey = joinTable.target_column;
34
+ }
35
+ }
36
+ entityTypes.push(entity);
37
+ }
38
+ return entityTypes;
39
+ }
40
+ catch (error) {
41
+ this.logger.error(`Error discovering entity types: ${error.message}`);
42
+ return [];
43
+ }
44
+ }
45
+ async getPrimaryKey(schemaName, tableName) {
46
+ const query = `
47
+ SELECT a.attname
48
+ FROM pg_index i
49
+ JOIN pg_attribute a ON a.attrelid = i.indrelid
50
+ AND a.attnum = ANY(i.indkey)
51
+ WHERE i.indrelid = '"${schemaName}"."${tableName}"'::regclass
52
+ AND i.indisprimary;
53
+ `;
54
+ try {
55
+ const { rows } = await this.targetPool.query(query);
56
+ return rows.length > 0 ? rows[0].attname : null;
57
+ }
58
+ catch (error) {
59
+ this.logger.error(`Error getting primary key for ${tableName}: ${error.message}`);
60
+ return null;
61
+ }
62
+ }
63
+ async getForeignKeys(schemaName, tableName) {
64
+ const query = `
65
+ SELECT
66
+ kcu.column_name,
67
+ ccu.table_name AS foreign_table_name,
68
+ ccu.column_name AS foreign_column_name
69
+ FROM
70
+ information_schema.table_constraints tc
71
+ JOIN information_schema.key_column_usage kcu
72
+ ON tc.constraint_name = kcu.constraint_name
73
+ AND tc.table_schema = kcu.table_schema
74
+ JOIN information_schema.constraint_column_usage ccu
75
+ ON ccu.constraint_name = tc.constraint_name
76
+ AND ccu.table_schema = tc.table_schema
77
+ WHERE
78
+ tc.constraint_type = 'FOREIGN KEY'
79
+ AND tc.table_schema = $1
80
+ AND tc.table_name = $2;
81
+ `;
82
+ try {
83
+ const { rows } = await this.targetPool.query(query, [schemaName, tableName]);
84
+ return rows;
85
+ }
86
+ catch (error) {
87
+ this.logger.error(`Error getting foreign keys for ${tableName}: ${error.message}`);
88
+ return [];
89
+ }
90
+ }
91
+ async findJoinTables(schemaName, sourceTable, targetTable) {
92
+ const query = `
93
+ WITH source_fks AS (
94
+ SELECT
95
+ tc.table_name,
96
+ kcu.column_name,
97
+ ccu.table_name AS referenced_table
98
+ FROM
99
+ information_schema.table_constraints tc
100
+ JOIN information_schema.key_column_usage kcu
101
+ ON tc.constraint_name = kcu.constraint_name
102
+ AND tc.table_schema = kcu.table_schema
103
+ JOIN information_schema.constraint_column_usage ccu
104
+ ON ccu.constraint_name = tc.constraint_name
105
+ AND ccu.table_schema = tc.table_schema
106
+ WHERE
107
+ tc.constraint_type = 'FOREIGN KEY'
108
+ AND tc.table_schema = $1
109
+ AND ccu.table_name = $2
110
+ ),
111
+ target_fks AS (
112
+ SELECT
113
+ tc.table_name,
114
+ kcu.column_name,
115
+ ccu.table_name AS referenced_table
116
+ FROM
117
+ information_schema.table_constraints tc
118
+ JOIN information_schema.key_column_usage kcu
119
+ ON tc.constraint_name = kcu.constraint_name
120
+ AND tc.table_schema = kcu.table_schema
121
+ JOIN information_schema.constraint_column_usage ccu
122
+ ON ccu.constraint_name = tc.constraint_name
123
+ AND ccu.table_schema = tc.table_schema
124
+ WHERE
125
+ tc.constraint_type = 'FOREIGN KEY'
126
+ AND tc.table_schema = $1
127
+ AND ccu.table_name = $3
128
+ )
129
+ SELECT
130
+ s.table_name AS join_table,
131
+ s.column_name AS source_column,
132
+ t.column_name AS target_column
133
+ FROM
134
+ source_fks s
135
+ JOIN target_fks t ON s.table_name = t.table_name
136
+ `;
137
+ try {
138
+ const { rows } = await this.targetPool.query(query, [
139
+ schemaName,
140
+ sourceTable,
141
+ targetTable,
142
+ ]);
143
+ return rows;
144
+ }
145
+ catch (error) {
146
+ this.logger.error(`Error finding join tables between ${sourceTable} and ${targetTable}: ${error.message}`);
147
+ return [];
148
+ }
149
+ }
150
+ }
151
+ exports.EntityDiscovery = EntityDiscovery;
152
+ //# sourceMappingURL=entity-discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity-discovery.js","sourceRoot":"","sources":["../../../src/scripts/data-migration/entity-discovery.ts"],"names":[],"mappings":";;;AAAA,2CAAwC;AAIxC,MAAa,eAAe;IAG1B,YAA6B,UAAgB;QAAhB,eAAU,GAAV,UAAU,CAAM;QAF5B,WAAM,GAAG,IAAI,eAAM,CAAC,iBAAiB,CAAC,CAAC;IAER,CAAC;IAEjD,KAAK,CAAC,mBAAmB,CACvB,UAAkB,EAClB,MAAgB;QAEhB,IAAI,CAAC;YACH,MAAM,WAAW,GAAiB,EAAE,CAAC;YAErC,KAAK,MAAM,SAAS,IAAI,MAAM,EAAE,CAAC;gBAE/B,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;gBAEnE,IAAI,CAAC,UAAU,EAAE,CAAC;oBAChB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,kCAAkC,SAAS,YAAY,CAAC,CAAC;oBAC1E,SAAS;gBACX,CAAC;gBAGD,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;gBAGrE,MAAM,kBAAkB,GAAG,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAC/C,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,aAAa,CAAC;oBACtC,EAAE,CAAC,kBAAkB,KAAK,WAAW,CACtC,CAAC;gBAGF,MAAM,MAAM,GAAe;oBACzB,IAAI,EAAE,SAAS;oBACf,OAAO,EAAE,UAAU;oBACnB,UAAU,EAAE,kBAAkB,aAAlB,kBAAkB,uBAAlB,kBAAkB,CAAE,WAAW;iBAC5C,CAAC;gBAGF,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;oBAEvB,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,cAAc,CAC1C,UAAU,EACV,SAAS,EACT,WAAW,CACZ,CAAC;oBAEF,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBAC1B,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;wBAChC,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC,UAAU,CAAC;wBACxC,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC,aAAa,CAAC;wBAC3C,MAAM,CAAC,cAAc,GAAG,SAAS,CAAC,aAAa,CAAC;oBAClD,CAAC;gBACH,CAAC;gBAED,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC3B,CAAC;YAED,OAAO,WAAW,CAAC;QACrB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,mCAAmC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACtE,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,aAAa,CACzB,UAAkB,EAClB,SAAiB;QAEjB,MAAM,KAAK,GAAG;;;;;8BAKY,UAAU,MAAM,SAAS;;KAElD,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACpD,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;QAClD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,iCAAiC,SAAS,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAClF,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,cAAc,CAC1B,UAAkB,EAClB,SAAiB;QAMjB,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;;KAiBb,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC;YAC7E,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,kCAAkC,SAAS,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACnF,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,cAAc,CAC1B,UAAkB,EAClB,WAAmB,EACnB,WAAmB;QAOnB,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA4Cb,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,EAAE;gBAClD,UAAU;gBACV,WAAW;gBACX,WAAW;aACZ,CAAC,CAAC;YACH,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,qCAAqC,WAAW,QAAQ,WAAW,KAAK,KAAK,CAAC,OAAO,EAAE,CACxF,CAAC;YACF,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;CACF;AAhMD,0CAgMC"}
@@ -0,0 +1,17 @@
1
+ import { PrismaClient } from "@prisma/client";
2
+ import { DatabaseConnections } from "./types";
3
+ export declare class ForeignKeyManager {
4
+ private readonly connections;
5
+ private readonly logger;
6
+ constructor(connections: DatabaseConnections);
7
+ getForeignKeyDependencies(schemaName: string, tableName: string): Promise<Array<{
8
+ column: string;
9
+ foreignTable: string;
10
+ foreignColumn: string;
11
+ }>>;
12
+ checkForeignKeyDependencies(prisma: PrismaClient, schemaName: string, row: any, dependencies: Array<{
13
+ column: string;
14
+ foreignTable: string;
15
+ foreignColumn: string;
16
+ }>): Promise<string[]>;
17
+ }