mirror of
https://github.com/strapi/strapi.git
synced 2025-07-10 10:33:53 +00:00
321 lines
7.7 KiB
TypeScript
321 lines
7.7 KiB
TypeScript
import { Transform, JSCodeshift, Collection } from 'jscodeshift';
|
|
|
|
/*
|
|
|
|
This codemod transforms @strapi/utils imports to change method calls to match the new public interface.
|
|
It will also warn about removed functions to avoid breaking user code.
|
|
|
|
ESM
|
|
|
|
Before:
|
|
|
|
import * as utils from '@strapi/utils';
|
|
|
|
utils.nameToSlug();
|
|
|
|
After:
|
|
|
|
import { strings } from '@strapi/utils';
|
|
|
|
strings.nameToSlug();
|
|
|
|
---
|
|
ESM
|
|
|
|
Before:
|
|
|
|
import { nameToSlug } from '@strapi/utils';
|
|
|
|
nameToSlug();
|
|
|
|
After:
|
|
|
|
import { strings } from '@strapi/utils';
|
|
|
|
strings.nameToSlug();
|
|
|
|
---
|
|
|
|
Common JS
|
|
|
|
Before:
|
|
|
|
const utils = require('@strapi/utils');
|
|
|
|
utils.nameToSlug();
|
|
|
|
After:
|
|
|
|
const { strings } = require('@strapi/utils');
|
|
|
|
strings.nameToSlug();
|
|
|
|
---
|
|
Common JS
|
|
|
|
Before:
|
|
|
|
const { nameToSlug } = require('@strapi/utils');
|
|
|
|
nameToSlug();
|
|
|
|
After:
|
|
|
|
const { strings } = require('@strapi/utils');
|
|
|
|
strings.nameToSlug();
|
|
|
|
*/
|
|
|
|
const changes = {
|
|
strings: {
|
|
nameToSlug: 'nameToSlug',
|
|
nameToCollectionName: 'nameToCollectionName',
|
|
stringEquals: 'isEqual',
|
|
isCamelCase: 'isCamelCase',
|
|
isKebabCase: 'isKebabCase',
|
|
toKebabCase: 'toKebabCase',
|
|
toRegressedEnumValue: 'toRegressedEnumValue',
|
|
startsWithANumber: 'startsWithANumber',
|
|
joinBy: 'joinBy',
|
|
},
|
|
arrays: {
|
|
stringIncludes: 'includesString',
|
|
},
|
|
objects: {
|
|
keysDeep: 'keysDeep',
|
|
},
|
|
dates: {
|
|
generateTimestampCode: 'timestampCode',
|
|
},
|
|
async: {
|
|
pipeAsync: 'pipe',
|
|
mapAsync: 'map',
|
|
reduceAsync: 'reduce',
|
|
},
|
|
};
|
|
|
|
const removed = [
|
|
'getCommonBeginning',
|
|
'templateConfiguration',
|
|
'removeUndefined',
|
|
'getConfigUrls',
|
|
'getAbsoluteAdminUrl',
|
|
'getAbsoluteServerUrl',
|
|
'forEachAsync',
|
|
];
|
|
|
|
const transformImports = (root: Collection, j: JSCodeshift) => {
|
|
root
|
|
.find(j.ImportDeclaration, {
|
|
source: { value: '@strapi/utils' },
|
|
})
|
|
.forEach((path) => {
|
|
if (!j.ImportDeclaration.check(path.value)) {
|
|
return;
|
|
}
|
|
|
|
path.value.specifiers.forEach((specifier) => {
|
|
if (!j.ImportSpecifier.check(specifier)) {
|
|
return false;
|
|
}
|
|
|
|
if (removed.includes(specifier.imported.name)) {
|
|
console.warn(
|
|
`Function "${specifier.imported.name}" was removed. You will have to remove it from your code.`
|
|
);
|
|
|
|
return false;
|
|
}
|
|
});
|
|
|
|
for (const primitive of Object.keys(changes)) {
|
|
const functions = Object.keys(changes[primitive]);
|
|
|
|
const specifiersToRefactor = path.value.specifiers.filter((specifier) => {
|
|
return j.ImportSpecifier.check(specifier) && functions.includes(specifier.imported.name);
|
|
});
|
|
|
|
if (specifiersToRefactor.length > 0) {
|
|
path.value.specifiers.unshift(j.importSpecifier(j.identifier(primitive)));
|
|
|
|
specifiersToRefactor.forEach((specifier) => {
|
|
const index = path.value.specifiers.indexOf(specifier);
|
|
path.value.specifiers.splice(index, 1);
|
|
});
|
|
}
|
|
}
|
|
|
|
if (path.value.specifiers?.length === 0) {
|
|
j(path).remove();
|
|
}
|
|
});
|
|
|
|
root.find(j.ImportNamespaceSpecifier).forEach((specifierPath) => {
|
|
if (specifierPath.parent.value.source.value === '@strapi/utils') {
|
|
for (const primitive of Object.keys(changes)) {
|
|
const functions = Object.keys(changes[primitive]);
|
|
functions.forEach((funcName) => {
|
|
root
|
|
.find(j.CallExpression, {
|
|
callee: {
|
|
type: 'MemberExpression',
|
|
property: {
|
|
type: 'Identifier',
|
|
name: funcName,
|
|
},
|
|
object: {
|
|
type: 'Identifier',
|
|
name: specifierPath.value.local.name,
|
|
},
|
|
},
|
|
})
|
|
.replaceWith((path) => {
|
|
return j.callExpression(
|
|
j.memberExpression(
|
|
j.memberExpression(
|
|
j.identifier(specifierPath.value.local.name),
|
|
j.identifier(primitive)
|
|
),
|
|
j.identifier(changes[primitive][funcName])
|
|
),
|
|
path.value.arguments
|
|
);
|
|
});
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
root
|
|
.find(j.VariableDeclarator, {
|
|
init: {
|
|
callee: {
|
|
name: 'require',
|
|
},
|
|
arguments: [{ value: '@strapi/utils' }],
|
|
},
|
|
})
|
|
.forEach((path) => {
|
|
// destructured require
|
|
|
|
if (j.ObjectPattern.check(path.value.id)) {
|
|
const properties = path.value.id.properties;
|
|
|
|
properties?.forEach((property) => {
|
|
if (!j.ObjectProperty.check(property) || !j.Identifier.check(property.value)) {
|
|
return false;
|
|
}
|
|
|
|
if (removed.includes(property.value.name)) {
|
|
console.warn(
|
|
`Function "${property.value.name}" was removed. You will have to remove it from your code.`
|
|
);
|
|
|
|
return false;
|
|
}
|
|
});
|
|
|
|
for (const primitive of Object.keys(changes)) {
|
|
const functions = Object.keys(changes[primitive]);
|
|
|
|
const propertiesToRefactor = properties?.filter((property) => {
|
|
return (
|
|
j.ObjectProperty.check(property) &&
|
|
j.Identifier.check(property.value) &&
|
|
functions.includes(property.value.name)
|
|
);
|
|
});
|
|
|
|
if (propertiesToRefactor?.length > 0) {
|
|
const identifier = j.identifier(primitive);
|
|
|
|
properties?.unshift(
|
|
j.objectProperty.from({
|
|
key: identifier,
|
|
value: identifier,
|
|
shorthand: true,
|
|
})
|
|
);
|
|
|
|
propertiesToRefactor.forEach((property) => {
|
|
const index = properties?.indexOf(property);
|
|
properties?.splice(index, 1);
|
|
});
|
|
}
|
|
}
|
|
|
|
if (path.value.id.properties?.length === 0) {
|
|
j(path).remove();
|
|
}
|
|
}
|
|
|
|
// namespace require
|
|
if (path.value.id.type === 'Identifier') {
|
|
const identifier = path.value.id.name;
|
|
|
|
for (const primitive of Object.keys(changes)) {
|
|
const functions = Object.keys(changes[primitive]);
|
|
functions.forEach((funcName) => {
|
|
root
|
|
.find(j.CallExpression, {
|
|
callee: {
|
|
type: 'MemberExpression',
|
|
property: {
|
|
type: 'Identifier',
|
|
name: funcName,
|
|
},
|
|
object: {
|
|
type: 'Identifier',
|
|
name: identifier,
|
|
},
|
|
},
|
|
})
|
|
.replaceWith((path) => {
|
|
return j.callExpression(
|
|
j.memberExpression(
|
|
j.memberExpression(j.identifier(identifier), j.identifier(primitive)),
|
|
j.identifier(changes[primitive][funcName])
|
|
),
|
|
path.value.arguments
|
|
);
|
|
});
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
for (const primitive of Object.keys(changes)) {
|
|
const functions = Object.keys(changes[primitive]);
|
|
functions.forEach((funcName) => {
|
|
root
|
|
.find(j.CallExpression, {
|
|
callee: {
|
|
type: 'Identifier',
|
|
name: funcName,
|
|
},
|
|
})
|
|
.replaceWith((path) => {
|
|
if (j.Identifier.check(path.value.callee)) {
|
|
path.value.callee.name = changes[primitive][funcName];
|
|
return j.memberExpression(j.identifier(primitive), path.value);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
};
|
|
|
|
const transform: Transform = (file, api) => {
|
|
const j = api.jscodeshift;
|
|
|
|
const root = j(file.source);
|
|
|
|
transformImports(root, j);
|
|
|
|
return root.toSource();
|
|
};
|
|
|
|
export const parser = 'tsx';
|
|
|
|
export default transform;
|