@sanity/schema 5.14.0-next.9 → 5.14.1-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,8 @@
1
1
  import { a as SchemaValidationResult, i as ProblemPathTypeSegment, l as Schema$1, n as ProblemPathPropertySegment, o as TypeWithProblems, r as ProblemPathSegment, s as _FIXME_, t as ProblemPath } from "./_chunks-dts/typedefs.js";
2
2
  import { SetSynchronization, SynchronizationRequest, SynchronizationResult } from "@sanity/descriptors";
3
3
  import * as _sanity_types0 from "@sanity/types";
4
- import { Schema, SchemaType, SchemaTypeDefinition, SchemaValidationProblem, SchemaValidationProblemGroup } from "@sanity/types";
4
+ import { SanityDocumentLike, Schema, SchemaType, SchemaTypeDefinition, SchemaValidationProblem, SchemaValidationProblemGroup } from "@sanity/types";
5
+ import { ComponentType, ReactNode } from "react";
5
6
  import { SchemaType as SchemaType$1 } from "groq-js";
6
7
  /** The scheduler is capable of executing work in different ways. */
7
8
  type Scheduler = {
@@ -44,6 +45,180 @@ declare function resolveSearchConfigForBaseFieldPaths(type: any, maxDepth?: numb
44
45
  */
45
46
  declare function resolveSearchConfig(type: any, maxDepth?: number): any;
46
47
  declare const ALL_FIELDS_GROUP_NAME = "all-fields";
48
+ declare function createSchemaFromManifestTypes(schemaDef: {
49
+ name: string;
50
+ types: unknown[];
51
+ }): Schema$1;
52
+ interface MediaLibraryConfig {
53
+ enabled?: boolean;
54
+ libraryId?: string;
55
+ __internal?: {
56
+ frontendHost?: string;
57
+ };
58
+ }
59
+ declare const SANITY_WORKSPACE_SCHEMA_ID_PREFIX = "_.schemas";
60
+ declare const SANITY_WORKSPACE_SCHEMA_TYPE = "system.schema";
61
+ declare const CURRENT_WORKSPACE_SCHEMA_VERSION = "2025-05-01";
62
+ type ManifestSerializable = string | number | boolean | {
63
+ [k: string]: ManifestSerializable;
64
+ } | ManifestSerializable[];
65
+ interface CreateManifest {
66
+ version: number;
67
+ createdAt: string;
68
+ workspaces: ManifestWorkspaceFile[];
69
+ studioVersion: string | null;
70
+ }
71
+ interface ManifestWorkspaceFile extends Omit<CreateWorkspaceManifest, 'schema' | 'tools'> {
72
+ schema: string;
73
+ tools: string;
74
+ }
75
+ interface CreateWorkspaceManifest {
76
+ name: string;
77
+ title?: string;
78
+ subtitle?: string;
79
+ basePath: string;
80
+ dataset: string;
81
+ projectId: string;
82
+ mediaLibrary?: MediaLibraryConfig;
83
+ schema: ManifestSchemaType[];
84
+ tools: ManifestTool[];
85
+ /**
86
+ * returns undefined in the case of the icon not being able to be stringified
87
+ */
88
+ icon: string | undefined;
89
+ }
90
+ interface ManifestSchemaType {
91
+ type: string;
92
+ name: string;
93
+ title?: string;
94
+ deprecated?: {
95
+ reason: string;
96
+ };
97
+ readOnly?: boolean | 'conditional';
98
+ hidden?: boolean | 'conditional';
99
+ validation?: ManifestValidationGroup[];
100
+ fields?: ManifestField[];
101
+ to?: ManifestReferenceMember[];
102
+ of?: ManifestArrayMember[];
103
+ preview?: {
104
+ select: Record<string, string>;
105
+ };
106
+ fieldsets?: ManifestFieldset[];
107
+ options?: Record<string, ManifestSerializable>;
108
+ marks?: {
109
+ annotations?: ManifestArrayMember[];
110
+ decorators?: ManifestTitledValue[];
111
+ };
112
+ lists?: ManifestTitledValue[];
113
+ styles?: ManifestTitledValue[];
114
+ }
115
+ interface ManifestFieldset {
116
+ name: string;
117
+ title?: string;
118
+ [index: string]: ManifestSerializable | undefined;
119
+ }
120
+ interface ManifestTitledValue {
121
+ value: string;
122
+ title?: string;
123
+ }
124
+ type ManifestField = ManifestSchemaType & {
125
+ fieldset?: string;
126
+ };
127
+ type ManifestArrayMember = Omit<ManifestSchemaType, 'name'> & {
128
+ name?: string;
129
+ };
130
+ type ManifestReferenceMember = Omit<ManifestSchemaType, 'name'> & {
131
+ name?: string;
132
+ };
133
+ interface ManifestValidationGroup {
134
+ rules: ManifestValidationRule[];
135
+ message?: string;
136
+ level?: 'error' | 'warning' | 'info';
137
+ }
138
+ type ManifestValidationRule = {
139
+ flag: string;
140
+ constraint?: ManifestSerializable;
141
+ [index: string]: ManifestSerializable | undefined;
142
+ };
143
+ interface ManifestTool {
144
+ name: string;
145
+ title: string;
146
+ /**
147
+ * returns undefined in the case of the icon not being able to be stringified
148
+ */
149
+ icon: string | undefined;
150
+ type: string | null;
151
+ }
152
+ type DefaultWorkspaceSchemaId = `${typeof SANITY_WORKSPACE_SCHEMA_ID_PREFIX}.${string}`;
153
+ type PrefixedWorkspaceSchemaId = `${DefaultWorkspaceSchemaId}.${string}`;
154
+ type WorkspaceSchemaId = DefaultWorkspaceSchemaId | PrefixedWorkspaceSchemaId;
155
+ interface StoredWorkspaceSchema extends SanityDocumentLike {
156
+ _type: typeof SANITY_WORKSPACE_SCHEMA_TYPE;
157
+ _id: WorkspaceSchemaId;
158
+ version: typeof CURRENT_WORKSPACE_SCHEMA_VERSION | undefined;
159
+ tag?: string;
160
+ workspace: {
161
+ name: string;
162
+ title?: string;
163
+ };
164
+ /**
165
+ * The API expects JSON coming in, but will store a string to save on attribute paths.
166
+ * Consumers must use JSON.parse on the value, put we deploy to the API using ManifestSchemaType[]
167
+ */
168
+ schema: string | ManifestSchemaType[];
169
+ }
170
+ interface ManifestWorkspaceInput {
171
+ name: string;
172
+ title?: string;
173
+ subtitle?: string;
174
+ basePath: string;
175
+ projectId: string;
176
+ dataset: string;
177
+ icon?: ComponentType | ReactNode;
178
+ mediaLibrary?: MediaLibraryConfig;
179
+ schema: Schema;
180
+ tools: ManifestToolInput[];
181
+ }
182
+ interface ManifestToolInput {
183
+ title: string;
184
+ name: string;
185
+ icon?: ComponentType | ReactNode;
186
+ __internalApplicationType?: string;
187
+ }
188
+ type IconResolver = (props: {
189
+ icon?: ComponentType | ReactNode;
190
+ title: string;
191
+ subtitle?: string;
192
+ }) => string | undefined | Promise<string | undefined>;
193
+ declare function extractCreateWorkspaceManifest(workspace: ManifestWorkspaceInput, iconResolver?: IconResolver): Promise<CreateWorkspaceManifest>;
194
+ /**
195
+ * Extracts all serializable properties from userland schema types,
196
+ * so they best-effort can be used as definitions for Schema.compile
197
+ . */
198
+ declare function extractManifestSchemaTypes(schema: Schema): ManifestSchemaType[];
199
+ declare const validForNamesChars = "a-zA-Z0-9_-";
200
+ declare const validForNamesPattern: RegExp;
201
+ declare function getWorkspaceSchemaId(args: {
202
+ workspaceName: string;
203
+ tag?: string;
204
+ }): {
205
+ safeBaseId: DefaultWorkspaceSchemaId;
206
+ safeTaggedId: WorkspaceSchemaId;
207
+ idWarning: string | undefined;
208
+ };
209
+ interface ParsedWorkspaceSchemaId {
210
+ schemaId: string;
211
+ workspace: string;
212
+ }
213
+ declare function parseWorkspaceSchemaId(id: string, errors: string[]): ParsedWorkspaceSchemaId | undefined;
214
+ declare function createStoredWorkspaceSchemaPayload(args: {
215
+ workspace: {
216
+ name: string;
217
+ title?: string;
218
+ };
219
+ schema: ManifestSchemaType[];
220
+ tag?: string;
221
+ }): Omit<StoredWorkspaceSchema, '_id' | '_type'>;
47
222
  declare const builtinTypes: ({
48
223
  name: string;
49
224
  title: string;
@@ -240,10 +415,6 @@ declare const builtinTypes: ({
240
415
  readOnly: boolean;
241
416
  })[];
242
417
  })[];
243
- declare function createSchemaFromManifestTypes(schemaDef: {
244
- name: string;
245
- types: unknown[];
246
- }): Schema$1;
247
418
  interface ExtractSchemaOptions {
248
419
  enforceRequiredFields?: boolean;
249
420
  }
@@ -311,4 +482,4 @@ declare class ValidationError extends Error {
311
482
  problems: SchemaValidationProblemGroup[];
312
483
  constructor(problems: SchemaValidationProblemGroup[]);
313
484
  }
314
- export { ALL_FIELDS_GROUP_NAME, DEFAULT_MAX_FIELD_DEPTH, DescriptorConverter, type _FIXME_ as FIXME, type SchemaValidationResult as Problem, type SchemaValidationResult as ValidationResult, type ProblemPath, type ProblemPathPropertySegment, type ProblemPathSegment, type ProblemPathTypeSegment, SchemaSynchronizationRequest, SchemaSynchronizationResult, type TypeWithProblems, ValidationError, builtinTypes, createSchemaFromManifestTypes, extractSchema, groupProblems, isActionEnabled, processSchemaSynchronization, resolveSearchConfig, resolveSearchConfigForBaseFieldPaths, validateMediaLibraryAssetAspect, validateSchema };
485
+ export { ALL_FIELDS_GROUP_NAME, type CreateManifest, type CreateWorkspaceManifest, DEFAULT_MAX_FIELD_DEPTH, type DefaultWorkspaceSchemaId, DescriptorConverter, type _FIXME_ as FIXME, type IconResolver, type ManifestSchemaType, type ManifestWorkspaceFile, type ParsedWorkspaceSchemaId, type SchemaValidationResult as Problem, type SchemaValidationResult as ValidationResult, type ProblemPath, type ProblemPathPropertySegment, type ProblemPathSegment, type ProblemPathTypeSegment, SchemaSynchronizationRequest, SchemaSynchronizationResult, type StoredWorkspaceSchema, type TypeWithProblems, ValidationError, type WorkspaceSchemaId, builtinTypes, createSchemaFromManifestTypes, createStoredWorkspaceSchemaPayload, extractCreateWorkspaceManifest, extractManifestSchemaTypes, extractSchema, getWorkspaceSchemaId, groupProblems, isActionEnabled, parseWorkspaceSchemaId, processSchemaSynchronization, resolveSearchConfig, resolveSearchConfigForBaseFieldPaths, validForNamesChars, validForNamesPattern, validateMediaLibraryAssetAspect, validateSchema };
package/lib/_internal.js CHANGED
@@ -14,6 +14,7 @@ import isPlainObject from "lodash-es/isPlainObject.js";
14
14
  import omit from "lodash-es/omit.js";
15
15
  import leven from "leven";
16
16
  import inspect from "object-inspect";
17
+ import startCase from "lodash-es/startCase.js";
17
18
  import { createReferenceTypeNode } from "groq-js";
18
19
  const MAX_IDLE_WORK = 8.333333333333334;
19
20
  class IdleScheduler {
@@ -1821,6 +1822,14 @@ function validateField(field, visitorContext) {
1821
1822
  `The type "${field.type}" is a document type and should not be used as a field type directly. Use a "reference" if you want to create a link to the document, or use "object" if you want to embed fields inline.`,
1822
1823
  HELP_IDS.FIELD_TYPE_IS_DOCUMENT
1823
1824
  )
1825
+ ), field.title && typeof field.title != "string" && problems.push(
1826
+ warning(
1827
+ `Field "${field.name}" has a non-string title. This is known to cause problems and will not be supported in future versions. Please use a string instead.`
1828
+ )
1829
+ ), field.description && typeof field.description != "string" && problems.push(
1830
+ warning(
1831
+ `Field "${field.name}" has a non-string description. This is known to cause problems and will not be supported in future versions. Please use a string instead.`
1832
+ )
1824
1833
  ), problems;
1825
1834
  }
1826
1835
  function getDuplicateFields(array2) {
@@ -2350,6 +2359,405 @@ function stringToRegExp(str) {
2350
2359
  const match = str.match(/^\/(.*)\/([gimuy]*)$/);
2351
2360
  return match ? new RegExp(match[1], match[2]) : new RegExp(str);
2352
2361
  }
2362
+ const DEFAULT_IMAGE_FIELDS = ["asset", "hotspot", "crop", "media"], DEFAULT_FILE_FIELDS = ["asset", "media"], DEFAULT_GEOPOINT_FIELDS = ["lat", "lng", "alt"], DEFAULT_SLUG_FIELDS = ["current", "source"];
2363
+ function getCustomFields(type) {
2364
+ const fields = type.fieldsets ? type.fieldsets.flatMap((fs) => fs.single ? fs.field : fs.fields.map((field) => ({
2365
+ ...field,
2366
+ fieldset: fs.name
2367
+ }))) : type.fields;
2368
+ return isType$1(type, "block") ? [] : isType$1(type, "slug") ? fields.filter((f) => !DEFAULT_SLUG_FIELDS.includes(f.name)) : isType$1(type, "geopoint") ? fields.filter((f) => !DEFAULT_GEOPOINT_FIELDS.includes(f.name)) : isType$1(type, "image") ? fields.filter((f) => !DEFAULT_IMAGE_FIELDS.includes(f.name)) : isType$1(type, "file") ? fields.filter((f) => !DEFAULT_FILE_FIELDS.includes(f.name)) : fields;
2369
+ }
2370
+ function isReference(type) {
2371
+ return isType$1(type, "reference");
2372
+ }
2373
+ function isCrossDatasetReference(type) {
2374
+ return isType$1(type, "crossDatasetReference");
2375
+ }
2376
+ function isGlobalDocumentReference(type) {
2377
+ return isType$1(type, "globalDocumentReference");
2378
+ }
2379
+ function isObjectField(maybeOjectField) {
2380
+ return typeof maybeOjectField == "object" && maybeOjectField !== null && "name" in maybeOjectField;
2381
+ }
2382
+ function isCustomized(maybeCustomized) {
2383
+ const internalOwnProps = getSchemaTypeInternalOwnProps(maybeCustomized);
2384
+ return isObjectField(maybeCustomized) && !isReference(maybeCustomized) && !isCrossDatasetReference(maybeCustomized) && !isGlobalDocumentReference(maybeCustomized) && "fields" in maybeCustomized && Array.isArray(maybeCustomized.fields) && // needed to differentiate inline, named array object types from globally defined types
2385
+ // we only consider it customized if the _definition_ has fields declared
2386
+ // this holds for all customizable object-like types: object, document, image and file
2387
+ internalOwnProps?.fields ? !!getCustomFields(maybeCustomized).length : !1;
2388
+ }
2389
+ function isType$1(schemaType, typeName) {
2390
+ return schemaType.name === typeName ? !0 : schemaType.type ? isType$1(schemaType.type, typeName) : !1;
2391
+ }
2392
+ function isDefined(value) {
2393
+ return value != null;
2394
+ }
2395
+ function isRecord(value) {
2396
+ return !!value && typeof value == "object";
2397
+ }
2398
+ function isPrimitive(value) {
2399
+ return isString(value) || isBoolean(value) || isNumber(value);
2400
+ }
2401
+ function isString(value) {
2402
+ return typeof value == "string";
2403
+ }
2404
+ function isNumber(value) {
2405
+ return typeof value == "number";
2406
+ }
2407
+ function isBoolean(value) {
2408
+ return typeof value == "boolean";
2409
+ }
2410
+ function getSchemaTypeInternalOwnProps(type) {
2411
+ return type?._internal_ownProps;
2412
+ }
2413
+ function getDefinedTypeName(type) {
2414
+ return getSchemaTypeInternalOwnProps(type)?.type;
2415
+ }
2416
+ const MAX_CUSTOM_PROPERTY_DEPTH = 5, noopIconResolver = () => {
2417
+ };
2418
+ async function extractCreateWorkspaceManifest(workspace, iconResolver = noopIconResolver) {
2419
+ const serializedSchema = extractManifestSchemaTypes(workspace.schema), serializedTools = await extractManifestTools(workspace.tools, iconResolver);
2420
+ return {
2421
+ name: workspace.name,
2422
+ title: workspace.title,
2423
+ subtitle: workspace.subtitle,
2424
+ basePath: workspace.basePath,
2425
+ projectId: workspace.projectId,
2426
+ dataset: workspace.dataset,
2427
+ icon: await iconResolver({
2428
+ icon: workspace.icon,
2429
+ title: workspace.title ?? workspace.name,
2430
+ subtitle: workspace.subtitle
2431
+ }),
2432
+ mediaLibrary: workspace.mediaLibrary,
2433
+ schema: serializedSchema,
2434
+ tools: serializedTools
2435
+ };
2436
+ }
2437
+ function extractManifestSchemaTypes(schema) {
2438
+ const typeNames = schema.getTypeNames(), studioDefaultTypeNames = Schema.compile({
2439
+ name: "default",
2440
+ types: builtinTypes
2441
+ }).getTypeNames();
2442
+ return typeNames.filter((typeName) => !studioDefaultTypeNames.includes(typeName)).map((typeName) => schema.get(typeName)).filter((type) => typeof type < "u").map((type) => transformType(type));
2443
+ }
2444
+ function transformCommonTypeFields(type, typeName, context) {
2445
+ const arrayProps = typeName === "array" && type.jsonType === "array" ? transformArrayMember(type) : {}, referenceProps = isReference(type) ? transformReference(type) : {}, crossDatasetRefProps = isCrossDatasetReference(type) ? transformCrossDatasetReference(type) : {}, globalRefProps = isGlobalDocumentReference(type) ? transformGlobalDocumentReference(type) : {}, objectFields = type.jsonType === "object" && type.type && isCustomized(type) ? {
2446
+ fields: getCustomFields(type).map((objectField) => transformField(objectField))
2447
+ } : {};
2448
+ return {
2449
+ ...retainCustomTypeProps(type),
2450
+ ...transformValidation(type.validation),
2451
+ ...ensureString("description", type.description),
2452
+ ...objectFields,
2453
+ ...arrayProps,
2454
+ ...referenceProps,
2455
+ ...crossDatasetRefProps,
2456
+ ...globalRefProps,
2457
+ ...ensureConditional("readOnly", type.readOnly),
2458
+ ...ensureConditional("hidden", type.hidden),
2459
+ ...transformFieldsets(type),
2460
+ // fieldset prop gets instrumented via getCustomFields
2461
+ ...ensureString("fieldset", type.fieldset),
2462
+ ...transformBlockType(type)
2463
+ };
2464
+ }
2465
+ function transformFieldsets(type) {
2466
+ if (type.jsonType !== "object")
2467
+ return {};
2468
+ const fieldsets = type.fieldsets?.filter((fs) => !fs.single).map((fs) => {
2469
+ const options = isRecord(fs.options) ? { options: retainSerializableProps(fs.options) } : {};
2470
+ return {
2471
+ name: fs.name,
2472
+ ...ensureCustomTitle(fs.name, fs.title),
2473
+ ...ensureString("description", fs.description),
2474
+ ...ensureConditional("readOnly", fs.readOnly),
2475
+ ...ensureConditional("hidden", fs.hidden),
2476
+ ...options
2477
+ };
2478
+ });
2479
+ return fieldsets?.length ? { fieldsets } : {};
2480
+ }
2481
+ function transformType(type, context) {
2482
+ const typeName = type.type ? type.type.name : type.jsonType;
2483
+ return {
2484
+ ...transformCommonTypeFields(type, typeName),
2485
+ name: type.name,
2486
+ type: typeName,
2487
+ ...ensureCustomTitle(type.name, type.title)
2488
+ };
2489
+ }
2490
+ function retainCustomTypeProps(type) {
2491
+ const manuallySerializedFields = [
2492
+ //explicitly added
2493
+ "name",
2494
+ "title",
2495
+ "description",
2496
+ "readOnly",
2497
+ "hidden",
2498
+ "validation",
2499
+ "fieldsets",
2500
+ "fields",
2501
+ "to",
2502
+ "of",
2503
+ // not serialized
2504
+ "type",
2505
+ "jsonType",
2506
+ "__experimental_actions",
2507
+ "__experimental_formPreviewTitle",
2508
+ "__experimental_omnisearch_visibility",
2509
+ "__experimental_search",
2510
+ "components",
2511
+ "icon",
2512
+ "orderings",
2513
+ "preview",
2514
+ "groups",
2515
+ //only exists on fields
2516
+ "group"
2517
+ // we know about these, but let them be generically handled
2518
+ // deprecated
2519
+ // rows (from text)
2520
+ // initialValue
2521
+ // options
2522
+ // crossDatasetReference props
2523
+ ], typeWithoutManuallyHandledFields = Object.fromEntries(
2524
+ Object.entries(type).filter(
2525
+ ([key]) => !manuallySerializedFields.includes(key)
2526
+ )
2527
+ );
2528
+ return retainSerializableProps(typeWithoutManuallyHandledFields);
2529
+ }
2530
+ function retainSerializableProps(maybeSerializable, depth = 0) {
2531
+ if (!(depth > MAX_CUSTOM_PROPERTY_DEPTH) && isDefined(maybeSerializable)) {
2532
+ if (isPrimitive(maybeSerializable))
2533
+ return maybeSerializable === "" ? void 0 : maybeSerializable;
2534
+ if (maybeSerializable instanceof RegExp)
2535
+ return maybeSerializable.toString();
2536
+ if (Array.isArray(maybeSerializable)) {
2537
+ const arrayItems = maybeSerializable.map((item) => retainSerializableProps(item, depth + 1)).filter((item) => isDefined(item));
2538
+ return arrayItems.length ? arrayItems : void 0;
2539
+ }
2540
+ if (isRecord(maybeSerializable)) {
2541
+ const serializableEntries = Object.entries(maybeSerializable).map(([key, value]) => [key, retainSerializableProps(value, depth + 1)]).filter(([, value]) => isDefined(value));
2542
+ return serializableEntries.length ? Object.fromEntries(serializableEntries) : void 0;
2543
+ }
2544
+ }
2545
+ }
2546
+ function transformField(field, context) {
2547
+ const fieldType = field.type, typeName = getDefinedTypeName(fieldType) ?? fieldType.name;
2548
+ return {
2549
+ ...transformCommonTypeFields(fieldType, typeName),
2550
+ name: field.name,
2551
+ type: typeName,
2552
+ ...ensureCustomTitle(field.name, fieldType.title),
2553
+ // this prop gets added synthetically via getCustomFields
2554
+ ...ensureString("fieldset", field.fieldset)
2555
+ };
2556
+ }
2557
+ function transformArrayMember(arrayMember, context) {
2558
+ return {
2559
+ of: arrayMember.of.map((type) => {
2560
+ const typeName = getDefinedTypeName(type) ?? type.name;
2561
+ return {
2562
+ ...transformCommonTypeFields(type, typeName),
2563
+ type: typeName,
2564
+ ...typeName === type.name ? {} : { name: type.name },
2565
+ ...ensureCustomTitle(type.name, type.title)
2566
+ };
2567
+ })
2568
+ };
2569
+ }
2570
+ function transformReference(reference2) {
2571
+ return {
2572
+ to: (reference2.to ?? []).map((type) => ({
2573
+ ...retainCustomTypeProps(type),
2574
+ type: type.name
2575
+ }))
2576
+ };
2577
+ }
2578
+ function transformCrossDatasetReference(reference2) {
2579
+ return {
2580
+ to: (reference2.to ?? []).map((crossDataset) => {
2581
+ const preview = crossDataset.preview?.select ? { preview: { select: crossDataset.preview.select } } : {};
2582
+ return {
2583
+ type: crossDataset.type,
2584
+ ...ensureCustomTitle(crossDataset.type, crossDataset.title),
2585
+ ...preview
2586
+ };
2587
+ })
2588
+ };
2589
+ }
2590
+ function transformGlobalDocumentReference(reference2) {
2591
+ return {
2592
+ to: (reference2.to ?? []).map((crossDataset) => {
2593
+ const preview = crossDataset.preview?.select ? { preview: { select: crossDataset.preview.select } } : {};
2594
+ return {
2595
+ type: crossDataset.type,
2596
+ ...ensureCustomTitle(crossDataset.type, crossDataset.title),
2597
+ ...preview
2598
+ };
2599
+ })
2600
+ };
2601
+ }
2602
+ const transformTypeValidationRule = (rule) => ({
2603
+ ...rule,
2604
+ constraint: "constraint" in rule && (typeof rule.constraint == "string" ? rule.constraint.toLowerCase() : retainSerializableProps(rule.constraint))
2605
+ }), validationRuleTransformers = {
2606
+ type: transformTypeValidationRule
2607
+ };
2608
+ function transformValidation(validation) {
2609
+ const validationArray = (Array.isArray(validation) ? validation : [validation]).filter(
2610
+ (value) => typeof value == "object" && "_type" in value
2611
+ ), disallowedFlags = ["type"], disallowedConstraintTypes = [Rule.FIELD_REF], serializedValidation = validationArray.map(({ _rules, _message, _level }) => {
2612
+ const message = typeof _message == "string" ? { message: _message } : {};
2613
+ return {
2614
+ rules: _rules.filter((rule) => {
2615
+ if (!("constraint" in rule))
2616
+ return !1;
2617
+ const { flag, constraint } = rule;
2618
+ return disallowedFlags.includes(flag) ? !1 : !(typeof constraint == "object" && "type" in constraint && disallowedConstraintTypes.includes(constraint.type));
2619
+ }).reduce((rules, rule) => {
2620
+ const transformedRule = (validationRuleTransformers[rule.flag] ?? ((spec) => retainSerializableProps(spec)))(rule);
2621
+ return transformedRule ? [...rules, transformedRule] : rules;
2622
+ }, []),
2623
+ level: _level,
2624
+ ...message
2625
+ };
2626
+ }).filter((group) => !!group.rules.length);
2627
+ return serializedValidation.length ? { validation: serializedValidation } : {};
2628
+ }
2629
+ function ensureCustomTitle(typeName, value) {
2630
+ const titleObject = ensureString("title", value), defaultTitle = startCase(typeName);
2631
+ return titleObject.title === defaultTitle ? {} : titleObject;
2632
+ }
2633
+ function ensureString(key, value) {
2634
+ return typeof value == "string" ? {
2635
+ [key]: value
2636
+ } : {};
2637
+ }
2638
+ function ensureConditional(key, value) {
2639
+ return typeof value == "boolean" ? {
2640
+ [key]: value
2641
+ } : typeof value == "function" ? {
2642
+ [key]: "conditional"
2643
+ } : {};
2644
+ }
2645
+ function transformBlockType(blockType, context) {
2646
+ if (blockType.jsonType !== "object" || !isType$1(blockType, "block"))
2647
+ return {};
2648
+ const childrenField = blockType.fields?.find((field) => field.name === "children");
2649
+ if (!childrenField)
2650
+ return {};
2651
+ const ofType = childrenField.type.of;
2652
+ if (!ofType)
2653
+ return {};
2654
+ const spanType = ofType.find((memberType) => memberType.name === "span");
2655
+ if (!spanType)
2656
+ return {};
2657
+ const inlineObjectTypes = ofType.filter((memberType) => memberType.name !== "span") || [];
2658
+ return {
2659
+ marks: {
2660
+ annotations: spanType.annotations.map((t) => transformType(t)),
2661
+ decorators: resolveEnabledDecorators(spanType)
2662
+ },
2663
+ lists: resolveEnabledListItems(blockType),
2664
+ styles: resolveEnabledStyles(blockType),
2665
+ of: inlineObjectTypes.map((t) => transformType(t))
2666
+ };
2667
+ }
2668
+ function resolveEnabledStyles(blockType) {
2669
+ const styleField = blockType.fields?.find((btField) => btField.name === "style");
2670
+ return resolveTitleValueArray(styleField?.type?.options?.list);
2671
+ }
2672
+ function resolveEnabledDecorators(spanType) {
2673
+ return "decorators" in spanType ? resolveTitleValueArray(spanType.decorators) : void 0;
2674
+ }
2675
+ function resolveEnabledListItems(blockType) {
2676
+ const listField = blockType.fields?.find((btField) => btField.name === "listItem");
2677
+ return resolveTitleValueArray(listField?.type?.options?.list);
2678
+ }
2679
+ function resolveTitleValueArray(possibleArray) {
2680
+ if (!possibleArray || !Array.isArray(possibleArray))
2681
+ return;
2682
+ const titledValues = possibleArray.filter(
2683
+ (d) => isRecord(d) && !!d.value && isString(d.value)
2684
+ ).map((item) => ({
2685
+ value: item.value,
2686
+ ...ensureString("title", item.title)
2687
+ }));
2688
+ if (titledValues?.length)
2689
+ return titledValues;
2690
+ }
2691
+ const extractManifestTools = async (tools, iconResolver = noopIconResolver) => Promise.all(
2692
+ tools.map(async (tool) => {
2693
+ const { title, name, icon, __internalApplicationType: type } = tool;
2694
+ return {
2695
+ title,
2696
+ name,
2697
+ type: type || null,
2698
+ icon: await iconResolver({
2699
+ icon,
2700
+ title
2701
+ })
2702
+ };
2703
+ })
2704
+ ), SANITY_WORKSPACE_SCHEMA_ID_PREFIX = "_.schemas", CURRENT_WORKSPACE_SCHEMA_VERSION = "2025-05-01", validForNamesChars = "a-zA-Z0-9_-", validForNamesPattern = new RegExp(`^[${validForNamesChars}]+$`, "g"), validForIdChars = "a-zA-Z0-9._-", validForIdPattern = new RegExp(`^[${validForIdChars}]+$`, "g"), requiredInId = SANITY_WORKSPACE_SCHEMA_ID_PREFIX.replace(/[.]/g, "\\."), idPatternString = `^${requiredInId}\\.([${validForNamesChars}]+)`, baseIdPattern = new RegExp(`${idPatternString}$`), taggedIdPattern = new RegExp(`${idPatternString}\\.tag\\.([${validForNamesChars}]+)$`);
2705
+ function getWorkspaceSchemaId(args) {
2706
+ const { workspaceName: rawWorkspaceName, tag } = args;
2707
+ let workspaceName = rawWorkspaceName, idWarning;
2708
+ workspaceName.match(validForNamesPattern) || (workspaceName = workspaceName.replace(new RegExp(`[^${validForNamesChars}]`, "g"), "_"), idWarning = [
2709
+ `Workspace "${rawWorkspaceName}" contains characters unsupported by schema _id [${validForNamesChars}], they will be replaced with _.`,
2710
+ "This could lead duplicate schema ids: consider renaming your workspace."
2711
+ ].join(`
2712
+ `));
2713
+ const safeBaseId = `${SANITY_WORKSPACE_SCHEMA_ID_PREFIX}.${workspaceName}`;
2714
+ return {
2715
+ safeBaseId,
2716
+ safeTaggedId: `${safeBaseId}${tag ? `.tag.${tag}` : ""}`,
2717
+ idWarning
2718
+ };
2719
+ }
2720
+ function parseWorkspaceSchemaId(id, errors) {
2721
+ const trimmedId = id.trim();
2722
+ if (!trimmedId.match(validForIdPattern)) {
2723
+ errors.push(`id can only contain characters in [${validForIdChars}] but found: "${trimmedId}"`);
2724
+ return;
2725
+ }
2726
+ if (trimmedId.startsWith("-")) {
2727
+ errors.push(`id cannot start with - (dash) but found: "${trimmedId}"`);
2728
+ return;
2729
+ }
2730
+ if (trimmedId.match(/\.\./g)) {
2731
+ errors.push(`id cannot have consecutive . (period) characters, but found: "${trimmedId}"`);
2732
+ return;
2733
+ }
2734
+ const [, workspace] = trimmedId.match(taggedIdPattern) ?? trimmedId.match(baseIdPattern) ?? [];
2735
+ if (!workspace) {
2736
+ errors.push(
2737
+ [
2738
+ `id must either match ${SANITY_WORKSPACE_SCHEMA_ID_PREFIX}.<workspaceName> `,
2739
+ `or ${SANITY_WORKSPACE_SCHEMA_ID_PREFIX}.<workspaceName>.tag.<tag> but found: "${trimmedId}". `,
2740
+ `Note that workspace name characters not in [${validForNamesChars}] has to be replaced with _ for schema id.`
2741
+ ].join("")
2742
+ );
2743
+ return;
2744
+ }
2745
+ return {
2746
+ schemaId: trimmedId,
2747
+ workspace
2748
+ };
2749
+ }
2750
+ function createStoredWorkspaceSchemaPayload(args) {
2751
+ return {
2752
+ version: CURRENT_WORKSPACE_SCHEMA_VERSION,
2753
+ tag: args.tag,
2754
+ workspace: {
2755
+ name: args.workspace.name,
2756
+ title: args.workspace.title
2757
+ },
2758
+ schema: args.schema
2759
+ };
2760
+ }
2353
2761
  const documentDefaultFields = (typeName) => ({
2354
2762
  _id: {
2355
2763
  type: "objectAttribute",
@@ -2950,12 +3358,19 @@ export {
2950
3358
  ValidationError,
2951
3359
  builtinTypes,
2952
3360
  createSchemaFromManifestTypes,
3361
+ createStoredWorkspaceSchemaPayload,
3362
+ extractCreateWorkspaceManifest,
3363
+ extractManifestSchemaTypes,
2953
3364
  extractSchema,
3365
+ getWorkspaceSchemaId,
2954
3366
  groupProblems,
2955
3367
  isActionEnabled,
3368
+ parseWorkspaceSchemaId,
2956
3369
  processSchemaSynchronization,
2957
3370
  resolveSearchConfig,
2958
3371
  resolveSearchConfigForBaseFieldPaths,
3372
+ validForNamesChars,
3373
+ validForNamesPattern,
2959
3374
  validateMediaLibraryAssetAspect,
2960
3375
  validateSchema
2961
3376
  };