Relevant source files
The following files were used as context for generating this wiki page:
- drizzle-kit/src/cli/commands/migrate.ts
- drizzle-kit/src/cli/index.ts
- drizzle-kit/src/cli/schema.ts
- drizzle-kit/src/cli/views.ts
- drizzle-kit/src/api.ts
- drizzle-kit/src/cli/commands/utils.ts
- drizzle-kit/src/snapshotsDiffer.ts
- drizzle-kit/src/cli/commands/introspect.ts
- drizzle-kit/src/cli/commands/push.ts
- drizzle-kit/src/cli/connections.ts
- drizzle-kit/src/cli/commands/check.ts
- drizzle-kit/src/cli/validations/outputs.ts
- drizzle-kit/src/cli/commands/singlestorePushUtils.ts
- drizzle-kit/src/utils.ts
- drizzle-kit/src/cli/commands/pgPushUtils.ts
- drizzle-kit/src/cli/validations/common.ts
- drizzle-kit/src/cli/utils.ts
- drizzle-kit/src/cli/validations/sqlite.ts
- drizzle-kit/src/cli/validations/cli.ts
- drizzle-kit/src/index.ts
- drizzle-kit/src/cli/commands/singlestoreUp.ts
- drizzle-kit/src/cli/commands/drop.ts
- drizzle-kit/src/cli/selector-ui.ts
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 Name | Target Replacement | Hidden Status |
|---|---|---|
generate:pg, generate:mysql, generate:sqlite | generate | true |
push:pg, push:mysql, push:sqlite | push | true |
introspect:pg, introspect:mysql, introspect:sqlite | introspect | true |
up:pg, up:mysql, up:sqlite | up | true |
check:pg, check:mysql, check:sqlite | check | true |
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.
| Context | Error Condition | Validation Message |
|---|---|---|
common | Ambiguous parameters | You can't use both --config and other cli options for {command} command |
postgres | Missing connection parameters | Either "url" or "host", "database" are required for database connection |
mysql / singlestore | Invalid driver option | Only "mysql2" is available options for "--driver" |
sqlite | Missing driver parameter | Either 'better-sqlite3', 'libsql', 'turso', 'expo', 'durable-sqlite' are available options for 'driver' param |
studio | Unspecified dialect | Please 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 Function | Input Type | Output Type | Conflict Prompt Routine |
|---|---|---|---|
schemasResolver | ResolverInput<Table> | ResolverOutput<Table> | promptSchemasConflict |
tablesResolver | ResolverInput<Table> | ResolverOutputWithMoved<Table> | promptNamedWithSchemasConflict |
viewsResolver | ResolverInput<View> | ResolverOutputWithMoved<View> | promptNamedWithSchemasConflict |
sequencesResolver | ResolverInput<Sequence> | ResolverOutputWithMoved<Sequence> | promptNamedWithSchemasConflict |
roleResolver | RolesResolverInput<Role> | RolesResolverOutput<Role> | promptNamedConflict |
policyResolver | TablePolicyResolverInput<Policy> | TablePolicyResolverOutput<Policy> | promptColumnsConflicts |
enumsResolver | ResolverInput<Enum> | ResolverOutputWithMoved<Enum> | promptNamedWithSchemasConflict |
columnsResolver | ColumnsResolverInput<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.
| Dialect | Validator Schema | Target Version |
|---|---|---|
postgresql | backwardCompatiblePgSchema | 7 |
sqlite | backwardCompatibleSqliteSchema | 6 |
turso | backwardCompatibleSqliteSchema | 6 |
mysql | backwardCompatibleMysqlSchema | 5 |
singlestore | backwardCompatibleSingleStoreSchema | 1 |
gel | backwardCompatibleGelSchema | 1 |
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:
- Non-latest snapshots: If
report.nonLatestcontains entries, it logs that each snapshot is outdated and instructs users to executedrizzle-kit up, exiting with code1. - Malformed data: If
report.malformedcontains entries, it logs malformed warnings for each failing file. - Snapshot collisions: It inspects
report.idsMapto 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 Target | Action | Source Reference |
|---|---|---|
meta/_journal.json | Read and updated to remove the selected entry | drizzle-kit/src/cli/commands/drop.ts:17-18, drizzle-kit/src/cli/commands/drop.ts:32-35 |
<tag>.sql | Unlinked via rmSync | drizzle-kit/src/cli/commands/drop.ts:36, drizzle-kit/src/cli/commands/drop.ts:42 |
meta/<prefix>_snapshot.json | Unlinked via rmSync | drizzle-kit/src/cli/commands/drop.ts:37-41, drizzle-kit/src/cli/commands/drop.ts:43 |
migrations.js | Rewritten if bundle is true | drizzle-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 Name | Parameters | Return Type | Purpose | Source Reference |
|---|---|---|---|---|
warning | msg: string | void | Renders a yellow [Warning] tag and message via hanji | drizzle-kit/src/cli/views.ts:7-9 |
err | msg: string | void | Renders a bold red Error tag and message via render | drizzle-kit/src/cli/views.ts:10-12 |
info | msg: string, greyMsg?: string | string | Returns a bold blue Info: label followed by message and grey text | drizzle-kit/src/cli/views.ts:14-16 |
grey | msg: string | string | Returns the input string styled in grey | drizzle-kit/src/cli/views.ts:17-19 |
error | error: string, greyMsg?: string | string | Returns a red background white text Error badge with message | drizzle-kit/src/cli/views.ts:21-23 |
schema | schema: CommonSchema | string | Serializes table and enum summary counts with styled names | drizzle-kit/src/cli/views.ts:25-76 |
tableKey | it: NamedWithSchema | string | Formats a table key using schema prefix if schema is present and not public | drizzle-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
Related
On This Page
OverviewCommand Registration and Brocli EntrypointsBrocli Command Execution and EntrypointCommand Definitions and Legacy AliasesVersion Assertions and Environment ValidationConfig Loading and Runtime PreparationTSX Runtime Registration and ES5 AssertionsParameter Transformation and Validation BridgesMigration Generation and Interactive DisambiguationMigration Preparation and Snapshot DiffingInteractive Conflict DisambiguationSchema Integrity Verification WorkflowFolder Preparation and Snapshot ValidationValidation Reporting and Collision DetectionMigration Lifecycle Pruning and UpgradesMigration Pruning via DropDialect-Specific Up HandlersTerminal Rendering and Interactive ComponentsCLI Views and Formatting HelpersInteractive Prompts and SelectorsProgress SpinnersRelated