@osdk/client 2.2.0-beta.2 → 2.2.0-beta.20

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 (483) hide show
  1. package/CHANGELOG.md +269 -0
  2. package/build/browser/Client.js.map +1 -1
  3. package/build/browser/MinimalClientContext.js.map +1 -1
  4. package/build/browser/__unstable/ConjureSupport.js.map +1 -1
  5. package/build/browser/actions/ActionValidationError.js +1 -1
  6. package/build/browser/actions/ActionValidationError.js.map +1 -1
  7. package/build/browser/actions/actions.test.js +226 -87
  8. package/build/browser/actions/actions.test.js.map +1 -1
  9. package/build/browser/actions/applyAction.js +28 -16
  10. package/build/browser/actions/applyAction.js.map +1 -1
  11. package/build/browser/createClient.js +19 -8
  12. package/build/browser/createClient.js.map +1 -1
  13. package/build/browser/createClient.test.js +14 -6
  14. package/build/browser/createClient.test.js.map +1 -1
  15. package/build/browser/createMinimalClient.js +2 -2
  16. package/build/browser/createMinimalClient.js.map +1 -1
  17. package/build/browser/createMinimalClientHelper.js +25 -0
  18. package/build/browser/createMinimalClientHelper.js.map +1 -0
  19. package/build/browser/derivedProperties/createWithPropertiesObjectSet.js +36 -13
  20. package/build/browser/derivedProperties/createWithPropertiesObjectSet.js.map +1 -1
  21. package/build/browser/derivedProperties/createWithPropertiesObjectSet.test.js +133 -0
  22. package/build/browser/derivedProperties/createWithPropertiesObjectSet.test.js.map +1 -1
  23. package/build/browser/derivedProperties/derivedPropertyDefinitionFactory.js +94 -0
  24. package/build/browser/derivedProperties/derivedPropertyDefinitionFactory.js.map +1 -0
  25. package/build/browser/fetchMetadata.test.js +11 -9
  26. package/build/browser/fetchMetadata.test.js.map +1 -1
  27. package/build/browser/index.js +1 -0
  28. package/build/browser/index.js.map +1 -1
  29. package/build/browser/intellisense.test.helpers/showsObjectPropertyJsdoc.js +25 -0
  30. package/build/browser/intellisense.test.helpers/showsObjectPropertyJsdoc.js.map +1 -0
  31. package/build/browser/intellisense.test.js +17 -1
  32. package/build/browser/intellisense.test.js.map +1 -1
  33. package/build/browser/internal/conversions/modernToLegacyGroupByClause.js +7 -0
  34. package/build/browser/internal/conversions/modernToLegacyGroupByClause.js.map +1 -1
  35. package/build/browser/internal/conversions/modernToLegacyWhereClause.js +1 -1
  36. package/build/browser/internal/conversions/modernToLegacyWhereClause.js.map +1 -1
  37. package/build/browser/logger/BaseLogger.js +59 -0
  38. package/build/browser/logger/BaseLogger.js.map +1 -0
  39. package/build/browser/logger/BrowserLogger.js +67 -0
  40. package/build/browser/logger/BrowserLogger.js.map +1 -0
  41. package/build/browser/logger/MinimalLogger.js +39 -0
  42. package/build/browser/logger/MinimalLogger.js.map +1 -0
  43. package/build/browser/logger/MinimalLogger.test.js +60 -0
  44. package/build/browser/logger/MinimalLogger.test.js.map +1 -0
  45. package/build/browser/logger/TestLogger.js +56 -0
  46. package/build/browser/logger/TestLogger.js.map +1 -0
  47. package/build/browser/object/AttachmentUpload.js +3 -0
  48. package/build/browser/object/AttachmentUpload.js.map +1 -1
  49. package/build/browser/object/SimpleOsdkProperties.js +2 -0
  50. package/build/browser/object/SimpleOsdkProperties.js.map +1 -0
  51. package/build/browser/object/aggregate.test.js +12 -2
  52. package/build/browser/object/aggregate.test.js.map +1 -1
  53. package/build/browser/object/attachment.test.js +20 -7
  54. package/build/browser/object/attachment.test.js.map +1 -1
  55. package/build/browser/object/convertWireToOsdkObjects/BaseHolder.js +2 -0
  56. package/build/browser/object/convertWireToOsdkObjects/BaseHolder.js.map +1 -0
  57. package/build/browser/object/convertWireToOsdkObjects/InterfaceHolder.js.map +1 -1
  58. package/build/browser/object/convertWireToOsdkObjects/ObjectHolder.js.map +1 -1
  59. package/build/browser/object/convertWireToOsdkObjects/createOsdkInterface.js +29 -0
  60. package/build/browser/object/convertWireToOsdkObjects/createOsdkInterface.js.map +1 -1
  61. package/build/browser/object/convertWireToOsdkObjects/createOsdkObject.js +53 -35
  62. package/build/browser/object/convertWireToOsdkObjects/createOsdkObject.js.map +1 -1
  63. package/build/browser/object/convertWireToOsdkObjects/getDollarAs.js.map +1 -1
  64. package/build/browser/object/convertWireToOsdkObjects/getDollarLink.js.map +1 -1
  65. package/build/browser/object/convertWireToOsdkObjects.js +10 -11
  66. package/build/browser/object/convertWireToOsdkObjects.js.map +1 -1
  67. package/build/browser/object/convertWireToOsdkObjects.test.js +46 -36
  68. package/build/browser/object/convertWireToOsdkObjects.test.js.map +1 -1
  69. package/build/browser/object/fetchPage.js +17 -4
  70. package/build/browser/object/fetchPage.js.map +1 -1
  71. package/build/browser/object/fetchPage.test.js +56 -2
  72. package/build/browser/object/fetchPage.test.js.map +1 -1
  73. package/build/browser/object/geotimeseriesreference.test.js +56 -134
  74. package/build/browser/object/geotimeseriesreference.test.js.map +1 -1
  75. package/build/browser/object/media.test.js +19 -14
  76. package/build/browser/object/media.test.js.map +1 -1
  77. package/build/browser/object/object.test.js +182 -66
  78. package/build/browser/object/object.test.js.map +1 -1
  79. package/build/browser/object/timeseries.test.js +119 -85
  80. package/build/browser/object/timeseries.test.js.map +1 -1
  81. package/build/browser/objectSet/InterfaceObjectSet.test.js +37 -17
  82. package/build/browser/objectSet/InterfaceObjectSet.test.js.map +1 -1
  83. package/build/browser/objectSet/ObjectSet.test.js +212 -114
  84. package/build/browser/objectSet/ObjectSet.test.js.map +1 -1
  85. package/build/browser/objectSet/ObjectSetListenerWebsocket.js +20 -16
  86. package/build/browser/objectSet/ObjectSetListenerWebsocket.js.map +1 -1
  87. package/build/browser/objectSet/ObjectSetListenerWebsocket.test.js +21 -12
  88. package/build/browser/objectSet/ObjectSetListenerWebsocket.test.js.map +1 -1
  89. package/build/browser/objectSet/createObjectSet.js +2 -1
  90. package/build/browser/objectSet/createObjectSet.js.map +1 -1
  91. package/build/browser/observable/ListPayload.js.map +1 -1
  92. package/build/browser/observable/ObjectPayload.js.map +1 -1
  93. package/build/browser/observable/ObservableClient.js.map +1 -1
  94. package/build/browser/observable/OptimisticBuilder.js.map +1 -1
  95. package/build/browser/observable/internal/ActionApplication.js +102 -0
  96. package/build/browser/observable/internal/ActionApplication.js.map +1 -0
  97. package/build/browser/observable/internal/BulkObjectLoader.js +93 -0
  98. package/build/browser/observable/internal/BulkObjectLoader.js.map +1 -0
  99. package/build/browser/observable/internal/BulkObjectLoader.test.js +112 -0
  100. package/build/browser/observable/internal/BulkObjectLoader.test.js.map +1 -0
  101. package/build/browser/observable/internal/CacheKey.js +38 -1
  102. package/build/browser/observable/internal/CacheKey.js.map +1 -1
  103. package/build/browser/observable/internal/CacheKeys.js +4 -4
  104. package/build/browser/observable/internal/CacheKeys.js.map +1 -1
  105. package/build/browser/observable/internal/Changes.js +58 -0
  106. package/build/browser/observable/internal/Changes.js.map +1 -0
  107. package/build/browser/observable/internal/Layer.js +6 -3
  108. package/build/browser/observable/internal/Layer.js.map +1 -1
  109. package/build/browser/observable/internal/ListQuery.js +495 -129
  110. package/build/browser/observable/internal/ListQuery.js.map +1 -1
  111. package/build/browser/observable/internal/ObjectQuery.js +40 -14
  112. package/build/browser/observable/internal/ObjectQuery.js.map +1 -1
  113. package/build/browser/observable/internal/ObservableClientImpl.js +4 -12
  114. package/build/browser/observable/internal/ObservableClientImpl.js.map +1 -1
  115. package/build/browser/observable/internal/OptimisticJob.js +30 -29
  116. package/build/browser/observable/internal/OptimisticJob.js.map +1 -1
  117. package/build/browser/observable/internal/OrderByCanonicalizer.js +73 -0
  118. package/build/browser/observable/internal/OrderByCanonicalizer.js.map +1 -0
  119. package/build/browser/observable/internal/OrderByCanonicalizer.test.js +78 -0
  120. package/build/browser/observable/internal/OrderByCanonicalizer.test.js.map +1 -0
  121. package/build/browser/observable/internal/Query.js +79 -6
  122. package/build/browser/observable/internal/Query.js.map +1 -1
  123. package/build/browser/observable/internal/RefCounts.js +7 -2
  124. package/build/browser/observable/internal/RefCounts.js.map +1 -1
  125. package/build/browser/observable/internal/SimpleWhereClause.js +2 -0
  126. package/build/browser/observable/internal/SimpleWhereClause.js.map +1 -0
  127. package/build/browser/observable/internal/Store.js +140 -190
  128. package/build/browser/observable/internal/Store.js.map +1 -1
  129. package/build/browser/observable/internal/Store.test.js +666 -300
  130. package/build/browser/observable/internal/Store.test.js.map +1 -1
  131. package/build/browser/observable/internal/WhereClauseCanonicalizer.js +11 -3
  132. package/build/browser/observable/internal/WhereClauseCanonicalizer.js.map +1 -1
  133. package/build/browser/observable/internal/objectMatchesWhereClause.js +0 -4
  134. package/build/browser/observable/internal/objectMatchesWhereClause.js.map +1 -1
  135. package/build/browser/observable/internal/objectMatchesWhereClause.test.js.map +1 -1
  136. package/build/browser/observable/internal/testUtils.js +222 -19
  137. package/build/browser/observable/internal/testUtils.js.map +1 -1
  138. package/build/browser/ontology/StandardOntologyProvider.test.js +17 -16
  139. package/build/browser/ontology/StandardOntologyProvider.test.js.map +1 -1
  140. package/build/browser/ontology/loadFullObjectMetadata.js +0 -1
  141. package/build/browser/ontology/loadFullObjectMetadata.js.map +1 -1
  142. package/build/browser/public/internal.js +2 -0
  143. package/build/browser/public/internal.js.map +1 -1
  144. package/build/browser/public/unstable-do-not-use.js +1 -0
  145. package/build/browser/public/unstable-do-not-use.js.map +1 -1
  146. package/build/browser/public-utils/osdkConfig.js +49 -0
  147. package/build/browser/public-utils/osdkConfig.js.map +1 -0
  148. package/build/{esm/observable/internal/ChangedObjects.js → browser/public-utils/vite-env.d.ts} +2 -7
  149. package/build/browser/queries/applyQuery.js +34 -2
  150. package/build/browser/queries/applyQuery.js.map +1 -1
  151. package/build/browser/queries/queries.test.js +36 -13
  152. package/build/browser/queries/queries.test.js.map +1 -1
  153. package/build/browser/queries/types.js.map +1 -1
  154. package/build/browser/tsserver.js.map +1 -1
  155. package/build/browser/util/UserAgent.js +1 -1
  156. package/build/browser/util/UserAgent.js.map +1 -1
  157. package/build/browser/util/extractRdpDefinition.js +140 -0
  158. package/build/browser/util/extractRdpDefinition.js.map +1 -0
  159. package/build/browser/util/extractRdpDefinition.test.js +233 -0
  160. package/build/browser/util/extractRdpDefinition.test.js.map +1 -0
  161. package/build/browser/{observable/internal/ChangedObjects.js → util/isPoint.js} +3 -7
  162. package/build/browser/util/isPoint.js.map +1 -0
  163. package/build/browser/util/objectSpecifierUtils.js +48 -0
  164. package/build/browser/util/objectSpecifierUtils.js.map +1 -0
  165. package/build/browser/util/objectSpecifierUtils.test.js +42 -0
  166. package/build/browser/util/objectSpecifierUtils.test.js.map +1 -0
  167. package/build/browser/util/toDataValue.js +14 -2
  168. package/build/browser/util/toDataValue.js.map +1 -1
  169. package/build/browser/util/toDataValue.test.js +37 -16
  170. package/build/browser/util/toDataValue.test.js.map +1 -1
  171. package/build/browser/util/toDataValueQueries.js +25 -2
  172. package/build/browser/util/toDataValueQueries.js.map +1 -1
  173. package/build/cjs/{Client-C8K3E1vH.d.cts → Client-CgL2LKN9.d.cts} +7 -8
  174. package/build/cjs/{chunk-T5UE6BI7.cjs → chunk-33GHS3X4.cjs} +256 -80
  175. package/build/cjs/chunk-33GHS3X4.cjs.map +1 -0
  176. package/build/cjs/{chunk-X7WGNFZ4.cjs → chunk-37QC7LR3.cjs} +173 -34
  177. package/build/cjs/chunk-37QC7LR3.cjs.map +1 -0
  178. package/build/cjs/chunk-T4NIFYZS.cjs +14 -0
  179. package/build/cjs/chunk-T4NIFYZS.cjs.map +1 -0
  180. package/build/cjs/index.cjs +298 -177
  181. package/build/cjs/index.cjs.map +1 -1
  182. package/build/cjs/index.d.cts +14 -22
  183. package/build/cjs/public/internal.cjs +61 -7
  184. package/build/cjs/public/internal.cjs.map +1 -1
  185. package/build/cjs/public/internal.d.cts +50 -3
  186. package/build/cjs/public/unstable-do-not-use.cjs +1181 -527
  187. package/build/cjs/public/unstable-do-not-use.cjs.map +1 -1
  188. package/build/cjs/public/unstable-do-not-use.d.cts +44 -25
  189. package/build/esm/Client.js.map +1 -1
  190. package/build/esm/MinimalClientContext.js.map +1 -1
  191. package/build/esm/__unstable/ConjureSupport.js.map +1 -1
  192. package/build/esm/actions/ActionValidationError.js +1 -1
  193. package/build/esm/actions/ActionValidationError.js.map +1 -1
  194. package/build/esm/actions/actions.test.js +226 -87
  195. package/build/esm/actions/actions.test.js.map +1 -1
  196. package/build/esm/actions/applyAction.js +28 -16
  197. package/build/esm/actions/applyAction.js.map +1 -1
  198. package/build/esm/createClient.js +19 -8
  199. package/build/esm/createClient.js.map +1 -1
  200. package/build/esm/createClient.test.js +14 -6
  201. package/build/esm/createClient.test.js.map +1 -1
  202. package/build/esm/createMinimalClient.js +2 -2
  203. package/build/esm/createMinimalClient.js.map +1 -1
  204. package/build/esm/createMinimalClientHelper.js +25 -0
  205. package/build/esm/createMinimalClientHelper.js.map +1 -0
  206. package/build/esm/derivedProperties/createWithPropertiesObjectSet.js +36 -13
  207. package/build/esm/derivedProperties/createWithPropertiesObjectSet.js.map +1 -1
  208. package/build/esm/derivedProperties/createWithPropertiesObjectSet.test.js +133 -0
  209. package/build/esm/derivedProperties/createWithPropertiesObjectSet.test.js.map +1 -1
  210. package/build/esm/derivedProperties/derivedPropertyDefinitionFactory.js +94 -0
  211. package/build/esm/derivedProperties/derivedPropertyDefinitionFactory.js.map +1 -0
  212. package/build/esm/fetchMetadata.test.js +11 -9
  213. package/build/esm/fetchMetadata.test.js.map +1 -1
  214. package/build/esm/index.js +1 -0
  215. package/build/esm/index.js.map +1 -1
  216. package/build/esm/intellisense.test.helpers/showsObjectPropertyJsdoc.js +25 -0
  217. package/build/esm/intellisense.test.helpers/showsObjectPropertyJsdoc.js.map +1 -0
  218. package/build/esm/intellisense.test.js +17 -1
  219. package/build/esm/intellisense.test.js.map +1 -1
  220. package/build/esm/internal/conversions/modernToLegacyGroupByClause.js +7 -0
  221. package/build/esm/internal/conversions/modernToLegacyGroupByClause.js.map +1 -1
  222. package/build/esm/internal/conversions/modernToLegacyWhereClause.js +1 -1
  223. package/build/esm/internal/conversions/modernToLegacyWhereClause.js.map +1 -1
  224. package/build/esm/logger/BaseLogger.js +59 -0
  225. package/build/esm/logger/BaseLogger.js.map +1 -0
  226. package/build/esm/logger/BrowserLogger.js +67 -0
  227. package/build/esm/logger/BrowserLogger.js.map +1 -0
  228. package/build/esm/logger/MinimalLogger.js +39 -0
  229. package/build/esm/logger/MinimalLogger.js.map +1 -0
  230. package/build/esm/logger/MinimalLogger.test.js +60 -0
  231. package/build/esm/logger/MinimalLogger.test.js.map +1 -0
  232. package/build/esm/logger/TestLogger.js +56 -0
  233. package/build/esm/logger/TestLogger.js.map +1 -0
  234. package/build/esm/object/AttachmentUpload.js +3 -0
  235. package/build/esm/object/AttachmentUpload.js.map +1 -1
  236. package/build/esm/object/SimpleOsdkProperties.js +2 -0
  237. package/build/esm/object/SimpleOsdkProperties.js.map +1 -0
  238. package/build/esm/object/aggregate.test.js +12 -2
  239. package/build/esm/object/aggregate.test.js.map +1 -1
  240. package/build/esm/object/attachment.test.js +20 -7
  241. package/build/esm/object/attachment.test.js.map +1 -1
  242. package/build/esm/object/convertWireToOsdkObjects/BaseHolder.js +2 -0
  243. package/build/esm/object/convertWireToOsdkObjects/BaseHolder.js.map +1 -0
  244. package/build/esm/object/convertWireToOsdkObjects/InterfaceHolder.js.map +1 -1
  245. package/build/esm/object/convertWireToOsdkObjects/ObjectHolder.js.map +1 -1
  246. package/build/esm/object/convertWireToOsdkObjects/createOsdkInterface.js +29 -0
  247. package/build/esm/object/convertWireToOsdkObjects/createOsdkInterface.js.map +1 -1
  248. package/build/esm/object/convertWireToOsdkObjects/createOsdkObject.js +53 -35
  249. package/build/esm/object/convertWireToOsdkObjects/createOsdkObject.js.map +1 -1
  250. package/build/esm/object/convertWireToOsdkObjects/getDollarAs.js.map +1 -1
  251. package/build/esm/object/convertWireToOsdkObjects/getDollarLink.js.map +1 -1
  252. package/build/esm/object/convertWireToOsdkObjects.js +10 -11
  253. package/build/esm/object/convertWireToOsdkObjects.js.map +1 -1
  254. package/build/esm/object/convertWireToOsdkObjects.test.js +46 -36
  255. package/build/esm/object/convertWireToOsdkObjects.test.js.map +1 -1
  256. package/build/esm/object/fetchPage.js +17 -4
  257. package/build/esm/object/fetchPage.js.map +1 -1
  258. package/build/esm/object/fetchPage.test.js +56 -2
  259. package/build/esm/object/fetchPage.test.js.map +1 -1
  260. package/build/esm/object/geotimeseriesreference.test.js +56 -134
  261. package/build/esm/object/geotimeseriesreference.test.js.map +1 -1
  262. package/build/esm/object/media.test.js +19 -14
  263. package/build/esm/object/media.test.js.map +1 -1
  264. package/build/esm/object/object.test.js +182 -66
  265. package/build/esm/object/object.test.js.map +1 -1
  266. package/build/esm/object/timeseries.test.js +119 -85
  267. package/build/esm/object/timeseries.test.js.map +1 -1
  268. package/build/esm/objectSet/InterfaceObjectSet.test.js +37 -17
  269. package/build/esm/objectSet/InterfaceObjectSet.test.js.map +1 -1
  270. package/build/esm/objectSet/ObjectSet.test.js +212 -114
  271. package/build/esm/objectSet/ObjectSet.test.js.map +1 -1
  272. package/build/esm/objectSet/ObjectSetListenerWebsocket.js +20 -16
  273. package/build/esm/objectSet/ObjectSetListenerWebsocket.js.map +1 -1
  274. package/build/esm/objectSet/ObjectSetListenerWebsocket.test.js +21 -12
  275. package/build/esm/objectSet/ObjectSetListenerWebsocket.test.js.map +1 -1
  276. package/build/esm/objectSet/createObjectSet.js +2 -1
  277. package/build/esm/objectSet/createObjectSet.js.map +1 -1
  278. package/build/esm/observable/ListPayload.js.map +1 -1
  279. package/build/esm/observable/ObjectPayload.js.map +1 -1
  280. package/build/esm/observable/ObservableClient.js.map +1 -1
  281. package/build/esm/observable/OptimisticBuilder.js.map +1 -1
  282. package/build/esm/observable/internal/ActionApplication.js +102 -0
  283. package/build/esm/observable/internal/ActionApplication.js.map +1 -0
  284. package/build/esm/observable/internal/BulkObjectLoader.js +93 -0
  285. package/build/esm/observable/internal/BulkObjectLoader.js.map +1 -0
  286. package/build/esm/observable/internal/BulkObjectLoader.test.js +112 -0
  287. package/build/esm/observable/internal/BulkObjectLoader.test.js.map +1 -0
  288. package/build/esm/observable/internal/CacheKey.js +38 -1
  289. package/build/esm/observable/internal/CacheKey.js.map +1 -1
  290. package/build/esm/observable/internal/CacheKeys.js +4 -4
  291. package/build/esm/observable/internal/CacheKeys.js.map +1 -1
  292. package/build/esm/observable/internal/Changes.js +58 -0
  293. package/build/esm/observable/internal/Changes.js.map +1 -0
  294. package/build/esm/observable/internal/Layer.js +6 -3
  295. package/build/esm/observable/internal/Layer.js.map +1 -1
  296. package/build/esm/observable/internal/ListQuery.js +495 -129
  297. package/build/esm/observable/internal/ListQuery.js.map +1 -1
  298. package/build/esm/observable/internal/ObjectQuery.js +40 -14
  299. package/build/esm/observable/internal/ObjectQuery.js.map +1 -1
  300. package/build/esm/observable/internal/ObservableClientImpl.js +4 -12
  301. package/build/esm/observable/internal/ObservableClientImpl.js.map +1 -1
  302. package/build/esm/observable/internal/OptimisticJob.js +30 -29
  303. package/build/esm/observable/internal/OptimisticJob.js.map +1 -1
  304. package/build/esm/observable/internal/OrderByCanonicalizer.js +73 -0
  305. package/build/esm/observable/internal/OrderByCanonicalizer.js.map +1 -0
  306. package/build/esm/observable/internal/OrderByCanonicalizer.test.js +78 -0
  307. package/build/esm/observable/internal/OrderByCanonicalizer.test.js.map +1 -0
  308. package/build/esm/observable/internal/Query.js +79 -6
  309. package/build/esm/observable/internal/Query.js.map +1 -1
  310. package/build/esm/observable/internal/RefCounts.js +7 -2
  311. package/build/esm/observable/internal/RefCounts.js.map +1 -1
  312. package/build/esm/observable/internal/SimpleWhereClause.js +2 -0
  313. package/build/esm/observable/internal/SimpleWhereClause.js.map +1 -0
  314. package/build/esm/observable/internal/Store.js +140 -190
  315. package/build/esm/observable/internal/Store.js.map +1 -1
  316. package/build/esm/observable/internal/Store.test.js +666 -300
  317. package/build/esm/observable/internal/Store.test.js.map +1 -1
  318. package/build/esm/observable/internal/WhereClauseCanonicalizer.js +11 -3
  319. package/build/esm/observable/internal/WhereClauseCanonicalizer.js.map +1 -1
  320. package/build/esm/observable/internal/objectMatchesWhereClause.js +0 -4
  321. package/build/esm/observable/internal/objectMatchesWhereClause.js.map +1 -1
  322. package/build/esm/observable/internal/objectMatchesWhereClause.test.js.map +1 -1
  323. package/build/esm/observable/internal/testUtils.js +222 -19
  324. package/build/esm/observable/internal/testUtils.js.map +1 -1
  325. package/build/esm/ontology/StandardOntologyProvider.test.js +17 -16
  326. package/build/esm/ontology/StandardOntologyProvider.test.js.map +1 -1
  327. package/build/esm/ontology/loadFullObjectMetadata.js +0 -1
  328. package/build/esm/ontology/loadFullObjectMetadata.js.map +1 -1
  329. package/build/esm/public/internal.js +2 -0
  330. package/build/esm/public/internal.js.map +1 -1
  331. package/build/esm/public/unstable-do-not-use.js +1 -0
  332. package/build/esm/public/unstable-do-not-use.js.map +1 -1
  333. package/build/esm/public-utils/osdkConfig.js +49 -0
  334. package/build/esm/public-utils/osdkConfig.js.map +1 -0
  335. package/build/esm/public-utils/vite-env.d.ts +19 -0
  336. package/build/esm/queries/applyQuery.js +34 -2
  337. package/build/esm/queries/applyQuery.js.map +1 -1
  338. package/build/esm/queries/queries.test.js +36 -13
  339. package/build/esm/queries/queries.test.js.map +1 -1
  340. package/build/esm/queries/types.js.map +1 -1
  341. package/build/esm/tsserver.js.map +1 -1
  342. package/build/esm/util/UserAgent.js +1 -1
  343. package/build/esm/util/UserAgent.js.map +1 -1
  344. package/build/esm/util/extractRdpDefinition.js +140 -0
  345. package/build/esm/util/extractRdpDefinition.js.map +1 -0
  346. package/build/esm/util/extractRdpDefinition.test.js +233 -0
  347. package/build/esm/util/extractRdpDefinition.test.js.map +1 -0
  348. package/build/esm/util/isPoint.js +20 -0
  349. package/build/esm/util/isPoint.js.map +1 -0
  350. package/build/esm/util/objectSpecifierUtils.js +48 -0
  351. package/build/esm/util/objectSpecifierUtils.js.map +1 -0
  352. package/build/esm/util/objectSpecifierUtils.test.js +42 -0
  353. package/build/esm/util/objectSpecifierUtils.test.js.map +1 -0
  354. package/build/esm/util/toDataValue.js +14 -2
  355. package/build/esm/util/toDataValue.js.map +1 -1
  356. package/build/esm/util/toDataValue.test.js +37 -16
  357. package/build/esm/util/toDataValue.test.js.map +1 -1
  358. package/build/esm/util/toDataValueQueries.js +25 -2
  359. package/build/esm/util/toDataValueQueries.js.map +1 -1
  360. package/build/types/Client.d.ts +1 -1
  361. package/build/types/Client.d.ts.map +1 -1
  362. package/build/types/MinimalClientContext.d.ts +1 -1
  363. package/build/types/MinimalClientContext.d.ts.map +1 -1
  364. package/build/types/__unstable/ConjureSupport.d.ts +2 -2
  365. package/build/types/actions/applyAction.d.ts +1 -2
  366. package/build/types/actions/applyAction.d.ts.map +1 -1
  367. package/build/types/createClient.d.ts +1 -1
  368. package/build/types/createClient.d.ts.map +1 -1
  369. package/build/types/createClient.test.d.ts +2 -1
  370. package/build/types/createClient.test.d.ts.map +1 -1
  371. package/build/types/createMinimalClientHelper.d.ts +1 -0
  372. package/build/types/createMinimalClientHelper.d.ts.map +1 -0
  373. package/build/types/derivedProperties/derivedPropertyDefinitionFactory.d.ts +1 -0
  374. package/build/types/derivedProperties/derivedPropertyDefinitionFactory.d.ts.map +1 -0
  375. package/build/types/index.d.ts +5 -5
  376. package/build/types/index.d.ts.map +1 -1
  377. package/build/types/intellisense.test.helpers/showsObjectPropertyJsdoc.d.ts +1 -0
  378. package/build/types/intellisense.test.helpers/showsObjectPropertyJsdoc.d.ts.map +1 -0
  379. package/build/types/logger/BaseLogger.d.ts +33 -0
  380. package/build/types/logger/BaseLogger.d.ts.map +1 -0
  381. package/build/types/logger/BrowserLogger.d.ts +9 -0
  382. package/build/types/logger/BrowserLogger.d.ts.map +1 -0
  383. package/build/types/logger/MinimalLogger.d.ts +9 -0
  384. package/build/types/logger/MinimalLogger.d.ts.map +1 -0
  385. package/build/types/logger/MinimalLogger.test.d.ts +1 -0
  386. package/build/types/logger/MinimalLogger.test.d.ts.map +1 -0
  387. package/build/types/logger/TestLogger.d.ts +14 -0
  388. package/build/types/logger/TestLogger.d.ts.map +1 -0
  389. package/build/types/object/AttachmentUpload.d.ts +3 -0
  390. package/build/types/object/AttachmentUpload.d.ts.map +1 -1
  391. package/build/types/object/SimpleOsdkProperties.d.ts +1 -0
  392. package/build/types/object/SimpleOsdkProperties.d.ts.map +1 -0
  393. package/build/types/object/convertWireToOsdkObjects/BaseHolder.d.ts +1 -0
  394. package/build/types/object/convertWireToOsdkObjects/BaseHolder.d.ts.map +1 -0
  395. package/build/types/object/convertWireToOsdkObjects.d.ts +8 -1
  396. package/build/types/object/convertWireToOsdkObjects.d.ts.map +1 -1
  397. package/build/types/object/fetchPage.d.ts.map +1 -1
  398. package/build/types/object/object.test.d.ts.map +1 -1
  399. package/build/types/objectSet/ObjectSet.test.d.ts.map +1 -1
  400. package/build/types/observable/ListPayload.d.ts +5 -9
  401. package/build/types/observable/ListPayload.d.ts.map +1 -1
  402. package/build/types/observable/ObjectPayload.d.ts +4 -7
  403. package/build/types/observable/ObjectPayload.d.ts.map +1 -1
  404. package/build/types/observable/ObservableClient.d.ts +33 -10
  405. package/build/types/observable/ObservableClient.d.ts.map +1 -1
  406. package/build/types/observable/OptimisticBuilder.d.ts +1 -1
  407. package/build/types/observable/OptimisticBuilder.d.ts.map +1 -1
  408. package/build/types/observable/internal/ActionApplication.d.ts +9 -0
  409. package/build/types/observable/internal/ActionApplication.d.ts.map +1 -0
  410. package/build/types/observable/internal/BulkObjectLoader.d.ts +8 -0
  411. package/build/types/observable/internal/BulkObjectLoader.d.ts.map +1 -0
  412. package/build/types/observable/internal/BulkObjectLoader.test.d.ts +1 -0
  413. package/build/types/observable/internal/BulkObjectLoader.test.d.ts.map +1 -0
  414. package/build/types/observable/internal/CacheKeys.d.ts +2 -1
  415. package/build/types/observable/internal/CacheKeys.d.ts.map +1 -1
  416. package/build/types/observable/internal/Changes.d.ts +15 -0
  417. package/build/types/observable/internal/Changes.d.ts.map +1 -0
  418. package/build/types/observable/internal/Layer.d.ts +2 -1
  419. package/build/types/observable/internal/Layer.d.ts.map +1 -1
  420. package/build/types/observable/internal/ListQuery.d.ts +69 -23
  421. package/build/types/observable/internal/ListQuery.d.ts.map +1 -1
  422. package/build/types/observable/internal/ObjectQuery.d.ts +8 -9
  423. package/build/types/observable/internal/ObjectQuery.d.ts.map +1 -1
  424. package/build/types/observable/internal/OptimisticJob.d.ts +2 -2
  425. package/build/types/observable/internal/OptimisticJob.d.ts.map +1 -1
  426. package/build/types/observable/internal/OrderByCanonicalizer.d.ts +12 -0
  427. package/build/types/observable/internal/OrderByCanonicalizer.d.ts.map +1 -0
  428. package/build/types/observable/internal/OrderByCanonicalizer.test.d.ts +1 -0
  429. package/build/types/observable/internal/OrderByCanonicalizer.test.d.ts.map +1 -0
  430. package/build/types/observable/internal/Query.d.ts +45 -9
  431. package/build/types/observable/internal/Query.d.ts.map +1 -1
  432. package/build/types/observable/internal/RefCounts.d.ts.map +1 -1
  433. package/build/types/observable/internal/SimpleWhereClause.d.ts +2 -0
  434. package/build/types/observable/internal/SimpleWhereClause.d.ts.map +1 -0
  435. package/build/types/observable/internal/Store.d.ts +34 -30
  436. package/build/types/observable/internal/Store.d.ts.map +1 -1
  437. package/build/types/observable/internal/WhereClauseCanonicalizer.d.ts +2 -1
  438. package/build/types/observable/internal/WhereClauseCanonicalizer.d.ts.map +1 -1
  439. package/build/types/observable/internal/objectMatchesWhereClause.d.ts +4 -2
  440. package/build/types/observable/internal/objectMatchesWhereClause.d.ts.map +1 -1
  441. package/build/types/observable/internal/testUtils.d.ts +48 -9
  442. package/build/types/observable/internal/testUtils.d.ts.map +1 -1
  443. package/build/types/public/internal.d.ts +2 -0
  444. package/build/types/public/internal.d.ts.map +1 -1
  445. package/build/types/public/unstable-do-not-use.d.ts +4 -5
  446. package/build/types/public/unstable-do-not-use.d.ts.map +1 -1
  447. package/build/types/public-utils/osdkConfig.d.ts +8 -0
  448. package/build/types/public-utils/osdkConfig.d.ts.map +1 -0
  449. package/build/types/public-utils/vite-env.d.d.ts +3 -0
  450. package/build/types/public-utils/vite-env.d.d.ts.map +1 -0
  451. package/build/types/queries/applyQuery.d.ts +4 -2
  452. package/build/types/queries/applyQuery.d.ts.map +1 -1
  453. package/build/types/queries/types.d.ts +1 -1
  454. package/build/types/queries/types.d.ts.map +1 -1
  455. package/build/types/tsserver.d.ts +1 -1
  456. package/build/types/tsserver.d.ts.map +1 -1
  457. package/build/types/util/extractRdpDefinition.d.ts +4 -0
  458. package/build/types/util/extractRdpDefinition.d.ts.map +1 -0
  459. package/build/types/util/extractRdpDefinition.test.d.ts +1 -0
  460. package/build/types/util/extractRdpDefinition.test.d.ts.map +1 -0
  461. package/build/types/util/isPoint.d.ts +1 -0
  462. package/build/types/util/isPoint.d.ts.map +1 -0
  463. package/build/types/util/objectSpecifierUtils.d.ts +24 -0
  464. package/build/types/util/objectSpecifierUtils.d.ts.map +1 -0
  465. package/build/types/util/objectSpecifierUtils.test.d.ts +1 -0
  466. package/build/types/util/objectSpecifierUtils.test.d.ts.map +1 -0
  467. package/package.json +20 -16
  468. package/build/browser/Logger.js +0 -2
  469. package/build/browser/Logger.js.map +0 -1
  470. package/build/browser/observable/internal/ChangedObjects.js.map +0 -1
  471. package/build/cjs/chunk-Q7SFCCGT.cjs +0 -11
  472. package/build/cjs/chunk-Q7SFCCGT.cjs.map +0 -1
  473. package/build/cjs/chunk-T5UE6BI7.cjs.map +0 -1
  474. package/build/cjs/chunk-X7WGNFZ4.cjs.map +0 -1
  475. package/build/cjs/graphql-JJX5MZPQ.cjs +0 -10491
  476. package/build/cjs/graphql-JJX5MZPQ.cjs.map +0 -1
  477. package/build/esm/Logger.js +0 -2
  478. package/build/esm/Logger.js.map +0 -1
  479. package/build/esm/observable/internal/ChangedObjects.js.map +0 -1
  480. package/build/types/Logger.d.ts +0 -18
  481. package/build/types/Logger.d.ts.map +0 -1
  482. package/build/types/observable/internal/ChangedObjects.d.ts +0 -7
  483. package/build/types/observable/internal/ChangedObjects.d.ts.map +0 -1
@@ -14,14 +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 { editTodo, Employee, FooInterface, Todo } from "@osdk/client.test.ontology";
18
+ import { ActionTypeBuilder, FauxFoundry, ontologies, startNodeApiServer, stubData } from "@osdk/shared.test";
19
+ import chalk from "chalk";
20
+ import invariant from "tiny-invariant";
19
21
  import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi, vitest } from "vitest";
22
+ import { ActionValidationError } from "../../actions/ActionValidationError.js";
20
23
  import { createClient } from "../../createClient.js";
24
+ import { TestLogger } from "../../logger/TestLogger.js";
21
25
  import { createOptimisticId } from "./OptimisticId.js";
22
- import { Store } from "./Store.js";
23
- import { applyCustomMatchers, createClientMockHelper, createDefer, expectSingleListCallAndClear, expectSingleObjectCallAndClear, listPayloadContaining, mockListSubCallback, mockSingleSubCallback, objectPayloadContaining, waitForCall } from "./testUtils.js";
26
+ import { runOptimisticJob } from "./OptimisticJob.js";
27
+ import { invalidateList, Store } from "./Store.js";
28
+ import { applyCustomMatchers, createClientMockHelper, createDefer, expectNoMoreCalls, expectSingleListCallAndClear, expectSingleObjectCallAndClear, getObject, mockListSubCallback, mockSingleSubCallback, objectPayloadContaining, updateList, updateObject, waitForCall } from "./testUtils.js";
29
+ const JOHN_DOE_ID = 50030;
24
30
  const defer = createDefer();
31
+ const logger = new TestLogger();
25
32
  beforeAll(() => {
26
33
  vi.setConfig({
27
34
  fakeTimers: {
@@ -38,7 +45,56 @@ const ANY_INIT_ENTRY = {
38
45
  lastUpdated: 0,
39
46
  status: "init"
40
47
  };
48
+
49
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
50
+ function fullTaskName(task) {
51
+ return task ? `${fullTaskName(task.suite)} > ${task.name}` : "";
52
+ }
53
+ beforeEach(x => {
54
+ console.log(chalk.bgRed(chalk.white(fullTaskName(x.task))));
55
+ });
56
+
57
+ // helper method to make debugging tests easier
58
+ function testStage(s) {
59
+ console.log(chalk.bgYellow(`Test Stage: ${s}`));
60
+ }
41
61
  applyCustomMatchers();
62
+ function setupOntology(fauxFoundry) {
63
+ const fauxOntology = fauxFoundry.getDefaultOntology();
64
+ ontologies.addEmployeeOntology(fauxOntology);
65
+ fauxFoundry.getDefaultOntology().registerObjectType(stubData.todoWithLinkTypes);
66
+ fauxFoundry.getDefaultOntology().registerActionType(stubData.editTodo.actionTypeV2, (b, payload) => {
67
+ const {
68
+ id,
69
+ ...other
70
+ } = payload.parameters;
71
+ b.modifyObject(Todo.apiName, id, {
72
+ ...other
73
+ });
74
+ });
75
+ }
76
+ function setupSomeEmployees(fauxFoundry) {
77
+ const dataStore = fauxFoundry.getDefaultDataStore();
78
+ dataStore.registerObject(Employee, {
79
+ employeeId: 1
80
+ });
81
+ dataStore.registerObject(Employee, {
82
+ employeeId: 2
83
+ });
84
+ dataStore.registerObject(Employee, {
85
+ $apiName: "Employee",
86
+ employeeId: 3
87
+ });
88
+ dataStore.registerObject(Employee, {
89
+ $apiName: "Employee",
90
+ employeeId: 4
91
+ });
92
+ dataStore.registerObject(Employee, {
93
+ $apiName: "Employee",
94
+ employeeId: JOHN_DOE_ID,
95
+ fullName: "John Doe"
96
+ });
97
+ }
42
98
  describe(Store, () => {
43
99
  describe("with mock server", () => {
44
100
  let client;
@@ -46,44 +102,51 @@ describe(Store, () => {
46
102
  let employeesAsServerReturns;
47
103
  let mutatedEmployees;
48
104
  beforeAll(async () => {
49
- apiServer.listen();
50
- client = createClient("https://stack.palantir.com", $ontologyRid, async () => "myAccessToken");
105
+ const testSetup = startNodeApiServer(new FauxFoundry("https://stack.palantir.com/"), createClient, {
106
+ logger
107
+ });
108
+ ({
109
+ client
110
+ } = testSetup);
111
+ setupOntology(testSetup.fauxFoundry);
112
+ setupSomeEmployees(testSetup.fauxFoundry);
51
113
  employeesAsServerReturns = (await client(Employee).fetchPage()).data;
52
114
  mutatedEmployees = [employeesAsServerReturns[0], employeesAsServerReturns[1].$clone({
53
115
  fullName: "foo"
54
116
  }), ...employeesAsServerReturns.slice(2)];
55
- });
56
- afterAll(() => {
57
- apiServer.close();
117
+ return () => {
118
+ testSetup.apiServer.close();
119
+ };
58
120
  });
59
121
  beforeEach(() => {
60
122
  cache = new Store(client);
61
- });
62
- afterEach(() => {
63
- cache = undefined;
123
+ return () => {
124
+ cache = undefined;
125
+ };
64
126
  });
65
127
  it("basic single object works", async () => {
66
128
  const emp = employeesAsServerReturns[0];
129
+ const cacheKey = cache.getCacheKey("object", "Employee", emp.$primaryKey);
67
130
 
68
131
  // starts empty
69
- expect(cache.getObject(Employee, emp.$primaryKey)).toBeUndefined();
70
- const result = cache.updateObject(Employee, emp);
132
+ expect(cache.getValue(cacheKey)?.value).toBeUndefined();
133
+ const result = updateObject(cache, emp);
71
134
  expect(emp).toBe(result);
72
135
 
73
136
  // getting the object now matches the result
74
- expect(cache.getObject(Employee, emp.$primaryKey)).toEqual(result);
75
- const updatedEmpFromCache = cache.updateObject(Employee, emp.$clone({
137
+ expect(cache.getValue(cacheKey)?.value).toEqual(result);
138
+ const updatedEmpFromCache = updateObject(cache, emp.$clone({
76
139
  fullName: "new name"
77
140
  }));
78
141
  expect(updatedEmpFromCache).not.toBe(emp);
79
142
 
80
143
  // getting it again is the updated object
81
- expect(cache.getObject(Employee, emp.$primaryKey)).toEqual(updatedEmpFromCache);
144
+ expect(cache.getValue(cacheKey)?.value).toEqual(updatedEmpFromCache);
82
145
  });
83
146
  describe("optimistic updates", () => {
84
147
  it("rolls back objects", async () => {
85
148
  const emp = employeesAsServerReturns[0];
86
- cache.updateObject(Employee, emp); // pre-seed the cache with the "real" value
149
+ updateObject(cache, emp); // pre-seed the cache with the "real" value
87
150
 
88
151
  const subFn = mockSingleSubCallback();
89
152
  defer(cache.observeObject(Employee, emp.$primaryKey, {
@@ -92,7 +155,7 @@ describe(Store, () => {
92
155
  expectSingleObjectCallAndClear(subFn, emp, "loaded");
93
156
  const optimisticId = createOptimisticId();
94
157
  // update with an optimistic write
95
- cache.updateObject(Employee, emp.$clone({
158
+ updateObject(cache, emp.$clone({
96
159
  fullName: "new name"
97
160
  }), {
98
161
  optimisticId
@@ -106,10 +169,12 @@ describe(Store, () => {
106
169
  expectSingleObjectCallAndClear(subFn, emp, "loaded");
107
170
  });
108
171
  it("rolls back to an updated real value", async () => {
109
- vi.useFakeTimers();
110
-
111
172
  // pre-seed the cache with the "real" value
112
- cache.updateList(Employee, {}, employeesAsServerReturns);
173
+ updateList(cache, {
174
+ type: Employee,
175
+ where: {},
176
+ orderBy: {}
177
+ }, employeesAsServerReturns);
113
178
  const emp = employeesAsServerReturns[0];
114
179
  const empSubFn = mockSingleSubCallback();
115
180
  defer(cache.observeObject(Employee, emp.$primaryKey, {
@@ -117,88 +182,90 @@ describe(Store, () => {
117
182
  }, empSubFn));
118
183
  expectSingleObjectCallAndClear(empSubFn, emp, "loaded");
119
184
  const listSubFn = mockListSubCallback();
120
- defer(cache.observeList(Employee, {}, {
185
+ defer(cache.observeList({
186
+ type: Employee,
121
187
  mode: "offline"
122
188
  }, listSubFn));
189
+ await waitForCall(listSubFn, 1);
123
190
  expectSingleListCallAndClear(listSubFn, employeesAsServerReturns);
124
191
  const optimisticEmployee = emp.$clone({
125
192
  fullName: "new name"
126
193
  });
127
194
  const optimisticId = createOptimisticId();
195
+ testStage("optimistic update");
196
+ expect(listSubFn.next).not.toHaveBeenCalled();
128
197
 
129
198
  // update with an optimistic write
130
- cache.updateObject(Employee, optimisticEmployee, {
199
+ updateObject(cache, optimisticEmployee, {
131
200
  optimisticId
132
201
  });
202
+ testStage("after optimistic update");
133
203
 
134
204
  // expect optimistic write
135
205
  expectSingleObjectCallAndClear(empSubFn, optimisticEmployee);
136
206
 
137
207
  // expect optimistic write to the list
138
- expectSingleListCallAndClear(listSubFn, [optimisticEmployee, ...employeesAsServerReturns.slice(1)]);
208
+ await waitForCall(listSubFn, 1);
209
+ expectSingleListCallAndClear(listSubFn, [optimisticEmployee, ...employeesAsServerReturns.slice(1)], {
210
+ isOptimistic: true,
211
+ status: "loading"
212
+ });
139
213
 
140
214
  // write the real update, via the earlier list definition
141
215
  const truthUpdatedEmployee = emp.$clone({
142
216
  fullName: "real update"
143
217
  });
144
- cache.updateList(Employee, {}, [truthUpdatedEmployee]);
145
-
146
- // we shouldn't expect an update because the top layer has a value
147
- expect(empSubFn).not.toHaveBeenCalled();
148
-
149
- // we do get an update to the list but we still see the optimistic value
150
- // for the object
151
- expectSingleListCallAndClear(listSubFn, [optimisticEmployee]);
218
+ testStage("write real update");
219
+ updateList(cache, {
220
+ type: Employee,
221
+ where: {},
222
+ orderBy: {}
223
+ }, [truthUpdatedEmployee]);
152
224
 
153
225
  // remove the optimistic write
154
226
  cache.removeLayer(optimisticId);
155
227
 
156
228
  // see the object observation get updated
157
- expectSingleObjectCallAndClear(empSubFn, truthUpdatedEmployee);
229
+ expectSingleObjectCallAndClear(empSubFn, truthUpdatedEmployee, "loaded");
158
230
 
159
231
  // see the list get updated
160
- expectSingleListCallAndClear(listSubFn, [truthUpdatedEmployee]);
161
- vi.useRealTimers();
232
+ await waitForCall(listSubFn, 1);
233
+ expectSingleListCallAndClear(listSubFn, [truthUpdatedEmployee], {
234
+ status: "loaded",
235
+ isOptimistic: false
236
+ });
162
237
  });
163
238
  it("rolls back to an updated real value via list", async () => {
164
239
  const emp = employeesAsServerReturns[0];
165
- cache.updateObject(Employee, emp); // pre-seed the cache with the "real" value
240
+ updateObject(cache, emp); // pre-seed the cache with the "real" value
166
241
 
167
242
  const subFn = mockSingleSubCallback();
168
243
  defer(cache.observeObject(Employee, emp.$primaryKey, {
169
244
  mode: "offline"
170
245
  }, subFn));
171
- expect(subFn).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
172
- object: emp,
173
- status: "loaded"
174
- }));
175
- subFn.mockClear();
246
+ expectSingleObjectCallAndClear(subFn, emp, "loaded");
176
247
  const optimisticEmployee = emp.$clone({
177
248
  fullName: "new name"
178
249
  });
179
250
 
180
251
  // update with an optimistic write
181
252
  const optimisticId = createOptimisticId();
182
- cache.updateObject(Employee, optimisticEmployee, {
253
+ updateObject(cache, optimisticEmployee, {
183
254
  optimisticId
184
255
  });
185
- expect(subFn).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
186
- object: optimisticEmployee
187
- }));
188
- subFn.mockClear();
256
+ expectSingleObjectCallAndClear(subFn, optimisticEmployee);
189
257
  const truthUpdatedEmployee = emp.$clone({
190
258
  fullName: "real update"
191
259
  });
192
- cache.updateObject(Employee, truthUpdatedEmployee);
260
+ updateObject(cache, truthUpdatedEmployee);
193
261
 
194
262
  // we shouldn't expect an update because the top layer has a value
195
- expect(subFn).not.toHaveBeenCalled();
263
+ expect(subFn.next).not.toHaveBeenCalled();
196
264
 
197
265
  // remove the optimistic write
198
266
  cache.removeLayer(optimisticId);
199
- expect(subFn).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
200
- object: truthUpdatedEmployee
201
- }));
267
+ expectSingleObjectCallAndClear(subFn, truthUpdatedEmployee);
268
+ expectNoMoreCalls(subFn);
202
269
  });
203
270
  });
204
271
  describe(".invalidateObject", () => {
@@ -207,29 +274,20 @@ describe(Store, () => {
207
274
  const staleEmp = emp.$clone({
208
275
  fullName: "stale"
209
276
  });
210
- cache.updateObject(Employee, staleEmp);
277
+ updateObject(cache, staleEmp);
211
278
  const subFn = mockSingleSubCallback();
212
279
  defer(cache.observeObject(Employee, emp.$primaryKey, {
213
280
  mode: "offline"
214
281
  }, subFn));
215
- expect(subFn).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
216
- object: staleEmp,
217
- status: "loaded"
218
- }));
219
- subFn.mockClear();
282
+ expectSingleObjectCallAndClear(subFn, staleEmp, "loaded");
220
283
 
221
284
  // invalidate
222
285
  void cache.invalidateObject(Employee, staleEmp.$primaryKey);
223
- await vi.waitFor(() => expect(subFn).toHaveBeenCalled());
224
- expect(subFn).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
225
- object: staleEmp,
226
- status: "loading"
227
- }));
228
- subFn.mockClear();
229
- await vi.waitFor(() => expect(subFn).toHaveBeenCalled());
230
- expect(subFn).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
231
- object: emp
232
- }));
286
+ await waitForCall(subFn);
287
+ expectSingleObjectCallAndClear(subFn, staleEmp, "loading");
288
+ await waitForCall(subFn);
289
+ expectSingleObjectCallAndClear(subFn, emp, "loaded");
290
+ expectNoMoreCalls(subFn);
233
291
  });
234
292
  });
235
293
  describe(".invalidateList", () => {
@@ -244,39 +302,43 @@ describe(Store, () => {
244
302
  const staleEmp = emp.$clone({
245
303
  fullName: "stale"
246
304
  });
247
- cache.updateList(Employee, {}, [staleEmp]);
305
+ updateList(cache, {
306
+ type: Employee,
307
+ where: {},
308
+ orderBy: {}
309
+ }, [staleEmp]);
248
310
  const subFn = mockSingleSubCallback();
249
311
  defer(cache.observeObject(Employee, emp.$primaryKey, {
250
312
  mode: "offline"
251
313
  }, subFn));
252
314
  expectSingleObjectCallAndClear(subFn, staleEmp);
253
315
  const subListFn = mockListSubCallback();
254
- defer(cache.observeList(Employee, {}, {
316
+ defer(cache.observeList({
317
+ type: Employee,
255
318
  mode: "offline"
256
319
  }, subListFn));
257
- await vi.waitFor(() => expect(subListFn).toHaveBeenCalled());
258
- expect(subListFn).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
259
- resolvedList: [staleEmp],
320
+ await waitForCall(subListFn, 1);
321
+ expectSingleListCallAndClear(subListFn, [staleEmp], {
260
322
  status: "loaded"
261
- }));
262
- subListFn.mockClear();
263
- cache.invalidateList(Employee, {});
264
- await vi.waitFor(() => expect(subListFn).toHaveBeenCalled());
265
- expect(subListFn).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
266
- resolvedList: [staleEmp],
323
+ });
324
+ testStage("invalidate");
325
+ const invalidateListPromise = invalidateList(cache, {
326
+ type: Employee
327
+ });
328
+ testStage("check invalidate");
329
+ await waitForCall(subListFn, 1);
330
+ expectSingleListCallAndClear(subListFn, [staleEmp], {
267
331
  status: "loading"
268
- }));
269
- subListFn.mockClear();
270
- await vi.waitFor(() => expect(subListFn).toHaveBeenCalled());
271
- expect(subListFn).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
272
- resolvedList: employeesAsServerReturns
273
- }));
274
- subListFn.mockClear();
275
- await vi.waitFor(() => expect(subFn).toHaveBeenCalled());
276
- expect(subFn).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
277
- status: "loaded",
278
- object: emp
279
- }));
332
+ });
333
+ await waitForCall(subListFn, 1);
334
+ expectSingleListCallAndClear(subListFn, employeesAsServerReturns, {
335
+ status: "loaded"
336
+ });
337
+ await waitForCall(subFn, 1);
338
+ expectSingleObjectCallAndClear(subFn, emp, "loaded");
339
+
340
+ // don't leave promises dangling
341
+ await invalidateListPromise;
280
342
  });
281
343
  });
282
344
  describe(".invalidateObjectType", () => {
@@ -291,92 +353,92 @@ describe(Store, () => {
291
353
  const staleEmp = emp.$clone({
292
354
  fullName: "stale"
293
355
  });
294
- cache.updateList(Employee, {}, [staleEmp]);
356
+ updateList(cache, {
357
+ type: Employee,
358
+ where: {},
359
+ orderBy: {}
360
+ }, [staleEmp]);
295
361
  const subFn = mockSingleSubCallback();
296
362
  defer(cache.observeObject(Employee, emp.$primaryKey, {
297
363
  mode: "offline"
298
364
  }, subFn));
299
365
  expectSingleObjectCallAndClear(subFn, staleEmp);
300
366
  const subListFn = mockListSubCallback();
301
- defer(cache.observeList(Employee, {}, {
367
+ defer(cache.observeList({
368
+ type: Employee,
369
+ where: {},
370
+ orderBy: {},
302
371
  mode: "offline"
303
372
  }, subListFn));
304
- await vi.waitFor(() => expect(subListFn).toHaveBeenCalled());
305
- expect(subListFn).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
306
- resolvedList: [staleEmp],
373
+ await waitForCall(subListFn, 1);
374
+ expectSingleListCallAndClear(subListFn, [staleEmp], {
307
375
  status: "loaded"
308
- }));
309
- subListFn.mockClear();
310
- cache.invalidateObjectType(Employee);
311
- await vi.waitFor(() => expect(subListFn).toHaveBeenCalled());
312
- expect(subListFn).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
313
- resolvedList: [staleEmp],
376
+ });
377
+ testStage("invalidate");
378
+ const pInvalidateComplete = cache.invalidateObjectType(Employee, undefined);
379
+ await waitForCall(subListFn, 1);
380
+ expectSingleListCallAndClear(subListFn, [staleEmp], {
314
381
  status: "loading"
315
- }));
316
- subListFn.mockClear();
317
- await vi.waitFor(() => expect(subListFn).toHaveBeenCalled());
318
- expect(subListFn).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
319
- resolvedList: employeesAsServerReturns
320
- }));
321
- subListFn.mockClear();
322
- await vi.waitFor(() => expect(subFn).toHaveBeenCalled());
323
- expect(subFn).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
324
- status: "loaded",
325
- object: emp
326
- }));
382
+ });
383
+ await waitForCall(subListFn, 1);
384
+ expectSingleListCallAndClear(subListFn, employeesAsServerReturns);
385
+ await waitForCall(subFn, 1);
386
+ expectSingleObjectCallAndClear(subFn, emp, "loaded");
387
+
388
+ // we don't need this value to control the test but we want to make sure we don't have
389
+ // any unhandled exceptions upon test completion
390
+ await pInvalidateComplete;
327
391
  });
328
392
  });
329
393
  describe(".observeObject (force)", () => {
330
394
  const subFn1 = mockSingleSubCallback();
331
395
  const subFn2 = mockSingleSubCallback();
332
396
  beforeEach(async () => {
333
- subFn1.mockClear();
334
- subFn2.mockClear();
397
+ subFn1.complete.mockClear();
398
+ subFn1.next.mockClear();
399
+ subFn1.error.mockClear();
400
+ subFn2.complete.mockClear();
401
+ subFn2.next.mockClear();
402
+ subFn2.error.mockClear();
335
403
  });
336
404
  const likeEmployee50030 = expect.objectContaining({
337
- $primaryKey: 50030,
405
+ $primaryKey: JOHN_DOE_ID,
338
406
  fullName: "John Doe"
339
407
  });
340
408
  it("fetches and updates twice", async () => {
341
- defer(cache.observeObject(Employee, 50030, {
409
+ defer(cache.observeObject(Employee, JOHN_DOE_ID, {
342
410
  mode: "force"
343
411
  }, subFn1));
344
- expect(subFn1).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
412
+ expect(subFn1.next).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
345
413
  status: "loading",
346
414
  object: undefined,
347
415
  isOptimistic: false
348
416
  }));
349
- subFn1.mockClear();
350
- await vi.waitFor(() => expect(subFn1).toHaveBeenCalled());
351
- expect(subFn1).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
417
+ subFn1.next.mockClear();
418
+ await waitForCall(subFn1);
419
+ expect(subFn1.next).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
352
420
  object: likeEmployee50030,
353
421
  isOptimistic: false
354
422
  }));
355
- const firstLoad = subFn1.mock.lastCall?.[0];
356
- subFn1.mockClear();
357
- defer(cache.observeObject(Employee, 50030, {
423
+ const firstLoad = subFn1.next.mock.lastCall?.[0];
424
+ subFn1.next.mockClear();
425
+ defer(cache.observeObject(Employee, JOHN_DOE_ID, {
358
426
  mode: "force"
359
427
  }, subFn2));
360
- expect(subFn1).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
361
- status: "loading"
362
- }));
363
- subFn1.mockClear();
428
+ expectSingleObjectCallAndClear(subFn1, likeEmployee50030, "loading");
364
429
 
365
430
  // should be the earlier results
366
- expect(subFn2).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
367
- status: "loading"
368
- }));
369
- subFn2.mockClear();
431
+ expectSingleObjectCallAndClear(subFn2, likeEmployee50030, "loading");
370
432
 
371
433
  // both will be updated
372
434
  for (const s of [subFn1, subFn2]) {
373
435
  // wait for the result to come in
374
- await vi.waitFor(() => expect(s).toHaveBeenCalled());
375
- expect(s).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
436
+ await waitForCall(s, 1);
437
+ expect(s.next).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
376
438
  ...firstLoad,
377
439
  lastUpdated: expect.toBeGreaterThan(firstLoad.lastUpdated)
378
440
  }));
379
- s.mockClear();
441
+ s.next.mockClear();
380
442
  }
381
443
  });
382
444
  });
@@ -384,152 +446,185 @@ describe(Store, () => {
384
446
  const subFn = mockSingleSubCallback();
385
447
  let sub;
386
448
  beforeEach(() => {
387
- subFn.mockClear();
388
- sub = defer(cache.observeObject(Employee, 50030, {
449
+ subFn.complete.mockClear();
450
+ subFn.next.mockClear();
451
+ subFn.error.mockClear();
452
+ sub = defer(cache.observeObject(Employee, JOHN_DOE_ID, {
389
453
  mode: "offline"
390
454
  }, subFn));
391
- expect(subFn).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
392
- status: "init",
393
- object: undefined
394
- }));
395
- subFn.mockClear();
455
+ expectSingleObjectCallAndClear(subFn, undefined, "init");
396
456
  });
397
457
  it("does basic observation and unsubscribe", async () => {
398
- const emp = employeesAsServerReturns[0];
458
+ const emp = employeesAsServerReturns.find(x => x.$primaryKey === JOHN_DOE_ID);
399
459
 
400
460
  // force an update
401
- cache.updateObject(Employee, emp);
402
- expect(subFn).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
403
- object: emp
404
- }));
405
- subFn.mockClear();
461
+ updateObject(cache, emp);
462
+ expectSingleObjectCallAndClear(subFn, emp);
406
463
 
407
464
  // force again
408
- cache.updateObject(Employee, emp.$clone({
465
+ updateObject(cache, emp.$clone({
409
466
  fullName: "new name"
410
467
  }));
411
- expect(subFn).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
412
- object: expect.objectContaining({
413
- fullName: "new name"
414
- })
468
+ expectSingleObjectCallAndClear(subFn, emp.$clone({
469
+ fullName: "new name"
415
470
  }));
416
- subFn.mockClear();
417
471
  sub.unsubscribe();
418
472
 
419
473
  // force again but no subscription update
420
- cache.updateObject(Employee, emp.$clone({
474
+ updateObject(cache, emp.$clone({
421
475
  fullName: "new name 2"
422
476
  }));
423
- expect(subFn).not.toHaveBeenCalled();
477
+ expect(subFn.next).not.toHaveBeenCalled();
424
478
  });
425
479
  it("observes with list update", async () => {
426
- const emp = employeesAsServerReturns[0];
480
+ const emp = employeesAsServerReturns.find(x => x.$primaryKey === JOHN_DOE_ID);
427
481
 
428
482
  // force an update
429
- cache.updateObject(Employee, emp.$clone({
483
+ updateObject(cache, emp.$clone({
430
484
  fullName: "not the name"
431
485
  }));
432
- expect(subFn).toHaveBeenCalledTimes(1);
433
- cache.updateList(Employee, {}, employeesAsServerReturns);
434
- expect(subFn).toHaveBeenCalledTimes(2);
435
- expect(subFn.mock.calls[1][0]).toEqual(objectPayloadContaining({
486
+ expect(subFn.next).toHaveBeenCalledTimes(1);
487
+ updateList(cache, {
488
+ type: Employee,
489
+ where: {},
490
+ orderBy: {}
491
+ }, employeesAsServerReturns);
492
+ expect(subFn.next).toHaveBeenCalledTimes(2);
493
+ expect(subFn.next.mock.calls[1][0]).toEqual(objectPayloadContaining({
436
494
  object: emp
437
495
  }));
438
496
  });
439
497
  });
440
498
  describe(".observeList", () => {
441
499
  const listSub1 = mockListSubCallback();
500
+ const ifaceSub = mockListSubCallback();
442
501
  beforeEach(() => {
443
502
  vi.useFakeTimers({});
444
- listSub1.mockReset();
503
+ vi.mocked(listSub1.next).mockReset();
504
+ vi.mocked(listSub1.error).mockReset();
505
+ vi.mocked(listSub1.complete).mockReset();
506
+ vi.mocked(ifaceSub.next).mockReset();
507
+ vi.mocked(ifaceSub.error).mockReset();
508
+ vi.mocked(ifaceSub.complete).mockReset();
445
509
  });
446
510
  afterEach(() => {
447
511
  vi.useRealTimers();
448
512
  });
449
513
  describe("mode=force", () => {
450
514
  it("initial load", async () => {
451
- defer(cache.observeList(Employee, {}, {
515
+ defer(cache.observeList({
516
+ type: Employee,
517
+ orderBy: {},
452
518
  mode: "force"
453
519
  }, listSub1));
520
+ defer(cache.observeList({
521
+ type: FooInterface,
522
+ orderBy: {},
523
+ mode: "force"
524
+ }, ifaceSub));
454
525
  vitest.runOnlyPendingTimers();
455
- await vi.waitFor(() => expect(listSub1).toHaveBeenCalled());
456
- expect(listSub1).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
457
- status: "loading",
458
- resolvedList: []
459
- }));
460
- listSub1.mockClear();
461
- await vi.waitFor(() => expect(listSub1).toHaveBeenCalled());
462
- expect(listSub1).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
463
- resolvedList: employeesAsServerReturns,
526
+ await waitForCall(listSub1);
527
+ await waitForCall(ifaceSub);
528
+ expectSingleListCallAndClear(listSub1, [], {
529
+ status: "loading"
530
+ });
531
+ expectSingleListCallAndClear(ifaceSub, [], {
532
+ status: "loading"
533
+ });
534
+ await waitForCall(listSub1);
535
+ expectSingleListCallAndClear(listSub1, employeesAsServerReturns, {
464
536
  status: "loaded"
465
- }));
537
+ });
538
+ await waitForCall(ifaceSub);
539
+ expectSingleListCallAndClear(ifaceSub, employeesAsServerReturns, {
540
+ status: "loaded"
541
+ });
542
+ expectNoMoreCalls(listSub1);
543
+ expectNoMoreCalls(ifaceSub);
544
+ expect(listSub1.next).not.toHaveBeenCalled();
545
+ expect(listSub1.error).not.toHaveBeenCalled();
546
+ expect(ifaceSub.next).not.toHaveBeenCalled();
547
+ expect(ifaceSub.error).not.toHaveBeenCalled();
466
548
  });
467
549
  it("subsequent load", async () => {
468
550
  // Pre-seed with data the server doesn't return
469
- cache.updateList(Employee, {}, mutatedEmployees);
470
- defer(cache.observeList(Employee, {}, {
551
+ updateList(cache, {
552
+ type: Employee,
553
+ where: {},
554
+ orderBy: {}
555
+ }, mutatedEmployees);
556
+ defer(cache.observeList({
557
+ type: Employee,
471
558
  mode: "force"
472
559
  }, listSub1));
473
- await vi.waitFor(() => expect(listSub1).toHaveBeenCalled());
474
- expect(listSub1).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
475
- resolvedList: mutatedEmployees,
560
+ await waitForCall(listSub1, 1);
561
+ const firstLoad = listSub1.next.mock.calls[0][0];
562
+ expectSingleListCallAndClear(listSub1, mutatedEmployees, {
476
563
  status: "loading"
477
- }));
478
- const firstLoad = listSub1.mock.calls[0][0];
479
- listSub1.mockClear();
480
- await vi.waitFor(() => expect(listSub1).toHaveBeenCalled());
481
- expect(listSub1).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
482
- resolvedList: employeesAsServerReturns,
564
+ });
565
+ await waitForCall(listSub1, 1);
566
+ expectSingleListCallAndClear(listSub1, employeesAsServerReturns, {
483
567
  status: "loaded",
484
568
  lastUpdated: expect.toBeGreaterThan(firstLoad.lastUpdated)
485
- }));
486
- listSub1.mockClear();
569
+ });
487
570
  });
488
571
  });
489
572
  describe("mode = offline", () => {
490
573
  it("updates with list updates", async () => {
491
- defer(cache.observeList(Employee, {}, {
574
+ defer(cache.observeList({
575
+ type: Employee,
576
+ where: {},
577
+ orderBy: {},
492
578
  mode: "offline"
493
579
  }, listSub1));
494
- expect(listSub1).toHaveBeenCalledTimes(0);
495
- cache.updateList(Employee, {}, employeesAsServerReturns);
580
+ expect(listSub1.next).toHaveBeenCalledTimes(0);
581
+ updateList(cache, {
582
+ type: Employee,
583
+ where: {},
584
+ orderBy: {}
585
+ }, employeesAsServerReturns);
496
586
  vitest.runOnlyPendingTimers();
497
- expect(listSub1).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
498
- resolvedList: employeesAsServerReturns
499
- }));
500
- listSub1.mockClear();
587
+ expectSingleListCallAndClear(listSub1, employeesAsServerReturns);
501
588
 
502
589
  // list is just now one object
503
- cache.updateList(Employee, {}, [employeesAsServerReturns[0]]);
590
+ updateList(cache, {
591
+ type: Employee,
592
+ where: {},
593
+ orderBy: {}
594
+ }, [employeesAsServerReturns[0]]);
504
595
  vitest.runOnlyPendingTimers();
505
- expect(listSub1).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
506
- resolvedList: [employeesAsServerReturns[0]]
507
- }));
596
+ expectSingleListCallAndClear(listSub1, [employeesAsServerReturns[0]]);
508
597
  });
509
598
  it("updates with different list updates", async () => {
510
- defer(cache.observeList(Employee, {}, {
599
+ defer(cache.observeList({
600
+ type: Employee,
601
+ where: {},
602
+ orderBy: {},
511
603
  mode: "offline"
512
604
  }, listSub1));
513
- expect(listSub1).toHaveBeenCalledTimes(0);
514
- cache.updateList(Employee, {}, employeesAsServerReturns);
605
+ expect(listSub1.next).toHaveBeenCalledTimes(0);
606
+ updateList(cache, {
607
+ type: Employee,
608
+ where: {},
609
+ orderBy: {}
610
+ }, employeesAsServerReturns);
515
611
  vitest.runOnlyPendingTimers();
516
- expect(listSub1).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
517
- resolvedList: employeesAsServerReturns
518
- }));
519
- listSub1.mockClear();
612
+ expectSingleListCallAndClear(listSub1, employeesAsServerReturns);
520
613
 
521
614
  // new where === different list
522
- cache.updateList(Employee, {
523
- employeeId: {
524
- $gt: 0
525
- }
615
+ updateList(cache, {
616
+ type: Employee,
617
+ where: {
618
+ employeeId: {
619
+ $gt: 0
620
+ }
621
+ },
622
+ orderBy: {}
526
623
  }, mutatedEmployees);
527
624
  vitest.runOnlyPendingTimers();
528
625
 
529
626
  // original list updates still
530
- expect(listSub1).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
531
- resolvedList: mutatedEmployees
532
- }));
627
+ expectSingleListCallAndClear(listSub1, mutatedEmployees);
533
628
  });
534
629
  });
535
630
  });
@@ -542,57 +637,127 @@ describe(Store, () => {
542
637
  });
543
638
  it("works in the solo case", async () => {
544
639
  const listSub = mockListSubCallback();
545
- defer(cache.observeList(Employee, {}, {
640
+ defer(cache.observeList({
641
+ type: Employee,
642
+ where: {},
643
+ orderBy: {},
546
644
  mode: "force",
547
645
  pageSize: 1
548
646
  }, listSub));
549
- expect(listSub).not.toHaveBeenCalled();
550
- await vi.waitFor(() => expect(listSub).toHaveBeenCalled());
551
- expect(listSub).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
647
+ expect(listSub.next).not.toHaveBeenCalled();
648
+ await waitForCall(listSub, 1);
649
+ expectSingleListCallAndClear(listSub, [], {
552
650
  status: "loading"
553
- }));
554
- listSub.mockClear();
555
- await vi.waitFor(() => expect(listSub).toHaveBeenCalled());
556
- expect(listSub).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
557
- resolvedList: employeesAsServerReturns.slice(0, 1),
558
- status: "loaded"
559
- }));
651
+ });
652
+ await waitForCall(listSub, 1);
560
653
  const {
561
654
  fetchMore
562
- } = listSub.mock.calls[0][0];
563
- listSub.mockClear();
655
+ } = listSub.next.mock.calls[0][0];
656
+ expectSingleListCallAndClear(listSub, employeesAsServerReturns.slice(0, 1), {
657
+ status: "loaded"
658
+ });
564
659
  void fetchMore();
565
- await vi.waitFor(() => expect(listSub).toHaveBeenCalledTimes(1));
566
- expect(listSub).toHaveBeenCalledExactlyOnceWith(listPayloadContaining({
567
- resolvedList: employeesAsServerReturns.slice(0, 1),
660
+ await waitForCall(listSub, 1);
661
+ expectSingleListCallAndClear(listSub, employeesAsServerReturns.slice(0, 1), {
568
662
  status: "loading"
569
- }));
570
- listSub.mockClear();
571
- await vi.waitFor(() => expect(listSub).toHaveBeenCalledTimes(1));
572
- expect(listSub).toHaveBeenCalledWith(listPayloadContaining({
573
- resolvedList: employeesAsServerReturns.slice(0, 2),
663
+ });
664
+ await waitForCall(listSub, 1);
665
+ expectSingleListCallAndClear(listSub, employeesAsServerReturns.slice(0, 2), {
574
666
  status: "loaded"
575
- }));
667
+ });
576
668
  });
577
669
  });
578
670
  });
579
671
  describe("with mock client", () => {
580
672
  let client;
581
- let mockClient;
582
- let cache;
673
+ let apiServer;
674
+ let fauxFoundry;
675
+ let store;
676
+ beforeAll(async () => {
677
+ const testSetup = startNodeApiServer(new FauxFoundry("https://stack.palantir.com/", undefined, {
678
+ logger
679
+ }), createClient, {
680
+ logger
681
+ });
682
+ ({
683
+ client,
684
+ apiServer,
685
+ fauxFoundry
686
+ } = testSetup);
687
+ setupOntology(testSetup.fauxFoundry);
688
+ return () => {
689
+ testSetup.apiServer.close();
690
+ };
691
+ });
692
+ beforeEach(() => {
693
+ apiServer.resetHandlers();
694
+ });
583
695
  beforeEach(async () => {
584
- mockClient = createClientMockHelper();
585
- client = mockClient.client;
586
- cache = new Store(client);
696
+ store = new Store(client);
697
+ });
698
+ it("properly fires error handler for a list", async () => {
699
+ const sub = mockListSubCallback();
700
+ store.observeList({
701
+ type: Employee,
702
+ where: {
703
+ aBadPropertyThatDoesNotExist: "aBadValue"
704
+ },
705
+ orderBy: {}
706
+ }, sub);
707
+ await waitForCall(sub.error, 1);
708
+ expect(sub.error).toHaveBeenCalled();
709
+ expect(sub.next).not.toHaveBeenCalled();
710
+ });
711
+ describe("batching", () => {
712
+ it("groups requests for single objects", async () => {
713
+ fauxFoundry.getDefaultDataStore().registerObject(Employee, {
714
+ $apiName: "Employee",
715
+ employeeId: 0
716
+ });
717
+ fauxFoundry.getDefaultDataStore().registerObject(Employee, {
718
+ $apiName: "Employee",
719
+ employeeId: 1
720
+ });
721
+ const a = mockSingleSubCallback();
722
+ const b = mockSingleSubCallback();
723
+ defer(store.observeObject(Employee, 0, {}, a));
724
+ defer(store.observeObject(Employee, 1, {}, b));
725
+ await a.expectLoadingAndLoaded({
726
+ loading: objectPayloadContaining({
727
+ status: "loading",
728
+ object: undefined
729
+ }),
730
+ loaded: objectPayloadContaining({
731
+ object: expect.objectContaining({
732
+ $primaryKey: 0
733
+ })
734
+ })
735
+ });
736
+ await b.expectLoadingAndLoaded({
737
+ loading: objectPayloadContaining({
738
+ status: "loading",
739
+ object: undefined
740
+ }),
741
+ loaded: objectPayloadContaining({
742
+ object: expect.objectContaining({
743
+ $primaryKey: 1
744
+ })
745
+ })
746
+ });
747
+ });
587
748
  });
588
749
  describe("actions", () => {
750
+ beforeEach(() => {
751
+ fauxFoundry.getDefaultDataStore().clear();
752
+ });
589
753
  it("properly invalidates objects", async () => {
590
- // after the below `observeObject`, the cache will need to load from the server
591
- mockClient.mockFetchOneOnce().resolve({
592
- $apiName: "Todo"
754
+ fauxFoundry.getDefaultDataStore().registerObject(Todo, {
755
+ $apiName: "Todo",
756
+ id: 0,
757
+ text: "og title"
593
758
  });
594
759
  const todoSubFn = mockSingleSubCallback();
595
- defer(cache.observeObject(Todo, 0, {}, todoSubFn));
760
+ defer(store.observeObject(Todo, 0, {}, todoSubFn));
596
761
  await todoSubFn.expectLoadingAndLoaded({
597
762
  loading: objectPayloadContaining({
598
763
  status: "loading",
@@ -606,23 +771,10 @@ describe(Store, () => {
606
771
  });
607
772
 
608
773
  // at this point we have an observation properly set up
609
- mockClient.mockApplyActionOnce().resolve({
610
- addedObjects: [{
611
- objectType: "Todo",
612
- primaryKey: 0
613
- }]
614
- });
615
-
616
- // after we apply the action, the object is invalidated and gets re-requested
617
-
618
- mockClient.mockFetchOneOnce().resolve({
619
- $apiName: "Todo",
774
+ await store.applyAction(editTodo, {
775
+ id: 0,
620
776
  text: "hello there kind sir"
621
777
  });
622
- const actionPromise = cache.applyAction(createOffice, {
623
- officeId: "whatever"
624
- });
625
- await actionPromise;
626
778
  await todoSubFn.expectLoadingAndLoaded({
627
779
  loading: objectPayloadContaining({
628
780
  status: "loading"
@@ -635,17 +787,19 @@ describe(Store, () => {
635
787
  });
636
788
  });
637
789
  it("rolls back optimistic updates on error", async () => {
638
- const fauxObject = {
639
- $apiName: "Todo",
640
- $objectType: "Todo",
641
- $primaryKey: 0,
642
- $title: "does not matter"
643
- };
790
+ const fauxObject = expect.objectContaining({
791
+ id: 0,
792
+ text: "does not matter"
793
+ });
644
794
 
645
- // after the below `observeObject`, the cache will need to load from the server
646
- mockClient.mockFetchOneOnce().resolve(fauxObject);
795
+ // set the object in the "backend"
796
+ fauxFoundry.getDefaultDataStore().registerObject(Todo, {
797
+ $apiName: "Todo",
798
+ id: 0,
799
+ text: "does not matter"
800
+ });
647
801
  const todoSubFn = mockSingleSubCallback();
648
- defer(cache.observeObject(Todo, 0, {}, todoSubFn));
802
+ defer(store.observeObject(Todo, 0, {}, todoSubFn));
649
803
  await todoSubFn.expectLoadingAndLoaded({
650
804
  loading: objectPayloadContaining({
651
805
  status: "loading",
@@ -658,47 +812,259 @@ describe(Store, () => {
658
812
  isOptimistic: false
659
813
  })
660
814
  });
815
+ const object = store.getValue(store.getCacheKey("object", "Todo", 0))?.value;
816
+ !object ? process.env.NODE_ENV !== "production" ? invariant(false) : invariant(false) : void 0;
661
817
 
662
818
  // at this point we have an observation properly set up
663
- const applyActionResult = mockClient.mockApplyActionOnce();
664
- const actionPromise = cache.applyAction(createOffice, {
665
- officeId: "whatever"
819
+ await expect(store.applyAction(editTodo, {
820
+ id: "not an id that exists"
666
821
  }, {
667
822
  optimisticUpdate: ctx => {
668
- ctx.updateObject({
669
- ...fauxObject,
670
- someValue: "optimistic"
671
- });
823
+ ctx.updateObject(object.$clone({
824
+ text: "optimistic"
825
+ }));
672
826
  }
827
+ })).rejects.toThrow(ActionValidationError);
828
+ await waitForCall(todoSubFn, 2);
829
+ await todoSubFn.expectLoadingAndLoaded({
830
+ loading: objectPayloadContaining({
831
+ status: "loading",
832
+ object: expect.objectContaining({
833
+ id: 0,
834
+ text: "optimistic"
835
+ }),
836
+ isOptimistic: true
837
+ }),
838
+ loaded: objectPayloadContaining({
839
+ object: fauxObject,
840
+ status: "loaded",
841
+ isOptimistic: false
842
+ })
673
843
  });
674
- await waitForCall(todoSubFn, 1);
675
- expect(todoSubFn).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
676
- object: {
677
- ...fauxObject,
678
- someValue: "optimistic"
679
- },
680
- status: "loading",
681
- isOptimistic: true
844
+ });
845
+ });
846
+ describe("orderBy", async () => {
847
+ let nextPk = 0;
848
+ let fauxObjectA;
849
+ let fauxObjectB;
850
+ let fauxObjectC;
851
+ beforeAll(async () => {
852
+ fauxFoundry.getDefaultDataStore().clear();
853
+ [fauxObjectA, fauxObjectB, fauxObjectC] = await Promise.all(["a", "b", "c"].map(text => {
854
+ const id = nextPk++;
855
+ fauxFoundry.getDefaultDataStore().registerObject(Todo, {
856
+ $apiName: "Todo",
857
+ id,
858
+ text
859
+ });
860
+ return client(Todo).fetchOne(id);
682
861
  }));
683
- todoSubFn.mockClear();
862
+ });
863
+ const noWhereNoOrderBy = {
864
+ type: Todo,
865
+ where: {},
866
+ orderBy: {}
867
+ };
868
+ const noWhereOrderByText = {
869
+ type: Todo,
870
+ where: {},
871
+ orderBy: {
872
+ text: "asc"
873
+ }
874
+ };
875
+ const subListUnordered = mockListSubCallback();
876
+ const subListOrdered = mockListSubCallback();
877
+ beforeEach(() => {
878
+ defer(store.observeList({
879
+ ...noWhereNoOrderBy,
880
+ mode: "offline"
881
+ }, subListUnordered));
882
+ expect(subListUnordered.next).toHaveBeenCalledTimes(0);
883
+ defer(store.observeList({
884
+ ...noWhereOrderByText,
885
+ mode: "offline"
886
+ }, subListOrdered));
887
+ expect(subListOrdered.next).toHaveBeenCalledTimes(0);
888
+ });
889
+ it("invalidates the correct lists", async () => {
890
+ // for whatever reason, the first list is loaded as [B, A]
891
+ updateList(store, noWhereNoOrderBy, [fauxObjectB, fauxObjectA]);
892
+ await waitForCall(subListUnordered, 1);
893
+ expectSingleListCallAndClear(subListUnordered, [fauxObjectB, fauxObjectA]);
684
894
 
685
- // let the action error out
686
- applyActionResult.reject("an error thrown");
687
- await expect(actionPromise).rejects.toThrow("an error thrown");
895
+ // The other list definitely matches on the where clause and we can insert
896
+ // orderBy properly. So this is [A, B]
897
+ await waitForCall(subListOrdered, 1);
898
+ expectSingleListCallAndClear(subListOrdered, [fauxObjectA, fauxObjectB]);
688
899
 
689
- // back to the original object
690
- await waitForCall(todoSubFn, 1);
691
- expect(todoSubFn).toHaveBeenCalledExactlyOnceWith(objectPayloadContaining({
692
- object: fauxObject,
693
- status: "loaded",
900
+ // For whatever reason, object B is no longer in the first set (use your imagination)
901
+ // but we have added a C before A. So the first list is [C, A]
902
+ updateList(store, {
903
+ type: Todo,
904
+ where: {},
905
+ orderBy: {}
906
+ }, [fauxObjectC, fauxObjectA]);
907
+ await waitForCall(subListUnordered, 1);
908
+ expectSingleListCallAndClear(subListUnordered, [fauxObjectC, fauxObjectA]);
909
+
910
+ // Nothing told the system that B was deleted so we can presume it still exists
911
+ // and therefore the second list is now [A, B, C]
912
+ await waitForCall(subListOrdered, 1);
913
+ expectSingleListCallAndClear(subListOrdered, [fauxObjectA, fauxObjectB, fauxObjectC]);
914
+ });
915
+ it("produces proper results with optimistic updates and successful action", async () => {
916
+ const optimisticallyMutatedA = fauxObjectA.$clone({
917
+ text: "optimistic"
918
+ });
919
+ const pkForOptimistic = nextPk++;
920
+ const optimisticallyCreatedObjectD = expect.objectContaining({
921
+ "text": "d",
922
+ id: pkForOptimistic
923
+ });
924
+
925
+ // for whatever reason, the first list is loaded as [B, A]
926
+ updateList(store, noWhereNoOrderBy, [fauxObjectB, fauxObjectA]);
927
+ await waitForCall(subListUnordered, 1);
928
+ expectSingleListCallAndClear(subListUnordered, [fauxObjectB, fauxObjectA]);
929
+
930
+ // The other list definitely matches on the where clause and we can insert
931
+ // orderBy properly. So this is [A, B]
932
+ await waitForCall(subListOrdered, 1);
933
+ expectSingleListCallAndClear(subListOrdered, [fauxObjectA, fauxObjectB]);
934
+ testStage("Start");
935
+
936
+ // Perform something optimistic.
937
+ const removeOptimisticResult = runOptimisticJob(store, b => {
938
+ b.createObject(Todo, pkForOptimistic, {
939
+ id: pkForOptimistic,
940
+ text: "d"
941
+ });
942
+ b.updateObject(optimisticallyMutatedA);
943
+ });
944
+
945
+ // The first list is now [B, A, optimistic]
946
+ await waitForCall(subListUnordered, 1);
947
+ expectSingleListCallAndClear(subListUnordered, [fauxObjectB, optimisticallyMutatedA,
948
+ // same position, new values
949
+ optimisticallyCreatedObjectD], {
950
+ isOptimistic: true
951
+ });
952
+
953
+ // the second list is now [A, B, optimistic]
954
+ await waitForCall(subListOrdered, 1);
955
+ expectSingleListCallAndClear(subListOrdered, [fauxObjectB, optimisticallyCreatedObjectD, optimisticallyMutatedA], {
956
+ isOptimistic: true
957
+ });
958
+
959
+ // Roll back the optimistic update
960
+ await removeOptimisticResult();
961
+
962
+ // The first list is now [B, A]
963
+ await waitForCall(subListUnordered, 1);
964
+ expectSingleListCallAndClear(subListUnordered, [fauxObjectB, fauxObjectA], {
694
965
  isOptimistic: false
695
- }));
966
+ });
967
+
968
+ // the second list is now [A, B]
969
+ await waitForCall(subListOrdered, 1);
970
+ expectSingleListCallAndClear(subListOrdered, [fauxObjectA, fauxObjectB], {
971
+ isOptimistic: false
972
+ });
973
+ });
974
+ // I think these are named backwards
975
+ it("produces proper results with optimistic updates and rollback", async () => {
976
+ const pkForOptimistic = nextPk++;
977
+ const optimisticallyCreatedObjectD = expect.objectContaining({
978
+ "$primaryKey": pkForOptimistic,
979
+ "$title": undefined,
980
+ // FIXME once this is calculated by optimistic then this needs to be the right value
981
+ "text": "d optimistic",
982
+ id: pkForOptimistic
983
+ });
984
+ const optimisticallyMutatedA = fauxObjectA.$clone({
985
+ text: "optimistic"
986
+ });
987
+ testStage("Initial Setup");
988
+
989
+ // for whatever reason, the first list is loaded as [B, A]
990
+ updateList(store, noWhereNoOrderBy, [fauxObjectB, fauxObjectA]);
991
+ await waitForCall(subListUnordered, 1);
992
+ expectSingleListCallAndClear(subListUnordered, [fauxObjectB, fauxObjectA]);
993
+
994
+ // The other list definitely matches on the where clause and we can insert
995
+ // orderBy properly. So this is [A, B]
996
+ expectSingleListCallAndClear(subListOrdered, [fauxObjectA, fauxObjectB]);
997
+ testStage("Optimistic Creation");
998
+
999
+ // create the weirdest action ever. It always creates a Todo with
1000
+ // a new primary key and the text "d" and updates A
1001
+ const {
1002
+ actionDefinition: crazyAction,
1003
+ actionTypeV2: crazyActionTypeV2
1004
+ } = new ActionTypeBuilder("asdf").addParameter("foo", "string").build();
1005
+ fauxFoundry.getDefaultOntology().registerActionType(crazyActionTypeV2, batch => {
1006
+ const idForD = nextPk++;
1007
+ batch.addObject(Todo.apiName, idForD, {
1008
+ id: idForD,
1009
+ text: "d"
1010
+ });
1011
+ batch.modifyObject(fauxObjectA.$apiName, fauxObjectA.$primaryKey, {
1012
+ text: "a prime",
1013
+ $title: "a prime" // FIXME we shouldn't have to set this, it can be calculated
1014
+ });
1015
+ });
1016
+
1017
+ // the optimistic job will call createObject which triggers the `objectFactory2` of the
1018
+ // cache context.
1019
+
1020
+ // Perform something optimistic.
1021
+ const pActionResult = store.applyAction(crazyAction, {}, {
1022
+ optimisticUpdate: b => {
1023
+ b.createObject(Todo, pkForOptimistic, {
1024
+ id: pkForOptimistic,
1025
+ text: "d optimistic"
1026
+ });
1027
+ b.updateObject(optimisticallyMutatedA);
1028
+ }
1029
+ });
1030
+ testStage("Optimistic Updates");
1031
+
1032
+ // The first list is now [B, A, optimistic]
1033
+ await waitForCall(subListUnordered, 1);
1034
+ expectSingleListCallAndClear(subListUnordered, [fauxObjectB, optimisticallyMutatedA,
1035
+ // same position, new values
1036
+ optimisticallyCreatedObjectD], {
1037
+ isOptimistic: true
1038
+ });
1039
+
1040
+ // the second list is now [B, optimistic, optimistic a]
1041
+ await waitForCall(subListOrdered, 1);
1042
+ expectSingleListCallAndClear(subListOrdered, [fauxObjectB, optimisticallyCreatedObjectD, optimisticallyMutatedA], {
1043
+ isOptimistic: true
1044
+ });
1045
+ testStage("Resolve Action");
1046
+ const modifiedObjectA = fauxObjectA.$clone({
1047
+ text: "a prime"
1048
+ });
1049
+ const pkForD = (await pActionResult).addedObjects?.[0].primaryKey;
1050
+ !(typeof pkForD === "number") ? process.env.NODE_ENV !== "production" ? invariant(false) : invariant(false) : void 0;
1051
+ // load this without the cache for comparisons
1052
+ const createdObjectD = await client(Todo).fetchOne(pkForD);
1053
+ await waitForCall(subListUnordered, 1);
1054
+ expectSingleListCallAndClear(subListUnordered, [fauxObjectB, modifiedObjectA, createdObjectD], {
1055
+ isOptimistic: false
1056
+ });
1057
+ await waitForCall(subListOrdered, 1);
1058
+ expectSingleListCallAndClear(subListOrdered, [modifiedObjectA, fauxObjectB, createdObjectD], {
1059
+ isOptimistic: false
1060
+ });
696
1061
  });
697
1062
  });
698
1063
  });
699
1064
  describe("layers", () => {
700
1065
  it("properly remove", () => {
701
- const store = new Store({});
1066
+ const clientHelper = createClientMockHelper();
1067
+ const store = new Store(clientHelper.client);
702
1068
  const baseObjects = [1, 2].map(i => ({
703
1069
  $primaryKey: i,
704
1070
  $objectType: "Employee",
@@ -709,12 +1075,12 @@ describe(Store, () => {
709
1075
 
710
1076
  // set the truth
711
1077
  for (const obj of baseObjects) {
712
- store.updateObject("Employee", obj);
1078
+ updateObject(store, obj);
713
1079
  }
714
1080
 
715
1081
  // expect the truth
716
1082
  for (const obj of baseObjects) {
717
- expect(store.getObject("Employee", obj.$primaryKey)).toEqual(expect.objectContaining({
1083
+ expect(getObject(store, "Employee", obj.$primaryKey)).toEqual(expect.objectContaining({
718
1084
  $title: `truth ${obj.$primaryKey}`
719
1085
  }));
720
1086
  }
@@ -734,7 +1100,7 @@ describe(Store, () => {
734
1100
 
735
1101
  // expect the optimistic values
736
1102
  for (let i = 0; i < 2; i++) {
737
- expect(store.getObject("Employee", baseObjects[i].$primaryKey)).toEqual(expect.objectContaining({
1103
+ expect(getObject(store, "Employee", baseObjects[i].$primaryKey)).toEqual(expect.objectContaining({
738
1104
  $title: `optimistic ${baseObjects[i].$primaryKey}`
739
1105
  }));
740
1106
  }
@@ -743,10 +1109,10 @@ describe(Store, () => {
743
1109
  store.removeLayer(layerIds[0]);
744
1110
 
745
1111
  // should have truth object 1 and optimistic object 2
746
- expect(store.getObject("Employee", 1)).toEqual(expect.objectContaining({
1112
+ expect(getObject(store, "Employee", 1)).toEqual(expect.objectContaining({
747
1113
  $title: "truth 1"
748
1114
  }));
749
- expect(store.getObject("Employee", 2)).toEqual(expect.objectContaining({
1115
+ expect(getObject(store, "Employee", 2)).toEqual(expect.objectContaining({
750
1116
  $title: "optimistic 2"
751
1117
  }));
752
1118
 
@@ -755,7 +1121,7 @@ describe(Store, () => {
755
1121
 
756
1122
  // should have truth objects
757
1123
  for (const obj of baseObjects) {
758
- expect(store.getObject("Employee", obj.$primaryKey)).toEqual(expect.objectContaining({
1124
+ expect(getObject(store, "Employee", obj.$primaryKey)).toEqual(expect.objectContaining({
759
1125
  $title: `truth ${obj.$primaryKey}`
760
1126
  }));
761
1127
  }