Default Description set by probot/settings

Overview

sanity-typed-schema-builder

Build Sanity schemas declaratively and get typescript types of schema values for free!

  • Typescript types for Sanity Values!
  • Get mock values for tests!
  • Get zod schemas for parsing values (most notably, date values into javascript Date)

Install

npm install sanity-typed-schema-builder

Usage

import { s } from "sanity-typed-schema-builder";

// Declare types in a familiar way
const fooType = s.document({
  name: "foo",
  fields: [
    {
      name: "foo",
      type: s.string(),
    },
    {
      name: "bar",
      type: s.array({ of: [s.boolean(), s.number({ readOnly: true })] }),
    },
    {
      name: "hello",
      optional: true,
      type: s.object({
        fields: [
          {
            name: "world",
            type: s.number(),
          },
        ],
      }),
    },
  ],
});

// Typescript Types!
type FooType = s.infer<typeof fooType>;

/**
 *  s.infer<typeof fooType> = {
 *    _createdAt: string;
 *    _id: string;
 *    _rev: string;
 *    _type: "foo";
 *    _updatedAt: string;
 *    bar: (boolean | number)[];
 *    foo: string;
 *    hello?: {
 *      world: number;
 *    };
 *  };
 **/

// Use @faker-js/faker to create mocks for tests!
import { faker } from "@faker-js/faker";

const fooMock = fooType.mock(faker);

// Use zod to parse untyped values (and transform values, note _createdAt & _updatedAt specifically)
const parsedFoo: s.output<typeof fooType> = fooType.parse(someInput);

/**
 *  s.output<typeof fooType> = {
 *    _createdAt: Date;
 *    _id: string;
 *    _rev: string;
 *    _type: "foo";
 *    _updatedAt: Date;
 *    bar: (boolean | number)[];
 *    foo: string;
 *    hello?: {
 *      world: number;
 *    };
 *  };
 **/

// Use schemas in Sanity
createSchema({
  name: "default",
  types: [fooType.schema()],
});

Notable Differences:

For all types, the properties provided are the same as the sanity schema types except for these specific differences:

type is removed

type is defined via the typed methods, so they aren't required directly

name, title, description, fieldset, & group are defined in fields

For all types except document and named objects, type, name, title, description, fieldset, & group are not defined in the type but in the fields. These aren't relevant specifically to the type, but rather in their relationship to the parent object or document:

s.object({
  fields: [
    {
      // All of these are defined here in the field
      name: "foo",
      title: "Foo",
      description: "This is foo",
      // Not inside of the type itself
      type: s.number({ hidden: true }),
    },
  ],
});

Rule.required() replaced with optional boolean in fields

For types with fields (document, object, objectNamed, file, & image), the fields can be marked as optional. This will both not set the validation: (Rule) => Rule.required() and type the inferred type.

s.object({
  fields: [
    {
      name: "foo",
      type: s.number(),
    },
    {
      name: "bar",
      optional: true,
      type: s.number(),
    },
  ],
});

type Value = s.infer<typeof type>;

/**
 * s.infer<typeof type> = {
 *   foo: number;
 *   bar?: number;
 * }
 */

const parsedValue: s.output<typeof type> = type.parse(someInput);

/**
 * s.output<typeof type> = {
 *   foo: number;
 *   bar?: number;
 * }
 */

const schema = type.schema();

/**
 * const schema = {
 *   type: "object",
 *   fields: [
 *     {
 *       name: "foo",
 *       type: "number",
 *       validation: (Rule) => Rule.validation(),
 *     },
 *     {
 *       name: "bar",
 *       type: "number",
 *     },
 *   ],
 * };
 */

preview is typed

TODO

Custom mock

Our mocks are using Faker under the hood and give default mocks. These mocks are configurable.

const type = s.string({
  mock: (faker: Faker, path: string) => faker.name.firstName(),
});

const mock = type.mock(); // "Katelynn"

Custom zod

Our parsing is using Zod under the hood and has default parsing. These zod schemas are configurable.

const type = s.string({
  zod: (zod) => zod.transform((value) => value.length),
});

type Value = s.infer<typeof type>; // This is still a string.

const parsedValue: s.output<typeof type> = type.parse("hello"); // This is a number, specifically `5` in this case

Types

Array

const type = array({
  // Any of the same properties as a normal sanity schema
  // https://www.sanity.io/docs/array-type

  // `of` uses other types directly:
  of: [s.boolean(), s.datetime()],

  // length?: number    sets both zod and validation: (Rule) => Rule.length(length)
  // max?: number       sets both zod and validation: (Rule) => Rule.max(max)
  // min?: number       sets both zod and validation: (Rule) => Rule.min(min)
  // nonempty?: boolean sets both zod and validation: (Rule) => Rule.min(1)
});

type Value = s.infer<typeof type>;

/**
 * s.infer<typeof type> = (boolean | string)[];
 */

const parsedValue: s.output<typeof type> = type.parse(someInput);

/**
 * Notice the recursive transform, particularly with `datetime` becoming a `Date`
 *
 * s.output<typeof type> = (boolean | Date)[];
 */

const schema = type.schema();

/**
 * const schema = {
 *   type: "array",
 *   of: [{ type: "boolean" }, { type: "datetime" }],
 *   ...
 * };
 */

Block

const type = block({
  // Any of the same properties as a normal sanity schema
  // https://www.sanity.io/docs/block-type
});

type Value = s.infer<typeof type>;

/**
 * s.infer<typeof type> = PortableTextBlock;
 */

const parsedValue: s.output<typeof type> = type.parse(someInput);

/**
 * s.output<typeof type> = PortableTextBlock;
 */

const schema = type.schema();

/**
 * const schema = {
 *   type: "block",
 *   ...
 * };
 */

Boolean

const type = boolean({
  // Any of the same properties as a normal sanity schema
  // https://www.sanity.io/docs/boolean-type
});

type Value = s.infer<typeof type>;

/**
 * s.infer<typeof type> = boolean;
 */

const parsedValue: s.output<typeof type> = type.parse(someInput);

/**
 * s.output<typeof type> = boolean;
 */

const schema = type.schema();

/**
 * const schema = {
 *   type: "boolean",
 *   ...
 * };
 */

Date

const type = date({
  // Any of the same properties as a normal sanity schema
  // https://www.sanity.io/docs/date-type
});

type Value = s.infer<typeof type>;

/**
 * s.infer<typeof type> = string;
 */

const parsedValue: s.output<typeof type> = type.parse(someInput);

/**
 * s.output<typeof type> = string;
 */

const schema = type.schema();

/**
 * const schema = {
 *   type: "date",
 *   ...
 * };
 */

Datetime

const type = datetime({
  // Any of the same properties as a normal sanity schema
  // https://www.sanity.io/docs/datetime-type
  // max?: string sets both zod and validation: (Rule) => Rule.max(max)
  // min?: string sets both zod and validation: (Rule) => Rule.min(min)
});

type Value = s.infer<typeof type>;

/**
 * s.infer<typeof type> = string;
 */

const parsedValue: s.output<typeof type> = type.parse(someInput);

/**
 * s.output<typeof type> = Date;
 */

const schema = type.schema();

/**
 * const schema = {
 *   type: "datetime",
 *   ...
 * };
 */

Document

const type = document({
  // Any of the same properties as a normal sanity schema
  // https://www.sanity.io/docs/document-type
  name: "foo",
  fields: [
    {
      name: "foo",
      type: s.number(),
    },
    {
      name: "bar",
      optional: true,
      type: s.number(),
    },
  ],
});

type Value = s.infer<typeof type>;

/**
 * s.infer<typeof type> = {
 *   _createdAt: string;
 *   _id: string;
 *   _rev: string;
 *   _type: "foo";
 *   _updatedAt: string;
 *   foo: number;
 *   bar?: number;
 * };
 */

const parsedValue: s.output<typeof type> = type.parse(someInput);

/**
 * s.output<typeof type> = {
 *   _createdAt: Date;
 *   _id: string;
 *   _rev: string;
 *   _type: "foo";
 *   _updatedAt: Date;
 *   foo: number;
 *   bar?: number;
 * };
 */

const schema = type.schema();

/**
 * const schema = {
 *   name: "foo",
 *   type: "document",
 *   fields: [...],
 *   ...
 * };
 */

File

const type = file({
  // Any of the same properties as a normal sanity schema
  // https://www.sanity.io/docs/file-type
  fields: [
    {
      name: "foo",
      type: s.number(),
    },
    {
      name: "bar",
      optional: true,
      type: s.number(),
    },
  ],
});

type Value = s.infer<typeof type>;

/**
 * s.infer<typeof type> = {
 *   _type: "file";
 *   asset: {
 *     _type: "reference";
 *     _ref: string;
 *   };
 *   foo: number;
 *   bar?: number;
 * };
 */

const parsedValue: s.output<typeof type> = type.parse(someInput);

/**
 * s.output<typeof type> = {
 *   _type: "file";
 *   asset: {
 *     _type: "reference";
 *     _ref: string;
 *   };
 *   foo: number;
 *   bar?: number;
 * };
 */

const schema = type.schema();

/**
 * const schema = {
 *   name: "foo",
 *   type: "file",
 *   fields: [...],
 *   ...
 * };
 */

Geopoint

const type = geopoint({
  // Any of the same properties as a normal sanity schema
  // https://www.sanity.io/docs/geopoint-type
});

type Value = s.infer<typeof type>;

/**
 * s.infer<typeof type> = {
 *   _type: "geopoint";
 *   alt: number;
 *   lat: number;
 *   lng: number;
 * };
 */

const parsedValue: s.output<typeof type> = type.parse(someInput);

/**
 * s.output<typeof type> = {
 *   _type: "geopoint";
 *   alt: number;
 *   lat: number;
 *   lng: number;
 * };
 */

const schema = type.schema();

/**
 * const schema = {
 *   type: "geopoint",
 *   ...
 * };
 */

Image

const type = image({
  // Any of the same properties as a normal sanity schema
  // https://www.sanity.io/docs/image-type
  // hotspot?: true adds the `crop` & `hotspot` to the value types, mocks, and parsing
  fields: [
    {
      name: "foo",
      type: s.number(),
    },
    {
      name: "bar",
      optional: true,
      type: s.number(),
    },
  ],
});

type Value = s.infer<typeof type>;

/**
 * s.infer<typeof type> = {
 *   _type: "image";
 *   asset: {
 *     _type: "reference";
 *     _ref: string;
 *   };
 *   foo: number;
 *   bar?: number;
 * };
 */

const parsedValue: s.output<typeof type> = type.parse(someInput);

/**
 * s.output<typeof type> = {
 *   _type: "image";
 *   asset: {
 *     _type: "reference";
 *     _ref: string;
 *   };
 *   foo: number;
 *   bar?: number;
 * };
 */

const schema = type.schema();

/**
 * const schema = {
 *   name: "foo",
 *   type: "image",
 *   fields: [...],
 *   ...
 * };
 */

Number

const type = number({
  // Any of the same properties as a normal sanity schema
  // https://www.sanity.io/docs/number-type
  // greaterThan?: number sets both zod and validation: (Rule) => Rule.greaterThan(greaterThan)
  // integer?: boolean    sets both zod and validation: (Rule) => Rule.integer()
  // lessThan?: number    sets both zod and validation: (Rule) => Rule.lessThan(lessThan)
  // max?: number         sets both zod and validation: (Rule) => Rule.max(max)
  // min?: number         sets both zod and validation: (Rule) => Rule.min(min)
  // negative?: boolean   sets both zod and validation: (Rule) => Rule.negative()
  // positive?: boolean   sets both zod and validation: (Rule) => Rule.positive()
  // precision?: number   sets both zod and validation: (Rule) => Rule.precision(precision)
});

type Value = s.infer<typeof type>;

/**
 * s.infer<typeof type> = number;
 */

const parsedValue: s.output<typeof type> = type.parse(someInput);

/**
 * s.output<typeof type> = number;
 */

const schema = type.schema();

/**
 * const schema = {
 *   type: "number",
 *   ...
 * };
 */

Object

const type = object({
  // Any of the same properties as a normal sanity schema
  // https://www.sanity.io/docs/object-type
  fields: [
    {
      name: "foo",
      type: s.number(),
    },
    {
      name: "bar",
      optional: true,
      type: s.number(),
    },
  ],
});

type Value = s.infer<typeof type>;

/**
 * s.infer<typeof type> = {
 *   foo: number;
 *   bar?: number;
 * };
 */

const parsedValue: s.output<typeof type> = type.parse(someInput);

/**
 * s.output<typeof type> = {
 *   foo: number;
 *   bar?: number;
 * };
 */

const schema = type.schema();

/**
 * const schema = {
 *   name: "foo",
 *   type: "object",
 *   fields: [...],
 *   ...
 * };
 */

Object (Named)

This is separate from object because, when objects are named in sanity, there are significant differences:

  • The value has a _type field equal to the object's name.
  • They can be used directly in schemas (like any other schema).
  • They can also be registered as a top level object and simply referenced by type within another schema.
const type = objectNamed({
  // Any of the same properties as a normal sanity schema
  // https://www.sanity.io/docs/object-type
  name: "aNamedObject",
  fields: [
    {
      name: "foo",
      type: s.number(),
    },
    {
      name: "bar",
      optional: true,
      type: s.number(),
    },
  ],
});

type Value = s.infer<typeof type>;

/**
 * s.infer<typeof type> = {
 *   _type: "aNamedObject";
 *   foo: number;
 *   bar?: number;
 * };
 */

const parsedValue: s.output<typeof type> = type.parse(someInput);

/**
 * s.output<typeof type> = {
 *   _type: "aNamedObject";
 *   foo: number;
 *   bar?: number;
 * };
 */

const schema = type.schema();

/**
 * const schema = {
 *   name: "foo",
 *   type: "object",
 *   fields: [...],
 *   ...
 * };
 */
// Use `.ref()` to reference it in another schema.
const someOtherType = array({ of: [type.ref()] });

// The reference value is used directly.
type SomeOtherValue = s.infer<typeof someOtherType>;

/**
 * type SomeOtherValue = [{
 *   _type: "aNamedObject";
 *   foo: number;
 *   bar?: number;
 * }];
 */

// The schema is made within the referencing schema
const someOtherTypeSchema = someOtherType.schema();

/**
 * const someOtherTypeSchema = {
 *   type: "array",
 *   of: [{ type: "" }],
 *   ...
 * };
 */

createSchema({
  name: "default",
  types: [type.schema(), someOtherType.schema()],
});

Reference

const type = reference({
  // Any of the same properties as a normal sanity schema
  // https://www.sanity.io/docs/reference-type
  to: [someDocumentType, someOtherDocumentType],
});

type Value = s.infer<typeof type>;

/**
 * s.infer<typeof type> = {
 *   _ref: string;
 *   _type: "reference";
 *   _weak?: boolean;
 * };
 */

const parsedValue: s.output<typeof type> = type.parse(someInput);

/**
 * s.output<typeof type> = {
 *   _ref: string;
 *   _type: "reference";
 *   _weak?: boolean;
 * };
 */

const schema = type.schema();

/**
 * const schema = {
 *   type: "reference",
 *   to: [...],
 *   ...
 * };
 */

Slug

const type = slug({
  // Any of the same properties as a normal sanity schema
  // https://www.sanity.io/docs/slug-type
});

type Value = s.infer<typeof type>;

/**
 * s.infer<typeof type> = {
 *   _type: "slug";
 *   current: string;
 * };
 */

const parsedValue: s.output<typeof type> = type.parse(someInput);

/**
 * s.output<typeof type> = string;
 */

const schema = type.schema();

/**
 * const schema = {
 *   type: "slug",
 *   ...
 * };
 */

String

const type = string({
  // Any of the same properties as a normal sanity schema
  // https://www.sanity.io/docs/string-type
  // length?: number sets both zod and validation: (Rule) => Rule.length(length)
  // max?: number    sets both zod and validation: (Rule) => Rule.max(max)
  // min?: number    sets both zod and validation: (Rule) => Rule.min(min)
  // regex?: Regex   sets both zod and validation: (Rule) => Rule.regex(regex)
});

type Value = s.infer<typeof type>;

/**
 * s.infer<typeof type> = string;
 */

const parsedValue: s.output<typeof type> = type.parse(someInput);

/**
 * s.output<typeof type> = string;
 */

const schema = type.schema();

/**
 * const schema = {
 *   type: "string",
 *   ...
 * };
 */

Text

const type = text({
  // Any of the same properties as a normal sanity schema
  // https://www.sanity.io/docs/text-type
  // length?: number sets both zod and validation: (Rule) => Rule.length(length)
  // max?: number    sets both zod and validation: (Rule) => Rule.max(max)
  // min?: number    sets both zod and validation: (Rule) => Rule.min(min)
  // regex?: Regex   sets both zod and validation: (Rule) => Rule.regex(regex)
});

type Value = s.infer<typeof type>;

/**
 * s.infer<typeof type> = string;
 */

const parsedValue: s.output<typeof type> = type.parse(someInput);

/**
 * s.output<typeof type> = string;
 */

const schema = type.schema();

/**
 * const schema = {
 *   type: "text",
 *   ...
 * };
 */

URL

const type = url({
  // Any of the same properties as a normal sanity schema
  // https://www.sanity.io/docs/url-type
});

type Value = s.infer<typeof type>;

/**
 * s.infer<typeof type> = string;
 */

const parsedValue: s.output<typeof type> = type.parse(someInput);

/**
 * s.output<typeof type> = string;
 */

const schema = type.schema();

/**
 * const schema = {
 *   type: "url",
 *   ...
 * };
 */
Comments
  • Fields on referenced documents not showing

    Fields on referenced documents not showing

    I'm trying to access fields on an array of referenced documents, but only the baked in reference properties show, not any of my fields.

    Is there a proper way to consume a referenced document?

    Here is a snippet and codesandbox link:

    Code snippet ```ts import { s } from "sanity-typed-schema-builder";

    const testReference = s.document({ name: "testReference", title: "Test Reference", fields: [ { name: "title", title: "Title", type: s.string(), }, { name: "description", title: "Description", type: s.text(), } ] });

    export const testDoc = s.document({ name: "testDoc", fields: [ { name: "testArray", title: "test Array", type: s.array({ of: [ s.reference({ to: [testReference] }) ] }) } ] });

    export type TestType = s.infer;

    const test = {} as TestType;

    // no Title found :( test.testArray[0].title;

    <details>
    opened by mckelveygreg 18
  • array() of blocks() are readonly but PortableText requires a mutable value.

    array() of blocks() are readonly but PortableText requires a mutable value.

    Currently you have to go through some hoops to not get errors.

    type DeepWriteable<T> = { -readonly [P in keyof T]: DeepWriteable<T[P]> };
    return (
        <PortableText value={value as DeepWriteable<typeof value>} components={} />
    )
    

    Am i doing something wrong, or could we maybe use the readOnly prop in the schema to make these mutable in the resulting types?

    released 
    opened by miklschmidt 5
  • build(deps-dev): bump eslint from 8.19.0 to 8.20.0

    build(deps-dev): bump eslint from 8.19.0 to 8.20.0

    Bumps eslint from 8.19.0 to 8.20.0.

    Release notes

    Sourced from eslint's releases.

    v8.20.0

    Features

    Bug Fixes

    • 30be0ed fix: no-warning-comments rule escapes special RegEx characters in terms (#16090) (Lachlan Hunt)
    • bfe5e88 fix: ignore spacing before ] and } in comma-spacing (#16113) (Milos Djermanovic)

    Documentation

    • 845c4f4 docs: Add website team details (#16115) (Nicholas C. Zakas)
    • 5a0dfdb docs: Link to blog post in no-constant-binary-expression (#16112) (Jordan Eldredge)
    • bc692a9 docs: remove install command (#16084) (Strek)
    • 49ca3f0 docs: don't show toc when content not found (#16095) (Amaresh S M)
    • ba19e3f docs: enhance 404 page UI (#16097) (Amaresh S M)
    • a75d3b4 docs: remove unused meta.docs.category field in working-with-rules page (#16109) (Brandon Scott)
    • cdc0206 docs: add formatters page edit link (#16094) (Amaresh S M)
    • 4d1ed22 docs: preselect default theme (#16098) (Strek)
    • 4b79612 docs: add missing correct/incorrect containers (#16087) (Milos Djermanovic)
    • 09f6acb docs: fix UI bug on rules index and details pages (#16082) (Deepshika S)
    • f5db264 docs: remove remaining duplicate rule descriptions (#16093) (Milos Djermanovic)
    • 32a6b2a docs: Add scroll behaviour smooth (#16056) (Amaresh S M)

    Chores

    • bbf8df4 chore: Mark autogenerated release blog post as draft (#16130) (Nicholas C. Zakas)
    • eee4306 chore: update internal lint dependencies (#16088) (Bryan Mishkin)
    • 9615a42 chore: update formatter examples template to avoid markdown lint error (#16085) (Milos Djermanovic)
    • 62541ed chore: fix markdown linting error (#16083) (唯然)
    Changelog

    Sourced from eslint's changelog.

    v8.20.0 - July 16, 2022

    • bbf8df4 chore: Mark autogenerated release blog post as draft (#16130) (Nicholas C. Zakas)
    • 845c4f4 docs: Add website team details (#16115) (Nicholas C. Zakas)
    • 5a0dfdb docs: Link to blog post in no-constant-binary-expression (#16112) (Jordan Eldredge)
    • bc692a9 docs: remove install command (#16084) (Strek)
    • 30be0ed fix: no-warning-comments rule escapes special RegEx characters in terms (#16090) (Lachlan Hunt)
    • ca83178 feat: catch preprocess errors (#16105) (JounQin)
    • 49ca3f0 docs: don't show toc when content not found (#16095) (Amaresh S M)
    • ba19e3f docs: enhance 404 page UI (#16097) (Amaresh S M)
    • bfe5e88 fix: ignore spacing before ] and } in comma-spacing (#16113) (Milos Djermanovic)
    • a75d3b4 docs: remove unused meta.docs.category field in working-with-rules page (#16109) (Brandon Scott)
    • cdc0206 docs: add formatters page edit link (#16094) (Amaresh S M)
    • 4d1ed22 docs: preselect default theme (#16098) (Strek)
    • 4b79612 docs: add missing correct/incorrect containers (#16087) (Milos Djermanovic)
    • 09f6acb docs: fix UI bug on rules index and details pages (#16082) (Deepshika S)
    • f5db264 docs: remove remaining duplicate rule descriptions (#16093) (Milos Djermanovic)
    • 32a6b2a docs: Add scroll behaviour smooth (#16056) (Amaresh S M)
    • eee4306 chore: update internal lint dependencies (#16088) (Bryan Mishkin)
    • 9615a42 chore: update formatter examples template to avoid markdown lint error (#16085) (Milos Djermanovic)
    • 62541ed chore: fix markdown linting error (#16083) (唯然)
    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    automerge dependabot released 
    opened by dependabot[bot] 3
  • fix(types): document _id is not guaranteed to be a UUID

    fix(types): document _id is not guaranteed to be a UUID

    There are 2 cases where _id is not a valid UUID, which causes parsing to fail, despite a valid document:

    1. Drafts. (draft.some-uuid)
    2. String id set via the structure builder:
    S.document()
    .schemaType('header')
    .title('Site Header')
    .documentId('header')
    .views([
    	S.view.form().icon(PencilSquareIcon),
    	S.view
    		.component(iframePreview)
    		.options({ previewURL })
    		.icon(EyeIcon)
    		.title('Web Preview'),
    ]),
    

    This PR replaces the UUID type for _id on documents with a regular string.

    released 
    opened by miklschmidt 2
  • Type 'unknown' with circular references

    Type 'unknown' with circular references

    Hi!

    I just ran into this issue, where I have a circular reference (see image), which works fine in the studio, but the schema builder gives my type "unknown" for all the schemas in the circle. Break the circle, and all the types work fine. Just wondering if anyone has a solution to this?

    Screen Shot 2022-07-20 at 11 46 56 AM
    opened by EilifAkerjordet 2
  • fix(types): hotspot and crop can be undefined on images

    fix(types): hotspot and crop can be undefined on images

    The current types enforce that hotspot and crop are always present on images when enabled, but hotspot and crop are optional in sanity when enabled. This PR makes hotspot and crop optional (breaking change since one now needs to check if they're undefined in the application code). This makes images work seamlessly with @sanity/image-url, even when new uploaded images haven't had a crop / hotspot set.

    released 
    opened by miklschmidt 1
  • build(deps): bump actions/checkout from 2 to 3

    build(deps): bump actions/checkout from 2 to 3

    Bumps actions/checkout from 2 to 3.

    Release notes

    Sourced from actions/checkout's releases.

    v3.0.0

    • Updated to the node16 runtime by default
      • This requires a minimum Actions Runner version of v2.285.0 to run, which is by default available in GHES 3.4 or later.

    v2.4.2

    What's Changed

    Full Changelog: https://github.com/actions/checkout/compare/v2...v2.4.2

    v2.4.1

    • Fixed an issue where checkout failed to run in container jobs due to the new git setting safe.directory

    v2.4.0

    • Convert SSH URLs like org-<ORG_ID>@github.com: to https://github.com/ - pr

    v2.3.5

    Update dependencies

    v2.3.4

    v2.3.3

    v2.3.2

    Add Third Party License Information to Dist Files

    v2.3.1

    Fix default branch resolution for .wiki and when using SSH

    v2.3.0

    Fallback to the default branch

    v2.2.0

    Fetch all history for all tags and branches when fetch-depth=0

    v2.1.1

    Changes to support GHES (here and here)

    v2.1.0

    ... (truncated)

    Changelog

    Sourced from actions/checkout's changelog.

    Changelog

    v3.0.2

    v3.0.1

    v3.0.0

    v2.3.1

    v2.3.0

    v2.2.0

    v2.1.1

    • Changes to support GHES (here and here)

    v2.1.0

    v2.0.0

    v2 (beta)

    • Improved fetch performance

    ... (truncated)

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    automerge dependabot released 
    opened by dependabot[bot] 1
  • build(deps): bump @sanity/types from 3.0.0-dev-preview.11 to 3.0.0-v3-pte.17

    build(deps): bump @sanity/types from 3.0.0-dev-preview.11 to 3.0.0-v3-pte.17

    Bumps @sanity/types from 3.0.0-dev-preview.11 to 3.0.0-v3-pte.17.

    Release notes

    Sourced from @​sanity/types's releases.

    v3.0.0-dev-preview.12

    Changes

    • New studios gets bootstrapped with deploy and deploy-graphql scripts (mapping to sanity deploy/sanity graphql deploy)
    • The default document node resolver for desk structures now gets the ConfigContext passed as the second argument, matching the regular structure
    • Added and exposed new assertion methods:
      • isDocumentSchemaType
      • isArrayOfObjectsSchemaType
      • isArrayOfPrimitivesSchemaType
      • isObjectInputProps
      • isStringInputProps
      • isNumberInputProps
      • isBooleanInputProps
      • isArrayOfObjectsInputProps
      • isArrayOfPrimitivesInputProps
    • BREAKING CHANGE: The history store no longer exposes the historyEventsFor() method
    • BREAKING CHANGE: The @sanity/transaction-collator module is now deprecated and will no longer be maintained
    • BREAKING CHANGE: Document nodes in structure now requires you to define a schemaType

    🐛 Notable bugfixes

    • Fixes issue where studio requests would not be tagged correctly
    • Fixes issue where schema type errors would be caught by the global error handler instead of the specific schema error boundary
    • Fixes issue where deployed studios would crash when attempting to upload images/files
    • Fixes issue where studio might crash when attempting to preview a file as if it was an image
    • Fixes issue where building/deploying a studio would not work if the configuration file had .tsx/.jsx extension
    • Fixes issue where the global error handler would be used for known errors
    • Fixes issue where the wrong order would be used when resolving input components, leading to slug input without a generate button, array inputs without drag handles and a few other cases
    • Fixes a few warnings being printed to the console when publishing
    • Fixes a few issues with the typescript definitions for schema declarations

    📓 Full changelog

    Author Message Commit
    Espen Hovlandsdal fix(server): add missing esbuild peer dependency e22cebf6e
    Espen Hovlandsdal fix(form): inline attr-accept dependency 097e5efd6
    Espen Hovlandsdal fix(types): check asset id prefix when determining if object is image cbbde1ca8
    Espen Hovlandsdal fix(types): add validation on field definitions a312e2ebb
    Espen Hovlandsdal fix(types): add missing placeholder property on date/datetime schema definitions 245201fef
    Espen Hovlandsdal fix(types): allow field references in validation min/max/gt/lt rules c5de07b22
    Espen Hovlandsdal fix(types): add schema options for cross-dataset references c00f5c550
    Espen Hovlandsdal chore(test-studio): migrate schema files to typescript 8a759793d
    Marius Lundgård refactor: defer global error listener to let error boundary subscribe 4e4acc9ea
    Espen Hovlandsdal fix(server): resolve tsx/jsx studio config when building 9d884b5bf
    Espen Hovlandsdal chore(test-studio): migrate schema files to typescript 34120ef5f
    Espen Hovlandsdal refactor(hooks): use type-only import for client 7915c91b3
    Espen Hovlandsdal fix(studio): prevent global error handler from catching known errors d80f1e154
    Espen Hovlandsdal refactor(errors): only expose subscribe() method on global error channel b2b742d92
    Espen Hovlandsdal refactor(errors): improve typings for global error handler 375095cbc
    Espen Hovlandsdal feat(cli): add deploy + deploy-graphql scripts to package.json 9058bf6ac
    Espen Hovlandsdal refactor(portable-text-editor): improve typings 268dd1529

    ... (truncated)

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    automerge dependabot 
    opened by dependabot[bot] 1
  • build(deps-dev): bump @typescript-eslint/parser from 5.32.0 to 5.33.0

    build(deps-dev): bump @typescript-eslint/parser from 5.32.0 to 5.33.0

    Bumps @typescript-eslint/parser from 5.32.0 to 5.33.0.

    Release notes

    Sourced from @​typescript-eslint/parser's releases.

    v5.33.0

    5.33.0 (2022-08-08)

    Bug Fixes

    • eslint-plugin: [no-extra-parens] handle await with type assertion (#5428) (e03826f)
    • website: add explicit frontmatter description to rule docs (#5429) (63cba5f)

    Features

    • eslint-plugin: [member-ordering] support static blocks (#5417) (5983e5a)
    • eslint-plugin: [prefer-as-const] adds support for class properties (#5413) (d2394f8)
    Changelog

    Sourced from @​typescript-eslint/parser's changelog.

    5.33.0 (2022-08-08)

    Note: Version bump only for package @​typescript-eslint/parser

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    automerge dependabot released 
    opened by dependabot[bot] 1
  • build(deps-dev): bump eslint-plugin-jest from 26.7.0 to 26.8.0

    build(deps-dev): bump eslint-plugin-jest from 26.7.0 to 26.8.0

    Bumps eslint-plugin-jest from 26.7.0 to 26.8.0.

    Release notes

    Sourced from eslint-plugin-jest's releases.

    v26.8.0

    26.8.0 (2022-08-07)

    Features

    Changelog

    Sourced from eslint-plugin-jest's changelog.

    26.8.0 (2022-08-07)

    Features

    Commits
    • d1ee640 chore(release): 26.8.0 [skip ci]
    • aa4be21 feat: resolve expect based on scope (#1173)
    • baa76cf chore(deps): lock file maintenance
    • cf591ff chore: sort package.json (#1181)
    • 26e2791 chore: remove eslint-plugin-eslint-config as it doesn't work with ESLint 8 ...
    • See full diff in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    automerge dependabot released 
    opened by dependabot[bot] 1
  • build(deps-dev): bump @typescript-eslint/eslint-plugin from 5.31.0 to 5.32.0

    build(deps-dev): bump @typescript-eslint/eslint-plugin from 5.31.0 to 5.32.0

    Bumps @typescript-eslint/eslint-plugin from 5.31.0 to 5.32.0.

    Release notes

    Sourced from @​typescript-eslint/eslint-plugin's releases.

    v5.32.0

    5.32.0 (2022-08-01)

    Features

    • eslint-plugin: [no-use-before-define] add "allowNamedExports" option (#5397) (ad412cd)
    Changelog

    Sourced from @​typescript-eslint/eslint-plugin's changelog.

    5.32.0 (2022-08-01)

    Features

    • eslint-plugin: [no-use-before-define] add "allowNamedExports" option (#5397) (ad412cd)
    Commits
    • 17dcf27 chore: publish v5.32.0
    • ad412cd feat(eslint-plugin): [no-use-before-define] add "allowNamedExports" option (#...
    • ad26b74 docs(eslint-plugin): typo in member-ordering rule documentation (#5394)
    • See full diff in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    automerge dependabot released 
    opened by dependabot[bot] 1
  • Implement namedObjectArray using discriminatedUnion

    Implement namedObjectArray using discriminatedUnion

    I added namedObjectArray using zod's discriminatedUnion, primarily for better error reporting when using a "page builder" array containing multiple different named objects, which i can only assume is fairly common practice in a CMS. At least we use it on all our pages, to allow editors to build pages visually via a live preview.

    with namedObjectArray instead of array you get super concise errors pointing exactly to the problem, instead of thousands of lines (which grow with the amount of page "sections" you have in your array) which are impossible to reason about.

    Hopefully it's useful to others, at least we can't really function without it :)

    opened by miklschmidt 9
  • How do we add validation?

    How do we add validation?

    Hello,

    I am unsure if I may be missing something, but it seems the validation property is not a valid type. I see we can use Zod, but that seems to apply only for transformation, not validation.

    Is there a way to use validation?

    Thanks

    opened by bawahakim 1
  • How to attach a preview component?

    How to attach a preview component?

    Hello!

    Thank you so much for this plugin!

    I'm having some trouble with attaching a preview component to my objectNamed. In my old js code I just do it like this:

    preview: {
      select: {
        title: "title",
        image: "image",
      },
      component: Preview,
    },
    

    but the preview.component key is not valid to use.

    Cheers

    opened by benjick 2
  • Block annotations error: `Expected element to have a _type property`

    Block annotations error: `Expected element to have a _type property`

    I'm attempting to do some pretty complicated block annotations, but this seems to be in the unknown typed portion of the library.

    Are there different rules that apply here? I'm having to spread s.<type> instead of using the normal type: s.<type> syntax.

    It was working ok, until I started using a custom input that doesn't seem to like the array that I'm updating?

    I'm having a hard time figuring out to make a codesandbox reproduction for this as well. Not sure how to setup sanity in something like that.

    TLDR;

    • looking for tips for custom annotations
    • looking for sanity codesandbox / stackblitz templates
    opened by mckelveygreg 0
  • Confusing resolved names

    Confusing resolved names

    As @mckelveygreg made clear in #158, some things about "resolve" are unclear:

    • s.resolved<...> should be the type but with references resolved. Right now it's both parsed AND resolved. These should be two separate types.
    • docType.resolve(mock) doesn't describe that it's for mocks, so it implies it does something you'd want in application code, which is untrue.
    • docType.resolve and docType.parse should be independent. Resolving also parses, which is unexpected. We should be able to do both to the same doc, but it's unclear how this API should go.

    This was a consequence of the main use case I made this library for, which is not everyone's use case:

    • I query each document independently and fully. No expanded references, no projections, etc. Since I cache and traverse through application logic rather than in groq's syntax, none of this is an issue to me.
    • Parsing everything right after querying is easy and non-conflicing with any types.
    • Mocking for tests is easy, resolving the types there is mainly because my application logic does join these together and I'd like to have that in my tests.

    However we go about fixing this, there's definitely breaking changes (which is fine). I think making s.resolved<...> the same as s.infer<...>, except references are the type of the resolved document should be easy.

    The bigger issue is parsing. Parsing expects the value of the doc, and it essentially needs to handle a doc that has expanded references as well (and return the correct types). Expanded references are only one thing that a query can do that's "non-standard", which starts opening the door into parsing any valid query. Doing the work for this specific use case will likely cover a lot of use cases, but ultimately end up opening the door into individually solving the various groq query use cases.

    Having a query builder that utilizes these types will get us type safe queries, typed outputs from those queries, and a parser that traverses all the way through to the query outputs. This will make the "typing docs with resolved references" an irrelevant problem: if we can type our queries, we'll type whichever references we happen to resolve, along with whatever else we want to do in our groq queries.

    My big issue with this is groq is not small. Typing docs was relatively straightforward and not fragile, creating a typed query builder for everything groq can do is not going to easy or straightforward, will grow scope massively, and be prone to bugs.

    opened by saiichihashimoto 1
Releases(v1.15.11)
Owner
Saiichi Shayan Hashimoto
Saiichi Shayan Hashimoto
A basic USDZ file (Pixar Universal Scene Description) loader for ThreeJS

Three USDZ Loader A basic USDZ (binary Universal Scene Description) reader for Three.js The plugins supports animation as well as loading multiple USD

Pierre-Olivier NAHOUM 37 Dec 13, 2022
Create Bootstrap 5 Modal Box using JavaScript with custom title, description, button labels and custom YES button callback

Dynamic BS5 Modal Box Create Bootstrap 5 Modal Box using JavaScript with custom title, description, button labels and custom YES button callback Insta

null 5 Oct 23, 2022
vite-react-typescript with eslint and prettier predefined settings

Vite + React + Typescript + Eslint + Prettier A starter for React with Typescript with the fast Vite and all static code testing with Eslint and forma

The Sword Breaker 315 Dec 30, 2022
A Kernel Package that adds a tab to Discord settings where you can add and arrange custom code snippets.

Code Snippets A Kernel package (specifically for Discord) that adds a tab in settings where you can add and manage code snippets. Requires: https://gi

SwishyPlugs 6 Dec 14, 2022
Plugin for the Steam Deck, to adjust color settings, like saturation or gamma

vibrantDeck A Steam Deck plugin (for Decky Loader) to adjust screen saturation / vibrancy. Build instrutions Clone the repository to use as an example

libvibrant 48 Jan 8, 2023
Small js library to animate some writing effect through a list of strings. It also supports settings for typo errors, to make it more human likely.

Write and Delete Small js library to animate some writing effect through a list of strings. It also supports settings for typo errors, to make it more

fabs 2 Nov 15, 2022
NoExGen is a node.js express application generator with modern folder structure, namespace/project mapping and much more! It contains preconfigured Settings and Routing files, ready to be used in any project.

Installation $ npm install -g noexgen Quick Start You can use Node Package Execution to create your node-express application as shown below: Create th

Souvik Sen 7 Oct 8, 2022
Use plain functions as modifiers. Polyfill for RFC: 757 | Default Modifier Manager

Use plain functions as modifiers. Polyfill for RFC: 757 | Default Modifier Manager

null 7 Jan 14, 2022
This is an unofficial front end for Hacker News, reminiscent of the Windows XP era Outlook email client on a Windows XP default desktop

Hacker XP Hacker News styled as the Windows XP Outlook email client. Try out Hacker XP here! Description This is an unofficial front end for Hacker Ne

null 19 Jul 12, 2022
Replaces the default Strapi WYSIWYG editor with a customized build of CKEditor 5 html editor packed with useful plugins.

CKEditor 5 for Strapi Replaces the default Strapi WYSIWYG editor with a customized build of CKEditor 5 packed with useful plugins. ?? Get Started Feat

null 39 Jan 2, 2023
Custom alert box using javaScript and css. This plugin will provide the functionality to customize the default JavaScript alert box.

customAlertBoxPlugin Custom Alert Box Plugin Using JavaScript and CSS Author: Suraj Aswal Must Include CSS Code/Default Custom Alert Box Class: /* mus

Suraj Aswal 17 Sep 10, 2022
Tries to execute sync/async function, returns a specified default value if the function throws

good-try Tries to execute sync/async function, returns a specified default value if the function throws. Why Why not nice-try with it's 70+ million do

Antonio Stoilkov 14 Dec 8, 2022
Vaultacks lets users store files off-chain on Gaia. Files are encrypted by default but also can be made public and shared

Vaultacks Vaultacks is built on the Stacks Chain. It lets users upload files to Gaia, a off-chain data storage system. Vaultacks currently uses the de

Anish De 5 Sep 14, 2022
This plugin integrates by default with Twitter bootstrap using badges to display the maximum lenght of the field where the user is inserting text. Uses the HTML5 attribute "maxlength" to work.

Bootstrap MaxLength This plugin integrates by default with Twitter bootstrap using badges to display the maximum length of the field where the user is

Maurizio 772 Dec 25, 2022
Chrome extension that switches default build tool to Maven at start.spring.io

start.spring.io default to Maven On the 18th of October 2022 https://start.spring.io switched the default build tool from Maven to Gradle spring-io/st

Maciej Walkowiak 11 Dec 14, 2022
SET Revision is a website to help you identify "sets" in the card game SET.

Welcome to SET Revision! SET Revision is a website to help you identify "sets" in the card game SET. The code in this repository is aimed for learners

Benjamin Piper 2 Oct 3, 2022
A set of best practices for JavaScript projects

中文版 | 日本語版 | 한국어 | Русский | Português Project Guidelines · While developing a new project is like rolling on a green field for you, maintaining it is

Elsewhen 28.4k Jan 1, 2023
This repository contains a basic example on how to set up and run test automation jobs with CircleCI and report results to Testmo.

CircleCI test automation example This repository contains a basic example on how to set up and run test automation jobs with CircleCI and report resul

Testmo 2 Dec 23, 2021