openyida 2026.7.13 → 2026.7.14-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 +15 -22
- package/bin/yida.js +72 -220
- package/lib/agent-center/api.js +2 -2
- package/lib/aggregate-table/aggregate-table.js +2 -2
- package/lib/ai/ai.js +7 -12
- package/lib/app/canvas-compile.js +2 -2
- package/lib/app/create-app.js +5 -19
- package/lib/app/create-form.js +54 -76
- package/lib/app/create-page.js +4 -19
- package/lib/app/er.js +11 -8
- package/lib/app/export-app.js +2 -2
- package/lib/app/externalize-form.js +12 -10
- package/lib/app/get-schema.js +12 -10
- package/lib/app/import-app.js +6 -22
- package/lib/app/list-forms.js +3 -19
- package/lib/app/nav-group.js +6 -19
- package/lib/app/publish.js +60 -198
- package/lib/app/update-app.js +4 -18
- package/lib/app/update-form-config.js +20 -113
- package/lib/app-permission/app-permission.js +2 -2
- package/lib/auth/oauth-loopback.js +156 -0
- package/lib/auth/org.js +169 -322
- package/lib/auth/token-auth.js +346 -0
- package/lib/auth/token-store.js +174 -0
- package/lib/basic-info/basic-info.js +11 -12
- package/lib/bridge/bridge.js +29 -27
- package/lib/connector/api.js +4 -4
- package/lib/core/agent-capabilities.js +92 -8
- package/lib/core/batch.js +8 -8
- package/lib/core/check-data.js +2 -2
- package/lib/core/command-manifest.js +3 -3
- package/lib/core/doctor.js +19 -22
- package/lib/core/env-cmd.js +1 -3
- package/lib/core/env-manager.js +8 -121
- package/lib/core/env.js +30 -72
- package/lib/core/locales/ar.js +5 -5
- package/lib/core/locales/de.js +5 -5
- package/lib/core/locales/en.js +26 -26
- package/lib/core/locales/es.js +5 -5
- package/lib/core/locales/fr.js +5 -5
- package/lib/core/locales/hi.js +5 -5
- package/lib/core/locales/ja.js +14 -14
- package/lib/core/locales/ko.js +5 -5
- package/lib/core/locales/pt.js +5 -5
- package/lib/core/locales/vi.js +5 -5
- package/lib/core/locales/zh-HK.js +15 -15
- package/lib/core/locales/zh.js +26 -26
- package/lib/core/query-data.js +2 -2
- package/lib/core/task-center.js +2 -2
- package/lib/core/utils.js +156 -400
- package/lib/core/yida-client.js +57 -22
- package/lib/corp-efficiency/corp-efficiency.js +3 -3
- package/lib/corp-manager/api.js +2 -2
- package/lib/db/db-seq-fix.js +20 -25
- package/lib/flash-note/flash-to-prd.js +2 -2
- package/lib/i18n-management/i18n-management.js +2 -2
- package/lib/integration/integration-check.js +10 -7
- package/lib/integration/integration-create.js +11 -8
- package/lib/integration/integration-list.js +11 -8
- package/lib/mcp/server.js +5 -54
- package/lib/page-config/get-page-config.js +2 -2
- package/lib/page-config/save-share-config.js +2 -2
- package/lib/page-config/verify-short-url.js +2 -2
- package/lib/permission/get-permission.js +2 -2
- package/lib/permission/save-permission.js +2 -2
- package/lib/process/ai-form-setting.js +2 -2
- package/lib/process/create-process.js +2 -2
- package/lib/process/preview-process.js +2 -2
- package/lib/report/append.js +3 -3
- package/lib/report/index.js +3 -3
- package/package.json +1 -1
- package/scripts/check-syntax.js +6 -0
- package/scripts/e2e-real/full-runner.js +2 -10
- package/scripts/e2e-real/runner.js +0 -31
- package/scripts/eval/screenshot.js +27 -69
- package/scripts/nightly-smoke.js +16 -34
- package/scripts/postinstall.js +6 -2
- package/yida-skills/SKILL.md +10 -6
- package/yida-skills/references/development-rules.md +2 -2
- package/yida-skills/references/setup-and-env.md +10 -9
- package/yida-skills/skills/sls-log-workbench/SKILL.md +2 -2
- package/yida-skills/skills/sls-log-workbench/sls-query.js +27 -54
- package/yida-skills/skills/yida-flash-note-to-prd/SKILL.md +1 -1
- package/yida-skills/skills/yida-integration/SKILL.md +3 -3
- package/yida-skills/skills/yida-login/SKILL.md +56 -74
- package/yida-skills/skills/yida-logout/SKILL.md +13 -12
- package/yida-skills/skills/yida-process-rule/SKILL.md +1 -1
- package/yida-skills/skills/yida-publish-page/SKILL.md +1 -1
- package/yida-skills/skills/yida-report/references/report-api-guide.md +4 -20
- package/yida-skills/skills-index.json +4 -4
- package/lib/auth/auth.js +0 -313
- package/lib/auth/cdp-browser-login.js +0 -390
- package/lib/auth/codex-login.js +0 -71
- package/lib/auth/login.js +0 -550
- package/lib/auth/qr-login.js +0 -1575
|
@@ -1,22 +1,96 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const crypto = require('crypto');
|
|
3
4
|
const path = require('path');
|
|
4
5
|
const { version } = require('../../package.json');
|
|
5
6
|
const { t } = require('./i18n');
|
|
6
7
|
const { buildCommandManifest } = require('./command-manifest');
|
|
7
8
|
const { buildEnvironmentSnapshot } = require('./env');
|
|
8
|
-
const {
|
|
9
|
+
const { tokenStatus } = require('../auth/token-auth');
|
|
9
10
|
|
|
10
11
|
function redactLogin(login) {
|
|
11
12
|
const redacted = { ...login };
|
|
12
|
-
delete redacted.
|
|
13
|
-
delete redacted.
|
|
13
|
+
delete redacted.access_token;
|
|
14
|
+
delete redacted.refresh_token;
|
|
14
15
|
return redacted;
|
|
15
16
|
}
|
|
16
17
|
|
|
18
|
+
function compactLogin(login) {
|
|
19
|
+
return {
|
|
20
|
+
status: login.status,
|
|
21
|
+
can_auto_use: login.can_auto_use === true,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function canonicalize(value) {
|
|
26
|
+
if (Array.isArray(value)) {
|
|
27
|
+
return value.map(canonicalize);
|
|
28
|
+
}
|
|
29
|
+
if (!value || typeof value !== 'object') {
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return Object.keys(value)
|
|
34
|
+
.sort()
|
|
35
|
+
.reduce((result, key) => {
|
|
36
|
+
result[key] = canonicalize(value[key]);
|
|
37
|
+
return result;
|
|
38
|
+
}, {});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function buildCommandManifestDigest(manifest) {
|
|
42
|
+
const digestPayload = {
|
|
43
|
+
schema_version: manifest.schema_version,
|
|
44
|
+
command_prefix: manifest.command_prefix,
|
|
45
|
+
summary: {
|
|
46
|
+
command_count: manifest.summary.command_count,
|
|
47
|
+
group_count: manifest.summary.group_count,
|
|
48
|
+
side_effect_counts: manifest.summary.side_effect_counts,
|
|
49
|
+
permission_mode_counts: manifest.summary.permission_mode_counts,
|
|
50
|
+
core_workflows: manifest.summary.core_workflows,
|
|
51
|
+
},
|
|
52
|
+
commands: manifest.commands.map(entry => ({
|
|
53
|
+
id: entry.id,
|
|
54
|
+
usage: entry.usage,
|
|
55
|
+
requires_login: entry.requires_login,
|
|
56
|
+
output: entry.output,
|
|
57
|
+
side_effect_kind: entry.side_effect && entry.side_effect.kind,
|
|
58
|
+
permission_mode: entry.permission && entry.permission.mode,
|
|
59
|
+
permission_effect: entry.permission && entry.permission.effect,
|
|
60
|
+
})),
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
return crypto
|
|
64
|
+
.createHash('sha256')
|
|
65
|
+
.update(JSON.stringify(canonicalize(digestPayload)))
|
|
66
|
+
.digest('hex');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function buildAgentCapabilitiesSummary() {
|
|
70
|
+
const envSnapshot = buildEnvironmentSnapshot();
|
|
71
|
+
const loginStatus = tokenStatus({ includeSecrets: false });
|
|
72
|
+
const manifest = buildCommandManifest({ t, version });
|
|
73
|
+
const projectRoot = envSnapshot.active.projectRoot;
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
schema_version: 1,
|
|
77
|
+
name: 'openyida-agent-capabilities-summary',
|
|
78
|
+
version,
|
|
79
|
+
login: compactLogin(loginStatus),
|
|
80
|
+
workdir: projectRoot,
|
|
81
|
+
workdir_exists: !!envSnapshot.active.projectRootExists,
|
|
82
|
+
cache_dir: path.join(projectRoot, '.cache'),
|
|
83
|
+
openyida_task_cache_dir: path.join(projectRoot, '.cache', 'openyida'),
|
|
84
|
+
command_manifest_digest: buildCommandManifestDigest(manifest),
|
|
85
|
+
command_manifest_digest_algorithm: 'sha256',
|
|
86
|
+
command_count: manifest.summary.command_count,
|
|
87
|
+
full_capabilities_command: 'openyida agent-capabilities --json',
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
17
91
|
function buildAgentCapabilities() {
|
|
18
92
|
const envSnapshot = buildEnvironmentSnapshot();
|
|
19
|
-
const loginStatus = redactLogin(
|
|
93
|
+
const loginStatus = redactLogin(tokenStatus({ includeSecrets: false }));
|
|
20
94
|
const manifest = buildCommandManifest({ t, version });
|
|
21
95
|
const projectRoot = envSnapshot.active.projectRoot;
|
|
22
96
|
|
|
@@ -32,7 +106,8 @@ function buildAgentCapabilities() {
|
|
|
32
106
|
active: envSnapshot.active,
|
|
33
107
|
login: loginStatus,
|
|
34
108
|
recommended: {
|
|
35
|
-
preflight_command: 'openyida agent-capabilities --json',
|
|
109
|
+
preflight_command: 'openyida agent-capabilities --summary-json',
|
|
110
|
+
full_capabilities_command: 'openyida agent-capabilities --json',
|
|
36
111
|
mutation_guard: 'Run mutating commands only when login.status is ok or after a successful openyida login.',
|
|
37
112
|
workdir: projectRoot,
|
|
38
113
|
cache_dir: path.join(projectRoot, '.cache'),
|
|
@@ -58,7 +133,7 @@ function buildAgentCapabilities() {
|
|
|
58
133
|
},
|
|
59
134
|
sideEffects: {
|
|
60
135
|
read_only_preflight: [
|
|
61
|
-
'openyida agent-capabilities --json',
|
|
136
|
+
'openyida agent-capabilities --summary-json',
|
|
62
137
|
'openyida env --json',
|
|
63
138
|
'openyida login --check-only --json',
|
|
64
139
|
'openyida commands --json',
|
|
@@ -80,11 +155,20 @@ function buildAgentCapabilities() {
|
|
|
80
155
|
};
|
|
81
156
|
}
|
|
82
157
|
|
|
83
|
-
|
|
84
|
-
|
|
158
|
+
function shouldUseSummary(args = []) {
|
|
159
|
+
return args.includes('--summary-json') || args.includes('--compact');
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
async function run(args = []) {
|
|
163
|
+
const payload = shouldUseSummary(args)
|
|
164
|
+
? buildAgentCapabilitiesSummary()
|
|
165
|
+
: buildAgentCapabilities();
|
|
166
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
85
167
|
}
|
|
86
168
|
|
|
87
169
|
module.exports = {
|
|
88
170
|
buildAgentCapabilities,
|
|
171
|
+
buildAgentCapabilitiesSummary,
|
|
172
|
+
buildCommandManifestDigest,
|
|
89
173
|
run,
|
|
90
174
|
};
|
package/lib/core/batch.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* batch.js - 批量命令编排(一次登录,多条命令复用
|
|
2
|
+
* batch.js - 批量命令编排(一次登录,多条命令复用 token 缓存)
|
|
3
3
|
*
|
|
4
4
|
* 用法:
|
|
5
5
|
* openyida batch <commands-file> # 从文件读取,每行一条命令
|
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
* 设计要点:
|
|
15
15
|
* - 零侵入:不修改任何已有命令的 run() 函数
|
|
16
16
|
* - 每条子命令通过 child_process.execFileSync 调用 bin/yida.js,
|
|
17
|
-
*
|
|
17
|
+
* token 文件已在磁盘上,各命令读取时直接命中缓存(零登录开销)
|
|
18
18
|
* - 子命令自动注入 --quiet,stdout 只收 JSON,stderr 静默
|
|
19
|
-
* - batch 启动时先做一次
|
|
19
|
+
* - batch 启动时先做一次 loadAuthData 预检,确保登录态可用
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
'use strict';
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
const fs = require('fs');
|
|
25
25
|
const path = require('path');
|
|
26
26
|
const { execFileSync } = require('child_process');
|
|
27
|
-
const {
|
|
27
|
+
const { loadAuthData, triggerLogin } = require('./utils');
|
|
28
28
|
const { banner, step, success, fail, info, warn, result, label } = require('./chalk');
|
|
29
29
|
|
|
30
30
|
const YIDA_BIN = path.resolve(__dirname, '../../bin/yida.js');
|
|
@@ -211,12 +211,12 @@ async function run(args) {
|
|
|
211
211
|
step(1, '检查登录态');
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
-
let
|
|
215
|
-
if (!
|
|
214
|
+
let authData = loadAuthData();
|
|
215
|
+
if (!authData) {
|
|
216
216
|
if (!quiet) { info('未找到登录缓存,触发登录...'); }
|
|
217
|
-
|
|
217
|
+
authData = triggerLogin();
|
|
218
218
|
}
|
|
219
|
-
if (!
|
|
219
|
+
if (!authData) {
|
|
220
220
|
fail('登录失败,无法执行批量命令');
|
|
221
221
|
console.log(JSON.stringify({ success: false, error: 'login_failed' }));
|
|
222
222
|
process.exit(1);
|
package/lib/core/check-data.js
CHANGED
|
@@ -17,7 +17,7 @@ const fs = require('fs');
|
|
|
17
17
|
const path = require('path');
|
|
18
18
|
const { warn } = require('./chalk');
|
|
19
19
|
const { CliError } = require('./cli-error');
|
|
20
|
-
const { createAuthRef, createYidaClient } = require('./yida-client');
|
|
20
|
+
const { createAuthRef, createYidaClient, isAuthRefReady } = require('./yida-client');
|
|
21
21
|
|
|
22
22
|
const USAGE = `openyida data check - 流程表单异常数据检测
|
|
23
23
|
|
|
@@ -78,7 +78,7 @@ function parseError(message) {
|
|
|
78
78
|
|
|
79
79
|
function ensureSession() {
|
|
80
80
|
const authRef = createAuthRef();
|
|
81
|
-
if (!authRef
|
|
81
|
+
if (!isAuthRefReady(authRef)) {
|
|
82
82
|
fail('无法获取有效登录态或 CSRF Token');
|
|
83
83
|
}
|
|
84
84
|
return authRef;
|
|
@@ -703,13 +703,13 @@ const COMMAND_GROUPS = [
|
|
|
703
703
|
id: 'auth',
|
|
704
704
|
titleKey: 'help.group_auth',
|
|
705
705
|
commands: [
|
|
706
|
-
command('login', ['login'], 'login [target-url] [--
|
|
706
|
+
command('login', ['login'], 'login [target-url] [--env <name>|--intl|--overseas|--global|--yidaapps|--alibaba] [--client-id <clientId>] [--endpoint <url>]', 'help.cmd_login', {
|
|
707
707
|
requiresLogin: false,
|
|
708
708
|
output: 'json',
|
|
709
709
|
}),
|
|
710
710
|
command('logout', ['logout'], 'logout', 'help.cmd_logout', { requiresLogin: false }),
|
|
711
711
|
command('auth', ['auth'], 'auth <status|login|refresh|logout>', 'help.cmd_auth', { requiresLogin: false }),
|
|
712
|
-
command('org', ['org'], 'org <list|switch>', 'help.cmd_org'),
|
|
712
|
+
command('org', ['org'], 'org <list|switch> [--json] [--corp-id <corpId>]', 'help.cmd_org'),
|
|
713
713
|
command('env', ['env'], 'env [--json|setup|list|show|switch|add|remove] [options]', 'help.cmd_env', {
|
|
714
714
|
requiresLogin: false,
|
|
715
715
|
output: 'text|json',
|
|
@@ -871,7 +871,7 @@ const COMMAND_GROUPS = [
|
|
|
871
871
|
requiresLogin: false,
|
|
872
872
|
output: 'json',
|
|
873
873
|
}),
|
|
874
|
-
command('agent-capabilities', ['agent-capabilities'], 'agent-capabilities [--json]', 'help.cmd_agent_capabilities', {
|
|
874
|
+
command('agent-capabilities', ['agent-capabilities'], 'agent-capabilities [--json] [--summary-json|--compact]', 'help.cmd_agent_capabilities', {
|
|
875
875
|
requiresLogin: false,
|
|
876
876
|
output: 'json',
|
|
877
877
|
}),
|
package/lib/core/doctor.js
CHANGED
|
@@ -199,19 +199,19 @@ class EnvironmentChecker {
|
|
|
199
199
|
require.resolve('playwright');
|
|
200
200
|
return {
|
|
201
201
|
id: 'env-playwright',
|
|
202
|
-
label: '
|
|
202
|
+
label: '可选浏览器能力(Playwright 已安装)',
|
|
203
203
|
passed: true,
|
|
204
204
|
severity: Severity.INFO,
|
|
205
|
-
message: '
|
|
205
|
+
message: '当前 CLI 默认使用 OAuth token 登录;Playwright 仅用于少量浏览器预览或兼容场景',
|
|
206
206
|
fixType: null,
|
|
207
207
|
};
|
|
208
208
|
} catch {
|
|
209
209
|
return {
|
|
210
210
|
id: 'env-playwright',
|
|
211
|
-
label: '
|
|
211
|
+
label: '可选浏览器能力(Playwright 未安装)',
|
|
212
212
|
passed: true,
|
|
213
213
|
severity: Severity.INFO,
|
|
214
|
-
message: '
|
|
214
|
+
message: '当前 CLI 默认使用 OAuth token 登录,不依赖 Playwright',
|
|
215
215
|
fixType: null,
|
|
216
216
|
};
|
|
217
217
|
}
|
|
@@ -254,32 +254,29 @@ class EnvironmentChecker {
|
|
|
254
254
|
}
|
|
255
255
|
|
|
256
256
|
checkLoginStatus() {
|
|
257
|
-
|
|
258
|
-
const {
|
|
259
|
-
const cookieData = loadCookieData(this.projectRoot);
|
|
257
|
+
const { tokenStatus } = require('../auth/token-auth');
|
|
258
|
+
const status = tokenStatus({ projectRoot: this.projectRoot });
|
|
260
259
|
|
|
261
|
-
if (
|
|
260
|
+
if (status.status !== 'ok') {
|
|
262
261
|
return {
|
|
263
262
|
id: 'env-login',
|
|
264
|
-
label: '
|
|
263
|
+
label: '宜搭 token 登录态',
|
|
265
264
|
passed: false,
|
|
266
265
|
severity: Severity.WARNING,
|
|
267
|
-
message: '
|
|
266
|
+
message: '未登录或 token 已过期(运行 openyida login 登录)',
|
|
268
267
|
fixType: FixType.COMMAND,
|
|
269
|
-
fixCommand: 'openyida login
|
|
268
|
+
fixCommand: 'openyida login',
|
|
270
269
|
};
|
|
271
270
|
}
|
|
272
271
|
|
|
273
|
-
const hasToken = cookieData.cookies.some((c) => c.name === 'tianshu_csrf_token');
|
|
274
|
-
const passed = hasToken;
|
|
275
272
|
return {
|
|
276
273
|
id: 'env-login',
|
|
277
|
-
label:
|
|
278
|
-
passed,
|
|
279
|
-
severity:
|
|
280
|
-
message:
|
|
281
|
-
fixType:
|
|
282
|
-
fixCommand:
|
|
274
|
+
label: '宜搭 token 登录态:已登录',
|
|
275
|
+
passed: true,
|
|
276
|
+
severity: Severity.INFO,
|
|
277
|
+
message: null,
|
|
278
|
+
fixType: null,
|
|
279
|
+
fixCommand: null,
|
|
283
280
|
};
|
|
284
281
|
}
|
|
285
282
|
|
|
@@ -287,10 +284,10 @@ class EnvironmentChecker {
|
|
|
287
284
|
try {
|
|
288
285
|
const https = require('https');
|
|
289
286
|
const http = require('http');
|
|
290
|
-
const {
|
|
287
|
+
const { loadAuthData } = require('./utils');
|
|
291
288
|
const { resolveEndpoint } = require('./env-manager');
|
|
292
|
-
const
|
|
293
|
-
const baseUrl = resolveEndpoint(
|
|
289
|
+
const authData = loadAuthData(this.projectRoot);
|
|
290
|
+
const baseUrl = resolveEndpoint(authData, this.projectRoot);
|
|
294
291
|
const parsedUrl = new URL(baseUrl);
|
|
295
292
|
const requestModule = parsedUrl.protocol === 'https:' ? https : http;
|
|
296
293
|
await new Promise((resolve, reject) => {
|
package/lib/core/env-cmd.js
CHANGED
|
@@ -214,7 +214,6 @@ function cmdShow(envName) {
|
|
|
214
214
|
if (envConfig.tenantId) {
|
|
215
215
|
console.log(` ${BOLD}租户 ID:${RESET} ${envConfig.tenantId}`);
|
|
216
216
|
}
|
|
217
|
-
console.log(` ${BOLD}Cookie 文件:${RESET}${envConfig.cookieFile || 'cookies-public.json'}`);
|
|
218
217
|
console.log('');
|
|
219
218
|
}
|
|
220
219
|
|
|
@@ -358,7 +357,6 @@ async function cmdAdd(envName) {
|
|
|
358
357
|
baseUrl: baseUrl.replace(/\/+$/, ''),
|
|
359
358
|
loginUrl: loginUrl || inferredLoginUrl,
|
|
360
359
|
description: description || undefined,
|
|
361
|
-
cookieFile: `cookies-${envName}.json`,
|
|
362
360
|
};
|
|
363
361
|
|
|
364
362
|
if (dwsEndpoint) { newEnvConfig.dwsEndpoint = dwsEndpoint; }
|
|
@@ -381,7 +379,7 @@ async function cmdAdd(envName) {
|
|
|
381
379
|
console.log('');
|
|
382
380
|
console.log(`${YELLOW}下一步:切换到该环境并登录${RESET}`);
|
|
383
381
|
console.log(` ${CYAN}openyida env switch ${envName}${RESET}`);
|
|
384
|
-
console.log(` ${CYAN}openyida login
|
|
382
|
+
console.log(` ${CYAN}openyida login${RESET}`);
|
|
385
383
|
console.log('');
|
|
386
384
|
}
|
|
387
385
|
|
package/lib/core/env-manager.js
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* env-manager.js - 多环境配置管理
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* 支持公有云与私有化宜搭并存,通过环境配置文件管理多套端点。
|
|
5
5
|
*
|
|
6
6
|
* 配置文件:{projectRoot}/.cache/openyida-envs.json
|
|
7
|
-
* Cookie 隔离:.cache/cookies-{envName}.json
|
|
8
|
-
*
|
|
9
7
|
* 优先级(高 → 低):
|
|
10
8
|
* 1. 环境变量 OPENYIDA_ENDPOINT
|
|
11
|
-
* 2.
|
|
9
|
+
* 2. authData.base_url(登录后实际跳转域名)
|
|
12
10
|
* 3. 环境变量 OPENYIDA_ENV 指定的环境配置
|
|
13
11
|
* 4. 当前激活的环境配置(openyida-envs.json current 字段)
|
|
14
12
|
* 5. 默认公有云 https://www.aliwork.com
|
|
@@ -17,11 +15,8 @@
|
|
|
17
15
|
* loadEnvsConfig() - 读取环境配置文件(不存在则返回默认公有云配置)
|
|
18
16
|
* saveEnvsConfig(config) - 写入环境配置文件
|
|
19
17
|
* getCurrentEnvConfig() - 获取当前激活的环境配置(含环境变量覆盖)
|
|
20
|
-
* getCookieFilePath(root) - 获取当前环境的 Cookie 文件绝对路径
|
|
21
|
-
* migrateOldCookieFile() - 迁移旧版 cookies.json → cookies-public.json
|
|
22
18
|
* resolveEndpoint() - 解析最终 baseUrl(含完整优先级)
|
|
23
19
|
* resolveLoginUrl() - 解析最终登录 URL
|
|
24
|
-
* deriveBaseUrlFromLoginState() - 从 Cookie + 浏览器当前 URL 解析实际 baseUrl
|
|
25
20
|
*/
|
|
26
21
|
|
|
27
22
|
'use strict';
|
|
@@ -95,7 +90,6 @@ const DEFAULT_PUBLIC_ENV = {
|
|
|
95
90
|
baseUrl: DEFAULT_BASE_URL,
|
|
96
91
|
loginUrl: DEFAULT_LOGIN_URL,
|
|
97
92
|
description: '阿里云公有云宜搭',
|
|
98
|
-
cookieFile: 'cookies-public.json',
|
|
99
93
|
};
|
|
100
94
|
|
|
101
95
|
/** 阿里内网宜搭环境配置 */
|
|
@@ -103,7 +97,6 @@ const DEFAULT_ALIBABA_INTERNAL_ENV = {
|
|
|
103
97
|
baseUrl: ALIBABA_INTERNAL_BASE_URL,
|
|
104
98
|
loginUrl: ALIBABA_INTERNAL_LOGIN_URL,
|
|
105
99
|
description: '阿里内网宜搭',
|
|
106
|
-
cookieFile: 'cookies-alibaba.json',
|
|
107
100
|
};
|
|
108
101
|
|
|
109
102
|
/** 海外版 YiDA / DingTalk International 环境配置 */
|
|
@@ -111,7 +104,6 @@ const DEFAULT_INTERNATIONAL_ENV = {
|
|
|
111
104
|
baseUrl: INTERNATIONAL_BASE_URL,
|
|
112
105
|
loginUrl: INTERNATIONAL_LOGIN_URL,
|
|
113
106
|
description: '海外版 YiDA Apps / DingTalk International(www.yidaapps.com)',
|
|
114
|
-
cookieFile: 'cookies-intl.json',
|
|
115
107
|
};
|
|
116
108
|
|
|
117
109
|
const BUILTIN_ENVIRONMENTS = {
|
|
@@ -158,13 +150,6 @@ const ENV_ALIASES = {
|
|
|
158
150
|
'内网': 'alibaba',
|
|
159
151
|
};
|
|
160
152
|
|
|
161
|
-
const SHARED_COOKIE_DOMAINS = new Set([
|
|
162
|
-
'aliwork.com',
|
|
163
|
-
'yidaapps.com',
|
|
164
|
-
'alibaba-inc.com',
|
|
165
|
-
'yidaapps.com',
|
|
166
|
-
]);
|
|
167
|
-
|
|
168
153
|
const KNOWN_YIDA_HOSTS = new Set([
|
|
169
154
|
'www.aliwork.com',
|
|
170
155
|
'www.yidaapps.com',
|
|
@@ -208,8 +193,7 @@ function isLegacyInternationalEnv(envConfig) {
|
|
|
208
193
|
return !!(
|
|
209
194
|
envConfig &&
|
|
210
195
|
normalizeBaseUrl(envConfig.baseUrl, null) === DEFAULT_BASE_URL &&
|
|
211
|
-
(!envConfig.loginUrl || envConfig.loginUrl === LEGACY_INTERNATIONAL_LOGIN_URL)
|
|
212
|
-
(!envConfig.cookieFile || envConfig.cookieFile === 'cookies-intl.json')
|
|
196
|
+
(!envConfig.loginUrl || envConfig.loginUrl === LEGACY_INTERNATIONAL_LOGIN_URL)
|
|
213
197
|
);
|
|
214
198
|
}
|
|
215
199
|
|
|
@@ -244,10 +228,6 @@ function normalizeHostname(value) {
|
|
|
244
228
|
return trimmed;
|
|
245
229
|
}
|
|
246
230
|
|
|
247
|
-
function isSharedCookieDomain(hostname) {
|
|
248
|
-
return SHARED_COOKIE_DOMAINS.has(normalizeHostname(hostname));
|
|
249
|
-
}
|
|
250
|
-
|
|
251
231
|
function isYidaServiceHost(hostname) {
|
|
252
232
|
const host = normalizeHostname(hostname);
|
|
253
233
|
if (!host) { return false; }
|
|
@@ -323,55 +303,6 @@ function inferLoginUrlForBaseUrl(baseUrl, fallbackLoginUrl) {
|
|
|
323
303
|
return fallbackLoginUrl || `${normalizedBaseUrl}/workPlatform`;
|
|
324
304
|
}
|
|
325
305
|
|
|
326
|
-
function cookieDomainToBaseUrl(domain, fallbackUrl) {
|
|
327
|
-
const host = normalizeHostname(domain);
|
|
328
|
-
if (!host || isSharedCookieDomain(host)) {
|
|
329
|
-
return null;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
const fallbackOrigin = normalizeBaseUrl(fallbackUrl, null);
|
|
333
|
-
if (fallbackOrigin) {
|
|
334
|
-
const fallbackHost = normalizeHostname(fallbackOrigin);
|
|
335
|
-
if (host === fallbackHost) {
|
|
336
|
-
return fallbackOrigin;
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
if (isYidaServiceHost(host)) {
|
|
341
|
-
return `https://${host}`;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
return null;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
function deriveBaseUrlFromCookies(cookies = [], fallbackUrl = DEFAULT_BASE_URL) {
|
|
348
|
-
const fallbackOrigin = normalizeBaseUrl(fallbackUrl, DEFAULT_BASE_URL);
|
|
349
|
-
const cookieList = Array.isArray(cookies) ? cookies : [];
|
|
350
|
-
const preferredCookieNames = ['yida_user_cookie', 'tianshu_csrf_token'];
|
|
351
|
-
|
|
352
|
-
for (const cookieName of preferredCookieNames) {
|
|
353
|
-
const cookie = cookieList.find((item) => item && item.name === cookieName && item.domain);
|
|
354
|
-
const baseUrl = cookie ? cookieDomainToBaseUrl(cookie.domain, fallbackOrigin) : null;
|
|
355
|
-
if (baseUrl) { return baseUrl; }
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
return fallbackOrigin;
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
function deriveBaseUrlFromLoginState(cookies = [], loginUrl = DEFAULT_LOGIN_URL, currentUrl = null) {
|
|
362
|
-
const fallbackBaseUrl = deriveBaseUrlFromUrl(loginUrl, currentUrl);
|
|
363
|
-
const cookieBaseUrl = deriveBaseUrlFromCookies(cookies, fallbackBaseUrl);
|
|
364
|
-
const currentOrigin = normalizeBaseUrl(currentUrl, null);
|
|
365
|
-
const currentHost = normalizeHostname(currentOrigin);
|
|
366
|
-
const loginHost = normalizeHostname(normalizeBaseUrl(loginUrl, null));
|
|
367
|
-
|
|
368
|
-
if (currentOrigin && isYidaServiceHost(currentHost) && currentHost !== loginHost) {
|
|
369
|
-
return currentOrigin;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
return cookieBaseUrl;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
306
|
function deriveBaseUrlFromUrl(fallbackBaseUrl, candidateUrl) {
|
|
376
307
|
let fallbackOrigin = normalizeBaseUrl(fallbackBaseUrl, DEFAULT_BASE_URL);
|
|
377
308
|
const fallbackHost = normalizeHostname(fallbackOrigin);
|
|
@@ -468,67 +399,27 @@ function getCurrentEnvConfig(projectRoot) {
|
|
|
468
399
|
return { name: envName, config: envConfig };
|
|
469
400
|
}
|
|
470
401
|
|
|
471
|
-
// ── Cookie 文件路径 ───────────────────────────────────
|
|
472
|
-
|
|
473
|
-
/**
|
|
474
|
-
* 获取当前环境的 Cookie 文件绝对路径。
|
|
475
|
-
* 若环境配置不存在,兜底使用 cookies-public.json。
|
|
476
|
-
* @param {string} [projectRoot]
|
|
477
|
-
* @returns {string}
|
|
478
|
-
*/
|
|
479
|
-
function getCookieFilePath(projectRoot) {
|
|
480
|
-
const root = projectRoot || findProjectRoot();
|
|
481
|
-
const { config: envConfig } = getCurrentEnvConfig(root);
|
|
482
|
-
const cookieFileName = envConfig.cookieFile || 'cookies-public.json';
|
|
483
|
-
return path.join(root, '.cache', cookieFileName);
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
// ── 旧版 Cookie 迁移 ──────────────────────────────────
|
|
487
|
-
|
|
488
|
-
/**
|
|
489
|
-
* 将旧版 cookies.json 迁移为 cookies-public.json。
|
|
490
|
-
* 仅在旧文件存在且新文件不存在时执行,保证向后兼容。
|
|
491
|
-
* @param {string} [projectRoot]
|
|
492
|
-
* @returns {boolean} 是否执行了迁移
|
|
493
|
-
*/
|
|
494
|
-
function migrateOldCookieFile(projectRoot) {
|
|
495
|
-
const root = projectRoot || findProjectRoot();
|
|
496
|
-
const oldFile = path.join(root, '.cache', 'cookies.json');
|
|
497
|
-
const newFile = path.join(root, '.cache', 'cookies-public.json');
|
|
498
|
-
|
|
499
|
-
if (fs.existsSync(oldFile) && !fs.existsSync(newFile)) {
|
|
500
|
-
try {
|
|
501
|
-
fs.copyFileSync(oldFile, newFile);
|
|
502
|
-
// 保留旧文件作为备份,不删除,避免其他工具依赖
|
|
503
|
-
return true;
|
|
504
|
-
} catch {
|
|
505
|
-
return false;
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
return false;
|
|
509
|
-
}
|
|
510
|
-
|
|
511
402
|
// ── 端点解析 ──────────────────────────────────────────
|
|
512
403
|
|
|
513
404
|
/**
|
|
514
405
|
* 解析最终的 baseUrl,按优先级:
|
|
515
406
|
* 1. OPENYIDA_ENDPOINT 环境变量
|
|
516
|
-
* 2.
|
|
407
|
+
* 2. authData.base_url(登录后实际跳转域名)
|
|
517
408
|
* 3. 当前激活环境配置的 baseUrl
|
|
518
409
|
* 4. 默认公有云
|
|
519
|
-
* @param {object} [
|
|
410
|
+
* @param {object} [authData]
|
|
520
411
|
* @param {string} [projectRoot]
|
|
521
412
|
* @returns {string}
|
|
522
413
|
*/
|
|
523
|
-
function resolveEndpoint(
|
|
414
|
+
function resolveEndpoint(authData, projectRoot) {
|
|
524
415
|
// 优先级 1:环境变量强制指定
|
|
525
416
|
if (process.env.OPENYIDA_ENDPOINT) {
|
|
526
417
|
return normalizeBaseUrl(process.env.OPENYIDA_ENDPOINT, DEFAULT_BASE_URL);
|
|
527
418
|
}
|
|
528
419
|
|
|
529
420
|
// 优先级 2:登录缓存中记录的实际服务域名
|
|
530
|
-
if (
|
|
531
|
-
return normalizeBaseUrl(
|
|
421
|
+
if (authData && authData.base_url) {
|
|
422
|
+
return normalizeBaseUrl(authData.base_url, DEFAULT_BASE_URL);
|
|
532
423
|
}
|
|
533
424
|
|
|
534
425
|
// 优先级 3:当前激活环境配置
|
|
@@ -584,8 +475,6 @@ module.exports = {
|
|
|
584
475
|
loadEnvsConfig,
|
|
585
476
|
saveEnvsConfig,
|
|
586
477
|
getCurrentEnvConfig,
|
|
587
|
-
getCookieFilePath,
|
|
588
|
-
migrateOldCookieFile,
|
|
589
478
|
resolveEndpoint,
|
|
590
479
|
resolveLoginUrl,
|
|
591
480
|
normalizeBaseUrl,
|
|
@@ -595,7 +484,5 @@ module.exports = {
|
|
|
595
484
|
inferEnvironmentNameFromUrl,
|
|
596
485
|
inferLoginUrlForBaseUrl,
|
|
597
486
|
deriveBaseUrlFromDingtalkOAuthUrl,
|
|
598
|
-
deriveBaseUrlFromCookies,
|
|
599
|
-
deriveBaseUrlFromLoginState,
|
|
600
487
|
deriveBaseUrlFromUrl,
|
|
601
488
|
};
|