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,2103 @@
1
+ import { createData } from "./createData";
2
+ import { DataApi } from '../data-api';
3
+ import { InMemoryDataProvider } from '../data-providers/in-memory-database';
4
+ import { ArrayEntityDataProvider } from "../data-providers/array-entity-data-provider";
5
+ import { MockRestDataProvider } from './testHelper.spec';
6
+ import { TestDataApiResponse } from "./TestDataApiResponse";
7
+ import { Done } from "./Done";
8
+ import { Status } from './testModel/models';
9
+ import { Remult } from '../context';
10
+ import { WebSqlDataProvider } from '../data-providers/web-sql-data-provider';
11
+ import { DataList } from '../../../angular/interfaces/src/dataList';
12
+ import { UrlBuilder } from '../../urlBuilder';
13
+ import { SqlDatabase } from '../data-providers/sql-database';
14
+ import { addFilterToUrlAndReturnTrueIfSuccessful, RestDataProvider, RestDataProviderHttpProviderUsingFetch } from '../data-providers/rest-data-provider';
15
+ import { entityFilterToJson } from '../filter/filter-interfaces';
16
+ import { Categories, Categories as newCategories } from './remult-3-entities';
17
+ import { Field, decorateColumnSettings, Entity, EntityBase, FieldType, Fields, getEntityKey, isAutoIncrement, getEntityRef } from '../remult3';
18
+ import { CompoundIdField } from '../column';
19
+ import { actionInfo } from '../server-action';
20
+ import { assign } from '../../assign';
21
+ import { entityWithValidations } from '../shared-tests/entityWithValidations';
22
+ import { entityWithValidationsOnColumn } from './entityWithValidationsOnColumn';
23
+ import { ValueConverters } from "../valueConverters";
24
+ import { FilterConsumerBridgeToSqlRequest, dbNamesOf } from "../filter/filter-consumer-bridge-to-sql-request";
25
+ import axios from "axios";
26
+ import { HttpProviderBridgeToRestDataProviderHttpProvider, retry, toPromise } from "../buildRestDataProvider";
27
+ import { describeClass } from "../remult3/DecoratorReplacer";
28
+ import { remult } from "../remult-proxy";
29
+ //SqlDatabase.LogToConsole = true;
30
+ @FieldType({
31
+ valueConverter: {
32
+ toJson: x => x?.thePhone,
33
+ fromJson: x => new Phone(x)
34
+ }
35
+ })
36
+ class Phone {
37
+ thePhone;
38
+ constructor(thePhone) {
39
+ this.thePhone = thePhone;
40
+ }
41
+ }
42
+ @Entity('')
43
+ class tableWithPhone extends EntityBase {
44
+ @Fields.integer()
45
+ id;
46
+ @Field(() => Phone)
47
+ phone;
48
+ }
49
+ describe("test object column stored as string", () => {
50
+ it("was changed should work correctly", async () => {
51
+ var remult = new Remult(new InMemoryDataProvider());
52
+ let repo = remult.repo(tableWithPhone);
53
+ let r = repo.create();
54
+ r.id = 1;
55
+ r.phone = new Phone("123");
56
+ await r.save();
57
+ r.phone = new Phone("123");
58
+ expect(r.$.phone.valueChanged()).toBe(false);
59
+ expect(r._.wasChanged()).toBe(false);
60
+ });
61
+ });
62
+ describe('Test basic row functionality', () => {
63
+ it("filter on date keeps the type", () => {
64
+ });
65
+ it("finds its id column", () => {
66
+ let c = new Remult().repo(newCategories);
67
+ expect(c.metadata.idMetadata.field.key).toBe("id");
68
+ let n = c.create();
69
+ n.id = 5;
70
+ expect(n._.getId()).toBe(5);
71
+ });
72
+ it("object assign works", () => {
73
+ let a = {};
74
+ let b = {};
75
+ a.info = 3;
76
+ Object.assign(b, a);
77
+ expect(b.info).toBe(3);
78
+ });
79
+ it("Original values update correctly", async () => {
80
+ let c = await (await createData(async (insert) => await insert(1, 'noam')))[0].findFirst();
81
+ expect(c.categoryName).toBe('noam');
82
+ expect(c._.fields.categoryName.originalValue).toBe('noam');
83
+ c.categoryName = 'yael';
84
+ expect(c.categoryName).toBe('yael');
85
+ expect(c._.fields.categoryName.originalValue).toBe('noam');
86
+ await c._.save();
87
+ expect(c.categoryName).toBe('yael');
88
+ expect(c._.fields.categoryName.originalValue).toBe('yael');
89
+ });
90
+ it("Find or Create", async () => {
91
+ let [repo] = await (await createData());
92
+ let row = await repo.findFirst({ id: 1 }, { createIfNotFound: true });
93
+ expect(row._.isNew()).toBe(true);
94
+ expect(row.id).toBe(1);
95
+ await row._.save();
96
+ let row2 = await repo.findFirst({ id: 1 }, { createIfNotFound: true });
97
+ expect(row2._.isNew()).toBe(false);
98
+ expect(row2.id).toBe(1);
99
+ });
100
+ it("Find or Create id", async () => {
101
+ let [repo] = await (await createData());
102
+ let row = await repo.findId(1, { createIfNotFound: true });
103
+ expect(row._.isNew()).toBe(true);
104
+ expect(row.id).toBe(1);
105
+ await row._.save();
106
+ let row2 = await repo.findId(1, { createIfNotFound: true });
107
+ expect(row2._.isNew()).toBe(false);
108
+ expect(row2.id).toBe(1);
109
+ });
110
+ it("object is autonemous", () => {
111
+ let x = new Remult().repo(newCategories).create();
112
+ let y = new Remult().repo(newCategories).create();
113
+ x.categoryName = 'noam';
114
+ y.categoryName = 'yael';
115
+ expect(x.categoryName).toBe('noam');
116
+ expect(y.categoryName).toBe('yael');
117
+ });
118
+ it("find the col value", () => {
119
+ let x = new Remult().repo(newCategories).create();
120
+ let y = new Remult().repo(newCategories).create();
121
+ x.categoryName = 'noam';
122
+ y.categoryName = 'yael';
123
+ expect(y._.fields.find(x._.fields.categoryName.metadata).value).toBe('yael');
124
+ expect(y._.fields.find(x._.fields.categoryName.metadata.key).value).toBe('yael');
125
+ expect(y._.metadata.fields.find('categoryName').key).toBe('categoryName');
126
+ });
127
+ it("can be saved to a pojo", async () => {
128
+ let ctx = new Remult().repo(newCategories);
129
+ let x = ctx.create();
130
+ x.id = 1;
131
+ x.categoryName = 'noam';
132
+ let y = x._.toApiJson();
133
+ expect(y.id).toBe(1);
134
+ expect(y.categoryName).toBe('noam');
135
+ });
136
+ // it("json name is important", async () => {
137
+ // let ctx = new Remult().for(newCategories);
138
+ // let x = ctx.create();
139
+ // x.id = 1;
140
+ // x.categoryName.defs.key = 'xx';
141
+ // x.categoryName = 'noam';
142
+ // let y = x._.toApiPojo();;
143
+ // expect(y.id).toBe(1);
144
+ // expect(y.xx).toBe('noam');
145
+ // });
146
+ // it("json name is important 1", async () => {
147
+ // let ctx = new Remult().for_old(myTestEntity);
148
+ // let x = ctx.create();
149
+ // x.id.value = 1;
150
+ // expect(x.name1.defs.key).toBe('name');
151
+ // x.name1.value = 'noam';
152
+ // let y = ctx.toApiPojo(x);
153
+ // expect(y.id).toBe(1);
154
+ // expect(y.name).toBe('noam', JSON.stringify(y));
155
+ // y.name = 'yael';
156
+ // new Remult().for_old(myTestEntity)._updateEntityBasedOnApi(x, y);
157
+ // expect(x.name1.value).toBe('yael');
158
+ // });
159
+ // it("json name is important", () => {
160
+ // let x = new myTestEntity();
161
+ // x.id.value = 1;
162
+ // x.name1.value = 'a';
163
+ // var y = new myTestEntity();
164
+ // expect(x.columns.find(y.name1).value).toBe('a');
165
+ // });
166
+ });
167
+ @Entity('myTestEntity')
168
+ class myTestEntity extends EntityBase {
169
+ @Fields.integer()
170
+ id;
171
+ @Fields.string({ key: 'name' })
172
+ name1;
173
+ }
174
+ describe("data api", () => {
175
+ beforeEach(() => actionInfo.runningOnServer = true);
176
+ afterEach(() => actionInfo.runningOnServer = false);
177
+ it("get based on id", async () => {
178
+ let [c, remult] = await createData(async (insert) => await insert(1, 'noam'));
179
+ var api = new DataApi(c, remult);
180
+ let t = new TestDataApiResponse();
181
+ let d = new Done();
182
+ t.success = async (data) => {
183
+ expect(data.id).toBe(1);
184
+ expect(data.categoryName).toBe('noam');
185
+ d.ok();
186
+ };
187
+ await api.get(t, 1);
188
+ d.test();
189
+ });
190
+ it("get based on id virtual column", async () => {
191
+ let [c, remult] = await createData(async (insert) => await insert(1, 'noam'));
192
+ var api = new DataApi(c, remult);
193
+ let t = new TestDataApiResponse();
194
+ let d = new Done();
195
+ t.success = async (data) => {
196
+ expect(data.id).toBe(1);
197
+ expect(data.categoryName).toBe('noam');
198
+ expect(data.categoryNameLength).toBe(4);
199
+ d.ok();
200
+ };
201
+ await api.get(t, 1);
202
+ d.test();
203
+ });
204
+ it("get based on id virtual column async", async () => {
205
+ let [c, remult] = await createData(async (insert) => await insert(1, 'noam'));
206
+ var api = new DataApi(c, remult);
207
+ let t = new TestDataApiResponse();
208
+ let d = new Done();
209
+ t.success = async (data) => {
210
+ expect(data.id).toBe(1);
211
+ expect(data.categoryName).toBe('noam');
212
+ expect(data.categoryNameLengthAsync).toBe(4);
213
+ d.ok();
214
+ };
215
+ await api.get(t, 1);
216
+ d.test();
217
+ });
218
+ it("get based on id can fail", async () => {
219
+ let [c, remult] = await createData(async (insert) => await insert(1, 'noam'));
220
+ var api = new DataApi(c, remult);
221
+ let t = new TestDataApiResponse();
222
+ let d = new Done();
223
+ t.notFound = () => d.ok();
224
+ await api.get(t, 2);
225
+ d.test();
226
+ });
227
+ let remult = new Remult();
228
+ remult.dataProvider = (new InMemoryDataProvider());
229
+ it("validate with validations on column fails", async () => {
230
+ let remult = new Remult(new InMemoryDataProvider());
231
+ var s = remult.repo(entityWithValidationsOnColumn);
232
+ let c = s.create();
233
+ c.myId = 1;
234
+ c.name = 'noam';
235
+ await c._.save();
236
+ c.name = '1';
237
+ expect((await c._.validate()).modelState.name).toBe('invalid on column');
238
+ c.name = "123";
239
+ expect(await c._.validate()).toBeUndefined();
240
+ });
241
+ it("validation works on non active record", async () => {
242
+ let remult = new Remult(new InMemoryDataProvider());
243
+ var repo = remult.repo(entityWithValidationsOnColumn);
244
+ expect((await repo.validate({ name: "1" })).modelState.name).toBe('invalid on column');
245
+ expect(await repo.validate({ name: "123" })).toBeUndefined();
246
+ expect(await repo.validate({ name: "1" }, "myId")).toBeUndefined();
247
+ });
248
+ it("validate with validations on column fails 1", async () => {
249
+ let remult = new Remult(new InMemoryDataProvider());
250
+ var s = remult.repo(entityWithValidationsOnColumn);
251
+ let c = s.create();
252
+ c.myId = 1;
253
+ c.name = 'noam';
254
+ await c._.save();
255
+ c.name = '1';
256
+ expect(await c.$.name.validate()).toBe(false);
257
+ c.name = "123";
258
+ const val = await c._.validate();
259
+ expect(val).toBeUndefined();
260
+ });
261
+ it("put with validations on entity fails", async () => {
262
+ let remult = new Remult(new InMemoryDataProvider());
263
+ var s = remult.repo(entityWithValidations);
264
+ let c = s.create();
265
+ c.myId = 1;
266
+ c.name = 'noam';
267
+ await c._.save();
268
+ let api = new DataApi(s, remult);
269
+ let t = new TestDataApiResponse();
270
+ let d = new Done();
271
+ t.error = async (data) => {
272
+ expect(data.modelState.name).toBe('invalid');
273
+ d.ok();
274
+ };
275
+ await api.put(t, 1, {
276
+ name: '1'
277
+ });
278
+ d.test();
279
+ var x = await s.find({ where: { myId: 1 } });
280
+ expect(x[0].name).toBe('noam');
281
+ });
282
+ it("delete fails when not found", async () => {
283
+ let [c, remult] = await createData(async (insert) => await insert(1, 'noam'));
284
+ var api = new DataApi(c, remult);
285
+ let t = new TestDataApiResponse();
286
+ let d = new Done();
287
+ t.notFound = () => d.ok();
288
+ await api.delete(t, 2);
289
+ d.test();
290
+ });
291
+ it("delete works ", async () => {
292
+ let [c, remult] = await createData(async (insert) => await insert(1, 'noam'));
293
+ var api = new DataApi(c, remult);
294
+ let t = new TestDataApiResponse();
295
+ let d = new Done();
296
+ t.deleted = () => d.ok();
297
+ await api.delete(t, 1);
298
+ let r = await c.find();
299
+ expect(r.length).toBe(0);
300
+ });
301
+ it("delete falis nicely ", async () => {
302
+ let ctx = new Remult();
303
+ ctx.dataProvider = ({
304
+ getEntityDataProvider: (x) => {
305
+ let r = new ArrayEntityDataProvider(x, [{ id: 1 }]);
306
+ r.delete = () => { throw "ERROR"; };
307
+ return r;
308
+ }, transaction: undefined
309
+ });
310
+ var api = new DataApi(ctx.repo(newCategories), ctx);
311
+ let t = new TestDataApiResponse();
312
+ let d = new Done();
313
+ t.error = () => d.ok();
314
+ await api.delete(t, 1);
315
+ d.test();
316
+ });
317
+ it("post works", async () => {
318
+ let [c, remult] = await createData(async () => { });
319
+ var api = new DataApi(c, remult);
320
+ let t = new TestDataApiResponse();
321
+ let d = new Done();
322
+ t.created = async (data) => {
323
+ expect(data.id).toBe(1);
324
+ expect(data.categoryName).toBe('noam');
325
+ d.ok();
326
+ };
327
+ await api.post(t, { id: 1, categoryName: 'noam' });
328
+ d.test();
329
+ expect(await c.count()).toBe(1);
330
+ });
331
+ it("post works for array", async () => {
332
+ let [c, remult] = await createData(async () => { });
333
+ var api = new DataApi(c, remult);
334
+ let t = new TestDataApiResponse();
335
+ let d = new Done();
336
+ t.created = async (data) => {
337
+ expect(data.length).toBe(2);
338
+ expect(data[0].id).toBe(1);
339
+ expect(data[0].categoryName).toBe('noam');
340
+ expect(data[1].id).toBe(2);
341
+ expect(data[1].categoryName).toBe('yael');
342
+ d.ok();
343
+ };
344
+ await api.post(t, [{ id: 1, categoryName: 'noam' }, { id: 2, categoryName: "yael" }]);
345
+ d.test();
346
+ expect(await c.count()).toBe(2);
347
+ });
348
+ it("post fails on duplicate index", async () => {
349
+ let [c, remult] = await createData(async (i) => { await i(1, 'noam'); });
350
+ var api = new DataApi(c, remult);
351
+ let t = new TestDataApiResponse();
352
+ let d = new Done();
353
+ t.error = err => {
354
+ if (!err.message)
355
+ fail('no message');
356
+ d.ok();
357
+ };
358
+ await api.post(t, { id: 1, categoryName: 'noam' });
359
+ d.test();
360
+ });
361
+ it("getArray works", async () => {
362
+ let [c, remult] = await createData(async (i) => {
363
+ await i(1, 'noam');
364
+ await i(2, 'yael');
365
+ });
366
+ var api = new DataApi(c, remult);
367
+ let t = new TestDataApiResponse();
368
+ let d = new Done();
369
+ t.success = data => {
370
+ expect(data.length).toBe(2);
371
+ expect(data[0].id).toBe(1);
372
+ d.ok();
373
+ };
374
+ await api.getArray(t, undefined);
375
+ d.test();
376
+ });
377
+ it("getArray works with filter", async () => {
378
+ let [c, remult] = await createData(async (i) => {
379
+ await i(1, 'noam');
380
+ await i(2, 'yael');
381
+ });
382
+ var api = new DataApi(c, remult);
383
+ let t = new TestDataApiResponse();
384
+ let d = new Done();
385
+ t.success = data => {
386
+ expect(data.length).toBe(1);
387
+ expect(data[0].id).toBe(2);
388
+ d.ok();
389
+ };
390
+ await api.getArray(t, {
391
+ get: x => {
392
+ if (x == "id")
393
+ return "2";
394
+ return undefined;
395
+ }
396
+ });
397
+ d.test();
398
+ });
399
+ it("getArray works with filter and multiple values", async () => {
400
+ let [c, remult] = await createData(async (i) => {
401
+ await i(1, 'noam');
402
+ await i(2, 'yael');
403
+ await i(3, 'yoni');
404
+ });
405
+ var api = new DataApi(c, remult);
406
+ let t = new TestDataApiResponse();
407
+ let d = new Done();
408
+ t.success = data => {
409
+ expect(data.length).toBe(1);
410
+ expect(data[0].id).toBe(2);
411
+ d.ok();
412
+ };
413
+ await api.getArray(t, {
414
+ get: x => {
415
+ if (x == "id.ne")
416
+ return ["1", "3"];
417
+ return undefined;
418
+ }
419
+ });
420
+ d.test();
421
+ });
422
+ it("getArray works with filter and multiple values with closed list columns", async () => {
423
+ let [c, remult] = await createData(async (i) => {
424
+ await i(1, 'noam', undefined, Status.open);
425
+ await i(2, 'yael', undefined, Status.closed);
426
+ await i(3, 'yoni', undefined, Status.hold);
427
+ });
428
+ var api = new DataApi(c, remult);
429
+ let t = new TestDataApiResponse();
430
+ let d = new Done();
431
+ t.success = data => {
432
+ expect(data.length).toBe(1);
433
+ expect(data[0].id).toBe(2);
434
+ d.ok();
435
+ };
436
+ await api.getArray(t, {
437
+ get: x => {
438
+ if (x == "status.ne")
439
+ return ["0", "2"];
440
+ return undefined;
441
+ }
442
+ });
443
+ d.test();
444
+ });
445
+ it("getArray works with filter and in with closed list columns", async () => {
446
+ let [c, remult] = await createData(async (i) => {
447
+ await i(1, 'noam', undefined, Status.open);
448
+ await i(2, 'yael', undefined, Status.closed);
449
+ await i(3, 'yoni', undefined, Status.hold);
450
+ });
451
+ var api = new DataApi(c, remult);
452
+ let t = new TestDataApiResponse();
453
+ let d = new Done();
454
+ t.success = data => {
455
+ expect(data.length).toBe(2);
456
+ expect(data[0].id).toBe(2);
457
+ expect(data[1].id).toBe(3);
458
+ d.ok();
459
+ };
460
+ await api.getArray(t, {
461
+ get: x => {
462
+ if (x == "status.in")
463
+ return '[1, 2]';
464
+ return undefined;
465
+ }
466
+ });
467
+ d.test();
468
+ });
469
+ it("get array works with filter in body and in array statement", async () => {
470
+ let [c, remult] = await createData(async (i) => {
471
+ await i(1, 'noam', undefined, Status.open);
472
+ await i(2, 'yael', undefined, Status.closed);
473
+ await i(3, 'yoni', undefined, Status.hold);
474
+ });
475
+ var api = new DataApi(c, remult);
476
+ let t = new TestDataApiResponse();
477
+ let d = new Done();
478
+ t.success = data => {
479
+ expect(data.length).toBe(2);
480
+ expect(data[0].id).toBe(2);
481
+ expect(data[1].id).toBe(3);
482
+ d.ok();
483
+ };
484
+ await api.getArray(t, {
485
+ get: x => {
486
+ return undefined;
487
+ }
488
+ }, {
489
+ "status.in": [1, 2]
490
+ });
491
+ d.test();
492
+ });
493
+ it("get array works with filter in body and or statement", async () => {
494
+ let [c, remult] = await createData(async (i) => {
495
+ await i(1, 'noam', undefined, Status.open);
496
+ await i(2, 'yael', undefined, Status.closed);
497
+ await i(3, 'yoni', undefined, Status.hold);
498
+ });
499
+ var api = new DataApi(c, remult);
500
+ let t = new TestDataApiResponse();
501
+ let d = new Done();
502
+ t.success = data => {
503
+ expect(data.length).toBe(2);
504
+ expect(data[0].id).toBe(2);
505
+ expect(data[1].id).toBe(3);
506
+ d.ok();
507
+ };
508
+ await api.getArray(t, {
509
+ get: x => {
510
+ return undefined;
511
+ }
512
+ }, {
513
+ OR: [
514
+ { status: 1 },
515
+ { status: 2 }
516
+ ]
517
+ });
518
+ d.test();
519
+ });
520
+ it("delete with validation fails", async () => {
521
+ var deleting = new Done();
522
+ let happend = false;
523
+ let type = class extends newCategories {
524
+ };
525
+ Entity(undefined, {
526
+ allowApiDelete: true,
527
+ deleted: () => happend = true,
528
+ deleting: (t) => {
529
+ deleting.ok();
530
+ t._.fields.categoryName.error = 'err';
531
+ }
532
+ })(type);
533
+ let [c, remult] = await createData(async (insert) => await insert(1, 'noam'), type);
534
+ var api = new DataApi(c, remult);
535
+ let t = new TestDataApiResponse();
536
+ let d = new Done();
537
+ t.error = async (data) => {
538
+ d.ok();
539
+ };
540
+ await api.delete(t, 1);
541
+ d.test();
542
+ deleting.test();
543
+ expect(happend).toBe(false);
544
+ var x = await c.find({ where: { id: 1 } });
545
+ expect(x[0].categoryName).toBe('noam');
546
+ });
547
+ it("delete with validation exception fails", async () => {
548
+ var deleting = new Done();
549
+ let happend = false;
550
+ let type = class extends newCategories {
551
+ };
552
+ Entity(undefined, {
553
+ allowApiDelete: true,
554
+ deleted: () => happend = true,
555
+ deleting: () => {
556
+ deleting.ok();
557
+ throw 'err';
558
+ }
559
+ })(type);
560
+ let [c, remult] = await createData(async (insert) => await insert(1, 'noam'), type);
561
+ var api = new DataApi(c, remult);
562
+ let t = new TestDataApiResponse();
563
+ let d = new Done();
564
+ t.error = async (data) => {
565
+ d.ok();
566
+ };
567
+ await api.delete(t, 1);
568
+ d.test();
569
+ deleting.test();
570
+ expect(happend).toBe(false);
571
+ var x = await c.find({ where: { id: 1 } });
572
+ expect(x[0].categoryName).toBe('noam');
573
+ });
574
+ it("delete with validation exception fails - no data api", async () => {
575
+ var deleting = new Done();
576
+ let happend = false;
577
+ let type = class extends newCategories {
578
+ };
579
+ Entity(undefined, {
580
+ allowApiDelete: true,
581
+ deleted: () => happend = true,
582
+ deleting: () => {
583
+ deleting.ok();
584
+ throw 'err';
585
+ }
586
+ })(type);
587
+ let [c] = await createData(async (insert) => await insert(1, 'noam'), type);
588
+ let h2 = false;
589
+ let h3 = false;
590
+ try {
591
+ await (await c.findId(1))._.delete();
592
+ h2 = true;
593
+ }
594
+ catch {
595
+ h3 = true;
596
+ }
597
+ expect(h2).toBe(false);
598
+ expect(h3).toBe(true);
599
+ });
600
+ it("delete works", async () => {
601
+ var deleting = new Done();
602
+ let happend = false;
603
+ let type = class extends newCategories {
604
+ };
605
+ Entity(undefined, {
606
+ allowApiDelete: true,
607
+ deleted: (t) => {
608
+ happend = true;
609
+ expect(t.id).toBe(1);
610
+ },
611
+ deleting: () => {
612
+ deleting.ok();
613
+ }
614
+ })(type);
615
+ let [c, remult] = await createData(async (insert) => await insert(1, 'noam'), type);
616
+ expect(c.metadata.apiDeleteAllowed()).toBe(true);
617
+ expect(c.metadata.apiUpdateAllowed()).toBe(true);
618
+ expect(c.metadata.apiInsertAllowed()).toBe(true);
619
+ var api = new DataApi(c, remult);
620
+ let t = new TestDataApiResponse();
621
+ let d = new Done();
622
+ t.deleted = async () => {
623
+ d.ok();
624
+ };
625
+ await api.delete(t, 1);
626
+ d.test();
627
+ deleting.test();
628
+ expect(happend).toBe(true);
629
+ var x = await c.find({ where: { id: 1 } });
630
+ expect(x.length).toBe(0);
631
+ });
632
+ it("check api defaults", async () => {
633
+ const c = class {
634
+ id = 0;
635
+ name = '';
636
+ };
637
+ describeClass(c, Entity("asdf"), {
638
+ id: Fields.autoIncrement(),
639
+ name: Fields.string()
640
+ });
641
+ const repo = new Remult(new InMemoryDataProvider()).repo(c);
642
+ expect(repo.metadata.apiDeleteAllowed()).toBe(false);
643
+ expect(repo.metadata.apiUpdateAllowed()).toBe(false);
644
+ expect(repo.metadata.apiInsertAllowed()).toBe(false);
645
+ expect(repo.metadata.apiDeleteAllowed({ id: 1 })).toBe(false);
646
+ expect(repo.metadata.apiUpdateAllowed({ id: 1 })).toBe(false);
647
+ expect(repo.metadata.apiInsertAllowed({ id: 1 })).toBe(false);
648
+ expect(repo.fields.id.apiUpdateAllowed()).toBe(false);
649
+ expect(repo.fields.id.apiUpdateAllowed({ id: 1 })).toBe(false);
650
+ expect(repo.fields.name.apiUpdateAllowed()).toBe(true);
651
+ expect(repo.fields.name.apiUpdateAllowed({ id: 1 })).toBe(true);
652
+ expect(repo.metadata.apiReadAllowed).toBe(true);
653
+ let x = { id: 1 };
654
+ expect(getEntityRef(x, false)).toBe(undefined);
655
+ repo.metadata.fields.id.displayValue(x);
656
+ repo.metadata.fields.id.apiUpdateAllowed(x);
657
+ repo.metadata.apiDeleteAllowed(x);
658
+ repo.metadata.apiUpdateAllowed(x);
659
+ await repo.validate(x);
660
+ expect(getEntityRef(x, false)).toBeUndefined();
661
+ });
662
+ it("put with validation fails", async () => {
663
+ let count = 0;
664
+ let type = class extends newCategories {
665
+ };
666
+ Entity(undefined, {
667
+ allowApiUpdate: true,
668
+ saving: t => {
669
+ count++;
670
+ if (t.categoryName.includes('1'))
671
+ t._.fields.categoryName.error = 'err';
672
+ }
673
+ })(type);
674
+ let [c, remult] = await createData(async (insert) => await insert(1, 'noam'), type);
675
+ var api = new DataApi(c, remult);
676
+ let t = new TestDataApiResponse();
677
+ let d = new Done();
678
+ t.error = async (data) => {
679
+ d.ok();
680
+ };
681
+ count = 0;
682
+ await api.put(t, 1, {
683
+ categoryName: 'noam 1'
684
+ });
685
+ d.test();
686
+ var x = await c.find({ where: { id: 1 } });
687
+ expect(x[0].categoryName).toBe('noam');
688
+ expect(count).toBe(1);
689
+ });
690
+ it("afterSave works", async () => {
691
+ let count = 0;
692
+ let startTest = false;
693
+ let savedWorked = new Done();
694
+ let type = class extends newCategories {
695
+ };
696
+ Entity(undefined, {
697
+ allowApiUpdate: true,
698
+ saving: () => count++,
699
+ saved: (t) => {
700
+ if (!startTest)
701
+ return;
702
+ savedWorked.ok();
703
+ expect(t._.fields.categoryName.originalValue).toBe('noam');
704
+ expect(t.categoryName).toBe('noam 1');
705
+ }
706
+ })(type);
707
+ let [c, remult] = await createData(async (insert) => await insert(1, 'noam'), type);
708
+ var api = new DataApi(c, remult);
709
+ let t = new TestDataApiResponse();
710
+ let d = new Done();
711
+ t.success = async (data) => {
712
+ d.ok();
713
+ };
714
+ count = 0;
715
+ startTest = true;
716
+ await api.put(t, 1, {
717
+ categoryName: 'noam 1'
718
+ });
719
+ d.test();
720
+ savedWorked.test();
721
+ var x = await c.find({ where: { id: 1 } });
722
+ expect(x[0].categoryName).toBe('noam 1');
723
+ expect(count).toBe(1);
724
+ });
725
+ it("afterSave works on insert", async () => {
726
+ let type = class extends newCategories {
727
+ };
728
+ Entity(undefined, {
729
+ allowApiUpdate: true,
730
+ allowApiInsert: true,
731
+ saved: (t) => {
732
+ savedWorked.ok();
733
+ expect(t._.isNew()).toBe(true);
734
+ expect(t._.fields.categoryName.originalValue).toBe(undefined);
735
+ expect(t.categoryName).toBe('noam 1');
736
+ }
737
+ })(type);
738
+ let [c, remult] = await createData(async (insert) => { }, type);
739
+ let savedWorked = new Done();
740
+ var api = new DataApi(c, remult);
741
+ let t = new TestDataApiResponse();
742
+ let d = new Done();
743
+ t.created = async (data) => {
744
+ d.ok();
745
+ };
746
+ await api.post(t, {
747
+ id: 1,
748
+ categoryName: 'noam 1'
749
+ });
750
+ d.test();
751
+ savedWorked.test();
752
+ var x = await c.find({ where: { id: 1 } });
753
+ expect(x[0].categoryName).toBe('noam 1');
754
+ });
755
+ it("put with disable save still works", async () => {
756
+ let startTest = false;
757
+ let mem = new InMemoryDataProvider();
758
+ remult.dataProvider = (mem);
759
+ let type = class extends newCategories {
760
+ };
761
+ Entity('testE', {
762
+ allowApiUpdate: true,
763
+ saving: (row, cancel) => {
764
+ if (startTest) {
765
+ mem.rows["testE"][0].categoryName = 'kuku';
766
+ expect(mem.rows["testE"][0].categoryName).toBe('kuku');
767
+ cancel();
768
+ }
769
+ }
770
+ })(type);
771
+ {
772
+ let c = remult.repo(type).create();
773
+ c.id = 1;
774
+ c.categoryName = 'name';
775
+ c.description = "noam";
776
+ await c._.save();
777
+ }
778
+ ;
779
+ var api = new DataApi(remult.repo(type), remult);
780
+ let t = new TestDataApiResponse();
781
+ let d = new Done();
782
+ t.success = data => {
783
+ expect(data.categoryName).toBe('kuku');
784
+ d.ok();
785
+ };
786
+ startTest = true;
787
+ await api.put(t, 1, {
788
+ categoryName: 'noam 1'
789
+ });
790
+ d.test();
791
+ var x = await remult.repo(type).find({ where: { id: 1 } });
792
+ expect(x[0].categoryName).toBe('kuku');
793
+ });
794
+ it("get based on id with excluded columns", async () => {
795
+ let type = class extends newCategories {
796
+ categoryName;
797
+ };
798
+ Fields.string({ includeInApi: false })(type.prototype, "categoryName");
799
+ Entity('')(type);
800
+ let [c, remult] = await createData(async (insert) => await insert(1, 'noam'), type);
801
+ var api = new DataApi(c, remult);
802
+ let t = new TestDataApiResponse();
803
+ let d = new Done();
804
+ t.success = async (data) => {
805
+ expect(data.id).toBe(1);
806
+ expect(data.categoryName).toBe(undefined);
807
+ d.ok();
808
+ };
809
+ await api.get(t, 1);
810
+ d.test();
811
+ });
812
+ it("row reload", async () => {
813
+ let [c, remult] = await createData(async (insert) => await insert(1, 'noam'));
814
+ let a = await c.findId(1);
815
+ let b = await c.findId(1, { useCache: false });
816
+ a.categoryName = "yael";
817
+ await a._.save();
818
+ expect(b.categoryName).toBe('noam');
819
+ await b._.reload();
820
+ expect(b.categoryName).toBe('yael');
821
+ expect(b._.wasChanged()).toBe(false);
822
+ expect(b.$.categoryName.originalValue).toBe('yael');
823
+ });
824
+ it("Find null works", async () => {
825
+ let [c, remult] = await createData(async (insert) => await insert(1, 'noam'));
826
+ expect(await c.findId(null)).toBeNull();
827
+ expect(await c.findId(undefined)).toBeNull();
828
+ });
829
+ it("put updates", async () => {
830
+ let [c, remult] = await createData(async (insert) => await insert(1, 'noam'));
831
+ var api = new DataApi(c, remult);
832
+ let t = new TestDataApiResponse();
833
+ let d = new Done();
834
+ t.success = async (data) => {
835
+ expect(data.id).toBe(1);
836
+ expect(data.categoryName).toBe('noam 1');
837
+ d.ok();
838
+ };
839
+ await api.put(t, 1, {
840
+ categoryName: 'noam 1'
841
+ });
842
+ d.test();
843
+ var x = await c.find({ where: { id: 1 } });
844
+ expect(x[0].categoryName).toBe('noam 1');
845
+ });
846
+ it("put updates and readonly columns", async () => {
847
+ let type = class extends newCategories {
848
+ categoryName;
849
+ };
850
+ Fields.string({ allowApiUpdate: false })(type.prototype, "categoryName");
851
+ Entity('', { allowApiUpdate: true })(type);
852
+ let [c, remult] = await createData(async (insert) => await insert(1, 'noam'), type);
853
+ var api = new DataApi(c, remult);
854
+ let t = new TestDataApiResponse();
855
+ let d = new Done();
856
+ t.success = async (data) => {
857
+ expect(data.id).toBe(1);
858
+ expect(data.categoryName).toBe('noam');
859
+ d.ok();
860
+ };
861
+ await api.put(t, 1, {
862
+ categoryName: 'noam 1'
863
+ });
864
+ d.test();
865
+ var x = await c.find({ where: { id: 1 } });
866
+ expect(x[0].categoryName).toBe('noam');
867
+ });
868
+ it("put fails when not found", async () => {
869
+ let [c, remult] = await createData(async (insert) => insert(1, 'noam'));
870
+ var api = new DataApi(c, remult);
871
+ let t = new TestDataApiResponse();
872
+ let d = new Done();
873
+ t.notFound = () => d.ok();
874
+ await api.put(t, 2, {});
875
+ d.test();
876
+ });
877
+ it("put updates", async () => {
878
+ let type = class extends newCategories {
879
+ categoryName;
880
+ };
881
+ Fields.string({ includeInApi: false })(type.prototype, "categoryName");
882
+ Entity('', { allowApiUpdate: true })(type);
883
+ let [c, remult] = await createData(async (insert) => await insert(1, 'noam'), type);
884
+ expect(c.fields.categoryName.includedInApi).toBe(false);
885
+ expect(c.fields.description.includedInApi).toBe(true);
886
+ var api = new DataApi(c, remult);
887
+ let t = new TestDataApiResponse();
888
+ let d = new Done();
889
+ t.success = async (data) => {
890
+ expect(data.id).toBe(1);
891
+ expect(data.categoryName).toBe(undefined);
892
+ d.ok();
893
+ };
894
+ await api.put(t, 1, {
895
+ categoryName: 'noam 1'
896
+ });
897
+ d.test();
898
+ var x = await c.find({ where: { id: 1 } });
899
+ expect(x[0].categoryName).toBe('noam');
900
+ });
901
+ it("post with syntax error fails well", async () => {
902
+ let type = class extends newCategories {
903
+ };
904
+ Entity('', {
905
+ allowApiInsert: true,
906
+ saving: (x) => x.description.length + 1
907
+ })(type);
908
+ let [c, remult] = await createData(async (insert) => { }, type);
909
+ var api = new DataApi(c, remult);
910
+ let t = new TestDataApiResponse();
911
+ let d = new Done();
912
+ t.error = async (data) => {
913
+ expect(data.message).toContain("Cannot read prop");
914
+ d.ok();
915
+ };
916
+ await api.post(t, { id: 1, categoryName: 'noam' });
917
+ d.test();
918
+ expect((await c.find()).length).toBe(0);
919
+ });
920
+ it("getArray works with filter contains", async () => {
921
+ let [c, remult] = await createData(async (i) => {
922
+ await i(1, 'noam');
923
+ await i(2, 'yael');
924
+ await i(3, 'yoni');
925
+ });
926
+ var api = new DataApi(c, remult);
927
+ let t = new TestDataApiResponse();
928
+ let d = new Done();
929
+ t.success = data => {
930
+ expect(data.length).toBe(2);
931
+ expect(data[0].id).toBe(1);
932
+ expect(data[1].id).toBe(2);
933
+ d.ok();
934
+ };
935
+ await api.getArray(t, {
936
+ get: x => {
937
+ if (x == c.create()._.fields.categoryName.metadata.key + '.contains')
938
+ return "a";
939
+ return undefined;
940
+ }
941
+ });
942
+ d.test();
943
+ });
944
+ it("getArray works with predefined filter", async () => {
945
+ let [c, remult] = await createData(async (i) => {
946
+ await i(1, 'noam', 'a');
947
+ await i(2, 'yael', 'b');
948
+ await i(3, 'yoni', 'a');
949
+ });
950
+ var api = new DataApi(c, remult);
951
+ let t = new TestDataApiResponse();
952
+ let d = new Done();
953
+ t.success = data => {
954
+ expect(data.length).toBe(2);
955
+ expect(data[0].id).toBe(1);
956
+ d.ok();
957
+ };
958
+ await api.getArray(t, {
959
+ get: x => {
960
+ if (x == c.create()._.fields.description.metadata.key)
961
+ return "a";
962
+ return undefined;
963
+ }
964
+ });
965
+ d.test();
966
+ });
967
+ it("allow api read depends also on api crud", async () => {
968
+ let sc = new Remult();
969
+ let type = class extends EntityBase {
970
+ };
971
+ Entity('a', { allowApiCrud: false })(type);
972
+ expect(sc.repo(type).metadata.apiReadAllowed).toBe(false);
973
+ });
974
+ it("allow api read depends also on api crud", async () => {
975
+ let sc = new Remult();
976
+ let type = class extends EntityBase {
977
+ };
978
+ Entity('a', { allowApiCrud: false, allowApiRead: true })(type);
979
+ expect(sc.repo(type).metadata.apiReadAllowed).toBe(true);
980
+ });
981
+ it("read is not Allowed", async () => {
982
+ let type = class extends newCategories {
983
+ };
984
+ Entity('', {
985
+ allowApiRead: false
986
+ })(type);
987
+ let [c, remult] = await createData(async (i) => {
988
+ await i(1, 'noam', 'a');
989
+ await i(2, 'yael', 'b');
990
+ await i(3, 'yoni', 'a');
991
+ }, type);
992
+ var api = new DataApi(c, remult);
993
+ let t = new TestDataApiResponse();
994
+ let d = new Done();
995
+ t.forbidden = () => {
996
+ d.ok();
997
+ };
998
+ await api.getArray(t, {
999
+ get: x => {
1000
+ if (x == "categoryName")
1001
+ return "a";
1002
+ return undefined;
1003
+ }
1004
+ });
1005
+ d.test();
1006
+ });
1007
+ it("get is not Allowed", async () => {
1008
+ let type = class extends newCategories {
1009
+ };
1010
+ Entity('', {
1011
+ allowApiRead: false,
1012
+ allowApiCrud: undefined,
1013
+ allowApiUpdate: undefined
1014
+ })(type);
1015
+ let [c, remult] = await createData(async (i) => {
1016
+ await i(1, 'noam', 'a');
1017
+ await i(2, 'yael', 'b');
1018
+ await i(3, 'yoni', 'a');
1019
+ }, type);
1020
+ var api = new DataApi(c, remult);
1021
+ let t = new TestDataApiResponse();
1022
+ let d = new Done();
1023
+ t.forbidden = () => {
1024
+ d.ok();
1025
+ };
1026
+ await api.get(t, 1);
1027
+ d.test();
1028
+ });
1029
+ it("count is not Allowed", async () => {
1030
+ let type = class extends newCategories {
1031
+ };
1032
+ Entity('', {
1033
+ allowApiRead: false
1034
+ })(type);
1035
+ let [c, remult] = await createData(async (i) => {
1036
+ await i(1, 'noam', 'a');
1037
+ await i(2, 'yael', 'b');
1038
+ await i(3, 'yoni', 'a');
1039
+ }, type);
1040
+ var api = new DataApi(c, remult);
1041
+ let t = new TestDataApiResponse();
1042
+ let d = new Done();
1043
+ t.forbidden = () => {
1044
+ d.ok();
1045
+ };
1046
+ await api.count(t, {
1047
+ get: x => {
1048
+ if (x == "categoryName")
1049
+ return "a";
1050
+ return undefined;
1051
+ }
1052
+ });
1053
+ d.test();
1054
+ });
1055
+ it("delete id not Allowed", async () => {
1056
+ let type = class extends newCategories {
1057
+ };
1058
+ Entity('', {
1059
+ allowApiDelete: false
1060
+ })(type);
1061
+ let [c, remult] = await createData(async (i) => {
1062
+ await i(1, 'noam', 'a');
1063
+ await i(2, 'yael', 'b');
1064
+ await i(3, 'yoni', 'a');
1065
+ }, type);
1066
+ var api = new DataApi(c, remult);
1067
+ let t = new TestDataApiResponse();
1068
+ let d = new Done();
1069
+ t.forbidden = () => {
1070
+ d.ok();
1071
+ };
1072
+ await api.delete(t, 2);
1073
+ d.test();
1074
+ });
1075
+ it("apiRequireId", async () => {
1076
+ let type = class extends newCategories {
1077
+ };
1078
+ Entity('', {
1079
+ apiRequireId: true
1080
+ })(type);
1081
+ let [c, remult] = await createData(async (i) => {
1082
+ await i(1, 'noam', 'a');
1083
+ await i(2, 'yael', 'b');
1084
+ await i(3, 'yoni', 'a');
1085
+ }, type);
1086
+ var api = new DataApi(c, remult);
1087
+ let t = new TestDataApiResponse();
1088
+ let d = new Done();
1089
+ t.forbidden = () => {
1090
+ d.ok();
1091
+ };
1092
+ await api.getArray(t, {
1093
+ get: x => {
1094
+ if (x == "categoryName")
1095
+ return "a";
1096
+ return undefined;
1097
+ }
1098
+ });
1099
+ d.test();
1100
+ t = new TestDataApiResponse();
1101
+ d = new Done();
1102
+ t.success = () => {
1103
+ d.ok();
1104
+ };
1105
+ await api.getArray(t, {
1106
+ get: x => {
1107
+ if (x == "id")
1108
+ return "1";
1109
+ return undefined;
1110
+ }
1111
+ });
1112
+ d.test();
1113
+ t = new TestDataApiResponse();
1114
+ d = new Done();
1115
+ t.success = () => {
1116
+ d.ok();
1117
+ };
1118
+ await api.get(t, 1);
1119
+ d.test();
1120
+ });
1121
+ it("delete id not Allowed for specific row", async () => {
1122
+ let type = class extends newCategories {
1123
+ };
1124
+ Entity('', {
1125
+ allowApiDelete: (t, c) => {
1126
+ return t.id == 1;
1127
+ }
1128
+ })(type);
1129
+ let [c, remult] = await createData(async (i) => {
1130
+ await i(1, 'noam', 'a');
1131
+ await i(2, 'yael', 'b');
1132
+ await i(3, 'yoni', 'a');
1133
+ }, type);
1134
+ var api = new DataApi(c, remult);
1135
+ let t = new TestDataApiResponse();
1136
+ let d = new Done();
1137
+ t.forbidden = () => {
1138
+ d.ok();
1139
+ };
1140
+ await api.delete(t, 2);
1141
+ d.test();
1142
+ t = new TestDataApiResponse();
1143
+ d = new Done();
1144
+ t.deleted = () => d.ok();
1145
+ await api.delete(t, 1);
1146
+ d.test();
1147
+ });
1148
+ it("update id not Allowed for specific row", async () => {
1149
+ let type = class extends newCategories {
1150
+ };
1151
+ Entity('', {
1152
+ allowApiUpdate: (t, c) => {
1153
+ return t.id == 1;
1154
+ }
1155
+ })(type);
1156
+ let [c, remult] = await createData(async (i) => {
1157
+ await i(1, 'noam', 'a');
1158
+ await i(2, 'yael', 'b');
1159
+ await i(3, 'yoni', 'a');
1160
+ }, type);
1161
+ var api = new DataApi(c, remult);
1162
+ let t = new TestDataApiResponse();
1163
+ let d = new Done();
1164
+ t.forbidden = () => {
1165
+ d.ok();
1166
+ };
1167
+ await api.put(t, 2, {
1168
+ categoryName: 'noam 1'
1169
+ });
1170
+ d.test();
1171
+ expect(c.metadata.apiUpdateAllowed({ id: 2 })).toBe(false);
1172
+ expect(c.metadata.apiUpdateAllowed({ id: 1 })).toBe(true);
1173
+ t = new TestDataApiResponse();
1174
+ d = new Done();
1175
+ t.success = () => d.ok();
1176
+ await api.put(t, 1, {
1177
+ categoryName: 'noam 1'
1178
+ });
1179
+ d.test();
1180
+ });
1181
+ it("insert id not Allowed for specific row", async () => {
1182
+ let type = class extends newCategories {
1183
+ };
1184
+ Entity('', {
1185
+ allowApiInsert: (t, c) => {
1186
+ return t.categoryName == 'ok';
1187
+ }
1188
+ })(type);
1189
+ let [c, remult] = await createData(async (i) => {
1190
+ await i(1, 'noam', 'a');
1191
+ await i(2, 'yael', 'b');
1192
+ await i(3, 'yoni', 'a');
1193
+ }, type);
1194
+ var api = new DataApi(c, remult);
1195
+ let t = new TestDataApiResponse();
1196
+ let d = new Done();
1197
+ t.forbidden = () => {
1198
+ d.ok();
1199
+ };
1200
+ await api.post(t, {
1201
+ categoryName: 'wrong'
1202
+ });
1203
+ d.test();
1204
+ t = new TestDataApiResponse();
1205
+ d = new Done();
1206
+ t.created = () => d.ok();
1207
+ await api.post(t, {
1208
+ categoryName: 'ok'
1209
+ });
1210
+ d.test();
1211
+ });
1212
+ it("getArray works with sort", async () => {
1213
+ let [c, remult] = await createData(async (i) => {
1214
+ await i(1, 'a');
1215
+ await i(2, 'c');
1216
+ await i(3, 'b');
1217
+ await i(4, 'c');
1218
+ });
1219
+ var api = new DataApi(c, remult);
1220
+ let t = new TestDataApiResponse();
1221
+ let d = new Done();
1222
+ t.success = data => {
1223
+ expect(data.length).toBe(4);
1224
+ expect(data[0].id).toBe(1);
1225
+ expect(data[1].id).toBe(3);
1226
+ expect(data[2].id).toBe(4);
1227
+ expect(data[3].id).toBe(2);
1228
+ d.ok();
1229
+ };
1230
+ await api.getArray(t, {
1231
+ get: x => {
1232
+ if (x == "_sort")
1233
+ return "categoryName,id";
1234
+ if (x == "_order")
1235
+ return "asc,desc";
1236
+ return undefined;
1237
+ }
1238
+ });
1239
+ d.test();
1240
+ });
1241
+ it("columnsAreOk", () => {
1242
+ let c = new Remult().repo(newCategories).create();
1243
+ expect([...c._.fields].length).toBe(6);
1244
+ expect(c._.fields.toArray().length).toBe(6);
1245
+ });
1246
+ });
1247
+ describe("rest call use url get or fallback to post", () => {
1248
+ it("should get", () => {
1249
+ let url = new UrlBuilder('');
1250
+ expect(addFilterToUrlAndReturnTrueIfSuccessful({ a: 1 }, url)).toBe(true);
1251
+ expect(url.url).toBe("?a=1");
1252
+ });
1253
+ it("should get 1", () => {
1254
+ let url = new UrlBuilder('');
1255
+ expect(addFilterToUrlAndReturnTrueIfSuccessful({ "a.ne": 1 }, url)).toBe(true);
1256
+ expect(url.url).toBe("?a.ne=1");
1257
+ });
1258
+ it("should get 2", () => {
1259
+ let url = new UrlBuilder('');
1260
+ expect(addFilterToUrlAndReturnTrueIfSuccessful({ "a.ne": [1, 2] }, url)).toBe(true);
1261
+ expect(url.url).toBe("?a.ne=1&a.ne=2");
1262
+ });
1263
+ it("should get 3", () => {
1264
+ let url = new UrlBuilder('');
1265
+ expect(addFilterToUrlAndReturnTrueIfSuccessful({ "a.in": [1, 2] }, url)).toBe(true);
1266
+ expect(url.url).toBe("?a.in=%5B1%2C2%5D");
1267
+ });
1268
+ it("should post ", () => {
1269
+ let url = new UrlBuilder('');
1270
+ expect(addFilterToUrlAndReturnTrueIfSuccessful({ "a.in": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] }, url)).toBe(false);
1271
+ });
1272
+ it("should post ", () => {
1273
+ let url = new UrlBuilder('');
1274
+ expect(addFilterToUrlAndReturnTrueIfSuccessful({ or: [{ a: 1 }, { a: 3 }] }, url)).toBe(false);
1275
+ });
1276
+ });
1277
+ describe("column validation", () => {
1278
+ it("validation clears on reset", () => {
1279
+ let c = new Remult().repo(newCategories).create();
1280
+ expect(c._.hasErrors()).toBe(true);
1281
+ c._.fields.id.error = "x";
1282
+ expect(c._.fields.id.error).toBe("x");
1283
+ expect(c._.hasErrors()).toBe(false);
1284
+ c._.undoChanges();
1285
+ expect(c._.fields.id.error).toBe(undefined);
1286
+ expect(c._.hasErrors()).toBe(true);
1287
+ });
1288
+ it("validation clears on change", () => {
1289
+ let c = new Remult().repo(newCategories).create();
1290
+ expect(c._.hasErrors()).toBe(true);
1291
+ c._.fields.id.error = "x";
1292
+ expect(c._.hasErrors()).toBe(false);
1293
+ expect(c._.fields.id.error).toBe("x");
1294
+ c.id = 1;
1295
+ //expect(c._.isValid()).toBe(true);
1296
+ //expect(c._.columns.id.error).toBe(undefined);
1297
+ });
1298
+ it("test date filter and values", async () => {
1299
+ let sql = new SqlDatabase(new WebSqlDataProvider('identity_game'));
1300
+ let c = new Remult(sql);
1301
+ await sql.execute("drop table if exists t1");
1302
+ c.dataProvider = (sql);
1303
+ let type = class extends EntityBase {
1304
+ id;
1305
+ name;
1306
+ c3;
1307
+ };
1308
+ Entity('t1')(type);
1309
+ Fields.autoIncrement()(type.prototype, "id");
1310
+ Fields.string()(type.prototype, "name");
1311
+ Fields.date()(type.prototype, "c3");
1312
+ let f = c.repo(type);
1313
+ let d = new Date(2020, 1, 2, 3, 4, 5, 6);
1314
+ let p = f.create();
1315
+ p.name = '1';
1316
+ p.c3 = d;
1317
+ await p._.save();
1318
+ await f.create({ name: '2', c3: new Date(2021) }).save();
1319
+ p = await f.findFirst({ c3: d });
1320
+ p = await f.findFirst({ c3: d });
1321
+ f.findFirst({ c3: d });
1322
+ expect(p.name).toBe('1');
1323
+ p = await f.findFirst({ c3: { $ne: d } });
1324
+ expect(p.name).toBe('2');
1325
+ p = await f.findFirst({ c3: { "!=": d } });
1326
+ expect(p.name).toBe('2');
1327
+ });
1328
+ });
1329
+ describe("test web sql identity", () => {
1330
+ it("play", async () => {
1331
+ let sql = new SqlDatabase(new WebSqlDataProvider('identity_game'));
1332
+ let c = new Remult(sql);
1333
+ await sql.execute("drop table if exists t1");
1334
+ c.dataProvider = (sql);
1335
+ let type = class extends EntityBase {
1336
+ id;
1337
+ name;
1338
+ };
1339
+ Entity('t1')(type);
1340
+ Fields.autoIncrement()(type.prototype, "id");
1341
+ Fields.string()(type.prototype, "name");
1342
+ let f = c.repo(type);
1343
+ let t = f.create();
1344
+ t.name = 'a';
1345
+ await t._.save();
1346
+ expect(t.id).toBe(1);
1347
+ t = f.create();
1348
+ t.name = 'b';
1349
+ await t._.save();
1350
+ expect(t.id).toBe(2);
1351
+ });
1352
+ });
1353
+ describe("compound id", () => {
1354
+ it("id field is compound", () => {
1355
+ let ctx = new Remult();
1356
+ expect(ctx.repo(CompoundIdEntity).metadata.idMetadata.field instanceof CompoundIdField).toBe(true);
1357
+ });
1358
+ it("result id filter works with object", async () => {
1359
+ let ctx = new Remult();
1360
+ let repo = ctx.repo(CompoundIdEntity);
1361
+ let id = repo.metadata.idMetadata.field;
1362
+ var n = await dbNamesOf(repo.metadata);
1363
+ let f = new FilterConsumerBridgeToSqlRequest({
1364
+ addParameterAndReturnSqlToken: x => x
1365
+ }, n);
1366
+ id.resultIdFilter(undefined, repo.create({ a: 1, b: 2 })).__applyToConsumer(f);
1367
+ expect(await f.resolveWhere()).toBe(" where a = 1 and b = 2");
1368
+ });
1369
+ it("check is auto increment", async () => {
1370
+ let ctx = new Remult();
1371
+ let repo = ctx.repo(CompoundIdEntity);
1372
+ expect(isAutoIncrement(repo.metadata.idMetadata.field)).toBe(false);
1373
+ });
1374
+ it("result id filter works with id", async () => {
1375
+ let ctx = new Remult();
1376
+ let repo = ctx.repo(CompoundIdEntity);
1377
+ let id = repo.metadata.idMetadata.field;
1378
+ var n = await dbNamesOf(repo.metadata);
1379
+ let f = new FilterConsumerBridgeToSqlRequest({
1380
+ addParameterAndReturnSqlToken: x => x
1381
+ }, n);
1382
+ id.resultIdFilter("1,2", repo.create({ a: 1, b: 2 })).__applyToConsumer(f);
1383
+ expect(await f.resolveWhere()).toBe(" where a = 1 and b = 2");
1384
+ });
1385
+ it("some things should not work", async () => {
1386
+ let ctx = new Remult();
1387
+ let repo = ctx.repo(CompoundIdEntity);
1388
+ let id = repo.metadata.idMetadata.field;
1389
+ expect(() => id.valueConverter).toThrowError();
1390
+ expect(await id.getDbName()).toBe("");
1391
+ });
1392
+ it("compound sql", async () => {
1393
+ let sql = new SqlDatabase(new WebSqlDataProvider('compound'));
1394
+ let ctx = new Remult();
1395
+ ctx.dataProvider = (sql);
1396
+ let cod = ctx.repo(CompoundIdEntity);
1397
+ for (const od of await cod.find({ where: { a: 99 } })) {
1398
+ await od._.delete();
1399
+ }
1400
+ let od = cod.create();
1401
+ od.a = 99;
1402
+ od.b = 1;
1403
+ await od._.save();
1404
+ od = await cod.findFirst({ a: 99 });
1405
+ od.c = 5;
1406
+ await od._.save();
1407
+ await od._.delete();
1408
+ });
1409
+ const ctx = new Remult();
1410
+ it("start", async () => {
1411
+ let mem = new InMemoryDataProvider();
1412
+ let ctx = new Remult();
1413
+ ctx.dataProvider = (mem);
1414
+ let s = ctx.repo(CompoundIdEntity);
1415
+ mem.rows[s.metadata.key] = [{ a: 1, b: 11, c: 111 }, { a: 2, b: 22, c: 222 }];
1416
+ var r = await s.find();
1417
+ expect(r.length).toBe(2);
1418
+ expect(r[0].a).toBe(1);
1419
+ expect(r[0]._.getId()).toBe('1,11');
1420
+ r = await s.find({ where: s.metadata.idMetadata.getIdFilter('1,11') });
1421
+ expect(r.length).toBe(1);
1422
+ expect(r[0].a).toBe(1);
1423
+ });
1424
+ it("update", async () => {
1425
+ let mem = new InMemoryDataProvider();
1426
+ let ctx = new Remult();
1427
+ ctx.dataProvider = (mem);
1428
+ let c = ctx.repo(CompoundIdEntity);
1429
+ mem.rows[c.metadata.key] = [{ a: 1, b: 11, c: 111 }, { a: 2, b: 22, c: 222 }];
1430
+ var r = await c.find();
1431
+ expect(r[0].c).toBe(111);
1432
+ r[0].c = 55;
1433
+ expect(r[0]._.fields.c.originalValue).toBe(111);
1434
+ let saved = await r[0]._.save();
1435
+ expect(r[0].c).toBe(55);
1436
+ expect(mem.rows[c.metadata.key][0].c).toBe(55);
1437
+ expect(mem.rows[c.metadata.key][0].id).toBe(undefined);
1438
+ expect(r[0]._.getId()).toBe('1,11');
1439
+ });
1440
+ it("update2", async () => {
1441
+ let mem = new InMemoryDataProvider();
1442
+ let ctx = new Remult();
1443
+ ctx.dataProvider = (mem);
1444
+ let c = ctx.repo(CompoundIdEntity);
1445
+ mem.rows[c.metadata.key] = [{ a: 1, b: 11, c: 111 }, { a: 2, b: 22, c: 222 }];
1446
+ var r = await c.find();
1447
+ r[0].b = 55;
1448
+ let saved = await r[0]._.save();
1449
+ expect(mem.rows[c.metadata.key][0].b).toBe(55);
1450
+ expect(mem.rows[c.metadata.key][0].id).toBe(undefined);
1451
+ expect(r[0]._.getId()).toBe('1,55');
1452
+ });
1453
+ it("insert", async () => {
1454
+ let mem = new InMemoryDataProvider();
1455
+ let ctx = new Remult();
1456
+ ctx.dataProvider = (mem);
1457
+ let c = ctx.repo(CompoundIdEntity).create();
1458
+ mem.rows[ctx.repo(CompoundIdEntity).metadata.key].push({ a: 1, b: 11, c: 111 }, { a: 2, b: 22, c: 222 });
1459
+ c.a = 3;
1460
+ c.b = 33;
1461
+ c.c = 3333;
1462
+ await c._.save();
1463
+ expect(mem.rows[ctx.repo(CompoundIdEntity).metadata.key][2].b).toBe(33);
1464
+ expect(mem.rows[ctx.repo(CompoundIdEntity).metadata.key][2].id).toBe(undefined);
1465
+ expect(c._.getId()).toBe('3,33');
1466
+ });
1467
+ it("delete", async () => {
1468
+ let mem = new InMemoryDataProvider();
1469
+ let ctx = new Remult();
1470
+ ctx.dataProvider = (mem);
1471
+ let c = ctx.repo(CompoundIdEntity);
1472
+ mem.rows[c.metadata.key] = [{ a: 1, b: 11, c: 111 }, { a: 2, b: 22, c: 222 }];
1473
+ let r = await c.find();
1474
+ await r[1]._.delete();
1475
+ expect(mem.rows[c.metadata.key].length).toBe(1);
1476
+ expect(mem.rows[c.metadata.key][0].a).toBe(1);
1477
+ });
1478
+ });
1479
+ describe("test data list", () => {
1480
+ it("delete works", async () => {
1481
+ let [c] = await createData(async (i) => {
1482
+ await i(1, 'a');
1483
+ await i(2, 'b');
1484
+ await i(3, 'c');
1485
+ });
1486
+ let rl = new DataList(c);
1487
+ await rl.get();
1488
+ expect(rl.items.length).toBe(3);
1489
+ await rl.items[1]._.delete();
1490
+ expect(rl.items.length).toBe(2);
1491
+ });
1492
+ it("dbname of entity string works", async () => {
1493
+ let type = class extends Categories {
1494
+ };
1495
+ Entity('testName', { dbName: 'test' })(type);
1496
+ let r = new Remult().repo(type);
1497
+ expect((await r.metadata.getDbName())).toBe('test');
1498
+ });
1499
+ it("dbname of entity can use column names", async () => {
1500
+ let r = new Remult().repo(EntityWithLateBoundDbName);
1501
+ expect((await r.metadata.getDbName())).toBe('(select CategoryID)');
1502
+ });
1503
+ it("delete fails nicely", async () => {
1504
+ let cont = new Remult();
1505
+ cont.dataProvider = ({
1506
+ getEntityDataProvider: x => {
1507
+ let r = new ArrayEntityDataProvider(x, [{ id: 1 }, { id: 2 }, { id: 3 }]);
1508
+ r.delete = id => { return Promise.resolve().then(() => { throw Promise.resolve("error"); }); };
1509
+ return r;
1510
+ }, transaction: undefined
1511
+ });
1512
+ let rl = new DataList(cont.repo(newCategories));
1513
+ await rl.get();
1514
+ expect(rl.items.length).toBe(3);
1515
+ try {
1516
+ await rl.items[1]._.delete();
1517
+ fail("was not supposed to get here");
1518
+ }
1519
+ catch (err) {
1520
+ expect(rl.items.length).toBe(3);
1521
+ expect(rl.items[1]._.error).toBe("error");
1522
+ }
1523
+ });
1524
+ });
1525
+ describe("test date storage", () => {
1526
+ it("works", () => {
1527
+ let val = "1976-06-16";
1528
+ /** */
1529
+ var d = ValueConverters.DateOnly.fromJson(val);
1530
+ expect(d.getFullYear()).toBe(1976);
1531
+ expect(d.getMonth()).toBe(5);
1532
+ expect(d.getDate()).toBe(16);
1533
+ });
1534
+ it("works", () => {
1535
+ let val = new Date(1976, 5, 16);
1536
+ expect(ValueConverters.DateOnly.toJson(val)).toBe('1976-06-16');
1537
+ // expect(ValueConverters.DateOnly.displayValue(val)).toBe("6/16/1976");
1538
+ });
1539
+ });
1540
+ @Entity(undefined)
1541
+ class myEntity {
1542
+ }
1543
+ describe("", () => {
1544
+ it("dbname of entity string works when key is not defined", async () => {
1545
+ let r = new Remult().repo(myEntity);
1546
+ expect((await r.metadata.getDbName())).toBe('myEntity');
1547
+ expect(r.metadata.key).toBe('myEntity');
1548
+ expect(getEntityKey(myEntity)).toBeUndefined();
1549
+ });
1550
+ });
1551
+ describe("test bool value", () => {
1552
+ it("should work", () => {
1553
+ let col = decorateColumnSettings({ valueType: Boolean }, new Remult());
1554
+ expect(col.valueConverter.fromJson(true)).toBe(true);
1555
+ expect(col.valueConverter.fromJson(false)).toBe(false);
1556
+ });
1557
+ });
1558
+ describe("test number negative", () => {
1559
+ // it("negative", () => {
1560
+ // let nc = decorateColumnSettings<number>({ dataType: Number });
1561
+ // expect(nc.valueConverter.toInput(nc.valueConverter.fromInput("-", ''), '')).toBe("-");
1562
+ // });
1563
+ // it("negative2", () => {
1564
+ // let nc = decorateColumnSettings<number>({ dataType: Number });;
1565
+ // expect(nc.valueConverter.fromInput('2-1', '')).toBe(0);
1566
+ // });
1567
+ // it("negative decimal", () => {
1568
+ // let nc = new NumberColumn();
1569
+ // nc.inputValue = '-0.00';
1570
+ // expect(nc.value).toBe(0);
1571
+ // expect(nc.inputValue).toBe('-0.00');
1572
+ // nc.inputValue = '-0.001';
1573
+ // expect(nc.value).toBe(-0.001);
1574
+ // expect(nc.inputValue).toBe('-0.001');
1575
+ // });
1576
+ });
1577
+ describe("cache", () => {
1578
+ it("find first useCache", async () => {
1579
+ let [r,] = await createData(async (i) => i(1, "noam"));
1580
+ await r.findFirst({ id: 1 }, { useCache: true });
1581
+ await r.find().then(x => assign(x[0], { categoryName: 'a' }).save());
1582
+ expect((await r.findFirst({ id: 1 })).categoryName).toBe("a");
1583
+ expect((await r.findFirst({ id: 1 })).categoryName).toBe("a");
1584
+ expect((await r.findFirst({ id: 1 }, { useCache: true })).categoryName).toBe("noam");
1585
+ });
1586
+ it("find id", async () => {
1587
+ let [r,] = await createData(async (i) => i(1, "noam"));
1588
+ await r.findId(1);
1589
+ await r.find().then(x => assign(x[0], { categoryName: 'a' }).save());
1590
+ expect((await r.findId(1)).categoryName).toBe("noam");
1591
+ expect((await r.findId(1, { useCache: false })).categoryName).toBe("a");
1592
+ });
1593
+ });
1594
+ describe("test rest data provider translates data correctly", () => {
1595
+ it("rest data provider works with update", async () => {
1596
+ let [, serverRemult] = await createData(async (insert) => await insert(1, "test"));
1597
+ let restDb = new MockRestDataProvider(serverRemult);
1598
+ let remult = new Remult();
1599
+ remult.dataProvider = (restDb);
1600
+ let c = await remult.repo(Categories).findId(1, { useCache: false });
1601
+ expect(c.categoryName).toBe("test");
1602
+ c.categoryName = "test1";
1603
+ await c.save();
1604
+ expect(c.categoryName).toBe("test1");
1605
+ c = await remult.repo(Categories).findId(1, { useCache: false });
1606
+ expect(c.categoryName).toBe("test1");
1607
+ c.categoryName = undefined;
1608
+ await c.save();
1609
+ expect(c.categoryName).toBeNull();
1610
+ c = await remult.repo(Categories).findId(1, { useCache: false });
1611
+ expect(c.categoryName).toBeNull();
1612
+ });
1613
+ it("get works", async () => {
1614
+ let type = class extends EntityBase {
1615
+ a;
1616
+ b;
1617
+ };
1618
+ Entity('x')(type);
1619
+ Fields.integer()(type.prototype, 'a');
1620
+ Fields.date()(type.prototype, 'b');
1621
+ let c = new Remult().repo(type);
1622
+ let z = new RestDataProvider(() => ({
1623
+ httpClient: {
1624
+ delete: () => undefined,
1625
+ get: async () => {
1626
+ return [
1627
+ {
1628
+ a: 1,
1629
+ b: "2021-05-16T08:32:19.905Z"
1630
+ }
1631
+ ];
1632
+ },
1633
+ post: () => undefined,
1634
+ put: () => undefined
1635
+ }
1636
+ }));
1637
+ let x = z.getEntityDataProvider(c.metadata);
1638
+ let r = await x.find();
1639
+ expect(r.length).toBe(1);
1640
+ expect(r[0].a).toBe(1);
1641
+ expect(r[0].b.valueOf()).toBe(new Date("2021-05-16T08:32:19.905Z").valueOf());
1642
+ expect(r[0].b instanceof Date).toBe(true);
1643
+ });
1644
+ it("test api client", async () => {
1645
+ let type = class extends EntityBase {
1646
+ a;
1647
+ b;
1648
+ };
1649
+ Entity('x')(type);
1650
+ Fields.integer()(type.prototype, 'a');
1651
+ Fields.date()(type.prototype, 'b');
1652
+ let results = [];
1653
+ const remult = new Remult();
1654
+ let c = remult.repo(type);
1655
+ remult.apiClient.httpClient = async (url, args) => {
1656
+ results.push("a:" + url);
1657
+ return ({ status: 200, json: async () => [] });
1658
+ };
1659
+ await c.find();
1660
+ expect(results).toEqual(["a:/api/x"]);
1661
+ results = [];
1662
+ remult.apiClient.url = '/yy';
1663
+ await c.find();
1664
+ expect(results).toEqual(["a:/yy/x"]);
1665
+ results = [];
1666
+ remult.apiClient.httpClient = async (url, args) => {
1667
+ results.push("b:" + url);
1668
+ return ({ status: 200, json: async () => [] });
1669
+ };
1670
+ await c.find();
1671
+ expect(results).toEqual(["b:/yy/x"]);
1672
+ });
1673
+ it("put works", async () => {
1674
+ let type = class extends EntityBase {
1675
+ a;
1676
+ b;
1677
+ };
1678
+ Entity('x')(type);
1679
+ Fields.integer()(type.prototype, 'a');
1680
+ Fields.date()(type.prototype, 'b');
1681
+ let c = new Remult().repo(type);
1682
+ let r = await entityFilterToJson(c.metadata, { b: new Date("2021-05-16T08:32:19.905Z") });
1683
+ expect(r.b).toBe("2021-05-16T08:32:19.905Z");
1684
+ });
1685
+ it("put works", async () => {
1686
+ let type = class extends EntityBase {
1687
+ a;
1688
+ b;
1689
+ };
1690
+ Entity('x')(type);
1691
+ Fields.integer()(type.prototype, 'a');
1692
+ Fields.date()(type.prototype, 'b');
1693
+ let c = new Remult().repo(type);
1694
+ let done = new Done();
1695
+ let z = new RestDataProvider(() => ({
1696
+ httpClient: {
1697
+ delete: () => undefined,
1698
+ get: () => undefined,
1699
+ post: async (x, data) => {
1700
+ done.ok();
1701
+ expect(data.a).toBe(1);
1702
+ expect(data.b).toBe("2021-05-16T08:32:19.905Z");
1703
+ return data;
1704
+ },
1705
+ put: () => undefined
1706
+ }
1707
+ }));
1708
+ let x = z.getEntityDataProvider(c.metadata);
1709
+ let r = await x.insert({
1710
+ a: 1,
1711
+ b: new Date("2021-05-16T08:32:19.905Z")
1712
+ });
1713
+ expect(r.a).toBe(1);
1714
+ expect(r.b instanceof Date).toBe(true);
1715
+ expect(r.b.toISOString()).toBe("2021-05-16T08:32:19.905Z");
1716
+ done.test();
1717
+ });
1718
+ });
1719
+ describe("check allowedDataType", () => {
1720
+ let c = new Remult();
1721
+ c.dataProvider = (new InMemoryDataProvider());
1722
+ let strA = 'roleA', strB = 'roleB', strC = 'roleC';
1723
+ let roleA = (strA);
1724
+ let roleB = (strB);
1725
+ let roleC = (strC);
1726
+ beforeAll(async (done) => {
1727
+ c.user = { id: 'x', name: 'y', roles: [strA, strB] };
1728
+ done();
1729
+ });
1730
+ it("1", () => {
1731
+ expect(c.isAllowed(strA)).toBe(true);
1732
+ });
1733
+ function myIt(allowed, expected, description) {
1734
+ if (!description && allowed != undefined)
1735
+ description = allowed.toString();
1736
+ it(description, () => {
1737
+ expect(c.isAllowed(allowed)).toBe(expected);
1738
+ });
1739
+ }
1740
+ myIt(strA, true, "a");
1741
+ myIt(strC, false, "a");
1742
+ myIt([strA], true, "a");
1743
+ myIt([strC], false, "a");
1744
+ myIt([strA], true, "a");
1745
+ myIt([strC, strA], true, "a");
1746
+ myIt([strC, "strD"], false, "a");
1747
+ myIt(roleA, true);
1748
+ myIt(roleC, false);
1749
+ myIt([roleA], true);
1750
+ myIt([roleC], false);
1751
+ myIt([roleC, roleA], true);
1752
+ myIt([roleC, "strD"], false);
1753
+ myIt(c => c.isAllowed(roleA), true);
1754
+ myIt(true, true);
1755
+ myIt(false, false);
1756
+ myIt(undefined, undefined);
1757
+ it("no context", () => {
1758
+ let c = new Remult();
1759
+ c.dataProvider = (new InMemoryDataProvider());
1760
+ c.user = undefined;
1761
+ expect(c.isAllowed(true)).toBe(true);
1762
+ expect(c.isAllowed(c => true)).toBe(true);
1763
+ expect(c.isAllowed(false)).toBe(false);
1764
+ expect(c.isAllowed(c => false)).toBe(false);
1765
+ // expect(c.isAllowed([false, true])).toBe(true);
1766
+ // expect(c.isAllowed([false, c => true])).toBe(true);
1767
+ // expect(c.isAllowed([false, false])).toBe(false);
1768
+ // expect(c.isAllowed([false, c => false])).toBe(false);
1769
+ expect(c.isAllowed("abc")).toBe(false);
1770
+ });
1771
+ });
1772
+ describe("test http retry", () => {
1773
+ it("test http retry for proxy", async () => {
1774
+ let i = 0;
1775
+ const r = await retry(async () => {
1776
+ if (i++ == 0)
1777
+ throw Error("Error occurred while trying to proxy");
1778
+ return 7;
1779
+ });
1780
+ expect(i).toBe(2);
1781
+ expect(r).toBe(7);
1782
+ });
1783
+ it("fails on other errors", async () => {
1784
+ let ok = false;
1785
+ try {
1786
+ await retry(async () => { throw Error("Another error"); });
1787
+ ok = true;
1788
+ }
1789
+ catch { }
1790
+ expect(ok).toBe(false);
1791
+ });
1792
+ it("fails on other errors that has no message", async () => {
1793
+ let ok = false;
1794
+ try {
1795
+ await retry(async () => { throw "Another error"; });
1796
+ ok = true;
1797
+ }
1798
+ catch { }
1799
+ expect(ok).toBe(false);
1800
+ });
1801
+ });
1802
+ describe("test toPromise", () => {
1803
+ it("handles rxjs style", async () => {
1804
+ const r = await toPromise({
1805
+ toPromise: async () => 7
1806
+ });
1807
+ expect(r).toBe(7);
1808
+ });
1809
+ it("handles normal promise", async () => {
1810
+ const r = await toPromise(new Promise(r => r(7)));
1811
+ expect(r).toBe(7);
1812
+ });
1813
+ it("handles axios results", async () => {
1814
+ const r = await toPromise(new Promise(r => r({
1815
+ data: 7,
1816
+ headers: {},
1817
+ request: {},
1818
+ status: 200
1819
+ })));
1820
+ expect(r).toBe(7);
1821
+ });
1822
+ });
1823
+ @Entity("CompoundIdPojoEntity", {
1824
+ id: x => [x.a, x.b]
1825
+ })
1826
+ class CompoundIdSimple {
1827
+ @Fields.integer()
1828
+ a;
1829
+ @Fields.integer()
1830
+ b;
1831
+ @Fields.integer()
1832
+ c;
1833
+ }
1834
+ describe("CompoundIdPojoEntity", () => {
1835
+ it("test basic operations", async () => {
1836
+ var repo = new Remult(new InMemoryDataProvider()).repo(CompoundIdSimple);
1837
+ expect(repo.metadata.idMetadata.getId({ a: 1, b: 10, c: 100 })).toBe("1,10");
1838
+ });
1839
+ it("test delete by id", async () => {
1840
+ var repo = new Remult(new InMemoryDataProvider()).repo(CompoundIdSimple);
1841
+ await repo.insert([
1842
+ { a: 1, b: 10, c: 100 },
1843
+ { a: 2, b: 20, c: 200 },
1844
+ { a: 3, b: 30, c: 300 },
1845
+ ]);
1846
+ await repo.delete(repo.metadata.idMetadata.getId({ a: 2, b: 20 }));
1847
+ expect((await repo.find()).map(x => x.a)).toEqual([1, 3]);
1848
+ });
1849
+ it("test delete", async () => {
1850
+ var repo = new Remult(new InMemoryDataProvider()).repo(CompoundIdSimple);
1851
+ await repo.insert([
1852
+ { a: 1, b: 10, c: 100 },
1853
+ { a: 2, b: 20, c: 200 },
1854
+ { a: 3, b: 30, c: 300 },
1855
+ ]);
1856
+ await repo.delete({ a: 2, b: 20, c: 200 });
1857
+ expect((await repo.find()).map(x => x.a)).toEqual([1, 3]);
1858
+ });
1859
+ it("test delete with partial object", async () => {
1860
+ var repo = new Remult(new InMemoryDataProvider()).repo(CompoundIdSimple);
1861
+ await repo.insert([
1862
+ { a: 1, b: 10, c: 100 },
1863
+ { a: 2, b: 20, c: 200 },
1864
+ { a: 3, b: 30, c: 300 },
1865
+ ]);
1866
+ await repo.delete({ a: 2, b: 20 });
1867
+ expect((await repo.find()).map(x => x.a)).toEqual([1, 3]);
1868
+ });
1869
+ it("test save", async () => {
1870
+ var repo = new Remult(new InMemoryDataProvider()).repo(CompoundIdSimple);
1871
+ await repo.insert([
1872
+ { a: 1, b: 10, c: 100 },
1873
+ { a: 2, b: 20, c: 200 },
1874
+ { a: 3, b: 30, c: 300 },
1875
+ ]);
1876
+ await repo.save({ a: 2, b: 20, c: 201 });
1877
+ expect((await repo.findFirst({ a: 2, b: 20 })).c).toBe(201);
1878
+ });
1879
+ it("test update", async () => {
1880
+ var repo = new Remult(new InMemoryDataProvider()).repo(CompoundIdSimple);
1881
+ await repo.insert([
1882
+ { a: 2, b: 20, c: 200 },
1883
+ ]);
1884
+ await repo.update(repo.metadata.idMetadata.getId({ a: 2, b: 20 }), { c: 201 });
1885
+ expect((await repo.findFirst({ a: 2, b: 20 })).c).toBe(201);
1886
+ });
1887
+ it("test update", async () => {
1888
+ var repo = new Remult(new InMemoryDataProvider()).repo(CompoundIdSimple);
1889
+ await repo.insert([
1890
+ { a: 2, b: 20, c: 200 },
1891
+ ]);
1892
+ await repo.update(repo.metadata.idMetadata.getId({ a: 2, b: 20 }), { c: 201 });
1893
+ expect((await repo.findFirst({ a: 2, b: 20 })).c).toBe(201);
1894
+ });
1895
+ it("test update", async () => {
1896
+ var repo = new Remult(new InMemoryDataProvider()).repo(CompoundIdSimple);
1897
+ await repo.insert([
1898
+ { a: 2, b: 20, c: 200 },
1899
+ ]);
1900
+ await repo.update({ a: 2, b: 20 }, { c: 201 });
1901
+ expect((await repo.findFirst({ a: 2, b: 20 })).c).toBe(201);
1902
+ });
1903
+ it("test update change of id fields", async () => {
1904
+ var repo = new Remult(new InMemoryDataProvider()).repo(CompoundIdSimple);
1905
+ await repo.insert([
1906
+ { a: 2, b: 20, c: 200 },
1907
+ ]);
1908
+ await repo.update(repo.metadata.idMetadata.getId({ a: 2, b: 20 }), { b: 21 });
1909
+ expect((await repo.findFirst({ a: 2 })).b).toBe(21);
1910
+ });
1911
+ });
1912
+ @Entity('compountIdEntity', {
1913
+ id: x => [x.a, x.b],
1914
+ })
1915
+ class CompoundIdEntity extends EntityBase {
1916
+ @Fields.integer()
1917
+ a;
1918
+ @Fields.integer()
1919
+ b;
1920
+ @Fields.integer()
1921
+ c;
1922
+ }
1923
+ @Entity('', {
1924
+ validation: (t => {
1925
+ if (!t.name || t.name.length < 3)
1926
+ t._.fields.name.error = 'invalid';
1927
+ })
1928
+ })
1929
+ export class entityWithValidationsOnEntityEvent extends EntityBase {
1930
+ @Fields.integer()
1931
+ myId;
1932
+ @Fields.string()
1933
+ name;
1934
+ }
1935
+ @Entity('stam', {
1936
+ sqlExpression: async (t) => '(select ' + t.fields.id.options.dbName + ')'
1937
+ })
1938
+ export class EntityWithLateBoundDbName extends EntityBase {
1939
+ @Fields.integer({ dbName: 'CategoryID' })
1940
+ id;
1941
+ }
1942
+ describe("test fetch", () => {
1943
+ it("test remult with non default fetch function", async () => {
1944
+ var r = new Remult(new RestDataProviderHttpProviderUsingFetch(async (url, info) => {
1945
+ return new mockResponse({ status: 200, json: async () => ({ count: 7 }) });
1946
+ }));
1947
+ expect(await r.repo(Categories).count()).toBe(7);
1948
+ });
1949
+ it("test remult with non default fetch function1", async () => {
1950
+ var r = new Remult(async (url, info) => {
1951
+ return new mockResponse({ status: 200, json: async () => ({ count: 7 }) });
1952
+ });
1953
+ expect(await r.repo(Categories).count()).toBe(7);
1954
+ });
1955
+ it("axios uses the correct api", () => {
1956
+ const r = new Remult(axios);
1957
+ expect(r.apiClient.httpClient).toBe(axios);
1958
+ expect(r.dataProvider.apiProvider().httpClient).toBe(axios); //
1959
+ expect(r.dataProvider.getEntityDataProvider(r.repo(Categories).metadata).http()
1960
+ instanceof HttpProviderBridgeToRestDataProviderHttpProvider).toBe(true);
1961
+ });
1962
+ it("get", async () => {
1963
+ let z = await new RestDataProviderHttpProviderUsingFetch(async (url, info) => {
1964
+ return new mockResponse({ status: 200, json: async () => 7 });
1965
+ }).get('abc');
1966
+ expect(z).toBe(7);
1967
+ });
1968
+ it("error", async () => {
1969
+ try {
1970
+ await new RestDataProviderHttpProviderUsingFetch(async (url, info) => {
1971
+ return new mockResponse({ status: 401, statusText: 'text', url: 'url', json: async () => ({}) });
1972
+ }).get('abc');
1973
+ }
1974
+ catch (err) {
1975
+ expect(err).toEqual({
1976
+ status: 401, message: 'text', url: 'url'
1977
+ });
1978
+ }
1979
+ });
1980
+ it("error4", async () => {
1981
+ try {
1982
+ await new RestDataProviderHttpProviderUsingFetch(async (url, info) => {
1983
+ return new mockResponse({
1984
+ status: 401, statusText: 'text', url: 'url', json: async () => {
1985
+ throw "error";
1986
+ }
1987
+ });
1988
+ }).get('abc');
1989
+ }
1990
+ catch (err) {
1991
+ expect(err).toEqual({
1992
+ status: 401, message: 'text', url: 'url'
1993
+ });
1994
+ }
1995
+ });
1996
+ it("error3", async () => {
1997
+ try {
1998
+ await new RestDataProviderHttpProviderUsingFetch(async (url, info) => {
1999
+ return new mockResponse({ status: 401, statusText: 'text', url: 'url', json: async () => ({ message: 'message' }) });
2000
+ }).get('abc');
2001
+ }
2002
+ catch (err) {
2003
+ expect(err).toEqual({
2004
+ status: 401, url: 'url',
2005
+ message: 'message'
2006
+ });
2007
+ }
2008
+ });
2009
+ it("error2", async () => {
2010
+ try {
2011
+ await new RestDataProviderHttpProviderUsingFetch(async (url, info) => {
2012
+ throw Promise.resolve("123");
2013
+ }).get('abc');
2014
+ }
2015
+ catch (err) {
2016
+ expect(err).toEqual("123");
2017
+ }
2018
+ });
2019
+ it("post", async () => {
2020
+ let z = await new RestDataProviderHttpProviderUsingFetch(async (url, info) => {
2021
+ return new mockResponse({ status: 200, json: async () => 7 });
2022
+ }).post('abc', {});
2023
+ expect(z).toBe(7);
2024
+ });
2025
+ it("put", async () => {
2026
+ let z = await new RestDataProviderHttpProviderUsingFetch(async (url, info) => {
2027
+ return new mockResponse({ status: 200, json: async () => 7 });
2028
+ }).put('abc', {});
2029
+ expect(z).toBe(7);
2030
+ });
2031
+ it("delete", async () => {
2032
+ let z = await new RestDataProviderHttpProviderUsingFetch(async (url, info) => {
2033
+ expect(info.headers).toEqual({}); // fastify fails with content type and no body
2034
+ return new mockResponse({ status: 204, json: async () => 7 });
2035
+ }).delete('abc');
2036
+ expect(z).toBeUndefined();
2037
+ });
2038
+ it("rest doesn't support transactions", async () => {
2039
+ const r = new RestDataProvider(() => undefined);
2040
+ let ok = false;
2041
+ try {
2042
+ await r.transaction(async () => { });
2043
+ ok = true;
2044
+ }
2045
+ catch { }
2046
+ expect(ok).toBe(false);
2047
+ });
2048
+ it("json field works", async () => {
2049
+ const r = new Remult(new InMemoryDataProvider());
2050
+ var e = class {
2051
+ id;
2052
+ person;
2053
+ };
2054
+ describeClass(e, Entity("asdf"), {
2055
+ id: Fields.integer(),
2056
+ person: Fields.json({
2057
+ valueConverter: {
2058
+ toJson: x => x.name,
2059
+ fromJson: x => ({ name: x })
2060
+ }
2061
+ })
2062
+ });
2063
+ expect(r.repo(e).fields.person.valueConverter.toDb({ name: "noam" })).toBe("noam");
2064
+ });
2065
+ it("test repo consistent instance", () => {
2066
+ let x = remult.repo(Categories);
2067
+ let y = remult.repo(Categories);
2068
+ expect(x).toBe(y);
2069
+ });
2070
+ });
2071
+ class mockResponse {
2072
+ constructor(val) {
2073
+ Object.assign(this, val);
2074
+ }
2075
+ headers;
2076
+ ok;
2077
+ redirected;
2078
+ status;
2079
+ statusText;
2080
+ type;
2081
+ url;
2082
+ clone() {
2083
+ throw new Error("Method not implemented.");
2084
+ }
2085
+ body;
2086
+ bodyUsed;
2087
+ trailer;
2088
+ arrayBuffer() {
2089
+ throw new Error("Method not implemented.");
2090
+ }
2091
+ blob() {
2092
+ throw new Error("Method not implemented.");
2093
+ }
2094
+ formData() {
2095
+ throw new Error("Method not implemented.");
2096
+ }
2097
+ json() {
2098
+ throw new Error("Method not implemented.");
2099
+ }
2100
+ text() {
2101
+ throw new Error("Method not implemented.");
2102
+ }
2103
+ }