cogsbox-shape 0.5.204 → 0.5.206
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/README.md +43 -41
- package/cogsbox-shape-state/dist/example/type-hover-example.js +2 -2
- package/cogsbox-shape-state/dist/plugin.d.ts +1 -0
- package/cogsbox-shape-state/dist/plugin.js +24 -4
- package/dist/schema.d.ts +51 -50
- package/dist/schema.js +91 -84
- package/dist/vitest/fullSchema.test.js +249 -127
- package/dist/vitest/refineRuntime.test.js +85 -14
- package/package.json +1 -1
|
@@ -16,7 +16,7 @@ describe("Schema Builder Type Tests (with expect-type)", () => {
|
|
|
16
16
|
});
|
|
17
17
|
it("should correctly type a nullable integer field", () => {
|
|
18
18
|
const ageField = s.sqlite({ type: "int", nullable: true });
|
|
19
|
-
expectTypeOf(ageField.config.
|
|
19
|
+
expectTypeOf(ageField.config.zodClientCheckedSchema).toEqualTypeOf();
|
|
20
20
|
});
|
|
21
21
|
it("should correctly type a primary key field", () => {
|
|
22
22
|
const idField = s.sqlite({ type: "int", pk: true });
|
|
@@ -34,7 +34,7 @@ describe("Schema Builder Type Tests (with expect-type)", () => {
|
|
|
34
34
|
});
|
|
35
35
|
describe("Chainable Methods", () => {
|
|
36
36
|
it("should create a union type when .client provides a different type", () => {
|
|
37
|
-
const idField = s.sqlite({ type: "int", pk: true }).
|
|
37
|
+
const idField = s.sqlite({ type: "int", pk: true }).client({
|
|
38
38
|
value: () => "temp-uuid-123",
|
|
39
39
|
schema: z.literal("temp-uuid-123"),
|
|
40
40
|
});
|
|
@@ -43,13 +43,13 @@ describe("Schema Builder Type Tests (with expect-type)", () => {
|
|
|
43
43
|
it("should NOT create a union type when .client provides the same type", () => {
|
|
44
44
|
const countField = s
|
|
45
45
|
.sqlite({ type: "int" })
|
|
46
|
-
.
|
|
46
|
+
.client({ value: () => 0, schema: z.number() });
|
|
47
47
|
expectTypeOf().toEqualTypeOf();
|
|
48
48
|
});
|
|
49
|
-
it("should correctly override the client schema with .
|
|
49
|
+
it("should correctly override the client schema with .client()", () => {
|
|
50
50
|
const statusField = s
|
|
51
51
|
.sqlite({ type: "int" })
|
|
52
|
-
.
|
|
52
|
+
.client(() => z.boolean());
|
|
53
53
|
expectTypeOf().toEqualTypeOf();
|
|
54
54
|
expectTypeOf().toEqualTypeOf();
|
|
55
55
|
expectTypeOf().toEqualTypeOf();
|
|
@@ -57,16 +57,16 @@ describe("Schema Builder Type Tests (with expect-type)", () => {
|
|
|
57
57
|
it("should add validation to client schema with .client()", () => {
|
|
58
58
|
const nameField = s
|
|
59
59
|
.sqlite({ type: "varchar" })
|
|
60
|
-
.
|
|
61
|
-
.
|
|
60
|
+
.client({ value: "John" })
|
|
61
|
+
.clientCheck((tools) => tools.client.min(3));
|
|
62
62
|
expectTypeOf().toEqualTypeOf();
|
|
63
63
|
});
|
|
64
|
-
it("should chain .
|
|
64
|
+
it("should chain .client().clientCheck().server() correctly", () => {
|
|
65
65
|
const nameField = s
|
|
66
66
|
.sqlite({ type: "varchar" })
|
|
67
|
-
.
|
|
68
|
-
.
|
|
69
|
-
.server((tools) => tools.
|
|
67
|
+
.client({ value: "" })
|
|
68
|
+
.clientCheck((tools) => tools.client.min(3))
|
|
69
|
+
.server((tools) => tools.client.min(5));
|
|
70
70
|
expectTypeOf().toEqualTypeOf();
|
|
71
71
|
expectTypeOf().toEqualTypeOf();
|
|
72
72
|
});
|
|
@@ -75,7 +75,7 @@ describe("Schema Builder Type Tests (with expect-type)", () => {
|
|
|
75
75
|
// 1. Define schemas with placeholders
|
|
76
76
|
const users = schema({
|
|
77
77
|
_tableName: "users",
|
|
78
|
-
id: s.sqlite({ type: "int", pk: true }).
|
|
78
|
+
id: s.sqlite({ type: "int", pk: true }).client({
|
|
79
79
|
value: () => "new-user",
|
|
80
80
|
schema: z.literal("new-user"),
|
|
81
81
|
}),
|
|
@@ -84,7 +84,7 @@ describe("Schema Builder Type Tests (with expect-type)", () => {
|
|
|
84
84
|
const posts = schema({
|
|
85
85
|
_tableName: "posts",
|
|
86
86
|
id: s.sqlite({ type: "int", pk: true }),
|
|
87
|
-
isPublished: s.sqlite({ type: "int" }).
|
|
87
|
+
isPublished: s.sqlite({ type: "int" }).client(() => z.boolean()),
|
|
88
88
|
authorId: s.reference(() => users.id),
|
|
89
89
|
});
|
|
90
90
|
// 2. Create the registry and resolve relations
|
|
@@ -110,7 +110,7 @@ describe("Schema Builder Runtime Behavior", () => {
|
|
|
110
110
|
// Define the schema using the new builder syntax
|
|
111
111
|
const defaultsSchema = schema({
|
|
112
112
|
_tableName: "defaults",
|
|
113
|
-
fromInitialState: s.sqlite({ type: "varchar" }).
|
|
113
|
+
fromInitialState: s.sqlite({ type: "varchar" }).client({
|
|
114
114
|
value: () => "from-initial-state",
|
|
115
115
|
schema: z.string(),
|
|
116
116
|
}),
|
|
@@ -123,7 +123,7 @@ describe("Schema Builder Runtime Behavior", () => {
|
|
|
123
123
|
defaults: {},
|
|
124
124
|
});
|
|
125
125
|
const defaults = box.defaults.defaults;
|
|
126
|
-
it("should get default from .
|
|
126
|
+
it("should get default from .client()", () => {
|
|
127
127
|
expect(defaults.fromInitialState).toBe("from-initial-state");
|
|
128
128
|
});
|
|
129
129
|
it("should get default from SQL config", () => {
|
|
@@ -142,7 +142,7 @@ describe("Schema Builder Runtime Behavior", () => {
|
|
|
142
142
|
id: s.sqlite({ type: "int", pk: true }),
|
|
143
143
|
status: s
|
|
144
144
|
.sqlite({ type: "int" }) // DB: 0=Inactive, 1=Active
|
|
145
|
-
.
|
|
145
|
+
.client(() => z.enum(["inactive", "active"])) // Client: "inactive" | "active"
|
|
146
146
|
.transform({
|
|
147
147
|
toClient: (dbValue) => (dbValue === 1 ? "active" : "inactive"),
|
|
148
148
|
toDb: (clientValue) => (clientValue === "active" ? 1 : 0),
|
|
@@ -155,13 +155,13 @@ describe("Schema Builder Runtime Behavior", () => {
|
|
|
155
155
|
const box = createSchemaBox({ complex: complexSchemaDef }, {
|
|
156
156
|
complex: {},
|
|
157
157
|
});
|
|
158
|
-
const { client, sql, server } = box.complex.schemas;
|
|
158
|
+
const { client: clientChecked, sql, server } = box.complex.schemas;
|
|
159
159
|
const { toClient, toDb } = box.complex.transforms;
|
|
160
160
|
it("should correctly transform a DB object to a Client object", () => {
|
|
161
161
|
const dbData = { id: 1, status: 1, name: "Test" };
|
|
162
162
|
const clientResult = toClient(dbData);
|
|
163
163
|
expect(clientResult.status).toBe("active");
|
|
164
|
-
expect(() =>
|
|
164
|
+
expect(() => clientChecked.parse(clientResult)).not.toThrow();
|
|
165
165
|
});
|
|
166
166
|
it("should correctly transform a Client object to a DB object", () => {
|
|
167
167
|
const clientData = { id: 1, status: "inactive", name: "Test" };
|
|
@@ -183,78 +183,78 @@ describe("Tools params are actual Zod schemas at runtime", () => {
|
|
|
183
183
|
it("should provide actual Zod schemas as tools in .client()", () => {
|
|
184
184
|
let capturedTools;
|
|
185
185
|
s.sqlite({ type: "varchar" })
|
|
186
|
-
.
|
|
187
|
-
.
|
|
186
|
+
.client({ value: "test" })
|
|
187
|
+
.clientCheck((tools) => {
|
|
188
188
|
capturedTools = {
|
|
189
189
|
sql: tools.sql,
|
|
190
|
-
clientInput: tools.clientInput,
|
|
191
190
|
client: tools.client,
|
|
191
|
+
clientCheck: tools.clientCheck,
|
|
192
192
|
};
|
|
193
|
-
return tools.
|
|
193
|
+
return tools.clientCheck;
|
|
194
194
|
});
|
|
195
195
|
expect(capturedTools).toBeDefined();
|
|
196
196
|
expect(capturedTools.sql).toBeInstanceOf(z.ZodType);
|
|
197
197
|
expect(typeof capturedTools.sql.parse).toBe("function");
|
|
198
198
|
expect(typeof capturedTools.sql.safeParse).toBe("function");
|
|
199
|
-
expect(capturedTools.clientInput).toBeInstanceOf(z.ZodType);
|
|
200
|
-
expect(typeof capturedTools.clientInput.parse).toBe("function");
|
|
201
199
|
expect(capturedTools.client).toBeInstanceOf(z.ZodType);
|
|
202
200
|
expect(typeof capturedTools.client.parse).toBe("function");
|
|
201
|
+
expect(capturedTools.clientCheck).toBeInstanceOf(z.ZodType);
|
|
202
|
+
expect(typeof capturedTools.clientCheck.parse).toBe("function");
|
|
203
203
|
});
|
|
204
204
|
it("should provide actual Zod schemas as tools in .server()", () => {
|
|
205
205
|
let capturedTools;
|
|
206
206
|
s.sqlite({ type: "varchar" })
|
|
207
|
-
.
|
|
208
|
-
.
|
|
207
|
+
.client({ value: "test" })
|
|
208
|
+
.clientCheck((tools) => tools.client)
|
|
209
209
|
.server((tools) => {
|
|
210
210
|
capturedTools = {
|
|
211
211
|
sql: tools.sql,
|
|
212
|
-
clientInput: tools.clientInput,
|
|
213
212
|
client: tools.client,
|
|
213
|
+
clientCheck: tools.clientCheck,
|
|
214
214
|
};
|
|
215
|
-
return tools.
|
|
215
|
+
return tools.clientCheck;
|
|
216
216
|
});
|
|
217
217
|
expect(capturedTools).toBeDefined();
|
|
218
218
|
expect(capturedTools.sql).toBeInstanceOf(z.ZodType);
|
|
219
|
-
expect(capturedTools.clientInput).toBeInstanceOf(z.ZodType);
|
|
220
219
|
expect(capturedTools.client).toBeInstanceOf(z.ZodType);
|
|
220
|
+
expect(capturedTools.clientCheck).toBeInstanceOf(z.ZodType);
|
|
221
221
|
});
|
|
222
222
|
it("should allow calling Zod methods on tools params in .client()", () => {
|
|
223
|
-
let
|
|
223
|
+
let clientSchema;
|
|
224
224
|
s.sqlite({ type: "varchar" })
|
|
225
|
-
.
|
|
226
|
-
.
|
|
227
|
-
|
|
228
|
-
const validated = tools.
|
|
225
|
+
.client({ value: "" })
|
|
226
|
+
.clientCheck((tools) => {
|
|
227
|
+
clientSchema = tools.client;
|
|
228
|
+
const validated = tools.client.min(3);
|
|
229
229
|
expect(validated.safeParse("ab").success).toBe(false);
|
|
230
230
|
expect(validated.safeParse("abc").success).toBe(true);
|
|
231
231
|
return validated;
|
|
232
232
|
});
|
|
233
|
-
expect(
|
|
233
|
+
expect(clientSchema).toBeInstanceOf(z.ZodString);
|
|
234
234
|
});
|
|
235
235
|
it("should allow calling Zod methods on tools params in .server()", () => {
|
|
236
|
-
let
|
|
236
|
+
let serverClientSchema;
|
|
237
237
|
s.sqlite({ type: "varchar" })
|
|
238
|
-
.
|
|
239
|
-
.
|
|
238
|
+
.client({ value: "" })
|
|
239
|
+
.clientCheck((tools) => tools.client.min(3))
|
|
240
240
|
.server((tools) => {
|
|
241
|
-
|
|
242
|
-
const validated = tools.
|
|
241
|
+
serverClientSchema = tools.client;
|
|
242
|
+
const validated = tools.client.min(5);
|
|
243
243
|
expect(validated.safeParse("abcd").success).toBe(false);
|
|
244
244
|
expect(validated.safeParse("abcde").success).toBe(true);
|
|
245
245
|
return validated;
|
|
246
246
|
});
|
|
247
|
-
expect(
|
|
247
|
+
expect(serverClientSchema).toBeInstanceOf(z.ZodString);
|
|
248
248
|
});
|
|
249
249
|
it("should provide correct Zod types for numeric fields in tools", () => {
|
|
250
250
|
let capturedSql;
|
|
251
251
|
let capturedInput;
|
|
252
252
|
s.sqlite({ type: "int" })
|
|
253
|
-
.
|
|
254
|
-
.
|
|
253
|
+
.client({ value: 0 })
|
|
254
|
+
.clientCheck((tools) => {
|
|
255
255
|
capturedSql = tools.sql;
|
|
256
|
-
capturedInput = tools.
|
|
257
|
-
return tools.
|
|
256
|
+
capturedInput = tools.client;
|
|
257
|
+
return tools.client;
|
|
258
258
|
});
|
|
259
259
|
expect(capturedSql).toBeInstanceOf(z.ZodNumber);
|
|
260
260
|
expect(capturedSql.parse(42)).toBe(42);
|
|
@@ -264,10 +264,10 @@ describe("Tools params are actual Zod schemas at runtime", () => {
|
|
|
264
264
|
it("should provide correct Zod types for boolean fields in tools", () => {
|
|
265
265
|
let capturedInput;
|
|
266
266
|
s.sqlite({ type: "int" })
|
|
267
|
-
.
|
|
268
|
-
.
|
|
269
|
-
capturedInput = tools.
|
|
270
|
-
return tools.
|
|
267
|
+
.client(() => z.boolean())
|
|
268
|
+
.clientCheck((tools) => {
|
|
269
|
+
capturedInput = tools.client;
|
|
270
|
+
return tools.client;
|
|
271
271
|
});
|
|
272
272
|
expect(capturedInput).toBeInstanceOf(z.ZodBoolean);
|
|
273
273
|
expect(capturedInput.parse(true)).toBe(true);
|
|
@@ -276,22 +276,110 @@ describe("Tools params are actual Zod schemas at runtime", () => {
|
|
|
276
276
|
it("should allow nullable() and other modifiers on tools params", () => {
|
|
277
277
|
let capturedInput;
|
|
278
278
|
s.sqlite({ type: "varchar", nullable: true })
|
|
279
|
-
.
|
|
280
|
-
.
|
|
281
|
-
capturedInput = tools.
|
|
282
|
-
expect(tools.
|
|
283
|
-
expect(tools.
|
|
284
|
-
return tools.
|
|
279
|
+
.client({ value: null, schema: z.string().nullable() })
|
|
280
|
+
.clientCheck((tools) => {
|
|
281
|
+
capturedInput = tools.client;
|
|
282
|
+
expect(tools.client.safeParse(null).success).toBe(true);
|
|
283
|
+
expect(tools.client.safeParse("hello").success).toBe(true);
|
|
284
|
+
return tools.client;
|
|
285
285
|
});
|
|
286
286
|
expect(capturedInput).toBeInstanceOf(z.ZodNullable);
|
|
287
287
|
});
|
|
288
288
|
});
|
|
289
|
+
describe("client vs clientChecked schema divergence after .clientCheck()", () => {
|
|
290
|
+
it("should retain unmodified client schema after .clientCheck() adds .min()", () => {
|
|
291
|
+
const nameField = s.sqlite({ type: "varchar" })
|
|
292
|
+
.client({ value: "John" })
|
|
293
|
+
.clientCheck((tools) => tools.client.min(3));
|
|
294
|
+
const clientSchema = nameField.config.zodClientSchema;
|
|
295
|
+
const clientCheckedSchema = nameField.config.zodClientCheckedSchema;
|
|
296
|
+
expect(clientSchema.safeParse("ab").success).toBe(true);
|
|
297
|
+
expect(clientCheckedSchema.safeParse("ab").success).toBe(false);
|
|
298
|
+
expect(clientCheckedSchema.safeParse("abc").success).toBe(true);
|
|
299
|
+
});
|
|
300
|
+
it("should diverge at box schema level after .clientCheck()", () => {
|
|
301
|
+
const users = schema({
|
|
302
|
+
_tableName: "users",
|
|
303
|
+
id: s.sqlite({ type: "int", pk: true }),
|
|
304
|
+
name: s.sqlite({ type: "varchar" })
|
|
305
|
+
.client({ value: "" })
|
|
306
|
+
.clientCheck((tools) => tools.client.min(3)),
|
|
307
|
+
});
|
|
308
|
+
const box = createSchemaBox({ users }, { users: {} });
|
|
309
|
+
expect(box.users.schemas.client.shape.name.safeParse("ab").success).toBe(true);
|
|
310
|
+
expect(box.users.schemas.clientChecked.shape.name.safeParse("ab").success).toBe(false);
|
|
311
|
+
expect(box.users.schemas.clientChecked.shape.name.safeParse("abc").success).toBe(true);
|
|
312
|
+
});
|
|
313
|
+
it("should apply .email() only to clientChecked schema, not client", () => {
|
|
314
|
+
const nameField = s.sqlite({ type: "varchar" })
|
|
315
|
+
.client({ value: "" })
|
|
316
|
+
.clientCheck((tools) => tools.client.email());
|
|
317
|
+
expect(nameField.config.zodClientSchema.safeParse("not-an-email").success).toBe(true);
|
|
318
|
+
expect(nameField.config.zodClientCheckedSchema.safeParse("not-an-email").success).toBe(false);
|
|
319
|
+
expect(nameField.config.zodClientCheckedSchema.safeParse("a@b.com").success).toBe(true);
|
|
320
|
+
});
|
|
321
|
+
it("should apply .max() only to clientChecked schema, not client", () => {
|
|
322
|
+
const countField = s.sqlite({ type: "int" })
|
|
323
|
+
.client({ value: () => 0, schema: z.number() })
|
|
324
|
+
.clientCheck((tools) => tools.client.max(100));
|
|
325
|
+
expect(countField.config.zodClientSchema.safeParse(200).success).toBe(true);
|
|
326
|
+
expect(countField.config.zodClientCheckedSchema.safeParse(200).success).toBe(false);
|
|
327
|
+
expect(countField.config.zodClientCheckedSchema.safeParse(50).success).toBe(true);
|
|
328
|
+
});
|
|
329
|
+
it("should produce different schemas across all three layers: client, clientChecked, server", () => {
|
|
330
|
+
const nameField = s.sqlite({ type: "varchar" })
|
|
331
|
+
.client({ value: "" })
|
|
332
|
+
.clientCheck((tools) => tools.client.min(3))
|
|
333
|
+
.server((tools) => tools.client.min(5));
|
|
334
|
+
expect(nameField.config.zodClientSchema.safeParse("a").success).toBe(true);
|
|
335
|
+
expect(nameField.config.zodClientCheckedSchema.safeParse("a").success).toBe(false);
|
|
336
|
+
expect(nameField.config.zodClientCheckedSchema.safeParse("abc").success).toBe(true);
|
|
337
|
+
expect(nameField.config.zodValidationSchema.safeParse("abc").success).toBe(false);
|
|
338
|
+
expect(nameField.config.zodValidationSchema.safeParse("abcde").success).toBe(true);
|
|
339
|
+
});
|
|
340
|
+
it("should preserve clientInputZod on the internal builder config after .clientCheck()", () => {
|
|
341
|
+
let capturedConfig;
|
|
342
|
+
const field = s.sqlite({ type: "varchar" })
|
|
343
|
+
.client({ value: "x" })
|
|
344
|
+
.clientCheck((tools) => {
|
|
345
|
+
capturedConfig = { clientInputZod: tools.clientInputZod };
|
|
346
|
+
return tools.client.min(3);
|
|
347
|
+
});
|
|
348
|
+
expect(field.config.zodClientSchema).toBeDefined();
|
|
349
|
+
expect(field.config.zodClientCheckedSchema).toBeDefined();
|
|
350
|
+
expect(field.config.zodClientSchema).not.toBe(field.config.zodClientCheckedSchema);
|
|
351
|
+
});
|
|
352
|
+
it("should diverge when refine targets only 'clientCheck' layer, not 'client'", () => {
|
|
353
|
+
const forms = schema({
|
|
354
|
+
_tableName: "forms",
|
|
355
|
+
id: s.sqlite({ type: "int", pk: true }),
|
|
356
|
+
password: s.sqlite({ type: "varchar" }).client({ value: "" }),
|
|
357
|
+
confirmPassword: s.sqlite({ type: "varchar" }).client({ value: "" }),
|
|
358
|
+
}).refine((r) => [
|
|
359
|
+
r("clientCheck", (row) => {
|
|
360
|
+
if (row.password !== row.confirmPassword) {
|
|
361
|
+
return { path: ["confirmPassword"], message: "Passwords must match" };
|
|
362
|
+
}
|
|
363
|
+
return undefined;
|
|
364
|
+
}),
|
|
365
|
+
]);
|
|
366
|
+
const box = createSchemaBox({ forms }, { forms: {} });
|
|
367
|
+
const clientResult = box.forms.schemas.client.safeParse({
|
|
368
|
+
id: 1, password: "abc", confirmPassword: "def",
|
|
369
|
+
});
|
|
370
|
+
expect(clientResult.success).toBe(true);
|
|
371
|
+
const clientCheckedResult = box.forms.schemas.clientChecked.safeParse({
|
|
372
|
+
id: 1, password: "abc", confirmPassword: "def",
|
|
373
|
+
});
|
|
374
|
+
expect(clientCheckedResult.success).toBe(false);
|
|
375
|
+
});
|
|
376
|
+
});
|
|
289
377
|
describe("New Session Features - Base Schema Without Relations", () => {
|
|
290
378
|
const users = schema({
|
|
291
379
|
_tableName: "users",
|
|
292
380
|
id: s
|
|
293
381
|
.sqlite({ type: "int", pk: true })
|
|
294
|
-
.
|
|
382
|
+
.client({ value: () => "user-123", schema: z.string() }),
|
|
295
383
|
petId: s.reference(() => pets.id),
|
|
296
384
|
pets: s.hasMany(),
|
|
297
385
|
});
|
|
@@ -313,7 +401,7 @@ describe("New Session Features - Base Schema Without Relations", () => {
|
|
|
313
401
|
it("should exclude relations from base client schema", () => {
|
|
314
402
|
expectTypeOf().toEqualTypeOf();
|
|
315
403
|
// Runtime check - the schema shape should not include 'pets'
|
|
316
|
-
const clientShape = box.users.schemas.
|
|
404
|
+
const clientShape = box.users.schemas.clientChecked.shape;
|
|
317
405
|
expect(clientShape).not.toHaveProperty("pets");
|
|
318
406
|
expect(clientShape).toHaveProperty("id");
|
|
319
407
|
expect(clientShape).toHaveProperty("petId");
|
|
@@ -333,7 +421,7 @@ describe("New Session Features - Base Schema Without Relations", () => {
|
|
|
333
421
|
});
|
|
334
422
|
expectTypeOf().toEqualTypeOf();
|
|
335
423
|
// Runtime check
|
|
336
|
-
const viewShape = userView.schemas.
|
|
424
|
+
const viewShape = userView.schemas.clientChecked.shape;
|
|
337
425
|
expect(viewShape).toHaveProperty("pets");
|
|
338
426
|
expect(viewShape.pets).toBeInstanceOf(z.ZodArray);
|
|
339
427
|
});
|
|
@@ -343,7 +431,7 @@ describe("New Session Features - Base Schema Without Relations", () => {
|
|
|
343
431
|
});
|
|
344
432
|
expectTypeOf().toEqualTypeOf();
|
|
345
433
|
// Runtime check - owner should not have pets
|
|
346
|
-
const shape = userViewNested.schemas.
|
|
434
|
+
const shape = userViewNested.schemas.clientChecked.shape;
|
|
347
435
|
if (shape.pets instanceof z.ZodArray) {
|
|
348
436
|
const petSchema = shape.pets.element;
|
|
349
437
|
if (petSchema instanceof z.ZodObject) {
|
|
@@ -389,8 +477,8 @@ describe("Relation Defaults in Views", () => {
|
|
|
389
477
|
_tableName: "users",
|
|
390
478
|
id: s
|
|
391
479
|
.sqlite({ type: "int", pk: true })
|
|
392
|
-
.
|
|
393
|
-
name: s.sqlite({ type: "varchar" }).
|
|
480
|
+
.client({ value: () => "user-123", schema: z.string() }),
|
|
481
|
+
name: s.sqlite({ type: "varchar" }).client({ value: "John" }),
|
|
394
482
|
posts: s.hasMany({ count: 2 }), // Should generate 2 posts
|
|
395
483
|
comments: s.hasMany([]), // Should be empty array
|
|
396
484
|
profile: s.hasOne(true), // Changed from {} to true
|
|
@@ -400,7 +488,7 @@ describe("Relation Defaults in Views", () => {
|
|
|
400
488
|
const posts = schema({
|
|
401
489
|
_tableName: "posts",
|
|
402
490
|
id: s.sqlite({ type: "int", pk: true }),
|
|
403
|
-
title: s.sqlite({ type: "varchar" }).
|
|
491
|
+
title: s.sqlite({ type: "varchar" }).client({ value: "Default Post" }),
|
|
404
492
|
authorId: s.reference(() => users.id),
|
|
405
493
|
user: s.hasOne(true),
|
|
406
494
|
});
|
|
@@ -409,14 +497,14 @@ describe("Relation Defaults in Views", () => {
|
|
|
409
497
|
id: s.sqlite({ type: "int", pk: true }),
|
|
410
498
|
text: s
|
|
411
499
|
.sqlite({ type: "varchar" })
|
|
412
|
-
.
|
|
500
|
+
.client({ value: "Default Comment" }),
|
|
413
501
|
userId: s.reference(() => users.id),
|
|
414
502
|
user: s.hasOne(true),
|
|
415
503
|
});
|
|
416
504
|
const profiles = schema({
|
|
417
505
|
_tableName: "profiles",
|
|
418
506
|
id: s.sqlite({ type: "int", pk: true }),
|
|
419
|
-
bio: s.sqlite({ type: "varchar" }).
|
|
507
|
+
bio: s.sqlite({ type: "varchar" }).client({ value: "Default Bio" }),
|
|
420
508
|
userId: s.reference(() => users.id),
|
|
421
509
|
user: s.hasOne(true),
|
|
422
510
|
});
|
|
@@ -484,10 +572,10 @@ describe("Relation Defaults in Views", () => {
|
|
|
484
572
|
expect(defaults.posts?.[0]).not.toHaveProperty("author"); // Relation not selected
|
|
485
573
|
});
|
|
486
574
|
});
|
|
487
|
-
describe("
|
|
575
|
+
describe("Client defaults and transforms", () => {
|
|
488
576
|
const userSchema = schema({
|
|
489
577
|
_tableName: "users",
|
|
490
|
-
id: s.sqlite({ type: "int", pk: true }).
|
|
578
|
+
id: s.sqlite({ type: "int", pk: true }).client({
|
|
491
579
|
value: () => `temp_${Math.random().toString(36).substr(2, 9)}`,
|
|
492
580
|
schema: z.string(),
|
|
493
581
|
}),
|
|
@@ -496,12 +584,12 @@ describe("Transform affects defaults", () => {
|
|
|
496
584
|
.server(() => z.email("Invalid email address")),
|
|
497
585
|
isActive: s
|
|
498
586
|
.sqlite({ type: "int" })
|
|
499
|
-
.
|
|
587
|
+
.client(() => z.boolean())
|
|
500
588
|
.transform({
|
|
501
589
|
toClient: (val) => val === 1,
|
|
502
590
|
toDb: (val) => (val ? 1 : 0),
|
|
503
591
|
}),
|
|
504
|
-
role: s.sqlite({ type: "varchar" }).
|
|
592
|
+
role: s.sqlite({ type: "varchar" }).client({
|
|
505
593
|
value: "user",
|
|
506
594
|
schema: z.enum(["user", "admin"]),
|
|
507
595
|
}),
|
|
@@ -509,7 +597,7 @@ describe("Transform affects defaults", () => {
|
|
|
509
597
|
const box = createSchemaBox({ users: userSchema }, { users: {} });
|
|
510
598
|
const { transforms } = box.users;
|
|
511
599
|
const defaults = box.users.generateDefaults();
|
|
512
|
-
it("should
|
|
600
|
+
it("should infer schema-only client defaults without running toClient", () => {
|
|
513
601
|
expect(defaults.isActive).toBe(false);
|
|
514
602
|
expect(typeof defaults.isActive).toBe("boolean");
|
|
515
603
|
});
|
|
@@ -521,10 +609,44 @@ describe("Transform affects defaults", () => {
|
|
|
521
609
|
expect(clientVersion.isActive).toBe(false);
|
|
522
610
|
expect(typeof clientVersion.isActive).toBe("boolean");
|
|
523
611
|
});
|
|
612
|
+
it("should prefer explicit client defaults over inferred defaults", () => {
|
|
613
|
+
const explicitDefaults = createSchemaBox({
|
|
614
|
+
users: schema({
|
|
615
|
+
_tableName: "users",
|
|
616
|
+
score: s.sqlite({ type: "int" }).client({
|
|
617
|
+
value: 7,
|
|
618
|
+
schema: z.number().min(0),
|
|
619
|
+
}),
|
|
620
|
+
isActive: s.sqlite({ type: "int" }).client({
|
|
621
|
+
value: true,
|
|
622
|
+
schema: z.boolean(),
|
|
623
|
+
}),
|
|
624
|
+
}),
|
|
625
|
+
}, { users: {} }).users.generateDefaults();
|
|
626
|
+
expect(explicitDefaults.score).toBe(7);
|
|
627
|
+
expect(explicitDefaults.isActive).toBe(true);
|
|
628
|
+
});
|
|
629
|
+
it("should not use toClient while generating defaults", () => {
|
|
630
|
+
const defaults = createSchemaBox({
|
|
631
|
+
users: schema({
|
|
632
|
+
_tableName: "users",
|
|
633
|
+
isActive: s
|
|
634
|
+
.sqlite({ type: "int" })
|
|
635
|
+
.client(() => z.boolean())
|
|
636
|
+
.transform({
|
|
637
|
+
toClient: () => {
|
|
638
|
+
throw new Error("toClient should not run for defaults");
|
|
639
|
+
},
|
|
640
|
+
toDb: (value) => (value ? 1 : 0),
|
|
641
|
+
}),
|
|
642
|
+
}),
|
|
643
|
+
}, { users: {} }).users.generateDefaults();
|
|
644
|
+
expect(defaults.isActive).toBe(false);
|
|
645
|
+
});
|
|
524
646
|
});
|
|
525
647
|
describe("UUID generation in initialState", () => {
|
|
526
648
|
it("should call value function with uuid tool", () => {
|
|
527
|
-
const field = s.sqlite({ type: "int", pk: true }).
|
|
649
|
+
const field = s.sqlite({ type: "int", pk: true }).client({
|
|
528
650
|
value: ({ uuid }) => uuid(),
|
|
529
651
|
schema: z.string(),
|
|
530
652
|
clientPk: true,
|
|
@@ -540,15 +662,15 @@ describe("UUID generation in initialState", () => {
|
|
|
540
662
|
describe("Missing properties - parseForDb, parseFromDb, pk, clientPk, isClientRecord", () => {
|
|
541
663
|
const users = schema({
|
|
542
664
|
_tableName: "users",
|
|
543
|
-
id: s.sqlite({ type: "int", pk: true }).
|
|
665
|
+
id: s.sqlite({ type: "int", pk: true }).client({
|
|
544
666
|
value: ({ uuid }) => uuid(),
|
|
545
667
|
schema: z.string(),
|
|
546
668
|
clientPk: true,
|
|
547
669
|
}),
|
|
548
|
-
name: s.sqlite({ type: "varchar" }).
|
|
670
|
+
name: s.sqlite({ type: "varchar" }).client({ value: "John" }),
|
|
549
671
|
isActive: s
|
|
550
672
|
.sqlite({ type: "int" })
|
|
551
|
-
.
|
|
673
|
+
.client(() => z.boolean())
|
|
552
674
|
.transform({
|
|
553
675
|
toClient: (val) => val === 1,
|
|
554
676
|
toDb: (val) => (val ? 1 : 0),
|
|
@@ -559,7 +681,7 @@ describe("Missing properties - parseForDb, parseFromDb, pk, clientPk, isClientRe
|
|
|
559
681
|
const posts = schema({
|
|
560
682
|
_tableName: "posts",
|
|
561
683
|
id: s.sqlite({ type: "int", pk: true }),
|
|
562
|
-
title: s.sqlite({ type: "varchar" }).
|
|
684
|
+
title: s.sqlite({ type: "varchar" }).client({ value: "Untitled" }),
|
|
563
685
|
authorId: s.reference(() => users.id),
|
|
564
686
|
});
|
|
565
687
|
const box = createSchemaBox({ users, posts }, {
|
|
@@ -576,7 +698,7 @@ describe("Missing properties - parseForDb, parseFromDb, pk, clientPk, isClientRe
|
|
|
576
698
|
const sqlKeys = Object.keys(box.users.schemas.sql.shape);
|
|
577
699
|
expect(sqlKeys).toContain("email_address");
|
|
578
700
|
expect(sqlKeys).not.toContain("email");
|
|
579
|
-
const clientKeys = Object.keys(box.users.schemas.
|
|
701
|
+
const clientKeys = Object.keys(box.users.schemas.clientChecked.shape);
|
|
580
702
|
expect(clientKeys).toContain("email");
|
|
581
703
|
expect(clientKeys).not.toContain("email_address");
|
|
582
704
|
});
|
|
@@ -650,13 +772,13 @@ describe("Smart clientPk and isClientRecord logic", () => {
|
|
|
650
772
|
const smartSchema = schema({
|
|
651
773
|
_tableName: "smart_table",
|
|
652
774
|
// 1. Auto-detect function execution
|
|
653
|
-
id: s.sqlite({ type: "int", pk: true }).
|
|
775
|
+
id: s.sqlite({ type: "int", pk: true }).client({
|
|
654
776
|
value: ({ uuid }) => uuid(),
|
|
655
777
|
schema: z.string(),
|
|
656
778
|
clientPk: true, // Should auto-detect by dummy-executing the uuid factory
|
|
657
779
|
}),
|
|
658
780
|
// 2. Custom function + mapped db key
|
|
659
|
-
mappedId: s.sqlite({ type: "int", field: "db_mapped_id" }).
|
|
781
|
+
mappedId: s.sqlite({ type: "int", field: "db_mapped_id" }).client({
|
|
660
782
|
value: "temp_999",
|
|
661
783
|
schema: z.string(),
|
|
662
784
|
clientPk: (val) => typeof val === "string" && val.startsWith("temp_"),
|
|
@@ -693,17 +815,17 @@ describe("Nested relations with transforms", () => {
|
|
|
693
815
|
_tableName: "users",
|
|
694
816
|
id: s
|
|
695
817
|
.sqlite({ type: "int", pk: true })
|
|
696
|
-
.
|
|
697
|
-
name: s.sqlite({ type: "varchar" }).
|
|
818
|
+
.client({ value: () => "user-123", schema: z.string() }),
|
|
819
|
+
name: s.sqlite({ type: "varchar" }).client({ value: "John" }),
|
|
698
820
|
posts: s.hasMany({ count: 1 }),
|
|
699
821
|
});
|
|
700
822
|
const posts = schema({
|
|
701
823
|
_tableName: "posts",
|
|
702
824
|
id: s.sqlite({ type: "int", pk: true }),
|
|
703
|
-
title: s.sqlite({ type: "varchar" }).
|
|
825
|
+
title: s.sqlite({ type: "varchar" }).client({ value: "Default Post" }),
|
|
704
826
|
isPublished: s
|
|
705
827
|
.sqlite({ type: "int" })
|
|
706
|
-
.
|
|
828
|
+
.client(() => z.boolean())
|
|
707
829
|
.transform({
|
|
708
830
|
toClient: (val) => val === 1,
|
|
709
831
|
toDb: (val) => (val ? 1 : 0),
|
|
@@ -714,10 +836,10 @@ describe("Nested relations with transforms", () => {
|
|
|
714
836
|
const comments = schema({
|
|
715
837
|
_tableName: "comments",
|
|
716
838
|
id: s.sqlite({ type: "int", pk: true }),
|
|
717
|
-
text: s.sqlite({ type: "varchar" }).
|
|
839
|
+
text: s.sqlite({ type: "varchar" }).client({ value: "Comment" }),
|
|
718
840
|
isDeleted: s
|
|
719
841
|
.sqlite({ type: "int" })
|
|
720
|
-
.
|
|
842
|
+
.client(() => z.boolean())
|
|
721
843
|
.transform({
|
|
722
844
|
toClient: (val) => val === 1,
|
|
723
845
|
toDb: (val) => (val ? 1 : 0),
|
|
@@ -843,17 +965,17 @@ describe("Nested relations with transforms", () => {
|
|
|
843
965
|
describe("sqlOnly fields", () => {
|
|
844
966
|
const users = schema({
|
|
845
967
|
_tableName: "users",
|
|
846
|
-
id: s.sqlite({ type: "int", pk: true }).
|
|
968
|
+
id: s.sqlite({ type: "int", pk: true }).client({
|
|
847
969
|
value: () => "user-123",
|
|
848
970
|
schema: z.string(),
|
|
849
971
|
}),
|
|
850
|
-
name: s.sqlite({ type: "varchar" }).
|
|
972
|
+
name: s.sqlite({ type: "varchar" }).client({ value: "John" }),
|
|
851
973
|
internalToken: s.sqlite({ type: "varchar", sqlOnly: true }),
|
|
852
974
|
});
|
|
853
975
|
const box = createSchemaBox({ users }, { users: {} });
|
|
854
976
|
it("should exclude sqlOnly fields from client schema", () => {
|
|
855
977
|
expectTypeOf().not.toHaveProperty("internalToken");
|
|
856
|
-
const clientKeys = Object.keys(box.users.schemas.
|
|
978
|
+
const clientKeys = Object.keys(box.users.schemas.clientChecked.shape);
|
|
857
979
|
expect(clientKeys).not.toContain("internalToken");
|
|
858
980
|
});
|
|
859
981
|
it("should include sqlOnly fields in sql schema", () => {
|
|
@@ -873,7 +995,7 @@ describe("sqlOnly fields", () => {
|
|
|
873
995
|
});
|
|
874
996
|
it("should NOT include sqlOnly fields in toDb output", () => {
|
|
875
997
|
const { toDb } = box.users.transforms;
|
|
876
|
-
const clientData = { id: 1, name: "John" };
|
|
998
|
+
const clientData = { id: "1", name: "John" };
|
|
877
999
|
const result = toDb(clientData);
|
|
878
1000
|
expect(result).not.toHaveProperty("internalToken");
|
|
879
1001
|
});
|
|
@@ -896,7 +1018,7 @@ describe("SQL enum fields", () => {
|
|
|
896
1018
|
const box = createSchemaBox({ posts }, { posts: {} });
|
|
897
1019
|
it("should validate enum values in sql, client, and server schemas", () => {
|
|
898
1020
|
expect(box.posts.schemas.sql.shape.status.parse("published")).toBe("published");
|
|
899
|
-
expect(box.posts.schemas.
|
|
1021
|
+
expect(box.posts.schemas.clientChecked.shape.status.parse("archived")).toBe("archived");
|
|
900
1022
|
expect(box.posts.schemas.server.shape.status.parse("draft")).toBe("draft");
|
|
901
1023
|
expect(() => box.posts.schemas.server.shape.status.parse("deleted")).toThrow();
|
|
902
1024
|
});
|
|
@@ -916,9 +1038,9 @@ describe("derive - computed fields", () => {
|
|
|
916
1038
|
const users = schema({
|
|
917
1039
|
_tableName: "users",
|
|
918
1040
|
id: s.sqlite({ type: "int", pk: true }),
|
|
919
|
-
fullName: s.
|
|
920
|
-
firstName: s.sqlite({ type: "varchar" }).
|
|
921
|
-
lastName: s.sqlite({ type: "varchar" }).
|
|
1041
|
+
fullName: s.client(""),
|
|
1042
|
+
firstName: s.sqlite({ type: "varchar" }).client({ value: "John" }),
|
|
1043
|
+
lastName: s.sqlite({ type: "varchar" }).client({ value: "Doe" }),
|
|
922
1044
|
}).derive({
|
|
923
1045
|
forClient: {
|
|
924
1046
|
fullName: (row) => `${row.firstName} ${row.lastName}`,
|
|
@@ -946,10 +1068,10 @@ describe("derive - computed fields", () => {
|
|
|
946
1068
|
const products = schema({
|
|
947
1069
|
_tableName: "products",
|
|
948
1070
|
id: s.sqlite({ type: "int", pk: true }),
|
|
949
|
-
price: s.sqlite({ type: "int" }).
|
|
950
|
-
quantity: s.sqlite({ type: "int" }).
|
|
951
|
-
total: s.
|
|
952
|
-
formattedPrice: s.
|
|
1071
|
+
price: s.sqlite({ type: "int" }).client({ value: 100 }),
|
|
1072
|
+
quantity: s.sqlite({ type: "int" }).client({ value: 5 }),
|
|
1073
|
+
total: s.client(0),
|
|
1074
|
+
formattedPrice: s.client(""),
|
|
953
1075
|
}).derive({
|
|
954
1076
|
forClient: {
|
|
955
1077
|
total: (row) => row.price * row.quantity,
|
|
@@ -965,8 +1087,8 @@ describe("derive - computed fields", () => {
|
|
|
965
1087
|
const contacts = schema({
|
|
966
1088
|
_tableName: "contacts",
|
|
967
1089
|
id: s.sqlite({ type: "int", pk: true }),
|
|
968
|
-
firstName: s.sqlite({ type: "varchar" }).
|
|
969
|
-
lastName: s.sqlite({ type: "varchar" }).
|
|
1090
|
+
firstName: s.sqlite({ type: "varchar" }).client({ value: "John" }),
|
|
1091
|
+
lastName: s.sqlite({ type: "varchar" }).client({ value: "Doe" }),
|
|
970
1092
|
searchName: s.sqlite({ type: "varchar", sqlOnly: true }),
|
|
971
1093
|
}).derive({
|
|
972
1094
|
forDb: {
|
|
@@ -988,9 +1110,9 @@ describe("derive - computed fields", () => {
|
|
|
988
1110
|
const contacts = schema({
|
|
989
1111
|
_tableName: "contacts",
|
|
990
1112
|
id: s.sqlite({ type: "int", pk: true }),
|
|
991
|
-
firstName: s.sqlite({ type: "varchar" }).
|
|
992
|
-
lastName: s.sqlite({ type: "varchar" }).
|
|
993
|
-
fullName: s.sqlite({ type: "varchar" }).
|
|
1113
|
+
firstName: s.sqlite({ type: "varchar" }).client({ value: "John" }),
|
|
1114
|
+
lastName: s.sqlite({ type: "varchar" }).client({ value: "Doe" }),
|
|
1115
|
+
fullName: s.sqlite({ type: "varchar" }).client({ value: "" }),
|
|
994
1116
|
}).derive({
|
|
995
1117
|
forDb: {
|
|
996
1118
|
fullName: (row) => `${row.firstName} ${row.lastName}`.trim(),
|
|
@@ -1010,13 +1132,13 @@ describe("refine", () => {
|
|
|
1010
1132
|
const events = schema({
|
|
1011
1133
|
_tableName: "events",
|
|
1012
1134
|
id: s.sqlite({ type: "int", pk: true }),
|
|
1013
|
-
startDate: s.sqlite({ type: "varchar" }).
|
|
1014
|
-
endDate: s.sqlite({ type: "varchar" }).
|
|
1015
|
-
content: s.sqlite({ type: "varchar", nullable: true }).
|
|
1135
|
+
startDate: s.sqlite({ type: "varchar" }).client({ value: "" }),
|
|
1136
|
+
endDate: s.sqlite({ type: "varchar" }).client({ value: "" }),
|
|
1137
|
+
content: s.sqlite({ type: "varchar", nullable: true }).client({
|
|
1016
1138
|
value: null,
|
|
1017
1139
|
schema: z.string().nullable(),
|
|
1018
1140
|
}),
|
|
1019
|
-
isPublished: s.sqlite({ type: "boolean" }).
|
|
1141
|
+
isPublished: s.sqlite({ type: "boolean" }).client({ value: false }),
|
|
1020
1142
|
}).refine((r) => [
|
|
1021
1143
|
r("server", (row) => {
|
|
1022
1144
|
const errors = [];
|
|
@@ -1068,10 +1190,10 @@ describe("refine", () => {
|
|
|
1068
1190
|
const forms = schema({
|
|
1069
1191
|
_tableName: "forms",
|
|
1070
1192
|
id: s.sqlite({ type: "int", pk: true }),
|
|
1071
|
-
password: s.sqlite({ type: "varchar" }).
|
|
1072
|
-
confirmPassword: s.sqlite({ type: "varchar" }).
|
|
1193
|
+
password: s.sqlite({ type: "varchar" }).client({ value: "" }),
|
|
1194
|
+
confirmPassword: s.sqlite({ type: "varchar" }).client({ value: "" }),
|
|
1073
1195
|
}).refine((r) => [
|
|
1074
|
-
r(["
|
|
1196
|
+
r(["client", "clientCheck"], (row) => {
|
|
1075
1197
|
if (row.password !== row.confirmPassword) {
|
|
1076
1198
|
return {
|
|
1077
1199
|
path: ["confirmPassword"],
|
|
@@ -1082,7 +1204,7 @@ describe("refine", () => {
|
|
|
1082
1204
|
}),
|
|
1083
1205
|
]);
|
|
1084
1206
|
const box = createSchemaBox({ forms }, { forms: {} });
|
|
1085
|
-
const result = box.forms.schemas.
|
|
1207
|
+
const result = box.forms.schemas.client.safeParse({
|
|
1086
1208
|
id: 1,
|
|
1087
1209
|
password: "secret",
|
|
1088
1210
|
confirmPassword: "different",
|
|
@@ -1091,7 +1213,7 @@ describe("refine", () => {
|
|
|
1091
1213
|
if (!result.success) {
|
|
1092
1214
|
expect(result.error.issues[0].message).toBe("Passwords must match");
|
|
1093
1215
|
}
|
|
1094
|
-
const validResult = box.forms.schemas.
|
|
1216
|
+
const validResult = box.forms.schemas.client.safeParse({
|
|
1095
1217
|
id: 1,
|
|
1096
1218
|
password: "secret",
|
|
1097
1219
|
confirmPassword: "secret",
|
|
@@ -1102,8 +1224,8 @@ describe("refine", () => {
|
|
|
1102
1224
|
const items = schema({
|
|
1103
1225
|
_tableName: "items",
|
|
1104
1226
|
id: s.sqlite({ type: "int", pk: true }),
|
|
1105
|
-
min: s.sqlite({ type: "int" }).
|
|
1106
|
-
max: s.sqlite({ type: "int" }).
|
|
1227
|
+
min: s.sqlite({ type: "int" }).client({ value: 0 }),
|
|
1228
|
+
max: s.sqlite({ type: "int" }).client({ value: 100 }),
|
|
1107
1229
|
}).refine((r) => [
|
|
1108
1230
|
r("server", (row) => {
|
|
1109
1231
|
if (row.min > row.max) {
|
|
@@ -1122,8 +1244,8 @@ describe("refine", () => {
|
|
|
1122
1244
|
const records = schema({
|
|
1123
1245
|
_tableName: "records",
|
|
1124
1246
|
id: s.sqlite({ type: "int", pk: true }),
|
|
1125
|
-
firstName: s.sqlite({ type: "varchar" }).
|
|
1126
|
-
lastName: s.sqlite({ type: "varchar" }).
|
|
1247
|
+
firstName: s.sqlite({ type: "varchar" }).client({ value: "" }),
|
|
1248
|
+
lastName: s.sqlite({ type: "varchar" }).client({ value: "" }),
|
|
1127
1249
|
fullName: s.sqlite({ type: "varchar", sqlOnly: true }),
|
|
1128
1250
|
})
|
|
1129
1251
|
.derive({
|
|
@@ -1159,8 +1281,8 @@ describe("client-only fields", () => {
|
|
|
1159
1281
|
const tasks = schema({
|
|
1160
1282
|
_tableName: "tasks",
|
|
1161
1283
|
id: s.sqlite({ type: "int", pk: true }),
|
|
1162
|
-
title: s.sqlite({ type: "varchar" }).
|
|
1163
|
-
statusLabel: s.
|
|
1284
|
+
title: s.sqlite({ type: "varchar" }).client({ value: "" }),
|
|
1285
|
+
statusLabel: s.client(""),
|
|
1164
1286
|
});
|
|
1165
1287
|
const taskBox = createSchemaBox({ tasks }, { tasks: {} });
|
|
1166
1288
|
expect(taskBox.tasks.transforms.parseForDb({
|
|
@@ -1176,7 +1298,7 @@ describe("client-only fields", () => {
|
|
|
1176
1298
|
describe("sqlOnly with derive in relations", () => {
|
|
1177
1299
|
const users = schema({
|
|
1178
1300
|
_tableName: "users",
|
|
1179
|
-
id: s.sqlite({ type: "int", pk: true }).
|
|
1301
|
+
id: s.sqlite({ type: "int", pk: true }).client({
|
|
1180
1302
|
value: () => "user-123",
|
|
1181
1303
|
schema: z.string(),
|
|
1182
1304
|
}),
|
|
@@ -1186,9 +1308,9 @@ describe("sqlOnly with derive in relations", () => {
|
|
|
1186
1308
|
const posts = schema({
|
|
1187
1309
|
_tableName: "posts",
|
|
1188
1310
|
id: s.sqlite({ type: "int", pk: true }),
|
|
1189
|
-
title: s.sqlite({ type: "varchar" }).
|
|
1311
|
+
title: s.sqlite({ type: "varchar" }).client({ value: "Post" }),
|
|
1190
1312
|
authorId: s.reference(() => users.id),
|
|
1191
|
-
preview: s.
|
|
1313
|
+
preview: s.client(""),
|
|
1192
1314
|
}).derive({
|
|
1193
1315
|
forClient: {
|
|
1194
1316
|
preview: (row) => row.title.substring(0, 5),
|
|
@@ -1199,7 +1321,7 @@ describe("sqlOnly with derive in relations", () => {
|
|
|
1199
1321
|
});
|
|
1200
1322
|
it("should exclude sqlOnly fields from view but include derived", () => {
|
|
1201
1323
|
const view = box.users.createView({ posts: true });
|
|
1202
|
-
const viewClientKeys = Object.keys(view.schemas.
|
|
1324
|
+
const viewClientKeys = Object.keys(view.schemas.clientChecked.shape);
|
|
1203
1325
|
expect(viewClientKeys).not.toContain("internalScore");
|
|
1204
1326
|
expect(viewClientKeys).toContain("id");
|
|
1205
1327
|
expect(viewClientKeys).toContain("posts");
|
|
@@ -1227,15 +1349,15 @@ describe("defaultsDefinition", () => {
|
|
|
1227
1349
|
_tableName: "users",
|
|
1228
1350
|
id: s
|
|
1229
1351
|
.sqlite({ type: "int", pk: true })
|
|
1230
|
-
.
|
|
1231
|
-
name: s.sqlite({ type: "varchar" }).
|
|
1352
|
+
.client({ value: "user-123", schema: z.string() }),
|
|
1353
|
+
name: s.sqlite({ type: "varchar" }).client({ value: "John" }),
|
|
1232
1354
|
posts: s.hasMany({ count: 2 }),
|
|
1233
1355
|
profile: s.hasOne(true),
|
|
1234
1356
|
});
|
|
1235
1357
|
const posts = schema({
|
|
1236
1358
|
_tableName: "posts",
|
|
1237
1359
|
id: s.sqlite({ type: "int", pk: true }),
|
|
1238
|
-
title: s.sqlite({ type: "varchar" }).
|
|
1360
|
+
title: s.sqlite({ type: "varchar" }).client({ value: "Default Post" }),
|
|
1239
1361
|
authorId: s.reference(() => users.id),
|
|
1240
1362
|
user: s.hasOne(true),
|
|
1241
1363
|
});
|
|
@@ -1279,19 +1401,19 @@ describe("defaultsDefinition", () => {
|
|
|
1279
1401
|
describe("dynamic value functions re-run on each view.defaults() call", () => {
|
|
1280
1402
|
const factory = schema({
|
|
1281
1403
|
_tableName: "factories",
|
|
1282
|
-
id: s.sqlite({ type: "int", pk: true }).
|
|
1404
|
+
id: s.sqlite({ type: "int", pk: true }).client({
|
|
1283
1405
|
value: () => `temp_${Math.random().toString(36).substr(2, 8)}`,
|
|
1284
1406
|
schema: z.string(),
|
|
1285
1407
|
clientPk: true,
|
|
1286
1408
|
}),
|
|
1287
1409
|
name: s
|
|
1288
1410
|
.sqlite({ type: "varchar", length: 100 })
|
|
1289
|
-
.
|
|
1411
|
+
.client({ value: "MyFactory" }),
|
|
1290
1412
|
boxes: s.hasMany({ count: 2 }),
|
|
1291
1413
|
});
|
|
1292
1414
|
const box = schema({
|
|
1293
1415
|
_tableName: "boxes",
|
|
1294
|
-
id: s.sqlite({ type: "int", pk: true }).
|
|
1416
|
+
id: s.sqlite({ type: "int", pk: true }).client({
|
|
1295
1417
|
value: () => `box_${Math.random().toString(36).substr(2, 8)}`,
|
|
1296
1418
|
schema: z.string(),
|
|
1297
1419
|
clientPk: true,
|
|
@@ -1301,7 +1423,7 @@ describe("dynamic value functions re-run on each view.defaults() call", () => {
|
|
|
1301
1423
|
});
|
|
1302
1424
|
const boxVariant = schema({
|
|
1303
1425
|
_tableName: "box_variants",
|
|
1304
|
-
id: s.sqlite({ type: "int", pk: true }).
|
|
1426
|
+
id: s.sqlite({ type: "int", pk: true }).client({
|
|
1305
1427
|
value: () => `var_${Math.random().toString(36).substr(2, 8)}`,
|
|
1306
1428
|
schema: z.string(),
|
|
1307
1429
|
clientPk: true,
|
|
@@ -1309,7 +1431,7 @@ describe("dynamic value functions re-run on each view.defaults() call", () => {
|
|
|
1309
1431
|
boxId: s.reference(() => box.id),
|
|
1310
1432
|
label: s
|
|
1311
1433
|
.sqlite({ type: "varchar", length: 50 })
|
|
1312
|
-
.
|
|
1434
|
+
.client({ value: "Standard" }),
|
|
1313
1435
|
});
|
|
1314
1436
|
const box_ = createSchemaBox({ factory, box, boxVariant }, {
|
|
1315
1437
|
factory: {
|