sonamu 0.6.0 → 0.7.1
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 +2 -1
- package/dist/api/caster.d.ts.map +1 -1
- package/dist/api/caster.js +6 -1
- 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 +178 -409
- package/dist/api/config.d.ts +27 -13
- package/dist/api/config.d.ts.map +1 -1
- package/dist/api/config.js +19 -26
- package/dist/api/context.d.ts +4 -3
- package/dist/api/context.d.ts.map +1 -1
- package/dist/api/context.js +1 -1
- package/dist/api/decorators.d.ts +20 -6
- package/dist/api/decorators.d.ts.map +1 -1
- package/dist/api/decorators.js +111 -18
- package/dist/api/index.d.ts +2 -2
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +3 -3
- package/dist/api/sonamu.d.ts +7 -7
- package/dist/api/sonamu.d.ts.map +1 -1
- package/dist/api/sonamu.js +83 -51
- 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 +5 -1
- package/dist/bin/build-config.d.ts.map +1 -1
- package/dist/bin/build-config.js +5 -2
- package/dist/bin/cli.js +165 -64
- 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 +30 -13
- 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 +232 -89
- 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 +11 -10
- package/dist/database/db.d.ts +5 -6
- package/dist/database/db.d.ts.map +1 -1
- package/dist/database/db.js +22 -25
- 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 +2 -2
- package/dist/database/puri.d.ts +25 -14
- package/dist/database/puri.d.ts.map +1 -1
- package/dist/database/puri.js +83 -21
- package/dist/database/puri.types.d.ts +21 -7
- package/dist/database/puri.types.d.ts.map +1 -1
- package/dist/database/puri.types.js +4 -1
- 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 +1 -1
- 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 +227 -78
- package/dist/entity/entity-manager.d.ts +165 -2
- package/dist/entity/entity-manager.d.ts.map +1 -1
- package/dist/entity/entity-manager.js +26 -10
- package/dist/entity/entity.d.ts +5 -3
- package/dist/entity/entity.d.ts.map +1 -1
- package/dist/entity/entity.js +153 -54
- 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 +1 -1
- 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 +1 -1
- 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 +1 -1
- package/dist/file-storage/file-storage.js +2 -2
- package/dist/index.d.ts +18 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -13
- 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 +123 -67
- 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 +67 -218
- package/dist/migration/migrator.d.ts +24 -73
- package/dist/migration/migrator.d.ts.map +1 -1
- package/dist/migration/migrator.js +121 -301
- 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 +1 -1
- 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 +91 -8
- package/dist/naite/naite.d.ts.map +1 -1
- package/dist/naite/naite.js +285 -41
- package/dist/stream/sse.d.ts +2 -2
- package/dist/stream/sse.d.ts.map +1 -1
- package/dist/stream/sse.js +1 -1
- package/dist/syncer/api-parser.d.ts +3 -13
- package/dist/syncer/api-parser.d.ts.map +1 -1
- package/dist/syncer/api-parser.js +67 -56
- package/dist/syncer/checksum.d.ts +2 -2
- package/dist/syncer/checksum.d.ts.map +1 -1
- package/dist/syncer/checksum.js +11 -11
- package/dist/syncer/code-generator.d.ts +3 -3
- package/dist/syncer/code-generator.d.ts.map +1 -1
- package/dist/syncer/code-generator.js +37 -17
- package/dist/syncer/entity-operations.d.ts +2 -2
- package/dist/syncer/entity-operations.d.ts.map +1 -1
- package/dist/syncer/entity-operations.js +9 -8
- package/dist/syncer/file-patterns.d.ts +1 -1
- package/dist/syncer/file-patterns.d.ts.map +1 -1
- package/dist/syncer/file-patterns.js +1 -1
- package/dist/syncer/index.d.ts +4 -4
- package/dist/syncer/index.d.ts.map +1 -1
- package/dist/syncer/index.js +5 -5
- package/dist/syncer/module-loader.d.ts +4 -4
- package/dist/syncer/module-loader.d.ts.map +1 -1
- package/dist/syncer/module-loader.js +17 -12
- package/dist/syncer/syncer.d.ts +31 -24
- package/dist/syncer/syncer.d.ts.map +1 -1
- package/dist/syncer/syncer.js +92 -45
- package/dist/template/entity-converter.d.ts +1 -1
- package/dist/template/entity-converter.d.ts.map +1 -1
- package/dist/template/entity-converter.js +15 -8
- package/dist/template/helpers.d.ts +2 -2
- package/dist/template/helpers.d.ts.map +1 -1
- package/dist/template/helpers.js +3 -3
- package/dist/template/implementations/entity.template.d.ts +2 -2
- package/dist/template/implementations/entity.template.d.ts.map +1 -1
- package/dist/template/implementations/entity.template.js +4 -5
- package/dist/template/implementations/generated.template.d.ts +2 -3
- package/dist/template/implementations/generated.template.d.ts.map +1 -1
- package/dist/template/implementations/generated.template.js +46 -29
- package/dist/template/implementations/generated_http.template.d.ts +2 -3
- package/dist/template/implementations/generated_http.template.d.ts.map +1 -1
- package/dist/template/implementations/generated_http.template.js +9 -9
- package/dist/template/implementations/generated_sso.template.d.ts +3 -4
- package/dist/template/implementations/generated_sso.template.d.ts.map +1 -1
- package/dist/template/implementations/generated_sso.template.js +54 -25
- package/dist/template/implementations/init_types.template.d.ts +2 -2
- package/dist/template/implementations/init_types.template.d.ts.map +1 -1
- package/dist/template/implementations/init_types.template.js +2 -2
- package/dist/template/implementations/model.template.d.ts +2 -2
- package/dist/template/implementations/model.template.d.ts.map +1 -1
- package/dist/template/implementations/model.template.js +47 -37
- package/dist/template/implementations/model_test.template.d.ts +2 -2
- package/dist/template/implementations/model_test.template.d.ts.map +1 -1
- package/dist/template/implementations/model_test.template.js +2 -2
- package/dist/template/implementations/service.template.d.ts +4 -4
- package/dist/template/implementations/service.template.d.ts.map +1 -1
- package/dist/template/implementations/service.template.js +24 -16
- package/dist/template/implementations/view_enums_buttonset.template.d.ts +2 -2
- package/dist/template/implementations/view_enums_buttonset.template.d.ts.map +1 -1
- package/dist/template/implementations/view_enums_buttonset.template.js +1 -1
- package/dist/template/implementations/view_enums_dropdown.template.d.ts +2 -2
- package/dist/template/implementations/view_enums_dropdown.template.d.ts.map +1 -1
- package/dist/template/implementations/view_enums_dropdown.template.js +2 -2
- package/dist/template/implementations/view_enums_select.template.d.ts +2 -2
- package/dist/template/implementations/view_enums_select.template.d.ts.map +1 -1
- package/dist/template/implementations/view_enums_select.template.js +2 -2
- package/dist/template/implementations/view_form.template.d.ts +2 -2
- package/dist/template/implementations/view_form.template.d.ts.map +1 -1
- package/dist/template/implementations/view_form.template.js +4 -4
- package/dist/template/implementations/view_id_all_select.template.d.ts +2 -2
- package/dist/template/implementations/view_id_all_select.template.d.ts.map +1 -1
- package/dist/template/implementations/view_id_all_select.template.js +1 -1
- package/dist/template/implementations/view_id_async_select.template.d.ts +2 -2
- package/dist/template/implementations/view_id_async_select.template.d.ts.map +1 -1
- package/dist/template/implementations/view_id_async_select.template.js +1 -1
- package/dist/template/implementations/view_list.template.d.ts +2 -2
- package/dist/template/implementations/view_list.template.d.ts.map +1 -1
- package/dist/template/implementations/view_list.template.js +29 -19
- package/dist/template/implementations/view_list_columns.template.d.ts +3 -3
- package/dist/template/implementations/view_list_columns.template.d.ts.map +1 -1
- package/dist/template/implementations/view_list_columns.template.js +1 -1
- package/dist/template/implementations/view_search_input.template.d.ts +2 -2
- package/dist/template/implementations/view_search_input.template.d.ts.map +1 -1
- package/dist/template/implementations/view_search_input.template.js +1 -1
- package/dist/template/index.d.ts +4 -2
- package/dist/template/index.d.ts.map +1 -1
- package/dist/template/index.js +5 -3
- 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 +12 -2
- package/dist/template/template.d.ts.map +1 -1
- package/dist/template/template.js +19 -6
- package/dist/template/zod-converter.d.ts +40 -7
- package/dist/template/zod-converter.d.ts.map +1 -1
- package/dist/template/zod-converter.js +386 -58
- 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 +12 -3
- 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 +338 -236
- package/dist/types/types.d.ts +709 -104
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/types.js +309 -52
- package/dist/typings/knex.d.js +2 -2
- package/dist/utils/async-utils.d.ts.map +1 -1
- package/dist/utils/async-utils.js +3 -3
- package/dist/utils/console-util.js +1 -1
- package/dist/utils/controller.d.ts +1 -0
- package/dist/utils/controller.d.ts.map +1 -1
- package/dist/utils/controller.js +4 -1
- package/dist/utils/esm-utils.d.ts +0 -6
- package/dist/utils/esm-utils.d.ts.map +1 -1
- package/dist/utils/esm-utils.js +2 -9
- 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 +1 -1
- package/dist/utils/lodash-able.d.ts.map +1 -1
- package/dist/utils/lodash-able.js +1 -1
- 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 +1 -1
- package/dist/utils/path-utils.d.ts.map +1 -1
- package/dist/utils/path-utils.js +3 -3
- package/dist/utils/process-utils.js +1 -1
- 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 +14 -3
- 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 +7 -1
- package/dist/utils/utils.d.ts.map +1 -1
- package/dist/utils/utils.js +44 -5
- 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 +1 -1
- package/package.json +55 -30
- 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 +176 -533
- package/src/api/config.ts +39 -56
- package/src/api/context.ts +7 -18
- package/src/api/decorators.ts +175 -46
- package/src/api/index.ts +2 -2
- package/src/api/sonamu.ts +133 -124
- package/src/api/validator.ts +83 -0
- package/src/bin/build-config.ts +7 -1
- package/src/bin/cli.ts +192 -110
- 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 +36 -50
- 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 +182 -126
- package/src/database/puri.types.ts +64 -31
- package/src/database/transaction-context.ts +1 -1
- package/src/database/upsert-builder.ts +261 -132
- package/src/entity/entity-manager.ts +36 -28
- package/src/entity/entity.ts +330 -249
- 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 -12
- package/src/migration/code-generation.ts +185 -172
- package/src/migration/migration-set.ts +80 -293
- package/src/migration/migrator.ts +182 -425
- 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 +378 -33
- package/src/shared/web.shared.ts.txt +20 -24
- package/src/stream/sse.ts +5 -5
- package/src/syncer/api-parser.ts +52 -69
- package/src/syncer/checksum.ts +25 -37
- package/src/syncer/code-generator.ts +58 -62
- package/src/syncer/entity-operations.ts +12 -15
- package/src/syncer/file-patterns.ts +2 -2
- package/src/syncer/index.ts +4 -4
- package/src/syncer/module-loader.ts +28 -25
- package/src/syncer/syncer.ts +155 -162
- package/src/template/entity-converter.ts +18 -27
- package/src/template/helpers.ts +8 -11
- package/src/template/implementations/entity.template.ts +6 -6
- package/src/template/implementations/generated.template.ts +99 -99
- package/src/template/implementations/generated_http.template.ts +21 -54
- package/src/template/implementations/generated_sso.template.ts +78 -65
- package/src/template/implementations/init_types.template.ts +4 -6
- package/src/template/implementations/model.template.ts +47 -38
- package/src/template/implementations/model_test.template.ts +3 -3
- package/src/template/implementations/service.template.ts +56 -80
- package/src/template/implementations/view_enums_buttonset.template.ts +2 -2
- package/src/template/implementations/view_enums_dropdown.template.ts +4 -4
- package/src/template/implementations/view_enums_select.template.ts +3 -3
- package/src/template/implementations/view_form.template.ts +34 -75
- package/src/template/implementations/view_id_all_select.template.ts +2 -2
- package/src/template/implementations/view_id_async_select.template.ts +9 -23
- package/src/template/implementations/view_list.template.ts +54 -95
- package/src/template/implementations/view_list_columns.template.ts +4 -10
- package/src/template/implementations/view_search_input.template.ts +2 -2
- package/src/template/index.ts +4 -2
- package/src/template/template-manager.ts +166 -0
- package/src/template/template-types.ts +16 -0
- package/src/template/template.ts +29 -10
- package/src/template/zod-converter.ts +459 -101
- package/src/testing/_relation-graph.ts +18 -11
- package/src/testing/fixture-manager.ts +468 -362
- package/src/types/types.ts +516 -248
- package/src/typings/knex.d.ts +7 -9
- package/src/utils/async-utils.ts +8 -12
- package/src/utils/console-util.ts +1 -1
- package/src/utils/controller.ts +3 -0
- package/src/utils/esm-utils.ts +8 -18
- 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 +3 -6
- package/src/utils/process-utils.ts +1 -1
- package/src/utils/sql-parser.ts +23 -5
- package/src/utils/type-utils.ts +83 -0
- package/src/utils/utils.ts +58 -9
- package/src/utils/zod-error.ts +3 -3
- 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 -72
- 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 -39
- 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 -210
- package/src/bin/cli-wrapper.ts +0 -82
- package/src/database/knex-plugins/knex-on-duplicate-update.ts +0 -45
- package/src/entity/entity-utils.ts +0 -291
package/src/entity/entity.ts
CHANGED
|
@@ -1,31 +1,33 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
1
|
+
import assert from "assert";
|
|
2
|
+
import { writeFile } from "fs/promises";
|
|
3
|
+
import inflection from "inflection";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import { group, unique } from "radashi";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { Sonamu } from "../api/sonamu";
|
|
4
8
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
type EntityIndex,
|
|
10
|
+
type EntityJson,
|
|
11
|
+
type EntityProp,
|
|
12
|
+
type EntityPropNode,
|
|
13
|
+
type EntitySubsetRow,
|
|
10
14
|
isBelongsToOneRelationProp,
|
|
11
|
-
|
|
15
|
+
isEnumProp,
|
|
12
16
|
isHasManyRelationProp,
|
|
13
17
|
isManyToManyRelationProp,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
isOneToOneRelationProp,
|
|
19
|
+
isRelationProp,
|
|
20
|
+
isVirtualProp,
|
|
21
|
+
type RelationProp,
|
|
22
|
+
type StringProp,
|
|
23
|
+
type SubsetQuery,
|
|
20
24
|
} from "../types/types";
|
|
21
|
-
import
|
|
22
|
-
import
|
|
23
|
-
import { writeFile } from "fs/promises";
|
|
24
|
-
import { z } from "zod";
|
|
25
|
-
import { Sonamu } from "../api/sonamu";
|
|
26
|
-
import prettier from "prettier";
|
|
27
|
-
import { nonNullable } from "../utils/utils";
|
|
25
|
+
import { importMembers } from "../utils/esm-utils";
|
|
26
|
+
import { formatCode } from "../utils/formatter";
|
|
28
27
|
import { exists } from "../utils/fs-utils";
|
|
28
|
+
import { runtimePath } from "../utils/path-utils";
|
|
29
|
+
import { assertDefined, nonNullable } from "../utils/utils";
|
|
30
|
+
import { EntityManager } from "./entity-manager";
|
|
29
31
|
|
|
30
32
|
export class Entity {
|
|
31
33
|
id: string;
|
|
@@ -52,7 +54,7 @@ export class Entity {
|
|
|
52
54
|
[name: string]: z.ZodTypeAny;
|
|
53
55
|
} = {};
|
|
54
56
|
enums: {
|
|
55
|
-
[enumId: string]: z.ZodEnum<
|
|
57
|
+
[enumId: string]: z.ZodEnum<Readonly<Record<string, string>>>;
|
|
56
58
|
} = {};
|
|
57
59
|
enumLabels: {
|
|
58
60
|
[enumId: string]: {
|
|
@@ -60,16 +62,7 @@ export class Entity {
|
|
|
60
62
|
};
|
|
61
63
|
} = {};
|
|
62
64
|
|
|
63
|
-
constructor({
|
|
64
|
-
id,
|
|
65
|
-
parentId,
|
|
66
|
-
table,
|
|
67
|
-
title,
|
|
68
|
-
props,
|
|
69
|
-
indexes,
|
|
70
|
-
subsets,
|
|
71
|
-
enums,
|
|
72
|
-
}: EntityJson) {
|
|
65
|
+
constructor({ id, parentId, table, title, props, indexes, subsets, enums }: EntityJson) {
|
|
73
66
|
// id
|
|
74
67
|
this.id = id;
|
|
75
68
|
this.parentId = parentId;
|
|
@@ -86,22 +79,16 @@ export class Entity {
|
|
|
86
79
|
}
|
|
87
80
|
return prop;
|
|
88
81
|
});
|
|
89
|
-
this.propsDict =
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}, {});
|
|
82
|
+
this.propsDict = Object.fromEntries(
|
|
83
|
+
props.map((prop) => {
|
|
84
|
+
return [prop.name, prop];
|
|
85
|
+
}),
|
|
86
|
+
);
|
|
95
87
|
|
|
96
88
|
// relations
|
|
97
|
-
this.relations =
|
|
98
|
-
.filter((prop) => isRelationProp(prop))
|
|
99
|
-
|
|
100
|
-
return {
|
|
101
|
-
...result,
|
|
102
|
-
[prop.name]: prop,
|
|
103
|
-
};
|
|
104
|
-
}, {});
|
|
89
|
+
this.relations = Object.fromEntries(
|
|
90
|
+
props.filter((prop) => isRelationProp(prop)).map((prop) => [prop.name, prop]),
|
|
91
|
+
);
|
|
105
92
|
} else {
|
|
106
93
|
this.props = [];
|
|
107
94
|
this.propsDict = {};
|
|
@@ -118,25 +105,180 @@ export class Entity {
|
|
|
118
105
|
this.enumLabels = enums ?? {};
|
|
119
106
|
this.enums = Object.fromEntries(
|
|
120
107
|
Object.entries(this.enumLabels).map(([key, enumLabel]) => {
|
|
121
|
-
return [
|
|
122
|
-
|
|
123
|
-
z.enum(
|
|
124
|
-
Object.keys(enumLabel) as unknown as readonly [string, ...string[]]
|
|
125
|
-
),
|
|
126
|
-
];
|
|
127
|
-
})
|
|
108
|
+
return [key, z.enum(Object.keys(enumLabel) as unknown as readonly [string, ...string[]])];
|
|
109
|
+
}),
|
|
128
110
|
);
|
|
129
111
|
|
|
130
112
|
// names
|
|
131
113
|
this.names = {
|
|
132
|
-
parentFs: inflection
|
|
133
|
-
.dasherize(inflection.underscore(parentId ?? id))
|
|
134
|
-
.toLowerCase(),
|
|
114
|
+
parentFs: inflection.dasherize(inflection.underscore(parentId ?? id)).toLowerCase(),
|
|
135
115
|
fs: inflection.dasherize(inflection.underscore(id)).toLowerCase(),
|
|
136
116
|
module: id,
|
|
137
117
|
};
|
|
138
118
|
}
|
|
139
119
|
|
|
120
|
+
/*
|
|
121
|
+
subset을 Puri 코드로 변환
|
|
122
|
+
*/
|
|
123
|
+
getPuriSubsetQuery(subsetKey: string): string {
|
|
124
|
+
const subset = this.subsets[subsetKey];
|
|
125
|
+
const subsetQuery = this.resolveSubsetQuery("", subset);
|
|
126
|
+
|
|
127
|
+
const lines: string[] = [];
|
|
128
|
+
|
|
129
|
+
// from
|
|
130
|
+
lines.push(`return qbWrapper`);
|
|
131
|
+
lines.push(`.from("${this.table}")`);
|
|
132
|
+
|
|
133
|
+
// join
|
|
134
|
+
for (const join of subsetQuery.joins) {
|
|
135
|
+
const joinMethod = join.join === "inner" ? "join" : "leftJoin";
|
|
136
|
+
|
|
137
|
+
if ("custom" in join) {
|
|
138
|
+
// custom join clause는 raw 사용
|
|
139
|
+
lines.push(
|
|
140
|
+
`.${joinMethod}({ ${join.as}: "${join.table}" }, qbWrapper.knex.raw(\`${join.custom}\`))`,
|
|
141
|
+
);
|
|
142
|
+
} else {
|
|
143
|
+
lines.push(`.${joinMethod}({ ${join.as}: "${join.table}" }, "${join.from}", "${join.to}")`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// select
|
|
148
|
+
const selectObj: Record<string, string> = {};
|
|
149
|
+
for (const selectItem of subsetQuery.select) {
|
|
150
|
+
// "users.id" 또는 "users.id as user__id" 형태
|
|
151
|
+
const match = selectItem.match(/^(.+?)(?: as (.+))?$/);
|
|
152
|
+
if (match) {
|
|
153
|
+
const [, column, alias] = match;
|
|
154
|
+
const key = alias ?? assertDefined(column.split(".").pop());
|
|
155
|
+
selectObj[key] = `"${column.trim()}"`;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
lines.push(`.select({`);
|
|
160
|
+
Object.entries(selectObj).forEach(([key, value]) => {
|
|
161
|
+
lines.push(`${key}: ${value},`);
|
|
162
|
+
});
|
|
163
|
+
lines.push(`});`);
|
|
164
|
+
|
|
165
|
+
return lines.join("\n");
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
getPuriLoaderQuery(subsetKey: string): string {
|
|
169
|
+
const subset = this.subsets[subsetKey];
|
|
170
|
+
const { loaders } = this.resolveSubsetQuery("", subset);
|
|
171
|
+
|
|
172
|
+
const lines: string[] = [`[`];
|
|
173
|
+
|
|
174
|
+
const parseSelect = (select: string, table: string) => {
|
|
175
|
+
const tablePrefix = `${table}.`;
|
|
176
|
+
if (select.startsWith(tablePrefix)) {
|
|
177
|
+
return `${select.replace(tablePrefix, "")}: "${select}"`;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (select.includes(" as ")) {
|
|
181
|
+
const [column, alias] = select.split(" as ");
|
|
182
|
+
return `${alias}: "${column}"`;
|
|
183
|
+
}
|
|
184
|
+
return `${select}: "${select}"`;
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
// 재귀적으로 loader 생성하는 헬퍼 함수
|
|
188
|
+
const generateLoaderCode = (loaders: SubsetQuery["loaders"]): string[] => {
|
|
189
|
+
const loaderLines: string[] = [];
|
|
190
|
+
|
|
191
|
+
for (const loader of loaders) {
|
|
192
|
+
const { toTable, toCol, through } = loader.manyJoin;
|
|
193
|
+
loaderLines.push(
|
|
194
|
+
"{",
|
|
195
|
+
`as: "${loader.as}",`,
|
|
196
|
+
`refId: "${loader.manyJoin.idField}",`,
|
|
197
|
+
`qb: (qbWrapper: PuriWrapper<DatabaseSchemaExtend>, fromIds: number[]) => {`,
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
if (through === undefined) {
|
|
201
|
+
// HasMany
|
|
202
|
+
loaderLines.push(
|
|
203
|
+
//
|
|
204
|
+
"return qbWrapper",
|
|
205
|
+
`.from("${toTable}")`,
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
loader.oneJoins.forEach((join: SubsetQuery["joins"][number]) => {
|
|
209
|
+
const joinType = join.join === "inner" ? "join" : "leftJoin";
|
|
210
|
+
if ("custom" in join) {
|
|
211
|
+
// FIXME: 검증 필요
|
|
212
|
+
loaderLines.push(
|
|
213
|
+
`.${joinType}({ ${join.as}: "${join.table}" }, (j) => {`,
|
|
214
|
+
`j.on(Puri.rawString("${join.custom}"));`,
|
|
215
|
+
"})",
|
|
216
|
+
);
|
|
217
|
+
} else {
|
|
218
|
+
loaderLines.push(
|
|
219
|
+
`.${joinType}({ ${join.as}: "${join.table}" }, "${join.from}", "${join.to}")`,
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
loaderLines.push(
|
|
225
|
+
`.whereIn("${toTable}.${toCol}", fromIds)`,
|
|
226
|
+
`.select({`,
|
|
227
|
+
`${loader.select.map((select: string) => parseSelect(select, toTable)).join(",")},`,
|
|
228
|
+
`refId: "${toTable}.${toCol}",`,
|
|
229
|
+
`});`,
|
|
230
|
+
);
|
|
231
|
+
} else {
|
|
232
|
+
// ManyToMany
|
|
233
|
+
loaderLines.push(
|
|
234
|
+
"return qbWrapper",
|
|
235
|
+
`.from("${through.table}")`,
|
|
236
|
+
`.join("${toTable}", "${through.table}.${through.toCol}", "${toTable}.${toCol}")`,
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
loader.oneJoins.forEach((join: SubsetQuery["joins"][number]) => {
|
|
240
|
+
const joinType = join.join === "inner" ? "join" : "leftJoin";
|
|
241
|
+
if ("custom" in join) {
|
|
242
|
+
// FIXME: 검증 필요
|
|
243
|
+
loaderLines.push(
|
|
244
|
+
`.${joinType}({ ${join.as}: "${join.table}" }, (j) => {`,
|
|
245
|
+
`j.on(Puri.rawString("${join.custom}"));`,
|
|
246
|
+
"})",
|
|
247
|
+
);
|
|
248
|
+
} else {
|
|
249
|
+
loaderLines.push(
|
|
250
|
+
`.${joinType}({ ${join.as}: "${join.table}" }, "${join.from}", "${join.to}")`,
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
loaderLines.push(
|
|
255
|
+
`.whereIn("${through.table}.${through.fromCol}", fromIds)`,
|
|
256
|
+
`.select({`,
|
|
257
|
+
`${loader.select.map((select: string) => parseSelect(select, toTable)).join(",")},`,
|
|
258
|
+
`refId: "${through.table}.${through.fromCol}",`,
|
|
259
|
+
`});`,
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
loaderLines.push(`},`);
|
|
264
|
+
|
|
265
|
+
// 중첩 loaders 처리
|
|
266
|
+
if (loader.loaders && loader.loaders.length > 0) {
|
|
267
|
+
loaderLines.push("loaders: [", ...generateLoaderCode(loader.loaders), "],");
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
loaderLines.push("},");
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return loaderLines;
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
lines.push(...generateLoaderCode(loaders));
|
|
277
|
+
lines.push(`]`);
|
|
278
|
+
|
|
279
|
+
return lines.join("\n");
|
|
280
|
+
}
|
|
281
|
+
|
|
140
282
|
/*
|
|
141
283
|
subset SELECT/JOIN/LOADER 결과 리턴
|
|
142
284
|
*/
|
|
@@ -152,13 +294,13 @@ export class Entity {
|
|
|
152
294
|
resolveSubsetQuery(
|
|
153
295
|
prefix: string,
|
|
154
296
|
fields: string[],
|
|
155
|
-
isAlreadyOuterJoined: boolean = false
|
|
297
|
+
isAlreadyOuterJoined: boolean = false,
|
|
156
298
|
): SubsetQuery {
|
|
157
299
|
// prefix 치환 (prefix는 ToOneRelation이 복수로 붙은 경우 모두 __로 변경됨)
|
|
158
300
|
prefix = prefix.replace(/\./g, "__");
|
|
159
301
|
|
|
160
302
|
// 서브셋을 1뎁스만 분리하여 그룹핑
|
|
161
|
-
const subsetGroup =
|
|
303
|
+
const subsetGroup = group(fields, (field) => {
|
|
162
304
|
if (field.includes(".")) {
|
|
163
305
|
const [rel] = field.split(".");
|
|
164
306
|
return rel;
|
|
@@ -170,27 +312,21 @@ export class Entity {
|
|
|
170
312
|
const result = Object.keys(subsetGroup).reduce(
|
|
171
313
|
(r, groupKey) => {
|
|
172
314
|
const fields = subsetGroup[groupKey];
|
|
315
|
+
assert(fields !== undefined, "fields is undefined");
|
|
316
|
+
|
|
173
317
|
// 현재 테이블 필드셋은 select, virtual에 추가하고 리턴
|
|
174
318
|
if (groupKey === "") {
|
|
175
|
-
const realFields = fields.filter(
|
|
176
|
-
|
|
177
|
-
);
|
|
178
|
-
const virtualFields = fields.filter((field) =>
|
|
179
|
-
isVirtualProp(this.propsDict[field])
|
|
180
|
-
);
|
|
319
|
+
const realFields = fields.filter((field) => !isVirtualProp(this.propsDict[field]));
|
|
320
|
+
const virtualFields = fields.filter((field) => isVirtualProp(this.propsDict[field]));
|
|
181
321
|
|
|
182
322
|
if (prefix === "") {
|
|
183
323
|
// 현재 테이블인 경우
|
|
184
|
-
r.select = r.select.concat(
|
|
185
|
-
realFields.map((field) => `${this.table}.${field}`)
|
|
186
|
-
);
|
|
324
|
+
r.select = r.select.concat(realFields.map((field) => `${this.table}.${field}`));
|
|
187
325
|
r.virtual = r.virtual.concat(virtualFields);
|
|
188
326
|
} else {
|
|
189
327
|
// 넘어온 테이블인 경우
|
|
190
328
|
r.select = r.select.concat(
|
|
191
|
-
realFields.map(
|
|
192
|
-
(field) => `${prefix}.${field} as ${prefix}__${field}`
|
|
193
|
-
)
|
|
329
|
+
realFields.map((field) => `${prefix}.${field} as ${prefix}__${field}`),
|
|
194
330
|
);
|
|
195
331
|
}
|
|
196
332
|
|
|
@@ -203,23 +339,16 @@ export class Entity {
|
|
|
203
339
|
}
|
|
204
340
|
const relEntity = EntityManager.get(relation.with);
|
|
205
341
|
|
|
206
|
-
if (
|
|
207
|
-
isOneToOneRelationProp(relation) ||
|
|
208
|
-
isBelongsToOneRelationProp(relation)
|
|
209
|
-
) {
|
|
342
|
+
if (isOneToOneRelationProp(relation) || isBelongsToOneRelationProp(relation)) {
|
|
210
343
|
// -One Relation: JOIN 으로 처리
|
|
211
|
-
const relFields = fields.map((field) =>
|
|
212
|
-
field.split(".").slice(1).join(".")
|
|
213
|
-
);
|
|
344
|
+
const relFields = fields.map((field) => field.split(".").slice(1).join("."));
|
|
214
345
|
|
|
215
346
|
// -One Relation에서 id 필드만 참조하는 경우 릴레이션 넘기지 않고 리턴
|
|
216
347
|
if (relFields.length === 1 && relFields[0] === "id") {
|
|
217
348
|
if (prefix === "") {
|
|
218
349
|
r.select = r.select.concat(`${this.table}.${groupKey}_id`);
|
|
219
350
|
} else {
|
|
220
|
-
r.select = r.select.concat(
|
|
221
|
-
`${prefix}.${groupKey}_id as ${prefix}__${groupKey}_id`
|
|
222
|
-
);
|
|
351
|
+
r.select = r.select.concat(`${prefix}.${groupKey}_id as ${prefix}__${groupKey}_id`);
|
|
223
352
|
}
|
|
224
353
|
return r;
|
|
225
354
|
}
|
|
@@ -231,10 +360,7 @@ export class Entity {
|
|
|
231
360
|
}
|
|
232
361
|
|
|
233
362
|
if (isOneToOneRelationProp(relation)) {
|
|
234
|
-
if (
|
|
235
|
-
relation.hasJoinColumn === true &&
|
|
236
|
-
(relation.nullable ?? false) === false
|
|
237
|
-
) {
|
|
363
|
+
if (relation.hasJoinColumn === true && (relation.nullable ?? false) === false) {
|
|
238
364
|
return "inner";
|
|
239
365
|
} else {
|
|
240
366
|
return "outer";
|
|
@@ -248,32 +374,37 @@ export class Entity {
|
|
|
248
374
|
}
|
|
249
375
|
})();
|
|
250
376
|
const relSubsetQuery = relEntity.resolveSubsetQuery(
|
|
251
|
-
`${prefix !== "" ? prefix
|
|
377
|
+
`${prefix !== "" ? `${prefix}.` : ""}${groupKey}`,
|
|
252
378
|
relFields,
|
|
253
|
-
innerOrOuter === "outer"
|
|
379
|
+
innerOrOuter === "outer",
|
|
254
380
|
);
|
|
255
381
|
r.select = r.select.concat(relSubsetQuery.select);
|
|
256
382
|
r.virtual = r.virtual.concat(relSubsetQuery.virtual);
|
|
257
383
|
|
|
258
|
-
const joinAs = prefix === "" ? groupKey : prefix
|
|
384
|
+
const joinAs = prefix === "" ? groupKey : `${prefix}__${groupKey}`;
|
|
259
385
|
const fromTable = prefix === "" ? this.table : prefix;
|
|
260
386
|
|
|
261
|
-
let joinClause
|
|
387
|
+
let joinClause:
|
|
388
|
+
| {
|
|
389
|
+
from: string;
|
|
390
|
+
to: string;
|
|
391
|
+
}
|
|
392
|
+
| {
|
|
393
|
+
custom: string;
|
|
394
|
+
};
|
|
262
395
|
if (relation.customJoinClause) {
|
|
263
396
|
joinClause = {
|
|
264
397
|
custom: relation.customJoinClause,
|
|
265
398
|
};
|
|
266
399
|
} else {
|
|
267
|
-
let from, to;
|
|
400
|
+
let from: string, to: string;
|
|
268
401
|
if (isOneToOneRelationProp(relation)) {
|
|
269
402
|
if (relation.hasJoinColumn) {
|
|
270
403
|
from = `${fromTable}.${relation.name}_id`;
|
|
271
404
|
to = `${joinAs}.id`;
|
|
272
405
|
} else {
|
|
273
406
|
from = `${fromTable}.id`;
|
|
274
|
-
to = `${joinAs}.${inflection.underscore(
|
|
275
|
-
this.names.fs.replace(/\-/g, "_")
|
|
276
|
-
)}_id`;
|
|
407
|
+
to = `${joinAs}.${inflection.underscore(this.names.fs.replace(/-/g, "_"))}_id`;
|
|
277
408
|
}
|
|
278
409
|
} else {
|
|
279
410
|
from = `${fromTable}.${relation.name}_id`;
|
|
@@ -310,14 +441,9 @@ export class Entity {
|
|
|
310
441
|
}
|
|
311
442
|
|
|
312
443
|
r.joins = r.joins.concat(relSubsetQuery.joins);
|
|
313
|
-
} else if (
|
|
314
|
-
isHasManyRelationProp(relation) ||
|
|
315
|
-
isManyToManyRelationProp(relation)
|
|
316
|
-
) {
|
|
444
|
+
} else if (isHasManyRelationProp(relation) || isManyToManyRelationProp(relation)) {
|
|
317
445
|
// -Many Relation: Loader 로 처리
|
|
318
|
-
const relFields = fields.map((field) =>
|
|
319
|
-
field.split(".").slice(1).join(".")
|
|
320
|
-
);
|
|
446
|
+
const relFields = fields.map((field) => field.split(".").slice(1).join("."));
|
|
321
447
|
const relSubsetQuery = relEntity.resolveSubsetQuery("", relFields);
|
|
322
448
|
|
|
323
449
|
let manyJoin: SubsetQuery["loaders"][number]["manyJoin"];
|
|
@@ -364,7 +490,7 @@ export class Entity {
|
|
|
364
490
|
virtual: [],
|
|
365
491
|
joins: [],
|
|
366
492
|
loaders: [],
|
|
367
|
-
} as SubsetQuery
|
|
493
|
+
} as SubsetQuery,
|
|
368
494
|
);
|
|
369
495
|
return result;
|
|
370
496
|
}
|
|
@@ -372,13 +498,10 @@ export class Entity {
|
|
|
372
498
|
/*
|
|
373
499
|
FieldExpr[] 을 EntityPropNode[] 로 변환
|
|
374
500
|
*/
|
|
375
|
-
fieldExprsToPropNodes(
|
|
376
|
-
fieldExprs: string[],
|
|
377
|
-
entity: Entity = this
|
|
378
|
-
): EntityPropNode[] {
|
|
501
|
+
fieldExprsToPropNodes(fieldExprs: string[], entity: Entity = this): EntityPropNode[] {
|
|
379
502
|
const groups = fieldExprs.reduce(
|
|
380
503
|
(result, fieldExpr) => {
|
|
381
|
-
let key, value, elseExpr;
|
|
504
|
+
let key: string, value: string, elseExpr: string[];
|
|
382
505
|
if (fieldExpr.includes(".")) {
|
|
383
506
|
[key, ...elseExpr] = fieldExpr.split(".");
|
|
384
507
|
value = elseExpr.join(".");
|
|
@@ -392,91 +515,85 @@ export class Entity {
|
|
|
392
515
|
},
|
|
393
516
|
{} as {
|
|
394
517
|
[k: string]: string[];
|
|
395
|
-
}
|
|
518
|
+
},
|
|
396
519
|
);
|
|
397
520
|
|
|
398
|
-
return Object.keys(groups)
|
|
399
|
-
|
|
400
|
-
const group = groups[key];
|
|
401
|
-
|
|
402
|
-
// 일반 prop 처리
|
|
403
|
-
if (key === "") {
|
|
404
|
-
return group.map((propName) => {
|
|
405
|
-
// uuid 개별 처리
|
|
406
|
-
if (propName === "uuid") {
|
|
407
|
-
return {
|
|
408
|
-
nodeType: "plain" as const,
|
|
409
|
-
prop: {
|
|
410
|
-
type: "string",
|
|
411
|
-
name: "uuid",
|
|
412
|
-
length: 128,
|
|
413
|
-
} as StringProp,
|
|
414
|
-
children: [],
|
|
415
|
-
};
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
const prop = entity.props.find((p) => p.name === propName);
|
|
419
|
-
if (prop === undefined) {
|
|
420
|
-
console.log({ propName, groups });
|
|
421
|
-
throw new Error(`${entity.id} -- 잘못된 FieldExpr ${propName}`);
|
|
422
|
-
}
|
|
423
|
-
return {
|
|
424
|
-
nodeType: "plain" as const,
|
|
425
|
-
prop,
|
|
426
|
-
children: [],
|
|
427
|
-
};
|
|
428
|
-
});
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
// relation prop 처리
|
|
432
|
-
const prop = entity.propsDict[key];
|
|
433
|
-
if (!isRelationProp(prop)) {
|
|
434
|
-
throw new Error(`잘못된 FieldExpr ${key}.${group[0]}`);
|
|
435
|
-
}
|
|
436
|
-
const relEntity = EntityManager.get(prop.with);
|
|
521
|
+
return Object.keys(groups).flatMap((key) => {
|
|
522
|
+
const group = groups[key];
|
|
437
523
|
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
524
|
+
// 일반 prop 처리
|
|
525
|
+
if (key === "") {
|
|
526
|
+
return group.map((propName) => {
|
|
527
|
+
// uuid 개별 처리
|
|
528
|
+
if (propName === "uuid") {
|
|
443
529
|
return {
|
|
444
530
|
nodeType: "plain" as const,
|
|
445
531
|
prop: {
|
|
446
|
-
|
|
447
|
-
name:
|
|
448
|
-
|
|
449
|
-
},
|
|
532
|
+
type: "string",
|
|
533
|
+
name: "uuid",
|
|
534
|
+
length: 128,
|
|
535
|
+
} as StringProp,
|
|
450
536
|
children: [],
|
|
451
|
-
};
|
|
537
|
+
} as EntityPropNode;
|
|
452
538
|
}
|
|
539
|
+
|
|
540
|
+
const prop = entity.props.find((p) => p.name === propName);
|
|
541
|
+
if (prop === undefined) {
|
|
542
|
+
console.log({ propName, groups });
|
|
543
|
+
throw new Error(`${entity.id} -- 잘못된 FieldExpr ${propName}`);
|
|
544
|
+
}
|
|
545
|
+
return {
|
|
546
|
+
nodeType: "plain" as const,
|
|
547
|
+
prop,
|
|
548
|
+
children: [],
|
|
549
|
+
};
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// relation prop 처리
|
|
554
|
+
const prop = entity.propsDict[key];
|
|
555
|
+
if (!isRelationProp(prop)) {
|
|
556
|
+
throw new Error(`잘못된 FieldExpr ${key}.${group[0]}`);
|
|
557
|
+
}
|
|
558
|
+
const relEntity = EntityManager.get(prop.with);
|
|
559
|
+
|
|
560
|
+
// relation -One 에 id 필드 하나인 경우
|
|
561
|
+
if (isBelongsToOneRelationProp(prop) || isOneToOneRelationProp(prop)) {
|
|
562
|
+
if (group.length === 1 && (group[0] === "id" || group[0] === "id?")) {
|
|
563
|
+
// id 하나만 있는지 체크해서, 하나만 있으면 상위 prop으로 id를 리턴
|
|
564
|
+
const idProp = relEntity.propsDict.id;
|
|
565
|
+
return {
|
|
566
|
+
nodeType: "plain" as const,
|
|
567
|
+
prop: {
|
|
568
|
+
...idProp,
|
|
569
|
+
name: `${key}_id`,
|
|
570
|
+
nullable: prop.nullable,
|
|
571
|
+
},
|
|
572
|
+
children: [],
|
|
573
|
+
};
|
|
453
574
|
}
|
|
575
|
+
}
|
|
454
576
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
577
|
+
// -One 그외의 경우 object로 리턴
|
|
578
|
+
// -Many의 경우 array로 리턴
|
|
579
|
+
// Recursive 로 뎁스 처리
|
|
580
|
+
const children = this.fieldExprsToPropNodes(group, relEntity);
|
|
581
|
+
const nodeType =
|
|
582
|
+
isBelongsToOneRelationProp(prop) || isOneToOneRelationProp(prop)
|
|
583
|
+
? ("object" as const)
|
|
584
|
+
: ("array" as const);
|
|
463
585
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
.flat();
|
|
586
|
+
return {
|
|
587
|
+
prop,
|
|
588
|
+
children,
|
|
589
|
+
nodeType,
|
|
590
|
+
};
|
|
591
|
+
});
|
|
471
592
|
}
|
|
472
593
|
|
|
473
|
-
getFieldExprs(
|
|
474
|
-
prefix = "",
|
|
475
|
-
maxDepth: number = 3,
|
|
476
|
-
froms: string[] = []
|
|
477
|
-
): string[] {
|
|
594
|
+
getFieldExprs(prefix = "", maxDepth: number = 3, froms: string[] = []): string[] {
|
|
478
595
|
return this.props
|
|
479
|
-
.
|
|
596
|
+
.flatMap((prop) => {
|
|
480
597
|
const propName = [prefix, prop.name].filter((v) => v !== "").join(".");
|
|
481
598
|
if (propName === prefix) {
|
|
482
599
|
return null;
|
|
@@ -491,14 +608,10 @@ export class Entity {
|
|
|
491
608
|
}
|
|
492
609
|
// 정방향 relation인 경우 recursive 콜
|
|
493
610
|
const relMd = EntityManager.get(prop.with);
|
|
494
|
-
return relMd.getFieldExprs(propName, maxDepth - 1, [
|
|
495
|
-
...froms,
|
|
496
|
-
this.id,
|
|
497
|
-
]);
|
|
611
|
+
return relMd.getFieldExprs(propName, maxDepth - 1, [...froms, this.id]);
|
|
498
612
|
}
|
|
499
613
|
return propName;
|
|
500
614
|
})
|
|
501
|
-
.flat()
|
|
502
615
|
.filter((f) => f !== null) as string[];
|
|
503
616
|
}
|
|
504
617
|
|
|
@@ -529,40 +642,35 @@ export class Entity {
|
|
|
529
642
|
// subset
|
|
530
643
|
if (Object.keys(this.subsets).length > 0) {
|
|
531
644
|
EntityManager.setModulePath(`${this.id}SubsetKey`, `sonamu.generated`);
|
|
532
|
-
EntityManager.setModulePath(
|
|
533
|
-
|
|
534
|
-
`sonamu.generated`
|
|
535
|
-
);
|
|
536
|
-
Object.keys(this.subsets).map((subsetKey) => {
|
|
645
|
+
EntityManager.setModulePath(`${this.id}SubsetMapping`, `sonamu.generated`);
|
|
646
|
+
for (const subsetKey of Object.keys(this.subsets)) {
|
|
537
647
|
EntityManager.setModulePath(
|
|
538
648
|
`${this.id}Subset${subsetKey.toUpperCase()}`,
|
|
539
|
-
`sonamu.generated
|
|
649
|
+
`sonamu.generated`,
|
|
540
650
|
);
|
|
541
|
-
}
|
|
651
|
+
}
|
|
542
652
|
}
|
|
543
653
|
|
|
544
654
|
// enums
|
|
545
|
-
Object.keys(this.enumLabels)
|
|
655
|
+
for (const enumId of Object.keys(this.enumLabels)) {
|
|
546
656
|
EntityManager.setModulePath(enumId, `sonamu.generated`);
|
|
547
|
-
}
|
|
657
|
+
}
|
|
548
658
|
|
|
549
659
|
// types
|
|
550
660
|
const typesModulePath = `${basePath}/${this.names.parentFs}.types`;
|
|
551
|
-
const
|
|
661
|
+
const typesFilePath = path.join(
|
|
552
662
|
Sonamu.apiRootPath,
|
|
553
|
-
`dist/application/${typesModulePath}.js`
|
|
663
|
+
runtimePath(`dist/application/${typesModulePath}.js`),
|
|
554
664
|
);
|
|
555
665
|
|
|
556
|
-
if (await exists(
|
|
557
|
-
const
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
};
|
|
565
|
-
}, {});
|
|
666
|
+
if (await exists(typesFilePath)) {
|
|
667
|
+
const importedMembers = await importMembers<z.ZodTypeAny>(typesFilePath);
|
|
668
|
+
this.types = Object.fromEntries(
|
|
669
|
+
importedMembers.map(({ name, value }) => {
|
|
670
|
+
EntityManager.setModulePath(name, typesModulePath);
|
|
671
|
+
return [name, value];
|
|
672
|
+
}),
|
|
673
|
+
) as { [name: string]: z.ZodTypeAny };
|
|
566
674
|
}
|
|
567
675
|
}
|
|
568
676
|
|
|
@@ -593,25 +701,17 @@ export class Entity {
|
|
|
593
701
|
const subsetRows = this.getSubsetRows();
|
|
594
702
|
this.subsets = Object.fromEntries(
|
|
595
703
|
Object.entries(this.subsets).map(([subsetKey]) => {
|
|
596
|
-
return [
|
|
597
|
-
|
|
598
|
-
this.subsetRowsToSubsetFields(subsetRows, subsetKey),
|
|
599
|
-
];
|
|
600
|
-
})
|
|
704
|
+
return [subsetKey, this.subsetRowsToSubsetFields(subsetRows, subsetKey)];
|
|
705
|
+
}),
|
|
601
706
|
);
|
|
602
707
|
|
|
603
708
|
// save
|
|
604
709
|
const jsonPath = path.join(
|
|
605
710
|
Sonamu.apiRootPath,
|
|
606
|
-
`src/application/${this.names.parentFs}/${this.names.fs}.entity.json
|
|
711
|
+
`src/application/${this.names.parentFs}/${this.names.fs}.entity.json`,
|
|
607
712
|
);
|
|
608
713
|
const json = this.toJson();
|
|
609
|
-
await writeFile(
|
|
610
|
-
jsonPath,
|
|
611
|
-
await prettier.format(JSON.stringify(json), {
|
|
612
|
-
parser: "json",
|
|
613
|
-
})
|
|
614
|
-
);
|
|
714
|
+
await writeFile(jsonPath, formatCode(JSON.stringify(json), "json", jsonPath));
|
|
615
715
|
|
|
616
716
|
// reload
|
|
617
717
|
await EntityManager.register(json);
|
|
@@ -619,7 +719,7 @@ export class Entity {
|
|
|
619
719
|
|
|
620
720
|
getSubsetRows(
|
|
621
721
|
_subsets?: { [key: string]: string[] },
|
|
622
|
-
prefixes: string[] = []
|
|
722
|
+
prefixes: string[] = [],
|
|
623
723
|
): EntitySubsetRow[] {
|
|
624
724
|
if (prefixes.length > 10) {
|
|
625
725
|
return [];
|
|
@@ -627,20 +727,15 @@ export class Entity {
|
|
|
627
727
|
|
|
628
728
|
const subsets = _subsets ?? this.subsets;
|
|
629
729
|
const subsetKeys = Object.keys(subsets);
|
|
630
|
-
const allFields =
|
|
730
|
+
const allFields = unique(subsetKeys.flatMap((key) => subsets[key]));
|
|
631
731
|
|
|
632
732
|
return this.props.map((prop) => {
|
|
633
733
|
if (
|
|
634
734
|
prop.type === "relation" &&
|
|
635
|
-
allFields.find((f) =>
|
|
636
|
-
f.startsWith([...prefixes, prop.name].join(".") + ".")
|
|
637
|
-
)
|
|
735
|
+
allFields.find((f) => f.startsWith(`${[...prefixes, prop.name].join(".")}.`))
|
|
638
736
|
) {
|
|
639
737
|
const relEntity = EntityManager.get(prop.with);
|
|
640
|
-
const children = relEntity.getSubsetRows(subsets, [
|
|
641
|
-
...prefixes,
|
|
642
|
-
`${prop.name}`,
|
|
643
|
-
]);
|
|
738
|
+
const children = relEntity.getSubsetRows(subsets, [...prefixes, `${prop.name}`]);
|
|
644
739
|
|
|
645
740
|
return {
|
|
646
741
|
field: prop.name,
|
|
@@ -650,11 +745,8 @@ export class Entity {
|
|
|
650
745
|
isOpen: children.length > 0,
|
|
651
746
|
has: Object.fromEntries(
|
|
652
747
|
subsetKeys.map((subsetKey) => {
|
|
653
|
-
return [
|
|
654
|
-
|
|
655
|
-
children.every((child) => child.has[subsetKey] === true),
|
|
656
|
-
];
|
|
657
|
-
})
|
|
748
|
+
return [subsetKey, children.every((child) => child.has[subsetKey] === true)];
|
|
749
|
+
}),
|
|
658
750
|
),
|
|
659
751
|
};
|
|
660
752
|
}
|
|
@@ -669,19 +761,16 @@ export class Entity {
|
|
|
669
761
|
const subsetFields = subsets[subsetKey];
|
|
670
762
|
const has = subsetFields.some((f) => {
|
|
671
763
|
const field = [...prefixes, prop.name].join(".");
|
|
672
|
-
return f === field || f.startsWith(field
|
|
764
|
+
return f === field || f.startsWith(`${field}.`);
|
|
673
765
|
});
|
|
674
766
|
return [subsetKey, has];
|
|
675
|
-
})
|
|
767
|
+
}),
|
|
676
768
|
),
|
|
677
769
|
};
|
|
678
770
|
});
|
|
679
771
|
}
|
|
680
772
|
|
|
681
|
-
subsetRowsToSubsetFields(
|
|
682
|
-
subsetRows: EntitySubsetRow[],
|
|
683
|
-
subsetKey: string
|
|
684
|
-
): string[] {
|
|
773
|
+
subsetRowsToSubsetFields(subsetRows: EntitySubsetRow[], subsetKey: string): string[] {
|
|
685
774
|
return subsetRows
|
|
686
775
|
.map((subsetRow) => {
|
|
687
776
|
if (subsetRow.children.length > 0) {
|
|
@@ -723,9 +812,7 @@ export class Entity {
|
|
|
723
812
|
propName,
|
|
724
813
|
});
|
|
725
814
|
|
|
726
|
-
const prop = EntityManager.get(entityId).props.find(
|
|
727
|
-
(p) => p.name === propName
|
|
728
|
-
);
|
|
815
|
+
const prop = EntityManager.get(entityId).props.find((p) => p.name === propName);
|
|
729
816
|
if (!prop) {
|
|
730
817
|
throw new Error(`${entityId}의 잘못된 서브셋키 ${subsetField}`);
|
|
731
818
|
}
|
|
@@ -762,7 +849,7 @@ export class Entity {
|
|
|
762
849
|
...a,
|
|
763
850
|
propName: newProp.name,
|
|
764
851
|
}
|
|
765
|
-
: a
|
|
852
|
+
: a,
|
|
766
853
|
);
|
|
767
854
|
// 분석한 필드를 다시 서브셋 필드로 복구
|
|
768
855
|
return modified.map((a) => a.propName).join(".");
|
|
@@ -800,11 +887,7 @@ export class Entity {
|
|
|
800
887
|
const modifiedSubsetFields = subset
|
|
801
888
|
.map((subsetField) => {
|
|
802
889
|
const analyzed = relEntity.analyzeSubsetField(subsetField);
|
|
803
|
-
if (
|
|
804
|
-
analyzed.find(
|
|
805
|
-
(a) => a.propName === oldName && a.entityId === this.id
|
|
806
|
-
)
|
|
807
|
-
) {
|
|
890
|
+
if (analyzed.find((a) => a.propName === oldName && a.entityId === this.id)) {
|
|
808
891
|
return null;
|
|
809
892
|
} else {
|
|
810
893
|
return subsetField;
|
|
@@ -820,9 +903,9 @@ export class Entity {
|
|
|
820
903
|
}
|
|
821
904
|
|
|
822
905
|
// 현재 엔티티의 인덱스에서 제외
|
|
823
|
-
EntityManager.get(this.id).indexes
|
|
906
|
+
for (const index of EntityManager.get(this.id).indexes) {
|
|
824
907
|
index.columns = index.columns.filter((col) => col !== oldName);
|
|
825
|
-
}
|
|
908
|
+
}
|
|
826
909
|
|
|
827
910
|
// 프롭 삭제
|
|
828
911
|
this.props.splice(at, 1);
|
|
@@ -840,9 +923,7 @@ export class Entity {
|
|
|
840
923
|
|
|
841
924
|
// 서브셋 필드를 내려가면서 마지막으로 relation된 엔티티를 찾음
|
|
842
925
|
const lastEntityId = arr.reduce((entityId, field) => {
|
|
843
|
-
const relProp = EntityManager.get(entityId).props.find(
|
|
844
|
-
(p) => p.name === field
|
|
845
|
-
);
|
|
926
|
+
const relProp = EntityManager.get(entityId).props.find((p) => p.name === field);
|
|
846
927
|
if (!relProp || relProp.type !== "relation") {
|
|
847
928
|
console.debug({ arr, thisId: this.id, entityId, field });
|
|
848
929
|
throw new Error(`잘못된 서브셋키 ${subsetField}`);
|