@bcdflow/dev-inspector 2.0.1 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +7 -11
- package/dist/middleware/index.js +7 -18
- package/dist/middleware/index.js.map +2 -2
- package/package.json +1 -1
package/bin/cli.js
CHANGED
|
@@ -120,15 +120,10 @@ function activate() {
|
|
|
120
120
|
|
|
121
121
|
// 즉시 검증 시도
|
|
122
122
|
console.log('Validating license...');
|
|
123
|
-
const body = JSON.stringify({
|
|
124
|
-
key,
|
|
125
|
-
package: 'dev-inspector',
|
|
126
|
-
version: '2.0.0',
|
|
127
|
-
machineId: getMachineId(),
|
|
128
|
-
});
|
|
123
|
+
const body = JSON.stringify({ key });
|
|
129
124
|
|
|
130
125
|
const https = require('https');
|
|
131
|
-
const req = https.request('https://gate.bcdflow.net/api/
|
|
126
|
+
const req = https.request('https://gate.bcdflow.net/api/license/validate', {
|
|
132
127
|
method: 'POST',
|
|
133
128
|
headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) },
|
|
134
129
|
timeout: 5000,
|
|
@@ -145,16 +140,17 @@ function activate() {
|
|
|
145
140
|
try {
|
|
146
141
|
if (fs.existsSync(CACHE_FILE)) cache = JSON.parse(fs.readFileSync(CACHE_FILE, 'utf-8'));
|
|
147
142
|
} catch {}
|
|
143
|
+
const expiresAt = result.license?.expiresAt || null;
|
|
148
144
|
cache[keyHash] = {
|
|
149
|
-
tier:
|
|
145
|
+
tier: 'pro',
|
|
150
146
|
valid: true,
|
|
151
|
-
expiresAt
|
|
147
|
+
expiresAt,
|
|
152
148
|
checkedAt: Date.now(),
|
|
153
149
|
};
|
|
154
150
|
fs.writeFileSync(CACHE_FILE, JSON.stringify(cache, null, 2));
|
|
155
151
|
|
|
156
|
-
console.log(`\n✓ License activated:
|
|
157
|
-
if (
|
|
152
|
+
console.log(`\n✓ License activated: Pro`);
|
|
153
|
+
if (expiresAt) console.log(` Expires: ${expiresAt.split('T')[0]}`);
|
|
158
154
|
console.log('\nRestart your server to apply. Or set DEV_INSPECTOR_KEY in .env');
|
|
159
155
|
} else {
|
|
160
156
|
console.error(`\n✗ License validation failed: ${result.error || 'Unknown error'}`);
|
package/dist/middleware/index.js
CHANGED
|
@@ -105,7 +105,7 @@ var crypto = __toESM(require("crypto"));
|
|
|
105
105
|
var os = __toESM(require("os"));
|
|
106
106
|
var fs = __toESM(require("fs"));
|
|
107
107
|
var path = __toESM(require("path"));
|
|
108
|
-
var VALIDATE_URL = "https://gate.bcdflow.net/api/
|
|
108
|
+
var VALIDATE_URL = "https://gate.bcdflow.net/api/license/validate";
|
|
109
109
|
var CACHE_DIR = path.join(os.homedir(), ".dev-inspector");
|
|
110
110
|
var CACHE_FILE = path.join(CACHE_DIR, "license-cache.json");
|
|
111
111
|
var CACHE_TTL = 24 * 60 * 60 * 1e3;
|
|
@@ -117,14 +117,6 @@ var FREE_STATUS = {
|
|
|
117
117
|
checkedAt: Date.now()
|
|
118
118
|
};
|
|
119
119
|
var _currentStatus = { ...FREE_STATUS };
|
|
120
|
-
function getMachineId() {
|
|
121
|
-
try {
|
|
122
|
-
const raw = os.hostname() + ":" + os.userInfo().username;
|
|
123
|
-
return crypto.createHash("sha256").update(raw).digest("hex").slice(0, 16);
|
|
124
|
-
} catch {
|
|
125
|
-
return "unknown";
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
120
|
function readCache(key) {
|
|
129
121
|
try {
|
|
130
122
|
if (!fs.existsSync(CACHE_FILE)) return null;
|
|
@@ -155,12 +147,8 @@ function writeCache(key, status) {
|
|
|
155
147
|
}
|
|
156
148
|
}
|
|
157
149
|
async function remoteValidate(key) {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
package: "dev-inspector",
|
|
161
|
-
version: "2.0.0",
|
|
162
|
-
machineId: getMachineId()
|
|
163
|
-
});
|
|
150
|
+
var _a;
|
|
151
|
+
const body = JSON.stringify({ key });
|
|
164
152
|
const controller = new AbortController();
|
|
165
153
|
const timer = setTimeout(() => controller.abort(), VALIDATE_TIMEOUT);
|
|
166
154
|
try {
|
|
@@ -175,10 +163,11 @@ async function remoteValidate(key) {
|
|
|
175
163
|
return { ...FREE_STATUS, checkedAt: Date.now() };
|
|
176
164
|
}
|
|
177
165
|
const data = await res.json();
|
|
166
|
+
const isValid = !!data.valid;
|
|
178
167
|
return {
|
|
179
|
-
tier:
|
|
180
|
-
valid:
|
|
181
|
-
expiresAt: data.expiresAt || null,
|
|
168
|
+
tier: isValid ? "pro" : "free",
|
|
169
|
+
valid: isValid,
|
|
170
|
+
expiresAt: ((_a = data.license) == null ? void 0 : _a.expiresAt) || null,
|
|
182
171
|
checkedAt: Date.now()
|
|
183
172
|
};
|
|
184
173
|
} catch {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/middleware/index.ts", "../../src/middleware/routes.ts", "../../src/middleware/emitter.ts", "../../src/mcp/tools.ts", "../../src/license/validator.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Dev InSpector Express Middleware\n *\n * Usage:\n * const { devInspector } = require('@bcdflow/dev-inspector');\n * app.use(devInspector({ licenseKey: process.env.DEV_INSPECTOR_KEY }));\n */\nimport { createRoutes } from './routes';\nimport { validateLicense, getLicenseStatus, loadKeyFromConfig } from '../license/validator';\n\nexport interface DevInspectorOptions {\n /** \uB77C\uC774\uC120\uC2A4 \uD0A4 (\uC5C6\uC73C\uBA74 DEV_INSPECTOR_KEY \uD658\uACBD\uBCC0\uC218 \uB610\uB294 ~/.dev-inspector/config.json) */\n licenseKey?: string;\n /** API \uB77C\uC6B0\uD2B8 \uC811\uB450\uC0AC (\uAE30\uBCF8: '/api/v1/dev-inspector') */\n prefix?: string;\n /** production\uC5D0\uC11C\uB3C4 \uD65C\uC131\uD654 (\uAE30\uBCF8: false) */\n enabled?: boolean;\n /** HTML \uC751\uB2F5\uC5D0 \uD074\uB77C\uC774\uC5B8\uD2B8 \uC2A4\uD06C\uB9BD\uD2B8 \uC790\uB3D9 \uC8FC\uC785 (\uAE30\uBCF8: false) */\n autoInject?: boolean;\n}\n\n// express\uB97C \uD638\uC2A4\uD2B8 \uD504\uB85C\uC81D\uD2B8\uC5D0\uC11C resolve\nfunction getExpress(): any {\n try {\n const { createRequire } = require('module');\n const hostRequire = createRequire(process.cwd() + '/package.json');\n return hostRequire('express');\n } catch {\n return require('express');\n }\n}\n\n// \uB77C\uC774\uC120\uC2A4 \uAC80\uC99D Promise (startup \uC2DC \uD55C \uBC88\uB9CC)\nlet _licensePromise: Promise<void> | null = null;\n\nexport function devInspector(options: DevInspectorOptions = {}): any {\n const {\n prefix = '/api/v1/dev-inspector',\n enabled,\n autoInject = false,\n } = options;\n\n const express = getExpress();\n const router = express.Router();\n\n // production \uD658\uACBD \uCCB4\uD06C\n const isEnabled = enabled !== undefined ? enabled : process.env.NODE_ENV !== 'production';\n if (!isEnabled) {\n return router;\n }\n\n // \uB77C\uC774\uC120\uC2A4 \uD0A4 resolve: options > env > config file\n const licenseKey = options.licenseKey\n || process.env.DEV_INSPECTOR_KEY\n || loadKeyFromConfig();\n\n // \uBE44\uB3D9\uAE30 \uAC80\uC99D \uC2DC\uC791 (\uC11C\uBC84 \uC2DC\uC791\uC744 \uBE14\uB85D\uD558\uC9C0 \uC54A\uC74C)\n _licensePromise = validateLicense(licenseKey).then((status) => {\n if (status.tier === 'pro') {\n console.log(`[dev-inspector] License: Pro (valid${status.expiresAt ? ` until ${status.expiresAt.split('T')[0]}` : ''})`);\n } else if (licenseKey) {\n console.log('[dev-inspector] License: invalid or expired \u2014 Free tier (11 tools)');\n } else {\n console.log('[dev-inspector] Free tier (11 tools). Set DEV_INSPECTOR_KEY for full access.');\n }\n });\n\n // API \uB77C\uC6B0\uD2B8 \uB9C8\uC6B4\uD2B8\n router.use(prefix, createRoutes());\n\n // \uD074\uB77C\uC774\uC5B8\uD2B8 \uC790\uB3D9 \uC8FC\uC785\n if (autoInject) {\n router.use((req: any, res: any, next: any) => {\n const originalSend = res.send.bind(res);\n res.send = function (body: any) {\n if (typeof body === 'string' && (body.includes('</body>') || body.includes('</html>'))) {\n const scriptTag = `<script src=\"${prefix}/client.js\" defer><\\/script>`;\n if (body.includes('</body>')) {\n body = body.replace('</body>', `${scriptTag}\\n</body>`);\n } else if (body.includes('</html>')) {\n body = body.replace('</html>', `${scriptTag}\\n</html>`);\n }\n }\n return originalSend(body);\n };\n next();\n });\n }\n\n return router;\n}\n\n/** \uB77C\uC774\uC120\uC2A4 \uAC80\uC99D \uC644\uB8CC \uB300\uAE30 (routes\uC5D0\uC11C \uC0AC\uC6A9) */\nexport function waitForLicense(): Promise<void> {\n if (_licensePromise) return _licensePromise;\n return Promise.resolve();\n}\n\nexport { createRoutes } from './routes';\nexport { inspectorEmitter } from './emitter';\nexport { getLicenseStatus } from '../license/validator';\n", "/**\n * Dev Inspector MCP Routes \u2014 SSE + REST \uBE0C\uB9BF\uC9C0 + \uB77C\uC774\uC120\uC2A4 \uAC8C\uC774\uD305\n */\nimport { readFileSync } from 'fs';\nimport { join } from 'path';\nimport { inspectorEmitter } from './emitter';\nimport { getToolsForTier, FREE_TOOL_NAMES } from '../mcp/tools';\nimport { getLicenseStatus } from '../license/validator';\nimport { waitForLicense } from './index';\n\nfunction getExpress(): any {\n try {\n const { createRequire } = require('module');\n const hostRequire = createRequire(process.cwd() + '/package.json');\n return hostRequire('express');\n } catch {\n return require('express');\n }\n}\n\nexport function createRoutes(): any {\n const express = getExpress();\n const router = express.Router();\n\n const sseClients = new Set<any>();\n const pendingResults = new Map<string, {\n resolve: (value: unknown) => void;\n timer: ReturnType<typeof setTimeout>;\n }>();\n\n // ========== SSE \uC2A4\uD2B8\uB9BC ==========\n router.get('/stream', (req: any, res: any) => {\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no');\n res.flushHeaders();\n\n res.write(`data: ${JSON.stringify({ type: 'connected', timestamp: Date.now() })}\\n\\n`);\n sseClients.add(res);\n\n const heartbeat = setInterval(() => {\n res.write(': heartbeat\\n\\n');\n }, 30000);\n\n req.on('close', () => {\n clearInterval(heartbeat);\n sseClients.delete(res);\n });\n });\n\n function broadcast(event: string, data: unknown): void {\n const payload = `event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`;\n for (const client of sseClients) {\n try { client.write(payload); } catch { sseClients.delete(client); }\n }\n }\n\n // ========== \uB3C4\uAD6C \uD638\uCD9C (\uB77C\uC774\uC120\uC2A4 \uAC8C\uC774\uD305) ==========\n router.post('/call', async (req: any, res: any) => {\n const { id, tool, params } = req.body;\n if (!id || !tool) {\n res.status(400).json({ error: 'id and tool are required' });\n return;\n }\n\n // \uB77C\uC774\uC120\uC2A4 \uAC80\uC99D \uC644\uB8CC \uB300\uAE30 (\uCD5C\uB300 2\uCD08)\n try {\n await Promise.race([\n waitForLicense(),\n new Promise(r => setTimeout(r, 2000)),\n ]);\n } catch { /* ignore */ }\n\n // Pro \uB3C4\uAD6C\uB97C Free tier\uC5D0\uC11C \uD638\uCD9C \uC2DC \uCC28\uB2E8\n const status = getLicenseStatus();\n if (status.tier === 'free' && !FREE_TOOL_NAMES.has(tool)) {\n res.json({\n result: {\n error: `\"${tool}\" requires a Pro license. Set DEV_INSPECTOR_KEY for full access.`,\n upgrade: true,\n freeTier: true,\n },\n });\n return;\n }\n\n if (sseClients.size === 0) {\n res.json({ error: 'No browser connected. Open a page with dev-inspector client loaded.' });\n return;\n }\n\n broadcast('tool_call', { id, tool, params });\n\n try {\n const result = await new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n pendingResults.delete(id);\n reject(new Error('Tool call timed out (30s)'));\n }, 30000);\n pendingResults.set(id, { resolve, timer });\n });\n res.json({ result });\n } catch (err: any) {\n res.json({ error: err.message });\n }\n });\n\n // ========== \uB3C4\uAD6C \uACB0\uACFC ==========\n router.post('/result', (req: any, res: any) => {\n const { id, result } = req.body;\n if (!id) {\n res.status(400).json({ error: 'id is required' });\n return;\n }\n const pending = pendingResults.get(id);\n if (pending) {\n clearTimeout(pending.timer);\n pendingResults.delete(id);\n pending.resolve(result);\n }\n res.json({ success: true });\n });\n\n // ========== \uBE0C\uB77C\uC6B0\uC800 \uC774\uBCA4\uD2B8 ==========\n router.post('/event', (req: any, res: any) => {\n inspectorEmitter.emit('browser_event', req.body);\n res.json({ success: true });\n });\n\n // ========== \uB3C4\uAD6C \uBAA9\uB85D (\uB77C\uC774\uC120\uC2A4 \uAE30\uBC18 \uD544\uD130\uB9C1) ==========\n router.get('/tools', (_req: any, res: any) => {\n const status = getLicenseStatus();\n res.json({ tools: getToolsForTier(status.tier) });\n });\n\n // ========== \uB77C\uC774\uC120\uC2A4 \uC0C1\uD0DC ==========\n router.get('/license-status', (_req: any, res: any) => {\n const status = getLicenseStatus();\n res.json({\n tier: status.tier,\n valid: status.valid,\n expiresAt: status.expiresAt,\n });\n });\n\n // ========== \uD074\uB77C\uC774\uC5B8\uD2B8 JS \uBC88\uB4E4 ==========\n let clientBundle: string | null = null;\n\n router.get('/client.js', (_req: any, res: any) => {\n if (!clientBundle) {\n try {\n clientBundle = readFileSync(join(__dirname, '..', 'client', 'dev-inspector.js'), 'utf-8');\n } catch {\n res.status(404).send('// Client bundle not found. Run: npm run build');\n return;\n }\n }\n res.setHeader('Content-Type', 'application/javascript');\n res.send(clientBundle);\n });\n\n // ========== \uC0C1\uD0DC \uD655\uC778 ==========\n router.get('/status', (_req: any, res: any) => {\n const status = getLicenseStatus();\n res.json({\n connected: sseClients.size > 0,\n clients: sseClients.size,\n pendingCalls: pendingResults.size,\n license: status.tier,\n });\n });\n\n return router;\n}\n", "/**\n * Inspector Event Emitter \u2014 \uB3C4\uAD6C \uD638\uCD9C/\uACB0\uACFC \uBE0C\uB9BF\uC9C0\n * MCP \uC11C\uBC84 \u2192 Express \uB77C\uC6B0\uD2B8 \u2192 SSE \u2192 \uBE0C\uB77C\uC6B0\uC800 \uAC04 \uC774\uBCA4\uD2B8 \uC911\uACC4\n */\nimport { EventEmitter } from 'events';\n\nexport const inspectorEmitter = new EventEmitter();\ninspectorEmitter.setMaxListeners(50);\n", "/**\n * MCP Tool Definitions \u2014 34\uAC1C DOM \uAC80\uC0AC \uB3C4\uAD6C\n * tier: 'free' (11\uAC1C) | 'pro' (23\uAC1C)\n */\nexport const MCP_TOOLS = [\n // ===== Free Tier (11\uAC1C) =====\n { name: 'inspect_element', tier: 'free', description: 'Inspect a DOM element by CSS selector. Returns selector, classes, computed styles, bounding box, hierarchy, accessibility, and text content.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'CSS selector' } }, required: ['selector'] } },\n { name: 'select_element', tier: 'free', description: 'Visually select and highlight a DOM element on the page with annotation metadata.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'CSS selector' }, note: { type: 'string', description: 'Comment or note' }, intent: { type: 'string', enum: ['fix', 'change', 'question', 'approve'], description: 'What action is needed' }, severity: { type: 'string', enum: ['blocking', 'important', 'suggestion'], description: 'How critical' } }, required: ['selector'] } },\n { name: 'list_selections', tier: 'free', description: 'List all selected/annotated elements.', inputSchema: { type: 'object', properties: {} } },\n { name: 'get_computed_styles', tier: 'free', description: 'Get computed CSS styles of a DOM element.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'CSS selector' }, properties: { type: 'array', items: { type: 'string' }, description: 'CSS properties to query' } }, required: ['selector'] } },\n { name: 'clear_selections', tier: 'free', description: 'Clear all selections.', inputSchema: { type: 'object', properties: {} } },\n { name: 'get_pending', tier: 'free', description: 'Get all pending annotations.', inputSchema: { type: 'object', properties: { sessionId: { type: 'string' } } } },\n { name: 'acknowledge', tier: 'free', description: 'Mark annotation as seen.', inputSchema: { type: 'object', properties: { annotationId: { type: 'string' } }, required: ['annotationId'] } },\n { name: 'resolve', tier: 'free', description: 'Mark annotation as resolved.', inputSchema: { type: 'object', properties: { annotationId: { type: 'string' }, summary: { type: 'string' } }, required: ['annotationId'] } },\n { name: 'dismiss', tier: 'free', description: 'Dismiss annotation with reason.', inputSchema: { type: 'object', properties: { annotationId: { type: 'string' }, reason: { type: 'string' } }, required: ['annotationId', 'reason'] } },\n { name: 'reply', tier: 'free', description: 'Add threaded reply to annotation.', inputSchema: { type: 'object', properties: { annotationId: { type: 'string' }, message: { type: 'string' } }, required: ['annotationId', 'message'] } },\n { name: 'get_bug_context', tier: 'free', description: 'Get environment context: browser, viewport, URL, console errors, page uptime.', inputSchema: { type: 'object', properties: {} } },\n\n // ===== Pro Tier =====\n { name: 'annotate_text', tier: 'pro', description: 'Find and highlight text on the page with optional note.', inputSchema: { type: 'object', properties: { pattern: { type: 'string', description: 'Text to find' }, note: { type: 'string', description: 'Note' } }, required: ['pattern'] } },\n { name: 'pause_animations', tier: 'pro', description: 'Pause or resume all animations.', inputSchema: { type: 'object', properties: { paused: { type: 'boolean', description: 'true=pause, false=resume' } }, required: ['paused'] } },\n { name: 'watch_annotations', tier: 'pro', description: 'Wait for new annotations (batched).', inputSchema: { type: 'object', properties: { batchWindowSeconds: { type: 'number' }, timeoutSeconds: { type: 'number' } } } },\n // React tools\n { name: 'inspect_component', tier: 'pro', description: 'Inspect a React component. Returns component name, props, hierarchy, and source file hint.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'CSS selector of element' }, name: { type: 'string', description: 'React component name' } } } },\n { name: 'find_components', tier: 'pro', description: 'Scan the page for all React components with instance count and example selectors.', inputSchema: { type: 'object', properties: { root: { type: 'string', description: 'CSS selector for root (defaults to body)' } } } },\n // Dev Loop tools\n { name: 'capture_page', tier: 'pro', description: 'Capture a screenshot of the page or a specific element. Returns base64 data URL.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'CSS selector (omit for viewport)' }, fullPage: { type: 'boolean', description: 'Capture full viewport' } } } },\n { name: 'extract_page_structure', tier: 'pro', description: 'Extract page structure: headings, images, buttons, links, form inputs, layout containers, colors, and fonts.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'Root selector (defaults to body)' }, maxDepth: { type: 'number', description: 'Max DOM depth (default 5, max 10)' } } } },\n { name: 'verify_element', tier: 'pro', description: 'Verify element properties against expected values (width, height, color, display, text, visible, position).', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'CSS selector' }, expected: { type: 'object', description: 'Expected values' } }, required: ['selector', 'expected'] } },\n { name: 'check_responsive', tier: 'pro', description: 'Check how an element is affected by media queries across breakpoints.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'CSS selector' }, breakpoints: { type: 'array', items: { type: 'number' }, description: 'Viewport widths (default: [375, 768, 1024, 1440])' } }, required: ['selector'] } },\n // Tier 1: Accessibility & Advanced\n { name: 'audit_accessibility', tier: 'pro', description: 'Run accessibility audit: alt text, form labels, contrast, heading hierarchy, landmarks, ARIA issues.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'Scope selector (defaults to page)' }, rules: { type: 'array', items: { type: 'string' }, description: 'Specific rules to check' } } } },\n { name: 'check_contrast', tier: 'pro', description: 'Check WCAG color contrast ratios for text elements.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'Element selector' }, selectors: { type: 'array', items: { type: 'string' }, description: 'Multiple selectors' } } } },\n { name: 'inspect_css_rules', tier: 'pro', description: 'Inspect actual CSS rules (not computed) that apply to an element with specificity and source.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'CSS selector' }, pseudo: { type: 'string', description: 'Pseudo-element (e.g. ::before)' } }, required: ['selector'] } },\n { name: 'capture_labeled', tier: 'pro', description: 'Capture screenshot with numbered labels on interactive elements.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'Scope selector' }, labelTypes: { type: 'array', items: { type: 'string' }, description: 'Element types to label' } } } },\n // Tier 2: Design & Comparison\n { name: 'extract_design_tokens', tier: 'pro', description: 'Extract design system tokens: colors, spacing, typography, borders, shadows.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'Scope selector (defaults to body)' } } } },\n { name: 'compare_screenshots', tier: 'pro', description: 'Compare two screenshots and report visual differences (10x10 grid analysis).', inputSchema: { type: 'object', properties: { before: { type: 'string', description: 'Base64 data URL before' }, after: { type: 'string', description: 'Base64 data URL after' } }, required: ['before', 'after'] } },\n { name: 'inspect_react_state', tier: 'pro', description: 'Inspect React component hooks: useState, useReducer, useContext, useRef, useMemo values.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'CSS selector of component element' } }, required: ['selector'] } },\n { name: 'validate_page_structure', tier: 'pro', description: 'Validate page structure: headings, landmarks, images, links, forms, ARIA. Returns score 0-100.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'Scope selector (defaults to page)' } } } },\n // Tier 3: Code Generation & Metrics\n { name: 'map_to_tailwind', tier: 'pro', description: 'Map element computed styles to equivalent Tailwind CSS classes.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'CSS selector' } }, required: ['selector'] } },\n { name: 'get_performance_metrics', tier: 'pro', description: 'Get page performance: load timing, FP, FCP, LCP, CLS, DOM count, memory.', inputSchema: { type: 'object', properties: {} } },\n { name: 'generate_test_code', tier: 'pro', description: 'Generate Playwright or Cypress test code for a DOM element.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'CSS selector' }, framework: { type: 'string', enum: ['playwright', 'cypress'], description: 'Test framework (default: playwright)' }, assertions: { type: 'array', items: { type: 'string' }, description: 'Assertion types' } }, required: ['selector'] } },\n { name: 'inspect_tab_order', tier: 'pro', description: 'Inspect sequential tab/focus order with accessibility warnings.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'Scope selector' } } } },\n // Export\n { name: 'list_assets', tier: 'pro', description: 'List all images, SVGs, and CSS background images with src, alt, dimensions.', inputSchema: { type: 'object', properties: {} } },\n { name: 'export_bug_report', tier: 'pro', description: 'Export annotations as formatted bug report (github, linear, markdown, bug-report).', inputSchema: { type: 'object', properties: { format: { type: 'string', enum: ['github', 'linear', 'markdown', 'bug-report'], description: 'Output format (default: markdown)' } } } },\n];\n\n/** Free tier \uB3C4\uAD6C \uC774\uB984 Set */\nexport const FREE_TOOL_NAMES = new Set(\n MCP_TOOLS.filter(t => t.tier === 'free').map(t => t.name)\n);\n\n/** MCP \uC751\uB2F5\uC6A9: tier \uD544\uB4DC \uC81C\uAC70 */\nexport function getToolsForTier(tier: 'free' | 'pro') {\n const tools = tier === 'pro' ? MCP_TOOLS : MCP_TOOLS.filter(t => t.tier === 'free');\n return tools.map(({ tier: _tier, ...rest }) => rest);\n}\n", "/**\n * License Validator \u2014 \uB77C\uC774\uC120\uC2A4 \uD0A4 \uAC80\uC99D + \uCE90\uC2DC\n * gate.bcdflow.net\uC73C\uB85C \uD0A4 \uAC80\uC99D, ~/.dev-inspector/license-cache.json\uC5D0 \uCE90\uC2DC\n */\nimport * as crypto from 'crypto';\nimport * as os from 'os';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nconst VALIDATE_URL = 'https://gate.bcdflow.net/api/v1/license/validate';\nconst CACHE_DIR = path.join(os.homedir(), '.dev-inspector');\nconst CACHE_FILE = path.join(CACHE_DIR, 'license-cache.json');\nconst CACHE_TTL = 24 * 60 * 60 * 1000; // 24\uC2DC\uAC04\nconst VALIDATE_TIMEOUT = 5000; // 5\uCD08\n\nexport interface LicenseStatus {\n tier: 'free' | 'pro';\n valid: boolean;\n expiresAt: string | null;\n checkedAt: number;\n}\n\nconst FREE_STATUS: LicenseStatus = {\n tier: 'free',\n valid: false,\n expiresAt: null,\n checkedAt: Date.now(),\n};\n\nlet _currentStatus: LicenseStatus = { ...FREE_STATUS };\n\n// ========== Machine ID ==========\nfunction getMachineId(): string {\n try {\n const raw = os.hostname() + ':' + os.userInfo().username;\n return crypto.createHash('sha256').update(raw).digest('hex').slice(0, 16);\n } catch {\n return 'unknown';\n }\n}\n\n// ========== \uCE90\uC2DC ==========\nfunction readCache(key: string): LicenseStatus | null {\n try {\n if (!fs.existsSync(CACHE_FILE)) return null;\n const data = JSON.parse(fs.readFileSync(CACHE_FILE, 'utf-8'));\n const keyHash = crypto.createHash('sha256').update(key).digest('hex').slice(0, 16);\n const entry = data[keyHash];\n if (!entry) return null;\n // TTL \uCCB4\uD06C\n if (Date.now() - entry.checkedAt > CACHE_TTL) return null;\n return entry as LicenseStatus;\n } catch {\n return null;\n }\n}\n\nfunction writeCache(key: string, status: LicenseStatus): void {\n try {\n if (!fs.existsSync(CACHE_DIR)) fs.mkdirSync(CACHE_DIR, { recursive: true });\n let data: Record<string, unknown> = {};\n try {\n if (fs.existsSync(CACHE_FILE)) {\n data = JSON.parse(fs.readFileSync(CACHE_FILE, 'utf-8'));\n }\n } catch { /* ignore */ }\n const keyHash = crypto.createHash('sha256').update(key).digest('hex').slice(0, 16);\n data[keyHash] = status;\n fs.writeFileSync(CACHE_FILE, JSON.stringify(data, null, 2));\n } catch { /* ignore */ }\n}\n\n// ========== \uC6D0\uACA9 \uAC80\uC99D ==========\nasync function remoteValidate(key: string): Promise<LicenseStatus> {\n const body = JSON.stringify({\n key,\n package: 'dev-inspector',\n version: '2.0.0',\n machineId: getMachineId(),\n });\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), VALIDATE_TIMEOUT);\n\n try {\n const res = await fetch(VALIDATE_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body,\n signal: controller.signal,\n });\n clearTimeout(timer);\n\n if (!res.ok) {\n return { ...FREE_STATUS, checkedAt: Date.now() };\n }\n\n const data = await res.json();\n return {\n tier: data.tier === 'pro' ? 'pro' : 'free',\n valid: !!data.valid,\n expiresAt: data.expiresAt || null,\n checkedAt: Date.now(),\n };\n } catch {\n clearTimeout(timer);\n return { ...FREE_STATUS, checkedAt: Date.now() };\n }\n}\n\n// ========== \uACF5\uAC1C API ==========\n\n/**\n * \uB77C\uC774\uC120\uC2A4 \uD0A4 \uAC80\uC99D (\uBE44\uB3D9\uAE30)\n * 1. \uD0A4\uAC00 \uC5C6\uC73C\uBA74 \u2192 free\n * 2. \uCE90\uC2DC\uAC00 \uC720\uD6A8\uD558\uBA74 \u2192 \uCE90\uC2DC \uC0AC\uC6A9\n * 3. \uC6D0\uACA9 \uAC80\uC99D \u2192 \uACB0\uACFC \uCE90\uC2DC\n * 4. \uC6D0\uACA9 \uC2E4\uD328 \u2192 \uB9CC\uB8CC\uB41C \uCE90\uC2DC\uB77C\uB3C4 \uC0AC\uC6A9, \uC5C6\uC73C\uBA74 free\n */\nexport async function validateLicense(key?: string): Promise<LicenseStatus> {\n if (!key) {\n _currentStatus = { ...FREE_STATUS, checkedAt: Date.now() };\n return _currentStatus;\n }\n\n // \uCE90\uC2DC \uD655\uC778\n const cached = readCache(key);\n if (cached) {\n _currentStatus = cached;\n return _currentStatus;\n }\n\n // \uC6D0\uACA9 \uAC80\uC99D\n const result = await remoteValidate(key);\n\n if (result.valid) {\n writeCache(key, result);\n _currentStatus = result;\n return _currentStatus;\n }\n\n // \uC6D0\uACA9 \uC2E4\uD328 \uC2DC \uB9CC\uB8CC\uB41C \uCE90\uC2DC\uB77C\uB3C4 \uD655\uC778\n try {\n if (fs.existsSync(CACHE_FILE)) {\n const data = JSON.parse(fs.readFileSync(CACHE_FILE, 'utf-8'));\n const keyHash = crypto.createHash('sha256').update(key).digest('hex').slice(0, 16);\n const expired = data[keyHash];\n if (expired?.valid) {\n // \uB9CC\uB8CC\uB41C \uCE90\uC2DC\uC9C0\uB9CC grace period \uD5C8\uC6A9 (\uCD94\uAC00 24\uC2DC\uAC04)\n _currentStatus = { ...expired, checkedAt: Date.now() };\n return _currentStatus;\n }\n }\n } catch { /* ignore */ }\n\n _currentStatus = result;\n return _currentStatus;\n}\n\n/** \uD604\uC7AC \uB77C\uC774\uC120\uC2A4 \uC0C1\uD0DC (\uB3D9\uAE30, validateLicense \uD638\uCD9C \uD6C4 \uC0AC\uC6A9) */\nexport function getLicenseStatus(): LicenseStatus {\n return _currentStatus;\n}\n\n/** \uD65C\uC131\uD654 \uCEE4\uB9E8\uB4DC\uC6A9: \uD0A4\uB97C config\uC5D0 \uC800\uC7A5 */\nexport function saveKeyToConfig(key: string): void {\n try {\n if (!fs.existsSync(CACHE_DIR)) fs.mkdirSync(CACHE_DIR, { recursive: true });\n const configFile = path.join(CACHE_DIR, 'config.json');\n let config: Record<string, unknown> = {};\n try {\n if (fs.existsSync(configFile)) {\n config = JSON.parse(fs.readFileSync(configFile, 'utf-8'));\n }\n } catch { /* ignore */ }\n config.licenseKey = key;\n fs.writeFileSync(configFile, JSON.stringify(config, null, 2));\n } catch { /* ignore */ }\n}\n\n/** config\uC5D0\uC11C \uC800\uC7A5\uB41C \uD0A4 \uC77D\uAE30 */\nexport function loadKeyFromConfig(): string | undefined {\n try {\n const configFile = path.join(CACHE_DIR, 'config.json');\n if (!fs.existsSync(configFile)) return undefined;\n const config = JSON.parse(fs.readFileSync(configFile, 'utf-8'));\n return config.licenseKey || undefined;\n } catch {\n return undefined;\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["/**\n * Dev InSpector Express Middleware\n *\n * Usage:\n * const { devInspector } = require('@bcdflow/dev-inspector');\n * app.use(devInspector({ licenseKey: process.env.DEV_INSPECTOR_KEY }));\n */\nimport { createRoutes } from './routes';\nimport { validateLicense, getLicenseStatus, loadKeyFromConfig } from '../license/validator';\n\nexport interface DevInspectorOptions {\n /** \uB77C\uC774\uC120\uC2A4 \uD0A4 (\uC5C6\uC73C\uBA74 DEV_INSPECTOR_KEY \uD658\uACBD\uBCC0\uC218 \uB610\uB294 ~/.dev-inspector/config.json) */\n licenseKey?: string;\n /** API \uB77C\uC6B0\uD2B8 \uC811\uB450\uC0AC (\uAE30\uBCF8: '/api/v1/dev-inspector') */\n prefix?: string;\n /** production\uC5D0\uC11C\uB3C4 \uD65C\uC131\uD654 (\uAE30\uBCF8: false) */\n enabled?: boolean;\n /** HTML \uC751\uB2F5\uC5D0 \uD074\uB77C\uC774\uC5B8\uD2B8 \uC2A4\uD06C\uB9BD\uD2B8 \uC790\uB3D9 \uC8FC\uC785 (\uAE30\uBCF8: false) */\n autoInject?: boolean;\n}\n\n// express\uB97C \uD638\uC2A4\uD2B8 \uD504\uB85C\uC81D\uD2B8\uC5D0\uC11C resolve\nfunction getExpress(): any {\n try {\n const { createRequire } = require('module');\n const hostRequire = createRequire(process.cwd() + '/package.json');\n return hostRequire('express');\n } catch {\n return require('express');\n }\n}\n\n// \uB77C\uC774\uC120\uC2A4 \uAC80\uC99D Promise (startup \uC2DC \uD55C \uBC88\uB9CC)\nlet _licensePromise: Promise<void> | null = null;\n\nexport function devInspector(options: DevInspectorOptions = {}): any {\n const {\n prefix = '/api/v1/dev-inspector',\n enabled,\n autoInject = false,\n } = options;\n\n const express = getExpress();\n const router = express.Router();\n\n // production \uD658\uACBD \uCCB4\uD06C\n const isEnabled = enabled !== undefined ? enabled : process.env.NODE_ENV !== 'production';\n if (!isEnabled) {\n return router;\n }\n\n // \uB77C\uC774\uC120\uC2A4 \uD0A4 resolve: options > env > config file\n const licenseKey = options.licenseKey\n || process.env.DEV_INSPECTOR_KEY\n || loadKeyFromConfig();\n\n // \uBE44\uB3D9\uAE30 \uAC80\uC99D \uC2DC\uC791 (\uC11C\uBC84 \uC2DC\uC791\uC744 \uBE14\uB85D\uD558\uC9C0 \uC54A\uC74C)\n _licensePromise = validateLicense(licenseKey).then((status) => {\n if (status.tier === 'pro') {\n console.log(`[dev-inspector] License: Pro (valid${status.expiresAt ? ` until ${status.expiresAt.split('T')[0]}` : ''})`);\n } else if (licenseKey) {\n console.log('[dev-inspector] License: invalid or expired \u2014 Free tier (11 tools)');\n } else {\n console.log('[dev-inspector] Free tier (11 tools). Set DEV_INSPECTOR_KEY for full access.');\n }\n });\n\n // API \uB77C\uC6B0\uD2B8 \uB9C8\uC6B4\uD2B8\n router.use(prefix, createRoutes());\n\n // \uD074\uB77C\uC774\uC5B8\uD2B8 \uC790\uB3D9 \uC8FC\uC785\n if (autoInject) {\n router.use((req: any, res: any, next: any) => {\n const originalSend = res.send.bind(res);\n res.send = function (body: any) {\n if (typeof body === 'string' && (body.includes('</body>') || body.includes('</html>'))) {\n const scriptTag = `<script src=\"${prefix}/client.js\" defer><\\/script>`;\n if (body.includes('</body>')) {\n body = body.replace('</body>', `${scriptTag}\\n</body>`);\n } else if (body.includes('</html>')) {\n body = body.replace('</html>', `${scriptTag}\\n</html>`);\n }\n }\n return originalSend(body);\n };\n next();\n });\n }\n\n return router;\n}\n\n/** \uB77C\uC774\uC120\uC2A4 \uAC80\uC99D \uC644\uB8CC \uB300\uAE30 (routes\uC5D0\uC11C \uC0AC\uC6A9) */\nexport function waitForLicense(): Promise<void> {\n if (_licensePromise) return _licensePromise;\n return Promise.resolve();\n}\n\nexport { createRoutes } from './routes';\nexport { inspectorEmitter } from './emitter';\nexport { getLicenseStatus } from '../license/validator';\n", "/**\n * Dev Inspector MCP Routes \u2014 SSE + REST \uBE0C\uB9BF\uC9C0 + \uB77C\uC774\uC120\uC2A4 \uAC8C\uC774\uD305\n */\nimport { readFileSync } from 'fs';\nimport { join } from 'path';\nimport { inspectorEmitter } from './emitter';\nimport { getToolsForTier, FREE_TOOL_NAMES } from '../mcp/tools';\nimport { getLicenseStatus } from '../license/validator';\nimport { waitForLicense } from './index';\n\nfunction getExpress(): any {\n try {\n const { createRequire } = require('module');\n const hostRequire = createRequire(process.cwd() + '/package.json');\n return hostRequire('express');\n } catch {\n return require('express');\n }\n}\n\nexport function createRoutes(): any {\n const express = getExpress();\n const router = express.Router();\n\n const sseClients = new Set<any>();\n const pendingResults = new Map<string, {\n resolve: (value: unknown) => void;\n timer: ReturnType<typeof setTimeout>;\n }>();\n\n // ========== SSE \uC2A4\uD2B8\uB9BC ==========\n router.get('/stream', (req: any, res: any) => {\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no');\n res.flushHeaders();\n\n res.write(`data: ${JSON.stringify({ type: 'connected', timestamp: Date.now() })}\\n\\n`);\n sseClients.add(res);\n\n const heartbeat = setInterval(() => {\n res.write(': heartbeat\\n\\n');\n }, 30000);\n\n req.on('close', () => {\n clearInterval(heartbeat);\n sseClients.delete(res);\n });\n });\n\n function broadcast(event: string, data: unknown): void {\n const payload = `event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`;\n for (const client of sseClients) {\n try { client.write(payload); } catch { sseClients.delete(client); }\n }\n }\n\n // ========== \uB3C4\uAD6C \uD638\uCD9C (\uB77C\uC774\uC120\uC2A4 \uAC8C\uC774\uD305) ==========\n router.post('/call', async (req: any, res: any) => {\n const { id, tool, params } = req.body;\n if (!id || !tool) {\n res.status(400).json({ error: 'id and tool are required' });\n return;\n }\n\n // \uB77C\uC774\uC120\uC2A4 \uAC80\uC99D \uC644\uB8CC \uB300\uAE30 (\uCD5C\uB300 2\uCD08)\n try {\n await Promise.race([\n waitForLicense(),\n new Promise(r => setTimeout(r, 2000)),\n ]);\n } catch { /* ignore */ }\n\n // Pro \uB3C4\uAD6C\uB97C Free tier\uC5D0\uC11C \uD638\uCD9C \uC2DC \uCC28\uB2E8\n const status = getLicenseStatus();\n if (status.tier === 'free' && !FREE_TOOL_NAMES.has(tool)) {\n res.json({\n result: {\n error: `\"${tool}\" requires a Pro license. Set DEV_INSPECTOR_KEY for full access.`,\n upgrade: true,\n freeTier: true,\n },\n });\n return;\n }\n\n if (sseClients.size === 0) {\n res.json({ error: 'No browser connected. Open a page with dev-inspector client loaded.' });\n return;\n }\n\n broadcast('tool_call', { id, tool, params });\n\n try {\n const result = await new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n pendingResults.delete(id);\n reject(new Error('Tool call timed out (30s)'));\n }, 30000);\n pendingResults.set(id, { resolve, timer });\n });\n res.json({ result });\n } catch (err: any) {\n res.json({ error: err.message });\n }\n });\n\n // ========== \uB3C4\uAD6C \uACB0\uACFC ==========\n router.post('/result', (req: any, res: any) => {\n const { id, result } = req.body;\n if (!id) {\n res.status(400).json({ error: 'id is required' });\n return;\n }\n const pending = pendingResults.get(id);\n if (pending) {\n clearTimeout(pending.timer);\n pendingResults.delete(id);\n pending.resolve(result);\n }\n res.json({ success: true });\n });\n\n // ========== \uBE0C\uB77C\uC6B0\uC800 \uC774\uBCA4\uD2B8 ==========\n router.post('/event', (req: any, res: any) => {\n inspectorEmitter.emit('browser_event', req.body);\n res.json({ success: true });\n });\n\n // ========== \uB3C4\uAD6C \uBAA9\uB85D (\uB77C\uC774\uC120\uC2A4 \uAE30\uBC18 \uD544\uD130\uB9C1) ==========\n router.get('/tools', (_req: any, res: any) => {\n const status = getLicenseStatus();\n res.json({ tools: getToolsForTier(status.tier) });\n });\n\n // ========== \uB77C\uC774\uC120\uC2A4 \uC0C1\uD0DC ==========\n router.get('/license-status', (_req: any, res: any) => {\n const status = getLicenseStatus();\n res.json({\n tier: status.tier,\n valid: status.valid,\n expiresAt: status.expiresAt,\n });\n });\n\n // ========== \uD074\uB77C\uC774\uC5B8\uD2B8 JS \uBC88\uB4E4 ==========\n let clientBundle: string | null = null;\n\n router.get('/client.js', (_req: any, res: any) => {\n if (!clientBundle) {\n try {\n clientBundle = readFileSync(join(__dirname, '..', 'client', 'dev-inspector.js'), 'utf-8');\n } catch {\n res.status(404).send('// Client bundle not found. Run: npm run build');\n return;\n }\n }\n res.setHeader('Content-Type', 'application/javascript');\n res.send(clientBundle);\n });\n\n // ========== \uC0C1\uD0DC \uD655\uC778 ==========\n router.get('/status', (_req: any, res: any) => {\n const status = getLicenseStatus();\n res.json({\n connected: sseClients.size > 0,\n clients: sseClients.size,\n pendingCalls: pendingResults.size,\n license: status.tier,\n });\n });\n\n return router;\n}\n", "/**\n * Inspector Event Emitter \u2014 \uB3C4\uAD6C \uD638\uCD9C/\uACB0\uACFC \uBE0C\uB9BF\uC9C0\n * MCP \uC11C\uBC84 \u2192 Express \uB77C\uC6B0\uD2B8 \u2192 SSE \u2192 \uBE0C\uB77C\uC6B0\uC800 \uAC04 \uC774\uBCA4\uD2B8 \uC911\uACC4\n */\nimport { EventEmitter } from 'events';\n\nexport const inspectorEmitter = new EventEmitter();\ninspectorEmitter.setMaxListeners(50);\n", "/**\n * MCP Tool Definitions \u2014 34\uAC1C DOM \uAC80\uC0AC \uB3C4\uAD6C\n * tier: 'free' (11\uAC1C) | 'pro' (23\uAC1C)\n */\nexport const MCP_TOOLS = [\n // ===== Free Tier (11\uAC1C) =====\n { name: 'inspect_element', tier: 'free', description: 'Inspect a DOM element by CSS selector. Returns selector, classes, computed styles, bounding box, hierarchy, accessibility, and text content.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'CSS selector' } }, required: ['selector'] } },\n { name: 'select_element', tier: 'free', description: 'Visually select and highlight a DOM element on the page with annotation metadata.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'CSS selector' }, note: { type: 'string', description: 'Comment or note' }, intent: { type: 'string', enum: ['fix', 'change', 'question', 'approve'], description: 'What action is needed' }, severity: { type: 'string', enum: ['blocking', 'important', 'suggestion'], description: 'How critical' } }, required: ['selector'] } },\n { name: 'list_selections', tier: 'free', description: 'List all selected/annotated elements.', inputSchema: { type: 'object', properties: {} } },\n { name: 'get_computed_styles', tier: 'free', description: 'Get computed CSS styles of a DOM element.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'CSS selector' }, properties: { type: 'array', items: { type: 'string' }, description: 'CSS properties to query' } }, required: ['selector'] } },\n { name: 'clear_selections', tier: 'free', description: 'Clear all selections.', inputSchema: { type: 'object', properties: {} } },\n { name: 'get_pending', tier: 'free', description: 'Get all pending annotations.', inputSchema: { type: 'object', properties: { sessionId: { type: 'string' } } } },\n { name: 'acknowledge', tier: 'free', description: 'Mark annotation as seen.', inputSchema: { type: 'object', properties: { annotationId: { type: 'string' } }, required: ['annotationId'] } },\n { name: 'resolve', tier: 'free', description: 'Mark annotation as resolved.', inputSchema: { type: 'object', properties: { annotationId: { type: 'string' }, summary: { type: 'string' } }, required: ['annotationId'] } },\n { name: 'dismiss', tier: 'free', description: 'Dismiss annotation with reason.', inputSchema: { type: 'object', properties: { annotationId: { type: 'string' }, reason: { type: 'string' } }, required: ['annotationId', 'reason'] } },\n { name: 'reply', tier: 'free', description: 'Add threaded reply to annotation.', inputSchema: { type: 'object', properties: { annotationId: { type: 'string' }, message: { type: 'string' } }, required: ['annotationId', 'message'] } },\n { name: 'get_bug_context', tier: 'free', description: 'Get environment context: browser, viewport, URL, console errors, page uptime.', inputSchema: { type: 'object', properties: {} } },\n\n // ===== Pro Tier =====\n { name: 'annotate_text', tier: 'pro', description: 'Find and highlight text on the page with optional note.', inputSchema: { type: 'object', properties: { pattern: { type: 'string', description: 'Text to find' }, note: { type: 'string', description: 'Note' } }, required: ['pattern'] } },\n { name: 'pause_animations', tier: 'pro', description: 'Pause or resume all animations.', inputSchema: { type: 'object', properties: { paused: { type: 'boolean', description: 'true=pause, false=resume' } }, required: ['paused'] } },\n { name: 'watch_annotations', tier: 'pro', description: 'Wait for new annotations (batched).', inputSchema: { type: 'object', properties: { batchWindowSeconds: { type: 'number' }, timeoutSeconds: { type: 'number' } } } },\n // React tools\n { name: 'inspect_component', tier: 'pro', description: 'Inspect a React component. Returns component name, props, hierarchy, and source file hint.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'CSS selector of element' }, name: { type: 'string', description: 'React component name' } } } },\n { name: 'find_components', tier: 'pro', description: 'Scan the page for all React components with instance count and example selectors.', inputSchema: { type: 'object', properties: { root: { type: 'string', description: 'CSS selector for root (defaults to body)' } } } },\n // Dev Loop tools\n { name: 'capture_page', tier: 'pro', description: 'Capture a screenshot of the page or a specific element. Returns base64 data URL.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'CSS selector (omit for viewport)' }, fullPage: { type: 'boolean', description: 'Capture full viewport' } } } },\n { name: 'extract_page_structure', tier: 'pro', description: 'Extract page structure: headings, images, buttons, links, form inputs, layout containers, colors, and fonts.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'Root selector (defaults to body)' }, maxDepth: { type: 'number', description: 'Max DOM depth (default 5, max 10)' } } } },\n { name: 'verify_element', tier: 'pro', description: 'Verify element properties against expected values (width, height, color, display, text, visible, position).', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'CSS selector' }, expected: { type: 'object', description: 'Expected values' } }, required: ['selector', 'expected'] } },\n { name: 'check_responsive', tier: 'pro', description: 'Check how an element is affected by media queries across breakpoints.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'CSS selector' }, breakpoints: { type: 'array', items: { type: 'number' }, description: 'Viewport widths (default: [375, 768, 1024, 1440])' } }, required: ['selector'] } },\n // Tier 1: Accessibility & Advanced\n { name: 'audit_accessibility', tier: 'pro', description: 'Run accessibility audit: alt text, form labels, contrast, heading hierarchy, landmarks, ARIA issues.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'Scope selector (defaults to page)' }, rules: { type: 'array', items: { type: 'string' }, description: 'Specific rules to check' } } } },\n { name: 'check_contrast', tier: 'pro', description: 'Check WCAG color contrast ratios for text elements.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'Element selector' }, selectors: { type: 'array', items: { type: 'string' }, description: 'Multiple selectors' } } } },\n { name: 'inspect_css_rules', tier: 'pro', description: 'Inspect actual CSS rules (not computed) that apply to an element with specificity and source.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'CSS selector' }, pseudo: { type: 'string', description: 'Pseudo-element (e.g. ::before)' } }, required: ['selector'] } },\n { name: 'capture_labeled', tier: 'pro', description: 'Capture screenshot with numbered labels on interactive elements.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'Scope selector' }, labelTypes: { type: 'array', items: { type: 'string' }, description: 'Element types to label' } } } },\n // Tier 2: Design & Comparison\n { name: 'extract_design_tokens', tier: 'pro', description: 'Extract design system tokens: colors, spacing, typography, borders, shadows.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'Scope selector (defaults to body)' } } } },\n { name: 'compare_screenshots', tier: 'pro', description: 'Compare two screenshots and report visual differences (10x10 grid analysis).', inputSchema: { type: 'object', properties: { before: { type: 'string', description: 'Base64 data URL before' }, after: { type: 'string', description: 'Base64 data URL after' } }, required: ['before', 'after'] } },\n { name: 'inspect_react_state', tier: 'pro', description: 'Inspect React component hooks: useState, useReducer, useContext, useRef, useMemo values.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'CSS selector of component element' } }, required: ['selector'] } },\n { name: 'validate_page_structure', tier: 'pro', description: 'Validate page structure: headings, landmarks, images, links, forms, ARIA. Returns score 0-100.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'Scope selector (defaults to page)' } } } },\n // Tier 3: Code Generation & Metrics\n { name: 'map_to_tailwind', tier: 'pro', description: 'Map element computed styles to equivalent Tailwind CSS classes.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'CSS selector' } }, required: ['selector'] } },\n { name: 'get_performance_metrics', tier: 'pro', description: 'Get page performance: load timing, FP, FCP, LCP, CLS, DOM count, memory.', inputSchema: { type: 'object', properties: {} } },\n { name: 'generate_test_code', tier: 'pro', description: 'Generate Playwright or Cypress test code for a DOM element.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'CSS selector' }, framework: { type: 'string', enum: ['playwright', 'cypress'], description: 'Test framework (default: playwright)' }, assertions: { type: 'array', items: { type: 'string' }, description: 'Assertion types' } }, required: ['selector'] } },\n { name: 'inspect_tab_order', tier: 'pro', description: 'Inspect sequential tab/focus order with accessibility warnings.', inputSchema: { type: 'object', properties: { selector: { type: 'string', description: 'Scope selector' } } } },\n // Export\n { name: 'list_assets', tier: 'pro', description: 'List all images, SVGs, and CSS background images with src, alt, dimensions.', inputSchema: { type: 'object', properties: {} } },\n { name: 'export_bug_report', tier: 'pro', description: 'Export annotations as formatted bug report (github, linear, markdown, bug-report).', inputSchema: { type: 'object', properties: { format: { type: 'string', enum: ['github', 'linear', 'markdown', 'bug-report'], description: 'Output format (default: markdown)' } } } },\n];\n\n/** Free tier \uB3C4\uAD6C \uC774\uB984 Set */\nexport const FREE_TOOL_NAMES = new Set(\n MCP_TOOLS.filter(t => t.tier === 'free').map(t => t.name)\n);\n\n/** MCP \uC751\uB2F5\uC6A9: tier \uD544\uB4DC \uC81C\uAC70 */\nexport function getToolsForTier(tier: 'free' | 'pro') {\n const tools = tier === 'pro' ? MCP_TOOLS : MCP_TOOLS.filter(t => t.tier === 'free');\n return tools.map(({ tier: _tier, ...rest }) => rest);\n}\n", "/**\n * License Validator \u2014 \uB77C\uC774\uC120\uC2A4 \uD0A4 \uAC80\uC99D + \uCE90\uC2DC\n * gate.bcdflow.net\uC73C\uB85C \uD0A4 \uAC80\uC99D, ~/.dev-inspector/license-cache.json\uC5D0 \uCE90\uC2DC\n */\nimport * as crypto from 'crypto';\nimport * as os from 'os';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nconst VALIDATE_URL = 'https://gate.bcdflow.net/api/license/validate';\nconst CACHE_DIR = path.join(os.homedir(), '.dev-inspector');\nconst CACHE_FILE = path.join(CACHE_DIR, 'license-cache.json');\nconst CACHE_TTL = 24 * 60 * 60 * 1000; // 24\uC2DC\uAC04\nconst VALIDATE_TIMEOUT = 5000; // 5\uCD08\n\nexport interface LicenseStatus {\n tier: 'free' | 'pro';\n valid: boolean;\n expiresAt: string | null;\n checkedAt: number;\n}\n\nconst FREE_STATUS: LicenseStatus = {\n tier: 'free',\n valid: false,\n expiresAt: null,\n checkedAt: Date.now(),\n};\n\nlet _currentStatus: LicenseStatus = { ...FREE_STATUS };\n\n// ========== Machine ID ==========\nfunction getMachineId(): string {\n try {\n const raw = os.hostname() + ':' + os.userInfo().username;\n return crypto.createHash('sha256').update(raw).digest('hex').slice(0, 16);\n } catch {\n return 'unknown';\n }\n}\n\n// ========== \uCE90\uC2DC ==========\nfunction readCache(key: string): LicenseStatus | null {\n try {\n if (!fs.existsSync(CACHE_FILE)) return null;\n const data = JSON.parse(fs.readFileSync(CACHE_FILE, 'utf-8'));\n const keyHash = crypto.createHash('sha256').update(key).digest('hex').slice(0, 16);\n const entry = data[keyHash];\n if (!entry) return null;\n // TTL \uCCB4\uD06C\n if (Date.now() - entry.checkedAt > CACHE_TTL) return null;\n return entry as LicenseStatus;\n } catch {\n return null;\n }\n}\n\nfunction writeCache(key: string, status: LicenseStatus): void {\n try {\n if (!fs.existsSync(CACHE_DIR)) fs.mkdirSync(CACHE_DIR, { recursive: true });\n let data: Record<string, unknown> = {};\n try {\n if (fs.existsSync(CACHE_FILE)) {\n data = JSON.parse(fs.readFileSync(CACHE_FILE, 'utf-8'));\n }\n } catch { /* ignore */ }\n const keyHash = crypto.createHash('sha256').update(key).digest('hex').slice(0, 16);\n data[keyHash] = status;\n fs.writeFileSync(CACHE_FILE, JSON.stringify(data, null, 2));\n } catch { /* ignore */ }\n}\n\n// ========== \uC6D0\uACA9 \uAC80\uC99D ==========\nasync function remoteValidate(key: string): Promise<LicenseStatus> {\n const body = JSON.stringify({ key });\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), VALIDATE_TIMEOUT);\n\n try {\n const res = await fetch(VALIDATE_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body,\n signal: controller.signal,\n });\n clearTimeout(timer);\n\n if (!res.ok) {\n return { ...FREE_STATUS, checkedAt: Date.now() };\n }\n\n const data = await res.json();\n // gate \uC11C\uBC84 \uC751\uB2F5: { valid, license: { status, expiresAt, ... } }\n const isValid = !!data.valid;\n return {\n tier: isValid ? 'pro' : 'free',\n valid: isValid,\n expiresAt: data.license?.expiresAt || null,\n checkedAt: Date.now(),\n };\n } catch {\n clearTimeout(timer);\n return { ...FREE_STATUS, checkedAt: Date.now() };\n }\n}\n\n// ========== \uACF5\uAC1C API ==========\n\n/**\n * \uB77C\uC774\uC120\uC2A4 \uD0A4 \uAC80\uC99D (\uBE44\uB3D9\uAE30)\n * 1. \uD0A4\uAC00 \uC5C6\uC73C\uBA74 \u2192 free\n * 2. \uCE90\uC2DC\uAC00 \uC720\uD6A8\uD558\uBA74 \u2192 \uCE90\uC2DC \uC0AC\uC6A9\n * 3. \uC6D0\uACA9 \uAC80\uC99D \u2192 \uACB0\uACFC \uCE90\uC2DC\n * 4. \uC6D0\uACA9 \uC2E4\uD328 \u2192 \uB9CC\uB8CC\uB41C \uCE90\uC2DC\uB77C\uB3C4 \uC0AC\uC6A9, \uC5C6\uC73C\uBA74 free\n */\nexport async function validateLicense(key?: string): Promise<LicenseStatus> {\n if (!key) {\n _currentStatus = { ...FREE_STATUS, checkedAt: Date.now() };\n return _currentStatus;\n }\n\n // \uCE90\uC2DC \uD655\uC778\n const cached = readCache(key);\n if (cached) {\n _currentStatus = cached;\n return _currentStatus;\n }\n\n // \uC6D0\uACA9 \uAC80\uC99D\n const result = await remoteValidate(key);\n\n if (result.valid) {\n writeCache(key, result);\n _currentStatus = result;\n return _currentStatus;\n }\n\n // \uC6D0\uACA9 \uC2E4\uD328 \uC2DC \uB9CC\uB8CC\uB41C \uCE90\uC2DC\uB77C\uB3C4 \uD655\uC778\n try {\n if (fs.existsSync(CACHE_FILE)) {\n const data = JSON.parse(fs.readFileSync(CACHE_FILE, 'utf-8'));\n const keyHash = crypto.createHash('sha256').update(key).digest('hex').slice(0, 16);\n const expired = data[keyHash];\n if (expired?.valid) {\n // \uB9CC\uB8CC\uB41C \uCE90\uC2DC\uC9C0\uB9CC grace period \uD5C8\uC6A9 (\uCD94\uAC00 24\uC2DC\uAC04)\n _currentStatus = { ...expired, checkedAt: Date.now() };\n return _currentStatus;\n }\n }\n } catch { /* ignore */ }\n\n _currentStatus = result;\n return _currentStatus;\n}\n\n/** \uD604\uC7AC \uB77C\uC774\uC120\uC2A4 \uC0C1\uD0DC (\uB3D9\uAE30, validateLicense \uD638\uCD9C \uD6C4 \uC0AC\uC6A9) */\nexport function getLicenseStatus(): LicenseStatus {\n return _currentStatus;\n}\n\n/** \uD65C\uC131\uD654 \uCEE4\uB9E8\uB4DC\uC6A9: \uD0A4\uB97C config\uC5D0 \uC800\uC7A5 */\nexport function saveKeyToConfig(key: string): void {\n try {\n if (!fs.existsSync(CACHE_DIR)) fs.mkdirSync(CACHE_DIR, { recursive: true });\n const configFile = path.join(CACHE_DIR, 'config.json');\n let config: Record<string, unknown> = {};\n try {\n if (fs.existsSync(configFile)) {\n config = JSON.parse(fs.readFileSync(configFile, 'utf-8'));\n }\n } catch { /* ignore */ }\n config.licenseKey = key;\n fs.writeFileSync(configFile, JSON.stringify(config, null, 2));\n } catch { /* ignore */ }\n}\n\n/** config\uC5D0\uC11C \uC800\uC7A5\uB41C \uD0A4 \uC77D\uAE30 */\nexport function loadKeyFromConfig(): string | undefined {\n try {\n const configFile = path.join(CACHE_DIR, 'config.json');\n if (!fs.existsSync(configFile)) return undefined;\n const config = JSON.parse(fs.readFileSync(configFile, 'utf-8'));\n return config.licenseKey || undefined;\n } catch {\n return undefined;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["getExpress"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bcdflow/dev-inspector",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"description": "DOM inspector + MCP bridge for AI coding assistants. Express middleware that enables Claude Code to inspect, annotate, and audit web pages in real-time.",
|
|
5
5
|
"main": "dist/middleware/index.js",
|
|
6
6
|
"bin": {
|