sonamu 0.10.12 → 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 +131 -27
- 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 +12 -6
- 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 +3 -2
- package/dist/migration/migrator.d.ts.map +1 -1
- package/dist/migration/migrator.js +27 -21
- 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/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 +135 -128
- 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.map +1 -1
- package/dist/ui/migrations-api.js +17 -15
- package/dist/ui-web/assets/index-DV1AAq6W.js +178 -0
- package/dist/ui-web/index.html +1 -1
- 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 +5 -3
- 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 +153 -36
- 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 +68 -41
- package/src/migration/postgresql-schema-reader.ts +52 -47
- package/src/migration/slack-confirm.ts +17 -15
- 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 +727 -616
- package/src/ui/async-route.ts +4 -0
- package/src/ui/cdd-service.ts +35 -12
- package/src/ui/migrations-api.ts +63 -51
- 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-C0m1pk6K.js +0 -177
package/src/stream/ws.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { type EventEmitter } from "node:events";
|
|
2
3
|
import { hostname } from "node:os";
|
|
3
4
|
|
|
4
|
-
import { type WebSocket } from "ws";
|
|
5
|
+
import { type RawData, type WebSocket } from "ws";
|
|
5
6
|
import { z } from "zod";
|
|
6
7
|
|
|
8
|
+
import { runtimeTypeOf } from "../runtime-type";
|
|
9
|
+
import { isStringValue } from "../utils/runtime-value";
|
|
7
10
|
import { type WebSocketAudience } from "./ws-audience";
|
|
8
11
|
import { type WebSocketClusterBus } from "./ws-cluster-bus";
|
|
9
12
|
import { type WebSocketPresenceStore } from "./ws-presence-store";
|
|
@@ -46,7 +49,7 @@ const OUTBOUND_RETRY_DELAY_MS = 5;
|
|
|
46
49
|
// meta는 optional이므로 기존 `{event, data}` 메시지도 그대로 파싱됨 (backward-compatible)
|
|
47
50
|
const WebSocketEnvelopeSchema = z.object({
|
|
48
51
|
event: z.string(),
|
|
49
|
-
data: z.
|
|
52
|
+
data: z.json(),
|
|
50
53
|
meta: z
|
|
51
54
|
.object({
|
|
52
55
|
traceparent: z.string().optional(),
|
|
@@ -61,17 +64,25 @@ type MessageHandler<T> = (
|
|
|
61
64
|
) => void | Promise<void>;
|
|
62
65
|
type CloseHandler = () => void | Promise<void>;
|
|
63
66
|
|
|
64
|
-
export type WebSocketEventMap = Record<string,
|
|
67
|
+
export type WebSocketEventMap<EventPayload = never> = Record<string, EventPayload>;
|
|
68
|
+
export type WebSocketTransport = Pick<
|
|
69
|
+
WebSocket,
|
|
70
|
+
"bufferedAmount" | "close" | "ping" | "readyState" | "send" | "terminate"
|
|
71
|
+
> & {
|
|
72
|
+
off: (...args: Parameters<EventEmitter["off"]>) => void;
|
|
73
|
+
on: (...args: Parameters<EventEmitter["on"]>) => void;
|
|
74
|
+
};
|
|
65
75
|
|
|
66
|
-
type
|
|
76
|
+
type WebSocketEventFields = Record<string, z.ZodType>;
|
|
77
|
+
type InferWebSocketEventMap<TSchema extends WebSocketEventFields> = z.infer<z.ZodObject<TSchema>>;
|
|
67
78
|
|
|
68
|
-
export type WebSocketOutEvents<TOut extends
|
|
79
|
+
export type WebSocketOutEvents<TOut extends object = WebSocketEventMap> = TOut;
|
|
69
80
|
|
|
70
|
-
export type WebSocketInEvents<TIn extends
|
|
81
|
+
export type WebSocketInEvents<TIn extends object = WebSocketEventMap> = TIn;
|
|
71
82
|
|
|
72
83
|
export interface WebSocketConnection<
|
|
73
|
-
TOut extends
|
|
74
|
-
TIn extends
|
|
84
|
+
TOut extends object = WebSocketEventMap,
|
|
85
|
+
TIn extends object = WebSocketEventMap,
|
|
75
86
|
> extends ManagedWebSocketConnection {
|
|
76
87
|
transport: "ws";
|
|
77
88
|
onClose(callback: CloseHandler): void;
|
|
@@ -90,11 +101,14 @@ export interface WebSocketConnection<
|
|
|
90
101
|
clearUserId(): void;
|
|
91
102
|
}
|
|
92
103
|
|
|
93
|
-
export type AnyWebSocketConnection = WebSocketConnection<
|
|
104
|
+
export type AnyWebSocketConnection = WebSocketConnection<object, object>;
|
|
94
105
|
|
|
95
106
|
type ParsedEnvelope = z.infer<typeof WebSocketEnvelopeSchema>;
|
|
96
107
|
|
|
97
|
-
type WebSocketConnectionOptions<
|
|
108
|
+
type WebSocketConnectionOptions<
|
|
109
|
+
TOut extends WebSocketEventFields,
|
|
110
|
+
TIn extends WebSocketEventFields,
|
|
111
|
+
> = {
|
|
98
112
|
namespace?: string;
|
|
99
113
|
heartbeat?: number;
|
|
100
114
|
active?: boolean;
|
|
@@ -137,8 +151,11 @@ export class WebSocketRuntime {
|
|
|
137
151
|
this.registry = new WebSocketRegistry(registryOptions);
|
|
138
152
|
}
|
|
139
153
|
|
|
140
|
-
registerConnection<
|
|
141
|
-
|
|
154
|
+
registerConnection<
|
|
155
|
+
TOutSchema extends WebSocketEventFields,
|
|
156
|
+
TInSchema extends WebSocketEventFields,
|
|
157
|
+
>(
|
|
158
|
+
socket: WebSocketTransport,
|
|
142
159
|
options: Omit<
|
|
143
160
|
WebSocketConnectionOptions<TOutSchema, TInSchema>,
|
|
144
161
|
"registry" | "telemetryController"
|
|
@@ -155,19 +172,29 @@ export class WebSocketRuntime {
|
|
|
155
172
|
this.registry.activate(connectionId);
|
|
156
173
|
}
|
|
157
174
|
|
|
158
|
-
broadcast(event: string, data:
|
|
175
|
+
broadcast<Data>(event: string, data: Data, namespace?: string): void {
|
|
159
176
|
this.registry.broadcast(event, data, namespace);
|
|
160
177
|
}
|
|
161
178
|
|
|
162
|
-
publishToRoom(
|
|
179
|
+
publishToRoom<Data>(
|
|
180
|
+
roomId: WebSocketRoomId,
|
|
181
|
+
event: string,
|
|
182
|
+
data: Data,
|
|
183
|
+
namespace?: string,
|
|
184
|
+
): void {
|
|
163
185
|
this.registry.publishToRoom(roomId, event, data, namespace);
|
|
164
186
|
}
|
|
165
187
|
|
|
166
|
-
publishToUser(
|
|
188
|
+
publishToUser<Data>(
|
|
189
|
+
userId: WebSocketUserId,
|
|
190
|
+
event: string,
|
|
191
|
+
data: Data,
|
|
192
|
+
namespace?: string,
|
|
193
|
+
): void {
|
|
167
194
|
this.registry.publishToUser(userId, event, data, namespace);
|
|
168
195
|
}
|
|
169
196
|
|
|
170
|
-
publishToAudience(audience: WebSocketAudience, event: string, data:
|
|
197
|
+
publishToAudience<Data>(audience: WebSocketAudience, event: string, data: Data): void {
|
|
171
198
|
this.registry.publishToAudience(audience, event, data);
|
|
172
199
|
}
|
|
173
200
|
|
|
@@ -185,7 +212,10 @@ export function createWebSocketRuntime(options: WebSocketRuntimeOptions = {}): W
|
|
|
185
212
|
return new WebSocketRuntime(options);
|
|
186
213
|
}
|
|
187
214
|
|
|
188
|
-
class WebSocketConnectionImpl<
|
|
215
|
+
class WebSocketConnectionImpl<
|
|
216
|
+
TOutSchema extends WebSocketEventFields,
|
|
217
|
+
TInSchema extends WebSocketEventFields,
|
|
218
|
+
>
|
|
189
219
|
implements
|
|
190
220
|
WebSocketConnection<InferWebSocketEventMap<TOutSchema>, InferWebSocketEventMap<TInSchema>>,
|
|
191
221
|
TelemetryInspectableConnection,
|
|
@@ -212,10 +242,10 @@ class WebSocketConnectionImpl<TOutSchema extends z.ZodRawShape, TInSchema extend
|
|
|
212
242
|
private readonly connectionStartedAt = performance.now();
|
|
213
243
|
|
|
214
244
|
// connection 수명 동안 유지되는 식별자. setUserId/clearUserId로 업데이트되며 emit hot path에서 매번 registry lookup하지 않도록 캐시함
|
|
215
|
-
private
|
|
245
|
+
private currentUserId?: string;
|
|
216
246
|
|
|
217
247
|
get userId(): string | undefined {
|
|
218
|
-
return this.
|
|
248
|
+
return this.currentUserId;
|
|
219
249
|
}
|
|
220
250
|
|
|
221
251
|
private closedInternal = false;
|
|
@@ -226,7 +256,7 @@ class WebSocketConnectionImpl<TOutSchema extends z.ZodRawShape, TInSchema extend
|
|
|
226
256
|
private outboundFlushScheduled = false;
|
|
227
257
|
|
|
228
258
|
constructor(
|
|
229
|
-
private readonly socket:
|
|
259
|
+
private readonly socket: WebSocketTransport,
|
|
230
260
|
private readonly options: WebSocketConnectionOptions<TOutSchema, TInSchema>,
|
|
231
261
|
) {
|
|
232
262
|
this.namespace = options.namespace ?? "default";
|
|
@@ -235,8 +265,8 @@ class WebSocketConnectionImpl<TOutSchema extends z.ZodRawShape, TInSchema extend
|
|
|
235
265
|
this.connectionSpanId = options.spanId;
|
|
236
266
|
this.connectionParentSpanId = options.parentSpanId;
|
|
237
267
|
this.connectionSampled = options.sampled;
|
|
238
|
-
this.eventSchemasIn = options.inEvents
|
|
239
|
-
this.eventSchemasOut = options.outEvents
|
|
268
|
+
this.eventSchemasIn = options.inEvents["shape"];
|
|
269
|
+
this.eventSchemasOut = options.outEvents["shape"];
|
|
240
270
|
|
|
241
271
|
let resolveClosePromise!: () => void;
|
|
242
272
|
this.closePromise = new Promise<void>((resolve) => {
|
|
@@ -266,7 +296,9 @@ class WebSocketConnectionImpl<TOutSchema extends z.ZodRawShape, TInSchema extend
|
|
|
266
296
|
): void {
|
|
267
297
|
const eventKey = String(event);
|
|
268
298
|
const handlers = this.messageHandlers.get(eventKey) ?? [];
|
|
269
|
-
handlers.push(
|
|
299
|
+
handlers.push(
|
|
300
|
+
/* SAFETY: 등록된 WebSocket 이벤트 스키마가 이 값의 타입을 보장한다. */ handler as MessageHandler<unknown>,
|
|
301
|
+
);
|
|
270
302
|
this.messageHandlers.set(eventKey, handlers);
|
|
271
303
|
this.flushPendingMessages(eventKey);
|
|
272
304
|
}
|
|
@@ -278,7 +310,7 @@ class WebSocketConnectionImpl<TOutSchema extends z.ZodRawShape, TInSchema extend
|
|
|
278
310
|
this.publishValidated(String(event), data);
|
|
279
311
|
}
|
|
280
312
|
|
|
281
|
-
publishUntyped(event: string, data:
|
|
313
|
+
publishUntyped<Data>(event: string, data: Data): void {
|
|
282
314
|
this.publishValidated(event, data);
|
|
283
315
|
}
|
|
284
316
|
|
|
@@ -295,12 +327,12 @@ class WebSocketConnectionImpl<TOutSchema extends z.ZodRawShape, TInSchema extend
|
|
|
295
327
|
}
|
|
296
328
|
|
|
297
329
|
setUserId(userId: WebSocketUserId): void {
|
|
298
|
-
this.
|
|
330
|
+
this.currentUserId = String(userId);
|
|
299
331
|
this.options.registry.setUserId(this.id, userId);
|
|
300
332
|
}
|
|
301
333
|
|
|
302
334
|
clearUserId(): void {
|
|
303
|
-
this.
|
|
335
|
+
this.currentUserId = undefined;
|
|
304
336
|
this.options.registry.clearUserId(this.id);
|
|
305
337
|
}
|
|
306
338
|
|
|
@@ -327,7 +359,7 @@ class WebSocketConnectionImpl<TOutSchema extends z.ZodRawShape, TInSchema extend
|
|
|
327
359
|
return {
|
|
328
360
|
connectionId: this.id,
|
|
329
361
|
namespace: this.namespace,
|
|
330
|
-
userId: this.
|
|
362
|
+
userId: this.currentUserId,
|
|
331
363
|
traceId: this.connectionTraceId,
|
|
332
364
|
spanId: this.connectionSpanId,
|
|
333
365
|
parentSpanId: this.connectionParentSpanId,
|
|
@@ -368,7 +400,7 @@ class WebSocketConnectionImpl<TOutSchema extends z.ZodRawShape, TInSchema extend
|
|
|
368
400
|
}
|
|
369
401
|
|
|
370
402
|
// 인바운드 메시지를 순차 처리 큐에 올림. Sonamu envelope 검증 수행
|
|
371
|
-
private readonly handleMessage = (raw:
|
|
403
|
+
private readonly handleMessage = (raw: RawData) => {
|
|
372
404
|
this.enqueueMessageTask(async () => {
|
|
373
405
|
const text = normalizeMessage(raw);
|
|
374
406
|
const parsedEnvelope = safeParseEnvelope(text);
|
|
@@ -391,7 +423,7 @@ class WebSocketConnectionImpl<TOutSchema extends z.ZodRawShape, TInSchema extend
|
|
|
391
423
|
};
|
|
392
424
|
|
|
393
425
|
private readonly handleClose = (code?: number, reason?: Buffer | string) => {
|
|
394
|
-
const reasonText =
|
|
426
|
+
const reasonText = isStringValue(reason) ? reason : reason?.toString();
|
|
395
427
|
this.markClosed(code, reasonText);
|
|
396
428
|
};
|
|
397
429
|
|
|
@@ -487,7 +519,7 @@ class WebSocketConnectionImpl<TOutSchema extends z.ZodRawShape, TInSchema extend
|
|
|
487
519
|
const messageTraceFields = {
|
|
488
520
|
connectionId: this.id,
|
|
489
521
|
namespace: this.namespace,
|
|
490
|
-
userId: this.
|
|
522
|
+
userId: this.currentUserId,
|
|
491
523
|
traceId: traceCtx.traceId,
|
|
492
524
|
spanId: traceCtx.spanId,
|
|
493
525
|
parentSpanId: traceCtx.parentSpanId,
|
|
@@ -545,7 +577,7 @@ class WebSocketConnectionImpl<TOutSchema extends z.ZodRawShape, TInSchema extend
|
|
|
545
577
|
}
|
|
546
578
|
}
|
|
547
579
|
|
|
548
|
-
private publishValidated(event: string, data:
|
|
580
|
+
private publishValidated<Data>(event: string, data: Data): void {
|
|
549
581
|
const schema = this.eventSchemasOut[event];
|
|
550
582
|
if (!schema) {
|
|
551
583
|
this.options.telemetryController.emit({
|
|
@@ -584,7 +616,6 @@ class WebSocketConnectionImpl<TOutSchema extends z.ZodRawShape, TInSchema extend
|
|
|
584
616
|
data: parsed.data,
|
|
585
617
|
}),
|
|
586
618
|
event,
|
|
587
|
-
parsed.data,
|
|
588
619
|
);
|
|
589
620
|
}
|
|
590
621
|
|
|
@@ -705,8 +736,8 @@ class WebSocketConnectionImpl<TOutSchema extends z.ZodRawShape, TInSchema extend
|
|
|
705
736
|
}
|
|
706
737
|
|
|
707
738
|
// queue가 한계에 도달하면 1013으로 닫아 느린 소비자가 메모리를 끝없이 잡아먹지 못하게 함
|
|
708
|
-
//
|
|
709
|
-
private enqueueOutboundMessage(payload: string, event: string
|
|
739
|
+
// telemetry preview는 직렬화된 payload에서 복원해 전송 데이터와 같은 JSON 계약을 유지함
|
|
740
|
+
private enqueueOutboundMessage(payload: string, event: string): void {
|
|
710
741
|
if (this.pendingOutboundMessages.length >= MAX_PENDING_OUTBOUND_MESSAGES) {
|
|
711
742
|
this.options.telemetryController.emit({
|
|
712
743
|
name: "ws.backpressure.overflow",
|
|
@@ -723,7 +754,7 @@ class WebSocketConnectionImpl<TOutSchema extends z.ZodRawShape, TInSchema extend
|
|
|
723
754
|
level: "debug",
|
|
724
755
|
...this.telemetryFields(),
|
|
725
756
|
detail: { event },
|
|
726
|
-
payload: data,
|
|
757
|
+
payload: safeParseEnvelope(payload)?.data,
|
|
727
758
|
});
|
|
728
759
|
this.scheduleOutboundFlush();
|
|
729
760
|
}
|
|
@@ -818,7 +849,7 @@ class WebSocketConnectionImpl<TOutSchema extends z.ZodRawShape, TInSchema extend
|
|
|
818
849
|
status: "error",
|
|
819
850
|
...fields,
|
|
820
851
|
attributes: { event },
|
|
821
|
-
errorType: error instanceof Error ? error.name :
|
|
852
|
+
errorType: error instanceof Error ? error.name : runtimeTypeOf(error),
|
|
822
853
|
});
|
|
823
854
|
this.close(WS_CLOSE_CODE_INTERNAL_ERROR, "Outbound publish failed");
|
|
824
855
|
return;
|
|
@@ -838,8 +869,8 @@ class WebSocketConnectionImpl<TOutSchema extends z.ZodRawShape, TInSchema extend
|
|
|
838
869
|
}
|
|
839
870
|
}
|
|
840
871
|
|
|
841
|
-
function normalizeMessage(raw:
|
|
842
|
-
if (
|
|
872
|
+
function normalizeMessage(raw: RawData): string {
|
|
873
|
+
if (isStringValue(raw)) {
|
|
843
874
|
return raw;
|
|
844
875
|
}
|
|
845
876
|
|
|
@@ -862,7 +893,10 @@ function normalizeMessage(raw: unknown): string {
|
|
|
862
893
|
|
|
863
894
|
function safeParseEnvelope(raw: string): ParsedEnvelope | null {
|
|
864
895
|
try {
|
|
865
|
-
const parsed =
|
|
896
|
+
const parsed =
|
|
897
|
+
/* SAFETY: 등록된 WebSocket 이벤트 스키마가 이 값의 타입을 보장한다. */ JSON.parse(
|
|
898
|
+
raw,
|
|
899
|
+
) as unknown;
|
|
866
900
|
const validated = WebSocketEnvelopeSchema.safeParse(parsed);
|
|
867
901
|
return validated.success ? validated.data : null;
|
|
868
902
|
} catch {
|
|
@@ -6,6 +6,7 @@ import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
|
|
8
8
|
import { registeredApis } from "../../api/decorators";
|
|
9
|
+
import { type AbsolutePath } from "../../utils/path-utils";
|
|
9
10
|
import { readApisFromFile } from "../api-parser";
|
|
10
11
|
|
|
11
12
|
describe("readApisFromFile websocket type refs", () => {
|
|
@@ -47,7 +48,7 @@ describe("readApisFromFile websocket type refs", () => {
|
|
|
47
48
|
});
|
|
48
49
|
|
|
49
50
|
tempDir = await mkdtemp(path.join(tmpdir(), "sonamu-api-parser-"));
|
|
50
|
-
const filePath = path.join(tempDir, "chat.frame.ts")
|
|
51
|
+
const filePath: AbsolutePath = `/${path.relative("/", path.join(tempDir, "chat.frame.ts"))}`;
|
|
51
52
|
await writeFile(
|
|
52
53
|
filePath,
|
|
53
54
|
`
|
|
@@ -64,7 +65,7 @@ class ChatFrameClass {
|
|
|
64
65
|
`.trim(),
|
|
65
66
|
);
|
|
66
67
|
|
|
67
|
-
const [api] = await readApisFromFile(filePath
|
|
68
|
+
const [api] = await readApisFromFile(filePath);
|
|
68
69
|
|
|
69
70
|
expect(api?.websocketOptions?.outEventsTypeRef).toEqual({
|
|
70
71
|
t: "ref",
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { access, mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
6
|
+
|
|
7
|
+
import { type SonamuConfig } from "../../api/config";
|
|
8
|
+
import { Sonamu } from "../../api/sonamu";
|
|
9
|
+
import { type AbsolutePath } from "../../utils/path-utils";
|
|
10
|
+
import { Syncer, type SyncerDependencies } from "../syncer";
|
|
11
|
+
import { actionGenerateHttpValidators } from "../syncer-actions";
|
|
12
|
+
|
|
13
|
+
function toAbsolutePath(filePath: string): AbsolutePath {
|
|
14
|
+
if (!path.isAbsolute(filePath)) {
|
|
15
|
+
throw new Error(`절대 경로가 필요합니다: ${filePath}`);
|
|
16
|
+
}
|
|
17
|
+
// SAFETY: path.isAbsolute 검사로 AbsolutePath 계약을 확인했다.
|
|
18
|
+
return filePath as AbsolutePath;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function createDependencies() {
|
|
22
|
+
return {
|
|
23
|
+
actionCopySharedToTargetsIfNotExists: vi
|
|
24
|
+
.fn<SyncerDependencies["actionCopySharedToTargetsIfNotExists"]>()
|
|
25
|
+
.mockResolvedValue(undefined),
|
|
26
|
+
actionGenerateHttpValidators: vi.fn<SyncerDependencies["actionGenerateHttpValidators"]>(),
|
|
27
|
+
actionGenerateSsrEntryServerIfNotExists: vi
|
|
28
|
+
.fn<SyncerDependencies["actionGenerateSsrEntryServerIfNotExists"]>()
|
|
29
|
+
.mockResolvedValue([]),
|
|
30
|
+
findChangedFilesUsingChecksums: vi.fn<SyncerDependencies["findChangedFilesUsingChecksums"]>(),
|
|
31
|
+
renewChecksums: vi.fn<SyncerDependencies["renewChecksums"]>().mockResolvedValue(undefined),
|
|
32
|
+
} satisfies SyncerDependencies;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const testConfig = {
|
|
36
|
+
api: { dir: "api", route: { prefix: "/api" } },
|
|
37
|
+
i18n: { defaultLocale: "ko", supportedLocales: ["ko"] },
|
|
38
|
+
sync: { targets: [] },
|
|
39
|
+
database: {},
|
|
40
|
+
server: {
|
|
41
|
+
apiConfig: {
|
|
42
|
+
contextProvider: (defaultContext) => defaultContext,
|
|
43
|
+
guardHandler: () => undefined,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
} satisfies SonamuConfig;
|
|
47
|
+
|
|
48
|
+
describe("HTTP validator registry sync 정리", () => {
|
|
49
|
+
const tempRoots: string[] = [];
|
|
50
|
+
|
|
51
|
+
afterEach(async () => {
|
|
52
|
+
vi.restoreAllMocks();
|
|
53
|
+
await Promise.all(
|
|
54
|
+
tempRoots.splice(0).map((rootPath) => rm(rootPath, { recursive: true, force: true })),
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it.each([
|
|
59
|
+
{ label: "opt-out", value: false as const },
|
|
60
|
+
{ label: "JIT", value: { api: "jit" as const } },
|
|
61
|
+
])("$label 정책은 남아 있는 generated registry를 제거한다", async ({ value }) => {
|
|
62
|
+
const apiRootPath = await mkdtemp(path.join(os.tmpdir(), "sonamu-registry-sync-test-"));
|
|
63
|
+
tempRoots.push(apiRootPath);
|
|
64
|
+
const registryPath = path.join(apiRootPath, "src/application/sonamu.validators.generated.ts");
|
|
65
|
+
await mkdir(path.dirname(registryPath), { recursive: true });
|
|
66
|
+
await writeFile(registryPath, "export const validators = new Map();\n");
|
|
67
|
+
Sonamu.apiRootPath = toAbsolutePath(apiRootPath);
|
|
68
|
+
Sonamu.config = {
|
|
69
|
+
...testConfig,
|
|
70
|
+
api: { ...testConfig.api, dir: "." },
|
|
71
|
+
validation: { zodCompiler: value },
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
await actionGenerateHttpValidators();
|
|
75
|
+
|
|
76
|
+
await expect(access(registryPath)).rejects.toMatchObject({ code: "ENOENT" });
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it("registry-only drift를 경고로 넘기지 않고 즉시 재생성한다", async () => {
|
|
80
|
+
const appRootPath = await mkdtemp(path.join(os.tmpdir(), "sonamu-registry-drift-test-"));
|
|
81
|
+
tempRoots.push(appRootPath);
|
|
82
|
+
const apiRootPath = path.join(appRootPath, "api");
|
|
83
|
+
const registryPath = toAbsolutePath(
|
|
84
|
+
path.join(apiRootPath, "src/application/sonamu.validators.generated.ts"),
|
|
85
|
+
);
|
|
86
|
+
await mkdir(path.dirname(registryPath), { recursive: true });
|
|
87
|
+
await writeFile(registryPath, "// drifted registry\n");
|
|
88
|
+
Sonamu.apiRootPath = toAbsolutePath(apiRootPath);
|
|
89
|
+
Sonamu.config = {
|
|
90
|
+
...testConfig,
|
|
91
|
+
validation: { zodCompiler: { api: "aot" } },
|
|
92
|
+
};
|
|
93
|
+
const dependencies = createDependencies();
|
|
94
|
+
dependencies.actionGenerateHttpValidators.mockResolvedValue(registryPath);
|
|
95
|
+
dependencies.findChangedFilesUsingChecksums.mockResolvedValue([registryPath]);
|
|
96
|
+
vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
97
|
+
|
|
98
|
+
await new Syncer(dependencies).sync();
|
|
99
|
+
|
|
100
|
+
expect(dependencies.actionGenerateHttpValidators).toHaveBeenCalledTimes(1);
|
|
101
|
+
expect(dependencies.renewChecksums).toHaveBeenCalledTimes(1);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("삭제된 registry가 checksum 변경 목록에서 빠져도 다른 tracked 변경 처리 중 복구한다", async () => {
|
|
105
|
+
const appRootPath = await mkdtemp(path.join(os.tmpdir(), "sonamu-missing-registry-test-"));
|
|
106
|
+
tempRoots.push(appRootPath);
|
|
107
|
+
const apiRootPath = path.join(appRootPath, "api");
|
|
108
|
+
const registryPath = toAbsolutePath(
|
|
109
|
+
path.join(apiRootPath, "src/application/sonamu.validators.generated.ts"),
|
|
110
|
+
);
|
|
111
|
+
const unrelatedPath = toAbsolutePath(
|
|
112
|
+
path.join(apiRootPath, "src/application/queries.generated.ts"),
|
|
113
|
+
);
|
|
114
|
+
await mkdir(path.dirname(unrelatedPath), { recursive: true });
|
|
115
|
+
await writeFile(unrelatedPath, "// unrelated tracked change\n");
|
|
116
|
+
Sonamu.apiRootPath = toAbsolutePath(apiRootPath);
|
|
117
|
+
Sonamu.config = {
|
|
118
|
+
...testConfig,
|
|
119
|
+
validation: { zodCompiler: { api: "aot" } },
|
|
120
|
+
};
|
|
121
|
+
const order: string[] = [];
|
|
122
|
+
const dependencies = createDependencies();
|
|
123
|
+
dependencies.actionGenerateHttpValidators.mockImplementation(async () => {
|
|
124
|
+
order.push("registry");
|
|
125
|
+
return registryPath;
|
|
126
|
+
});
|
|
127
|
+
dependencies.findChangedFilesUsingChecksums.mockResolvedValue([unrelatedPath]);
|
|
128
|
+
dependencies.renewChecksums.mockImplementation(async () => {
|
|
129
|
+
order.push("checksum");
|
|
130
|
+
});
|
|
131
|
+
vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
132
|
+
|
|
133
|
+
await new Syncer(dependencies).sync();
|
|
134
|
+
|
|
135
|
+
expect(order).toEqual(["registry", "checksum"]);
|
|
136
|
+
});
|
|
137
|
+
});
|
package/src/syncer/api-parser.ts
CHANGED
|
@@ -77,7 +77,7 @@ export async function readApisFromFile(filePath: AbsolutePath): Promise<Extended
|
|
|
77
77
|
return resolveParamDec(
|
|
78
78
|
{
|
|
79
79
|
name: paramDec.name,
|
|
80
|
-
type: paramDec.type as ts.TypeNode,
|
|
80
|
+
type: /* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ paramDec.type as ts.TypeNode,
|
|
81
81
|
optional: paramDec.questionToken !== undefined || paramDec.initializer !== undefined,
|
|
82
82
|
defaultDef,
|
|
83
83
|
},
|
|
@@ -253,7 +253,10 @@ function resolveTypeNode(typeNode: ts.TypeNode): ApiParamType {
|
|
|
253
253
|
case ts.SyntaxKind.VoidKeyword:
|
|
254
254
|
return "void";
|
|
255
255
|
case ts.SyntaxKind.LiteralType: {
|
|
256
|
-
const literal =
|
|
256
|
+
const literal =
|
|
257
|
+
/* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ (
|
|
258
|
+
typeNode as ts.LiteralTypeNode
|
|
259
|
+
).literal;
|
|
257
260
|
if (ts.isStringLiteral(literal)) {
|
|
258
261
|
return {
|
|
259
262
|
t: "string-literal",
|
|
@@ -278,35 +281,46 @@ function resolveTypeNode(typeNode: ts.TypeNode): ApiParamType {
|
|
|
278
281
|
}
|
|
279
282
|
}
|
|
280
283
|
case ts.SyntaxKind.ArrayType: {
|
|
281
|
-
const arrNode =
|
|
284
|
+
const arrNode =
|
|
285
|
+
/* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ typeNode as ts.ArrayTypeNode;
|
|
282
286
|
return {
|
|
283
287
|
t: "array",
|
|
284
288
|
elementsType: resolveTypeNode(arrNode.elementType),
|
|
285
289
|
};
|
|
286
290
|
}
|
|
287
291
|
case ts.SyntaxKind.TypeLiteral: {
|
|
288
|
-
const literalNode =
|
|
292
|
+
const literalNode =
|
|
293
|
+
/* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ typeNode as ts.TypeLiteralNode;
|
|
289
294
|
return {
|
|
290
295
|
t: "object",
|
|
291
296
|
props: literalNode.members.map((member) => {
|
|
292
297
|
if (ts.isIndexSignatureDeclaration(member)) {
|
|
293
298
|
assert(member.parameters[0]);
|
|
294
299
|
const res = resolveParamDec({
|
|
295
|
-
name:
|
|
296
|
-
|
|
300
|
+
name: /* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ member
|
|
301
|
+
.parameters[0].name as ts.Identifier,
|
|
302
|
+
type: /* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ member
|
|
303
|
+
.parameters[0].type as ts.TypeNode,
|
|
297
304
|
});
|
|
298
305
|
|
|
299
306
|
return resolveParamDec({
|
|
300
|
-
name: {
|
|
307
|
+
name: /* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ {
|
|
301
308
|
escapedText: `[${res.name}${res.optional ? "?" : ""}: ${res.type}]`,
|
|
302
309
|
} as ts.Identifier,
|
|
303
310
|
type: member.type,
|
|
304
311
|
});
|
|
305
312
|
} else {
|
|
306
313
|
return resolveParamDec({
|
|
307
|
-
name:
|
|
308
|
-
|
|
309
|
-
|
|
314
|
+
name: /* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ /* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ (
|
|
315
|
+
member as ts.PropertySignature
|
|
316
|
+
).name as ts.Identifier,
|
|
317
|
+
type: /* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ /* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ (
|
|
318
|
+
member as ts.PropertySignature
|
|
319
|
+
).type as ts.TypeNode,
|
|
320
|
+
optional:
|
|
321
|
+
/* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ (
|
|
322
|
+
member as ts.PropertySignature
|
|
323
|
+
).questionToken !== undefined,
|
|
310
324
|
});
|
|
311
325
|
}
|
|
312
326
|
}),
|
|
@@ -315,26 +329,40 @@ function resolveTypeNode(typeNode: ts.TypeNode): ApiParamType {
|
|
|
315
329
|
case ts.SyntaxKind.TypeReference:
|
|
316
330
|
return {
|
|
317
331
|
t: "ref",
|
|
318
|
-
id:
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
332
|
+
id: /* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ /* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ (
|
|
333
|
+
(typeNode as ts.TypeReferenceNode).typeName as ts.Identifier
|
|
334
|
+
).escapedText.toString(),
|
|
335
|
+
args: /* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ (
|
|
336
|
+
typeNode as ts.TypeReferenceNode
|
|
337
|
+
).typeArguments?.map((typeArg) => resolveTypeNode(typeArg)),
|
|
322
338
|
};
|
|
323
339
|
case ts.SyntaxKind.UnionType:
|
|
324
340
|
return {
|
|
325
341
|
t: "union",
|
|
326
|
-
types:
|
|
342
|
+
types: /* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ (
|
|
343
|
+
typeNode as ts.UnionTypeNode
|
|
344
|
+
).types.map((type) => resolveTypeNode(type)),
|
|
327
345
|
};
|
|
328
346
|
case ts.SyntaxKind.IntersectionType:
|
|
329
347
|
return {
|
|
330
348
|
t: "intersection",
|
|
331
|
-
types:
|
|
349
|
+
types: /* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ (
|
|
350
|
+
typeNode as ts.IntersectionTypeNode
|
|
351
|
+
).types.map((type) => resolveTypeNode(type)),
|
|
332
352
|
};
|
|
333
353
|
case ts.SyntaxKind.IndexedAccessType:
|
|
334
354
|
return {
|
|
335
355
|
t: "indexed-access",
|
|
336
|
-
object: resolveTypeNode(
|
|
337
|
-
|
|
356
|
+
object: resolveTypeNode(
|
|
357
|
+
/* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ (
|
|
358
|
+
typeNode as ts.IndexedAccessTypeNode
|
|
359
|
+
).objectType,
|
|
360
|
+
),
|
|
361
|
+
index: resolveTypeNode(
|
|
362
|
+
/* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ (
|
|
363
|
+
typeNode as ts.IndexedAccessTypeNode
|
|
364
|
+
).indexType,
|
|
365
|
+
),
|
|
338
366
|
};
|
|
339
367
|
case ts.SyntaxKind.TupleType:
|
|
340
368
|
if (ts.isTupleTypeNode(typeNode)) {
|
|
@@ -347,18 +375,29 @@ function resolveTypeNode(typeNode: ts.TypeNode): ApiParamType {
|
|
|
347
375
|
case ts.SyntaxKind.ParenthesizedType:
|
|
348
376
|
// 괄호로 묶인 타입 (예: (A & B)[] 에서 (A & B))
|
|
349
377
|
// 내부 타입을 재귀적으로 resolve
|
|
350
|
-
return resolveTypeNode(
|
|
378
|
+
return resolveTypeNode(
|
|
379
|
+
/* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ (
|
|
380
|
+
typeNode as ts.ParenthesizedTypeNode
|
|
381
|
+
).type,
|
|
382
|
+
);
|
|
351
383
|
|
|
352
384
|
case ts.SyntaxKind.FunctionType:
|
|
353
385
|
return {
|
|
354
386
|
t: "function",
|
|
355
|
-
parameters:
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
387
|
+
parameters:
|
|
388
|
+
/* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ (
|
|
389
|
+
typeNode as ts.FunctionTypeNode
|
|
390
|
+
).parameters.map((param) => ({
|
|
391
|
+
name: param.name.getText(),
|
|
392
|
+
type: param.type ? resolveTypeNode(param.type) : "unknown",
|
|
393
|
+
optional: param.questionToken !== undefined,
|
|
394
|
+
defaultDef: undefined,
|
|
395
|
+
})),
|
|
396
|
+
returnType: resolveTypeNode(
|
|
397
|
+
/* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ (
|
|
398
|
+
typeNode as ts.FunctionTypeNode
|
|
399
|
+
).type,
|
|
400
|
+
),
|
|
362
401
|
};
|
|
363
402
|
case undefined:
|
|
364
403
|
throw new Error(`typeNode undefined`);
|
|
@@ -377,7 +416,8 @@ function resolveParamDec(
|
|
|
377
416
|
},
|
|
378
417
|
index: number = 0,
|
|
379
418
|
): ApiParam {
|
|
380
|
-
const name =
|
|
419
|
+
const name =
|
|
420
|
+
/* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ paramDec.name as ts.Identifier;
|
|
381
421
|
const type = resolveTypeNode(paramDec.type);
|
|
382
422
|
|
|
383
423
|
if (name === undefined) {
|