UNPKG

sanity

Version:

Sanity is a real-time content infrastructure with a scalable, hosted backend featuring a Graph Oriented Query Language (GROQ), asset pipelines and fast edge caches

116 lines (99 loc) 3.48 kB
import {readdir} from 'node:fs/promises' import path from 'node:path' import {type CliCommandDefinition} from '@sanity/cli' import {type Migration} from '@sanity/migrate' import {Table} from 'console-table-printer' import {register} from 'esbuild-register/dist/node' import {MIGRATION_SCRIPT_EXTENSIONS, MIGRATIONS_DIRECTORY} from './constants' import {isLoadableMigrationScript, resolveMigrationScript} from './utils/resolveMigrationScript' const helpText = `` const listMigrationCommand: CliCommandDefinition = { name: 'list', group: 'migration', signature: '', helpText, description: 'List available migrations', action: async (_, context) => { const {workDir, output, chalk} = context try { const migrations = await resolveMigrations(workDir) if (migrations.length === 0) { output.print('No migrations found in migrations folder of the project') output.print( `\nRun ${chalk.green(`\`sanity migration create <NAME>\``)} to create a new migration`, ) return } const table = new Table({ title: `Found ${migrations.length} migrations in project`, columns: [ {name: 'id', title: 'ID', alignment: 'left'}, {name: 'title', title: 'Title', alignment: 'left'}, ], }) migrations.forEach((definedMigration) => { table.addRow({id: definedMigration.id, title: definedMigration.migration.title}) }) table.printTable() output.print('\nRun `sanity migration run <ID>` to run a migration') } catch (error) { if (error.code === 'ENOENT') { output.print('No migrations folder found in the project') output.print( `\nRun ${chalk.green(`\`sanity migration create <NAME>\``)} to create a new migration`, ) return } throw new Error(`An error occurred while listing migrations: ${error.message}`) } }, } /** * A resolved migration, where you are guaranteed that the migration file exists * * @internal */ export interface ResolvedMigration { id: string migration: Migration } /** * Resolves all migrations in the studio working directory * * @param workDir - The studio working directory * @returns Array of migrations and their respective paths * @internal */ export async function resolveMigrations(workDir: string): Promise<ResolvedMigration[]> { let unregister if (!__DEV__) { unregister = register({ target: `node${process.version.slice(1)}`, }).unregister } const migrationsDir = path.join(workDir, MIGRATIONS_DIRECTORY) const migrationEntries = await readdir(migrationsDir, {withFileTypes: true}) const migrations: ResolvedMigration[] = [] for (const entry of migrationEntries) { const entryName = entry.isDirectory() ? entry.name : removeMigrationScriptExtension(entry.name) const candidates = resolveMigrationScript(workDir, entryName).filter(isLoadableMigrationScript) for (const candidate of candidates) { migrations.push({ id: entryName, migration: candidate.mod.default, }) } } if (unregister) { unregister() } return migrations } function removeMigrationScriptExtension(fileName: string) { // Remove `.ts`, `.js` etc from the end of a filename return MIGRATION_SCRIPT_EXTENSIONS.reduce( (name, ext) => (name.endsWith(`.${ext}`) ? path.basename(name, `.${ext}`) : name), fileName, ) } export default listMigrationCommand