feat: allow loading predefined migrations from proper exports (#9872)
Currently, predefined migrations can only be loaded if they are part of
one of our db adapters.
With this PR, plugins will be able to export their own predefined
migrations that can be created like this:
`pnpm payload migrate:create --file
@payloadcms/plugin-someplugin/someMigration`
with the plugin exporting it in their package.json:
```json
"exports": {
"./someMigration": {
"import": "./someMigration.mjs",
"types": "./someMigration.mjs",
"default": "./someMigration.mjs"
}
},
```
This commit is contained in:
@@ -21,11 +21,12 @@ export const getPredefinedMigration = async ({
|
||||
}): Promise<MigrationTemplateArgs> => {
|
||||
// Check for predefined migration.
|
||||
// Either passed in via --file or prefixed with '@payloadcms/db-mongodb/' for example
|
||||
if (file || migrationNameArg?.startsWith('@payloadcms/')) {
|
||||
// removes the package name from the migrationName.
|
||||
const migrationName = (file || migrationNameArg).split('/').slice(2).join('/')
|
||||
let cleanPath = path.join(dirname, `./predefinedMigrations/${migrationName}`)
|
||||
const importPath = file ?? migrationNameArg
|
||||
|
||||
if (importPath?.startsWith('@payloadcms/db-')) {
|
||||
// removes the package name from the migrationName.
|
||||
const migrationName = importPath.split('/').slice(2).join('/')
|
||||
let cleanPath = path.join(dirname, `./predefinedMigrations/${migrationName}`)
|
||||
if (fs.existsSync(`${cleanPath}.mjs`)) {
|
||||
cleanPath = `${cleanPath}.mjs`
|
||||
} else if (fs.existsSync(`${cleanPath}.js`)) {
|
||||
@@ -36,12 +37,15 @@ export const getPredefinedMigration = async ({
|
||||
})
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
cleanPath = cleanPath.replaceAll('\\', '/')
|
||||
const moduleURL = pathToFileURL(cleanPath)
|
||||
try {
|
||||
const { downSQL, imports, upSQL } = await eval(`import('${moduleURL.href}')`)
|
||||
return { downSQL, imports, upSQL }
|
||||
return {
|
||||
downSQL,
|
||||
imports,
|
||||
upSQL,
|
||||
}
|
||||
} catch (err) {
|
||||
payload.logger.error({
|
||||
err,
|
||||
@@ -49,6 +53,22 @@ export const getPredefinedMigration = async ({
|
||||
})
|
||||
process.exit(1)
|
||||
}
|
||||
} else if (importPath) {
|
||||
try {
|
||||
const { downSQL, imports, upSQL } = await eval(`import('${importPath}')`)
|
||||
return {
|
||||
downSQL,
|
||||
imports,
|
||||
upSQL,
|
||||
}
|
||||
} catch (_err) {
|
||||
if (importPath?.includes('/')) {
|
||||
// We can assume that the intent was to import a file, thus we throw an error.
|
||||
throw new Error(`Error importing migration file from ${importPath}`)
|
||||
}
|
||||
// Silently fail. If the migration cannot be imported, it will be created as a blank migration and the import path will be used as the migration name.
|
||||
return {}
|
||||
}
|
||||
}
|
||||
return {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user