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
|
@@ -1,7 +1,32 @@
|
|
|
1
1
|
import SqlParser from "node-sql-parser";
|
|
2
2
|
|
|
3
|
+
import { isBooleanValue } from "../runtime-type";
|
|
4
|
+
import { isNumberValue, isObjectValue, isStringValue } from "../utils/runtime-value";
|
|
5
|
+
|
|
3
6
|
const INDEX_WHERE_SQL_PARSER = new SqlParser.Parser();
|
|
4
7
|
|
|
8
|
+
type SqlAstValue = null | undefined | boolean | number | string | SqlAstValue[] | SqlAstRecord;
|
|
9
|
+
interface SqlAstRecord {
|
|
10
|
+
[key: string]: SqlAstValue;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function parseSqlAstValue<Value>(value: Value): SqlAstValue {
|
|
14
|
+
if (value === null) return null;
|
|
15
|
+
if (value === undefined) return undefined;
|
|
16
|
+
if (isBooleanValue(value)) return value;
|
|
17
|
+
if (isNumberValue(value)) return value;
|
|
18
|
+
if (isStringValue(value)) return value;
|
|
19
|
+
if (Array.isArray(value)) {
|
|
20
|
+
return value.map(parseSqlAstValue);
|
|
21
|
+
}
|
|
22
|
+
if (isObjectValue(value)) {
|
|
23
|
+
return Object.fromEntries(
|
|
24
|
+
Object.entries(value).map(([key, child]) => [key, parseSqlAstValue(child)]),
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
throw new Error("지원하지 않는 SQL AST 값입니다");
|
|
28
|
+
}
|
|
29
|
+
|
|
5
30
|
/**
|
|
6
31
|
* Migration DDL 출력에 사용할 index predicate를 정리한다.
|
|
7
32
|
* 원본 SQL 표현은 보존하고, 빈 문자열과 전체를 감싼 괄호만 제거한다.
|
|
@@ -56,9 +81,11 @@ function removeOuterSqlParentheses(source: string): string {
|
|
|
56
81
|
function normalizeIndexWherePredicateByAst(where: string): string | undefined {
|
|
57
82
|
try {
|
|
58
83
|
// node-sql-parser는 raw predicate를 직접 파싱하지 않으므로 임시 SELECT WHERE로 감싼다.
|
|
59
|
-
const parsed =
|
|
60
|
-
|
|
61
|
-
|
|
84
|
+
const parsed = parseSqlAstValue(
|
|
85
|
+
INDEX_WHERE_SQL_PARSER.astify(
|
|
86
|
+
`SELECT * FROM __sonamu_index_predicate_source WHERE ${where}`,
|
|
87
|
+
{ database: "postgresql" },
|
|
88
|
+
),
|
|
62
89
|
);
|
|
63
90
|
const statement = Array.isArray(parsed) ? parsed[0] : parsed;
|
|
64
91
|
if (!isSqlAstRecord(statement)) {
|
|
@@ -71,7 +98,7 @@ function normalizeIndexWherePredicateByAst(where: string): string | undefined {
|
|
|
71
98
|
}
|
|
72
99
|
}
|
|
73
100
|
|
|
74
|
-
function serializeIndexWhereAst(node:
|
|
101
|
+
function serializeIndexWhereAst(node: SqlAstValue): string {
|
|
75
102
|
// PostgreSQL이 IN을 ANY(ARRAY[...])로 재작성하므로 membership은 먼저 특수 처리한다.
|
|
76
103
|
const membership = serializeSqlMembershipPredicate(node);
|
|
77
104
|
if (membership) {
|
|
@@ -139,7 +166,7 @@ function serializeIndexWhereAst(node: unknown): string {
|
|
|
139
166
|
}
|
|
140
167
|
}
|
|
141
168
|
|
|
142
|
-
function serializeSqlMembershipPredicate(node:
|
|
169
|
+
function serializeSqlMembershipPredicate(node: SqlAstValue): string | undefined {
|
|
143
170
|
if (!isSqlAstRecord(node) || getSqlAstString(node, "type") !== "binary_expr") {
|
|
144
171
|
return undefined;
|
|
145
172
|
}
|
|
@@ -166,7 +193,7 @@ function serializeSqlMembershipPredicate(node: unknown): string | undefined {
|
|
|
166
193
|
return `membership:${left}:in:[${values.join(",")}]`;
|
|
167
194
|
}
|
|
168
195
|
|
|
169
|
-
function serializeSqlMembershipValues(values:
|
|
196
|
+
function serializeSqlMembershipValues(values: SqlAstValue[] | undefined): string[] | undefined {
|
|
170
197
|
if (!values) {
|
|
171
198
|
return undefined;
|
|
172
199
|
}
|
|
@@ -176,7 +203,7 @@ function serializeSqlMembershipValues(values: unknown[] | undefined): string[] |
|
|
|
176
203
|
return [...new Set(serialized)].toSorted();
|
|
177
204
|
}
|
|
178
205
|
|
|
179
|
-
function getSqlAnyArrayElements(node:
|
|
206
|
+
function getSqlAnyArrayElements(node: SqlAstValue): SqlAstValue[] | undefined {
|
|
180
207
|
if (!isSqlAstRecord(node) || getSqlAstString(node, "type") !== "function") {
|
|
181
208
|
return undefined;
|
|
182
209
|
}
|
|
@@ -193,7 +220,7 @@ function getSqlAnyArrayElements(node: unknown): unknown[] | undefined {
|
|
|
193
220
|
return serializeSqlArrayElements(stripTextLikeSqlCast(arg));
|
|
194
221
|
}
|
|
195
222
|
|
|
196
|
-
function serializeSqlArrayElements(node:
|
|
223
|
+
function serializeSqlArrayElements(node: SqlAstValue): SqlAstValue[] {
|
|
197
224
|
if (!isSqlAstRecord(node)) {
|
|
198
225
|
return [];
|
|
199
226
|
}
|
|
@@ -206,7 +233,7 @@ function serializeSqlArrayElements(node: unknown): unknown[] {
|
|
|
206
233
|
return serializeSqlExprList(node);
|
|
207
234
|
}
|
|
208
235
|
|
|
209
|
-
function serializeSqlExprList(node:
|
|
236
|
+
function serializeSqlExprList(node: SqlAstValue): SqlAstValue[] {
|
|
210
237
|
if (!isSqlAstRecord(node)) {
|
|
211
238
|
return [];
|
|
212
239
|
}
|
|
@@ -219,7 +246,7 @@ function serializeSqlExprList(node: unknown): unknown[] {
|
|
|
219
246
|
return [node];
|
|
220
247
|
}
|
|
221
248
|
|
|
222
|
-
function stripTextLikeSqlCast(node:
|
|
249
|
+
function stripTextLikeSqlCast(node: SqlAstValue): SqlAstValue {
|
|
223
250
|
if (!isSqlAstRecord(node) || getSqlAstString(node, "type") !== "cast") {
|
|
224
251
|
return node;
|
|
225
252
|
}
|
|
@@ -233,13 +260,13 @@ function stripTextLikeSqlCast(node: unknown): unknown {
|
|
|
233
260
|
return stripTextLikeSqlCast(node.expr);
|
|
234
261
|
}
|
|
235
262
|
|
|
236
|
-
function isSqlStringLiteralLike(node:
|
|
263
|
+
function isSqlStringLiteralLike(node: SqlAstValue): boolean {
|
|
237
264
|
// 문자열 literal에 붙은 text 계열 cast는 membership 비교에서 의미가 같다.
|
|
238
265
|
const stripped = stripTextLikeSqlCast(node);
|
|
239
266
|
return isSqlAstRecord(stripped) && getSqlAstString(stripped, "type") === "single_quote_string";
|
|
240
267
|
}
|
|
241
268
|
|
|
242
|
-
function getSqlCastTargetType(node:
|
|
269
|
+
function getSqlCastTargetType(node: SqlAstRecord): string | undefined {
|
|
243
270
|
if (!Array.isArray(node.target)) {
|
|
244
271
|
return undefined;
|
|
245
272
|
}
|
|
@@ -270,24 +297,24 @@ function normalizeSqlDataType(type: string): string {
|
|
|
270
297
|
.replace(/^character varying$/, "varchar");
|
|
271
298
|
}
|
|
272
299
|
|
|
273
|
-
function serializeSqlColumnRef(node:
|
|
300
|
+
function serializeSqlColumnRef(node: SqlAstRecord): string {
|
|
274
301
|
const table = serializeSqlIdentifierNode(node.table);
|
|
275
302
|
const column = serializeSqlIdentifierNode(node.column);
|
|
276
303
|
return `column:${table ? `${table}.` : ""}${column}`;
|
|
277
304
|
}
|
|
278
305
|
|
|
279
|
-
function serializeSqlIdentifierNode(node:
|
|
280
|
-
if (
|
|
306
|
+
function serializeSqlIdentifierNode(node: SqlAstValue): string {
|
|
307
|
+
if (isStringValue(node)) {
|
|
281
308
|
return normalizeSqlIdentifier(node);
|
|
282
309
|
}
|
|
283
310
|
|
|
284
311
|
// quoted identifier와 function name의 AST shape 차이를 같은 identifier 문자열로 흡수한다.
|
|
285
312
|
if (isSqlAstRecord(node)) {
|
|
286
|
-
if (
|
|
313
|
+
if (isStringValue(node.value)) {
|
|
287
314
|
return normalizeSqlIdentifier(node.value);
|
|
288
315
|
}
|
|
289
316
|
|
|
290
|
-
if (isSqlAstRecord(node.expr) &&
|
|
317
|
+
if (isSqlAstRecord(node.expr) && isStringValue(node.expr.value)) {
|
|
291
318
|
return normalizeSqlIdentifier(node.expr.value);
|
|
292
319
|
}
|
|
293
320
|
}
|
|
@@ -295,9 +322,9 @@ function serializeSqlIdentifierNode(node: unknown): string {
|
|
|
295
322
|
return "";
|
|
296
323
|
}
|
|
297
324
|
|
|
298
|
-
function getSqlFunctionName(node:
|
|
325
|
+
function getSqlFunctionName(node: SqlAstRecord): string {
|
|
299
326
|
const name = node.name;
|
|
300
|
-
if (
|
|
327
|
+
if (isStringValue(name)) {
|
|
301
328
|
return normalizeSqlIdentifier(name);
|
|
302
329
|
}
|
|
303
330
|
|
|
@@ -324,7 +351,7 @@ function normalizeSqlOperator(operator: string | undefined): string {
|
|
|
324
351
|
return (operator ?? "").trim().toUpperCase().replace(/\s+/g, " ");
|
|
325
352
|
}
|
|
326
353
|
|
|
327
|
-
function serializeUnknownSqlAstRecord(node:
|
|
354
|
+
function serializeUnknownSqlAstRecord(node: SqlAstRecord): string {
|
|
328
355
|
// 아직 명시적으로 다루지 않는 AST 노드는 key 정렬로 최소한 안정적인 비교값을 만든다.
|
|
329
356
|
const entries = Object.entries(node)
|
|
330
357
|
.filter(([key]) => key !== "parentheses")
|
|
@@ -334,13 +361,13 @@ function serializeUnknownSqlAstRecord(node: Record<string, unknown>): string {
|
|
|
334
361
|
return `record:{${entries.join(",")}}`;
|
|
335
362
|
}
|
|
336
363
|
|
|
337
|
-
function isSqlAstRecord(value:
|
|
338
|
-
return
|
|
364
|
+
function isSqlAstRecord(value: SqlAstValue): value is SqlAstRecord {
|
|
365
|
+
return isObjectValue(value) && value !== null && !Array.isArray(value);
|
|
339
366
|
}
|
|
340
367
|
|
|
341
|
-
function getSqlAstString(node:
|
|
368
|
+
function getSqlAstString(node: SqlAstRecord, key: string): string | undefined {
|
|
342
369
|
const value = node[key];
|
|
343
|
-
return
|
|
370
|
+
return isStringValue(value) ? value : undefined;
|
|
344
371
|
}
|
|
345
372
|
|
|
346
373
|
function findMatchingParenthesisInSql(source: string, openIndex: number): number {
|
|
@@ -199,10 +199,14 @@ export function getMigrationSetFromEntity(entity: Entity): MigrationSetAndJoinTa
|
|
|
199
199
|
},
|
|
200
200
|
{
|
|
201
201
|
table: entity.table,
|
|
202
|
-
columns:
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
202
|
+
columns:
|
|
203
|
+
/* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as MigrationColumn[],
|
|
204
|
+
indexes:
|
|
205
|
+
/* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as MigrationIndex[],
|
|
206
|
+
foreigns:
|
|
207
|
+
/* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as MigrationForeign[],
|
|
208
|
+
joinTables:
|
|
209
|
+
/* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ [] as MigrationJoinTable[],
|
|
206
210
|
},
|
|
207
211
|
);
|
|
208
212
|
|
|
@@ -268,6 +272,8 @@ function resolveEntityPropTypeToMigrationColumnType(prop: EntityProp): Migration
|
|
|
268
272
|
return "tsvector";
|
|
269
273
|
default:
|
|
270
274
|
exhaustive(prop);
|
|
271
|
-
throw new Error(
|
|
275
|
+
throw new Error(
|
|
276
|
+
`Unknown entity prop type: ${/* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ (prop as { type: string }).type}`,
|
|
277
|
+
);
|
|
272
278
|
}
|
|
273
279
|
}
|
|
@@ -18,6 +18,7 @@ import { Naite } from "../naite/naite";
|
|
|
18
18
|
import { type GenMigrationCode, type MigrationSet } from "../types/types";
|
|
19
19
|
import { isLocal, isTest } from "../utils/controller";
|
|
20
20
|
import { exists } from "../utils/fs-utils";
|
|
21
|
+
import { isObjectValue, isStringValue } from "../utils/runtime-value";
|
|
21
22
|
import { generateAlterCode, generateCreateCode } from "./code-generation";
|
|
22
23
|
import { getMigrationSetFromEntity } from "./migration-set";
|
|
23
24
|
import { PostgreSQLSchemaReader } from "./postgresql-schema-reader";
|
|
@@ -40,12 +41,16 @@ export type MigrationResult = {
|
|
|
40
41
|
applied: string[];
|
|
41
42
|
}[];
|
|
42
43
|
|
|
44
|
+
function padDatePart(number: number, size: number = 2): string {
|
|
45
|
+
return number.toString().padStart(size, "0");
|
|
46
|
+
}
|
|
47
|
+
|
|
43
48
|
export class MigrationTargetExecutionError extends Error {
|
|
44
49
|
constructor(
|
|
45
50
|
public readonly connKey: MigrationTarget | "shadow",
|
|
46
|
-
|
|
51
|
+
cause: unknown,
|
|
47
52
|
) {
|
|
48
|
-
super(
|
|
53
|
+
super(cause instanceof Error ? cause.message : String(cause));
|
|
49
54
|
this.name = "MigrationTargetExecutionError";
|
|
50
55
|
}
|
|
51
56
|
}
|
|
@@ -82,23 +87,29 @@ function withTimeout<T>(promise: Promise<T>, ms: number, onTimeout: () => Error)
|
|
|
82
87
|
* CLI 리팩토링 시점에서 제거해주셔도 무방합니다.
|
|
83
88
|
*/
|
|
84
89
|
export class Migrator {
|
|
85
|
-
private isMissingMigrationTableError(error:
|
|
86
|
-
if (
|
|
90
|
+
private isMissingMigrationTableError<Value>(error: Value): boolean {
|
|
91
|
+
if (!isObjectValue(error) || error === null) {
|
|
87
92
|
return false;
|
|
88
93
|
}
|
|
89
94
|
|
|
90
|
-
const maybePostgresError =
|
|
95
|
+
const maybePostgresError =
|
|
96
|
+
/* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ error as {
|
|
97
|
+
code?: unknown;
|
|
98
|
+
message?: unknown;
|
|
99
|
+
};
|
|
91
100
|
return (
|
|
92
101
|
maybePostgresError.code === "42P01" &&
|
|
93
|
-
|
|
102
|
+
isStringValue(maybePostgresError.message) &&
|
|
94
103
|
maybePostgresError.message.includes("knex_migrations")
|
|
95
104
|
);
|
|
96
105
|
}
|
|
97
106
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
107
|
+
/** 현재 실행 환경에서 허용된 마이그레이션 대상 키를 반환합니다. */
|
|
108
|
+
getMigrationTargetKeys(): MigrationTarget[] {
|
|
109
|
+
const connKeys =
|
|
110
|
+
/* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ Object.keys(
|
|
111
|
+
Sonamu.dbConfig,
|
|
112
|
+
).filter((key) => !key.endsWith("_readonly")) as (keyof SonamuDBConfig)[];
|
|
102
113
|
|
|
103
114
|
if (isLocal()) {
|
|
104
115
|
return connKeys;
|
|
@@ -146,16 +157,20 @@ export class Migrator {
|
|
|
146
157
|
return results;
|
|
147
158
|
}
|
|
148
159
|
|
|
149
|
-
private migrationName(migration:
|
|
150
|
-
if (
|
|
160
|
+
private migrationName<Value>(migration: Value): string {
|
|
161
|
+
if (isStringValue(migration)) {
|
|
151
162
|
return path.basename(migration);
|
|
152
163
|
}
|
|
153
|
-
if (
|
|
154
|
-
const candidate =
|
|
155
|
-
|
|
164
|
+
if (isObjectValue(migration) && migration !== null) {
|
|
165
|
+
const candidate =
|
|
166
|
+
/* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ migration as {
|
|
167
|
+
file?: unknown;
|
|
168
|
+
name?: unknown;
|
|
169
|
+
};
|
|
170
|
+
if (isStringValue(candidate.file)) {
|
|
156
171
|
return path.basename(candidate.file);
|
|
157
172
|
}
|
|
158
|
-
if (
|
|
173
|
+
if (isStringValue(candidate.name)) {
|
|
159
174
|
return path.basename(candidate.name);
|
|
160
175
|
}
|
|
161
176
|
}
|
|
@@ -177,7 +192,7 @@ export class Migrator {
|
|
|
177
192
|
options?: MigrationRunOptions,
|
|
178
193
|
): Knex.MigratorConfigWithLifecycleHooks {
|
|
179
194
|
let files: string[] = [];
|
|
180
|
-
const emitFile = (type: "file-start" | "file-executed", migration:
|
|
195
|
+
const emitFile = <Value>(type: "file-start" | "file-executed", migration: Value) => {
|
|
181
196
|
const file = this.migrationName(migration);
|
|
182
197
|
const index = Math.max(files.indexOf(file), 0);
|
|
183
198
|
this.emitProgress(options, {
|
|
@@ -221,7 +236,10 @@ export class Migrator {
|
|
|
221
236
|
getConnections(): MigrationConnectionMeta[] {
|
|
222
237
|
const slackConfirm = new SlackConfirm();
|
|
223
238
|
return this.getMigrationTargetKeys().map((connKey) => {
|
|
224
|
-
const connection =
|
|
239
|
+
const connection =
|
|
240
|
+
/* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ Sonamu.dbConfig[
|
|
241
|
+
connKey
|
|
242
|
+
].connection as Knex.PgConnectionConfig;
|
|
225
243
|
const host = connection.host ?? "localhost";
|
|
226
244
|
return {
|
|
227
245
|
connKey,
|
|
@@ -272,11 +290,13 @@ export class Migrator {
|
|
|
272
290
|
const startedAt = performance.now();
|
|
273
291
|
const codes = await this.getMigrationCodes();
|
|
274
292
|
const knexOptions = Sonamu.dbConfig[connKey];
|
|
275
|
-
const connection =
|
|
293
|
+
const connection =
|
|
294
|
+
/* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ knexOptions.connection as Knex.PgConnectionConfig;
|
|
295
|
+
// SAFETY: Knex가 제공한 PostgreSQL 연결 구성을 복사해 timeout 필드만 덮어쓴다.
|
|
276
296
|
const tConn = createKnexInstance({
|
|
277
297
|
...knexOptions,
|
|
278
298
|
connection: {
|
|
279
|
-
...
|
|
299
|
+
...connection,
|
|
280
300
|
connectionTimeoutMillis: MIGRATION_CONN_TIMEOUT_MS,
|
|
281
301
|
},
|
|
282
302
|
pool: {
|
|
@@ -306,32 +326,33 @@ export class Migrator {
|
|
|
306
326
|
const pending: string[] = await tConn.migrate.list().then(
|
|
307
327
|
([, files]: [unknown[], { file: string }[]]) =>
|
|
308
328
|
files.map(({ file }) => file.replace(/\.ts$/, "")),
|
|
309
|
-
(
|
|
310
|
-
if (this.isMissingMigrationTableError(
|
|
329
|
+
(cause: unknown) => {
|
|
330
|
+
if (this.isMissingMigrationTableError(cause)) {
|
|
311
331
|
return codes.map(({ name }) => name);
|
|
312
332
|
}
|
|
313
|
-
error ??=
|
|
333
|
+
error ??= cause instanceof Error ? cause.message : String(cause);
|
|
314
334
|
return [];
|
|
315
335
|
},
|
|
316
336
|
);
|
|
317
337
|
const currentVersion: string | "none" | "error" = await tConn.migrate
|
|
318
338
|
.currentVersion()
|
|
319
|
-
.catch((
|
|
320
|
-
if (this.isMissingMigrationTableError(
|
|
339
|
+
.catch((cause: unknown) => {
|
|
340
|
+
if (this.isMissingMigrationTableError(cause)) {
|
|
321
341
|
return "none" as const;
|
|
322
342
|
}
|
|
323
|
-
error ??=
|
|
343
|
+
error ??= cause instanceof Error ? cause.message : String(cause);
|
|
324
344
|
return "error" as const;
|
|
325
345
|
});
|
|
326
346
|
Naite.t("migrator:getStatus:status", status);
|
|
327
|
-
|
|
347
|
+
const connectionStatus: MigrationConnectionStatus = {
|
|
328
348
|
connKey,
|
|
329
349
|
currentVersion,
|
|
330
350
|
status,
|
|
331
351
|
pending,
|
|
332
352
|
latencyMs: performance.now() - startedAt,
|
|
333
|
-
...(error === undefined ? {} : { error }),
|
|
334
353
|
};
|
|
354
|
+
if (error !== undefined) connectionStatus.error = error;
|
|
355
|
+
return connectionStatus;
|
|
335
356
|
} catch (caught) {
|
|
336
357
|
const error = caught instanceof Error ? caught.message : String(caught);
|
|
337
358
|
console.warn(
|
|
@@ -397,12 +418,15 @@ export class Migrator {
|
|
|
397
418
|
const conns = connections.map((connection, index) => {
|
|
398
419
|
const status = connectionStatuses[index];
|
|
399
420
|
assert(status !== undefined);
|
|
400
|
-
const configured =
|
|
421
|
+
const configured =
|
|
422
|
+
/* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ Sonamu.dbConfig[
|
|
423
|
+
connection.connKey
|
|
424
|
+
].connection as Knex.PgConnectionConfig;
|
|
401
425
|
return {
|
|
402
426
|
name: connection.name,
|
|
403
427
|
connKey: connection.connKey,
|
|
404
428
|
connString:
|
|
405
|
-
`pg://${configured.user ?? ""}@${configured.host}:${configured.port}/${configured.database}` as ConnString,
|
|
429
|
+
/* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ `pg://${configured.user ?? ""}@${configured.host}:${configured.port}/${configured.database}` as ConnString,
|
|
406
430
|
currentVersion: status.currentVersion,
|
|
407
431
|
status: status.status,
|
|
408
432
|
pending: status.pending,
|
|
@@ -484,10 +508,12 @@ export class Migrator {
|
|
|
484
508
|
options: Sonamu.dbConfig[target],
|
|
485
509
|
}))
|
|
486
510
|
.filter((c) => c.options !== undefined),
|
|
487
|
-
({ options }) =>
|
|
488
|
-
`${(
|
|
489
|
-
|
|
490
|
-
|
|
511
|
+
({ options: dbOptions }) =>
|
|
512
|
+
`${/* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ (dbOptions.connection as Knex.PgConnectionConfig).host}:${
|
|
513
|
+
/* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ (
|
|
514
|
+
dbOptions.connection as Knex.PgConnectionConfig
|
|
515
|
+
).port ?? 5432
|
|
516
|
+
}/${/* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ (dbOptions.connection as Knex.PgConnectionConfig).database}`,
|
|
491
517
|
);
|
|
492
518
|
|
|
493
519
|
// get connections
|
|
@@ -515,14 +541,13 @@ export class Migrator {
|
|
|
515
541
|
|
|
516
542
|
private genDateTag(index: number, baseDate: Date = new Date()): string {
|
|
517
543
|
const date = new Date(baseDate.getTime() + index * 1000);
|
|
518
|
-
const pad = (num: number, size: number = 2) => num.toString().padStart(size, "0");
|
|
519
544
|
return (
|
|
520
545
|
date.getFullYear().toString() +
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
546
|
+
padDatePart(date.getMonth() + 1) +
|
|
547
|
+
padDatePart(date.getDate()) +
|
|
548
|
+
padDatePart(date.getHours()) +
|
|
549
|
+
padDatePart(date.getMinutes()) +
|
|
550
|
+
padDatePart(date.getSeconds())
|
|
526
551
|
);
|
|
527
552
|
}
|
|
528
553
|
|
|
@@ -635,7 +660,9 @@ export class Migrator {
|
|
|
635
660
|
* @category 분리형 마이그레이션 API
|
|
636
661
|
*/
|
|
637
662
|
async runShadowTest(options?: MigrationRunOptions): Promise<MigrationResult> {
|
|
638
|
-
const baseTestConn =
|
|
663
|
+
const baseTestConn =
|
|
664
|
+
/* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ Sonamu.dbConfig
|
|
665
|
+
.test.connection as Knex.PgConnectionConfig;
|
|
639
666
|
const workerId = process.env.SONAMU_WORKER_DB === "true" ? process.env.VITEST_POOL_ID : null;
|
|
640
667
|
const templateDatabase =
|
|
641
668
|
workerId !== null ? `${baseTestConn.database}_${workerId ?? "1"}` : baseTestConn.database;
|
|
@@ -164,7 +164,8 @@ class PostgreSQLSchemaReaderClass {
|
|
|
164
164
|
);
|
|
165
165
|
|
|
166
166
|
// indexes 처리
|
|
167
|
-
const indexes: MigrationIndex[] =
|
|
167
|
+
const indexes: MigrationIndex[] = [];
|
|
168
|
+
for (const indexName of Object.keys(dbIndexesGroup)) {
|
|
168
169
|
const currentIndexes = dbIndexesGroup[indexName]?.toSorted(
|
|
169
170
|
(left, right) => left.column_order - right.column_order,
|
|
170
171
|
);
|
|
@@ -180,34 +181,42 @@ class PostgreSQLSchemaReaderClass {
|
|
|
180
181
|
parsedIndexDefinition.accessMethod ?? firstIndex.index_type,
|
|
181
182
|
);
|
|
182
183
|
|
|
183
|
-
|
|
184
|
+
const indexColumns: MigrationIndex["columns"] = [];
|
|
185
|
+
for (const currentIndex of currentIndexes) {
|
|
186
|
+
const opclass = this.extractIndexColumnOpclass(
|
|
187
|
+
parsedIndexDefinition.columnDefinitions[currentIndex.column_order - 1],
|
|
188
|
+
);
|
|
189
|
+
const column: MigrationIndex["columns"][number] = {
|
|
190
|
+
name: currentIndex.column_name,
|
|
191
|
+
};
|
|
192
|
+
if (opclass) {
|
|
193
|
+
Object.assign(column, { opclass });
|
|
194
|
+
}
|
|
195
|
+
switch (using) {
|
|
196
|
+
case "btree":
|
|
197
|
+
Object.assign(column, {
|
|
198
|
+
sortOrder: currentIndex.sort_order,
|
|
199
|
+
nullsFirst: currentIndex.nulls_first,
|
|
200
|
+
});
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
indexColumns.push(column);
|
|
204
|
+
}
|
|
205
|
+
const index: MigrationIndex = {
|
|
184
206
|
type: restoredIndexType,
|
|
185
207
|
name: indexName,
|
|
186
|
-
columns:
|
|
187
|
-
name: idx.column_name,
|
|
188
|
-
...(this.extractIndexColumnOpclass(
|
|
189
|
-
parsedIndexDefinition.columnDefinitions[idx.column_order - 1],
|
|
190
|
-
)
|
|
191
|
-
? {
|
|
192
|
-
opclass: this.extractIndexColumnOpclass(
|
|
193
|
-
parsedIndexDefinition.columnDefinitions[idx.column_order - 1],
|
|
194
|
-
),
|
|
195
|
-
}
|
|
196
|
-
: {}),
|
|
197
|
-
...(using === "btree"
|
|
198
|
-
? {
|
|
199
|
-
sortOrder: idx.sort_order,
|
|
200
|
-
nullsFirst: idx.nulls_first,
|
|
201
|
-
}
|
|
202
|
-
: {}),
|
|
203
|
-
})),
|
|
204
|
-
|
|
208
|
+
columns: indexColumns,
|
|
205
209
|
nullsNotDistinct: firstIndex.nulls_not_distinct,
|
|
206
|
-
...(firstIndex.predicate ? { where: firstIndex.predicate } : {}),
|
|
207
|
-
...(using ? { using } : {}),
|
|
208
210
|
...this.parseVectorIndexOptions(restoredIndexType, parsedIndexDefinition.withOptions),
|
|
209
211
|
};
|
|
210
|
-
|
|
212
|
+
if (firstIndex.predicate) {
|
|
213
|
+
index.where = firstIndex.predicate;
|
|
214
|
+
}
|
|
215
|
+
if (using) {
|
|
216
|
+
index.using = using;
|
|
217
|
+
}
|
|
218
|
+
indexes.push(index);
|
|
219
|
+
}
|
|
211
220
|
|
|
212
221
|
// foreigns 처리
|
|
213
222
|
const foreigns: MigrationForeign[] = dbForeigns.map((dbForeign) => {
|
|
@@ -231,14 +240,14 @@ class PostgreSQLSchemaReaderClass {
|
|
|
231
240
|
* PostgreSQL의 constraint action을 Knex 형식으로 변환
|
|
232
241
|
*/
|
|
233
242
|
private mapConstraintAction(action: string): RelationOn {
|
|
234
|
-
const actionMap
|
|
235
|
-
"NO ACTION"
|
|
236
|
-
RESTRICT
|
|
237
|
-
CASCADE
|
|
238
|
-
"SET NULL"
|
|
239
|
-
"SET DEFAULT"
|
|
240
|
-
|
|
241
|
-
return actionMap
|
|
243
|
+
const actionMap = new Map<string, RelationOn>([
|
|
244
|
+
["NO ACTION", "NO ACTION"],
|
|
245
|
+
["RESTRICT", "RESTRICT"],
|
|
246
|
+
["CASCADE", "CASCADE"],
|
|
247
|
+
["SET NULL", "SET NULL"],
|
|
248
|
+
["SET DEFAULT", "SET DEFAULT"],
|
|
249
|
+
]);
|
|
250
|
+
return actionMap.get(action) ?? "NO ACTION";
|
|
242
251
|
}
|
|
243
252
|
|
|
244
253
|
/**
|
|
@@ -277,7 +286,9 @@ class PostgreSQLSchemaReaderClass {
|
|
|
277
286
|
AND c.table_schema = 'public'
|
|
278
287
|
ORDER BY c.ordinal_position
|
|
279
288
|
`;
|
|
280
|
-
const columns =
|
|
289
|
+
const columns = /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ (
|
|
290
|
+
await compareDB.raw(columnsQuery, [tableName])
|
|
291
|
+
).rows as PgColumn[];
|
|
281
292
|
if (columns.length === 0) {
|
|
282
293
|
throw new Error(`Table not found: ${tableName}`);
|
|
283
294
|
}
|
|
@@ -398,7 +409,7 @@ class PostgreSQLSchemaReaderClass {
|
|
|
398
409
|
return undefined;
|
|
399
410
|
}
|
|
400
411
|
|
|
401
|
-
return normalized as MigrationIndex["using"];
|
|
412
|
+
return /* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ normalized as MigrationIndex["using"];
|
|
402
413
|
}
|
|
403
414
|
|
|
404
415
|
private parseVectorIndexOptions(
|
|
@@ -406,14 +417,12 @@ class PostgreSQLSchemaReaderClass {
|
|
|
406
417
|
withOptions: Record<string, string>,
|
|
407
418
|
): Pick<MigrationIndex, "m" | "efConstruction" | "lists"> {
|
|
408
419
|
if (type === "hnsw") {
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
: {}),
|
|
416
|
-
};
|
|
420
|
+
const options: Pick<MigrationIndex, "m" | "efConstruction"> = {};
|
|
421
|
+
const m = this.parseIntegerOption(withOptions.m);
|
|
422
|
+
const efConstruction = this.parseIntegerOption(withOptions.ef_construction);
|
|
423
|
+
if (m !== undefined) options.m = m;
|
|
424
|
+
if (efConstruction !== undefined) options.efConstruction = efConstruction;
|
|
425
|
+
return options;
|
|
417
426
|
}
|
|
418
427
|
|
|
419
428
|
if (type === "ivfflat") {
|
|
@@ -456,11 +465,7 @@ class PostgreSQLSchemaReaderClass {
|
|
|
456
465
|
return tokens.at(-1);
|
|
457
466
|
}
|
|
458
467
|
|
|
459
|
-
private parseIndexDefinition(indexDefinition: string)
|
|
460
|
-
accessMethod?: string;
|
|
461
|
-
columnDefinitions: string[];
|
|
462
|
-
withOptions: Record<string, string>;
|
|
463
|
-
} {
|
|
468
|
+
private parseIndexDefinition(indexDefinition: string) {
|
|
464
469
|
const accessMethod = indexDefinition.match(/\bUSING\s+([a-z_][\w]*)/i)?.[1]?.toLowerCase();
|
|
465
470
|
const usingMatchIndex = indexDefinition.search(/\bUSING\b/i);
|
|
466
471
|
const columnsStart = usingMatchIndex >= 0 ? indexDefinition.indexOf("(", usingMatchIndex) : -1;
|
|
@@ -138,12 +138,13 @@ export class SlackConfirm {
|
|
|
138
138
|
throw new Error(`Slack API HTTP error: ${response.status}`);
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
-
const data =
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
141
|
+
const data =
|
|
142
|
+
/* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ (await response.json()) as {
|
|
143
|
+
ok: boolean;
|
|
144
|
+
error?: string;
|
|
145
|
+
channel: string;
|
|
146
|
+
ts: string;
|
|
147
|
+
};
|
|
147
148
|
if (!data.ok) {
|
|
148
149
|
throw new Error(`Slack API error: ${data.error}`);
|
|
149
150
|
}
|
|
@@ -202,16 +203,17 @@ ${migrationsText}`;
|
|
|
202
203
|
throw new Error(`Slack API HTTP error: ${response.status}`);
|
|
203
204
|
}
|
|
204
205
|
|
|
205
|
-
const data =
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
206
|
+
const data =
|
|
207
|
+
/* SAFETY: Knex와 PostgreSQL 스키마 조회 계약이 이 값의 타입을 보장한다. */ (await response.json()) as {
|
|
208
|
+
ok: boolean;
|
|
209
|
+
error?: string;
|
|
210
|
+
message?: {
|
|
211
|
+
reactions?: Array<{
|
|
212
|
+
name: string;
|
|
213
|
+
users?: string[];
|
|
214
|
+
}>;
|
|
215
|
+
};
|
|
213
216
|
};
|
|
214
|
-
};
|
|
215
217
|
if (!data.ok) {
|
|
216
218
|
throw new Error(`Slack API error: ${data.error}`);
|
|
217
219
|
}
|
|
@@ -103,7 +103,7 @@ class NaiteReporterClass {
|
|
|
103
103
|
private async send(data: NaiteMessagingTypes.NaiteMessage): Promise<void> {
|
|
104
104
|
const msg = `${JSON.stringify(data)}\n`;
|
|
105
105
|
|
|
106
|
-
await this.ensureConnection().catch((
|
|
106
|
+
await this.ensureConnection().catch(() => {});
|
|
107
107
|
|
|
108
108
|
if (this.connected && this.socket) {
|
|
109
109
|
this.socket.write(msg);
|