@javalabs/prisma-client 1.0.16 → 1.0.19

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 (106) hide show
  1. package/.dockerignore +14 -0
  2. package/Dockerfile +23 -0
  3. package/README.md +269 -269
  4. package/dist/index.d.ts +1 -1
  5. package/dist/prisma.service.d.ts +1 -1
  6. package/dist/scripts/add-uuid-to-table.js +32 -32
  7. package/dist/scripts/data-migration/batch-migrator.js +12 -12
  8. package/dist/scripts/data-migration/data-transformer.js +14 -14
  9. package/dist/scripts/data-migration/dependency-resolver.js +23 -23
  10. package/dist/scripts/data-migration/entity-discovery.js +68 -68
  11. package/dist/scripts/data-migration/foreign-key-manager.js +23 -23
  12. package/dist/scripts/data-migration/migration-tool.js +5 -5
  13. package/dist/scripts/data-migration/schema-utils.js +74 -74
  14. package/dist/scripts/data-migration/typecast-manager.js +4 -4
  15. package/dist/scripts/database-initializer.js +5 -5
  16. package/dist/scripts/drop-database.js +5 -5
  17. package/dist/scripts/fix-data-types.js +53 -53
  18. package/dist/scripts/fix-enum-values.js +34 -34
  19. package/dist/scripts/fix-schema-discrepancies.js +40 -40
  20. package/dist/scripts/fix-table-indexes.js +81 -81
  21. package/dist/scripts/migrate-schema-structure.js +4 -4
  22. package/dist/scripts/migrate-uuid.js +19 -19
  23. package/dist/scripts/post-migration-validator.js +49 -49
  24. package/dist/scripts/pre-migration-validator.js +107 -107
  25. package/dist/scripts/reset-database.js +21 -21
  26. package/dist/scripts/retry-failed-migrations.js +28 -28
  27. package/dist/scripts/run-migration.js +5 -5
  28. package/dist/scripts/schema-sync.js +18 -18
  29. package/dist/scripts/sequence-sync-cli.js +55 -55
  30. package/dist/scripts/sequence-synchronizer.js +20 -20
  31. package/dist/scripts/sync-enum-types.js +30 -30
  32. package/dist/scripts/sync-enum-values.js +52 -52
  33. package/dist/scripts/truncate-database.js +10 -10
  34. package/dist/scripts/verify-migration-setup.js +10 -10
  35. package/dist/tsconfig.tsbuildinfo +1 -1
  36. package/migration-config.json +63 -63
  37. package/migration-config.json.bk +95 -95
  38. package/package.json +44 -44
  39. package/prisma/migrations/add_accepts_partial_payments_to_users.sql +19 -0
  40. package/prisma/migrations/add_amount_received_to_manual_payments.sql +19 -0
  41. package/prisma/migrations/add_commission_fields.sql +33 -0
  42. package/prisma/migrations/add_uuid_to_transactions.sql +13 -13
  43. package/prisma/migrations/complete_partial_payments_migration.sql +53 -0
  44. package/prisma/migrations/create_settlements_table.sql +60 -0
  45. package/prisma/schema.prisma +56 -4
  46. package/src/index.ts +23 -23
  47. package/src/prisma-factory.service.ts +40 -40
  48. package/src/prisma.module.ts +9 -9
  49. package/src/prisma.service.ts +16 -16
  50. package/src/scripts/add-uuid-to-table.ts +138 -138
  51. package/src/scripts/create-tenant-schemas.ts +145 -145
  52. package/src/scripts/data-migration/batch-migrator.ts +248 -248
  53. package/src/scripts/data-migration/data-transformer.ts +426 -426
  54. package/src/scripts/data-migration/db-connector.ts +120 -120
  55. package/src/scripts/data-migration/dependency-resolver.ts +174 -174
  56. package/src/scripts/data-migration/entity-discovery.ts +196 -196
  57. package/src/scripts/data-migration/foreign-key-manager.ts +277 -277
  58. package/src/scripts/data-migration/migration-config.json +63 -63
  59. package/src/scripts/data-migration/migration-tool.ts +509 -509
  60. package/src/scripts/data-migration/schema-utils.ts +248 -248
  61. package/src/scripts/data-migration/tenant-migrator.ts +201 -201
  62. package/src/scripts/data-migration/typecast-manager.ts +193 -193
  63. package/src/scripts/data-migration/types.ts +113 -113
  64. package/src/scripts/database-initializer.ts +49 -49
  65. package/src/scripts/drop-database.ts +104 -104
  66. package/src/scripts/dump-source-db.sh +61 -61
  67. package/src/scripts/encrypt-user-passwords.ts +36 -36
  68. package/src/scripts/error-handler.ts +117 -117
  69. package/src/scripts/fix-data-types.ts +241 -241
  70. package/src/scripts/fix-enum-values.ts +357 -357
  71. package/src/scripts/fix-schema-discrepancies.ts +317 -317
  72. package/src/scripts/fix-table-indexes.ts +601 -601
  73. package/src/scripts/migrate-schema-structure.ts +90 -90
  74. package/src/scripts/migrate-uuid.ts +76 -76
  75. package/src/scripts/post-migration-validator.ts +526 -526
  76. package/src/scripts/pre-migration-validator.ts +610 -610
  77. package/src/scripts/reset-database.ts +263 -263
  78. package/src/scripts/retry-failed-migrations.ts +416 -416
  79. package/src/scripts/run-migration.ts +707 -707
  80. package/src/scripts/schema-sync.ts +128 -128
  81. package/src/scripts/sequence-sync-cli.ts +416 -416
  82. package/src/scripts/sequence-synchronizer.ts +127 -127
  83. package/src/scripts/sync-enum-types.ts +170 -170
  84. package/src/scripts/sync-enum-values.ts +563 -563
  85. package/src/scripts/truncate-database.ts +123 -123
  86. package/src/scripts/verify-migration-setup.ts +135 -135
  87. package/tsconfig.json +17 -17
  88. package/dist/scripts/data-migration/dependency-manager.d.ts +0 -9
  89. package/dist/scripts/data-migration/dependency-manager.js +0 -86
  90. package/dist/scripts/data-migration/dependency-manager.js.map +0 -1
  91. package/dist/scripts/data-migration/migration-config.json +0 -63
  92. package/dist/scripts/data-migration/migration-phases.d.ts +0 -5
  93. package/dist/scripts/data-migration/migration-phases.js +0 -55
  94. package/dist/scripts/data-migration/migration-phases.js.map +0 -1
  95. package/dist/scripts/data-migration/multi-source-migrator.d.ts +0 -17
  96. package/dist/scripts/data-migration/multi-source-migrator.js +0 -130
  97. package/dist/scripts/data-migration/multi-source-migrator.js.map +0 -1
  98. package/dist/scripts/data-migration/phase-generator.d.ts +0 -15
  99. package/dist/scripts/data-migration/phase-generator.js +0 -187
  100. package/dist/scripts/data-migration/phase-generator.js.map +0 -1
  101. package/dist/scripts/data-migration.d.ts +0 -22
  102. package/dist/scripts/data-migration.js +0 -593
  103. package/dist/scripts/data-migration.js.map +0 -1
  104. package/dist/scripts/multi-db-migration.d.ts +0 -1
  105. package/dist/scripts/multi-db-migration.js +0 -55
  106. package/dist/scripts/multi-db-migration.js.map +0 -1
@@ -1,127 +1,127 @@
1
- import { Logger } from "@nestjs/common";
2
- import { Pool } from "pg";
3
-
4
- export class SequenceSynchronizer {
5
- private readonly logger = new Logger("SequenceSynchronizer");
6
- private readonly pool: Pool;
7
-
8
- constructor(databaseUrl: string) {
9
- this.pool = new Pool({
10
- connectionString: databaseUrl,
11
- });
12
- }
13
-
14
- async synchronizeSequences(): Promise<void> {
15
- try {
16
- this.logger.log("Iniciando sincronización de secuencias");
17
-
18
- // Obtener todas las tablas en la base de datos
19
- const tables = await this.getTables();
20
- this.logger.log(`Encontradas ${tables.length} tablas para procesar`);
21
-
22
- // Procesar cada tabla
23
- for (const table of tables) {
24
- await this.synchronizeTableSequences(table);
25
- }
26
-
27
- this.logger.log("Sincronización de secuencias completada con éxito");
28
- } catch (error) {
29
- this.logger.error(
30
- `Error durante la sincronización de secuencias: ${error.message}`,
31
- error.stack
32
- );
33
- throw error;
34
- } finally {
35
- await this.pool.end();
36
- }
37
- }
38
-
39
- private async getTables(): Promise<string[]> {
40
- const query = `
41
- SELECT table_name
42
- FROM information_schema.tables
43
- WHERE table_schema = 'public'
44
- AND table_type = 'BASE TABLE'
45
- `;
46
-
47
- const result = await this.pool.query(query);
48
- return result.rows.map((row) => row.table_name);
49
- }
50
-
51
- private async synchronizeTableSequences(tableName: string): Promise<void> {
52
- try {
53
- // Verificar si la tabla tiene una columna id
54
- const columns = await this.pool.query(
55
- `
56
- SELECT column_name
57
- FROM information_schema.columns
58
- WHERE table_name = $1
59
- AND column_name = 'id'
60
- `,
61
- [tableName]
62
- );
63
-
64
- if (columns.rows.length === 0) {
65
- this.logger.debug(
66
- `La tabla ${tableName} no tiene columna id, omitiendo`
67
- );
68
- return;
69
- }
70
-
71
- // Verificar si existe una secuencia para esta tabla
72
- const sequenceName = `${tableName}_id_seq`;
73
- const sequences = await this.pool.query(
74
- `
75
- SELECT sequence_name
76
- FROM information_schema.sequences
77
- WHERE sequence_name = $1
78
- `,
79
- [sequenceName]
80
- );
81
-
82
- if (sequences.rows.length === 0) {
83
- this.logger.debug(
84
- `No se encontró secuencia para la tabla ${tableName}, omitiendo`
85
- );
86
- return;
87
- }
88
-
89
- // Obtener el máximo ID actual de la tabla
90
- const maxResult = await this.pool.query(`
91
- SELECT COALESCE(MAX(id), 0) as max_id FROM "${tableName}"
92
- `);
93
- const maxId = maxResult.rows[0].max_id;
94
-
95
- // Obtener el valor actual de la secuencia
96
- const currValResult = await this.pool.query(`
97
- SELECT last_value FROM "${sequenceName}"
98
- `);
99
- const currVal = currValResult.rows[0].last_value;
100
-
101
- this.logger.log(
102
- `Tabla ${tableName}: ID Máximo = ${maxId}, Valor Actual de Secuencia = ${currVal}`
103
- );
104
-
105
- // Actualizar la secuencia solo si es necesario
106
- if (currVal <= maxId) {
107
- await this.pool.query(
108
- `
109
- SELECT setval($1, $2, true)
110
- `,
111
- [sequenceName, maxId]
112
- );
113
- this.logger.log(
114
- `Actualizada secuencia para tabla ${tableName} a ${maxId}`
115
- );
116
- } else {
117
- this.logger.log(
118
- `La secuencia para la tabla ${tableName} ya está adelantada al ID máximo, no se requiere actualización`
119
- );
120
- }
121
- } catch (error) {
122
- this.logger.error(
123
- `Error sincronizando secuencias para tabla ${tableName}: ${error.message}`
124
- );
125
- }
126
- }
127
- }
1
+ import { Logger } from "@nestjs/common";
2
+ import { Pool } from "pg";
3
+
4
+ export class SequenceSynchronizer {
5
+ private readonly logger = new Logger("SequenceSynchronizer");
6
+ private readonly pool: Pool;
7
+
8
+ constructor(databaseUrl: string) {
9
+ this.pool = new Pool({
10
+ connectionString: databaseUrl,
11
+ });
12
+ }
13
+
14
+ async synchronizeSequences(): Promise<void> {
15
+ try {
16
+ this.logger.log("Iniciando sincronización de secuencias");
17
+
18
+ // Obtener todas las tablas en la base de datos
19
+ const tables = await this.getTables();
20
+ this.logger.log(`Encontradas ${tables.length} tablas para procesar`);
21
+
22
+ // Procesar cada tabla
23
+ for (const table of tables) {
24
+ await this.synchronizeTableSequences(table);
25
+ }
26
+
27
+ this.logger.log("Sincronización de secuencias completada con éxito");
28
+ } catch (error) {
29
+ this.logger.error(
30
+ `Error durante la sincronización de secuencias: ${error.message}`,
31
+ error.stack
32
+ );
33
+ throw error;
34
+ } finally {
35
+ await this.pool.end();
36
+ }
37
+ }
38
+
39
+ private async getTables(): Promise<string[]> {
40
+ const query = `
41
+ SELECT table_name
42
+ FROM information_schema.tables
43
+ WHERE table_schema = 'public'
44
+ AND table_type = 'BASE TABLE'
45
+ `;
46
+
47
+ const result = await this.pool.query(query);
48
+ return result.rows.map((row) => row.table_name);
49
+ }
50
+
51
+ private async synchronizeTableSequences(tableName: string): Promise<void> {
52
+ try {
53
+ // Verificar si la tabla tiene una columna id
54
+ const columns = await this.pool.query(
55
+ `
56
+ SELECT column_name
57
+ FROM information_schema.columns
58
+ WHERE table_name = $1
59
+ AND column_name = 'id'
60
+ `,
61
+ [tableName]
62
+ );
63
+
64
+ if (columns.rows.length === 0) {
65
+ this.logger.debug(
66
+ `La tabla ${tableName} no tiene columna id, omitiendo`
67
+ );
68
+ return;
69
+ }
70
+
71
+ // Verificar si existe una secuencia para esta tabla
72
+ const sequenceName = `${tableName}_id_seq`;
73
+ const sequences = await this.pool.query(
74
+ `
75
+ SELECT sequence_name
76
+ FROM information_schema.sequences
77
+ WHERE sequence_name = $1
78
+ `,
79
+ [sequenceName]
80
+ );
81
+
82
+ if (sequences.rows.length === 0) {
83
+ this.logger.debug(
84
+ `No se encontró secuencia para la tabla ${tableName}, omitiendo`
85
+ );
86
+ return;
87
+ }
88
+
89
+ // Obtener el máximo ID actual de la tabla
90
+ const maxResult = await this.pool.query(`
91
+ SELECT COALESCE(MAX(id), 0) as max_id FROM "${tableName}"
92
+ `);
93
+ const maxId = maxResult.rows[0].max_id;
94
+
95
+ // Obtener el valor actual de la secuencia
96
+ const currValResult = await this.pool.query(`
97
+ SELECT last_value FROM "${sequenceName}"
98
+ `);
99
+ const currVal = currValResult.rows[0].last_value;
100
+
101
+ this.logger.log(
102
+ `Tabla ${tableName}: ID Máximo = ${maxId}, Valor Actual de Secuencia = ${currVal}`
103
+ );
104
+
105
+ // Actualizar la secuencia solo si es necesario
106
+ if (currVal <= maxId) {
107
+ await this.pool.query(
108
+ `
109
+ SELECT setval($1, $2, true)
110
+ `,
111
+ [sequenceName, maxId]
112
+ );
113
+ this.logger.log(
114
+ `Actualizada secuencia para tabla ${tableName} a ${maxId}`
115
+ );
116
+ } else {
117
+ this.logger.log(
118
+ `La secuencia para la tabla ${tableName} ya está adelantada al ID máximo, no se requiere actualización`
119
+ );
120
+ }
121
+ } catch (error) {
122
+ this.logger.error(
123
+ `Error sincronizando secuencias para tabla ${tableName}: ${error.message}`
124
+ );
125
+ }
126
+ }
127
+ }
@@ -1,171 +1,171 @@
1
- import * as pg from 'pg';
2
- import * as dotenv from 'dotenv';
3
- import { Logger } from '@nestjs/common';
4
-
5
- dotenv.config();
6
-
7
- export class EnumSynchronizer {
8
- private readonly logger = new Logger('EnumSynchronizer');
9
- private readonly sourcePool: pg.Pool;
10
- private readonly targetPool: pg.Pool;
11
-
12
- constructor(
13
- private readonly sourceUrl: string = process.env.SOURCE_DATABASE_URL,
14
- private readonly targetUrl: string = process.env.DATABASE_URL
15
- ) {
16
- this.sourcePool = new pg.Pool({
17
- connectionString: this.sourceUrl,
18
- });
19
-
20
- this.targetPool = new pg.Pool({
21
- connectionString: this.targetUrl,
22
- });
23
- }
24
-
25
- async synchronizeEnums() {
26
- try {
27
- this.logger.log('Starting enum synchronization');
28
-
29
- // Obtener todos los tipos enum en la base de datos de origen
30
- const sourceEnumsResult = await this.sourcePool.query(`
31
- SELECT t.typname AS enum_name
32
- FROM pg_type t
33
- JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
34
- WHERE t.typtype = 'e'
35
- AND n.nspname = 'public'
36
- `);
37
-
38
- this.logger.log(`Found ${sourceEnumsResult.rows.length} enum types in source database`);
39
-
40
- // Para cada tipo enum, sincronizar sus valores
41
- for (const enumRow of sourceEnumsResult.rows) {
42
- const enumName = enumRow.enum_name;
43
- await this.synchronizeEnumType(enumName);
44
- }
45
-
46
- this.logger.log('Enum synchronization completed successfully');
47
- } catch (error) {
48
- this.logger.error(`Error during enum synchronization: ${error.message}`, error.stack);
49
- } finally {
50
- await this.cleanup();
51
- }
52
- }
53
-
54
- private async synchronizeEnumType(enumName: string) {
55
- this.logger.log(`Synchronizing enum type: ${enumName}`);
56
-
57
- try {
58
- // Obtener valores del enum en la base de datos de origen
59
- const sourceEnumValuesResult = await this.sourcePool.query(`
60
- SELECT e.enumlabel
61
- FROM pg_enum e
62
- JOIN pg_type t ON e.enumtypid = t.oid
63
- WHERE t.typname = $1
64
- ORDER BY e.enumsortorder
65
- `, [enumName]);
66
-
67
- const sourceEnumValues = sourceEnumValuesResult.rows.map(row => row.enumlabel);
68
- this.logger.log(`Source enum ${enumName} has values: ${sourceEnumValues.join(', ')}`);
69
-
70
- // Verificar si el enum existe en la base de datos de destino
71
- const targetEnumExistsResult = await this.targetPool.query(`
72
- SELECT 1
73
- FROM pg_type t
74
- JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
75
- WHERE t.typtype = 'e'
76
- AND t.typname = $1
77
- AND n.nspname = 'public'
78
- LIMIT 1
79
- `, [enumName]);
80
-
81
- if (targetEnumExistsResult.rows.length === 0) {
82
- // Si el enum no existe en el destino, crearlo
83
- await this.createEnumType(enumName, sourceEnumValues);
84
- } else {
85
- // Si el enum existe, actualizar sus valores
86
- await this.updateEnumValues(enumName, sourceEnumValues);
87
- }
88
- } catch (error) {
89
- this.logger.error(`Error synchronizing enum type ${enumName}: ${error.message}`);
90
- }
91
- }
92
-
93
- private async createEnumType(enumName: string, values: string[]) {
94
- this.logger.log(`Creating enum type ${enumName} in target database`);
95
-
96
- try {
97
- // Escapar los valores para la consulta SQL
98
- const escapedValues = values.map(value => `'${value.replace(/'/g, "''")}'`).join(', ');
99
-
100
- // Crear el tipo enum
101
- await this.targetPool.query(`
102
- CREATE TYPE ${enumName} AS ENUM (${escapedValues})
103
- `);
104
-
105
- this.logger.log(`Successfully created enum type ${enumName} with values: ${values.join(', ')}`);
106
- } catch (error) {
107
- this.logger.error(`Error creating enum type ${enumName}: ${error.message}`);
108
- }
109
- }
110
-
111
- private async updateEnumValues(enumName: string, sourceValues: string[]) {
112
- this.logger.log(`Updating enum type ${enumName} in target database`);
113
-
114
- try {
115
- // Obtener valores actuales del enum en la base de datos de destino
116
- const targetEnumValuesResult = await this.targetPool.query(`
117
- SELECT e.enumlabel
118
- FROM pg_enum e
119
- JOIN pg_type t ON e.enumtypid = t.oid
120
- WHERE t.typname = $1
121
- ORDER BY e.enumsortorder
122
- `, [enumName]);
123
-
124
- const targetEnumValues = targetEnumValuesResult.rows.map(row => row.enumlabel);
125
- this.logger.log(`Target enum ${enumName} has values: ${targetEnumValues.join(', ')}`);
126
-
127
- // Encontrar valores que están en el origen pero no en el destino
128
- const missingValues = sourceValues.filter(value => !targetEnumValues.includes(value));
129
-
130
- if (missingValues.length === 0) {
131
- this.logger.log(`Enum type ${enumName} is already up to date`);
132
- return;
133
- }
134
-
135
- this.logger.log(`Adding ${missingValues.length} new values to enum ${enumName}: ${missingValues.join(', ')}`);
136
-
137
- // Agregar los valores faltantes al enum
138
- for (const value of missingValues) {
139
- await this.targetPool.query(`
140
- ALTER TYPE ${enumName} ADD VALUE '${value.replace(/'/g, "''")}'
141
- `);
142
- }
143
-
144
- this.logger.log(`Successfully updated enum type ${enumName}`);
145
- } catch (error) {
146
- this.logger.error(`Error updating enum type ${enumName}: ${error.message}`);
147
- }
148
- }
149
-
150
- private async cleanup() {
151
- this.logger.log('Cleaning up database connections');
152
- await this.sourcePool.end();
153
- await this.targetPool.end();
154
- }
155
- }
156
-
157
- // Script para ejecutar desde línea de comandos
158
- if (require.main === module) {
159
- const run = async () => {
160
- try {
161
- const synchronizer = new EnumSynchronizer();
162
- await synchronizer.synchronizeEnums();
163
- process.exit(0);
164
- } catch (error) {
165
- console.error('Error:', error.message);
166
- process.exit(1);
167
- }
168
- };
169
-
170
- run();
1
+ import * as pg from 'pg';
2
+ import * as dotenv from 'dotenv';
3
+ import { Logger } from '@nestjs/common';
4
+
5
+ dotenv.config();
6
+
7
+ export class EnumSynchronizer {
8
+ private readonly logger = new Logger('EnumSynchronizer');
9
+ private readonly sourcePool: pg.Pool;
10
+ private readonly targetPool: pg.Pool;
11
+
12
+ constructor(
13
+ private readonly sourceUrl: string = process.env.SOURCE_DATABASE_URL,
14
+ private readonly targetUrl: string = process.env.DATABASE_URL
15
+ ) {
16
+ this.sourcePool = new pg.Pool({
17
+ connectionString: this.sourceUrl,
18
+ });
19
+
20
+ this.targetPool = new pg.Pool({
21
+ connectionString: this.targetUrl,
22
+ });
23
+ }
24
+
25
+ async synchronizeEnums() {
26
+ try {
27
+ this.logger.log('Starting enum synchronization');
28
+
29
+ // Obtener todos los tipos enum en la base de datos de origen
30
+ const sourceEnumsResult = await this.sourcePool.query(`
31
+ SELECT t.typname AS enum_name
32
+ FROM pg_type t
33
+ JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
34
+ WHERE t.typtype = 'e'
35
+ AND n.nspname = 'public'
36
+ `);
37
+
38
+ this.logger.log(`Found ${sourceEnumsResult.rows.length} enum types in source database`);
39
+
40
+ // Para cada tipo enum, sincronizar sus valores
41
+ for (const enumRow of sourceEnumsResult.rows) {
42
+ const enumName = enumRow.enum_name;
43
+ await this.synchronizeEnumType(enumName);
44
+ }
45
+
46
+ this.logger.log('Enum synchronization completed successfully');
47
+ } catch (error) {
48
+ this.logger.error(`Error during enum synchronization: ${error.message}`, error.stack);
49
+ } finally {
50
+ await this.cleanup();
51
+ }
52
+ }
53
+
54
+ private async synchronizeEnumType(enumName: string) {
55
+ this.logger.log(`Synchronizing enum type: ${enumName}`);
56
+
57
+ try {
58
+ // Obtener valores del enum en la base de datos de origen
59
+ const sourceEnumValuesResult = await this.sourcePool.query(`
60
+ SELECT e.enumlabel
61
+ FROM pg_enum e
62
+ JOIN pg_type t ON e.enumtypid = t.oid
63
+ WHERE t.typname = $1
64
+ ORDER BY e.enumsortorder
65
+ `, [enumName]);
66
+
67
+ const sourceEnumValues = sourceEnumValuesResult.rows.map(row => row.enumlabel);
68
+ this.logger.log(`Source enum ${enumName} has values: ${sourceEnumValues.join(', ')}`);
69
+
70
+ // Verificar si el enum existe en la base de datos de destino
71
+ const targetEnumExistsResult = await this.targetPool.query(`
72
+ SELECT 1
73
+ FROM pg_type t
74
+ JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
75
+ WHERE t.typtype = 'e'
76
+ AND t.typname = $1
77
+ AND n.nspname = 'public'
78
+ LIMIT 1
79
+ `, [enumName]);
80
+
81
+ if (targetEnumExistsResult.rows.length === 0) {
82
+ // Si el enum no existe en el destino, crearlo
83
+ await this.createEnumType(enumName, sourceEnumValues);
84
+ } else {
85
+ // Si el enum existe, actualizar sus valores
86
+ await this.updateEnumValues(enumName, sourceEnumValues);
87
+ }
88
+ } catch (error) {
89
+ this.logger.error(`Error synchronizing enum type ${enumName}: ${error.message}`);
90
+ }
91
+ }
92
+
93
+ private async createEnumType(enumName: string, values: string[]) {
94
+ this.logger.log(`Creating enum type ${enumName} in target database`);
95
+
96
+ try {
97
+ // Escapar los valores para la consulta SQL
98
+ const escapedValues = values.map(value => `'${value.replace(/'/g, "''")}'`).join(', ');
99
+
100
+ // Crear el tipo enum
101
+ await this.targetPool.query(`
102
+ CREATE TYPE ${enumName} AS ENUM (${escapedValues})
103
+ `);
104
+
105
+ this.logger.log(`Successfully created enum type ${enumName} with values: ${values.join(', ')}`);
106
+ } catch (error) {
107
+ this.logger.error(`Error creating enum type ${enumName}: ${error.message}`);
108
+ }
109
+ }
110
+
111
+ private async updateEnumValues(enumName: string, sourceValues: string[]) {
112
+ this.logger.log(`Updating enum type ${enumName} in target database`);
113
+
114
+ try {
115
+ // Obtener valores actuales del enum en la base de datos de destino
116
+ const targetEnumValuesResult = await this.targetPool.query(`
117
+ SELECT e.enumlabel
118
+ FROM pg_enum e
119
+ JOIN pg_type t ON e.enumtypid = t.oid
120
+ WHERE t.typname = $1
121
+ ORDER BY e.enumsortorder
122
+ `, [enumName]);
123
+
124
+ const targetEnumValues = targetEnumValuesResult.rows.map(row => row.enumlabel);
125
+ this.logger.log(`Target enum ${enumName} has values: ${targetEnumValues.join(', ')}`);
126
+
127
+ // Encontrar valores que están en el origen pero no en el destino
128
+ const missingValues = sourceValues.filter(value => !targetEnumValues.includes(value));
129
+
130
+ if (missingValues.length === 0) {
131
+ this.logger.log(`Enum type ${enumName} is already up to date`);
132
+ return;
133
+ }
134
+
135
+ this.logger.log(`Adding ${missingValues.length} new values to enum ${enumName}: ${missingValues.join(', ')}`);
136
+
137
+ // Agregar los valores faltantes al enum
138
+ for (const value of missingValues) {
139
+ await this.targetPool.query(`
140
+ ALTER TYPE ${enumName} ADD VALUE '${value.replace(/'/g, "''")}'
141
+ `);
142
+ }
143
+
144
+ this.logger.log(`Successfully updated enum type ${enumName}`);
145
+ } catch (error) {
146
+ this.logger.error(`Error updating enum type ${enumName}: ${error.message}`);
147
+ }
148
+ }
149
+
150
+ private async cleanup() {
151
+ this.logger.log('Cleaning up database connections');
152
+ await this.sourcePool.end();
153
+ await this.targetPool.end();
154
+ }
155
+ }
156
+
157
+ // Script para ejecutar desde línea de comandos
158
+ if (require.main === module) {
159
+ const run = async () => {
160
+ try {
161
+ const synchronizer = new EnumSynchronizer();
162
+ await synchronizer.synchronizeEnums();
163
+ process.exit(0);
164
+ } catch (error) {
165
+ console.error('Error:', error.message);
166
+ process.exit(1);
167
+ }
168
+ };
169
+
170
+ run();
171
171
  }