@sanity/schema 5.0.0-next.0-9b570ece82-202507150640 → 5.0.0-next.7

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.
package/lib/_internal.mjs DELETED
@@ -1,2131 +0,0 @@
1
- import { SetBuilder, processSetSynchronization } from "@sanity/descriptors";
2
- import { OWN_PROPS_NAME } from "./_chunks-es/resolve.mjs";
3
- import { DEFAULT_MAX_FIELD_DEPTH, resolveSearchConfig, resolveSearchConfigForBaseFieldPaths } from "./_chunks-es/resolve.mjs";
4
- import difference from "lodash/difference.js";
5
- import { createReferenceTypeNode } from "groq-js";
6
- import flatten from "lodash/flatten.js";
7
- import get from "lodash/get.js";
8
- import uniq from "lodash/uniq.js";
9
- import humanizeList from "humanize-list";
10
- import partition from "lodash/partition.js";
11
- import isPlainObject from "lodash/isPlainObject.js";
12
- import omit from "lodash/omit.js";
13
- import leven from "leven";
14
- import inspect from "object-inspect";
15
- const MAX_DEPTH_UKNOWN = 5;
16
- class DescriptorConverter {
17
- opts;
18
- cache = /* @__PURE__ */ new WeakMap();
19
- constructor(opts) {
20
- this.opts = opts;
21
- }
22
- /**
23
- * Returns a synchronization object for a schema.
24
- *
25
- * This is automatically cached in a weak map.
26
- */
27
- get(schema) {
28
- let value = this.cache.get(schema);
29
- if (value) return value;
30
- const builder = new SetBuilder();
31
- for (const name of schema.getLocalTypeNames()) {
32
- const typeDef = convertTypeDef(schema.get(name));
33
- builder.addObject("sanity.schema.namedType", { name, typeDef });
34
- }
35
- return schema.parent && builder.addSet(this.get(schema.parent)), value = builder.build("sanity.schema.registry"), this.cache.set(schema, value), value;
36
- }
37
- }
38
- function convertCommonTypeDef(schemaType, opts) {
39
- const ownProps = OWN_PROPS_NAME in schemaType ? schemaType[OWN_PROPS_NAME] : schemaType;
40
- let fields;
41
- Array.isArray(ownProps.fields) && (fields = ownProps.fields.map(
42
- ({ name, group, fieldset, type }) => ({
43
- name,
44
- typeDef: convertTypeDef(type),
45
- groups: arrayifyString(group),
46
- fieldset
47
- })
48
- ));
49
- let fieldsets;
50
- Array.isArray(ownProps.fieldsets) && (fieldsets = filterStringKey(
51
- "name",
52
- ownProps.fieldsets.map(
53
- ({ name, title, description, group, hidden, readOnly, options }) => ({
54
- name,
55
- title: maybeString(title),
56
- description: maybeString(description),
57
- group: maybeString(group),
58
- hidden: conditionalTrue(hidden),
59
- readOnly: conditionalTrue(readOnly),
60
- options: convertUnknown(options)
61
- })
62
- )
63
- ));
64
- let groups;
65
- Array.isArray(ownProps.groups) && (groups = filterStringKey(
66
- "name",
67
- ownProps.groups.map(
68
- ({ name, title, hidden, default: def }) => ({
69
- name,
70
- title: maybeString(title),
71
- hidden: conditionalTrue(hidden),
72
- default: maybeTrue(def)
73
- })
74
- )
75
- ));
76
- const reason = ownProps.deprecated?.reason;
77
- return {
78
- title: maybeString(ownProps.title),
79
- description: maybeStringOrJSX(ownProps.description),
80
- readOnly: conditionalTrue(ownProps.readOnly),
81
- hidden: conditionalTrue(ownProps.hidden),
82
- liveEdit: maybeTrue(ownProps.liveEdit),
83
- options: convertUnknown(ownProps.options),
84
- initialValue: convertUnknown(ownProps.initialValue),
85
- deprecated: typeof reason == "string" ? { reason } : void 0,
86
- placeholder: maybeString(ownProps.placeholder),
87
- rows: maybeNumberAsString(ownProps.rows),
88
- fields,
89
- fieldsets,
90
- groups
91
- };
92
- }
93
- function convertTypeDef(schemaType, opts) {
94
- const common2 = convertCommonTypeDef(schemaType);
95
- if (!schemaType.type)
96
- return {
97
- extends: null,
98
- jsonType: schemaType.jsonType,
99
- ...common2
100
- };
101
- switch (schemaType.type.name) {
102
- case "array":
103
- return {
104
- extends: "array",
105
- of: schemaType.of.map((ofType) => ({
106
- name: ofType.name,
107
- typeDef: convertTypeDef(ofType)
108
- })),
109
- ...common2
110
- };
111
- case "reference":
112
- case "globalDocumentReference":
113
- case "crossDatasetReference":
114
- return {
115
- extends: schemaType.type.name,
116
- to: filterStringKey(
117
- "name",
118
- schemaType.to.map((toType) => ({ name: toType.name || toType.type?.name || toType.type }))
119
- ),
120
- ...common2
121
- };
122
- default:
123
- return { extends: schemaType.type.name, ...common2 };
124
- }
125
- }
126
- function maybeString(val) {
127
- return typeof val == "string" ? val : void 0;
128
- }
129
- function maybeNumberAsString(val) {
130
- return typeof val == "number" ? val.toString() : void 0;
131
- }
132
- function maybeTrue(val) {
133
- return val === !0 ? !0 : void 0;
134
- }
135
- function conditionalTrue(val) {
136
- return typeof val == "function" ? FUNCTION_MARKER : maybeTrue(val);
137
- }
138
- function filterStringKey(key, arr) {
139
- return arr.filter((obj) => typeof obj[key] == "string");
140
- }
141
- function arrayifyString(val) {
142
- if (typeof val == "string")
143
- return [val];
144
- if (Array.isArray(val))
145
- return val.filter((elem) => typeof elem == "string");
146
- }
147
- const FUNCTION_MARKER = { __type: "function" }, UNKNOWN_MARKER = { __type: "unknown" }, UNDEFINED_MARKER = { __type: "undefined" }, CYCLIC_MARKER = { __type: "cyclic" }, MAX_DEPTH_MARKER = { __type: "maxDepth" };
148
- function convertUnknown(val, seen = /* @__PURE__ */ new Set(), maxDepth = MAX_DEPTH_UKNOWN) {
149
- if (maxDepth === 0) return MAX_DEPTH_MARKER;
150
- if (typeof val == "string" || typeof val == "boolean" || val === null || val === void 0)
151
- return val;
152
- if (typeof val == "number")
153
- return { __type: "number", value: val.toString() };
154
- if (typeof val == "function") return FUNCTION_MARKER;
155
- if (seen.has(val))
156
- return CYCLIC_MARKER;
157
- if (seen.add(val), typeof val == "object") {
158
- if (Array.isArray(val))
159
- return val.map((elem) => {
160
- const res = convertUnknown(elem, seen, maxDepth - 1);
161
- return res === void 0 ? UNDEFINED_MARKER : res;
162
- });
163
- if ("$$typeof" in val && "type" in val && "props" in val) {
164
- const { type, props } = val, strType = typeof type == "function" ? type.name : type;
165
- return typeof strType != "string" ? void 0 : {
166
- __type: "jsx",
167
- type: strType,
168
- props: convertUnknown(props, seen, maxDepth - 1)
169
- };
170
- }
171
- let hasType = !1;
172
- const result = {};
173
- for (const [key, field] of Object.entries(val))
174
- key === "__type" && (hasType = !0), result[key] = convertUnknown(field, seen, maxDepth - 1);
175
- return hasType ? { __type: "object", value: result } : result;
176
- }
177
- return UNKNOWN_MARKER;
178
- }
179
- function maybeStringOrJSX(val) {
180
- if (typeof val == "string") return val;
181
- if (val && typeof val == "object" && "$$typeof" in val && "type" in val && "props" in val) {
182
- const { type, props } = val, strType = typeof type == "function" ? type.name : type;
183
- return typeof strType != "string" ? void 0 : { __type: "jsx", type: strType, props: convertUnknown(props) };
184
- }
185
- }
186
- function processSchemaSynchronization(sync, response) {
187
- return processSetSynchronization(sync, response);
188
- }
189
- const ACTIONS_FLAG = "__experimental_actions", DEFAULT_ACTIONS = ["create", "update", "delete", "publish"], VALID_ACTIONS = DEFAULT_ACTIONS, readActions = (schemaType) => ACTIONS_FLAG in schemaType ? schemaType[ACTIONS_FLAG] : DEFAULT_ACTIONS, validateActions = (typeName, actions) => {
190
- if (!Array.isArray(actions))
191
- throw new Error(
192
- `The value of <type>.${ACTIONS_FLAG} should be an array with any of the actions ${VALID_ACTIONS.join(
193
- ", "
194
- )}`
195
- );
196
- const invalid = difference(actions, VALID_ACTIONS);
197
- if (invalid.length > 0)
198
- throw new Error(
199
- `Invalid action${invalid.length > 1 ? "s" : ""} configured for schema type "${typeName}": ${invalid.join(
200
- ", "
201
- )}. Valid actions are: ${VALID_ACTIONS.join(", ")}`
202
- );
203
- return actions;
204
- }, resolveEnabledActions = (schemaType) => validateActions(schemaType.name, readActions(schemaType)), isActionEnabled = (schemaType, action) => resolveEnabledActions(schemaType).includes(action);
205
- var assetSourceData = {
206
- name: "sanity.assetSourceData",
207
- title: "Asset Source Data",
208
- type: "object",
209
- fields: [
210
- {
211
- name: "name",
212
- title: "Source name",
213
- description: "A canonical name for the source this asset is originating from",
214
- type: "string"
215
- },
216
- {
217
- name: "id",
218
- title: "Asset Source ID",
219
- description: "The unique ID for the asset within the originating source so you can programatically find back to it",
220
- type: "string"
221
- },
222
- {
223
- name: "url",
224
- title: "Asset information URL",
225
- description: "A URL to find more information about this asset in the originating source",
226
- type: "string"
227
- }
228
- ]
229
- }, fileAsset = {
230
- name: "sanity.fileAsset",
231
- title: "File",
232
- type: "document",
233
- fieldsets: [
234
- {
235
- name: "system",
236
- title: "System fields",
237
- description: "These fields are managed by the system and not editable"
238
- }
239
- ],
240
- fields: [
241
- {
242
- name: "originalFilename",
243
- type: "string",
244
- title: "Original file name",
245
- readOnly: !0
246
- },
247
- {
248
- name: "label",
249
- type: "string",
250
- title: "Label"
251
- },
252
- {
253
- name: "title",
254
- type: "string",
255
- title: "Title"
256
- },
257
- {
258
- name: "description",
259
- type: "string",
260
- title: "Description"
261
- },
262
- {
263
- name: "altText",
264
- type: "string",
265
- title: "Alternative text"
266
- },
267
- {
268
- name: "sha1hash",
269
- type: "string",
270
- title: "SHA1 hash",
271
- readOnly: !0,
272
- fieldset: "system"
273
- },
274
- {
275
- name: "extension",
276
- type: "string",
277
- title: "File extension",
278
- readOnly: !0,
279
- fieldset: "system"
280
- },
281
- {
282
- name: "mimeType",
283
- type: "string",
284
- title: "Mime type",
285
- readOnly: !0,
286
- fieldset: "system"
287
- },
288
- {
289
- name: "size",
290
- type: "number",
291
- title: "File size in bytes",
292
- readOnly: !0,
293
- fieldset: "system"
294
- },
295
- {
296
- name: "assetId",
297
- type: "string",
298
- title: "Asset ID",
299
- readOnly: !0,
300
- fieldset: "system"
301
- },
302
- {
303
- name: "uploadId",
304
- type: "string",
305
- readOnly: !0,
306
- hidden: !0,
307
- fieldset: "system"
308
- },
309
- {
310
- name: "path",
311
- type: "string",
312
- title: "Path",
313
- readOnly: !0,
314
- fieldset: "system"
315
- },
316
- {
317
- name: "url",
318
- type: "string",
319
- title: "Url",
320
- readOnly: !0,
321
- fieldset: "system"
322
- },
323
- {
324
- name: "source",
325
- type: "sanity.assetSourceData",
326
- title: "Source",
327
- readOnly: !0,
328
- fieldset: "system"
329
- }
330
- ],
331
- preview: {
332
- select: {
333
- title: "originalFilename",
334
- path: "path",
335
- mimeType: "mimeType",
336
- size: "size"
337
- },
338
- prepare(doc) {
339
- return {
340
- title: doc.title || doc.path.split("/").slice(-1)[0],
341
- subtitle: `${doc.mimeType} (${(doc.size / 1024 / 1024).toFixed(2)} MB)`
342
- };
343
- }
344
- },
345
- orderings: [
346
- {
347
- title: "File size",
348
- name: "fileSizeDesc",
349
- by: [{ field: "size", direction: "desc" }]
350
- }
351
- ]
352
- }, geopoint = {
353
- title: "Geographical Point",
354
- name: "geopoint",
355
- type: "object",
356
- fields: [
357
- {
358
- name: "lat",
359
- type: "number",
360
- title: "Latitude"
361
- },
362
- {
363
- name: "lng",
364
- type: "number",
365
- title: "Longitude"
366
- },
367
- {
368
- name: "alt",
369
- type: "number",
370
- title: "Altitude"
371
- }
372
- ]
373
- }, imageAsset = {
374
- name: "sanity.imageAsset",
375
- title: "Image",
376
- type: "document",
377
- fieldsets: [
378
- {
379
- name: "system",
380
- title: "System fields",
381
- description: "These fields are managed by the system and not editable"
382
- }
383
- ],
384
- fields: [
385
- {
386
- name: "originalFilename",
387
- type: "string",
388
- title: "Original file name",
389
- readOnly: !0
390
- },
391
- {
392
- name: "label",
393
- type: "string",
394
- title: "Label"
395
- },
396
- {
397
- name: "title",
398
- type: "string",
399
- title: "Title"
400
- },
401
- {
402
- name: "description",
403
- type: "string",
404
- title: "Description"
405
- },
406
- {
407
- name: "altText",
408
- type: "string",
409
- title: "Alternative text"
410
- },
411
- {
412
- name: "sha1hash",
413
- type: "string",
414
- title: "SHA1 hash",
415
- readOnly: !0,
416
- fieldset: "system"
417
- },
418
- {
419
- name: "extension",
420
- type: "string",
421
- readOnly: !0,
422
- title: "File extension",
423
- fieldset: "system"
424
- },
425
- {
426
- name: "mimeType",
427
- type: "string",
428
- readOnly: !0,
429
- title: "Mime type",
430
- fieldset: "system"
431
- },
432
- {
433
- name: "size",
434
- type: "number",
435
- title: "File size in bytes",
436
- readOnly: !0,
437
- fieldset: "system"
438
- },
439
- {
440
- name: "assetId",
441
- type: "string",
442
- title: "Asset ID",
443
- readOnly: !0,
444
- fieldset: "system"
445
- },
446
- {
447
- name: "uploadId",
448
- type: "string",
449
- readOnly: !0,
450
- hidden: !0,
451
- fieldset: "system"
452
- },
453
- {
454
- name: "path",
455
- type: "string",
456
- title: "Path",
457
- readOnly: !0,
458
- fieldset: "system"
459
- },
460
- {
461
- name: "url",
462
- type: "string",
463
- title: "Url",
464
- readOnly: !0,
465
- fieldset: "system"
466
- },
467
- {
468
- name: "metadata",
469
- type: "sanity.imageMetadata",
470
- title: "Metadata"
471
- },
472
- {
473
- name: "source",
474
- type: "sanity.assetSourceData",
475
- title: "Source",
476
- readOnly: !0,
477
- fieldset: "system"
478
- }
479
- ],
480
- preview: {
481
- select: {
482
- id: "_id",
483
- title: "originalFilename",
484
- mimeType: "mimeType",
485
- size: "size"
486
- },
487
- prepare(doc) {
488
- return {
489
- title: doc.title || typeof doc.path == "string" && doc.path.split("/").slice(-1)[0],
490
- media: { asset: { _ref: doc.id } },
491
- subtitle: `${doc.mimeType} (${(Number(doc.size) / 1024 / 1024).toFixed(2)} MB)`
492
- };
493
- }
494
- },
495
- orderings: [
496
- {
497
- title: "File size",
498
- name: "fileSizeDesc",
499
- by: [{ field: "size", direction: "desc" }]
500
- }
501
- ]
502
- }, imageCrop = {
503
- name: "sanity.imageCrop",
504
- title: "Image crop",
505
- type: "object",
506
- fields: [
507
- {
508
- name: "top",
509
- type: "number"
510
- },
511
- {
512
- name: "bottom",
513
- type: "number"
514
- },
515
- {
516
- name: "left",
517
- type: "number"
518
- },
519
- {
520
- name: "right",
521
- type: "number"
522
- }
523
- ]
524
- }, imageDimensions = {
525
- name: "sanity.imageDimensions",
526
- type: "object",
527
- title: "Image dimensions",
528
- fields: [
529
- { name: "height", type: "number", title: "Height", readOnly: !0 },
530
- { name: "width", type: "number", title: "Width", readOnly: !0 },
531
- { name: "aspectRatio", type: "number", title: "Aspect ratio", readOnly: !0 }
532
- ]
533
- }, imageHotspot = {
534
- name: "sanity.imageHotspot",
535
- title: "Image hotspot",
536
- type: "object",
537
- fields: [
538
- {
539
- name: "x",
540
- type: "number"
541
- },
542
- {
543
- name: "y",
544
- type: "number"
545
- },
546
- {
547
- name: "height",
548
- type: "number"
549
- },
550
- {
551
- name: "width",
552
- type: "number"
553
- }
554
- ]
555
- }, imageMetadata = {
556
- name: "sanity.imageMetadata",
557
- title: "Image metadata",
558
- type: "object",
559
- fieldsets: [
560
- {
561
- name: "extra",
562
- title: "Extra metadata\u2026",
563
- options: {
564
- collapsable: !0
565
- }
566
- }
567
- ],
568
- fields: [
569
- {
570
- name: "location",
571
- type: "geopoint"
572
- },
573
- {
574
- name: "dimensions",
575
- title: "Dimensions",
576
- type: "sanity.imageDimensions",
577
- fieldset: "extra"
578
- },
579
- {
580
- name: "palette",
581
- type: "sanity.imagePalette",
582
- title: "Palette",
583
- fieldset: "extra"
584
- },
585
- {
586
- name: "lqip",
587
- title: "LQIP (Low-Quality Image Placeholder)",
588
- type: "string",
589
- readOnly: !0
590
- },
591
- {
592
- name: "blurHash",
593
- title: "BlurHash",
594
- type: "string",
595
- readOnly: !0
596
- },
597
- {
598
- name: "hasAlpha",
599
- title: "Has alpha channel",
600
- type: "boolean",
601
- readOnly: !0
602
- },
603
- {
604
- name: "isOpaque",
605
- title: "Is opaque",
606
- type: "boolean",
607
- readOnly: !0
608
- }
609
- ]
610
- }, imagePalette = {
611
- name: "sanity.imagePalette",
612
- title: "Image palette",
613
- type: "object",
614
- fields: [
615
- { name: "darkMuted", type: "sanity.imagePaletteSwatch", title: "Dark Muted" },
616
- { name: "lightVibrant", type: "sanity.imagePaletteSwatch", title: "Light Vibrant" },
617
- { name: "darkVibrant", type: "sanity.imagePaletteSwatch", title: "Dark Vibrant" },
618
- { name: "vibrant", type: "sanity.imagePaletteSwatch", title: "Vibrant" },
619
- { name: "dominant", type: "sanity.imagePaletteSwatch", title: "Dominant" },
620
- { name: "lightMuted", type: "sanity.imagePaletteSwatch", title: "Light Muted" },
621
- { name: "muted", type: "sanity.imagePaletteSwatch", title: "Muted" }
622
- ]
623
- }, imagePaletteSwatch = {
624
- name: "sanity.imagePaletteSwatch",
625
- title: "Image palette swatch",
626
- type: "object",
627
- fields: [
628
- { name: "background", type: "string", title: "Background", readOnly: !0 },
629
- { name: "foreground", type: "string", title: "Foreground", readOnly: !0 },
630
- { name: "population", type: "number", title: "Population", readOnly: !0 },
631
- { name: "title", type: "string", title: "String", readOnly: !0 }
632
- ]
633
- }, slug$1 = {
634
- title: "Slug",
635
- name: "slug",
636
- type: "object",
637
- fields: [
638
- {
639
- name: "current",
640
- title: "Current slug",
641
- type: "string",
642
- validation: (Rule) => Rule.required()
643
- },
644
- {
645
- // The source field is deprecated/unused, but leaving it included and hidden
646
- // to prevent rendering "Unknown field" warnings on legacy data
647
- name: "source",
648
- title: "Source field",
649
- type: "string",
650
- hidden: !0
651
- }
652
- ]
653
- };
654
- const builtinTypes = [
655
- assetSourceData,
656
- slug$1,
657
- geopoint,
658
- // legacyRichDate,
659
- imageAsset,
660
- fileAsset,
661
- imageCrop,
662
- imageHotspot,
663
- imageMetadata,
664
- imageDimensions,
665
- imagePalette,
666
- imagePaletteSwatch
667
- ], documentDefaultFields = (typeName) => ({
668
- _id: {
669
- type: "objectAttribute",
670
- value: { type: "string" }
671
- },
672
- _type: {
673
- type: "objectAttribute",
674
- value: { type: "string", value: typeName }
675
- },
676
- _createdAt: {
677
- type: "objectAttribute",
678
- value: { type: "string" }
679
- },
680
- _updatedAt: {
681
- type: "objectAttribute",
682
- value: { type: "string" }
683
- },
684
- _rev: {
685
- type: "objectAttribute",
686
- value: { type: "string" }
687
- }
688
- }), typesMap = /* @__PURE__ */ new Map([
689
- ["text", { type: "string" }],
690
- ["url", { type: "string" }],
691
- ["datetime", { type: "string" }],
692
- ["date", { type: "string" }],
693
- ["boolean", { type: "boolean" }],
694
- ["email", { type: "string" }]
695
- ]);
696
- function extractSchema(schemaDef, extractOptions = {}) {
697
- const inlineFields = /* @__PURE__ */ new Set(), documentTypes = /* @__PURE__ */ new Map(), schema = [];
698
- sortByDependencies(schemaDef).forEach((typeName) => {
699
- const schemaType = schemaDef.get(typeName);
700
- if (schemaType === void 0)
701
- return;
702
- const base = convertBaseType(schemaType);
703
- base !== null && (base.type === "type" && inlineFields.add(schemaType), base.type === "document" && documentTypes.set(typeName, base), schema.push(base));
704
- });
705
- function convertBaseType(schemaType) {
706
- let typeName;
707
- if (schemaType.type ? typeName = schemaType.type.name : "jsonType" in schemaType && (typeName = schemaType.jsonType), typeName === "document" && isObjectType(schemaType)) {
708
- const defaultAttributes = documentDefaultFields(schemaType.name), object2 = createObject(schemaType);
709
- return object2.type === "unknown" ? null : {
710
- name: schemaType.name,
711
- type: "document",
712
- attributes: {
713
- ...defaultAttributes,
714
- ...object2.attributes
715
- }
716
- };
717
- }
718
- const value = convertSchemaType(schemaType);
719
- return value.type === "unknown" ? null : value.type === "object" ? {
720
- name: schemaType.name,
721
- type: "type",
722
- value: {
723
- type: "object",
724
- attributes: {
725
- _type: {
726
- type: "objectAttribute",
727
- value: {
728
- type: "string",
729
- value: schemaType.name
730
- }
731
- },
732
- ...value.attributes
733
- }
734
- }
735
- } : {
736
- name: schemaType.name,
737
- type: "type",
738
- value
739
- };
740
- }
741
- function convertSchemaType(schemaType) {
742
- if (inlineFields.has(schemaType.type))
743
- return { type: "inline", name: schemaType.type.name };
744
- if (schemaType.type?.type?.name === "object")
745
- return { type: "inline", name: schemaType.type.name };
746
- if (isStringType(schemaType))
747
- return createStringTypeNodeDefintion(schemaType);
748
- if (isNumberType(schemaType))
749
- return createNumberTypeNodeDefintion(schemaType);
750
- if (schemaType.type && typesMap.has(schemaType.type.name))
751
- return typesMap.get(schemaType.type.name);
752
- if (isCrossDatasetReferenceType(schemaType))
753
- return { type: "unknown" };
754
- if (isGlobalDocumentReferenceType(schemaType))
755
- return { type: "unknown" };
756
- if (isReferenceType(schemaType))
757
- return createReferenceTypeNodeDefintion(schemaType);
758
- if (isArrayType(schemaType))
759
- return createArray(schemaType);
760
- if (isObjectType(schemaType))
761
- return createObject(schemaType);
762
- if (lastType(schemaType)?.name === "document") {
763
- const doc = documentTypes.get(schemaType.name);
764
- return doc === void 0 ? { type: "unknown" } : { type: "object", attributes: doc?.attributes };
765
- }
766
- throw new Error(`Type "${schemaType.name}" not found`);
767
- }
768
- function createObject(schemaType) {
769
- const attributes = {}, fields = gatherFields(schemaType);
770
- for (const field of fields) {
771
- const fieldIsRequired = isFieldRequired(field), value = convertSchemaType(field.type);
772
- if (value === null)
773
- continue;
774
- hasAssetRequired(field) && value.type === "object" && (value.attributes.asset.optional = !1);
775
- const optional = extractOptions.enforceRequiredFields ? fieldIsRequired === !1 : !0;
776
- attributes[field.name] = {
777
- type: "objectAttribute",
778
- value,
779
- optional
780
- };
781
- }
782
- return Object.keys(attributes).length === 0 ? { type: "unknown" } : (schemaType.type?.name !== "document" && schemaType.name !== "object" && (attributes._type = {
783
- type: "objectAttribute",
784
- value: {
785
- type: "string",
786
- value: schemaType.name
787
- }
788
- }), {
789
- type: "object",
790
- attributes
791
- });
792
- }
793
- function createArray(arraySchemaType) {
794
- const of = [];
795
- for (const item of arraySchemaType.of) {
796
- const field = convertSchemaType(item);
797
- field.type === "inline" ? of.push({
798
- type: "object",
799
- attributes: {
800
- _key: createKeyField()
801
- },
802
- rest: field
803
- }) : (field.type === "object" && (field.rest = {
804
- type: "object",
805
- attributes: {
806
- _key: createKeyField()
807
- }
808
- }), of.push(field));
809
- }
810
- return of.length === 0 ? { type: "null" } : {
811
- type: "array",
812
- of: of.length > 1 ? {
813
- type: "union",
814
- of
815
- } : of[0]
816
- };
817
- }
818
- return schema;
819
- }
820
- function createKeyField() {
821
- return {
822
- type: "objectAttribute",
823
- value: {
824
- type: "string"
825
- }
826
- };
827
- }
828
- function isFieldRequired(field) {
829
- const { validation } = field.type;
830
- if (!validation)
831
- return !1;
832
- const rules = Array.isArray(validation) ? validation : [validation];
833
- for (const rule of rules) {
834
- let required = !1;
835
- const proxy = new Proxy(
836
- {},
837
- {
838
- get: (target, methodName) => () => (methodName === "required" && (required = !0), proxy)
839
- }
840
- );
841
- if (typeof rule == "function" && (rule(proxy), required) || typeof rule == "object" && rule !== null && "_required" in rule && rule._required === "required")
842
- return !0;
843
- }
844
- return !1;
845
- }
846
- function hasAssetRequired(field) {
847
- const { validation } = field.type;
848
- if (!validation)
849
- return !1;
850
- const rules = Array.isArray(validation) ? validation : [validation];
851
- for (const rule of rules) {
852
- let assetRequired = !1;
853
- const proxy = new Proxy(
854
- {},
855
- {
856
- get: (target, methodName) => () => (methodName === "assetRequired" && (assetRequired = !0), proxy)
857
- }
858
- );
859
- if (typeof rule == "function" && (rule(proxy), assetRequired) || typeof rule == "object" && rule !== null && "_rules" in rule && Array.isArray(rule._rules) && rule._rules.some((r) => r.flag === "assetRequired"))
860
- return !0;
861
- }
862
- return !1;
863
- }
864
- function isObjectType(typeDef) {
865
- return isType(typeDef, "object") || typeDef.jsonType === "object" || "fields" in typeDef;
866
- }
867
- function isArrayType(typeDef) {
868
- return isType(typeDef, "array");
869
- }
870
- function isReferenceType(typeDef) {
871
- return isType(typeDef, "reference");
872
- }
873
- function isCrossDatasetReferenceType(typeDef) {
874
- return isType(typeDef, "crossDatasetReference");
875
- }
876
- function isGlobalDocumentReferenceType(typeDef) {
877
- return isType(typeDef, "globalDocumentReference");
878
- }
879
- function isStringType(typeDef) {
880
- return isType(typeDef, "string");
881
- }
882
- function isNumberType(typeDef) {
883
- return isType(typeDef, "number");
884
- }
885
- function createStringTypeNodeDefintion(stringSchemaType) {
886
- const listOptions = stringSchemaType.options?.list;
887
- return listOptions && Array.isArray(listOptions) ? {
888
- type: "union",
889
- of: listOptions.map((v) => ({
890
- type: "string",
891
- value: typeof v == "string" ? v : v.value
892
- }))
893
- } : {
894
- type: "string"
895
- };
896
- }
897
- function createNumberTypeNodeDefintion(numberSchemaType) {
898
- const listOptions = numberSchemaType.options?.list;
899
- return listOptions && Array.isArray(listOptions) ? {
900
- type: "union",
901
- of: listOptions.map((v) => ({
902
- type: "number",
903
- value: typeof v == "number" ? v : v.value
904
- }))
905
- } : {
906
- type: "number"
907
- };
908
- }
909
- function createReferenceTypeNodeDefintion(reference2) {
910
- const references = gatherReferenceNames(reference2);
911
- return references.length === 1 ? createReferenceTypeNode(references[0]) : {
912
- type: "union",
913
- of: references.map((name) => createReferenceTypeNode(name))
914
- };
915
- }
916
- function gatherReferenceNames(type) {
917
- const allReferences = gatherReferenceTypes(type);
918
- return [...new Set(allReferences.map((ref) => ref.name))];
919
- }
920
- function gatherReferenceTypes(type) {
921
- const refTo = "to" in type ? type.to : [];
922
- return "type" in type && isReferenceType(type.type) ? [...gatherReferenceTypes(type.type), ...refTo] : refTo;
923
- }
924
- function gatherFields(type) {
925
- return "fields" in type ? type.type ? gatherFields(type.type).concat(type.fields) : type.fields : [];
926
- }
927
- function isType(typeDef, typeName) {
928
- let type = typeDef;
929
- for (; type; ) {
930
- if (type.name === typeName || type.type && type.type.name === typeName)
931
- return !0;
932
- type = type.type;
933
- }
934
- return !1;
935
- }
936
- function lastType(typeDef) {
937
- let type = typeDef;
938
- for (; type; ) {
939
- if (!type.type)
940
- return type;
941
- type = type.type;
942
- }
943
- }
944
- function sortByDependencies(compiledSchema) {
945
- const seen = /* @__PURE__ */ new Set();
946
- function walkDependencies(schemaType, dependencies) {
947
- if (!seen.has(schemaType)) {
948
- if (seen.add(schemaType), "fields" in schemaType)
949
- for (const field of gatherFields(schemaType)) {
950
- const last = lastType(field.type);
951
- if (last.name === "document") {
952
- dependencies.add(last);
953
- continue;
954
- }
955
- let schemaTypeName;
956
- schemaType.type.type ? schemaTypeName = field.type.type.name : "jsonType" in schemaType.type && (schemaTypeName = field.type.jsonType), (schemaTypeName === "object" || schemaTypeName === "block") && (isReferenceType(field.type) ? field.type.to.forEach((ref) => dependencies.add(ref.type)) : dependencies.add(field.type)), walkDependencies(field.type, dependencies);
957
- }
958
- else if ("of" in schemaType)
959
- for (const item of schemaType.of)
960
- walkDependencies(item, dependencies);
961
- }
962
- }
963
- const dependencyMap = /* @__PURE__ */ new Map();
964
- compiledSchema.getTypeNames().forEach((typeName) => {
965
- const schemaType = compiledSchema.get(typeName);
966
- if (schemaType === void 0 || schemaType.type === null)
967
- return;
968
- const dependencies = /* @__PURE__ */ new Set();
969
- walkDependencies(schemaType, dependencies), dependencyMap.set(schemaType, dependencies), seen.clear();
970
- });
971
- const typeNames = [], currentlyVisiting = /* @__PURE__ */ new Set(), visited = /* @__PURE__ */ new Set();
972
- function visit(type) {
973
- if (visited.has(type) || currentlyVisiting.has(type))
974
- return;
975
- currentlyVisiting.add(type);
976
- const deps = dependencyMap.get(type);
977
- deps !== void 0 && deps.forEach((dep) => visit(dep)), currentlyVisiting.delete(type), visited.add(type), typeNames.includes(type.name) || typeNames.unshift(type.name);
978
- }
979
- for (const [type] of dependencyMap)
980
- visit(type);
981
- return typeNames;
982
- }
983
- const HELP_IDS = {
984
- TYPE_INVALID: "schema-type-invalid",
985
- TYPE_IS_ESM_MODULE: "schema-type-is-esm-module",
986
- TYPE_NAME_RESERVED: "schema-type-name-reserved",
987
- TYPE_MISSING_NAME: "schema-type-missing-name-or-type",
988
- TYPE_MISSING_TYPE: "schema-type-missing-name-or-type",
989
- TYPE_TITLE_RECOMMENDED: "schema-type-title-is-recommended",
990
- TYPE_TITLE_INVALID: "schema-type-title-is-recommended",
991
- OBJECT_FIELDS_INVALID: "schema-object-fields-invalid",
992
- OBJECT_FIELD_NOT_UNIQUE: "schema-object-fields-invalid",
993
- OBJECT_FIELD_NAME_INVALID: "schema-object-fields-invalid",
994
- OBJECT_FIELD_DEFINITION_INVALID_TYPE: "schema-object-fields-invalid",
995
- ARRAY_PREDEFINED_CHOICES_INVALID: "schema-predefined-choices-invalid",
996
- ARRAY_OF_ARRAY: "schema-array-of-array",
997
- ARRAY_OF_INVALID: "schema-array-of-invalid",
998
- ARRAY_OF_NOT_UNIQUE: "schema-array-of-invalid",
999
- ARRAY_OF_TYPE_GLOBAL_TYPE_CONFLICT: "schema-array-of-type-global-type-conflict",
1000
- ARRAY_OF_TYPE_BUILTIN_TYPE_CONFLICT: "schema-array-of-type-builtin-type-conflict",
1001
- REFERENCE_TO_INVALID: "schema-reference-to-invalid",
1002
- REFERENCE_TO_NOT_UNIQUE: "schema-reference-to-invalid",
1003
- REFERENCE_INVALID_OPTIONS: "schema-reference-invalid-options",
1004
- REFERENCE_INVALID_OPTIONS_LOCATION: "schema-reference-options-nesting",
1005
- REFERENCE_INVALID_FILTER_PARAMS_COMBINATION: "schema-reference-filter-params-combination",
1006
- SLUG_SLUGIFY_FN_RENAMED: "slug-slugifyfn-renamed",
1007
- ASSET_METADATA_FIELD_INVALID: "asset-metadata-field-invalid",
1008
- CROSS_DATASET_REFERENCE_INVALID: "cross-dataset-reference-invalid",
1009
- GLOBAL_DOCUMENT_REFERENCE_INVALID: "global-document-reference-invalid",
1010
- DEPRECATED_BLOCKEDITOR_KEY: "schema-deprecated-blockeditor-key",
1011
- STANDALONE_BLOCK_TYPE: "schema-standalone-block-type"
1012
- };
1013
- function createValidationResult(severity, message, helpId) {
1014
- if (helpId && !Object.keys(HELP_IDS).some((id) => HELP_IDS[id] === helpId))
1015
- throw new Error(
1016
- `Used the unknown helpId "${helpId}", please add it to the array in createValidationResult.js`
1017
- );
1018
- return {
1019
- severity,
1020
- message,
1021
- helpId
1022
- };
1023
- }
1024
- const error = (message, helpId) => createValidationResult("error", message, helpId), warning = (message, helpId) => createValidationResult("warning", message, helpId);
1025
- function groupProblems(types) {
1026
- return flatten(types.map((type) => getTypeProblems(type))).filter(
1027
- (type) => type.problems.length > 0
1028
- );
1029
- }
1030
- function createTypeWithMembersProblemsAccessor(memberPropertyName, getMembers = (type) => get(type, memberPropertyName)) {
1031
- return function(type, parentPath) {
1032
- const currentPath = [
1033
- ...parentPath,
1034
- { kind: "type", type: type.type, name: type.name }
1035
- ], members = getMembers(type) || [], memberProblems = Array.isArray(members) ? members.map((memberType) => {
1036
- const propertySegment = {
1037
- kind: "property",
1038
- name: memberPropertyName
1039
- }, memberPath = [...currentPath, propertySegment];
1040
- return getTypeProblems(memberType, memberPath);
1041
- }) : [
1042
- [
1043
- {
1044
- path: currentPath,
1045
- problems: [error(`Member declaration (${memberPropertyName}) is not an array`)]
1046
- }
1047
- ]
1048
- ];
1049
- return [
1050
- {
1051
- path: currentPath,
1052
- problems: type._problems || []
1053
- },
1054
- ...flatten(memberProblems)
1055
- ];
1056
- };
1057
- }
1058
- const arrify = (val) => Array.isArray(val) ? val : typeof val > "u" && [] || [val], getObjectProblems = createTypeWithMembersProblemsAccessor("fields"), getImageProblems = createTypeWithMembersProblemsAccessor("fields"), getFileProblems = createTypeWithMembersProblemsAccessor("fields"), getArrayProblems = createTypeWithMembersProblemsAccessor("of"), getReferenceProblems = createTypeWithMembersProblemsAccessor(
1059
- "to",
1060
- (type) => "to" in type ? arrify(type.to) : []
1061
- ), getBlockAnnotationProblems = createTypeWithMembersProblemsAccessor("marks.annotations"), getBlockMemberProblems = createTypeWithMembersProblemsAccessor("of"), getBlockProblems = (type, problems) => [
1062
- ...getBlockAnnotationProblems(type, problems),
1063
- ...getBlockMemberProblems(type, problems)
1064
- ];
1065
- function getDefaultProblems(type, path = []) {
1066
- return [
1067
- {
1068
- path: [...path, { kind: "type", type: type.type, name: type.name }],
1069
- problems: type._problems || []
1070
- }
1071
- ];
1072
- }
1073
- function getTypeProblems(type, path = []) {
1074
- switch (type.type) {
1075
- case "object":
1076
- return getObjectProblems(type, path);
1077
- case "document":
1078
- return getObjectProblems(type, path);
1079
- case "array":
1080
- return getArrayProblems(type, path);
1081
- case "reference":
1082
- return getReferenceProblems(type, path);
1083
- case "block":
1084
- return getBlockProblems(type, path);
1085
- case "image":
1086
- return getImageProblems(type, path);
1087
- case "file":
1088
- return getFileProblems(type, path);
1089
- default:
1090
- return getDefaultProblems(type, path);
1091
- }
1092
- }
1093
- function getDupes(array2, selector = (v) => v) {
1094
- const dupes = array2.reduce((acc, item) => {
1095
- const key = selector(item);
1096
- return acc[key] || (acc[key] = []), acc[key].push(item), acc;
1097
- }, {});
1098
- return Object.keys(dupes).map((key) => dupes[key].length > 1 ? dupes[key] : null).filter(Boolean);
1099
- }
1100
- const NOOP_VISITOR = (typeDef) => typeDef, TYPE_TYPE = { name: "type", type: null }, FUTURE_RESERVED = ["any", "time", "date"];
1101
- function traverseSchema(types = [], coreTypes2 = [], visitor = NOOP_VISITOR) {
1102
- const coreTypesRegistry = /* @__PURE__ */ Object.create(null), registry = /* @__PURE__ */ Object.create(null), coreTypeNames2 = coreTypes2.map((typeDef) => typeDef.name), reservedTypeNames = FUTURE_RESERVED.concat(coreTypeNames2), typeNames = types.map((typeDef) => typeDef && typeDef.name).filter(Boolean);
1103
- coreTypes2.forEach((coreType) => {
1104
- coreTypesRegistry[coreType.name] = coreType;
1105
- }), types.forEach((type, i) => {
1106
- registry[type && type.name || `__unnamed_${i}`] = {};
1107
- });
1108
- function getType(typeName) {
1109
- return typeName === "type" ? TYPE_TYPE : coreTypesRegistry[typeName] || registry[typeName] || null;
1110
- }
1111
- const duplicateNames = uniq(flatten(getDupes(typeNames)));
1112
- function isDuplicate(typeName) {
1113
- return duplicateNames.includes(typeName);
1114
- }
1115
- function getTypeNames() {
1116
- return typeNames.concat(coreTypeNames2);
1117
- }
1118
- function isReserved(typeName) {
1119
- return typeName === "type" || reservedTypeNames.includes(typeName);
1120
- }
1121
- const visitType = (isRoot) => (typeDef, index) => visitor(typeDef, {
1122
- visit: visitType(!1),
1123
- isRoot,
1124
- getType,
1125
- getTypeNames,
1126
- isReserved,
1127
- isDuplicate,
1128
- index
1129
- });
1130
- return coreTypes2.forEach((coreTypeDef) => {
1131
- Object.assign(coreTypesRegistry[coreTypeDef.name], visitType(coreTypeDef));
1132
- }), types.forEach((typeDef, i) => {
1133
- Object.assign(
1134
- registry[typeDef && typeDef.name || `__unnamed_${i}`],
1135
- visitType(!0)(typeDef, i)
1136
- );
1137
- }), {
1138
- get(typeName) {
1139
- const res = registry[typeName] || coreTypesRegistry[typeName];
1140
- if (res)
1141
- return res;
1142
- throw new Error(`No such type: ${typeName}`);
1143
- },
1144
- has(typeName) {
1145
- return typeName in registry || typeName in coreTypesRegistry;
1146
- },
1147
- getTypeNames() {
1148
- return Object.keys(registry);
1149
- },
1150
- getTypes() {
1151
- return this.getTypeNames().map(this.get);
1152
- },
1153
- toJSON() {
1154
- return this.getTypes();
1155
- }
1156
- };
1157
- }
1158
- const coreTypes = [
1159
- { name: "array", jsonType: "array", type: "type" },
1160
- { name: "block", jsonType: "object", type: "type" },
1161
- { name: "boolean", jsonType: "boolean", type: "type" },
1162
- { name: "datetime", jsonType: "string", type: "type" },
1163
- { name: "date", jsonType: "string", type: "type" },
1164
- { name: "document", jsonType: "object", type: "type" },
1165
- { name: "email", jsonType: "string", type: "type" },
1166
- { name: "file", jsonType: "object", type: "type" },
1167
- { name: "geopoint", jsonType: "object", type: "type" },
1168
- { name: "image", jsonType: "object", type: "type" },
1169
- { name: "number", jsonType: "number", type: "type" },
1170
- { name: "object", jsonType: "object", type: "type" },
1171
- { name: "reference", jsonType: "object", type: "type" },
1172
- { name: "crossDatasetReference", jsonType: "object", type: "type" },
1173
- { name: "globalDocumentReference", jsonType: "object", type: "type" },
1174
- { name: "slug", jsonType: "object", type: "type" },
1175
- { name: "span", jsonType: "object", type: "type" },
1176
- { name: "string", jsonType: "string", type: "type" },
1177
- { name: "telephone", jsonType: "string", type: "type" },
1178
- { name: "text", jsonType: "string", type: "type" },
1179
- { name: "url", jsonType: "string", type: "type" }
1180
- ], coreTypeNames = coreTypes.map((t) => t.name);
1181
- function traverseSanitySchema(schemaTypes, visitor) {
1182
- return traverseSchema(schemaTypes, coreTypes, visitor);
1183
- }
1184
- function isPrimitiveTypeName(typeName) {
1185
- return typeName === "string" || typeName === "number" || typeName === "boolean";
1186
- }
1187
- function isAssignable(typeName, type) {
1188
- return (typeof type.name == "string" ? type.name : type.type) === typeName;
1189
- }
1190
- function quote$2(n) {
1191
- return `"${n}"`;
1192
- }
1193
- function pluralize(arr, suf = "s") {
1194
- return arr.length === 1 ? "" : suf;
1195
- }
1196
- function format(value) {
1197
- return Array.isArray(value) ? `array with ${value.length} entries` : typeof value == "object" && value !== null ? `object with keys ${humanizeList(Object.keys(value).map(quote$2))}` : quote$2(value);
1198
- }
1199
- var array = (typeDef, visitorContext) => {
1200
- const ofIsArray = Array.isArray(typeDef.of);
1201
- if (ofIsArray) {
1202
- const invalid = typeDef.of.reduce((errs, def, idx) => {
1203
- if (typeof def.name == "string" && // specifying the same name as the type is redundant, but should not be a hard error at this point
1204
- // Consider showing a warning for this and deprecate this ability eventually
1205
- def.name !== def.type && coreTypeNames.includes(def.name))
1206
- return errs.concat(
1207
- error(
1208
- `Found array member declaration with the same type name as a built-in type ("${def.name}"). Array members can not be given the same name as a built-in type.`,
1209
- HELP_IDS.ARRAY_OF_TYPE_BUILTIN_TYPE_CONFLICT
1210
- )
1211
- );
1212
- if (def.type === "object" && def.name && visitorContext.getType(def.name))
1213
- return errs.concat(
1214
- warning(
1215
- `Found array member declaration with the same name as the global schema type "${def.name}". It's recommended to use a unique name to avoid possibly incompatible data types that shares the same name.`,
1216
- HELP_IDS.ARRAY_OF_TYPE_GLOBAL_TYPE_CONFLICT
1217
- )
1218
- );
1219
- if (def.type === "array")
1220
- return errs.concat(
1221
- error(
1222
- 'Found array member declaration of type "array" - multidimensional arrays are not currently supported by Sanity',
1223
- HELP_IDS.ARRAY_OF_ARRAY
1224
- )
1225
- );
1226
- if (def)
1227
- return errs;
1228
- const err = `Found ${def === null ? "null" : typeof def}, expected member declaration`;
1229
- return errs.concat(
1230
- error(
1231
- `Found invalid type member declaration in array at index ${idx}: ${err}`,
1232
- HELP_IDS.ARRAY_OF_INVALID
1233
- )
1234
- );
1235
- }, []);
1236
- if (invalid.length > 0)
1237
- return {
1238
- ...typeDef,
1239
- of: [],
1240
- _problems: invalid
1241
- };
1242
- }
1243
- const problems = flatten([
1244
- ofIsArray ? getDupes(typeDef.of, (t) => `${t.name};${t.type}`).map(
1245
- (dupes) => error(
1246
- `Found ${dupes.length} members with same type, but not unique names "${dupes[0].type}" in array. This makes it impossible to tell their values apart and you should consider naming them`,
1247
- HELP_IDS.ARRAY_OF_NOT_UNIQUE
1248
- )
1249
- ) : error(
1250
- 'The array type is missing or having an invalid value for the required "of" property',
1251
- HELP_IDS.ARRAY_OF_INVALID
1252
- )
1253
- ]), of = ofIsArray ? typeDef.of : [], hasObjectTypesWithoutName = of.some(
1254
- (type) => type.type === "object" && typeof type.name > "u"
1255
- );
1256
- of.some((ofType) => ofType.type === "block") && hasObjectTypesWithoutName && problems.push(
1257
- error(
1258
- "The array type's 'of' property can't have an object type without a 'name' property as member, when the 'block' type is also a member of that array.",
1259
- HELP_IDS.ARRAY_OF_INVALID
1260
- )
1261
- );
1262
- const [primitiveTypes, objectTypes] = partition(
1263
- of,
1264
- (ofType) => isPrimitiveTypeName(ofType.type) || isPrimitiveTypeName(visitorContext.getType(ofType.type)?.jsonType)
1265
- ), isMixedArray = primitiveTypes.length > 0 && objectTypes.length > 0;
1266
- if (isMixedArray) {
1267
- const primitiveTypeNames = primitiveTypes.map((t) => t.type), objectTypeNames = objectTypes.map((t) => t.type);
1268
- problems.push(
1269
- error(
1270
- `The array type's 'of' property can't have both object types and primitive types (found primitive type ${pluralize(
1271
- primitiveTypeNames
1272
- )} ${humanizeList(primitiveTypeNames.map(quote$2))} and object type${pluralize(
1273
- objectTypeNames
1274
- )} ${humanizeList(objectTypeNames.map(quote$2))})`,
1275
- HELP_IDS.ARRAY_OF_INVALID
1276
- )
1277
- );
1278
- }
1279
- const list = typeDef?.options?.list;
1280
- return !isMixedArray && Array.isArray(list) && (primitiveTypes.length > 0 ? list.forEach((option) => {
1281
- const value = option?.value ?? option;
1282
- if (!primitiveTypes.some((primitiveType) => typeof value === visitorContext.getType(primitiveType.type).jsonType)) {
1283
- const formattedTypeList = humanizeList(
1284
- primitiveTypes.map((t) => t.name || t.type),
1285
- { conjunction: "or" }
1286
- );
1287
- problems.push(
1288
- error(
1289
- `An invalid entry found in options.list: ${format(
1290
- value
1291
- )}. Must be either a value of type ${formattedTypeList}, or an object with {title: string, value: ${formattedTypeList}}`,
1292
- HELP_IDS.ARRAY_PREDEFINED_CHOICES_INVALID
1293
- )
1294
- );
1295
- }
1296
- }) : list.forEach((option) => {
1297
- const optionTypeName = option._type || "object";
1298
- objectTypes.some(
1299
- (validObjectType) => isAssignable(optionTypeName, validObjectType)
1300
- ) || problems.push(
1301
- error(
1302
- `An invalid entry found in options.list: ${format(
1303
- option
1304
- )}. Must be an object with "_type" set to ${humanizeList(
1305
- objectTypes.map((t) => t.name || t.type).map((t) => t === "object" ? "undefined" : quote$2(t)),
1306
- { conjunction: "or" }
1307
- )}`,
1308
- HELP_IDS.ARRAY_PREDEFINED_CHOICES_INVALID
1309
- )
1310
- );
1311
- })), typeDef?.options?.list && typeDef?.options?.layout === "tags" && problems.push(
1312
- warning(
1313
- "Found array member declaration with both tags layout and a list of predefined values. If you want to display a list of predefined values, remove the tags layout from `options`."
1314
- )
1315
- ), {
1316
- ...typeDef,
1317
- of: of.map(visitorContext.visit),
1318
- _problems: problems
1319
- };
1320
- };
1321
- function isJSONTypeOf(type, jsonType, visitorContext) {
1322
- if ("jsonType" in type)
1323
- return type.jsonType === jsonType;
1324
- const parentType = visitorContext.getType(type.type);
1325
- if (!parentType)
1326
- throw new Error(`Could not resolve jsonType of ${type.name}. No parent type found`);
1327
- return isJSONTypeOf(parentType, jsonType, visitorContext);
1328
- }
1329
- const getTypeOf = (thing) => Array.isArray(thing) ? "array" : typeof thing, quote$1 = (str) => `"${str}"`, allowedKeys = [
1330
- "components",
1331
- "lists",
1332
- "marks",
1333
- "name",
1334
- "of",
1335
- "options",
1336
- "styles",
1337
- "title",
1338
- "type",
1339
- "validation"
1340
- ], allowedMarkKeys = ["decorators", "annotations"], allowedStyleKeys = ["blockEditor", "title", "value", "icon", "component"], allowedDecoratorKeys = ["blockEditor", "title", "value", "icon", "component"], allowedListKeys = ["title", "value", "icon", "component"], supportedBuiltInObjectTypes = [
1341
- "file",
1342
- "image",
1343
- "object",
1344
- "reference",
1345
- "crossDatasetReference",
1346
- "globalDocumentReference"
1347
- ];
1348
- function validateBlockType(typeDef, visitorContext) {
1349
- const problems = [];
1350
- let styles = typeDef.styles, lists = typeDef.lists, marks = typeDef.marks, members = typeDef.of;
1351
- const disallowedKeys = Object.keys(typeDef).filter(
1352
- (key) => !allowedKeys.includes(key) && !key.startsWith("_")
1353
- );
1354
- return disallowedKeys.length > 0 && problems.push(
1355
- error(
1356
- `Found unknown properties for block declaration: ${humanizeList(
1357
- disallowedKeys.map(quote$1)
1358
- )}`
1359
- )
1360
- ), marks && (marks = validateMarks(typeDef.marks, visitorContext, problems)), styles && (styles = validateStyles(styles, visitorContext, problems)), lists && (lists = validateLists(lists, visitorContext, problems)), members && (members = validateMembers(members, visitorContext, problems)), {
1361
- ...omit(typeDef, disallowedKeys),
1362
- marks,
1363
- styles,
1364
- name: typeDef.name || typeDef.type,
1365
- of: members,
1366
- _problems: problems
1367
- };
1368
- }
1369
- function validateMarks(marks, visitorContext, problems) {
1370
- let decorators = marks.decorators, annotations = marks.annotations;
1371
- if (!isPlainObject(marks))
1372
- return problems.push(error(`"marks" declaration should be an object, got ${getTypeOf(marks)}`)), problems;
1373
- const disallowedMarkKeys = Object.keys(marks).filter(
1374
- (key) => !allowedMarkKeys.includes(key) && !key.startsWith("_")
1375
- );
1376
- return disallowedMarkKeys.length > 0 && problems.push(
1377
- error(
1378
- `Found unknown properties for block declaration: ${humanizeList(
1379
- disallowedMarkKeys.map(quote$1)
1380
- )}`
1381
- )
1382
- ), decorators && !Array.isArray(decorators) ? problems.push(
1383
- error(`"marks.decorators" declaration should be an array, got ${getTypeOf(decorators)}`)
1384
- ) : decorators && (decorators.filter((dec) => !!dec.blockEditor).forEach((dec) => {
1385
- dec.icon = dec.blockEditor.icon, dec.component = dec.blockEditor.render;
1386
- }), decorators = validateDecorators(decorators, visitorContext, problems)), annotations && !Array.isArray(annotations) ? problems.push(
1387
- error(`"marks.annotations" declaration should be an array, got ${getTypeOf(annotations)}`)
1388
- ) : annotations && (annotations = validateAnnotations(annotations, visitorContext, problems)), { ...marks, decorators, annotations };
1389
- }
1390
- function validateLists(lists, visitorContext, problems) {
1391
- return Array.isArray(lists) ? (lists.forEach((list, index) => {
1392
- if (!isPlainObject(list)) {
1393
- problems.push(error(`List must be an object, got ${getTypeOf(list)}`));
1394
- return;
1395
- }
1396
- const name = list.value || `#${index}`, disallowedKeys = Object.keys(list).filter(
1397
- (key) => !allowedListKeys.includes(key) && !key.startsWith("_")
1398
- );
1399
- disallowedKeys.length > 0 && problems.push(
1400
- error(
1401
- `Found unknown properties for list ${name}: ${humanizeList(disallowedKeys.map(quote$1))}`
1402
- )
1403
- ), list.value ? typeof list.value != "string" ? problems.push(
1404
- error(
1405
- `List type #${index} has an invalid "value" property, expected string, got ${getTypeOf(
1406
- list.value
1407
- )}`
1408
- )
1409
- ) : list.title || problems.push(warning(`List type ${name} is missing recommended "title" property`)) : problems.push(error(`List #${index} is missing required "value" property`));
1410
- }), lists) : (problems.push(error(`"lists" declaration should be an array, got ${getTypeOf(lists)}`)), problems);
1411
- }
1412
- function validateStyles(styles, visitorContext, problems) {
1413
- return Array.isArray(styles) ? (styles.forEach((style, index) => {
1414
- if (!isPlainObject(style)) {
1415
- problems.push(error(`Style must be an object, got ${getTypeOf(style)}`));
1416
- return;
1417
- }
1418
- const name = style.value || `#${index}`, disallowedKeys = Object.keys(style).filter(
1419
- (key) => !allowedStyleKeys.includes(key) && !key.startsWith("_")
1420
- );
1421
- disallowedKeys.length > 0 && problems.push(
1422
- error(
1423
- `Found unknown properties for style ${name}: ${humanizeList(disallowedKeys.map(quote$1))}`
1424
- )
1425
- ), style.value ? typeof style.value != "string" ? problems.push(
1426
- error(
1427
- `Style #${index} has an invalid "value" property, expected string, got ${getTypeOf(
1428
- style.value
1429
- )}`
1430
- )
1431
- ) : style.title || problems.push(warning(`Style ${name} is missing recommended "title" property`)) : problems.push(error(`Style #${index} is missing required "value" property`)), typeof style.blockEditor < "u" && (problems.push(
1432
- warning(
1433
- 'Style has deprecated key "blockEditor", please refer to the documentation on how to configure the block type for version 3.',
1434
- HELP_IDS.DEPRECATED_BLOCKEDITOR_KEY
1435
- )
1436
- ), style.component = style.component || style.blockEditor.render);
1437
- }), styles) : (problems.push(error(`"styles" declaration should be an array, got ${getTypeOf(styles)}`)), problems);
1438
- }
1439
- function validateDecorators(decorators, visitorContext, problems) {
1440
- return decorators.forEach((decorator, index) => {
1441
- if (!isPlainObject(decorator)) {
1442
- problems.push(error(`Annotation must be an object, got ${getTypeOf(decorator)}`));
1443
- return;
1444
- }
1445
- const name = decorator.value || `#${index}`, disallowedKeys = Object.keys(decorator).filter(
1446
- (key) => !allowedDecoratorKeys.includes(key) && !key.startsWith("_")
1447
- );
1448
- disallowedKeys.length > 0 && problems.push(
1449
- error(
1450
- `Found unknown properties for decorator ${name}: ${humanizeList(
1451
- disallowedKeys.map(quote$1)
1452
- )}`
1453
- )
1454
- ), decorator.value ? typeof decorator.value != "string" ? problems.push(
1455
- error(
1456
- `Decorator #${index} has an invalid "value" property, expected string, got ${getTypeOf(
1457
- decorator.value
1458
- )}`
1459
- )
1460
- ) : decorator.title || problems.push(warning(`Decorator ${name} is missing recommended "title" property`)) : problems.push(error(`Decorator #${index} is missing required "value" property`)), typeof decorator.blockEditor < "u" && (problems.push(
1461
- warning(
1462
- `Decorator "${name}" has deprecated key "blockEditor", please refer to the documentation on how to configure the block type for version 3.`,
1463
- HELP_IDS.DEPRECATED_BLOCKEDITOR_KEY
1464
- )
1465
- ), decorator.icon = decorator.icon || decorator.blockEditor.icon, decorator.component = decorator.component || decorator.blockEditor.render);
1466
- }), decorators;
1467
- }
1468
- function validateAnnotations(annotations, visitorContext, problems) {
1469
- return annotations.map((annotation) => {
1470
- if (!isPlainObject(annotation))
1471
- return {
1472
- ...annotation,
1473
- _problems: [error(`Annotation must be an object, got ${getTypeOf(annotation)}`)]
1474
- };
1475
- const { _problems } = visitorContext.visit(annotation, visitorContext), targetType = annotation.type && visitorContext.getType(annotation.type);
1476
- return targetType && !isJSONTypeOf(targetType, "object", visitorContext) && _problems.push(
1477
- error(
1478
- `Annotation cannot have type "${annotation.type}" - annotation types must inherit from object`
1479
- )
1480
- ), typeof annotation.blockEditor < "u" && (problems.push(
1481
- warning(
1482
- 'Annotation has deprecated key "blockEditor", please refer to the documentation on how to configure the block type for version 3.',
1483
- HELP_IDS.DEPRECATED_BLOCKEDITOR_KEY
1484
- )
1485
- ), annotation.icon = annotation.icon || annotation.blockEditor.icon, annotation.blockEditor?.render && !annotation.components?.annotation && (annotation.components = annotation.components || {}, annotation.components.annotation = annotation.components.annotation || annotation.blockEditor.render)), { ...annotation, _problems };
1486
- });
1487
- }
1488
- function validateMembers(members, visitorContext, problems) {
1489
- if (!Array.isArray(members)) {
1490
- problems.push(error(`"of" declaration should be an array, got ${getTypeOf(members)}`));
1491
- return;
1492
- }
1493
- return members.map((member) => {
1494
- const { _problems } = visitorContext.visit(member, visitorContext);
1495
- if (member.type === "object" && member.name && visitorContext.getType(member.name))
1496
- return {
1497
- ...member,
1498
- _problems: [
1499
- warning(
1500
- `Found array member declaration with the same name as the global schema type "${member.name}". It's recommended to use a unique name to avoid possibly incompatible data types that shares the same name.`,
1501
- HELP_IDS.ARRAY_OF_TYPE_GLOBAL_TYPE_CONFLICT
1502
- )
1503
- ]
1504
- };
1505
- let type = member;
1506
- for (; type && !type.jsonType; )
1507
- type = visitorContext.getType(type.type);
1508
- const nonObjectCoreTypes = coreTypeNames.filter((n) => !supportedBuiltInObjectTypes.includes(n));
1509
- return (
1510
- // Must be object-like type (to validate hoisted types)
1511
- type && type.jsonType !== "object" || // Can't be a core type, or core object type that isn't supported (like 'span')
1512
- nonObjectCoreTypes.some((coreName) => coreName === member.type) ? {
1513
- ...member,
1514
- _problems: [
1515
- error(
1516
- `Block member types must be a supported object-like type. The following built-in types are supported: '${supportedBuiltInObjectTypes.join(
1517
- "', '"
1518
- )}'. You can also use shorthands for previously defined object types like {type: 'myObjectType'}`,
1519
- HELP_IDS.ARRAY_OF_TYPE_BUILTIN_TYPE_CONFLICT
1520
- )
1521
- ]
1522
- } : { ...member, _problems }
1523
- );
1524
- });
1525
- }
1526
- function validateNonObjectFieldsProp(typeDef, visitorContext) {
1527
- if (!("fields" in typeDef))
1528
- return [];
1529
- let type = typeDef;
1530
- for (; type && !type.jsonType; )
1531
- type = visitorContext.getType(type.type);
1532
- return type && type.jsonType !== "object" ? [error('Type has propery "fields", but is not an object/document type.')] : [];
1533
- }
1534
- const quote = (str) => `"${str}"`;
1535
- function validateTypeName(typeName, visitorContext) {
1536
- const possibleTypeNames = visitorContext.getTypeNames();
1537
- if (!typeName)
1538
- return [error("Type is missing a type.", HELP_IDS.TYPE_MISSING_TYPE)];
1539
- if (typeof typeName != "string")
1540
- return [
1541
- error(
1542
- 'Type has an invalid "type"-property - should be a string.',
1543
- HELP_IDS.TYPE_MISSING_TYPE
1544
- )
1545
- ];
1546
- if (!possibleTypeNames.includes(typeName)) {
1547
- const suggestions = possibleTypeNames.map((possibleTypeName) => [leven(typeName, possibleTypeName), possibleTypeName]).filter(([distance]) => distance < 3).map(([_, name]) => name), suggestion = suggestions.length > 0 ? ` Did you mean ${humanizeList(suggestions.map(quote), { conjunction: "or" })}?` : "";
1548
- return [error(`Unknown type: ${typeName}.${suggestion}`)];
1549
- }
1550
- return [];
1551
- }
1552
- function validateDeprecatedProperties(type) {
1553
- const warnings = [];
1554
- return type?.inputComponent && warnings.push(
1555
- warning('The "inputComponent" property is deprecated. Use "components.input" instead.')
1556
- ), type?.preview?.component && warnings.push(
1557
- warning('The "preview.component" property is deprecated. Use "components.preview" instead.')
1558
- ), type?.diffComponent && warnings.push(
1559
- warning('The "diffComponent" property is deprecated. Use "components.diff" instead.')
1560
- ), type?.options?.editModal && warnings.push(
1561
- warning('The "options.editModal" property is deprecated. Use "options.modal" instead.')
1562
- ), type?.options?.isHighlighted && warnings.push(
1563
- warning(
1564
- 'The "options.isHighlighted" property is deprecated. You can put fields behind a collapsed fieldset if you want to hide them from plain sight.'
1565
- )
1566
- ), warnings;
1567
- }
1568
- var common = (typeDef, visitorContext) => ({
1569
- ...typeDef,
1570
- _problems: [
1571
- ...validateTypeName(typeDef.type, visitorContext),
1572
- ...validateNonObjectFieldsProp(typeDef, visitorContext),
1573
- ...validateDeprecatedProperties(typeDef)
1574
- ].filter(Boolean)
1575
- });
1576
- function normalizeToProp$2(typeDef) {
1577
- return Array.isArray(typeDef.to) ? typeDef.to : typeDef.to ? [typeDef.to] : typeDef.to;
1578
- }
1579
- const VALID_DATASET = /^[a-z0-9~][-_a-z0-9]+$/;
1580
- function isValidDatasetName(name) {
1581
- return name.length >= 2 && name.toLowerCase() === name && VALID_DATASET.test(name) || `The provided dataset "${name}" doesn't look like a valid dataset. Dataset names must be more than 2 characters, can only contain lowercase characters, numbers, underscores and dashes and can not start with a dash or an underscore`;
1582
- }
1583
- var crossDatasetReference = (typeDef, visitorContext) => {
1584
- const isValidTo = Array.isArray(typeDef.to) || isPlainObject(typeDef.to), normalizedTo = normalizeToProp$2(typeDef), problems = flatten([
1585
- isValidTo ? getDupes(normalizedTo, (t) => `${t.name};${t.type}`).map(
1586
- (dupes) => error(
1587
- `Found ${dupes.length} members with same type, but not unique names "${dupes[0].type}" in reference. This makes it impossible to tell their values apart and you should consider naming them`,
1588
- HELP_IDS.CROSS_DATASET_REFERENCE_INVALID
1589
- )
1590
- ) : error(
1591
- 'The cross dataset reference type is missing or having an invalid value for the required "to" property. It should be an array of accepted types.',
1592
- HELP_IDS.CROSS_DATASET_REFERENCE_INVALID
1593
- )
1594
- ]);
1595
- if (isValidTo && normalizedTo.length === 0 && problems.push(
1596
- error(
1597
- 'The cross dataset reference type should define at least one referenced type. Please check the "to" property.',
1598
- HELP_IDS.CROSS_DATASET_REFERENCE_INVALID
1599
- )
1600
- ), normalizedTo.forEach((crossDatasetTypeDef, index) => {
1601
- crossDatasetTypeDef.type || problems.push(
1602
- error(
1603
- `The referenced type at index ${index} must be named. Specify the name of the type you want to create references to.`,
1604
- HELP_IDS.CROSS_DATASET_REFERENCE_INVALID
1605
- )
1606
- ), isPlainObject(crossDatasetTypeDef.preview) || problems.push(
1607
- error(
1608
- `Missing required preview config for the referenced type "${crossDatasetTypeDef.type || "<unknown type>"}"`,
1609
- HELP_IDS.CROSS_DATASET_REFERENCE_INVALID
1610
- )
1611
- );
1612
- }), typeof typeDef.dataset == "string") {
1613
- const datasetValidation = isValidDatasetName(typeDef.dataset);
1614
- datasetValidation !== !0 && problems.push(error(datasetValidation, HELP_IDS.CROSS_DATASET_REFERENCE_INVALID));
1615
- } else
1616
- problems.push(
1617
- error(
1618
- "A cross dataset reference must specify a `dataset`",
1619
- HELP_IDS.CROSS_DATASET_REFERENCE_INVALID
1620
- )
1621
- );
1622
- return typeDef.studioUrl && typeof typeDef.studioUrl != "function" && problems.push(
1623
- error(
1624
- 'The "studioUrl" property on a cross dataset reference must be a function taking "{id, type}" as argument and returning a studio url.',
1625
- HELP_IDS.CROSS_DATASET_REFERENCE_INVALID
1626
- )
1627
- ), problems.push(...getOptionErrors$2(typeDef)), {
1628
- ...typeDef,
1629
- _problems: problems
1630
- };
1631
- };
1632
- function getOptionErrors$2(typeDef) {
1633
- const { options } = typeDef, problems = [];
1634
- return problems.push(
1635
- ...["filter", "filterParams"].filter((key) => key in typeDef).map(
1636
- (key) => error(
1637
- `\`${key}\` is not allowed on a reference type definition - did you mean \`options.${key}\`?`,
1638
- HELP_IDS.REFERENCE_INVALID_OPTIONS_LOCATION
1639
- )
1640
- )
1641
- ), options ? isPlainObject(options) ? typeof options.filter == "function" && typeof options.filterParams < "u" ? problems.concat(
1642
- error(
1643
- "`filterParams` cannot be used if `filter` is a function. Either statically define `filter` as a string, or return `params` from the `filter`-function.",
1644
- HELP_IDS.REFERENCE_INVALID_FILTER_PARAMS_COMBINATION
1645
- )
1646
- ) : typeof options.filter == "function" || !options.filter && !options.filterParams ? problems : typeof options.filter != "string" ? problems.concat(
1647
- error(`If set, \`filter\` must be a string. Got ${typeof options.filter}`)
1648
- ) : typeof options.filterParams < "u" && !isPlainObject(options.filterParams) ? problems.concat(error("If set, `filterParams` must be an object.")) : options.filterParams ? problems.concat(
1649
- Object.keys(options.filterParams).filter((key) => key.startsWith("__") || key.startsWith("$")).map((key) => error(`Filter parameter cannot be prefixed with "$" or "__". Got ${key}".`))
1650
- ) : problems : problems.concat(
1651
- error(
1652
- "The reference type expects `options` to be an object",
1653
- HELP_IDS.REFERENCE_INVALID_OPTIONS
1654
- )
1655
- ) : problems;
1656
- }
1657
- const REACT_SYM_RE = /^Symbol\(react\..+\)$/;
1658
- function isComponentLike(value) {
1659
- return typeof value == "function" || typeof value?.$$typeof == "symbol" && REACT_SYM_RE.test(String(value?.$$typeof));
1660
- }
1661
- function validateComponent(typeDef) {
1662
- const components = "components" in typeDef ? typeDef.components : !1;
1663
- if (!components)
1664
- return [];
1665
- const warnings = [];
1666
- return components.input && !isComponentLike(components.input) && warnings.push(
1667
- warning(
1668
- `The \`components.input\` property is set but does not appear to be a valid React component (expected a function, but saw ${inspect(
1669
- components.input
1670
- )}). If you have imported a custom input component, please verify that you have imported the correct named/default export.`
1671
- )
1672
- ), components.field && !isComponentLike(components.field) && warnings.push(
1673
- warning(
1674
- `The \`components.field\` property is set but does not appear to be a valid React component (expected a function, but saw ${inspect(
1675
- components.field
1676
- )}). If you have imported a custom field component, please verify that you have imported the correct named/default export.`
1677
- )
1678
- ), components.item && !isComponentLike(components.item) && warnings.push(
1679
- warning(
1680
- `The \`components.item\` property is set but does not appear to be a valid React component (expected a function, but saw ${inspect(
1681
- components.item
1682
- )}). If you have imported a custom item component, please verify that you have imported the correct named/default export.`
1683
- )
1684
- ), components.preview && !isComponentLike(components.preview) && warnings.push(
1685
- warning(
1686
- `The \`components.preview\` property is set but does not appear to be a valid React component (expected a function, but saw ${inspect(
1687
- components.preview
1688
- )}). If you have imported a custom preview component, please verify that you have imported the correct named/default export.`
1689
- )
1690
- ), warnings;
1691
- }
1692
- const VALID_FIELD_RE = /^[A-Za-z]+[0-9A-Za-z_]*$/, CONVENTIONAL_FIELD_RE = /^[A-Za-z_]+[0-9A-Za-z_]*$/;
1693
- function validateFieldName(name) {
1694
- return typeof name != "string" ? [
1695
- error(
1696
- `Field names must be strings. Saw "${inspect(name)}"`,
1697
- HELP_IDS.OBJECT_FIELD_NAME_INVALID
1698
- )
1699
- ] : name.startsWith("_") ? [
1700
- error(
1701
- `Invalid field name "${name}". Field names cannot start with underscores "_" as it's reserved for system fields.`,
1702
- HELP_IDS.OBJECT_FIELD_NAME_INVALID
1703
- )
1704
- ] : VALID_FIELD_RE.test(name) ? CONVENTIONAL_FIELD_RE.test(name) ? [] : [
1705
- warning(
1706
- "Thats an interesting field name for sure! But it is... how to put it... a bit... unconventional? It may be wise to keep special characters out of field names for easier access later on."
1707
- ),
1708
- HELP_IDS.OBJECT_FIELD_NAME_INVALID
1709
- ] : [
1710
- error(
1711
- `Invalid field name: "${name}". Fields can only contain characters from A-Z, numbers and underscores and should not start with a number (must pass the regular expression ${String(
1712
- VALID_FIELD_RE
1713
- )}).`,
1714
- HELP_IDS.OBJECT_FIELD_NAME_INVALID
1715
- )
1716
- ];
1717
- }
1718
- function validateField(field, _visitorContext) {
1719
- if (!isPlainObject(field))
1720
- return [
1721
- error(
1722
- `Incorrect type for field definition - should be an object, saw ${inspect(field)}`,
1723
- HELP_IDS.OBJECT_FIELD_DEFINITION_INVALID_TYPE
1724
- )
1725
- ];
1726
- const problems = [];
1727
- return problems.push(
1728
- ..."name" in field ? validateFieldName(field.name) : [error("Missing field name", HELP_IDS.OBJECT_FIELD_NAME_INVALID)]
1729
- ), problems.push(...validateComponent(field)), problems;
1730
- }
1731
- function getDuplicateFields(array2) {
1732
- const dupes = {};
1733
- return array2.forEach((field) => {
1734
- dupes[field.name] || (dupes[field.name] = []), dupes[field.name].push(field);
1735
- }), Object.keys(dupes).map((fieldName) => dupes[fieldName].length > 1 ? dupes[fieldName] : null).filter(Boolean);
1736
- }
1737
- function validateFields(fields, options = { allowEmpty: !1 }) {
1738
- const problems = [];
1739
- if (!Array.isArray(fields))
1740
- return [
1741
- error(
1742
- `The "fields" property must be an array of fields. Instead saw "${typeof fields}"`,
1743
- HELP_IDS.OBJECT_FIELDS_INVALID
1744
- )
1745
- ];
1746
- const fieldsWithNames = fields.filter((field) => typeof field.name == "string");
1747
- getDuplicateFields(fieldsWithNames).forEach((dupes) => {
1748
- problems.push(
1749
- error(
1750
- `Found ${dupes.length} fields with name "${dupes[0].name}" in object`,
1751
- HELP_IDS.OBJECT_FIELD_NOT_UNIQUE
1752
- )
1753
- );
1754
- }), fields.length === 0 && !options.allowEmpty && problems.push(error("Object should have at least one field", HELP_IDS.OBJECT_FIELDS_INVALID));
1755
- const standaloneBlockFields = fields.filter((field) => field.type === "block").map((field) => `"${field.name}"`);
1756
- if (standaloneBlockFields.length > 0) {
1757
- const fmtFields = standaloneBlockFields.join(", ");
1758
- problems.push(
1759
- error(
1760
- `Invalid standalone block field(s) ${fmtFields}. Block content must be defined as an array of blocks`,
1761
- HELP_IDS.STANDALONE_BLOCK_TYPE
1762
- )
1763
- );
1764
- }
1765
- return problems;
1766
- }
1767
- function validatePreview(preview) {
1768
- return isPlainObject(preview) ? typeof preview.prepare < "u" && typeof preview.prepare != "function" ? [
1769
- error(
1770
- `The "preview.prepare" property must be a function, instead saw "${typeof preview.prepare}"`
1771
- )
1772
- ] : preview.select ? isPlainObject(preview.select) ? Object.keys(preview.select).reduce((errs, key) => typeof preview.select[key] == "string" ? errs : errs.concat(
1773
- error(
1774
- `The key "${key}" of "preview.select" must be a string, instead saw "${typeof preview.select[key]}"`
1775
- )
1776
- ), []) : [
1777
- error(
1778
- `The "preview.select" property must be an object, instead saw "${typeof preview.prepare}"`
1779
- )
1780
- ] : [] : [error(`The "preview" property must be an object, instead saw "${typeof preview}"`)];
1781
- }
1782
- var object = (typeDef, visitorContext) => {
1783
- let problems = validateFields(typeDef.fields), preview = typeDef.preview;
1784
- if (preview) {
1785
- const previewErrors = validatePreview(typeDef.preview);
1786
- problems = problems.concat(previewErrors), preview = previewErrors.some((err) => err.severity === "error") ? {} : preview;
1787
- }
1788
- return typeDef.type !== "document" && typeDef.type !== "object" && typeof typeDef.initialValue < "u" && problems.push(
1789
- error('The "initialValue" property is currently only supported for document & object types.')
1790
- ), {
1791
- ...typeDef,
1792
- preview,
1793
- fields: (Array.isArray(typeDef.fields) ? typeDef.fields : []).map((field, index) => {
1794
- const { name, ...fieldTypeDef } = field, { _problems, ...fieldType } = visitorContext.visit(fieldTypeDef, index);
1795
- return {
1796
- name,
1797
- ...fieldType,
1798
- _problems: validateField(field).concat(_problems || [])
1799
- };
1800
- }),
1801
- _problems: problems
1802
- };
1803
- }, documentVisitor = (typeDefinition, visitorContext) => {
1804
- const typeDef = object(typeDefinition, visitorContext), { initialValue, initialValues } = typeDef;
1805
- return typeof initialValue < "u" && !isPlainObject(initialValue) && typeof initialValue != "function" && typeDef._problems.push(
1806
- error('The "initialValue" property must be either a plain object or a function')
1807
- ), typeof initialValues < "u" && typeDef._problems.push(error('Found property "initialValues" - did you mean "initialValue"?')), typeDef;
1808
- }, file = (typeDef, visitorContext) => {
1809
- const problems = [], fields = typeDef.fields;
1810
- fields && problems.push(...validateFields(fields, { allowEmpty: !0 }));
1811
- const invalidFieldNames = Array.isArray(fields) ? fields?.filter((field) => field.name === "asset") : [];
1812
- return typeDef.options && typeof typeDef.options.metadata < "u" && !Array.isArray(typeDef.options.metadata) ? problems.push(
1813
- error(
1814
- "Invalid type for file `metadata` field - must be an array of strings",
1815
- HELP_IDS.ASSET_METADATA_FIELD_INVALID
1816
- )
1817
- ) : invalidFieldNames.length > 0 && problems.push(error("The name `asset` is not a valid field name for type `file`.")), {
1818
- ...typeDef,
1819
- fields: (Array.isArray(fields) ? fields : []).map((field, index) => {
1820
- const { name, ...fieldTypeDef } = field, { _problems, ...fieldType } = visitorContext.visit(fieldTypeDef, index);
1821
- return {
1822
- name,
1823
- ...fieldType,
1824
- _problems: validateField(field).concat(_problems || [])
1825
- };
1826
- }),
1827
- _problems: problems
1828
- };
1829
- };
1830
- function normalizeToProp$1(typeDef) {
1831
- return Array.isArray(typeDef.to) ? typeDef.to : typeDef.to ? [typeDef.to] : [];
1832
- }
1833
- function isValidResourceType(resourceType) {
1834
- return resourceType ? resourceType != "media-library" && resourceType != "dataset" ? 'The resource type must be either "media-library" or "dataset"' : !0 : "The resource type must be a non-empty string";
1835
- }
1836
- function isValidResourceId(resourceType, resourceId) {
1837
- return resourceId ? resourceType === "dataset" ? resourceId.split(".").length !== 2 ? 'The resource ID for a dataset reference must be on the form "<projectId>.<datasetName>"' : !0 : resourceType === "media-library" ? !0 : `Cannot validate resource ID for resource type: ${resourceType}` : "The resource ID must be a non-empty string";
1838
- }
1839
- var globalDocumentReference = (typeDef, visitorContext) => {
1840
- const isValidTo = Array.isArray(typeDef.to) || isPlainObject(typeDef.to), normalizedTo = normalizeToProp$1(typeDef), problems = flatten([
1841
- isValidTo ? getDupes(normalizedTo, (t) => `${t.name};${t.type}`).map(
1842
- (dupes) => error(
1843
- `Found ${dupes.length} members with same type, but not unique names "${dupes[0].type}" in reference. This makes it impossible to tell their values apart and you should consider naming them`,
1844
- HELP_IDS.GLOBAL_DOCUMENT_REFERENCE_INVALID
1845
- )
1846
- ) : error(
1847
- 'The global document reference type is missing or having an invalid value for the required "to" property. It should be an array of accepted types.',
1848
- HELP_IDS.GLOBAL_DOCUMENT_REFERENCE_INVALID
1849
- )
1850
- ]);
1851
- if (isValidTo && normalizedTo.length === 0 && problems.push(
1852
- error(
1853
- 'The global document reference type should define at least one referenced type. Please check the "to" property.',
1854
- HELP_IDS.GLOBAL_DOCUMENT_REFERENCE_INVALID
1855
- )
1856
- ), normalizedTo.forEach((crossDatasetTypeDef, index) => {
1857
- crossDatasetTypeDef.type || problems.push(
1858
- error(
1859
- `The referenced type at index ${index} must be named. Specify the name of the type you want to create references to.`,
1860
- HELP_IDS.GLOBAL_DOCUMENT_REFERENCE_INVALID
1861
- )
1862
- ), isPlainObject(crossDatasetTypeDef.preview) || problems.push(
1863
- error(
1864
- `Missing required preview config for the referenced type "${crossDatasetTypeDef.type || "<unknown type>"}"`,
1865
- HELP_IDS.GLOBAL_DOCUMENT_REFERENCE_INVALID
1866
- )
1867
- );
1868
- }), typeof typeDef.resourceType == "string") {
1869
- const validation = isValidResourceType(typeDef.resourceType);
1870
- validation !== !0 && problems.push(error(validation, HELP_IDS.GLOBAL_DOCUMENT_REFERENCE_INVALID));
1871
- } else
1872
- problems.push(
1873
- error(
1874
- "A global document reference must specify a `resourceType`",
1875
- HELP_IDS.GLOBAL_DOCUMENT_REFERENCE_INVALID
1876
- )
1877
- );
1878
- if (typeof typeDef.resourceId == "string") {
1879
- const datasetValidation = isValidResourceId(typeDef.resourceType, typeDef.resourceId);
1880
- datasetValidation !== !0 && problems.push(error(datasetValidation, HELP_IDS.GLOBAL_DOCUMENT_REFERENCE_INVALID));
1881
- } else
1882
- problems.push(
1883
- error(
1884
- "A global document reference must specify a `resourceId`",
1885
- HELP_IDS.GLOBAL_DOCUMENT_REFERENCE_INVALID
1886
- )
1887
- );
1888
- return typeDef.studioUrl && typeof typeDef.studioUrl != "function" && typeof typeDef.studioUrl != "string" && problems.push(
1889
- error(
1890
- 'The "studioUrl" property on a global document reference must either be a function taking "{id, type}" as argument and returning a studio url, or a string being the base url pointing to a studio.',
1891
- HELP_IDS.GLOBAL_DOCUMENT_REFERENCE_INVALID
1892
- )
1893
- ), problems.push(...getOptionErrors$1(typeDef)), {
1894
- ...typeDef,
1895
- _problems: problems
1896
- };
1897
- };
1898
- function getOptionErrors$1(typeDef) {
1899
- const { options } = typeDef, problems = [];
1900
- return problems.push(
1901
- ...["filter", "filterParams"].filter((key) => key in typeDef).map(
1902
- (key) => error(
1903
- `\`${key}\` is not allowed on a reference type definition - did you mean \`options.${key}\`?`,
1904
- HELP_IDS.REFERENCE_INVALID_OPTIONS_LOCATION
1905
- )
1906
- )
1907
- ), options ? isPlainObject(options) ? typeof options.filter == "function" && typeof options.filterParams < "u" ? problems.concat(
1908
- error(
1909
- "`filterParams` cannot be used if `filter` is a function. Either statically define `filter` as a string, or return `params` from the `filter`-function.",
1910
- HELP_IDS.REFERENCE_INVALID_FILTER_PARAMS_COMBINATION
1911
- )
1912
- ) : typeof options.filter == "function" || !options.filter && !options.filterParams ? problems : typeof options.filter != "string" ? problems.concat(
1913
- error(`If set, \`filter\` must be a string. Got ${typeof options.filter}`)
1914
- ) : typeof options.filterParams < "u" && !isPlainObject(options.filterParams) ? problems.concat(error("If set, `filterParams` must be an object.")) : options.filterParams ? problems.concat(
1915
- Object.keys(options.filterParams).filter((key) => key.startsWith("__") || key.startsWith("$")).map((key) => error(`Filter parameter cannot be prefixed with "$" or "__". Got ${key}".`))
1916
- ) : problems : problems.concat(
1917
- error(
1918
- "The reference type expects `options` to be an object",
1919
- HELP_IDS.REFERENCE_INVALID_OPTIONS
1920
- )
1921
- ) : problems;
1922
- }
1923
- const autoMeta = ["dimensions", "hasAlpha", "isOpaque"];
1924
- var image = (typeDef, visitorContext) => {
1925
- const problems = [], fields = typeDef.fields;
1926
- fields && problems.push(...validateFields(fields, { allowEmpty: !0 }));
1927
- let options = typeDef.options;
1928
- const metadata = options?.metadata, superfluousMeta = Array.isArray(metadata) ? metadata.filter((meta) => autoMeta.includes(meta)) : [], invalidFieldNames = ["asset", "hotspot", "crop"], fieldsWithInvalidName = Array.isArray(fields) ? fields?.filter((field) => invalidFieldNames.includes(field.name)) : [];
1929
- return typeof metadata < "u" && !Array.isArray(metadata) ? problems.push(
1930
- error(
1931
- "Invalid type for image `metadata` field - must be an array of strings",
1932
- HELP_IDS.ASSET_METADATA_FIELD_INVALID
1933
- )
1934
- ) : superfluousMeta.length > 0 ? (problems.push(
1935
- warning(
1936
- `Image \`metadata\` field contains superfluous properties (they are always included): ${superfluousMeta.join(
1937
- ", "
1938
- )}`
1939
- )
1940
- ), options = { ...options, metadata: metadata.filter((meta) => !autoMeta.includes(meta)) }) : fieldsWithInvalidName.length > 0 && problems.push(
1941
- error(
1942
- `The names \`${invalidFieldNames.join(
1943
- "`, `"
1944
- )}\` are invalid field names for type \`image\`.`
1945
- )
1946
- ), {
1947
- ...typeDef,
1948
- options,
1949
- fields: (Array.isArray(fields) ? fields : []).map((field, index) => {
1950
- const { name, ...fieldTypeDef } = field, { _problems, ...fieldType } = visitorContext.visit(fieldTypeDef, index);
1951
- return {
1952
- name,
1953
- ...fieldType,
1954
- _problems: validateField(field).concat(_problems || [])
1955
- };
1956
- }),
1957
- _problems: problems
1958
- };
1959
- };
1960
- function normalizeToProp(typeDef) {
1961
- return Array.isArray(typeDef.to) ? typeDef.to : typeDef.to ? [typeDef.to] : typeDef.to;
1962
- }
1963
- var reference = (typeDef, visitorContext) => {
1964
- const isValidTo = Array.isArray(typeDef.to) || isPlainObject(typeDef.to), normalizedTo = normalizeToProp(typeDef), problems = flatten([
1965
- isValidTo ? getDupes(normalizedTo, (t) => `${t.name};${t.type}`).map(
1966
- (dupes) => error(
1967
- `Found ${dupes.length} members with same type, but not unique names "${dupes[0].type}" in reference. This makes it impossible to tell their values apart and you should consider naming them`,
1968
- HELP_IDS.REFERENCE_TO_INVALID
1969
- )
1970
- ) : error(
1971
- 'The reference type is missing or having an invalid value for the required "to" property. It should be an array of accepted types.',
1972
- HELP_IDS.REFERENCE_TO_INVALID
1973
- )
1974
- ]);
1975
- return isValidTo && normalizedTo.length === 0 && problems.push(
1976
- error(
1977
- 'The reference type should define at least one accepted type. Please check the "to" property.',
1978
- HELP_IDS.REFERENCE_TO_INVALID
1979
- )
1980
- ), problems.push(...getOptionErrors(typeDef)), {
1981
- ...typeDef,
1982
- to: (isValidTo ? normalizedTo : []).map(visitorContext.visit),
1983
- _problems: problems
1984
- };
1985
- };
1986
- function getOptionErrors(typeDef) {
1987
- const { options } = typeDef, problems = [];
1988
- return problems.push(
1989
- ...["filter", "filterParams"].filter((key) => key in typeDef).map(
1990
- (key) => error(
1991
- `\`${key}\` is not allowed on a reference type definition - did you mean \`options.${key}\`?`,
1992
- HELP_IDS.REFERENCE_INVALID_OPTIONS_LOCATION
1993
- )
1994
- )
1995
- ), options ? isPlainObject(options) ? typeof options.filter == "function" && typeof options.filterParams < "u" ? problems.concat(
1996
- error(
1997
- "`filterParams` cannot be used if `filter` is a function. Either statically define `filter` as a string, or return `params` from the `filter`-function.",
1998
- HELP_IDS.REFERENCE_INVALID_FILTER_PARAMS_COMBINATION
1999
- )
2000
- ) : typeof options.filter == "function" || !options.filter && !options.filterParams ? problems : typeof options.filter != "string" ? problems.concat(
2001
- error(`If set, \`filter\` must be a string. Got ${typeof options.filter}`)
2002
- ) : typeof options.filterParams < "u" && !isPlainObject(options.filterParams) ? problems.concat(error("If set, `filterParams` must be an object.")) : options.filterParams ? problems.concat(
2003
- Object.keys(options.filterParams).filter((key) => key.startsWith("__") || key.startsWith("$")).map((key) => error(`Filter parameter cannot be prefixed with "$" or "__". Got ${key}".`))
2004
- ) : problems : problems.concat(
2005
- error(
2006
- "The reference type expects `options` to be an object",
2007
- HELP_IDS.REFERENCE_INVALID_OPTIONS
2008
- )
2009
- ) : problems;
2010
- }
2011
- var rootType = (typeDef, visitorContext) => {
2012
- const hasName = !!typeDef.name;
2013
- if (!hasName && Object.keys(typeDef).length === 1)
2014
- return {
2015
- ...typeDef,
2016
- _problems: [
2017
- error(
2018
- "Invalid/undefined type declaration, check declaration or the import/export of the schema type.",
2019
- HELP_IDS.TYPE_INVALID
2020
- )
2021
- ]
2022
- };
2023
- const problems = [];
2024
- return looksLikeEsmModule(typeDef) ? problems.push(
2025
- error(
2026
- "Type appears to be an ES6 module imported through CommonJS require - use an import statement or access the `.default` property",
2027
- HELP_IDS.TYPE_IS_ESM_MODULE
2028
- )
2029
- ) : hasName ? visitorContext.isReserved(typeDef.name) && problems.push(
2030
- error(
2031
- `Invalid type name: "${typeDef.name}" is a reserved name.`,
2032
- HELP_IDS.TYPE_NAME_RESERVED
2033
- )
2034
- ) : problems.push(error("Missing type name", HELP_IDS.TYPE_MISSING_NAME)), visitorContext.isDuplicate(typeDef.name) && problems.push(
2035
- error(
2036
- `Invalid type name: A type with name "${typeDef.name}" is already defined in the schema.`
2037
- )
2038
- ), problems.push(...validateComponent(typeDef)), "title" in typeDef && typeof typeDef.title != "string" && problems.push(warning("Type title is not a string.", HELP_IDS.TYPE_TITLE_INVALID)), {
2039
- ...typeDef,
2040
- _problems: problems
2041
- };
2042
- };
2043
- function looksLikeEsmModule(typeDef) {
2044
- return !typeDef.name && typeDef.default && (typeDef.default.name || typeDef.default.title);
2045
- }
2046
- var slug = (typeDef, visitorContext) => {
2047
- const problems = [];
2048
- return typeDef.options && typeDef.options.slugifyFn && (problems.push(
2049
- warning(
2050
- 'Heads up! The "slugifyFn" option has been renamed to "slugify".',
2051
- HELP_IDS.SLUG_SLUGIFY_FN_RENAMED
2052
- )
2053
- ), typeDef.options.slugify = typeDef.options.slugifyFn), {
2054
- ...typeDef,
2055
- _problems: problems
2056
- };
2057
- };
2058
- const typeVisitors = {
2059
- array,
2060
- object,
2061
- slug,
2062
- file,
2063
- image,
2064
- block: validateBlockType,
2065
- document: documentVisitor,
2066
- reference,
2067
- crossDatasetReference,
2068
- globalDocumentReference
2069
- }, getNoopVisitor = (visitorContext) => (schemaDef) => ({
2070
- name: `<unnamed_type_@_index_${visitorContext.index}>`,
2071
- ...schemaDef,
2072
- _problems: []
2073
- });
2074
- function combine(...visitors) {
2075
- return (schemaType, visitorContext) => visitors.reduce(
2076
- (result, visitor) => {
2077
- const res = visitor(result, visitorContext);
2078
- return {
2079
- ...res,
2080
- _problems: result._problems.concat(res._problems)
2081
- };
2082
- },
2083
- { _problems: [], ...schemaType }
2084
- );
2085
- }
2086
- function validateSchema(schemaTypes, { transformTypeVisitors = (visitors) => visitors } = {}) {
2087
- return traverseSanitySchema(schemaTypes, (schemaDef, visitorContext) => {
2088
- const typeVisitor = schemaDef && schemaDef.type && transformTypeVisitors(typeVisitors)[schemaDef.type] || getNoopVisitor(visitorContext);
2089
- return visitorContext.isRoot ? combine(rootType, common, typeVisitor)(schemaDef, visitorContext) : combine(common, typeVisitor)(schemaDef, visitorContext);
2090
- });
2091
- }
2092
- function unsupportedTypeValidator(typeLabel) {
2093
- return function() {
2094
- return {
2095
- _problems: [
2096
- {
2097
- severity: "error",
2098
- message: `Type unsupported in Media Library aspects: ${typeLabel}.`
2099
- }
2100
- ]
2101
- };
2102
- };
2103
- }
2104
- function validateMediaLibraryAssetAspect(maybeAspect) {
2105
- const validated = validateSchema([maybeAspect], {
2106
- transformTypeVisitors: (typeVisitors2) => ({
2107
- ...typeVisitors2,
2108
- document: unsupportedTypeValidator("document"),
2109
- image: unsupportedTypeValidator("image"),
2110
- file: unsupportedTypeValidator("file"),
2111
- video: unsupportedTypeValidator("sanity.video"),
2112
- reference: unsupportedTypeValidator("reference"),
2113
- crossDatasetReference: unsupportedTypeValidator("cross dataset reference")
2114
- })
2115
- }), errors = groupProblems(validated.getTypes()).map((group) => group.problems.filter(({ severity }) => severity === "error")).filter((problems) => problems.length);
2116
- return [errors.length === 0, errors];
2117
- }
2118
- export {
2119
- DEFAULT_MAX_FIELD_DEPTH,
2120
- DescriptorConverter,
2121
- builtinTypes,
2122
- extractSchema,
2123
- groupProblems,
2124
- isActionEnabled,
2125
- processSchemaSynchronization,
2126
- resolveSearchConfig,
2127
- resolveSearchConfigForBaseFieldPaths,
2128
- validateMediaLibraryAssetAspect,
2129
- validateSchema
2130
- };
2131
- //# sourceMappingURL=_internal.mjs.map