Skip to content

Commit

Permalink
feat(codegen): add typegen methods to codegen package
Browse files Browse the repository at this point in the history
co-authored-by: Tonina Zhelyazkova <zhelyazkova.tonina@gmail.com>
  • Loading branch information
sgulseth and tzhelyazkova committed Mar 18, 2024
1 parent 0d3d984 commit f92f7b4
Show file tree
Hide file tree
Showing 11 changed files with 2,200 additions and 0 deletions.
4 changes: 4 additions & 0 deletions packages/@sanity/codegen/package.json
Expand Up @@ -59,18 +59,22 @@
},
"dependencies": {
"@babel/core": "^7.23.9",
"@babel/generator": "^7.23.6",
"@babel/preset-env": "^7.23.8",
"@babel/preset-react": "^7.23.3",
"@babel/preset-typescript": "^7.23.3",
"@babel/register": "^7.23.7",
"@babel/traverse": "^7.23.5",
"@babel/types": "^7.23.9",
"debug": "^4.3.4",
"globby": "^10.0.0",
"groq-js": "1.5.0-canary.1",
"tsconfig-paths": "^4.2.0"
},
"devDependencies": {
"@jest/globals": "^29.7.0",
"@types/babel__core": "^7.20.5",
"@types/babel__generator": "^7.6.8",
"@types/babel__register": "^7.17.3",
"@types/babel__traverse": "^7.18.1",
"@types/debug": "^4.1.12",
Expand Down
3 changes: 3 additions & 0 deletions packages/@sanity/codegen/src/_exports/index.ts
@@ -1,3 +1,6 @@
export {readSchema} from '../readSchema'
export {findQueriesInPath} from '../typescript/findQueriesInPath'
export {findQueriesInSource} from '../typescript/findQueriesInSource'
export {getResolver} from '../typescript/moduleResolver'
export {registerBabel} from '../typescript/registerBabel'
export {TypeGenerator} from '../typescript/typeGenerator'
14 changes: 14 additions & 0 deletions packages/@sanity/codegen/src/readSchema.ts
@@ -0,0 +1,14 @@
import {readFile} from 'fs/promises'
import {type SchemaType} from 'groq-js'

/**
* Read a schema from a given path
* @param path - The path to the schema
* @returns The schema
* @internal
* @beta
**/
export async function readSchema(path: string): Promise<SchemaType> {
const content = await readFile(path, 'utf-8')
return JSON.parse(content) // todo: ZOD validation?
}
@@ -0,0 +1,222 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

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;"`;

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

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

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

exports[`generateSchemaTypes should generate TypeScript type declarations for a schema 1`] = `
"export type Author = {
_id: string;
_type: \\"author\\";
_createdAt: string;
_updatedAt: string;
_rev: string;
name?: string;
};
export type Post = {
_id: string;
_type: \\"post\\";
_createdAt: string;
_updatedAt: string;
_rev: string;
title?: string;
author?: {
_ref: string;
_weak?: boolean;
} | {
_ref: string;
_weak?: boolean;
};
slug?: Slug;
excerpt?: string;
mainImage?: {
_type: \\"image\\";
asset: {
_ref: string;
_weak?: boolean;
};
caption?: string;
attribution?: string;
hotspot?: {
_type: \\"sanity.imageHotspot\\";
x: number;
y: number;
height: number;
width: number;
};
crop?: {
_type: \\"sanity.imageCrop\\";
top: number;
bottom: number;
left: number;
right: number;
};
};
body?: BlockContent;
};
export type Ghost = {
_id: string;
_type: \\"ghost\\";
_createdAt: string;
_updatedAt: string;
_rev: string;
name?: string;
};
export type BlockContent = Array<{
_key: string;
level?: number;
style?: \\"normal\\" | \\"h1\\" | \\"h2\\" | \\"h3\\" | \\"h4\\" | \\"blockquote\\";
listItem?: \\"bullet\\";
children: Array<{
_key: string;
text: string;
marks: Array<string | \\"strong\\" | \\"em\\">;
}>;
markDefs: Array<{
href?: string;
}>;
_key: string;
}>;
export type SanityAssetSourceData = {
name?: string;
id?: string;
url?: string;
_type: \\"sanity.assetSourceData\\";
};
export type Slug = {
current?: string;
source?: string;
_type: \\"slug\\";
};
export type Geopoint = {
lat?: number;
lng?: number;
alt?: number;
_type: \\"geopoint\\";
};
export type SanityImageAsset = {
_id: string;
_type: \\"sanity.imageAsset\\";
_createdAt: string;
_updatedAt: string;
_rev: string;
originalFilename?: string;
label?: string;
title?: string;
description?: string;
altText?: string;
sha1hash?: string;
extension?: string;
mimeType?: string;
size?: number;
assetId?: string;
uploadId?: string;
path?: string;
url?: string;
metadata?: SanityImageMetadata;
source?: SanityAssetSourceData;
};
export type SanityFileAsset = {
_id: string;
_type: \\"sanity.fileAsset\\";
_createdAt: string;
_updatedAt: string;
_rev: string;
originalFilename?: string;
label?: string;
title?: string;
description?: string;
altText?: string;
sha1hash?: string;
extension?: string;
mimeType?: string;
size?: number;
assetId?: string;
uploadId?: string;
path?: string;
url?: string;
source?: SanityAssetSourceData;
};
export type SanityImageCrop = {
top?: number;
bottom?: number;
left?: number;
right?: number;
_type: \\"sanity.imageCrop\\";
};
export type SanityImageHotspot = {
x?: number;
y?: number;
height?: number;
width?: number;
_type: \\"sanity.imageHotspot\\";
};
export type SanityImageMetadata = {
location?: Geopoint;
dimensions?: SanityImageDimensions;
palette?: SanityImagePalette;
lqip?: string;
blurHash?: string;
hasAlpha?: boolean;
isOpaque?: boolean;
_type: \\"sanity.imageMetadata\\";
};
export type SanityImageDimensions = {
height?: number;
width?: number;
aspectRatio?: number;
_type: \\"sanity.imageDimensions\\";
};
export type SanityImagePalette = {
darkMuted?: SanityImagePaletteSwatch;
lightVibrant?: SanityImagePaletteSwatch;
darkVibrant?: SanityImagePaletteSwatch;
vibrant?: SanityImagePaletteSwatch;
dominant?: SanityImagePaletteSwatch;
lightMuted?: SanityImagePaletteSwatch;
muted?: SanityImagePaletteSwatch;
_type: \\"sanity.imagePalette\\";
};
export type SanityImagePaletteSwatch = {
background?: string;
foreground?: string;
population?: number;
title?: string;
_type: \\"sanity.imagePaletteSwatch\\";
};"
`;

exports[`generateSchemaTypes should generate correct types for document schema with inline fields 1`] = `
"export type myObject = {
inlineField: {
test: string;
} & Test;
unknownObject: unknown;
arrayField: Array<string>;
unionField: {
test: string;
} | string | Test;
};"
`;
exports[`generateSchemaTypes should generate correct types for document schema with inline fields 2`] = `"export type someOtherType = MyObject;"`;
@@ -0,0 +1,22 @@
import assert from 'node:assert'
import path from 'node:path'

import {describe, expect, test} from '@jest/globals'

import {findQueriesInPath} from '../findQueriesInPath'

describe('findQueriesInPath', () => {
test('should throw an error if the query name already exists', async () => {
const stream = findQueriesInPath({
path: path.join(__dirname, 'fixtures', '{source1,source2}.ts'),
})
await stream.next()
const result = await stream.next()
if (!result.value) {
throw new Error('Expected to yield a result')
}
expect(result.value.type).toBe('error')
assert(result.value.type === 'error') // workaround for TS
expect(result.value.error.message).toMatch(/Duplicate query name found:/)
})
})

0 comments on commit f92f7b4

Please sign in to comment.