breeze-client 2.2.2 → 3.0.0

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 (299) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +83 -63
  3. package/adapters/abstract-data-service-adapter.d.ts +120 -0
  4. package/adapters/abstract-data-service-adapter.js +395 -0
  5. package/adapters/abstract-data-service-adapter.js.map +1 -0
  6. package/adapters/adapter-ajax-fetch.d.ts +12 -0
  7. package/adapters/adapter-ajax-fetch.js +13 -0
  8. package/adapters/adapter-ajax-fetch.js.map +1 -0
  9. package/{adapter-ajax-post → adapters}/adapter-ajax-post.d.ts +40 -36
  10. package/{fesm2022/breeze-client-adapter-ajax-post.mjs → adapters/adapter-ajax-post.js} +80 -82
  11. package/adapters/adapter-ajax-post.js.map +1 -0
  12. package/{adapter-ajax-fetch → adapters}/adapter-core.d.ts +4 -4
  13. package/{fesm2022/breeze-client-adapter-uri-builder-json.mjs → adapters/adapter-core.js} +48 -91
  14. package/adapters/adapter-core.js.map +1 -0
  15. package/adapters/adapter-data-service-webapi.d.ts +9 -0
  16. package/{fesm2022/breeze-client-adapter-data-service-webapi.mjs → adapters/adapter-data-service-webapi.js} +105 -107
  17. package/adapters/adapter-data-service-webapi.js.map +1 -0
  18. package/adapters/adapter-model-library-backing-store.d.ts +32 -0
  19. package/adapters/adapter-model-library-backing-store.js +321 -0
  20. package/adapters/adapter-model-library-backing-store.js.map +1 -0
  21. package/adapters/adapter-uri-builder-json.d.ts +11 -0
  22. package/adapters/adapter-uri-builder-json.js +40 -0
  23. package/adapters/adapter-uri-builder-json.js.map +1 -0
  24. package/adapters/http.d.ts +52 -0
  25. package/adapters/http.js +202 -0
  26. package/adapters/http.js.map +1 -0
  27. package/angular/adapter-angular-httpclient.d.ts +21 -0
  28. package/angular/adapter-angular-httpclient.js +70 -0
  29. package/angular/adapter-angular-httpclient.js.map +1 -0
  30. package/breeze.d.ts +215 -0
  31. package/breeze.js +141 -0
  32. package/breeze.js.map +1 -0
  33. package/config/config.d.ts +212 -0
  34. package/config/config.js +392 -0
  35. package/config/config.js.map +1 -0
  36. package/config/configure.d.ts +66 -0
  37. package/config/configure.js +46 -0
  38. package/config/configure.js.map +1 -0
  39. package/config/default-adapters.d.ts +1 -0
  40. package/config/default-adapters.js +40 -0
  41. package/config/default-adapters.js.map +1 -0
  42. package/config/interface-registry.d.ts +191 -0
  43. package/config/interface-registry.js +5 -0
  44. package/config/interface-registry.js.map +1 -0
  45. package/{src → core}/assert-param.d.ts +52 -60
  46. package/core/assert-param.js +390 -0
  47. package/core/assert-param.js.map +1 -0
  48. package/core/core.d.ts +285 -0
  49. package/core/core.js +772 -0
  50. package/core/core.js.map +1 -0
  51. package/core/enum.d.ts +116 -0
  52. package/core/enum.js +167 -0
  53. package/core/enum.js.map +1 -0
  54. package/core/event.d.ts +169 -0
  55. package/core/event.js +338 -0
  56. package/core/event.js.map +1 -0
  57. package/entity/array.d.ts +3 -0
  58. package/entity/array.js +4 -0
  59. package/entity/array.js.map +1 -0
  60. package/entity/complex-array.d.ts +17 -0
  61. package/entity/complex-array.js +104 -0
  62. package/entity/complex-array.js.map +1 -0
  63. package/entity/default-property-interceptor.d.ts +1 -0
  64. package/entity/default-property-interceptor.js +496 -0
  65. package/entity/default-property-interceptor.js.map +1 -0
  66. package/{src → entity}/entity-action.d.ts +36 -42
  67. package/entity/entity-action.js +45 -0
  68. package/entity/entity-action.js.map +1 -0
  69. package/entity/entity-aspect.d.ts +457 -0
  70. package/entity/entity-aspect.js +1262 -0
  71. package/entity/entity-aspect.js.map +1 -0
  72. package/entity/entity-base.d.ts +55 -0
  73. package/entity/entity-base.js +41 -0
  74. package/entity/entity-base.js.map +1 -0
  75. package/entity/entity-group.d.ts +1 -0
  76. package/entity/entity-group.js +224 -0
  77. package/entity/entity-group.js.map +1 -0
  78. package/entity/entity-key.d.ts +95 -0
  79. package/entity/entity-key.js +189 -0
  80. package/entity/entity-key.js.map +1 -0
  81. package/{src → entity}/entity-state.d.ts +112 -84
  82. package/entity/entity-state.js +135 -0
  83. package/entity/entity-state.js.map +1 -0
  84. package/entity/key-generator.d.ts +57 -0
  85. package/entity/key-generator.js +155 -0
  86. package/entity/key-generator.js.map +1 -0
  87. package/entity/observable-array.d.ts +25 -0
  88. package/entity/observable-array.js +230 -0
  89. package/entity/observable-array.js.map +1 -0
  90. package/entity/primitive-array.d.ts +12 -0
  91. package/entity/primitive-array.js +71 -0
  92. package/entity/primitive-array.js.map +1 -0
  93. package/entity/relation-array.d.ts +24 -0
  94. package/entity/relation-array.js +176 -0
  95. package/entity/relation-array.js.map +1 -0
  96. package/entity/unattached-children-map.d.ts +1 -0
  97. package/entity/unattached-children-map.js +105 -0
  98. package/entity/unattached-children-map.js.map +1 -0
  99. package/generate-entity-classes.js +1176 -0
  100. package/manager/entity-manager.d.ts +801 -0
  101. package/manager/entity-manager.js +2395 -0
  102. package/manager/entity-manager.js.map +1 -0
  103. package/{src → manager}/save-options.d.ts +48 -42
  104. package/manager/save-options.js +51 -0
  105. package/manager/save-options.js.map +1 -0
  106. package/{src → metadata}/data-service.d.ts +229 -184
  107. package/metadata/data-service.js +246 -0
  108. package/metadata/data-service.js.map +1 -0
  109. package/metadata/data-type.d.ts +122 -0
  110. package/metadata/data-type.js +465 -0
  111. package/metadata/data-type.js.map +1 -0
  112. package/metadata/entity-metadata.d.ts +1193 -0
  113. package/metadata/entity-metadata.js +2502 -0
  114. package/metadata/entity-metadata.js.map +1 -0
  115. package/{src → metadata}/local-query-comparison-options.d.ts +65 -59
  116. package/metadata/local-query-comparison-options.js +69 -0
  117. package/metadata/local-query-comparison-options.js.map +1 -0
  118. package/{src → metadata}/naming-convention.d.ts +75 -72
  119. package/metadata/naming-convention.js +97 -0
  120. package/metadata/naming-convention.js.map +1 -0
  121. package/mixins/mixin-get-entity-graph.d.ts +63 -0
  122. package/{fesm2022/breeze-client-mixin-get-entity-graph.mjs → mixins/mixin-get-entity-graph.js} +331 -253
  123. package/mixins/mixin-get-entity-graph.js.map +1 -0
  124. package/mixins/mixin-save-queuing.d.ts +98 -0
  125. package/{fesm2022/breeze-client-mixin-save-queuing.mjs → mixins/mixin-save-queuing.js} +493 -365
  126. package/mixins/mixin-save-queuing.js.map +1 -0
  127. package/package.json +63 -94
  128. package/query/entity-query.d.ts +521 -0
  129. package/query/entity-query.js +1149 -0
  130. package/query/entity-query.js.map +1 -0
  131. package/{src → query}/mapping-context.d.ts +44 -46
  132. package/query/mapping-context.js +412 -0
  133. package/query/mapping-context.js.map +1 -0
  134. package/query/predicate.d.ts +394 -0
  135. package/query/predicate.js +1294 -0
  136. package/query/predicate.js.map +1 -0
  137. package/query/property-path.d.ts +252 -0
  138. package/query/property-path.js +2 -0
  139. package/query/property-path.js.map +1 -0
  140. package/{src → query}/query-options.d.ts +143 -119
  141. package/query/query-options.js +180 -0
  142. package/query/query-options.js.map +1 -0
  143. package/rxjs/breeze-rxjs.d.ts +72 -0
  144. package/rxjs/breeze-rxjs.js +117 -0
  145. package/rxjs/breeze-rxjs.js.map +1 -0
  146. package/validation/validate.d.ts +583 -0
  147. package/validation/validate.js +961 -0
  148. package/validation/validate.js.map +1 -0
  149. package/{src → validation}/validation-options.d.ts +67 -63
  150. package/validation/validation-options.js +70 -0
  151. package/validation/validation-options.js.map +1 -0
  152. package/adapter-ajax-angularjs/adapter-ajax-angularjs.d.ts +0 -17
  153. package/adapter-ajax-angularjs/adapter-core.d.ts +0 -4
  154. package/adapter-ajax-angularjs/index.d.ts +0 -5
  155. package/adapter-ajax-fetch/adapter-ajax-fetch.d.ts +0 -18
  156. package/adapter-ajax-fetch/index.d.ts +0 -5
  157. package/adapter-ajax-httpclient/adapter-ajax-httpclient.d.ts +0 -13
  158. package/adapter-ajax-httpclient/adapter-core.d.ts +0 -4
  159. package/adapter-ajax-httpclient/index.d.ts +0 -5
  160. package/adapter-ajax-jquery/adapter-ajax-jquery.d.ts +0 -15
  161. package/adapter-ajax-jquery/index.d.ts +0 -5
  162. package/adapter-ajax-post/index.d.ts +0 -5
  163. package/adapter-data-service-odata/adapter-core.d.ts +0 -4
  164. package/adapter-data-service-odata/adapter-data-service-odata.d.ts +0 -17
  165. package/adapter-data-service-odata/index.d.ts +0 -5
  166. package/adapter-data-service-webapi/adapter-data-service-webapi.d.ts +0 -15
  167. package/adapter-data-service-webapi/index.d.ts +0 -5
  168. package/adapter-model-library-backing-store/adapter-model-library-backing-store.d.ts +0 -10
  169. package/adapter-model-library-backing-store/index.d.ts +0 -5
  170. package/adapter-model-library-ko/adapter-model-library-ko.d.ts +0 -10
  171. package/adapter-model-library-ko/index.d.ts +0 -5
  172. package/adapter-uri-builder-json/adapter-core.d.ts +0 -4
  173. package/adapter-uri-builder-json/adapter-uri-builder-json.d.ts +0 -8
  174. package/adapter-uri-builder-json/index.d.ts +0 -5
  175. package/adapter-uri-builder-odata/adapter-core.d.ts +0 -4
  176. package/adapter-uri-builder-odata/adapter-uri-builder-odata.d.ts +0 -8
  177. package/adapter-uri-builder-odata/index.d.ts +0 -5
  178. package/esm2022/adapter-ajax-angularjs/adapter-ajax-angularjs.mjs +0 -135
  179. package/esm2022/adapter-ajax-angularjs/adapter-core.mjs +0 -49
  180. package/esm2022/adapter-ajax-angularjs/breeze-client-adapter-ajax-angularjs.mjs +0 -5
  181. package/esm2022/adapter-ajax-fetch/adapter-ajax-fetch.mjs +0 -135
  182. package/esm2022/adapter-ajax-fetch/adapter-core.mjs +0 -49
  183. package/esm2022/adapter-ajax-fetch/breeze-client-adapter-ajax-fetch.mjs +0 -5
  184. package/esm2022/adapter-ajax-httpclient/adapter-ajax-httpclient.mjs +0 -139
  185. package/esm2022/adapter-ajax-httpclient/adapter-core.mjs +0 -49
  186. package/esm2022/adapter-ajax-httpclient/breeze-client-adapter-ajax-httpclient.mjs +0 -5
  187. package/esm2022/adapter-ajax-jquery/adapter-ajax-jquery.mjs +0 -107
  188. package/esm2022/adapter-ajax-jquery/breeze-client-adapter-ajax-jquery.mjs +0 -5
  189. package/esm2022/adapter-ajax-post/adapter-ajax-post.mjs +0 -77
  190. package/esm2022/adapter-ajax-post/breeze-client-adapter-ajax-post.mjs +0 -5
  191. package/esm2022/adapter-data-service-odata/adapter-core.mjs +0 -49
  192. package/esm2022/adapter-data-service-odata/adapter-data-service-odata.mjs +0 -461
  193. package/esm2022/adapter-data-service-odata/breeze-client-adapter-data-service-odata.mjs +0 -5
  194. package/esm2022/adapter-data-service-webapi/adapter-data-service-webapi.mjs +0 -100
  195. package/esm2022/adapter-data-service-webapi/breeze-client-adapter-data-service-webapi.mjs +0 -5
  196. package/esm2022/adapter-model-library-backing-store/adapter-model-library-backing-store.mjs +0 -269
  197. package/esm2022/adapter-model-library-backing-store/breeze-client-adapter-model-library-backing-store.mjs +0 -5
  198. package/esm2022/adapter-model-library-ko/adapter-model-library-ko.mjs +0 -241
  199. package/esm2022/adapter-model-library-ko/breeze-client-adapter-model-library-ko.mjs +0 -5
  200. package/esm2022/adapter-uri-builder-json/adapter-core.mjs +0 -49
  201. package/esm2022/adapter-uri-builder-json/adapter-uri-builder-json.mjs +0 -37
  202. package/esm2022/adapter-uri-builder-json/breeze-client-adapter-uri-builder-json.mjs +0 -5
  203. package/esm2022/adapter-uri-builder-odata/adapter-core.mjs +0 -49
  204. package/esm2022/adapter-uri-builder-odata/adapter-uri-builder-odata.mjs +0 -191
  205. package/esm2022/adapter-uri-builder-odata/breeze-client-adapter-uri-builder-odata.mjs +0 -5
  206. package/esm2022/breeze-client.mjs +0 -5
  207. package/esm2022/index.mjs +0 -2
  208. package/esm2022/mixin-get-entity-graph/breeze-client-mixin-get-entity-graph.mjs +0 -5
  209. package/esm2022/mixin-get-entity-graph/mixin-get-entity-graph.mjs +0 -269
  210. package/esm2022/mixin-save-queuing/breeze-client-mixin-save-queuing.mjs +0 -5
  211. package/esm2022/mixin-save-queuing/mixin-save-queuing.mjs +0 -421
  212. package/esm2022/src/abstract-data-service-adapter.mjs +0 -325
  213. package/esm2022/src/array.mjs +0 -4
  214. package/esm2022/src/assert-param.mjs +0 -330
  215. package/esm2022/src/breeze.mjs +0 -85
  216. package/esm2022/src/complex-array.mjs +0 -117
  217. package/esm2022/src/config.mjs +0 -232
  218. package/esm2022/src/core.mjs +0 -712
  219. package/esm2022/src/csdl-metadata-parser.mjs +0 -385
  220. package/esm2022/src/data-service.mjs +0 -221
  221. package/esm2022/src/data-type.mjs +0 -510
  222. package/esm2022/src/default-property-interceptor.mjs +0 -460
  223. package/esm2022/src/entity-action.mjs +0 -45
  224. package/esm2022/src/entity-aspect.mjs +0 -897
  225. package/esm2022/src/entity-group.mjs +0 -192
  226. package/esm2022/src/entity-key.mjs +0 -125
  227. package/esm2022/src/entity-manager.mjs +0 -2163
  228. package/esm2022/src/entity-metadata.mjs +0 -2242
  229. package/esm2022/src/entity-query.mjs +0 -1024
  230. package/esm2022/src/entity-state.mjs +0 -107
  231. package/esm2022/src/enum.mjs +0 -143
  232. package/esm2022/src/event.mjs +0 -264
  233. package/esm2022/src/interface-registry.mjs +0 -39
  234. package/esm2022/src/key-generator.mjs +0 -110
  235. package/esm2022/src/local-query-comparison-options.mjs +0 -65
  236. package/esm2022/src/mapping-context.mjs +0 -411
  237. package/esm2022/src/naming-convention.mjs +0 -92
  238. package/esm2022/src/observable-array.mjs +0 -183
  239. package/esm2022/src/predicate.mjs +0 -1259
  240. package/esm2022/src/primitive-array.mjs +0 -85
  241. package/esm2022/src/query-options.mjs +0 -152
  242. package/esm2022/src/relation-array.mjs +0 -173
  243. package/esm2022/src/save-options.mjs +0 -41
  244. package/esm2022/src/unattached-children-map.mjs +0 -56
  245. package/esm2022/src/validate.mjs +0 -995
  246. package/esm2022/src/validation-options.mjs +0 -64
  247. package/fesm2022/breeze-client-adapter-ajax-angularjs.mjs +0 -190
  248. package/fesm2022/breeze-client-adapter-ajax-angularjs.mjs.map +0 -1
  249. package/fesm2022/breeze-client-adapter-ajax-fetch.mjs +0 -190
  250. package/fesm2022/breeze-client-adapter-ajax-fetch.mjs.map +0 -1
  251. package/fesm2022/breeze-client-adapter-ajax-httpclient.mjs +0 -194
  252. package/fesm2022/breeze-client-adapter-ajax-httpclient.mjs.map +0 -1
  253. package/fesm2022/breeze-client-adapter-ajax-jquery.mjs +0 -114
  254. package/fesm2022/breeze-client-adapter-ajax-jquery.mjs.map +0 -1
  255. package/fesm2022/breeze-client-adapter-ajax-post.mjs.map +0 -1
  256. package/fesm2022/breeze-client-adapter-data-service-odata.mjs +0 -516
  257. package/fesm2022/breeze-client-adapter-data-service-odata.mjs.map +0 -1
  258. package/fesm2022/breeze-client-adapter-data-service-webapi.mjs.map +0 -1
  259. package/fesm2022/breeze-client-adapter-model-library-backing-store.mjs +0 -276
  260. package/fesm2022/breeze-client-adapter-model-library-backing-store.mjs.map +0 -1
  261. package/fesm2022/breeze-client-adapter-model-library-ko.mjs +0 -248
  262. package/fesm2022/breeze-client-adapter-model-library-ko.mjs.map +0 -1
  263. package/fesm2022/breeze-client-adapter-uri-builder-json.mjs.map +0 -1
  264. package/fesm2022/breeze-client-adapter-uri-builder-odata.mjs +0 -246
  265. package/fesm2022/breeze-client-adapter-uri-builder-odata.mjs.map +0 -1
  266. package/fesm2022/breeze-client-mixin-get-entity-graph.mjs.map +0 -1
  267. package/fesm2022/breeze-client-mixin-save-queuing.mjs.map +0 -1
  268. package/fesm2022/breeze-client.mjs +0 -14144
  269. package/fesm2022/breeze-client.mjs.map +0 -1
  270. package/index.d.ts +0 -1
  271. package/mixin-get-entity-graph/index.d.ts +0 -5
  272. package/mixin-get-entity-graph/mixin-get-entity-graph.d.ts +0 -31
  273. package/mixin-save-queuing/index.d.ts +0 -5
  274. package/mixin-save-queuing/mixin-save-queuing.d.ts +0 -32
  275. package/src/abstract-data-service-adapter.d.ts +0 -84
  276. package/src/array.d.ts +0 -3
  277. package/src/breeze.d.ts +0 -139
  278. package/src/complex-array.d.ts +0 -13
  279. package/src/config.d.ts +0 -104
  280. package/src/core.d.ts +0 -164
  281. package/src/csdl-metadata-parser.d.ts +0 -7
  282. package/src/data-type.d.ts +0 -89
  283. package/src/default-property-interceptor.d.ts +0 -4
  284. package/src/entity-aspect.d.ts +0 -332
  285. package/src/entity-group.d.ts +0 -28
  286. package/src/entity-key.d.ts +0 -77
  287. package/src/entity-manager.d.ts +0 -680
  288. package/src/entity-metadata.d.ts +0 -988
  289. package/src/entity-query.d.ts +0 -444
  290. package/src/enum.d.ts +0 -100
  291. package/src/event.d.ts +0 -142
  292. package/src/interface-registry.d.ts +0 -150
  293. package/src/key-generator.d.ts +0 -12
  294. package/src/observable-array.d.ts +0 -52
  295. package/src/predicate.d.ts +0 -376
  296. package/src/primitive-array.d.ts +0 -7
  297. package/src/relation-array.d.ts +0 -18
  298. package/src/unattached-children-map.d.ts +0 -19
  299. package/src/validate.d.ts +0 -650
@@ -1,367 +1,495 @@
1
- import { EntityState, breeze } from 'breeze-client';
2
-
3
- //#region Copyright, Version, and Description
4
- function enableSaveQueuing(em, enable = true) {
5
- let saveQueuing = em['_saveQueueing'] ||
6
- (em['_saveQueuing'] = new SaveQueuing(em));
7
- enable = (enable === undefined) ? true : enable;
8
- saveQueuing._isEnabled = enable;
9
- if (enable) {
10
- // delegate to save changes queuing
11
- em.saveChanges = saveChangesWithQueuing;
12
- }
13
- else {
14
- // revert to the native EntityManager.saveChanges
15
- em.saveChanges = em['_saveQueuing'].baseSaveChanges;
16
- }
17
- }
18
- /**
19
- * Replacement for EntityManager.saveChanges
20
- * This version queues saveChanges calls while a real save is in progress
21
- **/
22
- function saveChangesWithQueuing(entities, saveOptions) {
23
- try {
24
- // `this` is an EntityManager
25
- let saveQueuing = this._saveQueuing;
26
- if (saveQueuing.isSaving) {
27
- // save in progress; queue the save for later
28
- return saveQueuing.queueSaveChanges(entities);
29
- }
30
- else {
31
- // note that save is in progress; then save
32
- saveQueuing.isSaving = true;
33
- saveQueuing.saveOptions = saveOptions;
34
- return saveQueuing.saveChanges(entities, saveOptions);
35
- }
36
- }
37
- catch (err) {
38
- return Promise.reject(err);
39
- }
40
- }
41
- ///////// SaveQueuing /////////
42
- class SaveQueuing {
43
- entityManager;
44
- baseSaveChanges;
45
- isSaving;
46
- _isEnabled;
47
- activeSaveDeferred;
48
- nextSaveDeferred;
49
- activeSaveMemo;
50
- nextSaveMemo;
51
- saveOptions;
52
- constructor(entityManager) {
53
- this.entityManager = entityManager;
54
- this.baseSaveChanges = entityManager.saveChanges;
55
- this.isSaving = false;
56
- }
57
- isEnabled() {
58
- return this._isEnabled;
59
- }
60
- getSavedNothingResult() {
61
- return { entities: [], keyMappings: [] };
62
- }
63
- queueSaveChanges(entities) {
64
- let self = this; // `this` is a SaveQueuing
65
- let em = self.entityManager;
66
- let changes = entities || em.getChanges();
67
- if (changes.length === 0) {
68
- return Promise.resolve(this.getSavedNothingResult());
69
- }
70
- let valError = em.saveChangesValidateOnClient(changes);
71
- if (valError) {
72
- return Promise.reject(valError);
73
- }
74
- let saveMemo = self.nextSaveMemo || (self.nextSaveMemo = new SaveMemo());
75
- memoizeChanges();
76
- let deferred = self.nextSaveDeferred || (self.nextSaveDeferred = new Deferred());
77
- return deferred.promise;
78
- function memoizeChanges() {
79
- if (changes.length === 0) {
80
- return;
81
- }
82
- let queuedChanges = saveMemo.queuedChanges;
83
- changes.forEach(e => {
84
- if (!e.entityAspect.isBeingSaved && queuedChanges.indexOf(e) === -1) {
85
- queuedChanges.push(e);
86
- }
87
- });
88
- saveMemo.updateEntityMemos(changes);
89
- }
90
- }
91
- saveChanges(entities, saveOptions) {
92
- let self = this; // `this` is a SaveQueuing
93
- let promise = self.baseSaveChanges.call(self.entityManager, entities, saveOptions || self.saveOptions)
94
- .then(function (saveResult) { return self.saveSucceeded(saveResult); })
95
- .then(null, function (error) { console.log(error); return self.saveFailed(error); });
96
- rememberAddedOriginalValues(entities); // do it after ... so don't send OrigValues to the server
97
- return promise;
98
- function rememberAddedOriginalValues(entities) {
99
- // added entities normally don't have original values but these will now
100
- let added = entities ?
101
- entities.filter(function (e) { return e.entityAspect.entityState.isAdded(); }) :
102
- self.entityManager.getEntities(null, EntityState.Added);
103
- added.forEach(entity => {
104
- let props = entity.entityType.dataProperties;
105
- let originalValues = entity.entityAspect.originalValues;
106
- props.forEach(dp => {
107
- if (dp.isPartOfKey) {
108
- return;
109
- }
110
- originalValues[dp.name] = entity.getProperty(dp.name);
111
- });
112
- });
113
- }
114
- }
115
- saveSucceeded(saveResult) {
116
- let self = this; // `this` is a SaveQueueing
117
- let activeSaveDeferred = self.activeSaveDeferred;
118
- let nextSaveDeferred = self.nextSaveDeferred;
119
- let nextSaveMemo = self.nextSaveMemo;
120
- // prepare as if nothing queued or left to save
121
- self.isSaving = false;
122
- self.activeSaveDeferred = null;
123
- self.activeSaveMemo = null;
124
- self.nextSaveDeferred = null;
125
- self.nextSaveMemo = null;
126
- if (nextSaveMemo) {
127
- // a save was queued since last save returned
128
- nextSaveMemo.pkFixup(saveResult.keyMappings);
129
- nextSaveMemo.applyToSavedEntities(self.entityManager, saveResult.entities);
130
- // remove detached entities from queuedChanges
131
- let queuedChanges = nextSaveMemo.queuedChanges.filter(e => {
132
- return !e.entityAspect.entityState.isDetached();
133
- });
134
- if (queuedChanges.length > 0) {
135
- // save again
136
- self.isSaving = true;
137
- // remember the queued changes that triggered this save
138
- self.activeSaveDeferred = nextSaveDeferred;
139
- self.activeSaveMemo = nextSaveMemo;
140
- self.saveChanges(queuedChanges, this.saveOptions);
141
- }
142
- else if (nextSaveDeferred) {
143
- nextSaveDeferred.resolve(this.getSavedNothingResult());
144
- }
145
- }
146
- if (activeSaveDeferred) {
147
- activeSaveDeferred.resolve(saveResult);
148
- }
149
- return saveResult; // for the current promise chain
150
- }
151
- saveFailed(error) {
152
- let self = this; // `this` is a SaveQueueing
153
- error = new QueuedSaveFailedError(error, self);
154
- let activeSaveDeferred = self.activeSaveDeferred;
155
- let nextSaveDeferred = self.nextSaveDeferred;
156
- self.isSaving = false;
157
- self.activeSaveDeferred = null;
158
- self.activeSaveMemo = null;
159
- self.nextSaveDeferred = null;
160
- self.nextSaveMemo = null;
161
- if (activeSaveDeferred) {
162
- activeSaveDeferred.reject(error);
163
- }
164
- if (nextSaveDeferred) {
165
- nextSaveDeferred.reject(error);
166
- }
167
- return Promise.reject(error); // let promise chain hear error
168
- }
169
- }
170
- /// for backward compat with older Promise implementation
171
- class Deferred {
172
- resolve;
173
- reject;
174
- promise;
175
- constructor() {
176
- this.promise = new Promise(function (resolve, reject) {
177
- this.resolve = resolve;
178
- this.reject = reject;
179
- }.bind(this));
180
- }
181
- }
182
- ////////// QueuedSaveFailedError /////////
183
- // Error sub-class thrown when rejecting queued saves.
184
- class QueuedSaveFailedError extends Error {
185
- name = "QueuedSaveFailedError";
186
- innerError;
187
- message;
188
- failedSaveMemo;
189
- nextSaveMemo;
190
- // Error sub-class thrown when rejecting queued saves.
191
- // `innerError` is the actual save error
192
- // `failedSaveMemo` is the saveMemo that prompted this save
193
- // `nextSaveMemo` holds queued changes accumulated since that save.
194
- // You may try to recover using this info. Good luck with that.
195
- constructor(errObject, saveQueuing) {
196
- super();
197
- this.innerError = errObject;
198
- this.message = "Queued save failed: " + errObject.message;
199
- this.failedSaveMemo = saveQueuing.activeSaveMemo;
200
- this.nextSaveMemo = saveQueuing.nextSaveMemo;
201
- }
202
- }
203
- ////////// SaveMemo ////////////////
204
- // SaveMemo is a record of changes for a queued save, consisting of:
205
- // entityMemos: info about entities that are being saved and
206
- // have been changed since the save started
207
- // queuedChanges: entities that are queued for save but
208
- // are not currently being saved
209
- class SaveMemo {
210
- entityMemos;
211
- queuedChanges;
212
- constructor() {
213
- this.entityMemos = {};
214
- this.queuedChanges = [];
215
- }
216
- applyToSavedEntities(entityManager, savedEntities) {
217
- let entityMemos = this.entityMemos; // `this` is a SaveMemo
218
- let queuedChanges = this.queuedChanges;
219
- let restorePublishing = this.disableManagerPublishing(entityManager);
220
- try {
221
- savedEntities.forEach(saved => {
222
- let key = this.makeEntityMemoKey(saved);
223
- let entityMemo = entityMemos[key];
224
- let resave = entityMemo && entityMemo.applyToSavedEntity(saved);
225
- if (resave) {
226
- queuedChanges.push(saved);
227
- }
228
- });
229
- }
230
- finally {
231
- restorePublishing();
232
- // D#2651 hasChanges will be wrong if changes made while save in progress
233
- let hasChanges = queuedChanges.length > 0;
234
- // Must use breeze internal method to properly set this flag true
235
- if (hasChanges) {
236
- entityManager._setHasChanges(true);
237
- }
238
- }
239
- }
240
- disableManagerPublishing(manager) {
241
- let Event = breeze.Event;
242
- Event.enable('entityChanged', manager, false);
243
- Event.enable('hasChangesChanged', manager, false);
244
- return function restorePublishing() {
245
- Event.enable('entityChanged', manager, true);
246
- Event.enable('hasChangesChanged', manager, true);
247
- };
248
- }
249
- pkFixup(keyMappings) {
250
- let entityMemos = this.entityMemos; // `this` is a SaveMemo
251
- keyMappings.forEach(km => {
252
- let type = km.entityTypeName;
253
- let tempKey = type + '|' + km.tempValue;
254
- if (entityMemos[tempKey]) {
255
- entityMemos[type + '|' + km.realValue] = entityMemos[tempKey];
256
- delete entityMemos[tempKey];
257
- }
258
- for (let memoKey in entityMemos) {
259
- entityMemos[memoKey].fkFixup(km);
260
- }
261
- });
262
- }
263
- makeEntityMemoKey(entity) {
264
- let entityKey = entity.entityAspect.getKey();
265
- return entityKey.entityType.name + '|' + entityKey.values;
266
- }
267
- updateEntityMemos(changes) {
268
- let entityMemos = this.entityMemos; // `this` is a SaveMemo
269
- changes.forEach(change => {
270
- // only update entityMemo for entity being save
271
- if (!change.entityAspect.isBeingSaved) {
272
- return;
273
- }
274
- let key = this.makeEntityMemoKey(change);
275
- let entityMemo = entityMemos[key] || (entityMemos[key] = new EntityMemo(change));
276
- entityMemo.update();
277
- });
278
- }
279
- }
280
- ///////// EntityMemo Type ///////////////
281
- // Information about an entity that is being saved
282
- // and which has been changed since that save started
283
- class EntityMemo {
284
- entity;
285
- pendingChanges;
286
- isDeleted;
287
- constructor(entity) {
288
- this.entity = entity;
289
- this.pendingChanges = {};
290
- }
291
- applyToSavedEntity(saved) {
292
- let entityMemo = this;
293
- let aspect = saved.entityAspect;
294
- if (aspect.entityState.isDetached()) {
295
- return false;
296
- }
297
- else if (entityMemo.isDeleted) {
298
- aspect.setDeleted();
299
- return true;
300
- }
301
- // treat entity with pending changes as modified
302
- let props = Object.keys(entityMemo.pendingChanges);
303
- if (props.length === 0) {
304
- return false;
305
- }
306
- let originalValues = aspect.originalValues;
307
- props.forEach(name => {
308
- originalValues[name] = saved.getProperty(name);
309
- saved.setProperty(name, entityMemo.pendingChanges[name]);
310
- });
311
- aspect.setModified();
312
- return true;
313
- }
314
- fkFixup(keyMapping) {
315
- let entityMemo = this;
316
- let type = entityMemo.entity.entityType;
317
- let fkProps = type.foreignKeyProperties;
318
- fkProps.forEach(fkProp => {
319
- if (fkProp.parentType.name === keyMapping.entityTypeName &&
320
- entityMemo.pendingChanges[fkProp.name] === keyMapping.tempValue) {
321
- entityMemo.pendingChanges[fkProp.name] = keyMapping.realValue;
322
- }
323
- });
324
- }
325
- // update the entityMemo of changes to an entity being saved
326
- // so that we know how to save it again later
327
- update() {
328
- let entityMemo = this;
329
- let props;
330
- let entity = entityMemo.entity;
331
- let aspect = entity.entityAspect;
332
- let stateName = aspect.entityState.name;
333
- switch (stateName) {
334
- case 'Added':
335
- let originalValues = aspect.originalValues;
336
- props = entity.entityType.dataProperties;
337
- props.forEach(dp => {
338
- if (dp.isPartOfKey) {
339
- return;
340
- }
341
- let name = dp.name;
342
- let value = entity.getProperty(name);
343
- if (originalValues[name] !== value) {
344
- entityMemo.pendingChanges[name] = value;
345
- }
346
- });
347
- break;
348
- case 'Deleted':
349
- entityMemo.isDeleted = true;
350
- entityMemo.pendingChanges = {};
351
- break;
352
- case 'Modified':
353
- props = Object.keys(aspect.originalValues);
354
- props.forEach(name => {
355
- entityMemo.pendingChanges[name] = entity.getProperty(name);
356
- });
357
- break;
358
- }
359
- }
1
+ //#region Copyright, Version, and Description
2
+ /*
3
+ * Copyright 2015-2026 IdeaBlade, Inc. All Rights Reserved.
4
+ * Use, reproduction, distribution, and modification of this code is subject to the terms and
5
+ * conditions of the IdeaBlade Breeze license, available at http://www.breezejs.com/license
6
+ *
7
+ * Author: Ward Bell
8
+ * Version: 2.0.6 Steve Schmitt - convert to TypeScript, move to breeze-client repo, change enableSaveQueuing function
9
+ * Version: 2.0.5 Ward Bell
10
+ * --------------------------------------------------------------------------------
11
+ * Adds "Save Queuing" capability to new EntityManagers
12
+ *
13
+ * Save Queuing automatically queues and defers an EntityManager.saveChanges call
14
+ * when another save is in progress for that manager and the server has not yet responded.
15
+ * This feature is helpful when your app needs to allow rapid, continuous changes
16
+ * to entities that may be in the process of being saved.
17
+ *
18
+ * Without "Save Queuing", an EntityManager will throw an exception
19
+ * when you call saveChanges for an entity which is currently being saved.
20
+ *
21
+ * !!! Use with caution !!!
22
+ * It is usually better to disable user input while a save is in progress.
23
+ * Save Queuing may be appropriate for simple "auto-save" scenarios
24
+ * when the save latency is "short" (under a few seconds).
25
+ *
26
+ * Save Queuing is NOT intended for occassionally disconnected or offline scenarios.
27
+ *
28
+ * Save Queuing is experimental. It will not become a part of BreezeJS core
29
+ * but might become an official Breeze plugin in future
30
+ * although not necessarily in this form or with this API
31
+ *
32
+ * Must call EntityManager.enableSaveQueuing(true) to turn it on;
33
+ * EntityManager.enableSaveQueuing(false) restores the manager's original
34
+ * saveChanges method as it was at the time saveQueuing was first enabled.
35
+ *
36
+ * This module adds "enableSaveQueuing" to the EntityManager prototype.
37
+ * Calling "enableSaveQueuing(true)" adds a new _saveQueuing object
38
+ * to the manager instance.
39
+ *
40
+ * See DocCode:saveQueuingTests.js
41
+ * https://github.com/Breeze/breeze.js.samples/blob/master/net/DocCode/DocCode/tests/saveQueuingTests.js
42
+ *
43
+ * LIMITATIONS
44
+ * - Can't handle changes to the primary key (dangerous in any case)
45
+ * - Assumes promises. Does not support the (deprecated) success and fail callbacks
46
+ * - Does not queue saveOptions. The first one is re-used for all queued saves.
47
+ * - Does not deal with export/import of entities while save is inflight
48
+ * - Does not deal with rejectChanges while save is in flight
49
+ * - Does not support parallel saves even when the change-sets are independent.
50
+ * The native saveChanges allows such saves.
51
+ * SaveQueuing does not; too complex and doesn't fit the primary scenario anyway.
52
+ * - The resolved saveResult is the saveResult of the last completed save
53
+ * - A queued save that might have succeeded if saved immediately
54
+ * may fail because the server no longer accepts it later
55
+ * - Prior to Breeze v.1.5.3, a queued save that might have succeeded
56
+ * if saved immediately will fail if subsequently attempt to save
57
+ * an invalid entity. Can detect and circumvent after v.1.5.3.
58
+ *
59
+ * All members of EntityManager._saveQueuing are internal;
60
+ * touch them at your own risk.
61
+ */
62
+ //#endregion
63
+ import { EntityState, BreezeEvent } from '../breeze.js';
64
+ /**
65
+ * Turns save queuing on or off for one {@link EntityManager}.
66
+ *
67
+ * With it on, a `saveChanges` call made while another save is still in flight is held back
68
+ * rather than rejected, and sent as a single follow-up save when the first one returns. Each
69
+ * promise resolves with the result of the save that carried its changes.
70
+ *
71
+ * It also keeps edits made *during* a save. Without queuing those are overwritten by the
72
+ * server's values when the save result merges back, leaving the entity `Unchanged` and
73
+ * `hasChanges()` false - so nothing tells the application that a change was lost. A foreign key
74
+ * set during a save is carried over too: if the parent's row is still being inserted, the queued
75
+ * save substitutes the key the server assigned for the temporary one.
76
+ *
77
+ * Intended for short-latency auto-save. It is not an offline story, it reuses the first save's
78
+ * {@link SaveOptions}, and it does not cope with `rejectChanges`, export/import or primary-key
79
+ * changes while a save is in flight. Disabling user input for the duration of a save is usually
80
+ * the better answer; this is for applications that cannot.
81
+ *
82
+ * @param em - The manager to wrap. Its `saveChanges` is replaced, and restored when disabled.
83
+ * @param enable - `false` puts the manager's own `saveChanges` back. Calling this more than
84
+ * once on the same manager, in either direction, is harmless.
85
+ *
86
+ * @example
87
+ * ```ts
88
+ * import { enableSaveQueuing } from 'breeze-client/mixin-save-queuing';
89
+ *
90
+ * enableSaveQueuing(em, true);
91
+ *
92
+ * const first = em.saveChanges(); // sent now
93
+ * order.shipName = 'changed'; // typed while that save is out
94
+ * const second = em.saveChanges(); // queued, and sent when the first returns
95
+ * ```
96
+ *
97
+ * @see {@link QueuedSaveFailedError}, which every pending promise rejects with if a queued
98
+ * save fails.
99
+ */
100
+ export function enableSaveQueuing(em, enable = true) {
101
+ const emx = em;
102
+ let saveQueuing = emx['_saveQueuing'] ||
103
+ (emx['_saveQueuing'] = new SaveQueuing(em));
104
+ enable = (enable === undefined) ? true : enable;
105
+ saveQueuing._isEnabled = enable;
106
+ if (enable) {
107
+ // delegate to save changes queuing
108
+ em.saveChanges = saveChangesWithQueuing;
109
+ }
110
+ else {
111
+ // revert to the native EntityManager.saveChanges
112
+ em.saveChanges = emx['_saveQueuing'].baseSaveChanges;
113
+ }
360
114
  }
361
-
362
- /**
363
- * Generated bundle index. Do not edit.
115
+ /**
116
+ * Replacement for EntityManager.saveChanges
117
+ * This version queues saveChanges calls while a real save is in progress
364
118
  */
365
-
366
- export { QueuedSaveFailedError, enableSaveQueuing };
367
- //# sourceMappingURL=breeze-client-mixin-save-queuing.mjs.map
119
+ function saveChangesWithQueuing(entities, saveOptions) {
120
+ try {
121
+ // `this` is an EntityManager
122
+ let saveQueuing = this._saveQueuing;
123
+ if (saveQueuing.isSaving) {
124
+ // save in progress; queue the save for later
125
+ return saveQueuing.queueSaveChanges(entities);
126
+ }
127
+ else {
128
+ // note that save is in progress; then save
129
+ saveQueuing.isSaving = true;
130
+ saveQueuing.saveOptions = saveOptions;
131
+ return saveQueuing.saveChanges(entities, saveOptions);
132
+ }
133
+ }
134
+ catch (err) {
135
+ return Promise.reject(err);
136
+ }
137
+ }
138
+ ///////// SaveQueuing /////////
139
+ class SaveQueuing {
140
+ entityManager;
141
+ baseSaveChanges;
142
+ isSaving;
143
+ _isEnabled;
144
+ // null means 'nothing active / nothing queued'; these are reset to null between saves
145
+ activeSaveDeferred;
146
+ nextSaveDeferred;
147
+ activeSaveMemo;
148
+ nextSaveMemo;
149
+ saveOptions;
150
+ constructor(entityManager) {
151
+ this.entityManager = entityManager;
152
+ this.baseSaveChanges = entityManager.saveChanges;
153
+ this.isSaving = false;
154
+ }
155
+ isEnabled() {
156
+ return this._isEnabled;
157
+ }
158
+ getSavedNothingResult() {
159
+ return { entities: [], keyMappings: [] };
160
+ }
161
+ queueSaveChanges(entities) {
162
+ let self = this; // `this` is a SaveQueuing
163
+ let em = self.entityManager;
164
+ let changes = entities || em.getChanges();
165
+ if (changes.length === 0) {
166
+ return Promise.resolve(this.getSavedNothingResult());
167
+ }
168
+ let valError = em.saveChangesValidateOnClient(changes);
169
+ if (valError) {
170
+ return Promise.reject(valError);
171
+ }
172
+ let saveMemo = self.nextSaveMemo || (self.nextSaveMemo = new SaveMemo());
173
+ memoizeChanges();
174
+ let deferred = self.nextSaveDeferred || (self.nextSaveDeferred = new Deferred());
175
+ return deferred.promise;
176
+ function memoizeChanges() {
177
+ if (changes.length === 0) {
178
+ return;
179
+ }
180
+ let queuedChanges = saveMemo.queuedChanges;
181
+ changes.forEach(e => {
182
+ if (!e.entityAspect.isBeingSaved) {
183
+ queuedChanges.add(e);
184
+ }
185
+ });
186
+ saveMemo.updateEntityMemos(changes);
187
+ }
188
+ }
189
+ saveChanges(entities, saveOptions) {
190
+ let self = this; // `this` is a SaveQueuing
191
+ let promise = self.baseSaveChanges.call(self.entityManager, entities, saveOptions || self.saveOptions)
192
+ .then(function (saveResult) { return self.saveSucceeded(saveResult); })
193
+ .then(null, function (error) { console.log(error); return self.saveFailed(error); });
194
+ rememberAddedOriginalValues(entities); // do it after ... so don't send OrigValues to the server
195
+ return promise;
196
+ function rememberAddedOriginalValues(entities) {
197
+ // added entities normally don't have original values but these will now
198
+ let added = entities ?
199
+ entities.filter(function (e) { return e.entityAspect.entityState.isAdded(); }) :
200
+ self.entityManager.getEntities(undefined, EntityState.Added);
201
+ added.forEach(entity => {
202
+ let props = entity.entityType.dataProperties;
203
+ let originalValues = entity.entityAspect.originalValues;
204
+ props.forEach(dp => {
205
+ if (dp.isPartOfKey) {
206
+ return;
207
+ }
208
+ originalValues[dp.name] = entity.getProperty(dp.name);
209
+ });
210
+ });
211
+ }
212
+ }
213
+ saveSucceeded(saveResult) {
214
+ let self = this; // `this` is a SaveQueueing
215
+ let activeSaveDeferred = self.activeSaveDeferred;
216
+ let nextSaveDeferred = self.nextSaveDeferred;
217
+ let nextSaveMemo = self.nextSaveMemo;
218
+ // prepare as if nothing queued or left to save
219
+ self.isSaving = false;
220
+ self.activeSaveDeferred = null;
221
+ self.activeSaveMemo = null;
222
+ self.nextSaveDeferred = null;
223
+ self.nextSaveMemo = null;
224
+ if (nextSaveMemo) {
225
+ // a save was queued since last save returned
226
+ nextSaveMemo.pkFixup(saveResult.keyMappings);
227
+ nextSaveMemo.applyToSavedEntities(self.entityManager, saveResult.entities);
228
+ // remove detached entities from queuedChanges
229
+ let queuedChanges = Array.from(nextSaveMemo.queuedChanges).filter(e => {
230
+ return !e.entityAspect.entityState.isDetached();
231
+ });
232
+ if (queuedChanges.length > 0) {
233
+ // save again
234
+ self.isSaving = true;
235
+ // remember the queued changes that triggered this save
236
+ self.activeSaveDeferred = nextSaveDeferred;
237
+ self.activeSaveMemo = nextSaveMemo;
238
+ self.saveChanges(queuedChanges, this.saveOptions);
239
+ }
240
+ else if (nextSaveDeferred) {
241
+ nextSaveDeferred.resolve(this.getSavedNothingResult());
242
+ }
243
+ }
244
+ if (activeSaveDeferred) {
245
+ activeSaveDeferred.resolve(saveResult);
246
+ }
247
+ return saveResult; // for the current promise chain
248
+ }
249
+ saveFailed(error) {
250
+ let self = this; // `this` is a SaveQueueing
251
+ error = new QueuedSaveFailedError(error, self);
252
+ let activeSaveDeferred = self.activeSaveDeferred;
253
+ let nextSaveDeferred = self.nextSaveDeferred;
254
+ self.isSaving = false;
255
+ self.activeSaveDeferred = null;
256
+ self.activeSaveMemo = null;
257
+ self.nextSaveDeferred = null;
258
+ self.nextSaveMemo = null;
259
+ if (activeSaveDeferred) {
260
+ activeSaveDeferred.reject(error);
261
+ }
262
+ if (nextSaveDeferred) {
263
+ nextSaveDeferred.reject(error);
264
+ }
265
+ return Promise.reject(error); // let promise chain hear error
266
+ }
267
+ }
268
+ /// for backward compat with older Promise implementation
269
+ class Deferred {
270
+ resolve;
271
+ reject;
272
+ promise;
273
+ constructor() {
274
+ this.promise = new Promise(function (resolve, reject) {
275
+ this.resolve = resolve;
276
+ this.reject = reject;
277
+ }.bind(this));
278
+ }
279
+ }
280
+ /**
281
+ * What every pending promise rejects with when a queued save fails.
282
+ *
283
+ * One failure rejects the whole queue, because the saves behind it were built on the assumption
284
+ * that the one in front succeeded. Read {@link QueuedSaveFailedError.innerError} for what
285
+ * actually went wrong; the two memos are there for an application that wants to attempt a
286
+ * recovery, and are the mixin's internal bookkeeping rather than a documented shape.
287
+ *
288
+ * @example
289
+ * ```ts
290
+ * try {
291
+ * await em.saveChanges();
292
+ * } catch (e) {
293
+ * if (e instanceof QueuedSaveFailedError) {
294
+ * console.error(e.innerError);
295
+ * }
296
+ * }
297
+ * ```
298
+ */
299
+ export class QueuedSaveFailedError extends Error {
300
+ /** Always `"QueuedSaveFailedError"`, so the error can be recognized by name as well as with
301
+ `instanceof`. */
302
+ name = "QueuedSaveFailedError";
303
+ /** The error the underlying save actually failed with. */
304
+ innerError;
305
+ /** `"Queued save failed: "` followed by {@link QueuedSaveFailedError.innerError}'s message. */
306
+ message;
307
+ /** The changes that were in the save that failed. */
308
+ failedSaveMemo;
309
+ /** The changes queued up behind it, which were never sent. */
310
+ nextSaveMemo;
311
+ /** Created by save queuing when a queued save fails; applications receive it rather than
312
+ create it. `errObject` is the error the save failed with. */
313
+ constructor(errObject, saveQueuing) {
314
+ super();
315
+ this.innerError = errObject;
316
+ this.message = "Queued save failed: " + errObject.message;
317
+ this.failedSaveMemo = saveQueuing.activeSaveMemo;
318
+ this.nextSaveMemo = saveQueuing.nextSaveMemo;
319
+ }
320
+ }
321
+ ////////// SaveMemo ////////////////
322
+ // SaveMemo is a record of changes for a queued save, consisting of:
323
+ // entityMemos: info about entities that are being saved and
324
+ // have been changed since the save started
325
+ // queuedChanges: entities that are queued for save but
326
+ // are not currently being saved
327
+ class SaveMemo {
328
+ /** Keyed by 'entityTypeName|keyValues'. A Map: keys are data, entries are added,
329
+ renamed on pk fixup, and deleted. */
330
+ entityMemos;
331
+ /** A Set, so that queuing the same entity twice is both free and impossible: this is a
332
+ membership test per change per queued entity, which as an array was quadratic. Iteration
333
+ order is insertion order, so the entities are still saved in the order they were queued. */
334
+ queuedChanges;
335
+ constructor() {
336
+ this.entityMemos = new Map();
337
+ this.queuedChanges = new Set();
338
+ }
339
+ applyToSavedEntities(entityManager, savedEntities) {
340
+ let entityMemos = this.entityMemos; // `this` is a SaveMemo
341
+ let queuedChanges = this.queuedChanges;
342
+ let restorePublishing = this.disableManagerPublishing(entityManager);
343
+ try {
344
+ savedEntities.forEach(saved => {
345
+ let key = this.makeEntityMemoKey(saved);
346
+ let entityMemo = entityMemos.get(key);
347
+ let resave = entityMemo && entityMemo.applyToSavedEntity(saved);
348
+ if (resave) {
349
+ queuedChanges.add(saved);
350
+ }
351
+ });
352
+ }
353
+ finally {
354
+ restorePublishing();
355
+ // D#2651 hasChanges will be wrong if changes made while save in progress
356
+ let hasChanges = queuedChanges.size > 0;
357
+ // Must use breeze internal method to properly set this flag true
358
+ if (hasChanges) {
359
+ entityManager._setHasChanges(true);
360
+ }
361
+ }
362
+ }
363
+ disableManagerPublishing(manager) {
364
+ let Event = BreezeEvent;
365
+ Event.enable('entityChanged', manager, false);
366
+ Event.enable('hasChangesChanged', manager, false);
367
+ return function restorePublishing() {
368
+ Event.enable('entityChanged', manager, true);
369
+ Event.enable('hasChangesChanged', manager, true);
370
+ };
371
+ }
372
+ pkFixup(keyMappings) {
373
+ let entityMemos = this.entityMemos; // `this` is a SaveMemo
374
+ keyMappings.forEach(km => {
375
+ let type = km.entityTypeName;
376
+ let tempKey = type + '|' + km.tempValue;
377
+ const memo = entityMemos.get(tempKey);
378
+ if (memo) {
379
+ entityMemos.set(type + '|' + km.realValue, memo);
380
+ entityMemos.delete(tempKey);
381
+ }
382
+ entityMemos.forEach(m => m.fkFixup(km));
383
+ });
384
+ }
385
+ makeEntityMemoKey(entity) {
386
+ let entityKey = entity.entityAspect.getKey();
387
+ return entityKey.entityType.name + '|' + entityKey.values;
388
+ }
389
+ updateEntityMemos(changes) {
390
+ let entityMemos = this.entityMemos; // `this` is a SaveMemo
391
+ changes.forEach(change => {
392
+ // only update entityMemo for entity being save
393
+ if (!change.entityAspect.isBeingSaved) {
394
+ return;
395
+ }
396
+ let key = this.makeEntityMemoKey(change);
397
+ let entityMemo = entityMemos.get(key);
398
+ if (!entityMemo) {
399
+ entityMemo = new EntityMemo(change);
400
+ entityMemos.set(key, entityMemo);
401
+ }
402
+ entityMemo.update();
403
+ });
404
+ }
405
+ }
406
+ ///////// EntityMemo Type ///////////////
407
+ // Information about an entity that is being saved
408
+ // and which has been changed since that save started
409
+ class EntityMemo {
410
+ entity;
411
+ pendingChanges;
412
+ isDeleted;
413
+ constructor(entity) {
414
+ this.entity = entity;
415
+ this.pendingChanges = {};
416
+ }
417
+ applyToSavedEntity(saved) {
418
+ let entityMemo = this;
419
+ let aspect = saved.entityAspect;
420
+ if (aspect.entityState.isDetached()) {
421
+ return false;
422
+ }
423
+ else if (entityMemo.isDeleted) {
424
+ aspect.setDeleted();
425
+ return true;
426
+ }
427
+ // treat entity with pending changes as modified
428
+ let props = Object.keys(entityMemo.pendingChanges);
429
+ if (props.length === 0) {
430
+ return false;
431
+ }
432
+ let originalValues = aspect.originalValues;
433
+ props.forEach(name => {
434
+ originalValues[name] = saved.getProperty(name);
435
+ saved.setProperty(name, entityMemo.pendingChanges[name]);
436
+ });
437
+ aspect.setModified();
438
+ return true;
439
+ }
440
+ fkFixup(keyMapping) {
441
+ let entityMemo = this;
442
+ let type = entityMemo.entity.entityType;
443
+ let fkProps = type.foreignKeyProperties;
444
+ fkProps.forEach(fkProp => {
445
+ // The type this foreign key points *at*. `fkProp.parentType` is the type that declares it,
446
+ // which is what this used to compare and is only ever the same type for a self-referencing
447
+ // key - so an ordinary foreign key set during a save kept its temporary value and the
448
+ // queued save sent a negative key to the server. `relatedNavigationProperty` covers the
449
+ // usual case; a unidirectional 1-n has only the inverse, whose parent is the target.
450
+ const relatedType = fkProp.relatedNavigationProperty
451
+ ? fkProp.relatedNavigationProperty.entityType
452
+ : fkProp.inverseNavigationProperty && fkProp.inverseNavigationProperty.parentType;
453
+ if (relatedType && relatedType.name === keyMapping.entityTypeName &&
454
+ entityMemo.pendingChanges[fkProp.name] === keyMapping.tempValue) {
455
+ entityMemo.pendingChanges[fkProp.name] = keyMapping.realValue;
456
+ }
457
+ });
458
+ }
459
+ // update the entityMemo of changes to an entity being saved
460
+ // so that we know how to save it again later
461
+ update() {
462
+ let entityMemo = this;
463
+ let props;
464
+ let entity = entityMemo.entity;
465
+ let aspect = entity.entityAspect;
466
+ let stateName = aspect.entityState.name;
467
+ switch (stateName) {
468
+ case 'Added':
469
+ let originalValues = aspect.originalValues;
470
+ props = entity.entityType.dataProperties;
471
+ props.forEach(dp => {
472
+ if (dp.isPartOfKey) {
473
+ return;
474
+ }
475
+ let name = dp.name;
476
+ let value = entity.getProperty(name);
477
+ if (originalValues[name] !== value) {
478
+ entityMemo.pendingChanges[name] = value;
479
+ }
480
+ });
481
+ break;
482
+ case 'Deleted':
483
+ entityMemo.isDeleted = true;
484
+ entityMemo.pendingChanges = {};
485
+ break;
486
+ case 'Modified':
487
+ props = Object.keys(aspect.originalValues);
488
+ props.forEach(name => {
489
+ entityMemo.pendingChanges[name] = entity.getProperty(name);
490
+ });
491
+ break;
492
+ }
493
+ }
494
+ }
495
+ //# sourceMappingURL=mixin-save-queuing.js.map