@cheetah.js/cli 0.1.26 → 0.1.27

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.
@@ -1,466 +0,0 @@
1
- import { DriverInterface, EntityStorage, PgDriver } from '@cheetah.js/orm';
2
- import { ColDiff, ColumnsInfo, SnapshotTable, TableDiff } from './migrator';
3
-
4
- export class DiffCalculator {
5
- private entities: EntityStorage;
6
-
7
- constructor(
8
- entities: EntityStorage,
9
- private driver: DriverInterface,
10
- ) {
11
- this.entities = entities;
12
- }
13
-
14
- diff(snapshotBd: SnapshotTable[], snapshotEntities: SnapshotTable[]): TableDiff[] {
15
- const diffs: TableDiff[] = [];
16
- // Cria um mapa (dicionário) para facilitar o acesso por nome da tabela
17
- const bdTablesMap = new Map(snapshotBd.map((table) => [table.tableName, table]));
18
- const entityTablesMap = new Map(
19
- snapshotEntities.map((table) => [table.tableName, table]),
20
- );
21
-
22
- // Junta todos os nomes de tabelas
23
- const allTableNames = new Set([
24
- ...bdTablesMap.keys(),
25
- ...entityTablesMap.keys(),
26
- ]);
27
-
28
- allTableNames.forEach((tableName) => {
29
- const bdTable = bdTablesMap.get(tableName);
30
- const entityTable = entityTablesMap.get(tableName);
31
-
32
- if (!entityTable) {
33
- // Se a tabela só está no banco de dados, precisamos deletá-la
34
- diffs.push({
35
- tableName,
36
- colDiffs: [{ actionType: 'DELETE', colName: '*' }], // Indica que todas as colunas devem ser deletadas (ou seja, a tabela inteira)
37
- });
38
- } else if (!bdTable) {
39
- const colDiffs: ColDiff[] = entityTable.columns.flatMap((c) => {
40
- return this.createNewColumn(c, []);
41
- });
42
- // Se a tabela só está nas entidades, precisamos criá-la
43
- diffs.push({
44
- tableName,
45
- newTable: true,
46
- schema: entityTable.schema ?? 'public',
47
- colDiffs, // Indica que todas as colunas devem ser criadas
48
- });
49
- this.checkIndexes(bdTable, entityTable, colDiffs);
50
- } else {
51
- const colDiffs: ColDiff[] = [];
52
- // Se a tabela está em ambos, precisamos comparar as colunas
53
- const bdColumnsMap = new Map(bdTable.columns.map((col) => [col.name, col]));
54
- const entityColumnsMap = new Map(
55
- entityTable.columns.map((col) => [col.name, col]),
56
- );
57
- const allColumnNames = new Set([
58
- ...bdColumnsMap.keys(),
59
- ...entityColumnsMap.keys(),
60
- ]);
61
-
62
- allColumnNames.forEach((colName) => {
63
- const bdCol = bdColumnsMap.get(colName);
64
- const entityCol = entityColumnsMap.get(colName);
65
-
66
- if (!entityCol) {
67
- colDiffs.push({
68
- actionType: 'DELETE',
69
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
70
- //@ts-ignore
71
- colName: bdCol!.name,
72
- });
73
- } else if (!bdCol) {
74
- this.createNewColumn(entityCol, colDiffs);
75
- } else this.diffColumnSql(bdCol, entityCol, colDiffs);
76
- });
77
-
78
- this.checkIndexes(bdTable, entityTable, colDiffs);
79
-
80
- if (colDiffs.length > 0) {
81
- diffs.push({
82
- tableName: tableName,
83
- schema: entityTable.schema ?? 'public',
84
- colDiffs,
85
- });
86
- }
87
- }
88
- });
89
-
90
- return diffs;
91
- }
92
-
93
- private checkIndexes(
94
- bdTable: SnapshotTable | undefined,
95
- entityTable: SnapshotTable | undefined,
96
- colDiffs: ColDiff[],
97
- ) {
98
- if ((bdTable && bdTable.indexes) || (entityTable && entityTable.indexes)) {
99
- if (!bdTable || !bdTable.indexes) {
100
- colDiffs.push({
101
- actionType: 'INDEX',
102
- colName: '*',
103
- indexTables: entityTable!.indexes.map((index) => ({
104
- name: index.indexName,
105
- properties: index.columnName.split(','),
106
- })),
107
- });
108
- }
109
- if (!entityTable || !entityTable.indexes) {
110
- colDiffs.push({
111
- actionType: 'INDEX',
112
- colName: '*',
113
- indexTables: bdTable!.indexes.map((index) => ({ name: index.indexName })),
114
- });
115
- }
116
- }
117
-
118
- if (bdTable && bdTable.indexes && entityTable && entityTable.indexes) {
119
- const bdIndexesMap = new Map(
120
- bdTable.indexes.map((index) => [index.indexName, index]),
121
- );
122
- const entityIndexesMap = new Map(
123
- entityTable.indexes.map((index) => [index.indexName, index]),
124
- );
125
- const allIndexes = new Set([
126
- ...bdIndexesMap.keys(),
127
- ...entityIndexesMap.keys(),
128
- ]);
129
- allIndexes.forEach((indexName) => {
130
- const bdIndex = bdIndexesMap.get(indexName);
131
- const entityIndex = entityIndexesMap.get(indexName);
132
-
133
- if (!entityIndex) {
134
- colDiffs.push({
135
- actionType: 'INDEX',
136
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
137
- //@ts-ignore
138
- colName: bdIndex!.columnName,
139
- indexTables: [{ name: indexName }],
140
- });
141
- } else if (!bdIndex) {
142
- colDiffs.push({
143
- actionType: 'INDEX',
144
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
145
- //@ts-ignore
146
- colName: entityIndex.columnName,
147
- indexTables: [
148
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
149
- //@ts-ignore
150
- { name: indexName, properties: entityIndex.columnName.split(',') },
151
- ],
152
- });
153
- }
154
- });
155
- }
156
- }
157
-
158
- private createNewColumn(entityCol: ColumnsInfo, colDiffs: ColDiff[]): ColDiff[] {
159
- const colType = this.convertEntityTypeToSqlType(entityCol.type);
160
-
161
- colDiffs.push({
162
- actionType: 'CREATE',
163
- colName: entityCol.name,
164
- colType: colType.type,
165
- colLength: entityCol.length ?? colType.len,
166
- colChanges: {
167
- autoIncrement: entityCol.autoIncrement,
168
- default: entityCol.default,
169
- primary: entityCol.primary,
170
- unique: entityCol.unique,
171
- nullable: entityCol.nullable,
172
- enumItems: entityCol.enumItems,
173
- foreignKeys: entityCol.foreignKeys ?? undefined,
174
- precision: entityCol.precision ?? undefined,
175
- scale: entityCol.scale ?? undefined,
176
- },
177
- });
178
-
179
- return colDiffs;
180
- }
181
-
182
- private diffColumnType(
183
- bdCol: ColumnsInfo,
184
- entityCol: ColumnsInfo,
185
- colDiffs: ColDiff[],
186
- ): void {
187
- // if (bdCol.type === 'integer' && bdCol.primary) {
188
- // bdCol.type = 'numeric';
189
- // bdCol.length = 11;
190
- // }
191
- const isPostgres = this.driver instanceof PgDriver;
192
-
193
- if (bdCol.type === 'USER-DEFINED') {
194
- bdCol.type = 'enum';
195
- }
196
-
197
- const colT = this.convertEntityTypeToSqlType(entityCol.type);
198
- const colType = colT.type;
199
- let length = entityCol.length ?? colT.len;
200
-
201
- if (colType === 'integer' && isPostgres) {
202
- length = 32;
203
- }
204
-
205
- if (bdCol.isDecimal && isPostgres) {
206
- bdCol.type = 'decimal';
207
- length = bdCol.precision ?? 0;
208
- }
209
-
210
- if (!bdCol.type.includes(colType) || bdCol.length !== length) {
211
- colDiffs.push({
212
- actionType: 'ALTER',
213
- colName: entityCol.name,
214
- colType: colType,
215
- colLength: length,
216
- colChanges: {
217
- enumItems: entityCol.enumItems || undefined,
218
- precision: entityCol.precision ?? undefined,
219
- scale: entityCol.scale ?? undefined,
220
- },
221
- });
222
- }
223
- }
224
-
225
- private diffColumnDefault(
226
- bdCol: ColumnsInfo,
227
- entityCol: ColumnsInfo,
228
- colDiffs: ColDiff[],
229
- ): void {
230
- if (bdCol.default !== (entityCol.default ?? null)) {
231
- colDiffs.push({
232
- actionType: 'ALTER',
233
- colName: entityCol.name,
234
- colChanges: { default: entityCol.default },
235
- colLength: entityCol.length,
236
- });
237
- }
238
- }
239
-
240
- private diffColumnPrimary(
241
- bdCol: ColumnsInfo,
242
- entityCol: ColumnsInfo,
243
- colDiffs: ColDiff[],
244
- ): void {
245
- if (bdCol.primary !== (entityCol.primary ?? false)) {
246
- colDiffs.push({
247
- actionType: 'ALTER',
248
- colName: entityCol.name,
249
- colChanges: { primary: entityCol.primary },
250
- colLength: entityCol.length,
251
- });
252
- }
253
- }
254
-
255
- private diffColumnUnique(
256
- bdCol: ColumnsInfo,
257
- entityCol: ColumnsInfo,
258
- colDiffs: ColDiff[],
259
- ): void {
260
- if (bdCol.unique !== (entityCol.unique ?? false)) {
261
- if (bdCol.unique === false && entityCol.unique === undefined) {
262
- return;
263
- }
264
-
265
- if (entityCol.primary) {
266
- return;
267
- }
268
-
269
- colDiffs.push({
270
- actionType: 'ALTER',
271
- colName: entityCol.name,
272
- colChanges: { unique: entityCol.unique || false },
273
- colLength: entityCol.length,
274
- });
275
- }
276
- }
277
-
278
- private diffForeignKey(
279
- bdCol: ColumnsInfo,
280
- entityCol: ColumnsInfo,
281
- colDiffs: ColDiff[],
282
- ): void {
283
- if (bdCol.foreignKeys || entityCol.foreignKeys) {
284
- const bdFKMap = new Map(
285
- (bdCol.foreignKeys || []).map((fk) => [
286
- `${fk.referencedTableName}.${fk.referencedColumnName}`,
287
- fk,
288
- ]),
289
- );
290
- const entityFKMap = new Map(
291
- (entityCol.foreignKeys || []).map((fk) => [
292
- `${fk.referencedTableName}.${fk.referencedColumnName}`,
293
- fk,
294
- ]),
295
- );
296
-
297
- const allFKs = new Set([...bdFKMap.keys(), ...entityFKMap.keys()]);
298
-
299
- allFKs.forEach((fkName) => {
300
- const bdFK = bdFKMap.get(fkName);
301
- const entityFK = entityFKMap.get(fkName);
302
-
303
- if (!entityFK) {
304
- const fks = bdCol.foreignKeys?.filter((fk: any) => fk !== bdFK);
305
- colDiffs.push({
306
- actionType: 'ALTER',
307
- colName: bdCol.name,
308
- colChanges: {
309
- foreignKeys: fks.length > 0 ? fks : [],
310
- },
311
- });
312
- }
313
- // else if (!bdFK) {
314
- // colDiffs.push({
315
- // actionType: 'ALTER',
316
- // colName: entityCol.name,
317
- // colChanges: {
318
- // foreignKeys: [...(bdCol.foreignKeys || []), entityFK],
319
- // },
320
- // });
321
- // }
322
- });
323
- }
324
- }
325
-
326
- private diffColumnSql(
327
- bdCol: ColumnsInfo,
328
- entityCol: ColumnsInfo,
329
- colDiffs: ColDiff[],
330
- ) {
331
- this.diffForeignKey(bdCol, entityCol, colDiffs);
332
- this.diffEnum(bdCol, entityCol, colDiffs);
333
- this.diffColumnType(bdCol, entityCol, colDiffs);
334
- this.diffColumnDefault(bdCol, entityCol, colDiffs);
335
- this.diffColumnPrimary(bdCol, entityCol, colDiffs);
336
- this.diffColumnUnique(bdCol, entityCol, colDiffs);
337
- this.diffColumnNullable(bdCol, entityCol, colDiffs);
338
- this.diffColumnPrecisionAndScale(bdCol, entityCol, colDiffs);
339
-
340
- return colDiffs;
341
- }
342
-
343
- diffColumnPrecisionAndScale(
344
- bdCol: ColumnsInfo,
345
- entityCol: ColumnsInfo,
346
- colDiffs: ColDiff[],
347
- ) {
348
- const bdPrecision = bdCol.precision ?? 0;
349
- const entityPrecision = entityCol.precision ?? bdPrecision;
350
- const bdScale = bdCol.scale ?? 0;
351
- const entityScale = entityCol.scale ?? bdCol.scale;
352
-
353
- if (
354
- bdCol.isDecimal &&
355
- (bdPrecision !== entityPrecision ||
356
- (bdCol.isDecimal && bdScale !== entityScale))
357
- ) {
358
- colDiffs.push({
359
- actionType: 'ALTER',
360
- colType: 'decimal',
361
- colName: entityCol.name,
362
- colChanges: {
363
- precision: entityCol.precision ?? 0,
364
- scale: entityCol.scale ?? 0,
365
- },
366
- colLength: entityCol.length,
367
- });
368
- }
369
- }
370
-
371
- private diffColumnNullable(
372
- bdCol: ColumnsInfo,
373
- entityCol: ColumnsInfo,
374
- colDiffs: ColDiff[],
375
- ) {
376
- if (bdCol.nullable !== (entityCol.nullable ?? false)) {
377
- colDiffs.push({
378
- actionType: 'ALTER',
379
- colName: entityCol.name,
380
- colChanges: { nullable: entityCol.nullable ?? false },
381
- colLength: entityCol.length,
382
- });
383
- }
384
- }
385
-
386
- // TODO: Precisa ser de acordo com o driver
387
- // adicionar 'varchar' | 'text' | 'int' | 'bigint' | 'float' | 'double' | 'decimal' | 'date' | 'datetime' | 'time' | 'timestamp' | 'boolean' | 'json' | 'jsonb' | 'enum' | 'array' | 'uuid'
388
- private convertEntityTypeToSqlType(entityType: string): {
389
- type: string;
390
- len?: number;
391
- } {
392
- switch (entityType) {
393
- case 'Number':
394
- case 'int':
395
- return { type: 'integer', len: 32 };
396
- case 'bigint':
397
- return { type: 'bigint' };
398
- case 'float':
399
- case 'double':
400
- case 'decimal':
401
- return { type: 'decimal' };
402
- case 'String':
403
- case 'varchar':
404
- return { type: 'character varying', len: 255 };
405
- case 'Boolean':
406
- return { type: 'boolean', len: null };
407
- case 'Date':
408
- return { type: 'timestamp' };
409
- case 'Object':
410
- return { type: 'json', len: null };
411
- case 'uuid':
412
- return { type: 'uuid', len: null };
413
- case 'text':
414
- return { type: 'text' };
415
- case 'enum':
416
- return { type: 'enum', len: null };
417
- default:
418
- return { type: 'character varying', len: 255 };
419
- //... mais casos aqui ...
420
- }
421
- }
422
-
423
- private diffEnum(bdCol: ColumnsInfo, entityCol: ColumnsInfo, colDiffs: ColDiff[]) {
424
- if (bdCol.enumItems || entityCol.enumItems) {
425
- if (bdCol.enumItems && entityCol.enumItems) {
426
- const allEnums = new Set([...bdCol.enumItems, ...entityCol.enumItems]);
427
- const differences = [...allEnums].filter(
428
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
429
- //@ts-ignore
430
- (x) => !bdCol.enumItems?.includes(x) || !entityCol.enumItems?.includes(x),
431
- );
432
-
433
- if (differences.length === 0) {
434
- return;
435
- }
436
-
437
- colDiffs.push({
438
- actionType: 'ALTER',
439
- colName: entityCol.name,
440
- colType: 'enum',
441
- colChanges: {
442
- enumItems: entityCol.enumItems,
443
- },
444
- });
445
- }
446
-
447
- if (!entityCol.enumItems) {
448
- // colDiffs.push({
449
- // actionType: 'DELETE',
450
- // colName: bdCol.name,
451
- // colChanges: {
452
- // enumItems: [],
453
- // },
454
- // });
455
- } else if (!bdCol.enumItems) {
456
- colDiffs.push({
457
- actionType: 'CREATE',
458
- colName: entityCol.name,
459
- colChanges: {
460
- enumItems: entityCol.enumItems,
461
- },
462
- });
463
- }
464
- }
465
- }
466
- }