@lichidental/saas-cli 1.0.1 → 1.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/README.md CHANGED
@@ -1,93 +1,93 @@
1
- # saas-cli
2
-
3
- > **目标读者:所有人** — 第一次接触本工具从这里开始(安装、登录、试跑、文档地图)。不需要编程经验;更细的使用说明见 `docs/CLI使用手册.md`。
4
-
5
- 励齿口腔 SaaS 数据操作命令行工具:新建预约、查询医生 / 患者 / 预约项目。
6
-
7
- ## 快速开始
8
-
9
- > 下面出现的名词(npm、token、命令行……)如果不认识,先看本文末尾的 [名词表](#名词表看不懂的词查这里)。
10
-
11
- 前置:Node.js 22.12 或更高版本
12
-
13
- ```bash
14
- # 1. 安装(二选一)
15
- npm install -g @lichidental/saas-cli # 全局安装:装完在任何目录直接敲 saas-cli
16
- npx @lichidental/saas-cli reservation doctors # 或者不安装,用 npx 直接跑(适合先试试)
17
-
18
- # 2. 登录(只需一次)
19
- saas-cli auth login # 打开授权页,页面上点「复制 token」
20
- saas-cli auth login --token <粘贴的token> # 粘贴后回车:验证并保存到本机
21
-
22
- # 3. 试跑:列出医生(顺便验证登录是否成功)
23
- saas-cli reservation doctors
24
- ```
25
-
26
- 登录信息保存在本机,之后所有命令自动使用。常用登录管理:
27
-
28
- ```bash
29
- saas-cli auth status # 查看登录状态(加 --verify 可联网验证 token 是否有效)
30
- saas-cli auth logout # 退出登录(删除本机凭证)
31
- ```
32
-
33
- 创建一条预约:
34
-
35
- ```bash
36
- saas-cli reservation create --patient 张三 --doctor 李医生 --time "2026-11-05 10:00" --duration 30 --items "补牙"
37
- ```
38
-
39
- **token 从哪来**:运行 `saas-cli auth login` 会打开授权页(需先在浏览器登录 SaaS 系统),页面上有「复制 token」按钮;或向后端同学要一个。
40
- (还没有授权页之前,也可以手工取:浏览器登录 SaaS 后按 F12 → Application → Local Storage → `userInfo` → 复制 `token` 字段。)
41
-
42
- ## 命令一览
43
-
44
- | 命令 | 用途 |
45
- | ----------------------------------------- | -------------------------------------- |
46
- | `auth login` / `logout` / `status` | 登录 / 退出 / 查看登录状态 |
47
- | `reservation create` | 新建预约(传姓名自动查患者/医生/项目) |
48
- | `reservation list` | 查询预约(按患者 + 日期) |
49
- | `reservation doctors` | 医生列表 |
50
- | `reservation patients --keyword <关键词>` | 搜索患者 |
51
- | `reservation items [--keyword]` | 预约项目列表 |
52
- | `config set-token` / `config show` | 配置 token / 查看配置(兼容旧用法,推荐 auth) |
53
-
54
- 通用参数:`--env test|pre|prod`(默认 test)、`--token`、`--json`(输出结构化 JSON)、`--verbose`(打印请求详情)。
55
-
56
- ## 文档
57
-
58
- | 文档 | 目标读者 | 内容 |
59
- | ----------------------- | --------------- | ------------------------------------ |
60
- | `docs/CLI使用手册.md` | 使用者(人) | 上手步骤、命令示例、常见问题排查 |
61
- | `AGENTS.md` | AI | 命令契约、输出契约、错误码、任务流程 |
62
- | `docs/api/openapi.yaml` | AI / 程序 | 接口权威规范(机器可读) |
63
- | `docs/api/接口说明.md` | 后端工程师(人) | 接口字段中文含义 + 可直接复制的 curl |
64
- | `docs/开发指南.md` | 开发者(人) | 新增命令的模板与规范 |
65
- | `docs/前端配套-CLI授权页.md` | 前端工程师 | 登录授权页的需求说明与后端接口草案 |
66
-
67
- ## 注意事项
68
-
69
- - `reservation create` 是**真实写操作**,会创建预约数据;生产环境(prod)必须加 `--yes` 才执行,建议先用 `--dry-run` 预览。
70
- - `--sms` 会**真实给患者发短信**,默认不发送。
71
- - 医生 / 患者重名时工具不会猜,会列出候选要求指定。
72
- - 工具启动时会自动检查是否有新版本(每天最多检查一次,失败静默);用 `SAAS_CLI_NO_UPDATE_CHECK=1` 可关闭提醒。
73
-
74
- ## 名词表(看不懂的词查这里)
75
-
76
- | 名词 | 通俗解释 |
77
- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------- |
78
- | 命令行 / 终端 | 一个"敲命令"的窗口(不是鼠标点击的界面)。Windows 里可用 CMD、PowerShell 或 Git Bash,输入命令后按回车执行 |
79
- | CLI | 命令行工具的统称:不打开网页,敲命令就能用。本工具就是一套 CLI |
80
- | Node.js | 跑本工具需要的运行环境(相当于"播放器",本工具是"文件"),官网 nodejs.org 下载安装,版本要 22.12 以上 |
81
- | npm / npx | Node.js 自带的工具:npm 负责"装东西",npx 负责"临时跑一个工具"(不用先安装) |
82
- | `npm install -g` | 全局安装:装一次,之后在任何目录都能直接用命令名(如 `saas-cli`) |
83
- | 授权页 / `auth login` | 登录用的:跑 `saas-cli auth login` 会自动打开一个网页,上面有「复制 token」按钮;复制回来再跑一条命令就完成登录 |
84
- | token | 登录凭据,一串字符(像一张"电子通行证"),接口靠它确认你是谁、属于哪家诊所;会过期,过期了就重新登录 |
85
- | 环境变量 SAAS_TOKEN | 一种让工具读到 token 的系统设置方式(不落盘的临时方案);怎么设见《使用手册》第二节;不设也没关系,`auth login` 更省事 |
86
- | `--` 开头的参数 | 写在命令后面的可选项,用来控制行为,例如 `--dry-run` 只预览不创建、`--json` 输出给程序读的格式 |
87
- | 环境(test / pre / prod) | test=测试环境(专供造数据,随便试)、pre=预发环境(上线前演练)、prod=生产环境(真实在用的系统,务必谨慎) |
88
- | 接口 / API | 系统之间互相传数据的"窗口"。创建一条预约,就是通过"新建预约接口"完成的 |
89
- | JSON | 一种格式固定的文本,样子像 `{"name":"张三"}`;给程序读的标准格式,人也能看懂 |
90
- | curl | 系统自带的小工具:一行命令就能调用接口(不用打开网页),给技术同学手工测试用 |
91
- | openapi.yaml | 接口的"机器版说明书"(格式固定,AI 和工具能直接读);给人看的中文版在 `docs/api/接口说明.md` |
92
- | AGENTS.md | 专门写给 AI 助手看的说明书;人不看也没关系 |
93
- | 退出码 | 命令跑完后返回的数字:0=成功,非 0=失败。写自动化脚本时用得到,手工使用不用管 |
1
+ # saas-cli
2
+
3
+ > **目标读者:所有人** — 第一次接触本工具从这里开始(安装、登录、试跑、文档地图)。不需要编程经验;更细的使用说明见 `docs/CLI使用手册.md`。
4
+
5
+ 励齿口腔 SaaS 数据操作命令行工具:新建预约、查询医生 / 患者 / 预约项目。
6
+
7
+ ## 快速开始
8
+
9
+ > 下面出现的名词(npm、token、命令行……)如果不认识,先看本文末尾的 [名词表](#名词表看不懂的词查这里)。
10
+
11
+ 前置:Node.js 22.12 或更高版本
12
+
13
+ ```bash
14
+ # 1. 安装(二选一)
15
+ npm install -g @lichidental/saas-cli # 全局安装:装完在任何目录直接敲 saas-cli
16
+ npx @lichidental/saas-cli reservation doctors # 或者不安装,用 npx 直接跑(适合先试试)
17
+
18
+ # 2. 登录(只需一次)
19
+ saas-cli auth login # 打开授权页,页面上点「复制 token」
20
+ saas-cli auth login --token <粘贴的token> # 粘贴后回车:验证并保存到本机
21
+
22
+ # 3. 试跑:列出医生(顺便验证登录是否成功)
23
+ saas-cli reservation doctors
24
+ ```
25
+
26
+ 登录信息保存在本机,之后所有命令自动使用。常用登录管理:
27
+
28
+ ```bash
29
+ saas-cli auth status # 查看登录状态(加 --verify 可联网验证 token 是否有效)
30
+ saas-cli auth logout # 退出登录(删除本机凭证)
31
+ ```
32
+
33
+ 创建一条预约:
34
+
35
+ ```bash
36
+ saas-cli reservation create --patient 张三 --doctor 李医生 --time "2026-11-05 10:00" --duration 30 --items "补牙"
37
+ ```
38
+
39
+ **token 从哪来**:运行 `saas-cli auth login` 会打开授权页(需先在浏览器登录 SaaS 系统),页面上有「复制 token」按钮;或向后端同学要一个。
40
+ (还没有授权页之前,也可以手工取:浏览器登录 SaaS 后按 F12 → Application → Local Storage → `userInfo` → 复制 `token` 字段。)
41
+
42
+ ## 命令一览
43
+
44
+ | 命令 | 用途 |
45
+ | ----------------------------------------- | -------------------------------------- |
46
+ | `auth login` / `logout` / `status` | 登录 / 退出 / 查看登录状态 |
47
+ | `reservation create` | 新建预约(传姓名自动查患者/医生/项目) |
48
+ | `reservation list` | 查询预约(按患者 + 日期) |
49
+ | `reservation doctors` | 医生列表 |
50
+ | `reservation patients --keyword <关键词>` | 搜索患者 |
51
+ | `reservation items [--keyword]` | 预约项目列表 |
52
+ | `config set-token` / `config show` | 配置 token / 查看配置(兼容旧用法,推荐 auth) |
53
+
54
+ 通用参数:`--env test|pre|prod`(默认 test)、`--token`、`--json`(输出结构化 JSON)、`--verbose`(打印请求详情)。
55
+
56
+ ## 文档
57
+
58
+ | 文档 | 目标读者 | 内容 |
59
+ | ----------------------- | --------------- | ------------------------------------ |
60
+ | `docs/CLI使用手册.md` | 使用者(人) | 上手步骤、命令示例、常见问题排查 |
61
+ | `AGENTS.md` | AI | 命令契约、输出契约、错误码、任务流程 |
62
+ | `docs/api/openapi.yaml` | AI / 程序 | 接口权威规范(机器可读) |
63
+ | `docs/api/接口说明.md` | 后端工程师(人) | 接口字段中文含义 + 可直接复制的 curl |
64
+ | `docs/开发指南.md` | 开发者(人) | 新增命令的模板与规范 |
65
+ | `docs/前端配套-CLI授权页.md` | 前端工程师 | 登录授权页的需求说明与后端接口草案 |
66
+
67
+ ## 注意事项
68
+
69
+ - `reservation create` 是**真实写操作**,会创建预约数据;生产环境(prod)必须加 `--yes` 才执行,建议先用 `--dry-run` 预览。
70
+ - `--sms` 会**真实给患者发短信**,默认不发送。
71
+ - 医生 / 患者重名时工具不会猜,会列出候选要求指定。
72
+ - 工具启动时会自动检查是否有新版本(每天最多检查一次,失败静默);用 `SAAS_CLI_NO_UPDATE_CHECK=1` 可关闭提醒。
73
+
74
+ ## 名词表(看不懂的词查这里)
75
+
76
+ | 名词 | 通俗解释 |
77
+ | ----------------------- | ------------------------------------------------------------------------------------------------------------------------- |
78
+ | 命令行 / 终端 | 一个"敲命令"的窗口(不是鼠标点击的界面)。Windows 里可用 CMD、PowerShell 或 Git Bash,输入命令后按回车执行 |
79
+ | CLI | 命令行工具的统称:不打开网页,敲命令就能用。本工具就是一套 CLI |
80
+ | Node.js | 跑本工具需要的运行环境(相当于"播放器",本工具是"文件"),官网 nodejs.org 下载安装,版本要 22.12 以上 |
81
+ | npm / npx | Node.js 自带的工具:npm 负责"装东西",npx 负责"临时跑一个工具"(不用先安装) |
82
+ | `npm install -g` | 全局安装:装一次,之后在任何目录都能直接用命令名(如 `saas-cli`) |
83
+ | 授权页 / `auth login` | 登录用的:跑 `saas-cli auth login` 会自动打开一个网页,上面有「复制 token」按钮;复制回来再跑一条命令就完成登录 |
84
+ | token | 登录凭据,一串字符(像一张"电子通行证"),接口靠它确认你是谁、属于哪家诊所;会过期,过期了就重新登录 |
85
+ | 环境变量 SAAS_TOKEN | 一种让工具读到 token 的系统设置方式(不落盘的临时方案);怎么设见《使用手册》第二节;不设也没关系,`auth login` 更省事 |
86
+ | `--` 开头的参数 | 写在命令后面的可选项,用来控制行为,例如 `--dry-run` 只预览不创建、`--json` 输出给程序读的格式 |
87
+ | 环境(test / pre / prod) | test=测试环境(专供造数据,随便试)、pre=预发环境(上线前演练)、prod=生产环境(真实在用的系统,务必谨慎) |
88
+ | 接口 / API | 系统之间互相传数据的"窗口"。创建一条预约,就是通过"新建预约接口"完成的 |
89
+ | JSON | 一种格式固定的文本,样子像 `{"name":"张三"}`;给程序读的标准格式,人也能看懂 |
90
+ | curl | 系统自带的小工具:一行命令就能调用接口(不用打开网页),给技术同学手工测试用 |
91
+ | openapi.yaml | 接口的"机器版说明书"(格式固定,AI 和工具能直接读);给人看的中文版在 `docs/api/接口说明.md` |
92
+ | AGENTS.md | 专门写给 AI 助手看的说明书;人不看也没关系 |
93
+ | 退出码 | 命令跑完后返回的数字:0=成功,非 0=失败。写自动化脚本时用得到,手工使用不用管 |
@@ -1,144 +1,156 @@
1
- // commands/auth/login.mjs — 登录:验证 token 并保存到本机
2
- // 三种用法:
3
- // 1) saas-cli auth login --token <token> 直接验证并保存
4
- // 2) ... --token - (或管道) 从标准输入读取 token 后验证保存
5
- // 3) saas-cli auth login(无 --token) 引导打开授权页,给出后续操作指引(不阻塞等待)
6
- import { spawn } from "node:child_process"
7
- import readline from "node:readline"
8
- import { CliError, EXIT_CODES } from "../../lib/errors.mjs"
9
- import { createOutput } from "../../lib/output.mjs"
10
- import { buildContextWithToken } from "../../lib/context.mjs"
11
- import { assertValueNotOptionLike } from "../../lib/options.mjs"
12
- import { setToken, maskToken } from "../../lib/config.mjs"
13
- import { ENV_BASE_URLS } from "../../lib/http.mjs"
14
- import { listDoctors } from "../../api/employee.mjs"
15
-
16
- /** 授权页地址:默认 <环境地址>/cli-auth,可用 --auth-url 覆盖 */
17
- function authUrlFor(env, override) {
18
- if (override) {
19
- if (!/^https?:\/\//i.test(override)) {
20
- throw new CliError(`--auth-url 必须是 http/https 地址(收到:${override})`, { exitCode: EXIT_CODES.USAGE })
21
- }
22
- return override
23
- }
24
- const base = ENV_BASE_URLS[env]
25
- if (!base) {
26
- throw new CliError(`未知环境「${env}」,可选:${Object.keys(ENV_BASE_URLS).join(" / ")}`, {
27
- exitCode: EXIT_CODES.USAGE,
28
- })
29
- }
30
- return `${base}/cli-auth`
31
- }
32
-
33
- /** 用系统默认浏览器打开 URL(失败静默,不影响主流程);Windows 下 start 以新标签页打开,不打断已有页面 */
34
- function openBrowser(url) {
35
- const isWin = process.platform === "win32"
36
- const cmd = isWin ? "cmd" : process.platform === "darwin" ? "open" : "xdg-open"
37
- // windowsVerbatimArguments:参数原样传给 cmd,避免 node 二次转义把 URL 包成 \"...\"
38
- const args = isWin ? ["/c", "start", '""', url.replace(/&/g, "^&")] : [url]
39
- try {
40
- const p = spawn(cmd, args, {
41
- stdio: "ignore",
42
- detached: true,
43
- ...(isWin ? { windowsVerbatimArguments: true } : {}),
44
- })
45
- p.on("error", () => {})
46
- p.unref()
47
- } catch {
48
- // 打开失败不阻塞:使用者可手动复制链接
49
- }
50
- }
51
-
52
- /** 读取标准输入首行(管道场景);超时(10 秒)或无内容返回空串 */
53
- function readStdinLine() {
54
- return new Promise((resolve) => {
55
- const rl = readline.createInterface({ input: process.stdin })
56
- const timer = setTimeout(() => {
57
- rl.close()
58
- resolve("")
59
- }, 10000)
60
- rl.once("line", (line) => {
61
- clearTimeout(timer)
62
- rl.close()
63
- resolve(line.trim())
64
- })
65
- rl.once("close", () => {
66
- clearTimeout(timer)
67
- resolve("")
68
- })
69
- })
70
- }
71
-
72
- /** @param {import("commander").Command} topic */
73
- export function register(topic) {
74
- topic
75
- .command("login")
76
- .description("登录:验证 token 并保存到本机;不带 --token 时引导打开授权页")
77
- .option("--env <env>", "环境:test | pre | prod", "test")
78
- .option("--token <token>", "要登录的 token;- 表示从标准输入读取;省略则引导打开授权页")
79
- .option("--auth-url <url>", "授权页地址(默认 <环境地址>/cli-auth)")
80
- .option("--no-open", "不自动打开浏览器,只打印授权页链接")
81
- .option("--json", "输出结构化 JSON(默认输出人读摘要)")
82
- .option("--verbose", "打印请求详情(token 脱敏)")
83
- .action(async function () {
84
- const opts = this.opts()
85
- const out = createOutput({ json: Boolean(opts.json), verbose: Boolean(opts.verbose) })
86
- let token = typeof opts.token === "string" ? opts.token.trim() : ""
87
-
88
- if (token === "-") {
89
- // 显式要求从标准输入读取(脚本/剪贴板管道场景)
90
- token = await readStdinLine()
91
- if (!token) {
92
- throw new CliError("--token - 指定从标准输入读取,但没有读到内容", {
93
- exitCode: EXIT_CODES.USAGE,
94
- hint: "例:powershell -c Get-Clipboard | saas-cli auth login --token -",
95
- })
96
- }
97
- } else if (token) {
98
- assertValueNotOptionLike(opts.token, {
99
- option: "--token",
100
- hint: `用法:saas-cli auth login --env ${opts.env} --token <token>;或省略 --token 打开授权页按引导操作`,
101
- })
102
- }
103
-
104
- if (!token) {
105
- // 无 token:引导模式(打开授权页 + 指引),不阻塞等待输入
106
- const url = authUrlFor(opts.env, opts.authUrl)
107
- const interactive = Boolean(process.stdin.isTTY) || Boolean(process.stdout.isTTY)
108
- const opened = Boolean(opts.open) && interactive
109
- if (opened) openBrowser(url)
110
- out.success(
111
- "auth login",
112
- opts.env,
113
- { env: opts.env, authUrl: url, opened, configured: false },
114
- [
115
- opened ? "已在浏览器打开授权页(未打开则手动复制下面的链接):" : "请在浏览器中打开以下链接:",
116
- ` ${url}`,
117
- `登录后点击「复制 token」,然后运行:`,
118
- ` saas-cli auth login --env ${opts.env} --token <粘贴的token>`,
119
- "",
120
- `也可以直接用剪贴板管道一步完成(PowerShell):`,
121
- ` powershell -c Get-Clipboard | saas-cli auth login --env ${opts.env} --token -`,
122
- ].join("\n")
123
- )
124
- return
125
- }
126
-
127
- // 验证 token:调只读接口(医生列表)确认有效性,通过后再保存
128
- const { env, http } = buildContextWithToken(this, token)
129
- const res = await listDoctors(http)
130
- const doctorCount = (res.data ?? []).length
131
- const file = setToken(env, token)
132
-
133
- out.success(
134
- "auth login",
135
- env,
136
- { env, token: maskToken(token), verified: true, doctorCount, configFile: file },
137
- [
138
- `✓ 登录成功(环境:${env})`,
139
- ` token 已验证:${maskToken(token)},可访问 ${doctorCount} 名在职员工`,
140
- ` 已保存到:${file}`,
141
- ].join("\n")
142
- )
143
- })
144
- }
1
+ // commands/auth/login.mjs — 登录:验证 token 并保存到本机
2
+ // 三种用法:
3
+ // 1) saas-cli auth login --token <token> 直接验证并保存
4
+ // 2) ... --token - (或管道) 从标准输入读取 token 后验证保存
5
+ // 3) saas-cli auth login(无 --token) 引导打开授权页,给出后续操作指引(不阻塞等待)
6
+ import { spawn } from "node:child_process"
7
+ import readline from "node:readline"
8
+ import { CliError, EXIT_CODES } from "../../lib/errors.mjs"
9
+ import { createOutput } from "../../lib/output.mjs"
10
+ import { buildContextWithToken } from "../../lib/context.mjs"
11
+ import { assertValueNotOptionLike } from "../../lib/options.mjs"
12
+ import { setToken, maskToken } from "../../lib/config.mjs"
13
+ import { ENV_BASE_URLS } from "../../lib/http.mjs"
14
+ import { listDoctors } from "../../api/employee.mjs"
15
+
16
+ /**
17
+ * 授权页地址:默认 <环境地址>/cli-auth,可用 --auth-url 覆盖。
18
+ * 附加时间戳参数 t(与 SaaS 前端约定的防缓存方式一致):每次打开都是新 URL,绕过浏览器对旧页面的缓存,保证请求到最新版本
19
+ */
20
+ function authUrlFor(env, override) {
21
+ let url = ""
22
+ if (override) {
23
+ if (!/^https?:\/\//i.test(override)) {
24
+ throw new CliError(`--auth-url 必须是 http/https 地址(收到:${override})`, { exitCode: EXIT_CODES.USAGE })
25
+ }
26
+ url = override
27
+ } else {
28
+ const base = ENV_BASE_URLS[env]
29
+ if (!base) {
30
+ throw new CliError(`未知环境「${env}」,可选:${Object.keys(ENV_BASE_URLS).join(" / ")}`, {
31
+ exitCode: EXIT_CODES.USAGE,
32
+ })
33
+ }
34
+ url = `${base}/cli-auth`
35
+ }
36
+ try {
37
+ const u = new URL(url)
38
+ u.searchParams.set("t", Date.now().toString(36))
39
+ return u.toString()
40
+ } catch {
41
+ return url
42
+ }
43
+ }
44
+
45
+ /** 用系统默认浏览器打开 URL(失败静默,不影响主流程);Windows 下 start 以新标签页打开,不打断已有页面 */
46
+ function openBrowser(url) {
47
+ const isWin = process.platform === "win32"
48
+ const cmd = isWin ? "cmd" : process.platform === "darwin" ? "open" : "xdg-open"
49
+ // windowsVerbatimArguments:参数原样传给 cmd,避免 node 二次转义把 URL 包成 \"...\"
50
+ const args = isWin ? ["/c", "start", '""', url.replace(/&/g, "^&")] : [url]
51
+ try {
52
+ const p = spawn(cmd, args, {
53
+ stdio: "ignore",
54
+ detached: true,
55
+ ...(isWin ? { windowsVerbatimArguments: true } : {}),
56
+ })
57
+ p.on("error", () => {})
58
+ p.unref()
59
+ } catch {
60
+ // 打开失败不阻塞:使用者可手动复制链接
61
+ }
62
+ }
63
+
64
+ /** 读取标准输入首行(管道场景);超时(10 秒)或无内容返回空串 */
65
+ function readStdinLine() {
66
+ return new Promise((resolve) => {
67
+ const rl = readline.createInterface({ input: process.stdin })
68
+ const timer = setTimeout(() => {
69
+ rl.close()
70
+ resolve("")
71
+ }, 10000)
72
+ rl.once("line", (line) => {
73
+ clearTimeout(timer)
74
+ rl.close()
75
+ resolve(line.trim())
76
+ })
77
+ rl.once("close", () => {
78
+ clearTimeout(timer)
79
+ resolve("")
80
+ })
81
+ })
82
+ }
83
+
84
+ /** @param {import("commander").Command} topic */
85
+ export function register(topic) {
86
+ topic
87
+ .command("login")
88
+ .description("登录:验证 token 并保存到本机;不带 --token 时引导打开授权页")
89
+ .option("--env <env>", "环境:test | pre | prod", "test")
90
+ .option("--token <token>", "要登录的 token;- 表示从标准输入读取;省略则引导打开授权页")
91
+ .option("--auth-url <url>", "授权页地址(默认 <环境地址>/cli-auth)")
92
+ .option("--no-open", "不自动打开浏览器,只打印授权页链接")
93
+ .option("--json", "输出结构化 JSON(默认输出人读摘要)")
94
+ .option("--verbose", "打印请求详情(token 脱敏)")
95
+ .action(async function () {
96
+ const opts = this.opts()
97
+ const out = createOutput({ json: Boolean(opts.json), verbose: Boolean(opts.verbose) })
98
+ let token = typeof opts.token === "string" ? opts.token.trim() : ""
99
+
100
+ if (token === "-") {
101
+ // 显式要求从标准输入读取(脚本/剪贴板管道场景)
102
+ token = await readStdinLine()
103
+ if (!token) {
104
+ throw new CliError("--token - 指定从标准输入读取,但没有读到内容", {
105
+ exitCode: EXIT_CODES.USAGE,
106
+ hint: "例:powershell -c Get-Clipboard | saas-cli auth login --token -",
107
+ })
108
+ }
109
+ } else if (token) {
110
+ assertValueNotOptionLike(opts.token, {
111
+ option: "--token",
112
+ hint: `用法:saas-cli auth login --env ${opts.env} --token <token>;或省略 --token 打开授权页按引导操作`,
113
+ })
114
+ }
115
+
116
+ if (!token) {
117
+ // 无 token:引导模式(打开授权页 + 指引),不阻塞等待输入
118
+ const url = authUrlFor(opts.env, opts.authUrl)
119
+ const interactive = Boolean(process.stdin.isTTY) || Boolean(process.stdout.isTTY)
120
+ const opened = Boolean(opts.open) && interactive
121
+ if (opened) openBrowser(url)
122
+ out.success(
123
+ "auth login",
124
+ opts.env,
125
+ { env: opts.env, authUrl: url, opened, configured: false },
126
+ [
127
+ opened ? "已在浏览器打开授权页(未打开则手动复制下面的链接):" : "请在浏览器中打开以下链接:",
128
+ ` ${url}`,
129
+ `登录后点击「复制 token」,然后运行:`,
130
+ ` saas-cli auth login --env ${opts.env} --token <粘贴的token>`,
131
+ "",
132
+ `也可以直接用剪贴板管道一步完成(PowerShell):`,
133
+ ` powershell -c Get-Clipboard | saas-cli auth login --env ${opts.env} --token -`,
134
+ ].join("\n")
135
+ )
136
+ return
137
+ }
138
+
139
+ // 验证 token:调只读接口(医生列表)确认有效性,通过后再保存
140
+ const { env, http } = buildContextWithToken(this, token)
141
+ const res = await listDoctors(http)
142
+ const doctorCount = (res.data ?? []).length
143
+ const file = setToken(env, token)
144
+
145
+ out.success(
146
+ "auth login",
147
+ env,
148
+ { env, token: maskToken(token), verified: true, doctorCount, configFile: file },
149
+ [
150
+ `✓ 登录成功(环境:${env})`,
151
+ ` token 已验证:${maskToken(token)},可访问 ${doctorCount} 名在职员工`,
152
+ ` 已保存到:${file}`,
153
+ ].join("\n")
154
+ )
155
+ })
156
+ }
@@ -1,198 +1,198 @@
1
- # saas-cli 使用手册
2
-
3
- > **目标读者:会用命令行的使用者** — 无需编程经验,按示例照抄即可完成查询和创建预约。
4
- > 遇到报错请先看第五节的"常见问题";纯技术同学(写代码对接接口)请看 `api/接口说明.md`。
5
- > 文中不认识的词(命令行、token、参数……)查 `README.md` 末尾的"名词表"。
6
-
7
- 一个命令行小工具:不用打开网页界面,就能查医生 / 患者 / 预约项目,并创建预约。适合后端同学造测试数据、联调排查。
8
-
9
- ---
10
-
11
- ## 一、安装(1 分钟)
12
-
13
- 1. 安装 [Node.js](https://nodejs.org) 22.12 或更高版本(命令行执行 `node -v` 能输出版本号即可)
14
- 2. 全局安装本工具:
15
-
16
- ```bash
17
- npm install -g @lichidental/saas-cli
18
- ```
19
-
20
- 装完在任何目录都能直接用 `saas-cli` 命令;也可以不安装,用 `npx @lichidental/saas-cli <命令>` 临时跑。
21
-
22
- (本仓库开发者:在项目根目录 `npm install` 后,下文所有 `saas-cli` 可用 `node cli.mjs` 替代。)
23
-
24
- ## 二、登录(配置一次即可)
25
-
26
- 工具需要一个登录凭据(token)才能调接口。**推荐用登录命令,两步完成**:
27
-
28
- ```bash
29
- # 第 1 步:打开授权页(需先在浏览器登录 SaaS 系统)
30
- saas-cli auth login
31
-
32
- # 在授权页上点「复制 token」,回到命令行执行第 2 步(把 <token> 换成复制的内容):
33
- saas-cli auth login --token <token>
34
- ```
35
-
36
- 第 2 步会自动**验证** token 是否有效,通过后保存到本机;以后所有命令自动使用它。
37
-
38
- 常用管理命令:
39
-
40
- ```bash
41
- saas-cli auth status # 查看登录状态(加 --verify 可联网验证 token 有效性)
42
- saas-cli auth logout # 退出登录(删除本机凭证)
43
- ```
44
-
45
- **其他登录方式**(任选;token 优先级:命令行 `--token` > 环境变量 `SAAS_TOKEN` > 配置文件):
46
-
47
- ```bash
48
- # 从剪贴板直接管道输入(PowerShell;先在授权页复制 token)
49
- powershell -c Get-Clipboard | saas-cli auth login --token -
50
-
51
- # 临时使用不落盘:每次命令临时传 --token,或设置环境变量 SAAS_TOKEN
52
- set SAAS_TOKEN=你的token # CMD(仅当前窗口有效)
53
- $env:SAAS_TOKEN="你的token" # PowerShell(仅当前窗口有效)
54
- export SAAS_TOKEN=你的token # Git Bash(仅当前窗口有效)
55
- ```
56
-
57
- > 授权页还没上线前,可手工获取 token:浏览器登录 SaaS 系统 → 按 F12 → Application(应用)→ Local Storage → 找到 `userInfo` → 复制 `token` 字段的值;或向后端同学要一个。拿到后同样用 `saas-cli auth login --token <token>` 保存。
58
-
59
- 查看当前配置(兼容命令):
60
-
61
- ```bash
62
- saas-cli config show
63
- ```
64
-
65
- ## 三、5 分钟上手
66
-
67
- ```bash
68
- # 1. 看看有哪些医生(顺便验证 token 是否可用)
69
- saas-cli reservation doctors
70
-
71
- # 2. 搜一个患者(关键词可以是姓名/手机号/病历号)
72
- saas-cli reservation patients --keyword 张
73
-
74
- # 3. 不实际创建,先预览一下将提交的内容
75
- saas-cli reservation create --patient 张三 --doctor 李医生 --time "2026-11-05 10:00" --items 补牙 --dry-run
76
-
77
- # 4. 确认没问题,去掉 --dry-run 真正创建
78
- saas-cli reservation create --patient 张三 --doctor 李医生 --time "2026-11-05 10:00" --items 补牙
79
-
80
- # 5. 回查确认
81
- saas-cli reservation list --patient 张三 --date 2026-11-05
82
- ```
83
-
84
- ## 四、命令详解
85
-
86
- ### 通用参数(所有命令可用)
87
-
88
- | 参数 | 说明 |
89
- | ----------------------- | ------------------------------------------------ |
90
- | `--env test\|pre\|prod` | 目标环境,默认 `test` |
91
- | `--token <token>` | 临时指定 token(覆盖配置) |
92
- | `--json` | 输出结构化 JSON(给程序/AI 解析用;默认是人读摘要) |
93
- | `--verbose` | 打印请求/响应详情(token 打码),排查问题用 |
94
-
95
- `saas-cli --help` 看全部命令;`saas-cli reservation create --help` 看单个命令帮助。
96
-
97
- ### reservation create — 新建预约
98
-
99
- ```bash
100
- saas-cli reservation create --patient 张三 --doctor 李医生 --time "2026-11-05 10:00" --duration 30 --items "补牙,口腔检查" --remark "备注内容"
101
- ```
102
-
103
- | 参数 | 说明 |
104
- | -------------------------- | -------------------------------------------------------------- |
105
- | `--patient <姓名/手机号/病历号>` | 自动搜索患者;**重名时会列出候选并报错**,此时用下面两种方式指定 |
106
- | `--patient-code <编码或病历号>` | 直接指定患者编码(如 YONGCE26073100001)或病历号(如 YONGCE26073100142),跳过搜索 |
107
- | `--doctor <姓名>` | 自动匹配医生(同理,重名会列候选) |
108
- | `--doctor-id <userUid>` | 直接指定医生,跳过搜索 |
109
- | `--time <时间>` | 预约开始时间,如 `"2026-11-05 10:00"`;省略 = 当前时间 |
110
- | `--duration <分钟>` | 时长,15~480 之间,默认 30 |
111
- | `--items <名称列表>` | 项目名称,逗号分隔(中英文逗号都行),如 `"洗牙,补牙"` |
112
- | `--items-json <json>` | 直接给项目 JSON(跳过名称匹配),格式见 `--help` |
113
- | `--first <1\|0>` | 1=初诊,0=复诊;不传则按患者历史自动判断 |
114
- | `--dry-run` | 只打印请求体,不创建(强烈建议先用它预览) |
115
- | `--sms` | 创建后给患者发预约短信(**默认不发**,会给真实手机发短信) |
116
- | `--yes` | 生产环境(prod)写操作必须加,防止误操作 |
117
-
118
- 创建成功会输出:
119
-
120
- ```
121
- ✓ 预约创建成功(环境:test)
122
- 患者 张三(YONGCE26073100001)
123
- 医生 李医生(userUid:26051131994)
124
- 时间 2026-11-02 09:00:00 起 15 分钟
125
- 就诊类型 复诊
126
- 项目 口腔检查
127
- 短信 未发送(如需发送加 --sms)
128
- 预约ID 1260618
129
- ```
130
-
131
- ### reservation list — 查询预约
132
-
133
- ```bash
134
- saas-cli reservation list --patient 张三 # 查今天
135
- saas-cli reservation list --patient 张三 --date 2026-10-15 # 查指定日期
136
- saas-cli reservation list --patient-code YONGCE26073100001 --date 2026-10-15
137
- saas-cli reservation list --patient YONGCE26073100142 --date 2026-10-15 # 病历号也可以
138
- ```
139
-
140
- ### reservation doctors / patients / items — 查询辅助
141
-
142
- ```bash
143
- saas-cli reservation doctors # 医生列表(拿 userUid)
144
- saas-cli reservation patients --keyword 张 # 患者列表(拿 customCode)
145
- saas-cli reservation items --keyword 洁 # 项目列表(名称参考),不加参数列全部
146
- ```
147
-
148
- ### auth — 登录管理(推荐)
149
-
150
- ```bash
151
- saas-cli auth login # 打开授权页(按提示获取 token)
152
- saas-cli auth login --token <token> # 验证并保存 token
153
- saas-cli auth status # 查看登录状态(--verify 联网验证)
154
- saas-cli auth logout # 退出登录
155
- ```
156
-
157
- ### config — 配置管理(兼容旧用法)
158
-
159
- ```bash
160
- saas-cli config set-token --env test --token xxx # 保存 token(不做验证)
161
- saas-cli config show # 查看配置(token 打码)
162
- ```
163
-
164
- ## 五、常见问题
165
-
166
- **Q:报 `✗ 认证失败:登录失效,请重新登录!`(退出码 3)**
167
- token 过期了。重新走一遍第二节的登录流程(`saas-cli auth login` → 复制 → `saas-cli auth login --token <新token>`)即可。
168
-
169
- **Q:报 `✗ 环境 test 未配置 token`**
170
- 还没登录。按第二节操作(`saas-cli auth login`);也可用命令加 `--token` 或环境变量 `SAAS_TOKEN` 临时传入。
171
-
172
- **Q:报 `患者「张三」匹配到 N 条`**
173
- 重名。用 `--patient-code <编码>` 指定具体哪一个(先用 `reservation patients --keyword 张三` 查看编码);医生重名同理,用 `--doctor-id`。
174
-
175
- **Q:报 `✗ 未找到患者「XXX」`**
176
- 关键词没匹配到。换个关键词(试试手机号或病历号),或先用 `reservation patients --keyword` 确认拼写。
177
-
178
- **Q:报 `✗ 版本校验失败`(status 999)**
179
- 后端发现客户端版本号过旧。工具会自动读取目标环境当前版本号规避;若持续出现,检查本机能否访问 `https://test.saas.lichidental.com/index.html`(公司网络是否有限制),然后再试。
180
-
181
- **Q:报 `✗ 网络请求失败`**
182
- 网络不通或超时(15 秒)。检查网络/代理后重试;查询类命令可直接重试,创建命令重试前先用 `reservation list` 回查确认上次是否已成功(创建命令每执行一次都会新建一条,确认上次没成功再重试,避免建重)。
183
-
184
- **Q:命令没反应/时间不对**
185
- `--time` 用的是本机时区的时间。格式必须是 `"2026-11-05 10:00"` 或带秒 `"2026-11-05 10:00:00"`。
186
-
187
- **Q:想看接口实际发出去的原始请求**
188
- 加 `--verbose`,会打印请求地址、请求体、原始响应(token 自动打码)。
189
-
190
- **Q:输出的 JSON 想直接给程序用**
191
- 加 `--json`,stdout 只有一段 JSON;错误也是 JSON 格式(方便脚本判断 `ok` 字段和退出码)。
192
-
193
- ## 六、安全须知
194
-
195
- - `reservation create` 是**真实写操作**;生产环境(prod)必须加 `--yes`,建议先用 `--dry-run` 预览
196
- - `--sms` 会**真实给患者手机发短信**,默认关闭,确认需要时再加
197
- - token 保存在本机配置文件中(Windows: `%APPDATA%\saas-cli\config.json`,权限设为仅本人可读;旧版 `create-saas-cli` 目录会自动兼容迁移);如不希望落盘,就用环境变量或每次 `--token` 传入
198
- - 不要把 token 提交到代码仓库或发给无关人员
1
+ # saas-cli 使用手册
2
+
3
+ > **目标读者:会用命令行的使用者** — 无需编程经验,按示例照抄即可完成查询和创建预约。
4
+ > 遇到报错请先看第五节的"常见问题";纯技术同学(写代码对接接口)请看 `api/接口说明.md`。
5
+ > 文中不认识的词(命令行、token、参数……)查 `README.md` 末尾的"名词表"。
6
+
7
+ 一个命令行小工具:不用打开网页界面,就能查医生 / 患者 / 预约项目,并创建预约。适合后端同学造测试数据、联调排查。
8
+
9
+ ---
10
+
11
+ ## 一、安装(1 分钟)
12
+
13
+ 1. 安装 [Node.js](https://nodejs.org) 22.12 或更高版本(命令行执行 `node -v` 能输出版本号即可)
14
+ 2. 全局安装本工具:
15
+
16
+ ```bash
17
+ npm install -g @lichidental/saas-cli
18
+ ```
19
+
20
+ 装完在任何目录都能直接用 `saas-cli` 命令;也可以不安装,用 `npx @lichidental/saas-cli <命令>` 临时跑。
21
+
22
+ (本仓库开发者:在项目根目录 `npm install` 后,下文所有 `saas-cli` 可用 `node cli.mjs` 替代。)
23
+
24
+ ## 二、登录(配置一次即可)
25
+
26
+ 工具需要一个登录凭据(token)才能调接口。**推荐用登录命令,两步完成**:
27
+
28
+ ```bash
29
+ # 第 1 步:打开授权页(需先在浏览器登录 SaaS 系统)
30
+ saas-cli auth login
31
+
32
+ # 在授权页上点「复制 token」,回到命令行执行第 2 步(把 <token> 换成复制的内容):
33
+ saas-cli auth login --token <token>
34
+ ```
35
+
36
+ 第 2 步会自动**验证** token 是否有效,通过后保存到本机;以后所有命令自动使用它。
37
+
38
+ 常用管理命令:
39
+
40
+ ```bash
41
+ saas-cli auth status # 查看登录状态(加 --verify 可联网验证 token 有效性)
42
+ saas-cli auth logout # 退出登录(删除本机凭证)
43
+ ```
44
+
45
+ **其他登录方式**(任选;token 优先级:命令行 `--token` > 环境变量 `SAAS_TOKEN` > 配置文件):
46
+
47
+ ```bash
48
+ # 从剪贴板直接管道输入(PowerShell;先在授权页复制 token)
49
+ powershell -c Get-Clipboard | saas-cli auth login --token -
50
+
51
+ # 临时使用不落盘:每次命令临时传 --token,或设置环境变量 SAAS_TOKEN
52
+ set SAAS_TOKEN=你的token # CMD(仅当前窗口有效)
53
+ $env:SAAS_TOKEN="你的token" # PowerShell(仅当前窗口有效)
54
+ export SAAS_TOKEN=你的token # Git Bash(仅当前窗口有效)
55
+ ```
56
+
57
+ > 授权页还没上线前,可手工获取 token:浏览器登录 SaaS 系统 → 按 F12 → Application(应用)→ Local Storage → 找到 `userInfo` → 复制 `token` 字段的值;或向后端同学要一个。拿到后同样用 `saas-cli auth login --token <token>` 保存。
58
+
59
+ 查看当前配置(兼容命令):
60
+
61
+ ```bash
62
+ saas-cli config show
63
+ ```
64
+
65
+ ## 三、5 分钟上手
66
+
67
+ ```bash
68
+ # 1. 看看有哪些医生(顺便验证 token 是否可用)
69
+ saas-cli reservation doctors
70
+
71
+ # 2. 搜一个患者(关键词可以是姓名/手机号/病历号)
72
+ saas-cli reservation patients --keyword 张
73
+
74
+ # 3. 不实际创建,先预览一下将提交的内容
75
+ saas-cli reservation create --patient 张三 --doctor 李医生 --time "2026-11-05 10:00" --items 补牙 --dry-run
76
+
77
+ # 4. 确认没问题,去掉 --dry-run 真正创建
78
+ saas-cli reservation create --patient 张三 --doctor 李医生 --time "2026-11-05 10:00" --items 补牙
79
+
80
+ # 5. 回查确认
81
+ saas-cli reservation list --patient 张三 --date 2026-11-05
82
+ ```
83
+
84
+ ## 四、命令详解
85
+
86
+ ### 通用参数(所有命令可用)
87
+
88
+ | 参数 | 说明 |
89
+ | ----------------------- | ------------------------------------------------ |
90
+ | `--env test\|pre\|prod` | 目标环境,默认 `test` |
91
+ | `--token <token>` | 临时指定 token(覆盖配置) |
92
+ | `--json` | 输出结构化 JSON(给程序/AI 解析用;默认是人读摘要) |
93
+ | `--verbose` | 打印请求/响应详情(token 打码),排查问题用 |
94
+
95
+ `saas-cli --help` 看全部命令;`saas-cli reservation create --help` 看单个命令帮助。
96
+
97
+ ### reservation create — 新建预约
98
+
99
+ ```bash
100
+ saas-cli reservation create --patient 张三 --doctor 李医生 --time "2026-11-05 10:00" --duration 30 --items "补牙,口腔检查" --remark "备注内容"
101
+ ```
102
+
103
+ | 参数 | 说明 |
104
+ | -------------------------- | -------------------------------------------------------------- |
105
+ | `--patient <姓名/手机号/病历号>` | 自动搜索患者;**重名时会列出候选并报错**,此时用下面两种方式指定 |
106
+ | `--patient-code <编码或病历号>` | 直接指定患者编码(如 YONGCE26073100001)或病历号(如 YONGCE26073100142),跳过搜索 |
107
+ | `--doctor <姓名>` | 自动匹配医生(同理,重名会列候选) |
108
+ | `--doctor-id <userUid>` | 直接指定医生,跳过搜索 |
109
+ | `--time <时间>` | 预约开始时间,如 `"2026-11-05 10:00"`;省略 = 当前时间 |
110
+ | `--duration <分钟>` | 时长,15~480 之间,默认 30 |
111
+ | `--items <名称列表>` | 项目名称,逗号分隔(中英文逗号都行),如 `"洗牙,补牙"` |
112
+ | `--items-json <json>` | 直接给项目 JSON(跳过名称匹配),格式见 `--help` |
113
+ | `--first <1\|0>` | 1=初诊,0=复诊;不传则按患者历史自动判断 |
114
+ | `--dry-run` | 只打印请求体,不创建(强烈建议先用它预览) |
115
+ | `--sms` | 创建后给患者发预约短信(**默认不发**,会给真实手机发短信) |
116
+ | `--yes` | 生产环境(prod)写操作必须加,防止误操作 |
117
+
118
+ 创建成功会输出:
119
+
120
+ ```
121
+ ✓ 预约创建成功(环境:test)
122
+ 患者 张三(YONGCE26073100001)
123
+ 医生 李医生(userUid:26051131994)
124
+ 时间 2026-11-02 09:00:00 起 15 分钟
125
+ 就诊类型 复诊
126
+ 项目 口腔检查
127
+ 短信 未发送(如需发送加 --sms)
128
+ 预约ID 1260618
129
+ ```
130
+
131
+ ### reservation list — 查询预约
132
+
133
+ ```bash
134
+ saas-cli reservation list --patient 张三 # 查今天
135
+ saas-cli reservation list --patient 张三 --date 2026-10-15 # 查指定日期
136
+ saas-cli reservation list --patient-code YONGCE26073100001 --date 2026-10-15
137
+ saas-cli reservation list --patient YONGCE26073100142 --date 2026-10-15 # 病历号也可以
138
+ ```
139
+
140
+ ### reservation doctors / patients / items — 查询辅助
141
+
142
+ ```bash
143
+ saas-cli reservation doctors # 医生列表(拿 userUid)
144
+ saas-cli reservation patients --keyword 张 # 患者列表(拿 customCode)
145
+ saas-cli reservation items --keyword 洁 # 项目列表(名称参考),不加参数列全部
146
+ ```
147
+
148
+ ### auth — 登录管理(推荐)
149
+
150
+ ```bash
151
+ saas-cli auth login # 打开授权页(按提示获取 token)
152
+ saas-cli auth login --token <token> # 验证并保存 token
153
+ saas-cli auth status # 查看登录状态(--verify 联网验证)
154
+ saas-cli auth logout # 退出登录
155
+ ```
156
+
157
+ ### config — 配置管理(兼容旧用法)
158
+
159
+ ```bash
160
+ saas-cli config set-token --env test --token xxx # 保存 token(不做验证)
161
+ saas-cli config show # 查看配置(token 打码)
162
+ ```
163
+
164
+ ## 五、常见问题
165
+
166
+ **Q:报 `✗ 认证失败:登录失效,请重新登录!`(退出码 3)**
167
+ token 过期了。重新走一遍第二节的登录流程(`saas-cli auth login` → 复制 → `saas-cli auth login --token <新token>`)即可。
168
+
169
+ **Q:报 `✗ 环境 test 未配置 token`**
170
+ 还没登录。按第二节操作(`saas-cli auth login`);也可用命令加 `--token` 或环境变量 `SAAS_TOKEN` 临时传入。
171
+
172
+ **Q:报 `患者「张三」匹配到 N 条`**
173
+ 重名。用 `--patient-code <编码>` 指定具体哪一个(先用 `reservation patients --keyword 张三` 查看编码);医生重名同理,用 `--doctor-id`。
174
+
175
+ **Q:报 `✗ 未找到患者「XXX」`**
176
+ 关键词没匹配到。换个关键词(试试手机号或病历号),或先用 `reservation patients --keyword` 确认拼写。
177
+
178
+ **Q:报 `✗ 版本校验失败`(status 999)**
179
+ 后端发现客户端版本号过旧。工具会自动读取目标环境当前版本号规避;若持续出现,检查本机能否访问 `https://test.saas.lichidental.com/index.html`(公司网络是否有限制),然后再试。
180
+
181
+ **Q:报 `✗ 网络请求失败`**
182
+ 网络不通或超时(15 秒)。检查网络/代理后重试;查询类命令可直接重试,创建命令重试前先用 `reservation list` 回查确认上次是否已成功(创建命令每执行一次都会新建一条,确认上次没成功再重试,避免建重)。
183
+
184
+ **Q:命令没反应/时间不对**
185
+ `--time` 用的是本机时区的时间。格式必须是 `"2026-11-05 10:00"` 或带秒 `"2026-11-05 10:00:00"`。
186
+
187
+ **Q:想看接口实际发出去的原始请求**
188
+ 加 `--verbose`,会打印请求地址、请求体、原始响应(token 自动打码)。
189
+
190
+ **Q:输出的 JSON 想直接给程序用**
191
+ 加 `--json`,stdout 只有一段 JSON;错误也是 JSON 格式(方便脚本判断 `ok` 字段和退出码)。
192
+
193
+ ## 六、安全须知
194
+
195
+ - `reservation create` 是**真实写操作**;生产环境(prod)必须加 `--yes`,建议先用 `--dry-run` 预览
196
+ - `--sms` 会**真实给患者手机发短信**,默认关闭,确认需要时再加
197
+ - token 保存在本机配置文件中(Windows: `%APPDATA%\saas-cli\config.json`,权限设为仅本人可读;旧版 `create-saas-cli` 目录会自动兼容迁移);如不希望落盘,就用环境变量或每次 `--token` 传入
198
+ - 不要把 token 提交到代码仓库或发给无关人员
package/package.json CHANGED
@@ -1,42 +1,42 @@
1
- {
2
- "name": "@lichidental/saas-cli",
3
- "version": "1.0.1",
4
- "description": "励齿 SaaS 数据操作 CLI:新建预约、查询医生/患者/预约项目等",
5
- "type": "module",
6
- "engines": {
7
- "node": ">=22.12.0"
8
- },
9
- "bin": {
10
- "saas-cli": "./cli.mjs"
11
- },
12
- "files": [
13
- "cli.mjs",
14
- "commands",
15
- "lib",
16
- "api",
17
- "README.md",
18
- "AGENTS.md",
19
- "docs/CLI使用手册.md",
20
- "docs/开发指南.md",
21
- "docs/api/openapi.yaml",
22
- "docs/api/接口说明.md"
23
- ],
24
- "scripts": {
25
- "test": "node --test"
26
- },
27
- "publishConfig": {
28
- "registry": "https://registry.npmjs.org/",
29
- "access": "public"
30
- },
31
- "license": "UNLICENSED",
32
- "repository": {
33
- "type": "git",
34
- "url": "git+https://lichigit.lichidental.com/sass/create-saas-cli.git"
35
- },
36
- "dependencies": {
37
- "commander": "^15.0.0"
38
- },
39
- "devDependencies": {
40
- "@types/node": "^26.6.5"
41
- }
42
- }
1
+ {
2
+ "name": "@lichidental/saas-cli",
3
+ "version": "1.0.2",
4
+ "description": "励齿 SaaS 数据操作 CLI:新建预约、查询医生/患者/预约项目等",
5
+ "type": "module",
6
+ "engines": {
7
+ "node": ">=22.12.0"
8
+ },
9
+ "bin": {
10
+ "saas-cli": "./cli.mjs"
11
+ },
12
+ "files": [
13
+ "cli.mjs",
14
+ "commands",
15
+ "lib",
16
+ "api",
17
+ "README.md",
18
+ "AGENTS.md",
19
+ "docs/CLI使用手册.md",
20
+ "docs/开发指南.md",
21
+ "docs/api/openapi.yaml",
22
+ "docs/api/接口说明.md"
23
+ ],
24
+ "scripts": {
25
+ "test": "node --test"
26
+ },
27
+ "publishConfig": {
28
+ "registry": "https://registry.npmjs.org/",
29
+ "access": "public"
30
+ },
31
+ "license": "UNLICENSED",
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "git+https://lichigit.lichidental.com/sass/create-saas-cli.git"
35
+ },
36
+ "dependencies": {
37
+ "commander": "^15.0.0"
38
+ },
39
+ "devDependencies": {
40
+ "@types/node": "^26.6.5"
41
+ }
42
+ }