@flowerforce/flowerbase 1.3.1-beta.2 → 1.3.1-beta.4

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,3 +1,4 @@
1
+ import { Document } from 'mongodb';
1
2
  import { ExecuteQueryParams, Functions } from './interface';
2
3
  /**
3
4
  * > Loads the functions config json file
@@ -13,13 +14,14 @@ export declare const loadFunctions: (rootDir?: string) => Promise<Functions>;
13
14
  export declare const executeQuery: ({ currentMethod, query, update, filter, options, returnNewDocument, document, documents, pipeline, isClient }: ExecuteQueryParams) => Promise<{
14
15
  find: () => Promise<any[]>;
15
16
  findOne: () => Promise<unknown>;
17
+ count: () => Promise<number>;
16
18
  deleteOne: () => Promise<unknown>;
17
- insertOne: () => Promise<import("mongodb/mongodb").InsertOneResult<import("bson").Document>>;
18
- updateOne: () => Promise<unknown> | import("mongodb/mongodb").FindCursor<any> | import("mongodb/mongodb").ChangeStream<import("bson").Document, import("bson").Document> | import("mongodb/mongodb").AggregationCursor<import("bson").Document>;
19
- findOneAndUpdate: () => Promise<import("bson").Document | null>;
20
- aggregate: () => Promise<import("bson").Document[]>;
21
- insertMany: () => Promise<import("mongodb/mongodb").InsertManyResult<import("bson").Document>>;
22
- updateMany: () => Promise<import("mongodb/mongodb").UpdateResult<import("bson").Document>>;
23
- deleteMany: () => Promise<import("mongodb/mongodb").DeleteResult>;
19
+ insertOne: () => Promise<import("mongodb").InsertOneResult<Document>>;
20
+ updateOne: () => Promise<unknown> | import("mongodb").FindCursor<any> | import("mongodb").ChangeStream<Document, Document> | import("mongodb").AggregationCursor<Document>;
21
+ findOneAndUpdate: () => Promise<Document | null>;
22
+ aggregate: () => Promise<Document[]>;
23
+ insertMany: () => Promise<import("mongodb").InsertManyResult<Document>>;
24
+ updateMany: () => Promise<import("mongodb").UpdateResult<Document>>;
25
+ deleteMany: () => Promise<import("mongodb").DeleteResult>;
24
26
  }>;
25
27
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/features/functions/utils.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAE3D;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAU,gBAAuB,KAAG,OAAO,CAAC,SAAS,CAwB9E,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GAAU,+GAWhC,kBAAkB;;;;;;;;;;;EA0DpB,CAAA"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/features/functions/utils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAGlC,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAE3D;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAU,gBAAuB,KAAG,OAAO,CAAC,SAAS,CAwB9E,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GAAU,+GAWhC,kBAAkB;;;;;;;;;;;;EA4EpB,CAAA"}
@@ -70,15 +70,29 @@ const executeQuery = (_a) => __awaiter(void 0, [_a], void 0, function* ({ curren
70
70
  : typeof returnNewDocument === 'boolean'
71
71
  ? { returnDocument: returnNewDocument ? 'after' : 'before' }
72
72
  : undefined;
73
+ const parsedOptions = resolvedOptions ? bson_1.EJSON.deserialize(resolvedOptions) : undefined;
73
74
  return {
74
75
  find: () => __awaiter(void 0, void 0, void 0, function* () {
75
- return yield currentMethod(bson_1.EJSON.deserialize(resolvedQuery)).toArray();
76
+ return yield (() => {
77
+ const cursor = currentMethod(bson_1.EJSON.deserialize(resolvedQuery));
78
+ if (parsedOptions === null || parsedOptions === void 0 ? void 0 : parsedOptions.sort) {
79
+ cursor.sort(parsedOptions.sort);
80
+ }
81
+ if (typeof (parsedOptions === null || parsedOptions === void 0 ? void 0 : parsedOptions.skip) === 'number') {
82
+ cursor.skip(parsedOptions.skip);
83
+ }
84
+ if (typeof (parsedOptions === null || parsedOptions === void 0 ? void 0 : parsedOptions.limit) === 'number') {
85
+ cursor.limit(parsedOptions.limit);
86
+ }
87
+ return cursor.toArray();
88
+ })();
76
89
  }),
77
90
  findOne: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery)),
91
+ count: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), parsedOptions),
78
92
  deleteOne: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery)),
79
93
  insertOne: () => currentMethod(bson_1.EJSON.deserialize(document)),
80
94
  updateOne: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), bson_1.EJSON.deserialize(resolvedUpdate)),
81
- findOneAndUpdate: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), bson_1.EJSON.deserialize(resolvedUpdate), resolvedOptions ? bson_1.EJSON.deserialize(resolvedOptions) : undefined),
95
+ findOneAndUpdate: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), bson_1.EJSON.deserialize(resolvedUpdate), parsedOptions),
82
96
  aggregate: () => __awaiter(void 0, void 0, void 0, function* () {
83
97
  return (yield currentMethod(bson_1.EJSON.deserialize(pipeline), {}, // TODO -> ADD OPTIONS
84
98
  isClient)).toArray();
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/mongodb-atlas/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAyC,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAiyBrF,QAAA,MAAM,YAAY,EAAE,oBAsBlB,CAAA;AAEF,eAAe,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/mongodb-atlas/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAyC,oBAAoB,EAAE,MAAM,SAAS,CAAA;AA4yBrF,QAAA,MAAM,YAAY,EAAE,oBAsBlB,CAAA;AAEF,eAAe,YAAY,CAAA"}
@@ -401,6 +401,16 @@ const getOperators = (collection, { rules, collName, user, run_as_system }) => {
401
401
  // System mode: return original unfiltered cursor
402
402
  return collection.find(query);
403
403
  },
404
+ count: (query, options) => {
405
+ if (!run_as_system) {
406
+ (0, utils_2.checkDenyOperation)(normalizedRules, collection.collectionName, model_1.CRUD_OPERATIONS.READ);
407
+ const formattedQuery = (0, utils_2.getFormattedQuery)(filters, query, user);
408
+ const currentQuery = formattedQuery.length ? { $and: formattedQuery } : {};
409
+ logService('count query', { collName, currentQuery });
410
+ return collection.countDocuments(currentQuery, options);
411
+ }
412
+ return collection.countDocuments(query, options);
413
+ },
404
414
  /**
405
415
  * Watches changes on a MongoDB collection with optional role-based filtering of change events.
406
416
  *
@@ -30,6 +30,7 @@ export type GetOperatorsFunction = (collection: Collection<Document>, { rules, c
30
30
  updateOne: (...params: Parameters<Method<'updateOne'>>) => ReturnType<Method<'updateOne'>>;
31
31
  findOneAndUpdate: (filter: MongoFilter<Document>, update: UpdateFilter<Document> | Document[], options?: FindOneAndUpdateOptions) => Promise<Document | null>;
32
32
  find: (...params: Parameters<Method<'find'>>) => FindCursor;
33
+ count: (...params: Parameters<Method<'countDocuments'>>) => ReturnType<Method<'countDocuments'>>;
33
34
  watch: (...params: Parameters<Method<'watch'>>) => ReturnType<Method<'watch'>>;
34
35
  aggregate: (...params: [...Parameters<Method<'aggregate'>>, isClient: boolean]) => ReturnType<Method<'aggregate'>>;
35
36
  insertMany: (...params: Parameters<Method<'insertMany'>>) => ReturnType<Method<'insertMany'>>;
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../src/services/mongodb-atlas/model.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../src/services/mongodb-atlas/model.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,7 @@ import { AggregationPipeline, Filter, Projection, Rules } from '../../features/r
5
5
  import { Role } from '../../utils/roles/interface';
6
6
  import { CRUD_OPERATIONS, GetValidRuleParams } from './model';
7
7
  export declare const getValidRule: <T extends Role | Filter>({ filters, user, record }: GetValidRuleParams<T>) => T[];
8
- export declare const getFormattedQuery: (filters: Filter[] | undefined, query: Parameters<Collection<Document>["findOne"]>[0], user?: User) => FilterMongoDB<Document>[];
8
+ export declare const getFormattedQuery: (filters?: Filter[], query?: Parameters<Collection<Document>["findOne"]>[0], user?: User) => FilterMongoDB<Document>[];
9
9
  export declare const getFormattedProjection: (filters?: Filter[], user?: User) => Projection | null;
10
10
  export declare const applyAccessControlToPipeline: (pipeline: AggregationPipeline, rules: Record<string, {
11
11
  filters?: Filter[];
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/services/mongodb-atlas/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAElC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,SAAS,CAAA;AACvE,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AACtC,OAAO,EACL,mBAAmB,EAEnB,MAAM,EAEN,UAAU,EACV,KAAK,EAGN,MAAM,gCAAgC,CAAA;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,6BAA6B,CAAA;AAGlD,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAE7D,eAAO,MAAM,YAAY,GAAI,CAAC,SAAS,IAAI,GAAG,MAAM,EAAE,2BAInD,kBAAkB,CAAC,CAAC,CAAC,QA8BvB,CAAA;AAED,eAAO,MAAM,iBAAiB,GAC5B,SAAS,MAAM,EAAE,YAAK,EACtB,OAAO,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EACrD,OAAO,IAAI,8BAcZ,CAAA;AAED,eAAO,MAAM,sBAAsB,GACjC,UAAS,MAAM,EAAO,EACtB,OAAO,IAAI,KACV,UAAU,GAAG,IAaf,CAAA;AAED,eAAO,MAAM,4BAA4B,GACvC,UAAU,mBAAmB,EAC7B,OAAO,MAAM,CACX,MAAM,EACN;IACE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,KAAK,CAAC,EAAE,IAAI,EAAE,CAAA;CACf,CACF,EACD,MAAM,IAAI,EACV,gBAAgB,MAAM,EACtB,UAAU;IACR,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B,KACA,mBA6GF,CAAA;AAED,eAAO,MAAM,kBAAkB,GAC7B,OAAO,KAAK,EACZ,gBAAgB,MAAM,EACtB,WAAW,eAAe,SAM3B,CAAA;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,aAAa,CAAC,QAAQ,CAAC,EAAE;;;;;;;;iBA2HwvrS,CAAC;sBAAgC,CAAC;2BAAsC,CAAC;;;;IAnH/3rS;AAED,eAAO,MAAM,0BAA0B,GAAI,UAAU,QAAQ,EAAE,aAgC9D,CAAA;AAYD,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,mBAAmB,QA+BvE;AAED,wBAAgB,8BAA8B,CAAC,WAAW,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,IAAI,EAAE,CAAA;CAAE,YAK9E;AAyBD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,EAAE,uBAKtF"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/services/mongodb-atlas/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAElC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,SAAS,CAAA;AACvE,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AACtC,OAAO,EACL,mBAAmB,EAEnB,MAAM,EAEN,UAAU,EACV,KAAK,EAGN,MAAM,gCAAgC,CAAA;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,6BAA6B,CAAA;AAGlD,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAE7D,eAAO,MAAM,YAAY,GAAI,CAAC,SAAS,IAAI,GAAG,MAAM,EAAE,2BAInD,kBAAkB,CAAC,CAAC,CAAC,QA8BvB,CAAA;AAED,eAAO,MAAM,iBAAiB,GAC5B,UAAS,MAAM,EAAO,EACtB,QAAQ,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EACtD,OAAO,IAAI,8BAcZ,CAAA;AAED,eAAO,MAAM,sBAAsB,GACjC,UAAS,MAAM,EAAO,EACtB,OAAO,IAAI,KACV,UAAU,GAAG,IAaf,CAAA;AAED,eAAO,MAAM,4BAA4B,GACvC,UAAU,mBAAmB,EAC7B,OAAO,MAAM,CACX,MAAM,EACN;IACE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,KAAK,CAAC,EAAE,IAAI,EAAE,CAAA;CACf,CACF,EACD,MAAM,IAAI,EACV,gBAAgB,MAAM,EACtB,UAAU;IACR,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B,KACA,mBA6GF,CAAA;AAED,eAAO,MAAM,kBAAkB,GAC7B,OAAO,KAAK,EACZ,gBAAgB,MAAM,EACtB,WAAW,eAAe,SAM3B,CAAA;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,aAAa,CAAC,QAAQ,CAAC,EAAE;;;;;;;;iBA2HuvrS,CAAC;sBAAgC,CAAC;2BAAsC,CAAC;;;;IAnH93rS;AAED,eAAO,MAAM,0BAA0B,GAAI,UAAU,QAAQ,EAAE,aAgC9D,CAAA;AAYD,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,mBAAmB,QA+BvE;AAED,wBAAgB,8BAA8B,CAAC,WAAW,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,IAAI,EAAE,CAAA;CAAE,YAK9E;AAyBD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,EAAE,uBAKtF"}
@@ -36,7 +36,7 @@ exports.hashPassword = hashPassword;
36
36
  const comparePassword = (plaintext, storedPassword) => __awaiter(void 0, void 0, void 0, function* () {
37
37
  const [storedHash, storedSalt] = storedPassword.split('.');
38
38
  if (!storedHash || !storedSalt) {
39
- throw new Error(`Invalid stored password: ${storedPassword}`);
39
+ throw new Error('Invalid credentials');
40
40
  }
41
41
  const storedBuffer = Buffer.from(storedHash, 'hex');
42
42
  const buffer = (yield scrypt(plaintext, storedSalt, 64));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowerforce/flowerbase",
3
- "version": "1.3.1-beta.2",
3
+ "version": "1.3.1-beta.4",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,5 +1,6 @@
1
1
  import fs from 'fs'
2
2
  import path from 'node:path'
3
+ import { Document } from 'mongodb'
3
4
  import { EJSON } from 'bson'
4
5
  import { GetOperatorsFunction } from '../../services/mongodb-atlas/model'
5
6
  import { ExecuteQueryParams, Functions } from './interface'
@@ -65,15 +66,33 @@ export const executeQuery = async ({
65
66
  : typeof returnNewDocument === 'boolean'
66
67
  ? { returnDocument: returnNewDocument ? 'after' : 'before' }
67
68
  : undefined
69
+ const parsedOptions = resolvedOptions ? EJSON.deserialize(resolvedOptions) : undefined
68
70
  return {
69
71
  find: async () =>
70
- await (currentMethod as ReturnType<GetOperatorsFunction>['find'])(
71
- EJSON.deserialize(resolvedQuery)
72
- ).toArray(),
72
+ await (() => {
73
+ const cursor = (currentMethod as ReturnType<GetOperatorsFunction>['find'])(
74
+ EJSON.deserialize(resolvedQuery)
75
+ )
76
+ if (parsedOptions?.sort) {
77
+ cursor.sort(parsedOptions.sort as Document)
78
+ }
79
+ if (typeof parsedOptions?.skip === 'number') {
80
+ cursor.skip(parsedOptions.skip)
81
+ }
82
+ if (typeof parsedOptions?.limit === 'number') {
83
+ cursor.limit(parsedOptions.limit)
84
+ }
85
+ return cursor.toArray()
86
+ })(),
73
87
  findOne: () =>
74
88
  (currentMethod as ReturnType<GetOperatorsFunction>['findOne'])(
75
89
  EJSON.deserialize(resolvedQuery)
76
90
  ),
91
+ count: () =>
92
+ (currentMethod as ReturnType<GetOperatorsFunction>['count'])(
93
+ EJSON.deserialize(resolvedQuery),
94
+ parsedOptions
95
+ ),
77
96
  deleteOne: () =>
78
97
  (currentMethod as ReturnType<GetOperatorsFunction>['deleteOne'])(
79
98
  EJSON.deserialize(resolvedQuery)
@@ -87,7 +106,7 @@ export const executeQuery = async ({
87
106
  (currentMethod as ReturnType<GetOperatorsFunction>['findOneAndUpdate'])(
88
107
  EJSON.deserialize(resolvedQuery),
89
108
  EJSON.deserialize(resolvedUpdate),
90
- resolvedOptions ? EJSON.deserialize(resolvedOptions) : undefined
109
+ parsedOptions
91
110
  ),
92
111
  aggregate: async () =>
93
112
  (await (currentMethod as ReturnType<GetOperatorsFunction>['aggregate'])(
@@ -0,0 +1,87 @@
1
+ import MongoDbAtlas from '..'
2
+ import { Rules } from '../../../features/rules/interface'
3
+
4
+ const createAppWithCollection = (collection: Record<string, unknown>) => ({
5
+ mongo: {
6
+ client: {
7
+ db: jest.fn().mockReturnValue({
8
+ collection: jest.fn().mockReturnValue(collection)
9
+ })
10
+ }
11
+ }
12
+ })
13
+
14
+ const createRules = (overrides?: Partial<Rules[keyof Rules]>): Rules => ({
15
+ todos: {
16
+ database: 'db',
17
+ collection: 'todos',
18
+ filters: overrides?.filters ?? [],
19
+ roles: overrides?.roles ?? [
20
+ {
21
+ name: 'reader',
22
+ apply_when: {},
23
+ insert: true,
24
+ delete: true,
25
+ search: true,
26
+ read: true,
27
+ write: true
28
+ }
29
+ ],
30
+ ...overrides
31
+ }
32
+ })
33
+
34
+ describe('mongodb-atlas count', () => {
35
+ it('applies formatted query for RBAC before counting', async () => {
36
+ const countDocuments = jest.fn().mockResolvedValue(7)
37
+ const collection = {
38
+ collectionName: 'todos',
39
+ countDocuments
40
+ }
41
+
42
+ const rules = {
43
+ filters: [
44
+ {
45
+ name: 'ownerFilter',
46
+ query: { ownerId: 'user-1' },
47
+ apply_when: {}
48
+ }
49
+ ]
50
+ }
51
+
52
+ const operators = MongoDbAtlas(createAppWithCollection(collection) as any, {
53
+ rules: createRules(rules),
54
+ user: { id: 'user-1' }
55
+ })
56
+ .db('db')
57
+ .collection('todos')
58
+
59
+ const result = await operators.count({ workspace: 'workspace-1' })
60
+
61
+ expect(result).toBe(7)
62
+ expect(countDocuments).toHaveBeenCalledWith(
63
+ { $and: [{ ownerId: 'user-1' }, { workspace: 'workspace-1' }] },
64
+ undefined
65
+ )
66
+ })
67
+
68
+ it('delegates directly when running as system', async () => {
69
+ const countDocuments = jest.fn().mockResolvedValue(42)
70
+ const collection = {
71
+ collectionName: 'todos',
72
+ countDocuments
73
+ }
74
+
75
+ const operators = MongoDbAtlas(createAppWithCollection(collection) as any, {
76
+ run_as_system: true
77
+ })
78
+ .db('db')
79
+ .collection('todos')
80
+
81
+ const options = { maxTimeMS: 500 }
82
+ const result = await operators.count({ workspace: 'workspace-2' }, options)
83
+
84
+ expect(result).toBe(42)
85
+ expect(countDocuments).toHaveBeenCalledWith({ workspace: 'workspace-2' }, options)
86
+ })
87
+ })
@@ -473,6 +473,17 @@ const getOperators: GetOperatorsFunction = (
473
473
  // System mode: return original unfiltered cursor
474
474
  return collection.find(query)
475
475
  },
476
+ count: (query, options) => {
477
+ if (!run_as_system) {
478
+ checkDenyOperation(normalizedRules, collection.collectionName, CRUD_OPERATIONS.READ)
479
+ const formattedQuery = getFormattedQuery(filters, query, user)
480
+ const currentQuery = formattedQuery.length ? { $and: formattedQuery } : {}
481
+ logService('count query', { collName, currentQuery })
482
+ return collection.countDocuments(currentQuery, options)
483
+ }
484
+
485
+ return collection.countDocuments(query, options)
486
+ },
476
487
  /**
477
488
  * Watches changes on a MongoDB collection with optional role-based filtering of change events.
478
489
  *
@@ -64,6 +64,9 @@ export type GetOperatorsFunction = (
64
64
  options?: FindOneAndUpdateOptions
65
65
  ) => Promise<Document | null>
66
66
  find: (...params: Parameters<Method<'find'>>) => FindCursor
67
+ count: (
68
+ ...params: Parameters<Method<'countDocuments'>>
69
+ ) => ReturnType<Method<'countDocuments'>>
67
70
  watch: (...params: Parameters<Method<'watch'>>) => ReturnType<Method<'watch'>>
68
71
  aggregate: (
69
72
  ...params: [...Parameters<Method<'aggregate'>>, isClient: boolean]
@@ -55,7 +55,7 @@ export const getValidRule = <T extends Role | Filter>({
55
55
 
56
56
  export const getFormattedQuery = (
57
57
  filters: Filter[] = [],
58
- query: Parameters<Collection<Document>['findOne']>[0],
58
+ query?: Parameters<Collection<Document>['findOne']>[0],
59
59
  user?: User
60
60
  ) => {
61
61
  const preFilter = getValidRule({ filters, user })
@@ -24,7 +24,7 @@ export const comparePassword = async (plaintext: string, storedPassword: string)
24
24
  const [storedHash, storedSalt] = storedPassword.split('.')
25
25
 
26
26
  if (!storedHash || !storedSalt) {
27
- throw new Error(`Invalid stored password: ${storedPassword}`);
27
+ throw new Error('Invalid credentials');
28
28
  }
29
29
 
30
30
  const storedBuffer = Buffer.from(storedHash, 'hex')