sonamu 0.0.20 → 0.0.22
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/dist/bin/cli.js +9 -0
- package/dist/bin/cli.js.map +1 -1
- package/dist/database/upsert-builder.d.ts +2 -0
- package/dist/database/upsert-builder.d.ts.map +1 -1
- package/dist/database/upsert-builder.js +25 -2
- package/dist/database/upsert-builder.js.map +1 -1
- package/dist/smd/migrator.d.ts +2 -0
- package/dist/smd/migrator.d.ts.map +1 -1
- package/dist/smd/migrator.js +92 -75
- package/dist/smd/migrator.js.map +1 -1
- package/dist/smd/smd-utils.d.ts +7 -1
- package/dist/smd/smd-utils.d.ts.map +1 -1
- package/dist/smd/smd-utils.js +18 -1
- package/dist/smd/smd-utils.js.map +1 -1
- package/dist/smd/smd.d.ts +3 -2
- package/dist/smd/smd.d.ts.map +1 -1
- package/dist/smd/smd.js +7 -17
- package/dist/smd/smd.js.map +1 -1
- package/dist/templates/model_test.template.js +1 -1
- package/dist/templates/smd.template.d.ts.map +1 -1
- package/dist/templates/smd.template.js +5 -1
- package/dist/templates/smd.template.js.map +1 -1
- package/dist/templates/view_search_input.template.js +3 -3
- package/dist/types/types.d.ts +14 -3
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/types.js +5 -1
- package/dist/types/types.js.map +1 -1
- package/package.json +1 -1
- package/src/bin/cli.ts +9 -0
- package/src/database/upsert-builder.ts +24 -2
- package/src/smd/migrator.ts +118 -92
- package/src/smd/smd-utils.ts +21 -0
- package/src/smd/smd.ts +19 -17
- package/src/templates/model_test.template.ts +1 -1
- package/src/templates/smd.template.ts +5 -1
- package/src/templates/view_search_input.template.ts +3 -3
- package/src/types/types.ts +18 -3
package/src/smd/migrator.ts
CHANGED
|
@@ -124,6 +124,18 @@ export class Migrator {
|
|
|
124
124
|
await this.cleanUpDist(true);
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
+
async check(): Promise<void> {
|
|
128
|
+
const codes = await this.compareMigrations();
|
|
129
|
+
if (codes.length === 0) {
|
|
130
|
+
console.log(chalk.green("\n현재 모두 싱크된 상태입니다."));
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// 현재 생성된 코드 표기
|
|
135
|
+
console.table(codes, ["type", "title"]);
|
|
136
|
+
console.log(codes[0]);
|
|
137
|
+
}
|
|
138
|
+
|
|
127
139
|
async run(): Promise<void> {
|
|
128
140
|
// pending 마이그레이션 확인
|
|
129
141
|
const [, pendingList] = await this.targets.pending.migrate.list();
|
|
@@ -420,14 +432,8 @@ export class Migrator {
|
|
|
420
432
|
).map((key) => {
|
|
421
433
|
// 배열 원소의 순서가 달라서 불일치가 발생하는걸 방지하기 위해 각 항목별로 정렬 처리 후 비교
|
|
422
434
|
if (key === "columnsAndIndexes") {
|
|
423
|
-
const smdColumns = sortBy(
|
|
424
|
-
|
|
425
|
-
(a: any) => (a as MigrationColumn).name
|
|
426
|
-
);
|
|
427
|
-
const dbColumns = sortBy(
|
|
428
|
-
dbSet.columns,
|
|
429
|
-
(a: any) => (a as MigrationColumn).name
|
|
430
|
-
);
|
|
435
|
+
const smdColumns = sortBy(smdSet.columns, (a: any) => a.name);
|
|
436
|
+
const dbColumns = sortBy(dbSet.columns, (a: any) => a.name);
|
|
431
437
|
|
|
432
438
|
/* 디버깅용 코드, 특정 컬럼에서 불일치 발생할 때 확인
|
|
433
439
|
const smdCreatedAt = smdSet.columns.find(
|
|
@@ -439,11 +445,11 @@ export class Migrator {
|
|
|
439
445
|
console.debug({ smdCreatedAt, dbCreatedAt });
|
|
440
446
|
*/
|
|
441
447
|
|
|
442
|
-
const smdIndexes = sortBy(smdSet.indexes, (a
|
|
443
|
-
|
|
448
|
+
const smdIndexes = sortBy(smdSet.indexes, (a) =>
|
|
449
|
+
[a.type, ...a.columns].join("-")
|
|
444
450
|
);
|
|
445
|
-
const dbIndexes = sortBy(dbSet.indexes, (a
|
|
446
|
-
|
|
451
|
+
const dbIndexes = sortBy(dbSet.indexes, (a) =>
|
|
452
|
+
[a.type, ...a.columns].join("-")
|
|
447
453
|
);
|
|
448
454
|
|
|
449
455
|
const isEqualColumns = equal(smdColumns, dbColumns);
|
|
@@ -462,17 +468,20 @@ export class Migrator {
|
|
|
462
468
|
);
|
|
463
469
|
}
|
|
464
470
|
} else {
|
|
465
|
-
const smdForeigns = sortBy(smdSet.foreigns, (a
|
|
466
|
-
|
|
471
|
+
const smdForeigns = sortBy(smdSet.foreigns, (a) =>
|
|
472
|
+
[a.to, ...a.columns].join("-")
|
|
467
473
|
);
|
|
468
|
-
const dbForeigns = sortBy(dbSet.foreigns, (a
|
|
469
|
-
|
|
474
|
+
const dbForeigns = sortBy(dbSet.foreigns, (a) =>
|
|
475
|
+
[a.to, ...a.columns].join("-")
|
|
470
476
|
);
|
|
471
477
|
|
|
472
478
|
if (equal(smdForeigns, dbForeigns) === false) {
|
|
473
|
-
// TODO FK alter
|
|
474
|
-
console.log(chalk.red(`FK 다름! ${smdSet.table}`));
|
|
475
479
|
// console.dir({ smdForeigns, dbForeigns }, { depth: null });
|
|
480
|
+
return this.generateAlterCode_Foreigns(
|
|
481
|
+
smdSet.table,
|
|
482
|
+
smdForeigns,
|
|
483
|
+
dbForeigns
|
|
484
|
+
);
|
|
476
485
|
}
|
|
477
486
|
}
|
|
478
487
|
return null;
|
|
@@ -550,9 +559,6 @@ export class Migrator {
|
|
|
550
559
|
columns: currentIndexes.map(
|
|
551
560
|
(currentIndex) => currentIndex.Column_name
|
|
552
561
|
),
|
|
553
|
-
...propIf(currentIndexes.length > 1, {
|
|
554
|
-
name: keyName,
|
|
555
|
-
}),
|
|
556
562
|
};
|
|
557
563
|
}
|
|
558
564
|
);
|
|
@@ -742,66 +748,6 @@ export class Migrator {
|
|
|
742
748
|
r.columns.push(column);
|
|
743
749
|
}
|
|
744
750
|
|
|
745
|
-
// 일반 컬럼 + ToOne 케이스 컬럼
|
|
746
|
-
if (
|
|
747
|
-
!isRelationProp(prop) ||
|
|
748
|
-
isBelongsToOneRelationProp(prop) ||
|
|
749
|
-
(isOneToOneRelationProp(prop) && prop.hasJoinColumn)
|
|
750
|
-
) {
|
|
751
|
-
const propName = !isRelationProp(prop)
|
|
752
|
-
? prop.name
|
|
753
|
-
: `${prop.name}_id`;
|
|
754
|
-
|
|
755
|
-
// index 처리
|
|
756
|
-
if (prop.index !== undefined) {
|
|
757
|
-
if (prop.index !== true) {
|
|
758
|
-
prop.index.map((indexName) => {
|
|
759
|
-
const namedOne = r.indexes.find(
|
|
760
|
-
(_index) => _index.name === indexName
|
|
761
|
-
);
|
|
762
|
-
if (namedOne) {
|
|
763
|
-
namedOne.columns.push(propName);
|
|
764
|
-
} else {
|
|
765
|
-
r.indexes.push({
|
|
766
|
-
type: "index",
|
|
767
|
-
columns: [propName],
|
|
768
|
-
name: indexName,
|
|
769
|
-
});
|
|
770
|
-
}
|
|
771
|
-
});
|
|
772
|
-
} else {
|
|
773
|
-
r.indexes.push({
|
|
774
|
-
type: "index",
|
|
775
|
-
columns: [propName],
|
|
776
|
-
});
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
// unique 처리
|
|
780
|
-
if (prop.unique !== undefined) {
|
|
781
|
-
if (prop.unique !== true) {
|
|
782
|
-
prop.unique.map((indexName) => {
|
|
783
|
-
const namedOne = r.indexes.find(
|
|
784
|
-
(_index) => _index.name === indexName
|
|
785
|
-
);
|
|
786
|
-
if (namedOne) {
|
|
787
|
-
namedOne.columns.push(propName);
|
|
788
|
-
} else {
|
|
789
|
-
r.indexes.push({
|
|
790
|
-
type: "unique",
|
|
791
|
-
columns: [propName],
|
|
792
|
-
name: indexName,
|
|
793
|
-
});
|
|
794
|
-
}
|
|
795
|
-
});
|
|
796
|
-
} else {
|
|
797
|
-
r.indexes.push({
|
|
798
|
-
type: "unique",
|
|
799
|
-
columns: [propName],
|
|
800
|
-
});
|
|
801
|
-
}
|
|
802
|
-
}
|
|
803
|
-
}
|
|
804
|
-
|
|
805
751
|
if (isManyToManyRelationProp(prop)) {
|
|
806
752
|
// ManyToMany 케이스
|
|
807
753
|
const relMd = SMDManager.get(prop.with);
|
|
@@ -888,6 +834,9 @@ export class Migrator {
|
|
|
888
834
|
}
|
|
889
835
|
);
|
|
890
836
|
|
|
837
|
+
// indexes
|
|
838
|
+
migrationSet.indexes = smd.indexes;
|
|
839
|
+
|
|
891
840
|
// uuid
|
|
892
841
|
migrationSet.columns = migrationSet.columns.concat({
|
|
893
842
|
name: "uuid",
|
|
@@ -949,15 +898,11 @@ export class Migrator {
|
|
|
949
898
|
}
|
|
950
899
|
const lines = uniq(
|
|
951
900
|
indexes.reduce((r, index) => {
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
.map((col) => `'${col}'`)
|
|
958
|
-
.join(",")}], '${index.name}')`
|
|
959
|
-
);
|
|
960
|
-
}
|
|
901
|
+
r.push(
|
|
902
|
+
`table.${index.type}([${index.columns
|
|
903
|
+
.map((col) => `'${col}'`)
|
|
904
|
+
.join(",")}])`
|
|
905
|
+
);
|
|
961
906
|
return r;
|
|
962
907
|
}, [] as string[])
|
|
963
908
|
);
|
|
@@ -1362,10 +1307,10 @@ export class Migrator {
|
|
|
1362
1307
|
};
|
|
1363
1308
|
const extraIndexes = {
|
|
1364
1309
|
db: differenceBy(dbIndexes, smdIndexes, (col) =>
|
|
1365
|
-
[col.type, col.
|
|
1310
|
+
[col.type, col.columns.join("-")].join("//")
|
|
1366
1311
|
),
|
|
1367
1312
|
smd: differenceBy(smdIndexes, dbIndexes, (col) =>
|
|
1368
|
-
[col.type, col.
|
|
1313
|
+
[col.type, col.columns.join("-")].join("//")
|
|
1369
1314
|
),
|
|
1370
1315
|
};
|
|
1371
1316
|
if (extraIndexes.smd.length > 0) {
|
|
@@ -1439,6 +1384,87 @@ export class Migrator {
|
|
|
1439
1384
|
return linesTo;
|
|
1440
1385
|
}
|
|
1441
1386
|
|
|
1387
|
+
generateAlterCode_Foreigns(
|
|
1388
|
+
table: string,
|
|
1389
|
+
smdForeigns: MigrationForeign[],
|
|
1390
|
+
dbForeigns: MigrationForeign[]
|
|
1391
|
+
): GenMigrationCode[] {
|
|
1392
|
+
// console.log({ smdForeigns, dbForeigns });
|
|
1393
|
+
|
|
1394
|
+
const getKey = (mf: MigrationForeign): string => {
|
|
1395
|
+
return [mf.columns.join("-"), mf.to].join("///");
|
|
1396
|
+
};
|
|
1397
|
+
const fkTo = smdForeigns.reduce(
|
|
1398
|
+
(result, smdF) => {
|
|
1399
|
+
const matchingDbF = dbForeigns.find(
|
|
1400
|
+
(dbF) => getKey(smdF) === getKey(dbF)
|
|
1401
|
+
);
|
|
1402
|
+
if (!matchingDbF) {
|
|
1403
|
+
result.add.push(smdF);
|
|
1404
|
+
return result;
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
if (equal(smdF, matchingDbF) === false) {
|
|
1408
|
+
result.alterSrc.push(matchingDbF);
|
|
1409
|
+
result.alterDst.push(smdF);
|
|
1410
|
+
return result;
|
|
1411
|
+
}
|
|
1412
|
+
return result;
|
|
1413
|
+
},
|
|
1414
|
+
{
|
|
1415
|
+
add: [] as MigrationForeign[],
|
|
1416
|
+
alterSrc: [] as MigrationForeign[],
|
|
1417
|
+
alterDst: [] as MigrationForeign[],
|
|
1418
|
+
}
|
|
1419
|
+
);
|
|
1420
|
+
|
|
1421
|
+
const linesTo = {
|
|
1422
|
+
add: this.genForeignDefinitions(table, fkTo.add),
|
|
1423
|
+
alterSrc: this.genForeignDefinitions(table, fkTo.alterSrc),
|
|
1424
|
+
alterDst: this.genForeignDefinitions(table, fkTo.alterDst),
|
|
1425
|
+
};
|
|
1426
|
+
|
|
1427
|
+
const lines: string[] = [
|
|
1428
|
+
'import { Knex } from "knex";',
|
|
1429
|
+
"",
|
|
1430
|
+
"export async function up(knex: Knex): Promise<void> {",
|
|
1431
|
+
`return knex.schema.alterTable("${table}", (table) => {`,
|
|
1432
|
+
...linesTo.add.up,
|
|
1433
|
+
...linesTo.alterSrc.down,
|
|
1434
|
+
...linesTo.alterDst.up,
|
|
1435
|
+
"})",
|
|
1436
|
+
"}",
|
|
1437
|
+
"",
|
|
1438
|
+
"export async function down(knex: Knex): Promise<void> {",
|
|
1439
|
+
`return knex.schema.alterTable("${table}", (table) => {`,
|
|
1440
|
+
...linesTo.add.down,
|
|
1441
|
+
...linesTo.alterDst.down,
|
|
1442
|
+
...linesTo.alterSrc.up,
|
|
1443
|
+
"})",
|
|
1444
|
+
"}",
|
|
1445
|
+
];
|
|
1446
|
+
|
|
1447
|
+
const formatted = prettier.format(lines.join("\n"), {
|
|
1448
|
+
parser: "typescript",
|
|
1449
|
+
});
|
|
1450
|
+
|
|
1451
|
+
const title = [
|
|
1452
|
+
"alter",
|
|
1453
|
+
table,
|
|
1454
|
+
"foreigns",
|
|
1455
|
+
// TODO 바뀌는 부분
|
|
1456
|
+
].join("_");
|
|
1457
|
+
|
|
1458
|
+
return [
|
|
1459
|
+
{
|
|
1460
|
+
table,
|
|
1461
|
+
title,
|
|
1462
|
+
formatted,
|
|
1463
|
+
type: "normal",
|
|
1464
|
+
},
|
|
1465
|
+
];
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1442
1468
|
async destroy(): Promise<void> {
|
|
1443
1469
|
await Promise.all(
|
|
1444
1470
|
this.targets.apply.map((db) => {
|
package/src/smd/smd-utils.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
JsonProp,
|
|
16
16
|
ManyToManyRelationProp,
|
|
17
17
|
OneToOneRelationProp,
|
|
18
|
+
SMDIndex,
|
|
18
19
|
StringProp,
|
|
19
20
|
TextProp,
|
|
20
21
|
TimeProp,
|
|
@@ -22,6 +23,7 @@ import {
|
|
|
22
23
|
UuidProp,
|
|
23
24
|
VirtualProp,
|
|
24
25
|
} from "../types/types";
|
|
26
|
+
import { asArray } from "../utils/model";
|
|
25
27
|
|
|
26
28
|
export const p = {
|
|
27
29
|
integer,
|
|
@@ -264,3 +266,22 @@ function relationManyToMany(
|
|
|
264
266
|
...option,
|
|
265
267
|
};
|
|
266
268
|
}
|
|
269
|
+
|
|
270
|
+
export const i = {
|
|
271
|
+
index,
|
|
272
|
+
unique,
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
function index(columns: string | string[]): SMDIndex {
|
|
276
|
+
return {
|
|
277
|
+
type: "index",
|
|
278
|
+
columns: asArray(columns),
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function unique(columns: string | string[]): SMDIndex {
|
|
283
|
+
return {
|
|
284
|
+
type: "unique",
|
|
285
|
+
columns: asArray(columns),
|
|
286
|
+
};
|
|
287
|
+
}
|
package/src/smd/smd.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
SMDPropNode,
|
|
16
16
|
isEnumProp,
|
|
17
17
|
StringProp,
|
|
18
|
+
SMDIndex,
|
|
18
19
|
} from "../types/types";
|
|
19
20
|
import inflection from "inflection";
|
|
20
21
|
import path from "path";
|
|
@@ -39,6 +40,7 @@ export class SMD {
|
|
|
39
40
|
relations: {
|
|
40
41
|
[key: string]: RelationProp;
|
|
41
42
|
};
|
|
43
|
+
indexes: SMDIndex[];
|
|
42
44
|
subsets: {
|
|
43
45
|
[key: string]: string[];
|
|
44
46
|
};
|
|
@@ -52,7 +54,15 @@ export class SMD {
|
|
|
52
54
|
[name: string]: EnumsLabelKo<string>;
|
|
53
55
|
} = {};
|
|
54
56
|
|
|
55
|
-
constructor({
|
|
57
|
+
constructor({
|
|
58
|
+
id,
|
|
59
|
+
parentId,
|
|
60
|
+
table,
|
|
61
|
+
title,
|
|
62
|
+
props,
|
|
63
|
+
indexes,
|
|
64
|
+
subsets,
|
|
65
|
+
}: SMDInput<any>) {
|
|
56
66
|
// id
|
|
57
67
|
this.id = id;
|
|
58
68
|
this.parentId = parentId;
|
|
@@ -91,6 +101,9 @@ export class SMD {
|
|
|
91
101
|
this.relations = {};
|
|
92
102
|
}
|
|
93
103
|
|
|
104
|
+
// indexes
|
|
105
|
+
this.indexes = indexes ?? [];
|
|
106
|
+
|
|
94
107
|
// subsets
|
|
95
108
|
this.subsets = subsets ?? {};
|
|
96
109
|
|
|
@@ -514,22 +527,11 @@ export class SMD {
|
|
|
514
527
|
|
|
515
528
|
registerTableSpecs(): void {
|
|
516
529
|
const uniqueColumns = uniq(
|
|
517
|
-
this.
|
|
518
|
-
.
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
: prop.name;
|
|
523
|
-
if (prop.unique === true) {
|
|
524
|
-
return propColumn;
|
|
525
|
-
} else if (prop.unique && Array.isArray(prop.unique)) {
|
|
526
|
-
return propColumn;
|
|
527
|
-
} else {
|
|
528
|
-
return null;
|
|
529
|
-
}
|
|
530
|
-
})
|
|
531
|
-
.filter((prop) => prop !== null)
|
|
532
|
-
) as string[];
|
|
530
|
+
this.indexes
|
|
531
|
+
.filter((idx) => idx.type === "unique")
|
|
532
|
+
.map((idx) => idx.columns)
|
|
533
|
+
.flat()
|
|
534
|
+
);
|
|
533
535
|
|
|
534
536
|
SMDManager.setTableSpec({
|
|
535
537
|
name: this.table,
|
|
@@ -21,7 +21,7 @@ export class Template__model_test extends Template {
|
|
|
21
21
|
...this.getTargetAndPath(names),
|
|
22
22
|
body: `
|
|
23
23
|
import { describe, test, expect } from "vitest";
|
|
24
|
-
import { bootstrap } from '../../testing/
|
|
24
|
+
import { bootstrap } from '../../testing/bootstrap';
|
|
25
25
|
|
|
26
26
|
bootstrap([]);
|
|
27
27
|
describe.skip("${smdId}ModelTest", () => {
|
|
@@ -21,7 +21,7 @@ export class Template__smd extends Template {
|
|
|
21
21
|
return {
|
|
22
22
|
...this.getTargetAndPath(names),
|
|
23
23
|
body: `
|
|
24
|
-
import { p, SMDInput } from "sonamu";
|
|
24
|
+
import { p, i, SMDInput } from "sonamu";
|
|
25
25
|
import { ${smdId}FieldExpr } from "./${names.fs}.generated";
|
|
26
26
|
|
|
27
27
|
/*
|
|
@@ -37,6 +37,10 @@ export const ${names.camel}SmdInput: SMDInput<${smdId}FieldExpr> = {
|
|
|
37
37
|
now: true,
|
|
38
38
|
}),
|
|
39
39
|
],
|
|
40
|
+
indexes: [
|
|
41
|
+
i.index('created_at'),
|
|
42
|
+
//
|
|
43
|
+
],
|
|
40
44
|
subsets: {
|
|
41
45
|
A: [ 'id', 'created_at' ]
|
|
42
46
|
}
|
|
@@ -34,8 +34,8 @@ export function ${names.capital}SearchInput({
|
|
|
34
34
|
}) {
|
|
35
35
|
const [keyword, setKeyword] = useState<string>(inputValue ?? '');
|
|
36
36
|
|
|
37
|
-
const handleKeyDown = (e: {
|
|
38
|
-
if (inputOnChange && e.
|
|
37
|
+
const handleKeyDown = (e: { key: string }) => {
|
|
38
|
+
if (inputOnChange && e.key === 'Enter') {
|
|
39
39
|
inputOnChange(e as any, {
|
|
40
40
|
value: keyword,
|
|
41
41
|
});
|
|
@@ -51,7 +51,7 @@ export function ${names.capital}SearchInput({
|
|
|
51
51
|
labelPosition="left"
|
|
52
52
|
action={{
|
|
53
53
|
icon: 'search',
|
|
54
|
-
onClick: () => handleKeyDown({
|
|
54
|
+
onClick: () => handleKeyDown({ key: 'Enter' }),
|
|
55
55
|
}}
|
|
56
56
|
{...inputProps}
|
|
57
57
|
value={keyword}
|
package/src/types/types.ts
CHANGED
|
@@ -122,8 +122,6 @@ type _RelationProp = {
|
|
|
122
122
|
name: string;
|
|
123
123
|
with: string;
|
|
124
124
|
nullable?: boolean;
|
|
125
|
-
index?: true | string[];
|
|
126
|
-
unique?: true | string[];
|
|
127
125
|
toFilter?: true;
|
|
128
126
|
};
|
|
129
127
|
export type OneToOneRelationProp = _RelationProp & {
|
|
@@ -180,12 +178,19 @@ export type SMDProp =
|
|
|
180
178
|
| VirtualProp
|
|
181
179
|
| RelationProp;
|
|
182
180
|
|
|
181
|
+
export type SMDIndex = {
|
|
182
|
+
type: "index" | "unique";
|
|
183
|
+
columns: string[];
|
|
184
|
+
name?: string;
|
|
185
|
+
};
|
|
186
|
+
|
|
183
187
|
export type SMDInput<T extends string> = {
|
|
184
188
|
id: string;
|
|
185
189
|
parentId?: string;
|
|
186
190
|
table?: string;
|
|
187
191
|
title?: string;
|
|
188
192
|
props?: SMDProp[];
|
|
193
|
+
indexes?: SMDIndex[];
|
|
189
194
|
subsets?: {
|
|
190
195
|
[subset: string]: T[];
|
|
191
196
|
};
|
|
@@ -323,6 +328,17 @@ export type SubsetQuery = {
|
|
|
323
328
|
};
|
|
324
329
|
|
|
325
330
|
/* Knex Migration */
|
|
331
|
+
export type KnexError = {
|
|
332
|
+
code: string;
|
|
333
|
+
errno: number;
|
|
334
|
+
sql: string;
|
|
335
|
+
sqlMessage: string;
|
|
336
|
+
sqlState: string;
|
|
337
|
+
};
|
|
338
|
+
export function isKnexError(e: any): e is KnexError {
|
|
339
|
+
return e.code && e.sqlMessage && e.sqlState;
|
|
340
|
+
}
|
|
341
|
+
|
|
326
342
|
export type KnexColumnType =
|
|
327
343
|
| "string"
|
|
328
344
|
| "text"
|
|
@@ -352,7 +368,6 @@ export type MigrationColumn = {
|
|
|
352
368
|
export type MigrationIndex = {
|
|
353
369
|
columns: string[];
|
|
354
370
|
type: "unique" | "index";
|
|
355
|
-
name?: string;
|
|
356
371
|
};
|
|
357
372
|
export type MigrationForeign = {
|
|
358
373
|
columns: string[];
|