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
|
@@ -1,6 +1,23 @@
|
|
|
1
|
+
import { runtimeTypeOf } from "../runtime-type";
|
|
2
|
+
import { isFunctionValue, isObjectValue } from "../utils/runtime-value";
|
|
1
3
|
import { InMemoryEventStore, InMemoryMetricStore, InMemorySpanStore } from "./ws-telemetry-memory";
|
|
2
4
|
import { generateSpanId, generateTraceId, parseTraceParent } from "./ws-telemetry-trace";
|
|
3
5
|
|
|
6
|
+
export type WebSocketTelemetryValue =
|
|
7
|
+
| null
|
|
8
|
+
| undefined
|
|
9
|
+
| bigint
|
|
10
|
+
| boolean
|
|
11
|
+
| number
|
|
12
|
+
| string
|
|
13
|
+
| Date
|
|
14
|
+
| WebSocketTelemetryValue[]
|
|
15
|
+
| WebSocketTelemetryAttributes;
|
|
16
|
+
|
|
17
|
+
export interface WebSocketTelemetryAttributes {
|
|
18
|
+
[key: string]: WebSocketTelemetryValue;
|
|
19
|
+
}
|
|
20
|
+
|
|
4
21
|
// -- Record types (unchanged) --
|
|
5
22
|
|
|
6
23
|
export type WebSocketTelemetryRecordBase = {
|
|
@@ -24,7 +41,7 @@ export type WebSocketTelemetryEventRecord = WebSocketTelemetryRecordBase & {
|
|
|
24
41
|
name: string;
|
|
25
42
|
level: "debug" | "info" | "warn" | "error";
|
|
26
43
|
attributes?: Record<string, string | number | boolean>;
|
|
27
|
-
detail?:
|
|
44
|
+
detail?: WebSocketTelemetryAttributes;
|
|
28
45
|
payloadPreview?: string;
|
|
29
46
|
};
|
|
30
47
|
|
|
@@ -49,12 +66,12 @@ export type WebSocketTelemetrySpanRecord = WebSocketTelemetryRecordBase & {
|
|
|
49
66
|
events?: Array<{
|
|
50
67
|
name: string;
|
|
51
68
|
timestamp: number;
|
|
52
|
-
attributes?:
|
|
69
|
+
attributes?: WebSocketTelemetryAttributes;
|
|
53
70
|
}>;
|
|
54
71
|
links?: Array<{
|
|
55
72
|
traceId: string;
|
|
56
73
|
spanId: string;
|
|
57
|
-
attributes?:
|
|
74
|
+
attributes?: WebSocketTelemetryAttributes;
|
|
58
75
|
}>;
|
|
59
76
|
};
|
|
60
77
|
|
|
@@ -72,8 +89,8 @@ export type WebSocketTelemetryEventInput = {
|
|
|
72
89
|
connectionId?: string;
|
|
73
90
|
userId?: string;
|
|
74
91
|
attributes?: Record<string, string | number | boolean>;
|
|
75
|
-
detail?:
|
|
76
|
-
payload?:
|
|
92
|
+
detail?: WebSocketTelemetryAttributes;
|
|
93
|
+
payload?: WebSocketTelemetryValue;
|
|
77
94
|
traceId?: string;
|
|
78
95
|
spanId?: string;
|
|
79
96
|
parentSpanId?: string;
|
|
@@ -113,12 +130,12 @@ export type WebSocketSpanInput = {
|
|
|
113
130
|
events?: Array<{
|
|
114
131
|
name: string;
|
|
115
132
|
timestamp: number;
|
|
116
|
-
attributes?:
|
|
133
|
+
attributes?: WebSocketTelemetryAttributes;
|
|
117
134
|
}>;
|
|
118
135
|
links?: Array<{
|
|
119
136
|
traceId: string;
|
|
120
137
|
spanId: string;
|
|
121
|
-
attributes?:
|
|
138
|
+
attributes?: WebSocketTelemetryAttributes;
|
|
122
139
|
}>;
|
|
123
140
|
};
|
|
124
141
|
|
|
@@ -434,7 +451,7 @@ function isSensitiveKey(key: string): boolean {
|
|
|
434
451
|
return SENSITIVE_KEY_PATTERNS.some((pattern) => normalized.includes(pattern));
|
|
435
452
|
}
|
|
436
453
|
|
|
437
|
-
function redactValue(value:
|
|
454
|
+
function redactValue(value: WebSocketTelemetryValue, key?: string): WebSocketTelemetryValue {
|
|
438
455
|
if (key !== undefined && isSensitiveKey(key)) {
|
|
439
456
|
return REDACTED_VALUE;
|
|
440
457
|
}
|
|
@@ -447,8 +464,8 @@ function redactValue(value: unknown, key?: string): unknown {
|
|
|
447
464
|
return value;
|
|
448
465
|
}
|
|
449
466
|
|
|
450
|
-
if (value &&
|
|
451
|
-
const redacted:
|
|
467
|
+
if (value && isObjectValue(value)) {
|
|
468
|
+
const redacted: WebSocketTelemetryAttributes = {};
|
|
452
469
|
for (const [childKey, childValue] of Object.entries(value)) {
|
|
453
470
|
redacted[childKey] = redactValue(childValue, childKey);
|
|
454
471
|
}
|
|
@@ -464,6 +481,7 @@ function redactValue(value: unknown, key?: string): unknown {
|
|
|
464
481
|
*/
|
|
465
482
|
function defaultSensitiveKeyRedact(record: WebSocketTelemetryRecord): WebSocketTelemetryRecord {
|
|
466
483
|
if (record.type === "event") {
|
|
484
|
+
// SAFETY: redactor는 이벤트 레코드의 키 구조를 유지하고 값만 마스킹한다.
|
|
467
485
|
return {
|
|
468
486
|
...record,
|
|
469
487
|
attributes: record.attributes
|
|
@@ -477,6 +495,7 @@ function defaultSensitiveKeyRedact(record: WebSocketTelemetryRecord): WebSocketT
|
|
|
477
495
|
}
|
|
478
496
|
|
|
479
497
|
if (record.type === "metric") {
|
|
498
|
+
// SAFETY: redactor는 메트릭 레코드의 키 구조를 유지하고 값만 마스킹한다.
|
|
480
499
|
return {
|
|
481
500
|
...record,
|
|
482
501
|
tags: record.tags
|
|
@@ -486,6 +505,7 @@ function defaultSensitiveKeyRedact(record: WebSocketTelemetryRecord): WebSocketT
|
|
|
486
505
|
};
|
|
487
506
|
}
|
|
488
507
|
|
|
508
|
+
// SAFETY: redactor는 span과 하위 이벤트·링크의 키 구조를 유지하고 값만 마스킹한다.
|
|
489
509
|
return {
|
|
490
510
|
...record,
|
|
491
511
|
attributes: record.attributes
|
|
@@ -494,19 +514,19 @@ function defaultSensitiveKeyRedact(record: WebSocketTelemetryRecord): WebSocketT
|
|
|
494
514
|
events: record.events?.map((event) => ({
|
|
495
515
|
...event,
|
|
496
516
|
attributes: event.attributes
|
|
497
|
-
? (redactValue(event.attributes) as
|
|
517
|
+
? (redactValue(event.attributes) as WebSocketTelemetryAttributes)
|
|
498
518
|
: undefined,
|
|
499
519
|
})),
|
|
500
520
|
links: record.links?.map((link) => ({
|
|
501
521
|
...link,
|
|
502
522
|
attributes: link.attributes
|
|
503
|
-
? (redactValue(link.attributes) as
|
|
523
|
+
? (redactValue(link.attributes) as WebSocketTelemetryAttributes)
|
|
504
524
|
: undefined,
|
|
505
525
|
})),
|
|
506
526
|
};
|
|
507
527
|
}
|
|
508
528
|
|
|
509
|
-
function truncatePayloadPreview(payload:
|
|
529
|
+
function truncatePayloadPreview(payload: WebSocketTelemetryValue, maxBytes: number): string {
|
|
510
530
|
try {
|
|
511
531
|
const serialized = JSON.stringify(redactValue(payload));
|
|
512
532
|
if (Buffer.byteLength(serialized, "utf-8") <= maxBytes) {
|
|
@@ -536,8 +556,8 @@ function truncateUtf8String(value: string, maxBytes: number): string {
|
|
|
536
556
|
return result + suffix;
|
|
537
557
|
}
|
|
538
558
|
|
|
539
|
-
export function isPromiseLike(value:
|
|
540
|
-
return
|
|
559
|
+
export function isPromiseLike<Value>(value: Value): value is Value & Promise<void> {
|
|
560
|
+
return isObjectValue(value) && value !== null && "then" in value && "catch" in value;
|
|
541
561
|
}
|
|
542
562
|
|
|
543
563
|
// -- TokenBucket (unchanged) --
|
|
@@ -679,7 +699,7 @@ type ResolvedSpanPipelineOptions = {
|
|
|
679
699
|
type InternalEventReporter = (
|
|
680
700
|
name: string,
|
|
681
701
|
level: WebSocketTelemetryEventRecord["level"],
|
|
682
|
-
detail?:
|
|
702
|
+
detail?: WebSocketTelemetryAttributes,
|
|
683
703
|
) => void;
|
|
684
704
|
|
|
685
705
|
// -- TelemetryPipeline (abstract) --
|
|
@@ -695,7 +715,7 @@ abstract class TelemetryPipeline<
|
|
|
695
715
|
> {
|
|
696
716
|
abstract readonly signal: "event" | "metric" | "span";
|
|
697
717
|
protected readonly sinks: TSink[];
|
|
698
|
-
protected readonly
|
|
718
|
+
protected readonly telemetryStore: TStore;
|
|
699
719
|
protected readonly tokenBucket: TokenBucket;
|
|
700
720
|
protected readonly maxInFlightEmits: number;
|
|
701
721
|
protected readonly runtimeMetadata: RuntimeMetadata;
|
|
@@ -717,7 +737,7 @@ abstract class TelemetryPipeline<
|
|
|
717
737
|
runtimeMetadata: RuntimeMetadata,
|
|
718
738
|
) {
|
|
719
739
|
this.sinks = sinks;
|
|
720
|
-
this.
|
|
740
|
+
this.telemetryStore = store;
|
|
721
741
|
this.tokenBucket = new TokenBucket(maxRecordsPerSecond, maxRecordsPerSecond);
|
|
722
742
|
this.maxInFlightEmits = maxInFlightEmits;
|
|
723
743
|
this.sharedRedactor = sharedRedactor;
|
|
@@ -726,7 +746,7 @@ abstract class TelemetryPipeline<
|
|
|
726
746
|
}
|
|
727
747
|
|
|
728
748
|
get store(): TStore {
|
|
729
|
-
return this.
|
|
749
|
+
return this.telemetryStore;
|
|
730
750
|
}
|
|
731
751
|
|
|
732
752
|
setInternalEventReporter(reporter: InternalEventReporter): void {
|
|
@@ -772,7 +792,8 @@ abstract class TelemetryPipeline<
|
|
|
772
792
|
this.droppedCount += 1;
|
|
773
793
|
return;
|
|
774
794
|
}
|
|
775
|
-
prepared =
|
|
795
|
+
prepared =
|
|
796
|
+
/* SAFETY: 등록된 WebSocket 이벤트 스키마가 이 값의 타입을 보장한다. */ afterDefault as TRecord;
|
|
776
797
|
} catch {
|
|
777
798
|
this.droppedCount += 1;
|
|
778
799
|
return;
|
|
@@ -860,7 +881,7 @@ abstract class TelemetryPipeline<
|
|
|
860
881
|
}
|
|
861
882
|
|
|
862
883
|
// result.type === record.type === TRecord["type"]이므로 narrowed TRecord로 안전하게 좁힐 수 있다.
|
|
863
|
-
return result as TRecord;
|
|
884
|
+
return /* SAFETY: 등록된 WebSocket 이벤트 스키마가 이 값의 타입을 보장한다. */ result as TRecord;
|
|
864
885
|
}
|
|
865
886
|
|
|
866
887
|
protected dispatchToSinks(record: TRecord, selfObserveFailures = true): void {
|
|
@@ -885,9 +906,9 @@ abstract class TelemetryPipeline<
|
|
|
885
906
|
() => {
|
|
886
907
|
this.decrementInFlightEmit(sink);
|
|
887
908
|
},
|
|
888
|
-
(
|
|
909
|
+
(cause: unknown) => {
|
|
889
910
|
this.decrementInFlightEmit(sink);
|
|
890
|
-
this.observeSinkFailure("emit",
|
|
911
|
+
this.observeSinkFailure("emit", cause, selfObserveFailures);
|
|
891
912
|
},
|
|
892
913
|
);
|
|
893
914
|
}
|
|
@@ -906,9 +927,9 @@ abstract class TelemetryPipeline<
|
|
|
906
927
|
this.inFlightEmits.set(sink, current - 1);
|
|
907
928
|
}
|
|
908
929
|
|
|
909
|
-
private observeSinkFailure(
|
|
930
|
+
private observeSinkFailure<Value>(
|
|
910
931
|
phase: "emit" | "shutdown",
|
|
911
|
-
error:
|
|
932
|
+
error: Value,
|
|
912
933
|
selfObserveFailure: boolean,
|
|
913
934
|
): void {
|
|
914
935
|
this.sinkFailureCount += 1;
|
|
@@ -916,14 +937,14 @@ abstract class TelemetryPipeline<
|
|
|
916
937
|
this.dispatchInternalEvent("ws.telemetry.sink.failed", "warn", {
|
|
917
938
|
phase,
|
|
918
939
|
signal: this.signal,
|
|
919
|
-
errorType: error instanceof Error ? error.name :
|
|
940
|
+
errorType: error instanceof Error ? error.name : runtimeTypeOf(error),
|
|
920
941
|
});
|
|
921
942
|
}
|
|
922
943
|
|
|
923
944
|
protected dispatchInternalEvent(
|
|
924
945
|
name: string,
|
|
925
946
|
level: WebSocketTelemetryEventRecord["level"],
|
|
926
|
-
detail?:
|
|
947
|
+
detail?: WebSocketTelemetryAttributes,
|
|
927
948
|
): void {
|
|
928
949
|
if (this.internalEventReporter === undefined) return;
|
|
929
950
|
try {
|
|
@@ -953,8 +974,8 @@ abstract class TelemetryPipeline<
|
|
|
953
974
|
let timeout: ReturnType<typeof setTimeout> | null = null;
|
|
954
975
|
const shutdownPromise = result.then(
|
|
955
976
|
() => "completed" as const,
|
|
956
|
-
(
|
|
957
|
-
throw
|
|
977
|
+
(cause: unknown) => {
|
|
978
|
+
throw cause;
|
|
958
979
|
},
|
|
959
980
|
);
|
|
960
981
|
const timeoutPromise = new Promise<"timeout">((resolve) => {
|
|
@@ -1056,7 +1077,7 @@ class EventPipeline extends TelemetryPipeline<
|
|
|
1056
1077
|
dispatchInternalDiagnosticEvent(
|
|
1057
1078
|
name: string,
|
|
1058
1079
|
level: WebSocketTelemetryEventRecord["level"],
|
|
1059
|
-
detail?:
|
|
1080
|
+
detail?: WebSocketTelemetryAttributes,
|
|
1060
1081
|
): void {
|
|
1061
1082
|
const record: WebSocketTelemetryEventRecord = {
|
|
1062
1083
|
type: "event",
|
|
@@ -1172,7 +1193,7 @@ class MetricPipeline extends TelemetryPipeline<
|
|
|
1172
1193
|
|
|
1173
1194
|
if (
|
|
1174
1195
|
this.collectionInterval &&
|
|
1175
|
-
|
|
1196
|
+
isObjectValue(this.collectionInterval) &&
|
|
1176
1197
|
"unref" in this.collectionInterval
|
|
1177
1198
|
) {
|
|
1178
1199
|
this.collectionInterval.unref();
|
|
@@ -1595,28 +1616,30 @@ function buildController(
|
|
|
1595
1616
|
// 신호별 redactor / beforeRecord 해석.
|
|
1596
1617
|
// null이면 sharedRedactor를 undefined로 덮어써 step 2 자체를 skip한다.
|
|
1597
1618
|
const eventsSharedRedactor = eventsOpt.redactor === null ? undefined : defaults.redactor;
|
|
1598
|
-
const eventsSignalRedactor =
|
|
1599
|
-
typeof eventsOpt.redactor === "function" ? eventsOpt.redactor : undefined;
|
|
1619
|
+
const eventsSignalRedactor = isFunctionValue(eventsOpt.redactor) ? eventsOpt.redactor : undefined;
|
|
1600
1620
|
const eventsSharedBeforeRecord =
|
|
1601
1621
|
eventsOpt.beforeRecord === null ? undefined : defaults.beforeRecord;
|
|
1602
|
-
const eventsSignalBeforeRecord =
|
|
1603
|
-
|
|
1622
|
+
const eventsSignalBeforeRecord = isFunctionValue(eventsOpt.beforeRecord)
|
|
1623
|
+
? eventsOpt.beforeRecord
|
|
1624
|
+
: undefined;
|
|
1604
1625
|
|
|
1605
1626
|
const metricsSharedRedactor = metricsOpt.redactor === null ? undefined : defaults.redactor;
|
|
1606
|
-
const metricsSignalRedactor =
|
|
1607
|
-
|
|
1627
|
+
const metricsSignalRedactor = isFunctionValue(metricsOpt.redactor)
|
|
1628
|
+
? metricsOpt.redactor
|
|
1629
|
+
: undefined;
|
|
1608
1630
|
const metricsSharedBeforeRecord =
|
|
1609
1631
|
metricsOpt.beforeRecord === null ? undefined : defaults.beforeRecord;
|
|
1610
|
-
const metricsSignalBeforeRecord =
|
|
1611
|
-
|
|
1632
|
+
const metricsSignalBeforeRecord = isFunctionValue(metricsOpt.beforeRecord)
|
|
1633
|
+
? metricsOpt.beforeRecord
|
|
1634
|
+
: undefined;
|
|
1612
1635
|
|
|
1613
1636
|
const spansSharedRedactor = spansOpt.redactor === null ? undefined : defaults.redactor;
|
|
1614
|
-
const spansSignalRedactor =
|
|
1615
|
-
typeof spansOpt.redactor === "function" ? spansOpt.redactor : undefined;
|
|
1637
|
+
const spansSignalRedactor = isFunctionValue(spansOpt.redactor) ? spansOpt.redactor : undefined;
|
|
1616
1638
|
const spansSharedBeforeRecord =
|
|
1617
1639
|
spansOpt.beforeRecord === null ? undefined : defaults.beforeRecord;
|
|
1618
|
-
const spansSignalBeforeRecord =
|
|
1619
|
-
|
|
1640
|
+
const spansSignalBeforeRecord = isFunctionValue(spansOpt.beforeRecord)
|
|
1641
|
+
? spansOpt.beforeRecord
|
|
1642
|
+
: undefined;
|
|
1620
1643
|
|
|
1621
1644
|
// events
|
|
1622
1645
|
const eventSinks: WebSocketTelemetryEventSink[] = eventsOpt.sinks ? [...eventsOpt.sinks] : [];
|
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",
|