UNPKG

@swell/cli

Version:

Swell's command line interface/utility

217 lines (216 loc) 8.7 kB
import { confirm, input, select } from '@inquirer/prompts'; import { Args, Flags } from '@oclif/core'; import path from 'node:path'; import ora from 'ora'; import { CreateAppCommand } from '../../create-app-command.js'; import { newConfig, swellConfigFileExists } from '../../lib/app-config.js'; import { toAppId, toAppName } from '../../lib/create/index.js'; import style from '../../lib/style.js'; export default class CreateApp extends CreateAppCommand { appType = ''; static args = { id: Args.string({ default: '', description: `id of the app to create`, }), }; static description = 'Create an app.'; static examples = [ { command: 'swell create app', description: 'Create app following command prompts.', }, { command: 'swell create app my_app -y', description: 'Create app and accept all default values.', }, { command: 'swell create app -p yarn', description: 'Create app with yarn package manager instead of npm by default.', }, { command: 'swell create app -p none', description: 'Create app without installing TypeScript bindings, etc.', }, ]; static flags = { pkg: Flags.string({ char: 'p', default: 'npm', description: `use npm or yarn to install default dependencies, or none to disable`, options: ['npm', 'yarn', 'none'], }), type: Flags.string({ char: 't', description: `create a specific app type`, options: ['admin', 'integration', 'storefront', 'theme'], }), }; async createSwellConfig({ allowOverwrite = true, inputId = '', inputStorefrontApp, inputType, inputYes, nestedPath = true, }) { let confirmYes = inputYes; const type = inputType || (confirmYes ? 'admin' : await select({ choices: [ { name: 'Admin', value: 'admin' }, { name: 'Integration', value: 'integration' }, { name: 'Storefront', value: 'storefront' }, { name: 'Theme', value: 'theme' }, ], message: `What is the primary purpose of the app?`, })); const typeLabel = type === 'theme' ? 'theme' : 'app'; const typeLabelTitle = type === 'theme' ? 'Theme' : 'App'; const name = confirmYes ? toAppName(inputId) : await input({ default: inputId ? toAppName(inputId) : '', message: `${typeLabelTitle} name`, validate: (answer) => answer.length > 2, }); let appId = toAppId(inputId || ''); if (!appId) { appId = await input({ default: toAppId(name), message: `${typeLabelTitle} ID`, validate: (answer) => answer.length > 2, }); appId = toAppId(appId); confirmYes = Boolean(inputYes && appId); } const version = confirmYes ? '1.0.0' : await input({ default: '1.0.0', message: `${typeLabelTitle} version`, }); const description = confirmYes ? '' : await input({ default: 'Something special', message: `Describe your ${typeLabel}`, }); let storefrontInstalledApps; let storefrontAppId; let installedStorefrontApp; if (type === 'theme') { storefrontInstalledApps = await this.getInstalledStorefrontApps(); if (storefrontInstalledApps === false) { return; } storefrontAppId = inputStorefrontApp || (storefrontInstalledApps.length > 1 ? await select({ choices: storefrontInstalledApps.map(({ app, id }) => ({ name: app.name, value: id, })), message: `Which storefront app is your theme for?`, }) : storefrontInstalledApps[0].id); installedStorefrontApp = storefrontInstalledApps.find((installedApp) => inputStorefrontApp ? inputStorefrontApp === installedApp.app_private_id || inputStorefrontApp === installedApp.app_public_id || inputStorefrontApp === installedApp.app_id || inputStorefrontApp === toAppId(installedApp.app_private_id) : installedApp.id === storefrontAppId); if (!installedStorefrontApp) { this.error(`Could not find an installed storefront app by id: ${storefrontAppId}`); } } const swellConfigJson = { description, id: appId, name, type, version, ...(type === 'theme' ? { theme: { storefront: { app: toAppId(installedStorefrontApp.app_private_id), }, }, } : { permissions: [], }), }; const appPath = path.join(process.cwd(), inputId || appId); if (swellConfigFileExists(appPath)) { if (allowOverwrite) { if (!confirmYes) { const continueCreateApp = await confirm({ message: `An app already exists in the target path ${appPath}. Overwrite?`, }); if (!continueCreateApp) { return; } } } else { this.error(`An app already exists in the target path ${appPath}.`); } } this.log(`\nCreating ${this.appType === 'theme' ? 'theme' : 'app'} ${style.appConfigValue(name)} in ${appPath}/swell.json`); this.log(`\n${JSON.stringify(swellConfigJson, null, 2)}\n`); const confirmCreateApp = confirmYes ? true : await confirm({ message: 'Ok to continue?', }); if (!confirmCreateApp) { return; } const config = newConfig(nestedPath ? inputId || appId : ''); config.clear(); config.set(swellConfigJson); return { appId, config, installedStorefrontApp, swellConfigJson }; } async run() { const { args, flags } = await this.parse(CreateApp); const { id } = args; const { pkg, yes } = flags; const confirmYes = Boolean(yes && id); const createParams = await this.createSwellConfig({ inputId: id, inputStorefrontApp: flags['storefront-app'], inputType: flags.type, inputYes: confirmYes, }); if (!createParams) { return; } const { appId, config, installedStorefrontApp } = createParams; !confirmYes && this.log(); const spinner = ora(); spinner.start('Creating app...'); if (pkg !== 'none') { await this.tryPackageSetup(appId, config, pkg); } await this.createAppConfigFolders(config); spinner.succeed(`${style.appConfigValue(config.get('name'))} app created.\n`); let createdFrontend; let createdTheme; if (installedStorefrontApp) { createdTheme = await this.createThemeApp(config, flags, installedStorefrontApp); } else if (config.get('type') === 'storefront') { createdFrontend = await this.createStorefrontApp(config, flags); } else { createdFrontend = await this.createFrontendApp(config, flags); } this.log('\nNext steps:'); this.log(`Run ${style.command('swell app push')} to push configurations to your test store.`); this.log(`Run ${style.command('swell app install')} to install the app in another store or environment.`); if (createdFrontend) { this.log(`Run ${style.command('swell app frontend dev')} to start a local dev server for your frontend app.`); } else if (createdTheme) { this.log(`Run ${style.command('swell app theme dev')} to start a local dev server for your theme.`); } } }