@zfadhli/koko-cli 0.1.0 → 0.2.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 CHANGED
@@ -130,7 +130,7 @@ bar.increment(1, { package: "koko" });
130
130
  | `clearOnComplete` | `boolean` | `false` |
131
131
  | `stopOnComplete` | `boolean` | `false` |
132
132
 
133
- ### `createCLI(name, version?)`
133
+ ### `createCLI(name, version?, options?)`
134
134
 
135
135
  Creates an opinionated CLI application builder (wraps cac).
136
136
 
@@ -138,6 +138,10 @@ Creates an opinionated CLI application builder (wraps cac).
138
138
  - Action handlers receive `(options, ctx)` with typed options
139
139
  - `ctx` provides `.spinner()`, `.progress()`, `.color`
140
140
 
141
+ **Banner** — When a `version` is provided, a styled banner (`name v{version}`) is
142
+ automatically printed to stderr before each command action. Customize or disable
143
+ it with `.banner()`.
144
+
141
145
  ```ts
142
146
  const cli = createCLI("deploy", "1.0.0")
143
147
  .description("Deployment tool");
@@ -158,6 +162,30 @@ cli.command("build <input>", "Build project", (cmd) => {
158
162
  cli.parse();
159
163
  ```
160
164
 
165
+ #### `.banner(text?)`
166
+
167
+ Controls the startup banner shown before command actions.
168
+
169
+ | Argument | Behavior |
170
+ |----------|----------|
171
+ | _(none)_ or `true` | Default `name v{version}` (bold cyan + yellow) |
172
+ | `false` | Disable banner entirely |
173
+ | `"Custom {name} {version}"` | Custom text; `{name}` and `{version}` are substituted |
174
+
175
+ ```ts
176
+ // Disable the banner
177
+ cli.banner(false)
178
+
179
+ // Custom banner text
180
+ cli.banner("=== {name} v{version} ===")
181
+ ```
182
+
183
+ The banner can also be controlled via the third argument to `createCLI`:
184
+
185
+ ```ts
186
+ createCLI("myapp", "1.0.0", { banner: false })
187
+ ```
188
+
161
189
  ### Icons
162
190
 
163
191
  Standardized icon constants:
package/dist/index.d.mts CHANGED
@@ -67,9 +67,14 @@ interface CommandBuilder {
67
67
  action<T>(handler: CLIAction<T>): void;
68
68
  }
69
69
  type CommandSetup = (cmd: CommandBuilder) => void;
70
+ type BannerOption = string | boolean;
71
+ interface CLIOptions {
72
+ banner?: BannerOption;
73
+ }
70
74
  interface CLIBuilder {
71
75
  command(name: string, description: string, setup: CommandSetup): CLIBuilder;
72
76
  description(text: string): CLIBuilder;
77
+ banner(text?: BannerOption): CLIBuilder;
73
78
  parse(argv?: string[]): void;
74
79
  }
75
80
  //#endregion
@@ -81,6 +86,11 @@ interface CLIBuilder {
81
86
  * receives a typed options object and a `ctx` with built-in access to
82
87
  * spinner, progress bar, and colors.
83
88
  *
89
+ * When a `version` is provided, a styled banner (`name v{version}`) is
90
+ * automatically printed to stderr before every command action. Use
91
+ * `.banner(false)` to disable or `.banner("Custom {name} {version}")`
92
+ * to customize.
93
+ *
84
94
  * ```ts
85
95
  * const cli = createCLI('my-app', '1.0.0').description('My CLI')
86
96
  *
@@ -98,7 +108,7 @@ interface CLIBuilder {
98
108
  * cli.parse()
99
109
  * ```
100
110
  */
101
- declare function createCLI(name: string, version?: string): CLIBuilder;
111
+ declare function createCLI(name: string, version?: string, options?: CLIOptions): CLIBuilder;
102
112
  //#endregion
103
113
  //#region src/errors.d.ts
104
114
  declare class CliToolkitError extends Error {
@@ -158,4 +168,4 @@ declare function createProgress(options: ProgressOptions): ProgressInstance;
158
168
  */
159
169
  declare function createSpinner(text?: string, options?: SpinnerOptions): SpinnerInstance;
160
170
  //#endregion
161
- export { type CLIAction, type CLIBuilder, CliToolkitError, type ColorName, type CommandBuilder, type CommandContext, type CommandSetup, ICON_ERROR, ICON_INFO, ICON_SUCCESS, ICON_WARN, type OptionConfig, type ProgressInstance, type ProgressOptions, type SpinnerInstance, type SpinnerOptions, type SpinnerStyle, type StyleName, color, createCLI, createProgress, createSpinner };
171
+ export { type BannerOption, type CLIAction, type CLIBuilder, type CLIOptions, CliToolkitError, type ColorName, type CommandBuilder, type CommandContext, type CommandSetup, ICON_ERROR, ICON_INFO, ICON_SUCCESS, ICON_WARN, type OptionConfig, type ProgressInstance, type ProgressOptions, type SpinnerInstance, type SpinnerOptions, type SpinnerStyle, type StyleName, color, createCLI, createProgress, createSpinner };
package/dist/index.mjs CHANGED
@@ -247,12 +247,31 @@ function parsePositionalNames(rawName) {
247
247
  return names;
248
248
  }
249
249
  /**
250
+ * Resolve the banner text to display before a command action runs.
251
+ *
252
+ * Returns `null` when the banner should be suppressed.
253
+ */
254
+ function resolveBanner(config, name, version) {
255
+ if (config === false || config === void 0) return null;
256
+ if (typeof config === "string") {
257
+ if (!config) return null;
258
+ return config.replace(/\{name\}/g, name).replace(/\{version\}/g, version ?? "");
259
+ }
260
+ if (!version) return null;
261
+ return `${color.bold(color.cyan(name))} ${color.yellow(`v${version}`)}`;
262
+ }
263
+ /**
250
264
  * Create a CLI application with an opinionated builder API.
251
265
  *
252
266
  * Auto-attaches `--help` and `--version`. Each command's action handler
253
267
  * receives a typed options object and a `ctx` with built-in access to
254
268
  * spinner, progress bar, and colors.
255
269
  *
270
+ * When a `version` is provided, a styled banner (`name v{version}`) is
271
+ * automatically printed to stderr before every command action. Use
272
+ * `.banner(false)` to disable or `.banner("Custom {name} {version}")`
273
+ * to customize.
274
+ *
256
275
  * ```ts
257
276
  * const cli = createCLI('my-app', '1.0.0').description('My CLI')
258
277
  *
@@ -270,10 +289,11 @@ function parsePositionalNames(rawName) {
270
289
  * cli.parse()
271
290
  * ```
272
291
  */
273
- function createCLI(name, version) {
292
+ function createCLI(name, version, options) {
274
293
  const cli = cac(name);
275
294
  if (version) cli.version(version);
276
295
  cli.help();
296
+ let bannerConfig = options?.banner ?? (version ? true : void 0);
277
297
  function createContext() {
278
298
  return {
279
299
  color,
@@ -290,6 +310,10 @@ function createCLI(name, version) {
290
310
  cli.usage(text);
291
311
  return builder;
292
312
  },
313
+ banner(text) {
314
+ bannerConfig = text ?? true;
315
+ return builder;
316
+ },
293
317
  command(rawName, description, setup) {
294
318
  const positionalNames = parsePositionalNames(rawName);
295
319
  const rawCmd = cli.command(rawName, description);
@@ -304,6 +328,8 @@ function createCLI(name, version) {
304
328
  },
305
329
  action(handler) {
306
330
  rawCmd.action((...args) => {
331
+ const bannerText = resolveBanner(bannerConfig, name, version);
332
+ if (bannerText) console.error(bannerText);
307
333
  const options = args[args.length - 1];
308
334
  for (let i = 0; i < positionalNames.length; i++) options[positionalNames[i]] = args[i];
309
335
  return handler(options, createContext());
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@zfadhli/koko-cli",
3
3
  "type": "module",
4
- "version": "0.1.0",
4
+ "version": "0.2.0",
5
5
  "description": "Composition-based CLI toolkit — wraps cac, picocolors, cli-progress, cli-spinners",
6
6
  "license": "MIT",
7
7
  "author": "Koko contributors",