sanity-advanced-validators 0.6.0 → 0.9.0
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/README.md +20 -17
- package/dist/index.cjs +24 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +24 -17
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -23,12 +23,18 @@ This package includes a set of Sanity validators for aggressive and weird edge c
|
|
|
23
23
|
|
|
24
24
|
Imagine that you’ve got a document that has an optional video file, but…
|
|
25
25
|
|
|
26
|
-
- it’s required on the `/about` page
|
|
27
26
|
- if the video exists, it must be either **MP4** or **MOV**
|
|
28
27
|
- and there must be a poster image that's between **1250x800** and **2500x1600** pixels in size
|
|
28
|
+
- and it’s _always_ required on the `/home` page
|
|
29
29
|
|
|
30
30
|
```typescript
|
|
31
|
-
import {
|
|
31
|
+
import { defineType, defineField } from 'sanity'
|
|
32
|
+
import {
|
|
33
|
+
requiredIfSlugEq,
|
|
34
|
+
requiredIfSiblingNeq,
|
|
35
|
+
minDimensions,
|
|
36
|
+
maxDimensions
|
|
37
|
+
} from 'sanity-advanced-validators'
|
|
32
38
|
|
|
33
39
|
const Page = defineType({
|
|
34
40
|
name: "page",
|
|
@@ -43,14 +49,11 @@ const Page = defineType({
|
|
|
43
49
|
type: "file",
|
|
44
50
|
validation: (rule) =>
|
|
45
51
|
rule.custom(
|
|
46
|
-
requiredIfSlugEq(
|
|
47
|
-
'about',
|
|
48
|
-
'A video is required if {slugKey} is {operand}.'
|
|
49
|
-
)
|
|
52
|
+
requiredIfSlugEq('home', 'A video is required on the home page.')
|
|
50
53
|
).custom(
|
|
51
54
|
fileExtension(['mp4', 'mov'])
|
|
52
55
|
)
|
|
53
|
-
})
|
|
56
|
+
}),
|
|
54
57
|
defineField({
|
|
55
58
|
name: "posterImage",
|
|
56
59
|
type: "image",
|
|
@@ -413,8 +416,8 @@ defineType({
|
|
|
413
416
|
Mark a field as `required` for documents with matching slugs.
|
|
414
417
|
|
|
415
418
|
```typescript
|
|
416
|
-
operand: string | number | null | Array<string, number> //
|
|
417
|
-
key?: string, // name of
|
|
419
|
+
operand: string | number | null | Array<string, number> // value or values that you’re testing for
|
|
420
|
+
key?: string, // name of slug field if not "slug"
|
|
418
421
|
message?: string // optional custom error message; replaces {slugKey} and {operand} with your input, and {siblingSlugValue} with the value of the sibling you’re testing against.
|
|
419
422
|
```
|
|
420
423
|
|
|
@@ -462,8 +465,8 @@ defineField({
|
|
|
462
465
|
Require fields on pages that don't match one or more slugs.
|
|
463
466
|
|
|
464
467
|
```typescript
|
|
465
|
-
operand: string | number | null | Array<string, number> //
|
|
466
|
-
key?: string, // name of
|
|
468
|
+
operand: string | number | null | Array<string, number> // value or values that you’re testing
|
|
469
|
+
key?: string, // name of slug field if not "slug"
|
|
467
470
|
message?: string // optional custom error message; replaces {slugKey} and {operand} with your input, and {siblingSlugValue} with the value of the sibling you’re testing against.
|
|
468
471
|
```
|
|
469
472
|
|
|
@@ -520,7 +523,7 @@ defineField({
|
|
|
520
523
|
}),
|
|
521
524
|
```
|
|
522
525
|
|
|
523
|
-
|
|
526
|
+
_Custom error messages are highly recommended here._ Without a custom message above, the default error message would be:
|
|
524
527
|
|
|
525
528
|
```
|
|
526
529
|
“me@googlecom” does not match the pattern /^([a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6})*$/.
|
|
@@ -655,26 +658,26 @@ defineField({
|
|
|
655
658
|
|
|
656
659
|
---
|
|
657
660
|
|
|
658
|
-
## Extending these and writing your own
|
|
659
|
-
|
|
660
|
-
Most of these validators rely on a function called `getSibling()`. If you’re thinking about picking this apart and writing your own custom validator, take a close look at how these validators use it.
|
|
661
|
-
|
|
662
661
|
## Roadmap
|
|
663
662
|
|
|
664
663
|
### Nested pathfinders
|
|
665
664
|
|
|
666
665
|
Since building these validator, I took to putting my slugs in a metadata object. I need to update `requiredIfSlugEq` to accept a path, like `requiredIfSlugEq('metadata.slug', 'some-values')`.
|
|
667
666
|
|
|
668
|
-
This pathfinding should be added to any validator that takes a sibling, like `requiredIfSiblingEq`. It can probably be snapped into `getSibling`.
|
|
667
|
+
This pathfinding should be added to any validator that takes a sibling, like `requiredIfSiblingEq('metadata.slug.current', 'home')`. It can probably be snapped into `getSibling`.
|
|
669
668
|
|
|
670
669
|
While I’m at it, there’s a possibility that `getSibling` could detect the target type. If that type is `slug`, then it could add `current` to the path, and then I can deprecate `requiredIfSlugEq` altogether.
|
|
671
670
|
|
|
671
|
+
On a related note, `requiredIfSlugEq` does not work in an object nested inside an array. If we can deprecate `requiredIfSlugEq`, then this would be automatically resolved.
|
|
672
|
+
|
|
672
673
|
### Image and File checks
|
|
673
674
|
|
|
674
675
|
`minDimensions`, `maxDimensions`, and `fileExtension` should check to see if the field is of type `image` or `file`.
|
|
675
676
|
|
|
676
677
|
Some of the other checks should probably make sure the field is _not_ `image` or `file`.
|
|
677
678
|
|
|
679
|
+
An `aspectRatio(n)` might be nice (ex. `aspectRatio(1.6)` or `aspectRatio(1.6/1)`).
|
|
680
|
+
|
|
678
681
|
### new referencedDocumentFieldEq validator
|
|
679
682
|
|
|
680
683
|
```
|
package/dist/index.cjs
CHANGED
|
@@ -132,23 +132,23 @@ var maxDepth = (maxDepth2, key, message = `Error: You can only nest {key} {maxDe
|
|
|
132
132
|
};
|
|
133
133
|
|
|
134
134
|
// src/requiredIfSlugEq.ts
|
|
135
|
-
var requiredIfSlugEq = (
|
|
136
|
-
var _a
|
|
137
|
-
const
|
|
138
|
-
const
|
|
139
|
-
if (!value && !!slugValue &&
|
|
140
|
-
return message.replace("{slugKey}", slugKey).replace("{operand}",
|
|
135
|
+
var requiredIfSlugEq = (operand, slugKey = "slug", message = `This is a required field.`) => (value, context) => {
|
|
136
|
+
var _a;
|
|
137
|
+
const slugValue = (_a = getSibling(slugKey, context)) == null ? void 0 : _a.current;
|
|
138
|
+
const operands = typeof operand === "string" ? [operand] : operand;
|
|
139
|
+
if (!value && !!slugValue && operands.includes(slugValue)) {
|
|
140
|
+
return message.replace("{slugKey}", slugKey).replace("{operand}", operands.join(", or ")).replace("{siblingSlugValue}", slugValue);
|
|
141
141
|
}
|
|
142
142
|
return true;
|
|
143
143
|
};
|
|
144
144
|
|
|
145
145
|
// src/requiredIfSlugNeq.ts
|
|
146
|
-
var requiredIfSlugNeq = (
|
|
147
|
-
var _a
|
|
148
|
-
const
|
|
149
|
-
const slugValue = (
|
|
150
|
-
if (!value && !
|
|
151
|
-
return message.replace("{slugKey}", slugKey).replace("{operand}",
|
|
146
|
+
var requiredIfSlugNeq = (operand, slugKey = "slug", message = `This is a required field.`) => (value, context) => {
|
|
147
|
+
var _a;
|
|
148
|
+
const operands = typeof operand === "string" ? [operand] : operand;
|
|
149
|
+
const slugValue = (_a = getSibling(slugKey, context)) == null ? void 0 : _a.current;
|
|
150
|
+
if (!value && !operands.includes(slugValue)) {
|
|
151
|
+
return message.replace("{slugKey}", slugKey).replace("{operand}", operands.join(", or ")).replace("{siblingSlugValue}", slugValue);
|
|
152
152
|
}
|
|
153
153
|
return true;
|
|
154
154
|
};
|
|
@@ -175,12 +175,19 @@ var requiredIfSiblingNeq = (key, operand, message = "Required if {key} does not
|
|
|
175
175
|
return true;
|
|
176
176
|
};
|
|
177
177
|
|
|
178
|
-
// src/
|
|
179
|
-
var import_lodash_es = require("lodash-es");
|
|
178
|
+
// src/getSibling.ts
|
|
180
179
|
var getSibling = (key, context) => {
|
|
181
|
-
|
|
182
|
-
const
|
|
183
|
-
|
|
180
|
+
const path = context.path ? context.path.slice(0, -1) : [];
|
|
181
|
+
const sibling = [...path, key].reduce((acc, step) => {
|
|
182
|
+
if (typeof step === "string" && acc.hasOwnProperty(step)) {
|
|
183
|
+
return acc[step];
|
|
184
|
+
} else if (typeof step === "object" && step.hasOwnProperty("_key") && Array.isArray(acc)) {
|
|
185
|
+
return acc.find((i) => i._key === step._key);
|
|
186
|
+
} else {
|
|
187
|
+
console.error("sanity-advanced-validators: Unreachable point reached!");
|
|
188
|
+
return acc;
|
|
189
|
+
}
|
|
190
|
+
}, context.document);
|
|
184
191
|
return sibling;
|
|
185
192
|
};
|
|
186
193
|
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/referencedDocumentRequires.ts","../src/fileExtension.ts","../src/minCount.ts","../src/maxCount.ts","../src/minDimensions.ts","../src/maxDimensions.ts","../src/maxDepth.ts","../src/requiredIfSlugEq.ts","../src/requiredIfSlugNeq.ts","../src/requiredIfSiblingEq.ts","../src/requiredIfSiblingNeq.ts","../src/lib/getSibling.ts","../src/regex.ts"],"sourcesContent":["export * from \"./referencedDocumentRequires\"\nexport * from \"./fileExtension\"\nexport * from \"./minCount\"\nexport * from \"./maxCount\"\nexport * from \"./minDimensions\"\nexport * from \"./maxDimensions\"\nexport * from \"./maxDepth\"\nexport * from \"./requiredIfSlugEq\"\nexport * from \"./requiredIfSlugNeq\"\nexport * from \"./requiredIfSiblingEq\"\nexport * from \"./requiredIfSiblingNeq\"\nexport * from \"./lib\"\nexport * from \"./regex\"\n","import { ValidationContext } from \"sanity\"\n\nexport const referencedDocumentRequires = (\n documentType: string, \n field: string, \n message: string = `{documentType}’s {field} must be filled.`\n) => async (value: any | undefined, context: ValidationContext) => {\n if (!value?._ref) {\n return true\n }\n const client = context.getClient({ apiVersion: \"2022-08-12\" })\n // todo: use current API version, or test with no version at all\n\n // todo: if there's a value._type or value.referenced._type or something, we get rid of document.type from inputs\n const data = await client.fetch(`\n *[_type == \"${documentType}\" && _id == \"${value._ref}\"]{\n ${field}\n }[0]\n `) // TODO: why is typescript screaming about this? Fetch takes two parameters.\n if (!data[field]) {\n return message.replace(\"{documentType}\", documentType).replace(\"{field}\", field)\n }\n return true\n}\n","import { getExtension } from \"@sanity/asset-utils\"\nimport { FileValue } from \"sanity\"\n\nexport const fileExtension = (\n validFileExtension: string | Array<string>, \n message: string = `Image must be of type {validFileExtension}`\n) => (value: FileValue | undefined) => {\n if (!value || !value.asset) {\n return true\n }\n const validExtensions = typeof validFileExtension === \"string\" ? [validFileExtension] : validFileExtension\n const filetype = getExtension(value.asset._ref)\n if (!validExtensions.includes(filetype)) {\n return message.replace(\"{validFileExtension}\", validExtensions.join(\", or \"))\n }\n return true\n}\n\n// todo: this should fail if its attached to a field that is not of type \"file\"","export const minCount = (n: number, message?: string) => (value: Array<unknown> | undefined) => {\n if (!value) {\n return true\n }\n if (value.length < n) {\n return message ? message.replace(\"{n}\", n.toString()) : `Array must contain at least ${n} items.`\n }\n return true\n}\n","export const maxCount = (n: number, message?: string) => (value: Array<unknown> | undefined) => {\n if (!value) {\n return true\n }\n if (value.length > n) {\n return message ? message.replace(\"{n}\", n.toString()) : `Array must contain at most ${n} items.`\n }\n return true\n}\n","import { getImageDimensions } from \"@sanity/asset-utils\"\nimport { FileValue } from \"sanity\"\n\nexport const minDimensions =\n ({ x, y }: { x: number; y: number }, message?: string) =>\n (value: FileValue | undefined) => {\n if (!value || !value.asset) {\n return true\n }\n const { width, height } = getImageDimensions(value.asset._ref)\n if (!!x && width < x) {\n return message \n ? message.replace(\"{width}\", width.toString())\n .replace(\"{height}\", height.toString())\n .replace(\"{x}\", x.toString())\n .replace(\"{y}\", !y ? \"(any)\" : y.toString()) \n : `Image must be at least ${x} pixels wide.`\n }\n if (!!y && height < y) {\n return message \n ? message.replace(\"{width}\", width.toString())\n .replace(\"{height}\", height.toString())\n .replace(\"{x}\", !x ? \"(any)\" : x.toString())\n .replace(\"{y}\", y.toString())\n : `Image must be at least ${y} pixels tall.`\n }\n return true\n }\n\n// todo: this should fail if its attached to a field that is not of type \"image\"","import { getImageDimensions } from \"@sanity/asset-utils\"\nimport { FileValue } from \"sanity\"\n\nexport const maxDimensions =\n ({ x, y }: { x: number; y: number }, message?: string) =>\n (value: FileValue | undefined) => {\n if (!value || !value.asset) {\n return true\n }\n const { width, height } = getImageDimensions(value.asset._ref)\n if (!!x && width > x) {\n return message \n ? message.replace(\"{width}\", width.toString())\n .replace(\"{height}\", height.toString())\n .replace(\"{x}\", x.toString())\n .replace(\"{y}\", !y ? \"(any)\" : y.toString()) \n : `Image must be at most ${x} pixels wide.`\n }\n if (!!y && height > y) {\n return message \n ? message.replace(\"{width}\", width.toString())\n .replace(\"{height}\", height.toString())\n .replace(\"{x}\", !x ? \"(any)\" : x.toString())\n .replace(\"{y}\", y.toString())\n : `Image must be at most ${y} pixels tall.`\n }\n return true\n }\n\n// todo: this should fail if its attached to a field that is not of type \"image\"","import { ValidationContext } from \"sanity\"\n\nexport const maxDepth = (\n maxDepth: number, \n key: string,\n message: string = `Error: You can only nest {key} {maxDepth} levels deep.`\n) => (_: any, context: ValidationContext) => {\n let regex = new RegExp(String.raw`topLevelItems|${key}`)\n const paths = (context.path as Array<any>).filter((e) => typeof e === \"string\" && e.match(regex))\n if (paths.length > maxDepth) {\n return message\n .replace(\"{key}\", key)\n .replace(\"{nestedValueName}\", key) // backward compatibility\n .replace(\"{maxDepth}\", maxDepth.toString())\n }\n return true\n}\n","import { ValidationContext } from \"sanity\"\n\n/*\nSanity has a funny idea of conditional fields. Every field is _always_ present, but it might be hidden.\nex. hidden: (node) => node.parent.slug === 'hideMe'\nThis works really well — unless a field marked as required gets hidden. \n\nThis validator conditionally marks a field as required only for specific slugs. It accepts a string or array of strings.\n```\nvalidation: (rule) => rule.custom(requiredIfSlugEq('alpha'))\nvalidation: (rule) => rule.custom(requiredIfSlugEq(['alpha', 'beta']))\nvalidation: (rule) => rule.custom(requiredIfSlugNotEq(['beta']))\n```\n\nIf the key of your slug is not simply \"slug\", fill that in the optional second parameter.\n```\nvalidation: (rule) => rule.custom(requiredIfSlugEq('alpha', 'id'))\n```\n\n\"Could this method be simpler if it just checked for the self.hidden state?\"\nNot possible, since the hidden state is not exposed to the context.\n\nBut even if it were, you wouldn't want to. There are valid reasons to make a component required but hidden.\nex. an admin- or developer-level identifier that you don't want civilians to see or edit.\n*/\n\nexport const requiredIfSlugEq = (\n slug: Array<string> | string, \n slugKey: string = \"slug\", \n message: string = `This is a required field.`\n) =>\n (value: unknown | undefined, context: ValidationContext) => {\n const slugs = typeof slug === \"string\" ? [slug] : slug\n const slugValue = (context.parent as any)?.[slugKey]?.current\n \n // todo: does slugKey exist? If not, fail.\n // todo: deal with nested slugKey (ex. metadata.slug)\n \n if (!value && !!slugValue && slugs.includes(slugValue)) {\n return message\n .replace(\"{slugKey}\", slugKey)\n .replace(\"{operand}\", slugs.join(', or '))\n .replace(\"{siblingSlugValue}\", slugValue)\n }\n return true\n }","import { ValidationContext } from \"sanity\"\n\nexport const requiredIfSlugNeq = (\n slug: Array<string> | string, \n slugKey: string = \"slug\", \n message: string = `This is a required field.`\n) =>\n (value: unknown | undefined, context: ValidationContext) => {\n const slugs = typeof slug === \"string\" ? [slug] : slug\n const slugValue = (context.parent as any)?.[slugKey]?.current\n if (!value && !slugs.includes(slugValue)) {\n return message\n .replace(\"{slugKey}\", slugKey)\n .replace(\"{operand}\", slugs.join(', or '))\n .replace(\"{siblingSlugValue}\", slugValue)\n \n }\n return true\n }\n","import {getSibling} from './'\nimport {ValidationContext} from 'sanity'\n\n/*\nFor a given object that has multiple fields, mark a field as `required` if a sibling has a particular value.\n\n```\ndefineType({\n name: 'ifAlphaAlsoBeta',\n type: 'object',\n fields: [\n defineField({\n name: 'alpha',\n type: 'string',\n options: {\n list: ['left', 'right'],\n layout: 'radio',\n direction: 'horizontal',\n },\n }),\n defineField({\n name: 'beta',\n type: 'string',\n placeholder: 'If alpha is “left”, I’m also required',\n validation: (rule) => rule.custom(requiredIfSiblingEq('alpha', 'left')),\n })\n ],\n})\n```\n\nIncidentally, context.path is technically Array<sanity.PathSegment>.\n\nThat shouldn't matter, but dealing with that and remapping siblingKey as a PathSegment could be a possible future enhancement.\n*/\n\nexport const requiredIfSiblingEq = (\n key: string, \n operand: string | number | null | Array<string | number | null>, \n message: string = 'Required if {key} equals {operand}.'\n) =>\n (value: unknown | undefined, context: ValidationContext) => {\n const siblingValue = getSibling(key, context)\n const operands = Array.isArray(operand) ? operand : [operand]\n if (!value && operands.includes(siblingValue)) {\n return message\n .replace('{key}', key)\n .replace('{operand}', operands.join(', or ') ?? 'null')\n .replace('{value}', operands.join(', or ') ?? 'null') // backward compatibility\n .replace('{siblingValue}', siblingValue)\n }\n return true\n }\n","import {getSibling} from './'\nimport {ValidationContext} from 'sanity'\n\nexport const requiredIfSiblingNeq = (\n key: string, \n operand: string | number | null | Array<string | number | null>, \n message: string = 'Required if {key} does not equal {operand}.'\n) =>\n (value: unknown | undefined, context: ValidationContext) => {\n const siblingValue = getSibling(key, context)\n const operands = Array.isArray(operand) ? operand : [operand]\n if(!value && !operands.includes(siblingValue)) {\n return message\n .replace('{key}', key)\n .replace('{operand}', operands.join(', or ') ?? 'null')\n .replace('{value}', operands.join(', or ') ?? 'null') // backward compatibility\n .replace('{siblingValue}', siblingValue)\n }\n return true\n }\n\n\n\n\n\n\n\n\n\n","import { get } from \"lodash-es\"\nimport { ValidationContext } from \"sanity\"\n\nexport const getSibling = (key: string | number, context: ValidationContext) => {\n if(!context.path) return undefined\n const pathToParentObject = context.path.slice(0, -1) as Array<string | number>\n const sibling = get(context.document, [...pathToParentObject, key])\n return sibling\n}\n\n/*\nTODO:\n There is an issue with finding a sibling when in an array element.\n If the context document looks something like this…\n {\n someArray: [\n {\n _key: 'abc123',\n targetSibling: 'herpderp'\n }\n ]\n }\n … we wind up with a path of…\n [ 'someArray', { _key: 'ab123' }, 'targetSibling' ]\n lodash.get() is trying to do an exact match, it doesn't know how to get object by _key.\n \n Will probably have to replace get() with a gnarly recursive lookup function.\n*/\n","export const regex =\n (pattern: RegExp, message: string = `“{value}” does not match the pattern {pattern}.`) =>\n (value: unknown) => {\n if (!value) {\n return true\n }\n const valueAsString = typeof value !== \"string\" ? value.toString() : value\n return pattern.test(valueAsString) ? true : message.replace(\"{value}\", valueAsString).replace(\"{pattern}\", pattern.toString())\n }\n"],"mappings":"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","names":["import_asset_utils","import_asset_utils","maxDepth","regex"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/referencedDocumentRequires.ts","../src/fileExtension.ts","../src/minCount.ts","../src/maxCount.ts","../src/minDimensions.ts","../src/maxDimensions.ts","../src/maxDepth.ts","../src/requiredIfSlugEq.ts","../src/requiredIfSlugNeq.ts","../src/requiredIfSiblingEq.ts","../src/requiredIfSiblingNeq.ts","../src/getSibling.ts","../src/regex.ts"],"sourcesContent":["export * from \"./referencedDocumentRequires\"\nexport * from \"./fileExtension\"\nexport * from \"./minCount\"\nexport * from \"./maxCount\"\nexport * from \"./minDimensions\"\nexport * from \"./maxDimensions\"\nexport * from \"./maxDepth\"\nexport * from \"./requiredIfSlugEq\"\nexport * from \"./requiredIfSlugNeq\"\nexport * from \"./requiredIfSiblingEq\"\nexport * from \"./requiredIfSiblingNeq\"\nexport * from \"./getSibling\"\nexport * from \"./regex\"\n","import { ValidationContext } from \"sanity\"\n\nexport const referencedDocumentRequires = (\n documentType: string, \n field: string, \n message: string = `{documentType}’s {field} must be filled.`\n) => async (value: any | undefined, context: ValidationContext) => {\n if (!value?._ref) {\n return true\n }\n const client = context.getClient({ apiVersion: \"2022-08-12\" })\n // todo: use current API version, or test with no version at all\n\n // todo: if there's a value._type or value.referenced._type or something, we get rid of document.type from inputs\n const data = await client.fetch(`\n *[_type == \"${documentType}\" && _id == \"${value._ref}\"]{\n ${field}\n }[0]\n `) // TODO: why is typescript screaming about this? Fetch takes two parameters.\n if (!data[field]) {\n return message.replace(\"{documentType}\", documentType).replace(\"{field}\", field)\n }\n return true\n}\n","import { getExtension } from \"@sanity/asset-utils\"\nimport { FileValue } from \"sanity\"\n\nexport const fileExtension = (\n validFileExtension: string | Array<string>, \n message: string = `Image must be of type {validFileExtension}`\n) => (value: FileValue | undefined) => {\n if (!value || !value.asset) {\n return true\n }\n const validExtensions = typeof validFileExtension === \"string\" ? [validFileExtension] : validFileExtension\n const filetype = getExtension(value.asset._ref)\n if (!validExtensions.includes(filetype)) {\n return message.replace(\"{validFileExtension}\", validExtensions.join(\", or \"))\n }\n return true\n}\n\n// todo: this should fail if its attached to a field that is not of type \"file\"","export const minCount = (n: number, message?: string) => (value: Array<unknown> | undefined) => {\n if (!value) {\n return true\n }\n if (value.length < n) {\n return message ? message.replace(\"{n}\", n.toString()) : `Array must contain at least ${n} items.`\n }\n return true\n}\n","export const maxCount = (n: number, message?: string) => (value: Array<unknown> | undefined) => {\n if (!value) {\n return true\n }\n if (value.length > n) {\n return message ? message.replace(\"{n}\", n.toString()) : `Array must contain at most ${n} items.`\n }\n return true\n}\n","import { getImageDimensions } from \"@sanity/asset-utils\"\nimport { FileValue } from \"sanity\"\n\nexport const minDimensions =\n ({ x, y }: { x: number; y: number }, message?: string) =>\n (value: FileValue | undefined) => {\n if (!value || !value.asset) {\n return true\n }\n const { width, height } = getImageDimensions(value.asset._ref)\n if (!!x && width < x) {\n return message \n ? message.replace(\"{width}\", width.toString())\n .replace(\"{height}\", height.toString())\n .replace(\"{x}\", x.toString())\n .replace(\"{y}\", !y ? \"(any)\" : y.toString()) \n : `Image must be at least ${x} pixels wide.`\n }\n if (!!y && height < y) {\n return message \n ? message.replace(\"{width}\", width.toString())\n .replace(\"{height}\", height.toString())\n .replace(\"{x}\", !x ? \"(any)\" : x.toString())\n .replace(\"{y}\", y.toString())\n : `Image must be at least ${y} pixels tall.`\n }\n return true\n }\n\n// todo: this should fail if its attached to a field that is not of type \"image\"","import { getImageDimensions } from \"@sanity/asset-utils\"\nimport { FileValue } from \"sanity\"\n\nexport const maxDimensions =\n ({ x, y }: { x: number; y: number }, message?: string) =>\n (value: FileValue | undefined) => {\n if (!value || !value.asset) {\n return true\n }\n const { width, height } = getImageDimensions(value.asset._ref)\n if (!!x && width > x) {\n return message \n ? message.replace(\"{width}\", width.toString())\n .replace(\"{height}\", height.toString())\n .replace(\"{x}\", x.toString())\n .replace(\"{y}\", !y ? \"(any)\" : y.toString()) \n : `Image must be at most ${x} pixels wide.`\n }\n if (!!y && height > y) {\n return message \n ? message.replace(\"{width}\", width.toString())\n .replace(\"{height}\", height.toString())\n .replace(\"{x}\", !x ? \"(any)\" : x.toString())\n .replace(\"{y}\", y.toString())\n : `Image must be at most ${y} pixels tall.`\n }\n return true\n }\n\n// todo: this should fail if its attached to a field that is not of type \"image\"","import { ValidationContext } from \"sanity\"\n\nexport const maxDepth = (\n maxDepth: number, \n key: string,\n message: string = `Error: You can only nest {key} {maxDepth} levels deep.`\n) => (_: any, context: ValidationContext) => {\n let regex = new RegExp(String.raw`topLevelItems|${key}`)\n const paths = (context.path as Array<any>).filter((e) => typeof e === \"string\" && e.match(regex))\n if (paths.length > maxDepth) {\n return message\n .replace(\"{key}\", key)\n .replace(\"{nestedValueName}\", key) // backward compatibility\n .replace(\"{maxDepth}\", maxDepth.toString())\n }\n return true\n}\n","import { getSibling } from \"./\"\nimport { ValidationContext } from \"sanity\"\n\n/*\nSanity has a funny idea of conditional fields. Every field is _always_ present, but it might be hidden.\nex. hidden: (node) => node.parent.slug === 'hideMe'\nThis works really well — unless a field marked as required gets hidden. \n\nThis validator conditionally marks a field as required only for specific slugs. It accepts a string or array of strings.\n```\nvalidation: (rule) => rule.custom(requiredIfSlugEq('alpha'))\nvalidation: (rule) => rule.custom(requiredIfSlugEq(['alpha', 'beta']))\nvalidation: (rule) => rule.custom(requiredIfSlugNotEq(['beta']))\n```\n\nIf the key of your slug is not simply \"slug\", fill that in the optional second parameter.\n```\nvalidation: (rule) => rule.custom(requiredIfSlugEq('alpha', 'id'))\n```\n\n\"Could this method be simpler if it just checked for the self.hidden state?\"\nNot possible, since the hidden state is not exposed to the context.\n\nBut even if it were, you wouldn't want to. There are valid reasons to make a component required but hidden.\nex. an admin- or developer-level identifier that you don't want civilians to see or edit.\n*/\n\nexport const requiredIfSlugEq =\n (operand: Array<string> | string, slugKey: string = \"slug\", message: string = `This is a required field.`) =>\n (value: unknown | undefined, context: ValidationContext) => {\n const slugValue = getSibling(slugKey, context)?.current\n const operands = typeof operand === \"string\" ? [operand] : operand\n\n // todo: does slugKey exist? If not, fail.\n // todo: deal with nested slugKey (ex. metadata.slug)\n\n if (!value && !!slugValue && operands.includes(slugValue)) {\n return message.replace(\"{slugKey}\", slugKey).replace(\"{operand}\", operands.join(\", or \")).replace(\"{siblingSlugValue}\", slugValue)\n }\n return true\n }\n","import { getSibling } from \"./\"\nimport { ValidationContext } from \"sanity\"\n\nexport const requiredIfSlugNeq =\n (operand: Array<string> | string, slugKey: string = \"slug\", message: string = `This is a required field.`) =>\n (value: unknown | undefined, context: ValidationContext) => {\n const operands = typeof operand === \"string\" ? [operand] : operand\n const slugValue = getSibling(slugKey, context)?.current\n if (!value && !operands.includes(slugValue)) {\n return message.replace(\"{slugKey}\", slugKey).replace(\"{operand}\", operands.join(\", or \")).replace(\"{siblingSlugValue}\", slugValue)\n }\n return true\n }\n","import { getSibling } from \"./\"\nimport { ValidationContext } from \"sanity\"\n\n/*\nFor a given object that has multiple fields, mark a field as `required` if a sibling has a particular value.\n\n```\ndefineType({\n name: 'ifAlphaAlsoBeta',\n type: 'object',\n fields: [\n defineField({\n name: 'alpha',\n type: 'string',\n options: {\n list: ['left', 'right'],\n layout: 'radio',\n direction: 'horizontal',\n },\n }),\n defineField({\n name: 'beta',\n type: 'string',\n placeholder: 'If alpha is “left”, I’m also required',\n validation: (rule) => rule.custom(requiredIfSiblingEq('alpha', 'left')),\n })\n ],\n})\n```\n\nIncidentally, context.path is technically Array<sanity.PathSegment>.\n\nThat shouldn't matter, but dealing with that and remapping siblingKey as a PathSegment could be a possible future enhancement.\n*/\n\nexport const requiredIfSiblingEq =\n (key: string, operand: string | number | null | Array<string | number | null>, message: string = \"Required if {key} equals {operand}.\") =>\n (value: unknown | undefined, context: ValidationContext) => {\n const siblingValue = getSibling(key, context)\n const operands = Array.isArray(operand) ? operand : [operand]\n if (!value && operands.includes(siblingValue)) {\n return message\n .replace(\"{key}\", key)\n .replace(\"{operand}\", operands.join(\", or \") ?? \"null\")\n .replace(\"{value}\", operands.join(\", or \") ?? \"null\") // backward compatibility\n .replace(\"{siblingValue}\", siblingValue)\n }\n return true\n }\n","import {getSibling} from './'\nimport {ValidationContext} from 'sanity'\n\nexport const requiredIfSiblingNeq = (\n key: string, \n operand: string | number | null | Array<string | number | null>, \n message: string = 'Required if {key} does not equal {operand}.'\n) =>\n (value: unknown | undefined, context: ValidationContext) => {\n const siblingValue = getSibling(key, context)\n const operands = Array.isArray(operand) ? operand : [operand]\n if(!value && !operands.includes(siblingValue)) {\n return message\n .replace('{key}', key)\n .replace('{operand}', operands.join(', or ') ?? 'null')\n .replace('{value}', operands.join(', or ') ?? 'null') // backward compatibility\n .replace('{siblingValue}', siblingValue)\n }\n return true\n }\n\n\n\n\n\n\n\n\n\n","import { ValidationContext } from \"sanity\"\n\nexport const getSibling = (key: string | number, context: ValidationContext) => {\n const path = context.path ? (context.path.slice(0, -1) as Array<string | number>) : []\n const sibling = [...path, key].reduce((acc: any, step: string | number | Record<\"_key\", string>) => {\n if (typeof step === \"string\" && acc.hasOwnProperty(step)) {\n return acc[step]\n } else if (typeof step === \"object\" && step.hasOwnProperty(\"_key\") && Array.isArray(acc)) {\n return acc.find((i) => i._key === step._key)\n } else {\n // should never arrive here\n console.error(\"sanity-advanced-validators: Unreachable point reached!\")\n return acc\n }\n }, context.document)\n return sibling\n}\n","export const regex =\n (pattern: RegExp, message: string = `“{value}” does not match the pattern {pattern}.`) =>\n (value: unknown) => {\n if (!value) {\n return true\n }\n const valueAsString = typeof value !== \"string\" ? value.toString() : value\n return pattern.test(valueAsString) ? true : message.replace(\"{value}\", valueAsString).replace(\"{pattern}\", pattern.toString())\n }\n"],"mappings":"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","names":["import_asset_utils","import_asset_utils","maxDepth","regex"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -20,9 +20,9 @@ declare const maxDimensions: ({ x, y }: {
|
|
|
20
20
|
|
|
21
21
|
declare const maxDepth: (maxDepth: number, key: string, message?: string) => (_: any, context: ValidationContext) => string | true;
|
|
22
22
|
|
|
23
|
-
declare const requiredIfSlugEq: (
|
|
23
|
+
declare const requiredIfSlugEq: (operand: Array<string> | string, slugKey?: string, message?: string) => (value: unknown | undefined, context: ValidationContext) => string | true;
|
|
24
24
|
|
|
25
|
-
declare const requiredIfSlugNeq: (
|
|
25
|
+
declare const requiredIfSlugNeq: (operand: Array<string> | string, slugKey?: string, message?: string) => (value: unknown | undefined, context: ValidationContext) => string | true;
|
|
26
26
|
|
|
27
27
|
declare const requiredIfSiblingEq: (key: string, operand: string | number | null | Array<string | number | null>, message?: string) => (value: unknown | undefined, context: ValidationContext) => string | true;
|
|
28
28
|
|
package/dist/index.d.ts
CHANGED
|
@@ -20,9 +20,9 @@ declare const maxDimensions: ({ x, y }: {
|
|
|
20
20
|
|
|
21
21
|
declare const maxDepth: (maxDepth: number, key: string, message?: string) => (_: any, context: ValidationContext) => string | true;
|
|
22
22
|
|
|
23
|
-
declare const requiredIfSlugEq: (
|
|
23
|
+
declare const requiredIfSlugEq: (operand: Array<string> | string, slugKey?: string, message?: string) => (value: unknown | undefined, context: ValidationContext) => string | true;
|
|
24
24
|
|
|
25
|
-
declare const requiredIfSlugNeq: (
|
|
25
|
+
declare const requiredIfSlugNeq: (operand: Array<string> | string, slugKey?: string, message?: string) => (value: unknown | undefined, context: ValidationContext) => string | true;
|
|
26
26
|
|
|
27
27
|
declare const requiredIfSiblingEq: (key: string, operand: string | number | null | Array<string | number | null>, message?: string) => (value: unknown | undefined, context: ValidationContext) => string | true;
|
|
28
28
|
|
package/dist/index.js
CHANGED
|
@@ -94,23 +94,23 @@ var maxDepth = (maxDepth2, key, message = `Error: You can only nest {key} {maxDe
|
|
|
94
94
|
};
|
|
95
95
|
|
|
96
96
|
// src/requiredIfSlugEq.ts
|
|
97
|
-
var requiredIfSlugEq = (
|
|
98
|
-
var _a
|
|
99
|
-
const
|
|
100
|
-
const
|
|
101
|
-
if (!value && !!slugValue &&
|
|
102
|
-
return message.replace("{slugKey}", slugKey).replace("{operand}",
|
|
97
|
+
var requiredIfSlugEq = (operand, slugKey = "slug", message = `This is a required field.`) => (value, context) => {
|
|
98
|
+
var _a;
|
|
99
|
+
const slugValue = (_a = getSibling(slugKey, context)) == null ? void 0 : _a.current;
|
|
100
|
+
const operands = typeof operand === "string" ? [operand] : operand;
|
|
101
|
+
if (!value && !!slugValue && operands.includes(slugValue)) {
|
|
102
|
+
return message.replace("{slugKey}", slugKey).replace("{operand}", operands.join(", or ")).replace("{siblingSlugValue}", slugValue);
|
|
103
103
|
}
|
|
104
104
|
return true;
|
|
105
105
|
};
|
|
106
106
|
|
|
107
107
|
// src/requiredIfSlugNeq.ts
|
|
108
|
-
var requiredIfSlugNeq = (
|
|
109
|
-
var _a
|
|
110
|
-
const
|
|
111
|
-
const slugValue = (
|
|
112
|
-
if (!value && !
|
|
113
|
-
return message.replace("{slugKey}", slugKey).replace("{operand}",
|
|
108
|
+
var requiredIfSlugNeq = (operand, slugKey = "slug", message = `This is a required field.`) => (value, context) => {
|
|
109
|
+
var _a;
|
|
110
|
+
const operands = typeof operand === "string" ? [operand] : operand;
|
|
111
|
+
const slugValue = (_a = getSibling(slugKey, context)) == null ? void 0 : _a.current;
|
|
112
|
+
if (!value && !operands.includes(slugValue)) {
|
|
113
|
+
return message.replace("{slugKey}", slugKey).replace("{operand}", operands.join(", or ")).replace("{siblingSlugValue}", slugValue);
|
|
114
114
|
}
|
|
115
115
|
return true;
|
|
116
116
|
};
|
|
@@ -137,12 +137,19 @@ var requiredIfSiblingNeq = (key, operand, message = "Required if {key} does not
|
|
|
137
137
|
return true;
|
|
138
138
|
};
|
|
139
139
|
|
|
140
|
-
// src/
|
|
141
|
-
import { get } from "lodash-es";
|
|
140
|
+
// src/getSibling.ts
|
|
142
141
|
var getSibling = (key, context) => {
|
|
143
|
-
|
|
144
|
-
const
|
|
145
|
-
|
|
142
|
+
const path = context.path ? context.path.slice(0, -1) : [];
|
|
143
|
+
const sibling = [...path, key].reduce((acc, step) => {
|
|
144
|
+
if (typeof step === "string" && acc.hasOwnProperty(step)) {
|
|
145
|
+
return acc[step];
|
|
146
|
+
} else if (typeof step === "object" && step.hasOwnProperty("_key") && Array.isArray(acc)) {
|
|
147
|
+
return acc.find((i) => i._key === step._key);
|
|
148
|
+
} else {
|
|
149
|
+
console.error("sanity-advanced-validators: Unreachable point reached!");
|
|
150
|
+
return acc;
|
|
151
|
+
}
|
|
152
|
+
}, context.document);
|
|
146
153
|
return sibling;
|
|
147
154
|
};
|
|
148
155
|
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/referencedDocumentRequires.ts","../src/fileExtension.ts","../src/minCount.ts","../src/maxCount.ts","../src/minDimensions.ts","../src/maxDimensions.ts","../src/maxDepth.ts","../src/requiredIfSlugEq.ts","../src/requiredIfSlugNeq.ts","../src/requiredIfSiblingEq.ts","../src/requiredIfSiblingNeq.ts","../src/lib/getSibling.ts","../src/regex.ts"],"sourcesContent":["import { ValidationContext } from \"sanity\"\n\nexport const referencedDocumentRequires = (\n documentType: string, \n field: string, \n message: string = `{documentType}’s {field} must be filled.`\n) => async (value: any | undefined, context: ValidationContext) => {\n if (!value?._ref) {\n return true\n }\n const client = context.getClient({ apiVersion: \"2022-08-12\" })\n // todo: use current API version, or test with no version at all\n\n // todo: if there's a value._type or value.referenced._type or something, we get rid of document.type from inputs\n const data = await client.fetch(`\n *[_type == \"${documentType}\" && _id == \"${value._ref}\"]{\n ${field}\n }[0]\n `) // TODO: why is typescript screaming about this? Fetch takes two parameters.\n if (!data[field]) {\n return message.replace(\"{documentType}\", documentType).replace(\"{field}\", field)\n }\n return true\n}\n","import { getExtension } from \"@sanity/asset-utils\"\nimport { FileValue } from \"sanity\"\n\nexport const fileExtension = (\n validFileExtension: string | Array<string>, \n message: string = `Image must be of type {validFileExtension}`\n) => (value: FileValue | undefined) => {\n if (!value || !value.asset) {\n return true\n }\n const validExtensions = typeof validFileExtension === \"string\" ? [validFileExtension] : validFileExtension\n const filetype = getExtension(value.asset._ref)\n if (!validExtensions.includes(filetype)) {\n return message.replace(\"{validFileExtension}\", validExtensions.join(\", or \"))\n }\n return true\n}\n\n// todo: this should fail if its attached to a field that is not of type \"file\"","export const minCount = (n: number, message?: string) => (value: Array<unknown> | undefined) => {\n if (!value) {\n return true\n }\n if (value.length < n) {\n return message ? message.replace(\"{n}\", n.toString()) : `Array must contain at least ${n} items.`\n }\n return true\n}\n","export const maxCount = (n: number, message?: string) => (value: Array<unknown> | undefined) => {\n if (!value) {\n return true\n }\n if (value.length > n) {\n return message ? message.replace(\"{n}\", n.toString()) : `Array must contain at most ${n} items.`\n }\n return true\n}\n","import { getImageDimensions } from \"@sanity/asset-utils\"\nimport { FileValue } from \"sanity\"\n\nexport const minDimensions =\n ({ x, y }: { x: number; y: number }, message?: string) =>\n (value: FileValue | undefined) => {\n if (!value || !value.asset) {\n return true\n }\n const { width, height } = getImageDimensions(value.asset._ref)\n if (!!x && width < x) {\n return message \n ? message.replace(\"{width}\", width.toString())\n .replace(\"{height}\", height.toString())\n .replace(\"{x}\", x.toString())\n .replace(\"{y}\", !y ? \"(any)\" : y.toString()) \n : `Image must be at least ${x} pixels wide.`\n }\n if (!!y && height < y) {\n return message \n ? message.replace(\"{width}\", width.toString())\n .replace(\"{height}\", height.toString())\n .replace(\"{x}\", !x ? \"(any)\" : x.toString())\n .replace(\"{y}\", y.toString())\n : `Image must be at least ${y} pixels tall.`\n }\n return true\n }\n\n// todo: this should fail if its attached to a field that is not of type \"image\"","import { getImageDimensions } from \"@sanity/asset-utils\"\nimport { FileValue } from \"sanity\"\n\nexport const maxDimensions =\n ({ x, y }: { x: number; y: number }, message?: string) =>\n (value: FileValue | undefined) => {\n if (!value || !value.asset) {\n return true\n }\n const { width, height } = getImageDimensions(value.asset._ref)\n if (!!x && width > x) {\n return message \n ? message.replace(\"{width}\", width.toString())\n .replace(\"{height}\", height.toString())\n .replace(\"{x}\", x.toString())\n .replace(\"{y}\", !y ? \"(any)\" : y.toString()) \n : `Image must be at most ${x} pixels wide.`\n }\n if (!!y && height > y) {\n return message \n ? message.replace(\"{width}\", width.toString())\n .replace(\"{height}\", height.toString())\n .replace(\"{x}\", !x ? \"(any)\" : x.toString())\n .replace(\"{y}\", y.toString())\n : `Image must be at most ${y} pixels tall.`\n }\n return true\n }\n\n// todo: this should fail if its attached to a field that is not of type \"image\"","import { ValidationContext } from \"sanity\"\n\nexport const maxDepth = (\n maxDepth: number, \n key: string,\n message: string = `Error: You can only nest {key} {maxDepth} levels deep.`\n) => (_: any, context: ValidationContext) => {\n let regex = new RegExp(String.raw`topLevelItems|${key}`)\n const paths = (context.path as Array<any>).filter((e) => typeof e === \"string\" && e.match(regex))\n if (paths.length > maxDepth) {\n return message\n .replace(\"{key}\", key)\n .replace(\"{nestedValueName}\", key) // backward compatibility\n .replace(\"{maxDepth}\", maxDepth.toString())\n }\n return true\n}\n","import { ValidationContext } from \"sanity\"\n\n/*\nSanity has a funny idea of conditional fields. Every field is _always_ present, but it might be hidden.\nex. hidden: (node) => node.parent.slug === 'hideMe'\nThis works really well — unless a field marked as required gets hidden. \n\nThis validator conditionally marks a field as required only for specific slugs. It accepts a string or array of strings.\n```\nvalidation: (rule) => rule.custom(requiredIfSlugEq('alpha'))\nvalidation: (rule) => rule.custom(requiredIfSlugEq(['alpha', 'beta']))\nvalidation: (rule) => rule.custom(requiredIfSlugNotEq(['beta']))\n```\n\nIf the key of your slug is not simply \"slug\", fill that in the optional second parameter.\n```\nvalidation: (rule) => rule.custom(requiredIfSlugEq('alpha', 'id'))\n```\n\n\"Could this method be simpler if it just checked for the self.hidden state?\"\nNot possible, since the hidden state is not exposed to the context.\n\nBut even if it were, you wouldn't want to. There are valid reasons to make a component required but hidden.\nex. an admin- or developer-level identifier that you don't want civilians to see or edit.\n*/\n\nexport const requiredIfSlugEq = (\n slug: Array<string> | string, \n slugKey: string = \"slug\", \n message: string = `This is a required field.`\n) =>\n (value: unknown | undefined, context: ValidationContext) => {\n const slugs = typeof slug === \"string\" ? [slug] : slug\n const slugValue = (context.parent as any)?.[slugKey]?.current\n \n // todo: does slugKey exist? If not, fail.\n // todo: deal with nested slugKey (ex. metadata.slug)\n \n if (!value && !!slugValue && slugs.includes(slugValue)) {\n return message\n .replace(\"{slugKey}\", slugKey)\n .replace(\"{operand}\", slugs.join(', or '))\n .replace(\"{siblingSlugValue}\", slugValue)\n }\n return true\n }","import { ValidationContext } from \"sanity\"\n\nexport const requiredIfSlugNeq = (\n slug: Array<string> | string, \n slugKey: string = \"slug\", \n message: string = `This is a required field.`\n) =>\n (value: unknown | undefined, context: ValidationContext) => {\n const slugs = typeof slug === \"string\" ? [slug] : slug\n const slugValue = (context.parent as any)?.[slugKey]?.current\n if (!value && !slugs.includes(slugValue)) {\n return message\n .replace(\"{slugKey}\", slugKey)\n .replace(\"{operand}\", slugs.join(', or '))\n .replace(\"{siblingSlugValue}\", slugValue)\n \n }\n return true\n }\n","import {getSibling} from './'\nimport {ValidationContext} from 'sanity'\n\n/*\nFor a given object that has multiple fields, mark a field as `required` if a sibling has a particular value.\n\n```\ndefineType({\n name: 'ifAlphaAlsoBeta',\n type: 'object',\n fields: [\n defineField({\n name: 'alpha',\n type: 'string',\n options: {\n list: ['left', 'right'],\n layout: 'radio',\n direction: 'horizontal',\n },\n }),\n defineField({\n name: 'beta',\n type: 'string',\n placeholder: 'If alpha is “left”, I’m also required',\n validation: (rule) => rule.custom(requiredIfSiblingEq('alpha', 'left')),\n })\n ],\n})\n```\n\nIncidentally, context.path is technically Array<sanity.PathSegment>.\n\nThat shouldn't matter, but dealing with that and remapping siblingKey as a PathSegment could be a possible future enhancement.\n*/\n\nexport const requiredIfSiblingEq = (\n key: string, \n operand: string | number | null | Array<string | number | null>, \n message: string = 'Required if {key} equals {operand}.'\n) =>\n (value: unknown | undefined, context: ValidationContext) => {\n const siblingValue = getSibling(key, context)\n const operands = Array.isArray(operand) ? operand : [operand]\n if (!value && operands.includes(siblingValue)) {\n return message\n .replace('{key}', key)\n .replace('{operand}', operands.join(', or ') ?? 'null')\n .replace('{value}', operands.join(', or ') ?? 'null') // backward compatibility\n .replace('{siblingValue}', siblingValue)\n }\n return true\n }\n","import {getSibling} from './'\nimport {ValidationContext} from 'sanity'\n\nexport const requiredIfSiblingNeq = (\n key: string, \n operand: string | number | null | Array<string | number | null>, \n message: string = 'Required if {key} does not equal {operand}.'\n) =>\n (value: unknown | undefined, context: ValidationContext) => {\n const siblingValue = getSibling(key, context)\n const operands = Array.isArray(operand) ? operand : [operand]\n if(!value && !operands.includes(siblingValue)) {\n return message\n .replace('{key}', key)\n .replace('{operand}', operands.join(', or ') ?? 'null')\n .replace('{value}', operands.join(', or ') ?? 'null') // backward compatibility\n .replace('{siblingValue}', siblingValue)\n }\n return true\n }\n\n\n\n\n\n\n\n\n\n","import { get } from \"lodash-es\"\nimport { ValidationContext } from \"sanity\"\n\nexport const getSibling = (key: string | number, context: ValidationContext) => {\n if(!context.path) return undefined\n const pathToParentObject = context.path.slice(0, -1) as Array<string | number>\n const sibling = get(context.document, [...pathToParentObject, key])\n return sibling\n}\n\n/*\nTODO:\n There is an issue with finding a sibling when in an array element.\n If the context document looks something like this…\n {\n someArray: [\n {\n _key: 'abc123',\n targetSibling: 'herpderp'\n }\n ]\n }\n … we wind up with a path of…\n [ 'someArray', { _key: 'ab123' }, 'targetSibling' ]\n lodash.get() is trying to do an exact match, it doesn't know how to get object by _key.\n \n Will probably have to replace get() with a gnarly recursive lookup function.\n*/\n","export const regex =\n (pattern: RegExp, message: string = `“{value}” does not match the pattern {pattern}.`) =>\n (value: unknown) => {\n if (!value) {\n return true\n }\n const valueAsString = typeof value !== \"string\" ? value.toString() : value\n return pattern.test(valueAsString) ? true : message.replace(\"{value}\", valueAsString).replace(\"{pattern}\", pattern.toString())\n }\n"],"mappings":"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","names":["getImageDimensions","maxDepth","regex"]}
|
|
1
|
+
{"version":3,"sources":["../src/referencedDocumentRequires.ts","../src/fileExtension.ts","../src/minCount.ts","../src/maxCount.ts","../src/minDimensions.ts","../src/maxDimensions.ts","../src/maxDepth.ts","../src/requiredIfSlugEq.ts","../src/requiredIfSlugNeq.ts","../src/requiredIfSiblingEq.ts","../src/requiredIfSiblingNeq.ts","../src/getSibling.ts","../src/regex.ts"],"sourcesContent":["import { ValidationContext } from \"sanity\"\n\nexport const referencedDocumentRequires = (\n documentType: string, \n field: string, \n message: string = `{documentType}’s {field} must be filled.`\n) => async (value: any | undefined, context: ValidationContext) => {\n if (!value?._ref) {\n return true\n }\n const client = context.getClient({ apiVersion: \"2022-08-12\" })\n // todo: use current API version, or test with no version at all\n\n // todo: if there's a value._type or value.referenced._type or something, we get rid of document.type from inputs\n const data = await client.fetch(`\n *[_type == \"${documentType}\" && _id == \"${value._ref}\"]{\n ${field}\n }[0]\n `) // TODO: why is typescript screaming about this? Fetch takes two parameters.\n if (!data[field]) {\n return message.replace(\"{documentType}\", documentType).replace(\"{field}\", field)\n }\n return true\n}\n","import { getExtension } from \"@sanity/asset-utils\"\nimport { FileValue } from \"sanity\"\n\nexport const fileExtension = (\n validFileExtension: string | Array<string>, \n message: string = `Image must be of type {validFileExtension}`\n) => (value: FileValue | undefined) => {\n if (!value || !value.asset) {\n return true\n }\n const validExtensions = typeof validFileExtension === \"string\" ? [validFileExtension] : validFileExtension\n const filetype = getExtension(value.asset._ref)\n if (!validExtensions.includes(filetype)) {\n return message.replace(\"{validFileExtension}\", validExtensions.join(\", or \"))\n }\n return true\n}\n\n// todo: this should fail if its attached to a field that is not of type \"file\"","export const minCount = (n: number, message?: string) => (value: Array<unknown> | undefined) => {\n if (!value) {\n return true\n }\n if (value.length < n) {\n return message ? message.replace(\"{n}\", n.toString()) : `Array must contain at least ${n} items.`\n }\n return true\n}\n","export const maxCount = (n: number, message?: string) => (value: Array<unknown> | undefined) => {\n if (!value) {\n return true\n }\n if (value.length > n) {\n return message ? message.replace(\"{n}\", n.toString()) : `Array must contain at most ${n} items.`\n }\n return true\n}\n","import { getImageDimensions } from \"@sanity/asset-utils\"\nimport { FileValue } from \"sanity\"\n\nexport const minDimensions =\n ({ x, y }: { x: number; y: number }, message?: string) =>\n (value: FileValue | undefined) => {\n if (!value || !value.asset) {\n return true\n }\n const { width, height } = getImageDimensions(value.asset._ref)\n if (!!x && width < x) {\n return message \n ? message.replace(\"{width}\", width.toString())\n .replace(\"{height}\", height.toString())\n .replace(\"{x}\", x.toString())\n .replace(\"{y}\", !y ? \"(any)\" : y.toString()) \n : `Image must be at least ${x} pixels wide.`\n }\n if (!!y && height < y) {\n return message \n ? message.replace(\"{width}\", width.toString())\n .replace(\"{height}\", height.toString())\n .replace(\"{x}\", !x ? \"(any)\" : x.toString())\n .replace(\"{y}\", y.toString())\n : `Image must be at least ${y} pixels tall.`\n }\n return true\n }\n\n// todo: this should fail if its attached to a field that is not of type \"image\"","import { getImageDimensions } from \"@sanity/asset-utils\"\nimport { FileValue } from \"sanity\"\n\nexport const maxDimensions =\n ({ x, y }: { x: number; y: number }, message?: string) =>\n (value: FileValue | undefined) => {\n if (!value || !value.asset) {\n return true\n }\n const { width, height } = getImageDimensions(value.asset._ref)\n if (!!x && width > x) {\n return message \n ? message.replace(\"{width}\", width.toString())\n .replace(\"{height}\", height.toString())\n .replace(\"{x}\", x.toString())\n .replace(\"{y}\", !y ? \"(any)\" : y.toString()) \n : `Image must be at most ${x} pixels wide.`\n }\n if (!!y && height > y) {\n return message \n ? message.replace(\"{width}\", width.toString())\n .replace(\"{height}\", height.toString())\n .replace(\"{x}\", !x ? \"(any)\" : x.toString())\n .replace(\"{y}\", y.toString())\n : `Image must be at most ${y} pixels tall.`\n }\n return true\n }\n\n// todo: this should fail if its attached to a field that is not of type \"image\"","import { ValidationContext } from \"sanity\"\n\nexport const maxDepth = (\n maxDepth: number, \n key: string,\n message: string = `Error: You can only nest {key} {maxDepth} levels deep.`\n) => (_: any, context: ValidationContext) => {\n let regex = new RegExp(String.raw`topLevelItems|${key}`)\n const paths = (context.path as Array<any>).filter((e) => typeof e === \"string\" && e.match(regex))\n if (paths.length > maxDepth) {\n return message\n .replace(\"{key}\", key)\n .replace(\"{nestedValueName}\", key) // backward compatibility\n .replace(\"{maxDepth}\", maxDepth.toString())\n }\n return true\n}\n","import { getSibling } from \"./\"\nimport { ValidationContext } from \"sanity\"\n\n/*\nSanity has a funny idea of conditional fields. Every field is _always_ present, but it might be hidden.\nex. hidden: (node) => node.parent.slug === 'hideMe'\nThis works really well — unless a field marked as required gets hidden. \n\nThis validator conditionally marks a field as required only for specific slugs. It accepts a string or array of strings.\n```\nvalidation: (rule) => rule.custom(requiredIfSlugEq('alpha'))\nvalidation: (rule) => rule.custom(requiredIfSlugEq(['alpha', 'beta']))\nvalidation: (rule) => rule.custom(requiredIfSlugNotEq(['beta']))\n```\n\nIf the key of your slug is not simply \"slug\", fill that in the optional second parameter.\n```\nvalidation: (rule) => rule.custom(requiredIfSlugEq('alpha', 'id'))\n```\n\n\"Could this method be simpler if it just checked for the self.hidden state?\"\nNot possible, since the hidden state is not exposed to the context.\n\nBut even if it were, you wouldn't want to. There are valid reasons to make a component required but hidden.\nex. an admin- or developer-level identifier that you don't want civilians to see or edit.\n*/\n\nexport const requiredIfSlugEq =\n (operand: Array<string> | string, slugKey: string = \"slug\", message: string = `This is a required field.`) =>\n (value: unknown | undefined, context: ValidationContext) => {\n const slugValue = getSibling(slugKey, context)?.current\n const operands = typeof operand === \"string\" ? [operand] : operand\n\n // todo: does slugKey exist? If not, fail.\n // todo: deal with nested slugKey (ex. metadata.slug)\n\n if (!value && !!slugValue && operands.includes(slugValue)) {\n return message.replace(\"{slugKey}\", slugKey).replace(\"{operand}\", operands.join(\", or \")).replace(\"{siblingSlugValue}\", slugValue)\n }\n return true\n }\n","import { getSibling } from \"./\"\nimport { ValidationContext } from \"sanity\"\n\nexport const requiredIfSlugNeq =\n (operand: Array<string> | string, slugKey: string = \"slug\", message: string = `This is a required field.`) =>\n (value: unknown | undefined, context: ValidationContext) => {\n const operands = typeof operand === \"string\" ? [operand] : operand\n const slugValue = getSibling(slugKey, context)?.current\n if (!value && !operands.includes(slugValue)) {\n return message.replace(\"{slugKey}\", slugKey).replace(\"{operand}\", operands.join(\", or \")).replace(\"{siblingSlugValue}\", slugValue)\n }\n return true\n }\n","import { getSibling } from \"./\"\nimport { ValidationContext } from \"sanity\"\n\n/*\nFor a given object that has multiple fields, mark a field as `required` if a sibling has a particular value.\n\n```\ndefineType({\n name: 'ifAlphaAlsoBeta',\n type: 'object',\n fields: [\n defineField({\n name: 'alpha',\n type: 'string',\n options: {\n list: ['left', 'right'],\n layout: 'radio',\n direction: 'horizontal',\n },\n }),\n defineField({\n name: 'beta',\n type: 'string',\n placeholder: 'If alpha is “left”, I’m also required',\n validation: (rule) => rule.custom(requiredIfSiblingEq('alpha', 'left')),\n })\n ],\n})\n```\n\nIncidentally, context.path is technically Array<sanity.PathSegment>.\n\nThat shouldn't matter, but dealing with that and remapping siblingKey as a PathSegment could be a possible future enhancement.\n*/\n\nexport const requiredIfSiblingEq =\n (key: string, operand: string | number | null | Array<string | number | null>, message: string = \"Required if {key} equals {operand}.\") =>\n (value: unknown | undefined, context: ValidationContext) => {\n const siblingValue = getSibling(key, context)\n const operands = Array.isArray(operand) ? operand : [operand]\n if (!value && operands.includes(siblingValue)) {\n return message\n .replace(\"{key}\", key)\n .replace(\"{operand}\", operands.join(\", or \") ?? \"null\")\n .replace(\"{value}\", operands.join(\", or \") ?? \"null\") // backward compatibility\n .replace(\"{siblingValue}\", siblingValue)\n }\n return true\n }\n","import {getSibling} from './'\nimport {ValidationContext} from 'sanity'\n\nexport const requiredIfSiblingNeq = (\n key: string, \n operand: string | number | null | Array<string | number | null>, \n message: string = 'Required if {key} does not equal {operand}.'\n) =>\n (value: unknown | undefined, context: ValidationContext) => {\n const siblingValue = getSibling(key, context)\n const operands = Array.isArray(operand) ? operand : [operand]\n if(!value && !operands.includes(siblingValue)) {\n return message\n .replace('{key}', key)\n .replace('{operand}', operands.join(', or ') ?? 'null')\n .replace('{value}', operands.join(', or ') ?? 'null') // backward compatibility\n .replace('{siblingValue}', siblingValue)\n }\n return true\n }\n\n\n\n\n\n\n\n\n\n","import { ValidationContext } from \"sanity\"\n\nexport const getSibling = (key: string | number, context: ValidationContext) => {\n const path = context.path ? (context.path.slice(0, -1) as Array<string | number>) : []\n const sibling = [...path, key].reduce((acc: any, step: string | number | Record<\"_key\", string>) => {\n if (typeof step === \"string\" && acc.hasOwnProperty(step)) {\n return acc[step]\n } else if (typeof step === \"object\" && step.hasOwnProperty(\"_key\") && Array.isArray(acc)) {\n return acc.find((i) => i._key === step._key)\n } else {\n // should never arrive here\n console.error(\"sanity-advanced-validators: Unreachable point reached!\")\n return acc\n }\n }, context.document)\n return sibling\n}\n","export const regex =\n (pattern: RegExp, message: string = `“{value}” does not match the pattern {pattern}.`) =>\n (value: unknown) => {\n if (!value) {\n return true\n }\n const valueAsString = typeof value !== \"string\" ? value.toString() : value\n return pattern.test(valueAsString) ? true : message.replace(\"{value}\", valueAsString).replace(\"{pattern}\", pattern.toString())\n }\n"],"mappings":"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","names":["getImageDimensions","maxDepth","regex"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"package-name": "sanity-advanced-validators",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Advanced input validation tools for Sanity CMS.",
|
|
5
5
|
"author": "Eric_WVGG",
|
|
6
6
|
"license": "MIT",
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"dist"
|
|
22
22
|
],
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@sanity/asset-utils": "^2.
|
|
25
|
-
"sanity": "^
|
|
24
|
+
"@sanity/asset-utils": "^2.3.0",
|
|
25
|
+
"sanity": "^5.1.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"tsup": "^8.5.0",
|