diff --git a/packages/create-catalyst/src/commands/create.ts b/packages/create-catalyst/src/commands/create.ts index 4f052b0f1e..dde874eae1 100644 --- a/packages/create-catalyst/src/commands/create.ts +++ b/packages/create-catalyst/src/commands/create.ts @@ -8,6 +8,7 @@ import { join } from 'path'; import { promisify } from 'util'; import { z } from 'zod'; +import { applyIntegrations } from '../utils/apply-integrations'; import { checkStorefrontLimit } from '../utils/check-storefront-limit'; import { cloneCatalyst } from '../utils/clone-catalyst'; import { getLatestCoreTag } from '../utils/get-latest-core-tag'; @@ -29,6 +30,7 @@ export const create = new Command('create') .option('--access-token ', 'BigCommerce access token') .option('--channel-id ', 'BigCommerce channel ID') .option('--customer-impersonation-token ', 'BigCommerce customer impersonation token') + .option('--integrations ', 'Integrations to include in your project') .addOption( new Option( '--gh-ref ', @@ -146,6 +148,8 @@ export const create = new Command('create') await installDependencies(projectDir, packageManager); + await applyIntegrations(options.integrations, { projectDir, packageManager }); + console.log( [ `\n${chalk.green('Success!')} Created '${projectName}' at '${projectDir}'\n`, @@ -257,6 +261,8 @@ export const create = new Command('create') failText: (err) => chalk.red(`Failed to create GraphQL schema: ${err.message}`), }); + await applyIntegrations(options.integrations, { projectDir, packageManager }); + console.log( `\n${chalk.green('Success!')} Created '${projectName}' at '${projectDir}'\n`, '\nNext steps:\n', diff --git a/packages/create-catalyst/src/utils/apply-integrations.ts b/packages/create-catalyst/src/utils/apply-integrations.ts new file mode 100644 index 0000000000..76a941025e --- /dev/null +++ b/packages/create-catalyst/src/utils/apply-integrations.ts @@ -0,0 +1,91 @@ +import { exec as execCallback } from 'child_process'; +import { readJsonSync } from 'fs-extra/esm'; +import { downloadTemplate } from 'giget'; +import { addDependency, addDevDependency } from 'nypm'; +import { join } from 'path'; +import { promisify } from 'util'; +import * as z from 'zod'; + +import { PackageManager } from './pm'; +import { spinner } from './spinner'; + +const exec = promisify(execCallback); + +export async function applyIntegrations( + integrations: string[] | undefined, + { projectDir, packageManager }: { projectDir: string; packageManager: PackageManager }, +) { + if (!integrations) { + console.log('No integrations to apply'); + + return; + } + + if (integrations.length > 1) { + console.warn('Applying multiple integrations is not supported yet'); + } + + const integration = integrations[0]; + const integrationDir = join(projectDir, 'integrations', integration); + + await spinner( + downloadTemplate(`github:bigcommerce/catalyst/integrations/${integration}#main`, { + dir: integrationDir, + offline: false, + }), + { + text: `Cloning ${integration} integration...`, + successText: `${integration} integration cloned successfully`, + failText: (err) => `Failed to clone ${integration} integration: ${err.message}`, + }, + ); + + const manifest = z + .object({ + dependencies: z.array(z.string()), + devDependencies: z.array(z.string()), + environmentVariables: z.array(z.string()), + }) + .parse(readJsonSync(join(integrationDir, 'manifest.json'))); + + if (manifest.dependencies.length) { + await spinner( + addDependency(manifest.dependencies, { + cwd: projectDir, + silent: true, + packageManager, + }), + { + text: 'Installing integration dependencies...', + successText: 'Integration Dependencies installed successfully', + failText: (err) => `Failed to install dependencies: ${err.message}`, + }, + ); + } + + if (manifest.devDependencies.length) { + await spinner( + addDevDependency(manifest.devDependencies, { + cwd: projectDir, + silent: true, + packageManager, + }), + { + text: 'Installing integration development dependencies...', + successText: 'Integration development dependencies installed successfully', + failText: (err) => `Failed to install integration development dependencies: ${err.message}`, + }, + ); + } + + await spinner( + exec(`git apply -p2 ${join(integrationDir, 'integration.patch')}`, { cwd: projectDir }), + { + text: 'Applying integration patch...', + successText: 'Integration patch applied successfully', + failText: (err) => `Failed to apply integration patch: ${err.message}`, + }, + ); + + console.log('Integration applied successfully! Feel free to delete the `integrations` folder'); +}