dappbooster 2.0.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.d.ts +3 -0
- package/dist/app.js +49 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +6 -0
- package/dist/import/components/Ask.d.ts +11 -0
- package/dist/import/components/Ask.js +18 -0
- package/dist/import/components/Divider.d.ts +5 -0
- package/dist/import/components/Divider.js +4 -0
- package/dist/import/components/MainTitle.d.ts +3 -0
- package/dist/import/components/MainTitle.js +6 -0
- package/dist/import/components/Multiselect/MultiSelect.d.ts +33 -0
- package/dist/import/components/Multiselect/MultiSelect.js +68 -0
- package/dist/import/components/Multiselect/components/Checkbox.d.ts +6 -0
- package/dist/import/components/Multiselect/components/Checkbox.js +6 -0
- package/dist/import/components/Multiselect/components/Indicator.d.ts +6 -0
- package/dist/import/components/Multiselect/components/Indicator.js +6 -0
- package/dist/import/components/Multiselect/components/Item.d.ts +7 -0
- package/dist/import/components/Multiselect/components/Item.js +4 -0
- package/dist/import/components/Multiselect/index.d.ts +1 -0
- package/dist/import/components/Multiselect/index.js +1 -0
- package/dist/import/components/steps/CloneRepo/CloneRepo.d.ts +13 -0
- package/dist/import/components/steps/CloneRepo/CloneRepo.js +13 -0
- package/dist/import/components/steps/CloneRepo/Commands.d.ts +12 -0
- package/dist/import/components/steps/CloneRepo/Commands.js +29 -0
- package/dist/import/components/steps/FileCleanup.d.ts +18 -0
- package/dist/import/components/steps/FileCleanup.js +72 -0
- package/dist/import/components/steps/Install/CustomInstallation.d.ts +16 -0
- package/dist/import/components/steps/Install/CustomInstallation.js +31 -0
- package/dist/import/components/steps/Install/FullInstallation.d.ts +7 -0
- package/dist/import/components/steps/Install/FullInstallation.js +10 -0
- package/dist/import/components/steps/Install/Install.d.ts +12 -0
- package/dist/import/components/steps/Install/Install.js +29 -0
- package/dist/import/components/steps/Install/InstallAllPackages.d.ts +7 -0
- package/dist/import/components/steps/Install/InstallAllPackages.js +9 -0
- package/dist/import/components/steps/InstallationMode.d.ts +8 -0
- package/dist/import/components/steps/InstallationMode.js +28 -0
- package/dist/import/components/steps/OptionalPackages.d.ts +15 -0
- package/dist/import/components/steps/OptionalPackages.js +51 -0
- package/dist/import/components/steps/PostInstall.d.ts +16 -0
- package/dist/import/components/steps/PostInstall.js +79 -0
- package/dist/import/components/steps/ProjectName.d.ts +14 -0
- package/dist/import/components/steps/ProjectName.js +25 -0
- package/dist/import/constants/config.d.ts +4 -0
- package/dist/import/constants/config.js +18 -0
- package/dist/import/types/types.d.ts +10 -0
- package/dist/import/types/types.js +1 -0
- package/dist/import/utils/utils.d.ts +32 -0
- package/dist/import/utils/utils.js +47 -0
- package/package.json +30 -19
- package/readme.md +39 -0
- package/.nvmrc +0 -1
- package/.prettierrc +0 -7
- package/LICENSE +0 -21
- package/README.md +0 -36
- package/import/config.js +0 -17
- package/import/git.js +0 -56
- package/import/install.js +0 -199
- package/import/user-prompts.js +0 -145
- package/index.js +0 -33
package/dist/app.d.ts
ADDED
package/dist/app.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Box } from 'ink';
|
|
2
|
+
import React, { useState, useMemo, useCallback } from 'react';
|
|
3
|
+
import MainTitle from './import/components/MainTitle.js';
|
|
4
|
+
import CloneRepo from './import/components/steps/CloneRepo/CloneRepo.js';
|
|
5
|
+
import FileCleanup from './import/components/steps/FileCleanup.js';
|
|
6
|
+
import Install from './import/components/steps/Install/Install.js';
|
|
7
|
+
import InstallationMode from './import/components/steps/InstallationMode.js';
|
|
8
|
+
import OptionalPackages from './import/components/steps/OptionalPackages.js';
|
|
9
|
+
import PostInstall from './import/components/steps/PostInstall.js';
|
|
10
|
+
import ProjectName from './import/components/steps/ProjectName.js';
|
|
11
|
+
import { canShowStep } from './import/utils/utils.js';
|
|
12
|
+
const App = () => {
|
|
13
|
+
const [projectName, setProjectName] = useState('');
|
|
14
|
+
const [currentStep, setCurrentStep] = useState(1);
|
|
15
|
+
const [setupType, setSetupType] = useState();
|
|
16
|
+
const [selectedFeatures, setSelectedFeatures] = useState();
|
|
17
|
+
const finishStep = useCallback(() => setCurrentStep(currentStep + 1), [currentStep]);
|
|
18
|
+
const onSelectSetupType = useCallback((item) => setSetupType(item), []);
|
|
19
|
+
const onSelectSelectedFeatures = useCallback((selectedItems) => setSelectedFeatures([...selectedItems]), []);
|
|
20
|
+
const steps = useMemo(() => [
|
|
21
|
+
React.createElement(ProjectName, { onCompletion: finishStep, onSubmit: setProjectName, projectName: projectName, key: 1 }),
|
|
22
|
+
React.createElement(CloneRepo, { onCompletion: finishStep, projectName: projectName, key: 2 }),
|
|
23
|
+
React.createElement(InstallationMode, { onCompletion: finishStep, onSelect: onSelectSetupType, key: 3 }),
|
|
24
|
+
React.createElement(OptionalPackages, { installation: setupType?.value, onCompletion: finishStep, onSubmit: onSelectSelectedFeatures, key: 4 }),
|
|
25
|
+
React.createElement(Install, { installationConfig: {
|
|
26
|
+
installationType: setupType?.value,
|
|
27
|
+
selectedFeatures: selectedFeatures,
|
|
28
|
+
}, onCompletion: finishStep, projectName: projectName, key: 5 }),
|
|
29
|
+
React.createElement(FileCleanup, { installationConfig: {
|
|
30
|
+
installationType: setupType?.value,
|
|
31
|
+
selectedFeatures: selectedFeatures,
|
|
32
|
+
}, onCompletion: finishStep, projectName: projectName, key: 6 }),
|
|
33
|
+
React.createElement(PostInstall, { projectName: projectName, installationConfig: {
|
|
34
|
+
installationType: setupType?.value,
|
|
35
|
+
selectedFeatures: selectedFeatures,
|
|
36
|
+
}, key: 7 }),
|
|
37
|
+
], [
|
|
38
|
+
finishStep,
|
|
39
|
+
onSelectSelectedFeatures,
|
|
40
|
+
setupType?.value,
|
|
41
|
+
selectedFeatures,
|
|
42
|
+
onSelectSetupType,
|
|
43
|
+
projectName,
|
|
44
|
+
]);
|
|
45
|
+
return (React.createElement(Box, { flexDirection: 'column', rowGap: 1, width: 80 },
|
|
46
|
+
React.createElement(MainTitle, null),
|
|
47
|
+
steps.map((item, index) => canShowStep(currentStep, index + 1) && item)));
|
|
48
|
+
};
|
|
49
|
+
export default App;
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Box, Text } from 'ink';
|
|
2
|
+
import TextInput from 'ink-text-input';
|
|
3
|
+
import React, { useMemo, useState } from 'react';
|
|
4
|
+
import { isAnswerConfirmed } from '../utils/utils.js';
|
|
5
|
+
const Ask = ({ question, onSubmit, answer, tip, errorMessage, placeholder }) => {
|
|
6
|
+
const [input, setInput] = useState('');
|
|
7
|
+
const answered = useMemo(() => isAnswerConfirmed(answer, errorMessage), [answer, errorMessage]);
|
|
8
|
+
return (React.createElement(Box, { flexDirection: 'column', rowGap: 1 },
|
|
9
|
+
React.createElement(Box, { flexDirection: 'column' },
|
|
10
|
+
React.createElement(Box, null,
|
|
11
|
+
React.createElement(Text, { color: 'whiteBright' },
|
|
12
|
+
question,
|
|
13
|
+
": "),
|
|
14
|
+
answered ? (React.createElement(Text, { bold: true, color: 'green' }, answer)) : (React.createElement(TextInput, { onChange: setInput, onSubmit: onSubmit, placeholder: placeholder, value: input }))),
|
|
15
|
+
tip && React.createElement(Text, { color: 'gray' }, tip)),
|
|
16
|
+
errorMessage && (React.createElement(Text, { bold: true, color: 'red' }, errorMessage))));
|
|
17
|
+
};
|
|
18
|
+
export default Ask;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import BigText from 'ink-big-text';
|
|
2
|
+
import Gradient from 'ink-gradient';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
const MainTitle = () => (React.createElement(Gradient, { colors: ['#ff438c', '#bb1d79', '#8b46a4', '#6a2581'] },
|
|
5
|
+
React.createElement(BigText, { lineHeight: 1, font: 'chrome', text: "dAppBooster" })));
|
|
6
|
+
export default MainTitle;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import CheckBox from './components/Checkbox.js';
|
|
3
|
+
import Indicator from './components/Indicator.js';
|
|
4
|
+
import ItemComponent from './components/Item.js';
|
|
5
|
+
type Item<T> = {
|
|
6
|
+
label: string;
|
|
7
|
+
value: T;
|
|
8
|
+
key?: string | number;
|
|
9
|
+
};
|
|
10
|
+
type MultiSelectProps<T> = {
|
|
11
|
+
items: Item<T>[];
|
|
12
|
+
defaultSelected?: Item<T>[];
|
|
13
|
+
focus?: boolean;
|
|
14
|
+
initialIndex?: number;
|
|
15
|
+
indicatorComponent?: React.FC<{
|
|
16
|
+
isHighlighted: boolean;
|
|
17
|
+
}>;
|
|
18
|
+
checkboxComponent?: React.FC<{
|
|
19
|
+
isSelected: boolean;
|
|
20
|
+
}>;
|
|
21
|
+
itemComponent?: React.FC<{
|
|
22
|
+
isHighlighted: boolean;
|
|
23
|
+
label: string;
|
|
24
|
+
}>;
|
|
25
|
+
limit?: number | null;
|
|
26
|
+
onSelect?: (selectedItem: Item<T>) => void;
|
|
27
|
+
onUnselect?: (unselectedItem: Item<T>) => void;
|
|
28
|
+
onSubmit?: (selectedItems: Item<T>[]) => void;
|
|
29
|
+
onHighlight?: (highlightedItem: Item<T>) => void;
|
|
30
|
+
};
|
|
31
|
+
declare const MultiSelect: <T>({ items, defaultSelected, focus, initialIndex, indicatorComponent, checkboxComponent, itemComponent, limit, onSelect, onUnselect, onSubmit, onHighlight, }: MultiSelectProps<T>) => React.JSX.Element;
|
|
32
|
+
export default MultiSelect;
|
|
33
|
+
export { Indicator, ItemComponent, CheckBox, type Item };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Box, useInput } from 'ink';
|
|
2
|
+
import React, { useCallback, useState } from 'react';
|
|
3
|
+
import CheckBox from './components/Checkbox.js';
|
|
4
|
+
import Indicator from './components/Indicator.js';
|
|
5
|
+
import ItemComponent from './components/Item.js';
|
|
6
|
+
const MultiSelect = ({ items = [], defaultSelected = [], focus = true, initialIndex = 0, indicatorComponent = Indicator, checkboxComponent = CheckBox, itemComponent = ItemComponent, limit = null, onSelect = () => { }, onUnselect = () => { }, onSubmit = () => { }, onHighlight = () => { }, }) => {
|
|
7
|
+
const [highlightedIndex, setHighlightedIndex] = useState(initialIndex);
|
|
8
|
+
const [selectedItems, setSelectedItems] = useState(defaultSelected);
|
|
9
|
+
const hasLimit = limit !== null && limit < items.length;
|
|
10
|
+
const slicedItems = hasLimit ? items.slice(0, limit) : items;
|
|
11
|
+
const includesItems = useCallback((item, selectedItems) => {
|
|
12
|
+
return (selectedItems.filter((selectedItem) => selectedItem.value === item.value && selectedItem.label === item.label).length > 0);
|
|
13
|
+
}, []);
|
|
14
|
+
const handleSelect = useCallback((item) => {
|
|
15
|
+
if (includesItems(item, selectedItems)) {
|
|
16
|
+
const newSelectedItems = selectedItems.filter((selectedItem) => selectedItem.value !== item.value && selectedItem.label !== item.label);
|
|
17
|
+
setSelectedItems(newSelectedItems);
|
|
18
|
+
onUnselect(item);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
const newSelectedItems = [...selectedItems, item];
|
|
22
|
+
setSelectedItems(newSelectedItems);
|
|
23
|
+
onSelect(item);
|
|
24
|
+
}
|
|
25
|
+
}, [selectedItems, onSelect, onUnselect, includesItems]);
|
|
26
|
+
const handleSubmit = useCallback(() => {
|
|
27
|
+
onSubmit(selectedItems);
|
|
28
|
+
}, [selectedItems, onSubmit]);
|
|
29
|
+
useInput(useCallback((input, key) => {
|
|
30
|
+
if (key.upArrow) {
|
|
31
|
+
setHighlightedIndex((prevIndex) => {
|
|
32
|
+
const index = prevIndex === 0 ? slicedItems.length - 1 : prevIndex - 1;
|
|
33
|
+
// biome-ignore lint/style/noNonNullAssertion: <explanation>
|
|
34
|
+
onHighlight(slicedItems[index]);
|
|
35
|
+
return index;
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
else if (key.downArrow) {
|
|
39
|
+
setHighlightedIndex((prevIndex) => {
|
|
40
|
+
const index = prevIndex === slicedItems.length - 1 ? 0 : prevIndex + 1;
|
|
41
|
+
// biome-ignore lint/style/noNonNullAssertion: <explanation>
|
|
42
|
+
onHighlight(slicedItems[index]);
|
|
43
|
+
return index;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
else if (key.return) {
|
|
47
|
+
handleSubmit();
|
|
48
|
+
}
|
|
49
|
+
else if (input === ' ') {
|
|
50
|
+
// biome-ignore lint/style/noNonNullAssertion: <explanation>
|
|
51
|
+
handleSelect(slicedItems[highlightedIndex]);
|
|
52
|
+
}
|
|
53
|
+
}, [onHighlight, handleSelect, handleSubmit, slicedItems, highlightedIndex]), { isActive: focus });
|
|
54
|
+
return (React.createElement(Box, { flexDirection: "column" }, slicedItems.map((item, index) => {
|
|
55
|
+
const key = item.key || item.label;
|
|
56
|
+
const isHighlighted = index === highlightedIndex;
|
|
57
|
+
const isSelected = includesItems(item, selectedItems);
|
|
58
|
+
return (React.createElement(Box, { key: key },
|
|
59
|
+
React.createElement(indicatorComponent, { isHighlighted }),
|
|
60
|
+
React.createElement(checkboxComponent, { isSelected }),
|
|
61
|
+
React.createElement(itemComponent, {
|
|
62
|
+
...item,
|
|
63
|
+
isHighlighted,
|
|
64
|
+
})));
|
|
65
|
+
})));
|
|
66
|
+
};
|
|
67
|
+
export default MultiSelect;
|
|
68
|
+
export { Indicator, ItemComponent, CheckBox };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import figures from 'figures';
|
|
2
|
+
import { Box, Text } from 'ink';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
const CheckBox = ({ isSelected = false }) => (React.createElement(Box, { marginRight: 1 },
|
|
5
|
+
React.createElement(Text, { color: isSelected ? 'green' : 'white' }, isSelected ? figures.circleFilled : figures.circle)));
|
|
6
|
+
export default CheckBox;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import figures from 'figures';
|
|
2
|
+
import { Box, Text } from 'ink';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
const Indicator = ({ isHighlighted = false }) => (React.createElement(Box, { marginRight: 1 },
|
|
5
|
+
React.createElement(Text, { color: isHighlighted ? 'green' : undefined }, isHighlighted ? figures.pointer : ' ')));
|
|
6
|
+
export default Indicator;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default, type Item, Indicator, CheckBox, ItemComponent } from './MultiSelect.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default, Indicator, CheckBox, ItemComponent } from './MultiSelect.js';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type FC } from 'react';
|
|
2
|
+
interface Props {
|
|
3
|
+
projectName: string;
|
|
4
|
+
onCompletion: () => void;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Step for cloning the repository.
|
|
8
|
+
* @param projectName
|
|
9
|
+
* @param onCompletion
|
|
10
|
+
* @constructor
|
|
11
|
+
*/
|
|
12
|
+
declare const CloneRepo: FC<Props>;
|
|
13
|
+
export default CloneRepo;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import Divider from '../../Divider.js';
|
|
3
|
+
import Commands from './Commands.js';
|
|
4
|
+
/**
|
|
5
|
+
* Step for cloning the repository.
|
|
6
|
+
* @param projectName
|
|
7
|
+
* @param onCompletion
|
|
8
|
+
* @constructor
|
|
9
|
+
*/
|
|
10
|
+
const CloneRepo = ({ projectName, onCompletion }) => (React.createElement(React.Fragment, null,
|
|
11
|
+
React.createElement(Divider, { title: 'Git tasks' }),
|
|
12
|
+
React.createElement(Commands, { projectName: projectName, onCompletion: onCompletion })));
|
|
13
|
+
export default CloneRepo;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type FC } from 'react';
|
|
2
|
+
interface Props {
|
|
3
|
+
projectName: string;
|
|
4
|
+
onCompletion: () => void;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Executes all the commands to clone the dAppBooster repository.
|
|
8
|
+
* @param projectName
|
|
9
|
+
* @param onCompletion
|
|
10
|
+
*/
|
|
11
|
+
declare const Commands: FC<Props>;
|
|
12
|
+
export default Commands;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import * as process from 'node:process';
|
|
3
|
+
import { Box, Text } from 'ink';
|
|
4
|
+
import { Script, Spawn } from 'ink-spawn';
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import { repoUrl } from '../../../constants/config.js';
|
|
7
|
+
/**
|
|
8
|
+
* Executes all the commands to clone the dAppBooster repository.
|
|
9
|
+
* @param projectName
|
|
10
|
+
* @param onCompletion
|
|
11
|
+
*/
|
|
12
|
+
const Commands = ({ projectName, onCompletion }) => {
|
|
13
|
+
const projectFolder = join(process.cwd(), projectName);
|
|
14
|
+
return (React.createElement(Box, { flexDirection: 'column', gap: 0 },
|
|
15
|
+
React.createElement(Script, null,
|
|
16
|
+
React.createElement(Box, { columnGap: 1 },
|
|
17
|
+
React.createElement(Text, { color: 'whiteBright' }, "Cloning dAppBooster in"),
|
|
18
|
+
React.createElement(Text, { italic: true }, projectName)),
|
|
19
|
+
React.createElement(Spawn, { shell: true, silent: true, successText: 'Done!', failureText: `Failed to clone the project, check if a folder called "${projectName}" already exists and your read/write permissions...`, runningText: 'Working...', command: "git", args: ['clone', '--depth', '1', '--no-checkout', repoUrl, projectName] }),
|
|
20
|
+
React.createElement(Text, { color: 'whiteBright' }, "Fetching tags"),
|
|
21
|
+
React.createElement(Spawn, { shell: true, cwd: projectFolder, silent: true, command: 'git', args: ['fetch', '--tags'], runningText: 'Working...', successText: 'Done!', failureText: 'Error...' }),
|
|
22
|
+
React.createElement(Text, { color: 'whiteBright' }, "Checking out latest tag"),
|
|
23
|
+
React.createElement(Spawn, { shell: true, cwd: projectFolder, command: "git", args: ['checkout $(git describe --tags `git rev-list --tags --max-count=1`)'], successText: "Done!", failureText: 'Error...' }),
|
|
24
|
+
React.createElement(Text, { color: 'whiteBright' }, "Removing .git folder"),
|
|
25
|
+
React.createElement(Spawn, { shell: true, cwd: projectFolder, command: "rm", args: ['-rf', '.git'], successText: "Done!", failureText: 'Error...' }),
|
|
26
|
+
React.createElement(Text, { color: 'whiteBright' }, "Initializing Git repository"),
|
|
27
|
+
React.createElement(Spawn, { shell: true, cwd: projectFolder, command: "git", args: ['init'], successText: "Done!", failureText: 'Error...', onCompletion: onCompletion }))));
|
|
28
|
+
};
|
|
29
|
+
export default Commands;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type FC } from 'react';
|
|
2
|
+
import type { InstallationType, MultiSelectItem } from '../../types/types.js';
|
|
3
|
+
interface Props {
|
|
4
|
+
onCompletion: () => void;
|
|
5
|
+
projectName: string;
|
|
6
|
+
installationConfig: {
|
|
7
|
+
installationType: InstallationType | undefined;
|
|
8
|
+
selectedFeatures?: Array<MultiSelectItem>;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Performs file cleanup after the installation process
|
|
13
|
+
* @param onCompletion
|
|
14
|
+
* @param installation
|
|
15
|
+
* @param projectName
|
|
16
|
+
*/
|
|
17
|
+
declare const FileCleanup: FC<Props>;
|
|
18
|
+
export default FileCleanup;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { Box, Text } from 'ink';
|
|
4
|
+
import { Script, Spawn } from 'ink-spawn';
|
|
5
|
+
import React, { useMemo } from 'react';
|
|
6
|
+
import { featureSelected, getProjectFolder } from '../../utils/utils.js';
|
|
7
|
+
import Divider from '../Divider.js';
|
|
8
|
+
const packageJSONCleanup = (projectFolder, selectedFeatures) => {
|
|
9
|
+
const packageJSONPath = join(projectFolder, 'package.json');
|
|
10
|
+
const packageJSON = JSON.parse(readFileSync(packageJSONPath, 'utf8'));
|
|
11
|
+
if (!featureSelected('subgraph', selectedFeatures)) {
|
|
12
|
+
packageJSON.scripts['subgraph-codegen'] = undefined;
|
|
13
|
+
}
|
|
14
|
+
if (!featureSelected('typedoc', selectedFeatures)) {
|
|
15
|
+
packageJSON.scripts['typedoc:build'] = undefined;
|
|
16
|
+
}
|
|
17
|
+
if (!featureSelected('vocs', selectedFeatures)) {
|
|
18
|
+
packageJSON.scripts['docs:build'] = undefined;
|
|
19
|
+
packageJSON.scripts['docs:dev'] = undefined;
|
|
20
|
+
packageJSON.scripts['docs:preview'] = undefined;
|
|
21
|
+
}
|
|
22
|
+
if (!featureSelected('husky', selectedFeatures)) {
|
|
23
|
+
packageJSON.scripts.prepare = undefined;
|
|
24
|
+
}
|
|
25
|
+
writeFileSync(packageJSONPath, `${JSON.stringify(packageJSON, null, 2)}\n`);
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Performs file cleanup after the installation process
|
|
29
|
+
* @param onCompletion
|
|
30
|
+
* @param installation
|
|
31
|
+
* @param projectName
|
|
32
|
+
*/
|
|
33
|
+
const FileCleanup = ({ onCompletion, installationConfig, projectName }) => {
|
|
34
|
+
const { installationType, selectedFeatures } = installationConfig;
|
|
35
|
+
const projectFolder = useMemo(() => getProjectFolder(projectName), [projectName]);
|
|
36
|
+
const currentHomeFolder = `${projectFolder}/src/components/pageComponents/home`;
|
|
37
|
+
return (React.createElement(React.Fragment, null,
|
|
38
|
+
React.createElement(Divider, { title: 'File cleanup' }),
|
|
39
|
+
React.createElement(Box, { flexDirection: 'column', gap: 0 },
|
|
40
|
+
React.createElement(Script, null,
|
|
41
|
+
installationType === 'custom' && (React.createElement(Script, { onCompletion: () => packageJSONCleanup(projectFolder, selectedFeatures) },
|
|
42
|
+
!featureSelected('demo', selectedFeatures) && (React.createElement(Script, null,
|
|
43
|
+
React.createElement(Text, { color: 'whiteBright' }, "Component demos"),
|
|
44
|
+
React.createElement(Spawn, { shell: true, cwd: projectFolder, silent: true, command: "rm", args: ['-rf', currentHomeFolder], runningText: 'Removing home files...', successText: 'Done!', failureText: 'Error...' }),
|
|
45
|
+
React.createElement(Spawn, { shell: true, cwd: projectFolder, silent: true, command: "mkdir", args: ['-p', currentHomeFolder], runningText: 'Creating home folder...', successText: 'Done!', failureText: 'Error...' }),
|
|
46
|
+
React.createElement(Spawn, { shell: true, cwd: projectFolder, silent: true, command: "cp", args: ['./.install-files/home/index.tsx', currentHomeFolder], runningText: 'Creating new home page file...', successText: 'Done!', failureText: 'Error...' }))),
|
|
47
|
+
!featureSelected('subgraph', selectedFeatures) && (React.createElement(Script, null,
|
|
48
|
+
React.createElement(Text, { color: 'whiteBright' }, "Subgraph"),
|
|
49
|
+
React.createElement(Spawn, { shell: true, cwd: projectFolder, silent: true, command: "rm", args: ['-rf', './src/subgraphs'], runningText: 'Removing subgraphs folder...', successText: 'Done!', failureText: 'Error...' }),
|
|
50
|
+
featureSelected('demo', selectedFeatures) && (React.createElement(Script, null,
|
|
51
|
+
React.createElement(Spawn, { shell: true, cwd: projectFolder, silent: true, command: "rm", args: ['-rf', `${currentHomeFolder}/Examples/demos/subgraphs`], runningText: 'Removing subgraphs demos folder...', successText: 'Done!', failureText: 'Error...' }),
|
|
52
|
+
React.createElement(Spawn, { shell: true, cwd: projectFolder, silent: true, command: "rm", args: [`${currentHomeFolder}/index.tsx`], runningText: 'Removing home page file...', successText: 'Done!', failureText: 'Error...' }),
|
|
53
|
+
React.createElement(Spawn, { shell: true, cwd: projectFolder, silent: true, command: "cp", args: [
|
|
54
|
+
'./.install-files/home/Examples/index.tsx',
|
|
55
|
+
`${currentHomeFolder}/index.tsx`,
|
|
56
|
+
], runningText: 'Creating new home page file...', successText: 'Done!', failureText: 'Error...' }))))),
|
|
57
|
+
!featureSelected('typedoc', selectedFeatures) && (React.createElement(Script, null,
|
|
58
|
+
React.createElement(Text, { color: 'whiteBright' }, "Typedoc"),
|
|
59
|
+
React.createElement(Spawn, { shell: true, cwd: projectFolder, silent: true, command: "rm", args: ['./typedoc.json'], runningText: 'Removing config...', successText: 'Done!', failureText: 'Error...' }))),
|
|
60
|
+
!featureSelected('vocs', selectedFeatures) && (React.createElement(Script, null,
|
|
61
|
+
React.createElement(Text, { color: 'whiteBright' }, "Vocs"),
|
|
62
|
+
React.createElement(Spawn, { shell: true, cwd: projectFolder, silent: true, command: "rm", args: ['./vocs.config.ts'], runningText: 'Removing config...', successText: 'Done!', failureText: 'Error...' }),
|
|
63
|
+
React.createElement(Spawn, { shell: true, cwd: projectFolder, silent: true, command: "rm", args: ['-rf', './docs'], runningText: 'Removing docs folder...', successText: 'Done!', failureText: 'Error...' }))),
|
|
64
|
+
!featureSelected('husky', selectedFeatures) && (React.createElement(Script, null,
|
|
65
|
+
React.createElement(Text, { color: 'whiteBright' }, "Husky"),
|
|
66
|
+
React.createElement(Spawn, { shell: true, cwd: projectFolder, silent: true, command: "rm", args: ['-rf', './.husky'], runningText: 'Removing Husky folder...', successText: 'Done!', failureText: 'Error...' }),
|
|
67
|
+
React.createElement(Spawn, { shell: true, cwd: projectFolder, silent: true, command: "rm", args: ['./.lintstagedrc.mjs'], runningText: 'Removing lint-staged config...', successText: 'Done!', failureText: 'Error...' }),
|
|
68
|
+
React.createElement(Spawn, { shell: true, cwd: projectFolder, silent: true, command: "rm", args: ['./commitlint.config.js'], runningText: 'Removing commitlint config...', successText: 'Done!', failureText: 'Error...' }))))),
|
|
69
|
+
React.createElement(Text, { color: 'whiteBright' }, "Install script"),
|
|
70
|
+
React.createElement(Spawn, { shell: true, cwd: projectFolder, silent: true, command: "rm", args: ['-rf', './.install-files'], runningText: 'Removing folder...', successText: 'Done!', failureText: 'Error...', onCompletion: onCompletion })))));
|
|
71
|
+
};
|
|
72
|
+
export default FileCleanup;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type FC } from 'react';
|
|
2
|
+
import type { MultiSelectItem } from '../../../types/types.js';
|
|
3
|
+
interface Props {
|
|
4
|
+
onCompletion: () => void;
|
|
5
|
+
projectFolder: string;
|
|
6
|
+
selectedFeatures?: Array<MultiSelectItem>;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Performs a custom installation based on the selected features: basically we tell `pnpm` what
|
|
10
|
+
* features to remove (everything's included in package.json by default to simplify things)
|
|
11
|
+
* @param onCompletion
|
|
12
|
+
* @param selectedFeatures
|
|
13
|
+
* @param projectFolder
|
|
14
|
+
*/
|
|
15
|
+
declare const CustomInstallation: FC<Props>;
|
|
16
|
+
export default CustomInstallation;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Box, Text } from 'ink';
|
|
2
|
+
import { Script, Spawn } from 'ink-spawn';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { getPackages } from '../../../utils/utils.js';
|
|
5
|
+
import InstallAllPackages from './InstallAllPackages.js';
|
|
6
|
+
/**
|
|
7
|
+
* Performs a custom installation based on the selected features: basically we tell `pnpm` what
|
|
8
|
+
* features to remove (everything's included in package.json by default to simplify things)
|
|
9
|
+
* @param onCompletion
|
|
10
|
+
* @param selectedFeatures
|
|
11
|
+
* @param projectFolder
|
|
12
|
+
*/
|
|
13
|
+
const CustomInstallation = ({ onCompletion, selectedFeatures, projectFolder }) => {
|
|
14
|
+
// Collects the packages to remove based on the selected features and makes
|
|
15
|
+
// a string out of them so that we can pass it to `pnpm remove` command.
|
|
16
|
+
const packagesToRemove = [
|
|
17
|
+
...getPackages('subgraph', selectedFeatures),
|
|
18
|
+
...getPackages('typedoc', selectedFeatures),
|
|
19
|
+
...getPackages('vocs', selectedFeatures),
|
|
20
|
+
...getPackages('husky', selectedFeatures),
|
|
21
|
+
]
|
|
22
|
+
.join(' ')
|
|
23
|
+
.trim();
|
|
24
|
+
return (React.createElement(Box, { flexDirection: 'column', gap: 0 }, !packagesToRemove ? (React.createElement(Script, null,
|
|
25
|
+
React.createElement(InstallAllPackages, { projectFolder: projectFolder, onCompletion: onCompletion }))) : (React.createElement(Script, null,
|
|
26
|
+
React.createElement(Text, { color: 'whiteBright' }, "Installing packages"),
|
|
27
|
+
React.createElement(Spawn, { shell: true, cwd: projectFolder, silent: true, command: 'pnpm', args: ['remove', packagesToRemove], runningText: 'Working...', successText: 'Done!', failureText: 'Error...' }),
|
|
28
|
+
React.createElement(Text, { color: 'whiteBright' }, "Executing post-install scripts"),
|
|
29
|
+
React.createElement(Spawn, { shell: true, cwd: projectFolder, silent: true, command: 'pnpm', args: ['run', 'postinstall'], runningText: 'Working...', successText: 'Done!', failureText: 'Error...', onCompletion: onCompletion })))));
|
|
30
|
+
};
|
|
31
|
+
export default CustomInstallation;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Box } from 'ink';
|
|
2
|
+
import { Script } from 'ink-spawn';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import InstallAllPackages from './InstallAllPackages.js';
|
|
5
|
+
const FullInstallation = ({ onCompletion, projectFolder }) => {
|
|
6
|
+
return (React.createElement(Box, { flexDirection: 'column', gap: 0 },
|
|
7
|
+
React.createElement(Script, null,
|
|
8
|
+
React.createElement(InstallAllPackages, { projectFolder: projectFolder, onCompletion: onCompletion }))));
|
|
9
|
+
};
|
|
10
|
+
export default FullInstallation;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type FC } from 'react';
|
|
2
|
+
import type { InstallationType, MultiSelectItem } from '../../../types/types.js';
|
|
3
|
+
interface Props {
|
|
4
|
+
installationConfig: {
|
|
5
|
+
installationType: InstallationType | undefined;
|
|
6
|
+
selectedFeatures?: Array<MultiSelectItem>;
|
|
7
|
+
};
|
|
8
|
+
projectName: string;
|
|
9
|
+
onCompletion: () => void;
|
|
10
|
+
}
|
|
11
|
+
declare const Install: FC<Props>;
|
|
12
|
+
export default Install;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Box, Text } from 'ink';
|
|
2
|
+
import { Script, Spawn } from 'ink-spawn';
|
|
3
|
+
import React, { useMemo } from 'react';
|
|
4
|
+
import { getProjectFolder } from '../../../utils/utils.js';
|
|
5
|
+
import Divider from '../../Divider.js';
|
|
6
|
+
import CustomInstallation from './CustomInstallation.js';
|
|
7
|
+
import FullInstallation from './FullInstallation.js';
|
|
8
|
+
const Install = ({ projectName, onCompletion, installationConfig }) => {
|
|
9
|
+
const { installationType, selectedFeatures } = installationConfig;
|
|
10
|
+
const projectFolder = useMemo(() => getProjectFolder(projectName), [projectName]);
|
|
11
|
+
const title = installationType
|
|
12
|
+
? installationType[0]?.toUpperCase() + installationType.slice(1)
|
|
13
|
+
: '';
|
|
14
|
+
return (React.createElement(React.Fragment, null,
|
|
15
|
+
React.createElement(Divider, { title: `${title ?? 'Full'} installation` }),
|
|
16
|
+
React.createElement(Box, { flexDirection: 'column', gap: 0 },
|
|
17
|
+
React.createElement(Script, null,
|
|
18
|
+
React.createElement(Box, { columnGap: 1 },
|
|
19
|
+
React.createElement(Text, { color: 'whiteBright' },
|
|
20
|
+
"Creating",
|
|
21
|
+
' ',
|
|
22
|
+
React.createElement(Text, { italic: true, color: 'white' }, ".env.local"),
|
|
23
|
+
' ',
|
|
24
|
+
"file")),
|
|
25
|
+
React.createElement(Spawn, { shell: true, cwd: projectFolder, silent: true, command: 'cp', args: ['.env.example', '.env.local'], runningText: 'Working...', successText: 'Done!', failureText: 'Error...' }),
|
|
26
|
+
installationType === 'full' && (React.createElement(FullInstallation, { onCompletion: onCompletion, projectFolder: projectFolder })),
|
|
27
|
+
installationType === 'custom' && (React.createElement(CustomInstallation, { selectedFeatures: selectedFeatures, onCompletion: onCompletion, projectFolder: projectFolder }))))));
|
|
28
|
+
};
|
|
29
|
+
export default Install;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Text } from 'ink';
|
|
2
|
+
import { Spawn } from 'ink-spawn';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
const InstallAllPackages = ({ projectFolder, onCompletion }) => {
|
|
5
|
+
return (React.createElement(React.Fragment, null,
|
|
6
|
+
React.createElement(Text, { color: 'whiteBright' }, "Installing packages"),
|
|
7
|
+
React.createElement(Spawn, { shell: true, cwd: projectFolder, silent: true, command: 'pnpm', args: ['i'], runningText: 'Working...', successText: 'Done!', failureText: 'Error...', onCompletion: onCompletion })));
|
|
8
|
+
};
|
|
9
|
+
export default InstallAllPackages;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type FC } from 'react';
|
|
2
|
+
import type { InstallationSelectItem } from '../../types/types.js';
|
|
3
|
+
interface Props {
|
|
4
|
+
onCompletion: () => void;
|
|
5
|
+
onSelect: (item: InstallationSelectItem) => void;
|
|
6
|
+
}
|
|
7
|
+
declare const InstallationMode: FC<Props>;
|
|
8
|
+
export default InstallationMode;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import figures from 'figures';
|
|
2
|
+
import { Text } from 'ink';
|
|
3
|
+
import SelectInput from 'ink-select-input';
|
|
4
|
+
import React, { useState } from 'react';
|
|
5
|
+
import Divider from '../Divider.js';
|
|
6
|
+
const installationTypeItems = [
|
|
7
|
+
{
|
|
8
|
+
label: 'Full',
|
|
9
|
+
value: 'full',
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
label: 'Custom',
|
|
13
|
+
value: 'custom',
|
|
14
|
+
},
|
|
15
|
+
];
|
|
16
|
+
const InstallationMode = ({ onCompletion, onSelect }) => {
|
|
17
|
+
const [isFocused, setIsFocused] = useState(true);
|
|
18
|
+
const handleSelect = (item) => {
|
|
19
|
+
onSelect(item);
|
|
20
|
+
onCompletion();
|
|
21
|
+
setIsFocused(false);
|
|
22
|
+
};
|
|
23
|
+
return (React.createElement(React.Fragment, null,
|
|
24
|
+
React.createElement(Divider, { title: 'Installation setup' }),
|
|
25
|
+
React.createElement(Text, { color: 'whiteBright' }, "Choose installation type"),
|
|
26
|
+
React.createElement(SelectInput, { indicatorComponent: ({ isSelected }) => (React.createElement(Text, { color: "green" }, isSelected ? `${figures.pointer} ` : ' ')), itemComponent: ({ label, isSelected }) => (React.createElement(Text, { color: isSelected ? 'green' : 'white', bold: isSelected }, label)), isFocused: isFocused, items: installationTypeItems, onSelect: handleSelect })));
|
|
27
|
+
};
|
|
28
|
+
export default InstallationMode;
|