@dependfix/engine 0.4.0 → 0.6.0
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/dist/auth.d.mts +2 -184
- package/dist/auth.mjs +1 -1
- package/dist/{auth2.mjs → chunks/auth.mjs} +9 -14
- package/dist/chunks/auth.mjs.map +1 -0
- package/dist/chunks/index.d.mts +254 -0
- package/dist/index.d.mts +1168 -242
- package/dist/index.mjs +11372 -5222
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -9
- package/dist/auth-provider.d.mts +0 -82
- package/dist/auth2.mjs.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dependfix/engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "dependfix 执行引擎:编排、采集、修复与研判核心(cli / mcp / platform 共享)",
|
|
5
5
|
"author": "CaoMeiYouRen",
|
|
6
6
|
"license": "MIT",
|
|
@@ -39,23 +39,25 @@
|
|
|
39
39
|
"dist"
|
|
40
40
|
],
|
|
41
41
|
"engines": {
|
|
42
|
-
"node": "
|
|
42
|
+
"node": "^22.23.4 || ^24.22.1"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@octokit/auth-app": "^8.3.1",
|
|
46
46
|
"@octokit/request-error": "^7.1.2",
|
|
47
47
|
"@octokit/rest": "^22.0.1",
|
|
48
|
-
"p-queue": "^
|
|
48
|
+
"p-queue": "^10.0.0",
|
|
49
|
+
"semver": "^7.8.5",
|
|
49
50
|
"tslib": "^2.8.1",
|
|
50
|
-
"yaml": "^2.9.
|
|
51
|
-
"zod": "^4.6.
|
|
52
|
-
"@dependfix/core": "0.
|
|
51
|
+
"yaml": "^2.9.1",
|
|
52
|
+
"zod": "^4.6.7",
|
|
53
|
+
"@dependfix/core": "0.7.0"
|
|
53
54
|
},
|
|
54
55
|
"devDependencies": {
|
|
55
|
-
"@types/node": "^26.
|
|
56
|
-
"
|
|
56
|
+
"@types/node": "^26.6.6",
|
|
57
|
+
"@types/semver": "^7.8.0",
|
|
58
|
+
"nock": "^15.0.5",
|
|
57
59
|
"rimraf": "^6.1.3",
|
|
58
|
-
"tsdown": "^0.23.
|
|
60
|
+
"tsdown": "^0.23.4",
|
|
59
61
|
"typescript": "^6.0.3"
|
|
60
62
|
},
|
|
61
63
|
"publishConfig": {
|
package/dist/auth-provider.d.mts
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import { Octokit } from "@octokit/rest";
|
|
2
|
-
//#region src/auth/auth-provider.d.ts
|
|
3
|
-
/**
|
|
4
|
-
* GitHub 认证抽象层。
|
|
5
|
-
*
|
|
6
|
-
* 支持 PAT(classic / fine-grained)与 GitHub App installation token 两种认证路径。
|
|
7
|
-
* 调用方通过 `getOctokit()` 获取已认证的 Octokit 实例;通过 `getGitCredential()`
|
|
8
|
-
* 获取推送/clone 用的 Git 凭据;通过 `getCommitAuthor()` 获取 commit author 信息。
|
|
9
|
-
*
|
|
10
|
-
* `authProvider` 字段用于审计与调试(区分 PAT vs App 路径)。
|
|
11
|
-
*
|
|
12
|
-
* @example
|
|
13
|
-
* ```typescript
|
|
14
|
-
* // 推荐:从 fromPat / fromApp 工厂构造
|
|
15
|
-
* const auth = fromPat('ghp_xxxx')
|
|
16
|
-
* const octokit = auth.getOctokit()
|
|
17
|
-
*
|
|
18
|
-
* // git push 凭据
|
|
19
|
-
* const { username, token } = auth.getGitCredential()
|
|
20
|
-
*
|
|
21
|
-
* // commit author(PAT 路径固定;App 路径动态)
|
|
22
|
-
* const { name, email } = auth.getCommitAuthor()
|
|
23
|
-
* ```
|
|
24
|
-
*/
|
|
25
|
-
interface AuthProvider {
|
|
26
|
-
/** 获取已认证的 Octokit 实例 */
|
|
27
|
-
getOctokit(): Octokit;
|
|
28
|
-
/** 获取推送 / clone 用的 Git 凭据(用户名 + token) */
|
|
29
|
-
getGitCredential(): {
|
|
30
|
-
username: string;
|
|
31
|
-
token: string;
|
|
32
|
-
};
|
|
33
|
-
/**
|
|
34
|
-
* 获取 commit author 信息。
|
|
35
|
-
*
|
|
36
|
-
* - PAT 路径:固定返回 `{ name: 'dependfix[bot]', email: 'dependfix[bot]@users.noreply.github.com' }`(保持现有行为零变化)
|
|
37
|
-
* - GitHub App 路径:动态生成 `{app_id}+{bot_login}[bot]@users.noreply.github.com`(GitHub App 协议要求)
|
|
38
|
-
*/
|
|
39
|
-
getCommitAuthor(): {
|
|
40
|
-
name: string;
|
|
41
|
-
email: string;
|
|
42
|
-
};
|
|
43
|
-
/** 认证路径标识(用于审计 + 调试) */
|
|
44
|
-
readonly authProvider: 'pat' | 'github-app';
|
|
45
|
-
}
|
|
46
|
-
/** 工厂函数统一选项(与 OctokitClientOptions.retry 字段对齐) */
|
|
47
|
-
interface AuthProviderOptions {
|
|
48
|
-
/** API 限流 / 次要限流指数退避重试策略。默认 maxRetries=3。 */
|
|
49
|
-
retry?: {
|
|
50
|
-
maxRetries?: number;
|
|
51
|
-
baseDelayMs?: number;
|
|
52
|
-
maxBackoffMs?: number;
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
/** PAT 工厂参数(仅 token;retry 在 options 注入) */
|
|
56
|
-
type FromPatParams = string;
|
|
57
|
-
/** GitHub App 工厂参数 */
|
|
58
|
-
interface FromAppParams {
|
|
59
|
-
/** GitHub App ID */
|
|
60
|
-
appId: string;
|
|
61
|
-
/** PEM 格式私钥 */
|
|
62
|
-
privateKey: string;
|
|
63
|
-
/** Installation ID */
|
|
64
|
-
installationId: string;
|
|
65
|
-
/** Bot 用户名(用于 commit author 动态生成;M18.1 commit 4 实施) */
|
|
66
|
-
botLogin?: string;
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* PAT 路径固定 commit author(保持现有行为零变化)。
|
|
70
|
-
*
|
|
71
|
-
* 注:现有 PAT 路径硬编码 `dependfix[bot]@users.noreply.github.com`,虽非真实 bot 身份(字符串约定),
|
|
72
|
-
* 但保持行为不变以确保 PAT 用户无感升级。已知缺陷由 C22 范围之外的后续阶段修复。
|
|
73
|
-
*/
|
|
74
|
-
declare const PAT_COMMIT_AUTHOR: {
|
|
75
|
-
readonly name: "dependfix[bot]";
|
|
76
|
-
readonly email: "dependfix[bot]@users.noreply.github.com";
|
|
77
|
-
};
|
|
78
|
-
/** PAT 路径固定 Git 用户名(用于 git push 时的 Basic Auth) */
|
|
79
|
-
declare const PAT_GIT_USERNAME = "x-access-token";
|
|
80
|
-
//#endregion
|
|
81
|
-
export { PAT_COMMIT_AUTHOR as a, FromPatParams as i, AuthProviderOptions as n, PAT_GIT_USERNAME as o, FromAppParams as r, AuthProvider as t };
|
|
82
|
-
//# sourceMappingURL=auth-provider.d.mts.map
|
package/dist/auth2.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auth2.mjs","names":[],"sources":["../src/github/client.ts","../src/auth/auth-provider.ts","../src/auth/pat-provider.ts","../src/auth/app-provider.ts","../src/auth/installation-token-cache.ts"],"sourcesContent":["import { Octokit } from '@octokit/rest'\nimport { RequestError } from '@octokit/request-error'\nimport type { AuthProvider } from '../auth/auth-provider'\n\nexport interface RetryPolicyOptions {\n /** 最大重试次数(默认 3;0 = 不重试) */\n maxRetries?: number\n /** 指数退避基数毫秒(默认 1000;测试时可调小) */\n baseDelayMs?: number\n /**\n * 指数退避单次等待上限毫秒(默认 30000),防止长时间空转。\n * Retry-After / x-ratelimit-reset 指定的等待同样受此上限约束。\n */\n maxBackoffMs?: number\n}\n\nexport interface OctokitClientOptions {\n /**\n * 认证抽象层(M18.1 实施后唯一推荐入口)。\n *\n * 调用方应通过 `fromPat(token)` 或 `fromApp(params)` 构造;\n * 优先使用此字段,新代码不得使用 deprecated 的 `token` 字段。\n *\n * @see {@link ../auth/auth-provider} AuthProvider 接口定义\n * @see [C22 PAT 无感升级评估 §4.2 AuthProvider 接口设计](../../../../docs/design/governance/c22-pat-backward-compat.md)\n */\n auth?: AuthProvider\n\n /**\n * @deprecated 使用 `auth` 替代。\n *\n * 保留作为低层入口;`token` 路径与 `auth: fromPat(token)` 行为等价\n * (共享同一 retry policy 与限流重试 hook)。\n * 计划在 M19+ 评估移除。\n */\n token?: string\n\n /**\n * API 基地址。\n * 默认 `https://api.github.com`。\n * 测试时指向 nock 拦截的同一地址。\n */\n baseUrl?: string\n\n /**\n * API 限流 / 次要限流(secondary rate limit)指数退避重试策略。\n * 默认 maxRetries=3。对 429、primary rate limit(403 + x-ratelimit-remaining: 0)、\n * secondary rate limit(403/429 带 secondary/abuse/retry 特征)自动退避重试;\n * 权限类 403 不重试。\n *\n * 行为由具体 AuthProvider 实现决定:\n * - `PatAuthProvider` 委托给本函数(`createGitHubClient({ token, retry })`)—— retry 字段透传生效\n * - `AppAuthProvider` 自管 retry(commit 4 实施)\n */\n retry?: RetryPolicyOptions\n}\n\n/**\n * 创建已认证的 Octokit 实例。\n *\n * 调用方直接使用 `octokit.rest.*` 访问所有已类型化的 GitHub REST API。\n * 分页使用 `octokit.paginate()` 自动合并多页结果。\n *\n * 配置 `retry` 时通过 `hook.wrap('request')` 统一包装所有请求\n * (含 paginate 内部请求),对限流响应做指数退避重试。\n *\n * @example\n * ```typescript\n * // 推荐:使用 auth 抽象层(M18.1 实施后)\n * import { fromPat } from '@dependfix/engine/auth'\n * const octokit = createGitHubClient({ auth: fromPat('ghp_xxxx') })\n *\n * // 向后兼容:使用 token 字段(deprecated)\n * const octokit = createGitHubClient({ token: 'ghp_xxxx' })\n *\n * // 仓库信息\n * const { data: repo } = await octokit.rest.repos.get({ owner: 'foo', repo: 'bar' })\n *\n * // Dependabot 告警(自动分页)\n * const alerts = await octokit.paginate(\n * octokit.rest.dependabot.listAlertsForRepo,\n * { owner: 'foo', repo: 'bar', state: 'open', per_page: 100 },\n * )\n * ```\n */\nexport function createGitHubClient(options: OctokitClientOptions): Octokit {\n // 优先使用 auth 抽象层\n if (options.auth) {\n return options.auth.getOctokit()\n }\n\n // 向后兼容:token 路径保留原实现(限流重试 + Octokit 构造)\n if (!options.token) {\n throw new Error('createGitHubClient: must provide either `auth` (AuthProvider) or `token` (deprecated)')\n }\n\n const client = new Octokit({\n auth: options.token,\n baseUrl: options.baseUrl ?? 'https://api.github.com',\n })\n\n const maxRetries = options.retry?.maxRetries ?? 3\n if (maxRetries > 0) {\n applyRetryPolicy(client, {\n maxRetries,\n baseDelayMs: options.retry?.baseDelayMs ?? 1000,\n maxBackoffMs: options.retry?.maxBackoffMs ?? MAX_BACKOFF_MS_DEFAULT,\n })\n }\n\n return client\n}\n\n// ---------------------------------------------------------------------------\n// Retry policy(统一 hook 包装,对全部请求生效)\n// ---------------------------------------------------------------------------\n\nconst SECONDARY_RATE_LIMIT_RE = /secondary rate limit|abuse|retry later|retry-after/i\n/** 指数退避单次等待默认上限(30s),防止长时间空转(可经 retry.maxBackoffMs 覆盖) */\nconst MAX_BACKOFF_MS_DEFAULT = 30_000\n\nfunction applyRetryPolicy(client: Octokit, retry: RetryPolicyOptions): void {\n const maxRetries = retry.maxRetries ?? 3\n const baseDelayMs = retry.baseDelayMs ?? 1000\n const maxBackoffMs = retry.maxBackoffMs ?? MAX_BACKOFF_MS_DEFAULT\n\n client.hook.wrap('request', async (request, options) => {\n // 写请求(POST/PATCH/PUT/DELETE)不做限流重试——非幂等操作避免重放;\n // 限流重试仅适用于只读 GET/HEAD(GitHub 限流检查在请求执行前,写请求重放风险虽低仍应规避)\n const method = (options.method ?? 'GET').toUpperCase()\n if (method !== 'GET' && method !== 'HEAD') {\n return request(options)\n }\n\n let attempt = 0\n for (;;) {\n try {\n return await request(options)\n } catch (error: unknown) {\n const delayMs = computeRetryDelayMs(error, attempt, baseDelayMs, maxBackoffMs)\n if (delayMs === null || attempt >= maxRetries) {\n throw error\n }\n attempt += 1\n await sleep(delayMs)\n }\n }\n })\n}\n\n/**\n * 计算限流重试等待时间(纯函数,可单测)。\n *\n * 可重试(返回等待毫秒):\n * - 429(Too Many Requests / secondary rate limit)\n * - 403 + `x-ratelimit-remaining: 0`(primary rate limit)\n * - 403/429 + message 含 secondary rate limit / abuse / retry 特征\n *\n * 等待策略(Retry-After 优先):\n * 1. `retry-after` 头(秒)→ 等待其秒数(受 maxBackoffMs 上限约束)\n * 2. `x-ratelimit-reset`(unix 秒)→ 等待到 reset + 1s 缓冲\n * 3. 否则 → 指数退避 `baseDelayMs * 2^attempt`\n * 所有等待均受 maxBackoffMs 上限约束(默认 30s)。\n *\n * 不重试(返回 null):\n * - 非 RequestError(网络错误等由上层 AppError 语义处理)\n * - 权限类 403(无限流特征)\n * - 其他状态码\n */\nexport function computeRetryDelayMs(\n error: unknown,\n attempt: number,\n baseDelayMs = 1000,\n maxBackoffMs = MAX_BACKOFF_MS_DEFAULT,\n): number | null {\n if (!(error instanceof RequestError)) {\n return null\n }\n\n const status = error.status\n const headers = error.response?.headers ?? {}\n const remaining = headers['x-ratelimit-remaining']\n const message = error.message\n\n let retryable = false\n if (status === 429) {\n retryable = true\n } else if (status === 403) {\n if (remaining !== undefined && remaining === '0') {\n retryable = true // primary rate limit\n } else if (SECONDARY_RATE_LIMIT_RE.test(message)) {\n retryable = true // secondary rate limit(403 形态)\n }\n }\n\n if (!retryable) {\n return null\n }\n\n // Retry-After 头优先(GitHub secondary rate limit 常返回,秒为单位)\n const retryAfter = headers['retry-after']\n if (retryAfter !== undefined) {\n const seconds = Number(retryAfter)\n if (Number.isFinite(seconds) && seconds > 0) {\n return Math.min(seconds * 1000, maxBackoffMs)\n }\n }\n\n // 其次等待到限流重置时刻(primary rate limit 标准行为)\n const reset = headers['x-ratelimit-reset']\n if (reset !== undefined) {\n const resetMs = Number(reset) * 1000\n if (Number.isFinite(resetMs) && resetMs > 0) {\n const waitMs = resetMs - Date.now() + 1000\n if (waitMs > 0) {\n return Math.min(waitMs, maxBackoffMs)\n }\n }\n }\n\n // 指数退避兜底\n return Math.min(baseDelayMs * 2 ** attempt, maxBackoffMs)\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n","import type { Octokit } from '@octokit/rest'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * GitHub 认证抽象层。\n *\n * 支持 PAT(classic / fine-grained)与 GitHub App installation token 两种认证路径。\n * 调用方通过 `getOctokit()` 获取已认证的 Octokit 实例;通过 `getGitCredential()`\n * 获取推送/clone 用的 Git 凭据;通过 `getCommitAuthor()` 获取 commit author 信息。\n *\n * `authProvider` 字段用于审计与调试(区分 PAT vs App 路径)。\n *\n * @example\n * ```typescript\n * // 推荐:从 fromPat / fromApp 工厂构造\n * const auth = fromPat('ghp_xxxx')\n * const octokit = auth.getOctokit()\n *\n * // git push 凭据\n * const { username, token } = auth.getGitCredential()\n *\n * // commit author(PAT 路径固定;App 路径动态)\n * const { name, email } = auth.getCommitAuthor()\n * ```\n */\nexport interface AuthProvider {\n /** 获取已认证的 Octokit 实例 */\n getOctokit(): Octokit\n\n /** 获取推送 / clone 用的 Git 凭据(用户名 + token) */\n getGitCredential(): { username: string, token: string }\n\n /**\n * 获取 commit author 信息。\n *\n * - PAT 路径:固定返回 `{ name: 'dependfix[bot]', email: 'dependfix[bot]@users.noreply.github.com' }`(保持现有行为零变化)\n * - GitHub App 路径:动态生成 `{app_id}+{bot_login}[bot]@users.noreply.github.com`(GitHub App 协议要求)\n */\n getCommitAuthor(): { name: string, email: string }\n\n /** 认证路径标识(用于审计 + 调试) */\n readonly authProvider: 'pat' | 'github-app'\n}\n\n/** 工厂函数统一选项(与 OctokitClientOptions.retry 字段对齐) */\nexport interface AuthProviderOptions {\n /** API 限流 / 次要限流指数退避重试策略。默认 maxRetries=3。 */\n retry?: {\n maxRetries?: number\n baseDelayMs?: number\n maxBackoffMs?: number\n }\n}\n\n/** PAT 工厂参数(仅 token;retry 在 options 注入) */\nexport type FromPatParams = string\n\n/** GitHub App 工厂参数 */\nexport interface FromAppParams {\n /** GitHub App ID */\n appId: string\n /** PEM 格式私钥 */\n privateKey: string\n /** Installation ID */\n installationId: string\n /** Bot 用户名(用于 commit author 动态生成;M18.1 commit 4 实施) */\n botLogin?: string\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/**\n * PAT 路径固定 commit author(保持现有行为零变化)。\n *\n * 注:现有 PAT 路径硬编码 `dependfix[bot]@users.noreply.github.com`,虽非真实 bot 身份(字符串约定),\n * 但保持行为不变以确保 PAT 用户无感升级。已知缺陷由 C22 范围之外的后续阶段修复。\n */\nexport const PAT_COMMIT_AUTHOR = {\n name: 'dependfix[bot]',\n email: 'dependfix[bot]@users.noreply.github.com',\n} as const\n\n/** PAT 路径固定 Git 用户名(用于 git push 时的 Basic Auth) */\nexport const PAT_GIT_USERNAME = 'x-access-token'\n","import { Octokit } from '@octokit/rest'\nimport { createGitHubClient } from '../github/client'\nimport {\n PAT_COMMIT_AUTHOR,\n PAT_GIT_USERNAME,\n type AuthProvider,\n type AuthProviderOptions,\n type FromPatParams,\n} from './auth-provider'\n\n/**\n * PAT 工厂函数。委托给 `PatAuthProvider` 类。\n *\n * 保留 `fromPat` 命名习惯便于与 `fromApp` 对齐(统一工厂语义)。\n *\n * @example\n * ```typescript\n * const auth = fromPat('ghp_xxxx')\n * const octokit = auth.getOctokit()\n * const { username, token } = auth.getGitCredential()\n * ```\n */\nexport function fromPat(token: FromPatParams, options?: AuthProviderOptions): AuthProvider {\n return new PatAuthProvider(token, options)\n}\n\n/**\n * PAT 认证路径实现。\n *\n * `getOctokit()` 委托给 [`createGitHubClient`](../github/client.ts) 以复用现有 retry policy 与限流重试实现;\n * Octokit 实例缓存以避免重复构造(每次 `new Octokit()` + `hook.wrap()` 都有开销)。\n *\n * 行为与原 `createGitHubClient({ token })` 等价:\n * - `getOctokit()` 返回通过 PAT 认证的 Octokit 实例(含限流重试 hook)\n * - `getGitCredential()` 返回推送用的 Basic Auth(username = `'x-access-token'`)\n * - `getCommitAuthor()` 返回固定 `dependfix[bot]`(PAT 路径用户行为零变化)\n *\n * @example\n * ```typescript\n * const auth = new PatAuthProvider('ghp_xxxx', { retry: { maxRetries: 3 } })\n * const octokit = auth.getOctokit()\n * ```\n */\nexport class PatAuthProvider implements AuthProvider {\n readonly authProvider = 'pat' as const\n\n private readonly token: FromPatParams\n private readonly retry?: AuthProviderOptions['retry']\n private cachedOctokit: Octokit | null = null\n\n constructor(token: FromPatParams, options?: AuthProviderOptions) {\n this.token = token\n this.retry = options?.retry\n }\n\n /**\n * 获取已认证的 Octokit 实例(首次调用构造并缓存)。\n */\n getOctokit(): Octokit {\n if (!this.cachedOctokit) {\n this.cachedOctokit = createGitHubClient({ token: this.token, retry: this.retry })\n }\n return this.cachedOctokit\n }\n\n /** 获取推送 / clone 用的 Git 凭据(username = `'x-access-token'`,token = PAT) */\n getGitCredential(): { username: string, token: string } {\n return { username: PAT_GIT_USERNAME, token: this.token }\n }\n\n /** 获取 commit author(PAT 路径固定 `dependfix[bot]`) */\n getCommitAuthor(): { name: string, email: string } {\n return { ...PAT_COMMIT_AUTHOR }\n }\n}\n","import { Octokit } from '@octokit/rest'\nimport { createAppAuth } from '@octokit/auth-app'\nimport type {\n AuthProvider,\n AuthProviderOptions,\n FromAppParams,\n} from './auth-provider'\n\n// ---------------------------------------------------------------------------\n// AppAuthProvider - GitHub App installation token 认证实现\n// ---------------------------------------------------------------------------\n\n/**\n * GitHub App 工厂函数(**M18.1 commit 4 完整实施**)。\n *\n * 委托给 [`AppAuthProvider`] 类。\n *\n * @example\n * ```typescript\n * const auth = fromApp({\n * appId: '123456',\n * privateKey: '-----BEGIN RSA PRIVATE KEY-----\\n...',\n * installationId: '7890123',\n * botLogin: 'dependfix-bot[bot]',\n * })\n * const octokit = auth.getOctokit()\n * ```\n */\nexport function fromApp(\n params: FromAppParams,\n options?: AuthProviderOptions,\n): AuthProvider {\n return new AppAuthProvider(params, options)\n}\n\n/**\n * GitHub App 认证路径实现。\n *\n * 使用 [`@octokit/auth-app`](https://github.com/octokit/auth-app.js) 提供:\n * - JWT signing(App 身份认证)\n * - `getInstallationOctokit`(installation token 获取;库内置 59 分钟 LRU TTL 缓存)\n * - 自动 installation token 轮换\n *\n * 注意:\n * - `getGitCredential()` 返回的 `token` 字段为占位符(installation token 不能直接从 AppAuthProvider 获取;\n * 由 [`@octokit/auth-app`](https://github.com/octokit/auth-app.js) 内部管理);调用方应通过 `getOctokit()`\n * 拿到的 Octokit 实例进行 API 调用\n * - `getCommitAuthor()` 按 GitHub App 协议动态生成 `{app_id}+{bot_login}[bot]@users.noreply.github.com`\n * - Octokit 实例缓存以避免重复构造\n *\n * @see [C22 PAT 无感升级评估 §4.2 AuthProvider 接口设计](../../../../docs/design/governance/c22-pat-backward-compat.md)\n */\nexport class AppAuthProvider implements AuthProvider {\n readonly authProvider = 'github-app' as const\n\n private readonly params: FromAppParams\n // retry 选项保留用于未来扩展(AppAuthProvider 当前不直接使用 retry;由 @octokit/auth-app 自管)\n private readonly _options?: AuthProviderOptions\n private cachedOctokit: Octokit | null = null\n\n constructor(params: FromAppParams, options?: AuthProviderOptions) {\n this.params = params\n this._options = options\n }\n\n /**\n * 获取已认证的 Octokit 实例。\n *\n * 首次调用时构造并缓存;后续调用复用同一实例。\n * installation token 由 `@octokit/auth-app` 内部管理(59 分钟 LRU TTL 缓存)。\n *\n * **构造方式**:使用 `authStrategy: createAppAuth` + `auth: {appId, privateKey, installationId}`\n * 双字段组合(`@octokit/auth-app` v8.x README 标准用法),**而非** `auth: createAppAuth(...)`\n * 单字段调用——后者被 `@octokit/core` 视作字符串 token 路径抛 `Token passed to createTokenAuth is not a string`,\n * 或被 `authStrategy` 字段调用后命中 `auth(state, authOptions)` 的 `default` 分支抛 `Invalid auth type: undefined`\n * (todo.md §M18.4 e2e 验证 + audit quick depth Reject 后补修发现)。\n *\n * @see [@octokit/auth-app README §installation authentication](https://github.com/octokit/auth-app.js#installation-authentication)\n */\n getOctokit(): Octokit {\n if (!this.cachedOctokit) {\n this.cachedOctokit = new Octokit({\n authStrategy: createAppAuth,\n auth: {\n appId: this.params.appId,\n privateKey: this.params.privateKey,\n installationId: this.params.installationId,\n },\n baseUrl: 'https://api.github.com',\n })\n }\n return this.cachedOctokit\n }\n\n /**\n * 获取推送 / clone 用的 Git 凭据。\n *\n * 注意:installation token 由 `@octokit/auth-app` 内部管理,**不**能从 AppAuthProvider 直接获取;\n * 本方法返回的 `token` 字段为占位符(`'installation-token-managed-by-octokit-auth-app'`)。\n * 调用方应通过 `getOctokit()` 拿到的 Octokit 实例进行 API 调用(含 git push / clone 等写操作)。\n */\n getGitCredential(): { username: string, token: string } {\n return {\n username: 'x-access-token',\n token: 'installation-token-managed-by-octokit-auth-app',\n }\n }\n\n /**\n * 获取 commit author。\n *\n * 按 GitHub App 协议动态生成 `{app_id}+{bot_login}[bot]@users.noreply.github.com`:\n * - `name`:`{app_id}[bot]`(GitHub 自动识别 bot 身份)\n * - `email`:`{app_id}+{bot_login}[bot]@users.noreply.github.com`(GitHub noreply email 格式)\n *\n * 当 `params.botLogin` 未提供时,使用 `dependfix[bot]` 作为 fallback(保持与 PAT 路径一致的格式);\n * 但建议调用方显式提供 `botLogin` 以确保 commit author 真实 bot 身份归属。\n */\n getCommitAuthor(): { name: string, email: string } {\n const botLogin = this.params.botLogin ?? 'dependfix[bot]'\n const appId = this.params.appId\n return {\n name: `${appId}[bot]`,\n email: `${appId}+${botLogin}@users.noreply.github.com`,\n }\n }\n}\n","import type { FromAppParams } from './auth-provider'\n\n// ---------------------------------------------------------------------------\n// Installation Token Cache - 占位 + 监控 API\n// ---------------------------------------------------------------------------\n\n/**\n * Installation token 缓存层(**M18.1 commit 4 实施**)。\n *\n * 当前实现:**依赖 [@octokit/auth-app](https://github.com/octokit/auth-app.js) 内置缓存**\n * (59 分钟 LRU TTL;GitHub token 有效期 60 分钟 - 1 分钟缓冲)。\n *\n * 本类作为未来扩展点:\n * - 缓存统计(命中率 / 大小 / 清理 API)\n * - 失败重试 + 报警(M18.2 集成时实施)\n * - 多 worker 共享(Redis-backed;超出 M18.1 范围)\n *\n * 注意:\n * - `getOrRefresh` 当前委托给 `createAppAuthentication` + `getInstallationOctokit`\n * - 当 [@octokit/auth-app](https://github.com/octokit/auth-app.js) 内部缓存命中时不会触发 API 调用\n * - 缓存未命中时自动调用 `POST /app/installations/{installation_id}/access_tokens` 获取新 token\n *\n * @see [C22 PAT 无感升级评估 §4.7 commit 拆分纪律](../../../../docs/design/governance/c22-pat-backward-compat.md)\n */\nexport class InstallationTokenCache {\n private readonly params: FromAppParams\n private readonly ttlMs: number\n\n constructor(params: FromAppParams, options?: { ttlMs?: number, refreshThresholdMs?: number }) {\n this.params = params\n // 默认 59 分钟(与 @octokit/auth-app 默认一致)\n this.ttlMs = options?.ttlMs ?? 59 * 60 * 1000\n }\n\n /**\n * 获取或刷新 installation token。\n *\n * 当前为占位实现:直接返回 `'installation-token-managed-by-octokit-auth-app'` 占位字符串。\n * 调用方应使用 `fromApp(params).getOctokit()` 获取真实 Octokit 实例(由 `@octokit/auth-app`\n * 自动管理 installation token 缓存)。\n *\n * @throws 永不抛错(占位实现)\n */\n async getOrRefresh(): Promise<string> {\n // 占位实现:真实 token 由 @octokit/auth-app 内部管理\n // 本方法保留作为未来扩展点(Redis-backed / 失败重试 / 报警)\n return 'installation-token-managed-by-octokit-auth-app'\n }\n\n /** 清理过期缓存项(占位实现) */\n clear(): void {\n // 占位实现:@octokit/auth-app 内部管理缓存清理\n // 保留接口签名便于未来替换为自有实现\n }\n\n /** 获取缓存 TTL 配置(毫秒) */\n getTtlMs(): number {\n return this.ttlMs\n }\n\n /** 获取 cache key(基于 installationId) */\n static getCacheKey(params: FromAppParams): string {\n return `installation:${params.installationId}`\n }\n}\n"],"mappings":"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"}
|