on-zero 0.4.7 → 0.4.8
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.
- package/dist/cjs/createZeroClient.cjs +5 -1
- package/dist/cjs/createZeroClient.native.js +5 -1
- package/dist/cjs/createZeroClient.native.js.map +1 -1
- package/dist/cjs/generate-helpers.cjs +123 -19
- package/dist/cjs/generate-helpers.native.js +149 -25
- package/dist/cjs/generate-helpers.native.js.map +1 -1
- package/dist/cjs/generate-lite.native.js.map +1 -1
- package/dist/cjs/generate-lite.test.cjs +112 -0
- package/dist/cjs/generate-lite.test.native.js +112 -0
- package/dist/cjs/generate-lite.test.native.js.map +1 -1
- package/dist/cjs/generate.cjs +9 -1
- package/dist/cjs/generate.native.js +9 -1
- package/dist/cjs/generate.native.js.map +1 -1
- package/dist/cjs/generate.test.cjs +87 -0
- package/dist/cjs/generate.test.native.js +87 -0
- package/dist/cjs/generate.test.native.js.map +1 -1
- package/dist/esm/createZeroClient.mjs +5 -1
- package/dist/esm/createZeroClient.mjs.map +1 -1
- package/dist/esm/createZeroClient.native.js +5 -1
- package/dist/esm/createZeroClient.native.js.map +1 -1
- package/dist/esm/generate-helpers.mjs +123 -19
- package/dist/esm/generate-helpers.mjs.map +1 -1
- package/dist/esm/generate-helpers.native.js +149 -25
- package/dist/esm/generate-helpers.native.js.map +1 -1
- package/dist/esm/generate-lite.mjs.map +1 -1
- package/dist/esm/generate-lite.native.js.map +1 -1
- package/dist/esm/generate-lite.test.mjs +112 -0
- package/dist/esm/generate-lite.test.mjs.map +1 -1
- package/dist/esm/generate-lite.test.native.js +112 -0
- package/dist/esm/generate-lite.test.native.js.map +1 -1
- package/dist/esm/generate.mjs +9 -1
- package/dist/esm/generate.mjs.map +1 -1
- package/dist/esm/generate.native.js +9 -1
- package/dist/esm/generate.native.js.map +1 -1
- package/dist/esm/generate.test.mjs +87 -0
- package/dist/esm/generate.test.mjs.map +1 -1
- package/dist/esm/generate.test.native.js +87 -0
- package/dist/esm/generate.test.native.js.map +1 -1
- package/package.json +2 -2
- package/src/createZeroClient.tsx +6 -1
- package/src/generate-helpers.ts +141 -20
- package/src/generate-lite.test.ts +135 -0
- package/src/generate-lite.ts +1 -2
- package/src/generate.test.ts +96 -0
- package/src/generate.ts +11 -3
- package/types/createZeroClient.d.ts.map +1 -1
- package/types/generate-helpers.d.ts.map +1 -1
- package/types/generate-lite.d.ts.map +1 -1
- package/types/generate.d.ts.map +1 -1
|
@@ -230,6 +230,93 @@ export const mutate = mutations({
|
|
|
230
230
|
expect(content).toContain("reset");
|
|
231
231
|
expect(content).toContain("v.string()");
|
|
232
232
|
});
|
|
233
|
+
test("generates validators for string-model multiline mutation params", async function () {
|
|
234
|
+
writeFileSync(join(testDir, "models/agentEvent.ts"), `
|
|
235
|
+
import { mutations, serverWhere } from 'on-zero'
|
|
236
|
+
|
|
237
|
+
const perm = serverWhere('agentEvent', () => true)
|
|
238
|
+
|
|
239
|
+
export const mutate = mutations('agentEvent', perm, {
|
|
240
|
+
claimReviewLease: async (
|
|
241
|
+
{ tx },
|
|
242
|
+
props: {
|
|
243
|
+
id: string
|
|
244
|
+
projectId: string
|
|
245
|
+
agentId: string
|
|
246
|
+
userId: string
|
|
247
|
+
taskId: string
|
|
248
|
+
reviewKey: string
|
|
249
|
+
runnerId: string
|
|
250
|
+
createdAt: number
|
|
251
|
+
},
|
|
252
|
+
) => {
|
|
253
|
+
await tx.mutate.agentEvent.insert(props)
|
|
254
|
+
},
|
|
255
|
+
})
|
|
256
|
+
`);
|
|
257
|
+
await generate({
|
|
258
|
+
dir: testDir,
|
|
259
|
+
silent: true
|
|
260
|
+
});
|
|
261
|
+
var content = readFileSync(join(testDir, "generated/syncedMutations.ts"), "utf-8");
|
|
262
|
+
expect(content).toContain("claimReviewLease");
|
|
263
|
+
expect(content).toContain("projectId: v.string()");
|
|
264
|
+
expect(content).toContain("createdAt: v.number()");
|
|
265
|
+
expect(content).not.toContain("claimReviewLease: v.object({})");
|
|
266
|
+
});
|
|
267
|
+
test("generates validators for object intersections", async function () {
|
|
268
|
+
writeFileSync(join(testDir, "models/agent.ts"), `
|
|
269
|
+
import { mutations, serverWhere } from 'on-zero'
|
|
270
|
+
|
|
271
|
+
const perm = serverWhere('agent', () => true)
|
|
272
|
+
|
|
273
|
+
export const mutate = mutations('agent', perm, {
|
|
274
|
+
update: async (
|
|
275
|
+
{ tx },
|
|
276
|
+
props: {
|
|
277
|
+
id: string
|
|
278
|
+
} & {
|
|
279
|
+
status?: string
|
|
280
|
+
currentTaskId?: string
|
|
281
|
+
[key: string]: unknown
|
|
282
|
+
},
|
|
283
|
+
) => {
|
|
284
|
+
await tx.mutate.agent.update(props)
|
|
285
|
+
},
|
|
286
|
+
})
|
|
287
|
+
`);
|
|
288
|
+
await generate({
|
|
289
|
+
dir: testDir,
|
|
290
|
+
silent: true
|
|
291
|
+
});
|
|
292
|
+
var content = readFileSync(join(testDir, "generated/syncedMutations.ts"), "utf-8");
|
|
293
|
+
expect(content).toContain("update");
|
|
294
|
+
expect(content).toContain("id: v.string()");
|
|
295
|
+
expect(content).toContain("status: v.optional(v.string())");
|
|
296
|
+
expect(content).toContain("currentTaskId: v.optional(v.string())");
|
|
297
|
+
expect(content).not.toContain("update: v.object({})");
|
|
298
|
+
expect(content).not.toContain("[key");
|
|
299
|
+
});
|
|
300
|
+
test("uses v.unknown for untyped mutation payloads", async function () {
|
|
301
|
+
writeFileSync(join(testDir, "models/project.ts"), `
|
|
302
|
+
import { mutations, serverWhere } from 'on-zero'
|
|
303
|
+
|
|
304
|
+
const perm = serverWhere('project', () => true)
|
|
305
|
+
|
|
306
|
+
export const mutate = mutations('project', perm, {
|
|
307
|
+
insert: async ({ tx }, project) => {
|
|
308
|
+
await tx.mutate.project.insert(project)
|
|
309
|
+
},
|
|
310
|
+
})
|
|
311
|
+
`);
|
|
312
|
+
await generate({
|
|
313
|
+
dir: testDir,
|
|
314
|
+
silent: true
|
|
315
|
+
});
|
|
316
|
+
var content = readFileSync(join(testDir, "generated/syncedMutations.ts"), "utf-8");
|
|
317
|
+
expect(content).toContain("insert: v.unknown()");
|
|
318
|
+
expect(content).not.toContain("insert: v.void_()");
|
|
319
|
+
});
|
|
233
320
|
test("handles mutations with only context param (void)", async function () {
|
|
234
321
|
writeFileSync(join(testDir, "models/user.ts"), `
|
|
235
322
|
import { table, string } from 'on-zero'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["existsSync","mkdirSync","readFileSync","rmSync","writeFileSync","tmpdir","join","afterEach","beforeEach","describe","expect","test","generate","testDir","Date","now","recursive","force","result","dir","silent","modelCount","toBe","schemaCount","filesChanged","toBeGreaterThan","modelsContent","toContain","typesContent","tablesContent","queryCount","groupedContent","syncedContent","not","markerFile","after","first","second","mutationCount","content","toMatch"],"sources":["../../src/generate.test.ts"],"sourcesContent":[null],"mappings":"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
|
|
1
|
+
{"version":3,"names":["existsSync","mkdirSync","readFileSync","rmSync","writeFileSync","tmpdir","join","afterEach","beforeEach","describe","expect","test","generate","testDir","Date","now","recursive","force","result","dir","silent","modelCount","toBe","schemaCount","filesChanged","toBeGreaterThan","modelsContent","toContain","typesContent","tablesContent","queryCount","groupedContent","syncedContent","not","markerFile","after","first","second","mutationCount","content","toMatch"],"sources":["../../src/generate.test.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "on-zero",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.8",
|
|
4
4
|
"description": "A typed layer over @rocicorp/zero with queries, mutations, and permissions",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"source": "src/index.ts",
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
}
|
|
78
78
|
},
|
|
79
79
|
"dependencies": {
|
|
80
|
-
"@take-out/helpers": "0.4.
|
|
80
|
+
"@take-out/helpers": "0.4.8",
|
|
81
81
|
"chokidar": "^4.0.3",
|
|
82
82
|
"citty": "^0.1.6",
|
|
83
83
|
"valibot": "^1.1.0"
|
package/src/createZeroClient.tsx
CHANGED
|
@@ -37,6 +37,11 @@ export type GroupedQueries = Record<string, Record<string, (...args: any[]) => a
|
|
|
37
37
|
// - 'optimistic-allow': return true until server confirms
|
|
38
38
|
export type PermissionStrategy = 'optimistic' | 'optimistic-deny' | 'optimistic-allow'
|
|
39
39
|
|
|
40
|
+
function getZeroProxyValue(instance: object, key: PropertyKey) {
|
|
41
|
+
const value = Reflect.get(instance, key, instance)
|
|
42
|
+
return typeof value === 'function' ? value.bind(instance) : value
|
|
43
|
+
}
|
|
44
|
+
|
|
40
45
|
export function createZeroClient<
|
|
41
46
|
Schema extends ZeroSchema,
|
|
42
47
|
Models extends GenericModels,
|
|
@@ -175,7 +180,7 @@ export function createZeroClient<
|
|
|
175
180
|
`Zero instance not initialized. Ensure ZeroProvider is mounted before accessing 'zero'.`,
|
|
176
181
|
)
|
|
177
182
|
}
|
|
178
|
-
return
|
|
183
|
+
return getZeroProxyValue(latestZeroInstance, key)
|
|
179
184
|
},
|
|
180
185
|
})
|
|
181
186
|
|
package/src/generate-helpers.ts
CHANGED
|
@@ -17,7 +17,7 @@ export type ExtractedMutation = {
|
|
|
17
17
|
name: string
|
|
18
18
|
// 'void' | inline type string | unresolved reference
|
|
19
19
|
paramType: string
|
|
20
|
-
// generated valibot code, or ''
|
|
20
|
+
// generated valibot code, or '' when the payload is void/unknown
|
|
21
21
|
valibotCode: string
|
|
22
22
|
}
|
|
23
23
|
|
|
@@ -87,6 +87,93 @@ function splitTopLevelTypeUnion(type: string): string[] {
|
|
|
87
87
|
return parts.filter(Boolean)
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
function splitTopLevelTypeIntersection(type: string): string[] {
|
|
91
|
+
const parts: string[] = []
|
|
92
|
+
let depth = 0
|
|
93
|
+
let start = 0
|
|
94
|
+
let quote: string | null = null
|
|
95
|
+
|
|
96
|
+
for (let i = 0; i < type.length; i++) {
|
|
97
|
+
const char = type[i]
|
|
98
|
+
if (quote) {
|
|
99
|
+
if (char === '\\') {
|
|
100
|
+
i++
|
|
101
|
+
continue
|
|
102
|
+
}
|
|
103
|
+
if (char === quote) quote = null
|
|
104
|
+
continue
|
|
105
|
+
}
|
|
106
|
+
if (char === '"' || char === "'" || char === '`') {
|
|
107
|
+
quote = char
|
|
108
|
+
continue
|
|
109
|
+
}
|
|
110
|
+
if (char === '<' || char === '(' || char === '{' || char === '[') {
|
|
111
|
+
depth++
|
|
112
|
+
continue
|
|
113
|
+
}
|
|
114
|
+
if (char === '>' || char === ')' || char === '}' || char === ']') {
|
|
115
|
+
depth = Math.max(0, depth - 1)
|
|
116
|
+
continue
|
|
117
|
+
}
|
|
118
|
+
if (char === '&' && depth === 0 && type[i - 1] !== '&' && type[i + 1] !== '&') {
|
|
119
|
+
parts.push(type.slice(start, i).trim())
|
|
120
|
+
start = i + 1
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
parts.push(type.slice(start).trim())
|
|
125
|
+
return parts.filter(Boolean)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function stripTypeComments(type: string): string {
|
|
129
|
+
let out = ''
|
|
130
|
+
let quote: string | null = null
|
|
131
|
+
|
|
132
|
+
for (let i = 0; i < type.length; i++) {
|
|
133
|
+
const char = type[i]
|
|
134
|
+
const next = type[i + 1]
|
|
135
|
+
if (quote) {
|
|
136
|
+
out += char
|
|
137
|
+
if (char === '\\') {
|
|
138
|
+
if (next) {
|
|
139
|
+
out += next
|
|
140
|
+
i++
|
|
141
|
+
}
|
|
142
|
+
continue
|
|
143
|
+
}
|
|
144
|
+
if (char === quote) quote = null
|
|
145
|
+
continue
|
|
146
|
+
}
|
|
147
|
+
if (char === '"' || char === "'" || char === '`') {
|
|
148
|
+
quote = char
|
|
149
|
+
out += char
|
|
150
|
+
continue
|
|
151
|
+
}
|
|
152
|
+
if (char === '/' && next === '/') {
|
|
153
|
+
while (i < type.length && type[i] !== '\n') i++
|
|
154
|
+
if (i < type.length) out += '\n'
|
|
155
|
+
continue
|
|
156
|
+
}
|
|
157
|
+
if (char === '/' && next === '*') {
|
|
158
|
+
i += 2
|
|
159
|
+
while (i < type.length && !(type[i] === '*' && type[i + 1] === '/')) i++
|
|
160
|
+
i++
|
|
161
|
+
continue
|
|
162
|
+
}
|
|
163
|
+
out += char
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return out
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function nextNonWhitespace(type: string, start: number): string | undefined {
|
|
170
|
+
for (let i = start; i < type.length; i++) {
|
|
171
|
+
const char = type[i]
|
|
172
|
+
if (char && !/\s/.test(char)) return char
|
|
173
|
+
}
|
|
174
|
+
return undefined
|
|
175
|
+
}
|
|
176
|
+
|
|
90
177
|
function splitTopLevelObjectEntries(type: string): string[] {
|
|
91
178
|
const parts: string[] = []
|
|
92
179
|
let depth = 0
|
|
@@ -115,7 +202,14 @@ function splitTopLevelObjectEntries(type: string): string[] {
|
|
|
115
202
|
depth = Math.max(0, depth - 1)
|
|
116
203
|
continue
|
|
117
204
|
}
|
|
118
|
-
if (
|
|
205
|
+
if (
|
|
206
|
+
depth === 0 &&
|
|
207
|
+
(char === ';' ||
|
|
208
|
+
char === ',' ||
|
|
209
|
+
(char === '\n' &&
|
|
210
|
+
type.slice(start, i).includes(':') &&
|
|
211
|
+
!['|', '&'].includes(nextNonWhitespace(type, i + 1) ?? '')))
|
|
212
|
+
) {
|
|
119
213
|
parts.push(type.slice(start, i).trim())
|
|
120
214
|
start = i + 1
|
|
121
215
|
}
|
|
@@ -125,12 +219,35 @@ function splitTopLevelObjectEntries(type: string): string[] {
|
|
|
125
219
|
return parts.filter(Boolean)
|
|
126
220
|
}
|
|
127
221
|
|
|
222
|
+
function parseInlineObjectEntries(type: string): string[] | null | undefined {
|
|
223
|
+
if (!type.startsWith('{') || !type.endsWith('}')) return undefined
|
|
224
|
+
|
|
225
|
+
const inner = type.slice(1, -1).trim()
|
|
226
|
+
if (!inner) return []
|
|
227
|
+
|
|
228
|
+
const entries: string[] = []
|
|
229
|
+
for (const part of splitTopLevelObjectEntries(inner)) {
|
|
230
|
+
const trimmed = part.trim().replace(/[;,]\s*$/, '')
|
|
231
|
+
if (!trimmed || trimmed.startsWith('[')) continue
|
|
232
|
+
const match = trimmed.match(/^(?:readonly\s+)?(\w+)(\?)?:\s*(.+)$/s)
|
|
233
|
+
if (!match) continue
|
|
234
|
+
const [, name, opt, typeStr] = match
|
|
235
|
+
const parsed = parseTypeString(typeStr!.trim())
|
|
236
|
+
if (!parsed) return null // can't resolve inner type
|
|
237
|
+
let val = parsed
|
|
238
|
+
if (opt) val = `v.optional(${val})`
|
|
239
|
+
entries.push(`${formatObjectKey(name!)}: ${val}`)
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return entries
|
|
243
|
+
}
|
|
244
|
+
|
|
128
245
|
// simple string-based type parser for inline type annotations from source text.
|
|
129
246
|
// handles: primitives, inline objects { ... }, arrays, void/null/unknown.
|
|
130
247
|
// returns null for type references that cannot be resolved without a type
|
|
131
248
|
// checker (bare identifiers, generics, imported aliases).
|
|
132
249
|
export function parseTypeString(type: string): string | null {
|
|
133
|
-
type = type.trim()
|
|
250
|
+
type = stripTypeComments(type.trim()).trim()
|
|
134
251
|
|
|
135
252
|
const unionParts = splitTopLevelTypeUnion(type)
|
|
136
253
|
if (unionParts.length > 1) {
|
|
@@ -150,6 +267,18 @@ export function parseTypeString(type: string): string | null {
|
|
|
150
267
|
return val
|
|
151
268
|
}
|
|
152
269
|
|
|
270
|
+
const intersectionParts = splitTopLevelTypeIntersection(type)
|
|
271
|
+
if (intersectionParts.length > 1) {
|
|
272
|
+
const entries: string[] = []
|
|
273
|
+
for (const part of intersectionParts) {
|
|
274
|
+
const objectEntries = parseInlineObjectEntries(part)
|
|
275
|
+
if (!objectEntries) return null
|
|
276
|
+
entries.push(...objectEntries)
|
|
277
|
+
}
|
|
278
|
+
if (entries.length === 0) return 'v.object({})'
|
|
279
|
+
return `v.object({\n ${entries.join(',\n ')},\n })`
|
|
280
|
+
}
|
|
281
|
+
|
|
153
282
|
// primitives
|
|
154
283
|
if (type === 'string') return 'v.string()'
|
|
155
284
|
if (type === 'number') return 'v.number()'
|
|
@@ -159,25 +288,13 @@ export function parseTypeString(type: string): string | null {
|
|
|
159
288
|
if (type === 'any' || type === 'unknown') return 'v.unknown()'
|
|
160
289
|
|
|
161
290
|
// inline object: { key: type; ... }
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
const entries: string[] = []
|
|
166
|
-
for (const part of splitTopLevelObjectEntries(inner)) {
|
|
167
|
-
const trimmed = part.trim().replace(/[;,]\s*$/, '')
|
|
168
|
-
if (!trimmed) continue
|
|
169
|
-
const match = trimmed.match(/^(?:readonly\s+)?(\w+)(\?)?:\s*(.+)$/)
|
|
170
|
-
if (!match) continue
|
|
171
|
-
const [, name, opt, typeStr] = match
|
|
172
|
-
const parsed = parseTypeString(typeStr!.trim())
|
|
173
|
-
if (!parsed) return null // can't resolve inner type
|
|
174
|
-
let val = parsed
|
|
175
|
-
if (opt) val = `v.optional(${val})`
|
|
176
|
-
entries.push(`${formatObjectKey(name!)}: ${val}`)
|
|
177
|
-
}
|
|
291
|
+
const objectEntries = parseInlineObjectEntries(type)
|
|
292
|
+
if (objectEntries) {
|
|
293
|
+
const entries = objectEntries
|
|
178
294
|
if (entries.length === 0) return 'v.object({})'
|
|
179
295
|
return `v.object({\n ${entries.join(',\n ')},\n })`
|
|
180
296
|
}
|
|
297
|
+
if (objectEntries === null) return null
|
|
181
298
|
|
|
182
299
|
// array: T[]
|
|
183
300
|
if (type.endsWith('[]')) {
|
|
@@ -510,10 +627,14 @@ export function generateSyncedMutationsFile(modelMutations: ModelMutations[]): s
|
|
|
510
627
|
for (const mut of model.custom) {
|
|
511
628
|
if (model.hasCRUD && ['insert', 'update', 'delete', 'upsert'].includes(mut.name))
|
|
512
629
|
continue
|
|
513
|
-
if (mut.paramType === 'void'
|
|
630
|
+
if (mut.paramType === 'void') {
|
|
514
631
|
entries.push(` ${mut.name}: v.void_(),`)
|
|
515
632
|
continue
|
|
516
633
|
}
|
|
634
|
+
if (!mut.valibotCode) {
|
|
635
|
+
entries.push(` ${mut.name}: v.unknown(),`)
|
|
636
|
+
continue
|
|
637
|
+
}
|
|
517
638
|
entries.push(` ${mut.name}: ${extractValibotExpression(mut.valibotCode)},`)
|
|
518
639
|
}
|
|
519
640
|
|
|
@@ -99,6 +99,114 @@ describe('generateLite', () => {
|
|
|
99
99
|
expect(result.mutationCount).toBe(3)
|
|
100
100
|
})
|
|
101
101
|
|
|
102
|
+
test('parses newline-separated mutation object types', () => {
|
|
103
|
+
const files: Record<string, string> = {
|
|
104
|
+
[`${DIR}/models/agentEvent.ts`]: '// fake',
|
|
105
|
+
[`${DIR}/models/deployment.ts`]: '// fake',
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const fixtures: Record<string, LiteParsedFile> = {
|
|
109
|
+
[`${DIR}/models/agentEvent.ts`]: {
|
|
110
|
+
mutations: [
|
|
111
|
+
{
|
|
112
|
+
modelName: 'agentEvent',
|
|
113
|
+
handlers: [
|
|
114
|
+
{
|
|
115
|
+
name: 'claimReviewLease',
|
|
116
|
+
paramTypeText: `{
|
|
117
|
+
id: string
|
|
118
|
+
projectId: string
|
|
119
|
+
createdAt: number
|
|
120
|
+
}`,
|
|
121
|
+
},
|
|
122
|
+
],
|
|
123
|
+
schema: null,
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
queries: [],
|
|
127
|
+
},
|
|
128
|
+
[`${DIR}/models/deployment.ts`]: {
|
|
129
|
+
mutations: [
|
|
130
|
+
{
|
|
131
|
+
modelName: 'deployment',
|
|
132
|
+
handlers: [
|
|
133
|
+
{
|
|
134
|
+
name: 'deploy',
|
|
135
|
+
paramTypeText: `{
|
|
136
|
+
id: string
|
|
137
|
+
platform?: string // 'web' | 'ios'
|
|
138
|
+
buildTier?: string // 'dev' | 'testflight' | 'production'
|
|
139
|
+
}`,
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
schema: null,
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
queries: [],
|
|
146
|
+
},
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const result = generateLite({
|
|
150
|
+
files,
|
|
151
|
+
dir: DIR,
|
|
152
|
+
parse: makeParse(fixtures),
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
const synced = result.files['syncedMutations.ts']!
|
|
156
|
+
expect(synced).toContain('claimReviewLease:')
|
|
157
|
+
expect(synced).toContain('projectId: v.string()')
|
|
158
|
+
expect(synced).toContain('createdAt: v.number()')
|
|
159
|
+
expect(synced).toContain('deploy:')
|
|
160
|
+
expect(synced).toContain('platform: v.optional(v.string())')
|
|
161
|
+
expect(synced).toContain('buildTier: v.optional(v.string())')
|
|
162
|
+
expect(synced).not.toContain('claimReviewLease: v.object({})')
|
|
163
|
+
expect(synced).not.toContain('deploy: v.object({})')
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
test('parses object intersections and skips index signatures', () => {
|
|
167
|
+
const files: Record<string, string> = {
|
|
168
|
+
[`${DIR}/models/agent.ts`]: '// fake',
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const fixtures: Record<string, LiteParsedFile> = {
|
|
172
|
+
[`${DIR}/models/agent.ts`]: {
|
|
173
|
+
mutations: [
|
|
174
|
+
{
|
|
175
|
+
modelName: 'agent',
|
|
176
|
+
handlers: [
|
|
177
|
+
{
|
|
178
|
+
name: 'update',
|
|
179
|
+
paramTypeText: `{
|
|
180
|
+
id: string
|
|
181
|
+
} & {
|
|
182
|
+
status?: string
|
|
183
|
+
currentTaskId?: string
|
|
184
|
+
[key: string]: unknown
|
|
185
|
+
}`,
|
|
186
|
+
},
|
|
187
|
+
],
|
|
188
|
+
schema: null,
|
|
189
|
+
},
|
|
190
|
+
],
|
|
191
|
+
queries: [],
|
|
192
|
+
},
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const result = generateLite({
|
|
196
|
+
files,
|
|
197
|
+
dir: DIR,
|
|
198
|
+
parse: makeParse(fixtures),
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
const synced = result.files['syncedMutations.ts']!
|
|
202
|
+
expect(synced).toContain('update:')
|
|
203
|
+
expect(synced).toContain('id: v.string()')
|
|
204
|
+
expect(synced).toContain('status: v.optional(v.string())')
|
|
205
|
+
expect(synced).toContain('currentTaskId: v.optional(v.string())')
|
|
206
|
+
expect(synced).not.toContain('[key')
|
|
207
|
+
expect(synced).not.toContain('update: v.object({})')
|
|
208
|
+
})
|
|
209
|
+
|
|
102
210
|
test('falls back to v.unknown() for type references', () => {
|
|
103
211
|
const files: Record<string, string> = {
|
|
104
212
|
[`${DIR}/models/post.ts`]: '// fake',
|
|
@@ -141,6 +249,33 @@ describe('generateLite', () => {
|
|
|
141
249
|
expect(synced).toContain('publish: v.string()')
|
|
142
250
|
})
|
|
143
251
|
|
|
252
|
+
test('uses v.unknown() for explicitly unknown mutation params', () => {
|
|
253
|
+
const files: Record<string, string> = {
|
|
254
|
+
[`${DIR}/models/project.ts`]: '// fake',
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const fixtures: Record<string, LiteParsedFile> = {
|
|
258
|
+
[`${DIR}/models/project.ts`]: {
|
|
259
|
+
mutations: [
|
|
260
|
+
{
|
|
261
|
+
modelName: 'project',
|
|
262
|
+
handlers: [{ name: 'insert', paramTypeText: 'unknown' }],
|
|
263
|
+
schema: null,
|
|
264
|
+
},
|
|
265
|
+
],
|
|
266
|
+
queries: [],
|
|
267
|
+
},
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const result = generateLite({
|
|
271
|
+
files,
|
|
272
|
+
dir: DIR,
|
|
273
|
+
parse: makeParse(fixtures),
|
|
274
|
+
})
|
|
275
|
+
|
|
276
|
+
expect(result.files['syncedMutations.ts']!).toContain('insert: v.unknown()')
|
|
277
|
+
})
|
|
278
|
+
|
|
144
279
|
test('emits query files with v.unknown() fallback for references', () => {
|
|
145
280
|
const files: Record<string, string> = {
|
|
146
281
|
[`${DIR}/models/post.ts`]: '// fake',
|
package/src/generate-lite.ts
CHANGED
|
@@ -209,8 +209,7 @@ export function generateLite(opts: LiteGenerateOptions): LiteGenerateResult {
|
|
|
209
209
|
|
|
210
210
|
const paramType = h.paramTypeText.trim()
|
|
211
211
|
|
|
212
|
-
// unknown explicitly →
|
|
213
|
-
// matching the existing generator's behavior for 'unknown')
|
|
212
|
+
// unknown explicitly → permissive validator
|
|
214
213
|
if (paramType === 'unknown') {
|
|
215
214
|
return { name: h.name, paramType: 'unknown', valibotCode: '' }
|
|
216
215
|
}
|
package/src/generate.test.ts
CHANGED
|
@@ -311,6 +311,102 @@ export const mutate = mutations({
|
|
|
311
311
|
expect(content).toContain('v.string()')
|
|
312
312
|
})
|
|
313
313
|
|
|
314
|
+
test('generates validators for string-model multiline mutation params', async () => {
|
|
315
|
+
writeFileSync(
|
|
316
|
+
join(testDir, 'models/agentEvent.ts'),
|
|
317
|
+
`
|
|
318
|
+
import { mutations, serverWhere } from 'on-zero'
|
|
319
|
+
|
|
320
|
+
const perm = serverWhere('agentEvent', () => true)
|
|
321
|
+
|
|
322
|
+
export const mutate = mutations('agentEvent', perm, {
|
|
323
|
+
claimReviewLease: async (
|
|
324
|
+
{ tx },
|
|
325
|
+
props: {
|
|
326
|
+
id: string
|
|
327
|
+
projectId: string
|
|
328
|
+
agentId: string
|
|
329
|
+
userId: string
|
|
330
|
+
taskId: string
|
|
331
|
+
reviewKey: string
|
|
332
|
+
runnerId: string
|
|
333
|
+
createdAt: number
|
|
334
|
+
},
|
|
335
|
+
) => {
|
|
336
|
+
await tx.mutate.agentEvent.insert(props)
|
|
337
|
+
},
|
|
338
|
+
})
|
|
339
|
+
`,
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
await generate({ dir: testDir, silent: true })
|
|
343
|
+
|
|
344
|
+
const content = readFileSync(join(testDir, 'generated/syncedMutations.ts'), 'utf-8')
|
|
345
|
+
expect(content).toContain('claimReviewLease')
|
|
346
|
+
expect(content).toContain('projectId: v.string()')
|
|
347
|
+
expect(content).toContain('createdAt: v.number()')
|
|
348
|
+
expect(content).not.toContain('claimReviewLease: v.object({})')
|
|
349
|
+
})
|
|
350
|
+
|
|
351
|
+
test('generates validators for object intersections', async () => {
|
|
352
|
+
writeFileSync(
|
|
353
|
+
join(testDir, 'models/agent.ts'),
|
|
354
|
+
`
|
|
355
|
+
import { mutations, serverWhere } from 'on-zero'
|
|
356
|
+
|
|
357
|
+
const perm = serverWhere('agent', () => true)
|
|
358
|
+
|
|
359
|
+
export const mutate = mutations('agent', perm, {
|
|
360
|
+
update: async (
|
|
361
|
+
{ tx },
|
|
362
|
+
props: {
|
|
363
|
+
id: string
|
|
364
|
+
} & {
|
|
365
|
+
status?: string
|
|
366
|
+
currentTaskId?: string
|
|
367
|
+
[key: string]: unknown
|
|
368
|
+
},
|
|
369
|
+
) => {
|
|
370
|
+
await tx.mutate.agent.update(props)
|
|
371
|
+
},
|
|
372
|
+
})
|
|
373
|
+
`,
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
await generate({ dir: testDir, silent: true })
|
|
377
|
+
|
|
378
|
+
const content = readFileSync(join(testDir, 'generated/syncedMutations.ts'), 'utf-8')
|
|
379
|
+
expect(content).toContain('update')
|
|
380
|
+
expect(content).toContain('id: v.string()')
|
|
381
|
+
expect(content).toContain('status: v.optional(v.string())')
|
|
382
|
+
expect(content).toContain('currentTaskId: v.optional(v.string())')
|
|
383
|
+
expect(content).not.toContain('update: v.object({})')
|
|
384
|
+
expect(content).not.toContain('[key')
|
|
385
|
+
})
|
|
386
|
+
|
|
387
|
+
test('uses v.unknown for untyped mutation payloads', async () => {
|
|
388
|
+
writeFileSync(
|
|
389
|
+
join(testDir, 'models/project.ts'),
|
|
390
|
+
`
|
|
391
|
+
import { mutations, serverWhere } from 'on-zero'
|
|
392
|
+
|
|
393
|
+
const perm = serverWhere('project', () => true)
|
|
394
|
+
|
|
395
|
+
export const mutate = mutations('project', perm, {
|
|
396
|
+
insert: async ({ tx }, project) => {
|
|
397
|
+
await tx.mutate.project.insert(project)
|
|
398
|
+
},
|
|
399
|
+
})
|
|
400
|
+
`,
|
|
401
|
+
)
|
|
402
|
+
|
|
403
|
+
await generate({ dir: testDir, silent: true })
|
|
404
|
+
|
|
405
|
+
const content = readFileSync(join(testDir, 'generated/syncedMutations.ts'), 'utf-8')
|
|
406
|
+
expect(content).toContain('insert: v.unknown()')
|
|
407
|
+
expect(content).not.toContain('insert: v.void_()')
|
|
408
|
+
})
|
|
409
|
+
|
|
314
410
|
test('handles mutations with only context param (void)', async () => {
|
|
315
411
|
writeFileSync(
|
|
316
412
|
join(testDir, 'models/user.ts'),
|
package/src/generate.ts
CHANGED
|
@@ -274,13 +274,21 @@ function extractMutationsFromModel(
|
|
|
274
274
|
|
|
275
275
|
// determine overload
|
|
276
276
|
// 1-arg: mutations({ ... })
|
|
277
|
-
//
|
|
278
|
-
//
|
|
279
|
-
const
|
|
277
|
+
// schema model: mutations(schema, perm) / mutations(schema, perm, { ... })
|
|
278
|
+
// named model: mutations('name', handlers) / mutations('name', perm, { ... })
|
|
279
|
+
const firstArg = args[0]
|
|
280
|
+
const hasNamedModel = Boolean(firstArg && ts.isStringLiteralLike(firstArg))
|
|
281
|
+
const hasCRUD = args.length >= 2 && !hasNamedModel
|
|
280
282
|
let handlersArg: import('typescript').ObjectLiteralExpression | null = null
|
|
281
283
|
|
|
282
284
|
if (args.length === 1 && ts.isObjectLiteralExpression(args[0]!)) {
|
|
283
285
|
handlersArg = args[0] as import('typescript').ObjectLiteralExpression
|
|
286
|
+
} else if (hasNamedModel) {
|
|
287
|
+
if (args.length >= 3 && ts.isObjectLiteralExpression(args[2]!)) {
|
|
288
|
+
handlersArg = args[2] as import('typescript').ObjectLiteralExpression
|
|
289
|
+
} else if (args.length >= 2 && ts.isObjectLiteralExpression(args[1]!)) {
|
|
290
|
+
handlersArg = args[1] as import('typescript').ObjectLiteralExpression
|
|
291
|
+
}
|
|
284
292
|
} else if (args.length === 3 && ts.isObjectLiteralExpression(args[2]!)) {
|
|
285
293
|
handlersArg = args[2] as import('typescript').ObjectLiteralExpression
|
|
286
294
|
}
|