vite-plugin-react-server
Version:
Vite plugin for React Server Components (RSC)
132 lines (120 loc) • 3.4 kB
text/typescript
type ResolvePropsOptions = {
propsModule: Record<string, any>;
path: string;
exportName: string;
url: string;
};
type ResolvePropsResult =
| { type: "success"; key: string; props: any }
| { type: "error"; error: Error }
| { type: "skip" };
function isFunction(value: any) {
return typeof value === "function";
}
export async function resolveProps({
propsModule,
path,
exportName,
url,
}: ResolvePropsOptions): Promise<ResolvePropsResult> {
if (!propsModule) {
return {
type: "error",
error: new Error(`propsModule is ${typeof propsModule}`),
};
}
if (typeof propsModule !== "object") {
return {
type: "error",
error: new Error(
`propsModule must be an object, got ${typeof propsModule}`
),
};
}
const keys = Object.keys(propsModule);
let found = keys.find((v) => v === exportName || v === url || v === path);
if(exportName in propsModule) {
found = exportName;
}
if (found) {
let value = propsModule[found];
try {
// If it's a function, call it with the URL
if (isFunction(value)) {
const props = await value(url);
return {
type: "success",
key: found,
props,
};
}
// If it's a promise, await it
if (value && typeof value.then === "function") {
const props = await value;
return {
type: "success",
key: found,
props,
};
}
// If it's a plain object, use it directly
if (typeof value === "object" && value !== null) {
return {
type: "success",
key: found,
props: value,
};
}
return {
type: "error",
error: new Error(
`Expected props export "${exportName}" in "${path}" to be a function, promise, or object that resolves to props, instead got typeof ${typeof value}.`
),
};
} catch (error) {
console.trace(error);
console.warn(found, "error in resolveProps", propsModule, url, path);
return {
type: "error",
error: error as Error,
};
}
}
const commonjs = keys.find((v) => v === "exports");
if (!!commonjs) {
const exportKeys = (commonjs as unknown as { exports: any })["exports"]
? Object.keys((commonjs as unknown as { exports: any })["exports"])
: [];
const foundCommonJS = exportKeys.find(
(v) => v === exportName || v === url || v === path
);
return {
type: "error",
error: new Error(
`Expected props export "${exportName}" in "${path}", but instead got "exports" with ${
!!foundCommonJS
? foundCommonJS.toString()
: exportKeys.length
? exportKeys.join(", ")
: "no keys"
}, this will not work. Make sure to set esModule: true in rollupOptions.output. ${JSON.stringify(propsModule)}`
),
};
}
if (Object.keys(propsModule).includes("error")) {
return {
type: "error",
error: propsModule["error"],
};
}
return {
type: "error",
error: new Error(
`Could not find props export "${exportName}" in "${path}". ${
keys.length
? "Available exports: " + keys.join(", ")
: "The object was defined but has no properties. \"" + JSON.stringify(propsModule) + "\""
}`
),
};
}