Skip to content

Commit

Permalink
feat: add multiple components
Browse files Browse the repository at this point in the history
  • Loading branch information
vaibhk20 committed Oct 4, 2024
1 parent db9c7b6 commit c83c237
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 88 deletions.
41 changes: 13 additions & 28 deletions packages/gluestack-cli/src/commands/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import os from 'os';
import { join } from 'path';
import { handleError } from '../util/handle-error';
import { log } from '@clack/prompts';
import { componentAdder, hookAdder, isHookFromConfig } from '../util/add';
import { componentAdder } from '../util/add';
import { config } from '../config';
import {
checkWritablePath,
Expand All @@ -18,7 +18,7 @@ import { checkIfInitialized, getComponentsPath } from '../util/config';
const _homeDir = os.homedir();

const addOptionsSchema = z.object({
components: z.string().optional(),
components: z.array(z.string()),
all: z.boolean(),
useNpm: z.boolean(),
useYarn: z.boolean(),
Expand All @@ -39,19 +39,13 @@ export const add = new Command()
.option('--path <path>', 'path to the components directory')
.action(async (components, opts, command) => {
try {
if (command.args.length > 1) {
log.error(
'\x1b[31mOnly one component can be provided at a time, please provide the component name you want to add or --all.\x1b[0m'
);
process.exit(1);
}
const options = addOptionsSchema.parse({
components: components ?? '',
components: command.args.length > 0 ? command.args : [],
...opts,
});
if (
options.all === false &&
(options.components === '' || options.components === undefined)
(!options.all && options.components?.length === 0) ||
(options.all && options.components?.length > 0)
) {
log.error(
'\x1b[31mInvalid arguement, please provide the component/hook name you want to add or --all.\x1b[0m'
Expand Down Expand Up @@ -94,24 +88,15 @@ export const add = new Command()
config.writableComponentsPath = options.path;
}
await cloneRepositoryAtRoot(join(_homeDir, config.gluestackDir));
// define args based on --all or components
const args = options.all
? { addAll: true }
: { componentArgs: options.components.map((c) => c.toLowerCase()) };

if (options.all) {
try {
await componentAdder({
requestedComponent: '--all',
});
} catch (err) {
log.error(`\x1b[31mError: ${(err as Error).message}\x1b[0m`);
}
} else if (await isHookFromConfig(options.components)) {
options.components &&
(await hookAdder({
requestedHook: options.components,
}));
} else {
await componentAdder({
requestedComponent: options.components?.toLowerCase(),
});
try {
await componentAdder(args);
} catch (err) {
log.error(`\x1b[31mError: ${(err as Error).message}\x1b[0m`);
}
} catch (err) {
handleError(err);
Expand Down
151 changes: 91 additions & 60 deletions packages/gluestack-cli/src/util/add/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import fs from 'fs-extra';
import chalk from 'chalk';
import os from 'os';
import { basename, join, parse } from 'path';
import { log, confirm } from '@clack/prompts';
Expand All @@ -15,56 +16,65 @@ const _homeDir = os.homedir();
let existingComponentsChecked: boolean = false;

const componentAdder = async ({
requestedComponent = '',
addAll = false,
componentArgs = [],
showWarning = true,
}: {
addAll?: boolean;
componentArgs?: Array<string>;
showWarning?: boolean;
}) => {
try {
console.log(`\n\x1b[1mAdding new component...\x1b[0m\n`);
let hooksToAdd: string[] = [];
if (
requestedComponent &&
requestedComponent !== '--all' &&
!(await checkIfComponentIsValid(requestedComponent))
) {
log.error(
`The ${requestedComponent} does not exist. Kindly choose a valid component name.`
);
return;
}
let requestedComponents =
requestedComponent === '--all'
? await getAllComponents()
: [requestedComponent];

const { hooks } = await checkComponentDependencies(requestedComponents);
hooksToAdd = Array.from(hooks);

const updatedComponents =
!existingComponentsChecked && showWarning && requestedComponent
? await isComponentInProject(requestedComponents)
: requestedComponents;
const count = updatedComponents.length;
await Promise.all(
updatedComponents.map(async (component) => {
const targetPath = join(
projectRootPath,
config.writableComponentsPath,
component
const res = await sortComponentsAndHooks(componentArgs);
let componentsToAdd = res.components;
let hooksToAdd = res.hooks;
if (componentsToAdd.length > 0 || addAll) {
if (
!addAll &&
componentsToAdd?.length &&
!(await checkIfComponentIsValid(componentsToAdd))
) {
log.error(
chalk.red(
`Invalid names entered. Kindly check and choose a valid component name.`
)
);
return;
}
console.log(`\n\x1b[1mAdding new component...\x1b[0m\n`);
let requestedComponents = addAll
? await getAllComponents()
: componentsToAdd;
const { hooks } = await checkComponentDependencies(requestedComponents);
hooksToAdd = Array.from(hooks);

await writeComponent(component, targetPath);
})
)
.then(async () => {
await installDependencies(updatedComponents);
log.success(
`\x1b[32mDone!\x1b[0m Added new \x1b[1mgluestack-ui\x1b[0m ${count === 1 ? 'component' : 'components'} into project`
);
})
.catch((err) => {
log.error(`\x1b[31mError : ${(err as Error).message}\x1b[0m`);
});
if (hooksToAdd.length > 0) await hookAdder({ requestedHook: hooksToAdd });
const updatedComponents =
!existingComponentsChecked && showWarning && componentsToAdd.length
? await isComponentInProject(requestedComponents)
: requestedComponents;
const count = updatedComponents.length;
await Promise.all(
updatedComponents.map(async (component) => {
const targetPath = join(
projectRootPath,
config.writableComponentsPath,
component
);

await writeComponent(component, targetPath);
})
)
.then(async () => {
await installDependencies(updatedComponents);
log.success(
`\x1b[32mDone!\x1b[0m Added new \x1b[1mgluestack-ui\x1b[0m ${count === 1 ? 'component' : 'components'} into project`
);
})
.catch((err) => {
log.error(`\x1b[31mError : ${(err as Error).message}\x1b[0m`);
});
}
if (hooksToAdd.length > 0) await hookAdder(hooksToAdd);
} catch (err) {
log.error(`\x1b[31mError: ${(err as Error).message}\x1b[0m`);
}
Expand Down Expand Up @@ -121,9 +131,11 @@ const processTerminate = (message: string) => {
process.exit(1);
};

const checkIfComponentIsValid = async (component: string): Promise<boolean> => {
const checkIfComponentIsValid = async (
components: string[]
): Promise<boolean> => {
const componentList = await getAllComponents();
if (componentList.includes(component) || componentList.includes(component))
if (components.every((component) => componentList.includes(component)))
return true;
else return false;
};
Expand Down Expand Up @@ -165,11 +177,7 @@ const confirmOverride = async (
return shouldContinue;
};

const hookAdder = async ({
requestedHook,
}: {
requestedHook: string | string[];
}) => {
const hookAdder = async (requestedHook: string[]) => {
try {
console.log(`\n\x1b[1mAdding new hook...\x1b[0m\n`);
await writeHook(requestedHook);
Expand All @@ -181,12 +189,36 @@ const hookAdder = async ({
}
};

const isHookFromConfig = async (hook: string | undefined): Promise<boolean> => {
const sortComponentsAndHooks = async (
inputNames: string[] | undefined
): Promise<{ hooks: string[]; components: string[] }> => {
if (!inputNames || inputNames.length === 0) {
return { hooks: [], components: [] };
}

const hooksPath = join(
_homeDir,
config.gluestackDir,
config.hooksResourcePath
);
const hooksList = fs
.readdirSync(join(_homeDir, config.gluestackDir, config.hooksResourcePath))
.map((file) => removeHyphen(parse(file).name));
if (hook && hooksList.includes(hook.toLowerCase())) return true;
else return false;
.readdirSync(hooksPath)
.map((file) => removeHyphen(parse(file).name).toLowerCase());

const result = inputNames.reduce(
(acc, name) => {
const lowercaseName = name.toLowerCase();
if (hooksList.includes(lowercaseName)) {
acc.hooks.push(name);
} else {
acc.components.push(name);
}
return acc;
},
{ hooks: [] as string[], components: [] as string[] }
);

return result;
};

const hookFileName = async (hook: string): Promise<string> => {
Expand All @@ -201,8 +233,7 @@ const hookFileName = async (hook: string): Promise<string> => {
});
return fileName;
};
const writeHook = async (hooks: string | string[]) => {
const hooksArray = Array.isArray(hooks) ? hooks : [hooks];
const writeHook = async (hooksArray: string[]) => {
for (const hook of hooksArray) {
const fileName = await hookFileName(hook);
const utilsPath = join(
Expand Down Expand Up @@ -243,4 +274,4 @@ const confirmHookOverride = async (hook: string): Promise<boolean | symbol> => {
return shouldContinue;
};

export { componentAdder, getAllComponents, isHookFromConfig, hookAdder };
export { componentAdder, getAllComponents };
1 change: 1 addition & 0 deletions packages/gluestack/src/v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ async function createProject(createOptions: ProjectOptions) {
: `npx create-next-app@latest ${projectName} --ts --no-eslint --use-${packageManager} --import-alias "@/*" --no-tailwind --no-src-dir --app`;
} else if (projectType.includes('react-native')) {
// create react-native project
message = `⏳ Creating a react-native-cli project. Hang tight, this may take a bit...`;
const useCocoapods = router.includes('react-native-cli-cocoapods')
? true
: false;
Expand Down

0 comments on commit c83c237

Please sign in to comment.