@classytic/mongokit 3.4.5 → 3.5.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/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
- - **1150+ passing tests** - Battle-tested and production-ready
20
+ - **1170+ passing tests** - Battle-tested and production-ready
21
21
 
22
22
  ## Installation
23
23
 
@@ -125,6 +125,7 @@ UserSchema.index({ organizationId: 1, createdAt: -1, _id: -1 });
125
125
  | `createMany(data[], opts)` | `CreateOptions` | Create multiple documents |
126
126
  | `getById(id, opts)` | `CacheableOptions` | Find by ID |
127
127
  | `getByQuery(query, opts)` | `CacheableOptions` | Find one by query |
128
+ | `getOne(filter, opts)` | `CacheableOptions` | Find one by compound filter |
128
129
  | `getAll(params, opts)` | `CacheableOptions` | Paginated list (auto-detects mode) |
129
130
  | `findAll(filters, opts)` | `OperationOptions` | All docs without pagination |
130
131
  | `getOrCreate(query, data, opts)` | `SessionOptions` | Find or create |
@@ -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-DxNyLB2w.mjs";
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-BjXxDBgx.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 };
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "../chunk-CfYAbeIz.mjs";
2
- import { c as read_exports, h as aggregate_exports, n as update_exports, p as create_exports, u as delete_exports } from "../update-D6FFSUUO.mjs";
2
+ import { _ as aggregate_exports, f as delete_exports, h as create_exports, l as read_exports, r as update_exports } from "../update-DcWUpWBk.mjs";
3
3
  //#region src/actions/index.ts
4
4
  var actions_exports = /* @__PURE__ */ __exportAll({
5
5
  aggregate: () => aggregate_exports,
@@ -1,4 +1,4 @@
1
- import { J as Plugin } from "../types-sOh6QSzc.mjs";
1
+ import { J as Plugin } from "../types-DK6ELT6o.mjs";
2
2
  import { ClientSession, PipelineStage } from "mongoose";
3
3
 
4
4
  //#region src/ai/types.d.ts
@@ -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-sOh6QSzc.mjs";
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-DK6ELT6o.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-sOh6QSzc.mjs";
2
- import { t as index_d_exports } from "./index-DxNyLB2w.mjs";
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-DK6ELT6o.mjs";
2
+ import { t as index_d_exports } from "./index-BjXxDBgx.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-nJtqOI-E.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-C374oVAV.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-DISOoL9A.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-C78rAP7X.mjs";
6
6
  import * as _$mongoose from "mongoose";
7
7
  import { ClientSession, Expression, Model, PipelineStage, PopulateOptions } from "mongoose";
8
8
 
@@ -773,6 +773,7 @@ declare class Repository<TDoc = unknown> {
773
773
  readonly _hooks: Map<string, PrioritizedHook[]>;
774
774
  readonly _pagination: PaginationEngine<TDoc>;
775
775
  private readonly _hookMode;
776
+ readonly idField: string;
776
777
  [key: string]: unknown;
777
778
  private _hasTextIndex;
778
779
  constructor(Model: Model<TDoc, any, any, any>, plugins?: PluginType[], paginationConfig?: PaginationConfig, options?: RepositoryOptions);
@@ -826,6 +827,15 @@ declare class Repository<TDoc = unknown> {
826
827
  * Get single document by query
827
828
  */
828
829
  getByQuery(query: Record<string, unknown>, options?: CacheableOptions): Promise<TDoc | null>;
830
+ /**
831
+ * Get single document by arbitrary filter.
832
+ * Unlike getByQuery, this method is designed for Arc/controller use where
833
+ * compound filters (org scope + policy + id) are pre-built.
834
+ *
835
+ * @example
836
+ * const product = await repo.getOne({ slug: 'laptop', organizationId: 'org_1' });
837
+ */
838
+ getOne(query: Record<string, unknown>, options?: CacheableOptions): Promise<TDoc | null>;
829
839
  /**
830
840
  * Fetch ALL documents matching filters without pagination.
831
841
  * Use for background jobs, exports, batch processing where you need every doc.
@@ -904,7 +914,9 @@ declare class Repository<TDoc = unknown> {
904
914
  /**
905
915
  * Delete document by ID
906
916
  */
907
- delete(id: string | ObjectId, options?: SessionOptions): Promise<DeleteResult>;
917
+ delete(id: string | ObjectId, options?: SessionOptions & {
918
+ idField?: string;
919
+ }): Promise<DeleteResult>;
908
920
  /**
909
921
  * Execute aggregation pipeline
910
922
  * Routes through hook system for policy enforcement (multi-tenant, soft-delete)
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 { _ as LookupBuilder } from "./update-D6FFSUUO.mjs";
2
+ import { y as LookupBuilder } from "./update-DcWUpWBk.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-7Pa1wIsD.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-C4D1sc18.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-sOh6QSzc.mjs";
1
+ import { T as FieldPreset, _ as CrudSchemas, k as HttpError, ot as SchemaBuilderOptions, s as CacheAdapter, xt as ValidationResult, yt as UserContext } from "./types-DK6ELT6o.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-sOh6QSzc.mjs";
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-DK6ELT6o.mjs";
2
2
  import { Model } from "mongoose";
3
3
 
4
4
  //#region src/pagination/PaginationEngine.d.ts
@@ -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-nJtqOI-E.mjs";
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-DISOoL9A.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 };
@@ -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-7Pa1wIsD.mjs";
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-C4D1sc18.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 };
@@ -529,6 +529,9 @@ type HookMode = 'sync' | 'async';
529
529
  interface RepositoryOptions {
530
530
  /** Whether repository event hooks are awaited */
531
531
  hooks?: HookMode;
532
+ /** Custom ID field used by getById/update/delete (default: '_id').
533
+ * Set to 'slug', 'code', 'chatId', etc. for non-ObjectId lookups. */
534
+ idField?: string;
532
535
  }
533
536
  /** Pagination configuration */
534
537
  interface PaginationConfig {
@@ -699,6 +702,9 @@ interface OperationOptions extends ReadOptions {
699
702
  lean?: boolean;
700
703
  /** Throw error if document not found (default: true) */
701
704
  throwOnNotFound?: boolean;
705
+ /** Override the ID field for this call (default: repo.idField or '_id').
706
+ * Use when the same repo sometimes queries by _id and sometimes by slug/code. */
707
+ idField?: string;
702
708
  /** Additional query filters (e.g., for soft delete) */
703
709
  query?: Record<string, unknown>;
704
710
  }
@@ -926,7 +932,7 @@ interface RepositoryInstance {
926
932
  [key: string]: unknown;
927
933
  }
928
934
  /** Repository operation names */
929
- type RepositoryOperation = 'create' | 'createMany' | 'update' | 'updateMany' | 'delete' | 'deleteMany' | 'getById' | 'getByQuery' | 'getAll' | 'findAll' | 'getOrCreate' | 'count' | 'exists' | 'distinct' | 'aggregate' | 'aggregatePaginate' | 'lookupPopulate' | 'bulkWrite';
935
+ type RepositoryOperation = 'create' | 'createMany' | 'update' | 'updateMany' | 'delete' | 'deleteMany' | 'getById' | 'getByQuery' | 'getOne' | 'getAll' | 'findAll' | 'getOrCreate' | 'count' | 'exists' | 'distinct' | 'aggregate' | 'aggregatePaginate' | 'lookupPopulate' | 'bulkWrite';
930
936
  /** Event lifecycle phases */
931
937
  type EventPhase = 'before' | 'after' | 'error';
932
938
  /** Repository event names (generated from template literals) */
@@ -842,4 +842,4 @@ async function pullFromArray(Model, id, field, value, options = {}) {
842
842
  return update(Model, id, { $pull: { [field]: value } }, options);
843
843
  }
844
844
  //#endregion
845
- export { LookupBuilder as _, getById as a, read_exports as c, create as d, createMany as f, distinct as g, aggregate_exports as h, exists as i, deleteById as l, upsert as m, update_exports as n, getByQuery as o, create_exports as p, count as r, getOrCreate as s, update as t, delete_exports as u };
845
+ export { aggregate_exports as _, exists as a, getOrCreate as c, deleteByQuery as d, delete_exports as f, upsert as g, create_exports as h, count as i, read_exports as l, createMany as m, updateByQuery as n, getById as o, create as p, update_exports as r, getByQuery as s, update as t, deleteById as u, distinct as v, LookupBuilder as y };
@@ -1,5 +1,5 @@
1
- import { Z as PopulateSpec, pt as SortSpec, st as SelectSpec } from "../types-sOh6QSzc.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-C374oVAV.mjs";
1
+ import { Z as PopulateSpec, pt as SortSpec, st as SelectSpec } from "../types-DK6ELT6o.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-C78rAP7X.mjs";
3
3
 
4
4
  //#region src/utils/cache-keys.d.ts
5
5
  /**
@@ -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 { _ as LookupBuilder, a as getById, d as create, f as createMany, g as distinct, i as exists, l as deleteById, m as upsert, o as getByQuery, r as count, s as getOrCreate, t as update } from "./update-D6FFSUUO.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-DcWUpWBk.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";
@@ -1133,6 +1133,7 @@ var Repository = class {
1133
1133
  _hooks;
1134
1134
  _pagination;
1135
1135
  _hookMode;
1136
+ idField;
1136
1137
  _hasTextIndex = null;
1137
1138
  constructor(Model, plugins = [], paginationConfig = {}, options = {}) {
1138
1139
  this.Model = Model;
@@ -1140,6 +1141,7 @@ var Repository = class {
1140
1141
  this._hooks = /* @__PURE__ */ new Map();
1141
1142
  this._pagination = new PaginationEngine(Model, paginationConfig);
1142
1143
  this._hookMode = options.hooks ?? "async";
1144
+ this.idField = options.idField ?? "_id";
1143
1145
  plugins.forEach((plugin) => {
1144
1146
  this.use(plugin);
1145
1147
  });
@@ -1302,6 +1304,18 @@ var Repository = class {
1302
1304
  return cachedResult;
1303
1305
  }
1304
1306
  try {
1307
+ const effectiveIdField = options.idField ?? this.idField;
1308
+ if (effectiveIdField !== "_id") {
1309
+ const result = await getByQuery(this.Model, {
1310
+ [effectiveIdField]: id,
1311
+ ...context.query || {}
1312
+ }, context);
1313
+ await this._emitHook("after:getById", {
1314
+ context,
1315
+ result
1316
+ });
1317
+ return result;
1318
+ }
1305
1319
  if (typeof id === "string" && !mongoose.Types.ObjectId.isValid(id)) {
1306
1320
  if (context.throwOnNotFound === false || options.throwOnNotFound === false) return null;
1307
1321
  throw createError(404, "Document not found");
@@ -1356,6 +1370,46 @@ var Repository = class {
1356
1370
  }
1357
1371
  }
1358
1372
  /**
1373
+ * Get single document by arbitrary filter.
1374
+ * Unlike getByQuery, this method is designed for Arc/controller use where
1375
+ * compound filters (org scope + policy + id) are pre-built.
1376
+ *
1377
+ * @example
1378
+ * const product = await repo.getOne({ slug: 'laptop', organizationId: 'org_1' });
1379
+ */
1380
+ async getOne(query, options = {}) {
1381
+ const populateSpec = options.populateOptions || options.populate;
1382
+ const context = await this._buildContext("getOne", {
1383
+ query,
1384
+ ...options,
1385
+ populate: populateSpec
1386
+ });
1387
+ if (context._cacheHit) {
1388
+ const cachedResult = context._cachedResult;
1389
+ await this._emitHook("after:getOne", {
1390
+ context,
1391
+ result: cachedResult,
1392
+ fromCache: true
1393
+ });
1394
+ return cachedResult;
1395
+ }
1396
+ const finalQuery = context.query || query;
1397
+ try {
1398
+ const result = await getByQuery(this.Model, finalQuery, context);
1399
+ await this._emitHook("after:getOne", {
1400
+ context,
1401
+ result
1402
+ });
1403
+ return result;
1404
+ } catch (error) {
1405
+ await this._emitErrorHook("error:getOne", {
1406
+ context,
1407
+ error
1408
+ });
1409
+ throw this._handleError(error);
1410
+ }
1411
+ }
1412
+ /**
1359
1413
  * Fetch ALL documents matching filters without pagination.
1360
1414
  * Use for background jobs, exports, batch processing where you need every doc.
1361
1415
  *
@@ -1628,7 +1682,16 @@ var Repository = class {
1628
1682
  ...options
1629
1683
  });
1630
1684
  try {
1631
- const result = await update(this.Model, id, context.data || data, context);
1685
+ let result;
1686
+ const effectiveIdField = options.idField ?? this.idField;
1687
+ if (effectiveIdField !== "_id") {
1688
+ const updated = await updateByQuery(this.Model, {
1689
+ [effectiveIdField]: id,
1690
+ ...context.query || {}
1691
+ }, context.data || data, context);
1692
+ if (!updated) throw createError(404, "Document not found");
1693
+ result = updated;
1694
+ } else result = await update(this.Model, id, context.data || data, context);
1632
1695
  await this._emitHook("after:update", {
1633
1696
  context,
1634
1697
  result
@@ -1664,7 +1727,12 @@ var Repository = class {
1664
1727
  });
1665
1728
  return result;
1666
1729
  }
1667
- const result = await deleteById(this.Model, id, {
1730
+ const effectiveIdField = options.idField ?? this.idField;
1731
+ const deleteQuery = effectiveIdField !== "_id" ? {
1732
+ [effectiveIdField]: id,
1733
+ ...context.query || {}
1734
+ } : void 0;
1735
+ const result = deleteQuery ? await deleteByQuery(this.Model, deleteQuery, { session: options.session }) : await deleteById(this.Model, id, {
1668
1736
  session: options.session,
1669
1737
  query: context.query
1670
1738
  });
@@ -3599,7 +3667,7 @@ function softDeletePlugin(options = {}) {
3599
3667
  const updateData = { [deletedField]: /* @__PURE__ */ new Date() };
3600
3668
  if (context.user) updateData[deletedByField] = context.user._id || context.user.id;
3601
3669
  const deleteQuery = {
3602
- _id: context.id,
3670
+ [repo.idField || "_id"]: context.id,
3603
3671
  ...context.query || {}
3604
3672
  };
3605
3673
  if (!await repo.Model.findOneAndUpdate(deleteQuery, updateData, { session: context.session })) {
@@ -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-sOh6QSzc.mjs";
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-DK6ELT6o.mjs";
2
2
  import mongoose, { ClientSession } from "mongoose";
3
3
 
4
4
  //#region src/plugins/aggregate-helpers.plugin.d.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@classytic/mongokit",
3
- "version": "3.4.5",
3
+ "version": "3.5.0",
4
4
  "description": "Production-grade MongoDB repositories with zero dependencies - smart pagination, events, and plugins",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -109,6 +109,7 @@
109
109
  "@biomejs/biome": "^2.4.10",
110
110
  "@types/node": "^22.0.0",
111
111
  "@vitest/coverage-v8": "^3.2.4",
112
+ "knip": "^6.3.0",
112
113
  "mongodb-memory-server": "^10.4.3",
113
114
  "mongoose": "^9.1.3",
114
115
  "tsdown": "^0.21.7",