Skip to main content
Glama
test-prd-document.jsโ€ข6.49 kB
import sqlite3 from 'sqlite3'; import { open } from 'sqlite'; async function testPRDDocuments() { try { const db = await open({ filename: './data/workflow.db', driver: sqlite3.Database }); console.log('๐Ÿ”„ PRD ๋ฌธ์„œ ๊ธฐ๋Šฅ ํ…Œ์ŠคํŠธ ์‹œ์ž‘...\n'); // 1. ๋จผ์ € PRD ๋ชฉ๋ก ํ™•์ธ console.log('1๏ธโƒฃ ๊ธฐ์กด PRD ๋ชฉ๋ก:'); const prds = await db.all('SELECT id, title FROM prds LIMIT 3'); prds.forEach(prd => { console.log(` - [${prd.id}] ${prd.title}`); }); if (prds.length === 0) { console.log(' โŒ PRD๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.'); await db.close(); return; } const testPRD = prds[0]; console.log(`\n๐Ÿ“‹ ํ…Œ์ŠคํŠธ ๋Œ€์ƒ: ${testPRD.title}\n`); // 2. PRD์— ์ƒ์„ธ ๋ฌธ์„œ ์ƒ์„ฑ console.log('2๏ธโƒฃ PRD ์ƒ์„ธ ๋ฌธ์„œ ์ƒ์„ฑ...'); const documentResult = await db.run(` INSERT INTO documents (title, content, doc_type, category, tags, summary, created_by, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?) `, [ `${testPRD.title} - ์ƒ์„ธ ๊ธฐ์ˆ  ๋ช…์„ธ์„œ`, `# ${testPRD.title} ์ƒ์„ธ ๋ช…์„ธ ## ๋น„์ฆˆ๋‹ˆ์Šค ๋ชฉํ‘œ ๊ฐœ๋ฐœ์ž ์ค‘์‹ฌ MCP ํŒจํ‚ค์ง€ ๊ณต์œ  ์ปค๋ฎค๋‹ˆํ‹ฐ ๊ตฌ์ถ•. ๋ฌด๋ฃŒ 6๊ฐœ์›” ์šด์˜ ํ›„ ๊ด‘๊ณ +๊ตฌ๋… ์ˆ˜์ต ๋ชจ๋ธ๋กœ ์ง€์†๊ฐ€๋Šฅํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋ชจ๋ธ ๋‹ฌ์„ฑ. ## ํƒ€๊ฒŸ ์‚ฌ์šฉ์ž - MCP ํŒจํ‚ค์ง€ ๊ฐœ๋ฐœ์ž - ํด๋กœ๋“œ ์‚ฌ์šฉ์ž - AI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ์ž ## ์„ฑ๊ณต ๊ธฐ์ค€ - 6๊ฐœ์›”๊ฐ„ ์™„์ „ ๋ฌด๋ฃŒ ์šด์˜ ๋‹ฌ์„ฑ - 3๊ฐœ์›” ๋‚ด ์›” $100+ ์ˆ˜์ต ์ „ํ™˜ - 10,000 MAU ๋‹ฌ์„ฑ - ์ˆ˜์ต ๋Œ€๋น„ ์ธํ”„๋ผ ๋น„์šฉ 20% ์ดํ•˜ ์œ ์ง€ ## ๊ธฐ์ˆ  ์ œ์•ฝ์‚ฌํ•ญ - ์Šคํƒ: SvelteKit + Vercel + Supabase - ๋Œ€์—ญํญ ํ•œ๊ณ„: Supabase 2GB ์ œํ•œ - ๋ฌด๋ฃŒ ํ”Œ๋žœ ์ตœ๋Œ€ ํ™œ์šฉ - 30๋ถ„ ๋‚ด MVP ๋ฐฐํฌ ๊ฐ€๋Šฅ ## ํ•ต์‹ฌ ๊ธฐ๋Šฅ ### ์ธ์ฆ ์‹œ์Šคํ…œ - Google OAuth ์†Œ์…œ ๋กœ๊ทธ์ธ - Supabase Auth ํ™œ์šฉ ### ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ - GitHub API ์—ฐ๋™ ์ž๋™ ์ˆ˜์ง‘ - ํŒจํ‚ค์ง€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ ### ํ‰๊ฐ€ ์‹œ์Šคํ…œ - 5์  ๋งŒ์  ๋ณ„์  ํ‰๊ฐ€ - ์ƒ์„ธ ๋ฆฌ๋ทฐ ์ž‘์„ฑ ### ์ˆ˜์ต ๋ชจ๋ธ - Google AdSense ๊ด‘๊ณ  - ํ”„๋ฆฌ๋ฏธ์—„ ๊ตฌ๋… ($5/์›”)`, 'specification', `prd-${testPRD.id}`, '["mcp", "package-hub", "specification", "technical-spec"]', 'MCP Hub ํŒจํ‚ค์ง€ ๊ณต์œ  ํ”Œ๋žซํผ์˜ ์ƒ์„ธ ๊ธฐ์ˆ  ๋ช…์„ธ์„œ - ๋น„์ฆˆ๋‹ˆ์Šค ๋ชฉํ‘œ, ๊ธฐ์ˆ  ์ œ์•ฝ, ํ•ต์‹ฌ ๊ธฐ๋Šฅ ํฌํ•จ', 'test-script', 'approved' ]); let documentId = documentResult.lastInsertRowid; // SQLite lastInsertRowid๊ฐ€ undefined์ธ ๊ฒฝ์šฐ ์ง์ ‘ ์กฐํšŒ if (!documentId) { const lastDoc = await db.get('SELECT last_insert_rowid() as id'); documentId = lastDoc.id; } console.log(` โœ… ๋ฌธ์„œ ์ƒ์„ฑ ์™„๋ฃŒ! ID: ${documentId}`); if (!documentId) { console.error(' โŒ ๋ฌธ์„œ ID๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.'); await db.close(); return; } // 3. PRD์™€ ๋ฌธ์„œ ์—ฐ๊ฒฐ console.log('\n3๏ธโƒฃ PRD-๋ฌธ์„œ ์—ฐ๊ฒฐ ์ƒ์„ฑ...'); await db.run(` INSERT INTO document_links (document_id, linked_entity_type, linked_entity_id, link_type) VALUES (?, ?, ?, ?) `, [documentId, 'prd', testPRD.id, 'specification']); console.log(' โœ… PRD-๋ฌธ์„œ ์—ฐ๊ฒฐ ์™„๋ฃŒ!'); // 4. ์—ฐ๊ฒฐ๋œ ๋ฌธ์„œ ์กฐํšŒ ํ…Œ์ŠคํŠธ console.log('\n4๏ธโƒฃ PRD ์—ฐ๊ฒฐ ๋ฌธ์„œ ์กฐํšŒ...'); const linkedDocs = await db.all(` SELECT d.id, d.title, d.doc_type, d.summary, d.created_at, dl.link_type, dl.created_at as linked_at FROM documents d INNER JOIN document_links dl ON d.id = dl.document_id WHERE dl.linked_entity_type = 'prd' AND dl.linked_entity_id = ? `, [testPRD.id]); console.log(` ๐Ÿ“„ ์—ฐ๊ฒฐ๋œ ๋ฌธ์„œ ${linkedDocs.length}๊ฐœ:`); linkedDocs.forEach(doc => { console.log(` - [${doc.id}] ${doc.title}`); console.log(` ๐Ÿ“‹ ์œ ํ˜•: ${doc.doc_type} | ๐Ÿ”— ๋งํฌ: ${doc.link_type}`); console.log(` ๐Ÿ“ ์š”์•ฝ: ${doc.summary}`); console.log(` ๐Ÿ“… ์ƒ์„ฑ: ${new Date(doc.created_at).toLocaleString('ko-KR')}`); }); // 5. FTS ๊ฒ€์ƒ‰ ํ…Œ์ŠคํŠธ console.log('\n5๏ธโƒฃ ์ „๋ฌธ ๊ฒ€์ƒ‰ ํ…Œ์ŠคํŠธ...'); const searchResults = await db.all(` SELECT d.id, d.title, snippet(documents_fts, 1, '<mark>', '</mark>', '...', 15) as snippet FROM documents d INNER JOIN document_links dl ON d.id = dl.document_id INNER JOIN documents_fts ON documents_fts.rowid = d.id WHERE dl.linked_entity_type = 'prd' AND dl.linked_entity_id = ? AND documents_fts MATCH ? ORDER BY rank `, [testPRD.id, '์ˆ˜์ต']); console.log(` ๐Ÿ” "์ˆ˜์ต" ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ${searchResults.length}๊ฐœ:`); searchResults.forEach(result => { console.log(` - [${result.id}] ${result.title}`); console.log(` ๐Ÿ“„ ์Šค๋‹ˆํŽซ: ${result.snippet}`); }); // 6. ์—…๋ฐ์ดํŠธ ํ…Œ์ŠคํŠธ console.log('\n6๏ธโƒฃ ๋ฌธ์„œ ์—…๋ฐ์ดํŠธ ํ…Œ์ŠคํŠธ...'); await db.run(` UPDATE documents SET summary = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ? `, [ 'MCP Hub ํ”Œ๋žซํผ ์ƒ์„ธ ๋ช…์„ธ - ์—…๋ฐ์ดํŠธ๋จ (๋น„์ฆˆ๋‹ˆ์Šค ๋ชฉํ‘œ, ๊ธฐ์ˆ  ์Šคํƒ, ์ˆ˜์ต ๋ชจ๋ธ ํฌํ•จ)', documentId ]); console.log(` โœ… ๋ฌธ์„œ [${documentId}] ์—…๋ฐ์ดํŠธ ์™„๋ฃŒ!`); // 7. ์ตœ์ข… ๊ฒ€์ฆ console.log('\n7๏ธโƒฃ ์ตœ์ข… ๊ฒ€์ฆ...'); const finalDoc = await db.get(` SELECT d.*, dl.link_type FROM documents d INNER JOIN document_links dl ON d.id = dl.document_id WHERE d.id = ? `, [documentId]); console.log(' ๐Ÿ“‹ ์ตœ์ข… ๋ฌธ์„œ ์ •๋ณด:'); console.log(` - ID: ${finalDoc.id}`); console.log(` - ์ œ๋ชฉ: ${finalDoc.title}`); console.log(` - ์œ ํ˜•: ${finalDoc.doc_type}`); console.log(` - ๋งํฌ: ${finalDoc.link_type}`); console.log(` - ์นดํ…Œ๊ณ ๋ฆฌ: ${finalDoc.category}`); console.log(` - ์ƒํƒœ: ${finalDoc.status}`); console.log(` - ์š”์•ฝ: ${finalDoc.summary}`); await db.close(); console.log('\n๐ŸŽ‰ PRD ๋ฌธ์„œ ์‹œ์Šคํ…œ ํ…Œ์ŠคํŠธ ์™„๋ฃŒ!'); console.log('\n๐Ÿ“Š ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ:'); console.log(' โœ… PRD ์ƒ์„ธ ๋ฌธ์„œ ์ƒ์„ฑ'); console.log(' โœ… PRD-๋ฌธ์„œ ์ž๋™ ์—ฐ๊ฒฐ'); console.log(' โœ… ์—ฐ๊ฒฐ ๋ฌธ์„œ ์กฐํšŒ'); console.log(' โœ… ์ „๋ฌธ ๊ฒ€์ƒ‰ (FTS)'); console.log(' โœ… ๋ฌธ์„œ ์—…๋ฐ์ดํŠธ'); console.log(' โœ… ๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ ๊ฒ€์ฆ'); } catch (error) { console.error('โŒ ํ…Œ์ŠคํŠธ ์‹คํŒจ:', error.message); console.error(error.stack); } } testPRDDocuments();

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/foswmine/workflow-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server