sonamu 0.0.19 → 0.0.21

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 (37) hide show
  1. package/dist/bin/cli.js +9 -0
  2. package/dist/bin/cli.js.map +1 -1
  3. package/dist/database/base-model.d.ts.map +1 -1
  4. package/dist/database/base-model.js +14 -1
  5. package/dist/database/base-model.js.map +1 -1
  6. package/dist/smd/migrator.d.ts +2 -0
  7. package/dist/smd/migrator.d.ts.map +1 -1
  8. package/dist/smd/migrator.js +88 -69
  9. package/dist/smd/migrator.js.map +1 -1
  10. package/dist/smd/smd-utils.d.ts +7 -1
  11. package/dist/smd/smd-utils.d.ts.map +1 -1
  12. package/dist/smd/smd-utils.js +18 -1
  13. package/dist/smd/smd-utils.js.map +1 -1
  14. package/dist/smd/smd.d.ts +3 -2
  15. package/dist/smd/smd.d.ts.map +1 -1
  16. package/dist/smd/smd.js +7 -17
  17. package/dist/smd/smd.js.map +1 -1
  18. package/dist/templates/model_test.template.js +1 -1
  19. package/dist/templates/smd.template.d.ts.map +1 -1
  20. package/dist/templates/smd.template.js +5 -1
  21. package/dist/templates/smd.template.js.map +1 -1
  22. package/dist/templates/view_id_async_select.template.d.ts.map +1 -1
  23. package/dist/templates/view_id_async_select.template.js +7 -0
  24. package/dist/templates/view_id_async_select.template.js.map +1 -1
  25. package/dist/types/types.d.ts +6 -3
  26. package/dist/types/types.d.ts.map +1 -1
  27. package/dist/types/types.js.map +1 -1
  28. package/package.json +1 -1
  29. package/src/bin/cli.ts +9 -0
  30. package/src/database/base-model.ts +13 -1
  31. package/src/smd/migrator.ts +110 -76
  32. package/src/smd/smd-utils.ts +21 -0
  33. package/src/smd/smd.ts +19 -17
  34. package/src/templates/model_test.template.ts +1 -1
  35. package/src/templates/smd.template.ts +5 -1
  36. package/src/templates/view_id_async_select.template.ts +7 -0
  37. package/src/types/types.ts +7 -3
@@ -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();
@@ -439,10 +451,10 @@ export class Migrator {
439
451
  console.debug({ smdCreatedAt, dbCreatedAt });
440
452
  */
441
453
 
442
- const smdIndexes = sortBy(smdSet.indexes, (a: any) =>
454
+ const smdIndexes = sortBy(smdSet.indexes, (a) =>
443
455
  (a as MigrationIndex).columns.join("-")
444
456
  );
445
- const dbIndexes = sortBy(dbSet.indexes, (a: any) =>
457
+ const dbIndexes = sortBy(dbSet.indexes, (a) =>
446
458
  (a as MigrationIndex).columns.join("-")
447
459
  );
448
460
 
@@ -473,6 +485,11 @@ export class Migrator {
473
485
  // TODO FK alter
474
486
  console.log(chalk.red(`FK 다름! ${smdSet.table}`));
475
487
  // console.dir({ smdForeigns, dbForeigns }, { depth: null });
488
+ return this.generateAlterCode_Foreigns(
489
+ smdSet.table,
490
+ smdForeigns,
491
+ dbForeigns
492
+ );
476
493
  }
477
494
  }
478
495
  return null;
@@ -550,9 +567,6 @@ export class Migrator {
550
567
  columns: currentIndexes.map(
551
568
  (currentIndex) => currentIndex.Column_name
552
569
  ),
553
- ...propIf(currentIndexes.length > 1, {
554
- name: keyName,
555
- }),
556
570
  };
557
571
  }
558
572
  );
@@ -742,66 +756,6 @@ export class Migrator {
742
756
  r.columns.push(column);
743
757
  }
744
758
 
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
759
  if (isManyToManyRelationProp(prop)) {
806
760
  // ManyToMany 케이스
807
761
  const relMd = SMDManager.get(prop.with);
@@ -888,6 +842,9 @@ export class Migrator {
888
842
  }
889
843
  );
890
844
 
845
+ // indexes
846
+ migrationSet.indexes = smd.indexes;
847
+
891
848
  // uuid
892
849
  migrationSet.columns = migrationSet.columns.concat({
893
850
  name: "uuid",
@@ -949,15 +906,11 @@ export class Migrator {
949
906
  }
950
907
  const lines = uniq(
951
908
  indexes.reduce((r, index) => {
952
- if (index.name === undefined) {
953
- r.push(`table.${index.type}(['${index.columns[0]}'])`);
954
- } else {
955
- r.push(
956
- `table.${index.type}([${index.columns
957
- .map((col) => `'${col}'`)
958
- .join(",")}], '${index.name}')`
959
- );
960
- }
909
+ r.push(
910
+ `table.${index.type}([${index.columns
911
+ .map((col) => `'${col}'`)
912
+ .join(",")}])`
913
+ );
961
914
  return r;
962
915
  }, [] as string[])
963
916
  );
@@ -1362,10 +1315,10 @@ export class Migrator {
1362
1315
  };
1363
1316
  const extraIndexes = {
1364
1317
  db: differenceBy(dbIndexes, smdIndexes, (col) =>
1365
- [col.type, col.name ?? col.columns.join("-")].join("//")
1318
+ [col.type, col.columns.join("-")].join("//")
1366
1319
  ),
1367
1320
  smd: differenceBy(smdIndexes, dbIndexes, (col) =>
1368
- [col.type, col.name ?? col.columns.join("-")].join("//")
1321
+ [col.type, col.columns.join("-")].join("//")
1369
1322
  ),
1370
1323
  };
1371
1324
  if (extraIndexes.smd.length > 0) {
@@ -1439,6 +1392,87 @@ export class Migrator {
1439
1392
  return linesTo;
1440
1393
  }
1441
1394
 
1395
+ generateAlterCode_Foreigns(
1396
+ table: string,
1397
+ smdForeigns: MigrationForeign[],
1398
+ dbForeigns: MigrationForeign[]
1399
+ ): GenMigrationCode[] {
1400
+ // console.log({ smdForeigns, dbForeigns });
1401
+
1402
+ const getKey = (mf: MigrationForeign): string => {
1403
+ return [mf.columns.join("-"), mf.to].join("///");
1404
+ };
1405
+ const fkTo = smdForeigns.reduce(
1406
+ (result, smdF) => {
1407
+ const matchingDbF = dbForeigns.find(
1408
+ (dbF) => getKey(smdF) === getKey(dbF)
1409
+ );
1410
+ if (!matchingDbF) {
1411
+ result.add.push(smdF);
1412
+ return result;
1413
+ }
1414
+
1415
+ if (equal(smdF, matchingDbF) === false) {
1416
+ result.alterSrc.push(matchingDbF);
1417
+ result.alterDst.push(smdF);
1418
+ return result;
1419
+ }
1420
+ return result;
1421
+ },
1422
+ {
1423
+ add: [] as MigrationForeign[],
1424
+ alterSrc: [] as MigrationForeign[],
1425
+ alterDst: [] as MigrationForeign[],
1426
+ }
1427
+ );
1428
+
1429
+ const linesTo = {
1430
+ add: this.genForeignDefinitions(table, fkTo.add),
1431
+ alterSrc: this.genForeignDefinitions(table, fkTo.alterSrc),
1432
+ alterDst: this.genForeignDefinitions(table, fkTo.alterDst),
1433
+ };
1434
+
1435
+ const lines: string[] = [
1436
+ 'import { Knex } from "knex";',
1437
+ "",
1438
+ "export async function up(knex: Knex): Promise<void> {",
1439
+ `return knex.schema.alterTable("${table}", (table) => {`,
1440
+ ...linesTo.add.up,
1441
+ ...linesTo.alterSrc.down,
1442
+ ...linesTo.alterDst.up,
1443
+ "})",
1444
+ "}",
1445
+ "",
1446
+ "export async function down(knex: Knex): Promise<void> {",
1447
+ `return knex.schema.alterTable("${table}", (table) => {`,
1448
+ ...linesTo.add.down,
1449
+ ...linesTo.alterDst.down,
1450
+ ...linesTo.alterSrc.up,
1451
+ "})",
1452
+ "}",
1453
+ ];
1454
+
1455
+ const formatted = prettier.format(lines.join("\n"), {
1456
+ parser: "typescript",
1457
+ });
1458
+
1459
+ const title = [
1460
+ "alter",
1461
+ table,
1462
+ "foreigns",
1463
+ // TODO 바뀌는 부분
1464
+ ].join("_");
1465
+
1466
+ return [
1467
+ {
1468
+ table,
1469
+ title,
1470
+ formatted,
1471
+ type: "normal",
1472
+ },
1473
+ ];
1474
+ }
1475
+
1442
1476
  async destroy(): Promise<void> {
1443
1477
  await Promise.all(
1444
1478
  this.targets.apply.map((db) => {
@@ -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({ id, parentId, table, title, props, subsets }: SMDInput<any>) {
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.props
518
- .map((prop) => {
519
- const propColumn =
520
- isBelongsToOneRelationProp(prop) || isOneToOneRelationProp(prop)
521
- ? `${prop.name}_id`
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/helpers';
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
  }
@@ -83,6 +83,13 @@ export function ${names.capital}IdAsyncSelect<T extends ${
83
83
  );
84
84
  }, [${names.camelPlural}]);
85
85
 
86
+ useEffect(() => {
87
+ setListParams({
88
+ ...listParams,
89
+ ...baseListParams,
90
+ });
91
+ }, [baseListParams]);
92
+
86
93
  const handleSearchChange = (
87
94
  e: SyntheticEvent<HTMLElement, Event>,
88
95
  data: DropdownOnSearchChangeData,
@@ -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
  };
@@ -352,7 +357,6 @@ export type MigrationColumn = {
352
357
  export type MigrationIndex = {
353
358
  columns: string[];
354
359
  type: "unique" | "index";
355
- name?: string;
356
360
  };
357
361
  export type MigrationForeign = {
358
362
  columns: string[];