Skip to content

Commit

Permalink
feat(create): generate project from boilerplate
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Feb 21, 2022
1 parent 673e6db commit a34904b
Show file tree
Hide file tree
Showing 9 changed files with 36 additions and 157 deletions.
5 changes: 4 additions & 1 deletion packages/create/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,15 @@
"koishi"
],
"devDependencies": {
"@types/cross-spawn": "^6.0.2"
"@types/cross-spawn": "^6.0.2",
"@types/tar": "^6.1.1"
},
"dependencies": {
"axios": "^0.24.0",
"cross-spawn": "^7.0.3",
"kleur": "^4.1.4",
"prompts": "^2.4.2",
"tar": "^6.1.11",
"yargs-parser": "^21.0.0"
}
}
100 changes: 24 additions & 76 deletions packages/create/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@

import parse from 'yargs-parser'
import prompts from 'prompts'
import { blue, bold, dim, green, yellow } from 'kleur'
import { basename, join, relative } from 'path'
import spawn from 'cross-spawn'
import axios from 'axios'
import { blue, bold, dim, green, red, yellow } from 'kleur'
import { basename, join, relative } from 'path'
import { extract } from 'tar'
import * as fs from 'fs'

let project: string
let rootDir: string

const cwd = process.cwd()
const tempDir = join(__dirname, '..', 'template')
const meta = require(join(tempDir, 'package.json'))

const argv = parse(process.argv.slice(2), {
alias: {
Expand Down Expand Up @@ -41,7 +41,7 @@ async function getName() {
const { name } = await prompts({
type: 'text',
name: 'name',
message: 'Project Name:',
message: 'Project name:',
initial: 'koishi-app',
})
return name.trim() as string
Expand All @@ -60,20 +60,6 @@ function emptyDir(root: string) {
}
}

function copy(src: string, dest: string) {
const stat = fs.statSync(src)
if (!stat.isDirectory()) {
fs.copyFileSync(src, dest)
} else {
fs.mkdirSync(dest, { recursive: true })
for (const file of fs.readdirSync(src)) {
const srcFile = join(src, file)
const destFile = join(dest, file)
copy(srcFile, destFile)
}
}
}

async function confirm(message: string) {
const { yes } = await prompts({
type: 'confirm',
Expand Down Expand Up @@ -101,68 +87,31 @@ async function prepare() {
emptyDir(rootDir)
}

interface CompilerOptions {
dependencies: string[]
register: string
}

const compilers: Record<string, CompilerOptions> = {
'tsc': {
dependencies: ['ts-node'],
register: 'ts-node/register/transpile-only',
},
'esbuild': {
dependencies: ['esbuild', 'esbuild-register'],
register: 'esbuild-register',
},
}

const devDeps: string[] = []

const files: (string | [string, string])[] = [
['_gitignore', '.gitignore'],
'koishi.config.yml',
]

async function getCompiler() {
const keys = ['', ...Object.keys(compilers)]
const { name } = await prompts({
type: 'select',
name: 'name',
message: 'Choose a typescript compiler:',
choices: keys.map(value => ({ title: value || 'none', value })),
})

if (!name) {
files.push(['src-js', 'src'])
return
}

files.push('src', 'tsconfig.json')
const compiler = compilers[name]
devDeps.push('typescript', ...compiler.dependencies)
meta.scripts.start += ' -- -r ' + compiler.register
}

async function scaffold() {
console.log(dim(' Scaffolding project in ') + project + dim(' ...'))

for (const name of files) {
const [src, dest] = typeof name === 'string' ? [name, name] : name
copy(join(tempDir, src), join(rootDir, dest))
}
const mirror = process.env.GITHUB_MIRROR || 'https://hub.fastgit.xyz'
const url = `${mirror}/koishijs/boilerplate/archive/refs/heads/master.tar.gz`

for (const key in meta.devDependencies) {
if (!devDeps.includes(key)) {
delete meta.devDependencies[key]
}
try {
const { data } = await axios.get<NodeJS.ReadableStream>(url, { responseType: 'stream' })

await new Promise<void>((resolve, reject) => {
const stream = data.pipe(extract({ cwd: rootDir, newer: true, strip: 1 }))
stream.on('finish', resolve)
stream.on('error', reject)
})
} catch (err) {
if (!axios.isAxiosError(err) || !err.response) throw err
const { status, statusText } = err.response
console.log(`${red('error')} request failed with status code ${status} ${statusText}`)
process.exit(1)
}

// place "name" on the top of package.json
fs.writeFileSync(join(rootDir, 'package.json'), JSON.stringify({
name: project,
...meta,
}, null, 2))
const filename = join(rootDir, 'package.json')
const meta = require(filename)
meta.name = project
fs.writeFileSync(filename, JSON.stringify(meta, null, 2))

console.log(green(' Done.\n'))
}
Expand Down Expand Up @@ -210,7 +159,6 @@ async function start() {
project = basename(rootDir)

await prepare()
await getCompiler()
await scaffold()
await install()
}
Expand Down
5 changes: 0 additions & 5 deletions packages/create/template/_gitignore

This file was deleted.

11 changes: 0 additions & 11 deletions packages/create/template/koishi.config.yml

This file was deleted.

27 changes: 0 additions & 27 deletions packages/create/template/package.json

This file was deleted.

12 changes: 0 additions & 12 deletions packages/create/template/src-js/ping.js

This file was deleted.

12 changes: 0 additions & 12 deletions packages/create/template/src/ping.ts

This file was deleted.

13 changes: 0 additions & 13 deletions packages/create/template/tsconfig.json

This file was deleted.

8 changes: 8 additions & 0 deletions packages/scripts/build/compile.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import { defineBuild } from '../../../build'

export = defineBuild(async (base, options) => {
options.plugins = [{
name: 'external library',
setup(build) {
build.onResolve({ filter: /^([@/\w-]+|.+\/utils)$/ }, (a) => ({ external: true }))
},
}]

options.entryPoints.push(base + '/src/bin.ts')
options.entryPoints.push(base + '/src/utils.ts')
})

0 comments on commit a34904b

Please sign in to comment.