next-sanity icon indicating copy to clipboard operation
next-sanity copied to clipboard

v3 ready version of code-input causing schema errors

Open xanderjl opened this issue 1 year ago • 1 comments

I've been trying a few different ways of getting this to cooperate, but I keep hitting schema errors in Sanity.

// sanity.config.ts

import dynamic from "next/dynamic"
import { createConfig, Plugin } from "sanity"
import { deskTool } from "sanity/desk"
import structure from "./deskStructure"
import types from "./schemas"
const codeInput = () =>
  dynamic<Plugin<void>>(
    () =>
      import("@sanity/code-input").then(
        (mod) => mod.default.codeInput
      ) as Promise<any>,
    { ssr: false }
  )

const projectId = process.env.NEXT_PUBLIC_SANITY_PROJECT_ID!
const dataset = process.env.NEXT_PUBLIC_SANITY_DATASET!

const config = createConfig({
  name: "default",
  title: "strangelove-ventures",
  projectId,
  dataset,
  plugins: [deskTool({ structure }), codeInput()],
  schema: {
    types,
  },
  basePath: "/studio",
})

export default config

I'm having to use next/dynamic because when I pass the codeInput() function into the config using the usual ES6 import pattern, I get a 'window undefined' error.

I'm getting the schema error when I attempt to add the code type to my blockContent schema:

// blockContent.ts

const blockContent = {
  title: "Block Content",
  name: "blockContent",
  type: "array",
  of: [
    {
      title: "Block",
      type: "block",
      styles: [
        { title: "Normal", value: "normal" },
        { title: "H1", value: "h1" },
        { title: "H2", value: "h2" },
        { title: "H3", value: "h3" },
        { title: "H4", value: "h4" },
        { title: "Quote", value: "blockquote" },
      ],
      marks: {
        decorators: [
          { title: "Strong", value: "strong" },
          { title: "Emphasis", value: "em" },
        ],
        annotations: [
          {
            title: "URL",
            name: "link",
            type: "object",
            fields: [
              {
                title: "URL",
                name: "href",
                type: "url",
              },
            ],
          },
        ],
      },
    },
    {
      type: "image",
      options: { hotspot: true },
    },
    {
      type: "code",
    },
  ],
}

export default blockContent

Relevant deps from my package.json:

{
  "dependencies": {
    "@portabletext/react": "1.0.6",
    "@sanity/code-input": "^3.0.0-v3-studio.2",
    "@sanity/image-url": "^1.0.1",
    "@sanity/next-studio-layout": "^2.0.0-v3-studio.8",
    "next": "12.2.4",
    "next-sanity": "0.5.2",
    "react": "18.1.0",
    "react-dom": "18.1.0",
  },
  "devDependencies": {
    "@types/node": "17.0.41",
    "@types/styled-components": "^5.1.25",
    "eslint": "8.17.0",
    "eslint-config-next": "12.1.6",
    "prettier": "2.6.2",
    "sanity": "^3.0.0-dev-preview.12",
    "sanity-codegen": "^0.9.8",
    "styled-components": "^5.3.5",
    "typescript": "4.7.3"
  }
}

xanderjl avatar Aug 10 '22 02:08 xanderjl

cc @snorrees

stipsan avatar Aug 12 '22 04:08 stipsan

For those running into similar issues, here was the solve:

// sanity.config.ts

import { codeInput } from "@sanity/code-input"
import { createConfig } from "sanity"
import { deskTool } from "sanity/desk"
import structure from "./deskStructure"
import types from "./schemas"

const projectId = process.env.NEXT_PUBLIC_SANITY_PROJECT_ID!
const dataset = process.env.NEXT_PUBLIC_SANITY_DATASET!

const config = createConfig({
  name: "default",
  title: "whatever",
  projectId,
  dataset,
  plugins: [deskTool({ structure }), codeInput()],
  schema: {
    types,
  },
  basePath: "/studio",
})

export default config
// pages/studio/[[...index]].tsx

import { StudioPageLayoutProps } from "@sanity/next-studio-layout"
import { NextPage } from "next"
import dynamic from "next/dynamic"
import React from "react"
import config from "studio/sanity.config"
const StudioPageLayout = dynamic<StudioPageLayoutProps>(
  () =>
    import("@sanity/next-studio-layout").then(
      (mod) => mod.StudioPageLayout
    ),
  { ssr: false }
)

const Sanity: NextPage = () => <StudioPageLayout config={config} />

export default Sanity

I swear I had tried this pattern before, but you need to dynamically import the <StudioPageLayout />, not the code-input plugin. Hope this helps!

To the best of my knowledge, this is happening because of the ace editor the code-input plugin is built on top of. I only had to resort to this pattern once the plugin was added.

xanderjl avatar Aug 15 '22 22:08 xanderjl

@xanderjl hey, thanks for reporting! This is definitely a problem with the ace dependency: it interacts with the window object directly without any checks. This fails in a node environment, like you experienced.

We just released a new version of v3 code input. In it, we lazy load any ace-editor related code, so that it should render a placeholder on the server. With it, you no longer should have to your dynamic workaround for next-studio-layout 🤞

snorrees avatar Aug 16 '22 21:08 snorrees

We just released a new version of v3 code input

I noticed and took it for a spin! I'm still hitting an SSR error in v4 and I think I may have found the culprit. PreviewCode.tsx was still importing ReactAce from the package directly. I've cloned the repo and am testing the lazy loading/suspense wrapper pattern locally 👀

xanderjl avatar Aug 16 '22 21:08 xanderjl

Hmm that didn't seem to fix it either. At a bit of a loss 😅

xanderjl avatar Aug 16 '22 21:08 xanderjl

Never mind I fixed it! Will open a PR shortly

xanderjl avatar Aug 16 '22 22:08 xanderjl

So much for me writing unit tests to reproduce when I didnt test it a SSR stack 🙈

snorrees avatar Aug 16 '22 23:08 snorrees

Turns out I don't have access to push up my branch, which makes sense 😅

Is there an article outlining how to contribute to the sanity org repos?

xanderjl avatar Aug 16 '22 23:08 xanderjl

I think you would have to make a fork. But from what you are saying, simply adding the hook to the preview comp should fix it right? I'll get on that tomorrow!

snorrees avatar Aug 16 '22 23:08 snorrees

@xanderjl just released a new version of code-input that also makes the ace-code async in the preview component.

Let me know if it works out for you now; I just tested this in a regular studio deploy atm.

snorrees avatar Aug 17 '22 14:08 snorrees

@snorrees just bumped to the latest version and it's working as intended! Thanks for addressing this so quickly 😁

xanderjl avatar Aug 17 '22 16:08 xanderjl

Thats great to hear! Thanks for testing it!

snorrees avatar Aug 17 '22 17:08 snorrees

Thanks for reporting @xanderjl !

evenwestvang avatar Aug 17 '22 17:08 evenwestvang