@dreamor/atlas-cli 0.7.23 → 0.7.24
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.github.md +230 -0
- package/README.md +1 -59
- package/atlas.cjs +226 -0
- package/package.json +7 -9
- package/atlas.js +0 -5
- package/dist/adapters/atlas/auth/browser.js +0 -37
- package/dist/adapters/atlas/auth/index.js +0 -4
- package/dist/adapters/atlas/auth/login.js +0 -187
- package/dist/adapters/atlas/auth/portable.js +0 -193
- package/dist/adapters/atlas/auth/refresh.js +0 -138
- package/dist/adapters/atlas/auth/session.js +0 -167
- package/dist/adapters/atlas/cli.js +0 -561
- package/dist/adapters/atlas/commands/_output_schema.js +0 -379
- package/dist/adapters/atlas/commands/actual/_logic.js +0 -116
- package/dist/adapters/atlas/commands/actual/index.js +0 -138
- package/dist/adapters/atlas/commands/auth.js +0 -1
- package/dist/adapters/atlas/commands/baseline/index.js +0 -137
- package/dist/adapters/atlas/commands/compare/_logic.js +0 -39
- package/dist/adapters/atlas/commands/compare/index.js +0 -89
- package/dist/adapters/atlas/commands/exec.js +0 -81
- package/dist/adapters/atlas/commands/project/index.js +0 -218
- package/dist/adapters/atlas/commands/schema.js +0 -25
- package/dist/adapters/atlas/commands/suggest.js +0 -83
- package/dist/adapters/atlas/commands/update.js +0 -104
- package/dist/adapters/atlas/daemon/index.js +0 -145
- package/dist/adapters/atlas/dict/index.js +0 -41
- package/dist/adapters/atlas/http/client.js +0 -200
- package/dist/adapters/atlas/http/index.js +0 -1
- package/dist/adapters/atlas/schema/actual.js +0 -16
- package/dist/adapters/atlas/schema/baseline.js +0 -34
- package/dist/adapters/atlas/schema/department.js +0 -11
- package/dist/adapters/atlas/schema/index.js +0 -4
- package/dist/adapters/atlas/schema/project.js +0 -13
- package/dist/adapters/atlas/util/cidr.js +0 -114
- package/dist/adapters/atlas/util/constants.js +0 -4
- package/dist/adapters/atlas/util/env.js +0 -56
- package/dist/adapters/atlas/util/environment.js +0 -152
- package/dist/adapters/atlas/util/errors.js +0 -49
- package/dist/adapters/atlas/util/helpers.js +0 -17
- package/dist/adapters/atlas/util/months.js +0 -65
- package/dist/adapters/atlas/util/output-limit.js +0 -21
- package/dist/adapters/atlas/util/output.js +0 -70
- package/dist/adapters/atlas/util/paths.js +0 -40
- package/dist/adapters/atlas/util/portable-store.js +0 -153
- package/dist/adapters/atlas/util/secure-fs.js +0 -41
- package/dist/adapters/atlas/util/time.js +0 -17
- package/dist/adapters/atlas/util/version.js +0 -1
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
import { readFile, unlink } from 'fs/promises';
|
|
2
|
-
import { existsSync } from 'fs';
|
|
3
|
-
import { secureMkdir, secureWriteFile } from '../util/secure-fs.js';
|
|
4
|
-
import { getAtlasHome, getCookieFile } from '../util/paths.js';
|
|
5
|
-
const SESSION_DIR = getAtlasHome();
|
|
6
|
-
const COOKIE_FILE = getCookieFile();
|
|
7
|
-
let cachedCookies = null;
|
|
8
|
-
/**
|
|
9
|
-
* 读取持久化的 cookies(从本地文件)
|
|
10
|
-
* Playwright SSO 登录后将 cookies 写入此文件
|
|
11
|
-
*
|
|
12
|
-
* 沙盒免命令登录:本地文件缺失时若设置了 ATLAS_COOKIES_B64,则内存中一次性
|
|
13
|
-
* import(不落盘),让 agent 只注入 secret 就能用上。这条路径在 startAuthRefresh
|
|
14
|
-
* 之外的成本几乎为零,避免每次调用都重新解 base64/gzip。
|
|
15
|
-
*/
|
|
16
|
-
export async function readCookies() {
|
|
17
|
-
if (cachedCookies)
|
|
18
|
-
return cachedCookies;
|
|
19
|
-
try {
|
|
20
|
-
if (!existsSync(COOKIE_FILE)) {
|
|
21
|
-
// 沙盒自动导入:ATLAS_COOKIES_B64 内存注入(不落盘)
|
|
22
|
-
const b64 = process.env.ATLAS_COOKIES_B64;
|
|
23
|
-
if (b64 && b64.trim().length > 0) {
|
|
24
|
-
const imported = await importFromEnvBase64(b64);
|
|
25
|
-
if (imported && imported.length > 0) {
|
|
26
|
-
cachedCookies = imported;
|
|
27
|
-
return imported;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
const data = await readFile(COOKIE_FILE, 'utf-8');
|
|
33
|
-
const cookies = JSON.parse(data);
|
|
34
|
-
cachedCookies = cookies;
|
|
35
|
-
return cookies;
|
|
36
|
-
}
|
|
37
|
-
catch {
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* 解 ATLAS_COOKIES_B64 环境变量为新版 portable bundle(gzip+base64 JSON)。
|
|
43
|
-
* 兼容旧格式:纯 JSON 数组 cookies(无 manifest 包装)。
|
|
44
|
-
* 失败返回 null,绝不抛——避免阻塞主流程。
|
|
45
|
-
*/
|
|
46
|
-
async function importFromEnvBase64(b64) {
|
|
47
|
-
try {
|
|
48
|
-
const { parseBundleBase64 } = await import('../util/portable-store.js');
|
|
49
|
-
const { bundle } = await parseBundleBase64(b64);
|
|
50
|
-
return bundle.cookies;
|
|
51
|
-
}
|
|
52
|
-
catch {
|
|
53
|
-
// 兼容:直接是纯 JSON 数组字符串(非 gzip)
|
|
54
|
-
try {
|
|
55
|
-
const parsed = JSON.parse(b64);
|
|
56
|
-
if (Array.isArray(parsed))
|
|
57
|
-
return parsed;
|
|
58
|
-
}
|
|
59
|
-
catch {
|
|
60
|
-
// fallthrough
|
|
61
|
-
}
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
/** 仅内存导入(importCmd --persist=false 用),不落盘 */
|
|
66
|
-
export function __setCachedCookiesForImport(cookies) {
|
|
67
|
-
cachedCookies = cookies;
|
|
68
|
-
}
|
|
69
|
-
export async function writeCookies(cookies) {
|
|
70
|
-
cachedCookies = cookies;
|
|
71
|
-
await secureMkdir(SESSION_DIR, { recursive: true });
|
|
72
|
-
await secureWriteFile(COOKIE_FILE, JSON.stringify(cookies, null, 2));
|
|
73
|
-
}
|
|
74
|
-
export async function clearCookies() {
|
|
75
|
-
cachedCookies = null;
|
|
76
|
-
try {
|
|
77
|
-
await unlink(COOKIE_FILE);
|
|
78
|
-
}
|
|
79
|
-
catch {
|
|
80
|
-
// ignore
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* 从 daemon 获取 cookies(附带 Bearer token 鉴权)。
|
|
85
|
-
*
|
|
86
|
-
* 连接配置走 resolveDaemonConfig():优先 ATLAS_DAEMON_URL + ATLAS_DAEMON_TOKEN
|
|
87
|
-
* (沙盒连宿主机 daemon),回退 localhost + 本机 ~/.atlas/daemon.token(本机复用)。
|
|
88
|
-
* 失败返回 null,绝不抛——调用方据此降级到本地 cookies。
|
|
89
|
-
*/
|
|
90
|
-
export async function fetchCookiesFromDaemon() {
|
|
91
|
-
try {
|
|
92
|
-
const { resolveDaemonConfig } = await import('../util/environment.js');
|
|
93
|
-
const cfg = resolveDaemonConfig();
|
|
94
|
-
if (!cfg.url)
|
|
95
|
-
return null;
|
|
96
|
-
// token:env 优先(ATLAS_DAEMON_TOKEN),回退本地 token 文件(default 分支)
|
|
97
|
-
let token = cfg.token ?? '';
|
|
98
|
-
if (!token) {
|
|
99
|
-
const { getDaemonTokenFile } = await import('../util/paths.js');
|
|
100
|
-
const tokenFile = getDaemonTokenFile();
|
|
101
|
-
if (existsSync(tokenFile)) {
|
|
102
|
-
token = (await readFile(tokenFile, 'utf-8')).trim();
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
const { request } = await import('undici');
|
|
106
|
-
const headers = {};
|
|
107
|
-
if (token)
|
|
108
|
-
headers['Authorization'] = `Bearer ${token}`;
|
|
109
|
-
const resp = await request(`${cfg.url.replace(/\/$/, '')}/api/cookies`, {
|
|
110
|
-
headers,
|
|
111
|
-
headersTimeout: 5000,
|
|
112
|
-
bodyTimeout: 5000,
|
|
113
|
-
});
|
|
114
|
-
const text = await resp.body.text();
|
|
115
|
-
const json = JSON.parse(text);
|
|
116
|
-
if (json?.cookies && Array.isArray(json.cookies)) {
|
|
117
|
-
return json.cookies;
|
|
118
|
-
}
|
|
119
|
-
return null;
|
|
120
|
-
}
|
|
121
|
-
catch {
|
|
122
|
-
return null;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
/** 兼容旧接口:从 cookies 中提取第一个可用的 token 类值 */
|
|
126
|
-
export async function getSessionToken() {
|
|
127
|
-
const cookies = await readCookies();
|
|
128
|
-
if (!cookies || cookies.length === 0)
|
|
129
|
-
return null;
|
|
130
|
-
// Try to find an auth token cookie
|
|
131
|
-
const tokenCookie = cookies.find((c) => c.name.includes('token') ||
|
|
132
|
-
c.name.includes('sid') ||
|
|
133
|
-
c.name.includes('session') ||
|
|
134
|
-
c.name.includes('SESSION'));
|
|
135
|
-
// 没找到 token cookie 时返回 null,避免返回无效 cookie 导致上层误判为"已登录"
|
|
136
|
-
return tokenCookie?.value ?? null;
|
|
137
|
-
}
|
|
138
|
-
const findCookie = (cookies, name) => cookies.find((c) => c.name === name);
|
|
139
|
-
/**
|
|
140
|
-
* 从已有 cookies 派生 Banma 身份。纯函数,无副作用,便于测试。
|
|
141
|
-
* 任一来源缺失对应字段返回空字符串;cookies 为空数组返回 null。
|
|
142
|
-
*/
|
|
143
|
-
export function getBanmaIdentity(cookies) {
|
|
144
|
-
if (!cookies || cookies.length === 0)
|
|
145
|
-
return null;
|
|
146
|
-
const token = findCookie(cookies, 'access_token')?.value ?? '';
|
|
147
|
-
const user = findCookie(cookies, 'buc_username')?.value ?? '';
|
|
148
|
-
// buc_userinfo 是 base64 编码的 JSON,含 emp_id / account / name 等
|
|
149
|
-
let staffId = '';
|
|
150
|
-
const userinfoValue = findCookie(cookies, 'buc_userinfo')?.value;
|
|
151
|
-
if (userinfoValue) {
|
|
152
|
-
try {
|
|
153
|
-
const decoded = JSON.parse(Buffer.from(userinfoValue, 'base64').toString('utf-8'));
|
|
154
|
-
if (decoded && decoded.emp_id != null)
|
|
155
|
-
staffId = String(decoded.emp_id);
|
|
156
|
-
}
|
|
157
|
-
catch {
|
|
158
|
-
// 解码或解析失败:保持空字符串,不阻断请求
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
return { token, user, staffId };
|
|
162
|
-
}
|
|
163
|
-
/** 读取持久化 cookies 并派生 Banma 身份,供 HttpClient 使用 */
|
|
164
|
-
export async function readBanmaIdentity() {
|
|
165
|
-
const cookies = await readCookies();
|
|
166
|
-
return getBanmaIdentity(cookies);
|
|
167
|
-
}
|