over-zero 0.0.32 → 0.0.33

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 (254) hide show
  1. package/cli.cjs +3 -0
  2. package/dist/cjs/cli.cjs +228 -190
  3. package/dist/cjs/cli.js +60 -27
  4. package/dist/cjs/cli.js.map +1 -1
  5. package/dist/cjs/cli.native.js +277 -228
  6. package/dist/cjs/cli.native.js.map +1 -1
  7. package/dist/cjs/createPermissions.js.map +1 -1
  8. package/dist/cjs/createPermissions.native.js.map +1 -1
  9. package/dist/cjs/createZeroClient.cjs +6 -3
  10. package/dist/cjs/createZeroClient.js +11 -4
  11. package/dist/cjs/createZeroClient.js.map +1 -1
  12. package/dist/cjs/createZeroClient.native.js +40 -5
  13. package/dist/cjs/createZeroClient.native.js.map +1 -1
  14. package/dist/cjs/createZeroServer.cjs +3 -2
  15. package/dist/cjs/createZeroServer.js +2 -2
  16. package/dist/cjs/createZeroServer.js.map +1 -1
  17. package/dist/cjs/createZeroServer.native.js +4 -2
  18. package/dist/cjs/createZeroServer.native.js.map +1 -1
  19. package/dist/cjs/helpers/batchQuery.js.map +1 -1
  20. package/dist/cjs/helpers/batchQuery.native.js.map +1 -1
  21. package/dist/cjs/helpers/createMutators.js.map +1 -1
  22. package/dist/cjs/helpers/createMutators.native.js.map +1 -1
  23. package/dist/cjs/helpers/didRunPermissionCheck.js.map +1 -1
  24. package/dist/cjs/helpers/didRunPermissionCheck.native.js.map +1 -1
  25. package/dist/cjs/helpers/ensureLoggedIn.js.map +1 -1
  26. package/dist/cjs/helpers/ensureLoggedIn.native.js.map +1 -1
  27. package/dist/cjs/helpers/getQueryOrMutatorAuthData.js.map +1 -1
  28. package/dist/cjs/helpers/getQueryOrMutatorAuthData.native.js.map +1 -1
  29. package/dist/cjs/helpers/mutatorContext.js.map +1 -1
  30. package/dist/cjs/helpers/mutatorContext.native.js.map +1 -1
  31. package/dist/cjs/helpers/prettyFormatZeroQuery.js.map +1 -1
  32. package/dist/cjs/helpers/prettyFormatZeroQuery.native.js.map +1 -1
  33. package/dist/cjs/helpers/useZeroDebug.js.map +1 -1
  34. package/dist/cjs/helpers/useZeroDebug.native.js.map +1 -1
  35. package/dist/cjs/index.cjs +1 -0
  36. package/dist/cjs/index.js +1 -0
  37. package/dist/cjs/index.js.map +1 -1
  38. package/dist/cjs/index.native.js +1 -0
  39. package/dist/cjs/index.native.js.map +1 -1
  40. package/dist/cjs/mutations.js.map +1 -1
  41. package/dist/cjs/mutations.native.js.map +1 -1
  42. package/dist/cjs/{builder.cjs → queryRegistry.cjs} +12 -10
  43. package/dist/cjs/{queryBuilder.js → queryRegistry.js} +13 -11
  44. package/dist/cjs/queryRegistry.js.map +6 -0
  45. package/dist/cjs/{queryBuilder.native.js → queryRegistry.native.js} +13 -12
  46. package/dist/cjs/queryRegistry.native.js.map +1 -0
  47. package/dist/cjs/serverWhere.js.map +1 -1
  48. package/dist/cjs/serverWhere.native.js.map +1 -1
  49. package/dist/cjs/state.cjs +1 -4
  50. package/dist/cjs/state.js +1 -4
  51. package/dist/cjs/state.js.map +1 -1
  52. package/dist/cjs/state.native.js +1 -2
  53. package/dist/cjs/state.native.js.map +1 -1
  54. package/dist/cjs/where.js.map +1 -1
  55. package/dist/cjs/where.native.js.map +1 -1
  56. package/dist/cjs/zql.js.map +1 -1
  57. package/dist/cjs/zql.native.js.map +1 -1
  58. package/dist/esm/cli.js +61 -28
  59. package/dist/esm/cli.js.map +1 -1
  60. package/dist/esm/cli.mjs +227 -189
  61. package/dist/esm/cli.mjs.map +1 -1
  62. package/dist/esm/cli.native.js +276 -227
  63. package/dist/esm/cli.native.js.map +1 -1
  64. package/dist/esm/createPermissions.js.map +1 -1
  65. package/dist/esm/createPermissions.mjs.map +1 -1
  66. package/dist/esm/createPermissions.native.js.map +1 -1
  67. package/dist/esm/createZeroClient.js +11 -3
  68. package/dist/esm/createZeroClient.js.map +1 -1
  69. package/dist/esm/createZeroClient.mjs +6 -3
  70. package/dist/esm/createZeroClient.mjs.map +1 -1
  71. package/dist/esm/createZeroClient.native.js +40 -5
  72. package/dist/esm/createZeroClient.native.js.map +1 -1
  73. package/dist/esm/createZeroServer.js +2 -2
  74. package/dist/esm/createZeroServer.js.map +1 -1
  75. package/dist/esm/createZeroServer.mjs +3 -2
  76. package/dist/esm/createZeroServer.mjs.map +1 -1
  77. package/dist/esm/createZeroServer.native.js +4 -2
  78. package/dist/esm/createZeroServer.native.js.map +1 -1
  79. package/dist/esm/helpers/batchQuery.js.map +1 -1
  80. package/dist/esm/helpers/batchQuery.mjs.map +1 -1
  81. package/dist/esm/helpers/batchQuery.native.js.map +1 -1
  82. package/dist/esm/helpers/createMutators.js.map +1 -1
  83. package/dist/esm/helpers/createMutators.mjs.map +1 -1
  84. package/dist/esm/helpers/createMutators.native.js.map +1 -1
  85. package/dist/esm/helpers/didRunPermissionCheck.js.map +1 -1
  86. package/dist/esm/helpers/didRunPermissionCheck.mjs.map +1 -1
  87. package/dist/esm/helpers/didRunPermissionCheck.native.js.map +1 -1
  88. package/dist/esm/helpers/ensureLoggedIn.js.map +1 -1
  89. package/dist/esm/helpers/ensureLoggedIn.mjs.map +1 -1
  90. package/dist/esm/helpers/ensureLoggedIn.native.js.map +1 -1
  91. package/dist/esm/helpers/getQueryOrMutatorAuthData.js.map +1 -1
  92. package/dist/esm/helpers/getQueryOrMutatorAuthData.mjs.map +1 -1
  93. package/dist/esm/helpers/getQueryOrMutatorAuthData.native.js.map +1 -1
  94. package/dist/esm/helpers/mutatorContext.js.map +1 -1
  95. package/dist/esm/helpers/mutatorContext.mjs.map +1 -1
  96. package/dist/esm/helpers/mutatorContext.native.js.map +1 -1
  97. package/dist/esm/helpers/prettyFormatZeroQuery.js.map +1 -1
  98. package/dist/esm/helpers/prettyFormatZeroQuery.mjs.map +1 -1
  99. package/dist/esm/helpers/prettyFormatZeroQuery.native.js.map +1 -1
  100. package/dist/esm/helpers/useZeroDebug.js.map +1 -1
  101. package/dist/esm/helpers/useZeroDebug.mjs.map +1 -1
  102. package/dist/esm/helpers/useZeroDebug.native.js.map +1 -1
  103. package/dist/esm/index.js +1 -0
  104. package/dist/esm/index.js.map +1 -1
  105. package/dist/esm/index.mjs +1 -0
  106. package/dist/esm/index.mjs.map +1 -1
  107. package/dist/esm/index.native.js +1 -0
  108. package/dist/esm/index.native.js.map +1 -1
  109. package/dist/esm/mutations.js.map +1 -1
  110. package/dist/esm/mutations.mjs.map +1 -1
  111. package/dist/esm/mutations.native.js.map +1 -1
  112. package/dist/esm/queryRegistry.js +12 -0
  113. package/dist/esm/queryRegistry.js.map +6 -0
  114. package/dist/esm/queryRegistry.mjs +9 -0
  115. package/dist/esm/queryRegistry.mjs.map +1 -0
  116. package/dist/esm/queryRegistry.native.js +9 -0
  117. package/dist/esm/queryRegistry.native.js.map +1 -0
  118. package/dist/esm/serverWhere.js.map +1 -1
  119. package/dist/esm/serverWhere.mjs.map +1 -1
  120. package/dist/esm/serverWhere.native.js.map +1 -1
  121. package/dist/esm/state.js +1 -4
  122. package/dist/esm/state.js.map +1 -1
  123. package/dist/esm/state.mjs +1 -4
  124. package/dist/esm/state.mjs.map +1 -1
  125. package/dist/esm/state.native.js +1 -2
  126. package/dist/esm/state.native.js.map +1 -1
  127. package/dist/esm/where.js.map +1 -1
  128. package/dist/esm/where.mjs.map +1 -1
  129. package/dist/esm/where.native.js.map +1 -1
  130. package/dist/esm/zql.js.map +1 -1
  131. package/dist/esm/zql.mjs.map +1 -1
  132. package/dist/esm/zql.native.js.map +1 -1
  133. package/package.json +4 -4
  134. package/src/cli.ts +99 -79
  135. package/src/createPermissions.ts +8 -6
  136. package/src/createZeroClient.tsx +36 -15
  137. package/src/createZeroServer.ts +21 -15
  138. package/src/helpers/batchQuery.ts +2 -1
  139. package/src/helpers/createMutators.ts +3 -1
  140. package/src/helpers/didRunPermissionCheck.ts +1 -0
  141. package/src/helpers/ensureLoggedIn.ts +3 -1
  142. package/src/helpers/getQueryOrMutatorAuthData.ts +2 -1
  143. package/src/helpers/mutatorContext.ts +1 -0
  144. package/src/helpers/prettyFormatZeroQuery.ts +2 -1
  145. package/src/helpers/useZeroDebug.ts +3 -1
  146. package/src/index.ts +1 -0
  147. package/src/mutations.ts +2 -1
  148. package/src/queryRegistry.ts +12 -0
  149. package/src/serverWhere.ts +3 -2
  150. package/src/state.ts +2 -2
  151. package/src/types.ts +10 -9
  152. package/src/where.ts +3 -1
  153. package/src/zql.ts +1 -0
  154. package/types/createPermissions.d.ts +1 -1
  155. package/types/createPermissions.d.ts.map +1 -1
  156. package/types/createZeroClient.d.ts +5 -3
  157. package/types/createZeroClient.d.ts.map +1 -1
  158. package/types/createZeroServer.d.ts +4 -3
  159. package/types/createZeroServer.d.ts.map +1 -1
  160. package/types/helpers/batchQuery.d.ts.map +1 -1
  161. package/types/helpers/createMutators.d.ts.map +1 -1
  162. package/types/helpers/didRunPermissionCheck.d.ts.map +1 -1
  163. package/types/helpers/ensureLoggedIn.d.ts.map +1 -1
  164. package/types/helpers/getQueryOrMutatorAuthData.d.ts.map +1 -1
  165. package/types/helpers/mutatorContext.d.ts.map +1 -1
  166. package/types/helpers/prettyFormatZeroQuery.d.ts.map +1 -1
  167. package/types/helpers/useZeroDebug.d.ts.map +1 -1
  168. package/types/index.d.ts +1 -0
  169. package/types/index.d.ts.map +1 -1
  170. package/types/mutations.d.ts +1 -1
  171. package/types/mutations.d.ts.map +1 -1
  172. package/types/queryRegistry.d.ts +3 -0
  173. package/types/queryRegistry.d.ts.map +1 -0
  174. package/types/serverWhere.d.ts +1 -1
  175. package/types/serverWhere.d.ts.map +1 -1
  176. package/types/state.d.ts.map +1 -1
  177. package/types/types.d.ts.map +1 -1
  178. package/types/where.d.ts +1 -1
  179. package/types/where.d.ts.map +1 -1
  180. package/types/zql.d.ts.map +1 -1
  181. package/dist/cjs/builder.js +0 -26
  182. package/dist/cjs/builder.js.map +0 -6
  183. package/dist/cjs/builder.native.js +0 -35
  184. package/dist/cjs/builder.native.js.map +0 -1
  185. package/dist/cjs/helpers/context.cjs +0 -40
  186. package/dist/cjs/helpers/context.js +0 -36
  187. package/dist/cjs/helpers/context.js.map +0 -6
  188. package/dist/cjs/helpers/context.native.js +0 -43
  189. package/dist/cjs/helpers/context.native.js.map +0 -1
  190. package/dist/cjs/helpers/queryContext.cjs +0 -40
  191. package/dist/cjs/helpers/queryContext.js +0 -36
  192. package/dist/cjs/helpers/queryContext.js.map +0 -6
  193. package/dist/cjs/helpers/queryContext.native.js +0 -43
  194. package/dist/cjs/helpers/queryContext.native.js.map +0 -1
  195. package/dist/cjs/helpers/queryOrMutatorAuthData.cjs +0 -0
  196. package/dist/cjs/helpers/queryOrMutatorAuthData.js +0 -1
  197. package/dist/cjs/helpers/queryOrMutatorAuthData.js.map +0 -6
  198. package/dist/cjs/helpers/queryOrMutatorAuthData.native.js +0 -2
  199. package/dist/cjs/helpers/queryOrMutatorAuthData.native.js.map +0 -1
  200. package/dist/cjs/helpers/queryOrMutatorContext.cjs +0 -0
  201. package/dist/cjs/helpers/queryOrMutatorContext.js +0 -1
  202. package/dist/cjs/helpers/queryOrMutatorContext.js.map +0 -6
  203. package/dist/cjs/helpers/queryOrMutatorContext.native.js +0 -2
  204. package/dist/cjs/helpers/queryOrMutatorContext.native.js.map +0 -1
  205. package/dist/cjs/query.cjs +0 -34
  206. package/dist/cjs/query.js +0 -28
  207. package/dist/cjs/query.js.map +0 -6
  208. package/dist/cjs/query.native.js +0 -39
  209. package/dist/cjs/query.native.js.map +0 -1
  210. package/dist/cjs/queryBuilder.cjs +0 -31
  211. package/dist/cjs/queryBuilder.js.map +0 -6
  212. package/dist/cjs/queryBuilder.native.js.map +0 -1
  213. package/dist/esm/builder.js +0 -10
  214. package/dist/esm/builder.js.map +0 -6
  215. package/dist/esm/builder.mjs +0 -8
  216. package/dist/esm/builder.mjs.map +0 -1
  217. package/dist/esm/builder.native.js +0 -9
  218. package/dist/esm/builder.native.js.map +0 -1
  219. package/dist/esm/helpers/context.js +0 -20
  220. package/dist/esm/helpers/context.js.map +0 -6
  221. package/dist/esm/helpers/context.mjs +0 -15
  222. package/dist/esm/helpers/context.mjs.map +0 -1
  223. package/dist/esm/helpers/context.native.js +0 -15
  224. package/dist/esm/helpers/context.native.js.map +0 -1
  225. package/dist/esm/helpers/queryContext.js +0 -20
  226. package/dist/esm/helpers/queryContext.js.map +0 -6
  227. package/dist/esm/helpers/queryContext.mjs +0 -15
  228. package/dist/esm/helpers/queryContext.mjs.map +0 -1
  229. package/dist/esm/helpers/queryContext.native.js +0 -15
  230. package/dist/esm/helpers/queryContext.native.js.map +0 -1
  231. package/dist/esm/helpers/queryOrMutatorAuthData.js +0 -1
  232. package/dist/esm/helpers/queryOrMutatorAuthData.js.map +0 -6
  233. package/dist/esm/helpers/queryOrMutatorAuthData.mjs +0 -2
  234. package/dist/esm/helpers/queryOrMutatorAuthData.mjs.map +0 -1
  235. package/dist/esm/helpers/queryOrMutatorAuthData.native.js +0 -2
  236. package/dist/esm/helpers/queryOrMutatorAuthData.native.js.map +0 -1
  237. package/dist/esm/helpers/queryOrMutatorContext.js +0 -1
  238. package/dist/esm/helpers/queryOrMutatorContext.js.map +0 -6
  239. package/dist/esm/helpers/queryOrMutatorContext.mjs +0 -2
  240. package/dist/esm/helpers/queryOrMutatorContext.mjs.map +0 -1
  241. package/dist/esm/helpers/queryOrMutatorContext.native.js +0 -2
  242. package/dist/esm/helpers/queryOrMutatorContext.native.js.map +0 -1
  243. package/dist/esm/query.js +0 -13
  244. package/dist/esm/query.js.map +0 -6
  245. package/dist/esm/query.mjs +0 -11
  246. package/dist/esm/query.mjs.map +0 -1
  247. package/dist/esm/query.native.js +0 -13
  248. package/dist/esm/query.native.js.map +0 -1
  249. package/dist/esm/queryBuilder.js +0 -10
  250. package/dist/esm/queryBuilder.js.map +0 -6
  251. package/dist/esm/queryBuilder.mjs +0 -8
  252. package/dist/esm/queryBuilder.mjs.map +0 -1
  253. package/dist/esm/queryBuilder.native.js +0 -9
  254. package/dist/esm/queryBuilder.native.js.map +0 -1
package/src/cli.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env node
2
+ import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs'
3
+ import { basename, resolve } from 'node:path'
4
+
2
5
  import { ModelToValibot } from '@sinclair/typebox-codegen/model'
3
6
  import { TypeScriptToModel } from '@sinclair/typebox-codegen/typescript'
4
7
  import { defineCommand, runMain } from 'citty'
5
- import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs'
6
- import { basename, resolve } from 'node:path'
7
8
  import * as ts from 'typescript'
8
9
 
9
10
  /**
@@ -113,56 +114,6 @@ const generateQueries = defineCommand({
113
114
  },
114
115
  })
115
116
 
116
- function generateServerQueriesFile(
117
- queries: Array<{ name: string; params: string; valibotCode: string }>
118
- ) {
119
- const imports = `import * as v from 'valibot'\nimport * as queries from './queries'\n`
120
-
121
- const validators = queries
122
- .map((q) => {
123
- // extract just the schema definition (without import and type export)
124
- const lines = q.valibotCode.split('\n').filter((l) => l.trim())
125
- // find line starting with "export const QueryParams"
126
- const schemaLineIndex = lines.findIndex((l) =>
127
- l.startsWith('export const QueryParams')
128
- )
129
- if (schemaLineIndex === -1) {
130
- return `export const ${q.name}Schema = v.void()`
131
- }
132
-
133
- // get the full schema (might be multiline)
134
- const schemaLines: string[] = []
135
- let openBraces = 0
136
- let started = false
137
-
138
- for (let i = schemaLineIndex; i < lines.length; i++) {
139
- const line = lines[i]!
140
- const cleaned = started ? line : line.replace('export const QueryParams = ', '')
141
- schemaLines.push(cleaned)
142
- started = true
143
-
144
- // count braces to know when we're done
145
- openBraces += (cleaned.match(/\{/g) || []).length
146
- openBraces -= (cleaned.match(/\}/g) || []).length
147
- openBraces += (cleaned.match(/\(/g) || []).length
148
- openBraces -= (cleaned.match(/\)/g) || []).length
149
-
150
- // done when braces are balanced and we have at least one line
151
- if (openBraces === 0 && schemaLines.length > 0) {
152
- break
153
- }
154
- }
155
-
156
- const schemaDef = schemaLines.join('\n')
157
- return `export const ${q.name}Schema = ${schemaDef}`
158
- })
159
- .join('\n\n')
160
-
161
- const queryMap = `\nexport const queryValidators = {\n${queries.map((q) => ` ${q.name}: ${q.name}Schema,`).join('\n')}\n} as const\n`
162
-
163
- return imports + '\n' + validators + '\n' + queryMap
164
- }
165
-
166
117
  const generate = defineCommand({
167
118
  meta: {
168
119
  name: 'generate',
@@ -323,14 +274,23 @@ const generate = defineCommand({
323
274
  )
324
275
 
325
276
  const allQueries = queryResults.flat()
326
- const queriesOutput = generateQueriesFile(allQueries)
327
- const queriesChanged = writeFileIfChanged(
328
- resolve(generatedDir, 'queries.ts'),
329
- queriesOutput
277
+ const clientQueriesOutput = generateClientQueriesFile(allQueries)
278
+ const serverQueriesOutput = generateServerQueriesFile(allQueries)
279
+
280
+ const clientChanged = writeFileIfChanged(
281
+ resolve(generatedDir, 'queries.client.ts'),
282
+ clientQueriesOutput
283
+ )
284
+ const serverChanged = writeFileIfChanged(
285
+ resolve(generatedDir, 'queries.server.ts'),
286
+ serverQueriesOutput
330
287
  )
331
288
 
332
- if (queriesChanged) {
333
- console.info(` 📝 Updated queries.ts`)
289
+ if (clientChanged) {
290
+ console.info(` 📝 Updated queries.client.ts`)
291
+ }
292
+ if (serverChanged) {
293
+ console.info(` 📝 Updated queries.server.ts`)
334
294
  }
335
295
 
336
296
  console.info(
@@ -445,7 +405,7 @@ function generateTablesFile(modelFiles: string[]) {
445
405
  return `// auto-generated by: over-zero generate\n// this is separate from models as otherwise you end up with circular types :/\n\n${exports}\n`
446
406
  }
447
407
 
448
- function generateQueriesFile(
408
+ function generateClientQueriesFile(
449
409
  queries: Array<{
450
410
  name: string
451
411
  params: string
@@ -453,30 +413,68 @@ function generateQueriesFile(
453
413
  sourceFile: string
454
414
  }>
455
415
  ) {
456
- // sort queries alphabetically
457
- const sortedQueries = [...queries].sort((a, b) => a.name.localeCompare(b.name))
416
+ // get unique source files sorted
417
+ const sortedFiles = [...new Set(queries.map((q) => q.sourceFile))].sort()
418
+
419
+ // generate imports
420
+ const imports = sortedFiles
421
+ .map((file) => `import * as ${file}Queries from '../queries/${file}'`)
422
+ .join('\n')
423
+
424
+ // generate namespaced export object
425
+ const namespaces = sortedFiles.map((file) => ` ${file}: ${file}Queries,`).join('\n')
426
+
427
+ return `/**
428
+ * auto-generated by: over-zero generate
429
+ *
430
+ * client-side query references for minification-safe query identity.
431
+ * this file re-exports all query modules - while this breaks tree-shaking,
432
+ * queries are typically small and few in number even in larger apps.
433
+ */
434
+ ${imports}
458
435
 
459
- // Group queries by source file
436
+ export const clientQueries = {
437
+ ${namespaces}
438
+ }
439
+ `
440
+ }
441
+
442
+ function generateServerQueriesFile(
443
+ queries: Array<{
444
+ name: string
445
+ params: string
446
+ valibotCode: string
447
+ sourceFile: string
448
+ }>
449
+ ) {
450
+ // group queries by source file
460
451
  const queryByFile = new Map<string, typeof queries>()
461
- for (const q of sortedQueries) {
452
+ for (const q of queries) {
462
453
  if (!queryByFile.has(q.sourceFile)) {
463
454
  queryByFile.set(q.sourceFile, [])
464
455
  }
465
456
  queryByFile.get(q.sourceFile)!.push(q)
466
457
  }
467
458
 
468
- // Generate imports for each query file (sorted)
469
- const queryImports = Array.from(queryByFile.keys())
470
- .sort()
459
+ // sort file names for consistent output
460
+ const sortedFiles = Array.from(queryByFile.keys()).sort()
461
+
462
+ // generate imports
463
+ const queryImports = sortedFiles
471
464
  .map((file) => `import * as ${file}Queries from '../queries/${file}'`)
472
465
  .join('\n')
473
466
 
474
- const imports = `import * as v from 'valibot'
467
+ const imports = `// auto-generated by: over-zero generate
468
+ // server-side syncedQuery wrappers with validators
475
469
  import { syncedQuery } from '@rocicorp/zero'
470
+ import * as v from 'valibot'
476
471
  ${queryImports}
477
472
  `
478
473
 
479
- const syncedQueries = sortedQueries
474
+ // generate synced queries grouped by namespace
475
+ const sortedQueries = [...queries].sort((a, b) => a.name.localeCompare(b.name))
476
+
477
+ const syncedQueryDefs = sortedQueries
480
478
  .map((q) => {
481
479
  // extract validator schema
482
480
  const lines = q.valibotCode.split('\n').filter((l) => l.trim())
@@ -514,21 +512,43 @@ ${queryImports}
514
512
  ? 'v.parser(v.tuple([]))'
515
513
  : `v.parser(v.tuple([${validatorDef}]))`
516
514
 
515
+ // namespaced query name: file.queryName
516
+ const namespacedName = `${q.sourceFile}.${q.name}`
517
+
517
518
  // for void queries, no arg parameter
518
519
  const queryFn =
519
520
  validatorDef === 'v.void()'
520
521
  ? `() => {
521
- return ${q.sourceFile}Queries.${q.name}()
522
- }`
522
+ return ${q.sourceFile}Queries.${q.name}()
523
+ }`
523
524
  : `(arg) => {
524
- return ${q.sourceFile}Queries.${q.name}(arg)
525
- }`
525
+ return ${q.sourceFile}Queries.${q.name}(arg)
526
+ }`
526
527
 
527
- return `export const ${q.name} = syncedQuery('${q.name}', ${wrappedValidator}, ${queryFn})`
528
+ return `const ${q.name}Synced = syncedQuery('${namespacedName}', ${wrappedValidator}, ${queryFn})`
528
529
  })
529
530
  .join('\n\n')
530
531
 
531
- return imports + '\n' + syncedQueries + '\n'
532
+ // generate namespaced export object
533
+ const namespaces = sortedFiles
534
+ .map((file) => {
535
+ const fileQueries = queryByFile
536
+ .get(file)!
537
+ .sort((a, b) => a.name.localeCompare(b.name))
538
+ const queryEntries = fileQueries
539
+ .map((q) => ` ${q.name}: ${q.name}Synced,`)
540
+ .join('\n')
541
+ return ` ${file}: {\n${queryEntries}\n },`
542
+ })
543
+ .join('\n')
544
+
545
+ return `${imports}
546
+ ${syncedQueryDefs}
547
+
548
+ export const serverQueries = {
549
+ ${namespaces}
550
+ }
551
+ `
532
552
  }
533
553
 
534
554
  function generateReadmeFile() {
@@ -541,7 +561,8 @@ this folder is auto-generated by over-zero. do not edit files here directly.
541
561
  - \`models.ts\` - exports all models from ../models
542
562
  - \`types.ts\` - typescript types derived from table schemas
543
563
  - \`tables.ts\` - exports table schemas for type inference
544
- - \`queries.ts\` - synced query definitions with validators
564
+ - \`queries.client.ts\` - namespaced query references for client setup
565
+ - \`queries.server.ts\` - namespaced syncedQuery wrappers for server setup
545
566
 
546
567
  ## usage guidelines
547
568
 
@@ -549,16 +570,15 @@ this folder is auto-generated by over-zero. do not edit files here directly.
549
570
 
550
571
  ### queries
551
572
 
552
- don't import queries from this folder on the client. instead, import from \`../queries/\`:
573
+ write your queries as plain functions in \`../queries/\` and import them directly:
553
574
 
554
575
  \`\`\`ts
555
- // ❌ bad - don't import from generated
556
- import { channelMessages } from '~/data/generated/queries'
557
-
558
576
  // ✅ good - import from queries
559
577
  import { channelMessages } from '~/data/queries/message'
560
578
  \`\`\`
561
579
 
580
+ the generated query files are only used internally by zero client/server setup.
581
+
562
582
  ### types
563
583
 
564
584
  you can import types from this folder, but prefer re-exporting from \`../types.ts\`:
@@ -1,15 +1,17 @@
1
+ import { ensure, EnsureError } from '@vxrn/helpers'
2
+
3
+ import { setDidRunPermissionCheck } from './helpers/didRunPermissionCheck'
4
+ import { mutatorContext } from './helpers/mutatorContext'
5
+ import { prettyFormatZeroQuery } from './helpers/prettyFormatZeroQuery'
6
+ import { getWhereTableName } from './where'
7
+
8
+ import type { AuthData, Can, TableName, Transaction, Where } from './types'
1
9
  import type {
2
10
  Condition,
3
11
  ExpressionBuilder,
4
12
  Query,
5
13
  Schema as ZeroSchema,
6
14
  } from '@rocicorp/zero'
7
- import { ensure, EnsureError } from '@vxrn/helpers'
8
- import { setDidRunPermissionCheck } from './helpers/didRunPermissionCheck'
9
- import { mutatorContext } from './helpers/mutatorContext'
10
- import { prettyFormatZeroQuery } from './helpers/prettyFormatZeroQuery'
11
- import type { AuthData, Can, TableName, Transaction, Where } from './types'
12
- import { getWhereTableName } from './where'
13
15
 
14
16
  export function createPermissions<Schema extends ZeroSchema>({
15
17
  environment,
@@ -1,34 +1,55 @@
1
- import type {
2
- HumanReadable,
3
- Query,
4
- ReadonlyJSONValue,
5
- Row,
6
- SyncedQuery,
7
- Zero,
8
- ZeroOptions,
9
- Schema as ZeroSchema,
10
- } from '@rocicorp/zero'
11
1
  import { syncedQuery } from '@rocicorp/zero'
12
2
  import { useZero, ZeroProvider, useQuery as zeroUseQuery } from '@rocicorp/zero/react'
13
3
  import { createEmitter, mapObject } from '@vxrn/helpers'
14
4
  import { createContext, use, useMemo, type ReactNode } from 'react'
5
+
15
6
  import { createPermissions } from './createPermissions'
16
7
  import { createMutators } from './helpers/createMutators'
17
8
  import { prettyFormatZeroQuery } from './helpers/prettyFormatZeroQuery'
18
9
  import { useZeroDebug } from './helpers/useZeroDebug'
10
+ import { registerQuery, getQueryName } from './queryRegistry'
19
11
  import { setAuthData, setSchema } from './state'
12
+
20
13
  import type { AuthData, GenericModels, GetZeroMutators, ZeroEvent } from './types'
14
+ import type {
15
+ HumanReadable,
16
+ Query,
17
+ ReadonlyJSONValue,
18
+ Row,
19
+ SyncedQuery,
20
+ Zero,
21
+ ZeroOptions,
22
+ Schema as ZeroSchema,
23
+ } from '@rocicorp/zero'
24
+
25
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
+ export type ClientQueries = Record<string, Record<string, (...args: any[]) => any>>
21
27
 
22
28
  export function createZeroClient<
23
29
  Schema extends ZeroSchema,
24
30
  Models extends GenericModels,
25
- >({ schema, models }: { schema: Schema; models: Models }) {
31
+ >({
32
+ schema,
33
+ models,
34
+ clientQueries,
35
+ }: {
36
+ schema: Schema
37
+ models: Models
38
+ clientQueries: ClientQueries
39
+ }) {
26
40
  type ZeroMutators = GetZeroMutators<Models>
27
41
  type ZeroInstance = Zero<Schema, ZeroMutators>
28
42
  type TableName = keyof ZeroInstance['query']
29
43
 
30
44
  setSchema(schema)
31
45
 
46
+ // build query registry from namespaced clientQueries
47
+ for (const [namespace, queries] of Object.entries(clientQueries)) {
48
+ for (const [name, fn] of Object.entries(queries)) {
49
+ registerQuery(fn, `${namespace}.${name}`)
50
+ }
51
+ }
52
+
32
53
  const DisabledContext = createContext(false)
33
54
 
34
55
  const modelWritePermissions = mapObject(models, (val) => val.permissions) as {
@@ -170,7 +191,7 @@ export function createZeroClient<
170
191
  }
171
192
 
172
193
  const fn = queryOrFn
173
- const queryName = fn.name || 'anonymousQuery'
194
+ const queryName = getQueryName(fn) || fn.name || 'anonymousQuery'
174
195
 
175
196
  // Determine if this is Pattern 2 (with params) or Pattern 3 (no params)
176
197
  const hasParams =
@@ -200,7 +221,7 @@ export function createZeroClient<
200
221
  const out = zeroUseQuery(actualQuery, options)
201
222
 
202
223
  if (process.env.NODE_ENV === 'development') {
203
- // biome-ignore lint/correctness/useHookAtTopLevel: ok
224
+ // eslint-disable-next-line react-hooks/rules-of-hooks
204
225
  useZeroDebug(actualQuery, options, out)
205
226
  }
206
227
 
@@ -218,10 +239,10 @@ export function createZeroClient<
218
239
  ...props
219
240
  }: Omit<ZeroOptions<Schema, ZeroMutators>, 'schema' | 'mutators'> & {
220
241
  children: ReactNode
221
- authData?: AuthData
242
+ authData?: AuthData | null
222
243
  disable?: boolean
223
244
  }) => {
224
- const authData = authDataIn as AuthData
245
+ const authData = (authDataIn ?? null) as AuthData
225
246
 
226
247
  const mutators = useMemo(() => {
227
248
  setAuthData(authData)
@@ -1,19 +1,13 @@
1
- import type {
2
- HumanReadable,
3
- Query,
4
- ReadonlyJSONValue,
5
- SyncedQuery,
6
- Schema as ZeroSchema,
7
- } from '@rocicorp/zero'
8
- import type { TransactionProviderInput } from '@rocicorp/zero/pg'
9
1
  import { handleGetQueriesRequest, PushProcessor } from '@rocicorp/zero/pg'
10
2
  import { zeroNodePg } from '@rocicorp/zero/server/adapters/pg'
11
3
  import { assertString, randomId } from '@vxrn/helpers'
12
4
  import { Pool } from 'pg'
5
+
13
6
  import { createPermissions } from './createPermissions'
14
7
  import { createMutators } from './helpers/createMutators'
15
8
  import { isInZeroMutation, mutatorContext } from './helpers/mutatorContext'
16
9
  import { setAuthData, setSchema } from './state'
10
+
17
11
  import type {
18
12
  AsyncAction,
19
13
  AuthData,
@@ -21,21 +15,31 @@ import type {
21
15
  GetZeroMutators,
22
16
  Transaction,
23
17
  } from './types'
18
+ import type {
19
+ HumanReadable,
20
+ Query,
21
+ ReadonlyJSONValue,
22
+ SyncedQuery,
23
+ Schema as ZeroSchema,
24
+ } from '@rocicorp/zero'
25
+ import type { TransactionProviderInput } from '@rocicorp/zero/pg'
26
+
27
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
+ export type ServerQueries = Record<
29
+ string,
30
+ Record<string, SyncedQuery<any, any, any, any, any>>
31
+ >
24
32
 
25
33
  export function createZeroServer<
26
34
  Schema extends ZeroSchema,
27
35
  Models extends GenericModels,
28
36
  ServerActions extends Record<string, unknown>,
29
- Queries extends Record<string, SyncedQuery<any, any, any, any, any>> = Record<
30
- string,
31
- never
32
- >,
33
37
  >({
34
38
  createServerActions,
35
39
  database,
36
40
  schema,
37
41
  models,
38
- queries,
42
+ serverQueries,
39
43
  }: {
40
44
  /**
41
45
  * The DB connection string, same as ZERO_UPSTREAM_DB
@@ -44,7 +48,7 @@ export function createZeroServer<
44
48
  schema: Schema
45
49
  models: Models
46
50
  createServerActions: () => ServerActions
47
- queries?: Queries
51
+ serverQueries?: ServerQueries
48
52
  }) {
49
53
  setSchema(schema)
50
54
 
@@ -115,7 +119,9 @@ export function createZeroServer<
115
119
  request: Request
116
120
  }) => {
117
121
  function getQuery(name: string, args: readonly ReadonlyJSONValue[]) {
118
- const q = queries?.[name]
122
+ // name format: "namespace.queryName" (e.g. "post.allPosts")
123
+ const [namespace, queryName] = name.split('.')
124
+ const q = serverQueries?.[namespace!]?.[queryName!]
119
125
  if (!q) {
120
126
  throw new Error(`No such query: ${name}`)
121
127
  }
@@ -1,6 +1,7 @@
1
- import type { Query, Row } from '@rocicorp/zero'
2
1
  import { sleep } from '@vxrn/helpers'
3
2
 
3
+ import type { Query, Row } from '@rocicorp/zero'
4
+
4
5
  export async function batchQuery<Q extends Query<any, any, any>, Item extends Row<Q>>(
5
6
  q: Q,
6
7
  mapper: (items: Item[]) => Promise<void>,
@@ -1,4 +1,7 @@
1
1
  import { isClient, isServer, mapObject, time } from '@vxrn/helpers'
2
+
3
+ import { runWithContext } from './mutatorContext'
4
+
2
5
  import type {
3
6
  AuthData,
4
7
  Can,
@@ -7,7 +10,6 @@ import type {
7
10
  MutatorContext,
8
11
  Transaction,
9
12
  } from '../types'
10
- import { runWithContext } from './mutatorContext'
11
13
 
12
14
  export function createMutators<Models extends GenericModels>({
13
15
  environment,
@@ -1,4 +1,5 @@
1
1
  import { globalValue } from '@vxrn/helpers'
2
+
2
3
  import type { MutatorContext } from '../types'
3
4
 
4
5
  const PermissionCheckRan = globalValue(
@@ -1,7 +1,9 @@
1
1
  import { ensure } from '@vxrn/helpers'
2
- import type { AuthData } from '../types'
2
+
3
3
  import { mutatorContext } from './mutatorContext'
4
4
 
5
+ import type { AuthData } from '../types'
6
+
5
7
  export const ensureLoggedIn = (): AuthData => {
6
8
  const { authData } = mutatorContext()
7
9
  ensure(authData, 'logged in')
@@ -1,7 +1,8 @@
1
1
  import { getAuthData } from '../state'
2
- import type { AuthData } from '../types'
3
2
  import { isInZeroMutation, mutatorContext } from './mutatorContext'
4
3
 
4
+ import type { AuthData } from '../types'
5
+
5
6
  export function getQueryOrMutatorAuthData(): AuthData | null {
6
7
  if (isInZeroMutation()) {
7
8
  return mutatorContext().authData as AuthData
@@ -1,4 +1,5 @@
1
1
  import { createAsyncContext } from '@vxrn/helpers'
2
+
2
3
  import type { MutatorContext } from '../types'
3
4
 
4
5
  const asyncContext = createAsyncContext<MutatorContext>()
@@ -1,6 +1,7 @@
1
- import type { Query } from '@rocicorp/zero'
2
1
  import { ellipsis } from '@vxrn/helpers'
3
2
 
3
+ import type { Query } from '@rocicorp/zero'
4
+
4
5
  export const prettyFormatZeroQuery = (
5
6
  query: Query<any, any, any>,
6
7
  mode: 'full' | 'minimal' = 'full'
@@ -1,8 +1,10 @@
1
- import type { Query } from '@rocicorp/zero'
2
1
  import { getCurrentComponentStack } from '@vxrn/helpers'
3
2
  import { useEffect, useId } from 'react'
3
+
4
4
  import { prettyFormatZeroQuery } from './prettyFormatZeroQuery'
5
5
 
6
+ import type { Query } from '@rocicorp/zero'
7
+
6
8
  const activeQueries = new Map<string, number>()
7
9
 
8
10
  // AST change tracking
package/src/index.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from './createPermissions'
2
+ export * from './queryRegistry'
2
3
  export * from './helpers/batchQuery'
3
4
  export * from './helpers/createMutators'
4
5
  export * from './helpers/ensureLoggedIn'
package/src/mutations.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { TableBuilderWithColumns } from '@rocicorp/zero'
2
1
  import { getDidRunPermissionCheck } from './helpers/didRunPermissionCheck'
2
+
3
3
  import type {
4
4
  MutatorContext,
5
5
  TableInsertRow,
@@ -7,6 +7,7 @@ import type {
7
7
  TableUpdateRow,
8
8
  Where,
9
9
  } from './types'
10
+ import type { TableBuilderWithColumns } from '@rocicorp/zero'
10
11
 
11
12
  // two ways to use it:
12
13
  // - mutations({}) which doesn't add the "allowed" helper or add CRUD
@@ -0,0 +1,12 @@
1
+ // registry for query functions to their stable names
2
+ // this allows minification while preserving query identity
3
+
4
+ const queryNameRegistry = new WeakMap<Function, string>()
5
+
6
+ export function registerQuery(fn: Function, name: string) {
7
+ queryNameRegistry.set(fn, name)
8
+ }
9
+
10
+ export function getQueryName(fn: Function): string | undefined {
11
+ return queryNameRegistry.get(fn)
12
+ }
@@ -1,7 +1,8 @@
1
- import type { Condition } from '@rocicorp/zero'
2
- import type { TableName, Where } from './types'
3
1
  import { where } from './where'
4
2
 
3
+ import type { TableName, Where } from './types'
4
+ import type { Condition } from '@rocicorp/zero'
5
+
5
6
  export function serverWhere<Table extends TableName, Builder extends Where<Table>>(
6
7
  tableName: Table,
7
8
  builder: Builder
package/src/state.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { createBuilder, type Schema } from '@rocicorp/zero'
2
+
2
3
  import type { AuthData, QueryBuilder } from './types'
3
4
 
4
5
  let schema: Schema | null = null
@@ -23,8 +24,7 @@ export const setSchema = (_: Schema) => {
23
24
  }
24
25
 
25
26
  export const getAuthData = () => {
26
- if (authData === undefined) throw new Error(errMessage)
27
- return authData
27
+ return authData || null
28
28
  }
29
29
 
30
30
  export const setAuthData = (_: AuthData) => {
package/src/types.ts CHANGED
@@ -47,13 +47,15 @@ export type TableName = keyof Schema['tables'] extends string
47
47
 
48
48
  export type Transaction = ZeroTransaction<Schema>
49
49
 
50
- export type AuthData = FinalConfig['authData'] extends Record<string, unknown>
51
- ? FinalConfig['authData']
52
- : Record<string, unknown>
50
+ export type AuthData =
51
+ FinalConfig['authData'] extends Record<string, unknown>
52
+ ? FinalConfig['authData']
53
+ : Record<string, unknown>
53
54
 
54
- export type ServerActions = FinalConfig['serverActions'] extends Record<string, unknown>
55
- ? FinalConfig['serverActions']
56
- : Record<string, unknown>
55
+ export type ServerActions =
56
+ FinalConfig['serverActions'] extends Record<string, unknown>
57
+ ? FinalConfig['serverActions']
58
+ : Record<string, unknown>
57
59
 
58
60
  export type QueryBuilder = SchemaQuery<Schema>
59
61
 
@@ -112,9 +114,8 @@ export type AsyncAction = () => Promise<void>
112
114
 
113
115
  type GenericTable = TableBuilderWithColumns<any>
114
116
 
115
- type GetTableSchema<TS extends GenericTable> = TS extends TableBuilderWithColumns<infer S>
116
- ? S
117
- : never
117
+ type GetTableSchema<TS extends GenericTable> =
118
+ TS extends TableBuilderWithColumns<infer S> ? S : never
118
119
 
119
120
  // all non-optional keys required (but optional can be undefined)
120
121
  export type TableInsertRow<TS extends GenericTable> = NullToOptional<
package/src/where.ts CHANGED
@@ -1,7 +1,9 @@
1
- import type { Condition, ExpressionBuilder } from '@rocicorp/zero'
2
1
  import { globalValue, isClient } from '@vxrn/helpers'
2
+
3
3
  import { getQueryOrMutatorAuthData } from './helpers/getQueryOrMutatorAuthData'
4
+
4
5
  import type { TableName, Where } from './types'
6
+ import type { Condition, ExpressionBuilder } from '@rocicorp/zero'
5
7
 
6
8
  export function where<Table extends TableName, Builder extends Where<Table>>(
7
9
  tableName: Table,
package/src/zql.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { getZQL } from './state'
2
+
2
3
  import type { QueryBuilder } from './types'
3
4
 
4
5
  export const zql = new Proxy({} as QueryBuilder, {