@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,98 @@
|
|
|
1
|
+
import { Logger } from '@nestjs/common';
|
|
2
|
+
|
|
3
|
+
import { isObjectIdLike } from '../helpers/id.helper.js';
|
|
4
|
+
import type { DataStore } from './data-store.interface.js';
|
|
5
|
+
import { getModelDescriptor } from './model-metadata.registry.js';
|
|
6
|
+
import { getRegisteredDataStore } from './persistence-runtime.registry.js';
|
|
7
|
+
|
|
8
|
+
/** A populate option as `toPopulateOptions()` yields it */
|
|
9
|
+
export interface NeutralPopulateOption {
|
|
10
|
+
/** Target model name, when the option overrides the field's `ref` */
|
|
11
|
+
model?: unknown;
|
|
12
|
+
path: string;
|
|
13
|
+
populate?: unknown;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const logger = new Logger('NeutralPopulate');
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Populate references of plain records the way Mongoose populate does, for stores without Mongoose documents (plan
|
|
20
|
+
* §3.6): per reference field, ONE `id $in` read through the target model's store — so its tenant layers, rights and
|
|
21
|
+
* row check apply to the loaded records as to any other read — then nested options, then the ids are replaced in
|
|
22
|
+
* place. An unresolved single reference becomes `null`, unresolved items of a reference list are dropped, as with
|
|
23
|
+
* Mongoose.
|
|
24
|
+
*/
|
|
25
|
+
export async function populateNeutral(
|
|
26
|
+
data: unknown,
|
|
27
|
+
options: ReadonlyArray<NeutralPopulateOption | string>,
|
|
28
|
+
modelName: string,
|
|
29
|
+
): Promise<void> {
|
|
30
|
+
const records = (Array.isArray(data) ? data : [data]).filter(
|
|
31
|
+
(record): record is Record<string, any> => !!record && typeof record === 'object',
|
|
32
|
+
);
|
|
33
|
+
if (!records.length || !options.length) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const descriptor = getModelDescriptor(modelName);
|
|
37
|
+
for (const option of options) {
|
|
38
|
+
const entry = typeof option === 'string' ? { path: option } : option;
|
|
39
|
+
for (const path of String(entry.path ?? '')
|
|
40
|
+
.split(/\s+/)
|
|
41
|
+
.filter(Boolean)) {
|
|
42
|
+
const field = descriptor?.fields[path];
|
|
43
|
+
const target = typeof entry.model === 'string' ? entry.model : field?.ref;
|
|
44
|
+
if (!field || field.kind !== 'ref' || !target) {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const store: DataStore<any> | undefined = getRegisteredDataStore(target);
|
|
48
|
+
if (!store) {
|
|
49
|
+
logger.debug(`${modelName}.${path}: no store is registered for "${target}", the reference stays an id`);
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const ids = new Set<string>();
|
|
53
|
+
for (const record of records) {
|
|
54
|
+
for (const id of idsOf(record[path])) {
|
|
55
|
+
ids.add(id);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (!ids.size) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
const loaded = await store.find({ id: { $in: [...ids] } });
|
|
62
|
+
if (entry.populate) {
|
|
63
|
+
await populateNeutral(loaded, toList(entry.populate), target);
|
|
64
|
+
}
|
|
65
|
+
const byId = new Map(loaded.map((item) => [String(item.id), item]));
|
|
66
|
+
for (const record of records) {
|
|
67
|
+
const value = record[path];
|
|
68
|
+
if (Array.isArray(value)) {
|
|
69
|
+
record[path] = value.map((item) => byId.get(idOf(item))).filter((item) => item !== undefined);
|
|
70
|
+
} else if (value !== undefined && value !== null) {
|
|
71
|
+
record[path] = byId.get(idOf(value)) ?? null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function toList(populate: unknown): Array<NeutralPopulateOption | string> {
|
|
79
|
+
return (Array.isArray(populate) ? populate : [populate]) as Array<NeutralPopulateOption | string>;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function idOf(value: unknown): string {
|
|
83
|
+
if (isObjectIdLike(value)) {
|
|
84
|
+
return value.toHexString();
|
|
85
|
+
}
|
|
86
|
+
if (value && typeof value === 'object') {
|
|
87
|
+
const nested = (value as { _id?: unknown; id?: unknown }).id ?? (value as { _id?: unknown })._id;
|
|
88
|
+
return String(nested ?? value);
|
|
89
|
+
}
|
|
90
|
+
return String(value);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function idsOf(value: unknown): string[] {
|
|
94
|
+
if (value === undefined || value === null) {
|
|
95
|
+
return [];
|
|
96
|
+
}
|
|
97
|
+
return (Array.isArray(value) ? value : [value]).filter((item) => item !== undefined && item !== null).map(idOf);
|
|
98
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persistence options a model class declares in code.
|
|
3
|
+
*/
|
|
4
|
+
export interface PersistedModelOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Name of the data source the model is stored in (a key of `database.sources`). The configuration's
|
|
7
|
+
* `database.models` wins over this declaration, so operations can move a model without a code change.
|
|
8
|
+
* @default the default source
|
|
9
|
+
*/
|
|
10
|
+
dataSource?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const PERSISTED_MODEL_OPTIONS = Symbol('PERSISTED_MODEL_OPTIONS');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Every class decorated with `@PersistedModel`, by class name. `SchemaFactory.createForClass()` keeps no reference to
|
|
17
|
+
* its class, so a model registered as `{ name, schema }` is matched to its declaration through the name
|
|
18
|
+
*/
|
|
19
|
+
const declaredByName = new Map<string, Function[]>();
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Declare where a model is stored.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* @PersistedModel({ dataSource: 'logs' })
|
|
27
|
+
* @Schema({ timestamps: true })
|
|
28
|
+
* export class AuditEntry extends CorePersistenceModel { … }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export function PersistedModel(options: PersistedModelOptions): ClassDecorator {
|
|
32
|
+
return (target) => {
|
|
33
|
+
Reflect.defineMetadata(PERSISTED_MODEL_OPTIONS, { ...options }, target);
|
|
34
|
+
const classes = declaredByName.get(target.name) ?? [];
|
|
35
|
+
if (!classes.includes(target)) {
|
|
36
|
+
declaredByName.set(target.name, [...classes, target]);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** The options a class declared with `@PersistedModel` (inherited from a parent class), if any. */
|
|
42
|
+
export function getPersistedModelOptions(target: Function): PersistedModelOptions | undefined {
|
|
43
|
+
return Reflect.getMetadata(PERSISTED_MODEL_OPTIONS, target);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The options declared for the model registered under `name` without its class: those of the `@PersistedModel` class
|
|
48
|
+
* of that name. Two decorated classes of that name that name different sources cannot be told apart — the
|
|
49
|
+
* registration must pass `model:` (or `dataSource:`) then, so this throws instead of guessing.
|
|
50
|
+
*/
|
|
51
|
+
export function getPersistedModelOptionsByName(name: string): PersistedModelOptions | undefined {
|
|
52
|
+
const classes = declaredByName.get(name) ?? [];
|
|
53
|
+
const sources = new Set(classes.map((target) => getPersistedModelOptions(target)?.dataSource));
|
|
54
|
+
if (sources.size > 1) {
|
|
55
|
+
throw new Error(
|
|
56
|
+
`@PersistedModel: ${classes.length} classes named "${name}" declare different data sources; pass \`model\` ` +
|
|
57
|
+
`(or \`dataSource\`) in CorePersistenceModule.forFeature() to say which one this model is`,
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
return classes.length ? getPersistedModelOptions(classes[0]) : undefined;
|
|
61
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process-wide state of the persistence layer: which models were registered, which store serves each, and the
|
|
3
|
+
* runtime that routes a model to its data source. Types-only imports — an import-free leaf, so every persistence
|
|
4
|
+
* file and the services may read it without forming a cycle (see `.claude/rules/architecture.md` → "DI Token
|
|
5
|
+
* Placement (SWC-Safe)").
|
|
6
|
+
*/
|
|
7
|
+
import type { DataStore } from './data-store.interface.js';
|
|
8
|
+
import type { LockStore } from './lock-store.interface.js';
|
|
9
|
+
|
|
10
|
+
/** A model as `CorePersistenceModule.forFeature()` registered it */
|
|
11
|
+
export interface PersistedModelRegistration {
|
|
12
|
+
/** The source the model class declares with `@PersistedModel`, or the definition's `dataSource` */
|
|
13
|
+
declaredSource?: string;
|
|
14
|
+
name: string;
|
|
15
|
+
/** The model's Mongoose schema */
|
|
16
|
+
schema: unknown;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Routes a model to the store of its data source (plan §3.9). Installed by `CoreModule.forRoot()` when the
|
|
21
|
+
* configuration names a SQL source; without one, every model keeps its Mongoose store.
|
|
22
|
+
*/
|
|
23
|
+
export interface PersistenceRuntime {
|
|
24
|
+
close(): Promise<void>;
|
|
25
|
+
/** The lease store of the default source when it is a SQL database; `undefined` when it is MongoDB */
|
|
26
|
+
defaultLockStore(): Promise<LockStore | undefined>;
|
|
27
|
+
/** Closes what only the boot needs (the owner connections that migrate the schema), once every store exists */
|
|
28
|
+
releaseBootConnections(): Promise<void>;
|
|
29
|
+
/** The store of a model; `mongoModel` is its Mongoose model, used when the model stays on MongoDB */
|
|
30
|
+
resolveStore(name: string, mongoModel: unknown): Promise<DataStore<any>>;
|
|
31
|
+
/** The configured SQL sources, each with a ping (`SELECT 1` on its application connection) for the health check */
|
|
32
|
+
sqlSources(): { name: string; ping: () => Promise<void> }[];
|
|
33
|
+
/** The default source when it is a SQL database — where the framework keeps its migration state */
|
|
34
|
+
defaultSqlSource(): undefined | { engine?: string; ownerUrl?: string; url: string };
|
|
35
|
+
/** Sources and model routing for the Hub; connection URLs reduced to scheme and host */
|
|
36
|
+
describe(): PersistenceOverview;
|
|
37
|
+
/**
|
|
38
|
+
* Delete the rows whose TTL has passed, in every SQL table this application opened — what MongoDB's TTL monitor does
|
|
39
|
+
* for a collection. Answers per model with a TTL field how many rows went
|
|
40
|
+
*/
|
|
41
|
+
sweepExpired(now?: Date): Promise<{ deleted: number; model: string }[]>;
|
|
42
|
+
/**
|
|
43
|
+
* Where Better-Auth keeps its data: the SQL source the `users` table is routed to, or `undefined` when the user model
|
|
44
|
+
* stays on MongoDB. Better-Auth and the user model share one row per user, so Better-Auth never decides this itself
|
|
45
|
+
*/
|
|
46
|
+
iamStorage(): Promise<IamSqlStorage | undefined>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** The SQL source Better-Auth runs on — the one the `users` table lives in */
|
|
50
|
+
export interface IamSqlStorage {
|
|
51
|
+
/**
|
|
52
|
+
* Bring the tables Better-Auth owns up to date. With the owner configured, `migrate` receives the OWNER's pool and runs
|
|
53
|
+
* while the framework's schema lock is held; the application role is then granted on `tables` and checked like on the
|
|
54
|
+
* framework's own tables. Without `ownerUrl`, `migrate` receives the application pool and must only verify.
|
|
55
|
+
*/
|
|
56
|
+
applySchema(migrate: (pool: unknown, asOwner: boolean) => Promise<void>, tables: string[]): Promise<void>;
|
|
57
|
+
/** The application role's `pg` pool of that source — Better-Auth's own adapter runs on it */
|
|
58
|
+
pool: unknown;
|
|
59
|
+
/** Name of the data source */
|
|
60
|
+
source: string;
|
|
61
|
+
/** The store of the user model */
|
|
62
|
+
users: DataStore<any>;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** What the data-source configuration resolved to, for operators (the Hub's persistence panel) */
|
|
66
|
+
export interface PersistenceOverview {
|
|
67
|
+
defaultSource?: string;
|
|
68
|
+
models: { name: string; source?: string }[];
|
|
69
|
+
sources: { driver: string; engine?: string; host: string; name: string; ownerConfigured: boolean }[];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const models = new Map<string, PersistedModelRegistration>();
|
|
73
|
+
/** Columns another library keeps in a framework table (Better-Auth's on `users`), per table */
|
|
74
|
+
const foreignColumns = new Map<string, Set<string>>();
|
|
75
|
+
const stores = new Map<string, DataStore<any>>();
|
|
76
|
+
/**
|
|
77
|
+
* The store serving a model, keyed by the Mongoose model INSTANCE. Every application has its own connection and
|
|
78
|
+
* therefore its own model instances, so this lookup — unlike the by-name map above — can never hand one application
|
|
79
|
+
* the store another one (in the same process: tests) created.
|
|
80
|
+
*/
|
|
81
|
+
const storesByModel = new WeakMap<object, DataStore<any>>();
|
|
82
|
+
let runtime: PersistenceRuntime | undefined;
|
|
83
|
+
|
|
84
|
+
export function registerPersistedModel(registration: PersistedModelRegistration): void {
|
|
85
|
+
models.set(registration.name, registration);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function getPersistedModels(): PersistedModelRegistration[] {
|
|
89
|
+
return [...models.values()];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Declare columns another library adds to a framework table: no field of the model declares them, but they are not
|
|
94
|
+
* left-overs of a removed field either — the schema evolution does not report them at every boot
|
|
95
|
+
*/
|
|
96
|
+
export function registerForeignColumns(table: string, columns: readonly string[]): void {
|
|
97
|
+
const known = foreignColumns.get(table) ?? new Set<string>();
|
|
98
|
+
columns.forEach((column) => known.add(column));
|
|
99
|
+
foreignColumns.set(table, known);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function isForeignColumn(table: string, column: string): boolean {
|
|
103
|
+
return foreignColumns.get(table)?.has(column) ?? false;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** Remember the store serving a model — the neutral populate loads references through it */
|
|
107
|
+
export function registerDataStore(name: string, store: DataStore<any>): void {
|
|
108
|
+
stores.set(name, store);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function getRegisteredDataStore(name: string): DataStore<any> | undefined {
|
|
112
|
+
return stores.get(name);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* The store serving a model, for a service that holds the MongoDB connection: through the connection's Mongoose model
|
|
117
|
+
* while MongoDB is connected, by name without one (PostgreSQL alone, or `database: false`) — the store registered for
|
|
118
|
+
* the model is then the only one there is
|
|
119
|
+
*/
|
|
120
|
+
export function getModelStore(
|
|
121
|
+
connection: { models?: Record<string, unknown> } | null | undefined,
|
|
122
|
+
name: string,
|
|
123
|
+
): DataStore<any> | undefined {
|
|
124
|
+
if (!connection) {
|
|
125
|
+
return getRegisteredDataStore(name);
|
|
126
|
+
}
|
|
127
|
+
const model = connection.models?.[name];
|
|
128
|
+
return model ? getStoreForModel(model) : undefined;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Remember which store serves the model behind a Mongoose model instance, so a service written against
|
|
133
|
+
* `@InjectModel()` runs on the store its model was routed to
|
|
134
|
+
*/
|
|
135
|
+
export function bindStoreToModel(model: unknown, store: DataStore<any>): void {
|
|
136
|
+
if (model && typeof model === 'function') {
|
|
137
|
+
storesByModel.set(model, store);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** The store routed for the model behind this Mongoose model instance, when one was registered */
|
|
142
|
+
export function getStoreForModel(model: unknown): DataStore<any> | undefined {
|
|
143
|
+
return model && typeof model === 'function' ? storesByModel.get(model) : undefined;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function setPersistenceRuntime(value: PersistenceRuntime | undefined): void {
|
|
147
|
+
runtime = value;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export function getPersistenceRuntime(): PersistenceRuntime | undefined {
|
|
151
|
+
return runtime;
|
|
152
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DI tokens of the persistence layer. Import-free leaf — see `.claude/rules/architecture.md`
|
|
3
|
+
* → "DI Token Placement (SWC-Safe)".
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** Injection token of the data store of a model, by model name. */
|
|
7
|
+
export function getStoreToken(modelName: string): string {
|
|
8
|
+
return `DataStore:${modelName}`;
|
|
9
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { RequestContext } from '../../services/request-context.service.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Audit-field decisions (`createdBy` / `updatedBy`), shared by every data store.
|
|
5
|
+
*
|
|
6
|
+
* `mongooseAuditFieldsPlugin` applies them to Mongoose documents and update objects; a SQL store applies
|
|
7
|
+
* the same functions to its rows and patches. Update objects use the Mongo-operator form (`$set`,
|
|
8
|
+
* `$setOnInsert`), which is also the neutral update language of the data store port.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/** Which audit fields a model stores. */
|
|
12
|
+
export interface AuditFieldPresence {
|
|
13
|
+
createdBy: boolean;
|
|
14
|
+
updatedBy: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The id the audit fields are stamped with: the current user's. `undefined` for system work (no
|
|
19
|
+
* user context: seeding, cron, migrations) — the fields are then left as they are.
|
|
20
|
+
*/
|
|
21
|
+
export function resolveAuditActorId(): string | undefined {
|
|
22
|
+
return RequestContext.getCurrentUser()?.id || undefined;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Stamp a document that is being written whole (create, or save of an existing document):
|
|
27
|
+
* `createdBy` only on a NEW document that does not carry one yet, `updatedBy` always.
|
|
28
|
+
*/
|
|
29
|
+
export function stampAuditOnWrite(
|
|
30
|
+
doc: Record<string, any>,
|
|
31
|
+
actorId: string,
|
|
32
|
+
fields: AuditFieldPresence,
|
|
33
|
+
isNew: boolean,
|
|
34
|
+
): void {
|
|
35
|
+
if (fields.createdBy && isNew && !doc['createdBy']) {
|
|
36
|
+
doc['createdBy'] = actorId;
|
|
37
|
+
}
|
|
38
|
+
if (fields.updatedBy) {
|
|
39
|
+
doc['updatedBy'] = actorId;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Stamp an update object: `updatedBy` flat and inside `$set`, and `createdBy` via `$setOnInsert` for
|
|
45
|
+
* the upsert case — unless the update already sets `createdBy`, which would make the two operators
|
|
46
|
+
* collide on one path.
|
|
47
|
+
*/
|
|
48
|
+
export function stampAuditOnUpdate(update: Record<string, any>, actorId: string, fields: AuditFieldPresence): void {
|
|
49
|
+
if (fields.updatedBy) {
|
|
50
|
+
update['updatedBy'] = actorId;
|
|
51
|
+
if (update.$set) {
|
|
52
|
+
update.$set['updatedBy'] = actorId;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (fields.createdBy && !update['createdBy'] && !update.$set?.['createdBy']) {
|
|
56
|
+
if (!update.$setOnInsert) {
|
|
57
|
+
update.$setOnInsert = {};
|
|
58
|
+
}
|
|
59
|
+
if (!update.$setOnInsert['createdBy']) {
|
|
60
|
+
update.$setOnInsert['createdBy'] = actorId;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Stamp a replacement document (no operators): `updatedBy`, and `createdBy` when absent — for the
|
|
67
|
+
* upsert case, where the replacement becomes a new document.
|
|
68
|
+
*/
|
|
69
|
+
export function stampAuditOnReplace(
|
|
70
|
+
replacement: Record<string, any>,
|
|
71
|
+
actorId: string,
|
|
72
|
+
fields: AuditFieldPresence,
|
|
73
|
+
): void {
|
|
74
|
+
if (fields.updatedBy) {
|
|
75
|
+
replacement['updatedBy'] = actorId;
|
|
76
|
+
}
|
|
77
|
+
if (fields.createdBy && !replacement['createdBy']) {
|
|
78
|
+
replacement['createdBy'] = actorId;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import bcrypt from 'bcrypt';
|
|
2
|
+
import { sha256 } from 'js-sha256';
|
|
3
|
+
|
|
4
|
+
import { ConfigService } from '../../services/config.service.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Password hashing decisions, shared by every data store: a plaintext password never reaches storage,
|
|
8
|
+
* whichever API wrote it. `mongoosePasswordPlugin` applies them to Mongoose writes; a SQL store applies
|
|
9
|
+
* the same functions to its rows and patches.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export async function hashUpdatePassword(update: any) {
|
|
13
|
+
if (!update) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (update.password) {
|
|
17
|
+
update.password = await hashPassword(update.password);
|
|
18
|
+
}
|
|
19
|
+
if (update.$set?.password) {
|
|
20
|
+
update.$set.password = await hashPassword(update.$set.password);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Compiled RegExp cache (built once on first call)
|
|
25
|
+
let compiledSkipPatterns: RegExp[] | null = null;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Reset the compiled skip patterns cache.
|
|
29
|
+
* Use in test environments where ConfigService is reset between test suites.
|
|
30
|
+
*/
|
|
31
|
+
export function resetSkipPatternsCache(): void {
|
|
32
|
+
compiledSkipPatterns = null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function getSkipPatterns(): RegExp[] {
|
|
36
|
+
if (compiledSkipPatterns !== null) {
|
|
37
|
+
return compiledSkipPatterns;
|
|
38
|
+
}
|
|
39
|
+
const pluginConfig = ConfigService.configFastButReadOnly?.security?.mongoosePasswordPlugin;
|
|
40
|
+
if (pluginConfig && typeof pluginConfig === 'object' && 'skipPatterns' in pluginConfig && pluginConfig.skipPatterns) {
|
|
41
|
+
compiledSkipPatterns = (pluginConfig.skipPatterns as (string | RegExp)[]).map((p) =>
|
|
42
|
+
p instanceof RegExp ? p : new RegExp(p),
|
|
43
|
+
);
|
|
44
|
+
} else {
|
|
45
|
+
compiledSkipPatterns = [];
|
|
46
|
+
}
|
|
47
|
+
return compiledSkipPatterns;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export async function hashPassword(password: string): Promise<string> {
|
|
51
|
+
// Already BCrypt-hashed → skip
|
|
52
|
+
if (/^\$2[aby]\$\d+\$/.test(password)) {
|
|
53
|
+
return password;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Check configured skip patterns (e.g. sentinel/lock values)
|
|
57
|
+
const skipPatterns = getSkipPatterns();
|
|
58
|
+
if (skipPatterns.some((pattern) => pattern.test(password))) {
|
|
59
|
+
return password;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// SHA256 pre-hash if configured and password is not already SHA256
|
|
63
|
+
const sha256Enabled = ConfigService.configFastButReadOnly?.sha256;
|
|
64
|
+
if (sha256Enabled && !/^[a-f0-9]{64}$/i.test(password)) {
|
|
65
|
+
password = sha256(password);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return bcrypt.hash(password, 10);
|
|
69
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { RoleEnum } from '../../enums/role.enum.js';
|
|
2
|
+
import { ConfigService } from '../../services/config.service.js';
|
|
3
|
+
import { RequestContext } from '../../services/request-context.service.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Role-assignment decisions (who may change `roles`), shared by every data store.
|
|
7
|
+
*
|
|
8
|
+
* `mongooseRoleGuardPlugin` applies them to Mongoose documents and update objects; a SQL store applies
|
|
9
|
+
* the same functions to its writes. This answers WHO may change roles (configurable, bypassable, strips
|
|
10
|
+
* the change); which VALUES may exist at all is the system-role policy's question.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Check if the current user is allowed to modify roles.
|
|
15
|
+
* Returns true if:
|
|
16
|
+
* - No user context (system operation)
|
|
17
|
+
* - bypassRoleGuard is active (via RequestContext.runWithBypassRoleGuard())
|
|
18
|
+
* - User has ADMIN role
|
|
19
|
+
* - User has one of the configured allowedRoles
|
|
20
|
+
*/
|
|
21
|
+
export function isRoleChangeAllowed(): boolean {
|
|
22
|
+
const currentUser = RequestContext.getCurrentUser();
|
|
23
|
+
// No user context (system operation) → allow
|
|
24
|
+
if (!currentUser) {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
// Explicit bypass (e.g. signUp with default roles, authorized service operations)
|
|
28
|
+
if (RequestContext.isBypassRoleGuard()) {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
// Admin → always allow
|
|
32
|
+
if (currentUser.hasRole?.([RoleEnum.ADMIN]) || currentUser.roles?.includes(RoleEnum.ADMIN)) {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Check configured allowedRoles
|
|
37
|
+
const pluginConfig = ConfigService.configFastButReadOnly?.security?.mongooseRoleGuardPlugin;
|
|
38
|
+
if (pluginConfig && typeof pluginConfig === 'object' && 'allowedRoles' in pluginConfig && pluginConfig.allowedRoles) {
|
|
39
|
+
const allowedRoles: string[] = pluginConfig.allowedRoles as string[];
|
|
40
|
+
if (currentUser.roles?.some((role: string) => allowedRoles.includes(role))) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Whether an update object (flat or with operators) touches `roles`. */
|
|
49
|
+
export function updateChangesRoles(update: any): boolean {
|
|
50
|
+
return !!(
|
|
51
|
+
update?.roles ||
|
|
52
|
+
update?.$set?.roles ||
|
|
53
|
+
update?.$push?.roles ||
|
|
54
|
+
update?.$addToSet?.roles ||
|
|
55
|
+
update?.$pull?.roles
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Remove every change to `roles` from an update object, in all operator forms. */
|
|
60
|
+
export function stripRoleChanges(update: any): void {
|
|
61
|
+
delete update.roles;
|
|
62
|
+
if (update.$set?.roles) {
|
|
63
|
+
delete update.$set.roles;
|
|
64
|
+
}
|
|
65
|
+
if (update.$push?.roles) {
|
|
66
|
+
delete update.$push.roles;
|
|
67
|
+
}
|
|
68
|
+
if (update.$addToSet?.roles) {
|
|
69
|
+
delete update.$addToSet.roles;
|
|
70
|
+
}
|
|
71
|
+
if (update.$pull?.roles) {
|
|
72
|
+
delete update.$pull.roles;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { BadRequestException } from '@nestjs/common';
|
|
2
|
+
|
|
3
|
+
import { looksLikeSystemRole, SYSTEM_ROLE_PREFIX } from '../../enums/role.enum.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* System-role decisions (which role VALUES may be stored at all), shared by every data store.
|
|
7
|
+
*
|
|
8
|
+
* `mongooseSystemRolePlugin` applies them to Mongoose writes; a SQL store applies the same functions and
|
|
9
|
+
* backs them with a `CHECK` constraint. Unconditional by design: being ADMIN or holding a bypass is
|
|
10
|
+
* authority over a role change, never permission to store a value that is invalid by construction.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** Normalize an unknown value to a string array; anything else becomes an empty baseline. */
|
|
14
|
+
export function toRoleArray(value: unknown): string[] {
|
|
15
|
+
return Array.isArray(value) ? value.filter((entry): entry is string => typeof entry === 'string') : [];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Throw if the write INTRODUCES a system role.
|
|
20
|
+
*
|
|
21
|
+
* `alreadyStored` is the document's current value. A system role that is already in there is NOT
|
|
22
|
+
* refused, and this is load-bearing rather than lenient: `CrudService.update()` writes the whole
|
|
23
|
+
* object back, so a login (`updateRefreshToken` → `update`) re-sends the stored `roles` verbatim.
|
|
24
|
+
* Refusing that would lock every already-contaminated account out of the system on upgrade — and
|
|
25
|
+
* would do the same, fleet-wide, to any project whose own role name happens to start with `s_`.
|
|
26
|
+
* An upgrade must not cause a login outage; cleaning up stored values is what the migration guide's
|
|
27
|
+
* audit query is for.
|
|
28
|
+
*
|
|
29
|
+
* Accepts anything: a non-array (nothing to check) and non-string elements (cannot be a system
|
|
30
|
+
* role) pass through untouched — type validation is not this plugin's job.
|
|
31
|
+
*/
|
|
32
|
+
export function assertNoSystemRoles(roles: unknown, alreadyStored: string[] = []): void {
|
|
33
|
+
if (!Array.isArray(roles)) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const introduced = roles.filter((role) => looksLikeSystemRole(role) && !alreadyStored.includes(role));
|
|
38
|
+
if (introduced.length) {
|
|
39
|
+
throw new BadRequestException(
|
|
40
|
+
`System roles (${SYSTEM_ROLE_PREFIX}*) must never be stored in user.roles: ${introduced.join(', ')}`,
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Whether an update object carries a system role in any operator form — the cheap pre-check before a baseline read. */
|
|
46
|
+
export function updateMayIntroduceSystemRoles(update: any): boolean {
|
|
47
|
+
return collectRoleValues(update).some((role) => looksLikeSystemRole(role));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Every roles value the update could write, flattened across the operators that can carry one. */
|
|
51
|
+
export function collectRoleValues(update: any): unknown[] {
|
|
52
|
+
const values: unknown[] = [
|
|
53
|
+
...toRoleArray(update.roles),
|
|
54
|
+
...toRoleArray(update.$set?.roles),
|
|
55
|
+
...toRoleArray(update.$setOnInsert?.roles),
|
|
56
|
+
];
|
|
57
|
+
|
|
58
|
+
for (const operator of [update.$push?.roles, update.$addToSet?.roles]) {
|
|
59
|
+
if (operator === undefined || operator === null) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
values.push(...(Array.isArray(operator?.$each) ? operator.$each : [operator]));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return values;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Check every operator through which a roles value can reach the document.
|
|
70
|
+
*
|
|
71
|
+
* `$pull` is deliberately NOT checked — removing an `s_*` value from a document that already has
|
|
72
|
+
* one is exactly the cleanup this release asks projects to perform, so it must stay possible.
|
|
73
|
+
*/
|
|
74
|
+
export function assertUpdateHasNoSystemRoles(update: any, alreadyStored: string[] = []): void {
|
|
75
|
+
if (!update) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
assertNoSystemRoles(update.roles, alreadyStored);
|
|
80
|
+
assertNoSystemRoles(update.$set?.roles, alreadyStored);
|
|
81
|
+
assertNoSystemRoles(update.$setOnInsert?.roles, alreadyStored);
|
|
82
|
+
|
|
83
|
+
// $push / $addToSet take either a bare value or a { $each: [...] } modifier
|
|
84
|
+
for (const operator of [update.$push?.roles, update.$addToSet?.roles]) {
|
|
85
|
+
if (operator === undefined || operator === null) {
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
assertNoSystemRoles(Array.isArray(operator?.$each) ? operator.$each : [operator], alreadyStored);
|
|
89
|
+
}
|
|
90
|
+
}
|