@flowerforce/flowerbase 1.8.4-beta.3 → 1.8.4-beta.5

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 (39) hide show
  1. package/README.md +3 -0
  2. package/dist/auth/plugins/jwt.d.ts +1 -1
  3. package/dist/auth/plugins/jwt.d.ts.map +1 -1
  4. package/dist/features/functions/controller.d.ts.map +1 -1
  5. package/dist/features/functions/controller.js +29 -2
  6. package/dist/features/functions/dtos.d.ts +2 -0
  7. package/dist/features/functions/dtos.d.ts.map +1 -1
  8. package/dist/features/functions/interface.d.ts +2 -0
  9. package/dist/features/functions/interface.d.ts.map +1 -1
  10. package/dist/features/functions/utils.d.ts +3 -1
  11. package/dist/features/functions/utils.d.ts.map +1 -1
  12. package/dist/features/functions/utils.js +3 -1
  13. package/dist/services/index.d.ts +8 -8
  14. package/dist/services/mongodb-atlas/index.d.ts.map +1 -1
  15. package/dist/services/mongodb-atlas/index.js +112 -29
  16. package/dist/services/mongodb-atlas/model.d.ts +2 -0
  17. package/dist/services/mongodb-atlas/model.d.ts.map +1 -1
  18. package/dist/services/mongodb-atlas/utils.d.ts +15 -0
  19. package/dist/services/mongodb-atlas/utils.d.ts.map +1 -1
  20. package/dist/services/mongodb-atlas/utils.js +74 -12
  21. package/dist/utils/context/helpers.d.ts +24 -24
  22. package/dist/utils/roles/machines/read/D/validators.d.ts +1 -1
  23. package/dist/utils/roles/machines/read/D/validators.d.ts.map +1 -1
  24. package/dist/utils/roles/machines/write/C/validators.d.ts +1 -1
  25. package/dist/utils/roles/machines/write/C/validators.d.ts.map +1 -1
  26. package/package.json +1 -1
  27. package/src/features/functions/__tests__/controller.test.ts +42 -2
  28. package/src/features/functions/__tests__/utils.test.ts +44 -0
  29. package/src/features/functions/controller.ts +36 -1
  30. package/src/features/functions/dtos.ts +2 -0
  31. package/src/features/functions/interface.ts +2 -0
  32. package/src/features/functions/utils.ts +13 -0
  33. package/src/services/mongodb-atlas/__tests__/realmCompatibility.test.ts +116 -0
  34. package/src/services/mongodb-atlas/__tests__/utils.test.ts +86 -1
  35. package/src/services/mongodb-atlas/index.ts +164 -44
  36. package/src/services/mongodb-atlas/model.ts +8 -0
  37. package/src/services/mongodb-atlas/utils.ts +81 -12
  38. package/tsconfig.json +0 -5
  39. package/tsconfig.spec.json +2 -1
package/README.md CHANGED
@@ -652,6 +652,7 @@ const todos = user.mongoClient('mongodb-atlas')
652
652
 
653
653
  await todos.insertOne({ title: 'Ship docs update', done: false })
654
654
  const openTodos = await todos.find({ done: false })
655
+ const labels = await todos.distinct('label', { done: false })
655
656
  ```
656
657
 
657
658
  `@flowerforce/flowerbase-client` supports:
@@ -661,6 +662,8 @@ const openTodos = await todos.find({ done: false })
661
662
  - change streams with `watch()` async iterator
662
663
  - BSON/EJSON interoperability (`ObjectId`, `Date`, etc.)
663
664
 
665
+ `bulkWrite()` is available on the MongoDB Atlas wrapper only for privileged functions executed with `run_as_system: true`. Regular client-scoped calls continue to use the per-operation methods (`insertOne`, `updateOne`, `updateMany`, `deleteOne`, `deleteMany`, `insertMany`).
666
+
664
667
  ## 💡 Use Cases by Feature
665
668
 
666
669
  ### 🔐 Authentication
@@ -9,6 +9,6 @@ type Options = {
9
9
  * @param {Object} opts - Options for the plugin.
10
10
  * @param {string} opts.secret - The secret key used for signing JWTs.
11
11
  */
12
- declare const _default: (fastify: import("fastify/fastify").FastifyInstance<import("fastify/fastify").RawServerDefault, import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>, import("fastify/fastify").FastifyBaseLogger, import("fastify/fastify").FastifyTypeProviderDefault>, opts: Options) => Promise<void>;
12
+ declare const _default: (fastify: import("fastify").FastifyInstance<import("fastify").RawServerDefault, import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>, import("fastify").FastifyBaseLogger, import("fastify").FastifyTypeProviderDefault>, opts: Options) => Promise<void>;
13
13
  export default _default;
14
14
  //# sourceMappingURL=jwt.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../../src/auth/plugins/jwt.ts"],"names":[],"mappings":"AAKA,KAAK,OAAO,GAAG;IACb,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAkBD;;;;;;;GAOG;iUAC8C,OAAO;AAAxD,wBA4GE"}
1
+ {"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../../src/auth/plugins/jwt.ts"],"names":[],"mappings":"AAKA,KAAK,OAAO,GAAG;IACb,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAkBD;;;;;;;GAOG;iSAC8C,OAAO;AAAxD,wBA4GE"}
@@ -1 +1 @@
1
- {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../src/features/functions/controller.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAKvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAmHhD,eAAO,MAAM,iCAAiC,GAAI,OAAO,OAAO,KAAG,OA0BlE,CAAA;AAID,eAAO,MAAM,6BAA6B,GAAI,OAAO,OAAO,KAAG,OAgD9D,CAAA;AAqHD,eAAO,MAAM,oCAAoC,GAAI,QAAQ,QAAQ,YAClC,CAAA;AAEnC;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,EAAE,kBA0RjC,CAAA"}
1
+ {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../src/features/functions/controller.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAKvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AA0IhD,eAAO,MAAM,iCAAiC,GAAI,OAAO,OAAO,KAAG,OA0BlE,CAAA;AAID,eAAO,MAAM,6BAA6B,GAAI,OAAO,OAAO,KAAG,OAgD9D,CAAA;AAqHD,eAAO,MAAM,oCAAoC,GAAI,QAAQ,QAAQ,YAClC,CAAA;AAEnC;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,EAAE,kBAsSjC,CAAA"}
@@ -26,6 +26,24 @@ const constants_1 = require("../../constants");
26
26
  const services_1 = require("../../services");
27
27
  const context_1 = require("../../utils/context");
28
28
  const utils_1 = require("./utils");
29
+ const SUPPORTED_QUERY_METHODS = [
30
+ 'find',
31
+ 'findOne',
32
+ 'count',
33
+ 'countDocuments',
34
+ 'distinct',
35
+ 'deleteOne',
36
+ 'insertOne',
37
+ 'updateOne',
38
+ 'findOneAndUpdate',
39
+ 'aggregate',
40
+ 'insertMany',
41
+ 'bulkWrite',
42
+ 'updateMany',
43
+ 'deleteMany'
44
+ ];
45
+ const isSupportedQueryMethod = (value) => typeof value === 'string' &&
46
+ SUPPORTED_QUERY_METHODS.includes(value);
29
47
  const normalizeUser = (payload) => {
30
48
  var _a, _b, _c, _d, _e, _f;
31
49
  if (!payload)
@@ -290,7 +308,10 @@ const functionsController = (app_1, _a) => __awaiter(void 0, [app_1, _a], void 0
290
308
  if (!serviceFn) {
291
309
  throw new Error(`Service "${req.body.service}" does not exist`);
292
310
  }
293
- const [{ database, collection, query, filter, update, projection, options, returnNewDocument, document, documents, pipeline = [] }] = args;
311
+ const [{ database, collection, key, query, filter, update, projection, options, returnNewDocument, document, documents, operations, pipeline = [] }] = args;
312
+ if (!isSupportedQueryMethod(method)) {
313
+ throw new Error(`Unsupported service method "${String(method)}"`);
314
+ }
294
315
  const currentMethod = serviceFn(app, { rules, user })
295
316
  .db(database)
296
317
  .collection(collection)[method];
@@ -298,6 +319,7 @@ const functionsController = (app_1, _a) => __awaiter(void 0, [app_1, _a], void 0
298
319
  const operatorsByType = yield (0, utils_1.executeQuery)({
299
320
  currentMethod,
300
321
  query,
322
+ key,
301
323
  filter,
302
324
  update,
303
325
  projection,
@@ -305,10 +327,15 @@ const functionsController = (app_1, _a) => __awaiter(void 0, [app_1, _a], void 0
305
327
  returnNewDocument,
306
328
  document,
307
329
  documents,
330
+ operations,
308
331
  pipeline,
309
332
  isClient: true
310
333
  });
311
- const serviceResult = yield operatorsByType[method]();
334
+ const operator = operatorsByType[method];
335
+ if (typeof operator !== 'function') {
336
+ throw new Error(`Unsupported service method "${method}"`);
337
+ }
338
+ const serviceResult = yield operator();
312
339
  res.type('application/json');
313
340
  return serializeEjson(serviceResult);
314
341
  }
@@ -17,6 +17,7 @@ export type FunctionCallBase64Dto = {
17
17
  type ArgumentsData = Arguments<{
18
18
  database: string;
19
19
  collection: string;
20
+ key?: string;
20
21
  filter?: Document;
21
22
  query: Parameters<GetOperatorsFunction>;
22
23
  update: Document;
@@ -25,6 +26,7 @@ type ArgumentsData = Arguments<{
25
26
  returnNewDocument?: boolean;
26
27
  document: Document;
27
28
  documents: Document[];
29
+ operations?: Document[];
28
30
  pipeline?: Document[];
29
31
  }>;
30
32
  export type Base64Function = {
@@ -1 +1 @@
1
- {"version":3,"file":"dtos.d.ts","sourceRoot":"","sources":["../../../src/features/functions/dtos.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAA;AAEzE,KAAK,UAAU,GAAG,OAAO,CAAC,MAAM,UAAU,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC,CAAA;AAE1E,MAAM,MAAM,eAAe,GACvB;IACA,IAAI,EAAE,UAAU,CAAA;IAChB,SAAS,EAAE,aAAa,CAAA;CACzB,GACC;IACA,SAAS,EAAE,aAAa,CAAA;IACxB,IAAI,EAAE,UAAU,CAAA;IAChB,OAAO,EAAE,eAAe,CAAA;CACzB,CAAA;AAEH,MAAM,MAAM,qBAAqB,GAAG;IAClC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,KAAK,aAAa,GAAG,SAAS,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,QAAQ,CAAA;IACjB,KAAK,EAAE,UAAU,CAAC,oBAAoB,CAAC,CAAA;IACvC,MAAM,EAAE,QAAQ,CAAA;IAChB,UAAU,CAAC,EAAE,QAAQ,CAAA;IACrB,OAAO,CAAC,EAAE,QAAQ,CAAA;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,QAAQ,EAAE,QAAQ,CAAA;IAClB,SAAS,EAAE,QAAQ,EAAE,CAAA;IACrB,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAA;CACtB,CAAC,CAAA;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,QAAQ,EAAE,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,KAAK,QAAQ,GAAG;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA"}
1
+ {"version":3,"file":"dtos.d.ts","sourceRoot":"","sources":["../../../src/features/functions/dtos.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAA;AAEzE,KAAK,UAAU,GAAG,OAAO,CAAC,MAAM,UAAU,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC,CAAA;AAE1E,MAAM,MAAM,eAAe,GACvB;IACA,IAAI,EAAE,UAAU,CAAA;IAChB,SAAS,EAAE,aAAa,CAAA;CACzB,GACC;IACA,SAAS,EAAE,aAAa,CAAA;IACxB,IAAI,EAAE,UAAU,CAAA;IAChB,OAAO,EAAE,eAAe,CAAA;CACzB,CAAA;AAEH,MAAM,MAAM,qBAAqB,GAAG;IAClC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,KAAK,aAAa,GAAG,SAAS,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,QAAQ,CAAA;IACjB,KAAK,EAAE,UAAU,CAAC,oBAAoB,CAAC,CAAA;IACvC,MAAM,EAAE,QAAQ,CAAA;IAChB,UAAU,CAAC,EAAE,QAAQ,CAAA;IACrB,OAAO,CAAC,EAAE,QAAQ,CAAA;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,QAAQ,EAAE,QAAQ,CAAA;IAClB,SAAS,EAAE,QAAQ,EAAE,CAAA;IACrB,UAAU,CAAC,EAAE,QAAQ,EAAE,CAAA;IACvB,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAA;CACtB,CAAC,CAAA;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,QAAQ,EAAE,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,KAAK,QAAQ,GAAG;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA"}
@@ -22,12 +22,14 @@ export type ExecuteQueryParams = {
22
22
  currentMethod: ReturnType<GetOperatorsFunction>[keyof ReturnType<GetOperatorsFunction>];
23
23
  query: Parameters<GetOperatorsFunction>;
24
24
  update: Document;
25
+ key?: string;
25
26
  filter?: Document;
26
27
  projection?: Document;
27
28
  options?: Document;
28
29
  returnNewDocument?: boolean;
29
30
  document: Document;
30
31
  documents: Document[];
32
+ operations?: Document[];
31
33
  pipeline: Document[];
32
34
  isClient?: boolean;
33
35
  };
@@ -1 +1 @@
1
- {"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../../src/features/functions/interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAClC,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAA;AACzE,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAE1C,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED,MAAM,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,GAAG;IACpD,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;AAEhD,MAAM,MAAM,uBAAuB,GAAG;IACpC,GAAG,EAAE,eAAe,CAAA;IACpB,aAAa,EAAE,SAAS,CAAA;IACxB,SAAS,EAAE,KAAK,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,aAAa,EAAE,UAAU,CAAC,oBAAoB,CAAC,CAAC,MAAM,UAAU,CAAC,oBAAoB,CAAC,CAAC,CAAA;IACvF,KAAK,EAAE,UAAU,CAAC,oBAAoB,CAAC,CAAA;IACvC,MAAM,EAAE,QAAQ,CAAA;IAChB,MAAM,CAAC,EAAE,QAAQ,CAAA;IACjB,UAAU,CAAC,EAAE,QAAQ,CAAA;IACrB,OAAO,CAAC,EAAE,QAAQ,CAAA;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,QAAQ,EAAE,QAAQ,CAAA;IAClB,SAAS,EAAE,QAAQ,EAAE,CAAA;IACrB,QAAQ,EAAE,QAAQ,EAAE,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,KAAK,0BAA0B,GAAG;IAChC,aAAa,EAAE,SAAS,CAAA;IACxB,KAAK,EAAE,KAAK,CAAA;CACb,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG,CAC/B,GAAG,EAAE,eAAe,EACpB,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE,0BAA0B,KACjD,OAAO,CAAC,IAAI,CAAC,CAAA"}
1
+ {"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../../src/features/functions/interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAClC,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAA;AACzE,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAE1C,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED,MAAM,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,GAAG;IACpD,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;AAEhD,MAAM,MAAM,uBAAuB,GAAG;IACpC,GAAG,EAAE,eAAe,CAAA;IACpB,aAAa,EAAE,SAAS,CAAA;IACxB,SAAS,EAAE,KAAK,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,aAAa,EAAE,UAAU,CAAC,oBAAoB,CAAC,CAAC,MAAM,UAAU,CAAC,oBAAoB,CAAC,CAAC,CAAA;IACvF,KAAK,EAAE,UAAU,CAAC,oBAAoB,CAAC,CAAA;IACvC,MAAM,EAAE,QAAQ,CAAA;IAChB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,QAAQ,CAAA;IACjB,UAAU,CAAC,EAAE,QAAQ,CAAA;IACrB,OAAO,CAAC,EAAE,QAAQ,CAAA;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,QAAQ,EAAE,QAAQ,CAAA;IAClB,SAAS,EAAE,QAAQ,EAAE,CAAA;IACrB,UAAU,CAAC,EAAE,QAAQ,EAAE,CAAA;IACvB,QAAQ,EAAE,QAAQ,EAAE,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,KAAK,0BAA0B,GAAG;IAChC,aAAa,EAAE,SAAS,CAAA;IACxB,KAAK,EAAE,KAAK,CAAA;CACb,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG,CAC/B,GAAG,EAAE,eAAe,EACpB,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE,0BAA0B,KACjD,OAAO,CAAC,IAAI,CAAC,CAAA"}
@@ -11,17 +11,19 @@ export declare const loadFunctions: (rootDir?: string) => Promise<Functions>;
11
11
  * @param query -> the query data
12
12
  * @param update -> the update Document that should be deserialized
13
13
  */
14
- export declare const executeQuery: ({ currentMethod, query, update, filter, projection, options, returnNewDocument, document, documents, pipeline, isClient }: ExecuteQueryParams) => Promise<{
14
+ export declare const executeQuery: ({ currentMethod, query, update, key, filter, projection, options, returnNewDocument, document, documents, operations, pipeline, isClient }: ExecuteQueryParams) => Promise<{
15
15
  find: () => Promise<any[]>;
16
16
  findOne: () => Promise<unknown>;
17
17
  count: () => Promise<number>;
18
18
  countDocuments: () => Promise<number>;
19
+ distinct: () => Promise<any[]>;
19
20
  deleteOne: () => Promise<import("mongodb").DeleteResult>;
20
21
  insertOne: () => Promise<import("mongodb").InsertOneResult<Document>>;
21
22
  updateOne: () => Promise<import("mongodb").UpdateResult<Document>>;
22
23
  findOneAndUpdate: () => Promise<Document | null>;
23
24
  aggregate: () => Promise<Document[]>;
24
25
  insertMany: () => Promise<import("mongodb").InsertManyResult<Document>>;
26
+ bulkWrite: () => Promise<import("mongodb").BulkWriteResult>;
25
27
  updateMany: () => Promise<import("mongodb").UpdateResult<Document>>;
26
28
  deleteMany: () => Promise<import("mongodb").DeleteResult>;
27
29
  }>;
@@ -1 +1 @@
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,2HAYhC,kBAAkB;;;;;;;;;;;;;EAsGpB,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,4IAchC,kBAAkB;;;;;;;;;;;;;;;EAiHpB,CAAA"}
@@ -58,7 +58,7 @@ exports.loadFunctions = loadFunctions;
58
58
  * @param query -> the query data
59
59
  * @param update -> the update Document that should be deserialized
60
60
  */
61
- const executeQuery = (_a) => __awaiter(void 0, [_a], void 0, function* ({ currentMethod, query, update, filter, projection, options, returnNewDocument, document, documents, pipeline, isClient = false }) {
61
+ const executeQuery = (_a) => __awaiter(void 0, [_a], void 0, function* ({ currentMethod, query, update, key, filter, projection, options, returnNewDocument, document, documents, operations, pipeline, isClient = false }) {
62
62
  const resolvedQuery = typeof query !== 'undefined'
63
63
  ? query
64
64
  : typeof filter !== 'undefined'
@@ -98,6 +98,7 @@ const executeQuery = (_a) => __awaiter(void 0, [_a], void 0, function* ({ curren
98
98
  findOne: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), resolvedProjection, parsedOptions),
99
99
  count: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), parsedOptions),
100
100
  countDocuments: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), parsedOptions),
101
+ distinct: () => currentMethod(key !== null && key !== void 0 ? key : '', bson_1.EJSON.deserialize(resolvedQuery), parsedOptions),
101
102
  deleteOne: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), parsedOptions),
102
103
  insertOne: () => currentMethod(bson_1.EJSON.deserialize(document)),
103
104
  updateOne: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), bson_1.EJSON.deserialize(resolvedUpdate), parsedOptions),
@@ -107,6 +108,7 @@ const executeQuery = (_a) => __awaiter(void 0, [_a], void 0, function* ({ curren
107
108
  isClient)).toArray();
108
109
  }),
109
110
  insertMany: () => currentMethod(bson_1.EJSON.deserialize(documents)),
111
+ bulkWrite: () => currentMethod(bson_1.EJSON.deserialize(operations !== null && operations !== void 0 ? operations : []), parsedOptions),
110
112
  updateMany: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), bson_1.EJSON.deserialize(resolvedUpdate)),
111
113
  deleteMany: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), parsedOptions)
112
114
  };
@@ -126,23 +126,23 @@ export declare const services: {
126
126
  invokedFrom?: string;
127
127
  };
128
128
  }) => {
129
- lambda: (region: string) => import("@aws-sdk/client-lambda/dist-types").Lambda & {
130
- Invoke: (params: import("@aws-sdk/client-lambda/dist-types").InvokeCommandInput) => Promise<Omit<import("@aws-sdk/client-lambda/dist-types").InvokeCommandOutput, "Payload"> & {
129
+ lambda: (region: string) => import("@aws-sdk/client-lambda").Lambda & {
130
+ Invoke: (params: import("@aws-sdk/client-lambda").InvokeCommandInput) => Promise<Omit<import("@aws-sdk/client-lambda").InvokeCommandOutput, "Payload"> & {
131
131
  Payload: {
132
132
  text: () => string | undefined;
133
133
  };
134
134
  }>;
135
- InvokeAsync: (params: import("@aws-sdk/client-lambda/dist-types").InvokeAsyncCommandInput) => Promise<import("@aws-sdk/client-lambda/dist-types").InvokeAsyncCommandOutput>;
135
+ InvokeAsync: (params: import("@aws-sdk/client-lambda").InvokeAsyncCommandInput) => Promise<import("@aws-sdk/client-lambda").InvokeAsyncCommandOutput>;
136
136
  };
137
- s3: (region: string) => import("@aws-sdk/client-s3/dist-types").S3Client & {
138
- PutObject: (params: import("@aws-sdk/client-s3/dist-types").PutObjectCommandInput) => Promise<import("@aws-sdk/client-s3/dist-types").PutObjectCommandOutput>;
139
- GetObject: (params: import("@aws-sdk/client-s3/dist-types").GetObjectCommandInput) => Promise<import("@aws-sdk/client-s3/dist-types").GetObjectCommandOutput>;
140
- getSignedUrl: (operation: "getObject" | "putObject", params: (import("@aws-sdk/client-s3/dist-types").GetObjectCommandInput | import("@aws-sdk/client-s3/dist-types").PutObjectCommandInput) & {
137
+ s3: (region: string) => import("@aws-sdk/client-s3").S3Client & {
138
+ PutObject: (params: import("@aws-sdk/client-s3").PutObjectCommandInput) => Promise<import("@aws-sdk/client-s3").PutObjectCommandOutput>;
139
+ GetObject: (params: import("@aws-sdk/client-s3").GetObjectCommandInput) => Promise<import("@aws-sdk/client-s3").GetObjectCommandOutput>;
140
+ getSignedUrl: (operation: "getObject" | "putObject", params: (import("@aws-sdk/client-s3").GetObjectCommandInput | import("@aws-sdk/client-s3").PutObjectCommandInput) & {
141
141
  Expires?: number;
142
142
  }, options?: {
143
143
  expiresIn?: number;
144
144
  }) => Promise<string>;
145
- PresignURL: (params: (import("@aws-sdk/client-s3/dist-types").GetObjectCommandInput | import("@aws-sdk/client-s3/dist-types").PutObjectCommandInput) & {
145
+ PresignURL: (params: (import("@aws-sdk/client-s3").GetObjectCommandInput | import("@aws-sdk/client-s3").PutObjectCommandInput) & {
146
146
  Method?: string;
147
147
  ExpirationMS?: number;
148
148
  Expires?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/mongodb-atlas/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAIL,QAAQ,EAQT,MAAM,SAAS,CAAA;AAOhB,OAAO,EAGL,oBAAoB,EAErB,MAAM,SAAS,CAAA;AA6JhB,eAAO,MAAM,kBAAkB,GAAI,OAAO,OAAO,KAAG,OA0BnD,CAAA;AA8BD,eAAO,MAAM,2BAA2B,GAAI,UAAU,QAAQ,EAAE,YAK5D,CAAA;AAwzCJ,QAAA,MAAM,YAAY,EAAE,oBAwBlB,CAAA;AAEF,eAAe,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/mongodb-atlas/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAIL,QAAQ,EAQT,MAAM,SAAS,CAAA;AAOhB,OAAO,EAGL,oBAAoB,EAErB,MAAM,SAAS,CAAA;AA8JhB,eAAO,MAAM,kBAAkB,GAAI,OAAO,OAAO,KAAG,OA0BnD,CAAA;AA8BD,eAAO,MAAM,2BAA2B,GAAI,UAAU,QAAQ,EAAE,YAK5D,CAAA;AA+6CJ,QAAA,MAAM,YAAY,EAAE,oBAwBlB,CAAA;AAEF,eAAe,YAAY,CAAA"}
@@ -408,6 +408,22 @@ const areUpdatedFieldsAllowed = (filtered, updated, updatedPaths) => {
408
408
  return (0, isEqual_1.default)(filtered, updated);
409
409
  return updatedPaths.every((path) => (0, isEqual_1.default)((0, get_1.default)(filtered, path), (0, get_1.default)(updated, path)));
410
410
  };
411
+ const appendDistinctValue = (values, candidate) => {
412
+ if (typeof candidate === 'undefined')
413
+ return;
414
+ if (!values.some((entry) => (0, isEqual_1.default)(entry, candidate))) {
415
+ values.push(candidate);
416
+ }
417
+ };
418
+ const collectDistinctValues = (documents, key) => documents.reduce((values, document) => {
419
+ const currentValue = (0, get_1.default)(document, key);
420
+ if (Array.isArray(currentValue)) {
421
+ currentValue.forEach((entry) => appendDistinctValue(values, entry));
422
+ return values;
423
+ }
424
+ appendDistinctValue(values, currentValue);
425
+ return values;
426
+ }, []);
411
427
  const getOperators = (mongo, { rules, dbName, collName, user, run_as_system, monitoringOrigin }) => {
412
428
  var _a, _b;
413
429
  const collection = mongo.client.db(dbName).collection(collName);
@@ -437,7 +453,39 @@ const getOperators = (mongo, { rules, dbName, collName, user, run_as_system, mon
437
453
  origin: monitoringOrigin
438
454
  });
439
455
  };
440
- return {
456
+ const validateReadableDocument = (currentDoc) => __awaiter(void 0, void 0, void 0, function* () {
457
+ var _a;
458
+ const winningRole = yield (0, utils_2.getWinningRoleAsync)(currentDoc, user, roles);
459
+ logDebug('find winningRole', {
460
+ collection: collName,
461
+ userId: getUserId(user),
462
+ winningRoleName: (_a = winningRole === null || winningRole === void 0 ? void 0 : winningRole.name) !== null && _a !== void 0 ? _a : null,
463
+ rolesLength: roles.length
464
+ });
465
+ const { status, document } = winningRole
466
+ ? yield (0, machines_1.checkValidation)(winningRole, {
467
+ type: 'read',
468
+ roles,
469
+ cursor: currentDoc,
470
+ expansions: getValidationExpansions(currentDoc)
471
+ }, user)
472
+ : fallbackAccess(currentDoc);
473
+ return status ? document : undefined;
474
+ });
475
+ const getScopedQuery = (query = {}) => {
476
+ const formattedQuery = (0, utils_3.getFormattedQuery)(filters, query, user);
477
+ const currentQuery = formattedQuery.length ? { $and: formattedQuery } : {};
478
+ const safeQuery = Array.isArray(formattedQuery)
479
+ ? (0, utils_3.normalizeQuery)(formattedQuery)
480
+ : formattedQuery;
481
+ return {
482
+ formattedQuery,
483
+ currentQuery,
484
+ safeQuery,
485
+ builtQuery: buildAndQuery(safeQuery)
486
+ };
487
+ };
488
+ const operators = {
441
489
  /**
442
490
  * Finds a single document in a MongoDB collection with optional role-based filtering and validation.
443
491
  *
@@ -459,13 +507,17 @@ const getOperators = (mongo, { rules, dbName, collName, user, run_as_system, mon
459
507
  var _a;
460
508
  try {
461
509
  const { projection, options: normalizedOptions } = resolveFindArgs(projectionOrOptions, options);
462
- const resolvedOptions = projection || normalizedOptions
463
- ? Object.assign(Object.assign({}, (normalizedOptions !== null && normalizedOptions !== void 0 ? normalizedOptions : {})), (projection ? { projection } : {})) : undefined;
464
510
  const resolvedQuery = query !== null && query !== void 0 ? query : {};
465
511
  if (!run_as_system) {
466
512
  (0, utils_3.checkDenyOperation)(normalizedRules, collection.collectionName, model_1.CRUD_OPERATIONS.READ);
467
513
  // Apply access control filters to the query
468
514
  const formattedQuery = (0, utils_3.getFormattedQuery)(filters, resolvedQuery, user);
515
+ // Rules-level projection has priority over client-provided projection.
516
+ // The merged projection is passed natively to MongoDB.
517
+ const rulesProjection = (0, utils_3.getFormattedProjection)(filters, user);
518
+ const finalProjection = (0, utils_3.mergeProjections)(projection, rulesProjection);
519
+ const resolvedOptions = finalProjection || normalizedOptions
520
+ ? Object.assign(Object.assign({}, (normalizedOptions !== null && normalizedOptions !== void 0 ? normalizedOptions : {})), (finalProjection ? { projection: finalProjection } : {})) : undefined;
469
521
  logDebug('update formattedQuery', {
470
522
  collection: collName,
471
523
  query,
@@ -509,8 +561,10 @@ const getOperators = (mongo, { rules, dbName, collName, user, run_as_system, mon
509
561
  emitMongoEvent('findOne');
510
562
  return Promise.resolve(response);
511
563
  }
512
- // System mode: no validation applied
513
- const response = yield collection.findOne(resolvedQuery, resolvedOptions);
564
+ // System mode: no validation applied, only client-provided projection/options.
565
+ const systemOptions = projection || normalizedOptions
566
+ ? Object.assign(Object.assign({}, (normalizedOptions !== null && normalizedOptions !== void 0 ? normalizedOptions : {})), (projection ? { projection } : {})) : undefined;
567
+ const response = yield collection.findOne(resolvedQuery, systemOptions);
514
568
  emitMongoEvent('findOne');
515
569
  return response;
516
570
  }
@@ -825,13 +879,17 @@ const getOperators = (mongo, { rules, dbName, collName, user, run_as_system, mon
825
879
  find: (query = {}, projectionOrOptions, options) => {
826
880
  try {
827
881
  const { projection, options: normalizedOptions } = resolveFindArgs(projectionOrOptions, options);
828
- const resolvedOptions = projection || normalizedOptions
829
- ? Object.assign(Object.assign({}, (normalizedOptions !== null && normalizedOptions !== void 0 ? normalizedOptions : {})), (projection ? { projection } : {})) : undefined;
830
882
  if (!run_as_system) {
831
883
  (0, utils_3.checkDenyOperation)(normalizedRules, collection.collectionName, model_1.CRUD_OPERATIONS.READ);
832
884
  // Pre-query filtering based on access control rules
833
885
  const formattedQuery = (0, utils_3.getFormattedQuery)(filters, query, user);
834
886
  const currentQuery = formattedQuery.length ? { $and: formattedQuery } : {};
887
+ // Rules-level projection has priority over client-provided projection.
888
+ // The merged projection is passed natively to MongoDB.
889
+ const rulesProjection = (0, utils_3.getFormattedProjection)(filters, user);
890
+ const finalProjection = (0, utils_3.mergeProjections)(projection, rulesProjection);
891
+ const resolvedOptions = finalProjection || normalizedOptions
892
+ ? Object.assign(Object.assign({}, (normalizedOptions !== null && normalizedOptions !== void 0 ? normalizedOptions : {})), (finalProjection ? { projection: finalProjection } : {})) : undefined;
835
893
  // aggiunto filter per evitare questo errore: $and argument's entries must be objects
836
894
  const cursor = collection.find(currentQuery, resolvedOptions);
837
895
  const originalToArray = cursor.toArray.bind(cursor);
@@ -842,32 +900,16 @@ const getOperators = (mongo, { rules, dbName, collName, user, run_as_system, mon
842
900
  */
843
901
  cursor.toArray = () => __awaiter(void 0, void 0, void 0, function* () {
844
902
  const response = yield originalToArray();
845
- const filteredResponse = yield Promise.all(response.map((currentDoc) => __awaiter(void 0, void 0, void 0, function* () {
846
- var _a;
847
- const winningRole = yield (0, utils_2.getWinningRoleAsync)(currentDoc, user, roles);
848
- logDebug('find winningRole', {
849
- collection: collName,
850
- userId: getUserId(user),
851
- winningRoleName: (_a = winningRole === null || winningRole === void 0 ? void 0 : winningRole.name) !== null && _a !== void 0 ? _a : null,
852
- rolesLength: roles.length
853
- });
854
- const { status, document } = winningRole
855
- ? yield (0, machines_1.checkValidation)(winningRole, {
856
- type: 'read',
857
- roles,
858
- cursor: currentDoc,
859
- expansions: getValidationExpansions(currentDoc)
860
- }, user)
861
- : fallbackAccess(currentDoc);
862
- return status ? document : undefined;
863
- })));
903
+ const filteredResponse = yield Promise.all(response.map((currentDoc) => validateReadableDocument(currentDoc)));
864
904
  return filteredResponse.filter(Boolean);
865
905
  });
866
906
  emitMongoEvent('find');
867
907
  return cursor;
868
908
  }
869
- // System mode: return original unfiltered cursor
870
- const cursor = collection.find(query, resolvedOptions);
909
+ // System mode: return original unfiltered cursor (only client projection/options).
910
+ const systemOptions = projection || normalizedOptions
911
+ ? Object.assign(Object.assign({}, (normalizedOptions !== null && normalizedOptions !== void 0 ? normalizedOptions : {})), (projection ? { projection } : {})) : undefined;
912
+ const cursor = collection.find(query, systemOptions);
871
913
  emitMongoEvent('find');
872
914
  return cursor;
873
915
  }
@@ -916,6 +958,32 @@ const getOperators = (mongo, { rules, dbName, collName, user, run_as_system, mon
916
958
  throw error;
917
959
  }
918
960
  }),
961
+ distinct: (key_1, ...args_1) => __awaiter(void 0, [key_1, ...args_1], void 0, function* (key, query = {}, options) {
962
+ try {
963
+ if (!key) {
964
+ throw new Error('distinct key is required');
965
+ }
966
+ if (!run_as_system) {
967
+ (0, utils_3.checkDenyOperation)(normalizedRules, collection.collectionName, model_1.CRUD_OPERATIONS.READ);
968
+ const { currentQuery } = getScopedQuery(query);
969
+ const projectedOptions = Object.assign(Object.assign({}, (options !== null && options !== void 0 ? options : {})), { projection: { _id: 1, [key]: 1 } });
970
+ const documents = yield collection.find(currentQuery, projectedOptions).toArray();
971
+ const readableDocuments = (yield Promise.all(documents.map((currentDoc) => validateReadableDocument(currentDoc)))).filter(Boolean);
972
+ const result = collectDistinctValues(readableDocuments, key);
973
+ emitMongoEvent('distinct');
974
+ return result;
975
+ }
976
+ const result = typeof options === 'undefined'
977
+ ? yield collection.distinct(key, query)
978
+ : yield collection.distinct(key, query, options);
979
+ emitMongoEvent('distinct');
980
+ return result;
981
+ }
982
+ catch (error) {
983
+ emitMongoEvent('distinct', undefined, error);
984
+ throw error;
985
+ }
986
+ }),
919
987
  /**
920
988
  * Watches changes on a MongoDB collection with optional role-based filtering of change events.
921
989
  *
@@ -1041,7 +1109,7 @@ const getOperators = (mongo, { rules, dbName, collName, user, run_as_system, mon
1041
1109
  formattedQuery,
1042
1110
  pipeline
1043
1111
  });
1044
- const projection = (0, utils_3.getFormattedProjection)(filters);
1112
+ const projection = (0, utils_3.getFormattedProjection)(filters, user);
1045
1113
  const hiddenFields = (0, utils_3.getHiddenFieldsFromRulesConfig)(rulesConfig);
1046
1114
  const sanitizedPipeline = (0, utils_3.applyAccessControlToPipeline)(pipeline, normalizedRules, user, collName, { isClientPipeline: true });
1047
1115
  logDebug('aggregate sanitizedPipeline', {
@@ -1117,6 +1185,20 @@ const getOperators = (mongo, { rules, dbName, collName, user, run_as_system, mon
1117
1185
  throw error;
1118
1186
  }
1119
1187
  }),
1188
+ bulkWrite: (operations, options) => __awaiter(void 0, void 0, void 0, function* () {
1189
+ try {
1190
+ if (!run_as_system) {
1191
+ throw new Error('bulkWrite is available only when run_as_system is enabled');
1192
+ }
1193
+ const result = yield collection.bulkWrite(operations, options);
1194
+ emitMongoEvent('bulkWrite', { operations: operations.length });
1195
+ return result;
1196
+ }
1197
+ catch (error) {
1198
+ emitMongoEvent('bulkWrite', { operations: Array.isArray(operations) ? operations.length : 0 }, error);
1199
+ throw error;
1200
+ }
1201
+ }),
1120
1202
  updateMany: (query, data, options) => __awaiter(void 0, void 0, void 0, function* () {
1121
1203
  try {
1122
1204
  const normalizedData = normalizeUpdatePayload(data);
@@ -1227,6 +1309,7 @@ const getOperators = (mongo, { rules, dbName, collName, user, run_as_system, mon
1227
1309
  }
1228
1310
  })
1229
1311
  };
1312
+ return operators;
1230
1313
  };
1231
1314
  const MongodbAtlas = (app, { rules, user, run_as_system, monitoring } = {}) => ({
1232
1315
  startSession: (options) => {
@@ -40,6 +40,8 @@ export type GetOperatorsFunction = (mongoInstance: FastifyInstance["mongo"], { r
40
40
  countDocuments: (...params: Parameters<Method<'countDocuments'>>) => ReturnType<Method<'countDocuments'>>;
41
41
  watch: (...params: Parameters<Method<'watch'>>) => ReturnType<Method<'watch'>>;
42
42
  aggregate: (...params: [...Parameters<Method<'aggregate'>>, isClient: boolean]) => ReturnType<Method<'aggregate'>>;
43
+ distinct: (key: Parameters<Method<'distinct'>>[0], filter?: Parameters<Method<'distinct'>>[1], options?: Parameters<Method<'distinct'>>[2]) => ReturnType<Method<'distinct'>>;
44
+ bulkWrite: (...params: Parameters<Method<'bulkWrite'>>) => ReturnType<Method<'bulkWrite'>>;
43
45
  insertMany: (...params: Parameters<Method<'insertMany'>>) => ReturnType<Method<'insertMany'>>;
44
46
  updateMany: (...params: Parameters<Method<'updateMany'>>) => ReturnType<Method<'updateMany'>>;
45
47
  deleteMany: (...params: Parameters<Method<'deleteMany'>>) => ReturnType<Method<'deleteMany'>>;
@@ -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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"}
@@ -7,6 +7,21 @@ import { CRUD_OPERATIONS, GetValidRuleParams } from './model';
7
7
  export declare const getValidRule: <T extends Role | Filter>({ filters, user, record }: GetValidRuleParams<T>) => T[];
8
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
+ /**
11
+ * Merges a client-provided projection with the one computed from rules filters.
12
+ *
13
+ * Rules have higher priority over the client:
14
+ * - If rules exclude a top-level field (e.g. `{ instock: 0 }`), every client
15
+ * reference to that field — including dotted sub-paths such as
16
+ * `"instock.qty": 1` — is dropped from the final projection.
17
+ * - If rules include a field (value `1`), it is always part of the final
18
+ * projection and overrides any conflicting client value.
19
+ * - The returned projection is always a valid MongoDB projection (no mixing of
20
+ * inclusion and exclusion on non-`_id` keys), so it can be passed as-is to
21
+ * native MongoDB methods.
22
+ * - Returns `undefined` when neither side provided a meaningful projection.
23
+ */
24
+ export declare const mergeProjections: (clientProjection: Projection | Document | undefined, rulesProjection: Projection | null | undefined) => Projection | Document | undefined;
10
25
  export declare const applyAccessControlToPipeline: (pipeline: AggregationPipeline, rules: Record<string, {
11
26
  filters?: Filter[];
12
27
  roles?: Role[];
@@ -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,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;;;;;;;;iBA0I8iqS,CAAC;sBAAgC,CAAC;2BAAsC,CAAC;;;;IAlIrrqS;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;AAwCD,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,IAMf,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,gBAAgB,GAC3B,kBAAkB,UAAU,GAAG,QAAQ,GAAG,SAAS,EACnD,iBAAiB,UAAU,GAAG,IAAI,GAAG,SAAS,KAC7C,UAAU,GAAG,QAAQ,GAAG,SAyD1B,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;;;;;;;;iBA0I2jkS,CAAC;sBAAgC,CAAC;2BAAsC,CAAC;;;;IAlIlskS;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;AAwCD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,EAAE,uBAKtF"}