mirror of
https://github.com/stefanpejcic/openpanel
synced 2025-06-26 18:28:26 +00:00
193 lines
4.6 KiB
TypeScript
193 lines
4.6 KiB
TypeScript
import decamelize from "decamelize";
|
|
import type {
|
|
API,
|
|
Collection,
|
|
FileInfo,
|
|
JSCodeshift,
|
|
JSXIdentifier,
|
|
} from "jscodeshift";
|
|
import {
|
|
addAttributeIfNotExist,
|
|
addOrUpdateImports,
|
|
wrapChildren,
|
|
wrapElement,
|
|
} from "../../utils/codeshift";
|
|
import { prettierFormat } from "../../utils/swizzle/prettierFormat";
|
|
|
|
export const parser = "tsx";
|
|
|
|
export default async function transformer(file: FileInfo, api: API) {
|
|
const j = api.jscodeshift;
|
|
const source = j(file.source);
|
|
|
|
const hasRefineElement =
|
|
source.find(j.JSXElement, {
|
|
openingElement: {
|
|
name: {
|
|
name: "Refine",
|
|
},
|
|
},
|
|
}).length !== 0;
|
|
|
|
if (!hasRefineElement) {
|
|
return;
|
|
}
|
|
|
|
const functionDeclaration = source.find(j.FunctionDeclaration, {
|
|
id: {
|
|
name: "App",
|
|
},
|
|
});
|
|
|
|
addReactRouterImports(j, source);
|
|
|
|
// Find the first jsx element in the function and wrap it with `BrowserRouter` component.
|
|
|
|
functionDeclaration.forEach((funcDec) => {
|
|
const openerElements = j(funcDec).find(j.JSXElement).at(0);
|
|
|
|
openerElements.forEach((openerElement) => {
|
|
wrapElement(j, source, openerElement, "BrowserRouter");
|
|
});
|
|
});
|
|
|
|
const refineElements = source.find(j.JSXElement, {
|
|
openingElement: {
|
|
name: {
|
|
name: "Refine",
|
|
},
|
|
},
|
|
});
|
|
|
|
refineElements.forEach((refineElement) => {
|
|
addAttributeIfNotExist(
|
|
j,
|
|
source,
|
|
refineElement,
|
|
"routerProvider",
|
|
j.jsxExpressionContainer(j.identifier("routerProvider")),
|
|
);
|
|
|
|
wrapChildren(j, source, refineElement, "Routes");
|
|
});
|
|
|
|
const routesElements = source.find(j.JSXElement, {
|
|
openingElement: {
|
|
name: {
|
|
name: "Routes",
|
|
},
|
|
},
|
|
});
|
|
|
|
routesElements.forEach((routesElement) => {
|
|
let elementCount = 0;
|
|
|
|
const newRouteElements = [];
|
|
|
|
routesElement.node?.children
|
|
?.filter((value) => {
|
|
return (
|
|
value.type === "JSXElement" &&
|
|
value.openingElement.name.type === "JSXIdentifier" &&
|
|
value.openingElement.name.name !== "Route"
|
|
);
|
|
})
|
|
?.forEach((child) => {
|
|
if (child.type === "JSXElement") {
|
|
elementCount++;
|
|
const firstAttribute =
|
|
elementCount === 1
|
|
? j.jsxAttribute(j.jsxIdentifier("index"))
|
|
: j.jsxAttribute(
|
|
j.jsxIdentifier("path"),
|
|
j.stringLiteral(
|
|
`/${decamelize(
|
|
(child.openingElement.name as JSXIdentifier).name,
|
|
{ separator: "-" },
|
|
)}`,
|
|
),
|
|
);
|
|
|
|
const routeElement = j.jsxElement(
|
|
j.jsxOpeningElement(
|
|
j.jsxIdentifier("Route"),
|
|
[
|
|
firstAttribute,
|
|
j.jsxAttribute(
|
|
j.jsxIdentifier("element"),
|
|
j.jsxExpressionContainer(j.jsxElement(child.openingElement)),
|
|
),
|
|
],
|
|
true,
|
|
),
|
|
);
|
|
|
|
newRouteElements.push(routeElement);
|
|
}
|
|
});
|
|
|
|
if (newRouteElements.length === 0) {
|
|
newRouteElements.push(...(routesElement.node.children ?? []));
|
|
} else {
|
|
addOrUpdateImports(j, source, "@refinedev/core", ["ErrorComponent"]);
|
|
|
|
const errorRoute = j.jsxElement(
|
|
j.jsxOpeningElement(
|
|
j.jsxIdentifier("Route"),
|
|
[
|
|
j.jsxAttribute(j.jsxIdentifier("path"), j.literal("*")),
|
|
j.jsxAttribute(
|
|
j.jsxIdentifier("element"),
|
|
j.jsxExpressionContainer(
|
|
j.jsxElement(
|
|
j.jsxOpeningElement(
|
|
j.jsxIdentifier("ErrorComponent"),
|
|
[],
|
|
true,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
true,
|
|
),
|
|
);
|
|
|
|
newRouteElements.push(errorRoute);
|
|
}
|
|
|
|
routesElement.replace(
|
|
j.jsxElement(
|
|
routesElement.node.openingElement,
|
|
routesElement.node.closingElement,
|
|
newRouteElements,
|
|
),
|
|
);
|
|
});
|
|
|
|
return await prettierFormat(source.toSource());
|
|
}
|
|
|
|
export const addReactRouterImports = (j: JSCodeshift, source: Collection) => {
|
|
addOrUpdateImports(
|
|
j,
|
|
source,
|
|
"react-router-dom",
|
|
["BrowserRouter", "Routes", "Route"],
|
|
(sourceDeclarations, targetDeclaration) => {
|
|
sourceDeclarations.at(0).insertAfter(targetDeclaration);
|
|
},
|
|
);
|
|
|
|
addOrUpdateImports(
|
|
j,
|
|
source,
|
|
"@refinedev/react-router-v6",
|
|
["routerProvider"],
|
|
(sourceDeclarations, targetDeclaration) => {
|
|
sourceDeclarations.at(0).insertAfter(targetDeclaration);
|
|
},
|
|
true,
|
|
);
|
|
};
|