bunli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,247 @@
1
+ # bunli
2
+
3
+ The Bunli CLI toolchain for developing, building, and distributing CLI applications.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ bun add -g bunli
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Development
14
+
15
+ Run your CLI in development mode with hot reloading:
16
+
17
+ ```bash
18
+ bunli dev
19
+
20
+ # With custom entry file
21
+ bunli dev --entry src/mycli.ts
22
+
23
+ # Enable debugging
24
+ bunli dev --inspect
25
+
26
+ # Custom debug port
27
+ bunli dev --inspect --port 9230
28
+
29
+ # Pass arguments to your CLI
30
+ bunli dev -- --help
31
+ ```
32
+
33
+ Development options:
34
+ - `--entry, -e` - Entry file (defaults to auto-detect)
35
+ - `--watch, -w` - Watch for changes (default: true)
36
+ - `--inspect, -i` - Enable debugger
37
+ - `--port, -p` - Debugger port (default: 9229)
38
+
39
+ ### Building
40
+
41
+ Build your CLI for production:
42
+
43
+ ```bash
44
+ # Traditional build (requires Bun runtime)
45
+ bunli build
46
+
47
+ # Build standalone executables for specific platforms
48
+ bunli build --targets darwin-arm64,linux-x64
49
+
50
+ # Build for the current platform only
51
+ bunli build --targets native
52
+
53
+ # Build for all supported platforms
54
+ bunli build --targets all
55
+ ```
56
+
57
+ ### Available Commands
58
+
59
+ - `bunli init` - Initialize a new Bunli CLI project
60
+ - `bunli dev` - Run CLI in development mode with hot reloading
61
+ - `bunli build` - Build your CLI for production
62
+ - `bunli test` - Run tests with Bun test runner
63
+ - `bunli release` - Release your CLI package
64
+
65
+ ### Project Initialization
66
+
67
+ Create a new Bunli CLI project:
68
+
69
+ ```bash
70
+ # Interactive setup
71
+ bunli init
72
+
73
+ # With project name
74
+ bunli init my-cli
75
+
76
+ # Advanced template
77
+ bunli init my-cli --template advanced
78
+
79
+ # Specify directory
80
+ bunli init --name my-cli --dir ./projects
81
+
82
+ # Skip git/install
83
+ bunli init --no-git --no-install
84
+ ```
85
+
86
+ Init options:
87
+ - `--name, -n` - Project name
88
+ - `--template, -t` - Project template (basic/advanced/monorepo)
89
+ - `--dir, -d` - Directory to create project in
90
+ - `--git, -g` - Initialize git repository (default: true)
91
+ - `--install` - Install dependencies (default: true)
92
+ - `--package-manager, -p` - Package manager to use (bun/pnpm/yarn/npm)
93
+
94
+ ### Testing
95
+
96
+ Run tests for your CLI:
97
+
98
+ ```bash
99
+ # Run all tests
100
+ bunli test
101
+
102
+ # Watch mode
103
+ bunli test --watch
104
+
105
+ # Generate coverage
106
+ bunli test --coverage
107
+
108
+ # Run tests in all workspace packages
109
+ bunli test --all
110
+ ```
111
+
112
+ Test options:
113
+ - `--pattern, -p` - Test file patterns
114
+ - `--watch, -w` - Watch for changes
115
+ - `--coverage, -c` - Generate coverage report
116
+ - `--bail, -b` - Stop on first failure
117
+ - `--timeout` - Test timeout in milliseconds
118
+ - `--all` - Run tests in all packages (workspace mode)
119
+
120
+ ### Releasing
121
+
122
+ Create a release of your CLI:
123
+
124
+ ```bash
125
+ # Interactive release
126
+ bunli release
127
+
128
+ # Specific version bump
129
+ bunli release --version patch
130
+ bunli release --version minor
131
+ bunli release --version major
132
+ bunli release --version 2.0.0
133
+
134
+ # Dry run
135
+ bunli release --dry
136
+
137
+ # Release all workspace packages
138
+ bunli release --all
139
+ ```
140
+
141
+ Release options:
142
+ - `--version, -v` - Version to release (patch/minor/major/x.y.z)
143
+ - `--tag, -t` - Git tag format
144
+ - `--npm` - Publish to npm
145
+ - `--github` - Create GitHub release
146
+ - `--dry, -d` - Dry run - show what would be done
147
+ - `--all` - Release all packages (workspace mode)
148
+
149
+ ### Build Options
150
+
151
+ The `build` command supports several options:
152
+
153
+ - `--entry, -e` - Entry file (defaults to auto-detect)
154
+ - `--outdir, -o` - Output directory (default: ./dist)
155
+ - `--outfile` - Output filename (for single executable)
156
+ - `--targets, -t` - Target platforms for compilation (comma-separated)
157
+ - `--minify, -m` - Minify output (default: true)
158
+ - `--sourcemap, -s` - Generate sourcemaps
159
+ - `--bytecode` - Enable bytecode compilation (experimental)
160
+ - `--runtime, -r` - Runtime target for non-compiled builds (bun/node)
161
+ - `--watch, -w` - Watch for changes
162
+
163
+ ### Standalone Executables
164
+
165
+ Bunli creates standalone executables when you specify target platforms. This bundles your CLI application with the Bun runtime into a single binary that can run without requiring Bun to be installed.
166
+
167
+ ```bash
168
+ # Build for specific platforms
169
+ bunli build --targets darwin-arm64,linux-x64,windows-x64
170
+
171
+ # Build for current platform only
172
+ bunli build --targets native
173
+
174
+ # Build for all platforms
175
+ bunli build --targets all
176
+ ```
177
+
178
+ Supported platforms:
179
+ - `darwin-arm64` - macOS Apple Silicon
180
+ - `darwin-x64` - macOS Intel
181
+ - `linux-arm64` - Linux ARM64
182
+ - `linux-x64` - Linux x64
183
+ - `windows-x64` - Windows x64
184
+
185
+ ### Configuration
186
+
187
+ Create a `bunli.config.ts` file in your project root:
188
+
189
+ ```typescript
190
+ import { defineConfig } from 'bunli'
191
+
192
+ export default defineConfig({
193
+ name: 'my-cli',
194
+ version: '1.0.0',
195
+
196
+ build: {
197
+ entry: './src/cli.ts',
198
+ outdir: './dist',
199
+ targets: ['darwin-arm64', 'linux-x64'], // Compile for these platforms
200
+ compress: true, // Compress multi-platform builds
201
+ minify: true,
202
+ external: ['some-native-module']
203
+ },
204
+
205
+ dev: {
206
+ watch: true,
207
+ inspect: false
208
+ }
209
+ })
210
+ ```
211
+
212
+ ### Build Behavior
213
+
214
+ The build system works as follows:
215
+
216
+ 1. **No targets specified** → Traditional JavaScript build
217
+ - Creates bundled `.js` files with shebangs
218
+ - Requires Bun (or Node.js) runtime to execute
219
+ - Supports multiple entry points
220
+
221
+ 2. **Targets specified** → Standalone executables
222
+ - Creates native binaries with embedded Bun runtime
223
+ - No runtime dependencies required
224
+ - Single entry point only
225
+ - Platform-specific subdirectories for multiple targets
226
+
227
+ ## Development
228
+
229
+ To work on Bunli itself:
230
+
231
+ ```bash
232
+ # Install dependencies
233
+ bun install
234
+
235
+ # Run in development
236
+ bun run dev
237
+
238
+ # Build
239
+ bun run build
240
+
241
+ # Run tests
242
+ bun test
243
+ ```
244
+
245
+ ## License
246
+
247
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env bun
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env bun
2
+ // @bun
3
+ var U0=Object.defineProperty;var F=(B,L)=>{for(var O in L)U0(B,O,{get:L[O],enumerable:!0,configurable:!0,set:(I)=>L[O]=()=>I})};var x=(B,L)=>()=>(B&&(L=B(B=0)),L);import{z as K}from"zod";import X0 from"path";import{existsSync as Y0}from"fs";async function J(B=process.cwd()){for(let L of j0){let O=X0.join(B,L);if(Y0(O))try{let I=await import(O),q=I.default||I;return Z0.parse(q)}catch(I){throw console.error(`Error loading config from ${O}:`,I),I}}return{}}var Z0,j0;var T=x(()=>{Z0=K.object({name:K.string().optional(),version:K.string().optional(),description:K.string().optional(),commands:K.object({manifest:K.string().optional(),directory:K.string().optional()}).optional(),build:K.object({entry:K.string().or(K.array(K.string())).optional(),outdir:K.string().optional(),targets:K.array(K.string()).optional(),compress:K.boolean().optional(),external:K.array(K.string()).optional(),minify:K.boolean().optional(),sourcemap:K.boolean().optional()}).optional(),dev:K.object({watch:K.boolean().optional(),inspect:K.boolean().optional(),port:K.number().optional()}).optional(),test:K.object({pattern:K.string().or(K.array(K.string())).optional(),coverage:K.boolean().optional(),watch:K.boolean().optional()}).optional(),release:K.object({npm:K.boolean().optional(),github:K.boolean().optional(),tagFormat:K.string().optional(),conventionalCommits:K.boolean().optional()}).optional(),workspace:K.object({packages:K.array(K.string()).optional(),shared:K.any().optional(),versionStrategy:K.enum(["fixed","independent"]).optional()}).optional()}),j0=["bunli.config.ts","bunli.config.js","bunli.config.mjs"]});import{existsSync as p}from"fs";import c from"path";async function h(B=process.cwd()){for(let O of E0){let I=c.join(B,O);if(p(I))return O}let L=c.join(B,"package.json");if(p(L))try{let O=await Bun.file(L).json();if(O.bin){if(typeof O.bin==="string")return O.bin;else if(typeof O.bin==="object"){let I=Object.values(O.bin)[0];if(typeof I==="string")return I}}}catch{}return}var E0;var u=x(()=>{E0=["src/cli.ts","src/index.ts","src/main.ts","cli.ts","index.ts","main.ts","src/cli.js","src/index.js","src/main.js","cli.js","index.js","main.js"]});var f={};F(f,{default:()=>W0});import{defineCommand as H0,option as k}from"@bunli/core";import{z as m}from"zod";import{spawn as J0}from"child_process";var W0;var t=x(()=>{T();u();W0=H0({name:"dev",description:"Run your CLI in development mode with hot reload",alias:"d",options:{entry:k(m.string().optional(),{short:"e",description:"Entry file (defaults to auto-detect)"}),watch:k(m.boolean().default(!0),{short:"w",description:"Watch for changes"}),inspect:k(m.boolean().default(!1),{short:"i",description:"Enable debugger"}),port:k(m.number().int().min(1).max(65535).optional(),{short:"p",description:"Debugger port"})},handler:async({flags:B,positional:L,spinner:O,colors:I})=>{let q=await J(),M=B.entry||q.build?.entry||await h();if(!M)console.error(I.red("No entry file found. Please specify with --entry or in bunli.config.ts")),process.exit(1);let Q=Array.isArray(M)?M[0]:M;if(!Q)console.error(I.red("Entry file is required")),process.exit(1);let Y=["run"];if(B.watch??q.dev?.watch??!0)Y.push("--hot");if(B.inspect??q.dev?.inspect){let U=B.port||q.dev?.port||9229;Y.push(`--inspect=${U}`)}if(Y.push(Q),L.length>0)Y.push("--",...L);console.log(I.cyan("Starting dev server...")),console.log(I.dim(`> bun ${Y.join(" ")}`)),console.log(),J0("bun",Y,{stdio:"inherit",env:{...process.env,NODE_ENV:"development"}}).on("exit",(U)=>{process.exit(U||0)})}})});var i={};F(i,{default:()=>R0});import{defineCommand as _0,option as _}from"@bunli/core";import{z as R}from"zod";var{$:G}=globalThis.Bun;import $ from"path";var R0;var n=x(()=>{T();u();R0=_0({name:"build",description:"Build your CLI for production",alias:"b",options:{entry:_(R.string().optional(),{short:"e",description:"Entry file (defaults to auto-detect)"}),outdir:_(R.string().optional(),{short:"o",description:"Output directory"}),outfile:_(R.string().optional(),{description:"Output filename (for single executable)"}),minify:_(R.boolean().optional(),{short:"m",description:"Minify output"}),sourcemap:_(R.boolean().optional(),{short:"s",description:"Generate sourcemaps"}),bytecode:_(R.boolean().default(!1),{description:"Enable bytecode compilation (experimental)"}),runtime:_(R.enum(["bun","node"]).optional(),{short:"r",description:"Runtime target (for non-compiled builds)"}),targets:_(R.string().optional().transform((B)=>{if(!B)return;return B.split(",").map((L)=>L.trim())}),{short:"t",description:"Target platforms for compilation (e.g., darwin-arm64,linux-x64)"}),watch:_(R.boolean().default(!1),{short:"w",description:"Watch for changes"})},handler:async({flags:B,spinner:L,colors:O})=>{let I=await J(),q=B.entry||I.build?.entry||await h();if(!q)console.error(O.red("No entry file found. Please specify with --entry or in bunli.config.ts")),process.exit(1);let M=B.targets||I.build?.targets,Q=M&&M.length>0;if(Q&&Array.isArray(q))console.error(O.red("Compiled builds only support a single entry file")),process.exit(1);let Y=Array.isArray(q)?q[0]:q;if(!Y)console.error(O.red("Entry file is undefined")),process.exit(1);let Z=B.outdir||I.build?.outdir||"./dist",U=L("Building CLI...");U.start();try{if(await G`rm -rf ${Z}`,await G`mkdir -p ${Z}`,Q){U.update("Compiling to standalone executable...");let X=[];if(M.includes("all"))X=["darwin-arm64","darwin-x64","linux-arm64","linux-x64","windows-x64"];else if(M.includes("native"))X=[`${process.platform}-${process.arch}`];else X=M;for(let E of X){U.update(`Compiling for ${E}...`);let W=X.length>1?$.join(Z,E):Z;await G`mkdir -p ${W}`;let y=$.extname(Y),d=y?Y.slice(0,-y.length):Y,b=$.basename(d),q0=E.includes("windows"),K0=B.outfile||$.join(W,q0?`${b}.exe`:b),V=["build",Y,"--compile","--outfile",K0,"--target",`bun-${E}`];if(B.minify??I.build?.minify??!0)V.push("--minify");if(B.sourcemap??I.build?.sourcemap??!1)V.push("--sourcemap");if(B.bytecode)V.push("--bytecode");let M0=I.build?.external||[];for(let Q0 of M0)V.push("--external",Q0);if((await G`bun ${V}`.quiet()).exitCode!==0)throw new Error(`Compilation failed for ${E}`)}if(I.build?.compress&&X.length>1){U.update("Compressing builds...");for(let E of X)await G`cd ${Z} && tar -czf ${E}.tar.gz ${E}`,await G`rm -rf ${Z}/${E}`}}else{let E={entrypoints:Array.isArray(q)?q:[q],outdir:Z,target:B.runtime||"bun",format:"esm",minify:B.minify??I.build?.minify??!0,sourcemap:B.sourcemap??I.build?.sourcemap??!1,external:I.build?.external||[]},A=await Bun.build(E);if(!A.success)throw new Error(`Build failed: ${A.logs.join("\\n")}`);for(let W of A.outputs)if(W.path.endsWith(".js")){let y=await W.text(),b=`#!/usr/bin/env ${B.runtime==="node"?"node":"bun"}
4
+ ${y}`;await Bun.write(W.path,b),await G`chmod +x ${W.path}`}}U.succeed("Build complete!");let j=await G`du -sh ${Z}`.text();console.log(O.dim(`Output size: ${j.trim()}`))}catch(j){U.fail("Build failed"),console.error(O.red(j instanceof Error?j.message:String(j))),process.exit(1)}}})});var a={};F(a,{default:()=>S0});import{defineCommand as G0,option as P}from"@bunli/core";import{z as N}from"zod";import{spawn as N0}from"child_process";import{readdir as x0}from"fs/promises";import{existsSync as g}from"fs";import e from"path";async function l(B,L,O){return new Promise((I,q)=>{let M=["test"],Q=L.pattern||O.test?.pattern||"**/*.test.ts",Y=Array.isArray(Q)?Q:[Q];if(M.push(...Y),L.watch??O.test?.watch)M.push("--watch");if(L.coverage??O.test?.coverage)M.push("--coverage");if(L.bail)M.push("--bail");if(L.timeout)M.push("--timeout",L.timeout.toString());let Z=N0("bun",M,{cwd:B,stdio:["inherit","pipe","pipe"],env:{...process.env,NODE_ENV:"test"}}),U="",j="";Z.stdout?.on("data",(X)=>{U+=X.toString(),process.stdout.write(X)}),Z.stderr?.on("data",(X)=>{j+=X.toString(),process.stderr.write(X)}),Z.on("exit",(X)=>{let E=(U.match(/\u2713/g)||[]).length,A=(U.match(/\u2717/g)||[]).length,W=(U.match(/\u229D/g)||[]).length;I({success:X===0,passed:E,failed:A,skipped:W})}),Z.on("error",q)})}async function A0(B){if(B.endsWith("/*")){let L=B.slice(0,-2);if(g(L))return(await x0(L,{withFileTypes:!0})).filter((I)=>I.isDirectory()&&g(e.join(L,I.name,"package.json"))).map((I)=>e.join(L,I.name))}return[]}var S0;var r=x(()=>{T();S0=G0({name:"test",description:"Run tests for your CLI",alias:"t",options:{pattern:P(N.string().or(N.array(N.string())).optional(),{short:"p",description:"Test file patterns"}),watch:P(N.boolean().default(!1),{short:"w",description:"Watch for changes"}),coverage:P(N.boolean().default(!1),{short:"c",description:"Generate coverage report"}),bail:P(N.boolean().default(!1),{short:"b",description:"Stop on first failure"}),timeout:P(N.number().int().positive().optional(),{description:"Test timeout in milliseconds"}),all:P(N.boolean().default(!1),{description:"Run tests in all packages (workspace mode)"})},handler:async({flags:B,positional:L,spinner:O,colors:I})=>{let q=await J();if(B.all&&q.workspace?.packages){let M=q.workspace.packages,Q=!0;for(let Y of M){let Z=await A0(Y);for(let U of Z){let j=O(`Testing ${U}...`);j.start();try{if((await l(U,B,q)).success)j.succeed(`${U} tests passed`);else if(j.fail(`${U} tests failed`),Q=!1,B.bail)break}catch(X){if(j.fail(`${U} tests failed`),console.error(I.red(X instanceof Error?X.message:String(X))),Q=!1,B.bail)break}}if(!Q&&B.bail)break}if(!Q)process.exit(1)}else{let M=O("Running tests...");M.start();try{let Q=await l(".",B,q);if(Q.success){if(M.succeed("All tests passed!"),console.log(I.green(`\u2713 ${Q.passed} tests passed`)),Q.skipped>0)console.log(I.yellow(`\u229D ${Q.skipped} tests skipped`))}else M.fail("Tests failed"),console.log(I.red(`\u2717 ${Q.failed} tests failed`)),process.exit(1)}catch(Q){M.fail("Tests failed"),console.error(I.red(Q instanceof Error?Q.message:String(Q))),process.exit(1)}}}})});var o={};F(o,{default:()=>P0});import{defineCommand as T0,option as w}from"@bunli/core";import{z as S}from"zod";var{$:H}=globalThis.Bun;async function w0(B,L,O,I,q){let M=await z(),Q=M.version||"0.0.0",Y=await D0(B.version,Q,O);if(console.log(q.bold(`Releasing ${M.name||"CLI"}`)),console.log(q.dim(` Current: ${Q}`)),console.log(q.dim(` New: ${Y}`)),console.log(),!B.dry){if(!await O.confirm("Continue with release?",{default:!0})){console.log(q.yellow("Release cancelled"));return}}let Z=[{name:"Running tests",cmd:()=>H`bun test`},{name:"Building project",cmd:()=>H`bun run build`},{name:"Updating version",cmd:()=>V0(Y)},{name:"Creating git tag",cmd:()=>F0(Y,L,B)},{name:"Publishing to npm",cmd:()=>$0(B,L)},{name:"Creating GitHub release",cmd:()=>v0(Y,B,L)}];for(let U of Z){if(U.name.includes("npm")&&!(B.npm??L.release?.npm??!0))continue;if(U.name.includes("GitHub")&&!(B.github??L.release?.github??!0))continue;let j=I(U.name);j.start();try{if(!B.dry)await U.cmd();j.succeed(U.name)}catch(X){if(j.fail(U.name),console.error(q.red(X instanceof Error?X.message:String(X))),!B.dry)process.exit(1)}}if(console.log(),console.log(q.green(`\u2728 Released ${M.name||"CLI"} v${Y}!`)),B.github??L.release?.github??!0)console.log(q.dim(`GitHub: https://github.com/${await s()}/releases/tag/v${Y}`));if(B.npm??L.release?.npm??!0)console.log(q.dim(`NPM: https://npmjs.com/package/${M.name}`))}async function C0(B,L,O,I,q){if(console.log(q.bold("Workspace Release")),L.workspace?.versionStrategy==="independent")console.log("Using independent versioning...");else console.log("Using fixed versioning...")}async function z(){return await Bun.file("package.json").json()}async function D0(B,L,O){if(B)if(["patch","minor","major"].includes(B))return v(L,B);else return B;let I=await O.select("Select version bump:",{choices:[{name:`patch (${v(L,"patch")})`,value:"patch"},{name:`minor (${v(L,"minor")})`,value:"minor"},{name:`major (${v(L,"major")})`,value:"major"},{name:"custom",value:"custom"}]});if(I==="custom")return await O("Enter version:");return v(L,I)}function v(B,L){let O=B.split(".").map(Number),[I=0,q=0,M=0]=O;switch(L){case"patch":return`${I}.${q}.${M+1}`;case"minor":return`${I}.${q+1}.0`;case"major":return`${I+1}.0.0`}}async function V0(B){let L=await z();L.version=B,await Bun.write("package.json",JSON.stringify(L,null,2)+"\\n")}async function F0(B,L,O){let q=(O.tag||L.release?.tagFormat||"v${version}").replace("${version}",B);await H`git add package.json`,await H`git commit -m "chore: release v${B}"`,await H`git tag ${q}`,await H`git push origin main --tags`}async function $0(B,L){if(!(B.npm??L.release?.npm??!0))return;if((await z()).private)throw new Error("Cannot publish private package to npm");await H`npm publish`}async function v0(B,L,O){if(!(L.github??O.release?.github??!0))return;let I=`v${B}`,q=await s();try{await H`gh --version`.quiet()}catch{console.warn("GitHub CLI not found, skipping GitHub release");return}await H`gh release create ${I} --title "Release ${I}" --generate-notes`}async function s(){return(await H`git remote get-url origin`.text()).match(/github\.com[:/]([^\s/]+\/[^\s/]+?)(?:\.git)?(?:\s|$)/)?.[1]??"unknown/repo"}var P0;var B0=x(()=>{T();P0=T0({name:"release",description:"Create a release of your CLI",alias:"r",options:{version:w(S.enum(["patch","minor","major"]).or(S.string()).optional(),{short:"v",description:"Version to release (patch/minor/major/x.y.z)"}),tag:w(S.string().optional(),{short:"t",description:"Git tag format"}),npm:w(S.boolean().optional(),{description:"Publish to npm"}),github:w(S.boolean().optional(),{description:"Create GitHub release"}),dry:w(S.boolean().default(!1),{short:"d",description:"Dry run - show what would be done"}),all:w(S.boolean().default(!1),{description:"Release all packages (workspace mode)"})},handler:async({flags:B,prompt:L,spinner:O,colors:I})=>{let q=await J();try{if((await H`git status --porcelain`.text()).trim()&&!B.dry)console.error(I.red("Working directory is not clean. Please commit or stash changes first.")),process.exit(1)}catch{console.error(I.red("Not a git repository")),process.exit(1)}if(B.all&&q.workspace?.packages)await C0(B,q,L,O,I);else await w0(B,q,L,O,I)}})});var I0={};F(I0,{default:()=>h0});import{defineCommand as y0,option as C}from"@bunli/core";import{z as D}from"zod";import{spawn as b0}from"child_process";var h0;var L0=x(()=>{h0=y0({name:"init",description:"Initialize a new Bunli CLI project",alias:"i",options:{name:C(D.string().optional(),{short:"n",description:"Project name"}),template:C(D.enum(["basic","advanced","monorepo"]).default("basic"),{short:"t",description:"Project template"}),dir:C(D.string().optional(),{short:"d",description:"Directory to create project in"}),git:C(D.boolean().default(!0),{short:"g",description:"Initialize git repository"}),install:C(D.boolean().default(!0),{description:"Install dependencies"}),"package-manager":C(D.enum(["bun","pnpm","yarn","npm"]).default("bun"),{short:"p",description:"Package manager to use"})},handler:async({flags:B,positional:L,colors:O})=>{console.log(O.cyan("\uD83D\uDE80 Creating new Bunli CLI project...")),console.log();let I=["create-bunli"];if(L[0])I.push(L[0]);else if(B.name)I.push(B.name);if(B.template!=="basic")I.push("--template",B.template);if(B.dir)I.push("--dir",B.dir);if(!B.git)I.push("--no-git");if(!B.install)I.push("--no-install");if(B["package-manager"]!=="bun")I.push("--package-manager",B["package-manager"]);console.log(O.dim(`> bunx ${I.join(" ")}`)),console.log();let q=b0("bunx",I,{stdio:"inherit",env:process.env});q.on("exit",(M)=>{if(M===0){console.log(),console.log(O.green("\uD83C\uDF89 Project created successfully!")),console.log(),console.log("Next steps:");let Q=L[0]||B.name||"your-project";console.log(O.gray(` cd ${Q}`)),console.log(O.gray(" bunli dev"))}else console.error(O.red("Failed to create project")),process.exit(M||1)}),q.on("error",(M)=>{console.error(O.red("Failed to run create-bunli:"),M.message),console.log(),console.log("Make sure create-bunli is available:"),console.log(O.gray(" bunx create-bunli --help")),process.exit(1)})}})});T();import{createCLI as k0}from"@bunli/core";var O0=k0({name:"bunli",version:"0.1.0",description:"The Bunli CLI toolchain for developing, building, and distributing CLIs"}),GB=await J();await O0.load({dev:()=>Promise.resolve().then(() => (t(),f)),build:()=>Promise.resolve().then(() => (n(),i)),test:()=>Promise.resolve().then(() => (r(),a)),release:()=>Promise.resolve().then(() => (B0(),o)),init:()=>Promise.resolve().then(() => (L0(),I0))});await O0.run();
@@ -0,0 +1,13 @@
1
+ import { z } from 'zod';
2
+ declare const _default: import("@bunli/core").Command<{
3
+ entry: import("@bunli/core").CLIOption<z.ZodOptional<z.ZodString>>;
4
+ outdir: import("@bunli/core").CLIOption<z.ZodOptional<z.ZodString>>;
5
+ outfile: import("@bunli/core").CLIOption<z.ZodOptional<z.ZodString>>;
6
+ minify: import("@bunli/core").CLIOption<z.ZodOptional<z.ZodBoolean>>;
7
+ sourcemap: import("@bunli/core").CLIOption<z.ZodOptional<z.ZodBoolean>>;
8
+ bytecode: import("@bunli/core").CLIOption<z.ZodDefault<z.ZodBoolean>>;
9
+ runtime: import("@bunli/core").CLIOption<z.ZodOptional<z.ZodEnum<["bun", "node"]>>>;
10
+ targets: import("@bunli/core").CLIOption<z.ZodEffects<z.ZodOptional<z.ZodString>, string[] | undefined, string | undefined>>;
11
+ watch: import("@bunli/core").CLIOption<z.ZodDefault<z.ZodBoolean>>;
12
+ }>;
13
+ export default _default;
@@ -0,0 +1,8 @@
1
+ import { z } from 'zod';
2
+ declare const _default: import("@bunli/core").Command<{
3
+ entry: import("@bunli/core").CLIOption<z.ZodOptional<z.ZodString>>;
4
+ watch: import("@bunli/core").CLIOption<z.ZodDefault<z.ZodBoolean>>;
5
+ inspect: import("@bunli/core").CLIOption<z.ZodDefault<z.ZodBoolean>>;
6
+ port: import("@bunli/core").CLIOption<z.ZodOptional<z.ZodNumber>>;
7
+ }>;
8
+ export default _default;
@@ -0,0 +1,10 @@
1
+ import { z } from 'zod';
2
+ declare const _default: import("@bunli/core").Command<{
3
+ name: import("@bunli/core").CLIOption<z.ZodOptional<z.ZodString>>;
4
+ template: import("@bunli/core").CLIOption<z.ZodDefault<z.ZodEnum<["basic", "advanced", "monorepo"]>>>;
5
+ dir: import("@bunli/core").CLIOption<z.ZodOptional<z.ZodString>>;
6
+ git: import("@bunli/core").CLIOption<z.ZodDefault<z.ZodBoolean>>;
7
+ install: import("@bunli/core").CLIOption<z.ZodDefault<z.ZodBoolean>>;
8
+ 'package-manager': import("@bunli/core").CLIOption<z.ZodDefault<z.ZodEnum<["bun", "pnpm", "yarn", "npm"]>>>;
9
+ }>;
10
+ export default _default;
@@ -0,0 +1,10 @@
1
+ import { z } from 'zod';
2
+ declare const _default: import("@bunli/core").Command<{
3
+ version: import("@bunli/core").CLIOption<z.ZodOptional<z.ZodUnion<[z.ZodEnum<["patch", "minor", "major"]>, z.ZodString]>>>;
4
+ tag: import("@bunli/core").CLIOption<z.ZodOptional<z.ZodString>>;
5
+ npm: import("@bunli/core").CLIOption<z.ZodOptional<z.ZodBoolean>>;
6
+ github: import("@bunli/core").CLIOption<z.ZodOptional<z.ZodBoolean>>;
7
+ dry: import("@bunli/core").CLIOption<z.ZodDefault<z.ZodBoolean>>;
8
+ all: import("@bunli/core").CLIOption<z.ZodDefault<z.ZodBoolean>>;
9
+ }>;
10
+ export default _default;
@@ -0,0 +1,10 @@
1
+ import { z } from 'zod';
2
+ declare const _default: import("@bunli/core").Command<{
3
+ pattern: import("@bunli/core").CLIOption<z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>>;
4
+ watch: import("@bunli/core").CLIOption<z.ZodDefault<z.ZodBoolean>>;
5
+ coverage: import("@bunli/core").CLIOption<z.ZodDefault<z.ZodBoolean>>;
6
+ bail: import("@bunli/core").CLIOption<z.ZodDefault<z.ZodBoolean>>;
7
+ timeout: import("@bunli/core").CLIOption<z.ZodOptional<z.ZodNumber>>;
8
+ all: import("@bunli/core").CLIOption<z.ZodDefault<z.ZodBoolean>>;
9
+ }>;
10
+ export default _default;
@@ -0,0 +1,175 @@
1
+ import { z } from 'zod';
2
+ export declare const bunliConfigSchema: z.ZodObject<{
3
+ name: z.ZodOptional<z.ZodString>;
4
+ version: z.ZodOptional<z.ZodString>;
5
+ description: z.ZodOptional<z.ZodString>;
6
+ commands: z.ZodOptional<z.ZodObject<{
7
+ manifest: z.ZodOptional<z.ZodString>;
8
+ directory: z.ZodOptional<z.ZodString>;
9
+ }, "strip", z.ZodTypeAny, {
10
+ manifest?: string | undefined;
11
+ directory?: string | undefined;
12
+ }, {
13
+ manifest?: string | undefined;
14
+ directory?: string | undefined;
15
+ }>>;
16
+ build: z.ZodOptional<z.ZodObject<{
17
+ entry: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
18
+ outdir: z.ZodOptional<z.ZodString>;
19
+ targets: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
20
+ compress: z.ZodOptional<z.ZodBoolean>;
21
+ external: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
22
+ minify: z.ZodOptional<z.ZodBoolean>;
23
+ sourcemap: z.ZodOptional<z.ZodBoolean>;
24
+ }, "strip", z.ZodTypeAny, {
25
+ entry?: string | string[] | undefined;
26
+ outdir?: string | undefined;
27
+ targets?: string[] | undefined;
28
+ compress?: boolean | undefined;
29
+ external?: string[] | undefined;
30
+ minify?: boolean | undefined;
31
+ sourcemap?: boolean | undefined;
32
+ }, {
33
+ entry?: string | string[] | undefined;
34
+ outdir?: string | undefined;
35
+ targets?: string[] | undefined;
36
+ compress?: boolean | undefined;
37
+ external?: string[] | undefined;
38
+ minify?: boolean | undefined;
39
+ sourcemap?: boolean | undefined;
40
+ }>>;
41
+ dev: z.ZodOptional<z.ZodObject<{
42
+ watch: z.ZodOptional<z.ZodBoolean>;
43
+ inspect: z.ZodOptional<z.ZodBoolean>;
44
+ port: z.ZodOptional<z.ZodNumber>;
45
+ }, "strip", z.ZodTypeAny, {
46
+ watch?: boolean | undefined;
47
+ inspect?: boolean | undefined;
48
+ port?: number | undefined;
49
+ }, {
50
+ watch?: boolean | undefined;
51
+ inspect?: boolean | undefined;
52
+ port?: number | undefined;
53
+ }>>;
54
+ test: z.ZodOptional<z.ZodObject<{
55
+ pattern: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
56
+ coverage: z.ZodOptional<z.ZodBoolean>;
57
+ watch: z.ZodOptional<z.ZodBoolean>;
58
+ }, "strip", z.ZodTypeAny, {
59
+ watch?: boolean | undefined;
60
+ pattern?: string | string[] | undefined;
61
+ coverage?: boolean | undefined;
62
+ }, {
63
+ watch?: boolean | undefined;
64
+ pattern?: string | string[] | undefined;
65
+ coverage?: boolean | undefined;
66
+ }>>;
67
+ release: z.ZodOptional<z.ZodObject<{
68
+ npm: z.ZodOptional<z.ZodBoolean>;
69
+ github: z.ZodOptional<z.ZodBoolean>;
70
+ tagFormat: z.ZodOptional<z.ZodString>;
71
+ conventionalCommits: z.ZodOptional<z.ZodBoolean>;
72
+ }, "strip", z.ZodTypeAny, {
73
+ npm?: boolean | undefined;
74
+ github?: boolean | undefined;
75
+ tagFormat?: string | undefined;
76
+ conventionalCommits?: boolean | undefined;
77
+ }, {
78
+ npm?: boolean | undefined;
79
+ github?: boolean | undefined;
80
+ tagFormat?: string | undefined;
81
+ conventionalCommits?: boolean | undefined;
82
+ }>>;
83
+ workspace: z.ZodOptional<z.ZodObject<{
84
+ packages: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
85
+ shared: z.ZodOptional<z.ZodAny>;
86
+ versionStrategy: z.ZodOptional<z.ZodEnum<["fixed", "independent"]>>;
87
+ }, "strip", z.ZodTypeAny, {
88
+ packages?: string[] | undefined;
89
+ shared?: any;
90
+ versionStrategy?: "fixed" | "independent" | undefined;
91
+ }, {
92
+ packages?: string[] | undefined;
93
+ shared?: any;
94
+ versionStrategy?: "fixed" | "independent" | undefined;
95
+ }>>;
96
+ }, "strip", z.ZodTypeAny, {
97
+ name?: string | undefined;
98
+ version?: string | undefined;
99
+ description?: string | undefined;
100
+ commands?: {
101
+ manifest?: string | undefined;
102
+ directory?: string | undefined;
103
+ } | undefined;
104
+ build?: {
105
+ entry?: string | string[] | undefined;
106
+ outdir?: string | undefined;
107
+ targets?: string[] | undefined;
108
+ compress?: boolean | undefined;
109
+ external?: string[] | undefined;
110
+ minify?: boolean | undefined;
111
+ sourcemap?: boolean | undefined;
112
+ } | undefined;
113
+ dev?: {
114
+ watch?: boolean | undefined;
115
+ inspect?: boolean | undefined;
116
+ port?: number | undefined;
117
+ } | undefined;
118
+ test?: {
119
+ watch?: boolean | undefined;
120
+ pattern?: string | string[] | undefined;
121
+ coverage?: boolean | undefined;
122
+ } | undefined;
123
+ release?: {
124
+ npm?: boolean | undefined;
125
+ github?: boolean | undefined;
126
+ tagFormat?: string | undefined;
127
+ conventionalCommits?: boolean | undefined;
128
+ } | undefined;
129
+ workspace?: {
130
+ packages?: string[] | undefined;
131
+ shared?: any;
132
+ versionStrategy?: "fixed" | "independent" | undefined;
133
+ } | undefined;
134
+ }, {
135
+ name?: string | undefined;
136
+ version?: string | undefined;
137
+ description?: string | undefined;
138
+ commands?: {
139
+ manifest?: string | undefined;
140
+ directory?: string | undefined;
141
+ } | undefined;
142
+ build?: {
143
+ entry?: string | string[] | undefined;
144
+ outdir?: string | undefined;
145
+ targets?: string[] | undefined;
146
+ compress?: boolean | undefined;
147
+ external?: string[] | undefined;
148
+ minify?: boolean | undefined;
149
+ sourcemap?: boolean | undefined;
150
+ } | undefined;
151
+ dev?: {
152
+ watch?: boolean | undefined;
153
+ inspect?: boolean | undefined;
154
+ port?: number | undefined;
155
+ } | undefined;
156
+ test?: {
157
+ watch?: boolean | undefined;
158
+ pattern?: string | string[] | undefined;
159
+ coverage?: boolean | undefined;
160
+ } | undefined;
161
+ release?: {
162
+ npm?: boolean | undefined;
163
+ github?: boolean | undefined;
164
+ tagFormat?: string | undefined;
165
+ conventionalCommits?: boolean | undefined;
166
+ } | undefined;
167
+ workspace?: {
168
+ packages?: string[] | undefined;
169
+ shared?: any;
170
+ versionStrategy?: "fixed" | "independent" | undefined;
171
+ } | undefined;
172
+ }>;
173
+ export type BunliConfig = z.infer<typeof bunliConfigSchema>;
174
+ export declare function loadConfig(cwd?: string): Promise<BunliConfig>;
175
+ export declare function defineConfig(config: BunliConfig): BunliConfig;
@@ -0,0 +1,3 @@
1
+ export { defineConfig, loadConfig, type BunliConfig } from './config.js';
2
+ export { findEntry } from './utils/find-entry.js';
3
+ export declare const version = "0.1.0";
package/dist/index.js ADDED
@@ -0,0 +1,119 @@
1
+ // @bun
2
+ // src/config.ts
3
+ import { z } from "zod";
4
+ import path from "path";
5
+ import { existsSync } from "fs";
6
+ var bunliConfigSchema = z.object({
7
+ name: z.string().optional(),
8
+ version: z.string().optional(),
9
+ description: z.string().optional(),
10
+ commands: z.object({
11
+ manifest: z.string().optional(),
12
+ directory: z.string().optional()
13
+ }).optional(),
14
+ build: z.object({
15
+ entry: z.string().or(z.array(z.string())).optional(),
16
+ outdir: z.string().optional(),
17
+ targets: z.array(z.string()).optional(),
18
+ compress: z.boolean().optional(),
19
+ external: z.array(z.string()).optional(),
20
+ minify: z.boolean().optional(),
21
+ sourcemap: z.boolean().optional()
22
+ }).optional(),
23
+ dev: z.object({
24
+ watch: z.boolean().optional(),
25
+ inspect: z.boolean().optional(),
26
+ port: z.number().optional()
27
+ }).optional(),
28
+ test: z.object({
29
+ pattern: z.string().or(z.array(z.string())).optional(),
30
+ coverage: z.boolean().optional(),
31
+ watch: z.boolean().optional()
32
+ }).optional(),
33
+ release: z.object({
34
+ npm: z.boolean().optional(),
35
+ github: z.boolean().optional(),
36
+ tagFormat: z.string().optional(),
37
+ conventionalCommits: z.boolean().optional()
38
+ }).optional(),
39
+ workspace: z.object({
40
+ packages: z.array(z.string()).optional(),
41
+ shared: z.any().optional(),
42
+ versionStrategy: z.enum(["fixed", "independent"]).optional()
43
+ }).optional()
44
+ });
45
+ var CONFIG_NAMES = [
46
+ "bunli.config.ts",
47
+ "bunli.config.js",
48
+ "bunli.config.mjs"
49
+ ];
50
+ async function loadConfig(cwd = process.cwd()) {
51
+ for (const configName of CONFIG_NAMES) {
52
+ const configPath = path.join(cwd, configName);
53
+ if (existsSync(configPath)) {
54
+ try {
55
+ const module = await import(configPath);
56
+ const config = module.default || module;
57
+ return bunliConfigSchema.parse(config);
58
+ } catch (error) {
59
+ console.error(`Error loading config from ${configPath}:`, error);
60
+ throw error;
61
+ }
62
+ }
63
+ }
64
+ return {};
65
+ }
66
+ function defineConfig(config) {
67
+ return config;
68
+ }
69
+ // src/utils/find-entry.ts
70
+ import { existsSync as existsSync2 } from "fs";
71
+ import path2 from "path";
72
+ var COMMON_ENTRIES = [
73
+ "src/cli.ts",
74
+ "src/index.ts",
75
+ "src/main.ts",
76
+ "cli.ts",
77
+ "index.ts",
78
+ "main.ts",
79
+ "src/cli.js",
80
+ "src/index.js",
81
+ "src/main.js",
82
+ "cli.js",
83
+ "index.js",
84
+ "main.js"
85
+ ];
86
+ async function findEntry(cwd = process.cwd()) {
87
+ for (const entry of COMMON_ENTRIES) {
88
+ const fullPath = path2.join(cwd, entry);
89
+ if (existsSync2(fullPath)) {
90
+ return entry;
91
+ }
92
+ }
93
+ const pkgPath = path2.join(cwd, "package.json");
94
+ if (existsSync2(pkgPath)) {
95
+ try {
96
+ const pkg = await Bun.file(pkgPath).json();
97
+ if (pkg.bin) {
98
+ if (typeof pkg.bin === "string") {
99
+ return pkg.bin;
100
+ } else if (typeof pkg.bin === "object") {
101
+ const firstBin = Object.values(pkg.bin)[0];
102
+ if (typeof firstBin === "string") {
103
+ return firstBin;
104
+ }
105
+ }
106
+ }
107
+ } catch {}
108
+ }
109
+ return;
110
+ }
111
+
112
+ // src/index.ts
113
+ var version = "0.1.0";
114
+ export {
115
+ version,
116
+ loadConfig,
117
+ findEntry,
118
+ defineConfig
119
+ };
@@ -0,0 +1 @@
1
+ export declare function findEntry(cwd?: string): Promise<string | undefined>;
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "bunli",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "The Bunli CLI toolchain for developing, building, and distributing CLIs",
6
+ "bin": {
7
+ "bunli": "./dist/cli.js"
8
+ },
9
+ "module": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "import": "./dist/index.js",
14
+ "types": "./dist/index.d.ts"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "author": "Arya Labs, Inc.",
21
+ "license": "MIT",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/AryaLabsHQ/bunli.git",
25
+ "directory": "packages/cli"
26
+ },
27
+ "bugs": {
28
+ "url": "https://github.com/AryaLabsHQ/bunli/issues"
29
+ },
30
+ "homepage": "https://github.com/AryaLabsHQ/bunli#readme",
31
+ "keywords": [
32
+ "bunli",
33
+ "cli",
34
+ "toolchain",
35
+ "bun",
36
+ "typescript",
37
+ "build-tool",
38
+ "development"
39
+ ],
40
+ "scripts": {
41
+ "dev": "bun run src/cli.ts",
42
+ "build": "bun run scripts/build.ts && bun run tsc",
43
+ "build:standalone": "bun run scripts/build.ts --compile",
44
+ "build:binaries": "bun run scripts/release-binaries.ts",
45
+ "test": "bun test",
46
+ "type-check": "tsc --noEmit",
47
+ "prepublishOnly": "bun run build"
48
+ },
49
+ "dependencies": {
50
+ "@bunli/core": "0.1.0",
51
+ "@bunli/utils": "0.1.0",
52
+ "glob": "^11.0.0",
53
+ "zod": "^3.24.1"
54
+ },
55
+ "devDependencies": {
56
+ "@types/bun": "latest",
57
+ "bun-types": "latest",
58
+ "typescript": "^5.8.0"
59
+ }
60
+ }