T
TanStack2mo ago
probable-pink

[Query collection] how to insert with defaults

hi guys. i have this query collection its query function is a server function that fetches from my database:
export const messageSchema = z.object({
message: z.string(),
chatId: z.string(),
senderId: z.string().nullable(),
})

export const messageCollection = createCollection(
queryCollectionOptions({
getKey: (message) => message.id,
queryClient: getContext().queryClient,
schema: messageSchema,
queryFn: () => getMessages(),
queryKey: ['messageCollection'],
}),
)
export const messageSchema = z.object({
message: z.string(),
chatId: z.string(),
senderId: z.string().nullable(),
})

export const messageCollection = createCollection(
queryCollectionOptions({
getKey: (message) => message.id,
queryClient: getContext().queryClient,
schema: messageSchema,
queryFn: () => getMessages(),
queryKey: ['messageCollection'],
}),
)
i only need to fill the fields from the message schema since fields like id are auto incrementing and dates has defaults set but when i make an insert, the collection makes me provide all fields. is there any way to handle this? thank u so much in advance!
30 Replies
metropolitan-bronze
metropolitan-bronze2mo ago
you can add defaults w/ zod https://zod.dev/api#defaults
Zod
Defining schemas | Zod
Complete API reference for all Zod schema types, methods, and validation features
probable-pink
probable-pinkOP2mo ago
hi is this the way to insert to the schema?
messageCollection.insert({
})
messageCollection.insert({
})
because when i try to insert this way it requires me to supply all fields
No description
probable-pink
probable-pinkOP2mo ago
my database already handles all the defaults so i want to just supply what my db needs (the ones from the zod schema)
metropolitan-bronze
metropolitan-bronze2mo ago
no, the zod schema the mutation.changes object just has the data you inserted
probable-pink
probable-pinkOP2mo ago
export const messageSchema = z.object({
message: z.string(),
chatId: z.string(),
senderId: z.string().nullable(),
id: z.number(),
createdAt: z.date().default(new Date()),
updatedAt: z.date().default(new Date()),
})

export const messageCollection = createCollection(
queryCollectionOptions({
getKey: (message) => message.id,
queryClient: getContext().queryClient,
schema: messageSchema,
queryFn: () => getMessages(),
queryKey: ['messageCollection'],
}),
)
export const messageSchema = z.object({
message: z.string(),
chatId: z.string(),
senderId: z.string().nullable(),
id: z.number(),
createdAt: z.date().default(new Date()),
updatedAt: z.date().default(new Date()),
})

export const messageCollection = createCollection(
queryCollectionOptions({
getKey: (message) => message.id,
queryClient: getContext().queryClient,
schema: messageSchema,
queryFn: () => getMessages(),
queryKey: ['messageCollection'],
}),
)
this is my schema now but it still required when i insert. am i misunderstanding its use?
No description
probable-pink
probable-pinkOP2mo ago
i thought if i added a default it would make it optional in the insert
metropolitan-bronze
metropolitan-bronze2mo ago
yeah, that's how it should work — perhaps it isn't working with query collections? https://github.com/TanStack/db/blob/968602e4ffc597eaa559219daf22d6ef6321162a/packages/db/tests/collection.test.ts#L1133-L1167
GitHub
db/packages/db/tests/collection.test.ts at 968602e4ffc597eaa559219d...
A reactive client store for building super fast apps - TanStack/db
probable-pink
probable-pinkOP2mo ago
slr. yea the schema worked on localcollection i just tested it. my version for both core-db and react db is ^0.1.7
metropolitan-bronze
metropolitan-bronze2mo ago
ok, then it seems there's something wrong with how the types are passed around in query collection — can you file an issue please?
probable-pink
probable-pinkOP2mo ago
slr again idk if this is helpful but i noticed its type is from the server function getMessages that i passed to it. its shape is the same as the required fields from the insert i will make a issue rn and make a reproduction thank you so much! @Kyle Mathews
probable-pink
probable-pinkOP2mo ago
GitHub
Feature Request: Allow default values / computed fields on Persiste...
Description When using queryCollectionOptions, inserts must fully satisfy the return type of the queryFn. This makes it hard to work with cases where some fields (like id or completed) should be au...
probable-pink
probable-pinkOP2mo ago
Creates query collection options for use with a standard Collection. This integrates TanStack Query with TanStack DB for automatic synchronization. Supports automatic type inference following the priority order: 1. Explicit type (highest priority) 2. Schema inference (second priority) 3. QueryFn return type inference (third priority) 4. Fallback to Record<string, unknown>
oh so it is a bug based on its signature help its prioritizing the queryFn's return type in my case
metropolitan-bronze
metropolitan-bronze2mo ago
oh interesting — so using that over the schema? So it just gets the ordering wrong? If you remove the return type, does it work
probable-pink
probable-pinkOP2mo ago
should i try replacing it with func that returns any?
metropolitan-bronze
metropolitan-bronze2mo ago
not entirely sure — that or unknown should be ignored
probable-pink
probable-pinkOP2mo ago
i just tried it and the type is any now. still not the schema
probable-pink
probable-pinkOP2mo ago
No description
probable-pink
probable-pinkOP2mo ago
const messageCollection: Collection<object, string | number, QueryCollectionUtils<object, string | number, object>, StandardSchemaV1<unknown, unknown>, object>
const messageCollection: Collection<object, string | number, QueryCollectionUtils<object, string | number, object>, StandardSchemaV1<unknown, unknown>, object>
is this impossible? i just realized we do need to pass the whole shape of the data in order to display optimistic updates. i wondering if theres a way to not make it hard to handle because currently if i have createdAt and updatedAt in my data, i would need to supply those fields in order to insert new data
metropolitan-bronze
metropolitan-bronze2mo ago
right, that's why we support adding defaults — they are applied even if perhaps the type isn't working correctly atm
probable-pink
probable-pinkOP2mo ago
thats good for me, any ideas about auto incrementing ids or server generated defaults?
metropolitan-bronze
metropolitan-bronze2mo ago
generally with incrementing ids you'll just want to pick a random id far larger than the current set — it'll get replaced by the server id once that syncs back
probable-pink
probable-pinkOP2mo ago
ohhh thats so awesome i didnt know that how about indicator datas like for messages example isSending flag? are metadata used for that? the ones that will be there to indicate that its optimistic data and should be overwritten by the actual data similar to how useOptimistic hook from react?
metropolitan-bronze
metropolitan-bronze2mo ago
we don't have that — we need it though — something along the lines of https://github.com/TanStack/db/issues/20
GitHub
Track Optimistic Status Per Record for Local-Only Query Differentia...
Problem Currently, there is no explicit way to distinguish between records that exist optimistically on the client and those that have been confirmed by the server. This can cause ambiguity in UI r...
probable-pink
probable-pinkOP2mo ago
i really like that. i would like to try although i dont have experience creating or contributing to libraries do you know where can i start so i can experiment? im really interested to contribute in this library
metropolitan-bronze
metropolitan-bronze2mo ago
a good place to start would be to try to fix your type issue — here's the type tests for the library https://github.com/TanStack/db/blob/main/packages/query-db-collection/tests/query.test-d.ts
GitHub
db/packages/query-db-collection/tests/query.test-d.ts at main · Ta...
A reactive client store for building super fast apps - TanStack/db
probable-pink
probable-pinkOP2mo ago
i can try that. i dont know how tho do i just fork the repo? i got it now i just read the contributing guide. ill see what i can do. thank you hello im still trying to decipher the repo @Kyle Mathews can i dm you? i have some questions
metropolitan-bronze
metropolitan-bronze2mo ago
let's just keep questions here
probable-pink
probable-pinkOP2mo ago
got it. i was missing a ensure config script i thought i need in the examples/react/todo its all good now
probable-pink
probable-pinkOP2mo ago
No description
probable-pink
probable-pinkOP2mo ago
i think theres a mistake in the test so i changed it. is this correct? based on the comment // Should use schema type, not TodoType from queryFn
export interface QueryCollectionConfig<
TExplicit extends object = object,
TSchema extends StandardSchemaV1 = never,
TQueryFn extends (
context: QueryFunctionContext<any>
) => Promise<Array<any>> = (
context: QueryFunctionContext<any>
) => Promise<Array<any>>,
TError = unknown,
TQueryKey extends QueryKey = QueryKey,
> {
export interface QueryCollectionConfig<
TExplicit extends object = object,
TSchema extends StandardSchemaV1 = never,
TQueryFn extends (
context: QueryFunctionContext<any>
) => Promise<Array<any>> = (
context: QueryFunctionContext<any>
) => Promise<Array<any>>,
TError = unknown,
TQueryKey extends QueryKey = QueryKey,
> {
im not good with this kind of typescript. maybe the TExplicit is defaulted to object instead of unknown thats why the ResolveType doesnt work normally? still not sure why the queryFn's type wins tho i cant set it to unknown since CollectionConfig gets angy
Diagnostics:
1. Type 'ResolveType<TExplicit, TSchema, TQueryFn>' does not satisfy the constraint 'object'.
Type 'TExplicit | ([TSchema] extends [never] ? InferQueryFnOutput<TQueryFn> : InferSchemaOutput<TSchema>)' is not assignable to type 'object'.
Type 'TExplicit' is not assignable to type 'object'. [2344]
Diagnostics:
1. Type 'ResolveType<TExplicit, TSchema, TQueryFn>' does not satisfy the constraint 'object'.
Type 'TExplicit | ([TSchema] extends [never] ? InferQueryFnOutput<TQueryFn> : InferSchemaOutput<TSchema>)' is not assignable to type 'object'.
Type 'TExplicit' is not assignable to type 'object'. [2344]

Did you find this page helpful?