@osdk/client 2.2.0-beta.7 → 2.2.0-beta.9

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/CHANGELOG.md +43 -0
  2. package/build/browser/Client.js.map +1 -1
  3. package/build/browser/createClient.js +11 -4
  4. package/build/browser/createClient.js.map +1 -1
  5. package/build/browser/createMinimalClient.js +2 -2
  6. package/build/browser/createMinimalClient.js.map +1 -1
  7. package/build/browser/index.js +1 -0
  8. package/build/browser/index.js.map +1 -1
  9. package/build/browser/object/SimpleOsdkProperties.js +2 -0
  10. package/build/browser/object/SimpleOsdkProperties.js.map +1 -0
  11. package/build/browser/object/convertWireToOsdkObjects/BaseHolder.js +2 -0
  12. package/build/browser/object/convertWireToOsdkObjects/BaseHolder.js.map +1 -0
  13. package/build/browser/object/convertWireToOsdkObjects/InterfaceHolder.js.map +1 -1
  14. package/build/browser/object/convertWireToOsdkObjects/ObjectHolder.js.map +1 -1
  15. package/build/browser/object/convertWireToOsdkObjects/createOsdkInterface.js +25 -0
  16. package/build/browser/object/convertWireToOsdkObjects/createOsdkInterface.js.map +1 -1
  17. package/build/browser/object/convertWireToOsdkObjects/createOsdkObject.js +10 -3
  18. package/build/browser/object/convertWireToOsdkObjects/createOsdkObject.js.map +1 -1
  19. package/build/browser/object/convertWireToOsdkObjects/getDollarAs.js.map +1 -1
  20. package/build/browser/object/convertWireToOsdkObjects/getDollarLink.js.map +1 -1
  21. package/build/browser/object/convertWireToOsdkObjects.js +12 -3
  22. package/build/browser/object/convertWireToOsdkObjects.js.map +1 -1
  23. package/build/browser/object/convertWireToOsdkObjects.test.js +7 -3
  24. package/build/browser/object/convertWireToOsdkObjects.test.js.map +1 -1
  25. package/build/browser/object/createObjectSpecifierFromPrimaryKey.js +20 -0
  26. package/build/browser/object/createObjectSpecifierFromPrimaryKey.js.map +1 -0
  27. package/build/browser/object/fetchPage.js +13 -1
  28. package/build/browser/object/fetchPage.js.map +1 -1
  29. package/build/browser/object/fetchPage.test.js +56 -2
  30. package/build/browser/object/fetchPage.test.js.map +1 -1
  31. package/build/browser/object/object.test.js +109 -0
  32. package/build/browser/object/object.test.js.map +1 -1
  33. package/build/browser/objectSet/InterfaceObjectSet.test.js +18 -2
  34. package/build/browser/objectSet/InterfaceObjectSet.test.js.map +1 -1
  35. package/build/browser/objectSet/ObjectSet.test.js +104 -100
  36. package/build/browser/objectSet/ObjectSet.test.js.map +1 -1
  37. package/build/browser/objectSet/ObjectSetListenerWebsocket.js +18 -14
  38. package/build/browser/objectSet/ObjectSetListenerWebsocket.js.map +1 -1
  39. package/build/browser/objectSet/ObjectSetListenerWebsocket.test.js +2 -0
  40. package/build/browser/objectSet/ObjectSetListenerWebsocket.test.js.map +1 -1
  41. package/build/browser/objectSet/createObjectSet.js.map +1 -1
  42. package/build/browser/observable/ListPayload.js.map +1 -1
  43. package/build/browser/observable/ObjectPayload.js.map +1 -1
  44. package/build/browser/observable/ObservableClient.js.map +1 -1
  45. package/build/browser/observable/internal/ActionApplication.js +29 -29
  46. package/build/browser/observable/internal/ActionApplication.js.map +1 -1
  47. package/build/browser/observable/internal/CacheKey.js +1 -1
  48. package/build/browser/observable/internal/CacheKey.js.map +1 -1
  49. package/build/browser/observable/internal/CacheKeys.js +2 -2
  50. package/build/browser/observable/internal/CacheKeys.js.map +1 -1
  51. package/build/browser/observable/internal/{ChangedObjects.js → Changes.js} +20 -9
  52. package/build/browser/observable/internal/Changes.js.map +1 -0
  53. package/build/browser/observable/internal/Layer.js +3 -0
  54. package/build/browser/observable/internal/Layer.js.map +1 -1
  55. package/build/browser/observable/internal/ListQuery.js +411 -170
  56. package/build/browser/observable/internal/ListQuery.js.map +1 -1
  57. package/build/browser/observable/internal/ObjectQuery.js +32 -16
  58. package/build/browser/observable/internal/ObjectQuery.js.map +1 -1
  59. package/build/browser/observable/internal/ObservableClientImpl.js +4 -12
  60. package/build/browser/observable/internal/ObservableClientImpl.js.map +1 -1
  61. package/build/browser/observable/internal/OptimisticJob.js.map +1 -1
  62. package/build/browser/observable/internal/OrderByCanonicalizer.js +73 -0
  63. package/build/browser/observable/internal/OrderByCanonicalizer.js.map +1 -0
  64. package/build/browser/observable/internal/OrderByCanonicalizer.test.js +78 -0
  65. package/build/browser/observable/internal/OrderByCanonicalizer.test.js.map +1 -0
  66. package/build/browser/observable/internal/Query.js +64 -31
  67. package/build/browser/observable/internal/Query.js.map +1 -1
  68. package/build/browser/observable/internal/RefCounts.js +7 -2
  69. package/build/browser/observable/internal/RefCounts.js.map +1 -1
  70. package/build/browser/observable/internal/SimpleWhereClause.js +2 -0
  71. package/build/browser/observable/internal/SimpleWhereClause.js.map +1 -0
  72. package/build/browser/observable/internal/Store.js +84 -267
  73. package/build/browser/observable/internal/Store.js.map +1 -1
  74. package/build/browser/observable/internal/Store.test.js +264 -247
  75. package/build/browser/observable/internal/Store.test.js.map +1 -1
  76. package/build/browser/observable/internal/WhereClauseCanonicalizer.js +11 -3
  77. package/build/browser/observable/internal/WhereClauseCanonicalizer.js.map +1 -1
  78. package/build/browser/observable/internal/objectMatchesWhereClause.js.map +1 -1
  79. package/build/browser/observable/internal/objectMatchesWhereClause.test.js.map +1 -1
  80. package/build/browser/observable/internal/testUtils.js +82 -18
  81. package/build/browser/observable/internal/testUtils.js.map +1 -1
  82. package/build/browser/public/unstable-do-not-use.js.map +1 -1
  83. package/build/browser/queries/applyQuery.js +33 -1
  84. package/build/browser/queries/applyQuery.js.map +1 -1
  85. package/build/browser/queries/queries.test.js +26 -5
  86. package/build/browser/queries/queries.test.js.map +1 -1
  87. package/build/browser/util/UserAgent.js +1 -1
  88. package/build/browser/util/toDataValueQueries.js +17 -0
  89. package/build/browser/util/toDataValueQueries.js.map +1 -1
  90. package/build/cjs/{Client-C8K3E1vH.d.cts → Client-DBTcM9gB.d.cts} +1 -1
  91. package/build/cjs/{chunk-JPENHIJB.cjs → chunk-EY52J5Z4.cjs} +25 -15
  92. package/build/cjs/chunk-EY52J5Z4.cjs.map +1 -0
  93. package/build/cjs/{chunk-IU47QMYO.cjs → chunk-MCQVHD2F.cjs} +32 -28
  94. package/build/cjs/chunk-MCQVHD2F.cjs.map +1 -0
  95. package/build/cjs/chunk-T4NIFYZS.cjs +14 -0
  96. package/build/cjs/chunk-T4NIFYZS.cjs.map +1 -0
  97. package/build/cjs/index.cjs +154 -73
  98. package/build/cjs/index.cjs.map +1 -1
  99. package/build/cjs/index.d.cts +6 -4
  100. package/build/cjs/public/internal.cjs +6 -6
  101. package/build/cjs/public/internal.d.cts +1 -1
  102. package/build/cjs/public/unstable-do-not-use.cjs +683 -539
  103. package/build/cjs/public/unstable-do-not-use.cjs.map +1 -1
  104. package/build/cjs/public/unstable-do-not-use.d.cts +28 -27
  105. package/build/esm/Client.js.map +1 -1
  106. package/build/esm/createClient.js +11 -4
  107. package/build/esm/createClient.js.map +1 -1
  108. package/build/esm/createMinimalClient.js +2 -2
  109. package/build/esm/createMinimalClient.js.map +1 -1
  110. package/build/esm/index.js +1 -0
  111. package/build/esm/index.js.map +1 -1
  112. package/build/esm/object/SimpleOsdkProperties.js +2 -0
  113. package/build/esm/object/SimpleOsdkProperties.js.map +1 -0
  114. package/build/esm/object/convertWireToOsdkObjects/BaseHolder.js +2 -0
  115. package/build/esm/object/convertWireToOsdkObjects/BaseHolder.js.map +1 -0
  116. package/build/esm/object/convertWireToOsdkObjects/InterfaceHolder.js.map +1 -1
  117. package/build/esm/object/convertWireToOsdkObjects/ObjectHolder.js.map +1 -1
  118. package/build/esm/object/convertWireToOsdkObjects/createOsdkInterface.js +25 -0
  119. package/build/esm/object/convertWireToOsdkObjects/createOsdkInterface.js.map +1 -1
  120. package/build/esm/object/convertWireToOsdkObjects/createOsdkObject.js +10 -3
  121. package/build/esm/object/convertWireToOsdkObjects/createOsdkObject.js.map +1 -1
  122. package/build/esm/object/convertWireToOsdkObjects/getDollarAs.js.map +1 -1
  123. package/build/esm/object/convertWireToOsdkObjects/getDollarLink.js.map +1 -1
  124. package/build/esm/object/convertWireToOsdkObjects.js +12 -3
  125. package/build/esm/object/convertWireToOsdkObjects.js.map +1 -1
  126. package/build/esm/object/convertWireToOsdkObjects.test.js +7 -3
  127. package/build/esm/object/convertWireToOsdkObjects.test.js.map +1 -1
  128. package/build/esm/object/createObjectSpecifierFromPrimaryKey.js +20 -0
  129. package/build/esm/object/createObjectSpecifierFromPrimaryKey.js.map +1 -0
  130. package/build/esm/object/fetchPage.js +13 -1
  131. package/build/esm/object/fetchPage.js.map +1 -1
  132. package/build/esm/object/fetchPage.test.js +56 -2
  133. package/build/esm/object/fetchPage.test.js.map +1 -1
  134. package/build/esm/object/object.test.js +109 -0
  135. package/build/esm/object/object.test.js.map +1 -1
  136. package/build/esm/objectSet/InterfaceObjectSet.test.js +18 -2
  137. package/build/esm/objectSet/InterfaceObjectSet.test.js.map +1 -1
  138. package/build/esm/objectSet/ObjectSet.test.js +104 -100
  139. package/build/esm/objectSet/ObjectSet.test.js.map +1 -1
  140. package/build/esm/objectSet/ObjectSetListenerWebsocket.js +18 -14
  141. package/build/esm/objectSet/ObjectSetListenerWebsocket.js.map +1 -1
  142. package/build/esm/objectSet/ObjectSetListenerWebsocket.test.js +2 -0
  143. package/build/esm/objectSet/ObjectSetListenerWebsocket.test.js.map +1 -1
  144. package/build/esm/objectSet/createObjectSet.js.map +1 -1
  145. package/build/esm/observable/ListPayload.js.map +1 -1
  146. package/build/esm/observable/ObjectPayload.js.map +1 -1
  147. package/build/esm/observable/ObservableClient.js.map +1 -1
  148. package/build/esm/observable/internal/ActionApplication.js +29 -29
  149. package/build/esm/observable/internal/ActionApplication.js.map +1 -1
  150. package/build/esm/observable/internal/CacheKey.js +1 -1
  151. package/build/esm/observable/internal/CacheKey.js.map +1 -1
  152. package/build/esm/observable/internal/CacheKeys.js +2 -2
  153. package/build/esm/observable/internal/CacheKeys.js.map +1 -1
  154. package/build/esm/observable/internal/{ChangedObjects.js → Changes.js} +20 -9
  155. package/build/esm/observable/internal/Changes.js.map +1 -0
  156. package/build/esm/observable/internal/Layer.js +3 -0
  157. package/build/esm/observable/internal/Layer.js.map +1 -1
  158. package/build/esm/observable/internal/ListQuery.js +411 -170
  159. package/build/esm/observable/internal/ListQuery.js.map +1 -1
  160. package/build/esm/observable/internal/ObjectQuery.js +32 -16
  161. package/build/esm/observable/internal/ObjectQuery.js.map +1 -1
  162. package/build/esm/observable/internal/ObservableClientImpl.js +4 -12
  163. package/build/esm/observable/internal/ObservableClientImpl.js.map +1 -1
  164. package/build/esm/observable/internal/OptimisticJob.js.map +1 -1
  165. package/build/esm/observable/internal/OrderByCanonicalizer.js +73 -0
  166. package/build/esm/observable/internal/OrderByCanonicalizer.js.map +1 -0
  167. package/build/esm/observable/internal/OrderByCanonicalizer.test.js +78 -0
  168. package/build/esm/observable/internal/OrderByCanonicalizer.test.js.map +1 -0
  169. package/build/esm/observable/internal/Query.js +64 -31
  170. package/build/esm/observable/internal/Query.js.map +1 -1
  171. package/build/esm/observable/internal/RefCounts.js +7 -2
  172. package/build/esm/observable/internal/RefCounts.js.map +1 -1
  173. package/build/esm/observable/internal/SimpleWhereClause.js +2 -0
  174. package/build/esm/observable/internal/SimpleWhereClause.js.map +1 -0
  175. package/build/esm/observable/internal/Store.js +84 -267
  176. package/build/esm/observable/internal/Store.js.map +1 -1
  177. package/build/esm/observable/internal/Store.test.js +264 -247
  178. package/build/esm/observable/internal/Store.test.js.map +1 -1
  179. package/build/esm/observable/internal/WhereClauseCanonicalizer.js +11 -3
  180. package/build/esm/observable/internal/WhereClauseCanonicalizer.js.map +1 -1
  181. package/build/esm/observable/internal/objectMatchesWhereClause.js.map +1 -1
  182. package/build/esm/observable/internal/objectMatchesWhereClause.test.js.map +1 -1
  183. package/build/esm/observable/internal/testUtils.js +82 -18
  184. package/build/esm/observable/internal/testUtils.js.map +1 -1
  185. package/build/esm/public/unstable-do-not-use.js.map +1 -1
  186. package/build/esm/queries/applyQuery.js +33 -1
  187. package/build/esm/queries/applyQuery.js.map +1 -1
  188. package/build/esm/queries/queries.test.js +26 -5
  189. package/build/esm/queries/queries.test.js.map +1 -1
  190. package/build/esm/util/UserAgent.js +1 -1
  191. package/build/esm/util/toDataValueQueries.js +17 -0
  192. package/build/esm/util/toDataValueQueries.js.map +1 -1
  193. package/build/types/Client.d.ts +1 -1
  194. package/build/types/Client.d.ts.map +1 -1
  195. package/build/types/createClient.d.ts.map +1 -1
  196. package/build/types/index.d.ts +2 -1
  197. package/build/types/index.d.ts.map +1 -1
  198. package/build/types/object/SimpleOsdkProperties.d.ts +1 -0
  199. package/build/types/object/SimpleOsdkProperties.d.ts.map +1 -0
  200. package/build/types/object/convertWireToOsdkObjects/BaseHolder.d.ts +1 -0
  201. package/build/types/object/convertWireToOsdkObjects/BaseHolder.d.ts.map +1 -0
  202. package/build/types/object/convertWireToOsdkObjects.d.ts +8 -1
  203. package/build/types/object/convertWireToOsdkObjects.d.ts.map +1 -1
  204. package/build/types/object/createObjectSpecifierFromPrimaryKey.d.ts +2 -0
  205. package/build/types/object/createObjectSpecifierFromPrimaryKey.d.ts.map +1 -0
  206. package/build/types/object/object.test.d.ts.map +1 -1
  207. package/build/types/objectSet/ObjectSet.test.d.ts.map +1 -1
  208. package/build/types/observable/ListPayload.d.ts +5 -9
  209. package/build/types/observable/ListPayload.d.ts.map +1 -1
  210. package/build/types/observable/ObjectPayload.d.ts +4 -7
  211. package/build/types/observable/ObjectPayload.d.ts.map +1 -1
  212. package/build/types/observable/ObservableClient.d.ts +27 -11
  213. package/build/types/observable/ObservableClient.d.ts.map +1 -1
  214. package/build/types/observable/internal/ActionApplication.d.ts.map +1 -1
  215. package/build/types/observable/internal/CacheKeys.d.ts +1 -1
  216. package/build/types/observable/internal/CacheKeys.d.ts.map +1 -1
  217. package/build/types/observable/internal/Changes.d.ts +15 -0
  218. package/build/types/observable/internal/Changes.d.ts.map +1 -0
  219. package/build/types/observable/internal/Layer.d.ts +1 -0
  220. package/build/types/observable/internal/Layer.d.ts.map +1 -1
  221. package/build/types/observable/internal/ListQuery.d.ts +59 -14
  222. package/build/types/observable/internal/ListQuery.d.ts.map +1 -1
  223. package/build/types/observable/internal/ObjectQuery.d.ts +5 -6
  224. package/build/types/observable/internal/ObjectQuery.d.ts.map +1 -1
  225. package/build/types/observable/internal/OptimisticJob.d.ts +1 -1
  226. package/build/types/observable/internal/OptimisticJob.d.ts.map +1 -1
  227. package/build/types/observable/internal/OrderByCanonicalizer.d.ts +12 -0
  228. package/build/types/observable/internal/OrderByCanonicalizer.d.ts.map +1 -0
  229. package/build/types/observable/internal/OrderByCanonicalizer.test.d.ts +1 -0
  230. package/build/types/observable/internal/OrderByCanonicalizer.test.d.ts.map +1 -0
  231. package/build/types/observable/internal/Query.d.ts +39 -4
  232. package/build/types/observable/internal/Query.d.ts.map +1 -1
  233. package/build/types/observable/internal/RefCounts.d.ts.map +1 -1
  234. package/build/types/observable/internal/SimpleWhereClause.d.ts +2 -0
  235. package/build/types/observable/internal/SimpleWhereClause.d.ts.map +1 -0
  236. package/build/types/observable/internal/Store.d.ts +19 -43
  237. package/build/types/observable/internal/Store.d.ts.map +1 -1
  238. package/build/types/observable/internal/WhereClauseCanonicalizer.d.ts +2 -1
  239. package/build/types/observable/internal/WhereClauseCanonicalizer.d.ts.map +1 -1
  240. package/build/types/observable/internal/objectMatchesWhereClause.d.ts +4 -2
  241. package/build/types/observable/internal/objectMatchesWhereClause.d.ts.map +1 -1
  242. package/build/types/observable/internal/testUtils.d.ts +39 -9
  243. package/build/types/observable/internal/testUtils.d.ts.map +1 -1
  244. package/build/types/public/unstable-do-not-use.d.ts +1 -4
  245. package/build/types/public/unstable-do-not-use.d.ts.map +1 -1
  246. package/build/types/queries/applyQuery.d.ts.map +1 -1
  247. package/package.json +13 -11
  248. package/build/browser/observable/internal/ChangedObjects.js.map +0 -1
  249. package/build/cjs/chunk-IU47QMYO.cjs.map +0 -1
  250. package/build/cjs/chunk-JPENHIJB.cjs.map +0 -1
  251. package/build/esm/observable/internal/ChangedObjects.js.map +0 -1
  252. package/build/types/observable/internal/ChangedObjects.d.ts +0 -11
  253. package/build/types/observable/internal/ChangedObjects.d.ts.map +0 -1
@@ -14,16 +14,21 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import { $ontologyRid, createOffice, Employee, Todo } from "@osdk/client.test.ontology";
18
- import { apiServer } from "@osdk/shared.test";
17
+ import { $ontologyRid, createOffice, Employee, FooInterface, Todo } from "@osdk/client.test.ontology";
18
+ import { wireObjectTypeFullMetadataToSdkObjectMetadata } from "@osdk/generator-converters";
19
+ import { apiServer, stubData } from "@osdk/shared.test";
19
20
  import chalk from "chalk";
20
21
  import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi, vitest } from "vitest";
21
22
  import { createClient } from "../../createClient.js";
23
+ import { createMinimalClient } from "../../createMinimalClient.js";
24
+ import { createObjectSet } from "../../objectSet/createObjectSet.js";
25
+ import { InterfaceDefinitions } from "../../ontology/OntologyProvider.js";
22
26
  import { createOptimisticId } from "./OptimisticId.js";
23
27
  import { runOptimisticJob } from "./OptimisticJob.js";
24
- import { Store } from "./Store.js";
25
- import { applyCustomMatchers, createClientMockHelper, createDefer, createTestLogger, expectSingleListCallAndClear, expectSingleObjectCallAndClear, listPayloadContaining, mockListSubCallback, mockSingleSubCallback, objectPayloadContaining, waitForCall } from "./testUtils.js";
28
+ import { invalidateList, Store } from "./Store.js";
29
+ import { applyCustomMatchers, createClientMockHelper, createDefer, createTestLogger, expectNoMoreCalls, expectSingleListCallAndClear, expectSingleObjectCallAndClear, getObject, mockListSubCallback, mockSingleSubCallback, objectPayloadContaining, updateList, updateObject, waitForCall } from "./testUtils.js";
26
30
  const defer = createDefer();
31
+ const logger = createTestLogger({});
27
32
  beforeAll(() => {
28
33
  vi.setConfig({
29
34
  fakeTimers: {
@@ -63,7 +68,7 @@ describe(Store, () => {
63
68
  beforeAll(async () => {
64
69
  apiServer.listen();
65
70
  client = createClient("https://stack.palantir.com", $ontologyRid, async () => "myAccessToken", {
66
- logger: createTestLogger({})
71
+ logger
67
72
  });
68
73
  employeesAsServerReturns = (await client(Employee).fetchPage()).data;
69
74
  mutatedEmployees = [employeesAsServerReturns[0], employeesAsServerReturns[1].$clone({
@@ -81,26 +86,27 @@ describe(Store, () => {
81
86
  });
82
87
  it("basic single object works", async () => {
83
88
  const emp = employeesAsServerReturns[0];
89
+ const cacheKey = cache.getCacheKey("object", "Employee", emp.$primaryKey);
84
90
 
85
91
  // starts empty
86
- expect(cache.getObject(Employee, emp.$primaryKey)).toBeUndefined();
87
- const result = cache.updateObject(Employee, emp);
92
+ expect(cache.getValue(cacheKey)?.value).toBeUndefined();
93
+ const result = updateObject(cache, emp);
88
94
  expect(emp).toBe(result);
89
95
 
90
96
  // getting the object now matches the result
91
- expect(cache.getObject(Employee, emp.$primaryKey)).toEqual(result);
92
- const updatedEmpFromCache = cache.updateObject(Employee, emp.$clone({
97
+ expect(cache.getValue(cacheKey)?.value).toEqual(result);
98
+ const updatedEmpFromCache = updateObject(cache, emp.$clone({
93
99
  fullName: "new name"
94
100
  }));
95
101
  expect(updatedEmpFromCache).not.toBe(emp);
96
102
 
97
103
  // getting it again is the updated object
98
- expect(cache.getObject(Employee, emp.$primaryKey)).toEqual(updatedEmpFromCache);
104
+ expect(cache.getValue(cacheKey)?.value).toEqual(updatedEmpFromCache);
99
105
  });
100
106
  describe("optimistic updates", () => {
101
107
  it("rolls back objects", async () => {
102
108
  const emp = employeesAsServerReturns[0];
103
- cache.updateObject(Employee, emp); // pre-seed the cache with the "real" value
109
+ updateObject(cache, emp); // pre-seed the cache with the "real" value
104
110
 
105
111
  const subFn = mockSingleSubCallback();
106
112
  defer(cache.observeObject(Employee, emp.$primaryKey, {
@@ -109,7 +115,7 @@ describe(Store, () => {
109
115
  expectSingleObjectCallAndClear(subFn, emp, "loaded");
110
116
  const optimisticId = createOptimisticId();
111
117
  // update with an optimistic write
112
- cache.updateObject(Employee, emp.$clone({
118
+ updateObject(cache, emp.$clone({
113
119
  fullName: "new name"
114
120
  }), {
115
121
  optimisticId
@@ -124,8 +130,8 @@ describe(Store, () => {
124
130
  });
125
131
  it("rolls back to an updated real value", async () => {
126
132
  // pre-seed the cache with the "real" value
127
- cache.updateList({
128
- objectType: Employee,
133
+ updateList(cache, {
134
+ type: Employee,
129
135
  where: {},
130
136
  orderBy: {}
131
137
  }, employeesAsServerReturns);
@@ -137,7 +143,7 @@ describe(Store, () => {
137
143
  expectSingleObjectCallAndClear(empSubFn, emp, "loaded");
138
144
  const listSubFn = mockListSubCallback();
139
145
  defer(cache.observeList({
140
- objectType: Employee,
146
+ type: Employee,
141
147
  mode: "offline"
142
148
  }, listSubFn));
143
149
  await waitForCall(listSubFn, 1);
@@ -147,10 +153,10 @@ describe(Store, () => {
147
153
  });
148
154
  const optimisticId = createOptimisticId();
149
155
  testStage("optimistic update");
150
- expect(listSubFn).not.toHaveBeenCalled();
156
+ expect(listSubFn.next).not.toHaveBeenCalled();
151
157
 
152
158
  // update with an optimistic write
153
- cache.updateObject(Employee, optimisticEmployee, {
159
+ updateObject(cache, optimisticEmployee, {
154
160
  optimisticId
155
161
  });
156
162
  testStage("after optimistic update");
@@ -170,8 +176,8 @@ describe(Store, () => {
170
176
  fullName: "real update"
171
177
  });
172
178
  testStage("write real update");
173
- cache.updateList({
174
- objectType: Employee,
179
+ updateList(cache, {
180
+ type: Employee,
175
181
  where: {},
176
182
  orderBy: {}
177
183
  }, [truthUpdatedEmployee]);
@@ -188,47 +194,38 @@ describe(Store, () => {
188
194
  status: "loaded",
189
195
  isOptimistic: false
190
196
  });
191
- vi.useRealTimers();
192
197
  });
193
198
  it("rolls back to an updated real value via list", async () => {
194
199
  const emp = employeesAsServerReturns[0];
195
- cache.updateObject(Employee, emp); // pre-seed the cache with the "real" value
200
+ updateObject(cache, emp); // pre-seed the cache with the "real" value
196
201
 
197
202
  const subFn = mockSingleSubCallback();
198
203
  defer(cache.observeObject(Employee, emp.$primaryKey, {
199
204
  mode: "offline"
200
205
  }, subFn));
201
- expect(subFn).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
202
- object: emp,
203
- status: "loaded"
204
- }));
205
- subFn.mockClear();
206
+ expectSingleObjectCallAndClear(subFn, emp, "loaded");
206
207
  const optimisticEmployee = emp.$clone({
207
208
  fullName: "new name"
208
209
  });
209
210
 
210
211
  // update with an optimistic write
211
212
  const optimisticId = createOptimisticId();
212
- cache.updateObject(Employee, optimisticEmployee, {
213
+ updateObject(cache, optimisticEmployee, {
213
214
  optimisticId
214
215
  });
215
- expect(subFn).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
216
- object: optimisticEmployee
217
- }));
218
- subFn.mockClear();
216
+ expectSingleObjectCallAndClear(subFn, optimisticEmployee);
219
217
  const truthUpdatedEmployee = emp.$clone({
220
218
  fullName: "real update"
221
219
  });
222
- cache.updateObject(Employee, truthUpdatedEmployee);
220
+ updateObject(cache, truthUpdatedEmployee);
223
221
 
224
222
  // we shouldn't expect an update because the top layer has a value
225
- expect(subFn).not.toHaveBeenCalled();
223
+ expect(subFn.next).not.toHaveBeenCalled();
226
224
 
227
225
  // remove the optimistic write
228
226
  cache.removeLayer(optimisticId);
229
- expect(subFn).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
230
- object: truthUpdatedEmployee
231
- }));
227
+ expectSingleObjectCallAndClear(subFn, truthUpdatedEmployee);
228
+ expectNoMoreCalls(subFn);
232
229
  });
233
230
  });
234
231
  describe(".invalidateObject", () => {
@@ -237,29 +234,20 @@ describe(Store, () => {
237
234
  const staleEmp = emp.$clone({
238
235
  fullName: "stale"
239
236
  });
240
- cache.updateObject(Employee, staleEmp);
237
+ updateObject(cache, staleEmp);
241
238
  const subFn = mockSingleSubCallback();
242
239
  defer(cache.observeObject(Employee, emp.$primaryKey, {
243
240
  mode: "offline"
244
241
  }, subFn));
245
- expect(subFn).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
246
- object: staleEmp,
247
- status: "loaded"
248
- }));
249
- subFn.mockClear();
242
+ expectSingleObjectCallAndClear(subFn, staleEmp, "loaded");
250
243
 
251
244
  // invalidate
252
245
  void cache.invalidateObject(Employee, staleEmp.$primaryKey);
253
- await vi.waitFor(() => expect(subFn).toHaveBeenCalled());
254
- expect(subFn).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
255
- object: staleEmp,
256
- status: "loading"
257
- }));
258
- subFn.mockClear();
259
- await vi.waitFor(() => expect(subFn).toHaveBeenCalled());
260
- expect(subFn).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
261
- object: emp
262
- }));
246
+ await waitForCall(subFn);
247
+ expectSingleObjectCallAndClear(subFn, staleEmp, "loading");
248
+ await waitForCall(subFn);
249
+ expectSingleObjectCallAndClear(subFn, emp, "loaded");
250
+ expectNoMoreCalls(subFn);
263
251
  });
264
252
  });
265
253
  describe(".invalidateList", () => {
@@ -274,8 +262,8 @@ describe(Store, () => {
274
262
  const staleEmp = emp.$clone({
275
263
  fullName: "stale"
276
264
  });
277
- cache.updateList({
278
- objectType: Employee,
265
+ updateList(cache, {
266
+ type: Employee,
279
267
  where: {},
280
268
  orderBy: {}
281
269
  }, [staleEmp]);
@@ -286,7 +274,7 @@ describe(Store, () => {
286
274
  expectSingleObjectCallAndClear(subFn, staleEmp);
287
275
  const subListFn = mockListSubCallback();
288
276
  defer(cache.observeList({
289
- objectType: Employee,
277
+ type: Employee,
290
278
  mode: "offline"
291
279
  }, subListFn));
292
280
  await waitForCall(subListFn, 1);
@@ -294,8 +282,8 @@ describe(Store, () => {
294
282
  status: "loaded"
295
283
  });
296
284
  testStage("invalidate");
297
- cache.invalidateList({
298
- objectType: Employee
285
+ const invalidateListPromise = invalidateList(cache, {
286
+ type: Employee
299
287
  });
300
288
  testStage("check invalidate");
301
289
  await waitForCall(subListFn, 1);
@@ -308,6 +296,9 @@ describe(Store, () => {
308
296
  });
309
297
  await waitForCall(subFn, 1);
310
298
  expectSingleObjectCallAndClear(subFn, emp, "loaded");
299
+
300
+ // don't leave promises dangling
301
+ await invalidateListPromise;
311
302
  });
312
303
  });
313
304
  describe(".invalidateObjectType", () => {
@@ -322,8 +313,8 @@ describe(Store, () => {
322
313
  const staleEmp = emp.$clone({
323
314
  fullName: "stale"
324
315
  });
325
- cache.updateList({
326
- objectType: Employee,
316
+ updateList(cache, {
317
+ type: Employee,
327
318
  where: {},
328
319
  orderBy: {}
329
320
  }, [staleEmp]);
@@ -334,7 +325,7 @@ describe(Store, () => {
334
325
  expectSingleObjectCallAndClear(subFn, staleEmp);
335
326
  const subListFn = mockListSubCallback();
336
327
  defer(cache.observeList({
337
- objectType: Employee,
328
+ type: Employee,
338
329
  where: {},
339
330
  orderBy: {},
340
331
  mode: "offline"
@@ -346,21 +337,13 @@ describe(Store, () => {
346
337
  testStage("invalidate");
347
338
  const pInvalidateComplete = cache.invalidateObjectType(Employee, undefined);
348
339
  await waitForCall(subListFn, 1);
349
- expect(subListFn).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
350
- resolvedList: [staleEmp],
340
+ expectSingleListCallAndClear(subListFn, [staleEmp], {
351
341
  status: "loading"
352
- }));
353
- subListFn.mockClear();
354
- await vi.waitFor(() => expect(subListFn).toHaveBeenCalled());
355
- expect(subListFn).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
356
- resolvedList: employeesAsServerReturns
357
- }));
358
- subListFn.mockClear();
359
- await vi.waitFor(() => expect(subFn).toHaveBeenCalled());
360
- expect(subFn).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
361
- status: "loaded",
362
- object: emp
363
- }));
342
+ });
343
+ await waitForCall(subListFn, 1);
344
+ expectSingleListCallAndClear(subListFn, employeesAsServerReturns);
345
+ await waitForCall(subFn, 1);
346
+ expectSingleObjectCallAndClear(subFn, emp, "loaded");
364
347
 
365
348
  // we don't need this value to control the test but we want to make sure we don't have
366
349
  // any unhandled exceptions upon test completion
@@ -371,8 +354,12 @@ describe(Store, () => {
371
354
  const subFn1 = mockSingleSubCallback();
372
355
  const subFn2 = mockSingleSubCallback();
373
356
  beforeEach(async () => {
374
- subFn1.mockClear();
375
- subFn2.mockClear();
357
+ subFn1.complete.mockClear();
358
+ subFn1.next.mockClear();
359
+ subFn1.error.mockClear();
360
+ subFn2.complete.mockClear();
361
+ subFn2.next.mockClear();
362
+ subFn2.error.mockClear();
376
363
  });
377
364
  const likeEmployee50030 = expect.objectContaining({
378
365
  $primaryKey: 50030,
@@ -382,42 +369,36 @@ describe(Store, () => {
382
369
  defer(cache.observeObject(Employee, 50030, {
383
370
  mode: "force"
384
371
  }, subFn1));
385
- expect(subFn1).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
372
+ expect(subFn1.next).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
386
373
  status: "loading",
387
374
  object: undefined,
388
375
  isOptimistic: false
389
376
  }));
390
- subFn1.mockClear();
391
- await vi.waitFor(() => expect(subFn1).toHaveBeenCalled());
392
- expect(subFn1).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
377
+ subFn1.next.mockClear();
378
+ await waitForCall(subFn1);
379
+ expect(subFn1.next).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
393
380
  object: likeEmployee50030,
394
381
  isOptimistic: false
395
382
  }));
396
- const firstLoad = subFn1.mock.lastCall?.[0];
397
- subFn1.mockClear();
383
+ const firstLoad = subFn1.next.mock.lastCall?.[0];
384
+ subFn1.next.mockClear();
398
385
  defer(cache.observeObject(Employee, 50030, {
399
386
  mode: "force"
400
387
  }, subFn2));
401
- expect(subFn1).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
402
- status: "loading"
403
- }));
404
- subFn1.mockClear();
388
+ expectSingleObjectCallAndClear(subFn1, likeEmployee50030, "loading");
405
389
 
406
390
  // should be the earlier results
407
- expect(subFn2).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
408
- status: "loading"
409
- }));
410
- subFn2.mockClear();
391
+ expectSingleObjectCallAndClear(subFn2, likeEmployee50030, "loading");
411
392
 
412
393
  // both will be updated
413
394
  for (const s of [subFn1, subFn2]) {
414
395
  // wait for the result to come in
415
- await vi.waitFor(() => expect(s).toHaveBeenCalled());
416
- expect(s).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
396
+ await waitForCall(s, 1);
397
+ expect(s.next).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
417
398
  ...firstLoad,
418
399
  lastUpdated: expect.toBeGreaterThan(firstLoad.lastUpdated)
419
400
  }));
420
- s.mockClear();
401
+ s.next.mockClear();
421
402
  }
422
403
  });
423
404
  });
@@ -425,68 +406,66 @@ describe(Store, () => {
425
406
  const subFn = mockSingleSubCallback();
426
407
  let sub;
427
408
  beforeEach(() => {
428
- subFn.mockClear();
409
+ subFn.complete.mockClear();
410
+ subFn.next.mockClear();
411
+ subFn.error.mockClear();
429
412
  sub = defer(cache.observeObject(Employee, 50030, {
430
413
  mode: "offline"
431
414
  }, subFn));
432
- expect(subFn).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
433
- status: "init",
434
- object: undefined
435
- }));
436
- subFn.mockClear();
415
+ expectSingleObjectCallAndClear(subFn, undefined, "init");
437
416
  });
438
417
  it("does basic observation and unsubscribe", async () => {
439
418
  const emp = employeesAsServerReturns[0];
440
419
 
441
420
  // force an update
442
- cache.updateObject(Employee, emp);
443
- expect(subFn).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
444
- object: emp
445
- }));
446
- subFn.mockClear();
421
+ updateObject(cache, emp);
422
+ expectSingleObjectCallAndClear(subFn, emp);
447
423
 
448
424
  // force again
449
- cache.updateObject(Employee, emp.$clone({
425
+ updateObject(cache, emp.$clone({
450
426
  fullName: "new name"
451
427
  }));
452
- expect(subFn).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
453
- object: expect.objectContaining({
454
- fullName: "new name"
455
- })
428
+ expectSingleObjectCallAndClear(subFn, emp.$clone({
429
+ fullName: "new name"
456
430
  }));
457
- subFn.mockClear();
458
431
  sub.unsubscribe();
459
432
 
460
433
  // force again but no subscription update
461
- cache.updateObject(Employee, emp.$clone({
434
+ updateObject(cache, emp.$clone({
462
435
  fullName: "new name 2"
463
436
  }));
464
- expect(subFn).not.toHaveBeenCalled();
437
+ expect(subFn.next).not.toHaveBeenCalled();
465
438
  });
466
439
  it("observes with list update", async () => {
467
440
  const emp = employeesAsServerReturns[0];
468
441
 
469
442
  // force an update
470
- cache.updateObject(Employee, emp.$clone({
443
+ updateObject(cache, emp.$clone({
471
444
  fullName: "not the name"
472
445
  }));
473
- expect(subFn).toHaveBeenCalledTimes(1);
474
- cache.updateList({
475
- objectType: Employee,
446
+ expect(subFn.next).toHaveBeenCalledTimes(1);
447
+ updateList(cache, {
448
+ type: Employee,
476
449
  where: {},
477
450
  orderBy: {}
478
451
  }, employeesAsServerReturns);
479
- expect(subFn).toHaveBeenCalledTimes(2);
480
- expect(subFn.mock.calls[1][0]).toEqual(objectPayloadContaining({
452
+ expect(subFn.next).toHaveBeenCalledTimes(2);
453
+ expect(subFn.next.mock.calls[1][0]).toEqual(objectPayloadContaining({
481
454
  object: emp
482
455
  }));
483
456
  });
484
457
  });
485
458
  describe(".observeList", () => {
486
459
  const listSub1 = mockListSubCallback();
460
+ const ifaceSub = mockListSubCallback();
487
461
  beforeEach(() => {
488
462
  vi.useFakeTimers({});
489
- listSub1.mockReset();
463
+ vi.mocked(listSub1.next).mockReset();
464
+ vi.mocked(listSub1.error).mockReset();
465
+ vi.mocked(listSub1.complete).mockReset();
466
+ vi.mocked(ifaceSub.next).mockReset();
467
+ vi.mocked(ifaceSub.error).mockReset();
468
+ vi.mocked(ifaceSub.complete).mockReset();
490
469
  });
491
470
  afterEach(() => {
492
471
  vi.useRealTimers();
@@ -494,102 +473,107 @@ describe(Store, () => {
494
473
  describe("mode=force", () => {
495
474
  it("initial load", async () => {
496
475
  defer(cache.observeList({
497
- objectType: Employee,
498
- where: {},
476
+ type: Employee,
499
477
  orderBy: {},
500
478
  mode: "force"
501
479
  }, listSub1));
480
+ defer(cache.observeList({
481
+ type: FooInterface,
482
+ orderBy: {},
483
+ mode: "force"
484
+ }, ifaceSub));
502
485
  vitest.runOnlyPendingTimers();
503
- await vi.waitFor(() => expect(listSub1).toHaveBeenCalled());
504
- expect(listSub1).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
505
- status: "loading",
506
- resolvedList: []
507
- }));
508
- listSub1.mockClear();
509
- await vi.waitFor(() => expect(listSub1).toHaveBeenCalled());
510
- expect(listSub1).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
511
- resolvedList: employeesAsServerReturns,
486
+ await waitForCall(listSub1);
487
+ await waitForCall(ifaceSub);
488
+ expectSingleListCallAndClear(listSub1, [], {
489
+ status: "loading"
490
+ });
491
+ expectSingleListCallAndClear(ifaceSub, [], {
492
+ status: "loading"
493
+ });
494
+ await waitForCall(listSub1);
495
+ expectSingleListCallAndClear(listSub1, employeesAsServerReturns, {
512
496
  status: "loaded"
513
- }));
497
+ });
498
+ await waitForCall(ifaceSub);
499
+ expectSingleListCallAndClear(ifaceSub, employeesAsServerReturns.filter(o => o.$primaryKey === 50050), {
500
+ status: "loaded"
501
+ });
502
+ expectNoMoreCalls(listSub1);
503
+ expectNoMoreCalls(ifaceSub);
504
+ expect(listSub1.next).not.toHaveBeenCalled();
505
+ expect(listSub1.error).not.toHaveBeenCalled();
506
+ expect(ifaceSub.next).not.toHaveBeenCalled();
507
+ expect(ifaceSub.error).not.toHaveBeenCalled();
514
508
  });
515
509
  it("subsequent load", async () => {
516
510
  // Pre-seed with data the server doesn't return
517
- cache.updateList({
518
- objectType: Employee,
511
+ updateList(cache, {
512
+ type: Employee,
519
513
  where: {},
520
514
  orderBy: {}
521
515
  }, mutatedEmployees);
522
516
  defer(cache.observeList({
523
- objectType: Employee,
517
+ type: Employee,
524
518
  mode: "force"
525
519
  }, listSub1));
526
520
  await waitForCall(listSub1, 1);
527
- const firstLoad = listSub1.mock.calls[0][0];
521
+ const firstLoad = listSub1.next.mock.calls[0][0];
528
522
  expectSingleListCallAndClear(listSub1, mutatedEmployees, {
529
523
  status: "loading"
530
524
  });
531
- await vi.waitFor(() => expect(listSub1).toHaveBeenCalled());
532
- expect(listSub1).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
533
- resolvedList: employeesAsServerReturns,
525
+ await waitForCall(listSub1, 1);
526
+ expectSingleListCallAndClear(listSub1, employeesAsServerReturns, {
534
527
  status: "loaded",
535
528
  lastUpdated: expect.toBeGreaterThan(firstLoad.lastUpdated)
536
- }));
537
- listSub1.mockClear();
529
+ });
538
530
  });
539
531
  });
540
532
  describe("mode = offline", () => {
541
533
  it("updates with list updates", async () => {
542
534
  defer(cache.observeList({
543
- objectType: Employee,
535
+ type: Employee,
544
536
  where: {},
545
537
  orderBy: {},
546
538
  mode: "offline"
547
539
  }, listSub1));
548
- expect(listSub1).toHaveBeenCalledTimes(0);
549
- cache.updateList({
550
- objectType: Employee,
540
+ expect(listSub1.next).toHaveBeenCalledTimes(0);
541
+ updateList(cache, {
542
+ type: Employee,
551
543
  where: {},
552
544
  orderBy: {}
553
545
  }, employeesAsServerReturns);
554
546
  vitest.runOnlyPendingTimers();
555
- expect(listSub1).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
556
- resolvedList: employeesAsServerReturns
557
- }));
558
- listSub1.mockClear();
547
+ expectSingleListCallAndClear(listSub1, employeesAsServerReturns);
559
548
 
560
549
  // list is just now one object
561
- cache.updateList({
562
- objectType: Employee,
550
+ updateList(cache, {
551
+ type: Employee,
563
552
  where: {},
564
553
  orderBy: {}
565
554
  }, [employeesAsServerReturns[0]]);
566
555
  vitest.runOnlyPendingTimers();
567
- expect(listSub1).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
568
- resolvedList: [employeesAsServerReturns[0]]
569
- }));
556
+ expectSingleListCallAndClear(listSub1, [employeesAsServerReturns[0]]);
570
557
  });
571
558
  it("updates with different list updates", async () => {
572
559
  defer(cache.observeList({
573
- objectType: Employee,
560
+ type: Employee,
574
561
  where: {},
575
562
  orderBy: {},
576
563
  mode: "offline"
577
564
  }, listSub1));
578
- expect(listSub1).toHaveBeenCalledTimes(0);
579
- cache.updateList({
580
- objectType: Employee,
565
+ expect(listSub1.next).toHaveBeenCalledTimes(0);
566
+ updateList(cache, {
567
+ type: Employee,
581
568
  where: {},
582
569
  orderBy: {}
583
570
  }, employeesAsServerReturns);
584
571
  vitest.runOnlyPendingTimers();
585
- expect(listSub1).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
586
- resolvedList: employeesAsServerReturns
587
- }));
588
- listSub1.mockClear();
572
+ expectSingleListCallAndClear(listSub1, employeesAsServerReturns);
589
573
 
590
574
  // new where === different list
591
- cache.updateList({
592
- objectType: Employee,
575
+ updateList(cache, {
576
+ type: Employee,
593
577
  where: {
594
578
  employeeId: {
595
579
  $gt: 0
@@ -600,9 +584,7 @@ describe(Store, () => {
600
584
  vitest.runOnlyPendingTimers();
601
585
 
602
586
  // original list updates still
603
- expect(listSub1).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
604
- resolvedList: mutatedEmployees
605
- }));
587
+ expectSingleListCallAndClear(listSub1, mutatedEmployees);
606
588
  });
607
589
  });
608
590
  });
@@ -616,39 +598,33 @@ describe(Store, () => {
616
598
  it("works in the solo case", async () => {
617
599
  const listSub = mockListSubCallback();
618
600
  defer(cache.observeList({
619
- objectType: Employee,
601
+ type: Employee,
620
602
  where: {},
621
603
  orderBy: {},
622
604
  mode: "force",
623
605
  pageSize: 1
624
606
  }, listSub));
625
- expect(listSub).not.toHaveBeenCalled();
626
- await vi.waitFor(() => expect(listSub).toHaveBeenCalled());
627
- expect(listSub).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
607
+ expect(listSub.next).not.toHaveBeenCalled();
608
+ await waitForCall(listSub, 1);
609
+ expectSingleListCallAndClear(listSub, [], {
628
610
  status: "loading"
629
- }));
630
- listSub.mockClear();
631
- await vi.waitFor(() => expect(listSub).toHaveBeenCalled());
632
- expect(listSub).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
633
- resolvedList: employeesAsServerReturns.slice(0, 1),
634
- status: "loaded"
635
- }));
611
+ });
612
+ await waitForCall(listSub, 1);
636
613
  const {
637
614
  fetchMore
638
- } = listSub.mock.calls[0][0];
639
- listSub.mockClear();
615
+ } = listSub.next.mock.calls[0][0];
616
+ expectSingleListCallAndClear(listSub, employeesAsServerReturns.slice(0, 1), {
617
+ status: "loaded"
618
+ });
640
619
  void fetchMore();
641
- await vi.waitFor(() => expect(listSub).toHaveBeenCalledTimes(1));
642
- expect(listSub).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
643
- resolvedList: employeesAsServerReturns.slice(0, 1),
620
+ await waitForCall(listSub, 1);
621
+ expectSingleListCallAndClear(listSub, employeesAsServerReturns.slice(0, 1), {
644
622
  status: "loading"
645
- }));
646
- listSub.mockClear();
647
- await vi.waitFor(() => expect(listSub).toHaveBeenCalledTimes(1));
648
- expect(listSub).toHaveBeenCalledWith(listPayloadContaining({
649
- resolvedList: employeesAsServerReturns.slice(0, 2),
623
+ });
624
+ await waitForCall(listSub, 1);
625
+ expectSingleListCallAndClear(listSub, employeesAsServerReturns.slice(0, 2), {
650
626
  status: "loaded"
651
- }));
627
+ });
652
628
  });
653
629
  });
654
630
  });
@@ -661,11 +637,25 @@ describe(Store, () => {
661
637
  client = mockClient.client;
662
638
  store = new Store(client);
663
639
  });
640
+ it("properly fires error handler for a list", async () => {
641
+ const error = new Error("A faux error");
642
+ mockClient.mockFetchPageOnce().reject(error);
643
+ const sub = mockListSubCallback();
644
+ store.observeList({
645
+ type: Employee,
646
+ where: {},
647
+ orderBy: {}
648
+ }, sub);
649
+ await waitForCall(sub.error, 1);
650
+ expect(sub.error).toHaveBeenCalled();
651
+ expect(sub.next).not.toHaveBeenCalled();
652
+ });
664
653
  describe("actions", () => {
665
654
  it("properly invalidates objects", async () => {
666
655
  // after the below `observeObject`, the cache will need to load from the server
667
656
  mockClient.mockFetchOneOnce().resolve({
668
- $apiName: "Todo"
657
+ $apiName: "Todo",
658
+ $primaryKey: 0
669
659
  });
670
660
  const todoSubFn = mockSingleSubCallback();
671
661
  defer(store.observeObject(Todo, 0, {}, todoSubFn));
@@ -690,15 +680,14 @@ describe(Store, () => {
690
680
  });
691
681
 
692
682
  // after we apply the action, the object is invalidated and gets re-requested
693
-
694
683
  mockClient.mockFetchOneOnce().resolve({
684
+ $primaryKey: 0,
695
685
  $apiName: "Todo",
696
686
  text: "hello there kind sir"
697
687
  });
698
- const actionPromise = store.applyAction(createOffice, {
688
+ await store.applyAction(createOffice, {
699
689
  officeId: "whatever"
700
690
  });
701
- await actionPromise;
702
691
  await todoSubFn.expectLoadingAndLoaded({
703
692
  loading: objectPayloadContaining({
704
693
  status: "loading"
@@ -748,7 +737,7 @@ describe(Store, () => {
748
737
  }
749
738
  });
750
739
  await waitForCall(todoSubFn, 1);
751
- expect(todoSubFn).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
740
+ expect(todoSubFn.next).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
752
741
  object: {
753
742
  ...fauxObject,
754
743
  text: "optimistic"
@@ -756,7 +745,7 @@ describe(Store, () => {
756
745
  status: "loading",
757
746
  isOptimistic: true
758
747
  }));
759
- todoSubFn.mockClear();
748
+ todoSubFn.next.mockClear();
760
749
 
761
750
  // let the action error out
762
751
  applyActionResult.reject("an error thrown");
@@ -764,43 +753,72 @@ describe(Store, () => {
764
753
 
765
754
  // back to the original object
766
755
  await waitForCall(todoSubFn, 1);
767
- expect(todoSubFn).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
756
+ expect(todoSubFn.next).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
768
757
  object: fauxObject,
769
758
  status: "loaded",
770
759
  isOptimistic: false
771
760
  }));
772
761
  });
773
762
  });
774
- describe("orderBy", () => {
763
+ describe("orderBy", async () => {
764
+ const ontologyProvider = {
765
+ getObjectDefinition: async () => {
766
+ return {
767
+ ...wireObjectTypeFullMetadataToSdkObjectMetadata(stubData.todoWithLinkTypes, true),
768
+ [InterfaceDefinitions]: {}
769
+ };
770
+ },
771
+ getActionDefinition() {
772
+ throw new Error("not implemented");
773
+ },
774
+ getInterfaceDefinition() {
775
+ throw new Error("not implemented");
776
+ },
777
+ getQueryDefinition() {
778
+ throw new Error("not implemented");
779
+ }
780
+ };
781
+ const minimalClient = createMinimalClient({
782
+ ontologyRid: "ri.whatever"
783
+ }, "https://localhost:8080", () => Promise.resolve("token"), {
784
+ logger
785
+ }, fetch, createObjectSet, () => () => ontologyProvider);
786
+ async function createObject(type, x) {
787
+ return (await minimalClient.objectFactory2(minimalClient, [{
788
+ ...x,
789
+ $apiName: type.apiName,
790
+ $objectType: type.apiName,
791
+ $objectSpecifier: `${type.apiName}:${x.$primaryKey}`
792
+ }], undefined))[0];
793
+ }
775
794
  let nextPk = 0;
776
- const fauxObjectA = {
777
- $apiName: "Todo",
778
- $objectType: "Todo",
779
- $primaryKey: nextPk++,
795
+ const fauxObjectA = await createObject(Todo, {
796
+ $primaryKey: nextPk,
780
797
  $title: "a",
798
+ id: nextPk,
781
799
  text: "a"
782
- };
783
- const fauxObjectB = {
784
- $apiName: "Todo",
785
- $objectType: "Todo",
786
- $primaryKey: nextPk++,
800
+ });
801
+ nextPk++;
802
+ const fauxObjectB = await createObject(Todo, {
803
+ $primaryKey: nextPk,
787
804
  $title: "b",
805
+ id: nextPk,
788
806
  text: "b"
789
- };
790
- const fauxObjectC = {
791
- $apiName: "Todo",
792
- $objectType: "Todo",
793
- $primaryKey: nextPk++,
807
+ });
808
+ nextPk++;
809
+ const fauxObjectC = await createObject(Todo, {
810
+ $primaryKey: nextPk,
794
811
  $title: "c",
812
+ id: nextPk,
795
813
  text: "c"
796
- };
814
+ });
797
815
  const noWhereNoOrderBy = {
798
- objectType: Todo,
816
+ type: Todo,
799
817
  where: {},
800
818
  orderBy: {}
801
819
  };
802
820
  const noWhereOrderByText = {
803
- objectType: Todo,
821
+ type: Todo,
804
822
  where: {},
805
823
  orderBy: {
806
824
  text: "asc"
@@ -813,16 +831,16 @@ describe(Store, () => {
813
831
  ...noWhereNoOrderBy,
814
832
  mode: "offline"
815
833
  }, subListUnordered));
816
- expect(subListUnordered).toHaveBeenCalledTimes(0);
834
+ expect(subListUnordered.next).toHaveBeenCalledTimes(0);
817
835
  defer(store.observeList({
818
836
  ...noWhereOrderByText,
819
837
  mode: "offline"
820
838
  }, subListOrdered));
821
- expect(subListOrdered).toHaveBeenCalledTimes(0);
839
+ expect(subListOrdered.next).toHaveBeenCalledTimes(0);
822
840
  });
823
841
  it("invalidates the correct lists", async () => {
824
842
  // for whatever reason, the first list is loaded as [B, A]
825
- store.updateList(noWhereNoOrderBy, [fauxObjectB, fauxObjectA]);
843
+ updateList(store, noWhereNoOrderBy, [fauxObjectB, fauxObjectA]);
826
844
  await waitForCall(subListUnordered, 1);
827
845
  expectSingleListCallAndClear(subListUnordered, [fauxObjectB, fauxObjectA]);
828
846
 
@@ -833,8 +851,8 @@ describe(Store, () => {
833
851
 
834
852
  // For whatever reason, object B is no longer in the first set (use your imagination)
835
853
  // but we have added a C before A. So the first list is [C, A]
836
- store.updateList({
837
- objectType: Todo,
854
+ updateList(store, {
855
+ type: Todo,
838
856
  where: {},
839
857
  orderBy: {}
840
858
  }, [fauxObjectC, fauxObjectA]);
@@ -847,22 +865,20 @@ describe(Store, () => {
847
865
  expectSingleListCallAndClear(subListOrdered, [fauxObjectA, fauxObjectB, fauxObjectC]);
848
866
  });
849
867
  it("produces proper results with optimistic updates and successful action", async () => {
850
- const optimisticallyMutatedA = {
868
+ const optimisticallyMutatedA = await createObject(Todo, {
851
869
  ...fauxObjectA,
852
870
  text: "optimistic"
853
- };
871
+ });
854
872
  const pkForOptimistic = nextPk++;
855
- const optimisticallyCreatedObjectD = {
856
- "$apiName": "Todo",
857
- "$objectType": "Todo",
873
+ const optimisticallyCreatedObjectD = await createObject(Todo, {
858
874
  "$primaryKey": pkForOptimistic,
859
875
  "$title": "d",
860
876
  "text": "d",
861
877
  id: pkForOptimistic
862
- };
878
+ });
863
879
 
864
880
  // for whatever reason, the first list is loaded as [B, A]
865
- store.updateList(noWhereNoOrderBy, [fauxObjectB, fauxObjectA]);
881
+ updateList(store, noWhereNoOrderBy, [fauxObjectB, fauxObjectA]);
866
882
  await waitForCall(subListUnordered, 1);
867
883
  expectSingleListCallAndClear(subListUnordered, [fauxObjectB, fauxObjectA]);
868
884
 
@@ -917,32 +933,28 @@ describe(Store, () => {
917
933
  // I think these are named backwards
918
934
  it("produces proper results with optimistic updates and rollback", async () => {
919
935
  const pkForOptimistic = nextPk++;
920
- const optimisticallyCreatedObjectD = {
921
- "$apiName": "Todo",
922
- "$objectType": "Todo",
936
+ const optimisticallyCreatedObjectD = await createObject(Todo, {
923
937
  "$primaryKey": pkForOptimistic,
924
938
  "$title": "d",
925
939
  "text": "d",
926
940
  id: pkForOptimistic
927
- };
928
- const optimisticallyMutatedA = {
941
+ });
942
+ const optimisticallyMutatedA = await createObject(Todo, {
929
943
  ...fauxObjectA,
930
944
  text: "optimistic"
931
- };
945
+ });
932
946
  testStage("Initial Setup");
933
947
 
934
948
  // later we will "create" this object
935
- const createdObjectD = {
936
- "$apiName": "Todo",
937
- "$objectType": "Todo",
949
+ const createdObjectD = await createObject(Todo, {
938
950
  "$primaryKey": 9000,
939
951
  "$title": "d prime",
940
952
  "text": "d prime",
941
953
  id: 9000
942
- };
954
+ });
943
955
 
944
956
  // for whatever reason, the first list is loaded as [B, A]
945
- store.updateList(noWhereNoOrderBy, [fauxObjectB, fauxObjectA]);
957
+ updateList(store, noWhereNoOrderBy, [fauxObjectB, fauxObjectA]);
946
958
  await waitForCall(subListUnordered, 1);
947
959
  expectSingleListCallAndClear(subListUnordered, [fauxObjectB, fauxObjectA]);
948
960
 
@@ -961,8 +973,8 @@ describe(Store, () => {
961
973
  officeId: "5"
962
974
  }, {
963
975
  optimisticUpdate: b => {
964
- b.createObject(Todo, pkForOptimistic, {
965
- id: pkForOptimistic,
976
+ b.createObject(Todo, optimisticallyCreatedObjectD.$primaryKey, {
977
+ id: optimisticallyCreatedObjectD.$primaryKey,
966
978
  text: "d"
967
979
  });
968
980
  b.updateObject(optimisticallyMutatedA);
@@ -978,16 +990,20 @@ describe(Store, () => {
978
990
  isOptimistic: true
979
991
  });
980
992
 
981
- // the second list is now [A, B, optimistic]
993
+ // the second list is now [B, optimistic, optimistic a]
982
994
  await waitForCall(subListOrdered, 1);
983
995
  expectSingleListCallAndClear(subListOrdered, [fauxObjectB, optimisticallyCreatedObjectD, optimisticallyMutatedA], {
984
996
  isOptimistic: true
985
997
  });
986
998
  testStage("Resolve Action");
987
- const modifiedObjectA = {
999
+ const modifiedObjectA = await createObject(Todo, {
988
1000
  ...fauxObjectA,
989
1001
  text: "a prime"
990
- };
1002
+ });
1003
+
1004
+ // console.log("winner?", modifiedObjectA.$as);
1005
+ // // throw "hi";
1006
+ // console.log("winner2?", modifiedObjectA.$as("Todo").$as);
991
1007
 
992
1008
  // The action will complete and then revalidate in order...
993
1009
  mockClient.mockFetchOneOnce(modifiedObjectA.$primaryKey).resolve(modifiedObjectA);
@@ -1023,6 +1039,7 @@ describe(Store, () => {
1023
1039
 
1024
1040
  await actionPromise;
1025
1041
  await waitForCall(subListUnordered, 1);
1042
+ console.log("=====", subListUnordered.next.mock.calls[0][0]);
1026
1043
  expectSingleListCallAndClear(subListUnordered, [fauxObjectB,
1027
1044
  // fauxObjectC,
1028
1045
  modifiedObjectA, createdObjectD], {
@@ -1049,12 +1066,12 @@ describe(Store, () => {
1049
1066
 
1050
1067
  // set the truth
1051
1068
  for (const obj of baseObjects) {
1052
- store.updateObject("Employee", obj);
1069
+ updateObject(store, obj);
1053
1070
  }
1054
1071
 
1055
1072
  // expect the truth
1056
1073
  for (const obj of baseObjects) {
1057
- expect(store.getObject("Employee", obj.$primaryKey)).toEqual(expect.objectContaining({
1074
+ expect(getObject(store, "Employee", obj.$primaryKey)).toEqual(expect.objectContaining({
1058
1075
  $title: `truth ${obj.$primaryKey}`
1059
1076
  }));
1060
1077
  }
@@ -1074,7 +1091,7 @@ describe(Store, () => {
1074
1091
 
1075
1092
  // expect the optimistic values
1076
1093
  for (let i = 0; i < 2; i++) {
1077
- expect(store.getObject("Employee", baseObjects[i].$primaryKey)).toEqual(expect.objectContaining({
1094
+ expect(getObject(store, "Employee", baseObjects[i].$primaryKey)).toEqual(expect.objectContaining({
1078
1095
  $title: `optimistic ${baseObjects[i].$primaryKey}`
1079
1096
  }));
1080
1097
  }
@@ -1083,10 +1100,10 @@ describe(Store, () => {
1083
1100
  store.removeLayer(layerIds[0]);
1084
1101
 
1085
1102
  // should have truth object 1 and optimistic object 2
1086
- expect(store.getObject("Employee", 1)).toEqual(expect.objectContaining({
1103
+ expect(getObject(store, "Employee", 1)).toEqual(expect.objectContaining({
1087
1104
  $title: "truth 1"
1088
1105
  }));
1089
- expect(store.getObject("Employee", 2)).toEqual(expect.objectContaining({
1106
+ expect(getObject(store, "Employee", 2)).toEqual(expect.objectContaining({
1090
1107
  $title: "optimistic 2"
1091
1108
  }));
1092
1109
 
@@ -1095,7 +1112,7 @@ describe(Store, () => {
1095
1112
 
1096
1113
  // should have truth objects
1097
1114
  for (const obj of baseObjects) {
1098
- expect(store.getObject("Employee", obj.$primaryKey)).toEqual(expect.objectContaining({
1115
+ expect(getObject(store, "Employee", obj.$primaryKey)).toEqual(expect.objectContaining({
1099
1116
  $title: `truth ${obj.$primaryKey}`
1100
1117
  }));
1101
1118
  }