@longzai-intelligence-cli/core 0.0.1 → 0.0.2

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/dist/index.d.ts CHANGED
@@ -1,5 +1,230 @@
1
1
  import "./rolldown-runtime-BqT_7tdF.js";
2
2
  import { Command } from "commander";
3
+ //#region src/contracts.d.ts
4
+ /**
5
+ * 能力契约定义
6
+ *
7
+ * core 保持中性:只定义交互、着色等能力的契约(type),
8
+ * 不含任何具体实现依赖(无 @clack/prompts、无 picocolors)。
9
+ *
10
+ * 固定策略实现(clack 交互 + picocolors 着色)由 @longzai-intelligence-cli/standard 提供;
11
+ * 消费方也可实现自己的 Provider 注入,以保留特定交互偏好或着色行为,
12
+ * 契约保证替换的安全性。
13
+ *
14
+ * 设计遵循 ADR-0048 多策略范式:契约统一、实现可替换、装配时选择。
15
+ */
16
+ /**
17
+ * 选择选项(交互层通用,与具体交互实现无关)
18
+ */
19
+ type SelectOption = {
20
+ /**
21
+ * 选项值
22
+ */
23
+ value: string;
24
+ /**
25
+ * 选项标签
26
+ */
27
+ label: string;
28
+ /**
29
+ * 选项提示
30
+ */
31
+ hint?: string;
32
+ };
33
+ /**
34
+ * 文本输入选项
35
+ */
36
+ type TextInputOptions = {
37
+ /**
38
+ * 占位提示文本
39
+ */
40
+ placeholder?: string;
41
+ /**
42
+ * 默认值
43
+ */
44
+ defaultValue?: string;
45
+ };
46
+ /**
47
+ * 确认选项
48
+ */
49
+ type ConfirmOptions = {
50
+ /**
51
+ * 默认选中值
52
+ */
53
+ defaultValue?: boolean;
54
+ };
55
+ /**
56
+ * 加载动画控制器
57
+ */
58
+ type SpinnerController = {
59
+ /**
60
+ * 启动动画
61
+ *
62
+ * @param message - 动画提示消息
63
+ */
64
+ start: (message: string) => void;
65
+ /**
66
+ * 停止动画
67
+ *
68
+ * @param message - 结束提示消息
69
+ */
70
+ stop: (message: string) => void;
71
+ };
72
+ /**
73
+ * 日志输出工具集(交互层日志,随 InteractionProvider 提供以保持输出风格一致)
74
+ */
75
+ type LogToolset = {
76
+ /**
77
+ * 输出信息级日志
78
+ */
79
+ info: (message: string) => void;
80
+ /**
81
+ * 输出成功级日志
82
+ */
83
+ success: (message: string) => void;
84
+ /**
85
+ * 输出警告级日志
86
+ */
87
+ warn: (message: string) => void;
88
+ /**
89
+ * 输出错误级日志
90
+ */
91
+ error: (message: string) => void;
92
+ /**
93
+ * 输出步骤级日志
94
+ */
95
+ step: (message: string) => void;
96
+ };
97
+ /**
98
+ * 交互能力契约
99
+ *
100
+ * 定义交互式输入(选择、确认、文本输入、加载动画、提示框、日志)的标准接口。
101
+ * 默认实现基于 @clack/prompts(方向键交互);
102
+ * 消费方可注入基于 node:readline(序号交互)的自定义实现,交互行为无损保留。
103
+ */
104
+ type InteractionProvider = {
105
+ /**
106
+ * 交互式单选
107
+ *
108
+ * @param message - 提示消息
109
+ * @param options - 选项列表
110
+ * @returns 选中的值
111
+ */
112
+ select: (message: string, options: SelectOption[]) => Promise<string>;
113
+ /**
114
+ * 交互式文本输入
115
+ *
116
+ * @param message - 提示消息
117
+ * @param options - 输入选项
118
+ * @returns 输入的文本
119
+ */
120
+ textInput: (message: string, options?: TextInputOptions) => Promise<string>;
121
+ /**
122
+ * 交互式确认
123
+ *
124
+ * @param message - 提示消息
125
+ * @param options - 确认选项
126
+ * @returns 确认结果
127
+ */
128
+ confirm: (message: string, options?: ConfirmOptions) => Promise<boolean>;
129
+ /**
130
+ * 创建加载动画
131
+ *
132
+ * @returns 加载动画控制器
133
+ */
134
+ spinner: () => SpinnerController;
135
+ /**
136
+ * 显示提示信息框
137
+ *
138
+ * @param message - 信息内容
139
+ * @param title - 信息标题
140
+ */
141
+ note: (message: string, title?: string) => void;
142
+ /**
143
+ * 日志输出工具集
144
+ */
145
+ log: LogToolset;
146
+ };
147
+ /**
148
+ * 着色能力契约
149
+ *
150
+ * 定义终端着色的标准接口。默认实现基于 picocolors;
151
+ * 消费方可注入自研 ANSI 实现以保留特定着色行为。
152
+ */
153
+ type ColorProvider = {
154
+ /**
155
+ * 红色文本
156
+ */
157
+ red: (text: string) => string;
158
+ /**
159
+ * 绿色文本
160
+ */
161
+ green: (text: string) => string;
162
+ /**
163
+ * 黄色文本
164
+ */
165
+ yellow: (text: string) => string;
166
+ /**
167
+ * 蓝色文本
168
+ */
169
+ blue: (text: string) => string;
170
+ /**
171
+ * 加粗文本
172
+ */
173
+ bold: (text: string) => string;
174
+ /**
175
+ * 灰色文本
176
+ */
177
+ gray: (text: string) => string;
178
+ };
179
+ /**
180
+ * 进度条控制器(交互无关、平台无关能力,core 直接提供实现)
181
+ */
182
+ type ProgressController = {
183
+ /**
184
+ * 更新进度
185
+ *
186
+ * @param percent - 进度百分比(0-100)
187
+ * @param message - 进度提示消息
188
+ */
189
+ update: (percent: number, message?: string) => void;
190
+ /**
191
+ * 完成进度条
192
+ *
193
+ * @param message - 完成消息
194
+ */
195
+ done: (message?: string) => void;
196
+ };
197
+ /**
198
+ * 输出格式类型
199
+ */
200
+ type OutputFormat = 'text' | 'json';
201
+ //#endregion
202
+ //#region src/provider.d.ts
203
+ /**
204
+ * 设置当前交互 provider(由 createCli 或消费方入口注入)
205
+ *
206
+ * @param provider - 交互 provider
207
+ */
208
+ declare function setInteractionProvider(provider: InteractionProvider): void;
209
+ /**
210
+ * 设置当前着色 provider(由 createCli 或消费方入口注入)
211
+ *
212
+ * @param provider - 着色 provider
213
+ */
214
+ declare function setColorProvider(provider: ColorProvider): void;
215
+ /**
216
+ * 获取当前交互 provider
217
+ *
218
+ * @returns 当前生效的交互 provider
219
+ */
220
+ declare function getInteractionProvider(): InteractionProvider;
221
+ /**
222
+ * 获取当前着色 provider
223
+ *
224
+ * @returns 当前生效的着色 provider
225
+ */
226
+ declare function getColorProvider(): ColorProvider;
227
+ //#endregion
3
228
  //#region src/create-cli.d.ts
4
229
  /**
5
230
  * createCli 工厂的配置选项
@@ -17,16 +242,37 @@ type CreateCliOptions = {
17
242
  * 版本号(默认从构建期注入读取,无需手动传入)
18
243
  */
19
244
  version?: string;
245
+ /**
246
+ * 交互 provider(决定 select/confirm/textInput 等的交互范式)
247
+ *
248
+ * 默认为中性回退。正式使用应注入 @longzai-intelligence-cli/standard 的 clack 实现,
249
+ * 或消费方自建的 readline 等实现,以保留特定交互偏好。
250
+ */
251
+ interaction?: InteractionProvider;
252
+ /**
253
+ * 着色 provider(决定 OutputFormatter/progressBar 等的着色实现)
254
+ *
255
+ * 默认为中性回退。正式使用应注入 @longzai-intelligence-cli/standard 的 picocolors 实现。
256
+ */
257
+ color?: ColorProvider;
20
258
  };
21
259
  /**
22
260
  * 创建 CLI 程序实例
23
261
  *
24
262
  * 基于 commander 封装,内置 `--version`(版本号由构建期 define 注入 + 开发期兜底)
25
- * 与 `--help`,调用方只需注册具体子命令后 `parseAsync(process.argv)` 即可。
263
+ * 与 `--help`。调用方注入交互/着色 provider 后,模块级交互函数(select/confirm 等)
264
+ * 与 OutputFormatter 即按注入的 provider 工作。
26
265
  *
27
266
  * @example
28
267
  * ```ts
29
- * const program = createCli({ name: 'lzi-my-app', description: '我的 CLI' });
268
+ * import { createCli } from '@longzai-intelligence-cli/core';
269
+ * import { clackInteraction, picocolorsColor } from '@longzai-intelligence-cli/standard';
270
+ *
271
+ * const program = createCli({
272
+ * name: 'lzi-my-app',
273
+ * interaction: clackInteraction,
274
+ * color: picocolorsColor,
275
+ * });
30
276
  * program.command('hello').action(() => console.log('hi'));
31
277
  * await program.parseAsync(process.argv);
32
278
  * ```;
@@ -36,7 +282,7 @@ type CreateCliOptions = {
36
282
  */
37
283
  declare function createCli(options: CreateCliOptions): Command;
38
284
  //#endregion
39
- //#region src/version/index.d.ts
285
+ //#region src/version.d.ts
40
286
  /**
41
287
  * 获取 CLI 版本号
42
288
  *
@@ -50,16 +296,13 @@ declare function createCli(options: CreateCliOptions): Command;
50
296
  */
51
297
  declare const getCliVersion: () => string;
52
298
  //#endregion
53
- //#region src/output/index.d.ts
54
- /**
55
- * 输出格式类型
56
- */
57
- type OutputFormat = 'text' | 'json';
299
+ //#region src/output.d.ts
58
300
  /**
59
301
  * 输出格式化器
60
302
  *
61
- * 支持 text(带颜色的可读输出)与 json(机器可读的结构化输出)两种格式,
62
- * 由 `parseOutputFormat` 从命令行 `--format` 参数解析得到。
303
+ * 支持 text(带颜色的可读输出)与 json(机器可读的结构化输出)两种格式。
304
+ * 着色由当前注入的 ColorProvider 决定(默认 @longzai-intelligence-cli/standard 的 picocolors 实现);
305
+ * 未注入时为中性无色,保证 core 单独可用。
63
306
  */
64
307
  declare class OutputFormatter {
65
308
  /**
@@ -72,6 +315,12 @@ declare class OutputFormatter {
72
315
  * @param format - 输出格式,默认 text
73
316
  */
74
317
  constructor(format?: OutputFormat);
318
+ /**
319
+ * 当前着色 provider(每次调用动态读取,保证 setProvider 后即时生效)
320
+ *
321
+ * @returns 当前着色 provider
322
+ */
323
+ private get colors();
75
324
  /**
76
325
  * 输出成功信息
77
326
  *
@@ -120,65 +369,18 @@ declare class OutputFormatter {
120
369
  */
121
370
  declare function parseOutputFormat(format?: string): OutputFormat;
122
371
  //#endregion
123
- //#region src/tui/index.d.ts
124
- /**
125
- * 选择选项
126
- */
127
- type SelectOption = {
128
- /**
129
- * 选项值
130
- */
131
- value: string;
132
- /**
133
- * 选项标签
134
- */
135
- label: string;
136
- /**
137
- * 选项提示
138
- */
139
- hint?: string;
140
- };
372
+ //#region src/tui.d.ts
141
373
  /**
142
- * 文本输入选项
143
- */
144
- type TextInputModule = {
145
- /**
146
- * 占位提示文本
147
- */
148
- placeholder?: string;
149
- /**
150
- * 默认值
151
- */
152
- defaultValue?: string;
153
- };
154
- /**
155
- * 确认选项
156
- */
157
- type ConfirmOptions = {
158
- /**
159
- * 默认选中值
160
- */
161
- defaultValue?: boolean;
162
- };
163
- /**
164
- * 加载动画控制器
374
+ * 交互层模块函数
375
+ *
376
+ * 这些函数读取当前注入的 InteractionProvider(由 createCli 或 setInteractionProvider 设置),
377
+ * 默认为中性回退。正式使用应注入 @longzai-intelligence-cli/standard 的 clack 实现。
378
+ *
379
+ * 消费方 command 文件可直接 `import { select } from '@longzai-intelligence-cli/core'` 调用,
380
+ * 无需感知当前用的是哪个 provider。
165
381
  */
166
- type SpinnerController = {
167
- /**
168
- * 启动动画
169
- *
170
- * @param message - 动画提示消息
171
- */
172
- start(message: string): void;
173
- /**
174
- * 停止动画
175
- *
176
- * @param message - 结束提示消息
177
- */
178
- stop(message: string): void;
179
- };
180
382
  /**
181
- * 交互式选择
383
+ * 交互式单选
182
384
  *
183
385
  * @param message - 提示消息
184
386
  * @param options - 选项列表
@@ -192,7 +394,7 @@ declare function select(message: string, options: SelectOption[]): Promise<strin
192
394
  * @param options - 输入选项
193
395
  * @returns 输入的文本
194
396
  */
195
- declare function textInput(message: string, options?: TextInputModule): Promise<string>;
397
+ declare function textInput(message: string, options?: TextInputOptions): Promise<string>;
196
398
  /**
197
399
  * 交互式确认
198
400
  *
@@ -215,7 +417,7 @@ declare function spinner(): SpinnerController;
215
417
  */
216
418
  declare function note(message: string, title?: string): void;
217
419
  /**
218
- * 日志输出工具集
420
+ * 日志输出工具集(委托当前 provider 的 log)
219
421
  */
220
422
  declare const log: {
221
423
  /**
@@ -250,4 +452,16 @@ declare const log: {
250
452
  step(message: string): void;
251
453
  };
252
454
  //#endregion
253
- export { type ConfirmOptions, type CreateCliOptions, type OutputFormat, OutputFormatter, type SelectOption, type SpinnerController, type TextInputModule, confirm, createCli, getCliVersion, log, note, parseOutputFormat, select, spinner, textInput };
455
+ //#region src/progress.d.ts
456
+ /**
457
+ * 进度条能力(交互无关、平台无关)
458
+ *
459
+ * 基于 process.stdout 的纯文本进度条,不依赖任何交互库。
460
+ * 着色由当前注入的 ColorProvider 决定。
461
+ *
462
+ * @param total - 总进度值(默认 100,仅用于明确语义,实际以 0-100 百分比驱动)
463
+ * @returns 进度条控制器
464
+ */
465
+ declare function progressBar(total?: number): ProgressController;
466
+ //#endregion
467
+ export { type ColorProvider, type ConfirmOptions, type CreateCliOptions, type InteractionProvider, type LogToolset, type OutputFormat, OutputFormatter, type ProgressController, type SelectOption, type SpinnerController, type TextInputOptions, confirm, createCli, getCliVersion, getColorProvider, getInteractionProvider, log, note, parseOutputFormat, progressBar, select, setColorProvider, setInteractionProvider, spinner, textInput };
package/dist/index.js CHANGED
@@ -1 +1,3 @@
1
- import"./rolldown-runtime-BqT_7tdF.js";import{Command as e}from"commander";import"node:fs";import"node:path";import"node:url";import{createNodeLogger as t}from"@longzai-intelligence-logger/node";import n from"picocolors";import*as r from"@clack/prompts";const i=()=>`0.0.1`;function a(t){let n=t.version??i(),r=new e;return r.name(t.name).version(n,`-v, --version`,`输出 ${t.name} 的版本号`),t.description&&r.description(t.description),r}const o=t(`@longzai-intelligence-cli/core/output`);var s=class{format;constructor(e=`text`){this.format=e}success(e,t){this.format===`json`?o.info(JSON.stringify({success:!0,data:e},null,2)):o.info(t?n.green(t):n.green(this.formatData(e)))}error(e){if(this.format===`json`){let t=e instanceof Error?{message:e.message,name:e.name}:{message:String(e)};o.info(JSON.stringify({success:!1,error:t},null,2))}else{let t=e instanceof Error?e.message:String(e);o.error(n.red(`错误: ${t}`))}}info(e){this.format===`json`?o.info(JSON.stringify({success:!0,message:e},null,2)):o.info(n.blue(e))}warn(e){this.format===`json`?o.info(JSON.stringify({success:!0,warning:e},null,2)):o.info(n.yellow(e))}table(e,t){if(this.format===`json`){let n=t.map(t=>{let n={};return e.forEach((e,r)=>{n[e]=t[r]??``}),n});o.info(JSON.stringify({success:!0,data:n},null,2))}else{let r=e.map((e,n)=>Math.max(e.length,...t.map(e=>(e[n]??``).length)));o.info(e.map((e,t)=>n.bold(e.padEnd(r[t]??0))).join(` `)),o.info(r.map(e=>`-`.repeat(e??0)).join(` `));for(let e of t)o.info(e.map((e,t)=>(e??``).padEnd(r[t]??0)).join(` `))}}formatData(e){return typeof e==`string`?e:typeof e==`number`||typeof e==`boolean`?String(e):JSON.stringify(e,null,2)}};function c(e){return e===`json`?`json`:`text`}async function l(e,t){let n=await r.select({message:e,options:t.map(e=>({value:e.value,label:e.label,hint:e.hint}))});return r.isCancel(n)&&(r.cancel(`操作已取消`),process.exit(0)),typeof n==`string`?n:String(n)}async function u(e,t){let n=await r.text({message:e,placeholder:t?.placeholder,defaultValue:t?.defaultValue});return r.isCancel(n)&&(r.cancel(`操作已取消`),process.exit(0)),typeof n==`string`?n:String(n)}async function d(e,t){let n=await r.confirm({message:e,initialValue:t?.defaultValue??!1});return r.isCancel(n)&&(r.cancel(`操作已取消`),process.exit(0)),typeof n==`boolean`?n:!!n}function f(){let e=r.spinner();return{start(t){e.start(t)},stop(t){e.stop(t)}}}function p(e,t){r.note(e,t)}const m={info(e){r.log.info(n.blue(e))},success(e){r.log.success(n.green(e))},warn(e){r.log.warn(n.yellow(e))},error(e){r.log.error(n.red(e))},step(e){r.log.step(e)}};export{s as OutputFormatter,d as confirm,a as createCli,i as getCliVersion,m as log,p as note,c as parseOutputFormat,l as select,f as spinner,u as textInput};
1
+ import"./rolldown-runtime-BqT_7tdF.js";import{createNodeLogger as e}from"@longzai-intelligence-logger/node";import{Command as t}from"commander";import"node:fs";import"node:path";import"node:url";const n=e(`@longzai-intelligence-cli/core/provider`),r={red:e=>e,green:e=>e,yellow:e=>e,blue:e=>e,bold:e=>e,gray:e=>e};let i={select:async(e,t)=>t[0]?.value??``,textInput:async(e,t)=>t?.defaultValue??``,confirm:async(e,t)=>t?.defaultValue??!1,spinner:()=>({start:e=>n.info(e),stop:e=>n.info(e)}),note:(e,t)=>{t?n.info(`${t}: ${e}`):n.info(e)},log:{info:e=>n.info(e),success:e=>n.info(e),warn:e=>n.warn(e),error:e=>n.error(e),step:e=>n.info(e)}},a=r;function o(e){i=e}function s(e){a=e}function c(){return i}function l(){return a}const u=()=>`0.0.2`;function d(e){let n=e.version??u();e.interaction&&o(e.interaction),e.color&&s(e.color);let r=new t;return r.name(e.name).version(n,`-v, --version`,`输出 ${e.name} 的版本号`),e.description&&r.description(e.description),r}const f=e(`@longzai-intelligence-cli/core/output`);var p=class{format;constructor(e=`text`){this.format=e}get colors(){return l()}success(e,t){this.format===`json`?f.info(JSON.stringify({success:!0,data:e},null,2)):f.info(t?this.colors.green(t):this.colors.green(this.formatData(e)))}error(e){if(this.format===`json`){let t=e instanceof Error?{message:e.message,name:e.name}:{message:String(e)};f.info(JSON.stringify({success:!1,error:t},null,2))}else{let t=e instanceof Error?e.message:String(e);f.error(this.colors.red(`错误: ${t}`))}}info(e){this.format===`json`?f.info(JSON.stringify({success:!0,message:e},null,2)):f.info(this.colors.blue(e))}warn(e){this.format===`json`?f.info(JSON.stringify({success:!0,warning:e},null,2)):f.info(this.colors.yellow(e))}table(e,t){if(this.format===`json`){let n=t.map(t=>{let n={};return e.forEach((e,r)=>{n[e]=t[r]??``}),n});f.info(JSON.stringify({success:!0,data:n},null,2))}else{let n=e.map((e,n)=>Math.max(e.length,...t.map(e=>(e[n]??``).length)));f.info(e.map((e,t)=>this.colors.bold(e.padEnd(n[t]??0))).join(` `)),f.info(n.map(e=>`-`.repeat(e??0)).join(` `));for(let e of t)f.info(e.map((e,t)=>(e??``).padEnd(n[t]??0)).join(` `))}}formatData(e){return typeof e==`string`?e:typeof e==`number`||typeof e==`boolean`?String(e):JSON.stringify(e,null,2)}};function m(e){return e===`json`?`json`:`text`}async function h(e,t){return c().select(e,t)}async function g(e,t){return c().textInput(e,t)}async function _(e,t){return c().confirm(e,t)}function v(){return c().spinner()}function y(e,t){c().note(e,t)}const b={info(e){c().log.info(e)},success(e){c().log.success(e)},warn(e){c().log.warn(e)},error(e){c().log.error(e)},step(e){c().log.step(e)}},x=e(`@longzai-intelligence-cli/core/progress`);function S(e=100){let t=-1;return{update(e,n){let r=Math.max(0,Math.min(100,e)),i=Math.round(r/100*30),a=`█`.repeat(i)+`░`.repeat(30-i);if(e!==t){t=e;let i=n?` ${n}`:``;process.stdout.write(`\r${l().blue(a)} ${r.toFixed(0)}%${i}`),r>=100&&process.stdout.write(`
2
+ `)}},done(e){process.stdout.write(`
3
+ `),e&&x.info(l().green(`✓ ${e}`))}}}export{p as OutputFormatter,_ as confirm,d as createCli,u as getCliVersion,l as getColorProvider,c as getInteractionProvider,b as log,y as note,m as parseOutputFormat,S as progressBar,h as select,s as setColorProvider,o as setInteractionProvider,v as spinner,g as textInput};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@longzai-intelligence-cli/core",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "private": false,
5
5
  "keywords": [
6
6
  "cli",
@@ -36,11 +36,9 @@
36
36
  "clean": "lzi-dev-cli clean"
37
37
  },
38
38
  "dependencies": {
39
- "@clack/prompts": "^0.11.0",
40
39
  "@longzai-intelligence-builder/utils": "^0.2.13",
41
40
  "@longzai-intelligence-logger/node": "^0.1.0",
42
- "commander": "^14.0.0",
43
- "picocolors": "^1.1.1"
41
+ "commander": "^14.0.0"
44
42
  },
45
43
  "devDependencies": {}
46
44
  }