remult 0.22.3 → 0.22.4

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 (253) 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/remult3/RepositoryImplementation.d.ts +1 -1
  228. package/esm/src/remult3/RepositoryImplementation.js +27 -4
  229. package/esm/src/shared-tests/db-tests.db-tests.js +57 -0
  230. package/esm/test-servers/shared/Task.d.ts +9 -0
  231. package/esm/test-servers/shared/Task.js +32 -0
  232. package/esm/test.d.ts +5 -0
  233. package/esm/test.js +6 -0
  234. package/package.json +1 -1
  235. package/src/remult3/RepositoryImplementation.d.ts +1 -1
  236. package/src/remult3/RepositoryImplementation.js +88 -63
  237. package/src/shared-tests/db-tests.db-tests.js +97 -0
  238. package/esm/src/id-entity.d.ts +0 -4
  239. package/esm/src/id-entity.js +0 -8
  240. package/postgres/postgresColumnSyntax.d.ts +0 -2
  241. package/postgres/postgresColumnSyntax.js +0 -34
  242. package/remult-middleware.d.ts +0 -2
  243. package/remult-middleware.js +0 -70
  244. package/server/register-actions-on-server.d.ts +0 -3
  245. package/server/register-actions-on-server.js +0 -50
  246. package/server/register-entities-on-server.d.ts +0 -3
  247. package/server/register-entities-on-server.js +0 -19
  248. package/src/backend-tests/my-test.backend-spec.js +0 -217
  249. package/src/backend-tests/test-http-server.backend-spec.d.ts +0 -6
  250. package/src/backend-tests/test-http-server.backend-spec.js +0 -342
  251. package/src/id-entity.d.ts +0 -4
  252. package/src/id-entity.js +0 -17
  253. package/valueConverters.js +0 -168
@@ -0,0 +1,86 @@
1
+ import { buildRestDataProvider } from "../buildRestDataProvider";
2
+ import { remult } from "../remult-proxy";
3
+ import { actionInfo } from "../server-action";
4
+ import { streamUrl } from "./SubscriptionChannel";
5
+ export class SseSubscriptionClient {
6
+ openConnection(onReconnect) {
7
+ let connectionId;
8
+ const channels = new Map();
9
+ const provider = buildRestDataProvider(remult.apiClient.httpClient);
10
+ let connected = false;
11
+ let source;
12
+ const client = {
13
+ close() {
14
+ source.close();
15
+ },
16
+ async subscribe(channel, handler) {
17
+ let listeners = channels.get(channel);
18
+ if (!listeners) {
19
+ channels.set(channel, listeners = []);
20
+ await subscribeToChannel(channel);
21
+ }
22
+ listeners.push(handler);
23
+ return () => {
24
+ listeners.splice(listeners.indexOf(handler, 1));
25
+ if (listeners.length == 0) {
26
+ actionInfo.runActionWithoutBlockingUI(() => provider.post(remult.apiClient.url + '/' + streamUrl + '/unsubscribe', {
27
+ channel: channel,
28
+ clientId: connectionId
29
+ }));
30
+ channels.delete(channel);
31
+ }
32
+ };
33
+ },
34
+ };
35
+ const createConnectionPromise = () => new Promise((res) => {
36
+ createConnection();
37
+ function createConnection() {
38
+ if (source)
39
+ source.close();
40
+ source = new EventSource(remult.apiClient.url + '/' + streamUrl, {
41
+ withCredentials: true
42
+ });
43
+ source.onmessage = e => {
44
+ let message = JSON.parse(e.data);
45
+ const listeners = channels.get(message.channel);
46
+ if (listeners)
47
+ listeners.forEach(x => x(message.data));
48
+ };
49
+ source.onerror = e => {
50
+ console.error("Live Query Event Source Error", e);
51
+ source.close();
52
+ setTimeout(() => {
53
+ createConnection();
54
+ }, 500);
55
+ };
56
+ source.addEventListener("connectionId", async (e) => {
57
+ //@ts-ignore
58
+ connectionId = e.data;
59
+ if (connected) {
60
+ for (const channel of channels.keys()) {
61
+ await subscribeToChannel(channel);
62
+ }
63
+ onReconnect();
64
+ }
65
+ else {
66
+ connected = true;
67
+ res(client);
68
+ }
69
+ });
70
+ }
71
+ });
72
+ return createConnectionPromise();
73
+ async function subscribeToChannel(channel) {
74
+ const result = await actionInfo.runActionWithoutBlockingUI(() => {
75
+ return provider.post(remult.apiClient.url + '/' + streamUrl + '/subscribe', {
76
+ channel: channel,
77
+ clientId: connectionId
78
+ });
79
+ });
80
+ if (result === ConnectionNotFoundError) {
81
+ await createConnectionPromise();
82
+ }
83
+ }
84
+ }
85
+ }
86
+ export const ConnectionNotFoundError = "client connection not found";
@@ -0,0 +1,72 @@
1
+ import { FindOptions, Remult } from '../../index';
2
+ import type { LiveQueryChangeInfo, RepositoryImplementation } from '../remult3';
3
+ export declare const streamUrl = "stream";
4
+ export declare class LiveQuerySubscriber<entityType> {
5
+ private repo;
6
+ private query;
7
+ sendDefaultState(onResult: (info: LiveQueryChangeInfo<entityType>) => void): void;
8
+ queryChannel: string;
9
+ subscribeCode: () => void;
10
+ unsubscribe: VoidFunction;
11
+ setAllItems(result: any[]): Promise<void>;
12
+ private allItemsMessage;
13
+ forListeners(what: (listener: (((reducer: (prevState: entityType[]) => entityType[]) => void))) => void, changes: LiveQueryChange[]): void;
14
+ private createReducerType;
15
+ handle(messages: LiveQueryChange[]): Promise<void>;
16
+ defaultQueryState: entityType[];
17
+ listeners: SubscriptionListener<LiveQueryChangeInfo<entityType>>[];
18
+ id: any;
19
+ constructor(repo: RepositoryImplementation<entityType>, query: SubscribeToQueryArgs<entityType>, userId: string);
20
+ }
21
+ export interface SubscriptionListener<type> {
22
+ next(message: type): void;
23
+ error(err: any): void;
24
+ complete(): void;
25
+ }
26
+ export type Unsubscribe = VoidFunction;
27
+ export interface SubscriptionClientConnection {
28
+ subscribe(channel: string, onMessage: (message: any) => void, onError: (err: any) => void): Promise<Unsubscribe>;
29
+ close(): void;
30
+ }
31
+ export interface SubscriptionClient {
32
+ openConnection(onReconnect: VoidFunction): Promise<SubscriptionClientConnection>;
33
+ }
34
+ export declare const liveQueryKeepAliveRoute = "_liveQueryKeepAlive";
35
+ interface SubscribeToQueryArgs<entityType = any> {
36
+ entityKey: string;
37
+ options: FindOptions<entityType>;
38
+ }
39
+ export declare type LiveQueryChange = {
40
+ type: "all";
41
+ data: any[];
42
+ } | {
43
+ type: "add";
44
+ data: any;
45
+ } | {
46
+ type: 'replace';
47
+ data: {
48
+ oldId: any;
49
+ item: any;
50
+ };
51
+ } | {
52
+ type: "remove";
53
+ data: {
54
+ id: any;
55
+ };
56
+ };
57
+ export interface SubscribeResult {
58
+ result: [];
59
+ queryChannel: string;
60
+ }
61
+ export interface ServerEventChannelSubscribeDTO {
62
+ clientId: string;
63
+ channel: string;
64
+ }
65
+ export declare class SubscriptionChannel<messageType> {
66
+ channelKey: string;
67
+ constructor(channelKey: string);
68
+ publish(message: messageType, remult?: Remult): void;
69
+ subscribe(next: (message: messageType) => void, remult?: Remult): Promise<Unsubscribe>;
70
+ subscribe(listener: Partial<SubscriptionListener<messageType>>): Promise<Unsubscribe>;
71
+ }
72
+ export {};
@@ -0,0 +1,123 @@
1
+ import { remult as defaultRemult, Sort } from '../../index';
2
+ import { v4 as uuid } from 'uuid';
3
+ import { getLiveQueryChannel } from '../data-api';
4
+ export const streamUrl = 'stream';
5
+ //@internal
6
+ export class LiveQuerySubscriber {
7
+ repo;
8
+ query;
9
+ sendDefaultState(onResult) {
10
+ onResult(this.createReducerType(() => [...this.defaultQueryState], this.allItemsMessage(this.defaultQueryState)));
11
+ }
12
+ queryChannel;
13
+ subscribeCode;
14
+ unsubscribe = () => { };
15
+ async setAllItems(result) {
16
+ const items = await this.repo.fromJsonArray(result, this.query.options.load);
17
+ this.forListeners(listener => {
18
+ listener(x => {
19
+ return items;
20
+ });
21
+ }, this.allItemsMessage(items));
22
+ }
23
+ allItemsMessage(items) {
24
+ return [
25
+ {
26
+ type: "all",
27
+ data: items
28
+ }
29
+ ];
30
+ }
31
+ forListeners(what, changes) {
32
+ what(reducer => {
33
+ this.defaultQueryState = reducer(this.defaultQueryState);
34
+ if (changes.find(c => c.type === "add" || c.type === "replace")) {
35
+ if (this.query.options.orderBy) {
36
+ const o = Sort.translateOrderByToSort(this.repo.metadata, this.query.options.orderBy);
37
+ this.defaultQueryState.sort((a, b) => o.compare(a, b));
38
+ }
39
+ }
40
+ });
41
+ for (const l of this.listeners) {
42
+ what(reducer => {
43
+ l.next(this.createReducerType(reducer, changes));
44
+ });
45
+ }
46
+ }
47
+ createReducerType(applyChanges, changes) {
48
+ return {
49
+ applyChanges,
50
+ changes,
51
+ items: this.defaultQueryState
52
+ };
53
+ }
54
+ async handle(messages) {
55
+ {
56
+ let x = messages.filter(({ type }) => type == "add" || type == "replace");
57
+ let loadedItems = await this.repo.fromJsonArray(x.map(m => m.data.item), this.query.options.load);
58
+ for (let index = 0; index < x.length; index++) {
59
+ const element = x[index];
60
+ element.data.item = loadedItems[index];
61
+ }
62
+ }
63
+ this.forListeners(listener => {
64
+ listener(items => {
65
+ if (!items)
66
+ items = [];
67
+ for (const message of messages) {
68
+ switch (message.type) {
69
+ case "all":
70
+ this.setAllItems(message.data);
71
+ break;
72
+ case "replace": {
73
+ items = items.map(x => this.repo.metadata.idMetadata.getId(x) === message.data.oldId ? message.data.item : x);
74
+ break;
75
+ }
76
+ case "add":
77
+ items = items.filter(x => this.repo.metadata.idMetadata.getId(x) !== this.repo.metadata.idMetadata.getId(message.data.item));
78
+ items.push(message.data.item);
79
+ break;
80
+ case "remove":
81
+ items = items.filter(x => this.repo.metadata.idMetadata.getId(x) !== message.data.id);
82
+ break;
83
+ }
84
+ ;
85
+ }
86
+ return items;
87
+ });
88
+ }, messages);
89
+ }
90
+ defaultQueryState = [];
91
+ listeners = [];
92
+ id = uuid();
93
+ constructor(repo, query, userId) {
94
+ this.repo = repo;
95
+ this.query = query;
96
+ this.queryChannel = getLiveQueryChannel(this.id, userId);
97
+ }
98
+ }
99
+ export const liveQueryKeepAliveRoute = '_liveQueryKeepAlive';
100
+ export class SubscriptionChannel {
101
+ channelKey;
102
+ constructor(channelKey) {
103
+ this.channelKey = channelKey;
104
+ }
105
+ publish(message, remult) {
106
+ remult = remult || defaultRemult;
107
+ remult.subscriptionServer.publishMessage(this.channelKey, message);
108
+ }
109
+ //@internal
110
+ subscribe(next, remult) {
111
+ remult = remult || defaultRemult;
112
+ let listener = next;
113
+ if (typeof (next) === "function") {
114
+ listener = {
115
+ next
116
+ };
117
+ }
118
+ listener.error ??= () => { };
119
+ listener.complete ??= () => { };
120
+ return remult.liveQuerySubscriber.subscribeChannel(this.channelKey, listener);
121
+ }
122
+ }
123
+ //TODO2 - consider moving the queued job mechanism into this.
@@ -0,0 +1,53 @@
1
+ import { itemChange } from '../context';
2
+ import { Repository } from '../remult3';
3
+ export interface SubscriptionServer {
4
+ publishMessage<T>(channel: string, message: T): Promise<void>;
5
+ }
6
+ export declare type PerformWithContext = (serializedRequest: any, entityKey: string, what: (repo: Repository<any>) => Promise<void>) => Promise<void>;
7
+ export declare class LiveQueryPublisher implements LiveQueryChangesListener {
8
+ private subscriptionServer;
9
+ private liveQueryStorage;
10
+ performWithContext: PerformWithContext;
11
+ constructor(subscriptionServer: () => SubscriptionServer, liveQueryStorage: () => LiveQueryStorage, performWithContext: PerformWithContext);
12
+ runPromise(p: Promise<any>): void;
13
+ debugFileSaver: (x: any) => void;
14
+ itemChanged(entityKey: string, changes: itemChange[]): Promise<void>;
15
+ }
16
+ export interface LiveQueryChangesListener {
17
+ itemChanged(entityKey: string, changes: itemChange[]): Promise<void>;
18
+ }
19
+ export interface LiveQueryStorage {
20
+ add(query: StoredQuery): Promise<void>;
21
+ remove(queryId: string): Promise<void>;
22
+ forEach(entityKey: string, callback: (args: {
23
+ query: StoredQuery;
24
+ setData(data: any): Promise<void>;
25
+ }) => Promise<void>): Promise<void>;
26
+ keepAliveAndReturnUnknownQueryIds(queryIds: string[]): Promise<string[]>;
27
+ }
28
+ export declare class InMemoryLiveQueryStorage implements LiveQueryStorage {
29
+ debugFileSaver: (x: any) => void;
30
+ debug(): void;
31
+ keepAliveAndReturnUnknownQueryIds(ids: string[]): Promise<string[]>;
32
+ queries: (StoredQuery & {
33
+ lastUsed: string;
34
+ })[];
35
+ constructor();
36
+ add(query: StoredQuery): Promise<void>;
37
+ removeCountForTesting: number;
38
+ remove(id: any): Promise<void>;
39
+ forEach(entityKey: string, handle: (args: {
40
+ query: StoredQuery;
41
+ setData(data: any): Promise<void>;
42
+ }) => Promise<void>): Promise<void>;
43
+ }
44
+ export interface StoredQuery {
45
+ entityKey: string;
46
+ id: string;
47
+ data: any;
48
+ }
49
+ export interface QueryData {
50
+ findOptionsJson: any;
51
+ requestJson: any;
52
+ lastIds: any[];
53
+ }
@@ -0,0 +1,111 @@
1
+ import { findOptionsFromJson } from '../data-providers/rest-data-provider';
2
+ /* @internal*/
3
+ export class LiveQueryPublisher {
4
+ subscriptionServer;
5
+ liveQueryStorage;
6
+ performWithContext;
7
+ constructor(subscriptionServer, liveQueryStorage, performWithContext) {
8
+ this.subscriptionServer = subscriptionServer;
9
+ this.liveQueryStorage = liveQueryStorage;
10
+ this.performWithContext = performWithContext;
11
+ }
12
+ runPromise(p) { }
13
+ debugFileSaver = (x) => { };
14
+ async itemChanged(entityKey, changes) {
15
+ //TODO 2 - optimize so that the user will get their messages first. Based on user id
16
+ await (this.liveQueryStorage().forEach(entityKey, async ({ query: q, setData }) => {
17
+ let query = { ...q.data };
18
+ await this.performWithContext(query.requestJson, entityKey, async (repo) => {
19
+ const messages = [];
20
+ const currentItems = await repo.find(findOptionsFromJson(query.findOptionsJson, repo.metadata));
21
+ const currentIds = currentItems.map(x => repo.getEntityRef(x).getId());
22
+ for (const id of query.lastIds.filter(y => !currentIds.includes(y))) {
23
+ let c = changes.find(c => c.oldId == id);
24
+ if (c === undefined || id != c.oldId || !currentIds.includes(c.id))
25
+ messages.push({
26
+ type: "remove",
27
+ data: {
28
+ id: id
29
+ }
30
+ });
31
+ }
32
+ for (const item of currentItems) {
33
+ const itemRef = repo.getEntityRef(item);
34
+ let c = changes.find(c => c.id == itemRef.getId());
35
+ if (c !== undefined && query.lastIds.includes(c.oldId)) {
36
+ messages.push({
37
+ type: "replace",
38
+ data: {
39
+ oldId: c.oldId,
40
+ item: itemRef.toApiJson()
41
+ }
42
+ });
43
+ }
44
+ else if (!query.lastIds.includes(itemRef.getId())) {
45
+ messages.push({
46
+ type: "add",
47
+ data: { item: itemRef.toApiJson() }
48
+ });
49
+ }
50
+ }
51
+ this.debugFileSaver({
52
+ query: q.id,
53
+ currentIds,
54
+ changes,
55
+ lastIds: query.lastIds,
56
+ messages
57
+ });
58
+ query.lastIds = currentIds;
59
+ await setData(query);
60
+ if (messages.length > 0)
61
+ this.subscriptionServer().publishMessage(q.id, messages);
62
+ });
63
+ }));
64
+ }
65
+ }
66
+ export class InMemoryLiveQueryStorage {
67
+ debugFileSaver = (x) => { };
68
+ debug() {
69
+ this.debugFileSaver(this.queries);
70
+ }
71
+ async keepAliveAndReturnUnknownQueryIds(ids) {
72
+ const result = [];
73
+ for (const id of ids) {
74
+ let q = this.queries.find(q => q.id === id);
75
+ if (q) {
76
+ q.lastUsed = new Date().toISOString();
77
+ }
78
+ else
79
+ result.push(id);
80
+ }
81
+ this.debug();
82
+ return result;
83
+ }
84
+ queries = [];
85
+ constructor() {
86
+ }
87
+ async add(query) {
88
+ this.queries.push({ ...query, lastUsed: new Date().toISOString() });
89
+ this.debug();
90
+ }
91
+ removeCountForTesting = 0;
92
+ async remove(id) {
93
+ this.queries = this.queries.filter(q => q.id !== id);
94
+ this.removeCountForTesting++;
95
+ this.debug();
96
+ }
97
+ async forEach(entityKey, handle) {
98
+ let d = new Date();
99
+ d.setMinutes(d.getMinutes() - 5);
100
+ this.queries = this.queries.filter(x => x.lastUsed > d.toISOString());
101
+ for (const q of this.queries) {
102
+ if (q.entityKey === entityKey) {
103
+ await handle({
104
+ query: q,
105
+ setData: async (data) => { q.data = data; },
106
+ });
107
+ }
108
+ }
109
+ this.debug();
110
+ }
111
+ }
@@ -0,0 +1,6 @@
1
+ export declare class eventTestEntity {
2
+ id: number;
3
+ title: string;
4
+ selectUser: string;
5
+ birthDate: Date;
6
+ }