Skip to content

Commit 67f485f

Browse files
committed
chore: adding special steps for specific add-ons
1 parent 2aa401c commit 67f485f

File tree

9 files changed

+150
-2
lines changed

9 files changed

+150
-2
lines changed

frameworks/react-cra/add-ons/start/info.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,6 @@
2626
"./index.html",
2727
"./src/main.tsx",
2828
"./src/App.css"
29-
]
29+
],
30+
"addOnSpecialSteps": ["rimraf-node-modules"]
3031
}

packages/cta-engine/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"memfs": "^4.17.0",
3737
"parse-gitignore": "^2.0.0",
3838
"prettier": "^3.5.0",
39+
"rimraf": "^6.0.1",
3940
"zod": "^3.24.2"
4041
},
4142
"devDependencies": {

packages/cta-engine/src/add-to-app.ts

+15
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
recursivelyGatherFilesFromEnvironment,
1717
} from './file-helpers.js'
1818
import { mergePackageJSON } from './package-json.js'
19+
import { runSpecialSteps } from './special-steps/index.js'
1920

2021
import type { Environment, Mode, Options } from './types.js'
2122
import type { PersistedOptions } from './config-file.js'
@@ -226,6 +227,20 @@ export async function addToApp(
226227
'Application files written',
227228
)
228229

230+
// Run any special steps for the new add-ons
231+
232+
const specialSteps = new Set<string>([])
233+
for (const addOn of newOptions.chosenAddOns) {
234+
for (const step of addOn.addOnSpecialSteps || []) {
235+
if (addOns.includes(addOn.id)) {
236+
specialSteps.add(step)
237+
}
238+
}
239+
}
240+
if (specialSteps.size) {
241+
await runSpecialSteps(environment, newOptions, Array.from(specialSteps))
242+
}
243+
229244
// Install dependencies
230245

231246
environment.startStep({

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

+12
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { createPackageJSON } from './package-json.js'
1111
import { createTemplateFile } from './template-file.js'
1212
import { installShadcnComponents } from './integrations/shadcn.js'
1313
import { setupGit } from './integrations/git.js'
14+
import { runSpecialSteps } from './special-steps/index.js'
1415

1516
import type { Environment, FileBundleHandler, Options } from './types.js'
1617

@@ -120,6 +121,17 @@ async function runCommandsAndInstallDependencies(
120121
s.stop(`Initialized git repository`)
121122
}
122123

124+
// Run any special steps for the new add-ons
125+
const specialSteps = new Set<string>([])
126+
for (const addOn of options.chosenAddOns) {
127+
for (const step of addOn.createSpecialSteps || []) {
128+
specialSteps.add(step)
129+
}
130+
}
131+
if (specialSteps.size) {
132+
await runSpecialSteps(environment, options, Array.from(specialSteps))
133+
}
134+
123135
// Install dependencies
124136
s.start(`Installing dependencies via ${options.packageManager}...`)
125137
environment.startStep({

packages/cta-engine/src/environment.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { existsSync, statSync } from 'node:fs'
1111
import { dirname } from 'node:path'
1212
import { execa } from 'execa'
1313
import { memfs } from 'memfs'
14+
import { rimraf } from 'rimraf'
1415

1516
import {
1617
cleanUpFileArray,
@@ -51,7 +52,7 @@ export function createDefaultEnvironment(): Environment {
5152
cwd,
5253
})
5354
return { stdout: result.stdout }
54-
} catch (e) {
55+
} catch {
5556
errors.push(
5657
`Command "${command} ${args.join(' ')}" did not run successfully. Please run this manually in your project.`,
5758
)
@@ -70,6 +71,9 @@ export function createDefaultEnvironment(): Environment {
7071
exists: (path: string) => existsSync(path),
7172
isDirectory: (path: string) => statSync(path).isDirectory(),
7273
readdir: async (path: string) => readdir(path),
74+
rimraf: async (path: string) => {
75+
await rimraf(path)
76+
},
7377

7478
appName: 'TanStack',
7579

@@ -175,6 +179,7 @@ export function createMemoryEnvironment(returnPathsRelativeTo: string = '') {
175179
environment.readdir = async (path: string) => {
176180
return Promise.resolve(fs.readdirSync(path).map((d) => d.toString()))
177181
}
182+
environment.rimraf = async () => {}
178183

179184
return {
180185
environment,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { rimrafNodeModules } from './rimraf-node-modules.js'
2+
3+
import type { Environment, Options } from '../types.js'
4+
5+
const specialStepsLookup: Record<
6+
string,
7+
(environment: Environment, options: Options) => Promise<void>
8+
> = {
9+
'rimraf-node-modules': rimrafNodeModules,
10+
}
11+
12+
export async function runSpecialSteps(
13+
environment: Environment,
14+
options: Options,
15+
specialSteps: Array<string>,
16+
) {
17+
if (specialSteps.length) {
18+
environment.startStep({
19+
id: 'special-steps',
20+
type: 'command',
21+
message: 'Removing node_modules...',
22+
})
23+
24+
for (const step of specialSteps) {
25+
const stepFunction = specialStepsLookup[step]
26+
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
27+
if (stepFunction) {
28+
await stepFunction(environment, options)
29+
} else {
30+
environment.error(`Special step ${step} not found`)
31+
}
32+
}
33+
34+
environment.finishStep('special-steps', 'Special steps complete')
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { resolve } from 'node:path'
2+
3+
import type { Environment, Options } from '../types.js'
4+
5+
const lockFiles = ['package-lock.json', 'yarn.lock', 'pnpm-lock.yaml']
6+
7+
export async function rimrafNodeModules(
8+
environment: Environment,
9+
options: Options,
10+
) {
11+
environment.startStep({
12+
id: 'special-steps',
13+
type: 'command',
14+
message: 'Removing node_modules...',
15+
})
16+
17+
await environment.rimraf(resolve(options.targetDir, 'node_modules'))
18+
19+
for (const lockFile of lockFiles) {
20+
const lockFilePath = resolve(options.targetDir, lockFile)
21+
if (environment.exists(lockFilePath)) {
22+
await environment.deleteFile(lockFilePath)
23+
}
24+
}
25+
}

packages/cta-engine/src/types.ts

+3
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ export const AddOnBaseSchema = z.object({
4949
dependsOn: z.array(z.string()).optional(),
5050
smallLogo: z.string().optional(),
5151
logo: z.string().optional(),
52+
addOnSpecialSteps: z.array(z.string()).optional(),
53+
createSpecialSteps: z.array(z.string()).optional(),
5254
})
5355

5456
export const StarterSchema = AddOnBaseSchema.extend({
@@ -171,6 +173,7 @@ type FileEnvironment = {
171173
isDirectory: (path: string) => boolean
172174
readFile: (path: string) => Promise<string>
173175
readdir: (path: string) => Promise<Array<string>>
176+
rimraf: (path: string) => Promise<void>
174177
}
175178

176179
export type StatusEvent = {

pnpm-lock.yaml

+50
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)