From 2c7236bfd192743562e6a3551247a4bac65d480d Mon Sep 17 00:00:00 2001 From: Rico Kahler Date: Wed, 4 Oct 2023 17:50:27 -0500 Subject: [PATCH] feat(cli): add CDR metadata to GraphQL json schema --- .../graphql/extractFromSanitySchema.ts | 45 ++- .../_internal/cli/actions/graphql/types.ts | 4 + .../__snapshots__/extract.test.ts.snap | 113 ++++++ .../graphql/__snapshots__/gen2.test.ts.snap | 332 +++++++++++++++++ .../graphql/__snapshots__/gen3.test.ts.snap | 334 +++++++++++++++++- .../test/cli/graphql/fixtures/test-studio.ts | 47 +++ 6 files changed, 872 insertions(+), 3 deletions(-) diff --git a/packages/sanity/src/_internal/cli/actions/graphql/extractFromSanitySchema.ts b/packages/sanity/src/_internal/cli/actions/graphql/extractFromSanitySchema.ts index 99163a5d949a..273748d65610 100644 --- a/packages/sanity/src/_internal/cli/actions/graphql/extractFromSanitySchema.ts +++ b/packages/sanity/src/_internal/cli/actions/graphql/extractFromSanitySchema.ts @@ -8,6 +8,7 @@ import type { ObjectSchemaType, ArraySchemaType, IntrinsicTypeName, + CrossDatasetReferenceSchemaType, } from '@sanity/types' import {generateHelpUrl} from '@sanity/generate-help-url' import {Schema} from '@sanity/schema' @@ -110,10 +111,43 @@ function isReference( return isType(typeDef, 'reference') } -function isCrossDatasetReference(typeDef: SchemaType) { +function isCrossDatasetReference( + typeDef: SchemaType | ObjectField | ObjectFieldType | CrossDatasetReferenceSchemaType, +) { return isType(typeDef, 'crossDatasetReference') } +function getCrossDatasetReferenceMetadata( + typeDef: SchemaType | ObjectField | ObjectFieldType | CrossDatasetReferenceSchemaType, +) { + if (!isCrossDatasetReference(typeDef)) return undefined + + function getTypeNames( + type: SchemaType | ObjectField | ObjectFieldType | CrossDatasetReferenceSchemaType | undefined, + ) { + if (!type) return undefined + if (!('to' in type)) return getTypeNames(type.type) + return type.to.map((t) => t.type).filter((t): t is string => typeof t === 'string') + } + + function getDataset( + type: SchemaType | ObjectField | ObjectFieldType | CrossDatasetReferenceSchemaType | undefined, + ) { + if (!type) return undefined + if ('dataset' in type && typeof type.dataset === 'string') return type.dataset + if (type.type) return getDataset(type.type) + return undefined + } + + const typeNames = getTypeNames(typeDef) + if (!typeNames) return undefined + + const dataset = getDataset(typeDef) + if (typeof dataset !== 'string') return undefined + + return {typeNames, dataset} +} + export function extractFromSanitySchema( sanitySchema: CompiledSchema, extractOptions: {nonNullDocumentFields?: boolean} = {}, @@ -228,7 +262,14 @@ export function extractFromSanitySchema( const gqlName = props.fieldName || mapped.name const originalName = type.name const original = gqlName === originalName ? {} : {originalName: originalName} - return {...props, ...mapped, ...original} + const crossDatasetReferenceMetadata = getCrossDatasetReferenceMetadata(type) + + return { + ...props, + ...mapped, + ...original, + ...(crossDatasetReferenceMetadata && {crossDatasetReferenceMetadata}), + } } function isField(def: SchemaType | ObjectField): def is ObjectField { diff --git a/packages/sanity/src/_internal/cli/actions/graphql/types.ts b/packages/sanity/src/_internal/cli/actions/graphql/types.ts index 179adfda9379..9bc8013edb35 100644 --- a/packages/sanity/src/_internal/cli/actions/graphql/types.ts +++ b/packages/sanity/src/_internal/cli/actions/graphql/types.ts @@ -45,6 +45,10 @@ export interface ConvertedType { interfaces?: string[] originalName?: string isReference?: boolean + crossDatasetReferenceMetadata?: { + dataset: string + typeNames: string[] + } } export interface ConvertedDocumentType extends ConvertedType { diff --git a/packages/sanity/test/cli/graphql/__snapshots__/extract.test.ts.snap b/packages/sanity/test/cli/graphql/__snapshots__/extract.test.ts.snap index 05f593d94440..db4b30933496 100644 --- a/packages/sanity/test/cli/graphql/__snapshots__/extract.test.ts.snap +++ b/packages/sanity/test/cli/graphql/__snapshots__/extract.test.ts.snap @@ -165,6 +165,51 @@ Object { "originalName": "block", "type": "Object", }, + Object { + "crossDatasetReferenceMetadata": Object { + "dataset": "production", + "typeNames": Array [ + "person", + ], + }, + "description": undefined, + "fields": Array [ + Object { + "description": undefined, + "fieldName": "_dataset", + "type": "String", + }, + Object { + "description": undefined, + "fieldName": "_key", + "type": "String", + }, + Object { + "description": undefined, + "fieldName": "_projectId", + "type": "String", + }, + Object { + "description": undefined, + "fieldName": "_ref", + "type": "String", + }, + Object { + "description": undefined, + "fieldName": "_type", + "type": "String", + }, + Object { + "description": undefined, + "fieldName": "_weak", + "type": "Boolean", + }, + ], + "kind": "Type", + "name": "CdrPersonReference", + "originalName": "cdrPersonReference", + "type": "Object", + }, Object { "description": undefined, "fields": Array [ @@ -339,6 +384,74 @@ Object { "originalName": "documentActionsTest", "type": "Object", }, + Object { + "description": undefined, + "fields": Array [ + Object { + "description": "Date the document was created", + "fieldName": "_createdAt", + "isNullable": true, + "type": "Datetime", + }, + Object { + "description": "Document ID", + "fieldName": "_id", + "isNullable": true, + "type": "ID", + }, + Object { + "description": undefined, + "fieldName": "_key", + "type": "String", + }, + Object { + "description": "Current document revision", + "fieldName": "_rev", + "isNullable": true, + "type": "String", + }, + Object { + "description": "Document type", + "fieldName": "_type", + "isNullable": true, + "type": "String", + }, + Object { + "description": "Date the document was last modified", + "fieldName": "_updatedAt", + "isNullable": true, + "type": "Datetime", + }, + Object { + "crossDatasetReferenceMetadata": Object { + "dataset": "production", + "typeNames": Array [ + "person", + "place", + ], + }, + "fieldName": "cdrFieldInline", + "type": "CrossDatasetReference", + }, + Object { + "crossDatasetReferenceMetadata": Object { + "dataset": "production", + "typeNames": Array [ + "person", + ], + }, + "fieldName": "cdrFieldNamed", + "type": "CdrPersonReference", + }, + ], + "interfaces": Array [ + "Document", + ], + "kind": "Type", + "name": "DocumentWithCdrField", + "originalName": "documentWithCdrField", + "type": "Object", + }, Object { "description": undefined, "fields": Array [ diff --git a/packages/sanity/test/cli/graphql/__snapshots__/gen2.test.ts.snap b/packages/sanity/test/cli/graphql/__snapshots__/gen2.test.ts.snap index 00c91ddb6c50..46d27d2c7696 100644 --- a/packages/sanity/test/cli/graphql/__snapshots__/gen2.test.ts.snap +++ b/packages/sanity/test/cli/graphql/__snapshots__/gen2.test.ts.snap @@ -109,6 +109,28 @@ Object { "fieldName": "DocumentActionsTest", "type": "DocumentActionsTest", }, + Object { + "args": Array [ + Object { + "description": "DocumentWithCdrField document ID", + "isNullable": false, + "name": "id", + "type": "ID", + }, + ], + "constraints": Array [ + Object { + "comparator": "eq", + "field": "_id", + "value": Object { + "argName": "id", + "kind": "argumentValue", + }, + }, + ], + "fieldName": "DocumentWithCdrField", + "type": "DocumentWithCdrField", + }, Object { "args": Array [ Object { @@ -259,6 +281,48 @@ Object { "kind": "List", }, }, + Object { + "args": Array [ + Object { + "description": "Max documents to return", + "isFieldFilter": false, + "name": "limit", + "type": "Int", + }, + Object { + "description": "Offset at which to start returning documents from", + "isFieldFilter": false, + "name": "offset", + "type": "Int", + }, + Object { + "name": "sort", + "type": Object { + "children": Object { + "isNullable": false, + "type": "DocumentWithCdrFieldSorting", + }, + "isNullable": true, + "kind": "List", + }, + }, + Object { + "isFieldFilter": true, + "name": "where", + "type": "DocumentWithCdrFieldFilter", + }, + ], + "fieldName": "allDocumentWithCdrField", + "filter": "_type == \\"documentWithCdrField\\"", + "type": Object { + "children": Object { + "isNullable": false, + "type": "DocumentWithCdrField", + }, + "isNullable": false, + "kind": "List", + }, + }, Object { "args": Array [ Object { @@ -635,6 +699,117 @@ Object { "kind": "InputObject", "name": "BooleanFilter", }, + Object { + "crossDatasetReferenceMetadata": Object { + "dataset": "production", + "typeNames": Array [ + "person", + ], + }, + "description": undefined, + "fields": Array [ + Object { + "description": undefined, + "fieldName": "_dataset", + "type": "String", + }, + Object { + "description": undefined, + "fieldName": "_key", + "type": "String", + }, + Object { + "description": undefined, + "fieldName": "_projectId", + "type": "String", + }, + Object { + "description": undefined, + "fieldName": "_ref", + "type": "String", + }, + Object { + "description": undefined, + "fieldName": "_type", + "type": "String", + }, + Object { + "description": undefined, + "fieldName": "_weak", + "type": "Boolean", + }, + ], + "kind": "Type", + "name": "CdrPersonReference", + "originalName": "cdrPersonReference", + "type": "Object", + }, + Object { + "fields": Array [ + Object { + "fieldName": "_dataset", + "isReference": undefined, + "type": "StringFilter", + }, + Object { + "fieldName": "_key", + "isReference": undefined, + "type": "StringFilter", + }, + Object { + "fieldName": "_projectId", + "isReference": undefined, + "type": "StringFilter", + }, + Object { + "fieldName": "_ref", + "isReference": undefined, + "type": "StringFilter", + }, + Object { + "fieldName": "_type", + "isReference": undefined, + "type": "StringFilter", + }, + Object { + "fieldName": "_weak", + "isReference": undefined, + "type": "BooleanFilter", + }, + ], + "kind": "InputObject", + "name": "CdrPersonReferenceFilter", + }, + Object { + "fields": Array [ + Object { + "fieldName": "_dataset", + "type": "SortOrder", + }, + Object { + "fieldName": "_key", + "type": "SortOrder", + }, + Object { + "fieldName": "_projectId", + "type": "SortOrder", + }, + Object { + "fieldName": "_ref", + "type": "SortOrder", + }, + Object { + "fieldName": "_type", + "type": "SortOrder", + }, + Object { + "fieldName": "_weak", + "type": "SortOrder", + }, + ], + "kind": "InputObject", + "name": "CdrPersonReferenceSorting", + }, Object { "description": undefined, "fields": Array [ @@ -1188,6 +1363,163 @@ Object { "kind": "InputObject", "name": "DocumentFilter", }, + Object { + "description": undefined, + "fields": Array [ + Object { + "description": "Date the document was created", + "fieldName": "_createdAt", + "isNullable": true, + "type": "Datetime", + }, + Object { + "description": "Document ID", + "fieldName": "_id", + "isNullable": true, + "type": "ID", + }, + Object { + "description": undefined, + "fieldName": "_key", + "type": "String", + }, + Object { + "description": "Current document revision", + "fieldName": "_rev", + "isNullable": true, + "type": "String", + }, + Object { + "description": "Document type", + "fieldName": "_type", + "isNullable": true, + "type": "String", + }, + Object { + "description": "Date the document was last modified", + "fieldName": "_updatedAt", + "isNullable": true, + "type": "Datetime", + }, + Object { + "crossDatasetReferenceMetadata": Object { + "dataset": "production", + "typeNames": Array [ + "person", + "place", + ], + }, + "fieldName": "cdrFieldInline", + "type": "CrossDatasetReference", + }, + Object { + "crossDatasetReferenceMetadata": Object { + "dataset": "production", + "typeNames": Array [ + "person", + ], + }, + "fieldName": "cdrFieldNamed", + "type": "CdrPersonReference", + }, + ], + "interfaces": Array [ + "Document", + ], + "kind": "Type", + "name": "DocumentWithCdrField", + "originalName": "documentWithCdrField", + "type": "Object", + }, + Object { + "fields": Array [ + Object { + "description": "Apply filters on document level", + "fieldName": "_", + "type": "DocumentFilter", + }, + Object { + "fieldName": "_createdAt", + "isReference": undefined, + "type": "DatetimeFilter", + }, + Object { + "fieldName": "_id", + "isReference": undefined, + "type": "IDFilter", + }, + Object { + "fieldName": "_key", + "isReference": undefined, + "type": "StringFilter", + }, + Object { + "fieldName": "_rev", + "isReference": undefined, + "type": "StringFilter", + }, + Object { + "fieldName": "_type", + "isReference": undefined, + "type": "StringFilter", + }, + Object { + "fieldName": "_updatedAt", + "isReference": undefined, + "type": "DatetimeFilter", + }, + Object { + "fieldName": "cdrFieldInline", + "isReference": undefined, + "type": "CrossDatasetReferenceFilter", + }, + Object { + "fieldName": "cdrFieldNamed", + "isReference": undefined, + "type": "CdrPersonReferenceFilter", + }, + ], + "kind": "InputObject", + "name": "DocumentWithCdrFieldFilter", + }, + Object { + "fields": Array [ + Object { + "fieldName": "_createdAt", + "type": "SortOrder", + }, + Object { + "fieldName": "_id", + "type": "SortOrder", + }, + Object { + "fieldName": "_key", + "type": "SortOrder", + }, + Object { + "fieldName": "_rev", + "type": "SortOrder", + }, + Object { + "fieldName": "_type", + "type": "SortOrder", + }, + Object { + "fieldName": "_updatedAt", + "type": "SortOrder", + }, + Object { + "fieldName": "cdrFieldInline", + "type": "CrossDatasetReferenceSorting", + }, + Object { + "fieldName": "cdrFieldNamed", + "type": "CdrPersonReferenceSorting", + }, + ], + "kind": "InputObject", + "name": "DocumentWithCdrFieldSorting", + }, Object { "description": undefined, "fields": Array [ diff --git a/packages/sanity/test/cli/graphql/__snapshots__/gen3.test.ts.snap b/packages/sanity/test/cli/graphql/__snapshots__/gen3.test.ts.snap index d92d717d036b..d6c0e7909552 100644 --- a/packages/sanity/test/cli/graphql/__snapshots__/gen3.test.ts.snap +++ b/packages/sanity/test/cli/graphql/__snapshots__/gen3.test.ts.snap @@ -109,6 +109,28 @@ Object { "fieldName": "DocumentActionsTest", "type": "DocumentActionsTest", }, + Object { + "args": Array [ + Object { + "description": "DocumentWithCdrField document ID", + "isNullable": false, + "name": "id", + "type": "ID", + }, + ], + "constraints": Array [ + Object { + "comparator": "eq", + "field": "_id", + "value": Object { + "argName": "id", + "kind": "argumentValue", + }, + }, + ], + "fieldName": "DocumentWithCdrField", + "type": "DocumentWithCdrField", + }, Object { "args": Array [ Object { @@ -249,7 +271,7 @@ Object { }, ], "fieldName": "allDocument", - "filter": "_type in [\\"sanity.imageAsset\\", \\"sanity.fileAsset\\", \\"documentActionsTest\\", \\"poppers\\", \\"author\\"]", + "filter": "_type in [\\"sanity.imageAsset\\", \\"sanity.fileAsset\\", \\"documentActionsTest\\", \\"poppers\\", \\"author\\", \\"documentWithCdrField\\"]", "type": Object { "children": Object { "isNullable": false, @@ -301,6 +323,48 @@ Object { "kind": "List", }, }, + Object { + "args": Array [ + Object { + "description": "Max documents to return", + "isFieldFilter": false, + "name": "limit", + "type": "Int", + }, + Object { + "description": "Offset at which to start returning documents from", + "isFieldFilter": false, + "name": "offset", + "type": "Int", + }, + Object { + "name": "sort", + "type": Object { + "children": Object { + "isNullable": false, + "type": "DocumentWithCdrFieldSorting", + }, + "isNullable": true, + "kind": "List", + }, + }, + Object { + "isFieldFilter": true, + "name": "where", + "type": "DocumentWithCdrFieldFilter", + }, + ], + "fieldName": "allDocumentWithCdrField", + "filter": "_type == \\"documentWithCdrField\\"", + "type": Object { + "children": Object { + "isNullable": false, + "type": "DocumentWithCdrField", + }, + "isNullable": false, + "kind": "List", + }, + }, Object { "args": Array [ Object { @@ -677,6 +741,117 @@ Object { "kind": "InputObject", "name": "BooleanFilter", }, + Object { + "crossDatasetReferenceMetadata": Object { + "dataset": "production", + "typeNames": Array [ + "person", + ], + }, + "description": undefined, + "fields": Array [ + Object { + "description": undefined, + "fieldName": "_dataset", + "type": "String", + }, + Object { + "description": undefined, + "fieldName": "_key", + "type": "String", + }, + Object { + "description": undefined, + "fieldName": "_projectId", + "type": "String", + }, + Object { + "description": undefined, + "fieldName": "_ref", + "type": "String", + }, + Object { + "description": undefined, + "fieldName": "_type", + "type": "String", + }, + Object { + "description": undefined, + "fieldName": "_weak", + "type": "Boolean", + }, + ], + "kind": "Type", + "name": "CdrPersonReference", + "originalName": "cdrPersonReference", + "type": "Object", + }, + Object { + "fields": Array [ + Object { + "fieldName": "_dataset", + "isReference": undefined, + "type": "StringFilter", + }, + Object { + "fieldName": "_key", + "isReference": undefined, + "type": "StringFilter", + }, + Object { + "fieldName": "_projectId", + "isReference": undefined, + "type": "StringFilter", + }, + Object { + "fieldName": "_ref", + "isReference": undefined, + "type": "StringFilter", + }, + Object { + "fieldName": "_type", + "isReference": undefined, + "type": "StringFilter", + }, + Object { + "fieldName": "_weak", + "isReference": undefined, + "type": "BooleanFilter", + }, + ], + "kind": "InputObject", + "name": "CdrPersonReferenceFilter", + }, + Object { + "fields": Array [ + Object { + "fieldName": "_dataset", + "type": "SortOrder", + }, + Object { + "fieldName": "_key", + "type": "SortOrder", + }, + Object { + "fieldName": "_projectId", + "type": "SortOrder", + }, + Object { + "fieldName": "_ref", + "type": "SortOrder", + }, + Object { + "fieldName": "_type", + "type": "SortOrder", + }, + Object { + "fieldName": "_weak", + "type": "SortOrder", + }, + ], + "kind": "InputObject", + "name": "CdrPersonReferenceSorting", + }, Object { "description": undefined, "fields": Array [ @@ -1275,6 +1450,163 @@ Object { "kind": "InputObject", "name": "DocumentSorting", }, + Object { + "description": undefined, + "fields": Array [ + Object { + "description": "Date the document was created", + "fieldName": "_createdAt", + "isNullable": true, + "type": "Datetime", + }, + Object { + "description": "Document ID", + "fieldName": "_id", + "isNullable": true, + "type": "ID", + }, + Object { + "description": undefined, + "fieldName": "_key", + "type": "String", + }, + Object { + "description": "Current document revision", + "fieldName": "_rev", + "isNullable": true, + "type": "String", + }, + Object { + "description": "Document type", + "fieldName": "_type", + "isNullable": true, + "type": "String", + }, + Object { + "description": "Date the document was last modified", + "fieldName": "_updatedAt", + "isNullable": true, + "type": "Datetime", + }, + Object { + "crossDatasetReferenceMetadata": Object { + "dataset": "production", + "typeNames": Array [ + "person", + "place", + ], + }, + "fieldName": "cdrFieldInline", + "type": "CrossDatasetReference", + }, + Object { + "crossDatasetReferenceMetadata": Object { + "dataset": "production", + "typeNames": Array [ + "person", + ], + }, + "fieldName": "cdrFieldNamed", + "type": "CdrPersonReference", + }, + ], + "interfaces": Array [ + "Document", + ], + "kind": "Type", + "name": "DocumentWithCdrField", + "originalName": "documentWithCdrField", + "type": "Object", + }, + Object { + "fields": Array [ + Object { + "description": "Apply filters on document level", + "fieldName": "_", + "type": "Sanity_DocumentFilter", + }, + Object { + "fieldName": "_createdAt", + "isReference": undefined, + "type": "DatetimeFilter", + }, + Object { + "fieldName": "_id", + "isReference": undefined, + "type": "IDFilter", + }, + Object { + "fieldName": "_key", + "isReference": undefined, + "type": "StringFilter", + }, + Object { + "fieldName": "_rev", + "isReference": undefined, + "type": "StringFilter", + }, + Object { + "fieldName": "_type", + "isReference": undefined, + "type": "StringFilter", + }, + Object { + "fieldName": "_updatedAt", + "isReference": undefined, + "type": "DatetimeFilter", + }, + Object { + "fieldName": "cdrFieldInline", + "isReference": undefined, + "type": "CrossDatasetReferenceFilter", + }, + Object { + "fieldName": "cdrFieldNamed", + "isReference": undefined, + "type": "CdrPersonReferenceFilter", + }, + ], + "kind": "InputObject", + "name": "DocumentWithCdrFieldFilter", + }, + Object { + "fields": Array [ + Object { + "fieldName": "_createdAt", + "type": "SortOrder", + }, + Object { + "fieldName": "_id", + "type": "SortOrder", + }, + Object { + "fieldName": "_key", + "type": "SortOrder", + }, + Object { + "fieldName": "_rev", + "type": "SortOrder", + }, + Object { + "fieldName": "_type", + "type": "SortOrder", + }, + Object { + "fieldName": "_updatedAt", + "type": "SortOrder", + }, + Object { + "fieldName": "cdrFieldInline", + "type": "CrossDatasetReferenceSorting", + }, + Object { + "fieldName": "cdrFieldNamed", + "type": "CdrPersonReferenceSorting", + }, + ], + "kind": "InputObject", + "name": "DocumentWithCdrFieldSorting", + }, Object { "description": undefined, "fields": Array [ diff --git a/packages/sanity/test/cli/graphql/fixtures/test-studio.ts b/packages/sanity/test/cli/graphql/fixtures/test-studio.ts index a994917d1093..5b5589b519a3 100644 --- a/packages/sanity/test/cli/graphql/fixtures/test-studio.ts +++ b/packages/sanity/test/cli/graphql/fixtures/test-studio.ts @@ -646,5 +646,52 @@ export default Schema.compile({ }, ], }, + { + title: 'Person in another dataset', + name: 'cdrPersonReference', + type: 'crossDatasetReference', + dataset: 'production', + to: [ + { + type: 'person', + preview: { + select: { + title: 'name', + media: 'image', + }, + }, + }, + ], + }, + { + title: 'Document with CDR Field', + name: 'documentWithCdrField', + type: 'document', + fields: [ + { + name: 'cdrFieldInline', + type: 'crossDatasetReference', + dataset: 'production', + to: [ + { + type: 'person', + preview: { + select: {title: 'name'}, + }, + }, + { + type: 'place', + preview: { + select: {title: 'name'}, + }, + }, + ], + }, + { + name: 'cdrFieldNamed', + type: 'cdrPersonReference', + }, + ], + }, ], })