Skip to content

Commit b48910c

Browse files
committed
CLI: add "db push" command
1 parent eabf3e2 commit b48910c

File tree

5 files changed

+97
-34
lines changed

5 files changed

+97
-34
lines changed

packages/cli/src/actions/common.ts

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export function handleSubProcessError(err: unknown) {
2+
if (
3+
err instanceof Error &&
4+
'status' in err &&
5+
typeof err.status === 'number'
6+
) {
7+
process.exit(err.status);
8+
} else {
9+
process.exit(1);
10+
}
11+
}

packages/cli/src/actions/db.ts

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import path from 'node:path';
2+
import { execPackage } from '../utils/exec-utils';
3+
import { getSchemaFile } from './action-utils';
4+
import { run as runGenerate } from './generate';
5+
import { handleSubProcessError } from './common';
6+
7+
type CommonOptions = {
8+
schema?: string;
9+
name?: string;
10+
};
11+
12+
/**
13+
* CLI action for db related commands
14+
*/
15+
export async function run(command: string, options: CommonOptions) {
16+
const schemaFile = getSchemaFile(options.schema);
17+
18+
// run generate first
19+
await runGenerate({
20+
schema: schemaFile,
21+
silent: true,
22+
});
23+
24+
const prismaSchemaFile = path.join(
25+
path.dirname(schemaFile),
26+
'schema.prisma'
27+
);
28+
29+
switch (command) {
30+
case 'push':
31+
await runPush(prismaSchemaFile, options);
32+
break;
33+
}
34+
}
35+
36+
async function runPush(prismaSchemaFile: string, options: any) {
37+
const cmd = `prisma db push --schema "${prismaSchemaFile}"${
38+
options.acceptDataLoss ? ' --accept-data-loss' : ''
39+
}${options.forceReset ? ' --force-reset' : ''} --skip-generate`;
40+
try {
41+
await execPackage(cmd, {
42+
stdio: 'inherit',
43+
});
44+
} catch (err) {
45+
handleSubProcessError(err);
46+
}
47+
}

packages/cli/src/actions/index.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
import { run as db } from './db';
12
import { run as generate } from './generate';
23
import { run as info } from './info';
34
import { run as migrate } from './migrate';
45

5-
export { generate, info, migrate };
6+
export { db, generate, info, migrate };

packages/cli/src/actions/migrate.ts

+9-25
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ type CommonOptions = {
99
};
1010

1111
/**
12-
* CLI action for generating code from schema
12+
* CLI action for migration-related commands
1313
*/
1414
export async function run(command: string, options: CommonOptions) {
1515
const schemaFile = getSchemaFile(options.schema);
@@ -27,28 +27,24 @@ export async function run(command: string, options: CommonOptions) {
2727

2828
switch (command) {
2929
case 'dev':
30-
await runDev(schemaFile, prismaSchemaFile, options);
30+
await runDev(prismaSchemaFile, options);
3131
break;
3232

3333
case 'reset':
34-
await runReset(schemaFile, prismaSchemaFile, options as any);
34+
await runReset(prismaSchemaFile, options as any);
3535
break;
3636

3737
case 'deploy':
38-
await runDeploy(schemaFile, prismaSchemaFile, options);
38+
await runDeploy(prismaSchemaFile, options);
3939
break;
4040

4141
case 'status':
42-
await runStatus(schemaFile, prismaSchemaFile, options);
42+
await runStatus(prismaSchemaFile, options);
4343
break;
4444
}
4545
}
4646

47-
async function runDev(
48-
_schemaFile: string,
49-
prismaSchemaFile: string,
50-
_options: unknown
51-
) {
47+
async function runDev(prismaSchemaFile: string, _options: unknown) {
5248
try {
5349
await execPackage(
5450
`prisma migrate dev --schema "${prismaSchemaFile}" --skip-generate`,
@@ -61,11 +57,7 @@ async function runDev(
6157
}
6258
}
6359

64-
async function runReset(
65-
_schemaFile: string,
66-
prismaSchemaFile: string,
67-
options: { force: boolean }
68-
) {
60+
async function runReset(prismaSchemaFile: string, options: { force: boolean }) {
6961
try {
7062
await execPackage(
7163
`prisma migrate reset --schema "${prismaSchemaFile}"${
@@ -80,11 +72,7 @@ async function runReset(
8072
}
8173
}
8274

83-
async function runDeploy(
84-
_schemaFile: string,
85-
prismaSchemaFile: string,
86-
_options: unknown
87-
) {
75+
async function runDeploy(prismaSchemaFile: string, _options: unknown) {
8876
try {
8977
await execPackage(
9078
`prisma migrate deploy --schema "${prismaSchemaFile}"`,
@@ -97,11 +85,7 @@ async function runDeploy(
9785
}
9886
}
9987

100-
async function runStatus(
101-
_schemaFile: string,
102-
prismaSchemaFile: string,
103-
_options: unknown
104-
) {
88+
async function runStatus(prismaSchemaFile: string, _options: unknown) {
10589
try {
10690
await execPackage(
10791
`prisma migrate status --schema "${prismaSchemaFile}"`,

packages/cli/src/index.ts

+28-8
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,24 @@ import { Command, Option } from 'commander';
44
import * as actions from './actions';
55
import { getVersion } from './utils/version-utils';
66

7-
export const infoAction = async (projectPath: string): Promise<void> => {
7+
const infoAction = async (projectPath: string): Promise<void> => {
88
await actions.info(projectPath);
99
};
1010

11-
export const generateAction = async (
11+
const generateAction = async (
1212
options: Parameters<typeof actions.generate>[0]
1313
): Promise<void> => {
1414
await actions.generate(options);
1515
};
1616

17-
export const migrateAction = async (
18-
command: string,
19-
options: any
20-
): Promise<void> => {
17+
const migrateAction = async (command: string, options: any): Promise<void> => {
2118
await actions.migrate(command, options);
2219
};
2320

21+
const dbAction = async (command: string, options: any): Promise<void> => {
22+
await actions.db(command, options);
23+
};
24+
2425
export function createProgram() {
2526
const program = new Command('zenstack');
2627

@@ -64,7 +65,7 @@ export function createProgram() {
6465

6566
const migrateCommand = program
6667
.command('migrate')
67-
.description('Run migration.');
68+
.description('Update the database schema with migrations.');
6869

6970
migrateCommand
7071
.command('dev')
@@ -91,7 +92,7 @@ export function createProgram() {
9192
.command('deploy')
9293
.addOption(schemaOption)
9394
.description(
94-
'deploy your pending migrations to your production/staging database.'
95+
'Deploy your pending migrations to your production/staging database.'
9596
)
9697
.action((options) => migrateAction('deploy', options));
9798

@@ -101,6 +102,25 @@ export function createProgram() {
101102
.description('check the status of your database migrations.')
102103
.action((options) => migrateAction('status', options));
103104

105+
const dbCommand = program
106+
.command('db')
107+
.description('Manage your database schema during development.');
108+
109+
dbCommand
110+
.command('push')
111+
.description('Push the state from your schema to your database')
112+
.addOption(schemaOption)
113+
.addOption(
114+
new Option('--accept-data-loss', 'ignore data loss warnings')
115+
)
116+
.addOption(
117+
new Option(
118+
'--force-reset',
119+
'force a reset of the database before push'
120+
)
121+
)
122+
.action((options) => dbAction('push', options));
123+
104124
return program;
105125
}
106126

0 commit comments

Comments
 (0)