@statezero/core 0.2.38 → 0.2.40

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 (294) hide show
  1. package/dist/actions/backend1/django_app/calculate-hash.d.ts +57 -0
  2. package/dist/actions/backend1/django_app/calculate-hash.js +80 -0
  3. package/dist/actions/backend1/django_app/calculate-hash.schema.json +148 -0
  4. package/dist/actions/backend1/django_app/get-current-username.d.ts +29 -0
  5. package/dist/actions/backend1/django_app/get-current-username.js +65 -0
  6. package/dist/actions/backend1/django_app/get-current-username.schema.json +47 -0
  7. package/dist/actions/backend1/django_app/get-server-status.d.ts +38 -0
  8. package/dist/actions/backend1/django_app/get-server-status.js +68 -0
  9. package/dist/actions/backend1/django_app/get-server-status.schema.json +93 -0
  10. package/dist/actions/backend1/django_app/get-user-info.d.ts +44 -0
  11. package/dist/actions/backend1/django_app/get-user-info.js +70 -0
  12. package/dist/actions/backend1/django_app/get-user-info.schema.json +127 -0
  13. package/dist/actions/backend1/django_app/index.d.ts +1 -0
  14. package/dist/actions/backend1/django_app/index.js +6 -0
  15. package/dist/actions/backend1/django_app/process-data.d.ts +51 -0
  16. package/dist/actions/backend1/django_app/process-data.js +78 -0
  17. package/dist/actions/backend1/django_app/process-data.schema.json +117 -0
  18. package/dist/actions/backend1/django_app/send-notification.d.ts +55 -0
  19. package/dist/actions/backend1/django_app/send-notification.js +81 -0
  20. package/dist/actions/backend1/django_app/send-notification.schema.json +175 -0
  21. package/dist/actions/backend1/index.d.ts +1 -0
  22. package/dist/actions/backend1/index.js +1 -0
  23. package/dist/actions/default/django_app/calculate-hash.d.ts +57 -0
  24. package/dist/actions/default/django_app/calculate-hash.js +80 -0
  25. package/dist/actions/default/django_app/calculate-hash.schema.json +148 -0
  26. package/dist/actions/default/django_app/get-current-username.d.ts +29 -0
  27. package/dist/actions/default/django_app/get-current-username.js +65 -0
  28. package/dist/actions/default/django_app/get-current-username.schema.json +47 -0
  29. package/dist/actions/default/django_app/get-server-status.d.ts +38 -0
  30. package/dist/actions/default/django_app/get-server-status.js +68 -0
  31. package/dist/actions/default/django_app/get-server-status.schema.json +93 -0
  32. package/dist/actions/default/django_app/get-user-info.d.ts +44 -0
  33. package/dist/actions/default/django_app/get-user-info.js +70 -0
  34. package/dist/actions/default/django_app/get-user-info.schema.json +127 -0
  35. package/dist/actions/default/django_app/index.d.ts +1 -0
  36. package/dist/actions/default/django_app/index.js +6 -0
  37. package/dist/actions/default/django_app/process-data.d.ts +51 -0
  38. package/dist/actions/default/django_app/process-data.js +78 -0
  39. package/dist/actions/default/django_app/process-data.schema.json +117 -0
  40. package/dist/actions/default/django_app/send-notification.d.ts +55 -0
  41. package/dist/actions/default/django_app/send-notification.js +81 -0
  42. package/dist/actions/default/django_app/send-notification.schema.json +175 -0
  43. package/dist/actions/default/index.d.ts +1 -0
  44. package/dist/actions/default/index.js +1 -0
  45. package/dist/actions/index.d.ts +1 -0
  46. package/dist/actions/index.js +5 -0
  47. package/dist/adaptors/react/composables.d.ts +1 -0
  48. package/dist/adaptors/react/composables.js +4 -0
  49. package/dist/adaptors/react/index.d.ts +1 -0
  50. package/dist/adaptors/react/index.js +1 -0
  51. package/dist/adaptors/vue/components/LayoutRenderer.js +46 -49
  52. package/dist/adaptors/vue/components/defaults/index.d.ts +7 -0
  53. package/dist/adaptors/vue/components/defaults/index.js +31 -0
  54. package/dist/adaptors/vue/components/index.d.ts +1 -0
  55. package/dist/adaptors/vue/components/index.js +7 -0
  56. package/dist/adaptors/vue/composables.d.ts +2 -0
  57. package/dist/adaptors/vue/composables.js +44 -0
  58. package/dist/adaptors/vue/index.d.ts +3 -0
  59. package/dist/adaptors/vue/index.js +4 -0
  60. package/dist/adaptors/vue/reactivity.d.ts +18 -0
  61. package/dist/adaptors/vue/reactivity.js +132 -0
  62. package/dist/cli/commands/sync.d.ts +6 -0
  63. package/dist/cli/commands/sync.js +30 -0
  64. package/dist/cli/commands/syncActions.d.ts +46 -0
  65. package/dist/cli/commands/syncActions.js +717 -0
  66. package/dist/cli/commands/syncModels.d.ts +132 -0
  67. package/dist/cli/commands/syncModels.js +1120 -0
  68. package/dist/cli/configFileLoader.d.ts +10 -0
  69. package/dist/cli/configFileLoader.js +85 -0
  70. package/dist/cli/index.d.ts +2 -0
  71. package/dist/cli/index.js +22 -0
  72. package/dist/config.d.ts +57 -0
  73. package/dist/config.js +273 -0
  74. package/dist/core/eventReceivers.d.ts +185 -0
  75. package/dist/core/eventReceivers.js +266 -0
  76. package/dist/core/utils.d.ts +8 -0
  77. package/dist/core/utils.js +62 -0
  78. package/dist/errorHandler.d.ts +21 -0
  79. package/dist/errorHandler.js +27 -0
  80. package/dist/filtering/localFiltering.d.ts +110 -0
  81. package/dist/filtering/localFiltering.js +1080 -0
  82. package/dist/flavours/django/dates.d.ts +34 -0
  83. package/dist/flavours/django/dates.js +113 -0
  84. package/dist/flavours/django/errors.d.ts +138 -0
  85. package/dist/flavours/django/errors.js +195 -0
  86. package/dist/flavours/django/f.d.ts +6 -0
  87. package/dist/flavours/django/f.js +91 -0
  88. package/dist/flavours/django/files.d.ts +62 -0
  89. package/dist/flavours/django/files.js +355 -0
  90. package/dist/flavours/django/makeApiCall.d.ts +36 -0
  91. package/dist/flavours/django/makeApiCall.js +169 -0
  92. package/dist/flavours/django/manager.d.ts +204 -0
  93. package/dist/flavours/django/manager.js +222 -0
  94. package/dist/flavours/django/model.d.ts +137 -0
  95. package/dist/flavours/django/model.js +366 -0
  96. package/dist/flavours/django/operationFactory.d.ts +73 -0
  97. package/dist/flavours/django/operationFactory.js +248 -0
  98. package/dist/flavours/django/q.d.ts +70 -0
  99. package/dist/flavours/django/q.js +43 -0
  100. package/dist/flavours/django/queryExecutor.d.ts +149 -0
  101. package/dist/flavours/django/queryExecutor.js +590 -0
  102. package/dist/flavours/django/querySet.d.ts +301 -0
  103. package/dist/flavours/django/querySet.js +736 -0
  104. package/dist/flavours/django/serializers.d.ts +39 -0
  105. package/dist/flavours/django/serializers.js +296 -0
  106. package/dist/flavours/django/tempPk.d.ts +31 -0
  107. package/dist/flavours/django/tempPk.js +92 -0
  108. package/dist/flavours/django/utils.d.ts +19 -0
  109. package/dist/flavours/django/utils.js +29 -0
  110. package/dist/index.d.ts +46 -0
  111. package/dist/index.js +48 -0
  112. package/dist/models/backend1/django_app/comprehensivemodel.d.ts +894 -0
  113. package/dist/models/backend1/django_app/comprehensivemodel.js +71 -0
  114. package/dist/models/backend1/django_app/comprehensivemodel.schema.json +870 -0
  115. package/dist/models/backend1/django_app/custompkmodel.d.ts +92 -0
  116. package/dist/models/backend1/django_app/custompkmodel.js +69 -0
  117. package/dist/models/backend1/django_app/custompkmodel.schema.json +71 -0
  118. package/dist/models/backend1/django_app/dailyrate.d.ts +230 -0
  119. package/dist/models/backend1/django_app/dailyrate.js +71 -0
  120. package/dist/models/backend1/django_app/dailyrate.schema.json +212 -0
  121. package/dist/models/backend1/django_app/deepmodellevel1.d.ts +140 -0
  122. package/dist/models/backend1/django_app/deepmodellevel1.js +72 -0
  123. package/dist/models/backend1/django_app/deepmodellevel1.schema.json +114 -0
  124. package/dist/models/backend1/django_app/deepmodellevel2.d.ts +118 -0
  125. package/dist/models/backend1/django_app/deepmodellevel2.js +71 -0
  126. package/dist/models/backend1/django_app/deepmodellevel2.schema.json +92 -0
  127. package/dist/models/backend1/django_app/deepmodellevel3.d.ts +92 -0
  128. package/dist/models/backend1/django_app/deepmodellevel3.js +69 -0
  129. package/dist/models/backend1/django_app/deepmodellevel3.schema.json +69 -0
  130. package/dist/models/backend1/django_app/dummymodel.d.ts +134 -0
  131. package/dist/models/backend1/django_app/dummymodel.js +71 -0
  132. package/dist/models/backend1/django_app/dummymodel.schema.json +109 -0
  133. package/dist/models/backend1/django_app/dummyrelatedmodel.d.ts +92 -0
  134. package/dist/models/backend1/django_app/dummyrelatedmodel.js +69 -0
  135. package/dist/models/backend1/django_app/dummyrelatedmodel.schema.json +69 -0
  136. package/dist/models/backend1/django_app/filetest.d.ts +140 -0
  137. package/dist/models/backend1/django_app/filetest.js +69 -0
  138. package/dist/models/backend1/django_app/filetest.schema.json +111 -0
  139. package/dist/models/backend1/django_app/index.d.ts +1 -0
  140. package/dist/models/backend1/django_app/index.js +21 -0
  141. package/dist/models/backend1/django_app/m2mdepthtestlevel1.d.ts +118 -0
  142. package/dist/models/backend1/django_app/m2mdepthtestlevel1.js +71 -0
  143. package/dist/models/backend1/django_app/m2mdepthtestlevel1.schema.json +94 -0
  144. package/dist/models/backend1/django_app/m2mdepthtestlevel2.d.ts +118 -0
  145. package/dist/models/backend1/django_app/m2mdepthtestlevel2.js +71 -0
  146. package/dist/models/backend1/django_app/m2mdepthtestlevel2.schema.json +94 -0
  147. package/dist/models/backend1/django_app/m2mdepthtestlevel3.d.ts +134 -0
  148. package/dist/models/backend1/django_app/m2mdepthtestlevel3.js +71 -0
  149. package/dist/models/backend1/django_app/m2mdepthtestlevel3.schema.json +112 -0
  150. package/dist/models/backend1/django_app/modelwithcustompkrelation.d.ts +118 -0
  151. package/dist/models/backend1/django_app/modelwithcustompkrelation.js +71 -0
  152. package/dist/models/backend1/django_app/modelwithcustompkrelation.schema.json +93 -0
  153. package/dist/models/backend1/django_app/modelwithrestrictedfields.d.ts +134 -0
  154. package/dist/models/backend1/django_app/modelwithrestrictedfields.js +71 -0
  155. package/dist/models/backend1/django_app/modelwithrestrictedfields.schema.json +111 -0
  156. package/dist/models/backend1/django_app/namefiltercustompkmodel.d.ts +92 -0
  157. package/dist/models/backend1/django_app/namefiltercustompkmodel.js +69 -0
  158. package/dist/models/backend1/django_app/namefiltercustompkmodel.schema.json +71 -0
  159. package/dist/models/backend1/django_app/order.d.ts +220 -0
  160. package/dist/models/backend1/django_app/order.js +71 -0
  161. package/dist/models/backend1/django_app/order.schema.json +203 -0
  162. package/dist/models/backend1/django_app/orderitem.d.ts +172 -0
  163. package/dist/models/backend1/django_app/orderitem.js +72 -0
  164. package/dist/models/backend1/django_app/orderitem.schema.json +149 -0
  165. package/dist/models/backend1/django_app/product.d.ts +254 -0
  166. package/dist/models/backend1/django_app/product.js +71 -0
  167. package/dist/models/backend1/django_app/product.schema.json +277 -0
  168. package/dist/models/backend1/django_app/productcategory.d.ts +92 -0
  169. package/dist/models/backend1/django_app/productcategory.js +69 -0
  170. package/dist/models/backend1/django_app/productcategory.schema.json +70 -0
  171. package/dist/models/backend1/django_app/rateplan.d.ts +92 -0
  172. package/dist/models/backend1/django_app/rateplan.js +69 -0
  173. package/dist/models/backend1/django_app/rateplan.schema.json +70 -0
  174. package/dist/models/backend1/django_app/restrictedfieldrelatedmodel.d.ts +108 -0
  175. package/dist/models/backend1/django_app/restrictedfieldrelatedmodel.js +69 -0
  176. package/dist/models/backend1/django_app/restrictedfieldrelatedmodel.schema.json +87 -0
  177. package/dist/models/backend1/fileobject.d.ts +4 -0
  178. package/dist/models/backend1/fileobject.js +9 -0
  179. package/dist/models/backend1/index.d.ts +2 -0
  180. package/dist/models/backend1/index.js +2 -0
  181. package/dist/models/default/django_app/comprehensivemodel.d.ts +894 -0
  182. package/dist/models/default/django_app/comprehensivemodel.js +71 -0
  183. package/dist/models/default/django_app/comprehensivemodel.schema.json +870 -0
  184. package/dist/models/default/django_app/custompkmodel.d.ts +92 -0
  185. package/dist/models/default/django_app/custompkmodel.js +69 -0
  186. package/dist/models/default/django_app/custompkmodel.schema.json +71 -0
  187. package/dist/models/default/django_app/dailyrate.d.ts +230 -0
  188. package/dist/models/default/django_app/dailyrate.js +71 -0
  189. package/dist/models/default/django_app/dailyrate.schema.json +212 -0
  190. package/dist/models/default/django_app/deepmodellevel1.d.ts +128 -0
  191. package/dist/models/default/django_app/deepmodellevel1.js +72 -0
  192. package/dist/models/default/django_app/deepmodellevel1.schema.json +102 -0
  193. package/dist/models/default/django_app/deepmodellevel2.d.ts +106 -0
  194. package/dist/models/default/django_app/deepmodellevel2.js +71 -0
  195. package/dist/models/default/django_app/deepmodellevel2.schema.json +80 -0
  196. package/dist/models/default/django_app/deepmodellevel3.d.ts +80 -0
  197. package/dist/models/default/django_app/deepmodellevel3.js +69 -0
  198. package/dist/models/default/django_app/deepmodellevel3.schema.json +57 -0
  199. package/dist/models/default/django_app/dummymodel.d.ts +122 -0
  200. package/dist/models/default/django_app/dummymodel.js +71 -0
  201. package/dist/models/default/django_app/dummymodel.schema.json +97 -0
  202. package/dist/models/default/django_app/dummyrelatedmodel.d.ts +80 -0
  203. package/dist/models/default/django_app/dummyrelatedmodel.js +69 -0
  204. package/dist/models/default/django_app/dummyrelatedmodel.schema.json +57 -0
  205. package/dist/models/default/django_app/filetest.d.ts +128 -0
  206. package/dist/models/default/django_app/filetest.js +69 -0
  207. package/dist/models/default/django_app/filetest.schema.json +99 -0
  208. package/dist/models/default/django_app/index.d.ts +1 -0
  209. package/dist/models/default/django_app/index.js +21 -0
  210. package/dist/models/default/django_app/m2mdepthtestlevel1.d.ts +118 -0
  211. package/dist/models/default/django_app/m2mdepthtestlevel1.js +71 -0
  212. package/dist/models/default/django_app/m2mdepthtestlevel1.schema.json +94 -0
  213. package/dist/models/default/django_app/m2mdepthtestlevel2.d.ts +118 -0
  214. package/dist/models/default/django_app/m2mdepthtestlevel2.js +71 -0
  215. package/dist/models/default/django_app/m2mdepthtestlevel2.schema.json +94 -0
  216. package/dist/models/default/django_app/m2mdepthtestlevel3.d.ts +134 -0
  217. package/dist/models/default/django_app/m2mdepthtestlevel3.js +71 -0
  218. package/dist/models/default/django_app/m2mdepthtestlevel3.schema.json +112 -0
  219. package/dist/models/default/django_app/modelwithcustompkrelation.d.ts +118 -0
  220. package/dist/models/default/django_app/modelwithcustompkrelation.js +71 -0
  221. package/dist/models/default/django_app/modelwithcustompkrelation.schema.json +93 -0
  222. package/dist/models/default/django_app/modelwithrestrictedfields.d.ts +134 -0
  223. package/dist/models/default/django_app/modelwithrestrictedfields.js +71 -0
  224. package/dist/models/default/django_app/modelwithrestrictedfields.schema.json +111 -0
  225. package/dist/models/default/django_app/namefiltercustompkmodel.d.ts +92 -0
  226. package/dist/models/default/django_app/namefiltercustompkmodel.js +69 -0
  227. package/dist/models/default/django_app/namefiltercustompkmodel.schema.json +71 -0
  228. package/dist/models/default/django_app/order.d.ts +220 -0
  229. package/dist/models/default/django_app/order.js +71 -0
  230. package/dist/models/default/django_app/order.schema.json +203 -0
  231. package/dist/models/default/django_app/orderitem.d.ts +172 -0
  232. package/dist/models/default/django_app/orderitem.js +72 -0
  233. package/dist/models/default/django_app/orderitem.schema.json +149 -0
  234. package/dist/models/default/django_app/product.d.ts +254 -0
  235. package/dist/models/default/django_app/product.js +71 -0
  236. package/dist/models/default/django_app/product.schema.json +277 -0
  237. package/dist/models/default/django_app/productcategory.d.ts +92 -0
  238. package/dist/models/default/django_app/productcategory.js +69 -0
  239. package/dist/models/default/django_app/productcategory.schema.json +70 -0
  240. package/dist/models/default/django_app/rateplan.d.ts +92 -0
  241. package/dist/models/default/django_app/rateplan.js +69 -0
  242. package/dist/models/default/django_app/rateplan.schema.json +70 -0
  243. package/dist/models/default/django_app/restrictedfieldrelatedmodel.d.ts +108 -0
  244. package/dist/models/default/django_app/restrictedfieldrelatedmodel.js +69 -0
  245. package/dist/models/default/django_app/restrictedfieldrelatedmodel.schema.json +87 -0
  246. package/dist/models/default/fileobject.d.ts +4 -0
  247. package/dist/models/default/fileobject.js +9 -0
  248. package/dist/models/default/index.d.ts +2 -0
  249. package/dist/models/default/index.js +2 -0
  250. package/dist/models/index.d.ts +1 -0
  251. package/dist/models/index.js +5 -0
  252. package/dist/react-entry.d.ts +2 -0
  253. package/dist/react-entry.js +2 -0
  254. package/dist/reactiveAdaptor.d.ts +24 -0
  255. package/dist/reactiveAdaptor.js +38 -0
  256. package/dist/reset.d.ts +15 -0
  257. package/dist/reset.js +97 -0
  258. package/dist/setup.d.ts +15 -0
  259. package/dist/setup.js +33 -0
  260. package/dist/syncEngine/cache/cache.d.ts +75 -0
  261. package/dist/syncEngine/cache/cache.js +355 -0
  262. package/dist/syncEngine/metrics/metricOptCalcs.d.ts +79 -0
  263. package/dist/syncEngine/metrics/metricOptCalcs.js +284 -0
  264. package/dist/syncEngine/registries/metricRegistry.d.ts +58 -0
  265. package/dist/syncEngine/registries/metricRegistry.js +171 -0
  266. package/dist/syncEngine/registries/modelStoreRegistry.d.ts +11 -0
  267. package/dist/syncEngine/registries/modelStoreRegistry.js +63 -0
  268. package/dist/syncEngine/registries/querysetStoreGraph.d.ts +41 -0
  269. package/dist/syncEngine/registries/querysetStoreGraph.js +174 -0
  270. package/dist/syncEngine/registries/querysetStoreRegistry.d.ts +72 -0
  271. package/dist/syncEngine/registries/querysetStoreRegistry.js +335 -0
  272. package/dist/syncEngine/stores/metricStore.d.ts +55 -0
  273. package/dist/syncEngine/stores/metricStore.js +222 -0
  274. package/dist/syncEngine/stores/modelStore.d.ts +53 -0
  275. package/dist/syncEngine/stores/modelStore.js +565 -0
  276. package/dist/syncEngine/stores/operation.d.ts +139 -0
  277. package/dist/syncEngine/stores/operation.js +291 -0
  278. package/dist/syncEngine/stores/operationEventHandlers.d.ts +8 -0
  279. package/dist/syncEngine/stores/operationEventHandlers.js +348 -0
  280. package/dist/syncEngine/stores/querysetStore.d.ts +60 -0
  281. package/dist/syncEngine/stores/querysetStore.js +294 -0
  282. package/dist/syncEngine/stores/reactivity.d.ts +3 -0
  283. package/dist/syncEngine/stores/reactivity.js +4 -0
  284. package/dist/syncEngine/stores/utils.d.ts +14 -0
  285. package/dist/syncEngine/stores/utils.js +32 -0
  286. package/dist/syncEngine/sync.d.ts +51 -0
  287. package/dist/syncEngine/sync.js +419 -0
  288. package/dist/testing.d.ts +63 -0
  289. package/dist/testing.js +175 -0
  290. package/dist/vue-entry.d.ts +15 -0
  291. package/dist/vue-entry.js +7 -0
  292. package/package.json +6 -7
  293. package/dist/adaptors/vue/components/layout.tailwind.css +0 -51
  294. /package/{dist → src}/adaptors/vue/components/layout.css +0 -0
@@ -0,0 +1,294 @@
1
+ import { Operation, Status, Type, operationRegistry } from './operation.js';
2
+ import { querysetEventEmitter } from './reactivity.js';
3
+ import { isNil, isEmpty, trim, isEqual } from 'lodash-es';
4
+ import { replaceTempPks, containsTempPk } from '../../flavours/django/tempPk.js';
5
+ import { modelStoreRegistry } from '../registries/modelStoreRegistry.js';
6
+ import { processIncludedEntities } from '../../flavours/django/makeApiCall.js';
7
+ import { Cache } from '../cache/cache.js';
8
+ import { filter } from "../../filtering/localFiltering.js";
9
+ export class QuerysetStore {
10
+ constructor(modelClass, fetchFn, queryset, initialGroundTruthPks = null, initialOperations = null, options = {}) {
11
+ this.modelClass = modelClass;
12
+ this.fetchFn = fetchFn;
13
+ this.queryset = queryset;
14
+ this.isSyncing = false;
15
+ this.lastSync = null;
16
+ this.isTemp = options.isTemp || false;
17
+ this.pruneThreshold = options.pruneThreshold || 10;
18
+ this.groundTruthPks = initialGroundTruthPks || [];
19
+ this.operationsMap = new Map();
20
+ // Track which model PKs are in this queryset's included data
21
+ // Map<modelName, Set<pk>>
22
+ this.includedPks = new Map();
23
+ if (Array.isArray(initialOperations)) {
24
+ for (const opData of initialOperations) {
25
+ const existing = operationRegistry.get(opData.operationId);
26
+ const op = existing || new Operation(opData, true);
27
+ this.operationsMap.set(op.operationId, op);
28
+ }
29
+ }
30
+ this.qsCache = new Cache("queryset-cache", {}, this.onHydrated.bind(this));
31
+ this._lastRenderedPks = null;
32
+ this.renderCallbacks = new Set();
33
+ // Register for model store changes to re-render when model data changes
34
+ // Only register permanent stores - temp stores are transient and should not
35
+ // accumulate callbacks (causes reactivity cascade when Vue creates new querysets)
36
+ if (!this.isTemp) {
37
+ const modelStore = modelStoreRegistry.getStore(this.modelClass);
38
+ this._modelStoreUnregister = modelStore.registerRenderCallback(() => {
39
+ this._emitRenderEvent();
40
+ });
41
+ }
42
+ }
43
+ // Caching
44
+ get cacheKey() {
45
+ return this.queryset.semanticKey;
46
+ }
47
+ onHydrated(hydratedData) {
48
+ if (this.groundTruthPks.length === 0 && this.operationsMap.size === 0) {
49
+ const cached = this.qsCache.get(this.cacheKey);
50
+ if (!isNil(cached) && !isEmpty(cached)) {
51
+ console.log(`[QuerysetStore] Hydrated ${this.modelClass.modelName} queryset with ${cached.length} items from cache`);
52
+ this.setGroundTruth(cached);
53
+ }
54
+ }
55
+ }
56
+ setCache(result) {
57
+ let nonTempPks = [];
58
+ result.forEach((pk) => {
59
+ if (typeof pk === "string" && containsTempPk(pk)) {
60
+ pk = replaceTempPks(pk);
61
+ if (isNil(pk) || isEmpty(trim(pk))) {
62
+ return;
63
+ }
64
+ }
65
+ nonTempPks.push(pk);
66
+ });
67
+ this.qsCache.set(this.cacheKey, nonTempPks);
68
+ }
69
+ clearCache() {
70
+ this.qsCache.delete(this.cacheKey);
71
+ }
72
+ // -- Core methods --
73
+ get operations() {
74
+ return Array.from(this.operationsMap.values());
75
+ }
76
+ get pkField() {
77
+ return this.modelClass.primaryKeyField;
78
+ }
79
+ get groundTruthSet() {
80
+ return new Set(this.groundTruthPks);
81
+ }
82
+ _emitRenderEvent() {
83
+ const newPks = this.render(true, false);
84
+ // 1. Always notify direct child stores to trigger their own re-evaluation.
85
+ // They will perform their own check to see if their own results have changed.
86
+ this.renderCallbacks.forEach((callback) => {
87
+ try {
88
+ callback();
89
+ }
90
+ catch (error) {
91
+ console.warn("Error in render callback:", error);
92
+ }
93
+ });
94
+ // 2. Only emit the global event for UI components if the final list of PKs has actually changed.
95
+ if (!isEqual(newPks, this._lastRenderedPks)) {
96
+ this._lastRenderedPks = newPks; // Update the cache with the new state
97
+ querysetEventEmitter.emit(`${this.modelClass.configKey}::${this.modelClass.modelName}::queryset::render`, { ast: this.queryset.build(), ModelClass: this.modelClass });
98
+ }
99
+ }
100
+ async addOperation(operation) {
101
+ this.operationsMap.set(operation.operationId, operation);
102
+ if (this.operationsMap.size > this.pruneThreshold) {
103
+ this.prune();
104
+ }
105
+ this._emitRenderEvent();
106
+ }
107
+ async updateOperation(operation) {
108
+ if (!this.operationsMap.has(operation.operationId))
109
+ return;
110
+ this.operationsMap.set(operation.operationId, operation);
111
+ this._emitRenderEvent();
112
+ return true;
113
+ }
114
+ async confirm(operation) {
115
+ if (!this.operationsMap.has(operation.operationId))
116
+ return;
117
+ this.operationsMap.set(operation.operationId, operation);
118
+ this._emitRenderEvent();
119
+ }
120
+ async reject(operation) {
121
+ if (!this.operationsMap.has(operation.operationId))
122
+ return;
123
+ this.operationsMap.set(operation.operationId, operation);
124
+ this._emitRenderEvent();
125
+ }
126
+ async setGroundTruth(groundTruthPks) {
127
+ this.groundTruthPks = Array.isArray(groundTruthPks) ? groundTruthPks : [];
128
+ this.lastSync = Date.now();
129
+ this._emitRenderEvent();
130
+ }
131
+ async setOperations(operations) {
132
+ this.operationsMap.clear();
133
+ if (Array.isArray(operations)) {
134
+ for (const op of operations) {
135
+ this.operationsMap.set(op.operationId, op);
136
+ }
137
+ }
138
+ this._emitRenderEvent();
139
+ }
140
+ getTrimmedOperations() {
141
+ const cutoff = Date.now() - 1000 * 60 * 2;
142
+ return this.operations.filter((op) => op.timestamp > cutoff);
143
+ }
144
+ getInflightOperations() {
145
+ return this.operations.filter((operation) => operation.status != Status.CONFIRMED &&
146
+ operation.status != Status.REJECTED);
147
+ }
148
+ prune() {
149
+ const renderedPks = this.render(false);
150
+ this.setGroundTruth(renderedPks);
151
+ this.setOperations(this.getInflightOperations());
152
+ }
153
+ registerRenderCallback(callback) {
154
+ this.renderCallbacks.add(callback);
155
+ return () => this.renderCallbacks.delete(callback);
156
+ }
157
+ /**
158
+ * Register this store with the model store for change notifications.
159
+ * Called when a temp store is promoted to permanent.
160
+ */
161
+ registerWithModelStore() {
162
+ if (this._modelStoreUnregister)
163
+ return; // Already registered
164
+ const modelStore = modelStoreRegistry.getStore(this.modelClass);
165
+ this._modelStoreUnregister = modelStore.registerRenderCallback(() => {
166
+ this._emitRenderEvent();
167
+ });
168
+ }
169
+ /**
170
+ * Helper to validate PKs against the model store and apply local filtering/sorting.
171
+ * This is the core of the rendering logic.
172
+ * @private
173
+ */
174
+ _getValidatedAndFilteredPks(pks) {
175
+ // 1. Convert PKs to instances, filtering out any that are null (deleted).
176
+ const instances = Array.from(pks)
177
+ .map((pk) => this.modelClass.fromPk(pk, this.queryset))
178
+ .filter((instance) => modelStoreRegistry.getEntity(this.modelClass, instance.pk) !== null);
179
+ // 2. Apply the queryset's AST (filters, ordering) to the validated instances.
180
+ const ast = this.queryset.build();
181
+ const finalPks = filter(instances, ast, this.modelClass, false); // false = return PKs
182
+ return finalPks;
183
+ }
184
+ render(optimistic = true, fromCache = false) {
185
+ // Check cache first if requested
186
+ if (fromCache) {
187
+ const cachedResult = this.qsCache.get(this.cacheKey);
188
+ if (Array.isArray(cachedResult)) {
189
+ return cachedResult;
190
+ }
191
+ }
192
+ // If no ground truth AND hasn't been synced, render from model store
193
+ // This handles chained optimistic filters, newly created stores, etc.
194
+ // (If synced with empty results, that's valid ground truth)
195
+ const pks = this.groundTruthPks.length === 0 && this.lastSync === null
196
+ ? this.renderFromModelStore()
197
+ : this.renderFromData(optimistic);
198
+ // Validate against model store and apply local filtering/sorting
199
+ let result = this._getValidatedAndFilteredPks(pks);
200
+ // Apply pagination limit
201
+ const limit = this.queryset.build().serializerOptions?.limit;
202
+ if (limit) {
203
+ result = result.slice(0, limit);
204
+ }
205
+ this.setCache(result);
206
+ return result;
207
+ }
208
+ renderFromData(optimistic = true) {
209
+ const renderedPks = this.groundTruthSet;
210
+ for (const op of this.operations) {
211
+ if (op.status !== Status.REJECTED &&
212
+ (optimistic || op.status === Status.CONFIRMED)) {
213
+ this.applyOperation(op, renderedPks);
214
+ }
215
+ }
216
+ let result = Array.from(renderedPks);
217
+ return result;
218
+ }
219
+ /**
220
+ * Render by getting all instances from the model store and filtering locally.
221
+ * Used when a queryset has no ground truth (temp stores, newly created stores, etc.)
222
+ */
223
+ renderFromModelStore() {
224
+ const modelStore = modelStoreRegistry.getStore(this.modelClass);
225
+ const allPks = modelStore.groundTruthPks;
226
+ const allInstances = allPks.map((pk) => this.modelClass.fromPk(pk, this.queryset));
227
+ const ast = this.queryset.build();
228
+ return filter(allInstances, ast, this.modelClass, false);
229
+ }
230
+ applyOperation(operation, currentPks) {
231
+ const pkField = this.pkField;
232
+ for (const instance of operation.instances) {
233
+ if (!instance || typeof instance !== "object" || !(pkField in instance)) {
234
+ console.warn(`[QuerysetStore ${this.modelClass.modelName}] Skipping instance in operation ${operation.operationId} due to missing PK '${String(pkField)}' or invalid format.`);
235
+ continue;
236
+ }
237
+ let pk = instance[pkField];
238
+ switch (operation.type) {
239
+ case Type.CREATE:
240
+ case Type.BULK_CREATE:
241
+ currentPks.add(pk);
242
+ break;
243
+ case Type.CHECKPOINT:
244
+ case Type.UPDATE:
245
+ case Type.UPDATE_INSTANCE:
246
+ break;
247
+ case Type.DELETE:
248
+ case Type.DELETE_INSTANCE:
249
+ currentPks.delete(pk);
250
+ break;
251
+ default:
252
+ console.error(`[QuerysetStore ${this.modelClass.modelName}] Unknown operation type: ${operation.type}`);
253
+ }
254
+ }
255
+ return currentPks;
256
+ }
257
+ /**
258
+ * Sync this queryset with the database.
259
+ * Fetches from DB and sets ground truth.
260
+ */
261
+ async sync() {
262
+ const id = this.modelClass.modelName;
263
+ if (this.isSyncing) {
264
+ console.warn(`[QuerysetStore ${id}] Already syncing, request ignored.`);
265
+ return;
266
+ }
267
+ this.isSyncing = true;
268
+ console.log(`[${id}] Starting sync...`);
269
+ try {
270
+ const response = await this.fetchFn({
271
+ ast: this.queryset.build(),
272
+ modelClass: this.modelClass,
273
+ });
274
+ const { data, included } = response;
275
+ if (!isNil(data)) {
276
+ console.log(`[${id}] Sync fetch completed. Received: ${JSON.stringify(data)}.`);
277
+ // Clear previous included PKs tracking before processing new data
278
+ this.includedPks.clear();
279
+ // Persist all instances (including nested) to the model store
280
+ processIncludedEntities(modelStoreRegistry, included, this.modelClass, this.queryset);
281
+ this.setGroundTruth(data);
282
+ }
283
+ this.setOperations(this.getInflightOperations());
284
+ this.lastSync = Date.now();
285
+ console.log(`[${id}] Sync completed.`);
286
+ }
287
+ catch (e) {
288
+ console.error(`[${id}] Failed to sync ground truth:`, e);
289
+ }
290
+ finally {
291
+ this.isSyncing = false;
292
+ }
293
+ }
294
+ }
@@ -0,0 +1,3 @@
1
+ export const modelEventEmitter: any;
2
+ export const querysetEventEmitter: any;
3
+ export const metricEventEmitter: any;
@@ -0,0 +1,4 @@
1
+ import mitt from 'mitt';
2
+ export const modelEventEmitter = mitt();
3
+ export const querysetEventEmitter = mitt();
4
+ export const metricEventEmitter = mitt();
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Guarantees an array of operations, is an array of operations. Handles
3
+ * the basic failure case of a single operation.
4
+ */
5
+ export function validateOperationsArray(operationsArray: any): any;
6
+ /**
7
+ * Extract the minimal signature we're using for “direct‐match” comparison.
8
+ */
9
+ export function getFingerprint(qs: any): {
10
+ nodes: any;
11
+ initialQueryset: any;
12
+ offset: any;
13
+ limit: any;
14
+ };
@@ -0,0 +1,32 @@
1
+ import { isNil, isEqual } from 'lodash-es';
2
+ import { filter } from '../../filtering/localFiltering.js';
3
+ /**
4
+ * Guarantees an array of operations, is an array of operations. Handles
5
+ * the basic failure case of a single operation.
6
+ */
7
+ export function validateOperationsArray(operationsArray) {
8
+ // verify the operations list
9
+ if (Array.isArray(operationsArray)) {
10
+ if (operationsArray.length > 0) {
11
+ if (!(operationsArray[0] instanceof Operation)) {
12
+ throw new Error(`operationsArray must be Operations not ${typeof (operationsArray[0])}`);
13
+ }
14
+ }
15
+ }
16
+ else if (!isNil(operationsArray)) {
17
+ if (!(operationsArray instanceof Operation)) {
18
+ throw new Error(`operationsArray must be Operations not ${typeof (operationsArray)}`);
19
+ }
20
+ operationsArray = [operationsArray]; // coerce it to be an array
21
+ }
22
+ return operationsArray;
23
+ }
24
+ /**
25
+ * Extract the minimal signature we're using for “direct‐match” comparison.
26
+ */
27
+ export function getFingerprint(qs) {
28
+ const { nodes } = qs;
29
+ const initialQueryset = qs._initialQueryset;
30
+ const { offset = null, limit = null } = qs._serializerOptions || {};
31
+ return { nodes, initialQueryset, offset, limit };
32
+ }
@@ -0,0 +1,51 @@
1
+ export class EventPayload {
2
+ constructor(data: any);
3
+ event: any;
4
+ model: any;
5
+ operation_id: any;
6
+ pk_field_name: any;
7
+ configKey: any;
8
+ instances: any;
9
+ _cachedInstances: any;
10
+ get modelClass(): Function | null;
11
+ getFullInstances(): Promise<any>;
12
+ }
13
+ export class SyncManager {
14
+ registries: Map<any, any>;
15
+ followedModels: Map<any, any>;
16
+ followAllQuerysets: boolean;
17
+ followedQuerysets: Map<any, any>;
18
+ periodicSyncTimer: NodeJS.Timeout | null;
19
+ eventBatch: Map<any, any>;
20
+ debounceTimer: NodeJS.Timeout | null;
21
+ maxWaitTimer: NodeJS.Timeout | null;
22
+ debounceMs: number;
23
+ maxWaitMs: number;
24
+ batchStartTime: number | null;
25
+ withTimeout(promise: any, ms: any): Promise<any>;
26
+ /**
27
+ * Initialize event handlers for all event receivers
28
+ */
29
+ initialize(): void;
30
+ startPeriodicSync(): void;
31
+ syncStaleQuerysets(): Promise<void>;
32
+ pruneUnreferencedModels(): void;
33
+ isStoreFollowed(registry: any, semanticKey: any): boolean;
34
+ cleanup(): void;
35
+ followModel(registry: any, modelClass: any): void;
36
+ unfollowModel(registry: any, modelClass: any): void;
37
+ manageRegistry(registry: any): void;
38
+ removeRegistry(registry: any): void;
39
+ /**
40
+ * Sync querysets that were marked MAYBE for a local operation.
41
+ * Called when a backend event arrives for an operation we initiated locally.
42
+ */
43
+ syncMaybeQuerysets(operationId: any): void;
44
+ handleEvent: (event: any) => void;
45
+ processBatch(reason?: string): void;
46
+ isQuerysetFollowed(queryset: any): boolean;
47
+ processQuerysetsBatch(representativeEvent: any, allEvents: any): void;
48
+ processMetrics(event: any): void;
49
+ processModels(event: any): void;
50
+ }
51
+ export const syncManager: SyncManager;