@longzai-intelligence-cli/core 0.0.9 → 0.0.11
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 +14 -25
- package/dist/index.d.ts +21 -4
- package/dist/index.js +2 -2
- package/package.json +9 -6
package/README.md
CHANGED
|
@@ -1,31 +1,20 @@
|
|
|
1
1
|
# @longzai-intelligence-cli/core
|
|
2
2
|
|
|
3
|
-
Longzai Intelligence
|
|
3
|
+
Longzai Intelligence Cli 的核心包,承载命令行应用的命令装配、输出版式、交互契约与版本注入等平台无关能力,是全部预设与各命令行应用的共同基础。
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## 简介
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
治理命令行基础设施的单一来源:交互与着色只定契约、实现经 Provider 注入,命令装配、输出版式、进度与持久化等能力由本包统一提供,各命令行应用不再散落自研 CLI 副本,避免装配与输出口径漂移。
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## 能力
|
|
10
10
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const program = createCli({
|
|
22
|
-
name: 'lzi-my-app',
|
|
23
|
-
description: '我的 CLI 应用',
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
program.command('hello').action(() => {
|
|
27
|
-
console.log('Hello, Longzai Intelligence!');
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
await program.parseAsync(process.argv);
|
|
31
|
-
```
|
|
11
|
+
- 命令装配工厂(`createCli()`,内置版本与帮助入口)
|
|
12
|
+
- 交互与着色契约(InteractionProvider / ColorProvider)及全局 Provider 槽位注入
|
|
13
|
+
- 交互函数(单选、确认、文本输入、spinner、提示与日志输出)
|
|
14
|
+
- 输出版式(text / json 双格式与表格渲染)
|
|
15
|
+
- 进度条与进度控制器
|
|
16
|
+
- CLI 版本号读取(构建期注入优先、开发期兜底)
|
|
17
|
+
- 命令定义工厂(选项声明与参数校验统一封装、父子命令挂接)
|
|
18
|
+
- 通用 JSON 文件持久化
|
|
19
|
+
- 日志条目格式化(时间戳、级别着色、条目美化、嵌套对象扁平化)
|
|
20
|
+
- 带前缀唯一 ID 生成
|
package/dist/index.d.ts
CHANGED
|
@@ -272,7 +272,8 @@ type CreateCliOptions = {
|
|
|
272
272
|
/**
|
|
273
273
|
* 创建 CLI 程序实例
|
|
274
274
|
*
|
|
275
|
-
* 基于 commander 封装,内置 `--version
|
|
275
|
+
* 基于 commander 封装,内置 `--version`(版本号显式传入优先,否则经 `getCliVersion`
|
|
276
|
+
* 解析——内联消费方构建期 define 注入 + 运行时 package.json 兜底)
|
|
276
277
|
* 与 `--help`。调用方注入交互/着色 provider 后,模块级交互函数(select/confirm 等)
|
|
277
278
|
* 与 OutputFormatter 即按注入的 provider 工作。
|
|
278
279
|
*
|
|
@@ -301,8 +302,8 @@ declare function createCli(options: CreateCliOptions): Command$1;
|
|
|
301
302
|
*
|
|
302
303
|
* 解析顺序:
|
|
303
304
|
*
|
|
304
|
-
* 1.
|
|
305
|
-
* 2.
|
|
305
|
+
* 1. `process.env.CLI_VERSION`——内联消费方构建期经 define 静态替换,或运行时环境变量注入
|
|
306
|
+
* 2. 兜底:从模块旁的 package.json 读取(源码形态 `src/../package.json`,产物形态 `dist/../package.json`)
|
|
306
307
|
* 3. 找不到时回退 '0.0.0'(极端沙箱场景),避免阻塞 --version 输出
|
|
307
308
|
*
|
|
308
309
|
* @returns CLI 版本号字符串
|
|
@@ -734,6 +735,22 @@ type CommandSpec<T extends z.ZodType> = {
|
|
|
734
735
|
*/
|
|
735
736
|
action: (validated: z.infer<T>, positionals: string[]) => Promise<void>;
|
|
736
737
|
};
|
|
738
|
+
/**
|
|
739
|
+
* 解析或创建 commander 父命令(公共工具)
|
|
740
|
+
*
|
|
741
|
+
* 在 program 的直接子命令中查找指定名称的父命令,找不到则创建。
|
|
742
|
+
* 用于消费方注册「父命令 + 子命令」形式(如 `template create`)时复用已有父命令,
|
|
743
|
+
* 规避 commander 14.x 对 program.command('template create') 多次调用重复创建 'template' 父命令
|
|
744
|
+
* 导致的 'cannot add command' 错误。
|
|
745
|
+
*
|
|
746
|
+
* 消费方用原生 commander 注册带空格子命令时(defineCommand 已内置此逻辑,无需手动调用),
|
|
747
|
+
* 应通过本函数获取父命令再 .command('子命令名'),而非 program.command('父 子')。
|
|
748
|
+
*
|
|
749
|
+
* @param program - commander 顶层 Command 实例
|
|
750
|
+
* @param parentName - 父命令名称(不含空格的单段名)
|
|
751
|
+
* @returns 已存在或新创建的父命令 Command 实例
|
|
752
|
+
*/
|
|
753
|
+
declare function resolveCommandParent(program: Command$1, parentName: string): Command$1;
|
|
737
754
|
/**
|
|
738
755
|
* 定义并注册命令(commander 选项 + zod 校验统一封装)
|
|
739
756
|
*
|
|
@@ -768,4 +785,4 @@ type CommandSpec<T extends z.ZodType> = {
|
|
|
768
785
|
*/
|
|
769
786
|
declare function defineCommand<T extends z.ZodType>(program: Command$1, spec: CommandSpec<T>): void;
|
|
770
787
|
//#endregion
|
|
771
|
-
export { type ColorProvider, type Command, type CommandSpec, type ConfirmOptions, type CreateCliOptions, type InteractionProvider, JsonStorage, type LogEntry, type LogLevel, type LogToolset, type OptionDecl, type OutputFormat, OutputFormatter, type ProgressController, type SelectOption, type SpinnerController, type TextInputOptions, confirm, createCli, defineCommand, flattenObject, formatLevel, formatLogEntry, formatTimestamp, generateId, getCliVersion, getColorProvider, getInteractionProvider, log, note, parseOutputFormat, progressBar, select, setColorProvider, setInteractionProvider, spinner, textInput };
|
|
788
|
+
export { type ColorProvider, type Command, type CommandSpec, type ConfirmOptions, type CreateCliOptions, type InteractionProvider, JsonStorage, type LogEntry, type LogLevel, type LogToolset, type OptionDecl, type OutputFormat, OutputFormatter, type ProgressController, type SelectOption, type SpinnerController, type TextInputOptions, confirm, createCli, defineCommand, flattenObject, formatLevel, formatLogEntry, formatTimestamp, generateId, getCliVersion, getColorProvider, getInteractionProvider, log, note, parseOutputFormat, progressBar, resolveCommandParent, select, setColorProvider, setInteractionProvider, spinner, textInput };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import"./rolldown-runtime-BqT_7tdF.js";import{createNodeLogger as e}from"@longzai-intelligence-logger/node";import{Command as t}from"commander";import{existsSync as n,mkdirSync as r,readFileSync as i,writeFileSync as a}from"node:fs";import{dirname as o}from"node:path";import"node:url";import*as
|
|
1
|
+
import"./rolldown-runtime-BqT_7tdF.js";import{createNodeLogger as e}from"@longzai-intelligence-logger/node";import{Command as t}from"commander";import{existsSync as n,mkdirSync as r,readFileSync as i,writeFileSync as a}from"node:fs";import{dirname as o,join as s}from"node:path";import{fileURLToPath as c}from"node:url";import*as l from"zod";const u=e(`@longzai-intelligence-cli/core/provider`),d={red:e=>e,green:e=>e,yellow:e=>e,blue:e=>e,cyan:e=>e,magenta:e=>e,gray:e=>e,bold:e=>e,dim:e=>e};let f={select:async(e,t)=>t[0]?.value??``,textInput:async(e,t)=>t?.defaultValue??``,confirm:async(e,t)=>t?.defaultValue??!1,spinner:()=>({start:e=>u.info(e),stop:e=>u.info(e)}),note:(e,t)=>{t?u.info(`${t}: ${e}`):u.info(e)},log:{info:e=>u.info(e),success:e=>u.info(e),warn:e=>u.warn(e),error:e=>u.error(e),step:e=>u.info(e)}},p=d;function m(e){f=e}function h(e){p=e}function g(){return f}function _(){return p}function v(e){return typeof e==`object`&&!!e&&(!(`name`in e)||typeof e.name==`string`)&&`version`in e&&typeof e.version==`string`}const y=()=>{let e=process.env.CLI_VERSION;if(typeof e==`string`&&e.length>0)return e;try{let e=s(o(c(import.meta.url)),`..`,`package.json`),t=JSON.parse(i(e,`utf-8`));if(v(t)&&t.name===`@longzai-intelligence-cli/core`)return t.version}catch{}return`0.0.0`};function b(e){let n=e.version??y();e.interaction&&m(e.interaction),e.color&&h(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 x=e(`@longzai-intelligence-cli/core/output`);var S=class{format;constructor(e=`text`){this.format=e}get colors(){return _()}success(e,t){this.format===`json`?x.info(JSON.stringify({success:!0,data:e},null,2)):x.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)};x.info(JSON.stringify({success:!1,error:t},null,2))}else{let t=e instanceof Error?e.message:String(e);x.error(this.colors.red(`错误: ${t}`))}}info(e){this.format===`json`?x.info(JSON.stringify({success:!0,message:e},null,2)):x.info(this.colors.blue(e))}warn(e){this.format===`json`?x.info(JSON.stringify({success:!0,warning:e},null,2)):x.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});x.info(JSON.stringify({success:!0,data:n},null,2))}else{let n=e.map((e,n)=>Math.min(60,Math.max(e.length,...t.map(e=>(e[n]??``).length))));x.info(e.map((e,t)=>this.colors.bold(e.padEnd(n[t]??0))).join(` `)),x.info(n.map(e=>`─`.repeat(e??0)).join(` `));for(let e of t)x.info(e.map((e,t)=>{let r=n[t]??0,i=e??``;return i.length>r?i.slice(0,Math.max(0,r-1))+`…`:i.padEnd(r)}).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 w(e,t){return g().select(e,t)}async function T(e,t){return g().textInput(e,t)}async function E(e,t){return g().confirm(e,t)}function D(){return g().spinner()}function O(e,t){g().note(e,t)}const k={info(e){g().log.info(e)},success(e){g().log.success(e)},warn(e){g().log.warn(e)},error(e){g().log.error(e)},step(e){g().log.step(e)}},A=e(`@longzai-intelligence-cli/core/progress`);function j(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${_().blue(a)} ${r.toFixed(0)}%${i}`),r>=100&&process.stdout.write(`
|
|
2
2
|
`)}},done(e){process.stdout.write(`
|
|
3
|
-
`),e&&
|
|
3
|
+
`),e&&A.info(_().green(`✓ ${e}`))}}}const M={debug:`gray`,error:`red`,fatal:`red`,info:`green`,trace:`gray`,warn:`yellow`};function N(e){try{return new Date(e).toLocaleString(`zh-CN`,{day:`2-digit`,hour:`2-digit`,hour12:!1,minute:`2-digit`,month:`2-digit`,second:`2-digit`,year:`numeric`})}catch{return e}}function P(e){let t=e.toLowerCase(),n=e.toUpperCase().padEnd(5),r=M[t]??`green`;return _()[r](n)}function F(e){let t=_(),n=[];return e.timestamp!==void 0&&n.push(t.gray(N(e.timestamp))),n.push(P(e.level??`info`)),e.serviceName!==void 0&&e.serviceName!==``&&n.push(t.blue(`[${e.serviceName}]`)),n.push(e.message??String(e.message??``)),e.metadata!==void 0&&typeof e.metadata==`object`&&Object.keys(e.metadata).length>0&&n.push(t.gray(JSON.stringify(e.metadata))),n.join(` `)}function I(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function L(e,t=``){let n={};for(let[r,i]of Object.entries(e)){let e=t===``?r:`${t}.${r}`;I(i)?Object.assign(n,L(i,e)):n[e]=String(i??``)}return n}const R=l.array(l.unknown());function z(e){return R.safeParse(e).success}var B=class{filePath;constructor(e){this.filePath=e;let t=o(e);n(t)||r(t,{recursive:!0}),n(e)||a(e,`[]`,`utf-8`)}read(){try{let e=i(this.filePath,`utf-8`),t=JSON.parse(e);return z(t)?t:[]}catch{return[]}}write(e){let t=o(this.filePath);n(t)||r(t,{recursive:!0}),a(this.filePath,JSON.stringify(e,null,2),`utf-8`)}add(e){let t=this.read();t.push(e),this.write(t)}find(e){return this.read().find(e)}remove(e){let t=this.read(),n=t.filter(t=>!e(t));return n.length!==t.length&&(this.write(n),!0)}update(e,t){let n=this.read(),r=!1,i=n.map(n=>e(n)?(r=!0,t(n)):n);return r&&this.write(i),r}};function V(e){return`${e}_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,8)}`}const H=e(`@longzai-intelligence-cli/core/define-command`);function U(e,t){let n=e.commands.find(e=>e.name()===t);return n===void 0?e.command(t):n}function W(e,t){if(t.length===1){let n=t[0];if(n===void 0)throw Error(`defineCommand: segments 为空,无法解析命令名`);return e.command(n)}let[n,...r]=t;if(n===void 0)throw Error(`defineCommand: segments 首段为空,无法解析父命令名`);let i=r.pop();if(i===void 0)throw Error(`defineCommand: segments 末段为空,无法解析子命令名`);let a=U(e,n);for(let e of r)a=U(a,e);return a.command(i)}function G(e,n){let r=W(e,n.name.split(` `).filter(e=>e.length>0));n.description&&r.description(n.description);for(let e of n.arguments??[])e.description?r.argument(e.signature,e.description):r.argument(e.signature);for(let e of n.options??[])e.defaultValue===void 0?r.option(e.flags,e.description??``):r.option(e.flags,e.description??``,e.defaultValue);r.action(async(...e)=>{let r=e[e.length-1];if(!(r instanceof t))return;let i=r.opts(),a=r.args,o=n.schema.safeParse(i);if(!o.success){let e=o.error.issues.map(e=>e.message).join(`, `);H.error(_().red(`参数校验失败: ${e}`)),g().log.error(`参数校验失败: ${e}`),process.exit(1)}await n.action(o.data,a)})}export{B as JsonStorage,S as OutputFormatter,E as confirm,b as createCli,G as defineCommand,L as flattenObject,P as formatLevel,F as formatLogEntry,N as formatTimestamp,V as generateId,y as getCliVersion,_ as getColorProvider,g as getInteractionProvider,k as log,O as note,C as parseOutputFormat,j as progressBar,U as resolveCommandParent,w as select,h as setColorProvider,m as setInteractionProvider,D as spinner,T as textInput};
|
package/package.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@longzai-intelligence-cli/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
4
4
|
"private": false,
|
|
5
|
+
"description": "Longzai Intelligence CLI 核心契约与平台无关能力",
|
|
5
6
|
"keywords": [
|
|
6
7
|
"cli",
|
|
7
8
|
"commander",
|
|
8
|
-
"
|
|
9
|
+
"core",
|
|
10
|
+
"infrastructure",
|
|
11
|
+
"longzai-intelligence"
|
|
9
12
|
],
|
|
10
13
|
"license": "UNLICENSED",
|
|
11
14
|
"files": [
|
|
@@ -22,12 +25,12 @@
|
|
|
22
25
|
},
|
|
23
26
|
"scripts": {
|
|
24
27
|
"build": "lzi-builder",
|
|
25
|
-
"build:prod": "NODE_ENV=production
|
|
28
|
+
"build:prod": "NODE_ENV=production bun run build",
|
|
26
29
|
"prepublishOnly": "bun run build:prod",
|
|
27
30
|
"typecheck": "bun run typecheck:app && bun run typecheck:node && bun run typecheck:test",
|
|
28
|
-
"typecheck:app": "tsgo
|
|
29
|
-
"typecheck:node": "tsgo
|
|
30
|
-
"typecheck:test": "tsgo
|
|
31
|
+
"typecheck:app": "lzi-tsgo typecheck tsconfig/app.json",
|
|
32
|
+
"typecheck:node": "lzi-tsgo typecheck tsconfig/node.json",
|
|
33
|
+
"typecheck:test": "lzi-tsgo typecheck tsconfig/test.json",
|
|
31
34
|
"lint": "oxlint && oxfmt --check",
|
|
32
35
|
"lint:fix": "oxlint --fix && oxfmt",
|
|
33
36
|
"test": "bun test",
|