@classytic/mongokit 1.0.0 → 1.0.2

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
@@ -19,13 +19,17 @@
19
19
  ## 📦 Installation
20
20
 
21
21
  ```bash
22
- npm install @classytic/mongokit mongoose
22
+ npm install @classytic/mongokit mongoose mongoose-paginate-v2 mongoose-aggregate-paginate-v2
23
23
  ```
24
24
 
25
- > **Peer Dependency:** Requires `mongoose ^8.0.0`
25
+ > **Peer Dependencies:**
26
+ > - `mongoose ^8.0.0 || ^9.0.0` (supports both Mongoose 8 and 9)
27
+ > - `mongoose-paginate-v2 ^1.9.0` (for pagination support)
28
+ > - `mongoose-aggregate-paginate-v2 ^1.1.0` (for aggregation pagination)
26
29
 
27
30
  ---
28
31
 
32
+
29
33
  ## 🚀 Quick Start
30
34
 
31
35
  ### Basic Usage
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@classytic/mongokit",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Event-driven MongoDB repositories for any Node.js framework",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -52,7 +52,9 @@
52
52
  },
53
53
  "homepage": "https://github.com/classytic/mongokit#readme",
54
54
  "peerDependencies": {
55
- "mongoose": "^8.0.0"
55
+ "mongoose": "^8.0.0 || ^9.0.0",
56
+ "mongoose-paginate-v2": "^1.9.0",
57
+ "mongoose-aggregate-paginate-v2": "^1.1.0"
56
58
  },
57
59
  "dependencies": {
58
60
  "http-errors": "^2.0.0"
@@ -62,10 +64,12 @@
62
64
  },
63
65
  "scripts": {
64
66
  "test": "node --test test/*.test.js",
65
- "test:watch": "node --test --watch test/*.test.js"
67
+ "test:watch": "node --test --watch test/*.test.js",
68
+ "publish:npm": "npm publish --access public"
66
69
  },
67
70
  "devDependencies": {
68
- "mongoose-paginate-v2": "^1.9.0"
71
+ "mongoose": "^9.0.0-rc1",
72
+ "mongoose-paginate-v2": "^1.9.0",
73
+ "mongoose-aggregate-paginate-v2": "^1.1.0"
69
74
  }
70
75
  }
71
-
@@ -44,15 +44,16 @@ export async function createDefault(Model, overrides = {}, options = {}) {
44
44
  * Upsert (create or update)
45
45
  */
46
46
  export async function upsert(Model, query, data, options = {}) {
47
- return Model.findOneAndUpdate(
48
- query,
49
- { $setOnInsert: data },
50
- {
51
- upsert: true,
52
- new: true,
53
- runValidators: true,
54
- session: options.session,
55
- }
56
- );
57
- }
47
+ return Model.findOneAndUpdate(
48
+ query,
49
+ { $setOnInsert: data },
50
+ {
51
+ upsert: true,
52
+ new: true,
53
+ runValidators: true,
54
+ session: options.session,
55
+ ...(options.updatePipeline !== undefined ? { updatePipeline: options.updatePipeline } : {}),
56
+ }
57
+ );
58
+ }
58
59
 
@@ -81,17 +81,18 @@ export async function getAll(Model, queryParams, options = {}) {
81
81
  * Get or create
82
82
  */
83
83
  export async function getOrCreate(Model, query, createData, options = {}) {
84
- return Model.findOneAndUpdate(
85
- query,
86
- { $setOnInsert: createData },
87
- {
88
- upsert: true,
89
- new: true,
90
- runValidators: true,
91
- session: options.session,
92
- }
93
- );
94
- }
84
+ return Model.findOneAndUpdate(
85
+ query,
86
+ { $setOnInsert: createData },
87
+ {
88
+ upsert: true,
89
+ new: true,
90
+ runValidators: true,
91
+ session: options.session,
92
+ ...(options.updatePipeline !== undefined ? { updatePipeline: options.updatePipeline } : {}),
93
+ }
94
+ );
95
+ }
95
96
 
96
97
  /**
97
98
  * Count documents
@@ -8,15 +8,16 @@ import createError from 'http-errors';
8
8
  /**
9
9
  * Update by ID
10
10
  */
11
- export async function update(Model, id, data, options = {}) {
12
- const document = await Model.findByIdAndUpdate(id, data, {
13
- new: true,
14
- runValidators: true,
15
- session: options.session,
16
- })
17
- .select(options.select)
18
- .populate(parsePopulate(options.populate))
19
- .lean(options.lean);
11
+ export async function update(Model, id, data, options = {}) {
12
+ const document = await Model.findByIdAndUpdate(id, data, {
13
+ new: true,
14
+ runValidators: true,
15
+ session: options.session,
16
+ ...(options.updatePipeline !== undefined ? { updatePipeline: options.updatePipeline } : {}),
17
+ })
18
+ .select(options.select)
19
+ .populate(parsePopulate(options.populate))
20
+ .lean(options.lean);
20
21
 
21
22
  if (!document) {
22
23
  throw createError(404, 'Document not found');
@@ -32,14 +33,15 @@ export async function update(Model, id, data, options = {}) {
32
33
  export async function updateWithConstraints(Model, id, data, constraints = {}, options = {}) {
33
34
  const query = { _id: id, ...constraints };
34
35
 
35
- const document = await Model.findOneAndUpdate(query, data, {
36
- new: true,
37
- runValidators: true,
38
- session: options.session,
39
- })
40
- .select(options.select)
41
- .populate(parsePopulate(options.populate))
42
- .lean(options.lean);
36
+ const document = await Model.findOneAndUpdate(query, data, {
37
+ new: true,
38
+ runValidators: true,
39
+ session: options.session,
40
+ ...(options.updatePipeline !== undefined ? { updatePipeline: options.updatePipeline } : {}),
41
+ })
42
+ .select(options.select)
43
+ .populate(parsePopulate(options.populate))
44
+ .lean(options.lean);
43
45
 
44
46
  return document;
45
47
  }
@@ -106,10 +108,11 @@ export async function updateWithValidation(
106
108
  * Update many documents
107
109
  */
108
110
  export async function updateMany(Model, query, data, options = {}) {
109
- const result = await Model.updateMany(query, data, {
110
- runValidators: true,
111
- session: options.session,
112
- });
111
+ const result = await Model.updateMany(query, data, {
112
+ runValidators: true,
113
+ session: options.session,
114
+ ...(options.updatePipeline !== undefined ? { updatePipeline: options.updatePipeline } : {}),
115
+ });
113
116
 
114
117
  return {
115
118
  matchedCount: result.matchedCount,
@@ -121,13 +124,14 @@ export async function updateMany(Model, query, data, options = {}) {
121
124
  * Update by query
122
125
  */
123
126
  export async function updateByQuery(Model, query, data, options = {}) {
124
- const document = await Model.findOneAndUpdate(query, data, {
125
- new: true,
126
- runValidators: true,
127
- session: options.session,
128
- })
129
- .select(options.select)
130
- .populate(parsePopulate(options.populate))
127
+ const document = await Model.findOneAndUpdate(query, data, {
128
+ new: true,
129
+ runValidators: true,
130
+ session: options.session,
131
+ ...(options.updatePipeline !== undefined ? { updatePipeline: options.updatePipeline } : {}),
132
+ })
133
+ .select(options.select)
134
+ .populate(parsePopulate(options.populate))
131
135
  .lean(options.lean);
132
136
 
133
137
  if (!document && options.throwOnNotFound !== false) {
@@ -1,9 +1,17 @@
1
- import { Model, Document, FilterQuery, UpdateQuery, ClientSession } from 'mongoose';
2
-
3
- export interface ActionOptions {
4
- session?: ClientSession;
5
- [key: string]: any;
6
- }
1
+ import { Model, Document, UpdateQuery, ClientSession } from 'mongoose';
2
+
3
+ // Compatibility alias: QueryFilter was introduced in Mongoose 9 and replaces FilterQuery.
4
+ // @ts-ignore - QueryFilter only exists in mongoose >= 9
5
+ type QueryFilterV9<T> = import('mongoose').QueryFilter<T>;
6
+ // @ts-ignore - FilterQuery was removed in mongoose >= 9
7
+ type QueryFilterV8<T> = import('mongoose').FilterQuery<T>;
8
+ type CompatibleQueryFilter<T> = QueryFilterV9<T> | QueryFilterV8<T>;
9
+
10
+ export interface ActionOptions {
11
+ session?: ClientSession;
12
+ updatePipeline?: boolean;
13
+ [key: string]: any;
14
+ }
7
15
 
8
16
  // Create actions
9
17
  export function create<T extends Document>(
@@ -24,12 +32,12 @@ export function createDefault<T extends Document>(
24
32
  options?: ActionOptions
25
33
  ): Promise<T>;
26
34
 
27
- export function upsert<T extends Document>(
28
- Model: Model<T>,
29
- query: FilterQuery<T>,
30
- data: Partial<T>,
31
- options?: ActionOptions
32
- ): Promise<T>;
35
+ export function upsert<T extends Document>(
36
+ Model: Model<T>,
37
+ query: CompatibleQueryFilter<T>,
38
+ data: Partial<T>,
39
+ options?: ActionOptions
40
+ ): Promise<T>;
33
41
 
34
42
  // Read actions
35
43
  export function getById<T extends Document>(
@@ -38,30 +46,30 @@ export function getById<T extends Document>(
38
46
  options?: ActionOptions
39
47
  ): Promise<T | null>;
40
48
 
41
- export function getByQuery<T extends Document>(
42
- Model: Model<T>,
43
- query: FilterQuery<T>,
44
- options?: ActionOptions
45
- ): Promise<T | null>;
46
-
47
- export function getOrCreate<T extends Document>(
48
- Model: Model<T>,
49
- query: FilterQuery<T>,
50
- createData: Partial<T>,
51
- options?: ActionOptions
52
- ): Promise<T>;
53
-
54
- export function count<T extends Document>(
55
- Model: Model<T>,
56
- query?: FilterQuery<T>,
57
- options?: ActionOptions
58
- ): Promise<number>;
59
-
60
- export function exists<T extends Document>(
61
- Model: Model<T>,
62
- query: FilterQuery<T>,
63
- options?: ActionOptions
64
- ): Promise<boolean>;
49
+ export function getByQuery<T extends Document>(
50
+ Model: Model<T>,
51
+ query: CompatibleQueryFilter<T>,
52
+ options?: ActionOptions
53
+ ): Promise<T | null>;
54
+
55
+ export function getOrCreate<T extends Document>(
56
+ Model: Model<T>,
57
+ query: CompatibleQueryFilter<T>,
58
+ createData: Partial<T>,
59
+ options?: ActionOptions
60
+ ): Promise<T>;
61
+
62
+ export function count<T extends Document>(
63
+ Model: Model<T>,
64
+ query?: CompatibleQueryFilter<T>,
65
+ options?: ActionOptions
66
+ ): Promise<number>;
67
+
68
+ export function exists<T extends Document>(
69
+ Model: Model<T>,
70
+ query: CompatibleQueryFilter<T>,
71
+ options?: ActionOptions
72
+ ): Promise<boolean>;
65
73
 
66
74
  // Update actions
67
75
  export function update<T extends Document>(
@@ -71,12 +79,12 @@ export function update<T extends Document>(
71
79
  options?: ActionOptions
72
80
  ): Promise<T | null>;
73
81
 
74
- export function updateMany<T extends Document>(
75
- Model: Model<T>,
76
- query: FilterQuery<T>,
77
- data: UpdateQuery<T>,
78
- options?: ActionOptions
79
- ): Promise<any>;
82
+ export function updateMany<T extends Document>(
83
+ Model: Model<T>,
84
+ query: CompatibleQueryFilter<T>,
85
+ data: UpdateQuery<T>,
86
+ options?: ActionOptions
87
+ ): Promise<any>;
80
88
 
81
89
  // Delete actions
82
90
  export function deleteById<T extends Document>(
@@ -85,11 +93,11 @@ export function deleteById<T extends Document>(
85
93
  options?: ActionOptions
86
94
  ): Promise<T | null>;
87
95
 
88
- export function deleteMany<T extends Document>(
89
- Model: Model<T>,
90
- query: FilterQuery<T>,
91
- options?: ActionOptions
92
- ): Promise<any>;
96
+ export function deleteMany<T extends Document>(
97
+ Model: Model<T>,
98
+ query: CompatibleQueryFilter<T>,
99
+ options?: ActionOptions
100
+ ): Promise<any>;
93
101
 
94
102
  // Aggregate actions
95
103
  export function aggregate<T extends Document>(
@@ -104,10 +112,10 @@ export function aggregatePaginate<T extends Document>(
104
112
  options?: ActionOptions
105
113
  ): Promise<any>;
106
114
 
107
- export function distinct<T extends Document>(
108
- Model: Model<T>,
109
- field: string,
110
- query?: FilterQuery<T>,
111
- options?: ActionOptions
112
- ): Promise<any[]>;
115
+ export function distinct<T extends Document>(
116
+ Model: Model<T>,
117
+ field: string,
118
+ query?: CompatibleQueryFilter<T>,
119
+ options?: ActionOptions
120
+ ): Promise<any[]>;
113
121
 
package/types/index.d.ts CHANGED
@@ -1,12 +1,20 @@
1
- import { Model, Document, ClientSession, PaginateOptions, PaginateResult, FilterQuery, UpdateQuery, AggregateOptions } from 'mongoose';
2
-
3
- export interface RepositoryOptions {
4
- session?: ClientSession;
5
- populate?: string | string[] | any;
6
- select?: string | any;
7
- lean?: boolean;
8
- throwOnNotFound?: boolean;
9
- }
1
+ import { Model, Document, ClientSession, PaginateOptions, PaginateResult, UpdateQuery, AggregateOptions } from 'mongoose';
2
+
3
+ // Compatibility alias: QueryFilter was introduced in Mongoose 9 and replaces FilterQuery.
4
+ // @ts-ignore - QueryFilter only exists in mongoose >= 9
5
+ type QueryFilterV9<T> = import('mongoose').QueryFilter<T>;
6
+ // @ts-ignore - FilterQuery was removed in mongoose >= 9
7
+ type QueryFilterV8<T> = import('mongoose').FilterQuery<T>;
8
+ type CompatibleQueryFilter<T> = QueryFilterV9<T> | QueryFilterV8<T>;
9
+
10
+ export interface RepositoryOptions {
11
+ session?: ClientSession;
12
+ populate?: string | string[] | any;
13
+ select?: string | any;
14
+ lean?: boolean;
15
+ throwOnNotFound?: boolean;
16
+ updatePipeline?: boolean;
17
+ }
10
18
 
11
19
  export interface QueryParams {
12
20
  pagination?: {
@@ -55,23 +63,23 @@ export class Repository<T extends Document> {
55
63
 
56
64
  // CRUD operations
57
65
  create(data: Partial<T>, options?: RepositoryOptions): Promise<T>;
58
- createMany(dataArray: Partial<T>[], options?: RepositoryOptions): Promise<T[]>;
59
-
60
- getById(id: string, options?: RepositoryOptions): Promise<T | null>;
61
- getByQuery(query: FilterQuery<T>, options?: RepositoryOptions): Promise<T | null>;
62
- getAll(queryParams?: QueryParams, options?: RepositoryOptions): Promise<PaginateResult<T>>;
63
- getOrCreate(query: FilterQuery<T>, createData: Partial<T>, options?: RepositoryOptions): Promise<T>;
64
-
65
- count(query?: FilterQuery<T>, options?: RepositoryOptions): Promise<number>;
66
- exists(query: FilterQuery<T>, options?: RepositoryOptions): Promise<boolean>;
67
-
68
- update(id: string, data: UpdateQuery<T>, options?: RepositoryOptions): Promise<T | null>;
66
+ createMany(dataArray: Partial<T>[], options?: RepositoryOptions): Promise<T[]>;
67
+
68
+ getById(id: string, options?: RepositoryOptions): Promise<T | null>;
69
+ getByQuery(query: CompatibleQueryFilter<T>, options?: RepositoryOptions): Promise<T | null>;
70
+ getAll(queryParams?: QueryParams, options?: RepositoryOptions): Promise<PaginateResult<T>>;
71
+ getOrCreate(query: CompatibleQueryFilter<T>, createData: Partial<T>, options?: RepositoryOptions): Promise<T>;
72
+
73
+ count(query?: CompatibleQueryFilter<T>, options?: RepositoryOptions): Promise<number>;
74
+ exists(query: CompatibleQueryFilter<T>, options?: RepositoryOptions): Promise<boolean>;
75
+
76
+ update(id: string, data: UpdateQuery<T>, options?: RepositoryOptions): Promise<T | null>;
69
77
  delete(id: string, options?: RepositoryOptions): Promise<T | null>;
70
78
 
71
- // Aggregation
72
- aggregate(pipeline: any[], options?: AggregateOptions): Promise<any[]>;
73
- aggregatePaginate(pipeline: any[], options?: PaginateOptions): Promise<any>;
74
- distinct(field: string, query?: FilterQuery<T>, options?: RepositoryOptions): Promise<any[]>;
79
+ // Aggregation
80
+ aggregate(pipeline: any[], options?: AggregateOptions): Promise<any[]>;
81
+ aggregatePaginate(pipeline: any[], options?: PaginateOptions): Promise<any>;
82
+ distinct(field: string, query?: CompatibleQueryFilter<T>, options?: RepositoryOptions): Promise<any[]>;
75
83
 
76
84
  // Transaction support
77
85
  withTransaction<R>(callback: (session: ClientSession) => Promise<R>): Promise<R>;