Skip to content

Commit

Permalink
feat(typegen): add all schema types exported union (#6962)
Browse files Browse the repository at this point in the history
  • Loading branch information
sgulseth committed Jun 18, 2024
1 parent 6b20e5f commit fa459a4
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 11 deletions.
2 changes: 2 additions & 0 deletions packages/@sanity/cli/test/__snapshots__/typegen.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ export type Slug = {
current?: string;
source?: string;
};
export type AllSanitySchemaTypes = Person | Slug;
export declare const internalGroqTypeReferenceTo: unique symbol;
// Source: ./src/queries.ts
// Variable: PAGE_QUERY
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,9 @@ export type SanityImagePaletteSwatch = {
population?: number;
title?: string;
_type: \\"sanity.imagePaletteSwatch\\";
};"
};
export type AllSanitySchemaTypes = Author | Post | Ghost | BlockContent | SanityAssetSourceData | Slug | Geopoint | SanityImageAsset | SanityFileAsset | SanityImageCrop | SanityImageHotspot | SanityImageMetadata | SanityImageDimensions | SanityImagePalette | SanityImagePaletteSwatch;"

This comment has been minimized.

Copy link
@scottrippey

scottrippey Jun 20, 2024

YES! ❤️ this! Thank you!

`;

exports[`generateSchemaTypes should generate correct types for document schema with inline fields 1`] = `
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ describe('generateSchemaTypes', () => {
"export type Author = {
_id: string;
name?: string;
};"
};
export type AllSanitySchemaTypes = Author;"
`)
})

Expand All @@ -80,7 +82,9 @@ describe('generateSchemaTypes', () => {
expect(actualOutput).toMatchInlineSnapshot(`
"export type Product = {
price: number;
};"
};
export type AllSanitySchemaTypes = Product;"
`)
})

Expand All @@ -103,7 +107,9 @@ describe('generateSchemaTypes', () => {
expect(actualOutput).toMatchInlineSnapshot(`
"export type Task = {
completed: boolean;
};"
};
export type AllSanitySchemaTypes = Task;"
`)
})

Expand Down Expand Up @@ -142,7 +148,9 @@ describe('generateSchemaTypes', () => {
street: string;
city: string;
};
};"
};
export type AllSanitySchemaTypes = User;"
`)
})

Expand All @@ -169,7 +177,9 @@ describe('generateSchemaTypes', () => {
expect(actualOutput).toMatchInlineSnapshot(`
"export type BlogPost = {
tags: Array<string>;
};"
};
export type AllSanitySchemaTypes = BlogPost;"
`)
})

Expand All @@ -193,7 +203,9 @@ describe('generateSchemaTypes', () => {
expect(actualOutput).toMatchInlineSnapshot(`
"export type DynamicData = {
metadata: unknown;
};"
};
export type AllSanitySchemaTypes = DynamicData;"
`)
})

Expand All @@ -217,7 +229,9 @@ describe('generateSchemaTypes', () => {
expect(actualOutput).toMatchInlineSnapshot(`
"export type Impossible = {
willNotHappen: null;
};"
};
export type AllSanitySchemaTypes = Impossible;"
`)
})

Expand Down Expand Up @@ -259,7 +273,9 @@ describe('generateSchemaTypes', () => {
export type Author = {
name: string;
};"
};
export type AllSanitySchemaTypes = BlogPost | Author;"
`)
})

Expand All @@ -286,7 +302,9 @@ export type Author = {
expect(actualOutput).toMatchInlineSnapshot(`
"export type MixedContent = {
content: string | number;
};"
};
export type AllSanitySchemaTypes = MixedContent;"
`)
})

Expand All @@ -310,7 +328,9 @@ export type Author = {
expect(actualOutput).toMatchInlineSnapshot(`
"export type OptionalData = {
obsoleteField: null;
};"
};
export type AllSanitySchemaTypes = OptionalData;"
`)
})

Expand Down
21 changes: 21 additions & 0 deletions packages/@sanity/codegen/src/typescript/typeGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
} from 'groq-js'

const REFERENCE_SYMBOL_NAME = 'internalGroqTypeReferenceTo'
const ALL_SCHEMA_TYPES = 'AllSanitySchemaTypes'

/**
* A class used to generate TypeScript types from a given schema
Expand Down Expand Up @@ -49,6 +50,26 @@ export class TypeGenerator {
typeDeclarations.push(t.exportNamedDeclaration(typeAlias))
})

typeDeclarations.push(
t.exportNamedDeclaration(
t.tsTypeAliasDeclaration(
t.identifier(this.getTypeName(ALL_SCHEMA_TYPES)),
null,
t.tsUnionType(
this.schema.map(({name}) => {
const typeName = this.typeNameMap.get(name)
if (!typeName) {
// this is a type guard since maps return undefined if the key is not found, however this map should
// be set inside the loop above by `this.getTypeName(...)`
throw new Error(`Unexpected error: Could not find type name for schema ${name}`)
}
return t.tsTypeReference(t.identifier(typeName))
}),
),
),
),
)

// Generate TypeScript code from the AST nodes
return typeDeclarations.map((decl) => new CodeGenerator(decl).generate().code).join('\n\n')
}
Expand Down

0 comments on commit fa459a4

Please sign in to comment.