remult 0.14.7 → 0.14.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.
Files changed (152) hide show
  1. package/LICENSE +21 -0
  2. package/esm/assign.d.ts +1 -0
  3. package/esm/assign.js +5 -0
  4. package/esm/classType.d.ts +3 -0
  5. package/esm/classType.js +1 -0
  6. package/esm/graphql.d.ts +5 -0
  7. package/esm/graphql.js +102 -0
  8. package/esm/index.d.ts +36 -0
  9. package/esm/index.js +30 -0
  10. package/esm/inputTypes.d.ts +9 -0
  11. package/esm/inputTypes.js +9 -0
  12. package/esm/postgres/index.d.ts +2 -0
  13. package/esm/postgres/index.js +2 -0
  14. package/esm/postgres/postgres-data-provider.d.ts +28 -0
  15. package/esm/postgres/postgres-data-provider.js +97 -0
  16. package/esm/postgres/schema-builder.d.ts +15 -0
  17. package/esm/postgres/schema-builder.js +128 -0
  18. package/esm/remult-express.d.ts +5 -0
  19. package/esm/remult-express.js +16 -0
  20. package/esm/remult-knex/index.d.ts +51 -0
  21. package/esm/remult-knex/index.js +381 -0
  22. package/esm/remult-middleware.d.ts +2 -0
  23. package/esm/remult-middleware.js +63 -0
  24. package/esm/remult-mongo.d.ts +9 -0
  25. package/esm/remult-mongo.js +220 -0
  26. package/esm/server/JsonEntityFileStorage.d.ts +7 -0
  27. package/esm/server/JsonEntityFileStorage.js +20 -0
  28. package/esm/server/expressBridge.d.ts +140 -0
  29. package/esm/server/expressBridge.js +668 -0
  30. package/esm/server/index.d.ts +4 -0
  31. package/esm/server/index.js +4 -0
  32. package/esm/server/register-actions-on-server.d.ts +3 -0
  33. package/esm/server/register-actions-on-server.js +24 -0
  34. package/esm/server/register-entities-on-server.d.ts +3 -0
  35. package/esm/server/register-entities-on-server.js +15 -0
  36. package/esm/src/__EntityValueProvider.d.ts +10 -0
  37. package/esm/src/__EntityValueProvider.js +1 -0
  38. package/esm/src/__RowsOfDataForTesting.d.ts +3 -0
  39. package/esm/src/__RowsOfDataForTesting.js +1 -0
  40. package/esm/src/backend-tests/backend-database-test-setup.backend-spec.d.ts +5 -0
  41. package/esm/src/backend-tests/backend-database-test-setup.backend-spec.js +113 -0
  42. package/esm/src/backend-tests/my-test.backend-spec.d.ts +1 -0
  43. package/esm/src/backend-tests/my-test.backend-spec.js +49 -0
  44. package/esm/src/column-interfaces.d.ts +95 -0
  45. package/esm/src/column-interfaces.js +7 -0
  46. package/esm/src/column.d.ts +49 -0
  47. package/esm/src/column.js +133 -0
  48. package/esm/src/context.d.ts +124 -0
  49. package/esm/src/context.js +285 -0
  50. package/esm/src/data-api.d.ts +33 -0
  51. package/esm/src/data-api.js +204 -0
  52. package/esm/src/data-interfaces.d.ts +37 -0
  53. package/esm/src/data-interfaces.js +12 -0
  54. package/esm/src/data-providers/array-entity-data-provider.d.ts +22 -0
  55. package/esm/src/data-providers/array-entity-data-provider.js +264 -0
  56. package/esm/src/data-providers/in-memory-database.d.ts +9 -0
  57. package/esm/src/data-providers/in-memory-database.js +16 -0
  58. package/esm/src/data-providers/json-data-provider.d.ts +12 -0
  59. package/esm/src/data-providers/json-data-provider.js +52 -0
  60. package/esm/src/data-providers/rest-data-provider.d.ts +35 -0
  61. package/esm/src/data-providers/rest-data-provider.js +188 -0
  62. package/esm/src/data-providers/sql-database.d.ts +16 -0
  63. package/esm/src/data-providers/sql-database.js +261 -0
  64. package/esm/src/data-providers/web-sql-data-provider.d.ts +18 -0
  65. package/esm/src/data-providers/web-sql-data-provider.js +121 -0
  66. package/esm/src/entity.d.ts +82 -0
  67. package/esm/src/entity.js +1 -0
  68. package/esm/src/filter/filter-consumer-bridge-to-sql-request.d.ts +50 -0
  69. package/esm/src/filter/filter-consumer-bridge-to-sql-request.js +139 -0
  70. package/esm/src/filter/filter-consumer-bridge-to-url-builder.d.ts +1 -0
  71. package/esm/src/filter/filter-consumer-bridge-to-url-builder.js +1 -0
  72. package/esm/src/filter/filter-interfaces.d.ts +85 -0
  73. package/esm/src/filter/filter-interfaces.js +467 -0
  74. package/esm/src/id-entity.d.ts +4 -0
  75. package/esm/src/id-entity.js +8 -0
  76. package/esm/src/remult3/RepositoryImplementation.d.ts +326 -0
  77. package/esm/src/remult3/RepositoryImplementation.js +1806 -0
  78. package/esm/src/remult3/index.d.ts +2 -0
  79. package/esm/src/remult3/index.js +2 -0
  80. package/esm/src/remult3/remult3.d.ts +312 -0
  81. package/esm/src/remult3/remult3.js +1 -0
  82. package/esm/src/server-action.d.ts +70 -0
  83. package/esm/src/server-action.js +365 -0
  84. package/esm/src/shared-tests/db-tests-setup.d.ts +23 -0
  85. package/esm/src/shared-tests/db-tests-setup.js +66 -0
  86. package/esm/src/shared-tests/db-tests.db-tests.d.ts +26 -0
  87. package/esm/src/shared-tests/db-tests.db-tests.js +723 -0
  88. package/esm/src/shared-tests/deleteAll.d.ts +2 -0
  89. package/esm/src/shared-tests/deleteAll.js +4 -0
  90. package/esm/src/shared-tests/entityWithValidations.d.ts +14 -0
  91. package/esm/src/shared-tests/entityWithValidations.js +53 -0
  92. package/esm/src/shared-tests/index.d.ts +4 -0
  93. package/esm/src/shared-tests/index.js +4 -0
  94. package/esm/src/shared-tests/test-custom-id-column.spec.d.ts +1 -0
  95. package/esm/src/shared-tests/test-custom-id-column.spec.js +62 -0
  96. package/esm/src/shared-tests/test-special-value.spec.d.ts +10 -0
  97. package/esm/src/shared-tests/test-special-value.spec.js +88 -0
  98. package/esm/src/shared-tests/test-update-with-null.spec.d.ts +1 -0
  99. package/esm/src/shared-tests/test-update-with-null.spec.js +47 -0
  100. package/esm/src/sort.d.ts +15 -0
  101. package/esm/src/sort.js +82 -0
  102. package/esm/src/sql-command.d.ts +15 -0
  103. package/esm/src/sql-command.js +1 -0
  104. package/esm/src/tests/Done.d.ts +5 -0
  105. package/esm/src/tests/Done.js +11 -0
  106. package/esm/src/tests/TestDataApiResponse.d.ts +10 -0
  107. package/esm/src/tests/TestDataApiResponse.js +22 -0
  108. package/esm/src/tests/c.d.ts +8 -0
  109. package/esm/src/tests/c.js +22 -0
  110. package/esm/src/tests/createData.d.ts +7 -0
  111. package/esm/src/tests/createData.js +22 -0
  112. package/esm/src/tests/d.d.ts +6 -0
  113. package/esm/src/tests/d.js +19 -0
  114. package/esm/src/tests/dWithPrefilter.d.ts +7 -0
  115. package/esm/src/tests/dWithPrefilter.js +32 -0
  116. package/esm/src/tests/entityForCustomFilter.d.ts +16 -0
  117. package/esm/src/tests/entityForCustomFilter.js +44 -0
  118. package/esm/src/tests/entityWithValidationsOnColumn.d.ts +5 -0
  119. package/esm/src/tests/entityWithValidationsOnColumn.js +21 -0
  120. package/esm/src/tests/frontend-database-tests-setup.spec.d.ts +4 -0
  121. package/esm/src/tests/frontend-database-tests-setup.spec.js +38 -0
  122. package/esm/src/tests/h.d.ts +6 -0
  123. package/esm/src/tests/h.js +35 -0
  124. package/esm/src/tests/remult-3-entities.d.ts +23 -0
  125. package/esm/src/tests/remult-3-entities.js +72 -0
  126. package/esm/src/tests/tasks.d.ts +6 -0
  127. package/esm/src/tests/tasks.js +24 -0
  128. package/esm/src/tests/testHelper.spec.d.ts +34 -0
  129. package/esm/src/tests/testHelper.spec.js +217 -0
  130. package/esm/src/tests/testModel/models.d.ts +16 -0
  131. package/esm/src/tests/testModel/models.js +31 -0
  132. package/esm/src/validators.d.ts +14 -0
  133. package/esm/src/validators.js +33 -0
  134. package/esm/urlBuilder.d.ts +6 -0
  135. package/esm/urlBuilder.js +19 -0
  136. package/esm/valueConverters.d.ts +12 -0
  137. package/esm/valueConverters.js +169 -0
  138. package/index.d.ts +1 -0
  139. package/index.js +1 -0
  140. package/package.json +22 -1
  141. package/postgres/index.d.ts +1 -0
  142. package/postgres/index.js +1 -0
  143. package/postgres/postgres-data-provider.d.ts +1 -13
  144. package/postgres/postgres-data-provider.js +28 -262
  145. package/postgres/schema-builder.d.ts +15 -0
  146. package/postgres/schema-builder.js +270 -0
  147. package/readme.md +68 -30
  148. package/src/data-providers/web-sql-data-provider.js +4 -3
  149. package/src/entity.d.ts +9 -2
  150. package/src/remult3/RepositoryImplementation.js +11 -3
  151. package/src/shared-tests/test-update-with-null.spec.js +38 -0
  152. package/valueConverters.js +4 -0
@@ -0,0 +1,668 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import { registerActionsOnServer } from './register-actions-on-server';
3
+ import { registerEntitiesOnServer } from './register-entities-on-server';
4
+ import { JsonEntityFileStorage } from './JsonEntityFileStorage';
5
+ import { Action, actionInfo } from '../src/server-action';
6
+ import { DataApi, serializeError } from '../src/data-api';
7
+ import { allEntities, Remult } from '../src/context';
8
+ import { Entity, Fields, getEntityKey } from '../src/remult3';
9
+ import { JsonDataProvider } from '../src/data-providers/json-data-provider';
10
+ import { IdEntity } from '../src/id-entity';
11
+ export function remultMiddlewareBase(app, options) {
12
+ if (!options) {
13
+ options = {};
14
+ }
15
+ actionInfo.runningOnServer = true;
16
+ if (options.defaultGetLimit) {
17
+ DataApi.defaultGetLimit = options.defaultGetLimit;
18
+ }
19
+ if (!options.queueStorage) {
20
+ options.queueStorage = new InMemoryQueueStorage();
21
+ }
22
+ let dataProvider;
23
+ if (typeof options.dataProvider === "function") {
24
+ dataProvider = options.dataProvider();
25
+ }
26
+ else
27
+ dataProvider = Promise.resolve(options.dataProvider);
28
+ dataProvider = dataProvider.then(dp => {
29
+ if (dp)
30
+ return dp;
31
+ return new JsonDataProvider(new JsonEntityFileStorage('./db'));
32
+ });
33
+ if (options.initApi) {
34
+ dataProvider = dataProvider.then(async (dp) => {
35
+ var remult = new Remult(dp);
36
+ await options.initApi(remult);
37
+ return dp;
38
+ });
39
+ }
40
+ let bridge = new ExpressBridge(app, new inProcessQueueHandler(options.queueStorage), options.initRequest, dataProvider);
41
+ if (options.logApiEndPoints !== undefined)
42
+ bridge.logApiEndPoints = options.logApiEndPoints;
43
+ if (options.rootPath === undefined)
44
+ options.rootPath = Remult.apiBaseUrl;
45
+ let apiArea = bridge.addArea(options.rootPath);
46
+ if (!options.disableAutoApi) {
47
+ let actions = [];
48
+ if (options.entities)
49
+ actions.push(...options.entities);
50
+ if (options.controllers)
51
+ actions.push(...options.controllers);
52
+ registerActionsOnServer(apiArea, actions);
53
+ registerEntitiesOnServer(apiArea, options.entities);
54
+ }
55
+ return Object.assign(app, {
56
+ getRemult: (req) => bridge.getRemult(req),
57
+ openApiDoc: (options) => bridge.openApiDoc(options),
58
+ addArea: x => bridge.addArea(x)
59
+ });
60
+ }
61
+ class ExpressBridge {
62
+ constructor(app, queue, initRequest, dataProvider) {
63
+ this.app = app;
64
+ this.queue = queue;
65
+ this.initRequest = initRequest;
66
+ this.dataProvider = dataProvider;
67
+ /* internal */
68
+ this.backendMethodsOpenApi = [];
69
+ this.logApiEndPoints = true;
70
+ }
71
+ openApiDoc(options) {
72
+ let r = new Remult();
73
+ if (!options.version)
74
+ options.version = "1.0.0";
75
+ let spec = {
76
+ info: { title: options.title, version: options.version },
77
+ openapi: "3.0.0",
78
+ //swagger: "2.0",
79
+ "components": {
80
+ "schemas": {},
81
+ "securitySchemes": {
82
+ "bearerAuth": {
83
+ "scheme": "bearer",
84
+ "bearerFormat": "JWT",
85
+ "type": "http"
86
+ }
87
+ }
88
+ },
89
+ paths: {}
90
+ };
91
+ let validationError = {
92
+ "400": {
93
+ "description": "Error: Bad Request",
94
+ "content": {
95
+ "application/json": {
96
+ "schema": {
97
+ "$ref": "#/components/schemas/InvalidResponse"
98
+ }
99
+ }
100
+ }
101
+ }
102
+ };
103
+ let security = {
104
+ "security": [
105
+ {
106
+ "bearerAuth": []
107
+ }
108
+ ]
109
+ };
110
+ let secureBase = (condition, def, item) => {
111
+ if (condition === undefined)
112
+ condition = def;
113
+ if (condition != false) {
114
+ if (condition != true) {
115
+ item = { ...item, ...security };
116
+ item.responses["403"] = { description: "forbidden" };
117
+ }
118
+ return item;
119
+ }
120
+ };
121
+ for (const e of allEntities) {
122
+ let meta = r.repo(e).metadata;
123
+ let key = getEntityKey(e);
124
+ let parameters = [];
125
+ if (key) {
126
+ let properties = {};
127
+ for (const f of meta.fields) {
128
+ let type = f.valueType == String ? "string" :
129
+ f.valueType == Boolean ? "boolean" :
130
+ f.valueType == Date ? "string" :
131
+ f.valueType == Number ? "number" :
132
+ "object";
133
+ properties[f.key] = {
134
+ type
135
+ };
136
+ parameters.push({
137
+ "name": f.key,
138
+ "in": "query",
139
+ "description": "filter equal to " + f.key,
140
+ "required": false,
141
+ "style": "simple",
142
+ type
143
+ });
144
+ parameters.push({
145
+ "name": f.key + "_ne",
146
+ "in": "query",
147
+ "description": "filter not equal to " + f.key,
148
+ "required": false,
149
+ "style": "simple",
150
+ type
151
+ });
152
+ }
153
+ spec.components.schemas[key] = {
154
+ type: "object",
155
+ properties
156
+ };
157
+ let definition = {
158
+ "$ref": "#/components/schemas/" + key
159
+ };
160
+ let secure = (condition, def, item) => {
161
+ item.tags = [meta.key];
162
+ if (condition === undefined)
163
+ condition = meta.options.allowApiCrud;
164
+ return secureBase(condition, def, item);
165
+ };
166
+ let apiPath = spec.paths['/api/' + key] = {};
167
+ let apiPathWithId = spec.paths['/api/' + key + "/{id}"] = {};
168
+ //https://github.com/2fd/open-api.d.ts
169
+ apiPath.get = secure(meta.options.allowApiRead, true, {
170
+ description: "return an array of " + key + ". supports filter operators. For more info on filtering [see this article](https://remult.dev/docs/rest-api.html#filter)",
171
+ parameters: [{
172
+ "name": "_limit",
173
+ "in": "query",
174
+ "description": "limit the number of returned rows, default 100",
175
+ "required": false,
176
+ "style": "simple",
177
+ "schema": { "type": "integer" }
178
+ },
179
+ {
180
+ "name": "_page",
181
+ "in": "query",
182
+ "description": "to be used for paging",
183
+ "required": false,
184
+ "schema": { "type": "integer" }
185
+ },
186
+ {
187
+ "name": "_sort",
188
+ "in": "query",
189
+ "description": "the columns to sort on",
190
+ "required": false,
191
+ "schema": { "type": "string" }
192
+ },
193
+ {
194
+ "name": "_order",
195
+ "in": "query",
196
+ "description": "the sort order to user for the columns in `_sort`",
197
+ "required": false,
198
+ "schema": { "type": "string" }
199
+ }, ...parameters],
200
+ responses: {
201
+ "200": {
202
+ "description": "returns an array of " + key,
203
+ "content": {
204
+ "application/json": {
205
+ "schema": {
206
+ "type": "array",
207
+ "items": definition
208
+ }
209
+ }
210
+ }
211
+ },
212
+ }
213
+ });
214
+ let idParameter = {
215
+ "name": "id",
216
+ "in": "path",
217
+ "description": "id of " + key,
218
+ "required": true,
219
+ "schema": { "type": "string" },
220
+ };
221
+ let itemInBody = {
222
+ "requestBody": {
223
+ "content": {
224
+ "application/json": {
225
+ "schema": {
226
+ "$ref": "#/components/schemas/" + key
227
+ }
228
+ }
229
+ }
230
+ }
231
+ };
232
+ apiPath.post = secure(meta.options.allowApiInsert, false, {
233
+ //"summary": "insert a " + key,
234
+ //"description": "insert a " + key,
235
+ "produces": ["application/json"],
236
+ ...itemInBody,
237
+ "responses": {
238
+ "201": {
239
+ "description": "Created",
240
+ "content": {
241
+ "application/json": {
242
+ "schema": {
243
+ "$ref": "#/components/schemas/" + key
244
+ }
245
+ }
246
+ }
247
+ },
248
+ ...validationError
249
+ }
250
+ });
251
+ apiPathWithId.get = secure(meta.options.allowApiRead, true, {
252
+ parameters: [idParameter],
253
+ responses: {
254
+ "200": {
255
+ // "description": "returns an item of " + key,
256
+ "content": {
257
+ "application/json": {
258
+ "schema": {
259
+ "$ref": "#/components/schemas/" + key
260
+ }
261
+ }
262
+ }
263
+ },
264
+ }
265
+ });
266
+ apiPathWithId.put = secure(meta.options.allowApiUpdate, false, {
267
+ //"summary": "Update a " + key,
268
+ //"description": "Update a " + key,
269
+ "produces": ["application/json"],
270
+ "parameters": [
271
+ idParameter
272
+ ],
273
+ ...itemInBody,
274
+ "responses": {
275
+ "200": {
276
+ "description": "successful operation",
277
+ "content": {
278
+ "application/json": {
279
+ "schema": {
280
+ "$ref": "#/components/schemas/" + key
281
+ }
282
+ }
283
+ }
284
+ },
285
+ ...validationError
286
+ }
287
+ });
288
+ apiPathWithId.delete = secure(meta.options.allowApiDelete, false, {
289
+ // "summary": "Delete a " + key,
290
+ // "description": "Delete a " + key,
291
+ "produces": ["application/json"],
292
+ "parameters": [
293
+ idParameter
294
+ ],
295
+ "responses": {
296
+ "204": {
297
+ "description": "Deleted"
298
+ },
299
+ ...validationError
300
+ }
301
+ });
302
+ }
303
+ }
304
+ for (const b of this.backendMethodsOpenApi) {
305
+ spec.paths[b.path] = {
306
+ post: secureBase(b.allowed, false, {
307
+ "produces": ["application/json"],
308
+ "tags": [b.tag],
309
+ "requestBody": {
310
+ "content": {
311
+ "application/json": {
312
+ "schema": {
313
+ "type": "object",
314
+ properties: {
315
+ "args": {
316
+ "type": "array",
317
+ "items": { "type": "string" }
318
+ }
319
+ }
320
+ }
321
+ }
322
+ }
323
+ },
324
+ "responses": {
325
+ "201": {
326
+ "description": "Created",
327
+ "content": {
328
+ "application/json": {
329
+ "schema": {
330
+ "type": "object",
331
+ properties: {
332
+ "data": {
333
+ "type": "object"
334
+ }
335
+ }
336
+ }
337
+ }
338
+ }
339
+ },
340
+ ...validationError
341
+ }
342
+ })
343
+ };
344
+ }
345
+ spec.components.schemas["InvalidResponse"] = {
346
+ "type": "object",
347
+ properties: {
348
+ "message": {
349
+ "type": "string"
350
+ },
351
+ "modelState": {
352
+ "type": "object"
353
+ }
354
+ }
355
+ };
356
+ return spec;
357
+ }
358
+ addArea(rootUrl) {
359
+ var r = new SiteArea(this, this.app, rootUrl, this.logApiEndPoints);
360
+ if (!this.firstArea) {
361
+ this.firstArea = r;
362
+ }
363
+ return r;
364
+ }
365
+ async getRemult(req) {
366
+ return this.firstArea.getRemult(req);
367
+ }
368
+ }
369
+ export class SiteArea {
370
+ constructor(bridge, app, rootUrl, logApiEndpoints) {
371
+ this.bridge = bridge;
372
+ this.app = app;
373
+ this.rootUrl = rootUrl;
374
+ this.logApiEndpoints = logApiEndpoints;
375
+ }
376
+ add(key, dataApiFactory) {
377
+ let myRoute = this.rootUrl + '/' + key;
378
+ if (this.logApiEndpoints)
379
+ console.log(myRoute);
380
+ this.app.route(myRoute)
381
+ .get(this.process((c, req, res) => dataApiFactory(c).httpGet(res, req))).put(this.process(async (c, req, res, orig) => dataApiFactory(c).put(res, '', orig.body)))
382
+ .delete(this.process(async (c, req, res, orig) => dataApiFactory(c).delete(res, '')))
383
+ .post(this.process(async (c, req, res, orig) => dataApiFactory(c).httpPost(res, req, orig.body)));
384
+ this.app.route(myRoute + '/:id')
385
+ //@ts-ignore
386
+ .get(this.process(async (c, req, res, orig) => dataApiFactory(c).get(res, orig.params.id)))
387
+ //@ts-ignore
388
+ .put(this.process(async (c, req, res, orig) => dataApiFactory(c).put(res, orig.params.id, orig.body)))
389
+ //@ts-ignore
390
+ .delete(this.process(async (c, req, res, orig) => dataApiFactory(c).delete(res, orig.params.id)));
391
+ }
392
+ process(what) {
393
+ return async (req, res) => {
394
+ let myReq = new ExpressRequestBridgeToDataApiRequest(req);
395
+ let myRes = new ExpressResponseBridgeToDataApiResponse(res, req);
396
+ let remult = new Remult();
397
+ remult.setDataProvider(await this.bridge.dataProvider);
398
+ if (req) {
399
+ let user = req['user'];
400
+ if (!user)
401
+ user = req['auth'];
402
+ if (user)
403
+ remult.setUser(user);
404
+ }
405
+ if (this.bridge.initRequest) {
406
+ await this.bridge.initRequest(remult, req);
407
+ }
408
+ what(remult, myReq, myRes, req);
409
+ };
410
+ }
411
+ ;
412
+ async getRemult(req) {
413
+ let remult;
414
+ await this.process(async (c) => {
415
+ remult = c;
416
+ })(req, undefined);
417
+ return remult;
418
+ }
419
+ initQueue() {
420
+ this.addAction({
421
+ __register: x => {
422
+ x(Action.apiUrlForJobStatus, false, () => true, async (data, req, res) => {
423
+ let job = await this.bridge.queue.getJobInfo(data.queuedJobId);
424
+ let userId = undefined;
425
+ if (req?.user)
426
+ userId = req.user.id;
427
+ if (job.userId == '')
428
+ job.userId = undefined;
429
+ if (userId != job.userId)
430
+ res.forbidden();
431
+ else
432
+ res.success(job.info);
433
+ });
434
+ }
435
+ });
436
+ this.initQueue = () => { };
437
+ }
438
+ addAction(action) {
439
+ action.__register((url, queue, allowed, what) => {
440
+ let myUrl = this.rootUrl + '/' + url;
441
+ let tag = (() => {
442
+ let split = url.split('/');
443
+ if (split.length == 1)
444
+ return 'Static Backend Methods';
445
+ else
446
+ return split[0];
447
+ })();
448
+ this.bridge.backendMethodsOpenApi.push({ path: myUrl, allowed, tag });
449
+ if (this.logApiEndpoints)
450
+ console.log(myUrl);
451
+ if (queue) {
452
+ this.initQueue();
453
+ this.bridge.queue.mapQueuedAction(myUrl, what);
454
+ }
455
+ this.app.route(myUrl).post(this.process(async (remult, req, res, orig) => {
456
+ if (queue) {
457
+ let r = {
458
+ queuedJobId: await this.bridge.queue.submitJob(myUrl, remult, orig.body)
459
+ };
460
+ res.success(r);
461
+ }
462
+ else
463
+ return what(orig.body, remult, res);
464
+ }));
465
+ });
466
+ }
467
+ }
468
+ export class ExpressRequestBridgeToDataApiRequest {
469
+ constructor(r) {
470
+ this.r = r;
471
+ }
472
+ get(key) {
473
+ return this.r.query[key];
474
+ }
475
+ }
476
+ class ExpressResponseBridgeToDataApiResponse {
477
+ constructor(r, req) {
478
+ this.r = r;
479
+ this.req = req;
480
+ }
481
+ forbidden() {
482
+ this.sendStatus(403);
483
+ }
484
+ sendStatus(status) {
485
+ this.r.writeHead(status).end();
486
+ }
487
+ progress(progress) {
488
+ }
489
+ success(data) {
490
+ this.r.json(data);
491
+ }
492
+ created(data) {
493
+ this.r.statusCode = 201;
494
+ this.r.json(data);
495
+ }
496
+ deleted() {
497
+ this.sendStatus(204);
498
+ }
499
+ notFound() {
500
+ this.sendStatus(404);
501
+ }
502
+ error(data) {
503
+ data = serializeError(data);
504
+ console.error({
505
+ message: data.message,
506
+ stack: data.stack?.split('\n'),
507
+ url: this.req.originalUrl ?? this.req.path,
508
+ method: this.req.method
509
+ });
510
+ this.r.status(400).json(data);
511
+ }
512
+ }
513
+ function throwError() {
514
+ throw "Invalid";
515
+ }
516
+ class inProcessQueueHandler {
517
+ constructor(storage) {
518
+ this.storage = storage;
519
+ this.actions = new Map();
520
+ }
521
+ async submitJob(url, req, body) {
522
+ let id = await this.storage.createJob(url, req.user ? req.user.id : undefined);
523
+ let job = await this.storage.getJobInfo(id);
524
+ this.actions.get(url)(body, req, {
525
+ error: error => job.setErrorResult(serializeError(error)),
526
+ success: result => job.setResult(result),
527
+ progress: progress => job.setProgress(progress)
528
+ });
529
+ return id;
530
+ }
531
+ mapQueuedAction(url, what) {
532
+ this.actions.set(url, what);
533
+ }
534
+ async getJobInfo(queuedJobId) {
535
+ return await this.storage.getJobInfo(queuedJobId);
536
+ }
537
+ }
538
+ class InMemoryQueueStorage {
539
+ constructor() {
540
+ this.jobs = new Map();
541
+ }
542
+ async getJobInfo(queuedJobId) {
543
+ return this.jobs.get(queuedJobId);
544
+ }
545
+ async createJob(url, userId) {
546
+ let id = this.jobs.size.toString();
547
+ this.jobs.set(id, {
548
+ info: {
549
+ done: false
550
+ },
551
+ userId: userId,
552
+ setErrorResult: (error) => {
553
+ let job = this.jobs.get(id);
554
+ job.info.done = true;
555
+ job.info.error = error;
556
+ },
557
+ setResult: (result) => {
558
+ let job = this.jobs.get(id);
559
+ job.info.done = true;
560
+ job.info.result = result;
561
+ },
562
+ setProgress: (progress) => {
563
+ let job = this.jobs.get(id);
564
+ job.info.progress = progress;
565
+ }
566
+ });
567
+ return id;
568
+ }
569
+ }
570
+ let test = 0;
571
+ export class EntityQueueStorage {
572
+ constructor(repo) {
573
+ this.repo = repo;
574
+ this.sync = Promise.resolve();
575
+ }
576
+ doSync(what) {
577
+ return this.sync = this.sync.then(() => what());
578
+ }
579
+ async getJobInfo(queuedJobId) {
580
+ let q = await this.repo.findId(queuedJobId);
581
+ let lastProgress = undefined;
582
+ return {
583
+ userId: q.userId,
584
+ info: {
585
+ done: q.done,
586
+ error: q.error ? JSON.parse(q.result) : undefined,
587
+ result: q.done && !q.error ? JSON.parse(q.result) : undefined,
588
+ progress: q.progress
589
+ },
590
+ setErrorResult: async (error) => {
591
+ await this.sync;
592
+ q.error = true;
593
+ q.done = true;
594
+ q.result = JSON.stringify(error);
595
+ q.doneTime = new Date();
596
+ q.progress = 1;
597
+ await this.doSync(() => q._.save());
598
+ },
599
+ setResult: async (result) => {
600
+ await this.sync;
601
+ q.done = true;
602
+ q.result = JSON.stringify(result);
603
+ q.doneTime = new Date();
604
+ await this.doSync(() => q._.save());
605
+ },
606
+ setProgress: async (progress) => {
607
+ if (progress === 0)
608
+ return;
609
+ let now = new Date();
610
+ if (lastProgress && now.valueOf() - lastProgress.valueOf() < 200)
611
+ return;
612
+ lastProgress = new Date();
613
+ await this.sync;
614
+ q.progress = progress;
615
+ await this.doSync(() => q._.save());
616
+ }
617
+ };
618
+ }
619
+ async createJob(url, userId) {
620
+ let q = this.repo.create();
621
+ q.userId = userId;
622
+ q.submitTime = new Date();
623
+ q.url = url;
624
+ await q._.save();
625
+ return q.id;
626
+ }
627
+ }
628
+ let JobsInQueueEntity = class JobsInQueueEntity extends IdEntity {
629
+ };
630
+ __decorate([
631
+ Fields.string(),
632
+ __metadata("design:type", String)
633
+ ], JobsInQueueEntity.prototype, "userId", void 0);
634
+ __decorate([
635
+ Fields.string(),
636
+ __metadata("design:type", String)
637
+ ], JobsInQueueEntity.prototype, "url", void 0);
638
+ __decorate([
639
+ Fields.date(),
640
+ __metadata("design:type", Date)
641
+ ], JobsInQueueEntity.prototype, "submitTime", void 0);
642
+ __decorate([
643
+ Fields.date(),
644
+ __metadata("design:type", Date)
645
+ ], JobsInQueueEntity.prototype, "doneTime", void 0);
646
+ __decorate([
647
+ Fields.string(),
648
+ __metadata("design:type", String)
649
+ ], JobsInQueueEntity.prototype, "result", void 0);
650
+ __decorate([
651
+ Fields.boolean(),
652
+ __metadata("design:type", Boolean)
653
+ ], JobsInQueueEntity.prototype, "done", void 0);
654
+ __decorate([
655
+ Fields.boolean(),
656
+ __metadata("design:type", Boolean)
657
+ ], JobsInQueueEntity.prototype, "error", void 0);
658
+ __decorate([
659
+ Fields.number(),
660
+ __metadata("design:type", Number)
661
+ ], JobsInQueueEntity.prototype, "progress", void 0);
662
+ JobsInQueueEntity = __decorate([
663
+ Entity(undefined, {
664
+ dbName: 'jobsInQueue'
665
+ })
666
+ ], JobsInQueueEntity);
667
+ export { JobsInQueueEntity };
668
+ allEntities.splice(allEntities.indexOf(JobsInQueueEntity), 1);
@@ -0,0 +1,4 @@
1
+ export { JsonEntityFileStorage } from './JsonEntityFileStorage';
2
+ export { SiteArea, queuedJobInfo, QueueStorage } from './expressBridge';
3
+ export { registerEntitiesOnServer } from './register-entities-on-server';
4
+ export { registerActionsOnServer } from './register-actions-on-server';
@@ -0,0 +1,4 @@
1
+ export { JsonEntityFileStorage } from './JsonEntityFileStorage';
2
+ export { SiteArea } from './expressBridge';
3
+ export { registerEntitiesOnServer } from './register-entities-on-server';
4
+ export { registerActionsOnServer } from './register-actions-on-server';
@@ -0,0 +1,3 @@
1
+ import { SiteArea } from "./expressBridge";
2
+ import { ClassType } from "../classType";
3
+ export declare function registerActionsOnServer(area: SiteArea, controllers?: ClassType<any>[]): void;