sanity-codegen
sanity-codegen copied to clipboard
Error: Cannot find module 'part:@sanity/base/client' when using Orderable Document List
same error here https://github.com/sanity-io/orderable-document-list/issues/14
Same type of error but with Error: Cannot find module 'part:@sanity/base/user
.
Using a custom React component in sanity that imports import { FormField } from "@sanity/base/components";
and some other existing sanity internal library components.
sanity build
compiles and prod site runs perfectly, just sanity-codegen throwing this error.
This is a complex issue that has to do with babel resolution of sanity parts as its core.
For some custom components, this may be sufficient: https://github.com/ricokahler/sanity-codegen/issues/59#issuecomment-762472234
But for Orderable Document List it isn't, as the type is defined via a function, eg orderRankField({ type: 'project' }),
Not sure what the solution actually is, but it may not really be possible with how sanity-codegen presently works.
Here is a solution for this plugin specifically, though it may be helpful for other plugins as well.
There are two steps: first, extend the codegen babel config to "no-op" the target plugin. Second, mock the essential bits that you're expecting the function/plugin to return.
sanity-codegen.config.ts (taken from here):
import { defaultBabelOptions } from 'sanity-codegen/cli';
import { SanityCodegenConfig } from 'sanity-codegen';
const config: SanityCodegenConfig = {
schemaPath: './schemas/index',
outputPath: '../web/src/config/sanity-schema.ts',
babelOptions: {
...defaultBabelOptions,
plugins: [
...defaultBabelOptions.plugins.filter(
([key]) => key !== 'module-resolver',
),
[
'module-resolver',
{
root: ['.'],
alias: {
// The below are all the defaults
'part:@sanity/base/schema-creator':
'sanity-codegen/schema-creator-shim',
'all:part:@sanity/base/schema-type':
'sanity-codegen/schema-type-shim',
'part:@sanity/base/schema-type': 'sanity-codegen/schema-type-shim',
'^part:.*': 'sanity-codegen/no-op',
'^config:.*': 'sanity-codegen/no-op',
'^all:part:.*': 'sanity-codegen/no-op',
// Here we specify which plugins need to be mocked
// (see mocks.ts for more info)
// 👇👇👇
'@sanity/orderable-document-list/lib/helpers/constants':
'sanity-codegen/no-op',
'@sanity/orderable-document-list': 'sanity-codegen/no-op',
// 👆👆👆
},
},
],
],
},
};
export default config;
I created a mocks.ts
to store my mock of orderRankField()
(and others in the future) like so:
import { orderRankField as _orderRankField } from '@sanity/orderable-document-list';
const constants = require('@sanity/orderable-document-list/lib/helpers/constants');
/** a mock of orderRankField for typegen purposes */
export const orderRankField = (props: {
type: string;
title?: string;
icon?: any;
id?: string;
filter?: string;
params?: {
lang: 'en_US';
};
}) => {
const name =
typeof constants.ORDER_FIELD_NAME === 'string'
? constants.ORDER_FIELD_NAME
: 'orderRank';
const orf = {
title: 'Order Rank',
readOnly: true,
hidden: true,
name,
type: 'string',
..._orderRankField(props),
};
return orf;
};
...so that I could then reference it in my document files, for example a "project" schema in project.ts
:
import { orderRankField } from '../util'; // my mocked one, NOT the version from the plugin
export const projectDoc = {
name: 'project',
type: 'document',
title: 'Project',
fields: [
name,
orderRankField({ type: 'project', title: 'Projects' }),
],
} as const;
A solution that worked for me is to use babel-plugin-search-and-replace to replace the custom input imports with a dummy component. Inspired by this solution: https://github.com/ricokahler/sanity-codegen/issues/59#issuecomment-1086887871
import { SanityCodegenConfig } from "sanity-codegen"
import { defaultBabelOptions } from "sanity-codegen/cli"
const sanityCodegenConfig: SanityCodegenConfig = {
schemaPath: "./schemas/schema",
outputPath: "./schema.ts",
babelOptions: {
...defaultBabelOptions,
plugins: [
...defaultBabelOptions.plugins,
[
"search-and-replace",
{
rules: [
{
search: /src\/components\/.*/, // part of the path to your components
replace: "sanity-codegen-components.tsx", // a file at the same level of your search
},
],
},
],
],
},
}
export default sanityCodegenConfig
We could possibly refactor this to make use of sanity-codegen/no-op
instead of creating a dummy component.