Skip to content

Commit

Permalink
feat: add CLI
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisbbreuer committed Feb 14, 2025
1 parent cd4d835 commit a562ff9
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 5 deletions.
12 changes: 12 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,15 @@ jobs:
run: bunx changelogithub
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}

- name: Attach Binaries
uses: softprops/action-gh-release@v2
with:
files: |
bin/bunfig-linux-x64
bin/bunfig-linux-arm64
bin/bunfig-windows-x64.exe
bin/bunfig-darwin-x64
bin/bunfig-darwin-arm64
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1 change: 1 addition & 0 deletions .vscode/dictionary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ preinstall
quickfix
shikijs
socio
softprops
Solana
Spatie
stacksjs
Expand Down
35 changes: 35 additions & 0 deletions bin/cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { CAC } from 'cac'
import { version } from '../package.json'
import { defaultConfigDir, defaultGeneratedDir, generateConfigTypes } from '../src/config'

const cli = new CAC('bunfig')

// Define CLI options interface to match our core types
interface CLIOptions {
configDir?: string
generatedDir?: string
verbose?: boolean
}

cli
.command('generate', 'Generate the config types')
.option('--config-dir <path>', 'The path to the config directory')
.option('--generated-dir <path>', 'The path to the generated directory')
.option('--verbose', 'Enable verbose logging')
.example('bunfig generate --config-dir ./config --generated-dir ./src/generated')
.action(async (options?: CLIOptions) => {
if (!options?.configDir || !options.generatedDir) {
return generateConfigTypes({
configDir: options?.configDir || defaultConfigDir,
generatedDir: options?.generatedDir || defaultGeneratedDir,
})
}
})

cli.command('version', 'Show the version of the Bunfig CLI').action(() => {
console.log(version)
})

cli.version(version)
cli.help()
cli.parse()
7 changes: 7 additions & 0 deletions build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ await Bun.build({
plugins: [dts()],
})

await Bun.build({
entrypoints: ['bin/cli.ts'],
outdir: './dist',
target: 'bun',
plugins: [dts()],
})

// Read the built file
const filePath = './dist/index.js'
const content = await readFile(filePath, 'utf8')
Expand Down
14 changes: 12 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,24 @@
},
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"bin": {
"bunfig": "./bin/cli.js"
},
"files": ["README.md", "dist"],
"scripts": {
"build": "bun --bun build.ts",
"build": "bun build.ts && bun run compile",
"compile": "bun build ./bin/cli.ts --compile --minify --outfile bin/bunfig",
"compile:all": "bun run compile:linux-x64 && bun run compile:linux-arm64 && bun run compile:windows-x64 && bun run compile:darwin-x64 && bun run compile:darwin-arm64",
"compile:linux-x64": "bun build ./bin/cli.ts --compile --minify --target=bun-linux-x64 --outfile bin/bunfig-linux-x64",
"compile:linux-arm64": "bun build ./bin/cli.ts --compile --minify --target=bun-linux-arm64 --outfile bin/bunfig-linux-arm64",
"compile:windows-x64": "bun build ./bin/cli.ts --compile --minify --target=bun-windows-x64 --outfile bin/bunfig-windows-x64.exe",
"compile:darwin-x64": "bun build ./bin/cli.ts --compile --minify --target=bun-darwin-x64 --outfile bin/bunfig-darwin-x64",
"compile:darwin-arm64": "bun build ./bin/cli.ts --compile --minify --target=bun-darwin-arm64 --outfile bin/bunfig-darwin-arm64",
"lint": "bunx --bun eslint .",
"lint:fix": "bunx --bun eslint . --fix",
"fresh": "bunx rimraf node_modules/ bun.lock && bun i",
"changelog": "bunx changelogen --output CHANGELOG.md",
"prepublishOnly": "bun --bun run build",
"prepublishOnly": "bun --bun run build && bun run compile:all",
"release": "bun run changelog && bunx bumpp package.json --all",
"test": "bun test",
"dev:docs": "bun --bun vitepress dev docs",
Expand Down
11 changes: 11 additions & 0 deletions scripts/generate-config-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { configDir, generateConfigTypes, generatedDir } from '../src/config'

try {
generateConfigTypes({
configDir,
generatedDir,
})
}
catch (error) {
console.warn('Warning: Could not generate config types:', error)
}
49 changes: 46 additions & 3 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
import type { ConfigNames } from './generated/config-types'
import type { Config } from './types'
import { resolve } from 'node:path'
import { existsSync, mkdirSync, readdirSync, writeFileSync } from 'node:fs'
import { dirname, resolve } from 'node:path'
import { deepMerge } from './utils'

export async function config<T>(options: Config<T> = { defaultConfig: {} as T }): Promise<T> {
return await loadConfig(options)
export async function config<T>(
nameOrOptions: ConfigNames | Config<T> = { defaultConfig: {} as T },
): Promise<T> {
if (typeof nameOrOptions === 'string') {
const { cwd } = await import('node:process')

return await loadConfig({
name: nameOrOptions,
cwd: cwd(),
generatedDir: './generated',
configDir: './config',
defaultConfig: {} as T,
})
}

return await loadConfig(nameOrOptions)
}

/**
Expand Down Expand Up @@ -102,3 +118,30 @@ export async function loadConfig<T>({
return defaultConfig
}
}

export const defaultConfigDir: string = resolve(__dirname, '../config')
export const defaultGeneratedDir: string = resolve(__dirname, '../src/generated')

export function generateConfigTypes(options: {
configDir: string
generatedDir: string
}): void {
const configDir = resolve(__dirname, options.configDir || '../config')
const generatedDir = resolve(__dirname, options.generatedDir || '../src/generated')
const outputFile = resolve(generatedDir, 'config-types.ts')

// Create generated directory if it doesn't exist
if (!existsSync(dirname(outputFile)))
mkdirSync(dirname(outputFile), { recursive: true })

// Default to empty array if config dir doesn't exist
const files = existsSync(configDir)
? readdirSync(configDir).map(file => file.replace(/\.(ts|js)$/, ''))
: []

const content = `// Generated by bunfig
export type ConfigNames = ${files.length ? `'${files.join('\' | \'')}'` : 'string'}
`

writeFileSync(outputFile, content)
}
1 change: 1 addition & 0 deletions src/generated/config-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type ConfigNames = string
2 changes: 2 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
export interface Config<T> {
name?: string
cwd?: string
generatedDir?: string
configDir?: string
endpoint?: string
headers?: Record<string, string>
defaultConfig: T
Expand Down

0 comments on commit a562ff9

Please sign in to comment.