Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/plenty-books-share.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@keystone-6/core': major
---

Removes `--reset-db` from `keystone dev`, use `keystone prisma db push --force-reset` to reset your database
7 changes: 4 additions & 3 deletions docs/pages/docs/guides/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,17 +129,18 @@ We strongly recommend enabling migrations if you are going to run your app in pr

### Resetting the database

From time to time, in development you may want to reset the database and recreate it from scratch. You can do this by passing the `--reset-db` flag:
From time to time, in development you may want to reset the database and recreate it from scratch.
You can do this by using Prisma:

```bash
$ keystone dev --reset-db
$ keystone prisma db push --force-reset
```

{% hint kind="error" %}
Doing this will destroy your database, including all data
{% /hint %}

This is mainly useful early in a project's development lifecycle, when you want to test database initialisation scripts or create a fresh set of test data.
This is typically useful early in a project's development lifecycle, when you want to test database initialisation scripts or create a fresh set of test data.

## postinstall

Expand Down
3 changes: 1 addition & 2 deletions packages/core/src/lib/migrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export async function pushPrismaSchemaToDatabase(
shadowDbUrl: string | undefined,
schema: string,
schemaPath: string,
resetDb = false
resetDb: boolean
) {
const before = Date.now();
await ensureDatabaseExists(dbUrl, path.dirname(schemaPath));
Expand Down Expand Up @@ -181,7 +181,6 @@ export async function deployMigrations(dbUrl: string) {
});
}

// TODO: don't have process.exit calls here
export async function devMigrations(
dbUrl: string,
shadowDbUrl: string | undefined,
Expand Down
8 changes: 2 additions & 6 deletions packages/core/src/scripts/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ export type Flags = {
fix: boolean; // TODO: remove, deprecated
frozen: boolean;
prisma: boolean;
resetDb: boolean;
server: boolean;
ui: boolean;
withMigrations: boolean;
Expand Down Expand Up @@ -80,10 +79,7 @@ export async function cli(cwd: string, argv: string[]) {

const command = input[0] || 'dev';
if (command === 'dev') {
return dev(
cwd,
defaultFlags(flags, { dbPush: true, prisma: true, resetDb: false, server: true, ui: true })
);
return dev(cwd, defaultFlags(flags, { dbPush: true, prisma: true, server: true, ui: true }));
}

if (command === 'build') {
Expand All @@ -95,7 +91,7 @@ export async function cli(cwd: string, argv: string[]) {
}

if (command === 'prisma') {
return prisma(cwd, argv.slice(1), defaultFlags(flags, { frozen: false }).frozen);
return prisma(cwd, argv.slice(1), Boolean(flags.frozen));
}

if (command === 'telemetry') return telemetry(cwd, argv[1]);
Expand Down
16 changes: 4 additions & 12 deletions packages/core/src/scripts/run/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,7 @@ type WatchBuildResult = { error: BuildFailure | null; result: BuildResult | null

export async function dev(
cwd: string,
{
dbPush,
prisma,
resetDb,
server,
ui,
}: Pick<Flags, 'dbPush' | 'prisma' | 'resetDb' | 'server' | 'ui'>
{ dbPush, prisma, server, ui }: Pick<Flags, 'dbPush' | 'prisma' | 'server' | 'ui'>
) {
console.log('✨ Starting Keystone');
const app = server ? express() : null;
Expand Down Expand Up @@ -135,7 +129,6 @@ export async function dev(
server,
prisma,
dbPush,
resetDb,
});

if (configWithHTTP?.server?.extendHttpServer && httpServer && context) {
Expand Down Expand Up @@ -375,12 +368,11 @@ async function setupInitialKeystone(
cwd: string,
options: {
dbPush: boolean;
resetDb: boolean;
prisma: boolean;
server: boolean;
}
) {
const { dbPush, resetDb, prisma, server } = options;
const { dbPush, prisma, server } = options;
const { graphQLSchema, adminMeta, getKeystone } = createSystem(config);

// Make local storage folders if used
Expand All @@ -403,15 +395,15 @@ async function setupInitialKeystone(
config.db.shadowDatabaseUrl,
prismaSchema,
getSchemaPaths(cwd).prisma,
resetDb
false
);
} else if (dbPush) {
await pushPrismaSchemaToDatabase(
config.db.url,
config.db.shadowDatabaseUrl,
prismaSchema,
getSchemaPaths(cwd).prisma,
resetDb
false
);
} else {
console.log('⚠️ Skipping database schema push');
Expand Down
84 changes: 20 additions & 64 deletions packages/core/src/scripts/tests/migrations.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,10 @@ setSkipWatching();

const dbUrl = 'file:./app.db';

async function setupAndStopDevServerForMigrations(cwd: string, resetDb: boolean = false) {
const stopServer = (await runCommand(
cwd,
`dev${resetDb ? ' --reset-db' : ''}`
)) as () => Promise<void>;
await stopServer();
}

function getPrismaClient(cwd: string) {
const prismaClient = new (requirePrismaClient(cwd).PrismaClient)({
return new (requirePrismaClient(cwd).PrismaClient)({
datasources: { sqlite: { url: dbUrl } },
});
return prismaClient;
}

async function getGeneratedMigration(
Expand Down Expand Up @@ -73,8 +64,8 @@ async function setupInitialProjectWithoutMigrations() {
'keystone.js': basicKeystoneConfig,
});
const recording = recordConsole();
await setupAndStopDevServerForMigrations(tmp);

await runCommand(tmp, 'dev');
expect(await introspectDb(tmp, dbUrl)).toEqual(`datasource db {
provider = "sqlite"
url = "file:./app.db"
Expand Down Expand Up @@ -106,7 +97,7 @@ describe('useMigrations: false', () => {
test('logs correctly when things are already up to date', async () => {
const tmp = await setupInitialProjectWithoutMigrations();
const recording = recordConsole();
await setupAndStopDevServerForMigrations(tmp);
await runCommand(tmp, 'dev');

expect(recording()).toMatchInlineSnapshot(`
"✨ Starting Keystone
Expand All @@ -132,7 +123,7 @@ describe('useMigrations: false', () => {
const recording = recordConsole({
'Do you want to continue? Some data will be lost.': true,
});
await setupAndStopDevServerForMigrations(tmp);
await runCommand(tmp, 'dev');

expect(await introspectDb(tmp, dbUrl)).toMatchInlineSnapshot(`
"datasource db {
Expand Down Expand Up @@ -174,7 +165,7 @@ describe('useMigrations: false', () => {
const recording = recordConsole({
'Do you want to continue? Some data will be lost.': false,
});
await expect(setupAndStopDevServerForMigrations(tmp)).rejects.toEqual(new ExitError(0));
await expect(runCommand(tmp, 'dev')).rejects.toEqual(new ExitError(0));

expect(await introspectDb(tmp, dbUrl)).toMatchInlineSnapshot(`
"datasource db {
Expand All @@ -201,17 +192,19 @@ describe('useMigrations: false', () => {
Push cancelled."
`);
});
test('--reset-db flag', async () => {
test('prisma db push --force-reset works', async () => {
const tmp = await setupInitialProjectWithoutMigrations();
{
const prismaClient = await getPrismaClient(tmp);
const prismaClient = getPrismaClient(tmp);
await prismaClient.todo.create({ data: { title: 'something' } });
await prismaClient.$disconnect();
}
const recording = recordConsole();
await setupAndStopDevServerForMigrations(tmp, true);

await runCommand(tmp, 'prisma db push --force-reset');
await runCommand(tmp, 'dev');
{
const prismaClient = await getPrismaClient(tmp);
const prismaClient = getPrismaClient(tmp);
expect(await prismaClient.todo.findMany()).toHaveLength(0);
await prismaClient.$disconnect();
}
Expand All @@ -221,8 +214,7 @@ describe('useMigrations: false', () => {
⭐️ Server listening on :3000 (http://localhost:3000/)
⭐️ GraphQL API available at /api/graphql
✨ Generating GraphQL and Prisma schemas
✨ Your database has been reset
✨ Your database is now in sync with your schema. Done in 0ms
✨ The database is already in sync with the Prisma schema.
✨ Connecting to the database
✨ Creating server
✅ GraphQL API ready"
Expand All @@ -244,7 +236,7 @@ async function setupInitialProjectWithMigrations() {
'Name of migration': 'init',
'Would you like to apply this migration?': true,
});
await setupAndStopDevServerForMigrations(tmp);
await runCommand(tmp, 'dev');

expect(await introspectDb(tmp, dbUrl)).toEqual(`datasource db {
provider = "sqlite"
Expand Down Expand Up @@ -304,7 +296,7 @@ describe('useMigrations: true', () => {
'Name of migration': 'add-is-complete',
'Would you like to apply this migration?': true,
});
await setupAndStopDevServerForMigrations(tmp);
await runCommand(tmp, 'dev');

expect(await introspectDb(tmp, dbUrl)).toMatchInlineSnapshot(`
"datasource db {
Expand Down Expand Up @@ -371,7 +363,7 @@ describe('useMigrations: true', () => {
'Name of migration': 'remove all fields except id',
'Would you like to apply this migration?': true,
});
await setupAndStopDevServerForMigrations(tmp);
await runCommand(tmp, 'dev');

expect(await introspectDb(tmp, dbUrl)).toMatchInlineSnapshot(`
"datasource db {
Expand Down Expand Up @@ -444,7 +436,7 @@ describe('useMigrations: true', () => {
'Name of migration': 'init',
'Would you like to apply this migration?': true,
});
await setupAndStopDevServerForMigrations(tmp);
await runCommand(tmp, 'dev');

expect(await introspectDb(tmp, dbUrl)).toMatchInlineSnapshot(`
"datasource db {
Expand Down Expand Up @@ -519,7 +511,7 @@ describe('useMigrations: true', () => {
'Do you want to continue? All data will be lost.': false,
});

await expect(setupAndStopDevServerForMigrations(tmp)).rejects.toEqual(new ExitError(0));
await expect(runCommand(tmp, 'dev')).rejects.toEqual(new ExitError(0));

expect(await fs.readFile(`${prevCwd}/app.db`)).toEqual(dbBuffer);

Expand Down Expand Up @@ -558,7 +550,7 @@ describe('useMigrations: true', () => {
'Name of migration': 'add-is-complete',
'Would you like to apply this migration?': false,
});
await expect(setupAndStopDevServerForMigrations(tmp)).rejects.toEqual(new ExitError(0));
await expect(runCommand(tmp, 'dev')).rejects.toEqual(new ExitError(0));

expect(await introspectDb(tmp, dbUrl)).toMatchInlineSnapshot(`
"datasource db {
Expand Down Expand Up @@ -617,7 +609,7 @@ describe('useMigrations: true', () => {
'keystone.js': basicWithMigrations,
});
const recording = recordConsole();
await setupAndStopDevServerForMigrations(tmp);
await runCommand(tmp, 'dev');

expect(await introspectDb(tmp, dbUrl)).toMatchInlineSnapshot(`
"datasource db {
Expand Down Expand Up @@ -653,46 +645,10 @@ describe('useMigrations: true', () => {
✅ GraphQL API ready"
`);
});
test('--reset-db flag', async () => {
const tmp = await setupInitialProjectWithMigrations();
{
const prismaClient = await getPrismaClient(tmp);
await prismaClient.todo.create({ data: { title: 'something' } });
await prismaClient.$disconnect();
}
const recording = recordConsole();
await setupAndStopDevServerForMigrations(tmp, true);
{
const prismaClient = await getPrismaClient(tmp);
expect(await prismaClient.todo.findMany()).toHaveLength(0);
await prismaClient.$disconnect();
}

const { migrationName } = await getGeneratedMigration(tmp, 1, 'init');

expect(recording().replace(new RegExp(migrationName, 'g'), 'migration_name'))
.toMatchInlineSnapshot(`
"✨ Starting Keystone
⭐️ Server listening on :3000 (http://localhost:3000/)
⭐️ GraphQL API available at /api/graphql
✨ Generating GraphQL and Prisma schemas
✨ Your database has been reset
Applying migration \`migration_name\`
✨ The following migration(s) have been applied:

migrations/
└─ migration_name/
└─ migration.sql
✨ Your migrations are up to date, no new migrations need to be created
✨ Connecting to the database
✨ Creating server
✅ GraphQL API ready"
`);
});
test('logs correctly when no migrations need to be created or applied', async () => {
const tmp = await setupInitialProjectWithMigrations();
const recording = recordConsole();
await setupAndStopDevServerForMigrations(tmp);
await runCommand(tmp, 'dev');

expect(recording()).toMatchInlineSnapshot(`
"✨ Starting Keystone
Expand Down
5 changes: 4 additions & 1 deletion packages/core/src/scripts/tests/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,10 @@ async function getSymlinkType(targetPath: string): Promise<'dir' | 'file'> {

export async function runCommand(cwd: string, args: string) {
const argv = parseArgsStringToArgv(args);
return cli(cwd, argv);
const proc = await cli(cwd, argv);
if (typeof proc === 'function') {
await proc();
}
}

let dirsToRemove: string[] = [];
Expand Down