Skip to content

Commit

Permalink
Get create command working
Browse files Browse the repository at this point in the history
  • Loading branch information
daun committed Sep 12, 2023
1 parent e3bdb1d commit 946a356
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 46 deletions.
103 changes: 57 additions & 46 deletions src/commands/create.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,24 @@
import * as fs from 'fs/promises'
import * as path from 'path'
import { join } from 'path'
import { Command, Flags } from '@oclif/core'
import chalk from 'chalk'
import { Listr } from 'listr2'
import { rimraf } from 'rimraf'
import { kebabCase, startCase, upperFirst } from 'lodash-es'

import { cloneRepo, fileExists, pascalCase } from '../util.js'
import { cloneRepo, fileExists, isDirectory, isEmptyDirectory, pascalCase } from '../util.js'

enum Type {
plugin = 'plugin',
theme = 'theme'
}

interface Names {
upper: string
pascal: string
title: string
kebab: string
short: string
full: string
title: string
}


interface Ctx {
type: Type
dir: string
Expand Down Expand Up @@ -65,46 +61,57 @@ export default class Create extends Command {
}

async run(): Promise<void> {
const { flags } = await this.parse(Create)
const { flags: { repo, ...flags } } = await this.parse(Create)

const type = Type[flags.type as keyof typeof Type]
const name = flags.name.replace(/^swup/i, '').replace(/(plugin|theme)$/i, '').trim()
const names: Names = {
upper: upperFirst(name),
pascal: pascalCase(name),
kebab: kebabCase(name),
title: startCase(name),
short: `${pascalCase(name)}${upperFirst(type)}`,
full: `Swup${pascalCase(name)}${upperFirst(type)}`,
}
const ctx: Ctx = {
type,
names,
dir: names.full,
path: path.join(process.cwd(), names.full),
repo: flags.repo
}
const names = this.generateNames(flags.name, type)
const dir = names.kebab
const path = join(process.cwd(), dir)

const ctx: Ctx = { type, names, dir, path, repo }

const tasks = [
{ title: 'Creating directory', task: this.createDirectory },
{ title: 'Cloning repository', task: this.cloneRepository },
{ title: 'Cleaning git directory', task: this.clearGitDirectory },
{ title: 'Updating package.json', task: this.updatePackageJson },
{ title: 'Updating plugin file', task: this.updatePluginFile },
{ title: 'Updating readme', task: this.updateReadme },
{ title: 'Creating directory', task: this.createDirectory.bind(this) },
{ title: 'Cloning repository', task: this.cloneRepository.bind(this) },
{ title: 'Cleaning git directory', task: this.clearGitDirectory.bind(this) },
{ title: 'Updating package.json', task: this.updatePackageJson.bind(this) },
{ title: 'Updating plugin file', task: this.updatePluginFile.bind(this) },
{ title: 'Updating readme', task: this.updateReadme.bind(this) },
]

try {
this.log(chalk`Creating {magenta ${type}} with name {green ${names.full}}...`)
await new Listr<Ctx>(tasks, { ctx }).run()
this.log(chalk`Created {green ${names.full}}`)
} catch (error) {
this.error(`${error}`)
this.log(chalk`Creating new ${type} {magenta ${names.pascal}}...`)
await new Listr<Ctx>(tasks, { ctx }).run()
this.log(chalk`Created ${type} {green ${names.pascal}}`)
}

async catch(error: Error) {
// this.error(error as Error)
throw error
}

generateNames(input: string, type: string): Names {
const base = input.replace(/^swup/i, '').replace(/(plugin|theme)$/i, '').trim()
const name = `Swup${pascalCase(base)}${upperFirst(type)}`

return {
pascal: name,
kebab: kebabCase(name),
title: startCase(name)
}
}

async createDirectory(ctx: Ctx): Promise<void> {
if (await fileExists(ctx.path)) {
throw new Error(`Directory ${ctx.dir} already exists.`)
const exists = await fileExists(ctx.path)
const dir = exists && await isDirectory(ctx.path)
const empty = dir && await isEmptyDirectory(ctx.path)
if (exists) {
if (!dir) {
throw new Error(`Unable to create directory ${ctx.dir}. A file of the same name already exists.`)
}
if (!empty) {
throw new Error(`Directory ${ctx.dir} already exists and has files in it.`)
}
return
}
try {
await fs.mkdir(ctx.path)
Expand All @@ -120,7 +127,7 @@ export default class Create extends Command {

async clearGitDirectory(ctx: Ctx): Promise<void> {
if (!ctx.path) return
await rimraf(path.join(ctx.path, '.git'))
await rimraf(join(ctx.path, '.git'))
}

async cloneRepository(ctx: Ctx): Promise<void> {
Expand All @@ -134,19 +141,19 @@ export default class Create extends Command {
}

async updatePluginFile(ctx: Ctx): Promise<void> {
const pluginPath = path.join(ctx.path, 'src/index.js')
const pluginPath = join(ctx.path, 'src/index.js')
try {
let data = await fs.readFile(pluginPath, 'utf8')
data = data.replace(/PluginName/g, ctx.names.short)
data = data.replace(/ThemeName/g, ctx.names.short)
data = data.replace(/PluginName/g, ctx.names.pascal)
data = data.replace(/ThemeName/g, ctx.names.pascal)
await fs.writeFile(pluginPath, data)
} catch (error) {
throw new Error(`Error updating plugin file: ${error}`)
}
}

async updatePackageJson(ctx: Ctx): Promise<void> {
const packagePath = path.join(ctx.path, 'package.json')
const packagePath = join(ctx.path, 'package.json')
let pckg: any
try {
pckg = JSON.parse(await fs.readFile(packagePath, 'utf8'))
Expand All @@ -155,6 +162,7 @@ export default class Create extends Command {
}

pckg.name = ctx.names.kebab
pckg.amdName = ctx.names.pascal
pckg.version = '0.0.0'
pckg.description = ''
pckg.author.name = ''
Expand All @@ -174,14 +182,17 @@ export default class Create extends Command {
}

async updateReadme(ctx: Ctx): Promise<void> {
const readmePath = path.join(ctx.path, 'readme.md')
const readmePath = join(ctx.path, 'readme.md')
try {
let data = await fs.readFile(readmePath, 'utf8')
data = data.replace(/ *\[comment\]: CLI-remove-start[\s\S]*\[comment\]: CLI-remove-end */g, '')
data = data.replace(/swup-\[(plugin-name|theme-name)\]-plugin/g, ctx.names.kebab)
data = data.replace(/swup-\[(plugin-name|theme-name)\]-(plugin|theme)/g, ctx.names.kebab)
data = data.replace(/Swup \[(Plugin Name|Theme Name)\] (Plugin|Theme)/g, ctx.names.title)
data = data.replace(/ \[(Plugin Name|Theme Name)\]/g, ctx.names.title)
data = data.replace(/Swup\[(PluginName|ThemeName)\](Plugin|Theme)/g, ctx.names.pascal)
data = data.replace(/\[(PluginName|ThemeName)\]/g, ctx.names.pascal)
data = data.replace(/(SwupNamePlugin|SwupNameTheme)/g, ctx.names.full)
data = data.replace(/(SwupNamePlugin|SwupNameTheme)/g, ctx.names.pascal)
data = `${data.trim()}\n`
await fs.writeFile(readmePath, data)
} catch (error) {
throw new Error(`Error updating readme: ${error}`)
Expand Down
19 changes: 19 additions & 0 deletions src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,25 @@ export async function fileExists(path: string): Promise<boolean> {
}
}

export async function isDirectory(path: string): Promise<boolean> {
try {
return (await fs.lstat(path)).isDirectory()
} catch (error) {
return false
}
}

export async function isEmptyDirectory(path: string): Promise<boolean> {
try {
const directory = await fs.opendir(path)
const entry = await directory.read()
await directory.close()
return entry === null
} catch (error) {
return false
}
}

export function cloneRepo(repoUrl: string, destination: string): Promise<void> {
return new Promise((resolve, reject) => {
exec(`git clone ${repoUrl} ${destination}`, (error, stdout, stderr) => {
Expand Down

0 comments on commit 946a356

Please sign in to comment.