create-bunli 0.2.0 → 0.4.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.
Files changed (71) hide show
  1. package/dist/cli.js +19 -3
  2. package/dist/index.js +19 -3
  3. package/dist/templates/advanced/.bunli/commands.gen.report.json +6 -0
  4. package/dist/templates/advanced/.bunli/commands.gen.ts +66 -0
  5. package/dist/templates/advanced/README.md +9 -9
  6. package/dist/templates/advanced/bunli.config.ts +4 -0
  7. package/dist/templates/advanced/package.json +3 -2
  8. package/dist/templates/advanced/src/commands/config.ts +4 -2
  9. package/dist/templates/advanced/src/commands/init.ts +6 -4
  10. package/dist/templates/advanced/src/commands/serve.ts +6 -4
  11. package/dist/templates/advanced/src/commands/validate.ts +4 -2
  12. package/dist/templates/advanced/src/index.ts +6 -6
  13. package/dist/templates/advanced/src/utils/constants.ts +1 -1
  14. package/dist/templates/advanced/template.json +9 -2
  15. package/dist/templates/basic/.bunli/commands.gen.report.json +6 -0
  16. package/dist/templates/basic/.bunli/commands.gen.ts +66 -0
  17. package/dist/templates/basic/README.md +2 -2
  18. package/dist/templates/basic/bunli.config.ts +4 -0
  19. package/dist/templates/basic/package.json +3 -2
  20. package/dist/templates/basic/src/commands/hello.ts +4 -2
  21. package/dist/templates/basic/src/index.ts +3 -3
  22. package/dist/templates/monorepo/.bunli/commands.gen.report.json +6 -0
  23. package/dist/templates/monorepo/.bunli/commands.gen.ts +66 -0
  24. package/dist/templates/monorepo/README.md +1 -1
  25. package/dist/templates/monorepo/bunli.config.ts +4 -0
  26. package/dist/templates/monorepo/package.json +2 -1
  27. package/dist/templates/monorepo/packages/cli/package.json +7 -6
  28. package/dist/templates/monorepo/packages/cli/src/index.ts +4 -4
  29. package/dist/templates/monorepo/packages/core/package.json +3 -3
  30. package/dist/templates/monorepo/packages/core/scripts/build.ts +2 -2
  31. package/dist/templates/monorepo/packages/core/src/commands/analyze.ts +5 -3
  32. package/dist/templates/monorepo/packages/core/src/commands/process.ts +5 -3
  33. package/dist/templates/monorepo/packages/core/src/index.ts +2 -2
  34. package/dist/templates/monorepo/packages/utils/package.json +2 -2
  35. package/dist/templates/monorepo/packages/utils/scripts/build.ts +1 -1
  36. package/dist/templates/monorepo/template.json +9 -2
  37. package/package.json +2 -2
  38. package/templates/advanced/.bunli/commands.gen.report.json +6 -0
  39. package/templates/advanced/.bunli/commands.gen.ts +66 -0
  40. package/templates/advanced/README.md +9 -9
  41. package/templates/advanced/bunli.config.ts +4 -0
  42. package/templates/advanced/package.json +3 -2
  43. package/templates/advanced/src/commands/config.ts +4 -2
  44. package/templates/advanced/src/commands/init.ts +6 -4
  45. package/templates/advanced/src/commands/serve.ts +6 -4
  46. package/templates/advanced/src/commands/validate.ts +4 -2
  47. package/templates/advanced/src/index.ts +6 -6
  48. package/templates/advanced/src/utils/constants.ts +1 -1
  49. package/templates/advanced/template.json +9 -2
  50. package/templates/basic/.bunli/commands.gen.report.json +6 -0
  51. package/templates/basic/.bunli/commands.gen.ts +66 -0
  52. package/templates/basic/README.md +2 -2
  53. package/templates/basic/bunli.config.ts +4 -0
  54. package/templates/basic/package.json +3 -2
  55. package/templates/basic/src/commands/hello.ts +4 -2
  56. package/templates/basic/src/index.ts +3 -3
  57. package/templates/monorepo/.bunli/commands.gen.report.json +6 -0
  58. package/templates/monorepo/.bunli/commands.gen.ts +66 -0
  59. package/templates/monorepo/README.md +1 -1
  60. package/templates/monorepo/bunli.config.ts +4 -0
  61. package/templates/monorepo/package.json +2 -1
  62. package/templates/monorepo/packages/cli/package.json +7 -6
  63. package/templates/monorepo/packages/cli/src/index.ts +4 -4
  64. package/templates/monorepo/packages/core/package.json +3 -3
  65. package/templates/monorepo/packages/core/scripts/build.ts +2 -2
  66. package/templates/monorepo/packages/core/src/commands/analyze.ts +5 -3
  67. package/templates/monorepo/packages/core/src/commands/process.ts +5 -3
  68. package/templates/monorepo/packages/core/src/index.ts +2 -2
  69. package/templates/monorepo/packages/utils/package.json +2 -2
  70. package/templates/monorepo/packages/utils/scripts/build.ts +1 -1
  71. package/templates/monorepo/template.json +9 -2
package/dist/cli.js CHANGED
@@ -95,13 +95,22 @@ async function getFilesToProcess(dir, manifest) {
95
95
  await walk(join(currentDir, entry.name), path);
96
96
  }
97
97
  } else {
98
- if (!path.match(/^(template\.json|\.template\.json|\.DS_Store|Thumbs\.db)$/)) {
98
+ if (!path.match(/^(template\.json|\.template\.json|\.DS_Store|Thumbs\.db)$/) || path === ".gitignore") {
99
99
  files.push(path);
100
100
  }
101
101
  }
102
102
  }
103
103
  }
104
104
  await walk(dir);
105
+ if (manifest?.files?.exclude) {
106
+ return files.filter((file) => {
107
+ return !manifest.files.exclude.some((pattern) => {
108
+ const regexPattern = pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*").replace(/\?/g, "[^/]");
109
+ const regex = new RegExp(`^${regexPattern}$`);
110
+ return regex.test(file);
111
+ });
112
+ });
113
+ }
105
114
  return files;
106
115
  }
107
116
  async function runPostInstallHooks(dir, hooks) {
@@ -169,9 +178,11 @@ async function createProject(options) {
169
178
  dir,
170
179
  offline,
171
180
  variables: {
172
- projectName: name,
181
+ name,
182
+ version: "0.1.0",
173
183
  description: `A CLI built with Bunli`,
174
184
  author: "",
185
+ license: "MIT",
175
186
  year: new Date().getFullYear().toString()
176
187
  }
177
188
  });
@@ -182,7 +193,12 @@ async function createProject(options) {
182
193
  try {
183
194
  await shell`cd ${dir} && git init`.quiet();
184
195
  await shell`cd ${dir} && git add .`.quiet();
185
- await shell`cd ${dir} && git commit -m "Initial commit"`.quiet();
196
+ await shell`cd ${dir} && git commit -m "feat: initialize ${name} CLI project with Bunli
197
+
198
+ - Generated using create-bunli template
199
+ - Includes basic CLI structure with commands directory
200
+ - Configured with Bunli build system and TypeScript
201
+ - Ready for development with bun run dev"`;
186
202
  gitSpin.succeed("Git repository initialized");
187
203
  } catch (error) {
188
204
  gitSpin.fail("Failed to initialize git repository");
package/dist/index.js CHANGED
@@ -89,13 +89,22 @@ async function getFilesToProcess(dir, manifest) {
89
89
  await walk(join(currentDir, entry.name), path);
90
90
  }
91
91
  } else {
92
- if (!path.match(/^(template\.json|\.template\.json|\.DS_Store|Thumbs\.db)$/)) {
92
+ if (!path.match(/^(template\.json|\.template\.json|\.DS_Store|Thumbs\.db)$/) || path === ".gitignore") {
93
93
  files.push(path);
94
94
  }
95
95
  }
96
96
  }
97
97
  }
98
98
  await walk(dir);
99
+ if (manifest?.files?.exclude) {
100
+ return files.filter((file) => {
101
+ return !manifest.files.exclude.some((pattern) => {
102
+ const regexPattern = pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*").replace(/\?/g, "[^/]");
103
+ const regex = new RegExp(`^${regexPattern}$`);
104
+ return regex.test(file);
105
+ });
106
+ });
107
+ }
99
108
  return files;
100
109
  }
101
110
  async function runPostInstallHooks(dir, hooks) {
@@ -163,9 +172,11 @@ async function createProject(options) {
163
172
  dir,
164
173
  offline,
165
174
  variables: {
166
- projectName: name,
175
+ name,
176
+ version: "0.1.0",
167
177
  description: `A CLI built with Bunli`,
168
178
  author: "",
179
+ license: "MIT",
169
180
  year: new Date().getFullYear().toString()
170
181
  }
171
182
  });
@@ -176,7 +187,12 @@ async function createProject(options) {
176
187
  try {
177
188
  await shell`cd ${dir} && git init`.quiet();
178
189
  await shell`cd ${dir} && git add .`.quiet();
179
- await shell`cd ${dir} && git commit -m "Initial commit"`.quiet();
190
+ await shell`cd ${dir} && git commit -m "feat: initialize ${name} CLI project with Bunli
191
+
192
+ - Generated using create-bunli template
193
+ - Includes basic CLI structure with commands directory
194
+ - Configured with Bunli build system and TypeScript
195
+ - Ready for development with bun run dev"`;
180
196
  gitSpin.succeed("Git repository initialized");
181
197
  } catch (error) {
182
198
  gitSpin.fail("Failed to initialize git repository");
@@ -0,0 +1,6 @@
1
+ {
2
+ "commandsParsed": 0,
3
+ "filesScanned": 0,
4
+ "skipped": [],
5
+ "names": []
6
+ }
@@ -0,0 +1,66 @@
1
+ // This file was automatically generated by Bunli.
2
+ // You should NOT make any changes in this file as it will be overwritten.
3
+
4
+ import type { Command, CLI, GeneratedOptionMeta, RegisteredCommands, CommandOptions, GeneratedCommandMeta } from '@bunli/core'
5
+ import { createGeneratedHelpers, registerGeneratedStore } from '@bunli/core'
6
+
7
+
8
+
9
+ // Narrow list of command names to avoid typeof-cycles in types
10
+ const names = [] as const
11
+ type GeneratedNames = typeof names[number]
12
+
13
+ const modules: Record<GeneratedNames, Command<any>> = {
14
+
15
+ } as const
16
+
17
+ const metadata: Record<GeneratedNames, GeneratedCommandMeta> = {
18
+
19
+ } as const
20
+
21
+ export const generated = registerGeneratedStore(createGeneratedHelpers(modules, metadata))
22
+
23
+ export const commands = generated.commands
24
+ export const commandMeta = generated.metadata
25
+
26
+ export interface GeneratedCLI {
27
+ register(cli?: CLI<any>): GeneratedCLI
28
+ list(): Array<{
29
+ name: GeneratedNames
30
+ command: (typeof modules)[GeneratedNames]
31
+ metadata: (typeof metadata)[GeneratedNames]
32
+ }>
33
+ get<Name extends GeneratedNames>(name: Name): (typeof modules)[Name]
34
+ getMetadata<Name extends GeneratedNames>(name: Name): (typeof metadata)[Name]
35
+ getFlags<Name extends keyof RegisteredCommands & string>(name: Name): CommandOptions<Name>
36
+ getFlagsMeta<Name extends GeneratedNames>(name: Name): Record<string, GeneratedOptionMeta>
37
+ withCLI(cli: CLI<any>): { execute(name: string, options: unknown): Promise<void> }
38
+ }
39
+
40
+ export const cli: GeneratedCLI = {
41
+ register: (cliInstance?: CLI<any>) => { generated.register(cliInstance); return cli },
42
+ list: () => generated.list(),
43
+ get: <Name extends GeneratedNames>(name: Name) => generated.get(name),
44
+ getMetadata: <Name extends GeneratedNames>(name: Name) => generated.getMetadata(name),
45
+ getFlags: <Name extends keyof RegisteredCommands & string>(name: Name) => generated.getFlags(name) as CommandOptions<Name>,
46
+ getFlagsMeta: <Name extends GeneratedNames>(name: Name) => generated.getFlagsMeta(name),
47
+ withCLI: (cliInstance) => generated.withCLI(cliInstance)
48
+ }
49
+
50
+ // Enhanced helper functions
51
+ export const listCommands = () => generated.list().map(c => c.name)
52
+ export const getCommandApi = <Name extends GeneratedNames>(name: Name) => generated.getMetadata(name)
53
+ export const getTypedFlags = <Name extends GeneratedNames>(name: Name) => generated.getFlags(name) as CommandOptions<Name>
54
+ export const validateCommand = <Name extends GeneratedNames>(name: Name, flags: Record<string, unknown>) => generated.validateCommand(name, flags)
55
+ export const findCommandByName = <Name extends GeneratedNames>(name: Name) => generated.findByName(name)
56
+ export const findCommandsByDescription = (searchTerm: string) => generated.findByDescription(searchTerm)
57
+ export const getCommandNames = () => generated.getCommandNames()
58
+
59
+ // Auto-register on import for zero-config usage
60
+ export default cli
61
+
62
+ // Ensure module augmentation happens on import
63
+ declare module '@bunli/core' {
64
+ // Precise key mapping without typeof cycles
65
+ interface RegisteredCommands extends Record<GeneratedNames, Command<any>> {}
66
+ }
@@ -1,4 +1,4 @@
1
- # {{projectName}}
1
+ # {{name}}
2
2
 
3
3
  {{description}}
4
4
 
@@ -6,16 +6,16 @@
6
6
 
7
7
  ```bash
8
8
  # Install globally
9
- bun add -g {{projectName}}
9
+ bun add -g {{name}}
10
10
 
11
11
  # Or use directly with bunx
12
- bunx {{projectName}} [command]
12
+ bunx {{name}} [command]
13
13
  ```
14
14
 
15
15
  ## Usage
16
16
 
17
17
  ```bash
18
- {{projectName}} <command> [options]
18
+ {{name}} <command> [options]
19
19
  ```
20
20
 
21
21
  ### Commands
@@ -24,7 +24,7 @@ bunx {{projectName}} [command]
24
24
  Initialize a new configuration file in the current directory.
25
25
 
26
26
  ```bash
27
- {{projectName}} init [options]
27
+ {{name}} init [options]
28
28
 
29
29
  Options:
30
30
  -f, --force Overwrite existing config
@@ -35,7 +35,7 @@ Options:
35
35
  Validate files against defined rules.
36
36
 
37
37
  ```bash
38
- {{projectName}} validate <files...> [options]
38
+ {{name}} validate <files...> [options]
39
39
 
40
40
  Options:
41
41
  -c, --config Path to config file
@@ -47,7 +47,7 @@ Options:
47
47
  Start a development server.
48
48
 
49
49
  ```bash
50
- {{projectName}} serve [options]
50
+ {{name}} serve [options]
51
51
 
52
52
  Options:
53
53
  -p, --port Port to listen on (default: 3000)
@@ -59,7 +59,7 @@ Options:
59
59
  Manage configuration settings.
60
60
 
61
61
  ```bash
62
- {{projectName}} config <action> [key] [value]
62
+ {{name}} config <action> [key] [value]
63
63
 
64
64
  Actions:
65
65
  get <key> Get a config value
@@ -78,7 +78,7 @@ Actions:
78
78
 
79
79
  ## Configuration
80
80
 
81
- Create a `{{projectName}}.config.js` file in your project root:
81
+ Create a `{{name}}.config.js` file in your project root:
82
82
 
83
83
  ```javascript
84
84
  export default {
@@ -5,6 +5,10 @@ export default defineConfig({
5
5
  version: '{{version}}',
6
6
  description: '{{description}}',
7
7
 
8
+ commands: {
9
+ directory: './src/commands'
10
+ },
11
+
8
12
  plugins: [],
9
13
 
10
14
  build: {
@@ -1,14 +1,15 @@
1
1
  {
2
- "name": "{{projectName}}",
2
+ "name": "{{name}}",
3
3
  "version": "0.1.0",
4
4
  "type": "module",
5
5
  "description": "{{description}}",
6
6
  "author": "{{author}}",
7
7
  "license": "{{license}}",
8
8
  "bin": {
9
- "{{projectName}}": "./dist/index.js"
9
+ "{{name}}": "./dist/index.js"
10
10
  },
11
11
  "scripts": {
12
+ "postinstall": "bunli generate",
12
13
  "dev": "bun run src/index.ts",
13
14
  "build": "bunli build",
14
15
  "test": "bun test",
@@ -2,7 +2,7 @@ import { defineCommand, option } from '@bunli/core'
2
2
  import { z } from 'zod'
3
3
  import { loadConfig, saveConfig, getConfigPath } from '../utils/config.js'
4
4
 
5
- export const configCommand = defineCommand({
5
+ const configCommand = defineCommand({
6
6
  name: 'config',
7
7
  description: 'Manage configuration',
8
8
  subcommands: [
@@ -142,4 +142,6 @@ function setNestedValue(obj: any, path: string, value: any): void {
142
142
  }
143
143
 
144
144
  current[lastKey] = value
145
- }
145
+ }
146
+
147
+ export default configCommand
@@ -2,7 +2,7 @@ import { defineCommand, option } from '@bunli/core'
2
2
  import { z } from 'zod'
3
3
  import { CONFIG_FILE_NAME, DEFAULT_CONFIG } from '../utils/constants.js'
4
4
 
5
- export const initCommand = defineCommand({
5
+ const initCommand = defineCommand({
6
6
  name: 'init',
7
7
  description: 'Initialize a new configuration file',
8
8
  options: {
@@ -55,7 +55,7 @@ export const initCommand = defineCommand({
55
55
  console.log()
56
56
  console.log('Next steps:')
57
57
  console.log(colors.gray(` 1. Edit ${CONFIG_FILE_NAME} to customize your configuration`))
58
- console.log(colors.gray(` 2. Run '{{projectName}} validate' to check your files`))
58
+ console.log(colors.gray(` 2. Run '{{name}} validate' to check your files`))
59
59
 
60
60
  } catch (error) {
61
61
  spin.fail('Failed to create config file')
@@ -89,7 +89,7 @@ function getConfigTemplate(template: 'minimal' | 'default' | 'full'): string {
89
89
  exclude: ['node_modules', 'dist', 'test'],
90
90
  }`,
91
91
 
92
- full: `import { defineConfig } from '{{projectName}}'
92
+ full: `import { defineConfig } from '{{name}}'
93
93
 
94
94
  export default defineConfig({
95
95
  // Validation rules
@@ -150,4 +150,6 @@ export default defineConfig({
150
150
  }
151
151
 
152
152
  return templates[template]
153
- }
153
+ }
154
+
155
+ export default initCommand
@@ -2,7 +2,7 @@ import { defineCommand, option } from '@bunli/core'
2
2
  import { z } from 'zod'
3
3
  import { loadConfig } from '../utils/config.js'
4
4
 
5
- export const serveCommand = defineCommand({
5
+ const serveCommand = defineCommand({
6
6
  name: 'serve',
7
7
  description: 'Start a development server',
8
8
  options: {
@@ -113,7 +113,7 @@ function getHomePage(): string {
113
113
  <!DOCTYPE html>
114
114
  <html>
115
115
  <head>
116
- <title>{{projectName}}</title>
116
+ <title>{{name}}</title>
117
117
  <style>
118
118
  body {
119
119
  font-family: system-ui, -apple-system, sans-serif;
@@ -156,7 +156,7 @@ function getHomePage(): string {
156
156
  </head>
157
157
  <body>
158
158
  <div class="container">
159
- <h1>{{projectName}}</h1>
159
+ <h1>{{name}}</h1>
160
160
  <p>{{description}}</p>
161
161
  <p><span class="status">Running</span></p>
162
162
 
@@ -173,4 +173,6 @@ function getHomePage(): string {
173
173
  </body>
174
174
  </html>
175
175
  `.trim()
176
- }
176
+ }
177
+
178
+ export default serveCommand
@@ -4,7 +4,7 @@ import { loadConfig } from '../utils/config.js'
4
4
  import { validateFiles } from '../utils/validator.js'
5
5
  import { glob } from '../utils/glob.js'
6
6
 
7
- export const validateCommand = defineCommand({
7
+ const validateCommand = defineCommand({
8
8
  name: 'validate',
9
9
  description: 'Validate files against defined rules',
10
10
  args: z.array(z.string()).min(1).describe('Files to validate'),
@@ -113,4 +113,6 @@ export const validateCommand = defineCommand({
113
113
  process.exit(1)
114
114
  }
115
115
  }
116
- })
116
+ })
117
+
118
+ export default validateCommand
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env bun
2
2
  import { createCLI } from '@bunli/core'
3
- import { initCommand } from './commands/init.js'
4
- import { validateCommand } from './commands/validate.js'
5
- import { serveCommand } from './commands/serve.js'
6
- import { configCommand } from './commands/config.js'
3
+ import initCommand from './commands/init.js'
4
+ import validateCommand from './commands/validate.js'
5
+ import serveCommand from './commands/serve.js'
6
+ import configCommand from './commands/config.js'
7
7
  import { loadConfig } from './utils/config.js'
8
8
 
9
- const cli = createCLI({
10
- name: '{{projectName}}',
9
+ const cli = await createCLI({
10
+ name: '{{name}}',
11
11
  version: '0.1.0',
12
12
  description: '{{description}}'
13
13
  })
@@ -1,4 +1,4 @@
1
- export const CONFIG_FILE_NAME = '{{projectName}}.config.js'
1
+ export const CONFIG_FILE_NAME = '{{name}}.config.js'
2
2
 
3
3
  export const DEFAULT_CONFIG = {
4
4
  rules: {},
@@ -3,7 +3,7 @@
3
3
  "description": "Advanced Bunli CLI template with multiple commands",
4
4
  "variables": [
5
5
  {
6
- "name": "projectName",
6
+ "name": "name",
7
7
  "message": "Project name",
8
8
  "type": "string",
9
9
  "default": "my-bunli-cli"
@@ -33,5 +33,12 @@
33
33
  { "label": "Unlicense", "value": "Unlicense" }
34
34
  ]
35
35
  }
36
- ]
36
+ ],
37
+ "files": {
38
+ "exclude": [
39
+ "node_modules/**",
40
+ ".git/**",
41
+ "template.json"
42
+ ]
43
+ }
37
44
  }
@@ -0,0 +1,6 @@
1
+ {
2
+ "commandsParsed": 0,
3
+ "filesScanned": 0,
4
+ "skipped": [],
5
+ "names": []
6
+ }
@@ -0,0 +1,66 @@
1
+ // This file was automatically generated by Bunli.
2
+ // You should NOT make any changes in this file as it will be overwritten.
3
+
4
+ import type { Command, CLI, GeneratedOptionMeta, RegisteredCommands, CommandOptions, GeneratedCommandMeta } from '@bunli/core'
5
+ import { createGeneratedHelpers, registerGeneratedStore } from '@bunli/core'
6
+
7
+
8
+
9
+ // Narrow list of command names to avoid typeof-cycles in types
10
+ const names = [] as const
11
+ type GeneratedNames = typeof names[number]
12
+
13
+ const modules: Record<GeneratedNames, Command<any>> = {
14
+
15
+ } as const
16
+
17
+ const metadata: Record<GeneratedNames, GeneratedCommandMeta> = {
18
+
19
+ } as const
20
+
21
+ export const generated = registerGeneratedStore(createGeneratedHelpers(modules, metadata))
22
+
23
+ export const commands = generated.commands
24
+ export const commandMeta = generated.metadata
25
+
26
+ export interface GeneratedCLI {
27
+ register(cli?: CLI<any>): GeneratedCLI
28
+ list(): Array<{
29
+ name: GeneratedNames
30
+ command: (typeof modules)[GeneratedNames]
31
+ metadata: (typeof metadata)[GeneratedNames]
32
+ }>
33
+ get<Name extends GeneratedNames>(name: Name): (typeof modules)[Name]
34
+ getMetadata<Name extends GeneratedNames>(name: Name): (typeof metadata)[Name]
35
+ getFlags<Name extends keyof RegisteredCommands & string>(name: Name): CommandOptions<Name>
36
+ getFlagsMeta<Name extends GeneratedNames>(name: Name): Record<string, GeneratedOptionMeta>
37
+ withCLI(cli: CLI<any>): { execute(name: string, options: unknown): Promise<void> }
38
+ }
39
+
40
+ export const cli: GeneratedCLI = {
41
+ register: (cliInstance?: CLI<any>) => { generated.register(cliInstance); return cli },
42
+ list: () => generated.list(),
43
+ get: <Name extends GeneratedNames>(name: Name) => generated.get(name),
44
+ getMetadata: <Name extends GeneratedNames>(name: Name) => generated.getMetadata(name),
45
+ getFlags: <Name extends keyof RegisteredCommands & string>(name: Name) => generated.getFlags(name) as CommandOptions<Name>,
46
+ getFlagsMeta: <Name extends GeneratedNames>(name: Name) => generated.getFlagsMeta(name),
47
+ withCLI: (cliInstance) => generated.withCLI(cliInstance)
48
+ }
49
+
50
+ // Enhanced helper functions
51
+ export const listCommands = () => generated.list().map(c => c.name)
52
+ export const getCommandApi = <Name extends GeneratedNames>(name: Name) => generated.getMetadata(name)
53
+ export const getTypedFlags = <Name extends GeneratedNames>(name: Name) => generated.getFlags(name) as CommandOptions<Name>
54
+ export const validateCommand = <Name extends GeneratedNames>(name: Name, flags: Record<string, unknown>) => generated.validateCommand(name, flags)
55
+ export const findCommandByName = <Name extends GeneratedNames>(name: Name) => generated.findByName(name)
56
+ export const findCommandsByDescription = (searchTerm: string) => generated.findByDescription(searchTerm)
57
+ export const getCommandNames = () => generated.getCommandNames()
58
+
59
+ // Auto-register on import for zero-config usage
60
+ export default cli
61
+
62
+ // Ensure module augmentation happens on import
63
+ declare module '@bunli/core' {
64
+ // Precise key mapping without typeof cycles
65
+ interface RegisteredCommands extends Record<GeneratedNames, Command<any>> {}
66
+ }
@@ -1,4 +1,4 @@
1
- # {{projectName}}
1
+ # {{name}}
2
2
 
3
3
  {{description}}
4
4
 
@@ -29,7 +29,7 @@ bun test
29
29
  ## Usage
30
30
 
31
31
  ```bash
32
- {{projectName}} hello --name World
32
+ {{name}} hello --name World
33
33
  ```
34
34
 
35
35
  ## Commands
@@ -5,6 +5,10 @@ export default defineConfig({
5
5
  version: '{{version}}',
6
6
  description: '{{description}}',
7
7
 
8
+ commands: {
9
+ directory: './src/commands'
10
+ },
11
+
8
12
  build: {
9
13
  entry: './src/index.ts',
10
14
  outdir: './dist',
@@ -1,13 +1,14 @@
1
1
  {
2
- "name": "{{projectName}}",
2
+ "name": "{{name}}",
3
3
  "version": "0.1.0",
4
4
  "type": "module",
5
5
  "description": "{{description}}",
6
6
  "author": "{{author}}",
7
7
  "bin": {
8
- "{{projectName}}": "./dist/index.js"
8
+ "{{name}}": "./dist/index.js"
9
9
  },
10
10
  "scripts": {
11
+ "postinstall": "bunli generate",
11
12
  "dev": "bun run src/index.ts",
12
13
  "build": "bunli build",
13
14
  "test": "bun test",
@@ -1,7 +1,7 @@
1
1
  import { defineCommand, option } from '@bunli/core'
2
2
  import { z } from 'zod'
3
3
 
4
- export const helloCommand = defineCommand({
4
+ const helloCommand = defineCommand({
5
5
  name: 'hello',
6
6
  description: 'Say hello to someone',
7
7
  options: {
@@ -26,4 +26,6 @@ export const helloCommand = defineCommand({
26
26
 
27
27
  console.log(colors.green(message))
28
28
  }
29
- })
29
+ })
30
+
31
+ export default helloCommand
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env bun
2
2
  import { createCLI } from '@bunli/core'
3
- import { helloCommand } from './commands/hello.js'
3
+ import helloCommand from './commands/hello.js'
4
4
 
5
- const cli = createCLI({
6
- name: '{{projectName}}',
5
+ const cli = await createCLI({
6
+ name: '{{name}}',
7
7
  version: '0.1.0',
8
8
  description: '{{description}}'
9
9
  })
@@ -0,0 +1,6 @@
1
+ {
2
+ "commandsParsed": 0,
3
+ "filesScanned": 0,
4
+ "skipped": [],
5
+ "names": []
6
+ }
@@ -0,0 +1,66 @@
1
+ // This file was automatically generated by Bunli.
2
+ // You should NOT make any changes in this file as it will be overwritten.
3
+
4
+ import type { Command, CLI, GeneratedOptionMeta, RegisteredCommands, CommandOptions, GeneratedCommandMeta } from '@bunli/core'
5
+ import { createGeneratedHelpers, registerGeneratedStore } from '@bunli/core'
6
+
7
+
8
+
9
+ // Narrow list of command names to avoid typeof-cycles in types
10
+ const names = [] as const
11
+ type GeneratedNames = typeof names[number]
12
+
13
+ const modules: Record<GeneratedNames, Command<any>> = {
14
+
15
+ } as const
16
+
17
+ const metadata: Record<GeneratedNames, GeneratedCommandMeta> = {
18
+
19
+ } as const
20
+
21
+ export const generated = registerGeneratedStore(createGeneratedHelpers(modules, metadata))
22
+
23
+ export const commands = generated.commands
24
+ export const commandMeta = generated.metadata
25
+
26
+ export interface GeneratedCLI {
27
+ register(cli?: CLI<any>): GeneratedCLI
28
+ list(): Array<{
29
+ name: GeneratedNames
30
+ command: (typeof modules)[GeneratedNames]
31
+ metadata: (typeof metadata)[GeneratedNames]
32
+ }>
33
+ get<Name extends GeneratedNames>(name: Name): (typeof modules)[Name]
34
+ getMetadata<Name extends GeneratedNames>(name: Name): (typeof metadata)[Name]
35
+ getFlags<Name extends keyof RegisteredCommands & string>(name: Name): CommandOptions<Name>
36
+ getFlagsMeta<Name extends GeneratedNames>(name: Name): Record<string, GeneratedOptionMeta>
37
+ withCLI(cli: CLI<any>): { execute(name: string, options: unknown): Promise<void> }
38
+ }
39
+
40
+ export const cli: GeneratedCLI = {
41
+ register: (cliInstance?: CLI<any>) => { generated.register(cliInstance); return cli },
42
+ list: () => generated.list(),
43
+ get: <Name extends GeneratedNames>(name: Name) => generated.get(name),
44
+ getMetadata: <Name extends GeneratedNames>(name: Name) => generated.getMetadata(name),
45
+ getFlags: <Name extends keyof RegisteredCommands & string>(name: Name) => generated.getFlags(name) as CommandOptions<Name>,
46
+ getFlagsMeta: <Name extends GeneratedNames>(name: Name) => generated.getFlagsMeta(name),
47
+ withCLI: (cliInstance) => generated.withCLI(cliInstance)
48
+ }
49
+
50
+ // Enhanced helper functions
51
+ export const listCommands = () => generated.list().map(c => c.name)
52
+ export const getCommandApi = <Name extends GeneratedNames>(name: Name) => generated.getMetadata(name)
53
+ export const getTypedFlags = <Name extends GeneratedNames>(name: Name) => generated.getFlags(name) as CommandOptions<Name>
54
+ export const validateCommand = <Name extends GeneratedNames>(name: Name, flags: Record<string, unknown>) => generated.validateCommand(name, flags)
55
+ export const findCommandByName = <Name extends GeneratedNames>(name: Name) => generated.findByName(name)
56
+ export const findCommandsByDescription = (searchTerm: string) => generated.findByDescription(searchTerm)
57
+ export const getCommandNames = () => generated.getCommandNames()
58
+
59
+ // Auto-register on import for zero-config usage
60
+ export default cli
61
+
62
+ // Ensure module augmentation happens on import
63
+ declare module '@bunli/core' {
64
+ // Precise key mapping without typeof cycles
65
+ interface RegisteredCommands extends Record<GeneratedNames, Command<any>> {}
66
+ }
@@ -1,4 +1,4 @@
1
- # {{projectName}}
1
+ # {{name}}
2
2
 
3
3
  {{description}}
4
4