sonamu 0.5.7 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.swcrc.project-default +18 -0
- package/bin/cli.js +24 -0
- package/dist/ai/agents/agent.d.ts +11 -0
- package/dist/ai/agents/agent.d.ts.map +1 -0
- package/dist/ai/agents/agent.js +65 -0
- package/dist/ai/agents/index.d.ts +3 -0
- package/dist/ai/agents/index.d.ts.map +1 -0
- package/dist/ai/agents/index.js +4 -0
- package/dist/ai/agents/types.d.ts +43 -0
- package/dist/ai/agents/types.d.ts.map +1 -0
- package/dist/ai/agents/types.js +3 -0
- package/dist/ai/index.d.ts +2 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +3 -0
- package/dist/ai/providers/rtzr/api.d.ts +22 -0
- package/dist/ai/providers/rtzr/api.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/api.js +28 -0
- package/dist/ai/providers/rtzr/error.d.ts +18 -0
- package/dist/ai/providers/rtzr/error.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/error.js +29 -0
- package/dist/ai/providers/rtzr/index.d.ts +5 -0
- package/dist/ai/providers/rtzr/index.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/index.js +6 -0
- package/dist/ai/providers/rtzr/model.d.ts +52 -0
- package/dist/ai/providers/rtzr/model.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/model.js +137 -0
- package/dist/ai/providers/rtzr/options.d.ts +7 -0
- package/dist/ai/providers/rtzr/options.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/options.js +47 -0
- package/dist/ai/providers/rtzr/provider.d.ts +18 -0
- package/dist/ai/providers/rtzr/provider.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/provider.js +54 -0
- package/dist/ai/providers/rtzr/utils.d.ts +19 -0
- package/dist/ai/providers/rtzr/utils.d.ts.map +1 -0
- package/dist/ai/providers/rtzr/utils.js +88 -0
- package/dist/api/base-frame.d.ts +2 -2
- package/dist/api/base-frame.d.ts.map +1 -1
- package/dist/api/base-frame.js +13 -2
- package/dist/api/caster.d.ts.map +1 -1
- package/dist/api/caster.js +71 -2
- package/dist/api/code-converters.d.ts +58 -14
- package/dist/api/code-converters.d.ts.map +1 -1
- package/dist/api/code-converters.js +258 -2
- package/dist/api/config.d.ts +90 -0
- package/dist/api/config.d.ts.map +1 -0
- package/dist/api/config.js +25 -0
- package/dist/api/context.d.ts +4 -2
- package/dist/api/context.d.ts.map +1 -1
- package/dist/api/context.js +3 -2
- package/dist/api/decorators.d.ts +20 -6
- package/dist/api/decorators.d.ts.map +1 -1
- package/dist/api/decorators.js +235 -2
- package/dist/api/index.d.ts +2 -2
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +9 -2
- package/dist/api/sonamu.d.ts +10 -24
- package/dist/api/sonamu.d.ts.map +1 -1
- package/dist/api/sonamu.js +514 -2
- package/dist/api/validator.d.ts +6 -0
- package/dist/api/validator.d.ts.map +1 -0
- package/dist/api/validator.js +81 -0
- package/dist/bin/build-config.d.ts +6 -1
- package/dist/bin/build-config.d.ts.map +1 -1
- package/dist/bin/build-config.js +15 -2
- package/dist/bin/cli.js +519 -2
- package/dist/bin/hot-hook-register.d.ts +11 -0
- package/dist/bin/hot-hook-register.d.ts.map +1 -0
- package/dist/bin/hot-hook-register.js +21 -0
- package/dist/bin/loader-register.d.ts +2 -0
- package/dist/bin/loader-register.d.ts.map +1 -0
- package/dist/bin/loader-register.js +34 -0
- package/dist/database/_batch_update.d.ts +5 -3
- package/dist/database/_batch_update.d.ts.map +1 -1
- package/dist/database/_batch_update.js +95 -2
- package/dist/database/base-model.d.ts +96 -10
- package/dist/database/base-model.d.ts.map +1 -1
- package/dist/database/base-model.js +390 -2
- package/dist/database/base-model.types.d.ts +93 -0
- package/dist/database/base-model.types.d.ts.map +1 -0
- package/dist/database/base-model.types.js +10 -0
- package/dist/database/code-generator.d.ts +1 -1
- package/dist/database/code-generator.d.ts.map +1 -1
- package/dist/database/code-generator.js +54 -2
- package/dist/database/db.d.ts +6 -21
- package/dist/database/db.d.ts.map +1 -1
- package/dist/database/db.js +129 -2
- package/dist/database/puri-subset.test-d.js +81 -0
- package/dist/database/puri-subset.types.d.ts +123 -0
- package/dist/database/puri-subset.types.d.ts.map +1 -0
- package/dist/database/puri-subset.types.js +16 -0
- package/dist/database/puri-wrapper.d.ts +13 -11
- package/dist/database/puri-wrapper.d.ts.map +1 -1
- package/dist/database/puri-wrapper.js +109 -2
- package/dist/database/puri.d.ts +41 -23
- package/dist/database/puri.d.ts.map +1 -1
- package/dist/database/puri.js +601 -2
- package/dist/database/puri.types.d.ts +25 -6
- package/dist/database/puri.types.d.ts.map +1 -1
- package/dist/database/puri.types.js +6 -2
- package/dist/database/transaction-context.d.ts +1 -1
- package/dist/database/transaction-context.d.ts.map +1 -1
- package/dist/database/transaction-context.js +14 -2
- package/dist/database/upsert-builder.d.ts +9 -3
- package/dist/database/upsert-builder.d.ts.map +1 -1
- package/dist/database/upsert-builder.js +365 -2
- package/dist/entity/entity-manager.d.ts +167 -2
- package/dist/entity/entity-manager.d.ts.map +1 -1
- package/dist/entity/entity-manager.js +130 -2
- package/dist/entity/entity.d.ts +5 -3
- package/dist/entity/entity.d.ts.map +1 -1
- package/dist/entity/entity.js +750 -2
- package/dist/exceptions/error-handler.d.ts +1 -1
- package/dist/exceptions/error-handler.d.ts.map +1 -1
- package/dist/exceptions/error-handler.js +29 -2
- package/dist/exceptions/so-exceptions.d.ts +1 -1
- package/dist/exceptions/so-exceptions.d.ts.map +1 -1
- package/dist/exceptions/so-exceptions.js +85 -2
- package/dist/file-storage/driver.d.ts +1 -1
- package/dist/file-storage/driver.d.ts.map +1 -1
- package/dist/file-storage/driver.js +79 -2
- package/dist/file-storage/file-storage.js +75 -2
- package/dist/index.d.ts +18 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +34 -2
- package/dist/migration/code-generation.d.ts +1 -1
- package/dist/migration/code-generation.d.ts.map +1 -1
- package/dist/migration/code-generation.js +614 -2
- package/dist/migration/migration-set.d.ts +2 -10
- package/dist/migration/migration-set.d.ts.map +1 -1
- package/dist/migration/migration-set.js +213 -2
- package/dist/migration/migrator.d.ts +24 -82
- package/dist/migration/migrator.d.ts.map +1 -1
- package/dist/migration/migrator.js +330 -2
- package/dist/migration/postgresql-schema-reader.d.ts +51 -0
- package/dist/migration/postgresql-schema-reader.d.ts.map +1 -0
- package/dist/migration/postgresql-schema-reader.js +245 -0
- package/dist/migration/types.d.ts +6 -38
- package/dist/migration/types.d.ts.map +1 -1
- package/dist/migration/types.js +3 -2
- package/dist/naite/messaging-types.d.ts +43 -0
- package/dist/naite/messaging-types.d.ts.map +1 -0
- package/dist/naite/messaging-types.js +7 -0
- package/dist/naite/naite-reporter.d.ts +41 -0
- package/dist/naite/naite-reporter.d.ts.map +1 -0
- package/dist/naite/naite-reporter.js +102 -0
- package/dist/naite/naite.d.ts +95 -0
- package/dist/naite/naite.d.ts.map +1 -0
- package/dist/naite/naite.js +316 -0
- package/dist/stream/index.js +3 -2
- package/dist/stream/sse.d.ts +2 -2
- package/dist/stream/sse.d.ts.map +1 -1
- package/dist/stream/sse.js +38 -2
- package/dist/syncer/api-parser.d.ts +10 -0
- package/dist/syncer/api-parser.d.ts.map +1 -0
- package/dist/syncer/api-parser.js +240 -0
- package/dist/syncer/checksum.d.ts +21 -0
- package/dist/syncer/checksum.d.ts.map +1 -0
- package/dist/syncer/checksum.js +98 -0
- package/dist/syncer/code-generator.d.ts +20 -0
- package/dist/syncer/code-generator.d.ts.map +1 -0
- package/dist/syncer/code-generator.js +161 -0
- package/dist/syncer/entity-operations.d.ts +17 -0
- package/dist/syncer/entity-operations.d.ts.map +1 -0
- package/dist/syncer/entity-operations.js +59 -0
- package/dist/syncer/file-patterns.d.ts +29 -0
- package/dist/syncer/file-patterns.d.ts.map +1 -0
- package/dist/syncer/file-patterns.js +38 -0
- package/dist/syncer/index.d.ts +6 -0
- package/dist/syncer/index.d.ts.map +1 -1
- package/dist/syncer/index.js +9 -2
- package/dist/syncer/module-loader.d.ts +35 -0
- package/dist/syncer/module-loader.d.ts.map +1 -0
- package/dist/syncer/module-loader.js +87 -0
- package/dist/syncer/syncer.d.ts +98 -106
- package/dist/syncer/syncer.d.ts.map +1 -1
- package/dist/syncer/syncer.js +422 -2
- package/dist/template/entity-converter.d.ts +14 -0
- package/dist/template/entity-converter.d.ts.map +1 -0
- package/dist/template/entity-converter.js +108 -0
- package/dist/template/helpers.d.ts +23 -0
- package/dist/template/helpers.d.ts.map +1 -0
- package/dist/template/helpers.js +64 -0
- package/dist/{templates → template/implementations}/entity.template.d.ts +3 -3
- package/dist/template/implementations/entity.template.d.ts.map +1 -0
- package/dist/template/implementations/entity.template.js +86 -0
- package/dist/{templates → template/implementations}/generated.template.d.ts +3 -4
- package/dist/template/implementations/generated.template.d.ts.map +1 -0
- package/dist/template/implementations/generated.template.js +249 -0
- package/dist/{templates → template/implementations}/generated_http.template.d.ts +3 -4
- package/dist/template/implementations/generated_http.template.d.ts.map +1 -0
- package/dist/template/implementations/generated_http.template.js +131 -0
- package/dist/{templates → template/implementations}/generated_sso.template.d.ts +4 -5
- package/dist/template/implementations/generated_sso.template.d.ts.map +1 -0
- package/dist/template/implementations/generated_sso.template.js +134 -0
- package/dist/{templates → template/implementations}/init_types.template.d.ts +3 -3
- package/dist/template/implementations/init_types.template.d.ts.map +1 -0
- package/dist/template/implementations/init_types.template.js +38 -0
- package/dist/template/implementations/model.template.d.ts +17 -0
- package/dist/template/implementations/model.template.d.ts.map +1 -0
- package/dist/template/implementations/model.template.js +181 -0
- package/dist/{templates → template/implementations}/model_test.template.d.ts +3 -3
- package/dist/template/implementations/model_test.template.d.ts.map +1 -0
- package/dist/template/implementations/model_test.template.js +35 -0
- package/dist/{templates → template/implementations}/service.template.d.ts +6 -6
- package/dist/template/implementations/service.template.d.ts.map +1 -0
- package/dist/template/implementations/service.template.js +201 -0
- package/dist/{templates → template/implementations}/view_enums_buttonset.template.d.ts +3 -3
- package/dist/template/implementations/view_enums_buttonset.template.d.ts.map +1 -0
- package/dist/template/implementations/view_enums_buttonset.template.js +31 -0
- package/dist/{templates → template/implementations}/view_enums_dropdown.template.d.ts +3 -4
- package/dist/template/implementations/view_enums_dropdown.template.d.ts.map +1 -0
- package/dist/template/implementations/view_enums_dropdown.template.js +50 -0
- package/dist/{templates → template/implementations}/view_enums_select.template.d.ts +3 -3
- package/dist/template/implementations/view_enums_select.template.d.ts.map +1 -0
- package/dist/template/implementations/view_enums_select.template.js +55 -0
- package/dist/{templates → template/implementations}/view_form.template.d.ts +5 -5
- package/dist/template/implementations/view_form.template.d.ts.map +1 -0
- package/dist/template/implementations/view_form.template.js +337 -0
- package/dist/{templates → template/implementations}/view_id_all_select.template.d.ts +3 -3
- package/dist/template/implementations/view_id_all_select.template.d.ts.map +1 -0
- package/dist/template/implementations/view_id_all_select.template.js +31 -0
- package/dist/{templates → template/implementations}/view_id_async_select.template.d.ts +3 -3
- package/dist/template/implementations/view_id_async_select.template.d.ts.map +1 -0
- package/dist/template/implementations/view_id_async_select.template.js +105 -0
- package/dist/{templates → template/implementations}/view_list.template.d.ts +5 -13
- package/dist/template/implementations/view_list.template.d.ts.map +1 -0
- package/dist/template/implementations/view_list.template.js +475 -0
- package/dist/template/implementations/view_list_columns.template.d.ts +17 -0
- package/dist/template/implementations/view_list_columns.template.d.ts.map +1 -0
- package/dist/template/implementations/view_list_columns.template.js +49 -0
- package/dist/{templates → template/implementations}/view_search_input.template.d.ts +3 -3
- package/dist/template/implementations/view_search_input.template.d.ts.map +1 -0
- package/dist/template/implementations/view_search_input.template.js +64 -0
- package/dist/template/index.d.ts +7 -0
- package/dist/template/index.d.ts.map +1 -0
- package/dist/template/index.js +8 -0
- package/dist/template/template-manager.d.ts +56 -0
- package/dist/template/template-manager.d.ts.map +1 -0
- package/dist/template/template-manager.js +125 -0
- package/dist/template/template-types.d.ts +16 -0
- package/dist/template/template-types.d.ts.map +1 -0
- package/dist/template/template-types.js +7 -0
- package/dist/template/template.d.ts +49 -0
- package/dist/template/template.d.ts.map +1 -0
- package/dist/template/template.js +60 -0
- package/dist/template/zod-converter.d.ts +51 -0
- package/dist/template/zod-converter.d.ts.map +1 -0
- package/dist/template/zod-converter.js +449 -0
- package/dist/testing/_relation-graph.d.ts +1 -1
- package/dist/testing/_relation-graph.d.ts.map +1 -1
- package/dist/testing/_relation-graph.js +89 -2
- package/dist/testing/fixture-manager.d.ts +42 -11
- package/dist/testing/fixture-manager.d.ts.map +1 -1
- package/dist/testing/fixture-manager.js +623 -2
- package/dist/types/types.d.ts +747 -143
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/types.js +546 -2
- package/dist/typings/knex.d.js +3 -2
- package/dist/utils/async-utils.d.ts +7 -0
- package/dist/utils/async-utils.d.ts.map +1 -1
- package/dist/utils/async-utils.js +57 -2
- package/dist/utils/console-util.d.ts +2 -0
- package/dist/utils/console-util.d.ts.map +1 -0
- package/dist/utils/console-util.js +6 -0
- package/dist/utils/controller.d.ts +1 -0
- package/dist/utils/controller.d.ts.map +1 -1
- package/dist/utils/controller.js +29 -2
- package/dist/utils/esm-utils.d.ts +39 -0
- package/dist/utils/esm-utils.d.ts.map +1 -0
- package/dist/utils/esm-utils.js +49 -0
- package/dist/utils/formatter.d.ts +3 -0
- package/dist/utils/formatter.d.ts.map +1 -0
- package/dist/utils/formatter.js +110 -0
- package/dist/utils/fs-utils.d.ts +1 -1
- package/dist/utils/fs-utils.d.ts.map +1 -1
- package/dist/utils/fs-utils.js +17 -2
- package/dist/utils/lodash-able.d.ts.map +1 -1
- package/dist/utils/lodash-able.js +6 -2
- package/dist/utils/model.js +22 -2
- package/dist/utils/object-utils.d.ts +44 -0
- package/dist/utils/object-utils.d.ts.map +1 -0
- package/dist/utils/object-utils.js +191 -0
- package/dist/utils/path-utils.d.ts +89 -0
- package/dist/utils/path-utils.d.ts.map +1 -0
- package/dist/utils/path-utils.js +60 -0
- package/dist/utils/process-utils.d.ts +13 -0
- package/dist/utils/process-utils.d.ts.map +1 -0
- package/dist/utils/process-utils.js +36 -0
- package/dist/utils/sql-parser.d.ts +5 -1
- package/dist/utils/sql-parser.d.ts.map +1 -1
- package/dist/utils/sql-parser.js +46 -2
- package/dist/utils/type-utils.d.ts +23 -0
- package/dist/utils/type-utils.d.ts.map +1 -0
- package/dist/utils/type-utils.js +45 -0
- package/dist/utils/utils.d.ts +10 -7
- package/dist/utils/utils.d.ts.map +1 -1
- package/dist/utils/utils.js +72 -2
- package/dist/utils/zod-error.d.ts +1 -1
- package/dist/utils/zod-error.d.ts.map +1 -1
- package/dist/utils/zod-error.js +19 -2
- package/package.json +65 -27
- package/src/ai/agents/agent.ts +87 -0
- package/src/ai/agents/index.ts +2 -0
- package/src/ai/agents/types.ts +47 -0
- package/src/ai/index.ts +1 -0
- package/src/ai/providers/rtzr/api.ts +37 -0
- package/src/ai/providers/rtzr/error.ts +34 -0
- package/src/ai/providers/rtzr/index.ts +4 -0
- package/src/ai/providers/rtzr/model.ts +201 -0
- package/src/ai/providers/rtzr/options.ts +49 -0
- package/src/ai/providers/rtzr/provider.ts +91 -0
- package/src/ai/providers/rtzr/utils.ts +127 -0
- package/src/api/base-frame.ts +4 -2
- package/src/api/caster.ts +17 -23
- package/src/api/code-converters.ts +178 -535
- package/src/api/config.ts +125 -0
- package/src/api/context.ts +7 -17
- package/src/api/decorators.ts +176 -46
- package/src/api/index.ts +2 -2
- package/src/api/sonamu.ts +190 -167
- package/src/api/validator.ts +83 -0
- package/src/bin/build-config.ts +8 -1
- package/src/bin/cli.ts +258 -124
- package/src/bin/hot-hook-register.ts +22 -0
- package/src/bin/loader-register.ts +38 -0
- package/src/database/_batch_update.ts +46 -31
- package/src/database/base-model.ts +390 -182
- package/src/database/base-model.types.ts +155 -0
- package/src/database/code-generator.ts +13 -32
- package/src/database/db.ts +40 -96
- package/src/database/puri-subset.test-d.ts +471 -0
- package/src/database/puri-subset.types.ts +195 -0
- package/src/database/puri-wrapper.ts +58 -67
- package/src/database/puri.ts +229 -148
- package/src/database/puri.types.ts +76 -30
- package/src/database/transaction-context.ts +1 -1
- package/src/database/upsert-builder.ts +262 -132
- package/src/entity/entity-manager.ts +48 -36
- package/src/entity/entity.ts +330 -248
- package/src/exceptions/error-handler.ts +3 -3
- package/src/exceptions/so-exceptions.ts +11 -11
- package/src/file-storage/driver.ts +5 -5
- package/src/file-storage/file-storage.ts +2 -2
- package/src/index.ts +18 -10
- package/src/migration/code-generation.ts +185 -172
- package/src/migration/migration-set.ts +80 -293
- package/src/migration/migrator.ts +199 -571
- package/src/migration/mysql-schema-reader.ts.txt +272 -0
- package/src/migration/postgresql-schema-reader.ts +310 -0
- package/src/migration/types.ts +6 -39
- package/src/naite/messaging-types.ts +51 -0
- package/src/naite/naite-reporter.ts +128 -0
- package/src/naite/naite.ts +415 -0
- package/src/shared/web.shared.ts.txt +20 -24
- package/src/stream/sse.ts +5 -5
- package/src/syncer/api-parser.ts +282 -0
- package/src/syncer/checksum.ts +140 -0
- package/src/syncer/code-generator.ts +198 -0
- package/src/syncer/entity-operations.ts +65 -0
- package/src/syncer/file-patterns.ts +56 -0
- package/src/syncer/index.ts +6 -0
- package/src/syncer/module-loader.ts +128 -0
- package/src/syncer/syncer.ts +389 -1453
- package/src/template/entity-converter.ts +114 -0
- package/src/template/helpers.ts +81 -0
- package/src/{templates → template/implementations}/entity.template.ts +7 -7
- package/src/{templates → template/implementations}/generated.template.ts +101 -101
- package/src/{templates → template/implementations}/generated_http.template.ts +27 -57
- package/src/template/implementations/generated_sso.template.ts +151 -0
- package/src/{templates → template/implementations}/init_types.template.ts +5 -7
- package/src/{templates → template/implementations}/model.template.ts +52 -43
- package/src/{templates → template/implementations}/model_test.template.ts +5 -5
- package/src/{templates → template/implementations}/service.template.ts +66 -82
- package/src/{templates → template/implementations}/view_enums_buttonset.template.ts +3 -3
- package/src/{templates → template/implementations}/view_enums_dropdown.template.ts +4 -20
- package/src/{templates → template/implementations}/view_enums_select.template.ts +4 -4
- package/src/{templates → template/implementations}/view_form.template.ts +40 -83
- package/src/{templates → template/implementations}/view_id_all_select.template.ts +3 -3
- package/src/{templates → template/implementations}/view_id_async_select.template.ts +10 -24
- package/src/{templates → template/implementations}/view_list.template.ts +60 -152
- package/src/{templates → template/implementations}/view_list_columns.template.ts +5 -11
- package/src/{templates → template/implementations}/view_search_input.template.ts +3 -3
- package/src/template/index.ts +6 -0
- package/src/template/template-manager.ts +166 -0
- package/src/template/template-types.ts +16 -0
- package/src/template/template.ts +105 -0
- package/src/template/zod-converter.ts +525 -0
- package/src/testing/_relation-graph.ts +18 -11
- package/src/testing/fixture-manager.ts +472 -359
- package/src/types/types.ts +553 -308
- package/src/typings/knex.d.ts +7 -9
- package/src/utils/async-utils.ts +23 -10
- package/src/utils/console-util.ts +4 -0
- package/src/utils/controller.ts +3 -0
- package/src/utils/esm-utils.ts +59 -0
- package/src/utils/formatter.ts +109 -0
- package/src/utils/fs-utils.ts +1 -1
- package/src/utils/lodash-able.ts +1 -4
- package/src/utils/object-utils.ts +217 -0
- package/src/utils/path-utils.ts +99 -0
- package/src/utils/process-utils.ts +46 -0
- package/src/utils/sql-parser.ts +23 -5
- package/src/utils/type-utils.ts +83 -0
- package/src/utils/utils.ts +66 -43
- package/src/utils/zod-error.ts +3 -4
- package/dist/api/base-frame.js.map +0 -1
- package/dist/api/caster.js.map +0 -1
- package/dist/api/code-converters.js.map +0 -1
- package/dist/api/context.js.map +0 -1
- package/dist/api/decorators.js.map +0 -1
- package/dist/api/index.js.map +0 -1
- package/dist/api/sonamu.js.map +0 -1
- package/dist/bin/build-config.js.map +0 -1
- package/dist/bin/cli-wrapper.d.ts +0 -3
- package/dist/bin/cli-wrapper.d.ts.map +0 -1
- package/dist/bin/cli-wrapper.js +0 -3
- package/dist/bin/cli-wrapper.js.map +0 -1
- package/dist/bin/cli.js.map +0 -1
- package/dist/database/_batch_update.js.map +0 -1
- package/dist/database/base-model.js.map +0 -1
- package/dist/database/code-generator.js.map +0 -1
- package/dist/database/db.js.map +0 -1
- package/dist/database/knex-plugins/knex-on-duplicate-update.d.ts +0 -2
- package/dist/database/knex-plugins/knex-on-duplicate-update.d.ts.map +0 -1
- package/dist/database/knex-plugins/knex-on-duplicate-update.js +0 -2
- package/dist/database/knex-plugins/knex-on-duplicate-update.js.map +0 -1
- package/dist/database/puri-wrapper.js.map +0 -1
- package/dist/database/puri.js.map +0 -1
- package/dist/database/puri.types.js.map +0 -1
- package/dist/database/transaction-context.js.map +0 -1
- package/dist/database/upsert-builder.js.map +0 -1
- package/dist/entity/entity-manager.js.map +0 -1
- package/dist/entity/entity-utils.d.ts +0 -61
- package/dist/entity/entity-utils.d.ts.map +0 -1
- package/dist/entity/entity-utils.js +0 -2
- package/dist/entity/entity-utils.js.map +0 -1
- package/dist/entity/entity.js.map +0 -1
- package/dist/exceptions/error-handler.js.map +0 -1
- package/dist/exceptions/so-exceptions.js.map +0 -1
- package/dist/file-storage/driver.js.map +0 -1
- package/dist/file-storage/file-storage.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/migration/code-generation.js.map +0 -1
- package/dist/migration/migration-set.js.map +0 -1
- package/dist/migration/migrator.js.map +0 -1
- package/dist/migration/types.js.map +0 -1
- package/dist/stream/index.js.map +0 -1
- package/dist/stream/sse.js.map +0 -1
- package/dist/syncer/index.js.map +0 -1
- package/dist/syncer/syncer.js.map +0 -1
- package/dist/templates/base-template.d.ts +0 -13
- package/dist/templates/base-template.d.ts.map +0 -1
- package/dist/templates/base-template.js +0 -2
- package/dist/templates/base-template.js.map +0 -1
- package/dist/templates/entity.template.d.ts.map +0 -1
- package/dist/templates/entity.template.js +0 -2
- package/dist/templates/entity.template.js.map +0 -1
- package/dist/templates/generated.template.d.ts.map +0 -1
- package/dist/templates/generated.template.js +0 -2
- package/dist/templates/generated.template.js.map +0 -1
- package/dist/templates/generated_http.template.d.ts.map +0 -1
- package/dist/templates/generated_http.template.js +0 -2
- package/dist/templates/generated_http.template.js.map +0 -1
- package/dist/templates/generated_sso.template.d.ts.map +0 -1
- package/dist/templates/generated_sso.template.js +0 -2
- package/dist/templates/generated_sso.template.js.map +0 -1
- package/dist/templates/index.d.ts +0 -2
- package/dist/templates/index.d.ts.map +0 -1
- package/dist/templates/index.js +0 -2
- package/dist/templates/index.js.map +0 -1
- package/dist/templates/init_types.template.d.ts.map +0 -1
- package/dist/templates/init_types.template.js +0 -2
- package/dist/templates/init_types.template.js.map +0 -1
- package/dist/templates/model.template.d.ts +0 -17
- package/dist/templates/model.template.d.ts.map +0 -1
- package/dist/templates/model.template.js +0 -2
- package/dist/templates/model.template.js.map +0 -1
- package/dist/templates/model_test.template.d.ts.map +0 -1
- package/dist/templates/model_test.template.js +0 -2
- package/dist/templates/model_test.template.js.map +0 -1
- package/dist/templates/service.template.d.ts.map +0 -1
- package/dist/templates/service.template.js +0 -2
- package/dist/templates/service.template.js.map +0 -1
- package/dist/templates/view_enums_buttonset.template.d.ts.map +0 -1
- package/dist/templates/view_enums_buttonset.template.js +0 -2
- package/dist/templates/view_enums_buttonset.template.js.map +0 -1
- package/dist/templates/view_enums_dropdown.template.d.ts.map +0 -1
- package/dist/templates/view_enums_dropdown.template.js +0 -2
- package/dist/templates/view_enums_dropdown.template.js.map +0 -1
- package/dist/templates/view_enums_select.template.d.ts.map +0 -1
- package/dist/templates/view_enums_select.template.js +0 -2
- package/dist/templates/view_enums_select.template.js.map +0 -1
- package/dist/templates/view_form.template.d.ts.map +0 -1
- package/dist/templates/view_form.template.js +0 -2
- package/dist/templates/view_form.template.js.map +0 -1
- package/dist/templates/view_id_all_select.template.d.ts.map +0 -1
- package/dist/templates/view_id_all_select.template.js +0 -2
- package/dist/templates/view_id_all_select.template.js.map +0 -1
- package/dist/templates/view_id_async_select.template.d.ts.map +0 -1
- package/dist/templates/view_id_async_select.template.js +0 -2
- package/dist/templates/view_id_async_select.template.js.map +0 -1
- package/dist/templates/view_list.template.d.ts.map +0 -1
- package/dist/templates/view_list.template.js +0 -2
- package/dist/templates/view_list.template.js.map +0 -1
- package/dist/templates/view_list_columns.template.d.ts +0 -17
- package/dist/templates/view_list_columns.template.d.ts.map +0 -1
- package/dist/templates/view_list_columns.template.js +0 -2
- package/dist/templates/view_list_columns.template.js.map +0 -1
- package/dist/templates/view_search_input.template.d.ts.map +0 -1
- package/dist/templates/view_search_input.template.js +0 -2
- package/dist/templates/view_search_input.template.js.map +0 -1
- package/dist/testing/_relation-graph.js.map +0 -1
- package/dist/testing/fixture-manager.js.map +0 -1
- package/dist/types/types.js.map +0 -1
- package/dist/typings/knex.d.js.map +0 -1
- package/dist/utils/async-utils.js.map +0 -1
- package/dist/utils/controller.js.map +0 -1
- package/dist/utils/fs-utils.js.map +0 -1
- package/dist/utils/lodash-able.js.map +0 -1
- package/dist/utils/model.js.map +0 -1
- package/dist/utils/sql-parser.js.map +0 -1
- package/dist/utils/utils.js.map +0 -1
- package/dist/utils/zod-error.js.map +0 -1
- package/src/bin/cli-wrapper.ts +0 -75
- package/src/database/knex-plugins/knex-on-duplicate-update.ts +0 -45
- package/src/entity/entity-utils.ts +0 -291
- package/src/templates/base-template.ts +0 -19
- package/src/templates/generated_sso.template.ts +0 -138
- package/src/templates/index.ts +0 -1
package/src/api/sonamu.ts
CHANGED
|
@@ -1,56 +1,22 @@
|
|
|
1
|
+
import assert from "assert";
|
|
1
2
|
import { AsyncLocalStorage } from "async_hooks";
|
|
2
|
-
import chalk from "chalk";
|
|
3
|
-
import fastify from "fastify";
|
|
4
|
-
import { readFile } from "fs/promises";
|
|
5
|
-
import path from "path";
|
|
6
|
-
import { exists } from "../utils/fs-utils";
|
|
7
|
-
|
|
8
3
|
import type { FSWatcher } from "chokidar";
|
|
9
|
-
import { formatInTimeZone } from "date-fns-tz";
|
|
10
4
|
import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
|
|
11
5
|
import type { IncomingMessage, Server, ServerResponse } from "http";
|
|
12
|
-
import
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
BadRequestException,
|
|
17
|
-
NotFoundException,
|
|
18
|
-
} from "../exceptions/so-exceptions";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import type { ZodObject } from "zod";
|
|
8
|
+
import type { SonamuDBConfig } from "../database/db";
|
|
19
9
|
import type { Driver } from "../file-storage/driver";
|
|
20
|
-
import {
|
|
10
|
+
import { Naite } from "../naite/naite";
|
|
21
11
|
import type { Syncer } from "../syncer/syncer";
|
|
22
|
-
import {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
SonamuServerOptions,
|
|
26
|
-
} from "../types/types";
|
|
27
|
-
import { isLocal, isTest } from "../utils/controller";
|
|
28
|
-
import { findApiRootPath } from "../utils/utils";
|
|
29
|
-
import { humanizeZodError } from "../utils/zod-error";
|
|
30
|
-
import { fastifyCaster } from "./caster";
|
|
31
|
-
import { getZodObjectFromApi } from "./code-converters";
|
|
12
|
+
import type { SonamuFastifyConfig } from "../types/types";
|
|
13
|
+
import type { AbsolutePath } from "../utils/path-utils";
|
|
14
|
+
import type { SonamuConfig, SonamuServerOptions } from "./config";
|
|
32
15
|
import type { AuthContext, Context, UploadContext } from "./context";
|
|
33
16
|
import type { ExtendedApi } from "./decorators";
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
export type SonamuConfig = {
|
|
37
|
-
projectName?: string;
|
|
38
|
-
api: {
|
|
39
|
-
dir: string;
|
|
40
|
-
};
|
|
41
|
-
sync: {
|
|
42
|
-
targets: string[];
|
|
43
|
-
};
|
|
44
|
-
route: {
|
|
45
|
-
prefix: string;
|
|
46
|
-
};
|
|
47
|
-
timezone?: string;
|
|
48
|
-
ui?: {
|
|
49
|
-
port: number;
|
|
50
|
-
};
|
|
51
|
-
};
|
|
17
|
+
|
|
52
18
|
export type SonamuSecrets = {
|
|
53
|
-
|
|
19
|
+
anthropic_api_key?: string;
|
|
54
20
|
};
|
|
55
21
|
class SonamuClass {
|
|
56
22
|
public isInitialized: boolean = false;
|
|
@@ -67,7 +33,20 @@ class SonamuClass {
|
|
|
67
33
|
if (store?.context) {
|
|
68
34
|
return store.context;
|
|
69
35
|
}
|
|
70
|
-
|
|
36
|
+
|
|
37
|
+
if (process.env.NODE_ENV === "test") {
|
|
38
|
+
// 테스팅 환경에서 컨텍스트가 주입되지 않은 경우 빈 컨텍스트 리턴
|
|
39
|
+
return {
|
|
40
|
+
request: null,
|
|
41
|
+
reply: null,
|
|
42
|
+
headers: {},
|
|
43
|
+
createSSE: () => {},
|
|
44
|
+
// biome-ignore lint/suspicious/noExplicitAny: 테스팅 환경에서 컨텍스트가 주입되지 않은 경우 빈 컨텍스트 리턴
|
|
45
|
+
naiteStore: new Map<string, any>(),
|
|
46
|
+
} as unknown as Context;
|
|
47
|
+
} else {
|
|
48
|
+
throw new Error("Sonamu cannot find context");
|
|
49
|
+
}
|
|
71
50
|
}
|
|
72
51
|
|
|
73
52
|
public getUploadContext(): UploadContext {
|
|
@@ -75,20 +54,18 @@ class SonamuClass {
|
|
|
75
54
|
if (store?.uploadContext) {
|
|
76
55
|
return store.uploadContext;
|
|
77
56
|
}
|
|
78
|
-
throw new Error(
|
|
79
|
-
"Sonamu cannot find upload context. Did you use @upload decorator?"
|
|
80
|
-
);
|
|
57
|
+
throw new Error("Sonamu cannot find upload context. Did you use @upload decorator?");
|
|
81
58
|
}
|
|
82
59
|
|
|
83
|
-
private _apiRootPath:
|
|
84
|
-
set apiRootPath(apiRootPath:
|
|
60
|
+
private _apiRootPath: AbsolutePath | null = null;
|
|
61
|
+
set apiRootPath(apiRootPath: AbsolutePath) {
|
|
85
62
|
this._apiRootPath = apiRootPath;
|
|
86
63
|
}
|
|
87
|
-
get apiRootPath():
|
|
64
|
+
get apiRootPath(): AbsolutePath {
|
|
88
65
|
if (this._apiRootPath === null) {
|
|
89
66
|
throw new Error("Sonamu has not been initialized");
|
|
90
67
|
}
|
|
91
|
-
return this._apiRootPath
|
|
68
|
+
return this._apiRootPath;
|
|
92
69
|
}
|
|
93
70
|
get appRootPath(): string {
|
|
94
71
|
return this.apiRootPath.split(path.sep).slice(0, -1).join(path.sep);
|
|
@@ -102,7 +79,7 @@ class SonamuClass {
|
|
|
102
79
|
if (this._dbConfig === null) {
|
|
103
80
|
throw new Error("Sonamu has not been initialized");
|
|
104
81
|
}
|
|
105
|
-
return this._dbConfig
|
|
82
|
+
return this._dbConfig;
|
|
106
83
|
}
|
|
107
84
|
|
|
108
85
|
private _syncer: Syncer | null = null;
|
|
@@ -113,7 +90,7 @@ class SonamuClass {
|
|
|
113
90
|
if (this._syncer === null) {
|
|
114
91
|
throw new Error("Sonamu has not been initialized");
|
|
115
92
|
}
|
|
116
|
-
return this._syncer
|
|
93
|
+
return this._syncer;
|
|
117
94
|
}
|
|
118
95
|
|
|
119
96
|
private _config: SonamuConfig | null = null;
|
|
@@ -157,37 +134,40 @@ class SonamuClass {
|
|
|
157
134
|
async init(
|
|
158
135
|
doSilent: boolean = false,
|
|
159
136
|
enableSync: boolean = true,
|
|
160
|
-
apiRootPath?:
|
|
161
|
-
forTesting: boolean = false
|
|
137
|
+
apiRootPath?: AbsolutePath,
|
|
138
|
+
forTesting: boolean = false,
|
|
162
139
|
) {
|
|
163
140
|
if (this.isInitialized) {
|
|
164
141
|
return;
|
|
165
142
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
);
|
|
143
|
+
|
|
144
|
+
if (!doSilent) {
|
|
145
|
+
const chalk = (await import("chalk")).default;
|
|
146
|
+
console.time(chalk.cyan(`Sonamu.init${forTesting ? " for testing" : ""}`));
|
|
147
|
+
}
|
|
170
148
|
|
|
171
149
|
// API 루트 패스
|
|
150
|
+
const { findApiRootPath } = await import("../utils/utils");
|
|
172
151
|
this.apiRootPath = apiRootPath ?? findApiRootPath();
|
|
173
|
-
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
(await readFile(secretsPath)).toString()
|
|
184
|
-
) as SonamuSecrets;
|
|
152
|
+
|
|
153
|
+
const { loadConfig } = await import("./config");
|
|
154
|
+
this.config = await loadConfig(this.apiRootPath);
|
|
155
|
+
// sonamu.config.ts 기본값 설정
|
|
156
|
+
this.config.database.database = this.config.database.database ?? "postgresql";
|
|
157
|
+
|
|
158
|
+
if (process.env.ANTHROPIC_API_KEY) {
|
|
159
|
+
this.secrets = {
|
|
160
|
+
anthropic_api_key: process.env.ANTHROPIC_API_KEY,
|
|
161
|
+
};
|
|
185
162
|
}
|
|
186
163
|
|
|
187
164
|
// DB 로드
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
165
|
+
const { DB } = await import("../database/db");
|
|
166
|
+
this.dbConfig = DB.generateDBConfig(this.config.database);
|
|
167
|
+
if (!doSilent) {
|
|
168
|
+
const chalk = (await import("chalk")).default;
|
|
169
|
+
console.log(chalk.green("DB Config Loaded!"));
|
|
170
|
+
}
|
|
191
171
|
|
|
192
172
|
// 테스팅인 경우 엔티티 로드 & 싱크 없이 중단
|
|
193
173
|
if (forTesting) {
|
|
@@ -204,30 +184,42 @@ class SonamuClass {
|
|
|
204
184
|
this.syncer = new Syncer();
|
|
205
185
|
|
|
206
186
|
// Autoload: Models / Types / APIs
|
|
207
|
-
await this.syncer.autoloadModels();
|
|
208
187
|
await this.syncer.autoloadTypes();
|
|
188
|
+
await this.syncer.autoloadModels();
|
|
209
189
|
await this.syncer.autoloadApis();
|
|
210
190
|
|
|
211
|
-
|
|
191
|
+
const { TemplateManager } = await import("../template");
|
|
192
|
+
await TemplateManager.autoload();
|
|
193
|
+
|
|
194
|
+
const { isLocal, isTest } = await import("../utils/controller");
|
|
195
|
+
if (isLocal()) {
|
|
196
|
+
// 로컬에서는 코드 생성을 위해 Biome 셋업이 필요함 (현재 apiRootPath 전달하여 실행)
|
|
197
|
+
(await import("../utils/formatter")).setupBiome(this.apiRootPath);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const { isHotReloadServer } = await import("../utils/controller");
|
|
201
|
+
if (isLocal() && !isTest() && isHotReloadServer() && enableSync) {
|
|
212
202
|
await this.syncer.sync();
|
|
213
203
|
|
|
214
|
-
|
|
215
|
-
this.startWatcher();
|
|
204
|
+
await this.startWatcher();
|
|
216
205
|
|
|
217
206
|
this.syncer.syncUI();
|
|
218
207
|
}
|
|
219
208
|
|
|
220
209
|
this.isInitialized = true;
|
|
221
|
-
!doSilent
|
|
210
|
+
if (!doSilent) {
|
|
211
|
+
const chalk = (await import("chalk")).default;
|
|
212
|
+
console.timeEnd(chalk.cyan("Sonamu.init"));
|
|
213
|
+
}
|
|
222
214
|
}
|
|
223
215
|
|
|
224
|
-
async createServer(
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
enableSync?: boolean;
|
|
228
|
-
doSilent?: boolean;
|
|
216
|
+
async createServer(initOptions?: { enableSync?: boolean; doSilent?: boolean }) {
|
|
217
|
+
if (this.isInitialized === false) {
|
|
218
|
+
await this.init(initOptions?.doSilent, initOptions?.enableSync);
|
|
229
219
|
}
|
|
230
|
-
|
|
220
|
+
|
|
221
|
+
const options = this.config.server;
|
|
222
|
+
const fastify = (await import("fastify")).default;
|
|
231
223
|
const server = fastify(options.fastify);
|
|
232
224
|
this.server = server;
|
|
233
225
|
|
|
@@ -238,17 +230,15 @@ class SonamuClass {
|
|
|
238
230
|
|
|
239
231
|
// 플러그인 등록
|
|
240
232
|
if (options.plugins) {
|
|
241
|
-
this.registerPlugins(server, options.plugins);
|
|
233
|
+
await this.registerPlugins(server, options.plugins);
|
|
242
234
|
}
|
|
243
235
|
|
|
244
236
|
if (options.auth) {
|
|
245
237
|
if (!options.plugins?.session) {
|
|
246
|
-
throw new Error(
|
|
247
|
-
"Auth requires session plugin. Please add plugins.session configuration."
|
|
248
|
-
);
|
|
238
|
+
throw new Error("Auth requires session plugin. Please add plugins.session configuration.");
|
|
249
239
|
}
|
|
250
240
|
|
|
251
|
-
this.registerAuth(server, options.auth);
|
|
241
|
+
await this.registerAuth(server, options.auth);
|
|
252
242
|
}
|
|
253
243
|
|
|
254
244
|
// API 라우팅 설정
|
|
@@ -269,7 +259,7 @@ class SonamuClass {
|
|
|
269
259
|
options?: {
|
|
270
260
|
enableSync?: boolean;
|
|
271
261
|
doSilent?: boolean;
|
|
272
|
-
}
|
|
262
|
+
},
|
|
273
263
|
) {
|
|
274
264
|
if (this.isInitialized === false) {
|
|
275
265
|
await this.init(options?.doSilent, options?.enableSync);
|
|
@@ -278,55 +268,72 @@ class SonamuClass {
|
|
|
278
268
|
this.server = server;
|
|
279
269
|
|
|
280
270
|
// timezone 설정
|
|
281
|
-
const timezone = this.config.timezone;
|
|
271
|
+
const timezone = this.config.api.timezone;
|
|
282
272
|
if (timezone) {
|
|
283
|
-
|
|
273
|
+
// 타임존에 맞게 응답 날짜 스트링을 변환해주어야 합니다.
|
|
274
|
+
// 가령 timezone이 "Asia/Seoul" 이면
|
|
275
|
+
// "2025-11-21T00:00:00.000Z" 를 "2025-11-21T09:00:00+09:00" 으로 변환해주어야 합니다.
|
|
276
|
+
const { formatInTimeZone } = await import("date-fns-tz");
|
|
277
|
+
|
|
284
278
|
// ISO 8601 날짜 형식 정규식 (예: 2024-01-15T09:30:00.000Z)
|
|
285
279
|
const ISO_DATE_REGEX = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3})?Z$/;
|
|
286
280
|
|
|
281
|
+
// T를 둘러싼 작은따옴표가 없다면 "2025-11-19176354618900018:56:29+09:00"와 같은 결과가 나옵니다.
|
|
282
|
+
// 이는 date-fns 특입니다.
|
|
283
|
+
// 이렇게 해도 괜찮습니다. "2025-11-19T18:56:29+09:00" 모양으로 잘 나옵니다.
|
|
284
|
+
const DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ssXXX";
|
|
285
|
+
|
|
287
286
|
server.setReplySerializer((payload) => {
|
|
288
287
|
return JSON.stringify(payload, (_key, value) => {
|
|
289
288
|
if (typeof value === "string" && ISO_DATE_REGEX.test(value)) {
|
|
290
|
-
return formatInTimeZone(
|
|
289
|
+
return formatInTimeZone(
|
|
290
|
+
new Date(value),
|
|
291
|
+
timezone as `${string}/${string}`,
|
|
292
|
+
DATE_FORMAT,
|
|
293
|
+
);
|
|
291
294
|
}
|
|
292
295
|
return value;
|
|
293
296
|
});
|
|
294
297
|
});
|
|
295
|
-
!options?.doSilent
|
|
298
|
+
if (!options?.doSilent) {
|
|
299
|
+
const chalk = (await import("chalk")).default;
|
|
296
300
|
console.log(chalk.green(`Timezone set to ${timezone}`));
|
|
301
|
+
}
|
|
297
302
|
}
|
|
298
303
|
|
|
299
304
|
// 전체 라우팅 리스트
|
|
300
305
|
server.get(
|
|
301
|
-
`${this.config.route.prefix}/routes`,
|
|
302
|
-
async (_request, _reply): Promise<
|
|
306
|
+
`${this.config.api.route.prefix}/routes`,
|
|
307
|
+
async (_request, _reply): Promise<typeof this.syncer.apis> => {
|
|
303
308
|
return this.syncer.apis;
|
|
304
|
-
}
|
|
309
|
+
},
|
|
305
310
|
);
|
|
306
311
|
|
|
307
312
|
// Healthcheck API
|
|
308
313
|
server.get(
|
|
309
|
-
`${this.config.route.prefix}/healthcheck`,
|
|
314
|
+
`${this.config.api.route.prefix}/healthcheck`,
|
|
310
315
|
async (_request, _reply): Promise<string> => {
|
|
311
316
|
return "ok";
|
|
312
|
-
}
|
|
317
|
+
},
|
|
313
318
|
);
|
|
314
319
|
|
|
315
320
|
// API 라우팅 (로컬HMR 상태와 구분)
|
|
321
|
+
const { isLocal } = await import("../utils/controller");
|
|
316
322
|
if (isLocal()) {
|
|
317
|
-
server.all("*", (request, reply) => {
|
|
323
|
+
server.all("*", async (request, reply) => {
|
|
318
324
|
const found = this.syncer.apis.find(
|
|
319
325
|
(api) =>
|
|
320
|
-
this.config.route.prefix + api.path === request.url.split("?")[0] &&
|
|
321
|
-
(api.options.httpMethod ?? "GET") === request.method.toUpperCase()
|
|
326
|
+
this.config.api.route.prefix + api.path === request.url.split("?")[0] &&
|
|
327
|
+
(api.options.httpMethod ?? "GET") === request.method.toUpperCase(),
|
|
322
328
|
);
|
|
323
329
|
if (found) {
|
|
324
330
|
return this.getApiHandler(found, config)(request, reply);
|
|
325
331
|
}
|
|
332
|
+
const { NotFoundException } = await import("../exceptions/so-exceptions");
|
|
326
333
|
throw new NotFoundException("존재하지 않는 API 접근입니다.");
|
|
327
334
|
});
|
|
328
335
|
} else {
|
|
329
|
-
this.syncer.apis
|
|
336
|
+
for (const api of this.syncer.apis) {
|
|
330
337
|
// model
|
|
331
338
|
if (this.syncer.models[api.modelName] === undefined) {
|
|
332
339
|
throw new Error(`정의되지 않은 모델에 접근 ${api.modelName}`);
|
|
@@ -334,24 +341,23 @@ class SonamuClass {
|
|
|
334
341
|
|
|
335
342
|
// route
|
|
336
343
|
server.route({
|
|
337
|
-
method: api.options.httpMethod
|
|
338
|
-
url: this.config.route.prefix + api.path,
|
|
344
|
+
method: api.options.httpMethod ?? "GET",
|
|
345
|
+
url: this.config.api.route.prefix + api.path,
|
|
339
346
|
handler: this.getApiHandler(api, config),
|
|
340
347
|
}); // END server.route
|
|
341
|
-
}
|
|
348
|
+
}
|
|
342
349
|
}
|
|
343
350
|
}
|
|
344
351
|
|
|
345
|
-
getApiHandler(
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
): Promise<unknown> => {
|
|
350
|
-
(api.options.guards ?? []).every((guard) =>
|
|
351
|
-
config.guardHandler(guard, request, api)
|
|
352
|
-
);
|
|
352
|
+
getApiHandler(
|
|
353
|
+
api: ExtendedApi,
|
|
354
|
+
config: SonamuFastifyConfig,
|
|
355
|
+
): (request: FastifyRequest, reply: FastifyReply) => Promise<unknown> {
|
|
356
|
+
return async (request: FastifyRequest, reply: FastifyReply): Promise<unknown> => {
|
|
357
|
+
(api.options.guards ?? []).every((guard) => config.guardHandler(guard, request, api));
|
|
353
358
|
|
|
354
359
|
// 파라미터 정보로 zod 스키마 빌드
|
|
360
|
+
const { getZodObjectFromApi } = await import("./code-converters");
|
|
355
361
|
const ReqType = getZodObjectFromApi(api, this.syncer.types);
|
|
356
362
|
|
|
357
363
|
// request 파싱
|
|
@@ -360,12 +366,16 @@ class SonamuClass {
|
|
|
360
366
|
[key: string]: unknown;
|
|
361
367
|
};
|
|
362
368
|
try {
|
|
369
|
+
const { fastifyCaster } = await import("./caster");
|
|
363
370
|
reqBody = fastifyCaster(ReqType).parse(request[which] ?? {});
|
|
364
371
|
} catch (e) {
|
|
372
|
+
const { ZodError } = await import("zod");
|
|
365
373
|
if (e instanceof ZodError) {
|
|
374
|
+
const { humanizeZodError } = await import("../utils/zod-error");
|
|
366
375
|
const messages = humanizeZodError(e)
|
|
367
376
|
.map((issue) => issue.message)
|
|
368
377
|
.join(" ");
|
|
378
|
+
const { BadRequestException } = await import("../exceptions/so-exceptions");
|
|
369
379
|
throw new BadRequestException(messages, {
|
|
370
380
|
zodError: e,
|
|
371
381
|
});
|
|
@@ -402,15 +412,12 @@ class SonamuClass {
|
|
|
402
412
|
}
|
|
403
413
|
|
|
404
414
|
// createSSEFactory 함수에 미리 request의 socket과 reply를 바인딩.
|
|
415
|
+
const { createSSEFactory } = await import("../stream/sse");
|
|
405
416
|
const createSSE = (<T extends ZodObject>(
|
|
406
417
|
_request: FastifyRequest,
|
|
407
418
|
_reply: FastifyReply,
|
|
408
|
-
_events: T
|
|
409
|
-
) => createSSEFactory(_request.socket, _reply, _events)).bind(
|
|
410
|
-
null,
|
|
411
|
-
request,
|
|
412
|
-
reply
|
|
413
|
-
);
|
|
419
|
+
_events: T,
|
|
420
|
+
) => createSSEFactory(_request.socket, _reply, _events)).bind(null, request, reply);
|
|
414
421
|
|
|
415
422
|
const context: Context = {
|
|
416
423
|
...(await Promise.resolve(
|
|
@@ -420,25 +427,24 @@ class SonamuClass {
|
|
|
420
427
|
reply,
|
|
421
428
|
headers: request.headers,
|
|
422
429
|
createSSE,
|
|
430
|
+
naiteStore: Naite.createStore(),
|
|
423
431
|
// auth
|
|
424
432
|
user: request.user ?? null,
|
|
425
433
|
passport: {
|
|
426
|
-
login: request.login.bind(
|
|
427
|
-
|
|
428
|
-
) as AuthContext["passport"]["login"],
|
|
429
|
-
logout: request.logout.bind(
|
|
430
|
-
request
|
|
431
|
-
) as AuthContext["passport"]["logout"],
|
|
434
|
+
login: request.login.bind(request) as AuthContext["passport"]["login"],
|
|
435
|
+
logout: request.logout.bind(request) as AuthContext["passport"]["logout"],
|
|
432
436
|
},
|
|
433
437
|
},
|
|
434
438
|
request,
|
|
435
|
-
reply
|
|
436
|
-
)
|
|
439
|
+
reply,
|
|
440
|
+
),
|
|
437
441
|
)),
|
|
438
442
|
};
|
|
439
443
|
|
|
440
444
|
const model = this.syncer.models[api.modelName];
|
|
441
445
|
return this.asyncLocalStorage.run({ context }, async () => {
|
|
446
|
+
const { ApiParamType } = await import("../types/types");
|
|
447
|
+
// biome-ignore lint/suspicious/noExplicitAny: model은 모델 인스턴스이므로 메서드 호출 가능
|
|
442
448
|
const result = await (model as any)[api.methodName].apply(
|
|
443
449
|
model,
|
|
444
450
|
api.parameters.map((param) => {
|
|
@@ -448,7 +454,7 @@ class SonamuClass {
|
|
|
448
454
|
} else {
|
|
449
455
|
return reqBody[param.name];
|
|
450
456
|
}
|
|
451
|
-
})
|
|
457
|
+
}),
|
|
452
458
|
);
|
|
453
459
|
reply.type(api.options.contentType ?? "application/json");
|
|
454
460
|
|
|
@@ -461,25 +467,46 @@ class SonamuClass {
|
|
|
461
467
|
};
|
|
462
468
|
}
|
|
463
469
|
|
|
464
|
-
startWatcher(): void {
|
|
465
|
-
const watchPath =
|
|
466
|
-
|
|
470
|
+
async startWatcher(): Promise<void> {
|
|
471
|
+
const watchPath = [
|
|
472
|
+
path.join(this.apiRootPath, "src"),
|
|
473
|
+
path.join(this.apiRootPath, "sonamu.config.ts"),
|
|
474
|
+
];
|
|
475
|
+
|
|
476
|
+
const chokidar = (await import("chokidar")).default;
|
|
467
477
|
this.watcher = chokidar.watch(watchPath, {
|
|
468
478
|
ignored: (path, stats) =>
|
|
469
|
-
|
|
470
|
-
!path.endsWith(".ts") &&
|
|
471
|
-
!path.endsWith(".json")) ||
|
|
472
|
-
path.endsWith("src/index.ts"),
|
|
479
|
+
!!stats?.isFile() && !path.endsWith(".ts") && !path.endsWith(".json"),
|
|
473
480
|
persistent: true,
|
|
474
481
|
ignoreInitial: true,
|
|
475
482
|
});
|
|
483
|
+
|
|
476
484
|
this.watcher.on("all", async (event: string, filePath: string) => {
|
|
485
|
+
const absolutePath = filePath as AbsolutePath;
|
|
486
|
+
assert(
|
|
487
|
+
absolutePath.startsWith(this.apiRootPath),
|
|
488
|
+
"File path is not within the API root path",
|
|
489
|
+
);
|
|
490
|
+
|
|
477
491
|
if (event !== "change" && event !== "add") {
|
|
478
492
|
return;
|
|
479
493
|
}
|
|
480
494
|
|
|
481
495
|
try {
|
|
482
|
-
|
|
496
|
+
// sonamu.config.ts 변경 시 재시작
|
|
497
|
+
const isConfigTs = filePath === path.join(this.apiRootPath, "sonamu.config.ts");
|
|
498
|
+
|
|
499
|
+
if (isConfigTs) {
|
|
500
|
+
const relativePath = filePath.replace(this.apiRootPath, "api");
|
|
501
|
+
const chalk = (await import("chalk")).default;
|
|
502
|
+
console.log(
|
|
503
|
+
chalk.bold(`Detected(${event}): ${chalk.blue(relativePath)} - Restarting...`),
|
|
504
|
+
);
|
|
505
|
+
process.kill(process.pid, "SIGUSR2");
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
await this.handleFileChange(event, absolutePath);
|
|
483
510
|
} catch (e) {
|
|
484
511
|
console.error(e);
|
|
485
512
|
}
|
|
@@ -498,10 +525,7 @@ class SonamuClass {
|
|
|
498
525
|
}
|
|
499
526
|
}
|
|
500
527
|
|
|
501
|
-
private registerPlugins(
|
|
502
|
-
server: FastifyInstance,
|
|
503
|
-
plugins: SonamuServerOptions["plugins"]
|
|
504
|
-
) {
|
|
528
|
+
private async registerPlugins(server: FastifyInstance, plugins: SonamuServerOptions["plugins"]) {
|
|
505
529
|
if (!plugins) {
|
|
506
530
|
return;
|
|
507
531
|
}
|
|
@@ -516,23 +540,23 @@ class SonamuClass {
|
|
|
516
540
|
session: "@fastify/secure-session",
|
|
517
541
|
} as const;
|
|
518
542
|
|
|
519
|
-
const registerPlugin = <K extends keyof NonNullable<typeof plugins>>(
|
|
543
|
+
const registerPlugin = async <K extends keyof NonNullable<typeof plugins>>(
|
|
520
544
|
key: K,
|
|
521
|
-
pluginName: string
|
|
545
|
+
pluginName: string,
|
|
522
546
|
) => {
|
|
523
547
|
const option = plugins[key];
|
|
524
548
|
if (!option) return;
|
|
525
549
|
|
|
526
550
|
if (option === true) {
|
|
527
|
-
server.register(import(pluginName));
|
|
551
|
+
server.register((await import(pluginName)).default);
|
|
528
552
|
} else {
|
|
529
|
-
server.register(import(pluginName), option);
|
|
553
|
+
server.register((await import(pluginName)).default, option);
|
|
530
554
|
}
|
|
531
555
|
};
|
|
532
556
|
|
|
533
|
-
|
|
534
|
-
registerPlugin(key as keyof typeof plugins, pluginName);
|
|
535
|
-
}
|
|
557
|
+
for (const [key, pluginName] of Object.entries(pluginsModules)) {
|
|
558
|
+
await registerPlugin(key as keyof typeof plugins, pluginName);
|
|
559
|
+
}
|
|
536
560
|
|
|
537
561
|
if (plugins.custom) {
|
|
538
562
|
plugins.custom(server);
|
|
@@ -541,16 +565,16 @@ class SonamuClass {
|
|
|
541
565
|
|
|
542
566
|
private async registerAuth(
|
|
543
567
|
server: FastifyInstance,
|
|
544
|
-
options: NonNullable<SonamuServerOptions["auth"]
|
|
568
|
+
options: NonNullable<SonamuServerOptions["auth"]>,
|
|
545
569
|
) {
|
|
570
|
+
// await import("fastify");
|
|
571
|
+
const fastifyPassport = (await import("@fastify/passport")).default;
|
|
546
572
|
server.register(fastifyPassport.initialize());
|
|
547
573
|
server.register(fastifyPassport.secureSession());
|
|
548
574
|
|
|
549
575
|
if (typeof options === "boolean") {
|
|
550
576
|
fastifyPassport.registerUserSerializer(async (user, _request) => user);
|
|
551
|
-
fastifyPassport.registerUserDeserializer(
|
|
552
|
-
async (serialized, _request) => serialized
|
|
553
|
-
);
|
|
577
|
+
fastifyPassport.registerUserDeserializer(async (serialized, _request) => serialized);
|
|
554
578
|
} else {
|
|
555
579
|
fastifyPassport.registerUserSerializer(options.userSerializer);
|
|
556
580
|
fastifyPassport.registerUserDeserializer(options.userDeserializer);
|
|
@@ -589,26 +613,24 @@ class SonamuClass {
|
|
|
589
613
|
await options.lifecycle?.onStart?.(server);
|
|
590
614
|
})
|
|
591
615
|
.catch(async (err) => {
|
|
616
|
+
const chalk = (await import("chalk")).default;
|
|
592
617
|
console.error(chalk.red("Failed to start server:", err));
|
|
593
618
|
await shutdown();
|
|
594
619
|
});
|
|
595
620
|
}
|
|
596
621
|
|
|
597
|
-
private async handleFileChange(
|
|
598
|
-
event: string,
|
|
599
|
-
filePath: string
|
|
600
|
-
): Promise<void> {
|
|
622
|
+
private async handleFileChange(event: string, filePath: AbsolutePath): Promise<void> {
|
|
601
623
|
// 첫 번째 파일이면 HMR 시작 시간 기록
|
|
602
624
|
if (this.pendingFiles.length === 0) {
|
|
603
625
|
this.hmrStartTime = Date.now();
|
|
604
626
|
}
|
|
605
|
-
|
|
606
627
|
this.pendingFiles.push(filePath);
|
|
607
628
|
|
|
608
|
-
const relativePath =
|
|
629
|
+
const relativePath = path.relative(this.apiRootPath, filePath);
|
|
630
|
+
const chalk = (await import("chalk")).default;
|
|
609
631
|
console.log(chalk.bold(`Detected(${event}): ${chalk.blue(relativePath)}`));
|
|
610
632
|
|
|
611
|
-
await this.syncer.syncFromWatcher(
|
|
633
|
+
await this.syncer.syncFromWatcher(event, filePath);
|
|
612
634
|
|
|
613
635
|
// 처리 완료된 파일을 대기 목록에서 제거
|
|
614
636
|
this.pendingFiles = this.pendingFiles.slice(1);
|
|
@@ -620,20 +642,21 @@ class SonamuClass {
|
|
|
620
642
|
}
|
|
621
643
|
|
|
622
644
|
private async finishHMR(): Promise<void> {
|
|
623
|
-
await this.syncer.
|
|
645
|
+
await this.syncer.renewChecksums();
|
|
624
646
|
|
|
625
647
|
const endTime = Date.now();
|
|
626
648
|
const totalTime = endTime - this.hmrStartTime;
|
|
649
|
+
const [chalk, { centerText }] = await Promise.all([
|
|
650
|
+
(await import("chalk")).default,
|
|
651
|
+
import("../utils/console-util"),
|
|
652
|
+
]);
|
|
627
653
|
const msg = `HMR Done! ${chalk.bold.white(`${totalTime}ms`)}`;
|
|
628
|
-
const margin = Math.max(0, (process.stdout.columns - msg.length) / 2);
|
|
629
654
|
|
|
630
|
-
console.log(
|
|
631
|
-
chalk.black.bgGreen(" ".repeat(margin) + msg + " ".repeat(margin))
|
|
632
|
-
);
|
|
655
|
+
console.log(chalk.black.bgGreen(centerText(msg)));
|
|
633
656
|
}
|
|
634
657
|
|
|
635
658
|
async destroy(): Promise<void> {
|
|
636
|
-
const { BaseModel } =
|
|
659
|
+
const { BaseModel } = await import("../database/base-model");
|
|
637
660
|
await BaseModel.destroy();
|
|
638
661
|
await this.watcher?.close();
|
|
639
662
|
this.storage?.destroy();
|