Skip to content

Commit

Permalink
feat(create): use @sxzz/create to download templates (#657)
Browse files Browse the repository at this point in the history
  • Loading branch information
marcusrbrown authored Dec 2, 2024
1 parent f58d2c4 commit 63b991f
Show file tree
Hide file tree
Showing 9 changed files with 289 additions and 157 deletions.
6 changes: 6 additions & 0 deletions .changeset/khaki-ducks-suffer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@bfra.me/create": minor
---

Use @sxzz/create for downloading templates

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"prettier": "3.4.1",
"publint": "0.2.12",
"rimraf": "6.0.1",
"ts-essentials": "10.0.3",
"typescript": "5.7.2"
},
"packageManager": "[email protected]",
Expand Down
28 changes: 22 additions & 6 deletions packages/create/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,47 @@
"author": "Marcus R. Brown <[email protected]>",
"type": "module",
"exports": {
".": "./dist/index.js",
"./cli": "./dist/cli.js"
".": {
"import": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
},
"./package.json": "./package.json"
},
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"bin": {
"create": "./dist/cli.js"
},
"files": [
"src",
"dist",
"!**/*.map"
],
"scripts": {
"build": "tsup",
"dev": "jiti src/cli.ts",
"prepack": "pnpm run build",
"start": "node dist/index.js",
"test": "vitest"
"test": "vitest || true"
},
"dependencies": {
"fs-extra": "11.2.0",
"yargs": "17.7.2"
"@clack/prompts": "0.8.2",
"@sxzz/create": "0.11.0",
"cac": "6.7.14",
"consola": "3.2.3"
},
"devDependencies": {
"@types/node": "22.10.1",
"@types/yargs": "17.0.33",
"memfs": "4.14.0",
"ts-essentials": "10.0.3",
"tsup": "8.3.5",
"typescript": "5.7.2",
"vitest": "2.1.6"
},
"publishConfig": {
"access": "public",
"provenance": true
}
}
116 changes: 19 additions & 97 deletions packages/create/src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,100 +1,22 @@
#!/usr/bin/env node

// This file implements the command-line interface for the create utility.

import type {ArgumentsCamelCase} from 'yargs'
import type {CreatePackageOptions} from './types.js'
import {hideBin} from 'yargs/helpers'
import yargs from 'yargs/yargs'
import cac from 'cac'
import consola from 'consola'
import {name, version} from '../package.json'
import {createPackage} from './index.js'
// const {name} = await import('../package.json', {assert: {type: 'json'}})

/**
* Implements the command-line interface for the create utility.
* This function is the entry point for the create CLI, which allows users to create new packages with various options.
*
* @returns A Promise that resolves when the CLI has completed.
*/
export const main = async (): Promise<void> => {
await yargs(hideBin(process.argv))
.usage('Usage: create <package-name> [options]')
.command(
'$0 <packageName>',
'Create a new package',
{
packageName: {
describe: 'Name of the package to create',
type: 'string',
demandOption: true,
},
template: {
alias: 't',
type: 'string',
description: 'Template to use',
default: 'default',
},
version: {
alias: 'v',
type: 'string',
description: 'Package version',
default: '1.0.0',
},
description: {
alias: 'd',
type: 'string',
description: 'Package description',
default: 'A new package',
},
author: {
type: 'string',
description: 'Author of the package',
default: '',
},
outputDir: {
alias: 'o',
type: 'string',
description: 'Output directory',
default: process.cwd(),
},
},
async (
argv: ArgumentsCamelCase<{
packageName: string
template: string
version: string
description: string
author: string
outputDir: string
}>,
) => {
const {packageName, template, version, description, author, outputDir} = argv

if (!packageName) {
console.error('Error: packageName is required.')
process.exit(1)
}

const options: CreatePackageOptions = {
template,
version,
description,
author,
outputDir,
}
const cli = cac(name)

try {
await createPackage(packageName, options)
console.log(`Package "${packageName}" has been created successfully.`)
} catch (error) {
if (error instanceof Error) {
console.error('An error occurred while creating the package:', error.message)
} else {
console.error('An unknown error occurred while creating the package')
}
process.exit(1)
}
},
)
.help()
.parse()
}
await main()
cli.command('[projectPath]', 'Create a new project').action(async (projectPath?: string) => {
try {
await createPackage({
outputDir: projectPath ?? process.cwd(),
})
console.log(`Package "${projectPath}" has been created successfully.`)
} catch (error) {
consola.error(error)
process.exit(1)
}
})
cli.help()
cli.version(version)
cli.parse()
34 changes: 13 additions & 21 deletions packages/create/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,31 @@
import type {CreatePackageOptions} from './types.js'
import fs from 'node:fs/promises'
import path from 'node:path'
import {run} from '@sxzz/create'

/**
* Creates a new package based on a specified template.
*
* @param packageName - The name of the new package.
* @param options - Options for creating the package, including the template to use, version, description, and author.
* @returns A Promise that resolves when the package has been created.
*/
export async function createPackage(
packageName: string,
options: CreatePackageOptions,
): Promise<void> {
export async function createPackage(options: CreatePackageOptions): Promise<void> {
const template = options.template || 'default'
const templateDir = path.join(import.meta.dirname, 'templates', template)
const targetDir = path.join(options.outputDir || process.cwd(), packageName)
const targetDir = options.outputDir || process.cwd()

// Create target directory
await fs.mkdir(targetDir, {recursive: true})

// Read package.json template and replace placeholders
const packageJsonTemplate = await fs.readFile(path.join(templateDir, 'package.json'), 'utf-8')
await run(targetDir, {
templates: [
{
name: 'default',
// Point to the template directory
url: `${templateDir}`,
},
],
})

const packageJsonContent = packageJsonTemplate
.replace(/{{packageName}}/g, packageName)
.replace(/{{version}}/g, options.version || '1.0.0')
.replace(/{{description}}/g, options.description || 'A new package')
.replace(/{{author}}/g, options.author || '')

await fs.writeFile(path.join(targetDir, 'package.json'), packageJsonContent)

// Copy index.ts template
const indexTsTemplate = await fs.readFile(path.join(templateDir, 'index.ts'), 'utf-8')
await fs.writeFile(path.join(targetDir, 'index.ts'), indexTsTemplate)

console.log(`Package ${packageName} created successfully.`)
console.log(`Package created successfully.`)
}
5 changes: 5 additions & 0 deletions packages/create/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import type {run} from '@sxzz/create'
import type {Prettify} from 'ts-essentials'

export type Config = Prettify<NonNullable<Parameters<typeof run>[1]>>

export interface CreatePackageOptions {
template?: string
version?: string
Expand Down
2 changes: 0 additions & 2 deletions packages/create/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
"$schema": "http://json.schemastore.org/tsconfig",
"extends": "../../tsconfig.json",
"compilerOptions": {
"module": "NodeNext",
"moduleResolution": "NodeNext",
"outDir": "./dist"
},
"include": ["src/**/*.ts"]
Expand Down
11 changes: 1 addition & 10 deletions packages/create/tsup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,10 @@ import {defineConfig} from 'tsup'

export default defineConfig([
{
entry: ['src/index.ts'],
entry: ['src/{index,cli}.ts'],
format: ['esm'],
dts: true,
sourcemap: true,
clean: true,
},
{
entry: ['src/cli.ts'],
format: ['esm'],
sourcemap: true,
clean: false,
banner: {
js: '#!/usr/bin/env node',
},
},
])
Loading

0 comments on commit 63b991f

Please sign in to comment.