on-zero 0.0.1

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 (371) hide show
  1. package/LICENSE +21 -0
  2. package/cli.cjs +3 -0
  3. package/dist/cjs/cli.cjs +405 -0
  4. package/dist/cjs/cli.js +397 -0
  5. package/dist/cjs/cli.js.map +6 -0
  6. package/dist/cjs/cli.native.js +505 -0
  7. package/dist/cjs/cli.native.js.map +1 -0
  8. package/dist/cjs/constants.cjs +28 -0
  9. package/dist/cjs/constants.js +22 -0
  10. package/dist/cjs/constants.js.map +6 -0
  11. package/dist/cjs/constants.native.js +31 -0
  12. package/dist/cjs/constants.native.js.map +1 -0
  13. package/dist/cjs/createPermissions.cjs +82 -0
  14. package/dist/cjs/createPermissions.js +77 -0
  15. package/dist/cjs/createPermissions.js.map +6 -0
  16. package/dist/cjs/createPermissions.native.js +107 -0
  17. package/dist/cjs/createPermissions.native.js.map +1 -0
  18. package/dist/cjs/createUseQuery.cjs +59 -0
  19. package/dist/cjs/createUseQuery.js +34 -0
  20. package/dist/cjs/createUseQuery.js.map +6 -0
  21. package/dist/cjs/createUseQuery.native.js +70 -0
  22. package/dist/cjs/createUseQuery.native.js.map +1 -0
  23. package/dist/cjs/createZeroClient.cjs +162 -0
  24. package/dist/cjs/createZeroClient.js +126 -0
  25. package/dist/cjs/createZeroClient.js.map +6 -0
  26. package/dist/cjs/createZeroClient.native.js +214 -0
  27. package/dist/cjs/createZeroClient.native.js.map +1 -0
  28. package/dist/cjs/createZeroServer.cjs +148 -0
  29. package/dist/cjs/createZeroServer.js +126 -0
  30. package/dist/cjs/createZeroServer.js.map +6 -0
  31. package/dist/cjs/createZeroServer.native.js +170 -0
  32. package/dist/cjs/createZeroServer.native.js.map +1 -0
  33. package/dist/cjs/helpers/batchQuery.cjs +49 -0
  34. package/dist/cjs/helpers/batchQuery.js +38 -0
  35. package/dist/cjs/helpers/batchQuery.js.map +6 -0
  36. package/dist/cjs/helpers/batchQuery.native.js +49 -0
  37. package/dist/cjs/helpers/batchQuery.native.js.map +1 -0
  38. package/dist/cjs/helpers/createMutators.cjs +90 -0
  39. package/dist/cjs/helpers/createMutators.js +85 -0
  40. package/dist/cjs/helpers/createMutators.js.map +6 -0
  41. package/dist/cjs/helpers/createMutators.native.js +132 -0
  42. package/dist/cjs/helpers/createMutators.native.js.map +1 -0
  43. package/dist/cjs/helpers/didRunPermissionCheck.cjs +30 -0
  44. package/dist/cjs/helpers/didRunPermissionCheck.js +26 -0
  45. package/dist/cjs/helpers/didRunPermissionCheck.js.map +6 -0
  46. package/dist/cjs/helpers/didRunPermissionCheck.native.js +39 -0
  47. package/dist/cjs/helpers/didRunPermissionCheck.native.js.map +1 -0
  48. package/dist/cjs/helpers/ensureLoggedIn.cjs +33 -0
  49. package/dist/cjs/helpers/ensureLoggedIn.js +25 -0
  50. package/dist/cjs/helpers/ensureLoggedIn.js.map +6 -0
  51. package/dist/cjs/helpers/ensureLoggedIn.native.js +36 -0
  52. package/dist/cjs/helpers/ensureLoggedIn.native.js.map +1 -0
  53. package/dist/cjs/helpers/getQueryOrMutatorAuthData.cjs +30 -0
  54. package/dist/cjs/helpers/getQueryOrMutatorAuthData.js +24 -0
  55. package/dist/cjs/helpers/getQueryOrMutatorAuthData.js.map +6 -0
  56. package/dist/cjs/helpers/getQueryOrMutatorAuthData.native.js +33 -0
  57. package/dist/cjs/helpers/getQueryOrMutatorAuthData.native.js.map +1 -0
  58. package/dist/cjs/helpers/mutatorContext.cjs +40 -0
  59. package/dist/cjs/helpers/mutatorContext.js +36 -0
  60. package/dist/cjs/helpers/mutatorContext.js.map +6 -0
  61. package/dist/cjs/helpers/mutatorContext.native.js +43 -0
  62. package/dist/cjs/helpers/mutatorContext.native.js.map +1 -0
  63. package/dist/cjs/helpers/prettyFormatZeroQuery.cjs +107 -0
  64. package/dist/cjs/helpers/prettyFormatZeroQuery.js +92 -0
  65. package/dist/cjs/helpers/prettyFormatZeroQuery.js.map +6 -0
  66. package/dist/cjs/helpers/prettyFormatZeroQuery.native.js +119 -0
  67. package/dist/cjs/helpers/prettyFormatZeroQuery.native.js.map +1 -0
  68. package/dist/cjs/helpers/useZeroDebug.cjs +68 -0
  69. package/dist/cjs/helpers/useZeroDebug.js +49 -0
  70. package/dist/cjs/helpers/useZeroDebug.js.map +6 -0
  71. package/dist/cjs/helpers/useZeroDebug.native.js +81 -0
  72. package/dist/cjs/helpers/useZeroDebug.native.js.map +1 -0
  73. package/dist/cjs/index.cjs +42 -0
  74. package/dist/cjs/index.js +35 -0
  75. package/dist/cjs/index.js.map +6 -0
  76. package/dist/cjs/index.native.js +45 -0
  77. package/dist/cjs/index.native.js.map +1 -0
  78. package/dist/cjs/mutations.cjs +51 -0
  79. package/dist/cjs/mutations.js +44 -0
  80. package/dist/cjs/mutations.js.map +6 -0
  81. package/dist/cjs/mutations.native.js +56 -0
  82. package/dist/cjs/mutations.native.js.map +1 -0
  83. package/dist/cjs/queryRegistry.cjs +33 -0
  84. package/dist/cjs/queryRegistry.js +28 -0
  85. package/dist/cjs/queryRegistry.js.map +6 -0
  86. package/dist/cjs/queryRegistry.native.js +36 -0
  87. package/dist/cjs/queryRegistry.native.js.map +1 -0
  88. package/dist/cjs/resolveQuery.cjs +41 -0
  89. package/dist/cjs/resolveQuery.js +40 -0
  90. package/dist/cjs/resolveQuery.js.map +6 -0
  91. package/dist/cjs/resolveQuery.native.js +46 -0
  92. package/dist/cjs/resolveQuery.native.js.map +1 -0
  93. package/dist/cjs/run.cjs +48 -0
  94. package/dist/cjs/run.js +37 -0
  95. package/dist/cjs/run.js.map +6 -0
  96. package/dist/cjs/run.native.js +52 -0
  97. package/dist/cjs/run.native.js.map +1 -0
  98. package/dist/cjs/server.cjs +18 -0
  99. package/dist/cjs/server.js +15 -0
  100. package/dist/cjs/server.js.map +6 -0
  101. package/dist/cjs/server.native.js +21 -0
  102. package/dist/cjs/server.native.js.map +1 -0
  103. package/dist/cjs/serverWhere.cjs +29 -0
  104. package/dist/cjs/serverWhere.js +24 -0
  105. package/dist/cjs/serverWhere.js.map +6 -0
  106. package/dist/cjs/serverWhere.native.js +32 -0
  107. package/dist/cjs/serverWhere.native.js.map +1 -0
  108. package/dist/cjs/state.cjs +49 -0
  109. package/dist/cjs/state.js +37 -0
  110. package/dist/cjs/state.js.map +6 -0
  111. package/dist/cjs/state.native.js +54 -0
  112. package/dist/cjs/state.native.js.map +1 -0
  113. package/dist/cjs/types.cjs +16 -0
  114. package/dist/cjs/types.js +14 -0
  115. package/dist/cjs/types.js.map +6 -0
  116. package/dist/cjs/types.native.js +19 -0
  117. package/dist/cjs/types.native.js.map +1 -0
  118. package/dist/cjs/where.cjs +41 -0
  119. package/dist/cjs/where.js +35 -0
  120. package/dist/cjs/where.js.map +6 -0
  121. package/dist/cjs/where.native.js +46 -0
  122. package/dist/cjs/where.native.js.map +1 -0
  123. package/dist/cjs/zeroRunner.cjs +34 -0
  124. package/dist/cjs/zeroRunner.js +32 -0
  125. package/dist/cjs/zeroRunner.js.map +6 -0
  126. package/dist/cjs/zeroRunner.native.js +37 -0
  127. package/dist/cjs/zeroRunner.native.js.map +1 -0
  128. package/dist/cjs/zql.cjs +31 -0
  129. package/dist/cjs/zql.js +26 -0
  130. package/dist/cjs/zql.js.map +6 -0
  131. package/dist/cjs/zql.native.js +35 -0
  132. package/dist/cjs/zql.native.js.map +1 -0
  133. package/dist/esm/cli.js +383 -0
  134. package/dist/esm/cli.js.map +6 -0
  135. package/dist/esm/cli.mjs +384 -0
  136. package/dist/esm/cli.mjs.map +1 -0
  137. package/dist/esm/cli.native.js +481 -0
  138. package/dist/esm/cli.native.js.map +1 -0
  139. package/dist/esm/constants.js +6 -0
  140. package/dist/esm/constants.js.map +6 -0
  141. package/dist/esm/constants.mjs +4 -0
  142. package/dist/esm/constants.mjs.map +1 -0
  143. package/dist/esm/constants.native.js +4 -0
  144. package/dist/esm/constants.native.js.map +1 -0
  145. package/dist/esm/createPermissions.js +66 -0
  146. package/dist/esm/createPermissions.js.map +6 -0
  147. package/dist/esm/createPermissions.mjs +59 -0
  148. package/dist/esm/createPermissions.mjs.map +1 -0
  149. package/dist/esm/createPermissions.native.js +81 -0
  150. package/dist/esm/createPermissions.native.js.map +1 -0
  151. package/dist/esm/createUseQuery.js +21 -0
  152. package/dist/esm/createUseQuery.js.map +6 -0
  153. package/dist/esm/createUseQuery.mjs +36 -0
  154. package/dist/esm/createUseQuery.mjs.map +1 -0
  155. package/dist/esm/createUseQuery.native.js +44 -0
  156. package/dist/esm/createUseQuery.native.js.map +1 -0
  157. package/dist/esm/createZeroClient.js +135 -0
  158. package/dist/esm/createZeroClient.js.map +6 -0
  159. package/dist/esm/createZeroClient.mjs +139 -0
  160. package/dist/esm/createZeroClient.mjs.map +1 -0
  161. package/dist/esm/createZeroClient.native.js +188 -0
  162. package/dist/esm/createZeroClient.native.js.map +1 -0
  163. package/dist/esm/createZeroServer.js +121 -0
  164. package/dist/esm/createZeroServer.js.map +6 -0
  165. package/dist/esm/createZeroServer.mjs +125 -0
  166. package/dist/esm/createZeroServer.mjs.map +1 -0
  167. package/dist/esm/createZeroServer.native.js +144 -0
  168. package/dist/esm/createZeroServer.native.js.map +1 -0
  169. package/dist/esm/helpers/batchQuery.js +22 -0
  170. package/dist/esm/helpers/batchQuery.js.map +6 -0
  171. package/dist/esm/helpers/batchQuery.mjs +26 -0
  172. package/dist/esm/helpers/batchQuery.mjs.map +1 -0
  173. package/dist/esm/helpers/batchQuery.native.js +23 -0
  174. package/dist/esm/helpers/batchQuery.native.js.map +1 -0
  175. package/dist/esm/helpers/createMutators.js +71 -0
  176. package/dist/esm/helpers/createMutators.js.map +6 -0
  177. package/dist/esm/helpers/createMutators.mjs +67 -0
  178. package/dist/esm/helpers/createMutators.mjs.map +1 -0
  179. package/dist/esm/helpers/createMutators.native.js +106 -0
  180. package/dist/esm/helpers/createMutators.native.js.map +1 -0
  181. package/dist/esm/helpers/didRunPermissionCheck.js +10 -0
  182. package/dist/esm/helpers/didRunPermissionCheck.js.map +6 -0
  183. package/dist/esm/helpers/didRunPermissionCheck.mjs +6 -0
  184. package/dist/esm/helpers/didRunPermissionCheck.mjs.map +1 -0
  185. package/dist/esm/helpers/didRunPermissionCheck.native.js +12 -0
  186. package/dist/esm/helpers/didRunPermissionCheck.native.js.map +1 -0
  187. package/dist/esm/helpers/ensureLoggedIn.js +10 -0
  188. package/dist/esm/helpers/ensureLoggedIn.js.map +6 -0
  189. package/dist/esm/helpers/ensureLoggedIn.mjs +10 -0
  190. package/dist/esm/helpers/ensureLoggedIn.mjs.map +1 -0
  191. package/dist/esm/helpers/ensureLoggedIn.native.js +10 -0
  192. package/dist/esm/helpers/ensureLoggedIn.native.js.map +1 -0
  193. package/dist/esm/helpers/getQueryOrMutatorAuthData.js +9 -0
  194. package/dist/esm/helpers/getQueryOrMutatorAuthData.js.map +6 -0
  195. package/dist/esm/helpers/getQueryOrMutatorAuthData.mjs +7 -0
  196. package/dist/esm/helpers/getQueryOrMutatorAuthData.mjs.map +1 -0
  197. package/dist/esm/helpers/getQueryOrMutatorAuthData.native.js +7 -0
  198. package/dist/esm/helpers/getQueryOrMutatorAuthData.native.js.map +1 -0
  199. package/dist/esm/helpers/mutatorContext.js +20 -0
  200. package/dist/esm/helpers/mutatorContext.js.map +6 -0
  201. package/dist/esm/helpers/mutatorContext.mjs +15 -0
  202. package/dist/esm/helpers/mutatorContext.mjs.map +1 -0
  203. package/dist/esm/helpers/mutatorContext.native.js +15 -0
  204. package/dist/esm/helpers/mutatorContext.native.js.map +1 -0
  205. package/dist/esm/helpers/prettyFormatZeroQuery.js +76 -0
  206. package/dist/esm/helpers/prettyFormatZeroQuery.js.map +6 -0
  207. package/dist/esm/helpers/prettyFormatZeroQuery.mjs +84 -0
  208. package/dist/esm/helpers/prettyFormatZeroQuery.mjs.map +1 -0
  209. package/dist/esm/helpers/prettyFormatZeroQuery.native.js +93 -0
  210. package/dist/esm/helpers/prettyFormatZeroQuery.native.js.map +1 -0
  211. package/dist/esm/helpers/useZeroDebug.js +35 -0
  212. package/dist/esm/helpers/useZeroDebug.js.map +6 -0
  213. package/dist/esm/helpers/useZeroDebug.mjs +45 -0
  214. package/dist/esm/helpers/useZeroDebug.mjs.map +1 -0
  215. package/dist/esm/helpers/useZeroDebug.native.js +55 -0
  216. package/dist/esm/helpers/useZeroDebug.native.js.map +1 -0
  217. package/dist/esm/index.js +20 -0
  218. package/dist/esm/index.js.map +6 -0
  219. package/dist/esm/index.mjs +17 -0
  220. package/dist/esm/index.mjs.map +1 -0
  221. package/dist/esm/index.native.js +17 -0
  222. package/dist/esm/index.native.js.map +1 -0
  223. package/dist/esm/mutations.js +28 -0
  224. package/dist/esm/mutations.js.map +6 -0
  225. package/dist/esm/mutations.mjs +28 -0
  226. package/dist/esm/mutations.mjs.map +1 -0
  227. package/dist/esm/mutations.native.js +30 -0
  228. package/dist/esm/mutations.native.js.map +1 -0
  229. package/dist/esm/queryRegistry.js +12 -0
  230. package/dist/esm/queryRegistry.js.map +6 -0
  231. package/dist/esm/queryRegistry.mjs +9 -0
  232. package/dist/esm/queryRegistry.mjs.map +1 -0
  233. package/dist/esm/queryRegistry.native.js +9 -0
  234. package/dist/esm/queryRegistry.native.js.map +1 -0
  235. package/dist/esm/resolveQuery.js +24 -0
  236. package/dist/esm/resolveQuery.js.map +6 -0
  237. package/dist/esm/resolveQuery.mjs +18 -0
  238. package/dist/esm/resolveQuery.mjs.map +1 -0
  239. package/dist/esm/resolveQuery.native.js +20 -0
  240. package/dist/esm/resolveQuery.native.js.map +1 -0
  241. package/dist/esm/run.js +22 -0
  242. package/dist/esm/run.js.map +6 -0
  243. package/dist/esm/run.mjs +24 -0
  244. package/dist/esm/run.mjs.map +1 -0
  245. package/dist/esm/run.native.js +25 -0
  246. package/dist/esm/run.native.js.map +1 -0
  247. package/dist/esm/server.js +2 -0
  248. package/dist/esm/server.js.map +6 -0
  249. package/dist/esm/server.mjs +2 -0
  250. package/dist/esm/server.mjs.map +1 -0
  251. package/dist/esm/server.native.js +2 -0
  252. package/dist/esm/server.native.js.map +1 -0
  253. package/dist/esm/serverWhere.js +8 -0
  254. package/dist/esm/serverWhere.js.map +6 -0
  255. package/dist/esm/serverWhere.mjs +6 -0
  256. package/dist/esm/serverWhere.mjs.map +1 -0
  257. package/dist/esm/serverWhere.native.js +6 -0
  258. package/dist/esm/serverWhere.native.js.map +1 -0
  259. package/dist/esm/state.js +21 -0
  260. package/dist/esm/state.js.map +6 -0
  261. package/dist/esm/state.mjs +22 -0
  262. package/dist/esm/state.mjs.map +1 -0
  263. package/dist/esm/state.native.js +24 -0
  264. package/dist/esm/state.native.js.map +1 -0
  265. package/dist/esm/types.js +1 -0
  266. package/dist/esm/types.js.map +6 -0
  267. package/dist/esm/types.mjs +2 -0
  268. package/dist/esm/types.mjs.map +1 -0
  269. package/dist/esm/types.native.js +2 -0
  270. package/dist/esm/types.native.js.map +1 -0
  271. package/dist/esm/where.js +20 -0
  272. package/dist/esm/where.js.map +6 -0
  273. package/dist/esm/where.mjs +17 -0
  274. package/dist/esm/where.mjs.map +1 -0
  275. package/dist/esm/where.native.js +19 -0
  276. package/dist/esm/where.native.js.map +1 -0
  277. package/dist/esm/zeroRunner.js +16 -0
  278. package/dist/esm/zeroRunner.js.map +6 -0
  279. package/dist/esm/zeroRunner.mjs +10 -0
  280. package/dist/esm/zeroRunner.mjs.map +1 -0
  281. package/dist/esm/zeroRunner.native.js +10 -0
  282. package/dist/esm/zeroRunner.native.js.map +1 -0
  283. package/dist/esm/zql.js +10 -0
  284. package/dist/esm/zql.js.map +6 -0
  285. package/dist/esm/zql.mjs +8 -0
  286. package/dist/esm/zql.mjs.map +1 -0
  287. package/dist/esm/zql.native.js +9 -0
  288. package/dist/esm/zql.native.js.map +1 -0
  289. package/package.json +98 -0
  290. package/readme.md +594 -0
  291. package/src/cli.ts +626 -0
  292. package/src/constants.native.ts +3 -0
  293. package/src/constants.ts +3 -0
  294. package/src/createPermissions.ts +131 -0
  295. package/src/createUseQuery.tsx +82 -0
  296. package/src/createZeroClient.tsx +301 -0
  297. package/src/createZeroServer.ts +226 -0
  298. package/src/helpers/batchQuery.ts +46 -0
  299. package/src/helpers/createMutators.ts +138 -0
  300. package/src/helpers/didRunPermissionCheck.ts +16 -0
  301. package/src/helpers/ensureLoggedIn.ts +11 -0
  302. package/src/helpers/getQueryOrMutatorAuthData.ts +12 -0
  303. package/src/helpers/mutatorContext.ts +25 -0
  304. package/src/helpers/prettyFormatZeroQuery.ts +167 -0
  305. package/src/helpers/useZeroDebug.ts +102 -0
  306. package/src/index.ts +18 -0
  307. package/src/mutations.ts +133 -0
  308. package/src/queryRegistry.ts +12 -0
  309. package/src/resolveQuery.ts +44 -0
  310. package/src/run.ts +62 -0
  311. package/src/server.ts +1 -0
  312. package/src/serverWhere.ts +21 -0
  313. package/src/state.ts +32 -0
  314. package/src/types.ts +136 -0
  315. package/src/where.ts +58 -0
  316. package/src/zeroRunner.ts +28 -0
  317. package/src/zql.ts +10 -0
  318. package/types/cli.d.ts +3 -0
  319. package/types/cli.d.ts.map +1 -0
  320. package/types/constants.d.ts +3 -0
  321. package/types/constants.d.ts.map +1 -0
  322. package/types/constants.native.d.ts +3 -0
  323. package/types/constants.native.d.ts.map +1 -0
  324. package/types/createPermissions.d.ts +10 -0
  325. package/types/createPermissions.d.ts.map +1 -0
  326. package/types/createUseQuery.d.ts +20 -0
  327. package/types/createUseQuery.d.ts.map +1 -0
  328. package/types/createZeroClient.d.ts +35 -0
  329. package/types/createZeroClient.d.ts.map +1 -0
  330. package/types/createZeroServer.d.ts +146 -0
  331. package/types/createZeroServer.d.ts.map +1 -0
  332. package/types/helpers/batchQuery.d.ts +7 -0
  333. package/types/helpers/batchQuery.d.ts.map +1 -0
  334. package/types/helpers/createMutators.d.ts +10 -0
  335. package/types/helpers/createMutators.d.ts.map +1 -0
  336. package/types/helpers/didRunPermissionCheck.d.ts +4 -0
  337. package/types/helpers/didRunPermissionCheck.d.ts.map +1 -0
  338. package/types/helpers/ensureLoggedIn.d.ts +3 -0
  339. package/types/helpers/ensureLoggedIn.d.ts.map +1 -0
  340. package/types/helpers/getQueryOrMutatorAuthData.d.ts +3 -0
  341. package/types/helpers/getQueryOrMutatorAuthData.d.ts.map +1 -0
  342. package/types/helpers/mutatorContext.d.ts +5 -0
  343. package/types/helpers/mutatorContext.d.ts.map +1 -0
  344. package/types/helpers/prettyFormatZeroQuery.d.ts +3 -0
  345. package/types/helpers/prettyFormatZeroQuery.d.ts.map +1 -0
  346. package/types/helpers/useZeroDebug.d.ts +3 -0
  347. package/types/helpers/useZeroDebug.d.ts.map +1 -0
  348. package/types/index.d.ts +17 -0
  349. package/types/index.d.ts.map +1 -0
  350. package/types/mutations.d.ts +20 -0
  351. package/types/mutations.d.ts.map +1 -0
  352. package/types/queryRegistry.d.ts +3 -0
  353. package/types/queryRegistry.d.ts.map +1 -0
  354. package/types/resolveQuery.d.ts +11 -0
  355. package/types/resolveQuery.d.ts.map +1 -0
  356. package/types/run.d.ts +7 -0
  357. package/types/run.d.ts.map +1 -0
  358. package/types/server.d.ts +2 -0
  359. package/types/server.d.ts.map +1 -0
  360. package/types/serverWhere.d.ts +5 -0
  361. package/types/serverWhere.d.ts.map +1 -0
  362. package/types/state.d.ts +8 -0
  363. package/types/state.d.ts.map +1 -0
  364. package/types/types.d.ts +78 -0
  365. package/types/types.d.ts.map +1 -0
  366. package/types/where.d.ts +6 -0
  367. package/types/where.d.ts.map +1 -0
  368. package/types/zeroRunner.d.ts +6 -0
  369. package/types/zeroRunner.d.ts.map +1 -0
  370. package/types/zql.d.ts +3 -0
  371. package/types/zql.d.ts.map +1 -0
package/src/cli.ts ADDED
@@ -0,0 +1,626 @@
1
+ #!/usr/bin/env node
2
+ import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs'
3
+ import { basename, resolve } from 'node:path'
4
+
5
+ import { ModelToValibot } from '@sinclair/typebox-codegen/model'
6
+ import { TypeScriptToModel } from '@sinclair/typebox-codegen/typescript'
7
+ import { defineCommand, runMain } from 'citty'
8
+ import * as ts from 'typescript'
9
+
10
+ /**
11
+ * Write file only if the content has changed.
12
+ * This prevents unnecessary rebuilds from file watchers.
13
+ */
14
+ function writeFileIfChanged(filePath: string, content: string): boolean {
15
+ try {
16
+ if (existsSync(filePath)) {
17
+ const existingContent = readFileSync(filePath, 'utf-8')
18
+ if (existingContent === content) {
19
+ return false // no change
20
+ }
21
+ }
22
+ } catch {
23
+ // if we can't read the file, proceed with writing
24
+ }
25
+
26
+ writeFileSync(filePath, content, 'utf-8')
27
+ return true // file was written
28
+ }
29
+
30
+ const generateQueries = defineCommand({
31
+ meta: {
32
+ name: 'generate-queries',
33
+ description: 'Generate server-side query validators from TypeScript query functions',
34
+ },
35
+ args: {
36
+ dir: {
37
+ type: 'positional',
38
+ description: 'Directory containing query files',
39
+ required: false,
40
+ default: '.',
41
+ },
42
+ },
43
+ async run({ args }) {
44
+ const dir = resolve(args.dir)
45
+
46
+ const { readdirSync } = await import('node:fs')
47
+
48
+ const files = readdirSync(dir).filter((f) => f.endsWith('.ts'))
49
+
50
+ const allQueries: Array<{ name: string; params: string; valibotCode: string }> = []
51
+
52
+ // process files in parallel
53
+ const results = await Promise.all(
54
+ files.map(async (file) => {
55
+ const filePath = resolve(dir, file)
56
+ const queries: typeof allQueries = []
57
+
58
+ try {
59
+ const content = readFileSync(filePath, 'utf-8')
60
+
61
+ const sourceFile = ts.createSourceFile(
62
+ filePath,
63
+ content,
64
+ ts.ScriptTarget.Latest,
65
+ true
66
+ )
67
+
68
+ ts.forEachChild(sourceFile, (node) => {
69
+ if (ts.isVariableStatement(node)) {
70
+ const exportModifier = node.modifiers?.find(
71
+ (m) => m.kind === ts.SyntaxKind.ExportKeyword
72
+ )
73
+ if (!exportModifier) return
74
+
75
+ const declaration = node.declarationList.declarations[0]
76
+ if (!declaration || !ts.isVariableDeclaration(declaration)) return
77
+
78
+ const name = declaration.name.getText(sourceFile)
79
+
80
+ if (
81
+ declaration.initializer &&
82
+ ts.isArrowFunction(declaration.initializer)
83
+ ) {
84
+ const params = declaration.initializer.parameters
85
+ let paramType = 'void'
86
+
87
+ if (params.length > 0) {
88
+ const param = params[0]!
89
+ paramType = param.type?.getText(sourceFile) || 'unknown'
90
+ }
91
+
92
+ try {
93
+ const typeString = `type QueryParams = ${paramType}`
94
+ const model = TypeScriptToModel.Generate(typeString)
95
+ const valibotCode = ModelToValibot.Generate(model)
96
+
97
+ queries.push({ name, params: paramType, valibotCode })
98
+ } catch (err) {
99
+ console.error(`✗ ${name}: ${err}`)
100
+ }
101
+ }
102
+ }
103
+ })
104
+ } catch (err) {
105
+ console.error(`Error processing ${file}:`, err)
106
+ }
107
+
108
+ return queries
109
+ })
110
+ )
111
+
112
+ allQueries.push(...results.flat())
113
+ console.info(`✓ ${allQueries.length} query validators`)
114
+ },
115
+ })
116
+
117
+ const generate = defineCommand({
118
+ meta: {
119
+ name: 'generate',
120
+ description: 'Generate models, types, tables, and query validators',
121
+ },
122
+ args: {
123
+ dir: {
124
+ type: 'positional',
125
+ description: 'Base directory (defaults to src/data)',
126
+ required: false,
127
+ default: 'src/data',
128
+ },
129
+ watch: {
130
+ type: 'boolean',
131
+ description: 'Watch for changes and regenerate',
132
+ required: false,
133
+ default: false,
134
+ },
135
+ after: {
136
+ type: 'string',
137
+ description: 'Command to run after generation completes',
138
+ required: false,
139
+ },
140
+ },
141
+ async run({ args }) {
142
+ const baseDir = resolve(args.dir)
143
+ const modelsDir = resolve(baseDir, 'models')
144
+ const generatedDir = resolve(baseDir, 'generated')
145
+ const queriesDir = resolve(baseDir, 'queries')
146
+
147
+ const runGenerate = async (options?: { silent?: boolean }) => {
148
+ const silent = options?.silent ?? false
149
+ // ensure generated dir exists
150
+ if (!existsSync(generatedDir)) {
151
+ mkdirSync(generatedDir, { recursive: true })
152
+ }
153
+
154
+ // read all model files and check for schemas in parallel
155
+ const allModelFiles = readdirSync(modelsDir)
156
+ .filter((f) => f.endsWith('.ts'))
157
+ .sort()
158
+
159
+ const schemaChecks = await Promise.all(
160
+ allModelFiles.map(async (f) => ({
161
+ file: f,
162
+ hasSchema: readFileSync(resolve(modelsDir, f), 'utf-8').includes(
163
+ 'export const schema = table('
164
+ ),
165
+ }))
166
+ )
167
+
168
+ const filesWithSchema = schemaChecks.filter((c) => c.hasSchema).map((c) => c.file)
169
+
170
+ // generate all files in parallel
171
+ const [modelsOutput, typesOutput, tablesOutput, readmeOutput] = await Promise.all([
172
+ Promise.resolve(generateModelsFile(allModelFiles)),
173
+ Promise.resolve(generateTypesFile(filesWithSchema)),
174
+ Promise.resolve(generateTablesFile(filesWithSchema)),
175
+ Promise.resolve(generateReadmeFile()),
176
+ ])
177
+
178
+ // write all generated files in parallel
179
+ const writeResults = await Promise.all([
180
+ Promise.resolve(
181
+ writeFileIfChanged(resolve(generatedDir, 'models.ts'), modelsOutput)
182
+ ),
183
+ Promise.resolve(
184
+ writeFileIfChanged(resolve(generatedDir, 'types.ts'), typesOutput)
185
+ ),
186
+ Promise.resolve(
187
+ writeFileIfChanged(resolve(generatedDir, 'tables.ts'), tablesOutput)
188
+ ),
189
+ Promise.resolve(
190
+ writeFileIfChanged(resolve(generatedDir, 'README.md'), readmeOutput)
191
+ ),
192
+ ])
193
+
194
+ const filesChanged = writeResults.filter(Boolean).length
195
+ if (filesChanged > 0 && !silent) {
196
+ console.info(` 📝 Updated ${filesChanged} file(s)`)
197
+ }
198
+
199
+ // generate synced queries
200
+ if (existsSync(queriesDir)) {
201
+ const queryFiles = readdirSync(queriesDir).filter((f) => f.endsWith('.ts'))
202
+
203
+ // process query files in parallel
204
+ const queryResults = await Promise.all(
205
+ queryFiles.map(async (file) => {
206
+ const filePath = resolve(queriesDir, file)
207
+ const fileBaseName = basename(file, '.ts')
208
+ const queries: Array<{
209
+ name: string
210
+ params: string
211
+ valibotCode: string
212
+ sourceFile: string
213
+ }> = []
214
+
215
+ try {
216
+ const content = readFileSync(filePath, 'utf-8')
217
+
218
+ const sourceFile = ts.createSourceFile(
219
+ filePath,
220
+ content,
221
+ ts.ScriptTarget.Latest,
222
+ true
223
+ )
224
+
225
+ ts.forEachChild(sourceFile, (node) => {
226
+ if (ts.isVariableStatement(node)) {
227
+ const exportModifier = node.modifiers?.find(
228
+ (m) => m.kind === ts.SyntaxKind.ExportKeyword
229
+ )
230
+ if (!exportModifier) return
231
+
232
+ const declaration = node.declarationList.declarations[0]
233
+ if (!declaration || !ts.isVariableDeclaration(declaration)) return
234
+
235
+ const name = declaration.name.getText(sourceFile)
236
+
237
+ // skip 'permission' exports
238
+ if (name === 'permission') return
239
+
240
+ if (
241
+ declaration.initializer &&
242
+ ts.isArrowFunction(declaration.initializer)
243
+ ) {
244
+ const params = declaration.initializer.parameters
245
+ let paramType = 'void'
246
+
247
+ if (params.length > 0) {
248
+ const param = params[0]!
249
+ paramType = param.type?.getText(sourceFile) || 'unknown'
250
+ }
251
+
252
+ try {
253
+ const typeString = `type QueryParams = ${paramType}`
254
+ const model = TypeScriptToModel.Generate(typeString)
255
+ const valibotCode = ModelToValibot.Generate(model)
256
+
257
+ queries.push({
258
+ name,
259
+ params: paramType,
260
+ valibotCode,
261
+ sourceFile: fileBaseName,
262
+ })
263
+ } catch (err) {
264
+ console.error(`✗ ${name}: ${err}`)
265
+ }
266
+ }
267
+ }
268
+ })
269
+ } catch (err) {
270
+ console.error(`Error processing ${file}:`, err)
271
+ }
272
+
273
+ return queries
274
+ })
275
+ )
276
+
277
+ const allQueries = queryResults.flat()
278
+ const groupedQueriesOutput = generateGroupedQueriesFile(allQueries)
279
+ const syncedQueriesOutput = generateSyncedQueriesFile(allQueries)
280
+
281
+ const groupedChanged = writeFileIfChanged(
282
+ resolve(generatedDir, 'groupedQueries.ts'),
283
+ groupedQueriesOutput
284
+ )
285
+ const syncedChanged = writeFileIfChanged(
286
+ resolve(generatedDir, 'syncedQueries.ts'),
287
+ syncedQueriesOutput
288
+ )
289
+
290
+ const queryFilesChanged = (groupedChanged ? 1 : 0) + (syncedChanged ? 1 : 0)
291
+ const totalFilesChanged = filesChanged + queryFilesChanged
292
+
293
+ if (totalFilesChanged > 0 && !silent) {
294
+ if (groupedChanged) {
295
+ console.info(` 📝 Updated groupedQueries.ts`)
296
+ }
297
+ if (syncedChanged) {
298
+ console.info(` 📝 Updated syncedQueries.ts`)
299
+ }
300
+ console.info(
301
+ `✓ ${allModelFiles.length} models (${filesWithSchema.length} schemas), ${allQueries.length} queries`
302
+ )
303
+ }
304
+
305
+ // run after command only if files changed and not silent
306
+ if (totalFilesChanged > 0 && !silent && args.after) {
307
+ try {
308
+ const { execSync } = await import('node:child_process')
309
+ execSync(args.after, { stdio: 'inherit' })
310
+ } catch (err) {
311
+ console.error(`Error running after command: ${err}`)
312
+ }
313
+ }
314
+ } else {
315
+ if (filesChanged > 0 && !silent) {
316
+ console.info(
317
+ `✓ ${allModelFiles.length} models (${filesWithSchema.length} schemas)`
318
+ )
319
+ }
320
+
321
+ // run after command only if files changed and not silent
322
+ if (filesChanged > 0 && !silent && args.after) {
323
+ try {
324
+ const { execSync } = await import('node:child_process')
325
+ execSync(args.after, { stdio: 'inherit' })
326
+ } catch (err) {
327
+ console.error(`Error running after command: ${err}`)
328
+ }
329
+ }
330
+ }
331
+ }
332
+
333
+ // run once (silent in watch mode for clean startup)
334
+ await runGenerate({ silent: args.watch })
335
+
336
+ // watch mode
337
+ if (args.watch) {
338
+ console.info('👀 watching...\n')
339
+ const chokidar = await import('chokidar')
340
+
341
+ let debounceTimer: ReturnType<typeof setTimeout> | null = null
342
+
343
+ const debouncedRegenerate = (path: string, event: string) => {
344
+ if (debounceTimer) {
345
+ clearTimeout(debounceTimer)
346
+ }
347
+
348
+ console.info(`\n${event} ${path}`)
349
+
350
+ debounceTimer = setTimeout(() => {
351
+ runGenerate()
352
+ }, 1000)
353
+ }
354
+
355
+ const watcher = chokidar.watch([modelsDir, queriesDir], {
356
+ persistent: true,
357
+ ignoreInitial: true,
358
+ })
359
+
360
+ watcher.on('change', (path) => debouncedRegenerate(path, '📝'))
361
+ watcher.on('add', (path) => debouncedRegenerate(path, '➕'))
362
+ watcher.on('unlink', (path) => debouncedRegenerate(path, '🗑️ '))
363
+
364
+ // keep process alive
365
+ await new Promise(() => {})
366
+ }
367
+ },
368
+ })
369
+
370
+ function generateModelsFile(modelFiles: string[]) {
371
+ const modelNames = modelFiles.map((f) => basename(f, '.ts')).sort()
372
+
373
+ // special case: user.ts should be imported as userPublic
374
+ const getImportName = (name: string) => (name === 'user' ? 'userPublic' : name)
375
+
376
+ // generate imports (sorted)
377
+ const imports = modelNames
378
+ .map((name) => {
379
+ const importName = getImportName(name)
380
+ return `import * as ${importName} from '../models/${name}'`
381
+ })
382
+ .join('\n')
383
+
384
+ // generate models object (sorted by import name)
385
+ const sortedByImportName = [...modelNames].sort((a, b) =>
386
+ getImportName(a).localeCompare(getImportName(b))
387
+ )
388
+ const modelsObj = `export const models = {\n${sortedByImportName.map((name) => ` ${getImportName(name)},`).join('\n')}\n}`
389
+
390
+ return `// auto-generated by: on-zero generate\n${imports}\n\n${modelsObj}\n`
391
+ }
392
+
393
+ function generateTypesFile(modelFiles: string[]) {
394
+ const modelNames = modelFiles.map((f) => basename(f, '.ts')).sort()
395
+
396
+ // special case: user.ts should reference userPublic in schema
397
+ const getSchemaName = (name: string) => (name === 'user' ? 'userPublic' : name)
398
+
399
+ // generate type exports using TableInsertRow and TableUpdateRow (sorted)
400
+ const typeExports = modelNames
401
+ .map((name) => {
402
+ const pascalName = name.charAt(0).toUpperCase() + name.slice(1)
403
+ const schemaName = getSchemaName(name)
404
+ return `export type ${pascalName} = TableInsertRow<typeof schema.${schemaName}>\nexport type ${pascalName}Update = TableUpdateRow<typeof schema.${schemaName}>`
405
+ })
406
+ .join('\n\n')
407
+
408
+ return `import type { TableInsertRow, TableUpdateRow } from 'on-zero'\nimport type * as schema from './tables'\n\n${typeExports}\n`
409
+ }
410
+
411
+ function generateTablesFile(modelFiles: string[]) {
412
+ const modelNames = modelFiles.map((f) => basename(f, '.ts')).sort()
413
+
414
+ // special case: user.ts should be exported as userPublic
415
+ const getExportName = (name: string) => (name === 'user' ? 'userPublic' : name)
416
+
417
+ // generate schema exports (sorted)
418
+ const exports = modelNames
419
+ .map((name) => `export { schema as ${getExportName(name)} } from '../models/${name}'`)
420
+ .join('\n')
421
+
422
+ return `// auto-generated by: on-zero generate\n// this is separate from models as otherwise you end up with circular types :/\n\n${exports}\n`
423
+ }
424
+
425
+ function generateGroupedQueriesFile(
426
+ queries: Array<{
427
+ name: string
428
+ params: string
429
+ valibotCode: string
430
+ sourceFile: string
431
+ }>
432
+ ) {
433
+ // get unique source files sorted
434
+ const sortedFiles = [...new Set(queries.map((q) => q.sourceFile))].sort()
435
+
436
+ // generate re-exports
437
+ const exports = sortedFiles
438
+ .map((file) => `export * as ${file} from '../queries/${file}'`)
439
+ .join('\n')
440
+
441
+ return `/**
442
+ * auto-generated by: on-zero generate
443
+ *
444
+ * grouped query re-exports for minification-safe query identity.
445
+ * this file re-exports all query modules - while this breaks tree-shaking,
446
+ * queries are typically small and few in number even in larger apps.
447
+ */
448
+ ${exports}
449
+ `
450
+ }
451
+
452
+ function generateSyncedQueriesFile(
453
+ queries: Array<{
454
+ name: string
455
+ params: string
456
+ valibotCode: string
457
+ sourceFile: string
458
+ }>
459
+ ) {
460
+ // group queries by source file
461
+ const queryByFile = new Map<string, typeof queries>()
462
+ for (const q of queries) {
463
+ if (!queryByFile.has(q.sourceFile)) {
464
+ queryByFile.set(q.sourceFile, [])
465
+ }
466
+ queryByFile.get(q.sourceFile)!.push(q)
467
+ }
468
+
469
+ // sort file names for consistent output
470
+ const sortedFiles = Array.from(queryByFile.keys()).sort()
471
+
472
+ const imports = `// auto-generated by: on-zero generate
473
+ // server-side query definitions with validators
474
+ import { defineQuery, defineQueries } from '@rocicorp/zero'
475
+ import * as v from 'valibot'
476
+ import * as Queries from './groupedQueries'
477
+ `
478
+
479
+ // generate grouped definitions by namespace
480
+ const namespaceDefs = sortedFiles
481
+ .map((file) => {
482
+ const fileQueries = queryByFile
483
+ .get(file)!
484
+ .sort((a, b) => a.name.localeCompare(b.name))
485
+
486
+ const queryDefs = fileQueries
487
+ .map((q) => {
488
+ // extract validator schema
489
+ const lines = q.valibotCode.split('\n').filter((l) => l.trim())
490
+ const schemaLineIndex = lines.findIndex((l) =>
491
+ l.startsWith('export const QueryParams')
492
+ )
493
+
494
+ let validatorDef = ''
495
+ if (schemaLineIndex !== -1) {
496
+ const schemaLines: string[] = []
497
+ let openBraces = 0
498
+ let started = false
499
+
500
+ for (let i = schemaLineIndex; i < lines.length; i++) {
501
+ const line = lines[i]!
502
+ const cleaned = started
503
+ ? line
504
+ : line.replace('export const QueryParams = ', '')
505
+ schemaLines.push(cleaned)
506
+ started = true
507
+
508
+ openBraces += (cleaned.match(/\{/g) || []).length
509
+ openBraces -= (cleaned.match(/\}/g) || []).length
510
+ openBraces += (cleaned.match(/\(/g) || []).length
511
+ openBraces -= (cleaned.match(/\)/g) || []).length
512
+
513
+ if (openBraces === 0 && schemaLines.length > 0) {
514
+ break
515
+ }
516
+ }
517
+ validatorDef = schemaLines.join('\n')
518
+ }
519
+
520
+ // for void queries, use the no-validator overload
521
+ if (q.params === 'void' || !validatorDef) {
522
+ return ` ${q.name}: defineQuery(() => Queries.${file}.${q.name}()),`
523
+ }
524
+
525
+ // indent the validator for proper formatting
526
+ const indentedValidator = validatorDef
527
+ .split('\n')
528
+ .map((line, i) => (i === 0 ? line : ` ${line}`))
529
+ .join('\n')
530
+
531
+ // defineQuery with validator and args
532
+ return ` ${q.name}: defineQuery(
533
+ ${indentedValidator},
534
+ ({ args }) => Queries.${file}.${q.name}(args)
535
+ ),`
536
+ })
537
+ .join('\n')
538
+
539
+ return `const ${file} = {\n${queryDefs}\n}`
540
+ })
541
+ .join('\n\n')
542
+
543
+ // build the defineQueries call with all namespaces
544
+ const queriesObject = sortedFiles.map((file) => ` ${file},`).join('\n')
545
+
546
+ return `${imports}
547
+ ${namespaceDefs}
548
+
549
+ export const queries = defineQueries({
550
+ ${queriesObject}
551
+ })
552
+ `
553
+ }
554
+
555
+ function generateReadmeFile() {
556
+ return `# generated
557
+
558
+ this folder is auto-generated by on-zero. do not edit files here directly.
559
+
560
+ ## what's generated
561
+
562
+ - \`models.ts\` - exports all models from ../models
563
+ - \`types.ts\` - typescript types derived from table schemas
564
+ - \`tables.ts\` - exports table schemas for type inference
565
+ - \`groupedQueries.ts\` - namespaced query re-exports for client setup
566
+ - \`syncedQueries.ts\` - namespaced syncedQuery wrappers for server setup
567
+
568
+ ## usage guidelines
569
+
570
+ **do not import generated files outside of the data folder.**
571
+
572
+ ### queries
573
+
574
+ write your queries as plain functions in \`../queries/\` and import them directly:
575
+
576
+ \`\`\`ts
577
+ // ✅ good - import from queries
578
+ import { channelMessages } from '~/data/queries/message'
579
+ \`\`\`
580
+
581
+ the generated query files are only used internally by zero client/server setup.
582
+
583
+ ### types
584
+
585
+ you can import types from this folder, but prefer re-exporting from \`../types.ts\`:
586
+
587
+ \`\`\`ts
588
+ // ❌ okay but not preferred
589
+ import type { Message } from '~/data/generated/types'
590
+
591
+ // ✅ better - re-export from types.ts
592
+ import type { Message } from '~/data/types'
593
+ \`\`\`
594
+
595
+ ## regeneration
596
+
597
+ files are regenerated when you run:
598
+
599
+ \`\`\`bash
600
+ bun on-zero generate
601
+ \`\`\`
602
+
603
+ or in watch mode:
604
+
605
+ \`\`\`bash
606
+ bun on-zero generate --watch
607
+ \`\`\`
608
+
609
+ ## more info
610
+
611
+ see the [on-zero readme](./node_modules/on-zero/README.md) for full documentation.
612
+ `
613
+ }
614
+
615
+ const main = defineCommand({
616
+ meta: {
617
+ name: 'on-zero',
618
+ description: 'on-zero CLI tools',
619
+ },
620
+ subCommands: {
621
+ generate: generate,
622
+ 'generate-queries': generateQueries,
623
+ },
624
+ })
625
+
626
+ runMain(main)
@@ -0,0 +1,3 @@
1
+
2
+ export const isServer = false
3
+ export const isBrowser = false
@@ -0,0 +1,3 @@
1
+
2
+ export const isServer = typeof window === 'undefined'
3
+ export const isBrowser = !isServer