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(core): Global Document References support #8299

Open
wants to merge 32 commits into
base: next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
ed11fd4
feat: add support for global document reference type
sgulseth Jan 6, 2025
b38d623
feat: add validation for global document references
sgulseth Jan 8, 2025
072cf94
wip: add global document references default input component
sgulseth Jan 8, 2025
5297eb3
fixup! feat: add support for global document reference type
sgulseth Jan 13, 2025
ee1d896
chore(test-studio): add staging config and gdr schema
sgulseth Jan 13, 2025
3f9f602
fix: gdr should not be part of reference check
sgulseth Jan 13, 2025
5b72d36
fix(gdr): fix preview component
sgulseth Jan 13, 2025
5c0cf8e
fix(core): fix typing-issues related to GlobalDocumentReferenceInput
skogsmaskin Jan 16, 2025
009c441
refactor(types): globalDocumentReference format to use ':' instead of…
skogsmaskin Jan 30, 2025
7aa028b
refactor(core): globalDocumentReference format to use ':' instead of '/'
skogsmaskin Jan 30, 2025
710b464
refactor(test-studio): globalDocumentReference format to use ':' inst…
skogsmaskin Jan 30, 2025
0d5bcff
fix(validation): add globalDocumentReference as valid built-in object…
skogsmaskin Feb 13, 2025
22464be
fix(cli): add exception for globalDocumentReference like with crossDa…
skogsmaskin Feb 13, 2025
3d14209
test(cli): update snapshots
skogsmaskin Feb 13, 2025
796f065
test(core): update GDR input test with new ref-format
skogsmaskin Feb 13, 2025
a08e56c
fix(core): fix GDR integration for asset libraries
skogsmaskin Mar 5, 2025
1fabcad
fix(core): fix naming of reference type to be global
skogsmaskin Mar 5, 2025
a2a4992
doc(types): add global document _ref format description to type
skogsmaskin Mar 5, 2025
d71a940
fix(core): rename translation key for consistency
skogsmaskin Mar 5, 2025
ecee998
fix(core): clean up apiVersion and hardcoded hostname for GDR client …
skogsmaskin Mar 6, 2025
ff5bc1b
fix(core): restore apiVersion on studioClient
skogsmaskin Mar 6, 2025
4a69bac
doc(core): update comment
skogsmaskin Mar 6, 2025
97ec594
test(core): support @testing-library DOM matcher types in vitest
skogsmaskin Mar 6, 2025
8e5d301
test(core): move test into __tests__ folder and fix value type
skogsmaskin Mar 6, 2025
bd325f9
doc(core): add note about refactoring similar files for useReferenceI…
skogsmaskin Mar 6, 2025
5b8ba17
fix(core): bump document pair action api min version
skogsmaskin Mar 6, 2025
b390c81
fix(core): pin GDR api versions and hosts to the current availability
skogsmaskin Mar 6, 2025
5a54d81
test(core): skip test based off crossdataset ref test that is also sk…
skogsmaskin Mar 6, 2025
39db37e
refactor(core): rename from asset-library to media-library'
skogsmaskin Mar 11, 2025
41bead8
refactor(schema): rename from asset-library to media-library'
skogsmaskin Mar 11, 2025
d332115
refactor(types): rename from asset-library to media-library'
skogsmaskin Mar 11, 2025
3478423
refactor(schema): improve GDR resource validator
skogsmaskin Mar 11, 2025
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
12 changes: 12 additions & 0 deletions dev/test-studio/sanity.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,18 @@ export default defineConfig([
enabled: true,
},
},
{
name: 'playground-staging',
title: 'playground (Staging)',
projectId: 'exx11uqh',
dataset: 'playground',
plugins: [sharedSettings()],
basePath: '/playground-staging',
apiHost: 'https://api.sanity.work',
auth: {
loginMethod: 'token',
},
},
{
name: 'custom-components',
title: 'Test Studio',
Expand Down
5 changes: 5 additions & 0 deletions dev/test-studio/schema/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ import date from './standard/date'
import datetime from './standard/datetime'
import emails from './standard/emails'
import files from './standard/files'
import globalDocumentReference, {
globalDocumentReferenceSubtype,
} from './standard/globalDocumentReference'
import images, {myImage} from './standard/images'
import numbers from './standard/numbers'
import objects, {myObject} from './standard/objects'
Expand Down Expand Up @@ -289,6 +292,8 @@ export const schemaTypes = [
conditionalFieldset,
crossDatasetReference,
crossDatasetSubtype,
globalDocumentReference,
globalDocumentReferenceSubtype,
fieldGroupsWithFieldsets,
ptReference,
validationTest,
Expand Down
206 changes: 206 additions & 0 deletions dev/test-studio/schema/standard/globalDocumentReference.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
import {BookIcon, MoonIcon, UserIcon} from '@sanity/icons'
import {defineType} from 'sanity'

export const globalDocumentReferenceSubtype = defineType({
type: 'globalDocumentReference',
name: 'globalDocumentSubtype',
title: 'Subtype of global document references',
resourceType: 'dataset',
resourceId: 'exx11uqh.blog',
to: [
{
type: 'book',
icon: BookIcon,
preview: {
select: {
title: 'title',
media: 'coverImage',
},
prepare(val) {
return {
title: val.title,
media: val.coverImage,
}
},
},
},
],
})

export default defineType({
name: 'globalDocumentReferenceTest',
type: 'document',
title: 'Global document reference test',
description: 'Test cases for global document references',
icon: MoonIcon,
fields: [
{name: 'title', type: 'string'},
{
name: 'bookInPlayground',
title: 'Reference to book in the "playground" dataset',
type: 'globalDocumentReference',
resourceType: 'dataset',
resourceId: 'exx11uqh.blog',
studioUrl: ({id, type}) => {
return type
? `${document.location.protocol}//${document.location.host}/playground/content/${type};${id}`
: null
},
to: [
{
type: 'book',
icon: BookIcon,
preview: {
select: {
title: 'title',
subtitle: 'descriptionMd',
media: 'coverImage',
},
prepare(val) {
return {
title: val.title,
subtitle: val.subtitle,
media: val.coverImage,
}
},
},
},
],
},
{
title: 'Reference to book or author in the "playground" dataset',
name: 'bookOrAuthorInPlayground',
type: 'globalDocumentReference',
resourceType: 'dataset',
resourceId: 'exx11uqh.blog',
weak: true,
studioUrl: ({id, type}) => {
return type
? `${document.location.protocol}//${document.location.host}/playground/content/${type};${id}`
: null
},
to: [
{
type: 'book',
icon: BookIcon,
preview: {
select: {
title: 'title',
subtitle: 'descriptionMd',
coverImage: 'coverImage',
},
prepare(val) {
return {
title: val.title,
subtitle: val.subtitle,
media: val.coverImage,
}
},
},
},
{
type: 'author',
icon: UserIcon,
preview: {
select: {
title: 'name',
},
prepare(val) {
return {
title: val.title,
media: val.media,
}
},
},
},
],
},
{
title: 'GDR in PTE',
name: 'portableText',
type: 'array',
of: [
{type: 'block'},
{
title: 'GDR subtype test',
name: 'globalDocumentSubtype',
type: 'globalDocumentSubtype',
},
],
},
{
title: 'GDR in array',
name: 'array',
type: 'array',
of: [
{
title: 'GDR subtype test',
name: 'globalDocumentSubtype',
type: 'globalDocumentSubtype',
},
],
},
{
title: 'GDR subtype test',
name: 'globalDocumentSubtype',
type: 'globalDocumentSubtype',
},
{
name: 'initialValueTest',
type: 'globalDocumentReference',
resourceType: 'dataset',
resourceId: 'exx11uqh.blog',
studioUrl: ({id, type}) => {
return type
? `${document.location.protocol}//${document.location.host}/playground/content/${type};${id}`
: null
},
to: [
{
type: 'book',
icon: BookIcon,
preview: {
select: {
title: 'title',
subtitle: 'descriptionMd',
media: 'coverImage',
},
prepare(val) {
return {
title: val.title,
subtitle: val.subtitle,
media: val.coverImage,
}
},
},
},
],
initialValue: () => ({
_type: 'reference',
_ref: 'dataset:exx11uqh.blog:4203c6bd-98c2-418e-9558-3ed56ebaf1d8',
_weak: true,
}),
},
],
preview: {
select: {
title: 'title',
authorRefName: 'bookOrAuthorInPlayground.name',
authorBff: 'bookOrAuthorInPlayground.bestFriend.name',
bookRefTitle: 'bookOrAuthorInPlayground.title',
},
prepare(values) {
return {
title: values.title,
subtitle: [
values.authorRefName
? `Author: ${values.authorRefName} (${`Bff: ${values.authorBff || 'none'}`})`
: '',
values.bookRefTitle ? `Book title: ${values.bookRefTitle}` : '',
]
.filter(Boolean)
.join(', '),
}
},
},
})
1 change: 1 addition & 0 deletions dev/test-studio/structure/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const STANDARD_INPUT_TYPES = [
'stringsTest',
'textsTest',
'urlsTest',
'globalDocumentReferenceTest',
]

export const STANDARD_PORTABLE_TEXT_INPUT_TYPES = [
Expand Down
107 changes: 107 additions & 0 deletions packages/@sanity/schema/src/legacy/types/globalDocumentReference.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import arrify from 'arrify'
import {pick} from 'lodash'

import {DEFAULT_OVERRIDEABLE_FIELDS} from './constants'
import {lazyGetter} from './utils'

export const REF_FIELD = {
name: '_ref',
title: 'Referenced document ID',
type: 'string',
}

export const WEAK_FIELD = {
name: '_weak',
title: 'Weak reference',
type: 'boolean',
}

const REFERENCE_FIELDS = [REF_FIELD, WEAK_FIELD]

const OVERRIDABLE_FIELDS = [...DEFAULT_OVERRIDEABLE_FIELDS]

const GLOBAL_DOCUMENT_REFERENCE_CORE = {
name: 'globalDocumentReference',
title: 'Global Document Reference',
type: null,
jsonType: 'object',
}

function humanize(arr: any, conjunction: any) {
const len = arr.length
if (len === 1) {
return arr[0]
}
const first = arr.slice(0, len - 1)
const last = arr[len - 1]
return `${first.join(', ')} ${conjunction} ${last}`
}

function buildTitle(type: any) {
if (!type.to || type.to.length === 0) {
return 'Global Document Reference'
}
return `Global Document Reference to ${humanize(
arrify(type.to).map((toType: any) => toType.title),
'or',
).toLowerCase()}`
}

export const GlobalDocumentReferenceType = {
get() {
return GLOBAL_DOCUMENT_REFERENCE_CORE
},
extend(subTypeDef: any, createMemberType: any) {
if (!subTypeDef.to) {
throw new Error(
`Missing "to" field in global document reference definition. Check the type ${subTypeDef.name}`,
)
}
const parsed = Object.assign(
pick(GLOBAL_DOCUMENT_REFERENCE_CORE, OVERRIDABLE_FIELDS),
subTypeDef,
{
type: GLOBAL_DOCUMENT_REFERENCE_CORE,
},
)

lazyGetter(parsed, 'fields', () => {
return REFERENCE_FIELDS.map((fieldDef) => {
const {name, ...type} = fieldDef
return {
name: name,
type: createMemberType(type),
}
})
})

lazyGetter(parsed, 'to', () => {
return arrify(subTypeDef.to).map((toType: any) => {
return {
...toType,
}
})
})

lazyGetter(parsed, 'title', () => subTypeDef.title || buildTitle(parsed))

return subtype(parsed)

function subtype(parent: any) {
return {
get() {
return parent
},
extend: (extensionDef: any) => {
if (extensionDef.of) {
throw new Error('Cannot override `of` of subtypes of "globalDocumentReference"')
}
const current = Object.assign({}, parent, pick(extensionDef, OVERRIDABLE_FIELDS), {
type: parent,
})
return subtype(current)
},
}
}
},
}
1 change: 1 addition & 0 deletions packages/@sanity/schema/src/legacy/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export {DateTimeType as datetime} from './datetime'
export {DocumentType as document} from './document'
export {EmailType as email} from './email'
export {FileType as file} from './file'
export {GlobalDocumentReferenceType as globalDocumentReference} from './globalDocumentReference'
export {ImageType as image} from './image'
export {NumberType as number} from './number'
export {ObjectType as object} from './object'
Expand Down
1 change: 1 addition & 0 deletions packages/@sanity/schema/src/sanity/coreTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const coreTypes = [
{name: 'object', jsonType: 'object', type: 'type'},
{name: 'reference', jsonType: 'object', type: 'type'},
{name: 'crossDatasetReference', jsonType: 'object', type: 'type'},
{name: 'globalDocumentReference', jsonType: 'object', type: 'type'},
{name: 'slug', jsonType: 'object', type: 'type'},
{name: 'span', jsonType: 'object', type: 'type'},
{name: 'string', jsonType: 'string', type: 'type'},
Expand Down
8 changes: 8 additions & 0 deletions packages/@sanity/schema/src/sanity/extractSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,11 @@ export function extractSchema(
return {type: 'unknown'} satisfies UnknownTypeNode // we don't support cross-dataset references at the moment
}

// Global document references are not supported
if (isGlobalDocumentReferenceType(schemaType)) {
return {type: 'unknown'} satisfies UnknownTypeNode // we don't support global document references at the moment
}

if (isReferenceType(schemaType)) {
return createReferenceTypeNodeDefintion(schemaType)
}
Expand Down Expand Up @@ -404,6 +409,9 @@ function isReferenceType(typeDef: SanitySchemaType): typeDef is ReferenceSchemaT
function isCrossDatasetReferenceType(typeDef: SanitySchemaType) {
return isType(typeDef, 'crossDatasetReference')
}
function isGlobalDocumentReferenceType(typeDef: SanitySchemaType) {
return isType(typeDef, 'globalDocumentReference')
}
function isStringType(typeDef: SanitySchemaType): typeDef is StringSchemaType {
return isType(typeDef, 'string')
}
Expand Down
Loading
Loading