@javalabs/prisma-client 1.0.18 → 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.
- package/.dockerignore +14 -0
- package/Dockerfile +23 -0
- package/README.md +269 -269
- package/dist/index.d.ts +1 -1
- package/dist/prisma.service.d.ts +1 -1
- package/dist/scripts/add-uuid-to-table.js +32 -32
- package/dist/scripts/data-migration/batch-migrator.js +12 -12
- package/dist/scripts/data-migration/data-transformer.js +14 -14
- package/dist/scripts/data-migration/dependency-resolver.js +23 -23
- package/dist/scripts/data-migration/entity-discovery.js +68 -68
- package/dist/scripts/data-migration/foreign-key-manager.js +23 -23
- package/dist/scripts/data-migration/migration-tool.js +5 -5
- package/dist/scripts/data-migration/schema-utils.js +74 -74
- package/dist/scripts/data-migration/typecast-manager.js +4 -4
- package/dist/scripts/database-initializer.js +5 -5
- package/dist/scripts/drop-database.js +5 -5
- package/dist/scripts/fix-data-types.js +53 -53
- package/dist/scripts/fix-enum-values.js +34 -34
- package/dist/scripts/fix-schema-discrepancies.js +40 -40
- package/dist/scripts/fix-table-indexes.js +81 -81
- package/dist/scripts/migrate-schema-structure.js +4 -4
- package/dist/scripts/migrate-uuid.js +19 -19
- package/dist/scripts/post-migration-validator.js +49 -49
- package/dist/scripts/pre-migration-validator.js +107 -107
- package/dist/scripts/reset-database.js +21 -21
- package/dist/scripts/retry-failed-migrations.js +28 -28
- package/dist/scripts/run-migration.js +5 -5
- package/dist/scripts/schema-sync.js +18 -18
- package/dist/scripts/sequence-sync-cli.js +55 -55
- package/dist/scripts/sequence-synchronizer.js +20 -20
- package/dist/scripts/sync-enum-types.js +30 -30
- package/dist/scripts/sync-enum-values.js +52 -52
- package/dist/scripts/truncate-database.js +10 -10
- package/dist/scripts/verify-migration-setup.js +10 -10
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/migration-config.json +63 -63
- package/migration-config.json.bk +95 -95
- package/package.json +44 -44
- package/prisma/migrations/add_accepts_partial_payments_to_users.sql +19 -0
- package/prisma/migrations/add_amount_received_to_manual_payments.sql +19 -0
- package/prisma/migrations/add_commission_fields.sql +33 -0
- package/prisma/migrations/add_uuid_to_transactions.sql +13 -13
- package/prisma/migrations/complete_partial_payments_migration.sql +53 -0
- package/prisma/migrations/create_settlements_table.sql +60 -0
- package/prisma/schema.prisma +47 -1
- package/src/index.ts +23 -23
- package/src/prisma-factory.service.ts +40 -40
- package/src/prisma.module.ts +9 -9
- package/src/prisma.service.ts +16 -16
- package/src/scripts/add-uuid-to-table.ts +138 -138
- package/src/scripts/create-tenant-schemas.ts +145 -145
- package/src/scripts/data-migration/batch-migrator.ts +248 -248
- package/src/scripts/data-migration/data-transformer.ts +426 -426
- package/src/scripts/data-migration/db-connector.ts +120 -120
- package/src/scripts/data-migration/dependency-resolver.ts +174 -174
- package/src/scripts/data-migration/entity-discovery.ts +196 -196
- package/src/scripts/data-migration/foreign-key-manager.ts +277 -277
- package/src/scripts/data-migration/migration-config.json +63 -63
- package/src/scripts/data-migration/migration-tool.ts +509 -509
- package/src/scripts/data-migration/schema-utils.ts +248 -248
- package/src/scripts/data-migration/tenant-migrator.ts +201 -201
- package/src/scripts/data-migration/typecast-manager.ts +193 -193
- package/src/scripts/data-migration/types.ts +113 -113
- package/src/scripts/database-initializer.ts +49 -49
- package/src/scripts/drop-database.ts +104 -104
- package/src/scripts/dump-source-db.sh +61 -61
- package/src/scripts/encrypt-user-passwords.ts +36 -36
- package/src/scripts/error-handler.ts +117 -117
- package/src/scripts/fix-data-types.ts +241 -241
- package/src/scripts/fix-enum-values.ts +357 -357
- package/src/scripts/fix-schema-discrepancies.ts +317 -317
- package/src/scripts/fix-table-indexes.ts +601 -601
- package/src/scripts/migrate-schema-structure.ts +90 -90
- package/src/scripts/migrate-uuid.ts +76 -76
- package/src/scripts/post-migration-validator.ts +526 -526
- package/src/scripts/pre-migration-validator.ts +610 -610
- package/src/scripts/reset-database.ts +263 -263
- package/src/scripts/retry-failed-migrations.ts +416 -416
- package/src/scripts/run-migration.ts +707 -707
- package/src/scripts/schema-sync.ts +128 -128
- package/src/scripts/sequence-sync-cli.ts +416 -416
- package/src/scripts/sequence-synchronizer.ts +127 -127
- package/src/scripts/sync-enum-types.ts +170 -170
- package/src/scripts/sync-enum-values.ts +563 -563
- package/src/scripts/truncate-database.ts +123 -123
- package/src/scripts/verify-migration-setup.ts +135 -135
- package/tsconfig.json +17 -17
- package/dist/scripts/data-migration/dependency-manager.d.ts +0 -9
- package/dist/scripts/data-migration/dependency-manager.js +0 -86
- package/dist/scripts/data-migration/dependency-manager.js.map +0 -1
- package/dist/scripts/data-migration/migration-config.json +0 -63
- package/dist/scripts/data-migration/migration-phases.d.ts +0 -5
- package/dist/scripts/data-migration/migration-phases.js +0 -55
- package/dist/scripts/data-migration/migration-phases.js.map +0 -1
- package/dist/scripts/data-migration/multi-source-migrator.d.ts +0 -17
- package/dist/scripts/data-migration/multi-source-migrator.js +0 -130
- package/dist/scripts/data-migration/multi-source-migrator.js.map +0 -1
- package/dist/scripts/data-migration/phase-generator.d.ts +0 -15
- package/dist/scripts/data-migration/phase-generator.js +0 -187
- package/dist/scripts/data-migration/phase-generator.js.map +0 -1
- package/dist/scripts/data-migration.d.ts +0 -22
- package/dist/scripts/data-migration.js +0 -593
- package/dist/scripts/data-migration.js.map +0 -1
- package/dist/scripts/multi-db-migration.d.ts +0 -1
- package/dist/scripts/multi-db-migration.js +0 -55
- package/dist/scripts/multi-db-migration.js.map +0 -1
|
@@ -36,18 +36,18 @@ catch (error) {
|
|
|
36
36
|
}
|
|
37
37
|
async function findExistingSequence(pool, tableName, columnName) {
|
|
38
38
|
try {
|
|
39
|
-
const query = `
|
|
40
|
-
SELECT
|
|
41
|
-
s.relname as sequence_name
|
|
42
|
-
FROM pg_class s
|
|
43
|
-
JOIN pg_depend d ON d.objid = s.oid
|
|
44
|
-
JOIN pg_class t ON d.refobjid = t.oid
|
|
45
|
-
JOIN pg_attribute a ON (d.refobjid, d.refobjsubid) = (a.attrelid, a.attnum)
|
|
46
|
-
JOIN pg_namespace n ON n.oid = s.relnamespace
|
|
47
|
-
WHERE s.relkind = 'S'
|
|
48
|
-
AND n.nspname = 'public'
|
|
49
|
-
AND t.relname = $1
|
|
50
|
-
AND a.attname = $2;
|
|
39
|
+
const query = `
|
|
40
|
+
SELECT
|
|
41
|
+
s.relname as sequence_name
|
|
42
|
+
FROM pg_class s
|
|
43
|
+
JOIN pg_depend d ON d.objid = s.oid
|
|
44
|
+
JOIN pg_class t ON d.refobjid = t.oid
|
|
45
|
+
JOIN pg_attribute a ON (d.refobjid, d.refobjsubid) = (a.attrelid, a.attnum)
|
|
46
|
+
JOIN pg_namespace n ON n.oid = s.relnamespace
|
|
47
|
+
WHERE s.relkind = 'S'
|
|
48
|
+
AND n.nspname = 'public'
|
|
49
|
+
AND t.relname = $1
|
|
50
|
+
AND a.attname = $2;
|
|
51
51
|
`;
|
|
52
52
|
const result = await pool.query(query, [tableName, columnName]);
|
|
53
53
|
if (result.rows.length > 0) {
|
|
@@ -81,14 +81,14 @@ async function findOrCreateSequence(pool, tableName, columnName) {
|
|
|
81
81
|
`${tableName}_seq`,
|
|
82
82
|
];
|
|
83
83
|
for (const name of possibleNames) {
|
|
84
|
-
const exists = await pool.query(`
|
|
85
|
-
SELECT EXISTS (
|
|
86
|
-
SELECT 1 FROM pg_class c
|
|
87
|
-
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
88
|
-
WHERE n.nspname = 'public'
|
|
89
|
-
AND c.relname = $1
|
|
90
|
-
AND c.relkind = 'S'
|
|
91
|
-
);
|
|
84
|
+
const exists = await pool.query(`
|
|
85
|
+
SELECT EXISTS (
|
|
86
|
+
SELECT 1 FROM pg_class c
|
|
87
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
88
|
+
WHERE n.nspname = 'public'
|
|
89
|
+
AND c.relname = $1
|
|
90
|
+
AND c.relkind = 'S'
|
|
91
|
+
);
|
|
92
92
|
`, [name]);
|
|
93
93
|
if (exists.rows[0].exists) {
|
|
94
94
|
sequenceName = name;
|
|
@@ -100,25 +100,25 @@ async function findOrCreateSequence(pool, tableName, columnName) {
|
|
|
100
100
|
if (options.verbose) {
|
|
101
101
|
logger.log(`Creating new sequence: ${sequenceName}`);
|
|
102
102
|
}
|
|
103
|
-
const maxValQuery = `
|
|
104
|
-
SELECT COALESCE(MAX("${columnName}"), 0) as max_val
|
|
105
|
-
FROM "${tableName}";
|
|
103
|
+
const maxValQuery = `
|
|
104
|
+
SELECT COALESCE(MAX("${columnName}"), 0) as max_val
|
|
105
|
+
FROM "${tableName}";
|
|
106
106
|
`;
|
|
107
107
|
const maxValResult = await pool.query(maxValQuery);
|
|
108
108
|
const maxVal = parseInt(maxValResult.rows[0].max_val);
|
|
109
109
|
if (!options.dryRun) {
|
|
110
|
-
await pool.query(`
|
|
111
|
-
CREATE SEQUENCE IF NOT EXISTS "${sequenceName}"
|
|
112
|
-
START WITH ${maxVal + 1}
|
|
113
|
-
INCREMENT BY 1
|
|
114
|
-
NO MINVALUE
|
|
115
|
-
NO MAXVALUE
|
|
116
|
-
CACHE 1;
|
|
110
|
+
await pool.query(`
|
|
111
|
+
CREATE SEQUENCE IF NOT EXISTS "${sequenceName}"
|
|
112
|
+
START WITH ${maxVal + 1}
|
|
113
|
+
INCREMENT BY 1
|
|
114
|
+
NO MINVALUE
|
|
115
|
+
NO MAXVALUE
|
|
116
|
+
CACHE 1;
|
|
117
117
|
`);
|
|
118
|
-
await pool.query(`
|
|
119
|
-
ALTER TABLE "${tableName}"
|
|
120
|
-
ALTER COLUMN "${columnName}"
|
|
121
|
-
SET DEFAULT nextval('${sequenceName}'::regclass);
|
|
118
|
+
await pool.query(`
|
|
119
|
+
ALTER TABLE "${tableName}"
|
|
120
|
+
ALTER COLUMN "${columnName}"
|
|
121
|
+
SET DEFAULT nextval('${sequenceName}'::regclass);
|
|
122
122
|
`);
|
|
123
123
|
logger.log(`✅ Sequence created and associated: ${sequenceName}`);
|
|
124
124
|
}
|
|
@@ -135,13 +135,13 @@ async function findOrCreateSequence(pool, tableName, columnName) {
|
|
|
135
135
|
}
|
|
136
136
|
async function getTableInfo(pool, tableName, idField) {
|
|
137
137
|
try {
|
|
138
|
-
const tableExistsQuery = `
|
|
139
|
-
SELECT EXISTS (
|
|
140
|
-
SELECT 1
|
|
141
|
-
FROM information_schema.tables
|
|
142
|
-
WHERE table_schema = $1
|
|
143
|
-
AND table_name = $2
|
|
144
|
-
);
|
|
138
|
+
const tableExistsQuery = `
|
|
139
|
+
SELECT EXISTS (
|
|
140
|
+
SELECT 1
|
|
141
|
+
FROM information_schema.tables
|
|
142
|
+
WHERE table_schema = $1
|
|
143
|
+
AND table_name = $2
|
|
144
|
+
);
|
|
145
145
|
`;
|
|
146
146
|
const tableExists = await pool.query(tableExistsQuery, [
|
|
147
147
|
migrationConfig.commonSchema,
|
|
@@ -152,14 +152,14 @@ async function getTableInfo(pool, tableName, idField) {
|
|
|
152
152
|
return null;
|
|
153
153
|
}
|
|
154
154
|
const sequenceName = await findOrCreateSequence(pool, tableName, idField);
|
|
155
|
-
const columnQuery = `
|
|
156
|
-
SELECT EXISTS (
|
|
157
|
-
SELECT 1 FROM pg_attrdef ad
|
|
158
|
-
JOIN pg_attribute a ON a.attrelid = ad.adrelid AND a.attnum = ad.adnum
|
|
159
|
-
WHERE a.attrelid = $1::regclass
|
|
160
|
-
AND a.attname = $2
|
|
161
|
-
AND (pg_get_expr(ad.adbin, ad.adrelid) LIKE 'nextval%' OR $3::text IS NOT NULL)
|
|
162
|
-
) as is_auto_increment;
|
|
155
|
+
const columnQuery = `
|
|
156
|
+
SELECT EXISTS (
|
|
157
|
+
SELECT 1 FROM pg_attrdef ad
|
|
158
|
+
JOIN pg_attribute a ON a.attrelid = ad.adrelid AND a.attnum = ad.adnum
|
|
159
|
+
WHERE a.attrelid = $1::regclass
|
|
160
|
+
AND a.attname = $2
|
|
161
|
+
AND (pg_get_expr(ad.adbin, ad.adrelid) LIKE 'nextval%' OR $3::text IS NOT NULL)
|
|
162
|
+
) as is_auto_increment;
|
|
163
163
|
`;
|
|
164
164
|
const columnResult = await pool.query(columnQuery, [
|
|
165
165
|
tableName,
|
|
@@ -202,14 +202,14 @@ async function checkTableSequence(pool, tableName) {
|
|
|
202
202
|
logger.log(`- Primary key column: ${tableInfo.primaryKeyColumn}`);
|
|
203
203
|
logger.log(`- Sequence: ${tableInfo.sequenceName}`);
|
|
204
204
|
}
|
|
205
|
-
const maxIdResult = await pool.query(`
|
|
206
|
-
SELECT COALESCE(MAX("${tableInfo.primaryKeyColumn}"), 0) as max_id
|
|
207
|
-
FROM "${tableInfo.tableName}";
|
|
205
|
+
const maxIdResult = await pool.query(`
|
|
206
|
+
SELECT COALESCE(MAX("${tableInfo.primaryKeyColumn}"), 0) as max_id
|
|
207
|
+
FROM "${tableInfo.tableName}";
|
|
208
208
|
`);
|
|
209
209
|
const maxId = parseInt(maxIdResult.rows[0].max_id);
|
|
210
|
-
const seqResult = await pool.query(`
|
|
211
|
-
SELECT last_value, is_called
|
|
212
|
-
FROM "${tableInfo.sequenceName}";
|
|
210
|
+
const seqResult = await pool.query(`
|
|
211
|
+
SELECT last_value, is_called
|
|
212
|
+
FROM "${tableInfo.sequenceName}";
|
|
213
213
|
`);
|
|
214
214
|
const currentSeqValue = parseInt(seqResult.rows[0].last_value);
|
|
215
215
|
const isCalled = seqResult.rows[0].is_called;
|
|
@@ -29,49 +29,49 @@ class SequenceSynchronizer {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
async getTables() {
|
|
32
|
-
const query = `
|
|
33
|
-
SELECT table_name
|
|
34
|
-
FROM information_schema.tables
|
|
35
|
-
WHERE table_schema = 'public'
|
|
36
|
-
AND table_type = 'BASE TABLE'
|
|
32
|
+
const query = `
|
|
33
|
+
SELECT table_name
|
|
34
|
+
FROM information_schema.tables
|
|
35
|
+
WHERE table_schema = 'public'
|
|
36
|
+
AND table_type = 'BASE TABLE'
|
|
37
37
|
`;
|
|
38
38
|
const result = await this.pool.query(query);
|
|
39
39
|
return result.rows.map((row) => row.table_name);
|
|
40
40
|
}
|
|
41
41
|
async synchronizeTableSequences(tableName) {
|
|
42
42
|
try {
|
|
43
|
-
const columns = await this.pool.query(`
|
|
44
|
-
SELECT column_name
|
|
45
|
-
FROM information_schema.columns
|
|
46
|
-
WHERE table_name = $1
|
|
47
|
-
AND column_name = 'id'
|
|
43
|
+
const columns = await this.pool.query(`
|
|
44
|
+
SELECT column_name
|
|
45
|
+
FROM information_schema.columns
|
|
46
|
+
WHERE table_name = $1
|
|
47
|
+
AND column_name = 'id'
|
|
48
48
|
`, [tableName]);
|
|
49
49
|
if (columns.rows.length === 0) {
|
|
50
50
|
this.logger.debug(`La tabla ${tableName} no tiene columna id, omitiendo`);
|
|
51
51
|
return;
|
|
52
52
|
}
|
|
53
53
|
const sequenceName = `${tableName}_id_seq`;
|
|
54
|
-
const sequences = await this.pool.query(`
|
|
55
|
-
SELECT sequence_name
|
|
56
|
-
FROM information_schema.sequences
|
|
57
|
-
WHERE sequence_name = $1
|
|
54
|
+
const sequences = await this.pool.query(`
|
|
55
|
+
SELECT sequence_name
|
|
56
|
+
FROM information_schema.sequences
|
|
57
|
+
WHERE sequence_name = $1
|
|
58
58
|
`, [sequenceName]);
|
|
59
59
|
if (sequences.rows.length === 0) {
|
|
60
60
|
this.logger.debug(`No se encontró secuencia para la tabla ${tableName}, omitiendo`);
|
|
61
61
|
return;
|
|
62
62
|
}
|
|
63
|
-
const maxResult = await this.pool.query(`
|
|
64
|
-
SELECT COALESCE(MAX(id), 0) as max_id FROM "${tableName}"
|
|
63
|
+
const maxResult = await this.pool.query(`
|
|
64
|
+
SELECT COALESCE(MAX(id), 0) as max_id FROM "${tableName}"
|
|
65
65
|
`);
|
|
66
66
|
const maxId = maxResult.rows[0].max_id;
|
|
67
|
-
const currValResult = await this.pool.query(`
|
|
68
|
-
SELECT last_value FROM "${sequenceName}"
|
|
67
|
+
const currValResult = await this.pool.query(`
|
|
68
|
+
SELECT last_value FROM "${sequenceName}"
|
|
69
69
|
`);
|
|
70
70
|
const currVal = currValResult.rows[0].last_value;
|
|
71
71
|
this.logger.log(`Tabla ${tableName}: ID Máximo = ${maxId}, Valor Actual de Secuencia = ${currVal}`);
|
|
72
72
|
if (currVal <= maxId) {
|
|
73
|
-
await this.pool.query(`
|
|
74
|
-
SELECT setval($1, $2, true)
|
|
73
|
+
await this.pool.query(`
|
|
74
|
+
SELECT setval($1, $2, true)
|
|
75
75
|
`, [sequenceName, maxId]);
|
|
76
76
|
this.logger.log(`Actualizada secuencia para tabla ${tableName} a ${maxId}`);
|
|
77
77
|
}
|
|
@@ -20,12 +20,12 @@ class EnumSynchronizer {
|
|
|
20
20
|
async synchronizeEnums() {
|
|
21
21
|
try {
|
|
22
22
|
this.logger.log('Starting enum synchronization');
|
|
23
|
-
const sourceEnumsResult = await this.sourcePool.query(`
|
|
24
|
-
SELECT t.typname AS enum_name
|
|
25
|
-
FROM pg_type t
|
|
26
|
-
JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
|
|
27
|
-
WHERE t.typtype = 'e'
|
|
28
|
-
AND n.nspname = 'public'
|
|
23
|
+
const sourceEnumsResult = await this.sourcePool.query(`
|
|
24
|
+
SELECT t.typname AS enum_name
|
|
25
|
+
FROM pg_type t
|
|
26
|
+
JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
|
|
27
|
+
WHERE t.typtype = 'e'
|
|
28
|
+
AND n.nspname = 'public'
|
|
29
29
|
`);
|
|
30
30
|
this.logger.log(`Found ${sourceEnumsResult.rows.length} enum types in source database`);
|
|
31
31
|
for (const enumRow of sourceEnumsResult.rows) {
|
|
@@ -44,23 +44,23 @@ class EnumSynchronizer {
|
|
|
44
44
|
async synchronizeEnumType(enumName) {
|
|
45
45
|
this.logger.log(`Synchronizing enum type: ${enumName}`);
|
|
46
46
|
try {
|
|
47
|
-
const sourceEnumValuesResult = await this.sourcePool.query(`
|
|
48
|
-
SELECT e.enumlabel
|
|
49
|
-
FROM pg_enum e
|
|
50
|
-
JOIN pg_type t ON e.enumtypid = t.oid
|
|
51
|
-
WHERE t.typname = $1
|
|
52
|
-
ORDER BY e.enumsortorder
|
|
47
|
+
const sourceEnumValuesResult = await this.sourcePool.query(`
|
|
48
|
+
SELECT e.enumlabel
|
|
49
|
+
FROM pg_enum e
|
|
50
|
+
JOIN pg_type t ON e.enumtypid = t.oid
|
|
51
|
+
WHERE t.typname = $1
|
|
52
|
+
ORDER BY e.enumsortorder
|
|
53
53
|
`, [enumName]);
|
|
54
54
|
const sourceEnumValues = sourceEnumValuesResult.rows.map(row => row.enumlabel);
|
|
55
55
|
this.logger.log(`Source enum ${enumName} has values: ${sourceEnumValues.join(', ')}`);
|
|
56
|
-
const targetEnumExistsResult = await this.targetPool.query(`
|
|
57
|
-
SELECT 1
|
|
58
|
-
FROM pg_type t
|
|
59
|
-
JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
|
|
60
|
-
WHERE t.typtype = 'e'
|
|
61
|
-
AND t.typname = $1
|
|
62
|
-
AND n.nspname = 'public'
|
|
63
|
-
LIMIT 1
|
|
56
|
+
const targetEnumExistsResult = await this.targetPool.query(`
|
|
57
|
+
SELECT 1
|
|
58
|
+
FROM pg_type t
|
|
59
|
+
JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
|
|
60
|
+
WHERE t.typtype = 'e'
|
|
61
|
+
AND t.typname = $1
|
|
62
|
+
AND n.nspname = 'public'
|
|
63
|
+
LIMIT 1
|
|
64
64
|
`, [enumName]);
|
|
65
65
|
if (targetEnumExistsResult.rows.length === 0) {
|
|
66
66
|
await this.createEnumType(enumName, sourceEnumValues);
|
|
@@ -77,8 +77,8 @@ class EnumSynchronizer {
|
|
|
77
77
|
this.logger.log(`Creating enum type ${enumName} in target database`);
|
|
78
78
|
try {
|
|
79
79
|
const escapedValues = values.map(value => `'${value.replace(/'/g, "''")}'`).join(', ');
|
|
80
|
-
await this.targetPool.query(`
|
|
81
|
-
CREATE TYPE ${enumName} AS ENUM (${escapedValues})
|
|
80
|
+
await this.targetPool.query(`
|
|
81
|
+
CREATE TYPE ${enumName} AS ENUM (${escapedValues})
|
|
82
82
|
`);
|
|
83
83
|
this.logger.log(`Successfully created enum type ${enumName} with values: ${values.join(', ')}`);
|
|
84
84
|
}
|
|
@@ -89,12 +89,12 @@ class EnumSynchronizer {
|
|
|
89
89
|
async updateEnumValues(enumName, sourceValues) {
|
|
90
90
|
this.logger.log(`Updating enum type ${enumName} in target database`);
|
|
91
91
|
try {
|
|
92
|
-
const targetEnumValuesResult = await this.targetPool.query(`
|
|
93
|
-
SELECT e.enumlabel
|
|
94
|
-
FROM pg_enum e
|
|
95
|
-
JOIN pg_type t ON e.enumtypid = t.oid
|
|
96
|
-
WHERE t.typname = $1
|
|
97
|
-
ORDER BY e.enumsortorder
|
|
92
|
+
const targetEnumValuesResult = await this.targetPool.query(`
|
|
93
|
+
SELECT e.enumlabel
|
|
94
|
+
FROM pg_enum e
|
|
95
|
+
JOIN pg_type t ON e.enumtypid = t.oid
|
|
96
|
+
WHERE t.typname = $1
|
|
97
|
+
ORDER BY e.enumsortorder
|
|
98
98
|
`, [enumName]);
|
|
99
99
|
const targetEnumValues = targetEnumValuesResult.rows.map(row => row.enumlabel);
|
|
100
100
|
this.logger.log(`Target enum ${enumName} has values: ${targetEnumValues.join(', ')}`);
|
|
@@ -105,8 +105,8 @@ class EnumSynchronizer {
|
|
|
105
105
|
}
|
|
106
106
|
this.logger.log(`Adding ${missingValues.length} new values to enum ${enumName}: ${missingValues.join(', ')}`);
|
|
107
107
|
for (const value of missingValues) {
|
|
108
|
-
await this.targetPool.query(`
|
|
109
|
-
ALTER TYPE ${enumName} ADD VALUE '${value.replace(/'/g, "''")}'
|
|
108
|
+
await this.targetPool.query(`
|
|
109
|
+
ALTER TYPE ${enumName} ADD VALUE '${value.replace(/'/g, "''")}'
|
|
110
110
|
`);
|
|
111
111
|
}
|
|
112
112
|
this.logger.log(`Successfully updated enum type ${enumName}`);
|
|
@@ -93,13 +93,13 @@ class EnumValueSynchronizer {
|
|
|
93
93
|
if (!fs.existsSync(logsDir)) {
|
|
94
94
|
fs.mkdirSync(logsDir, { recursive: true });
|
|
95
95
|
}
|
|
96
|
-
const enumsResult = await this.pool.query(`
|
|
97
|
-
SELECT t.typname AS enum_name
|
|
98
|
-
FROM pg_type t
|
|
99
|
-
JOIN pg_namespace n ON t.typnamespace = n.oid
|
|
100
|
-
WHERE t.typtype = 'e' -- enum types
|
|
101
|
-
AND n.nspname = 'public'
|
|
102
|
-
ORDER BY t.typname
|
|
96
|
+
const enumsResult = await this.pool.query(`
|
|
97
|
+
SELECT t.typname AS enum_name
|
|
98
|
+
FROM pg_type t
|
|
99
|
+
JOIN pg_namespace n ON t.typnamespace = n.oid
|
|
100
|
+
WHERE t.typtype = 'e' -- enum types
|
|
101
|
+
AND n.nspname = 'public'
|
|
102
|
+
ORDER BY t.typname
|
|
103
103
|
`);
|
|
104
104
|
this.logger.log(`Encontrados ${enumsResult.rows.length} tipos enum en la base de datos`);
|
|
105
105
|
for (const [specificEnum, consolidatedEnum] of Object.entries(this.enumMappings)) {
|
|
@@ -145,33 +145,33 @@ class EnumValueSynchronizer {
|
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
147
|
async enumExists(enumName) {
|
|
148
|
-
const result = await this.pool.query(`
|
|
149
|
-
SELECT 1
|
|
150
|
-
FROM pg_type t
|
|
151
|
-
JOIN pg_namespace n ON t.typnamespace = n.oid
|
|
152
|
-
WHERE t.typname = $1
|
|
153
|
-
AND t.typtype = 'e' -- enum types
|
|
154
|
-
AND n.nspname = 'public'
|
|
148
|
+
const result = await this.pool.query(`
|
|
149
|
+
SELECT 1
|
|
150
|
+
FROM pg_type t
|
|
151
|
+
JOIN pg_namespace n ON t.typnamespace = n.oid
|
|
152
|
+
WHERE t.typname = $1
|
|
153
|
+
AND t.typtype = 'e' -- enum types
|
|
154
|
+
AND n.nspname = 'public'
|
|
155
155
|
`, [enumName]);
|
|
156
156
|
return result.rows.length > 0;
|
|
157
157
|
}
|
|
158
158
|
async getEnumValues(enumName) {
|
|
159
|
-
const result = await this.pool.query(`
|
|
160
|
-
SELECT e.enumlabel
|
|
161
|
-
FROM pg_enum e
|
|
162
|
-
JOIN pg_type t ON e.enumtypid = t.oid
|
|
163
|
-
JOIN pg_namespace n ON t.typnamespace = n.oid
|
|
164
|
-
WHERE t.typname = $1
|
|
165
|
-
AND n.nspname = 'public'
|
|
166
|
-
ORDER BY e.enumsortorder
|
|
159
|
+
const result = await this.pool.query(`
|
|
160
|
+
SELECT e.enumlabel
|
|
161
|
+
FROM pg_enum e
|
|
162
|
+
JOIN pg_type t ON e.enumtypid = t.oid
|
|
163
|
+
JOIN pg_namespace n ON t.typnamespace = n.oid
|
|
164
|
+
WHERE t.typname = $1
|
|
165
|
+
AND n.nspname = 'public'
|
|
166
|
+
ORDER BY e.enumsortorder
|
|
167
167
|
`, [enumName]);
|
|
168
168
|
return result.rows.map((row) => row.enumlabel);
|
|
169
169
|
}
|
|
170
170
|
async addValueToEnum(enumName, value) {
|
|
171
171
|
try {
|
|
172
172
|
const escapedValue = value.replace(/'/g, "''");
|
|
173
|
-
await this.pool.query(`
|
|
174
|
-
ALTER TYPE ${enumName} ADD VALUE IF NOT EXISTS '${escapedValue}'
|
|
173
|
+
await this.pool.query(`
|
|
174
|
+
ALTER TYPE ${enumName} ADD VALUE IF NOT EXISTS '${escapedValue}'
|
|
175
175
|
`);
|
|
176
176
|
if (this.enumValuesCache[enumName]) {
|
|
177
177
|
if (!this.enumValuesCache[enumName].includes(value)) {
|
|
@@ -200,28 +200,28 @@ class EnumValueSynchronizer {
|
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
202
|
async getSchemas() {
|
|
203
|
-
const result = await this.pool.query(`
|
|
204
|
-
SELECT schema_name
|
|
205
|
-
FROM information_schema.schemata
|
|
206
|
-
WHERE schema_name NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
|
|
207
|
-
AND schema_name NOT LIKE 'pg_%'
|
|
203
|
+
const result = await this.pool.query(`
|
|
204
|
+
SELECT schema_name
|
|
205
|
+
FROM information_schema.schemata
|
|
206
|
+
WHERE schema_name NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
|
|
207
|
+
AND schema_name NOT LIKE 'pg_%'
|
|
208
208
|
`);
|
|
209
209
|
return result.rows.map((row) => row.schema_name);
|
|
210
210
|
}
|
|
211
211
|
async normalizeEnumValuesInSchema(schema) {
|
|
212
212
|
this.logger.log(`Procesando valores de enum en schema: ${schema}`);
|
|
213
213
|
try {
|
|
214
|
-
const enumColumnsQuery = `
|
|
215
|
-
SELECT
|
|
216
|
-
c.table_name,
|
|
217
|
-
c.column_name,
|
|
218
|
-
c.udt_name
|
|
219
|
-
FROM
|
|
220
|
-
information_schema.columns c
|
|
221
|
-
WHERE
|
|
222
|
-
c.table_schema = $1
|
|
223
|
-
AND c.data_type = 'USER-DEFINED'
|
|
224
|
-
AND c.udt_name LIKE 'enum_%'
|
|
214
|
+
const enumColumnsQuery = `
|
|
215
|
+
SELECT
|
|
216
|
+
c.table_name,
|
|
217
|
+
c.column_name,
|
|
218
|
+
c.udt_name
|
|
219
|
+
FROM
|
|
220
|
+
information_schema.columns c
|
|
221
|
+
WHERE
|
|
222
|
+
c.table_schema = $1
|
|
223
|
+
AND c.data_type = 'USER-DEFINED'
|
|
224
|
+
AND c.udt_name LIKE 'enum_%'
|
|
225
225
|
`;
|
|
226
226
|
const enumColumnsResult = await this.pool.query(enumColumnsQuery, [
|
|
227
227
|
schema,
|
|
@@ -254,10 +254,10 @@ class EnumValueSynchronizer {
|
|
|
254
254
|
this.logger.warn(`No se encontraron valores para el enum ${enumTypeName}. Omitiendo.`);
|
|
255
255
|
return;
|
|
256
256
|
}
|
|
257
|
-
const currentValuesQuery = `
|
|
258
|
-
SELECT DISTINCT "${columnName}"
|
|
259
|
-
FROM "${schema}"."${tableName}"
|
|
260
|
-
WHERE "${columnName}" IS NOT NULL
|
|
257
|
+
const currentValuesQuery = `
|
|
258
|
+
SELECT DISTINCT "${columnName}"
|
|
259
|
+
FROM "${schema}"."${tableName}"
|
|
260
|
+
WHERE "${columnName}" IS NOT NULL
|
|
261
261
|
`;
|
|
262
262
|
const currentValuesResult = await this.pool.query(currentValuesQuery);
|
|
263
263
|
const currentValues = currentValuesResult.rows.map((r) => r[columnName]);
|
|
@@ -270,10 +270,10 @@ class EnumValueSynchronizer {
|
|
|
270
270
|
for (const invalidValue of invalidValues) {
|
|
271
271
|
const normalizedValue = this.getNormalizedEnumValue(enumTypeName, invalidValue);
|
|
272
272
|
if (normalizedValue && normalizedValue !== invalidValue) {
|
|
273
|
-
const updateQuery = `
|
|
274
|
-
UPDATE "${schema}"."${tableName}"
|
|
275
|
-
SET "${columnName}" = $1
|
|
276
|
-
WHERE "${columnName}" = $2
|
|
273
|
+
const updateQuery = `
|
|
274
|
+
UPDATE "${schema}"."${tableName}"
|
|
275
|
+
SET "${columnName}" = $1
|
|
276
|
+
WHERE "${columnName}" = $2
|
|
277
277
|
`;
|
|
278
278
|
const result = await this.pool.query(updateQuery, [
|
|
279
279
|
normalizedValue,
|
|
@@ -285,10 +285,10 @@ class EnumValueSynchronizer {
|
|
|
285
285
|
}
|
|
286
286
|
}
|
|
287
287
|
else if (!normalizedValue) {
|
|
288
|
-
const updateQuery = `
|
|
289
|
-
UPDATE "${schema}"."${tableName}"
|
|
290
|
-
SET "${columnName}" = NULL
|
|
291
|
-
WHERE "${columnName}" = $1
|
|
288
|
+
const updateQuery = `
|
|
289
|
+
UPDATE "${schema}"."${tableName}"
|
|
290
|
+
SET "${columnName}" = NULL
|
|
291
|
+
WHERE "${columnName}" = $1
|
|
292
292
|
`;
|
|
293
293
|
const result = await this.pool.query(updateQuery, [invalidValue]);
|
|
294
294
|
this.logger.log(`Establecido valor '${invalidValue}' a NULL en ${result.rowCount} filas de ${schema}.${tableName}.${columnName}`);
|
|
@@ -32,22 +32,22 @@ class DatabaseTruncateTool {
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
async getSchemas() {
|
|
35
|
-
const result = await this.pool.query(`
|
|
36
|
-
SELECT schema_name
|
|
37
|
-
FROM information_schema.schemata
|
|
38
|
-
WHERE schema_name NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
|
|
39
|
-
AND schema_name NOT LIKE 'pg_%'
|
|
35
|
+
const result = await this.pool.query(`
|
|
36
|
+
SELECT schema_name
|
|
37
|
+
FROM information_schema.schemata
|
|
38
|
+
WHERE schema_name NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
|
|
39
|
+
AND schema_name NOT LIKE 'pg_%'
|
|
40
40
|
`);
|
|
41
41
|
return result.rows.map(row => row.schema_name);
|
|
42
42
|
}
|
|
43
43
|
async truncateSchema(schemaName) {
|
|
44
44
|
this.logger.log(`Processing schema: ${schemaName}`);
|
|
45
45
|
try {
|
|
46
|
-
const tablesResult = await this.pool.query(`
|
|
47
|
-
SELECT table_name
|
|
48
|
-
FROM information_schema.tables
|
|
49
|
-
WHERE table_schema = $1
|
|
50
|
-
AND table_type = 'BASE TABLE'
|
|
46
|
+
const tablesResult = await this.pool.query(`
|
|
47
|
+
SELECT table_name
|
|
48
|
+
FROM information_schema.tables
|
|
49
|
+
WHERE table_schema = $1
|
|
50
|
+
AND table_type = 'BASE TABLE'
|
|
51
51
|
`, [schemaName]);
|
|
52
52
|
const tables = tablesResult.rows.map(row => row.table_name);
|
|
53
53
|
if (tables.length === 0) {
|
|
@@ -56,11 +56,11 @@ class MigrationSetupVerifier {
|
|
|
56
56
|
async verifyTenants() {
|
|
57
57
|
this.logger.log('Verifying tenants in source database...');
|
|
58
58
|
try {
|
|
59
|
-
const result = await this.sourcePool.query(`
|
|
60
|
-
SELECT api_key, provider_id
|
|
61
|
-
FROM api_keys
|
|
62
|
-
WHERE api_key != ''
|
|
63
|
-
AND provider_id IS NOT NULL
|
|
59
|
+
const result = await this.sourcePool.query(`
|
|
60
|
+
SELECT api_key, provider_id
|
|
61
|
+
FROM api_keys
|
|
62
|
+
WHERE api_key != ''
|
|
63
|
+
AND provider_id IS NOT NULL
|
|
64
64
|
`);
|
|
65
65
|
this.logger.log(`Found ${result.rows.length} valid tenants in source database`);
|
|
66
66
|
if (result.rows.length === 0) {
|
|
@@ -80,11 +80,11 @@ class MigrationSetupVerifier {
|
|
|
80
80
|
async verifySchemas() {
|
|
81
81
|
this.logger.log('Verifying schemas in target database...');
|
|
82
82
|
try {
|
|
83
|
-
const result = await this.targetPool.query(`
|
|
84
|
-
SELECT schema_name
|
|
85
|
-
FROM information_schema.schemata
|
|
86
|
-
WHERE schema_name NOT IN ('public', 'information_schema', 'pg_catalog', 'pg_toast')
|
|
87
|
-
AND schema_name NOT LIKE 'pg_%'
|
|
83
|
+
const result = await this.targetPool.query(`
|
|
84
|
+
SELECT schema_name
|
|
85
|
+
FROM information_schema.schemata
|
|
86
|
+
WHERE schema_name NOT IN ('public', 'information_schema', 'pg_catalog', 'pg_toast')
|
|
87
|
+
AND schema_name NOT LIKE 'pg_%'
|
|
88
88
|
`);
|
|
89
89
|
this.logger.log(`Found ${result.rows.length} schemas in target database`);
|
|
90
90
|
if (result.rows.length === 0) {
|