hydrogen/packages/cli/src/commands/init/init.ts
2021-11-04 15:22:30 -07:00

118 lines
3 KiB
TypeScript

import {join, relative} from 'path';
import {readdirSync, copy} from 'fs-extra';
import {yellow, underline} from 'chalk';
import {Env} from '../../types';
import app from '../create/app';
export enum Template {
None = 'None',
Default = 'Default Hydrogen starter',
}
/**
* Create a new `@shopify/hydrogen` app.
*/
export async function init(env: Env) {
const {ui, fs, workspace} = env;
const name = await ui.ask('What do you want to name this app?', {
validate: validateProjectName,
default: 'snow-devil',
name: 'name',
});
workspace.name(name);
if (await fs.exists(workspace.root())) {
const overwrite = await ui.ask(
`${workspace.root()} is not an empty directory. Do you want to remove the existing files and continue?`,
{boolean: true, name: 'overwrite', default: false}
);
if (overwrite) {
await fs.empty(workspace.root());
}
}
const template = await ui.ask<Template>(
'Would you like to start from a template?',
{
choices: [Template.Default, Template.None],
name: 'template',
}
);
if (template === Template.None) {
const context = {name};
await app({ui, fs, workspace, context});
}
if (template === Template.Default) {
const templateDir = join(__dirname, 'templates', 'template-hydrogen');
const files = readdirSync(templateDir);
for await (const file of files) {
const srcPath = fs.join(templateDir, file);
const destPath = fs.join(workspace.root(), file);
await copy(srcPath, destPath);
}
if (process.env.LOCAL) {
workspace.install('@shopify/hydrogen', {
version: 'file:../../Shopify/hydrogen/packages/hydrogen',
});
}
}
console.log();
workspace.commit().then(() => finish({ui, workspace}));
}
async function finish({ui, workspace}: Pick<Env, 'ui' | 'workspace'>) {
console.log();
ui.say(
`${underline('Success!')} Created app in ${yellow(
`/${relative(process.cwd(), workspace.root())}`
)}.`
);
ui.say(`Run the following commands to get started:`);
console.log();
if (workspace.root() !== process.cwd()) {
ui.say([
[
` • cd ${relative(process.cwd(), workspace.root())}`,
'change into the project directory',
],
]);
}
const usesYarn = workspace.packageManager === 'yarn' || process.env.LOCAL;
ui.say([
[
`${usesYarn ? `yarn` : `npm install --legacy-peer-deps`}`,
' install the dependencies',
],
[`${usesYarn ? `yarn` : `npm run`} dev`, ' start the dev server'],
]);
console.log();
console.log();
console.log();
}
function validateProjectName(name: string) {
const packageNameRegExp =
/^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
if (packageNameRegExp.test(name)) {
return true;
}
const suggested = name
.trim()
.toLowerCase()
.replace(/\s+/g, '-')
.replace(/^[._]/, '')
.replace(/[^a-z0-9-~]+/g, '-');
return `Invalid package.json name. Try ${suggested} instead.`;
}