Skip to main content
doc0blade47/drizzle-ormdocumentation home
Sign in

CLI Command Architecture

Last updated Oct 12, 2026100% grounded
Relevant source files

The following files were used as context for generating this wiki page:

Overview

The CLI command architecture of drizzle-kit orchestrates schema migrations, database introspection, direct synchronization, and local environment execution by wiring command definitions, argument parsing, runtime compilation, and interactive terminal interfaces together. Powered by Brocli entrypoints and Hanji terminal renderers, the command layer handles user execution flows across PostgreSQL, MySQL, SQLite, Turso, SingleStore, and Gel dialects. It bridges configuration validation utilities with migration generators and snapshot diffing tools, ensuring schema integrity and managing the complete lifecycle of database development workflows. Sources: drizzle-kit/src/cli/commands/migrate.ts:1-57, drizzle-kit/src/cli/index.ts:1-48, drizzle-kit/src/cli/schema.ts:1-113, drizzle-kit/src/cli/views.ts:1-16, drizzle-kit/src/cli/commands/utils.ts:33-102

Command Registration and Brocli Entrypoints

Brocli Command Execution and Entrypoint

The CLI entrypoint of drizzle-kit initializes command parsing and dispatching via the @drizzle-team/brocli package. The root execution runner run accepts an array of active schema commands along with legacy command aliases, passing configuration options such as the CLI name drizzle-kit and the version handler function.

run([generate, migrate, pull, push, studio, up, check, drop, exportRaw, ...legacy], {
	name: 'drizzle-kit',
	version: version,
});

Sources: drizzle-kit/src/cli/index.ts:45-48

The version check asynchronous function queries ormCoreVersions to inspect underlying package metadata, formatting both the drizzle-kit version string (from process.env.DRIZZLE_KIT_VERSION or defaulting to --) and the drizzle-orm npm version before printing the result via chalk.gray.

const version = async () => {
	const { npmVersion } = await ormCoreVersions();
	const ormVersion = npmVersion ? `drizzle-orm: v${npmVersion}` : '';
	const envVersion = process.env.DRIZZLE_KIT_VERSION;
	const kitVersion = envVersion ? `v${envVersion}` : '--';
	const versions = `drizzle-kit: ${kitVersion}\n${ormVersion}`;
	console.log(chalk.gray(versions), '\n');
};

Sources: drizzle-kit/src/cli/index.ts:6-13

Command Definitions and Legacy Aliases

Active schema operations are declared using Brocli's command function in schema.ts, establishing command names, option filters, argument transformations, and asynchronous handlers. To maintain backward compatibility during major upgrades, the CLI registers hidden legacy commands that intercept obsolete dialect-specific commands and output migration instructions pointing to upgrade documentation.

Legacy Command NameTarget ReplacementHidden Status
generate:pg, generate:mysql, generate:sqlitegeneratetrue
push:pg, push:mysql, push:sqlitepushtrue
introspect:pg, introspect:mysql, introspect:sqliteintrospecttrue
up:pg, up:mysql, up:sqliteuptrue
check:pg, check:mysql, check:sqlitechecktrue
const legacyCommand = (name: string, newName: string) => {
	return command({
		name,
		hidden: true,
		handler: () => {
			console.log(
				`This command is deprecated, please use updated '${newName}' command (see https://orm.drizzle.team/kit-docs/upgrade-21#how-to-migrate-to-0210)`,
			);
		},
	});
};
 
const legacy = [
	legacyCommand('generate:pg', 'generate'),
	legacyCommand('generate:mysql', 'generate'),
	legacyCommand('generate:sqlite', 'generate'),
	legacyCommand('push:pg', 'push'),
	legacyCommand('push:mysql', 'push'),
	legacyCommand('push:sqlite', 'push'),
	legacyCommand('introspect:pg', 'introspect'),
	legacyCommand('introspect:mysql', 'introspect'),
	legacyCommand('introspect:sqlite', 'introspect'),
	legacyCommand('up:pg', 'up'),
	legacyCommand('up:mysql', 'up'),
	legacyCommand('up:sqlite', 'up'),
	legacyCommand('check:pg', 'check'),
	legacyCommand('check:mysql', 'check'),
	legacyCommand('check:sqlite', 'check'),
];

Sources: drizzle-kit/src/cli/index.ts:15-43

Warning

Legacy commands are explicitly marked with hidden: true and execute a handler that prints a deprecation warning rather than performing database operations, requiring users to upgrade to the unified dialect-agnostic command syntax.

Version Assertions and Environment Validation

Before executing command handlers, drizzle-kit performs rigorous core version and dependency assertions to guarantee compatibility between the CLI toolkit and the installed ORM runtime. The assertOrmCoreVersion utility queries drizzle-orm/version for its compatibilityVersion and verifies that it matches the required API version constant 10.

const requiredApiVersion = 10;
export const assertOrmCoreVersion = async () => {
	try {
		const { compatibilityVersion } = await import('drizzle-orm/version');
 
		await import('drizzle-orm/relations');
 
		if (compatibilityVersion && compatibilityVersion === requiredApiVersion) {
			return;
		}
 
		if (!compatibilityVersion || compatibilityVersion < requiredApiVersion) {
			console.log(
				'This version of drizzle-kit requires newer version of drizzle-orm\nPlease update drizzle-orm package to the latest version 👍',
			);
		} else {
			console.log(
				'This version of drizzle-kit is outdated\nPlease update drizzle-kit package to the latest version 👍',
			);
		}
	} catch (e) {
		console.log('Please install latest version of drizzle-orm');
	}
	process.exit(1);
};

Sources: drizzle-kit/src/cli/utils.ts:77-101

Important

If compatibilityVersion is missing or less than 10, the process logs an update prompt and exits with code 1 to prevent schema corruption caused by mismatched serializer protocols.

Additional helper assertions validate environment preconditions, such as checking that Node.js version 18 or above is active when running Drizzle Studio via assertStudioNodeVersion, and verifying required peer packages with assertPackages or assertEitherPackage.

export const assertStudioNodeVersion = () => {
	if (semver.gte(process.version, '18.0.0')) return;
 
	err('Drizzle Studio requires NodeJS v18 or above');
	process.exit(1);
};

Sources: drizzle-kit/src/cli/utils.ts:16-21

Config Loading and Runtime Preparation

TSX Runtime Registration and ES5 Assertions

To support TypeScript configuration files and schema definitions without prior manual compilation, drizzle-kit initializes runtime TypeScript execution via tsx. The ensureTsxRegistered function checks whether Bun or Deno is the active global runtime environment; if neither is detected, it requires and registers tsx/cjs/api.

let tsxRegistered = false;
const ensureTsxRegistered = () => {
	if (tsxRegistered) return;
 
	const isBun = typeof (globalThis as any).Bun !== 'undefined';
	const isDeno = typeof (globalThis as any).Deno !== 'undefined';
	if (isBun || isDeno) {
		tsxRegistered = true;
		return;
	}
 
	const tsx = require('tsx/cjs/api');
	tsx.register();
	tsxRegistered = true;
};

Sources: drizzle-kit/src/cli/commands/utils.ts:79-93

Concurrency across asynchronous configuration loading is managed by an InMemoryMutex implementation (registerMutex), which serializes execution locks through safeRegister.

export class InMemoryMutex {
	private lockPromise: Promise<void> | null = null;
 
	async withLock<T>(fn: () => Promise<T>): Promise<T> {
		// Wait for any existing lock
		while (this.lockPromise) {
			await this.lockPromise;
		}
 
		let resolveLock: (() => void) | undefined;
		this.lockPromise = new Promise<void>((resolve) => {
			resolveLock = resolve;
		});
 
		try {
			return await fn();
		} finally {
			this.lockPromise = null;
			resolveLock!(); // non-null assertion: TS now knows it's definitely assigned
		}
	}
}

Sources: drizzle-kit/src/cli/commands/utils.ts:54-75

Before evaluating configuration files, the runtime runs assertES5 to inspect compiler target options. If an unsupported target such as es5 is encountered via configuration errors, the process logs a corrective instruction and exits.

const assertES5 = async () => {
	try {
		await import('./_es5');
	} catch (e: any) {
		if ('errors' in e && Array.isArray(e.errors) && e.errors.length > 0) {
			const es5Error = (e.errors as any[]).filter((it) => it.text?.includes(`("es5") is not supported yet`)).length > 0;
			if (es5Error) {
				console.log(
					error(
						`Please change compilerOptions.target from 'es5' to 'es6' or above in your tsconfig.json`,
					),
				);
				process.exit(1);
			}
		}
		console.error(e);
		process.exit(1);
	}
};

Sources: drizzle-kit/src/cli/commands/utils.ts:34-52

Caution

Next.js default target configurations set to es5 cannot be consumed by esbuild-register; drizzle-kit explicitly intercepts this error and terminates execution if compilerOptions.target is not elevated to es6 or above.

Parameter Transformation and Validation Bridges

Command options parsed from the CLI or configuration files are normalized through dedicated parameter preparation helpers in utils.ts and validated via schema bridges. For instance, prepareCheckParams inspects whether parameters originate from the CLI or an external configuration file, validating that out and dialect properties are present.

export const prepareCheckParams = async (
	options: {
		config?: string;
		dialect?: Dialect;
		out?: string;
	},
	from: 'cli' | 'config',
): Promise<{ out: string; dialect: Dialect }> => {
	const config = from === 'config'
		? await drizzleConfigFromFile(options.config as string | undefined)
		: options;
 
	if (!config.out || !config.dialect) {
		let text = `Please provide required params for AWS Data API driver:\n`;
		console.log(error(text));
		console.log(wrapParam('database', config.out));
		console.log(wrapParam('secretArn', config.dialect));
		process.exit(1);
	}
	return { out: config.out, dialect: config.dialect };
};

Sources: drizzle-kit/src/cli/commands/utils.ts:103-123

Similarly, prepareDropParams evaluates drop targets, explicitly rejecting the gel dialect by terminating the process with an error message.

export const prepareDropParams = async (
	options: {
		config?: string;
		out?: string;
		driver?: Driver;
		dialect?: Dialect;
	},
	from: 'cli' | 'config',
): Promise<{ out: string; bundle: boolean }> => {
	const config = from === 'config'
		? await drizzleConfigFromFile(options.config as string | undefined)
		: options;
 
	if (config.dialect === 'gel') {
		console.log(
			error(
				`You can't use 'drop' command with Gel dialect`,
			),
		);
		process.exit(1);
	}
 
	return { out: config.out || 'drizzle', bundle: config.driver === 'expo' };
};

Sources: drizzle-kit/src/cli/commands/utils.ts:125-148

The table below outlines core configuration validation outputs and error messages defined for connection requirements and parameter constraints across database dialects.

ContextError ConditionValidation Message
commonAmbiguous parametersYou can't use both --config and other cli options for {command} command
postgresMissing connection parametersEither "url" or "host", "database" are required for database connection
mysql / singlestoreInvalid driver optionOnly "mysql2" is available options for "--driver"
sqliteMissing driver parameterEither 'better-sqlite3', 'libsql', 'turso', 'expo', 'durable-sqlite' are available options for 'driver' param
studioUnspecified dialectPlease specify 'dialect' param in config, either of 'postgresql', 'mysql', 'sqlite', turso or singlestore
	ambiguousParams: (command: string) =>
		withStyle.error(
			`You can't use both --config and other cli options for ${command} command`,
		),
	schema: (command: string) => withStyle.error(`"--schema" is a required field for ${command} command`),
},
postgres: {
	connection: {
		required: () =>
			withStyle.error(
				`Either "url" or "host", "database" are required for database connection`,
			),
		awsDataApi: () =>
			withStyle.error(
				"You need to provide 'database', 'secretArn' and 'resourceArn' for Drizzle Kit to connect to AWS Data API",
			),
	},
},
mysql: {
	connection: {
		driver: () => withStyle.error(`Only "mysql2" is available options for "--driver"`),
		required: () =>
			withStyle.error(
				`Either "url" or "host", "database" are required for database connection`,
			),
	},
},
sqlite: {
	connection: {
		driver: () => {
			const listOfDrivers = sqliteDriversLiterals
				.map((it) => `'${it.value}'`)
				.join(', ');
			return withStyle.error(
				`Either ${listOfDrivers} are available options for 'driver' param`,
			);
		},
		url: (driver: string) =>
			withStyle.error(
				`"url" is a required option for driver "${driver}". You can read more about drizzle.config: https://orm.drizzle.team/kit-docs/config-reference`,
			),
		authToken: (driver: string) =>
			withStyle.error(
				`"authToken" is a required option for driver "${driver}". You can read more about drizzle.config: https://orm.drizzle.team/kit-docs/config-reference`,
			),
	},
	introspect: {},
	push: {},
},
singlestore: {
	connection: {
		driver: () => withStyle.error(`Only "mysql2" is available options for "--driver"`),
		required: () =>
			withStyle.error(
				`Either "url" or "host", "database" are required for database connection`,
			),
	},

Sources: drizzle-kit/src/cli/validations/outputs.ts:33-89

Migration Generation and Interactive Disambiguation

Migration Preparation and Snapshot Diffing

When executing migration generation via [[Migration Toolkit Schema]], drizzle-kit initializes dialect-specific migration preparation and snapshot diffing routines. The migration workflow validates output directories using assertV1OutFolder and prepares migration folders via prepareMigrationFolder to ensure journals and snapshots conform to active specifications Migration Toolkit Schema. Schema changes are calculated by comparing current schema definitions against previous serialized snapshots using dedicated differ applications such as applyPgSnapshotsDiff, applyMysqlSnapshotsDiff, applySqliteSnapshotsDiff, applyLibSQLSnapshotsDiff, and applySingleStoreSnapshotsDiff.

applyLibSQLSnapshotsDiff,
applyMysqlSnapshotsDiff,
applyPgSnapshotsDiff,
applySingleStoreSnapshotsDiff,
applySqliteSnapshotsDiff,

Sources: drizzle-kit/src/cli/commands/migrate.ts:23-27

Warning

Attempting to run migration generation or schema pushes with outdated V1 migration folders containing 14-digit numeric directory formats will cause assertV1OutFolder to immediately terminate the process with an error instructing the user to run drizzle-kit up Migration Toolkit Schema.

Interactive Conflict Disambiguation

When schema structural modifications introduce ambiguity—such as determining whether an object was renamed, moved between schemas, created, or deleted—resolver hooks prompt users interactively. The migration command module defines resolvers for schemas, tables, views, sequences, roles, policies, enums, and columns. For instance, schemasResolver invokes promptSchemasConflict, while tablesResolver, viewsResolver, and enumsResolver delegate to promptNamedWithSchemasConflict.

export const schemasResolver = async (
	input: ResolverInput<Table>,
): Promise<ResolverOutput<Table>> => {
	try {
		const { created, deleted, renamed } = await promptSchemasConflict(
			input.created,
			input.deleted,
		);
 
		return { created: created, deleted: deleted, renamed: renamed };
	} catch (e) {
		console.error(e);
		throw e;
	}
};
 
export const tablesResolver = async (
	input: ResolverInput<Table>,
): Promise<ResolverOutputWithMoved<Table>> => {
	try {
		const { created, deleted, moved, renamed } = await promptNamedWithSchemasConflict(
			input.created,
			input.deleted,
			'table',
		);
 
		return {
			created: created,
			deleted: deleted,
			moved: moved,
			renamed: renamed,
		};
	} catch (e) {
		console.error(e);
		throw e;
	}
};
 
export const viewsResolver = async (
	input: ResolverInput<View>,
): Promise<ResolverOutputWithMoved<View>> => {
	try {
		const { created, deleted, moved, renamed } = await promptNamedWithSchemasConflict(
			input.created,
			input.deleted,
			'view',
		);
 

Sources: drizzle-kit/src/cli/commands/migrate.ts:68-115

The table below lists the conflict resolver functions, their expected input types, and their corresponding output resolution signatures in the migration command architecture.

Resolver FunctionInput TypeOutput TypeConflict Prompt Routine
schemasResolverResolverInput<Table>ResolverOutput<Table>promptSchemasConflict
tablesResolverResolverInput<Table>ResolverOutputWithMoved<Table>promptNamedWithSchemasConflict
viewsResolverResolverInput<View>ResolverOutputWithMoved<View>promptNamedWithSchemasConflict
sequencesResolverResolverInput<Sequence>ResolverOutputWithMoved<Sequence>promptNamedWithSchemasConflict
roleResolverRolesResolverInput<Role>RolesResolverOutput<Role>promptNamedConflict
policyResolverTablePolicyResolverInput<Policy>TablePolicyResolverOutput<Policy>promptColumnsConflicts
enumsResolverResolverInput<Enum>ResolverOutputWithMoved<Enum>promptNamedWithSchemasConflict
columnsResolverColumnsResolverInput<Column>ColumnsResolverOutput<Column>promptColumnsConflicts
export const schemasResolver = async (
	input: ResolverInput<Table>,
): Promise<ResolverOutput<Table>> => {
	try {
		const { created, deleted, renamed } = await promptSchemasConflict(
			input.created,
			input.deleted,
		);
 
		return { created: created, deleted: deleted, renamed: renamed };
	} catch (e) {
		console.error(e);
		throw e;
	}
};
 
export const tablesResolver = async (
	input: ResolverInput<Table>,
): Promise<ResolverOutputWithMoved<Table>> => {
	try {
		const { created, deleted, moved, renamed } = await promptNamedWithSchemasConflict(
			input.created,
			input.deleted,
			'table',
		);
 
		return {
			created: created,
			deleted: deleted,
			moved: moved,
			renamed: renamed,
		};
	} catch (e) {
		console.error(e);
		throw e;
	}
};
 
export const viewsResolver = async (
	input: ResolverInput<View>,
): Promise<ResolverOutputWithMoved<View>> => {
	try {
		const { created, deleted, moved, renamed } = await promptNamedWithSchemasConflict(
			input.created,
			input.deleted,
			'view',
		);
 
		return {
			created: created,
			deleted: deleted,
			moved: moved,
			renamed: renamed,
		};
	} catch (e) {
		console.error(e);
		throw e;
	}
};
 
export const mySqlViewsResolver = async (
	input: ResolverInput<ViewSquashed & { schema: '' }>,
): Promise<ResolverOutputWithMoved<ViewSquashed>> => {
	try {
		const { created, deleted, moved, renamed } = await promptNamedWithSchemasConflict(
			input.created,
			input.deleted,
			'view',
		);
 
		return {
			created: created,
			deleted: deleted,
			moved: moved,
			renamed: renamed,
		};
	} catch (e) {
		console.error(e);
		throw e;
	}

Sources: drizzle-kit/src/cli/commands/migrate.ts:68-300

Schema Integrity Verification Workflow

Folder Preparation and Snapshot Validation

The check command handler verifies the structural integrity of migration snapshots stored in the output directory. It initiates folder inspection through prepareOutFolder, which ensures the meta subdirectory and _journal.json file exist, initializes a dry journal via dryJournal if missing, and collects all active snapshot file paths Migration Toolkit Schema.

export const checkHandler = (out: string, dialect: Dialect) => {
	const { snapshots } = prepareOutFolder(out, dialect);
	const report = validateWithReport(snapshots, dialect);

Sources: drizzle-kit/src/cli/commands/check.ts:4-6, drizzle-kit/src/utils.ts:75-113

Snapshot validation is performed by validateWithReport, which maps over each snapshot file and evaluates it against dialect-specific validation schemas provided by validatorForDialect.

DialectValidator SchemaTarget Version
postgresqlbackwardCompatiblePgSchema7
sqlitebackwardCompatibleSqliteSchema6
tursobackwardCompatibleSqliteSchema6
mysqlbackwardCompatibleMysqlSchema5
singlestorebackwardCompatibleSingleStoreSchema1
gelbackwardCompatibleGelSchema1
const validatorForDialect = (dialect: Dialect) => {
	switch (dialect) {
		case 'postgresql':
			return { validator: backwardCompatiblePgSchema, version: 7 };
		case 'sqlite':
			return { validator: backwardCompatibleSqliteSchema, version: 6 };
		case 'turso':
			return { validator: backwardCompatibleSqliteSchema, version: 6 };
		case 'mysql':
			return { validator: backwardCompatibleMysqlSchema, version: 5 };
		case 'singlestore':
			return { validator: backwardCompatibleSingleStoreSchema, version: 1 };
		case 'gel':
			return { validator: backwardCompatibleGelSchema, version: 1 };
	}
};

Sources: drizzle-kit/src/utils.ts:115-130

Caution

If a snapshot file contains a version number exceeding the validator's maximum supported version, validateWithReport immediately logs an unsupported version message and terminates execution via process.exit(0).

Validation Reporting and Collision Detection

The checkHandler function processes the report returned by validateWithReport to detect outdated files, malformed JSON data, and branching snapshot collisions. It evaluates three primary conditions before determining whether to abort execution:

  1. Non-latest snapshots: If report.nonLatest contains entries, it logs that each snapshot is outdated and instructs users to execute drizzle-kit up, exiting with code 1.
  2. Malformed data: If report.malformed contains entries, it logs malformed warnings for each failing file.
  3. Snapshot collisions: It inspects report.idsMap to locate parent IDs referenced by multiple child snapshots (it[1].snapshots.length > 1), reporting any branching lineage collisions.
if (report.nonLatest.length > 0) {
	console.log(
		report.nonLatest
			.map((it) => {
				return `${it} is not of the latest version, please run "drizzle-kit up"`;
			})
			.join('\n'),
	);
	process.exit(1);
}
 
if (report.malformed.length) {
	const message = report.malformed
		.map((it) => {
			return `${it} data is malformed`;
		})
		.join('\n');
	console.log(message);
}
 
const collisionEntries = Object.entries(report.idsMap).filter(
	(it) => it[1].snapshots.length > 1,
);
 
const message = collisionEntries
	.map((it) => {
		const data = it[1];
		return `[${
			data.snapshots.join(
				', ',
			)
		}] are pointing to a parent snapshot: ${data.parent}/snapshot.json which is a collision.`;
	})
	.join('\n');
 
if (message) {
	console.log(message);
}
 
const abort = report.malformed.length!! || collisionEntries.length > 0;
 
if (abort) {
	process.exit(1);
}

Sources: drizzle-kit/src/cli/commands/check.ts:8-51

Note

The abort condition checks both malformed snapshot presence and collision entries using report.malformed.length!! || collisionEntries.length > 0, terminating the process with exit code 1 if integrity errors are found.

const abort = report.malformed.length!! || collisionEntries.length > 0;
 
if (abort) {
	process.exit(1);
}

Sources: drizzle-kit/src/cli/commands/check.ts:47-51

Migration Lifecycle Pruning and Upgrades

Migration Pruning via Drop

The dropMigration function manages the interactive removal of generated migration entries, cleaning up corresponding SQL files, meta snapshots, and journal records. It reads the migration journal from meta/_journal.json within the designated output folder and verifies that entries exist before proceeding Migration Toolkit Schema.

const metaFilePath = join(out, 'meta', '_journal.json');
const journal = JSON.parse(readFileSync(metaFilePath, 'utf-8')) as Journal;
 
if (journal.entries.length === 0) {
	console.log(
		`[${chalk.blue('i')}] no migration entries found in ${metaFilePath}`,
	);
	return;
}

Sources: drizzle-kit/src/cli/commands/drop.ts:17-25

If entries are found, dropMigration renders an interactive selection view using DropMigrationView to let users pick which migration entry to remove. If the selection is aborted, the function returns immediately without modifying the file system.

const result = await render(new DropMigrationView(journal.entries));
if (result.status === 'aborted') return;

Sources: drizzle-kit/src/cli/commands/drop.ts:27-28

Once a migration is selected, its entry is filtered out of the journal, and the associated .sql migration file and _snapshot.json file are permanently deleted from disk. If the bundle flag is enabled, an updated embedded migrations bundle is written via embeddedMigrations.

File / Path TargetActionSource Reference
meta/_journal.jsonRead and updated to remove the selected entrydrizzle-kit/src/cli/commands/drop.ts:17-18, drizzle-kit/src/cli/commands/drop.ts:32-35
<tag>.sqlUnlinked via rmSyncdrizzle-kit/src/cli/commands/drop.ts:36, drizzle-kit/src/cli/commands/drop.ts:42
meta/<prefix>_snapshot.jsonUnlinked via rmSyncdrizzle-kit/src/cli/commands/drop.ts:37-41, drizzle-kit/src/cli/commands/drop.ts:43
migrations.jsRewritten if bundle is truedrizzle-kit/src/cli/commands/drop.ts:46-50

Sources: drizzle-kit/src/cli/commands/drop.ts:17-50

Caution

The dropMigration function uses rmSync directly on the resolved .sql and snapshot file paths without checking file existence first, meaning unhandled file descriptor exceptions will occur if target files are missing or out of sync with the journal.

Dialect-Specific Up Handlers

Dialect upgrade commands update legacy or non-latest migration snapshot formats to match current serializer specifications Migration Toolkit Schema. The CLI routes upgrade execution through dedicated dialect handlers depending on the active configuration.

export const upSinglestoreHandler = (out: string) => {};

Sources: drizzle-kit/src/cli/commands/singlestoreUp.ts:1

Note

The SingleStore up command handler upSinglestoreHandler accepts an output directory path string but currently executes as a no-op stub awaiting full upgrade sequence implementation.

Sources: drizzle-kit/src/cli/commands/singlestoreUp.ts:1

Terminal Rendering and Interactive Components

CLI Views and Formatting Helpers

The CLI uses chalk and the hanji library to output formatted messages, warnings, errors, and schema summaries to the terminal. Message formatting functions wrap strings with specific color codes and styles depending on message severity.

export const warning = (msg: string) => {
	render(`[${chalk.yellow('Warning')}] ${msg}`);
};
export const err = (msg: string) => {
	render(`${chalk.bold.red('Error')} ${msg}`);
};
 
export const info = (msg: string, greyMsg: string = ''): string => {
	return `${chalk.blue.bold('Info:')} ${msg} ${greyMsg ? chalk.grey(greyMsg) : ''}`.trim();
};

Sources: drizzle-kit/src/cli/views.ts:7-16

The schema view function formats a CommonSchema structure into a readable block displaying table counts, column counts, index counts, foreign keys, and enum definitions. For SingleStore schemas, foreign key counts are omitted since SingleStore lacks foreign key support in this context.

export const schema = (schema: CommonSchema): string => {
	type TableEntry = (typeof schema)['tables'][keyof (typeof schema)['tables']];
	const tables = Object.values(schema.tables) as unknown as TableEntry[];
 
	let msg = chalk.bold(`${tables.length} tables\n`);
 
	msg += tables
		.map((t) => {
			const columnsCount = Object.values(t.columns).length;
			const indexesCount = Object.values(t.indexes).length;
			let foreignKeys: number = 0;
			// Singlestore doesn't have foreign keys
			if (schema.dialect !== 'singlestore') {
				// @ts-expect-error
				foreignKeys = Object.values(t.foreignKeys).length;
			}
 
			return `${chalk.bold.blue(t.name)} ${
				chalk.gray(
					`${columnsCount} columns ${indexesCount} indexes ${foreignKeys} fks`,
				)
			}`;
		})
		.join('\n');
 

Sources: drizzle-kit/src/cli/views.ts:25-49

Function NameParametersReturn TypePurposeSource Reference
warningmsg: stringvoidRenders a yellow [Warning] tag and message via hanjidrizzle-kit/src/cli/views.ts:7-9
errmsg: stringvoidRenders a bold red Error tag and message via renderdrizzle-kit/src/cli/views.ts:10-12
infomsg: string, greyMsg?: stringstringReturns a bold blue Info: label followed by message and grey textdrizzle-kit/src/cli/views.ts:14-16
greymsg: stringstringReturns the input string styled in greydrizzle-kit/src/cli/views.ts:17-19
errorerror: string, greyMsg?: stringstringReturns a red background white text Error badge with messagedrizzle-kit/src/cli/views.ts:21-23
schemaschema: CommonSchemastringSerializes table and enum summary counts with styled namesdrizzle-kit/src/cli/views.ts:25-76
tableKeyit: NamedWithSchemastringFormats a table key using schema prefix if schema is present and not publicdrizzle-kit/src/cli/views.ts:161-165

Sources: drizzle-kit/src/cli/views.ts:7-76, drizzle-kit/src/cli/views.ts:161-165

Interactive Prompts and Selectors

Interactive selection components extend Prompt from hanji and bind to SelectState instances to handle user input and keyboard navigation.

export class Select extends Prompt<{ index: number; value: string }> {
	private readonly data: SelectState<{ label: string; value: string }>;
 
	constructor(items: string[]) {
		super();
		this.on('attach', (terminal) => terminal.toggleCursor('hide'));
		this.on('detach', (terminal) => terminal.toggleCursor('show'));
 
		this.data = new SelectState(
			items.map((it) => ({ label: it, value: `${it}-value` })),
		);
		this.data.bind(this);
	}

Sources: drizzle-kit/src/cli/selector-ui.ts:4-16

The Select class maps an array of string items into label-value objects, hiding the terminal cursor upon attachment and restoring it upon detachment. When rendered, it highlights the currently selected item with a green ❯ prefix and returns the selected index and value via result().

render(status: 'idle' | 'submitted' | 'aborted'): string {
	if (status === 'submitted' || status === 'aborted') return '';
 
	let text = ``;
	this.data.items.forEach((it, idx) => {
		text += idx === this.data.selectedIdx
			? `${chalk.green('❯ ' + it.label)}`
			: `  ${it.label}`;
		text += idx != this.data.items.length - 1 ? '\n' : '';
	});
 
	return text;
}
 
result() {
	return {
		index: this.data.selectedIdx,
		value: this.data.items[this.data.selectedIdx]!.value!,
	};
}

Sources: drizzle-kit/src/cli/selector-ui.ts:18-37

For column and entity renaming disambiguation during migrations, ResolveColumnSelect, ResolveSelectNamed, and ResolveSelect prompts distinguish between column creation (+) and column renaming (~) actions.

export class ResolveColumnSelect<T extends Named> extends Prompt<
	RenamePropmtItem<T> | T
> {
	private readonly data: SelectState<RenamePropmtItem<T> | T>;
 
	constructor(
		private readonly tableName: string,
		private readonly base: Named,
		data: (RenamePropmtItem<T> | T)[],
	) {
		super();
		this.on('attach', (terminal) => terminal.toggleCursor('hide'));
		this.data = new SelectState(data);
		this.data.bind(this);
	}

Sources: drizzle-kit/src/cli/views.ts:89-103

Note

The isRenamePromptItem type guard checks whether an item contains both from and to properties to identify whether a schema element has been renamed rather than newly created.

Sources: drizzle-kit/src/cli/views.ts:83-87

Progress Spinners

Task execution progress is rendered through specialized view classes extending TaskView that animate spinner characters across terminal updates.

export class MigrateProgress extends TaskView {
	private readonly spinner: Spinner = new Spinner('⣷⣯⣟⡿⢿⣻⣽⣾'.split(''));

Sources: drizzle-kit/src/cli/views.ts:528-529

The MigrateProgress task view initializes a Spinner instance with a unicode frame sequence (⣷⣯⣟⡿⢿⣻⣽⣾) to render real-time progress indicators during migration operations.

Sources: drizzle-kit/src/cli/views.ts:528-529

Was this page helpful?