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
65 changes: 39 additions & 26 deletions packages/wb/src/commands/prisma.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ export const prismaCommand: CommandModule = {
describe: 'Run prisma commands',
builder: (yargs) => {
return yargs
.command(cleanUpLitestreamCommand)
.command(createLitestreamConfigCommand)
.command(deployCommand)
.command(deployForceCommand)
.command(createLitestreamConfigCommand)
.command(listBackupsCommand)
.command(litestreamCommand)
.command(setUpDBForLitestreamCommand)
.command(migrateCommand)
.command(migrateDevCommand)
.command(resetCommand)
Expand All @@ -39,6 +40,30 @@ export const prismaCommand: CommandModule = {
},
};

const cleanUpLitestreamCommand: CommandModule<unknown, InferredOptionTypes<typeof builder>> = {
command: 'cleanup-litestream',
describe: 'Clean up temporal Litestream files',
builder,
async handler(argv) {
const allProjects = await findPrismaProjects(argv);
for (const project of prepareForRunningCommand('prisma cleanup-litestream', allProjects)) {
await runWithSpawn(prismaScripts.cleanUpLitestream(project), project, argv);
}
},
};

const createLitestreamConfigCommand: CommandModule<unknown, InferredOptionTypes<typeof builder>> = {
command: 'create-litestream-config',
describe: 'Create Litestream configuration file',
builder,
async handler(argv) {
const allProjects = await findPrismaProjects(argv);
for (const project of prepareForRunningCommand('prisma create-litestream-config', allProjects)) {
createLitestreamConfig(project);
}
},
};

const deployCommand: CommandModule<unknown, InferredOptionTypes<typeof builder>> = {
command: 'deploy',
describe: 'Apply migration to DB without initializing it',
Expand All @@ -64,18 +89,6 @@ const deployForceCommand: CommandModule<unknown, InferredOptionTypes<typeof buil
},
};

const createLitestreamConfigCommand: CommandModule<unknown, InferredOptionTypes<typeof builder>> = {
command: 'create-litestream-config',
describe: 'Create Litestream configuration file',
builder,
async handler(argv) {
const allProjects = await findPrismaProjects(argv);
for (const project of prepareForRunningCommand('prisma create-litestream-config', allProjects)) {
createLitestreamConfig(project);
}
},
};

const listBackupsCommand: CommandModule<unknown, InferredOptionTypes<typeof builder>> = {
command: 'list-backups',
describe: 'List Litestream backups',
Expand All @@ -88,18 +101,6 @@ const listBackupsCommand: CommandModule<unknown, InferredOptionTypes<typeof buil
},
};

const litestreamCommand: CommandModule<unknown, InferredOptionTypes<typeof builder>> = {
command: 'litestream',
describe: 'Setup DB for Litestream',
builder,
async handler(argv) {
const allProjects = await findPrismaProjects(argv);
for (const project of prepareForRunningCommand('prisma litestream', allProjects)) {
await runWithSpawn(prismaScripts.litestream(project), project, argv);
}
},
};

const migrateCommand: CommandModule<unknown, InferredOptionTypes<typeof builder>> = {
command: 'migrate',
describe: 'Apply migration to DB with initializing it',
Expand Down Expand Up @@ -182,6 +183,18 @@ const seedCommand: CommandModule<unknown, InferredOptionTypes<typeof seedBuilder
},
};

const setUpDBForLitestreamCommand: CommandModule<unknown, InferredOptionTypes<typeof builder>> = {
command: 'setup-db-for-litestream',
describe: 'Setup DB for Litestream',
builder,
async handler(argv) {
const allProjects = await findPrismaProjects(argv);
for (const project of prepareForRunningCommand('prisma setup-db-for-litestream', allProjects)) {
await runWithSpawn(prismaScripts.setUpDBForLitestream(project), project, argv);
}
},
};

const studioBuilder = {
...builder,
'db-url-or-path': {
Expand Down
50 changes: 27 additions & 23 deletions packages/wb/src/scripts/prismaScripts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ import { runtimeWithArgs } from '../utils/runtime.js';
* and `YARN zzz` is replaced with `yarn zzz` or `node_modules/.bin/zzz`.
*/
class PrismaScripts {
cleanUpLitestream(project: Project): string {
const dirPath = getDatabaseDirPath(project);
// Cleanup existing artifacts to avoid issues with Litestream replication at first.
return `rm -Rf ${dirPath}/prod.sqlite3-*; rm -Rf ${dirPath}/prod.sqlite3.*; rm -Rf ${dirPath}/.prod.sqlite3*`;
}

deploy(_: Project, additionalOptions = ''): string {
return `PRISMA migrate deploy ${additionalOptions}`;
}
Expand All @@ -26,29 +32,6 @@ class PrismaScripts {
return `litestream ltx -config litestream.yml ${dirPath}/prod.sqlite3`;
}

litestream(project: Project): string {
const dirPath = getDatabaseDirPath(project);
// Cleanup existing artifacts to avoid issues with Litestream replication at first.
// cf. https://litestream.io/tips/
return `rm -Rf ${dirPath}/prod.sqlite3-*; rm -Rf ${dirPath}/prod.sqlite3.*; rm -Rf ${dirPath}/.prod.sqlite3*; ${runtimeWithArgs} -e '
const { PrismaClient } = require("@prisma/client");
const prisma = new PrismaClient();
(async () => {
try {
await prisma.$queryRawUnsafe("PRAGMA busy_timeout = 5000");
await prisma.$queryRawUnsafe("PRAGMA journal_mode = WAL");
await prisma.$queryRawUnsafe("PRAGMA synchronous = NORMAL");
await prisma.$queryRawUnsafe("PRAGMA wal_autocheckpoint = 0");
} catch (error) {
console.error("Failed due to:", error);
process.exit(1);
} finally {
await prisma.$disconnect();
}
})();
'`;
}

migrate(project: Project, additionalOptions = ''): string {
return `PRISMA migrate deploy ${additionalOptions} && PRISMA generate && ${this.seed(project)}`;
}
Expand Down Expand Up @@ -80,6 +63,27 @@ const prisma = new PrismaClient();
return `if [ -e "prisma/seeds.ts" ]; then BUN build-ts run prisma/seeds.ts; fi`;
}

setUpDBForLitestream(_: Project): string {
// cf. https://litestream.io/tips/
return `${runtimeWithArgs} -e '
const { PrismaClient } = require("@prisma/client");
const prisma = new PrismaClient();
(async () => {
try {
await prisma.$queryRawUnsafe("PRAGMA busy_timeout = 5000");
await prisma.$queryRawUnsafe("PRAGMA journal_mode = WAL");
await prisma.$queryRawUnsafe("PRAGMA synchronous = NORMAL");
await prisma.$queryRawUnsafe("PRAGMA wal_autocheckpoint = 0");
} catch (error) {
console.error("Failed due to:", error);
process.exit(1);
} finally {
await prisma.$disconnect();
}
})();
'`;
}

studio(project: Project, dbUrlOrPath?: string, additionalOptions = ''): string {
const FILE_SCHEMA = 'file:';
let prefix = '';
Expand Down