rxdb-server 15.7.0 → 15.13.0

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 (55) hide show
  1. package/README.md +4 -0
  2. package/dist/cjs/index.js.map +1 -1
  3. package/dist/cjs/plugins/adapter-express/index.js +122 -0
  4. package/dist/cjs/plugins/adapter-express/index.js.map +1 -0
  5. package/dist/cjs/plugins/client-rest/index.js.map +1 -1
  6. package/dist/cjs/plugins/client-rest/utils.js.map +1 -1
  7. package/dist/cjs/plugins/replication-server/helpers.js.map +1 -1
  8. package/dist/cjs/plugins/replication-server/index.js +1 -1
  9. package/dist/cjs/plugins/replication-server/index.js.map +1 -1
  10. package/dist/cjs/plugins/replication-server/types.js.map +1 -1
  11. package/dist/cjs/plugins/server/endpoint-replication.js +22 -20
  12. package/dist/cjs/plugins/server/endpoint-replication.js.map +1 -1
  13. package/dist/cjs/plugins/server/endpoint-rest.js +33 -31
  14. package/dist/cjs/plugins/server/endpoint-rest.js.map +1 -1
  15. package/dist/cjs/plugins/server/helper.js +6 -45
  16. package/dist/cjs/plugins/server/helper.js.map +1 -1
  17. package/dist/cjs/plugins/server/index.js +5 -15
  18. package/dist/cjs/plugins/server/index.js.map +1 -1
  19. package/dist/cjs/plugins/server/rx-server.js +25 -22
  20. package/dist/cjs/plugins/server/rx-server.js.map +1 -1
  21. package/dist/cjs/plugins/server/types.js.map +1 -1
  22. package/dist/esm/index.js.map +1 -1
  23. package/dist/esm/plugins/adapter-express/index.js +115 -0
  24. package/dist/esm/plugins/adapter-express/index.js.map +1 -0
  25. package/dist/esm/plugins/client-rest/index.js.map +1 -1
  26. package/dist/esm/plugins/client-rest/utils.js.map +1 -1
  27. package/dist/esm/plugins/replication-server/helpers.js.map +1 -1
  28. package/dist/esm/plugins/replication-server/index.js +1 -1
  29. package/dist/esm/plugins/replication-server/index.js.map +1 -1
  30. package/dist/esm/plugins/replication-server/types.js.map +1 -1
  31. package/dist/esm/plugins/server/endpoint-replication.js +23 -21
  32. package/dist/esm/plugins/server/endpoint-replication.js.map +1 -1
  33. package/dist/esm/plugins/server/endpoint-rest.js +34 -32
  34. package/dist/esm/plugins/server/endpoint-rest.js.map +1 -1
  35. package/dist/esm/plugins/server/helper.js +6 -42
  36. package/dist/esm/plugins/server/helper.js.map +1 -1
  37. package/dist/esm/plugins/server/index.js +3 -12
  38. package/dist/esm/plugins/server/index.js.map +1 -1
  39. package/dist/esm/plugins/server/rx-server.js +25 -22
  40. package/dist/esm/plugins/server/rx-server.js.map +1 -1
  41. package/dist/esm/plugins/server/types.js.map +1 -1
  42. package/dist/types/plugins/adapter-express/index.d.ts +7 -0
  43. package/dist/types/plugins/server/endpoint-replication.d.ts +3 -3
  44. package/dist/types/plugins/server/endpoint-rest.d.ts +3 -3
  45. package/dist/types/plugins/server/helper.d.ts +6 -8
  46. package/dist/types/plugins/server/index.d.ts +1 -1
  47. package/dist/types/plugins/server/rx-server.d.ts +12 -11
  48. package/dist/types/plugins/server/types.d.ts +26 -3
  49. package/package.json +33 -27
  50. package/plugins/adapter-express/index.cjs +2 -0
  51. package/plugins/adapter-express/index.d.cts +1 -0
  52. package/plugins/adapter-express/index.d.mts +1 -0
  53. package/plugins/adapter-express/index.mjs +1 -0
  54. package/plugins/adapter-express/index.ts +1 -0
  55. package/plugins/adapter-express/package.json +18 -0
@@ -1,7 +1,7 @@
1
1
  import { normalizeMangoQuery } from 'rxdb/plugins/core';
2
2
  import { filter, mergeMap } from 'rxjs';
3
3
  import { ensureNotFalsy, getFromMapOrThrow } from 'rxdb/plugins/utils';
4
- import { addAuthMiddleware, blockPreviousVersionPaths, closeConnection, docContainsServerOnlyFields, doesContainRegexQuerySelector, getDocAllowedMatcher, removeServerOnlyFieldsMonad, setCors, writeSSEHeaders } from "./helper.js";
4
+ import { addAuthMiddleware, blockPreviousVersionPaths, docContainsServerOnlyFields, doesContainRegexQuerySelector, getDocAllowedMatcher, removeServerOnlyFieldsMonad, setCors } from "./helper.js";
5
5
  export var REST_PATHS = ['query', 'query/observe', 'get', 'set', 'delete'
6
6
 
7
7
  // TODO
@@ -18,6 +18,7 @@ export var RxServerRestEndpoint = function RxServerRestEndpoint(server, name, co
18
18
  this.collection = collection;
19
19
  this.serverOnlyFields = serverOnlyFields;
20
20
  this.cors = cors;
21
+ var adapter = server.adapter;
21
22
  setCors(this.server, [this.name].join('/'), cors);
22
23
  blockPreviousVersionPaths(this.server, [this.name].join('/'), collection.schema.version);
23
24
  this.urlPath = [this.name, collection.schema.version].join('/');
@@ -36,19 +37,20 @@ export var RxServerRestEndpoint = function RxServerRestEndpoint(server, name, co
36
37
  return changeValidator(authData, change);
37
38
  };
38
39
  var removeServerOnlyFields = removeServerOnlyFieldsMonad(this.serverOnlyFields);
39
- this.server.expressApp.post('/' + this.urlPath + '/query', async (req, res) => {
40
+ this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/query', async (req, res) => {
41
+ ensureNotFalsy(adapter.getRequestBody(req), 'req body is empty');
40
42
  var authData = getFromMapOrThrow(authDataByRequest, req);
41
43
  var useQuery;
42
44
  try {
43
- useQuery = this.queryModifier(ensureNotFalsy(authData), normalizeMangoQuery(this.collection.schema.jsonSchema, req.body));
45
+ useQuery = this.queryModifier(ensureNotFalsy(authData), normalizeMangoQuery(this.collection.schema.jsonSchema, adapter.getRequestBody(req)));
44
46
  } catch (err) {
45
- closeConnection(res, 400, 'Bad Request');
47
+ adapter.closeConnection(res, 400, 'Bad Request');
46
48
  return;
47
49
  }
48
50
  var rxQuery = this.collection.find(useQuery);
49
51
  var result = await rxQuery.exec();
50
- res.setHeader('Content-Type', 'application/json');
51
- res.json({
52
+ adapter.setResponseHeader(res, 'Content-Type', 'application/json');
53
+ adapter.endResponseJson(res, {
52
54
  documents: result.map(d => removeServerOnlyFields(d.toJSON()))
53
55
  });
54
56
  });
@@ -58,10 +60,10 @@ export var RxServerRestEndpoint = function RxServerRestEndpoint(server, name, co
58
60
  * so we send the query as query parameter in base64
59
61
  * like ?query=e3NlbGVjdG9yOiB7fX0=
60
62
  */
61
- this.server.expressApp.get('/' + this.urlPath + '/query/observe', async (req, res) => {
63
+ this.server.adapter.get(this.server.serverApp, '/' + this.urlPath + '/query/observe', async (req, res) => {
62
64
  var authData = getFromMapOrThrow(authDataByRequest, req);
63
- writeSSEHeaders(res);
64
- var useQuery = this.queryModifier(ensureNotFalsy(authData), normalizeMangoQuery(this.collection.schema.jsonSchema, JSON.parse(atob(req.query.query))));
65
+ adapter.setSSEHeaders(res);
66
+ var useQuery = this.queryModifier(ensureNotFalsy(authData), normalizeMangoQuery(this.collection.schema.jsonSchema, JSON.parse(atob(adapter.getRequestQuery(req).query))));
65
67
  var rxQuery = this.collection.find(useQuery);
66
68
  var subscription = rxQuery.$.pipe(mergeMap(async result => {
67
69
  var resultData = result.map(doc => removeServerOnlyFields(doc.toJSON()));
@@ -72,27 +74,27 @@ export var RxServerRestEndpoint = function RxServerRestEndpoint(server, name, co
72
74
  * before emitting the new results.
73
75
  */
74
76
  try {
75
- authData = await server.authHandler(req.headers);
77
+ authData = await server.authHandler(adapter.getRequestHeaders(req));
76
78
  } catch (err) {
77
- closeConnection(res, 401, 'Unauthorized');
79
+ adapter.closeConnection(res, 401, 'Unauthorized');
78
80
  return null;
79
81
  }
80
82
  return resultData;
81
83
  }), filter(f => f !== null)).subscribe(resultData => {
82
- res.write('data: ' + JSON.stringify(resultData) + '\n\n');
84
+ adapter.responseWrite(res, 'data: ' + JSON.stringify(resultData) + '\n\n');
83
85
  });
84
86
 
85
87
  /**
86
88
  * @link https://youtu.be/0PcMuYGJPzM?si=AxkczxcMaUwhh8k9&t=363
87
89
  */
88
- req.on('close', () => {
90
+ adapter.onRequestClose(req, () => {
89
91
  subscription.unsubscribe();
90
- res.end();
92
+ adapter.endResponse(req);
91
93
  });
92
94
  });
93
- this.server.expressApp.post('/' + this.urlPath + '/get', async (req, res) => {
95
+ this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/get', async (req, res) => {
94
96
  var authData = getFromMapOrThrow(authDataByRequest, req);
95
- var ids = req.body;
97
+ var ids = adapter.getRequestBody(req);
96
98
  var rxQuery = this.collection.findByIds(ids);
97
99
  var resultMap = await rxQuery.exec();
98
100
  var resultValues = Array.from(resultMap.values());
@@ -100,19 +102,19 @@ export var RxServerRestEndpoint = function RxServerRestEndpoint(server, name, co
100
102
  var useDocs = resultValues.map(d => d.toJSON());
101
103
  useDocs = useDocs.filter(d => docMatcher(d));
102
104
  useDocs = useDocs.map(d => removeServerOnlyFields(d));
103
- res.setHeader('Content-Type', 'application/json');
104
- res.json({
105
+ adapter.setResponseHeader(res, 'Content-Type', 'application/json');
106
+ adapter.endResponseJson(res, {
105
107
  documents: useDocs
106
108
  });
107
109
  });
108
- this.server.expressApp.post('/' + this.urlPath + '/set', async (req, res) => {
110
+ this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/set', async (req, res) => {
109
111
  var authData = getFromMapOrThrow(authDataByRequest, req);
110
112
  var docDataMatcherWrite = getDocAllowedMatcher(this, ensureNotFalsy(authData));
111
- var docsData = req.body;
113
+ var docsData = adapter.getRequestBody(req);
112
114
  for (var docData of docsData) {
113
115
  var allowed = docDataMatcherWrite(docData);
114
116
  if (!allowed) {
115
- closeConnection(res, 403, 'Forbidden');
117
+ adapter.closeConnection(res, 403, 'Forbidden');
116
118
  return;
117
119
  }
118
120
  }
@@ -121,7 +123,7 @@ export var RxServerRestEndpoint = function RxServerRestEndpoint(server, name, co
121
123
  // just retry on conflicts
122
124
  docsData.push(docData);
123
125
  } else {
124
- closeConnection(res, 500, 'Internal Server Error');
126
+ adapter.closeConnection(res, 500, 'Internal Server Error');
125
127
  throw err;
126
128
  }
127
129
  }
@@ -141,7 +143,7 @@ export var RxServerRestEndpoint = function RxServerRestEndpoint(server, name, co
141
143
  assumedMasterState: removeServerOnlyFields(doc.toJSON(true))
142
144
  });
143
145
  if (!isAllowed) {
144
- closeConnection(res, 403, 'Forbidden');
146
+ adapter.closeConnection(res, 403, 'Forbidden');
145
147
  return {
146
148
  v: void 0
147
149
  };
@@ -156,13 +158,13 @@ export var RxServerRestEndpoint = function RxServerRestEndpoint(server, name, co
156
158
  }
157
159
  await Promise.all(promises);
158
160
  }
159
- res.setHeader('Content-Type', 'application/json');
160
- res.json({});
161
+ adapter.setResponseHeader(res, 'Content-Type', 'application/json');
162
+ adapter.endResponseJson(res, {});
161
163
  });
162
- this.server.expressApp.post('/' + this.urlPath + '/delete', async (req, res) => {
164
+ this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/delete', async (req, res) => {
163
165
  var authData = getFromMapOrThrow(authDataByRequest, req);
164
166
  var docDataMatcherWrite = getDocAllowedMatcher(this, ensureNotFalsy(authData));
165
- var ids = req.body;
167
+ var ids = adapter.getRequestBody(req);
166
168
  while (ids.length > 0) {
167
169
  var useIds = ids.slice(0);
168
170
  ids = [];
@@ -173,7 +175,7 @@ export var RxServerRestEndpoint = function RxServerRestEndpoint(server, name, co
173
175
  if (doc) {
174
176
  var isAllowedDoc = docDataMatcherWrite(doc.toJSON(true));
175
177
  if (!isAllowedDoc) {
176
- closeConnection(res, 403, 'Forbidden');
178
+ adapter.closeConnection(res, 403, 'Forbidden');
177
179
  return {
178
180
  v: void 0
179
181
  };
@@ -183,7 +185,7 @@ export var RxServerRestEndpoint = function RxServerRestEndpoint(server, name, co
183
185
  assumedMasterState: doc.toJSON(true)
184
186
  });
185
187
  if (!isAllowedChange) {
186
- closeConnection(res, 403, 'Forbidden');
188
+ adapter.closeConnection(res, 403, 'Forbidden');
187
189
  return {
188
190
  v: void 0
189
191
  };
@@ -193,7 +195,7 @@ export var RxServerRestEndpoint = function RxServerRestEndpoint(server, name, co
193
195
  // just retry on conflicts
194
196
  ids.push(id);
195
197
  } else {
196
- closeConnection(res, 500, 'Internal Server Error');
198
+ adapter.closeConnection(res, 500, 'Internal Server Error');
197
199
  throw err;
198
200
  }
199
201
  }));
@@ -206,8 +208,8 @@ export var RxServerRestEndpoint = function RxServerRestEndpoint(server, name, co
206
208
  }
207
209
  await Promise.all(promises);
208
210
  }
209
- res.setHeader('Content-Type', 'application/json');
210
- res.json({});
211
+ adapter.setResponseHeader(res, 'Content-Type', 'application/json');
212
+ adapter.endResponseJson(res, {});
211
213
  });
212
214
  };
213
215
  //# sourceMappingURL=endpoint-rest.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"endpoint-rest.js","names":["normalizeMangoQuery","filter","mergeMap","ensureNotFalsy","getFromMapOrThrow","addAuthMiddleware","blockPreviousVersionPaths","closeConnection","docContainsServerOnlyFields","doesContainRegexQuerySelector","getDocAllowedMatcher","removeServerOnlyFieldsMonad","setCors","writeSSEHeaders","REST_PATHS","RxServerRestEndpoint","server","name","collection","queryModifier","changeValidator","serverOnlyFields","cors","_this","type","join","schema","version","urlPath","primaryPath","authDataByRequest","authData","query","selector","Error","change","assumedMasterState","newDocumentState","removeServerOnlyFields","expressApp","post","req","res","useQuery","jsonSchema","body","err","rxQuery","find","result","exec","setHeader","json","documents","map","d","toJSON","get","JSON","parse","atob","subscription","$","pipe","resultData","doc","authHandler","headers","f","subscribe","write","stringify","on","unsubscribe","end","ids","findByIds","resultMap","resultValues","Array","from","values","docMatcher","useDocs","docDataMatcherWrite","docsData","docData","allowed","onWriteError","rxdb","code","push","length","promises","docs","useDocsData","slice","_loop","_docData","id","insert","catch","isAllowed","v","patch","_ret","Promise","all","useIds","docsMap","_loop2","isAllowedDoc","isAllowedChange","remove","_ret2"],"sources":["../../../../src/plugins/server/endpoint-rest.ts"],"sourcesContent":["import {\n FilledMangoQuery,\n RxCollection,\n RxError,\n normalizeMangoQuery\n} from 'rxdb/plugins/core';\nimport type { RxServer } from './rx-server.ts';\nimport type {\n RxServerChangeValidator,\n RxServerEndpoint,\n RxServerQueryModifier\n} from './types.ts';\nimport { filter, mergeMap } from 'rxjs';\nimport {\n ensureNotFalsy,\n getFromMapOrThrow\n} from 'rxdb/plugins/utils';\n\nimport {\n addAuthMiddleware,\n blockPreviousVersionPaths,\n closeConnection,\n docContainsServerOnlyFields,\n doesContainRegexQuerySelector,\n getDocAllowedMatcher,\n removeServerOnlyFieldsMonad,\n setCors,\n writeSSEHeaders\n} from './helper.ts';\n\n\nexport const REST_PATHS = [\n 'query',\n 'query/observe',\n 'get',\n 'set',\n 'delete',\n\n // TODO\n /*\n 'attachments/add',\n 'attachments/delete',\n 'events'\n */\n] as const;\n\n\nexport class RxServerRestEndpoint<AuthType, RxDocType> implements RxServerEndpoint<AuthType, RxDocType> {\n readonly type = 'rest';\n readonly urlPath: string;\n readonly changeValidator: RxServerChangeValidator<AuthType, RxDocType>;\n readonly queryModifier: RxServerQueryModifier<AuthType, RxDocType>;\n constructor(\n public readonly server: RxServer<AuthType>,\n public readonly name: string,\n public readonly collection: RxCollection<RxDocType>,\n queryModifier: RxServerQueryModifier<AuthType, RxDocType>,\n changeValidator: RxServerChangeValidator<AuthType, RxDocType>,\n public readonly serverOnlyFields: string[],\n public readonly cors?: string\n ) {\n setCors(this.server, [this.name].join('/'), cors);\n blockPreviousVersionPaths(this.server, [this.name].join('/'), collection.schema.version);\n\n this.urlPath = [this.name, collection.schema.version].join('/');\n const primaryPath = this.collection.schema.primaryPath;\n const authDataByRequest = addAuthMiddleware(\n this.server,\n this.urlPath\n );\n\n this.queryModifier = (authData, query) => {\n if (doesContainRegexQuerySelector(query.selector)) {\n throw new Error('$regex queries not allowed because of DOS-attacks');\n }\n return queryModifier(authData, query);\n }\n this.changeValidator = (authData, change) => {\n if (\n (\n change.assumedMasterState &&\n docContainsServerOnlyFields(serverOnlyFields, change.assumedMasterState)\n ) ||\n docContainsServerOnlyFields(serverOnlyFields, change.newDocumentState)\n ) {\n return false;\n }\n return changeValidator(authData, change);\n }\n const removeServerOnlyFields = removeServerOnlyFieldsMonad(this.serverOnlyFields);\n\n this.server.expressApp.post('/' + this.urlPath + '/query', async (req, res) => {\n const authData = getFromMapOrThrow(authDataByRequest, req);\n let useQuery: FilledMangoQuery<RxDocType>\n try {\n useQuery = this.queryModifier(\n ensureNotFalsy(authData),\n normalizeMangoQuery(\n this.collection.schema.jsonSchema,\n req.body\n )\n );\n } catch (err) {\n closeConnection(res, 400, 'Bad Request');\n return;\n }\n const rxQuery = this.collection.find(useQuery as any);\n const result = await rxQuery.exec();\n res.setHeader('Content-Type', 'application/json');\n res.json({\n documents: result.map(d => removeServerOnlyFields(d.toJSON()))\n });\n });\n\n /**\n * It is not possible to send data with server send events,\n * so we send the query as query parameter in base64\n * like ?query=e3NlbGVjdG9yOiB7fX0=\n */\n this.server.expressApp.get('/' + this.urlPath + '/query/observe', async (req, res) => {\n let authData = getFromMapOrThrow(authDataByRequest, req);\n writeSSEHeaders(res);\n\n const useQuery: FilledMangoQuery<RxDocType> = this.queryModifier(\n ensureNotFalsy(authData),\n normalizeMangoQuery(\n this.collection.schema.jsonSchema,\n JSON.parse(atob(req.query.query as string))\n )\n );\n\n const rxQuery = this.collection.find(useQuery as any);\n const subscription = rxQuery.$.pipe(\n mergeMap(async (result) => {\n const resultData = result.map(doc => removeServerOnlyFields(doc.toJSON()));\n\n /**\n * The auth-data might be expired\n * so we re-run the auth parsing each time\n * before emitting the new results.\n */\n try {\n authData = await server.authHandler(req.headers);\n } catch (err) {\n closeConnection(res, 401, 'Unauthorized');\n return null;\n }\n\n return resultData;\n }),\n filter(f => f !== null)\n ).subscribe(resultData => {\n res.write('data: ' + JSON.stringify(resultData) + '\\n\\n');\n });\n\n /**\n * @link https://youtu.be/0PcMuYGJPzM?si=AxkczxcMaUwhh8k9&t=363\n */\n req.on('close', () => {\n subscription.unsubscribe();\n res.end();\n });\n });\n\n\n this.server.expressApp.post('/' + this.urlPath + '/get', async (req, res) => {\n const authData = getFromMapOrThrow(authDataByRequest, req);\n const ids: string[] = req.body;\n\n const rxQuery = this.collection.findByIds(ids);\n const resultMap = await rxQuery.exec();\n const resultValues = Array.from(resultMap.values());\n const docMatcher = getDocAllowedMatcher(this, ensureNotFalsy(authData));\n let useDocs = resultValues.map(d => d.toJSON());\n useDocs = useDocs.filter(d => docMatcher(d as any));\n useDocs = useDocs.map(d => removeServerOnlyFields(d))\n\n res.setHeader('Content-Type', 'application/json');\n res.json({\n documents: useDocs\n });\n });\n\n this.server.expressApp.post('/' + this.urlPath + '/set', async (req, res) => {\n const authData = getFromMapOrThrow(authDataByRequest, req);\n const docDataMatcherWrite = getDocAllowedMatcher(this, ensureNotFalsy(authData));\n\n let docsData: RxDocType[] = req.body;\n\n for (const docData of docsData) {\n const allowed = docDataMatcherWrite(docData as any);\n if (!allowed) {\n closeConnection(res, 403, 'Forbidden');\n return;\n }\n }\n\n function onWriteError(err: RxError, docData: RxDocType) {\n if (err.rxdb && err.code === 'CONFLICT') {\n // just retry on conflicts\n docsData.push(docData);\n } else {\n closeConnection(res, 500, 'Internal Server Error');\n throw err;\n }\n }\n\n while (docsData.length > 0) {\n const promises: Promise<any>[] = [];\n const docs = await collection.findByIds(docsData.map(d => (d as any)[primaryPath])).exec();\n let useDocsData = docsData.slice();\n docsData = [];\n for (const docData of useDocsData) {\n const id = (docData as any)[primaryPath];\n const doc = docs.get(id);\n if (!doc) {\n promises.push(this.collection.insert(docData).catch(err => onWriteError(err, docData)));\n } else {\n const isAllowed = this.changeValidator(authData, {\n newDocumentState: removeServerOnlyFields(docData as any),\n assumedMasterState: removeServerOnlyFields(doc.toJSON(true))\n });\n if (!isAllowed) {\n closeConnection(res, 403, 'Forbidden');\n return;\n }\n promises.push(doc.patch(docData).catch(err => onWriteError(err, docData)));\n }\n }\n await Promise.all(promises);\n }\n\n res.setHeader('Content-Type', 'application/json');\n res.json({\n });\n });\n\n this.server.expressApp.post('/' + this.urlPath + '/delete', async (req, res) => {\n const authData = getFromMapOrThrow(authDataByRequest, req);\n const docDataMatcherWrite = getDocAllowedMatcher(this, ensureNotFalsy(authData));\n\n let ids: string[] = req.body;\n while (ids.length > 0) {\n const useIds = ids.slice(0);\n ids = [];\n const promises: Promise<any>[] = [];\n const docsMap = await this.collection.findByIds(useIds).exec();\n for (const id of useIds) {\n const doc = docsMap.get(id);\n if (doc) {\n const isAllowedDoc = docDataMatcherWrite(doc.toJSON(true) as any);\n if (!isAllowedDoc) {\n closeConnection(res, 403, 'Forbidden');\n return;\n }\n\n const isAllowedChange = this.changeValidator(authData, {\n newDocumentState: doc.toJSON(true) as any,\n assumedMasterState: doc.toJSON(true) as any\n });\n if (!isAllowedChange) {\n closeConnection(res, 403, 'Forbidden');\n return;\n }\n\n promises.push(doc.remove().catch((err: RxError) => {\n if (err.rxdb && err.code === 'CONFLICT') {\n // just retry on conflicts\n ids.push(id);\n } else {\n closeConnection(res, 500, 'Internal Server Error');\n throw err;\n }\n }));\n }\n }\n await Promise.all(promises);\n }\n res.setHeader('Content-Type', 'application/json');\n res.json({});\n });\n }\n}\n"],"mappings":"AAAA,SAIIA,mBAAmB,QAChB,mBAAmB;AAO1B,SAASC,MAAM,EAAEC,QAAQ,QAAQ,MAAM;AACvC,SACIC,cAAc,EACdC,iBAAiB,QACd,oBAAoB;AAE3B,SACIC,iBAAiB,EACjBC,yBAAyB,EACzBC,eAAe,EACfC,2BAA2B,EAC3BC,6BAA6B,EAC7BC,oBAAoB,EACpBC,2BAA2B,EAC3BC,OAAO,EACPC,eAAe,QACZ,aAAa;AAGpB,OAAO,IAAMC,UAAU,GAAG,CACtB,OAAO,EACP,eAAe,EACf,KAAK,EACL,KAAK,EACL;;AAEA;AACA;AACJ;AACA;AACA;AACA,EAJI,CAKM;AAGV,WAAaC,oBAAoB,GAK7B,SAAAA,qBACoBC,MAA0B,EAC1BC,IAAY,EACZC,UAAmC,EACnDC,aAAyD,EACzDC,eAA6D,EAC7CC,gBAA0B,EAC1BC,IAAa,EAC/B;EAAA,IAAAC,KAAA;EAAA,KAZOC,IAAI,GAAG,MAAM;EAAA,KAKFR,MAA0B,GAA1BA,MAA0B;EAAA,KAC1BC,IAAY,GAAZA,IAAY;EAAA,KACZC,UAAmC,GAAnCA,UAAmC;EAAA,KAGnCG,gBAA0B,GAA1BA,gBAA0B;EAAA,KAC1BC,IAAa,GAAbA,IAAa;EAE7BV,OAAO,CAAC,IAAI,CAACI,MAAM,EAAE,CAAC,IAAI,CAACC,IAAI,CAAC,CAACQ,IAAI,CAAC,GAAG,CAAC,EAAEH,IAAI,CAAC;EACjDhB,yBAAyB,CAAC,IAAI,CAACU,MAAM,EAAE,CAAC,IAAI,CAACC,IAAI,CAAC,CAACQ,IAAI,CAAC,GAAG,CAAC,EAAEP,UAAU,CAACQ,MAAM,CAACC,OAAO,CAAC;EAExF,IAAI,CAACC,OAAO,GAAG,CAAC,IAAI,CAACX,IAAI,EAAEC,UAAU,CAACQ,MAAM,CAACC,OAAO,CAAC,CAACF,IAAI,CAAC,GAAG,CAAC;EAC/D,IAAMI,WAAW,GAAG,IAAI,CAACX,UAAU,CAACQ,MAAM,CAACG,WAAW;EACtD,IAAMC,iBAAiB,GAAGzB,iBAAiB,CACvC,IAAI,CAACW,MAAM,EACX,IAAI,CAACY,OACT,CAAC;EAED,IAAI,CAACT,aAAa,GAAG,CAACY,QAAQ,EAAEC,KAAK,KAAK;IACtC,IAAIvB,6BAA6B,CAACuB,KAAK,CAACC,QAAQ,CAAC,EAAE;MAC/C,MAAM,IAAIC,KAAK,CAAC,mDAAmD,CAAC;IACxE;IACA,OAAOf,aAAa,CAACY,QAAQ,EAAEC,KAAK,CAAC;EACzC,CAAC;EACD,IAAI,CAACZ,eAAe,GAAG,CAACW,QAAQ,EAAEI,MAAM,KAAK;IACzC,IAEQA,MAAM,CAACC,kBAAkB,IACzB5B,2BAA2B,CAACa,gBAAgB,EAAEc,MAAM,CAACC,kBAAkB,CAAC,IAE5E5B,2BAA2B,CAACa,gBAAgB,EAAEc,MAAM,CAACE,gBAAgB,CAAC,EACxE;MACE,OAAO,KAAK;IAChB;IACA,OAAOjB,eAAe,CAACW,QAAQ,EAAEI,MAAM,CAAC;EAC5C,CAAC;EACD,IAAMG,sBAAsB,GAAG3B,2BAA2B,CAAC,IAAI,CAACU,gBAAgB,CAAC;EAEjF,IAAI,CAACL,MAAM,CAACuB,UAAU,CAACC,IAAI,CAAC,GAAG,GAAG,IAAI,CAACZ,OAAO,GAAG,QAAQ,EAAE,OAAOa,GAAG,EAAEC,GAAG,KAAK;IAC3E,IAAMX,QAAQ,GAAG3B,iBAAiB,CAAC0B,iBAAiB,EAAEW,GAAG,CAAC;IAC1D,IAAIE,QAAqC;IACzC,IAAI;MACAA,QAAQ,GAAG,IAAI,CAACxB,aAAa,CACzBhB,cAAc,CAAC4B,QAAQ,CAAC,EACxB/B,mBAAmB,CACf,IAAI,CAACkB,UAAU,CAACQ,MAAM,CAACkB,UAAU,EACjCH,GAAG,CAACI,IACR,CACJ,CAAC;IACL,CAAC,CAAC,OAAOC,GAAG,EAAE;MACVvC,eAAe,CAACmC,GAAG,EAAE,GAAG,EAAE,aAAa,CAAC;MACxC;IACJ;IACA,IAAMK,OAAO,GAAG,IAAI,CAAC7B,UAAU,CAAC8B,IAAI,CAACL,QAAe,CAAC;IACrD,IAAMM,MAAM,GAAG,MAAMF,OAAO,CAACG,IAAI,CAAC,CAAC;IACnCR,GAAG,CAACS,SAAS,CAAC,cAAc,EAAE,kBAAkB,CAAC;IACjDT,GAAG,CAACU,IAAI,CAAC;MACLC,SAAS,EAAEJ,MAAM,CAACK,GAAG,CAACC,CAAC,IAAIjB,sBAAsB,CAACiB,CAAC,CAACC,MAAM,CAAC,CAAC,CAAC;IACjE,CAAC,CAAC;EACN,CAAC,CAAC;;EAEF;AACR;AACA;AACA;AACA;EACQ,IAAI,CAACxC,MAAM,CAACuB,UAAU,CAACkB,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC7B,OAAO,GAAG,gBAAgB,EAAE,OAAOa,GAAG,EAAEC,GAAG,KAAK;IAClF,IAAIX,QAAQ,GAAG3B,iBAAiB,CAAC0B,iBAAiB,EAAEW,GAAG,CAAC;IACxD5B,eAAe,CAAC6B,GAAG,CAAC;IAEpB,IAAMC,QAAqC,GAAG,IAAI,CAACxB,aAAa,CAC5DhB,cAAc,CAAC4B,QAAQ,CAAC,EACxB/B,mBAAmB,CACf,IAAI,CAACkB,UAAU,CAACQ,MAAM,CAACkB,UAAU,EACjCc,IAAI,CAACC,KAAK,CAACC,IAAI,CAACnB,GAAG,CAACT,KAAK,CAACA,KAAe,CAAC,CAC9C,CACJ,CAAC;IAED,IAAMe,OAAO,GAAG,IAAI,CAAC7B,UAAU,CAAC8B,IAAI,CAACL,QAAe,CAAC;IACrD,IAAMkB,YAAY,GAAGd,OAAO,CAACe,CAAC,CAACC,IAAI,CAC/B7D,QAAQ,CAAC,MAAO+C,MAAM,IAAK;MACvB,IAAMe,UAAU,GAAGf,MAAM,CAACK,GAAG,CAACW,GAAG,IAAI3B,sBAAsB,CAAC2B,GAAG,CAACT,MAAM,CAAC,CAAC,CAAC,CAAC;;MAE1E;AACpB;AACA;AACA;AACA;MACoB,IAAI;QACAzB,QAAQ,GAAG,MAAMf,MAAM,CAACkD,WAAW,CAACzB,GAAG,CAAC0B,OAAO,CAAC;MACpD,CAAC,CAAC,OAAOrB,GAAG,EAAE;QACVvC,eAAe,CAACmC,GAAG,EAAE,GAAG,EAAE,cAAc,CAAC;QACzC,OAAO,IAAI;MACf;MAEA,OAAOsB,UAAU;IACrB,CAAC,CAAC,EACF/D,MAAM,CAACmE,CAAC,IAAIA,CAAC,KAAK,IAAI,CAC1B,CAAC,CAACC,SAAS,CAACL,UAAU,IAAI;MACtBtB,GAAG,CAAC4B,KAAK,CAAC,QAAQ,GAAGZ,IAAI,CAACa,SAAS,CAACP,UAAU,CAAC,GAAG,MAAM,CAAC;IAC7D,CAAC,CAAC;;IAEF;AACZ;AACA;IACYvB,GAAG,CAAC+B,EAAE,CAAC,OAAO,EAAE,MAAM;MAClBX,YAAY,CAACY,WAAW,CAAC,CAAC;MAC1B/B,GAAG,CAACgC,GAAG,CAAC,CAAC;IACb,CAAC,CAAC;EACN,CAAC,CAAC;EAGF,IAAI,CAAC1D,MAAM,CAACuB,UAAU,CAACC,IAAI,CAAC,GAAG,GAAG,IAAI,CAACZ,OAAO,GAAG,MAAM,EAAE,OAAOa,GAAG,EAAEC,GAAG,KAAK;IACzE,IAAMX,QAAQ,GAAG3B,iBAAiB,CAAC0B,iBAAiB,EAAEW,GAAG,CAAC;IAC1D,IAAMkC,GAAa,GAAGlC,GAAG,CAACI,IAAI;IAE9B,IAAME,OAAO,GAAG,IAAI,CAAC7B,UAAU,CAAC0D,SAAS,CAACD,GAAG,CAAC;IAC9C,IAAME,SAAS,GAAG,MAAM9B,OAAO,CAACG,IAAI,CAAC,CAAC;IACtC,IAAM4B,YAAY,GAAGC,KAAK,CAACC,IAAI,CAACH,SAAS,CAACI,MAAM,CAAC,CAAC,CAAC;IACnD,IAAMC,UAAU,GAAGxE,oBAAoB,CAAC,IAAI,EAAEP,cAAc,CAAC4B,QAAQ,CAAC,CAAC;IACvE,IAAIoD,OAAO,GAAGL,YAAY,CAACxB,GAAG,CAACC,CAAC,IAAIA,CAAC,CAACC,MAAM,CAAC,CAAC,CAAC;IAC/C2B,OAAO,GAAGA,OAAO,CAAClF,MAAM,CAACsD,CAAC,IAAI2B,UAAU,CAAC3B,CAAQ,CAAC,CAAC;IACnD4B,OAAO,GAAGA,OAAO,CAAC7B,GAAG,CAACC,CAAC,IAAIjB,sBAAsB,CAACiB,CAAC,CAAC,CAAC;IAErDb,GAAG,CAACS,SAAS,CAAC,cAAc,EAAE,kBAAkB,CAAC;IACjDT,GAAG,CAACU,IAAI,CAAC;MACLC,SAAS,EAAE8B;IACf,CAAC,CAAC;EACN,CAAC,CAAC;EAEF,IAAI,CAACnE,MAAM,CAACuB,UAAU,CAACC,IAAI,CAAC,GAAG,GAAG,IAAI,CAACZ,OAAO,GAAG,MAAM,EAAE,OAAOa,GAAG,EAAEC,GAAG,KAAK;IACzE,IAAMX,QAAQ,GAAG3B,iBAAiB,CAAC0B,iBAAiB,EAAEW,GAAG,CAAC;IAC1D,IAAM2C,mBAAmB,GAAG1E,oBAAoB,CAAC,IAAI,EAAEP,cAAc,CAAC4B,QAAQ,CAAC,CAAC;IAEhF,IAAIsD,QAAqB,GAAG5C,GAAG,CAACI,IAAI;IAEpC,KAAK,IAAMyC,OAAO,IAAID,QAAQ,EAAE;MAC5B,IAAME,OAAO,GAAGH,mBAAmB,CAACE,OAAc,CAAC;MACnD,IAAI,CAACC,OAAO,EAAE;QACVhF,eAAe,CAACmC,GAAG,EAAE,GAAG,EAAE,WAAW,CAAC;QACtC;MACJ;IACJ;IAEA,SAAS8C,YAAYA,CAAC1C,GAAY,EAAEwC,OAAkB,EAAE;MACpD,IAAIxC,GAAG,CAAC2C,IAAI,IAAI3C,GAAG,CAAC4C,IAAI,KAAK,UAAU,EAAE;QACrC;QACAL,QAAQ,CAACM,IAAI,CAACL,OAAO,CAAC;MAC1B,CAAC,MAAM;QACH/E,eAAe,CAACmC,GAAG,EAAE,GAAG,EAAE,uBAAuB,CAAC;QAClD,MAAMI,GAAG;MACb;IACJ;IAEA,OAAOuC,QAAQ,CAACO,MAAM,GAAG,CAAC,EAAE;MACxB,IAAMC,QAAwB,GAAG,EAAE;MACnC,IAAMC,IAAI,GAAG,MAAM5E,UAAU,CAAC0D,SAAS,CAACS,QAAQ,CAAC/B,GAAG,CAACC,CAAC,IAAKA,CAAC,CAAS1B,WAAW,CAAC,CAAC,CAAC,CAACqB,IAAI,CAAC,CAAC;MAC1F,IAAI6C,WAAW,GAAGV,QAAQ,CAACW,KAAK,CAAC,CAAC;MAClCX,QAAQ,GAAG,EAAE;MAAC,IAAAY,KAAA,kBAAAA,CAAAC,QAAA,EACqB;UAC/B,IAAMC,EAAE,GAAIb,QAAO,CAASzD,WAAW,CAAC;UACxC,IAAMoC,GAAG,GAAG6B,IAAI,CAACrC,GAAG,CAAC0C,EAAE,CAAC;UACxB,IAAI,CAAClC,GAAG,EAAE;YACN4B,QAAQ,CAACF,IAAI,CAACpE,KAAI,CAACL,UAAU,CAACkF,MAAM,CAACd,QAAO,CAAC,CAACe,KAAK,CAACvD,GAAG,IAAI0C,YAAY,CAAC1C,GAAG,EAAEwC,QAAO,CAAC,CAAC,CAAC;UAC3F,CAAC,MAAM;YACH,IAAMgB,SAAS,GAAG/E,KAAI,CAACH,eAAe,CAACW,QAAQ,EAAE;cAC7CM,gBAAgB,EAAEC,sBAAsB,CAACgD,QAAc,CAAC;cACxDlD,kBAAkB,EAAEE,sBAAsB,CAAC2B,GAAG,CAACT,MAAM,CAAC,IAAI,CAAC;YAC/D,CAAC,CAAC;YACF,IAAI,CAAC8C,SAAS,EAAE;cACZ/F,eAAe,CAACmC,GAAG,EAAE,GAAG,EAAE,WAAW,CAAC;cAAC;gBAAA6D,CAAA;cAAA;YAE3C;YACAV,QAAQ,CAACF,IAAI,CAAC1B,GAAG,CAACuC,KAAK,CAAClB,QAAO,CAAC,CAACe,KAAK,CAACvD,GAAG,IAAI0C,YAAY,CAAC1C,GAAG,EAAEwC,QAAO,CAAC,CAAC,CAAC;UAC9E;QACJ,CAAC;QAAAmB,IAAA;MAhBD,KAAK,IAAMnB,QAAO,IAAIS,WAAW;QAAAU,IAAA,SAAAR,KAAA,CAAAC,QAAA;QAAA,IAAAO,IAAA,SAAAA,IAAA,CAAAF,CAAA;MAAA;MAiBjC,MAAMG,OAAO,CAACC,GAAG,CAACd,QAAQ,CAAC;IAC/B;IAEAnD,GAAG,CAACS,SAAS,CAAC,cAAc,EAAE,kBAAkB,CAAC;IACjDT,GAAG,CAACU,IAAI,CAAC,CACT,CAAC,CAAC;EACN,CAAC,CAAC;EAEF,IAAI,CAACpC,MAAM,CAACuB,UAAU,CAACC,IAAI,CAAC,GAAG,GAAG,IAAI,CAACZ,OAAO,GAAG,SAAS,EAAE,OAAOa,GAAG,EAAEC,GAAG,KAAK;IAC5E,IAAMX,QAAQ,GAAG3B,iBAAiB,CAAC0B,iBAAiB,EAAEW,GAAG,CAAC;IAC1D,IAAM2C,mBAAmB,GAAG1E,oBAAoB,CAAC,IAAI,EAAEP,cAAc,CAAC4B,QAAQ,CAAC,CAAC;IAEhF,IAAI4C,GAAa,GAAGlC,GAAG,CAACI,IAAI;IAC5B,OAAO8B,GAAG,CAACiB,MAAM,GAAG,CAAC,EAAE;MACnB,IAAMgB,MAAM,GAAGjC,GAAG,CAACqB,KAAK,CAAC,CAAC,CAAC;MAC3BrB,GAAG,GAAG,EAAE;MACR,IAAMkB,QAAwB,GAAG,EAAE;MACnC,IAAMgB,OAAO,GAAG,MAAM,IAAI,CAAC3F,UAAU,CAAC0D,SAAS,CAACgC,MAAM,CAAC,CAAC1D,IAAI,CAAC,CAAC;MAAC,IAAA4D,MAAA,kBAAAA,CAAAX,EAAA,EACtC;UACrB,IAAMlC,GAAG,GAAG4C,OAAO,CAACpD,GAAG,CAAC0C,EAAE,CAAC;UAC3B,IAAIlC,GAAG,EAAE;YACL,IAAM8C,YAAY,GAAG3B,mBAAmB,CAACnB,GAAG,CAACT,MAAM,CAAC,IAAI,CAAQ,CAAC;YACjE,IAAI,CAACuD,YAAY,EAAE;cACfxG,eAAe,CAACmC,GAAG,EAAE,GAAG,EAAE,WAAW,CAAC;cAAC;gBAAA6D,CAAA;cAAA;YAE3C;YAEA,IAAMS,eAAe,GAAGzF,KAAI,CAACH,eAAe,CAACW,QAAQ,EAAE;cACnDM,gBAAgB,EAAE4B,GAAG,CAACT,MAAM,CAAC,IAAI,CAAQ;cACzCpB,kBAAkB,EAAE6B,GAAG,CAACT,MAAM,CAAC,IAAI;YACvC,CAAC,CAAC;YACF,IAAI,CAACwD,eAAe,EAAE;cAClBzG,eAAe,CAACmC,GAAG,EAAE,GAAG,EAAE,WAAW,CAAC;cAAC;gBAAA6D,CAAA;cAAA;YAE3C;YAEAV,QAAQ,CAACF,IAAI,CAAC1B,GAAG,CAACgD,MAAM,CAAC,CAAC,CAACZ,KAAK,CAAEvD,GAAY,IAAK;cAC/C,IAAIA,GAAG,CAAC2C,IAAI,IAAI3C,GAAG,CAAC4C,IAAI,KAAK,UAAU,EAAE;gBACrC;gBACAf,GAAG,CAACgB,IAAI,CAACQ,EAAE,CAAC;cAChB,CAAC,MAAM;gBACH5F,eAAe,CAACmC,GAAG,EAAE,GAAG,EAAE,uBAAuB,CAAC;gBAClD,MAAMI,GAAG;cACb;YACJ,CAAC,CAAC,CAAC;UACP;QACJ,CAAC;QAAAoE,KAAA;MA5BD,KAAK,IAAMf,EAAE,IAAIS,MAAM;QAAAM,KAAA,SAAAJ,MAAA,CAAAX,EAAA;QAAA,IAAAe,KAAA,SAAAA,KAAA,CAAAX,CAAA;MAAA;MA6BvB,MAAMG,OAAO,CAACC,GAAG,CAACd,QAAQ,CAAC;IAC/B;IACAnD,GAAG,CAACS,SAAS,CAAC,cAAc,EAAE,kBAAkB,CAAC;IACjDT,GAAG,CAACU,IAAI,CAAC,CAAC,CAAC,CAAC;EAChB,CAAC,CAAC;AACN,CAAC"}
1
+ {"version":3,"file":"endpoint-rest.js","names":["normalizeMangoQuery","filter","mergeMap","ensureNotFalsy","getFromMapOrThrow","addAuthMiddleware","blockPreviousVersionPaths","docContainsServerOnlyFields","doesContainRegexQuerySelector","getDocAllowedMatcher","removeServerOnlyFieldsMonad","setCors","REST_PATHS","RxServerRestEndpoint","server","name","collection","queryModifier","changeValidator","serverOnlyFields","cors","_this","type","adapter","join","schema","version","urlPath","primaryPath","authDataByRequest","authData","query","selector","Error","change","assumedMasterState","newDocumentState","removeServerOnlyFields","post","serverApp","req","res","getRequestBody","useQuery","jsonSchema","err","closeConnection","rxQuery","find","result","exec","setResponseHeader","endResponseJson","documents","map","d","toJSON","get","setSSEHeaders","JSON","parse","atob","getRequestQuery","subscription","$","pipe","resultData","doc","authHandler","getRequestHeaders","f","subscribe","responseWrite","stringify","onRequestClose","unsubscribe","endResponse","ids","findByIds","resultMap","resultValues","Array","from","values","docMatcher","useDocs","docDataMatcherWrite","docsData","docData","allowed","onWriteError","rxdb","code","push","length","promises","docs","useDocsData","slice","_loop","_docData","id","insert","catch","isAllowed","v","patch","_ret","Promise","all","useIds","docsMap","_loop2","isAllowedDoc","isAllowedChange","remove","_ret2"],"sources":["../../../../src/plugins/server/endpoint-rest.ts"],"sourcesContent":["import {\n FilledMangoQuery,\n RxCollection,\n RxError,\n normalizeMangoQuery\n} from 'rxdb/plugins/core';\nimport type { RxServer } from './rx-server.ts';\nimport type {\n RxServerChangeValidator,\n RxServerEndpoint,\n RxServerQueryModifier\n} from './types.ts';\nimport { filter, mergeMap } from 'rxjs';\nimport {\n ensureNotFalsy,\n getFromMapOrThrow\n} from 'rxdb/plugins/utils';\n\nimport {\n addAuthMiddleware,\n blockPreviousVersionPaths,\n docContainsServerOnlyFields,\n doesContainRegexQuerySelector,\n getDocAllowedMatcher,\n removeServerOnlyFieldsMonad,\n setCors\n} from './helper.ts';\n\n\nexport const REST_PATHS = [\n 'query',\n 'query/observe',\n 'get',\n 'set',\n 'delete',\n\n // TODO\n /*\n 'attachments/add',\n 'attachments/delete',\n 'events'\n */\n] as const;\n\n\nexport class RxServerRestEndpoint<ServerAppType, AuthType, RxDocType> implements RxServerEndpoint<AuthType, RxDocType> {\n readonly type = 'rest';\n readonly urlPath: string;\n readonly changeValidator: RxServerChangeValidator<AuthType, RxDocType>;\n readonly queryModifier: RxServerQueryModifier<AuthType, RxDocType>;\n constructor(\n public readonly server: RxServer<ServerAppType, AuthType>,\n public readonly name: string,\n public readonly collection: RxCollection<RxDocType>,\n queryModifier: RxServerQueryModifier<AuthType, RxDocType>,\n changeValidator: RxServerChangeValidator<AuthType, RxDocType>,\n public readonly serverOnlyFields: string[],\n public readonly cors?: string\n ) {\n const adapter = server.adapter;\n setCors(this.server, [this.name].join('/'), cors);\n blockPreviousVersionPaths(this.server, [this.name].join('/'), collection.schema.version);\n\n this.urlPath = [this.name, collection.schema.version].join('/');\n const primaryPath = this.collection.schema.primaryPath;\n const authDataByRequest = addAuthMiddleware(\n this.server,\n this.urlPath\n );\n\n this.queryModifier = (authData, query) => {\n if (doesContainRegexQuerySelector(query.selector)) {\n throw new Error('$regex queries not allowed because of DOS-attacks');\n }\n return queryModifier(authData, query);\n }\n this.changeValidator = (authData, change) => {\n if (\n (\n change.assumedMasterState &&\n docContainsServerOnlyFields(serverOnlyFields, change.assumedMasterState)\n ) ||\n docContainsServerOnlyFields(serverOnlyFields, change.newDocumentState)\n ) {\n return false;\n }\n return changeValidator(authData, change);\n }\n const removeServerOnlyFields = removeServerOnlyFieldsMonad(this.serverOnlyFields);\n\n this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/query', async (req, res) => {\n ensureNotFalsy(adapter.getRequestBody(req), 'req body is empty');\n const authData = getFromMapOrThrow(authDataByRequest, req);\n let useQuery: FilledMangoQuery<RxDocType>\n try {\n useQuery = this.queryModifier(\n ensureNotFalsy(authData),\n normalizeMangoQuery(\n this.collection.schema.jsonSchema,\n adapter.getRequestBody(req)\n )\n );\n } catch (err) {\n adapter.closeConnection(res, 400, 'Bad Request');\n return;\n }\n const rxQuery = this.collection.find(useQuery as any);\n const result = await rxQuery.exec();\n adapter.setResponseHeader(res, 'Content-Type', 'application/json');\n adapter.endResponseJson(res, {\n documents: result.map(d => removeServerOnlyFields(d.toJSON()))\n });\n });\n\n /**\n * It is not possible to send data with server send events,\n * so we send the query as query parameter in base64\n * like ?query=e3NlbGVjdG9yOiB7fX0=\n */\n this.server.adapter.get(this.server.serverApp, '/' + this.urlPath + '/query/observe', async (req, res) => {\n let authData = getFromMapOrThrow(authDataByRequest, req);\n adapter.setSSEHeaders(res);\n\n const useQuery: FilledMangoQuery<RxDocType> = this.queryModifier(\n ensureNotFalsy(authData),\n normalizeMangoQuery(\n this.collection.schema.jsonSchema,\n JSON.parse(atob(adapter.getRequestQuery(req).query as string))\n )\n );\n\n const rxQuery = this.collection.find(useQuery as any);\n const subscription = rxQuery.$.pipe(\n mergeMap(async (result) => {\n const resultData = result.map(doc => removeServerOnlyFields(doc.toJSON()));\n\n /**\n * The auth-data might be expired\n * so we re-run the auth parsing each time\n * before emitting the new results.\n */\n try {\n authData = await server.authHandler(adapter.getRequestHeaders(req));\n } catch (err) {\n adapter.closeConnection(res, 401, 'Unauthorized');\n return null;\n }\n\n return resultData;\n }),\n filter(f => f !== null)\n ).subscribe(resultData => {\n adapter.responseWrite(res, 'data: ' + JSON.stringify(resultData) + '\\n\\n');\n });\n\n /**\n * @link https://youtu.be/0PcMuYGJPzM?si=AxkczxcMaUwhh8k9&t=363\n */\n adapter.onRequestClose(req, () => {\n subscription.unsubscribe();\n adapter.endResponse(req);\n });\n });\n\n\n this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/get', async (req, res) => {\n const authData = getFromMapOrThrow(authDataByRequest, req);\n const ids: string[] = adapter.getRequestBody(req);\n\n const rxQuery = this.collection.findByIds(ids);\n const resultMap = await rxQuery.exec();\n const resultValues = Array.from(resultMap.values());\n const docMatcher = getDocAllowedMatcher(this, ensureNotFalsy(authData));\n let useDocs = resultValues.map(d => d.toJSON());\n useDocs = useDocs.filter(d => docMatcher(d as any));\n useDocs = useDocs.map(d => removeServerOnlyFields(d))\n\n adapter.setResponseHeader(res, 'Content-Type', 'application/json');\n adapter.endResponseJson(res, {\n documents: useDocs\n });\n });\n\n this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/set', async (req, res) => {\n const authData = getFromMapOrThrow(authDataByRequest, req);\n const docDataMatcherWrite = getDocAllowedMatcher(this, ensureNotFalsy(authData));\n\n let docsData: RxDocType[] = adapter.getRequestBody(req);\n\n for (const docData of docsData) {\n const allowed = docDataMatcherWrite(docData as any);\n if (!allowed) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n }\n\n function onWriteError(err: RxError, docData: RxDocType) {\n if (err.rxdb && err.code === 'CONFLICT') {\n // just retry on conflicts\n docsData.push(docData);\n } else {\n adapter.closeConnection(res, 500, 'Internal Server Error');\n throw err;\n }\n }\n\n while (docsData.length > 0) {\n const promises: Promise<any>[] = [];\n const docs = await collection.findByIds(docsData.map(d => (d as any)[primaryPath])).exec();\n let useDocsData = docsData.slice();\n docsData = [];\n for (const docData of useDocsData) {\n const id = (docData as any)[primaryPath];\n const doc = docs.get(id);\n if (!doc) {\n promises.push(this.collection.insert(docData).catch(err => onWriteError(err, docData)));\n } else {\n const isAllowed = this.changeValidator(authData, {\n newDocumentState: removeServerOnlyFields(docData as any),\n assumedMasterState: removeServerOnlyFields(doc.toJSON(true))\n });\n if (!isAllowed) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n promises.push(doc.patch(docData).catch(err => onWriteError(err, docData)));\n }\n }\n await Promise.all(promises);\n }\n\n adapter.setResponseHeader(res, 'Content-Type', 'application/json')\n adapter.endResponseJson(res, {});\n });\n\n this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/delete', async (req, res) => {\n const authData = getFromMapOrThrow(authDataByRequest, req);\n const docDataMatcherWrite = getDocAllowedMatcher(this, ensureNotFalsy(authData));\n\n let ids: string[] = adapter.getRequestBody(req);\n while (ids.length > 0) {\n const useIds = ids.slice(0);\n ids = [];\n const promises: Promise<any>[] = [];\n const docsMap = await this.collection.findByIds(useIds).exec();\n for (const id of useIds) {\n const doc = docsMap.get(id);\n if (doc) {\n const isAllowedDoc = docDataMatcherWrite(doc.toJSON(true) as any);\n if (!isAllowedDoc) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n\n const isAllowedChange = this.changeValidator(authData, {\n newDocumentState: doc.toJSON(true) as any,\n assumedMasterState: doc.toJSON(true) as any\n });\n if (!isAllowedChange) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n\n promises.push(doc.remove().catch((err: RxError) => {\n if (err.rxdb && err.code === 'CONFLICT') {\n // just retry on conflicts\n ids.push(id);\n } else {\n adapter.closeConnection(res, 500, 'Internal Server Error');\n throw err;\n }\n }));\n }\n }\n await Promise.all(promises);\n }\n adapter.setResponseHeader(res, 'Content-Type', 'application/json');\n adapter.endResponseJson(res, {});\n });\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1,4 +1,3 @@
1
- import expressCors from 'cors';
2
1
  import { flatClone, getQueryMatcher, normalizeMangoQuery, uniqueArray } from 'rxdb/plugins/core';
3
2
  export function setCors(server, path, cors) {
4
3
  var useCors = cors;
@@ -6,11 +5,7 @@ export function setCors(server, path, cors) {
6
5
  useCors = server.cors;
7
6
  }
8
7
  if (useCors) {
9
- server.expressApp.options('/' + path + '/*', expressCors({
10
- origin: useCors,
11
- // some legacy browsers (IE11, various SmartTVs) choke on 204
12
- optionsSuccessStatus: 200
13
- }));
8
+ server.adapter.setCors(server.serverApp, path, useCors);
14
9
  }
15
10
  }
16
11
 
@@ -22,8 +17,8 @@ export function blockPreviousVersionPaths(server, path, currentVersion) {
22
17
  var v = 0;
23
18
  var _loop = function () {
24
19
  var version = v;
25
- server.expressApp.all('/' + path + '/' + version + '/*', (req, res) => {
26
- closeConnection(res, 426, 'Outdated version ' + version + ' (newest is ' + currentVersion + ')');
20
+ server.adapter.all(server.serverApp, '/' + path + '/' + version + '/*', (req, res) => {
21
+ server.adapter.closeConnection(res, 426, 'Outdated version ' + version + ' (newest is ' + currentVersion + ')');
27
22
  });
28
23
  v++;
29
24
  };
@@ -31,17 +26,6 @@ export function blockPreviousVersionPaths(server, path, currentVersion) {
31
26
  _loop();
32
27
  }
33
28
  }
34
- export async function closeConnection(response, code, message) {
35
- var responseWrite = {
36
- code,
37
- error: true,
38
- message
39
- };
40
- response.statusCode = code;
41
- response.set("Connection", "close");
42
- await response.write(JSON.stringify(responseWrite));
43
- response.end();
44
- }
45
29
  export function addAuthMiddleware(server, path) {
46
30
  var authDataByRequest = new WeakMap();
47
31
  async function auth(req, res, next) {
@@ -50,13 +34,11 @@ export function addAuthMiddleware(server, path) {
50
34
  authDataByRequest.set(req, authData);
51
35
  next();
52
36
  } catch (err) {
53
- closeConnection(res, 401, 'Unauthorized');
37
+ server.adapter.closeConnection(res, 401, 'Unauthorized');
54
38
  return;
55
39
  }
56
40
  }
57
- server.expressApp.all('/' + path + '/*', auth, function (req, res, next) {
58
- next();
59
- });
41
+ server.adapter.all(server.serverApp, '/' + path + '/*', auth);
60
42
  return authDataByRequest;
61
43
  }
62
44
  var defaultMatchingQuery = {
@@ -69,24 +51,6 @@ export function getDocAllowedMatcher(endpoint, authData) {
69
51
  var docDataMatcher = getQueryMatcher(endpoint.collection.schema.jsonSchema, useQuery);
70
52
  return docDataMatcher;
71
53
  }
72
- export function writeSSEHeaders(res) {
73
- res.writeHead(200, {
74
- /**
75
- * Use exact these headers to make is less likely
76
- * for people to have problems.
77
- * @link https://www.youtube.com/watch?v=0PcMuYGJPzM
78
- */
79
- 'Content-Type': 'text/event-stream; charset=utf-8',
80
- 'Connection': 'keep-alive',
81
- 'Cache-Control': 'no-cache',
82
- /**
83
- * Required for nginx
84
- * @link https://stackoverflow.com/q/61029079/3443137
85
- */
86
- 'X-Accel-Buffering': 'no'
87
- });
88
- res.flushHeaders();
89
- }
90
54
  export function docContainsServerOnlyFields(serverOnlyFields, doc) {
91
55
  var has = serverOnlyFields.find(field => {
92
56
  return typeof doc[field] !== 'undefined';
@@ -126,7 +90,7 @@ export function mergeServerDocumentFieldsMonad(serverOnlyFields) {
126
90
  }
127
91
 
128
92
  /**
129
- * $regex queries are dangerous because they can dos-attach the
93
+ * $regex queries are dangerous because they can dos-attack the server.
130
94
  *
131
95
  * @param selector
132
96
  */
@@ -1 +1 @@
1
- {"version":3,"file":"helper.js","names":["expressCors","flatClone","getQueryMatcher","normalizeMangoQuery","uniqueArray","setCors","server","path","cors","useCors","expressApp","options","origin","optionsSuccessStatus","blockPreviousVersionPaths","currentVersion","v","_loop","version","all","req","res","closeConnection","response","code","message","responseWrite","error","statusCode","set","write","JSON","stringify","end","addAuthMiddleware","authDataByRequest","WeakMap","auth","next","authData","authHandler","headers","err","defaultMatchingQuery","selector","skip","sort","getDocAllowedMatcher","endpoint","useQuery","queryModifier","collection","schema","jsonSchema","docDataMatcher","writeSSEHeaders","writeHead","flushHeaders","docContainsServerOnlyFields","serverOnlyFields","doc","has","find","field","removeServerOnlyFieldsMonad","serverOnlyFieldsStencil","_meta","undefined","_rev","_attachments","forEach","docData","Object","assign","mergeServerDocumentFieldsMonad","useFields","slice","clientDoc","serverDoc","ret","doesContainRegexQuerySelector","Array","isArray","found","item","entries","key","value"],"sources":["../../../../src/plugins/server/helper.ts"],"sourcesContent":["import { RxServer } from './rx-server';\nimport expressCors from 'cors';\nimport type {\n Request,\n Response,\n NextFunction\n} from 'express';\nimport { RxServerAuthData, RxServerEndpoint } from './types';\nimport {\n FilledMangoQuery,\n MangoQuerySelector,\n RxDocumentData,\n RxReplicationWriteToMasterRow,\n flatClone,\n getQueryMatcher,\n normalizeMangoQuery,\n uniqueArray\n} from 'rxdb/plugins/core';\n\nexport function setCors(\n server: RxServer<any>,\n path: string,\n cors?: string\n) {\n let useCors = cors;\n if (!useCors) {\n useCors = server.cors;\n }\n if (useCors) {\n server.expressApp.options('/' + path + '/*', expressCors({\n origin: useCors,\n // some legacy browsers (IE11, various SmartTVs) choke on 204\n optionsSuccessStatus: 200\n }));\n }\n}\n\n/**\n * \"block\" the previous version urls and send a 426 on them so that\n * the clients know they must update.\n */\nexport function blockPreviousVersionPaths(\n server: RxServer<any>,\n path: string,\n currentVersion: number\n\n) {\n let v = 0;\n while (v < currentVersion) {\n const version = v;\n server.expressApp.all('/' + path + '/' + version + '/*', (req, res) => {\n closeConnection(res, 426, 'Outdated version ' + version + ' (newest is ' + currentVersion + ')');\n });\n v++;\n }\n}\n\n\nexport async function closeConnection(response: Response, code: number, message: string) {\n const responseWrite = {\n code,\n error: true,\n message\n };\n response.statusCode = code;\n response.set(\"Connection\", \"close\");\n await response.write(JSON.stringify(responseWrite));\n response.end();\n}\n\n\nexport function addAuthMiddleware<AuthType>(\n server: RxServer<AuthType>,\n path: string,\n): WeakMap<Request, RxServerAuthData<AuthType>> {\n const authDataByRequest = new WeakMap<Request, RxServerAuthData<AuthType>>();\n async function auth(req: Request, res: Response, next: NextFunction) {\n try {\n const authData = await server.authHandler(req.headers);\n authDataByRequest.set(req, authData);\n next();\n } catch (err) {\n closeConnection(res, 401, 'Unauthorized');\n return;\n }\n }\n server.expressApp.all('/' + path + '/*', auth, function (req, res, next) {\n next();\n });\n return authDataByRequest;\n}\n\nconst defaultMatchingQuery: FilledMangoQuery<any> = {\n selector: {},\n skip: 0,\n sort: []\n} as const;\n\nexport function getDocAllowedMatcher<RxDocType, AuthType>(\n endpoint: RxServerEndpoint<AuthType, RxDocType>,\n authData: RxServerAuthData<AuthType>\n) {\n const useQuery: FilledMangoQuery<RxDocType> = endpoint.queryModifier ? endpoint.queryModifier(\n authData,\n normalizeMangoQuery(\n endpoint.collection.schema.jsonSchema,\n {}\n )\n ) : defaultMatchingQuery;\n const docDataMatcher = getQueryMatcher(endpoint.collection.schema.jsonSchema, useQuery);\n return docDataMatcher;\n}\n\nexport function writeSSEHeaders(res: Response) {\n res.writeHead(200, {\n /**\n * Use exact these headers to make is less likely\n * for people to have problems.\n * @link https://www.youtube.com/watch?v=0PcMuYGJPzM\n */\n 'Content-Type': 'text/event-stream; charset=utf-8',\n 'Connection': 'keep-alive',\n 'Cache-Control': 'no-cache',\n /**\n * Required for nginx\n * @link https://stackoverflow.com/q/61029079/3443137\n */\n 'X-Accel-Buffering': 'no'\n });\n res.flushHeaders();\n}\n\nexport function docContainsServerOnlyFields(\n serverOnlyFields: string[],\n doc: any\n) {\n const has = serverOnlyFields.find(field => {\n return typeof doc[field] !== 'undefined'\n });\n return has;\n}\n\nexport function removeServerOnlyFieldsMonad<RxDocType>(serverOnlyFields: string[]) {\n const serverOnlyFieldsStencil: any = {\n _meta: undefined,\n _rev: undefined,\n _attachments: undefined\n };\n serverOnlyFields.forEach(field => serverOnlyFieldsStencil[field] = undefined);\n return (\n docData?: RxDocType | RxDocumentData<RxDocType>\n ) => {\n if (!docData) {\n return docData;\n }\n return Object.assign({}, docData, serverOnlyFieldsStencil);\n }\n}\n\nexport function mergeServerDocumentFieldsMonad<RxDocType>(serverOnlyFields: string[]) {\n let useFields = serverOnlyFields.slice(0);\n // useFields.push('_rev');\n // useFields.push('_meta');\n // useFields.push('_attachments');\n useFields = uniqueArray(useFields);\n\n return (\n clientDoc: RxDocType | RxDocumentData<RxDocType>,\n serverDoc?: RxDocType | RxDocumentData<RxDocType>\n ) => {\n if (!serverDoc) {\n return clientDoc;\n }\n const ret = flatClone(clientDoc);\n useFields.forEach(field => {\n (ret as any)[field] = (serverDoc as any)[field];\n });\n return ret;\n }\n}\n\n\n/**\n * $regex queries are dangerous because they can dos-attach the \n * \n * @param selector \n */\nexport function doesContainRegexQuerySelector(selector: MangoQuerySelector<any> | any): boolean {\n if (!selector) {\n return false;\n }\n if (Array.isArray(selector)) {\n const found = !!selector.find(item => doesContainRegexQuerySelector(item));\n return found;\n }\n\n if (typeof selector !== 'object') {\n return false;\n }\n\n const entries = Object.entries(selector);\n for (const [key, value] of entries) {\n if (key === '$regex') {\n return true;\n } else {\n const has = doesContainRegexQuerySelector(value);\n if (has) {\n return true;\n }\n }\n }\n\n return false;\n}\n"],"mappings":"AACA,OAAOA,WAAW,MAAM,MAAM;AAO9B,SAKIC,SAAS,EACTC,eAAe,EACfC,mBAAmB,EACnBC,WAAW,QACR,mBAAmB;AAE1B,OAAO,SAASC,OAAOA,CACnBC,MAAqB,EACrBC,IAAY,EACZC,IAAa,EACf;EACE,IAAIC,OAAO,GAAGD,IAAI;EAClB,IAAI,CAACC,OAAO,EAAE;IACVA,OAAO,GAAGH,MAAM,CAACE,IAAI;EACzB;EACA,IAAIC,OAAO,EAAE;IACTH,MAAM,CAACI,UAAU,CAACC,OAAO,CAAC,GAAG,GAAGJ,IAAI,GAAG,IAAI,EAAEP,WAAW,CAAC;MACrDY,MAAM,EAAEH,OAAO;MACf;MACAI,oBAAoB,EAAE;IAC1B,CAAC,CAAC,CAAC;EACP;AACJ;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASC,yBAAyBA,CACrCR,MAAqB,EACrBC,IAAY,EACZQ,cAAsB,EAExB;EACE,IAAIC,CAAC,GAAG,CAAC;EAAC,IAAAC,KAAA,YAAAA,CAAA,EACiB;IACvB,IAAMC,OAAO,GAAGF,CAAC;IACjBV,MAAM,CAACI,UAAU,CAACS,GAAG,CAAC,GAAG,GAAGZ,IAAI,GAAG,GAAG,GAAGW,OAAO,GAAG,IAAI,EAAE,CAACE,GAAG,EAAEC,GAAG,KAAK;MACnEC,eAAe,CAACD,GAAG,EAAE,GAAG,EAAE,mBAAmB,GAAGH,OAAO,GAAG,cAAc,GAAGH,cAAc,GAAG,GAAG,CAAC;IACpG,CAAC,CAAC;IACFC,CAAC,EAAE;EACP,CAAC;EAND,OAAOA,CAAC,GAAGD,cAAc;IAAAE,KAAA;EAAA;AAO7B;AAGA,OAAO,eAAeK,eAAeA,CAACC,QAAkB,EAAEC,IAAY,EAAEC,OAAe,EAAE;EACrF,IAAMC,aAAa,GAAG;IAClBF,IAAI;IACJG,KAAK,EAAE,IAAI;IACXF;EACJ,CAAC;EACDF,QAAQ,CAACK,UAAU,GAAGJ,IAAI;EAC1BD,QAAQ,CAACM,GAAG,CAAC,YAAY,EAAE,OAAO,CAAC;EACnC,MAAMN,QAAQ,CAACO,KAAK,CAACC,IAAI,CAACC,SAAS,CAACN,aAAa,CAAC,CAAC;EACnDH,QAAQ,CAACU,GAAG,CAAC,CAAC;AAClB;AAGA,OAAO,SAASC,iBAAiBA,CAC7B5B,MAA0B,EAC1BC,IAAY,EACgC;EAC5C,IAAM4B,iBAAiB,GAAG,IAAIC,OAAO,CAAsC,CAAC;EAC5E,eAAeC,IAAIA,CAACjB,GAAY,EAAEC,GAAa,EAAEiB,IAAkB,EAAE;IACjE,IAAI;MACA,IAAMC,QAAQ,GAAG,MAAMjC,MAAM,CAACkC,WAAW,CAACpB,GAAG,CAACqB,OAAO,CAAC;MACtDN,iBAAiB,CAACN,GAAG,CAACT,GAAG,EAAEmB,QAAQ,CAAC;MACpCD,IAAI,CAAC,CAAC;IACV,CAAC,CAAC,OAAOI,GAAG,EAAE;MACVpB,eAAe,CAACD,GAAG,EAAE,GAAG,EAAE,cAAc,CAAC;MACzC;IACJ;EACJ;EACAf,MAAM,CAACI,UAAU,CAACS,GAAG,CAAC,GAAG,GAAGZ,IAAI,GAAG,IAAI,EAAE8B,IAAI,EAAE,UAAUjB,GAAG,EAAEC,GAAG,EAAEiB,IAAI,EAAE;IACrEA,IAAI,CAAC,CAAC;EACV,CAAC,CAAC;EACF,OAAOH,iBAAiB;AAC5B;AAEA,IAAMQ,oBAA2C,GAAG;EAChDC,QAAQ,EAAE,CAAC,CAAC;EACZC,IAAI,EAAE,CAAC;EACPC,IAAI,EAAE;AACV,CAAU;AAEV,OAAO,SAASC,oBAAoBA,CAChCC,QAA+C,EAC/CT,QAAoC,EACtC;EACE,IAAMU,QAAqC,GAAGD,QAAQ,CAACE,aAAa,GAAGF,QAAQ,CAACE,aAAa,CACzFX,QAAQ,EACRpC,mBAAmB,CACf6C,QAAQ,CAACG,UAAU,CAACC,MAAM,CAACC,UAAU,EACrC,CAAC,CACL,CACJ,CAAC,GAAGV,oBAAoB;EACxB,IAAMW,cAAc,GAAGpD,eAAe,CAAC8C,QAAQ,CAACG,UAAU,CAACC,MAAM,CAACC,UAAU,EAAEJ,QAAQ,CAAC;EACvF,OAAOK,cAAc;AACzB;AAEA,OAAO,SAASC,eAAeA,CAAClC,GAAa,EAAE;EAC3CA,GAAG,CAACmC,SAAS,CAAC,GAAG,EAAE;IACf;AACR;AACA;AACA;AACA;IACQ,cAAc,EAAE,kCAAkC;IAClD,YAAY,EAAE,YAAY;IAC1B,eAAe,EAAE,UAAU;IAC3B;AACR;AACA;AACA;IACQ,mBAAmB,EAAE;EACzB,CAAC,CAAC;EACFnC,GAAG,CAACoC,YAAY,CAAC,CAAC;AACtB;AAEA,OAAO,SAASC,2BAA2BA,CACvCC,gBAA0B,EAC1BC,GAAQ,EACV;EACE,IAAMC,GAAG,GAAGF,gBAAgB,CAACG,IAAI,CAACC,KAAK,IAAI;IACvC,OAAO,OAAOH,GAAG,CAACG,KAAK,CAAC,KAAK,WAAW;EAC5C,CAAC,CAAC;EACF,OAAOF,GAAG;AACd;AAEA,OAAO,SAASG,2BAA2BA,CAAYL,gBAA0B,EAAE;EAC/E,IAAMM,uBAA4B,GAAG;IACjCC,KAAK,EAAEC,SAAS;IAChBC,IAAI,EAAED,SAAS;IACfE,YAAY,EAAEF;EAClB,CAAC;EACDR,gBAAgB,CAACW,OAAO,CAACP,KAAK,IAAIE,uBAAuB,CAACF,KAAK,CAAC,GAAGI,SAAS,CAAC;EAC7E,OACII,OAA+C,IAC9C;IACD,IAAI,CAACA,OAAO,EAAE;MACV,OAAOA,OAAO;IAClB;IACA,OAAOC,MAAM,CAACC,MAAM,CAAC,CAAC,CAAC,EAAEF,OAAO,EAAEN,uBAAuB,CAAC;EAC9D,CAAC;AACL;AAEA,OAAO,SAASS,8BAA8BA,CAAYf,gBAA0B,EAAE;EAClF,IAAIgB,SAAS,GAAGhB,gBAAgB,CAACiB,KAAK,CAAC,CAAC,CAAC;EACzC;EACA;EACA;EACAD,SAAS,GAAGvE,WAAW,CAACuE,SAAS,CAAC;EAElC,OAAO,CACHE,SAAgD,EAChDC,SAAiD,KAChD;IACD,IAAI,CAACA,SAAS,EAAE;MACZ,OAAOD,SAAS;IACpB;IACA,IAAME,GAAG,GAAG9E,SAAS,CAAC4E,SAAS,CAAC;IAChCF,SAAS,CAACL,OAAO,CAACP,KAAK,IAAI;MACtBgB,GAAG,CAAShB,KAAK,CAAC,GAAIe,SAAS,CAASf,KAAK,CAAC;IACnD,CAAC,CAAC;IACF,OAAOgB,GAAG;EACd,CAAC;AACL;;AAGA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,6BAA6BA,CAACpC,QAAuC,EAAW;EAC5F,IAAI,CAACA,QAAQ,EAAE;IACX,OAAO,KAAK;EAChB;EACA,IAAIqC,KAAK,CAACC,OAAO,CAACtC,QAAQ,CAAC,EAAE;IACzB,IAAMuC,KAAK,GAAG,CAAC,CAACvC,QAAQ,CAACkB,IAAI,CAACsB,IAAI,IAAIJ,6BAA6B,CAACI,IAAI,CAAC,CAAC;IAC1E,OAAOD,KAAK;EAChB;EAEA,IAAI,OAAOvC,QAAQ,KAAK,QAAQ,EAAE;IAC9B,OAAO,KAAK;EAChB;EAEA,IAAMyC,OAAO,GAAGb,MAAM,CAACa,OAAO,CAACzC,QAAQ,CAAC;EACxC,KAAK,IAAM,CAAC0C,GAAG,EAAEC,KAAK,CAAC,IAAIF,OAAO,EAAE;IAChC,IAAIC,GAAG,KAAK,QAAQ,EAAE;MAClB,OAAO,IAAI;IACf,CAAC,MAAM;MACH,IAAMzB,GAAG,GAAGmB,6BAA6B,CAACO,KAAK,CAAC;MAChD,IAAI1B,GAAG,EAAE;QACL,OAAO,IAAI;MACf;IACJ;EACJ;EAEA,OAAO,KAAK;AAChB"}
1
+ {"version":3,"file":"helper.js","names":["flatClone","getQueryMatcher","normalizeMangoQuery","uniqueArray","setCors","server","path","cors","useCors","adapter","serverApp","blockPreviousVersionPaths","currentVersion","v","_loop","version","all","req","res","closeConnection","addAuthMiddleware","authDataByRequest","WeakMap","auth","next","authData","authHandler","headers","set","err","defaultMatchingQuery","selector","skip","sort","getDocAllowedMatcher","endpoint","useQuery","queryModifier","collection","schema","jsonSchema","docDataMatcher","docContainsServerOnlyFields","serverOnlyFields","doc","has","find","field","removeServerOnlyFieldsMonad","serverOnlyFieldsStencil","_meta","undefined","_rev","_attachments","forEach","docData","Object","assign","mergeServerDocumentFieldsMonad","useFields","slice","clientDoc","serverDoc","ret","doesContainRegexQuerySelector","Array","isArray","found","item","entries","key","value"],"sources":["../../../../src/plugins/server/helper.ts"],"sourcesContent":["import { RxServer } from './rx-server';\nimport type {\n Request,\n Response,\n NextFunction\n} from 'express';\nimport type { RxServerAdapter, RxServerAuthData, RxServerEndpoint } from './types';\nimport {\n FilledMangoQuery,\n MangoQuerySelector,\n RxDocumentData,\n flatClone,\n getQueryMatcher,\n normalizeMangoQuery,\n uniqueArray\n} from 'rxdb/plugins/core';\n\nexport function setCors(\n server: RxServer<any, any>,\n path: string,\n cors?: string\n) {\n let useCors = cors;\n if (!useCors) {\n useCors = server.cors;\n }\n if (useCors) {\n server.adapter.setCors(server.serverApp, path, useCors);\n }\n}\n\n/**\n * \"block\" the previous version urls and send a 426 on them so that\n * the clients know they must update.\n */\nexport function blockPreviousVersionPaths(\n server: RxServer<any, any>,\n path: string,\n currentVersion: number\n\n) {\n let v = 0;\n while (v < currentVersion) {\n const version = v;\n server.adapter.all(server.serverApp, '/' + path + '/' + version + '/*', (req, res) => {\n server.adapter.closeConnection(res, 426, 'Outdated version ' + version + ' (newest is ' + currentVersion + ')');\n });\n v++;\n }\n}\n\n\nexport function addAuthMiddleware<AuthType>(\n server: RxServer<any, AuthType>,\n path: string,\n): WeakMap<Request, RxServerAuthData<AuthType>> {\n const authDataByRequest = new WeakMap<Request, RxServerAuthData<AuthType>>();\n async function auth(req: any, res: any, next: NextFunction) {\n try {\n const authData = await server.authHandler(req.headers);\n authDataByRequest.set(req, authData);\n next();\n } catch (err) {\n server.adapter.closeConnection(res, 401, 'Unauthorized');\n return;\n }\n }\n server.adapter.all(server.serverApp, '/' + path + '/*', auth);\n return authDataByRequest;\n}\n\nconst defaultMatchingQuery: FilledMangoQuery<any> = {\n selector: {},\n skip: 0,\n sort: []\n} as const;\n\nexport function getDocAllowedMatcher<RxDocType, AuthType>(\n endpoint: RxServerEndpoint<AuthType, RxDocType>,\n authData: RxServerAuthData<AuthType>\n) {\n const useQuery: FilledMangoQuery<RxDocType> = endpoint.queryModifier ? endpoint.queryModifier(\n authData,\n normalizeMangoQuery(\n endpoint.collection.schema.jsonSchema,\n {}\n )\n ) : defaultMatchingQuery;\n const docDataMatcher = getQueryMatcher(endpoint.collection.schema.jsonSchema, useQuery);\n return docDataMatcher;\n}\n\n\nexport function docContainsServerOnlyFields(\n serverOnlyFields: string[],\n doc: any\n) {\n const has = serverOnlyFields.find(field => {\n return typeof doc[field] !== 'undefined'\n });\n return has;\n}\n\nexport function removeServerOnlyFieldsMonad<RxDocType>(serverOnlyFields: string[]) {\n const serverOnlyFieldsStencil: any = {\n _meta: undefined,\n _rev: undefined,\n _attachments: undefined\n };\n serverOnlyFields.forEach(field => serverOnlyFieldsStencil[field] = undefined);\n return (\n docData?: RxDocType | RxDocumentData<RxDocType>\n ) => {\n if (!docData) {\n return docData;\n }\n return Object.assign({}, docData, serverOnlyFieldsStencil);\n }\n}\n\nexport function mergeServerDocumentFieldsMonad<RxDocType>(serverOnlyFields: string[]) {\n let useFields = serverOnlyFields.slice(0);\n // useFields.push('_rev');\n // useFields.push('_meta');\n // useFields.push('_attachments');\n useFields = uniqueArray(useFields);\n\n return (\n clientDoc: RxDocType | RxDocumentData<RxDocType>,\n serverDoc?: RxDocType | RxDocumentData<RxDocType>\n ) => {\n if (!serverDoc) {\n return clientDoc;\n }\n const ret = flatClone(clientDoc);\n useFields.forEach(field => {\n (ret as any)[field] = (serverDoc as any)[field];\n });\n return ret;\n }\n}\n\n\n/**\n * $regex queries are dangerous because they can dos-attack the server.\n * \n * @param selector \n */\nexport function doesContainRegexQuerySelector(selector: MangoQuerySelector<any> | any): boolean {\n if (!selector) {\n return false;\n }\n if (Array.isArray(selector)) {\n const found = !!selector.find(item => doesContainRegexQuerySelector(item));\n return found;\n }\n\n if (typeof selector !== 'object') {\n return false;\n }\n\n const entries = Object.entries(selector);\n for (const [key, value] of entries) {\n if (key === '$regex') {\n return true;\n } else {\n const has = doesContainRegexQuerySelector(value);\n if (has) {\n return true;\n }\n }\n }\n\n return false;\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1,30 +1,21 @@
1
1
  import { ensureNotFalsy, flatClone } from 'rxdb/plugins/utils';
2
2
  import { RxServer } from "./rx-server.js";
3
- import express from 'express';
4
3
  export * from "./types.js";
5
4
  export * from "./endpoint-replication.js";
6
5
  export * from "./endpoint-rest.js";
7
6
  export * from "./helper.js";
8
- export async function startRxServer(options) {
7
+ export async function createRxServer(options) {
9
8
  options = flatClone(options);
10
9
  if (!options.serverApp) {
11
- var app = express();
12
- options.serverApp = app;
10
+ options.serverApp = await options.adapter.create();
13
11
  }
14
- options.serverApp.use(express.json());
15
- var httpServer = await new Promise((res, rej) => {
16
- var hostname = options.hostname ? options.hostname : 'localhost';
17
- var ret = ensureNotFalsy(options.serverApp).listen(options.port, hostname, () => {
18
- res(ret);
19
- });
20
- });
21
12
  var authHandler = options.authHandler ? options.authHandler : () => {
22
13
  return {
23
14
  data: {},
24
15
  validUntil: Date.now() * 2
25
16
  };
26
17
  };
27
- var server = new RxServer(options.database, authHandler, httpServer, ensureNotFalsy(options.serverApp), options.cors);
18
+ var server = new RxServer(options, authHandler, ensureNotFalsy(options.serverApp), options.cors);
28
19
  return server;
29
20
  }
30
21
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["ensureNotFalsy","flatClone","RxServer","express","startRxServer","options","serverApp","app","use","json","httpServer","Promise","res","rej","hostname","ret","listen","port","authHandler","data","validUntil","Date","now","server","database","cors"],"sources":["../../../../src/plugins/server/index.ts"],"sourcesContent":["import { ensureNotFalsy, flatClone } from 'rxdb/plugins/utils';\nimport { RxServer } from './rx-server.ts';\nimport { RxServerAuthHandler, RxServerOptions } from './types.ts';\nimport express from 'express';\nimport {\n Server as HttpServer\n} from 'http';\n\nexport * from './types.ts';\nexport * from './endpoint-replication.ts';\nexport * from './endpoint-rest.ts';\nexport * from './helper.ts';\n\nexport async function startRxServer<AuthType>(options: RxServerOptions<AuthType>): Promise<RxServer<AuthType>> {\n options = flatClone(options);\n if (!options.serverApp) {\n const app = express();\n options.serverApp = app;\n }\n\n options.serverApp.use(express.json());\n\n\n const httpServer: HttpServer = await new Promise((res, rej) => {\n const hostname = options.hostname ? options.hostname : 'localhost';\n const ret = ensureNotFalsy(options.serverApp).listen(options.port, hostname, () => {\n res(ret);\n });\n });\n\n const authHandler: RxServerAuthHandler<AuthType> = options.authHandler ? options.authHandler : () => {\n return {\n data: {} as any,\n validUntil: Date.now() * 2\n };\n };\n\n const server = new RxServer<AuthType>(\n options.database,\n authHandler,\n httpServer,\n ensureNotFalsy(options.serverApp),\n options.cors\n );\n\n return server;\n}\n"],"mappings":"AAAA,SAASA,cAAc,EAAEC,SAAS,QAAQ,oBAAoB;AAC9D,SAASC,QAAQ,QAAQ,gBAAgB;AAEzC,OAAOC,OAAO,MAAM,SAAS;AAK7B,cAAc,YAAY;AAC1B,cAAc,2BAA2B;AACzC,cAAc,oBAAoB;AAClC,cAAc,aAAa;AAE3B,OAAO,eAAeC,aAAaA,CAAWC,OAAkC,EAA+B;EAC3GA,OAAO,GAAGJ,SAAS,CAACI,OAAO,CAAC;EAC5B,IAAI,CAACA,OAAO,CAACC,SAAS,EAAE;IACpB,IAAMC,GAAG,GAAGJ,OAAO,CAAC,CAAC;IACrBE,OAAO,CAACC,SAAS,GAAGC,GAAG;EAC3B;EAEAF,OAAO,CAACC,SAAS,CAACE,GAAG,CAACL,OAAO,CAACM,IAAI,CAAC,CAAC,CAAC;EAGrC,IAAMC,UAAsB,GAAG,MAAM,IAAIC,OAAO,CAAC,CAACC,GAAG,EAAEC,GAAG,KAAK;IAC3D,IAAMC,QAAQ,GAAGT,OAAO,CAACS,QAAQ,GAAGT,OAAO,CAACS,QAAQ,GAAG,WAAW;IAClE,IAAMC,GAAG,GAAGf,cAAc,CAACK,OAAO,CAACC,SAAS,CAAC,CAACU,MAAM,CAACX,OAAO,CAACY,IAAI,EAAEH,QAAQ,EAAE,MAAM;MAC/EF,GAAG,CAACG,GAAG,CAAC;IACZ,CAAC,CAAC;EACN,CAAC,CAAC;EAEF,IAAMG,WAA0C,GAAGb,OAAO,CAACa,WAAW,GAAGb,OAAO,CAACa,WAAW,GAAG,MAAM;IACjG,OAAO;MACHC,IAAI,EAAE,CAAC,CAAQ;MACfC,UAAU,EAAEC,IAAI,CAACC,GAAG,CAAC,CAAC,GAAG;IAC7B,CAAC;EACL,CAAC;EAED,IAAMC,MAAM,GAAG,IAAIrB,QAAQ,CACvBG,OAAO,CAACmB,QAAQ,EAChBN,WAAW,EACXR,UAAU,EACVV,cAAc,CAACK,OAAO,CAACC,SAAS,CAAC,EACjCD,OAAO,CAACoB,IACZ,CAAC;EAED,OAAOF,MAAM;AACjB"}
1
+ {"version":3,"file":"index.js","names":["ensureNotFalsy","flatClone","RxServer","createRxServer","options","serverApp","adapter","create","authHandler","data","validUntil","Date","now","server","cors"],"sources":["../../../../src/plugins/server/index.ts"],"sourcesContent":["import { ensureNotFalsy, flatClone } from 'rxdb/plugins/utils';\nimport { RxServer } from './rx-server.ts';\nimport { RxServerAuthHandler, RxServerOptions } from './types.ts';\n\nexport * from './types.ts';\nexport * from './endpoint-replication.ts';\nexport * from './endpoint-rest.ts';\nexport * from './helper.ts';\n\nexport async function createRxServer<ServerAdapterType, AuthType>(\n options: RxServerOptions<ServerAdapterType, AuthType>\n): Promise<RxServer<ServerAdapterType, AuthType>> {\n options = flatClone(options);\n if (!options.serverApp) {\n options.serverApp = await options.adapter.create();\n }\n const authHandler: RxServerAuthHandler<AuthType> = options.authHandler ? options.authHandler : () => {\n return {\n data: {} as any,\n validUntil: Date.now() * 2\n };\n };\n\n const server = new RxServer<ServerAdapterType, AuthType>(\n options,\n authHandler,\n ensureNotFalsy(options.serverApp),\n options.cors\n );\n\n return server;\n}\n"],"mappings":"AAAA,SAASA,cAAc,EAAEC,SAAS,QAAQ,oBAAoB;AAC9D,SAASC,QAAQ,QAAQ,gBAAgB;AAGzC,cAAc,YAAY;AAC1B,cAAc,2BAA2B;AACzC,cAAc,oBAAoB;AAClC,cAAc,aAAa;AAE3B,OAAO,eAAeC,cAAcA,CAChCC,OAAqD,EACP;EAC9CA,OAAO,GAAGH,SAAS,CAACG,OAAO,CAAC;EAC5B,IAAI,CAACA,OAAO,CAACC,SAAS,EAAE;IACpBD,OAAO,CAACC,SAAS,GAAG,MAAMD,OAAO,CAACE,OAAO,CAACC,MAAM,CAAC,CAAC;EACtD;EACA,IAAMC,WAA0C,GAAGJ,OAAO,CAACI,WAAW,GAAGJ,OAAO,CAACI,WAAW,GAAG,MAAM;IACjG,OAAO;MACHC,IAAI,EAAE,CAAC,CAAQ;MACfC,UAAU,EAAEC,IAAI,CAACC,GAAG,CAAC,CAAC,GAAG;IAC7B,CAAC;EACL,CAAC;EAED,IAAMC,MAAM,GAAG,IAAIX,QAAQ,CACvBE,OAAO,EACPI,WAAW,EACXR,cAAc,CAACI,OAAO,CAACC,SAAS,CAAC,EACjCD,OAAO,CAACU,IACZ,CAAC;EAED,OAAOD,MAAM;AACjB","ignoreList":[]}
@@ -1,44 +1,47 @@
1
1
  import { RxServerReplicationEndpoint } from "./endpoint-replication.js";
2
2
  import { RxServerRestEndpoint } from "./endpoint-rest.js";
3
3
  export var RxServer = /*#__PURE__*/function () {
4
- function RxServer(database, authHandler, httpServer, expressApp, cors = '*') {
4
+ function RxServer(options, authHandler, serverApp, cors = '*') {
5
5
  this.endpoints = [];
6
6
  this.closeFn = (() => this.close()).bind(this);
7
- this.database = database;
7
+ this.options = options;
8
8
  this.authHandler = authHandler;
9
- this.httpServer = httpServer;
10
- this.expressApp = expressApp;
9
+ this.serverApp = serverApp;
11
10
  this.cors = cors;
12
- database.onDestroy.push(this.closeFn);
11
+ this.database = options.database;
12
+ this.adapter = options.adapter;
13
+ options.database.onDestroy.push(this.closeFn);
13
14
  }
14
15
  var _proto = RxServer.prototype;
15
- _proto.addReplicationEndpoint = async function addReplicationEndpoint(opts) {
16
+ _proto.ensureNotStarted = function ensureNotStarted() {
17
+ if (this.listenPromise) {
18
+ throw new Error('This operation cannot be run after the RxServer has been started already');
19
+ }
20
+ };
21
+ _proto.addReplicationEndpoint = function addReplicationEndpoint(opts) {
22
+ this.ensureNotStarted();
16
23
  var endpoint = new RxServerReplicationEndpoint(this, opts.name, opts.collection, opts.queryModifier ? opts.queryModifier : (_a, q) => q, opts.changeValidator ? opts.changeValidator : () => true, opts.serverOnlyFields ? opts.serverOnlyFields : [], opts.cors);
17
24
  this.endpoints.push(endpoint);
18
25
  return endpoint;
19
26
  };
20
- _proto.addRestEndpoint = async function addRestEndpoint(opts) {
27
+ _proto.addRestEndpoint = function addRestEndpoint(opts) {
28
+ this.ensureNotStarted();
21
29
  var endpoint = new RxServerRestEndpoint(this, opts.name, opts.collection, opts.queryModifier ? opts.queryModifier : (_a, q) => q, opts.changeValidator ? opts.changeValidator : () => true, opts.serverOnlyFields ? opts.serverOnlyFields : [], opts.cors);
22
30
  this.endpoints.push(endpoint);
23
31
  return endpoint;
24
32
  };
33
+ _proto.start = async function start() {
34
+ this.ensureNotStarted();
35
+ var hostname = this.options.hostname ? this.options.hostname : 'localhost';
36
+ this.listenPromise = this.options.adapter.listen(this.serverApp, this.options.port, hostname);
37
+ return this.listenPromise;
38
+ };
25
39
  _proto.close = async function close() {
26
40
  this.database.onDestroy = this.database.onDestroy.filter(fn => fn !== this.closeFn);
27
- await new Promise((res, rej) => {
28
- this.httpServer.close(err => {
29
- if (err) {
30
- rej(err);
31
- } else {
32
- res();
33
- }
34
- });
35
- /**
36
- * By default it will await all ongoing connections
37
- * before it closes. So we have to close it directly.
38
- * @link https://stackoverflow.com/a/36830072/3443137
39
- */
40
- setImmediate(() => this.httpServer.emit('close'));
41
- });
41
+ if (this.listenPromise) {
42
+ await this.listenPromise;
43
+ await this.options.adapter.close(this.serverApp);
44
+ }
42
45
  };
43
46
  return RxServer;
44
47
  }();
@@ -1 +1 @@
1
- {"version":3,"file":"rx-server.js","names":["RxServerReplicationEndpoint","RxServerRestEndpoint","RxServer","database","authHandler","httpServer","expressApp","cors","endpoints","closeFn","close","bind","onDestroy","push","_proto","prototype","addReplicationEndpoint","opts","endpoint","name","collection","queryModifier","_a","q","changeValidator","serverOnlyFields","addRestEndpoint","filter","fn","Promise","res","rej","err","setImmediate","emit"],"sources":["../../../../src/plugins/server/rx-server.ts"],"sourcesContent":["import type {\n RxCollection,\n RxDatabase\n} from 'rxdb/plugins/core';\nimport { RxServerReplicationEndpoint } from './endpoint-replication.ts';\nimport type {\n RxServerAuthHandler,\n RxServerChangeValidator,\n RxServerEndpoint,\n RxServerQueryModifier\n} from './types.ts';\nimport {\n Server as HttpServer\n} from 'http';\nimport { Express } from 'express';\nimport { RxServerRestEndpoint } from './endpoint-rest.ts';\n\nexport class RxServer<AuthType> {\n public readonly endpoints: RxServerEndpoint<AuthType, any>[] = [];\n\n private closeFn = (() => this.close()).bind(this);\n\n constructor(\n public readonly database: RxDatabase,\n public readonly authHandler: RxServerAuthHandler<AuthType>,\n public readonly httpServer: HttpServer,\n public readonly expressApp: Express,\n public readonly cors: string = '*'\n ) {\n database.onDestroy.push(this.closeFn);\n }\n\n public async addReplicationEndpoint<RxDocType>(opts: {\n name: string,\n collection: RxCollection<RxDocType>,\n queryModifier?: RxServerQueryModifier<AuthType, RxDocType>,\n changeValidator?: RxServerChangeValidator<AuthType, RxDocType>,\n /**\n * Set a origin for allowed CORS requests.\n * Overwrites the cors option of the server.\n * [default='*']\n */\n cors?: '*' | string,\n serverOnlyFields?: string[]\n }) {\n const endpoint = new RxServerReplicationEndpoint(\n this,\n opts.name,\n opts.collection,\n opts.queryModifier ? opts.queryModifier : (_a, q) => q,\n opts.changeValidator ? opts.changeValidator : () => true,\n opts.serverOnlyFields ? opts.serverOnlyFields : [],\n opts.cors\n );\n this.endpoints.push(endpoint);\n return endpoint;\n }\n\n public async addRestEndpoint<RxDocType>(opts: {\n name: string,\n collection: RxCollection<RxDocType>,\n queryModifier?: RxServerQueryModifier<AuthType, RxDocType>,\n changeValidator?: RxServerChangeValidator<AuthType, RxDocType>,\n /**\n * Set a origin for allowed CORS requests.\n * Overwrites the cors option of the server.\n * [default='*']\n */\n cors?: '*' | string,\n serverOnlyFields?: string[]\n }) {\n const endpoint = new RxServerRestEndpoint(\n this,\n opts.name,\n opts.collection,\n opts.queryModifier ? opts.queryModifier : (_a, q) => q,\n opts.changeValidator ? opts.changeValidator : () => true,\n opts.serverOnlyFields ? opts.serverOnlyFields : [],\n opts.cors\n );\n this.endpoints.push(endpoint);\n return endpoint;\n }\n\n async close() {\n this.database.onDestroy = this.database.onDestroy.filter(fn => fn !== this.closeFn);\n await new Promise<void>((res, rej) => {\n this.httpServer.close((err) => {\n if (err) { rej(err); } else { res(); }\n });\n /**\n * By default it will await all ongoing connections\n * before it closes. So we have to close it directly.\n * @link https://stackoverflow.com/a/36830072/3443137\n */\n setImmediate(() => this.httpServer.emit('close'));\n });\n\n }\n}\n"],"mappings":"AAIA,SAASA,2BAA2B,QAAQ,2BAA2B;AAWvE,SAASC,oBAAoB,QAAQ,oBAAoB;AAEzD,WAAaC,QAAQ;EAKjB,SAAAA,SACoBC,QAAoB,EACpBC,WAA0C,EAC1CC,UAAsB,EACtBC,UAAmB,EACnBC,IAAY,GAAG,GAAG,EACpC;IAAA,KAVcC,SAAS,GAAsC,EAAE;IAAA,KAEzDC,OAAO,GAAG,CAAC,MAAM,IAAI,CAACC,KAAK,CAAC,CAAC,EAAEC,IAAI,CAAC,IAAI,CAAC;IAAA,KAG7BR,QAAoB,GAApBA,QAAoB;IAAA,KACpBC,WAA0C,GAA1CA,WAA0C;IAAA,KAC1CC,UAAsB,GAAtBA,UAAsB;IAAA,KACtBC,UAAmB,GAAnBA,UAAmB;IAAA,KACnBC,IAAY,GAAZA,IAAY;IAE5BJ,QAAQ,CAACS,SAAS,CAACC,IAAI,CAAC,IAAI,CAACJ,OAAO,CAAC;EACzC;EAAC,IAAAK,MAAA,GAAAZ,QAAA,CAAAa,SAAA;EAAAD,MAAA,CAEYE,sBAAsB,GAAnC,eAAAA,uBAA+CC,IAY9C,EAAE;IACC,IAAMC,QAAQ,GAAG,IAAIlB,2BAA2B,CAC5C,IAAI,EACJiB,IAAI,CAACE,IAAI,EACTF,IAAI,CAACG,UAAU,EACfH,IAAI,CAACI,aAAa,GAAGJ,IAAI,CAACI,aAAa,GAAG,CAACC,EAAE,EAAEC,CAAC,KAAKA,CAAC,EACtDN,IAAI,CAACO,eAAe,GAAGP,IAAI,CAACO,eAAe,GAAG,MAAM,IAAI,EACxDP,IAAI,CAACQ,gBAAgB,GAAGR,IAAI,CAACQ,gBAAgB,GAAG,EAAE,EAClDR,IAAI,CAACV,IACT,CAAC;IACD,IAAI,CAACC,SAAS,CAACK,IAAI,CAACK,QAAQ,CAAC;IAC7B,OAAOA,QAAQ;EACnB,CAAC;EAAAJ,MAAA,CAEYY,eAAe,GAA5B,eAAAA,gBAAwCT,IAYvC,EAAE;IACC,IAAMC,QAAQ,GAAG,IAAIjB,oBAAoB,CACrC,IAAI,EACJgB,IAAI,CAACE,IAAI,EACTF,IAAI,CAACG,UAAU,EACfH,IAAI,CAACI,aAAa,GAAGJ,IAAI,CAACI,aAAa,GAAG,CAACC,EAAE,EAAEC,CAAC,KAAKA,CAAC,EACtDN,IAAI,CAACO,eAAe,GAAGP,IAAI,CAACO,eAAe,GAAG,MAAM,IAAI,EACxDP,IAAI,CAACQ,gBAAgB,GAAGR,IAAI,CAACQ,gBAAgB,GAAG,EAAE,EAClDR,IAAI,CAACV,IACT,CAAC;IACD,IAAI,CAACC,SAAS,CAACK,IAAI,CAACK,QAAQ,CAAC;IAC7B,OAAOA,QAAQ;EACnB,CAAC;EAAAJ,MAAA,CAEKJ,KAAK,GAAX,eAAAA,MAAA,EAAc;IACV,IAAI,CAACP,QAAQ,CAACS,SAAS,GAAG,IAAI,CAACT,QAAQ,CAACS,SAAS,CAACe,MAAM,CAACC,EAAE,IAAIA,EAAE,KAAK,IAAI,CAACnB,OAAO,CAAC;IACnF,MAAM,IAAIoB,OAAO,CAAO,CAACC,GAAG,EAAEC,GAAG,KAAK;MAClC,IAAI,CAAC1B,UAAU,CAACK,KAAK,CAAEsB,GAAG,IAAK;QAC3B,IAAIA,GAAG,EAAE;UAAED,GAAG,CAACC,GAAG,CAAC;QAAE,CAAC,MAAM;UAAEF,GAAG,CAAC,CAAC;QAAE;MACzC,CAAC,CAAC;MACF;AACZ;AACA;AACA;AACA;MACYG,YAAY,CAAC,MAAM,IAAI,CAAC5B,UAAU,CAAC6B,IAAI,CAAC,OAAO,CAAC,CAAC;IACrD,CAAC,CAAC;EAEN,CAAC;EAAA,OAAAhC,QAAA;AAAA"}
1
+ {"version":3,"file":"rx-server.js","names":["RxServerReplicationEndpoint","RxServerRestEndpoint","RxServer","options","authHandler","serverApp","cors","endpoints","closeFn","close","bind","database","adapter","onDestroy","push","_proto","prototype","ensureNotStarted","listenPromise","Error","addReplicationEndpoint","opts","endpoint","name","collection","queryModifier","_a","q","changeValidator","serverOnlyFields","addRestEndpoint","start","hostname","listen","port","filter","fn"],"sources":["../../../../src/plugins/server/rx-server.ts"],"sourcesContent":["import type {\n RxCollection,\n RxDatabase\n} from 'rxdb/plugins/core';\nimport { RxServerReplicationEndpoint } from './endpoint-replication.ts';\nimport type {\n RxServerAdapter,\n RxServerAuthHandler,\n RxServerChangeValidator,\n RxServerEndpoint,\n RxServerOptions,\n RxServerQueryModifier\n} from './types.ts';\nimport { RxServerRestEndpoint } from './endpoint-rest.ts';\n\nexport class RxServer<ServerAppType, AuthType> {\n public readonly endpoints: RxServerEndpoint<AuthType, any>[] = [];\n\n private closeFn = (() => this.close()).bind(this);\n public listenPromise?: Promise<void>;\n\n public readonly database: RxDatabase;\n public readonly adapter: RxServerAdapter<ServerAppType>;\n\n constructor(\n public readonly options: RxServerOptions<ServerAppType, AuthType>,\n public readonly authHandler: RxServerAuthHandler<AuthType>,\n public readonly serverApp: ServerAppType,\n public readonly cors: string = '*'\n ) {\n this.database = options.database;\n this.adapter = options.adapter;\n options.database.onDestroy.push(this.closeFn);\n }\n\n private ensureNotStarted() {\n if (this.listenPromise) {\n throw new Error('This operation cannot be run after the RxServer has been started already');\n }\n\n }\n\n public addReplicationEndpoint<RxDocType>(opts: {\n name: string,\n collection: RxCollection<RxDocType>,\n queryModifier?: RxServerQueryModifier<AuthType, RxDocType>,\n changeValidator?: RxServerChangeValidator<AuthType, RxDocType>,\n /**\n * Set a origin for allowed CORS requests.\n * Overwrites the cors option of the server.\n * [default='*']\n */\n cors?: '*' | string,\n serverOnlyFields?: string[]\n }) {\n this.ensureNotStarted();\n const endpoint = new RxServerReplicationEndpoint(\n this,\n opts.name,\n opts.collection,\n opts.queryModifier ? opts.queryModifier : (_a, q) => q,\n opts.changeValidator ? opts.changeValidator : () => true,\n opts.serverOnlyFields ? opts.serverOnlyFields : [],\n opts.cors\n );\n this.endpoints.push(endpoint);\n return endpoint;\n }\n\n public addRestEndpoint<RxDocType>(opts: {\n name: string,\n collection: RxCollection<RxDocType>,\n queryModifier?: RxServerQueryModifier<AuthType, RxDocType>,\n changeValidator?: RxServerChangeValidator<AuthType, RxDocType>,\n /**\n * Set a origin for allowed CORS requests.\n * Overwrites the cors option of the server.\n * [default='*']\n */\n cors?: '*' | string,\n serverOnlyFields?: string[]\n }) {\n this.ensureNotStarted();\n const endpoint = new RxServerRestEndpoint(\n this,\n opts.name,\n opts.collection,\n opts.queryModifier ? opts.queryModifier : (_a, q) => q,\n opts.changeValidator ? opts.changeValidator : () => true,\n opts.serverOnlyFields ? opts.serverOnlyFields : [],\n opts.cors\n );\n this.endpoints.push(endpoint);\n return endpoint;\n }\n\n async start() {\n this.ensureNotStarted();\n const hostname = this.options.hostname ? this.options.hostname : 'localhost';\n this.listenPromise = this.options.adapter.listen(this.serverApp, this.options.port, hostname);\n return this.listenPromise;\n }\n\n async close() {\n this.database.onDestroy = this.database.onDestroy.filter(fn => fn !== this.closeFn);\n if (this.listenPromise) {\n await this.listenPromise;\n await this.options.adapter.close(this.serverApp);\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}