@refactorized/sanity-codegen v0.9.8-0
⚠️ This is a special HZ fork that handles reference types differently
(see original repo for actual updates and code-gen hotness. This readme is stripped down from the original)
Installation ⚠️ (THIS IS DIFFERENT)
The original package refers to itself a bunch, and we want to be able to merge upstream fixes, so we need to alias our version to the original name:
yarn add -D sanity-codegen@npm:@hzdg/sanity-codegen@latest
Note: Prettier is a peer dependency
CLI Usage
Create a sanity-codegen.config.ts
or sanity-codegen.config.js
at the root of your project.
import { SanityCodegenConfig } from 'sanity-codegen';
const config: SanityCodegenConfig = {
schemaPath: './path/to/your/schema',
outputPath: './schema.ts',
// NOTE: The CLI ships with a pre-configured babel config that shims out
// the Sanity parts system. This babel config does not read from any
// `.babelrc` or `babel.config.js`. You can only configure extra babel
// options here.
// babelOptions: require('./.babelrc.json'), // (optional)
};
export default config;
See here for the rest of the available options.
Additionally, you can import the default babel config from const { defaultBabelOptions } = require('sanity-codegen/cli')
if you need to merge your current config.
Then run the CLI with npx
at the root of your sanity project.
npx sanity-codegen
Running with
npx
runs the CLI in the context of your project's node_modules.
Schema Codegen Options
If you want your type to be marked as required instead of optional, add codegen: { required: true }
to your schema fields:
export default {
name: 'myDocument',
type: 'document',
fields: [
{
name: 'aRequiredField',
type: 'string',
// 👇👇👇
codegen: { required: true },
validation: (Rule) => Rule.required(),
// 👆👆👆
},
],
};
This will tell the codegen to remove the optional ?
modifier on the field.
NOTE: Drafts that are run through the document may have incorrect types. Be aware of this when using preview mode.
Usage with first-party client (@sanity/client
)
For more stable usage, you can use the generated types with the first party javascript client @sanity/client
(or the tiny alternative picosanity
).
Query for documents like normal but use the generated types to create the correct type for your query.
import sanityClient from '@sanity/client';
import groq from 'groq';
import type * as Schema from '../your-resulting-codegen';
const client = sanityClient({
projectId: 'your-project-id',
dataset: 'bikeshop',
token: 'sanity-auth-token', // or leave blank to be anonymous user
useCdn: true, // `false` if you want to ensure fresh data
});
// Step 1: write a query
const query = groq`
*[_type == 'blogPost'] {
// pick the title
title,
// then a full expansion of the author
author -> { ... },
}
`;
// Step 2: create a type for your query's result composed from the codegen types.
//
// Refer to Typescript's utility types for useful type helpers:
// https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys
//
// And also intersections:
// https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html#intersection-types
type QueryResult = Array<
Omit<Pick<Schema.BlogPost, 'title'>, 'author'> & {
author: Schema.Author;
}
>;
async function main() {
// Step 3: add the `QueryResult` as the type parameter as well as the query
const results = await client.fetch<QueryResult>(query);
const first = results[0];
console.log(first.title); // "Title"
console.log(first.author); // { name: 'Example', bio: '...' }
}
main().catch((e) => {
console.error(e);
process.exit(1);
});
Next.js
If you're using Next.js you can write your projections/transforms in getStaticProps
and use the return type to infer incoming props. The types will flow down nicely 😎.
import sanity from './sanity-client';
export const getStaticProps = async (context) => {
const slug = context.params?.slug as string;
const [blogPost] = sanity.getAll('blogPost', `seo.slug.current == "${slug}"`);
const { title, content } = blogPost;
return { props: { title, content } };
};
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
type Props = UnwrapPromise<ReturnType<typeof getStaticProps>>['props'];
function BlogPost({ title, content }: Props) {
return (
<>
<h1>{title}</h1>
<p>{content}</p>
</>
);
}
export default BlogPost;
API Usage
Better docs coming soon. For now the gist is:
import generateTypes from 'sanity-codegen/generate-types';
generateTypes({
// see here:
// https://github.com/ricokahler/sanity-codegen/blob/13250d60892bfc95b73d88b28e88b574a31935a7/src/generate-types.ts#L85-L109
}).then((generatedTypes) => {
// `generatedTypes` is a string with the typescript code
});
However you may run into challenges with executing the code if your schema imports from the sanity parts system. The CLI tries to help you with this.
Related Projects
sanity-typed-queries
— Returns a query builder object that returns typed queries. Works without codegen.groq-types
— Another GROQ codegen lib 😎