Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(codegen): expose referenced type as hidden symbol #6008

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`generateSchemaTypes can generate well known types 1`] = `"export declare const internalGroqTypeReferenceTo: unique symbol;"`;

exports[`generateSchemaTypes generateTypeNodeTypes should be able to generate types for type nodes: boolean 1`] = `"export type test_2 = boolean;"`;

exports[`generateSchemaTypes generateTypeNodeTypes should be able to generate types for type nodes: null 1`] = `"export type test_5 = null;"`;
Expand Down Expand Up @@ -30,9 +32,11 @@ export type Post = {
author?: {
_ref: string;
_weak?: boolean;
[internalGroqTypeReferenceTo]?: \\"author\\";
} | {
_ref: string;
_weak?: boolean;
[internalGroqTypeReferenceTo]?: \\"ghost\\";
};
slug?: Slug;
excerpt?: string;
Expand All @@ -41,6 +45,7 @@ export type Post = {
asset: {
_ref: string;
_weak?: boolean;
[internalGroqTypeReferenceTo]?: \\"sanity.imageAsset\\";
};
caption?: string;
attribution?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ describe('generateSchemaTypes', () => {
expect(typeDeclarations).toMatchSnapshot()
})

test('can generate well known types', async () => {
const typeDeclarations = TypeGenerator.generateKnownTypes()

expect(typeDeclarations).toMatchSnapshot()
})

test('should generate correct types for document schema with string fields', () => {
const schema: SchemaType = [
{
Expand Down Expand Up @@ -247,6 +253,7 @@ describe('generateSchemaTypes', () => {
_ref: string;
_type: \\"reference\\";
_weak?: boolean;
[internalGroqTypeReferenceTo]?: \\"author\\";
};
};

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

const REFERENCE_SYMBOL_NAME = 'internalGroqTypeReferenceTo'

/**
* A class used to generate TypeScript types from a given schema
* @internal
Expand Down Expand Up @@ -71,6 +73,18 @@ export class TypeGenerator {
return new CodeGenerator(t.exportNamedDeclaration(typeAlias)).generate().code
}

static generateKnownTypes(): string {
const typeOperator = t.tsTypeOperator(t.tsSymbolKeyword())
typeOperator.operator = 'unique'

const identifier = t.identifier(REFERENCE_SYMBOL_NAME)
identifier.typeAnnotation = t.tsTypeAnnotation(typeOperator)

const decleration = t.variableDeclaration('const', [t.variableDeclarator(identifier)])
decleration.declare = true
return new CodeGenerator(t.exportNamedDeclaration(decleration)).generate().code
}

/**
* Since we are sanitizing identifiers we migt end up with collisions. Ie there might be a type mux.video and muxVideo, both these
* types would be sanityized into MuxVideo. To avoid this we keep track of the generated type names and add a index to the name.
Expand Down Expand Up @@ -204,6 +218,15 @@ export class TypeGenerator {
}
}
}
if (typeNode.dereferencesTo !== undefined) {
const derefType = t.tsPropertySignature(
t.identifier(REFERENCE_SYMBOL_NAME),
t.tsTypeAnnotation(t.tsLiteralType(t.stringLiteral(typeNode.dereferencesTo))),
)
derefType.computed = true
derefType.optional = true
props.push(derefType)
}
return t.tsTypeLiteral(props)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@ async function main() {
const schema = await readSchema(opts.schemaPath)

const typeGenerator = new TypeGenerator(schema)
const schemaTypes = typeGenerator.generateSchemaTypes()
const schemaTypes = [
typeGenerator.generateSchemaTypes(),
TypeGenerator.generateKnownTypes(),
].join('\n')
const resolver = getResolver()

parentPort?.postMessage({
Expand Down
Loading