@statezero/core 0.2.37 → 0.2.38

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 (307) hide show
  1. package/dist/adaptors/vue/components/LayoutRenderer.js +166 -0
  2. package/dist/adaptors/vue/components/defaults/AlertElement.js +31 -0
  3. package/dist/adaptors/vue/components/defaults/DisplayElement.js +44 -0
  4. package/dist/adaptors/vue/components/defaults/DividerElement.js +10 -0
  5. package/dist/adaptors/vue/components/defaults/ErrorBlock.js +24 -0
  6. package/dist/adaptors/vue/components/defaults/GroupElement.js +41 -0
  7. package/dist/adaptors/vue/components/defaults/LabelElement.js +21 -0
  8. package/dist/adaptors/vue/components/defaults/TabsElement.js +38 -0
  9. package/package.json +6 -4
  10. package/dist/actions/backend1/django_app/calculate-hash.d.ts +0 -57
  11. package/dist/actions/backend1/django_app/calculate-hash.js +0 -80
  12. package/dist/actions/backend1/django_app/calculate-hash.schema.json +0 -148
  13. package/dist/actions/backend1/django_app/get-current-username.d.ts +0 -29
  14. package/dist/actions/backend1/django_app/get-current-username.js +0 -65
  15. package/dist/actions/backend1/django_app/get-current-username.schema.json +0 -47
  16. package/dist/actions/backend1/django_app/get-server-status.d.ts +0 -38
  17. package/dist/actions/backend1/django_app/get-server-status.js +0 -68
  18. package/dist/actions/backend1/django_app/get-server-status.schema.json +0 -93
  19. package/dist/actions/backend1/django_app/get-user-info.d.ts +0 -44
  20. package/dist/actions/backend1/django_app/get-user-info.js +0 -70
  21. package/dist/actions/backend1/django_app/get-user-info.schema.json +0 -127
  22. package/dist/actions/backend1/django_app/index.d.ts +0 -1
  23. package/dist/actions/backend1/django_app/index.js +0 -6
  24. package/dist/actions/backend1/django_app/process-data.d.ts +0 -51
  25. package/dist/actions/backend1/django_app/process-data.js +0 -78
  26. package/dist/actions/backend1/django_app/process-data.schema.json +0 -117
  27. package/dist/actions/backend1/django_app/send-notification.d.ts +0 -55
  28. package/dist/actions/backend1/django_app/send-notification.js +0 -81
  29. package/dist/actions/backend1/django_app/send-notification.schema.json +0 -175
  30. package/dist/actions/backend1/index.d.ts +0 -1
  31. package/dist/actions/backend1/index.js +0 -1
  32. package/dist/actions/default/django_app/calculate-hash.d.ts +0 -57
  33. package/dist/actions/default/django_app/calculate-hash.js +0 -80
  34. package/dist/actions/default/django_app/calculate-hash.schema.json +0 -148
  35. package/dist/actions/default/django_app/get-current-username.d.ts +0 -29
  36. package/dist/actions/default/django_app/get-current-username.js +0 -65
  37. package/dist/actions/default/django_app/get-current-username.schema.json +0 -47
  38. package/dist/actions/default/django_app/get-server-status.d.ts +0 -38
  39. package/dist/actions/default/django_app/get-server-status.js +0 -68
  40. package/dist/actions/default/django_app/get-server-status.schema.json +0 -93
  41. package/dist/actions/default/django_app/get-user-info.d.ts +0 -44
  42. package/dist/actions/default/django_app/get-user-info.js +0 -70
  43. package/dist/actions/default/django_app/get-user-info.schema.json +0 -127
  44. package/dist/actions/default/django_app/index.d.ts +0 -1
  45. package/dist/actions/default/django_app/index.js +0 -6
  46. package/dist/actions/default/django_app/process-data.d.ts +0 -51
  47. package/dist/actions/default/django_app/process-data.js +0 -78
  48. package/dist/actions/default/django_app/process-data.schema.json +0 -117
  49. package/dist/actions/default/django_app/send-notification.d.ts +0 -55
  50. package/dist/actions/default/django_app/send-notification.js +0 -81
  51. package/dist/actions/default/django_app/send-notification.schema.json +0 -175
  52. package/dist/actions/default/index.d.ts +0 -1
  53. package/dist/actions/default/index.js +0 -1
  54. package/dist/actions/index.d.ts +0 -1
  55. package/dist/actions/index.js +0 -5
  56. package/dist/adaptors/react/composables.d.ts +0 -1
  57. package/dist/adaptors/react/composables.js +0 -4
  58. package/dist/adaptors/react/index.d.ts +0 -1
  59. package/dist/adaptors/react/index.js +0 -1
  60. package/dist/adaptors/vue/components/LayoutRenderer.vue +0 -361
  61. package/dist/adaptors/vue/components/defaults/AlertElement.vue +0 -38
  62. package/dist/adaptors/vue/components/defaults/DisplayElement.vue +0 -57
  63. package/dist/adaptors/vue/components/defaults/DividerElement.vue +0 -13
  64. package/dist/adaptors/vue/components/defaults/ErrorBlock.vue +0 -28
  65. package/dist/adaptors/vue/components/defaults/GroupElement.vue +0 -53
  66. package/dist/adaptors/vue/components/defaults/LabelElement.vue +0 -25
  67. package/dist/adaptors/vue/components/defaults/TabsElement.vue +0 -54
  68. package/dist/adaptors/vue/components/defaults/index.d.ts +0 -7
  69. package/dist/adaptors/vue/components/defaults/index.js +0 -31
  70. package/dist/adaptors/vue/components/index.d.ts +0 -1
  71. package/dist/adaptors/vue/components/index.js +0 -7
  72. package/dist/adaptors/vue/composables.d.ts +0 -2
  73. package/dist/adaptors/vue/composables.js +0 -44
  74. package/dist/adaptors/vue/index.d.ts +0 -3
  75. package/dist/adaptors/vue/index.js +0 -4
  76. package/dist/adaptors/vue/reactivity.d.ts +0 -18
  77. package/dist/adaptors/vue/reactivity.js +0 -132
  78. package/dist/cli/commands/sync.d.ts +0 -6
  79. package/dist/cli/commands/sync.js +0 -30
  80. package/dist/cli/commands/syncActions.d.ts +0 -46
  81. package/dist/cli/commands/syncActions.js +0 -717
  82. package/dist/cli/commands/syncModels.d.ts +0 -132
  83. package/dist/cli/commands/syncModels.js +0 -1120
  84. package/dist/cli/configFileLoader.d.ts +0 -10
  85. package/dist/cli/configFileLoader.js +0 -85
  86. package/dist/cli/index.d.ts +0 -2
  87. package/dist/cli/index.js +0 -22
  88. package/dist/config.d.ts +0 -57
  89. package/dist/config.js +0 -273
  90. package/dist/core/eventReceivers.d.ts +0 -185
  91. package/dist/core/eventReceivers.js +0 -266
  92. package/dist/core/utils.d.ts +0 -8
  93. package/dist/core/utils.js +0 -62
  94. package/dist/errorHandler.d.ts +0 -21
  95. package/dist/errorHandler.js +0 -27
  96. package/dist/filtering/localFiltering.d.ts +0 -110
  97. package/dist/filtering/localFiltering.js +0 -1080
  98. package/dist/flavours/django/dates.d.ts +0 -34
  99. package/dist/flavours/django/dates.js +0 -113
  100. package/dist/flavours/django/errors.d.ts +0 -138
  101. package/dist/flavours/django/errors.js +0 -195
  102. package/dist/flavours/django/f.d.ts +0 -6
  103. package/dist/flavours/django/f.js +0 -91
  104. package/dist/flavours/django/files.d.ts +0 -62
  105. package/dist/flavours/django/files.js +0 -355
  106. package/dist/flavours/django/makeApiCall.d.ts +0 -36
  107. package/dist/flavours/django/makeApiCall.js +0 -169
  108. package/dist/flavours/django/manager.d.ts +0 -204
  109. package/dist/flavours/django/manager.js +0 -222
  110. package/dist/flavours/django/model.d.ts +0 -137
  111. package/dist/flavours/django/model.js +0 -366
  112. package/dist/flavours/django/operationFactory.d.ts +0 -73
  113. package/dist/flavours/django/operationFactory.js +0 -248
  114. package/dist/flavours/django/q.d.ts +0 -70
  115. package/dist/flavours/django/q.js +0 -43
  116. package/dist/flavours/django/queryExecutor.d.ts +0 -149
  117. package/dist/flavours/django/queryExecutor.js +0 -590
  118. package/dist/flavours/django/querySet.d.ts +0 -301
  119. package/dist/flavours/django/querySet.js +0 -736
  120. package/dist/flavours/django/serializers.d.ts +0 -39
  121. package/dist/flavours/django/serializers.js +0 -296
  122. package/dist/flavours/django/tempPk.d.ts +0 -31
  123. package/dist/flavours/django/tempPk.js +0 -92
  124. package/dist/flavours/django/utils.d.ts +0 -19
  125. package/dist/flavours/django/utils.js +0 -29
  126. package/dist/index.d.ts +0 -46
  127. package/dist/index.js +0 -48
  128. package/dist/models/backend1/django_app/comprehensivemodel.d.ts +0 -894
  129. package/dist/models/backend1/django_app/comprehensivemodel.js +0 -71
  130. package/dist/models/backend1/django_app/comprehensivemodel.schema.json +0 -870
  131. package/dist/models/backend1/django_app/custompkmodel.d.ts +0 -92
  132. package/dist/models/backend1/django_app/custompkmodel.js +0 -69
  133. package/dist/models/backend1/django_app/custompkmodel.schema.json +0 -71
  134. package/dist/models/backend1/django_app/dailyrate.d.ts +0 -230
  135. package/dist/models/backend1/django_app/dailyrate.js +0 -71
  136. package/dist/models/backend1/django_app/dailyrate.schema.json +0 -212
  137. package/dist/models/backend1/django_app/deepmodellevel1.d.ts +0 -140
  138. package/dist/models/backend1/django_app/deepmodellevel1.js +0 -72
  139. package/dist/models/backend1/django_app/deepmodellevel1.schema.json +0 -114
  140. package/dist/models/backend1/django_app/deepmodellevel2.d.ts +0 -118
  141. package/dist/models/backend1/django_app/deepmodellevel2.js +0 -71
  142. package/dist/models/backend1/django_app/deepmodellevel2.schema.json +0 -92
  143. package/dist/models/backend1/django_app/deepmodellevel3.d.ts +0 -92
  144. package/dist/models/backend1/django_app/deepmodellevel3.js +0 -69
  145. package/dist/models/backend1/django_app/deepmodellevel3.schema.json +0 -69
  146. package/dist/models/backend1/django_app/dummymodel.d.ts +0 -134
  147. package/dist/models/backend1/django_app/dummymodel.js +0 -71
  148. package/dist/models/backend1/django_app/dummymodel.schema.json +0 -109
  149. package/dist/models/backend1/django_app/dummyrelatedmodel.d.ts +0 -92
  150. package/dist/models/backend1/django_app/dummyrelatedmodel.js +0 -69
  151. package/dist/models/backend1/django_app/dummyrelatedmodel.schema.json +0 -69
  152. package/dist/models/backend1/django_app/filetest.d.ts +0 -140
  153. package/dist/models/backend1/django_app/filetest.js +0 -69
  154. package/dist/models/backend1/django_app/filetest.schema.json +0 -111
  155. package/dist/models/backend1/django_app/index.d.ts +0 -1
  156. package/dist/models/backend1/django_app/index.js +0 -21
  157. package/dist/models/backend1/django_app/m2mdepthtestlevel1.d.ts +0 -118
  158. package/dist/models/backend1/django_app/m2mdepthtestlevel1.js +0 -71
  159. package/dist/models/backend1/django_app/m2mdepthtestlevel1.schema.json +0 -94
  160. package/dist/models/backend1/django_app/m2mdepthtestlevel2.d.ts +0 -118
  161. package/dist/models/backend1/django_app/m2mdepthtestlevel2.js +0 -71
  162. package/dist/models/backend1/django_app/m2mdepthtestlevel2.schema.json +0 -94
  163. package/dist/models/backend1/django_app/m2mdepthtestlevel3.d.ts +0 -134
  164. package/dist/models/backend1/django_app/m2mdepthtestlevel3.js +0 -71
  165. package/dist/models/backend1/django_app/m2mdepthtestlevel3.schema.json +0 -112
  166. package/dist/models/backend1/django_app/modelwithcustompkrelation.d.ts +0 -118
  167. package/dist/models/backend1/django_app/modelwithcustompkrelation.js +0 -71
  168. package/dist/models/backend1/django_app/modelwithcustompkrelation.schema.json +0 -93
  169. package/dist/models/backend1/django_app/modelwithrestrictedfields.d.ts +0 -134
  170. package/dist/models/backend1/django_app/modelwithrestrictedfields.js +0 -71
  171. package/dist/models/backend1/django_app/modelwithrestrictedfields.schema.json +0 -111
  172. package/dist/models/backend1/django_app/namefiltercustompkmodel.d.ts +0 -92
  173. package/dist/models/backend1/django_app/namefiltercustompkmodel.js +0 -69
  174. package/dist/models/backend1/django_app/namefiltercustompkmodel.schema.json +0 -71
  175. package/dist/models/backend1/django_app/order.d.ts +0 -220
  176. package/dist/models/backend1/django_app/order.js +0 -71
  177. package/dist/models/backend1/django_app/order.schema.json +0 -203
  178. package/dist/models/backend1/django_app/orderitem.d.ts +0 -172
  179. package/dist/models/backend1/django_app/orderitem.js +0 -72
  180. package/dist/models/backend1/django_app/orderitem.schema.json +0 -149
  181. package/dist/models/backend1/django_app/product.d.ts +0 -254
  182. package/dist/models/backend1/django_app/product.js +0 -71
  183. package/dist/models/backend1/django_app/product.schema.json +0 -277
  184. package/dist/models/backend1/django_app/productcategory.d.ts +0 -92
  185. package/dist/models/backend1/django_app/productcategory.js +0 -69
  186. package/dist/models/backend1/django_app/productcategory.schema.json +0 -70
  187. package/dist/models/backend1/django_app/rateplan.d.ts +0 -92
  188. package/dist/models/backend1/django_app/rateplan.js +0 -69
  189. package/dist/models/backend1/django_app/rateplan.schema.json +0 -70
  190. package/dist/models/backend1/django_app/restrictedfieldrelatedmodel.d.ts +0 -108
  191. package/dist/models/backend1/django_app/restrictedfieldrelatedmodel.js +0 -69
  192. package/dist/models/backend1/django_app/restrictedfieldrelatedmodel.schema.json +0 -87
  193. package/dist/models/backend1/fileobject.d.ts +0 -4
  194. package/dist/models/backend1/fileobject.js +0 -9
  195. package/dist/models/backend1/index.d.ts +0 -2
  196. package/dist/models/backend1/index.js +0 -2
  197. package/dist/models/default/django_app/comprehensivemodel.d.ts +0 -894
  198. package/dist/models/default/django_app/comprehensivemodel.js +0 -71
  199. package/dist/models/default/django_app/comprehensivemodel.schema.json +0 -870
  200. package/dist/models/default/django_app/custompkmodel.d.ts +0 -92
  201. package/dist/models/default/django_app/custompkmodel.js +0 -69
  202. package/dist/models/default/django_app/custompkmodel.schema.json +0 -71
  203. package/dist/models/default/django_app/dailyrate.d.ts +0 -230
  204. package/dist/models/default/django_app/dailyrate.js +0 -71
  205. package/dist/models/default/django_app/dailyrate.schema.json +0 -212
  206. package/dist/models/default/django_app/deepmodellevel1.d.ts +0 -128
  207. package/dist/models/default/django_app/deepmodellevel1.js +0 -72
  208. package/dist/models/default/django_app/deepmodellevel1.schema.json +0 -102
  209. package/dist/models/default/django_app/deepmodellevel2.d.ts +0 -106
  210. package/dist/models/default/django_app/deepmodellevel2.js +0 -71
  211. package/dist/models/default/django_app/deepmodellevel2.schema.json +0 -80
  212. package/dist/models/default/django_app/deepmodellevel3.d.ts +0 -80
  213. package/dist/models/default/django_app/deepmodellevel3.js +0 -69
  214. package/dist/models/default/django_app/deepmodellevel3.schema.json +0 -57
  215. package/dist/models/default/django_app/dummymodel.d.ts +0 -122
  216. package/dist/models/default/django_app/dummymodel.js +0 -71
  217. package/dist/models/default/django_app/dummymodel.schema.json +0 -97
  218. package/dist/models/default/django_app/dummyrelatedmodel.d.ts +0 -80
  219. package/dist/models/default/django_app/dummyrelatedmodel.js +0 -69
  220. package/dist/models/default/django_app/dummyrelatedmodel.schema.json +0 -57
  221. package/dist/models/default/django_app/filetest.d.ts +0 -128
  222. package/dist/models/default/django_app/filetest.js +0 -69
  223. package/dist/models/default/django_app/filetest.schema.json +0 -99
  224. package/dist/models/default/django_app/index.d.ts +0 -1
  225. package/dist/models/default/django_app/index.js +0 -21
  226. package/dist/models/default/django_app/m2mdepthtestlevel1.d.ts +0 -118
  227. package/dist/models/default/django_app/m2mdepthtestlevel1.js +0 -71
  228. package/dist/models/default/django_app/m2mdepthtestlevel1.schema.json +0 -94
  229. package/dist/models/default/django_app/m2mdepthtestlevel2.d.ts +0 -118
  230. package/dist/models/default/django_app/m2mdepthtestlevel2.js +0 -71
  231. package/dist/models/default/django_app/m2mdepthtestlevel2.schema.json +0 -94
  232. package/dist/models/default/django_app/m2mdepthtestlevel3.d.ts +0 -134
  233. package/dist/models/default/django_app/m2mdepthtestlevel3.js +0 -71
  234. package/dist/models/default/django_app/m2mdepthtestlevel3.schema.json +0 -112
  235. package/dist/models/default/django_app/modelwithcustompkrelation.d.ts +0 -118
  236. package/dist/models/default/django_app/modelwithcustompkrelation.js +0 -71
  237. package/dist/models/default/django_app/modelwithcustompkrelation.schema.json +0 -93
  238. package/dist/models/default/django_app/modelwithrestrictedfields.d.ts +0 -134
  239. package/dist/models/default/django_app/modelwithrestrictedfields.js +0 -71
  240. package/dist/models/default/django_app/modelwithrestrictedfields.schema.json +0 -111
  241. package/dist/models/default/django_app/namefiltercustompkmodel.d.ts +0 -92
  242. package/dist/models/default/django_app/namefiltercustompkmodel.js +0 -69
  243. package/dist/models/default/django_app/namefiltercustompkmodel.schema.json +0 -71
  244. package/dist/models/default/django_app/order.d.ts +0 -220
  245. package/dist/models/default/django_app/order.js +0 -71
  246. package/dist/models/default/django_app/order.schema.json +0 -203
  247. package/dist/models/default/django_app/orderitem.d.ts +0 -172
  248. package/dist/models/default/django_app/orderitem.js +0 -72
  249. package/dist/models/default/django_app/orderitem.schema.json +0 -149
  250. package/dist/models/default/django_app/product.d.ts +0 -254
  251. package/dist/models/default/django_app/product.js +0 -71
  252. package/dist/models/default/django_app/product.schema.json +0 -277
  253. package/dist/models/default/django_app/productcategory.d.ts +0 -92
  254. package/dist/models/default/django_app/productcategory.js +0 -69
  255. package/dist/models/default/django_app/productcategory.schema.json +0 -70
  256. package/dist/models/default/django_app/rateplan.d.ts +0 -92
  257. package/dist/models/default/django_app/rateplan.js +0 -69
  258. package/dist/models/default/django_app/rateplan.schema.json +0 -70
  259. package/dist/models/default/django_app/restrictedfieldrelatedmodel.d.ts +0 -108
  260. package/dist/models/default/django_app/restrictedfieldrelatedmodel.js +0 -69
  261. package/dist/models/default/django_app/restrictedfieldrelatedmodel.schema.json +0 -87
  262. package/dist/models/default/fileobject.d.ts +0 -4
  263. package/dist/models/default/fileobject.js +0 -9
  264. package/dist/models/default/index.d.ts +0 -2
  265. package/dist/models/default/index.js +0 -2
  266. package/dist/models/index.d.ts +0 -1
  267. package/dist/models/index.js +0 -5
  268. package/dist/react-entry.d.ts +0 -2
  269. package/dist/react-entry.js +0 -2
  270. package/dist/reactiveAdaptor.d.ts +0 -24
  271. package/dist/reactiveAdaptor.js +0 -38
  272. package/dist/reset.d.ts +0 -15
  273. package/dist/reset.js +0 -97
  274. package/dist/setup.d.ts +0 -15
  275. package/dist/setup.js +0 -33
  276. package/dist/syncEngine/cache/cache.d.ts +0 -75
  277. package/dist/syncEngine/cache/cache.js +0 -355
  278. package/dist/syncEngine/metrics/metricOptCalcs.d.ts +0 -79
  279. package/dist/syncEngine/metrics/metricOptCalcs.js +0 -284
  280. package/dist/syncEngine/registries/metricRegistry.d.ts +0 -58
  281. package/dist/syncEngine/registries/metricRegistry.js +0 -171
  282. package/dist/syncEngine/registries/modelStoreRegistry.d.ts +0 -11
  283. package/dist/syncEngine/registries/modelStoreRegistry.js +0 -63
  284. package/dist/syncEngine/registries/querysetStoreGraph.d.ts +0 -41
  285. package/dist/syncEngine/registries/querysetStoreGraph.js +0 -174
  286. package/dist/syncEngine/registries/querysetStoreRegistry.d.ts +0 -72
  287. package/dist/syncEngine/registries/querysetStoreRegistry.js +0 -335
  288. package/dist/syncEngine/stores/metricStore.d.ts +0 -55
  289. package/dist/syncEngine/stores/metricStore.js +0 -222
  290. package/dist/syncEngine/stores/modelStore.d.ts +0 -53
  291. package/dist/syncEngine/stores/modelStore.js +0 -565
  292. package/dist/syncEngine/stores/operation.d.ts +0 -139
  293. package/dist/syncEngine/stores/operation.js +0 -291
  294. package/dist/syncEngine/stores/operationEventHandlers.d.ts +0 -8
  295. package/dist/syncEngine/stores/operationEventHandlers.js +0 -322
  296. package/dist/syncEngine/stores/querysetStore.d.ts +0 -60
  297. package/dist/syncEngine/stores/querysetStore.js +0 -294
  298. package/dist/syncEngine/stores/reactivity.d.ts +0 -3
  299. package/dist/syncEngine/stores/reactivity.js +0 -4
  300. package/dist/syncEngine/stores/utils.d.ts +0 -14
  301. package/dist/syncEngine/stores/utils.js +0 -32
  302. package/dist/syncEngine/sync.d.ts +0 -46
  303. package/dist/syncEngine/sync.js +0 -389
  304. package/dist/testing.d.ts +0 -63
  305. package/dist/testing.js +0 -175
  306. package/dist/vue-entry.d.ts +0 -15
  307. package/dist/vue-entry.js +0 -7
@@ -1,366 +0,0 @@
1
- import { Manager } from "./manager.js";
2
- import { ValidationError } from "./errors.js";
3
- import { modelStoreRegistry } from "../../syncEngine/registries/modelStoreRegistry.js";
4
- import { isNil } from "lodash-es";
5
- import { QueryExecutor } from "./queryExecutor.js";
6
- import { wrapReactiveModel } from "../../reactiveAdaptor.js";
7
- import { DateParsingHelpers } from "./dates.js";
8
- import { FileObject } from './files.js';
9
- import { configInstance } from "../../config.js";
10
- import { ModelSerializer } from "./serializers.js";
11
- import { parseStateZeroError, MultipleObjectsReturned, DoesNotExist, } from "./errors.js";
12
- import axios from "axios";
13
- /**
14
- * A constructor for a Model.
15
- *
16
- * @typedef {Function} ModelConstructor
17
- * @param {any} data - Data to initialize the model.
18
- * @returns {Model}
19
- *
20
- * @property {Manager} objects - The model's manager.
21
- * @property {string} configKey - The configuration key.
22
- * @property {string} modelName - The model name.
23
- * @property {string} primaryKeyField - The primary key field (default 'id').
24
- */
25
- /**
26
- * Base Model class with integrated API implementation.
27
- *
28
- * @abstract
29
- */
30
- export class Model {
31
- constructor(data = {}) {
32
- this.serializer = new ModelSerializer(this.constructor);
33
- const serializedData = this.serializer.toInternal(data);
34
- this._data = serializedData;
35
- this._pk = serializedData[this.constructor.primaryKeyField] || undefined;
36
- this.__version = 0;
37
- return wrapReactiveModel(this);
38
- }
39
- /**
40
- * Remote-only manager that skips local store updates.
41
- */
42
- static get remote() {
43
- return this.objects.remote();
44
- }
45
- touch() {
46
- this.__version++;
47
- }
48
- /**
49
- * Returns the primary key of the model instance.
50
- *
51
- * @returns {number|undefined} The primary key.
52
- */
53
- get pk() {
54
- return this._pk;
55
- }
56
- /**
57
- * Sets the primary key of the model instance.
58
- *
59
- * @param {number|undefined} value - The new primary key value.
60
- */
61
- set pk(value) {
62
- this._pk = value;
63
- this.touch();
64
- }
65
- /**
66
- * Instantiate from pk using queryset scoped singletons
67
- */
68
- static fromPk(pk, querySet) {
69
- let qsId = querySet ? querySet.__uuid : "";
70
- let key = `${qsId}__${this.configKey}__${this.modelName}__${pk}`;
71
- if (!this.instanceCache.has(key)) {
72
- const instance = new this();
73
- instance.pk = pk;
74
- this.instanceCache.set(key, instance);
75
- }
76
- return this.instanceCache.get(key);
77
- }
78
- /**
79
- * Gets a field value from the internal data store
80
- *
81
- * @param {string} field - The field name
82
- * @returns {any} The field value
83
- */
84
- getField(field) {
85
- // Access the reactive __version property to establish dependency for vue integration
86
- const trackVersion = this.__version;
87
- const ModelClass = this.constructor;
88
- if (ModelClass.primaryKeyField === field)
89
- return this._pk;
90
- // check local overrides
91
- let value = this._data[field];
92
- // if its not been overridden, get it from the store
93
- if (value === undefined && !isNil(this._pk)) {
94
- let storedValue = modelStoreRegistry.getEntity(ModelClass, this._pk);
95
- if (storedValue)
96
- value = storedValue[field]; // if stops null -> undefined
97
- }
98
- // Use serializer to convert internal format to live format
99
- return this.serializer.toLiveField(field, value);
100
- }
101
- /**
102
- * Sets a field value in the internal data store
103
- *
104
- * @param {string} field - The field name
105
- * @param {any} value - The field value to set
106
- */
107
- setField(field, value) {
108
- const ModelClass = this.constructor;
109
- // Use serializer to convert live format to internal format
110
- const internalValue = this.serializer.toInternalField(field, value);
111
- if (ModelClass.primaryKeyField === field) {
112
- this._pk = internalValue;
113
- }
114
- else {
115
- this._data[field] = internalValue;
116
- }
117
- }
118
- /**
119
- * Validates that the provided data object only contains keys
120
- * defined in the model's allowed fields. Supports nested fields
121
- * using double underscore notation (e.g., author__name).
122
- *
123
- * @param {Object} data - The object to validate.
124
- * @throws {ValidationError} If an unknown key is found.
125
- */
126
- static validateFields(data) {
127
- if (isNil(data))
128
- return;
129
- const allowedFields = this.fields;
130
- for (const key of Object.keys(data)) {
131
- if (key === "repr" || key === "type")
132
- continue;
133
- // Handle nested fields by splitting on double underscore
134
- // and taking just the base field name
135
- const baseField = key.split("__")[0];
136
- if (!allowedFields.includes(baseField)) {
137
- let errorMsg = `Invalid field: ${baseField}. Allowed fields are: ${allowedFields.join(", ")}`;
138
- console.error(errorMsg);
139
- throw new ValidationError(errorMsg);
140
- }
141
- }
142
- }
143
- /**
144
- * Serializes the model instance.
145
- *
146
- * By default, it returns all enumerable own properties.
147
- * Subclasses should override this to return specific keys.
148
- *
149
- * @param {boolean} includeRepr - Whether to include the repr field (for caching). Default: false.
150
- * @returns {Object} The serialized model data.
151
- */
152
- serialize(includeRepr = false) {
153
- const ModelClass = this.constructor;
154
- const data = {};
155
- // Collect all field values (already in internal format)
156
- for (const field of ModelClass.fields) {
157
- if (field === ModelClass.primaryKeyField) {
158
- data[field] = this._pk;
159
- }
160
- else {
161
- let value = this._data[field];
162
- // Get from store if not in local data
163
- if (value === undefined && !isNil(this._pk)) {
164
- const storedData = modelStoreRegistry.getEntity(ModelClass, this._pk);
165
- if (storedData) {
166
- value = storedData[field];
167
- }
168
- }
169
- data[field] = value;
170
- }
171
- }
172
- // Include repr field if requested (for caching purposes)
173
- if (includeRepr && !isNil(this._pk)) {
174
- const storedData = modelStoreRegistry.getEntity(ModelClass, this._pk);
175
- if (storedData && storedData.repr) {
176
- data.repr = storedData.repr;
177
- }
178
- }
179
- // Data is already in internal format, so return as-is for API transmission
180
- return data;
181
- }
182
- /**
183
- * Saves the model instance by either creating a new record or updating an existing one.
184
- *
185
- * @returns {Promise<Model>} A promise that resolves to the updated model instance.
186
- */
187
- async save() {
188
- const ModelClass = this.constructor;
189
- const pkField = ModelClass.primaryKeyField;
190
- const querySet = !this.pk
191
- ? ModelClass.objects.newQuerySet()
192
- : ModelClass.objects.filter({ [pkField]: this.pk });
193
- const data = this.serialize();
194
- let instance;
195
- if (!this.pk) {
196
- // Create new instance
197
- instance = await QueryExecutor.execute(querySet, "create", { data });
198
- }
199
- else {
200
- // Update existing instance
201
- instance = await QueryExecutor.execute(querySet, "update_instance", {
202
- data,
203
- });
204
- }
205
- this._pk = instance.pk;
206
- this._data = {};
207
- return this;
208
- }
209
- /**
210
- * Deletes the instance from the database.
211
- *
212
- * Returns a tuple with the number of objects deleted and an object mapping
213
- * model names to the number of objects deleted, matching Django's behavior.
214
- *
215
- * @returns {Promise<[number, Object]>} A promise that resolves to the deletion result.
216
- * @throws {Error} If the instance has not been saved (no primary key).
217
- */
218
- async delete() {
219
- if (!this.pk) {
220
- throw new Error("Cannot delete unsaved instance");
221
- }
222
- const ModelClass = this.constructor;
223
- const pkField = ModelClass.primaryKeyField;
224
- const querySet = ModelClass.objects.filter({ [pkField]: this.pk });
225
- // Pass the instance data with primary key as the args
226
- const args = { [pkField]: this.pk };
227
- const result = await QueryExecutor.execute(querySet, "delete_instance", args);
228
- // result -> [deletedCount, { [modelName]: deletedCount }];
229
- return result;
230
- }
231
- /**
232
- * Refreshes the model instance with data from the database.
233
- *
234
- * @returns {Promise<void>} A promise that resolves when the instance has been refreshed.
235
- * @throws {Error} If the instance has not been saved (no primary key).
236
- */
237
- async refreshFromDb() {
238
- if (!this.pk) {
239
- throw new Error("Cannot refresh unsaved instance");
240
- }
241
- const ModelClass = this.constructor;
242
- const fresh = await ModelClass.objects.get({
243
- [ModelClass.primaryKeyField]: this.pk,
244
- });
245
- // clear the current data and fresh data will flow
246
- this._data = {};
247
- }
248
- /**
249
- * Validates the model instance using the same serialize behavior as save()
250
- * @param {string} validateType - 'create' or 'update' (defaults to auto-detect)
251
- * @param {boolean} partial - Whether to allow partial validation
252
- * @returns {Promise<boolean>} Promise that resolves to true if valid, throws error if invalid
253
- */
254
- async validate(validateType = null, partial = false) {
255
- const ModelClass = this.constructor;
256
- if (!validateType) {
257
- validateType = this.pk ? "update" : "create";
258
- }
259
- // Validate the validateType parameter
260
- if (!["update", "create"].includes(validateType)) {
261
- throw new Error(`Validation type must be 'update' or 'create', not '${validateType}'`);
262
- }
263
- // Use the same serialize logic as save()
264
- const data = this.serialize();
265
- // Delegate to static method
266
- return ModelClass.validate(data, validateType, partial);
267
- }
268
- /**
269
- * Static method to validate data without creating an instance
270
- * @param {Object} data - Data to validate
271
- * @param {string} validateType - 'create' or 'update'
272
- * @param {boolean} partial - Whether to allow partial validation
273
- * @returns {Promise<boolean>} Promise that resolves to true if valid, throws error if invalid
274
- */
275
- static async validate(data, validateType = "create", partial = false) {
276
- const ModelClass = this;
277
- // Validate the validateType parameter
278
- if (!["update", "create"].includes(validateType)) {
279
- throw new Error(`Validation type must be 'update' or 'create', not '${validateType}'`);
280
- }
281
- // Get backend config and check if it exists
282
- const config = configInstance.getConfig();
283
- const backend = config.backendConfigs[ModelClass.configKey];
284
- if (!backend) {
285
- throw new Error(`No backend configuration found for key: ${ModelClass.configKey}`);
286
- }
287
- // Build URL for validate endpoint
288
- const baseUrl = backend.API_URL.replace(/\/+$/, "");
289
- const url = `${baseUrl}/${ModelClass.modelName}/validate/`;
290
- // Prepare headers
291
- const headers = {
292
- "Content-Type": "application/json",
293
- ...(backend.getAuthHeaders ? backend.getAuthHeaders() : {}),
294
- };
295
- // Make direct API call to validate endpoint
296
- try {
297
- const response = await axios.post(url, {
298
- data: data,
299
- validate_type: validateType,
300
- partial: partial,
301
- }, { headers });
302
- // Backend returns {"valid": true} on success
303
- return response.data.valid === true;
304
- }
305
- catch (error) {
306
- if (error.response && error.response.data) {
307
- const parsedError = parseStateZeroError(error.response.data);
308
- if (Error.captureStackTrace) {
309
- Error.captureStackTrace(parsedError, ModelClass.validate);
310
- }
311
- throw parsedError;
312
- }
313
- throw new Error(`Validation failed: ${error.message}`);
314
- }
315
- }
316
- /**
317
- * Get field permissions for the current user (cached on the class)
318
- * @param {boolean} refresh - Force refresh the cached permissions
319
- * @returns {Promise<{visible_fields: string[], creatable_fields: string[], editable_fields: string[]}>}
320
- */
321
- static async getFieldPermissions(refresh = false) {
322
- const ModelClass = this;
323
- // Return cached permissions if available and not forcing refresh
324
- if (!refresh && ModelClass._fieldPermissionsCache) {
325
- return ModelClass._fieldPermissionsCache;
326
- }
327
- // Get backend config and check if it exists
328
- const config = configInstance.getConfig();
329
- const backend = config.backendConfigs[ModelClass.configKey];
330
- if (!backend) {
331
- throw new Error(`No backend configuration found for key: ${ModelClass.configKey}`);
332
- }
333
- // Build URL for field permissions endpoint
334
- const baseUrl = backend.API_URL.replace(/\/+$/, "");
335
- const url = `${baseUrl}/${ModelClass.modelName}/field-permissions/`;
336
- // Prepare headers
337
- const headers = {
338
- "Content-Type": "application/json",
339
- ...(backend.getAuthHeaders ? backend.getAuthHeaders() : {}),
340
- };
341
- // Make direct API call to field permissions endpoint
342
- try {
343
- const response = await axios.get(url, { headers });
344
- // Cache the permissions on the class
345
- ModelClass._fieldPermissionsCache = response.data;
346
- // Backend returns {visible_fields: [], creatable_fields: [], editable_fields: []}
347
- return response.data;
348
- }
349
- catch (error) {
350
- if (error.response && error.response.data) {
351
- const parsedError = parseStateZeroError(error.response.data);
352
- if (Error.captureStackTrace) {
353
- Error.captureStackTrace(parsedError, ModelClass.getFieldPermissions);
354
- }
355
- throw parsedError;
356
- }
357
- throw new Error(`Failed to get field permissions: ${error.message}`);
358
- }
359
- }
360
- }
361
- /**
362
- * Creates a new Model instance.
363
- *
364
- * @param {any} [data={}] - The data for initialization.
365
- */
366
- Model.instanceCache = new Map();
@@ -1,73 +0,0 @@
1
- /**
2
- * Factory for creating Operation instances with consistent behavior
3
- * across QueryExecutor and hotpath event handling
4
- */
5
- export class OperationFactory {
6
- /**
7
- * Create a CREATE operation
8
- * @param {QuerySet} queryset - The queryset context
9
- * @param {Object} data - The data for the new instance
10
- * @param {string} [operationId] - Optional operation ID (for hotpath events)
11
- * @returns {Operation} The created operation
12
- */
13
- static createCreateOperation(queryset: QuerySet, data?: Object, operationId?: string): Operation;
14
- /**
15
- * Create a BULK_CREATE operation
16
- * @param {QuerySet} queryset - The queryset context
17
- * @param {Array<Object>} dataList - Array of data objects for the new instances
18
- * @param {string} [operationId] - Optional operation ID (for hotpath events)
19
- * @returns {Operation} The created operation
20
- */
21
- static createBulkCreateOperation(queryset: QuerySet, dataList?: Array<Object>, operationId?: string): Operation;
22
- /**
23
- * Create an UPDATE operation with optimistic instance updates
24
- * @param {QuerySet} queryset - The queryset context
25
- * @param {Object} data - The update data
26
- * @param {Object} filter - Optional filter for the update
27
- * @param {string} [operationId] - Optional operation ID (for hotpath events)
28
- * @returns {Operation} The created operation
29
- */
30
- static createUpdateOperation(queryset: QuerySet, data?: Object, filter?: Object, operationId?: string): Operation;
31
- /**
32
- * Create a DELETE operation
33
- * @param {QuerySet} queryset - The queryset context
34
- * @param {string} [operationId] - Optional operation ID (for hotpath events)
35
- * @returns {Operation} The created operation
36
- */
37
- static createDeleteOperation(queryset: QuerySet, operationId?: string): Operation;
38
- /**
39
- * Create an UPDATE_INSTANCE operation
40
- * @param {QuerySet} queryset - The queryset context
41
- * @param {Object} data - The update data
42
- * @param {string} [operationId] - Optional operation ID (for hotpath events)
43
- * @returns {Operation} The created operation
44
- */
45
- static createUpdateInstanceOperation(queryset: QuerySet, data?: Object, operationId?: string): Operation;
46
- /**
47
- * Create a DELETE_INSTANCE operation
48
- * @param {QuerySet} queryset - The queryset context
49
- * @param {Object} instanceData - The instance to delete (object with PK)
50
- * @param {string} [operationId] - Optional operation ID (for hotpath events)
51
- * @returns {Operation} The created operation
52
- */
53
- static createDeleteInstanceOperation(queryset: QuerySet, instanceData: Object, operationId?: string): Operation;
54
- /**
55
- * Create a GET_OR_CREATE operation with local filtering logic
56
- * @param {QuerySet} queryset - The queryset context
57
- * @param {Object} lookup - The lookup criteria
58
- * @param {Object} defaults - The default values for creation
59
- * @param {string} [operationId] - Optional operation ID (for hotpath events)
60
- * @returns {Operation} The created operation
61
- */
62
- static createGetOrCreateOperation(queryset: QuerySet, lookup?: Object, defaults?: Object, operationId?: string): Operation;
63
- /**
64
- * Create an UPDATE_OR_CREATE operation with local filtering logic
65
- * @param {QuerySet} queryset - The queryset context
66
- * @param {Object} lookup - The lookup criteria
67
- * @param {Object} defaults - The default values for creation/update
68
- * @param {string} [operationId] - Optional operation ID (for hotpath events)
69
- * @returns {Operation} The created operation
70
- */
71
- static createUpdateOrCreateOperation(queryset: QuerySet, lookup?: Object, defaults?: Object, operationId?: string): Operation;
72
- }
73
- import { Operation } from '../../syncEngine/stores/operation.js';
@@ -1,248 +0,0 @@
1
- import { Operation, Type, Status } from '../../syncEngine/stores/operation.js';
2
- import { v7 as uuid7 } from 'uuid';
3
- import { createTempPk } from './tempPk.js';
4
- import { getRequiredFields, pickRequiredFields, processQuery } from '../../filtering/localFiltering.js';
5
- import { evaluateExpression } from './f.js';
6
- import { modelStoreRegistry } from '../../syncEngine/registries/modelStoreRegistry.js';
7
- import { querysetStoreRegistry } from '../../syncEngine/registries/querysetStoreRegistry.js';
8
- import { isNil } from 'lodash-es';
9
- /**
10
- * Factory for creating Operation instances with consistent behavior
11
- * across QueryExecutor and hotpath event handling
12
- */
13
- export class OperationFactory {
14
- /**
15
- * Create a CREATE operation
16
- * @param {QuerySet} queryset - The queryset context
17
- * @param {Object} data - The data for the new instance
18
- * @param {string} [operationId] - Optional operation ID (for hotpath events)
19
- * @returns {Operation} The created operation
20
- */
21
- static createCreateOperation(queryset, data = {}, operationId = null) {
22
- const ModelClass = queryset.ModelClass;
23
- const primaryKeyField = ModelClass.primaryKeyField;
24
- const opId = operationId || `${uuid7()}`;
25
- const tempPk = createTempPk(opId);
26
- return new Operation({
27
- operationId: opId,
28
- type: Type.CREATE,
29
- instances: [{ ...data, [primaryKeyField]: tempPk }],
30
- queryset: queryset,
31
- args: { data },
32
- localOnly: queryset._optimisticOnly || false,
33
- });
34
- }
35
- /**
36
- * Create a BULK_CREATE operation
37
- * @param {QuerySet} queryset - The queryset context
38
- * @param {Array<Object>} dataList - Array of data objects for the new instances
39
- * @param {string} [operationId] - Optional operation ID (for hotpath events)
40
- * @returns {Operation} The created operation
41
- */
42
- static createBulkCreateOperation(queryset, dataList = [], operationId = null) {
43
- const ModelClass = queryset.ModelClass;
44
- const primaryKeyField = ModelClass.primaryKeyField;
45
- const opId = operationId || `${uuid7()}`;
46
- // Create temp PKs for each instance
47
- const instances = dataList.map((data, index) => {
48
- const tempPk = createTempPk(`${opId}_${index}`);
49
- return { ...data, [primaryKeyField]: tempPk };
50
- });
51
- return new Operation({
52
- operationId: opId,
53
- type: Type.BULK_CREATE,
54
- instances: instances,
55
- queryset: queryset,
56
- args: { data: dataList },
57
- localOnly: queryset._optimisticOnly || false,
58
- });
59
- }
60
- /**
61
- * Create an UPDATE operation with optimistic instance updates
62
- * @param {QuerySet} queryset - The queryset context
63
- * @param {Object} data - The update data
64
- * @param {Object} filter - Optional filter for the update
65
- * @param {string} [operationId] - Optional operation ID (for hotpath events)
66
- * @returns {Operation} The created operation
67
- */
68
- static createUpdateOperation(queryset, data = {}, filter = null, operationId = null) {
69
- const ModelClass = queryset.ModelClass;
70
- const primaryKeyField = ModelClass.primaryKeyField;
71
- const store = querysetStoreRegistry.getStore(queryset);
72
- const querysetPks = store.render();
73
- const opId = operationId || `${uuid7()}`;
74
- // Create optimistic instances with F expression evaluation
75
- const optimisticInstances = querysetPks.map(pk => {
76
- const instance = modelStoreRegistry.getEntity(ModelClass, pk);
77
- const updatedInstance = { ...instance };
78
- updatedInstance[primaryKeyField] = pk;
79
- for (const [key, value] of Object.entries(data)) {
80
- if (value && typeof value === 'object' && value.__f_expr) {
81
- const evaluatedValue = evaluateExpression(value, instance);
82
- if (evaluatedValue !== null) {
83
- updatedInstance[key] = evaluatedValue;
84
- }
85
- else {
86
- updatedInstance[key] = instance[key];
87
- }
88
- }
89
- else {
90
- updatedInstance[key] = value;
91
- }
92
- }
93
- return updatedInstance;
94
- });
95
- return new Operation({
96
- operationId: opId,
97
- type: Type.UPDATE,
98
- instances: optimisticInstances,
99
- queryset: queryset,
100
- args: { filter, data },
101
- localOnly: queryset._optimisticOnly || false,
102
- });
103
- }
104
- /**
105
- * Create a DELETE operation
106
- * @param {QuerySet} queryset - The queryset context
107
- * @param {string} [operationId] - Optional operation ID (for hotpath events)
108
- * @returns {Operation} The created operation
109
- */
110
- static createDeleteOperation(queryset, operationId = null) {
111
- const ModelClass = queryset.ModelClass;
112
- const primaryKeyField = ModelClass.primaryKeyField;
113
- const store = querysetStoreRegistry.getStore(queryset);
114
- const querysetPks = store.render();
115
- const opId = operationId || `${uuid7()}`;
116
- const instances = querysetPks.map((pk) => ({ [primaryKeyField]: pk }));
117
- return new Operation({
118
- operationId: opId,
119
- type: Type.DELETE,
120
- instances: instances,
121
- queryset: queryset,
122
- args: {},
123
- localOnly: queryset._optimisticOnly || false,
124
- });
125
- }
126
- /**
127
- * Create an UPDATE_INSTANCE operation
128
- * @param {QuerySet} queryset - The queryset context
129
- * @param {Object} data - The update data
130
- * @param {string} [operationId] - Optional operation ID (for hotpath events)
131
- * @returns {Operation} The created operation
132
- */
133
- static createUpdateInstanceOperation(queryset, data = {}, operationId = null) {
134
- const ModelClass = queryset.ModelClass;
135
- const primaryKeyField = ModelClass.primaryKeyField;
136
- const store = querysetStoreRegistry.getStore(queryset);
137
- const querysetPks = store.render();
138
- const opId = operationId || `${uuid7()}`;
139
- const instances = querysetPks.map(pk => ({ ...data, [primaryKeyField]: pk }));
140
- return new Operation({
141
- operationId: opId,
142
- type: Type.UPDATE_INSTANCE,
143
- instances: instances,
144
- queryset: queryset,
145
- args: { data },
146
- localOnly: queryset._optimisticOnly || false,
147
- });
148
- }
149
- /**
150
- * Create a DELETE_INSTANCE operation
151
- * @param {QuerySet} queryset - The queryset context
152
- * @param {Object} instanceData - The instance to delete (object with PK)
153
- * @param {string} [operationId] - Optional operation ID (for hotpath events)
154
- * @returns {Operation} The created operation
155
- */
156
- static createDeleteInstanceOperation(queryset, instanceData, operationId = null) {
157
- const opId = operationId || `${uuid7()}`;
158
- return new Operation({
159
- operationId: opId,
160
- type: Type.DELETE_INSTANCE,
161
- instances: [instanceData],
162
- queryset: queryset,
163
- args: instanceData,
164
- localOnly: queryset._optimisticOnly || false,
165
- });
166
- }
167
- /**
168
- * Create a GET_OR_CREATE operation with local filtering logic
169
- * @param {QuerySet} queryset - The queryset context
170
- * @param {Object} lookup - The lookup criteria
171
- * @param {Object} defaults - The default values for creation
172
- * @param {string} [operationId] - Optional operation ID (for hotpath events)
173
- * @returns {Operation} The created operation
174
- */
175
- static createGetOrCreateOperation(queryset, lookup = {}, defaults = {}, operationId = null) {
176
- const ModelClass = queryset.ModelClass;
177
- const primaryKeyField = ModelClass.primaryKeyField;
178
- const opId = operationId || `${uuid7()}`;
179
- // Get all current instances from the store for local filtering
180
- const modelStore = modelStoreRegistry.getStore(ModelClass);
181
- const allInstances = modelStore.render();
182
- // Create a queryset filter for the lookup criteria
183
- const lookupFilter = { ...lookup };
184
- const lookupQuerySet = new queryset.constructor(ModelClass).filter(lookupFilter);
185
- const lookupQuery = lookupQuerySet.build();
186
- // Use local filtering to find matching instances
187
- const requiredPaths = getRequiredFields(lookupQuery, ModelClass);
188
- const prunedData = allInstances.map(inst => pickRequiredFields(requiredPaths, ModelClass.fromPk(inst[primaryKeyField], queryset)));
189
- const matchingPks = processQuery(prunedData, lookupQuery, ModelClass);
190
- // Find the corresponding instances
191
- const matchingInstances = allInstances.filter(inst => matchingPks.includes(inst[primaryKeyField]));
192
- const isCreatingNew = matchingInstances.length === 0;
193
- const effectiveType = isCreatingNew ? Type.CREATE : Type.UPDATE;
194
- // Create the instance data
195
- const instanceData = isCreatingNew
196
- ? { ...lookup, ...defaults, [primaryKeyField]: opId }
197
- : matchingInstances[0];
198
- return new Operation({
199
- operationId: opId,
200
- type: effectiveType,
201
- instances: [instanceData],
202
- queryset: queryset,
203
- args: { lookup, defaults },
204
- localOnly: queryset._optimisticOnly || false,
205
- });
206
- }
207
- /**
208
- * Create an UPDATE_OR_CREATE operation with local filtering logic
209
- * @param {QuerySet} queryset - The queryset context
210
- * @param {Object} lookup - The lookup criteria
211
- * @param {Object} defaults - The default values for creation/update
212
- * @param {string} [operationId] - Optional operation ID (for hotpath events)
213
- * @returns {Operation} The created operation
214
- */
215
- static createUpdateOrCreateOperation(queryset, lookup = {}, defaults = {}, operationId = null) {
216
- const ModelClass = queryset.ModelClass;
217
- const primaryKeyField = ModelClass.primaryKeyField;
218
- const opId = operationId || `${uuid7()}`;
219
- // Get all current instances from the store for local filtering
220
- const modelStore = modelStoreRegistry.getStore(ModelClass);
221
- const allInstances = modelStore.render();
222
- // Create a queryset filter for the lookup criteria
223
- const lookupFilter = { ...lookup };
224
- const lookupQuerySet = new queryset.constructor(ModelClass).filter(lookupFilter);
225
- const lookupQuery = lookupQuerySet.build();
226
- // Use local filtering to find matching instances
227
- const requiredPaths = getRequiredFields(lookupQuery, ModelClass);
228
- const prunedData = allInstances.map(inst => pickRequiredFields(requiredPaths, ModelClass.fromPk(inst[primaryKeyField], queryset)));
229
- const matchingPks = processQuery(prunedData, lookupQuery, ModelClass);
230
- // Find the corresponding instances
231
- const matchingInstances = allInstances.filter(inst => matchingPks.includes(inst[primaryKeyField]));
232
- const isCreatingNew = matchingInstances.length === 0;
233
- const isUpdating = !isCreatingNew;
234
- const effectiveType = isCreatingNew ? Type.CREATE : Type.UPDATE;
235
- // Create the instance data
236
- const instanceData = isCreatingNew
237
- ? { ...lookup, ...defaults, [primaryKeyField]: opId }
238
- : { ...matchingInstances[0], ...defaults };
239
- return new Operation({
240
- operationId: opId,
241
- type: effectiveType,
242
- instances: [instanceData],
243
- queryset: queryset,
244
- args: { lookup, defaults },
245
- localOnly: queryset._optimisticOnly || false,
246
- });
247
- }
248
- }