Skip to content

Commit

Permalink
Merge pull request #3705 from drizzle-team/drizzle-kit/export-sql
Browse files Browse the repository at this point in the history
created export command for drizzle-kit
  • Loading branch information
AndriiSherman authored Dec 12, 2024
2 parents d379dcf + 5ba9147 commit 21dab20
Show file tree
Hide file tree
Showing 6 changed files with 338 additions and 6 deletions.
168 changes: 167 additions & 1 deletion drizzle-kit/src/cli/commands/migrate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ import {
ResolveSelectNamed,
schema,
} from '../views';
import { GenerateConfig } from './utils';
import { ExportConfig, GenerateConfig } from './utils';

export type Named = {
name: string;
Expand Down Expand Up @@ -368,6 +368,44 @@ export const prepareAndMigratePg = async (config: GenerateConfig) => {
}
};

export const prepareAndExportPg = async (config: ExportConfig) => {
const schemaPath = config.schema;

try {
const { prev, cur } = await preparePgMigrationSnapshot(
[], // no snapshots before
schemaPath,
undefined,
);

const validatedPrev = pgSchema.parse(prev);
const validatedCur = pgSchema.parse(cur);

const squashedPrev = squashPgScheme(validatedPrev);
const squashedCur = squashPgScheme(validatedCur);

const { sqlStatements } = await applyPgSnapshotsDiff(
squashedPrev,
squashedCur,
schemasResolver,
enumsResolver,
sequencesResolver,
policyResolver,
indPolicyResolver,
roleResolver,
tablesResolver,
columnsResolver,
viewsResolver,
validatedPrev,
validatedCur,
);

console.log(sqlStatements.join('\n'));
} catch (e) {
console.error(e);
}
};

export const preparePgPush = async (
cur: PgSchema,
prev: PgSchema,
Expand Down Expand Up @@ -697,6 +735,70 @@ export const prepareAndMigrateSingleStore = async (config: GenerateConfig) => {
}
};

export const prepareAndExportSinglestore = async (config: ExportConfig) => {
const schemaPath = config.schema;

try {
const { prev, cur } = await prepareSingleStoreMigrationSnapshot(
[],
schemaPath,
undefined,
);

const validatedPrev = singlestoreSchema.parse(prev);
const validatedCur = singlestoreSchema.parse(cur);

const squashedPrev = squashSingleStoreScheme(validatedPrev);
const squashedCur = squashSingleStoreScheme(validatedCur);

const { sqlStatements, _meta } = await applySingleStoreSnapshotsDiff(
squashedPrev,
squashedCur,
tablesResolver,
columnsResolver,
/* singleStoreViewsResolver, */
validatedPrev,
validatedCur,
);

console.log(sqlStatements.join('\n'));
} catch (e) {
console.error(e);
}
};

export const prepareAndExportMysql = async (config: ExportConfig) => {
const schemaPath = config.schema;

try {
const { prev, cur, custom } = await prepareMySqlMigrationSnapshot(
[],
schemaPath,
undefined,
);

const validatedPrev = mysqlSchema.parse(prev);
const validatedCur = mysqlSchema.parse(cur);

const squashedPrev = squashMysqlScheme(validatedPrev);
const squashedCur = squashMysqlScheme(validatedCur);

const { sqlStatements, statements, _meta } = await applyMysqlSnapshotsDiff(
squashedPrev,
squashedCur,
tablesResolver,
columnsResolver,
mySqlViewsResolver,
validatedPrev,
validatedCur,
);

console.log(sqlStatements.join('\n'));
} catch (e) {
console.error(e);
}
};

export const prepareAndMigrateSqlite = async (config: GenerateConfig) => {
const outFolder = config.out;
const schemaPath = config.schema;
Expand Down Expand Up @@ -760,6 +862,38 @@ export const prepareAndMigrateSqlite = async (config: GenerateConfig) => {
}
};

export const prepareAndExportSqlite = async (config: ExportConfig) => {
const schemaPath = config.schema;

try {
const { prev, cur } = await prepareSqliteMigrationSnapshot(
[],
schemaPath,
undefined,
);

const validatedPrev = sqliteSchema.parse(prev);
const validatedCur = sqliteSchema.parse(cur);

const squashedPrev = squashSqliteScheme(validatedPrev);
const squashedCur = squashSqliteScheme(validatedCur);

const { sqlStatements, _meta } = await applySqliteSnapshotsDiff(
squashedPrev,
squashedCur,
tablesResolver,
columnsResolver,
sqliteViewsResolver,
validatedPrev,
validatedCur,
);

console.log(sqlStatements.join('\n'));
} catch (e) {
console.error(e);
}
};

export const prepareAndMigrateLibSQL = async (config: GenerateConfig) => {
const outFolder = config.out;
const schemaPath = config.schema;
Expand Down Expand Up @@ -822,6 +956,38 @@ export const prepareAndMigrateLibSQL = async (config: GenerateConfig) => {
}
};

export const prepareAndExportLibSQL = async (config: ExportConfig) => {
const schemaPath = config.schema;

try {
const { prev, cur, custom } = await prepareSqliteMigrationSnapshot(
[],
schemaPath,
undefined,
);

const validatedPrev = sqliteSchema.parse(prev);
const validatedCur = sqliteSchema.parse(cur);

const squashedPrev = squashSqliteScheme(validatedPrev);
const squashedCur = squashSqliteScheme(validatedCur);

const { sqlStatements, _meta } = await applyLibSQLSnapshotsDiff(
squashedPrev,
squashedCur,
tablesResolver,
columnsResolver,
sqliteViewsResolver,
validatedPrev,
validatedCur,
);

console.log(sqlStatements.join('\n'));
} catch (e) {
console.error(e);
}
};

export const prepareSQLitePush = async (
schemaPath: string | string[],
snapshot: SQLiteSchema,
Expand Down
44 changes: 42 additions & 2 deletions drizzle-kit/src/cli/commands/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,12 @@ export type GenerateConfig = {
driver?: Driver;
};

export type ExportConfig = {
dialect: Dialect;
schema: string | string[];
sql: boolean;
};

export const prepareGenerateConfig = async (
options: {
config?: string;
Expand Down Expand Up @@ -185,6 +191,38 @@ export const prepareGenerateConfig = async (
};
};

export const prepareExportConfig = async (
options: {
config?: string;
schema?: string;
dialect?: Dialect;
sql: boolean;
},
from: 'config' | 'cli',
): Promise<ExportConfig> => {
const config = from === 'config' ? await drizzleConfigFromFile(options.config, true) : options;

const { schema, dialect, sql } = config;

if (!schema || !dialect) {
console.log(error('Please provide required params:'));
console.log(wrapParam('schema', schema));
console.log(wrapParam('dialect', dialect));
process.exit(1);
}

const fileNames = prepareFilenames(schema);
if (fileNames.length === 0) {
render(`[${chalk.blue('i')}] No schema file in ${schema} was found`);
process.exit(0);
}
return {
dialect: dialect,
schema: schema,
sql: sql,
};
};

export const flattenDatabaseCredentials = (config: any) => {
if ('dbCredentials' in config) {
const { dbCredentials, ...rest } = config;
Expand Down Expand Up @@ -768,6 +806,7 @@ export const prepareMigrateConfig = async (configPath: string | undefined) => {

export const drizzleConfigFromFile = async (
configPath?: string,
isExport?: boolean,
): Promise<CliConfig> => {
const prefix = process.env.TEST_CONFIG_PATH_PREFIX || '';

Expand All @@ -783,7 +822,7 @@ export const drizzleConfigFromFile = async (
? 'drizzle.config.js'
: 'drizzle.config.json';

if (!configPath) {
if (!configPath && !isExport) {
console.log(
chalk.gray(
`No config path provided, using default '${defaultConfigPath}'`,
Expand All @@ -798,7 +837,8 @@ export const drizzleConfigFromFile = async (
process.exit(1);
}

console.log(chalk.grey(`Reading config file '${path}'`));
if (!isExport) console.log(chalk.grey(`Reading config file '${path}'`));

const { unregister } = await safeRegister();
const required = require(`${path}`);
const content = required.default ?? required;
Expand Down
4 changes: 2 additions & 2 deletions drizzle-kit/src/cli/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { command, run } from '@drizzle-team/brocli';
import chalk from 'chalk';
import { check, drop, generate, migrate, pull, push, studio, up } from './schema';
import { check, drop, exportRaw, generate, migrate, pull, push, studio, up } from './schema';
import { ormCoreVersions } from './utils';

const version = async () => {
Expand Down Expand Up @@ -42,7 +42,7 @@ const legacy = [
legacyCommand('check:sqlite', 'check'),
];

run([generate, migrate, pull, push, studio, up, check, drop, ...legacy], {
run([generate, migrate, pull, push, studio, up, check, drop, exportRaw, ...legacy], {
name: 'drizzle-kit',
version: version,
});
45 changes: 45 additions & 0 deletions drizzle-kit/src/cli/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { upSqliteHandler } from './commands/sqliteUp';
import {
prepareCheckParams,
prepareDropParams,
prepareExportConfig,
prepareGenerateConfig,
prepareMigrateConfig,
preparePullConfig,
Expand Down Expand Up @@ -747,3 +748,47 @@ export const studio = command({
}
},
});

export const exportRaw = command({
name: 'export',
desc: 'Generate diff between current state and empty state in specified formats: sql',
options: {
sql: boolean('sql').default(true).desc('Generate as sql'),
config: optionConfig,
dialect: optionDialect,
schema: string().desc('Path to a schema file or folder'),
},
transform: async (opts) => {
const from = assertCollisions('export', opts, ['sql'], ['dialect', 'schema']);
return prepareExportConfig(opts, from);
},
handler: async (opts) => {
await assertOrmCoreVersion();
await assertPackages('drizzle-orm');

const {
prepareAndExportPg,
prepareAndExportMysql,
prepareAndExportSqlite,
prepareAndExportLibSQL,
prepareAndExportSinglestore,
} = await import(
'./commands/migrate'
);

const dialect = opts.dialect;
if (dialect === 'postgresql') {
await prepareAndExportPg(opts);
} else if (dialect === 'mysql') {
await prepareAndExportMysql(opts);
} else if (dialect === 'sqlite') {
await prepareAndExportSqlite(opts);
} else if (dialect === 'turso') {
await prepareAndExportLibSQL(opts);
} else if (dialect === 'singlestore') {
await prepareAndExportSinglestore(opts);
} else {
assertUnreachable(dialect);
}
},
});
4 changes: 3 additions & 1 deletion drizzle-kit/src/cli/validations/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ export type Commands =
| 'check'
| 'up'
| 'drop'
| 'push';
| 'push'
| 'export';

type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;
type IsUnion<T> = [T] extends [UnionToIntersection<T>] ? false : true;
Expand Down Expand Up @@ -111,6 +112,7 @@ export const configCommonSchema = object({
migrations: configMigrations,
dbCredentials: any().optional(),
casing: casingType.optional(),
sql: boolean().default(true),
}).passthrough();

export const casing = union([literal('camel'), literal('preserve')]).default(
Expand Down
Loading

0 comments on commit 21dab20

Please # to comment.