@classytic/mongokit 3.1.6 → 3.2.1

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.
@@ -1,4 +1,4 @@
1
- import { U as UserContext, F as FieldPreset, H as HttpError, C as CacheAdapter, g as SchemaBuilderOptions, h as CrudSchemas, V as ValidationResult } from './types-B5Uv6Ak7.js';
1
+ import { z as UserContext, Q as FieldPreset, H as HttpError, a7 as CacheAdapter, X as SchemaBuilderOptions, Z as CrudSchemas, V as ValidationResult } from './types-Jni1KgkP.js';
2
2
  import mongoose__default, { Schema } from 'mongoose';
3
3
 
4
4
  /**
@@ -109,6 +109,37 @@ declare function createFieldPreset(config: Partial<FieldPreset>): FieldPreset;
109
109
  */
110
110
  declare function createError(status: number, message: string): HttpError;
111
111
 
112
+ /**
113
+ * Internal Logger
114
+ *
115
+ * Centralizes all console output behind configurable functions.
116
+ * Users can silence, redirect, or replace the logger entirely.
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * import { configureLogger } from '@classytic/mongokit';
121
+ *
122
+ * // Silence all warnings
123
+ * configureLogger({ warn: () => {} });
124
+ *
125
+ * // Send to your logging system
126
+ * configureLogger({ warn: (msg) => myLogger.warn(msg) });
127
+ *
128
+ * // Silence everything
129
+ * configureLogger(false);
130
+ * ```
131
+ */
132
+ type LogFn = (message: string, ...args: unknown[]) => void;
133
+ interface LoggerConfig {
134
+ warn: LogFn;
135
+ debug: LogFn;
136
+ }
137
+ /**
138
+ * Configure the internal logger.
139
+ * Pass `false` to silence all output.
140
+ */
141
+ declare function configureLogger(config: Partial<LoggerConfig> | false): void;
142
+
112
143
  /**
113
144
  * In-Memory Cache Adapter
114
145
  *
@@ -197,4 +228,4 @@ declare function isFieldUpdateAllowed(fieldName: string, options?: SchemaBuilder
197
228
  */
198
229
  declare function validateUpdateBody(body?: Record<string, unknown>, options?: SchemaBuilderOptions): ValidationResult;
199
230
 
200
- export { getMongooseProjection as a, buildCrudSchemasFromMongooseSchema as b, createFieldPreset as c, buildCrudSchemasFromModel as d, getImmutableFields as e, filterResponseData as f, getFieldsForUser as g, getSystemManagedFields as h, isFieldUpdateAllowed as i, createError as j, createMemoryCache as k, validateUpdateBody as v };
231
+ export { getMongooseProjection as a, buildCrudSchemasFromMongooseSchema as b, createFieldPreset as c, buildCrudSchemasFromModel as d, getImmutableFields as e, filterResponseData as f, getFieldsForUser as g, getSystemManagedFields as h, isFieldUpdateAllowed as i, createError as j, configureLogger as k, createMemoryCache as l, validateUpdateBody as v };
@@ -1,5 +1,5 @@
1
1
  import { Model } from 'mongoose';
2
- import { A as AnyDocument, P as PaginationConfig, O as OffsetPaginationOptions, a as OffsetPaginationResult, K as KeysetPaginationOptions, b as KeysetPaginationResult, c as AggregatePaginationOptions, d as AggregatePaginationResult } from '../types-B5Uv6Ak7.js';
2
+ import { A as AnyDocument, P as PaginationConfig, O as OffsetPaginationOptions, a as OffsetPaginationResult, K as KeysetPaginationOptions, b as KeysetPaginationResult, c as AggregatePaginationOptions, d as AggregatePaginationResult } from '../types-Jni1KgkP.js';
3
3
 
4
4
  /**
5
5
  * Pagination Engine
@@ -1,2 +1,3 @@
1
- export { PaginationEngine } from '../chunks/chunk-M2XHQGZB.js';
2
- import '../chunks/chunk-VJXDGP3C.js';
1
+ export { PaginationEngine } from '../chunks/chunk-44KXLGPO.js';
2
+ import '../chunks/chunk-JWUAVZ3L.js';
3
+ import '../chunks/chunk-WSFCRVEQ.js';
@@ -1,4 +1,4 @@
1
- import { F as FieldPreset, G as Plugin, a2 as Logger, a3 as SoftDeleteOptions, k as ObjectId, f as SortSpec, S as SelectSpec, e as PopulateSpec, a as OffsetPaginationResult, L as RepositoryInstance, a0 as ValidatorDefinition, a1 as ValidationChainOptions, m as RepositoryContext, a8 as CacheOptions, aa as CacheStats, ac as CascadeOptions } from '../types-B5Uv6Ak7.js';
1
+ import { Q as FieldPreset, g as Plugin, a1 as Logger, a2 as SoftDeleteOptions, j as ObjectId, f as SortSpec, S as SelectSpec, e as PopulateSpec, a as OffsetPaginationResult, E as RepositoryInstance, $ as ValidatorDefinition, a0 as ValidationChainOptions, k as RepositoryContext, a8 as CacheOptions, aa as CacheStats, ac as CascadeOptions } from '../types-Jni1KgkP.js';
2
2
  import { ClientSession } from 'mongoose';
3
3
 
4
4
  /**
@@ -796,4 +796,127 @@ interface CacheMethods {
796
796
  */
797
797
  declare function cascadePlugin(options: CascadeOptions): Plugin;
798
798
 
799
- export { type AggregateHelpersMethods, type BatchOperationsMethods, type CacheMethods, type MethodRegistryRepository, type MongoOperationsMethods, type SoftDeleteMethods, type SubdocumentMethods, aggregateHelpersPlugin, auditLogPlugin, autoInject, batchOperationsPlugin, blockIf, cachePlugin, cascadePlugin, fieldFilterPlugin, immutableField, methodRegistryPlugin, mongoOperationsPlugin, requireField, softDeletePlugin, subdocumentPlugin, timestampPlugin, uniqueField, validationChainPlugin };
799
+ /**
800
+ * Multi-Tenant Plugin
801
+ *
802
+ * Automatically injects tenant isolation filters into all queries.
803
+ * Ensures data isolation by adding organizationId (or custom tenant field)
804
+ * to every read and write operation.
805
+ *
806
+ * @example
807
+ * ```typescript
808
+ * // Basic — scopes every operation by organizationId from context
809
+ * const repo = new Repository(Invoice, [
810
+ * multiTenantPlugin({ tenantField: 'organizationId' }),
811
+ * ]);
812
+ *
813
+ * const invoices = await repo.getAll(
814
+ * { filters: { status: 'paid' } },
815
+ * { organizationId: 'org_123' }
816
+ * );
817
+ * // Actual query: { status: 'paid', organizationId: 'org_123' }
818
+ *
819
+ * // Super admin bypass — skip scoping based on context
820
+ * const repo = new Repository(Invoice, [
821
+ * multiTenantPlugin({
822
+ * tenantField: 'organizationId',
823
+ * skipWhen: (context) => context.role === 'superadmin',
824
+ * }),
825
+ * ]);
826
+ *
827
+ * // Admin sees all orgs
828
+ * await repo.getAll({ page: 1, limit: 10 }, { role: 'superadmin' });
829
+ *
830
+ * // Automatic context — resolve tenant from AsyncLocalStorage
831
+ * const repo = new Repository(Invoice, [
832
+ * multiTenantPlugin({
833
+ * tenantField: 'organizationId',
834
+ * resolveContext: () => asyncLocalStorage.getStore()?.tenantId,
835
+ * }),
836
+ * ]);
837
+ * ```
838
+ */
839
+
840
+ interface MultiTenantOptions {
841
+ /** Field name used for tenant isolation (default: 'organizationId') */
842
+ tenantField?: string;
843
+ /** Context key to read tenant ID from (default: 'organizationId') */
844
+ contextKey?: string;
845
+ /** Throw if tenant ID is missing from context (default: true) */
846
+ required?: boolean;
847
+ /** Operations to skip tenant injection (e.g., for admin/system queries) */
848
+ skipOperations?: string[];
849
+ /**
850
+ * Dynamic skip — receives the context and operation name, returns true to
851
+ * bypass tenant scoping for this call. Use for role-based bypass (e.g.,
852
+ * super admin) without needing a separate repo instance.
853
+ *
854
+ * @example
855
+ * ```typescript
856
+ * skipWhen: (context) => context.role === 'superadmin'
857
+ * ```
858
+ */
859
+ skipWhen?: (context: RepositoryContext, operation: string) => boolean;
860
+ /**
861
+ * Resolve tenant ID from external source (e.g., AsyncLocalStorage, CLS).
862
+ * Called when tenant ID is not found in context. If it returns a value,
863
+ * that value is used as the tenant ID without requiring it in context.
864
+ *
865
+ * @example
866
+ * ```typescript
867
+ * resolveContext: () => asyncLocalStorage.getStore()?.tenantId
868
+ * ```
869
+ */
870
+ resolveContext?: () => string | undefined;
871
+ }
872
+ declare function multiTenantPlugin(options?: MultiTenantOptions): Plugin;
873
+
874
+ /**
875
+ * Observability Plugin
876
+ *
877
+ * Adds operation timing, structured metrics, and APM hook points.
878
+ * Works with any monitoring system — just provide an onMetric callback.
879
+ *
880
+ * @example
881
+ * ```typescript
882
+ * const repo = new Repository(User, [
883
+ * observabilityPlugin({
884
+ * onMetric: (metric) => {
885
+ * // Send to DataDog, New Relic, OpenTelemetry, or console
886
+ * console.log(`${metric.operation} took ${metric.durationMs}ms`);
887
+ * statsd.histogram('mongokit.operation', metric.durationMs, { op: metric.operation });
888
+ * },
889
+ * }),
890
+ * ]);
891
+ * ```
892
+ */
893
+
894
+ interface OperationMetric {
895
+ /** Operation name (e.g., 'create', 'getAll', 'update') */
896
+ operation: string;
897
+ /** Model/collection name */
898
+ model: string;
899
+ /** Duration in milliseconds */
900
+ durationMs: number;
901
+ /** Whether the operation succeeded */
902
+ success: boolean;
903
+ /** Error message if failed */
904
+ error?: string;
905
+ /** Timestamp when the operation started */
906
+ startedAt: Date;
907
+ /** User ID if available */
908
+ userId?: string;
909
+ /** Organization ID if available */
910
+ organizationId?: string;
911
+ }
912
+ interface ObservabilityOptions {
913
+ /** Callback invoked after every operation with timing data */
914
+ onMetric: (metric: OperationMetric) => void;
915
+ /** Operations to track (default: all) */
916
+ operations?: string[];
917
+ /** Threshold in ms — only report operations slower than this */
918
+ slowThresholdMs?: number;
919
+ }
920
+ declare function observabilityPlugin(options: ObservabilityOptions): Plugin;
921
+
922
+ export { type AggregateHelpersMethods, type BatchOperationsMethods, type CacheMethods, type MethodRegistryRepository, type MongoOperationsMethods, type MultiTenantOptions, type ObservabilityOptions, type OperationMetric, type SoftDeleteMethods, type SubdocumentMethods, aggregateHelpersPlugin, auditLogPlugin, autoInject, batchOperationsPlugin, blockIf, cachePlugin, cascadePlugin, fieldFilterPlugin, immutableField, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, requireField, softDeletePlugin, subdocumentPlugin, timestampPlugin, uniqueField, validationChainPlugin };
@@ -1,4 +1,6 @@
1
- export { aggregateHelpersPlugin, auditLogPlugin, autoInject, batchOperationsPlugin, blockIf, cachePlugin, cascadePlugin, fieldFilterPlugin, immutableField, methodRegistryPlugin, mongoOperationsPlugin, requireField, softDeletePlugin, subdocumentPlugin, timestampPlugin, uniqueField, validationChainPlugin } from '../chunks/chunk-CSLJ2PL2.js';
2
- import '../chunks/chunk-CF6FLC2G.js';
1
+ export { aggregateHelpersPlugin, auditLogPlugin, autoInject, batchOperationsPlugin, blockIf, cachePlugin, cascadePlugin, fieldFilterPlugin, immutableField, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, requireField, softDeletePlugin, subdocumentPlugin, timestampPlugin, uniqueField, validationChainPlugin } from '../chunks/chunk-B64F5ZWE.js';
2
+ import '../chunks/chunk-GZBKEPVE.js';
3
3
  import '../chunks/chunk-2ZN65ZOP.js';
4
- import '../chunks/chunk-VJXDGP3C.js';
4
+ import '../chunks/chunk-URLJFIR7.js';
5
+ import '../chunks/chunk-JWUAVZ3L.js';
6
+ import '../chunks/chunk-WSFCRVEQ.js';
@@ -1,13 +1,6 @@
1
+ import * as mongoose from 'mongoose';
1
2
  import { Document, PopulateOptions, ClientSession, PipelineStage, Model, Types } from 'mongoose';
2
3
 
3
- /**
4
- * MongoKit Type Definitions
5
- *
6
- * Production-grade types for MongoDB repository pattern with TypeScript
7
- *
8
- * @module @classytic/mongokit
9
- */
10
-
11
4
  /** Re-export mongoose ObjectId */
12
5
  type ObjectId = Types.ObjectId;
13
6
  /** Generic document type */
@@ -220,6 +213,8 @@ interface WithTransactionOptions {
220
213
  allowFallback?: boolean;
221
214
  /** Optional hook to observe fallback triggers */
222
215
  onFallback?: (error: Error) => void;
216
+ /** MongoDB transaction options (readConcern, writeConcern, readPreference, maxCommitTimeMS) */
217
+ transactionOptions?: mongoose.mongo.TransactionOptions;
223
218
  }
224
219
  /** Create operation options */
225
220
  interface CreateOptions {
@@ -308,6 +303,8 @@ interface RepositoryContext {
308
303
  limit?: number;
309
304
  /** Cursor for next page (keyset pagination) */
310
305
  after?: string;
306
+ /** Search query string */
307
+ search?: string;
311
308
  /** Whether this is a soft delete operation (set by softDeletePlugin) */
312
309
  softDeleted?: boolean;
313
310
  /** Include soft-deleted documents in queries */
@@ -344,6 +341,8 @@ interface RepositoryInstance {
344
341
  _pagination: unknown;
345
342
  use(plugin: PluginType): this;
346
343
  on(event: string, listener: (data: any) => void | Promise<void>): this;
344
+ off(event: string, listener: (data: any) => void | Promise<void>): this;
345
+ removeAllListeners(event?: string): this;
347
346
  emit(event: string, data: unknown): void;
348
347
  emitAsync(event: string, data: unknown): Promise<void>;
349
348
  registerMethod?(name: string, fn: Function): void;
@@ -356,9 +355,17 @@ type RepositoryOperation = 'create' | 'createMany' | 'update' | 'updateMany' | '
356
355
  type EventPhase = 'before' | 'after' | 'error';
357
356
  /** Repository event names (generated from template literals) */
358
357
  type RepositoryEvent = `${EventPhase}:${RepositoryOperation}` | 'method:registered' | 'error:hook';
359
- /** Type-safe event handler map */
358
+ /**
359
+ * Type-safe event handler map
360
+ *
361
+ * Hook signature contract:
362
+ * - `before:*` — receives `context: RepositoryContext` directly (not wrapped).
363
+ * Plugins mutate context in-place to inject filters, data, etc.
364
+ * - `after:*` — receives `{ context, result }` where result is the operation output.
365
+ * - `error:*` — receives `{ context, error }` where error is the caught Error.
366
+ */
360
367
  type EventHandlers<TDoc = unknown> = {
361
- [K in RepositoryEvent]?: K extends `after:${string}` ? (payload: {
368
+ [K in RepositoryEvent]?: K extends `before:${string}` ? (context: RepositoryContext) => void | Promise<void> : K extends `after:${string}` ? (payload: {
362
369
  context: RepositoryContext;
363
370
  result: TDoc | TDoc[];
364
371
  }) => void | Promise<void> : K extends `error:${string}` ? (payload: {
@@ -770,4 +777,4 @@ type AllPluginMethods<TDoc> = {
770
777
  */
771
778
  type WithPlugins<TDoc, TRepo extends RepositoryInstance = RepositoryInstance> = TRepo & AllPluginMethods<TDoc>;
772
779
 
773
- export type { DecodedCursor as $, AnyDocument as A, UpdateManyResult as B, CacheAdapter as C, DeepPartial as D, UpdateWithValidationResult as E, FieldPreset as F, Plugin as G, HttpError as H, InferDocument as I, PluginFunction as J, KeysetPaginationOptions as K, RepositoryInstance as L, RepositoryOperation as M, NonNullableFields as N, OffsetPaginationOptions as O, PaginationConfig as P, EventPhase as Q, RepositoryOptions as R, SelectSpec as S, RepositoryEvent as T, UserContext as U, ValidationResult as V, WithTransactionOptions as W, EventHandlers as X, EventPayload as Y, FieldRules as Z, JsonSchema as _, OffsetPaginationResult as a, ValidatorDefinition as a0, ValidationChainOptions as a1, Logger as a2, SoftDeleteOptions as a3, SoftDeleteFilterMode as a4, SoftDeleteRepository as a5, GroupResult as a6, MinMaxResult as a7, CacheOptions as a8, CacheOperationOptions as a9, CacheStats as aa, CascadeRelation as ab, CascadeOptions as ac, AllPluginMethods as ad, WithPlugins as ae, KeysetPaginationResult as b, AggregatePaginationOptions as c, AggregatePaginationResult as d, PopulateSpec as e, SortSpec as f, SchemaBuilderOptions as g, CrudSchemas as h, PaginationResult as i, PluginType as j, ObjectId as k, UpdateOptions as l, RepositoryContext as m, AnyModel as n, SortDirection as o, HookMode as p, InferRawDoc as q, PartialBy as r, RequiredBy as s, KeysOfType as t, Strict as u, CreateInput as v, UpdateInput as w, OperationOptions as x, CreateOptions as y, DeleteResult as z };
780
+ export type { ValidatorDefinition as $, AnyDocument as A, PluginFunction as B, CreateInput as C, DeepPartial as D, RepositoryInstance as E, RepositoryOperation as F, EventPhase as G, HttpError as H, InferDocument as I, RepositoryEvent as J, KeysetPaginationOptions as K, EventHandlers as L, EventPayload as M, NonNullableFields as N, OffsetPaginationOptions as O, PaginationConfig as P, FieldPreset as Q, RepositoryOptions as R, SelectSpec as S, FieldRules as T, UpdateOptions as U, ValidationResult as V, WithTransactionOptions as W, SchemaBuilderOptions as X, JsonSchema as Y, CrudSchemas as Z, DecodedCursor as _, OffsetPaginationResult as a, ValidationChainOptions as a0, Logger as a1, SoftDeleteOptions as a2, SoftDeleteFilterMode as a3, SoftDeleteRepository as a4, GroupResult as a5, MinMaxResult as a6, CacheAdapter as a7, CacheOptions as a8, CacheOperationOptions as a9, CacheStats as aa, CascadeRelation as ab, CascadeOptions as ac, AllPluginMethods as ad, WithPlugins as ae, KeysetPaginationResult as b, AggregatePaginationOptions as c, AggregatePaginationResult as d, PopulateSpec as e, SortSpec as f, Plugin as g, PaginationResult as h, PluginType as i, ObjectId as j, RepositoryContext as k, AnyModel as l, SortDirection as m, HookMode as n, InferRawDoc as o, PartialBy as p, RequiredBy as q, KeysOfType as r, Strict as s, UpdateInput as t, OperationOptions as u, CreateOptions as v, DeleteResult as w, UpdateManyResult as x, UpdateWithValidationResult as y, UserContext as z };
@@ -1,5 +1,5 @@
1
- export { d as buildCrudSchemasFromModel, b as buildCrudSchemasFromMongooseSchema, j as createError, c as createFieldPreset, k as createMemoryCache, f as filterResponseData, g as getFieldsForUser, e as getImmutableFields, a as getMongooseProjection, h as getSystemManagedFields, i as isFieldUpdateAllowed, v as validateUpdateBody } from '../mongooseToJsonSchema-Cc5AwuDu.js';
2
- import { S as SelectSpec, e as PopulateSpec, f as SortSpec } from '../types-B5Uv6Ak7.js';
1
+ export { d as buildCrudSchemasFromModel, b as buildCrudSchemasFromMongooseSchema, k as configureLogger, j as createError, c as createFieldPreset, l as createMemoryCache, f as filterResponseData, g as getFieldsForUser, e as getImmutableFields, a as getMongooseProjection, h as getSystemManagedFields, i as isFieldUpdateAllowed, v as validateUpdateBody } from '../mongooseToJsonSchema-CaRF_bCN.js';
2
+ import { S as SelectSpec, e as PopulateSpec, f as SortSpec } from '../types-Jni1KgkP.js';
3
3
  import 'mongoose';
4
4
 
5
5
  /**
@@ -1,3 +1,5 @@
1
- export { buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, createMemoryCache, getImmutableFields, getSystemManagedFields, isFieldUpdateAllowed, validateUpdateBody } from '../chunks/chunk-IT7DCOKR.js';
1
+ export { buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, createMemoryCache, getImmutableFields, getSystemManagedFields, isFieldUpdateAllowed, validateUpdateBody } from '../chunks/chunk-UE2IEXZJ.js';
2
2
  export { byIdKey, byQueryKey, createFieldPreset, filterResponseData, getFieldsForUser, getMongooseProjection, listPattern, listQueryKey, modelPattern, versionKey } from '../chunks/chunk-2ZN65ZOP.js';
3
- export { createError } from '../chunks/chunk-VJXDGP3C.js';
3
+ export { configureLogger } from '../chunks/chunk-URLJFIR7.js';
4
+ export { createError } from '../chunks/chunk-JWUAVZ3L.js';
5
+ import '../chunks/chunk-WSFCRVEQ.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@classytic/mongokit",
3
- "version": "3.1.6",
3
+ "version": "3.2.1",
4
4
  "description": "Production-grade MongoDB repositories with zero dependencies - smart pagination, events, and plugins",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -27,6 +27,10 @@
27
27
  "./actions": {
28
28
  "types": "./dist/actions/index.d.ts",
29
29
  "default": "./dist/actions/index.js"
30
+ },
31
+ "./ai": {
32
+ "types": "./dist/ai/index.d.ts",
33
+ "default": "./dist/ai/index.js"
30
34
  }
31
35
  },
32
36
  "files": [
@@ -50,6 +54,10 @@
50
54
  "cache",
51
55
  "multi-tenant",
52
56
  "multi-tenancy",
57
+ "vector-search",
58
+ "embeddings",
59
+ "atlas-search",
60
+ "observability",
53
61
  "event-driven",
54
62
  "plugin-based",
55
63
  "zero-dependencies",
@@ -73,7 +81,7 @@
73
81
  },
74
82
  "homepage": "https://github.com/classytic/mongokit#readme",
75
83
  "peerDependencies": {
76
- "mongoose": "^8.0.0 || ^9.0.0"
84
+ "mongoose": "^9.0.0"
77
85
  },
78
86
  "engines": {
79
87
  "node": ">=18"
@@ -1,14 +0,0 @@
1
- var __defProp = Object.defineProperty;
2
- var __export = (target, all) => {
3
- for (var name in all)
4
- __defProp(target, name, { get: all[name], enumerable: true });
5
- };
6
-
7
- // src/utils/error.ts
8
- function createError(status, message) {
9
- const error = new Error(message);
10
- error.status = status;
11
- return error;
12
- }
13
-
14
- export { __export, createError };