@lenne.tech/nest-server 12.0.0 → 12.1.0
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/.claude/rules/architecture.md +6 -1
- package/.claude/rules/better-auth.md +46 -0
- package/.claude/rules/configurable-features.md +3 -2
- package/.claude/rules/package-management.md +24 -2
- package/.claude/rules/persistence.md +100 -0
- package/.claude/rules/role-system.md +9 -0
- package/.claude/rules/testing.md +116 -18
- package/CLAUDE.md +21 -2
- package/FRAMEWORK-API.md +6 -4
- package/README.md +106 -34
- package/dist/core/common/decorators/unified-field.decorator.d.ts +2 -1
- package/dist/core/common/decorators/unified-field.decorator.js +4 -1
- package/dist/core/common/decorators/unified-field.decorator.js.map +1 -1
- package/dist/core/common/filters/mongoose-cast-error.filter.d.ts +7 -5
- package/dist/core/common/filters/mongoose-cast-error.filter.js +3 -2
- package/dist/core/common/filters/mongoose-cast-error.filter.js.map +1 -1
- package/dist/core/common/helpers/db.helper.d.ts +2 -1
- package/dist/core/common/helpers/db.helper.js +32 -26
- package/dist/core/common/helpers/db.helper.js.map +1 -1
- package/dist/core/common/helpers/decorator.helper.d.ts +1 -1
- package/dist/core/common/helpers/filter.helper.d.ts +2 -1
- package/dist/core/common/helpers/filter.helper.js.map +1 -1
- package/dist/core/common/helpers/gridfs.helper.d.ts +4 -4
- package/dist/core/common/helpers/gridfs.helper.js +14 -6
- package/dist/core/common/helpers/gridfs.helper.js.map +1 -1
- package/dist/core/common/helpers/id.helper.d.ts +4 -1
- package/dist/core/common/helpers/id.helper.js +10 -4
- package/dist/core/common/helpers/id.helper.js.map +1 -1
- package/dist/core/common/helpers/model.helper.js +5 -5
- package/dist/core/common/helpers/model.helper.js.map +1 -1
- package/dist/core/common/helpers/service.helper.js +3 -3
- package/dist/core/common/helpers/service.helper.js.map +1 -1
- package/dist/core/common/interfaces/server-options.interface.d.ts +18 -2
- package/dist/core/common/interfaces/service-options.interface.d.ts +2 -2
- package/dist/core/common/models/core-persistence.model.d.ts +1 -2
- package/dist/core/common/models/core-persistence.model.js +3 -3
- package/dist/core/common/models/core-persistence.model.js.map +1 -1
- package/dist/core/common/persistence/core-persistence.lifecycle.d.ts +9 -0
- package/dist/core/common/persistence/core-persistence.lifecycle.js +38 -0
- package/dist/core/common/persistence/core-persistence.lifecycle.js.map +1 -0
- package/dist/core/common/persistence/core-persistence.module.d.ts +9 -0
- package/dist/core/common/persistence/core-persistence.module.js +76 -0
- package/dist/core/common/persistence/core-persistence.module.js.map +1 -0
- package/dist/core/common/persistence/data-source.config.d.ts +33 -0
- package/dist/core/common/persistence/data-source.config.js +151 -0
- package/dist/core/common/persistence/data-source.config.js.map +1 -0
- package/dist/core/common/persistence/data-source.runtime.d.ts +45 -0
- package/dist/core/common/persistence/data-source.runtime.js +278 -0
- package/dist/core/common/persistence/data-source.runtime.js.map +1 -0
- package/dist/core/common/persistence/data-store.interface.d.ts +73 -0
- package/dist/core/common/persistence/data-store.interface.js +2 -0
- package/dist/core/common/persistence/data-store.interface.js.map +1 -0
- package/dist/core/common/persistence/expiry-sweep.d.ts +12 -0
- package/dist/core/common/persistence/expiry-sweep.js +55 -0
- package/dist/core/common/persistence/expiry-sweep.js.map +1 -0
- package/dist/core/common/persistence/id-format.d.ts +3 -0
- package/dist/core/common/persistence/id-format.js +21 -0
- package/dist/core/common/persistence/id-format.js.map +1 -0
- package/dist/core/common/persistence/infrastructure-locks.d.ts +13 -0
- package/dist/core/common/persistence/infrastructure-locks.js +35 -0
- package/dist/core/common/persistence/infrastructure-locks.js.map +1 -0
- package/dist/core/common/persistence/inject-store.decorator.d.ts +1 -0
- package/dist/core/common/persistence/inject-store.decorator.js +6 -0
- package/dist/core/common/persistence/inject-store.decorator.js.map +1 -0
- package/dist/core/common/persistence/lock-store.interface.d.ts +5 -0
- package/dist/core/common/persistence/lock-store.interface.js +2 -0
- package/dist/core/common/persistence/lock-store.interface.js.map +1 -0
- package/dist/core/common/persistence/model-descriptor.interface.d.ts +36 -0
- package/dist/core/common/persistence/model-descriptor.interface.js +2 -0
- package/dist/core/common/persistence/model-descriptor.interface.js.map +1 -0
- package/dist/core/common/persistence/model-metadata.registry.d.ts +14 -0
- package/dist/core/common/persistence/model-metadata.registry.js +194 -0
- package/dist/core/common/persistence/model-metadata.registry.js.map +1 -0
- package/dist/core/common/persistence/mongo/collection-name.d.ts +2 -0
- package/dist/core/common/persistence/mongo/collection-name.js +73 -0
- package/dist/core/common/persistence/mongo/collection-name.js.map +1 -0
- package/dist/core/common/persistence/mongo/declared-schema.view.d.ts +11 -0
- package/dist/core/common/persistence/mongo/declared-schema.view.js +292 -0
- package/dist/core/common/persistence/mongo/declared-schema.view.js.map +1 -0
- package/dist/core/common/persistence/mongo/hex-object-id.d.ts +13 -0
- package/dist/core/common/persistence/mongo/hex-object-id.js +54 -0
- package/dist/core/common/persistence/mongo/hex-object-id.js.map +1 -0
- package/dist/core/common/persistence/mongo/model-declarations.d.ts +35 -0
- package/dist/core/common/persistence/mongo/model-declarations.js +80 -0
- package/dist/core/common/persistence/mongo/model-declarations.js.map +1 -0
- package/dist/core/common/persistence/mongo/mongo-packages.d.ts +15 -0
- package/dist/core/common/persistence/mongo/mongo-packages.js +66 -0
- package/dist/core/common/persistence/mongo/mongo-packages.js.map +1 -0
- package/dist/core/common/persistence/mongo/mongoose-compat.d.ts +22 -0
- package/dist/core/common/persistence/mongo/mongoose-compat.js +65 -0
- package/dist/core/common/persistence/mongo/mongoose-compat.js.map +1 -0
- package/dist/core/common/persistence/mongo/no-mongo-connection.module.d.ts +2 -0
- package/dist/core/common/persistence/mongo/no-mongo-connection.module.js +19 -0
- package/dist/core/common/persistence/mongo/no-mongo-connection.module.js.map +1 -0
- package/dist/core/common/persistence/mongo-lock-store.d.ts +21 -0
- package/dist/core/common/persistence/mongo-lock-store.js +72 -0
- package/dist/core/common/persistence/mongo-lock-store.js.map +1 -0
- package/dist/core/common/persistence/mongoose-data-store.d.ts +33 -0
- package/dist/core/common/persistence/mongoose-data-store.js +187 -0
- package/dist/core/common/persistence/mongoose-data-store.js.map +1 -0
- package/dist/core/common/persistence/neutral-populate.d.ts +6 -0
- package/dist/core/common/persistence/neutral-populate.js +72 -0
- package/dist/core/common/persistence/neutral-populate.js.map +1 -0
- package/dist/core/common/persistence/persisted-model.decorator.d.ts +6 -0
- package/dist/core/common/persistence/persisted-model.decorator.js +24 -0
- package/dist/core/common/persistence/persisted-model.decorator.js.map +1 -0
- package/dist/core/common/persistence/persistence-runtime.registry.d.ts +61 -0
- package/dist/core/common/persistence/persistence-runtime.registry.js +47 -0
- package/dist/core/common/persistence/persistence-runtime.registry.js.map +1 -0
- package/dist/core/common/persistence/persistence.tokens.d.ts +1 -0
- package/dist/core/common/persistence/persistence.tokens.js +4 -0
- package/dist/core/common/persistence/persistence.tokens.js.map +1 -0
- package/dist/core/common/persistence/policies/audit.policy.d.ts +8 -0
- package/dist/core/common/persistence/policies/audit.policy.js +37 -0
- package/dist/core/common/persistence/policies/audit.policy.js.map +1 -0
- package/dist/core/common/persistence/policies/password.policy.d.ts +3 -0
- package/dist/core/common/persistence/policies/password.policy.js +46 -0
- package/dist/core/common/persistence/policies/password.policy.js.map +1 -0
- package/dist/core/common/persistence/policies/role-guard.policy.d.ts +3 -0
- package/dist/core/common/persistence/policies/role-guard.policy.js +46 -0
- package/dist/core/common/persistence/policies/role-guard.policy.js.map +1 -0
- package/dist/core/common/persistence/policies/system-role.policy.d.ts +5 -0
- package/dist/core/common/persistence/policies/system-role.policy.js +46 -0
- package/dist/core/common/persistence/policies/system-role.policy.js.map +1 -0
- package/dist/core/common/persistence/policies/tenant.policy.d.ts +19 -0
- package/dist/core/common/persistence/policies/tenant.policy.js +120 -0
- package/dist/core/common/persistence/policies/tenant.policy.js.map +1 -0
- package/dist/core/common/persistence/routed-model.guard.d.ts +4 -0
- package/dist/core/common/persistence/routed-model.guard.js +73 -0
- package/dist/core/common/persistence/routed-model.guard.js.map +1 -0
- package/dist/core/common/persistence/sql/mysql/mysql-data-store.d.ts +46 -0
- package/dist/core/common/persistence/sql/mysql/mysql-data-store.js +350 -0
- package/dist/core/common/persistence/sql/mysql/mysql-data-store.js.map +1 -0
- package/dist/core/common/persistence/sql/mysql/mysql-executor.d.ts +13 -0
- package/dist/core/common/persistence/sql/mysql/mysql-executor.js +194 -0
- package/dist/core/common/persistence/sql/mysql/mysql-executor.js.map +1 -0
- package/dist/core/common/persistence/sql/mysql/mysql-lock-store.d.ts +11 -0
- package/dist/core/common/persistence/sql/mysql/mysql-lock-store.js +55 -0
- package/dist/core/common/persistence/sql/mysql/mysql-lock-store.js.map +1 -0
- package/dist/core/common/persistence/sql/mysql/mysql-schema.compiler.d.ts +36 -0
- package/dist/core/common/persistence/sql/mysql/mysql-schema.compiler.js +288 -0
- package/dist/core/common/persistence/sql/mysql/mysql-schema.compiler.js.map +1 -0
- package/dist/core/common/persistence/sql/mysql/mysql-schema.migrator.d.ts +19 -0
- package/dist/core/common/persistence/sql/mysql/mysql-schema.migrator.js +328 -0
- package/dist/core/common/persistence/sql/mysql/mysql-schema.migrator.js.map +1 -0
- package/dist/core/common/persistence/sql/mysql/mysql-session.d.ts +13 -0
- package/dist/core/common/persistence/sql/mysql/mysql-session.js +85 -0
- package/dist/core/common/persistence/sql/mysql/mysql-session.js.map +1 -0
- package/dist/core/common/persistence/sql/mysql/mysql-update.compiler.d.ts +9 -0
- package/dist/core/common/persistence/sql/mysql/mysql-update.compiler.js +264 -0
- package/dist/core/common/persistence/sql/mysql/mysql-update.compiler.js.map +1 -0
- package/dist/core/common/persistence/sql/mysql/mysql-where.compiler.d.ts +20 -0
- package/dist/core/common/persistence/sql/mysql/mysql-where.compiler.js +519 -0
- package/dist/core/common/persistence/sql/mysql/mysql-where.compiler.js.map +1 -0
- package/dist/core/common/persistence/sql/postgres/postgres-lock-store.d.ts +11 -0
- package/dist/core/common/persistence/sql/postgres/postgres-lock-store.js +44 -0
- package/dist/core/common/persistence/sql/postgres/postgres-lock-store.js.map +1 -0
- package/dist/core/common/persistence/sql/postgres/postgres-schema.compiler.d.ts +42 -0
- package/dist/core/common/persistence/sql/postgres/postgres-schema.compiler.js +220 -0
- package/dist/core/common/persistence/sql/postgres/postgres-schema.compiler.js.map +1 -0
- package/dist/core/common/persistence/sql/postgres/postgres-schema.migrator.d.ts +12 -0
- package/dist/core/common/persistence/sql/postgres/postgres-schema.migrator.js +315 -0
- package/dist/core/common/persistence/sql/postgres/postgres-schema.migrator.js.map +1 -0
- package/dist/core/common/persistence/sql/postgres/postgres-update.compiler.d.ts +5 -0
- package/dist/core/common/persistence/sql/postgres/postgres-update.compiler.js +225 -0
- package/dist/core/common/persistence/sql/postgres/postgres-update.compiler.js.map +1 -0
- package/dist/core/common/persistence/sql/postgres/postgres-where.compiler.d.ts +13 -0
- package/dist/core/common/persistence/sql/postgres/postgres-where.compiler.js +484 -0
- package/dist/core/common/persistence/sql/postgres/postgres-where.compiler.js.map +1 -0
- package/dist/core/common/persistence/sql/sql-cast.d.ts +2 -0
- package/dist/core/common/persistence/sql/sql-cast.js +194 -0
- package/dist/core/common/persistence/sql/sql-cast.js.map +1 -0
- package/dist/core/common/persistence/sql/sql-data-store.d.ts +79 -0
- package/dist/core/common/persistence/sql/sql-data-store.js +592 -0
- package/dist/core/common/persistence/sql/sql-data-store.js.map +1 -0
- package/dist/core/common/persistence/sql/sql-dialect.d.ts +20 -0
- package/dist/core/common/persistence/sql/sql-dialect.js +38 -0
- package/dist/core/common/persistence/sql/sql-dialect.js.map +1 -0
- package/dist/core/common/persistence/sql/sql-errors.d.ts +17 -0
- package/dist/core/common/persistence/sql/sql-errors.js +25 -0
- package/dist/core/common/persistence/sql/sql-errors.js.map +1 -0
- package/dist/core/common/persistence/sql/sql-executor.factory.d.ts +11 -0
- package/dist/core/common/persistence/sql/sql-executor.factory.js +199 -0
- package/dist/core/common/persistence/sql/sql-executor.factory.js.map +1 -0
- package/dist/core/common/persistence/sql/sql-executor.interface.d.ts +32 -0
- package/dist/core/common/persistence/sql/sql-executor.interface.js +2 -0
- package/dist/core/common/persistence/sql/sql-executor.interface.js.map +1 -0
- package/dist/core/common/persistence/sql/sql-naming.d.ts +15 -0
- package/dist/core/common/persistence/sql/sql-naming.js +90 -0
- package/dist/core/common/persistence/sql/sql-naming.js.map +1 -0
- package/dist/core/common/persistence/sql/sql-schema.shared.d.ts +25 -0
- package/dist/core/common/persistence/sql/sql-schema.shared.js +69 -0
- package/dist/core/common/persistence/sql/sql-schema.shared.js.map +1 -0
- package/dist/core/common/persistence/sql/sql-session.d.ts +6 -0
- package/dist/core/common/persistence/sql/sql-session.js +78 -0
- package/dist/core/common/persistence/sql/sql-session.js.map +1 -0
- package/dist/core/common/persistence/sql/where-shared.d.ts +18 -0
- package/dist/core/common/persistence/sql/where-shared.js +93 -0
- package/dist/core/common/persistence/sql/where-shared.js.map +1 -0
- package/dist/core/common/persistence/store-guards.d.ts +10 -0
- package/dist/core/common/persistence/store-guards.js +49 -0
- package/dist/core/common/persistence/store-guards.js.map +1 -0
- package/dist/core/common/persistence/store-upsert.d.ts +2 -0
- package/dist/core/common/persistence/store-upsert.js +20 -0
- package/dist/core/common/persistence/store-upsert.js.map +1 -0
- package/dist/core/common/persistence/unavailable-store.d.ts +2 -0
- package/dist/core/common/persistence/unavailable-store.js +53 -0
- package/dist/core/common/persistence/unavailable-store.js.map +1 -0
- package/dist/core/common/persistence/unsupported-capability.error.d.ts +3 -0
- package/dist/core/common/persistence/unsupported-capability.error.js +4 -0
- package/dist/core/common/persistence/unsupported-capability.error.js.map +1 -0
- package/dist/core/common/plugins/mongoose-audit-fields.plugin.js +24 -68
- package/dist/core/common/plugins/mongoose-audit-fields.plugin.js.map +1 -1
- package/dist/core/common/plugins/mongoose-id.plugin.js +3 -0
- package/dist/core/common/plugins/mongoose-id.plugin.js.map +1 -1
- package/dist/core/common/plugins/mongoose-password.plugin.d.ts +1 -3
- package/dist/core/common/plugins/mongoose-password.plugin.js +2 -45
- package/dist/core/common/plugins/mongoose-password.plugin.js.map +1 -1
- package/dist/core/common/plugins/mongoose-role-guard.plugin.js +5 -46
- package/dist/core/common/plugins/mongoose-role-guard.plugin.js.map +1 -1
- package/dist/core/common/plugins/mongoose-system-role.plugin.js +2 -43
- package/dist/core/common/plugins/mongoose-system-role.plugin.js.map +1 -1
- package/dist/core/common/plugins/mongoose-tenant.plugin.js +10 -70
- package/dist/core/common/plugins/mongoose-tenant.plugin.js.map +1 -1
- package/dist/core/common/scalars/upload.scalar.js +1 -1
- package/dist/core/common/scalars/upload.scalar.js.map +1 -1
- package/dist/core/common/services/core-cron-jobs.initializer.js +1 -1
- package/dist/core/common/services/core-cron-jobs.initializer.js.map +1 -1
- package/dist/core/common/services/core-cron-jobs.service.d.ts +1 -0
- package/dist/core/common/services/core-cron-jobs.service.js +23 -14
- package/dist/core/common/services/core-cron-jobs.service.js.map +1 -1
- package/dist/core/common/services/crud.service.d.ts +4 -1
- package/dist/core/common/services/crud.service.js +132 -23
- package/dist/core/common/services/crud.service.js.map +1 -1
- package/dist/core/common/services/model-doc.service.js +1 -1
- package/dist/core/common/services/model-doc.service.js.map +1 -1
- package/dist/core/common/services/module.service.d.ts +9 -2
- package/dist/core/common/services/module.service.js +51 -6
- package/dist/core/common/services/module.service.js.map +1 -1
- package/dist/core/common/types/field-selection.type.d.ts +1 -1
- package/dist/core/common/types/id.type.d.ts +4 -4
- package/dist/core/common/types/object-id-like.type.d.ts +3 -0
- package/dist/core/common/types/object-id-like.type.js +2 -0
- package/dist/core/common/types/object-id-like.type.js.map +1 -0
- package/dist/core/common/types/populate-config.type.d.ts +1 -1
- package/dist/core/common/types/string-or-object-id.type.d.ts +2 -2
- package/dist/core/modules/ai/core-ai.constants.d.ts +4 -0
- package/dist/core/modules/ai/core-ai.constants.js +4 -0
- package/dist/core/modules/ai/core-ai.constants.js.map +1 -1
- package/dist/core/modules/ai/core-ai.module.js +21 -17
- package/dist/core/modules/ai/core-ai.module.js.map +1 -1
- package/dist/core/modules/ai/models/core-ai-budget-limit.model.d.ts +2 -92
- package/dist/core/modules/ai/models/core-ai-budget-limit.model.js +1 -1
- package/dist/core/modules/ai/models/core-ai-budget-limit.model.js.map +1 -1
- package/dist/core/modules/ai/models/core-ai-connection-preference.model.d.ts +2 -87
- package/dist/core/modules/ai/models/core-ai-connection-preference.model.js +1 -1
- package/dist/core/modules/ai/models/core-ai-connection-preference.model.js.map +1 -1
- package/dist/core/modules/ai/models/core-ai-connection.model.d.ts +2 -177
- package/dist/core/modules/ai/models/core-ai-connection.model.js +1 -1
- package/dist/core/modules/ai/models/core-ai-connection.model.js.map +1 -1
- package/dist/core/modules/ai/models/core-ai-conversation.model.d.ts +2 -92
- package/dist/core/modules/ai/models/core-ai-conversation.model.js +3 -4
- package/dist/core/modules/ai/models/core-ai-conversation.model.js.map +1 -1
- package/dist/core/modules/ai/models/core-ai-interaction.model.d.ts +2 -120
- package/dist/core/modules/ai/models/core-ai-interaction.model.js +2 -3
- package/dist/core/modules/ai/models/core-ai-interaction.model.js.map +1 -1
- package/dist/core/modules/ai/models/core-ai-mcp-oauth.models.d.ts +3 -0
- package/dist/core/modules/ai/models/core-ai-mcp-oauth.models.js +21 -0
- package/dist/core/modules/ai/models/core-ai-mcp-oauth.models.js.map +1 -0
- package/dist/core/modules/ai/models/core-ai-mode.model.d.ts +2 -102
- package/dist/core/modules/ai/models/core-ai-mode.model.js +1 -1
- package/dist/core/modules/ai/models/core-ai-mode.model.js.map +1 -1
- package/dist/core/modules/ai/models/core-ai-prompt-hint.model.d.ts +2 -97
- package/dist/core/modules/ai/models/core-ai-prompt-hint.model.js +1 -1
- package/dist/core/modules/ai/models/core-ai-prompt-hint.model.js.map +1 -1
- package/dist/core/modules/ai/models/core-ai-prompt.model.d.ts +2 -112
- package/dist/core/modules/ai/models/core-ai-prompt.model.js +1 -1
- package/dist/core/modules/ai/models/core-ai-prompt.model.js.map +1 -1
- package/dist/core/modules/ai/models/core-ai-slot.model.d.ts +2 -112
- package/dist/core/modules/ai/models/core-ai-slot.model.js +1 -1
- package/dist/core/modules/ai/models/core-ai-slot.model.js.map +1 -1
- package/dist/core/modules/ai/models/core-ai-tool-grant.model.d.ts +2 -97
- package/dist/core/modules/ai/models/core-ai-tool-grant.model.js +1 -1
- package/dist/core/modules/ai/models/core-ai-tool-grant.model.js.map +1 -1
- package/dist/core/modules/ai/models/core-ai-tool-policy.model.d.ts +2 -103
- package/dist/core/modules/ai/models/core-ai-tool-policy.model.js +1 -1
- package/dist/core/modules/ai/models/core-ai-tool-policy.model.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-budget.service.d.ts +3 -1
- package/dist/core/modules/ai/services/core-ai-budget.service.js +15 -5
- package/dist/core/modules/ai/services/core-ai-budget.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-connection-preference.service.d.ts +1 -1
- package/dist/core/modules/ai/services/core-ai-connection-preference.service.js +6 -10
- package/dist/core/modules/ai/services/core-ai-connection-preference.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-connection.service.d.ts +1 -1
- package/dist/core/modules/ai/services/core-ai-connection.service.js +20 -42
- package/dist/core/modules/ai/services/core-ai-connection.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-conversation.service.d.ts +1 -1
- package/dist/core/modules/ai/services/core-ai-conversation.service.js +28 -29
- package/dist/core/modules/ai/services/core-ai-conversation.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-interaction.service.d.ts +1 -1
- package/dist/core/modules/ai/services/core-ai-interaction.service.js +3 -4
- package/dist/core/modules/ai/services/core-ai-interaction.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-mcp-oauth.service.d.ts +8 -0
- package/dist/core/modules/ai/services/core-ai-mcp-oauth.service.js +70 -18
- package/dist/core/modules/ai/services/core-ai-mcp-oauth.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-mode.service.d.ts +1 -1
- package/dist/core/modules/ai/services/core-ai-mode.service.js +3 -7
- package/dist/core/modules/ai/services/core-ai-mode.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-prompt-hint.service.d.ts +8 -1
- package/dist/core/modules/ai/services/core-ai-prompt-hint.service.js +32 -26
- package/dist/core/modules/ai/services/core-ai-prompt-hint.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-prompt.service.d.ts +1 -1
- package/dist/core/modules/ai/services/core-ai-prompt.service.js +10 -13
- package/dist/core/modules/ai/services/core-ai-prompt.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-slot.service.d.ts +1 -1
- package/dist/core/modules/ai/services/core-ai-slot.service.js +14 -25
- package/dist/core/modules/ai/services/core-ai-slot.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-tool-grant.service.d.ts +1 -1
- package/dist/core/modules/ai/services/core-ai-tool-grant.service.js +6 -18
- package/dist/core/modules/ai/services/core-ai-tool-grant.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-tool-policy.service.d.ts +1 -1
- package/dist/core/modules/ai/services/core-ai-tool-policy.service.js +4 -8
- package/dist/core/modules/ai/services/core-ai-tool-policy.service.js.map +1 -1
- package/dist/core/modules/api-token/core-api-token.model.js +1 -1
- package/dist/core/modules/api-token/core-api-token.model.js.map +1 -1
- package/dist/core/modules/api-token/core-api-token.module.js +3 -2
- package/dist/core/modules/api-token/core-api-token.module.js.map +1 -1
- package/dist/core/modules/api-token/core-api-token.service.d.ts +8 -2
- package/dist/core/modules/api-token/core-api-token.service.js +106 -39
- package/dist/core/modules/api-token/core-api-token.service.js.map +1 -1
- package/dist/core/modules/auth/core-auth.module.js +2 -0
- package/dist/core/modules/auth/core-auth.module.js.map +1 -1
- package/dist/core/modules/auth/guards/legacy-auth-rate-limit.guard.js +1 -2
- package/dist/core/modules/auth/guards/legacy-auth-rate-limit.guard.js.map +1 -1
- package/dist/core/modules/auth/guards/role-guard.token.d.ts +1 -0
- package/dist/core/modules/auth/guards/role-guard.token.js +2 -0
- package/dist/core/modules/auth/guards/role-guard.token.js.map +1 -0
- package/dist/core/modules/auth/services/core-auth.service.js +4 -2
- package/dist/core/modules/auth/services/core-auth.service.js.map +1 -1
- package/dist/core/modules/better-auth/better-auth-sql.helper.d.ts +6 -0
- package/dist/core/modules/better-auth/better-auth-sql.helper.js +113 -0
- package/dist/core/modules/better-auth/better-auth-sql.helper.js.map +1 -0
- package/dist/core/modules/better-auth/better-auth-token.service.d.ts +3 -1
- package/dist/core/modules/better-auth/better-auth-token.service.js +15 -24
- package/dist/core/modules/better-auth/better-auth-token.service.js.map +1 -1
- package/dist/core/modules/better-auth/better-auth.config.d.ts +7 -0
- package/dist/core/modules/better-auth/better-auth.config.js +16 -5
- package/dist/core/modules/better-auth/better-auth.config.js.map +1 -1
- package/dist/core/modules/better-auth/better-auth.types.d.ts +1 -1
- package/dist/core/modules/better-auth/core-better-auth-api.middleware.d.ts +1 -0
- package/dist/core/modules/better-auth/core-better-auth-api.middleware.js +6 -1
- package/dist/core/modules/better-auth/core-better-auth-api.middleware.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth-challenge.service.js +30 -15
- package/dist/core/modules/better-auth/core-better-auth-challenge.service.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth-mongo.users.d.ts +10 -0
- package/dist/core/modules/better-auth/core-better-auth-mongo.users.js +24 -0
- package/dist/core/modules/better-auth/core-better-auth-mongo.users.js.map +1 -0
- package/dist/core/modules/better-auth/core-better-auth-sql.registry.d.ts +3 -0
- package/dist/core/modules/better-auth/core-better-auth-sql.registry.js +8 -0
- package/dist/core/modules/better-auth/core-better-auth-sql.registry.js.map +1 -0
- package/dist/core/modules/better-auth/core-better-auth-sql.store.d.ts +71 -0
- package/dist/core/modules/better-auth/core-better-auth-sql.store.js +190 -0
- package/dist/core/modules/better-auth/core-better-auth-sql.store.js.map +1 -0
- package/dist/core/modules/better-auth/core-better-auth-user.mapper.d.ts +24 -1
- package/dist/core/modules/better-auth/core-better-auth-user.mapper.js +308 -32
- package/dist/core/modules/better-auth/core-better-auth-user.mapper.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth.module.d.ts +2 -0
- package/dist/core/modules/better-auth/core-better-auth.module.js +54 -32
- package/dist/core/modules/better-auth/core-better-auth.module.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth.service.d.ts +7 -2
- package/dist/core/modules/better-auth/core-better-auth.service.js +61 -9
- package/dist/core/modules/better-auth/core-better-auth.service.js.map +1 -1
- package/dist/core/modules/file/core-file-info.model.d.ts +1 -2
- package/dist/core/modules/file/core-file-info.model.js +2 -2
- package/dist/core/modules/file/core-file-info.model.js.map +1 -1
- package/dist/core/modules/file/core-file.service.d.ts +5 -3
- package/dist/core/modules/file/core-file.service.js +16 -9
- package/dist/core/modules/file/core-file.service.js.map +1 -1
- package/dist/core/modules/file/file-metadata.helper.d.ts +1 -1
- package/dist/core/modules/file/file-metadata.helper.js +2 -2
- package/dist/core/modules/file/file-metadata.helper.js.map +1 -1
- package/dist/core/modules/file/file-metadata.models.d.ts +35 -0
- package/dist/core/modules/file/file-metadata.models.js +20 -0
- package/dist/core/modules/file/file-metadata.models.js.map +1 -0
- package/dist/core/modules/file/file-metadata.store.d.ts +6 -0
- package/dist/core/modules/file/file-metadata.store.js +77 -0
- package/dist/core/modules/file/file-metadata.store.js.map +1 -0
- package/dist/core/modules/file/file-storage.helper.d.ts +1 -0
- package/dist/core/modules/file/file-storage.helper.js +34 -0
- package/dist/core/modules/file/file-storage.helper.js.map +1 -1
- package/dist/core/modules/file/filesystem-file.helper.d.ts +1 -1
- package/dist/core/modules/file/filesystem-file.helper.js +4 -4
- package/dist/core/modules/file/filesystem-file.helper.js.map +1 -1
- package/dist/core/modules/file/s3-file.helper.d.ts +1 -1
- package/dist/core/modules/file/s3-file.helper.js +5 -5
- package/dist/core/modules/file/s3-file.helper.js.map +1 -1
- package/dist/core/modules/health-check/core-health-check.module.js +12 -2
- package/dist/core/modules/health-check/core-health-check.module.js.map +1 -1
- package/dist/core/modules/health-check/core-health-check.service.d.ts +4 -3
- package/dist/core/modules/health-check/core-health-check.service.js +26 -5
- package/dist/core/modules/health-check/core-health-check.service.js.map +1 -1
- package/dist/core/modules/hub/core-hub.controller.d.ts +1 -0
- package/dist/core/modules/hub/core-hub.controller.js +10 -0
- package/dist/core/modules/hub/core-hub.controller.js.map +1 -1
- package/dist/core/modules/hub/core-hub.service.js +1 -1
- package/dist/core/modules/hub/core-hub.service.js.map +1 -1
- package/dist/core/modules/hub/helpers/hub-client-js.helper.js +23 -0
- package/dist/core/modules/hub/helpers/hub-client-js.helper.js.map +1 -1
- package/dist/core/modules/hub/hub-action-messages.d.ts +2 -0
- package/dist/core/modules/hub/hub-action-messages.js +2 -0
- package/dist/core/modules/hub/hub-action-messages.js.map +1 -1
- package/dist/core/modules/hub/hub-nav.js +1 -0
- package/dist/core/modules/hub/hub-nav.js.map +1 -1
- package/dist/core/modules/hub/interfaces/hub-panels.interface.d.ts +17 -1
- package/dist/core/modules/hub/services/core-hub-db.service.d.ts +6 -1
- package/dist/core/modules/hub/services/core-hub-db.service.js +16 -14
- package/dist/core/modules/hub/services/core-hub-db.service.js.map +1 -1
- package/dist/core/modules/hub/services/core-hub-migrations.service.d.ts +5 -0
- package/dist/core/modules/hub/services/core-hub-migrations.service.js +74 -1
- package/dist/core/modules/hub/services/core-hub-migrations.service.js.map +1 -1
- package/dist/core/modules/hub/services/core-hub-sources.service.d.ts +2 -1
- package/dist/core/modules/hub/services/core-hub-sources.service.js +32 -0
- package/dist/core/modules/hub/services/core-hub-sources.service.js.map +1 -1
- package/dist/core/modules/hub/services/hub-query-profiler.service.js +1 -1
- package/dist/core/modules/hub/services/hub-query-profiler.service.js.map +1 -1
- package/dist/core/modules/migrate/cli/migrate-cli.d.ts +2 -0
- package/dist/core/modules/migrate/cli/migrate-cli.js +35 -1
- package/dist/core/modules/migrate/cli/migrate-cli.js.map +1 -1
- package/dist/core/modules/migrate/index.d.ts +3 -0
- package/dist/core/modules/migrate/index.js +3 -0
- package/dist/core/modules/migrate/index.js.map +1 -1
- package/dist/core/modules/migrate/migration-runner.d.ts +2 -2
- package/dist/core/modules/migrate/migration-runner.js.map +1 -1
- package/dist/core/modules/migrate/migration-state-store.interface.d.ts +16 -0
- package/dist/core/modules/migrate/migration-state-store.interface.js +2 -0
- package/dist/core/modules/migrate/migration-state-store.interface.js.map +1 -0
- package/dist/core/modules/migrate/migration.helper.d.ts +3 -2
- package/dist/core/modules/migrate/migration.helper.js +21 -6
- package/dist/core/modules/migrate/migration.helper.js.map +1 -1
- package/dist/core/modules/migrate/mongo-state-store.d.ts +5 -12
- package/dist/core/modules/migrate/mongo-state-store.js +30 -24
- package/dist/core/modules/migrate/mongo-state-store.js.map +1 -1
- package/dist/core/modules/migrate/sql-migration.helper.d.ts +4 -0
- package/dist/core/modules/migrate/sql-migration.helper.js +34 -0
- package/dist/core/modules/migrate/sql-migration.helper.js.map +1 -0
- package/dist/core/modules/migrate/sql-state-store.d.ts +24 -0
- package/dist/core/modules/migrate/sql-state-store.js +129 -0
- package/dist/core/modules/migrate/sql-state-store.js.map +1 -0
- package/dist/core/modules/system-setup/core-system-setup.service.d.ts +8 -0
- package/dist/core/modules/system-setup/core-system-setup.service.js +41 -25
- package/dist/core/modules/system-setup/core-system-setup.service.js.map +1 -1
- package/dist/core/modules/tenant/core-tenant-member.model.js +1 -1
- package/dist/core/modules/tenant/core-tenant-member.model.js.map +1 -1
- package/dist/core/modules/tenant/core-tenant-member.store.d.ts +2 -0
- package/dist/core/modules/tenant/core-tenant-member.store.js +6 -0
- package/dist/core/modules/tenant/core-tenant-member.store.js.map +1 -0
- package/dist/core/modules/tenant/core-tenant.guard.d.ts +8 -3
- package/dist/core/modules/tenant/core-tenant.guard.js +57 -28
- package/dist/core/modules/tenant/core-tenant.guard.js.map +1 -1
- package/dist/core/modules/tenant/core-tenant.module.js +3 -2
- package/dist/core/modules/tenant/core-tenant.module.js.map +1 -1
- package/dist/core/modules/tenant/core-tenant.service.d.ts +3 -1
- package/dist/core/modules/tenant/core-tenant.service.js +48 -28
- package/dist/core/modules/tenant/core-tenant.service.js.map +1 -1
- package/dist/core/modules/tus/core-tus.service.d.ts +1 -1
- package/dist/core/modules/tus/core-tus.service.js +8 -7
- package/dist/core/modules/tus/core-tus.service.js.map +1 -1
- package/dist/core/modules/tus/tus.module.js +1 -1
- package/dist/core/modules/tus/tus.module.js.map +1 -1
- package/dist/core/modules/user/core-user.model.d.ts +1 -1
- package/dist/core/modules/user/core-user.model.js +1 -1
- package/dist/core/modules/user/core-user.model.js.map +1 -1
- package/dist/core/modules/user/core-user.service.d.ts +3 -1
- package/dist/core/modules/user/core-user.service.js +71 -16
- package/dist/core/modules/user/core-user.service.js.map +1 -1
- package/dist/core.module.js +39 -5
- package/dist/core.module.js.map +1 -1
- package/dist/index.d.ts +26 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -1
- package/dist/server/common/models/persistence.model.d.ts +1 -1
- package/dist/server/common/models/persistence.model.js +3 -3
- package/dist/server/common/models/persistence.model.js.map +1 -1
- package/dist/server/modules/file/file-info.model.d.ts +1 -77
- package/dist/server/modules/file/file-info.model.js +1 -1
- package/dist/server/modules/file/file-info.model.js.map +1 -1
- package/dist/server/modules/file/file.service.js +1 -1
- package/dist/server/modules/file/file.service.js.map +1 -1
- package/dist/server/modules/user/user.model.d.ts +2 -186
- package/dist/server/modules/user/user.model.js +4 -5
- package/dist/server/modules/user/user.model.js.map +1 -1
- package/dist/server/modules/user/user.module.js +4 -3
- package/dist/server/modules/user/user.module.js.map +1 -1
- package/dist/server/modules/user/user.service.d.ts +1 -1
- package/dist/server/modules/user/user.service.js +5 -8
- package/dist/server/modules/user/user.service.js.map +1 -1
- package/dist/test/test.helper.js +2 -2
- package/dist/test/test.helper.js.map +1 -1
- package/dist/types/graphql-upload.d.ts +10 -7
- package/docs/REQUEST-LIFECYCLE.md +6 -3
- package/docs/choosing-a-database.md +107 -0
- package/docs/native-driver-security.md +29 -0
- package/docs/security-overrides.md +15 -6
- package/migration-guides/12.0.x-to-12.1.x.md +255 -0
- package/package.json +75 -29
- package/src/core/common/decorators/unified-field.decorator.ts +11 -1
- package/src/core/common/filters/mongoose-cast-error.filter.ts +12 -6
- package/src/core/common/helpers/db.helper.ts +40 -25
- package/src/core/common/helpers/decorator.helper.ts +1 -1
- package/src/core/common/helpers/filter.helper.ts +2 -1
- package/src/core/common/helpers/gridfs.helper.ts +28 -9
- package/src/core/common/helpers/id.helper.ts +21 -4
- package/src/core/common/helpers/model.helper.ts +5 -6
- package/src/core/common/helpers/service.helper.ts +3 -3
- package/src/core/common/interfaces/server-options.interface.ts +118 -10
- package/src/core/common/interfaces/service-options.interface.ts +2 -2
- package/src/core/common/models/core-persistence.model.ts +3 -3
- package/src/core/common/persistence/core-persistence.lifecycle.ts +47 -0
- package/src/core/common/persistence/core-persistence.module.ts +109 -0
- package/src/core/common/persistence/data-source.config.ts +271 -0
- package/src/core/common/persistence/data-source.runtime.ts +351 -0
- package/src/core/common/persistence/data-store.interface.ts +155 -0
- package/src/core/common/persistence/expiry-sweep.ts +105 -0
- package/src/core/common/persistence/id-format.ts +43 -0
- package/src/core/common/persistence/infrastructure-locks.ts +66 -0
- package/src/core/common/persistence/inject-store.decorator.ts +16 -0
- package/src/core/common/persistence/lock-store.interface.ts +17 -0
- package/src/core/common/persistence/model-descriptor.interface.ts +90 -0
- package/src/core/common/persistence/model-metadata.registry.ts +285 -0
- package/src/core/common/persistence/mongo/collection-name.ts +87 -0
- package/src/core/common/persistence/mongo/declared-schema.view.ts +378 -0
- package/src/core/common/persistence/mongo/hex-object-id.ts +75 -0
- package/src/core/common/persistence/mongo/model-declarations.ts +135 -0
- package/src/core/common/persistence/mongo/mongo-packages.ts +130 -0
- package/src/core/common/persistence/mongo/mongoose-compat.ts +129 -0
- package/src/core/common/persistence/mongo/no-mongo-connection.module.ts +18 -0
- package/src/core/common/persistence/mongo-lock-store.ts +121 -0
- package/src/core/common/persistence/mongoose-data-store.ts +232 -0
- package/src/core/common/persistence/neutral-populate.ts +98 -0
- package/src/core/common/persistence/persisted-model.decorator.ts +61 -0
- package/src/core/common/persistence/persistence-runtime.registry.ts +152 -0
- package/src/core/common/persistence/persistence.tokens.ts +9 -0
- package/src/core/common/persistence/policies/audit.policy.ts +80 -0
- package/src/core/common/persistence/policies/password.policy.ts +69 -0
- package/src/core/common/persistence/policies/role-guard.policy.ts +74 -0
- package/src/core/common/persistence/policies/system-role.policy.ts +90 -0
- package/src/core/common/persistence/policies/tenant.policy.ts +245 -0
- package/src/core/common/persistence/routed-model.guard.ts +107 -0
- package/src/core/common/persistence/sql/mysql/mysql-data-store.ts +503 -0
- package/src/core/common/persistence/sql/mysql/mysql-executor.ts +281 -0
- package/src/core/common/persistence/sql/mysql/mysql-lock-store.ts +87 -0
- package/src/core/common/persistence/sql/mysql/mysql-schema.compiler.ts +424 -0
- package/src/core/common/persistence/sql/mysql/mysql-schema.migrator.ts +453 -0
- package/src/core/common/persistence/sql/mysql/mysql-session.ts +131 -0
- package/src/core/common/persistence/sql/mysql/mysql-update.compiler.ts +379 -0
- package/src/core/common/persistence/sql/mysql/mysql-where.compiler.ts +686 -0
- package/src/core/common/persistence/sql/postgres/postgres-lock-store.ts +76 -0
- package/src/core/common/persistence/sql/postgres/postgres-schema.compiler.ts +328 -0
- package/src/core/common/persistence/sql/postgres/postgres-schema.migrator.ts +448 -0
- package/src/core/common/persistence/sql/postgres/postgres-update.compiler.ts +310 -0
- package/src/core/common/persistence/sql/postgres/postgres-where.compiler.ts +638 -0
- package/src/core/common/persistence/sql/sql-cast.ts +227 -0
- package/src/core/common/persistence/sql/sql-data-store.ts +762 -0
- package/src/core/common/persistence/sql/sql-dialect.ts +85 -0
- package/src/core/common/persistence/sql/sql-errors.ts +49 -0
- package/src/core/common/persistence/sql/sql-executor.factory.ts +282 -0
- package/src/core/common/persistence/sql/sql-executor.interface.ts +57 -0
- package/src/core/common/persistence/sql/sql-naming.ts +133 -0
- package/src/core/common/persistence/sql/sql-schema.shared.ts +105 -0
- package/src/core/common/persistence/sql/sql-session.ts +158 -0
- package/src/core/common/persistence/sql/where-shared.ts +118 -0
- package/src/core/common/persistence/store-guards.ts +73 -0
- package/src/core/common/persistence/store-upsert.ts +36 -0
- package/src/core/common/persistence/unavailable-store.ts +63 -0
- package/src/core/common/persistence/unsupported-capability.error.ts +7 -0
- package/src/core/common/plugins/mongoose-audit-fields.plugin.ts +33 -74
- package/src/core/common/plugins/mongoose-id.plugin.ts +9 -0
- package/src/core/common/plugins/mongoose-password.plugin.ts +6 -62
- package/src/core/common/plugins/mongoose-role-guard.plugin.ts +11 -63
- package/src/core/common/plugins/mongoose-system-role.plugin.ts +7 -78
- package/src/core/common/plugins/mongoose-tenant.plugin.ts +23 -144
- package/src/core/common/scalars/upload.scalar.ts +8 -3
- package/src/core/common/services/core-cron-jobs.initializer.ts +1 -1
- package/src/core/common/services/core-cron-jobs.service.ts +33 -22
- package/src/core/common/services/crud.service.ts +166 -35
- package/src/core/common/services/model-doc.service.ts +1 -1
- package/src/core/common/services/module.service.ts +78 -6
- package/src/core/common/types/field-selection.type.ts +1 -1
- package/src/core/common/types/id.type.ts +2 -2
- package/src/core/common/types/object-id-like.type.ts +11 -0
- package/src/core/common/types/populate-config.type.ts +1 -1
- package/src/core/common/types/string-or-object-id.type.ts +2 -2
- package/src/core/modules/ai/README.md +15 -2
- package/src/core/modules/ai/core-ai.constants.ts +10 -0
- package/src/core/modules/ai/core-ai.module.ts +32 -17
- package/src/core/modules/ai/models/core-ai-budget-limit.model.ts +2 -2
- package/src/core/modules/ai/models/core-ai-connection-preference.model.ts +2 -2
- package/src/core/modules/ai/models/core-ai-connection.model.ts +2 -2
- package/src/core/modules/ai/models/core-ai-conversation.model.ts +8 -4
- package/src/core/modules/ai/models/core-ai-interaction.model.ts +3 -3
- package/src/core/modules/ai/models/core-ai-mcp-oauth.models.ts +46 -0
- package/src/core/modules/ai/models/core-ai-mode.model.ts +2 -2
- package/src/core/modules/ai/models/core-ai-prompt-hint.model.ts +2 -2
- package/src/core/modules/ai/models/core-ai-prompt.model.ts +2 -2
- package/src/core/modules/ai/models/core-ai-slot.model.ts +2 -2
- package/src/core/modules/ai/models/core-ai-tool-grant.model.ts +2 -2
- package/src/core/modules/ai/models/core-ai-tool-policy.model.ts +2 -2
- package/src/core/modules/ai/services/core-ai-budget.service.ts +22 -4
- package/src/core/modules/ai/services/core-ai-connection-preference.service.ts +6 -13
- package/src/core/modules/ai/services/core-ai-connection.service.ts +34 -44
- package/src/core/modules/ai/services/core-ai-conversation.service.ts +31 -29
- package/src/core/modules/ai/services/core-ai-interaction.service.ts +3 -3
- package/src/core/modules/ai/services/core-ai-mcp-oauth.service.ts +93 -20
- package/src/core/modules/ai/services/core-ai-mode.service.ts +3 -6
- package/src/core/modules/ai/services/core-ai-prompt-hint.service.ts +43 -26
- package/src/core/modules/ai/services/core-ai-prompt.service.ts +15 -12
- package/src/core/modules/ai/services/core-ai-slot.service.ts +20 -24
- package/src/core/modules/ai/services/core-ai-tool-grant.service.ts +17 -27
- package/src/core/modules/ai/services/core-ai-tool-policy.service.ts +7 -10
- package/src/core/modules/api-token/core-api-token.model.ts +1 -1
- package/src/core/modules/api-token/core-api-token.module.ts +4 -2
- package/src/core/modules/api-token/core-api-token.service.ts +118 -43
- package/src/core/modules/auth/core-auth.module.ts +2 -0
- package/src/core/modules/auth/guards/legacy-auth-rate-limit.guard.ts +4 -3
- package/src/core/modules/auth/guards/role-guard.token.ts +7 -0
- package/src/core/modules/auth/services/core-auth.service.ts +16 -2
- package/src/core/modules/better-auth/INTEGRATION-CHECKLIST.md +1 -1
- package/src/core/modules/better-auth/README.md +10 -1
- package/src/core/modules/better-auth/better-auth-sql.helper.ts +191 -0
- package/src/core/modules/better-auth/better-auth-token.service.ts +26 -35
- package/src/core/modules/better-auth/better-auth.config.ts +43 -7
- package/src/core/modules/better-auth/better-auth.types.ts +1 -1
- package/src/core/modules/better-auth/core-better-auth-api.middleware.ts +13 -1
- package/src/core/modules/better-auth/core-better-auth-challenge.service.ts +36 -18
- package/src/core/modules/better-auth/core-better-auth-mongo.users.ts +35 -0
- package/src/core/modules/better-auth/core-better-auth-sql.registry.ts +20 -0
- package/src/core/modules/better-auth/core-better-auth-sql.store.ts +309 -0
- package/src/core/modules/better-auth/core-better-auth-user.mapper.ts +418 -40
- package/src/core/modules/better-auth/core-better-auth.module.ts +71 -35
- package/src/core/modules/better-auth/core-better-auth.service.ts +81 -12
- package/src/core/modules/file/README.md +16 -3
- package/src/core/modules/file/core-file-info.model.ts +2 -2
- package/src/core/modules/file/core-file.service.ts +27 -18
- package/src/core/modules/file/file-metadata.helper.ts +7 -3
- package/src/core/modules/file/file-metadata.models.ts +44 -0
- package/src/core/modules/file/file-metadata.store.ts +109 -0
- package/src/core/modules/file/file-storage.helper.ts +47 -2
- package/src/core/modules/file/filesystem-file.helper.ts +11 -8
- package/src/core/modules/file/s3-file.helper.ts +11 -7
- package/src/core/modules/health-check/core-health-check.module.ts +16 -2
- package/src/core/modules/health-check/core-health-check.service.ts +25 -3
- package/src/core/modules/hub/README.md +20 -11
- package/src/core/modules/hub/core-hub.controller.ts +5 -0
- package/src/core/modules/hub/core-hub.service.ts +1 -1
- package/src/core/modules/hub/helpers/hub-client-js.helper.ts +23 -0
- package/src/core/modules/hub/hub-action-messages.ts +6 -0
- package/src/core/modules/hub/hub-nav.ts +1 -0
- package/src/core/modules/hub/interfaces/hub-panels.interface.ts +8 -1
- package/src/core/modules/hub/services/core-hub-db.service.ts +35 -17
- package/src/core/modules/hub/services/core-hub-migrations.service.ts +96 -2
- package/src/core/modules/hub/services/core-hub-sources.service.ts +47 -1
- package/src/core/modules/hub/services/hub-query-profiler.service.ts +1 -1
- package/src/core/modules/migrate/README.md +54 -0
- package/src/core/modules/migrate/cli/migrate-cli.ts +44 -3
- package/src/core/modules/migrate/index.ts +3 -0
- package/src/core/modules/migrate/migration-runner.ts +3 -2
- package/src/core/modules/migrate/migration-state-store.interface.ts +24 -0
- package/src/core/modules/migrate/migration.helper.ts +35 -10
- package/src/core/modules/migrate/mongo-state-store.ts +64 -65
- package/src/core/modules/migrate/sql-migration.helper.ts +48 -0
- package/src/core/modules/migrate/sql-state-store.ts +198 -0
- package/src/core/modules/system-setup/README.md +14 -2
- package/src/core/modules/system-setup/core-system-setup.service.ts +77 -45
- package/src/core/modules/tenant/README.md +9 -2
- package/src/core/modules/tenant/core-tenant-member.model.ts +1 -1
- package/src/core/modules/tenant/core-tenant-member.store.ts +13 -0
- package/src/core/modules/tenant/core-tenant.guard.ts +77 -24
- package/src/core/modules/tenant/core-tenant.module.ts +6 -3
- package/src/core/modules/tenant/core-tenant.service.ts +59 -42
- package/src/core/modules/tus/core-tus.service.ts +11 -12
- package/src/core/modules/tus/tus.module.ts +1 -1
- package/src/core/modules/user/core-user.model.ts +2 -2
- package/src/core/modules/user/core-user.service.ts +98 -20
- package/src/core.module.ts +60 -5
- package/src/index.ts +26 -0
- package/src/server/common/models/persistence.model.ts +4 -4
- package/src/server/modules/file/file-info.model.ts +1 -1
- package/src/server/modules/file/file.service.ts +1 -1
- package/src/server/modules/user/user.model.ts +10 -5
- package/src/server/modules/user/user.module.ts +9 -3
- package/src/server/modules/user/user.service.ts +9 -11
- package/src/test/test.helper.ts +2 -2
- package/src/types/graphql-upload.d.ts +10 -7
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
import { BadRequestException, Logger } from '@nestjs/common';
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
DataStoreUpdate,
|
|
5
|
+
FindOptions,
|
|
6
|
+
PushOptions,
|
|
7
|
+
StoreCapabilities,
|
|
8
|
+
StoredRecord,
|
|
9
|
+
UpdateOptions,
|
|
10
|
+
Where,
|
|
11
|
+
} from '../../data-store.interface.js';
|
|
12
|
+
import type { FieldDescriptor, ModelDescriptor } from '../../model-descriptor.interface.js';
|
|
13
|
+
import { isRoleChangeAllowed } from '../../policies/role-guard.policy.js';
|
|
14
|
+
import { assertNoSystemRoles } from '../../policies/system-role.policy.js';
|
|
15
|
+
import { resolveTenantScope } from '../../policies/tenant.policy.js';
|
|
16
|
+
import {
|
|
17
|
+
assertArrayField,
|
|
18
|
+
assertInteger,
|
|
19
|
+
assertNonNegativeInteger,
|
|
20
|
+
assertSampleSize,
|
|
21
|
+
assertSelectFields,
|
|
22
|
+
} from '../../store-guards.js';
|
|
23
|
+
import { castFilterValue } from '../sql-cast.js';
|
|
24
|
+
import { POSTGRES_STORE_CAPABILITIES, SqlDataStore, type SqlDataStoreOptions } from '../sql-data-store.js';
|
|
25
|
+
import { DuplicateKeyError, UnsupportedQueryError } from '../sql-errors.js';
|
|
26
|
+
import type { SqlQueryResult, SqlStatement } from '../sql-executor.interface.js';
|
|
27
|
+
import { columnName, quoteMysqlIdentifier, SqlParams } from '../sql-naming.js';
|
|
28
|
+
import { SCALAR_KINDS, splitPath, toJson } from '../where-shared.js';
|
|
29
|
+
import type { MysqlExecutor } from './mysql-executor.js';
|
|
30
|
+
import type { MysqlVariant } from './mysql-session.js';
|
|
31
|
+
import { compileMysqlUpdate, mysqlArrayOf, mysqlItemText, mysqlPullExpression } from './mysql-update.compiler.js';
|
|
32
|
+
import {
|
|
33
|
+
compileMysqlPath,
|
|
34
|
+
compileMysqlWhere,
|
|
35
|
+
mysqlArrayItems,
|
|
36
|
+
mysqlJsonNumber,
|
|
37
|
+
mysqlJsonPath,
|
|
38
|
+
mysqlJsonSortKeys,
|
|
39
|
+
mysqlJsonValue,
|
|
40
|
+
} from './mysql-where.compiler.js';
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* What MySQL and MariaDB offer through the SQL store: everything PostgreSQL does except row-level security — neither
|
|
44
|
+
* database has it, so tenant isolation is the store's before-layer and its row check after every read (plan §3.4)
|
|
45
|
+
*/
|
|
46
|
+
export const MYSQL_STORE_CAPABILITIES: Readonly<StoreCapabilities> = Object.freeze({
|
|
47
|
+
...POSTGRES_STORE_CAPABILITIES,
|
|
48
|
+
rls: false,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
/** Error numbers the store answers like MongoDB does */
|
|
52
|
+
export const MYSQL_ERRORS = {
|
|
53
|
+
/** A CHECK constraint refused the row: ER_CHECK_CONSTRAINT_VIOLATED on MySQL, ER_CONSTRAINT_FAILED on MariaDB */
|
|
54
|
+
checkFailed: { mariadb: 4025, mysql: 3819 } as Record<MysqlVariant, number>,
|
|
55
|
+
dataTooLong: 1406,
|
|
56
|
+
duplicateEntry: 1062,
|
|
57
|
+
} as const;
|
|
58
|
+
|
|
59
|
+
/** The largest LIMIT, for an OFFSET without one — MySQL has no OFFSET on its own */
|
|
60
|
+
const NO_LIMIT = '18446744073709551615';
|
|
61
|
+
|
|
62
|
+
type Run = <R = Record<string, any>>(statement: SqlStatement) => Promise<SqlQueryResult<R>>;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* The SQL data store on MySQL 8.4 and MariaDB 11.8 (plan phase 6): the PostgreSQL store's policies and record mapping,
|
|
66
|
+
* with the statements in the MySQL dialect.
|
|
67
|
+
*
|
|
68
|
+
* Neither database has `RETURNING` on every statement, so a write that answers with the record runs in a transaction:
|
|
69
|
+
* the write, then the read of the row it wrote — the row stays locked between the two, so the answer is the state the
|
|
70
|
+
* write produced. `updateOne()` / `deleteOne()` pick their row with `SELECT … FOR UPDATE` in the same transaction, which
|
|
71
|
+
* gives MongoDB's findOneAndUpdate guarantee without a retry.
|
|
72
|
+
*/
|
|
73
|
+
export class MysqlDataStore<T = Record<string, any>> extends SqlDataStore<T> {
|
|
74
|
+
override readonly capabilities = MYSQL_STORE_CAPABILITIES;
|
|
75
|
+
override readonly driver: string = 'mysql';
|
|
76
|
+
protected override readonly logger = new Logger(MysqlDataStore.name);
|
|
77
|
+
private readonly variant: MysqlVariant;
|
|
78
|
+
|
|
79
|
+
constructor(executor: MysqlExecutor, model: ModelDescriptor, options: SqlDataStoreOptions = {}) {
|
|
80
|
+
super(executor, model, options);
|
|
81
|
+
this.variant = executor.variant;
|
|
82
|
+
this.driver = executor.variant;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// -- reads ----------------------------------------------------------------------------------------------
|
|
86
|
+
|
|
87
|
+
override async count(where?: Where<T>): Promise<number> {
|
|
88
|
+
const params = new SqlParams();
|
|
89
|
+
const { rows } = await this.run<{ n: number | string }>({
|
|
90
|
+
params: params.values,
|
|
91
|
+
text: `SELECT COUNT(*) AS n FROM ${this.table} WHERE ${this.where(where, params)}`,
|
|
92
|
+
});
|
|
93
|
+
return Number(rows[0].n);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
override async sum(field: string, where?: Where<T>): Promise<{ count: number; sum: number }> {
|
|
97
|
+
assertSelectFields([field]);
|
|
98
|
+
const params = new SqlParams();
|
|
99
|
+
const path = compileMysqlPath(this.variant, this.model, field, params);
|
|
100
|
+
if (path.kind === 'array') {
|
|
101
|
+
throw new UnsupportedQueryError(`sum() needs a single value, "${field}" is an array`);
|
|
102
|
+
}
|
|
103
|
+
// A JSON value counts only when it is a number, as MongoDB's $sum ignores other types
|
|
104
|
+
const value = path.kind === 'column' ? path.expr : mysqlJsonNumber(path.expr);
|
|
105
|
+
const { rows } = await this.run<{ n: number | string; total: number | string }>({
|
|
106
|
+
params: params.values,
|
|
107
|
+
text: `SELECT COUNT(*) AS n, COALESCE(SUM(${value}), 0) AS total FROM ${this.table} WHERE ${this.where(where, params)}`,
|
|
108
|
+
});
|
|
109
|
+
return { count: Number(rows[0].n), sum: Number(rows[0].total) };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
override async distinct(field: string, where?: Where<T>): Promise<unknown[]> {
|
|
113
|
+
const params = new SqlParams();
|
|
114
|
+
const path = compileMysqlPath(this.variant, this.model, field, params);
|
|
115
|
+
const condition = this.where(where, params);
|
|
116
|
+
if (path.kind === 'array') {
|
|
117
|
+
const { rows } = await this.run<{ v: unknown }>({
|
|
118
|
+
params: params.values,
|
|
119
|
+
text: `SELECT d.v AS v FROM ${this.table}, ${mysqlArrayItems(path.expr, 'd')} WHERE ${condition}`,
|
|
120
|
+
});
|
|
121
|
+
// MariaDB answers a JSON_TABLE item as JSON text; values are compared as JSON, not as their spelling
|
|
122
|
+
return unique(rows.map((row) => (this.variant === 'mariadb' ? parseJsonText(row.v) : (row.v ?? null))));
|
|
123
|
+
}
|
|
124
|
+
const { rows } = await this.run<{ v: unknown }>({
|
|
125
|
+
params: params.values,
|
|
126
|
+
text: `SELECT DISTINCT ${path.expr} AS v FROM ${this.table} WHERE ${condition} AND ${path.expr} IS NOT NULL`,
|
|
127
|
+
});
|
|
128
|
+
return path.kind === 'column' && path.field
|
|
129
|
+
? rows.map((row) => this.fromColumn(path.field!, row.v))
|
|
130
|
+
: unique(rows.map((row) => row.v));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
override async find(where?: Where<T>, options: FindOptions = {}): Promise<StoredRecord<T>[]> {
|
|
134
|
+
const sample = options.sample === undefined ? undefined : assertSampleSize(options.sample);
|
|
135
|
+
const params = new SqlParams();
|
|
136
|
+
let text = `SELECT ${this.selectList(options.select, options.exclude)} FROM ${this.table} WHERE ${this.where(where, params)}`;
|
|
137
|
+
text += this.orderBy(options, params);
|
|
138
|
+
if (options.limit !== undefined) {
|
|
139
|
+
text += ` LIMIT ${params.add(assertNonNegativeInteger(options.limit, 'limit'))}`;
|
|
140
|
+
}
|
|
141
|
+
if (options.skip !== undefined) {
|
|
142
|
+
text += `${options.limit === undefined ? ` LIMIT ${NO_LIMIT}` : ''} OFFSET ${params.add(assertNonNegativeInteger(options.skip, 'skip'))}`;
|
|
143
|
+
}
|
|
144
|
+
if (sample !== undefined) {
|
|
145
|
+
// The page first, then the draw — MongoDB's `$sample` after `$sort`, `$skip` and `$limit`
|
|
146
|
+
text = `SELECT * FROM (${text}) AS \`page\` ORDER BY RAND() LIMIT ${params.add(sample)}`;
|
|
147
|
+
}
|
|
148
|
+
const { rows } = await this.run({ params: params.values, text });
|
|
149
|
+
return this.toRecords(rows, options.select);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// -- writes ---------------------------------------------------------------------------------------------
|
|
153
|
+
|
|
154
|
+
override async insert(record: Partial<T>): Promise<StoredRecord<T>> {
|
|
155
|
+
const doc = await this.beforeInsert({ ...(record as Record<string, any>) });
|
|
156
|
+
const params = new SqlParams();
|
|
157
|
+
const { columns, id, values } = this.insertValues(doc, params);
|
|
158
|
+
return this.transaction(async (run) => {
|
|
159
|
+
await run({
|
|
160
|
+
params: params.values,
|
|
161
|
+
text: `INSERT INTO ${this.table} (${columns.join(', ')}) VALUES (${values.join(', ')})`,
|
|
162
|
+
});
|
|
163
|
+
return (await this.readById(run, id))!;
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
override async updateById(
|
|
168
|
+
id: string,
|
|
169
|
+
update: DataStoreUpdate<T>,
|
|
170
|
+
options: UpdateOptions = {},
|
|
171
|
+
): Promise<null | StoredRecord<T>> {
|
|
172
|
+
const patch = await this.preparePatch(update, options);
|
|
173
|
+
const params = new SqlParams();
|
|
174
|
+
const assignments = this.compileUpdate(patch, params);
|
|
175
|
+
if (!assignments.length) {
|
|
176
|
+
return this.findById(id);
|
|
177
|
+
}
|
|
178
|
+
const condition = this.where({ id } as Where<T>, params);
|
|
179
|
+
return this.transaction(async (run) => {
|
|
180
|
+
const { rowCount } = await run({
|
|
181
|
+
params: params.values,
|
|
182
|
+
text: `UPDATE ${this.table} SET ${assignments.join(', ')} WHERE ${condition}`,
|
|
183
|
+
});
|
|
184
|
+
// The driver counts MATCHED rows (CLIENT_FOUND_ROWS), so an update that changes nothing still finds its record
|
|
185
|
+
return rowCount ? this.readById(run, id) : null;
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
override async updateOne(where: Where<T>, update: DataStoreUpdate<T>): Promise<null | StoredRecord<T>> {
|
|
190
|
+
const patch = await this.preparePatch(update);
|
|
191
|
+
const params = new SqlParams();
|
|
192
|
+
const assignments = this.compileUpdate(patch, params);
|
|
193
|
+
if (!assignments.length) {
|
|
194
|
+
return this.findOne(where);
|
|
195
|
+
}
|
|
196
|
+
return this.transaction(async (run) => {
|
|
197
|
+
const id = await this.lockFirst(run, where);
|
|
198
|
+
if (id === undefined) {
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
await run({
|
|
202
|
+
params: params.values,
|
|
203
|
+
text: `UPDATE ${this.table} SET ${assignments.join(', ')} WHERE \`id\` = ${params.add(id)}`,
|
|
204
|
+
});
|
|
205
|
+
return this.readById(run, id);
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
override async deleteById(id: string): Promise<null | StoredRecord<T>> {
|
|
210
|
+
return this.deleteFirst({ id } as Where<T>);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
override async deleteOne(where: Where<T>): Promise<null | StoredRecord<T>> {
|
|
214
|
+
return this.deleteFirst(where);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
override async pushToArray(
|
|
218
|
+
id: string,
|
|
219
|
+
field: string,
|
|
220
|
+
items: readonly unknown[],
|
|
221
|
+
options: PushOptions = {},
|
|
222
|
+
): Promise<void> {
|
|
223
|
+
assertArrayField(field, 'pushToArray');
|
|
224
|
+
if (!items.length) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
const descriptor = this.arrayField(field, 'pushToArray');
|
|
228
|
+
if (field === 'roles') {
|
|
229
|
+
if (this.roleGuardEnabled() && !isRoleChangeAllowed()) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
assertNoSystemRoles(items);
|
|
233
|
+
}
|
|
234
|
+
const variant = this.variant;
|
|
235
|
+
const column = this.quote(columnName(field));
|
|
236
|
+
const json = toJson(items.map((item) => this.castItem(descriptor, field, item)));
|
|
237
|
+
const position = options.position === undefined ? undefined : assertInteger(options.position, 'position');
|
|
238
|
+
const slice = options.slice === undefined ? undefined : assertInteger(options.slice, 'slice');
|
|
239
|
+
|
|
240
|
+
// MongoDB order: insert at the position, then sort, then slice. Each stage reads the array `source` holds
|
|
241
|
+
type Stage = (params: SqlParams, source: string) => string;
|
|
242
|
+
const stages: Stage[] = [
|
|
243
|
+
(params, source) => {
|
|
244
|
+
const existing = `COALESCE(${source}, JSON_ARRAY())`;
|
|
245
|
+
const added = mysqlJsonValue(variant, params.add(json));
|
|
246
|
+
if (position === undefined) {
|
|
247
|
+
return `JSON_MERGE_PRESERVE(${existing}, ${added})`;
|
|
248
|
+
}
|
|
249
|
+
const at =
|
|
250
|
+
position < 0 ? `GREATEST(JSON_LENGTH(${existing}) + ${params.add(position)}, 0)` : params.add(position);
|
|
251
|
+
// The items before the position, the new ones, the rest — three arrays rather than one ordered union:
|
|
252
|
+
// MariaDB refuses a derived table that reads the row being updated
|
|
253
|
+
const part = (alias: string, keep: string) =>
|
|
254
|
+
mysqlArrayOf(
|
|
255
|
+
variant,
|
|
256
|
+
mysqlItemText(variant, `${alias}.v`),
|
|
257
|
+
`${alias}.${alias}_n`,
|
|
258
|
+
`${mysqlArrayItems(existing, alias, true)} WHERE ${alias}.${alias}_n ${keep} ${at}`,
|
|
259
|
+
);
|
|
260
|
+
return `JSON_MERGE_PRESERVE(${part('h', '<=')}, ${added}, ${part('t', '>')})`;
|
|
261
|
+
},
|
|
262
|
+
];
|
|
263
|
+
if (options.sort) {
|
|
264
|
+
const sort = options.sort;
|
|
265
|
+
stages.push((params, source) =>
|
|
266
|
+
mysqlArrayOf(
|
|
267
|
+
variant,
|
|
268
|
+
mysqlItemText(variant, 's.v'),
|
|
269
|
+
this.itemOrder(sort, params),
|
|
270
|
+
mysqlArrayItems(source, 's', true),
|
|
271
|
+
),
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
if (slice !== undefined) {
|
|
275
|
+
stages.push((params, source) =>
|
|
276
|
+
mysqlArrayOf(
|
|
277
|
+
variant,
|
|
278
|
+
mysqlItemText(variant, 'l.v'),
|
|
279
|
+
'l.l_n',
|
|
280
|
+
`${mysqlArrayItems(source, 'l', true)} WHERE ${slice < 0 ? `l.l_n > JSON_LENGTH(${source}) - ${params.add(-slice)}` : `l.l_n <= ${params.add(slice)}`}`,
|
|
281
|
+
),
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (stages.length === 1) {
|
|
286
|
+
const params = new SqlParams();
|
|
287
|
+
const value = stages.reduce((source, stage) => stage(params, source), column);
|
|
288
|
+
await this.updateColumn(id, column, value, params);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
// Several stages: one statement each, in one transaction, every stage reading the column the previous one wrote.
|
|
292
|
+
// Nested into one expression, a stage's JSON_TABLE argument would hold a subquery reading the row being updated —
|
|
293
|
+
// MySQL 8.4 refuses that ("Unknown column … in 'a table function argument'")
|
|
294
|
+
const { $setOnInsert: _insertOnly, ...stamped } = await this.beforeUpdate({});
|
|
295
|
+
await this.transaction(async (run) => {
|
|
296
|
+
for (const [index, stage] of stages.entries()) {
|
|
297
|
+
const params = new SqlParams();
|
|
298
|
+
const assignments = [
|
|
299
|
+
`${column} = ${stage(params, column)}`,
|
|
300
|
+
...(index === stages.length - 1 ? this.compileUpdate(stamped, params) : []),
|
|
301
|
+
];
|
|
302
|
+
const { rowCount } = await run({
|
|
303
|
+
params: params.values,
|
|
304
|
+
text: `UPDATE ${this.table} SET ${assignments.join(', ')} WHERE ${this.where({ id } as Where<T>, params)}`,
|
|
305
|
+
});
|
|
306
|
+
if (!rowCount) {
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
override async pullFromArray(id: string, field: string, condition: unknown): Promise<void> {
|
|
314
|
+
assertArrayField(field, 'pullFromArray');
|
|
315
|
+
this.arrayField(field, 'pullFromArray');
|
|
316
|
+
if (field === 'roles' && this.roleGuardEnabled() && !isRoleChangeAllowed()) {
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
const params = new SqlParams();
|
|
320
|
+
const column = this.quote(columnName(field));
|
|
321
|
+
await this.updateColumn(
|
|
322
|
+
id,
|
|
323
|
+
column,
|
|
324
|
+
mysqlPullExpression(this.variant, this.model, field, column, condition, params),
|
|
325
|
+
params,
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// -- statements -----------------------------------------------------------------------------------------
|
|
330
|
+
|
|
331
|
+
protected override quote(name: string): string {
|
|
332
|
+
return quoteMysqlIdentifier(name);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
protected override compileWhere(where: Where, params: SqlParams): string {
|
|
336
|
+
return compileMysqlWhere(this.variant, this.model, where, params);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
protected override compileUpdate(update: DataStoreUpdate, params: SqlParams): string[] {
|
|
340
|
+
return compileMysqlUpdate(this.variant, this.model, update, params);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/** NULL sorts first ascending and last descending on both servers — MongoDB's order for a missing value */
|
|
344
|
+
protected override orderBy(options: FindOptions, params: SqlParams): string {
|
|
345
|
+
if (options.collation && !this.collationWarned) {
|
|
346
|
+
this.collationWarned = true;
|
|
347
|
+
this.logger.warn(`${this.modelName}: a collation is not applied on MySQL / MariaDB; strings compare byte-wise`);
|
|
348
|
+
}
|
|
349
|
+
const parts: string[] = [];
|
|
350
|
+
for (const [path, direction] of Object.entries(options.sort ?? {})) {
|
|
351
|
+
if (direction !== 1 && direction !== -1) {
|
|
352
|
+
throw new UnsupportedQueryError(`sort direction for "${path}" must be 1 or -1`);
|
|
353
|
+
}
|
|
354
|
+
const { expr, kind } = compileMysqlPath(this.variant, this.model, path, params);
|
|
355
|
+
if (kind === 'array') {
|
|
356
|
+
throw new UnsupportedQueryError(`sort by the array field "${path}"`);
|
|
357
|
+
}
|
|
358
|
+
const order = direction === 1 ? 'ASC' : 'DESC';
|
|
359
|
+
parts.push(...(kind === 'column' ? [`${expr} ${order}`] : mysqlJsonSortKeys(expr, order)));
|
|
360
|
+
}
|
|
361
|
+
if (!parts.length && options.skip === undefined && options.limit === undefined) {
|
|
362
|
+
return '';
|
|
363
|
+
}
|
|
364
|
+
if (!Object.keys(options.sort ?? {}).some((path) => path === 'id' || path === '_id')) {
|
|
365
|
+
parts.push('`id` ASC');
|
|
366
|
+
}
|
|
367
|
+
return ` ORDER BY ${parts.join(', ')}`;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
protected override itemOrder(sort: Record<string, -1 | 1> | number, params: SqlParams): string {
|
|
371
|
+
if (typeof sort === 'number') {
|
|
372
|
+
return [...mysqlJsonSortKeys('s.v', sort === -1 ? 'DESC' : 'ASC'), 's.s_n'].join(', ');
|
|
373
|
+
}
|
|
374
|
+
return [
|
|
375
|
+
...Object.entries(sort).flatMap(([path, direction]) =>
|
|
376
|
+
mysqlJsonSortKeys(
|
|
377
|
+
`JSON_EXTRACT(s.v, ${params.add(mysqlJsonPath(splitPath(path)))})`,
|
|
378
|
+
direction === -1 ? 'DESC' : 'ASC',
|
|
379
|
+
),
|
|
380
|
+
),
|
|
381
|
+
's.s_n',
|
|
382
|
+
].join(', ');
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// -- values ---------------------------------------------------------------------------------------------
|
|
386
|
+
|
|
387
|
+
/** A value bound for a column: typed, or JSON text for arrays, objects and undeclared content */
|
|
388
|
+
protected override toColumn(field: FieldDescriptor, path: string, value: unknown, params: SqlParams): string {
|
|
389
|
+
if (value === null || value === undefined) {
|
|
390
|
+
return 'NULL';
|
|
391
|
+
}
|
|
392
|
+
if (field.isArray) {
|
|
393
|
+
const items = Array.isArray(value) ? value : [value];
|
|
394
|
+
return params.add(toJson(items.map((item) => this.castItem(field, path, item))));
|
|
395
|
+
}
|
|
396
|
+
if (SCALAR_KINDS.has(field.kind)) {
|
|
397
|
+
return params.add(castFilterValue(field, path, value));
|
|
398
|
+
}
|
|
399
|
+
return params.add(toJson(value));
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
protected override fromColumn(field: FieldDescriptor, value: unknown): unknown {
|
|
403
|
+
if (value === null || value === undefined) {
|
|
404
|
+
return undefined;
|
|
405
|
+
}
|
|
406
|
+
if (!field.isArray && field.kind === 'boolean') {
|
|
407
|
+
// tinyint(1)
|
|
408
|
+
return value === true || Number(value) === 1;
|
|
409
|
+
}
|
|
410
|
+
if (!field.isArray && field.kind === 'date' && typeof value === 'string') {
|
|
411
|
+
// Drizzle's session reads DATETIME as text; the column holds UTC wall-clock time (`mysql-session.ts`)
|
|
412
|
+
return new Date(`${value.replace(' ', 'T')}Z`);
|
|
413
|
+
}
|
|
414
|
+
if ((field.isArray || field.kind === 'object') && typeof value === 'string') {
|
|
415
|
+
// JSON text the driver did not parse — an array or an object field never holds a string
|
|
416
|
+
return JSON.parse(value);
|
|
417
|
+
}
|
|
418
|
+
return super.fromColumn(field, value);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* MySQL / MariaDB errors as the answers the MongoDB path gives for the same situation. Matched by error NUMBER and
|
|
423
|
+
* server: the driver names numbers from MySQL's list, and MariaDB's 4025 (a failed CHECK) is another error there
|
|
424
|
+
*/
|
|
425
|
+
protected override mapError(error: unknown): unknown {
|
|
426
|
+
const errno = Number((error as { errno?: unknown })?.errno);
|
|
427
|
+
if (errno === MYSQL_ERRORS.duplicateEntry) {
|
|
428
|
+
return new DuplicateKeyError(this.modelName);
|
|
429
|
+
}
|
|
430
|
+
if (errno === MYSQL_ERRORS.dataTooLong) {
|
|
431
|
+
return new BadRequestException(`${this.modelName}: a value is longer than its column allows`);
|
|
432
|
+
}
|
|
433
|
+
if (errno === MYSQL_ERRORS.checkFailed[this.variant]) {
|
|
434
|
+
// The roles CHECK is the only check constraint the framework creates
|
|
435
|
+
return new BadRequestException(`${this.modelName}: the value is not allowed`);
|
|
436
|
+
}
|
|
437
|
+
return error;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// -- helpers --------------------------------------------------------------------------------------------
|
|
441
|
+
|
|
442
|
+
/** Run `fn` in one transaction on one connection; a failure rolls everything back and is mapped like `run()` */
|
|
443
|
+
private async transaction<R>(fn: (run: Run) => Promise<R>): Promise<R> {
|
|
444
|
+
const scope = resolveTenantScope();
|
|
445
|
+
try {
|
|
446
|
+
return await this.executor.transaction((tx) => fn((statement) => tx.run(statement, scope)));
|
|
447
|
+
} catch (error) {
|
|
448
|
+
throw this.mapError(error);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/** The record with this id as stored, without the tenant filter — the caller wrote or locked it in its scope */
|
|
453
|
+
private async readById(run: Run, id: string): Promise<null | StoredRecord<T>> {
|
|
454
|
+
const params = new SqlParams();
|
|
455
|
+
const { rows } = await run({
|
|
456
|
+
params: params.values,
|
|
457
|
+
text: `SELECT ${this.selectList()} FROM ${this.table} WHERE \`id\` = ${params.add(id)}`,
|
|
458
|
+
});
|
|
459
|
+
return this.toRecords(rows)[0] ?? null;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/** The id of the first match, its row locked until the transaction ends */
|
|
463
|
+
private async lockFirst(run: Run, where: Where<T>): Promise<string | undefined> {
|
|
464
|
+
const params = new SqlParams();
|
|
465
|
+
const { rows } = await run<{ id: string }>({
|
|
466
|
+
params: params.values,
|
|
467
|
+
text: `SELECT \`id\` FROM ${this.table} WHERE ${this.where(where, params)} LIMIT 1 FOR UPDATE`,
|
|
468
|
+
});
|
|
469
|
+
return rows[0]?.id;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
private async deleteFirst(where: Where<T>): Promise<null | StoredRecord<T>> {
|
|
473
|
+
return this.transaction(async (run) => {
|
|
474
|
+
const params = new SqlParams();
|
|
475
|
+
const { rows } = await run({
|
|
476
|
+
params: params.values,
|
|
477
|
+
text: `SELECT ${this.selectList()} FROM ${this.table} WHERE ${this.where(where, params)} LIMIT 1 FOR UPDATE`,
|
|
478
|
+
});
|
|
479
|
+
if (!rows.length) {
|
|
480
|
+
return null;
|
|
481
|
+
}
|
|
482
|
+
// Mapped before the delete: a row outside the tenant scope fails the row check and nothing is deleted
|
|
483
|
+
const [record] = this.toRecords(rows);
|
|
484
|
+
const remove = new SqlParams();
|
|
485
|
+
await run({ params: remove.values, text: `DELETE FROM ${this.table} WHERE \`id\` = ${remove.add(rows[0].id)}` });
|
|
486
|
+
return record;
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/** JSON text as its value; a value the driver already parsed stays as it is */
|
|
492
|
+
function parseJsonText(value: unknown): unknown {
|
|
493
|
+
return typeof value === 'string' ? JSON.parse(value) : (value ?? null);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/** Each value once, compared as JSON */
|
|
497
|
+
function unique(values: unknown[]): unknown[] {
|
|
498
|
+
const seen = new Set<string>();
|
|
499
|
+
return values.filter((value) => {
|
|
500
|
+
const key = toJson(value);
|
|
501
|
+
return seen.has(key) ? false : (seen.add(key), true);
|
|
502
|
+
});
|
|
503
|
+
}
|