sonamu 0.10.12 → 0.10.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai/agents/agent.d.ts +1 -1
- package/dist/ai/agents/agent.d.ts.map +1 -1
- package/dist/ai/agents/agent.js +5 -6
- package/dist/ai/agents/types.d.ts +1 -1
- package/dist/ai/agents/types.d.ts.map +1 -1
- package/dist/ai/providers/rtzr/api.js +18 -18
- package/dist/ai/providers/rtzr/error.d.ts.map +1 -1
- package/dist/ai/providers/rtzr/error.js +17 -15
- package/dist/ai/providers/rtzr/model.d.ts.map +1 -1
- package/dist/ai/providers/rtzr/model.js +3 -2
- package/dist/ai/providers/rtzr/options.d.ts.map +1 -1
- package/dist/ai/providers/rtzr/options.js +16 -16
- package/dist/ai/providers/rtzr/provider.d.ts.map +1 -1
- package/dist/ai/providers/rtzr/provider.js +9 -9
- package/dist/ai/providers/rtzr/utils.d.ts.map +1 -1
- package/dist/ai/providers/rtzr/utils.js +1 -1
- package/dist/api/caster.d.ts.map +1 -1
- package/dist/api/caster.js +17 -17
- package/dist/api/code-converters.d.ts +4 -2
- package/dist/api/code-converters.d.ts.map +1 -1
- package/dist/api/code-converters.js +100 -19
- package/dist/api/config.d.ts +16 -1
- package/dist/api/config.d.ts.map +1 -1
- package/dist/api/config.js +28 -21
- package/dist/api/context.d.ts +2 -2
- package/dist/api/context.d.ts.map +1 -1
- package/dist/api/context.js +1 -1
- package/dist/api/decorators.d.ts.map +1 -1
- package/dist/api/decorators.js +18 -11
- package/dist/api/http-validator.d.ts +36 -0
- package/dist/api/http-validator.d.ts.map +1 -0
- package/dist/api/http-validator.js +72 -0
- package/dist/api/index.js +6 -4
- package/dist/api/sonamu.d.ts +59 -20
- package/dist/api/sonamu.d.ts.map +1 -1
- package/dist/api/sonamu.js +250 -106
- package/dist/api/websocket-helpers.d.ts +7 -5
- package/dist/api/websocket-helpers.d.ts.map +1 -1
- package/dist/api/websocket-helpers.js +6 -6
- package/dist/auth/audit-log/builders.d.ts.map +1 -1
- package/dist/auth/audit-log/builders.js +1 -1
- package/dist/auth/audit-log/client-ip.d.ts +1 -1
- package/dist/auth/audit-log/client-ip.d.ts.map +1 -1
- package/dist/auth/audit-log/client-ip.js +4 -2
- package/dist/auth/audit-log/events.d.ts +5 -1
- package/dist/auth/audit-log/events.d.ts.map +1 -1
- package/dist/auth/audit-log/events.js +1 -1
- package/dist/auth/audit-log/plugin.d.ts +0 -8
- package/dist/auth/audit-log/plugin.d.ts.map +1 -1
- package/dist/auth/audit-log/plugin.js +48 -52
- package/dist/auth/audit-log-ingestor.d.ts.map +1 -1
- package/dist/auth/audit-log-ingestor.js +16 -12
- package/dist/auth/auth-generator.d.ts.map +1 -1
- package/dist/auth/auth-generator.js +1 -1
- package/dist/auth/better-auth-request.d.ts.map +1 -1
- package/dist/auth/better-auth-request.js +6 -5
- package/dist/auth/knex-adapter.js +1 -1
- package/dist/auth/plugins/entity-definitions/index.d.ts +13 -1
- package/dist/auth/plugins/entity-definitions/index.d.ts.map +1 -1
- package/dist/auth/plugins/entity-definitions/index.js +1 -1
- package/dist/auth/plugins/wrappers/admin.d.ts +1 -1
- package/dist/bin/build-config.d.ts +25 -0
- package/dist/bin/build-config.d.ts.map +1 -1
- package/dist/bin/build-config.js +105 -2
- package/dist/bin/cli.js +131 -27
- package/dist/bin/compiler-policy.d.ts +3 -0
- package/dist/bin/compiler-policy.d.ts.map +1 -0
- package/dist/bin/compiler-policy.js +24 -0
- package/dist/bin/fixture.d.ts.map +1 -1
- package/dist/bin/fixture.js +5 -3
- package/dist/bin/test-command.d.ts +22 -1
- package/dist/bin/test-command.d.ts.map +1 -1
- package/dist/bin/test-command.js +18 -10
- package/dist/bin/ts-loader-registration.d.ts +7 -1
- package/dist/bin/ts-loader-registration.d.ts.map +1 -1
- package/dist/bin/ts-loader-registration.js +13 -4
- package/dist/cache/decorator.d.ts.map +1 -1
- package/dist/cache/decorator.js +11 -4
- package/dist/compress/compress.d.ts.map +1 -1
- package/dist/compress/compress.js +1 -1
- package/dist/cone/cone-generator.d.ts +14 -1
- package/dist/cone/cone-generator.d.ts.map +1 -1
- package/dist/cone/cone-generator.js +13 -9
- package/dist/database/_batch_update.js +1 -1
- package/dist/database/base-model.d.ts +22 -10
- package/dist/database/base-model.d.ts.map +1 -1
- package/dist/database/base-model.js +26 -16
- package/dist/database/base-model.types.d.ts +15 -3
- package/dist/database/base-model.types.d.ts.map +1 -1
- package/dist/database/db.d.ts +12 -2
- package/dist/database/db.d.ts.map +1 -1
- package/dist/database/db.js +10 -7
- package/dist/database/knex.d.ts.map +1 -1
- package/dist/database/knex.js +17 -14
- package/dist/database/puri.d.ts +11 -9
- package/dist/database/puri.d.ts.map +1 -1
- package/dist/database/puri.js +93 -79
- package/dist/database/puri.types.d.ts +21 -21
- package/dist/database/puri.types.d.ts.map +1 -1
- package/dist/database/puri.types.js +1 -1
- package/dist/database/upsert-builder.d.ts +12 -10
- package/dist/database/upsert-builder.d.ts.map +1 -1
- package/dist/database/upsert-builder.js +20 -12
- package/dist/dict/sd.d.ts.map +1 -1
- package/dist/dict/sd.js +1 -1
- package/dist/dict/sonamu-dictionary.d.ts.map +1 -1
- package/dist/dict/sonamu-dictionary.js +1 -1
- package/dist/dict/utils.d.ts.map +1 -1
- package/dist/dict/utils.js +7 -2
- package/dist/entity/entity-manager.d.ts +13 -4
- package/dist/entity/entity-manager.d.ts.map +1 -1
- package/dist/entity/entity-manager.js +19 -11
- package/dist/entity/entity-template-cone.d.ts +73 -5
- package/dist/entity/entity-template-cone.d.ts.map +1 -1
- package/dist/entity/entity-template-cone.js +4 -2
- package/dist/entity/entity.d.ts +6 -2
- package/dist/entity/entity.d.ts.map +1 -1
- package/dist/entity/entity.js +30 -28
- package/dist/env.d.ts +3 -1
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +1 -1
- package/dist/exceptions/error-handler.d.ts.map +1 -1
- package/dist/exceptions/error-handler.js +7 -2
- package/dist/exceptions/so-exceptions.d.ts +24 -20
- package/dist/exceptions/so-exceptions.d.ts.map +1 -1
- package/dist/exceptions/so-exceptions.js +4 -2
- package/dist/filter/utils.d.ts +7 -2
- package/dist/filter/utils.d.ts.map +1 -1
- package/dist/filter/utils.js +8 -6
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -6
- package/dist/logger/configure.d.ts.map +1 -1
- package/dist/logger/configure.js +10 -10
- package/dist/migration/code-generation.d.ts.map +1 -1
- package/dist/migration/code-generation.js +50 -46
- package/dist/migration/index-where-predicate.d.ts.map +1 -1
- package/dist/migration/index-where-predicate.js +22 -8
- package/dist/migration/migration-set.d.ts.map +1 -1
- package/dist/migration/migration-set.js +1 -1
- package/dist/migration/migrator.d.ts +3 -2
- package/dist/migration/migrator.d.ts.map +1 -1
- package/dist/migration/migrator.js +27 -21
- package/dist/migration/postgresql-schema-reader.d.ts.map +1 -1
- package/dist/migration/postgresql-schema-reader.js +51 -36
- package/dist/migration/slack-confirm.d.ts.map +1 -1
- package/dist/migration/slack-confirm.js +1 -1
- package/dist/naite/naite-reporter.js +2 -2
- package/dist/naite/naite.d.ts +74 -15
- package/dist/naite/naite.d.ts.map +1 -1
- package/dist/naite/naite.js +5 -19
- package/dist/runtime-type.d.ts +6 -0
- package/dist/runtime-type.d.ts.map +1 -0
- package/dist/runtime-type.js +26 -0
- package/dist/ssr/hmr-opt-out.d.ts +26 -0
- package/dist/ssr/hmr-opt-out.d.ts.map +1 -0
- package/dist/ssr/hmr-opt-out.js +59 -0
- package/dist/ssr/renderer.d.ts.map +1 -1
- package/dist/ssr/renderer.js +4 -1
- package/dist/storage/base-file.js +14 -14
- package/dist/storage/buffered-file.d.ts +2 -2
- package/dist/storage/buffered-file.d.ts.map +1 -1
- package/dist/storage/buffered-file.js +12 -12
- package/dist/storage/s3-driver.d.ts.map +1 -1
- package/dist/storage/s3-driver.js +1 -1
- package/dist/storage/uploaded-file.d.ts +2 -2
- package/dist/storage/uploaded-file.d.ts.map +1 -1
- package/dist/storage/uploaded-file.js +8 -8
- package/dist/stream/sse.js +11 -11
- package/dist/stream/ws-core.d.ts +1 -1
- package/dist/stream/ws-core.d.ts.map +1 -1
- package/dist/stream/ws-delivery.d.ts +1 -1
- package/dist/stream/ws-delivery.d.ts.map +1 -1
- package/dist/stream/ws-delivery.js +6 -4
- package/dist/stream/ws-local-connection-store.d.ts.map +1 -1
- package/dist/stream/ws-local-connection-store.js +4 -2
- package/dist/stream/ws-presence-store.js +1 -1
- package/dist/stream/ws-registry.d.ts +4 -4
- package/dist/stream/ws-registry.d.ts.map +1 -1
- package/dist/stream/ws-registry.js +4 -2
- package/dist/stream/ws-telemetry.d.ts +16 -12
- package/dist/stream/ws-telemetry.d.ts.map +1 -1
- package/dist/stream/ws-telemetry.js +22 -18
- package/dist/stream/ws.d.ts +18 -12
- package/dist/stream/ws.d.ts.map +1 -1
- package/dist/stream/ws.js +26 -22
- package/dist/syncer/api-parser.js +1 -1
- package/dist/syncer/checksum.d.ts.map +1 -1
- package/dist/syncer/checksum.js +7 -8
- package/dist/syncer/code-generator.d.ts.map +1 -1
- package/dist/syncer/code-generator.js +13 -14
- package/dist/syncer/entity-operations.d.ts.map +1 -1
- package/dist/syncer/entity-operations.js +5 -6
- package/dist/syncer/file-copy.d.ts +5 -0
- package/dist/syncer/file-copy.d.ts.map +1 -0
- package/dist/syncer/file-copy.js +36 -0
- package/dist/syncer/file-patterns.d.ts +1 -0
- package/dist/syncer/file-patterns.d.ts.map +1 -1
- package/dist/syncer/file-patterns.js +5 -2
- package/dist/syncer/file-tracking.d.ts.map +1 -1
- package/dist/syncer/file-tracking.js +5 -4
- package/dist/syncer/filesystem-dependencies.d.ts +15 -0
- package/dist/syncer/filesystem-dependencies.d.ts.map +1 -0
- package/dist/syncer/filesystem-dependencies.js +53 -0
- package/dist/syncer/module-loader.d.ts +1 -1
- package/dist/syncer/module-loader.d.ts.map +1 -1
- package/dist/syncer/module-loader.js +6 -4
- package/dist/syncer/syncer-actions.d.ts +4 -0
- package/dist/syncer/syncer-actions.d.ts.map +1 -1
- package/dist/syncer/syncer-actions.js +34 -17
- package/dist/syncer/syncer.d.ts +17 -6
- package/dist/syncer/syncer.d.ts.map +1 -1
- package/dist/syncer/syncer.js +71 -29
- package/dist/syncer/watcher.d.ts.map +1 -1
- package/dist/syncer/watcher.js +3 -3
- package/dist/tasks/decorator.d.ts +6 -6
- package/dist/tasks/decorator.d.ts.map +1 -1
- package/dist/tasks/decorator.js +4 -4
- package/dist/tasks/step-wrapper.d.ts +6 -4
- package/dist/tasks/step-wrapper.d.ts.map +1 -1
- package/dist/tasks/step-wrapper.js +5 -5
- package/dist/tasks/workflow-manager.d.ts.map +1 -1
- package/dist/tasks/workflow-manager.js +13 -7
- package/dist/template/entity-converter.d.ts +1 -1
- package/dist/template/entity-converter.d.ts.map +1 -1
- package/dist/template/entity-converter.js +2 -2
- package/dist/template/helpers.d.ts +8 -6
- package/dist/template/helpers.d.ts.map +1 -1
- package/dist/template/helpers.js +1 -1
- package/dist/template/implementations/generated.template.d.ts.map +1 -1
- package/dist/template/implementations/generated.template.js +4 -4
- package/dist/template/implementations/generated_http.template.d.ts +7 -4
- package/dist/template/implementations/generated_http.template.d.ts.map +1 -1
- package/dist/template/implementations/generated_http.template.js +21 -21
- package/dist/template/implementations/generated_sso.template.d.ts.map +1 -1
- package/dist/template/implementations/generated_sso.template.js +6 -3
- package/dist/template/implementations/http_validators.template.d.ts +18 -0
- package/dist/template/implementations/http_validators.template.d.ts.map +1 -0
- package/dist/template/implementations/http_validators.template.js +127 -0
- package/dist/template/implementations/model.template.d.ts.map +1 -1
- package/dist/template/implementations/model.template.js +1 -1
- package/dist/template/implementations/queries.template.js +1 -1
- package/dist/template/implementations/sd.template.d.ts.map +1 -1
- package/dist/template/implementations/sd.template.js +79 -39
- package/dist/template/implementations/services.template.d.ts.map +1 -1
- package/dist/template/implementations/services.template.js +6 -4
- package/dist/template/implementations/view_form.template.d.ts +6 -1
- package/dist/template/implementations/view_form.template.d.ts.map +1 -1
- package/dist/template/implementations/view_form.template.js +23 -15
- package/dist/template/implementations/view_list.template.d.ts.map +1 -1
- package/dist/template/implementations/view_list.template.js +11 -6
- package/dist/template/template-manager.d.ts.map +1 -1
- package/dist/template/template-manager.js +9 -7
- package/dist/template/template-types.d.ts +12 -5
- package/dist/template/template-types.d.ts.map +1 -1
- package/dist/template/template-types.js +1 -1
- package/dist/template/template.d.ts +2 -2
- package/dist/template/template.d.ts.map +1 -1
- package/dist/template/template.js +6 -4
- package/dist/template/zod-converter.d.ts +0 -19
- package/dist/template/zod-converter.d.ts.map +1 -1
- package/dist/template/zod-converter.js +100 -84
- package/dist/testing/_relation-graph.d.ts.map +1 -1
- package/dist/testing/_relation-graph.js +2 -1
- package/dist/testing/bootstrap.d.ts.map +1 -1
- package/dist/testing/bootstrap.js +9 -6
- package/dist/testing/data-explorer.d.ts +32 -7
- package/dist/testing/data-explorer.d.ts.map +1 -1
- package/dist/testing/data-explorer.js +77 -31
- package/dist/testing/dev-test-routes.d.ts +8 -1
- package/dist/testing/dev-test-routes.d.ts.map +1 -1
- package/dist/testing/dev-test-routes.js +125 -108
- package/dist/testing/dev-vitest-manager.d.ts +54 -8
- package/dist/testing/dev-vitest-manager.d.ts.map +1 -1
- package/dist/testing/dev-vitest-manager.js +24 -9
- package/dist/testing/faker-mappings.d.ts +412 -1
- package/dist/testing/faker-mappings.d.ts.map +1 -1
- package/dist/testing/faker-mappings.js +1 -1
- package/dist/testing/filesystem.d.ts +2 -0
- package/dist/testing/filesystem.d.ts.map +1 -0
- package/dist/testing/filesystem.js +7 -0
- package/dist/testing/fixture-generator.d.ts +25 -8
- package/dist/testing/fixture-generator.d.ts.map +1 -1
- package/dist/testing/fixture-generator.js +132 -73
- package/dist/testing/fixture-loader.d.ts +3 -1
- package/dist/testing/fixture-loader.d.ts.map +1 -1
- package/dist/testing/fixture-loader.js +1 -20
- package/dist/testing/fixture-manager.d.ts +8 -7
- package/dist/testing/fixture-manager.d.ts.map +1 -1
- package/dist/testing/fixture-manager.js +91 -59
- package/dist/testing/global-setup.d.ts.map +1 -1
- package/dist/testing/global-setup.js +5 -2
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +6 -3
- package/dist/types/types.d.ts +101 -99
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/types.js +234 -225
- package/dist/ui/ai-api.d.ts.map +1 -1
- package/dist/ui/ai-api.js +1 -1
- package/dist/ui/ai-client.d.ts.map +1 -1
- package/dist/ui/ai-client.js +28 -18
- package/dist/ui/api.d.ts.map +1 -1
- package/dist/ui/api.js +135 -128
- package/dist/ui/async-route.d.ts +3 -0
- package/dist/ui/async-route.d.ts.map +1 -0
- package/dist/ui/async-route.js +12 -0
- package/dist/ui/cdd-service.d.ts +9 -7
- package/dist/ui/cdd-service.d.ts.map +1 -1
- package/dist/ui/cdd-service.js +7 -5
- package/dist/ui/migrations-api.d.ts.map +1 -1
- package/dist/ui/migrations-api.js +17 -15
- package/dist/ui-web/assets/index-DV1AAq6W.js +178 -0
- package/dist/ui-web/index.html +1 -1
- package/dist/utils/formatter.d.ts.map +1 -1
- package/dist/utils/formatter.js +7 -5
- package/dist/utils/fs-utils.d.ts +3 -3
- package/dist/utils/fs-utils.d.ts.map +1 -1
- package/dist/utils/fs-utils.js +6 -6
- package/dist/utils/model.d.ts +3 -5
- package/dist/utils/model.d.ts.map +1 -1
- package/dist/utils/model.js +1 -1
- package/dist/utils/object-utils.d.ts +1 -1
- package/dist/utils/object-utils.d.ts.map +1 -1
- package/dist/utils/object-utils.js +17 -16
- package/dist/utils/process-utils.d.ts.map +1 -1
- package/dist/utils/process-utils.js +4 -2
- package/dist/utils/runtime-value.d.ts +13 -0
- package/dist/utils/runtime-value.d.ts.map +1 -0
- package/dist/utils/runtime-value.js +40 -0
- package/dist/utils/sql-parser.d.ts +8 -1
- package/dist/utils/sql-parser.d.ts.map +1 -1
- package/dist/utils/sql-parser.js +6 -3
- package/dist/utils/type-utils.d.ts.map +1 -1
- package/dist/utils/type-utils.js +10 -8
- package/dist/utils/utils.d.ts +2 -2
- package/dist/utils/utils.d.ts.map +1 -1
- package/dist/utils/utils.js +11 -8
- package/dist/utils/zod-error.d.ts.map +1 -1
- package/dist/utils/zod-error.js +7 -4
- package/dist/vector/chunking.d.ts.map +1 -1
- package/dist/vector/chunking.js +1 -1
- package/dist/vector/embedding.d.ts.map +1 -1
- package/dist/vector/embedding.js +1 -1
- package/dist/vector/types.d.ts +3 -2
- package/dist/vector/types.d.ts.map +1 -1
- package/package.json +5 -3
- package/src/ai/agents/agent.ts +5 -5
- package/src/ai/agents/types.ts +1 -1
- package/src/ai/providers/rtzr/__tests__/model.test.ts +2 -2
- package/src/ai/providers/rtzr/error.ts +5 -3
- package/src/ai/providers/rtzr/model.ts +3 -2
- package/src/ai/providers/rtzr/options.ts +10 -5
- package/src/ai/providers/rtzr/provider.ts +10 -10
- package/src/ai/providers/rtzr/utils.ts +3 -1
- package/src/api/__tests__/config.test.ts +11 -21
- package/src/api/__tests__/sonamu.http-validator.test.ts +512 -0
- package/src/api/__tests__/sonamu.websocket.test.ts +51 -41
- package/src/api/__tests__/zod-compiler-policy.test.ts +95 -0
- package/src/api/caster.ts +6 -8
- package/src/api/code-converters.ts +136 -36
- package/src/api/config.ts +62 -4
- package/src/api/context.ts +3 -3
- package/src/api/decorators.ts +28 -17
- package/src/api/http-validator.ts +149 -0
- package/src/api/sonamu.ts +459 -152
- package/src/api/websocket-helpers.ts +24 -17
- package/src/auth/audit-log/builders.ts +3 -2
- package/src/auth/audit-log/client-ip.ts +4 -2
- package/src/auth/audit-log/events.ts +15 -1
- package/src/auth/audit-log/plugin.ts +129 -200
- package/src/auth/audit-log-ingestor.ts +19 -15
- package/src/auth/auth-generator.ts +10 -5
- package/src/auth/better-auth-request.ts +4 -3
- package/src/auth/knex-adapter.ts +8 -2
- package/src/auth/plugins/entity-definitions/index.ts +6 -5
- package/src/bin/__tests__/http-validator-benchmark.test.ts +94 -0
- package/src/bin/__tests__/test-command.test.ts +9 -15
- package/src/bin/__tests__/ts-loader-register.test.ts +15 -17
- package/src/bin/__tests__/zod-compiler-build.test.ts +307 -0
- package/src/bin/build-config.ts +167 -0
- package/src/bin/cli.ts +153 -36
- package/src/bin/compiler-policy.ts +35 -0
- package/src/bin/fixture.ts +14 -3
- package/src/bin/test-command.ts +74 -29
- package/src/bin/ts-loader-registration.ts +22 -4
- package/src/cache/decorator.ts +10 -3
- package/src/compress/compress.ts +17 -4
- package/src/cone/cone-generator.ts +34 -6
- package/src/database/__tests__/db.test.ts +1 -0
- package/src/database/__tests__/puri.test.ts +16 -15
- package/src/database/__tests__/transaction-scope.test.ts +5 -0
- package/src/database/_batch_update.ts +1 -0
- package/src/database/base-model.ts +81 -50
- package/src/database/base-model.types.ts +6 -6
- package/src/database/db.ts +29 -19
- package/src/database/knex.ts +30 -17
- package/src/database/puri-subset.test-d.ts +17 -0
- package/src/database/puri.ts +181 -143
- package/src/database/puri.types.test-d.ts +31 -1
- package/src/database/puri.types.ts +23 -21
- package/src/database/upsert-builder.ts +75 -53
- package/src/dict/sd.ts +15 -5
- package/src/dict/sonamu-dictionary.ts +6 -6
- package/src/dict/utils.ts +9 -1
- package/src/entity/entity-manager.ts +26 -9
- package/src/entity/entity-template-cone.ts +5 -10
- package/src/entity/entity.ts +50 -34
- package/src/env.ts +7 -3
- package/src/exceptions/error-handler.ts +17 -2
- package/src/exceptions/so-exceptions.ts +26 -20
- package/src/filter/utils.ts +21 -11
- package/src/index.ts +3 -0
- package/src/logger/configure.ts +26 -18
- package/src/migration/__tests__/migrator.test.ts +50 -57
- package/src/migration/code-generation.ts +132 -104
- package/src/migration/index-where-predicate.ts +51 -24
- package/src/migration/migration-set.ts +11 -5
- package/src/migration/migrator.ts +68 -41
- package/src/migration/postgresql-schema-reader.ts +52 -47
- package/src/migration/slack-confirm.ts +17 -15
- package/src/naite/naite-reporter.ts +1 -1
- package/src/naite/naite.ts +97 -24
- package/src/runtime-type.ts +34 -0
- package/src/ssr/hmr-opt-out.ts +78 -0
- package/src/ssr/renderer.ts +6 -0
- package/src/storage/base-file.ts +13 -13
- package/src/storage/buffered-file.ts +11 -11
- package/src/storage/s3-driver.ts +4 -1
- package/src/storage/uploaded-file.ts +8 -8
- package/src/stream/__tests__/ws-contracts.test.ts +4 -2
- package/src/stream/__tests__/ws-telemetry.test.ts +1 -1
- package/src/stream/__tests__/ws.test.ts +30 -6
- package/src/stream/sse.ts +12 -11
- package/src/stream/ws-core.ts +1 -1
- package/src/stream/ws-delivery.ts +16 -7
- package/src/stream/ws-local-connection-store.ts +2 -3
- package/src/stream/ws-presence-store.ts +6 -1
- package/src/stream/ws-registry.ts +16 -7
- package/src/stream/ws-telemetry.ts +66 -43
- package/src/stream/ws.ts +73 -39
- package/src/syncer/__tests__/api-parser.websocket-type-ref.test.ts +3 -2
- package/src/syncer/__tests__/http-validator-registry.test.ts +137 -0
- package/src/syncer/api-parser.ts +67 -27
- package/src/syncer/checksum.ts +17 -11
- package/src/syncer/code-generator.ts +25 -17
- package/src/syncer/entity-operations.ts +3 -5
- package/src/syncer/file-copy.ts +46 -0
- package/src/syncer/file-patterns.ts +11 -8
- package/src/syncer/file-tracking.ts +3 -4
- package/src/syncer/filesystem-dependencies.ts +73 -0
- package/src/syncer/module-loader.ts +8 -4
- package/src/syncer/syncer-actions.ts +56 -18
- package/src/syncer/syncer.ts +116 -43
- package/src/syncer/watcher.ts +8 -4
- package/src/tasks/decorator.ts +20 -12
- package/src/tasks/step-wrapper.ts +19 -9
- package/src/tasks/workflow-manager.ts +15 -9
- package/src/template/__tests__/http_validators.template.test.ts +160 -0
- package/src/template/__tests__/services.template.mutation.test.ts +24 -23
- package/src/template/__tests__/services.template.websocket.test.ts +21 -25
- package/src/template/entity-converter.ts +5 -2
- package/src/template/helpers.ts +8 -9
- package/src/template/implementations/generated.template.ts +5 -4
- package/src/template/implementations/generated_http.template.ts +61 -15
- package/src/template/implementations/generated_sso.template.ts +15 -4
- package/src/template/implementations/http_validators.template.ts +175 -0
- package/src/template/implementations/model.template.ts +3 -1
- package/src/template/implementations/sd.template.ts +81 -41
- package/src/template/implementations/services.template.ts +2 -2
- package/src/template/implementations/view_form.template.ts +56 -39
- package/src/template/implementations/view_list.template.ts +31 -23
- package/src/template/template-manager.ts +15 -13
- package/src/template/template-types.ts +13 -5
- package/src/template/template.ts +4 -3
- package/src/template/zod-converter.ts +206 -91
- package/src/testing/__tests__/dev-test-routes.test.ts +85 -25
- package/src/testing/__tests__/dev-vitest-manager.test.ts +15 -15
- package/src/testing/_relation-graph.ts +4 -1
- package/src/testing/bootstrap.ts +12 -5
- package/src/testing/data-explorer.ts +102 -53
- package/src/testing/dev-test-routes.ts +87 -50
- package/src/testing/dev-vitest-manager.ts +88 -32
- package/src/testing/faker-mappings.ts +2 -2
- package/src/testing/filesystem.ts +1 -0
- package/src/testing/fixture-generator.ts +191 -131
- package/src/testing/fixture-loader.ts +5 -1
- package/src/testing/fixture-manager.ts +129 -90
- package/src/testing/global-setup.ts +7 -3
- package/src/testing/index.ts +5 -0
- package/src/types/__tests__/entity-json-schema-search-text.test.ts +9 -3
- package/src/types/types.ts +184 -158
- package/src/ui/ai-api.ts +9 -7
- package/src/ui/ai-client.ts +61 -56
- package/src/ui/api.ts +727 -616
- package/src/ui/async-route.ts +4 -0
- package/src/ui/cdd-service.ts +35 -12
- package/src/ui/migrations-api.ts +63 -51
- package/src/utils/formatter.ts +7 -3
- package/src/utils/fs-utils.ts +5 -5
- package/src/utils/model.ts +4 -5
- package/src/utils/object-utils.ts +32 -22
- package/src/utils/process-utils.ts +4 -1
- package/src/utils/runtime-value.ts +43 -0
- package/src/utils/sql-parser.ts +13 -6
- package/src/utils/type-utils.ts +9 -7
- package/src/utils/utils.ts +19 -21
- package/src/utils/zod-error.ts +4 -2
- package/src/vector/chunking.ts +6 -1
- package/src/vector/embedding.ts +2 -1
- package/src/vector/types.ts +4 -2
- package/tsdown.api.config.ts +5 -2
- package/dist/ui-web/assets/index-C0m1pk6K.js +0 -177
package/src/syncer/checksum.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import crypto from "crypto";
|
|
2
2
|
import { createReadStream, type PathLike } from "fs";
|
|
3
|
-
import { readFile, writeFile } from "fs/promises";
|
|
4
3
|
import path from "path";
|
|
5
4
|
|
|
6
5
|
import equal from "fast-deep-equal";
|
|
@@ -8,10 +7,10 @@ import { isEqual } from "radashi";
|
|
|
8
7
|
|
|
9
8
|
import { Sonamu } from "../api/sonamu";
|
|
10
9
|
import { globAsync } from "../utils/async-utils";
|
|
11
|
-
import { exists } from "../utils/fs-utils";
|
|
12
10
|
import { type AbsolutePath, type AppRelativePath } from "../utils/path-utils";
|
|
13
11
|
import { differenceWith } from "../utils/utils";
|
|
14
12
|
import { getChecksumPatternGroupInAbsolutePath, GLOB_EXCLUDE } from "./file-patterns";
|
|
13
|
+
import { syncerFileExists, syncerFilesystem } from "./filesystem-dependencies";
|
|
15
14
|
|
|
16
15
|
type PathAndChecksum = {
|
|
17
16
|
path: AbsolutePath;
|
|
@@ -61,7 +60,10 @@ async function getCurrentChecksums(): Promise<PathAndChecksum[]> {
|
|
|
61
60
|
|
|
62
61
|
// 동일 파일이 여러 패턴에 매치될 수 있으므로(예: sd.generated.ts는 generated와 sdGenerated에 모두 매치)
|
|
63
62
|
// 중복 제거 후 안정 정렬.
|
|
64
|
-
const filePaths =
|
|
63
|
+
const filePaths =
|
|
64
|
+
/* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ Array.from(
|
|
65
|
+
new Set(allPaths),
|
|
66
|
+
).toSorted() as AbsolutePath[];
|
|
65
67
|
|
|
66
68
|
return await Promise.all(
|
|
67
69
|
filePaths.map(async (filePath) => {
|
|
@@ -75,17 +77,18 @@ async function getCurrentChecksums(): Promise<PathAndChecksum[]> {
|
|
|
75
77
|
|
|
76
78
|
async function getPreviousChecksums(): Promise<PathAndChecksum[]> {
|
|
77
79
|
const checksumFilePath = getChecksumFilePath();
|
|
78
|
-
if (!(await
|
|
80
|
+
if (!(await syncerFileExists(checksumFilePath))) {
|
|
79
81
|
return [];
|
|
80
82
|
}
|
|
81
83
|
|
|
82
84
|
try {
|
|
83
|
-
const previousChecksums =
|
|
84
|
-
|
|
85
|
+
const previousChecksums =
|
|
86
|
+
/* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ JSON.parse(
|
|
87
|
+
await syncerFilesystem.readFile(checksumFilePath, "utf-8"),
|
|
88
|
+
).map((r: { path: AppRelativePath; checksum: string }) => ({
|
|
85
89
|
path: path.join(Sonamu.appRootPath, r.path), // 체크섬 파일에서 읽을 때: appRoot 상대 경로 → 절대 경로
|
|
86
90
|
checksum: r.checksum,
|
|
87
|
-
})
|
|
88
|
-
) as PathAndChecksum[];
|
|
91
|
+
})) as PathAndChecksum[];
|
|
89
92
|
return previousChecksums;
|
|
90
93
|
} catch (e) {
|
|
91
94
|
// 체크섬 파일이 손상된 경우 빈 배열 반환 (전체 재동기화 유도)
|
|
@@ -98,7 +101,10 @@ async function getPreviousChecksums(): Promise<PathAndChecksum[]> {
|
|
|
98
101
|
}
|
|
99
102
|
|
|
100
103
|
function getChecksumFilePath(): AbsolutePath {
|
|
101
|
-
return path.join(
|
|
104
|
+
return /* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ path.join(
|
|
105
|
+
Sonamu.apiRootPath,
|
|
106
|
+
"sonamu.lock",
|
|
107
|
+
) as AbsolutePath;
|
|
102
108
|
}
|
|
103
109
|
|
|
104
110
|
async function saveChecksums(checksums: PathAndChecksum[]): Promise<void> {
|
|
@@ -109,8 +115,8 @@ async function saveChecksums(checksums: PathAndChecksum[]): Promise<void> {
|
|
|
109
115
|
path: path.relative(Sonamu.appRootPath, r.path), // 체크섬 파일에 저장할 때: 절대 경로 → appRoot 상대 경로
|
|
110
116
|
checksum: r.checksum,
|
|
111
117
|
}))
|
|
112
|
-
.
|
|
113
|
-
await writeFile(checksumFilePath, JSON.stringify(serialized, null, 2), "utf-8");
|
|
118
|
+
.toSorted((a, b) => a.path.localeCompare(b.path));
|
|
119
|
+
await syncerFilesystem.writeFile(checksumFilePath, JSON.stringify(serialized, null, 2), "utf-8");
|
|
114
120
|
}
|
|
115
121
|
|
|
116
122
|
async function getChecksumOfFile(filePath: PathLike): Promise<string> {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { mkdir, writeFile } from "fs/promises";
|
|
2
1
|
import path from "path";
|
|
3
2
|
|
|
4
3
|
import chalk from "chalk";
|
|
@@ -21,10 +20,10 @@ import {
|
|
|
21
20
|
import { everyAsync, filterAsync } from "../utils/async-utils";
|
|
22
21
|
import { isTest } from "../utils/controller";
|
|
23
22
|
import { formatCode } from "../utils/formatter";
|
|
24
|
-
import { exists } from "../utils/fs-utils";
|
|
25
23
|
import { wrapIf } from "../utils/lodash-able";
|
|
26
24
|
import { type AbsolutePath } from "../utils/path-utils";
|
|
27
25
|
import { trackWritten } from "./file-tracking";
|
|
26
|
+
import { syncerFileExists, syncerFilesystem } from "./filesystem-dependencies";
|
|
28
27
|
|
|
29
28
|
/**
|
|
30
29
|
* 템플릿을 렌더링하고 파일로 생성합니다.
|
|
@@ -51,8 +50,8 @@ export async function generateTemplate<T extends TemplateKey>(
|
|
|
51
50
|
// 템플릿 렌더
|
|
52
51
|
const pathAndCodes = (
|
|
53
52
|
await Promise.all(
|
|
54
|
-
keys.map(async (
|
|
55
|
-
return await renderTemplate(
|
|
53
|
+
keys.map(async (templateKey) => {
|
|
54
|
+
return await renderTemplate(templateKey, templateOptions);
|
|
56
55
|
}),
|
|
57
56
|
)
|
|
58
57
|
).flat();
|
|
@@ -65,7 +64,10 @@ export async function generateTemplate<T extends TemplateKey>(
|
|
|
65
64
|
const { targets } = Sonamu.config.sync;
|
|
66
65
|
const filePath = `${Sonamu.appRootPath}/${pathAndCode.path}`;
|
|
67
66
|
const dstFilePaths = targets.map((target) => filePath.replace("/:target/", `/${target}/`));
|
|
68
|
-
return await everyAsync(
|
|
67
|
+
return await everyAsync(
|
|
68
|
+
dstFilePaths,
|
|
69
|
+
async (dstPath) => !(await syncerFileExists(dstPath)),
|
|
70
|
+
);
|
|
69
71
|
});
|
|
70
72
|
}
|
|
71
73
|
})();
|
|
@@ -103,8 +105,8 @@ export async function renderTemplate<T extends keyof TemplateOptions>(
|
|
|
103
105
|
if (rendered.preTemplates) {
|
|
104
106
|
preTemplateResolved = (
|
|
105
107
|
await Promise.all(
|
|
106
|
-
rendered.preTemplates.map(({ key, options }) => {
|
|
107
|
-
return renderTemplate(
|
|
108
|
+
rendered.preTemplates.map(({ key: preTemplateKey, options: preTemplateOptions }) => {
|
|
109
|
+
return renderTemplate(preTemplateKey, preTemplateOptions);
|
|
108
110
|
}),
|
|
109
111
|
)
|
|
110
112
|
).flat();
|
|
@@ -122,7 +124,10 @@ async function resolveRenderedTemplate(
|
|
|
122
124
|
const { target, path: filePath, body, importKeys, customHeaders } = result;
|
|
123
125
|
|
|
124
126
|
// import 할 대상의 대상 path 추출
|
|
125
|
-
const builtInSchemaNames = Object.values(BUILT_IN_TYPES).map(
|
|
127
|
+
const builtInSchemaNames = Object.values(BUILT_IN_TYPES).map(
|
|
128
|
+
(info) =>
|
|
129
|
+
/* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ info.schemaName as string,
|
|
130
|
+
);
|
|
126
131
|
const importDefs = importKeys
|
|
127
132
|
// 내장 타입 스키마는 이미 sonamu에서 import되므로 제외
|
|
128
133
|
.filter((importKey) => !builtInSchemaNames.includes(importKey))
|
|
@@ -157,7 +162,7 @@ async function resolveRenderedTemplate(
|
|
|
157
162
|
}
|
|
158
163
|
return r;
|
|
159
164
|
},
|
|
160
|
-
[] as {
|
|
165
|
+
/* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ [] as {
|
|
161
166
|
keys: string[];
|
|
162
167
|
from: string;
|
|
163
168
|
}[],
|
|
@@ -178,12 +183,12 @@ async function resolveRenderedTemplate(
|
|
|
178
183
|
return [header, body].join("\n\n");
|
|
179
184
|
} else {
|
|
180
185
|
Naite.t("resolveRenderedTemplate:beforeFormat", { key, header, body });
|
|
181
|
-
const
|
|
186
|
+
const formattedCode = await formatCode(
|
|
182
187
|
[header, body].join("\n\n"),
|
|
183
188
|
`${Sonamu.appRootPath}/${filePath}`,
|
|
184
189
|
);
|
|
185
|
-
Naite.t(`resolveRenderedTemplate:formatted:${key}`,
|
|
186
|
-
return
|
|
190
|
+
Naite.t(`resolveRenderedTemplate:formatted:${key}`, formattedCode);
|
|
191
|
+
return formattedCode;
|
|
187
192
|
}
|
|
188
193
|
})();
|
|
189
194
|
|
|
@@ -196,18 +201,21 @@ async function resolveRenderedTemplate(
|
|
|
196
201
|
async function writeCodeToPathEachTarget(pathAndCode: PathAndCode): Promise<AbsolutePath[]> {
|
|
197
202
|
const { targets } = Sonamu.config.sync;
|
|
198
203
|
const { appRootPath } = Sonamu;
|
|
199
|
-
const filePath =
|
|
204
|
+
const filePath =
|
|
205
|
+
/* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ `${Sonamu.appRootPath}/${pathAndCode.path}` as AbsolutePath;
|
|
200
206
|
|
|
201
207
|
const dstFilePaths = unique(
|
|
202
|
-
|
|
208
|
+
/* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ targets.map(
|
|
209
|
+
(target) => filePath.replace("/:target/", `/${target}/`),
|
|
210
|
+
) as AbsolutePath[],
|
|
203
211
|
);
|
|
204
212
|
return await Promise.all(
|
|
205
213
|
dstFilePaths.map(async (dstFilePath) => {
|
|
206
214
|
const dir = path.dirname(dstFilePath);
|
|
207
|
-
if (!(await
|
|
208
|
-
await mkdir(dir, { recursive: true });
|
|
215
|
+
if (!(await syncerFileExists(dir))) {
|
|
216
|
+
await syncerFilesystem.mkdir(dir, { recursive: true });
|
|
209
217
|
}
|
|
210
|
-
await writeFile(dstFilePath, pathAndCode.code);
|
|
218
|
+
await syncerFilesystem.writeFile(dstFilePath, pathAndCode.code);
|
|
211
219
|
// 방금 우리가 쓴 path를 등록 → dev watcher의 후속 change 이벤트가
|
|
212
220
|
// 외부 변경으로 오인되지 않도록 거름 가드 자료 제공.
|
|
213
221
|
await trackWritten(dstFilePath);
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { rm } from "fs/promises";
|
|
2
|
-
|
|
3
1
|
import chalk from "chalk";
|
|
4
2
|
|
|
5
3
|
import { Sonamu } from "../api/sonamu";
|
|
@@ -8,8 +6,8 @@ import { EntityManager } from "../entity/entity-manager";
|
|
|
8
6
|
import { BadRequestException } from "../exceptions/so-exceptions";
|
|
9
7
|
import { type TemplateOptions } from "../types/types";
|
|
10
8
|
import { isTest } from "../utils/controller";
|
|
11
|
-
import { exists } from "../utils/fs-utils";
|
|
12
9
|
import { generateTemplate } from "./code-generator";
|
|
10
|
+
import { syncerFileExists, syncerFilesystem } from "./filesystem-dependencies";
|
|
13
11
|
|
|
14
12
|
/**
|
|
15
13
|
* 새로운 엔티티를 생성합니다.
|
|
@@ -53,9 +51,9 @@ export async function delEntity(entityId: string): Promise<{ delPaths: string[]
|
|
|
53
51
|
})(); // iife
|
|
54
52
|
|
|
55
53
|
for (const delPath of delPaths) {
|
|
56
|
-
if (await
|
|
54
|
+
if (await syncerFileExists(delPath)) {
|
|
57
55
|
!isTest() && console.log(chalk.red(`DELETE ${delPath}`));
|
|
58
|
-
await rm(delPath, { recursive: true, force: true });
|
|
56
|
+
await syncerFilesystem.rm(delPath, { recursive: true, force: true });
|
|
59
57
|
} else {
|
|
60
58
|
!isTest() && console.log(chalk.yellow(`NOT_EXISTS ${delPath}`));
|
|
61
59
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import path, { dirname } from "node:path";
|
|
2
|
+
|
|
3
|
+
import { formatCode } from "../utils/formatter";
|
|
4
|
+
import { syncerFileExists, syncerFilesystem } from "./filesystem-dependencies";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Syncer 파일시스템 경계를 통해 파일을 복사하고 클라이언트용 import 경로를 변환합니다.
|
|
8
|
+
*/
|
|
9
|
+
export async function copyFileWithReplaceCoreToShared(
|
|
10
|
+
fromPath: string,
|
|
11
|
+
toPath: string,
|
|
12
|
+
syncHeader?: string,
|
|
13
|
+
): Promise<boolean> {
|
|
14
|
+
if (!(await syncerFileExists(fromPath))) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const oldFileContent = await syncerFilesystem.readFile(fromPath, "utf-8");
|
|
19
|
+
let newFileContent = replaceCoreImport(oldFileContent, toPath);
|
|
20
|
+
|
|
21
|
+
if (syncHeader) {
|
|
22
|
+
const generatedBlockRegex = /\/\*\*\r?\n \* @generated\r?\n[\s\S]*?\*\/\r?\n(\r?\n)*/;
|
|
23
|
+
newFileContent = generatedBlockRegex.test(newFileContent)
|
|
24
|
+
? newFileContent.replace(generatedBlockRegex, `${syncHeader}\n\n`)
|
|
25
|
+
: `${syncHeader}\n\n${newFileContent}`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (toPath.endsWith(".ts") || toPath.endsWith(".tsx")) {
|
|
29
|
+
newFileContent = await formatCode(newFileContent, toPath);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
await syncerFilesystem.writeFile(toPath, newFileContent);
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function replaceCoreImport(source: string, toPath: string): string {
|
|
37
|
+
const srcMatch = toPath.match(/^(.+\/src)\//);
|
|
38
|
+
if (!srcMatch) {
|
|
39
|
+
return source;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const servicesDir = path.join(srcMatch[1], "services");
|
|
43
|
+
const relativePath = path.relative(dirname(toPath), servicesDir);
|
|
44
|
+
const sharedPath = relativePath === "" ? "./sonamu.shared" : `${relativePath}/sonamu.shared`;
|
|
45
|
+
return source.replace(/from "sonamu(\/dict)?"/g, `from "${sharedPath}"`);
|
|
46
|
+
}
|
|
@@ -56,6 +56,7 @@ export function getChecksumPatternGroup() {
|
|
|
56
56
|
// 여기에는 Sonamu의 모든 sync 산출물이 있는 것은 아닙니다.
|
|
57
57
|
// sonamu.shared.ts와 entry-server.generated.tsx와 같은
|
|
58
58
|
// sync 초반 1회성 부트스트랩 파일들은 관리 안 하기 때문에 여기에 리스팅도 안 합니다.
|
|
59
|
+
httpValidatorsGenerated: api("src/application/**/sonamu.validators.generated.ts"),
|
|
59
60
|
generated: api("src/application/**/*.generated.{ts,tsx,sso.ts}"),
|
|
60
61
|
generatedCopied: targets("src/services/**/sonamu.generated.{ts,tsx}"),
|
|
61
62
|
httpGenerated: api("src/application/**/*.generated.http"),
|
|
@@ -67,6 +68,11 @@ export function getChecksumPatternGroup() {
|
|
|
67
68
|
} satisfies Record<string, AppRelativePath>;
|
|
68
69
|
}
|
|
69
70
|
|
|
71
|
+
// Node 내장 fs.glob의 brace expansion은 단일 멤버 {x}를 풀지 않으므로, 멤버가 1개일 때는 alternation 없이 직접 결합합니다.
|
|
72
|
+
function braceJoin(dirs: readonly string[]) {
|
|
73
|
+
return dirs.length === 1 ? dirs[0] : `{${dirs.join(",")}}`;
|
|
74
|
+
}
|
|
75
|
+
|
|
70
76
|
/**
|
|
71
77
|
* 위치 카테고리별 글롭 빌더를 만들어 반환합니다.
|
|
72
78
|
* - api(rest): api 디렉토리에 한정
|
|
@@ -77,16 +83,13 @@ function globBuilders() {
|
|
|
77
83
|
const apiDir = Sonamu.config.api.dir;
|
|
78
84
|
const targetDirs = Sonamu.config.sync.targets;
|
|
79
85
|
|
|
80
|
-
// Node 내장 fs.glob의 brace expansion은 단일 멤버 {x}를 풀지 않으므로, 멤버가 1개일 때는 alternation 없이 직접 결합합니다.
|
|
81
|
-
const braceJoin = (dirs: readonly string[]) =>
|
|
82
|
-
dirs.length === 1 ? dirs[0] : `{${dirs.join(",")}}`;
|
|
83
|
-
|
|
84
86
|
return {
|
|
85
|
-
api: (pathFromApi: string) =>
|
|
87
|
+
api: (pathFromApi: string) =>
|
|
88
|
+
/* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ `${apiDir}/${pathFromApi}` as AppRelativePath,
|
|
86
89
|
targets: (pathFromTarget: string) =>
|
|
87
|
-
`${braceJoin(targetDirs)}/${pathFromTarget}` as AppRelativePath,
|
|
90
|
+
/* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ `${braceJoin(targetDirs)}/${pathFromTarget}` as AppRelativePath,
|
|
88
91
|
anywhere: (pathFromAnywhere: string) =>
|
|
89
|
-
`${braceJoin([apiDir, ...targetDirs])}/${pathFromAnywhere}` as AppRelativePath,
|
|
92
|
+
/* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ `${braceJoin([apiDir, ...targetDirs])}/${pathFromAnywhere}` as AppRelativePath,
|
|
90
93
|
};
|
|
91
94
|
}
|
|
92
95
|
|
|
@@ -110,7 +113,7 @@ export const GLOB_EXCLUDE = ["**/node_modules/**", "**/dist/**", "**/build/**",
|
|
|
110
113
|
*/
|
|
111
114
|
export function getChecksumPatternGroupInAbsolutePath(): GlobPattern<AbsolutePath> {
|
|
112
115
|
const group = getChecksumPatternGroup();
|
|
113
|
-
return Object.fromEntries(
|
|
116
|
+
return /* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ Object.fromEntries(
|
|
114
117
|
Object.entries(group).map(([key, value]) => [
|
|
115
118
|
key,
|
|
116
119
|
path.join(Sonamu.appRootPath, value), // appRoot 상대 경로 → 절대 경로
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { stat } from "fs/promises";
|
|
2
|
-
|
|
3
1
|
import { type AbsolutePath } from "../utils/path-utils";
|
|
2
|
+
import { syncerFilesystem } from "./filesystem-dependencies";
|
|
4
3
|
|
|
5
4
|
export const fileWrittenAt = new Map<AbsolutePath, number>();
|
|
6
5
|
|
|
@@ -9,7 +8,7 @@ export const fileWrittenAt = new Map<AbsolutePath, number>();
|
|
|
9
8
|
* 디스크에서 mtime을 직접 읽어 정확한 값으로 등록합니다.
|
|
10
9
|
*/
|
|
11
10
|
export async function trackWritten(filePath: AbsolutePath): Promise<void> {
|
|
12
|
-
const fileStat = await stat(filePath);
|
|
11
|
+
const fileStat = await syncerFilesystem.stat(filePath);
|
|
13
12
|
fileWrittenAt.set(filePath, fileStat.mtimeMs);
|
|
14
13
|
}
|
|
15
14
|
|
|
@@ -22,6 +21,6 @@ export async function isLastChangedByMe(filePath: AbsolutePath): Promise<boolean
|
|
|
22
21
|
if (registered === undefined) {
|
|
23
22
|
return false;
|
|
24
23
|
}
|
|
25
|
-
const fileStat = await stat(filePath);
|
|
24
|
+
const fileStat = await syncerFilesystem.stat(filePath);
|
|
26
25
|
return fileStat.mtimeMs <= registered;
|
|
27
26
|
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import {
|
|
2
|
+
constants,
|
|
3
|
+
type MakeDirectoryOptions,
|
|
4
|
+
type PathLike,
|
|
5
|
+
type RmOptions,
|
|
6
|
+
type Stats,
|
|
7
|
+
} from "node:fs";
|
|
8
|
+
import { access, mkdir, readFile, rm, stat, unlink, writeFile } from "node:fs/promises";
|
|
9
|
+
|
|
10
|
+
export type SyncerFilesystemDependencies = {
|
|
11
|
+
access(path: PathLike, mode?: number): Promise<void>;
|
|
12
|
+
mkdir(path: PathLike, options?: MakeDirectoryOptions): Promise<string | undefined>;
|
|
13
|
+
readFile(path: PathLike, encoding: BufferEncoding): Promise<string>;
|
|
14
|
+
rm(path: PathLike, options?: RmOptions): Promise<void>;
|
|
15
|
+
stat(path: PathLike): Promise<Stats>;
|
|
16
|
+
unlink(path: PathLike): Promise<void>;
|
|
17
|
+
writeFile(
|
|
18
|
+
path: PathLike,
|
|
19
|
+
data: string | NodeJS.ArrayBufferView,
|
|
20
|
+
encoding?: BufferEncoding,
|
|
21
|
+
): Promise<void>;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const defaults: SyncerFilesystemDependencies = {
|
|
25
|
+
access: (path, mode) => access(path, mode),
|
|
26
|
+
mkdir: (path, options) => mkdir(path, options),
|
|
27
|
+
readFile: (path, encoding) => readFile(path, encoding),
|
|
28
|
+
rm: (path, options) => rm(path, options),
|
|
29
|
+
stat: (path) => stat(path),
|
|
30
|
+
unlink: (path) => unlink(path),
|
|
31
|
+
writeFile: (path, data, encoding) => writeFile(path, data, encoding),
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const syncerFilesystem: SyncerFilesystemDependencies = { ...defaults };
|
|
35
|
+
|
|
36
|
+
export async function syncerFileExists(path: PathLike): Promise<boolean> {
|
|
37
|
+
try {
|
|
38
|
+
await syncerFilesystem.access(path, constants.F_OK);
|
|
39
|
+
return true;
|
|
40
|
+
} catch {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** 테스트와 임베딩 환경에서 Syncer의 파일시스템 경계를 교체합니다. */
|
|
46
|
+
export function configureSyncerFilesystem(
|
|
47
|
+
dependencies: Partial<SyncerFilesystemDependencies>,
|
|
48
|
+
): () => void {
|
|
49
|
+
const restorers: Array<() => void> = [];
|
|
50
|
+
const override = <Key extends keyof SyncerFilesystemDependencies>(key: Key): void => {
|
|
51
|
+
if (!(key in dependencies)) return;
|
|
52
|
+
|
|
53
|
+
const previousDependency = syncerFilesystem[key];
|
|
54
|
+
Object.assign(syncerFilesystem, { [key]: dependencies[key] });
|
|
55
|
+
restorers.push(() => Object.assign(syncerFilesystem, { [key]: previousDependency }));
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
override("access");
|
|
59
|
+
override("mkdir");
|
|
60
|
+
override("readFile");
|
|
61
|
+
override("rm");
|
|
62
|
+
override("stat");
|
|
63
|
+
override("unlink");
|
|
64
|
+
override("writeFile");
|
|
65
|
+
|
|
66
|
+
let configured = true;
|
|
67
|
+
return () => {
|
|
68
|
+
if (!configured) return;
|
|
69
|
+
configured = false;
|
|
70
|
+
|
|
71
|
+
for (const restore of restorers) restore();
|
|
72
|
+
};
|
|
73
|
+
}
|
|
@@ -11,6 +11,7 @@ import { globAsync } from "../utils/async-utils";
|
|
|
11
11
|
import { importMembers } from "../utils/esm-utils";
|
|
12
12
|
import { runtimePath } from "../utils/path-utils";
|
|
13
13
|
import { type AbsolutePath } from "../utils/path-utils";
|
|
14
|
+
import { isFunctionValue, isObjectValue } from "../utils/runtime-value";
|
|
14
15
|
import { readApisFromFile } from "./api-parser";
|
|
15
16
|
|
|
16
17
|
export type LoadedApis = ExtendedApi[];
|
|
@@ -35,7 +36,10 @@ export async function loadApis(): Promise<LoadedApis> {
|
|
|
35
36
|
Sonamu.apiRootPath,
|
|
36
37
|
"src/application/**/*.{model,frame}.ts", // !! runtimePath 안 씀 주의 !!
|
|
37
38
|
);
|
|
38
|
-
const modelPaths =
|
|
39
|
+
const modelPaths =
|
|
40
|
+
/* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ (await globAsync(
|
|
41
|
+
modelPathsPattern,
|
|
42
|
+
)) as AbsolutePath[];
|
|
39
43
|
|
|
40
44
|
const apis: LoadedApis = [];
|
|
41
45
|
for (const filePath of modelPaths) {
|
|
@@ -125,16 +129,16 @@ export async function loadWorkflows() {
|
|
|
125
129
|
importedMembers
|
|
126
130
|
.filter(({ value }) => {
|
|
127
131
|
return (
|
|
128
|
-
|
|
132
|
+
isObjectValue(value) &&
|
|
129
133
|
value !== null &&
|
|
130
134
|
"type" in value &&
|
|
131
135
|
value.type === "workflow" &&
|
|
132
136
|
"fn" in value &&
|
|
133
|
-
|
|
137
|
+
isFunctionValue(value.fn)
|
|
134
138
|
);
|
|
135
139
|
})
|
|
136
140
|
.map(({ value }) => {
|
|
137
|
-
return value as WorkflowMetadata;
|
|
141
|
+
return /* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ value as WorkflowMetadata;
|
|
138
142
|
}),
|
|
139
143
|
);
|
|
140
144
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import assert from "assert";
|
|
2
|
-
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
3
2
|
import path, { dirname } from "path";
|
|
4
3
|
|
|
5
4
|
import chalk from "chalk";
|
|
@@ -10,10 +9,12 @@ import { AlreadyProcessedException } from "../exceptions/so-exceptions";
|
|
|
10
9
|
import { Naite } from "../naite/naite";
|
|
11
10
|
import { isTest } from "../utils/controller";
|
|
12
11
|
import { formatCode } from "../utils/formatter";
|
|
13
|
-
import { copyFileWithReplaceCoreToShared, exists } from "../utils/fs-utils";
|
|
14
12
|
import { type AbsolutePath } from "../utils/path-utils";
|
|
13
|
+
import { isObjectValue } from "../utils/runtime-value";
|
|
15
14
|
import { generateTemplate } from "./code-generator";
|
|
15
|
+
import { copyFileWithReplaceCoreToShared } from "./file-copy";
|
|
16
16
|
import { trackWritten } from "./file-tracking";
|
|
17
|
+
import { syncerFileExists, syncerFilesystem } from "./filesystem-dependencies";
|
|
17
18
|
|
|
18
19
|
// web/.sonamu.env 에 현재 설정값 저장
|
|
19
20
|
export async function actionSyncConfig() {
|
|
@@ -22,8 +23,11 @@ export async function actionSyncConfig() {
|
|
|
22
23
|
|
|
23
24
|
Naite.t("actionSyncConfig", { content });
|
|
24
25
|
await Promise.all([
|
|
25
|
-
...Sonamu.config.sync.targets.map(
|
|
26
|
-
|
|
26
|
+
...Sonamu.config.sync.targets.map((target) => {
|
|
27
|
+
return syncerFilesystem.writeFile(
|
|
28
|
+
path.join(Sonamu.appRootPath, target, ".sonamu.env"),
|
|
29
|
+
content,
|
|
30
|
+
);
|
|
27
31
|
}),
|
|
28
32
|
generateTemplate("generated_sso", {}, { overwrite: true }),
|
|
29
33
|
]);
|
|
@@ -88,6 +92,30 @@ export async function actionGenerateHttps(): Promise<AbsolutePath> {
|
|
|
88
92
|
return res;
|
|
89
93
|
}
|
|
90
94
|
|
|
95
|
+
/**
|
|
96
|
+
* 최종 REST caster를 담는 API 전용 validator registry를 재생성합니다.
|
|
97
|
+
*/
|
|
98
|
+
export async function actionGenerateHttpValidators(): Promise<AbsolutePath> {
|
|
99
|
+
const registryPath =
|
|
100
|
+
/* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ path.join(
|
|
101
|
+
Sonamu.apiRootPath,
|
|
102
|
+
"src/application/sonamu.validators.generated.ts",
|
|
103
|
+
) as AbsolutePath;
|
|
104
|
+
const policy = Sonamu.config.validation?.zodCompiler;
|
|
105
|
+
const isAot = isObjectValue(policy) && policy !== null && policy.api === "aot";
|
|
106
|
+
if (!isAot) {
|
|
107
|
+
// opt-out/JIT 전환 뒤 AOT compile import가 애플리케이션에 남지 않도록 산출물도 함께 정리합니다.
|
|
108
|
+
if (await syncerFileExists(registryPath)) {
|
|
109
|
+
await syncerFilesystem.unlink(registryPath);
|
|
110
|
+
}
|
|
111
|
+
return registryPath;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const [generatedPath] = await generateTemplate("http_validators", {}, { overwrite: true });
|
|
115
|
+
assert(generatedPath);
|
|
116
|
+
return generatedPath;
|
|
117
|
+
}
|
|
118
|
+
|
|
91
119
|
/**
|
|
92
120
|
* queries.generated.ts 재생성합니다.
|
|
93
121
|
* @returns 생성된 파일 경로 배열.
|
|
@@ -137,8 +165,8 @@ export async function actionSyncFilesToTargets(tsPaths: AbsolutePath[]): Promise
|
|
|
137
165
|
.replace(`/${apiDir}/`, `/${target}/`)
|
|
138
166
|
.replace("/application/", "/services/");
|
|
139
167
|
const dir = dirname(dst);
|
|
140
|
-
if (!(await
|
|
141
|
-
await mkdir(dir, { recursive: true });
|
|
168
|
+
if (!(await syncerFileExists(dir))) {
|
|
169
|
+
await syncerFilesystem.mkdir(dir, { recursive: true });
|
|
142
170
|
}
|
|
143
171
|
const syncHeader = [
|
|
144
172
|
"/**",
|
|
@@ -147,7 +175,9 @@ export async function actionSyncFilesToTargets(tsPaths: AbsolutePath[]): Promise
|
|
|
147
175
|
" */",
|
|
148
176
|
].join("\n");
|
|
149
177
|
await copyFileWithReplaceCoreToShared(realSrc, dst, syncHeader);
|
|
150
|
-
await trackWritten(
|
|
178
|
+
await trackWritten(
|
|
179
|
+
/* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ dst as AbsolutePath,
|
|
180
|
+
);
|
|
151
181
|
!isTest() &&
|
|
152
182
|
console.log(
|
|
153
183
|
chalk.bold("Copied: ") + chalk.blue(dst.replace(`${Sonamu.appRootPath}/`, "")),
|
|
@@ -174,7 +204,9 @@ export async function actionCopySharedToTargetsIfNotExists(): Promise<void> {
|
|
|
174
204
|
import.meta.dirname.replace("/dist/", "/src/"),
|
|
175
205
|
"../dict/utils.ts",
|
|
176
206
|
);
|
|
177
|
-
const dictUtilsCode = (await
|
|
207
|
+
const dictUtilsCode = (await syncerFileExists(dictUtilsPath))
|
|
208
|
+
? await syncerFilesystem.readFile(dictUtilsPath, "utf-8")
|
|
209
|
+
: "";
|
|
178
210
|
|
|
179
211
|
// 특정 변수 치환을 위해서 사용합니다.
|
|
180
212
|
const convertMap = {
|
|
@@ -192,16 +224,16 @@ export async function actionCopySharedToTargetsIfNotExists(): Promise<void> {
|
|
|
192
224
|
import.meta.dirname.replace("/dist/", "/src/"),
|
|
193
225
|
`../shared/${target}.shared.ts.txt`,
|
|
194
226
|
);
|
|
195
|
-
if (!(await
|
|
227
|
+
if (!(await syncerFileExists(srcPath))) {
|
|
196
228
|
continue;
|
|
197
229
|
}
|
|
198
|
-
if (!(await
|
|
230
|
+
if (!(await syncerFileExists(path.join(Sonamu.appRootPath, target)))) {
|
|
199
231
|
throw new Error(
|
|
200
232
|
`Tried to copy sonamu.shared.ts to target '${target}' but the target directory does not exist. Please check your project directory structure.`,
|
|
201
233
|
);
|
|
202
234
|
}
|
|
203
235
|
|
|
204
|
-
const fullText = await readFile(srcPath, "utf-8");
|
|
236
|
+
const fullText = await syncerFilesystem.readFile(srcPath, "utf-8");
|
|
205
237
|
const convertedText = Object.entries(convertMap).reduce(
|
|
206
238
|
(acc, [key, value]) => acc.replace(`$[[${key}]]`, value),
|
|
207
239
|
fullText,
|
|
@@ -211,8 +243,8 @@ export async function actionCopySharedToTargetsIfNotExists(): Promise<void> {
|
|
|
211
243
|
const destPath = path.join(Sonamu.appRootPath, target, "src/services/sonamu.shared.ts");
|
|
212
244
|
|
|
213
245
|
// 정말 혹시나지만 target 디렉토리는 있어도 src/services 디렉토리는 없을 수 있으므로 미리 생성해줍니다.
|
|
214
|
-
if (!(await
|
|
215
|
-
await mkdir(path.dirname(destPath), { recursive: true });
|
|
246
|
+
if (!(await syncerFileExists(path.dirname(destPath)))) {
|
|
247
|
+
await syncerFilesystem.mkdir(path.dirname(destPath), { recursive: true });
|
|
216
248
|
console.warn(`Created directory '${path.dirname(destPath)}' because it did not exist.`);
|
|
217
249
|
}
|
|
218
250
|
|
|
@@ -221,11 +253,11 @@ export async function actionCopySharedToTargetsIfNotExists(): Promise<void> {
|
|
|
221
253
|
// 최초 1회만 생성하고 이후에는 덮어쓰지 않습니다.
|
|
222
254
|
// 템플릿 내용($[[dictUtils]] 등)이 변경되었을 때 반영이 필요하면,
|
|
223
255
|
// 해당 파일을 삭제한 뒤 `pnpm sonamu sync`로 재생성하면 됩니다.
|
|
224
|
-
if (await
|
|
256
|
+
if (await syncerFileExists(destPath)) {
|
|
225
257
|
continue;
|
|
226
258
|
}
|
|
227
259
|
|
|
228
|
-
await writeFile(destPath, await formatCode(convertedText, destPath));
|
|
260
|
+
await syncerFilesystem.writeFile(destPath, await formatCode(convertedText, destPath));
|
|
229
261
|
!isTest() &&
|
|
230
262
|
console.log(chalk.bold("Copied: ") + chalk.blue(path.relative(Sonamu.appRootPath, destPath)));
|
|
231
263
|
}
|
|
@@ -244,7 +276,11 @@ export async function actionSyncSonamuDictionary(): Promise<void> {
|
|
|
244
276
|
const { targets } = Sonamu.config.sync;
|
|
245
277
|
const i18nConfig = Sonamu.config.i18n;
|
|
246
278
|
|
|
247
|
-
const targetList =
|
|
279
|
+
const targetList =
|
|
280
|
+
/* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ [
|
|
281
|
+
"api",
|
|
282
|
+
...targets,
|
|
283
|
+
] as ("api" | "web" | "app")[];
|
|
248
284
|
|
|
249
285
|
const apiI18nDir = path.join(Sonamu.appRootPath, Sonamu.config.api.dir, "src/i18n");
|
|
250
286
|
|
|
@@ -273,7 +309,7 @@ async function syncLocaleFiles(
|
|
|
273
309
|
const targetI18nDir = path.join(Sonamu.appRootPath, target, "src/i18n");
|
|
274
310
|
|
|
275
311
|
// 디렉토리가 없으면 생성
|
|
276
|
-
await mkdir(targetI18nDir, { recursive: true });
|
|
312
|
+
await syncerFilesystem.mkdir(targetI18nDir, { recursive: true });
|
|
277
313
|
|
|
278
314
|
for (const locale of locales) {
|
|
279
315
|
const sourceFile = path.join(apiI18nDir, `${locale}.ts`);
|
|
@@ -286,7 +322,9 @@ async function syncLocaleFiles(
|
|
|
286
322
|
" */",
|
|
287
323
|
].join("\n");
|
|
288
324
|
await copyFileWithReplaceCoreToShared(sourceFile, targetFile, syncHeader);
|
|
289
|
-
await trackWritten(
|
|
325
|
+
await trackWritten(
|
|
326
|
+
/* SAFETY: TypeScript AST 파싱과 동기화 입력 계약이 이 값의 타입을 보장한다. */ targetFile as AbsolutePath,
|
|
327
|
+
);
|
|
290
328
|
!isTest() &&
|
|
291
329
|
console.log(chalk.bold("Copied: ") + chalk.cyan(`${target}/src/i18n/${locale}.ts`));
|
|
292
330
|
}
|