yidaconnector 2026.6.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/LICENSE +21 -0
- package/README.md +383 -0
- package/bin/yida.js +670 -0
- package/lib/app/form-navigation.js +58 -0
- package/lib/app/get-schema.js +538 -0
- package/lib/auth/auth.js +294 -0
- package/lib/auth/cdp-browser-login.js +390 -0
- package/lib/auth/codex-login.js +71 -0
- package/lib/auth/login.js +475 -0
- package/lib/auth/org.js +363 -0
- package/lib/auth/qr-login.js +1563 -0
- package/lib/core/chalk.js +384 -0
- package/lib/core/check-update.js +82 -0
- package/lib/core/cli-error.js +39 -0
- package/lib/core/command-manifest.js +106 -0
- package/lib/core/env-cmd.js +545 -0
- package/lib/core/env-manager.js +601 -0
- package/lib/core/env.js +287 -0
- package/lib/core/i18n.js +177 -0
- package/lib/core/locales/ar.js +805 -0
- package/lib/core/locales/de.js +805 -0
- package/lib/core/locales/en.js +1623 -0
- package/lib/core/locales/es.js +805 -0
- package/lib/core/locales/fr.js +805 -0
- package/lib/core/locales/hi.js +805 -0
- package/lib/core/locales/ja.js +1197 -0
- package/lib/core/locales/ko.js +807 -0
- package/lib/core/locales/pt.js +805 -0
- package/lib/core/locales/vi.js +805 -0
- package/lib/core/locales/zh-HK.js +1233 -0
- package/lib/core/locales/zh.js +1584 -0
- package/lib/core/query-data.js +781 -0
- package/lib/core/redact.js +100 -0
- package/lib/core/utils.js +799 -0
- package/lib/core/yida-client.js +117 -0
- package/package.json +94 -0
- package/project/config.json +4 -0
- package/project/pages/src/demo-birthday-game.oyd.jsx +832 -0
- package/project/pages/src/demo-chip-insight.oyd.jsx +983 -0
- package/project/pages/src/demo-compat-smoke.oyd.jsx +58 -0
- package/project/pages/src/demo-crm-batch-entry.oyd.jsx +805 -0
- package/project/pages/src/demo-crm-dashboard.oyd.jsx +677 -0
- package/project/pages/src/demo-future-vision-2026.oyd.jsx +1102 -0
- package/project/pages/src/demo-ppt.oyd.jsx +1192 -0
- package/project/pages/src/demo-salary-calculator.oyd.jsx +904 -0
- package/project/pages/src/yidaconnector-knowledge-doc.oyd.jsx +1714 -0
- package/project/prd/demo-birthday-game.md +39 -0
- package/project/prd/demo-crm.md +463 -0
- package/project/prd/demo-dingtalk-ai-solution-center.md +425 -0
- package/project/prd/demo-future-vision-2026.md +78 -0
- package/project/prd/demo-salary-calculator.md +101 -0
- package/scripts/build-skills-package.js +406 -0
- package/scripts/check-syntax.js +59 -0
- package/scripts/demo-dws.sh +106 -0
- package/scripts/e2e-real/cleanup.js +67 -0
- package/scripts/e2e-real/fixtures/form-fields.json +18 -0
- package/scripts/e2e-real/full-runner.js +1566 -0
- package/scripts/e2e-real/runner.js +293 -0
- package/scripts/e2e-real/skill-coverage.js +115 -0
- package/scripts/generate-command-docs.js +109 -0
- package/scripts/nightly-smoke.js +134 -0
- package/scripts/postinstall.js +545 -0
- package/scripts/solution-center-runner.js +368 -0
- package/scripts/validate-ci.sh +50 -0
- package/scripts/validate-command-manifest.js +119 -0
- package/scripts/validate-package-size.js +78 -0
- package/scripts/validate-skills.js +247 -0
- package/scripts/validate-structure.js +66 -0
- package/yida-skills/SKILL.md +163 -0
- package/yida-skills/references/yida-api.md +1309 -0
- package/yida-skills/skills/large-file-write/SKILL.md +91 -0
- package/yida-skills/skills/large-file-write/references/write-patterns.md +149 -0
- package/yida-skills/skills/large-file-write/scripts/write.js +157 -0
- package/yida-skills/skills/yida-data-management/SKILL.md +252 -0
- package/yida-skills/skills/yida-data-management/references/api-matrix.md +49 -0
- package/yida-skills/skills/yida-data-management/references/data-format-guide.md +159 -0
- package/yida-skills/skills/yida-data-management/references/verified-endpoints.md +62 -0
- package/yida-skills/skills/yida-login/SKILL.md +159 -0
- package/yida-skills/skills/yida-logout/SKILL.md +67 -0
|
@@ -0,0 +1,545 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* env-cmd.js - 多环境管理 CLI 子命令
|
|
3
|
+
*
|
|
4
|
+
* 子命令:
|
|
5
|
+
* yidaconnector env list 列出所有环境及当前激活环境
|
|
6
|
+
* yidaconnector env add <name> 交互式添加私有化环境配置
|
|
7
|
+
* yidaconnector env switch <name> 切换当前激活环境
|
|
8
|
+
* yidaconnector env remove <name> 移除环境配置(不可删除 public)
|
|
9
|
+
* yidaconnector env show [name] 显示环境详细配置
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
'use strict';
|
|
13
|
+
|
|
14
|
+
const { execSync } = require('child_process');
|
|
15
|
+
const readline = require('readline');
|
|
16
|
+
const { c, warn } = require('./chalk');
|
|
17
|
+
const {
|
|
18
|
+
loadEnvsConfig,
|
|
19
|
+
saveEnvsConfig,
|
|
20
|
+
DEFAULT_BASE_URL,
|
|
21
|
+
DEFAULT_LOGIN_URL,
|
|
22
|
+
DEFAULT_PUBLIC_ENV,
|
|
23
|
+
DEFAULT_INTERNATIONAL_ENV,
|
|
24
|
+
DEFAULT_ALIBABA_INTERNAL_ENV,
|
|
25
|
+
resolveEnvNameAlias,
|
|
26
|
+
inferLoginUrlForBaseUrl,
|
|
27
|
+
} = require('./env-manager');
|
|
28
|
+
|
|
29
|
+
// ── 颜色常量 ──────────────────────────────────────────
|
|
30
|
+
|
|
31
|
+
const RESET = c.reset;
|
|
32
|
+
const BOLD = c.bold;
|
|
33
|
+
const DIM = c.dim;
|
|
34
|
+
const GREEN = c.green;
|
|
35
|
+
const YELLOW = c.yellow;
|
|
36
|
+
const CYAN = c.cyan;
|
|
37
|
+
const RED = c.red;
|
|
38
|
+
const BLUE = c.blue;
|
|
39
|
+
|
|
40
|
+
// ── 工具函数 ──────────────────────────────────────────
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* 交互式读取用户输入。
|
|
44
|
+
* @param {string} prompt - 提示文字
|
|
45
|
+
* @param {string} [defaultValue] - 默认值(用户直接回车时使用)
|
|
46
|
+
* @returns {Promise<string>}
|
|
47
|
+
*/
|
|
48
|
+
function askQuestion(prompt, defaultValue) {
|
|
49
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
50
|
+
const displayPrompt = defaultValue
|
|
51
|
+
? `${prompt} ${DIM}[${defaultValue}]${RESET} `
|
|
52
|
+
: `${prompt} `;
|
|
53
|
+
|
|
54
|
+
return new Promise((resolve) => {
|
|
55
|
+
rl.question(displayPrompt, (answer) => {
|
|
56
|
+
rl.close();
|
|
57
|
+
const trimmed = answer.trim();
|
|
58
|
+
resolve(trimmed || defaultValue || '');
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* 格式化环境名称标签(当前激活环境高亮显示)。
|
|
65
|
+
* @param {string} envName
|
|
66
|
+
* @param {string} currentEnv
|
|
67
|
+
* @returns {string}
|
|
68
|
+
*/
|
|
69
|
+
function formatEnvLabel(envName, currentEnv) {
|
|
70
|
+
if (envName === currentEnv) {
|
|
71
|
+
return `${GREEN}${BOLD}${envName}${RESET} ${GREEN}← 当前${RESET}`;
|
|
72
|
+
}
|
|
73
|
+
return `${CYAN}${envName}${RESET}`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function getLoginHost(loginUrl) {
|
|
77
|
+
try {
|
|
78
|
+
return new URL(loginUrl || DEFAULT_LOGIN_URL).hostname;
|
|
79
|
+
} catch {
|
|
80
|
+
return loginUrl || DEFAULT_LOGIN_URL;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function isBuiltinEnvName(envName) {
|
|
85
|
+
return ['public', 'intl', 'alibaba'].includes(envName);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function isDingTalkWukongRunning() {
|
|
89
|
+
if (process.platform !== 'darwin') {return false;}
|
|
90
|
+
try {
|
|
91
|
+
return execSync('ps -axo args', { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] })
|
|
92
|
+
.includes('/Applications/DingTalkWuKong.app/');
|
|
93
|
+
} catch {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function detectSetupRecommendation() {
|
|
99
|
+
if (process.env.YIDACONNECTOR_ENV) {
|
|
100
|
+
return resolveEnvNameAlias(process.env.YIDACONNECTOR_ENV);
|
|
101
|
+
}
|
|
102
|
+
if ((process.env.YIDACONNECTOR_LOGIN_URL || '').includes('login.dingtalk.io')) {
|
|
103
|
+
return 'intl';
|
|
104
|
+
}
|
|
105
|
+
if ((process.env.YIDACONNECTOR_ENDPOINT || '').includes('yidaapps.com')) {
|
|
106
|
+
return 'intl';
|
|
107
|
+
}
|
|
108
|
+
if ((process.env.YIDACONNECTOR_ENDPOINT || '').includes('alibaba-inc.com')) {
|
|
109
|
+
return 'alibaba';
|
|
110
|
+
}
|
|
111
|
+
if (isDingTalkWukongRunning()) {
|
|
112
|
+
return 'intl';
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
let activeTool = null;
|
|
116
|
+
try {
|
|
117
|
+
activeTool = require('./utils').detectActiveTool();
|
|
118
|
+
} catch {
|
|
119
|
+
activeTool = null;
|
|
120
|
+
}
|
|
121
|
+
if (activeTool && activeTool.tool === 'wukong') {
|
|
122
|
+
return 'intl';
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return 'public';
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function switchToEnv(envName) {
|
|
129
|
+
const resolvedEnvName = resolveEnvNameAlias(envName);
|
|
130
|
+
const config = loadEnvsConfig();
|
|
131
|
+
|
|
132
|
+
if (!config.environments[resolvedEnvName]) {
|
|
133
|
+
warn(`${RED}错误:环境 "${envName}" 不存在${RESET}`);
|
|
134
|
+
warn(`使用 ${CYAN}yidaconnector env list${RESET} 查看所有环境`);
|
|
135
|
+
process.exit(1);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const previousEnv = config.current;
|
|
139
|
+
config.current = resolvedEnvName;
|
|
140
|
+
saveEnvsConfig(config);
|
|
141
|
+
|
|
142
|
+
console.log('');
|
|
143
|
+
console.log(`${GREEN}✅ 已切换环境${RESET}`);
|
|
144
|
+
console.log(` ${DIM}${previousEnv}${RESET} → ${GREEN}${BOLD}${resolvedEnvName}${RESET}`);
|
|
145
|
+
console.log(` 地址:${config.environments[resolvedEnvName].baseUrl}`);
|
|
146
|
+
console.log(` 登录:${getLoginHost(config.environments[resolvedEnvName].loginUrl)}`);
|
|
147
|
+
console.log('');
|
|
148
|
+
console.log(`${DIM}下一步:运行 yidaconnector login;在悟空中可运行 yidaconnector login --wukong${RESET}`);
|
|
149
|
+
console.log('');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// ── 子命令实现 ────────────────────────────────────────
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* env list - 列出所有环境。
|
|
156
|
+
*/
|
|
157
|
+
function cmdList() {
|
|
158
|
+
const config = loadEnvsConfig();
|
|
159
|
+
const envNames = Object.keys(config.environments);
|
|
160
|
+
|
|
161
|
+
console.log('');
|
|
162
|
+
console.log(`${BOLD}宜搭环境列表${RESET}`);
|
|
163
|
+
console.log(`${'─'.repeat(50)}`);
|
|
164
|
+
|
|
165
|
+
if (envNames.length === 0) {
|
|
166
|
+
console.log(`${DIM} 暂无环境配置${RESET}`);
|
|
167
|
+
} else {
|
|
168
|
+
for (const envName of envNames) {
|
|
169
|
+
const envConfig = config.environments[envName];
|
|
170
|
+
const label = formatEnvLabel(envName, config.current);
|
|
171
|
+
console.log(` ${label}`);
|
|
172
|
+
console.log(` ${DIM}地址:${RESET}${envConfig.baseUrl || DEFAULT_BASE_URL}`);
|
|
173
|
+
console.log(` ${DIM}登录:${RESET}${getLoginHost(envConfig.loginUrl || DEFAULT_LOGIN_URL)}`);
|
|
174
|
+
if (envConfig.description) {
|
|
175
|
+
console.log(` ${DIM}描述:${RESET}${envConfig.description}`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
console.log('');
|
|
181
|
+
console.log(`${DIM}使用 yidaconnector env setup 进入向导,或 yidaconnector env switch <name> 切换环境${RESET}`);
|
|
182
|
+
console.log(`${DIM}使用 yidaconnector env add <name> 添加私有化环境${RESET}`);
|
|
183
|
+
console.log('');
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* env show [name] - 显示环境详细配置。
|
|
188
|
+
* @param {string} [envName]
|
|
189
|
+
*/
|
|
190
|
+
function cmdShow(envName) {
|
|
191
|
+
const config = loadEnvsConfig();
|
|
192
|
+
const targetName = resolveEnvNameAlias(envName || config.current);
|
|
193
|
+
const envConfig = config.environments[targetName];
|
|
194
|
+
|
|
195
|
+
if (!envConfig) {
|
|
196
|
+
warn(`${RED}错误:环境 "${targetName}" 不存在${RESET}`);
|
|
197
|
+
warn(`使用 ${CYAN}yidaconnector env list${RESET} 查看所有环境`);
|
|
198
|
+
process.exit(1);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const isActive = targetName === config.current;
|
|
202
|
+
|
|
203
|
+
console.log('');
|
|
204
|
+
console.log(`${BOLD}环境详情:${CYAN}${targetName}${RESET}${isActive ? ` ${GREEN}← 当前激活${RESET}` : ''}`);
|
|
205
|
+
console.log(`${'─'.repeat(50)}`);
|
|
206
|
+
console.log(` ${BOLD}地址:${RESET} ${envConfig.baseUrl || DEFAULT_BASE_URL}`);
|
|
207
|
+
console.log(` ${BOLD}登录 URL:${RESET} ${envConfig.loginUrl || DEFAULT_LOGIN_URL}`);
|
|
208
|
+
if (envConfig.description) {
|
|
209
|
+
console.log(` ${BOLD}描述:${RESET} ${envConfig.description}`);
|
|
210
|
+
}
|
|
211
|
+
if (envConfig.dwsEndpoint) {
|
|
212
|
+
console.log(` ${BOLD}DWS 端点:${RESET} ${envConfig.dwsEndpoint}`);
|
|
213
|
+
}
|
|
214
|
+
if (envConfig.tenantId) {
|
|
215
|
+
console.log(` ${BOLD}租户 ID:${RESET} ${envConfig.tenantId}`);
|
|
216
|
+
}
|
|
217
|
+
console.log(` ${BOLD}Cookie 文件:${RESET}${envConfig.cookieFile || 'cookies-public.json'}`);
|
|
218
|
+
console.log('');
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* env switch <name> - 切换当前激活环境。
|
|
223
|
+
* @param {string} envName
|
|
224
|
+
*/
|
|
225
|
+
function cmdSwitch(envName) {
|
|
226
|
+
if (!envName) {
|
|
227
|
+
warn(`${RED}错误:请指定要切换的环境名称${RESET}`);
|
|
228
|
+
warn(`用法:${CYAN}yidaconnector env switch <name>${RESET}`);
|
|
229
|
+
process.exit(1);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const resolvedEnvName = resolveEnvNameAlias(envName);
|
|
233
|
+
const config = loadEnvsConfig();
|
|
234
|
+
|
|
235
|
+
if (!config.environments[resolvedEnvName]) {
|
|
236
|
+
warn(`${RED}错误:环境 "${envName}" 不存在${RESET}`);
|
|
237
|
+
warn(`使用 ${CYAN}yidaconnector env list${RESET} 查看所有环境`);
|
|
238
|
+
process.exit(1);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (config.current === resolvedEnvName) {
|
|
242
|
+
console.log(`${YELLOW}当前已在 "${resolvedEnvName}" 环境,无需切换${RESET}`);
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
switchToEnv(resolvedEnvName);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* env remove <name> - 移除环境配置。
|
|
251
|
+
* @param {string} envName
|
|
252
|
+
*/
|
|
253
|
+
function cmdRemove(envName) {
|
|
254
|
+
if (!envName) {
|
|
255
|
+
warn(`${RED}错误:请指定要移除的环境名称${RESET}`);
|
|
256
|
+
warn(`用法:${CYAN}yidaconnector env remove <name>${RESET}`);
|
|
257
|
+
process.exit(1);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
envName = resolveEnvNameAlias(envName);
|
|
261
|
+
if (isBuiltinEnvName(envName)) {
|
|
262
|
+
warn(`${RED}错误:不能删除内置环境 "${envName}"${RESET}`);
|
|
263
|
+
process.exit(1);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const config = loadEnvsConfig();
|
|
267
|
+
|
|
268
|
+
if (!config.environments[envName]) {
|
|
269
|
+
warn(`${RED}错误:环境 "${envName}" 不存在${RESET}`);
|
|
270
|
+
process.exit(1);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// 若删除的是当前激活环境,自动切回 public
|
|
274
|
+
const wasActive = config.current === envName;
|
|
275
|
+
delete config.environments[envName];
|
|
276
|
+
if (wasActive) {
|
|
277
|
+
config.current = 'public';
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
saveEnvsConfig(config);
|
|
281
|
+
|
|
282
|
+
console.log('');
|
|
283
|
+
console.log(`${GREEN}✅ 已移除环境 "${envName}"${RESET}`);
|
|
284
|
+
if (wasActive) {
|
|
285
|
+
console.log(`${YELLOW}已自动切换回 "public" 环境${RESET}`);
|
|
286
|
+
}
|
|
287
|
+
console.log('');
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* env add <name> - 交互式添加私有化环境配置。
|
|
292
|
+
* @param {string} envName
|
|
293
|
+
*/
|
|
294
|
+
async function cmdAdd(envName) {
|
|
295
|
+
if (!envName) {
|
|
296
|
+
warn(`${RED}错误:请指定环境名称${RESET}`);
|
|
297
|
+
warn(`用法:${CYAN}yidaconnector env add <name>${RESET}`);
|
|
298
|
+
warn(`示例:${CYAN}yidaconnector env add private-prod${RESET}`);
|
|
299
|
+
process.exit(1);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// 环境名称校验:只允许字母、数字、连字符
|
|
303
|
+
if (!/^[a-zA-Z0-9-]+$/.test(envName)) {
|
|
304
|
+
warn(`${RED}错误:环境名称只能包含字母、数字和连字符(-)${RESET}`);
|
|
305
|
+
process.exit(1);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if (envName === 'public') {
|
|
309
|
+
warn(`${RED}错误:"public" 是保留的默认环境名称,不能添加${RESET}`);
|
|
310
|
+
process.exit(1);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if (resolveEnvNameAlias(envName) !== envName || isBuiltinEnvName(envName)) {
|
|
314
|
+
warn(`${RED}错误:"${envName}" 是内置环境或内置别名,不能作为私有化环境名称${RESET}`);
|
|
315
|
+
process.exit(1);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const config = loadEnvsConfig();
|
|
319
|
+
const existingConfig = config.environments[envName];
|
|
320
|
+
|
|
321
|
+
if (existingConfig) {
|
|
322
|
+
console.log(`${YELLOW}环境 "${envName}" 已存在,将更新其配置${RESET}`);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
console.log('');
|
|
326
|
+
console.log(`${BOLD}添加私有化宜搭环境:${CYAN}${envName}${RESET}`);
|
|
327
|
+
console.log(`${'─'.repeat(50)}`);
|
|
328
|
+
console.log(`${DIM}直接回车使用默认值,输入内容后回车确认${RESET}`);
|
|
329
|
+
console.log('');
|
|
330
|
+
|
|
331
|
+
const defaultBaseUrl = existingConfig?.baseUrl || '';
|
|
332
|
+
const baseUrl = await askQuestion(`${BOLD}宜搭服务地址${RESET}(如 https://yida.company.com):`, defaultBaseUrl);
|
|
333
|
+
|
|
334
|
+
if (!baseUrl) {
|
|
335
|
+
warn(`${RED}错误:服务地址不能为空${RESET}`);
|
|
336
|
+
process.exit(1);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// 自动推导登录 URL:yidaapps.com 必须走 login.dingtalk.io OAuth。
|
|
340
|
+
const inferredLoginUrl = inferLoginUrlForBaseUrl(baseUrl);
|
|
341
|
+
const workPlatformLoginUrl = baseUrl.replace(/\/+$/, '') + '/workPlatform';
|
|
342
|
+
const defaultLoginUrl = existingConfig?.loginUrl && existingConfig.loginUrl !== workPlatformLoginUrl
|
|
343
|
+
? existingConfig.loginUrl
|
|
344
|
+
: inferredLoginUrl;
|
|
345
|
+
const loginUrl = await askQuestion(`${BOLD}登录页面地址${RESET}:`, defaultLoginUrl);
|
|
346
|
+
|
|
347
|
+
const defaultDescription = existingConfig?.description || '';
|
|
348
|
+
const description = await askQuestion(`${BOLD}环境描述${RESET}(可选):`, defaultDescription);
|
|
349
|
+
|
|
350
|
+
const defaultDwsEndpoint = existingConfig?.dwsEndpoint || '';
|
|
351
|
+
const dwsEndpoint = await askQuestion(`${BOLD}钉钉 DWS 端点${RESET}(私有化钉钉 OpenAPI 网关,可选):`, defaultDwsEndpoint);
|
|
352
|
+
|
|
353
|
+
const defaultTenantId = existingConfig?.tenantId || '';
|
|
354
|
+
const tenantId = await askQuestion(`${BOLD}租户 ID${RESET}(可选):`, defaultTenantId);
|
|
355
|
+
|
|
356
|
+
// 构建环境配置
|
|
357
|
+
const newEnvConfig = {
|
|
358
|
+
baseUrl: baseUrl.replace(/\/+$/, ''),
|
|
359
|
+
loginUrl: loginUrl || inferredLoginUrl,
|
|
360
|
+
description: description || undefined,
|
|
361
|
+
cookieFile: `cookies-${envName}.json`,
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
if (dwsEndpoint) { newEnvConfig.dwsEndpoint = dwsEndpoint; }
|
|
365
|
+
if (tenantId) { newEnvConfig.tenantId = tenantId; }
|
|
366
|
+
|
|
367
|
+
// 清理 undefined 字段
|
|
368
|
+
Object.keys(newEnvConfig).forEach((key) => {
|
|
369
|
+
if (newEnvConfig[key] === undefined) { delete newEnvConfig[key]; }
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
config.environments[envName] = newEnvConfig;
|
|
373
|
+
saveEnvsConfig(config);
|
|
374
|
+
|
|
375
|
+
console.log('');
|
|
376
|
+
console.log(`${GREEN}✅ 环境 "${envName}" 已${existingConfig ? '更新' : '添加'}${RESET}`);
|
|
377
|
+
console.log('');
|
|
378
|
+
console.log(` 地址:${CYAN}${newEnvConfig.baseUrl}${RESET}`);
|
|
379
|
+
console.log(` 登录:${CYAN}${newEnvConfig.loginUrl}${RESET}`);
|
|
380
|
+
if (newEnvConfig.description) { console.log(` 描述:${newEnvConfig.description}`); }
|
|
381
|
+
console.log('');
|
|
382
|
+
console.log(`${YELLOW}下一步:切换到该环境并登录${RESET}`);
|
|
383
|
+
console.log(` ${CYAN}yidaconnector env switch ${envName}${RESET}`);
|
|
384
|
+
console.log(` ${CYAN}yidaconnector login --qr${RESET}`);
|
|
385
|
+
console.log('');
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
async function cmdSetup() {
|
|
389
|
+
const config = loadEnvsConfig();
|
|
390
|
+
const recommendedEnv = detectSetupRecommendation();
|
|
391
|
+
const options = [
|
|
392
|
+
{
|
|
393
|
+
key: 'public',
|
|
394
|
+
title: '阿里云公有云 / 国内钉钉',
|
|
395
|
+
baseUrl: DEFAULT_PUBLIC_ENV.baseUrl,
|
|
396
|
+
loginUrl: DEFAULT_PUBLIC_ENV.loginUrl,
|
|
397
|
+
},
|
|
398
|
+
{
|
|
399
|
+
key: 'intl',
|
|
400
|
+
title: '海外 YiDA Apps / DingTalk / Dingtalk Wukong',
|
|
401
|
+
baseUrl: DEFAULT_INTERNATIONAL_ENV.baseUrl,
|
|
402
|
+
loginUrl: DEFAULT_INTERNATIONAL_ENV.loginUrl,
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
key: 'alibaba',
|
|
406
|
+
title: '阿里内网员工环境',
|
|
407
|
+
baseUrl: DEFAULT_ALIBABA_INTERNAL_ENV.baseUrl,
|
|
408
|
+
loginUrl: DEFAULT_ALIBABA_INTERNAL_ENV.loginUrl,
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
key: 'custom',
|
|
412
|
+
title: '私有化部署 / 专属域名',
|
|
413
|
+
baseUrl: '自定义',
|
|
414
|
+
loginUrl: '自定义',
|
|
415
|
+
},
|
|
416
|
+
];
|
|
417
|
+
const defaultIndex = Math.max(0, options.findIndex((item) => item.key === recommendedEnv));
|
|
418
|
+
|
|
419
|
+
console.log('');
|
|
420
|
+
console.log(`${BOLD}YidaConnector 环境设置向导${RESET}`);
|
|
421
|
+
console.log(`${'─'.repeat(50)}`);
|
|
422
|
+
console.log(`${DIM}请选择客户实际登录入口。可随时用 yidaconnector env switch 切换。${RESET}`);
|
|
423
|
+
console.log('');
|
|
424
|
+
|
|
425
|
+
options.forEach((item, index) => {
|
|
426
|
+
const isRecommended = index === defaultIndex;
|
|
427
|
+
console.log(` ${CYAN}${index + 1}.${RESET} ${item.title}${isRecommended ? ` ${GREEN}← 推荐${RESET}` : ''}`);
|
|
428
|
+
console.log(` ${DIM}地址:${item.baseUrl}${RESET}`);
|
|
429
|
+
console.log(` ${DIM}登录:${getLoginHost(item.loginUrl)}${RESET}`);
|
|
430
|
+
});
|
|
431
|
+
console.log('');
|
|
432
|
+
|
|
433
|
+
const answer = await askQuestion(`${BOLD}选择环境${RESET}(1-${options.length}):`, String(defaultIndex + 1));
|
|
434
|
+
const selectedIndex = Number.parseInt(answer, 10) - 1;
|
|
435
|
+
const selected = options[selectedIndex];
|
|
436
|
+
if (!selected) {
|
|
437
|
+
warn(`${RED}错误:无效选择${RESET}`);
|
|
438
|
+
process.exit(1);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
if (selected.key === 'custom') {
|
|
442
|
+
const envName = await askQuestion(`${BOLD}私有化环境名称${RESET}(如 private-prod):`, '');
|
|
443
|
+
await cmdAdd(envName);
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
if (config.current === selected.key) {
|
|
448
|
+
console.log('');
|
|
449
|
+
console.log(`${YELLOW}当前已在 "${selected.key}" 环境,无需切换${RESET}`);
|
|
450
|
+
console.log('');
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
switchToEnv(selected.key);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* 显示 env 命令帮助信息。
|
|
459
|
+
*/
|
|
460
|
+
function showHelp() {
|
|
461
|
+
console.log('');
|
|
462
|
+
console.log(`${BOLD}yidaconnector env - 多环境管理${RESET}`);
|
|
463
|
+
console.log('');
|
|
464
|
+
console.log(`${CYAN}用法:${RESET}`);
|
|
465
|
+
console.log(' yidaconnector env <子命令> [参数]');
|
|
466
|
+
console.log('');
|
|
467
|
+
console.log(`${CYAN}子命令:${RESET}`);
|
|
468
|
+
console.log(` ${GREEN}list${RESET} 列出所有环境及当前激活环境`);
|
|
469
|
+
console.log(` ${GREEN}setup${RESET} 交互式选择公有云、海外、内网或私有化环境`);
|
|
470
|
+
console.log(` ${GREEN}add <name>${RESET} 交互式添加私有化环境配置`);
|
|
471
|
+
console.log(` ${GREEN}switch <name>${RESET} 切换当前激活环境`);
|
|
472
|
+
console.log(` ${GREEN}remove <name>${RESET} 移除环境配置`);
|
|
473
|
+
console.log(` ${GREEN}show [name]${RESET} 显示环境详细配置`);
|
|
474
|
+
console.log('');
|
|
475
|
+
console.log(`${CYAN}示例:${RESET}`);
|
|
476
|
+
console.log(` ${BLUE}yidaconnector env list${RESET} 查看所有环境`);
|
|
477
|
+
console.log(` ${BLUE}yidaconnector env setup${RESET} 进入环境设置向导`);
|
|
478
|
+
console.log(` ${BLUE}yidaconnector env add private-prod${RESET} 添加私有化生产环境`);
|
|
479
|
+
console.log(` ${BLUE}yidaconnector env switch private-prod${RESET} 切换到私有化环境`);
|
|
480
|
+
console.log(` ${BLUE}yidaconnector env show private-prod${RESET} 查看环境详情`);
|
|
481
|
+
console.log(` ${BLUE}yidaconnector env remove private-prod${RESET} 删除私有化环境`);
|
|
482
|
+
console.log('');
|
|
483
|
+
console.log(`${CYAN}环境变量(优先级高于配置文件):${RESET}`);
|
|
484
|
+
console.log(` ${YELLOW}YIDACONNECTOR_ENDPOINT${RESET}=https://yida.company.com 强制指定宜搭地址`);
|
|
485
|
+
console.log(` ${YELLOW}YIDACONNECTOR_LOGIN_URL${RESET}=https://... 强制指定登录页`);
|
|
486
|
+
console.log(` ${YELLOW}YIDACONNECTOR_ENV${RESET}=private-prod 快速切换环境(不修改配置文件)`);
|
|
487
|
+
console.log(` ${YELLOW}YIDACONNECTOR_DWS_ENDPOINT${RESET}=https://dws.company.com 私有化钉钉网关`);
|
|
488
|
+
console.log('');
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// ── 主入口 ────────────────────────────────────────────
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* env 命令主入口。
|
|
495
|
+
* @param {string[]} args - process.argv.slice(3) 之后的参数
|
|
496
|
+
*/
|
|
497
|
+
async function run(args) {
|
|
498
|
+
const subCommand = args[0];
|
|
499
|
+
const subArgs = args.slice(1);
|
|
500
|
+
|
|
501
|
+
switch (subCommand) {
|
|
502
|
+
case 'list':
|
|
503
|
+
case undefined:
|
|
504
|
+
cmdList();
|
|
505
|
+
break;
|
|
506
|
+
|
|
507
|
+
case 'show':
|
|
508
|
+
cmdShow(subArgs[0]);
|
|
509
|
+
break;
|
|
510
|
+
|
|
511
|
+
case 'switch':
|
|
512
|
+
cmdSwitch(subArgs[0]);
|
|
513
|
+
break;
|
|
514
|
+
|
|
515
|
+
case 'setup':
|
|
516
|
+
case 'init':
|
|
517
|
+
case 'configure':
|
|
518
|
+
await cmdSetup();
|
|
519
|
+
break;
|
|
520
|
+
|
|
521
|
+
case 'remove':
|
|
522
|
+
case 'rm':
|
|
523
|
+
case 'delete':
|
|
524
|
+
cmdRemove(subArgs[0]);
|
|
525
|
+
break;
|
|
526
|
+
|
|
527
|
+
case 'add':
|
|
528
|
+
case 'create':
|
|
529
|
+
await cmdAdd(subArgs[0]);
|
|
530
|
+
break;
|
|
531
|
+
|
|
532
|
+
case '--help':
|
|
533
|
+
case '-h':
|
|
534
|
+
case 'help':
|
|
535
|
+
showHelp();
|
|
536
|
+
break;
|
|
537
|
+
|
|
538
|
+
default:
|
|
539
|
+
warn(`${RED}未知的 env 子命令:${subCommand}${RESET}`);
|
|
540
|
+
warn(`使用 ${CYAN}yidaconnector env --help${RESET} 查看帮助`);
|
|
541
|
+
process.exit(1);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
module.exports = { run };
|