sonamu 0.10.11 → 0.10.13
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/dist/ai/agents/agent.d.ts +1 -1
- package/dist/ai/agents/agent.d.ts.map +1 -1
- package/dist/ai/agents/agent.js +5 -6
- package/dist/ai/agents/types.d.ts +1 -1
- package/dist/ai/agents/types.d.ts.map +1 -1
- package/dist/ai/providers/rtzr/api.js +18 -18
- package/dist/ai/providers/rtzr/error.d.ts.map +1 -1
- package/dist/ai/providers/rtzr/error.js +17 -15
- package/dist/ai/providers/rtzr/model.d.ts.map +1 -1
- package/dist/ai/providers/rtzr/model.js +3 -2
- package/dist/ai/providers/rtzr/options.d.ts.map +1 -1
- package/dist/ai/providers/rtzr/options.js +16 -16
- package/dist/ai/providers/rtzr/provider.d.ts.map +1 -1
- package/dist/ai/providers/rtzr/provider.js +9 -9
- package/dist/ai/providers/rtzr/utils.d.ts.map +1 -1
- package/dist/ai/providers/rtzr/utils.js +1 -1
- package/dist/api/caster.d.ts.map +1 -1
- package/dist/api/caster.js +17 -17
- package/dist/api/code-converters.d.ts +4 -2
- package/dist/api/code-converters.d.ts.map +1 -1
- package/dist/api/code-converters.js +100 -19
- package/dist/api/config.d.ts +16 -1
- package/dist/api/config.d.ts.map +1 -1
- package/dist/api/config.js +28 -21
- package/dist/api/context.d.ts +2 -2
- package/dist/api/context.d.ts.map +1 -1
- package/dist/api/context.js +1 -1
- package/dist/api/decorators.d.ts.map +1 -1
- package/dist/api/decorators.js +18 -11
- package/dist/api/http-validator.d.ts +36 -0
- package/dist/api/http-validator.d.ts.map +1 -0
- package/dist/api/http-validator.js +72 -0
- package/dist/api/index.js +6 -4
- package/dist/api/sonamu.d.ts +59 -20
- package/dist/api/sonamu.d.ts.map +1 -1
- package/dist/api/sonamu.js +250 -106
- package/dist/api/websocket-helpers.d.ts +7 -5
- package/dist/api/websocket-helpers.d.ts.map +1 -1
- package/dist/api/websocket-helpers.js +6 -6
- package/dist/auth/audit-log/builders.d.ts.map +1 -1
- package/dist/auth/audit-log/builders.js +1 -1
- package/dist/auth/audit-log/client-ip.d.ts +1 -1
- package/dist/auth/audit-log/client-ip.d.ts.map +1 -1
- package/dist/auth/audit-log/client-ip.js +4 -2
- package/dist/auth/audit-log/events.d.ts +5 -1
- package/dist/auth/audit-log/events.d.ts.map +1 -1
- package/dist/auth/audit-log/events.js +1 -1
- package/dist/auth/audit-log/plugin.d.ts +0 -8
- package/dist/auth/audit-log/plugin.d.ts.map +1 -1
- package/dist/auth/audit-log/plugin.js +48 -52
- package/dist/auth/audit-log-ingestor.d.ts.map +1 -1
- package/dist/auth/audit-log-ingestor.js +16 -12
- package/dist/auth/auth-generator.d.ts.map +1 -1
- package/dist/auth/auth-generator.js +1 -1
- package/dist/auth/better-auth-request.d.ts.map +1 -1
- package/dist/auth/better-auth-request.js +6 -5
- package/dist/auth/knex-adapter.js +1 -1
- package/dist/auth/plugins/entity-definitions/index.d.ts +13 -1
- package/dist/auth/plugins/entity-definitions/index.d.ts.map +1 -1
- package/dist/auth/plugins/entity-definitions/index.js +1 -1
- package/dist/auth/plugins/wrappers/admin.d.ts +1 -1
- package/dist/bin/build-config.d.ts +25 -0
- package/dist/bin/build-config.d.ts.map +1 -1
- package/dist/bin/build-config.js +105 -2
- package/dist/bin/cli.js +133 -29
- package/dist/bin/compiler-policy.d.ts +3 -0
- package/dist/bin/compiler-policy.d.ts.map +1 -0
- package/dist/bin/compiler-policy.js +24 -0
- package/dist/bin/fixture.d.ts.map +1 -1
- package/dist/bin/fixture.js +5 -3
- package/dist/bin/test-command.d.ts +22 -1
- package/dist/bin/test-command.d.ts.map +1 -1
- package/dist/bin/test-command.js +18 -10
- package/dist/bin/ts-loader-registration.d.ts +7 -1
- package/dist/bin/ts-loader-registration.d.ts.map +1 -1
- package/dist/bin/ts-loader-registration.js +13 -4
- package/dist/cache/decorator.d.ts.map +1 -1
- package/dist/cache/decorator.js +11 -4
- package/dist/compress/compress.d.ts.map +1 -1
- package/dist/compress/compress.js +1 -1
- package/dist/cone/cone-generator.d.ts +14 -1
- package/dist/cone/cone-generator.d.ts.map +1 -1
- package/dist/cone/cone-generator.js +13 -9
- package/dist/database/_batch_update.js +1 -1
- package/dist/database/base-model.d.ts +22 -10
- package/dist/database/base-model.d.ts.map +1 -1
- package/dist/database/base-model.js +26 -16
- package/dist/database/base-model.types.d.ts +15 -3
- package/dist/database/base-model.types.d.ts.map +1 -1
- package/dist/database/db.d.ts +12 -2
- package/dist/database/db.d.ts.map +1 -1
- package/dist/database/db.js +10 -7
- package/dist/database/knex.d.ts.map +1 -1
- package/dist/database/knex.js +17 -14
- package/dist/database/puri.d.ts +11 -9
- package/dist/database/puri.d.ts.map +1 -1
- package/dist/database/puri.js +93 -79
- package/dist/database/puri.types.d.ts +21 -21
- package/dist/database/puri.types.d.ts.map +1 -1
- package/dist/database/puri.types.js +1 -1
- package/dist/database/upsert-builder.d.ts +12 -10
- package/dist/database/upsert-builder.d.ts.map +1 -1
- package/dist/database/upsert-builder.js +20 -12
- package/dist/dict/sd.d.ts.map +1 -1
- package/dist/dict/sd.js +1 -1
- package/dist/dict/sonamu-dictionary.d.ts.map +1 -1
- package/dist/dict/sonamu-dictionary.js +1 -1
- package/dist/dict/utils.d.ts.map +1 -1
- package/dist/dict/utils.js +7 -2
- package/dist/entity/entity-manager.d.ts +13 -4
- package/dist/entity/entity-manager.d.ts.map +1 -1
- package/dist/entity/entity-manager.js +19 -11
- package/dist/entity/entity-template-cone.d.ts +73 -5
- package/dist/entity/entity-template-cone.d.ts.map +1 -1
- package/dist/entity/entity-template-cone.js +4 -2
- package/dist/entity/entity.d.ts +6 -2
- package/dist/entity/entity.d.ts.map +1 -1
- package/dist/entity/entity.js +30 -28
- package/dist/env.d.ts +3 -1
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +1 -1
- package/dist/exceptions/error-handler.d.ts.map +1 -1
- package/dist/exceptions/error-handler.js +7 -2
- package/dist/exceptions/so-exceptions.d.ts +24 -20
- package/dist/exceptions/so-exceptions.d.ts.map +1 -1
- package/dist/exceptions/so-exceptions.js +4 -2
- package/dist/filter/utils.d.ts +7 -2
- package/dist/filter/utils.d.ts.map +1 -1
- package/dist/filter/utils.js +8 -6
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -7
- package/dist/logger/configure.d.ts.map +1 -1
- package/dist/logger/configure.js +10 -10
- package/dist/migration/code-generation.d.ts.map +1 -1
- package/dist/migration/code-generation.js +50 -46
- package/dist/migration/index-where-predicate.d.ts.map +1 -1
- package/dist/migration/index-where-predicate.js +22 -8
- package/dist/migration/migration-set.d.ts.map +1 -1
- package/dist/migration/migration-set.js +1 -1
- package/dist/migration/migrator.d.ts +61 -36
- package/dist/migration/migrator.d.ts.map +1 -1
- package/dist/migration/migrator.js +276 -167
- package/dist/migration/postgresql-schema-reader.d.ts.map +1 -1
- package/dist/migration/postgresql-schema-reader.js +51 -36
- package/dist/migration/slack-confirm.d.ts.map +1 -1
- package/dist/migration/slack-confirm.js +1 -1
- package/dist/migration/types.d.ts +54 -0
- package/dist/migration/types.d.ts.map +1 -1
- package/dist/naite/naite-reporter.js +2 -2
- package/dist/naite/naite.d.ts +74 -15
- package/dist/naite/naite.d.ts.map +1 -1
- package/dist/naite/naite.js +5 -19
- package/dist/runtime-type.d.ts +6 -0
- package/dist/runtime-type.d.ts.map +1 -0
- package/dist/runtime-type.js +26 -0
- package/dist/ssr/hmr-opt-out.d.ts +26 -0
- package/dist/ssr/hmr-opt-out.d.ts.map +1 -0
- package/dist/ssr/hmr-opt-out.js +59 -0
- package/dist/ssr/renderer.d.ts.map +1 -1
- package/dist/ssr/renderer.js +4 -1
- package/dist/storage/base-file.js +14 -14
- package/dist/storage/buffered-file.d.ts +2 -2
- package/dist/storage/buffered-file.d.ts.map +1 -1
- package/dist/storage/buffered-file.js +12 -12
- package/dist/storage/s3-driver.d.ts.map +1 -1
- package/dist/storage/s3-driver.js +1 -1
- package/dist/storage/uploaded-file.d.ts +2 -2
- package/dist/storage/uploaded-file.d.ts.map +1 -1
- package/dist/storage/uploaded-file.js +8 -8
- package/dist/stream/sse.js +11 -11
- package/dist/stream/ws-core.d.ts +1 -1
- package/dist/stream/ws-core.d.ts.map +1 -1
- package/dist/stream/ws-delivery.d.ts +1 -1
- package/dist/stream/ws-delivery.d.ts.map +1 -1
- package/dist/stream/ws-delivery.js +6 -4
- package/dist/stream/ws-local-connection-store.d.ts.map +1 -1
- package/dist/stream/ws-local-connection-store.js +4 -2
- package/dist/stream/ws-presence-store.js +1 -1
- package/dist/stream/ws-registry.d.ts +4 -4
- package/dist/stream/ws-registry.d.ts.map +1 -1
- package/dist/stream/ws-registry.js +4 -2
- package/dist/stream/ws-telemetry.d.ts +16 -12
- package/dist/stream/ws-telemetry.d.ts.map +1 -1
- package/dist/stream/ws-telemetry.js +22 -18
- package/dist/stream/ws.d.ts +18 -12
- package/dist/stream/ws.d.ts.map +1 -1
- package/dist/stream/ws.js +26 -22
- package/dist/syncer/api-parser.js +1 -1
- package/dist/syncer/checksum.d.ts.map +1 -1
- package/dist/syncer/checksum.js +7 -8
- package/dist/syncer/code-generator.d.ts.map +1 -1
- package/dist/syncer/code-generator.js +13 -14
- package/dist/syncer/entity-operations.d.ts.map +1 -1
- package/dist/syncer/entity-operations.js +5 -6
- package/dist/syncer/file-copy.d.ts +5 -0
- package/dist/syncer/file-copy.d.ts.map +1 -0
- package/dist/syncer/file-copy.js +36 -0
- package/dist/syncer/file-patterns.d.ts +1 -0
- package/dist/syncer/file-patterns.d.ts.map +1 -1
- package/dist/syncer/file-patterns.js +5 -2
- package/dist/syncer/file-tracking.d.ts.map +1 -1
- package/dist/syncer/file-tracking.js +5 -4
- package/dist/syncer/filesystem-dependencies.d.ts +15 -0
- package/dist/syncer/filesystem-dependencies.d.ts.map +1 -0
- package/dist/syncer/filesystem-dependencies.js +53 -0
- package/dist/syncer/module-loader.d.ts +1 -1
- package/dist/syncer/module-loader.d.ts.map +1 -1
- package/dist/syncer/module-loader.js +6 -4
- package/dist/syncer/syncer-actions.d.ts +4 -0
- package/dist/syncer/syncer-actions.d.ts.map +1 -1
- package/dist/syncer/syncer-actions.js +34 -17
- package/dist/syncer/syncer.d.ts +17 -6
- package/dist/syncer/syncer.d.ts.map +1 -1
- package/dist/syncer/syncer.js +71 -29
- package/dist/syncer/watcher.d.ts.map +1 -1
- package/dist/syncer/watcher.js +3 -3
- package/dist/tasks/decorator.d.ts +6 -6
- package/dist/tasks/decorator.d.ts.map +1 -1
- package/dist/tasks/decorator.js +4 -4
- package/dist/tasks/step-wrapper.d.ts +6 -4
- package/dist/tasks/step-wrapper.d.ts.map +1 -1
- package/dist/tasks/step-wrapper.js +5 -5
- package/dist/tasks/workflow-manager.d.ts.map +1 -1
- package/dist/tasks/workflow-manager.js +13 -7
- 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 +2 -2
- package/dist/template/helpers.d.ts +8 -6
- package/dist/template/helpers.d.ts.map +1 -1
- package/dist/template/helpers.js +1 -1
- package/dist/template/implementations/generated.template.d.ts.map +1 -1
- package/dist/template/implementations/generated.template.js +4 -4
- package/dist/template/implementations/generated_http.template.d.ts +7 -4
- package/dist/template/implementations/generated_http.template.d.ts.map +1 -1
- package/dist/template/implementations/generated_http.template.js +21 -21
- package/dist/template/implementations/generated_sso.template.d.ts.map +1 -1
- package/dist/template/implementations/generated_sso.template.js +6 -3
- package/dist/template/implementations/http_validators.template.d.ts +18 -0
- package/dist/template/implementations/http_validators.template.d.ts.map +1 -0
- package/dist/template/implementations/http_validators.template.js +127 -0
- package/dist/template/implementations/model.template.d.ts.map +1 -1
- package/dist/template/implementations/model.template.js +1 -1
- package/dist/template/implementations/queries.template.js +1 -1
- package/dist/template/implementations/sd.template.d.ts.map +1 -1
- package/dist/template/implementations/sd.template.js +79 -39
- package/dist/template/implementations/services.template.d.ts.map +1 -1
- package/dist/template/implementations/services.template.js +6 -4
- package/dist/template/implementations/view_form.template.d.ts +6 -1
- package/dist/template/implementations/view_form.template.d.ts.map +1 -1
- package/dist/template/implementations/view_form.template.js +23 -15
- package/dist/template/implementations/view_list.template.d.ts.map +1 -1
- package/dist/template/implementations/view_list.template.js +11 -6
- package/dist/template/template-manager.d.ts.map +1 -1
- package/dist/template/template-manager.js +9 -7
- package/dist/template/template-types.d.ts +12 -5
- package/dist/template/template-types.d.ts.map +1 -1
- package/dist/template/template-types.js +1 -1
- package/dist/template/template.d.ts +2 -2
- package/dist/template/template.d.ts.map +1 -1
- package/dist/template/template.js +6 -4
- package/dist/template/zod-converter.d.ts +0 -19
- package/dist/template/zod-converter.d.ts.map +1 -1
- package/dist/template/zod-converter.js +100 -84
- package/dist/testing/_relation-graph.d.ts.map +1 -1
- package/dist/testing/_relation-graph.js +2 -1
- package/dist/testing/bootstrap.d.ts.map +1 -1
- package/dist/testing/bootstrap.js +9 -6
- package/dist/testing/data-explorer.d.ts +32 -7
- package/dist/testing/data-explorer.d.ts.map +1 -1
- package/dist/testing/data-explorer.js +77 -31
- package/dist/testing/dev-test-routes.d.ts +8 -1
- package/dist/testing/dev-test-routes.d.ts.map +1 -1
- package/dist/testing/dev-test-routes.js +125 -108
- package/dist/testing/dev-vitest-manager.d.ts +54 -8
- package/dist/testing/dev-vitest-manager.d.ts.map +1 -1
- package/dist/testing/dev-vitest-manager.js +24 -9
- package/dist/testing/faker-mappings.d.ts +412 -1
- package/dist/testing/faker-mappings.d.ts.map +1 -1
- package/dist/testing/faker-mappings.js +1 -1
- package/dist/testing/filesystem.d.ts +2 -0
- package/dist/testing/filesystem.d.ts.map +1 -0
- package/dist/testing/filesystem.js +7 -0
- package/dist/testing/fixture-generator.d.ts +25 -8
- package/dist/testing/fixture-generator.d.ts.map +1 -1
- package/dist/testing/fixture-generator.js +132 -73
- package/dist/testing/fixture-loader.d.ts +3 -1
- package/dist/testing/fixture-loader.d.ts.map +1 -1
- package/dist/testing/fixture-loader.js +1 -20
- package/dist/testing/fixture-manager.d.ts +8 -7
- package/dist/testing/fixture-manager.d.ts.map +1 -1
- package/dist/testing/fixture-manager.js +91 -59
- package/dist/testing/global-setup.d.ts.map +1 -1
- package/dist/testing/global-setup.js +5 -2
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +6 -3
- package/dist/types/types.d.ts +101 -99
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/types.js +234 -225
- package/dist/ui/ai-api.d.ts.map +1 -1
- package/dist/ui/ai-api.js +1 -1
- package/dist/ui/ai-client.d.ts.map +1 -1
- package/dist/ui/ai-client.js +28 -18
- package/dist/ui/api.d.ts.map +1 -1
- package/dist/ui/api.js +146 -210
- package/dist/ui/async-route.d.ts +3 -0
- package/dist/ui/async-route.d.ts.map +1 -0
- package/dist/ui/async-route.js +12 -0
- package/dist/ui/cdd-service.d.ts +9 -7
- package/dist/ui/cdd-service.d.ts.map +1 -1
- package/dist/ui/cdd-service.js +7 -5
- package/dist/ui/migrations-api.d.ts +3 -0
- package/dist/ui/migrations-api.d.ts.map +1 -0
- package/dist/ui/migrations-api.js +215 -0
- package/dist/ui-web/assets/index-D3QNH-Dv.css +1 -0
- package/dist/ui-web/assets/index-DV1AAq6W.js +178 -0
- package/dist/ui-web/index.html +2 -2
- package/dist/utils/formatter.d.ts.map +1 -1
- package/dist/utils/formatter.js +7 -5
- package/dist/utils/fs-utils.d.ts +3 -3
- package/dist/utils/fs-utils.d.ts.map +1 -1
- package/dist/utils/fs-utils.js +6 -6
- package/dist/utils/model.d.ts +3 -5
- package/dist/utils/model.d.ts.map +1 -1
- package/dist/utils/model.js +1 -1
- package/dist/utils/object-utils.d.ts +1 -1
- package/dist/utils/object-utils.d.ts.map +1 -1
- package/dist/utils/object-utils.js +17 -16
- package/dist/utils/process-utils.d.ts.map +1 -1
- package/dist/utils/process-utils.js +4 -2
- package/dist/utils/runtime-value.d.ts +13 -0
- package/dist/utils/runtime-value.d.ts.map +1 -0
- package/dist/utils/runtime-value.js +40 -0
- package/dist/utils/sql-parser.d.ts +8 -1
- package/dist/utils/sql-parser.d.ts.map +1 -1
- package/dist/utils/sql-parser.js +6 -3
- package/dist/utils/type-utils.d.ts.map +1 -1
- package/dist/utils/type-utils.js +10 -8
- package/dist/utils/utils.d.ts +2 -2
- package/dist/utils/utils.d.ts.map +1 -1
- package/dist/utils/utils.js +11 -8
- package/dist/utils/zod-error.d.ts.map +1 -1
- package/dist/utils/zod-error.js +7 -4
- package/dist/vector/chunking.d.ts.map +1 -1
- package/dist/vector/chunking.js +1 -1
- package/dist/vector/embedding.d.ts.map +1 -1
- package/dist/vector/embedding.js +1 -1
- package/dist/vector/types.d.ts +3 -2
- package/dist/vector/types.d.ts.map +1 -1
- package/package.json +11 -7
- package/src/ai/agents/agent.ts +5 -5
- package/src/ai/agents/types.ts +1 -1
- package/src/ai/providers/rtzr/__tests__/model.test.ts +2 -2
- package/src/ai/providers/rtzr/error.ts +5 -3
- package/src/ai/providers/rtzr/model.ts +3 -2
- package/src/ai/providers/rtzr/options.ts +10 -5
- package/src/ai/providers/rtzr/provider.ts +10 -10
- package/src/ai/providers/rtzr/utils.ts +3 -1
- package/src/api/__tests__/config.test.ts +11 -21
- package/src/api/__tests__/sonamu.http-validator.test.ts +512 -0
- package/src/api/__tests__/sonamu.websocket.test.ts +51 -41
- package/src/api/__tests__/zod-compiler-policy.test.ts +95 -0
- package/src/api/caster.ts +6 -8
- package/src/api/code-converters.ts +136 -36
- package/src/api/config.ts +62 -4
- package/src/api/context.ts +3 -3
- package/src/api/decorators.ts +28 -17
- package/src/api/http-validator.ts +149 -0
- package/src/api/sonamu.ts +459 -152
- package/src/api/websocket-helpers.ts +24 -17
- package/src/auth/audit-log/builders.ts +3 -2
- package/src/auth/audit-log/client-ip.ts +4 -2
- package/src/auth/audit-log/events.ts +15 -1
- package/src/auth/audit-log/plugin.ts +129 -200
- package/src/auth/audit-log-ingestor.ts +19 -15
- package/src/auth/auth-generator.ts +10 -5
- package/src/auth/better-auth-request.ts +4 -3
- package/src/auth/knex-adapter.ts +8 -2
- package/src/auth/plugins/entity-definitions/index.ts +6 -5
- package/src/bin/__tests__/http-validator-benchmark.test.ts +94 -0
- package/src/bin/__tests__/test-command.test.ts +9 -15
- package/src/bin/__tests__/ts-loader-register.test.ts +15 -17
- package/src/bin/__tests__/zod-compiler-build.test.ts +307 -0
- package/src/bin/build-config.ts +167 -0
- package/src/bin/cli.ts +155 -38
- package/src/bin/compiler-policy.ts +35 -0
- package/src/bin/fixture.ts +14 -3
- package/src/bin/test-command.ts +74 -29
- package/src/bin/ts-loader-registration.ts +22 -4
- package/src/cache/decorator.ts +10 -3
- package/src/compress/compress.ts +17 -4
- package/src/cone/cone-generator.ts +34 -6
- package/src/database/__tests__/db.test.ts +1 -0
- package/src/database/__tests__/puri.test.ts +16 -15
- package/src/database/__tests__/transaction-scope.test.ts +5 -0
- package/src/database/_batch_update.ts +1 -0
- package/src/database/base-model.ts +81 -50
- package/src/database/base-model.types.ts +6 -6
- package/src/database/db.ts +29 -19
- package/src/database/knex.ts +30 -17
- package/src/database/puri-subset.test-d.ts +17 -0
- package/src/database/puri.ts +181 -143
- package/src/database/puri.types.test-d.ts +31 -1
- package/src/database/puri.types.ts +23 -21
- package/src/database/upsert-builder.ts +75 -53
- package/src/dict/sd.ts +15 -5
- package/src/dict/sonamu-dictionary.ts +6 -6
- package/src/dict/utils.ts +9 -1
- package/src/entity/entity-manager.ts +26 -9
- package/src/entity/entity-template-cone.ts +5 -10
- package/src/entity/entity.ts +50 -34
- package/src/env.ts +7 -3
- package/src/exceptions/error-handler.ts +17 -2
- package/src/exceptions/so-exceptions.ts +26 -20
- package/src/filter/utils.ts +21 -11
- package/src/index.ts +3 -0
- package/src/logger/configure.ts +26 -18
- package/src/migration/__tests__/migrator.test.ts +50 -57
- package/src/migration/code-generation.ts +132 -104
- package/src/migration/index-where-predicate.ts +51 -24
- package/src/migration/migration-set.ts +11 -5
- package/src/migration/migrator.ts +392 -244
- package/src/migration/postgresql-schema-reader.ts +52 -47
- package/src/migration/slack-confirm.ts +17 -15
- package/src/migration/types.ts +57 -0
- package/src/naite/naite-reporter.ts +1 -1
- package/src/naite/naite.ts +97 -24
- package/src/runtime-type.ts +34 -0
- package/src/ssr/hmr-opt-out.ts +78 -0
- package/src/ssr/renderer.ts +6 -0
- package/src/storage/base-file.ts +13 -13
- package/src/storage/buffered-file.ts +11 -11
- package/src/storage/s3-driver.ts +4 -1
- package/src/storage/uploaded-file.ts +8 -8
- package/src/stream/__tests__/ws-contracts.test.ts +4 -2
- package/src/stream/__tests__/ws-telemetry.test.ts +1 -1
- package/src/stream/__tests__/ws.test.ts +30 -6
- package/src/stream/sse.ts +12 -11
- package/src/stream/ws-core.ts +1 -1
- package/src/stream/ws-delivery.ts +16 -7
- package/src/stream/ws-local-connection-store.ts +2 -3
- package/src/stream/ws-presence-store.ts +6 -1
- package/src/stream/ws-registry.ts +16 -7
- package/src/stream/ws-telemetry.ts +66 -43
- package/src/stream/ws.ts +73 -39
- package/src/syncer/__tests__/api-parser.websocket-type-ref.test.ts +3 -2
- package/src/syncer/__tests__/http-validator-registry.test.ts +137 -0
- package/src/syncer/api-parser.ts +67 -27
- package/src/syncer/checksum.ts +17 -11
- package/src/syncer/code-generator.ts +25 -17
- package/src/syncer/entity-operations.ts +3 -5
- package/src/syncer/file-copy.ts +46 -0
- package/src/syncer/file-patterns.ts +11 -8
- package/src/syncer/file-tracking.ts +3 -4
- package/src/syncer/filesystem-dependencies.ts +73 -0
- package/src/syncer/module-loader.ts +8 -4
- package/src/syncer/syncer-actions.ts +56 -18
- package/src/syncer/syncer.ts +116 -43
- package/src/syncer/watcher.ts +8 -4
- package/src/tasks/decorator.ts +20 -12
- package/src/tasks/step-wrapper.ts +19 -9
- package/src/tasks/workflow-manager.ts +15 -9
- package/src/template/__tests__/http_validators.template.test.ts +160 -0
- package/src/template/__tests__/services.template.mutation.test.ts +24 -23
- package/src/template/__tests__/services.template.websocket.test.ts +21 -25
- package/src/template/entity-converter.ts +5 -2
- package/src/template/helpers.ts +8 -9
- package/src/template/implementations/generated.template.ts +5 -4
- package/src/template/implementations/generated_http.template.ts +61 -15
- package/src/template/implementations/generated_sso.template.ts +15 -4
- package/src/template/implementations/http_validators.template.ts +175 -0
- package/src/template/implementations/model.template.ts +3 -1
- package/src/template/implementations/sd.template.ts +81 -41
- package/src/template/implementations/services.template.ts +2 -2
- package/src/template/implementations/view_form.template.ts +56 -39
- package/src/template/implementations/view_list.template.ts +31 -23
- package/src/template/template-manager.ts +15 -13
- package/src/template/template-types.ts +13 -5
- package/src/template/template.ts +4 -3
- package/src/template/zod-converter.ts +206 -91
- package/src/testing/__tests__/dev-test-routes.test.ts +85 -25
- package/src/testing/__tests__/dev-vitest-manager.test.ts +15 -15
- package/src/testing/_relation-graph.ts +4 -1
- package/src/testing/bootstrap.ts +12 -5
- package/src/testing/data-explorer.ts +102 -53
- package/src/testing/dev-test-routes.ts +87 -50
- package/src/testing/dev-vitest-manager.ts +88 -32
- package/src/testing/faker-mappings.ts +2 -2
- package/src/testing/filesystem.ts +1 -0
- package/src/testing/fixture-generator.ts +191 -131
- package/src/testing/fixture-loader.ts +5 -1
- package/src/testing/fixture-manager.ts +129 -90
- package/src/testing/global-setup.ts +7 -3
- package/src/testing/index.ts +5 -0
- package/src/types/__tests__/entity-json-schema-search-text.test.ts +9 -3
- package/src/types/types.ts +184 -158
- package/src/ui/ai-api.ts +9 -7
- package/src/ui/ai-client.ts +61 -56
- package/src/ui/api.ts +726 -770
- package/src/ui/async-route.ts +4 -0
- package/src/ui/cdd-service.ts +35 -12
- package/src/ui/migrations-api.ts +381 -0
- package/src/utils/formatter.ts +7 -3
- package/src/utils/fs-utils.ts +5 -5
- package/src/utils/model.ts +4 -5
- package/src/utils/object-utils.ts +32 -22
- package/src/utils/process-utils.ts +4 -1
- package/src/utils/runtime-value.ts +43 -0
- package/src/utils/sql-parser.ts +13 -6
- package/src/utils/type-utils.ts +9 -7
- package/src/utils/utils.ts +19 -21
- package/src/utils/zod-error.ts +4 -2
- package/src/vector/chunking.ts +6 -1
- package/src/vector/embedding.ts +2 -1
- package/src/vector/types.ts +4 -2
- package/tsdown.api.config.ts +5 -2
- package/dist/ui-web/assets/index-CJf8uJYf.js +0 -176
- package/dist/ui-web/assets/index-GMMIVGja.css +0 -1
|
@@ -6,6 +6,20 @@ import { type ExtendedApi } from "../../api/decorators";
|
|
|
6
6
|
import { Sonamu } from "../../api/sonamu";
|
|
7
7
|
import { Template } from "../template";
|
|
8
8
|
|
|
9
|
+
type RequestDefaultValue =
|
|
10
|
+
| null
|
|
11
|
+
| undefined
|
|
12
|
+
| bigint
|
|
13
|
+
| boolean
|
|
14
|
+
| number
|
|
15
|
+
| string
|
|
16
|
+
| RequestDefaultValue[]
|
|
17
|
+
| RequestDefaultObject;
|
|
18
|
+
|
|
19
|
+
interface RequestDefaultObject {
|
|
20
|
+
[key: string]: RequestDefaultValue;
|
|
21
|
+
}
|
|
22
|
+
|
|
9
23
|
export class Template__generated_http extends Template {
|
|
10
24
|
constructor() {
|
|
11
25
|
super("generated_http");
|
|
@@ -67,16 +81,23 @@ export class Template__generated_http extends Template {
|
|
|
67
81
|
};
|
|
68
82
|
}
|
|
69
83
|
|
|
70
|
-
zodTypeToReqDefault(zodType: z.ZodType, name: string):
|
|
84
|
+
zodTypeToReqDefault(zodType: z.ZodType, name: string): RequestDefaultValue {
|
|
71
85
|
if (zodType instanceof z.ZodObject) {
|
|
72
86
|
return Object.fromEntries(
|
|
73
|
-
Object.keys(zodType
|
|
87
|
+
Object.keys(zodType["shape"]).map((key) => [
|
|
74
88
|
key,
|
|
75
|
-
this.zodTypeToReqDefault(zodType
|
|
89
|
+
this.zodTypeToReqDefault(zodType["shape"][key], key),
|
|
76
90
|
]),
|
|
77
91
|
);
|
|
78
92
|
} else if (zodType instanceof z.ZodArray) {
|
|
79
|
-
return [
|
|
93
|
+
return [
|
|
94
|
+
this.zodTypeToReqDefault(
|
|
95
|
+
/* SAFETY: ZodArray 분기이므로 element가 배열 원소 스키마다. */ (
|
|
96
|
+
zodType as z.ZodArray<z.ZodType>
|
|
97
|
+
).element,
|
|
98
|
+
name,
|
|
99
|
+
),
|
|
100
|
+
];
|
|
80
101
|
} else if (zodType instanceof z.core.$ZodString) {
|
|
81
102
|
// NOTE: z.ZodString으로 비교하면 z.url(), z.email() 등의 타입에서 문제가 생기므로 z.core.$ZodString으로 비교함
|
|
82
103
|
if (name.endsWith("_at") || name.endsWith("_date") || name === "range") {
|
|
@@ -96,11 +117,21 @@ export class Template__generated_http extends Template {
|
|
|
96
117
|
} else if (zodType instanceof z.ZodEnum) {
|
|
97
118
|
return zodType.options[0];
|
|
98
119
|
} else if (zodType instanceof z.ZodOptional) {
|
|
99
|
-
return this.zodTypeToReqDefault(
|
|
120
|
+
return this.zodTypeToReqDefault(
|
|
121
|
+
/* SAFETY: ZodOptional 분기이므로 innerType이 선택 속성의 스키마다. */ (
|
|
122
|
+
zodType as z.ZodOptional<z.ZodType>
|
|
123
|
+
).def.innerType,
|
|
124
|
+
name,
|
|
125
|
+
);
|
|
100
126
|
} else if (zodType instanceof z.ZodNullable) {
|
|
101
127
|
return null;
|
|
102
128
|
} else if (zodType instanceof z.ZodUnion) {
|
|
103
|
-
return this.zodTypeToReqDefault(
|
|
129
|
+
return this.zodTypeToReqDefault(
|
|
130
|
+
/* SAFETY: ZodUnion 분기이므로 options의 첫 항목이 유효한 대안 스키마다. */ (
|
|
131
|
+
zodType as z.ZodUnion<z.ZodType[]>
|
|
132
|
+
).def.options[0],
|
|
133
|
+
name,
|
|
134
|
+
);
|
|
104
135
|
} else if (zodType instanceof z.ZodUnknown) {
|
|
105
136
|
return "unknown";
|
|
106
137
|
} else if (zodType instanceof z.ZodTuple) {
|
|
@@ -112,20 +143,36 @@ export class Template__generated_http extends Template {
|
|
|
112
143
|
return zodType.value;
|
|
113
144
|
} else if (zodType instanceof z.ZodRecord || zodType instanceof z.ZodMap) {
|
|
114
145
|
// oxlint-disable-next-line @typescript-eslint/no-explicit-any -- ZodRecord 타입 사용
|
|
115
|
-
const kvDef =
|
|
146
|
+
const kvDef = /* SAFETY: ZodRecord/ZodMap 분기이므로 def가 키-값 스키마 정의다. */ (
|
|
147
|
+
zodType as z.ZodRecord<any, z.ZodType> | z.ZodMap<z.ZodType, z.ZodType>
|
|
148
|
+
).def;
|
|
116
149
|
// oxlint-disable-next-line @typescript-eslint/no-explicit-any -- ZodIntersection 타입 사용
|
|
117
|
-
const key = this.zodTypeToReqDefault(kvDef.keyType, name)
|
|
150
|
+
const key = String(this.zodTypeToReqDefault(kvDef.keyType, name));
|
|
118
151
|
const value = this.zodTypeToReqDefault(kvDef.valueType, name);
|
|
119
152
|
return { [key]: value };
|
|
120
153
|
} else if (zodType instanceof z.ZodSet) {
|
|
121
|
-
return [
|
|
154
|
+
return [
|
|
155
|
+
this.zodTypeToReqDefault(
|
|
156
|
+
/* SAFETY: ZodSet 분기이므로 valueType이 집합 원소 스키마다. */ (
|
|
157
|
+
zodType as z.ZodSet<z.ZodType>
|
|
158
|
+
).def.valueType,
|
|
159
|
+
name,
|
|
160
|
+
),
|
|
161
|
+
];
|
|
122
162
|
} else if (zodType instanceof z.ZodIntersection) {
|
|
123
163
|
return this.zodTypeToReqDefault(
|
|
124
|
-
|
|
164
|
+
/* SAFETY: ZodIntersection 분기이므로 right가 교차 타입의 우측 스키마다. */ (
|
|
165
|
+
zodType as z.ZodIntersection<z.ZodType, z.ZodType>
|
|
166
|
+
).def.right,
|
|
125
167
|
name,
|
|
126
168
|
);
|
|
127
169
|
} else if (zodType instanceof z.ZodDefault) {
|
|
128
|
-
return this.zodTypeToReqDefault(
|
|
170
|
+
return this.zodTypeToReqDefault(
|
|
171
|
+
/* SAFETY: ZodDefault 분기이므로 innerType이 기본값 적용 전 스키마다. */ (
|
|
172
|
+
zodType as z.ZodDefault<z.ZodType>
|
|
173
|
+
).def.innerType,
|
|
174
|
+
name,
|
|
175
|
+
);
|
|
129
176
|
} else {
|
|
130
177
|
// console.log(zodType);
|
|
131
178
|
return `unknown-${zodType.type}`;
|
|
@@ -135,12 +182,11 @@ export class Template__generated_http extends Template {
|
|
|
135
182
|
resolveApiParams(
|
|
136
183
|
api: ExtendedApi,
|
|
137
184
|
references: { [typeName: string]: z.ZodType },
|
|
138
|
-
):
|
|
185
|
+
): RequestDefaultObject {
|
|
139
186
|
const reqType = getZodObjectFromApi(api, references);
|
|
140
187
|
try {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
};
|
|
188
|
+
// SAFETY: getZodObjectFromApi는 객체 스키마를 반환하므로 기본값도 객체이다.
|
|
189
|
+
const def = this.zodTypeToReqDefault(reqType, "unknownName") as RequestDefaultObject;
|
|
144
190
|
return def;
|
|
145
191
|
} catch (error) {
|
|
146
192
|
console.error(error);
|
|
@@ -36,6 +36,13 @@ function mapBetterAuthFieldType(type: string): string {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
function addLoaderIdTypeSafetyComments(query: string): string {
|
|
40
|
+
return query.replaceAll(
|
|
41
|
+
/fromIds as (?:number|string)\[\]/g,
|
|
42
|
+
"/* SAFETY: 로더가 전달하는 ID는 소스 엔티티의 기본 키 타입과 일치한다. */ $&",
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
39
46
|
export class Template__generated_sso extends Template {
|
|
40
47
|
constructor() {
|
|
41
48
|
super("generated_sso");
|
|
@@ -88,7 +95,8 @@ export class Template__generated_sso extends Template {
|
|
|
88
95
|
lines: [
|
|
89
96
|
`export const ${entityCamelName}LoaderQueries = {`,
|
|
90
97
|
...subsetKeys.map((subsetKey) => {
|
|
91
|
-
|
|
98
|
+
const query = entity.getPuriLoaderQuery(subsetKey);
|
|
99
|
+
return `${subsetKey}: ${addLoaderIdTypeSafetyComments(query)},`;
|
|
92
100
|
}),
|
|
93
101
|
`} as const satisfies PuriLoaderQueries<${subsetKeyTypeName}>;`,
|
|
94
102
|
"",
|
|
@@ -128,7 +136,7 @@ export class Template__generated_sso extends Template {
|
|
|
128
136
|
importKeys: unique([...result.importKeys, ...ts.importKeys]),
|
|
129
137
|
};
|
|
130
138
|
},
|
|
131
|
-
{
|
|
139
|
+
/* SAFETY: reduce 누산기는 label을 제외한 SourceCode의 두 배열로 초기화된다. */ {
|
|
132
140
|
lines: [],
|
|
133
141
|
importKeys: [],
|
|
134
142
|
} as Omit<SourceCode, "label">,
|
|
@@ -295,7 +303,9 @@ export class Template__generated_sso extends Template {
|
|
|
295
303
|
}
|
|
296
304
|
|
|
297
305
|
// oxlint-disable-next-line @typescript-eslint/no-explicit-any -- additionalFields 타입이 동적임
|
|
298
|
-
const additionalFields =
|
|
306
|
+
const additionalFields =
|
|
307
|
+
/* SAFETY: better-auth 설정의 user.additionalFields는 동적 필드 맵이다. */ (authConfig as any)
|
|
308
|
+
?.user?.additionalFields;
|
|
299
309
|
if (!additionalFields || Object.keys(additionalFields).length === 0) {
|
|
300
310
|
// additionalFields가 없으면 기본 User 타입만 사용
|
|
301
311
|
return {
|
|
@@ -310,7 +320,8 @@ export class Template__generated_sso extends Template {
|
|
|
310
320
|
// additionalFields를 TypeScript 타입으로 변환
|
|
311
321
|
const fieldLines = Object.entries(additionalFields).map(([key, value]) => {
|
|
312
322
|
// oxlint-disable-next-line @typescript-eslint/no-explicit-any -- better-auth additionalFields 구조
|
|
313
|
-
const fieldConfig =
|
|
323
|
+
const fieldConfig =
|
|
324
|
+
/* SAFETY: additionalFields의 각 값은 better-auth 필드 설정 객체이다. */ value as any;
|
|
314
325
|
const isRequired = fieldConfig.required !== false;
|
|
315
326
|
|
|
316
327
|
let fieldType: string;
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { type ExtendedApi } from "../../api/decorators";
|
|
2
|
+
import {
|
|
3
|
+
getHttpValidatorFingerprint,
|
|
4
|
+
getHttpValidatorRouteIdentifier,
|
|
5
|
+
getHttpValidatorRouteKey,
|
|
6
|
+
} from "../../api/http-validator";
|
|
7
|
+
import { Sonamu } from "../../api/sonamu";
|
|
8
|
+
import { type ApiParamType } from "../../types/types";
|
|
9
|
+
import { isObjectValue, isStringValue } from "../../utils/runtime-value";
|
|
10
|
+
import { Template } from "../template";
|
|
11
|
+
|
|
12
|
+
function collectReferencedTypes(type: ApiParamType, result: Set<string>): void {
|
|
13
|
+
if (isStringValue(type)) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
switch (type.t) {
|
|
17
|
+
case "ref":
|
|
18
|
+
result.add(type.id);
|
|
19
|
+
for (const argument of type.args ?? []) {
|
|
20
|
+
collectReferencedTypes(argument, result);
|
|
21
|
+
}
|
|
22
|
+
return;
|
|
23
|
+
case "array":
|
|
24
|
+
collectReferencedTypes(type.elementsType, result);
|
|
25
|
+
return;
|
|
26
|
+
case "object":
|
|
27
|
+
for (const prop of type.props) {
|
|
28
|
+
collectReferencedTypes(prop.type, result);
|
|
29
|
+
}
|
|
30
|
+
return;
|
|
31
|
+
case "union":
|
|
32
|
+
case "intersection":
|
|
33
|
+
for (const member of type.types) {
|
|
34
|
+
collectReferencedTypes(member, result);
|
|
35
|
+
}
|
|
36
|
+
return;
|
|
37
|
+
case "tuple-type":
|
|
38
|
+
for (const element of type.elements) {
|
|
39
|
+
collectReferencedTypes(element, result);
|
|
40
|
+
}
|
|
41
|
+
return;
|
|
42
|
+
case "indexed-access":
|
|
43
|
+
collectReferencedTypes(type.object, result);
|
|
44
|
+
collectReferencedTypes(type.index, result);
|
|
45
|
+
return;
|
|
46
|
+
case "type-param":
|
|
47
|
+
if (type.constraint !== undefined) {
|
|
48
|
+
collectReferencedTypes(type.constraint, result);
|
|
49
|
+
}
|
|
50
|
+
return;
|
|
51
|
+
case "function":
|
|
52
|
+
for (const parameter of type.parameters) {
|
|
53
|
+
collectReferencedTypes(parameter.type, result);
|
|
54
|
+
}
|
|
55
|
+
collectReferencedTypes(type.returnType, result);
|
|
56
|
+
return;
|
|
57
|
+
case "string-literal":
|
|
58
|
+
case "numeric-literal":
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export class Template__http_validators extends Template {
|
|
64
|
+
constructor() {
|
|
65
|
+
super("http_validators");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
getTargetAndPath() {
|
|
69
|
+
return {
|
|
70
|
+
target: `${Sonamu.config.api.dir}/src/application`,
|
|
71
|
+
path: "sonamu.validators.generated.ts",
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
render() {
|
|
76
|
+
const apis = [...Sonamu.syncer.apis]
|
|
77
|
+
.filter((api) => api.websocketOptions === undefined)
|
|
78
|
+
.toSorted((left, right) =>
|
|
79
|
+
getHttpValidatorRouteKey(left).localeCompare(getHttpValidatorRouteKey(right)),
|
|
80
|
+
);
|
|
81
|
+
const routeKeys = apis.map(getHttpValidatorRouteKey);
|
|
82
|
+
const duplicateKey = routeKeys.find((key, index) => routeKeys.indexOf(key) !== index);
|
|
83
|
+
if (duplicateKey !== undefined) {
|
|
84
|
+
throw new Error(`중복된 HTTP validator route key: ${duplicateKey}`);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const fingerprint = getHttpValidatorFingerprint(apis);
|
|
88
|
+
const policy = Sonamu.config.validation?.zodCompiler;
|
|
89
|
+
const isAot = isObjectValue(policy) && policy !== null && policy.api === "aot";
|
|
90
|
+
const hasAotValidators = isAot && apis.length > 0;
|
|
91
|
+
const referencedTypes = new Set<string>();
|
|
92
|
+
for (const api of apis) {
|
|
93
|
+
for (const typeParameter of api.typeParameters) {
|
|
94
|
+
collectReferencedTypes(typeParameter, referencedTypes);
|
|
95
|
+
}
|
|
96
|
+
for (const parameter of api.parameters) {
|
|
97
|
+
collectReferencedTypes(parameter.type, referencedTypes);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const importKeys = [...referencedTypes]
|
|
101
|
+
.filter((typeName) => Sonamu.syncer.types[typeName] !== undefined)
|
|
102
|
+
.toSorted();
|
|
103
|
+
const body = isAot
|
|
104
|
+
? this.renderAotRegistry(apis, fingerprint, importKeys)
|
|
105
|
+
: this.renderPlainStub(apis, fingerprint);
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
...this.getTargetAndPath(),
|
|
109
|
+
body,
|
|
110
|
+
importKeys,
|
|
111
|
+
customHeaders: [
|
|
112
|
+
"/**",
|
|
113
|
+
" * @generated",
|
|
114
|
+
" * 직접 수정하지 마세요.",
|
|
115
|
+
" */",
|
|
116
|
+
"",
|
|
117
|
+
"/* oxlint-disable */",
|
|
118
|
+
"",
|
|
119
|
+
...(hasAotValidators
|
|
120
|
+
? [
|
|
121
|
+
`import { compile } from "zod-compiler";`,
|
|
122
|
+
`import { fastifyCaster, getZodObjectFromApi } from "sonamu";`,
|
|
123
|
+
]
|
|
124
|
+
: []),
|
|
125
|
+
],
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
private renderAotRegistry(
|
|
130
|
+
apis: ExtendedApi[],
|
|
131
|
+
fingerprint: string,
|
|
132
|
+
importKeys: string[],
|
|
133
|
+
): string {
|
|
134
|
+
const declarations = apis.map((api) => {
|
|
135
|
+
const identifier = `validator_${getHttpValidatorRouteIdentifier(api)}`;
|
|
136
|
+
const schemaApi = {
|
|
137
|
+
modelName: api.modelName,
|
|
138
|
+
methodName: api.methodName,
|
|
139
|
+
path: api.path,
|
|
140
|
+
options: { httpMethod: api.options.httpMethod ?? "GET" },
|
|
141
|
+
typeParameters: api.typeParameters,
|
|
142
|
+
parameters: api.parameters,
|
|
143
|
+
returnType: "unknown",
|
|
144
|
+
} satisfies ExtendedApi;
|
|
145
|
+
return `export const ${identifier} = compile(fastifyCaster(getZodObjectFromApi(${JSON.stringify(schemaApi)}, { ...types })));`;
|
|
146
|
+
});
|
|
147
|
+
const routeIds = Object.fromEntries(
|
|
148
|
+
apis.map((api) => [getHttpValidatorRouteKey(api), getHttpValidatorRouteIdentifier(api)]),
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
return [
|
|
152
|
+
`export const fingerprint = ${JSON.stringify(fingerprint)};`,
|
|
153
|
+
`export const routeIds = ${JSON.stringify(routeIds)};`,
|
|
154
|
+
`const types = { ${importKeys.join(", ")} };`,
|
|
155
|
+
...declarations,
|
|
156
|
+
`export const validators = new Map([`,
|
|
157
|
+
...apis.map((api) => {
|
|
158
|
+
const routeKey = getHttpValidatorRouteKey(api);
|
|
159
|
+
return ` [${JSON.stringify(routeKey)}, validator_${getHttpValidatorRouteIdentifier(api)}],`;
|
|
160
|
+
}),
|
|
161
|
+
`]);`,
|
|
162
|
+
].join("\n");
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
private renderPlainStub(apis: ExtendedApi[], fingerprint: string): string {
|
|
166
|
+
const routeIds = Object.fromEntries(
|
|
167
|
+
apis.map((api) => [getHttpValidatorRouteKey(api), getHttpValidatorRouteIdentifier(api)]),
|
|
168
|
+
);
|
|
169
|
+
return [
|
|
170
|
+
`export const fingerprint = ${JSON.stringify(fingerprint)};`,
|
|
171
|
+
`export const routeIds = ${JSON.stringify(routeIds)};`,
|
|
172
|
+
`export const validators = new Map();`,
|
|
173
|
+
].join("\n");
|
|
174
|
+
}
|
|
175
|
+
}
|
|
@@ -33,7 +33,9 @@ export class Template__model extends Template {
|
|
|
33
33
|
const listParamsNode = zodTypeToRenderingNode(listParamsZodType);
|
|
34
34
|
|
|
35
35
|
const subsetKeyZodType = await getZodTypeById(`${entityId}SubsetKey`);
|
|
36
|
-
const subsetKeys =
|
|
36
|
+
const subsetKeys =
|
|
37
|
+
/* SAFETY: 생성된 *SubsetKey 타입은 enum 스키마로 등록된다. */ (subsetKeyZodType as z.ZodEnum)
|
|
38
|
+
.enum;
|
|
37
39
|
|
|
38
40
|
const names = EntityManager.getNamesFromId(entityId);
|
|
39
41
|
const entity = EntityManager.get(entityId);
|
|
@@ -52,8 +52,9 @@ const SUPPORTED_LOCALES = ${JSON.stringify(supportedLocales)} as const;
|
|
|
52
52
|
function getCurrentLocale(): (typeof SUPPORTED_LOCALES)[number] {
|
|
53
53
|
try {
|
|
54
54
|
const ctx = Sonamu.getContext();
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
const locale = ctx.locale;
|
|
56
|
+
return SUPPORTED_LOCALES.find((supportedLocale) => supportedLocale === locale) ?? DEFAULT_LOCALE;
|
|
57
|
+
} catch {
|
|
57
58
|
return DEFAULT_LOCALE;
|
|
58
59
|
}
|
|
59
60
|
}
|
|
@@ -61,14 +62,14 @@ function getCurrentLocale(): (typeof SUPPORTED_LOCALES)[number] {
|
|
|
61
62
|
: `
|
|
62
63
|
const DEFAULT_LOCALE = "${defaultLocale}" as const;
|
|
63
64
|
export const SUPPORTED_LOCALES = ${JSON.stringify(supportedLocales)} as const;
|
|
64
|
-
let
|
|
65
|
+
let currentLocale: (typeof SUPPORTED_LOCALES)[number] = DEFAULT_LOCALE;
|
|
65
66
|
|
|
66
67
|
export function setLocale(locale: (typeof SUPPORTED_LOCALES)[number]) {
|
|
67
|
-
|
|
68
|
+
currentLocale = locale;
|
|
68
69
|
}
|
|
69
70
|
|
|
70
71
|
export function getCurrentLocale(): (typeof SUPPORTED_LOCALES)[number] {
|
|
71
|
-
return
|
|
72
|
+
return currentLocale;
|
|
72
73
|
}
|
|
73
74
|
`.trim();
|
|
74
75
|
|
|
@@ -126,7 +127,10 @@ export function defineLocale(dict: Partial<MergedDictionary>) {
|
|
|
126
127
|
}
|
|
127
128
|
|
|
128
129
|
// 각 locale별로 rc-keys + entity labels + 프로젝트 dict 합침
|
|
129
|
-
|
|
130
|
+
type DictionaryRegistry = {
|
|
131
|
+
[L in (typeof SUPPORTED_LOCALES)[number]]: Partial<MergedDictionary>;
|
|
132
|
+
};
|
|
133
|
+
const dictionaries: DictionaryRegistry = {
|
|
130
134
|
${defaultLocale}: { ...${getRCKeysVarName(defaultLocale)}, ...entityLabels, ...${defaultLocale} },
|
|
131
135
|
${supportedLocales
|
|
132
136
|
.filter((locale) => locale !== defaultLocale)
|
|
@@ -138,29 +142,33 @@ type SDReturnType<K extends DictKey> = MergedDictionary[K] extends (...args: inf
|
|
|
138
142
|
? (...args: P) => LocalizedString
|
|
139
143
|
: LocalizedString;
|
|
140
144
|
|
|
141
|
-
function getDictValue<K extends DictKey>(key: K, locale:
|
|
145
|
+
function getDictValue<K extends DictKey>(key: K, locale: (typeof SUPPORTED_LOCALES)[number]): SDReturnType<K> {
|
|
142
146
|
// 1. 지정된 locale에서 조회
|
|
143
147
|
const dict = dictionaries[locale];
|
|
144
148
|
if (dict?.[key] !== undefined) {
|
|
145
|
-
|
|
149
|
+
// SAFETY: 요청 locale의 같은 키는 MergedDictionary가 정한 반환 종류를 유지합니다.
|
|
150
|
+
return dict[key] as SDReturnType<K>;
|
|
146
151
|
}
|
|
147
152
|
|
|
148
153
|
// 2. default locale에서 조회
|
|
149
154
|
if (locale !== DEFAULT_LOCALE && dictionaries[DEFAULT_LOCALE]?.[key] !== undefined) {
|
|
150
|
-
|
|
155
|
+
// SAFETY: 기본 locale의 같은 키는 MergedDictionary가 정한 반환 종류를 유지합니다.
|
|
156
|
+
return dictionaries[DEFAULT_LOCALE][key] as SDReturnType<K>;
|
|
151
157
|
}
|
|
152
158
|
|
|
153
159
|
// 3. supported locales 순회
|
|
154
160
|
for (const supportedLocale of SUPPORTED_LOCALES) {
|
|
155
161
|
if (supportedLocale !== locale && supportedLocale !== DEFAULT_LOCALE) {
|
|
156
162
|
if (dictionaries[supportedLocale]?.[key] !== undefined) {
|
|
157
|
-
|
|
163
|
+
// SAFETY: 대체 locale의 같은 키는 MergedDictionary가 정한 반환 종류를 유지합니다.
|
|
164
|
+
return dictionaries[supportedLocale][key] as SDReturnType<K>;
|
|
158
165
|
}
|
|
159
166
|
}
|
|
160
167
|
}
|
|
161
168
|
|
|
162
|
-
//
|
|
163
|
-
|
|
169
|
+
// 모든 locale에 값이 없으면 동적으로 조합된 키를 그대로 노출합니다.
|
|
170
|
+
// SAFETY: 누락된 사전 키의 문자열 표현은 LocalizedString fallback 규약을 따릅니다.
|
|
171
|
+
return String(key) as SDReturnType<K>;
|
|
164
172
|
}
|
|
165
173
|
|
|
166
174
|
/**
|
|
@@ -226,58 +234,85 @@ type LocalizedColumnCandidate<T, K extends string> =
|
|
|
226
234
|
type LocalizedColumnReturn<T, K extends string> =
|
|
227
235
|
| LocalizedColumnValueFrom<LocalizedColumnCandidate<T, K>>
|
|
228
236
|
| undefined;
|
|
229
|
-
type LocaleValueMap =
|
|
237
|
+
type LocaleValueMap = {
|
|
238
|
+
[L in (typeof SUPPORTED_LOCALES)[number]]?: LocalizedColumnValue;
|
|
239
|
+
};
|
|
240
|
+
function isString<V>(value: V): value is V & string {
|
|
241
|
+
return Object.prototype.toString.call(value) === "[object String]";
|
|
242
|
+
}
|
|
230
243
|
|
|
231
|
-
function isLocalizedColumnValue(value:
|
|
232
|
-
return
|
|
244
|
+
function isLocalizedColumnValue<V>(value: V): value is V & LocalizedColumnValue {
|
|
245
|
+
return isString(value) || (Array.isArray(value) && value.every(isString));
|
|
233
246
|
}
|
|
234
247
|
|
|
235
|
-
function isLocalizedColumnScalarValue(value:
|
|
236
|
-
return ["
|
|
248
|
+
function isLocalizedColumnScalarValue<V>(value: V): value is V & LocalizedColumnScalarValue {
|
|
249
|
+
return ["[object String]", "[object Number]", "[object Boolean]", "[object BigInt]"].includes(
|
|
250
|
+
Object.prototype.toString.call(value),
|
|
251
|
+
);
|
|
237
252
|
}
|
|
238
253
|
|
|
239
|
-
function isEmptyLocalizedColumnValue(value:
|
|
254
|
+
function isEmptyLocalizedColumnValue<V>(value: V): value is V & (null | undefined | "") {
|
|
240
255
|
return value === null || value === undefined || value === "";
|
|
241
256
|
}
|
|
242
257
|
|
|
243
|
-
|
|
258
|
+
type PropertyValue<T, K extends PropertyKey> = K extends keyof T ? T[K] : undefined;
|
|
259
|
+
|
|
260
|
+
function getProperty<T extends object, K extends PropertyKey>(row: T, key: K): PropertyValue<T, K> {
|
|
261
|
+
if (!(key in row)) {
|
|
262
|
+
// SAFETY: 존재하지 않는 후보 키는 조건부 속성 타입에서도 undefined입니다.
|
|
263
|
+
return undefined as PropertyValue<T, K>;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// SAFETY: own/inherited 키 존재를 확인했으므로 해당 키의 조건부 속성 타입으로 좁힐 수 있습니다.
|
|
267
|
+
return (row as T & Record<K, PropertyValue<T, K>>)[key];
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function getNestedLocaleValue<T extends object, K extends LocalizedBaseColumn<T>>(
|
|
244
271
|
row: T,
|
|
245
272
|
column: K,
|
|
246
273
|
locale: (typeof SUPPORTED_LOCALES)[number],
|
|
247
|
-
):
|
|
248
|
-
const columnValue = row
|
|
249
|
-
if (columnValue === null ||
|
|
274
|
+
): LocalizedColumnValue | undefined {
|
|
275
|
+
const columnValue = getProperty(row, column);
|
|
276
|
+
if (columnValue === null || Object.prototype.toString.call(columnValue) !== "[object Object]") {
|
|
250
277
|
return undefined;
|
|
251
278
|
}
|
|
252
279
|
|
|
280
|
+
// SAFETY: 일반 객체 검사를 통과한 값만 locale별 값 맵으로 조회합니다.
|
|
253
281
|
return (columnValue as LocaleValueMap)[locale];
|
|
254
282
|
}
|
|
255
283
|
|
|
256
|
-
|
|
284
|
+
function localizedKey<K extends string>(columnName: K, localeName: (typeof SUPPORTED_LOCALES)[number]) {
|
|
285
|
+
return \`\${columnName}_\${localeName}\`;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export function localizedColumn<T extends object, K extends LocalizedBaseColumn<T>>(
|
|
257
289
|
row: T,
|
|
258
290
|
column: K,
|
|
259
291
|
): LocalizedColumnReturn<T, K> {
|
|
260
|
-
const
|
|
261
|
-
const locale = SUPPORTED_LOCALES.includes(
|
|
262
|
-
const otherLocales = SUPPORTED_LOCALES.filter(
|
|
263
|
-
|
|
292
|
+
const requestedLocale = getCurrentLocale();
|
|
293
|
+
const locale = SUPPORTED_LOCALES.includes(requestedLocale) ? requestedLocale : DEFAULT_LOCALE;
|
|
294
|
+
const otherLocales = SUPPORTED_LOCALES.filter(
|
|
295
|
+
(candidateLocale) => candidateLocale !== locale && candidateLocale !== DEFAULT_LOCALE,
|
|
296
|
+
);
|
|
264
297
|
const values = [
|
|
265
|
-
{ value: row
|
|
298
|
+
{ value: getProperty(row, localizedKey(column, locale)), source: "direct" },
|
|
266
299
|
{ value: getNestedLocaleValue(row, column, locale), source: "nested" },
|
|
267
|
-
{ value: row
|
|
268
|
-
{ value: row
|
|
300
|
+
{ value: getProperty(row, column), source: "direct" },
|
|
301
|
+
{ value: getProperty(row, localizedKey(column, DEFAULT_LOCALE)), source: "direct" },
|
|
269
302
|
{ value: getNestedLocaleValue(row, column, DEFAULT_LOCALE), source: "nested" },
|
|
270
303
|
...otherLocales.flatMap((l) => [
|
|
271
|
-
{ value: row
|
|
304
|
+
{ value: getProperty(row, localizedKey(column, l)), source: "direct" },
|
|
272
305
|
{ value: getNestedLocaleValue(row, column, l), source: "nested" },
|
|
273
306
|
]),
|
|
274
307
|
];
|
|
275
308
|
|
|
276
309
|
for (const { value, source } of values) {
|
|
277
310
|
if (!isEmptyLocalizedColumnValue(value) && isLocalizedColumnValue(value)) {
|
|
311
|
+
// SAFETY: 값 가드가 선택한 컬럼의 문자열 또는 문자열 배열임을 확인했습니다.
|
|
278
312
|
return value as LocalizedColumnReturn<T, K>;
|
|
279
313
|
}
|
|
280
314
|
if (source === "direct" && !isEmptyLocalizedColumnValue(value) && isLocalizedColumnScalarValue(value)) {
|
|
315
|
+
// SAFETY: 직접 컬럼의 스칼라 값은 문자열로 변환해 지역화 반환 타입을 충족합니다.
|
|
281
316
|
return String(value) as LocalizedColumnReturn<T, K>;
|
|
282
317
|
}
|
|
283
318
|
}
|
|
@@ -292,14 +327,19 @@ export function localizedColumn<T extends Record<string, unknown>, K extends Loc
|
|
|
292
327
|
* @example
|
|
293
328
|
* SD.enumLabels("TagOrderBy")[key] // → 현재 locale의 라벨
|
|
294
329
|
*/
|
|
295
|
-
|
|
296
|
-
|
|
330
|
+
interface EnumLabels {
|
|
331
|
+
[key: string]: LocalizedString;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
SD.enumLabels = (enumName: string): EnumLabels => {
|
|
335
|
+
return new Proxy<EnumLabels>({}, {
|
|
297
336
|
get(_, key: string | symbol) {
|
|
298
|
-
if (
|
|
337
|
+
if (Object.prototype.toString.call(key) === "[object Symbol]") {
|
|
299
338
|
return undefined;
|
|
300
339
|
}
|
|
301
340
|
|
|
302
|
-
|
|
341
|
+
// SAFETY: 생성된 enum 이름과 값의 조합은 enum 사전 키 형식을 따릅니다.
|
|
342
|
+
const dictKey = \`enum.\${enumName}.\${String(key)}\` as DictKey;
|
|
303
343
|
return getDictValue(dictKey, getCurrentLocale());
|
|
304
344
|
}
|
|
305
345
|
});
|
|
@@ -318,16 +358,16 @@ SD.enumLabels = (enumName: string): Record<string, LocalizedString> => {
|
|
|
318
358
|
* react-components의 rc-keys를 추출합
|
|
319
359
|
* sonamu/src/dict/rc-keys.ts 파일의 소스 코드를 직접 읽어서 반환
|
|
320
360
|
*/
|
|
321
|
-
private extractRCKeysSourceCode()
|
|
361
|
+
private extractRCKeysSourceCode() {
|
|
322
362
|
try {
|
|
323
363
|
// rc-keys.ts 파일 경로
|
|
324
|
-
const
|
|
325
|
-
const
|
|
364
|
+
const currentFilename = fileURLToPath(import.meta.url);
|
|
365
|
+
const currentDirectory = path.dirname(currentFilename);
|
|
326
366
|
|
|
327
367
|
// dist에서 실행될 때는 src로 경로 변경
|
|
328
|
-
const basePath =
|
|
329
|
-
?
|
|
330
|
-
:
|
|
368
|
+
const basePath = currentDirectory.includes("/dist/")
|
|
369
|
+
? currentDirectory.replace("/dist/", "/src/")
|
|
370
|
+
: currentDirectory;
|
|
331
371
|
|
|
332
372
|
const rcKeysPath = path.join(basePath, "../../dict/rc-keys.ts");
|
|
333
373
|
|
|
@@ -11,6 +11,7 @@ import { Sonamu } from "../../api/sonamu";
|
|
|
11
11
|
import { EntityManager } from "../../entity/entity-manager";
|
|
12
12
|
import { type TemplateOptions } from "../../types/types";
|
|
13
13
|
import { ApiParamType } from "../../types/types";
|
|
14
|
+
import { isStringValue } from "../../utils/runtime-value";
|
|
14
15
|
import { assertDefined } from "../../utils/utils";
|
|
15
16
|
import { Template } from "../template";
|
|
16
17
|
import { BUILT_IN_TYPES, zodTypeToTsTypeDef } from "../zod-converter";
|
|
@@ -197,8 +198,7 @@ export function ${methodNameWebSocketCamelized}(
|
|
|
197
198
|
.map((param) => {
|
|
198
199
|
// primitive 타입인지 체크
|
|
199
200
|
const isPrimitive =
|
|
200
|
-
|
|
201
|
-
["string", "number", "boolean"].includes(param.type);
|
|
201
|
+
isStringValue(param.type) && ["string", "number", "boolean"].includes(param.type);
|
|
202
202
|
|
|
203
203
|
if (isPrimitive) {
|
|
204
204
|
// primitive: 직접 formData.append
|