@_davideast/stitch-mcp 0.5.2 → 0.5.3
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/dist/chunk-22bymmh9.js +137 -0
- package/dist/chunk-22bymmh9.js.map +10 -0
- package/dist/chunk-387yyye2.js +248 -0
- package/dist/chunk-387yyye2.js.map +14 -0
- package/dist/chunk-3ff2k44g.js +19 -0
- package/dist/chunk-3ff2k44g.js.map +9 -0
- package/dist/chunk-46cay1zp.js +273 -0
- package/dist/chunk-46cay1zp.js.map +10 -0
- package/dist/chunk-48e1jpm8.js +167 -0
- package/dist/chunk-48e1jpm8.js.map +10 -0
- package/dist/chunk-4arzkk1s.js +69 -0
- package/dist/chunk-4arzkk1s.js.map +10 -0
- package/dist/chunk-4js7vw6h.js +415 -0
- package/dist/chunk-4js7vw6h.js.map +20 -0
- package/dist/chunk-4p1wfk3t.js +736 -0
- package/dist/chunk-4p1wfk3t.js.map +16 -0
- package/dist/chunk-4zg969tc.js +370 -0
- package/dist/chunk-4zg969tc.js.map +16 -0
- package/dist/chunk-5jjt7tgw.js +247 -0
- package/dist/chunk-5jjt7tgw.js.map +14 -0
- package/dist/chunk-5t2h8z2n.js +273 -0
- package/dist/chunk-5t2h8z2n.js.map +10 -0
- package/dist/chunk-5zy3et1m.js +759 -0
- package/dist/chunk-5zy3et1m.js.map +19 -0
- package/dist/chunk-6wvst7z8.js +125 -0
- package/dist/chunk-6wvst7z8.js.map +12 -0
- package/dist/chunk-8mm08arm.js +256 -0
- package/dist/chunk-8mm08arm.js.map +11 -0
- package/dist/chunk-8nv4wwv0.js +19 -0
- package/dist/chunk-8nv4wwv0.js.map +9 -0
- package/dist/chunk-9cjny9z2.js +19 -0
- package/dist/chunk-9cjny9z2.js.map +9 -0
- package/dist/chunk-9ggfw78s.js +19 -0
- package/dist/chunk-9ggfw78s.js.map +9 -0
- package/dist/chunk-9nyyn1hn.js +125 -0
- package/dist/chunk-9nyyn1hn.js.map +12 -0
- package/dist/chunk-9nzbvp6r.js +19 -0
- package/dist/chunk-9nzbvp6r.js.map +9 -0
- package/dist/chunk-a0gmbh8e.js +415 -0
- package/dist/chunk-a0gmbh8e.js.map +20 -0
- package/dist/chunk-acv998mp.js +941 -0
- package/dist/chunk-acv998mp.js.map +27 -0
- package/dist/chunk-cpjsvven.js +10 -0
- package/dist/chunk-cpjsvven.js.map +9 -0
- package/dist/chunk-dmrahbs1.js +31467 -0
- package/dist/chunk-dmrahbs1.js.map +245 -0
- package/dist/chunk-dts6851a.js +137 -0
- package/dist/chunk-dts6851a.js.map +10 -0
- package/dist/chunk-efd0rm6g.js +69 -0
- package/dist/chunk-efd0rm6g.js.map +10 -0
- package/dist/chunk-f1kjn6cd.js +16554 -0
- package/dist/chunk-f1kjn6cd.js.map +98 -0
- package/dist/chunk-f5f6ekgp.js +109 -0
- package/dist/chunk-f5f6ekgp.js.map +10 -0
- package/dist/chunk-fmewhfh3.js +137 -0
- package/dist/chunk-fmewhfh3.js.map +10 -0
- package/dist/chunk-fmhrn6cg.js +6382 -0
- package/dist/chunk-fmhrn6cg.js.map +109 -0
- package/dist/chunk-gh7dzfhb.js +256 -0
- package/dist/chunk-gh7dzfhb.js.map +11 -0
- package/dist/chunk-gwhtc0fe.js +370 -0
- package/dist/chunk-gwhtc0fe.js.map +16 -0
- package/dist/chunk-hc7sdwmn.js +449 -0
- package/dist/chunk-hc7sdwmn.js.map +17 -0
- package/dist/chunk-k4xwb3wp.js +44184 -0
- package/dist/chunk-k4xwb3wp.js.map +237 -0
- package/dist/chunk-k751yfm6.js +736 -0
- package/dist/chunk-k751yfm6.js.map +16 -0
- package/dist/chunk-kkc2tvar.js +19 -0
- package/dist/chunk-kkc2tvar.js.map +9 -0
- package/dist/chunk-kva47mgc.js +10 -0
- package/dist/chunk-kva47mgc.js.map +9 -0
- package/dist/chunk-nv2j020p.js +45210 -0
- package/dist/chunk-nv2j020p.js.map +258 -0
- package/dist/chunk-pdj9s41r.js +683 -0
- package/dist/chunk-pdj9s41r.js.map +17 -0
- package/dist/chunk-ppphsy4t.js +273 -0
- package/dist/chunk-ppphsy4t.js.map +10 -0
- package/dist/chunk-psmw9zpa.js +941 -0
- package/dist/chunk-psmw9zpa.js.map +27 -0
- package/dist/chunk-pz31v3ma.js +24 -0
- package/dist/chunk-pz31v3ma.js.map +9 -0
- package/dist/chunk-qbt0906e.js +1495 -0
- package/dist/chunk-qbt0906e.js.map +23 -0
- package/dist/chunk-rh3k09h7.js +19 -0
- package/dist/chunk-rh3k09h7.js.map +9 -0
- package/dist/chunk-saznae7w.js +10 -0
- package/dist/chunk-saznae7w.js.map +9 -0
- package/dist/chunk-sscqdg1j.js +69 -0
- package/dist/chunk-sscqdg1j.js.map +10 -0
- package/dist/chunk-stgj6y85.js +835 -0
- package/dist/chunk-stgj6y85.js.map +19 -0
- package/dist/chunk-t3tqmxyj.js +42 -0
- package/dist/chunk-t3tqmxyj.js.map +9 -0
- package/dist/chunk-v8ak35zd.js +94 -0
- package/dist/chunk-v8ak35zd.js.map +10 -0
- package/dist/chunk-w9acw256.js +167 -0
- package/dist/chunk-w9acw256.js.map +10 -0
- package/dist/chunk-wq60thjn.js +167 -0
- package/dist/chunk-wq60thjn.js.map +10 -0
- package/dist/chunk-wzkdeb8a.js +736 -0
- package/dist/chunk-wzkdeb8a.js.map +16 -0
- package/dist/chunk-xxv6j815.js +256 -0
- package/dist/chunk-xxv6j815.js.map +11 -0
- package/dist/chunk-yjnj35q8.js +1495 -0
- package/dist/chunk-yjnj35q8.js.map +23 -0
- package/dist/chunk-yvzzrczy.js +45206 -0
- package/dist/chunk-yvzzrczy.js.map +258 -0
- package/dist/chunk-ywax1akt.js +370 -0
- package/dist/chunk-ywax1akt.js.map +16 -0
- package/dist/chunk-zakq9pc0.js +4989 -0
- package/dist/chunk-zakq9pc0.js.map +65 -0
- package/dist/commands/doctor/command.js +1 -1
- package/dist/commands/doctor/steps/AdcProjectCheckStep.d.ts +8 -0
- package/dist/commands/init/command.js +1 -1
- package/dist/commands/logout/command.js +1 -1
- package/dist/commands/proxy/command.js +1 -1
- package/dist/commands/screens/command.js +2 -2
- package/dist/commands/serve/command.js +3 -3
- package/dist/commands/site/command.js +1 -1
- package/dist/commands/snapshot/command.js +1 -1
- package/dist/commands/tool/command.js +1 -1
- package/dist/commands/view/command.js +1 -1
- package/dist/index.js +4 -4
- package/dist/lib/server/AssetGateway.d.ts +12 -0
- package/package.json +1 -1
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/commands/site/ui/SiteBuilder.tsx", "../node_modules/ink-spinner/build/index.js", "../node_modules/ink-text-input/build/index.js", "../src/commands/site/utils/SiteManifest.ts", "../src/commands/site/ui/components/StatusIcon.tsx", "../src/commands/site/ui/ScreenList.tsx", "../src/commands/site/hooks/useProjectHydration.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import React, { useState, useEffect, useMemo, useCallback } from 'react';\nimport { Box, Text, useInput, useApp } from 'ink';\nimport Spinner from 'ink-spinner';\nimport TextInput from 'ink-text-input';\nimport { SiteService } from '../../../lib/services/site/SiteService.js';\nimport { StitchViteServer } from '../../../lib/server/vite/StitchViteServer.js';\nimport { openUrl } from '../../../platform/browser.js';\nimport { SiteManifest } from '../utils/SiteManifest.js';\nimport { fetchWithRetry } from '../utils/fetchWithRetry.js';\nimport { ScreenList } from './ScreenList.js';\nimport { useProjectHydration } from '../hooks/useProjectHydration.js';\nimport type { UIScreen, SiteConfig } from '../../../lib/services/site/types.js';\nimport type { Stitch } from '@google/stitch-sdk';\n\ninterface SiteBuilderProps {\n projectId: string;\n client: Stitch;\n onExit: (config: SiteConfig | null, htmlContent?: Map<string, string>) => void;\n}\n\nexport const SiteBuilder: React.FC<SiteBuilderProps> = ({ projectId, client, onExit }) => {\n const { exit } = useApp();\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n // New state\n const [screens, setScreens] = useState<UIScreen[]>([]);\n const [showSelectedOnly, setShowSelectedOnly] = useState(false);\n const [activeIndex, setActiveIndex] = useState(0);\n const [viewMode, setViewMode] = useState<'default' | 'discarded'>('default');\n\n const siteManifest = useMemo(() => new SiteManifest(projectId), [projectId]);\n\n const [isEditingRoute, setIsEditingRoute] = useState(false);\n const [routeValue, setRouteValue] = useState('');\n\n const [followMode, setFollowMode] = useState(true);\n const [showAllKeys, setShowAllKeys] = useState(false);\n const [serverUrl, setServerUrl] = useState<string | null>(null);\n const [server, setServer] = useState<StitchViteServer | null>(null);\n\n // Initialize\n useEffect(() => {\n let mounted = true;\n const srv = new StitchViteServer();\n setServer(srv);\n\n const init = async () => {\n try {\n // Start server\n const url = await srv.start(0);\n if (mounted) setServerUrl(url);\n\n // Fetch screens\n const project = client.project(projectId);\n const sdkScreens = await project.screens();\n\n // Convert to UIScreen\n const uiScreens = await Promise.all(\n sdkScreens.map(async (s: any) => ({\n id: s.screenId,\n title: s.title ?? s.screenId,\n status: 'ignored' as const,\n route: '',\n downloadUrl: await s.getHtml().catch(() => null)\n }))\n ) as UIScreen[];\n\n // Load saved screen state (status + routes)\n const saved = await siteManifest.load();\n for (const screen of uiScreens) {\n const state = saved.get(screen.id);\n if (state?.status) screen.status = state.status;\n if (state?.route) screen.route = state.route;\n }\n\n if (mounted) {\n setScreens(uiScreens);\n setLoading(false);\n }\n } catch (e: any) {\n if (mounted) setError(e.message);\n }\n };\n\n init();\n\n return () => {\n mounted = false;\n srv.stop();\n };\n }, [projectId, client]);\n\n // Derived display list\n const displayList = useMemo(() => {\n let list = screens.map((s, i) => ({ screen: s, sourceIndex: i }));\n\n if (viewMode === 'discarded') {\n return list.filter(item => item.screen.status === 'discarded');\n }\n\n // Default: hide discarded\n list = list.filter(item => item.screen.status !== 'discarded');\n\n if (showSelectedOnly) {\n list = list.filter(item => item.screen.status === 'included');\n }\n\n return list;\n }, [screens, viewMode, showSelectedOnly]);\n\n // Clamp activeIndex when list changes\n useEffect(() => {\n setActiveIndex(prev => {\n if (displayList.length === 0) return 0;\n return Math.min(prev, Math.max(0, displayList.length - 1));\n });\n }, [displayList.length]);\n\n // Hydration logic\n const activeItem = displayList[activeIndex];\n const activeScreenId = activeItem?.screen.id;\n\n // Stable fetchContent reference using fetchWithRetry directly\n const fetchContent = useCallback((url: string) => fetchWithRetry(url), []);\n\n const { hydrationStatus, progress, htmlContent } = useProjectHydration(screens, server, fetchContent, activeScreenId);\n\n // Navigate effect (Follow Mode)\n useEffect(() => {\n if (server && followMode && hydrationStatus === 'ready' && activeScreenId) {\n server.navigate(`/_preview/${activeScreenId}`);\n }\n }, [activeScreenId, followMode, server, hydrationStatus]);\n\n // Input handling\n useInput((input, key) => {\n if (loading || error) return;\n\n // When editing route, TextInput handles input.\n // We only listen for Escape to cancel or Enter to submit (handled by TextInput onSubmit/onChange logic?)\n // Actually ink-text-input handles value updates, but we need to handle commit/cancel.\n // However, if we use useInput here, it might conflict if not careful.\n // ink-text-input captures input if focused? No, it just renders.\n // We need to capture input here if NOT editing.\n if (isEditingRoute) {\n if (key.escape) {\n setIsEditingRoute(false);\n setRouteValue(''); // Reset or keep? Reset seems better for cancel.\n }\n return;\n }\n\n if (key.upArrow) {\n setActiveIndex(prev => Math.max(0, prev - 1));\n }\n if (key.downArrow) {\n setActiveIndex(prev => Math.min(displayList.length - 1, prev + 1));\n }\n\n if (input === ' ') {\n if (activeItem) {\n const originalIndex = activeItem.sourceIndex;\n setScreens(prev => {\n const next = [...prev];\n const s = next[originalIndex];\n if (s) {\n s.status = s.status === 'included' ? 'ignored' : 'included';\n }\n siteManifest.save(next);\n return next;\n });\n }\n }\n\n if (key.return) {\n if (activeItem) {\n setRouteValue(activeItem.screen.route);\n setIsEditingRoute(true);\n }\n }\n\n if (input === 't') {\n setShowSelectedOnly(prev => !prev);\n }\n\n if (input === 'f') {\n setFollowMode(prev => !prev);\n }\n\n if (input === 'x') {\n const item = displayList[activeIndex];\n if (!item) return;\n\n if (viewMode === 'discarded') {\n // Undiscard → set to 'ignored'\n const idx = item.sourceIndex;\n setScreens(prev => {\n const next = [...prev];\n if (next[idx]) next[idx]!.status = 'ignored';\n siteManifest.save(next);\n return next;\n });\n } else {\n // Discard\n const idx = item.sourceIndex;\n setScreens(prev => {\n const next = [...prev];\n if (next[idx]) next[idx]!.status = 'discarded';\n siteManifest.save(next);\n return next;\n });\n }\n }\n\n if (input === 'd') {\n setViewMode(prev => prev === 'default' ? 'discarded' : 'default');\n setActiveIndex(0);\n }\n\n if (input === 'o') {\n if (serverUrl && activeScreenId) {\n const target = `${serverUrl}/_preview/${activeScreenId}`;\n openUrl(target);\n }\n }\n\n if (input === 'g') {\n // Validate\n const included = screens.filter(s => s.status === 'included');\n const invalid = included.find(s => !s.route || s.route.trim() === '');\n\n if (invalid) {\n // Can't show error easily without new state, maybe console error or alert?\n // For now, maybe just don't generate?\n // Or better, set an error message in UI?\n // Since we don't have a persistent error UI, let's just do nothing or maybe flash?\n // Plan didn't specify error UI.\n // \"Show a warning and refuse to generate.\"\n // I'll reuse 'error' state but that might be blocking.\n // Let's rely on validation during generation or maybe a quick alert line.\n // I'll assume valid for now or maybe just alert if I can.\n // I'll prevent exit.\n return;\n }\n\n const finalConfig: SiteConfig = {\n projectId,\n routes: included.map(s => ({\n screenId: s.id,\n route: s.route,\n status: s.status as 'included' | 'ignored'\n }))\n };\n onExit(finalConfig, htmlContent);\n exit();\n }\n\n if (input === 'e') {\n const included = screens.filter(s => s.status === 'included');\n const exportData = {\n projectId,\n routes: included.map(s => ({\n screenId: s.id,\n route: s.route,\n })),\n };\n process.stdout.write(JSON.stringify(exportData, null, 2) + '\\n');\n }\n\n if (input === '?') {\n setShowAllKeys(prev => !prev);\n }\n\n if (input === 'q') {\n onExit(null);\n exit();\n }\n });\n\n const handleRouteSubmit = (val: string) => {\n if (activeItem) {\n const originalIndex = activeItem.sourceIndex;\n setScreens(prev => {\n const next = [...prev];\n if (next[originalIndex]) {\n next[originalIndex]!.route = val;\n }\n siteManifest.save(next);\n return next;\n });\n setIsEditingRoute(false);\n // Move to next\n setActiveIndex(prev => Math.min(displayList.length - 1, prev + 1));\n }\n };\n\n if (error) {\n return <Text color=\"red\">Error: {error}</Text>;\n }\n\n if (loading) {\n return (\n <Box>\n <Text color=\"green\"><Spinner type=\"dots\" /> Loading project...</Text>\n </Box>\n );\n }\n\n return (\n <Box flexDirection=\"column\" height=\"100%\">\n {/* Header */}\n <Box borderStyle=\"single\" borderColor=\"cyan\" paddingX={1}>\n <Text>Stitch Site Builder</Text>\n <Box marginLeft={2}>\n <Text color=\"gray\">{serverUrl}</Text>\n </Box>\n <Box marginLeft={2}>\n {viewMode === 'discarded' ? (\n <Text color=\"red\">Viewing Discarded ({displayList.length})</Text>\n ) : (\n <Text>Filter: {showSelectedOnly ? 'Selected' : 'All'} ({displayList.length})</Text>\n )}\n </Box>\n {viewMode === 'default' && screens.filter(s => s.status === 'discarded').length > 0 && (\n <Box marginLeft={2}>\n <Text dimColor>{screens.filter(s => s.status === 'discarded').length} discarded (press d to view)</Text>\n </Box>\n )}\n <Box marginLeft={2}>\n {hydrationStatus === 'downloading' && (\n <Text color=\"yellow\">\n <Spinner type=\"dots\" /> Downloading... {Math.round(progress * 100)}%\n </Text>\n )}\n {hydrationStatus === 'ready' && <Text color=\"green\">Ready</Text>}\n </Box>\n </Box>\n\n {/* List */}\n <ScreenList items={displayList} activeIndex={activeIndex} />\n\n {/* Route Editor */}\n <Box borderStyle=\"single\" borderColor={isEditingRoute ? \"green\" : \"gray\"} paddingX={1} flexDirection=\"column\">\n {activeItem ? (\n <>\n <Text bold>Route for: {activeItem.screen.title}</Text>\n {isEditingRoute ? (\n <Box>\n <Text color=\"green\">{'> '}</Text>\n <TextInput\n value={routeValue}\n onChange={setRouteValue}\n onSubmit={handleRouteSubmit}\n />\n </Box>\n ) : (\n <Box>\n <Text color=\"gray\">{activeItem.screen.route || 'No route defined'}</Text>\n <Box marginLeft={2}>\n <Text dimColor>Press Enter to edit</Text>\n </Box>\n </Box>\n )}\n </>\n ) : (\n <Text color=\"gray\">No screen selected</Text>\n )}\n </Box>\n\n {/* Keymap */}\n <Box borderStyle=\"single\" borderColor=\"gray\" paddingX={1}>\n <Text dimColor>\n {viewMode === 'discarded'\n ? '[x] Undiscard [d] Back to All [q] Quit'\n : showAllKeys\n ? `[Space] Toggle [Enter] Edit Route [x] Discard [d] View Discarded [t] Filter [f] Follow: ${followMode ? 'ON' : 'OFF'} [o] Open [g] Generate [e] Export [q] Quit [?] Less`\n : '[Space] Toggle [Enter] Edit Route [g] Generate [x] Discard [o] Open [q] Quit [?] More'\n }\n </Text>\n </Box>\n </Box>\n );\n};\n",
|
|
6
|
+
"import React, { useState, useEffect } from 'react';\nimport { Text } from 'ink';\nimport spinners from 'cli-spinners';\n/**\n * Spinner.\n */\nfunction Spinner({ type = 'dots' }) {\n const [frame, setFrame] = useState(0);\n const spinner = spinners[type];\n useEffect(() => {\n const timer = setInterval(() => {\n setFrame(previousFrame => {\n const isLastFrame = previousFrame === spinner.frames.length - 1;\n return isLastFrame ? 0 : previousFrame + 1;\n });\n }, spinner.interval);\n return () => {\n clearInterval(timer);\n };\n }, [spinner]);\n return React.createElement(Text, null, spinner.frames[frame]);\n}\nexport default Spinner;\n//# sourceMappingURL=index.js.map",
|
|
7
|
+
"import React, { useState, useEffect } from 'react';\nimport { Text, useInput } from 'ink';\nimport chalk from 'chalk';\nfunction TextInput({ value: originalValue, placeholder = '', focus = true, mask, highlightPastedText = false, showCursor = true, onChange, onSubmit, }) {\n const [state, setState] = useState({\n cursorOffset: (originalValue || '').length,\n cursorWidth: 0,\n });\n const { cursorOffset, cursorWidth } = state;\n useEffect(() => {\n setState(previousState => {\n if (!focus || !showCursor) {\n return previousState;\n }\n const newValue = originalValue || '';\n if (previousState.cursorOffset > newValue.length - 1) {\n return {\n cursorOffset: newValue.length,\n cursorWidth: 0,\n };\n }\n return previousState;\n });\n }, [originalValue, focus, showCursor]);\n const cursorActualWidth = highlightPastedText ? cursorWidth : 0;\n const value = mask ? mask.repeat(originalValue.length) : originalValue;\n let renderedValue = value;\n let renderedPlaceholder = placeholder ? chalk.grey(placeholder) : undefined;\n // Fake mouse cursor, because it's too inconvenient to deal with actual cursor and ansi escapes\n if (showCursor && focus) {\n renderedPlaceholder =\n placeholder.length > 0\n ? chalk.inverse(placeholder[0]) + chalk.grey(placeholder.slice(1))\n : chalk.inverse(' ');\n renderedValue = value.length > 0 ? '' : chalk.inverse(' ');\n let i = 0;\n for (const char of value) {\n renderedValue +=\n i >= cursorOffset - cursorActualWidth && i <= cursorOffset\n ? chalk.inverse(char)\n : char;\n i++;\n }\n if (value.length > 0 && cursorOffset === value.length) {\n renderedValue += chalk.inverse(' ');\n }\n }\n useInput((input, key) => {\n if (key.upArrow ||\n key.downArrow ||\n (key.ctrl && input === 'c') ||\n key.tab ||\n (key.shift && key.tab)) {\n return;\n }\n if (key.return) {\n if (onSubmit) {\n onSubmit(originalValue);\n }\n return;\n }\n let nextCursorOffset = cursorOffset;\n let nextValue = originalValue;\n let nextCursorWidth = 0;\n if (key.leftArrow) {\n if (showCursor) {\n nextCursorOffset--;\n }\n }\n else if (key.rightArrow) {\n if (showCursor) {\n nextCursorOffset++;\n }\n }\n else if (key.backspace || key.delete) {\n if (cursorOffset > 0) {\n nextValue =\n originalValue.slice(0, cursorOffset - 1) +\n originalValue.slice(cursorOffset, originalValue.length);\n nextCursorOffset--;\n }\n }\n else {\n nextValue =\n originalValue.slice(0, cursorOffset) +\n input +\n originalValue.slice(cursorOffset, originalValue.length);\n nextCursorOffset += input.length;\n if (input.length > 1) {\n nextCursorWidth = input.length;\n }\n }\n if (cursorOffset < 0) {\n nextCursorOffset = 0;\n }\n if (cursorOffset > originalValue.length) {\n nextCursorOffset = originalValue.length;\n }\n setState({\n cursorOffset: nextCursorOffset,\n cursorWidth: nextCursorWidth,\n });\n if (nextValue !== originalValue) {\n onChange(nextValue);\n }\n }, { isActive: focus });\n return (React.createElement(Text, null, placeholder\n ? value.length > 0\n ? renderedValue\n : renderedPlaceholder\n : renderedValue));\n}\nexport default TextInput;\nexport function UncontrolledTextInput({ initialValue = '', ...props }) {\n const [value, setValue] = useState(initialValue);\n return React.createElement(TextInput, { ...props, value: value, onChange: setValue });\n}\n//# sourceMappingURL=index.js.map",
|
|
8
|
+
"import fs from 'fs-extra';\nimport path from 'path';\nimport os from 'os';\n\ninterface ScreenState {\n status?: 'included' | 'ignored' | 'discarded';\n route?: string;\n}\n\ninterface SiteManifestData {\n screens: Record<string, ScreenState>;\n}\n\ninterface LegacyDiscardData {\n discardedScreenIds: string[];\n}\n\nexport class SiteManifest {\n private filePath: string;\n private legacyPath: string;\n\n constructor(projectId: string) {\n const dir = path.join(os.homedir(), '.stitch-mcp', 'site', projectId);\n this.filePath = path.join(dir, 'site-manifest.json');\n this.legacyPath = path.join(dir, 'discarded.json');\n }\n\n async load(): Promise<Map<string, ScreenState>> {\n try {\n const data: SiteManifestData = await fs.readJson(this.filePath);\n return new Map(Object.entries(data.screens || {}));\n } catch {\n // site-manifest.json doesn't exist or is corrupted — try legacy migration\n }\n\n try {\n const legacy: LegacyDiscardData = await fs.readJson(this.legacyPath);\n const map = new Map<string, ScreenState>();\n for (const id of legacy.discardedScreenIds || []) {\n map.set(id, { status: 'discarded' });\n }\n return map;\n } catch {\n return new Map();\n }\n }\n\n async save(screens: { id: string; status: string; route: string }[]): Promise<void> {\n const record: Record<string, ScreenState> = {};\n for (const screen of screens) {\n const entry: ScreenState = {};\n if (screen.status !== 'ignored') {\n entry.status = screen.status as ScreenState['status'];\n }\n if (screen.route !== '') {\n entry.route = screen.route;\n }\n if (entry.status || entry.route) {\n record[screen.id] = entry;\n }\n }\n await fs.ensureDir(path.dirname(this.filePath));\n const data: SiteManifestData = { screens: record };\n await fs.writeJson(this.filePath, data, { spaces: 2 });\n }\n}\n",
|
|
9
|
+
"import React from 'react';\nimport { Text } from 'ink';\n\ninterface StatusIconProps {\n status: 'included' | 'ignored' | 'discarded';\n}\n\nexport const StatusIcon: React.FC<StatusIconProps> = ({ status }) => {\n if (status === 'included') {\n return <Text color=\"green\">✔ </Text>;\n }\n if (status === 'discarded') {\n return <Text color=\"red\">✖ </Text>;\n }\n return <Text color=\"gray\">- </Text>;\n};\n",
|
|
10
|
+
"import React from 'react';\nimport { Box, Text, useStdout } from 'ink';\nimport type { UIScreen } from './types.js';\nimport { StatusIcon } from './components/StatusIcon.js';\n\ninterface ScreenListProps {\n items: { screen: UIScreen; sourceIndex: number }[];\n activeIndex: number;\n}\n\nexport const ScreenList: React.FC<ScreenListProps> = ({ items, activeIndex }) => {\n const { stdout } = useStdout();\n const height = stdout ? stdout.rows : 20; // Default to 20 if unavailable\n const LIST_HEIGHT = Math.max(5, height - 10); // Reserve space for header/footer\n\n // Adjust start to keep active item in view\n let start = 0;\n if (activeIndex >= LIST_HEIGHT) {\n start = activeIndex - LIST_HEIGHT + 1;\n }\n start = Math.max(0, activeIndex - Math.floor(LIST_HEIGHT / 2));\n const end = Math.min(items.length, start + LIST_HEIGHT);\n\n // Correction if near end\n if (end - start < LIST_HEIGHT && items.length > LIST_HEIGHT) {\n start = Math.max(0, items.length - LIST_HEIGHT);\n }\n\n const visibleItems = items.slice(start, end);\n\n return (\n <Box flexDirection=\"column\" flexGrow={1} borderStyle=\"single\" borderColor=\"blue\">\n {start > 0 && (\n <Box paddingLeft={1}>\n <Text color=\"gray\">... {start} more above ...</Text>\n </Box>\n )}\n\n {visibleItems.map((item, i) => {\n const index = start + i;\n const isActive = index === activeIndex;\n const { screen } = item;\n\n return (\n <Box key={screen.id}>\n <Text color={isActive ? 'cyan' : undefined}>\n {isActive ? '> ' : ' '}\n </Text>\n <StatusIcon status={screen.status} />\n <Text color={isActive ? 'cyan' : undefined} wrap=\"truncate\">\n {screen.title}\n </Text>\n {screen.route && (\n <Text color=\"gray\">{' -> '}{screen.route}</Text>\n )}\n </Box>\n );\n })}\n\n {end < items.length && (\n <Box paddingLeft={1}>\n <Text color=\"gray\">... {items.length - end} more below ...</Text>\n </Box>\n )}\n </Box>\n );\n};\n",
|
|
11
|
+
"import { useState, useEffect, useRef } from 'react';\nimport { StitchViteServer } from '../../../lib/server/vite/StitchViteServer.js';\nimport type { UIScreen } from '../../../lib/services/site/types.js';\nimport pLimit from 'p-limit';\n\nexport type HydrationStatus = 'idle' | 'downloading' | 'ready' | 'error';\n\nexport type FetchContentFn = (url: string) => Promise<string>;\n\nexport function useProjectHydration(\n screens: UIScreen[],\n server: StitchViteServer | null,\n fetchContent: FetchContentFn,\n activeScreenId?: string\n) {\n const [hydrationStatus, setHydrationStatus] = useState<HydrationStatus>('idle');\n const [progress, setProgress] = useState(0);\n const contentCache = useRef<Map<string, string>>(new Map());\n const [htmlContent, setHtmlContent] = useState<Map<string, string>>(new Map());\n\n useEffect(() => {\n if (!server || screens.length === 0) return;\n\n let mounted = true;\n\n const hydrate = async () => {\n // Determine what needs to be downloaded\n // 1. All included screens\n // 2. The active screen (for preview), even if ignored\n const toDownload = screens.filter(s => {\n if (contentCache.current.has(s.id)) return false;\n return s.status === 'included' || s.id === activeScreenId;\n });\n\n if (toDownload.length === 0) {\n // If nothing to download, ensure server has everything mounted\n // (Just in case activeScreenId changed to something already cached but not mounted?\n // Actually server mount is persistent as long as server is running.\n // But if we have cached content, we should ensure it is mounted.)\n\n // Also check if we should update status to ready\n if (hydrationStatus === 'idle' || hydrationStatus === 'downloading') {\n setHydrationStatus('ready');\n setHtmlContent(new Map(contentCache.current));\n }\n\n // Mount cached content to server if not already?\n // It's safer to re-mount or check.\n // For now, let's just mount the active one to be sure if it's cached.\n if (activeScreenId && contentCache.current.has(activeScreenId)) {\n server.mount(`/_preview/${activeScreenId}`, contentCache.current.get(activeScreenId)!);\n }\n\n return;\n }\n\n setHydrationStatus('downloading');\n const limit = pLimit(3);\n let completed = 0;\n const total = toDownload.length;\n\n try {\n await Promise.all(toDownload.map(screen => limit(async () => {\n if (!mounted) return;\n\n if (!screen.downloadUrl) return;\n\n try {\n const html = await fetchContent(screen.downloadUrl);\n if (mounted) {\n contentCache.current.set(screen.id, html);\n server.mount(`/_preview/${screen.id}`, html);\n }\n } catch (e) {\n console.error(`Failed to hydrate ${screen.id}`, e);\n }\n\n if (mounted) {\n completed++;\n setProgress(completed / total);\n }\n })));\n\n if (mounted) {\n setHtmlContent(new Map(contentCache.current));\n setHydrationStatus('ready');\n }\n } catch (e) {\n if (mounted) setHydrationStatus('error');\n }\n };\n\n hydrate();\n\n return () => { mounted = false; };\n }, [screens, server, fetchContent, activeScreenId]);\n\n return { hydrationStatus, progress, htmlContent };\n}\n"
|
|
12
|
+
],
|
|
13
|
+
"mappings": "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",
|
|
14
|
+
"debugId": "BA12672C2AC4B82664756E2164756E21",
|
|
15
|
+
"names": []
|
|
16
|
+
}
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SiteBuilder,
|
|
3
|
+
SiteManifest
|
|
4
|
+
} from "./chunk-4p1wfk3t.js";
|
|
5
|
+
import {
|
|
6
|
+
require_jsx_dev_runtime
|
|
7
|
+
} from "./chunk-krfqppg2.js";
|
|
8
|
+
import {
|
|
9
|
+
AssetGateway
|
|
10
|
+
} from "./chunk-yvzzrczy.js";
|
|
11
|
+
import {
|
|
12
|
+
require_lib
|
|
13
|
+
} from "./chunk-w8q7nsm7.js";
|
|
14
|
+
import {
|
|
15
|
+
render_default
|
|
16
|
+
} from "./chunk-f1kjn6cd.js";
|
|
17
|
+
import"./chunk-4jwmvjb4.js";
|
|
18
|
+
import {
|
|
19
|
+
fetchWithRetry
|
|
20
|
+
} from "./chunk-6gw9apqb.js";
|
|
21
|
+
import {
|
|
22
|
+
stitch
|
|
23
|
+
} from "./chunk-a1mk24q9.js";
|
|
24
|
+
import {
|
|
25
|
+
pLimit
|
|
26
|
+
} from "./chunk-a5xra9jn.js";
|
|
27
|
+
import"./chunk-nq68kghz.js";
|
|
28
|
+
import"./chunk-hc7sdwmn.js";
|
|
29
|
+
import"./chunk-3sfn889r.js";
|
|
30
|
+
import {
|
|
31
|
+
exports_external
|
|
32
|
+
} from "./chunk-c6ge431q.js";
|
|
33
|
+
import {
|
|
34
|
+
__toESM
|
|
35
|
+
} from "./chunk-9wyra8hs.js";
|
|
36
|
+
|
|
37
|
+
// src/lib/services/site/SiteService.ts
|
|
38
|
+
var import_fs_extra = __toESM(require_lib(), 1);
|
|
39
|
+
import path from "path";
|
|
40
|
+
class SiteService {
|
|
41
|
+
static toUIScreens(screens) {
|
|
42
|
+
return screens.filter((s) => s.htmlCode && s.htmlCode.downloadUrl).map((s) => ({
|
|
43
|
+
id: s.name,
|
|
44
|
+
title: s.title,
|
|
45
|
+
downloadUrl: s.htmlCode.downloadUrl,
|
|
46
|
+
status: "ignored",
|
|
47
|
+
route: ""
|
|
48
|
+
}));
|
|
49
|
+
}
|
|
50
|
+
static async generateSite(config, htmlContent, assetGateway, outputDir = ".") {
|
|
51
|
+
await import_fs_extra.default.ensureDir(path.join(outputDir, "src/pages"));
|
|
52
|
+
await import_fs_extra.default.ensureDir(path.join(outputDir, "src/layouts"));
|
|
53
|
+
await import_fs_extra.default.ensureDir(path.join(outputDir, "public/assets"));
|
|
54
|
+
const pkgJson = {
|
|
55
|
+
name: "stitch-site",
|
|
56
|
+
type: "module",
|
|
57
|
+
version: "0.0.1",
|
|
58
|
+
scripts: {
|
|
59
|
+
dev: "astro dev",
|
|
60
|
+
start: "astro dev",
|
|
61
|
+
build: "astro build",
|
|
62
|
+
preview: "astro preview",
|
|
63
|
+
astro: "astro"
|
|
64
|
+
},
|
|
65
|
+
dependencies: {
|
|
66
|
+
astro: "^5.0.0"
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
await import_fs_extra.default.writeJson(path.join(outputDir, "package.json"), pkgJson, { spaces: 2 });
|
|
70
|
+
const astroConfig = `import { defineConfig } from 'astro/config';
|
|
71
|
+
export default defineConfig({});`;
|
|
72
|
+
await import_fs_extra.default.writeFile(path.join(outputDir, "astro.config.mjs"), astroConfig);
|
|
73
|
+
const layout = `---
|
|
74
|
+
interface Props {
|
|
75
|
+
title: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const { title } = Astro.props;
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
<!doctype html>
|
|
82
|
+
<html lang="en">
|
|
83
|
+
<head>
|
|
84
|
+
<meta charset="UTF-8" />
|
|
85
|
+
<meta name="description" content="Astro description" />
|
|
86
|
+
<meta name="viewport" content="width=device-width" />
|
|
87
|
+
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
88
|
+
<meta name="generator" content={Astro.generator} />
|
|
89
|
+
<title>{title}</title>
|
|
90
|
+
</head>
|
|
91
|
+
<body>
|
|
92
|
+
<slot />
|
|
93
|
+
</body>
|
|
94
|
+
</html>
|
|
95
|
+
`;
|
|
96
|
+
await import_fs_extra.default.writeFile(path.join(outputDir, "src/layouts/Layout.astro"), layout);
|
|
97
|
+
const limit = pLimit(10);
|
|
98
|
+
const tasks = config.routes.map((route) => limit(async () => {
|
|
99
|
+
if (route.status !== "included")
|
|
100
|
+
return;
|
|
101
|
+
const html = htmlContent.get(route.screenId);
|
|
102
|
+
if (!html) {
|
|
103
|
+
console.warn(`No HTML content found for screen ${route.screenId}`);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const { html: rewrittenHtml, assets } = await assetGateway.rewriteHtmlForBuild(html);
|
|
107
|
+
const assetsDir = path.join(outputDir, "public/assets");
|
|
108
|
+
for (const asset of assets) {
|
|
109
|
+
await assetGateway.copyAssetTo(asset.url, path.join(assetsDir, asset.filename));
|
|
110
|
+
}
|
|
111
|
+
let filePath = route.route;
|
|
112
|
+
if (filePath === "/") {
|
|
113
|
+
filePath = "index";
|
|
114
|
+
} else {
|
|
115
|
+
if (filePath.startsWith("/"))
|
|
116
|
+
filePath = filePath.substring(1);
|
|
117
|
+
}
|
|
118
|
+
const fullPath = path.join(outputDir, "src/pages", `${filePath}.astro`);
|
|
119
|
+
await import_fs_extra.default.ensureDir(path.dirname(fullPath));
|
|
120
|
+
await import_fs_extra.default.writeFile(fullPath, rewrittenHtml);
|
|
121
|
+
}));
|
|
122
|
+
await Promise.all(tasks);
|
|
123
|
+
}
|
|
124
|
+
static slugify(text) {
|
|
125
|
+
return text.toString().toLowerCase().replace(/\s+/g, "-").replace(/[^\w\-]+/g, "").replace(/\-\-+/g, "-").replace(/^-+/, "").replace(/-+$/, "");
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// src/commands/site/utils/suggestRoute.ts
|
|
130
|
+
var HOME_SLUGS = new Set(["home", "landing", "landing-page", "index"]);
|
|
131
|
+
function suggestRoute(title) {
|
|
132
|
+
const slug = title.toLowerCase().replace(/[^a-z0-9\s-]/g, "").trim().replace(/\s+/g, "-").replace(/-+/g, "-");
|
|
133
|
+
return HOME_SLUGS.has(slug) ? "/" : `/${slug}`;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// src/commands/site/list-screens/handler.ts
|
|
137
|
+
class ListScreensHandler {
|
|
138
|
+
client;
|
|
139
|
+
constructor(client) {
|
|
140
|
+
this.client = client;
|
|
141
|
+
}
|
|
142
|
+
async execute(input) {
|
|
143
|
+
try {
|
|
144
|
+
const project = this.client.project(input.projectId);
|
|
145
|
+
const sdkScreens = await project.screens();
|
|
146
|
+
const limit = pLimit(3);
|
|
147
|
+
const screens = await Promise.all(sdkScreens.map((s) => limit(async () => {
|
|
148
|
+
const htmlUrl = await s.getHtml().catch(() => null);
|
|
149
|
+
return {
|
|
150
|
+
screenId: s.screenId,
|
|
151
|
+
title: s.title ?? s.screenId,
|
|
152
|
+
suggestedRoute: suggestRoute(s.title ?? s.screenId),
|
|
153
|
+
hasHtml: htmlUrl !== null
|
|
154
|
+
};
|
|
155
|
+
})));
|
|
156
|
+
return { success: true, projectId: input.projectId, screens };
|
|
157
|
+
} catch (e) {
|
|
158
|
+
return {
|
|
159
|
+
success: false,
|
|
160
|
+
error: {
|
|
161
|
+
code: "SCREENS_FETCH_FAILED",
|
|
162
|
+
message: e.message,
|
|
163
|
+
recoverable: false
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// src/commands/site/list-screens/spec.ts
|
|
171
|
+
var ListScreensInputSchema = exports_external.object({
|
|
172
|
+
projectId: exports_external.string().min(1, "projectId is required")
|
|
173
|
+
});
|
|
174
|
+
var ListScreensErrorCode = exports_external.enum([
|
|
175
|
+
"PROJECT_NOT_FOUND",
|
|
176
|
+
"SCREENS_FETCH_FAILED"
|
|
177
|
+
]);
|
|
178
|
+
|
|
179
|
+
// src/commands/site/generate/handler.ts
|
|
180
|
+
class GenerateHandler {
|
|
181
|
+
client;
|
|
182
|
+
fetchHtml;
|
|
183
|
+
constructor(client, fetchHtml = fetchWithRetry) {
|
|
184
|
+
this.client = client;
|
|
185
|
+
this.fetchHtml = fetchHtml;
|
|
186
|
+
}
|
|
187
|
+
async execute(input) {
|
|
188
|
+
try {
|
|
189
|
+
const project = this.client.project(input.projectId);
|
|
190
|
+
const sdkScreens = await project.screens();
|
|
191
|
+
const screenMap = new Map(sdkScreens.map((s) => [s.screenId, s]));
|
|
192
|
+
const missingIds = input.routesJson.map((r) => r.screenId).filter((id) => !screenMap.has(id));
|
|
193
|
+
if (missingIds.length > 0) {
|
|
194
|
+
return {
|
|
195
|
+
success: false,
|
|
196
|
+
error: {
|
|
197
|
+
code: "SCREEN_NOT_FOUND",
|
|
198
|
+
message: `Screen IDs not found in project: ${missingIds.join(", ")}`,
|
|
199
|
+
hint: `Run stitch site -p ${input.projectId} --list-screens to see available screen IDs.`,
|
|
200
|
+
recoverable: true
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
const limit = pLimit(3);
|
|
205
|
+
const htmlContent = new Map;
|
|
206
|
+
const errors = [];
|
|
207
|
+
await Promise.all(input.routesJson.map((r) => limit(async () => {
|
|
208
|
+
const screen = screenMap.get(r.screenId);
|
|
209
|
+
try {
|
|
210
|
+
const htmlUrl = await screen.getHtml();
|
|
211
|
+
const html = htmlUrl ? await this.fetchHtml(htmlUrl) : "";
|
|
212
|
+
htmlContent.set(r.screenId, html);
|
|
213
|
+
} catch (e) {
|
|
214
|
+
errors.push(`${r.screenId}: ${e.message}`);
|
|
215
|
+
}
|
|
216
|
+
})));
|
|
217
|
+
if (errors.length > 0) {
|
|
218
|
+
return {
|
|
219
|
+
success: false,
|
|
220
|
+
error: {
|
|
221
|
+
code: "HTML_FETCH_FAILED",
|
|
222
|
+
message: `Failed to fetch HTML for screens: ${errors.join("; ")}`,
|
|
223
|
+
recoverable: false
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
const config = {
|
|
228
|
+
projectId: input.projectId,
|
|
229
|
+
routes: input.routesJson.map((r) => ({ screenId: r.screenId, route: r.route, status: "included" }))
|
|
230
|
+
};
|
|
231
|
+
const assetGateway = new AssetGateway;
|
|
232
|
+
await SiteService.generateSite(config, htmlContent, assetGateway, input.outputDir);
|
|
233
|
+
return {
|
|
234
|
+
success: true,
|
|
235
|
+
outputDir: input.outputDir,
|
|
236
|
+
pages: input.routesJson.map((r) => ({ screenId: r.screenId, route: r.route }))
|
|
237
|
+
};
|
|
238
|
+
} catch (e) {
|
|
239
|
+
return {
|
|
240
|
+
success: false,
|
|
241
|
+
error: {
|
|
242
|
+
code: "GENERATE_FAILED",
|
|
243
|
+
message: e.message,
|
|
244
|
+
recoverable: false
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// src/commands/site/generate/spec.ts
|
|
252
|
+
var RouteEntrySchema = exports_external.object({
|
|
253
|
+
screenId: exports_external.string().min(1, "screenId is required"),
|
|
254
|
+
route: exports_external.string().startsWith("/", "route must start with /")
|
|
255
|
+
});
|
|
256
|
+
var RoutesJsonSchema = exports_external.string().transform((str, ctx) => {
|
|
257
|
+
try {
|
|
258
|
+
const parsed = JSON.parse(str);
|
|
259
|
+
const result = exports_external.array(RouteEntrySchema).safeParse(parsed);
|
|
260
|
+
if (!result.success) {
|
|
261
|
+
ctx.addIssue({ code: exports_external.ZodIssueCode.custom, message: result.error.issues[0]?.message ?? "Invalid routes array" });
|
|
262
|
+
return exports_external.NEVER;
|
|
263
|
+
}
|
|
264
|
+
return result.data;
|
|
265
|
+
} catch {
|
|
266
|
+
ctx.addIssue({ code: exports_external.ZodIssueCode.custom, message: "routes must be valid JSON" });
|
|
267
|
+
return exports_external.NEVER;
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
var GenerateInputSchema = exports_external.object({
|
|
271
|
+
projectId: exports_external.string().min(1, "projectId is required"),
|
|
272
|
+
routesJson: RoutesJsonSchema,
|
|
273
|
+
outputDir: exports_external.string().default(".")
|
|
274
|
+
});
|
|
275
|
+
var GenerateErrorCode = exports_external.enum([
|
|
276
|
+
"INVALID_ROUTES",
|
|
277
|
+
"SCREEN_NOT_FOUND",
|
|
278
|
+
"HTML_FETCH_FAILED",
|
|
279
|
+
"GENERATE_FAILED"
|
|
280
|
+
]);
|
|
281
|
+
|
|
282
|
+
// src/commands/site/index.tsx
|
|
283
|
+
var jsx_dev_runtime = __toESM(require_jsx_dev_runtime(), 1);
|
|
284
|
+
|
|
285
|
+
class SiteCommandHandler {
|
|
286
|
+
client;
|
|
287
|
+
constructor(client = stitch) {
|
|
288
|
+
this.client = client;
|
|
289
|
+
}
|
|
290
|
+
async execute(options) {
|
|
291
|
+
if (options.listScreens) {
|
|
292
|
+
const input = ListScreensInputSchema.safeParse({ projectId: options.projectId });
|
|
293
|
+
if (!input.success) {
|
|
294
|
+
console.log(JSON.stringify({ success: false, error: { code: "INVALID_INPUT", message: input.error.issues[0]?.message } }, null, 2));
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
const result = await new ListScreensHandler(this.client).execute(input.data);
|
|
298
|
+
console.log(JSON.stringify(result, null, 2));
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
if (options.routes !== undefined) {
|
|
302
|
+
const input = GenerateInputSchema.safeParse({
|
|
303
|
+
projectId: options.projectId,
|
|
304
|
+
routesJson: options.routes,
|
|
305
|
+
outputDir: options.outputDir
|
|
306
|
+
});
|
|
307
|
+
if (!input.success) {
|
|
308
|
+
console.log(JSON.stringify({ success: false, error: { code: "INVALID_INPUT", message: input.error.issues[0]?.message } }, null, 2));
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
const result = await new GenerateHandler(this.client).execute(input.data);
|
|
312
|
+
console.log(JSON.stringify(result, null, 2));
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
if (options.export) {
|
|
316
|
+
const project = this.client.project(options.projectId);
|
|
317
|
+
const sdkScreens = await project.screens();
|
|
318
|
+
const uiScreens = await Promise.all(sdkScreens.map(async (s) => ({
|
|
319
|
+
id: s.screenId,
|
|
320
|
+
title: s.title ?? s.screenId,
|
|
321
|
+
status: "ignored",
|
|
322
|
+
route: "",
|
|
323
|
+
downloadUrl: await s.getHtml().catch(() => null)
|
|
324
|
+
})));
|
|
325
|
+
const validScreens = uiScreens.filter((s) => !!s.downloadUrl);
|
|
326
|
+
const siteManifest = new SiteManifest(options.projectId);
|
|
327
|
+
const saved = await siteManifest.load();
|
|
328
|
+
for (const screen of validScreens) {
|
|
329
|
+
const state = saved.get(screen.id);
|
|
330
|
+
if (state?.status)
|
|
331
|
+
screen.status = state.status;
|
|
332
|
+
if (state?.route)
|
|
333
|
+
screen.route = state.route;
|
|
334
|
+
}
|
|
335
|
+
const included = validScreens.filter((s) => s.status === "included");
|
|
336
|
+
const exportData = {
|
|
337
|
+
projectId: options.projectId,
|
|
338
|
+
routes: included.map((s) => ({
|
|
339
|
+
screenId: s.id,
|
|
340
|
+
route: s.route
|
|
341
|
+
}))
|
|
342
|
+
};
|
|
343
|
+
console.log(JSON.stringify(exportData, null, 2));
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
let resultConfig = null;
|
|
347
|
+
let resultHtml;
|
|
348
|
+
const { waitUntilExit } = render_default(/* @__PURE__ */ jsx_dev_runtime.jsxDEV(SiteBuilder, {
|
|
349
|
+
projectId: options.projectId,
|
|
350
|
+
client: this.client,
|
|
351
|
+
onExit: (config, html) => {
|
|
352
|
+
resultConfig = config;
|
|
353
|
+
resultHtml = html;
|
|
354
|
+
}
|
|
355
|
+
}, undefined, false, undefined, this));
|
|
356
|
+
await waitUntilExit();
|
|
357
|
+
if (resultConfig && resultHtml) {
|
|
358
|
+
console.log("Generating site...");
|
|
359
|
+
const assetGateway = new AssetGateway;
|
|
360
|
+
const outputDir = options.outputDir || ".";
|
|
361
|
+
await SiteService.generateSite(resultConfig, resultHtml, assetGateway, outputDir);
|
|
362
|
+
console.log("Site generated successfully!");
|
|
363
|
+
} else {}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
export {
|
|
367
|
+
SiteCommandHandler
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
//# debugId=38734F280B97272E64756E2164756E21
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/lib/services/site/SiteService.ts", "../src/commands/site/utils/suggestRoute.ts", "../src/commands/site/list-screens/handler.ts", "../src/commands/site/list-screens/spec.ts", "../src/commands/site/generate/handler.ts", "../src/commands/site/generate/spec.ts", "../src/commands/site/index.tsx"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { RemoteScreen, SiteConfig, IAssetGateway, UIScreen } from './types.js';\nimport fs from 'fs-extra';\nimport path from 'path';\nimport pLimit from 'p-limit';\n\nexport class SiteService {\n static toUIScreens(screens: RemoteScreen[]): UIScreen[] {\n return screens\n .filter((s) => s.htmlCode && s.htmlCode.downloadUrl)\n .map((s) => ({\n id: s.name,\n title: s.title,\n downloadUrl: s.htmlCode!.downloadUrl!,\n status: 'ignored',\n route: '',\n }));\n }\n\n static async generateSite(\n config: SiteConfig,\n htmlContent: Map<string, string>,\n assetGateway: IAssetGateway,\n outputDir: string = '.'\n ): Promise<void> {\n // Scaffold\n await fs.ensureDir(path.join(outputDir, 'src/pages'));\n await fs.ensureDir(path.join(outputDir, 'src/layouts'));\n await fs.ensureDir(path.join(outputDir, 'public/assets'));\n\n // package.json\n const pkgJson = {\n name: \"stitch-site\",\n type: \"module\",\n version: \"0.0.1\",\n scripts: {\n \"dev\": \"astro dev\",\n \"start\": \"astro dev\",\n \"build\": \"astro build\",\n \"preview\": \"astro preview\",\n \"astro\": \"astro\"\n },\n dependencies: {\n \"astro\": \"^5.0.0\"\n }\n };\n await fs.writeJson(path.join(outputDir, 'package.json'), pkgJson, { spaces: 2 });\n\n // astro.config.mjs\n const astroConfig = `import { defineConfig } from 'astro/config';\nexport default defineConfig({});`;\n await fs.writeFile(path.join(outputDir, 'astro.config.mjs'), astroConfig);\n\n // src/layouts/Layout.astro\n const layout = `---\ninterface Props {\n\ttitle: string;\n}\n\nconst { title } = Astro.props;\n---\n\n<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"UTF-8\" />\n\t\t<meta name=\"description\" content=\"Astro description\" />\n\t\t<meta name=\"viewport\" content=\"width=device-width\" />\n\t\t<link rel=\"icon\" type=\"image/svg+xml\" href=\"/favicon.svg\" />\n\t\t<meta name=\"generator\" content={Astro.generator} />\n\t\t<title>{title}</title>\n\t</head>\n\t<body>\n\t\t<slot />\n\t</body>\n</html>\n`;\n await fs.writeFile(path.join(outputDir, 'src/layouts/Layout.astro'), layout);\n\n // Process routes\n const limit = pLimit(10);\n const tasks = config.routes.map((route) =>\n limit(async () => {\n if (route.status !== 'included') return;\n\n const html = htmlContent.get(route.screenId);\n if (!html) {\n console.warn(`No HTML content found for screen ${route.screenId}`);\n return;\n }\n\n // Rewrite\n const { html: rewrittenHtml, assets } = await assetGateway.rewriteHtmlForBuild(html);\n\n // Copy assets\n const assetsDir = path.join(outputDir, 'public/assets');\n for (const asset of assets) {\n await assetGateway.copyAssetTo(asset.url, path.join(assetsDir, asset.filename));\n }\n\n let filePath = route.route;\n if (filePath === '/') {\n filePath = 'index';\n } else {\n // Remove leading slash\n if (filePath.startsWith('/')) filePath = filePath.substring(1);\n }\n\n const fullPath = path.join(outputDir, 'src/pages', `${filePath}.astro`);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, rewrittenHtml);\n })\n );\n\n await Promise.all(tasks);\n }\n\n static slugify(text: string): string {\n return text.toString().toLowerCase()\n .replace(/\\s+/g, '-')\n .replace(/[^\\w\\-]+/g, '')\n .replace(/\\-\\-+/g, '-')\n .replace(/^-+/, '')\n .replace(/-+$/, '');\n }\n}\n",
|
|
6
|
+
"const HOME_SLUGS = new Set(['home', 'landing', 'landing-page', 'index']);\n\nexport function suggestRoute(title: string): string {\n const slug = title\n .toLowerCase()\n .replace(/[^a-z0-9\\s-]/g, '')\n .trim()\n .replace(/\\s+/g, '-')\n .replace(/-+/g, '-');\n return HOME_SLUGS.has(slug) ? '/' : `/${slug}`;\n}\n",
|
|
7
|
+
"import type { Stitch } from '@google/stitch-sdk';\nimport pLimit from 'p-limit';\nimport type { ListScreensSpec, ListScreensInput, ListScreensResult } from './spec.js';\nimport { suggestRoute } from '../utils/suggestRoute.js';\n\nexport class ListScreensHandler implements ListScreensSpec {\n constructor(private readonly client: Stitch) {}\n\n async execute(input: ListScreensInput): Promise<ListScreensResult> {\n try {\n const project = this.client.project(input.projectId);\n const sdkScreens = await project.screens();\n\n const limit = pLimit(3);\n const screens = await Promise.all(\n sdkScreens.map((s: any) => limit(async () => {\n const htmlUrl = await s.getHtml().catch(() => null);\n return {\n screenId: s.screenId,\n title: s.title ?? s.screenId,\n suggestedRoute: suggestRoute(s.title ?? s.screenId),\n hasHtml: htmlUrl !== null,\n };\n }))\n );\n\n return { success: true, projectId: input.projectId, screens };\n } catch (e: any) {\n return {\n success: false,\n error: {\n code: 'SCREENS_FETCH_FAILED',\n message: e.message,\n recoverable: false,\n },\n };\n }\n }\n}\n",
|
|
8
|
+
"import { z } from 'zod';\n\n// 1. INPUT\nexport const ListScreensInputSchema = z.object({\n projectId: z.string().min(1, 'projectId is required'),\n});\nexport type ListScreensInput = z.infer<typeof ListScreensInputSchema>;\n\n// 2. ERROR CODES\nexport const ListScreensErrorCode = z.enum([\n 'PROJECT_NOT_FOUND',\n 'SCREENS_FETCH_FAILED',\n]);\nexport type ListScreensErrorCode = z.infer<typeof ListScreensErrorCode>;\n\n// 3. RESULT\nexport type ListScreensSuccess = {\n success: true;\n projectId: string;\n screens: Array<{\n screenId: string;\n title: string;\n suggestedRoute: string;\n hasHtml: boolean;\n }>;\n};\n\nexport type ListScreensFailure = {\n success: false;\n error: {\n code: ListScreensErrorCode;\n message: string;\n recoverable: boolean;\n };\n};\n\nexport type ListScreensResult = ListScreensSuccess | ListScreensFailure;\n\n// 4. INTERFACE\nexport interface ListScreensSpec {\n execute(input: ListScreensInput): Promise<ListScreensResult>;\n}\n",
|
|
9
|
+
"import type { Stitch } from '@google/stitch-sdk';\nimport pLimit from 'p-limit';\nimport type { GenerateSpec, GenerateInput, GenerateResult } from './spec.js';\nimport { SiteService } from '../../../lib/services/site/SiteService.js';\nimport { AssetGateway } from '../../../lib/server/AssetGateway.js';\nimport { fetchWithRetry } from '../utils/fetchWithRetry.js';\n\nexport class GenerateHandler implements GenerateSpec {\n constructor(\n private readonly client: Stitch,\n private readonly fetchHtml: (url: string) => Promise<string> = fetchWithRetry,\n ) {}\n\n async execute(input: GenerateInput): Promise<GenerateResult> {\n try {\n const project = this.client.project(input.projectId);\n const sdkScreens = await project.screens();\n const screenMap = new Map(sdkScreens.map((s: any) => [s.screenId, s]));\n\n // Validate all requested screenIds exist\n const missingIds = input.routesJson\n .map(r => r.screenId)\n .filter(id => !screenMap.has(id));\n\n if (missingIds.length > 0) {\n return {\n success: false,\n error: {\n code: 'SCREEN_NOT_FOUND',\n message: `Screen IDs not found in project: ${missingIds.join(', ')}`,\n hint: `Run stitch site -p ${input.projectId} --list-screens to see available screen IDs.`,\n recoverable: true,\n },\n };\n }\n\n // Fetch HTML for each screen\n const limit = pLimit(3);\n const htmlContent = new Map<string, string>();\n const errors: string[] = [];\n\n await Promise.all(\n input.routesJson.map(r => limit(async () => {\n const screen = screenMap.get(r.screenId)!;\n try {\n const htmlUrl = await screen.getHtml();\n const html = htmlUrl ? await this.fetchHtml(htmlUrl) : '';\n htmlContent.set(r.screenId, html);\n } catch (e: any) {\n errors.push(`${r.screenId}: ${e.message}`);\n }\n }))\n );\n\n if (errors.length > 0) {\n return {\n success: false,\n error: {\n code: 'HTML_FETCH_FAILED',\n message: `Failed to fetch HTML for screens: ${errors.join('; ')}`,\n recoverable: false,\n },\n };\n }\n\n const config = {\n projectId: input.projectId,\n routes: input.routesJson.map(r => ({ screenId: r.screenId, route: r.route, status: 'included' as const })),\n };\n\n const assetGateway = new AssetGateway();\n await SiteService.generateSite(config, htmlContent, assetGateway, input.outputDir);\n\n return {\n success: true,\n outputDir: input.outputDir,\n pages: input.routesJson.map(r => ({ screenId: r.screenId, route: r.route })),\n };\n } catch (e: any) {\n return {\n success: false,\n error: {\n code: 'GENERATE_FAILED',\n message: e.message,\n recoverable: false,\n },\n };\n }\n }\n}\n",
|
|
10
|
+
"import { z } from 'zod';\n\n// 1. VALIDATION HELPERS\nconst RouteEntrySchema = z.object({\n screenId: z.string().min(1, 'screenId is required'),\n route: z.string().startsWith('/', 'route must start with /'),\n});\n\nconst RoutesJsonSchema = z.string().transform((str, ctx) => {\n try {\n const parsed = JSON.parse(str);\n const result = z.array(RouteEntrySchema).safeParse(parsed);\n if (!result.success) {\n ctx.addIssue({ code: z.ZodIssueCode.custom, message: result.error.issues[0]?.message ?? 'Invalid routes array' });\n return z.NEVER;\n }\n return result.data;\n } catch {\n ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'routes must be valid JSON' });\n return z.NEVER;\n }\n});\n\n// 2. INPUT\nexport const GenerateInputSchema = z.object({\n projectId: z.string().min(1, 'projectId is required'),\n routesJson: RoutesJsonSchema,\n outputDir: z.string().default('.'),\n});\nexport type GenerateInput = z.infer<typeof GenerateInputSchema>;\n\n// 3. ERROR CODES\nexport const GenerateErrorCode = z.enum([\n 'INVALID_ROUTES',\n 'SCREEN_NOT_FOUND',\n 'HTML_FETCH_FAILED',\n 'GENERATE_FAILED',\n]);\nexport type GenerateErrorCode = z.infer<typeof GenerateErrorCode>;\n\n// 4. RESULT\nexport type GenerateSuccess = {\n success: true;\n outputDir: string;\n pages: Array<{ screenId: string; route: string }>;\n};\n\nexport type GenerateFailure = {\n success: false;\n error: {\n code: GenerateErrorCode;\n message: string;\n hint?: string;\n recoverable: boolean;\n };\n};\n\nexport type GenerateResult = GenerateSuccess | GenerateFailure;\n\n// 5. INTERFACE\nexport interface GenerateSpec {\n execute(input: GenerateInput): Promise<GenerateResult>;\n}\n",
|
|
11
|
+
"import React from 'react';\nimport { render } from 'ink';\nimport { stitch } from '@google/stitch-sdk';\nimport type { Stitch } from '@google/stitch-sdk';\nimport { SiteBuilder } from './ui/SiteBuilder.js';\nimport { SiteService } from '../../lib/services/site/SiteService.js';\nimport { AssetGateway } from '../../lib/server/AssetGateway.js';\nimport { SiteManifest } from './utils/SiteManifest.js';\nimport { ListScreensHandler } from './list-screens/handler.js';\nimport { ListScreensInputSchema } from './list-screens/spec.js';\nimport { GenerateHandler } from './generate/handler.js';\nimport { GenerateInputSchema } from './generate/spec.js';\nimport type { SiteConfig, UIScreen } from '../../lib/services/site/types.js';\n\ninterface SiteCommandOptions {\n projectId: string;\n outputDir?: string;\n export?: boolean;\n listScreens?: boolean;\n routes?: string;\n}\n\nexport class SiteCommandHandler {\n constructor(private client: Stitch = stitch) {}\n\n async execute(options: SiteCommandOptions) {\n if (options.listScreens) {\n const input = ListScreensInputSchema.safeParse({ projectId: options.projectId });\n if (!input.success) {\n console.log(JSON.stringify({ success: false, error: { code: 'INVALID_INPUT', message: input.error.issues[0]?.message } }, null, 2));\n return;\n }\n const result = await new ListScreensHandler(this.client).execute(input.data);\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n if (options.routes !== undefined) {\n const input = GenerateInputSchema.safeParse({\n projectId: options.projectId,\n routesJson: options.routes,\n outputDir: options.outputDir,\n });\n if (!input.success) {\n console.log(JSON.stringify({ success: false, error: { code: 'INVALID_INPUT', message: input.error.issues[0]?.message } }, null, 2));\n return;\n }\n const result = await new GenerateHandler(this.client).execute(input.data);\n console.log(JSON.stringify(result, null, 2));\n return;\n }\n\n if (options.export) {\n const project = this.client.project(options.projectId);\n const sdkScreens = await project.screens();\n\n const uiScreens = await Promise.all(\n sdkScreens.map(async (s: any) => ({\n id: s.screenId,\n title: s.title ?? s.screenId,\n status: 'ignored' as const,\n route: '',\n downloadUrl: await s.getHtml().catch(() => null)\n }))\n ) as UIScreen[];\n\n const validScreens = uiScreens.filter(s => !!s.downloadUrl);\n\n const siteManifest = new SiteManifest(options.projectId);\n const saved = await siteManifest.load();\n for (const screen of validScreens) {\n const state = saved.get(screen.id);\n if (state?.status) screen.status = state.status;\n if (state?.route) screen.route = state.route;\n }\n\n const included = validScreens.filter(s => s.status === 'included');\n const exportData = {\n projectId: options.projectId,\n routes: included.map(s => ({\n screenId: s.id,\n route: s.route,\n })),\n };\n console.log(JSON.stringify(exportData, null, 2));\n return;\n }\n\n let resultConfig: SiteConfig | null = null;\n let resultHtml: Map<string, string> | undefined;\n\n const { waitUntilExit } = render(\n <SiteBuilder\n projectId={options.projectId}\n client={this.client}\n onExit={(config, html) => {\n resultConfig = config;\n resultHtml = html;\n }}\n />\n );\n\n await waitUntilExit();\n\n if (resultConfig && resultHtml) {\n console.log('Generating site...');\n const assetGateway = new AssetGateway();\n const outputDir = options.outputDir || '.';\n\n await SiteService.generateSite(\n resultConfig,\n resultHtml,\n assetGateway,\n outputDir\n );\n console.log('Site generated successfully!');\n } else {\n // console.log('Cancelled.');\n }\n }\n}\n"
|
|
12
|
+
],
|
|
13
|
+
"mappings": "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",
|
|
14
|
+
"debugId": "38734F280B97272E64756E2164756E21",
|
|
15
|
+
"names": []
|
|
16
|
+
}
|