@flowerforce/flowerbase 1.4.2-beta.4 → 1.4.2-beta.6

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 +1 @@
1
- {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../src/features/functions/controller.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AA2ChD;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,EAAE,kBAwJjC,CAAA"}
1
+ {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../src/features/functions/controller.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AA2ChD;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,EAAE,kBA0JjC,CAAA"}
@@ -67,7 +67,7 @@ const functionsController = (app_1, _a) => __awaiter(void 0, [app_1, _a], void 0
67
67
  if (!serviceFn) {
68
68
  throw new Error(`Service "${req.body.service}" does not exist`);
69
69
  }
70
- const [{ database, collection, query, filter, update, options, returnNewDocument, document, documents, pipeline = [] }] = args;
70
+ const [{ database, collection, query, filter, update, projection, options, returnNewDocument, document, documents, pipeline = [] }] = args;
71
71
  const currentMethod = serviceFn(app, { rules, user })
72
72
  .db(database)
73
73
  .collection(collection)[method];
@@ -77,6 +77,7 @@ const functionsController = (app_1, _a) => __awaiter(void 0, [app_1, _a], void 0
77
77
  query,
78
78
  filter,
79
79
  update,
80
+ projection,
80
81
  options,
81
82
  returnNewDocument,
82
83
  document,
@@ -112,7 +113,7 @@ const functionsController = (app_1, _a) => __awaiter(void 0, [app_1, _a], void 0
112
113
  return JSON.stringify(result);
113
114
  }
114
115
  catch (error) {
115
- res.status(500);
116
+ res.status(400);
116
117
  res.type('application/json');
117
118
  return JSON.stringify({
118
119
  error: formatFunctionExecutionError(error),
@@ -20,6 +20,7 @@ type ArgumentsData = Arguments<{
20
20
  filter?: Document;
21
21
  query: Parameters<GetOperatorsFunction>;
22
22
  update: Document;
23
+ projection?: Document;
23
24
  options?: Document;
24
25
  returnNewDocument?: boolean;
25
26
  document: Document;
@@ -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,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,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"}
@@ -22,6 +22,7 @@ export type ExecuteQueryParams = {
22
22
  query: Parameters<GetOperatorsFunction>;
23
23
  update: Document;
24
24
  filter?: Document;
25
+ projection?: Document;
25
26
  options?: Document;
26
27
  returnNewDocument?: boolean;
27
28
  document: Document;
@@ -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;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAEtE,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,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;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAEtE,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"}
@@ -11,11 +11,11 @@ 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, options, returnNewDocument, document, documents, pipeline, isClient }: ExecuteQueryParams) => Promise<{
14
+ export declare const executeQuery: ({ currentMethod, query, update, filter, projection, options, returnNewDocument, document, documents, pipeline, isClient }: ExecuteQueryParams) => Promise<{
15
15
  find: () => Promise<any[]>;
16
16
  findOne: () => Promise<unknown>;
17
17
  count: () => Promise<number>;
18
- deleteOne: () => Promise<unknown>;
18
+ deleteOne: () => Promise<import("mongodb").DeleteResult>;
19
19
  insertOne: () => Promise<import("mongodb").InsertOneResult<Document>>;
20
20
  updateOne: () => Promise<unknown> | import("mongodb").FindCursor<any> | import("mongodb").ChangeStream<Document, Document> | import("mongodb").AggregationCursor<Document>;
21
21
  findOneAndUpdate: () => Promise<Document | null>;
@@ -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,+GAWhC,kBAAkB;;;;;;;;;;;;EA4EpB,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,2HAYhC,kBAAkB;;;;;;;;;;;;EA4FpB,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, options, returnNewDocument, document, documents, pipeline, isClient = false }) {
61
+ const executeQuery = (_a) => __awaiter(void 0, [_a], void 0, function* ({ currentMethod, query, update, filter, projection, options, returnNewDocument, document, documents, pipeline, isClient = false }) {
62
62
  const resolvedQuery = typeof query !== 'undefined'
63
63
  ? query
64
64
  : typeof filter !== 'undefined'
@@ -71,10 +71,18 @@ const executeQuery = (_a) => __awaiter(void 0, [_a], void 0, function* ({ curren
71
71
  ? { returnDocument: returnNewDocument ? 'after' : 'before' }
72
72
  : undefined;
73
73
  const parsedOptions = resolvedOptions ? bson_1.EJSON.deserialize(resolvedOptions) : undefined;
74
+ const parsedProjection = typeof projection !== 'undefined' ? bson_1.EJSON.deserialize(projection) : undefined;
75
+ const resolvedProjection = typeof projection !== 'undefined'
76
+ ? parsedProjection
77
+ : parsedOptions &&
78
+ typeof parsedOptions === 'object' &&
79
+ 'projection' in parsedOptions
80
+ ? parsedOptions.projection
81
+ : undefined;
74
82
  return {
75
83
  find: () => __awaiter(void 0, void 0, void 0, function* () {
76
84
  return yield (() => {
77
- const cursor = currentMethod(bson_1.EJSON.deserialize(resolvedQuery));
85
+ const cursor = currentMethod(bson_1.EJSON.deserialize(resolvedQuery), resolvedProjection, parsedOptions);
78
86
  if (parsedOptions === null || parsedOptions === void 0 ? void 0 : parsedOptions.sort) {
79
87
  cursor.sort(parsedOptions.sort);
80
88
  }
@@ -87,9 +95,9 @@ const executeQuery = (_a) => __awaiter(void 0, [_a], void 0, function* ({ curren
87
95
  return cursor.toArray();
88
96
  })();
89
97
  }),
90
- findOne: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery)),
98
+ findOne: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), resolvedProjection, parsedOptions),
91
99
  count: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), parsedOptions),
92
- deleteOne: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery)),
100
+ deleteOne: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), parsedOptions),
93
101
  insertOne: () => currentMethod(bson_1.EJSON.deserialize(document)),
94
102
  updateOne: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), bson_1.EJSON.deserialize(resolvedUpdate)),
95
103
  findOneAndUpdate: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), bson_1.EJSON.deserialize(resolvedUpdate), parsedOptions),
@@ -99,7 +107,7 @@ const executeQuery = (_a) => __awaiter(void 0, [_a], void 0, function* ({ curren
99
107
  }),
100
108
  insertMany: () => currentMethod(bson_1.EJSON.deserialize(documents)),
101
109
  updateMany: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), bson_1.EJSON.deserialize(resolvedUpdate)),
102
- deleteMany: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery))
110
+ deleteMany: () => currentMethod(bson_1.EJSON.deserialize(resolvedQuery), parsedOptions)
103
111
  };
104
112
  });
105
113
  exports.executeQuery = executeQuery;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/mongodb-atlas/index.ts"],"names":[],"mappings":"AAcA,OAAO,EAAyC,oBAAoB,EAAE,MAAM,SAAS,CAAA;AA60BrF,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":"AAcA,OAAO,EAAyC,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAm2BrF,QAAA,MAAM,YAAY,EAAE,oBAsBlB,CAAA;AAEF,eAAe,YAAY,CAAA"}
@@ -75,6 +75,8 @@ const getOperators = (collection, { rules, collName, user, run_as_system }) => {
75
75
  * Finds a single document in a MongoDB collection with optional role-based filtering and validation.
76
76
  *
77
77
  * @param {Filter<Document>} query - The MongoDB query used to match the document.
78
+ * @param {Document} [projection] - Optional projection to select returned fields.
79
+ * @param {FindOneOptions} [options] - Optional settings for the findOne operation.
78
80
  * @returns {Promise<Document | {} | null>} A promise resolving to the document if found and permitted, an empty object if access is denied, or `null` if not found.
79
81
  *
80
82
  * @description
@@ -86,12 +88,15 @@ const getOperators = (collection, { rules, collName, user, run_as_system }) => {
86
88
  * - Validates the result using `checkValidation` to ensure read permission.
87
89
  * - If validation fails, returns an empty object; otherwise returns the validated document.
88
90
  */
89
- findOne: (query) => __awaiter(void 0, void 0, void 0, function* () {
91
+ findOne: (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (query = {}, projection, options) {
90
92
  var _a;
93
+ const resolvedOptions = projection || options
94
+ ? Object.assign(Object.assign({}, (options !== null && options !== void 0 ? options : {})), (projection ? { projection } : {})) : undefined;
95
+ const resolvedQuery = query !== null && query !== void 0 ? query : {};
91
96
  if (!run_as_system) {
92
97
  (0, utils_2.checkDenyOperation)(normalizedRules, collection.collectionName, model_1.CRUD_OPERATIONS.READ);
93
98
  // Apply access control filters to the query
94
- const formattedQuery = (0, utils_2.getFormattedQuery)(filters, query, user);
99
+ const formattedQuery = (0, utils_2.getFormattedQuery)(filters, resolvedQuery, user);
95
100
  logDebug('update formattedQuery', {
96
101
  collection: collName,
97
102
  query,
@@ -106,7 +111,7 @@ const getOperators = (collection, { rules, collName, user, run_as_system }) => {
106
111
  logService('findOne query', { collName, formattedQuery });
107
112
  const safeQuery = (0, utils_2.normalizeQuery)(formattedQuery);
108
113
  logService('findOne normalizedQuery', { collName, safeQuery });
109
- const result = yield collection.findOne({ $and: safeQuery });
114
+ const result = yield collection.findOne({ $and: safeQuery }, resolvedOptions);
110
115
  logDebug('findOne result', {
111
116
  collection: collName,
112
117
  result
@@ -130,12 +135,13 @@ const getOperators = (collection, { rules, collName, user, run_as_system }) => {
130
135
  return Promise.resolve(status ? document : {});
131
136
  }
132
137
  // System mode: no validation applied
133
- return collection.findOne(query);
138
+ return collection.findOne(resolvedQuery, resolvedOptions);
134
139
  }),
135
140
  /**
136
141
  * Deletes a single document from a MongoDB collection with optional role-based validation.
137
142
  *
138
143
  * @param {Filter<Document>} [query={}] - The MongoDB query used to match the document to delete.
144
+ * @param {DeleteOptions} [options] - Optional settings for the delete operation.
139
145
  * @returns {Promise<DeleteResult>} A promise resolving to the result of the delete operation.
140
146
  *
141
147
  * @throws {Error} If the user is not authorized to delete the document.
@@ -149,7 +155,7 @@ const getOperators = (collection, { rules, collName, user, run_as_system }) => {
149
155
  * - If validation fails, throws an error.
150
156
  * - If validation passes, deletes the document using the filtered query.
151
157
  */
152
- deleteOne: (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (query = {}) {
158
+ deleteOne: (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (query = {}, options) {
153
159
  var _a;
154
160
  if (!run_as_system) {
155
161
  (0, utils_2.checkDenyOperation)(normalizedRules, collection.collectionName, model_1.CRUD_OPERATIONS.DELETE);
@@ -174,10 +180,10 @@ const getOperators = (collection, { rules, collName, user, run_as_system }) => {
174
180
  if (!status) {
175
181
  throw new Error('Delete not permitted');
176
182
  }
177
- return collection.deleteOne({ $and: formattedQuery });
183
+ return collection.deleteOne({ $and: formattedQuery }, options);
178
184
  }
179
185
  // System mode: bypass access control
180
- return collection.deleteOne(query);
186
+ return collection.deleteOne(query, options);
181
187
  }),
182
188
  /**
183
189
  * Inserts a single document into a MongoDB collection with optional role-based validation.
@@ -372,6 +378,9 @@ const getOperators = (collection, { rules, collName, user, run_as_system }) => {
372
378
  * Finds documents in a MongoDB collection with optional role-based access control and post-query validation.
373
379
  *
374
380
  * @param {Filter<Document>} query - The MongoDB query to filter documents.
381
+ * @param {Document} [projection] - Optional projection to select returned fields.
382
+ * @param {FindOptions} [options] - Optional settings for the find operation.
383
+ * @param {FindOptions} [options] - Optional settings for the find operation.
375
384
  * @returns {FindCursor} A customized `FindCursor` that includes additional access control logic in its `toArray()` method.
376
385
  *
377
386
  * @description
@@ -385,14 +394,16 @@ const getOperators = (collection, { rules, collName, user, run_as_system }) => {
385
394
  *
386
395
  * This ensures that both pre-query filtering and post-query validation are applied consistently.
387
396
  */
388
- find: (query) => {
397
+ find: (query = {}, projection, options) => {
398
+ const resolvedOptions = projection || options
399
+ ? Object.assign(Object.assign({}, (options !== null && options !== void 0 ? options : {})), (projection ? { projection } : {})) : undefined;
389
400
  if (!run_as_system) {
390
401
  (0, utils_2.checkDenyOperation)(normalizedRules, collection.collectionName, model_1.CRUD_OPERATIONS.READ);
391
402
  // Pre-query filtering based on access control rules
392
403
  const formattedQuery = (0, utils_2.getFormattedQuery)(filters, query, user);
393
404
  const currentQuery = formattedQuery.length ? { $and: formattedQuery } : {};
394
405
  // aggiunto filter per evitare questo errore: $and argument's entries must be objects
395
- const cursor = collection.find(currentQuery);
406
+ const cursor = collection.find(currentQuery, resolvedOptions);
396
407
  const originalToArray = cursor.toArray.bind(cursor);
397
408
  /**
398
409
  * Overridden `toArray` method that validates each document for read access.
@@ -425,7 +436,7 @@ const getOperators = (collection, { rules, collName, user, run_as_system }) => {
425
436
  return cursor;
426
437
  }
427
438
  // System mode: return original unfiltered cursor
428
- return collection.find(query);
439
+ return collection.find(query, resolvedOptions);
429
440
  },
430
441
  count: (query, options) => {
431
442
  if (!run_as_system) {
@@ -640,6 +651,7 @@ const getOperators = (collection, { rules, collName, user, run_as_system }) => {
640
651
  * Deletes multiple documents from a MongoDB collection with role-based access control and validation.
641
652
  *
642
653
  * @param query - The initial MongoDB query to filter documents to be deleted.
654
+ * @param {DeleteOptions} [options] - Optional settings for the delete operation.
643
655
  * @returns {Promise<{ acknowledged: boolean, deletedCount: number }>} A promise resolving to the deletion result.
644
656
  *
645
657
  * @description
@@ -650,7 +662,7 @@ const getOperators = (collection, { rules, collName, user, run_as_system }) => {
650
662
  * - Validates each document against user roles.
651
663
  * - Deletes only the documents that the current user has permission to delete.
652
664
  */
653
- deleteMany: (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (query = {}) {
665
+ deleteMany: (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (query = {}, options) {
654
666
  if (!run_as_system) {
655
667
  (0, utils_2.checkDenyOperation)(normalizedRules, collection.collectionName, model_1.CRUD_OPERATIONS.DELETE);
656
668
  // Apply access control filters
@@ -682,10 +694,10 @@ const getOperators = (collection, { rules, collName, user, run_as_system }) => {
682
694
  const deleteQuery = {
683
695
  $and: [...formattedQuery, { _id: { $in: elementsToDelete } }]
684
696
  };
685
- return collection.deleteMany(deleteQuery);
697
+ return collection.deleteMany(deleteQuery, options);
686
698
  }
687
699
  // If running as system, bypass access control and delete directly
688
- return collection.deleteMany(query);
700
+ return collection.deleteMany(query, options);
689
701
  })
690
702
  };
691
703
  };
@@ -1,5 +1,5 @@
1
1
  import { FastifyInstance } from 'fastify';
2
- import { Collection, Document, FindCursor, FindOneAndUpdateOptions, Filter as MongoFilter, UpdateFilter, WithId } from 'mongodb';
2
+ import { Collection, Document, FindCursor, FindOneAndUpdateOptions, FindOneOptions, FindOptions, Filter as MongoFilter, UpdateFilter, WithId } from 'mongodb';
3
3
  import { User } from '../../auth/dtos';
4
4
  import { Filter, Rules } from '../../features/rules/interface';
5
5
  import { Role } from '../../utils/roles/interface';
@@ -24,12 +24,12 @@ export type GetOperatorsFunction = (collection: Collection<Document>, { rules, c
24
24
  run_as_system?: boolean;
25
25
  collName: string;
26
26
  }) => {
27
- findOne: (...params: Parameters<Method<'findOne'>>) => ReturnType<Method<'findOne'>>;
28
- deleteOne: (...params: Parameters<Method<'findOne'>>) => ReturnType<Method<'findOne'>>;
27
+ findOne: (filter?: MongoFilter<Document>, projection?: Document, options?: FindOneOptions) => ReturnType<Method<'findOne'>>;
28
+ deleteOne: (...params: Parameters<Method<'deleteOne'>>) => ReturnType<Method<'deleteOne'>>;
29
29
  insertOne: (...params: Parameters<Method<'insertOne'>>) => ReturnType<Method<'insertOne'>>;
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
- find: (...params: Parameters<Method<'find'>>) => FindCursor;
32
+ find: (filter?: MongoFilter<Document>, projection?: Document, options?: FindOptions) => FindCursor;
33
33
  count: (...params: Parameters<Method<'countDocuments'>>) => ReturnType<Method<'countDocuments'>>;
34
34
  watch: (...params: Parameters<Method<'watch'>>) => ReturnType<Method<'watch'>>;
35
35
  aggregate: (...params: [...Parameters<Method<'aggregate'>>, isClient: boolean]) => ReturnType<Method<'aggregate'>>;
@@ -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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowerforce/flowerbase",
3
- "version": "1.4.2-beta.4",
3
+ "version": "1.4.2-beta.6",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -81,6 +81,7 @@ export const functionsController: FunctionController = async (
81
81
  query,
82
82
  filter,
83
83
  update,
84
+ projection,
84
85
  options,
85
86
  returnNewDocument,
86
87
  document,
@@ -98,6 +99,7 @@ export const functionsController: FunctionController = async (
98
99
  query,
99
100
  filter,
100
101
  update,
102
+ projection,
101
103
  options,
102
104
  returnNewDocument,
103
105
  document,
@@ -136,7 +138,7 @@ export const functionsController: FunctionController = async (
136
138
  res.type('application/json')
137
139
  return JSON.stringify(result)
138
140
  } catch (error) {
139
- res.status(500)
141
+ res.status(400)
140
142
  res.type('application/json')
141
143
  return JSON.stringify({
142
144
  error: formatFunctionExecutionError(error),
@@ -26,6 +26,7 @@ type ArgumentsData = Arguments<{
26
26
  filter?: Document
27
27
  query: Parameters<GetOperatorsFunction>
28
28
  update: Document
29
+ projection?: Document
29
30
  options?: Document
30
31
  returnNewDocument?: boolean
31
32
  document: Document
@@ -25,6 +25,7 @@ export type ExecuteQueryParams = {
25
25
  query: Parameters<GetOperatorsFunction>
26
26
  update: Document
27
27
  filter?: Document
28
+ projection?: Document
28
29
  options?: Document
29
30
  returnNewDocument?: boolean
30
31
  document: Document
@@ -46,6 +46,7 @@ export const executeQuery = async ({
46
46
  query,
47
47
  update,
48
48
  filter,
49
+ projection,
49
50
  options,
50
51
  returnNewDocument,
51
52
  document,
@@ -67,11 +68,23 @@ export const executeQuery = async ({
67
68
  ? { returnDocument: returnNewDocument ? 'after' : 'before' }
68
69
  : undefined
69
70
  const parsedOptions = resolvedOptions ? EJSON.deserialize(resolvedOptions) : undefined
71
+ const parsedProjection =
72
+ typeof projection !== 'undefined' ? EJSON.deserialize(projection) : undefined
73
+ const resolvedProjection =
74
+ typeof projection !== 'undefined'
75
+ ? parsedProjection
76
+ : parsedOptions &&
77
+ typeof parsedOptions === 'object' &&
78
+ 'projection' in parsedOptions
79
+ ? (parsedOptions as Document).projection
80
+ : undefined
70
81
  return {
71
82
  find: async () =>
72
83
  await (() => {
73
84
  const cursor = (currentMethod as ReturnType<GetOperatorsFunction>['find'])(
74
- EJSON.deserialize(resolvedQuery)
85
+ EJSON.deserialize(resolvedQuery),
86
+ resolvedProjection,
87
+ parsedOptions
75
88
  )
76
89
  if (parsedOptions?.sort) {
77
90
  cursor.sort(parsedOptions.sort as Document)
@@ -86,7 +99,9 @@ export const executeQuery = async ({
86
99
  })(),
87
100
  findOne: () =>
88
101
  (currentMethod as ReturnType<GetOperatorsFunction>['findOne'])(
89
- EJSON.deserialize(resolvedQuery)
102
+ EJSON.deserialize(resolvedQuery),
103
+ resolvedProjection,
104
+ parsedOptions
90
105
  ),
91
106
  count: () =>
92
107
  (currentMethod as ReturnType<GetOperatorsFunction>['count'])(
@@ -95,7 +110,8 @@ export const executeQuery = async ({
95
110
  ),
96
111
  deleteOne: () =>
97
112
  (currentMethod as ReturnType<GetOperatorsFunction>['deleteOne'])(
98
- EJSON.deserialize(resolvedQuery)
113
+ EJSON.deserialize(resolvedQuery),
114
+ parsedOptions
99
115
  ),
100
116
  insertOne: () =>
101
117
  (currentMethod as ReturnType<GetOperatorsFunction>['insertOne'])(
@@ -125,7 +141,8 @@ export const executeQuery = async ({
125
141
  ),
126
142
  deleteMany: () =>
127
143
  (currentMethod as ReturnType<GetOperatorsFunction>['deleteMany'])(
128
- EJSON.deserialize(resolvedQuery)
144
+ EJSON.deserialize(resolvedQuery),
145
+ parsedOptions
129
146
  )
130
147
  }
131
148
  }
@@ -89,6 +89,8 @@ const getOperators: GetOperatorsFunction = (
89
89
  * Finds a single document in a MongoDB collection with optional role-based filtering and validation.
90
90
  *
91
91
  * @param {Filter<Document>} query - The MongoDB query used to match the document.
92
+ * @param {Document} [projection] - Optional projection to select returned fields.
93
+ * @param {FindOneOptions} [options] - Optional settings for the findOne operation.
92
94
  * @returns {Promise<Document | {} | null>} A promise resolving to the document if found and permitted, an empty object if access is denied, or `null` if not found.
93
95
  *
94
96
  * @description
@@ -100,11 +102,19 @@ const getOperators: GetOperatorsFunction = (
100
102
  * - Validates the result using `checkValidation` to ensure read permission.
101
103
  * - If validation fails, returns an empty object; otherwise returns the validated document.
102
104
  */
103
- findOne: async (query) => {
105
+ findOne: async (query = {}, projection, options) => {
106
+ const resolvedOptions =
107
+ projection || options
108
+ ? {
109
+ ...(options ?? {}),
110
+ ...(projection ? { projection } : {})
111
+ }
112
+ : undefined
113
+ const resolvedQuery = query ?? {}
104
114
  if (!run_as_system) {
105
115
  checkDenyOperation(normalizedRules, collection.collectionName, CRUD_OPERATIONS.READ)
106
116
  // Apply access control filters to the query
107
- const formattedQuery = getFormattedQuery(filters, query, user)
117
+ const formattedQuery = getFormattedQuery(filters, resolvedQuery, user)
108
118
  logDebug('update formattedQuery', {
109
119
  collection: collName,
110
120
  query,
@@ -120,7 +130,7 @@ const getOperators: GetOperatorsFunction = (
120
130
  logService('findOne query', { collName, formattedQuery })
121
131
  const safeQuery = normalizeQuery(formattedQuery)
122
132
  logService('findOne normalizedQuery', { collName, safeQuery })
123
- const result = await collection.findOne({ $and: safeQuery })
133
+ const result = await collection.findOne({ $and: safeQuery }, resolvedOptions)
124
134
  logDebug('findOne result', {
125
135
  collection: collName,
126
136
  result
@@ -151,12 +161,13 @@ const getOperators: GetOperatorsFunction = (
151
161
  return Promise.resolve(status ? document : {})
152
162
  }
153
163
  // System mode: no validation applied
154
- return collection.findOne(query)
164
+ return collection.findOne(resolvedQuery, resolvedOptions)
155
165
  },
156
166
  /**
157
167
  * Deletes a single document from a MongoDB collection with optional role-based validation.
158
168
  *
159
169
  * @param {Filter<Document>} [query={}] - The MongoDB query used to match the document to delete.
170
+ * @param {DeleteOptions} [options] - Optional settings for the delete operation.
160
171
  * @returns {Promise<DeleteResult>} A promise resolving to the result of the delete operation.
161
172
  *
162
173
  * @throws {Error} If the user is not authorized to delete the document.
@@ -170,7 +181,7 @@ const getOperators: GetOperatorsFunction = (
170
181
  * - If validation fails, throws an error.
171
182
  * - If validation passes, deletes the document using the filtered query.
172
183
  */
173
- deleteOne: async (query = {}) => {
184
+ deleteOne: async (query = {}, options) => {
174
185
  if (!run_as_system) {
175
186
  checkDenyOperation(normalizedRules, collection.collectionName, CRUD_OPERATIONS.DELETE)
176
187
  // Apply access control filters
@@ -202,10 +213,10 @@ const getOperators: GetOperatorsFunction = (
202
213
  throw new Error('Delete not permitted')
203
214
  }
204
215
 
205
- return collection.deleteOne({ $and: formattedQuery })
216
+ return collection.deleteOne({ $and: formattedQuery }, options)
206
217
  }
207
218
  // System mode: bypass access control
208
- return collection.deleteOne(query)
219
+ return collection.deleteOne(query, options)
209
220
  },
210
221
  /**
211
222
  * Inserts a single document into a MongoDB collection with optional role-based validation.
@@ -438,6 +449,9 @@ const getOperators: GetOperatorsFunction = (
438
449
  * Finds documents in a MongoDB collection with optional role-based access control and post-query validation.
439
450
  *
440
451
  * @param {Filter<Document>} query - The MongoDB query to filter documents.
452
+ * @param {Document} [projection] - Optional projection to select returned fields.
453
+ * @param {FindOptions} [options] - Optional settings for the find operation.
454
+ * @param {FindOptions} [options] - Optional settings for the find operation.
441
455
  * @returns {FindCursor} A customized `FindCursor` that includes additional access control logic in its `toArray()` method.
442
456
  *
443
457
  * @description
@@ -451,14 +465,21 @@ const getOperators: GetOperatorsFunction = (
451
465
  *
452
466
  * This ensures that both pre-query filtering and post-query validation are applied consistently.
453
467
  */
454
- find: (query) => {
468
+ find: (query = {}, projection, options) => {
469
+ const resolvedOptions =
470
+ projection || options
471
+ ? {
472
+ ...(options ?? {}),
473
+ ...(projection ? { projection } : {})
474
+ }
475
+ : undefined
455
476
  if (!run_as_system) {
456
477
  checkDenyOperation(normalizedRules, collection.collectionName, CRUD_OPERATIONS.READ)
457
478
  // Pre-query filtering based on access control rules
458
479
  const formattedQuery = getFormattedQuery(filters, query, user)
459
480
  const currentQuery = formattedQuery.length ? { $and: formattedQuery } : {}
460
481
  // aggiunto filter per evitare questo errore: $and argument's entries must be objects
461
- const cursor = collection.find(currentQuery)
482
+ const cursor = collection.find(currentQuery, resolvedOptions)
462
483
  const originalToArray = cursor.toArray.bind(cursor)
463
484
 
464
485
  /**
@@ -502,7 +523,7 @@ const getOperators: GetOperatorsFunction = (
502
523
  return cursor
503
524
  }
504
525
  // System mode: return original unfiltered cursor
505
- return collection.find(query)
526
+ return collection.find(query, resolvedOptions)
506
527
  },
507
528
  count: (query, options) => {
508
529
  if (!run_as_system) {
@@ -793,6 +814,7 @@ const getOperators: GetOperatorsFunction = (
793
814
  * Deletes multiple documents from a MongoDB collection with role-based access control and validation.
794
815
  *
795
816
  * @param query - The initial MongoDB query to filter documents to be deleted.
817
+ * @param {DeleteOptions} [options] - Optional settings for the delete operation.
796
818
  * @returns {Promise<{ acknowledged: boolean, deletedCount: number }>} A promise resolving to the deletion result.
797
819
  *
798
820
  * @description
@@ -803,7 +825,7 @@ const getOperators: GetOperatorsFunction = (
803
825
  * - Validates each document against user roles.
804
826
  * - Deletes only the documents that the current user has permission to delete.
805
827
  */
806
- deleteMany: async (query = {}) => {
828
+ deleteMany: async (query = {}, options) => {
807
829
  if (!run_as_system) {
808
830
  checkDenyOperation(normalizedRules, collection.collectionName, CRUD_OPERATIONS.DELETE)
809
831
  // Apply access control filters
@@ -849,10 +871,10 @@ const getOperators: GetOperatorsFunction = (
849
871
  const deleteQuery = {
850
872
  $and: [...formattedQuery, { _id: { $in: elementsToDelete } }]
851
873
  }
852
- return collection.deleteMany(deleteQuery)
874
+ return collection.deleteMany(deleteQuery, options)
853
875
  }
854
876
  // If running as system, bypass access control and delete directly
855
- return collection.deleteMany(query)
877
+ return collection.deleteMany(query, options)
856
878
  }
857
879
  }
858
880
  }
@@ -4,6 +4,8 @@ import {
4
4
  Document,
5
5
  FindCursor,
6
6
  FindOneAndUpdateOptions,
7
+ FindOneOptions,
8
+ FindOptions,
7
9
  Filter as MongoFilter,
8
10
  UpdateFilter,
9
11
  WithId
@@ -50,8 +52,12 @@ export type GetOperatorsFunction = (
50
52
  collName: string
51
53
  }
52
54
  ) => {
53
- findOne: (...params: Parameters<Method<'findOne'>>) => ReturnType<Method<'findOne'>>
54
- deleteOne: (...params: Parameters<Method<'findOne'>>) => ReturnType<Method<'findOne'>>
55
+ findOne: (
56
+ filter?: MongoFilter<Document>,
57
+ projection?: Document,
58
+ options?: FindOneOptions
59
+ ) => ReturnType<Method<'findOne'>>
60
+ deleteOne: (...params: Parameters<Method<'deleteOne'>>) => ReturnType<Method<'deleteOne'>>
55
61
  insertOne: (
56
62
  ...params: Parameters<Method<'insertOne'>>
57
63
  ) => ReturnType<Method<'insertOne'>>
@@ -63,7 +69,11 @@ export type GetOperatorsFunction = (
63
69
  update: UpdateFilter<Document> | Document[],
64
70
  options?: FindOneAndUpdateOptions
65
71
  ) => Promise<Document | null>
66
- find: (...params: Parameters<Method<'find'>>) => FindCursor
72
+ find: (
73
+ filter?: MongoFilter<Document>,
74
+ projection?: Document,
75
+ options?: FindOptions
76
+ ) => FindCursor
67
77
  count: (
68
78
  ...params: Parameters<Method<'countDocuments'>>
69
79
  ) => ReturnType<Method<'countDocuments'>>