sonamu 0.2.31 → 0.2.33

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 (46) hide show
  1. package/.pnp.cjs +11 -10
  2. package/.vscode/settings.json +1 -1
  3. package/dist/api/sonamu.d.ts.map +1 -1
  4. package/dist/api/sonamu.js +3 -0
  5. package/dist/api/sonamu.js.map +1 -1
  6. package/dist/bin/cli.js +7 -4
  7. package/dist/bin/cli.js.map +1 -1
  8. package/dist/database/_batch_update.d.ts +15 -0
  9. package/dist/database/_batch_update.d.ts.map +1 -0
  10. package/dist/database/_batch_update.js +89 -0
  11. package/dist/database/_batch_update.js.map +1 -0
  12. package/dist/database/base-model.d.ts +2 -1
  13. package/dist/database/base-model.d.ts.map +1 -1
  14. package/dist/database/base-model.js +45 -31
  15. package/dist/database/base-model.js.map +1 -1
  16. package/dist/database/upsert-builder.d.ts.map +1 -1
  17. package/dist/database/upsert-builder.js +11 -54
  18. package/dist/database/upsert-builder.js.map +1 -1
  19. package/dist/entity/entity.js +1 -1
  20. package/dist/entity/entity.js.map +1 -1
  21. package/dist/entity/migrator.d.ts +4 -4
  22. package/dist/entity/migrator.d.ts.map +1 -1
  23. package/dist/entity/migrator.js +213 -205
  24. package/dist/entity/migrator.js.map +1 -1
  25. package/dist/syncer/syncer.d.ts.map +1 -1
  26. package/dist/syncer/syncer.js +26 -26
  27. package/dist/syncer/syncer.js.map +1 -1
  28. package/dist/templates/base-template.d.ts +1 -1
  29. package/dist/templates/base-template.d.ts.map +1 -1
  30. package/dist/templates/generated_http.template.d.ts +2 -2
  31. package/dist/templates/generated_http.template.d.ts.map +1 -1
  32. package/dist/templates/generated_http.template.js +49 -38
  33. package/dist/templates/generated_http.template.js.map +1 -1
  34. package/dist/templates/view_form.template.d.ts +2 -2
  35. package/dist/templates/view_list.template.d.ts +2 -2
  36. package/package.json +3 -3
  37. package/src/api/sonamu.ts +4 -0
  38. package/src/bin/cli.ts +11 -6
  39. package/src/database/_batch_update.ts +106 -0
  40. package/src/database/base-model.ts +66 -42
  41. package/src/database/upsert-builder.ts +16 -12
  42. package/src/entity/entity.ts +1 -1
  43. package/src/entity/migrator.ts +106 -103
  44. package/src/syncer/syncer.ts +58 -58
  45. package/src/templates/base-template.ts +1 -1
  46. package/src/templates/generated_http.template.ts +37 -35
@@ -429,7 +429,7 @@ export class Migrator {
429
429
  {
430
430
  file: string;
431
431
  directory: string;
432
- }[]
432
+ }[],
433
433
  ];
434
434
  const migrationsDir = `${Sonamu.apiRootPath}/src/migrations`;
435
435
  const delList = pendingList.map((df) => {
@@ -752,50 +752,50 @@ export class Migrator {
752
752
  if (dbSet === null) {
753
753
  // 기존 테이블 없음, 새로 테이블 생성
754
754
  return [
755
- this.generateCreateCode_ColumnAndIndexes(
755
+ await this.generateCreateCode_ColumnAndIndexes(
756
756
  entitySet.table,
757
757
  entitySet.columns,
758
758
  entitySet.indexes
759
759
  ),
760
- ...this.generateCreateCode_Foreign(
760
+ ...(await this.generateCreateCode_Foreign(
761
761
  entitySet.table,
762
762
  entitySet.foreigns
763
- ),
763
+ )),
764
764
  ];
765
765
  }
766
766
 
767
767
  // 기존 테이블 존재하는 케이스
768
- const alterCodes: (GenMigrationCode | GenMigrationCode[] | null)[] = (
769
- ["columnsAndIndexes", "foreigns"] as const
770
- ).map((key) => {
771
- // 배열 원소의 순서가 달라서 불일치가 발생하는걸 방지하기 위해 각 항목별로 정렬 처리 후 비교
772
- if (key === "columnsAndIndexes") {
773
- const replaceColumnDefaultTo = (col: MigrationColumn) => {
774
- // float인 경우 기본값을 0으로 지정하는 경우 "0.00"으로 변환되는 케이스 대응
775
- if (
776
- col.type === "float" &&
777
- col.defaultTo &&
778
- col.defaultTo.includes('"') === false
779
- ) {
780
- col.defaultTo = `"${Number(col.defaultTo).toFixed(
781
- col.scale ?? 2
782
- )}"`;
783
- }
784
- // string인 경우 기본값이 빈 스트링인 경우 대응
785
- if (col.type === "string" && col.defaultTo === "") {
786
- col.defaultTo = '""';
787
- }
788
- return col;
789
- };
790
- const entityColumns = sortBy(
791
- entitySet.columns,
792
- (a) => a.name
793
- ).map(replaceColumnDefaultTo);
794
- const dbColumns = sortBy(dbSet.columns, (a) => a.name).map(
795
- replaceColumnDefaultTo
796
- );
797
-
798
- /* 디버깅용 코드, 특정 컬럼에서 불일치 발생할 때 확인
768
+ const alterCodes: (GenMigrationCode | GenMigrationCode[] | null)[] =
769
+ await Promise.all(
770
+ (["columnsAndIndexes", "foreigns"] as const).map((key) => {
771
+ // 배열 원소의 순서가 달라서 불일치가 발생하는걸 방지하기 위해 각 항목별로 정렬 처리 후 비교
772
+ if (key === "columnsAndIndexes") {
773
+ const replaceColumnDefaultTo = (col: MigrationColumn) => {
774
+ // float인 경우 기본값을 0으로 지정하는 경우 "0.00"으로 변환되는 케이스 대응
775
+ if (
776
+ col.type === "float" &&
777
+ col.defaultTo &&
778
+ col.defaultTo.includes('"') === false
779
+ ) {
780
+ col.defaultTo = `"${Number(col.defaultTo).toFixed(
781
+ col.scale ?? 2
782
+ )}"`;
783
+ }
784
+ // string인 경우 기본값이 빈 스트링인 경우 대응
785
+ if (col.type === "string" && col.defaultTo === "") {
786
+ col.defaultTo = '""';
787
+ }
788
+ return col;
789
+ };
790
+ const entityColumns = sortBy(
791
+ entitySet.columns,
792
+ (a) => a.name
793
+ ).map(replaceColumnDefaultTo);
794
+ const dbColumns = sortBy(dbSet.columns, (a) => a.name).map(
795
+ replaceColumnDefaultTo
796
+ );
797
+
798
+ /* 디버깅용 코드, 특정 컬럼에서 불일치 발생할 때 확인
799
799
  const entityColumn = entitySet.columns.find(
800
800
  (col) => col.name === "price_krw"
801
801
  );
@@ -805,63 +805,66 @@ export class Migrator {
805
805
  console.debug({ entityColumn, dbColumn });
806
806
  */
807
807
 
808
- const entityIndexes = sortBy(entitySet.indexes, (a) =>
809
- [
810
- a.type,
811
- ...a.columns.sort((c1, c2) => (c1 > c2 ? 1 : -1)),
812
- ].join("-")
813
- );
814
- const dbIndexes = sortBy(dbSet.indexes, (a) =>
815
- [
816
- a.type,
817
- ...a.columns.sort((c1, c2) => (c1 > c2 ? 1 : -1)),
818
- ].join("-")
819
- );
820
-
821
- const isEqualColumns = equal(entityColumns, dbColumns);
822
- const isEqualIndexes = equal(entityIndexes, dbIndexes);
823
- if (isEqualColumns && isEqualIndexes) {
808
+ const entityIndexes = sortBy(entitySet.indexes, (a) =>
809
+ [
810
+ a.type,
811
+ ...a.columns.sort((c1, c2) => (c1 > c2 ? 1 : -1)),
812
+ ].join("-")
813
+ );
814
+ const dbIndexes = sortBy(dbSet.indexes, (a) =>
815
+ [
816
+ a.type,
817
+ ...a.columns.sort((c1, c2) => (c1 > c2 ? 1 : -1)),
818
+ ].join("-")
819
+ );
820
+
821
+ const isEqualColumns = equal(entityColumns, dbColumns);
822
+ const isEqualIndexes = equal(entityIndexes, dbIndexes);
823
+ if (isEqualColumns && isEqualIndexes) {
824
+ return null;
825
+ } else {
826
+ // this.showMigrationSet("MD", entitySet);
827
+ // this.showMigrationSet("DB", dbSet);
828
+ return this.generateAlterCode_ColumnAndIndexes(
829
+ entitySet.table,
830
+ entityColumns,
831
+ entityIndexes,
832
+ dbColumns,
833
+ dbIndexes
834
+ );
835
+ }
836
+ } else {
837
+ const replaceNoActionOnMySQL = (f: MigrationForeign) => {
838
+ // MySQL에서 RESTRICT와 NO ACTION은 동일함
839
+ const { onDelete, onUpdate } = f;
840
+ return {
841
+ ...f,
842
+ onUpdate:
843
+ onUpdate === "RESTRICT" ? "NO ACTION" : onUpdate,
844
+ onDelete:
845
+ onDelete === "RESTRICT" ? "NO ACTION" : onDelete,
846
+ };
847
+ };
848
+
849
+ const entityForeigns = sortBy(entitySet.foreigns, (a) =>
850
+ [a.to, ...a.columns].join("-")
851
+ ).map((f) => replaceNoActionOnMySQL(f));
852
+ const dbForeigns = sortBy(dbSet.foreigns, (a) =>
853
+ [a.to, ...a.columns].join("-")
854
+ ).map((f) => replaceNoActionOnMySQL(f));
855
+
856
+ if (equal(entityForeigns, dbForeigns) === false) {
857
+ // console.dir({ entityForeigns, dbForeigns }, { depth: null });
858
+ return this.generateAlterCode_Foreigns(
859
+ entitySet.table,
860
+ entityForeigns,
861
+ dbForeigns
862
+ );
863
+ }
864
+ }
824
865
  return null;
825
- } else {
826
- // this.showMigrationSet("MD", entitySet);
827
- // this.showMigrationSet("DB", dbSet);
828
- return this.generateAlterCode_ColumnAndIndexes(
829
- entitySet.table,
830
- entityColumns,
831
- entityIndexes,
832
- dbColumns,
833
- dbIndexes
834
- );
835
- }
836
- } else {
837
- const replaceNoActionOnMySQL = (f: MigrationForeign) => {
838
- // MySQL에서 RESTRICT와 NO ACTION은 동일함
839
- const { onDelete, onUpdate } = f;
840
- return {
841
- ...f,
842
- onUpdate: onUpdate === "RESTRICT" ? "NO ACTION" : onUpdate,
843
- onDelete: onDelete === "RESTRICT" ? "NO ACTION" : onDelete,
844
- };
845
- };
846
-
847
- const entityForeigns = sortBy(entitySet.foreigns, (a) =>
848
- [a.to, ...a.columns].join("-")
849
- ).map((f) => replaceNoActionOnMySQL(f));
850
- const dbForeigns = sortBy(dbSet.foreigns, (a) =>
851
- [a.to, ...a.columns].join("-")
852
- ).map((f) => replaceNoActionOnMySQL(f));
853
-
854
- if (equal(entityForeigns, dbForeigns) === false) {
855
- // console.dir({ entityForeigns, dbForeigns }, { depth: null });
856
- return this.generateAlterCode_Foreigns(
857
- entitySet.table,
858
- entityForeigns,
859
- dbForeigns
860
- );
861
- }
862
- }
863
- return null;
864
- });
866
+ })
867
+ );
865
868
  if (alterCodes.every((alterCode) => alterCode === null)) {
866
869
  return null;
867
870
  } else {
@@ -1398,11 +1401,11 @@ export class Migrator {
1398
1401
  /*
1399
1402
  테이블 생성하는 케이스 - 컬럼/인덱스 생성
1400
1403
  */
1401
- generateCreateCode_ColumnAndIndexes(
1404
+ async generateCreateCode_ColumnAndIndexes(
1402
1405
  table: string,
1403
1406
  columns: MigrationColumn[],
1404
1407
  indexes: MigrationIndex[]
1405
- ): GenMigrationCode {
1408
+ ): Promise<GenMigrationCode> {
1406
1409
  // 컬럼, 인덱스 처리
1407
1410
  const lines: string[] = [
1408
1411
  'import { Knex } from "knex";',
@@ -1425,7 +1428,7 @@ export class Migrator {
1425
1428
  table,
1426
1429
  type: "normal",
1427
1430
  title: `create__${table}`,
1428
- formatted: prettier.format(lines.join("\n"), {
1431
+ formatted: await prettier.format(lines.join("\n"), {
1429
1432
  parser: "typescript",
1430
1433
  }),
1431
1434
  };
@@ -1433,10 +1436,10 @@ export class Migrator {
1433
1436
  /*
1434
1437
  테이블 생성하는 케이스 - FK 생성
1435
1438
  */
1436
- generateCreateCode_Foreign(
1439
+ async generateCreateCode_Foreign(
1437
1440
  table: string,
1438
1441
  foreigns: MigrationForeign[]
1439
- ): GenMigrationCode[] {
1442
+ ): Promise<GenMigrationCode[]> {
1440
1443
  if (foreigns.length === 0) {
1441
1444
  return [];
1442
1445
  }
@@ -1473,7 +1476,7 @@ export class Migrator {
1473
1476
  table,
1474
1477
  type: "foreign",
1475
1478
  title: `foreign__${table}__${foreignKeysString}`,
1476
- formatted: prettier.format(lines.join("\n"), {
1479
+ formatted: await prettier.format(lines.join("\n"), {
1477
1480
  parser: "typescript",
1478
1481
  }),
1479
1482
  },
@@ -1550,13 +1553,13 @@ export class Migrator {
1550
1553
  }
1551
1554
  }
1552
1555
 
1553
- generateAlterCode_ColumnAndIndexes(
1556
+ async generateAlterCode_ColumnAndIndexes(
1554
1557
  table: string,
1555
1558
  entityColumns: MigrationColumn[],
1556
1559
  entityIndexes: MigrationIndex[],
1557
1560
  dbColumns: MigrationColumn[],
1558
1561
  dbIndexes: MigrationIndex[]
1559
- ): GenMigrationCode[] {
1562
+ ): Promise<GenMigrationCode[]> {
1560
1563
  /*
1561
1564
  세부 비교 후 다른점 찾아서 코드 생성
1562
1565
 
@@ -1615,7 +1618,7 @@ export class Migrator {
1615
1618
  "}",
1616
1619
  ];
1617
1620
 
1618
- const formatted = prettier.format(lines.join("\n"), {
1621
+ const formatted = await prettier.format(lines.join("\n"), {
1619
1622
  parser: "typescript",
1620
1623
  });
1621
1624
 
@@ -1853,11 +1856,11 @@ export class Migrator {
1853
1856
  return linesTo;
1854
1857
  }
1855
1858
 
1856
- generateAlterCode_Foreigns(
1859
+ async generateAlterCode_Foreigns(
1857
1860
  table: string,
1858
1861
  entityForeigns: MigrationForeign[],
1859
1862
  dbForeigns: MigrationForeign[]
1860
- ): GenMigrationCode[] {
1863
+ ): Promise<GenMigrationCode[]> {
1861
1864
  // console.log({ entityForeigns, dbForeigns });
1862
1865
 
1863
1866
  const getKey = (mf: MigrationForeign): string => {
@@ -1913,7 +1916,7 @@ export class Migrator {
1913
1916
  "}",
1914
1917
  ];
1915
1918
 
1916
- const formatted = prettier.format(lines.join("\n"), {
1919
+ const formatted = await prettier.format(lines.join("\n"), {
1917
1920
  parser: "typescript",
1918
1921
  });
1919
1922
 
@@ -121,7 +121,7 @@ export class Syncer {
121
121
  models: { [modelName: string]: unknown } = {};
122
122
 
123
123
  get checksumsPath(): string {
124
- return path.join(Sonamu.apiRootPath, "/.tf-checksum");
124
+ return path.join(Sonamu.apiRootPath, "/.so-checksum");
125
125
  }
126
126
  public constructor() {}
127
127
 
@@ -705,7 +705,12 @@ export class Syncer {
705
705
  );
706
706
  // console.debug(chalk.yellow(`autoload:models @ ${pathPattern}`));
707
707
 
708
- const filePaths = await globAsync(pathPattern);
708
+ const filePaths = (await globAsync(pathPattern)).filter((path) => {
709
+ // src 디렉터리 내에 있는 해당 파일이 존재할 경우에만 로드
710
+ // 삭제된 파일이지만 dist에 남아있는 경우 BaseSchema undefined 에러 방지
711
+ const srcPath = path.replace("/dist/", "/src/").replace(".js", ".ts");
712
+ return existsSync(srcPath);
713
+ });
709
714
  const modules = await importMultiple(filePaths);
710
715
  const functions = modules
711
716
  .map(({ imported }) => Object.entries(imported))
@@ -731,7 +736,14 @@ export class Syncer {
731
736
 
732
737
  const filePaths = (
733
738
  await Promise.all(pathPatterns.map((pattern) => globAsync(pattern)))
734
- ).flat();
739
+ )
740
+ .flat()
741
+ .filter((path) => {
742
+ // src 디렉터리 내에 있는 해당 파일이 존재할 경우에만 로드
743
+ // 삭제된 파일이지만 dist에 남아있는 경우 BaseSchema undefined 에러 방지
744
+ const srcPath = path.replace("/dist/", "/src/").replace(".js", ".ts");
745
+ return existsSync(srcPath);
746
+ });
735
747
  const modules = await importMultiple(filePaths, doRefresh);
736
748
  const functions = modules
737
749
  .map(({ imported }) => Object.entries(imported))
@@ -822,7 +834,7 @@ export class Syncer {
822
834
  }
823
835
  }
824
836
 
825
- const rendered = template.render(options, ...extra);
837
+ const rendered = await template.render(options, ...extra);
826
838
  const resolved = await this.resolveRenderedTemplate(key, rendered);
827
839
 
828
840
  let preTemplateResolved: PathAndCode[] = [];
@@ -896,7 +908,7 @@ export class Syncer {
896
908
  if (key === "generated_http") {
897
909
  return [header, body].join("\n\n");
898
910
  } else {
899
- return await prettier.format([header, body].join("\n\n"), {
911
+ return prettier.format([header, body].join("\n\n"), {
900
912
  parser: key === "entity" ? "json" : "typescript",
901
913
  });
902
914
  }
@@ -954,32 +966,17 @@ export class Syncer {
954
966
  )
955
967
  ).flat();
956
968
 
957
- /*
958
- overwrite가 true일 때
959
- - 생각하지 않고 그냥 다 덮어씀
960
- overwrite가 false일 때
961
- - 옵션1 (현재구현): 그냥 파일 하나라도 있으면 코드 생성 안함
962
- - 옵션2 : 있는 파일은 전부 그대로 두고 없는 파일만 싹 생성함
963
- - 옵션3 : 메인 파일만 그대로 두고, 파생 파일은 전부 생성함 => 이게 맞지 않나?
964
- */
965
-
966
969
  const filteredPathAndCodes: PathAndCode[] = (() => {
967
970
  if (generateOptions.overwrite === true) {
968
971
  return pathAndCodes;
969
972
  } else {
970
- return pathAndCodes.filter((pathAndCode, index) => {
971
- if (index === 0) {
972
- const { targets } = Sonamu.config.sync;
973
- const filePath = `${Sonamu.appRootPath}/${pathAndCode.path}`;
974
- const dstFilePaths = targets.map((target) =>
975
- filePath.replace("/:target/", `/${target}/`)
976
- );
977
- return dstFilePaths.every(
978
- (dstPath) => existsSync(dstPath) === false
979
- );
980
- } else {
981
- return true;
982
- }
973
+ return pathAndCodes.filter((pathAndCode) => {
974
+ const { targets } = Sonamu.config.sync;
975
+ const filePath = `${Sonamu.appRootPath}/${pathAndCode.path}`;
976
+ const dstFilePaths = targets.map((target) =>
977
+ filePath.replace("/:target/", `/${target}/`)
978
+ );
979
+ return dstFilePaths.every((dstPath) => existsSync(dstPath) === false);
983
980
  });
984
981
  }
985
982
  })();
@@ -1026,32 +1023,38 @@ export class Syncer {
1026
1023
  (name) => name !== names.constant
1027
1024
  );
1028
1025
 
1029
- return keys.reduce((result, key) => {
1030
- const tpl = this.getTemplate(key);
1031
- if (key.startsWith("view_enums")) {
1032
- enumsKeys.map((componentId) => {
1033
- const { target, path: p } = tpl.getTargetAndPath(names, componentId);
1034
- result[`${key}__${componentId}`] = existsSync(
1035
- path.join(Sonamu.appRootPath, target, p)
1036
- );
1037
- });
1038
- return result;
1039
- }
1026
+ return keys.reduce(
1027
+ (result, key) => {
1028
+ const tpl = this.getTemplate(key);
1029
+ if (key.startsWith("view_enums")) {
1030
+ enumsKeys.map((componentId) => {
1031
+ const { target, path: p } = tpl.getTargetAndPath(
1032
+ names,
1033
+ componentId
1034
+ );
1035
+ result[`${key}__${componentId}`] = existsSync(
1036
+ path.join(Sonamu.appRootPath, target, p)
1037
+ );
1038
+ });
1039
+ return result;
1040
+ }
1040
1041
 
1041
- const { target, path: p } = tpl.getTargetAndPath(names);
1042
- const { targets } = Sonamu.config.sync;
1043
- if (target.includes(":target")) {
1044
- targets.map((t) => {
1045
- result[`${key}__${t}`] = existsSync(
1046
- path.join(Sonamu.appRootPath, target.replace(":target", t), p)
1047
- );
1048
- });
1049
- } else {
1050
- result[key] = existsSync(path.join(Sonamu.appRootPath, target, p));
1051
- }
1042
+ const { target, path: p } = tpl.getTargetAndPath(names);
1043
+ const { targets } = Sonamu.config.sync;
1044
+ if (target.includes(":target")) {
1045
+ targets.map((t) => {
1046
+ result[`${key}__${t}`] = existsSync(
1047
+ path.join(Sonamu.appRootPath, target.replace(":target", t), p)
1048
+ );
1049
+ });
1050
+ } else {
1051
+ result[key] = existsSync(path.join(Sonamu.appRootPath, target, p));
1052
+ }
1052
1053
 
1053
- return result;
1054
- }, {} as Record<`${TemplateKey}${string}`, boolean>);
1054
+ return result;
1055
+ },
1056
+ {} as Record<`${TemplateKey}${string}`, boolean>
1057
+ );
1055
1058
  }
1056
1059
 
1057
1060
  async getZodTypeById(zodTypeId: string): Promise<z.ZodTypeAny> {
@@ -1096,9 +1099,8 @@ export class Syncer {
1096
1099
  const obj = await propNode.children.reduce(
1097
1100
  async (promise, childPropNode) => {
1098
1101
  const result = await promise;
1099
- result[childPropNode.prop!.name] = await this.propNodeToZodType(
1100
- childPropNode
1101
- );
1102
+ result[childPropNode.prop!.name] =
1103
+ await this.propNodeToZodType(childPropNode);
1102
1104
  return result;
1103
1105
  },
1104
1106
  {} as any
@@ -1332,10 +1334,8 @@ export class Syncer {
1332
1334
  table?: string,
1333
1335
  title?: string
1334
1336
  ) {
1335
- if (/^[a-zA-Z_$][a-zA-Z_$0-9]*$/.test(entityId) === false) {
1336
- throw new BadRequestException(
1337
- "entityId는 자바스크립트 변수명 규칙을 따라야 합니다."
1338
- );
1337
+ if (!/^[A-Z][a-zA-Z0-9]*$/.test(entityId)) {
1338
+ throw new BadRequestException("entityId는 CamelCase 형식이어야 합니다.");
1339
1339
  }
1340
1340
 
1341
1341
  await this.generateTemplate("entity", {
@@ -7,7 +7,7 @@ export abstract class Template {
7
7
  public abstract render(
8
8
  options: TemplateOptions[TemplateKey],
9
9
  ...extra: unknown[]
10
- ): RenderedTemplate;
10
+ ): RenderedTemplate | Promise<RenderedTemplate>;
11
11
 
12
12
  public abstract getTargetAndPath(
13
13
  names?: EntityNamesRecord,
@@ -21,7 +21,7 @@ export class Template__generated_http extends Template {
21
21
  };
22
22
  }
23
23
 
24
- render({}: TemplateOptions["generated_http"]) {
24
+ async render({}: TemplateOptions["generated_http"]) {
25
25
  const {
26
26
  syncer: { types, apis },
27
27
  config: {
@@ -29,42 +29,44 @@ export class Template__generated_http extends Template {
29
29
  },
30
30
  } = Sonamu;
31
31
 
32
- const lines = apis.map((api) => {
33
- const reqObject = this.resolveApiParams(api, types);
32
+ const lines = await Promise.all(
33
+ apis.map(async (api) => {
34
+ const reqObject = this.resolveApiParams(api, types);
34
35
 
35
- const dataLines = (() => {
36
- if ((api.options.httpMethod ?? "GET") === "GET") {
37
- return {
38
- querystring: [
39
- qs
40
- .stringify(reqObject, { encode: false })
41
- .split("&")
42
- .join("\n\t&"),
43
- ],
44
- body: [],
45
- };
46
- } else {
47
- return {
48
- querystring: [],
49
- body: [
50
- "",
51
- prettier.format(JSON.stringify(reqObject), {
52
- parser: "json",
53
- }),
54
- ],
55
- };
56
- }
57
- })();
36
+ const dataLines = await (async () => {
37
+ if ((api.options.httpMethod ?? "GET") === "GET") {
38
+ return {
39
+ querystring: [
40
+ qs
41
+ .stringify(reqObject, { encode: false })
42
+ .split("&")
43
+ .join("\n\t&"),
44
+ ],
45
+ body: [],
46
+ };
47
+ } else {
48
+ return {
49
+ querystring: [],
50
+ body: [
51
+ "",
52
+ await prettier.format(JSON.stringify(reqObject), {
53
+ parser: "json",
54
+ }),
55
+ ],
56
+ };
57
+ }
58
+ })();
58
59
 
59
- return [
60
- [
61
- `${api.options.httpMethod ?? "GET"} {{baseUrl}}${prefix}${api.path}`,
62
- ...dataLines.querystring,
63
- ].join("\n\t?"),
64
- `Content-Type: ${api.options.contentType ?? "application/json"}`,
65
- ...dataLines.body,
66
- ].join("\n");
67
- });
60
+ return [
61
+ [
62
+ `${api.options.httpMethod ?? "GET"} {{baseUrl}}${prefix}${api.path}`,
63
+ ...dataLines.querystring,
64
+ ].join("\n\t?"),
65
+ `Content-Type: ${api.options.contentType ?? "application/json"}`,
66
+ ...dataLines.body,
67
+ ].join("\n");
68
+ })
69
+ );
68
70
 
69
71
  return {
70
72
  ...this.getTargetAndPath(),