여러 줄 주석이 설명보다 경위(예전·실측·지적)를 적고 있어 읽는 사람이 결론을 찾기 어려웠다. - ts·tsx·js·mjs·css·py 478개: 여러 줄 주석은 첫 문장 한 줄로, 과거형·날짜 문장은 삭제 - 주석 위치는 TypeScript 파서·파이썬 tokenize/ast 로 찾는다 — 문자열 안의 # · /* 는 건드리지 않는다 - eslint·ts·noqa·type: ignore 같은 지시 주석은 그대로 둔다 파이썬 275개 정리 전후 AST 동일, TS 298개 주석 뺀 토큰 동일(빈 JSX 주석 10곳만 차이). site·frontend·admin tsc, site vitest 105 passed Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
118 lines
4.3 KiB
TypeScript
118 lines
4.3 KiB
TypeScript
import { asJson, createSql } from './db';
|
|
|
|
const industries = [
|
|
['beauty', 'beauty', '뷰티'],
|
|
['beauty.hair', 'beauty.hair', '미용실'],
|
|
['beauty.nail', 'beauty.nail', '네일샵'],
|
|
['food', 'food', '음식점'],
|
|
['food.korean', 'food.korean', '한식당'],
|
|
['health', 'health', '의료'],
|
|
['health.dental', 'health.dental', '치과'],
|
|
['stay', 'stay', '숙박'],
|
|
['stay.pension', 'stay.pension', '펜션'],
|
|
];
|
|
|
|
const regions = [
|
|
['kr', 'kr', '대한민국'],
|
|
['kr.seoul', 'kr.seoul', '서울'],
|
|
['kr.seoul.gangnam', 'kr.seoul.gangnam', '강남'],
|
|
['kr.seoul.mapo', 'kr.seoul.mapo', '마포'],
|
|
['kr.busan', 'kr.busan', '부산'],
|
|
['kr.busan.haeundae', 'kr.busan.haeundae', '해운대'],
|
|
['kr.jeonbuk', 'kr.jeonbuk', '전북'],
|
|
['kr.jeonbuk.gunsan', 'kr.jeonbuk.gunsan', '군산'],
|
|
];
|
|
|
|
const merchants = [
|
|
{
|
|
externalId: 'site-1001',
|
|
name: '레브살롱',
|
|
industryId: 'beauty.hair',
|
|
regionId: 'kr.seoul.gangnam',
|
|
description: '강남역 3번 출구 앞 프라이빗 헤어살롱. 1:1 디자이너 전담 시스템.',
|
|
siteUrl: 'https://rev-salon.example.com',
|
|
profile: {
|
|
services: ['남자 커트', '여성 펌', '뿌리염색', '두피 클리닉'],
|
|
features: ['주차 가능', '심야 영업', '예약제'],
|
|
priceRange: '30,000~120,000원',
|
|
},
|
|
},
|
|
{
|
|
externalId: 'site-1002',
|
|
name: '헤어랩 강남점',
|
|
industryId: 'beauty.hair',
|
|
regionId: 'kr.seoul.gangnam',
|
|
description: '강남 대형 헤어샵. 염색과 클리닉 전문.',
|
|
siteUrl: 'https://hairlab.example.com',
|
|
profile: {
|
|
services: ['뿌리 염색', '여성 펌', '두피클리닉'],
|
|
features: ['주차가능', '단체 예약'],
|
|
priceRange: '25,000~150,000원',
|
|
},
|
|
},
|
|
{
|
|
externalId: 'site-2001',
|
|
name: '해운대 소담한상',
|
|
industryId: 'food.korean',
|
|
regionId: 'kr.busan.haeundae',
|
|
description: '해운대 해변 인근 한정식집. 제철 해산물 코스 제공.',
|
|
siteUrl: 'https://sodam.example.com',
|
|
profile: {
|
|
services: ['한정식 코스', '점심 특선', '단체 예약'],
|
|
features: ['오션뷰', '룸 완비', '발렛파킹'],
|
|
priceRange: '25,000~80,000원',
|
|
},
|
|
},
|
|
{
|
|
// 실제 업체.
|
|
externalId: 'site-3001',
|
|
name: '스테이머뭄',
|
|
industryId: 'stay.pension',
|
|
regionId: 'kr.jeonbuk.gunsan',
|
|
description:
|
|
'군산 원도심 말랭이마을 옆에 자리한 독채 스테이. A동·B동 두 채를 통째로 쓰며 기준 2인, 최대 4인.',
|
|
siteUrl: 'https://www.instagram.com/staymeomoom/',
|
|
profile: {
|
|
services: ['독채 대여', 'A동', 'B동'],
|
|
features: ['독채', '프라이빗', '2인 기준', '최대 4인', '원도심', '감성숙소'],
|
|
audiences: ['커플', '친구', '가족', '혼자'],
|
|
nearby: ['말랭이마을', '신흥동 일본식가옥', '동국사', '초원사진관', '이성당',
|
|
'경암동 철길마을', '근대역사박물관', '월명공원', '시간여행마을'],
|
|
address: '전북특별자치도 군산시 절골길 18 (신흥동)',
|
|
capacity: { standard: 2, max: 4 },
|
|
buildings: 2,
|
|
unverified: ['가격', '바베큐', '스파', '주차', '애견동반'],
|
|
},
|
|
},
|
|
];
|
|
|
|
async function main() {
|
|
const sql = createSql();
|
|
|
|
for (const [id, path, name] of industries) {
|
|
await sql`INSERT INTO industry (id, path, name) VALUES (${id}, ${path}::ltree, ${name})
|
|
ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name`;
|
|
}
|
|
for (const [id, path, name] of regions) {
|
|
await sql`INSERT INTO region (id, path, name) VALUES (${id}, ${path}::ltree, ${name})
|
|
ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name`;
|
|
}
|
|
for (const m of merchants) {
|
|
await sql`
|
|
INSERT INTO merchant (external_id, name, industry_id, region_id, description, profile, site_url)
|
|
VALUES (${m.externalId}, ${m.name}, ${m.industryId}, ${m.regionId},
|
|
${m.description}, ${sql.json(asJson(m.profile))}, ${m.siteUrl})
|
|
ON CONFLICT (external_id) DO UPDATE SET
|
|
name = EXCLUDED.name, description = EXCLUDED.description,
|
|
profile = EXCLUDED.profile, updated_at = now()`;
|
|
}
|
|
|
|
await sql.end();
|
|
console.log(`✅ seed: industry=${industries.length} region=${regions.length} merchant=${merchants.length}`);
|
|
}
|
|
|
|
main().catch((e) => {
|
|
console.error('❌ seed failed:', e);
|
|
process.exit(1);
|
|
});
|