JSPM

  • Created
  • Published
  • Downloads 1507
  • Score
    100M100P100Q118925F

Mock @sanity-typed/client for local development and testing

Package Exports

  • @sanity-typed/client-mock
  • @sanity-typed/client-mock/dist/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@sanity-typed/client-mock) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

@sanity-typed/client-mock

NPM Downloads GitHub commit activity (branch) GitHub Repo stars GitHub contributors GitHub issues by-label Minified Size License

GitHub Sponsors

Mock @sanity-typed/client for local development and testing

Watch How to Offline Your Sanity Client and Generate Mock Data

Page Contents

Install

npm install sanity @sanity-typed/client-mock

Usage

Use createClient instead of the createClient from @sanity-typed/client and include initial documents.

product.ts:

// import { defineArrayMember, defineField, defineType } from "sanity";
import {
  defineArrayMember,
  defineField,
  defineType,
} from "@sanity-typed/types";

/** No changes using defineType, defineField, and defineArrayMember */
export const product = defineType({
  name: "product",
  type: "document",
  title: "Product",
  fields: [
    defineField({
      name: "productName",
      type: "string",
      title: "Product name",
      validation: (Rule) => Rule.required(),
    }),
    defineField({
      name: "tags",
      type: "array",
      title: "Tags for item",
      of: [
        defineArrayMember({
          type: "object",
          name: "tag",
          fields: [
            defineField({ type: "string", name: "label" }),
            defineField({ type: "string", name: "value" }),
          ],
        }),
      ],
    }),
  ],
});

sanity.config.ts:

import { visionTool } from "@sanity/vision";
import { deskTool } from "sanity/desk";

// import { defineConfig } from "sanity";
import { defineConfig } from "@sanity-typed/types";
import type { InferSchemaValues } from "@sanity-typed/types";

import { product } from "./schemas/product";

/** No changes using defineConfig */
const config = defineConfig({
  projectId: "59t1ed5o",
  dataset: "production",
  plugins: [deskTool(), visionTool()],
  schema: {
    types: [
      product,
      // ...
    ],
  },
});

export default config;

/** Typescript type of all types! */
export type SanityValues = InferSchemaValues<typeof config>;
/**
 *  SanityValues === {
 *    product: {
 *      _createdAt: string;
 *      _id: string;
 *      _rev: string;
 *      _type: "product";
 *      _updatedAt: string;
 *      productName: string;
 *      tags?: {
 *        _key: string;
 *        _type: "tag";
 *        label?: string;
 *        value?: string;
 *      }[];
 *    };
 *    // ... all your types!
 *  }
 */

mocked-client.ts:

import type { SanityValues } from "sanity.config";

// import { createClient } from "@sanity-typed/client";
import { createClient } from "@sanity-typed/client-mock";

/** Small change using createClient */
// export const client = createClient({
export const client = createClient<SanityValues>({
  dataset: [
    {
      _createdAt: "2011-12-15T03:57:59.213Z",
      _id: "id",
      _rev: "rev",
      _type: "product",
      _updatedAt: "2029-01-01T06:23:59.079Z",
      productName: "Mock Product",
      tags: [
        {
          _key: "key",
          _type: "tag",
          label: "Mock Tag Label",
          value: "Mock Tag Value",
        },
      ],
    },
    // ...
  ],
})({
  projectId: "59t1ed5o",
  dataset: "production",
  useCdn: true,
  apiVersion: "2023-05-23",
});

export const makeTypedQuery = async () =>
  client.fetch('*[_type=="product"]{_id,productName,tags}');
/**
 *  makeTypedQuery() === Promise<[{
 *    _id: "id",
 *    productName: "Mock Product",
 *    tags: [
 *      {
 *        _key: "key",
 *        _type: "tag",
 *        label: "Mock Tag Label",
 *        value: "Mock Tag Value",
 *      },
 *    ],
 *  }]>
 */

Depending on your tree-shaking setup, you'll want to swap between the real client and the mock client. Additionally, using @sanity-typed/faker along with the mock client can be a great way to generate fake data.

mocks.ts:

import { base, en } from "@faker-js/faker";
import config from "sanity.config";

import { sanityConfigToFaker } from "@sanity-typed/faker";

export const getMockDataset = () => {
  const sanityFaker = sanityConfigToFaker(config, {
    faker: { locale: [en, base] },
  });
  /**
   *  typeof sanityFaker === {
   *    [type in keyof SanityValues]: () => SanityValues[type];
   *  }
   */

  return [
    sanityFaker.product(),
    sanityFaker.product(),
    sanityFaker.product(),
    sanityFaker.product(),
    sanityFaker.product(),
  ];
};

swapping-client.ts:

import type { SanityValues } from "sanity.config";

import { createClient as createLiveClient } from "@sanity-typed/client";
import { createClient as createMockClient } from "@sanity-typed/client-mock";

import { getMockDataset } from "./mocks";

// @ts-expect-error -- TODO https://github.com/saiichihashimoto/sanity-typed/issues/482
const createClient = process.env.VERCEL
  ? createLiveClient<SanityValues>()
  : createMockClient<SanityValues>({ dataset: getMockDataset() });

export const client = createClient({
  projectId: "59t1ed5o",
  dataset: "production",
  useCdn: true,
  apiVersion: "2023-05-23",
});

export const makeTypedQuery = async () =>
  client.fetch('*[_type=="product"]{_id,productName,tags}');

Considerations

Config in Runtime

@sanity-typed/* generally has the goal of only having effect to types and no runtime effects. This package is an exception. This means that you will have to import your sanity config to use this. While sanity v3 is better than v2 at having a standard build environment, you will have to handle any nuances, including having a much larger build.

Alternatives