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/typings/knex.d.ts
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
/** biome-ignore-all lint/correctness/noUnusedImports: d.ts */
|
|
2
|
+
/** biome-ignore-all lint/suspicious/noExplicitAny: d.ts */
|
|
3
|
+
/** biome-ignore-all lint/correctness/noUnusedVariables: d.ts */
|
|
4
|
+
|
|
5
|
+
import type { Knex } from "knex";
|
|
2
6
|
|
|
3
7
|
declare module "knex" {
|
|
4
8
|
namespace Knex {
|
|
5
9
|
interface QueryBuilder {
|
|
6
|
-
|
|
7
|
-
...columns: string[]
|
|
8
|
-
): Knex.QueryBuilder<TRecord, TResult>;
|
|
9
|
-
|
|
10
|
-
columnInfo<TRecord>(
|
|
11
|
-
column?: keyof TRecord
|
|
12
|
-
): Promise<Knex.ColumnInfo | ColumnInfosObj>;
|
|
10
|
+
columnInfo<TRecord>(column?: keyof TRecord): Promise<Knex.ColumnInfo | ColumnInfosObj>;
|
|
13
11
|
|
|
14
12
|
whereBetween<TRecord, TResult>(
|
|
15
13
|
columnName: string,
|
|
16
|
-
range: readonly [any, any]
|
|
14
|
+
range: readonly [any, any],
|
|
17
15
|
): Knex.QueryBuilder;
|
|
18
16
|
}
|
|
19
17
|
|
package/src/utils/async-utils.ts
CHANGED
|
@@ -8,12 +8,10 @@ import path from "path";
|
|
|
8
8
|
*/
|
|
9
9
|
export async function filterAsync<T>(
|
|
10
10
|
arr: T[],
|
|
11
|
-
predicate: (item: T, index: number, array: T[]) => Promise<boolean
|
|
11
|
+
predicate: (item: T, index: number, array: T[]) => Promise<boolean>,
|
|
12
12
|
): Promise<T[]> {
|
|
13
13
|
const results = await Promise.all(
|
|
14
|
-
arr.map((item, index) =>
|
|
15
|
-
predicate(item, index, arr).then((keep) => ({ item, keep }))
|
|
16
|
-
)
|
|
14
|
+
arr.map((item, index) => predicate(item, index, arr).then((keep) => ({ item, keep }))),
|
|
17
15
|
);
|
|
18
16
|
return results.filter((r) => r.keep).map((r) => r.item);
|
|
19
17
|
}
|
|
@@ -25,7 +23,7 @@ export async function filterAsync<T>(
|
|
|
25
23
|
*/
|
|
26
24
|
export async function everyAsync<T>(
|
|
27
25
|
arr: T[],
|
|
28
|
-
predicate: (item: T, index: number, array: T[]) => Promise<boolean
|
|
26
|
+
predicate: (item: T, index: number, array: T[]) => Promise<boolean>,
|
|
29
27
|
): Promise<boolean> {
|
|
30
28
|
for (let i = 0; i < arr.length; i++) {
|
|
31
29
|
if (!(await predicate(arr[i], i, arr))) {
|
|
@@ -42,11 +40,9 @@ export async function everyAsync<T>(
|
|
|
42
40
|
*/
|
|
43
41
|
export async function mapAsync<T, U>(
|
|
44
42
|
arr: T[],
|
|
45
|
-
mapper: (item: T, index: number, array: T[]) => Promise<U
|
|
43
|
+
mapper: (item: T, index: number, array: T[]) => Promise<U>,
|
|
46
44
|
): Promise<U[]> {
|
|
47
|
-
return Promise.all(
|
|
48
|
-
arr.map((item, index) => mapper(item, index, arr))
|
|
49
|
-
);
|
|
45
|
+
return Promise.all(arr.map((item, index) => mapper(item, index, arr)));
|
|
50
46
|
}
|
|
51
47
|
|
|
52
48
|
/**
|
|
@@ -57,7 +53,7 @@ export async function mapAsync<T, U>(
|
|
|
57
53
|
export async function reduceAsync<T, U>(
|
|
58
54
|
arr: T[],
|
|
59
55
|
reducer: (accumulator: U, currentValue: T, index: number, array: T[]) => Promise<U>,
|
|
60
|
-
initialValue: U
|
|
56
|
+
initialValue: U,
|
|
61
57
|
): Promise<U> {
|
|
62
58
|
let accumulator = initialValue;
|
|
63
59
|
for (let i = 0; i < arr.length; i++) {
|
|
@@ -69,8 +65,8 @@ export async function reduceAsync<T, U>(
|
|
|
69
65
|
/**
|
|
70
66
|
* 비동기 glob 함수입니다.
|
|
71
67
|
* AsyncIterableIterator로 날아오는 glob의 반환을 받아 끝까지 돌아서 배열로 반환합니다.
|
|
72
|
-
* @param pathPattern
|
|
73
|
-
* @returns
|
|
68
|
+
* @param pathPattern
|
|
69
|
+
* @returns
|
|
74
70
|
*/
|
|
75
71
|
export async function globAsync(pathPattern: string): Promise<string[]> {
|
|
76
72
|
const files: string[] = [];
|
package/src/utils/controller.ts
CHANGED
package/src/utils/esm-utils.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { dirname } from "path";
|
|
2
|
+
import { fileURLToPath, pathToFileURL } from "url";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* import.meta.url로부터 __filename 생성
|
|
@@ -31,22 +31,11 @@ export function getDirname(metaUrl: string): string {
|
|
|
31
31
|
* const url = createImportUrl('/path/to/file.js');
|
|
32
32
|
* await import(url);
|
|
33
33
|
*/
|
|
34
|
-
export function createImportUrl(
|
|
35
|
-
absolutePath: string
|
|
36
|
-
): string {
|
|
34
|
+
export function createImportUrl(absolutePath: string): string {
|
|
37
35
|
const fileUrl = pathToFileURL(absolutePath).href;
|
|
38
36
|
return fileUrl;
|
|
39
37
|
}
|
|
40
38
|
|
|
41
|
-
/**
|
|
42
|
-
* HMR 환경 감지
|
|
43
|
-
*
|
|
44
|
-
* @returns hot reload 환경인지 여부
|
|
45
|
-
*/
|
|
46
|
-
export function isHotReloadServer(): boolean {
|
|
47
|
-
return process.env.HOT === 'yes';
|
|
48
|
-
}
|
|
49
|
-
|
|
50
39
|
/**
|
|
51
40
|
* 캐시를 무시하고 새로 임포트(cache busting)하는데, 이때 가져온 모듈의 exported members들을 배열로 가져옵니다.
|
|
52
41
|
*
|
|
@@ -57,13 +46,14 @@ export function isHotReloadServer(): boolean {
|
|
|
57
46
|
* @returns { name: string; value: ExportedMemberT }[]
|
|
58
47
|
*/
|
|
59
48
|
export async function importMembers<ExportedMemberT>(
|
|
60
|
-
filePath: string
|
|
49
|
+
filePath: string,
|
|
61
50
|
): Promise<{ name: string; value: ExportedMemberT }[]> {
|
|
62
51
|
const imported = await import(createImportUrl(filePath));
|
|
63
52
|
|
|
64
|
-
const allExportedMembers = Object.entries<ExportedMemberT>(imported).map(
|
|
65
|
-
|
|
66
|
-
|
|
53
|
+
const allExportedMembers = Object.entries<ExportedMemberT>(imported).map(([name, value]) => ({
|
|
54
|
+
name,
|
|
55
|
+
value,
|
|
56
|
+
}));
|
|
67
57
|
|
|
68
58
|
return allExportedMembers;
|
|
69
59
|
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { Biome } from "@biomejs/js-api/nodejs";
|
|
2
|
+
import { Naite } from "../naite/naite";
|
|
3
|
+
import { isTest } from "./controller";
|
|
4
|
+
|
|
5
|
+
const biome = new Biome();
|
|
6
|
+
let projectKey: number = -1;
|
|
7
|
+
|
|
8
|
+
export function setupBiome(path: string) {
|
|
9
|
+
if (projectKey !== -1) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
projectKey = biome.openProject(path).projectKey;
|
|
14
|
+
biome.applyConfiguration(projectKey, {
|
|
15
|
+
formatter: {
|
|
16
|
+
enabled: true,
|
|
17
|
+
formatWithErrors: false,
|
|
18
|
+
indentStyle: "space",
|
|
19
|
+
indentWidth: 2,
|
|
20
|
+
lineEnding: "lf",
|
|
21
|
+
lineWidth: 100,
|
|
22
|
+
attributePosition: "auto",
|
|
23
|
+
},
|
|
24
|
+
linter: {
|
|
25
|
+
enabled: true,
|
|
26
|
+
rules: {
|
|
27
|
+
recommended: true,
|
|
28
|
+
style: {
|
|
29
|
+
useNodejsImportProtocol: "off",
|
|
30
|
+
},
|
|
31
|
+
correctness: {
|
|
32
|
+
useParseIntRadix: "off",
|
|
33
|
+
noEmptyPattern: "off",
|
|
34
|
+
noUnusedImports: {
|
|
35
|
+
level: "warn",
|
|
36
|
+
fix: "safe",
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
a11y: {
|
|
40
|
+
noLabelWithoutControl: "off",
|
|
41
|
+
},
|
|
42
|
+
complexity: {
|
|
43
|
+
noBannedTypes: "off",
|
|
44
|
+
},
|
|
45
|
+
suspicious: {
|
|
46
|
+
noArrayIndexKey: "off",
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
javascript: {
|
|
51
|
+
formatter: {
|
|
52
|
+
jsxQuoteStyle: "double",
|
|
53
|
+
quoteProperties: "asNeeded",
|
|
54
|
+
trailingCommas: "all",
|
|
55
|
+
semicolons: "always",
|
|
56
|
+
arrowParentheses: "always",
|
|
57
|
+
bracketSpacing: true,
|
|
58
|
+
bracketSameLine: false,
|
|
59
|
+
quoteStyle: "double",
|
|
60
|
+
attributePosition: "auto",
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
json: {
|
|
64
|
+
formatter: {
|
|
65
|
+
indentWidth: 2,
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
assist: {
|
|
69
|
+
enabled: true,
|
|
70
|
+
actions: {
|
|
71
|
+
source: {
|
|
72
|
+
organizeImports: "on",
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function formatCode(code: string, parser: "typescript" | "json", filePath: string) {
|
|
80
|
+
Naite.t("formatCode", { code, parser });
|
|
81
|
+
|
|
82
|
+
if (projectKey === -1) {
|
|
83
|
+
console.warn("Biome is not setup. Please call setupBiome first.");
|
|
84
|
+
return code;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// 포맷팅을 먼저 해야함
|
|
88
|
+
const formatted = biome.formatContent(projectKey, code, { filePath });
|
|
89
|
+
Naite.t("formatCode:formatted", formatted);
|
|
90
|
+
if (formatted.diagnostics.filter((d) => d.severity === "error").length > 0) {
|
|
91
|
+
console.error(formatted.diagnostics);
|
|
92
|
+
throw new Error("Biome format error");
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// 린팅을 그 다음에
|
|
96
|
+
const linted = biome.lintContent(projectKey, formatted.content, {
|
|
97
|
+
filePath,
|
|
98
|
+
fixFileMode: "safeAndUnsafeFixes",
|
|
99
|
+
});
|
|
100
|
+
if (linted.diagnostics.filter((d) => d.severity === "error").length > 0) {
|
|
101
|
+
Naite.t("formatCode:linted:content", linted.content);
|
|
102
|
+
Naite.t("formatCode:linted:diagnostics", linted.diagnostics);
|
|
103
|
+
!isTest() && console.dir(linted.diagnostics, { depth: null });
|
|
104
|
+
throw new Error("Biome lint error");
|
|
105
|
+
}
|
|
106
|
+
Naite.t("formatCode:linted", linted);
|
|
107
|
+
|
|
108
|
+
return linted.content;
|
|
109
|
+
}
|
package/src/utils/fs-utils.ts
CHANGED
package/src/utils/lodash-able.ts
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
export function wrapIf(
|
|
2
|
-
source: string,
|
|
3
|
-
predicate: (str: string) => [boolean, string]
|
|
4
|
-
): string {
|
|
1
|
+
export function wrapIf(source: string, predicate: (str: string) => [boolean, string]): string {
|
|
5
2
|
const [ok, wrapped] = predicate(source);
|
|
6
3
|
return ok ? wrapped : source;
|
|
7
4
|
}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
type Primitive = string | number | boolean | null | undefined;
|
|
2
|
+
|
|
3
|
+
type TypedArray =
|
|
4
|
+
| Int8Array
|
|
5
|
+
| Uint8Array
|
|
6
|
+
| Uint8ClampedArray
|
|
7
|
+
| Int16Array
|
|
8
|
+
| Uint16Array
|
|
9
|
+
| Int32Array
|
|
10
|
+
| Uint32Array
|
|
11
|
+
| Float32Array
|
|
12
|
+
| Float64Array
|
|
13
|
+
| BigInt64Array
|
|
14
|
+
| BigUint64Array;
|
|
15
|
+
|
|
16
|
+
type StructuredCloneable = Date | ArrayBuffer | TypedArray;
|
|
17
|
+
|
|
18
|
+
/** 직렬화 불가 타입 (명시적 제외용) */
|
|
19
|
+
type NonSerializable =
|
|
20
|
+
| Function
|
|
21
|
+
| Promise<unknown>
|
|
22
|
+
| RegExp
|
|
23
|
+
| symbol
|
|
24
|
+
// biome-ignore lint/suspicious/noExplicitAny: WeakMap의 제네릭 파라미터
|
|
25
|
+
| WeakMap<any, any>
|
|
26
|
+
// biome-ignore lint/suspicious/noExplicitAny: WeakSet의 제네릭 파라미터
|
|
27
|
+
| WeakSet<any>
|
|
28
|
+
// biome-ignore lint/suspicious/noExplicitAny: WeakRef의 제네릭 파라미터
|
|
29
|
+
| WeakRef<any>;
|
|
30
|
+
|
|
31
|
+
/** 재귀적 직렬화 가능 타입 */
|
|
32
|
+
export type Serializable =
|
|
33
|
+
| Primitive
|
|
34
|
+
| StructuredCloneable
|
|
35
|
+
| SerializableArray
|
|
36
|
+
| SerializableMap
|
|
37
|
+
| SerializableSet
|
|
38
|
+
| SerializableObject;
|
|
39
|
+
|
|
40
|
+
interface SerializableArray extends Array<Serializable> {}
|
|
41
|
+
|
|
42
|
+
interface SerializableMap extends Map<Serializable, Serializable> {}
|
|
43
|
+
|
|
44
|
+
interface SerializableSet extends Set<Serializable> {}
|
|
45
|
+
|
|
46
|
+
interface SerializableObject {
|
|
47
|
+
[key: string]: Serializable;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 주어진 타입 T가 직렬화 가능한지 검증하는 조건부 타입
|
|
52
|
+
* 직렬화 불가한 값이 포함되어 있으면 never를 반환하여 타입 에러가 발생합니다
|
|
53
|
+
*/
|
|
54
|
+
export type AssertSerializable<T> = T extends NonSerializable
|
|
55
|
+
? never
|
|
56
|
+
: T extends Primitive | StructuredCloneable
|
|
57
|
+
? T
|
|
58
|
+
: T extends Map<infer K, infer V>
|
|
59
|
+
? Map<AssertSerializable<K>, AssertSerializable<V>>
|
|
60
|
+
: T extends Set<infer U>
|
|
61
|
+
? Set<AssertSerializable<U>>
|
|
62
|
+
: T extends Array<infer U>
|
|
63
|
+
? AssertSerializable<U>[]
|
|
64
|
+
: T extends object
|
|
65
|
+
? { [K in keyof T]: AssertSerializable<T[K]> }
|
|
66
|
+
: T;
|
|
67
|
+
|
|
68
|
+
export interface SerializableCheckResult {
|
|
69
|
+
valid: boolean;
|
|
70
|
+
reason?: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* 값이 Vitest worker/process 간 전달 가능한지 검증합니다.
|
|
75
|
+
* Serializable하다는 것은 결국 message port와 process.send를 통해 전달 가능한 것을 의미합니다.
|
|
76
|
+
*
|
|
77
|
+
* @param value - 검증할 값
|
|
78
|
+
* @param path - 현재 경로 (에러 메시지용, 내부 재귀에서 사용)
|
|
79
|
+
* @param seen - 순환 참조 감지용 WeakSet (내부 재귀에서 사용)
|
|
80
|
+
* @returns 검증 결과 { valid: boolean, reason?: string }
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* isSerializable({ a: 1, b: "hello" }) // { valid: true }
|
|
84
|
+
* isSerializable({ fn: () => {} }) // { valid: false, reason: "Function at fn" }
|
|
85
|
+
* isSerializable({ deep: { nested: Promise.resolve() } }) // { valid: false, reason: "Promise at deep.nested" }
|
|
86
|
+
*/
|
|
87
|
+
export function isSerializable(
|
|
88
|
+
value: unknown,
|
|
89
|
+
path: string[] = [],
|
|
90
|
+
seen: WeakSet<object> = new WeakSet(),
|
|
91
|
+
): SerializableCheckResult {
|
|
92
|
+
// typeof null === 'object'이므로 먼저 처리
|
|
93
|
+
if (value === null) {
|
|
94
|
+
return { valid: true };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const type = typeof value;
|
|
98
|
+
if (type === "string" || type === "number" || type === "boolean" || type === "undefined") {
|
|
99
|
+
return { valid: true };
|
|
100
|
+
}
|
|
101
|
+
if (type === "bigint") {
|
|
102
|
+
return { valid: true };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (type === "function") {
|
|
106
|
+
return { valid: false, reason: `Function at ${formatPath(path)}` };
|
|
107
|
+
}
|
|
108
|
+
if (type === "symbol") {
|
|
109
|
+
return { valid: false, reason: `Symbol at ${formatPath(path)}` };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (type === "object") {
|
|
113
|
+
const obj = value as object;
|
|
114
|
+
|
|
115
|
+
if (obj instanceof Promise) {
|
|
116
|
+
return { valid: false, reason: `Promise at ${formatPath(path)}` };
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (obj instanceof RegExp) {
|
|
120
|
+
return { valid: false, reason: `RegExp at ${formatPath(path)}` };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (obj instanceof WeakMap) {
|
|
124
|
+
return { valid: false, reason: `WeakMap at ${formatPath(path)}` };
|
|
125
|
+
}
|
|
126
|
+
if (obj instanceof WeakSet) {
|
|
127
|
+
return { valid: false, reason: `WeakSet at ${formatPath(path)}` };
|
|
128
|
+
}
|
|
129
|
+
if (typeof WeakRef !== "undefined" && obj instanceof WeakRef) {
|
|
130
|
+
return { valid: false, reason: `WeakRef at ${formatPath(path)}` };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// 순환 참조 허용하되 무한루프 방지
|
|
134
|
+
if (seen.has(obj)) {
|
|
135
|
+
return { valid: true };
|
|
136
|
+
}
|
|
137
|
+
seen.add(obj);
|
|
138
|
+
|
|
139
|
+
if (obj instanceof Date) {
|
|
140
|
+
return { valid: true };
|
|
141
|
+
}
|
|
142
|
+
if (obj instanceof ArrayBuffer) {
|
|
143
|
+
return { valid: true };
|
|
144
|
+
}
|
|
145
|
+
if (ArrayBuffer.isView(obj)) {
|
|
146
|
+
return { valid: true };
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (obj instanceof Map) {
|
|
150
|
+
let i = 0;
|
|
151
|
+
for (const [k, v] of obj) {
|
|
152
|
+
const keyResult = isSerializable(k, [...path, `Map.key[${i}]`], seen);
|
|
153
|
+
if (!keyResult.valid) return keyResult;
|
|
154
|
+
|
|
155
|
+
const valResult = isSerializable(v, [...path, `Map.value[${i}]`], seen);
|
|
156
|
+
if (!valResult.valid) return valResult;
|
|
157
|
+
i++;
|
|
158
|
+
}
|
|
159
|
+
return { valid: true };
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (obj instanceof Set) {
|
|
163
|
+
let i = 0;
|
|
164
|
+
for (const item of obj) {
|
|
165
|
+
const result = isSerializable(item, [...path, `Set[${i}]`], seen);
|
|
166
|
+
if (!result.valid) return result;
|
|
167
|
+
i++;
|
|
168
|
+
}
|
|
169
|
+
return { valid: true };
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (Array.isArray(obj)) {
|
|
173
|
+
for (let i = 0; i < obj.length; i++) {
|
|
174
|
+
const result = isSerializable(obj[i], [...path, `[${i}]`], seen);
|
|
175
|
+
if (!result.valid) return result;
|
|
176
|
+
}
|
|
177
|
+
return { valid: true };
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Vitest는 Error를 허용하지만 속성은 직렬화 필요
|
|
181
|
+
if (obj instanceof Error) {
|
|
182
|
+
const errorProps = Object.keys(obj).filter((k) => !["name", "message", "stack"].includes(k));
|
|
183
|
+
for (const key of errorProps) {
|
|
184
|
+
const result = isSerializable(
|
|
185
|
+
(obj as unknown as Record<string, unknown>)[key],
|
|
186
|
+
[...path, key],
|
|
187
|
+
seen,
|
|
188
|
+
);
|
|
189
|
+
if (!result.valid) return result;
|
|
190
|
+
}
|
|
191
|
+
return { valid: true };
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Object.prototype 또는 null을 프로토타입으로 가지는 경우만 plain object
|
|
195
|
+
const proto = Object.getPrototypeOf(obj);
|
|
196
|
+
if (proto !== Object.prototype && proto !== null) {
|
|
197
|
+
const constructorName = obj.constructor?.name ?? "Unknown";
|
|
198
|
+
return {
|
|
199
|
+
valid: false,
|
|
200
|
+
reason: `Class instance (${constructorName}) at ${formatPath(path)}`,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
for (const key of Object.keys(obj)) {
|
|
205
|
+
const result = isSerializable((obj as Record<string, unknown>)[key], [...path, key], seen);
|
|
206
|
+
if (!result.valid) return result;
|
|
207
|
+
}
|
|
208
|
+
return { valid: true };
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return { valid: false, reason: `Unknown type (${type}) at ${formatPath(path)}` };
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function formatPath(path: string[]): string {
|
|
215
|
+
if (path.length === 0) return "(root)";
|
|
216
|
+
return path.join(".");
|
|
217
|
+
}
|
package/src/utils/path-utils.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isHotReloadServer } from "./
|
|
1
|
+
import { isHotReloadServer, isTest } from "./controller.js";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* API 패키지 내부 상대 경로 (src/ 또는 dist/로 시작)
|
|
@@ -10,7 +10,7 @@ import { isHotReloadServer } from "./esm-utils.js";
|
|
|
10
10
|
*
|
|
11
11
|
* **기준점**: `Sonamu.apiRootPath` (일반적으로 프로젝트의 `/api` 디렉토리)
|
|
12
12
|
*/
|
|
13
|
-
export type ApiRelativePath = `${"src" | "dist"}/${string}` |
|
|
13
|
+
export type ApiRelativePath = `${"src" | "dist"}/${string}` | "sonamu.config.ts";
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* 앱 루트 기준 상대 경로 (api/, web/ 등 타겟 디렉토리로 시작)
|
|
@@ -90,10 +90,7 @@ export type AbsolutePath = `/${string}`;
|
|
|
90
90
|
* @param anyPath
|
|
91
91
|
* @returns
|
|
92
92
|
*/
|
|
93
|
-
export function runtimePath(
|
|
94
|
-
anyPath: string,
|
|
95
|
-
isDev: boolean = isHotReloadServer()
|
|
96
|
-
): string {
|
|
93
|
+
export function runtimePath(anyPath: string, isDev: boolean = isHotReloadServer() || isTest()): string {
|
|
97
94
|
if (isDev) {
|
|
98
95
|
return anyPath.replace(/dist\//, "src/").replace(/\.js/, ".ts");
|
|
99
96
|
} else {
|
package/src/utils/sql-parser.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import type { AST, ColumnRef, Expr, ExpressionValue, From, Join, Select } from "node-sql-parser";
|
|
2
|
+
import { unique } from "radashi";
|
|
3
|
+
import { nonNullable } from "./utils";
|
|
3
4
|
|
|
4
5
|
export function getTableName(expr: ColumnRef) {
|
|
5
6
|
if ("table" in expr && expr.table !== null) {
|
|
@@ -30,11 +31,28 @@ export function getTableNamesFromWhere(ast: AST | AST[]): string[] {
|
|
|
30
31
|
return [...extractTableName(where.left), ...extractTableName(where.right)];
|
|
31
32
|
};
|
|
32
33
|
|
|
33
|
-
return
|
|
34
|
+
return unique(
|
|
34
35
|
(Array.isArray(ast) ? ast : [ast]).flatMap((a) =>
|
|
35
36
|
a.type === "select" || a.type === "update" || a.type === "delete"
|
|
36
37
|
? extractTableNames(a.where)
|
|
37
|
-
: []
|
|
38
|
-
)
|
|
38
|
+
: [],
|
|
39
|
+
),
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* 주의: table명이 아닌 alias를 반환함
|
|
45
|
+
*/
|
|
46
|
+
export function getJoinTables(ast: AST | AST[], joinTypes: Join["join"][]): string[] {
|
|
47
|
+
const extractJoinTables = (froms: From[]): string[] => {
|
|
48
|
+
return froms
|
|
49
|
+
.map((f) => ("join" in f && joinTypes.includes(f.join) ? f.as : null))
|
|
50
|
+
.filter(nonNullable);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
return unique(
|
|
54
|
+
(Array.isArray(ast) ? ast : [ast]).flatMap((a) =>
|
|
55
|
+
a.type === "select" && Array.isArray(a.from) ? extractJoinTables(a.from) : [],
|
|
56
|
+
),
|
|
39
57
|
);
|
|
40
58
|
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// 타입을 펼쳐서 보여주는 유틸리티 (객체에만 사용해야 함)
|
|
2
|
+
type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;
|
|
3
|
+
|
|
4
|
+
// 핵심 로직
|
|
5
|
+
type SetPath<T, P extends string, V> = T extends readonly (infer U)[] // [Step 1] 현재 타입이 배열인가? -> 요소(U)에 대해 재귀 호출 후 배열로 감쌈
|
|
6
|
+
? SetPath<U, P, V>[]
|
|
7
|
+
: // [Step 2] 경로가 점(.)으로 나뉘는가?
|
|
8
|
+
P extends `${infer K}.${infer Rest}`
|
|
9
|
+
? K extends keyof T
|
|
10
|
+
? // [Step 2-1] 키가 존재함
|
|
11
|
+
Expand<{
|
|
12
|
+
[Key in keyof T]: Key extends K
|
|
13
|
+
? SetPath<T[K], Rest, V> // 재귀 호출
|
|
14
|
+
: T[Key];
|
|
15
|
+
}>
|
|
16
|
+
: // [Step 2-2] 키가 없음 (새로운 객체 경로 생성)
|
|
17
|
+
Expand<T & { [Key in K]: SetPath<{}, Rest, V> }>
|
|
18
|
+
: // [Step 3] 경로의 마지막 (Base Case)
|
|
19
|
+
P extends keyof T
|
|
20
|
+
? // [Step 3-1] 기존 키 덮어쓰기 (교차 타입 & 대신 조건부 타입으로 완전 교체)
|
|
21
|
+
Expand<{ [Key in keyof T]: Key extends P ? V : T[Key] }>
|
|
22
|
+
: // [Step 3-2] 새 키 추가
|
|
23
|
+
Expand<T & { [Key in P]: V }>;
|
|
24
|
+
|
|
25
|
+
export function withProp<T extends object, P extends string, V>(
|
|
26
|
+
obj: T,
|
|
27
|
+
path: P,
|
|
28
|
+
value: V,
|
|
29
|
+
): SetPath<T, P, V> {
|
|
30
|
+
const keys = path.split(".");
|
|
31
|
+
if (keys.length === 0) throw new Error("Path cannot be empty");
|
|
32
|
+
const result = structuredClone(obj);
|
|
33
|
+
|
|
34
|
+
const setDeep = (current: any, keys: string[], value: V): void => {
|
|
35
|
+
if (keys.length === 0) return;
|
|
36
|
+
const [key, ...rest] = keys;
|
|
37
|
+
|
|
38
|
+
if (rest.length === 0) {
|
|
39
|
+
if (Array.isArray(current)) {
|
|
40
|
+
current.forEach((item) => {
|
|
41
|
+
item[key] = value;
|
|
42
|
+
});
|
|
43
|
+
} else {
|
|
44
|
+
current[key] = value;
|
|
45
|
+
}
|
|
46
|
+
} else {
|
|
47
|
+
if (!(key in current) || typeof current[key] !== "object") {
|
|
48
|
+
current[key] = {};
|
|
49
|
+
}
|
|
50
|
+
if (Array.isArray(current[key])) {
|
|
51
|
+
current[key].forEach((item: any) => {
|
|
52
|
+
setDeep(item, rest, value);
|
|
53
|
+
});
|
|
54
|
+
} else {
|
|
55
|
+
setDeep(current[key], rest, value);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
setDeep(result, keys, value);
|
|
61
|
+
return result as SetPath<T, P, V>;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
interface ChainWrapper<T> {
|
|
65
|
+
// 경로에 값을 설정하고 변경된 타입의 새로운 체인 래퍼를 반환합니다.
|
|
66
|
+
set<P extends string, V>(path: P, value: V): ChainWrapper<SetPath<T, P, V>>;
|
|
67
|
+
|
|
68
|
+
// 최종 결과 객체를 반환합니다.
|
|
69
|
+
value(): T;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* 객체를 감싸서 체이닝을 시작합니다.
|
|
74
|
+
*/
|
|
75
|
+
export function withProps<T extends object>(obj: T): ChainWrapper<T> {
|
|
76
|
+
return {
|
|
77
|
+
set: <P extends string, V>(path: P, value: V) => {
|
|
78
|
+
const nextObj = withProp(obj, path, value);
|
|
79
|
+
return withProps(nextObj) as ChainWrapper<SetPath<T, P, V>>;
|
|
80
|
+
},
|
|
81
|
+
value: () => obj,
|
|
82
|
+
};
|
|
83
|
+
}
|