@strapi/codemods
Advanced tools
Comparing version 1.0.2 to 1.1.0
@@ -10,3 +10,4 @@ // Node.js core | ||
const { migratePlugin, migrateApiFolder, migrateDependencies } = v4.migrationHelpers; | ||
const { migratePlugin, migrateApiFolder, migrateDependencies, migrateApplicationFolderStructure } = | ||
v4.migrationHelpers; | ||
@@ -21,3 +22,3 @@ // Global utils | ||
logger.error(`${chalk.yellow(resolve(path))} does not exist`); | ||
process.exit(1) | ||
process.exit(1); | ||
} | ||
@@ -58,2 +59,3 @@ | ||
await migrateDependencies(projectPath); | ||
await migrateApplicationFolderStructure(projectPath); | ||
await migrateApiFolder(projectPath); | ||
@@ -60,0 +62,0 @@ }; |
@@ -18,3 +18,3 @@ const { resolve } = require('path'); | ||
try { | ||
const { stdout } = await execa('git', ['status', '--porcelain']); | ||
const { stdout } = await execa('git', [`--git-dir=${path}/.git`, `--work-tree=${path}`, 'status', '--porcelain']); | ||
if (stdout.length) | ||
@@ -21,0 +21,0 @@ throw Error( |
@@ -1,26 +0,28 @@ | ||
module.exports = [ | ||
{ | ||
method: 'GET', | ||
path: '/test', | ||
handler: 'test.index', | ||
config: { | ||
policies: [], | ||
module.exports = { | ||
routes: [ | ||
{ | ||
method: 'GET', | ||
path: '/test', | ||
handler: 'test.index', | ||
config: { | ||
policies: [], | ||
}, | ||
}, | ||
}, | ||
{ | ||
method: 'POST', | ||
path: '/test/create', | ||
handler: 'test.create', | ||
config: { | ||
policies: [], | ||
{ | ||
method: 'POST', | ||
path: '/test/create', | ||
handler: 'test.create', | ||
config: { | ||
policies: [], | ||
}, | ||
}, | ||
}, | ||
{ | ||
method: 'PUT', | ||
path: '/test/:id', | ||
handler: 'test.update', | ||
config: { | ||
policies: [], | ||
{ | ||
method: 'PUT', | ||
path: '/test/:id', | ||
handler: 'test.update', | ||
config: { | ||
policies: [], | ||
}, | ||
}, | ||
}, | ||
]; | ||
], | ||
}; |
@@ -5,2 +5,9 @@ jest.mock('../convert-models-to-content-types', () => jest.fn()); | ||
jest.mock('../../utils/run-jscodeshift', () => jest.fn()); | ||
jest.mock('../update-api-folder-structure/utils', () => ({ | ||
cleanEmptyDirectories: jest.fn(() => Promise.resolve()), | ||
getDirsAtPath: jest.fn(() => [ | ||
{ name: 'test', isDirectory: jest.fn(() => true) }, | ||
{ name: 'test-two', isDirectory: jest.fn(() => true) }, | ||
]), | ||
})); | ||
@@ -20,7 +27,2 @@ const { join, resolve } = require('path'); | ||
jest.spyOn(console, 'log').mockImplementation(() => {}); | ||
fs.readdir.mockReturnValueOnce([ | ||
{ name: 'test', isDirectory: jest.fn(() => true) }, | ||
{ name: 'test-two', isDirectory: jest.fn(() => true) }, | ||
{ name: 'test.js', isDirectory: jest.fn(() => false) }, | ||
]); | ||
}); | ||
@@ -32,3 +34,3 @@ | ||
it('copies the v3 api to src directory', async () => { | ||
it('copies the v3 api to a v3 directory for safe keeping', async () => { | ||
const appPath = 'test-dir'; | ||
@@ -38,6 +40,16 @@ | ||
const expectedV4Path = join(resolve(appPath), 'src', 'api-copy'); | ||
expect(fs.copy).toHaveBeenCalledWith(join(resolve(appPath), 'api'), expectedV4Path); | ||
const expectedv3CopyPath = join(resolve(appPath), 'v3', 'api'); | ||
expect(fs.copy).toHaveBeenCalledWith(join(resolve(appPath), 'api'), expectedv3CopyPath); | ||
}); | ||
it('moves the v3 api to v4 src directory', async () => { | ||
const appPath = 'test-dir'; | ||
await updateApiFolderStructure(appPath); | ||
const expectedV4Path = join(resolve(appPath), 'src', 'api'); | ||
expect(fs.move).toHaveBeenCalledWith(join(resolve(appPath), 'api'), expectedV4Path); | ||
}); | ||
it('converts models to content types', async () => { | ||
@@ -48,4 +60,8 @@ const appPath = 'test-dir'; | ||
const expectedV4Path = join(resolve(appPath), 'src', 'api-copy'); | ||
const expectedV4Path = join(resolve(appPath), 'src', 'api'); | ||
const expectedv4ExtensionsPath = join(resolve(appPath), 'src', 'extensions'); | ||
expect(updateContentTypes).toBeCalled(); | ||
expect(updateContentTypes.mock.calls).toEqual([ | ||
[join(expectedv4ExtensionsPath, 'test')], | ||
[join(expectedv4ExtensionsPath, 'test-two')], | ||
[join(expectedV4Path, 'test')], | ||
@@ -61,6 +77,6 @@ [join(expectedV4Path, 'test-two')], | ||
const expectedV4Path = join(resolve(appPath), 'src', 'api-copy'); | ||
const expectedV4Path = join(resolve(appPath), 'src', 'api'); | ||
expect(updateRoutes.mock.calls).toEqual([ | ||
[join(expectedV4Path, 'test'), 'test'], | ||
[join(expectedV4Path, 'test-two'), 'test-two'], | ||
[join(expectedV4Path, 'test'), 'test', 'test'], | ||
[join(expectedV4Path, 'test-two'), 'test-two', 'test-two'], | ||
]); | ||
@@ -74,3 +90,3 @@ }); | ||
const expectedV4Path = join(resolve(appPath), 'src', 'api-copy'); | ||
const expectedV4Path = join(resolve(appPath), 'src', 'api'); | ||
expect(updatePolicies.mock.calls).toEqual([ | ||
@@ -87,3 +103,3 @@ [join(expectedV4Path, 'test')], | ||
const expectedV4Path = join(resolve(appPath), 'src', 'api-copy'); | ||
const expectedV4Path = join(resolve(appPath), 'src', 'api'); | ||
expect(runJscodeshift.mock.calls).toEqual([ | ||
@@ -90,0 +106,0 @@ [join(expectedV4Path, 'test', 'services'), 'convert-object-export-to-function'], |
/** | ||
* Migrate API folder structure to v4 | ||
*/ | ||
const { join } = require('path'); | ||
@@ -10,3 +9,5 @@ const fs = require('fs-extra'); | ||
const { isPlural, isSingular } = pluralize; | ||
const logger = require('../../global/utils/logger'); | ||
const getRelationObject = require('./get-relation-object'); | ||
@@ -29,3 +30,3 @@ /** | ||
const v4SchemaJsonPath = join(apiPath, 'content-types', contentTypeName, 'schema.json'); | ||
try { | ||
@@ -45,2 +46,49 @@ // Read the settings.json file | ||
_.set(schemaJson, 'info', infoUpdate); | ||
if (schemaJson.attributes) { | ||
Object.entries(schemaJson.attributes).forEach(([key, attribute]) => { | ||
// Not a relation, return early | ||
if (!attribute.via && !attribute.collection && !attribute.model) return; | ||
if ( | ||
attribute.plugin === 'upload' && | ||
(attribute.model === 'file' || attribute.collection === 'file') | ||
) { | ||
// Handle the Media Plugin | ||
attribute = { | ||
type: 'media', | ||
allowedTypes: attribute.allowedTypes, | ||
multiple: _.has(attribute, 'collection'), | ||
required: attribute.required, | ||
private: attribute.private, | ||
}; | ||
} else if (attribute.via && attribute.model && isSingular(attribute.via)) { | ||
// One-To-One | ||
attribute = getRelationObject('oneToOne', { ...attribute, inversed: true }); | ||
} else if (attribute.model && !attribute.via && !attribute.collection) { | ||
// One-To-One (One-Way) | ||
attribute = getRelationObject('oneToOne', { ...attribute, inversed: false }); | ||
} else if (attribute.via && attribute.model && isPlural(attribute.via)) { | ||
// Many-To-One | ||
attribute = getRelationObject('manyToOne', { ...attribute, inversed: true }); | ||
} else if (attribute.via && attribute.collection && isPlural(attribute.via)) { | ||
// Many-To-Many | ||
attribute = getRelationObject('manyToMany', { | ||
...attribute, | ||
inversed: attribute.dominant, | ||
}); | ||
} else if (attribute.collection && !attribute.via && !attribute.model) { | ||
// Many-Way | ||
attribute = getRelationObject('oneToMany', attribute); | ||
} else if (attribute.via && attribute.collection) { | ||
// One-To-Many | ||
attribute = getRelationObject('oneToMany', { ...attribute, inversed: false }); | ||
} else { | ||
logger.warn(`unknown relation type, please fix manually: ${key}`); | ||
} | ||
_.set(schemaJson, `attributes.${key}`, attribute); | ||
}); | ||
} | ||
// Create the new content-types/api/schema.json file | ||
@@ -47,0 +95,0 @@ await fs.ensureFile(v4SchemaJsonPath); |
const migrateApiFolder = require('./update-api-folder-structure'); | ||
const migrateDependencies = require('./update-package-dependencies'); | ||
const migratePlugin = require('./update-plugin-folder-structure'); | ||
const migrateApplicationFolderStructure = require('./update-application-folder-structure'); | ||
@@ -9,2 +10,3 @@ module.exports = { | ||
migratePlugin, | ||
migrateApplicationFolderStructure, | ||
}; |
@@ -13,3 +13,3 @@ const { join } = require('path'); | ||
*/ | ||
module.exports = async (apiPath, apiName) => { | ||
module.exports = async (apiPath, apiName, renamedFrom) => { | ||
const v3RoutePath = join(apiPath, 'config', 'routes.json'); | ||
@@ -34,4 +34,9 @@ const v4RoutePath = join(apiPath, 'routes', `${apiName}.js`); | ||
const renamedRoutes = updatedRoutes.map((route) => { | ||
route.handler = route.handler.replace(renamedFrom, apiName); | ||
return route; | ||
}); | ||
// Transform objects to strings | ||
const routesToString = inspect(updatedRoutes, { depth: Infinity }); | ||
const routesToString = inspect({ routes: renamedRoutes }, { depth: Infinity }); | ||
@@ -38,0 +43,0 @@ // Export routes from create js file |
{ | ||
"name": "@strapi/codemods", | ||
"version": "1.0.2", | ||
"version": "1.1.0", | ||
"main": "bin/cli.js", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
84151
82
2257
32