remult 0.22.3 → 0.22.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) hide show
  1. package/esm/angular/interfaces/index.d.ts +1 -0
  2. package/esm/angular/interfaces/index.js +1 -0
  3. package/esm/angular/interfaces/src/column-collection.d.ts +70 -0
  4. package/esm/angular/interfaces/src/column-collection.js +341 -0
  5. package/esm/angular/interfaces/src/data-area-settings.d.ts +15 -0
  6. package/esm/angular/interfaces/src/data-area-settings.js +35 -0
  7. package/esm/angular/interfaces/src/data-control-interfaces.d.ts +36 -0
  8. package/esm/angular/interfaces/src/data-control-interfaces.js +57 -0
  9. package/esm/angular/interfaces/src/dataList.d.ts +13 -0
  10. package/esm/angular/interfaces/src/dataList.js +42 -0
  11. package/esm/angular/interfaces/src/filter-helper.d.ts +13 -0
  12. package/esm/angular/interfaces/src/filter-helper.js +59 -0
  13. package/esm/angular/interfaces/src/grid-settings.d.ts +145 -0
  14. package/esm/angular/interfaces/src/grid-settings.js +387 -0
  15. package/esm/angular/interfaces/src/public_api.d.ts +4 -0
  16. package/esm/angular/interfaces/src/public_api.js +4 -0
  17. package/esm/angular/src/angular/RemultAngularPluginsService.d.ts +4 -0
  18. package/esm/angular/src/angular/RemultAngularPluginsService.js +3 -0
  19. package/esm/angular/src/angular/data-control/data-control2.component.d.ts +49 -0
  20. package/esm/angular/src/angular/data-control/data-control2.component.js +138 -0
  21. package/esm/core/SseSubscriptionServer.d.ts +33 -0
  22. package/esm/core/SseSubscriptionServer.js +107 -0
  23. package/esm/core/assign.d.ts +1 -0
  24. package/esm/core/assign.js +5 -0
  25. package/esm/core/classType.d.ts +3 -0
  26. package/esm/core/classType.js +1 -0
  27. package/esm/core/index.d.ts +27 -0
  28. package/esm/core/index.js +25 -0
  29. package/esm/core/inputTypes.d.ts +9 -0
  30. package/esm/core/inputTypes.js +9 -0
  31. package/esm/core/live-query/data-provider-live-query-storage.d.ts +22 -0
  32. package/esm/core/live-query/data-provider-live-query-storage.js +71 -0
  33. package/esm/core/postgres/index.d.ts +2 -0
  34. package/esm/core/postgres/index.js +2 -0
  35. package/esm/core/postgres/postgres-data-provider.d.ts +36 -0
  36. package/esm/core/postgres/postgres-data-provider.js +120 -0
  37. package/esm/core/postgres/schema-builder.d.ts +17 -0
  38. package/esm/core/postgres/schema-builder.js +153 -0
  39. package/esm/core/remult-fresh.d.ts +17 -0
  40. package/esm/core/remult-fresh.js +29 -0
  41. package/esm/core/remult-knex/index.d.ts +30 -0
  42. package/esm/core/remult-knex/index.js +446 -0
  43. package/esm/core/remult-mongo.d.ts +24 -0
  44. package/esm/core/remult-mongo.js +254 -0
  45. package/esm/core/server/JsonEntityFileStorage.d.ts +10 -0
  46. package/esm/core/server/JsonEntityFileStorage.js +25 -0
  47. package/esm/core/server/core.d.ts +4 -0
  48. package/esm/core/server/core.js +4 -0
  49. package/esm/core/server/expressBridge.d.ts +182 -0
  50. package/esm/core/server/expressBridge.js +938 -0
  51. package/esm/core/server/index.d.ts +6 -0
  52. package/esm/core/server/index.js +9 -0
  53. package/esm/core/server/initAsyncHooks.d.ts +1 -0
  54. package/esm/core/server/initAsyncHooks.js +9 -0
  55. package/esm/core/server/initDataProvider.d.ts +2 -0
  56. package/esm/core/server/initDataProvider.js +14 -0
  57. package/esm/core/src/__EntityValueProvider.d.ts +11 -0
  58. package/esm/core/src/__EntityValueProvider.js +1 -0
  59. package/esm/core/src/__RowsOfDataForTesting.d.ts +3 -0
  60. package/esm/core/src/__RowsOfDataForTesting.js +1 -0
  61. package/esm/core/src/backend-tests/backend-database-test-setup.backend-spec.d.ts +6 -0
  62. package/esm/core/src/backend-tests/backend-database-test-setup.backend-spec.js +147 -0
  63. package/{src → esm/core/src}/backend-tests/my-test.backend-spec.d.ts +1 -1
  64. package/esm/core/src/backend-tests/my-test.backend-spec.js +197 -0
  65. package/esm/core/src/backend-tests/test-http-server.backend-spec.d.ts +1 -0
  66. package/esm/core/src/backend-tests/test-http-server.backend-spec.js +167 -0
  67. package/esm/core/src/buildRestDataProvider.d.ts +31 -0
  68. package/esm/core/src/buildRestDataProvider.js +113 -0
  69. package/esm/core/src/column-interfaces.d.ts +154 -0
  70. package/esm/core/src/column-interfaces.js +7 -0
  71. package/esm/core/src/column.d.ts +58 -0
  72. package/esm/core/src/column.js +174 -0
  73. package/esm/core/src/context.d.ts +134 -0
  74. package/esm/core/src/context.js +286 -0
  75. package/esm/core/src/data-api.d.ts +39 -0
  76. package/esm/core/src/data-api.js +279 -0
  77. package/esm/core/src/data-interfaces.d.ts +41 -0
  78. package/esm/core/src/data-interfaces.js +12 -0
  79. package/esm/core/src/data-providers/array-entity-data-provider.d.ts +22 -0
  80. package/esm/core/src/data-providers/array-entity-data-provider.js +252 -0
  81. package/esm/core/src/data-providers/in-memory-database.d.ts +9 -0
  82. package/esm/core/src/data-providers/in-memory-database.js +14 -0
  83. package/esm/core/src/data-providers/json-data-provider.d.ts +12 -0
  84. package/esm/core/src/data-providers/json-data-provider.js +55 -0
  85. package/esm/core/src/data-providers/rest-data-provider.d.ts +49 -0
  86. package/esm/core/src/data-providers/rest-data-provider.js +256 -0
  87. package/esm/core/src/data-providers/sql-database.d.ts +33 -0
  88. package/esm/core/src/data-providers/sql-database.js +384 -0
  89. package/esm/core/src/data-providers/web-sql-data-provider.d.ts +24 -0
  90. package/esm/core/src/data-providers/web-sql-data-provider.js +143 -0
  91. package/esm/core/src/entity.d.ts +91 -0
  92. package/esm/core/src/entity.js +1 -0
  93. package/esm/core/src/filter/filter-consumer-bridge-to-sql-request.d.ts +50 -0
  94. package/esm/core/src/filter/filter-consumer-bridge-to-sql-request.js +150 -0
  95. package/esm/core/src/filter/filter-consumer-bridge-to-url-builder.d.ts +1 -0
  96. package/esm/core/src/filter/filter-consumer-bridge-to-url-builder.js +1 -0
  97. package/esm/core/src/filter/filter-interfaces.d.ts +85 -0
  98. package/esm/core/src/filter/filter-interfaces.js +477 -0
  99. package/esm/core/src/live-query/LiveQueryClient.d.ts +20 -0
  100. package/esm/core/src/live-query/LiveQueryClient.js +188 -0
  101. package/esm/core/src/live-query/SseSubscriptionClient.d.ts +5 -0
  102. package/esm/core/src/live-query/SseSubscriptionClient.js +86 -0
  103. package/esm/core/src/live-query/SubscriptionChannel.d.ts +72 -0
  104. package/esm/core/src/live-query/SubscriptionChannel.js +123 -0
  105. package/esm/core/src/live-query/SubscriptionServer.d.ts +53 -0
  106. package/esm/core/src/live-query/SubscriptionServer.js +111 -0
  107. package/esm/core/src/live-query/live-query-tests.spec.d.ts +6 -0
  108. package/esm/core/src/live-query/live-query-tests.spec.js +952 -0
  109. package/esm/core/src/remult-proxy.d.ts +35 -0
  110. package/esm/core/src/remult-proxy.js +113 -0
  111. package/esm/core/src/remult3/DecoratorReplacer.d.ts +10 -0
  112. package/esm/core/src/remult3/DecoratorReplacer.js +20 -0
  113. package/esm/core/src/remult3/RepositoryImplementation.d.ts +355 -0
  114. package/esm/core/src/remult3/RepositoryImplementation.js +2109 -0
  115. package/esm/core/src/remult3/index.d.ts +2 -0
  116. package/esm/core/src/remult3/index.js +2 -0
  117. package/esm/core/src/remult3/remult3.d.ts +395 -0
  118. package/esm/core/src/remult3/remult3.js +2 -0
  119. package/esm/core/src/server-action.d.ts +81 -0
  120. package/esm/core/src/server-action.js +394 -0
  121. package/esm/core/src/shared-tests/db-tests-setup.d.ts +32 -0
  122. package/esm/core/src/shared-tests/db-tests-setup.js +78 -0
  123. package/esm/core/src/shared-tests/db-tests.db-tests.d.ts +25 -0
  124. package/esm/core/src/shared-tests/db-tests.db-tests.js +810 -0
  125. package/esm/core/src/shared-tests/deleteAll.d.ts +2 -0
  126. package/esm/core/src/shared-tests/deleteAll.js +4 -0
  127. package/esm/core/src/shared-tests/entityWithValidations.d.ts +14 -0
  128. package/esm/core/src/shared-tests/entityWithValidations.js +43 -0
  129. package/esm/core/src/shared-tests/index.d.ts +4 -0
  130. package/esm/core/src/shared-tests/index.js +4 -0
  131. package/esm/core/src/shared-tests/test-custom-id-column.spec.d.ts +1 -0
  132. package/esm/core/src/shared-tests/test-custom-id-column.spec.js +67 -0
  133. package/esm/core/src/shared-tests/test-special-value.spec.d.ts +10 -0
  134. package/esm/core/src/shared-tests/test-special-value.spec.js +73 -0
  135. package/esm/core/src/shared-tests/test-update-with-null.spec.d.ts +1 -0
  136. package/esm/core/src/shared-tests/test-update-with-null.spec.js +31 -0
  137. package/esm/core/src/sort.d.ts +16 -0
  138. package/esm/core/src/sort.js +103 -0
  139. package/esm/core/src/sql-command.d.ts +19 -0
  140. package/esm/core/src/sql-command.js +1 -0
  141. package/esm/core/src/test.d.ts +3 -0
  142. package/esm/core/src/test.js +12 -0
  143. package/esm/core/src/tests/Done.d.ts +5 -0
  144. package/esm/core/src/tests/Done.js +9 -0
  145. package/esm/core/src/tests/RowProvider.spec.d.ts +16 -0
  146. package/esm/core/src/tests/RowProvider.spec.js +631 -0
  147. package/esm/core/src/tests/TestDataApiResponse.d.ts +10 -0
  148. package/esm/core/src/tests/TestDataApiResponse.js +22 -0
  149. package/esm/core/src/tests/basicRowFunctionality.spec.d.ts +8 -0
  150. package/esm/core/src/tests/basicRowFunctionality.spec.js +2103 -0
  151. package/esm/core/src/tests/c.d.ts +8 -0
  152. package/esm/core/src/tests/c.js +13 -0
  153. package/esm/core/src/tests/createData.d.ts +7 -0
  154. package/esm/core/src/tests/createData.js +22 -0
  155. package/esm/core/src/tests/d.d.ts +6 -0
  156. package/esm/core/src/tests/d.js +11 -0
  157. package/esm/core/src/tests/dWithPrefilter.d.ts +7 -0
  158. package/esm/core/src/tests/dWithPrefilter.js +18 -0
  159. package/esm/core/src/tests/entityForCustomFilter.d.ts +16 -0
  160. package/esm/core/src/tests/entityForCustomFilter.js +33 -0
  161. package/esm/core/src/tests/entityWithValidationsOnColumn.d.ts +5 -0
  162. package/esm/core/src/tests/entityWithValidationsOnColumn.js +13 -0
  163. package/esm/core/src/tests/frontend-database-tests-setup.spec.d.ts +4 -0
  164. package/esm/core/src/tests/frontend-database-tests-setup.spec.js +37 -0
  165. package/esm/core/src/tests/h.d.ts +6 -0
  166. package/esm/core/src/tests/h.js +24 -0
  167. package/esm/core/src/tests/remult-3-basic-tests.spec.d.ts +1 -0
  168. package/esm/core/src/tests/remult-3-basic-tests.spec.js +236 -0
  169. package/esm/core/src/tests/remult-3-entities.d.ts +23 -0
  170. package/esm/core/src/tests/remult-3-entities.js +39 -0
  171. package/esm/core/src/tests/tasks.d.ts +6 -0
  172. package/esm/core/src/tests/tasks.js +10 -0
  173. package/esm/core/src/tests/test-context-as-storage.spec.d.ts +0 -0
  174. package/esm/core/src/tests/test-context-as-storage.spec.js +1 -0
  175. package/esm/core/src/tests/test-data-api/predefined-filter.spec.d.ts +1 -0
  176. package/esm/core/src/tests/test-data-api/predefined-filter.spec.js +389 -0
  177. package/esm/core/src/tests/test-data-api/test-put-with-validation.spec.d.ts +5 -0
  178. package/esm/core/src/tests/test-data-api/test-put-with-validation.spec.js +152 -0
  179. package/esm/core/src/tests/test-decorator-precedence.spec.d.ts +1 -0
  180. package/esm/core/src/tests/test-decorator-precedence.spec.js +38 -0
  181. package/esm/core/src/tests/test-default-value.spec.d.ts +1 -0
  182. package/esm/core/src/tests/test-default-value.spec.js +33 -0
  183. package/esm/core/src/tests/test-entity-inheritance.spec.d.ts +14 -0
  184. package/esm/core/src/tests/test-entity-inheritance.spec.js +82 -0
  185. package/esm/core/src/tests/test-exceptions.spec.d.ts +1 -0
  186. package/esm/core/src/tests/test-exceptions.spec.js +375 -0
  187. package/esm/core/src/tests/test-json.spec.d.ts +1 -0
  188. package/esm/core/src/tests/test-json.spec.js +115 -0
  189. package/esm/core/src/tests/test-many-to-one-relation-in-entity.spec.d.ts +9 -0
  190. package/esm/core/src/tests/test-many-to-one-relation-in-entity.spec.js +809 -0
  191. package/esm/core/src/tests/test-non-active-record.spec.d.ts +1 -0
  192. package/esm/core/src/tests/test-non-active-record.spec.js +66 -0
  193. package/esm/core/src/tests/test-object-column.spec.d.ts +1 -0
  194. package/esm/core/src/tests/test-object-column.spec.js +189 -0
  195. package/esm/core/src/tests/test-paged-foreach.spec.d.ts +1 -0
  196. package/esm/core/src/tests/test-paged-foreach.spec.js +328 -0
  197. package/esm/core/src/tests/test-remult-angular.spec.d.ts +1 -0
  198. package/esm/core/src/tests/test-remult-angular.spec.js +23 -0
  199. package/esm/core/src/tests/test-server-controller.spec.d.ts +7 -0
  200. package/esm/core/src/tests/test-server-controller.spec.js +489 -0
  201. package/esm/core/src/tests/test-server-expressions.spec.d.ts +1 -0
  202. package/esm/core/src/tests/test-server-expressions.spec.js +178 -0
  203. package/esm/core/src/tests/test-server-method-on-entity.spec.d.ts +1 -0
  204. package/esm/core/src/tests/test-server-method-on-entity.spec.js +306 -0
  205. package/esm/core/src/tests/test-sql-expression.spec.d.ts +5 -0
  206. package/esm/core/src/tests/test-sql-expression.spec.js +205 -0
  207. package/esm/core/src/tests/test-sql.spec.d.ts +1 -0
  208. package/esm/core/src/tests/test-sql.spec.js +170 -0
  209. package/esm/core/src/tests/test-subscribe.spec.d.ts +1 -0
  210. package/esm/core/src/tests/test-subscribe.spec.js +135 -0
  211. package/esm/core/src/tests/test-type-recovery.spec.d.ts +1 -0
  212. package/esm/core/src/tests/test-type-recovery.spec.js +49 -0
  213. package/esm/core/src/tests/test-where-api.spec.d.ts +1 -0
  214. package/esm/core/src/tests/test-where-api.spec.js +434 -0
  215. package/esm/core/src/tests/testHelper.spec.d.ts +36 -0
  216. package/esm/core/src/tests/testHelper.spec.js +226 -0
  217. package/esm/core/src/tests/testModel/models.d.ts +16 -0
  218. package/esm/core/src/tests/testModel/models.js +25 -0
  219. package/esm/core/src/validators.d.ts +14 -0
  220. package/esm/core/src/validators.js +33 -0
  221. package/{valueConverters.d.ts → esm/core/src/valueConverters.d.ts} +13 -12
  222. package/esm/core/src/valueConverters.js +197 -0
  223. package/esm/core/urlBuilder.d.ts +6 -0
  224. package/esm/core/urlBuilder.js +20 -0
  225. package/esm/graphql.js +27 -27
  226. package/esm/postgres/schema-builder.js +4 -4
  227. package/esm/src/context.d.ts +6 -1
  228. package/esm/src/remult3/RepositoryImplementation.d.ts +1 -1
  229. package/esm/src/remult3/RepositoryImplementation.js +27 -4
  230. package/esm/src/shared-tests/db-tests.db-tests.js +57 -0
  231. package/esm/test-servers/shared/Task.d.ts +9 -0
  232. package/esm/test-servers/shared/Task.js +32 -0
  233. package/esm/test.d.ts +5 -0
  234. package/esm/test.js +6 -0
  235. package/package.json +1 -1
  236. package/src/context.d.ts +6 -1
  237. package/src/remult3/RepositoryImplementation.d.ts +1 -1
  238. package/src/remult3/RepositoryImplementation.js +88 -63
  239. package/src/shared-tests/db-tests.db-tests.js +97 -0
  240. package/esm/src/id-entity.d.ts +0 -4
  241. package/esm/src/id-entity.js +0 -8
  242. package/postgres/postgresColumnSyntax.d.ts +0 -2
  243. package/postgres/postgresColumnSyntax.js +0 -34
  244. package/remult-middleware.d.ts +0 -2
  245. package/remult-middleware.js +0 -70
  246. package/server/register-actions-on-server.d.ts +0 -3
  247. package/server/register-actions-on-server.js +0 -50
  248. package/server/register-entities-on-server.d.ts +0 -3
  249. package/server/register-entities-on-server.js +0 -19
  250. package/src/backend-tests/my-test.backend-spec.js +0 -217
  251. package/src/backend-tests/test-http-server.backend-spec.d.ts +0 -6
  252. package/src/backend-tests/test-http-server.backend-spec.js +0 -342
  253. package/src/id-entity.d.ts +0 -4
  254. package/src/id-entity.js +0 -17
  255. package/valueConverters.js +0 -168
@@ -0,0 +1,286 @@
1
+ import { actionInfo, serverActionField } from './server-action';
2
+ import { RestDataProvider } from './data-providers/rest-data-provider';
3
+ import { RepositoryImplementation } from "./remult3/RepositoryImplementation";
4
+ import { LiveQueryClient } from "./live-query/LiveQueryClient";
5
+ import { SseSubscriptionClient } from "./live-query/SseSubscriptionClient";
6
+ import { RemultProxy, remult } from "./remult-proxy";
7
+ import { buildRestDataProvider, isExternalHttpProvider } from "./buildRestDataProvider";
8
+ export class RemultAsyncLocalStorage {
9
+ remultObjectStorage;
10
+ static enable() {
11
+ remult.remultFactory = () => {
12
+ const r = RemultAsyncLocalStorage.instance.getRemult();
13
+ if (r)
14
+ return r;
15
+ else
16
+ throw new Error("remult object was requested outside of a valid context, try running it within initApi or a remult request cycle");
17
+ };
18
+ }
19
+ static disable() {
20
+ remult.resetFactory();
21
+ }
22
+ constructor(remultObjectStorage) {
23
+ this.remultObjectStorage = remultObjectStorage;
24
+ }
25
+ run(remult, callback) {
26
+ if (this.remultObjectStorage)
27
+ this.remultObjectStorage.run(remult, callback);
28
+ else
29
+ callback();
30
+ }
31
+ getRemult() {
32
+ if (!this.remultObjectStorage) {
33
+ throw new Error("can't use static remult in this environment, `async_hooks` were not initialized");
34
+ }
35
+ return this.remultObjectStorage.getStore();
36
+ }
37
+ static instance = new RemultAsyncLocalStorage(undefined);
38
+ }
39
+ export function isBackend() {
40
+ return actionInfo.runningOnServer || !remult.dataProvider.isProxy;
41
+ }
42
+ export class Remult {
43
+ /**Return's a `Repository` of the specific entity type
44
+ * @example
45
+ * const taskRepo = remult.repo(Task);
46
+ * @see [Repository](https://remult.dev/docs/ref_repository.html)
47
+ * @param entity - the entity to use
48
+ * @param dataProvider - an optional alternative data provider to use. Useful for writing to offline storage or an alternative data provider
49
+ */
50
+ repo(entity, dataProvider) {
51
+ if (dataProvider === undefined)
52
+ dataProvider = this.dataProvider;
53
+ let dpCache = this.repCache.get(dataProvider);
54
+ if (!dpCache)
55
+ this.repCache.set(dataProvider, dpCache = new Map());
56
+ let r = dpCache.get(entity);
57
+ if (!r) {
58
+ dpCache.set(entity, r = new RepositoryImplementation(entity, this, dataProvider));
59
+ }
60
+ return r;
61
+ }
62
+ /** Returns the current user's info */
63
+ user;
64
+ /** Checks if a user was authenticated */
65
+ authenticated() {
66
+ return this.user?.id !== undefined;
67
+ }
68
+ /** checks if the user has any of the roles specified in the parameters
69
+ * @example
70
+ * remult.isAllowed("admin")
71
+ * @see
72
+ * [Allowed](https://remult.dev/docs/allowed.html)
73
+ */
74
+ isAllowed(roles) {
75
+ if (roles == undefined)
76
+ return undefined;
77
+ if (roles instanceof Array) {
78
+ for (const role of roles) {
79
+ if (this.isAllowed(role) === true) {
80
+ return true;
81
+ }
82
+ }
83
+ return false;
84
+ }
85
+ if (typeof roles === 'function') {
86
+ return roles(this);
87
+ }
88
+ if (typeof roles === 'boolean')
89
+ return roles;
90
+ if (typeof roles === 'string')
91
+ if (this.user?.roles?.indexOf(roles.toString()) >= 0)
92
+ return true;
93
+ return false;
94
+ }
95
+ /** checks if the user matches the allowedForInstance callback
96
+ * @see
97
+ * [Allowed](https://remult.dev/docs/allowed.html)
98
+ */
99
+ isAllowedForInstance(instance, allowed) {
100
+ if (Array.isArray(allowed)) {
101
+ {
102
+ for (const item of allowed) {
103
+ if (this.isAllowedForInstance(instance, item))
104
+ return true;
105
+ }
106
+ }
107
+ }
108
+ else if (typeof (allowed) === "function") {
109
+ return allowed(instance, this);
110
+ }
111
+ else
112
+ return this.isAllowed(allowed);
113
+ }
114
+ /** The current data provider */
115
+ dataProvider = new RestDataProvider(() => this.apiClient);
116
+ /* @internal */
117
+ repCache = new Map();
118
+ constructor(provider) {
119
+ if (provider && provider.getEntityDataProvider) {
120
+ this.dataProvider = provider;
121
+ return;
122
+ }
123
+ if (isExternalHttpProvider(provider)) {
124
+ this.apiClient.httpClient = provider;
125
+ }
126
+ else if (typeof (provider) === "function")
127
+ this.apiClient.httpClient = provider;
128
+ else if (provider) {
129
+ const apiClient = provider;
130
+ if (apiClient.httpClient)
131
+ this.apiClient.httpClient = apiClient.httpClient;
132
+ if (apiClient.url)
133
+ this.apiClient.url = apiClient.url;
134
+ if (apiClient.subscriptionClient)
135
+ this.apiClient.subscriptionClient = apiClient.subscriptionClient;
136
+ if (apiClient.wrapMessageHandling)
137
+ this.apiClient.wrapMessageHandling = apiClient.wrapMessageHandling;
138
+ }
139
+ }
140
+ /* @internal*/
141
+ liveQueryStorage;
142
+ subscriptionServer;
143
+ /* @internal*/
144
+ liveQueryPublisher = {
145
+ itemChanged: async () => { }
146
+ };
147
+ //@ts-ignore // type error of typescript regarding args that doesn't appear in my normal development
148
+ /** Used to call a `backendMethod` using a specific `remult` object
149
+ * @example
150
+ * await remult.call(TasksController.setAll, undefined, true);
151
+ * @param backendMethod - the backend method to call
152
+ * @param classInstance - the class instance of the backend method, for static backend methods use undefined
153
+ * @param args - the arguments to send to the backend method
154
+ */
155
+ call(backendMethod, classInstance, ...args) {
156
+ const z = (backendMethod[serverActionField]);
157
+ if (!z.doWork)
158
+ throw Error("The method received is not a valid backend method");
159
+ //@ts-ignore
160
+ return z.doWork(args, classInstance, this.apiClient.url, buildRestDataProvider(this.apiClient.httpClient));
161
+ }
162
+ /* @internal*/
163
+ liveQuerySubscriber = new LiveQueryClient(() => this.apiClient, () => this.user?.id);
164
+ /** A helper callback that can be used to debug and trace all find operations. Useful in debugging scenarios */
165
+ static onFind = (metadata, options) => { };
166
+ clearAllCache() {
167
+ this.repCache.clear();
168
+ }
169
+ /** A helper callback that is called whenever an entity is created. */
170
+ static entityRefInit;
171
+ /** context information that can be used to store custom information that will be disposed as part of the `remult` object */
172
+ context = {};
173
+ /** The api client that will be used by `remult` to perform calls to the `api` */
174
+ apiClient = {
175
+ url: '/api',
176
+ subscriptionClient: new SseSubscriptionClient()
177
+ };
178
+ static run(callback, options) {
179
+ const remult = new Remult();
180
+ if (options.dataProvider)
181
+ remult.dataProvider = options.dataProvider;
182
+ let r;
183
+ RemultAsyncLocalStorage.instance.run(remult, () => {
184
+ r = callback();
185
+ });
186
+ return r;
187
+ }
188
+ }
189
+ RemultProxy.defaultRemult = new Remult();
190
+ ;
191
+ export const allEntities = [];
192
+ export const classHelpers = new Map();
193
+ export class ClassHelper {
194
+ classes = new Map();
195
+ }
196
+ export function setControllerSettings(target, options) {
197
+ let r = target;
198
+ while (true) {
199
+ let helper = classHelpers.get(r);
200
+ if (!helper)
201
+ classHelpers.set(r, helper = new ClassHelper());
202
+ helper.classes.set(target, options);
203
+ let p = Object.getPrototypeOf(r.prototype);
204
+ if (p == null)
205
+ break;
206
+ r = p.constructor;
207
+ }
208
+ }
209
+ export class Allow {
210
+ static everyone = () => true;
211
+ static authenticated = (...args) => {
212
+ if (args.length > 1) {
213
+ return args[1].authenticated();
214
+ }
215
+ else if (args.length == 1) {
216
+ if (args[0].authenticated)
217
+ return args[0].authenticated();
218
+ }
219
+ return remult.authenticated();
220
+ };
221
+ }
222
+ export const queryConfig = {
223
+ defaultPageSize: 200
224
+ };
225
+ export class EventSource {
226
+ listeners = [];
227
+ async fire() {
228
+ for (const l of this.listeners) {
229
+ await l();
230
+ }
231
+ }
232
+ dispatcher = {
233
+ observe: async (what) => {
234
+ this.listeners.push(what);
235
+ await what();
236
+ return () => {
237
+ this.listeners = this.listeners.filter(x => x != what);
238
+ };
239
+ }
240
+ };
241
+ }
242
+ export async function doTransaction(remult, what) {
243
+ const trans = new transactionLiveQueryPublisher(remult.liveQueryPublisher);
244
+ let ok = true;
245
+ const result = await remult.dataProvider.transaction(async (ds) => {
246
+ remult.dataProvider = (ds);
247
+ remult.liveQueryPublisher = trans;
248
+ await what();
249
+ ok = true;
250
+ });
251
+ if (ok)
252
+ await trans.flush();
253
+ }
254
+ class transactionLiveQueryPublisher {
255
+ orig;
256
+ constructor(orig) {
257
+ this.orig = orig;
258
+ }
259
+ transactionItems = new Map();
260
+ async itemChanged(entityKey, changes) {
261
+ let items = this.transactionItems.get(entityKey);
262
+ if (!items) {
263
+ this.transactionItems.set(entityKey, items = []);
264
+ }
265
+ for (const c of changes) {
266
+ if (c.oldId !== undefined) {
267
+ const item = items.find(y => y.id === c.oldId);
268
+ if (item !== undefined) {
269
+ if (c.deleted)
270
+ item.deleted = true;
271
+ if (c.id != item.id)
272
+ item.id = c.id;
273
+ }
274
+ else
275
+ items.push(c);
276
+ }
277
+ else
278
+ items.push(c);
279
+ }
280
+ }
281
+ async flush() {
282
+ for (const key of this.transactionItems.keys()) {
283
+ await this.orig.itemChanged(key, this.transactionItems.get(key));
284
+ }
285
+ }
286
+ }
@@ -0,0 +1,39 @@
1
+ import { Remult } from './context';
2
+ import type { FindOptions, Repository } from './remult3';
3
+ import type { ErrorInfo } from './data-interfaces';
4
+ export declare class DataApi<T = any> {
5
+ private repository;
6
+ private remult;
7
+ constructor(repository: Repository<T>, remult: Remult);
8
+ httpGet(res: DataApiResponse, req: DataApiRequest, serializeContext: () => Promise<any>): Promise<void>;
9
+ httpPost(res: DataApiResponse, req: DataApiRequest, body: any, serializeContext: () => Promise<any>): Promise<void>;
10
+ static defaultGetLimit: number;
11
+ get(response: DataApiResponse, id: any): Promise<void>;
12
+ count(response: DataApiResponse, request: DataApiRequest, filterBody?: any): Promise<void>;
13
+ getArrayImpl(response: DataApiResponse, request: DataApiRequest, filterBody: any): Promise<{
14
+ r: any[];
15
+ findOptions: FindOptions<T>;
16
+ }>;
17
+ getArray(response: DataApiResponse, request: DataApiRequest, filterBody?: any): Promise<void>;
18
+ liveQuery(response: DataApiResponse, request: DataApiRequest, filterBody: any, serializeContext: () => Promise<any>, queryChannel: string): Promise<void>;
19
+ private buildWhere;
20
+ private doOnId;
21
+ put(response: DataApiResponse, id: any, body: any): Promise<void>;
22
+ delete(response: DataApiResponse, id: any): Promise<void>;
23
+ post(response: DataApiResponse, body: any): Promise<void>;
24
+ }
25
+ export interface DataApiResponse {
26
+ success(data: any): void;
27
+ deleted(): void;
28
+ created(data: any): void;
29
+ notFound(): void;
30
+ error(data: ErrorInfo): void;
31
+ forbidden(): void;
32
+ progress(progress: number): void;
33
+ }
34
+ export interface DataApiRequest {
35
+ get(key: string): any;
36
+ }
37
+ export declare function determineSort(sortUrlParm: string, dirUrlParam: string): any;
38
+ export declare function serializeError(data: ErrorInfo): ErrorInfo<any>;
39
+ export declare function getLiveQueryChannel(queryId: string, userId: string): string;
@@ -0,0 +1,279 @@
1
+ import { customUrlToken, buildFilterFromRequestParameters } from './filter/filter-interfaces';
2
+ import { doTransaction } from './context';
3
+ import { Filter } from './filter/filter-interfaces';
4
+ import { ForbiddenError } from './server-action';
5
+ import { findOptionsToJson, liveQueryAction } from './data-providers/rest-data-provider';
6
+ export class DataApi {
7
+ repository;
8
+ remult;
9
+ constructor(repository, remult) {
10
+ this.repository = repository;
11
+ this.remult = remult;
12
+ }
13
+ httpGet(res, req, serializeContext) {
14
+ const action = req?.get("__action");
15
+ if (action?.startsWith(liveQueryAction))
16
+ return this.liveQuery(res, req, undefined, serializeContext, getLiveQueryChannel(action.substring(liveQueryAction.length), this.remult.user?.id));
17
+ switch (action) {
18
+ case "get":
19
+ case "count":
20
+ return this.count(res, req, undefined);
21
+ }
22
+ return this.getArray(res, req, undefined);
23
+ }
24
+ async httpPost(res, req, body, serializeContext) {
25
+ const action = req?.get("__action");
26
+ if (action?.startsWith(liveQueryAction))
27
+ return this.liveQuery(res, req, undefined, serializeContext, getLiveQueryChannel(action.substring(liveQueryAction.length), this.remult.user?.id));
28
+ switch (action) {
29
+ case "get":
30
+ return this.getArray(res, req, body);
31
+ case "count":
32
+ return this.count(res, req, body);
33
+ case "endLiveQuery":
34
+ await this.remult.liveQueryStorage.remove(getLiveQueryChannel(body.id, this.remult.user?.id));
35
+ res.success("ok");
36
+ return;
37
+ default:
38
+ return this.post(res, body);
39
+ }
40
+ }
41
+ static defaultGetLimit = 0;
42
+ async get(response, id) {
43
+ if (!this.repository.metadata.apiReadAllowed) {
44
+ response.forbidden();
45
+ return;
46
+ }
47
+ await this.doOnId(response, id, async (row) => response.success(this.repository.getEntityRef(row).toApiJson()));
48
+ }
49
+ async count(response, request, filterBody) {
50
+ if (!this.repository.metadata.apiReadAllowed) {
51
+ response.forbidden();
52
+ return;
53
+ }
54
+ try {
55
+ response.success({ count: +await this.repository.count(await this.buildWhere(request, filterBody)) });
56
+ }
57
+ catch (err) {
58
+ response.error(err);
59
+ }
60
+ }
61
+ async getArrayImpl(response, request, filterBody) {
62
+ let findOptions = { load: () => [] };
63
+ findOptions.where = await this.buildWhere(request, filterBody);
64
+ if (request) {
65
+ let sort = request.get("_sort");
66
+ if (sort != undefined) {
67
+ let dir = request.get('_order');
68
+ findOptions.orderBy = determineSort(sort, dir);
69
+ }
70
+ let limit = +request.get("_limit");
71
+ if (!limit && DataApi.defaultGetLimit)
72
+ limit = DataApi.defaultGetLimit;
73
+ findOptions.limit = limit;
74
+ findOptions.page = +request.get("_page");
75
+ }
76
+ if (this.remult.isAllowed(this.repository.metadata.options.apiRequireId)) {
77
+ let hasId = false;
78
+ let w = await Filter.fromEntityFilter(this.repository.metadata, findOptions.where);
79
+ if (w) {
80
+ w.__applyToConsumer({
81
+ containsCaseInsensitive: () => { },
82
+ isDifferentFrom: () => { },
83
+ isEqualTo: (col, val) => {
84
+ if (this.repository.metadata.idMetadata.isIdField(col))
85
+ hasId = true;
86
+ },
87
+ custom: () => { },
88
+ databaseCustom: () => { },
89
+ isGreaterOrEqualTo: () => { },
90
+ isGreaterThan: () => { },
91
+ isIn: () => { },
92
+ isLessOrEqualTo: () => { },
93
+ isLessThan: () => { },
94
+ isNotNull: () => { },
95
+ isNull: () => { },
96
+ or: () => { }
97
+ });
98
+ }
99
+ if (!hasId) {
100
+ response.forbidden();
101
+ throw new ForbiddenError();
102
+ }
103
+ }
104
+ const r = await this.repository.find(findOptions)
105
+ .then(async (r) => {
106
+ return await Promise.all(r.map(async (y) => this.repository.getEntityRef(y).toApiJson()));
107
+ });
108
+ return { r, findOptions };
109
+ }
110
+ async getArray(response, request, filterBody) {
111
+ if (!this.repository.metadata.apiReadAllowed) {
112
+ response.forbidden();
113
+ return;
114
+ }
115
+ try {
116
+ const { r } = await this.getArrayImpl(response, request, filterBody);
117
+ response.success(r);
118
+ }
119
+ catch (err) {
120
+ if (err.isForbiddenError)
121
+ response.forbidden();
122
+ else
123
+ response.error(err);
124
+ }
125
+ }
126
+ async liveQuery(response, request, filterBody, serializeContext, queryChannel) {
127
+ if (!this.repository.metadata.apiReadAllowed) {
128
+ response.forbidden();
129
+ return;
130
+ }
131
+ try {
132
+ const r = await this.getArrayImpl(response, request, filterBody);
133
+ const data = {
134
+ requestJson: await serializeContext(),
135
+ findOptionsJson: findOptionsToJson(r.findOptions, this.repository.metadata),
136
+ lastIds: r.r.map(y => this.repository.metadata.idMetadata.getId(y))
137
+ };
138
+ await this.remult.liveQueryStorage.add({
139
+ entityKey: this.repository.metadata.key,
140
+ id: queryChannel,
141
+ data
142
+ });
143
+ response.success(r.r);
144
+ }
145
+ catch (err) {
146
+ if (err.isForbiddenError)
147
+ response.forbidden();
148
+ else
149
+ response.error(err);
150
+ }
151
+ }
152
+ async buildWhere(request, filterBody) {
153
+ var where = [];
154
+ if (this.repository.metadata.options.apiPrefilter) {
155
+ if (typeof this.repository.metadata.options.apiPrefilter === "function")
156
+ where.push(await this.repository.metadata.options.apiPrefilter());
157
+ else
158
+ where.push(this.repository.metadata.options.apiPrefilter);
159
+ }
160
+ if (request) {
161
+ where.push(buildFilterFromRequestParameters(this.repository.metadata, {
162
+ get: key => {
163
+ let result = request.get(key);
164
+ if (key.startsWith(customUrlToken) && result)
165
+ return JSON.parse(result);
166
+ return result;
167
+ }
168
+ }));
169
+ }
170
+ if (filterBody)
171
+ where.push(Filter.entityFilterFromJson(this.repository.metadata, filterBody));
172
+ return { $and: where };
173
+ }
174
+ async doOnId(response, id, what) {
175
+ try {
176
+ var where = [this.repository.metadata.idMetadata.getIdFilter(id)];
177
+ if (this.repository.metadata.options.apiPrefilter) {
178
+ if (typeof this.repository.metadata.options.apiPrefilter === "function")
179
+ where.push(await this.repository.metadata.options.apiPrefilter());
180
+ else
181
+ where.push(this.repository.metadata.options.apiPrefilter);
182
+ }
183
+ await this.repository.find({
184
+ where: { $and: where }
185
+ })
186
+ .then(async (r) => {
187
+ if (r.length == 0)
188
+ response.notFound();
189
+ else if (r.length > 1)
190
+ response.error({ message: "id is not unique" });
191
+ else
192
+ await what(r[0]);
193
+ });
194
+ }
195
+ catch (err) {
196
+ response.error(err);
197
+ }
198
+ }
199
+ async put(response, id, body) {
200
+ await this.doOnId(response, id, async (row) => {
201
+ let ref = this.repository.getEntityRef(row);
202
+ await ref._updateEntityBasedOnApi(body);
203
+ if (!ref.apiUpdateAllowed) {
204
+ response.forbidden();
205
+ return;
206
+ }
207
+ await ref.save();
208
+ response.success(ref.toApiJson());
209
+ });
210
+ }
211
+ async delete(response, id) {
212
+ await this.doOnId(response, id, async (row) => {
213
+ if (!this.repository.getEntityRef(row).apiDeleteAllowed) {
214
+ response.forbidden();
215
+ return;
216
+ }
217
+ await this.repository.getEntityRef(row).delete();
218
+ response.deleted();
219
+ });
220
+ }
221
+ async post(response, body) {
222
+ try {
223
+ const insert = async (what) => {
224
+ let newr = this.repository.create();
225
+ await this.repository.getEntityRef(newr)._updateEntityBasedOnApi(what);
226
+ if (!this.repository.getEntityRef(newr).apiInsertAllowed) {
227
+ throw new ForbiddenError();
228
+ }
229
+ await this.repository.getEntityRef(newr).save();
230
+ return this.repository.getEntityRef(newr).toApiJson();
231
+ };
232
+ if (Array.isArray(body)) {
233
+ const result = [];
234
+ await doTransaction(this.remult, async () => {
235
+ for (const item of body) {
236
+ result.push(await insert(item));
237
+ }
238
+ });
239
+ response.created(result);
240
+ }
241
+ else
242
+ response.created(await insert(body));
243
+ }
244
+ catch (err) {
245
+ if (err.isForbiddenError)
246
+ response.forbidden();
247
+ else
248
+ response.error(err);
249
+ }
250
+ }
251
+ }
252
+ export function determineSort(sortUrlParm, dirUrlParam) {
253
+ let dirItems = [];
254
+ if (dirUrlParam)
255
+ dirItems = dirUrlParam.split(',');
256
+ let result = {};
257
+ sortUrlParm.split(',').map((name, i) => {
258
+ let key = name.trim();
259
+ if (i < dirItems.length && dirItems[i].toLowerCase().trim().startsWith("d"))
260
+ return result[key] = "desc";
261
+ else
262
+ return result[key] = "asc";
263
+ });
264
+ return result;
265
+ }
266
+ export function serializeError(data) {
267
+ if (data instanceof TypeError) {
268
+ data = { message: data.message, stack: data.stack };
269
+ }
270
+ let x = JSON.parse(JSON.stringify(data));
271
+ if (!x.message && !x.modelState)
272
+ data = { message: data.message, stack: data.stack };
273
+ if (typeof x === 'string')
274
+ data = { message: x };
275
+ return data;
276
+ }
277
+ export function getLiveQueryChannel(queryId, userId) {
278
+ return `users:${userId}:queries:${queryId}`;
279
+ }
@@ -0,0 +1,41 @@
1
+ import { Sort } from './sort';
2
+ import { Filter } from './filter/filter-interfaces';
3
+ import { EntityMetadata, OmitEB } from './remult3';
4
+ export interface DataProvider {
5
+ getEntityDataProvider(entity: EntityMetadata): EntityDataProvider;
6
+ transaction(action: (dataProvider: DataProvider) => Promise<void>): Promise<void>;
7
+ ensureSchema?(entities: EntityMetadata[]): Promise<void>;
8
+ isProxy?: boolean;
9
+ }
10
+ export interface Storage {
11
+ ensureSchema(): Promise<void>;
12
+ }
13
+ export interface EntityDataProvider {
14
+ count(where: Filter): Promise<number>;
15
+ find(options?: EntityDataProviderFindOptions): Promise<Array<any>>;
16
+ update(id: any, data: any): Promise<any>;
17
+ delete(id: any): Promise<void>;
18
+ insert(data: any): Promise<any>;
19
+ }
20
+ export interface EntityDataProviderFindOptions {
21
+ where?: Filter;
22
+ limit?: number;
23
+ page?: number;
24
+ orderBy?: Sort;
25
+ }
26
+ export interface RestDataProviderHttpProvider {
27
+ post(url: string, data: any): Promise<any>;
28
+ delete(url: string): Promise<void>;
29
+ put(url: string, data: any): Promise<any>;
30
+ get(url: string): Promise<any>;
31
+ }
32
+ export declare function extractSort(sort: any): Sort;
33
+ export interface ErrorInfo<entityType = any> {
34
+ message?: string;
35
+ modelState?: {
36
+ [Properties in keyof Partial<OmitEB<entityType>>]?: string;
37
+ };
38
+ stack?: string;
39
+ exception?: any;
40
+ httpStatusCode?: number;
41
+ }
@@ -0,0 +1,12 @@
1
+ import { Sort } from './sort';
2
+ export function extractSort(sort) {
3
+ if (sort instanceof Sort)
4
+ return sort;
5
+ if (sort instanceof Array) {
6
+ let r = new Sort();
7
+ sort.forEach(i => {
8
+ r.Segments.push(i);
9
+ });
10
+ return r;
11
+ }
12
+ }
@@ -0,0 +1,22 @@
1
+ import { EntityDataProvider, EntityDataProviderFindOptions } from '../data-interfaces';
2
+ import { Filter } from '../filter/filter-interfaces';
3
+ import { EntityMetadata, EntityFilter } from '../remult3';
4
+ export declare class ArrayEntityDataProvider implements EntityDataProvider {
5
+ private entity;
6
+ private rows?;
7
+ static rawFilter(filter: CustomArrayFilter): EntityFilter<any>;
8
+ constructor(entity: EntityMetadata, rows?: any[] | undefined);
9
+ private verifyThatRowHasAllNotNullColumns;
10
+ count(where?: Filter): Promise<number>;
11
+ find(options?: EntityDataProviderFindOptions): Promise<any[]>;
12
+ translateFromJson(row: any): {};
13
+ translateToJson(row: any): {};
14
+ private idMatches;
15
+ update(id: any, data: any): Promise<any>;
16
+ delete(id: any): Promise<void>;
17
+ insert(data: any): Promise<any>;
18
+ }
19
+ export type CustomArrayFilter = (item: any) => boolean;
20
+ export interface CustomArrayFilterObject {
21
+ arrayFilter: CustomArrayFilter;
22
+ }