7f59b94dcf
Rebrand repository from "Re:Link" to "Startover" across the codebase. Updates include package names and scopes (@relink/* -> @startover/*), import paths, Next.js transpile settings, vitest name, UI text and docs, Dockerfile and CI/workflow names, deploy scripts and repo paths, and example/production env values. Also add auth-related env vars, an apps/web .env symlink, and small formatting/typing cleanups in several TSX/TS files and tests to accommodate the rename.
198 lines
4.4 KiB
TypeScript
198 lines
4.4 KiB
TypeScript
import { PrismaClient } from '@prisma/client';
|
|
import { execSync } from 'node:child_process';
|
|
import { resolve, dirname } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const SCHEMA_PATH = resolve(__dirname, '../prisma/schema.prisma');
|
|
|
|
const TEST_DATABASE_URL =
|
|
process.env['DATABASE_TEST_URL'] ??
|
|
'postgresql://startover:startover_test@localhost:5433/startover_test';
|
|
|
|
let testClient: PrismaClient | null = null;
|
|
|
|
export function getTestPrismaClient(): PrismaClient {
|
|
if (testClient) {
|
|
return testClient;
|
|
}
|
|
|
|
testClient = new PrismaClient({
|
|
datasourceUrl: TEST_DATABASE_URL,
|
|
log: ['error'],
|
|
});
|
|
|
|
return testClient;
|
|
}
|
|
|
|
export async function setupTestDatabase(): Promise<PrismaClient> {
|
|
execSync(
|
|
`DATABASE_URL="${TEST_DATABASE_URL}" npx prisma db push --schema="${SCHEMA_PATH}" --skip-generate --accept-data-loss`,
|
|
{
|
|
stdio: 'pipe',
|
|
cwd: resolve(__dirname, '..'),
|
|
},
|
|
);
|
|
|
|
const client = getTestPrismaClient();
|
|
await client.$connect();
|
|
return client;
|
|
}
|
|
|
|
export async function teardownTestDatabase(): Promise<void> {
|
|
if (testClient) {
|
|
await testClient.$disconnect();
|
|
testClient = null;
|
|
}
|
|
}
|
|
|
|
const TABLE_NAMES = [
|
|
'signature_evidences',
|
|
'contract_versions',
|
|
'escrow_transactions',
|
|
'inspection_records',
|
|
'dispute_cases',
|
|
'contracts',
|
|
'subsidy_documents',
|
|
'subsidy_checklist_items',
|
|
'subsidy_cases',
|
|
'match_requests',
|
|
'store_photos',
|
|
'store_lifecycles',
|
|
'store_facilities',
|
|
'store_leases',
|
|
'stores',
|
|
'vendor_coverage_regions',
|
|
'vendor_certifications',
|
|
'vendors',
|
|
'user_consents',
|
|
'user_profiles',
|
|
'users',
|
|
'outbox_events',
|
|
'event_logs',
|
|
'audit_logs',
|
|
'idempotency_keys',
|
|
'feature_flags',
|
|
'policy_versions',
|
|
'industry_taxonomies',
|
|
'region_hierarchies',
|
|
];
|
|
|
|
export async function cleanAllTables(prisma: PrismaClient): Promise<void> {
|
|
for (const table of TABLE_NAMES) {
|
|
await prisma.$executeRawUnsafe(`TRUNCATE TABLE "${table}" CASCADE`);
|
|
}
|
|
}
|
|
|
|
export async function seedTestMasterData(prisma: PrismaClient): Promise<void> {
|
|
// 지역 마스터 데이터
|
|
const kr = await prisma.regionHierarchy.create({
|
|
data: {
|
|
code: 'KR',
|
|
nameKo: '대한민국',
|
|
regionType: 'COUNTRY',
|
|
depth: 0,
|
|
pathCode: 'KR',
|
|
sortOrder: 1,
|
|
isActive: true,
|
|
isBetaEnabled: false,
|
|
},
|
|
});
|
|
|
|
const seoul = await prisma.regionHierarchy.create({
|
|
data: {
|
|
code: 'KR.SEOUL',
|
|
nameKo: '서울특별시',
|
|
regionType: 'SIDO',
|
|
parentId: kr.id,
|
|
depth: 1,
|
|
pathCode: 'KR.SEOUL',
|
|
sortOrder: 1,
|
|
isActive: true,
|
|
isBetaEnabled: false,
|
|
},
|
|
});
|
|
|
|
const gangnam = await prisma.regionHierarchy.create({
|
|
data: {
|
|
code: 'KR.SEOUL.GANGNAM',
|
|
nameKo: '강남구',
|
|
regionType: 'SIGUNGU',
|
|
parentId: seoul.id,
|
|
depth: 2,
|
|
pathCode: 'KR.SEOUL.GANGNAM',
|
|
sortOrder: 1,
|
|
isActive: true,
|
|
isBetaEnabled: false,
|
|
},
|
|
});
|
|
|
|
await prisma.regionHierarchy.create({
|
|
data: {
|
|
code: 'KR.BETA.GANGNAM_CORE',
|
|
nameKo: '강남권 베타 클러스터',
|
|
regionType: 'BETA_CLUSTER',
|
|
parentId: gangnam.id,
|
|
depth: 3,
|
|
pathCode: 'KR.BETA.GANGNAM_CORE',
|
|
sortOrder: 10,
|
|
isActive: true,
|
|
isBetaEnabled: true,
|
|
},
|
|
});
|
|
|
|
// 비베타 지역 (테스트용)
|
|
await prisma.regionHierarchy.create({
|
|
data: {
|
|
code: 'KR.BUSAN',
|
|
nameKo: '부산광역시',
|
|
regionType: 'SIDO',
|
|
parentId: kr.id,
|
|
depth: 1,
|
|
pathCode: 'KR.BUSAN',
|
|
sortOrder: 2,
|
|
isActive: true,
|
|
isBetaEnabled: false,
|
|
},
|
|
});
|
|
|
|
// 업종 마스터 데이터
|
|
const fnb = await prisma.industryTaxonomy.create({
|
|
data: {
|
|
code: 'FNB',
|
|
nameKo: '음식점/카페',
|
|
depth: 0,
|
|
sortOrder: 1,
|
|
isLeaf: false,
|
|
isActive: true,
|
|
isBetaEnabled: true,
|
|
},
|
|
});
|
|
|
|
await prisma.industryTaxonomy.create({
|
|
data: {
|
|
code: 'FNB.CAFE',
|
|
nameKo: '카페',
|
|
parentId: fnb.id,
|
|
depth: 1,
|
|
sortOrder: 1,
|
|
isLeaf: true,
|
|
isActive: true,
|
|
isBetaEnabled: true,
|
|
},
|
|
});
|
|
|
|
await prisma.industryTaxonomy.create({
|
|
data: {
|
|
code: 'FNB.KOREAN',
|
|
nameKo: '한식',
|
|
parentId: fnb.id,
|
|
depth: 1,
|
|
sortOrder: 3,
|
|
isLeaf: true,
|
|
isActive: true,
|
|
isBetaEnabled: true,
|
|
},
|
|
});
|
|
}
|