Skip to content

Commit 3e1987c

Browse files
committed
Refactoring and a whole lot more functionality
1 parent a7080af commit 3e1987c

File tree

12 files changed

+602
-127
lines changed

12 files changed

+602
-127
lines changed

cli/add-on-developer/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,12 @@
1616
"@codemirror/lang-javascript": "^6.2.3",
1717
"@codemirror/lang-json": "^6.0.1",
1818
"@radix-ui/react-accordion": "^1.2.3",
19+
"@radix-ui/react-checkbox": "^1.1.4",
1920
"@radix-ui/react-dialog": "^1.1.6",
2021
"@radix-ui/react-slot": "^1.1.2",
2122
"@radix-ui/react-tabs": "^1.1.3",
23+
"@radix-ui/react-toggle": "^1.1.2",
24+
"@radix-ui/react-toggle-group": "^1.1.2",
2225
"@tailwindcss/vite": "^4.0.6",
2326
"@tanstack/cta-engine": "workspace:*",
2427
"@tanstack/react-query": "^5.66.5",
@@ -35,6 +38,7 @@
3538
"execa": "^9.5.2",
3639
"lucide-react": "^0.476.0",
3740
"react": "^19.0.0",
41+
"react-codemirror-merge": "^4.23.10",
3842
"react-dom": "^19.0.0",
3943
"tailwind-merge": "^3.0.2",
4044
"tailwindcss": "^4.0.6",
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import CodeMirror from '@uiw/react-codemirror'
2+
import CodeMirrorMerge from 'react-codemirror-merge'
3+
4+
import { javascript } from '@codemirror/lang-javascript'
5+
import { json } from '@codemirror/lang-json'
6+
import { css } from '@codemirror/lang-css'
7+
import { html } from '@codemirror/lang-html'
8+
9+
import { okaidia } from '@uiw/codemirror-theme-okaidia'
10+
11+
export default function FileViewer({
12+
originalFile,
13+
modifiedFile,
14+
filePath,
15+
}: {
16+
originalFile: string
17+
modifiedFile: string
18+
filePath: string
19+
}) {
20+
function getLanguage(file: string) {
21+
if (file.endsWith('.js') || file.endsWith('.jsx')) {
22+
return javascript({ jsx: true })
23+
}
24+
if (file.endsWith('.ts') || file.endsWith('.tsx')) {
25+
return javascript({ typescript: true, jsx: true })
26+
}
27+
if (file.endsWith('.json')) {
28+
return json()
29+
}
30+
if (file.endsWith('.css')) {
31+
return css()
32+
}
33+
if (file.endsWith('.html')) {
34+
return html()
35+
}
36+
return javascript()
37+
}
38+
const language = getLanguage(filePath)
39+
40+
if (!originalFile) {
41+
return (
42+
<CodeMirror
43+
value={modifiedFile}
44+
theme={okaidia}
45+
height="100vh"
46+
width="100%"
47+
readOnly
48+
extensions={[language]}
49+
className="text-lg"
50+
/>
51+
)
52+
}
53+
return (
54+
<CodeMirrorMerge
55+
orientation="b-a"
56+
theme={okaidia}
57+
height="100vh"
58+
width="100%"
59+
readOnly
60+
className="text-lg"
61+
>
62+
<CodeMirrorMerge.Original value={originalFile} extensions={[language]} />
63+
<CodeMirrorMerge.Modified value={modifiedFile} extensions={[language]} />
64+
</CodeMirrorMerge>
65+
)
66+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import * as React from "react"
2+
import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
3+
import { CheckIcon } from "lucide-react"
4+
5+
import { cn } from "@/lib/utils"
6+
7+
function Checkbox({
8+
className,
9+
...props
10+
}: React.ComponentProps<typeof CheckboxPrimitive.Root>) {
11+
return (
12+
<CheckboxPrimitive.Root
13+
data-slot="checkbox"
14+
className={cn(
15+
"peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
16+
className
17+
)}
18+
{...props}
19+
>
20+
<CheckboxPrimitive.Indicator
21+
data-slot="checkbox-indicator"
22+
className="flex items-center justify-center text-current transition-none"
23+
>
24+
<CheckIcon className="size-3.5" />
25+
</CheckboxPrimitive.Indicator>
26+
</CheckboxPrimitive.Root>
27+
)
28+
}
29+
30+
export { Checkbox }
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import * as React from "react"
2+
import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group"
3+
import { type VariantProps } from "class-variance-authority"
4+
5+
import { cn } from "@/lib/utils"
6+
import { toggleVariants } from "@/components/ui/toggle"
7+
8+
const ToggleGroupContext = React.createContext<
9+
VariantProps<typeof toggleVariants>
10+
>({
11+
size: "default",
12+
variant: "default",
13+
})
14+
15+
function ToggleGroup({
16+
className,
17+
variant,
18+
size,
19+
children,
20+
...props
21+
}: React.ComponentProps<typeof ToggleGroupPrimitive.Root> &
22+
VariantProps<typeof toggleVariants>) {
23+
return (
24+
<ToggleGroupPrimitive.Root
25+
data-slot="toggle-group"
26+
data-variant={variant}
27+
data-size={size}
28+
className={cn(
29+
"group/toggle-group flex w-fit items-center rounded-md data-[variant=outline]:shadow-xs",
30+
className
31+
)}
32+
{...props}
33+
>
34+
<ToggleGroupContext.Provider value={{ variant, size }}>
35+
{children}
36+
</ToggleGroupContext.Provider>
37+
</ToggleGroupPrimitive.Root>
38+
)
39+
}
40+
41+
function ToggleGroupItem({
42+
className,
43+
children,
44+
variant,
45+
size,
46+
...props
47+
}: React.ComponentProps<typeof ToggleGroupPrimitive.Item> &
48+
VariantProps<typeof toggleVariants>) {
49+
const context = React.useContext(ToggleGroupContext)
50+
51+
return (
52+
<ToggleGroupPrimitive.Item
53+
data-slot="toggle-group-item"
54+
data-variant={context.variant || variant}
55+
data-size={context.size || size}
56+
className={cn(
57+
toggleVariants({
58+
variant: context.variant || variant,
59+
size: context.size || size,
60+
}),
61+
"min-w-0 flex-1 shrink-0 rounded-none shadow-none first:rounded-l-md last:rounded-r-md focus:z-10 focus-visible:z-10 data-[variant=outline]:border-l-0 data-[variant=outline]:first:border-l",
62+
className
63+
)}
64+
{...props}
65+
>
66+
{children}
67+
</ToggleGroupPrimitive.Item>
68+
)
69+
}
70+
71+
export { ToggleGroup, ToggleGroupItem }
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
"use client"
2+
3+
import * as React from "react"
4+
import * as TogglePrimitive from "@radix-ui/react-toggle"
5+
import { cva, type VariantProps } from "class-variance-authority"
6+
7+
import { cn } from "@/lib/utils"
8+
9+
const toggleVariants = cva(
10+
"inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium hover:bg-muted hover:text-muted-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] outline-none transition-[color,box-shadow] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive whitespace-nowrap",
11+
{
12+
variants: {
13+
variant: {
14+
default: "bg-transparent",
15+
outline:
16+
"border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground",
17+
},
18+
size: {
19+
default: "h-9 px-2 min-w-9",
20+
sm: "h-8 px-1.5 min-w-8",
21+
lg: "h-10 px-2.5 min-w-10",
22+
},
23+
},
24+
defaultVariants: {
25+
variant: "default",
26+
size: "default",
27+
},
28+
}
29+
)
30+
31+
function Toggle({
32+
className,
33+
variant,
34+
size,
35+
...props
36+
}: React.ComponentProps<typeof TogglePrimitive.Root> &
37+
VariantProps<typeof toggleVariants>) {
38+
return (
39+
<TogglePrimitive.Root
40+
data-slot="toggle"
41+
className={cn(toggleVariants({ variant, size, className }))}
42+
{...props}
43+
/>
44+
)
45+
}
46+
47+
export { Toggle, toggleVariants }
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import { createServerFn } from '@tanstack/react-start'
2+
import { readFileSync } from 'node:fs'
3+
import { basename, resolve } from 'node:path'
4+
5+
import {
6+
getAllAddOns,
7+
createApp,
8+
createMemoryEnvironment,
9+
createAppOptionsFromPersisted,
10+
} from '@tanstack/cta-engine'
11+
12+
import type {
13+
AddOn,
14+
PersistedOptions,
15+
Framework,
16+
Mode,
17+
} from '@tanstack/cta-engine'
18+
19+
export const getAddons = createServerFn({
20+
method: 'GET',
21+
})
22+
.validator((data: unknown) => {
23+
return data as { platform: Framework; mode: Mode }
24+
})
25+
.handler(({ data: { platform, mode } }) => {
26+
return getAllAddOns(platform, mode)
27+
})
28+
29+
export const getAddonInfo = createServerFn({
30+
method: 'GET',
31+
}).handler(async () => {
32+
const addOnInfo = readFileSync(
33+
resolve(process.env.PROJECT_PATH, 'add-on.json'),
34+
)
35+
return JSON.parse(addOnInfo.toString())
36+
})
37+
38+
export const getOriginalOptions = createServerFn({
39+
method: 'GET',
40+
}).handler(async () => {
41+
const addOnInfo = readFileSync(resolve(process.env.PROJECT_PATH, '.cta.json'))
42+
return JSON.parse(addOnInfo.toString()) as PersistedOptions
43+
})
44+
45+
export const runCreateApp = createServerFn({
46+
method: 'POST',
47+
})
48+
.validator((data: unknown) => {
49+
return data as { withAddOn: boolean; options: PersistedOptions }
50+
})
51+
.handler(
52+
async ({
53+
data: { withAddOn, options: persistedOptions },
54+
}: {
55+
data: { withAddOn: boolean; options: PersistedOptions }
56+
}) => {
57+
const { output, environment } = createMemoryEnvironment()
58+
const options = await createAppOptionsFromPersisted(persistedOptions)
59+
options.chosenAddOns = withAddOn
60+
? [...options.chosenAddOns, (await getAddonInfo()) as AddOn]
61+
: [...options.chosenAddOns]
62+
await createApp(
63+
{
64+
...options,
65+
},
66+
{
67+
silent: true,
68+
environment,
69+
cwd: process.env.PROJECT_PATH,
70+
},
71+
)
72+
73+
output.files = Object.keys(output.files).reduce<Record<string, string>>(
74+
(acc, file) => {
75+
if (basename(file) !== '.cta.json') {
76+
acc[file] = output.files[file]
77+
}
78+
return acc
79+
},
80+
{},
81+
)
82+
83+
return output
84+
},
85+
)

0 commit comments

Comments
 (0)