Skip to content

Commit 59a1caa

Browse files
feat: custom packages selection / removal
1 parent 925da47 commit 59a1caa

3 files changed

Lines changed: 125 additions & 25 deletions

File tree

Lines changed: 110 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,120 @@
1-
import { Text } from 'ink'
1+
import { join } from 'node:path'
2+
import process from 'node:process'
3+
import { Box, Text } from 'ink'
4+
import { Script, Spawn } from 'ink-spawn'
25
import React, { type FC } from 'react'
6+
import { featurePackages } from '../../../constants/config.js'
37
import type { Item as CustomOptionsItem } from '../OptionalPackages.js'
48

59
interface Props {
6-
installationPackages?: Array<CustomOptionsItem>
10+
customOptions?: Array<CustomOptionsItem>
711
onCompletion: () => void
812
projectName: string
913
}
1014

11-
const CustomInstallation: FC<Props> = ({ projectName, onCompletion, installationPackages }) => (
12-
<Text>Custom Installation!</Text>
13-
)
15+
/**
16+
* Performs a custom installation based on the selected features: basically we tell `pnpm` what
17+
* features to remove (everything's included in package.json by default to simplify things)
18+
* @param projectName
19+
* @param onCompletion
20+
* @param customOptions
21+
*/
22+
const CustomInstallation: FC<Props> = ({ projectName, onCompletion, customOptions }) => {
23+
const projectDir = join(process.cwd(), projectName)
24+
25+
/**
26+
* Selected features won't be removed, unselected features will be.
27+
* @param feature
28+
* @param featuresList
29+
*/
30+
const featureSelected = (feature: string, featuresList: Array<CustomOptionsItem> | undefined) => {
31+
return !!featuresList?.find((item: CustomOptionsItem) => item.value === feature)
32+
}
33+
34+
/**
35+
* Returns the packages to remove checking first if the feature is selected or not.
36+
* Selected features are kept, unselected features are removed.
37+
* @param feature
38+
*/
39+
const getPackages = (feature: string) => {
40+
const packages = featurePackages[feature]
41+
42+
return featureSelected(feature, customOptions) ? [] : packages?.length ? packages : []
43+
}
44+
45+
const demoSupport = featureSelected('demo', customOptions)
46+
const subgraphSupport = featureSelected('subgraph', customOptions)
47+
const typedocSupport = featureSelected('typedoc', customOptions)
48+
const vocsSupport = featureSelected('vocs', customOptions)
49+
const huskySupport = featureSelected('husky', customOptions)
50+
51+
const packagesToRemove = [
52+
...getPackages('subgraph'),
53+
...getPackages('typedoc'),
54+
...getPackages('vocs'),
55+
...getPackages('husky'),
56+
]
57+
.join(' ')
58+
.trim()
59+
60+
return (
61+
<Box
62+
flexDirection={'column'}
63+
gap={0}
64+
>
65+
<Text color={'whiteBright'}>demo selected: {demoSupport ? 'true' : 'false'}</Text>
66+
<Text color={'whiteBright'}>subgraph selected: {subgraphSupport ? 'true' : 'false'}</Text>
67+
<Text color={'whiteBright'}>typedoc selected: {typedocSupport ? 'true' : 'false'}</Text>
68+
<Text color={'whiteBright'}>vocs selected: {vocsSupport ? 'true' : 'false'}</Text>
69+
<Text color={'whiteBright'}>husky selected: {huskySupport ? 'true' : 'false'}</Text>
70+
{!packagesToRemove ? (
71+
<Script>
72+
{/* If there are no packages to remove simply install everything... */}
73+
<Text color={'whiteBright'}>Installing packages</Text>
74+
<Spawn
75+
shell
76+
cwd={projectDir}
77+
silent
78+
command={'pnpm'}
79+
args={['i']}
80+
runningText={'Working...'}
81+
successText={'Done!'}
82+
failureText={'Error...'}
83+
onCompletion={onCompletion}
84+
/>
85+
</Script>
86+
) : (
87+
<Script>
88+
{/* `pnpm remove` will install the necessary packages while uninstalling the unwanted ones... */}
89+
<Text color={'whiteBright'}>Installing packages</Text>
90+
<Spawn
91+
shell
92+
cwd={projectDir}
93+
// silent
94+
command={'pnpm'}
95+
args={['remove', packagesToRemove]}
96+
// runningText={'Working...'}
97+
// successText={'Done!'}
98+
// failureText={'Error...'}
99+
// onCompletion={onCompletion}
100+
/>
101+
{/* ... but it won't run the post-install script, so we run the post-install scripts manually */}
102+
<Text color={'whiteBright'}>Executing post-install scripts</Text>
103+
<Spawn
104+
shell
105+
cwd={projectDir}
106+
silent
107+
command={'pnpm'}
108+
args={['run', 'postinstall']}
109+
runningText={'Working...'}
110+
successText={'Done!'}
111+
failureText={'Error...'}
112+
// onCompletion={onCompletion}
113+
/>
114+
</Script>
115+
)}
116+
</Box>
117+
)
118+
}
14119

15120
export default CustomInstallation

source/import/components/steps/Install/Install.tsx

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { join } from 'node:path'
22
import process from 'node:process'
33
import { Box, Text } from 'ink'
44
import { Script, Spawn } from 'ink-spawn'
5-
import React, { type FC, useState } from 'react'
5+
import React, { type FC } from 'react'
66
import Divider from '../../Divider.js'
77
import type { Installation } from '../InstallationType.js'
88
import type { Item as CustomOptionsItem } from '../OptionalPackages.js'
@@ -21,7 +21,6 @@ interface Props {
2121
const Install: FC<Props> = ({ projectName, onCompletion, installation }) => {
2222
const { installationType, customOptions } = installation
2323
const projectDir = join(process.cwd(), projectName)
24-
const [canInstall, setCanInstall] = useState(false)
2524

2625
return (
2726
<>
@@ -52,26 +51,21 @@ const Install: FC<Props> = ({ projectName, onCompletion, installation }) => {
5251
runningText={'Working...'}
5352
successText={'Done!'}
5453
failureText={'Error...'}
55-
onCompletion={() => setCanInstall(true)}
5654
/>
55+
{installationType === 'full' && (
56+
<FullInstallation
57+
projectName={projectName}
58+
onCompletion={onCompletion}
59+
/>
60+
)}
61+
{installationType === 'custom' && (
62+
<CustomInstallation
63+
customOptions={customOptions}
64+
projectName={projectName}
65+
onCompletion={onCompletion}
66+
/>
67+
)}
5768
</Script>
58-
{canInstall && (
59-
<>
60-
{installationType === 'full' && (
61-
<FullInstallation
62-
projectName={projectName}
63-
onCompletion={onCompletion}
64-
/>
65-
)}
66-
{installationType === 'custom' && (
67-
<CustomInstallation
68-
installationPackages={customOptions}
69-
projectName={projectName}
70-
onCompletion={onCompletion}
71-
/>
72-
)}
73-
</>
74-
)}
7569
</Box>
7670
</>
7771
)

source/import/components/steps/OptionalPackages.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ const OptionalPackages: FC<Props> = ({ onCompletion, onSubmit, installation }) =
6666
<>
6767
<Text color={'whiteBright'}>Choose optional packages</Text>
6868
<MultiSelect
69+
defaultSelected={customPackages}
6970
focus={isFocused}
7071
items={customPackages}
7172
onSubmit={onHandleSubmit}

0 commit comments

Comments
 (0)