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
@@ -4,32 +4,42 @@ import {
4
4
  readFileSync,
5
5
  rmSync,
6
6
  symlinkSync,
7
- writeFileSync,
7
+ writeFileSync as writeFile,
8
8
  } from 'node:fs'
9
9
  import { tmpdir } from 'node:os'
10
- import { join } from 'node:path'
10
+ import { dirname, join } from 'node:path'
11
11
  import { runInNewContext } from 'node:vm'
12
12
 
13
13
  import * as zero from '@rocicorp/zero'
14
- import { afterEach, beforeEach, describe, expect, test } from 'vitest'
14
+ import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'
15
15
 
16
- import { generate, generateDrizzleSchemaFile } from './generate'
16
+ import {
17
+ deriveDataMembership,
18
+ generate,
19
+ generateDrizzleSchemaFile,
20
+ generateDrizzleSchemaInputFile,
21
+ } from './generate'
17
22
 
18
23
  const testDir = join(tmpdir(), 'on-zero-test-' + Date.now())
19
24
 
25
+ function writeFileSync(path: string, content: string) {
26
+ mkdirSync(dirname(path), { recursive: true })
27
+ writeFile(path, content)
28
+ }
29
+
20
30
  beforeEach(() => {
21
- mkdirSync(join(testDir, 'models'), { recursive: true })
22
- mkdirSync(join(testDir, 'queries'), { recursive: true })
31
+ mkdirSync(testDir, { recursive: true })
23
32
  })
24
33
 
25
34
  afterEach(() => {
35
+ vi.restoreAllMocks()
26
36
  rmSync(testDir, { recursive: true, force: true })
27
37
  })
28
38
 
29
39
  describe('generate', () => {
30
40
  test('generates models.ts, types.ts, tables.ts from model files', async () => {
31
41
  writeFileSync(
32
- join(testDir, 'models/post.ts'),
42
+ join(testDir, 'post/mutations.ts'),
33
43
  `
34
44
  import { table, string, boolean } from 'on-zero'
35
45
 
@@ -38,11 +48,11 @@ export const schema = table('post', {
38
48
  title: string(),
39
49
  published: boolean(),
40
50
  })
41
- `,
51
+ `
42
52
  )
43
53
 
44
54
  writeFileSync(
45
- join(testDir, 'models/comment.ts'),
55
+ join(testDir, 'comment/mutations.ts'),
46
56
  `
47
57
  import { table, string } from 'on-zero'
48
58
 
@@ -51,16 +61,16 @@ export const schema = table('comment', {
51
61
  postId: string(),
52
62
  body: string(),
53
63
  })
54
- `,
64
+ `
55
65
  )
56
66
 
57
67
  writeFileSync(
58
- join(testDir, 'models/post.test.ts'),
59
- `throw new Error('test files must not be generated as models')`,
68
+ join(testDir, 'post/post.test.ts'),
69
+ `throw new Error('test files must not be generated as models')`
60
70
  )
61
71
  writeFileSync(
62
- join(testDir, 'queries/comment.spec.ts'),
63
- `throw new Error('spec files must not be generated as queries')`,
72
+ join(testDir, 'comment/comment.spec.ts'),
73
+ `throw new Error('spec files must not be generated as queries')`
64
74
  )
65
75
 
66
76
  const result = await generate({ dir: testDir, silent: true })
@@ -76,37 +86,37 @@ export const schema = table('comment', {
76
86
 
77
87
  // check models.ts content
78
88
  const modelsContent = readFileSync(join(testDir, 'generated/models.ts'), 'utf-8')
79
- expect(modelsContent).toContain("import * as comment from '../models/comment'")
80
- expect(modelsContent).toContain("import * as post from '../models/post'")
89
+ expect(modelsContent).toContain("import * as comment from '../comment/mutations'")
90
+ expect(modelsContent).toContain("import * as post from '../post/mutations'")
81
91
  expect(modelsContent).not.toContain('post.test')
82
92
  expect(modelsContent).toContain('export const models = {')
83
93
 
84
94
  // check types.ts content
85
95
  const typesContent = readFileSync(join(testDir, 'generated/types.ts'), 'utf-8')
86
96
  expect(typesContent).toContain(
87
- 'export type Post = TableInsertRow<typeof schema.post>',
97
+ 'export type Post = TableInsertRow<typeof schema.post>'
88
98
  )
89
99
  expect(typesContent).toContain(
90
- 'export type Comment = TableInsertRow<typeof schema.comment>',
100
+ 'export type Comment = TableInsertRow<typeof schema.comment>'
91
101
  )
92
102
 
93
103
  // check tables.ts content
94
104
  const tablesContent = readFileSync(join(testDir, 'generated/tables.ts'), 'utf-8')
95
- expect(tablesContent).toContain("export { schema as post } from '../models/post'")
105
+ expect(tablesContent).toContain("export { schema as post } from '../post/mutations'")
96
106
  expect(tablesContent).toContain(
97
- "export { schema as comment } from '../models/comment'",
107
+ "export { schema as comment } from '../comment/mutations'"
98
108
  )
99
109
  })
100
110
 
101
111
  test('generates query validators from query files', async () => {
102
112
  // need at least one model
103
113
  writeFileSync(
104
- join(testDir, 'models/post.ts'),
105
- `export const schema = table('post', { id: string() })`,
114
+ join(testDir, 'post/mutations.ts'),
115
+ `export const schema = table('post', { id: string() })`
106
116
  )
107
117
 
108
118
  writeFileSync(
109
- join(testDir, 'queries/post.ts'),
119
+ join(testDir, 'post/queries.ts'),
110
120
  `
111
121
  import { zero } from '../zero'
112
122
 
@@ -116,7 +126,7 @@ export const postById = ({ id }: { id: string }) => zero.query.post.where('id',
116
126
 
117
127
  export const postsByAuthor = ({ authorId, limit }: { authorId: string; limit?: number }) =>
118
128
  zero.query.post.where('authorId', authorId).limit(limit ?? 10)
119
- `,
129
+ `
120
130
  )
121
131
 
122
132
  const result = await generate({ dir: testDir, silent: true })
@@ -130,14 +140,15 @@ export const postsByAuthor = ({ authorId, limit }: { authorId: string; limit?: n
130
140
  // check groupedQueries.ts
131
141
  const groupedContent = readFileSync(
132
142
  join(testDir, 'generated/groupedQueries.ts'),
133
- 'utf-8',
143
+ 'utf-8'
134
144
  )
135
- expect(groupedContent).toContain("export * as post from '../queries/post'")
145
+ expect(groupedContent).toContain("import * as postSource from '../post/queries'")
146
+ expect(groupedContent).toContain('postById: postSource.postById')
136
147
 
137
148
  // check syncedQueries.ts has validators
138
149
  const syncedContent = readFileSync(
139
150
  join(testDir, 'generated/syncedQueries.ts'),
140
- 'utf-8',
151
+ 'utf-8'
141
152
  )
142
153
  expect(syncedContent).toContain('allPosts: defineQuery')
143
154
  expect(syncedContent).toContain('postById: defineQuery')
@@ -147,16 +158,16 @@ export const postsByAuthor = ({ authorId, limit }: { authorId: string; limit?: n
147
158
 
148
159
  test('skips permission exports in queries', async () => {
149
160
  writeFileSync(
150
- join(testDir, 'models/post.ts'),
151
- `export const schema = table('post', { id: string() })`,
161
+ join(testDir, 'post/mutations.ts'),
162
+ `export const schema = table('post', { id: string() })`
152
163
  )
153
164
 
154
165
  writeFileSync(
155
- join(testDir, 'queries/post.ts'),
166
+ join(testDir, 'post/queries.ts'),
156
167
  `
157
168
  export const permission = () => ({ canRead: true })
158
169
  export const allPosts = () => zero.query.post
159
- `,
170
+ `
160
171
  )
161
172
 
162
173
  const result = await generate({ dir: testDir, silent: true })
@@ -165,7 +176,7 @@ export const allPosts = () => zero.query.post
165
176
 
166
177
  const syncedContent = readFileSync(
167
178
  join(testDir, 'generated/syncedQueries.ts'),
168
- 'utf-8',
179
+ 'utf-8'
169
180
  )
170
181
  expect(syncedContent).toContain('allPosts')
171
182
  expect(syncedContent).not.toContain('permission:')
@@ -173,14 +184,14 @@ export const allPosts = () => zero.query.post
173
184
 
174
185
  test('aliases user import without changing the model key', async () => {
175
186
  writeFileSync(
176
- join(testDir, 'models/user.ts'),
177
- `export const schema = table('user', { id: string(), name: string() })`,
187
+ join(testDir, 'user/mutations.ts'),
188
+ `export const schema = table('user', { id: string(), name: string() })`
178
189
  )
179
190
 
180
191
  await generate({ dir: testDir, silent: true })
181
192
 
182
193
  const modelsContent = readFileSync(join(testDir, 'generated/models.ts'), 'utf-8')
183
- expect(modelsContent).toContain("import * as userPublic from '../models/user'")
194
+ expect(modelsContent).toContain("import * as userPublic from '../user/mutations'")
184
195
  expect(modelsContent).toContain('user: userPublic,')
185
196
  expect(modelsContent).not.toContain('\n userPublic,')
186
197
 
@@ -190,8 +201,8 @@ export const allPosts = () => zero.query.post
190
201
 
191
202
  test('runs after command when files change', async () => {
192
203
  writeFileSync(
193
- join(testDir, 'models/post.ts'),
194
- `export const schema = table('post', { id: string() })`,
204
+ join(testDir, 'post/mutations.ts'),
205
+ `export const schema = table('post', { id: string() })`
195
206
  )
196
207
 
197
208
  // use a command that creates a marker file
@@ -208,8 +219,8 @@ export const allPosts = () => zero.query.post
208
219
 
209
220
  test('does not regenerate when nothing changed', async () => {
210
221
  writeFileSync(
211
- join(testDir, 'models/post.ts'),
212
- `export const schema = table('post', { id: string() })`,
222
+ join(testDir, 'post/mutations.ts'),
223
+ `export const schema = table('post', { id: string() })`
213
224
  )
214
225
 
215
226
  const first = await generate({ dir: testDir, silent: true })
@@ -221,12 +232,12 @@ export const allPosts = () => zero.query.post
221
232
 
222
233
  test('force regenerates without source changes', async () => {
223
234
  writeFileSync(
224
- join(testDir, 'models/post.ts'),
225
- `export const schema = table('post', { id: string() })`,
235
+ join(testDir, 'post/mutations.ts'),
236
+ `export const schema = table('post', { id: string() })`
226
237
  )
227
238
  writeFileSync(
228
- join(testDir, 'queries/post.ts'),
229
- `export const allPosts = () => zero.query.post`,
239
+ join(testDir, 'post/queries.ts'),
240
+ `export const allPosts = () => zero.query.post`
230
241
  )
231
242
  await generate({ dir: testDir, silent: true })
232
243
  const syncedQueriesPath = join(testDir, 'generated/syncedQueries.ts')
@@ -238,10 +249,461 @@ export const allPosts = () => zero.query.post
238
249
  })
239
250
  })
240
251
 
252
+ describe('instance layout', () => {
253
+ const dataDir = () => join(testDir, 'src/data')
254
+
255
+ test('discovers file and folder namespaces and emits related sync closure', async () => {
256
+ writeFileSync(
257
+ join(dataDir(), 'control/reaction.ts'),
258
+ `export const allReactions = () => zql.reaction`
259
+ )
260
+ writeFileSync(
261
+ join(dataDir(), 'on-zero.config.ts'),
262
+ `export default defineConfig({ instances: { control: {}, project: { scope: 'projectId' } } })`
263
+ )
264
+ writeFileSync(
265
+ join(dataDir(), 'project/message/queries.ts'),
266
+ `
267
+ const unused = () => zql.message.related('notARealRelation')
268
+ const withComments = () => zql.message.related('comments', (q) => q.related('author'))
269
+ export const messages = () => withComments()
270
+ `
271
+ )
272
+ writeFileSync(
273
+ join(dataDir(), 'project/message/mutations.ts'),
274
+ `export const schema = table('message').columns({ id: string(), projectId: string() })`
275
+ )
276
+ writeFileSync(
277
+ join(dataDir(), 'project/message/helpers.ts'),
278
+ `export const privateHelper = () => 'ignored'`
279
+ )
280
+ writeFileSync(
281
+ join(testDir, 'src/database/relations.ts'),
282
+ `
283
+ export const relations = defineRelations(schema, (r) => ({
284
+ message: { comments: r.many.comment({}) },
285
+ comment: { author: r.one.userPublic({}) },
286
+ }))
287
+ `
288
+ )
289
+ writeFileSync(
290
+ join(testDir, 'src/database/schema.ts'),
291
+ `
292
+ export const comment = sqliteTable('comment', { id: text(), projectId: text() })
293
+ export const userPublic = sqliteTable('user_public', { id: text(), projectId: text() })
294
+ `
295
+ )
296
+
297
+ const membership = await deriveDataMembership({ dir: dataDir() })
298
+ expect(membership.allTables).toEqual(['comment', 'message', 'reaction', 'userPublic'])
299
+ expect(membership.instances.project).toEqual({
300
+ tables: ['message'],
301
+ syncTables: ['comment', 'message', 'userPublic'],
302
+ supportTables: [],
303
+ scope: 'projectId',
304
+ })
305
+
306
+ await generate({ dir: dataDir(), silent: true })
307
+
308
+ const grouped = readFileSync(join(dataDir(), 'generated/groupedQueries.ts'), 'utf8')
309
+ expect(grouped).toContain("from '../control/reaction'")
310
+ expect(grouped).toContain("from '../project/message/queries'")
311
+ expect(grouped).not.toContain('privateHelper')
312
+
313
+ const manifest = readFileSync(join(dataDir(), 'generated/instances.ts'), 'utf8')
314
+ expect(manifest).toContain('control: {')
315
+ expect(manifest).toContain('project: {')
316
+ expect(manifest).toContain('tables: ["message"]')
317
+ expect(manifest).toContain('syncTables: ["comment","message","userPublic"]')
318
+ expect(manifest).toContain(
319
+ `defaultVisibility: (value: string) => ({ column: "projectId", value })`
320
+ )
321
+ })
322
+
323
+ test('derives single-file namespaces from data exports', async () => {
324
+ writeFileSync(
325
+ join(dataDir(), 'server.ts'),
326
+ `export const serverRows = () => zql.server`
327
+ )
328
+ writeFileSync(
329
+ join(dataDir(), 'types.ts'),
330
+ `export const formatRow = (value: string) => value`
331
+ )
332
+ writeFileSync(
333
+ join(dataDir(), 'auth.ts'),
334
+ `export function authId(auth: { id: string }) { return auth.id }`
335
+ )
336
+
337
+ await expect(deriveDataMembership({ dir: dataDir() })).resolves.toEqual({
338
+ instances: {
339
+ default: {
340
+ tables: ['server'],
341
+ syncTables: ['server'],
342
+ supportTables: [],
343
+ scope: null,
344
+ },
345
+ },
346
+ allTables: ['server'],
347
+ })
348
+ })
349
+
350
+ test('warns once and ignores an unparseable non-data file', async () => {
351
+ writeFileSync(join(dataDir(), 'post.ts'), `export const posts = () => zql.post`)
352
+ writeFileSync(join(dataDir(), 'types.ts'), `export type Broken = {`)
353
+ const warn = vi.spyOn(console, 'warn').mockImplementation(() => {})
354
+
355
+ await expect(deriveDataMembership({ dir: dataDir() })).resolves.toMatchObject({
356
+ allTables: ['post'],
357
+ })
358
+ expect(warn).toHaveBeenCalledOnce()
359
+ expect(warn).toHaveBeenCalledWith(
360
+ '[on-zero] ignoring data/types.ts: no recognized data exports'
361
+ )
362
+ warn.mockRestore()
363
+ })
364
+
365
+ test('derives fileless support tables through mutation helpers', async () => {
366
+ writeFileSync(
367
+ join(dataDir(), 'post.ts'),
368
+ `
369
+ import { writeAudit } from './helpers/writeAudit'
370
+ export const posts = () => zql.post
371
+ export const mutate = mutations('post', { save: async (ctx) => writeAudit(ctx.tx) })
372
+ `
373
+ )
374
+ writeFileSync(
375
+ join(dataDir(), 'helpers/writeAudit.ts'),
376
+ `
377
+ import { readSettings } from './readSettings'
378
+ export async function writeAudit(tx: Transaction) {
379
+ await tx.mutate.audit.insert({ id: 'audit' })
380
+ await tx.mutate.post.update({ id: 'post' })
381
+ await tx.mutate[tableName].insert({ id: 'dynamic' })
382
+ return readSettings(tx)
383
+ }
384
+ `
385
+ )
386
+ writeFileSync(
387
+ join(dataDir(), 'helpers/readSettings.ts'),
388
+ `export const readSettings = (tx: Transaction) => tx.query.settings`
389
+ )
390
+
391
+ await expect(deriveDataMembership({ dir: dataDir() })).resolves.toEqual({
392
+ instances: {
393
+ default: {
394
+ tables: ['post'],
395
+ syncTables: ['post'],
396
+ supportTables: ['audit', 'settings'],
397
+ scope: null,
398
+ },
399
+ },
400
+ allTables: ['audit', 'post', 'settings'],
401
+ })
402
+ })
403
+
404
+ test('includes a fileless support table in every instance that uses it', async () => {
405
+ writeFileSync(
406
+ join(dataDir(), 'control/account.ts'),
407
+ `export const mutate = mutations('account', { save: async (ctx) => ctx.tx.mutate.audit.insert({}) })`
408
+ )
409
+ writeFileSync(
410
+ join(dataDir(), 'on-zero.config.ts'),
411
+ `export default defineConfig({ instances: { control: {}, project: { scope: 'projectId' } } })`
412
+ )
413
+ writeFileSync(
414
+ join(dataDir(), 'project/message.ts'),
415
+ `
416
+ export const schema = table('message').columns({ id: string(), projectId: string() })
417
+ export const mutate = mutations(schema, permission, {
418
+ save: async (ctx) => ctx.tx.mutate.audit.insert({}),
419
+ })
420
+ `
421
+ )
422
+
423
+ await expect(deriveDataMembership({ dir: dataDir() })).resolves.toMatchObject({
424
+ instances: {
425
+ control: { supportTables: ['audit'] },
426
+ project: { supportTables: ['audit'] },
427
+ },
428
+ allTables: ['account', 'audit', 'message'],
429
+ })
430
+ })
431
+
432
+ test('keeps a configured default instance at the data root', async () => {
433
+ writeFileSync(
434
+ join(dataDir(), 'on-zero.config.ts'),
435
+ `export default defineConfig({ instances: { default: { dir: '.', supportTables: ['accountGithubOrgLink', 'accountRepo', 'usageLedger'] }, project: { scope: 'projectId' } } })`
436
+ )
437
+ writeFileSync(
438
+ join(dataDir(), 'account.ts'),
439
+ `export const accounts = () => zql.account`
440
+ )
441
+ writeFileSync(
442
+ join(dataDir(), 'project/message.ts'),
443
+ `export const schema = table('message').columns({ id: string(), projectId: string() })`
444
+ )
445
+
446
+ await expect(deriveDataMembership({ dir: dataDir() })).resolves.toEqual({
447
+ instances: {
448
+ default: {
449
+ tables: ['account'],
450
+ syncTables: ['account'],
451
+ supportTables: ['accountGithubOrgLink', 'accountRepo', 'usageLedger'],
452
+ scope: null,
453
+ },
454
+ project: {
455
+ tables: ['message'],
456
+ syncTables: ['message'],
457
+ supportTables: [],
458
+ scope: 'projectId',
459
+ },
460
+ },
461
+ allTables: [
462
+ 'account',
463
+ 'accountGithubOrgLink',
464
+ 'accountRepo',
465
+ 'message',
466
+ 'usageLedger',
467
+ ],
468
+ })
469
+ })
470
+
471
+ test('emits only relations whose source and target are derived members', async () => {
472
+ writeFileSync(join(dataDir(), 'post.ts'), `export const posts = () => zql.post`)
473
+ writeFileSync(
474
+ join(dataDir(), 'comment.ts'),
475
+ `export const comments = () => zql.comment`
476
+ )
477
+ writeFileSync(
478
+ join(testDir, 'src/database/relations.ts'),
479
+ `
480
+ export const relations = defineRelations(schema, (r) => ({
481
+ post: {
482
+ comments: r.many.comment({}),
483
+ privateNotes: r.many.privateNote({}),
484
+ },
485
+ comment: { post: r.one.post({}), author: r.one.privateUser({}) },
486
+ privateNote: { post: r.one.post({}) },
487
+ }))
488
+ `
489
+ )
490
+
491
+ const generated = await generateDrizzleSchemaInputFile({
492
+ dir: dataDir(),
493
+ schemaImportPath: '../../database/schema',
494
+ })
495
+ const runnable = generated
496
+ .replace(`import { defineRelations } from 'drizzle-orm'`, '')
497
+ .replace(`import * as schema from "../../database/schema"`, '')
498
+ .replace(/export \{[^\n]+\} from [^\n]+/, '')
499
+ .replace('export const relations =', 'globalThis.relations =')
500
+ const context = {
501
+ schema: { comment: {}, post: {} },
502
+ defineRelations: (_schema: unknown, factory: (relations: unknown) => unknown) =>
503
+ factory({
504
+ one: new Proxy({}, { get: (_target, table) => () => ({ table }) }),
505
+ many: new Proxy({}, { get: (_target, table) => () => ({ table }) }),
506
+ }),
507
+ } as { relations?: unknown }
508
+
509
+ runInNewContext(runnable, context)
510
+
511
+ expect(context.relations).toEqual({
512
+ comment: { post: { table: 'post' } },
513
+ post: { comments: { table: 'comment' } },
514
+ })
515
+ })
516
+
517
+ test('rejects a relation that crosses instance ownership', async () => {
518
+ writeFileSync(
519
+ join(dataDir(), 'control/userPublic.ts'),
520
+ `export const users = () => zql.userPublic`
521
+ )
522
+ writeFileSync(
523
+ join(dataDir(), 'on-zero.config.ts'),
524
+ `export default defineConfig({ instances: { control: {}, project: { scope: 'projectId' } } })`
525
+ )
526
+ writeFileSync(
527
+ join(dataDir(), 'project/message.ts'),
528
+ `
529
+ export const schema = table('message').columns({ id: string(), projectId: string() })
530
+ export const messages = () => zql.message.related('author')
531
+ `
532
+ )
533
+ writeFileSync(
534
+ join(testDir, 'src/database/relations.ts'),
535
+ `export const relations = defineRelations(schema, (r) => ({ message: { author: r.one.userPublic({}) } }))`
536
+ )
537
+
538
+ await expect(generate({ dir: dataDir(), silent: true })).rejects.toThrow(
539
+ /message\.messages.*instance 'project'.*userPublic.*instance 'control'/
540
+ )
541
+ })
542
+
543
+ test('rejects a scoped sync table without the scope column', async () => {
544
+ writeFileSync(
545
+ join(dataDir(), 'on-zero.config.ts'),
546
+ `export default defineConfig({ instances: { project: { scope: 'projectId' } } })`
547
+ )
548
+ writeFileSync(
549
+ join(dataDir(), 'project/message.ts'),
550
+ `export const schema = table('message').columns({ id: string() })`
551
+ )
552
+
553
+ await expect(generate({ dir: dataDir(), silent: true })).rejects.toThrow(
554
+ /table 'message'.*instance 'project'.*scope column 'projectId'/
555
+ )
556
+ })
557
+
558
+ test('rejects duplicate namespaces across instances', async () => {
559
+ writeFileSync(
560
+ join(dataDir(), 'control/message.ts'),
561
+ `export const messages = () => zql.message`
562
+ )
563
+ writeFileSync(
564
+ join(dataDir(), 'on-zero.config.ts'),
565
+ `export default defineConfig({ instances: { control: {}, project: { scope: 'projectId' } } })`
566
+ )
567
+ writeFileSync(
568
+ join(dataDir(), 'project/message.ts'),
569
+ `export const schema = table('message').columns({ projectId: string() })`
570
+ )
571
+
572
+ await expect(generate({ dir: dataDir(), silent: true })).rejects.toThrow(
573
+ /namespace 'message'.*instances 'control' and 'project'/
574
+ )
575
+ })
576
+
577
+ test('resolves configured instance directories relative to the config file', async () => {
578
+ writeFileSync(
579
+ join(dataDir(), 'on-zero.config.ts'),
580
+ `export default defineConfig({ instances: { control: { dir: './planes/control-data', supportTables: ['audit'] }, project: { dir: '../project-data', scope: 'projectId' } } })`
581
+ )
582
+ writeFileSync(
583
+ join(dataDir(), 'planes/control-data/account.ts'),
584
+ `export const accounts = () => zql.account`
585
+ )
586
+ writeFileSync(
587
+ join(testDir, 'src/project-data/message.ts'),
588
+ `export const schema = table('message').columns({ id: string(), projectId: string() })`
589
+ )
590
+
591
+ await expect(
592
+ deriveDataMembership({
593
+ dir: dataDir(),
594
+ config: join(dataDir(), 'on-zero.config.ts'),
595
+ })
596
+ ).resolves.toEqual({
597
+ instances: {
598
+ control: {
599
+ tables: ['account'],
600
+ syncTables: ['account'],
601
+ supportTables: ['audit'],
602
+ scope: null,
603
+ },
604
+ project: {
605
+ tables: ['message'],
606
+ syncTables: ['message'],
607
+ supportTables: [],
608
+ scope: 'projectId',
609
+ },
610
+ },
611
+ allTables: ['account', 'audit', 'message'],
612
+ })
613
+
614
+ await expect(
615
+ generate({
616
+ dir: dataDir(),
617
+ config: join(dataDir(), 'on-zero.config.ts'),
618
+ silent: true,
619
+ })
620
+ ).resolves.toMatchObject({ modelCount: 2, schemaCount: 1 })
621
+ expect(readFileSync(join(dataDir(), 'generated/models.ts'), 'utf8')).toContain(
622
+ "from '../../project-data/message'"
623
+ )
624
+ })
625
+
626
+ test('rejects missing configured instance directories', async () => {
627
+ writeFileSync(
628
+ join(dataDir(), 'on-zero.config.ts'),
629
+ `export default defineConfig({ instances: { project: { dir: './missing' } } })`
630
+ )
631
+
632
+ await expect(deriveDataMembership({ dir: dataDir() })).rejects.toThrow(
633
+ /instance 'project' directory does not exist.*missing/
634
+ )
635
+ })
636
+
637
+ test('rejects two instances that resolve to the same directory', async () => {
638
+ writeFileSync(
639
+ join(dataDir(), 'on-zero.config.ts'),
640
+ `export default defineConfig({ instances: { control: { dir: './shared' }, project: { dir: './shared' } } })`
641
+ )
642
+ writeFileSync(
643
+ join(dataDir(), 'shared/account.ts'),
644
+ `export const accounts = () => zql.account`
645
+ )
646
+
647
+ await expect(deriveDataMembership({ dir: dataDir() })).rejects.toThrow(
648
+ /instances 'control' and 'project' resolve to the same directory/
649
+ )
650
+ })
651
+
652
+ test('rejects root namespaces when instances are configured', async () => {
653
+ writeFileSync(
654
+ join(dataDir(), 'on-zero.config.ts'),
655
+ `export default defineConfig({ instances: { project: {} } })`
656
+ )
657
+ writeFileSync(
658
+ join(dataDir(), 'project/message.ts'),
659
+ `export const rows = () => zql.message`
660
+ )
661
+ writeFileSync(join(dataDir(), 'account.ts'), `export const rows = () => zql.account`)
662
+
663
+ await expect(deriveDataMembership({ dir: dataDir() })).rejects.toThrow(
664
+ /data namespace .*account\.ts.*outside every instance directory/
665
+ )
666
+ })
667
+
668
+ test('rejects removed instance.ts configuration', async () => {
669
+ writeFileSync(join(dataDir(), 'post.ts'), `export const posts = () => zql.post`)
670
+ writeFileSync(
671
+ join(dataDir(), 'project/instance.ts'),
672
+ `export default defineInstance({ scope: 'projectId' })`
673
+ )
674
+
675
+ await expect(deriveDataMembership({ dir: dataDir() })).rejects.toThrow(
676
+ /uses removed instance\.ts configuration/
677
+ )
678
+ })
679
+
680
+ test('rejects the removed top-level layout', async () => {
681
+ writeFileSync(
682
+ join(dataDir(), 'queries/message.ts'),
683
+ `export const messages = () => zql.message`
684
+ )
685
+
686
+ await expect(generate({ dir: dataDir(), silent: true })).rejects.toThrow(
687
+ /removed top-level queries\/ layout/
688
+ )
689
+ })
690
+
691
+ test('rejects dynamically named relations', async () => {
692
+ writeFileSync(
693
+ join(dataDir(), 'message.ts'),
694
+ `export const messages = (relation: string) => zql.message.related(relation)`
695
+ )
696
+
697
+ await expect(generate({ dir: dataDir(), silent: true })).rejects.toThrow(
698
+ /related\(\) without a string literal.*statically derivable/
699
+ )
700
+ })
701
+ })
702
+
241
703
  describe('mutations', () => {
242
704
  test('generates validators for inline mutation param types', async () => {
243
705
  writeFileSync(
244
- join(testDir, 'models/post.ts'),
706
+ join(testDir, 'post/mutations.ts'),
245
707
  `
246
708
  import { table, string } from 'on-zero'
247
709
  import { mutations, serverWhere } from 'on-zero'
@@ -258,7 +720,7 @@ export const mutate = mutations(schema, perm, {
258
720
  await tx.mutate.post.update({ id, archived: true })
259
721
  },
260
722
  })
261
- `,
723
+ `
262
724
  )
263
725
 
264
726
  const result = await generate({ dir: testDir, silent: true })
@@ -274,7 +736,7 @@ export const mutate = mutations(schema, perm, {
274
736
 
275
737
  test('generates CRUD validators from schema columns', async () => {
276
738
  writeFileSync(
277
- join(testDir, 'models/task.ts'),
739
+ join(testDir, 'task/mutations.ts'),
278
740
  `
279
741
  import { table, string, number, boolean } from 'on-zero'
280
742
  import { mutations, serverWhere } from 'on-zero'
@@ -290,7 +752,7 @@ export const schema = table('task').columns({
290
752
  const perm = serverWhere('task', () => true)
291
753
 
292
754
  export const mutate = mutations(schema, perm)
293
- `,
755
+ `
294
756
  )
295
757
 
296
758
  const result = await generate({ dir: testDir, silent: true })
@@ -310,7 +772,7 @@ export const mutate = mutations(schema, perm)
310
772
 
311
773
  test('treats models without export const mutate as empty mutations', async () => {
312
774
  writeFileSync(
313
- join(testDir, 'models/readonly.ts'),
775
+ join(testDir, 'readonly/mutations.ts'),
314
776
  `
315
777
  import { table, string } from 'on-zero'
316
778
 
@@ -318,7 +780,7 @@ export const schema = table('readonly').columns({
318
780
  id: string(),
319
781
  name: string(),
320
782
  }).primaryKey('id')
321
- `,
783
+ `
322
784
  )
323
785
 
324
786
  const result = await generate({ dir: testDir, silent: true })
@@ -330,7 +792,7 @@ export const schema = table('readonly').columns({
330
792
 
331
793
  test('extracts custom mutations from bare mutations({})', async () => {
332
794
  writeFileSync(
333
- join(testDir, 'models/admin.ts'),
795
+ join(testDir, 'admin/mutations.ts'),
334
796
  `
335
797
  import { mutations } from 'on-zero'
336
798
 
@@ -339,7 +801,7 @@ export const mutate = mutations({
339
801
  await tx.mutate.admin.delete({ id: targetId })
340
802
  },
341
803
  })
342
- `,
804
+ `
343
805
  )
344
806
 
345
807
  const result = await generate({ dir: testDir, silent: true })
@@ -351,7 +813,7 @@ export const mutate = mutations({
351
813
 
352
814
  test('generates validators for string-model multiline mutation params', async () => {
353
815
  writeFileSync(
354
- join(testDir, 'models/agentEvent.ts'),
816
+ join(testDir, 'agentEvent/mutations.ts'),
355
817
  `
356
818
  import { mutations, serverWhere } from 'on-zero'
357
819
 
@@ -374,7 +836,7 @@ export const mutate = mutations('agentEvent', perm, {
374
836
  await tx.mutate.agentEvent.insert(props)
375
837
  },
376
838
  })
377
- `,
839
+ `
378
840
  )
379
841
 
380
842
  await generate({ dir: testDir, silent: true })
@@ -388,7 +850,7 @@ export const mutate = mutations('agentEvent', perm, {
388
850
 
389
851
  test('generates validators for object intersections', async () => {
390
852
  writeFileSync(
391
- join(testDir, 'models/agent.ts'),
853
+ join(testDir, 'agent/mutations.ts'),
392
854
  `
393
855
  import { mutations, serverWhere } from 'on-zero'
394
856
 
@@ -408,7 +870,7 @@ export const mutate = mutations('agent', perm, {
408
870
  await tx.mutate.agent.update(props)
409
871
  },
410
872
  })
411
- `,
873
+ `
412
874
  )
413
875
 
414
876
  await generate({ dir: testDir, silent: true })
@@ -424,7 +886,7 @@ export const mutate = mutations('agent', perm, {
424
886
 
425
887
  test('uses v.unknown for untyped mutation payloads', async () => {
426
888
  writeFileSync(
427
- join(testDir, 'models/project.ts'),
889
+ join(testDir, 'project/mutations.ts'),
428
890
  `
429
891
  import { mutations, serverWhere } from 'on-zero'
430
892
 
@@ -435,7 +897,7 @@ export const mutate = mutations('project', perm, {
435
897
  await tx.mutate.project.insert(project)
436
898
  },
437
899
  })
438
- `,
900
+ `
439
901
  )
440
902
 
441
903
  await generate({ dir: testDir, silent: true })
@@ -447,7 +909,7 @@ export const mutate = mutations('project', perm, {
447
909
 
448
910
  test('handles mutations with only context param (void)', async () => {
449
911
  writeFileSync(
450
- join(testDir, 'models/user.ts'),
912
+ join(testDir, 'user/mutations.ts'),
451
913
  `
452
914
  import { table, string } from 'on-zero'
453
915
  import { mutations, serverWhere } from 'on-zero'
@@ -464,7 +926,7 @@ export const mutate = mutations(schema, perm, {
464
926
  // no second param
465
927
  },
466
928
  })
467
- `,
929
+ `
468
930
  )
469
931
 
470
932
  const result = await generate({ dir: testDir, silent: true })
@@ -476,7 +938,7 @@ export const mutate = mutations(schema, perm, {
476
938
 
477
939
  test('handles primitive param type', async () => {
478
940
  writeFileSync(
479
- join(testDir, 'models/user.ts'),
941
+ join(testDir, 'user/mutations.ts'),
480
942
  `
481
943
  import { table, string } from 'on-zero'
482
944
  import { mutations, serverWhere } from 'on-zero'
@@ -493,7 +955,7 @@ export const mutate = mutations(schema, perm, {
493
955
  await tx.mutate.user.update({ id: userId })
494
956
  },
495
957
  })
496
- `,
958
+ `
497
959
  )
498
960
 
499
961
  const result = await generate({ dir: testDir, silent: true })
@@ -505,7 +967,7 @@ export const mutate = mutations(schema, perm, {
505
967
 
506
968
  test('handles array param type', async () => {
507
969
  writeFileSync(
508
- join(testDir, 'models/batch.ts'),
970
+ join(testDir, 'batch/mutations.ts'),
509
971
  `
510
972
  import { mutations } from 'on-zero'
511
973
 
@@ -514,7 +976,7 @@ export const mutate = mutations({
514
976
  for (const { id } of ids) await tx.mutate.batch.delete({ id })
515
977
  },
516
978
  })
517
- `,
979
+ `
518
980
  )
519
981
 
520
982
  const result = await generate({ dir: testDir, silent: true })
@@ -526,7 +988,7 @@ export const mutate = mutations({
526
988
 
527
989
  test('populates mutationCount and caching works', async () => {
528
990
  writeFileSync(
529
- join(testDir, 'models/item.ts'),
991
+ join(testDir, 'item/mutations.ts'),
530
992
  `
531
993
  import { table, string } from 'on-zero'
532
994
  import { mutations, serverWhere } from 'on-zero'
@@ -543,7 +1005,7 @@ export const mutate = mutations(schema, perm, {
543
1005
  await tx.mutate.item.update({ id, name })
544
1006
  },
545
1007
  })
546
- `,
1008
+ `
547
1009
  )
548
1010
 
549
1011
  const first = await generate({ dir: testDir, silent: true })
@@ -559,18 +1021,18 @@ describe('type resolution', () => {
559
1021
  test('resolves imported type references for mutations', async () => {
560
1022
  // types file that the model imports from
561
1023
  writeFileSync(
562
- join(testDir, 'models/types.ts'),
1024
+ join(testDir, 'post/types.ts'),
563
1025
  `
564
1026
  export type ArchiveParams = {
565
1027
  id: string
566
1028
  reason: string
567
1029
  archived: boolean
568
1030
  }
569
- `,
1031
+ `
570
1032
  )
571
1033
 
572
1034
  writeFileSync(
573
- join(testDir, 'models/post.ts'),
1035
+ join(testDir, 'post/mutations.ts'),
574
1036
  `
575
1037
  import { table, string, boolean } from 'on-zero'
576
1038
  import { mutations } from 'on-zero'
@@ -581,7 +1043,7 @@ export const mutate = mutations({
581
1043
  await tx.mutate.post.update(params)
582
1044
  },
583
1045
  })
584
- `,
1046
+ `
585
1047
  )
586
1048
 
587
1049
  const result = await generate({ dir: testDir, silent: true })
@@ -596,7 +1058,7 @@ export const mutate = mutations({
596
1058
 
597
1059
  test('resolves utility types like Pick', async () => {
598
1060
  writeFileSync(
599
- join(testDir, 'models/types.ts'),
1061
+ join(testDir, 'item/types.ts'),
600
1062
  `
601
1063
  export type Item = {
602
1064
  id: string
@@ -604,11 +1066,11 @@ export type Item = {
604
1066
  description: string
605
1067
  count: number
606
1068
  }
607
- `,
1069
+ `
608
1070
  )
609
1071
 
610
1072
  writeFileSync(
611
- join(testDir, 'models/item.ts'),
1073
+ join(testDir, 'item/mutations.ts'),
612
1074
  `
613
1075
  import { table, string, number } from 'on-zero'
614
1076
  import { mutations, serverWhere } from 'on-zero'
@@ -628,7 +1090,7 @@ export const mutate = mutations(schema, perm, {
628
1090
  await tx.mutate.item.update(updates)
629
1091
  },
630
1092
  })
631
- `,
1093
+ `
632
1094
  )
633
1095
 
634
1096
  const result = await generate({ dir: testDir, silent: true })
@@ -644,12 +1106,12 @@ export const mutate = mutations(schema, perm, {
644
1106
 
645
1107
  test('resolves instantiated Zero row fields through Partial and Omit', async () => {
646
1108
  symlinkSync(
647
- join(import.meta.dirname, '../../../node_modules'),
1109
+ join(import.meta.dirname, '../node_modules'),
648
1110
  join(testDir, 'node_modules'),
649
- 'dir',
1111
+ 'dir'
650
1112
  )
651
1113
  writeFileSync(
652
- join(testDir, 'models/types.ts'),
1114
+ join(testDir, 'item/types.ts'),
653
1115
  `
654
1116
  import type { Row } from '@rocicorp/zero'
655
1117
  import { drizzleZeroConfig } from 'drizzle-zero-sqlite'
@@ -663,11 +1125,11 @@ const item = sqliteTable('item', {
663
1125
  const schema = drizzleZeroConfig({ item })
664
1126
 
665
1127
  export type Item = Row<(typeof schema)['tables']['item']>
666
- `,
1128
+ `
667
1129
  )
668
1130
 
669
1131
  writeFileSync(
670
- join(testDir, 'models/item.ts'),
1132
+ join(testDir, 'item/mutations.ts'),
671
1133
  `
672
1134
  import { mutations } from 'on-zero'
673
1135
  import type { Item } from './types'
@@ -679,7 +1141,7 @@ export const mutate = mutations('item', {
679
1141
  await tx.mutate.item.update(props)
680
1142
  },
681
1143
  })
682
- `,
1144
+ `
683
1145
  )
684
1146
 
685
1147
  await generate({ dir: testDir, silent: true })
@@ -693,17 +1155,17 @@ export const mutate = mutations('item', {
693
1155
 
694
1156
  test('skips symbol-keyed properties when resolving imported mutation param types', async () => {
695
1157
  writeFileSync(
696
- join(testDir, 'models/types.ts'),
1158
+ join(testDir, 'item/types.ts'),
697
1159
  `
698
1160
  export type WeirdParams = {
699
1161
  id: string
700
1162
  [Symbol.iterator]?: () => Iterator<string>
701
1163
  }
702
- `,
1164
+ `
703
1165
  )
704
1166
 
705
1167
  writeFileSync(
706
- join(testDir, 'models/item.ts'),
1168
+ join(testDir, 'item/mutations.ts'),
707
1169
  `
708
1170
  import { mutations } from 'on-zero'
709
1171
  import type { WeirdParams } from './types'
@@ -713,7 +1175,7 @@ export const mutate = mutations({
713
1175
  await tx.mutate.item.delete({ id: params.id })
714
1176
  },
715
1177
  })
716
- `,
1178
+ `
717
1179
  )
718
1180
 
719
1181
  await generate({ dir: testDir, silent: true })
@@ -726,27 +1188,27 @@ export const mutate = mutations({
726
1188
 
727
1189
  test('resolves imported types in query params', async () => {
728
1190
  writeFileSync(
729
- join(testDir, 'models/post.ts'),
730
- `export const schema = table('post', { id: string() })`,
1191
+ join(testDir, 'post/mutations.ts'),
1192
+ `export const schema = table('post', { id: string() })`
731
1193
  )
732
1194
 
733
1195
  writeFileSync(
734
- join(testDir, 'queries/types.ts'),
1196
+ join(testDir, 'post/types.ts'),
735
1197
  `
736
1198
  export type PostFilter = {
737
1199
  authorId: string
738
1200
  published: boolean
739
1201
  }
740
- `,
1202
+ `
741
1203
  )
742
1204
 
743
1205
  writeFileSync(
744
- join(testDir, 'queries/post.ts'),
1206
+ join(testDir, 'post/queries.ts'),
745
1207
  `
746
1208
  import type { PostFilter } from './types'
747
1209
 
748
1210
  export const filteredPosts = (filter: PostFilter) => zero.query.post
749
- `,
1211
+ `
750
1212
  )
751
1213
 
752
1214
  const result = await generate({ dir: testDir, silent: true })
@@ -810,7 +1272,7 @@ describe('generateDrizzleSchemaFile', () => {
810
1272
  const executableSource = source
811
1273
  .replace(
812
1274
  "import { boolean, createSchema, json, number, relationships, string, table } from '@rocicorp/zero'",
813
- '',
1275
+ ''
814
1276
  )
815
1277
  .replace('export const schema =', 'globalThis.generatedSchema =')
816
1278
  const context: Record<string, unknown> = { ...zero }