@classytic/mongokit 3.5.1 → 3.5.3
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/README.md +21 -2
- package/dist/actions/index.d.mts +1 -1
- package/dist/actions/index.mjs +1 -1
- package/dist/ai/index.d.mts +1 -1
- package/dist/{index-BjXxDBgx.d.mts → index-D3ydSXYC.d.mts} +1 -1
- package/dist/index.d.mts +4 -4
- package/dist/index.mjs +2 -2
- package/dist/{mongooseToJsonSchema-C78rAP7X.d.mts → mongooseToJsonSchema-BivI9LWt.d.mts} +1 -1
- package/dist/pagination/PaginationEngine.d.mts +1 -1
- package/dist/plugins/index.d.mts +1 -1
- package/dist/plugins/index.mjs +1 -1
- package/dist/{types-DK6ELT6o.d.mts → types-wCkH8jE3.d.mts} +4 -0
- package/dist/{update-DcWUpWBk.mjs → update-AVfKWNGt.mjs} +36 -0
- package/dist/utils/index.d.mts +2 -2
- package/dist/{validation-chain.plugin-DISOoL9A.d.mts → validation-chain.plugin-CGE_mKQr.d.mts} +1 -1
- package/dist/{validation-chain.plugin-DboBJfGs.mjs → validation-chain.plugin-KjPV_6_N.mjs} +141 -61
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
- **Search governance** - Text index guard (throws `400` if no index), allowlisted sort/filter fields, ReDoS protection
|
|
18
18
|
- **Vector search** - MongoDB Atlas `$vectorSearch` with auto-embedding and multimodal support
|
|
19
19
|
- **TypeScript first** - Full type safety with discriminated unions, typed events, and field autocomplete
|
|
20
|
-
- **
|
|
20
|
+
- **Extensively tested** — battle-tested and production-ready
|
|
21
21
|
|
|
22
22
|
## Installation
|
|
23
23
|
|
|
@@ -1423,6 +1423,25 @@ if (dupErr) {
|
|
|
1423
1423
|
}
|
|
1424
1424
|
```
|
|
1425
1425
|
|
|
1426
|
+
## Custom ID Field
|
|
1427
|
+
|
|
1428
|
+
Use `idField` when your documents use a custom identifier (slug, UUID, code) instead of `_id`:
|
|
1429
|
+
|
|
1430
|
+
```typescript
|
|
1431
|
+
// Repo-level: all calls use slug
|
|
1432
|
+
const productRepo = new Repository(ProductModel, [], {}, { idField: 'slug' });
|
|
1433
|
+
await productRepo.getById('laptop'); // { slug: 'laptop' }
|
|
1434
|
+
await productRepo.update('laptop', { price: 999 }); // { slug: 'laptop' }
|
|
1435
|
+
await productRepo.delete('laptop'); // { slug: 'laptop' }
|
|
1436
|
+
|
|
1437
|
+
// Per-call override: same repo, different lookups
|
|
1438
|
+
const repo = new Repository(ChatModel);
|
|
1439
|
+
await repo.getById('507f1f77bcf86cd799439011'); // by _id
|
|
1440
|
+
await repo.getById('my-chat-uuid', { idField: 'chatId' }); // by chatId
|
|
1441
|
+
```
|
|
1442
|
+
|
|
1443
|
+
All plugins respect `idField`: soft-delete, cascade, audit-log, audit-trail, validation-chain, elastic, cache, observability.
|
|
1444
|
+
|
|
1426
1445
|
## No Breaking Changes
|
|
1427
1446
|
|
|
1428
1447
|
Extending Repository works exactly the same with Mongoose 8 and 9. The package:
|
|
@@ -1430,7 +1449,7 @@ Extending Repository works exactly the same with Mongoose 8 and 9. The package:
|
|
|
1430
1449
|
- Uses its own event system (not Mongoose middleware)
|
|
1431
1450
|
- Defines its own `FilterQuery` type (unaffected by Mongoose 9 rename)
|
|
1432
1451
|
- Properly gates update pipelines (safe for Mongoose 9's stricter defaults)
|
|
1433
|
-
-
|
|
1452
|
+
- Full test suite passes on Mongoose 9
|
|
1434
1453
|
|
|
1435
1454
|
## License
|
|
1436
1455
|
|
package/dist/actions/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as create_d_exports, i as delete_d_exports, n as update_d_exports, o as aggregate_d_exports, r as read_d_exports } from "../index-
|
|
1
|
+
import { a as create_d_exports, i as delete_d_exports, n as update_d_exports, o as aggregate_d_exports, r as read_d_exports } from "../index-D3ydSXYC.mjs";
|
|
2
2
|
export { aggregate_d_exports as aggregate, create_d_exports as create, delete_d_exports as deleteActions, read_d_exports as read, update_d_exports as update };
|
package/dist/actions/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "../chunk-CfYAbeIz.mjs";
|
|
2
|
-
import { _ as aggregate_exports, f as delete_exports, h as create_exports, l as read_exports, r as update_exports } from "../update-
|
|
2
|
+
import { _ as aggregate_exports, f as delete_exports, h as create_exports, l as read_exports, r as update_exports } from "../update-AVfKWNGt.mjs";
|
|
3
3
|
//#region src/actions/index.ts
|
|
4
4
|
var actions_exports = /* @__PURE__ */ __exportAll({
|
|
5
5
|
aggregate: () => aggregate_exports,
|
package/dist/ai/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as ReadPreferenceType, At as LookupOptions, D as GroupResult, V as ObjectId, W as OperationOptions, Z as PopulateSpec, _t as UpdateOptions, a as AnyDocument, b as DeleteResult, g as CreateOptions, gt as UpdateManyResult, pt as SortSpec, st as SelectSpec, vt as UpdateWithValidationResult, z as MinMaxResult } from "./types-
|
|
1
|
+
import { $ as ReadPreferenceType, At as LookupOptions, D as GroupResult, V as ObjectId, W as OperationOptions, Z as PopulateSpec, _t as UpdateOptions, a as AnyDocument, b as DeleteResult, g as CreateOptions, gt as UpdateManyResult, pt as SortSpec, st as SelectSpec, vt as UpdateWithValidationResult, z as MinMaxResult } from "./types-wCkH8jE3.mjs";
|
|
2
2
|
import { ClientSession, Model, PipelineStage } from "mongoose";
|
|
3
3
|
|
|
4
4
|
//#region src/actions/aggregate.d.ts
|
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { $ as ReadPreferenceType, A as InferDocument, At as LookupOptions, B as NonNullableFields, C as EventPayload, Ct as WithPlugins, D as GroupResult, Dt as IRequestContext, E as FieldRules, Et as IControllerResponse, F as KeysetPaginationResult, G as PaginationConfig, H as OffsetPaginationOptions, I as Logger, J as Plugin, K as PaginationResult, L as LookupPopulateOptions, M as JsonSchema, N as KeysOfType, O as HookMode, Ot as IResponseFormatter, P as KeysetPaginationOptions, Q as ReadOptions, R as LookupPopulateResult, S as EventHandlers, St as ValidatorDefinition, T as FieldPreset, Tt as IController, U as OffsetPaginationResult, V as ObjectId, W as OperationOptions, X as PluginType, Y as PluginFunction, Z as PopulateSpec, _ as CrudSchemas, _t as UpdateOptions, a as AnyDocument, at as RequiredBy, b as DeleteResult, bt as ValidationChainOptions, c as CacheOperationOptions, ct as SessionOptions, d as CacheableOptions, dt as SoftDeleteRepository, et as RepositoryContext, f as CascadeOptions, ft as SortDirection, g as CreateOptions, gt as UpdateManyResult, h as CreateInput, ht as UpdateInput, i as AllPluginMethods, it as RepositoryOptions, j as InferRawDoc, k as HttpError, kt as LookupBuilder, l as CacheOptions, lt as SoftDeleteFilterMode, m as CollationOptions, mt as Strict, n as AggregatePaginationOptions, nt as RepositoryInstance, o as AnyModel, ot as SchemaBuilderOptions, p as CascadeRelation, pt as SortSpec, q as PartialBy, r as AggregatePaginationResult, rt as RepositoryOperation, s as CacheAdapter, st as SelectSpec, t as AggregateOptions, tt as RepositoryEvent, u as CacheStats, ut as SoftDeleteOptions, v as DecodedCursor, vt as UpdateWithValidationResult, w as EventPhase, wt as WithTransactionOptions, x as DocField, xt as ValidationResult, y as DeepPartial, yt as UserContext, z as MinMaxResult } from "./types-
|
|
2
|
-
import { t as index_d_exports } from "./index-
|
|
1
|
+
import { $ as ReadPreferenceType, A as InferDocument, At as LookupOptions, B as NonNullableFields, C as EventPayload, Ct as WithPlugins, D as GroupResult, Dt as IRequestContext, E as FieldRules, Et as IControllerResponse, F as KeysetPaginationResult, G as PaginationConfig, H as OffsetPaginationOptions, I as Logger, J as Plugin, K as PaginationResult, L as LookupPopulateOptions, M as JsonSchema, N as KeysOfType, O as HookMode, Ot as IResponseFormatter, P as KeysetPaginationOptions, Q as ReadOptions, R as LookupPopulateResult, S as EventHandlers, St as ValidatorDefinition, T as FieldPreset, Tt as IController, U as OffsetPaginationResult, V as ObjectId, W as OperationOptions, X as PluginType, Y as PluginFunction, Z as PopulateSpec, _ as CrudSchemas, _t as UpdateOptions, a as AnyDocument, at as RequiredBy, b as DeleteResult, bt as ValidationChainOptions, c as CacheOperationOptions, ct as SessionOptions, d as CacheableOptions, dt as SoftDeleteRepository, et as RepositoryContext, f as CascadeOptions, ft as SortDirection, g as CreateOptions, gt as UpdateManyResult, h as CreateInput, ht as UpdateInput, i as AllPluginMethods, it as RepositoryOptions, j as InferRawDoc, k as HttpError, kt as LookupBuilder, l as CacheOptions, lt as SoftDeleteFilterMode, m as CollationOptions, mt as Strict, n as AggregatePaginationOptions, nt as RepositoryInstance, o as AnyModel, ot as SchemaBuilderOptions, p as CascadeRelation, pt as SortSpec, q as PartialBy, r as AggregatePaginationResult, rt as RepositoryOperation, s as CacheAdapter, st as SelectSpec, t as AggregateOptions, tt as RepositoryEvent, u as CacheStats, ut as SoftDeleteOptions, v as DecodedCursor, vt as UpdateWithValidationResult, w as EventPhase, wt as WithTransactionOptions, x as DocField, xt as ValidationResult, y as DeepPartial, yt as UserContext, z as MinMaxResult } from "./types-wCkH8jE3.mjs";
|
|
2
|
+
import { t as index_d_exports } from "./index-D3ydSXYC.mjs";
|
|
3
3
|
import { PaginationEngine } from "./pagination/PaginationEngine.mjs";
|
|
4
|
-
import { A as dateSequentialId, B as AuditEntry, C as elasticSearchPlugin, D as PrefixedIdOptions, E as IdGenerator, F as CacheMethods, G as AuditTrailOptions, H as AuditQueryOptions, I as cachePlugin, J as auditLogPlugin, K as AuditTrailQuery, L as BatchOperationsMethods, M as prefixedId, N as sequentialId, O as SequentialIdOptions, P as cascadePlugin, R as BulkWriteResult, S as ElasticSearchOptions, T as DateSequentialIdOptions, U as AuditQueryResult, V as AuditOperation, W as AuditTrailMethods, X as aggregateHelpersPlugin, Y as AggregateHelpersMethods, _ as MongoOperationsMethods, a as uniqueField, b as methodRegistryPlugin, c as SubdocumentMethods, d as softDeletePlugin, f as ObservabilityOptions, g as multiTenantPlugin, h as MultiTenantOptions, i as requireField, j as getNextSequence, k as customIdPlugin, l as subdocumentPlugin, m as observabilityPlugin, n as blockIf, o as validationChainPlugin, p as OperationMetric, q as auditTrailPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as SoftDeleteMethods, v as mongoOperationsPlugin, w as CustomIdOptions, x as fieldFilterPlugin, z as batchOperationsPlugin } from "./validation-chain.plugin-
|
|
5
|
-
import { a as isFieldUpdateAllowed, c as configureLogger, d as getFieldsForUser, f as getMongooseProjection, i as getSystemManagedFields, l as createFieldPreset, m as parseDuplicateKeyError, n as buildCrudSchemasFromMongooseSchema, o as validateUpdateBody, p as createError, r as getImmutableFields, s as createMemoryCache, t as buildCrudSchemasFromModel, u as filterResponseData } from "./mongooseToJsonSchema-
|
|
4
|
+
import { A as dateSequentialId, B as AuditEntry, C as elasticSearchPlugin, D as PrefixedIdOptions, E as IdGenerator, F as CacheMethods, G as AuditTrailOptions, H as AuditQueryOptions, I as cachePlugin, J as auditLogPlugin, K as AuditTrailQuery, L as BatchOperationsMethods, M as prefixedId, N as sequentialId, O as SequentialIdOptions, P as cascadePlugin, R as BulkWriteResult, S as ElasticSearchOptions, T as DateSequentialIdOptions, U as AuditQueryResult, V as AuditOperation, W as AuditTrailMethods, X as aggregateHelpersPlugin, Y as AggregateHelpersMethods, _ as MongoOperationsMethods, a as uniqueField, b as methodRegistryPlugin, c as SubdocumentMethods, d as softDeletePlugin, f as ObservabilityOptions, g as multiTenantPlugin, h as MultiTenantOptions, i as requireField, j as getNextSequence, k as customIdPlugin, l as subdocumentPlugin, m as observabilityPlugin, n as blockIf, o as validationChainPlugin, p as OperationMetric, q as auditTrailPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as SoftDeleteMethods, v as mongoOperationsPlugin, w as CustomIdOptions, x as fieldFilterPlugin, z as batchOperationsPlugin } from "./validation-chain.plugin-CGE_mKQr.mjs";
|
|
5
|
+
import { a as isFieldUpdateAllowed, c as configureLogger, d as getFieldsForUser, f as getMongooseProjection, i as getSystemManagedFields, l as createFieldPreset, m as parseDuplicateKeyError, n as buildCrudSchemasFromMongooseSchema, o as validateUpdateBody, p as createError, r as getImmutableFields, s as createMemoryCache, t as buildCrudSchemasFromModel, u as filterResponseData } from "./mongooseToJsonSchema-BivI9LWt.mjs";
|
|
6
6
|
import * as _$mongoose from "mongoose";
|
|
7
7
|
import { ClientSession, Expression, Model, PipelineStage, PopulateOptions } from "mongoose";
|
|
8
8
|
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { a as warn, n as parseDuplicateKeyError, r as configureLogger, t as createError } from "./error-Bpbi_NKo.mjs";
|
|
2
|
-
import { y as LookupBuilder } from "./update-
|
|
2
|
+
import { y as LookupBuilder } from "./update-AVfKWNGt.mjs";
|
|
3
3
|
import { t as actions_exports } from "./actions/index.mjs";
|
|
4
4
|
import { t as PaginationEngine } from "./PaginationEngine-DCs-zKwZ.mjs";
|
|
5
|
-
import { A as aggregateHelpersPlugin, C as HOOK_PRIORITY, D as AuditTrailQuery, E as batchOperationsPlugin, O as auditTrailPlugin, S as cachePlugin, T as AggregationBuilder, _ as dateSequentialId, a as uniqueField, b as sequentialId, c as subdocumentPlugin, d as multiTenantPlugin, f as mongoOperationsPlugin, g as customIdPlugin, h as elasticSearchPlugin, i as requireField, k as auditLogPlugin, l as softDeletePlugin, m as fieldFilterPlugin, n as blockIf, o as validationChainPlugin, p as methodRegistryPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as observabilityPlugin, v as getNextSequence, w as Repository, x as cascadePlugin, y as prefixedId } from "./validation-chain.plugin-
|
|
5
|
+
import { A as aggregateHelpersPlugin, C as HOOK_PRIORITY, D as AuditTrailQuery, E as batchOperationsPlugin, O as auditTrailPlugin, S as cachePlugin, T as AggregationBuilder, _ as dateSequentialId, a as uniqueField, b as sequentialId, c as subdocumentPlugin, d as multiTenantPlugin, f as mongoOperationsPlugin, g as customIdPlugin, h as elasticSearchPlugin, i as requireField, k as auditLogPlugin, l as softDeletePlugin, m as fieldFilterPlugin, n as blockIf, o as validationChainPlugin, p as methodRegistryPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as observabilityPlugin, v as getNextSequence, w as Repository, x as cascadePlugin, y as prefixedId } from "./validation-chain.plugin-KjPV_6_N.mjs";
|
|
6
6
|
import { i as getMongooseProjection, n as filterResponseData, r as getFieldsForUser, t as createFieldPreset } from "./field-selection-reyDRzXf.mjs";
|
|
7
7
|
import { a as isFieldUpdateAllowed, i as getSystemManagedFields, n as buildCrudSchemasFromMongooseSchema, o as validateUpdateBody, r as getImmutableFields, s as createMemoryCache, t as buildCrudSchemasFromModel } from "./mongooseToJsonSchema-B6Qyl8BK.mjs";
|
|
8
8
|
import mongoose from "mongoose";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { T as FieldPreset, _ as CrudSchemas, k as HttpError, ot as SchemaBuilderOptions, s as CacheAdapter, xt as ValidationResult, yt as UserContext } from "./types-
|
|
1
|
+
import { T as FieldPreset, _ as CrudSchemas, k as HttpError, ot as SchemaBuilderOptions, s as CacheAdapter, xt as ValidationResult, yt as UserContext } from "./types-wCkH8jE3.mjs";
|
|
2
2
|
import mongoose, { Schema } from "mongoose";
|
|
3
3
|
|
|
4
4
|
//#region src/utils/error.d.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { F as KeysetPaginationResult, G as PaginationConfig, H as OffsetPaginationOptions, P as KeysetPaginationOptions, U as OffsetPaginationResult, a as AnyDocument, n as AggregatePaginationOptions, r as AggregatePaginationResult } from "../types-
|
|
1
|
+
import { F as KeysetPaginationResult, G as PaginationConfig, H as OffsetPaginationOptions, P as KeysetPaginationOptions, U as OffsetPaginationResult, a as AnyDocument, n as AggregatePaginationOptions, r as AggregatePaginationResult } from "../types-wCkH8jE3.mjs";
|
|
2
2
|
import { Model } from "mongoose";
|
|
3
3
|
|
|
4
4
|
//#region src/pagination/PaginationEngine.d.ts
|
package/dist/plugins/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as dateSequentialId, B as AuditEntry, C as elasticSearchPlugin, D as PrefixedIdOptions, E as IdGenerator, F as CacheMethods, G as AuditTrailOptions, H as AuditQueryOptions, I as cachePlugin, J as auditLogPlugin, K as AuditTrailQuery, L as BatchOperationsMethods, M as prefixedId, N as sequentialId, O as SequentialIdOptions, P as cascadePlugin, S as ElasticSearchOptions, T as DateSequentialIdOptions, U as AuditQueryResult, V as AuditOperation, W as AuditTrailMethods, X as aggregateHelpersPlugin, Y as AggregateHelpersMethods, _ as MongoOperationsMethods, a as uniqueField, b as methodRegistryPlugin, c as SubdocumentMethods, d as softDeletePlugin, f as ObservabilityOptions, g as multiTenantPlugin, h as MultiTenantOptions, i as requireField, j as getNextSequence, k as customIdPlugin, l as subdocumentPlugin, m as observabilityPlugin, n as blockIf, o as validationChainPlugin, p as OperationMetric, q as auditTrailPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as SoftDeleteMethods, v as mongoOperationsPlugin, w as CustomIdOptions, x as fieldFilterPlugin, y as MethodRegistryRepository, z as batchOperationsPlugin } from "../validation-chain.plugin-
|
|
1
|
+
import { A as dateSequentialId, B as AuditEntry, C as elasticSearchPlugin, D as PrefixedIdOptions, E as IdGenerator, F as CacheMethods, G as AuditTrailOptions, H as AuditQueryOptions, I as cachePlugin, J as auditLogPlugin, K as AuditTrailQuery, L as BatchOperationsMethods, M as prefixedId, N as sequentialId, O as SequentialIdOptions, P as cascadePlugin, S as ElasticSearchOptions, T as DateSequentialIdOptions, U as AuditQueryResult, V as AuditOperation, W as AuditTrailMethods, X as aggregateHelpersPlugin, Y as AggregateHelpersMethods, _ as MongoOperationsMethods, a as uniqueField, b as methodRegistryPlugin, c as SubdocumentMethods, d as softDeletePlugin, f as ObservabilityOptions, g as multiTenantPlugin, h as MultiTenantOptions, i as requireField, j as getNextSequence, k as customIdPlugin, l as subdocumentPlugin, m as observabilityPlugin, n as blockIf, o as validationChainPlugin, p as OperationMetric, q as auditTrailPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as SoftDeleteMethods, v as mongoOperationsPlugin, w as CustomIdOptions, x as fieldFilterPlugin, y as MethodRegistryRepository, z as batchOperationsPlugin } from "../validation-chain.plugin-CGE_mKQr.mjs";
|
|
2
2
|
export { type AggregateHelpersMethods, type AuditEntry, type AuditOperation, type AuditQueryOptions, type AuditQueryResult, type AuditTrailMethods, type AuditTrailOptions, AuditTrailQuery, type BatchOperationsMethods, type CacheMethods, type CustomIdOptions, type DateSequentialIdOptions, type ElasticSearchOptions, type IdGenerator, type MethodRegistryRepository, type MongoOperationsMethods, type MultiTenantOptions, type ObservabilityOptions, type OperationMetric, type PrefixedIdOptions, type SequentialIdOptions, type SoftDeleteMethods, type SubdocumentMethods, aggregateHelpersPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, blockIf, cachePlugin, cascadePlugin, customIdPlugin, dateSequentialId, elasticSearchPlugin, fieldFilterPlugin, getNextSequence, immutableField, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, prefixedId, requireField, sequentialId, softDeletePlugin, subdocumentPlugin, timestampPlugin, uniqueField, validationChainPlugin };
|
package/dist/plugins/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as aggregateHelpersPlugin, D as AuditTrailQuery, E as batchOperationsPlugin, O as auditTrailPlugin, S as cachePlugin, _ as dateSequentialId, a as uniqueField, b as sequentialId, c as subdocumentPlugin, d as multiTenantPlugin, f as mongoOperationsPlugin, g as customIdPlugin, h as elasticSearchPlugin, i as requireField, k as auditLogPlugin, l as softDeletePlugin, m as fieldFilterPlugin, n as blockIf, o as validationChainPlugin, p as methodRegistryPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as observabilityPlugin, v as getNextSequence, x as cascadePlugin, y as prefixedId } from "../validation-chain.plugin-
|
|
1
|
+
import { A as aggregateHelpersPlugin, D as AuditTrailQuery, E as batchOperationsPlugin, O as auditTrailPlugin, S as cachePlugin, _ as dateSequentialId, a as uniqueField, b as sequentialId, c as subdocumentPlugin, d as multiTenantPlugin, f as mongoOperationsPlugin, g as customIdPlugin, h as elasticSearchPlugin, i as requireField, k as auditLogPlugin, l as softDeletePlugin, m as fieldFilterPlugin, n as blockIf, o as validationChainPlugin, p as methodRegistryPlugin, r as immutableField, s as timestampPlugin, t as autoInject, u as observabilityPlugin, v as getNextSequence, x as cascadePlugin, y as prefixedId } from "../validation-chain.plugin-KjPV_6_N.mjs";
|
|
2
2
|
export { AuditTrailQuery, aggregateHelpersPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, blockIf, cachePlugin, cascadePlugin, customIdPlugin, dateSequentialId, elasticSearchPlugin, fieldFilterPlugin, getNextSequence, immutableField, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, prefixedId, requireField, sequentialId, softDeletePlugin, subdocumentPlugin, timestampPlugin, uniqueField, validationChainPlugin };
|
|
@@ -684,6 +684,10 @@ type PaginationResult<T = unknown> = OffsetPaginationResult<T> | KeysetPaginatio
|
|
|
684
684
|
interface SessionOptions {
|
|
685
685
|
/** MongoDB session for transactions */
|
|
686
686
|
session?: ClientSession;
|
|
687
|
+
/** Organization/tenant ID for multi-tenant plugin scoping */
|
|
688
|
+
organizationId?: string | ObjectId;
|
|
689
|
+
/** Extensible — plugins can read custom fields from options */
|
|
690
|
+
[key: string]: unknown;
|
|
687
691
|
}
|
|
688
692
|
/** Read options — session + readPreference for read-only operations */
|
|
689
693
|
interface ReadOptions extends SessionOptions {
|
|
@@ -279,6 +279,42 @@ var LookupBuilder = class LookupBuilder {
|
|
|
279
279
|
return sanitized;
|
|
280
280
|
}
|
|
281
281
|
};
|
|
282
|
+
/**
|
|
283
|
+
* Performance Guidelines for $lookup at Scale:
|
|
284
|
+
*
|
|
285
|
+
* 1. **Index Requirements** (Critical for millions of records):
|
|
286
|
+
* - localField should be indexed on source collection
|
|
287
|
+
* - foreignField should be indexed on target collection (unique index preferred)
|
|
288
|
+
*
|
|
289
|
+
* Example:
|
|
290
|
+
* ```typescript
|
|
291
|
+
* // Employee collection
|
|
292
|
+
* employeeSchema.index({ departmentSlug: 1 });
|
|
293
|
+
*
|
|
294
|
+
* // Department collection
|
|
295
|
+
* departmentSchema.index({ slug: 1 }, { unique: true });
|
|
296
|
+
* ```
|
|
297
|
+
*
|
|
298
|
+
* 2. **Query Performance**:
|
|
299
|
+
* - With proper indexes: O(log n) per lookup
|
|
300
|
+
* - Without indexes: O(n * m) - AVOID THIS!
|
|
301
|
+
* - Use explain() to verify index usage: IXSCAN (good) vs COLLSCAN (bad)
|
|
302
|
+
*
|
|
303
|
+
* 3. **Pipeline Optimization**:
|
|
304
|
+
* - Place $match stages as early as possible
|
|
305
|
+
* - Use $project to reduce field size before lookups
|
|
306
|
+
* - Limit joined results with pipeline: [{ $match: {...} }, { $limit: n }]
|
|
307
|
+
*
|
|
308
|
+
* 4. **Memory Considerations**:
|
|
309
|
+
* - Each lookup creates a new field in memory
|
|
310
|
+
* - Use $project after lookup to remove unnecessary fields
|
|
311
|
+
* - Consider allowDiskUse: true for very large datasets
|
|
312
|
+
*
|
|
313
|
+
* 5. **Alternative Approaches**:
|
|
314
|
+
* - For 1:1 relationships with high read frequency: Consider storing ObjectId + slug
|
|
315
|
+
* - For read-heavy workloads: Consider caching or materialized views
|
|
316
|
+
* - For real-time dashboards: Consider separate aggregation collections
|
|
317
|
+
*/
|
|
282
318
|
//#endregion
|
|
283
319
|
//#region src/actions/aggregate.ts
|
|
284
320
|
var aggregate_exports = /* @__PURE__ */ __exportAll({
|
package/dist/utils/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Z as PopulateSpec, pt as SortSpec, st as SelectSpec } from "../types-
|
|
2
|
-
import { a as isFieldUpdateAllowed, c as configureLogger, d as getFieldsForUser, f as getMongooseProjection, i as getSystemManagedFields, l as createFieldPreset, n as buildCrudSchemasFromMongooseSchema, o as validateUpdateBody, p as createError, r as getImmutableFields, s as createMemoryCache, t as buildCrudSchemasFromModel, u as filterResponseData } from "../mongooseToJsonSchema-
|
|
1
|
+
import { Z as PopulateSpec, pt as SortSpec, st as SelectSpec } from "../types-wCkH8jE3.mjs";
|
|
2
|
+
import { a as isFieldUpdateAllowed, c as configureLogger, d as getFieldsForUser, f as getMongooseProjection, i as getSystemManagedFields, l as createFieldPreset, n as buildCrudSchemasFromMongooseSchema, o as validateUpdateBody, p as createError, r as getImmutableFields, s as createMemoryCache, t as buildCrudSchemasFromModel, u as filterResponseData } from "../mongooseToJsonSchema-BivI9LWt.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/utils/cache-keys.d.ts
|
|
5
5
|
/**
|
package/dist/{validation-chain.plugin-DISOoL9A.d.mts → validation-chain.plugin-CGE_mKQr.d.mts}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { I as Logger, J as Plugin, St as ValidatorDefinition, T as FieldPreset, U as OffsetPaginationResult, V as ObjectId, Z as PopulateSpec, bt as ValidationChainOptions, et as RepositoryContext, f as CascadeOptions, l as CacheOptions, nt as RepositoryInstance, pt as SortSpec, st as SelectSpec, u as CacheStats, ut as SoftDeleteOptions } from "./types-
|
|
1
|
+
import { I as Logger, J as Plugin, St as ValidatorDefinition, T as FieldPreset, U as OffsetPaginationResult, V as ObjectId, Z as PopulateSpec, bt as ValidationChainOptions, et as RepositoryContext, f as CascadeOptions, l as CacheOptions, nt as RepositoryInstance, pt as SortSpec, st as SelectSpec, u as CacheStats, ut as SoftDeleteOptions } from "./types-wCkH8jE3.mjs";
|
|
2
2
|
import mongoose, { ClientSession } from "mongoose";
|
|
3
3
|
|
|
4
4
|
//#region src/plugins/aggregate-helpers.plugin.d.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as warn, i as debug, n as parseDuplicateKeyError, t as createError } from "./error-Bpbi_NKo.mjs";
|
|
2
|
-
import { a as exists, c as getOrCreate, d as deleteByQuery, g as upsert, i as count, m as createMany, n as updateByQuery, o as getById, p as create, s as getByQuery, t as update, u as deleteById, v as distinct, y as LookupBuilder } from "./update-
|
|
2
|
+
import { a as exists, c as getOrCreate, d as deleteByQuery, g as upsert, i as count, m as createMany, n as updateByQuery, o as getById, p as create, s as getByQuery, t as update, u as deleteById, v as distinct, y as LookupBuilder } from "./update-AVfKWNGt.mjs";
|
|
3
3
|
import { t as PaginationEngine } from "./PaginationEngine-DCs-zKwZ.mjs";
|
|
4
4
|
import { a as byIdKey, c as listQueryKey, l as modelPattern, o as byQueryKey, r as getFieldsForUser, u as versionKey } from "./field-selection-reyDRzXf.mjs";
|
|
5
5
|
import mongoose from "mongoose";
|
|
@@ -79,9 +79,10 @@ function auditLogPlugin(logger) {
|
|
|
79
79
|
name: "auditLog",
|
|
80
80
|
apply(repo) {
|
|
81
81
|
repo.on("after:create", ({ context, result }) => {
|
|
82
|
+
const idKey = repo.idField || "_id";
|
|
82
83
|
logger?.info?.("Document created", {
|
|
83
84
|
model: context.model || repo.model,
|
|
84
|
-
id: result?.
|
|
85
|
+
id: result?.[idKey],
|
|
85
86
|
userId: context.user?._id || context.user?.id,
|
|
86
87
|
organizationId: context.organizationId
|
|
87
88
|
});
|
|
@@ -89,7 +90,7 @@ function auditLogPlugin(logger) {
|
|
|
89
90
|
repo.on("after:update", ({ context, result }) => {
|
|
90
91
|
logger?.info?.("Document updated", {
|
|
91
92
|
model: context.model || repo.model,
|
|
92
|
-
id: context.id || result?._id,
|
|
93
|
+
id: context.id || result?.[repo.idField || "_id"],
|
|
93
94
|
userId: context.user?._id || context.user?.id,
|
|
94
95
|
organizationId: context.organizationId
|
|
95
96
|
});
|
|
@@ -282,10 +283,11 @@ function auditTrailPlugin(options = {}) {
|
|
|
282
283
|
const AuditModel = getAuditModel(collectionName, ttlDays);
|
|
283
284
|
if (opsSet.has("create")) repo.on("after:create", ({ context, result }) => {
|
|
284
285
|
const doc = toPlainObject(result);
|
|
286
|
+
const idKey = repo.idField || "_id";
|
|
285
287
|
writeAudit(AuditModel, {
|
|
286
288
|
model: context.model || repo.model,
|
|
287
289
|
operation: "create",
|
|
288
|
-
documentId: doc?.
|
|
290
|
+
documentId: doc?.[idKey],
|
|
289
291
|
userId: getUserId(context),
|
|
290
292
|
orgId: context.organizationId,
|
|
291
293
|
document: trackDocument ? sanitizeDoc(doc, excludeFields) : void 0,
|
|
@@ -313,7 +315,7 @@ function auditTrailPlugin(options = {}) {
|
|
|
313
315
|
writeAudit(AuditModel, {
|
|
314
316
|
model: context.model || repo.model,
|
|
315
317
|
operation: "update",
|
|
316
|
-
documentId: context.id || doc?._id,
|
|
318
|
+
documentId: context.id || doc?.[repo.idField || "_id"],
|
|
317
319
|
userId: getUserId(context),
|
|
318
320
|
orgId: context.organizationId,
|
|
319
321
|
changes,
|
|
@@ -1103,6 +1105,52 @@ var AggregationBuilder = class AggregationBuilder {
|
|
|
1103
1105
|
return new AggregationBuilder().match(query);
|
|
1104
1106
|
}
|
|
1105
1107
|
};
|
|
1108
|
+
/**
|
|
1109
|
+
* Optimized Aggregation Patterns for Scale
|
|
1110
|
+
*
|
|
1111
|
+
* 1. **Early Filtering** - Always place $match as early as possible:
|
|
1112
|
+
* ```typescript
|
|
1113
|
+
* new AggregationBuilder()
|
|
1114
|
+
* .match({ status: 'active' }) // ✅ Filter first
|
|
1115
|
+
* .lookup(...) // Then join
|
|
1116
|
+
* .sort(...)
|
|
1117
|
+
* ```
|
|
1118
|
+
*
|
|
1119
|
+
* 2. **Index Usage** - Ensure indexes on:
|
|
1120
|
+
* - Fields in $match
|
|
1121
|
+
* - Fields in $sort (especially with $limit)
|
|
1122
|
+
* - Fields in $lookup (both local and foreign)
|
|
1123
|
+
*
|
|
1124
|
+
* 3. **Projection** - Remove unnecessary fields early:
|
|
1125
|
+
* ```typescript
|
|
1126
|
+
* .project({ password: 0, internalNotes: 0 }) // Remove before joins
|
|
1127
|
+
* .lookup(...)
|
|
1128
|
+
* ```
|
|
1129
|
+
*
|
|
1130
|
+
* 4. **Faceted Pagination** - Get count and data in one query:
|
|
1131
|
+
* ```typescript
|
|
1132
|
+
* .facet({
|
|
1133
|
+
* metadata: [{ $count: 'total' }],
|
|
1134
|
+
* data: [{ $skip: skip }, { $limit: limit }]
|
|
1135
|
+
* })
|
|
1136
|
+
* ```
|
|
1137
|
+
*
|
|
1138
|
+
* 5. **allowDiskUse** - For large datasets:
|
|
1139
|
+
* ```typescript
|
|
1140
|
+
* new AggregationBuilder()
|
|
1141
|
+
* .match({ status: 'active' })
|
|
1142
|
+
* .allowDiskUse()
|
|
1143
|
+
* .exec(Model)
|
|
1144
|
+
* ```
|
|
1145
|
+
*
|
|
1146
|
+
* 6. **Vector Search** - Semantic similarity (Atlas only):
|
|
1147
|
+
* ```typescript
|
|
1148
|
+
* new AggregationBuilder()
|
|
1149
|
+
* .vectorSearch({ index: 'vec_idx', path: 'embedding', queryVector: vec, limit: 10 })
|
|
1150
|
+
* .withVectorScore()
|
|
1151
|
+
* .exec(Model)
|
|
1152
|
+
* ```
|
|
1153
|
+
*/
|
|
1106
1154
|
//#endregion
|
|
1107
1155
|
//#region src/Repository.ts
|
|
1108
1156
|
function ensureLookupProjectionIncludesCursorFields(projection, sort) {
|
|
@@ -2383,6 +2431,34 @@ function cachePlugin(options) {
|
|
|
2383
2431
|
}
|
|
2384
2432
|
}, { priority: HOOK_PRIORITY.CACHE });
|
|
2385
2433
|
/**
|
|
2434
|
+
* before:getOne - Same cache logic as getByQuery (single-doc)
|
|
2435
|
+
*/
|
|
2436
|
+
repo.on("before:getOne", async (context) => {
|
|
2437
|
+
if (context.skipCache) return;
|
|
2438
|
+
try {
|
|
2439
|
+
const collectionVersion = await getVersion();
|
|
2440
|
+
const query = context.query || {};
|
|
2441
|
+
const key = byQueryKey(config.prefix, model, collectionVersion, query, {
|
|
2442
|
+
select: context.select,
|
|
2443
|
+
populate: context.populate
|
|
2444
|
+
});
|
|
2445
|
+
const cached = await config.adapter.get(key);
|
|
2446
|
+
if (cached !== null && cached !== void 0) {
|
|
2447
|
+
log(`Cache HIT for getOne: ${key}`);
|
|
2448
|
+
stats.hits++;
|
|
2449
|
+
context._cacheHit = true;
|
|
2450
|
+
context._cachedResult = cached;
|
|
2451
|
+
} else {
|
|
2452
|
+
log(`Cache MISS for getOne: ${key}`);
|
|
2453
|
+
stats.misses++;
|
|
2454
|
+
context._cacheKey = key;
|
|
2455
|
+
}
|
|
2456
|
+
} catch (e) {
|
|
2457
|
+
log(`Cache error for getOne:`, e);
|
|
2458
|
+
stats.errors++;
|
|
2459
|
+
}
|
|
2460
|
+
}, { priority: HOOK_PRIORITY.CACHE });
|
|
2461
|
+
/**
|
|
2386
2462
|
* before:getAll - Check cache for list query
|
|
2387
2463
|
* Runs at CACHE priority (200) — after policy hooks inject filters
|
|
2388
2464
|
*/
|
|
@@ -2478,6 +2554,25 @@ function cachePlugin(options) {
|
|
|
2478
2554
|
}
|
|
2479
2555
|
});
|
|
2480
2556
|
/**
|
|
2557
|
+
* after:getOne - Cache the result (same as getByQuery)
|
|
2558
|
+
*/
|
|
2559
|
+
repo.on("after:getOne", async (payload) => {
|
|
2560
|
+
const { context, result } = payload;
|
|
2561
|
+
if (context._cacheHit || context.skipCache || result === null) return;
|
|
2562
|
+
const collectionVersion = await getVersion();
|
|
2563
|
+
const query = context.query || {};
|
|
2564
|
+
const key = byQueryKey(config.prefix, model, collectionVersion, query, {
|
|
2565
|
+
select: context.select,
|
|
2566
|
+
populate: context.populate
|
|
2567
|
+
});
|
|
2568
|
+
try {
|
|
2569
|
+
await config.adapter.set(key, result, context.cacheTtl ?? config.queryTtl);
|
|
2570
|
+
stats.sets++;
|
|
2571
|
+
} catch (e) {
|
|
2572
|
+
log(`Failed to cache getOne:`, e);
|
|
2573
|
+
}
|
|
2574
|
+
});
|
|
2575
|
+
/**
|
|
2481
2576
|
* after:getAll - Cache the result
|
|
2482
2577
|
*/
|
|
2483
2578
|
repo.on("after:getAll", async (payload) => {
|
|
@@ -2726,7 +2821,8 @@ function cascadePlugin(options) {
|
|
|
2726
2821
|
repo.on("before:deleteMany", async (context) => {
|
|
2727
2822
|
const query = context.query;
|
|
2728
2823
|
if (!query || Object.keys(query).length === 0) return;
|
|
2729
|
-
|
|
2824
|
+
const idField = repo.idField || "_id";
|
|
2825
|
+
context._cascadeIds = (await repo.Model.find(query, { [idField]: 1 }).lean().session(context.session ?? null)).map((doc) => doc[idField]);
|
|
2730
2826
|
});
|
|
2731
2827
|
repo.on("after:deleteMany", async (payload) => {
|
|
2732
2828
|
const { context } = payload;
|
|
@@ -3093,17 +3189,18 @@ function elasticSearchPlugin(options) {
|
|
|
3093
3189
|
limit,
|
|
3094
3190
|
from
|
|
3095
3191
|
};
|
|
3096
|
-
const
|
|
3192
|
+
const mongoIdField = repo.idField || "_id";
|
|
3193
|
+
const mongoQuery = this.Model.find({ [mongoIdField]: { $in: ids } });
|
|
3097
3194
|
if (searchOptions.mongoOptions?.select) mongoQuery.select(searchOptions.mongoOptions.select);
|
|
3098
3195
|
if (searchOptions.mongoOptions?.populate) mongoQuery.populate(searchOptions.mongoOptions.populate);
|
|
3099
3196
|
if (searchOptions.mongoOptions?.lean !== false) mongoQuery.lean();
|
|
3100
3197
|
return {
|
|
3101
3198
|
docs: (await mongoQuery.exec()).sort((a, b) => {
|
|
3102
|
-
const aId = String(a
|
|
3103
|
-
const bId = String(b
|
|
3199
|
+
const aId = String(a[mongoIdField]);
|
|
3200
|
+
const bId = String(b[mongoIdField]);
|
|
3104
3201
|
return (docsOrder.get(aId) ?? Number.MAX_SAFE_INTEGER) - (docsOrder.get(bId) ?? Number.MAX_SAFE_INTEGER);
|
|
3105
3202
|
}).map((doc) => {
|
|
3106
|
-
const strId = String(doc
|
|
3203
|
+
const strId = String(doc[mongoIdField]);
|
|
3107
3204
|
if (searchOptions.mongoOptions?.lean !== false) return {
|
|
3108
3205
|
...doc,
|
|
3109
3206
|
_score: scores.get(strId)
|
|
@@ -3143,8 +3240,10 @@ function fieldFilterPlugin(fieldPreset) {
|
|
|
3143
3240
|
else context.select = presetSelect;
|
|
3144
3241
|
};
|
|
3145
3242
|
repo.on("before:getAll", applyFieldFiltering);
|
|
3243
|
+
repo.on("before:findAll", applyFieldFiltering);
|
|
3146
3244
|
repo.on("before:getById", applyFieldFiltering);
|
|
3147
3245
|
repo.on("before:getByQuery", applyFieldFiltering);
|
|
3246
|
+
repo.on("before:getOne", applyFieldFiltering);
|
|
3148
3247
|
}
|
|
3149
3248
|
};
|
|
3150
3249
|
}
|
|
@@ -3430,12 +3529,14 @@ function multiTenantPlugin(options = {}) {
|
|
|
3430
3529
|
const { tenantField = "organizationId", contextKey = "organizationId", required = true, skipOperations = [], skipWhen, resolveContext } = options;
|
|
3431
3530
|
const filterOps = [
|
|
3432
3531
|
"getAll",
|
|
3532
|
+
"findAll",
|
|
3433
3533
|
"aggregatePaginate",
|
|
3434
3534
|
"lookupPopulate"
|
|
3435
3535
|
];
|
|
3436
3536
|
const queryReadOps = [
|
|
3437
3537
|
"getById",
|
|
3438
3538
|
"getByQuery",
|
|
3539
|
+
"getOne",
|
|
3439
3540
|
"count",
|
|
3440
3541
|
"exists",
|
|
3441
3542
|
"getOrCreate",
|
|
@@ -3528,7 +3629,14 @@ const DEFAULT_OPS = [
|
|
|
3528
3629
|
"delete",
|
|
3529
3630
|
"getById",
|
|
3530
3631
|
"getByQuery",
|
|
3632
|
+
"getOne",
|
|
3531
3633
|
"getAll",
|
|
3634
|
+
"findAll",
|
|
3635
|
+
"getOrCreate",
|
|
3636
|
+
"count",
|
|
3637
|
+
"exists",
|
|
3638
|
+
"distinct",
|
|
3639
|
+
"aggregate",
|
|
3532
3640
|
"aggregatePaginate",
|
|
3533
3641
|
"lookupPopulate"
|
|
3534
3642
|
];
|
|
@@ -3683,7 +3791,7 @@ function softDeletePlugin(options = {}) {
|
|
|
3683
3791
|
context.softDeleted = true;
|
|
3684
3792
|
}
|
|
3685
3793
|
}, { priority: HOOK_PRIORITY.POLICY });
|
|
3686
|
-
|
|
3794
|
+
const injectDeleteFilterToFilters = (context) => {
|
|
3687
3795
|
if (options.soft !== false) {
|
|
3688
3796
|
const deleteFilter = buildDeletedFilter(deletedField, filterMode, !!context.includeDeleted);
|
|
3689
3797
|
if (Object.keys(deleteFilter).length > 0) context.filters = {
|
|
@@ -3691,53 +3799,8 @@ function softDeletePlugin(options = {}) {
|
|
|
3691
3799
|
...deleteFilter
|
|
3692
3800
|
};
|
|
3693
3801
|
}
|
|
3694
|
-
}
|
|
3695
|
-
|
|
3696
|
-
if (options.soft !== false) {
|
|
3697
|
-
const deleteFilter = buildDeletedFilter(deletedField, filterMode, !!context.includeDeleted);
|
|
3698
|
-
if (Object.keys(deleteFilter).length > 0) context.query = {
|
|
3699
|
-
...context.query || {},
|
|
3700
|
-
...deleteFilter
|
|
3701
|
-
};
|
|
3702
|
-
}
|
|
3703
|
-
}, { priority: HOOK_PRIORITY.POLICY });
|
|
3704
|
-
repo.on("before:getByQuery", (context) => {
|
|
3705
|
-
if (options.soft !== false) {
|
|
3706
|
-
const deleteFilter = buildDeletedFilter(deletedField, filterMode, !!context.includeDeleted);
|
|
3707
|
-
if (Object.keys(deleteFilter).length > 0) context.query = {
|
|
3708
|
-
...context.query || {},
|
|
3709
|
-
...deleteFilter
|
|
3710
|
-
};
|
|
3711
|
-
}
|
|
3712
|
-
}, { priority: HOOK_PRIORITY.POLICY });
|
|
3713
|
-
repo.on("before:count", (context) => {
|
|
3714
|
-
if (options.soft !== false) {
|
|
3715
|
-
const deleteFilter = buildDeletedFilter(deletedField, filterMode, !!context.includeDeleted);
|
|
3716
|
-
if (Object.keys(deleteFilter).length > 0) context.query = {
|
|
3717
|
-
...context.query || {},
|
|
3718
|
-
...deleteFilter
|
|
3719
|
-
};
|
|
3720
|
-
}
|
|
3721
|
-
}, { priority: HOOK_PRIORITY.POLICY });
|
|
3722
|
-
repo.on("before:exists", (context) => {
|
|
3723
|
-
if (options.soft !== false) {
|
|
3724
|
-
const deleteFilter = buildDeletedFilter(deletedField, filterMode, !!context.includeDeleted);
|
|
3725
|
-
if (Object.keys(deleteFilter).length > 0) context.query = {
|
|
3726
|
-
...context.query || {},
|
|
3727
|
-
...deleteFilter
|
|
3728
|
-
};
|
|
3729
|
-
}
|
|
3730
|
-
}, { priority: HOOK_PRIORITY.POLICY });
|
|
3731
|
-
repo.on("before:getOrCreate", (context) => {
|
|
3732
|
-
if (options.soft !== false) {
|
|
3733
|
-
const deleteFilter = buildDeletedFilter(deletedField, filterMode, !!context.includeDeleted);
|
|
3734
|
-
if (Object.keys(deleteFilter).length > 0) context.query = {
|
|
3735
|
-
...context.query || {},
|
|
3736
|
-
...deleteFilter
|
|
3737
|
-
};
|
|
3738
|
-
}
|
|
3739
|
-
}, { priority: HOOK_PRIORITY.POLICY });
|
|
3740
|
-
repo.on("before:distinct", (context) => {
|
|
3802
|
+
};
|
|
3803
|
+
const injectDeleteFilterToQuery = (context) => {
|
|
3741
3804
|
if (options.soft !== false) {
|
|
3742
3805
|
const deleteFilter = buildDeletedFilter(deletedField, filterMode, !!context.includeDeleted);
|
|
3743
3806
|
if (Object.keys(deleteFilter).length > 0) context.query = {
|
|
@@ -3745,7 +3808,23 @@ function softDeletePlugin(options = {}) {
|
|
|
3745
3808
|
...deleteFilter
|
|
3746
3809
|
};
|
|
3747
3810
|
}
|
|
3748
|
-
}
|
|
3811
|
+
};
|
|
3812
|
+
for (const op of [
|
|
3813
|
+
"getAll",
|
|
3814
|
+
"findAll",
|
|
3815
|
+
"aggregatePaginate",
|
|
3816
|
+
"lookupPopulate"
|
|
3817
|
+
]) repo.on(`before:${op}`, injectDeleteFilterToFilters, { priority: HOOK_PRIORITY.POLICY });
|
|
3818
|
+
for (const op of [
|
|
3819
|
+
"getById",
|
|
3820
|
+
"getOne",
|
|
3821
|
+
"getByQuery",
|
|
3822
|
+
"count",
|
|
3823
|
+
"exists",
|
|
3824
|
+
"getOrCreate",
|
|
3825
|
+
"distinct",
|
|
3826
|
+
"aggregate"
|
|
3827
|
+
]) repo.on(`before:${op}`, injectDeleteFilterToQuery, { priority: HOOK_PRIORITY.POLICY });
|
|
3749
3828
|
repo.on("before:updateMany", (context) => {
|
|
3750
3829
|
if (options.soft !== false) {
|
|
3751
3830
|
const deleteFilter = buildDeletedFilter(deletedField, filterMode, !!context.includeDeleted);
|
|
@@ -4103,12 +4182,13 @@ function uniqueField(field, errorMessage) {
|
|
|
4103
4182
|
warn(`[mongokit] uniqueField('${field}'): getByQuery not available on repo, skipping uniqueness check`);
|
|
4104
4183
|
return;
|
|
4105
4184
|
}
|
|
4185
|
+
const idKey = repo.idField || "_id";
|
|
4106
4186
|
const existing = await getByQuery.call(repo, query, {
|
|
4107
|
-
select:
|
|
4187
|
+
select: idKey,
|
|
4108
4188
|
lean: true,
|
|
4109
4189
|
throwOnNotFound: false
|
|
4110
4190
|
});
|
|
4111
|
-
if (existing && String(existing
|
|
4191
|
+
if (existing && String(existing[idKey]) !== String(context.id)) throw createError(409, errorMessage || `${field} already exists`);
|
|
4112
4192
|
}
|
|
4113
4193
|
};
|
|
4114
4194
|
}
|
package/package.json
CHANGED