@javalabs/prisma-client 1.0.27 → 1.0.29

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 (50) hide show
  1. package/.github/CODEOWNERS +1 -1
  2. package/README.md +269 -269
  3. package/migration-config.json +63 -63
  4. package/migration-config.json.bk +95 -95
  5. package/migrations/add_reserved_amount.sql +7 -7
  6. package/package.json +44 -44
  7. package/prisma/migrations/add_uuid_to_transactions.sql +13 -13
  8. package/prisma/schema.prisma +609 -601
  9. package/src/index.ts +23 -23
  10. package/src/prisma-factory.service.ts +40 -40
  11. package/src/prisma.module.ts +9 -9
  12. package/src/prisma.service.ts +16 -16
  13. package/src/scripts/add-uuid-to-table.ts +138 -138
  14. package/src/scripts/create-tenant-schemas.ts +145 -145
  15. package/src/scripts/data-migration/batch-migrator.ts +248 -248
  16. package/src/scripts/data-migration/data-transformer.ts +426 -426
  17. package/src/scripts/data-migration/db-connector.ts +120 -120
  18. package/src/scripts/data-migration/dependency-resolver.ts +174 -174
  19. package/src/scripts/data-migration/entity-discovery.ts +196 -196
  20. package/src/scripts/data-migration/foreign-key-manager.ts +277 -277
  21. package/src/scripts/data-migration/migration-config.json +63 -63
  22. package/src/scripts/data-migration/migration-tool.ts +509 -509
  23. package/src/scripts/data-migration/schema-utils.ts +248 -248
  24. package/src/scripts/data-migration/tenant-migrator.ts +201 -201
  25. package/src/scripts/data-migration/typecast-manager.ts +193 -193
  26. package/src/scripts/data-migration/types.ts +113 -113
  27. package/src/scripts/database-initializer.ts +49 -49
  28. package/src/scripts/drop-database.ts +104 -104
  29. package/src/scripts/dump-source-db.sh +61 -61
  30. package/src/scripts/encrypt-user-passwords.ts +36 -36
  31. package/src/scripts/error-handler.ts +117 -117
  32. package/src/scripts/fix-data-types.ts +241 -241
  33. package/src/scripts/fix-enum-values.ts +357 -357
  34. package/src/scripts/fix-schema-discrepancies.ts +317 -317
  35. package/src/scripts/fix-table-indexes.ts +601 -601
  36. package/src/scripts/migrate-schema-structure.ts +90 -90
  37. package/src/scripts/migrate-uuid.ts +76 -76
  38. package/src/scripts/post-migration-validator.ts +526 -526
  39. package/src/scripts/pre-migration-validator.ts +610 -610
  40. package/src/scripts/reset-database.ts +263 -263
  41. package/src/scripts/retry-failed-migrations.ts +416 -416
  42. package/src/scripts/run-migration.ts +707 -707
  43. package/src/scripts/schema-sync.ts +128 -128
  44. package/src/scripts/sequence-sync-cli.ts +416 -416
  45. package/src/scripts/sequence-synchronizer.ts +127 -127
  46. package/src/scripts/sync-enum-types.ts +170 -170
  47. package/src/scripts/sync-enum-values.ts +563 -563
  48. package/src/scripts/truncate-database.ts +123 -123
  49. package/src/scripts/verify-migration-setup.ts +135 -135
  50. package/tsconfig.json +17 -17
@@ -1,248 +1,248 @@
1
- import { Logger } from "@nestjs/common";
2
- import { ColumnSchema } from "./types";
3
-
4
- export class SchemaUtils {
5
- private readonly logger = new Logger("SchemaUtils");
6
-
7
- constructor(private readonly connections: any) {}
8
-
9
- // En el método getTableSchema de SchemaUtils
10
- async getTableSchema(
11
- tableName: string,
12
- dbType: "source" | "target",
13
- schema: string = "public"
14
- ): Promise<ColumnSchema[]> {
15
- const pool =
16
- dbType === "source"
17
- ? this.connections.sourcePool
18
- : this.connections.targetPool;
19
-
20
- const query = `
21
- SELECT
22
- c.table_name,
23
- c.column_name,
24
- c.data_type,
25
- c.udt_name,
26
- c.character_maximum_length,
27
- c.is_nullable,
28
- c.column_default,
29
- tc.constraint_type
30
- FROM
31
- information_schema.columns c
32
- LEFT JOIN information_schema.constraint_column_usage ccu
33
- ON c.column_name = ccu.column_name
34
- AND c.table_name = ccu.table_name
35
- LEFT JOIN information_schema.table_constraints tc
36
- ON ccu.constraint_name = tc.constraint_name
37
- WHERE
38
- c.table_schema = $1
39
- AND c.table_name = $2
40
- ORDER BY
41
- c.ordinal_position
42
- `;
43
-
44
- try {
45
- const result = await pool.query(query, [schema, tableName]);
46
- // No transformar los nombres de las columnas, mantener el case original
47
- return result.rows;
48
- } catch (error) {
49
- this.logger.error(
50
- `Error getting schema for ${schema}.${tableName}: ${error.message}`
51
- );
52
- return [];
53
- }
54
- }
55
-
56
- async checkSchemaExists(schemaName: string): Promise<boolean> {
57
- try {
58
- const query = `
59
- SELECT schema_name
60
- FROM information_schema.schemata
61
- WHERE schema_name = $1
62
- `;
63
- const result = await this.connections.targetPool.query(query, [
64
- schemaName,
65
- ]);
66
- return result.rows.length > 0;
67
- } catch (error) {
68
- this.logger.error(`Error checking if schema exists: ${error.message}`);
69
- return false;
70
- }
71
- }
72
-
73
- async getTargetTables(schemaName: string): Promise<string[]> {
74
- try {
75
- const query = `
76
- SELECT table_name
77
- FROM information_schema.tables
78
- WHERE table_schema = $1
79
- AND table_type = 'BASE TABLE'
80
- `;
81
- const result = await this.connections.targetPool.query(query, [
82
- schemaName,
83
- ]);
84
-
85
- // Log para depuración
86
- this.logger.log(
87
- `Found ${result.rows.length} tables in schema ${schemaName}`
88
- );
89
- result.rows.forEach((row) => {
90
- this.logger.log(`Table in schema ${schemaName}: ${row.table_name}`);
91
- });
92
-
93
- return result.rows.map((row) => row.table_name);
94
- } catch (error) {
95
- this.logger.error(`Error getting target tables: ${error.message}`);
96
- return [];
97
- }
98
- }
99
-
100
- async getEnumValues(schemaName: string, enumName: string): Promise<string[]> {
101
- try {
102
- // Consulta para obtener los valores posibles de un enum
103
- const query = `
104
- SELECT e.enumlabel
105
- FROM pg_type t
106
- JOIN pg_enum e ON t.oid = e.enumtypid
107
- JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
108
- WHERE t.typname = $1
109
- AND n.nspname = $2
110
- `;
111
- const result = await this.connections.targetPool.query(query, [
112
- enumName,
113
- schemaName,
114
- ]);
115
- return result.rows.map((row) => row.enumlabel);
116
- } catch (error) {
117
- this.logger.error(
118
- `Error getting enum values for ${enumName}: ${error.message}`
119
- );
120
- return [];
121
- }
122
- }
123
-
124
- async executeQuery(query: string, params: any[] = []): Promise<any> {
125
- return this.connections.targetPool.query(query, params);
126
- }
127
-
128
- async queryTargetDb(query: string, params: any[]): Promise<{ rows: any[] }> {
129
- return this.connections.targetPool.query(query, params);
130
- }
131
-
132
- async createMissingColumns(
133
- tableName: string,
134
- schema: string,
135
- columns: ColumnSchema[]
136
- ) {
137
- for (const column of columns) {
138
- try {
139
- const query = `
140
- ALTER TABLE "${schema}"."${tableName}"
141
- ADD COLUMN IF NOT EXISTS "${column.column_name}" ${column.data_type}
142
- ${column.is_nullable === "NO" ? "NOT NULL" : ""}
143
- ${column.column_default ? `DEFAULT ${column.column_default}` : ""}
144
- `;
145
- await this.connections.targetPool.query(query);
146
-
147
- // Add unique constraint if needed
148
- if (column.constraint_type === "UNIQUE") {
149
- const constraintName = `${tableName}_${column.column_name}_unique`;
150
- const uniqueQuery = `
151
- DO $$
152
- BEGIN
153
- IF NOT EXISTS (
154
- SELECT 1 FROM pg_constraint WHERE conname = '${constraintName}'
155
- ) THEN
156
- ALTER TABLE "${schema}"."${tableName}"
157
- ADD CONSTRAINT "${constraintName}" UNIQUE ("${column.column_name}");
158
- END IF;
159
- END $$;
160
- `;
161
- await this.connections.targetPool.query(uniqueQuery);
162
- }
163
- } catch (error) {
164
- this.logger.error(
165
- `Error creating column ${column.column_name}: ${error.message}`
166
- );
167
- throw error;
168
- }
169
- }
170
- }
171
-
172
- async createSchema(schemaName: string): Promise<void> {
173
- try {
174
- // Create schema
175
- await this.connections.targetPool.query(
176
- `CREATE SCHEMA IF NOT EXISTS "${schemaName}"`
177
- );
178
-
179
- // Copy table structure from public schema
180
- const tables = await this.getPublicTables();
181
-
182
- for (const table of tables) {
183
- await this.connections.targetPool.query(`
184
- CREATE TABLE IF NOT EXISTS "${schemaName}"."${table}" (
185
- LIKE public."${table}" INCLUDING ALL
186
- );
187
- `);
188
- }
189
-
190
- this.logger.log(`Created schema ${schemaName} with all tables`);
191
- } catch (error) {
192
- this.logger.error(
193
- `Error creating schema ${schemaName}: ${error.message}`
194
- );
195
- throw error;
196
- }
197
- }
198
-
199
- private async getPublicTables(): Promise<string[]> {
200
- const result = await this.connections.targetPool.query(`
201
- SELECT tablename
202
- FROM pg_tables
203
- WHERE schemaname = 'public'
204
- `);
205
- return result.rows.map((row) => row.tablename);
206
- }
207
-
208
- async getTableColumns(
209
- schema: string,
210
- table: string
211
- ): Promise<ColumnSchema[]> {
212
- const query = `
213
- SELECT
214
- column_name,
215
- data_type,
216
- is_nullable,
217
- column_default,
218
- character_maximum_length,
219
- numeric_precision,
220
- numeric_scale
221
- FROM information_schema.columns
222
- WHERE table_schema = $1
223
- AND table_name = $2
224
- ORDER BY ordinal_position;
225
- `;
226
-
227
- try {
228
- const result = await this.connections.sourcePool.query(query, [
229
- schema,
230
- table,
231
- ]);
232
- return result.rows.map((row: any) => ({
233
- column_name: row.column_name,
234
- data_type: row.data_type,
235
- is_nullable: row.is_nullable,
236
- column_default: row.column_default,
237
- character_maximum_length: row.character_maximum_length,
238
- numeric_precision: row.numeric_precision,
239
- numeric_scale: row.numeric_scale,
240
- }));
241
- } catch (error) {
242
- this.logger.error(
243
- `Error obteniendo columnas para ${schema}.${table}: ${error.message}`
244
- );
245
- throw error;
246
- }
247
- }
248
- }
1
+ import { Logger } from "@nestjs/common";
2
+ import { ColumnSchema } from "./types";
3
+
4
+ export class SchemaUtils {
5
+ private readonly logger = new Logger("SchemaUtils");
6
+
7
+ constructor(private readonly connections: any) {}
8
+
9
+ // En el método getTableSchema de SchemaUtils
10
+ async getTableSchema(
11
+ tableName: string,
12
+ dbType: "source" | "target",
13
+ schema: string = "public"
14
+ ): Promise<ColumnSchema[]> {
15
+ const pool =
16
+ dbType === "source"
17
+ ? this.connections.sourcePool
18
+ : this.connections.targetPool;
19
+
20
+ const query = `
21
+ SELECT
22
+ c.table_name,
23
+ c.column_name,
24
+ c.data_type,
25
+ c.udt_name,
26
+ c.character_maximum_length,
27
+ c.is_nullable,
28
+ c.column_default,
29
+ tc.constraint_type
30
+ FROM
31
+ information_schema.columns c
32
+ LEFT JOIN information_schema.constraint_column_usage ccu
33
+ ON c.column_name = ccu.column_name
34
+ AND c.table_name = ccu.table_name
35
+ LEFT JOIN information_schema.table_constraints tc
36
+ ON ccu.constraint_name = tc.constraint_name
37
+ WHERE
38
+ c.table_schema = $1
39
+ AND c.table_name = $2
40
+ ORDER BY
41
+ c.ordinal_position
42
+ `;
43
+
44
+ try {
45
+ const result = await pool.query(query, [schema, tableName]);
46
+ // No transformar los nombres de las columnas, mantener el case original
47
+ return result.rows;
48
+ } catch (error) {
49
+ this.logger.error(
50
+ `Error getting schema for ${schema}.${tableName}: ${error.message}`
51
+ );
52
+ return [];
53
+ }
54
+ }
55
+
56
+ async checkSchemaExists(schemaName: string): Promise<boolean> {
57
+ try {
58
+ const query = `
59
+ SELECT schema_name
60
+ FROM information_schema.schemata
61
+ WHERE schema_name = $1
62
+ `;
63
+ const result = await this.connections.targetPool.query(query, [
64
+ schemaName,
65
+ ]);
66
+ return result.rows.length > 0;
67
+ } catch (error) {
68
+ this.logger.error(`Error checking if schema exists: ${error.message}`);
69
+ return false;
70
+ }
71
+ }
72
+
73
+ async getTargetTables(schemaName: string): Promise<string[]> {
74
+ try {
75
+ const query = `
76
+ SELECT table_name
77
+ FROM information_schema.tables
78
+ WHERE table_schema = $1
79
+ AND table_type = 'BASE TABLE'
80
+ `;
81
+ const result = await this.connections.targetPool.query(query, [
82
+ schemaName,
83
+ ]);
84
+
85
+ // Log para depuración
86
+ this.logger.log(
87
+ `Found ${result.rows.length} tables in schema ${schemaName}`
88
+ );
89
+ result.rows.forEach((row) => {
90
+ this.logger.log(`Table in schema ${schemaName}: ${row.table_name}`);
91
+ });
92
+
93
+ return result.rows.map((row) => row.table_name);
94
+ } catch (error) {
95
+ this.logger.error(`Error getting target tables: ${error.message}`);
96
+ return [];
97
+ }
98
+ }
99
+
100
+ async getEnumValues(schemaName: string, enumName: string): Promise<string[]> {
101
+ try {
102
+ // Consulta para obtener los valores posibles de un enum
103
+ const query = `
104
+ SELECT e.enumlabel
105
+ FROM pg_type t
106
+ JOIN pg_enum e ON t.oid = e.enumtypid
107
+ JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
108
+ WHERE t.typname = $1
109
+ AND n.nspname = $2
110
+ `;
111
+ const result = await this.connections.targetPool.query(query, [
112
+ enumName,
113
+ schemaName,
114
+ ]);
115
+ return result.rows.map((row) => row.enumlabel);
116
+ } catch (error) {
117
+ this.logger.error(
118
+ `Error getting enum values for ${enumName}: ${error.message}`
119
+ );
120
+ return [];
121
+ }
122
+ }
123
+
124
+ async executeQuery(query: string, params: any[] = []): Promise<any> {
125
+ return this.connections.targetPool.query(query, params);
126
+ }
127
+
128
+ async queryTargetDb(query: string, params: any[]): Promise<{ rows: any[] }> {
129
+ return this.connections.targetPool.query(query, params);
130
+ }
131
+
132
+ async createMissingColumns(
133
+ tableName: string,
134
+ schema: string,
135
+ columns: ColumnSchema[]
136
+ ) {
137
+ for (const column of columns) {
138
+ try {
139
+ const query = `
140
+ ALTER TABLE "${schema}"."${tableName}"
141
+ ADD COLUMN IF NOT EXISTS "${column.column_name}" ${column.data_type}
142
+ ${column.is_nullable === "NO" ? "NOT NULL" : ""}
143
+ ${column.column_default ? `DEFAULT ${column.column_default}` : ""}
144
+ `;
145
+ await this.connections.targetPool.query(query);
146
+
147
+ // Add unique constraint if needed
148
+ if (column.constraint_type === "UNIQUE") {
149
+ const constraintName = `${tableName}_${column.column_name}_unique`;
150
+ const uniqueQuery = `
151
+ DO $$
152
+ BEGIN
153
+ IF NOT EXISTS (
154
+ SELECT 1 FROM pg_constraint WHERE conname = '${constraintName}'
155
+ ) THEN
156
+ ALTER TABLE "${schema}"."${tableName}"
157
+ ADD CONSTRAINT "${constraintName}" UNIQUE ("${column.column_name}");
158
+ END IF;
159
+ END $$;
160
+ `;
161
+ await this.connections.targetPool.query(uniqueQuery);
162
+ }
163
+ } catch (error) {
164
+ this.logger.error(
165
+ `Error creating column ${column.column_name}: ${error.message}`
166
+ );
167
+ throw error;
168
+ }
169
+ }
170
+ }
171
+
172
+ async createSchema(schemaName: string): Promise<void> {
173
+ try {
174
+ // Create schema
175
+ await this.connections.targetPool.query(
176
+ `CREATE SCHEMA IF NOT EXISTS "${schemaName}"`
177
+ );
178
+
179
+ // Copy table structure from public schema
180
+ const tables = await this.getPublicTables();
181
+
182
+ for (const table of tables) {
183
+ await this.connections.targetPool.query(`
184
+ CREATE TABLE IF NOT EXISTS "${schemaName}"."${table}" (
185
+ LIKE public."${table}" INCLUDING ALL
186
+ );
187
+ `);
188
+ }
189
+
190
+ this.logger.log(`Created schema ${schemaName} with all tables`);
191
+ } catch (error) {
192
+ this.logger.error(
193
+ `Error creating schema ${schemaName}: ${error.message}`
194
+ );
195
+ throw error;
196
+ }
197
+ }
198
+
199
+ private async getPublicTables(): Promise<string[]> {
200
+ const result = await this.connections.targetPool.query(`
201
+ SELECT tablename
202
+ FROM pg_tables
203
+ WHERE schemaname = 'public'
204
+ `);
205
+ return result.rows.map((row) => row.tablename);
206
+ }
207
+
208
+ async getTableColumns(
209
+ schema: string,
210
+ table: string
211
+ ): Promise<ColumnSchema[]> {
212
+ const query = `
213
+ SELECT
214
+ column_name,
215
+ data_type,
216
+ is_nullable,
217
+ column_default,
218
+ character_maximum_length,
219
+ numeric_precision,
220
+ numeric_scale
221
+ FROM information_schema.columns
222
+ WHERE table_schema = $1
223
+ AND table_name = $2
224
+ ORDER BY ordinal_position;
225
+ `;
226
+
227
+ try {
228
+ const result = await this.connections.sourcePool.query(query, [
229
+ schema,
230
+ table,
231
+ ]);
232
+ return result.rows.map((row: any) => ({
233
+ column_name: row.column_name,
234
+ data_type: row.data_type,
235
+ is_nullable: row.is_nullable,
236
+ column_default: row.column_default,
237
+ character_maximum_length: row.character_maximum_length,
238
+ numeric_precision: row.numeric_precision,
239
+ numeric_scale: row.numeric_scale,
240
+ }));
241
+ } catch (error) {
242
+ this.logger.error(
243
+ `Error obteniendo columnas para ${schema}.${table}: ${error.message}`
244
+ );
245
+ throw error;
246
+ }
247
+ }
248
+ }