Skip to content

Commit 37d96f5

Browse files
committed
use @tanstack/cli
1 parent 7aa5178 commit 37d96f5

File tree

11 files changed

+39
-97
lines changed

11 files changed

+39
-97
lines changed

package.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,7 @@
4848
"@stackblitz/sdk": "^1.11.0",
4949
"@tailwindcss/typography": "^0.5.13",
5050
"@tailwindcss/vite": "^4.1.11",
51-
"@tanstack/cta-engine": "^0.49.1",
52-
"@tanstack/cta-framework-react-cra": "^0.48.3",
53-
"@tanstack/cta-framework-solid": "^0.48.3",
51+
"@tanstack/create": "^0.49.1",
5452
"@tanstack/pacer": "^0.16.4",
5553
"@tanstack/react-pacer": "^0.17.4",
5654
"@tanstack/react-query": "^5.90.12",

pnpm-lock.yaml

Lines changed: 5 additions & 29 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/builder/api/compile.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
type Starter,
99
type LineAttribution as CtaLineAttribution,
1010
type AttributedFile as CtaAttributedFile,
11-
} from '@tanstack/cta-engine'
11+
} from '@tanstack/create'
1212

1313
type AddOnType = 'add-on' | 'example' | 'starter' | 'toolchain' | 'deployment'
1414
type AddOnPhase = 'setup' | 'add-on'

src/builder/api/config.ts

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,12 @@
1-
import { getFrameworkById } from '@tanstack/cta-engine'
2-
import { register as registerReact } from '@tanstack/cta-framework-react-cra'
3-
import { register as registerSolid } from '@tanstack/cta-framework-solid'
1+
import { getFrameworkById } from '@tanstack/create'
42
import type { FrameworkId } from '../frameworks'
53

64
export { type FrameworkId, FRAMEWORKS } from '../frameworks'
75

8-
let frameworksRegistered = false
9-
10-
export function ensureFrameworksRegistered() {
11-
if (!frameworksRegistered) {
12-
registerReact()
13-
registerSolid()
14-
frameworksRegistered = true
15-
}
16-
}
17-
186
export function getFramework(id: FrameworkId = 'react-cra') {
19-
ensureFrameworksRegistered()
207
const framework = getFrameworkById(id)
218
if (!framework) {
22-
throw new Error(`${id} framework not found after registration`)
9+
throw new Error(`${id} framework not found`)
2310
}
2411
return framework
2512
}

src/builder/api/features.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getAllAddOns, type AddOn, type AddOnOption } from '@tanstack/cta-engine'
1+
import { getAllAddOns, type AddOn, type AddOnOption } from '@tanstack/create'
22
import { getFramework, DEFAULT_MODE, DEFAULT_REQUIRED_ADDONS, type FrameworkId } from './config'
33
import { partners } from '~/utils/partners'
44

src/builder/api/remote.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { loadRemoteAddOn, loadStarter } from '@tanstack/cta-engine'
1+
import { loadRemoteAddOn, loadStarter } from '@tanstack/create'
22
import { type AddOnCompiled, type StarterCompiled } from './compile'
33
import { validateRemoteUrl } from '~/utils/url-validation.server'
44

src/builder/api/suggest.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getAllAddOns, type AddOn } from '@tanstack/cta-engine'
1+
import { getAllAddOns, type AddOn } from '@tanstack/create'
22
import type { ProjectDefinition } from './compile'
33
import { getFramework, DEFAULT_MODE } from './config'
44

src/builder/api/validate.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Uses cta-engine to validate project definitions.
55
*/
66

7-
import { getAllAddOns, type AddOn } from '@tanstack/cta-engine'
7+
import { getAllAddOns, type AddOn } from '@tanstack/create'
88
import type { ProjectDefinition } from './compile'
99
import { getFramework, DEFAULT_MODE } from './config'
1010

src/components/builder/ConfigPanel.tsx

Lines changed: 7 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import { useState, useCallback, useMemo } from 'react'
99
import { Link } from '@tanstack/react-router'
10-
import JSZip from 'jszip'
10+
1111
import {
1212
Copy,
1313
Download,
@@ -16,7 +16,6 @@ import {
1616
Rocket,
1717
Check,
1818
HelpCircle,
19-
Loader2,
2019
Search,
2120
Github,
2221
} from 'lucide-react'
@@ -430,7 +429,6 @@ function BuildProjectDropdown({
430429
const [showTemplateExport, setShowTemplateExport] = useState(false)
431430
const [templateName, setTemplateName] = useState('')
432431
const [templateDescription, setTemplateDescription] = useState('')
433-
const [isGeneratingZip, setIsGeneratingZip] = useState(false)
434432

435433
const copyToClipboard = async (text: string, type: string) => {
436434
await navigator.clipboard.writeText(text)
@@ -458,30 +456,9 @@ function BuildProjectDropdown({
458456
return `${window.location.origin}/api/builder/download?${params.toString()}`
459457
}, [projectName, features, tailwind, featureOptions])
460458

461-
const downloadZip = useCallback(async () => {
462-
if (!compiledOutput?.files) return
463-
464-
setIsGeneratingZip(true)
465-
try {
466-
const zip = new JSZip()
467-
const rootFolder = zip.folder(projectName)
468-
if (!rootFolder) return
469-
470-
for (const [filePath, content] of Object.entries(compiledOutput.files)) {
471-
rootFolder.file(filePath, content)
472-
}
473-
474-
const blob = await zip.generateAsync({ type: 'blob' })
475-
const url = URL.createObjectURL(blob)
476-
const a = document.createElement('a')
477-
a.href = url
478-
a.download = `${projectName}.zip`
479-
a.click()
480-
URL.revokeObjectURL(url)
481-
} finally {
482-
setIsGeneratingZip(false)
483-
}
484-
}, [compiledOutput?.files, projectName])
459+
const downloadZip = useCallback(() => {
460+
window.location.href = getDownloadUrl()
461+
}, [getDownloadUrl])
485462

486463
const generateTemplateJson = () => {
487464
const template = {
@@ -540,14 +517,10 @@ function BuildProjectDropdown({
540517
variant="primary"
541518
className="flex-1 flex items-center justify-center gap-2"
542519
onClick={downloadZip}
543-
disabled={!compiledOutput?.files || isGeneratingZip}
520+
disabled={!compiledOutput?.files}
544521
>
545-
{isGeneratingZip ? (
546-
<Loader2 className="w-4 h-4 animate-spin" />
547-
) : (
548-
<Download className="w-4 h-4" />
549-
)}
550-
{isGeneratingZip ? 'Generating...' : 'Download ZIP'}
522+
<Download className="w-4 h-4" />
523+
Download ZIP
551524
</Button>
552525
<Button
553526
variant="ghost"

src/routes/api/builder/download.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@ import { createFileRoute } from '@tanstack/react-router'
22
import JSZip from 'jszip'
33
import { compileHandler } from '~/builder/api'
44

5+
const BASE64_PREFIX = 'base64::'
6+
7+
function decodeBase64File(content: string): Buffer | null {
8+
if (content.startsWith(BASE64_PREFIX)) {
9+
return Buffer.from(content.slice(BASE64_PREFIX.length), 'base64')
10+
}
11+
return null
12+
}
13+
514
export const Route = createFileRoute('/api/builder/download')({
615
// @ts-expect-error server property not in route types yet
716
server: {
@@ -44,7 +53,13 @@ export const Route = createFileRoute('/api/builder/download')({
4453
}
4554

4655
for (const [filePath, content] of Object.entries(result.files)) {
47-
rootFolder.file(filePath, content)
56+
// Handle base64-encoded binary files (SVGs, images, etc.)
57+
const binaryContent = decodeBase64File(content)
58+
if (binaryContent) {
59+
rootFolder.file(filePath, binaryContent, { binary: true })
60+
} else {
61+
rootFolder.file(filePath, content)
62+
}
4863
}
4964

5065
const blob = await zip.generateAsync({ type: 'arraybuffer' })

0 commit comments

Comments
 (0)