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,135 +1,48 @@
|
|
|
1
|
-
import
|
|
2
|
-
import knex, { Knex } from "knex";
|
|
1
|
+
import assert from "assert";
|
|
3
2
|
import chalk from "chalk";
|
|
4
|
-
import { DateTime } from "luxon";
|
|
5
3
|
import { mkdir, readdir, unlink, writeFile } from "fs/promises";
|
|
6
|
-
import {
|
|
7
|
-
import prompts from "prompts";
|
|
8
|
-
import { execSync } from "child_process";
|
|
4
|
+
import knex, { type Knex } from "knex";
|
|
9
5
|
import path from "path";
|
|
10
|
-
import {
|
|
11
|
-
import { EntityManager } from "../entity/entity-manager";
|
|
6
|
+
import { group, sum, unique } from "radashi";
|
|
12
7
|
import { Sonamu } from "../api";
|
|
8
|
+
import { DB, type SonamuDBConfig } from "../database/db";
|
|
9
|
+
import { EntityManager } from "../entity/entity-manager";
|
|
13
10
|
import { ServiceUnavailableException } from "../exceptions/so-exceptions";
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
11
|
+
import { Naite } from "../naite/naite";
|
|
12
|
+
import type { GenMigrationCode, MigrationSet } from "../types/types";
|
|
13
|
+
import { isTest } from "../utils/controller";
|
|
14
|
+
import { exists } from "../utils/fs-utils";
|
|
15
|
+
import { generateAlterCode, generateCreateCode } from "./code-generation";
|
|
18
16
|
import { getMigrationSetFromEntity } from "./migration-set";
|
|
17
|
+
import { PostgreSQLSchemaReader } from "./postgresql-schema-reader";
|
|
18
|
+
import type { ConnString, MigrationCode, MigrationStatus } from "./types";
|
|
19
19
|
|
|
20
|
-
type
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
export type MigrationResult = {
|
|
21
|
+
connKey: string;
|
|
22
|
+
batchNo: number;
|
|
23
|
+
applied: string[];
|
|
24
|
+
}[];
|
|
24
25
|
|
|
25
26
|
export class Migrator {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
pending: Knex;
|
|
29
|
-
shadow: Knex;
|
|
30
|
-
apply: Knex[];
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
constructor(private readonly options: MigratorOptions) {
|
|
34
|
-
const { dbConfig } = Sonamu;
|
|
35
|
-
|
|
36
|
-
if (this.options.mode === "dev") {
|
|
37
|
-
const devDB = knex(dbConfig.development_master);
|
|
38
|
-
const testDB = knex(dbConfig.test);
|
|
39
|
-
const fixtureLocalDB = knex(dbConfig.fixture_local);
|
|
40
|
-
|
|
41
|
-
const applyDBs = [devDB, testDB, fixtureLocalDB];
|
|
42
|
-
if (
|
|
43
|
-
(dbConfig.fixture_local.connection as Knex.MySql2ConnectionConfig)
|
|
44
|
-
.host !==
|
|
45
|
-
(dbConfig.fixture_remote.connection as Knex.MySql2ConnectionConfig)
|
|
46
|
-
.host ||
|
|
47
|
-
(dbConfig.fixture_local.connection as Knex.MySql2ConnectionConfig)
|
|
48
|
-
.database !==
|
|
49
|
-
(dbConfig.fixture_remote.connection as Knex.MySql2ConnectionConfig)
|
|
50
|
-
.database
|
|
51
|
-
) {
|
|
52
|
-
const fixtureRemoteDB = knex(dbConfig.fixture_remote);
|
|
53
|
-
applyDBs.push(fixtureRemoteDB);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
this.targets = {
|
|
57
|
-
compare: devDB,
|
|
58
|
-
pending: devDB,
|
|
59
|
-
shadow: testDB,
|
|
60
|
-
apply: applyDBs,
|
|
61
|
-
};
|
|
62
|
-
} else if (this.options.mode === "deploy") {
|
|
63
|
-
const productionDB = knex(dbConfig.production_master);
|
|
64
|
-
const testDB = knex(dbConfig.test);
|
|
65
|
-
|
|
66
|
-
this.targets = {
|
|
67
|
-
pending: productionDB,
|
|
68
|
-
shadow: testDB,
|
|
69
|
-
apply: [productionDB],
|
|
70
|
-
};
|
|
71
|
-
} else {
|
|
72
|
-
throw new Error(`잘못된 모드 ${this.options.mode} 입력`);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
private async getMigrationCodes(): Promise<{
|
|
77
|
-
normal: MigrationCode[];
|
|
78
|
-
onlyTs: MigrationCode[];
|
|
79
|
-
onlyJs: MigrationCode[];
|
|
80
|
-
}> {
|
|
81
|
-
const srcMigrationsDir = `${Sonamu.apiRootPath}/src/migrations`;
|
|
82
|
-
const distMigrationsDir = `${Sonamu.apiRootPath}/dist/migrations`;
|
|
27
|
+
private async getMigrationCodes(): Promise<MigrationCode[]> {
|
|
28
|
+
const srcMigrationsDir = path.join(Sonamu.apiRootPath, "src", "migrations"); // 이건 환경에 관계없이 항상 src에서 찾아야 해요.
|
|
83
29
|
|
|
84
30
|
if (!(await exists(srcMigrationsDir))) {
|
|
85
31
|
await mkdir(srcMigrationsDir, {
|
|
86
32
|
recursive: true,
|
|
87
33
|
});
|
|
88
34
|
}
|
|
89
|
-
if (!(await exists(distMigrationsDir))) {
|
|
90
|
-
await mkdir(distMigrationsDir, {
|
|
91
|
-
recursive: true,
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
const srcMigrations = (await readdir(srcMigrationsDir))
|
|
95
|
-
.filter((f) => f.endsWith(".ts"))
|
|
96
|
-
.map((f) => f.split(".")[0]);
|
|
97
|
-
const distMigrations = (await readdir(distMigrationsDir))
|
|
98
|
-
.filter((f) => f.endsWith(".js"))
|
|
99
|
-
.map((f) => f.split(".")[0]);
|
|
100
35
|
|
|
101
|
-
const
|
|
102
|
-
.
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
.sort((a, b) => (a > b ? 1 : -1));
|
|
109
|
-
|
|
110
|
-
const onlyTs = _.difference(srcMigrations, distMigrations).map(
|
|
111
|
-
(filename) => {
|
|
112
|
-
return {
|
|
113
|
-
name: filename,
|
|
114
|
-
path: path.join(srcMigrationsDir, filename) + ".ts",
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
const onlyJs = _.difference(distMigrations, srcMigrations).map(
|
|
120
|
-
(filename) => {
|
|
121
|
-
return {
|
|
122
|
-
name: filename,
|
|
123
|
-
path: path.join(distMigrationsDir, filename) + ".js",
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
);
|
|
36
|
+
const codes = (await readdir(srcMigrationsDir))
|
|
37
|
+
.filter((f) => f.endsWith(".ts"))
|
|
38
|
+
.map((f) => ({
|
|
39
|
+
name: f.replace(".ts", ""),
|
|
40
|
+
path: path.join(srcMigrationsDir, f),
|
|
41
|
+
}))
|
|
42
|
+
.sort((a, b) => (a.name < b.name ? 1 : -1)); // 이름 내림차순 정렬(최신순)
|
|
127
43
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
onlyTs,
|
|
131
|
-
onlyJs,
|
|
132
|
-
};
|
|
44
|
+
Naite.t("migrator:getMigrationCodes:results", codes);
|
|
45
|
+
return codes;
|
|
133
46
|
}
|
|
134
47
|
|
|
135
48
|
/**
|
|
@@ -142,30 +55,15 @@ export class Migrator {
|
|
|
142
55
|
* @returns
|
|
143
56
|
*/
|
|
144
57
|
async getStatus(): Promise<MigrationStatus> {
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
console.debug({ onlyTs });
|
|
148
|
-
throw new ServiceUnavailableException(
|
|
149
|
-
`There are un-compiled TS migration files.\nPlease compile them first. You might want to run a development server with HMR.\n\n${onlyTs
|
|
150
|
-
.map((f) => f.name)
|
|
151
|
-
.join("\n")}`
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
if (onlyJs.length > 0) {
|
|
155
|
-
console.debug({ onlyJs });
|
|
156
|
-
await Promise.all(
|
|
157
|
-
onlyJs.map(async (f) => {
|
|
158
|
-
execSync(
|
|
159
|
-
`rm -f ${f.path.replace("/src/", "/dist/").replace(".ts", ".js")}`
|
|
160
|
-
);
|
|
161
|
-
})
|
|
162
|
-
);
|
|
163
|
-
}
|
|
58
|
+
const codes = await this.getMigrationCodes();
|
|
59
|
+
Naite.t("migrator:getStatus:codes", codes);
|
|
164
60
|
|
|
165
61
|
const connKeys = Object.keys(Sonamu.dbConfig).filter(
|
|
166
|
-
(key) => key.endsWith("_slave") === false
|
|
62
|
+
(key) => key.endsWith("_slave") === false,
|
|
167
63
|
) as (keyof typeof Sonamu.dbConfig)[];
|
|
168
64
|
|
|
65
|
+
let migrationStatusError: string | undefined;
|
|
66
|
+
|
|
169
67
|
const statuses = await Promise.all(
|
|
170
68
|
connKeys.map(async (connKey) => {
|
|
171
69
|
const knexOptions = Sonamu.dbConfig[connKey];
|
|
@@ -177,51 +75,59 @@ export class Migrator {
|
|
|
177
75
|
} catch (err) {
|
|
178
76
|
console.warn(
|
|
179
77
|
chalk.yellow(
|
|
180
|
-
`${connKey}의 마이그레이션 상태를 가져오는 데에 실패하였습니다. 데이터베이스가 올바르게 구성되지 않은 것 같습니다. 확인하시고 다시 시도해주세요.\n시도한 연결 설정:\n${JSON.stringify(knexOptions.connection, null, 2)}\n발생한 에러:\n${err}\n
|
|
181
|
-
)
|
|
78
|
+
`${connKey}의 마이그레이션 상태를 가져오는 데에 실패하였습니다. 데이터베이스가 올바르게 구성되지 않은 것 같습니다. 확인하시고 다시 시도해주세요.\n시도한 연결 설정:\n${JSON.stringify(knexOptions.connection, null, 2)}\n발생한 에러:\n${err}\n`,
|
|
79
|
+
),
|
|
182
80
|
);
|
|
183
|
-
|
|
81
|
+
migrationStatusError = err instanceof Error ? err.message : String(err);
|
|
82
|
+
return "error";
|
|
184
83
|
}
|
|
185
84
|
})();
|
|
186
|
-
const pending = await (async () => {
|
|
85
|
+
const pending: string[] = await (async () => {
|
|
187
86
|
try {
|
|
188
87
|
const [, fdList] = await tConn.migrate.list();
|
|
189
|
-
return fdList.map((fd: { file: string }) =>
|
|
190
|
-
fd.file.replace(".js", "")
|
|
191
|
-
);
|
|
88
|
+
return fdList.map((fd: { file: string }) => fd.file.replace(".ts", ""));
|
|
192
89
|
} catch (err) {
|
|
90
|
+
migrationStatusError = err instanceof Error ? err.message : String(err);
|
|
193
91
|
return [];
|
|
194
92
|
}
|
|
195
93
|
})();
|
|
196
94
|
const currentVersion = await (async () => {
|
|
197
95
|
try {
|
|
198
96
|
return await tConn.migrate.currentVersion();
|
|
199
|
-
} catch (
|
|
97
|
+
} catch (_err) {
|
|
98
|
+
migrationStatusError = _err instanceof Error ? _err.message : String(_err);
|
|
200
99
|
return "error";
|
|
201
100
|
}
|
|
202
101
|
})();
|
|
102
|
+
Naite.t("migrator:getStatus:status", status);
|
|
203
103
|
|
|
204
|
-
const connection =
|
|
205
|
-
knexOptions.connection as Knex.MySql2ConnectionConfig;
|
|
104
|
+
const connection = knexOptions.connection as Knex.PgConnectionConfig;
|
|
206
105
|
|
|
207
106
|
await tConn.destroy();
|
|
208
107
|
|
|
209
108
|
return {
|
|
210
109
|
name: connKey.replace("_master", ""),
|
|
211
110
|
connKey,
|
|
212
|
-
connString: `
|
|
111
|
+
connString: `pg://${connection.user ?? ""}@${connection.host}:${
|
|
213
112
|
connection.port
|
|
214
113
|
}/${connection.database}` as ConnString,
|
|
215
114
|
currentVersion,
|
|
216
|
-
status,
|
|
115
|
+
status: status as number | "error",
|
|
217
116
|
pending,
|
|
218
117
|
};
|
|
219
|
-
})
|
|
118
|
+
}),
|
|
220
119
|
);
|
|
221
120
|
|
|
121
|
+
Naite.t("migrator:getStatus:conns", statuses);
|
|
122
|
+
|
|
222
123
|
const preparedCodes: GenMigrationCode[] = await (async () => {
|
|
223
124
|
const status0conn = statuses.find((status) => status.status === 0);
|
|
224
125
|
if (status0conn === undefined) {
|
|
126
|
+
console.warn(
|
|
127
|
+
chalk.yellow(
|
|
128
|
+
`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.`,
|
|
129
|
+
),
|
|
130
|
+
);
|
|
225
131
|
return [];
|
|
226
132
|
}
|
|
227
133
|
|
|
@@ -233,24 +139,14 @@ export class Migrator {
|
|
|
233
139
|
return genCodes;
|
|
234
140
|
})();
|
|
235
141
|
|
|
142
|
+
Naite.t("migrator:getStatus:preparedCodes", preparedCodes);
|
|
143
|
+
|
|
236
144
|
return {
|
|
237
145
|
conns: statuses,
|
|
238
|
-
codes
|
|
146
|
+
codes,
|
|
239
147
|
preparedCodes,
|
|
148
|
+
error: migrationStatusError,
|
|
240
149
|
};
|
|
241
|
-
/*
|
|
242
|
-
TS/JS 코드 컴파일 상태 확인
|
|
243
|
-
1. 원본 파일 없는 JS파일이 존재하는 경우: 삭제
|
|
244
|
-
2. 컴파일 되지 않은 TS파일이 존재하는 경우: throw 쳐서 데브 서버 오픈 요청
|
|
245
|
-
|
|
246
|
-
DB 마이그레이션 상태 확인
|
|
247
|
-
1. 전체 DB설정에 대해서 현재 마이그레이션 상태 확인
|
|
248
|
-
- connKey: string
|
|
249
|
-
- status: number
|
|
250
|
-
- currentVersion: string
|
|
251
|
-
- list: { file: string; directory: string }[]
|
|
252
|
-
|
|
253
|
-
*/
|
|
254
150
|
}
|
|
255
151
|
|
|
256
152
|
/**
|
|
@@ -265,16 +161,13 @@ export class Migrator {
|
|
|
265
161
|
*/
|
|
266
162
|
async runAction(
|
|
267
163
|
action: "apply" | "rollback",
|
|
268
|
-
targets: (keyof SonamuDBConfig)[]
|
|
269
|
-
): Promise<
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
applied: string[];
|
|
274
|
-
}[]
|
|
275
|
-
> {
|
|
164
|
+
targets: (keyof SonamuDBConfig)[],
|
|
165
|
+
): Promise<MigrationResult> {
|
|
166
|
+
Naite.t("migrator:runAction:action", action);
|
|
167
|
+
Naite.t("migrator:runAction:targets", targets);
|
|
168
|
+
|
|
276
169
|
// get uniq knex configs
|
|
277
|
-
const configs =
|
|
170
|
+
const configs = unique(
|
|
278
171
|
targets
|
|
279
172
|
.map((target) => ({
|
|
280
173
|
connKey: target,
|
|
@@ -282,9 +175,9 @@ export class Migrator {
|
|
|
282
175
|
}))
|
|
283
176
|
.filter((c) => c.options !== undefined),
|
|
284
177
|
({ options }) =>
|
|
285
|
-
`${(options.connection as Knex.
|
|
286
|
-
(options.connection as Knex.
|
|
287
|
-
}/${(options.connection as Knex.
|
|
178
|
+
`${(options.connection as Knex.PgConnectionConfig).host}:${
|
|
179
|
+
(options.connection as Knex.PgConnectionConfig).port ?? 5432
|
|
180
|
+
}/${(options.connection as Knex.PgConnectionConfig).database}`,
|
|
288
181
|
);
|
|
289
182
|
|
|
290
183
|
// get connections
|
|
@@ -292,7 +185,7 @@ export class Migrator {
|
|
|
292
185
|
configs.map(async (config) => ({
|
|
293
186
|
connKey: config.connKey,
|
|
294
187
|
knex: knex(config.options),
|
|
295
|
-
}))
|
|
188
|
+
})),
|
|
296
189
|
);
|
|
297
190
|
|
|
298
191
|
// action
|
|
@@ -305,9 +198,9 @@ export class Migrator {
|
|
|
305
198
|
return {
|
|
306
199
|
connKey,
|
|
307
200
|
batchNo,
|
|
308
|
-
applied,
|
|
201
|
+
applied, // 이번 latest 호출로 인해 "up"이 적용된 마이그레이션 이름(e.g. "20251124233557_create__companies.ts")들의 배열입니다. 참고: https://github.com/knex/knex/blob/01b177c485d696f1b72858dee728ba143c4fad76/lib/migrations/migrate/Migrator.js#L560
|
|
309
202
|
};
|
|
310
|
-
})
|
|
203
|
+
}),
|
|
311
204
|
);
|
|
312
205
|
case "rollback":
|
|
313
206
|
return Promise.all(
|
|
@@ -316,9 +209,9 @@ export class Migrator {
|
|
|
316
209
|
return {
|
|
317
210
|
connKey,
|
|
318
211
|
batchNo,
|
|
319
|
-
applied,
|
|
212
|
+
applied, // 이번 rollback 호출로 인해 "down"이 적용된(=롤백된) 마이그레이션 이름(e.g. "20251124233557_create__companies.ts")들의 배열입니다. 참고: https://github.com/knex/knex/blob/01b177c485d696f1b72858dee728ba143c4fad76/lib/migrations/migrate/Migrator.js#L611
|
|
320
213
|
};
|
|
321
|
-
})
|
|
214
|
+
}),
|
|
322
215
|
);
|
|
323
216
|
}
|
|
324
217
|
})();
|
|
@@ -327,12 +220,32 @@ export class Migrator {
|
|
|
327
220
|
await Promise.all(
|
|
328
221
|
conns.map(({ knex }) => {
|
|
329
222
|
return knex.destroy();
|
|
330
|
-
})
|
|
223
|
+
}),
|
|
331
224
|
);
|
|
332
225
|
|
|
226
|
+
Naite.t("migrator:runAction:result", result);
|
|
227
|
+
|
|
333
228
|
return result;
|
|
334
229
|
}
|
|
335
230
|
|
|
231
|
+
/**
|
|
232
|
+
* 삭제 가능한 마이그레이션 코드 파일을 검증합니다.
|
|
233
|
+
*
|
|
234
|
+
* @param conns 마이그레이션 상태 배열
|
|
235
|
+
* @param codeNames 삭제할 마이그레이션 코드 파일 이름 배열
|
|
236
|
+
* @returns 삭제 가능 여부 및 적용된 마이그레이션 코드 파일 이름
|
|
237
|
+
*/
|
|
238
|
+
validateDeletable(conns: MigrationStatus["conns"], codeNames: string[]) {
|
|
239
|
+
const appliedCodes = codeNames.filter((codeName) =>
|
|
240
|
+
conns.some((conn) => conn.pending.includes(codeName) === false),
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
return {
|
|
244
|
+
canDelete: appliedCodes.length === 0,
|
|
245
|
+
appliedCodes,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
336
249
|
/**
|
|
337
250
|
* 마이그레이션 코드 파일을 삭제합니다.
|
|
338
251
|
*
|
|
@@ -343,36 +256,38 @@ export class Migrator {
|
|
|
343
256
|
*/
|
|
344
257
|
async delCodes(codeNames: string[]): Promise<number> {
|
|
345
258
|
const { conns } = await this.getStatus();
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
return codeNames.some(
|
|
349
|
-
(codeName) => conn.pending.includes(codeName) === false
|
|
350
|
-
);
|
|
351
|
-
})
|
|
352
|
-
) {
|
|
259
|
+
const { canDelete, appliedCodes } = this.validateDeletable(conns, codeNames);
|
|
260
|
+
if (!canDelete) {
|
|
353
261
|
throw new Error(
|
|
354
|
-
|
|
262
|
+
`You cannot delete a migration file if there is already applied. Applied codes: ${appliedCodes.join(", ")}`,
|
|
355
263
|
);
|
|
356
264
|
}
|
|
357
265
|
|
|
358
|
-
|
|
359
|
-
.
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
266
|
+
return sum(
|
|
267
|
+
await Promise.all(
|
|
268
|
+
codeNames.map(async (codeName) => {
|
|
269
|
+
const filePath = `${Sonamu.apiRootPath}/src/migrations/${codeName}.ts`;
|
|
270
|
+
if (await exists(filePath)) {
|
|
271
|
+
await unlink(filePath);
|
|
272
|
+
return 1;
|
|
273
|
+
}
|
|
274
|
+
return 0;
|
|
275
|
+
}),
|
|
276
|
+
),
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
private genDateTag(index: number, baseDate: Date = new Date()): string {
|
|
281
|
+
const date = new Date(baseDate.getTime() + index * 1000);
|
|
282
|
+
const pad = (num: number, size: number = 2) => num.toString().padStart(size, "0");
|
|
283
|
+
return (
|
|
284
|
+
date.getFullYear().toString() +
|
|
285
|
+
pad(date.getMonth() + 1) +
|
|
286
|
+
pad(date.getDate()) +
|
|
287
|
+
pad(date.getHours()) +
|
|
288
|
+
pad(date.getMinutes()) +
|
|
289
|
+
pad(date.getSeconds())
|
|
374
290
|
);
|
|
375
|
-
return _.sum(res);
|
|
376
291
|
}
|
|
377
292
|
|
|
378
293
|
/**
|
|
@@ -384,6 +299,7 @@ export class Migrator {
|
|
|
384
299
|
*/
|
|
385
300
|
async generatePreparedCodes(): Promise<number> {
|
|
386
301
|
const { preparedCodes } = await this.getStatus();
|
|
302
|
+
Naite.t("migrator:generatePreparedCodes:preparedCodes", preparedCodes);
|
|
387
303
|
if (preparedCodes.length === 0) {
|
|
388
304
|
console.log(chalk.green("\n현재 모두 싱크된 상태입니다."));
|
|
389
305
|
return 0;
|
|
@@ -394,392 +310,54 @@ export class Migrator {
|
|
|
394
310
|
|
|
395
311
|
for (const [index, pcode] of preparedCodes.entries()) {
|
|
396
312
|
if (pcode.formatted) {
|
|
397
|
-
const dateTag =
|
|
398
|
-
.plus({ seconds: index })
|
|
399
|
-
.toFormat("yyyyMMddHHmmss");
|
|
313
|
+
const dateTag = this.genDateTag(index);
|
|
400
314
|
const filePath = `${migrationsDir}/${dateTag}_${pcode.title}.ts`;
|
|
401
|
-
await writeFile(filePath, pcode.formatted
|
|
402
|
-
console.log(chalk.green(`MIGRTAION CREATED ${filePath}`));
|
|
315
|
+
await writeFile(filePath, pcode.formatted);
|
|
316
|
+
!isTest() && console.log(chalk.green(`MIGRTAION CREATED ${filePath}`));
|
|
403
317
|
}
|
|
404
318
|
}
|
|
405
319
|
|
|
406
320
|
return preparedCodes.length;
|
|
407
321
|
}
|
|
408
322
|
|
|
409
|
-
|
|
410
|
-
* pending 마이그레이션 목록을 삭제합니다.
|
|
411
|
-
*
|
|
412
|
-
* CLI에서 사용됩니다.
|
|
413
|
-
*/
|
|
414
|
-
async clearPendingList(): Promise<void> {
|
|
415
|
-
const [, pendingList] = (await this.targets.pending.migrate.list()) as [
|
|
416
|
-
unknown,
|
|
417
|
-
{
|
|
418
|
-
file: string;
|
|
419
|
-
directory: string;
|
|
420
|
-
}[],
|
|
421
|
-
];
|
|
422
|
-
const migrationsDir = `${Sonamu.apiRootPath}/src/migrations`;
|
|
423
|
-
const delList = pendingList.map((df) => {
|
|
424
|
-
return path.join(migrationsDir, df.file).replace(".js", ".ts");
|
|
425
|
-
});
|
|
426
|
-
for (let p of delList) {
|
|
427
|
-
if (await exists(p)) {
|
|
428
|
-
await unlink(p);
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
await this.cleanUpDist(true);
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
/**
|
|
435
|
-
* 마이그레이션 코드 파일을 확인합니다.
|
|
436
|
-
*
|
|
437
|
-
* CLI에서 사용됩니다.
|
|
438
|
-
*/
|
|
439
|
-
async check(): Promise<void> {
|
|
440
|
-
const codes = await this.compareMigrations(this.targets.compare!);
|
|
441
|
-
if (codes.length === 0) {
|
|
442
|
-
console.log(chalk.green("\n현재 모두 싱크된 상태입니다."));
|
|
443
|
-
return;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
// 현재 생성된 코드 표기
|
|
447
|
-
console.table(codes, ["type", "title"]);
|
|
448
|
-
console.log(codes[0]);
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
/**
|
|
452
|
-
* 마이그레이션을 수행합니다.
|
|
453
|
-
*
|
|
454
|
-
* runAction이 인자로 들어온 타겟들에 대해 주어진 동작(apply/rollback)을 수행한다면,
|
|
455
|
-
* 이 함수는 생성자로 들어온 connection(knex)들에 대해 마이그레이션을 수행합니다.
|
|
456
|
-
*
|
|
457
|
-
* CLI에서 사용됩니다.
|
|
458
|
-
*/
|
|
459
|
-
async run(): Promise<void> {
|
|
460
|
-
// pending 마이그레이션 확인
|
|
461
|
-
const [, pendingList] = await this.targets.pending.migrate.list();
|
|
462
|
-
if (pendingList.length > 0) {
|
|
463
|
-
console.log(
|
|
464
|
-
chalk.red("pending 된 마이그레이션이 존재합니다."),
|
|
465
|
-
pendingList.map((pending: any) => pending.file)
|
|
466
|
-
);
|
|
467
|
-
|
|
468
|
-
// pending이 있는 경우 Shadow DB 테스트 진행 여부 컨펌
|
|
469
|
-
const answer = await prompts({
|
|
470
|
-
type: "confirm",
|
|
471
|
-
name: "value",
|
|
472
|
-
message: "Shadow DB 테스트를 진행하시겠습니까?",
|
|
473
|
-
initial: true,
|
|
474
|
-
});
|
|
475
|
-
if (answer.value === false) {
|
|
476
|
-
return;
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
console.time(chalk.blue("Migrator - runShadowTest"));
|
|
480
|
-
await this.runShadowTest();
|
|
481
|
-
console.timeEnd(chalk.blue("Migrator - runShadowTest"));
|
|
482
|
-
await Promise.all(
|
|
483
|
-
this.targets.apply.map(async (applyDb) => {
|
|
484
|
-
const label = chalk.green(
|
|
485
|
-
`APPLIED ${
|
|
486
|
-
applyDb.client.connectionSettings.host
|
|
487
|
-
} ${applyDb.client.database()}`
|
|
488
|
-
);
|
|
489
|
-
console.time(label);
|
|
490
|
-
const [,] = await applyDb.migrate.latest();
|
|
491
|
-
console.timeEnd(label);
|
|
492
|
-
})
|
|
493
|
-
);
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
// Entity-DB간 비교하여 코드 생성 리턴
|
|
497
|
-
const codes = await this.compareMigrations(this.targets.compare!);
|
|
498
|
-
if (codes.length === 0) {
|
|
499
|
-
console.log(chalk.green("\n현재 모두 싱크된 상태입니다."));
|
|
500
|
-
return;
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
// 현재 생성된 코드 표기
|
|
504
|
-
console.table(codes, ["type", "title"]);
|
|
505
|
-
|
|
506
|
-
/* DEBUG: 디버깅용 코드
|
|
507
|
-
codes.map((code) => console.log(code.formatted));
|
|
508
|
-
process.exit();
|
|
509
|
-
*/
|
|
510
|
-
|
|
511
|
-
// 실제 파일 생성 프롬프트
|
|
512
|
-
const answer = await prompts({
|
|
513
|
-
type: "confirm",
|
|
514
|
-
name: "value",
|
|
515
|
-
message: "마이그레이션 코드를 생성하시겠습니까?",
|
|
516
|
-
initial: false,
|
|
517
|
-
});
|
|
518
|
-
if (answer.value === false) {
|
|
519
|
-
return;
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
// 실제 코드 생성
|
|
523
|
-
const migrationsDir = `${Sonamu.apiRootPath}/src/migrations`;
|
|
524
|
-
|
|
525
|
-
for (const [index, code] of codes.entries()) {
|
|
526
|
-
if (code.formatted) {
|
|
527
|
-
const dateTag = DateTime.local()
|
|
528
|
-
.plus({ seconds: index })
|
|
529
|
-
.toFormat("yyyyMMddHHmmss");
|
|
530
|
-
const filePath = `${migrationsDir}/${dateTag}_${code.title}.ts`;
|
|
531
|
-
await writeFile(filePath, code.formatted!);
|
|
532
|
-
console.log(chalk.green(`MIGRTAION CREATED ${filePath}`));
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
/**
|
|
538
|
-
* 타겟으로 지정된 DB를 롤백합니다.
|
|
539
|
-
*
|
|
540
|
-
* runAction이 인자로 들어온 타겟들에 대해 주어진 동작(apply/rollback)을 수행한다면,
|
|
541
|
-
* 이 함수는 생성자로 들어온 connection(knex)들에 대해 롤백을 수행합니다.
|
|
542
|
-
*
|
|
543
|
-
* CLI에서 사용됩니다.
|
|
544
|
-
*/
|
|
545
|
-
async rollback() {
|
|
546
|
-
console.time(chalk.red("rollback:"));
|
|
547
|
-
const rollbackAllResult = await Promise.all(
|
|
548
|
-
this.targets.apply.map(async (db) => {
|
|
549
|
-
await db.migrate.forceFreeMigrationsLock();
|
|
550
|
-
return db.migrate.rollback(undefined, false);
|
|
551
|
-
})
|
|
552
|
-
);
|
|
553
|
-
console.dir({ rollbackAllResult }, { depth: null });
|
|
554
|
-
console.timeEnd(chalk.red("rollback:"));
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
/**
|
|
558
|
-
* 빌드된 마이그레이션 파일을 삭제합니다.
|
|
559
|
-
*
|
|
560
|
-
* CLI에서 사용됩니다.
|
|
561
|
-
*
|
|
562
|
-
* @param force 강제 삭제 여부
|
|
563
|
-
* @returns
|
|
564
|
-
*/
|
|
565
|
-
async cleanUpDist(force: boolean = false): Promise<void> {
|
|
566
|
-
async function getFilesUnder(dir: string): Promise<string[]> {
|
|
567
|
-
const migrationPath = path.join(Sonamu.apiRootPath, dir, "migrations");
|
|
568
|
-
if (!(await exists(migrationPath))) {
|
|
569
|
-
await mkdir(migrationPath, {
|
|
570
|
-
recursive: true,
|
|
571
|
-
});
|
|
572
|
-
}
|
|
573
|
-
return (await readdir(migrationPath)).filter(
|
|
574
|
-
(filename) => filename.startsWith(".") === false
|
|
575
|
-
);
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
const files = {
|
|
579
|
-
src: await getFilesUnder("src"),
|
|
580
|
-
dist: await getFilesUnder("dist"),
|
|
581
|
-
};
|
|
582
|
-
|
|
583
|
-
const diffOnSrc = _.differenceBy(
|
|
584
|
-
files.src,
|
|
585
|
-
files.dist,
|
|
586
|
-
(filename) => filename.split(".")[0]
|
|
587
|
-
);
|
|
588
|
-
if (diffOnSrc.length > 0) {
|
|
589
|
-
throw new Error(
|
|
590
|
-
"컴파일 되지 않은 파일이 있습니다.\n" + diffOnSrc.join("\n")
|
|
591
|
-
);
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
const diffOnDist = _.differenceBy(
|
|
595
|
-
files.dist,
|
|
596
|
-
files.src,
|
|
597
|
-
(filename) => filename.split(".")[0]
|
|
598
|
-
);
|
|
599
|
-
if (diffOnDist.length > 0) {
|
|
600
|
-
console.log(chalk.red("원본 ts파일을 찾을 수 없는 js파일이 있습니다."));
|
|
601
|
-
console.log(diffOnDist);
|
|
602
|
-
|
|
603
|
-
if (!force) {
|
|
604
|
-
const answer = await prompts({
|
|
605
|
-
type: "confirm",
|
|
606
|
-
name: "value",
|
|
607
|
-
message: "삭제를 진행하시겠습니까?",
|
|
608
|
-
initial: true,
|
|
609
|
-
});
|
|
610
|
-
if (answer.value === false) {
|
|
611
|
-
return;
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
const filesToRm = diffOnDist.map((filename) => {
|
|
616
|
-
return path.join(Sonamu.apiRootPath, "dist", "migrations", filename);
|
|
617
|
-
});
|
|
618
|
-
for (const filePath of filesToRm) {
|
|
619
|
-
await unlink(filePath);
|
|
620
|
-
}
|
|
621
|
-
console.log(chalk.green(`${filesToRm.length}건 삭제되었습니다!`));
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
/**
|
|
626
|
-
* Shadow DB 테스트를 진행합니다.
|
|
627
|
-
*
|
|
628
|
-
* Sonamu UI에서 사용됩니다.
|
|
629
|
-
*
|
|
630
|
-
* @returns Shadow DB 테스트 결과
|
|
631
|
-
*/
|
|
632
|
-
async runShadowTest(): Promise<
|
|
633
|
-
{
|
|
634
|
-
connKey: string;
|
|
635
|
-
batchNo: number;
|
|
636
|
-
applied: string[];
|
|
637
|
-
}[]
|
|
638
|
-
> {
|
|
639
|
-
// ShadowDB 생성 후 테스트 진행
|
|
640
|
-
const tdb = knex(Sonamu.dbConfig.test);
|
|
641
|
-
const tdbConn = Sonamu.dbConfig.test
|
|
642
|
-
.connection as Knex.MySql2ConnectionConfig;
|
|
643
|
-
const shadowDatabase = tdbConn.database + "__migration_shadow";
|
|
644
|
-
const tmpSqlPath = `/tmp/${shadowDatabase}.sql`;
|
|
645
|
-
|
|
646
|
-
// 테스트DB 덤프 후 Database명 치환
|
|
647
|
-
console.log(
|
|
648
|
-
chalk.magenta(`${tdbConn.database}의 데이터 ${tmpSqlPath}로 덤프`)
|
|
649
|
-
);
|
|
650
|
-
execSync(
|
|
651
|
-
`mysqldump -h${tdbConn.host} -P${tdbConn.port ?? 3306} -u${tdbConn.user} -p'${tdbConn.password}' ${tdbConn.database} --single-transaction --no-create-db --triggers > ${tmpSqlPath};`
|
|
652
|
-
);
|
|
653
|
-
execSync(
|
|
654
|
-
`sed -i'' -e 's/\`${tdbConn.database}\`/\`${shadowDatabase}\`/g' ${tmpSqlPath};`
|
|
655
|
-
);
|
|
656
|
-
|
|
657
|
-
// 기존 ShadowDB 리셋
|
|
658
|
-
console.log(chalk.magenta(`${shadowDatabase} 리셋`));
|
|
659
|
-
await tdb.raw(`DROP DATABASE IF EXISTS \`${shadowDatabase}\`;`);
|
|
660
|
-
await tdb.raw(`CREATE DATABASE \`${shadowDatabase}\`;`);
|
|
661
|
-
|
|
662
|
-
// ShadowDB 테이블 + 데이터 생성
|
|
663
|
-
console.log(chalk.magenta(`${shadowDatabase} 데이터베이스 생성`));
|
|
664
|
-
execSync(
|
|
665
|
-
`mysql -h${tdbConn.host} -P${tdbConn.port ?? 3306} -u${tdbConn.user} -p'${tdbConn.password}' ${shadowDatabase} < ${tmpSqlPath};`
|
|
666
|
-
);
|
|
667
|
-
|
|
668
|
-
// shadow db 테스트 진행
|
|
669
|
-
const sdb = knex({
|
|
670
|
-
...Sonamu.dbConfig.test,
|
|
671
|
-
connection: {
|
|
672
|
-
...tdbConn,
|
|
673
|
-
database: shadowDatabase,
|
|
674
|
-
password: tdbConn.password,
|
|
675
|
-
},
|
|
676
|
-
});
|
|
677
|
-
|
|
678
|
-
// shadow db 테스트 진행
|
|
679
|
-
try {
|
|
680
|
-
const [batchNo, applied] = await sdb.migrate.latest();
|
|
681
|
-
console.log(chalk.green("Shadow DB 테스트에 성공했습니다!"), {
|
|
682
|
-
batchNo,
|
|
683
|
-
applied,
|
|
684
|
-
});
|
|
685
|
-
|
|
686
|
-
// 생성한 Shadow DB 삭제
|
|
687
|
-
console.log(chalk.magenta(`${shadowDatabase} 삭제`));
|
|
688
|
-
await tdb.raw(`DROP DATABASE IF EXISTS \`${shadowDatabase}\`;`);
|
|
689
|
-
|
|
690
|
-
return [
|
|
691
|
-
{
|
|
692
|
-
connKey: "shadow",
|
|
693
|
-
batchNo,
|
|
694
|
-
applied,
|
|
695
|
-
},
|
|
696
|
-
];
|
|
697
|
-
} catch (e) {
|
|
698
|
-
console.error(e);
|
|
699
|
-
throw new ServiceUnavailableException("Shadow DB 테스트 진행 중 에러");
|
|
700
|
-
} finally {
|
|
701
|
-
await tdb.destroy();
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
/**
|
|
706
|
-
* 모든 DB를 롤백하고 전체 마이그레이션 파일을 삭제합니다.
|
|
707
|
-
*
|
|
708
|
-
* CLI에서 사용됩니다.
|
|
709
|
-
*
|
|
710
|
-
* @returns
|
|
711
|
-
*/
|
|
712
|
-
async resetAll() {
|
|
713
|
-
const answer = await prompts({
|
|
714
|
-
type: "confirm",
|
|
715
|
-
name: "value",
|
|
716
|
-
message: "모든 DB를 롤백하고 전체 마이그레이션 파일을 삭제하시겠습니까?",
|
|
717
|
-
initial: false,
|
|
718
|
-
});
|
|
719
|
-
if (answer.value === false) {
|
|
720
|
-
return;
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
console.time(chalk.red("rollback-all:"));
|
|
724
|
-
const rollbackAllResult = await Promise.all(
|
|
725
|
-
this.targets.apply.map(async (db) => {
|
|
726
|
-
await db.migrate.forceFreeMigrationsLock();
|
|
727
|
-
return db.migrate.rollback(undefined, true);
|
|
728
|
-
})
|
|
729
|
-
);
|
|
730
|
-
console.log({ rollbackAllResult });
|
|
731
|
-
console.timeEnd(chalk.red("rollback-all:"));
|
|
732
|
-
|
|
733
|
-
const migrationsDir = `${Sonamu.apiRootPath}/src/migrations`;
|
|
734
|
-
console.time(chalk.red("delete migration files"));
|
|
735
|
-
execSync(`rm -f ${migrationsDir}/*`);
|
|
736
|
-
execSync(`rm -f ${migrationsDir.replace("/src/", "/dist/")}/*`);
|
|
737
|
-
console.timeEnd(chalk.red("delete migration files"));
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
private async compareMigrations(
|
|
741
|
-
compareDB: Knex
|
|
742
|
-
): Promise<GenMigrationCode[]> {
|
|
323
|
+
async compareMigrations(compareDB: Knex): Promise<GenMigrationCode[]> {
|
|
743
324
|
// Entity 순회하여 싱크
|
|
744
325
|
const entityIds = EntityManager.getAllIds();
|
|
745
326
|
|
|
746
327
|
// 조인테이블 포함하여 Entity에서 MigrationSet 추출
|
|
747
328
|
const entitySetsWithJoinTable = entityIds
|
|
748
329
|
.filter((entityId) => EntityManager.get(entityId).props.length > 0)
|
|
749
|
-
.map((entityId) =>
|
|
750
|
-
getMigrationSetFromEntity(EntityManager.get(entityId))
|
|
751
|
-
);
|
|
330
|
+
.map((entityId) => getMigrationSetFromEntity(EntityManager.get(entityId)));
|
|
752
331
|
|
|
753
332
|
// 조인테이블만 추출
|
|
754
|
-
const joinTablesWithDup = entitySetsWithJoinTable
|
|
755
|
-
.map((entitySet) => entitySet.joinTables)
|
|
756
|
-
.flat();
|
|
333
|
+
const joinTablesWithDup = entitySetsWithJoinTable.flatMap((entitySet) => entitySet.joinTables);
|
|
757
334
|
// 중복 제거 (중복인 경우 indexes를 병합)
|
|
758
|
-
const joinTables = Object.values(
|
|
759
|
-
|
|
760
|
-
).map((tables) => {
|
|
335
|
+
const joinTables = Object.values(group(joinTablesWithDup, (jt) => jt.table)).map((tables) => {
|
|
336
|
+
assert(tables !== undefined, "tables is undefined");
|
|
761
337
|
if (tables.length === 1) {
|
|
762
338
|
return tables[0];
|
|
763
339
|
}
|
|
764
340
|
return {
|
|
765
341
|
...tables[0],
|
|
766
|
-
indexes:
|
|
342
|
+
indexes: unique(
|
|
767
343
|
tables.flatMap((t) => t.indexes),
|
|
768
|
-
(index) => [index.type, ...index.columns.sort()].join("-")
|
|
344
|
+
(index) => [index.type, ...index.columns.sort()].join("-"),
|
|
769
345
|
),
|
|
770
346
|
};
|
|
771
347
|
});
|
|
772
348
|
|
|
773
349
|
// 조인테이블 포함하여 MigrationSet 배열
|
|
774
|
-
const entitySets: MigrationSet[] = [
|
|
775
|
-
...entitySetsWithJoinTable,
|
|
776
|
-
...joinTables,
|
|
777
|
-
];
|
|
350
|
+
const entitySets: MigrationSet[] = [...entitySetsWithJoinTable, ...joinTables];
|
|
778
351
|
|
|
779
352
|
const codes: GenMigrationCode[] = (
|
|
780
353
|
await Promise.all(
|
|
781
354
|
entitySets.map(async (entitySet) => {
|
|
782
|
-
const dbSet = await getMigrationSetFromDB(
|
|
355
|
+
const dbSet = await PostgreSQLSchemaReader.getMigrationSetFromDB(
|
|
356
|
+
compareDB,
|
|
357
|
+
entitySet.table,
|
|
358
|
+
);
|
|
359
|
+
Naite.t(`migrator:compareMigrations:entitySet:${entitySet.table}`, entitySet);
|
|
360
|
+
Naite.t(`migrator:compareMigrations:dbSet:${entitySet.table}`, dbSet);
|
|
783
361
|
|
|
784
362
|
if (dbSet === null) {
|
|
785
363
|
// 기존 테이블 없음, 새로 테이블 생성
|
|
@@ -788,13 +366,13 @@ export class Migrator {
|
|
|
788
366
|
// 기존 테이블 존재하는 케이스
|
|
789
367
|
return await generateAlterCode(entitySet, dbSet);
|
|
790
368
|
}
|
|
791
|
-
})
|
|
369
|
+
}),
|
|
792
370
|
)
|
|
793
371
|
).flat();
|
|
794
372
|
|
|
795
373
|
// normal 타입이 앞으로, foreign이 뒤로
|
|
796
374
|
codes.sort((codeA, codeB) => {
|
|
797
|
-
if (codeA.type === "foreign" && codeB.type
|
|
375
|
+
if (codeA.type === "foreign" && codeB.type === "normal") {
|
|
798
376
|
return 1;
|
|
799
377
|
} else if (codeA.type === "normal" && codeB.type === "foreign") {
|
|
800
378
|
return -1;
|
|
@@ -807,17 +385,67 @@ export class Migrator {
|
|
|
807
385
|
}
|
|
808
386
|
|
|
809
387
|
/**
|
|
810
|
-
*
|
|
388
|
+
* Shadow DB 테스트를 진행합니다.
|
|
811
389
|
*
|
|
812
|
-
*
|
|
390
|
+
* Sonamu UI에서 사용됩니다.
|
|
813
391
|
*
|
|
814
|
-
* @returns
|
|
392
|
+
* @returns Shadow DB 테스트 결과
|
|
815
393
|
*/
|
|
816
|
-
async
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
)
|
|
394
|
+
async runShadowTest(): Promise<MigrationResult> {
|
|
395
|
+
const tdbConn = Sonamu.dbConfig.test.connection as Knex.PgConnectionConfig;
|
|
396
|
+
const shadowDatabase = `${tdbConn.database}__migration_shadow`;
|
|
397
|
+
|
|
398
|
+
// 테스트 상황에서는 트랜잭션을 초기화하고, 새 데이터베이스 커넥션을 가져와야 함
|
|
399
|
+
if (isTest()) {
|
|
400
|
+
await DB.clearTestTransaction();
|
|
401
|
+
await DB.destroy();
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// 기존 Shadow DB 삭제 후 Shadow DB 생성
|
|
405
|
+
const tdb = knex(Sonamu.dbConfig.test);
|
|
406
|
+
!isTest() && console.log(chalk.magenta(`${shadowDatabase} 삭제`));
|
|
407
|
+
await tdb.raw(`DROP DATABASE IF EXISTS ${shadowDatabase}`);
|
|
408
|
+
await tdb.raw(`CREATE DATABASE ${shadowDatabase} TEMPLATE ${tdbConn.database}`);
|
|
409
|
+
|
|
410
|
+
// Shadow DB에 연결
|
|
411
|
+
const sdb = knex({
|
|
412
|
+
...Sonamu.dbConfig.test,
|
|
413
|
+
connection: {
|
|
414
|
+
...tdbConn,
|
|
415
|
+
database: shadowDatabase,
|
|
416
|
+
password: tdbConn.password,
|
|
417
|
+
},
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
// shadow DB 테스트 진행
|
|
421
|
+
try {
|
|
422
|
+
const [batchNo, applied] = await sdb.migrate.latest();
|
|
423
|
+
!isTest() &&
|
|
424
|
+
console.log(chalk.green("Shadow DB 테스트에 성공했습니다!"), {
|
|
425
|
+
batchNo,
|
|
426
|
+
applied,
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
return [
|
|
430
|
+
{
|
|
431
|
+
connKey: "shadow",
|
|
432
|
+
batchNo,
|
|
433
|
+
applied,
|
|
434
|
+
},
|
|
435
|
+
];
|
|
436
|
+
} catch (e) {
|
|
437
|
+
console.error(e);
|
|
438
|
+
throw new ServiceUnavailableException("Shadow DB 테스트 진행 중 에러");
|
|
439
|
+
} finally {
|
|
440
|
+
// Shadow DB 연결 종료
|
|
441
|
+
await sdb.destroy();
|
|
442
|
+
|
|
443
|
+
// Shadow DB 삭제
|
|
444
|
+
!isTest() && console.log(chalk.magenta(`${shadowDatabase} 삭제`));
|
|
445
|
+
await tdb.raw(`DROP DATABASE IF EXISTS ${shadowDatabase}`);
|
|
446
|
+
|
|
447
|
+
// Test DB 연결 종료
|
|
448
|
+
await tdb.destroy();
|
|
449
|
+
}
|
|
822
450
|
}
|
|
823
451
|
}
|