sonamu 0.5.7 → 0.7.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/.swcrc.project-default +18 -0
- package/bin/cli.js +24 -0
- package/dist/ai/agents/agent.d.ts +11 -0
- package/dist/ai/agents/agent.d.ts.map +1 -0
- package/dist/ai/agents/agent.js +65 -0
- package/dist/ai/agents/index.d.ts +3 -0
- package/dist/ai/agents/index.d.ts.map +1 -0
- package/dist/ai/agents/index.js +4 -0
- package/dist/ai/agents/types.d.ts +43 -0
- package/dist/ai/agents/types.d.ts.map +1 -0
- package/dist/ai/agents/types.js +3 -0
- package/dist/ai/index.d.ts +2 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +3 -0
- package/dist/ai/providers/rtzr/api.d.ts +22 -0
- package/dist/ai/providers/rtzr/api.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/api.js +28 -0
- package/dist/ai/providers/rtzr/error.d.ts +18 -0
- package/dist/ai/providers/rtzr/error.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/error.js +29 -0
- package/dist/ai/providers/rtzr/index.d.ts +5 -0
- package/dist/ai/providers/rtzr/index.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/index.js +6 -0
- package/dist/ai/providers/rtzr/model.d.ts +52 -0
- package/dist/ai/providers/rtzr/model.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/model.js +137 -0
- package/dist/ai/providers/rtzr/options.d.ts +7 -0
- package/dist/ai/providers/rtzr/options.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/options.js +47 -0
- package/dist/ai/providers/rtzr/provider.d.ts +18 -0
- package/dist/ai/providers/rtzr/provider.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/provider.js +54 -0
- package/dist/ai/providers/rtzr/utils.d.ts +19 -0
- package/dist/ai/providers/rtzr/utils.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/utils.js +88 -0
- package/dist/api/base-frame.d.ts +2 -2
- package/dist/api/base-frame.d.ts.map +1 -1
- package/dist/api/base-frame.js +13 -2
- package/dist/api/caster.d.ts.map +1 -1
- package/dist/api/caster.js +71 -2
- package/dist/api/code-converters.d.ts +58 -14
- package/dist/api/code-converters.d.ts.map +1 -1
- package/dist/api/code-converters.js +258 -2
- package/dist/api/config.d.ts +90 -0
- package/dist/api/config.d.ts.map +1 -0
- package/dist/api/config.js +25 -0
- package/dist/api/context.d.ts +4 -2
- package/dist/api/context.d.ts.map +1 -1
- package/dist/api/context.js +3 -2
- package/dist/api/decorators.d.ts +20 -6
- package/dist/api/decorators.d.ts.map +1 -1
- package/dist/api/decorators.js +235 -2
- package/dist/api/index.d.ts +2 -2
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +9 -2
- package/dist/api/sonamu.d.ts +10 -24
- package/dist/api/sonamu.d.ts.map +1 -1
- package/dist/api/sonamu.js +514 -2
- package/dist/api/validator.d.ts +6 -0
- package/dist/api/validator.d.ts.map +1 -0
- package/dist/api/validator.js +81 -0
- package/dist/bin/build-config.d.ts +6 -1
- package/dist/bin/build-config.d.ts.map +1 -1
- package/dist/bin/build-config.js +15 -2
- package/dist/bin/cli.js +519 -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/bin/loader-register.d.ts +2 -0
- package/dist/bin/loader-register.d.ts.map +1 -0
- package/dist/bin/loader-register.js +34 -0
- package/dist/database/_batch_update.d.ts +5 -3
- package/dist/database/_batch_update.d.ts.map +1 -1
- package/dist/database/_batch_update.js +95 -2
- package/dist/database/base-model.d.ts +96 -10
- package/dist/database/base-model.d.ts.map +1 -1
- package/dist/database/base-model.js +390 -2
- package/dist/database/base-model.types.d.ts +93 -0
- package/dist/database/base-model.types.d.ts.map +1 -0
- package/dist/database/base-model.types.js +10 -0
- package/dist/database/code-generator.d.ts +1 -1
- package/dist/database/code-generator.d.ts.map +1 -1
- package/dist/database/code-generator.js +54 -2
- package/dist/database/db.d.ts +6 -21
- package/dist/database/db.d.ts.map +1 -1
- package/dist/database/db.js +129 -2
- package/dist/database/puri-subset.test-d.js +81 -0
- package/dist/database/puri-subset.types.d.ts +123 -0
- package/dist/database/puri-subset.types.d.ts.map +1 -0
- package/dist/database/puri-subset.types.js +16 -0
- package/dist/database/puri-wrapper.d.ts +13 -11
- package/dist/database/puri-wrapper.d.ts.map +1 -1
- package/dist/database/puri-wrapper.js +109 -2
- package/dist/database/puri.d.ts +41 -23
- package/dist/database/puri.d.ts.map +1 -1
- package/dist/database/puri.js +601 -2
- package/dist/database/puri.types.d.ts +25 -6
- package/dist/database/puri.types.d.ts.map +1 -1
- package/dist/database/puri.types.js +6 -2
- package/dist/database/transaction-context.d.ts +1 -1
- package/dist/database/transaction-context.d.ts.map +1 -1
- package/dist/database/transaction-context.js +14 -2
- package/dist/database/upsert-builder.d.ts +9 -3
- package/dist/database/upsert-builder.d.ts.map +1 -1
- package/dist/database/upsert-builder.js +365 -2
- package/dist/entity/entity-manager.d.ts +167 -2
- package/dist/entity/entity-manager.d.ts.map +1 -1
- package/dist/entity/entity-manager.js +130 -2
- package/dist/entity/entity.d.ts +5 -3
- package/dist/entity/entity.d.ts.map +1 -1
- package/dist/entity/entity.js +750 -2
- package/dist/exceptions/error-handler.d.ts +1 -1
- package/dist/exceptions/error-handler.d.ts.map +1 -1
- package/dist/exceptions/error-handler.js +29 -2
- package/dist/exceptions/so-exceptions.d.ts +1 -1
- package/dist/exceptions/so-exceptions.d.ts.map +1 -1
- package/dist/exceptions/so-exceptions.js +85 -2
- package/dist/file-storage/driver.d.ts +1 -1
- package/dist/file-storage/driver.d.ts.map +1 -1
- package/dist/file-storage/driver.js +79 -2
- package/dist/file-storage/file-storage.js +75 -2
- package/dist/index.d.ts +18 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +34 -2
- package/dist/migration/code-generation.d.ts +1 -1
- package/dist/migration/code-generation.d.ts.map +1 -1
- package/dist/migration/code-generation.js +614 -2
- package/dist/migration/migration-set.d.ts +2 -10
- package/dist/migration/migration-set.d.ts.map +1 -1
- package/dist/migration/migration-set.js +213 -2
- package/dist/migration/migrator.d.ts +24 -82
- package/dist/migration/migrator.d.ts.map +1 -1
- package/dist/migration/migrator.js +330 -2
- package/dist/migration/postgresql-schema-reader.d.ts +51 -0
- package/dist/migration/postgresql-schema-reader.d.ts.map +1 -0
- package/dist/migration/postgresql-schema-reader.js +245 -0
- package/dist/migration/types.d.ts +6 -38
- package/dist/migration/types.d.ts.map +1 -1
- package/dist/migration/types.js +3 -2
- package/dist/naite/messaging-types.d.ts +43 -0
- package/dist/naite/messaging-types.d.ts.map +1 -0
- package/dist/naite/messaging-types.js +7 -0
- package/dist/naite/naite-reporter.d.ts +41 -0
- package/dist/naite/naite-reporter.d.ts.map +1 -0
- package/dist/naite/naite-reporter.js +102 -0
- package/dist/naite/naite.d.ts +95 -0
- package/dist/naite/naite.d.ts.map +1 -0
- package/dist/naite/naite.js +316 -0
- package/dist/stream/index.js +3 -2
- package/dist/stream/sse.d.ts +2 -2
- package/dist/stream/sse.d.ts.map +1 -1
- package/dist/stream/sse.js +38 -2
- package/dist/syncer/api-parser.d.ts +10 -0
- package/dist/syncer/api-parser.d.ts.map +1 -0
- package/dist/syncer/api-parser.js +240 -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 +161 -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 +59 -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 +87 -0
- package/dist/syncer/syncer.d.ts +98 -106
- package/dist/syncer/syncer.d.ts.map +1 -1
- package/dist/syncer/syncer.js +422 -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 +108 -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 +86 -0
- package/dist/{templates → template/implementations}/generated.template.d.ts +3 -4
- package/dist/template/implementations/generated.template.d.ts.map +1 -0
- package/dist/template/implementations/generated.template.js +249 -0
- package/dist/{templates → template/implementations}/generated_http.template.d.ts +3 -4
- 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 +4 -5
- package/dist/template/implementations/generated_sso.template.d.ts.map +1 -0
- package/dist/template/implementations/generated_sso.template.js +134 -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 +181 -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 +201 -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 +475 -0
- package/dist/template/implementations/view_list_columns.template.d.ts +17 -0
- 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 +7 -0
- package/dist/template/index.d.ts.map +1 -0
- package/dist/template/index.js +8 -0
- package/dist/template/template-manager.d.ts +56 -0
- package/dist/template/template-manager.d.ts.map +1 -0
- package/dist/template/template-manager.js +125 -0
- package/dist/template/template-types.d.ts +16 -0
- package/dist/template/template-types.d.ts.map +1 -0
- package/dist/template/template-types.js +7 -0
- package/dist/template/template.d.ts +49 -0
- package/dist/template/template.d.ts.map +1 -0
- package/dist/template/template.js +60 -0
- package/dist/template/zod-converter.d.ts +51 -0
- package/dist/template/zod-converter.d.ts.map +1 -0
- package/dist/template/zod-converter.js +449 -0
- package/dist/testing/_relation-graph.d.ts +1 -1
- package/dist/testing/_relation-graph.d.ts.map +1 -1
- package/dist/testing/_relation-graph.js +89 -2
- package/dist/testing/fixture-manager.d.ts +42 -11
- package/dist/testing/fixture-manager.d.ts.map +1 -1
- package/dist/testing/fixture-manager.js +623 -2
- package/dist/types/types.d.ts +747 -143
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/types.js +546 -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.d.ts +1 -0
- package/dist/utils/controller.d.ts.map +1 -1
- package/dist/utils/controller.js +29 -2
- package/dist/utils/esm-utils.d.ts +39 -0
- package/dist/utils/esm-utils.d.ts.map +1 -0
- package/dist/utils/esm-utils.js +49 -0
- package/dist/utils/formatter.d.ts +3 -0
- package/dist/utils/formatter.d.ts.map +1 -0
- package/dist/utils/formatter.js +110 -0
- package/dist/utils/fs-utils.d.ts +1 -1
- package/dist/utils/fs-utils.d.ts.map +1 -1
- package/dist/utils/fs-utils.js +17 -2
- package/dist/utils/lodash-able.d.ts.map +1 -1
- package/dist/utils/lodash-able.js +6 -2
- package/dist/utils/model.js +22 -2
- package/dist/utils/object-utils.d.ts +44 -0
- package/dist/utils/object-utils.d.ts.map +1 -0
- package/dist/utils/object-utils.js +191 -0
- 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.d.ts +5 -1
- package/dist/utils/sql-parser.d.ts.map +1 -1
- package/dist/utils/sql-parser.js +46 -2
- package/dist/utils/type-utils.d.ts +23 -0
- package/dist/utils/type-utils.d.ts.map +1 -0
- package/dist/utils/type-utils.js +45 -0
- package/dist/utils/utils.d.ts +10 -7
- package/dist/utils/utils.d.ts.map +1 -1
- package/dist/utils/utils.js +72 -2
- package/dist/utils/zod-error.d.ts +1 -1
- package/dist/utils/zod-error.d.ts.map +1 -1
- package/dist/utils/zod-error.js +19 -2
- package/package.json +65 -27
- package/src/ai/agents/agent.ts +87 -0
- package/src/ai/agents/index.ts +2 -0
- package/src/ai/agents/types.ts +47 -0
- package/src/ai/index.ts +1 -0
- package/src/ai/providers/rtzr/api.ts +37 -0
- package/src/ai/providers/rtzr/error.ts +34 -0
- package/src/ai/providers/rtzr/index.ts +4 -0
- package/src/ai/providers/rtzr/model.ts +201 -0
- package/src/ai/providers/rtzr/options.ts +49 -0
- package/src/ai/providers/rtzr/provider.ts +91 -0
- package/src/ai/providers/rtzr/utils.ts +127 -0
- package/src/api/base-frame.ts +4 -2
- package/src/api/caster.ts +17 -23
- package/src/api/code-converters.ts +178 -535
- package/src/api/config.ts +125 -0
- package/src/api/context.ts +7 -17
- package/src/api/decorators.ts +176 -46
- package/src/api/index.ts +2 -2
- package/src/api/sonamu.ts +190 -167
- package/src/api/validator.ts +83 -0
- package/src/bin/build-config.ts +8 -1
- package/src/bin/cli.ts +258 -124
- package/src/bin/hot-hook-register.ts +22 -0
- package/src/bin/loader-register.ts +38 -0
- package/src/database/_batch_update.ts +46 -31
- package/src/database/base-model.ts +390 -182
- package/src/database/base-model.types.ts +155 -0
- package/src/database/code-generator.ts +13 -32
- package/src/database/db.ts +40 -96
- package/src/database/puri-subset.test-d.ts +471 -0
- package/src/database/puri-subset.types.ts +195 -0
- package/src/database/puri-wrapper.ts +58 -67
- package/src/database/puri.ts +229 -148
- package/src/database/puri.types.ts +76 -30
- package/src/database/transaction-context.ts +1 -1
- package/src/database/upsert-builder.ts +262 -132
- package/src/entity/entity-manager.ts +48 -36
- package/src/entity/entity.ts +330 -248
- package/src/exceptions/error-handler.ts +3 -3
- package/src/exceptions/so-exceptions.ts +11 -11
- package/src/file-storage/driver.ts +5 -5
- package/src/file-storage/file-storage.ts +2 -2
- package/src/index.ts +18 -10
- package/src/migration/code-generation.ts +185 -172
- package/src/migration/migration-set.ts +80 -293
- package/src/migration/migrator.ts +199 -571
- package/src/migration/mysql-schema-reader.ts.txt +272 -0
- package/src/migration/postgresql-schema-reader.ts +310 -0
- package/src/migration/types.ts +6 -39
- package/src/naite/messaging-types.ts +51 -0
- package/src/naite/naite-reporter.ts +128 -0
- package/src/naite/naite.ts +415 -0
- package/src/shared/web.shared.ts.txt +20 -24
- package/src/stream/sse.ts +5 -5
- package/src/syncer/api-parser.ts +282 -0
- package/src/syncer/checksum.ts +140 -0
- package/src/syncer/code-generator.ts +198 -0
- package/src/syncer/entity-operations.ts +65 -0
- package/src/syncer/file-patterns.ts +56 -0
- package/src/syncer/index.ts +6 -0
- package/src/syncer/module-loader.ts +128 -0
- package/src/syncer/syncer.ts +389 -1453
- package/src/template/entity-converter.ts +114 -0
- package/src/template/helpers.ts +81 -0
- package/src/{templates → template/implementations}/entity.template.ts +7 -7
- package/src/{templates → template/implementations}/generated.template.ts +101 -101
- package/src/{templates → template/implementations}/generated_http.template.ts +27 -57
- package/src/template/implementations/generated_sso.template.ts +151 -0
- package/src/{templates → template/implementations}/init_types.template.ts +5 -7
- package/src/{templates → template/implementations}/model.template.ts +52 -43
- package/src/{templates → template/implementations}/model_test.template.ts +5 -5
- package/src/{templates → template/implementations}/service.template.ts +66 -82
- package/src/{templates → template/implementations}/view_enums_buttonset.template.ts +3 -3
- package/src/{templates → template/implementations}/view_enums_dropdown.template.ts +4 -20
- package/src/{templates → template/implementations}/view_enums_select.template.ts +4 -4
- package/src/{templates → template/implementations}/view_form.template.ts +40 -83
- package/src/{templates → template/implementations}/view_id_all_select.template.ts +3 -3
- package/src/{templates → template/implementations}/view_id_async_select.template.ts +10 -24
- package/src/{templates → template/implementations}/view_list.template.ts +60 -152
- package/src/{templates → template/implementations}/view_list_columns.template.ts +5 -11
- package/src/{templates → template/implementations}/view_search_input.template.ts +3 -3
- package/src/template/index.ts +6 -0
- package/src/template/template-manager.ts +166 -0
- package/src/template/template-types.ts +16 -0
- package/src/template/template.ts +105 -0
- package/src/template/zod-converter.ts +525 -0
- package/src/testing/_relation-graph.ts +18 -11
- package/src/testing/fixture-manager.ts +472 -359
- package/src/types/types.ts +553 -308
- package/src/typings/knex.d.ts +7 -9
- package/src/utils/async-utils.ts +23 -10
- package/src/utils/console-util.ts +4 -0
- package/src/utils/controller.ts +3 -0
- package/src/utils/esm-utils.ts +59 -0
- package/src/utils/formatter.ts +109 -0
- package/src/utils/fs-utils.ts +1 -1
- package/src/utils/lodash-able.ts +1 -4
- package/src/utils/object-utils.ts +217 -0
- package/src/utils/path-utils.ts +99 -0
- package/src/utils/process-utils.ts +46 -0
- package/src/utils/sql-parser.ts +23 -5
- package/src/utils/type-utils.ts +83 -0
- package/src/utils/utils.ts +66 -43
- package/src/utils/zod-error.ts +3 -4
- 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.d.ts +0 -3
- package/dist/bin/cli-wrapper.d.ts.map +0 -1
- package/dist/bin/cli-wrapper.js +0 -3
- 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.d.ts +0 -2
- package/dist/database/knex-plugins/knex-on-duplicate-update.d.ts.map +0 -1
- package/dist/database/knex-plugins/knex-on-duplicate-update.js +0 -2
- 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.d.ts +0 -61
- package/dist/entity/entity-utils.d.ts.map +0 -1
- package/dist/entity/entity-utils.js +0 -2
- 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 +0 -17
- 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/bin/cli-wrapper.ts +0 -75
- package/src/database/knex-plugins/knex-on-duplicate-update.ts +0 -45
- package/src/entity/entity-utils.ts +0 -291
- package/src/templates/base-template.ts +0 -19
- package/src/templates/generated_sso.template.ts +0 -138
- package/src/templates/index.ts +0 -1
|
@@ -1,2 +1,330 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:true});Object.defineProperty(exports,"Migrator",{enumerable:true,get:function(){return Migrator}});var _lodash=/*#__PURE__*/_interop_require_default(require("lodash"));var _knex=/*#__PURE__*/_interop_require_default(require("knex"));var _chalk=/*#__PURE__*/_interop_require_default(require("chalk"));var _luxon=require("luxon");var _promises=require("fs/promises");var _fsutils=require("../utils/fs-utils");var _prompts=/*#__PURE__*/_interop_require_default(require("prompts"));var _child_process=require("child_process");var _path=/*#__PURE__*/_interop_require_default(require("path"));var _entitymanager=require("../entity/entity-manager");var _api=require("../api");var _soexceptions=require("../exceptions/so-exceptions");var _codegeneration=require("./code-generation");var _migrationset=require("./migration-set");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_with_holes(arr){if(Array.isArray(arr))return arr}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 _iterable_to_array_limit(arr,i){var _i=arr==null?null:typeof Symbol!=="undefined"&&arr[Symbol.iterator]||arr["@@iterator"];if(_i==null)return;var _arr=[];var _n=true;var _d=false;var _s,_e;try{for(_i=_i.call(arr);!(_n=(_s=_i.next()).done);_n=true){_arr.push(_s.value);if(i&&_arr.length===i)break}}catch(err){_d=true;_e=err}finally{try{if(!_n&&_i["return"]!=null)_i["return"]()}finally{if(_d)throw _e}}return _arr}function _non_iterable_rest(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}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 _object_spread(target){for(var i=1;i<arguments.length;i++){var source=arguments[i]!=null?arguments[i]:{};var ownKeys=Object.keys(source);if(typeof Object.getOwnPropertySymbols==="function"){ownKeys=ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym){return Object.getOwnPropertyDescriptor(source,sym).enumerable}))}ownKeys.forEach(function(key){_define_property(target,key,source[key])})}return target}function ownKeys(object,enumerableOnly){var keys=Object.keys(object);if(Object.getOwnPropertySymbols){var symbols=Object.getOwnPropertySymbols(object);if(enumerableOnly){symbols=symbols.filter(function(sym){return Object.getOwnPropertyDescriptor(object,sym).enumerable})}keys.push.apply(keys,symbols)}return keys}function _object_spread_props(target,source){source=source!=null?source:{};if(Object.getOwnPropertyDescriptors){Object.defineProperties(target,Object.getOwnPropertyDescriptors(source))}else{ownKeys(Object(source)).forEach(function(key){Object.defineProperty(target,key,Object.getOwnPropertyDescriptor(source,key))})}return target}function _sliced_to_array(arr,i){return _array_with_holes(arr)||_iterable_to_array_limit(arr,i)||_unsupported_iterable_to_array(arr,i)||_non_iterable_rest()}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}}}var Migrator=/*#__PURE__*/function(){"use strict";function Migrator(options){_class_call_check(this,Migrator);_define_property(this,"options",void 0);_define_property(this,"targets",void 0);this.options=options;var dbConfig=_api.Sonamu.dbConfig;if(this.options.mode==="dev"){var devDB=(0,_knex.default)(dbConfig.development_master);var testDB=(0,_knex.default)(dbConfig.test);var fixtureLocalDB=(0,_knex.default)(dbConfig.fixture_local);var applyDBs=[devDB,testDB,fixtureLocalDB];if(dbConfig.fixture_local.connection.host!==dbConfig.fixture_remote.connection.host||dbConfig.fixture_local.connection.database!==dbConfig.fixture_remote.connection.database){var fixtureRemoteDB=(0,_knex.default)(dbConfig.fixture_remote);applyDBs.push(fixtureRemoteDB)}this.targets={compare:devDB,pending:devDB,shadow:testDB,apply:applyDBs}}else if(this.options.mode==="deploy"){var productionDB=(0,_knex.default)(dbConfig.production_master);var testDB1=(0,_knex.default)(dbConfig.test);this.targets={pending:productionDB,shadow:testDB1,apply:[productionDB]}}else{throw new Error("잘못된 모드 ".concat(this.options.mode," 입력"))}}_create_class(Migrator,[{key:"getMigrationCodes",value:function getMigrationCodes(){return _async_to_generator(function(){var srcMigrationsDir,distMigrationsDir,srcMigrations,distMigrations,normal,onlyTs,onlyJs;return _ts_generator(this,function(_state){switch(_state.label){case 0:srcMigrationsDir="".concat(_api.Sonamu.apiRootPath,"/src/migrations");distMigrationsDir="".concat(_api.Sonamu.apiRootPath,"/dist/migrations");return[4,(0,_fsutils.exists)(srcMigrationsDir)];case 1:if(!!_state.sent())return[3,3];return[4,(0,_promises.mkdir)(srcMigrationsDir,{recursive:true})];case 2:_state.sent();_state.label=3;case 3:return[4,(0,_fsutils.exists)(distMigrationsDir)];case 4:if(!!_state.sent())return[3,6];return[4,(0,_promises.mkdir)(distMigrationsDir,{recursive:true})];case 5:_state.sent();_state.label=6;case 6:return[4,(0,_promises.readdir)(srcMigrationsDir)];case 7:srcMigrations=_state.sent().filter(function(f){return f.endsWith(".ts")}).map(function(f){return f.split(".")[0]});return[4,(0,_promises.readdir)(distMigrationsDir)];case 8:distMigrations=_state.sent().filter(function(f){return f.endsWith(".js")}).map(function(f){return f.split(".")[0]});normal=_lodash.default.intersection(srcMigrations,distMigrations).map(function(filename){return{name:filename,path:_path.default.join(srcMigrationsDir,filename)+".ts"}}).sort(function(a,b){return a>b?1:-1});onlyTs=_lodash.default.difference(srcMigrations,distMigrations).map(function(filename){return{name:filename,path:_path.default.join(srcMigrationsDir,filename)+".ts"}});onlyJs=_lodash.default.difference(distMigrations,srcMigrations).map(function(filename){return{name:filename,path:_path.default.join(distMigrationsDir,filename)+".js"}});return[2,{normal:normal,onlyTs:onlyTs,onlyJs:onlyJs}]}})})()}},{key:"getStatus",value:function getStatus(){return _async_to_generator(function(){var _this,_ref,normal,onlyTs,onlyJs,connKeys,statuses,preparedCodes;return _ts_generator(this,function(_state){switch(_state.label){case 0:_this=this;return[4,this.getMigrationCodes()];case 1:_ref=_state.sent(),normal=_ref.normal,onlyTs=_ref.onlyTs,onlyJs=_ref.onlyJs;if(onlyTs.length>0){console.debug({onlyTs:onlyTs});throw new _soexceptions.ServiceUnavailableException("There are un-compiled TS migration files.\nPlease compile them first. You might want to run a development server with HMR.\n\n".concat(onlyTs.map(function(f){return f.name}).join("\n")))}if(!(onlyJs.length>0))return[3,3];console.debug({onlyJs:onlyJs});return[4,Promise.all(onlyJs.map(function(f){return _async_to_generator(function(){return _ts_generator(this,function(_state){(0,_child_process.execSync)("rm -f ".concat(f.path.replace("/src/","/dist/").replace(".ts",".js")));return[2]})})()}))];case 2:_state.sent();_state.label=3;case 3:connKeys=Object.keys(_api.Sonamu.dbConfig).filter(function(key){return key.endsWith("_slave")===false});return[4,Promise.all(connKeys.map(function(connKey){return _async_to_generator(function(){var knexOptions,tConn,status,pending,currentVersion,connection,_connection_user;return _ts_generator(this,function(_state){switch(_state.label){case 0:knexOptions=_api.Sonamu.dbConfig[connKey];tConn=(0,_knex.default)(knexOptions);return[4,function(){return _async_to_generator(function(){var err;return _ts_generator(this,function(_state){switch(_state.label){case 0:_state.trys.push([0,2,,3]);return[4,tConn.migrate.status()];case 1:return[2,_state.sent()];case 2:err=_state.sent();console.warn(_chalk.default.yellow("".concat(connKey,"의 마이그레이션 상태를 가져오는 데에 실패하였습니다. 데이터베이스가 올바르게 구성되지 않은 것 같습니다. 확인하시고 다시 시도해주세요.\n시도한 연결 설정:\n").concat(JSON.stringify(knexOptions.connection,null,2),"\n발생한 에러:\n").concat(err,"\n")));return[2,"error"];case 3:return[2]}})})()}()];case 1:status=_state.sent();return[4,function(){return _async_to_generator(function(){var _ref,fdList,err;return _ts_generator(this,function(_state){switch(_state.label){case 0:_state.trys.push([0,2,,3]);return[4,tConn.migrate.list()];case 1:_ref=_sliced_to_array.apply(void 0,[_state.sent(),2]),fdList=_ref[1];return[2,fdList.map(function(fd){return fd.file.replace(".js","")})];case 2:err=_state.sent();return[2,[]];case 3:return[2]}})})()}()];case 2:pending=_state.sent();return[4,function(){return _async_to_generator(function(){var err;return _ts_generator(this,function(_state){switch(_state.label){case 0:_state.trys.push([0,2,,3]);return[4,tConn.migrate.currentVersion()];case 1:return[2,_state.sent()];case 2:err=_state.sent();return[2,"error"];case 3:return[2]}})})()}()];case 3:currentVersion=_state.sent();connection=knexOptions.connection;return[4,tConn.destroy()];case 4:_state.sent();return[2,{name:connKey.replace("_master",""),connKey:connKey,connString:"mysql2://".concat((_connection_user=connection.user)!==null&&_connection_user!==void 0?_connection_user:"","@").concat(connection.host,":").concat(connection.port,"/").concat(connection.database),currentVersion:currentVersion,status:status,pending:pending}]}})})()}))];case 4:statuses=_state.sent();return[4,function(){return _async_to_generator(function(){var status0conn,compareDBconn,genCodes;return _ts_generator(this,function(_state){switch(_state.label){case 0:status0conn=statuses.find(function(status){return status.status===0});if(status0conn===undefined){return[2,[]]}compareDBconn=(0,_knex.default)(_api.Sonamu.dbConfig[status0conn.connKey]);return[4,this.compareMigrations(compareDBconn)];case 1:genCodes=_state.sent();return[4,compareDBconn.destroy()];case 2:_state.sent();return[2,genCodes]}})}).call(_this)}()];case 5:preparedCodes=_state.sent();return[2,{conns:statuses,codes:normal,preparedCodes:preparedCodes}]}})}).call(this)}},{key:"runAction",value:function runAction(action,targets){return _async_to_generator(function(){var configs,conns,result;return _ts_generator(this,function(_state){switch(_state.label){case 0:configs=_lodash.default.uniqBy(targets.map(function(target){return{connKey:target,options:_api.Sonamu.dbConfig[target]}}).filter(function(c){return c.options!==undefined}),function(param){var options=param.options;var _options_connection_port;return"".concat(options.connection.host,":").concat((_options_connection_port=options.connection.port)!==null&&_options_connection_port!==void 0?_options_connection_port:3306,"/").concat(options.connection.database)});return[4,Promise.all(configs.map(function(config){return _async_to_generator(function(){return _ts_generator(this,function(_state){return[2,{connKey:config.connKey,knex:(0,_knex.default)(config.options)}]})})()}))];case 1:conns=_state.sent();return[4,function(){return _async_to_generator(function(){return _ts_generator(this,function(_state){switch(action){case"apply":return[2,Promise.all(conns.map(function(param){var connKey=param.connKey,knex=param.knex;return _async_to_generator(function(){var _ref,batchNo,applied;return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,knex.migrate.latest()];case 1:_ref=_sliced_to_array.apply(void 0,[_state.sent(),2]),batchNo=_ref[0],applied=_ref[1];return[2,{connKey:connKey,batchNo:batchNo,applied:applied}]}})})()}))];case"rollback":return[2,Promise.all(conns.map(function(param){var connKey=param.connKey,knex=param.knex;return _async_to_generator(function(){var _ref,batchNo,applied;return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,knex.migrate.rollback()];case 1:_ref=_sliced_to_array.apply(void 0,[_state.sent(),2]),batchNo=_ref[0],applied=_ref[1];return[2,{connKey:connKey,batchNo:batchNo,applied:applied}]}})})()}))]}return[2]})})()}()];case 2:result=_state.sent();return[4,Promise.all(conns.map(function(param){var knex=param.knex;return knex.destroy()}))];case 3:_state.sent();return[2,result]}})})()}},{key:"delCodes",value:function delCodes(codeNames){return _async_to_generator(function(){var conns,delFiles,res;return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,this.getStatus()];case 1:conns=_state.sent().conns;if(conns.some(function(conn){return codeNames.some(function(codeName){return conn.pending.includes(codeName)===false})})){throw new Error("You cannot delete a migration file if there is already applied.")}delFiles=codeNames.map(function(codeName){return["".concat(_api.Sonamu.apiRootPath,"/src/migrations/").concat(codeName,".ts"),"".concat(_api.Sonamu.apiRootPath,"/dist/migrations/").concat(codeName,".js")]}).flat();return[4,Promise.all(delFiles.map(function(delFile){return _async_to_generator(function(){return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,(0,_fsutils.exists)(delFile)];case 1:if(!_state.sent())return[3,3];console.log(_chalk.default.red("DELETE: ".concat(delFile)));return[4,(0,_promises.unlink)(delFile)];case 2:_state.sent();return[2,delFiles.includes(".ts")?1:0];case 3:return[2,0]}})})()}))];case 2:res=_state.sent();return[2,_lodash.default.sum(res)]}})}).call(this)}},{key:"generatePreparedCodes",value:function generatePreparedCodes(){return _async_to_generator(function(){var preparedCodes,migrationsDir,_iteratorNormalCompletion,_didIteratorError,_iteratorError,_iterator,_step,_step_value,index,pcode,dateTag,filePath,err;return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,this.getStatus()];case 1:preparedCodes=_state.sent().preparedCodes;if(preparedCodes.length===0){console.log(_chalk.default.green("\n현재 모두 싱크된 상태입니다."));return[2,0]}migrationsDir="".concat(_api.Sonamu.apiRootPath,"/src/migrations");_iteratorNormalCompletion=true,_didIteratorError=false,_iteratorError=undefined;_state.label=2;case 2:_state.trys.push([2,7,8,9]);_iterator=preparedCodes.entries()[Symbol.iterator]();_state.label=3;case 3:if(!!(_iteratorNormalCompletion=(_step=_iterator.next()).done))return[3,6];_step_value=_sliced_to_array(_step.value,2),index=_step_value[0],pcode=_step_value[1];if(!pcode.formatted)return[3,5];dateTag=_luxon.DateTime.local().plus({seconds:index}).toFormat("yyyyMMddHHmmss");filePath="".concat(migrationsDir,"/").concat(dateTag,"_").concat(pcode.title,".ts");return[4,(0,_promises.writeFile)(filePath,pcode.formatted)];case 4:_state.sent();console.log(_chalk.default.green("MIGRTAION CREATED ".concat(filePath)));_state.label=5;case 5:_iteratorNormalCompletion=true;return[3,3];case 6:return[3,9];case 7:err=_state.sent();_didIteratorError=true;_iteratorError=err;return[3,9];case 8:try{if(!_iteratorNormalCompletion&&_iterator.return!=null){_iterator.return()}}finally{if(_didIteratorError){throw _iteratorError}}return[7];case 9:return[2,preparedCodes.length]}})}).call(this)}},{key:"clearPendingList",value:function clearPendingList(){return _async_to_generator(function(){var _ref,pendingList,migrationsDir,delList,_iteratorNormalCompletion,_didIteratorError,_iteratorError,_iterator,_step,p,err;return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,this.targets.pending.migrate.list()];case 1:_ref=_sliced_to_array.apply(void 0,[_state.sent(),2]),pendingList=_ref[1];migrationsDir="".concat(_api.Sonamu.apiRootPath,"/src/migrations");delList=pendingList.map(function(df){return _path.default.join(migrationsDir,df.file).replace(".js",".ts")});_iteratorNormalCompletion=true,_didIteratorError=false,_iteratorError=undefined;_state.label=2;case 2:_state.trys.push([2,8,9,10]);_iterator=delList[Symbol.iterator]();_state.label=3;case 3:if(!!(_iteratorNormalCompletion=(_step=_iterator.next()).done))return[3,7];p=_step.value;return[4,(0,_fsutils.exists)(p)];case 4:if(!_state.sent())return[3,6];return[4,(0,_promises.unlink)(p)];case 5:_state.sent();_state.label=6;case 6:_iteratorNormalCompletion=true;return[3,3];case 7:return[3,10];case 8:err=_state.sent();_didIteratorError=true;_iteratorError=err;return[3,10];case 9:try{if(!_iteratorNormalCompletion&&_iterator.return!=null){_iterator.return()}}finally{if(_didIteratorError){throw _iteratorError}}return[7];case 10:return[4,this.cleanUpDist(true)];case 11:_state.sent();return[2]}})}).call(this)}},{key:"check",value:function check(){return _async_to_generator(function(){var codes;return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,this.compareMigrations(this.targets.compare)];case 1:codes=_state.sent();if(codes.length===0){console.log(_chalk.default.green("\n현재 모두 싱크된 상태입니다."));return[2]}console.table(codes,["type","title"]);console.log(codes[0]);return[2]}})}).call(this)}},{key:"run",value:function run(){return _async_to_generator(function(){var _ref,pendingList,answer,codes,answer1,migrationsDir,_iteratorNormalCompletion,_didIteratorError,_iteratorError,_iterator,_step,_step_value,index,code,dateTag,filePath,err;return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,this.targets.pending.migrate.list()];case 1:_ref=_sliced_to_array.apply(void 0,[_state.sent(),2]),pendingList=_ref[1];if(!(pendingList.length>0))return[3,5];console.log(_chalk.default.red("pending 된 마이그레이션이 존재합니다."),pendingList.map(function(pending){return pending.file}));return[4,(0,_prompts.default)({type:"confirm",name:"value",message:"Shadow DB 테스트를 진행하시겠습니까?",initial:true})];case 2:answer=_state.sent();if(answer.value===false){return[2]}console.time(_chalk.default.blue("Migrator - runShadowTest"));return[4,this.runShadowTest()];case 3:_state.sent();console.timeEnd(_chalk.default.blue("Migrator - runShadowTest"));return[4,Promise.all(this.targets.apply.map(function(applyDb){return _async_to_generator(function(){var label,_ref;return _ts_generator(this,function(_state){switch(_state.label){case 0:label=_chalk.default.green("APPLIED ".concat(applyDb.client.connectionSettings.host," ").concat(applyDb.client.database()));console.time(label);return[4,applyDb.migrate.latest()];case 1:_ref=_sliced_to_array.apply(void 0,[_state.sent(),1]);console.timeEnd(label);return[2]}})})()}))];case 4:_state.sent();_state.label=5;case 5:return[4,this.compareMigrations(this.targets.compare)];case 6:codes=_state.sent();if(codes.length===0){console.log(_chalk.default.green("\n현재 모두 싱크된 상태입니다."));return[2]}console.table(codes,["type","title"]);return[4,(0,_prompts.default)({type:"confirm",name:"value",message:"마이그레이션 코드를 생성하시겠습니까?",initial:false})];case 7:answer1=_state.sent();if(answer1.value===false){return[2]}migrationsDir="".concat(_api.Sonamu.apiRootPath,"/src/migrations");_iteratorNormalCompletion=true,_didIteratorError=false,_iteratorError=undefined;_state.label=8;case 8:_state.trys.push([8,13,14,15]);_iterator=codes.entries()[Symbol.iterator]();_state.label=9;case 9:if(!!(_iteratorNormalCompletion=(_step=_iterator.next()).done))return[3,12];_step_value=_sliced_to_array(_step.value,2),index=_step_value[0],code=_step_value[1];if(!code.formatted)return[3,11];dateTag=_luxon.DateTime.local().plus({seconds:index}).toFormat("yyyyMMddHHmmss");filePath="".concat(migrationsDir,"/").concat(dateTag,"_").concat(code.title,".ts");return[4,(0,_promises.writeFile)(filePath,code.formatted)];case 10:_state.sent();console.log(_chalk.default.green("MIGRTAION CREATED ".concat(filePath)));_state.label=11;case 11:_iteratorNormalCompletion=true;return[3,9];case 12:return[3,15];case 13:err=_state.sent();_didIteratorError=true;_iteratorError=err;return[3,15];case 14:try{if(!_iteratorNormalCompletion&&_iterator.return!=null){_iterator.return()}}finally{if(_didIteratorError){throw _iteratorError}}return[7];case 15:return[2]}})}).call(this)}},{key:"rollback",value:function rollback(){return _async_to_generator(function(){var rollbackAllResult;return _ts_generator(this,function(_state){switch(_state.label){case 0:console.time(_chalk.default.red("rollback:"));return[4,Promise.all(this.targets.apply.map(function(db){return _async_to_generator(function(){return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,db.migrate.forceFreeMigrationsLock()];case 1:_state.sent();return[2,db.migrate.rollback(undefined,false)]}})})()}))];case 1:rollbackAllResult=_state.sent();console.dir({rollbackAllResult:rollbackAllResult},{depth:null});console.timeEnd(_chalk.default.red("rollback:"));return[2]}})}).call(this)}},{key:"cleanUpDist",value:function cleanUpDist(){var force=arguments.length>0&&arguments[0]!==void 0?arguments[0]:false;return _async_to_generator(function(){var files,_tmp,diffOnSrc,diffOnDist,answer,filesToRm,_iteratorNormalCompletion,_didIteratorError,_iteratorError,_iterator,_step,filePath,err;function getFilesUnder(dir){return _async_to_generator(function(){var migrationPath;return _ts_generator(this,function(_state){switch(_state.label){case 0:migrationPath=_path.default.join(_api.Sonamu.apiRootPath,dir,"migrations");return[4,(0,_fsutils.exists)(migrationPath)];case 1:if(!!_state.sent())return[3,3];return[4,(0,_promises.mkdir)(migrationPath,{recursive:true})];case 2:_state.sent();_state.label=3;case 3:return[4,(0,_promises.readdir)(migrationPath)];case 4:return[2,_state.sent().filter(function(filename){return filename.startsWith(".")===false})]}})})()}return _ts_generator(this,function(_state){switch(_state.label){case 0:_tmp={};return[4,getFilesUnder("src")];case 1:_tmp.src=_state.sent();return[4,getFilesUnder("dist")];case 2:files=(_tmp.dist=_state.sent(),_tmp);diffOnSrc=_lodash.default.differenceBy(files.src,files.dist,function(filename){return filename.split(".")[0]});if(diffOnSrc.length>0){throw new Error("컴파일 되지 않은 파일이 있습니다.\n"+diffOnSrc.join("\n"))}diffOnDist=_lodash.default.differenceBy(files.dist,files.src,function(filename){return filename.split(".")[0]});if(!(diffOnDist.length>0))return[3,13];console.log(_chalk.default.red("원본 ts파일을 찾을 수 없는 js파일이 있습니다."));console.log(diffOnDist);if(!!force)return[3,4];return[4,(0,_prompts.default)({type:"confirm",name:"value",message:"삭제를 진행하시겠습니까?",initial:true})];case 3:answer=_state.sent();if(answer.value===false){return[2]}_state.label=4;case 4:filesToRm=diffOnDist.map(function(filename){return _path.default.join(_api.Sonamu.apiRootPath,"dist","migrations",filename)});_iteratorNormalCompletion=true,_didIteratorError=false,_iteratorError=undefined;_state.label=5;case 5:_state.trys.push([5,10,11,12]);_iterator=filesToRm[Symbol.iterator]();_state.label=6;case 6:if(!!(_iteratorNormalCompletion=(_step=_iterator.next()).done))return[3,9];filePath=_step.value;return[4,(0,_promises.unlink)(filePath)];case 7:_state.sent();_state.label=8;case 8:_iteratorNormalCompletion=true;return[3,6];case 9:return[3,12];case 10:err=_state.sent();_didIteratorError=true;_iteratorError=err;return[3,12];case 11:try{if(!_iteratorNormalCompletion&&_iterator.return!=null){_iterator.return()}}finally{if(_didIteratorError){throw _iteratorError}}return[7];case 12:console.log(_chalk.default.green("".concat(filesToRm.length,"건 삭제되었습니다!")));_state.label=13;case 13:return[2]}})})()}},{key:"runShadowTest",value:function runShadowTest(){return _async_to_generator(function(){var tdb,tdbConn,shadowDatabase,tmpSqlPath,_tdbConn_port,_tdbConn_port1,sdb,_ref,batchNo,applied,e;return _ts_generator(this,function(_state){switch(_state.label){case 0:tdb=(0,_knex.default)(_api.Sonamu.dbConfig.test);tdbConn=_api.Sonamu.dbConfig.test.connection;shadowDatabase=tdbConn.database+"__migration_shadow";tmpSqlPath="/tmp/".concat(shadowDatabase,".sql");console.log(_chalk.default.magenta("".concat(tdbConn.database,"의 데이터 ").concat(tmpSqlPath,"로 덤프")));(0,_child_process.execSync)("mysqldump -h".concat(tdbConn.host," -P").concat((_tdbConn_port=tdbConn.port)!==null&&_tdbConn_port!==void 0?_tdbConn_port:3306," -u").concat(tdbConn.user," -p'").concat(tdbConn.password,"' ").concat(tdbConn.database," --single-transaction --no-create-db --triggers > ").concat(tmpSqlPath,";"));(0,_child_process.execSync)("sed -i'' -e 's/`".concat(tdbConn.database,"`/`").concat(shadowDatabase,"`/g' ").concat(tmpSqlPath,";"));console.log(_chalk.default.magenta("".concat(shadowDatabase," 리셋")));return[4,tdb.raw("DROP DATABASE IF EXISTS `".concat(shadowDatabase,"`;"))];case 1:_state.sent();return[4,tdb.raw("CREATE DATABASE `".concat(shadowDatabase,"`;"))];case 2:_state.sent();console.log(_chalk.default.magenta("".concat(shadowDatabase," 데이터베이스 생성")));(0,_child_process.execSync)("mysql -h".concat(tdbConn.host," -P").concat((_tdbConn_port1=tdbConn.port)!==null&&_tdbConn_port1!==void 0?_tdbConn_port1:3306," -u").concat(tdbConn.user," -p'").concat(tdbConn.password,"' ").concat(shadowDatabase," < ").concat(tmpSqlPath,";"));sdb=(0,_knex.default)(_object_spread_props(_object_spread({},_api.Sonamu.dbConfig.test),{connection:_object_spread_props(_object_spread({},tdbConn),{database:shadowDatabase,password:tdbConn.password})}));_state.label=3;case 3:_state.trys.push([3,6,7,9]);return[4,sdb.migrate.latest()];case 4:_ref=_sliced_to_array.apply(void 0,[_state.sent(),2]),batchNo=_ref[0],applied=_ref[1];console.log(_chalk.default.green("Shadow DB 테스트에 성공했습니다!"),{batchNo:batchNo,applied:applied});console.log(_chalk.default.magenta("".concat(shadowDatabase," 삭제")));return[4,tdb.raw("DROP DATABASE IF EXISTS `".concat(shadowDatabase,"`;"))];case 5:_state.sent();return[2,[{connKey:"shadow",batchNo:batchNo,applied:applied}]];case 6:e=_state.sent();console.error(e);throw new _soexceptions.ServiceUnavailableException("Shadow DB 테스트 진행 중 에러");case 7:return[4,tdb.destroy()];case 8:_state.sent();return[7];case 9:return[2]}})})()}},{key:"resetAll",value:function resetAll(){return _async_to_generator(function(){var answer,rollbackAllResult,migrationsDir;return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,(0,_prompts.default)({type:"confirm",name:"value",message:"모든 DB를 롤백하고 전체 마이그레이션 파일을 삭제하시겠습니까?",initial:false})];case 1:answer=_state.sent();if(answer.value===false){return[2]}console.time(_chalk.default.red("rollback-all:"));return[4,Promise.all(this.targets.apply.map(function(db){return _async_to_generator(function(){return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,db.migrate.forceFreeMigrationsLock()];case 1:_state.sent();return[2,db.migrate.rollback(undefined,true)]}})})()}))];case 2:rollbackAllResult=_state.sent();console.log({rollbackAllResult:rollbackAllResult});console.timeEnd(_chalk.default.red("rollback-all:"));migrationsDir="".concat(_api.Sonamu.apiRootPath,"/src/migrations");console.time(_chalk.default.red("delete migration files"));(0,_child_process.execSync)("rm -f ".concat(migrationsDir,"/*"));(0,_child_process.execSync)("rm -f ".concat(migrationsDir.replace("/src/","/dist/"),"/*"));console.timeEnd(_chalk.default.red("delete migration files"));return[2]}})}).call(this)}},{key:"compareMigrations",value:function compareMigrations(compareDB){return _async_to_generator(function(){var entityIds,entitySetsWithJoinTable,joinTablesWithDup,joinTables,entitySets,codes;return _ts_generator(this,function(_state){switch(_state.label){case 0:entityIds=_entitymanager.EntityManager.getAllIds();entitySetsWithJoinTable=entityIds.filter(function(entityId){return _entitymanager.EntityManager.get(entityId).props.length>0}).map(function(entityId){return(0,_migrationset.getMigrationSetFromEntity)(_entitymanager.EntityManager.get(entityId))});joinTablesWithDup=entitySetsWithJoinTable.map(function(entitySet){return entitySet.joinTables}).flat();joinTables=Object.values(_lodash.default.groupBy(joinTablesWithDup,function(jt){return jt.table})).map(function(tables){if(tables.length===1){return tables[0]}return _object_spread_props(_object_spread({},tables[0]),{indexes:_lodash.default.uniqBy(tables.flatMap(function(t){return t.indexes}),function(index){return[index.type].concat(_to_consumable_array(index.columns.sort())).join("-")})})});entitySets=_to_consumable_array(entitySetsWithJoinTable).concat(_to_consumable_array(joinTables));return[4,Promise.all(entitySets.map(function(entitySet){return _async_to_generator(function(){var dbSet;return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,(0,_migrationset.getMigrationSetFromDB)(compareDB,entitySet.table)];case 1:dbSet=_state.sent();if(!(dbSet===null))return[3,3];return[4,(0,_codegeneration.generateCreateCode)(entitySet)];case 2:return[2,_state.sent()];case 3:return[4,(0,_codegeneration.generateAlterCode)(entitySet,dbSet)];case 4:return[2,_state.sent()];case 5:return[2]}})})()}))];case 1:codes=_state.sent().flat();codes.sort(function(codeA,codeB){if(codeA.type==="foreign"&&codeB.type=="normal"){return 1}else if(codeA.type==="normal"&&codeB.type==="foreign"){return-1}else{return 0}});return[2,codes]}})})()}},{key:"destroy",value:function destroy(){return _async_to_generator(function(){return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,Promise.all(this.targets.apply.map(function(db){return db.destroy()}))];case 1:_state.sent();return[2]}})}).call(this)}}]);return Migrator}();
|
|
2
|
-
|
|
1
|
+
import assert from "assert";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { mkdir, readdir, unlink, writeFile } from "node:fs/promises";
|
|
4
|
+
import knex from "knex";
|
|
5
|
+
import path from "path";
|
|
6
|
+
import { group, sum, unique } from "radashi";
|
|
7
|
+
import { Sonamu } from "../api/index.js";
|
|
8
|
+
import { DB } from "../database/db.js";
|
|
9
|
+
import { EntityManager } from "../entity/entity-manager.js";
|
|
10
|
+
import { ServiceUnavailableException } from "../exceptions/so-exceptions.js";
|
|
11
|
+
import { Naite } from "../naite/naite.js";
|
|
12
|
+
import { isTest } from "../utils/controller.js";
|
|
13
|
+
import { exists } from "../utils/fs-utils.js";
|
|
14
|
+
import { generateAlterCode, generateCreateCode } from "./code-generation.js";
|
|
15
|
+
import { getMigrationSetFromEntity } from "./migration-set.js";
|
|
16
|
+
import { PostgreSQLSchemaReader } from "./postgresql-schema-reader.js";
|
|
17
|
+
export class Migrator {
|
|
18
|
+
async getMigrationCodes() {
|
|
19
|
+
const srcMigrationsDir = path.join(Sonamu.apiRootPath, "src", "migrations"); // 이건 환경에 관계없이 항상 src에서 찾아야 해요.
|
|
20
|
+
if (!await exists(srcMigrationsDir)) {
|
|
21
|
+
await mkdir(srcMigrationsDir, {
|
|
22
|
+
recursive: true
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
const codes = (await readdir(srcMigrationsDir)).filter((f)=>f.endsWith(".ts")).map((f)=>({
|
|
26
|
+
name: f.replace(".ts", ""),
|
|
27
|
+
path: path.join(srcMigrationsDir, f)
|
|
28
|
+
})).sort((a, b)=>a.name < b.name ? 1 : -1); // 이름 내림차순 정렬(최신순)
|
|
29
|
+
Naite.t("migrator:getMigrationCodes:results", codes);
|
|
30
|
+
return codes;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 타겟별 마이그레이션 상태와 코드 생성/준비 상태를 구해옵니다.
|
|
34
|
+
* 실제로 DB에 접근도 하고 마이그레이션 코드 파일도 확인하고,
|
|
35
|
+
* 필요하다면 적용할 수 있는 코드를 생성까지 해옵니다.
|
|
36
|
+
*
|
|
37
|
+
* CLI와 Sonamu UI에서 사용됩니다.
|
|
38
|
+
*
|
|
39
|
+
* @returns
|
|
40
|
+
*/ async getStatus() {
|
|
41
|
+
const codes = await this.getMigrationCodes();
|
|
42
|
+
Naite.t("migrator:getStatus:codes", codes);
|
|
43
|
+
const connKeys = Object.keys(Sonamu.dbConfig).filter((key)=>key.endsWith("_slave") === false);
|
|
44
|
+
let migrationStatusError;
|
|
45
|
+
const statuses = await Promise.all(connKeys.map(async (connKey)=>{
|
|
46
|
+
const knexOptions = Sonamu.dbConfig[connKey];
|
|
47
|
+
const tConn = knex(knexOptions);
|
|
48
|
+
const status = await (async ()=>{
|
|
49
|
+
try {
|
|
50
|
+
return await tConn.migrate.status();
|
|
51
|
+
} catch (err) {
|
|
52
|
+
console.warn(chalk.yellow(`${connKey}의 마이그레이션 상태를 가져오는 데에 실패하였습니다. 데이터베이스가 올바르게 구성되지 않은 것 같습니다. 확인하시고 다시 시도해주세요.\n시도한 연결 설정:\n${JSON.stringify(knexOptions.connection, null, 2)}\n발생한 에러:\n${err}\n`));
|
|
53
|
+
migrationStatusError = err instanceof Error ? err.message : String(err);
|
|
54
|
+
return "error";
|
|
55
|
+
}
|
|
56
|
+
})();
|
|
57
|
+
const pending = await (async ()=>{
|
|
58
|
+
try {
|
|
59
|
+
const [, fdList] = await tConn.migrate.list();
|
|
60
|
+
return fdList.map((fd)=>fd.file.replace(".ts", ""));
|
|
61
|
+
} catch (err) {
|
|
62
|
+
migrationStatusError = err instanceof Error ? err.message : String(err);
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
})();
|
|
66
|
+
const currentVersion = await (async ()=>{
|
|
67
|
+
try {
|
|
68
|
+
return await tConn.migrate.currentVersion();
|
|
69
|
+
} catch (_err) {
|
|
70
|
+
migrationStatusError = _err instanceof Error ? _err.message : String(_err);
|
|
71
|
+
return "error";
|
|
72
|
+
}
|
|
73
|
+
})();
|
|
74
|
+
Naite.t("migrator:getStatus:status", status);
|
|
75
|
+
const connection = knexOptions.connection;
|
|
76
|
+
await tConn.destroy();
|
|
77
|
+
return {
|
|
78
|
+
name: connKey.replace("_master", ""),
|
|
79
|
+
connKey,
|
|
80
|
+
connString: `pg://${connection.user ?? ""}@${connection.host}:${connection.port}/${connection.database}`,
|
|
81
|
+
currentVersion,
|
|
82
|
+
status: status,
|
|
83
|
+
pending
|
|
84
|
+
};
|
|
85
|
+
}));
|
|
86
|
+
Naite.t("migrator:getStatus:conns", statuses);
|
|
87
|
+
const preparedCodes = await (async ()=>{
|
|
88
|
+
const status0conn = statuses.find((status)=>status.status === 0);
|
|
89
|
+
if (status0conn === undefined) {
|
|
90
|
+
console.warn(chalk.yellow(`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.`));
|
|
91
|
+
return [];
|
|
92
|
+
}
|
|
93
|
+
const compareDBconn = knex(Sonamu.dbConfig[status0conn.connKey]);
|
|
94
|
+
const genCodes = await this.compareMigrations(compareDBconn);
|
|
95
|
+
await compareDBconn.destroy();
|
|
96
|
+
return genCodes;
|
|
97
|
+
})();
|
|
98
|
+
Naite.t("migrator:getStatus:preparedCodes", preparedCodes);
|
|
99
|
+
return {
|
|
100
|
+
conns: statuses,
|
|
101
|
+
codes,
|
|
102
|
+
preparedCodes,
|
|
103
|
+
error: migrationStatusError
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* 마이그레이션을 적용하거나 롤백합니다.
|
|
108
|
+
* Sonamu UI에서 마이그레이션 작업을 수행할 때 사용됩니다.
|
|
109
|
+
*
|
|
110
|
+
* CLI와 Sonamu UI에서 사용됩니다.
|
|
111
|
+
*
|
|
112
|
+
* @param action 작업 유형 (apply/rollback)
|
|
113
|
+
* @param targets 작업 대상 DB 설정 키 (keyof SonamuDBConfig)
|
|
114
|
+
* @returns 작업 결과
|
|
115
|
+
*/ async runAction(action, targets) {
|
|
116
|
+
Naite.t("migrator:runAction:action", action);
|
|
117
|
+
Naite.t("migrator:runAction:targets", targets);
|
|
118
|
+
// get uniq knex configs
|
|
119
|
+
const configs = unique(targets.map((target)=>({
|
|
120
|
+
connKey: target,
|
|
121
|
+
options: Sonamu.dbConfig[target]
|
|
122
|
+
})).filter((c)=>c.options !== undefined), ({ options })=>`${options.connection.host}:${options.connection.port ?? 5432}/${options.connection.database}`);
|
|
123
|
+
// get connections
|
|
124
|
+
const conns = await Promise.all(configs.map(async (config)=>({
|
|
125
|
+
connKey: config.connKey,
|
|
126
|
+
knex: knex(config.options)
|
|
127
|
+
})));
|
|
128
|
+
// action
|
|
129
|
+
const result = await (async ()=>{
|
|
130
|
+
switch(action){
|
|
131
|
+
case "apply":
|
|
132
|
+
return Promise.all(conns.map(async ({ connKey, knex })=>{
|
|
133
|
+
const [batchNo, applied] = await knex.migrate.latest();
|
|
134
|
+
return {
|
|
135
|
+
connKey,
|
|
136
|
+
batchNo,
|
|
137
|
+
applied
|
|
138
|
+
};
|
|
139
|
+
}));
|
|
140
|
+
case "rollback":
|
|
141
|
+
return Promise.all(conns.map(async ({ connKey, knex })=>{
|
|
142
|
+
const [batchNo, applied] = await knex.migrate.rollback();
|
|
143
|
+
return {
|
|
144
|
+
connKey,
|
|
145
|
+
batchNo,
|
|
146
|
+
applied
|
|
147
|
+
};
|
|
148
|
+
}));
|
|
149
|
+
}
|
|
150
|
+
})();
|
|
151
|
+
// destroy
|
|
152
|
+
await Promise.all(conns.map(({ knex })=>{
|
|
153
|
+
return knex.destroy();
|
|
154
|
+
}));
|
|
155
|
+
Naite.t("migrator:runAction:result", result);
|
|
156
|
+
return result;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* 삭제 가능한 마이그레이션 코드 파일을 검증합니다.
|
|
160
|
+
*
|
|
161
|
+
* @param conns 마이그레이션 상태 배열
|
|
162
|
+
* @param codeNames 삭제할 마이그레이션 코드 파일 이름 배열
|
|
163
|
+
* @returns 삭제 가능 여부 및 적용된 마이그레이션 코드 파일 이름
|
|
164
|
+
*/ validateDeletable(conns, codeNames) {
|
|
165
|
+
const appliedCodes = codeNames.filter((codeName)=>conns.some((conn)=>conn.pending.includes(codeName) === false));
|
|
166
|
+
return {
|
|
167
|
+
canDelete: appliedCodes.length === 0,
|
|
168
|
+
appliedCodes
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* 마이그레이션 코드 파일을 삭제합니다.
|
|
173
|
+
*
|
|
174
|
+
* Sonamu UI에서 사용됩니다.
|
|
175
|
+
*
|
|
176
|
+
* @param codeNames 삭제할 마이그레이션 코드 파일 이름 배열
|
|
177
|
+
* @returns 삭제된 마이그레이션 코드 파일 개수
|
|
178
|
+
*/ async delCodes(codeNames) {
|
|
179
|
+
const { conns } = await this.getStatus();
|
|
180
|
+
const { canDelete, appliedCodes } = this.validateDeletable(conns, codeNames);
|
|
181
|
+
if (!canDelete) {
|
|
182
|
+
throw new Error(`You cannot delete a migration file if there is already applied. Applied codes: ${appliedCodes.join(", ")}`);
|
|
183
|
+
}
|
|
184
|
+
return sum(await Promise.all(codeNames.map(async (codeName)=>{
|
|
185
|
+
const filePath = `${Sonamu.apiRootPath}/src/migrations/${codeName}.ts`;
|
|
186
|
+
if (await exists(filePath)) {
|
|
187
|
+
await unlink(filePath);
|
|
188
|
+
return 1;
|
|
189
|
+
}
|
|
190
|
+
return 0;
|
|
191
|
+
})));
|
|
192
|
+
}
|
|
193
|
+
genDateTag(index, baseDate = new Date()) {
|
|
194
|
+
const date = new Date(baseDate.getTime() + index * 1000);
|
|
195
|
+
const pad = (num, size = 2)=>num.toString().padStart(size, "0");
|
|
196
|
+
return date.getFullYear().toString() + pad(date.getMonth() + 1) + pad(date.getDate()) + pad(date.getHours()) + pad(date.getMinutes()) + pad(date.getSeconds());
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* 마이그레이션 코드 파일을 생성합니다.
|
|
200
|
+
*
|
|
201
|
+
* Sonamu UI에서 사용됩니다.
|
|
202
|
+
*
|
|
203
|
+
* @returns 생성된 마이그레이션 코드 파일 개수
|
|
204
|
+
*/ async generatePreparedCodes() {
|
|
205
|
+
const { preparedCodes } = await this.getStatus();
|
|
206
|
+
Naite.t("migrator:generatePreparedCodes:preparedCodes", preparedCodes);
|
|
207
|
+
if (preparedCodes.length === 0) {
|
|
208
|
+
console.log(chalk.green("\n현재 모두 싱크된 상태입니다."));
|
|
209
|
+
return 0;
|
|
210
|
+
}
|
|
211
|
+
// 실제 코드 생성
|
|
212
|
+
const migrationsDir = `${Sonamu.apiRootPath}/src/migrations`;
|
|
213
|
+
for (const [index, pcode] of preparedCodes.entries()){
|
|
214
|
+
if (pcode.formatted) {
|
|
215
|
+
const dateTag = this.genDateTag(index);
|
|
216
|
+
const filePath = `${migrationsDir}/${dateTag}_${pcode.title}.ts`;
|
|
217
|
+
await writeFile(filePath, pcode.formatted);
|
|
218
|
+
!isTest() && console.log(chalk.green(`MIGRTAION CREATED ${filePath}`));
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return preparedCodes.length;
|
|
222
|
+
}
|
|
223
|
+
async compareMigrations(compareDB) {
|
|
224
|
+
// Entity 순회하여 싱크
|
|
225
|
+
const entityIds = EntityManager.getAllIds();
|
|
226
|
+
// 조인테이블 포함하여 Entity에서 MigrationSet 추출
|
|
227
|
+
const entitySetsWithJoinTable = entityIds.filter((entityId)=>EntityManager.get(entityId).props.length > 0).map((entityId)=>getMigrationSetFromEntity(EntityManager.get(entityId)));
|
|
228
|
+
// 조인테이블만 추출
|
|
229
|
+
const joinTablesWithDup = entitySetsWithJoinTable.flatMap((entitySet)=>entitySet.joinTables);
|
|
230
|
+
// 중복 제거 (중복인 경우 indexes를 병합)
|
|
231
|
+
const joinTables = Object.values(group(joinTablesWithDup, (jt)=>jt.table)).map((tables)=>{
|
|
232
|
+
assert(tables !== undefined, "tables is undefined");
|
|
233
|
+
if (tables.length === 1) {
|
|
234
|
+
return tables[0];
|
|
235
|
+
}
|
|
236
|
+
return {
|
|
237
|
+
...tables[0],
|
|
238
|
+
indexes: unique(tables.flatMap((t)=>t.indexes), (index)=>[
|
|
239
|
+
index.type,
|
|
240
|
+
...index.columns.sort()
|
|
241
|
+
].join("-"))
|
|
242
|
+
};
|
|
243
|
+
});
|
|
244
|
+
// 조인테이블 포함하여 MigrationSet 배열
|
|
245
|
+
const entitySets = [
|
|
246
|
+
...entitySetsWithJoinTable,
|
|
247
|
+
...joinTables
|
|
248
|
+
];
|
|
249
|
+
const codes = (await Promise.all(entitySets.map(async (entitySet)=>{
|
|
250
|
+
const dbSet = await PostgreSQLSchemaReader.getMigrationSetFromDB(compareDB, entitySet.table);
|
|
251
|
+
Naite.t(`migrator:compareMigrations:entitySet:${entitySet.table}`, entitySet);
|
|
252
|
+
Naite.t(`migrator:compareMigrations:dbSet:${entitySet.table}`, dbSet);
|
|
253
|
+
if (dbSet === null) {
|
|
254
|
+
// 기존 테이블 없음, 새로 테이블 생성
|
|
255
|
+
return await generateCreateCode(entitySet);
|
|
256
|
+
} else {
|
|
257
|
+
// 기존 테이블 존재하는 케이스
|
|
258
|
+
return await generateAlterCode(entitySet, dbSet);
|
|
259
|
+
}
|
|
260
|
+
}))).flat();
|
|
261
|
+
// normal 타입이 앞으로, foreign이 뒤로
|
|
262
|
+
codes.sort((codeA, codeB)=>{
|
|
263
|
+
if (codeA.type === "foreign" && codeB.type === "normal") {
|
|
264
|
+
return 1;
|
|
265
|
+
} else if (codeA.type === "normal" && codeB.type === "foreign") {
|
|
266
|
+
return -1;
|
|
267
|
+
} else {
|
|
268
|
+
return 0;
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
return codes;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Shadow DB 테스트를 진행합니다.
|
|
275
|
+
*
|
|
276
|
+
* Sonamu UI에서 사용됩니다.
|
|
277
|
+
*
|
|
278
|
+
* @returns Shadow DB 테스트 결과
|
|
279
|
+
*/ async runShadowTest() {
|
|
280
|
+
const tdbConn = Sonamu.dbConfig.test.connection;
|
|
281
|
+
const shadowDatabase = `${tdbConn.database}__migration_shadow`;
|
|
282
|
+
// 테스트 상황에서는 트랜잭션을 초기화하고, 새 데이터베이스 커넥션을 가져와야 함
|
|
283
|
+
if (isTest()) {
|
|
284
|
+
await DB.clearTestTransaction();
|
|
285
|
+
await DB.destroy();
|
|
286
|
+
}
|
|
287
|
+
// 기존 Shadow DB 삭제 후 Shadow DB 생성
|
|
288
|
+
const tdb = knex(Sonamu.dbConfig.test);
|
|
289
|
+
!isTest() && console.log(chalk.magenta(`${shadowDatabase} 삭제`));
|
|
290
|
+
await tdb.raw(`DROP DATABASE IF EXISTS ${shadowDatabase}`);
|
|
291
|
+
await tdb.raw(`CREATE DATABASE ${shadowDatabase} TEMPLATE ${tdbConn.database}`);
|
|
292
|
+
// Shadow DB에 연결
|
|
293
|
+
const sdb = knex({
|
|
294
|
+
...Sonamu.dbConfig.test,
|
|
295
|
+
connection: {
|
|
296
|
+
...tdbConn,
|
|
297
|
+
database: shadowDatabase,
|
|
298
|
+
password: tdbConn.password
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
// shadow DB 테스트 진행
|
|
302
|
+
try {
|
|
303
|
+
const [batchNo, applied] = await sdb.migrate.latest();
|
|
304
|
+
!isTest() && console.log(chalk.green("Shadow DB 테스트에 성공했습니다!"), {
|
|
305
|
+
batchNo,
|
|
306
|
+
applied
|
|
307
|
+
});
|
|
308
|
+
return [
|
|
309
|
+
{
|
|
310
|
+
connKey: "shadow",
|
|
311
|
+
batchNo,
|
|
312
|
+
applied
|
|
313
|
+
}
|
|
314
|
+
];
|
|
315
|
+
} catch (e) {
|
|
316
|
+
console.error(e);
|
|
317
|
+
throw new ServiceUnavailableException("Shadow DB 테스트 진행 중 에러");
|
|
318
|
+
} finally{
|
|
319
|
+
// Shadow DB 연결 종료
|
|
320
|
+
await sdb.destroy();
|
|
321
|
+
// Shadow DB 삭제
|
|
322
|
+
!isTest() && console.log(chalk.magenta(`${shadowDatabase} 삭제`));
|
|
323
|
+
await tdb.raw(`DROP DATABASE IF EXISTS ${shadowDatabase}`);
|
|
324
|
+
// Test DB 연결 종료
|
|
325
|
+
await tdb.destroy();
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9taWdyYXRpb24vbWlncmF0b3IudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGFzc2VydCBmcm9tIFwiYXNzZXJ0XCI7XG5pbXBvcnQgY2hhbGsgZnJvbSBcImNoYWxrXCI7XG5pbXBvcnQgeyBta2RpciwgcmVhZGRpciwgdW5saW5rLCB3cml0ZUZpbGUgfSBmcm9tIFwiZnMvcHJvbWlzZXNcIjtcbmltcG9ydCBrbmV4LCB7IHR5cGUgS25leCB9IGZyb20gXCJrbmV4XCI7XG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IHsgZ3JvdXAsIHN1bSwgdW5pcXVlIH0gZnJvbSBcInJhZGFzaGlcIjtcbmltcG9ydCB7IFNvbmFtdSB9IGZyb20gXCIuLi9hcGlcIjtcbmltcG9ydCB7IERCLCB0eXBlIFNvbmFtdURCQ29uZmlnIH0gZnJvbSBcIi4uL2RhdGFiYXNlL2RiXCI7XG5pbXBvcnQgeyBFbnRpdHlNYW5hZ2VyIH0gZnJvbSBcIi4uL2VudGl0eS9lbnRpdHktbWFuYWdlclwiO1xuaW1wb3J0IHsgU2VydmljZVVuYXZhaWxhYmxlRXhjZXB0aW9uIH0gZnJvbSBcIi4uL2V4Y2VwdGlvbnMvc28tZXhjZXB0aW9uc1wiO1xuaW1wb3J0IHsgTmFpdGUgfSBmcm9tIFwiLi4vbmFpdGUvbmFpdGVcIjtcbmltcG9ydCB0eXBlIHsgR2VuTWlncmF0aW9uQ29kZSwgTWlncmF0aW9uU2V0IH0gZnJvbSBcIi4uL3R5cGVzL3R5cGVzXCI7XG5pbXBvcnQgeyBpc1Rlc3QgfSBmcm9tIFwiLi4vdXRpbHMvY29udHJvbGxlclwiO1xuaW1wb3J0IHsgZXhpc3RzIH0gZnJvbSBcIi4uL3V0aWxzL2ZzLXV0aWxzXCI7XG5pbXBvcnQgeyBnZW5lcmF0ZUFsdGVyQ29kZSwgZ2VuZXJhdGVDcmVhdGVDb2RlIH0gZnJvbSBcIi4vY29kZS1nZW5lcmF0aW9uXCI7XG5pbXBvcnQgeyBnZXRNaWdyYXRpb25TZXRGcm9tRW50aXR5IH0gZnJvbSBcIi4vbWlncmF0aW9uLXNldFwiO1xuaW1wb3J0IHsgUG9zdGdyZVNRTFNjaGVtYVJlYWRlciB9IGZyb20gXCIuL3Bvc3RncmVzcWwtc2NoZW1hLXJlYWRlclwiO1xuaW1wb3J0IHR5cGUgeyBDb25uU3RyaW5nLCBNaWdyYXRpb25Db2RlLCBNaWdyYXRpb25TdGF0dXMgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG5leHBvcnQgdHlwZSBNaWdyYXRpb25SZXN1bHQgPSB7XG4gIGNvbm5LZXk6IHN0cmluZztcbiAgYmF0Y2hObzogbnVtYmVyO1xuICBhcHBsaWVkOiBzdHJpbmdbXTtcbn1bXTtcblxuZXhwb3J0IGNsYXNzIE1pZ3JhdG9yIHtcbiAgcHJpdmF0ZSBhc3luYyBnZXRNaWdyYXRpb25Db2RlcygpOiBQcm9taXNlPE1pZ3JhdGlvbkNvZGVbXT4ge1xuICAgIGNvbnN0IHNyY01pZ3JhdGlvbnNEaXIgPSBwYXRoLmpvaW4oU29uYW11LmFwaVJvb3RQYXRoLCBcInNyY1wiLCBcIm1pZ3JhdGlvbnNcIik7IC8vIOydtOqxtCDtmZjqsr3sl5Ag6rSA6rOE7JeG7J20IO2VreyDgSBzcmPsl5DshJwg7LC+7JWE7JW8IO2VtOyalC5cblxuICAgIGlmICghKGF3YWl0IGV4aXN0cyhzcmNNaWdyYXRpb25zRGlyKSkpIHtcbiAgICAgIGF3YWl0IG1rZGlyKHNyY01pZ3JhdGlvbnNEaXIsIHtcbiAgICAgICAgcmVjdXJzaXZlOiB0cnVlLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgY29uc3QgY29kZXMgPSAoYXdhaXQgcmVhZGRpcihzcmNNaWdyYXRpb25zRGlyKSlcbiAgICAgIC5maWx0ZXIoKGYpID0+IGYuZW5kc1dpdGgoXCIudHNcIikpXG4gICAgICAubWFwKChmKSA9PiAoe1xuICAgICAgICBuYW1lOiBmLnJlcGxhY2UoXCIudHNcIiwgXCJcIiksXG4gICAgICAgIHBhdGg6IHBhdGguam9pbihzcmNNaWdyYXRpb25zRGlyLCBmKSxcbiAgICAgIH0pKVxuICAgICAgLnNvcnQoKGEsIGIpID0+IChhLm5hbWUgPCBiLm5hbWUgPyAxIDogLTEpKTsgLy8g7J2066aEIOuCtOumvOywqOyInCDsoJXroKwo7LWc7Iug7IicKVxuXG4gICAgTmFpdGUudChcIm1pZ3JhdG9yOmdldE1pZ3JhdGlvbkNvZGVzOnJlc3VsdHNcIiwgY29kZXMpO1xuICAgIHJldHVybiBjb2RlcztcbiAgfVxuXG4gIC8qKlxuICAgKiDtg4Dqsp/rs4Qg66eI7J206re466CI7J207IWYIOyDge2DnOyZgCDsvZTrk5wg7IOd7ISxL+ykgOu5hCDsg4Htg5zrpbwg6rWs7ZW07Ji164uI64ukLlxuICAgKiDsi6TsoJzroZwgRELsl5Ag7KCR6re864+EIO2VmOqzoCDrp4jsnbTqt7jroIjsnbTshZgg7L2U65OcIO2MjOydvOuPhCDtmZXsnbjtlZjqs6AsXG4gICAqIO2VhOyalO2VmOuLpOuptCDsoIHsmqntlaAg7IiYIOyeiOuKlCDsvZTrk5zrpbwg7IOd7ISx6rmM7KeAIO2VtOyYteuLiOuLpC5cbiAgICpcbiAgICogQ0xJ7JmAIFNvbmFtdSBVSeyXkOyEnCDsgqzsmqnrkKnri4jri6QuXG4gICAqXG4gICAqIEByZXR1cm5zXG4gICAqL1xuICBhc3luYyBnZXRTdGF0dXMoKTogUHJvbWlzZTxNaWdyYXRpb25TdGF0dXM+IHtcbiAgICBjb25zdCBjb2RlcyA9IGF3YWl0IHRoaXMuZ2V0TWlncmF0aW9uQ29kZXMoKTtcbiAgICBOYWl0ZS50KFwibWlncmF0b3I6Z2V0U3RhdHVzOmNvZGVzXCIsIGNvZGVzKTtcblxuICAgIGNvbnN0IGNvbm5LZXlzID0gT2JqZWN0LmtleXMoU29uYW11LmRiQ29uZmlnKS5maWx0ZXIoXG4gICAgICAoa2V5KSA9PiBrZXkuZW5kc1dpdGgoXCJfc2xhdmVcIikgPT09IGZhbHNlLFxuICAgICkgYXMgKGtleW9mIHR5cGVvZiBTb25hbXUuZGJDb25maWcpW107XG5cbiAgICBsZXQgbWlncmF0aW9uU3RhdHVzRXJyb3I6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICAgIGNvbnN0IHN0YXR1c2VzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBjb25uS2V5cy5tYXAoYXN5bmMgKGNvbm5LZXkpID0+IHtcbiAgICAgICAgY29uc3Qga25leE9wdGlvbnMgPSBTb25hbXUuZGJDb25maWdbY29ubktleV07XG4gICAgICAgIGNvbnN0IHRDb25uID0ga25leChrbmV4T3B0aW9ucyk7XG5cbiAgICAgICAgY29uc3Qgc3RhdHVzID0gYXdhaXQgKGFzeW5jICgpID0+IHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHRDb25uLm1pZ3JhdGUuc3RhdHVzKCk7XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgICAgIGNoYWxrLnllbGxvdyhcbiAgICAgICAgICAgICAgICBgJHtjb25uS2V5feydmCDrp4jsnbTqt7jroIjsnbTshZgg7IOB7YOc66W8IOqwgOyguOyYpOuKlCDrjbDsl5Ag7Iuk7Yyo7ZWY7JiA7Iq164uI64ukLiDrjbDsnbTthLDrsqDsnbTsiqTqsIAg7Jis67CU66W06rKMIOq1rOyEseuQmOyngCDslYrsnYAg6rKDIOqwmeyKteuLiOuLpC4g7ZmV7J247ZWY7Iuc6rOgIOuLpOyLnCDsi5zrj4TtlbTso7zshLjsmpQuXFxu7Iuc64+E7ZWcIOyXsOqysCDshKTsoJU6XFxuJHtKU09OLnN0cmluZ2lmeShrbmV4T3B0aW9ucy5jb25uZWN0aW9uLCBudWxsLCAyKX1cXG7rsJzsg53tlZwg7JeQ65+sOlxcbiR7ZXJyfVxcbmAsXG4gICAgICAgICAgICAgICksXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgbWlncmF0aW9uU3RhdHVzRXJyb3IgPSBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVycik7XG4gICAgICAgICAgICByZXR1cm4gXCJlcnJvclwiO1xuICAgICAgICAgIH1cbiAgICAgICAgfSkoKTtcbiAgICAgICAgY29uc3QgcGVuZGluZzogc3RyaW5nW10gPSBhd2FpdCAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBbLCBmZExpc3RdID0gYXdhaXQgdENvbm4ubWlncmF0ZS5saXN0KCk7XG4gICAgICAgICAgICByZXR1cm4gZmRMaXN0Lm1hcCgoZmQ6IHsgZmlsZTogc3RyaW5nIH0pID0+IGZkLmZpbGUucmVwbGFjZShcIi50c1wiLCBcIlwiKSk7XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBtaWdyYXRpb25TdGF0dXNFcnJvciA9IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKTtcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pKCk7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRWZXJzaW9uID0gYXdhaXQgKGFzeW5jICgpID0+IHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHRDb25uLm1pZ3JhdGUuY3VycmVudFZlcnNpb24oKTtcbiAgICAgICAgICB9IGNhdGNoIChfZXJyKSB7XG4gICAgICAgICAgICBtaWdyYXRpb25TdGF0dXNFcnJvciA9IF9lcnIgaW5zdGFuY2VvZiBFcnJvciA/IF9lcnIubWVzc2FnZSA6IFN0cmluZyhfZXJyKTtcbiAgICAgICAgICAgIHJldHVybiBcImVycm9yXCI7XG4gICAgICAgICAgfVxuICAgICAgICB9KSgpO1xuICAgICAgICBOYWl0ZS50KFwibWlncmF0b3I6Z2V0U3RhdHVzOnN0YXR1c1wiLCBzdGF0dXMpO1xuXG4gICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBrbmV4T3B0aW9ucy5jb25uZWN0aW9uIGFzIEtuZXguUGdDb25uZWN0aW9uQ29uZmlnO1xuXG4gICAgICAgIGF3YWl0IHRDb25uLmRlc3Ryb3koKTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIG5hbWU6IGNvbm5LZXkucmVwbGFjZShcIl9tYXN0ZXJcIiwgXCJcIiksXG4gICAgICAgICAgY29ubktleSxcbiAgICAgICAgICBjb25uU3RyaW5nOiBgcGc6Ly8ke2Nvbm5lY3Rpb24udXNlciA/PyBcIlwifUAke2Nvbm5lY3Rpb24uaG9zdH06JHtcbiAgICAgICAgICAgIGNvbm5lY3Rpb24ucG9ydFxuICAgICAgICAgIH0vJHtjb25uZWN0aW9uLmRhdGFiYXNlfWAgYXMgQ29ublN0cmluZyxcbiAgICAgICAgICBjdXJyZW50VmVyc2lvbixcbiAgICAgICAgICBzdGF0dXM6IHN0YXR1cyBhcyBudW1iZXIgfCBcImVycm9yXCIsXG4gICAgICAgICAgcGVuZGluZyxcbiAgICAgICAgfTtcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICBOYWl0ZS50KFwibWlncmF0b3I6Z2V0U3RhdHVzOmNvbm5zXCIsIHN0YXR1c2VzKTtcblxuICAgIGNvbnN0IHByZXBhcmVkQ29kZXM6IEdlbk1pZ3JhdGlvbkNvZGVbXSA9IGF3YWl0IChhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzdGF0dXMwY29ubiA9IHN0YXR1c2VzLmZpbmQoKHN0YXR1cykgPT4gc3RhdHVzLnN0YXR1cyA9PT0gMCk7XG4gICAgICBpZiAoc3RhdHVzMGNvbm4gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgY2hhbGsueWVsbG93KFxuICAgICAgICAgICAgYFdoaWxlIHRyeWluZyB0byBwcmVwYXJlIG1pZ3JhdGlvbiBjb2Rlcywgd2UgZm91bmQgdGhhdCB0aGVyZSBpcyBubyBkYXRhYmFzZSB0byBjb21wYXJlIG1pZ3JhdGlvbnMuIFdlIG5lZWQgYXQgbGVhc3Qgb25lIGRhdGFiYXNlIHdoZXJlIGV2ZXJ5IG1pZ3JhdGlvbiBpcyBhcHBsaWVkKHN0YXR1cyA9PT0gMCkuIFlvdSBtaWdodCB3YW50IHRvIGFwcGx5IHlvdXIgZXhpc3RpbmcgbWlncmF0aW9ucyB0byBvbmUgb2YgdGhlIGRhdGFiYXNlcy5gLFxuICAgICAgICAgICksXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY29tcGFyZURCY29ubiA9IGtuZXgoU29uYW11LmRiQ29uZmlnW3N0YXR1czBjb25uLmNvbm5LZXldKTtcbiAgICAgIGNvbnN0IGdlbkNvZGVzID0gYXdhaXQgdGhpcy5jb21wYXJlTWlncmF0aW9ucyhjb21wYXJlREJjb25uKTtcblxuICAgICAgYXdhaXQgY29tcGFyZURCY29ubi5kZXN0cm95KCk7XG5cbiAgICAgIHJldHVybiBnZW5Db2RlcztcbiAgICB9KSgpO1xuXG4gICAgTmFpdGUudChcIm1pZ3JhdG9yOmdldFN0YXR1czpwcmVwYXJlZENvZGVzXCIsIHByZXBhcmVkQ29kZXMpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbm5zOiBzdGF0dXNlcyxcbiAgICAgIGNvZGVzLFxuICAgICAgcHJlcGFyZWRDb2RlcyxcbiAgICAgIGVycm9yOiBtaWdyYXRpb25TdGF0dXNFcnJvcixcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIOuniOydtOq3uOugiOydtOyFmOydhCDsoIHsmqntlZjqsbDrgpgg66Gk67Cx7ZWp64uI64ukLlxuICAgKiBTb25hbXUgVUnsl5DshJwg66eI7J206re466CI7J207IWYIOyekeyXheydhCDsiJjtlontlaAg65WMIOyCrOyaqeuQqeuLiOuLpC5cbiAgICpcbiAgICogQ0xJ7JmAIFNvbmFtdSBVSeyXkOyEnCDsgqzsmqnrkKnri4jri6QuXG4gICAqXG4gICAqIEBwYXJhbSBhY3Rpb24g7J6R7JeFIOycoO2YlSAoYXBwbHkvcm9sbGJhY2spXG4gICAqIEBwYXJhbSB0YXJnZXRzIOyekeyXhSDrjIDsg4EgREIg7ISk7KCVIO2CpCAoa2V5b2YgU29uYW11REJDb25maWcpXG4gICAqIEByZXR1cm5zIOyekeyXhSDqsrDqs7xcbiAgICovXG4gIGFzeW5jIHJ1bkFjdGlvbihcbiAgICBhY3Rpb246IFwiYXBwbHlcIiB8IFwicm9sbGJhY2tcIixcbiAgICB0YXJnZXRzOiAoa2V5b2YgU29uYW11REJDb25maWcpW10sXG4gICk6IFByb21pc2U8TWlncmF0aW9uUmVzdWx0PiB7XG4gICAgTmFpdGUudChcIm1pZ3JhdG9yOnJ1bkFjdGlvbjphY3Rpb25cIiwgYWN0aW9uKTtcbiAgICBOYWl0ZS50KFwibWlncmF0b3I6cnVuQWN0aW9uOnRhcmdldHNcIiwgdGFyZ2V0cyk7XG5cbiAgICAvLyBnZXQgdW5pcSBrbmV4IGNvbmZpZ3NcbiAgICBjb25zdCBjb25maWdzID0gdW5pcXVlKFxuICAgICAgdGFyZ2V0c1xuICAgICAgICAubWFwKCh0YXJnZXQpID0+ICh7XG4gICAgICAgICAgY29ubktleTogdGFyZ2V0LFxuICAgICAgICAgIG9wdGlvbnM6IFNvbmFtdS5kYkNvbmZpZ1t0YXJnZXQgYXMga2V5b2YgdHlwZW9mIFNvbmFtdS5kYkNvbmZpZ10sXG4gICAgICAgIH0pKVxuICAgICAgICAuZmlsdGVyKChjKSA9PiBjLm9wdGlvbnMgIT09IHVuZGVmaW5lZCksXG4gICAgICAoeyBvcHRpb25zIH0pID0+XG4gICAgICAgIGAkeyhvcHRpb25zLmNvbm5lY3Rpb24gYXMgS25leC5QZ0Nvbm5lY3Rpb25Db25maWcpLmhvc3R9OiR7XG4gICAgICAgICAgKG9wdGlvbnMuY29ubmVjdGlvbiBhcyBLbmV4LlBnQ29ubmVjdGlvbkNvbmZpZykucG9ydCA/PyA1NDMyXG4gICAgICAgIH0vJHsob3B0aW9ucy5jb25uZWN0aW9uIGFzIEtuZXguUGdDb25uZWN0aW9uQ29uZmlnKS5kYXRhYmFzZX1gLFxuICAgICk7XG5cbiAgICAvLyBnZXQgY29ubmVjdGlvbnNcbiAgICBjb25zdCBjb25ucyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgY29uZmlncy5tYXAoYXN5bmMgKGNvbmZpZykgPT4gKHtcbiAgICAgICAgY29ubktleTogY29uZmlnLmNvbm5LZXksXG4gICAgICAgIGtuZXg6IGtuZXgoY29uZmlnLm9wdGlvbnMpLFxuICAgICAgfSkpLFxuICAgICk7XG5cbiAgICAvLyBhY3Rpb25cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCAoYXN5bmMgKCkgPT4ge1xuICAgICAgc3dpdGNoIChhY3Rpb24pIHtcbiAgICAgICAgY2FzZSBcImFwcGx5XCI6XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKFxuICAgICAgICAgICAgY29ubnMubWFwKGFzeW5jICh7IGNvbm5LZXksIGtuZXggfSkgPT4ge1xuICAgICAgICAgICAgICBjb25zdCBbYmF0Y2hObywgYXBwbGllZF0gPSBhd2FpdCBrbmV4Lm1pZ3JhdGUubGF0ZXN0KCk7XG4gICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgY29ubktleSxcbiAgICAgICAgICAgICAgICBiYXRjaE5vLFxuICAgICAgICAgICAgICAgIGFwcGxpZWQsIC8vIOydtOuyiCBsYXRlc3Qg7Zi47Lac66GcIOyduO2VtCBcInVwXCLsnbQg7KCB7Jqp65CcIOuniOydtOq3uOugiOydtOyFmCDsnbTrpoQoZS5nLiBcIjIwMjUxMTI0MjMzNTU3X2NyZWF0ZV9fY29tcGFuaWVzLnRzXCIp65Ok7J2YIOuwsOyXtOyeheuLiOuLpC4g7LC46rOgOiBodHRwczovL2dpdGh1Yi5jb20va25leC9rbmV4L2Jsb2IvMDFiMTc3YzQ4NWQ2OTZmMWI3Mjg1OGRlZTcyOGJhMTQzYzRmYWQ3Ni9saWIvbWlncmF0aW9ucy9taWdyYXRlL01pZ3JhdG9yLmpzI0w1NjBcbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICk7XG4gICAgICAgIGNhc2UgXCJyb2xsYmFja1wiOlxuICAgICAgICAgIHJldHVybiBQcm9taXNlLmFsbChcbiAgICAgICAgICAgIGNvbm5zLm1hcChhc3luYyAoeyBjb25uS2V5LCBrbmV4IH0pID0+IHtcbiAgICAgICAgICAgICAgY29uc3QgW2JhdGNoTm8sIGFwcGxpZWRdID0gYXdhaXQga25leC5taWdyYXRlLnJvbGxiYWNrKCk7XG4gICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgY29ubktleSxcbiAgICAgICAgICAgICAgICBiYXRjaE5vLFxuICAgICAgICAgICAgICAgIGFwcGxpZWQsIC8vIOydtOuyiCByb2xsYmFjayDtmLjstpzroZwg7J247ZW0IFwiZG93blwi7J20IOyggeyaqeuQnCg966Gk67Cx65CcKSDrp4jsnbTqt7jroIjsnbTshZgg7J2066aEKGUuZy4gXCIyMDI1MTEyNDIzMzU1N19jcmVhdGVfX2NvbXBhbmllcy50c1wiKeuTpOydmCDrsLDsl7TsnoXri4jri6QuIOywuOqzoDogaHR0cHM6Ly9naXRodWIuY29tL2tuZXgva25leC9ibG9iLzAxYjE3N2M0ODVkNjk2ZjFiNzI4NThkZWU3MjhiYTE0M2M0ZmFkNzYvbGliL21pZ3JhdGlvbnMvbWlncmF0ZS9NaWdyYXRvci5qcyNMNjExXG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICApO1xuICAgICAgfVxuICAgIH0pKCk7XG5cbiAgICAvLyBkZXN0cm95XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBjb25ucy5tYXAoKHsga25leCB9KSA9PiB7XG4gICAgICAgIHJldHVybiBrbmV4LmRlc3Ryb3koKTtcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICBOYWl0ZS50KFwibWlncmF0b3I6cnVuQWN0aW9uOnJlc3VsdFwiLCByZXN1bHQpO1xuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiDsgq3soJwg6rCA64ql7ZWcIOuniOydtOq3uOugiOydtOyFmCDsvZTrk5wg7YyM7J287J2EIOqygOymne2VqeuLiOuLpC5cbiAgICpcbiAgICogQHBhcmFtIGNvbm5zIOuniOydtOq3uOugiOydtOyFmCDsg4Htg5wg67Cw7Je0XG4gICAqIEBwYXJhbSBjb2RlTmFtZXMg7IKt7KCc7ZWgIOuniOydtOq3uOugiOydtOyFmCDsvZTrk5wg7YyM7J28IOydtOumhCDrsLDsl7RcbiAgICogQHJldHVybnMg7IKt7KCcIOqwgOuKpSDsl6zrtoAg67CPIOyggeyaqeuQnCDrp4jsnbTqt7jroIjsnbTshZgg7L2U65OcIO2MjOydvCDsnbTrpoRcbiAgICovXG4gIHZhbGlkYXRlRGVsZXRhYmxlKGNvbm5zOiBNaWdyYXRpb25TdGF0dXNbXCJjb25uc1wiXSwgY29kZU5hbWVzOiBzdHJpbmdbXSkge1xuICAgIGNvbnN0IGFwcGxpZWRDb2RlcyA9IGNvZGVOYW1lcy5maWx0ZXIoKGNvZGVOYW1lKSA9PlxuICAgICAgY29ubnMuc29tZSgoY29ubikgPT4gY29ubi5wZW5kaW5nLmluY2x1ZGVzKGNvZGVOYW1lKSA9PT0gZmFsc2UpLFxuICAgICk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgY2FuRGVsZXRlOiBhcHBsaWVkQ29kZXMubGVuZ3RoID09PSAwLFxuICAgICAgYXBwbGllZENvZGVzLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICog66eI7J206re466CI7J207IWYIOy9lOuTnCDtjIzsnbzsnYQg7IKt7KCc7ZWp64uI64ukLlxuICAgKlxuICAgKiBTb25hbXUgVUnsl5DshJwg7IKs7Jqp65Cp64uI64ukLlxuICAgKlxuICAgKiBAcGFyYW0gY29kZU5hbWVzIOyCreygnO2VoCDrp4jsnbTqt7jroIjsnbTshZgg7L2U65OcIO2MjOydvCDsnbTrpoQg67Cw7Je0XG4gICAqIEByZXR1cm5zIOyCreygnOuQnCDrp4jsnbTqt7jroIjsnbTshZgg7L2U65OcIO2MjOydvCDqsJzsiJhcbiAgICovXG4gIGFzeW5jIGRlbENvZGVzKGNvZGVOYW1lczogc3RyaW5nW10pOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IHsgY29ubnMgfSA9IGF3YWl0IHRoaXMuZ2V0U3RhdHVzKCk7XG4gICAgY29uc3QgeyBjYW5EZWxldGUsIGFwcGxpZWRDb2RlcyB9ID0gdGhpcy52YWxpZGF0ZURlbGV0YWJsZShjb25ucywgY29kZU5hbWVzKTtcbiAgICBpZiAoIWNhbkRlbGV0ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgWW91IGNhbm5vdCBkZWxldGUgYSBtaWdyYXRpb24gZmlsZSBpZiB0aGVyZSBpcyBhbHJlYWR5IGFwcGxpZWQuIEFwcGxpZWQgY29kZXM6ICR7YXBwbGllZENvZGVzLmpvaW4oXCIsIFwiKX1gLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gc3VtKFxuICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgIGNvZGVOYW1lcy5tYXAoYXN5bmMgKGNvZGVOYW1lKSA9PiB7XG4gICAgICAgICAgY29uc3QgZmlsZVBhdGggPSBgJHtTb25hbXUuYXBpUm9vdFBhdGh9L3NyYy9taWdyYXRpb25zLyR7Y29kZU5hbWV9LnRzYDtcbiAgICAgICAgICBpZiAoYXdhaXQgZXhpc3RzKGZpbGVQYXRoKSkge1xuICAgICAgICAgICAgYXdhaXQgdW5saW5rKGZpbGVQYXRoKTtcbiAgICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfSksXG4gICAgICApLFxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIGdlbkRhdGVUYWcoaW5kZXg6IG51bWJlciwgYmFzZURhdGU6IERhdGUgPSBuZXcgRGF0ZSgpKTogc3RyaW5nIHtcbiAgICBjb25zdCBkYXRlID0gbmV3IERhdGUoYmFzZURhdGUuZ2V0VGltZSgpICsgaW5kZXggKiAxMDAwKTtcbiAgICBjb25zdCBwYWQgPSAobnVtOiBudW1iZXIsIHNpemU6IG51bWJlciA9IDIpID0+IG51bS50b1N0cmluZygpLnBhZFN0YXJ0KHNpemUsIFwiMFwiKTtcbiAgICByZXR1cm4gKFxuICAgICAgZGF0ZS5nZXRGdWxsWWVhcigpLnRvU3RyaW5nKCkgK1xuICAgICAgcGFkKGRhdGUuZ2V0TW9udGgoKSArIDEpICtcbiAgICAgIHBhZChkYXRlLmdldERhdGUoKSkgK1xuICAgICAgcGFkKGRhdGUuZ2V0SG91cnMoKSkgK1xuICAgICAgcGFkKGRhdGUuZ2V0TWludXRlcygpKSArXG4gICAgICBwYWQoZGF0ZS5nZXRTZWNvbmRzKCkpXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiDrp4jsnbTqt7jroIjsnbTshZgg7L2U65OcIO2MjOydvOydhCDsg53shLHtlanri4jri6QuXG4gICAqXG4gICAqIFNvbmFtdSBVSeyXkOyEnCDsgqzsmqnrkKnri4jri6QuXG4gICAqXG4gICAqIEByZXR1cm5zIOyDneyEseuQnCDrp4jsnbTqt7jroIjsnbTshZgg7L2U65OcIO2MjOydvCDqsJzsiJhcbiAgICovXG4gIGFzeW5jIGdlbmVyYXRlUHJlcGFyZWRDb2RlcygpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IHsgcHJlcGFyZWRDb2RlcyB9ID0gYXdhaXQgdGhpcy5nZXRTdGF0dXMoKTtcbiAgICBOYWl0ZS50KFwibWlncmF0b3I6Z2VuZXJhdGVQcmVwYXJlZENvZGVzOnByZXBhcmVkQ29kZXNcIiwgcHJlcGFyZWRDb2Rlcyk7XG4gICAgaWYgKHByZXBhcmVkQ29kZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICBjb25zb2xlLmxvZyhjaGFsay5ncmVlbihcIlxcbu2YhOyerCDrqqjrkZAg7Iux7YGs65CcIOyDge2DnOyeheuLiOuLpC5cIikpO1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuXG4gICAgLy8g7Iuk7KCcIOy9lOuTnCDsg53shLFcbiAgICBjb25zdCBtaWdyYXRpb25zRGlyID0gYCR7U29uYW11LmFwaVJvb3RQYXRofS9zcmMvbWlncmF0aW9uc2A7XG5cbiAgICBmb3IgKGNvbnN0IFtpbmRleCwgcGNvZGVdIG9mIHByZXBhcmVkQ29kZXMuZW50cmllcygpKSB7XG4gICAgICBpZiAocGNvZGUuZm9ybWF0dGVkKSB7XG4gICAgICAgIGNvbnN0IGRhdGVUYWcgPSB0aGlzLmdlbkRhdGVUYWcoaW5kZXgpO1xuICAgICAgICBjb25zdCBmaWxlUGF0aCA9IGAke21pZ3JhdGlvbnNEaXJ9LyR7ZGF0ZVRhZ31fJHtwY29kZS50aXRsZX0udHNgO1xuICAgICAgICBhd2FpdCB3cml0ZUZpbGUoZmlsZVBhdGgsIHBjb2RlLmZvcm1hdHRlZCk7XG4gICAgICAgICFpc1Rlc3QoKSAmJiBjb25zb2xlLmxvZyhjaGFsay5ncmVlbihgTUlHUlRBSU9OIENSRUFURUQgJHtmaWxlUGF0aH1gKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHByZXBhcmVkQ29kZXMubGVuZ3RoO1xuICB9XG5cbiAgYXN5bmMgY29tcGFyZU1pZ3JhdGlvbnMoY29tcGFyZURCOiBLbmV4KTogUHJvbWlzZTxHZW5NaWdyYXRpb25Db2RlW10+IHtcbiAgICAvLyBFbnRpdHkg7Iic7ZqM7ZWY7JesIOyLse2BrFxuICAgIGNvbnN0IGVudGl0eUlkcyA9IEVudGl0eU1hbmFnZXIuZ2V0QWxsSWRzKCk7XG5cbiAgICAvLyDsobDsnbjthYzsnbTruJQg7Y+s7ZWo7ZWY7JesIEVudGl0eeyXkOyEnCBNaWdyYXRpb25TZXQg7LaU7LacXG4gICAgY29uc3QgZW50aXR5U2V0c1dpdGhKb2luVGFibGUgPSBlbnRpdHlJZHNcbiAgICAgIC5maWx0ZXIoKGVudGl0eUlkKSA9PiBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCkucHJvcHMubGVuZ3RoID4gMClcbiAgICAgIC5tYXAoKGVudGl0eUlkKSA9PiBnZXRNaWdyYXRpb25TZXRGcm9tRW50aXR5KEVudGl0eU1hbmFnZXIuZ2V0KGVudGl0eUlkKSkpO1xuXG4gICAgLy8g7KGw7J247YWM7J2067iU66eMIOy2lOy2nFxuICAgIGNvbnN0IGpvaW5UYWJsZXNXaXRoRHVwID0gZW50aXR5U2V0c1dpdGhKb2luVGFibGUuZmxhdE1hcCgoZW50aXR5U2V0KSA9PiBlbnRpdHlTZXQuam9pblRhYmxlcyk7XG4gICAgLy8g7KSR67O1IOygnOqxsCAo7KSR67O17J24IOqyveyasCBpbmRleGVz66W8IOuzke2VqSlcbiAgICBjb25zdCBqb2luVGFibGVzID0gT2JqZWN0LnZhbHVlcyhncm91cChqb2luVGFibGVzV2l0aER1cCwgKGp0KSA9PiBqdC50YWJsZSkpLm1hcCgodGFibGVzKSA9PiB7XG4gICAgICBhc3NlcnQodGFibGVzICE9PSB1bmRlZmluZWQsIFwidGFibGVzIGlzIHVuZGVmaW5lZFwiKTtcbiAgICAgIGlmICh0YWJsZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIHJldHVybiB0YWJsZXNbMF07XG4gICAgICB9XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi50YWJsZXNbMF0sXG4gICAgICAgIGluZGV4ZXM6IHVuaXF1ZShcbiAgICAgICAgICB0YWJsZXMuZmxhdE1hcCgodCkgPT4gdC5pbmRleGVzKSxcbiAgICAgICAgICAoaW5kZXgpID0+IFtpbmRleC50eXBlLCAuLi5pbmRleC5jb2x1bW5zLnNvcnQoKV0uam9pbihcIi1cIiksXG4gICAgICAgICksXG4gICAgICB9O1xuICAgIH0pO1xuXG4gICAgLy8g7KGw7J247YWM7J2067iUIO2PrO2VqO2VmOyXrCBNaWdyYXRpb25TZXQg67Cw7Je0XG4gICAgY29uc3QgZW50aXR5U2V0czogTWlncmF0aW9uU2V0W10gPSBbLi4uZW50aXR5U2V0c1dpdGhKb2luVGFibGUsIC4uLmpvaW5UYWJsZXNdO1xuXG4gICAgY29uc3QgY29kZXM6IEdlbk1pZ3JhdGlvbkNvZGVbXSA9IChcbiAgICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICBlbnRpdHlTZXRzLm1hcChhc3luYyAoZW50aXR5U2V0KSA9PiB7XG4gICAgICAgICAgY29uc3QgZGJTZXQgPSBhd2FpdCBQb3N0Z3JlU1FMU2NoZW1hUmVhZGVyLmdldE1pZ3JhdGlvblNldEZyb21EQihcbiAgICAgICAgICAgIGNvbXBhcmVEQixcbiAgICAgICAgICAgIGVudGl0eVNldC50YWJsZSxcbiAgICAgICAgICApO1xuICAgICAgICAgIE5haXRlLnQoYG1pZ3JhdG9yOmNvbXBhcmVNaWdyYXRpb25zOmVudGl0eVNldDoke2VudGl0eVNldC50YWJsZX1gLCBlbnRpdHlTZXQpO1xuICAgICAgICAgIE5haXRlLnQoYG1pZ3JhdG9yOmNvbXBhcmVNaWdyYXRpb25zOmRiU2V0OiR7ZW50aXR5U2V0LnRhYmxlfWAsIGRiU2V0KTtcblxuICAgICAgICAgIGlmIChkYlNldCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgLy8g6riw7KG0IO2FjOydtOu4lCDsl4bsnYwsIOyDiOuhnCDthYzsnbTruJQg7IOd7ISxXG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgZ2VuZXJhdGVDcmVhdGVDb2RlKGVudGl0eVNldCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIOq4sOyhtCDthYzsnbTruJQg7KG07J6s7ZWY64qUIOy8gOydtOyKpFxuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IGdlbmVyYXRlQWx0ZXJDb2RlKGVudGl0eVNldCwgZGJTZXQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSksXG4gICAgICApXG4gICAgKS5mbGF0KCk7XG5cbiAgICAvLyBub3JtYWwg7YOA7J6F7J20IOyVnuycvOuhnCwgZm9yZWlnbuydtCDrkqTroZxcbiAgICBjb2Rlcy5zb3J0KChjb2RlQSwgY29kZUIpID0+IHtcbiAgICAgIGlmIChjb2RlQS50eXBlID09PSBcImZvcmVpZ25cIiAmJiBjb2RlQi50eXBlID09PSBcIm5vcm1hbFwiKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfSBlbHNlIGlmIChjb2RlQS50eXBlID09PSBcIm5vcm1hbFwiICYmIGNvZGVCLnR5cGUgPT09IFwiZm9yZWlnblwiKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiAwO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIGNvZGVzO1xuICB9XG5cbiAgLyoqXG4gICAqIFNoYWRvdyBEQiDthYzsiqTtirjrpbwg7KeE7ZaJ7ZWp64uI64ukLlxuICAgKlxuICAgKiBTb25hbXUgVUnsl5DshJwg7IKs7Jqp65Cp64uI64ukLlxuICAgKlxuICAgKiBAcmV0dXJucyBTaGFkb3cgREIg7YWM7Iqk7Yq4IOqysOqzvFxuICAgKi9cbiAgYXN5bmMgcnVuU2hhZG93VGVzdCgpOiBQcm9taXNlPE1pZ3JhdGlvblJlc3VsdD4ge1xuICAgIGNvbnN0IHRkYkNvbm4gPSBTb25hbXUuZGJDb25maWcudGVzdC5jb25uZWN0aW9uIGFzIEtuZXguUGdDb25uZWN0aW9uQ29uZmlnO1xuICAgIGNvbnN0IHNoYWRvd0RhdGFiYXNlID0gYCR7dGRiQ29ubi5kYXRhYmFzZX1fX21pZ3JhdGlvbl9zaGFkb3dgO1xuXG4gICAgLy8g7YWM7Iqk7Yq4IOyDge2ZqeyXkOyEnOuKlCDtirjrnpzsnq3shZjsnYQg7LSI6riw7ZmU7ZWY6rOgLCDsg4gg642w7J207YSw67Kg7J207IqkIOy7pOuEpeyFmOydhCDqsIDsoLjsmYDslbwg7ZWoXG4gICAgaWYgKGlzVGVzdCgpKSB7XG4gICAgICBhd2FpdCBEQi5jbGVhclRlc3RUcmFuc2FjdGlvbigpO1xuICAgICAgYXdhaXQgREIuZGVzdHJveSgpO1xuICAgIH1cblxuICAgIC8vIOq4sOyhtCBTaGFkb3cgREIg7IKt7KCcIO2bhCBTaGFkb3cgREIg7IOd7ISxXG4gICAgY29uc3QgdGRiID0ga25leChTb25hbXUuZGJDb25maWcudGVzdCk7XG4gICAgIWlzVGVzdCgpICYmIGNvbnNvbGUubG9nKGNoYWxrLm1hZ2VudGEoYCR7c2hhZG93RGF0YWJhc2V9IOyCreygnGApKTtcbiAgICBhd2FpdCB0ZGIucmF3KGBEUk9QIERBVEFCQVNFIElGIEVYSVNUUyAke3NoYWRvd0RhdGFiYXNlfWApO1xuICAgIGF3YWl0IHRkYi5yYXcoYENSRUFURSBEQVRBQkFTRSAke3NoYWRvd0RhdGFiYXNlfSBURU1QTEFURSAke3RkYkNvbm4uZGF0YWJhc2V9YCk7XG5cbiAgICAvLyBTaGFkb3cgRELsl5Ag7Jew6rKwXG4gICAgY29uc3Qgc2RiID0ga25leCh7XG4gICAgICAuLi5Tb25hbXUuZGJDb25maWcudGVzdCxcbiAgICAgIGNvbm5lY3Rpb246IHtcbiAgICAgICAgLi4udGRiQ29ubixcbiAgICAgICAgZGF0YWJhc2U6IHNoYWRvd0RhdGFiYXNlLFxuICAgICAgICBwYXNzd29yZDogdGRiQ29ubi5wYXNzd29yZCxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyBzaGFkb3cgREIg7YWM7Iqk7Yq4IOynhO2WiVxuICAgIHRyeSB7XG4gICAgICBjb25zdCBbYmF0Y2hObywgYXBwbGllZF0gPSBhd2FpdCBzZGIubWlncmF0ZS5sYXRlc3QoKTtcbiAgICAgICFpc1Rlc3QoKSAmJlxuICAgICAgICBjb25zb2xlLmxvZyhjaGFsay5ncmVlbihcIlNoYWRvdyBEQiDthYzsiqTtirjsl5Ag7ISx6rO17ZaI7Iq164uI64ukIVwiKSwge1xuICAgICAgICAgIGJhdGNoTm8sXG4gICAgICAgICAgYXBwbGllZCxcbiAgICAgICAgfSk7XG5cbiAgICAgIHJldHVybiBbXG4gICAgICAgIHtcbiAgICAgICAgICBjb25uS2V5OiBcInNoYWRvd1wiLFxuICAgICAgICAgIGJhdGNoTm8sXG4gICAgICAgICAgYXBwbGllZCxcbiAgICAgICAgfSxcbiAgICAgIF07XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgY29uc29sZS5lcnJvcihlKTtcbiAgICAgIHRocm93IG5ldyBTZXJ2aWNlVW5hdmFpbGFibGVFeGNlcHRpb24oXCJTaGFkb3cgREIg7YWM7Iqk7Yq4IOynhO2WiSDspJEg7JeQ65+sXCIpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICAvLyBTaGFkb3cgREIg7Jew6rKwIOyiheujjFxuICAgICAgYXdhaXQgc2RiLmRlc3Ryb3koKTtcblxuICAgICAgLy8gU2hhZG93IERCIOyCreygnFxuICAgICAgIWlzVGVzdCgpICYmIGNvbnNvbGUubG9nKGNoYWxrLm1hZ2VudGEoYCR7c2hhZG93RGF0YWJhc2V9IOyCreygnGApKTtcbiAgICAgIGF3YWl0IHRkYi5yYXcoYERST1AgREFUQUJBU0UgSUYgRVhJU1RTICR7c2hhZG93RGF0YWJhc2V9YCk7XG5cbiAgICAgIC8vIFRlc3QgREIg7Jew6rKwIOyiheujjFxuICAgICAgYXdhaXQgdGRiLmRlc3Ryb3koKTtcbiAgICB9XG4gIH1cbn1cbiJdLCJuYW1lcyI6WyJhc3NlcnQiLCJjaGFsayIsIm1rZGlyIiwicmVhZGRpciIsInVubGluayIsIndyaXRlRmlsZSIsImtuZXgiLCJwYXRoIiwiZ3JvdXAiLCJzdW0iLCJ1bmlxdWUiLCJTb25hbXUiLCJEQiIsIkVudGl0eU1hbmFnZXIiLCJTZXJ2aWNlVW5hdmFpbGFibGVFeGNlcHRpb24iLCJOYWl0ZSIsImlzVGVzdCIsImV4aXN0cyIsImdlbmVyYXRlQWx0ZXJDb2RlIiwiZ2VuZXJhdGVDcmVhdGVDb2RlIiwiZ2V0TWlncmF0aW9uU2V0RnJvbUVudGl0eSIsIlBvc3RncmVTUUxTY2hlbWFSZWFkZXIiLCJNaWdyYXRvciIsImdldE1pZ3JhdGlvbkNvZGVzIiwic3JjTWlncmF0aW9uc0RpciIsImpvaW4iLCJhcGlSb290UGF0aCIsInJlY3Vyc2l2ZSIsImNvZGVzIiwiZmlsdGVyIiwiZiIsImVuZHNXaXRoIiwibWFwIiwibmFtZSIsInJlcGxhY2UiLCJzb3J0IiwiYSIsImIiLCJ0IiwiZ2V0U3RhdHVzIiwiY29ubktleXMiLCJPYmplY3QiLCJrZXlzIiwiZGJDb25maWciLCJrZXkiLCJtaWdyYXRpb25TdGF0dXNFcnJvciIsInN0YXR1c2VzIiwiUHJvbWlzZSIsImFsbCIsImNvbm5LZXkiLCJrbmV4T3B0aW9ucyIsInRDb25uIiwic3RhdHVzIiwibWlncmF0ZSIsImVyciIsImNvbnNvbGUiLCJ3YXJuIiwieWVsbG93IiwiSlNPTiIsInN0cmluZ2lmeSIsImNvbm5lY3Rpb24iLCJFcnJvciIsIm1lc3NhZ2UiLCJTdHJpbmciLCJwZW5kaW5nIiwiZmRMaXN0IiwibGlzdCIsImZkIiwiZmlsZSIsImN1cnJlbnRWZXJzaW9uIiwiX2VyciIsImRlc3Ryb3kiLCJjb25uU3RyaW5nIiwidXNlciIsImhvc3QiLCJwb3J0IiwiZGF0YWJhc2UiLCJwcmVwYXJlZENvZGVzIiwic3RhdHVzMGNvbm4iLCJmaW5kIiwidW5kZWZpbmVkIiwiY29tcGFyZURCY29ubiIsImdlbkNvZGVzIiwiY29tcGFyZU1pZ3JhdGlvbnMiLCJjb25ucyIsImVycm9yIiwicnVuQWN0aW9uIiwiYWN0aW9uIiwidGFyZ2V0cyIsImNvbmZpZ3MiLCJ0YXJnZXQiLCJvcHRpb25zIiwiYyIsImNvbmZpZyIsInJlc3VsdCIsImJhdGNoTm8iLCJhcHBsaWVkIiwibGF0ZXN0Iiwicm9sbGJhY2siLCJ2YWxpZGF0ZURlbGV0YWJsZSIsImNvZGVOYW1lcyIsImFwcGxpZWRDb2RlcyIsImNvZGVOYW1lIiwic29tZSIsImNvbm4iLCJpbmNsdWRlcyIsImNhbkRlbGV0ZSIsImxlbmd0aCIsImRlbENvZGVzIiwiZmlsZVBhdGgiLCJnZW5EYXRlVGFnIiwiaW5kZXgiLCJiYXNlRGF0ZSIsIkRhdGUiLCJkYXRlIiwiZ2V0VGltZSIsInBhZCIsIm51bSIsInNpemUiLCJ0b1N0cmluZyIsInBhZFN0YXJ0IiwiZ2V0RnVsbFllYXIiLCJnZXRNb250aCIsImdldERhdGUiLCJnZXRIb3VycyIsImdldE1pbnV0ZXMiLCJnZXRTZWNvbmRzIiwiZ2VuZXJhdGVQcmVwYXJlZENvZGVzIiwibG9nIiwiZ3JlZW4iLCJtaWdyYXRpb25zRGlyIiwicGNvZGUiLCJlbnRyaWVzIiwiZm9ybWF0dGVkIiwiZGF0ZVRhZyIsInRpdGxlIiwiY29tcGFyZURCIiwiZW50aXR5SWRzIiwiZ2V0QWxsSWRzIiwiZW50aXR5U2V0c1dpdGhKb2luVGFibGUiLCJlbnRpdHlJZCIsImdldCIsInByb3BzIiwiam9pblRhYmxlc1dpdGhEdXAiLCJmbGF0TWFwIiwiZW50aXR5U2V0Iiwiam9pblRhYmxlcyIsInZhbHVlcyIsImp0IiwidGFibGUiLCJ0YWJsZXMiLCJpbmRleGVzIiwidHlwZSIsImNvbHVtbnMiLCJlbnRpdHlTZXRzIiwiZGJTZXQiLCJnZXRNaWdyYXRpb25TZXRGcm9tREIiLCJmbGF0IiwiY29kZUEiLCJjb2RlQiIsInJ1blNoYWRvd1Rlc3QiLCJ0ZGJDb25uIiwidGVzdCIsInNoYWRvd0RhdGFiYXNlIiwiY2xlYXJUZXN0VHJhbnNhY3Rpb24iLCJ0ZGIiLCJtYWdlbnRhIiwicmF3Iiwic2RiIiwicGFzc3dvcmQiLCJlIl0sIm1hcHBpbmdzIjoiQUFBQSxPQUFPQSxZQUFZLFNBQVM7QUFDNUIsT0FBT0MsV0FBVyxRQUFRO0FBQzFCLFNBQVND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
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { Knex } from "knex";
|
|
2
|
+
import type { MigrationColumn, MigrationSet } from "../types/types";
|
|
3
|
+
export type PgColumn = {
|
|
4
|
+
column_name: string;
|
|
5
|
+
data_type: string;
|
|
6
|
+
udt_name: string;
|
|
7
|
+
character_maximum_length: number | null;
|
|
8
|
+
numeric_precision: number | null;
|
|
9
|
+
numeric_scale: number | null;
|
|
10
|
+
is_nullable: string;
|
|
11
|
+
column_default: string | null;
|
|
12
|
+
};
|
|
13
|
+
type PgIndex = {
|
|
14
|
+
index_name: string;
|
|
15
|
+
column_name: string;
|
|
16
|
+
is_unique: boolean;
|
|
17
|
+
is_primary: boolean;
|
|
18
|
+
index_type: string;
|
|
19
|
+
};
|
|
20
|
+
type PgForeign = {
|
|
21
|
+
constraint_name: string;
|
|
22
|
+
column_name: string;
|
|
23
|
+
foreign_table_name: string;
|
|
24
|
+
foreign_column_name: string;
|
|
25
|
+
update_rule: string;
|
|
26
|
+
delete_rule: string;
|
|
27
|
+
};
|
|
28
|
+
declare class PostgreSQLSchemaReaderClass {
|
|
29
|
+
/**
|
|
30
|
+
* DB에서 테이블 정보를 읽어서 MigrationSet을 만들어옵니다.
|
|
31
|
+
* @param compareDB Knex 인스턴스
|
|
32
|
+
* @param table 테이블 이름
|
|
33
|
+
* @returns MigrationSet 객체
|
|
34
|
+
*/
|
|
35
|
+
getMigrationSetFromDB(compareDB: Knex, table: string): Promise<MigrationSet | null>;
|
|
36
|
+
/**
|
|
37
|
+
* PostgreSQL의 constraint action을 Knex 형식으로 변환
|
|
38
|
+
*/
|
|
39
|
+
private mapConstraintAction;
|
|
40
|
+
/**
|
|
41
|
+
* 기존 테이블 읽어서 cols, indexes, foreigns 반환
|
|
42
|
+
*/
|
|
43
|
+
readTable(compareDB: Knex, tableName: string): Promise<[PgColumn[], PgIndex[], PgForeign[]]>;
|
|
44
|
+
/**
|
|
45
|
+
* PostgreSQL 컬럼 타입을 분석하여 MigrationColumn 객체로 변환합니다.
|
|
46
|
+
*/
|
|
47
|
+
resolveDBColType(dbColumn: PgColumn): Pick<MigrationColumn, "type" | "length" | "precision" | "scale" | "numberType">;
|
|
48
|
+
}
|
|
49
|
+
export declare const PostgreSQLSchemaReader: PostgreSQLSchemaReaderClass;
|
|
50
|
+
export {};
|
|
51
|
+
//# sourceMappingURL=postgresql-schema-reader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgresql-schema-reader.d.ts","sourceRoot":"","sources":["../../src/migration/postgresql-schema-reader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAEjC,OAAO,KAAK,EACV,eAAe,EAGf,YAAY,EAEb,MAAM,gBAAgB,CAAC;AAExB,MAAM,MAAM,QAAQ,GAAG;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,wBAAwB,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B,CAAC;AAEF,KAAK,OAAO,GAAG;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,KAAK,SAAS,GAAG;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,cAAM,2BAA2B;IAC/B;;;;;OAKG;IACG,qBAAqB,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAuFzF;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAW3B;;OAEG;IACG,SAAS,CACb,SAAS,EAAE,IAAI,EACf,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;IAkEhD;;OAEG;IACH,gBAAgB,CACd,QAAQ,EAAE,QAAQ,GACjB,IAAI,CAAC,eAAe,EAAE,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,OAAO,GAAG,YAAY,CAAC;CAmFnF;AAED,eAAO,MAAM,sBAAsB,6BAAoC,CAAC"}
|