@classytic/mongokit 3.3.2 → 3.4.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.
Files changed (28) hide show
  1. package/README.md +137 -7
  2. package/dist/PaginationEngine-nY04eGUM.mjs +290 -0
  3. package/dist/actions/index.d.mts +2 -9
  4. package/dist/actions/index.mjs +3 -5
  5. package/dist/ai/index.d.mts +1 -1
  6. package/dist/ai/index.mjs +3 -3
  7. package/dist/chunk-CfYAbeIz.mjs +13 -0
  8. package/dist/{limits-s1-d8rWb.mjs → cursor-CHToazHy.mjs} +122 -171
  9. package/dist/{logger-D8ily-PP.mjs → error-Bpbi_NKo.mjs} +34 -22
  10. package/dist/{cache-keys-CzFwVnLy.mjs → field-selection-reyDRzXf.mjs} +110 -112
  11. package/dist/{aggregate-BkOG9qwr.d.mts → index-BuoZIZ15.d.mts} +132 -129
  12. package/dist/index.d.mts +549 -543
  13. package/dist/index.mjs +33 -101
  14. package/dist/{mongooseToJsonSchema-D_i2Am_O.mjs → mongooseToJsonSchema-B6Qyl8BK.mjs} +13 -12
  15. package/dist/{mongooseToJsonSchema-B6O2ED3n.d.mts → mongooseToJsonSchema-RX9YfJLu.d.mts} +24 -17
  16. package/dist/pagination/PaginationEngine.d.mts +1 -1
  17. package/dist/pagination/PaginationEngine.mjs +2 -209
  18. package/dist/plugins/index.d.mts +1 -2
  19. package/dist/plugins/index.mjs +2 -3
  20. package/dist/sort-C-BJEWUZ.mjs +57 -0
  21. package/dist/{types-pVY0w1Pp.d.mts → types-COINbsdL.d.mts} +57 -27
  22. package/dist/{aggregate-BClp040M.mjs → update-DGKMmBgG.mjs} +575 -565
  23. package/dist/utils/index.d.mts +2 -2
  24. package/dist/utils/index.mjs +4 -5
  25. package/dist/{custom-id.plugin-BJ3FSnzt.d.mts → validation-chain.plugin-BNoaKDOm.d.mts} +832 -832
  26. package/dist/{custom-id.plugin-FInXDsUX.mjs → validation-chain.plugin-da3fOo8A.mjs} +2410 -2246
  27. package/package.json +11 -6
  28. package/dist/chunk-DQk6qfdC.mjs +0 -18
@@ -0,0 +1,57 @@
1
+ import { t as __exportAll } from "./chunk-CfYAbeIz.mjs";
2
+ //#region src/pagination/utils/sort.ts
3
+ var sort_exports = /* @__PURE__ */ __exportAll({
4
+ getPrimaryField: () => getPrimaryField,
5
+ normalizeSort: () => normalizeSort,
6
+ validateKeysetSort: () => validateKeysetSort
7
+ });
8
+ /**
9
+ * Normalizes sort object to ensure stable key order
10
+ * Primary fields first, _id last (not alphabetical)
11
+ *
12
+ * @param sort - Sort specification
13
+ * @returns Normalized sort with stable key order
14
+ */
15
+ function normalizeSort(sort) {
16
+ const normalized = {};
17
+ Object.keys(sort).forEach((key) => {
18
+ if (key !== "_id") normalized[key] = sort[key];
19
+ });
20
+ if (sort._id !== void 0) normalized._id = sort._id;
21
+ return normalized;
22
+ }
23
+ /**
24
+ * Validates and normalizes sort for keyset pagination
25
+ * Auto-adds _id tie-breaker if needed
26
+ * Ensures _id direction matches primary field
27
+ *
28
+ * @param sort - Sort specification
29
+ * @returns Validated and normalized sort
30
+ * @throws Error if sort is invalid for keyset pagination
31
+ */
32
+ function validateKeysetSort(sort) {
33
+ const keys = Object.keys(sort);
34
+ if (keys.length === 0) throw new Error("Keyset pagination requires at least one sort field");
35
+ if (keys.length === 1 && keys[0] === "_id") return normalizeSort(sort);
36
+ for (const key of keys) if (sort[key] !== 1 && sort[key] !== -1) throw new Error(`Invalid sort direction for "${key}": must be 1 or -1, got ${sort[key]}`);
37
+ const nonIdKeys = keys.filter((k) => k !== "_id");
38
+ const primaryDirection = sort[nonIdKeys[0]];
39
+ for (const key of nonIdKeys) if (sort[key] !== primaryDirection) throw new Error("All sort fields must share the same direction for keyset pagination");
40
+ if (keys.includes("_id") && sort._id !== primaryDirection) throw new Error("_id direction must match primary field direction");
41
+ if (!keys.includes("_id")) return normalizeSort({
42
+ ...sort,
43
+ _id: primaryDirection
44
+ });
45
+ return normalizeSort(sort);
46
+ }
47
+ /**
48
+ * Extracts primary sort field (first non-_id field)
49
+ *
50
+ * @param sort - Sort specification
51
+ * @returns Primary field name
52
+ */
53
+ function getPrimaryField(sort) {
54
+ return Object.keys(sort).find((k) => k !== "_id") || "_id";
55
+ }
56
+ //#endregion
57
+ export { sort_exports as n, validateKeysetSort as r, getPrimaryField as t };
@@ -1,4 +1,4 @@
1
- import * as mongoose$1 from "mongoose";
1
+ import * as _$mongoose from "mongoose";
2
2
  import { ClientSession, Document, Model, PipelineStage, PopulateOptions, Types } from "mongoose";
3
3
 
4
4
  //#region src/query/LookupBuilder.d.ts
@@ -13,6 +13,8 @@ interface LookupOptions {
13
13
  as?: string;
14
14
  /** Whether to unwrap array to single object */
15
15
  single?: boolean;
16
+ /** Field selection on the joined collection (shorthand for $project pipeline) */
17
+ select?: string | Record<string, 0 | 1>;
16
18
  /** Additional pipeline to run on the joined collection */
17
19
  pipeline?: PipelineStage[];
18
20
  /** Optional let variables for pipeline */
@@ -76,6 +78,11 @@ declare class LookupBuilder {
76
78
  * Allows referencing local document fields in the pipeline
77
79
  */
78
80
  let(variables: Record<string, string>): this;
81
+ /**
82
+ * Control pipeline sanitization (default: true)
83
+ * Set to false for auto-generated pipelines that are known safe
84
+ */
85
+ sanitize(enabled: boolean): this;
79
86
  /**
80
87
  * Build the $lookup aggregation stage(s)
81
88
  * Returns an array of pipeline stages including $lookup and optional $unwind
@@ -451,7 +458,7 @@ interface IResponseFormatter {
451
458
  //#endregion
452
459
  //#region src/types.d.ts
453
460
  /** Read Preference Type for replica sets */
454
- type ReadPreferenceType = "primary" | "primaryPreferred" | "secondary" | "secondaryPreferred" | "nearest" | (string & {});
461
+ type ReadPreferenceType = 'primary' | 'primaryPreferred' | 'secondary' | 'secondaryPreferred' | 'nearest' | (string & {});
455
462
  /** Re-export mongoose ObjectId */
456
463
  type ObjectId = Types.ObjectId;
457
464
  /** Generic document type */
@@ -514,10 +521,10 @@ type NonNullableFields<T> = { [K in keyof T]: NonNullable<T[K]> };
514
521
  /**
515
522
  * Create/Update input types from document
516
523
  */
517
- type CreateInput<TDoc> = Omit<TDoc, "_id" | "createdAt" | "updatedAt" | "__v">;
518
- type UpdateInput<TDoc> = Partial<Omit<TDoc, "_id" | "createdAt" | "__v">>;
524
+ type CreateInput<TDoc> = Omit<TDoc, '_id' | 'createdAt' | 'updatedAt' | '__v'>;
525
+ type UpdateInput<TDoc> = Partial<Omit<TDoc, '_id' | 'createdAt' | '__v'>>;
519
526
  /** Hook execution mode */
520
- type HookMode = "sync" | "async";
527
+ type HookMode = 'sync' | 'async';
521
528
  /** Repository options */
522
529
  interface RepositoryOptions {
523
530
  /** Whether repository event hooks are awaited */
@@ -538,10 +545,21 @@ interface PaginationConfig {
538
545
  /** Use estimatedDocumentCount for faster counts on large collections */
539
546
  useEstimatedCount?: boolean;
540
547
  }
548
+ /** MongoDB collation options for locale-aware string comparison */
549
+ interface CollationOptions {
550
+ locale: string;
551
+ caseLevel?: boolean;
552
+ caseFirst?: 'upper' | 'lower' | 'off';
553
+ strength?: 1 | 2 | 3 | 4 | 5;
554
+ numericOrdering?: boolean;
555
+ alternate?: 'non-ignorable' | 'shifted';
556
+ maxVariable?: 'punct' | 'space';
557
+ backwards?: boolean;
558
+ }
541
559
  /** Base pagination options */
542
560
  interface BasePaginationOptions {
543
561
  /** Pagination mode (explicit override) */
544
- mode?: "offset" | "keyset";
562
+ mode?: 'offset' | 'keyset';
545
563
  /** MongoDB query filters */
546
564
  filters?: FilterQuery<AnyDocument>;
547
565
  /** Sort specification */
@@ -562,13 +580,15 @@ interface BasePaginationOptions {
562
580
  maxTimeMS?: number;
563
581
  /** Read preference for replica sets (e.g. 'secondaryPreferred') */
564
582
  readPreference?: ReadPreferenceType;
583
+ /** Collation for locale-aware string comparison and case-insensitive sorting */
584
+ collation?: CollationOptions;
565
585
  }
566
586
  /** Offset pagination options */
567
587
  interface OffsetPaginationOptions extends BasePaginationOptions {
568
588
  /** Page number (1-indexed) */
569
589
  page?: number;
570
590
  /** Count strategy for filtered queries (default: 'exact') */
571
- countStrategy?: "exact" | "estimated" | "none";
591
+ countStrategy?: 'exact' | 'estimated' | 'none';
572
592
  }
573
593
  /** Keyset (cursor) pagination options */
574
594
  interface KeysetPaginationOptions extends BasePaginationOptions {
@@ -591,17 +611,19 @@ interface AggregatePaginationOptions {
591
611
  hint?: string | Record<string, 1 | -1>;
592
612
  /** Maximum execution time in milliseconds */
593
613
  maxTimeMS?: number;
594
- /** Count strategy (default: 'exact' via $facet) */
595
- countStrategy?: "exact" | "estimated" | "none";
614
+ /** Count strategy (default: 'exact' via $facet).
615
+ * 'estimated' is accepted but treated as 'exact' in aggregation context
616
+ * since estimatedDocumentCount is not available inside pipelines. */
617
+ countStrategy?: 'exact' | 'estimated' | 'none';
596
618
  /** Pagination mode (reserved for API consistency) */
597
- mode?: "offset";
619
+ mode?: 'offset';
598
620
  /** Read preference for replica sets (e.g. 'secondaryPreferred') */
599
621
  readPreference?: ReadPreferenceType;
600
622
  }
601
623
  /** Offset pagination result */
602
624
  interface OffsetPaginationResult<T = unknown> {
603
625
  /** Pagination method used */
604
- method: "offset";
626
+ method: 'offset';
605
627
  /** Array of documents */
606
628
  docs: T[];
607
629
  /** Current page number */
@@ -622,7 +644,7 @@ interface OffsetPaginationResult<T = unknown> {
622
644
  /** Keyset pagination result */
623
645
  interface KeysetPaginationResult<T = unknown> {
624
646
  /** Pagination method used */
625
- method: "keyset";
647
+ method: 'keyset';
626
648
  /** Array of documents */
627
649
  docs: T[];
628
650
  /** Documents per page */
@@ -635,7 +657,7 @@ interface KeysetPaginationResult<T = unknown> {
635
657
  /** Aggregate pagination result */
636
658
  interface AggregatePaginationResult<T = unknown> {
637
659
  /** Pagination method used */
638
- method: "aggregate";
660
+ method: 'aggregate';
639
661
  /** Array of documents */
640
662
  docs: T[];
641
663
  /** Current page number */
@@ -670,7 +692,7 @@ interface OperationOptions {
670
692
  /** Additional query filters (e.g., for soft delete) */
671
693
  query?: Record<string, unknown>;
672
694
  /** Read preference for replica sets (e.g. 'secondaryPreferred') */
673
- readPreference?: "primary" | "primaryPreferred" | "secondary" | "secondaryPreferred" | "nearest" | string;
695
+ readPreference?: 'primary' | 'primaryPreferred' | 'secondary' | 'secondaryPreferred' | 'nearest' | string;
674
696
  }
675
697
  /** withTransaction options */
676
698
  interface WithTransactionOptions {
@@ -679,7 +701,7 @@ interface WithTransactionOptions {
679
701
  /** Optional hook to observe fallback triggers */
680
702
  onFallback?: (error: Error) => void;
681
703
  /** MongoDB transaction options (readConcern, writeConcern, readPreference, maxCommitTimeMS) */
682
- transactionOptions?: mongoose$1.mongo.TransactionOptions;
704
+ transactionOptions?: _$mongoose.mongo.TransactionOptions;
683
705
  }
684
706
  /** Create operation options */
685
707
  interface CreateOptions {
@@ -726,7 +748,7 @@ type UpdateWithValidationResult<T> = {
726
748
  error: {
727
749
  code: number;
728
750
  message: string;
729
- violations?: ValidationResult["violations"];
751
+ violations?: ValidationResult['violations'];
730
752
  };
731
753
  };
732
754
  /** User context for operations */
@@ -777,13 +799,13 @@ interface RepositoryContext {
777
799
  /** Search query string */
778
800
  search?: string;
779
801
  /** Pagination mode */
780
- mode?: "offset" | "keyset";
802
+ mode?: 'offset' | 'keyset';
781
803
  /** Query hint */
782
804
  hint?: string | Record<string, 1 | -1>;
783
805
  /** Maximum execution time in milliseconds */
784
806
  maxTimeMS?: number;
785
807
  /** Count strategy for offset pagination */
786
- countStrategy?: "exact" | "estimated" | "none";
808
+ countStrategy?: 'exact' | 'estimated' | 'none';
787
809
  /** Whether this is a soft delete operation (set by softDeletePlugin) */
788
810
  softDeleted?: boolean;
789
811
  /** Include soft-deleted documents in queries */
@@ -831,16 +853,22 @@ interface RepositoryInstance {
831
853
  removeAllListeners(event?: string): this;
832
854
  emit(event: string, data: unknown): void;
833
855
  emitAsync(event: string, data: unknown): Promise<void>;
834
- registerMethod?(name: string, fn: Function): void;
856
+ registerMethod?(name: string, fn: (...args: any[]) => any): void;
835
857
  hasMethod?(name: string): boolean;
858
+ _buildContext(operation: string, options: Record<string, unknown>): Promise<RepositoryContext>;
859
+ _handleError(error: Error): HttpError;
860
+ update(id: string | ObjectId, data: Record<string, unknown>, options?: Record<string, unknown>): Promise<unknown>;
861
+ aggregate(pipeline: PipelineStage[], options?: Record<string, unknown>): Promise<unknown[]>;
862
+ getByQuery(query: Record<string, unknown>, options?: Record<string, unknown>): Promise<unknown>;
863
+ _executeQuery<T>(buildQuery: (Model: Model<any>) => Promise<T>): Promise<T>;
836
864
  [key: string]: unknown;
837
865
  }
838
866
  /** Repository operation names */
839
- type RepositoryOperation = "create" | "createMany" | "update" | "updateMany" | "delete" | "deleteMany" | "getById" | "getByQuery" | "getAll" | "getOrCreate" | "count" | "exists" | "distinct" | "aggregate" | "aggregatePaginate" | "lookupPopulate" | "bulkWrite";
867
+ type RepositoryOperation = 'create' | 'createMany' | 'update' | 'updateMany' | 'delete' | 'deleteMany' | 'getById' | 'getByQuery' | 'getAll' | 'getOrCreate' | 'count' | 'exists' | 'distinct' | 'aggregate' | 'aggregatePaginate' | 'lookupPopulate' | 'bulkWrite';
840
868
  /** Event lifecycle phases */
841
- type EventPhase = "before" | "after" | "error";
869
+ type EventPhase = 'before' | 'after' | 'error';
842
870
  /** Repository event names (generated from template literals) */
843
- type RepositoryEvent = `${EventPhase}:${RepositoryOperation}` | "method:registered" | "error:hook";
871
+ type RepositoryEvent = `${EventPhase}:${RepositoryOperation}` | 'method:registered' | 'error:hook';
844
872
  /**
845
873
  * Type-safe event handler map
846
874
  *
@@ -890,7 +918,7 @@ interface SchemaBuilderOptions {
890
918
  /** Strict additional properties (default: false) */
891
919
  strictAdditionalProperties?: boolean;
892
920
  /** Date format: 'date' | 'datetime' */
893
- dateAs?: "date" | "datetime";
921
+ dateAs?: 'date' | 'datetime';
894
922
  /** Create schema options */
895
923
  create?: {
896
924
  /** Fields to omit from create schema */omitFields?: string[]; /** Override required status */
@@ -940,7 +968,7 @@ interface CrudSchemas {
940
968
  }
941
969
  /** Decoded cursor */
942
970
  interface DecodedCursor {
943
- /** Primary sort field value (rehydrated) */
971
+ /** Primary sort field value (rehydrated) — legacy compat */
944
972
  value: unknown;
945
973
  /** Document ID (rehydrated) */
946
974
  id: ObjectId | string;
@@ -948,13 +976,15 @@ interface DecodedCursor {
948
976
  sort: SortSpec;
949
977
  /** Cursor version */
950
978
  version: number;
979
+ /** All sort field values (rehydrated) — for compound sort */
980
+ values?: Record<string, unknown>;
951
981
  }
952
982
  /** Validator definition */
953
983
  interface ValidatorDefinition {
954
984
  /** Validator name */
955
985
  name: string;
956
986
  /** Operations to apply validator to */
957
- operations?: Array<"create" | "createMany" | "update" | "delete">;
987
+ operations?: Array<'create' | 'createMany' | 'update' | 'delete'>;
958
988
  /** Validation function */
959
989
  validate: (context: RepositoryContext, repo?: RepositoryInstance) => void | Promise<void>;
960
990
  }
@@ -971,7 +1001,7 @@ interface Logger {
971
1001
  debug?(message: string, meta?: Record<string, unknown>): void;
972
1002
  }
973
1003
  /** Filter mode for soft delete queries */
974
- type SoftDeleteFilterMode = "null" | "exists";
1004
+ type SoftDeleteFilterMode = 'null' | 'exists';
975
1005
  /** Soft delete plugin options */
976
1006
  interface SoftDeleteOptions {
977
1007
  /** Field name for deletion timestamp (default: 'deletedAt') */
@@ -1264,4 +1294,4 @@ type AllPluginMethods<TDoc> = {
1264
1294
  */
1265
1295
  type WithPlugins<TDoc, TRepo extends RepositoryInstance = RepositoryInstance> = TRepo & AllPluginMethods<TDoc>;
1266
1296
  //#endregion
1267
- export { SchemaBuilderOptions as $, KeysetPaginationOptions as A, PaginationResult as B, GroupResult as C, InferRawDoc as D, InferDocument as E, ObjectId as F, PopulateSpec as G, Plugin as H, OffsetPaginationOptions as I, RepositoryEvent as J, ReadPreferenceType as K, OffsetPaginationResult as L, Logger as M, MinMaxResult as N, JsonSchema as O, NonNullableFields as P, RequiredBy as Q, OperationOptions as R, FieldRules as S, LookupOptions as St, HttpError as T, PluginFunction as U, PartialBy as V, PluginType as W, RepositoryOperation as X, RepositoryInstance as Y, RepositoryOptions as Z, DeleteResult as _, IController as _t, AnyModel as a, SortSpec as at, EventPhase as b, IResponseFormatter as bt, CacheOptions as c, UpdateManyResult as ct, CascadeRelation as d, UserContext as dt, SelectSpec as et, CreateInput as f, ValidationChainOptions as ft, DeepPartial as g, WithTransactionOptions as gt, DecodedCursor as h, WithPlugins as ht, AnyDocument as i, SortDirection as it, KeysetPaginationResult as j, KeysOfType as k, CacheStats as l, UpdateOptions as lt, CrudSchemas as m, ValidatorDefinition as mt, AggregatePaginationResult as n, SoftDeleteOptions as nt, CacheAdapter as o, Strict as ot, CreateOptions as p, ValidationResult as pt, RepositoryContext as q, AllPluginMethods as r, SoftDeleteRepository as rt, CacheOperationOptions as s, UpdateInput as st, AggregatePaginationOptions as t, SoftDeleteFilterMode as tt, CascadeOptions as u, UpdateWithValidationResult as ut, EventHandlers as v, IControllerResponse as vt, HookMode as w, FieldPreset as x, LookupBuilder as xt, EventPayload as y, IRequestContext as yt, PaginationConfig as z };
1297
+ export { RequiredBy as $, KeysOfType as A, PaginationConfig as B, FieldRules as C, LookupOptions as Ct, InferDocument as D, HttpError as E, NonNullableFields as F, PluginType as G, PartialBy as H, ObjectId as I, RepositoryContext as J, PopulateSpec as K, OffsetPaginationOptions as L, KeysetPaginationResult as M, Logger as N, InferRawDoc as O, MinMaxResult as P, RepositoryOptions as Q, OffsetPaginationResult as R, FieldPreset as S, LookupBuilder as St, HookMode as T, Plugin as U, PaginationResult as V, PluginFunction as W, RepositoryInstance as X, RepositoryEvent as Y, RepositoryOperation as Z, DeepPartial as _, WithTransactionOptions as _t, AnyModel as a, SortDirection as at, EventPayload as b, IRequestContext as bt, CacheOptions as c, UpdateInput as ct, CascadeRelation as d, UpdateWithValidationResult as dt, SchemaBuilderOptions as et, CollationOptions as f, UserContext as ft, DecodedCursor as g, WithPlugins as gt, CrudSchemas as h, ValidatorDefinition as ht, AnyDocument as i, SoftDeleteRepository as it, KeysetPaginationOptions as j, JsonSchema as k, CacheStats as l, UpdateManyResult as lt, CreateOptions as m, ValidationResult as mt, AggregatePaginationResult as n, SoftDeleteFilterMode as nt, CacheAdapter as o, SortSpec as ot, CreateInput as p, ValidationChainOptions as pt, ReadPreferenceType as q, AllPluginMethods as r, SoftDeleteOptions as rt, CacheOperationOptions as s, Strict as st, AggregatePaginationOptions as t, SelectSpec as tt, CascadeOptions as u, UpdateOptions as ut, DeleteResult as v, IController as vt, GroupResult as w, EventPhase as x, IResponseFormatter as xt, EventHandlers as y, IControllerResponse as yt, OperationOptions as z };