@longzai-intelligence-cli/serve-kit 0.0.0-stage → 0.0.16
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 +8 -2
- package/dist/index.d.ts +204 -0
- package/dist/index.js +1 -0
- package/dist/rolldown-runtime-BqT_7tdF.js +1 -0
- package/package.json +43 -4
package/README.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @longzai-intelligence-cli/serve-kit
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
意图:作为 CLI 族的 `serve` 命令共享设施,以宿主声明契约、本机宿主运行时、命令装配三件套,让各工具仓以一份描述符接入本机宿主的拉起能力
|
|
4
|
+
|
|
5
|
+
定位:位于 cli 工作区 packages 目录,依赖 core 的命令框架与 local-server startup 包的监听核心,发布形态为 npm 库包
|
|
6
|
+
|
|
7
|
+
职能:解析监听参数并显式关闭端口共存绑定实现冲突快速失败,经端口注册表尽力登记实例档,输出就绪行并可选拉起系统浏览器,接管退出信号完成注销与优雅停机
|
|
8
|
+
|
|
9
|
+
边界:不约束宿主内部装配面,应用工厂由各仓 desktop-host 槽位自持,本包只消费 `ListenCapableApp` 结构形态
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { ListenCapableApp, StartServerCapabilities } from "@longzai-intelligence-local-server/startup";
|
|
2
|
+
import { createPortRegistry } from "@longzai-intelligence-port/registry";
|
|
3
|
+
import { Command } from "@longzai-intelligence-cli/core";
|
|
4
|
+
/**
|
|
5
|
+
* 宿主声明契约
|
|
6
|
+
*/
|
|
7
|
+
type ServeHostDescriptor = {
|
|
8
|
+
/**
|
|
9
|
+
* 域 slug,如 `issues`
|
|
10
|
+
*/
|
|
11
|
+
readonly domain: string;
|
|
12
|
+
/**
|
|
13
|
+
* 缺省监听端口,声明值即各仓 desktop-host 槽位的历史缺省口
|
|
14
|
+
*/
|
|
15
|
+
readonly defaultPort: number;
|
|
16
|
+
/**
|
|
17
|
+
* 端口注册表服务名,命名形态为域 slug 接 `-desktop-host` 后缀
|
|
18
|
+
*/
|
|
19
|
+
readonly serviceName: string;
|
|
20
|
+
/**
|
|
21
|
+
* 生产者完整仓库名,写入端口注册表实例档作群级 join key
|
|
22
|
+
*/
|
|
23
|
+
readonly producer: string;
|
|
24
|
+
/**
|
|
25
|
+
* 应用工厂,纯装配无副作用
|
|
26
|
+
*
|
|
27
|
+
* @remarks
|
|
28
|
+
* 工厂不监听端口不扫盘,返回对象满足 startup 包的 `ListenCapableApp` 结构形态
|
|
29
|
+
*/
|
|
30
|
+
readonly createApp: () => ListenCapableApp | Promise<ListenCapableApp>;
|
|
31
|
+
/**
|
|
32
|
+
* 实例档能力端点声明,写入端口注册表实例档
|
|
33
|
+
*/
|
|
34
|
+
readonly capabilities?: StartServerCapabilities;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* ui 命令运行选项
|
|
38
|
+
*/
|
|
39
|
+
type ServeHostRunOptions = {
|
|
40
|
+
/**
|
|
41
|
+
* 监听端口覆盖值
|
|
42
|
+
*
|
|
43
|
+
* @remarks
|
|
44
|
+
* 缺省解析顺序为选项覆盖值、环境变量 `PORT`、宿主声明缺省口
|
|
45
|
+
*/
|
|
46
|
+
readonly port?: number;
|
|
47
|
+
/**
|
|
48
|
+
* 绑定地址覆盖值
|
|
49
|
+
*
|
|
50
|
+
* @remarks
|
|
51
|
+
* 缺省解析顺序为选项覆盖值、环境变量 `HOST`、回环地址 `127.0.0.1`
|
|
52
|
+
*/
|
|
53
|
+
readonly host?: string;
|
|
54
|
+
/**
|
|
55
|
+
* 就绪后打开系统浏览器
|
|
56
|
+
*
|
|
57
|
+
* @default false
|
|
58
|
+
*/
|
|
59
|
+
readonly open?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* 端口注册表自登记开关
|
|
62
|
+
*
|
|
63
|
+
* @remarks
|
|
64
|
+
* 登记失败降级为警告不阻断宿主服务
|
|
65
|
+
* @default true
|
|
66
|
+
*/
|
|
67
|
+
readonly registry?: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* 端口注册表目录覆盖值
|
|
70
|
+
*
|
|
71
|
+
* @remarks
|
|
72
|
+
* 缺省走注册表自身的工作区锚定,测试环境可指向隔离目录
|
|
73
|
+
*/
|
|
74
|
+
readonly registryDir?: string;
|
|
75
|
+
/**
|
|
76
|
+
* 接管退出信号开关,测试环境可关闭
|
|
77
|
+
*
|
|
78
|
+
* @default true
|
|
79
|
+
*/
|
|
80
|
+
readonly handleSignals?: boolean;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* 就绪行格式化工具
|
|
84
|
+
*
|
|
85
|
+
* @remarks
|
|
86
|
+
* `ready url=` 前缀为本机宿主族的稳定输出形态,供人工与脚本双面识别
|
|
87
|
+
*/
|
|
88
|
+
/**
|
|
89
|
+
* 格式化就绪行
|
|
90
|
+
*
|
|
91
|
+
* @param host - 绑定地址
|
|
92
|
+
* @param port - 实际监听端口
|
|
93
|
+
* @param domain - 域 slug
|
|
94
|
+
* @returns 就绪行文本
|
|
95
|
+
*/
|
|
96
|
+
declare function formatReadyLine(host: string, port: number, domain: string): string;
|
|
97
|
+
/**
|
|
98
|
+
* 系统浏览器拉起工具
|
|
99
|
+
*
|
|
100
|
+
* @remarks
|
|
101
|
+
* 打开器派发为尽力而为,失败不阻断宿主服务
|
|
102
|
+
*/
|
|
103
|
+
/**
|
|
104
|
+
* 按平台选取系统打开器命令
|
|
105
|
+
*
|
|
106
|
+
* @param platform - 目标平台标识,缺省取当前进程平台
|
|
107
|
+
* @returns 打开器命令名,平台不支持时为 undefined
|
|
108
|
+
*/
|
|
109
|
+
declare function selectSystemOpener(platform?: NodeJS.Platform): string | undefined;
|
|
110
|
+
/**
|
|
111
|
+
* 就绪后在系统浏览器打开服务地址
|
|
112
|
+
*
|
|
113
|
+
* @param url - 服务地址
|
|
114
|
+
* @param opener - 打开器命令名,由调用侧经 `selectSystemOpener` 解析
|
|
115
|
+
* @returns 是否已成功派发打开器进程
|
|
116
|
+
*/
|
|
117
|
+
declare function openInSystemBrowser(url: string, opener: string | undefined): boolean;
|
|
118
|
+
/**
|
|
119
|
+
* 监听参数解析工具
|
|
120
|
+
*
|
|
121
|
+
* @remarks
|
|
122
|
+
* 端口合法域为 0 到 65535 的整数,0 表示由系统随机分配
|
|
123
|
+
*/
|
|
124
|
+
/**
|
|
125
|
+
* 解析监听端口
|
|
126
|
+
*
|
|
127
|
+
* @param override - 命令选项覆盖值
|
|
128
|
+
* @param envPort - 环境变量 `PORT` 原始字符串
|
|
129
|
+
* @param defaultPort - 宿主声明缺省口
|
|
130
|
+
* @returns 生效监听端口
|
|
131
|
+
* @throws {@link Error} 当生效值不是合法端口
|
|
132
|
+
*/
|
|
133
|
+
declare function resolveServeHostPort(override: number | undefined, envPort: string | undefined, defaultPort: number): number;
|
|
134
|
+
/**
|
|
135
|
+
* 解析绑定地址
|
|
136
|
+
*
|
|
137
|
+
* @param override - 命令选项覆盖值
|
|
138
|
+
* @param envHost - 环境变量 `HOST` 原始字符串
|
|
139
|
+
* @returns 生效绑定地址
|
|
140
|
+
*/
|
|
141
|
+
declare function resolveServeHostBindHost(override: string | undefined, envHost: string | undefined): string;
|
|
142
|
+
/**
|
|
143
|
+
* 端口注册表实例类型,由注册表工厂返回类型推导
|
|
144
|
+
*/
|
|
145
|
+
type PortRegistryInstance = ReturnType<typeof createPortRegistry>;
|
|
146
|
+
/**
|
|
147
|
+
* 停机处理器构造选项
|
|
148
|
+
*/
|
|
149
|
+
type ServeHostShutdownOptions = {
|
|
150
|
+
/**
|
|
151
|
+
* 端口注册表实例,登记降级时为 null
|
|
152
|
+
*/
|
|
153
|
+
readonly registry: PortRegistryInstance | null;
|
|
154
|
+
/**
|
|
155
|
+
* 端口注册表服务名
|
|
156
|
+
*/
|
|
157
|
+
readonly serviceName: string;
|
|
158
|
+
/**
|
|
159
|
+
* 宿主应用实例
|
|
160
|
+
*/
|
|
161
|
+
readonly app: ListenCapableApp;
|
|
162
|
+
/**
|
|
163
|
+
* 进程出口钩子,测试环境可注入替身
|
|
164
|
+
*
|
|
165
|
+
* @default process.exit
|
|
166
|
+
*/
|
|
167
|
+
readonly exit?: (code: number) => void;
|
|
168
|
+
};
|
|
169
|
+
/**
|
|
170
|
+
* 优雅停机处理器形态
|
|
171
|
+
*/
|
|
172
|
+
type ServeHostShutdown = () => void;
|
|
173
|
+
/**
|
|
174
|
+
* 构造优雅停机处理器
|
|
175
|
+
*
|
|
176
|
+
* @remarks
|
|
177
|
+
* 停机次序为先注销登记再停监听再退出,注销与停听任一异常不阻断退出
|
|
178
|
+
* @param options - 停机处理器构造选项
|
|
179
|
+
* @returns 停机处理器
|
|
180
|
+
*/
|
|
181
|
+
declare function buildServeHostShutdown(options: ServeHostShutdownOptions): ServeHostShutdown;
|
|
182
|
+
/**
|
|
183
|
+
* 拉起本机宿主并监听至退出信号
|
|
184
|
+
*
|
|
185
|
+
* @remarks
|
|
186
|
+
* 本函数在监听就绪后返回实际端口,进程存活由监听句柄维持,退出由信号处理器完成
|
|
187
|
+
* @param descriptor - 宿主声明契约
|
|
188
|
+
* @param options - 运行选项
|
|
189
|
+
* @returns 实际监听端口
|
|
190
|
+
* @throws {@link Error} 当端口非法或监听失败即端口被占用等
|
|
191
|
+
*/
|
|
192
|
+
declare function runServeHost(descriptor: ServeHostDescriptor, options?: ServeHostRunOptions): Promise<number>;
|
|
193
|
+
/**
|
|
194
|
+
* 注册本仓 `serve` 命令
|
|
195
|
+
*
|
|
196
|
+
* @remarks
|
|
197
|
+
* 命令语义为前台拉起本机宿主,宿主就绪后命令进程驻留至退出信号
|
|
198
|
+
* 仓级运行缺省与命令选项同键合并,命令选项优先
|
|
199
|
+
* @param program - CLI 程序实例
|
|
200
|
+
* @param descriptor - 宿主声明契约
|
|
201
|
+
* @param defaultRunOptions - 仓级运行缺省,测试环境可经此注入注册表隔离目录
|
|
202
|
+
*/
|
|
203
|
+
declare function registerServeCommand(program: Command, descriptor: ServeHostDescriptor, defaultRunOptions?: ServeHostRunOptions): void;
|
|
204
|
+
export { type ServeHostDescriptor, type ServeHostRunOptions, type ServeHostShutdownOptions, buildServeHostShutdown, formatReadyLine, openInSystemBrowser, registerServeCommand, resolveServeHostBindHost, resolveServeHostPort, runServeHost, selectSystemOpener };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./rolldown-runtime-BqT_7tdF.js";import{spawn as e}from"node:child_process";import{ensureError as t}from"@longzai-intelligence-error/utils";import{startServerFromEnv as n}from"@longzai-intelligence-local-server/startup";import{createPortRegistry as r}from"@longzai-intelligence-port/registry";import{defineCommand as i}from"@longzai-intelligence-cli/core";import*as a from"zod";function o(e,t,n){return`ready url=http://${e}:${t} domain=${n}`}function s(e=process.platform){if(e===`darwin`)return`open`;if(e===`linux`)return`xdg-open`}function c(t,n){if(n===void 0)return!1;try{return e(n,[t],{stdio:`ignore`}).unref(),!0}catch{return!1}}function l(e,t,n){let r=t!==void 0&&t.trim()!==``?Number(t):void 0,i=e??r??n;if(!Number.isInteger(i)||i<0||i>65535)throw Error(`监听端口非法:${String(i)},合法域为 0 到 65535 的整数,0 表示由系统随机分配`);return i}function u(e,t){let n=t!==void 0&&t.trim()!==``?t:void 0;return e??n??`127.0.0.1`}function d(e){return()=>{(async()=>{try{e.registry!==null&&await e.registry.deregister(e.serviceName),await e.app.stop?.()}finally{(e.exit??process.exit)(0)}})()}}async function f(e,i={}){let a=l(i.port,process.env.PORT,e.defaultPort),f=u(i.host,process.env.HOST),p=await e.createApp(),m=await n({createApp:async()=>p,port:a,host:f,handleSignals:!1}),h=null;if(i.registry!==!1)try{h=r(i.registryDir===void 0?void 0:{registryDir:i.registryDir}),await h.register(e.serviceName,{port:m,host:f,pid:process.pid,startedAt:Date.now(),producer:e.producer,capabilities:e.capabilities})}catch(e){h=null,process.stderr.write(`端口注册表登记失败,已降级继续服务:${t(e).message}\n`)}if(i.handleSignals!==!1){let t=d({registry:h,serviceName:e.serviceName,app:p});process.once(`SIGINT`,t),process.once(`SIGTERM`,t)}return process.stdout.write(`${o(f,m,e.domain)}\n`),i.open===!0&&(c(`http://${f}:${m}`,s())||process.stderr.write(`当前平台不支持自动打开浏览器,请手动访问 http://${f}:${m}\n`)),m}const p=a.object({port:a.coerce.number().int().min(0).max(65535).optional(),host:a.string().min(1).optional(),open:a.boolean().optional()});function m(e,n,r={}){i(e,{name:`serve`,description:`拉起 ${n.domain} 本机宿主`,options:[{flags:`--port <number>`,description:`监听端口,缺省读环境变量 PORT 再回落宿主声明缺省口`},{flags:`--host <address>`,description:`绑定地址,缺省读环境变量 HOST 再回落回环地址`},{flags:`--open`,description:`宿主就绪后打开系统浏览器`}],schema:p,action:async e=>{try{await f(n,{...r,port:e.port,host:e.host,open:e.open})}catch(e){process.stderr.write(`宿主启动失败:${t(e).message}\n`),process.exitCode=1}}})}export{d as buildServeHostShutdown,o as formatReadyLine,c as openInSystemBrowser,m as registerServeCommand,u as resolveServeHostBindHost,l as resolveServeHostPort,f as runServeHost,s as selectSystemOpener};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"node:module";export{};
|
package/package.json
CHANGED
|
@@ -1,6 +1,45 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@longzai-intelligence-cli/serve-kit",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.0.16",
|
|
4
|
+
"description": "Longzai Intelligence CLI 本机宿主拉起共享设施包",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"cli",
|
|
7
|
+
"desktop-host",
|
|
8
|
+
"longzai-intelligence",
|
|
9
|
+
"ui"
|
|
10
|
+
],
|
|
11
|
+
"license": "UNLICENSED",
|
|
12
|
+
"files": [
|
|
13
|
+
"dist"
|
|
14
|
+
],
|
|
15
|
+
"type": "module",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"import": "./dist/index.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "lzi-builder",
|
|
24
|
+
"build:prod": "NODE_ENV=production bun run build",
|
|
25
|
+
"prepublishOnly": "bun run build:prod",
|
|
26
|
+
"dev": "lzi-builder --watch",
|
|
27
|
+
"clean": "lzi-dev-tools clean",
|
|
28
|
+
"test": "lzi-bun test",
|
|
29
|
+
"test:watch": "lzi-bun test --watch",
|
|
30
|
+
"test:coverage": "lzi-bun test --coverage",
|
|
31
|
+
"lint": "lzi-lint lint",
|
|
32
|
+
"lint:fix": "lzi-lint fix",
|
|
33
|
+
"typecheck": "lzi-typecheck"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@longzai-intelligence-cli/core": "0.0.16",
|
|
37
|
+
"@longzai-intelligence-error/utils": "^0.2.0",
|
|
38
|
+
"@longzai-intelligence-local-server/startup": "^0.0.2",
|
|
39
|
+
"@longzai-intelligence-port/registry": "^0.0.7",
|
|
40
|
+
"zod": "^4.6.7"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"commander": "^15.0.0"
|
|
44
|
+
}
|
|
45
|
+
}
|