fork refine

This commit is contained in:
Stefan Pejcic
2024-02-05 10:23:04 +01:00
parent 3fffde9a8f
commit 8496a83edb
3634 changed files with 715528 additions and 2 deletions

View File

@@ -0,0 +1,79 @@
import { Collection, JSCodeshift } from "jscodeshift";
const authHookNames = [
"useForgotPassword",
"useGetIdentity",
"useIsAuthenticated",
"useAuthenticated",
"useLogin",
"useLogout",
"useOnError",
"useCheckError",
"usePermission",
"useRegister",
"useUpdatePassword",
"usePermissions",
];
export const addV3LegacyAuthProviderCompatibleTrueToAuthHooks = (
j: JSCodeshift,
root: Collection<any>,
) => {
const authHooks = root.find(j.CallExpression, {
callee: {
name: (name: string) => authHookNames.includes(name),
},
});
authHooks.forEach((authHook) => {
const args = authHook.value.arguments;
if (args.length === 0) {
args.push(
j.objectExpression([
j.objectProperty(
j.identifier("v3LegacyAuthProviderCompatible"),
j.booleanLiteral(true),
),
]),
);
return;
}
if (args.length === 1) {
const arg = args[0];
if (arg.type === "ObjectExpression") {
const legacyProp = arg.properties.find(
(property) =>
property["key"]?.name ===
"v3LegacyAuthProviderCompatible",
);
if (legacyProp) {
return;
}
arg.properties.push(
j.objectProperty(
j.identifier("v3LegacyAuthProviderCompatible"),
j.booleanLiteral(true),
),
);
}
if (arg.type === "Identifier") {
// turn to spread syntax and add v3LegacyAuthProviderCompatible
const newArg = j.objectExpression([
j.spreadElement(arg),
j.objectProperty(
j.identifier("v3LegacyAuthProviderCompatible"),
j.booleanLiteral(true),
),
]);
args[0] = newArg;
}
return;
}
});
};

View File

@@ -0,0 +1,43 @@
import { Collection, JSCodeshift } from "jscodeshift";
const REFINE_CORE_PATH = "@pankod/refine-core";
export const authProviderToLegacyAuthProvider = (
j: JSCodeshift,
root: Collection<any>,
) => {
const refineCorePath = root
.find(j.ImportDeclaration)
.filter((path) => path.node.source.value === REFINE_CORE_PATH)
.find(j.ImportSpecifier);
const authProviderImport = refineCorePath.filter(
(path) => path.node.imported.name === "AuthProvider",
);
// change AuthProvider to LegacyAuthProvider as AuthProvider
authProviderImport.forEach((authProvider) => {
j(authProvider).replaceWith(
j.importSpecifier(
j.identifier("LegacyAuthProvider as AuthProvider"),
),
);
});
// find <Refine>
root.findJSXElements("Refine").forEach((path) => {
const attributes = path.node.openingElement.attributes;
// find <Refine authProvider={}>
const authProviderAttribute = attributes.find(
(attribute) =>
attribute.type === "JSXAttribute" &&
attribute.name.name === "authProvider",
);
if (!authProviderAttribute) return;
// change authProvider={} to legacyAuthProvider={}
authProviderAttribute["name"]["name"] = "legacyAuthProvider";
});
};

View File

@@ -0,0 +1,978 @@
import {
JSCodeshift,
Collection,
ObjectExpression,
Property,
Identifier,
ObjectProperty,
BooleanLiteral,
JSXAttribute,
JSXExpressionContainer,
ArrayExpression,
} from "jscodeshift";
export const parser = "tsx";
const configToSpreadConfig = (j: JSCodeshift, source: Collection) => {
const useListHooks = source.find(j.CallExpression, {
callee: {
name: "useList",
},
});
useListHooks.replaceWith((p) => {
const configProperty = (
p.node.arguments[0] as unknown as ObjectExpression
).properties.find(
(p: Property) => (p.key as Identifier).name === "config",
);
if (!configProperty) {
return p.node;
}
const propertiesWithoutConfig = (
p.node.arguments[0] as unknown as ObjectExpression
).properties.filter(
(p: Property) => (p.key as Identifier).name !== "config",
);
const configProperties = (
(configProperty as ObjectProperty).value as ObjectExpression
).properties;
p.node.arguments = [
j.objectExpression([
...propertiesWithoutConfig,
...configProperties,
]),
];
return p.node;
});
};
const sortToSorters = (j: JSCodeshift, source: Collection) => {
const willCheckHooks = [
"useCheckboxGroup",
"useRadioGroup",
"useSelect",
"useAutocomplete",
"useList",
];
willCheckHooks.forEach((hookName) => {
const useListHooks = source.find(j.CallExpression, {
callee: {
name: hookName,
},
});
useListHooks.replaceWith((p) => {
if (p.node.arguments.length === 0) {
return p.node;
}
const sortProperty = (
p.node.arguments[0] as unknown as ObjectExpression
).properties.find(
(p: Property) => (p.key as Identifier).name === "sort",
);
if (!sortProperty) {
return p.node;
}
const propertiesWithoutSort = (
p.node.arguments[0] as unknown as ObjectExpression
).properties.filter(
(p: Property) => (p.key as Identifier).name !== "sort",
);
p.node.arguments = [
j.objectExpression([
...propertiesWithoutSort,
j.objectProperty(
j.identifier("sorters"),
(sortProperty as any).value,
),
]),
];
return p.node;
});
});
};
const sorterToSorters = (j: JSCodeshift, source: Collection) => {
const willCheckHooks = ["useExport"];
willCheckHooks.forEach((hookName) => {
const useListHooks = source.find(j.CallExpression, {
callee: {
name: hookName,
},
});
useListHooks.replaceWith((p) => {
if (p.node.arguments.length === 0) {
return p.node;
}
const sortProperty = (
p.node.arguments[0] as unknown as ObjectExpression
).properties.find(
(p: Property) => (p.key as Identifier).name === "sorter",
);
if (!sortProperty) {
return p.node;
}
const propertiesWithoutSort = (
p.node.arguments[0] as unknown as ObjectExpression
).properties.filter(
(p: Property) => (p.key as Identifier).name !== "sorter",
);
p.node.arguments = [
j.objectExpression([
...propertiesWithoutSort,
j.objectProperty(
j.identifier("sorters"),
(sortProperty as any).value,
),
]),
];
return p.node;
});
});
};
const resourceNametoResource = (j: JSCodeshift, source: Collection) => {
const willCheckHooks = ["useExport", "useImport"];
willCheckHooks.forEach((hookName) => {
const useListHooks = source.find(j.CallExpression, {
callee: {
name: hookName,
},
});
useListHooks.replaceWith((p) => {
if (p.node.arguments.length === 0) {
return p.node;
}
const resourceNameProperty = (
p.node.arguments[0] as unknown as ObjectExpression
).properties.find(
(p: Property) => (p.key as Identifier).name === "resourceName",
);
if (!resourceNameProperty) {
return p.node;
}
const propertiesWithoutResourceName = (
p.node.arguments[0] as unknown as ObjectExpression
).properties.filter(
(p: Property) => (p.key as Identifier).name !== "resourceName",
);
p.node.arguments = [
j.objectExpression([
...propertiesWithoutResourceName,
j.objectProperty(
j.identifier("resource"),
(resourceNameProperty as any).value,
),
]),
];
return p.node;
});
});
};
const deprecatedUseTablePaginationProps = [
"initialCurrent",
"initialPageSize",
"hasPagination",
];
const deprecatedUseTableFiltersProps = [
"initialFilter",
"permanentFilter",
"defaultSetFilterBehavior",
];
const deprecatedUseTableSortersProps = ["initialSorter", "permanentSorter"];
const fixDeprecatedReactTableProps = (j: JSCodeshift, source: Collection) => {
const refineReactTableImports = source.find(j.ImportDeclaration, {
source: {
value: "@pankod/refine-react-table",
},
specifiers: [
{
imported: {
name: "useTable",
},
},
],
});
if (refineReactTableImports.length === 0) {
return;
}
const useTableHooks = source.find(j.CallExpression, {
callee: {
name: "useTable",
},
});
useTableHooks.replaceWith((p) => {
if (p.node.arguments.length === 0) {
return p.node;
}
const hasRefineCoreProps = (
p.node.arguments[0] as ObjectExpression
).properties.find(
(p: Property) => (p.key as Identifier).name === "refineCoreProps",
);
if (!hasRefineCoreProps) {
return p.node;
}
const otherProperties = (
p.node.arguments[0] as ObjectExpression
).properties.filter(
(p: Property) => (p.key as Identifier).name !== "refineCoreProps",
);
const paginationProperties = deprecatedUseTablePaginationProps.map(
(prop) => {
const property = (
(hasRefineCoreProps as ObjectProperty)
.value as ObjectExpression
).properties.find(
(p: Property) => (p.key as Identifier).name === prop,
);
if (!property) {
return;
}
if (prop === "hasPagination") {
return j.property(
"init",
j.identifier("mode"),
j.literal(
(
(property as ObjectProperty)
.value as BooleanLiteral
).value
? "server"
: "off",
),
);
}
if (prop === "initialCurrent") {
return j.property(
"init",
j.identifier("current"),
(property as ObjectProperty).value,
);
}
if (prop === "initialPageSize") {
return j.property(
"init",
j.identifier("pageSize"),
(property as ObjectProperty).value,
);
}
return;
},
);
const paginationProperty = j.property(
"init",
j.identifier("pagination"),
j.objectExpression(paginationProperties.filter(Boolean)),
);
const filtersProperties = deprecatedUseTableFiltersProps.map((prop) => {
const property = (
(hasRefineCoreProps as ObjectProperty).value as ObjectExpression
).properties.find(
(p: Property) => (p.key as Identifier).name === prop,
);
if (!property) {
return;
}
if (prop === "initialFilter") {
return j.property(
"init",
j.identifier("initial"),
(property as ObjectProperty).value,
);
}
if (prop === "permanentFilter") {
return j.property(
"init",
j.identifier("permanent"),
(property as ObjectProperty).value,
);
}
if (prop === "defaultSetFilterBehavior") {
return j.property(
"init",
j.identifier("defaultBehavior"),
(property as ObjectProperty).value,
);
}
return;
});
const filtersProperty = j.property(
"init",
j.identifier("filters"),
j.objectExpression(filtersProperties.filter(Boolean)),
);
const sortersProperties = deprecatedUseTableSortersProps.map((prop) => {
const property = (
(hasRefineCoreProps as ObjectProperty).value as ObjectExpression
).properties.find(
(p: Property) => (p.key as Identifier).name === prop,
);
if (!property) {
return;
}
if (prop === "initialSorter") {
return j.property(
"init",
j.identifier("initial"),
(property as ObjectProperty).value,
);
}
if (prop === "permanentSorter") {
return j.property(
"init",
j.identifier("permanent"),
(property as ObjectProperty).value,
);
}
return;
});
const sortersProperty = j.property(
"init",
j.identifier("sorters"),
j.objectExpression(sortersProperties.filter(Boolean)),
);
const otherRefineCoreProps = (
(hasRefineCoreProps as ObjectProperty).value as ObjectExpression
).properties.filter(
(p: Property) =>
![
...deprecatedUseTablePaginationProps,
...deprecatedUseTableSortersProps,
...deprecatedUseTableFiltersProps,
].includes((p.key as Identifier).name),
);
const refineCorePropsProperty = j.property(
"init",
j.identifier("refineCoreProps"),
j.objectExpression(
[
...otherRefineCoreProps,
(paginationProperty.value as ObjectExpression).properties
.length > 0
? paginationProperty
: null,
(filtersProperty.value as ObjectExpression).properties
.length > 0
? filtersProperty
: null,
(sortersProperty.value as ObjectExpression).properties
.length > 0
? sortersProperty
: null,
].filter(Boolean),
),
);
p.node.arguments = [
j.objectExpression([...otherProperties, refineCorePropsProperty]),
];
return p.node;
});
};
const fixDeprecatedUseTableProps = (j: JSCodeshift, source: Collection) => {
const willCheckImports = ["useTable", "useDataGrid"];
willCheckImports.forEach((hook) => {
const useTableHooks = source.find(j.CallExpression, {
callee: {
name: hook,
},
});
useTableHooks.replaceWith((p) => {
if (p.node.arguments.length === 0) {
return p.node;
}
const otherProperties = (
p.node.arguments[0] as ObjectExpression
).properties.filter(
(p: Property) =>
![
...deprecatedUseTablePaginationProps,
...deprecatedUseTableSortersProps,
...deprecatedUseTableFiltersProps,
].includes((p.key as Identifier).name),
);
const paginationProperties = deprecatedUseTablePaginationProps.map(
(prop) => {
const property = (
p.node.arguments[0] as ObjectExpression
).properties.find(
(p: Property) => (p.key as Identifier).name === prop,
);
if (!property) {
return;
}
if (prop === "hasPagination") {
return j.property(
"init",
j.identifier("mode"),
j.literal(
(
(property as ObjectProperty)
.value as BooleanLiteral
).value
? "server"
: "off",
),
);
}
if (prop === "initialCurrent") {
return j.property(
"init",
j.identifier("current"),
(property as ObjectProperty).value,
);
}
if (prop === "initialPageSize") {
return j.property(
"init",
j.identifier("pageSize"),
(property as ObjectProperty).value,
);
}
return;
},
);
const paginationProperty = j.property(
"init",
j.identifier("pagination"),
j.objectExpression(paginationProperties.filter(Boolean)),
);
const filtersProperties = deprecatedUseTableFiltersProps.map(
(prop) => {
const property = (
p.node.arguments[0] as ObjectExpression
).properties.find(
(p: Property) => (p.key as Identifier).name === prop,
);
if (!property) {
return;
}
if (prop === "initialFilter") {
return j.property(
"init",
j.identifier("initial"),
(property as ObjectProperty).value,
);
}
if (prop === "permanentFilter") {
return j.property(
"init",
j.identifier("permanent"),
(property as ObjectProperty).value,
);
}
if (prop === "defaultSetFilterBehavior") {
return j.property(
"init",
j.identifier("defaultBehavior"),
(property as ObjectProperty).value,
);
}
return;
},
);
const filtersProperty = j.property(
"init",
j.identifier("filters"),
j.objectExpression(filtersProperties.filter(Boolean)),
);
const sortersProperties = deprecatedUseTableSortersProps.map(
(prop) => {
const property = (
p.node.arguments[0] as ObjectExpression
).properties.find(
(p: Property) => (p.key as Identifier).name === prop,
);
if (!property) {
return;
}
if (prop === "initialSorter") {
return j.property(
"init",
j.identifier("initial"),
(property as ObjectProperty).value,
);
}
if (prop === "permanentSorter") {
return j.property(
"init",
j.identifier("permanent"),
(property as ObjectProperty).value,
);
}
return;
},
);
const sortersProperty = j.property(
"init",
j.identifier("sorters"),
j.objectExpression(sortersProperties.filter(Boolean)),
);
p.node.arguments = [
j.objectExpression(
[
...otherProperties,
(paginationProperty.value as ObjectExpression)
.properties.length > 0
? paginationProperty
: null,
(filtersProperty.value as ObjectExpression).properties
.length > 0
? filtersProperty
: null,
(sortersProperty.value as ObjectExpression).properties
.length > 0
? sortersProperty
: null,
].filter(Boolean),
),
];
return p.node;
});
});
};
const fixUseListHasPaginationToPaginationMode = (
j: JSCodeshift,
source: Collection,
) => {
const useListHooks = source.find(j.CallExpression, {
callee: {
name: "useList",
},
});
useListHooks.replaceWith((p) => {
if (p.node.arguments.length === 0) {
return p.node;
}
const hasPaginationProperty = (
p.node.arguments[0] as ObjectExpression
).properties.find(
(p: Property) => (p.key as Identifier).name === "hasPagination",
);
if (!hasPaginationProperty) {
return p.node;
}
const paginationProperty = (
p.node.arguments[0] as ObjectExpression
).properties.find(
(p: Property) => (p.key as Identifier).name === "pagination",
);
if (paginationProperty) {
(paginationProperty as any).value.properties.push(
j.property(
"init",
j.identifier("mode"),
j.literal(
(
(hasPaginationProperty as ObjectProperty)
.value as BooleanLiteral
).value
? "server"
: "off",
),
),
);
} else {
(p.node.arguments[0] as ObjectExpression).properties.push(
j.property(
"init",
j.identifier("pagination"),
j.objectExpression([
j.property(
"init",
j.identifier("mode"),
j.literal(
(
(hasPaginationProperty as ObjectProperty)
.value as BooleanLiteral
).value
? "server"
: "off",
),
),
]),
),
);
}
(p.node.arguments[0] as ObjectExpression).properties = (
p.node.arguments[0] as ObjectExpression
).properties.filter(
(p: Property) => (p.key as Identifier).name !== "hasPagination",
);
return p.node;
});
};
const fixUseSelectHasPaginationToPaginationMode = (
j: JSCodeshift,
source: Collection,
) => {
const useSelectHooks = source.find(j.CallExpression, {
callee: {
name: "useSelect",
},
});
useSelectHooks.replaceWith((p) => {
const hasPaginationProperty = (
p.node.arguments[0] as ObjectExpression
).properties.find(
(p: Property) => (p.key as Identifier).name === "hasPagination",
);
const paginationProperty = (
p.node.arguments[0] as ObjectExpression
).properties.find(
(p: Property) => (p.key as Identifier).name === "pagination",
);
const hasMode = (
paginationProperty as unknown as any
)?.value?.properties?.find((p) => (p["name"] = "mode"));
if (hasPaginationProperty && !hasMode) {
if (paginationProperty) {
(paginationProperty as any).value.properties.push(
j.property(
"init",
j.identifier("mode"),
j.literal(
(
(hasPaginationProperty as ObjectProperty)
.value as BooleanLiteral
).value
? "server"
: "off",
),
),
);
} else {
(p.node.arguments[0] as ObjectExpression).properties.push(
j.property(
"init",
j.identifier("pagination"),
j.objectExpression([
j.property(
"init",
j.identifier("mode"),
j.literal(
(
(
hasPaginationProperty as ObjectProperty
).value as BooleanLiteral
).value
? "server"
: "off",
),
),
]),
),
);
}
}
if (!hasPaginationProperty && !hasMode) {
if (paginationProperty) {
(paginationProperty as any).value.properties.push(
j.property(
"init",
j.identifier("mode"),
j.stringLiteral("server"),
),
);
} else {
(p.node.arguments[0] as ObjectExpression).properties.push(
j.property(
"init",
j.identifier("pagination"),
j.objectExpression([
j.property(
"init",
j.identifier("mode"),
j.stringLiteral("server"),
),
]),
),
);
}
}
(p.node.arguments[0] as ObjectExpression).properties = (
p.node.arguments[0] as ObjectExpression
).properties.filter(
(p: Property) => (p.key as Identifier).name !== "hasPagination",
);
return p.node;
});
};
const useCustomConfigSortToSorters = (j: JSCodeshift, source: Collection) => {
const useCustomHooks = source.find(j.CallExpression, {
callee: {
name: "useCustom",
},
});
useCustomHooks.replaceWith((p) => {
if (p.node.arguments.length === 0) {
return p.node;
}
const configProperty = (
p.node.arguments[0] as ObjectExpression
).properties.find(
(p: Property) => (p.key as Identifier).name === "config",
);
if (!configProperty) {
return p.node;
}
const sortProperty = (
(configProperty as ObjectProperty).value as any
).properties.find(
(p: Property) => (p.key as Identifier).name === "sort",
);
if (!sortProperty) {
return p.node;
}
((configProperty as ObjectProperty).value as any).properties.push(
j.property(
"init",
j.identifier("sorters"),
(sortProperty as ObjectProperty).value,
),
);
((configProperty as ObjectProperty).value as any).properties = (
(configProperty as ObjectProperty).value as any
).properties.filter(
(p: Property) => (p.key as Identifier).name !== "sort",
);
return p.node;
});
};
const setSortertoSetSorters = (j: JSCodeshift, source: Collection) => {
const willCheckHooks = ["useTable", "useDataGrid"];
willCheckHooks.forEach((hook) => {
const updatedHooks = source.find(j.CallExpression, {
callee: {
name: hook,
},
});
if (updatedHooks.length === 0) {
return;
}
updatedHooks.forEach((path) => {
const setSorterProperty = path.parentPath.node.id.properties.find(
(p) => p.value.name === "setSorter",
);
if (setSorterProperty) {
setSorterProperty.value.name = "setSorters: setSorter";
}
const sorterPropery = path.parentPath.node.id.properties.find(
(p) => p.value.name === "sorter",
);
if (sorterPropery) {
sorterPropery.value.name = "sorters: sorter";
}
});
});
};
const addCommentToUseSimpleList = (j: JSCodeshift, source: Collection) => {
const useSimpleListHooks = source.find(j.CallExpression, {
callee: {
name: "useSimpleList",
},
});
useSimpleListHooks.forEach((path) => {
const comment = j.commentLine(
"`useSimpleList` does not accept all of Ant Design's `List` component props anymore. You can directly use `List` component instead.",
false,
true,
);
path.parentPath.insertBefore(comment);
});
};
const resourceOptionstoMeta = (j: JSCodeshift, source: Collection) => {
const refineElement = source.find(j.JSXElement, {
openingElement: {
name: {
name: "Refine",
},
},
});
if (refineElement.length === 0) {
return;
}
refineElement.forEach((path) => {
const resources = path.node.openingElement.attributes.find(
(p) => (p as JSXAttribute).name?.name === "resources",
);
if (!resources) {
return;
}
const options = (
((resources as JSXAttribute).value as JSXExpressionContainer)
.expression as ArrayExpression
).elements.filter((p) => {
const properties = (p as ObjectExpression).properties;
return (
properties.find(
(p) =>
((p as ObjectProperty).key as Identifier).name ===
"options",
) !== undefined
);
});
if (options.length === 0) {
return;
}
options.forEach((p) => {
const properties = (p as ObjectExpression).properties;
const optionsProperty = properties.find(
(p) =>
((p as ObjectProperty).key as Identifier).name ===
"options",
);
if (!optionsProperty) {
return;
}
(optionsProperty as ObjectProperty).key = j.identifier("meta");
});
});
};
export const fixV4Deprecations = async (j: JSCodeshift, source: Collection) => {
configToSpreadConfig(j, source);
sortToSorters(j, source);
sorterToSorters(j, source);
resourceNametoResource(j, source);
fixDeprecatedReactTableProps(j, source);
fixDeprecatedUseTableProps(j, source);
fixUseListHasPaginationToPaginationMode(j, source);
fixUseSelectHasPaginationToPaginationMode(j, source);
useCustomConfigSortToSorters(j, source);
setSortertoSetSorters(j, source);
addCommentToUseSimpleList(j, source);
resourceOptionstoMeta(j, source);
};

View File

@@ -0,0 +1,53 @@
import { JSCodeshift, Collection } from "jscodeshift";
export const metaDataToMeta = (j: JSCodeshift, source: Collection) => {
// find all JSX elements
source.find(j.JSXElement).forEach((path) => {
const attributes = path.node.openingElement.attributes;
if (!attributes) return;
// if they have a meta attribute, skip them.
const hasMeta = attributes.some(
(attribute) => attribute?.["name"]?.["name"] === "meta",
);
if (hasMeta) return;
// if they have a metaData change it to meta.
path.node.openingElement.attributes.forEach((attribute) => {
if (attribute?.["name"]?.["name"] === "metaData") {
attribute["name"]["name"] = "meta";
}
});
});
// find all call expressions
source.find(j.CallExpression).forEach((path) => {
// find all arguments
path.node.arguments.forEach((argument) => {
const properties = argument["properties"];
if (!properties) return;
// if they have a meta argument, skip them.
const hasMeta = properties.some(
(property) => property?.["key"]?.["name"] === "meta",
);
if (hasMeta) return;
// if they have a metaData change it to meta.
properties.forEach((property) => {
if (
property?.["shorthand"] &&
property?.["key"]?.["name"] === "metaData"
) {
property["key"]["name"] = "meta";
property["value"]["name"] === "metaData";
property["shorthand"] = false;
} else {
if (property?.["key"]?.["name"] === "metaData") {
property["key"]["name"] = "meta";
}
}
});
});
});
};

View File

@@ -0,0 +1,41 @@
import { JSCodeshift, Collection } from "jscodeshift";
const deprecatedPropName = "ignoreAccessControlProvider";
const newName = "accessControl";
const newProperty = "enabled";
export const moveDeprecatedAccessControlProps = (
j: JSCodeshift,
source: Collection,
) => {
source.find(j.JSXElement).forEach((path) => {
const attributes = path.node.openingElement.attributes;
if (!attributes) return;
const hasAccessControl = attributes.some(
(attribute) => attribute?.["name"]?.["name"] === "accessControl",
);
if (hasAccessControl) return;
const oldProp = path.node.openingElement.attributes.find(
(attribute) => {
return attribute?.["name"]?.["name"] === deprecatedPropName;
},
);
if (oldProp) {
const oldValue = oldProp?.["value"]?.["expression"]?.["value"];
const newValue = !oldValue;
oldProp["name"]["name"] = newName;
oldProp["value"]["expression"] = j.objectExpression([
j.objectProperty(
j.identifier(newProperty),
j.booleanLiteral(newValue),
),
]);
}
});
};

View File

@@ -0,0 +1,110 @@
import { Collection, JSCodeshift } from "jscodeshift";
import { CONFIG_FILE_NAME, CodemodConfig } from "../../helpers";
export const parser = "tsx";
const previousScope = "@pankod/refine-";
const newScope = "@refinedev/";
const deprecatedPackages = [
"@pankod/refine-react-location",
"@pankod/refine-react-router",
];
const getOldPackageName = (oldName: string) => {
return `${previousScope}${
oldName.replace(previousScope, "").split("/")[0]
}`;
};
const getNewPackageName = (oldName: string) => {
return `${newScope}${oldName.replace(previousScope, "").split("/")[0]}`;
};
const getNewImportValue = (oldValue: string) => {
return oldValue.replace(previousScope, newScope);
};
const renameImports = (j: JSCodeshift, source: Collection) => {
const config = new CodemodConfig(CONFIG_FILE_NAME);
source
.find(j.ImportDeclaration)
.filter(
(path) =>
path.node.source.value?.toString()?.startsWith(previousScope) &&
!deprecatedPackages.includes(
path.node.source.value?.toString() ?? "",
),
)
.forEach((path) => {
// for example import line is: @pankod/refine-antd/dist/style.css
const oldImportValue = path.node.source.value?.toString() ?? "";
// getOldPackageName will return @pankod/refine-antd
const oldName = getOldPackageName(oldImportValue);
// getNewPackageName will return @refinedev/antd
const newName = getNewPackageName(oldName);
// getNewImportValue will return @refinedev/antd/dist/style.css
const newImportValue = getNewImportValue(oldImportValue);
config.addPackage(newName);
config.removePackage(oldName);
j(path).replaceWith(
j.importDeclaration(
path.node.specifiers,
j.literal(newImportValue),
),
);
});
};
const renameExports = (j: JSCodeshift, source: Collection) => {
const config = new CodemodConfig(CONFIG_FILE_NAME);
source
.find(j.ExportNamedDeclaration)
.filter(
(path) =>
path.node.source &&
path.node.source.value?.toString()?.startsWith(previousScope) &&
!deprecatedPackages.includes(
path.node.source.value?.toString() ?? "",
),
)
.forEach((path) => {
// for example import line is: @pankod/refine-antd/dist/style.css
const oldImportValue = path.node.source.value?.toString() ?? "";
// getOldPackageName will return @pankod/refine-antd
const oldName = getOldPackageName(oldImportValue);
// getNewPackageName will return @refinedev/antd
const newName = getNewPackageName(oldName);
// getNewImportValue will return @refinedev/antd/dist/style.css
const newImportValue = getNewImportValue(oldImportValue);
config.addPackage(newName);
config.removePackage(oldName);
j(path).replaceWith(
j.exportNamedDeclaration(
path.node.declaration,
path.node.specifiers,
j.literal(newImportValue),
),
);
});
};
export const replacePankodImportsWithRefineDev = async (
j: JSCodeshift,
source: Collection,
) => {
renameImports(j, source);
renameExports(j, source);
};

View File

@@ -0,0 +1,48 @@
import { Collection, JSCodeshift } from "jscodeshift";
const COMPONENT_NAMES = [
"ShowButton",
"EditButton",
"DeleteButton",
"CloneButton",
"ListButton",
"RefreshButton",
"CreateButton",
];
const DEPRECATED_PROP_NAMES = ["resourceName", "resourceNameOrRouteName"];
const NEW_PROP_NAME = "resource";
export const resourceNameToResourceForButtons = (
j: JSCodeshift,
source: Collection,
) => {
// find all JSX elements that are named in COMPONENT_NAMES
const elements = source.find(j.JSXElement, {
openingElement: {
name: {
name: (name: string) => COMPONENT_NAMES.includes(name),
},
},
});
elements.forEach((path) => {
const attributes = path.node.openingElement.attributes;
if (!attributes) return;
// if they have a NEW_PROP_NAME attribute, skip them.
const hasNewAttribute = attributes.some(
(attribute) => attribute?.["name"]?.["name"] === NEW_PROP_NAME,
);
if (hasNewAttribute) return;
// if they have a metaData change it to meta.
path.node.openingElement.attributes.forEach((attribute) => {
if (DEPRECATED_PROP_NAMES.includes(attribute?.["name"]?.["name"])) {
attribute["name"]["name"] = NEW_PROP_NAME;
return;
}
});
});
};

View File

@@ -0,0 +1,86 @@
import { JSCodeshift, Collection, JSXAttribute } from "jscodeshift";
const legacyMap = {
"@pankod/refine-react-router-v6": "@pankod/refine-react-router-v6/legacy",
"@pankod/refine-nextjs-router": "@pankod/refine-nextjs-router/legacy",
"@pankod/refine-nextjs-router/app":
"@pankod/refine-nextjs-router/legacy-app",
"@pankod/refine-nextjs-router/pages":
"@pankod/refine-nextjs-router/legacy-pages",
"@pankod/refine-remix-router": "@pankod/refine-remix-router/legacy",
};
const oldRouterProp = "routerProvider";
const newRouterProp = "legacyRouterProvider";
const renameImport = (
j: JSCodeshift,
source: Collection,
from: string,
to: string,
) => {
source
.find(j.ImportDeclaration)
.filter((path) => path.node.source.value === from)
.forEach((path) => {
j(path).replaceWith(
j.importDeclaration(path.node.specifiers, j.literal(to)),
);
});
};
const renameExport = (
j: JSCodeshift,
source: Collection,
from: string,
to: string,
) => {
source
.find(j.ExportNamedDeclaration)
.filter((path) => path.node.source && path.node.source.value === from)
.forEach((path) => {
j(path).replaceWith(
j.exportNamedDeclaration(
path.node.declaration,
path.node.specifiers,
j.literal(to),
),
);
});
};
const renameProp = (
j: JSCodeshift,
source: Collection,
from: string,
to: string,
) => {
source
.find(j.JSXOpeningElement, { name: { name: "Refine" } })
.forEach((path) => {
const props = path.node.attributes;
const propIndex = props.findIndex(
(prop) => (prop as JSXAttribute)?.name?.name === from,
);
if (propIndex !== -1) {
const prop = props[propIndex];
if ((prop as JSXAttribute)?.name) {
if ("name" in prop) {
prop.name.name = to;
}
}
}
});
};
export const routerToLegacyRouter = (j: JSCodeshift, source: Collection) => {
Object.entries(legacyMap).forEach(([from, to]) => {
renameImport(j, source, from, to);
renameExport(j, source, from, to);
});
renameProp(j, source, oldRouterProp, newRouterProp);
};

View File

@@ -0,0 +1,121 @@
import { Collection, JSCodeshift } from "jscodeshift";
import { CONFIG_FILE_NAME, CodemodConfig } from "../../helpers";
import { separateImports } from "../../helpers";
import {
exported,
rename,
renameToDefault,
other,
} from "../../definitions/separated-imports/antd";
const REFINE_ANTD_PATH = "@pankod/refine-antd";
const ANTD_PATH = "antd";
const ANTD_VERSION = "^5.0.5";
const ANTD_ICONS_PATH = "@ant-design/icons";
const ANTD_ICONS_VERSION = "^5.0.1";
export const separateImportsAntD = (j: JSCodeshift, source: Collection) => {
const config = new CodemodConfig(CONFIG_FILE_NAME);
separateImports({
j,
source,
imports: exported,
renameImports: rename,
renameToDefault: renameToDefault,
otherImports: other,
currentLibName: REFINE_ANTD_PATH,
nextLibName: ANTD_PATH,
});
let addIcons = false;
const addAntd =
source.find(j.ImportDeclaration, {
source: {
value: ANTD_PATH,
},
}).length > 0;
// check Icons import
const refineImport = source.find(j.ImportDeclaration, {
source: {
value: REFINE_ANTD_PATH,
},
});
refineImport.replaceWith((p) => {
for (const item of p.node.specifiers) {
if (item.local.name === "Icons") {
// flag for adding `@antd-design/icons` dependency
addIcons = true;
// add new icon namespace import
source
.find(j.ImportDeclaration, {
source: {
value: REFINE_ANTD_PATH,
},
})
.forEach((path, i) => {
if (i === 0) {
path.insertAfter(
j.importDeclaration(
[
j.importNamespaceSpecifier(
j.identifier("Icons"),
),
],
j.literal(ANTD_ICONS_PATH),
),
);
}
});
}
}
p.node.specifiers = p.node.specifiers.filter(
(p) => p.local.name !== "Icons",
);
return p.node;
});
if (addIcons) {
config.addPackage(ANTD_ICONS_PATH, ANTD_ICONS_VERSION);
// add comment to antd-icons import
source
.find(j.ImportDeclaration, {
source: {
value: ANTD_ICONS_PATH,
},
})
.forEach((path) => {
path.node.comments = [
{
type: "CommentLine",
value: ` It is recommended to use explicit import as seen below to reduce bundle size.`,
},
{
type: "CommentLine",
value: ` import { IconName } from "@ant-design/icons";`,
},
];
});
}
if (addAntd) {
config.addPackage(ANTD_PATH, ANTD_VERSION);
}
// remove empty imports
source
.find(j.ImportDeclaration, {
source: {
value: REFINE_ANTD_PATH,
},
})
.filter((path) => path.node.specifiers.length === 0)
.remove();
};

View File

@@ -0,0 +1,29 @@
import { Collection, JSCodeshift } from "jscodeshift";
import {
CONFIG_FILE_NAME,
CodemodConfig,
separateImports,
} from "../../helpers";
import { exported, rename } from "../../definitions/separated-imports/chakra";
export const separateImportsChakra = (j: JSCodeshift, source: Collection) => {
const config = new CodemodConfig(CONFIG_FILE_NAME);
if (
source.find(j.ImportDeclaration, {
source: { value: "@pankod/refine-chakra-ui" },
}).length > 0
) {
config.addPackage("@chakra-ui/react", "^2.5.1");
}
separateImports({
j,
source,
imports: exported,
renameImports: rename,
otherImports: {},
currentLibName: "@pankod/refine-chakra-ui",
nextLibName: "@chakra-ui/react",
});
};

View File

@@ -0,0 +1,37 @@
import { Collection, JSCodeshift } from "jscodeshift";
import {
CONFIG_FILE_NAME,
CodemodConfig,
separateImports,
} from "../../helpers";
import {
exported,
rename,
other,
} from "../../definitions/separated-imports/mantine";
export const separateImportsMantine = (j: JSCodeshift, source: Collection) => {
const config = new CodemodConfig(CONFIG_FILE_NAME);
if (
source.find(j.ImportDeclaration, {
source: { value: "@pankod/refine-mantine" },
}).length > 0
) {
config.addPackage("@mantine/core", "^5.10.4");
config.addPackage("@mantine/hooks", "^5.10.4");
config.addPackage("@mantine/form", "^5.10.4");
config.addPackage("@mantine/notifications", "^5.10.4");
config.addPackage("@emotion/react", "^11.8.2");
}
separateImports({
j,
source,
imports: exported,
renameImports: rename,
otherImports: other,
currentLibName: "@pankod/refine-mantine",
nextLibName: "@mantine/core",
});
};

View File

@@ -0,0 +1,35 @@
import { Collection, JSCodeshift } from "jscodeshift";
import { exported } from "../../definitions/separated-imports/mui";
import {
CONFIG_FILE_NAME,
CodemodConfig,
separateImports,
} from "../../helpers";
export const separateImportsMUI = (j: JSCodeshift, source: Collection) => {
const config = new CodemodConfig(CONFIG_FILE_NAME);
if (
source.find(j.ImportDeclaration, {
source: { value: "@pankod/refine-mui" },
}).length > 0
) {
config.addPackage("@emotion/react", "^11.8.2");
config.addPackage("@emotion/styled", "^11.8.1");
config.addPackage("@mui/lab", "^5.0.0-alpha.85");
config.addPackage("@mui/material", "^5.8.6");
config.addPackage("@mui/x-data-grid", "^5.12.1");
}
separateImports({
j,
source,
imports: ["MuiList"],
renameImports: {
MuiList: "List",
},
otherImports: exported,
currentLibName: "@pankod/refine-mui",
nextLibName: "@mui/material",
});
};

View File

@@ -0,0 +1,39 @@
import { Collection, JSCodeshift } from "jscodeshift";
import { exported } from "../../definitions/separated-imports/react-hook-form";
import {
CONFIG_FILE_NAME,
CodemodConfig,
separateImports,
} from "../../helpers";
const REFINE_LIB_PATH = "@pankod/refine-react-hook-form";
const REACT_HOOK_FORM_PATH = "react-hook-form";
const REACT_HOOK_FORM_VERSION = "^7.30.0";
export const separateImportsReactHookForm = (
j: JSCodeshift,
source: Collection,
) => {
const config = new CodemodConfig(CONFIG_FILE_NAME);
separateImports({
j,
source,
imports: exported,
renameImports: {},
otherImports: {},
currentLibName: REFINE_LIB_PATH,
nextLibName: REACT_HOOK_FORM_PATH,
});
// if use `react-hook-form` add package.json
const reactQuery = source.find(j.ImportDeclaration, {
source: {
value: REACT_HOOK_FORM_PATH,
},
});
if (reactQuery.length) {
config.addPackage(REACT_HOOK_FORM_PATH, REACT_HOOK_FORM_VERSION);
}
};

View File

@@ -0,0 +1,39 @@
import { Collection, JSCodeshift } from "jscodeshift";
import { exported } from "../../definitions/separated-imports/react-query";
import {
CONFIG_FILE_NAME,
CodemodConfig,
separateImports,
} from "../../helpers";
const REFINE_LIB_PATH = "@pankod/refine-core";
const REACT_QUERY_PATH = "@tanstack/react-query";
const REACT_QUERY_VERSION = "^4.10.1";
export const separateImportsReactQuery = (
j: JSCodeshift,
source: Collection,
) => {
const config = new CodemodConfig(CONFIG_FILE_NAME);
separateImports({
j,
source,
imports: exported,
renameImports: {},
otherImports: {},
currentLibName: REFINE_LIB_PATH,
nextLibName: REACT_QUERY_PATH,
});
// if use `@tanstack/react-query` add package.json
const reactQuery = source.find(j.ImportDeclaration, {
source: {
value: REACT_QUERY_PATH,
},
});
if (reactQuery.length) {
config.addPackage(REACT_QUERY_PATH, REACT_QUERY_VERSION);
}
};

View File

@@ -0,0 +1,32 @@
import { Collection, JSCodeshift } from "jscodeshift";
import { exported } from "../../definitions/separated-imports/react-router-v6";
import {
CONFIG_FILE_NAME,
CodemodConfig,
separateImports,
} from "../../helpers";
export const separateImportsReactRouterV6 = (
j: JSCodeshift,
source: Collection,
) => {
const config = new CodemodConfig(CONFIG_FILE_NAME);
if (
source.find(j.ImportDeclaration, {
source: { value: "@pankod/refine-react-router-v6" },
}).length > 0
) {
config.addPackage("react-router-dom", "^6.8.1");
}
separateImports({
j,
source,
imports: exported,
renameImports: {},
otherImports: {},
currentLibName: "@pankod/refine-react-router-v6",
nextLibName: "react-router-dom",
});
};

View File

@@ -0,0 +1,32 @@
import { Collection, JSCodeshift } from "jscodeshift";
import { exported } from "../../definitions/separated-imports/react-table";
import {
CONFIG_FILE_NAME,
CodemodConfig,
separateImports,
} from "../../helpers";
export const separateImportsReactTable = (
j: JSCodeshift,
source: Collection,
) => {
const config = new CodemodConfig(CONFIG_FILE_NAME);
if (
source.find(j.ImportDeclaration, {
source: { value: "@pankod/refine-react-table" },
}).length > 0
) {
config.addPackage("@tanstack/react-table", "^8.2.6");
}
separateImports({
j,
source,
imports: exported,
renameImports: {},
otherImports: {},
currentLibName: "@pankod/refine-react-table",
nextLibName: "@tanstack/react-table",
});
};

View File

@@ -0,0 +1,94 @@
import { JSCodeshift, Collection } from "jscodeshift";
const REFINE_ANTD_PATH = "@pankod/refine-antd";
const REFINE_MUI_PATH = "@pankod/refine-mui";
const REFINE_CORE_PATH = "@pankod/refine-core";
const ANTD_IMPORTS_TO_MOVE_CORE = ["useMenu"];
const MUI_IMPORTS_TO_MOVE_CORE = ["useMenu"];
const moveImports = (
j: JSCodeshift,
source: Collection,
importNamesToMove: string[],
fromModule: string,
toModule: string,
) => {
importNamesToMove.forEach((importName) => {
// get the import declaration to be moved
const importsFromModule = source
.find(j.ImportDeclaration)
.filter((path) => path.node.source.value === fromModule)
.find(j.ImportSpecifier);
// filter the imports to be moved
const importsToBeMoved = importsFromModule.filter(
(path) =>
path.node.imported.name === importName ||
path.node.local?.name === importName,
);
if (!importsToBeMoved?.length) return;
importsToBeMoved.forEach((importToMove) => {
// get the import declaration of the import to move
const importsToModule = source
.find(j.ImportDeclaration)
.filter((path) => path.node.source.value === toModule);
// if there is no import declaration for the import to move, create import declaration and add it to the top of the file.
if (!importsToModule?.length) {
source
.get()
.node.program.body.unshift(
j.importDeclaration(
[importToMove.get().node],
j.stringLiteral(toModule),
),
);
// remove the moved import
j(importToMove).remove();
return;
}
// add new import from importsToBeMoved to the existing import declaration.
// we select the first import declaration if there are multiple import declarations.
const importTo = importsToModule.at(0).paths().at(0).get();
j(importTo).replaceWith(
j.importDeclaration(
[...importTo.node.specifiers, importToMove.get().node],
importTo.node.source,
),
);
// remove the moved import
j(importToMove).remove();
});
});
// remove empty import declarations after moving imports e.g. import { } from "@pankod/refine-antd"
source
.find(j.ImportDeclaration)
.filter((path) => path.node.source.value === fromModule)
.filter((path) => !path.node.specifiers?.length)
.forEach((path) => j(path).remove());
};
export const useMenuToCore = (j: JSCodeshift, source: Collection) => {
moveImports(
j,
source,
ANTD_IMPORTS_TO_MOVE_CORE,
REFINE_ANTD_PATH,
REFINE_CORE_PATH,
);
moveImports(
j,
source,
MUI_IMPORTS_TO_MOVE_CORE,
REFINE_MUI_PATH,
REFINE_CORE_PATH,
);
};