@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,39 @@
1
+ /**
2
+ * Serializes an action payload based on the action's input schema.
3
+ * Automatically handles model instances (extracts PK), files, dates, etc.
4
+ *
5
+ * @param {Object} payload - The raw payload with potentially model instances
6
+ * @param {Object} inputProperties - The action's input_properties schema
7
+ * @returns {Object} Serialized payload ready for API transmission
8
+ */
9
+ export function serializeActionPayload(payload: Object, inputProperties: Object): Object;
10
+ export namespace fileFieldSerializer {
11
+ function toInternal(value: any, context?: {}): any;
12
+ function toLive(value: any, context?: {}): any;
13
+ }
14
+ export namespace dateFieldSerializer {
15
+ export function toInternal_1(value: any, context?: {}): string | null | undefined;
16
+ export { toInternal_1 as toInternal };
17
+ export function toLive_1(value: any, context?: {}): any;
18
+ export { toLive_1 as toLive };
19
+ }
20
+ export namespace relationshipFieldSerializer {
21
+ export function toInternal_2(value: any, context?: {}): string | number | null | undefined;
22
+ export { toInternal_2 as toInternal };
23
+ export function toLive_2(value: any, context?: {}): any;
24
+ export { toLive_2 as toLive };
25
+ }
26
+ export namespace m2mFieldSerializer {
27
+ export function toInternal_3(value: any, context?: {}): (string | number)[] | null | undefined;
28
+ export { toInternal_3 as toInternal };
29
+ export function toLive_3(value: any, context?: {}): any;
30
+ export { toLive_3 as toLive };
31
+ }
32
+ export class ModelSerializer {
33
+ constructor(modelClass: any);
34
+ modelClass: any;
35
+ toInternalField(field: any, value: any, context?: {}): any;
36
+ toInternal(data: any): {};
37
+ toLiveField(field: any, value: any, context?: {}): any;
38
+ toLive(data: any): {};
39
+ }
@@ -0,0 +1,296 @@
1
+ import { configInstance } from "../../config.js";
2
+ import { isNil } from "lodash-es";
3
+ import { DateParsingHelpers } from "./dates.js";
4
+ /**
5
+ * Gets the backend timezone for a model class
6
+ * @param {Class} ModelClass - The model class
7
+ * @returns {string} The backend timezone or 'UTC' as fallback
8
+ */
9
+ function getBackendTimezone(ModelClass) {
10
+ if (!ModelClass || !ModelClass.configKey) {
11
+ return 'UTC'; // Default fallback
12
+ }
13
+ const config = configInstance.getConfig();
14
+ const backendConfig = config.backendConfigs[ModelClass.configKey] || config.backendConfigs.default;
15
+ return backendConfig.BACKEND_TZ || 'UTC';
16
+ }
17
+ /**
18
+ * File field serializer - handles both camelCase (frontend) and snake_case (backend) formats
19
+ */
20
+ export const fileFieldSerializer = {
21
+ // Store backend snake_case format internally for consistency with API
22
+ toInternal: (value, context = {}) => {
23
+ // Handle plain strings - throw error
24
+ if (typeof value === "string") {
25
+ throw new Error("File field expects a file object, not a string path");
26
+ }
27
+ if (isNil(value)) {
28
+ return null;
29
+ }
30
+ if (typeof value !== "object" || Array.isArray(value)) {
31
+ throw new Error(`expected file object, got ${Array.isArray(value) ? "array" : typeof value}`);
32
+ }
33
+ value = {
34
+ file_path: value.filePath || value.file_path,
35
+ file_name: value.fileName || value.file_name,
36
+ file_url: value.fileUrl || value.file_url,
37
+ size: value.size,
38
+ mime_type: value.mimeType || value.mime_type,
39
+ };
40
+ return value;
41
+ },
42
+ // Return object with both formats for maximum compatibility
43
+ toLive: (value, context = {}) => {
44
+ if (!value || typeof value !== "object")
45
+ return value;
46
+ // Build the proper file URL using the same logic as FileObject
47
+ const backendKey = context.model?.constructor?.configKey || "default";
48
+ const fullFileUrl = value.file_url
49
+ ? configInstance.buildFileUrl(value.file_url, backendKey)
50
+ : null;
51
+ return {
52
+ // snake_case (backend format)
53
+ file_path: value.file_path,
54
+ file_name: value.file_name,
55
+ file_url: fullFileUrl, // Use the built URL here
56
+ size: value.size,
57
+ mime_type: value.mime_type,
58
+ // camelCase (frontend format) - for compatibility
59
+ filePath: value.file_path,
60
+ fileName: value.file_name,
61
+ fileUrl: fullFileUrl, // Use the built URL here too
62
+ mimeType: value.mime_type,
63
+ };
64
+ },
65
+ };
66
+ /**
67
+ * Date/DateTime field serializer - uses DateParsingHelpers like the model does
68
+ */
69
+ export const dateFieldSerializer = {
70
+ toInternal: (value, context = {}) => {
71
+ if (isNil(value))
72
+ return value;
73
+ // If it's already a string, keep it (from API)
74
+ if (typeof value === "string")
75
+ return value;
76
+ // If it's a Date object, serialize it using DateParsingHelpers
77
+ if (value instanceof Date) {
78
+ const { model, field, fieldSchema } = context;
79
+ // Use model schema, or create minimal schema from fieldSchema (for actions)
80
+ const schema = model?.schema || (fieldSchema?.format && {
81
+ properties: { [field]: { format: fieldSchema.format } }
82
+ });
83
+ if (schema) {
84
+ return DateParsingHelpers.serializeDate(value, field, schema);
85
+ }
86
+ // Fallback if no schema context
87
+ return value.toISOString();
88
+ }
89
+ throw new Error(`expected string or Date, got ${typeof value}`);
90
+ },
91
+ toLive: (value, context = {}) => {
92
+ if (isNil(value) || typeof value !== "string")
93
+ return value;
94
+ const { model, field } = context;
95
+ if (model?.schema) {
96
+ // Get the backend timezone for this model
97
+ const timezone = getBackendTimezone(model);
98
+ // Use DateParsingHelpers with timezone awareness
99
+ // This ensures date strings are parsed in the server timezone, not browser timezone
100
+ return DateParsingHelpers.parseDate(value, field, model.schema, timezone);
101
+ }
102
+ // Fallback parsing if no schema context
103
+ try {
104
+ return new Date(value);
105
+ }
106
+ catch (e) {
107
+ console.warn(`Failed to parse date: ${value}`);
108
+ return value;
109
+ }
110
+ },
111
+ };
112
+ /**
113
+ * Foreign Key / One-to-One field serializer - follows existing relationship logic
114
+ */
115
+ export const relationshipFieldSerializer = {
116
+ toInternal: (value, context = {}) => {
117
+ if (isNil(value))
118
+ return value;
119
+ // Extract PK or use value directly
120
+ const pk = value.pk || value;
121
+ // Assert it's a valid PK type
122
+ if (typeof pk !== "string" && typeof pk !== "number") {
123
+ throw new Error(`Invalid primary key type for relationship field: expected string or number, got ${typeof pk}`);
124
+ }
125
+ return pk;
126
+ },
127
+ toLive: (value, context = {}) => {
128
+ if (isNil(value))
129
+ return value;
130
+ // Follow the exact same pattern as the original getField code
131
+ const { model, field } = context;
132
+ if (model.relationshipFields.has(field) && value) {
133
+ const fieldInfo = model.relationshipFields.get(field);
134
+ // For foreign-key and one-to-one, value is guaranteed to be a plain PK
135
+ return fieldInfo.ModelClass().fromPk(value);
136
+ }
137
+ return value;
138
+ },
139
+ };
140
+ /**
141
+ * Many-to-Many field serializer - follows existing m2m logic
142
+ */
143
+ export const m2mFieldSerializer = {
144
+ toInternal: (value, context = {}) => {
145
+ if (isNil(value))
146
+ return value;
147
+ if (!Array.isArray(value))
148
+ throw new Error(`expected array, got ${typeof value}`);
149
+ return value.map((item) => {
150
+ // Extract PK or use item directly
151
+ const pk = item.pk || item;
152
+ // Assert it's a valid PK type
153
+ if (typeof pk !== "string" && typeof pk !== "number") {
154
+ throw new Error(`Invalid primary key type for m2m field: expected string or number, got ${typeof pk}`);
155
+ }
156
+ return pk;
157
+ });
158
+ },
159
+ toLive: (value, context = {}) => {
160
+ if (isNil(value))
161
+ return value;
162
+ // Follow the exact same pattern as the original getField code
163
+ const { model, field } = context;
164
+ if (model.relationshipFields.has(field) && value) {
165
+ const fieldInfo = model.relationshipFields.get(field);
166
+ // Data corruption check like the original
167
+ if (!Array.isArray(value) && value) {
168
+ throw new Error(`Data corruption: m2m field for ${model.modelName} stored as ${value}`);
169
+ }
170
+ // Map each pk to the full model object - exactly like original
171
+ return value.map((pk) => fieldInfo.ModelClass().fromPk(pk));
172
+ }
173
+ return value;
174
+ },
175
+ };
176
+ const serializers = {
177
+ string: {
178
+ "file-path": fileFieldSerializer,
179
+ "image-path": fileFieldSerializer,
180
+ "date": dateFieldSerializer,
181
+ "date-time": dateFieldSerializer,
182
+ "foreign-key": relationshipFieldSerializer,
183
+ "one-to-one": relationshipFieldSerializer,
184
+ },
185
+ integer: {
186
+ "foreign-key": relationshipFieldSerializer,
187
+ "one-to-one": relationshipFieldSerializer,
188
+ },
189
+ // Add other PK types as needed
190
+ uuid: {
191
+ "foreign-key": relationshipFieldSerializer,
192
+ "one-to-one": relationshipFieldSerializer,
193
+ },
194
+ array: {
195
+ "many-to-many": m2mFieldSerializer,
196
+ },
197
+ };
198
+ /**
199
+ * Serializes an action payload based on the action's input schema.
200
+ * Automatically handles model instances (extracts PK), files, dates, etc.
201
+ *
202
+ * @param {Object} payload - The raw payload with potentially model instances
203
+ * @param {Object} inputProperties - The action's input_properties schema
204
+ * @returns {Object} Serialized payload ready for API transmission
205
+ */
206
+ export function serializeActionPayload(payload, inputProperties) {
207
+ if (!payload || !inputProperties)
208
+ return payload;
209
+ const serializedPayload = {};
210
+ for (const [field, value] of Object.entries(payload)) {
211
+ const fieldSchema = inputProperties[field];
212
+ if (!fieldSchema || value === undefined) {
213
+ serializedPayload[field] = value;
214
+ continue;
215
+ }
216
+ const { type, format } = fieldSchema;
217
+ // Check if we have a serializer for this type/format combo
218
+ const typeSerializers = serializers[type];
219
+ const serializer = typeSerializers?.[format];
220
+ if (serializer) {
221
+ serializedPayload[field] = serializer.toInternal(value, { field, fieldSchema });
222
+ }
223
+ else {
224
+ serializedPayload[field] = value;
225
+ }
226
+ }
227
+ return serializedPayload;
228
+ }
229
+ export class ModelSerializer {
230
+ constructor(modelClass) {
231
+ this.modelClass = modelClass;
232
+ }
233
+ toInternalField(field, value, context = {}) {
234
+ const fieldType = this.modelClass.schema?.properties[field]?.type;
235
+ const fieldFormat = this.modelClass.schema?.properties[field]?.format;
236
+ if (serializers[fieldType] && serializers[fieldType][fieldFormat]) {
237
+ return serializers[fieldType][fieldFormat].toInternal(value, {
238
+ model: this.modelClass,
239
+ field,
240
+ ...context,
241
+ });
242
+ }
243
+ // Fallback to default serialization
244
+ return value;
245
+ }
246
+ toInternal(data) {
247
+ const serializedData = {};
248
+ for (const field in data) {
249
+ serializedData[field] = this.toInternalField(field, data[field]);
250
+ }
251
+ return serializedData;
252
+ }
253
+ toLiveField(field, value, context = {}) {
254
+ const fieldType = this.modelClass.schema?.properties[field]?.type;
255
+ const fieldFormat = this.modelClass.schema?.properties[field]?.format;
256
+ if (serializers[fieldType] && serializers[fieldType][fieldFormat]) {
257
+ return serializers[fieldType][fieldFormat].toLive(value, {
258
+ model: this.modelClass,
259
+ field,
260
+ ...context,
261
+ });
262
+ }
263
+ // Django-style type coercion for basic types (mimics get_prep_value)
264
+ if (value !== null && value !== undefined) {
265
+ if (fieldType === 'integer') {
266
+ const num = Number(value);
267
+ return Number.isNaN(num) ? value : Math.trunc(num);
268
+ }
269
+ if (fieldType === 'number') {
270
+ const num = Number(value);
271
+ return Number.isNaN(num) ? value : num;
272
+ }
273
+ if (fieldType === 'boolean') {
274
+ if (typeof value === 'string') {
275
+ const lower = value.toLowerCase();
276
+ if (['true', '1', 't', 'yes'].includes(lower))
277
+ return true;
278
+ if (['false', '0', 'f', 'no', ''].includes(lower))
279
+ return false;
280
+ }
281
+ return Boolean(value);
282
+ }
283
+ if (fieldType === 'string' && typeof value !== 'string') {
284
+ return String(value);
285
+ }
286
+ }
287
+ return value;
288
+ }
289
+ toLive(data) {
290
+ const serializedData = {};
291
+ for (const field in data) {
292
+ serializedData[field] = this.toLiveField(field, data[field]);
293
+ }
294
+ return serializedData;
295
+ }
296
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Register a callback to be notified when a temp pk is resolved to a real pk
3
+ * @param {Function} callback - Called with (tempPk, realPk) when resolved
4
+ * @returns {Function} - Unsubscribe function
5
+ */
6
+ export function onTempPkResolved(callback: Function): Function;
7
+ /**
8
+ * Check if a string contains a temporary PK template
9
+ * @param {string} str - The string to check
10
+ * @returns {boolean} - True if the string contains a TempPK tag
11
+ */
12
+ export function containsTempPk(str: string): boolean;
13
+ /**
14
+ * Create a temporary PK with handlebars syntax
15
+ */
16
+ export function createTempPk(uuid: any): string;
17
+ /**
18
+ * Register a real PK for a temporary PK
19
+ */
20
+ export function setRealPk(uuid: any, realPk: any): void;
21
+ /**
22
+ * Get the real PK for a temp PK if it exists in the registry
23
+ * @param {any} pk - The pk to resolve (may be temp or real)
24
+ * @returns {any} - The real pk if found, otherwise the original pk
25
+ */
26
+ export function resolveToRealPk(pk: any): any;
27
+ /**
28
+ * Replace all temporary PKs in an object (or string) with their real values
29
+ */
30
+ export function replaceTempPks(payload: any): any;
31
+ export const tempPkMap: Map<any, any>;
@@ -0,0 +1,92 @@
1
+ import Handlebars from 'handlebars';
2
+ import superjson from 'superjson';
3
+ // Simple map to store temporary PK to real PK mappings
4
+ export const tempPkMap = new Map();
5
+ // Callbacks to notify when a temp pk is resolved to a real pk
6
+ const onResolveCallbacks = new Set();
7
+ /**
8
+ * Register a callback to be notified when a temp pk is resolved to a real pk
9
+ * @param {Function} callback - Called with (tempPk, realPk) when resolved
10
+ * @returns {Function} - Unsubscribe function
11
+ */
12
+ export function onTempPkResolved(callback) {
13
+ onResolveCallbacks.add(callback);
14
+ return () => onResolveCallbacks.delete(callback);
15
+ }
16
+ /**
17
+ * Check if a string contains a temporary PK template
18
+ * @param {string} str - The string to check
19
+ * @returns {boolean} - True if the string contains a TempPK tag
20
+ */
21
+ export function containsTempPk(str) {
22
+ return (typeof str === 'string' &&
23
+ /\{\{\s*TempPK_[^}\s]+\s*\}\}/.test(str));
24
+ }
25
+ /**
26
+ * Create a temporary PK with handlebars syntax
27
+ */
28
+ export function createTempPk(uuid) {
29
+ const tempPk = `{{TempPK_${uuid}}}`;
30
+ return tempPk;
31
+ }
32
+ /**
33
+ * Register a real PK for a temporary PK
34
+ */
35
+ export function setRealPk(uuid, realPk) {
36
+ const tempPk = `{{TempPK_${uuid}}}`;
37
+ const key = `"TempPK_${uuid}"`;
38
+ const value = typeof realPk === 'string' ? `"${realPk}"` : String(realPk);
39
+ tempPkMap.set(key, value);
40
+ // Notify listeners so they can migrate cache entries
41
+ for (const cb of onResolveCallbacks) {
42
+ try {
43
+ cb(tempPk, realPk);
44
+ }
45
+ catch (e) {
46
+ console.warn('[tempPk] onResolve callback error:', e);
47
+ }
48
+ }
49
+ }
50
+ /**
51
+ * Get the real PK for a temp PK if it exists in the registry
52
+ * @param {any} pk - The pk to resolve (may be temp or real)
53
+ * @returns {any} - The real pk if found, otherwise the original pk
54
+ */
55
+ export function resolveToRealPk(pk) {
56
+ if (!containsTempPk(String(pk)))
57
+ return pk;
58
+ // Extract the uuid from {{TempPK_uuid}}
59
+ const match = String(pk).match(/\{\{\s*TempPK_([^}\s]+)\s*\}\}/);
60
+ if (!match)
61
+ return pk;
62
+ const key = `"TempPK_${match[1]}"`;
63
+ const realPkStr = tempPkMap.get(key);
64
+ if (!realPkStr)
65
+ return pk;
66
+ // Parse the real pk (remove quotes if string, parse if number)
67
+ if (realPkStr.startsWith('"') && realPkStr.endsWith('"')) {
68
+ return realPkStr.slice(1, -1);
69
+ }
70
+ return parseInt(realPkStr, 10);
71
+ }
72
+ /**
73
+ * Replace all temporary PKs in an object (or string) with their real values
74
+ */
75
+ export function replaceTempPks(payload) {
76
+ if (tempPkMap.size === 0)
77
+ return payload;
78
+ const context = Object.fromEntries(tempPkMap);
79
+ try {
80
+ if (typeof payload === 'string') {
81
+ const template = Handlebars.compile(payload, { noEscape: true });
82
+ return template(context);
83
+ }
84
+ const str = superjson.stringify(payload);
85
+ const template = Handlebars.compile(str, { noEscape: true });
86
+ const replaced = template(context);
87
+ return superjson.parse(replaced);
88
+ }
89
+ catch (error) {
90
+ return payload;
91
+ }
92
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Given a live reactive handle and a Promise, wire them together so
3
+ * the handle is also thenable.
4
+ *
5
+ * @template T
6
+ * @param {LiveQueryset} live
7
+ * @param {Promise<T>} promise
8
+ * @returns {LiveQueryset & Promise<T>}
9
+ */
10
+ export function makeLiveThenable<T>(live: LiveQueryset, promise: Promise<T>): LiveQueryset & Promise<T>;
11
+ /**
12
+ * Remove the thenable hooks and clear the optimistic flag in-place, so the object
13
+ * can be returned without causing a recursive await loop.
14
+ *
15
+ * @template T
16
+ * @param {T} live
17
+ * @returns {T}
18
+ */
19
+ export function breakThenable<T>(live: T): T;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Given a live reactive handle and a Promise, wire them together so
3
+ * the handle is also thenable.
4
+ *
5
+ * @template T
6
+ * @param {LiveQueryset} live
7
+ * @param {Promise<T>} promise
8
+ * @returns {LiveQueryset & Promise<T>}
9
+ */
10
+ export function makeLiveThenable(live, promise) {
11
+ live.isOptimistic = true;
12
+ live.then = promise.then.bind(promise);
13
+ live.catch = promise.catch.bind(promise);
14
+ return live;
15
+ }
16
+ /**
17
+ * Remove the thenable hooks and clear the optimistic flag in-place, so the object
18
+ * can be returned without causing a recursive await loop.
19
+ *
20
+ * @template T
21
+ * @param {T} live
22
+ * @returns {T}
23
+ */
24
+ export function breakThenable(live) {
25
+ delete live.isOptimistic;
26
+ delete live.then;
27
+ delete live.catch;
28
+ return live;
29
+ }
@@ -0,0 +1,46 @@
1
+ import { EventType } from "./core/eventReceivers.js";
2
+ import { PusherEventReceiver } from "./core/eventReceivers.js";
3
+ import { setEventReceiver } from "./core/eventReceivers.js";
4
+ import { getEventReceiver } from "./core/eventReceivers.js";
5
+ import { setNamespaceResolver } from "./core/eventReceivers.js";
6
+ import { setupStateZero } from "./setup.js";
7
+ import { resetStateZero } from "./reset.js";
8
+ import { FileObject } from "./flavours/django/files.js";
9
+ import { querysetStoreRegistry } from "./syncEngine/registries/querysetStoreRegistry.js";
10
+ import { modelStoreRegistry } from "./syncEngine/registries/modelStoreRegistry.js";
11
+ import { metricRegistry } from "./syncEngine/registries/metricRegistry.js";
12
+ import { syncManager } from "./syncEngine/sync.js";
13
+ import { Operation } from "./syncEngine/stores/operation.js";
14
+ import { operationRegistry } from "./syncEngine/stores/operation.js";
15
+ import { Q } from "./flavours/django/q.js";
16
+ import { StateZeroError } from "./flavours/django/errors.js";
17
+ import { ValidationError } from "./flavours/django/errors.js";
18
+ import { DoesNotExist } from "./flavours/django/errors.js";
19
+ import { PermissionDenied } from "./flavours/django/errors.js";
20
+ import { MultipleObjectsReturned } from "./flavours/django/errors.js";
21
+ import { ASTValidationError } from "./flavours/django/errors.js";
22
+ import { ConfigError } from "./flavours/django/errors.js";
23
+ import { parseStateZeroError } from "./flavours/django/errors.js";
24
+ import { QuerySet } from "./flavours/django/querySet.js";
25
+ import { Manager } from "./flavours/django/manager.js";
26
+ import { ResultTuple } from "./flavours/django/queryExecutor.js";
27
+ import { Model } from "./flavours/django/model.js";
28
+ import { setConfig } from "./config.js";
29
+ import { getConfig } from "./config.js";
30
+ import { setBackendConfig } from "./config.js";
31
+ import { initializeEventReceiver } from "./config.js";
32
+ import { configInstance } from "./config.js";
33
+ import { getModelClass } from "./config.js";
34
+ import { initEventHandler } from "./syncEngine/stores/operationEventHandlers.js";
35
+ import { cleanupEventHandler } from "./syncEngine/stores/operationEventHandlers.js";
36
+ import { setAdapters } from "./reactiveAdaptor.js";
37
+ import { wrapReactiveModel } from "./reactiveAdaptor.js";
38
+ import { wrapReactiveQuerySet } from "./reactiveAdaptor.js";
39
+ import { serializeActionPayload } from "./flavours/django/serializers.js";
40
+ import { onStateZeroError } from "./errorHandler.js";
41
+ import { createTestConfig } from "./testing.js";
42
+ import { setupTestStateZero } from "./testing.js";
43
+ import { createActionMocker } from "./testing.js";
44
+ import { seedRemote } from "./testing.js";
45
+ import { resetRemote } from "./testing.js";
46
+ export { EventType, PusherEventReceiver, setEventReceiver, getEventReceiver, setNamespaceResolver, setupStateZero, resetStateZero, FileObject, querysetStoreRegistry, modelStoreRegistry, metricRegistry, syncManager, Operation, operationRegistry, Q, StateZeroError, ValidationError, DoesNotExist, PermissionDenied, MultipleObjectsReturned, ASTValidationError, ConfigError, parseStateZeroError, QuerySet, Manager, ResultTuple, Model, setConfig, getConfig, setBackendConfig, initializeEventReceiver, configInstance, getModelClass, initEventHandler, cleanupEventHandler, setAdapters, wrapReactiveModel, wrapReactiveQuerySet, serializeActionPayload, onStateZeroError, createTestConfig, setupTestStateZero, createActionMocker, seedRemote, resetRemote };
package/dist/index.js ADDED
@@ -0,0 +1,48 @@
1
+ // Core event receivers
2
+ import { EventType, PusherEventReceiver, setEventReceiver, getEventReceiver, setNamespaceResolver, } from "./core/eventReceivers.js";
3
+ import { setupStateZero } from "./setup.js";
4
+ // Django flavor modules
5
+ import { Q } from "./flavours/django/q.js";
6
+ import { StateZeroError, ValidationError, DoesNotExist, PermissionDenied, MultipleObjectsReturned, ASTValidationError, ConfigError, parseStateZeroError, } from "./flavours/django/errors.js";
7
+ import { querysetStoreRegistry } from "./syncEngine/registries/querysetStoreRegistry.js";
8
+ import { modelStoreRegistry } from "./syncEngine/registries/modelStoreRegistry.js";
9
+ import { metricRegistry } from "./syncEngine/registries/metricRegistry.js";
10
+ import { QueryExecutor, ResultTuple } from "./flavours/django/queryExecutor.js";
11
+ import { Operation, operationRegistry } from "./syncEngine/stores/operation.js";
12
+ import { QuerySet } from "./flavours/django/querySet.js";
13
+ import { Manager } from "./flavours/django/manager.js";
14
+ import { Model } from "./flavours/django/model.js";
15
+ import { FileObject } from "./flavours/django/files.js";
16
+ import { serializeActionPayload } from "./flavours/django/serializers.js";
17
+ // Configuration
18
+ import { setConfig, getConfig, setBackendConfig, initializeEventReceiver, configInstance, getModelClass, } from "./config.js";
19
+ import { setAdapters, wrapReactiveModel, wrapReactiveQuerySet, } from "./reactiveAdaptor.js";
20
+ import { syncManager } from "./syncEngine/sync.js";
21
+ import { initEventHandler, cleanupEventHandler, } from "./syncEngine/stores/operationEventHandlers.js";
22
+ import { resetStateZero } from "./reset.js";
23
+ import { onStateZeroError } from "./errorHandler.js";
24
+ import { createTestConfig, setupTestStateZero, createActionMocker, seedRemote, resetRemote, } from "./testing.js";
25
+ // Explicitly export everything
26
+ export {
27
+ // Core event receivers
28
+ EventType, PusherEventReceiver, setEventReceiver, getEventReceiver, setNamespaceResolver,
29
+ // Setup
30
+ setupStateZero, resetStateZero,
31
+ // Files
32
+ FileObject,
33
+ // Registry
34
+ querysetStoreRegistry, modelStoreRegistry, metricRegistry, syncManager,
35
+ // Operations
36
+ Operation, operationRegistry,
37
+ // Django flavor modules
38
+ Q, StateZeroError, ValidationError, DoesNotExist, PermissionDenied, MultipleObjectsReturned, ASTValidationError, ConfigError, parseStateZeroError, QuerySet, Manager, ResultTuple, Model,
39
+ // Configuration
40
+ setConfig, getConfig, setBackendConfig, initializeEventReceiver, configInstance, getModelClass,
41
+ // Reactivity framework integration
42
+ initEventHandler, cleanupEventHandler, setAdapters, wrapReactiveModel, wrapReactiveQuerySet,
43
+ // Action utilities
44
+ serializeActionPayload,
45
+ // Error handling
46
+ onStateZeroError,
47
+ // Testing helpers
48
+ createTestConfig, setupTestStateZero, createActionMocker, seedRemote, resetRemote, };