Skip to content

Commit e1dd57b

Browse files
committed
chore: file deleting support
1 parent 95d25d5 commit e1dd57b

File tree

6 files changed

+20
-4
lines changed

6 files changed

+20
-4
lines changed

examples/resume-example/starter.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,10 @@
5151
"./src/routes/index.tsx": "import { createFileRoute } from \"@tanstack/react-router\";\nimport { allJobs, allEducations } from \"content-collections\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"@/components/ui/card\";\nimport { Checkbox } from \"@/components/ui/checkbox\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Separator } from \"@/components/ui/separator\";\nimport {\n HoverCard,\n HoverCardContent,\n HoverCardTrigger,\n} from \"@/components/ui/hover-card\";\nimport { useState, useMemo } from \"react\";\nimport { marked } from \"marked\";\n\nexport const Route = createFileRoute(\"/\")({\n component: App,\n});\n\nfunction App() {\n const [selectedTags, setSelectedTags] = useState<string[]>([]);\n\n // Get unique tags from all jobs\n const allTags = useMemo(() => {\n const tags = new Set<string>();\n allJobs.forEach((job) => {\n job.tags.forEach((tag) => tags.add(tag));\n });\n return Array.from(tags).sort();\n }, []);\n\n // Filter jobs based on selected tags\n const filteredJobs = useMemo(() => {\n if (selectedTags.length === 0) return allJobs;\n return allJobs.filter((job) =>\n selectedTags.some((tag) => job.tags.includes(tag))\n );\n }, [selectedTags]);\n\n return (\n <div className=\"min-h-screen bg-gradient-to-b from-gray-50 to-gray-100\">\n <div className=\"flex\">\n {/* Sidebar with filters */}\n <div className=\"w-72 min-h-screen bg-white border-r shadow-sm p-8 sticky top-0\">\n <h3 className=\"text-lg font-semibold mb-6 text-gray-900\">\n Skills & Technologies\n </h3>\n <div className=\"space-y-4\">\n {allTags.map((tag) => (\n <div key={tag} className=\"flex items-center space-x-3 group\">\n <Checkbox\n id={tag}\n checked={selectedTags.includes(tag)}\n onCheckedChange={(checked) => {\n if (checked) {\n setSelectedTags([...selectedTags, tag]);\n } else {\n setSelectedTags(selectedTags.filter((t) => t !== tag));\n }\n }}\n className=\"data-[state=checked]:bg-blue-600\"\n />\n <label\n htmlFor={tag}\n className=\"text-sm font-medium leading-none text-gray-700 group-hover:text-gray-900 transition-colors cursor-pointer\"\n >\n {tag}\n </label>\n </div>\n ))}\n </div>\n </div>\n\n {/* Main content */}\n <div className=\"flex-1 p-8 lg:p-12\">\n <div className=\"max-w-4xl mx-auto space-y-12\">\n <div className=\"text-center space-y-4\">\n <h1 className=\"text-5xl font-bold bg-gradient-to-r from-gray-900 via-gray-800 to-gray-900 bg-clip-text text-transparent\">\n My Resume\n </h1>\n <p className=\"text-gray-600 text-lg\">\n Professional Experience & Education\n </p>\n <Separator className=\"mt-8\" />\n </div>\n\n {/* Career Summary */}\n <Card className=\"border-0 shadow-lg bg-white/50 backdrop-blur-sm\">\n <CardHeader>\n <CardTitle className=\"text-2xl text-gray-900\">\n Career Summary\n </CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"flex items-center gap-8\">\n <p className=\"text-gray-700 flex-1 leading-relaxed\">\n I am a passionate and driven professional seeking\n opportunities that will leverage my extensive experience in\n frontend development while providing continuous growth and\n learning opportunities. My goal is to contribute to\n innovative projects that challenge me to expand my skill set\n and make meaningful impacts through technology.\n </p>\n <img\n src=\"/headshot-on-white.jpg\"\n alt=\"Professional headshot\"\n className=\"w-44 h-52 rounded-2xl object-cover shadow-md transition-transform hover:scale-105\"\n />\n </div>\n </CardContent>\n </Card>\n\n {/* Work Experience */}\n <section className=\"space-y-6\">\n <h2 className=\"text-3xl font-semibold text-gray-900\">\n Work Experience\n </h2>\n <div className=\"space-y-6\">\n {filteredJobs.map((job) => (\n <Card\n key={job.jobTitle}\n className=\"border-0 shadow-md hover:shadow-lg transition-shadow\"\n >\n <CardHeader>\n <div className=\"flex justify-between items-start\">\n <div className=\"space-y-2\">\n <CardTitle className=\"text-xl text-gray-900\">\n {job.jobTitle}\n </CardTitle>\n <p className=\"text-blue-600 font-medium\">\n {job.company} - {job.location}\n </p>\n </div>\n <Badge variant=\"secondary\" className=\"text-sm\">\n {job.startDate} - {job.endDate || \"Present\"}\n </Badge>\n </div>\n </CardHeader>\n <CardContent>\n <p className=\"text-gray-700 mb-6 leading-relaxed\">\n {job.summary}\n </p>\n <div className=\"flex flex-wrap gap-2\">\n {job.tags.map((tag) => (\n <HoverCard key={tag}>\n <HoverCardTrigger>\n <Badge\n variant=\"outline\"\n className=\"hover:bg-gray-100 transition-colors cursor-pointer\"\n >\n {tag}\n </Badge>\n </HoverCardTrigger>\n <HoverCardContent className=\"w-64\">\n <p className=\"text-sm text-gray-600\">\n Experience with {tag} in professional\n development\n </p>\n </HoverCardContent>\n </HoverCard>\n ))}\n </div>\n {job.content && (\n <div\n className=\"mt-6 text-gray-700 prose prose-sm max-w-none\"\n dangerouslySetInnerHTML={{\n __html: marked(job.content),\n }}\n />\n )}\n </CardContent>\n </Card>\n ))}\n </div>\n </section>\n\n {/* Education */}\n <section className=\"space-y-6\">\n <h2 className=\"text-3xl font-semibold text-gray-900\">\n Education\n </h2>\n <div className=\"space-y-6\">\n {allEducations.map((education) => (\n <Card\n key={education.school}\n className=\"border-0 shadow-md hover:shadow-lg transition-shadow\"\n >\n <CardHeader>\n <CardTitle className=\"text-xl text-gray-900\">\n {education.school}\n </CardTitle>\n </CardHeader>\n <CardContent>\n <p className=\"text-gray-700 leading-relaxed\">\n {education.summary}\n </p>\n {education.content && (\n <div\n className=\"mt-6 text-gray-700 prose prose-sm max-w-none\"\n dangerouslySetInnerHTML={{\n __html: marked(education.content),\n }}\n />\n )}\n </CardContent>\n </Card>\n ))}\n </div>\n </section>\n </div>\n </div>\n </div>\n </div>\n );\n}\n",
5252
"./tsconfig.json": "{\n \"include\": [\"**/*.ts\", \"**/*.tsx\"],\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"jsx\": \"react-jsx\",\n \"module\": \"ESNext\",\n \"lib\": [\"ES2022\", \"DOM\", \"DOM.Iterable\"],\n \"types\": [\"vite/client\"],\n\n /* Bundler mode */\n \"moduleResolution\": \"bundler\",\n \"allowImportingTsExtensions\": true,\n \"verbatimModuleSyntax\": true,\n \"noEmit\": true,\n\n /* Linting */\n \"skipLibCheck\": true,\n \"strict\": true,\n \"noUnusedLocals\": true,\n \"noUnusedParameters\": true,\n \"noFallthroughCasesInSwitch\": true,\n \"noUncheckedSideEffectImports\": true,\n \"baseUrl\": \".\",\n \"paths\": {\n \"content-collections\": [\"./.content-collections/generated\"],\n \"@/*\": [\"./src/*\"]\n }\n }\n}\n"
5353
},
54-
"deletedFiles": []
54+
"deletedFiles": [
55+
"./src/components/Header.tsx",
56+
"./src/routes/api.demo-names.ts",
57+
"./src/routes/demo.start.api-request.tsx",
58+
"./src/routes/demo.start.server-funcs.tsx"
59+
]
5560
}

packages/cta-engine/src/add-ons.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,6 @@ export async function loadRemoteAddOn(url: string): Promise<AddOn> {
5454
...fileContent,
5555
getFiles: () => Promise.resolve(Object.keys(fileContent.files)),
5656
getFileContents: (path: string) => Promise.resolve(fileContent.files[path]),
57+
getDeletedFiles: () => Promise.resolve(fileContent.deletedFiles),
5758
}
5859
}

packages/cta-engine/src/create-app.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ async function writeFiles(environment: Environment, options: Options) {
3131
await templateFileFromContent(file, contents)
3232
}
3333
}
34+
35+
const deletedFiles = await bundle.getDeletedFiles()
36+
for (const file of deletedFiles) {
37+
await environment.deleteFile(resolve(options.targetDir, file))
38+
}
3439
}
3540

3641
await writeFileBundle(options.framework)

packages/cta-engine/src/custom-add-ons/starter.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,9 @@ export async function compileStarter(environment: Environment) {
8181
await compareFiles('.', ignore, output.files, changedFiles)
8282

8383
const deletedFiles: Array<string> = []
84-
for (const file of Object.keys(files)) {
85-
if (!existsSync(file)) {
86-
deletedFiles.push(file.replace(process.cwd(), '.'))
84+
for (const file of Object.keys(output.files)) {
85+
if (!existsSync(resolve(process.cwd(), file))) {
86+
deletedFiles.push(file)
8787
}
8888
}
8989

packages/cta-engine/src/frameworks.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ function getAddOns(framework: FrameworkDefinition) {
6060
deletedFiles: [],
6161
getFiles,
6262
getFileContents,
63+
getDeletedFiles: () => Promise.resolve([]),
6364
})
6465
}
6566
}
@@ -101,6 +102,9 @@ export function registerFramework(framework: FrameworkDefinition) {
101102
getFileContents: (path: string) => {
102103
return Promise.resolve(readFileHelper(resolve(baseAssetsDirectory, path)))
103104
},
105+
getDeletedFiles: () => {
106+
return Promise.resolve([])
107+
},
104108
basePackageJSON,
105109
optionalPackages,
106110
getAddOns: () => addOns,

packages/cta-engine/src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export type Mode = typeof CODE_ROUTER | typeof FILE_ROUTER
66
export type FileBundleHandler = {
77
getFiles: () => Promise<Array<string>>
88
getFileContents: (path: string) => Promise<string>
9+
getDeletedFiles: () => Promise<Array<string>>
910
}
1011

1112
export type Integration = {

0 commit comments

Comments
 (0)