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,477 @@
1
+ import { getEntityRef, getEntitySettings } from "../remult3";
2
+ export class Filter {
3
+ apply;
4
+ constructor(apply) {
5
+ this.apply = apply;
6
+ if (!this.apply) {
7
+ this.apply = () => { };
8
+ }
9
+ }
10
+ __applyToConsumer(add) {
11
+ this.apply(add);
12
+ }
13
+ static async resolve(filter) {
14
+ if (typeof filter === "function")
15
+ return await filter();
16
+ return filter;
17
+ }
18
+ static createCustom(rawFilterTranslator, key = '') {
19
+ let rawFilterInfo = { key: key, rawFilterTranslator };
20
+ return Object.assign((x) => {
21
+ let z = {};
22
+ if (x == undefined)
23
+ x = {};
24
+ if (!rawFilterInfo.key)
25
+ throw "Usage of custom filter before a key was assigned to it";
26
+ return {
27
+ [customUrlToken + rawFilterInfo.key]: x
28
+ };
29
+ }, { rawFilterInfo });
30
+ }
31
+ static fromEntityFilter(entity, whereItem) {
32
+ let result = [];
33
+ for (const key in whereItem) {
34
+ if (Object.prototype.hasOwnProperty.call(whereItem, key)) {
35
+ let fieldToFilter = whereItem[key];
36
+ {
37
+ if (key == "$or") {
38
+ result.push(new OrFilter(...fieldToFilter.map(x => Filter.fromEntityFilter(entity, x))));
39
+ }
40
+ else if (key == "$and") {
41
+ result.push(new AndFilter(...fieldToFilter.map(x => Filter.fromEntityFilter(entity, x))));
42
+ }
43
+ else if (key.startsWith(customUrlToken)) {
44
+ result.push(new Filter(x => {
45
+ x.custom(key.substring(customUrlToken.length), fieldToFilter);
46
+ }));
47
+ }
48
+ else if (key == customDatabaseFilterToken) {
49
+ result.push(new Filter(x => x.databaseCustom(fieldToFilter)));
50
+ }
51
+ else {
52
+ let fh = new filterHelper(entity.fields[key]);
53
+ let found = false;
54
+ if (fieldToFilter !== undefined && fieldToFilter != null) {
55
+ if (fieldToFilter.$id)
56
+ fieldToFilter = fieldToFilter.$id;
57
+ for (const key in fieldToFilter) {
58
+ if (Object.prototype.hasOwnProperty.call(fieldToFilter, key)) {
59
+ const element = fieldToFilter[key];
60
+ switch (key) {
61
+ case "$gte":
62
+ case ">=":
63
+ result.push(fh.isGreaterOrEqualTo(element));
64
+ found = true;
65
+ break;
66
+ case "$gt":
67
+ case ">":
68
+ result.push(fh.isGreaterThan(element));
69
+ found = true;
70
+ break;
71
+ case "$lte":
72
+ case "<=":
73
+ result.push(fh.isLessOrEqualTo(element));
74
+ found = true;
75
+ break;
76
+ case "$lt":
77
+ case "<":
78
+ result.push(fh.isLessThan(element));
79
+ found = true;
80
+ break;
81
+ case "$ne":
82
+ case "!=":
83
+ case "$nin":
84
+ found = true;
85
+ if (Array.isArray(element)) {
86
+ result.push(fh.isNotIn(element));
87
+ }
88
+ else
89
+ result.push(fh.isDifferentFrom(element));
90
+ break;
91
+ case "$in":
92
+ found = true;
93
+ result.push(fh.isIn(element));
94
+ break;
95
+ case "$contains":
96
+ found = true;
97
+ result.push(fh.contains(element));
98
+ break;
99
+ }
100
+ }
101
+ }
102
+ if (Array.isArray(fieldToFilter)) {
103
+ found = true;
104
+ result.push(fh.isIn(fieldToFilter));
105
+ }
106
+ }
107
+ if (!found && fieldToFilter !== undefined) {
108
+ result.push(fh.isEqualTo(fieldToFilter));
109
+ }
110
+ }
111
+ }
112
+ }
113
+ }
114
+ return new AndFilter(...result);
115
+ }
116
+ toJson() {
117
+ let r = new FilterSerializer();
118
+ this.__applyToConsumer(r);
119
+ return r.result;
120
+ }
121
+ static entityFilterToJson(entityDefs, where) {
122
+ return Filter.fromEntityFilter(entityDefs, where).toJson();
123
+ }
124
+ static entityFilterFromJson(entityDefs, packed) {
125
+ return buildFilterFromRequestParameters(entityDefs, { get: (key) => packed[key] });
126
+ }
127
+ static async translateCustomWhere(r, entity, remult) {
128
+ let f = new customTranslator(async (filterKey, custom) => {
129
+ let r = [];
130
+ for (const key in entity.entityType) {
131
+ const element = entity.entityType[key];
132
+ if (element && element.rawFilterInfo && element.rawFilterInfo.rawFilterTranslator) {
133
+ if (element.rawFilterInfo.key == filterKey) {
134
+ r.push(await Filter.fromEntityFilter(entity, await element.rawFilterInfo.rawFilterTranslator(custom, remult)));
135
+ }
136
+ }
137
+ }
138
+ return r;
139
+ });
140
+ r.__applyToConsumer(f);
141
+ await f.resolve();
142
+ r = new Filter(x => f.applyTo(x));
143
+ return r;
144
+ }
145
+ }
146
+ export class filterHelper {
147
+ metadata;
148
+ constructor(metadata) {
149
+ this.metadata = metadata;
150
+ }
151
+ processVal(val) {
152
+ let ei = getEntitySettings(this.metadata.valueType, false);
153
+ if (ei) {
154
+ if (!val)
155
+ return null;
156
+ if (typeof val === "string" || typeof val === "number")
157
+ return val;
158
+ return getEntityRef(val).getId();
159
+ }
160
+ return val;
161
+ }
162
+ contains(val) {
163
+ return new Filter(add => add.containsCaseInsensitive(this.metadata, val));
164
+ }
165
+ isLessThan(val) {
166
+ val = this.processVal(val);
167
+ return new Filter(add => add.isLessThan(this.metadata, val));
168
+ }
169
+ isGreaterOrEqualTo(val) {
170
+ val = this.processVal(val);
171
+ return new Filter(add => add.isGreaterOrEqualTo(this.metadata, val));
172
+ }
173
+ isNotIn(values) {
174
+ return new Filter(add => {
175
+ for (const v of values) {
176
+ add.isDifferentFrom(this.metadata, this.processVal(v));
177
+ }
178
+ });
179
+ }
180
+ isDifferentFrom(val) {
181
+ val = this.processVal(val);
182
+ if ((val === null || val === undefined) && this.metadata.allowNull)
183
+ return new Filter(add => add.isNotNull(this.metadata));
184
+ return new Filter(add => add.isDifferentFrom(this.metadata, val));
185
+ }
186
+ isLessOrEqualTo(val) {
187
+ val = this.processVal(val);
188
+ return new Filter(add => add.isLessOrEqualTo(this.metadata, val));
189
+ }
190
+ isGreaterThan(val) {
191
+ val = this.processVal(val);
192
+ return new Filter(add => add.isGreaterThan(this.metadata, val));
193
+ }
194
+ isEqualTo(val) {
195
+ val = this.processVal(val);
196
+ if ((val === null || val === undefined) && this.metadata.allowNull)
197
+ return new Filter(add => add.isNull(this.metadata));
198
+ return new Filter(add => add.isEqualTo(this.metadata, val));
199
+ }
200
+ isIn(val) {
201
+ val = val.map(x => this.processVal(x));
202
+ return new Filter(add => add.isIn(this.metadata, val));
203
+ }
204
+ }
205
+ export class AndFilter extends Filter {
206
+ filters;
207
+ constructor(...filters) {
208
+ super(add => {
209
+ for (const iterator of this.filters) {
210
+ if (iterator)
211
+ iterator.__applyToConsumer(add);
212
+ }
213
+ });
214
+ this.filters = filters;
215
+ }
216
+ add(filter) {
217
+ this.filters.push(filter);
218
+ }
219
+ }
220
+ export class OrFilter extends Filter {
221
+ filters;
222
+ constructor(...filters) {
223
+ super(add => {
224
+ let f = this.filters.filter(x => x !== undefined);
225
+ if (f.length > 1) {
226
+ add.or(f);
227
+ }
228
+ else if (f.length == 1)
229
+ f[0].__applyToConsumer(add);
230
+ });
231
+ this.filters = filters;
232
+ }
233
+ }
234
+ export const customUrlToken = "$custom$";
235
+ export const customDatabaseFilterToken = "$db$";
236
+ export class FilterSerializer {
237
+ result = {};
238
+ constructor() {
239
+ }
240
+ databaseCustom(databaseCustom) {
241
+ throw new Error("database custom is not allowed with api calls.");
242
+ }
243
+ custom(key, customItem) {
244
+ this.add(customUrlToken + key, customItem);
245
+ }
246
+ hasUndefined = false;
247
+ add(key, val) {
248
+ if (val === undefined)
249
+ this.hasUndefined = true;
250
+ let r = this.result;
251
+ if (!r[key]) {
252
+ r[key] = val;
253
+ return;
254
+ }
255
+ let v = r[key];
256
+ if (v instanceof Array) {
257
+ v.push(val);
258
+ }
259
+ else
260
+ v = [v, val];
261
+ r[key] = v;
262
+ }
263
+ or(orElements) {
264
+ this.add("OR", orElements.map(x => {
265
+ let f = new FilterSerializer();
266
+ x.__applyToConsumer(f);
267
+ return f.result;
268
+ }));
269
+ }
270
+ isNull(col) {
271
+ this.add(col.key + ".null", true);
272
+ }
273
+ isNotNull(col) {
274
+ this.add(col.key + ".null", false);
275
+ }
276
+ isIn(col, val) {
277
+ this.add(col.key + ".in", val.map(x => col.valueConverter.toJson(x)));
278
+ }
279
+ isEqualTo(col, val) {
280
+ this.add(col.key, col.valueConverter.toJson(val));
281
+ }
282
+ isDifferentFrom(col, val) {
283
+ this.add(col.key + '.ne', col.valueConverter.toJson(val));
284
+ }
285
+ isGreaterOrEqualTo(col, val) {
286
+ this.add(col.key + '.gte', col.valueConverter.toJson(val));
287
+ }
288
+ isGreaterThan(col, val) {
289
+ this.add(col.key + '.gt', col.valueConverter.toJson(val));
290
+ }
291
+ isLessOrEqualTo(col, val) {
292
+ this.add(col.key + '.lte', col.valueConverter.toJson(val));
293
+ }
294
+ isLessThan(col, val) {
295
+ this.add(col.key + '.lt', col.valueConverter.toJson(val));
296
+ }
297
+ containsCaseInsensitive(col, val) {
298
+ this.add(col.key + ".contains", val);
299
+ }
300
+ }
301
+ export function entityFilterToJson(entityDefs, where) {
302
+ if (!where)
303
+ return {};
304
+ return (Filter.fromEntityFilter(entityDefs, where)).toJson();
305
+ }
306
+ export function buildFilterFromRequestParameters(entity, filterInfo) {
307
+ let where = [];
308
+ [...entity.fields].forEach(col => {
309
+ function addFilter(operation, theFilter, jsonArray = false, asString = false) {
310
+ let val = filterInfo.get(col.key + operation);
311
+ if (val !== undefined) {
312
+ let addFilter = (val) => {
313
+ let theVal = val;
314
+ if (jsonArray) {
315
+ let arr;
316
+ if (typeof val === 'string')
317
+ arr = JSON.parse(val);
318
+ else
319
+ arr = val;
320
+ theVal = arr.map(x => asString ? x : col.valueConverter.fromJson(x));
321
+ }
322
+ else {
323
+ theVal = asString ? theVal : col.valueConverter.fromJson(theVal);
324
+ }
325
+ let f = theFilter(theVal);
326
+ if (f !== undefined) {
327
+ where.push({ [col.key]: f });
328
+ }
329
+ };
330
+ if (!jsonArray && val instanceof Array) {
331
+ val.forEach(v => {
332
+ addFilter(v);
333
+ });
334
+ }
335
+ else {
336
+ if (jsonArray) {
337
+ if (typeof val === 'string')
338
+ val = JSON.parse(val);
339
+ }
340
+ const array = separateArrayFromInnerArray(val);
341
+ for (const x of array) {
342
+ addFilter(x);
343
+ }
344
+ }
345
+ }
346
+ }
347
+ let c = new filterHelper(col);
348
+ addFilter('', val => val);
349
+ addFilter('.gt', val => ({ "$gt": val }));
350
+ addFilter('.gte', val => ({ "$gte": val }));
351
+ addFilter('.lt', val => ({ "$lt": val }));
352
+ addFilter('.lte', val => ({ "$lte": val }));
353
+ addFilter('.ne', val => ({ "$ne": val }));
354
+ addFilter('.in', val => val, true);
355
+ var nullFilter = filterInfo.get(col.key + ".null");
356
+ if (nullFilter) {
357
+ nullFilter = nullFilter.toString().trim().toLowerCase();
358
+ switch (nullFilter) {
359
+ case "y":
360
+ case "true":
361
+ case "yes":
362
+ where.push({ [col.key]: null });
363
+ break;
364
+ default:
365
+ where.push({ [col.key]: { "$ne": null } });
366
+ break;
367
+ }
368
+ }
369
+ addFilter('.contains', val => ({ $contains: val }), false, true);
370
+ });
371
+ let val = filterInfo.get('OR');
372
+ if (val) {
373
+ const array = separateArrayFromInnerArray(val);
374
+ where.push({
375
+ $and: array.map(v => ({
376
+ $or: v.map(x => buildFilterFromRequestParameters(entity, { get: (key) => x[key] }))
377
+ }))
378
+ });
379
+ }
380
+ for (const key in entity.entityType) {
381
+ const element = entity.entityType[key];
382
+ if (element && element.rawFilterInfo && element.rawFilterInfo.rawFilterTranslator) {
383
+ let custom = filterInfo.get(customUrlToken + key);
384
+ if (custom !== undefined) {
385
+ where.push({ [customUrlToken + key]: custom });
386
+ }
387
+ }
388
+ }
389
+ return { $and: where };
390
+ function separateArrayFromInnerArray(val) {
391
+ if (!Array.isArray(val))
392
+ return [val];
393
+ const nonArray = [], array = [];
394
+ for (const v of val) {
395
+ if (Array.isArray(v)) {
396
+ array.push(v);
397
+ }
398
+ else
399
+ nonArray.push(v);
400
+ }
401
+ array.push(nonArray);
402
+ return array;
403
+ }
404
+ }
405
+ class customTranslator {
406
+ translateCustom;
407
+ applyTo(x) {
408
+ this.commands.forEach(y => y(x));
409
+ }
410
+ constructor(translateCustom) {
411
+ this.translateCustom = translateCustom;
412
+ }
413
+ commands = [];
414
+ promises = [];
415
+ or(orElements) {
416
+ let newOrElements;
417
+ this.promises.push(Promise.all(orElements.map(async (element) => {
418
+ let c = new customTranslator(this.translateCustom);
419
+ element.__applyToConsumer(c);
420
+ await c.resolve();
421
+ return new Filter(x => c.applyTo(x));
422
+ })).then(x => {
423
+ newOrElements = x;
424
+ }));
425
+ this.commands.push(x => x.or(newOrElements));
426
+ }
427
+ isEqualTo(col, val) {
428
+ this.commands.push(x => x.isEqualTo(col, val));
429
+ }
430
+ isDifferentFrom(col, val) {
431
+ this.commands.push(x => x.isDifferentFrom(col, val));
432
+ }
433
+ isNull(col) {
434
+ this.commands.push(x => x.isNull(col));
435
+ }
436
+ isNotNull(col) {
437
+ this.commands.push(x => x.isNotNull(col));
438
+ }
439
+ isGreaterOrEqualTo(col, val) {
440
+ this.commands.push(x => x.isGreaterOrEqualTo(col, val));
441
+ }
442
+ isGreaterThan(col, val) {
443
+ this.commands.push(x => x.isGreaterThan(col, val));
444
+ }
445
+ isLessOrEqualTo(col, val) {
446
+ this.commands.push(x => x.isLessOrEqualTo(col, val));
447
+ }
448
+ isLessThan(col, val) {
449
+ this.commands.push(x => x.isLessThan(col, val));
450
+ }
451
+ containsCaseInsensitive(col, val) {
452
+ this.commands.push(x => x.containsCaseInsensitive(col, val));
453
+ }
454
+ isIn(col, val) {
455
+ this.commands.push(x => x.isIn(col, val));
456
+ }
457
+ custom(key, customItem) {
458
+ this.promises.push((async () => {
459
+ let r = await this.translateCustom(key, customItem);
460
+ if (r)
461
+ if (Array.isArray(r))
462
+ r.forEach(x => x.__applyToConsumer(this));
463
+ else
464
+ r.__applyToConsumer(this);
465
+ })());
466
+ }
467
+ databaseCustom(custom) {
468
+ this.commands.push(x => x.databaseCustom(custom));
469
+ }
470
+ async resolve() {
471
+ while (this.promises.length > 0) {
472
+ let p = this.promises;
473
+ this.promises = [];
474
+ await Promise.all(p);
475
+ }
476
+ }
477
+ }
@@ -0,0 +1,20 @@
1
+ import { FindOptions } from '../../index';
2
+ import type { LiveQueryChangeInfo, RepositoryImplementation } from '../remult3';
3
+ import { SubscriptionClientConnection, Unsubscribe, SubscriptionListener } from './SubscriptionChannel';
4
+ import type { ApiClient } from '../../index';
5
+ export declare class LiveQueryClient {
6
+ private apiProvider;
7
+ private getUserId;
8
+ wrapMessageHandling(handleMessage: any): void;
9
+ private queries;
10
+ private channels;
11
+ constructor(apiProvider: () => ApiClient, getUserId: () => string);
12
+ runPromise<X>(p: Promise<X>): Promise<X>;
13
+ close(): void;
14
+ subscribeChannel<T>(key: string, onResult: SubscriptionListener<T>): Promise<Unsubscribe>;
15
+ private closeIfNoListeners;
16
+ subscribe<entityType>(repo: RepositoryImplementation<entityType>, options: FindOptions<entityType>, listener: SubscriptionListener<LiveQueryChangeInfo<entityType>>): () => void;
17
+ client: Promise<SubscriptionClientConnection>;
18
+ interval: any;
19
+ private openIfNoOpened;
20
+ }
@@ -0,0 +1,188 @@
1
+ import { RestDataProvider } from '../data-providers/rest-data-provider';
2
+ import { buildRestDataProvider } from "../buildRestDataProvider";
3
+ import { LiveQuerySubscriber, liveQueryKeepAliveRoute } from './SubscriptionChannel';
4
+ /* @internal*/
5
+ export class LiveQueryClient {
6
+ apiProvider;
7
+ getUserId;
8
+ wrapMessageHandling(handleMessage) {
9
+ var x = this.apiProvider().wrapMessageHandling;
10
+ if (x)
11
+ x(handleMessage);
12
+ else
13
+ handleMessage();
14
+ }
15
+ ;
16
+ queries = new Map();
17
+ channels = new Map();
18
+ constructor(apiProvider, getUserId) {
19
+ this.apiProvider = apiProvider;
20
+ this.getUserId = getUserId;
21
+ }
22
+ runPromise(p) {
23
+ return p;
24
+ }
25
+ close() {
26
+ this.queries.clear();
27
+ this.channels.clear();
28
+ this.closeIfNoListeners();
29
+ }
30
+ async subscribeChannel(key, onResult) {
31
+ let onUnsubscribe = () => { };
32
+ const client = await this.openIfNoOpened();
33
+ try {
34
+ let q = this.channels.get(key);
35
+ if (!q) {
36
+ this.channels.set(key, q = new MessageChannel());
37
+ try {
38
+ q.unsubscribe = await client.subscribe(key, value => this.wrapMessageHandling(() => q.handle(value)), err => {
39
+ onResult.error(err);
40
+ });
41
+ }
42
+ catch (err) {
43
+ onResult.error(err);
44
+ throw err;
45
+ }
46
+ }
47
+ q.listeners.push(onResult);
48
+ onUnsubscribe = () => {
49
+ q.listeners.splice(q.listeners.indexOf(onResult), 1);
50
+ if (q.listeners.length == 0) {
51
+ this.channels.delete(key);
52
+ q.unsubscribe();
53
+ }
54
+ this.closeIfNoListeners();
55
+ };
56
+ }
57
+ catch (err) {
58
+ onResult.error(err);
59
+ throw err;
60
+ }
61
+ return () => {
62
+ onUnsubscribe();
63
+ onUnsubscribe = () => { };
64
+ };
65
+ }
66
+ closeIfNoListeners() {
67
+ if (this.client)
68
+ if (this.queries.size === 0 && this.channels.size === 0) {
69
+ this.runPromise(this.client.then(x => x.close()));
70
+ this.client = undefined;
71
+ clearInterval(this.interval);
72
+ this.interval = undefined;
73
+ }
74
+ }
75
+ subscribe(repo, options, listener) {
76
+ let alive = true;
77
+ let onUnsubscribe = () => { alive = false; };
78
+ this.runPromise(repo.buildEntityDataProviderFindOptions(options)
79
+ .then(opts => {
80
+ if (!alive)
81
+ return;
82
+ const { createKey, subscribe } = new RestDataProvider(this.apiProvider).getEntityDataProvider(repo.metadata).buildFindRequest(opts);
83
+ const eventTypeKey = createKey();
84
+ let q = this.queries.get(eventTypeKey);
85
+ if (!q) {
86
+ this.queries.set(eventTypeKey, q = new LiveQuerySubscriber(repo, { entityKey: repo.metadata.key, options }, this.getUserId()));
87
+ q.subscribeCode = () => {
88
+ if (q.unsubscribe) {
89
+ q.unsubscribe();
90
+ q.unsubscribe = () => { };
91
+ }
92
+ this.runPromise(this.subscribeChannel(q.queryChannel, {
93
+ next: (value) => this.runPromise(q.handle(value)),
94
+ complete: () => { },
95
+ error: er => {
96
+ q.listeners.forEach(l => l.error(er));
97
+ }
98
+ }).then(unsubscribeToChannel => {
99
+ if (q.listeners.length == 0) {
100
+ unsubscribeToChannel();
101
+ return;
102
+ }
103
+ this.runPromise(subscribe(q.id)
104
+ .then(r => {
105
+ if (q.listeners.length === 0) {
106
+ r.unsubscribe();
107
+ unsubscribeToChannel();
108
+ return;
109
+ }
110
+ this.runPromise(q.setAllItems(r.result));
111
+ q.unsubscribe = () => {
112
+ q.unsubscribe = () => { };
113
+ unsubscribeToChannel();
114
+ this.runPromise(r.unsubscribe());
115
+ };
116
+ })
117
+ .catch(err => {
118
+ listener.error(err);
119
+ }));
120
+ })).catch(err => {
121
+ q.listeners.forEach(l => l.error(err));
122
+ });
123
+ };
124
+ q.subscribeCode();
125
+ }
126
+ else {
127
+ q.sendDefaultState(listener.next);
128
+ }
129
+ q.listeners.push(listener);
130
+ onUnsubscribe = () => {
131
+ q.listeners.splice(q.listeners.indexOf(listener), 1);
132
+ listener.complete();
133
+ if (q.listeners.length == 0) {
134
+ this.queries.delete(eventTypeKey);
135
+ q.unsubscribe();
136
+ }
137
+ this.closeIfNoListeners();
138
+ };
139
+ })
140
+ .catch(err => {
141
+ listener.error(err);
142
+ }));
143
+ return () => {
144
+ onUnsubscribe();
145
+ };
146
+ }
147
+ client;
148
+ interval;
149
+ openIfNoOpened() {
150
+ if (!this.client) {
151
+ this.interval = setInterval(async () => {
152
+ const ids = [];
153
+ for (const q of this.queries.values()) {
154
+ ids.push(q.queryChannel);
155
+ }
156
+ if (ids.length > 0) {
157
+ let p = this.apiProvider();
158
+ let { actionInfo } = await import('../server-action');
159
+ const invalidIds = await this.runPromise(await actionInfo.runActionWithoutBlockingUI(() => buildRestDataProvider(p.httpClient).post(p.url + '/' + liveQueryKeepAliveRoute, ids)));
160
+ for (const id of invalidIds) {
161
+ for (const q of this.queries.values()) {
162
+ if (q.queryChannel === id)
163
+ q.subscribeCode();
164
+ }
165
+ }
166
+ }
167
+ }, 30000);
168
+ return this.runPromise(this.client =
169
+ this.apiProvider().subscriptionClient.openConnection(() => {
170
+ for (const q of this.queries.values()) {
171
+ q.subscribeCode();
172
+ }
173
+ }));
174
+ }
175
+ return this.client;
176
+ }
177
+ }
178
+ class MessageChannel {
179
+ id;
180
+ unsubscribe = () => { };
181
+ async handle(message) {
182
+ for (const l of this.listeners) {
183
+ l.next(message);
184
+ }
185
+ }
186
+ listeners = [];
187
+ constructor() { }
188
+ }
@@ -0,0 +1,5 @@
1
+ import { SubscriptionClient, SubscriptionClientConnection } from "./SubscriptionChannel";
2
+ export declare class SseSubscriptionClient implements SubscriptionClient {
3
+ openConnection(onReconnect: VoidFunction): Promise<SubscriptionClientConnection>;
4
+ }
5
+ export declare const ConnectionNotFoundError = "client connection not found";