Lines 162-202javascript
166`;R.writeFileSync(x.join(e,"vite.config.mjs"),s)}function Ac(e,t,o){let n=R.readFileSync(e,"utf8"),r=!1;if(!n.includes("cfm-preview-fonts")&&o&&n.includes("</head>")&&(n=n.replace("</head>",`${o}
167</head>`),r=!0),!n.includes("CFM_UI_CONFIG_SNAPSHOT")){let i=`<script>${t}</script>`;n=n.includes("</body>")?n.replace("</body>",`${i}
169${i}`,r=!0}r&&R.writeFileSync(e,n)}function Rc(e){return e.replace(/_/g," ")}async function Ri(e){let{projectRoot:t,outputDir:o,keys:n}=e,r=x.join(__dirname,"..",".."),i=x.join(r,"templates","preview-harness","vite-app");if(!R.existsSync(i))throw new Error(`Missing Vite preview harness template at ${i}`);let s=Sc(t),a=x.join(o,".preview-vite-work");R.existsSync(a)&&R.rmSync(a,{recursive:!0,force:!0}),He(i,a),R.mkdirSync(x.join(a,"agent","src"),{recursive:!0}),He(s.componentsDir,x.join(a,"agent","src","components")),s.libDir&&He(s.libDir,x.join(a,"agent","src","lib")),s.publicDir&&He(s.publicDi ...
172 <meta charset="UTF-8" />
173 <meta name="viewport" content="width=device-width, initial-scale=1.0" />
174 <title>${Rc(v)} \u2014 CFM Preview</title>
175 <link id="cfm-preview-fonts" rel="preconnect" href="https://fonts.googleapis.com" />
176 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
177 <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Roboto:wght@400;500;600;700&family=Open+Sans:wght@400;500;600;700&family=Lato:wght@400;500;600;700&family=Poppins:wght@400;500;600;700&family=Montserrat:wght@400;500;600;700&family=Nunito:wght@400;500;600;700&family=Raleway:wght@400;500;600;700&family=Source+Sans+3:wght@400;500;600;700&family=Merriweather:wght@400;500;600;700&family=Playfair+Display:wght@400;500;600;700&display=swap" />
180 <div id="root"></div>
181 <script type="module" src="../src/entries/${v}.tsx"></script>
183</html>`),R.writeFileSync(x.join(a,"src","entries",`${v}.tsx`),xc(v));R.writeFileSync(x.join(a,"tsconfig.json"),JSON.stringify({compilerOptions:{target:"ES2020",lib:["ES2020","DOM"
184`));let a={},c=J.join(e,"out","previews"),l=J.join(c,"manifest.json"),d=In(e);Bi(e)?console.log(`${O.dim} Reusing fresh preview export (${d.length} survey types) \u2014 skip Vite rebuild${O.reset}`):(console.log(`${O.dim} Exporting component previews for local wizard\u2026${O.reset}`),await wt({projectRoot:e,surveyTypes:d})),q.existsSync(l)&&(a=JSON.parse(q.readFileSync(l,"utf8")));let f=await Rs(4200),b=`http://localhost:${f}`;return new Promise((w,I)=>{let A=no.createServer(async(m,g)=>{try{let _=m.url??"/",D=_.split("?")[0];if(m.method==="GET"&&D.startsWith("/api/project-logo/")){let v= ...
185${(await Promise.resolve().then(()=>(Pe(),_i))).formatInput4NoWizardBlock()}
186`),g.writeHead(200,{"Content-Type":"application/json"}),g.end(JSON.stringify({ok:!0,deleted:"out/"})),setTimeout(()=>{A.close(()=>{I(new Error("Client quit the wizard without saving. Wizard garbage collection complete (out/ preview artifacts removed)."))})},300);return}if(m.method==="POST"&&_==="/api/upload-logo"){let v=await Cs(m),C=JSON.parse(v);q.existsSync(t)||q.mkdirSync(t,{recursive:!0});let k=C.base64.replace(/^data:image\/\w+;base64,/,""),h=Buffer.from(k,"base64"),G=J.extname(C.filename),U=J.basename(C.filename,G).toLowerCase().replace(/[^a-z0-9_-]/g,""),Y=`logo_${Date.now()}_${U}${G|| ...
187${O.green}\u2705 UI configuration saved to ${o}${O.reset}`);try{let{runApplyUiConfig:U}=await Promise.resolve().then(()=>(oo(),to));U({projectRoot:e,configPath:o})}catch(U){console.log(`${O.yellow} CSS apply skipped: ${U instanceof Error?U.message:String(U)}${O.reset}`)}await As(e),g.writeHead(200,{"Content-Type":"application/json"}),g.end(JSON.stringify({ok:!0})),setTimeout(()=>{A.close(()=>w())},500);return}if(m.method==="GET"){let v=_.split("?")[0];if(v==="/"&&(v="/index.html"),v.startsWith("/previews/")&&q.existsSync(c)){let h=v.replace(/^
188${O.bold}${O.cyan}\u{1F3A8} Survey UI Customization Wizard${O.reset}`),console.log(`${O.bold}\u{1F517} Client wizard link \u2014 share this URL only:${O.reset}`),console.log(` ${
189`),ll(m)}),A.on("error",I);let $=()=>{Promise.resolve().then(()=>(Po(),ko)).then(({cleanupOutFolder:m})=>
190${P.bold}${P.cyan}\u{1F3A8} CFM UI Customization (AWS)${P.reset}
191`),d&&(console.log(`${P.dim} Review mode: seed kept in survey-ui-config.json; final + diff written on complete.${P.reset}`),console.log(`${P.dim} Apply later with: npx cfm-sdk confirm-ui-config${P.reset}
192`));let f=[...fe],{outputDir:b,files:w}=await wt({projectRoot:a,useTemplatesOnly:e.useTemplatesOnly,surveyTypes:f}),I=w.map(D=>({path:D.path,contentType:D.contentType,sizeBytes:D.sizeBytes})),{config:A,source:$}=Xe({projectRoot:a,surveyTypes:f,instanceId:s});A.surveyTypes=f,fn($),d&&($t.writeFileSync(c.seedPath,JSON.stringify(A,null,2),"utf8"),$t.writeFileSync(l,JSON.stringify(A,null,2),"utf8"),console.log(`${P.dim} Seed snapshot \u2192 survey-ui-config.json (+ .seed.json)${P.reset}`));let m=await Dn(`${i}/wizard/session/start`,{method:"POST",headers:{Authorization:`Bearer ${r}`,"Content-Typ ...
193${P.bold}${P.cyan}\u{1F517} Client wizard link \u2014 share with the client:${P.reset}`),console.log(`${P.green} ${m.wizardUrl}${P.reset}`),console.log
194`),pl(m.wizardUrl),!t){console.log(`${P.yellow}--no-wait: wizard URL (not polling):${P.reset}`),console.log(m.wizardUrl),d&&console.log(`${P.dim} When wizard completes, poll manually or re-run without --no-wait to capture final + diff.${P.reset}`);
195${P.yellow}\u26A0 Client quit the wizard \u2014 session cleaned up on S3${P.reset}`),new Error("Client quit the wizard without saving. S3 preview garbage was removed. Re-run customize-ui to start a new session.");if(D.status==="ready"&&D.config){let v=Mo(
196${P.green}\u2705 Configuration ready${P.reset}`),D.logoUrl&&console.log(`${P.dim} Logo URL: ${D.logoUrl}${P.reset}`),d){let h=
197`);let o=Uo(t);for(let n of o.warnings)console.log(`${te.yellow}WARN:${te.reset} ${n}`);if(o.errors.length>0){console.log(`${te.red}FAIL:${te.reset} Framework scaffold incomplete (${o.framework
198${te.dim}Fix: setup.md \xB7 Next: npx cfm-sdk scaffold-check${te.reset}`),1}return o.framework!=="unknown"&&console.log(`${te.green}OK:${te.
199${te.dim}Next: Phase 3\u20134 copy bundle + implementation_plan${te.reset}`),0}var Bo=S(require("fs")),Qo=S(require("path"));W();ie();var we=S(require("fs")),_e=S(require("path")),kl=["src","components","app","lib"],Pl=["src/components/IntroPage.tsx","components/IntroPage.tsx","app/components/IntroPage.tsx"],Fl=["src/components/SurveyPage.tsx","components/SurveyPage.tsx","app/components/SurveyPage.tsx"],$l=["src/components/SurveyPage.tsx","components/SurveyPage.tsx","app/components/SurveyPage.tsx","src/globals.css","src/index.css","src/app/globals.css","app/globals.css","src/app/layout.tsx","a ...
200`);for(let s=0;s<i.length;s++){let a=i[s];Dl(a)||(Ll.test(a
201`);let t=Uo(e);for(let i of t.warnings)console.log(`${T.yellow}WARN:${T.reset} ${i}`);if(!t.ok){console.log(`${T.
202${T.dim}Fix: setup.md \xB7 Next: npx cfm-sdk verify-build --fast${T.reset}`),1}console.log(`${T.green}OK:${T.reset} Scaffold checks passed (${t.framework})`);let o=zs(e);
Long lines were clipped for display.