sonamu 0.5.6 → 0.6.0
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/api/base-frame.js +12 -2
- package/dist/api/caster.js +66 -2
- package/dist/api/code-converters.js +489 -2
- package/dist/api/config.d.ts +76 -0
- package/dist/api/config.d.ts.map +1 -0
- package/dist/api/config.js +32 -0
- package/dist/api/context.d.ts +1 -0
- package/dist/api/context.d.ts.map +1 -1
- package/dist/api/context.js +3 -2
- package/dist/api/decorators.d.ts +1 -0
- package/dist/api/decorators.d.ts.map +1 -1
- package/dist/api/decorators.js +142 -2
- package/dist/api/index.js +9 -2
- package/dist/api/sonamu.d.ts +8 -22
- package/dist/api/sonamu.d.ts.map +1 -1
- package/dist/api/sonamu.js +482 -2
- package/dist/bin/build-config.d.ts +2 -1
- package/dist/bin/build-config.d.ts.map +1 -1
- package/dist/bin/build-config.js +12 -2
- package/dist/bin/cli-wrapper.js +71 -2
- package/dist/bin/cli.js +418 -2
- package/dist/bin/hot-hook-register.d.ts +11 -0
- package/dist/bin/hot-hook-register.d.ts.map +1 -0
- package/dist/bin/hot-hook-register.js +21 -0
- package/dist/database/_batch_update.js +78 -2
- package/dist/database/base-model.js +247 -2
- package/dist/database/code-generator.js +53 -2
- package/dist/database/db.d.ts +5 -16
- package/dist/database/db.d.ts.map +1 -1
- package/dist/database/db.js +132 -2
- package/dist/database/knex-plugins/knex-on-duplicate-update.js +39 -2
- package/dist/database/puri-wrapper.d.ts +22 -10
- package/dist/database/puri-wrapper.d.ts.map +1 -1
- package/dist/database/puri-wrapper.js +109 -2
- package/dist/database/puri.d.ts +105 -73
- package/dist/database/puri.d.ts.map +1 -1
- package/dist/database/puri.js +539 -2
- package/dist/database/puri.types.d.ts +33 -42
- package/dist/database/puri.types.d.ts.map +1 -1
- package/dist/database/puri.types.js +3 -2
- package/dist/database/transaction-context.d.ts +3 -3
- package/dist/database/transaction-context.d.ts.map +1 -1
- package/dist/database/transaction-context.js +14 -2
- package/dist/database/upsert-builder.js +215 -2
- package/dist/entity/entity-manager.d.ts +3 -1
- package/dist/entity/entity-manager.d.ts.map +1 -1
- package/dist/entity/entity-manager.js +114 -2
- package/dist/entity/entity-utils.js +210 -2
- package/dist/entity/entity.d.ts.map +1 -1
- package/dist/entity/entity.js +651 -2
- package/dist/exceptions/error-handler.js +29 -2
- package/dist/exceptions/so-exceptions.js +85 -2
- package/dist/file-storage/driver.js +79 -2
- package/dist/file-storage/file-storage.js +75 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -2
- package/dist/migration/code-generation.js +558 -2
- package/dist/migration/migration-set.js +364 -2
- package/dist/migration/migrator.d.ts +0 -9
- package/dist/migration/migrator.d.ts.map +1 -1
- package/dist/migration/migrator.js +510 -2
- package/dist/migration/types.js +3 -2
- package/dist/naite/naite.d.ts +12 -0
- package/dist/naite/naite.d.ts.map +1 -0
- package/dist/naite/naite.js +72 -0
- package/dist/stream/index.js +3 -2
- package/dist/stream/sse.js +38 -2
- package/dist/syncer/api-parser.d.ts +20 -0
- package/dist/syncer/api-parser.d.ts.map +1 -0
- package/dist/syncer/api-parser.js +229 -0
- package/dist/syncer/checksum.d.ts +21 -0
- package/dist/syncer/checksum.d.ts.map +1 -0
- package/dist/syncer/checksum.js +98 -0
- package/dist/syncer/code-generator.d.ts +20 -0
- package/dist/syncer/code-generator.d.ts.map +1 -0
- package/dist/syncer/code-generator.js +141 -0
- package/dist/syncer/entity-operations.d.ts +17 -0
- package/dist/syncer/entity-operations.d.ts.map +1 -0
- package/dist/syncer/entity-operations.js +58 -0
- package/dist/syncer/file-patterns.d.ts +29 -0
- package/dist/syncer/file-patterns.d.ts.map +1 -0
- package/dist/syncer/file-patterns.js +38 -0
- package/dist/syncer/index.d.ts +6 -0
- package/dist/syncer/index.d.ts.map +1 -1
- package/dist/syncer/index.js +9 -2
- package/dist/syncer/module-loader.d.ts +35 -0
- package/dist/syncer/module-loader.d.ts.map +1 -0
- package/dist/syncer/module-loader.js +82 -0
- package/dist/syncer/syncer.d.ts +93 -108
- package/dist/syncer/syncer.d.ts.map +1 -1
- package/dist/syncer/syncer.js +375 -2
- package/dist/template/entity-converter.d.ts +14 -0
- package/dist/template/entity-converter.d.ts.map +1 -0
- package/dist/template/entity-converter.js +101 -0
- package/dist/template/helpers.d.ts +23 -0
- package/dist/template/helpers.d.ts.map +1 -0
- package/dist/template/helpers.js +64 -0
- package/dist/{templates → template/implementations}/entity.template.d.ts +3 -3
- package/dist/template/implementations/entity.template.d.ts.map +1 -0
- package/dist/template/implementations/entity.template.js +87 -0
- package/dist/{templates → template/implementations}/generated.template.d.ts +3 -3
- package/dist/template/implementations/generated.template.d.ts.map +1 -0
- package/dist/template/implementations/generated.template.js +232 -0
- package/dist/{templates → template/implementations}/generated_http.template.d.ts +3 -3
- package/dist/template/implementations/generated_http.template.d.ts.map +1 -0
- package/dist/template/implementations/generated_http.template.js +131 -0
- package/dist/{templates → template/implementations}/generated_sso.template.d.ts +3 -3
- package/dist/template/implementations/generated_sso.template.d.ts.map +1 -0
- package/dist/template/implementations/generated_sso.template.js +105 -0
- package/dist/{templates → template/implementations}/init_types.template.d.ts +3 -3
- package/dist/template/implementations/init_types.template.d.ts.map +1 -0
- package/dist/template/implementations/init_types.template.js +38 -0
- package/dist/template/implementations/model.template.d.ts +17 -0
- package/dist/template/implementations/model.template.d.ts.map +1 -0
- package/dist/template/implementations/model.template.js +171 -0
- package/dist/{templates → template/implementations}/model_test.template.d.ts +3 -3
- package/dist/template/implementations/model_test.template.d.ts.map +1 -0
- package/dist/template/implementations/model_test.template.js +35 -0
- package/dist/{templates → template/implementations}/service.template.d.ts +6 -6
- package/dist/template/implementations/service.template.d.ts.map +1 -0
- package/dist/template/implementations/service.template.js +193 -0
- package/dist/{templates → template/implementations}/view_enums_buttonset.template.d.ts +3 -3
- package/dist/template/implementations/view_enums_buttonset.template.d.ts.map +1 -0
- package/dist/template/implementations/view_enums_buttonset.template.js +31 -0
- package/dist/{templates → template/implementations}/view_enums_dropdown.template.d.ts +3 -4
- package/dist/template/implementations/view_enums_dropdown.template.d.ts.map +1 -0
- package/dist/template/implementations/view_enums_dropdown.template.js +50 -0
- package/dist/{templates → template/implementations}/view_enums_select.template.d.ts +3 -3
- package/dist/template/implementations/view_enums_select.template.d.ts.map +1 -0
- package/dist/template/implementations/view_enums_select.template.js +55 -0
- package/dist/{templates → template/implementations}/view_form.template.d.ts +5 -5
- package/dist/template/implementations/view_form.template.d.ts.map +1 -0
- package/dist/template/implementations/view_form.template.js +337 -0
- package/dist/{templates → template/implementations}/view_id_all_select.template.d.ts +3 -3
- package/dist/template/implementations/view_id_all_select.template.d.ts.map +1 -0
- package/dist/template/implementations/view_id_all_select.template.js +31 -0
- package/dist/{templates → template/implementations}/view_id_async_select.template.d.ts +3 -3
- package/dist/template/implementations/view_id_async_select.template.d.ts.map +1 -0
- package/dist/template/implementations/view_id_async_select.template.js +105 -0
- package/dist/{templates → template/implementations}/view_list.template.d.ts +5 -13
- package/dist/template/implementations/view_list.template.d.ts.map +1 -0
- package/dist/template/implementations/view_list.template.js +465 -0
- package/dist/{templates → template/implementations}/view_list_columns.template.d.ts +3 -3
- package/dist/template/implementations/view_list_columns.template.d.ts.map +1 -0
- package/dist/template/implementations/view_list_columns.template.js +49 -0
- package/dist/{templates → template/implementations}/view_search_input.template.d.ts +3 -3
- package/dist/template/implementations/view_search_input.template.d.ts.map +1 -0
- package/dist/template/implementations/view_search_input.template.js +64 -0
- package/dist/template/index.d.ts +5 -0
- package/dist/template/index.d.ts.map +1 -0
- package/dist/template/index.js +6 -0
- package/dist/template/template.d.ts +39 -0
- package/dist/template/template.d.ts.map +1 -0
- package/dist/template/template.js +47 -0
- package/dist/template/zod-converter.d.ts +18 -0
- package/dist/template/zod-converter.d.ts.map +1 -0
- package/dist/template/zod-converter.js +166 -0
- package/dist/testing/_relation-graph.js +80 -2
- package/dist/testing/fixture-manager.d.ts.map +1 -1
- package/dist/testing/fixture-manager.js +521 -2
- package/dist/types/types.d.ts +39 -40
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/types.js +289 -2
- package/dist/typings/knex.d.js +3 -2
- package/dist/utils/async-utils.d.ts +7 -0
- package/dist/utils/async-utils.d.ts.map +1 -1
- package/dist/utils/async-utils.js +57 -2
- package/dist/utils/console-util.d.ts +2 -0
- package/dist/utils/console-util.d.ts.map +1 -0
- package/dist/utils/console-util.js +6 -0
- package/dist/utils/controller.js +26 -2
- package/dist/utils/esm-utils.d.ts +45 -0
- package/dist/utils/esm-utils.d.ts.map +1 -0
- package/dist/utils/esm-utils.js +56 -0
- package/dist/utils/fs-utils.js +17 -2
- package/dist/utils/lodash-able.js +6 -2
- package/dist/utils/model.js +22 -2
- package/dist/utils/path-utils.d.ts +89 -0
- package/dist/utils/path-utils.d.ts.map +1 -0
- package/dist/utils/path-utils.js +60 -0
- package/dist/utils/process-utils.d.ts +13 -0
- package/dist/utils/process-utils.d.ts.map +1 -0
- package/dist/utils/process-utils.js +36 -0
- package/dist/utils/sql-parser.js +35 -2
- package/dist/utils/utils.d.ts +4 -7
- package/dist/utils/utils.d.ts.map +1 -1
- package/dist/utils/utils.js +33 -2
- package/dist/utils/zod-error.d.ts.map +1 -1
- package/dist/utils/zod-error.js +19 -2
- package/package.json +21 -9
- package/src/api/code-converters.ts +2 -2
- package/src/api/config.ts +142 -0
- package/src/api/context.ts +1 -0
- package/src/api/decorators.ts +15 -5
- package/src/api/sonamu.ts +102 -87
- package/src/bin/build-config.ts +2 -1
- package/src/bin/cli-wrapper.ts +10 -3
- package/src/bin/cli.ts +108 -56
- package/src/bin/hot-hook-register.ts +22 -0
- package/src/database/base-model.ts +1 -1
- package/src/database/code-generator.ts +1 -1
- package/src/database/db.ts +53 -60
- package/src/database/puri-wrapper.ts +104 -26
- package/src/database/puri.ts +477 -580
- package/src/database/puri.types.ts +111 -201
- package/src/database/transaction-context.ts +4 -4
- package/src/database/upsert-builder.ts +1 -1
- package/src/entity/entity-manager.ts +19 -15
- package/src/entity/entity.ts +4 -3
- package/src/index.ts +2 -0
- package/src/migration/code-generation.ts +1 -1
- package/src/migration/migration-set.ts +1 -1
- package/src/migration/migrator.ts +23 -152
- package/src/naite/naite.ts +70 -0
- package/src/syncer/api-parser.ts +299 -0
- package/src/syncer/checksum.ts +152 -0
- package/src/syncer/code-generator.ts +202 -0
- package/src/syncer/entity-operations.ts +68 -0
- package/src/syncer/file-patterns.ts +56 -0
- package/src/syncer/index.ts +6 -0
- package/src/syncer/module-loader.ts +125 -0
- package/src/syncer/syncer.ts +363 -1420
- package/src/template/entity-converter.ts +123 -0
- package/src/template/helpers.ts +84 -0
- package/src/{templates → template/implementations}/entity.template.ts +4 -4
- package/src/{templates → template/implementations}/generated.template.ts +9 -9
- package/src/{templates → template/implementations}/generated_http.template.ts +9 -6
- package/src/{templates → template/implementations}/generated_sso.template.ts +7 -7
- package/src/{templates → template/implementations}/init_types.template.ts +4 -4
- package/src/{templates → template/implementations}/model.template.ts +9 -9
- package/src/{templates → template/implementations}/model_test.template.ts +5 -5
- package/src/{templates → template/implementations}/service.template.ts +29 -12
- package/src/{templates → template/implementations}/view_enums_buttonset.template.ts +3 -3
- package/src/{templates → template/implementations}/view_enums_dropdown.template.ts +5 -21
- package/src/{templates → template/implementations}/view_enums_select.template.ts +4 -4
- package/src/{templates → template/implementations}/view_form.template.ts +11 -13
- package/src/{templates → template/implementations}/view_id_all_select.template.ts +3 -3
- package/src/{templates → template/implementations}/view_id_async_select.template.ts +3 -3
- package/src/{templates → template/implementations}/view_list.template.ts +13 -64
- package/src/{templates → template/implementations}/view_list_columns.template.ts +3 -3
- package/src/{templates → template/implementations}/view_search_input.template.ts +3 -3
- package/src/template/index.ts +4 -0
- package/src/template/template.ts +86 -0
- package/src/template/zod-converter.ts +219 -0
- package/src/testing/fixture-manager.ts +8 -1
- package/src/types/types.ts +39 -62
- package/src/utils/async-utils.ts +17 -0
- package/src/utils/console-util.ts +4 -0
- package/src/utils/esm-utils.ts +69 -0
- package/src/utils/path-utils.ts +102 -0
- package/src/utils/process-utils.ts +46 -0
- package/src/utils/sql-parser.ts +1 -1
- package/src/utils/utils.ts +14 -40
- package/src/utils/zod-error.ts +0 -1
- package/dist/api/base-frame.js.map +0 -1
- package/dist/api/caster.js.map +0 -1
- package/dist/api/code-converters.js.map +0 -1
- package/dist/api/context.js.map +0 -1
- package/dist/api/decorators.js.map +0 -1
- package/dist/api/index.js.map +0 -1
- package/dist/api/sonamu.js.map +0 -1
- package/dist/bin/build-config.js.map +0 -1
- package/dist/bin/cli-wrapper.js.map +0 -1
- package/dist/bin/cli.js.map +0 -1
- package/dist/database/_batch_update.js.map +0 -1
- package/dist/database/base-model.js.map +0 -1
- package/dist/database/code-generator.js.map +0 -1
- package/dist/database/db.js.map +0 -1
- package/dist/database/knex-plugins/knex-on-duplicate-update.js.map +0 -1
- package/dist/database/puri-wrapper.js.map +0 -1
- package/dist/database/puri.js.map +0 -1
- package/dist/database/puri.types.js.map +0 -1
- package/dist/database/transaction-context.js.map +0 -1
- package/dist/database/upsert-builder.js.map +0 -1
- package/dist/entity/entity-manager.js.map +0 -1
- package/dist/entity/entity-utils.js.map +0 -1
- package/dist/entity/entity.js.map +0 -1
- package/dist/exceptions/error-handler.js.map +0 -1
- package/dist/exceptions/so-exceptions.js.map +0 -1
- package/dist/file-storage/driver.js.map +0 -1
- package/dist/file-storage/file-storage.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/migration/code-generation.js.map +0 -1
- package/dist/migration/migration-set.js.map +0 -1
- package/dist/migration/migrator.js.map +0 -1
- package/dist/migration/types.js.map +0 -1
- package/dist/stream/index.js.map +0 -1
- package/dist/stream/sse.js.map +0 -1
- package/dist/syncer/index.js.map +0 -1
- package/dist/syncer/syncer.js.map +0 -1
- package/dist/templates/base-template.d.ts +0 -13
- package/dist/templates/base-template.d.ts.map +0 -1
- package/dist/templates/base-template.js +0 -2
- package/dist/templates/base-template.js.map +0 -1
- package/dist/templates/entity.template.d.ts.map +0 -1
- package/dist/templates/entity.template.js +0 -2
- package/dist/templates/entity.template.js.map +0 -1
- package/dist/templates/generated.template.d.ts.map +0 -1
- package/dist/templates/generated.template.js +0 -2
- package/dist/templates/generated.template.js.map +0 -1
- package/dist/templates/generated_http.template.d.ts.map +0 -1
- package/dist/templates/generated_http.template.js +0 -2
- package/dist/templates/generated_http.template.js.map +0 -1
- package/dist/templates/generated_sso.template.d.ts.map +0 -1
- package/dist/templates/generated_sso.template.js +0 -2
- package/dist/templates/generated_sso.template.js.map +0 -1
- package/dist/templates/index.d.ts +0 -2
- package/dist/templates/index.d.ts.map +0 -1
- package/dist/templates/index.js +0 -2
- package/dist/templates/index.js.map +0 -1
- package/dist/templates/init_types.template.d.ts.map +0 -1
- package/dist/templates/init_types.template.js +0 -2
- package/dist/templates/init_types.template.js.map +0 -1
- package/dist/templates/model.template.d.ts +0 -17
- package/dist/templates/model.template.d.ts.map +0 -1
- package/dist/templates/model.template.js +0 -2
- package/dist/templates/model.template.js.map +0 -1
- package/dist/templates/model_test.template.d.ts.map +0 -1
- package/dist/templates/model_test.template.js +0 -2
- package/dist/templates/model_test.template.js.map +0 -1
- package/dist/templates/service.template.d.ts.map +0 -1
- package/dist/templates/service.template.js +0 -2
- package/dist/templates/service.template.js.map +0 -1
- package/dist/templates/view_enums_buttonset.template.d.ts.map +0 -1
- package/dist/templates/view_enums_buttonset.template.js +0 -2
- package/dist/templates/view_enums_buttonset.template.js.map +0 -1
- package/dist/templates/view_enums_dropdown.template.d.ts.map +0 -1
- package/dist/templates/view_enums_dropdown.template.js +0 -2
- package/dist/templates/view_enums_dropdown.template.js.map +0 -1
- package/dist/templates/view_enums_select.template.d.ts.map +0 -1
- package/dist/templates/view_enums_select.template.js +0 -2
- package/dist/templates/view_enums_select.template.js.map +0 -1
- package/dist/templates/view_form.template.d.ts.map +0 -1
- package/dist/templates/view_form.template.js +0 -2
- package/dist/templates/view_form.template.js.map +0 -1
- package/dist/templates/view_id_all_select.template.d.ts.map +0 -1
- package/dist/templates/view_id_all_select.template.js +0 -2
- package/dist/templates/view_id_all_select.template.js.map +0 -1
- package/dist/templates/view_id_async_select.template.d.ts.map +0 -1
- package/dist/templates/view_id_async_select.template.js +0 -2
- package/dist/templates/view_id_async_select.template.js.map +0 -1
- package/dist/templates/view_list.template.d.ts.map +0 -1
- package/dist/templates/view_list.template.js +0 -2
- package/dist/templates/view_list.template.js.map +0 -1
- package/dist/templates/view_list_columns.template.d.ts.map +0 -1
- package/dist/templates/view_list_columns.template.js +0 -2
- package/dist/templates/view_list_columns.template.js.map +0 -1
- package/dist/templates/view_search_input.template.d.ts.map +0 -1
- package/dist/templates/view_search_input.template.js +0 -2
- package/dist/templates/view_search_input.template.js.map +0 -1
- package/dist/testing/_relation-graph.js.map +0 -1
- package/dist/testing/fixture-manager.js.map +0 -1
- package/dist/types/types.js.map +0 -1
- package/dist/typings/knex.d.js.map +0 -1
- package/dist/utils/async-utils.js.map +0 -1
- package/dist/utils/controller.js.map +0 -1
- package/dist/utils/fs-utils.js.map +0 -1
- package/dist/utils/lodash-able.js.map +0 -1
- package/dist/utils/model.js.map +0 -1
- package/dist/utils/sql-parser.js.map +0 -1
- package/dist/utils/utils.js.map +0 -1
- package/dist/utils/zod-error.js.map +0 -1
- package/src/templates/base-template.ts +0 -19
- package/src/templates/index.ts +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import _ from "lodash";
|
|
1
|
+
import * as _ from "lodash-es";
|
|
2
2
|
import knex, { Knex } from "knex";
|
|
3
3
|
import chalk from "chalk";
|
|
4
4
|
import { DateTime } from "luxon";
|
|
@@ -73,63 +73,24 @@ export class Migrator {
|
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
private async getMigrationCodes(): Promise<{
|
|
77
|
-
|
|
78
|
-
onlyTs: MigrationCode[];
|
|
79
|
-
onlyJs: MigrationCode[];
|
|
80
|
-
}> {
|
|
81
|
-
const srcMigrationsDir = `${Sonamu.apiRootPath}/src/migrations`;
|
|
82
|
-
const distMigrationsDir = `${Sonamu.apiRootPath}/dist/migrations`;
|
|
76
|
+
private async getMigrationCodes(): Promise<MigrationCode[]> {
|
|
77
|
+
const srcMigrationsDir = path.join(Sonamu.apiRootPath, "src", "migrations"); // 이건 환경에 관계없이 항상 src에서 찾아야 해요.
|
|
83
78
|
|
|
84
79
|
if (!(await exists(srcMigrationsDir))) {
|
|
85
80
|
await mkdir(srcMigrationsDir, {
|
|
86
81
|
recursive: true,
|
|
87
82
|
});
|
|
88
83
|
}
|
|
89
|
-
if (!(await exists(distMigrationsDir))) {
|
|
90
|
-
await mkdir(distMigrationsDir, {
|
|
91
|
-
recursive: true,
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
const srcMigrations = (await readdir(srcMigrationsDir))
|
|
95
|
-
.filter((f) => f.endsWith(".ts"))
|
|
96
|
-
.map((f) => f.split(".")[0]);
|
|
97
|
-
const distMigrations = (await readdir(distMigrationsDir))
|
|
98
|
-
.filter((f) => f.endsWith(".js"))
|
|
99
|
-
.map((f) => f.split(".")[0]);
|
|
100
|
-
|
|
101
|
-
const normal = _.intersection(srcMigrations, distMigrations)
|
|
102
|
-
.map((filename) => {
|
|
103
|
-
return {
|
|
104
|
-
name: filename,
|
|
105
|
-
path: path.join(srcMigrationsDir, filename) + ".ts",
|
|
106
|
-
};
|
|
107
|
-
})
|
|
108
|
-
.sort((a, b) => (a > b ? 1 : -1));
|
|
109
84
|
|
|
110
|
-
const
|
|
111
|
-
(
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
const onlyJs = _.difference(distMigrations, srcMigrations).map(
|
|
120
|
-
(filename) => {
|
|
121
|
-
return {
|
|
122
|
-
name: filename,
|
|
123
|
-
path: path.join(distMigrationsDir, filename) + ".js",
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
);
|
|
85
|
+
const codes = (await readdir(srcMigrationsDir))
|
|
86
|
+
.filter((f) => f.endsWith(".ts"))
|
|
87
|
+
.map((f) => ({
|
|
88
|
+
name: f.replace(".ts", ""),
|
|
89
|
+
path: path.join(srcMigrationsDir, f),
|
|
90
|
+
}))
|
|
91
|
+
.sort((a, b) => (a.name < b.name ? 1 : -1)); // 이름 내림차순 정렬(최신순)
|
|
127
92
|
|
|
128
|
-
return
|
|
129
|
-
normal,
|
|
130
|
-
onlyTs,
|
|
131
|
-
onlyJs,
|
|
132
|
-
};
|
|
93
|
+
return codes;
|
|
133
94
|
}
|
|
134
95
|
|
|
135
96
|
/**
|
|
@@ -142,25 +103,7 @@ export class Migrator {
|
|
|
142
103
|
* @returns
|
|
143
104
|
*/
|
|
144
105
|
async getStatus(): Promise<MigrationStatus> {
|
|
145
|
-
const
|
|
146
|
-
if (onlyTs.length > 0) {
|
|
147
|
-
console.debug({ onlyTs });
|
|
148
|
-
throw new ServiceUnavailableException(
|
|
149
|
-
`There are un-compiled TS migration files.\nPlease compile them first. You might want to run a development server with HMR.\n\n${onlyTs
|
|
150
|
-
.map((f) => f.name)
|
|
151
|
-
.join("\n")}`
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
if (onlyJs.length > 0) {
|
|
155
|
-
console.debug({ onlyJs });
|
|
156
|
-
await Promise.all(
|
|
157
|
-
onlyJs.map(async (f) => {
|
|
158
|
-
execSync(
|
|
159
|
-
`rm -f ${f.path.replace("/src/", "/dist/").replace(".ts", ".js")}`
|
|
160
|
-
);
|
|
161
|
-
})
|
|
162
|
-
);
|
|
163
|
-
}
|
|
106
|
+
const codes = await this.getMigrationCodes();
|
|
164
107
|
|
|
165
108
|
const connKeys = Object.keys(Sonamu.dbConfig).filter(
|
|
166
109
|
(key) => key.endsWith("_slave") === false
|
|
@@ -187,7 +130,7 @@ export class Migrator {
|
|
|
187
130
|
try {
|
|
188
131
|
const [, fdList] = await tConn.migrate.list();
|
|
189
132
|
return fdList.map((fd: { file: string }) =>
|
|
190
|
-
fd.file.replace(".
|
|
133
|
+
fd.file.replace(".ts", "")
|
|
191
134
|
);
|
|
192
135
|
} catch (err) {
|
|
193
136
|
return [];
|
|
@@ -222,6 +165,11 @@ export class Migrator {
|
|
|
222
165
|
const preparedCodes: GenMigrationCode[] = await (async () => {
|
|
223
166
|
const status0conn = statuses.find((status) => status.status === 0);
|
|
224
167
|
if (status0conn === undefined) {
|
|
168
|
+
console.warn(
|
|
169
|
+
chalk.yellow(
|
|
170
|
+
`While trying to prepare migration codes, we found that there is no database to compare migrations. We need at least one database where every migration is applied(status === 0). You might want to apply your existing migrations to one of the databases.`
|
|
171
|
+
)
|
|
172
|
+
);
|
|
225
173
|
return [];
|
|
226
174
|
}
|
|
227
175
|
|
|
@@ -235,14 +183,10 @@ export class Migrator {
|
|
|
235
183
|
|
|
236
184
|
return {
|
|
237
185
|
conns: statuses,
|
|
238
|
-
codes
|
|
186
|
+
codes,
|
|
239
187
|
preparedCodes,
|
|
240
188
|
};
|
|
241
189
|
/*
|
|
242
|
-
TS/JS 코드 컴파일 상태 확인
|
|
243
|
-
1. 원본 파일 없는 JS파일이 존재하는 경우: 삭제
|
|
244
|
-
2. 컴파일 되지 않은 TS파일이 존재하는 경우: throw 쳐서 데브 서버 오픈 요청
|
|
245
|
-
|
|
246
190
|
DB 마이그레이션 상태 확인
|
|
247
191
|
1. 전체 DB설정에 대해서 현재 마이그레이션 상태 확인
|
|
248
192
|
- connKey: string
|
|
@@ -355,12 +299,9 @@ export class Migrator {
|
|
|
355
299
|
);
|
|
356
300
|
}
|
|
357
301
|
|
|
358
|
-
const delFiles = codeNames
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
`${Sonamu.apiRootPath}/dist/migrations/${codeName}.js`,
|
|
362
|
-
])
|
|
363
|
-
.flat();
|
|
302
|
+
const delFiles = codeNames.map(
|
|
303
|
+
(codeName) => `${Sonamu.apiRootPath}/src/migrations/${codeName}.ts`
|
|
304
|
+
);
|
|
364
305
|
|
|
365
306
|
const res = await Promise.all(
|
|
366
307
|
delFiles.map(async (delFile) => {
|
|
@@ -421,14 +362,13 @@ export class Migrator {
|
|
|
421
362
|
];
|
|
422
363
|
const migrationsDir = `${Sonamu.apiRootPath}/src/migrations`;
|
|
423
364
|
const delList = pendingList.map((df) => {
|
|
424
|
-
return path.join(migrationsDir, df.file)
|
|
365
|
+
return path.join(migrationsDir, df.file);
|
|
425
366
|
});
|
|
426
367
|
for (let p of delList) {
|
|
427
368
|
if (await exists(p)) {
|
|
428
369
|
await unlink(p);
|
|
429
370
|
}
|
|
430
371
|
}
|
|
431
|
-
await this.cleanUpDist(true);
|
|
432
372
|
}
|
|
433
373
|
|
|
434
374
|
/**
|
|
@@ -553,75 +493,6 @@ export class Migrator {
|
|
|
553
493
|
console.dir({ rollbackAllResult }, { depth: null });
|
|
554
494
|
console.timeEnd(chalk.red("rollback:"));
|
|
555
495
|
}
|
|
556
|
-
|
|
557
|
-
/**
|
|
558
|
-
* 빌드된 마이그레이션 파일을 삭제합니다.
|
|
559
|
-
*
|
|
560
|
-
* CLI에서 사용됩니다.
|
|
561
|
-
*
|
|
562
|
-
* @param force 강제 삭제 여부
|
|
563
|
-
* @returns
|
|
564
|
-
*/
|
|
565
|
-
async cleanUpDist(force: boolean = false): Promise<void> {
|
|
566
|
-
async function getFilesUnder(dir: string): Promise<string[]> {
|
|
567
|
-
const migrationPath = path.join(Sonamu.apiRootPath, dir, "migrations");
|
|
568
|
-
if (!(await exists(migrationPath))) {
|
|
569
|
-
await mkdir(migrationPath, {
|
|
570
|
-
recursive: true,
|
|
571
|
-
});
|
|
572
|
-
}
|
|
573
|
-
return (await readdir(migrationPath)).filter(
|
|
574
|
-
(filename) => filename.startsWith(".") === false
|
|
575
|
-
);
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
const files = {
|
|
579
|
-
src: await getFilesUnder("src"),
|
|
580
|
-
dist: await getFilesUnder("dist"),
|
|
581
|
-
};
|
|
582
|
-
|
|
583
|
-
const diffOnSrc = _.differenceBy(
|
|
584
|
-
files.src,
|
|
585
|
-
files.dist,
|
|
586
|
-
(filename) => filename.split(".")[0]
|
|
587
|
-
);
|
|
588
|
-
if (diffOnSrc.length > 0) {
|
|
589
|
-
throw new Error(
|
|
590
|
-
"컴파일 되지 않은 파일이 있습니다.\n" + diffOnSrc.join("\n")
|
|
591
|
-
);
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
const diffOnDist = _.differenceBy(
|
|
595
|
-
files.dist,
|
|
596
|
-
files.src,
|
|
597
|
-
(filename) => filename.split(".")[0]
|
|
598
|
-
);
|
|
599
|
-
if (diffOnDist.length > 0) {
|
|
600
|
-
console.log(chalk.red("원본 ts파일을 찾을 수 없는 js파일이 있습니다."));
|
|
601
|
-
console.log(diffOnDist);
|
|
602
|
-
|
|
603
|
-
if (!force) {
|
|
604
|
-
const answer = await prompts({
|
|
605
|
-
type: "confirm",
|
|
606
|
-
name: "value",
|
|
607
|
-
message: "삭제를 진행하시겠습니까?",
|
|
608
|
-
initial: true,
|
|
609
|
-
});
|
|
610
|
-
if (answer.value === false) {
|
|
611
|
-
return;
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
const filesToRm = diffOnDist.map((filename) => {
|
|
616
|
-
return path.join(Sonamu.apiRootPath, "dist", "migrations", filename);
|
|
617
|
-
});
|
|
618
|
-
for (const filePath of filesToRm) {
|
|
619
|
-
await unlink(filePath);
|
|
620
|
-
}
|
|
621
|
-
console.log(chalk.green(`${filesToRm.length}건 삭제되었습니다!`));
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
|
|
625
496
|
/**
|
|
626
497
|
* Shadow DB 테스트를 진행합니다.
|
|
627
498
|
*
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Sonamu } from "../api/sonamu";
|
|
2
|
+
|
|
3
|
+
export class Naite {
|
|
4
|
+
// 테스트 로그 기록
|
|
5
|
+
static t(name: string, value: any) {
|
|
6
|
+
const context = Sonamu.getContext();
|
|
7
|
+
const store = context?.naiteStore;
|
|
8
|
+
|
|
9
|
+
if (!store) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
if (store.has(name)) {
|
|
13
|
+
// 이미 값이 있는 경우
|
|
14
|
+
if (Array.isArray(store.get(name))) {
|
|
15
|
+
// 배열에 추가
|
|
16
|
+
store.set(name, [...store.get(name), value]);
|
|
17
|
+
} else {
|
|
18
|
+
// 배열이 아닌 경우 배열로 변환
|
|
19
|
+
store.set(name, [store.get(name), value]);
|
|
20
|
+
}
|
|
21
|
+
} else {
|
|
22
|
+
// 값이 없는 경우 추가
|
|
23
|
+
store.set(name, value);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// 테스트에서 값 가져오기
|
|
28
|
+
static get(name: string): any {
|
|
29
|
+
const context = Sonamu.getContext();
|
|
30
|
+
if (!context?.naiteStore || !context.naiteStore.has(name)) {
|
|
31
|
+
throw new Error(`Naite.get: \`${name}\` not found`);
|
|
32
|
+
}
|
|
33
|
+
return context?.naiteStore?.get(name);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// 전체 리스트 가져오기
|
|
37
|
+
static getAll(): { [key: string]: any } {
|
|
38
|
+
const context = Sonamu.getContext();
|
|
39
|
+
if (!context?.naiteStore) {
|
|
40
|
+
return {};
|
|
41
|
+
}
|
|
42
|
+
return Object.fromEntries(context.naiteStore.entries());
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// expect 래퍼 (CJS-ESM 이슈로 현재 사용불가)
|
|
46
|
+
// static expect(name: string) {
|
|
47
|
+
// if (!this.vitestExpect) {
|
|
48
|
+
// throw new Error("Vitest is not initialized");
|
|
49
|
+
// }
|
|
50
|
+
// return this.vitestExpect(this.get(name));
|
|
51
|
+
// }
|
|
52
|
+
|
|
53
|
+
// 일반 로그 레벨
|
|
54
|
+
static d(_message: string) {
|
|
55
|
+
// TODO: Logger 연결
|
|
56
|
+
console.log(`[DEBUG] ${_message}`);
|
|
57
|
+
}
|
|
58
|
+
static i(_message: string) {
|
|
59
|
+
// TODO: Logger 연결
|
|
60
|
+
console.log(`[INFO] ${_message}`);
|
|
61
|
+
}
|
|
62
|
+
static w(_message: string) {
|
|
63
|
+
// TODO: Logger 연결
|
|
64
|
+
console.log(`[WARN] ${_message}`);
|
|
65
|
+
}
|
|
66
|
+
static e(_message: string) {
|
|
67
|
+
// TODO: Logger 연결
|
|
68
|
+
console.log(`[ERROR] ${_message}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { ApiParam, ApiParamType } from "../types/types";
|
|
2
|
+
import { readFile } from "fs/promises";
|
|
3
|
+
import * as _ from "lodash-es";
|
|
4
|
+
import ts from "typescript";
|
|
5
|
+
import { ExtendedApi, registeredApis } from "../api/decorators";
|
|
6
|
+
import inflection from "inflection";
|
|
7
|
+
import assert from "assert";
|
|
8
|
+
import { AbsolutePath } from "../utils/path-utils";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* TypeScript 파일을 파싱하여 API 메소드 정보를 추출합니다.
|
|
12
|
+
* @api 데코레이터가 붙은 메소드들의 타입 정보를 분석합니다.
|
|
13
|
+
* @param filePath - 파싱할 TypeScript 파일의 절대 경로
|
|
14
|
+
* @returns API 메소드 정보 배열 (타입 파라미터, 파라미터, 리턴 타입 등)
|
|
15
|
+
*/
|
|
16
|
+
export async function readApisFromFile(filePath: AbsolutePath) {
|
|
17
|
+
if (!filePath.endsWith(".ts")) {
|
|
18
|
+
throw new Error(`${filePath} does not seem to be a TypeScript file. Please check the file path. We only support parsing TypeScript files.`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const sourceFile = ts.createSourceFile(
|
|
22
|
+
filePath,
|
|
23
|
+
(await readFile(filePath)).toString(),
|
|
24
|
+
ts.ScriptTarget.Latest
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
const methods: Omit<ExtendedApi, "path" | "options">[] = [];
|
|
28
|
+
let modelName: string = "UnknownModel";
|
|
29
|
+
let methodName: string = "unknownMethod";
|
|
30
|
+
const visitor = (node: ts.Node) => {
|
|
31
|
+
if (ts.isClassDeclaration(node)) {
|
|
32
|
+
if (node.name && ts.isIdentifier(node.name)) {
|
|
33
|
+
modelName = node.name.escapedText.toString().replace(/Class$/, "");
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (ts.isMethodDeclaration(node)) {
|
|
37
|
+
if (ts.isIdentifier(node.name)) {
|
|
38
|
+
methodName = node.name.escapedText.toString();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const typeParameters: ApiParamType.TypeParam[] = (
|
|
42
|
+
node.typeParameters ?? []
|
|
43
|
+
).map((typeParam) => {
|
|
44
|
+
const tp = typeParam as ts.TypeParameterDeclaration;
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
t: "type-param",
|
|
48
|
+
id: tp.name.escapedText.toString(),
|
|
49
|
+
constraint: tp.constraint
|
|
50
|
+
? resolveTypeNode(tp.constraint)
|
|
51
|
+
: undefined,
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
const parameters: ApiParam[] = node.parameters.map((paramDec, index) => {
|
|
55
|
+
const defaultDef = printNode(paramDec.initializer, sourceFile);
|
|
56
|
+
|
|
57
|
+
// 기본값이 있는 경우 paramDec.type가 undefined로 나옴
|
|
58
|
+
|
|
59
|
+
return resolveParamDec(
|
|
60
|
+
{
|
|
61
|
+
name: paramDec.name,
|
|
62
|
+
type: paramDec.type as ts.TypeNode,
|
|
63
|
+
optional:
|
|
64
|
+
paramDec.questionToken !== undefined ||
|
|
65
|
+
paramDec.initializer !== undefined,
|
|
66
|
+
defaultDef,
|
|
67
|
+
},
|
|
68
|
+
index
|
|
69
|
+
);
|
|
70
|
+
});
|
|
71
|
+
if (node.type === undefined) {
|
|
72
|
+
throw new Error(
|
|
73
|
+
`리턴 타입이 기재되지 않은 메소드 ${modelName}.${methodName}`
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
const returnType = resolveTypeNode(node.type!);
|
|
77
|
+
|
|
78
|
+
methods.push({
|
|
79
|
+
modelName,
|
|
80
|
+
methodName,
|
|
81
|
+
typeParameters,
|
|
82
|
+
parameters,
|
|
83
|
+
returnType,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
ts.forEachChild(node, visitor);
|
|
87
|
+
};
|
|
88
|
+
visitor(sourceFile);
|
|
89
|
+
|
|
90
|
+
if (methods.length === 0) {
|
|
91
|
+
return [];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// 현재 파일의 등록된 API 필터
|
|
95
|
+
const currentModelApis = registeredApis.filter((api) => {
|
|
96
|
+
return methods.find(
|
|
97
|
+
(method) =>
|
|
98
|
+
method.modelName === api.modelName &&
|
|
99
|
+
method.methodName === api.methodName
|
|
100
|
+
);
|
|
101
|
+
});
|
|
102
|
+
if (currentModelApis.length === 0) {
|
|
103
|
+
// const p = path.join(tmpdir(), "sonamu-syncer-error.json");
|
|
104
|
+
// writeFileSync(p, JSON.stringify(registeredApis, null, 2));
|
|
105
|
+
// execSync(`open ${p}`);
|
|
106
|
+
throw new Error(`현재 파일에 사전 등록된 API가 없습니다. ${filePath}`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// 등록된 API에 현재 메소드 타입 정보 확장
|
|
110
|
+
const extendedApis = currentModelApis.map((api) => {
|
|
111
|
+
const foundMethod = methods.find(
|
|
112
|
+
(method) =>
|
|
113
|
+
method.modelName === api.modelName &&
|
|
114
|
+
method.methodName === api.methodName
|
|
115
|
+
);
|
|
116
|
+
return {
|
|
117
|
+
...api,
|
|
118
|
+
typeParameters: foundMethod!.typeParameters,
|
|
119
|
+
parameters: foundMethod!.parameters,
|
|
120
|
+
returnType: foundMethod!.returnType,
|
|
121
|
+
};
|
|
122
|
+
});
|
|
123
|
+
return extendedApis;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function resolveTypeNode(typeNode: ts.TypeNode): ApiParamType {
|
|
127
|
+
switch (typeNode?.kind) {
|
|
128
|
+
case ts.SyntaxKind.AnyKeyword:
|
|
129
|
+
return "any";
|
|
130
|
+
case ts.SyntaxKind.UnknownKeyword:
|
|
131
|
+
return "unknown";
|
|
132
|
+
case ts.SyntaxKind.StringKeyword:
|
|
133
|
+
return "string";
|
|
134
|
+
case ts.SyntaxKind.NumberKeyword:
|
|
135
|
+
return "number";
|
|
136
|
+
case ts.SyntaxKind.BooleanKeyword:
|
|
137
|
+
return "boolean";
|
|
138
|
+
case ts.SyntaxKind.UndefinedKeyword:
|
|
139
|
+
return "undefined";
|
|
140
|
+
case ts.SyntaxKind.NullKeyword:
|
|
141
|
+
return "null";
|
|
142
|
+
case ts.SyntaxKind.VoidKeyword:
|
|
143
|
+
return "void";
|
|
144
|
+
case ts.SyntaxKind.LiteralType:
|
|
145
|
+
const literal = (typeNode as ts.LiteralTypeNode).literal;
|
|
146
|
+
if (ts.isStringLiteral(literal)) {
|
|
147
|
+
return {
|
|
148
|
+
t: "string-literal",
|
|
149
|
+
value: literal.text,
|
|
150
|
+
};
|
|
151
|
+
} else if (ts.isNumericLiteral(literal)) {
|
|
152
|
+
return {
|
|
153
|
+
t: "numeric-literal",
|
|
154
|
+
value: Number(literal.text),
|
|
155
|
+
};
|
|
156
|
+
} else {
|
|
157
|
+
if (literal.kind === ts.SyntaxKind.NullKeyword) {
|
|
158
|
+
return "null";
|
|
159
|
+
} else if (literal.kind === ts.SyntaxKind.UndefinedKeyword) {
|
|
160
|
+
return "undefined";
|
|
161
|
+
} else if (literal.kind === ts.SyntaxKind.TrueKeyword) {
|
|
162
|
+
return "true";
|
|
163
|
+
} else if (literal.kind === ts.SyntaxKind.FalseKeyword) {
|
|
164
|
+
return "false";
|
|
165
|
+
}
|
|
166
|
+
throw new Error("알 수 없는 리터럴");
|
|
167
|
+
}
|
|
168
|
+
case ts.SyntaxKind.ArrayType:
|
|
169
|
+
const arrNode = typeNode as ts.ArrayTypeNode;
|
|
170
|
+
return {
|
|
171
|
+
t: "array",
|
|
172
|
+
elementsType: resolveTypeNode(arrNode.elementType),
|
|
173
|
+
};
|
|
174
|
+
case ts.SyntaxKind.TypeLiteral:
|
|
175
|
+
const literalNode = typeNode as ts.TypeLiteralNode;
|
|
176
|
+
return {
|
|
177
|
+
t: "object",
|
|
178
|
+
props: literalNode.members.map((member) => {
|
|
179
|
+
if (ts.isIndexSignatureDeclaration(member)) {
|
|
180
|
+
assert(member.parameters[0]);
|
|
181
|
+
const res = resolveParamDec({
|
|
182
|
+
name: member.parameters[0].name as ts.Identifier,
|
|
183
|
+
type: member.parameters[0].type as ts.TypeNode,
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
return resolveParamDec({
|
|
187
|
+
name: {
|
|
188
|
+
escapedText: `[${res.name}${res.optional ? "?" : ""}: ${
|
|
189
|
+
res.type
|
|
190
|
+
}]`,
|
|
191
|
+
} as ts.Identifier,
|
|
192
|
+
type: member.type as ts.TypeNode,
|
|
193
|
+
});
|
|
194
|
+
} else {
|
|
195
|
+
return resolveParamDec({
|
|
196
|
+
name: (member as ts.PropertySignature).name as ts.Identifier,
|
|
197
|
+
type: (member as ts.PropertySignature).type as ts.TypeNode,
|
|
198
|
+
optional:
|
|
199
|
+
(member as ts.PropertySignature).questionToken !== undefined,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}),
|
|
203
|
+
};
|
|
204
|
+
case ts.SyntaxKind.TypeReference:
|
|
205
|
+
return {
|
|
206
|
+
t: "ref",
|
|
207
|
+
id: (
|
|
208
|
+
(typeNode as ts.TypeReferenceNode).typeName as ts.Identifier
|
|
209
|
+
).escapedText.toString(),
|
|
210
|
+
args: (typeNode as ts.TypeReferenceNode).typeArguments?.map((typeArg) =>
|
|
211
|
+
resolveTypeNode(typeArg)
|
|
212
|
+
),
|
|
213
|
+
};
|
|
214
|
+
case ts.SyntaxKind.UnionType:
|
|
215
|
+
return {
|
|
216
|
+
t: "union",
|
|
217
|
+
types: (typeNode as ts.UnionTypeNode).types.map((type) =>
|
|
218
|
+
resolveTypeNode(type)
|
|
219
|
+
),
|
|
220
|
+
};
|
|
221
|
+
case ts.SyntaxKind.IntersectionType:
|
|
222
|
+
return {
|
|
223
|
+
t: "intersection",
|
|
224
|
+
types: (typeNode as ts.IntersectionTypeNode).types.map((type) =>
|
|
225
|
+
resolveTypeNode(type)
|
|
226
|
+
),
|
|
227
|
+
};
|
|
228
|
+
case ts.SyntaxKind.IndexedAccessType:
|
|
229
|
+
return {
|
|
230
|
+
t: "indexed-access",
|
|
231
|
+
object: resolveTypeNode(
|
|
232
|
+
(typeNode as ts.IndexedAccessTypeNode).objectType
|
|
233
|
+
),
|
|
234
|
+
index: resolveTypeNode(
|
|
235
|
+
(typeNode as ts.IndexedAccessTypeNode).indexType
|
|
236
|
+
),
|
|
237
|
+
};
|
|
238
|
+
case ts.SyntaxKind.TupleType:
|
|
239
|
+
if (ts.isTupleTypeNode(typeNode)) {
|
|
240
|
+
return {
|
|
241
|
+
t: "tuple-type",
|
|
242
|
+
elements: typeNode.elements.map((elem) => resolveTypeNode(elem)),
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
break;
|
|
246
|
+
case undefined:
|
|
247
|
+
throw new Error(`typeNode undefined`);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
console.debug(typeNode);
|
|
251
|
+
throw new Error(`알 수 없는 SyntaxKind ${typeNode.kind}`);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function resolveParamDec(
|
|
255
|
+
paramDec: {
|
|
256
|
+
name: ts.BindingName;
|
|
257
|
+
type: ts.TypeNode;
|
|
258
|
+
optional?: boolean;
|
|
259
|
+
defaultDef?: string;
|
|
260
|
+
},
|
|
261
|
+
index: number = 0
|
|
262
|
+
): ApiParam {
|
|
263
|
+
const name = paramDec.name as ts.Identifier;
|
|
264
|
+
const type = resolveTypeNode(paramDec.type);
|
|
265
|
+
|
|
266
|
+
if (name === undefined) {
|
|
267
|
+
console.debug({ name, type, paramDec });
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const result: ApiParam = {
|
|
271
|
+
name: name.escapedText ? name.escapedText.toString() : `nonameAt${index}`,
|
|
272
|
+
type,
|
|
273
|
+
optional: paramDec.optional === true,
|
|
274
|
+
defaultDef: paramDec?.defaultDef,
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
// 구조분해할당의 경우 타입이름 사용
|
|
278
|
+
if (
|
|
279
|
+
ts.isObjectBindingPattern(name) &&
|
|
280
|
+
ts.isTypeReferenceNode(paramDec.type) &&
|
|
281
|
+
ts.isIdentifier(paramDec.type.typeName)
|
|
282
|
+
) {
|
|
283
|
+
result.name = inflection.camelize(paramDec.type.typeName.text, true);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return result;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function printNode(
|
|
290
|
+
node: ts.Node | undefined,
|
|
291
|
+
sourceFile: ts.SourceFile
|
|
292
|
+
): string | undefined {
|
|
293
|
+
if (node === undefined) {
|
|
294
|
+
return undefined;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
|
|
298
|
+
return printer.printNode(ts.EmitHint.Unspecified, node, sourceFile);
|
|
299
|
+
}
|