sonamu 0.5.7 → 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.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 +2 -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.js +109 -2
- package/dist/database/puri.d.ts +23 -16
- package/dist/database/puri.d.ts.map +1 -1
- package/dist/database/puri.js +539 -2
- package/dist/database/puri.types.d.ts +8 -3
- package/dist/database/puri.types.d.ts.map +1 -1
- package/dist/database/puri.types.js +3 -2
- 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 -8
- 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 +1 -0
- package/src/api/sonamu.ts +81 -67
- 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 +10 -52
- package/src/database/puri.ts +78 -53
- package/src/database/puri.types.ts +18 -5
- 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 +19 -11
- 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 +38 -61
- 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
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hot-hook 초기화하는 모듈입니다.
|
|
3
|
+
*
|
|
4
|
+
* 이 파일은 --import 플래그로 프로세스 시작 시 로드되어야 합니다.
|
|
5
|
+
*
|
|
6
|
+
* 환경변수:
|
|
7
|
+
* - API_ROOT_PATH: 사용자 프로젝트의 API 루트 경로
|
|
8
|
+
* - HOT: 'yes'일 때만 hot-hook 활성화
|
|
9
|
+
*/ if (process.env.HOT === "yes" && process.env.API_ROOT_PATH) {
|
|
10
|
+
const { hot } = await import("@sonamu-kit/hot-hook");
|
|
11
|
+
await hot.init({
|
|
12
|
+
rootDirectory: process.env.API_ROOT_PATH,
|
|
13
|
+
boundaries: [
|
|
14
|
+
`./src/**/*.ts`
|
|
15
|
+
]
|
|
16
|
+
});
|
|
17
|
+
console.log("🔥 Hot-hook initialized");
|
|
18
|
+
}
|
|
19
|
+
export { };
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9iaW4vaG90LWhvb2stcmVnaXN0ZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBob3QtaG9vayDstIjquLDtmZTtlZjripQg66qo65OI7J6F64uI64ukLlxuICpcbiAqIOydtCDtjIzsnbzsnYAgLS1pbXBvcnQg7ZSM656Y6re466GcIO2UhOuhnOyEuOyKpCDsi5zsnpEg7IucIOuhnOuTnOuQmOyWtOyVvCDtlanri4jri6QuXG4gKlxuICog7ZmY6rK967OA7IiYOlxuICogLSBBUElfUk9PVF9QQVRIOiDsgqzsmqnsnpAg7ZSE66Gc7KCd7Yq47J2YIEFQSSDro6jtirgg6rK966GcXG4gKiAtIEhPVDogJ3llcyfsnbwg65WM66eMIGhvdC1ob29rIO2ZnOyEse2ZlFxuICovXG5cbmlmIChwcm9jZXNzLmVudi5IT1QgPT09IFwieWVzXCIgJiYgcHJvY2Vzcy5lbnYuQVBJX1JPT1RfUEFUSCkge1xuICBjb25zdCB7IGhvdCB9ID0gYXdhaXQgaW1wb3J0KFwiQHNvbmFtdS1raXQvaG90LWhvb2tcIik7XG5cbiAgYXdhaXQgaG90LmluaXQoe1xuICAgIHJvb3REaXJlY3Rvcnk6IHByb2Nlc3MuZW52LkFQSV9ST09UX1BBVEgsIC8vIOydtCDsuZzqtazqsIAg7ZSE66Gc7KCd7Yq4IEFQSSDqsr3roZzroZwg7J6YIOyEpOygleuQmOyWtOyVvCDslYTrnpgg67CU7Jq0642U66as6rCAIOyekeuPme2VqeuLiOuLpC5cbiAgICBib3VuZGFyaWVzOiBbYC4vc3JjLyoqLyoudHNgXSwgLy8g7ZSE66Gc7KCd7Yq47J2YIOydtCDsuZzqtazrk6TsnbQg67CU7Jq0642U66as6rCAIOuQqeuLiOuLpC5cbiAgfSk7XG5cbiAgY29uc29sZS5sb2coXCLwn5SlIEhvdC1ob29rIGluaXRpYWxpemVkXCIpO1xufVxuXG5leHBvcnQge307XG4iXSwibmFtZXMiOlsicHJvY2VzcyIsImVudiIsIkhPVCIsIkFQSV9ST09UX1BBVEgiLCJob3QiLCJpbml0Iiwicm9vdERpcmVjdG9yeSIsImJvdW5kYXJpZXMiLCJjb25zb2xlIiwibG9nIl0sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Q0FRQyxHQUVELElBQUlBLFFBQVFDLEdBQUcsQ0FBQ0MsR0FBRyxLQUFLLFNBQVNGLFFBQVFDLEdBQUcsQ0FBQ0UsYUFBYSxFQUFFO0lBQzFELE1BQU0sRUFBRUMsR0FBRyxFQUFFLEdBQUcsTUFBTSxNQUFNLENBQUM7SUFFN0IsTUFBTUEsSUFBSUMsSUFBSSxDQUFDO1FBQ2JDLGVBQWVOLFFBQVFDLEdBQUcsQ0FBQ0UsYUFBYTtRQUN4Q0ksWUFBWTtZQUFDLENBQUMsYUFBYSxDQUFDO1NBQUM7SUFDL0I7SUFFQUMsUUFBUUMsR0FBRyxDQUFDO0FBQ2Q7QUFFQSxXQUFVIn0=
|
|
@@ -1,2 +1,78 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/*
|
|
2
|
+
아래의 링크에서 참고해서 가져온 소스코드
|
|
3
|
+
https://github.com/knex/knex/issues/5716
|
|
4
|
+
*/ /**
|
|
5
|
+
* Batch update rows in a table. Technically its a patch since it only updates the specified columns. Any omitted columns will not be affected
|
|
6
|
+
* @param db
|
|
7
|
+
* @param tableName
|
|
8
|
+
* @param ids
|
|
9
|
+
* @param rows
|
|
10
|
+
* @param chunkSize
|
|
11
|
+
* @param trx
|
|
12
|
+
*/ export async function batchUpdate(knex, tableName, ids, rows, chunkSize = 50, trx = null) {
|
|
13
|
+
const chunks = [];
|
|
14
|
+
for(let i = 0; i < rows.length; i += chunkSize){
|
|
15
|
+
chunks.push(rows.slice(i, i + chunkSize));
|
|
16
|
+
}
|
|
17
|
+
const executeUpdate = async (chunk, transaction)=>{
|
|
18
|
+
const sql = generateBatchUpdateSQL(knex, tableName, chunk, ids);
|
|
19
|
+
return knex.raw(sql).transacting(transaction);
|
|
20
|
+
};
|
|
21
|
+
if (trx) {
|
|
22
|
+
for (const chunk of chunks){
|
|
23
|
+
await executeUpdate(chunk, trx);
|
|
24
|
+
}
|
|
25
|
+
} else {
|
|
26
|
+
await knex.transaction(async (newTrx)=>{
|
|
27
|
+
for (const chunk of chunks){
|
|
28
|
+
await executeUpdate(chunk, newTrx);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Generate a set of unique keys in a data array
|
|
35
|
+
*
|
|
36
|
+
* Example:
|
|
37
|
+
* [ { a: 1, b: 2 }, { a: 3, c: 4 } ] => Set([ "a", "b", "c" ])
|
|
38
|
+
* @param data
|
|
39
|
+
*/ function generateKeySetFromData(data) {
|
|
40
|
+
const keySet = new Set();
|
|
41
|
+
for (const row of data){
|
|
42
|
+
for (const key of Object.keys(row)){
|
|
43
|
+
keySet.add(key);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return keySet;
|
|
47
|
+
}
|
|
48
|
+
function generateBatchUpdateSQL(db, tableName, data, identifiers) {
|
|
49
|
+
const keySet = generateKeySetFromData(data);
|
|
50
|
+
const bindings = [];
|
|
51
|
+
const invalidIdentifiers = identifiers.filter((id)=>!keySet.has(id));
|
|
52
|
+
if (invalidIdentifiers.length > 0) {
|
|
53
|
+
throw new Error(`Invalid identifiers: ${invalidIdentifiers.join(", ")}. Identifiers must exist in the data`);
|
|
54
|
+
}
|
|
55
|
+
const cases = [];
|
|
56
|
+
for (const key of keySet){
|
|
57
|
+
if (identifiers.includes(key)) continue;
|
|
58
|
+
const rows = [];
|
|
59
|
+
for (const row of data){
|
|
60
|
+
if (Object.hasOwnProperty.call(row, key)) {
|
|
61
|
+
const whereClause = identifiers.map((id)=>`\`${id}\` = ?`).join(" AND ");
|
|
62
|
+
rows.push(`WHEN (${whereClause}) THEN ?`);
|
|
63
|
+
bindings.push(...identifiers.map((i)=>row[i]), row[key]);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const whenThen = rows.join(" ");
|
|
67
|
+
cases.push(`\`${key}\` = CASE ${whenThen} ELSE \`${key}\` END`);
|
|
68
|
+
}
|
|
69
|
+
const whereInClauses = identifiers.map((col)=>`${col} IN (${data.map(()=>"?").join(", ")})`).join(" AND ");
|
|
70
|
+
const whereInBindings = identifiers.flatMap((col)=>data.map((row)=>row[col]));
|
|
71
|
+
const sql = db.raw(`UPDATE \`${tableName}\` SET ${cases.join(", ")} WHERE ${whereInClauses}`, [
|
|
72
|
+
...bindings,
|
|
73
|
+
...whereInBindings
|
|
74
|
+
]);
|
|
75
|
+
return sql.toQuery();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kYXRhYmFzZS9fYmF0Y2hfdXBkYXRlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qXG4gIOyVhOuemOydmCDrp4Htgazsl5DshJwg7LC46rOg7ZW07IScIOqwgOyguOyYqCDshozsiqTsvZTrk5xcbiAgaHR0cHM6Ly9naXRodWIuY29tL2tuZXgva25leC9pc3N1ZXMvNTcxNlxuKi9cblxuaW1wb3J0IHsgS25leCB9IGZyb20gXCJrbmV4XCI7XG5cbmV4cG9ydCB0eXBlIFJvd1dpdGhJZDxJZCBleHRlbmRzIHN0cmluZz4gPSB7XG4gIFtrZXkgaW4gSWRdOiBhbnk7XG59ICYgUmVjb3JkPHN0cmluZywgYW55PjtcblxuLyoqXG4gKiBCYXRjaCB1cGRhdGUgcm93cyBpbiBhIHRhYmxlLiBUZWNobmljYWxseSBpdHMgYSBwYXRjaCBzaW5jZSBpdCBvbmx5IHVwZGF0ZXMgdGhlIHNwZWNpZmllZCBjb2x1bW5zLiBBbnkgb21pdHRlZCBjb2x1bW5zIHdpbGwgbm90IGJlIGFmZmVjdGVkXG4gKiBAcGFyYW0gZGJcbiAqIEBwYXJhbSB0YWJsZU5hbWVcbiAqIEBwYXJhbSBpZHNcbiAqIEBwYXJhbSByb3dzXG4gKiBAcGFyYW0gY2h1bmtTaXplXG4gKiBAcGFyYW0gdHJ4XG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBiYXRjaFVwZGF0ZTxJZCBleHRlbmRzIHN0cmluZz4oXG4gIGtuZXg6IEtuZXgsXG4gIHRhYmxlTmFtZTogc3RyaW5nLFxuICBpZHM6IElkW10sXG4gIHJvd3M6IFJvd1dpdGhJZDxJZD5bXSxcbiAgY2h1bmtTaXplID0gNTAsXG4gIHRyeDogS25leC5UcmFuc2FjdGlvbiB8IG51bGwgPSBudWxsXG4pIHtcbiAgY29uc3QgY2h1bmtzOiBSb3dXaXRoSWQ8SWQ+W11bXSA9IFtdO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHJvd3MubGVuZ3RoOyBpICs9IGNodW5rU2l6ZSkge1xuICAgIGNodW5rcy5wdXNoKHJvd3Muc2xpY2UoaSwgaSArIGNodW5rU2l6ZSkpO1xuICB9XG5cbiAgY29uc3QgZXhlY3V0ZVVwZGF0ZSA9IGFzeW5jIChcbiAgICBjaHVuazogUm93V2l0aElkPElkPltdLFxuICAgIHRyYW5zYWN0aW9uOiBLbmV4LlRyYW5zYWN0aW9uXG4gICkgPT4ge1xuICAgIGNvbnN0IHNxbCA9IGdlbmVyYXRlQmF0Y2hVcGRhdGVTUUwoa25leCwgdGFibGVOYW1lLCBjaHVuaywgaWRzKTtcbiAgICByZXR1cm4ga25leC5yYXcoc3FsKS50cmFuc2FjdGluZyh0cmFuc2FjdGlvbik7XG4gIH07XG5cbiAgaWYgKHRyeCkge1xuICAgIGZvciAoY29uc3QgY2h1bmsgb2YgY2h1bmtzKSB7XG4gICAgICBhd2FpdCBleGVjdXRlVXBkYXRlKGNodW5rLCB0cngpO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBhd2FpdCBrbmV4LnRyYW5zYWN0aW9uKGFzeW5jIChuZXdUcngpID0+IHtcbiAgICAgIGZvciAoY29uc3QgY2h1bmsgb2YgY2h1bmtzKSB7XG4gICAgICAgIGF3YWl0IGV4ZWN1dGVVcGRhdGUoY2h1bmssIG5ld1RyeCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cbn1cblxuLyoqXG4gKiBHZW5lcmF0ZSBhIHNldCBvZiB1bmlxdWUga2V5cyBpbiBhIGRhdGEgYXJyYXlcbiAqXG4gKiBFeGFtcGxlOlxuICogWyB7IGE6IDEsIGI6IDIgfSwgeyBhOiAzLCBjOiA0IH0gXSA9PiBTZXQoWyBcImFcIiwgXCJiXCIsIFwiY1wiIF0pXG4gKiBAcGFyYW0gZGF0YVxuICovXG5mdW5jdGlvbiBnZW5lcmF0ZUtleVNldEZyb21EYXRhKGRhdGE6IFJlY29yZDxzdHJpbmcsIGFueT5bXSkge1xuICBjb25zdCBrZXlTZXQ6IFNldDxzdHJpbmc+ID0gbmV3IFNldCgpO1xuICBmb3IgKGNvbnN0IHJvdyBvZiBkYXRhKSB7XG4gICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMocm93KSkge1xuICAgICAga2V5U2V0LmFkZChrZXkpO1xuICAgIH1cbiAgfVxuICByZXR1cm4ga2V5U2V0O1xufVxuXG5mdW5jdGlvbiBnZW5lcmF0ZUJhdGNoVXBkYXRlU1FMPElkIGV4dGVuZHMgc3RyaW5nPihcbiAgZGI6IEtuZXgsXG4gIHRhYmxlTmFtZTogc3RyaW5nLFxuICBkYXRhOiBSZWNvcmQ8c3RyaW5nLCBhbnk+W10sXG4gIGlkZW50aWZpZXJzOiBJZFtdXG4pIHtcbiAgY29uc3Qga2V5U2V0ID0gZ2VuZXJhdGVLZXlTZXRGcm9tRGF0YShkYXRhKTtcbiAgY29uc3QgYmluZGluZ3MgPSBbXTtcblxuICBjb25zdCBpbnZhbGlkSWRlbnRpZmllcnMgPSBpZGVudGlmaWVycy5maWx0ZXIoKGlkKSA9PiAha2V5U2V0LmhhcyhpZCkpO1xuICBpZiAoaW52YWxpZElkZW50aWZpZXJzLmxlbmd0aCA+IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgSW52YWxpZCBpZGVudGlmaWVyczogJHtpbnZhbGlkSWRlbnRpZmllcnMuam9pbihcIiwgXCIpfS4gSWRlbnRpZmllcnMgbXVzdCBleGlzdCBpbiB0aGUgZGF0YWBcbiAgICApO1xuICB9XG5cbiAgY29uc3QgY2FzZXMgPSBbXTtcbiAgZm9yIChjb25zdCBrZXkgb2Yga2V5U2V0KSB7XG4gICAgaWYgKGlkZW50aWZpZXJzLmluY2x1ZGVzKGtleSBhcyBJZCkpIGNvbnRpbnVlO1xuXG4gICAgY29uc3Qgcm93cyA9IFtdO1xuICAgIGZvciAoY29uc3Qgcm93IG9mIGRhdGEpIHtcbiAgICAgIGlmIChPYmplY3QuaGFzT3duUHJvcGVydHkuY2FsbChyb3csIGtleSkpIHtcbiAgICAgICAgY29uc3Qgd2hlcmVDbGF1c2UgPSBpZGVudGlmaWVyc1xuICAgICAgICAgIC5tYXAoKGlkKSA9PiBgXFxgJHtpZH1cXGAgPSA/YClcbiAgICAgICAgICAuam9pbihcIiBBTkQgXCIpO1xuICAgICAgICByb3dzLnB1c2goYFdIRU4gKCR7d2hlcmVDbGF1c2V9KSBUSEVOID9gKTtcbiAgICAgICAgYmluZGluZ3MucHVzaCguLi5pZGVudGlmaWVycy5tYXAoKGkpID0+IHJvd1tpXSksIHJvd1trZXldKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCB3aGVuVGhlbiA9IHJvd3Muam9pbihcIiBcIik7XG4gICAgY2FzZXMucHVzaChgXFxgJHtrZXl9XFxgID0gQ0FTRSAke3doZW5UaGVufSBFTFNFIFxcYCR7a2V5fVxcYCBFTkRgKTtcbiAgfVxuXG4gIGNvbnN0IHdoZXJlSW5DbGF1c2VzID0gaWRlbnRpZmllcnNcbiAgICAubWFwKChjb2wpID0+IGAke2NvbH0gSU4gKCR7ZGF0YS5tYXAoKCkgPT4gXCI/XCIpLmpvaW4oXCIsIFwiKX0pYClcbiAgICAuam9pbihcIiBBTkQgXCIpO1xuXG4gIGNvbnN0IHdoZXJlSW5CaW5kaW5ncyA9IGlkZW50aWZpZXJzLmZsYXRNYXAoKGNvbCkgPT5cbiAgICBkYXRhLm1hcCgocm93KSA9PiByb3dbY29sXSlcbiAgKTtcblxuICBjb25zdCBzcWwgPSBkYi5yYXcoXG4gICAgYFVQREFURSBcXGAke3RhYmxlTmFtZX1cXGAgU0VUICR7Y2FzZXMuam9pbihcIiwgXCIpfSBXSEVSRSAke3doZXJlSW5DbGF1c2VzfWAsXG4gICAgWy4uLmJpbmRpbmdzLCAuLi53aGVyZUluQmluZGluZ3NdXG4gICk7XG5cbiAgcmV0dXJuIHNxbC50b1F1ZXJ5KCk7XG59XG4iXSwibmFtZXMiOlsiYmF0Y2hVcGRhdGUiLCJrbmV4IiwidGFibGVOYW1lIiwiaWRzIiwicm93cyIsImNodW5rU2l6ZSIsInRyeCIsImNodW5rcyIsImkiLCJsZW5ndGgiLCJwdXNoIiwic2xpY2UiLCJleGVjdXRlVXBkYXRlIiwiY2h1bmsiLCJ0cmFuc2FjdGlvbiIsInNxbCIsImdlbmVyYXRlQmF0Y2hVcGRhdGVTUUwiLCJyYXciLCJ0cmFuc2FjdGluZyIsIm5ld1RyeCIsImdlbmVyYXRlS2V5U2V0RnJvbURhdGEiLCJkYXRhIiwia2V5U2V0IiwiU2V0Iiwicm93Iiwia2V5IiwiT2JqZWN0Iiwia2V5cyIsImFkZCIsImRiIiwiaWRlbnRpZmllcnMiLCJiaW5kaW5ncyIsImludmFsaWRJZGVudGlmaWVycyIsImZpbHRlciIsImlkIiwiaGFzIiwiRXJyb3IiLCJqb2luIiwiY2FzZXMiLCJpbmNsdWRlcyIsImhhc093blByb3BlcnR5IiwiY2FsbCIsIndoZXJlQ2xhdXNlIiwibWFwIiwid2hlblRoZW4iLCJ3aGVyZUluQ2xhdXNlcyIsImNvbCIsIndoZXJlSW5CaW5kaW5ncyIsImZsYXRNYXAiLCJ0b1F1ZXJ5Il0sIm1hcHBpbmdzIjoiQUFBQTs7O0FBR0EsR0FRQTs7Ozs7Ozs7Q0FRQyxHQUNELE9BQU8sZUFBZUEsWUFDcEJDLElBQVUsRUFDVkMsU0FBaUIsRUFDakJDLEdBQVMsRUFDVEMsSUFBcUIsRUFDckJDLFlBQVksRUFBRSxFQUNkQyxNQUErQixJQUFJO0lBRW5DLE1BQU1DLFNBQTRCLEVBQUU7SUFDcEMsSUFBSyxJQUFJQyxJQUFJLEdBQUdBLElBQUlKLEtBQUtLLE1BQU0sRUFBRUQsS0FBS0gsVUFBVztRQUMvQ0UsT0FBT0csSUFBSSxDQUFDTixLQUFLTyxLQUFLLENBQUNILEdBQUdBLElBQUlIO0lBQ2hDO0lBRUEsTUFBTU8sZ0JBQWdCLE9BQ3BCQyxPQUNBQztRQUVBLE1BQU1DLE1BQU1DLHVCQUF1QmYsTUFBTUMsV0FBV1csT0FBT1Y7UUFDM0QsT0FBT0YsS0FBS2dCLEdBQUcsQ0FBQ0YsS0FBS0csV0FBVyxDQUFDSjtJQUNuQztJQUVBLElBQUlSLEtBQUs7UUFDUCxLQUFLLE1BQU1PLFNBQVNOLE9BQVE7WUFDMUIsTUFBTUssY0FBY0MsT0FBT1A7UUFDN0I7SUFDRixPQUFPO1FBQ0wsTUFBTUwsS0FBS2EsV0FBVyxDQUFDLE9BQU9LO1lBQzVCLEtBQUssTUFBTU4sU0FBU04sT0FBUTtnQkFDMUIsTUFBTUssY0FBY0MsT0FBT007WUFDN0I7UUFDRjtJQUNGO0FBQ0Y7QUFFQTs7Ozs7O0NBTUMsR0FDRCxTQUFTQyx1QkFBdUJDLElBQTJCO0lBQ3pELE1BQU1DLFNBQXNCLElBQUlDO0lBQ2hDLEtBQUssTUFBTUMsT0FBT0gsS0FBTTtRQUN0QixLQUFLLE1BQU1JLE9BQU9DLE9BQU9DLElBQUksQ0FBQ0gsS0FBTTtZQUNsQ0YsT0FBT00sR0FBRyxDQUFDSDtRQUNiO0lBQ0Y7SUFDQSxPQUFPSDtBQUNUO0FBRUEsU0FBU04sdUJBQ1BhLEVBQVEsRUFDUjNCLFNBQWlCLEVBQ2pCbUIsSUFBMkIsRUFDM0JTLFdBQWlCO0lBRWpCLE1BQU1SLFNBQVNGLHVCQUF1QkM7SUFDdEMsTUFBTVUsV0FBVyxFQUFFO0lBRW5CLE1BQU1DLHFCQUFxQkYsWUFBWUcsTUFBTSxDQUFDLENBQUNDLEtBQU8sQ0FBQ1osT0FBT2EsR0FBRyxDQUFDRDtJQUNsRSxJQUFJRixtQkFBbUJ2QixNQUFNLEdBQUcsR0FBRztRQUNqQyxNQUFNLElBQUkyQixNQUNSLENBQUMscUJBQXFCLEVBQUVKLG1CQUFtQkssSUFBSSxDQUFDLE1BQU0sb0NBQW9DLENBQUM7SUFFL0Y7SUFFQSxNQUFNQyxRQUFRLEVBQUU7SUFDaEIsS0FBSyxNQUFNYixPQUFPSCxPQUFRO1FBQ3hCLElBQUlRLFlBQVlTLFFBQVEsQ0FBQ2QsTUFBWTtRQUVyQyxNQUFNckIsT0FBTyxFQUFFO1FBQ2YsS0FBSyxNQUFNb0IsT0FBT0gsS0FBTTtZQUN0QixJQUFJSyxPQUFPYyxjQUFjLENBQUNDLElBQUksQ0FBQ2pCLEtBQUtDLE1BQU07Z0JBQ3hDLE1BQU1pQixjQUFjWixZQUNqQmEsR0FBRyxDQUFDLENBQUNULEtBQU8sQ0FBQyxFQUFFLEVBQUVBLEdBQUcsTUFBTSxDQUFDLEVBQzNCRyxJQUFJLENBQUM7Z0JBQ1JqQyxLQUFLTSxJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUVnQyxZQUFZLFFBQVEsQ0FBQztnQkFDeENYLFNBQVNyQixJQUFJLElBQUlvQixZQUFZYSxHQUFHLENBQUMsQ0FBQ25DLElBQU1nQixHQUFHLENBQUNoQixFQUFFLEdBQUdnQixHQUFHLENBQUNDLElBQUk7WUFDM0Q7UUFDRjtRQUVBLE1BQU1tQixXQUFXeEMsS0FBS2lDLElBQUksQ0FBQztRQUMzQkMsTUFBTTVCLElBQUksQ0FBQyxDQUFDLEVBQUUsRUFBRWUsSUFBSSxVQUFVLEVBQUVtQixTQUFTLFFBQVEsRUFBRW5CLElBQUksTUFBTSxDQUFDO0lBQ2hFO0lBRUEsTUFBTW9CLGlCQUFpQmYsWUFDcEJhLEdBQUcsQ0FBQyxDQUFDRyxNQUFRLEdBQUdBLElBQUksS0FBSyxFQUFFekIsS0FBS3NCLEdBQUcsQ0FBQyxJQUFNLEtBQUtOLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUM1REEsSUFBSSxDQUFDO0lBRVIsTUFBTVUsa0JBQWtCakIsWUFBWWtCLE9BQU8sQ0FBQyxDQUFDRixNQUMzQ3pCLEtBQUtzQixHQUFHLENBQUMsQ0FBQ25CLE1BQVFBLEdBQUcsQ0FBQ3NCLElBQUk7SUFHNUIsTUFBTS9CLE1BQU1jLEdBQUdaLEdBQUcsQ0FDaEIsQ0FBQyxTQUFTLEVBQUVmLFVBQVUsT0FBTyxFQUFFb0MsTUFBTUQsSUFBSSxDQUFDLE1BQU0sT0FBTyxFQUFFUSxnQkFBZ0IsRUFDekU7V0FBSWQ7V0FBYWdCO0tBQWdCO0lBR25DLE9BQU9oQyxJQUFJa0MsT0FBTztBQUNwQiJ9
|
|
@@ -1,2 +1,247 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:true});function _export(target,all){for(var name in all)Object.defineProperty(target,name,{enumerable:true,get:Object.getOwnPropertyDescriptor(all,name).get})}_export(exports,{get BaseModel(){return BaseModel},get BaseModelClass(){return BaseModelClass}});var _luxon=require("luxon");var _lodash=require("lodash");var _db=require("./db");var _types=require("../types/types");var _inflection=/*#__PURE__*/_interop_require_default(require("inflection"));var _chalk=/*#__PURE__*/_interop_require_default(require("chalk"));var _upsertbuilder=require("./upsert-builder");var _nodesqlparser=/*#__PURE__*/_interop_require_default(require("node-sql-parser"));var _sqlparser=require("../utils/sql-parser");var _puriwrapper=require("./puri-wrapper");function _array_like_to_array(arr,len){if(len==null||len>arr.length)len=arr.length;for(var i=0,arr2=new Array(len);i<len;i++)arr2[i]=arr[i];return arr2}function _array_without_holes(arr){if(Array.isArray(arr))return _array_like_to_array(arr)}function asyncGeneratorStep(gen,resolve,reject,_next,_throw,key,arg){try{var info=gen[key](arg);var value=info.value}catch(error){reject(error);return}if(info.done){resolve(value)}else{Promise.resolve(value).then(_next,_throw)}}function _async_to_generator(fn){return function(){var self=this,args=arguments;return new Promise(function(resolve,reject){var gen=fn.apply(self,args);function _next(value){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"next",value)}function _throw(err){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"throw",err)}_next(undefined)})}}function _class_call_check(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function")}}function _defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor)}}function _create_class(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);return Constructor}function _define_property(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true})}else{obj[key]=value}return obj}function _interop_require_default(obj){return obj&&obj.__esModule?obj:{default:obj}}function _iterable_to_array(iter){if(typeof Symbol!=="undefined"&&iter[Symbol.iterator]!=null||iter["@@iterator"]!=null)return Array.from(iter)}function _non_iterable_spread(){throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _to_consumable_array(arr){return _array_without_holes(arr)||_iterable_to_array(arr)||_unsupported_iterable_to_array(arr)||_non_iterable_spread()}function _unsupported_iterable_to_array(o,minLen){if(!o)return;if(typeof o==="string")return _array_like_to_array(o,minLen);var n=Object.prototype.toString.call(o).slice(8,-1);if(n==="Object"&&o.constructor)n=o.constructor.name;if(n==="Map"||n==="Set")return Array.from(n);if(n==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return _array_like_to_array(o,minLen)}function _ts_generator(thisArg,body){var f,y,t,_={label:0,sent:function(){if(t[0]&1)throw t[1];return t[1]},trys:[],ops:[]},g=Object.create((typeof Iterator==="function"?Iterator:Object).prototype);return g.next=verb(0),g["throw"]=verb(1),g["return"]=verb(2),typeof Symbol==="function"&&(g[Symbol.iterator]=function(){return this}),g;function verb(n){return function(v){return step([n,v])}}function step(op){if(f)throw new TypeError("Generator is already executing.");while(g&&(g=0,op[0]&&(_=0)),_)try{if(f=1,y&&(t=op[0]&2?y["return"]:op[0]?y["throw"]||((t=y["return"])&&t.call(y),0):y.next)&&!(t=t.call(y,op[1])).done)return t;if(y=0,t)op=[op[0]&2,t.value];switch(op[0]){case 0:case 1:t=op;break;case 4:_.label++;return{value:op[1],done:false};case 5:_.label++;y=op[1];op=[0];continue;case 7:op=_.ops.pop();_.trys.pop();continue;default:if(!(t=_.trys,t=t.length>0&&t[t.length-1])&&(op[0]===6||op[0]===2)){_=0;continue}if(op[0]===3&&(!t||op[1]>t[0]&&op[1]<t[3])){_.label=op[1];break}if(op[0]===6&&_.label<t[1]){_.label=t[1];t=op;break}if(t&&_.label<t[2]){_.label=t[2];_.ops.push(op);break}if(t[2])_.ops.pop();_.trys.pop();continue}op=body.call(thisArg,_)}catch(e){op=[6,e];y=0}finally{f=t=0}if(op[0]&5)throw op[1];return{value:op[0]?op[1]:void 0,done:true}}}function _ts_values(o){var s=typeof Symbol==="function"&&Symbol.iterator,m=s&&o[s],i=0;if(m)return m.call(o);if(o&&typeof o.length==="number")return{next:function(){if(o&&i>=o.length)o=void 0;return{value:o&&o[i++],done:!o}}};throw new TypeError(s?"Object is not iterable.":"Symbol.iterator is not defined.")}var BaseModelClass=/*#__PURE__*/function(){"use strict";function BaseModelClass(){_class_call_check(this,BaseModelClass);_define_property(this,"modelName","Unknown")}_create_class(BaseModelClass,[{key:"getDB",value:function getDB(which){return _db.DB.getDB(which)}},{key:"getPuri",value:function getPuri(which){var trx=_db.DB.getTransactionContext().getTransaction(which);if(trx){return trx}var db=this.getDB(which);return new _puriwrapper.PuriWrapper(db,this.getUpsertBuilder())}},{key:"destroy",value:function destroy(){return _async_to_generator(function(){return _ts_generator(this,function(_state){return[2,_db.DB.destroy()]})})()}},{key:"myNow",value:function myNow(timestamp){var dt=timestamp===undefined?_luxon.DateTime.local():_luxon.DateTime.fromSeconds(timestamp);return dt.toFormat("yyyy-MM-dd HH:mm:ss")}},{key:"getInsertedIds",value:function getInsertedIds(wdb,rows,tableName,unqKeyFields){var chunkSize=arguments.length>4&&arguments[4]!==void 0?arguments[4]:500;return _async_to_generator(function(){var unqKeys,whereInField,selectField,chunks,resultIds,_iteratorNormalCompletion,_didIteratorError,_iteratorError,_iterator,_step,_$chunk,dbRows,err;return _ts_generator(this,function(_state){switch(_state.label){case 0:if(!wdb){wdb=this.getDB("w")}if(unqKeyFields.length>1){whereInField=wdb.raw("CONCAT_WS('_', '".concat(unqKeyFields.join(","),"')"));selectField="".concat(whereInField," as tmpUid");unqKeys=rows.map(function(row){return unqKeyFields.map(function(field){return row[field]}).join("_")})}else{whereInField=unqKeyFields[0];selectField=unqKeyFields[0];unqKeys=rows.map(function(row){return row[unqKeyFields[0]]})}chunks=(0,_lodash.chunk)(unqKeys,chunkSize);resultIds=[];_iteratorNormalCompletion=true,_didIteratorError=false,_iteratorError=undefined;_state.label=1;case 1:_state.trys.push([1,6,7,8]);_iterator=chunks[Symbol.iterator]();_state.label=2;case 2:if(!!(_iteratorNormalCompletion=(_step=_iterator.next()).done))return[3,5];_$chunk=_step.value;return[4,wdb(tableName).select("id",wdb.raw(selectField)).whereIn(whereInField,_$chunk)];case 3:dbRows=_state.sent();resultIds=resultIds.concat(dbRows.map(function(dbRow){return parseInt(dbRow.id)}));_state.label=4;case 4:_iteratorNormalCompletion=true;return[3,2];case 5:return[3,8];case 6:err=_state.sent();_didIteratorError=true;_iteratorError=err;return[3,8];case 7:try{if(!_iteratorNormalCompletion&&_iterator.return!=null){_iterator.return()}}finally{if(_didIteratorError){throw _iteratorError}}return[7];case 8:return[2,resultIds]}})}).call(this)}},{key:"useLoaders",value:function useLoaders(db,rows,loaders){return _async_to_generator(function(){var _this,_iteratorNormalCompletion,_didIteratorError,_iteratorError,_this1,_loop,_iterator,_step,err;return _ts_generator(this,function(_state){switch(_state.label){case 0:_this=this;if(loaders.length===0){return[2,rows]}_iteratorNormalCompletion=true,_didIteratorError=false,_iteratorError=undefined;_state.label=1;case 1:_state.trys.push([1,6,7,8]);_loop=function(){var loader,subQ,subRows,toCol,fromIds,idColumn,idColumn1,subRowGroups;return _ts_generator(this,function(_state){switch(_state.label){case 0:loader=_step.value;subQ=void 0;subRows=void 0;toCol=void 0;fromIds=rows.map(function(row){return row[loader.manyJoin.idField]});if(loader.manyJoin.through===undefined){idColumn="".concat(loader.manyJoin.toTable,".").concat(loader.manyJoin.toCol);subQ=db(loader.manyJoin.toTable).whereIn(idColumn,fromIds).select(_to_consumable_array(loader.select).concat([idColumn]));loader.oneJoins.map(function(join){if(join.join=="inner"){subQ.innerJoin("".concat(join.table," as ").concat(join.as),_this.getJoinClause(db,join))}else if(join.join=="outer"){subQ.leftOuterJoin("".concat(join.table," as ").concat(join.as),_this.getJoinClause(db,join))}});toCol=loader.manyJoin.toCol}else{idColumn1="".concat(loader.manyJoin.through.table,".").concat(loader.manyJoin.through.fromCol);subQ=db(loader.manyJoin.through.table).join(loader.manyJoin.toTable,"".concat(loader.manyJoin.through.table,".").concat(loader.manyJoin.through.toCol),"".concat(loader.manyJoin.toTable,".").concat(loader.manyJoin.toCol)).whereIn(idColumn1,fromIds).select((0,_lodash.uniq)(_to_consumable_array(loader.select).concat([idColumn1])));loader.oneJoins.map(function(join){if(join.join=="inner"){subQ.innerJoin("".concat(join.table," as ").concat(join.as),_this.getJoinClause(db,join))}else if(join.join=="outer"){subQ.leftOuterJoin("".concat(join.table," as ").concat(join.as),_this.getJoinClause(db,join))}});toCol=loader.manyJoin.through.fromCol}return[4,subQ];case 1:subRows=_state.sent();if(!loader.loaders)return[3,3];return[4,_this1.useLoaders(db,subRows,loader.loaders)];case 2:subRows=_state.sent();_state.label=3;case 3:subRowGroups=(0,_lodash.groupBy)(subRows,toCol);rows=rows.map(function(row){var _subRowGroups_row_loader_manyJoin_idField;row[loader.as]=((_subRowGroups_row_loader_manyJoin_idField=subRowGroups[row[loader.manyJoin.idField]])!==null&&_subRowGroups_row_loader_manyJoin_idField!==void 0?_subRowGroups_row_loader_manyJoin_idField:[]).map(function(r){return(0,_lodash.omit)(r,toCol)});return row});return[2]}})};_iterator=loaders[Symbol.iterator]();_state.label=2;case 2:if(!!(_iteratorNormalCompletion=(_step=_iterator.next()).done))return[3,5];_this1=this;return[5,_ts_values(_loop())];case 3:_state.sent();_state.label=4;case 4:_iteratorNormalCompletion=true;return[3,2];case 5:return[3,8];case 6:err=_state.sent();_didIteratorError=true;_iteratorError=err;return[3,8];case 7:try{if(!_iteratorNormalCompletion&&_iterator.return!=null){_iterator.return()}}finally{if(_didIteratorError){throw _iteratorError}}return[7];case 8:return[2,rows]}})}).call(this)}},{key:"hydrate",value:function hydrate(rows){var _this=this;return rows.map(function(row){var nestedKeys=Object.keys(row).filter(function(key){return key.includes("__")});var groups=(0,_lodash.groupBy)(nestedKeys,function(key){return key.split("__")[0]});var nullKeys=Object.keys(groups).filter(function(key){return groups[key].length>1&&groups[key].every(function(field){return row[field]===null||Array.isArray(row[field])&&row[field].length===0})});var hydrated=Object.keys(row).reduce(function(r,field){if(!field.includes("__")){if(Array.isArray(row[field])&&(0,_lodash.isObject)(row[field][0])){r[field]=_this.hydrate(row[field]);return r}else{r[field]=row[field];return r}}var parts=field.split("__");var objPath=parts[0]+parts.slice(1).map(function(part){return"[".concat(part,"]")}).join("");(0,_lodash.set)(r,objPath,row[field]&&Array.isArray(row[field])&&(0,_lodash.isObject)(row[field][0])?_this.hydrate(row[field]):row[field]);return r},{});nullKeys.map(function(nullKey){return hydrated[nullKey]=null});return hydrated})}},{key:"runSubsetQuery",value:function runSubsetQuery(_0){return _async_to_generator(function(param){var _this,params,baseTable,subset,subsetQuery,build,afterBuild,debug,_db,optimizeCountQuery,db,_params_queryMode,queryMode,select,virtual,joins,loaders,qb,applyJoinClause,total,rows;return _ts_generator(this,function(_state){switch(_state.label){case 0:_this=this;params=param.params,baseTable=param.baseTable,subset=param.subset,subsetQuery=param.subsetQuery,build=param.build,afterBuild=param.afterBuild,debug=param.debug,_db=param.db,optimizeCountQuery=param.optimizeCountQuery;db=_db!==null&&_db!==void 0?_db:this.getDB(subset.startsWith("A")?"w":"r");baseTable=baseTable!==null&&baseTable!==void 0?baseTable:_inflection.default.pluralize(_inflection.default.underscore(this.modelName));queryMode=(_params_queryMode=params.queryMode)!==null&&_params_queryMode!==void 0?_params_queryMode:params.id!==undefined?"list":"both";select=subsetQuery.select,virtual=subsetQuery.virtual,joins=subsetQuery.joins,loaders=subsetQuery.loaders;qb=build({qb:db.from(baseTable),db:db,select:select,joins:joins,virtual:virtual});applyJoinClause=function(qb,joins){joins.map(function(join){if(join.join=="inner"){qb.innerJoin("".concat(join.table," as ").concat(join.as),_this.getJoinClause(db,join))}else if(join.join=="outer"){qb.leftOuterJoin("".concat(join.table," as ").concat(join.as),_this.getJoinClause(db,join))}})};return[4,function(){return _async_to_generator(function(){var clonedQb,parser,parsedQuery,tables,needToJoin,_afterBuild,processedQb,parsedQuery1,q,countQuery,countRow,_countRow_total;return _ts_generator(this,function(_state){switch(_state.label){case 0:if(queryMode==="list"){return[2,undefined]}clonedQb=qb.clone().clear("order").clear("offset").clear("limit");parser=new _nodesqlparser.default.Parser;if(optimizeCountQuery){parsedQuery=parser.astify(clonedQb.toQuery());tables=(0,_sqlparser.getTableNamesFromWhere)(parsedQuery);needToJoin=(0,_lodash.uniq)(tables.flatMap(function(table){return table.split("__").map(function(t){return _inflection.default.pluralize(t)})}));applyJoinClause(clonedQb,joins.filter(function(j){return needToJoin.includes(j.table)}))}else{applyJoinClause(clonedQb,joins)}processedQb=(_afterBuild=afterBuild===null||afterBuild===void 0?void 0:afterBuild({qb:clonedQb,db:db,select:select,joins:joins,virtual:virtual}))!==null&&_afterBuild!==void 0?_afterBuild:clonedQb;parsedQuery1=parser.astify(processedQb.toQuery());q=Array.isArray(parsedQuery1)?parsedQuery1[0]:parsedQuery1;if(q.type!=="select"){throw new Error("Invalid query")}countQuery=q.distinct!==null?clonedQb.clear("select").select(db.raw("COUNT(DISTINCT `".concat((0,_sqlparser.getTableName)(q.columns[0].expr),"`.`").concat(q.columns[0].expr.column,"`) as total"))).first():clonedQb.clear("select").count("*",{as:"total"}).first();return[4,countQuery];case 1:countRow=_state.sent();if(debug===true||debug==="count"){console.debug("DEBUG: count query",_chalk.default.blue(countQuery.toQuery().toString()))}return[2,(_countRow_total=countRow===null||countRow===void 0?void 0:countRow.total)!==null&&_countRow_total!==void 0?_countRow_total:0]}})})()}()];case 1:total=_state.sent();return[4,function(){return _async_to_generator(function(){var clonedQb,_afterBuild,listQuery,rows;return _ts_generator(this,function(_state){switch(_state.label){case 0:if(queryMode==="count"){return[2,[]]}if(params.num!==0){qb.limit(params.num);qb.offset(params.num*(params.page-1))}clonedQb=qb.clone().select(select);applyJoinClause(clonedQb,joins);listQuery=(_afterBuild=afterBuild===null||afterBuild===void 0?void 0:afterBuild({qb:clonedQb,db:db,select:select,joins:joins,virtual:virtual}))!==null&&_afterBuild!==void 0?_afterBuild:clonedQb;return[4,listQuery];case 1:rows=_state.sent();if(debug===true||debug==="list"){console.debug("DEBUG: list query",_chalk.default.blue(listQuery.toQuery().toString()))}return[4,this.useLoaders(db,rows,loaders)];case 2:rows=_state.sent();rows=this.hydrate(rows);return[2,rows]}})}).call(_this)}()];case 2:rows=_state.sent();return[2,{rows:rows,total:total,subsetQuery:subsetQuery,qb:qb}]}})}).apply(this,arguments)}},{key:"getJoinClause",value:function getJoinClause(db,join){if(!(0,_types.isCustomJoinClause)(join)){return db.raw("".concat(join.from," = ").concat(join.to))}else{return db.raw(join.custom)}}},{key:"getUpsertBuilder",value:function getUpsertBuilder(){return new _upsertbuilder.UpsertBuilder}}]);return BaseModelClass}();var BaseModel=new BaseModelClass;
|
|
2
|
-
|
|
1
|
+
import { DateTime } from "luxon";
|
|
2
|
+
import { chunk, groupBy, isObject, omit, set, uniq } from "lodash-es";
|
|
3
|
+
import { DB } from "./db.js";
|
|
4
|
+
import { isCustomJoinClause } from "../types/types.js";
|
|
5
|
+
import inflection from "inflection";
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
import { UpsertBuilder } from "./upsert-builder.js";
|
|
8
|
+
import SqlParser from "node-sql-parser";
|
|
9
|
+
import { getTableName, getTableNamesFromWhere } from "../utils/sql-parser.js";
|
|
10
|
+
import { PuriWrapper } from "./puri-wrapper.js";
|
|
11
|
+
export class BaseModelClass {
|
|
12
|
+
modelName = "Unknown";
|
|
13
|
+
/* DB 인스턴스 get, destroy */ getDB(which) {
|
|
14
|
+
return DB.getDB(which);
|
|
15
|
+
}
|
|
16
|
+
getPuri(which) {
|
|
17
|
+
// 트랜잭션 컨텍스트에서 트랜잭션 획득
|
|
18
|
+
const trx = DB.getTransactionContext().getTransaction(which);
|
|
19
|
+
if (trx) {
|
|
20
|
+
return trx;
|
|
21
|
+
}
|
|
22
|
+
// 트랜잭션이 없으면 새로운 PuriWrapper 반환
|
|
23
|
+
const db = this.getDB(which);
|
|
24
|
+
return new PuriWrapper(db, this.getUpsertBuilder());
|
|
25
|
+
}
|
|
26
|
+
async destroy() {
|
|
27
|
+
return DB.destroy();
|
|
28
|
+
}
|
|
29
|
+
myNow(timestamp) {
|
|
30
|
+
const dt = timestamp === undefined ? DateTime.local() : DateTime.fromSeconds(timestamp);
|
|
31
|
+
return dt.toFormat("yyyy-MM-dd HH:mm:ss");
|
|
32
|
+
}
|
|
33
|
+
async getInsertedIds(wdb, rows, tableName, unqKeyFields, chunkSize = 500) {
|
|
34
|
+
if (!wdb) {
|
|
35
|
+
wdb = this.getDB("w");
|
|
36
|
+
}
|
|
37
|
+
let unqKeys;
|
|
38
|
+
let whereInField, selectField;
|
|
39
|
+
if (unqKeyFields.length > 1) {
|
|
40
|
+
whereInField = wdb.raw(`CONCAT_WS('_', '${unqKeyFields.join(",")}')`);
|
|
41
|
+
selectField = `${whereInField} as tmpUid`;
|
|
42
|
+
unqKeys = rows.map((row)=>unqKeyFields.map((field)=>row[field]).join("_"));
|
|
43
|
+
} else {
|
|
44
|
+
whereInField = unqKeyFields[0];
|
|
45
|
+
selectField = unqKeyFields[0];
|
|
46
|
+
unqKeys = rows.map((row)=>row[unqKeyFields[0]]);
|
|
47
|
+
}
|
|
48
|
+
const chunks = chunk(unqKeys, chunkSize);
|
|
49
|
+
let resultIds = [];
|
|
50
|
+
for (let chunk of chunks){
|
|
51
|
+
const dbRows = await wdb(tableName).select("id", wdb.raw(selectField)).whereIn(whereInField, chunk);
|
|
52
|
+
resultIds = resultIds.concat(dbRows.map((dbRow)=>parseInt(dbRow.id)));
|
|
53
|
+
}
|
|
54
|
+
return resultIds;
|
|
55
|
+
}
|
|
56
|
+
async useLoaders(db, rows, loaders) {
|
|
57
|
+
if (loaders.length === 0) {
|
|
58
|
+
return rows;
|
|
59
|
+
}
|
|
60
|
+
for (let loader of loaders){
|
|
61
|
+
let subQ;
|
|
62
|
+
let subRows;
|
|
63
|
+
let toCol;
|
|
64
|
+
const fromIds = rows.map((row)=>row[loader.manyJoin.idField]);
|
|
65
|
+
if (loader.manyJoin.through === undefined) {
|
|
66
|
+
// HasMany
|
|
67
|
+
const idColumn = `${loader.manyJoin.toTable}.${loader.manyJoin.toCol}`;
|
|
68
|
+
subQ = db(loader.manyJoin.toTable).whereIn(idColumn, fromIds).select([
|
|
69
|
+
...loader.select,
|
|
70
|
+
idColumn
|
|
71
|
+
]);
|
|
72
|
+
// HasMany에서 OneJoin이 있는 경우
|
|
73
|
+
loader.oneJoins.map((join)=>{
|
|
74
|
+
if (join.join == "inner") {
|
|
75
|
+
subQ.innerJoin(`${join.table} as ${join.as}`, this.getJoinClause(db, join));
|
|
76
|
+
} else if (join.join == "outer") {
|
|
77
|
+
subQ.leftOuterJoin(`${join.table} as ${join.as}`, this.getJoinClause(db, join));
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
toCol = loader.manyJoin.toCol;
|
|
81
|
+
} else {
|
|
82
|
+
// ManyToMany
|
|
83
|
+
const idColumn = `${loader.manyJoin.through.table}.${loader.manyJoin.through.fromCol}`;
|
|
84
|
+
subQ = db(loader.manyJoin.through.table).join(loader.manyJoin.toTable, `${loader.manyJoin.through.table}.${loader.manyJoin.through.toCol}`, `${loader.manyJoin.toTable}.${loader.manyJoin.toCol}`).whereIn(idColumn, fromIds).select(uniq([
|
|
85
|
+
...loader.select,
|
|
86
|
+
idColumn
|
|
87
|
+
]));
|
|
88
|
+
// ManyToMany에서 OneJoin이 있는 경우
|
|
89
|
+
loader.oneJoins.map((join)=>{
|
|
90
|
+
if (join.join == "inner") {
|
|
91
|
+
subQ.innerJoin(`${join.table} as ${join.as}`, this.getJoinClause(db, join));
|
|
92
|
+
} else if (join.join == "outer") {
|
|
93
|
+
subQ.leftOuterJoin(`${join.table} as ${join.as}`, this.getJoinClause(db, join));
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
toCol = loader.manyJoin.through.fromCol;
|
|
97
|
+
}
|
|
98
|
+
subRows = await subQ;
|
|
99
|
+
if (loader.loaders) {
|
|
100
|
+
// 추가 -Many 케이스가 있는 경우 recursion 처리
|
|
101
|
+
subRows = await this.useLoaders(db, subRows, loader.loaders);
|
|
102
|
+
}
|
|
103
|
+
// 불러온 row들을 참조ID 기준으로 분류 배치
|
|
104
|
+
const subRowGroups = groupBy(subRows, toCol);
|
|
105
|
+
rows = rows.map((row)=>{
|
|
106
|
+
row[loader.as] = (subRowGroups[row[loader.manyJoin.idField]] ?? []).map((r)=>omit(r, toCol));
|
|
107
|
+
return row;
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
return rows;
|
|
111
|
+
}
|
|
112
|
+
hydrate(rows) {
|
|
113
|
+
return rows.map((row)=>{
|
|
114
|
+
// nullable relation인 경우 관련된 필드가 전부 null로 생성되는 것 방지하는 코드
|
|
115
|
+
const nestedKeys = Object.keys(row).filter((key)=>key.includes("__"));
|
|
116
|
+
const groups = groupBy(nestedKeys, (key)=>key.split("__")[0]);
|
|
117
|
+
const nullKeys = Object.keys(groups).filter((key)=>groups[key].length > 1 && groups[key].every((field)=>row[field] === null || Array.isArray(row[field]) && row[field].length === 0));
|
|
118
|
+
const hydrated = Object.keys(row).reduce((r, field)=>{
|
|
119
|
+
if (!field.includes("__")) {
|
|
120
|
+
if (Array.isArray(row[field]) && isObject(row[field][0])) {
|
|
121
|
+
r[field] = this.hydrate(row[field]);
|
|
122
|
+
return r;
|
|
123
|
+
} else {
|
|
124
|
+
r[field] = row[field];
|
|
125
|
+
return r;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const parts = field.split("__");
|
|
129
|
+
const objPath = parts[0] + parts.slice(1).map((part)=>`[${part}]`).join("");
|
|
130
|
+
set(r, objPath, row[field] && Array.isArray(row[field]) && isObject(row[field][0]) ? this.hydrate(row[field]) : row[field]);
|
|
131
|
+
return r;
|
|
132
|
+
}, {});
|
|
133
|
+
nullKeys.map((nullKey)=>hydrated[nullKey] = null);
|
|
134
|
+
return hydrated;
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
async runSubsetQuery({ params, baseTable, subset, subsetQuery, build, afterBuild, debug, db: _db, optimizeCountQuery }) {
|
|
138
|
+
const db = _db ?? this.getDB(subset.startsWith("A") ? "w" : "r");
|
|
139
|
+
baseTable = baseTable ?? inflection.pluralize(inflection.underscore(this.modelName));
|
|
140
|
+
const queryMode = params.queryMode ?? (params.id !== undefined ? "list" : "both");
|
|
141
|
+
const { select, virtual, joins, loaders } = subsetQuery;
|
|
142
|
+
const qb = build({
|
|
143
|
+
qb: db.from(baseTable),
|
|
144
|
+
db,
|
|
145
|
+
select,
|
|
146
|
+
joins,
|
|
147
|
+
virtual
|
|
148
|
+
});
|
|
149
|
+
const applyJoinClause = (qb, joins)=>{
|
|
150
|
+
joins.map((join)=>{
|
|
151
|
+
if (join.join == "inner") {
|
|
152
|
+
qb.innerJoin(`${join.table} as ${join.as}`, this.getJoinClause(db, join));
|
|
153
|
+
} else if (join.join == "outer") {
|
|
154
|
+
qb.leftOuterJoin(`${join.table} as ${join.as}`, this.getJoinClause(db, join));
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
};
|
|
158
|
+
// countQuery
|
|
159
|
+
const total = await (async ()=>{
|
|
160
|
+
if (queryMode === "list") {
|
|
161
|
+
return undefined;
|
|
162
|
+
}
|
|
163
|
+
const clonedQb = qb.clone().clear("order").clear("offset").clear("limit");
|
|
164
|
+
const parser = new SqlParser.Parser();
|
|
165
|
+
// optmizeCountQuery가 true인 경우 다른 clause에 영향을 주지 않는 모든 join을 제외함
|
|
166
|
+
if (optimizeCountQuery) {
|
|
167
|
+
const parsedQuery = parser.astify(clonedQb.toQuery());
|
|
168
|
+
const tables = getTableNamesFromWhere(parsedQuery);
|
|
169
|
+
// where절에 사용되는 테이블의 조인을 위해 사용되는 테이블
|
|
170
|
+
const needToJoin = uniq(tables.flatMap((table)=>table.split("__").map((t)=>inflection.pluralize(t))));
|
|
171
|
+
applyJoinClause(clonedQb, joins.filter((j)=>needToJoin.includes(j.table)));
|
|
172
|
+
} else {
|
|
173
|
+
applyJoinClause(clonedQb, joins);
|
|
174
|
+
}
|
|
175
|
+
const processedQb = afterBuild?.({
|
|
176
|
+
qb: clonedQb,
|
|
177
|
+
db,
|
|
178
|
+
select,
|
|
179
|
+
joins,
|
|
180
|
+
virtual
|
|
181
|
+
}) ?? clonedQb;
|
|
182
|
+
const parsedQuery = parser.astify(processedQb.toQuery());
|
|
183
|
+
const q = Array.isArray(parsedQuery) ? parsedQuery[0] : parsedQuery;
|
|
184
|
+
if (q.type !== "select") {
|
|
185
|
+
throw new Error("Invalid query");
|
|
186
|
+
}
|
|
187
|
+
const countQuery = q.distinct !== null ? clonedQb.clear("select").select(db.raw(`COUNT(DISTINCT \`${getTableName(q.columns[0].expr)}\`.\`${q.columns[0].expr.column}\`) as total`)).first() : clonedQb.clear("select").count("*", {
|
|
188
|
+
as: "total"
|
|
189
|
+
}).first();
|
|
190
|
+
const countRow = await countQuery;
|
|
191
|
+
// debug: countQuery
|
|
192
|
+
if (debug === true || debug === "count") {
|
|
193
|
+
console.debug("DEBUG: count query", chalk.blue(countQuery.toQuery().toString()));
|
|
194
|
+
}
|
|
195
|
+
return countRow?.total ?? 0;
|
|
196
|
+
})();
|
|
197
|
+
// listQuery
|
|
198
|
+
const rows = await (async ()=>{
|
|
199
|
+
if (queryMode === "count") {
|
|
200
|
+
return [];
|
|
201
|
+
}
|
|
202
|
+
// limit, offset
|
|
203
|
+
if (params.num !== 0) {
|
|
204
|
+
qb.limit(params.num);
|
|
205
|
+
qb.offset(params.num * (params.page - 1));
|
|
206
|
+
}
|
|
207
|
+
// select, rows
|
|
208
|
+
const clonedQb = qb.clone().select(select);
|
|
209
|
+
// join
|
|
210
|
+
applyJoinClause(clonedQb, joins);
|
|
211
|
+
const listQuery = afterBuild?.({
|
|
212
|
+
qb: clonedQb,
|
|
213
|
+
db,
|
|
214
|
+
select,
|
|
215
|
+
joins,
|
|
216
|
+
virtual
|
|
217
|
+
}) ?? clonedQb;
|
|
218
|
+
let rows = await listQuery;
|
|
219
|
+
// debug: listQuery
|
|
220
|
+
if (debug === true || debug === "list") {
|
|
221
|
+
console.debug("DEBUG: list query", chalk.blue(listQuery.toQuery().toString()));
|
|
222
|
+
}
|
|
223
|
+
rows = await this.useLoaders(db, rows, loaders);
|
|
224
|
+
rows = this.hydrate(rows);
|
|
225
|
+
return rows;
|
|
226
|
+
})();
|
|
227
|
+
return {
|
|
228
|
+
rows,
|
|
229
|
+
total,
|
|
230
|
+
subsetQuery,
|
|
231
|
+
qb
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
getJoinClause(db, join) {
|
|
235
|
+
if (!isCustomJoinClause(join)) {
|
|
236
|
+
return db.raw(`${join.from} = ${join.to}`);
|
|
237
|
+
} else {
|
|
238
|
+
return db.raw(join.custom);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
getUpsertBuilder() {
|
|
242
|
+
return new UpsertBuilder();
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
export const BaseModel = new BaseModelClass();
|
|
246
|
+
|
|
247
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kYXRhYmFzZS9iYXNlLW1vZGVsLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERhdGVUaW1lIH0gZnJvbSBcImx1eG9uXCI7XG5pbXBvcnQgeyBLbmV4IH0gZnJvbSBcImtuZXhcIjtcbmltcG9ydCB7IGNodW5rLCBncm91cEJ5LCBpc09iamVjdCwgb21pdCwgc2V0LCB1bmlxIH0gZnJvbSBcImxvZGFzaC1lc1wiO1xuaW1wb3J0IHsgREJQcmVzZXQsIERCIH0gZnJvbSBcIi4vZGJcIjtcbmltcG9ydCB7IGlzQ3VzdG9tSm9pbkNsYXVzZSwgdHlwZSBTdWJzZXRRdWVyeSB9IGZyb20gXCIuLi90eXBlcy90eXBlc1wiO1xuaW1wb3J0IHR5cGUgeyBCYXNlTGlzdFBhcmFtcyB9IGZyb20gXCIuLi91dGlscy9tb2RlbFwiO1xuaW1wb3J0IGluZmxlY3Rpb24gZnJvbSBcImluZmxlY3Rpb25cIjtcbmltcG9ydCBjaGFsayBmcm9tIFwiY2hhbGtcIjtcbmltcG9ydCB7IFVwc2VydEJ1aWxkZXIgfSBmcm9tIFwiLi91cHNlcnQtYnVpbGRlclwiO1xuaW1wb3J0IFNxbFBhcnNlciBmcm9tIFwibm9kZS1zcWwtcGFyc2VyXCI7XG5pbXBvcnQgeyBnZXRUYWJsZU5hbWUsIGdldFRhYmxlTmFtZXNGcm9tV2hlcmUgfSBmcm9tIFwiLi4vdXRpbHMvc3FsLXBhcnNlclwiO1xuaW1wb3J0IHsgUHVyaVdyYXBwZXIgfSBmcm9tIFwiLi9wdXJpLXdyYXBwZXJcIjtcblxuZXhwb3J0IGNsYXNzIEJhc2VNb2RlbENsYXNzIHtcbiAgcHVibGljIG1vZGVsTmFtZTogc3RyaW5nID0gXCJVbmtub3duXCI7XG5cbiAgLyogREIg7J247Iqk7YS07IqkIGdldCwgZGVzdHJveSAqL1xuICBnZXREQih3aGljaDogREJQcmVzZXQpOiBLbmV4IHtcbiAgICByZXR1cm4gREIuZ2V0REIod2hpY2gpO1xuICB9XG5cbiAgZ2V0UHVyaSh3aGljaDogREJQcmVzZXQpOiBQdXJpV3JhcHBlciB7XG4gICAgLy8g7Yq4656c7J6t7IWYIOy7qO2FjeyKpO2KuOyXkOyEnCDtirjrnpzsnq3shZgg7ZqN65OdXG4gICAgY29uc3QgdHJ4ID0gREIuZ2V0VHJhbnNhY3Rpb25Db250ZXh0KCkuZ2V0VHJhbnNhY3Rpb24od2hpY2gpO1xuICAgIGlmICh0cngpIHtcbiAgICAgIHJldHVybiB0cng7XG4gICAgfVxuXG4gICAgLy8g7Yq4656c7J6t7IWY7J20IOyXhuycvOuptCDsg4jroZzsmrQgUHVyaVdyYXBwZXIg67CY7ZmYXG4gICAgY29uc3QgZGIgPSB0aGlzLmdldERCKHdoaWNoKTtcbiAgICByZXR1cm4gbmV3IFB1cmlXcmFwcGVyKGRiLCB0aGlzLmdldFVwc2VydEJ1aWxkZXIoKSk7XG4gIH1cblxuICBhc3luYyBkZXN0cm95KCkge1xuICAgIHJldHVybiBEQi5kZXN0cm95KCk7XG4gIH1cblxuICBteU5vdyh0aW1lc3RhbXA/OiBudW1iZXIpOiBzdHJpbmcge1xuICAgIGNvbnN0IGR0OiBEYXRlVGltZSA9XG4gICAgICB0aW1lc3RhbXAgPT09IHVuZGVmaW5lZFxuICAgICAgICA/IERhdGVUaW1lLmxvY2FsKClcbiAgICAgICAgOiBEYXRlVGltZS5mcm9tU2Vjb25kcyh0aW1lc3RhbXApO1xuICAgIHJldHVybiBkdC50b0Zvcm1hdChcInl5eXktTU0tZGQgSEg6bW06c3NcIik7XG4gIH1cblxuICBhc3luYyBnZXRJbnNlcnRlZElkcyhcbiAgICB3ZGI6IEtuZXgsXG4gICAgcm93czogYW55W10sXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgdW5xS2V5RmllbGRzOiBzdHJpbmdbXSxcbiAgICBjaHVua1NpemU6IG51bWJlciA9IDUwMFxuICApIHtcbiAgICBpZiAoIXdkYikge1xuICAgICAgd2RiID0gdGhpcy5nZXREQihcIndcIik7XG4gICAgfVxuXG4gICAgbGV0IHVucUtleXM6IHN0cmluZ1tdO1xuICAgIGxldCB3aGVyZUluRmllbGQ6IGFueSwgc2VsZWN0RmllbGQ6IHN0cmluZztcbiAgICBpZiAodW5xS2V5RmllbGRzLmxlbmd0aCA+IDEpIHtcbiAgICAgIHdoZXJlSW5GaWVsZCA9IHdkYi5yYXcoYENPTkNBVF9XUygnXycsICcke3VucUtleUZpZWxkcy5qb2luKFwiLFwiKX0nKWApO1xuICAgICAgc2VsZWN0RmllbGQgPSBgJHt3aGVyZUluRmllbGR9IGFzIHRtcFVpZGA7XG4gICAgICB1bnFLZXlzID0gcm93cy5tYXAoKHJvdykgPT5cbiAgICAgICAgdW5xS2V5RmllbGRzLm1hcCgoZmllbGQpID0+IHJvd1tmaWVsZF0pLmpvaW4oXCJfXCIpXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICB3aGVyZUluRmllbGQgPSB1bnFLZXlGaWVsZHNbMF07XG4gICAgICBzZWxlY3RGaWVsZCA9IHVucUtleUZpZWxkc1swXTtcbiAgICAgIHVucUtleXMgPSByb3dzLm1hcCgocm93KSA9PiByb3dbdW5xS2V5RmllbGRzWzBdXSk7XG4gICAgfVxuICAgIGNvbnN0IGNodW5rcyA9IGNodW5rKHVucUtleXMsIGNodW5rU2l6ZSk7XG5cbiAgICBsZXQgcmVzdWx0SWRzOiBudW1iZXJbXSA9IFtdO1xuICAgIGZvciAobGV0IGNodW5rIG9mIGNodW5rcykge1xuICAgICAgY29uc3QgZGJSb3dzID0gYXdhaXQgd2RiKHRhYmxlTmFtZSlcbiAgICAgICAgLnNlbGVjdChcImlkXCIsIHdkYi5yYXcoc2VsZWN0RmllbGQpKVxuICAgICAgICAud2hlcmVJbih3aGVyZUluRmllbGQsIGNodW5rKTtcbiAgICAgIHJlc3VsdElkcyA9IHJlc3VsdElkcy5jb25jYXQoXG4gICAgICAgIGRiUm93cy5tYXAoKGRiUm93OiBhbnkpID0+IHBhcnNlSW50KGRiUm93LmlkKSlcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdElkcztcbiAgfVxuXG4gIGFzeW5jIHVzZUxvYWRlcnMoZGI6IEtuZXgsIHJvd3M6IGFueVtdLCBsb2FkZXJzOiBTdWJzZXRRdWVyeVtcImxvYWRlcnNcIl0pIHtcbiAgICBpZiAobG9hZGVycy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiByb3dzO1xuICAgIH1cblxuICAgIGZvciAobGV0IGxvYWRlciBvZiBsb2FkZXJzKSB7XG4gICAgICBsZXQgc3ViUTogYW55O1xuICAgICAgbGV0IHN1YlJvd3M6IGFueVtdO1xuICAgICAgbGV0IHRvQ29sOiBzdHJpbmc7XG5cbiAgICAgIGNvbnN0IGZyb21JZHMgPSByb3dzLm1hcCgocm93KSA9PiByb3dbbG9hZGVyLm1hbnlKb2luLmlkRmllbGRdKTtcblxuICAgICAgaWYgKGxvYWRlci5tYW55Sm9pbi50aHJvdWdoID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgLy8gSGFzTWFueVxuICAgICAgICBjb25zdCBpZENvbHVtbiA9IGAke2xvYWRlci5tYW55Sm9pbi50b1RhYmxlfS4ke2xvYWRlci5tYW55Sm9pbi50b0NvbH1gO1xuICAgICAgICBzdWJRID0gZGIobG9hZGVyLm1hbnlKb2luLnRvVGFibGUpXG4gICAgICAgICAgLndoZXJlSW4oaWRDb2x1bW4sIGZyb21JZHMpXG4gICAgICAgICAgLnNlbGVjdChbLi4ubG9hZGVyLnNlbGVjdCwgaWRDb2x1bW5dKTtcblxuICAgICAgICAvLyBIYXNNYW557JeQ7IScIE9uZUpvaW7snbQg7J6I64qUIOqyveyasFxuICAgICAgICBsb2FkZXIub25lSm9pbnMubWFwKChqb2luKSA9PiB7XG4gICAgICAgICAgaWYgKGpvaW4uam9pbiA9PSBcImlubmVyXCIpIHtcbiAgICAgICAgICAgIHN1YlEuaW5uZXJKb2luKFxuICAgICAgICAgICAgICBgJHtqb2luLnRhYmxlfSBhcyAke2pvaW4uYXN9YCxcbiAgICAgICAgICAgICAgdGhpcy5nZXRKb2luQ2xhdXNlKGRiLCBqb2luKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGpvaW4uam9pbiA9PSBcIm91dGVyXCIpIHtcbiAgICAgICAgICAgIHN1YlEubGVmdE91dGVySm9pbihcbiAgICAgICAgICAgICAgYCR7am9pbi50YWJsZX0gYXMgJHtqb2luLmFzfWAsXG4gICAgICAgICAgICAgIHRoaXMuZ2V0Sm9pbkNsYXVzZShkYiwgam9pbilcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdG9Db2wgPSBsb2FkZXIubWFueUpvaW4udG9Db2w7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBNYW55VG9NYW55XG4gICAgICAgIGNvbnN0IGlkQ29sdW1uID0gYCR7bG9hZGVyLm1hbnlKb2luLnRocm91Z2gudGFibGV9LiR7bG9hZGVyLm1hbnlKb2luLnRocm91Z2guZnJvbUNvbH1gO1xuICAgICAgICBzdWJRID0gZGIobG9hZGVyLm1hbnlKb2luLnRocm91Z2gudGFibGUpXG4gICAgICAgICAgLmpvaW4oXG4gICAgICAgICAgICBsb2FkZXIubWFueUpvaW4udG9UYWJsZSxcbiAgICAgICAgICAgIGAke2xvYWRlci5tYW55Sm9pbi50aHJvdWdoLnRhYmxlfS4ke2xvYWRlci5tYW55Sm9pbi50aHJvdWdoLnRvQ29sfWAsXG4gICAgICAgICAgICBgJHtsb2FkZXIubWFueUpvaW4udG9UYWJsZX0uJHtsb2FkZXIubWFueUpvaW4udG9Db2x9YFxuICAgICAgICAgIClcbiAgICAgICAgICAud2hlcmVJbihpZENvbHVtbiwgZnJvbUlkcylcbiAgICAgICAgICAuc2VsZWN0KHVuaXEoWy4uLmxvYWRlci5zZWxlY3QsIGlkQ29sdW1uXSkpO1xuXG4gICAgICAgIC8vIE1hbnlUb01hbnnsl5DshJwgT25lSm9pbuydtCDsnojripQg6rK97JqwXG4gICAgICAgIGxvYWRlci5vbmVKb2lucy5tYXAoKGpvaW4pID0+IHtcbiAgICAgICAgICBpZiAoam9pbi5qb2luID09IFwiaW5uZXJcIikge1xuICAgICAgICAgICAgc3ViUS5pbm5lckpvaW4oXG4gICAgICAgICAgICAgIGAke2pvaW4udGFibGV9IGFzICR7am9pbi5hc31gLFxuICAgICAgICAgICAgICB0aGlzLmdldEpvaW5DbGF1c2UoZGIsIGpvaW4pXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0gZWxzZSBpZiAoam9pbi5qb2luID09IFwib3V0ZXJcIikge1xuICAgICAgICAgICAgc3ViUS5sZWZ0T3V0ZXJKb2luKFxuICAgICAgICAgICAgICBgJHtqb2luLnRhYmxlfSBhcyAke2pvaW4uYXN9YCxcbiAgICAgICAgICAgICAgdGhpcy5nZXRKb2luQ2xhdXNlKGRiLCBqb2luKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB0b0NvbCA9IGxvYWRlci5tYW55Sm9pbi50aHJvdWdoLmZyb21Db2w7XG4gICAgICB9XG4gICAgICBzdWJSb3dzID0gYXdhaXQgc3ViUTtcblxuICAgICAgaWYgKGxvYWRlci5sb2FkZXJzKSB7XG4gICAgICAgIC8vIOy2lOqwgCAtTWFueSDsvIDsnbTsiqTqsIAg7J6I64qUIOqyveyasCByZWN1cnNpb24g7LKY66asXG4gICAgICAgIHN1YlJvd3MgPSBhd2FpdCB0aGlzLnVzZUxvYWRlcnMoZGIsIHN1YlJvd3MsIGxvYWRlci5sb2FkZXJzKTtcbiAgICAgIH1cblxuICAgICAgLy8g67aI65+s7JioIHJvd+uTpOydhCDssLjsobBJRCDquLDspIDsnLzroZwg67aE66WYIOuwsOy5mFxuICAgICAgY29uc3Qgc3ViUm93R3JvdXBzID0gZ3JvdXBCeShzdWJSb3dzLCB0b0NvbCk7XG4gICAgICByb3dzID0gcm93cy5tYXAoKHJvdykgPT4ge1xuICAgICAgICByb3dbbG9hZGVyLmFzXSA9IChzdWJSb3dHcm91cHNbcm93W2xvYWRlci5tYW55Sm9pbi5pZEZpZWxkXV0gPz8gW10pLm1hcChcbiAgICAgICAgICAocikgPT4gb21pdChyLCB0b0NvbClcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHJvdztcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gcm93cztcbiAgfVxuXG4gIGh5ZHJhdGU8VD4ocm93czogVFtdKTogVFtdIHtcbiAgICByZXR1cm4gcm93cy5tYXAoKHJvdzogYW55KSA9PiB7XG4gICAgICAvLyBudWxsYWJsZSByZWxhdGlvbuyduCDqsr3smrAg6rSA66Co65CcIO2VhOuTnOqwgCDsoITrtoAgbnVsbOuhnCDsg53shLHrkJjripQg6rKDIOuwqeyngO2VmOuKlCDsvZTrk5xcbiAgICAgIGNvbnN0IG5lc3RlZEtleXMgPSBPYmplY3Qua2V5cyhyb3cpLmZpbHRlcigoa2V5KSA9PiBrZXkuaW5jbHVkZXMoXCJfX1wiKSk7XG4gICAgICBjb25zdCBncm91cHMgPSBncm91cEJ5KG5lc3RlZEtleXMsIChrZXkpID0+IGtleS5zcGxpdChcIl9fXCIpWzBdKTtcbiAgICAgIGNvbnN0IG51bGxLZXlzID0gT2JqZWN0LmtleXMoZ3JvdXBzKS5maWx0ZXIoXG4gICAgICAgIChrZXkpID0+XG4gICAgICAgICAgZ3JvdXBzW2tleV0ubGVuZ3RoID4gMSAmJlxuICAgICAgICAgIGdyb3Vwc1trZXldLmV2ZXJ5KFxuICAgICAgICAgICAgKGZpZWxkKSA9PlxuICAgICAgICAgICAgICByb3dbZmllbGRdID09PSBudWxsIHx8XG4gICAgICAgICAgICAgIChBcnJheS5pc0FycmF5KHJvd1tmaWVsZF0pICYmIHJvd1tmaWVsZF0ubGVuZ3RoID09PSAwKVxuICAgICAgICAgIClcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IGh5ZHJhdGVkID0gT2JqZWN0LmtleXMocm93KS5yZWR1Y2UoKHIsIGZpZWxkKSA9PiB7XG4gICAgICAgIGlmICghZmllbGQuaW5jbHVkZXMoXCJfX1wiKSkge1xuICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KHJvd1tmaWVsZF0pICYmIGlzT2JqZWN0KHJvd1tmaWVsZF1bMF0pKSB7XG4gICAgICAgICAgICByW2ZpZWxkXSA9IHRoaXMuaHlkcmF0ZShyb3dbZmllbGRdKTtcbiAgICAgICAgICAgIHJldHVybiByO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByW2ZpZWxkXSA9IHJvd1tmaWVsZF07XG4gICAgICAgICAgICByZXR1cm4gcjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBwYXJ0cyA9IGZpZWxkLnNwbGl0KFwiX19cIik7XG4gICAgICAgIGNvbnN0IG9ialBhdGggPVxuICAgICAgICAgIHBhcnRzWzBdICtcbiAgICAgICAgICBwYXJ0c1xuICAgICAgICAgICAgLnNsaWNlKDEpXG4gICAgICAgICAgICAubWFwKChwYXJ0KSA9PiBgWyR7cGFydH1dYClcbiAgICAgICAgICAgIC5qb2luKFwiXCIpO1xuICAgICAgICBzZXQoXG4gICAgICAgICAgcixcbiAgICAgICAgICBvYmpQYXRoLFxuICAgICAgICAgIHJvd1tmaWVsZF0gJiYgQXJyYXkuaXNBcnJheShyb3dbZmllbGRdKSAmJiBpc09iamVjdChyb3dbZmllbGRdWzBdKVxuICAgICAgICAgICAgPyB0aGlzLmh5ZHJhdGUocm93W2ZpZWxkXSlcbiAgICAgICAgICAgIDogcm93W2ZpZWxkXVxuICAgICAgICApO1xuXG4gICAgICAgIHJldHVybiByO1xuICAgICAgfSwge30gYXMgYW55KTtcbiAgICAgIG51bGxLZXlzLm1hcCgobnVsbEtleSkgPT4gKGh5ZHJhdGVkW251bGxLZXldID0gbnVsbCkpO1xuXG4gICAgICByZXR1cm4gaHlkcmF0ZWQ7XG4gICAgfSk7XG4gIH1cblxuICBhc3luYyBydW5TdWJzZXRRdWVyeTxUIGV4dGVuZHMgQmFzZUxpc3RQYXJhbXMsIFUgZXh0ZW5kcyBzdHJpbmc+KHtcbiAgICBwYXJhbXMsXG4gICAgYmFzZVRhYmxlLFxuICAgIHN1YnNldCxcbiAgICBzdWJzZXRRdWVyeSxcbiAgICBidWlsZCxcbiAgICBhZnRlckJ1aWxkLFxuICAgIGRlYnVnLFxuICAgIGRiOiBfZGIsXG4gICAgb3B0aW1pemVDb3VudFF1ZXJ5LFxuICB9OiB7XG4gICAgc3Vic2V0OiBVO1xuICAgIHBhcmFtczogVDtcbiAgICBzdWJzZXRRdWVyeTogU3Vic2V0UXVlcnk7XG4gICAgYnVpbGQ6IChidWlsZFBhcmFtczoge1xuICAgICAgcWI6IEtuZXguUXVlcnlCdWlsZGVyO1xuICAgICAgZGI6IEtuZXg7XG4gICAgICBzZWxlY3Q6IChzdHJpbmcgfCBLbmV4LlJhdylbXTtcbiAgICAgIGpvaW5zOiBTdWJzZXRRdWVyeVtcImpvaW5zXCJdO1xuICAgICAgdmlydHVhbDogc3RyaW5nW107XG4gICAgfSkgPT4gS25leC5RdWVyeUJ1aWxkZXI7XG4gICAgYWZ0ZXJCdWlsZD86IChidWlsZFBhcmFtczoge1xuICAgICAgcWI6IEtuZXguUXVlcnlCdWlsZGVyO1xuICAgICAgZGI6IEtuZXg7XG4gICAgICBzZWxlY3Q6IChzdHJpbmcgfCBLbmV4LlJhdylbXTtcbiAgICAgIGpvaW5zOiBTdWJzZXRRdWVyeVtcImpvaW5zXCJdO1xuICAgICAgdmlydHVhbDogc3RyaW5nW107XG4gICAgfSkgPT4gS25leC5RdWVyeUJ1aWxkZXI7XG4gICAgYmFzZVRhYmxlPzogc3RyaW5nO1xuICAgIGRlYnVnPzogYm9vbGVhbiB8IFwibGlzdFwiIHwgXCJjb3VudFwiO1xuICAgIGRiPzogS25leDtcbiAgICBvcHRpbWl6ZUNvdW50UXVlcnk/OiBib29sZWFuO1xuICB9KTogUHJvbWlzZTx7XG4gICAgcm93czogYW55W107XG4gICAgdG90YWw/OiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gICAgc3Vic2V0UXVlcnk6IFN1YnNldFF1ZXJ5O1xuICAgIHFiOiBLbmV4LlF1ZXJ5QnVpbGRlcjtcbiAgfT4ge1xuICAgIGNvbnN0IGRiID0gX2RiID8/IHRoaXMuZ2V0REIoc3Vic2V0LnN0YXJ0c1dpdGgoXCJBXCIpID8gXCJ3XCIgOiBcInJcIik7XG4gICAgYmFzZVRhYmxlID1cbiAgICAgIGJhc2VUYWJsZSA/PyBpbmZsZWN0aW9uLnBsdXJhbGl6ZShpbmZsZWN0aW9uLnVuZGVyc2NvcmUodGhpcy5tb2RlbE5hbWUpKTtcbiAgICBjb25zdCBxdWVyeU1vZGUgPVxuICAgICAgcGFyYW1zLnF1ZXJ5TW9kZSA/PyAocGFyYW1zLmlkICE9PSB1bmRlZmluZWQgPyBcImxpc3RcIiA6IFwiYm90aFwiKTtcblxuICAgIGNvbnN0IHsgc2VsZWN0LCB2aXJ0dWFsLCBqb2lucywgbG9hZGVycyB9ID0gc3Vic2V0UXVlcnk7XG4gICAgY29uc3QgcWIgPSBidWlsZCh7XG4gICAgICBxYjogZGIuZnJvbShiYXNlVGFibGUpLFxuICAgICAgZGIsXG4gICAgICBzZWxlY3QsXG4gICAgICBqb2lucyxcbiAgICAgIHZpcnR1YWwsXG4gICAgfSk7XG5cbiAgICBjb25zdCBhcHBseUpvaW5DbGF1c2UgPSAoXG4gICAgICBxYjogS25leC5RdWVyeUJ1aWxkZXIsXG4gICAgICBqb2luczogU3Vic2V0UXVlcnlbXCJqb2luc1wiXVxuICAgICkgPT4ge1xuICAgICAgam9pbnMubWFwKChqb2luKSA9PiB7XG4gICAgICAgIGlmIChqb2luLmpvaW4gPT0gXCJpbm5lclwiKSB7XG4gICAgICAgICAgcWIuaW5uZXJKb2luKFxuICAgICAgICAgICAgYCR7am9pbi50YWJsZX0gYXMgJHtqb2luLmFzfWAsXG4gICAgICAgICAgICB0aGlzLmdldEpvaW5DbGF1c2UoZGIsIGpvaW4pXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIGlmIChqb2luLmpvaW4gPT0gXCJvdXRlclwiKSB7XG4gICAgICAgICAgcWIubGVmdE91dGVySm9pbihcbiAgICAgICAgICAgIGAke2pvaW4udGFibGV9IGFzICR7am9pbi5hc31gLFxuICAgICAgICAgICAgdGhpcy5nZXRKb2luQ2xhdXNlKGRiLCBqb2luKVxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvLyBjb3VudFF1ZXJ5XG4gICAgY29uc3QgdG90YWwgPSBhd2FpdCAoYXN5bmMgKCkgPT4ge1xuICAgICAgaWYgKHF1ZXJ5TW9kZSA9PT0gXCJsaXN0XCIpIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY2xvbmVkUWIgPSBxYi5jbG9uZSgpLmNsZWFyKFwib3JkZXJcIikuY2xlYXIoXCJvZmZzZXRcIikuY2xlYXIoXCJsaW1pdFwiKTtcbiAgICAgIGNvbnN0IHBhcnNlciA9IG5ldyBTcWxQYXJzZXIuUGFyc2VyKCk7XG5cbiAgICAgIC8vIG9wdG1pemVDb3VudFF1ZXJ56rCAIHRydWXsnbgg6rK97JqwIOuLpOuluCBjbGF1c2Xsl5Ag7JiB7Zal7J2EIOyjvOyngCDslYrripQg66qo65OgIGpvaW7snYQg7KCc7Jm47ZWoXG4gICAgICBpZiAob3B0aW1pemVDb3VudFF1ZXJ5KSB7XG4gICAgICAgIGNvbnN0IHBhcnNlZFF1ZXJ5ID0gcGFyc2VyLmFzdGlmeShjbG9uZWRRYi50b1F1ZXJ5KCkpO1xuICAgICAgICBjb25zdCB0YWJsZXMgPSBnZXRUYWJsZU5hbWVzRnJvbVdoZXJlKHBhcnNlZFF1ZXJ5KTtcbiAgICAgICAgLy8gd2hlcmXsoIjsl5Ag7IKs7Jqp65CY64qUIO2FjOydtOu4lOydmCDsobDsnbjsnYQg7JyE7ZW0IOyCrOyaqeuQmOuKlCDthYzsnbTruJRcbiAgICAgICAgY29uc3QgbmVlZFRvSm9pbiA9IHVuaXEoXG4gICAgICAgICAgdGFibGVzLmZsYXRNYXAoKHRhYmxlKSA9PlxuICAgICAgICAgICAgdGFibGUuc3BsaXQoXCJfX1wiKS5tYXAoKHQpID0+IGluZmxlY3Rpb24ucGx1cmFsaXplKHQpKVxuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgICAgYXBwbHlKb2luQ2xhdXNlKFxuICAgICAgICAgIGNsb25lZFFiLFxuICAgICAgICAgIGpvaW5zLmZpbHRlcigoaikgPT4gbmVlZFRvSm9pbi5pbmNsdWRlcyhqLnRhYmxlKSlcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGFwcGx5Sm9pbkNsYXVzZShjbG9uZWRRYiwgam9pbnMpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBwcm9jZXNzZWRRYiA9XG4gICAgICAgIGFmdGVyQnVpbGQ/Lih7XG4gICAgICAgICAgcWI6IGNsb25lZFFiLFxuICAgICAgICAgIGRiLFxuICAgICAgICAgIHNlbGVjdCxcbiAgICAgICAgICBqb2lucyxcbiAgICAgICAgICB2aXJ0dWFsLFxuICAgICAgICB9KSA/PyBjbG9uZWRRYjtcblxuICAgICAgY29uc3QgcGFyc2VkUXVlcnkgPSBwYXJzZXIuYXN0aWZ5KHByb2Nlc3NlZFFiLnRvUXVlcnkoKSk7XG4gICAgICBjb25zdCBxID0gQXJyYXkuaXNBcnJheShwYXJzZWRRdWVyeSkgPyBwYXJzZWRRdWVyeVswXSA6IHBhcnNlZFF1ZXJ5O1xuICAgICAgaWYgKHEudHlwZSAhPT0gXCJzZWxlY3RcIikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHF1ZXJ5XCIpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBjb3VudFF1ZXJ5ID1cbiAgICAgICAgcS5kaXN0aW5jdCAhPT0gbnVsbFxuICAgICAgICAgID8gY2xvbmVkUWJcbiAgICAgICAgICAgICAgLmNsZWFyKFwic2VsZWN0XCIpXG4gICAgICAgICAgICAgIC5zZWxlY3QoXG4gICAgICAgICAgICAgICAgZGIucmF3KFxuICAgICAgICAgICAgICAgICAgYENPVU5UKERJU1RJTkNUIFxcYCR7Z2V0VGFibGVOYW1lKHEuY29sdW1uc1swXS5leHByKX1cXGAuXFxgJHtxLmNvbHVtbnNbMF0uZXhwci5jb2x1bW59XFxgKSBhcyB0b3RhbGBcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgLmZpcnN0KClcbiAgICAgICAgICA6IGNsb25lZFFiLmNsZWFyKFwic2VsZWN0XCIpLmNvdW50KFwiKlwiLCB7IGFzOiBcInRvdGFsXCIgfSkuZmlyc3QoKTtcbiAgICAgIGNvbnN0IGNvdW50Um93OiB7IHRvdGFsPzogbnVtYmVyIH0gPSBhd2FpdCBjb3VudFF1ZXJ5O1xuXG4gICAgICAvLyBkZWJ1ZzogY291bnRRdWVyeVxuICAgICAgaWYgKGRlYnVnID09PSB0cnVlIHx8IGRlYnVnID09PSBcImNvdW50XCIpIHtcbiAgICAgICAgY29uc29sZS5kZWJ1ZyhcbiAgICAgICAgICBcIkRFQlVHOiBjb3VudCBxdWVyeVwiLFxuICAgICAgICAgIGNoYWxrLmJsdWUoY291bnRRdWVyeS50b1F1ZXJ5KCkudG9TdHJpbmcoKSlcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGNvdW50Um93Py50b3RhbCA/PyAwO1xuICAgIH0pKCk7XG5cbiAgICAvLyBsaXN0UXVlcnlcbiAgICBjb25zdCByb3dzID0gYXdhaXQgKGFzeW5jICgpID0+IHtcbiAgICAgIGlmIChxdWVyeU1vZGUgPT09IFwiY291bnRcIikge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG5cbiAgICAgIC8vIGxpbWl0LCBvZmZzZXRcbiAgICAgIGlmIChwYXJhbXMubnVtICE9PSAwKSB7XG4gICAgICAgIHFiLmxpbWl0KHBhcmFtcy5udW0hKTtcbiAgICAgICAgcWIub2Zmc2V0KHBhcmFtcy5udW0hICogKHBhcmFtcy5wYWdlISAtIDEpKTtcbiAgICAgIH1cblxuICAgICAgLy8gc2VsZWN0LCByb3dzXG4gICAgICBjb25zdCBjbG9uZWRRYiA9IHFiLmNsb25lKCkuc2VsZWN0KHNlbGVjdCk7XG5cbiAgICAgIC8vIGpvaW5cbiAgICAgIGFwcGx5Sm9pbkNsYXVzZShjbG9uZWRRYiwgam9pbnMpO1xuXG4gICAgICBjb25zdCBsaXN0UXVlcnkgPVxuICAgICAgICBhZnRlckJ1aWxkPy4oe1xuICAgICAgICAgIHFiOiBjbG9uZWRRYixcbiAgICAgICAgICBkYixcbiAgICAgICAgICBzZWxlY3QsXG4gICAgICAgICAgam9pbnMsXG4gICAgICAgICAgdmlydHVhbCxcbiAgICAgICAgfSkgPz8gY2xvbmVkUWI7XG5cbiAgICAgIGxldCByb3dzID0gYXdhaXQgbGlzdFF1ZXJ5O1xuICAgICAgLy8gZGVidWc6IGxpc3RRdWVyeVxuICAgICAgaWYgKGRlYnVnID09PSB0cnVlIHx8IGRlYnVnID09PSBcImxpc3RcIikge1xuICAgICAgICBjb25zb2xlLmRlYnVnKFxuICAgICAgICAgIFwiREVCVUc6IGxpc3QgcXVlcnlcIixcbiAgICAgICAgICBjaGFsay5ibHVlKGxpc3RRdWVyeS50b1F1ZXJ5KCkudG9TdHJpbmcoKSlcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgcm93cyA9IGF3YWl0IHRoaXMudXNlTG9hZGVycyhkYiwgcm93cywgbG9hZGVycyk7XG4gICAgICByb3dzID0gdGhpcy5oeWRyYXRlKHJvd3MpO1xuICAgICAgcmV0dXJuIHJvd3M7XG4gICAgfSkoKTtcblxuICAgIHJldHVybiB7IHJvd3MsIHRvdGFsLCBzdWJzZXRRdWVyeSwgcWIgfTtcbiAgfVxuXG4gIGdldEpvaW5DbGF1c2UoXG4gICAgZGI6IEtuZXg8YW55LCB1bmtub3duPixcbiAgICBqb2luOiBTdWJzZXRRdWVyeVtcImpvaW5zXCJdW251bWJlcl1cbiAgKTogS25leC5SYXc8YW55PiB7XG4gICAgaWYgKCFpc0N1c3RvbUpvaW5DbGF1c2Uoam9pbikpIHtcbiAgICAgIHJldHVybiBkYi5yYXcoYCR7am9pbi5mcm9tfSA9ICR7am9pbi50b31gKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGRiLnJhdyhqb2luLmN1c3RvbSk7XG4gICAgfVxuICB9XG5cbiAgZ2V0VXBzZXJ0QnVpbGRlcigpOiBVcHNlcnRCdWlsZGVyIHtcbiAgICByZXR1cm4gbmV3IFVwc2VydEJ1aWxkZXIoKTtcbiAgfVxufVxuZXhwb3J0IGNvbnN0IEJhc2VNb2RlbCA9IG5ldyBCYXNlTW9kZWxDbGFzcygpO1xuIl0sIm5hbWVzIjpbIkRhdGVUaW1lIiwiY2h1bmsiLCJncm91cEJ5IiwiaXNPYmplY3QiLCJvbWl0Iiwic2V0IiwidW5pcSIsIkRCIiwiaXNDdXN0b21Kb2luQ2xhdXNlIiwiaW5mbGVjdGlvbiIsImNoYWxrIiwiVXBzZXJ0QnVpbGRlciIsIlNxbFBhcnNlciIsImdldFRhYmxlTmFtZSIsImdldFRhYmxlTmFtZXNGcm9tV2hlcmUiLCJQdXJpV3JhcHBlciIsIkJhc2VNb2RlbENsYXNzIiwibW9kZWxOYW1lIiwiZ2V0REIiLCJ3aGljaCIsImdldFB1cmkiLCJ0cngiLCJnZXRUcmFuc2FjdGlvbkNvbnRleHQiLCJnZXRUcmFuc2FjdGlvbiIsImRiIiwiZ2V0VXBzZXJ0QnVpbGRlciIsImRlc3Ryb3kiLCJteU5vdyIsInRpbWVzdGFtcCIsImR0IiwidW5kZWZpbmVkIiwibG9jYWwiLCJmcm9tU2Vjb25kcyIsInRvRm9ybWF0IiwiZ2V0SW5zZXJ0ZWRJZHMiLCJ3ZGIiLCJyb3dzIiwidGFibGVOYW1lIiwidW5xS2V5RmllbGRzIiwiY2h1bmtTaXplIiwidW5xS2V5cyIsIndoZXJlSW5GaWVsZCIsInNlbGVjdEZpZWxkIiwibGVuZ3RoIiwicmF3Iiwiam9pbiIsIm1hcCIsInJvdyIsImZpZWxkIiwiY2h1bmtzIiwicmVzdWx0SWRzIiwiZGJSb3dzIiwic2VsZWN0Iiwid2hlcmVJbiIsImNvbmNhdCIsImRiUm93IiwicGFyc2VJbnQiLCJpZCIsInVzZUxvYWRlcnMiLCJsb2FkZXJzIiwibG9hZGVyIiwic3ViUSIsInN1YlJvd3MiLCJ0b0NvbCIsImZyb21JZHMiLCJtYW55Sm9pbiIsImlkRmllbGQiLCJ0aHJvdWdoIiwiaWRDb2x1bW4iLCJ0b1RhYmxlIiwib25lSm9pbnMiLCJpbm5lckpvaW4iLCJ0YWJsZSIsImFzIiwiZ2V0Sm9pbkNsYXVzZSIsImxlZnRPdXRlckpvaW4iLCJmcm9tQ29sIiwic3ViUm93R3JvdXBzIiwiciIsImh5ZHJhdGUiLCJuZXN0ZWRLZXlzIiwiT2JqZWN0Iiwia2V5cyIsImZpbHRlciIsImtleSIsImluY2x1ZGVzIiwiZ3JvdXBzIiwic3BsaXQiLCJudWxsS2V5cyIsImV2ZXJ5IiwiQXJyYXkiLCJpc0FycmF5IiwiaHlkcmF0ZWQiLCJyZWR1Y2UiLCJwYXJ0cyIsIm9ialBhdGgiLCJzbGljZSIsInBhcnQiLCJudWxsS2V5IiwicnVuU3Vic2V0UXVlcnkiLCJwYXJhbXMiLCJiYXNlVGFibGUiLCJzdWJzZXQiLCJzdWJzZXRRdWVyeSIsImJ1aWxkIiwiYWZ0ZXJCdWlsZCIsImRlYnVnIiwiX2RiIiwib3B0aW1pemVDb3VudFF1ZXJ5Iiwic3RhcnRzV2l0aCIsInBsdXJhbGl6ZSIsInVuZGVyc2NvcmUiLCJxdWVyeU1vZGUiLCJ2aXJ0dWFsIiwiam9pbnMiLCJxYiIsImZyb20iLCJhcHBseUpvaW5DbGF1c2UiLCJ0b3RhbCIsImNsb25lZFFiIiwiY2xvbmUiLCJjbGVhciIsInBhcnNlciIsIlBhcnNlciIsInBhcnNlZFF1ZXJ5IiwiYXN0aWZ5IiwidG9RdWVyeSIsInRhYmxlcyIsIm5lZWRUb0pvaW4iLCJmbGF0TWFwIiwidCIsImoiLCJwcm9jZXNzZWRRYiIsInEiLCJ0eXBlIiwiRXJyb3IiLCJjb3VudFF1ZXJ5IiwiZGlzdGluY3QiLCJjb2x1bW5zIiwiZXhwciIsImNvbHVtbiIsImZpcnN0IiwiY291bnQiLCJjb3VudFJvdyIsImNvbnNvbGUiLCJibHVlIiwidG9TdHJpbmciLCJudW0iLCJsaW1pdCIsIm9mZnNldCIsInBhZ2UiLCJsaXN0UXVlcnkiLCJ0byIsImN1c3RvbSIsIkJhc2VNb2RlbCJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsUUFBUSxRQUFRLFFBQVE7QUFFakMsU0FBU0MsS0FBSyxFQUFFQyxPQUFPLEVBQUVDLFFBQVEsRUFBRUMsSUFBSSxFQUFFQyxHQUFHLEVBQUVDLElBQUksUUFBUSxZQUFZO0FBQ3RFLFNBQW1CQyxFQUFFLFFBQVEsVUFBTztBQUNwQyxTQUFTQyxrQkFBa0IsUUFBMEIsb0JBQWlCO0FBRXRFLE9BQU9DLGdCQUFnQixhQUFhO0FBQ3BDLE9BQU9DLFdBQVcsUUFBUTtBQUMxQixTQUFTQyxhQUFhLFFBQVEsc0JBQW1CO0FBQ2pELE9BQU9DLGVBQWUsa0JBQWtCO0FBQ3hDLFNBQVNDLFlBQVksRUFBRUMsc0JBQXNCLFFBQVEseUJBQXNCO0FBQzNFLFNBQVNDLFdBQVcsUUFBUSxvQkFBaUI7QUFFN0MsT0FBTyxNQUFNQztJQUNKQyxZQUFvQixVQUFVO0lBRXJDLHdCQUF3QixHQUN4QkMsTUFBTUMsS0FBZSxFQUFRO1FBQzNCLE9BQU9aLEdBQUdXLEtBQUssQ0FB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
|
|
@@ -1,2 +1,53 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import * as _ from "lodash-es";
|
|
2
|
+
import equal from "fast-deep-equal";
|
|
3
|
+
export class CodeGenerator {
|
|
4
|
+
getAlterColumnsTo(entityColumns, dbColumns) {
|
|
5
|
+
const columnsTo = {
|
|
6
|
+
add: [],
|
|
7
|
+
drop: [],
|
|
8
|
+
alter: []
|
|
9
|
+
};
|
|
10
|
+
// 컬럼명 기준 비교
|
|
11
|
+
const extraColumns = {
|
|
12
|
+
db: _.differenceBy(dbColumns, entityColumns, (col)=>col.name),
|
|
13
|
+
entity: _.differenceBy(entityColumns, dbColumns, (col)=>col.name)
|
|
14
|
+
};
|
|
15
|
+
if (extraColumns.entity.length > 0) {
|
|
16
|
+
columnsTo.add = columnsTo.add.concat(extraColumns.entity);
|
|
17
|
+
}
|
|
18
|
+
if (extraColumns.db.length > 0) {
|
|
19
|
+
columnsTo.drop = columnsTo.drop.concat(extraColumns.db);
|
|
20
|
+
}
|
|
21
|
+
// 동일 컬럼명의 세부 필드 비교
|
|
22
|
+
const sameDbColumns = _.intersectionBy(dbColumns, entityColumns, (col)=>col.name);
|
|
23
|
+
const sameMdColumns = _.intersectionBy(entityColumns, dbColumns, (col)=>col.name);
|
|
24
|
+
columnsTo.alter = _.differenceWith(sameDbColumns, sameMdColumns, (a, b)=>equal(a, b));
|
|
25
|
+
return columnsTo;
|
|
26
|
+
}
|
|
27
|
+
getAlterIndexesTo(entityIndexes, dbIndexes) {
|
|
28
|
+
// 인덱스 비교
|
|
29
|
+
let indexesTo = {
|
|
30
|
+
add: [],
|
|
31
|
+
drop: []
|
|
32
|
+
};
|
|
33
|
+
const extraIndexes = {
|
|
34
|
+
db: _.differenceBy(dbIndexes, entityIndexes, (col)=>[
|
|
35
|
+
col.type,
|
|
36
|
+
col.columns.join("-")
|
|
37
|
+
].join("//")),
|
|
38
|
+
entity: _.differenceBy(entityIndexes, dbIndexes, (col)=>[
|
|
39
|
+
col.type,
|
|
40
|
+
col.columns.join("-")
|
|
41
|
+
].join("//"))
|
|
42
|
+
};
|
|
43
|
+
if (extraIndexes.entity.length > 0) {
|
|
44
|
+
indexesTo.add = indexesTo.add.concat(extraIndexes.entity);
|
|
45
|
+
}
|
|
46
|
+
if (extraIndexes.db.length > 0) {
|
|
47
|
+
indexesTo.drop = indexesTo.drop.concat(extraIndexes.db);
|
|
48
|
+
}
|
|
49
|
+
return indexesTo;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kYXRhYmFzZS9jb2RlLWdlbmVyYXRvci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBfIGZyb20gXCJsb2Rhc2gtZXNcIjtcbmltcG9ydCBlcXVhbCBmcm9tIFwiZmFzdC1kZWVwLWVxdWFsXCI7XG5pbXBvcnQgeyBNaWdyYXRpb25Db2x1bW4sIE1pZ3JhdGlvbkluZGV4IH0gZnJvbSBcIi4uL3R5cGVzL3R5cGVzXCI7XG5cbmV4cG9ydCBjbGFzcyBDb2RlR2VuZXJhdG9yIHtcbiAgZ2V0QWx0ZXJDb2x1bW5zVG8oXG4gICAgZW50aXR5Q29sdW1uczogTWlncmF0aW9uQ29sdW1uW10sXG4gICAgZGJDb2x1bW5zOiBNaWdyYXRpb25Db2x1bW5bXVxuICApIHtcbiAgICBjb25zdCBjb2x1bW5zVG8gPSB7XG4gICAgICBhZGQ6IFtdIGFzIE1pZ3JhdGlvbkNvbHVtbltdLFxuICAgICAgZHJvcDogW10gYXMgTWlncmF0aW9uQ29sdW1uW10sXG4gICAgICBhbHRlcjogW10gYXMgTWlncmF0aW9uQ29sdW1uW10sXG4gICAgfTtcblxuICAgIC8vIOy7rOufvOuqhSDquLDspIAg67mE6rWQXG4gICAgY29uc3QgZXh0cmFDb2x1bW5zID0ge1xuICAgICAgZGI6IF8uZGlmZmVyZW5jZUJ5KGRiQ29sdW1ucywgZW50aXR5Q29sdW1ucywgKGNvbCkgPT4gY29sLm5hbWUpLFxuICAgICAgZW50aXR5OiBfLmRpZmZlcmVuY2VCeShlbnRpdHlDb2x1bW5zLCBkYkNvbHVtbnMsIChjb2wpID0+IGNvbC5uYW1lKSxcbiAgICB9O1xuICAgIGlmIChleHRyYUNvbHVtbnMuZW50aXR5Lmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbHVtbnNUby5hZGQgPSBjb2x1bW5zVG8uYWRkLmNvbmNhdChleHRyYUNvbHVtbnMuZW50aXR5KTtcbiAgICB9XG4gICAgaWYgKGV4dHJhQ29sdW1ucy5kYi5sZW5ndGggPiAwKSB7XG4gICAgICBjb2x1bW5zVG8uZHJvcCA9IGNvbHVtbnNUby5kcm9wLmNvbmNhdChleHRyYUNvbHVtbnMuZGIpO1xuICAgIH1cblxuICAgIC8vIOuPmeydvCDsu6zrn7zrqoXsnZgg7IS467aAIO2VhOuTnCDruYTqtZBcbiAgICBjb25zdCBzYW1lRGJDb2x1bW5zID0gXy5pbnRlcnNlY3Rpb25CeShcbiAgICAgIGRiQ29sdW1ucyxcbiAgICAgIGVudGl0eUNvbHVtbnMsXG4gICAgICAoY29sKSA9PiBjb2wubmFtZVxuICAgICk7XG4gICAgY29uc3Qgc2FtZU1kQ29sdW1ucyA9IF8uaW50ZXJzZWN0aW9uQnkoXG4gICAgICBlbnRpdHlDb2x1bW5zLFxuICAgICAgZGJDb2x1bW5zLFxuICAgICAgKGNvbCkgPT4gY29sLm5hbWVcbiAgICApO1xuICAgIGNvbHVtbnNUby5hbHRlciA9IF8uZGlmZmVyZW5jZVdpdGgoc2FtZURiQ29sdW1ucywgc2FtZU1kQ29sdW1ucywgKGEsIGIpID0+XG4gICAgICBlcXVhbChhLCBiKVxuICAgICk7XG5cbiAgICByZXR1cm4gY29sdW1uc1RvO1xuICB9XG5cbiAgZ2V0QWx0ZXJJbmRleGVzVG8oXG4gICAgZW50aXR5SW5kZXhlczogTWlncmF0aW9uSW5kZXhbXSxcbiAgICBkYkluZGV4ZXM6IE1pZ3JhdGlvbkluZGV4W11cbiAgKSB7XG4gICAgLy8g7J24642x7IqkIOu5hOq1kFxuICAgIGxldCBpbmRleGVzVG8gPSB7XG4gICAgICBhZGQ6IFtdIGFzIE1pZ3JhdGlvbkluZGV4W10sXG4gICAgICBkcm9wOiBbXSBhcyBNaWdyYXRpb25JbmRleFtdLFxuICAgIH07XG4gICAgY29uc3QgZXh0cmFJbmRleGVzID0ge1xuICAgICAgZGI6IF8uZGlmZmVyZW5jZUJ5KGRiSW5kZXhlcywgZW50aXR5SW5kZXhlcywgKGNvbCkgPT5cbiAgICAgICAgW2NvbC50eXBlLCBjb2wuY29sdW1ucy5qb2luKFwiLVwiKV0uam9pbihcIi8vXCIpXG4gICAgICApLFxuICAgICAgZW50aXR5OiBfLmRpZmZlcmVuY2VCeShlbnRpdHlJbmRleGVzLCBkYkluZGV4ZXMsIChjb2wpID0+XG4gICAgICAgIFtjb2wudHlwZSwgY29sLmNvbHVtbnMuam9pbihcIi1cIildLmpvaW4oXCIvL1wiKVxuICAgICAgKSxcbiAgICB9O1xuICAgIGlmIChleHRyYUluZGV4ZXMuZW50aXR5Lmxlbmd0aCA+IDApIHtcbiAgICAgIGluZGV4ZXNUby5hZGQgPSBpbmRleGVzVG8uYWRkLmNvbmNhdChleHRyYUluZGV4ZXMuZW50aXR5KTtcbiAgICB9XG4gICAgaWYgKGV4dHJhSW5kZXhlcy5kYi5sZW5ndGggPiAwKSB7XG4gICAgICBpbmRleGVzVG8uZHJvcCA9IGluZGV4ZXNUby5kcm9wLmNvbmNhdChleHRyYUluZGV4ZXMuZGIpO1xuICAgIH1cblxuICAgIHJldHVybiBpbmRleGVzVG87XG4gIH1cbn1cbiJdLCJuYW1lcyI6WyJfIiwiZXF1YWwiLCJDb2RlR2VuZXJhdG9yIiwiZ2V0QWx0ZXJDb2x1bW5zVG8iLCJlbnRpdHlDb2x1bW5zIiwiZGJDb2x1bW5zIiwiY29sdW1uc1RvIiwiYWRkIiwiZHJvcCIsImFsdGVyIiwiZXh0cmFDb2x1bW5zIiwiZGIiLCJkaWZmZXJlbmNlQnkiLCJjb2wiLCJuYW1lIiwiZW50aXR5IiwibGVuZ3RoIiwiY29uY2F0Iiwic2FtZURiQ29sdW1ucyIsImludGVyc2VjdGlvbkJ5Iiwic2FtZU1kQ29sdW1ucyIsImRpZmZlcmVuY2VXaXRoIiwiYSIsImIiLCJnZXRBbHRlckluZGV4ZXNUbyIsImVudGl0eUluZGV4ZXMiLCJkYkluZGV4ZXMiLCJpbmRleGVzVG8iLCJleHRyYUluZGV4ZXMiLCJ0eXBlIiwiY29sdW1ucyIsImpvaW4iXSwibWFwcGluZ3MiOiJBQUFBLFlBQVlBLE9BQU8sWUFBWTtBQUMvQixPQUFPQyxXQUFXLGtCQUFrQjtBQUdwQyxPQUFPLE1BQU1DO0lBQ1hDLGtCQUNFQyxhQUFnQyxFQUNoQ0MsU0FBNEIsRUFDNUI7UUFDQSxNQUFNQyxZQUFZO1lBQ2hCQyxLQUFLLEVBQUU7WUFDUEMsTUFBTSxFQUFFO1lBQ1JDLE9BQU8sRUFBRTtRQUNYO1FBRUEsWUFBWTtRQUNaLE1BQU1DLGVBQWU7WUFDbkJDLElBQUlYLEVBQUVZLFlBQVksQ0FBQ1AsV0FBV0QsZUFBZSxDQUFDUyxNQUFRQSxJQUFJQyxJQUFJO1lBQzlEQyxRQUFRZixFQUFFWSxZQUFZLENBQUNSLGVBQWVDLFdBQVcsQ0FBQ1EsTUFBUUEsSUFBSUMsSUFBSTtRQUNwRTtRQUNBLElBQUlKLGFBQWFLLE1BQU0sQ0FBQ0MsTUFBTSxHQUFHLEdBQUc7WUFDbENWLFVBQVVDLEdBQUcsR0FBR0QsVUFBVUMsR0FBRyxDQUFDVSxNQUFNLENBQUNQLGFBQWFLLE1BQU07UUFDMUQ7UUFDQSxJQUFJTCxhQUFhQyxFQUFFLENBQUNLLE1BQU0sR0FBRyxHQUFHO1lBQzlCVixVQUFVRSxJQUFJLEdBQUdGLFVBQVVFLElBQUksQ0FBQ1MsTUFBTSxDQUFDUCxhQUFhQyxFQUFFO1FBQ3hEO1FBRUEsbUJBQW1CO1FBQ25CLE1BQU1PLGdCQUFnQmxCLEVBQUVtQixjQUFjLENBQ3BDZCxXQUNBRCxlQUNBLENBQUNTLE1BQVFBLElBQUlDLElBQUk7UUFFbkIsTUFBTU0sZ0JBQWdCcEIsRUFBRW1CLGNBQWMsQ0FDcENmLGVBQ0FDLFdBQ0EsQ0FBQ1EsTUFBUUEsSUFBSUMsSUFBSTtRQUVuQlIsVUFBVUcsS0FBSyxHQUFHVCxFQUFFcUIsY0FBYyxDQUFDSCxlQUFlRSxlQUFlLENBQUNFLEdBQUdDLElBQ25FdEIsTUFBTXFCLEdBQUdDO1FBR1gsT0FBT2pCO0lBQ1Q7SUFFQWtCLGtCQUNFQyxhQUErQixFQUMvQkMsU0FBMkIsRUFDM0I7UUFDQSxTQUFTO1FBQ1QsSUFBSUMsWUFBWTtZQUNkcEIsS0FBSyxFQUFFO1lBQ1BDLE1BQU0sRUFBRTtRQUNWO1FBQ0EsTUFBTW9CLGVBQWU7WUFDbkJqQixJQUFJWCxFQUFFWSxZQUFZLENBQUNjLFdBQVdELGVBQWUsQ0FBQ1osTUFDNUM7b0JBQUNBLElBQUlnQixJQUFJO29CQUFFaEIsSUFBSWlCLE9BQU8sQ0FBQ0MsSUFBSSxDQUFDO2lCQUFLLENBQUNBLElBQUksQ0FBQztZQUV6Q2hCLFFBQVFmLEVBQUVZLFlBQVksQ0FBQ2EsZUFBZUMsV0FBVyxDQUFDYixNQUNoRDtvQkFBQ0EsSUFBSWdCLElBQUk7b0JBQUVoQixJQUFJaUIsT0FBTyxDQUFDQyxJQUFJLENBQUM7aUJBQUssQ0FBQ0EsSUFBSSxDQUFDO1FBRTNDO1FBQ0EsSUFBSUgsYUFBYWIsTUFBTSxDQUFDQyxNQUFNLEdBQUcsR0FBRztZQUNsQ1csVUFBVXBCLEdBQUcsR0FBR29CLFVBQVVwQixHQUFHLENBQUNVLE1BQU0sQ0FBQ1csYUFBYWIsTUFBTTtRQUMxRDtRQUNBLElBQUlhLGFBQWFqQixFQUFFLENBQUNLLE1BQU0sR0FBRyxHQUFHO1lBQzlCVyxVQUFVbkIsSUFBSSxHQUFHbUIsVUFBVW5CLElBQUksQ0FBQ1MsTUFBTSxDQUFDVyxhQUFhakIsRUFBRTtRQUN4RDtRQUVBLE9BQU9nQjtJQUNUO0FBQ0YifQ==
|
package/dist/database/db.d.ts
CHANGED
|
@@ -2,20 +2,7 @@ export type DBPreset = "w" | "r";
|
|
|
2
2
|
import { Knex } from "knex";
|
|
3
3
|
import { AsyncLocalStorage } from "async_hooks";
|
|
4
4
|
import { TransactionContext } from "./transaction-context";
|
|
5
|
-
|
|
6
|
-
connection?: Knex.MySql2ConnectionConfig;
|
|
7
|
-
};
|
|
8
|
-
export type SonamuDBBaseConfig = {
|
|
9
|
-
database: string;
|
|
10
|
-
defaultOptions?: MySQLConfig;
|
|
11
|
-
environments?: {
|
|
12
|
-
development?: MySQLConfig;
|
|
13
|
-
development_slave?: MySQLConfig;
|
|
14
|
-
production?: MySQLConfig;
|
|
15
|
-
production_slave?: MySQLConfig;
|
|
16
|
-
remote_fixture?: MySQLConfig;
|
|
17
|
-
};
|
|
18
|
-
};
|
|
5
|
+
import { SonamuConfig } from "../api/config";
|
|
19
6
|
export type SonamuDBConfig = {
|
|
20
7
|
development_master: Knex.Config;
|
|
21
8
|
development_slave: Knex.Config;
|
|
@@ -31,10 +18,9 @@ declare class DBClass {
|
|
|
31
18
|
transactionStorage: AsyncLocalStorage<TransactionContext>;
|
|
32
19
|
runWithTransaction<T>(callback: () => Promise<T>): Promise<T>;
|
|
33
20
|
getTransactionContext(): TransactionContext;
|
|
34
|
-
readKnexfile(): Promise<SonamuDBConfig>;
|
|
35
21
|
getDB(which: DBPreset): Knex;
|
|
36
22
|
destroy(): Promise<void>;
|
|
37
|
-
|
|
23
|
+
generateDBConfig(config: SonamuConfig["database"]): SonamuDBConfig;
|
|
38
24
|
testTransaction: Knex.Transaction | null;
|
|
39
25
|
createTestTransaction(): Promise<Knex.Transaction>;
|
|
40
26
|
clearTestTransaction(): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/database/db.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,GAAG,GAAG,GAAG,CAAC;AACjC,OAAa,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/database/db.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,GAAG,GAAG,GAAG,CAAC;AACjC,OAAa,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAGlC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAkB,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7D,MAAM,MAAM,cAAc,GAAG;IAC3B,kBAAkB,EAAE,IAAI,CAAC,MAAM,CAAC;IAChC,iBAAiB,EAAE,IAAI,CAAC,MAAM,CAAC;IAC/B,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC;IAClB,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC;IAC3B,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC;IAC5B,iBAAiB,EAAE,IAAI,CAAC,MAAM,CAAC;IAC/B,gBAAgB,EAAE,IAAI,CAAC,MAAM,CAAC;CAC/B,CAAC;AAEF,cAAM,OAAO;IACX,OAAO,CAAC,GAAG,CAAC,CAAO;IACnB,OAAO,CAAC,GAAG,CAAC,CAAO;IAEZ,kBAAkB,wCAA+C;IAEjE,kBAAkB,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAI7D,qBAAqB,IAAI,kBAAkB;IAIlD,KAAK,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAoDtB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAWvB,gBAAgB,CAAC,MAAM,EAAE,YAAY,CAAC,UAAU,CAAC,GAAG,cAAc;IAgFlE,eAAe,EAAE,IAAI,CAAC,WAAW,GAAG,IAAI,CAAQ;IACjD,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC;IAKlD,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC;CAI5C;AACD,eAAO,MAAM,EAAE,SAAgB,CAAC"}
|