on-zero 0.7.10 → 0.8.0

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 (546) hide show
  1. package/{readme.md → README.md} +172 -231
  2. package/dist/cjs/cli.cjs +5 -2
  3. package/dist/cjs/cli.native.js +5 -2
  4. package/dist/cjs/cli.native.js.map +1 -1
  5. package/dist/cjs/combineZeroClients.cjs +2 -2
  6. package/dist/cjs/combineZeroClients.native.js +6 -6
  7. package/dist/cjs/combineZeroClients.native.js.map +1 -1
  8. package/dist/cjs/config.cjs +30 -0
  9. package/dist/cjs/config.native.js +33 -0
  10. package/dist/cjs/config.native.js.map +1 -0
  11. package/dist/cjs/createPermissions.cjs +2 -2
  12. package/dist/cjs/createPermissions.native.js +17 -27
  13. package/dist/cjs/createPermissions.native.js.map +1 -1
  14. package/dist/cjs/createUseQuery.cjs +3 -3
  15. package/dist/cjs/createUseQuery.native.js +4 -4
  16. package/dist/cjs/createUseQuery.native.js.map +1 -1
  17. package/dist/cjs/createUseQueryDirect.cjs +4 -3
  18. package/dist/cjs/createUseQueryDirect.native.js +14 -18
  19. package/dist/cjs/createUseQueryDirect.native.js.map +1 -1
  20. package/dist/cjs/createZeroClient.cjs +29 -9
  21. package/dist/cjs/createZeroClient.connection.test.cjs +11 -0
  22. package/dist/cjs/createZeroClient.connection.test.native.js +14 -7
  23. package/dist/cjs/createZeroClient.connection.test.native.js.map +1 -1
  24. package/dist/cjs/createZeroClient.native.js +58 -32
  25. package/dist/cjs/createZeroClient.native.js.map +1 -1
  26. package/dist/cjs/createZeroClient.recovery.test.cjs +90 -3
  27. package/dist/cjs/createZeroClient.recovery.test.native.js +109 -19
  28. package/dist/cjs/createZeroClient.recovery.test.native.js.map +1 -1
  29. package/dist/cjs/generate-helpers.cjs +70 -17
  30. package/dist/cjs/generate-helpers.native.js +110 -23
  31. package/dist/cjs/generate-helpers.native.js.map +1 -1
  32. package/dist/cjs/generate-layout.cjs +586 -0
  33. package/dist/cjs/generate-layout.native.js +1275 -0
  34. package/dist/cjs/generate-layout.native.js.map +1 -0
  35. package/dist/cjs/generate-lite.cjs +295 -27
  36. package/dist/cjs/generate-lite.native.js +854 -102
  37. package/dist/cjs/generate-lite.native.js.map +1 -1
  38. package/dist/cjs/generate-lite.test.cjs +433 -41
  39. package/dist/cjs/generate-lite.test.native.js +446 -41
  40. package/dist/cjs/generate-lite.test.native.js.map +1 -1
  41. package/dist/cjs/generate.cjs +172 -94
  42. package/dist/cjs/generate.native.js +324 -148
  43. package/dist/cjs/generate.native.js.map +1 -1
  44. package/dist/cjs/generate.test.cjs +362 -45
  45. package/dist/cjs/generate.test.native.js +374 -45
  46. package/dist/cjs/generate.test.native.js.map +1 -1
  47. package/dist/cjs/helpers/NullToOptional.cjs +18 -0
  48. package/dist/cjs/helpers/NullToOptional.native.js +21 -0
  49. package/dist/cjs/helpers/NullToOptional.native.js.map +1 -0
  50. package/dist/cjs/helpers/asyncContext.cjs +128 -0
  51. package/dist/cjs/helpers/asyncContext.native.js +87 -0
  52. package/dist/cjs/helpers/asyncContext.native.js.map +1 -0
  53. package/dist/cjs/helpers/batchQuery.cjs +2 -2
  54. package/dist/cjs/helpers/batchQuery.native.js +2 -2
  55. package/dist/cjs/helpers/batchQuery.native.js.map +1 -1
  56. package/dist/cjs/helpers/createMutators.cjs +7 -4
  57. package/dist/cjs/helpers/createMutators.native.js +12 -9
  58. package/dist/cjs/helpers/createMutators.native.js.map +1 -1
  59. package/dist/cjs/helpers/createMutators.test.native.js +2 -2
  60. package/dist/cjs/helpers/createMutators.test.native.js.map +1 -1
  61. package/dist/cjs/helpers/ellipsis.cjs +35 -0
  62. package/dist/cjs/helpers/ellipsis.native.js +38 -0
  63. package/dist/cjs/helpers/ellipsis.native.js.map +1 -0
  64. package/dist/cjs/helpers/emitter.cjs +99 -0
  65. package/dist/cjs/helpers/emitter.native.js +125 -0
  66. package/dist/cjs/helpers/emitter.native.js.map +1 -0
  67. package/dist/cjs/helpers/ensure.cjs +33 -0
  68. package/dist/cjs/helpers/ensure.native.js +37 -0
  69. package/dist/cjs/helpers/ensure.native.js.map +1 -0
  70. package/dist/cjs/helpers/ensureLoggedIn.cjs +2 -2
  71. package/dist/cjs/helpers/ensureLoggedIn.native.js +3 -3
  72. package/dist/cjs/helpers/ensureLoggedIn.native.js.map +1 -1
  73. package/dist/cjs/helpers/errors.cjs +40 -0
  74. package/dist/cjs/helpers/errors.native.js +152 -0
  75. package/dist/cjs/helpers/errors.native.js.map +1 -0
  76. package/dist/cjs/helpers/getCurrentComponentStack.cjs +71 -0
  77. package/dist/cjs/helpers/getCurrentComponentStack.native.js +93 -0
  78. package/dist/cjs/helpers/getCurrentComponentStack.native.js.map +1 -0
  79. package/dist/cjs/helpers/globalValue.cjs +39 -0
  80. package/dist/cjs/helpers/globalValue.native.js +42 -0
  81. package/dist/cjs/helpers/globalValue.native.js.map +1 -0
  82. package/dist/cjs/helpers/mapObject.cjs +36 -0
  83. package/dist/cjs/helpers/mapObject.native.js +39 -0
  84. package/dist/cjs/helpers/mapObject.native.js.map +1 -0
  85. package/dist/cjs/helpers/mutationLifecycle.cjs +251 -0
  86. package/dist/cjs/helpers/mutationLifecycle.native.js +392 -0
  87. package/dist/cjs/helpers/mutationLifecycle.native.js.map +1 -0
  88. package/dist/cjs/helpers/mutationLifecycle.test.cjs +174 -0
  89. package/dist/cjs/helpers/mutationLifecycle.test.native.js +182 -0
  90. package/dist/cjs/helpers/mutationLifecycle.test.native.js.map +1 -0
  91. package/dist/cjs/helpers/mutatorContext.cjs +3 -3
  92. package/dist/cjs/helpers/mutatorContext.native.js +5 -5
  93. package/dist/cjs/helpers/mutatorContext.native.js.map +1 -1
  94. package/dist/cjs/helpers/platform.cjs +31 -0
  95. package/dist/cjs/helpers/platform.native.js +33 -0
  96. package/dist/cjs/helpers/platform.native.js.map +1 -0
  97. package/dist/cjs/helpers/prettyFormatZeroQuery.cjs +2 -2
  98. package/dist/cjs/helpers/prettyFormatZeroQuery.native.js +7 -7
  99. package/dist/cjs/helpers/prettyFormatZeroQuery.native.js.map +1 -1
  100. package/dist/cjs/helpers/queryContext.cjs +2 -2
  101. package/dist/cjs/helpers/queryContext.native.js +4 -4
  102. package/dist/cjs/helpers/queryContext.native.js.map +1 -1
  103. package/dist/cjs/helpers/recoverZeroClient.cjs +14 -15
  104. package/dist/cjs/helpers/recoverZeroClient.native.js +26 -23
  105. package/dist/cjs/helpers/recoverZeroClient.native.js.map +1 -1
  106. package/dist/cjs/helpers/recoverZeroClient.test.cjs +10 -8
  107. package/dist/cjs/helpers/recoverZeroClient.test.native.js +17 -21
  108. package/dist/cjs/helpers/recoverZeroClient.test.native.js.map +1 -1
  109. package/dist/cjs/helpers/sleep.cjs +34 -0
  110. package/dist/cjs/helpers/sleep.native.js +39 -0
  111. package/dist/cjs/helpers/sleep.native.js.map +1 -0
  112. package/dist/cjs/helpers/time.cjs +47 -0
  113. package/dist/cjs/helpers/time.native.js +80 -0
  114. package/dist/cjs/helpers/time.native.js.map +1 -0
  115. package/dist/cjs/helpers/tuple.cjs +18 -0
  116. package/dist/cjs/helpers/tuple.native.js +21 -0
  117. package/dist/cjs/helpers/tuple.native.js.map +1 -0
  118. package/dist/cjs/helpers/useMutation.native.js +5 -5
  119. package/dist/cjs/helpers/useMutation.native.js.map +1 -1
  120. package/dist/cjs/helpers/useMutation.test.native.js +1 -1
  121. package/dist/cjs/helpers/useMutation.test.native.js.map +1 -1
  122. package/dist/cjs/helpers/useZeroDebug.cjs +2 -2
  123. package/dist/cjs/helpers/useZeroDebug.native.js +7 -8
  124. package/dist/cjs/helpers/useZeroDebug.native.js.map +1 -1
  125. package/dist/cjs/index.cjs +9 -1
  126. package/dist/cjs/index.native.js +8 -0
  127. package/dist/cjs/index.native.js.map +1 -1
  128. package/dist/cjs/instanceRegistry.cjs +16 -4
  129. package/dist/cjs/instanceRegistry.native.js +56 -6
  130. package/dist/cjs/instanceRegistry.native.js.map +1 -1
  131. package/dist/cjs/multi.cjs +34 -13
  132. package/dist/cjs/multi.native.js +39 -17
  133. package/dist/cjs/multi.native.js.map +1 -1
  134. package/dist/cjs/multiInstance.test.cjs +6 -2
  135. package/dist/cjs/multiInstance.test.native.js +13 -9
  136. package/dist/cjs/multiInstance.test.native.js.map +1 -1
  137. package/dist/cjs/multiInstanceNested.test.native.js +10 -10
  138. package/dist/cjs/multiInstanceNested.test.native.js.map +1 -1
  139. package/dist/cjs/multiPartition.test.cjs +85 -36
  140. package/dist/cjs/multiPartition.test.native.js +102 -39
  141. package/dist/cjs/multiPartition.test.native.js.map +1 -1
  142. package/dist/cjs/mutations.cjs +2 -2
  143. package/dist/cjs/mutations.native.js +4 -4
  144. package/dist/cjs/mutations.native.js.map +1 -1
  145. package/dist/cjs/mutations.test.native.js +3 -3
  146. package/dist/cjs/mutations.test.native.js.map +1 -1
  147. package/dist/cjs/provideZero.hydration.test.cjs +3 -3
  148. package/dist/cjs/provideZero.hydration.test.native.js +4 -4
  149. package/dist/cjs/provideZero.hydration.test.native.js.map +1 -1
  150. package/dist/cjs/run.cjs +1 -1
  151. package/dist/cjs/run.native.js +3 -3
  152. package/dist/cjs/run.native.js.map +1 -1
  153. package/dist/cjs/server.cjs +20 -16
  154. package/dist/cjs/server.native.js +50 -57
  155. package/dist/cjs/server.native.js.map +1 -1
  156. package/dist/cjs/server.test.cjs +129 -6
  157. package/dist/cjs/server.test.native.js +141 -10
  158. package/dist/cjs/server.test.native.js.map +1 -1
  159. package/dist/cjs/serverWhere.test.native.js +3 -3
  160. package/dist/cjs/serverWhere.test.native.js.map +1 -1
  161. package/dist/cjs/state.cjs +2 -2
  162. package/dist/cjs/state.native.js +10 -10
  163. package/dist/cjs/state.native.js.map +1 -1
  164. package/dist/cjs/usePermission.test.native.js +3 -3
  165. package/dist/cjs/usePermission.test.native.js.map +1 -1
  166. package/dist/cjs/useQuery.empty.test.cjs +3 -3
  167. package/dist/cjs/useQuery.empty.test.native.js +6 -6
  168. package/dist/cjs/useQuery.empty.test.native.js.map +1 -1
  169. package/dist/cjs/useQuery.ssr.test.native.js +2 -2
  170. package/dist/cjs/useQuery.ssr.test.native.js.map +1 -1
  171. package/dist/cjs/vite-plugin.cjs +7 -8
  172. package/dist/cjs/vite-plugin.native.js +11 -11
  173. package/dist/cjs/vite-plugin.native.js.map +1 -1
  174. package/dist/cjs/where.cjs +3 -3
  175. package/dist/cjs/where.native.js +4 -4
  176. package/dist/cjs/where.native.js.map +1 -1
  177. package/dist/esm/cli.mjs +6 -3
  178. package/dist/esm/cli.mjs.map +1 -1
  179. package/dist/esm/cli.native.js +6 -3
  180. package/dist/esm/cli.native.js.map +1 -1
  181. package/dist/esm/combineZeroClients.mjs +1 -1
  182. package/dist/esm/combineZeroClients.mjs.map +1 -1
  183. package/dist/esm/combineZeroClients.native.js +5 -5
  184. package/dist/esm/combineZeroClients.native.js.map +1 -1
  185. package/dist/esm/config.mjs +5 -0
  186. package/dist/esm/config.mjs.map +1 -0
  187. package/dist/esm/config.native.js +5 -0
  188. package/dist/esm/config.native.js.map +1 -0
  189. package/dist/esm/createPermissions.mjs +1 -1
  190. package/dist/esm/createPermissions.mjs.map +1 -1
  191. package/dist/esm/createPermissions.native.js +16 -26
  192. package/dist/esm/createPermissions.native.js.map +1 -1
  193. package/dist/esm/createUseQuery.mjs +2 -2
  194. package/dist/esm/createUseQuery.mjs.map +1 -1
  195. package/dist/esm/createUseQuery.native.js +3 -3
  196. package/dist/esm/createUseQuery.native.js.map +1 -1
  197. package/dist/esm/createUseQueryDirect.mjs +2 -1
  198. package/dist/esm/createUseQueryDirect.mjs.map +1 -1
  199. package/dist/esm/createUseQueryDirect.native.js +12 -16
  200. package/dist/esm/createUseQueryDirect.native.js.map +1 -1
  201. package/dist/esm/createZeroClient.connection.test.mjs +11 -0
  202. package/dist/esm/createZeroClient.connection.test.mjs.map +1 -1
  203. package/dist/esm/createZeroClient.connection.test.native.js +14 -7
  204. package/dist/esm/createZeroClient.connection.test.native.js.map +1 -1
  205. package/dist/esm/createZeroClient.mjs +25 -5
  206. package/dist/esm/createZeroClient.mjs.map +1 -1
  207. package/dist/esm/createZeroClient.native.js +54 -28
  208. package/dist/esm/createZeroClient.native.js.map +1 -1
  209. package/dist/esm/createZeroClient.recovery.test.mjs +90 -3
  210. package/dist/esm/createZeroClient.recovery.test.mjs.map +1 -1
  211. package/dist/esm/createZeroClient.recovery.test.native.js +109 -19
  212. package/dist/esm/createZeroClient.recovery.test.native.js.map +1 -1
  213. package/dist/esm/generate-helpers.mjs +70 -18
  214. package/dist/esm/generate-helpers.mjs.map +1 -1
  215. package/dist/esm/generate-helpers.native.js +110 -24
  216. package/dist/esm/generate-helpers.native.js.map +1 -1
  217. package/dist/esm/generate-layout.mjs +560 -0
  218. package/dist/esm/generate-layout.mjs.map +1 -0
  219. package/dist/esm/generate-layout.native.js +1246 -0
  220. package/dist/esm/generate-layout.native.js.map +1 -0
  221. package/dist/esm/generate-lite.mjs +296 -28
  222. package/dist/esm/generate-lite.mjs.map +1 -1
  223. package/dist/esm/generate-lite.native.js +855 -103
  224. package/dist/esm/generate-lite.native.js.map +1 -1
  225. package/dist/esm/generate-lite.test.mjs +434 -42
  226. package/dist/esm/generate-lite.test.mjs.map +1 -1
  227. package/dist/esm/generate-lite.test.native.js +447 -42
  228. package/dist/esm/generate-lite.test.native.js.map +1 -1
  229. package/dist/esm/generate.mjs +172 -96
  230. package/dist/esm/generate.mjs.map +1 -1
  231. package/dist/esm/generate.native.js +324 -150
  232. package/dist/esm/generate.native.js.map +1 -1
  233. package/dist/esm/generate.test.mjs +366 -49
  234. package/dist/esm/generate.test.mjs.map +1 -1
  235. package/dist/esm/generate.test.native.js +378 -49
  236. package/dist/esm/generate.test.native.js.map +1 -1
  237. package/dist/esm/helpers/NullToOptional.mjs +2 -0
  238. package/dist/esm/helpers/NullToOptional.mjs.map +1 -0
  239. package/dist/esm/helpers/NullToOptional.native.js +2 -0
  240. package/dist/esm/helpers/NullToOptional.native.js.map +1 -0
  241. package/dist/esm/helpers/asyncContext.mjs +102 -0
  242. package/dist/esm/helpers/asyncContext.mjs.map +1 -0
  243. package/dist/esm/helpers/asyncContext.native.js +58 -0
  244. package/dist/esm/helpers/asyncContext.native.js.map +1 -0
  245. package/dist/esm/helpers/batchQuery.mjs +1 -1
  246. package/dist/esm/helpers/batchQuery.native.js +1 -1
  247. package/dist/esm/helpers/createMutators.mjs +5 -2
  248. package/dist/esm/helpers/createMutators.mjs.map +1 -1
  249. package/dist/esm/helpers/createMutators.native.js +10 -7
  250. package/dist/esm/helpers/createMutators.native.js.map +1 -1
  251. package/dist/esm/helpers/createMutators.test.native.js +2 -2
  252. package/dist/esm/helpers/createMutators.test.native.js.map +1 -1
  253. package/dist/esm/helpers/ellipsis.mjs +10 -0
  254. package/dist/esm/helpers/ellipsis.mjs.map +1 -0
  255. package/dist/esm/helpers/ellipsis.native.js +10 -0
  256. package/dist/esm/helpers/ellipsis.native.js.map +1 -0
  257. package/dist/esm/helpers/emitter.mjs +72 -0
  258. package/dist/esm/helpers/emitter.mjs.map +1 -0
  259. package/dist/esm/helpers/emitter.native.js +95 -0
  260. package/dist/esm/helpers/emitter.native.js.map +1 -0
  261. package/dist/esm/helpers/ensure.mjs +8 -0
  262. package/dist/esm/helpers/ensure.mjs.map +1 -0
  263. package/dist/esm/helpers/ensure.native.js +9 -0
  264. package/dist/esm/helpers/ensure.native.js.map +1 -0
  265. package/dist/esm/helpers/ensureLoggedIn.mjs +1 -1
  266. package/dist/esm/helpers/ensureLoggedIn.mjs.map +1 -1
  267. package/dist/esm/helpers/ensureLoggedIn.native.js +2 -2
  268. package/dist/esm/helpers/ensureLoggedIn.native.js.map +1 -1
  269. package/dist/esm/helpers/errors.mjs +14 -0
  270. package/dist/esm/helpers/errors.mjs.map +1 -0
  271. package/dist/esm/helpers/errors.native.js +123 -0
  272. package/dist/esm/helpers/errors.native.js.map +1 -0
  273. package/dist/esm/helpers/getCurrentComponentStack.mjs +35 -0
  274. package/dist/esm/helpers/getCurrentComponentStack.mjs.map +1 -0
  275. package/dist/esm/helpers/getCurrentComponentStack.native.js +54 -0
  276. package/dist/esm/helpers/getCurrentComponentStack.native.js.map +1 -0
  277. package/dist/esm/helpers/globalValue.mjs +14 -0
  278. package/dist/esm/helpers/globalValue.mjs.map +1 -0
  279. package/dist/esm/helpers/globalValue.native.js +14 -0
  280. package/dist/esm/helpers/globalValue.native.js.map +1 -0
  281. package/dist/esm/helpers/mapObject.mjs +11 -0
  282. package/dist/esm/helpers/mapObject.mjs.map +1 -0
  283. package/dist/esm/helpers/mapObject.native.js +11 -0
  284. package/dist/esm/helpers/mapObject.native.js.map +1 -0
  285. package/dist/esm/helpers/mutationLifecycle.mjs +221 -0
  286. package/dist/esm/helpers/mutationLifecycle.mjs.map +1 -0
  287. package/dist/esm/helpers/mutationLifecycle.native.js +359 -0
  288. package/dist/esm/helpers/mutationLifecycle.native.js.map +1 -0
  289. package/dist/esm/helpers/mutationLifecycle.test.mjs +175 -0
  290. package/dist/esm/helpers/mutationLifecycle.test.mjs.map +1 -0
  291. package/dist/esm/helpers/mutationLifecycle.test.native.js +180 -0
  292. package/dist/esm/helpers/mutationLifecycle.test.native.js.map +1 -0
  293. package/dist/esm/helpers/mutatorContext.mjs +1 -1
  294. package/dist/esm/helpers/mutatorContext.native.js +4 -4
  295. package/dist/esm/helpers/mutatorContext.native.js.map +1 -1
  296. package/dist/esm/helpers/platform.mjs +5 -0
  297. package/dist/esm/helpers/platform.mjs.map +1 -0
  298. package/dist/esm/helpers/platform.native.js +4 -0
  299. package/dist/esm/helpers/platform.native.js.map +1 -0
  300. package/dist/esm/helpers/prettyFormatZeroQuery.mjs +1 -1
  301. package/dist/esm/helpers/prettyFormatZeroQuery.native.js +6 -6
  302. package/dist/esm/helpers/prettyFormatZeroQuery.native.js.map +1 -1
  303. package/dist/esm/helpers/queryContext.mjs +1 -1
  304. package/dist/esm/helpers/queryContext.native.js +3 -3
  305. package/dist/esm/helpers/queryContext.native.js.map +1 -1
  306. package/dist/esm/helpers/recoverZeroClient.mjs +14 -15
  307. package/dist/esm/helpers/recoverZeroClient.mjs.map +1 -1
  308. package/dist/esm/helpers/recoverZeroClient.native.js +26 -23
  309. package/dist/esm/helpers/recoverZeroClient.native.js.map +1 -1
  310. package/dist/esm/helpers/recoverZeroClient.test.mjs +8 -6
  311. package/dist/esm/helpers/recoverZeroClient.test.mjs.map +1 -1
  312. package/dist/esm/helpers/recoverZeroClient.test.native.js +15 -19
  313. package/dist/esm/helpers/recoverZeroClient.test.native.js.map +1 -1
  314. package/dist/esm/helpers/sleep.mjs +9 -0
  315. package/dist/esm/helpers/sleep.mjs.map +1 -0
  316. package/dist/esm/helpers/sleep.native.js +11 -0
  317. package/dist/esm/helpers/sleep.native.js.map +1 -0
  318. package/dist/esm/helpers/time.mjs +22 -0
  319. package/dist/esm/helpers/time.mjs.map +1 -0
  320. package/dist/esm/helpers/time.native.js +52 -0
  321. package/dist/esm/helpers/time.native.js.map +1 -0
  322. package/dist/esm/helpers/tuple.mjs +2 -0
  323. package/dist/esm/helpers/tuple.mjs.map +1 -0
  324. package/dist/esm/helpers/tuple.native.js +2 -0
  325. package/dist/esm/helpers/tuple.native.js.map +1 -0
  326. package/dist/esm/helpers/useMutation.native.js +5 -5
  327. package/dist/esm/helpers/useMutation.native.js.map +1 -1
  328. package/dist/esm/helpers/useMutation.test.native.js +1 -1
  329. package/dist/esm/helpers/useMutation.test.native.js.map +1 -1
  330. package/dist/esm/helpers/useZeroDebug.mjs +1 -1
  331. package/dist/esm/helpers/useZeroDebug.mjs.map +1 -1
  332. package/dist/esm/helpers/useZeroDebug.native.js +6 -7
  333. package/dist/esm/helpers/useZeroDebug.native.js.map +1 -1
  334. package/dist/esm/index.js +3 -1
  335. package/dist/esm/index.js.map +1 -1
  336. package/dist/esm/index.mjs +3 -1
  337. package/dist/esm/index.mjs.map +1 -1
  338. package/dist/esm/index.native.js +3 -1
  339. package/dist/esm/index.native.js.map +1 -1
  340. package/dist/esm/instanceRegistry.mjs +13 -2
  341. package/dist/esm/instanceRegistry.mjs.map +1 -1
  342. package/dist/esm/instanceRegistry.native.js +53 -4
  343. package/dist/esm/instanceRegistry.native.js.map +1 -1
  344. package/dist/esm/multi.mjs +33 -12
  345. package/dist/esm/multi.mjs.map +1 -1
  346. package/dist/esm/multi.native.js +38 -16
  347. package/dist/esm/multi.native.js.map +1 -1
  348. package/dist/esm/multiInstance.test.mjs +5 -1
  349. package/dist/esm/multiInstance.test.mjs.map +1 -1
  350. package/dist/esm/multiInstance.test.native.js +12 -8
  351. package/dist/esm/multiInstance.test.native.js.map +1 -1
  352. package/dist/esm/multiInstanceNested.test.native.js +10 -10
  353. package/dist/esm/multiInstanceNested.test.native.js.map +1 -1
  354. package/dist/esm/multiPartition.test.mjs +86 -37
  355. package/dist/esm/multiPartition.test.mjs.map +1 -1
  356. package/dist/esm/multiPartition.test.native.js +103 -40
  357. package/dist/esm/multiPartition.test.native.js.map +1 -1
  358. package/dist/esm/mutations.mjs +1 -1
  359. package/dist/esm/mutations.mjs.map +1 -1
  360. package/dist/esm/mutations.native.js +3 -3
  361. package/dist/esm/mutations.native.js.map +1 -1
  362. package/dist/esm/mutations.test.native.js +3 -3
  363. package/dist/esm/mutations.test.native.js.map +1 -1
  364. package/dist/esm/provideZero.hydration.test.mjs +1 -1
  365. package/dist/esm/provideZero.hydration.test.mjs.map +1 -1
  366. package/dist/esm/provideZero.hydration.test.native.js +2 -2
  367. package/dist/esm/provideZero.hydration.test.native.js.map +1 -1
  368. package/dist/esm/run.mjs +1 -1
  369. package/dist/esm/run.mjs.map +1 -1
  370. package/dist/esm/run.native.js +3 -3
  371. package/dist/esm/run.native.js.map +1 -1
  372. package/dist/esm/server.mjs +20 -15
  373. package/dist/esm/server.mjs.map +1 -1
  374. package/dist/esm/server.native.js +50 -56
  375. package/dist/esm/server.native.js.map +1 -1
  376. package/dist/esm/server.test.mjs +130 -7
  377. package/dist/esm/server.test.mjs.map +1 -1
  378. package/dist/esm/server.test.native.js +142 -11
  379. package/dist/esm/server.test.native.js.map +1 -1
  380. package/dist/esm/serverWhere.test.mjs.map +1 -1
  381. package/dist/esm/serverWhere.test.native.js +3 -3
  382. package/dist/esm/serverWhere.test.native.js.map +1 -1
  383. package/dist/esm/state.mjs +1 -1
  384. package/dist/esm/state.mjs.map +1 -1
  385. package/dist/esm/state.native.js +9 -9
  386. package/dist/esm/state.native.js.map +1 -1
  387. package/dist/esm/usePermission.test.native.js +3 -3
  388. package/dist/esm/usePermission.test.native.js.map +1 -1
  389. package/dist/esm/useQuery.empty.test.mjs +1 -1
  390. package/dist/esm/useQuery.empty.test.mjs.map +1 -1
  391. package/dist/esm/useQuery.empty.test.native.js +4 -4
  392. package/dist/esm/useQuery.empty.test.native.js.map +1 -1
  393. package/dist/esm/useQuery.ssr.test.native.js +2 -2
  394. package/dist/esm/useQuery.ssr.test.native.js.map +1 -1
  395. package/dist/esm/vite-plugin.mjs +7 -8
  396. package/dist/esm/vite-plugin.mjs.map +1 -1
  397. package/dist/esm/vite-plugin.native.js +11 -11
  398. package/dist/esm/vite-plugin.native.js.map +1 -1
  399. package/dist/esm/where.mjs +1 -1
  400. package/dist/esm/where.mjs.map +1 -1
  401. package/dist/esm/where.native.js +2 -2
  402. package/dist/esm/where.native.js.map +1 -1
  403. package/package.json +18 -6
  404. package/src/cli.ts +11 -3
  405. package/src/combineZeroClients.tsx +18 -10
  406. package/src/config.ts +72 -0
  407. package/src/createPermissions.ts +3 -4
  408. package/src/createUseQuery.tsx +8 -8
  409. package/src/createUseQueryDirect.tsx +11 -10
  410. package/src/createZeroClient.authData.test.tsx +1 -1
  411. package/src/createZeroClient.connection.test.tsx +13 -2
  412. package/src/createZeroClient.recovery.test.tsx +100 -4
  413. package/src/createZeroClient.tsx +87 -30
  414. package/src/generate-helpers.ts +108 -31
  415. package/src/generate-layout.ts +841 -0
  416. package/src/generate-lite.test.ts +421 -42
  417. package/src/generate-lite.ts +479 -43
  418. package/src/generate.test.ts +552 -90
  419. package/src/generate.ts +360 -163
  420. package/src/helpers/NullToOptional.ts +5 -0
  421. package/src/helpers/asyncContext.native.ts +90 -0
  422. package/src/helpers/asyncContext.ts +159 -0
  423. package/src/helpers/batchQuery.ts +2 -2
  424. package/src/helpers/createMutators.ts +11 -8
  425. package/src/helpers/ellipsis.ts +9 -0
  426. package/src/helpers/emitter.tsx +106 -0
  427. package/src/helpers/ensure.ts +10 -0
  428. package/src/helpers/ensureLoggedIn.ts +1 -2
  429. package/src/helpers/errors.ts +13 -0
  430. package/src/helpers/getCurrentComponentStack.ts +56 -0
  431. package/src/helpers/globalValue.ts +40 -0
  432. package/src/helpers/mapObject.ts +14 -0
  433. package/src/helpers/mutationLifecycle.test.ts +180 -0
  434. package/src/helpers/mutationLifecycle.ts +313 -0
  435. package/src/helpers/mutatorContext.ts +3 -3
  436. package/src/helpers/platform.native.ts +2 -0
  437. package/src/helpers/platform.ts +16 -0
  438. package/src/helpers/prettyFormatZeroQuery.ts +2 -2
  439. package/src/helpers/queryContext.ts +2 -2
  440. package/src/helpers/recoverZeroClient.test.ts +23 -21
  441. package/src/helpers/recoverZeroClient.ts +56 -49
  442. package/src/helpers/sleep.ts +8 -0
  443. package/src/helpers/time.ts +51 -0
  444. package/src/helpers/tuple.ts +1 -0
  445. package/src/helpers/useMutation.tsx +3 -3
  446. package/src/helpers/useZeroDebug.ts +3 -3
  447. package/src/index.ts +13 -1
  448. package/src/instanceRegistry.ts +19 -6
  449. package/src/multi.ts +75 -31
  450. package/src/multiInstance.test.tsx +31 -13
  451. package/src/multiInstanceNested.test.tsx +2 -2
  452. package/src/multiPartition.test.ts +62 -27
  453. package/src/mutations.ts +10 -10
  454. package/src/provideZero.hydration.test.tsx +1 -1
  455. package/src/resolveQuery.ts +2 -2
  456. package/src/run.ts +7 -7
  457. package/src/server.test.ts +117 -18
  458. package/src/server.ts +70 -43
  459. package/src/serverWhere.ts +2 -2
  460. package/src/state.ts +2 -2
  461. package/src/types.ts +47 -6
  462. package/src/useQuery.empty.test.tsx +3 -3
  463. package/src/useQuery.ssr.test.ts +1 -1
  464. package/src/vite-plugin.ts +12 -9
  465. package/src/where.ts +6 -7
  466. package/src/zeroRunner.ts +2 -2
  467. package/types/combineZeroClients.d.ts +11 -5
  468. package/types/combineZeroClients.d.ts.map +1 -1
  469. package/types/config.d.ts +62 -0
  470. package/types/config.d.ts.map +1 -0
  471. package/types/createPermissions.d.ts.map +1 -1
  472. package/types/createUseQuery.d.ts.map +1 -1
  473. package/types/createUseQueryDirect.d.ts +1 -1
  474. package/types/createUseQueryDirect.d.ts.map +1 -1
  475. package/types/createZeroClient.d.ts +22 -12
  476. package/types/createZeroClient.d.ts.map +1 -1
  477. package/types/createZeroClient.recovery.test.d.ts.map +1 -1
  478. package/types/generate-helpers.d.ts +17 -2
  479. package/types/generate-helpers.d.ts.map +1 -1
  480. package/types/generate-layout.d.ts +26 -0
  481. package/types/generate-layout.d.ts.map +1 -0
  482. package/types/generate-lite.d.ts +29 -1
  483. package/types/generate-lite.d.ts.map +1 -1
  484. package/types/generate.d.ts +20 -0
  485. package/types/generate.d.ts.map +1 -1
  486. package/types/helpers/NullToOptional.d.ts +6 -0
  487. package/types/helpers/NullToOptional.d.ts.map +1 -0
  488. package/types/helpers/asyncContext.d.ts +15 -0
  489. package/types/helpers/asyncContext.d.ts.map +1 -0
  490. package/types/helpers/asyncContext.native.d.ts +8 -0
  491. package/types/helpers/asyncContext.native.d.ts.map +1 -0
  492. package/types/helpers/createMutators.d.ts +2 -1
  493. package/types/helpers/createMutators.d.ts.map +1 -1
  494. package/types/helpers/ellipsis.d.ts +2 -0
  495. package/types/helpers/ellipsis.d.ts.map +1 -0
  496. package/types/helpers/emitter.d.ts +21 -0
  497. package/types/helpers/emitter.d.ts.map +1 -0
  498. package/types/helpers/ensure.d.ts +2 -0
  499. package/types/helpers/ensure.d.ts.map +1 -0
  500. package/types/helpers/ensureLoggedIn.d.ts.map +1 -1
  501. package/types/helpers/errors.d.ts +7 -0
  502. package/types/helpers/errors.d.ts.map +1 -0
  503. package/types/helpers/getCurrentComponentStack.d.ts +2 -0
  504. package/types/helpers/getCurrentComponentStack.d.ts.map +1 -0
  505. package/types/helpers/globalValue.d.ts +23 -0
  506. package/types/helpers/globalValue.d.ts.map +1 -0
  507. package/types/helpers/mapObject.d.ts +4 -0
  508. package/types/helpers/mapObject.d.ts.map +1 -0
  509. package/types/helpers/mutationLifecycle.d.ts +44 -0
  510. package/types/helpers/mutationLifecycle.d.ts.map +1 -0
  511. package/types/helpers/mutationLifecycle.test.d.ts +2 -0
  512. package/types/helpers/mutationLifecycle.test.d.ts.map +1 -0
  513. package/types/helpers/platform.d.ts +3 -0
  514. package/types/helpers/platform.d.ts.map +1 -0
  515. package/types/helpers/platform.native.d.ts +3 -0
  516. package/types/helpers/platform.native.d.ts.map +1 -0
  517. package/types/helpers/recoverZeroClient.d.ts +13 -9
  518. package/types/helpers/recoverZeroClient.d.ts.map +1 -1
  519. package/types/helpers/sleep.d.ts +2 -0
  520. package/types/helpers/sleep.d.ts.map +1 -0
  521. package/types/helpers/time.d.ts +28 -0
  522. package/types/helpers/time.d.ts.map +1 -0
  523. package/types/helpers/tuple.d.ts +2 -0
  524. package/types/helpers/tuple.d.ts.map +1 -0
  525. package/types/index.d.ts +3 -1
  526. package/types/index.d.ts.map +1 -1
  527. package/types/instanceRegistry.d.ts +1 -0
  528. package/types/instanceRegistry.d.ts.map +1 -1
  529. package/types/multi.d.ts +23 -1
  530. package/types/multi.d.ts.map +1 -1
  531. package/types/mutations.d.ts +1 -1
  532. package/types/mutations.d.ts.map +1 -1
  533. package/types/run.d.ts.map +1 -1
  534. package/types/server.d.ts +12 -8
  535. package/types/server.d.ts.map +1 -1
  536. package/types/state.d.ts +1 -1
  537. package/types/state.d.ts.map +1 -1
  538. package/types/types.d.ts +23 -1
  539. package/types/types.d.ts.map +1 -1
  540. package/types/vite-plugin.d.ts.map +1 -1
  541. package/types/where.d.ts.map +1 -1
  542. package/lint/ssr-guards.js +0 -165
  543. package/test-fixtures/server-return-types.ts +0 -58
  544. package/test-fixtures/tsconfig.json +0 -13
  545. package/tsconfig.json +0 -26
  546. package/vitest.config.ts +0 -8
@@ -1,20 +1,24 @@
1
- import { existsSync, mkdirSync, readFileSync, rmSync, symlinkSync, writeFileSync } from "fs";
1
+ import { existsSync, mkdirSync, readFileSync, rmSync, symlinkSync, writeFileSync as writeFile } from "fs";
2
2
  import { tmpdir } from "os";
3
- import { join } from "path";
3
+ import { dirname, join } from "path";
4
4
  import { runInNewContext } from "vm";
5
5
  import * as zero from "@rocicorp/zero";
6
- import { afterEach, beforeEach, describe, expect, test } from "vitest";
7
- import { generate, generateDrizzleSchemaFile } from "./generate.native.js";
6
+ import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
7
+ import { deriveDataMembership, generate, generateDrizzleSchemaFile, generateDrizzleSchemaInputFile } from "./generate.native.js";
8
8
  var testDir = join(tmpdir(), "on-zero-test-" + Date.now());
9
- beforeEach(function () {
10
- mkdirSync(join(testDir, "models"), {
9
+ function writeFileSync(path, content) {
10
+ mkdirSync(dirname(path), {
11
11
  recursive: true
12
12
  });
13
- mkdirSync(join(testDir, "queries"), {
13
+ writeFile(path, content);
14
+ }
15
+ beforeEach(function () {
16
+ mkdirSync(testDir, {
14
17
  recursive: true
15
18
  });
16
19
  });
17
20
  afterEach(function () {
21
+ vi.restoreAllMocks();
18
22
  rmSync(testDir, {
19
23
  recursive: true,
20
24
  force: true
@@ -22,7 +26,7 @@ afterEach(function () {
22
26
  });
23
27
  describe("generate", function () {
24
28
  test("generates models.ts, types.ts, tables.ts from model files", async function () {
25
- writeFileSync(join(testDir, "models/post.ts"), `
29
+ writeFileSync(join(testDir, "post/mutations.ts"), `
26
30
  import { table, string, boolean } from 'on-zero'
27
31
 
28
32
  export const schema = table('post', {
@@ -31,7 +35,7 @@ export const schema = table('post', {
31
35
  published: boolean(),
32
36
  })
33
37
  `);
34
- writeFileSync(join(testDir, "models/comment.ts"), `
38
+ writeFileSync(join(testDir, "comment/mutations.ts"), `
35
39
  import { table, string } from 'on-zero'
36
40
 
37
41
  export const schema = table('comment', {
@@ -40,8 +44,8 @@ export const schema = table('comment', {
40
44
  body: string(),
41
45
  })
42
46
  `);
43
- writeFileSync(join(testDir, "models/post.test.ts"), `throw new Error('test files must not be generated as models')`);
44
- writeFileSync(join(testDir, "queries/comment.spec.ts"), `throw new Error('spec files must not be generated as queries')`);
47
+ writeFileSync(join(testDir, "post/post.test.ts"), `throw new Error('test files must not be generated as models')`);
48
+ writeFileSync(join(testDir, "comment/comment.spec.ts"), `throw new Error('spec files must not be generated as queries')`);
45
49
  var result = await generate({
46
50
  dir: testDir,
47
51
  silent: true
@@ -53,20 +57,20 @@ export const schema = table('comment', {
53
57
  expect(existsSync(join(testDir, "generated/types.ts"))).toBe(true);
54
58
  expect(existsSync(join(testDir, "generated/tables.ts"))).toBe(true);
55
59
  var modelsContent = readFileSync(join(testDir, "generated/models.ts"), "utf-8");
56
- expect(modelsContent).toContain("import * as comment from '../models/comment'");
57
- expect(modelsContent).toContain("import * as post from '../models/post'");
60
+ expect(modelsContent).toContain("import * as comment from '../comment/mutations'");
61
+ expect(modelsContent).toContain("import * as post from '../post/mutations'");
58
62
  expect(modelsContent).not.toContain("post.test");
59
63
  expect(modelsContent).toContain("export const models = {");
60
64
  var typesContent = readFileSync(join(testDir, "generated/types.ts"), "utf-8");
61
65
  expect(typesContent).toContain("export type Post = TableInsertRow<typeof schema.post>");
62
66
  expect(typesContent).toContain("export type Comment = TableInsertRow<typeof schema.comment>");
63
67
  var tablesContent = readFileSync(join(testDir, "generated/tables.ts"), "utf-8");
64
- expect(tablesContent).toContain("export { schema as post } from '../models/post'");
65
- expect(tablesContent).toContain("export { schema as comment } from '../models/comment'");
68
+ expect(tablesContent).toContain("export { schema as post } from '../post/mutations'");
69
+ expect(tablesContent).toContain("export { schema as comment } from '../comment/mutations'");
66
70
  });
67
71
  test("generates query validators from query files", async function () {
68
- writeFileSync(join(testDir, "models/post.ts"), `export const schema = table('post', { id: string() })`);
69
- writeFileSync(join(testDir, "queries/post.ts"), `
72
+ writeFileSync(join(testDir, "post/mutations.ts"), `export const schema = table('post', { id: string() })`);
73
+ writeFileSync(join(testDir, "post/queries.ts"), `
70
74
  import { zero } from '../zero'
71
75
 
72
76
  export const allPosts = () => zero.query.post
@@ -84,7 +88,8 @@ export const postsByAuthor = ({ authorId, limit }: { authorId: string; limit?: n
84
88
  expect(existsSync(join(testDir, "generated/groupedQueries.ts"))).toBe(true);
85
89
  expect(existsSync(join(testDir, "generated/syncedQueries.ts"))).toBe(true);
86
90
  var groupedContent = readFileSync(join(testDir, "generated/groupedQueries.ts"), "utf-8");
87
- expect(groupedContent).toContain("export * as post from '../queries/post'");
91
+ expect(groupedContent).toContain("import * as postSource from '../post/queries'");
92
+ expect(groupedContent).toContain("postById: postSource.postById");
88
93
  var syncedContent = readFileSync(join(testDir, "generated/syncedQueries.ts"), "utf-8");
89
94
  expect(syncedContent).toContain("allPosts: defineQuery");
90
95
  expect(syncedContent).toContain("postById: defineQuery");
@@ -92,8 +97,8 @@ export const postsByAuthor = ({ authorId, limit }: { authorId: string; limit?: n
92
97
  expect(syncedContent).toContain("v.object");
93
98
  });
94
99
  test("skips permission exports in queries", async function () {
95
- writeFileSync(join(testDir, "models/post.ts"), `export const schema = table('post', { id: string() })`);
96
- writeFileSync(join(testDir, "queries/post.ts"), `
100
+ writeFileSync(join(testDir, "post/mutations.ts"), `export const schema = table('post', { id: string() })`);
101
+ writeFileSync(join(testDir, "post/queries.ts"), `
97
102
  export const permission = () => ({ canRead: true })
98
103
  export const allPosts = () => zero.query.post
99
104
  `);
@@ -107,20 +112,20 @@ export const allPosts = () => zero.query.post
107
112
  expect(syncedContent).not.toContain("permission:");
108
113
  });
109
114
  test("aliases user import without changing the model key", async function () {
110
- writeFileSync(join(testDir, "models/user.ts"), `export const schema = table('user', { id: string(), name: string() })`);
115
+ writeFileSync(join(testDir, "user/mutations.ts"), `export const schema = table('user', { id: string(), name: string() })`);
111
116
  await generate({
112
117
  dir: testDir,
113
118
  silent: true
114
119
  });
115
120
  var modelsContent = readFileSync(join(testDir, "generated/models.ts"), "utf-8");
116
- expect(modelsContent).toContain("import * as userPublic from '../models/user'");
121
+ expect(modelsContent).toContain("import * as userPublic from '../user/mutations'");
117
122
  expect(modelsContent).toContain("user: userPublic,");
118
123
  expect(modelsContent).not.toContain("\n userPublic,");
119
124
  var typesContent = readFileSync(join(testDir, "generated/types.ts"), "utf-8");
120
125
  expect(typesContent).toContain("typeof schema.userPublic");
121
126
  });
122
127
  test("runs after command when files change", async function () {
123
- writeFileSync(join(testDir, "models/post.ts"), `export const schema = table('post', { id: string() })`);
128
+ writeFileSync(join(testDir, "post/mutations.ts"), `export const schema = table('post', { id: string() })`);
124
129
  var markerFile = join(testDir, "after-ran");
125
130
  var result = await generate({
126
131
  dir: testDir,
@@ -131,7 +136,7 @@ export const allPosts = () => zero.query.post
131
136
  expect(existsSync(markerFile)).toBe(true);
132
137
  });
133
138
  test("does not regenerate when nothing changed", async function () {
134
- writeFileSync(join(testDir, "models/post.ts"), `export const schema = table('post', { id: string() })`);
139
+ writeFileSync(join(testDir, "post/mutations.ts"), `export const schema = table('post', { id: string() })`);
135
140
  var first = await generate({
136
141
  dir: testDir,
137
142
  silent: true
@@ -144,8 +149,8 @@ export const allPosts = () => zero.query.post
144
149
  expect(second.filesChanged).toBe(0);
145
150
  });
146
151
  test("force regenerates without source changes", async function () {
147
- writeFileSync(join(testDir, "models/post.ts"), `export const schema = table('post', { id: string() })`);
148
- writeFileSync(join(testDir, "queries/post.ts"), `export const allPosts = () => zero.query.post`);
152
+ writeFileSync(join(testDir, "post/mutations.ts"), `export const schema = table('post', { id: string() })`);
153
+ writeFileSync(join(testDir, "post/queries.ts"), `export const allPosts = () => zero.query.post`);
149
154
  await generate({
150
155
  dir: testDir,
151
156
  silent: true
@@ -160,9 +165,333 @@ export const allPosts = () => zero.query.post
160
165
  expect(existsSync(syncedQueriesPath)).toBe(true);
161
166
  });
162
167
  });
168
+ describe("instance layout", function () {
169
+ var dataDir = function dataDir2() {
170
+ return join(testDir, "src/data");
171
+ };
172
+ test("discovers file and folder namespaces and emits related sync closure", async function () {
173
+ writeFileSync(join(dataDir(), "control/reaction.ts"), `export const allReactions = () => zql.reaction`);
174
+ writeFileSync(join(dataDir(), "on-zero.config.ts"), `export default defineConfig({ instances: { control: {}, project: { scope: 'projectId' } } })`);
175
+ writeFileSync(join(dataDir(), "project/message/queries.ts"), `
176
+ const unused = () => zql.message.related('notARealRelation')
177
+ const withComments = () => zql.message.related('comments', (q) => q.related('author'))
178
+ export const messages = () => withComments()
179
+ `);
180
+ writeFileSync(join(dataDir(), "project/message/mutations.ts"), `export const schema = table('message').columns({ id: string(), projectId: string() })`);
181
+ writeFileSync(join(dataDir(), "project/message/helpers.ts"), `export const privateHelper = () => 'ignored'`);
182
+ writeFileSync(join(testDir, "src/database/relations.ts"), `
183
+ export const relations = defineRelations(schema, (r) => ({
184
+ message: { comments: r.many.comment({}) },
185
+ comment: { author: r.one.userPublic({}) },
186
+ }))
187
+ `);
188
+ writeFileSync(join(testDir, "src/database/schema.ts"), `
189
+ export const comment = sqliteTable('comment', { id: text(), projectId: text() })
190
+ export const userPublic = sqliteTable('user_public', { id: text(), projectId: text() })
191
+ `);
192
+ var membership = await deriveDataMembership({
193
+ dir: dataDir()
194
+ });
195
+ expect(membership.allTables).toEqual(["comment", "message", "reaction", "userPublic"]);
196
+ expect(membership.instances.project).toEqual({
197
+ tables: ["message"],
198
+ syncTables: ["comment", "message", "userPublic"],
199
+ supportTables: [],
200
+ scope: "projectId"
201
+ });
202
+ await generate({
203
+ dir: dataDir(),
204
+ silent: true
205
+ });
206
+ var grouped = readFileSync(join(dataDir(), "generated/groupedQueries.ts"), "utf8");
207
+ expect(grouped).toContain("from '../control/reaction'");
208
+ expect(grouped).toContain("from '../project/message/queries'");
209
+ expect(grouped).not.toContain("privateHelper");
210
+ var manifest = readFileSync(join(dataDir(), "generated/instances.ts"), "utf8");
211
+ expect(manifest).toContain("control: {");
212
+ expect(manifest).toContain("project: {");
213
+ expect(manifest).toContain('tables: ["message"]');
214
+ expect(manifest).toContain('syncTables: ["comment","message","userPublic"]');
215
+ expect(manifest).toContain(`defaultVisibility: (value: string) => ({ column: "projectId", value })`);
216
+ });
217
+ test("derives single-file namespaces from data exports", async function () {
218
+ writeFileSync(join(dataDir(), "server.ts"), `export const serverRows = () => zql.server`);
219
+ writeFileSync(join(dataDir(), "types.ts"), `export const formatRow = (value: string) => value`);
220
+ writeFileSync(join(dataDir(), "auth.ts"), `export function authId(auth: { id: string }) { return auth.id }`);
221
+ await expect(deriveDataMembership({
222
+ dir: dataDir()
223
+ })).resolves.toEqual({
224
+ instances: {
225
+ default: {
226
+ tables: ["server"],
227
+ syncTables: ["server"],
228
+ supportTables: [],
229
+ scope: null
230
+ }
231
+ },
232
+ allTables: ["server"]
233
+ });
234
+ });
235
+ test("warns once and ignores an unparseable non-data file", async function () {
236
+ writeFileSync(join(dataDir(), "post.ts"), `export const posts = () => zql.post`);
237
+ writeFileSync(join(dataDir(), "types.ts"), `export type Broken = {`);
238
+ var warn = vi.spyOn(console, "warn").mockImplementation(function () {});
239
+ await expect(deriveDataMembership({
240
+ dir: dataDir()
241
+ })).resolves.toMatchObject({
242
+ allTables: ["post"]
243
+ });
244
+ expect(warn).toHaveBeenCalledOnce();
245
+ expect(warn).toHaveBeenCalledWith("[on-zero] ignoring data/types.ts: no recognized data exports");
246
+ warn.mockRestore();
247
+ });
248
+ test("derives fileless support tables through mutation helpers", async function () {
249
+ writeFileSync(join(dataDir(), "post.ts"), `
250
+ import { writeAudit } from './helpers/writeAudit'
251
+ export const posts = () => zql.post
252
+ export const mutate = mutations('post', { save: async (ctx) => writeAudit(ctx.tx) })
253
+ `);
254
+ writeFileSync(join(dataDir(), "helpers/writeAudit.ts"), `
255
+ import { readSettings } from './readSettings'
256
+ export async function writeAudit(tx: Transaction) {
257
+ await tx.mutate.audit.insert({ id: 'audit' })
258
+ await tx.mutate.post.update({ id: 'post' })
259
+ await tx.mutate[tableName].insert({ id: 'dynamic' })
260
+ return readSettings(tx)
261
+ }
262
+ `);
263
+ writeFileSync(join(dataDir(), "helpers/readSettings.ts"), `export const readSettings = (tx: Transaction) => tx.query.settings`);
264
+ await expect(deriveDataMembership({
265
+ dir: dataDir()
266
+ })).resolves.toEqual({
267
+ instances: {
268
+ default: {
269
+ tables: ["post"],
270
+ syncTables: ["post"],
271
+ supportTables: ["audit", "settings"],
272
+ scope: null
273
+ }
274
+ },
275
+ allTables: ["audit", "post", "settings"]
276
+ });
277
+ });
278
+ test("includes a fileless support table in every instance that uses it", async function () {
279
+ writeFileSync(join(dataDir(), "control/account.ts"), `export const mutate = mutations('account', { save: async (ctx) => ctx.tx.mutate.audit.insert({}) })`);
280
+ writeFileSync(join(dataDir(), "on-zero.config.ts"), `export default defineConfig({ instances: { control: {}, project: { scope: 'projectId' } } })`);
281
+ writeFileSync(join(dataDir(), "project/message.ts"), `
282
+ export const schema = table('message').columns({ id: string(), projectId: string() })
283
+ export const mutate = mutations(schema, permission, {
284
+ save: async (ctx) => ctx.tx.mutate.audit.insert({}),
285
+ })
286
+ `);
287
+ await expect(deriveDataMembership({
288
+ dir: dataDir()
289
+ })).resolves.toMatchObject({
290
+ instances: {
291
+ control: {
292
+ supportTables: ["audit"]
293
+ },
294
+ project: {
295
+ supportTables: ["audit"]
296
+ }
297
+ },
298
+ allTables: ["account", "audit", "message"]
299
+ });
300
+ });
301
+ test("keeps a configured default instance at the data root", async function () {
302
+ writeFileSync(join(dataDir(), "on-zero.config.ts"), `export default defineConfig({ instances: { default: { dir: '.', supportTables: ['accountGithubOrgLink', 'accountRepo', 'usageLedger'] }, project: { scope: 'projectId' } } })`);
303
+ writeFileSync(join(dataDir(), "account.ts"), `export const accounts = () => zql.account`);
304
+ writeFileSync(join(dataDir(), "project/message.ts"), `export const schema = table('message').columns({ id: string(), projectId: string() })`);
305
+ await expect(deriveDataMembership({
306
+ dir: dataDir()
307
+ })).resolves.toEqual({
308
+ instances: {
309
+ default: {
310
+ tables: ["account"],
311
+ syncTables: ["account"],
312
+ supportTables: ["accountGithubOrgLink", "accountRepo", "usageLedger"],
313
+ scope: null
314
+ },
315
+ project: {
316
+ tables: ["message"],
317
+ syncTables: ["message"],
318
+ supportTables: [],
319
+ scope: "projectId"
320
+ }
321
+ },
322
+ allTables: ["account", "accountGithubOrgLink", "accountRepo", "message", "usageLedger"]
323
+ });
324
+ });
325
+ test("emits only relations whose source and target are derived members", async function () {
326
+ writeFileSync(join(dataDir(), "post.ts"), `export const posts = () => zql.post`);
327
+ writeFileSync(join(dataDir(), "comment.ts"), `export const comments = () => zql.comment`);
328
+ writeFileSync(join(testDir, "src/database/relations.ts"), `
329
+ export const relations = defineRelations(schema, (r) => ({
330
+ post: {
331
+ comments: r.many.comment({}),
332
+ privateNotes: r.many.privateNote({}),
333
+ },
334
+ comment: { post: r.one.post({}), author: r.one.privateUser({}) },
335
+ privateNote: { post: r.one.post({}) },
336
+ }))
337
+ `);
338
+ var generated = await generateDrizzleSchemaInputFile({
339
+ dir: dataDir(),
340
+ schemaImportPath: "../../database/schema"
341
+ });
342
+ var runnable = generated.replace(`import { defineRelations } from 'drizzle-orm'`, "").replace(`import * as schema from "../../database/schema"`, "").replace(/export \{[^\n]+\} from [^\n]+/, "").replace("export const relations =", "globalThis.relations =");
343
+ var context = {
344
+ schema: {
345
+ comment: {},
346
+ post: {}
347
+ },
348
+ defineRelations: function defineRelations(_schema, factory) {
349
+ return factory({
350
+ one: new Proxy({}, {
351
+ get: function get(_target, table) {
352
+ return function () {
353
+ return {
354
+ table
355
+ };
356
+ };
357
+ }
358
+ }),
359
+ many: new Proxy({}, {
360
+ get: function get(_target, table) {
361
+ return function () {
362
+ return {
363
+ table
364
+ };
365
+ };
366
+ }
367
+ })
368
+ });
369
+ }
370
+ };
371
+ runInNewContext(runnable, context);
372
+ expect(context.relations).toEqual({
373
+ comment: {
374
+ post: {
375
+ table: "post"
376
+ }
377
+ },
378
+ post: {
379
+ comments: {
380
+ table: "comment"
381
+ }
382
+ }
383
+ });
384
+ });
385
+ test("rejects a relation that crosses instance ownership", async function () {
386
+ writeFileSync(join(dataDir(), "control/userPublic.ts"), `export const users = () => zql.userPublic`);
387
+ writeFileSync(join(dataDir(), "on-zero.config.ts"), `export default defineConfig({ instances: { control: {}, project: { scope: 'projectId' } } })`);
388
+ writeFileSync(join(dataDir(), "project/message.ts"), `
389
+ export const schema = table('message').columns({ id: string(), projectId: string() })
390
+ export const messages = () => zql.message.related('author')
391
+ `);
392
+ writeFileSync(join(testDir, "src/database/relations.ts"), `export const relations = defineRelations(schema, (r) => ({ message: { author: r.one.userPublic({}) } }))`);
393
+ await expect(generate({
394
+ dir: dataDir(),
395
+ silent: true
396
+ })).rejects.toThrow(/message\.messages.*instance 'project'.*userPublic.*instance 'control'/);
397
+ });
398
+ test("rejects a scoped sync table without the scope column", async function () {
399
+ writeFileSync(join(dataDir(), "on-zero.config.ts"), `export default defineConfig({ instances: { project: { scope: 'projectId' } } })`);
400
+ writeFileSync(join(dataDir(), "project/message.ts"), `export const schema = table('message').columns({ id: string() })`);
401
+ await expect(generate({
402
+ dir: dataDir(),
403
+ silent: true
404
+ })).rejects.toThrow(/table 'message'.*instance 'project'.*scope column 'projectId'/);
405
+ });
406
+ test("rejects duplicate namespaces across instances", async function () {
407
+ writeFileSync(join(dataDir(), "control/message.ts"), `export const messages = () => zql.message`);
408
+ writeFileSync(join(dataDir(), "on-zero.config.ts"), `export default defineConfig({ instances: { control: {}, project: { scope: 'projectId' } } })`);
409
+ writeFileSync(join(dataDir(), "project/message.ts"), `export const schema = table('message').columns({ projectId: string() })`);
410
+ await expect(generate({
411
+ dir: dataDir(),
412
+ silent: true
413
+ })).rejects.toThrow(/namespace 'message'.*instances 'control' and 'project'/);
414
+ });
415
+ test("resolves configured instance directories relative to the config file", async function () {
416
+ writeFileSync(join(dataDir(), "on-zero.config.ts"), `export default defineConfig({ instances: { control: { dir: './planes/control-data', supportTables: ['audit'] }, project: { dir: '../project-data', scope: 'projectId' } } })`);
417
+ writeFileSync(join(dataDir(), "planes/control-data/account.ts"), `export const accounts = () => zql.account`);
418
+ writeFileSync(join(testDir, "src/project-data/message.ts"), `export const schema = table('message').columns({ id: string(), projectId: string() })`);
419
+ await expect(deriveDataMembership({
420
+ dir: dataDir(),
421
+ config: join(dataDir(), "on-zero.config.ts")
422
+ })).resolves.toEqual({
423
+ instances: {
424
+ control: {
425
+ tables: ["account"],
426
+ syncTables: ["account"],
427
+ supportTables: ["audit"],
428
+ scope: null
429
+ },
430
+ project: {
431
+ tables: ["message"],
432
+ syncTables: ["message"],
433
+ supportTables: [],
434
+ scope: "projectId"
435
+ }
436
+ },
437
+ allTables: ["account", "audit", "message"]
438
+ });
439
+ await expect(generate({
440
+ dir: dataDir(),
441
+ config: join(dataDir(), "on-zero.config.ts"),
442
+ silent: true
443
+ })).resolves.toMatchObject({
444
+ modelCount: 2,
445
+ schemaCount: 1
446
+ });
447
+ expect(readFileSync(join(dataDir(), "generated/models.ts"), "utf8")).toContain("from '../../project-data/message'");
448
+ });
449
+ test("rejects missing configured instance directories", async function () {
450
+ writeFileSync(join(dataDir(), "on-zero.config.ts"), `export default defineConfig({ instances: { project: { dir: './missing' } } })`);
451
+ await expect(deriveDataMembership({
452
+ dir: dataDir()
453
+ })).rejects.toThrow(/instance 'project' directory does not exist.*missing/);
454
+ });
455
+ test("rejects two instances that resolve to the same directory", async function () {
456
+ writeFileSync(join(dataDir(), "on-zero.config.ts"), `export default defineConfig({ instances: { control: { dir: './shared' }, project: { dir: './shared' } } })`);
457
+ writeFileSync(join(dataDir(), "shared/account.ts"), `export const accounts = () => zql.account`);
458
+ await expect(deriveDataMembership({
459
+ dir: dataDir()
460
+ })).rejects.toThrow(/instances 'control' and 'project' resolve to the same directory/);
461
+ });
462
+ test("rejects root namespaces when instances are configured", async function () {
463
+ writeFileSync(join(dataDir(), "on-zero.config.ts"), `export default defineConfig({ instances: { project: {} } })`);
464
+ writeFileSync(join(dataDir(), "project/message.ts"), `export const rows = () => zql.message`);
465
+ writeFileSync(join(dataDir(), "account.ts"), `export const rows = () => zql.account`);
466
+ await expect(deriveDataMembership({
467
+ dir: dataDir()
468
+ })).rejects.toThrow(/data namespace .*account\.ts.*outside every instance directory/);
469
+ });
470
+ test("rejects removed instance.ts configuration", async function () {
471
+ writeFileSync(join(dataDir(), "post.ts"), `export const posts = () => zql.post`);
472
+ writeFileSync(join(dataDir(), "project/instance.ts"), `export default defineInstance({ scope: 'projectId' })`);
473
+ await expect(deriveDataMembership({
474
+ dir: dataDir()
475
+ })).rejects.toThrow(/uses removed instance\.ts configuration/);
476
+ });
477
+ test("rejects the removed top-level layout", async function () {
478
+ writeFileSync(join(dataDir(), "queries/message.ts"), `export const messages = () => zql.message`);
479
+ await expect(generate({
480
+ dir: dataDir(),
481
+ silent: true
482
+ })).rejects.toThrow(/removed top-level queries\/ layout/);
483
+ });
484
+ test("rejects dynamically named relations", async function () {
485
+ writeFileSync(join(dataDir(), "message.ts"), `export const messages = (relation: string) => zql.message.related(relation)`);
486
+ await expect(generate({
487
+ dir: dataDir(),
488
+ silent: true
489
+ })).rejects.toThrow(/related\(\) without a string literal.*statically derivable/);
490
+ });
491
+ });
163
492
  describe("mutations", function () {
164
493
  test("generates validators for inline mutation param types", async function () {
165
- writeFileSync(join(testDir, "models/post.ts"), `
494
+ writeFileSync(join(testDir, "post/mutations.ts"), `
166
495
  import { table, string } from 'on-zero'
167
496
  import { mutations, serverWhere } from 'on-zero'
168
497
 
@@ -191,7 +520,7 @@ export const mutate = mutations(schema, perm, {
191
520
  expect(content).toContain("v.string()");
192
521
  });
193
522
  test("generates CRUD validators from schema columns", async function () {
194
- writeFileSync(join(testDir, "models/task.ts"), `
523
+ writeFileSync(join(testDir, "task/mutations.ts"), `
195
524
  import { table, string, number, boolean } from 'on-zero'
196
525
  import { mutations, serverWhere } from 'on-zero'
197
526
 
@@ -218,7 +547,7 @@ export const mutate = mutations(schema, perm)
218
547
  expect(content).toContain("delete:");
219
548
  });
220
549
  test("treats models without export const mutate as empty mutations", async function () {
221
- writeFileSync(join(testDir, "models/readonly.ts"), `
550
+ writeFileSync(join(testDir, "readonly/mutations.ts"), `
222
551
  import { table, string } from 'on-zero'
223
552
 
224
553
  export const schema = table('readonly').columns({
@@ -235,7 +564,7 @@ export const schema = table('readonly').columns({
235
564
  expect(content).toContain("readonly: {");
236
565
  });
237
566
  test("extracts custom mutations from bare mutations({})", async function () {
238
- writeFileSync(join(testDir, "models/admin.ts"), `
567
+ writeFileSync(join(testDir, "admin/mutations.ts"), `
239
568
  import { mutations } from 'on-zero'
240
569
 
241
570
  export const mutate = mutations({
@@ -253,7 +582,7 @@ export const mutate = mutations({
253
582
  expect(content).toContain("v.string()");
254
583
  });
255
584
  test("generates validators for string-model multiline mutation params", async function () {
256
- writeFileSync(join(testDir, "models/agentEvent.ts"), `
585
+ writeFileSync(join(testDir, "agentEvent/mutations.ts"), `
257
586
  import { mutations, serverWhere } from 'on-zero'
258
587
 
259
588
  const perm = serverWhere('agentEvent', () => true)
@@ -287,7 +616,7 @@ export const mutate = mutations('agentEvent', perm, {
287
616
  expect(content).not.toContain("claimReviewLease: v.object({})");
288
617
  });
289
618
  test("generates validators for object intersections", async function () {
290
- writeFileSync(join(testDir, "models/agent.ts"), `
619
+ writeFileSync(join(testDir, "agent/mutations.ts"), `
291
620
  import { mutations, serverWhere } from 'on-zero'
292
621
 
293
622
  const perm = serverWhere('agent', () => true)
@@ -320,7 +649,7 @@ export const mutate = mutations('agent', perm, {
320
649
  expect(content).not.toContain("[key");
321
650
  });
322
651
  test("uses v.unknown for untyped mutation payloads", async function () {
323
- writeFileSync(join(testDir, "models/project.ts"), `
652
+ writeFileSync(join(testDir, "project/mutations.ts"), `
324
653
  import { mutations, serverWhere } from 'on-zero'
325
654
 
326
655
  const perm = serverWhere('project', () => true)
@@ -340,7 +669,7 @@ export const mutate = mutations('project', perm, {
340
669
  expect(content).not.toContain("insert: v.void_()");
341
670
  });
342
671
  test("handles mutations with only context param (void)", async function () {
343
- writeFileSync(join(testDir, "models/user.ts"), `
672
+ writeFileSync(join(testDir, "user/mutations.ts"), `
344
673
  import { table, string } from 'on-zero'
345
674
  import { mutations, serverWhere } from 'on-zero'
346
675
 
@@ -365,7 +694,7 @@ export const mutate = mutations(schema, perm, {
365
694
  expect(content).toContain("finishOnboarding");
366
695
  });
367
696
  test("handles primitive param type", async function () {
368
- writeFileSync(join(testDir, "models/user.ts"), `
697
+ writeFileSync(join(testDir, "user/mutations.ts"), `
369
698
  import { table, string } from 'on-zero'
370
699
  import { mutations, serverWhere } from 'on-zero'
371
700
 
@@ -391,7 +720,7 @@ export const mutate = mutations(schema, perm, {
391
720
  expect(content).toContain("v.string()");
392
721
  });
393
722
  test("handles array param type", async function () {
394
- writeFileSync(join(testDir, "models/batch.ts"), `
723
+ writeFileSync(join(testDir, "batch/mutations.ts"), `
395
724
  import { mutations } from 'on-zero'
396
725
 
397
726
  export const mutate = mutations({
@@ -409,7 +738,7 @@ export const mutate = mutations({
409
738
  expect(content).toContain("v.array");
410
739
  });
411
740
  test("populates mutationCount and caching works", async function () {
412
- writeFileSync(join(testDir, "models/item.ts"), `
741
+ writeFileSync(join(testDir, "item/mutations.ts"), `
413
742
  import { table, string } from 'on-zero'
414
743
  import { mutations, serverWhere } from 'on-zero'
415
744
 
@@ -441,14 +770,14 @@ export const mutate = mutations(schema, perm, {
441
770
  });
442
771
  describe("type resolution", function () {
443
772
  test("resolves imported type references for mutations", async function () {
444
- writeFileSync(join(testDir, "models/types.ts"), `
773
+ writeFileSync(join(testDir, "post/types.ts"), `
445
774
  export type ArchiveParams = {
446
775
  id: string
447
776
  reason: string
448
777
  archived: boolean
449
778
  }
450
779
  `);
451
- writeFileSync(join(testDir, "models/post.ts"), `
780
+ writeFileSync(join(testDir, "post/mutations.ts"), `
452
781
  import { table, string, boolean } from 'on-zero'
453
782
  import { mutations } from 'on-zero'
454
783
  import type { ArchiveParams } from './types'
@@ -470,7 +799,7 @@ export const mutate = mutations({
470
799
  expect(content).toContain("archived");
471
800
  });
472
801
  test("resolves utility types like Pick", async function () {
473
- writeFileSync(join(testDir, "models/types.ts"), `
802
+ writeFileSync(join(testDir, "item/types.ts"), `
474
803
  export type Item = {
475
804
  id: string
476
805
  name: string
@@ -478,7 +807,7 @@ export type Item = {
478
807
  count: number
479
808
  }
480
809
  `);
481
- writeFileSync(join(testDir, "models/item.ts"), `
810
+ writeFileSync(join(testDir, "item/mutations.ts"), `
482
811
  import { table, string, number } from 'on-zero'
483
812
  import { mutations, serverWhere } from 'on-zero'
484
813
  import type { Item } from './types'
@@ -509,8 +838,8 @@ export const mutate = mutations(schema, perm, {
509
838
  expect(content).not.toMatch(/rename:[\s\S]*count/);
510
839
  });
511
840
  test("resolves instantiated Zero row fields through Partial and Omit", async function () {
512
- symlinkSync(join(import.meta.dirname, "../../../node_modules"), join(testDir, "node_modules"), "dir");
513
- writeFileSync(join(testDir, "models/types.ts"), `
841
+ symlinkSync(join(import.meta.dirname, "../node_modules"), join(testDir, "node_modules"), "dir");
842
+ writeFileSync(join(testDir, "item/types.ts"), `
514
843
  import type { Row } from '@rocicorp/zero'
515
844
  import { drizzleZeroConfig } from 'drizzle-zero-sqlite'
516
845
  import { sqliteTable, text } from 'drizzle-orm/sqlite-core'
@@ -524,7 +853,7 @@ const schema = drizzleZeroConfig({ item })
524
853
 
525
854
  export type Item = Row<(typeof schema)['tables']['item']>
526
855
  `);
527
- writeFileSync(join(testDir, "models/item.ts"), `
856
+ writeFileSync(join(testDir, "item/mutations.ts"), `
528
857
  import { mutations } from 'on-zero'
529
858
  import type { Item } from './types'
530
859
 
@@ -547,13 +876,13 @@ export const mutate = mutations('item', {
547
876
  expect(content).not.toContain("description: v.optional(v.unknown())");
548
877
  });
549
878
  test("skips symbol-keyed properties when resolving imported mutation param types", async function () {
550
- writeFileSync(join(testDir, "models/types.ts"), `
879
+ writeFileSync(join(testDir, "item/types.ts"), `
551
880
  export type WeirdParams = {
552
881
  id: string
553
882
  [Symbol.iterator]?: () => Iterator<string>
554
883
  }
555
884
  `);
556
- writeFileSync(join(testDir, "models/item.ts"), `
885
+ writeFileSync(join(testDir, "item/mutations.ts"), `
557
886
  import { mutations } from 'on-zero'
558
887
  import type { WeirdParams } from './types'
559
888
 
@@ -573,14 +902,14 @@ export const mutate = mutations({
573
902
  expect(content).not.toContain("__@iterator");
574
903
  });
575
904
  test("resolves imported types in query params", async function () {
576
- writeFileSync(join(testDir, "models/post.ts"), `export const schema = table('post', { id: string() })`);
577
- writeFileSync(join(testDir, "queries/types.ts"), `
905
+ writeFileSync(join(testDir, "post/mutations.ts"), `export const schema = table('post', { id: string() })`);
906
+ writeFileSync(join(testDir, "post/types.ts"), `
578
907
  export type PostFilter = {
579
908
  authorId: string
580
909
  published: boolean
581
910
  }
582
911
  `);
583
- writeFileSync(join(testDir, "queries/post.ts"), `
912
+ writeFileSync(join(testDir, "post/queries.ts"), `
584
913
  import type { PostFilter } from './types'
585
914
 
586
915
  export const filteredPosts = (filter: PostFilter) => zero.query.post