@flowerforce/flowerbase 1.1.2-beta.1 → 1.1.2-beta.10

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":"AAMA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAGhD;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,EAAE,kBA0FjC,CAAA"}
1
+ {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../src/features/functions/controller.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAKhD;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,EAAE,kBAoHjC,CAAA"}
@@ -23,6 +23,7 @@ const utils_1 = require("./utils");
23
23
  */
24
24
  const functionsController = (app_1, _a) => __awaiter(void 0, [app_1, _a], void 0, function* (app, { functionsList, rules }) {
25
25
  app.addHook('preHandler', app.jwtAuthentication);
26
+ const streams = {};
26
27
  app.post('/call', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
27
28
  const { user } = req;
28
29
  const { name: method, arguments: args } = req.body;
@@ -73,23 +74,42 @@ const functionsController = (app_1, _a) => __awaiter(void 0, [app_1, _a], void 0
73
74
  const [{ database, collection }] = config.arguments;
74
75
  const app = state_1.StateManager.select('app');
75
76
  const services = state_1.StateManager.select('services');
76
- const changeStream = yield services['mongodb-atlas'](app, {
77
+ const headers = {
78
+ 'Content-Type': 'text/event-stream',
79
+ 'Cache-Control': 'no-cache',
80
+ 'Connection': 'keep-alive',
81
+ "access-control-allow-credentials": "true",
82
+ "access-control-allow-origin": '*',
83
+ "access-control-allow-headers": "X-Stitch-Location, X-Baas-Location, Location",
84
+ };
85
+ res.raw.writeHead(200, headers);
86
+ res.raw.flushHeaders();
87
+ const requestKey = baas_request || stitch_request;
88
+ if (!requestKey)
89
+ return;
90
+ const changeStream = streams[requestKey];
91
+ if (changeStream) {
92
+ changeStream.on('change', (change) => {
93
+ res.raw.write(`data: ${JSON.stringify(change)}\n\n`);
94
+ });
95
+ req.raw.on('close', () => {
96
+ var _a;
97
+ console.log("change stream closed");
98
+ (_a = changeStream === null || changeStream === void 0 ? void 0 : changeStream.close) === null || _a === void 0 ? void 0 : _a.call(changeStream);
99
+ delete streams[requestKey];
100
+ });
101
+ return;
102
+ }
103
+ streams[requestKey] = yield services['mongodb-atlas'](app, {
77
104
  user,
78
105
  rules
79
106
  })
80
107
  .db(database)
81
108
  .collection(collection)
82
109
  .watch([], { fullDocument: 'whenAvailable' });
83
- res.header('Content-Type', 'text/event-stream');
84
- res.header('Cache-Control', 'no-cache');
85
- res.header('Connection', 'keep-alive');
86
- res.raw.flushHeaders();
87
- changeStream.on('change', (change) => {
110
+ streams[requestKey].on('change', (change) => {
88
111
  res.raw.write(`data: ${JSON.stringify(change)}\n\n`);
89
112
  });
90
- req.raw.on('close', () => {
91
- changeStream.close();
92
- });
93
113
  }));
94
114
  });
95
115
  exports.functionsController = functionsController;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAA;AActB,cAAc,SAAS,CAAA;AAEvB,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAAC,EAC/B,SAAS,EACT,IAAI,EACJ,SAAqC,EACrC,IAA0B,EAC1B,UAAuC,EACxC,EAAE,gBAAgB,iBAwElB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAA;AActB,cAAc,SAAS,CAAA;AAEvB,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAAC,EAC/B,SAAS,EACT,IAA0B,EAC1B,SAAqC,EACrC,IAA0B,EAC1B,UAAuC,EACxC,EAAE,gBAAgB,iBAwElB"}
package/dist/index.js CHANGED
@@ -73,7 +73,7 @@ __exportStar(require("./model"), exports);
73
73
  * @param mongodbUrl -> the database connection string
74
74
  */
75
75
  function initialize(_a) {
76
- return __awaiter(this, arguments, void 0, function* ({ projectId, host, jwtSecret = constants_1.DEFAULT_CONFIG.JWT_SECRET, port = constants_1.DEFAULT_CONFIG.PORT, mongodbUrl = constants_1.DEFAULT_CONFIG.MONGODB_URL }) {
76
+ return __awaiter(this, arguments, void 0, function* ({ projectId, host = constants_1.DEFAULT_CONFIG.HOST, jwtSecret = constants_1.DEFAULT_CONFIG.JWT_SECRET, port = constants_1.DEFAULT_CONFIG.PORT, mongodbUrl = constants_1.DEFAULT_CONFIG.MONGODB_URL }) {
77
77
  var _b;
78
78
  const fastify = (0, fastify_1.default)({
79
79
  logger: !!constants_1.DEFAULT_CONFIG.ENABLE_LOGGER
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/mongodb-atlas/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAyC,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAmpBrF,QAAA,MAAM,YAAY,EAAE,oBAmBlB,CAAA;AAEF,eAAe,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/mongodb-atlas/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAyC,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAqpBrF,QAAA,MAAM,YAAY,EAAE,oBAmBlB,CAAA;AAEF,eAAe,YAAY,CAAA"}
@@ -292,14 +292,15 @@ const getOperators = (collection, { rules = {}, collName, user, run_as_system })
292
292
  const { filters, roles } = rules[collName] || {};
293
293
  // Apply access filters to initial change stream pipeline
294
294
  const formattedQuery = (0, utils_2.getFormattedQuery)(filters, {}, user);
295
+ const firstStep = formattedQuery.length ? {
296
+ $match: {
297
+ $and: formattedQuery
298
+ }
299
+ } : undefined;
295
300
  const formattedPipeline = [
296
- {
297
- $match: {
298
- $and: formattedQuery
299
- }
300
- },
301
+ firstStep,
301
302
  ...pipeline
302
- ];
303
+ ].filter(Boolean);
303
304
  const result = collection.watch(formattedPipeline, options);
304
305
  const originalOn = result.on.bind(result);
305
306
  /**
@@ -348,7 +349,7 @@ const getOperators = (collection, { rules = {}, collName, user, run_as_system })
348
349
  if (isClient) {
349
350
  throw new Error("Aggregate operator from cliente is not implemented! Move it to a function");
350
351
  }
351
- if (run_as_system) {
352
+ if (run_as_system || !isClient) {
352
353
  return collection.aggregate(pipeline, options);
353
354
  }
354
355
  (0, utils_2.checkDenyOperation)(rules, collection.collectionName, model_1.CRUD_OPERATIONS.READ);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowerforce/flowerbase",
3
- "version": "1.1.2-beta.1",
3
+ "version": "1.1.2-beta.10",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,5 +1,5 @@
1
1
  import { ObjectId } from 'bson'
2
-
2
+ import { ChangeStream, Document } from 'mongodb';
3
3
  import { services } from '../../services'
4
4
  import { StateManager } from '../../state'
5
5
  import { GenerateContext } from '../../utils/context'
@@ -7,6 +7,8 @@ import { Base64Function, FunctionCallBase64Dto, FunctionCallDto } from './dtos'
7
7
  import { FunctionController } from './interface'
8
8
  import { executeQuery } from './utils'
9
9
 
10
+
11
+
10
12
  /**
11
13
  * > Creates a pre handler for every query
12
14
  * @param app -> the fastify instance
@@ -19,6 +21,8 @@ export const functionsController: FunctionController = async (
19
21
  ) => {
20
22
  app.addHook('preHandler', app.jwtAuthentication)
21
23
 
24
+ const streams = {} as Record<string, ChangeStream<Document, Document>>
25
+
22
26
  app.post<{ Body: FunctionCallDto }>('/call', async (req, res) => {
23
27
  const { user } = req
24
28
  const { name: method, arguments: args } = req.body
@@ -78,29 +82,53 @@ export const functionsController: FunctionController = async (
78
82
  const config: Base64Function = JSON.parse(
79
83
  Buffer.from(baas_request || stitch_request || '', 'base64').toString('utf8')
80
84
  )
85
+
81
86
  const [{ database, collection }] = config.arguments
82
87
  const app = StateManager.select('app')
83
88
  const services = StateManager.select('services')
84
89
 
85
- const changeStream = await services['mongodb-atlas'](app, {
90
+ const headers = {
91
+ 'Content-Type': 'text/event-stream',
92
+ 'Cache-Control': 'no-cache',
93
+ 'Connection': 'keep-alive',
94
+ "access-control-allow-credentials": "true",
95
+ "access-control-allow-origin": '*',
96
+ "access-control-allow-headers": "X-Stitch-Location, X-Baas-Location, Location",
97
+ };
98
+
99
+ res.raw.writeHead(200, headers)
100
+ res.raw.flushHeaders();
101
+
102
+ const requestKey = baas_request || stitch_request
103
+
104
+ if (!requestKey) return
105
+
106
+ const changeStream = streams[requestKey]
107
+
108
+ if (changeStream) {
109
+ changeStream.on('change', (change) => {
110
+ res.raw.write(`data: ${JSON.stringify(change)}\n\n`);
111
+ });
112
+
113
+ req.raw.on('close', () => {
114
+ console.log("change stream closed");
115
+ changeStream?.close?.();
116
+ delete streams[requestKey]
117
+ });
118
+ return
119
+ }
120
+
121
+ streams[requestKey] = await services['mongodb-atlas'](app, {
86
122
  user,
87
123
  rules
88
124
  })
89
125
  .db(database)
90
126
  .collection(collection)
91
- .watch([], { fullDocument: 'whenAvailable' })
92
-
93
- res.header('Content-Type', 'text/event-stream')
94
- res.header('Cache-Control', 'no-cache')
95
- res.header('Connection', 'keep-alive')
96
- res.raw.flushHeaders()
127
+ .watch([], { fullDocument: 'whenAvailable' });
97
128
 
98
- changeStream.on('change', (change) => {
99
- res.raw.write(`data: ${JSON.stringify(change)}\n\n`)
100
- })
101
129
 
102
- req.raw.on('close', () => {
103
- changeStream.close()
104
- })
130
+ streams[requestKey].on('change', (change) => {
131
+ res.raw.write(`data: ${JSON.stringify(change)}\n\n`);
132
+ });
105
133
  })
106
134
  }
package/src/index.ts CHANGED
@@ -32,7 +32,7 @@ export type InitializeConfig = {
32
32
  */
33
33
  export async function initialize({
34
34
  projectId,
35
- host,
35
+ host = DEFAULT_CONFIG.HOST,
36
36
  jwtSecret = DEFAULT_CONFIG.JWT_SECRET,
37
37
  port = DEFAULT_CONFIG.PORT,
38
38
  mongodbUrl = DEFAULT_CONFIG.MONGODB_URL
@@ -342,14 +342,17 @@ const getOperators: GetOperatorsFunction = (
342
342
 
343
343
  // Apply access filters to initial change stream pipeline
344
344
  const formattedQuery = getFormattedQuery(filters, {}, user)
345
+
346
+ const firstStep = formattedQuery.length ? {
347
+ $match: {
348
+ $and: formattedQuery
349
+ }
350
+ } : undefined
351
+
345
352
  const formattedPipeline = [
346
- {
347
- $match: {
348
- $and: formattedQuery
349
- }
350
- },
353
+ firstStep,
351
354
  ...pipeline
352
- ]
355
+ ].filter(Boolean) as Document[]
353
356
 
354
357
  const result = collection.watch(formattedPipeline, options)
355
358
  const originalOn = result.on.bind(result)
@@ -414,7 +417,6 @@ const getOperators: GetOperatorsFunction = (
414
417
  listener(filteredChange)
415
418
  })
416
419
  }
417
-
418
420
  return result
419
421
  }
420
422
 
@@ -426,7 +428,7 @@ const getOperators: GetOperatorsFunction = (
426
428
  if (isClient) {
427
429
  throw new Error("Aggregate operator from cliente is not implemented! Move it to a function")
428
430
  }
429
- if (run_as_system) {
431
+ if (run_as_system || !isClient) {
430
432
  return collection.aggregate(pipeline, options)
431
433
  }
432
434
  checkDenyOperation(rules, collection.collectionName, CRUD_OPERATIONS.READ)