Fields on referenced documents not showing #158
Comments
Resolving references is up to you, so |
Hmm, so I'd like to be able to pass in type arguments for the referenced fields, but I'm not seeing a place to do that? |
Got it, you'll want to mess with the Ultimately, the types we're returning are the type of the document as it is in the confi (parsed or unparsed), but not to reflect queries (which might join, project, filter, or basically anything it feels like). Until we solve generating types from a query (which is a huge problem and not on the immediate roadmap), we can't reflect anything else, so you'll have to join the types somehow, ie |
One way of doing that is a query builder (which admittedly has drawbacks in edge cases, depending on how complete it is). An example of this is: https://github.com/danielroe/sanity-typed-queries I'm currently struggling quite a lot with getting the queries to output the expected structure, it gets messy really quickly when dealing with references, "slug" being an example requiring a custom selector instead of just
instead of what could have been
|
I think this test case is flawed:
resolve() doesn't actually expect resolved references, it expects
{
foo: false,
_createdAt: 2021-12-11T11:22:56.021Z,
_id: '16742cb7-3920-4592-9396-fea7596eb10f',
_rev: '_]_04B,f>YB?V$I[|z*]4\\0',
_type: 'foo',
_updatedAt: 2022-06-04T22:57:13.598Z
} ie. not an actual document. To clarify, type.resolve() results in the resolved type but unresolved data, and it throws an error if you pass it actually resolved data. |
.resolve expects a mocked document, not a real document. It's not going to join docs, query referenced docs, etc. It's purely so mocked documents can reference another mocked doc. |
I don't expect it to join docs or query data, i expect it to accept resolved data because it returns a resolved type. It doesn't. Currently there's no way to work with resolved data with zod parsing. Is that intended? |
Basically if zodResolved was of type |
Okay.. Sorry for all my rambling here, i'm learning as i type. For anyone stumbling on this issue, i found a way to deal with it. For slugs, do this: {
type: s.slug({
zodResolved: zod => zod.transform(slug => slug),
zod: zod => zod.transform(slug => slug),
})
} That will make sure the types match (slug now has To resolve references, i have this workaround, it's not ideal (keeping all pages in memory, even if they aren't needed, and old pages won't be removed currently), but until we get a way to parse pre-resolved data from a query, it's the only way i found to make references work: // schemas/page.ts
export const pageRefs: { [id: string]: s.output<typeof pageReference> } = {};
export const loadAllPageReferences = async (client: SanityClient) => {
const query = `*[_type == "page"]`;
const pages = await client.fetch<Array<s.output<typeof pageReference>>>(query);
pages.forEach(p => {
// validate the page
pageReference.resolve(p);
// save it for resolving references later.
pageRefs[p._id] = p;
});
}; // some schema where you reference a page
{
type: s.reference({
to: [pageReference],
zodResolved: zod => zod.transform(({ _ref }) => pageRefs[_ref]),
}),
} Now if you remember to call There's probably a better way to construct the query for loading the page references so that it only loads the pages that are referenced somewhere. |
tbh I'm losing track of what the issues you're having are and how to help. The thing I'm more concerned about is that I think that the documentation isn't clear what it means with |
I don't blame you, i apologize for the rambling, i've been working 24/7 trying to meet a deadline and i was partly frustrated, partly confused. I think you're right it's mostly a question of documentation. Primarily how to handle queries with expanded references as you said. Please use fairly complicated doc structures too, more than one level deep - the |
Yeah so just to pull it all together:
In your application (mostly in your queries), you'll expand references, make queries that do weird projections, all things that I can't really build for without truly taking on the "let's type your queries" problem as well, which isn't the current goal (although it's definitely something I've wanted to solve).
Currently, the types are for 1 and 3, although If we solved this problem for the queries, ie make a typed query builder, we can make all of this irrelevant, since we'll determine the types you need by implication. I have no idea how parsing actually survives that (the query builder would also have to pass through a |
I made an issue to follow my train of thought off of these learnings. I think there's some immediate helpful tasks that are easy (renaming some of this) and a much larger hidden task (typing queries) that's under this, which I don't have the bandwidth to take on. |
Yeah, that one is a lot of work! I wish some of the modern CMS's had this out of the box (cough sanity cough). There are a few that advertises typescript, but if your data isn't typed you lose most of the benefit and it's barely more than an inline documentation tool. Sanity v3 doesn't seem to do this either. |
From what I understand, sanity started (and grew! a lot!) before typescript became the giant de-facto thing it currently is. To some degree, they need to play catchup. This library (and sanity-codegen) are here to help! |
I brushed over the names fast and it just dawned on me that @mckelveygreg and @miklschmidt have not been the same person this whole time. |
Apropos of sanity-codegen, i see they are working on typing groq query results: https://sanity-codegen-dev.vercel.app/ |
I'm trying to access fields on an array of referenced documents, but only the baked in
reference
properties show, not any of my fields.Is there a proper way to consume a referenced document?
Here is a snippet and codesandbox link:
Code snippet
```ts import { s } from "sanity-typed-schema-builder";const testReference = s.document({
name: "testReference",
title: "Test Reference",
fields: [
{
name: "title",
title: "Title",
type: s.string(),
},
{
name: "description",
title: "Description",
type: s.text(),
}
]
});
export const testDoc = s.document({
name: "testDoc",
fields: [
{
name: "testArray",
title: "test Array",
type: s.array({
of: [
s.reference({
to: [testReference]
})
]
})
}
]
});
export type TestType = s.infer;
const test = {} as TestType;
// no Title found :(
test.testArray[0].title;
The text was updated successfully, but these errors were encountered: