@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,105 @@
|
|
|
1
|
+
import { defaultCollectionName } from '../mongo/collection-name.js';
|
|
2
|
+
import type { FieldDescriptor, ModelDescriptor } from '../model-descriptor.interface.js';
|
|
3
|
+
import { columnName } from './sql-naming.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The dialect-free half of the SQL schema (plan §3.12): how a model names its table and the framework names its
|
|
7
|
+
* indexes and constraints, the lease table every SQL schema carries, and how a schema change is reported. The
|
|
8
|
+
* PostgreSQL and MySQL / MariaDB compilers share it, so a model has one table name on every SQL database.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const lockField = (name: string, kind: 'date' | 'id' | 'string'): FieldDescriptor => ({
|
|
12
|
+
hasDefault: false,
|
|
13
|
+
index: false,
|
|
14
|
+
isArray: false,
|
|
15
|
+
kind,
|
|
16
|
+
lowercase: false,
|
|
17
|
+
name,
|
|
18
|
+
required: false,
|
|
19
|
+
select: true,
|
|
20
|
+
sparse: false,
|
|
21
|
+
trim: false,
|
|
22
|
+
unique: false,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
/** The framework's lease table (`PostgresLockStore`), created with every SQL schema */
|
|
26
|
+
export const LOCK_MODEL: ModelDescriptor = Object.freeze({
|
|
27
|
+
collection: 'lt_locks',
|
|
28
|
+
fields: {
|
|
29
|
+
_id: lockField('_id', 'id'),
|
|
30
|
+
acquiredAt: lockField('acquiredAt', 'date'),
|
|
31
|
+
expiresAt: lockField('expiresAt', 'date'),
|
|
32
|
+
owner: lockField('owner', 'string'),
|
|
33
|
+
},
|
|
34
|
+
indexes: [],
|
|
35
|
+
name: 'LtLock',
|
|
36
|
+
tenantScoped: false,
|
|
37
|
+
timestamps: false,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The table of a model: the collection MongoDB would use, in snake_case. A hyphen becomes an underscore (`s3-files` →
|
|
42
|
+
* `s3_files`): MongoDB allows it in a collection name, SQL not in an unquoted identifier
|
|
43
|
+
*/
|
|
44
|
+
export function tableName(model: ModelDescriptor): string {
|
|
45
|
+
const collection = model.collection ?? defaultCollectionName(model.name);
|
|
46
|
+
return columnName(collection.replace(/-/g, '_'));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** `prefix_table__parts`, shortened with a hash when it would exceed Postgres' 63-character identifier limit */
|
|
50
|
+
export function shortName(prefix: string, table: string, parts: string[]): string {
|
|
51
|
+
const full = `${prefix}_${table}__${parts.join('_')}`;
|
|
52
|
+
return full.length <= 63 ? full : `${full.slice(0, 54)}_${schemaHash(full)}`;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** FNV-1a, 8 hex characters: a stable short name for a definition */
|
|
56
|
+
export function schemaHash(text: string): string {
|
|
57
|
+
let value = 0x811c9dc5;
|
|
58
|
+
for (let i = 0; i < text.length; i++) {
|
|
59
|
+
value ^= text.charCodeAt(i);
|
|
60
|
+
value = Math.imul(value, 0x01000193) >>> 0;
|
|
61
|
+
}
|
|
62
|
+
return value.toString(16).padStart(8, '0');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export type SchemaChangeKind = 'automatic' | 'migration' | 'notice';
|
|
66
|
+
|
|
67
|
+
export interface SchemaChange {
|
|
68
|
+
description: string;
|
|
69
|
+
kind: SchemaChangeKind;
|
|
70
|
+
/** What would apply it (for `migration`: the suggestion `migrate:create --sql` writes) */
|
|
71
|
+
statements: string[];
|
|
72
|
+
table?: string;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export class SchemaMigrationRequiredError extends Error {
|
|
76
|
+
override readonly name = 'SchemaMigrationRequiredError';
|
|
77
|
+
|
|
78
|
+
constructor(readonly changes: SchemaChange[]) {
|
|
79
|
+
super(
|
|
80
|
+
`The database schema needs changes that are never applied automatically:\n${changes
|
|
81
|
+
.map(
|
|
82
|
+
(change) =>
|
|
83
|
+
` - ${change.description}${change.statements.map((statement) => `\n suggested: ${statement}`).join('')}`,
|
|
84
|
+
)
|
|
85
|
+
.join('\n')}\n` +
|
|
86
|
+
'Write a migration for them (`migrate create <name> --sql`), review the suggested statements — they may ' +
|
|
87
|
+
'rewrite or reject stored rows — and run it before this version starts.',
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export class SchemaOutOfDateError extends Error {
|
|
93
|
+
override readonly name = 'SchemaOutOfDateError';
|
|
94
|
+
|
|
95
|
+
constructor(readonly changes: SchemaChange[]) {
|
|
96
|
+
super(
|
|
97
|
+
`The database schema is not up to date and no owner connection is configured to update it:\n${changes.map((change) => ` - ${change.description}`).join('\n')}\n` +
|
|
98
|
+
'Configure `database.ownerUrl` (the role that owns the tables) or apply the changes with the migration runner.',
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export class UnsafeDatabaseRoleError extends Error {
|
|
104
|
+
override readonly name = 'UnsafeDatabaseRoleError';
|
|
105
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { Logger } from '@nestjs/common';
|
|
2
|
+
|
|
3
|
+
import type { SqlQueryResult, SqlStatement, SqlTenantScope } from './sql-executor.interface.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Connection-level safety and the per-statement tenant scope, shared by every SQL engine.
|
|
7
|
+
*
|
|
8
|
+
* Both are framework-owned on purpose: an engine that hands a broken connection back to its pool, or a scope
|
|
9
|
+
* that outlives its transaction, would leak one request's tenant into the next (plan §3.4, A10).
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Writes the tenant scope into the CURRENT transaction (`is_local = true`): it ends with the transaction and can
|
|
14
|
+
* never reach the next statement on a pooled connection. One statement for all three settings, so applying the
|
|
15
|
+
* scope costs nothing beyond the pipeline it travels in.
|
|
16
|
+
*/
|
|
17
|
+
export const APPLY_SCOPE_SQL =
|
|
18
|
+
"SELECT set_config('app.tenant_scope', $1, true), set_config('app.tenant_id', $2, true), set_config('app.tenant_ids', $3, true)";
|
|
19
|
+
|
|
20
|
+
/** The three settings for a scope, in the order of {@link APPLY_SCOPE_SQL}'s parameters. */
|
|
21
|
+
export function scopeParams(scope: SqlTenantScope): [string, string, string] {
|
|
22
|
+
switch (scope.kind) {
|
|
23
|
+
case 'system':
|
|
24
|
+
return ['system', '', ''];
|
|
25
|
+
case 'tenant':
|
|
26
|
+
return ['tenant', scope.tenantId, ''];
|
|
27
|
+
case 'tenants':
|
|
28
|
+
return ['tenants', '', JSON.stringify(scope.tenantIds)];
|
|
29
|
+
default:
|
|
30
|
+
return ['none', '', ''];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
type ErrorListener = (error: Error) => void;
|
|
35
|
+
|
|
36
|
+
interface PgClientLike {
|
|
37
|
+
_activeQuery?: unknown;
|
|
38
|
+
_queryQueue?: unknown[];
|
|
39
|
+
_sentQueryQueue?: unknown[];
|
|
40
|
+
getTransactionStatus?(): null | string;
|
|
41
|
+
on?(event: 'error', listener: ErrorListener): unknown;
|
|
42
|
+
query(text: string, params?: readonly unknown[]): Promise<{ rowCount: null | number; rows: any[] }>;
|
|
43
|
+
release(error?: Error | boolean): void;
|
|
44
|
+
removeListener?(event: 'error', listener: ErrorListener): unknown;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
interface PgPoolLike {
|
|
48
|
+
connect(): Promise<PgClientLike>;
|
|
49
|
+
connect(
|
|
50
|
+
callback: (error: Error | undefined, client: PgClientLike, release: (error?: Error | boolean) => void) => void,
|
|
51
|
+
): void;
|
|
52
|
+
listenerCount?(event: 'error'): number;
|
|
53
|
+
on?(event: 'error', listener: ErrorListener): unknown;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const poolLogger = new Logger('SqlPool');
|
|
57
|
+
const guardedPools = new WeakSet<object>();
|
|
58
|
+
|
|
59
|
+
/** Whether {@link guardPool} protects `pool`. */
|
|
60
|
+
export function isGuardedPool(pool: unknown): boolean {
|
|
61
|
+
return typeof pool === 'object' && pool !== null && guardedPools.has(pool);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Make a node-postgres pool destroy every connection that is handed back inside a transaction, with a query still
|
|
66
|
+
* in flight, or after it died, instead of re-using it — and keep a dying connection from ending the process.
|
|
67
|
+
*
|
|
68
|
+
* Measured (A10): after a client-side query timeout TypeORM 1.1 released broken connections (the pool then hung)
|
|
69
|
+
* and Kysely 0.29 released a connection still inside the dead transaction — the next request read the previous
|
|
70
|
+
* request's tenant. pg-pool binds `client.release` after emitting `acquire`, so the guard wraps `connect` and covers
|
|
71
|
+
* both the promise form (Kysely, Drizzle, the framework) and the callback form (TypeORM).
|
|
72
|
+
*
|
|
73
|
+
* "In flight" is node-postgres' own busy test: an active query, or one queued or already sent — on a pipelined
|
|
74
|
+
* client the sent ones wait in `_sentQueryQueue`, not in `_activeQuery`.
|
|
75
|
+
*
|
|
76
|
+
* pg-pool listens for `error` only on IDLE connections. A connection that dies while checked out — terminated by
|
|
77
|
+
* the server, or destroyed by node-postgres itself when a pipelined query times out — emits `error` with nobody
|
|
78
|
+
* listening, and Node ends the process on an unhandled `error` event. The guard listens for the whole checkout and
|
|
79
|
+
* hands that error to the release, so the pool destroys the connection. An IDLE connection's error is re-emitted
|
|
80
|
+
* by the pool, which is just as fatal without a listener: Kysely and Drizzle attach none (TypeORM does, and keeps
|
|
81
|
+
* its own), so the guard adds one where nobody listens.
|
|
82
|
+
*/
|
|
83
|
+
export function guardPool<P>(pool: P): P {
|
|
84
|
+
const target = pool as unknown as PgPoolLike;
|
|
85
|
+
if (guardedPools.has(target)) {
|
|
86
|
+
return pool;
|
|
87
|
+
}
|
|
88
|
+
const connect = target.connect.bind(target) as (...args: any[]) => any;
|
|
89
|
+
const unhealthy = (client: PgClientLike): Error | undefined =>
|
|
90
|
+
(client.getTransactionStatus?.() ?? 'I') !== 'I' ||
|
|
91
|
+
client._activeQuery ||
|
|
92
|
+
client._sentQueryQueue?.length ||
|
|
93
|
+
client._queryQueue?.length
|
|
94
|
+
? new Error('released inside a transaction or with a query in flight')
|
|
95
|
+
: undefined;
|
|
96
|
+
const wrap = (client: PgClientLike) => {
|
|
97
|
+
const release = client.release.bind(client);
|
|
98
|
+
let died: Error | undefined;
|
|
99
|
+
const onError: ErrorListener = (error) => {
|
|
100
|
+
died = error;
|
|
101
|
+
};
|
|
102
|
+
client.on?.('error', onError);
|
|
103
|
+
client.release = (error?: Error | boolean) => {
|
|
104
|
+
client.removeListener?.('error', onError);
|
|
105
|
+
return release(error ?? died ?? unhealthy(client));
|
|
106
|
+
};
|
|
107
|
+
return client.release;
|
|
108
|
+
};
|
|
109
|
+
(target as any).connect = (callback?: (...args: any[]) => void) =>
|
|
110
|
+
typeof callback === 'function'
|
|
111
|
+
? connect((error: Error | undefined, client: PgClientLike, release: any) =>
|
|
112
|
+
callback(error, client, error ? release : wrap(client)),
|
|
113
|
+
)
|
|
114
|
+
: connect().then((client: PgClientLike) => {
|
|
115
|
+
wrap(client);
|
|
116
|
+
return client;
|
|
117
|
+
});
|
|
118
|
+
if (!target.listenerCount?.('error')) {
|
|
119
|
+
target.on?.('error', (error) =>
|
|
120
|
+
poolLogger.warn(`An idle database connection failed and was removed from the pool: ${error.message}`),
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
guardedPools.add(target);
|
|
124
|
+
return pool;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Run ONE statement in its own transaction with `scope` applied: `BEGIN` · scope · statement · `COMMIT`, pipelined
|
|
129
|
+
* into a single round trip on a pool created with `pipeline: true` (plan §3.8, A13).
|
|
130
|
+
*
|
|
131
|
+
* Every step is awaited before the connection goes back, so the pool never receives a connection mid-pipeline. A
|
|
132
|
+
* failed statement aborts the transaction; Postgres then answers the `COMMIT` with a rollback, and the statement's
|
|
133
|
+
* own error is what the caller sees.
|
|
134
|
+
*/
|
|
135
|
+
export async function runInOwnTransaction<R>(
|
|
136
|
+
pool: unknown,
|
|
137
|
+
statement: SqlStatement,
|
|
138
|
+
scope: SqlTenantScope,
|
|
139
|
+
): Promise<SqlQueryResult<R>> {
|
|
140
|
+
const client = await (pool as PgPoolLike).connect();
|
|
141
|
+
try {
|
|
142
|
+
const [begin, applied, result, commit] = await Promise.allSettled([
|
|
143
|
+
client.query('BEGIN'),
|
|
144
|
+
client.query(APPLY_SCOPE_SQL, scopeParams(scope)),
|
|
145
|
+
client.query(statement.text, statement.params),
|
|
146
|
+
client.query('COMMIT'),
|
|
147
|
+
]);
|
|
148
|
+
for (const step of [begin, applied, result, commit]) {
|
|
149
|
+
if (step.status === 'rejected') {
|
|
150
|
+
throw step.reason;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
const value = (result as PromiseFulfilledResult<{ rowCount: null | number; rows: R[] }>).value;
|
|
154
|
+
return { rowCount: value.rowCount ?? value.rows.length, rows: value.rows };
|
|
155
|
+
} finally {
|
|
156
|
+
client.release();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type { FieldDescriptor, FieldKind } from '../model-descriptor.interface.js';
|
|
2
|
+
import { UnsupportedQueryError } from './sql-errors.js';
|
|
3
|
+
import { isPathSegment } from './sql-naming.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The dialect-free half of the filter compilers (`postgres/postgres-where.compiler.ts`, `mysql/mysql-where.compiler.ts`):
|
|
7
|
+
* what a filter MEANS — which values are operator objects, which paths are valid, which BSON type a `$type` names — so
|
|
8
|
+
* every SQL database reads a filter the same way and only the SQL it compiles to differs.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export const SCALAR_KINDS = new Set<FieldKind>([
|
|
12
|
+
'bigint',
|
|
13
|
+
'boolean',
|
|
14
|
+
'buffer',
|
|
15
|
+
'date',
|
|
16
|
+
'decimal',
|
|
17
|
+
'enum',
|
|
18
|
+
'id',
|
|
19
|
+
'number',
|
|
20
|
+
'ref',
|
|
21
|
+
'string',
|
|
22
|
+
'uuid',
|
|
23
|
+
]);
|
|
24
|
+
export const REGEX_KINDS = new Set<FieldKind>(['enum', 'ref', 'string']);
|
|
25
|
+
export const COMPARISON = { $gt: '>', $gte: '>=', $lt: '<', $lte: '<=' } as const;
|
|
26
|
+
export type ComparisonOperator = keyof typeof COMPARISON;
|
|
27
|
+
|
|
28
|
+
export type BsonType = 'array' | 'bool' | 'date' | 'null' | 'number' | 'object' | 'objectId' | 'string';
|
|
29
|
+
|
|
30
|
+
const BSON_TYPE_ALIASES: Record<number | string, BsonType> = {
|
|
31
|
+
1: 'number',
|
|
32
|
+
10: 'null',
|
|
33
|
+
16: 'number',
|
|
34
|
+
18: 'number',
|
|
35
|
+
19: 'number',
|
|
36
|
+
2: 'string',
|
|
37
|
+
3: 'object',
|
|
38
|
+
4: 'array',
|
|
39
|
+
7: 'objectId',
|
|
40
|
+
8: 'bool',
|
|
41
|
+
9: 'date',
|
|
42
|
+
array: 'array',
|
|
43
|
+
bool: 'bool',
|
|
44
|
+
date: 'date',
|
|
45
|
+
decimal: 'number',
|
|
46
|
+
double: 'number',
|
|
47
|
+
int: 'number',
|
|
48
|
+
long: 'number',
|
|
49
|
+
null: 'null',
|
|
50
|
+
number: 'number',
|
|
51
|
+
object: 'object',
|
|
52
|
+
objectId: 'objectId',
|
|
53
|
+
string: 'string',
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/** Which column kinds hold a value of a BSON type */
|
|
57
|
+
export const COLUMN_TYPES: Partial<Record<BsonType, (field: FieldDescriptor) => boolean>> = {
|
|
58
|
+
bool: (field) => field.kind === 'boolean',
|
|
59
|
+
date: (field) => field.kind === 'date',
|
|
60
|
+
number: (field) =>
|
|
61
|
+
['bigint', 'decimal', 'number'].includes(field.kind) || (field.kind === 'enum' && field.enumBase === 'number'),
|
|
62
|
+
objectId: (field) => field.kind === 'id' || field.kind === 'ref',
|
|
63
|
+
string: (field) => ['string', 'uuid'].includes(field.kind) || (field.kind === 'enum' && field.enumBase !== 'number'),
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export function bsonType(path: string, value: unknown): BsonType {
|
|
67
|
+
const type =
|
|
68
|
+
(typeof value === 'string' || typeof value === 'number') &&
|
|
69
|
+
Object.prototype.hasOwnProperty.call(BSON_TYPE_ALIASES, value)
|
|
70
|
+
? BSON_TYPE_ALIASES[value]
|
|
71
|
+
: undefined;
|
|
72
|
+
if (!type) {
|
|
73
|
+
throw new UnsupportedQueryError(`$type ${JSON.stringify(value)} at "${path}"`);
|
|
74
|
+
}
|
|
75
|
+
return type;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function splitPath(path: string): string[] {
|
|
79
|
+
const segments = path.split('.');
|
|
80
|
+
for (const segment of segments) {
|
|
81
|
+
if (!isPathSegment(segment)) {
|
|
82
|
+
throw new UnsupportedQueryError(`Invalid path "${path}"`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return segments;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function itemOf(field: FieldDescriptor): FieldDescriptor {
|
|
89
|
+
return { ...field, isArray: false };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
93
|
+
if (value === null || typeof value !== 'object') {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
const prototype = Object.getPrototypeOf(value);
|
|
97
|
+
return prototype === Object.prototype || prototype === null;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** An object of operators. Mixing operators and fields is refused, as MongoDB refuses it. */
|
|
101
|
+
export function isOperatorObject(value: unknown): boolean {
|
|
102
|
+
if (!isPlainObject(value)) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
const keys = Object.keys(value);
|
|
106
|
+
const operators = keys.filter((key) => key.startsWith('$')).length;
|
|
107
|
+
if (operators && operators !== keys.length) {
|
|
108
|
+
throw new UnsupportedQueryError('An object may not mix operators and fields');
|
|
109
|
+
}
|
|
110
|
+
return operators > 0;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** JSON for a JSON parameter: dates as ISO strings and ids as hex (their `toJSON`), bigints as numbers or strings */
|
|
114
|
+
export function toJson(value: unknown): string {
|
|
115
|
+
return JSON.stringify(value, (_key, item) =>
|
|
116
|
+
typeof item === 'bigint' ? (Number.isSafeInteger(Number(item)) ? Number(item) : item.toString()) : item,
|
|
117
|
+
);
|
|
118
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { UnsupportedQueryError } from './sql/sql-errors.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Argument checks every data store applies the same way, so a call refused on one database is refused on all.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/** native() / raw(): the reason is logged, so it has to say something */
|
|
8
|
+
export function assertAccessReason(reason: string, method: string): void {
|
|
9
|
+
if (!reason?.trim() || reason.trim().length < 20) {
|
|
10
|
+
throw new Error(`${method}() requires a meaningful reason (min 20 chars) — explain why native access is needed`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** find({ sample }): a positive integer — MongoDB refuses anything else in `$sample`, so every store does */
|
|
15
|
+
export function assertSampleSize(sample: unknown): number {
|
|
16
|
+
if (typeof sample !== 'number' || !Number.isInteger(sample) || sample < 1) {
|
|
17
|
+
throw new Error(`sample must be a positive integer, got ${String(sample)}`);
|
|
18
|
+
}
|
|
19
|
+
return sample;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** A whole number for a SQL clause (`limit`, `skip`, a push `position` or `slice`) */
|
|
23
|
+
export function assertInteger(value: unknown, name: string): number {
|
|
24
|
+
if (typeof value !== 'number' || !Number.isInteger(value)) {
|
|
25
|
+
throw new UnsupportedQueryError(`${name} must be an integer`);
|
|
26
|
+
}
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function assertNonNegativeInteger(value: unknown, name: string): number {
|
|
31
|
+
const result = assertInteger(value, name);
|
|
32
|
+
if (result < 0) {
|
|
33
|
+
throw new UnsupportedQueryError(`${name} must not be negative`);
|
|
34
|
+
}
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** pushToArray() / pullFromArray(): a field name, never an operator */
|
|
39
|
+
export function assertArrayField(field: string, method: string): void {
|
|
40
|
+
if (typeof field !== 'string' || !field || field.startsWith('$') || field.includes('\0')) {
|
|
41
|
+
throw new Error(`${method}: invalid field name "${field}"`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const SELECTABLE = /^[A-Za-z_]\w*$/;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* `select`: plain field names only. MongoDB joins them into a projection string, where `+name` forces a
|
|
49
|
+
* `select: false` field (a password hash) into the result and `-name` turns the projection into an exclusion —
|
|
50
|
+
* a caller passing names through must not be able to do either by accident.
|
|
51
|
+
*/
|
|
52
|
+
export function assertSelectFields(select: readonly string[] | undefined): void {
|
|
53
|
+
for (const field of select ?? []) {
|
|
54
|
+
if (typeof field !== 'string' || !SELECTABLE.test(field)) {
|
|
55
|
+
throw new Error(`select: invalid field name "${String(field)}"`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* `select` and `exclude` together: plain field names each, and never both — MongoDB refuses a projection that
|
|
62
|
+
* includes and excludes at once. The id cannot be left out: every record carries it.
|
|
63
|
+
*/
|
|
64
|
+
export function assertProjection(options: { exclude?: readonly string[]; select?: readonly string[] }): void {
|
|
65
|
+
assertSelectFields(options.select);
|
|
66
|
+
assertSelectFields(options.exclude);
|
|
67
|
+
if (options.select?.length && options.exclude?.length) {
|
|
68
|
+
throw new Error('select and exclude cannot be combined');
|
|
69
|
+
}
|
|
70
|
+
if (options.exclude?.some((field) => field === 'id' || field === '_id')) {
|
|
71
|
+
throw new Error('exclude: the id is always returned');
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { DataStore, StoredRecord, Where } from './data-store.interface.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Set fields on the record matching `where`, or create it — MongoDB's `updateOne(…, { upsert: true })` on any store.
|
|
5
|
+
*
|
|
6
|
+
* The store port has no upsert of its own (an `INSERT … ON CONFLICT` needs the conflict target, which only the caller
|
|
7
|
+
* knows), so this composes it: an atomic `updateOne`, and an `insert` when nothing matched. `where` must name a unique
|
|
8
|
+
* key of the model — that index is what turns a concurrent second insert into a duplicate-key error, after which the
|
|
9
|
+
* record exists and the update is applied to it.
|
|
10
|
+
*
|
|
11
|
+
* `onInsert` are fields only a new record gets (MongoDB's `$setOnInsert`).
|
|
12
|
+
*/
|
|
13
|
+
export async function upsertRecord<T>(
|
|
14
|
+
store: DataStore<T>,
|
|
15
|
+
where: Where<T> & Record<string, unknown>,
|
|
16
|
+
set: Record<string, unknown>,
|
|
17
|
+
onInsert: Record<string, unknown> = {},
|
|
18
|
+
): Promise<StoredRecord<T>> {
|
|
19
|
+
const updated = await store.updateOne(where, { $set: set } as any);
|
|
20
|
+
if (updated) {
|
|
21
|
+
return updated;
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
return await store.insert({ ...where, ...onInsert, ...set } as any);
|
|
25
|
+
} catch (error) {
|
|
26
|
+
if ((error as { code?: unknown })?.code !== 11000) {
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
// Another caller created it between the two steps: it exists now
|
|
30
|
+
const retried = await store.updateOne(where, { $set: set } as any);
|
|
31
|
+
if (!retried) {
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
return retried;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { DataStore } from './data-store.interface.js';
|
|
2
|
+
import { UnsupportedCapabilityError } from './unsupported-capability.error.js';
|
|
3
|
+
|
|
4
|
+
/** The data methods of the `DataStore` port */
|
|
5
|
+
const STORE_METHODS = new Set([
|
|
6
|
+
'count',
|
|
7
|
+
'deleteById',
|
|
8
|
+
'deleteMany',
|
|
9
|
+
'deleteOne',
|
|
10
|
+
'distinct',
|
|
11
|
+
'find',
|
|
12
|
+
'findById',
|
|
13
|
+
'findOne',
|
|
14
|
+
'insert',
|
|
15
|
+
'native',
|
|
16
|
+
'pullFromArray',
|
|
17
|
+
'pushToArray',
|
|
18
|
+
'raw',
|
|
19
|
+
'sum',
|
|
20
|
+
'updateById',
|
|
21
|
+
'updateMany',
|
|
22
|
+
'updateOne',
|
|
23
|
+
]);
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The store of a model no database can hold — the project runs with `database: false`, so a model registered with
|
|
27
|
+
* `CorePersistenceModule.forFeature()` (the framework registers its file metadata, for one) has nowhere to go. Every
|
|
28
|
+
* data method refuses with the reason; nothing fails while the application merely boots.
|
|
29
|
+
*/
|
|
30
|
+
export function unavailableStore<T = Record<string, any>>(modelName: string, reason: string): DataStore<T> {
|
|
31
|
+
const capabilities = {
|
|
32
|
+
aggregatePipeline: false,
|
|
33
|
+
changeFeed: false,
|
|
34
|
+
gridfs: false,
|
|
35
|
+
idType: 'objectId' as const,
|
|
36
|
+
mongoosePopulate: false,
|
|
37
|
+
rawFilterArm: false,
|
|
38
|
+
rls: false,
|
|
39
|
+
textSearch: false,
|
|
40
|
+
transactions: false,
|
|
41
|
+
};
|
|
42
|
+
return new Proxy({} as DataStore<T>, {
|
|
43
|
+
get(_target, property) {
|
|
44
|
+
if (property === 'modelName') {
|
|
45
|
+
return modelName;
|
|
46
|
+
}
|
|
47
|
+
if (property === 'driver') {
|
|
48
|
+
return 'none';
|
|
49
|
+
}
|
|
50
|
+
if (property === 'capabilities') {
|
|
51
|
+
return capabilities;
|
|
52
|
+
}
|
|
53
|
+
// Only the port's methods refuse: Nest probes every provider for lifecycle hooks (`onModuleInit`, …), and a
|
|
54
|
+
// promise check reads `then` — those must find nothing
|
|
55
|
+
if (typeof property !== 'string' || !STORE_METHODS.has(property)) {
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
return () => {
|
|
59
|
+
throw new UnsupportedCapabilityError(`${modelName}.${property}(): ${reason}`);
|
|
60
|
+
};
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An operation the model's data store cannot perform (plan §3.6: features ask the store, never the driver name).
|
|
3
|
+
* Named, so a call that would need MongoDB on a SQL-stored model fails loudly instead of reaching another database.
|
|
4
|
+
*/
|
|
5
|
+
export class UnsupportedCapabilityError extends Error {
|
|
6
|
+
override readonly name = 'UnsupportedCapabilityError';
|
|
7
|
+
}
|