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 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 { requiredIfSlugEq, requiredIfSiblingNeq, minDimensions, maxDimensions } from 'sanity-advanced-validators'
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> // possible slug or slugs you’re testing
417
- key?: string, // name of sibling if not "slug"
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> // possible slug or slugs you’re testing
466
- key?: string, // name of sibling if not "slug"
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
- **Custom error messages are highly recommended here.** Without the custom message above, the default response would be:
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 = (slug, slugKey = "slug", message = `This is a required field.`) => (value, context) => {
136
- var _a, _b;
137
- const slugs = typeof slug === "string" ? [slug] : slug;
138
- const slugValue = (_b = (_a = context.parent) == null ? void 0 : _a[slugKey]) == null ? void 0 : _b.current;
139
- if (!value && !!slugValue && slugs.includes(slugValue)) {
140
- return message.replace("{slugKey}", slugKey).replace("{operand}", slugs.join(", or ")).replace("{siblingSlugValue}", slugValue);
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 = (slug, slugKey = "slug", message = `This is a required field.`) => (value, context) => {
147
- var _a, _b;
148
- const slugs = typeof slug === "string" ? [slug] : slug;
149
- const slugValue = (_b = (_a = context.parent) == null ? void 0 : _a[slugKey]) == null ? void 0 : _b.current;
150
- if (!value && !slugs.includes(slugValue)) {
151
- return message.replace("{slugKey}", slugKey).replace("{operand}", slugs.join(", or ")).replace("{siblingSlugValue}", slugValue);
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/lib/getSibling.ts
179
- var import_lodash_es = require("lodash-es");
178
+ // src/getSibling.ts
180
179
  var getSibling = (key, context) => {
181
- if (!context.path) return void 0;
182
- const pathToParentObject = context.path.slice(0, -1);
183
- const sibling = (0, import_lodash_es.get)(context.document, [...pathToParentObject, key]);
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
 
@@ -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: (slug: Array<string> | string, slugKey?: string, message?: string) => (value: unknown | undefined, context: ValidationContext) => string | true;
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: (slug: Array<string> | string, slugKey?: string, message?: string) => (value: unknown | undefined, context: ValidationContext) => string | true;
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: (slug: Array<string> | string, slugKey?: string, message?: string) => (value: unknown | undefined, context: ValidationContext) => string | true;
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: (slug: Array<string> | string, slugKey?: string, message?: string) => (value: unknown | undefined, context: ValidationContext) => string | true;
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 = (slug, slugKey = "slug", message = `This is a required field.`) => (value, context) => {
98
- var _a, _b;
99
- const slugs = typeof slug === "string" ? [slug] : slug;
100
- const slugValue = (_b = (_a = context.parent) == null ? void 0 : _a[slugKey]) == null ? void 0 : _b.current;
101
- if (!value && !!slugValue && slugs.includes(slugValue)) {
102
- return message.replace("{slugKey}", slugKey).replace("{operand}", slugs.join(", or ")).replace("{siblingSlugValue}", slugValue);
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 = (slug, slugKey = "slug", message = `This is a required field.`) => (value, context) => {
109
- var _a, _b;
110
- const slugs = typeof slug === "string" ? [slug] : slug;
111
- const slugValue = (_b = (_a = context.parent) == null ? void 0 : _a[slugKey]) == null ? void 0 : _b.current;
112
- if (!value && !slugs.includes(slugValue)) {
113
- return message.replace("{slugKey}", slugKey).replace("{operand}", slugs.join(", or ")).replace("{siblingSlugValue}", slugValue);
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/lib/getSibling.ts
141
- import { get } from "lodash-es";
140
+ // src/getSibling.ts
142
141
  var getSibling = (key, context) => {
143
- if (!context.path) return void 0;
144
- const pathToParentObject = context.path.slice(0, -1);
145
- const sibling = get(context.document, [...pathToParentObject, key]);
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.6.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.2.1",
25
- "sanity": "^4.9.0"
24
+ "@sanity/asset-utils": "^2.3.0",
25
+ "sanity": "^5.1.0"
26
26
  },
27
27
  "devDependencies": {
28
28
  "tsup": "^8.5.0",