sanity-singletons
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSanity Singletons
Sanity Singleton 文档
A "singleton" is a document with a fixed id that can be created exactly once. Common examples: site settings, navigation, footer content. Studio supports singletons as a first-class primitive via the configuration registry plus a small set of Structure Tool helpers.
document.singletonsRequires 6.17.0 or later. Check the installed version in the lockfile before using this API. On older Studios, either upgrade first or use the userland pattern (fixed in a custom structure, plus manual and filtering) described in → .
sanitydocumentIdnewDocumentOptionsduplicatesanity-best-practicesstudio-structure“singleton” 是具有固定 id 且只能创建一次的文档。常见示例包括站点设置、导航和页脚内容。Studio 通过 配置注册表以及一组 Structure Tool helper,将 singleton 作为 first-class primitive 提供支持。
document.singletons需要 6.17.0 或更高版本。 使用此 API 前,请检查 lockfile 中安装的版本。在较旧的 Studio 上,应先升级,或使用 → 中所述的 userland 模式(在自定义 structure 中使用固定 ,并手动过滤 和 )。
sanitysanity-best-practicesstudio-structuredocumentIdnewDocumentOptionsduplicateWhen to use this skill
何时使用此 skill
- A developer asks how to create a "settings document" or "singleton".
- A studio configuration needs a registry entry.
document.singletons - Structure Tool needs to render a singleton as a list item or document pane.
- You're migrating an existing userland singleton implementation to the first-class API.
- You're migrating from a third-party singleton plugin such as (or its predecessor
sanity-plugin-singleton-management).sanity-plugin-singleton-tools
- 开发者询问如何创建“settings document”或“singleton”。
- Studio 配置需要添加一个 registry entry。
document.singletons - Structure Tool 需要将 singleton 呈现为列表项或文档窗格。
- 正在将现有的 userland singleton 实现迁移到 first-class API。
- 正在从第三方 singleton 插件(如 或其前身
sanity-plugin-singleton-management)迁移。sanity-plugin-singleton-tools
Registering a singleton
注册 singleton
Singletons are registered in configuration, not on the schema type. A singleton definition binds a definition id to a document id and a schema type:
ts
import {defineConfig, defineSingleton} from 'sanity'
export default defineConfig({
schema: {
types: [/* siteSettings and campaign are ordinary document types */],
},
document: {
singletons: [
// String shorthand — expands to
// {id: 'siteSettings', documentId: 'siteSettings', schemaType: 'siteSettings'}
'siteSettings',
// Definition object. `defineSingleton` is an optional typed identity
// helper; a plain object literal works too. `id` is omitted here, so it
// inherits each `documentId`.
defineSingleton({
documentId: 'springCampaign',
schemaType: 'campaign',
title: 'Spring campaign', // optional display metadata
initialValue: {season: 'spring'}, // optional per-singleton initial value
}),
defineSingleton({
documentId: 'summerCampaign',
schemaType: 'campaign',
title: 'Summer campaign',
initialValue: {season: 'summer'},
}),
],
},
})Key facts:
- produces a singleton definition, not a document schema. The schema type it references is defined separately with
defineSingletonand needs no singleton-specific configuration.defineType - Multiple singletons may share a schema type (like the two campaigns above), each with its own ,
title, andicon(falling back to the schema type's), and a shared schema type may also back ordinary documents.initialValue - The definition id is the singleton's stable identity, and it is optional — it inherits when omitted. Structure code references it (
documentId). Set it explicitly only to be verbose, to guard against future collisions, or to address a singleton universally when different workspaces or environments map it to different document ids.S.listItem().singleton('springCampaign') - A resolver function is also accepted: . Resolvers only ever receive fully resolved definitions (string shorthands are expanded first).
singletons: (prev, context) => [...prev, ...]
Validation at config-resolution time (all failures aggregate into one ):
ConfigResolutionError- : non-empty, unique across definitions (inherited ids count — an explicit id may not collide with another definition's inherited one). Used verbatim as a Structure Tool node id, so it is limited to
idand may not start with[a-zA-Z0-9._-]. It also may not match the name of a document type that no singleton claims, since the default content list keys both by id (the string shorthand never trips this — the type it names is claimed by the definition itself).__edit__ - : non-empty, unique, published-id shaped (no
documentId/drafts.prefix, onlyversions.).[a-zA-Z0-9._-] - : must name an existing document type. Need not be unique.
schemaType - Templates: an untagged template must not reuse a definition id (the generated singleton template claims it); at most one template may carry a given tag; tags must reference registered definitions.
singleton
Singleton 在 configuration 中注册,而不是在 schema type 上注册。singleton definition 将 definition id 绑定到 document id 和 schema type:
ts
import {defineConfig, defineSingleton} from 'sanity'
export default defineConfig({
schema: {
types: [/* siteSettings and campaign are ordinary document types */],
},
document: {
singletons: [
// String shorthand — expands to
// {id: 'siteSettings', documentId: 'siteSettings', schemaType: 'siteSettings'}
'siteSettings',
// Definition object. `defineSingleton` is an optional typed identity
// helper; a plain object literal works too. `id` is omitted here, so it
// inherits each `documentId`.
defineSingleton({
documentId: 'springCampaign',
schemaType: 'campaign',
title: 'Spring campaign', // optional display metadata
initialValue: {season: 'spring'}, // optional per-singleton initial value
}),
defineSingleton({
documentId: 'summerCampaign',
schemaType: 'campaign',
title: 'Summer campaign',
initialValue: {season: 'summer'},
}),
],
},
})关键事实:
- 生成的是 singleton definition,而不是 document schema。 它引用的 schema type 需要通过
defineSingleton单独定义,并且不需要任何 singleton 专用配置。defineType - 多个 singleton 可以共享同一个 schema type(如上述两个 campaign),每个 singleton 都有自己的 、
title和icon(未设置时回退到 schema type 的值),同一个 schema type 也可以同时支持普通文档。initialValue - definition id 是 singleton 的稳定标识,且为可选——省略时会继承 。Structure 代码通过它进行引用(
documentId)。只有在需要显式定义、防止未来发生冲突,或需要在不同 workspace 或 environment 中将 singleton 映射到不同 document id 时,才应显式设置。S.listItem().singleton('springCampaign') - 也可以传入 resolver function:。Resolver 只会收到完全解析后的 definitions(字符串 shorthand 会先被展开)。
singletons: (prev, context) => [...prev, ...]
在解析 configuration 时会执行以下验证(所有失败都会聚合到一个 中):
ConfigResolutionError- :不能为空,且必须在所有 definitions 中保持唯一(包括继承的 id——显式 id 不能与另一个 definition 继承的 id 冲突)。它会原样用作 Structure Tool 节点 id,因此仅允许使用
id,且不能以[a-zA-Z0-9._-]开头。它也不能与未被任何 singleton 声明的 document type 名称相同,因为默认内容列表同时使用 id 作为键(字符串 shorthand 不会触发此问题,因为它所命名的 type 已被该 definition 声明)。__edit__ - :不能为空,必须唯一,并且必须符合 published-id 格式(不能带有
documentId或drafts.前缀,只能使用versions.)。[a-zA-Z0-9._-] - :必须引用现有的 document type,但无需唯一。
schemaType - Templates:未带 tag 的 template 不能复用 definition id;每个 tag 最多只能由一个 template 携带;tag 必须引用已注册的 definition。
singleton
What Studio does automatically
Studio 会自动完成的工作
- Generates a dedicated initial value template per singleton — tagged with the definition id via , value from
ResolvedTemplate.singleton— instead of the plain per-type template, and removes tagged templates from every "create new" surface (global create menu, structure panes, reference inputs). The tagged template stays indefinition.initialValue ?? schemaType.initialValue, so opening the singleton before it exists still applies its initial value.source.templates - Injects (the definition id) into document-scoped configuration contexts —
context.singleton,document.actions,badges, field actions,inspectors,comments.enabled— looked up by published document id, so drafts and release versions of the singleton match, however the document was opened (structure, intent, deep link, search).askToEdit.enabled - Filters the document action, after all user resolvers run, so it cannot be reintroduced via
duplicate.document.actions - Hides the schema type from the implicit default content list in Structure Tool, and appends the singleton itself to that list — one item per definition, after the document type lists, in registration order, each equivalent to . A studio that has not configured Structure Tool needs no structure code at all. This applies only to the default structure; a
S.listItem().singleton(id)resolver replaces it wholesale.structure
What Studio deliberately does not do:
- Delete, unpublish, and discard stay available. Deleting a singleton is a legitimate "reset": structure still points at the fixed id, and editing recreates the document. To hide delete as well: .
document: {actions: (prev, context) => (context.singleton ? prev.filter((action) => action.action !== 'delete') : prev)} - Explicit structure is never filtered. works for singleton schema types and intentionally lists the singleton documents alongside ordinary ones.
S.documentTypeList(typeName) - No warning for "dangling" singletons. Structure resolves lazily, so Studio cannot detect a registered singleton that a custom structure never adds. (The default structure adds them all, so this only affects studios with a resolver.) Any heuristic short of eager resolution would misfire, because manual
structurewiring is supported. In a custom structure, always pair a registry entry with a structure entry.S.document().documentId(...).schemaType(...)
- 为每个 singleton 生成专用的初始值 template——通过 使用 definition id 作为 tag,值取自
ResolvedTemplate.singleton,而不是普通的 per-type template;同时会从所有“create new”入口中移除带 tag 的 templates(全局创建菜单、structure pane、reference input)。带 tag 的 template 仍保留在definition.initialValue ?? schemaType.initialValue中,因此在 singleton 尚不存在时打开它,仍会应用其初始值。source.templates - 将 (definition id)注入 document-scoped configuration contexts——
context.singleton、document.actions、badges、field actions、inspectors、comments.enabled。查找依据是已发布文档的 id,因此无论通过何种方式打开文档(structure、intent、deep link、search),singleton 的 draft 和 release version 都能正确匹配。askToEdit.enabled - 在所有 user resolver 运行完毕后过滤 document action,因此无法通过
duplicate重新引入该 action。document.actions - 在 Structure Tool 中将 schema type 从隐式默认内容列表中隐藏,并将 singleton 自身追加到该列表——每个 definition 对应一个条目,位于 document type 列表之后并按注册顺序排列,每个条目都等同于 。未配置 Structure Tool 的 Studio 完全不需要编写 structure 代码。此行为仅适用于默认 structure;
S.listItem().singleton(id)resolver 会完全替换默认 structure。structure
Studio 刻意不会执行以下操作:
- Delete、unpublish 和 discard 操作仍然可用。 删除 singleton 是一种合法的“重置”:structure 仍指向固定 id,再次编辑时会重新创建文档。如需同时隐藏 delete:。
document: {actions: (prev, context) => (context.singleton ? prev.filter((action) => action.action !== 'delete') : prev)} - 显式 structure 永远不会被过滤。 可用于 singleton schema type,并会有意将 singleton 文档与普通文档一起列出。
S.documentTypeList(typeName) - 不会对“悬空”的 singleton 发出警告。 Structure 是惰性解析的,因此 Studio 无法检测到已注册但自定义 structure 从未添加的 singleton。(默认 structure 会添加全部 singleton,因此这只影响使用 resolver 的 Studio。)任何不够 eager resolution 的启发式方案都会产生误判,因为手动
structure接线受到支持。在自定义 structure 中,始终应将 registry entry 与 structure entry 配对。S.document().documentId(...).schemaType(...)
Surfacing singletons in Structure Tool
在 Structure Tool 中呈现 singleton
With the default structure there is nothing to do — registered singletons are appended to the top-level content list automatically.
In a custom structure (any studio passing a resolver to ), add them explicitly. All helpers are keyed by definition id and throw a for unknown ids.
structurestructureTool()SerializeErrorWatch for this trap: , the usual way to reproduce the default lists inside a custom structure, excludes singleton schema types and does not add singleton items. therefore drops every singleton. Use alongside it:
S.documentTypeListItems()S.list().items([...S.documentTypeListItems()]).singletons()ts
S.list().id('__root__').title('Content').items(S.documentTypeListItems()).singletons()ts
// 1. Highest level: a list of singletons — a given set, or all of them.
S.list().id('singletons').title('Singletons').singletons(['siteSettings', 'springCampaign'])
S.list().id('singletons').title('Singletons').singletons()
// 2. A single list item (title/icon default from the definition, then the schema type).
S.listItem().singleton('siteSettings')
// 3. Low level: just the document pane.
S.listItem().title('Settings').id('settings').child(S.document().singleton('siteSettings'))Composition rules:
- Every default is overridable by normal chaining: ,
S.listItem().singleton('siteSettings').title('Global settings').S.document().singleton('siteSettings').documentId('override') - Titles are not disambiguated for you. The list item id defaults to the definition id (unique by construction), but the title falls back to the schema type's, so singletons sharing a schema type share a label. Give each definition a — it applies everywhere the singleton is rendered, including
title, which has no per-item overrides.S.list().singletons() - pins the singleton's tagged initial value template so its initial value applies even when the type has several templates; override with
S.document().singleton()..initialValueTemplate(...) - returns a builder without
S.list().singletons(). Calling.items()afterwards would replace the whole array and silently drop the singleton items, so the type forbids it. Call.items()before.items([...]), or put.singletons([...])entries inside a regularS.listItem().singleton()array. Repeated.items()calls append..singletons() - with no argument means every registered definition (registration order, including plugin-registered ones);
singletons()means none. Combining it with a hand-writtensingletons([])in the same list adds that singleton twice and fails with a duplicate-idS.listItem().singleton(id)— pass an explicit array when mixing.SerializeError - renders a live document preview instead of a static title, and defaults its id to the definition's
S.documentListItem().singleton(id)(not the definition id), because a document list item's id is the document it previews. Prefer plaindocumentIdwhen the singleton document may not exist yet.S.listItem()
使用默认 structure 时无需任何操作——注册的 singleton 会自动追加到顶层内容列表。
在自定义 structure(任何向 传入 resolver 的 Studio)中,需要显式添加它们。所有 helper 均以 definition id 为键,遇到未知 id 时会抛出 。
structureTool()structureSerializeError请注意以下陷阱: 是在自定义 structure 中复现默认列表的常用方式,但它会排除 singleton schema type,且不会添加 singleton 项目。因此, 会移除所有 singleton。请同时使用 :
S.documentTypeListItems()S.list().items([...S.documentTypeListItems()]).singletons()ts
S.list().id('__root__').title('Content').items(S.documentTypeListItems()).singletons()ts
// 1. Highest level: a list of singletons — a given set, or all of them.
S.list().id('singletons').title('Singletons').singletons(['siteSettings', 'springCampaign'])
S.list().id('singletons').title('Singletons').singletons()
// 2. A single list item (title/icon default from the definition, then the schema type).
S.listItem().singleton('siteSettings')
// 3. Low level: just the document pane.
S.listItem().title('Settings').id('settings').child(S.document().singleton('siteSettings'))组合规则:
- 所有默认值都可以通过常规链式调用覆盖:、
S.listItem().singleton('siteSettings').title('Global settings')。S.document().singleton('siteSettings').documentId('override') - 系统不会自动区分标题。 列表项 id 默认使用 definition id(根据构造方式保证唯一),但标题会回退到 schema type 的标题,因此共享 schema type 的 singleton 会使用相同标签。请为每个 definition 设置 ——它会应用在所有呈现 singleton 的位置,包括没有逐项覆盖机制的
title。S.list().singletons() - 会锁定 singleton 的带 tag 初始值 template,因此即使该 type 存在多个 templates,也会应用其初始值;可使用
S.document().singleton()覆盖。.initialValueTemplate(...) - 返回的 builder 不包含
S.list().singletons()。 之后调用.items()会替换整个数组并静默移除 singleton 项目,因此类型系统禁止这种用法。请先调用.items(),再调用.items([...]),或者将.singletons([...])项目放入常规S.listItem().singleton()数组中。重复调用.items()会追加项目。.singletons() - 不带参数的 表示所有已注册的 definitions(按注册顺序排列,包括插件注册的 definitions);
singletons()表示不包含任何 singleton。在同一个列表中将其与手写的singletons([])混合使用,会重复添加该 singleton,并抛出 duplicate-idS.listItem().singleton(id)——混合使用时请传入显式数组。SerializeError - 会呈现实时文档预览,而不是静态标题。它的 id 默认使用 definition 的
S.documentListItem().singleton(id)(而不是 definition id),因为 document list item 的 id 就是它所预览的文档。当 singleton 文档可能尚不存在时,优先使用普通的documentId。S.listItem()
Shared schema types and the "create new" escape hatch
共享 schema type 与“create new”逃生通道
Declaring a singleton over schema type replaces 's plain per-type template with the singleton's tagged template, so disappears from create menus. If ordinary documents should stay creatable, define an explicit untagged template — any id works, including itself, since the plain template no longer exists:
TTTTTts
schema: {
templates: (prev) => [
...prev,
{id: 'campaign-non-singleton', title: 'Campaign', schemaType: 'campaign', value: {}},
],
},This is the one place the default structure is not enough on its own: it surfaces the singletons over the shared type, but the type stays filtered, so ordinary documents of it remain unlisted while the structure looks complete. A shared schema type always needs an explicit somewhere in the structure. (A future flag on the definition will replace both the escape-hatch template and this structure entry.)
S.documentTypeListItem(typeName)allowNonSingletonDocumentsThe tag carries the semantics: templates with it are never create options; templates without it always are. The tag lives on — the resolved shape in — not on the authoring type, so developers never set it directly. To customise a singleton's initial value via , find the singleton's template by id (equal to the definition id) and spread it () — the spread preserves the tag at runtime, keeping it out of create menus. (Setting on the definition itself is usually simpler.)
singletonResolvedTemplatesource.templatesTemplateschema.templates{...template, value}initialValue为 schema type 声明 singleton 后, 的普通 per-type template 会被 singleton 的带 tag template 替换,因此 会从创建菜单中消失。如果普通 文档仍应可创建,需要定义一个显式的未带 tag template——任何 id 均可使用,包括 本身,因为普通 template 此时已不存在:
TTTTTts
schema: {
templates: (prev) => [
...prev,
{id: 'campaign-non-singleton', title: 'Campaign', schemaType: 'campaign', value: {}},
],
},这是默认 structure 本身无法完全处理的唯一场景:它会在共享 type 上呈现 singletons,但该 type 仍会被过滤,因此普通文档不会出现在列表中,而 structure 看起来却已经完整。共享的 schema type 始终需要在 structure 中的某个位置显式添加 。(未来 definition 上的 flag 将取代逃生通道 template 和此 structure entry。)
S.documentTypeListItem(typeName)allowNonSingletonDocumentssingletonResolvedTemplatesource.templatesTemplateschema.templates{...template, value}initialValueReading singletons from plugins
从插件中读取 singleton
- The resolved registry is available at (
source.document.singletons).useSource().document.singletons - Document-scoped resolvers receive (the definition id;
context.singletonanddocumentIdare already on the context).schemaType
- 已解析的 registry 可通过 (
source.document.singletons)获取。useSource().document.singletons - Document-scoped resolvers 会收到 (definition id;
context.singleton和documentId已存在于 context 中)。schemaType
Migrating a userland singleton setup
迁移 userland singleton 设置
Typical userland implementations combine three pieces; each is subsumed by the registry:
| Userland technique | First-class replacement |
|---|---|
| Automatic (tagged singleton templates are never create options) |
| Automatic (terminal, non-bypassable) |
Custom structure with | Keep, or simplify to |
Migration steps:
- Add the singleton to (string shorthand when id, document id, and type name are all identical).
document.singletons - Delete the manual and
newDocumentOptionsfiltering for that type.duplicate - Replace the manual structure wiring with (or keep the manual wiring — it remains fully supported; ensure the
S.listItem().singleton(id)/documentIdpair matches the definition soschemaTyperesolves). If the only reason a custom structure existed was to surface the singletons, delete the resolver entirely and let the default structure do it.context.singleton - If the schema type is only used by the singleton, nothing else changes. If it's shared with ordinary documents, add an explicit untagged template to keep them creatable, and to keep them listed.
S.documentTypeList(typeName)
典型的 userland 实现通常由三个部分组合而成,而 registry 已涵盖这些功能:
| Userland 技术 | First-class 替代方案 |
|---|---|
使用 | 自动处理(带 tag 的 singleton templates 永远不会成为创建选项) |
使用 | 自动处理(终态且无法绕过) |
使用 | 保留,或简化为 |
迁移步骤:
- 将 singleton 添加到 (当 id、document id 和 type name 完全相同时可使用字符串 shorthand)。
document.singletons - 删除针对该 type 的手动 和
newDocumentOptions过滤逻辑。duplicate - 使用 替换手动 structure 接线(也可以保留手动接线——它仍完全受支持;请确保
S.listItem().singleton(id)/documentId组合与 definition 匹配,以便schemaType能够正确解析)。如果自定义 structure 存在的唯一原因是呈现 singletons,请删除整个 resolver,让默认 structure 负责处理。context.singleton - 如果该 schema type 仅供 singleton 使用,则无需进行其他更改。如果它与普通文档共享,请添加显式的未带 tag template 以保持其可创建性,并添加 以保持其出现在列表中。
S.documentTypeList(typeName)
Migrating from sanity-plugin-singleton-management
sanity-plugin-singleton-management从 sanity-plugin-singleton-management
迁移
sanity-plugin-singleton-managementsanity-plugin-singleton-managementsanity-plugin-singleton-toolsoptions: {singleton: true}singletonTools()| Plugin technique | First-class replacement |
|---|---|
| A |
| Delete (creation and duplicate prevention are automatic) |
| |
| |
| |
Document id compatibility (the critical detail): the plugin's document id defaults to the schema type name (), so a plugin singleton edits the document . The string shorthand () produces exactly that document id — existing content keeps working with no data migration. If the plugin call passed an explicit , carry it over as the definition's .
S.document().schemaType(type).id(id ?? type)mySingletonmySingletonsingletons: ['mySingleton']iddocumentIdMigration steps:
-
For each schema type with: remove the option, and register the type in
options: {singleton: true}— the string shorthand when the plugin used the default id, otherwisedocument.singletons.{documentId: <the explicit id>, schemaType: <type>} -
Removefrom
singletonTools()and uninstall the package.plugins -
Replace the structure helpers per the table above. The plugin passedaround; the first-class helpers need neither — they read the registry from the builder's own context.
{S, context} -
Note a deliberate behavioural difference: the plugin allowlists actions (,
publish,discardChanges), hiding delete and unpublish. The first-class API only removesrestore— deleting a singleton is a legitimate "reset". To preserve the plugin's stricter behaviour, add:duplicatetsdocument: { actions: (prev, context) => context.singleton ? prev.filter(({action}) => ['publish', 'discardChanges', 'restore'].includes(action as string), ) : prev, },Only add this if the stricter behaviour is genuinely wanted — otherwise prefer the first-class default. -
If the plugin'swas used to render multiple singletons of the same schema type (its
singletonDocumentListItem/titleoverrides), register one definition per document id —id— which is the first-class model for exactly that case.{documentId, schemaType, title}
sanity-plugin-singleton-managementsanity-plugin-singleton-toolsoptions: {singleton: true}singletonTools()| 插件技术 | First-class 替代方案 |
|---|---|
schema type 上的 | |
| 删除(创建和防重复功能会自动生效) |
| |
| |
| |
Document id 兼容性(关键细节): 该插件的 document id 默认使用 schema type 名称(),因此 plugin singleton 编辑的文档就是 。字符串 shorthand()会生成完全相同的 document id,因此现有内容无需数据迁移即可继续使用。如果插件调用时传入了显式 ,则应将其迁移为 definition 的 。
S.document().schemaType(type).id(id ?? type)mySingletonmySingletonsingletons: ['mySingleton']iddocumentId迁移步骤:
-
对于每个设置了的 schema type:删除该 option,并将该 type 注册到
options: {singleton: true}——插件使用默认 id 时使用字符串 shorthand,否则使用document.singletons。{documentId: <the explicit id>, schemaType: <type>} -
从中移除
plugins并卸载该软件包。singletonTools() -
按照上表替换 structure helpers。该插件会在各处传递;first-class helpers 两者都不需要——它们会从 builder 自身的 context 中读取 registry。
{S, context} -
请注意一个有意保留的行为差异:该插件通过 allowlist 限定 actions(、
publish、discardChanges),因此会隐藏 delete 和 unpublish。first-class API 只会移除restore——删除 singleton 是一种合法的“重置”。如需保留插件更严格的行为,请添加:duplicatetsdocument: { actions: (prev, context) => context.singleton ? prev.filter(({action}) => ['publish', 'discardChanges', 'restore'].includes(action as string), ) : prev, },仅当确实需要这种更严格的行为时才应添加;否则建议使用 first-class 默认行为。 -
如果曾使用呈现同一 schema type 的多个 singletons(并覆盖其
singletonDocumentListItem/title),请为每个 document id 注册一个 definition——id——这正是 first-class 模型用于处理此类场景的方式。{documentId, schemaType, title}
Reference
参考
Source lives in the monorepo:
sanity-io/sanity- Config types & validation: ,
core/config/types.tscore/config/prepareConfig.tsx - Structure helpers: ,
Document.ts,ListItem.tsList.ts - Working example: ,
dev/test-studio/schema/singletons.ts,dev/test-studio/structure/resolveSingletons.tsdev/test-studio/structure/resolveStructure.ts - Worked migration of userland singletons over shared schema types (escape-hatch templates in , explicit
dev/test-studio/initialValueTemplates/index.tsopt-back-ins): theS.documentTypeListItem(),circular, andgrrmdefinitions injrr-tolkienresolveSingletons.ts
源代码位于 monorepo:
sanity-io/sanity- Config types 与 validation:、
core/config/types.tscore/config/prepareConfig.tsx - Structure helpers:、
Document.ts、ListItem.tsList.ts - 可运行示例:、
dev/test-studio/schema/singletons.ts、dev/test-studio/structure/resolveSingletons.tsdev/test-studio/structure/resolveStructure.ts - 在共享 schema types 上迁移 userland singletons 的完整示例(位于 的逃生通道 templates,以及显式使用
dev/test-studio/initialValueTemplates/index.ts重新启用):S.documentTypeListItem()中的resolveSingletons.ts、circular和grrmdefinitionsjrr-tolkien