sinka/api/src/tenancy/provision-database.ts
2026-09-15 21:10:42 -03:00

36 lines
1.4 KiB
TypeScript

import { execFile } from 'node:child_process';
import { join } from 'node:path';
import { promisify } from 'node:util';
import { PrismaClient as PlatformPrismaClient } from '../generated/platform';
import { adminDatabaseUrl, tenantDatabaseName, urlForDatabase } from './tenant-url';
const execFileAsync = promisify(execFile);
export async function createMysqlDatabase(database: string): Promise<void> {
const admin = new PlatformPrismaClient({
datasources: { db: { url: adminDatabaseUrl() } },
});
try {
await admin.$executeRawUnsafe(
`CREATE DATABASE IF NOT EXISTS \`${database}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci`,
);
await admin.$executeRawUnsafe(`GRANT ALL PRIVILEGES ON \`${database}\`.* TO 'sinka'@'%'`);
await admin.$executeRawUnsafe('FLUSH PRIVILEGES');
} finally {
await admin.$disconnect();
}
}
export async function pushTenantSchema(database: string): Promise<void> {
const prismaCli = join(process.cwd(), 'node_modules', 'prisma', 'build', 'index.js');
const schema = join(process.cwd(), 'prisma', 'tenant', 'schema.prisma');
await execFileAsync(process.execPath, [prismaCli, 'db', 'push', '--schema', schema, '--skip-generate'], {
env: { ...process.env, DATABASE_URL: urlForDatabase(database) },
timeout: 90_000,
});
}
export function databaseForSlug(slug: string): string {
return tenantDatabaseName(slug);
}