@morehao/dsh-github-trending 0.8.5 → 0.8.7
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/CHANGELOG.md +20 -0
- package/README.en.md +1 -1
- package/README.md +2 -2
- package/client.js +320 -288
- package/lib/{chunk-QOYTABJH.js → chunk-OMQY3T3V.js} +15 -267
- package/lib/index.d.ts +0 -1
- package/lib/index.js +2 -5
- package/lib/internal.d.ts +26 -96
- package/lib/internal.js +1 -1
- package/package.json +1 -1
|
@@ -3529,48 +3529,26 @@ async function probeGithubAuth(options) {
|
|
|
3529
3529
|
// src/host/github-auth.ts
|
|
3530
3530
|
var github_auth_exports = {};
|
|
3531
3531
|
__export(github_auth_exports, {
|
|
3532
|
-
CALLBACK_PATH: () => CALLBACK_PATH,
|
|
3533
3532
|
DEFAULT_GITHUB_CLIENT_ID: () => DEFAULT_GITHUB_CLIENT_ID,
|
|
3534
3533
|
DEFAULT_SCOPE: () => DEFAULT_SCOPE,
|
|
3535
3534
|
GITHUB_RECORD_KEY: () => GITHUB_RECORD_KEY2,
|
|
3536
3535
|
attemptView: () => attemptView,
|
|
3537
3536
|
beginGithubSignIn: () => beginGithubSignIn,
|
|
3538
|
-
buildAuthorizeUrl: () => buildAuthorizeUrl,
|
|
3539
3537
|
cancelGithubSignIn: () => cancelGithubSignIn,
|
|
3540
|
-
createPkce: () => createPkce,
|
|
3541
3538
|
ensureGithubFlow: () => ensureGithubFlow,
|
|
3542
3539
|
isGithubFlowRegistered: () => isGithubFlowRegistered,
|
|
3543
|
-
isHttpUrl: () => isHttpUrl,
|
|
3544
|
-
isLoopbackSignInAvailable: () => isLoopbackSignInAvailable,
|
|
3545
3540
|
registerGithubFlow: () => registerGithubFlow,
|
|
3546
|
-
renderCallbackPage: () => renderCallbackPage,
|
|
3547
3541
|
resetAttemptForTest: () => resetAttemptForTest,
|
|
3548
|
-
resolveClientId: () => resolveClientId
|
|
3549
|
-
resolveClientSecret: () => resolveClientSecret,
|
|
3550
|
-
resolveMethod: () => resolveMethod,
|
|
3551
|
-
verifyState: () => verifyState
|
|
3542
|
+
resolveClientId: () => resolveClientId
|
|
3552
3543
|
});
|
|
3553
|
-
import { createHash as createHash3, randomBytes as randomBytes2, timingSafeEqual as timingSafeEqual2 } from "crypto";
|
|
3554
3544
|
var GITHUB_RECORD_KEY2 = "github/default";
|
|
3555
|
-
var CALLBACK_PATH = "/api/morehao/github-trending/oauth/github/callback";
|
|
3556
3545
|
var DEFAULT_GITHUB_CLIENT_ID = "Ov23li7rhp0EKoqbkJKY";
|
|
3557
3546
|
function resolveClientId(deps) {
|
|
3558
3547
|
const fromConfig = deps.clientId;
|
|
3559
3548
|
return fromConfig !== void 0 && fromConfig !== "" ? fromConfig : DEFAULT_GITHUB_CLIENT_ID;
|
|
3560
3549
|
}
|
|
3561
|
-
function resolveClientSecret(deps) {
|
|
3562
|
-
const secret = deps.clientSecret;
|
|
3563
|
-
return secret !== void 0 && secret !== "" ? secret : void 0;
|
|
3564
|
-
}
|
|
3565
|
-
function isLoopbackSignInAvailable(deps) {
|
|
3566
|
-
return resolveClientSecret(deps) !== void 0;
|
|
3567
|
-
}
|
|
3568
|
-
function resolveMethod(deps, requested) {
|
|
3569
|
-
return requested === "browser" && !isLoopbackSignInAvailable(deps) ? "device" : requested;
|
|
3570
|
-
}
|
|
3571
|
-
var AUTHORIZE_URL = "https://github.com/login/oauth/authorize";
|
|
3572
|
-
var ACCESS_TOKEN_URL = "https://github.com/login/oauth/access_token";
|
|
3573
3550
|
var DEVICE_CODE_URL = "https://github.com/login/device/code";
|
|
3551
|
+
var ACCESS_TOKEN_URL = "https://github.com/login/oauth/access_token";
|
|
3574
3552
|
var GITHUB_USER_URL = "https://api.github.com/user";
|
|
3575
3553
|
var DEFAULT_SCOPE = "repo";
|
|
3576
3554
|
var DEFAULT_ATTEMPT_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
@@ -3580,105 +3558,6 @@ function attemptView() {
|
|
|
3580
3558
|
const { controller: _c, done: _d, ...view } = current;
|
|
3581
3559
|
return view;
|
|
3582
3560
|
}
|
|
3583
|
-
function base64url(buf) {
|
|
3584
|
-
return buf.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
3585
|
-
}
|
|
3586
|
-
function isHttpUrl(value) {
|
|
3587
|
-
if (typeof value !== "string" || value === "") return false;
|
|
3588
|
-
let url;
|
|
3589
|
-
try {
|
|
3590
|
-
url = new URL(value);
|
|
3591
|
-
} catch {
|
|
3592
|
-
return false;
|
|
3593
|
-
}
|
|
3594
|
-
return url.protocol === "https:" || url.protocol === "http:";
|
|
3595
|
-
}
|
|
3596
|
-
function createPkce() {
|
|
3597
|
-
const verifier = base64url(randomBytes2(32));
|
|
3598
|
-
const challenge = base64url(createHash3("sha256").update(verifier).digest());
|
|
3599
|
-
return { verifier, challenge };
|
|
3600
|
-
}
|
|
3601
|
-
function verifyState(received, expected) {
|
|
3602
|
-
const a = Buffer.from(received);
|
|
3603
|
-
const b = Buffer.from(expected);
|
|
3604
|
-
return a.length === b.length && timingSafeEqual2(a, b);
|
|
3605
|
-
}
|
|
3606
|
-
function renderCallbackPage(kind) {
|
|
3607
|
-
const ok = kind === "success";
|
|
3608
|
-
const title = ok ? "\u767B\u5F55\u5B8C\u6210" : "\u767B\u5F55\u672A\u5B8C\u6210";
|
|
3609
|
-
const heading = ok ? "GitHub \u6388\u6743\u6210\u529F" : "GitHub \u6388\u6743\u5931\u8D25";
|
|
3610
|
-
const body = ok ? "\u5DF2\u5B8C\u6210\u767B\u5F55\uFF0C\u53EF\u4EE5\u5173\u95ED\u6B64\u9875\u9762\u3002" : "\u6388\u6743\u6821\u9A8C\u672A\u901A\u8FC7\uFF0C\u8BF7\u56DE\u5230 DSH \u91CD\u65B0\u53D1\u8D77\u767B\u5F55\u3002";
|
|
3611
|
-
const accent = ok ? "#1f883d" : "#cf222e";
|
|
3612
|
-
const icon = ok ? '<path d="M20 6 9 17l-5-5"/>' : '<path d="M18 6 6 18"/><path d="m6 6 12 12"/>';
|
|
3613
|
-
const autoClose = ok ? "<script>(function(){try{setTimeout(function(){window.close()},1200)}catch(e){}})()</script>" : "";
|
|
3614
|
-
return `<!doctype html><html lang="zh-CN"><head><meta charset="utf-8">
|
|
3615
|
-
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
3616
|
-
<meta name="color-scheme" content="light dark">
|
|
3617
|
-
<title>${title}</title>
|
|
3618
|
-
<style>
|
|
3619
|
-
:root{--bg:#f6f8fa;--card:#ffffff;--fg:#1f2328;--muted:#59636e;--border:#d1d9e0;--accent:${accent}}
|
|
3620
|
-
@media (prefers-color-scheme:dark){:root{--bg:#0d1117;--card:#151b23;--fg:#e6edf3;--muted:#9198a1;--border:#3d444d}}
|
|
3621
|
-
*{box-sizing:border-box}
|
|
3622
|
-
html,body{height:100%}
|
|
3623
|
-
body{margin:0;display:flex;align-items:center;justify-content:center;padding:24px;
|
|
3624
|
-
background:var(--bg);color:var(--fg);
|
|
3625
|
-
font:400 15px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif}
|
|
3626
|
-
main{width:100%;max-width:400px;background:var(--card);border:1px solid var(--border);
|
|
3627
|
-
border-radius:14px;padding:40px 32px;text-align:center;
|
|
3628
|
-
box-shadow:0 8px 24px rgba(0,0,0,.06)}
|
|
3629
|
-
.mark{width:64px;height:64px;margin:0 auto 20px;border-radius:50%;display:flex;
|
|
3630
|
-
align-items:center;justify-content:center;background:color-mix(in srgb,var(--accent) 14%,transparent);color:var(--accent)}
|
|
3631
|
-
.mark svg{width:30px;height:30px;fill:none;stroke:currentColor;stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round}
|
|
3632
|
-
h1{margin:0 0 8px;font-size:19px;font-weight:600;letter-spacing:.2px}
|
|
3633
|
-
p{margin:0;color:var(--muted);font-size:14px}
|
|
3634
|
-
</style></head>
|
|
3635
|
-
<body><main role="status">
|
|
3636
|
-
<div class="mark"><svg viewBox="0 0 24 24" aria-hidden="true">${icon}</svg></div>
|
|
3637
|
-
<h1>${heading}</h1>
|
|
3638
|
-
<p>${body}</p>
|
|
3639
|
-
</main>${autoClose}</body></html>`;
|
|
3640
|
-
}
|
|
3641
|
-
function buildAuthorizeUrl(params) {
|
|
3642
|
-
const url = new URL(params.authorizeEndpoint);
|
|
3643
|
-
url.searchParams.set("client_id", params.clientId);
|
|
3644
|
-
url.searchParams.set("redirect_uri", params.redirectUri);
|
|
3645
|
-
url.searchParams.set("scope", params.scope);
|
|
3646
|
-
url.searchParams.set("state", params.state);
|
|
3647
|
-
url.searchParams.set("code_challenge", params.challenge);
|
|
3648
|
-
url.searchParams.set("code_challenge_method", "S256");
|
|
3649
|
-
return url.toString();
|
|
3650
|
-
}
|
|
3651
|
-
async function exchangeCode(fetchImpl, endpoint, params, signal) {
|
|
3652
|
-
const form = new URLSearchParams({
|
|
3653
|
-
client_id: params.clientId,
|
|
3654
|
-
code: params.code,
|
|
3655
|
-
code_verifier: params.verifier,
|
|
3656
|
-
redirect_uri: params.redirectUri
|
|
3657
|
-
});
|
|
3658
|
-
if (params.clientSecret !== void 0) form.set("client_secret", params.clientSecret);
|
|
3659
|
-
const response = await fetchImpl(endpoint, {
|
|
3660
|
-
method: "POST",
|
|
3661
|
-
headers: { accept: "application/json", "content-type": "application/x-www-form-urlencoded" },
|
|
3662
|
-
body: form.toString(),
|
|
3663
|
-
signal
|
|
3664
|
-
});
|
|
3665
|
-
if (!response.ok) throw new Error(`GitHub access_token HTTP ${response.status}`);
|
|
3666
|
-
const body = await response.json();
|
|
3667
|
-
if (typeof body.access_token !== "string" || body.access_token === "") {
|
|
3668
|
-
const error = typeof body.error === "string" ? body.error : void 0;
|
|
3669
|
-
if (error === "incorrect_client_credentials") {
|
|
3670
|
-
throw new Error(
|
|
3671
|
-
params.clientSecret === void 0 ? "GitHub \u7F51\u9875\u6388\u6743\u9700\u8981 client_secret\uFF08incorrect_client_credentials\uFF09\uFF0C\u5185\u7F6E\u7684\u516C\u5F00 client_id \u65E0\u6CD5\u5B8C\u6210\u8FD9\u4E00\u6B65\uFF1A\u8BF7\u6539\u7528\u8BBE\u5907\u7801\u767B\u5F55\uFF0C\u6216\u914D\u7F6E\u81EA\u5DF1\u7684 OAuth App client_id + client_secret\u3002" : "GitHub \u8BA4\u4E3A\u8FD9\u4E2A OAuth App \u7684 client_id / client_secret \u4E0D\u6B63\u786E\uFF08incorrect_client_credentials\uFF09\uFF1A\u8BF7\u68C0\u67E5\u63D2\u4EF6\u914D\u7F6E\uFF0C\u6216\u6539\u7528\u8BBE\u5907\u7801\u767B\u5F55\u3002"
|
|
3672
|
-
);
|
|
3673
|
-
}
|
|
3674
|
-
throw new Error(`GitHub access_token \u672A\u8FD4\u56DE token${error === void 0 ? "" : `\uFF08${error}\uFF09`}`);
|
|
3675
|
-
}
|
|
3676
|
-
return {
|
|
3677
|
-
token: body.access_token,
|
|
3678
|
-
...typeof body.token_type === "string" ? { tokenType: body.token_type } : {},
|
|
3679
|
-
...typeof body.scope === "string" ? { scope: body.scope } : {}
|
|
3680
|
-
};
|
|
3681
|
-
}
|
|
3682
3561
|
async function fetchLogin(fetchImpl, endpoint, token, signal) {
|
|
3683
3562
|
try {
|
|
3684
3563
|
const response = await fetchImpl(endpoint, {
|
|
@@ -3692,87 +3571,6 @@ async function fetchLogin(fetchImpl, endpoint, token, signal) {
|
|
|
3692
3571
|
return void 0;
|
|
3693
3572
|
}
|
|
3694
3573
|
}
|
|
3695
|
-
async function runBrowser(deps, session) {
|
|
3696
|
-
const webServer = deps.get("webServer");
|
|
3697
|
-
if (webServer === void 0 || typeof webServer.register !== "function") {
|
|
3698
|
-
throw new Error("webServer \u670D\u52A1\u4E0D\u53EF\u7528\uFF1A\u6D4F\u89C8\u5668\u767B\u5F55\u9700\u8981\u5B83\u627F\u8F7D OAuth \u56DE\u8C03");
|
|
3699
|
-
}
|
|
3700
|
-
const clientId = resolveClientId(deps);
|
|
3701
|
-
if (clientId === void 0 || clientId === "") throw new Error("\u7F3A\u5C11 GitHub OAuth client_id");
|
|
3702
|
-
const clientSecret = resolveClientSecret(deps);
|
|
3703
|
-
if (clientSecret === void 0) {
|
|
3704
|
-
throw new Error("\u56DE\u73AF\u767B\u5F55\u4E0D\u53EF\u7528\uFF1A\u6CA1\u6709\u914D\u7F6E GitHub OAuth App \u7684 client_secret\uFF0C\u8BF7\u6539\u7528\u8BBE\u5907\u7801\u767B\u5F55");
|
|
3705
|
-
}
|
|
3706
|
-
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
3707
|
-
const endpoints = normalizeEndpoints(deps.endpoints);
|
|
3708
|
-
const scope = deps.scope ?? DEFAULT_SCOPE;
|
|
3709
|
-
const state = base64url(randomBytes2(32));
|
|
3710
|
-
const { verifier, challenge } = createPkce();
|
|
3711
|
-
let resolveCode;
|
|
3712
|
-
let rejectCode;
|
|
3713
|
-
const codePromise = new Promise((resolve, reject) => {
|
|
3714
|
-
resolveCode = resolve;
|
|
3715
|
-
rejectCode = reject;
|
|
3716
|
-
});
|
|
3717
|
-
codePromise.catch(() => void 0);
|
|
3718
|
-
const dispose = webServer.register({
|
|
3719
|
-
kind: "exact",
|
|
3720
|
-
path: CALLBACK_PATH,
|
|
3721
|
-
handler: (req, res) => {
|
|
3722
|
-
let url;
|
|
3723
|
-
try {
|
|
3724
|
-
url = new URL(req.url ?? "/", "http://127.0.0.1");
|
|
3725
|
-
} catch {
|
|
3726
|
-
res.writeHead(400, { "cache-control": "no-store" }).end();
|
|
3727
|
-
return;
|
|
3728
|
-
}
|
|
3729
|
-
const code = url.searchParams.get("code") ?? "";
|
|
3730
|
-
const gotState = url.searchParams.get("state") ?? "";
|
|
3731
|
-
const single = url.searchParams.getAll("state").length === 1 && url.searchParams.getAll("code").length === 1;
|
|
3732
|
-
const bad = req.method !== "GET" || url.pathname !== CALLBACK_PATH || !single || code === "" || !verifyState(gotState, state);
|
|
3733
|
-
if (bad) {
|
|
3734
|
-
res.writeHead(400, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store" }).end(renderCallbackPage("error"));
|
|
3735
|
-
return;
|
|
3736
|
-
}
|
|
3737
|
-
res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store" }).end(renderCallbackPage("success"));
|
|
3738
|
-
resolveCode(code);
|
|
3739
|
-
}
|
|
3740
|
-
});
|
|
3741
|
-
try {
|
|
3742
|
-
const origin = localOrigin(webServer);
|
|
3743
|
-
const redirectUri = `${origin}${CALLBACK_PATH}`;
|
|
3744
|
-
const authorizeUrl = buildAuthorizeUrl({
|
|
3745
|
-
authorizeEndpoint: endpoints.authorize,
|
|
3746
|
-
clientId,
|
|
3747
|
-
redirectUri,
|
|
3748
|
-
scope,
|
|
3749
|
-
state,
|
|
3750
|
-
challenge
|
|
3751
|
-
});
|
|
3752
|
-
updateCurrent({ phase: "waiting-browser", authorizeUrl, expiresAt: Date.now() + attemptTimeout(deps) });
|
|
3753
|
-
session.notify?.({ message: "Continue in your browser to sign in to GitHub.", url: authorizeUrl });
|
|
3754
|
-
const code = await withAbort(codePromise, session.signal, () => rejectCode(new Error("authorization cancelled")));
|
|
3755
|
-
updateCurrent({ phase: "exchanging" });
|
|
3756
|
-
const exchanged = await exchangeCode(
|
|
3757
|
-
fetchImpl,
|
|
3758
|
-
endpoints.accessToken,
|
|
3759
|
-
{ clientId, clientSecret, code, verifier, redirectUri },
|
|
3760
|
-
session.signal
|
|
3761
|
-
);
|
|
3762
|
-
const login = await fetchLogin(fetchImpl, endpoints.user, exchanged.token, session.signal);
|
|
3763
|
-
const payload = {
|
|
3764
|
-
version: 1,
|
|
3765
|
-
token: exchanged.token,
|
|
3766
|
-
...login === void 0 ? {} : { login },
|
|
3767
|
-
tokenType: exchanged.tokenType ?? "bearer",
|
|
3768
|
-
scope: exchanged.scope ?? scope
|
|
3769
|
-
};
|
|
3770
|
-
if (typeof session.commit === "function") await session.commit({ kind: "grant", payload });
|
|
3771
|
-
updateCurrent({ phase: "done", ...login === void 0 ? {} : { login } });
|
|
3772
|
-
} finally {
|
|
3773
|
-
dispose();
|
|
3774
|
-
}
|
|
3775
|
-
}
|
|
3776
3574
|
async function runDevice(deps, session) {
|
|
3777
3575
|
const clientId = resolveClientId(deps);
|
|
3778
3576
|
if (clientId === void 0 || clientId === "") throw new Error("\u7F3A\u5C11 GitHub OAuth client_id");
|
|
@@ -3797,17 +3595,15 @@ async function runDevice(deps, session) {
|
|
|
3797
3595
|
const intervalSec = typeof start.interval === "number" && start.interval > 0 ? start.interval : 5;
|
|
3798
3596
|
const expiresInSec = typeof start.expires_in === "number" && start.expires_in > 0 ? start.expires_in : 900;
|
|
3799
3597
|
const deadline = Date.now() + expiresInSec * 1e3;
|
|
3800
|
-
const verificationUriComplete = isHttpUrl(start.verification_uri_complete) ? start.verification_uri_complete : void 0;
|
|
3801
3598
|
updateCurrent({
|
|
3802
3599
|
phase: "waiting-device",
|
|
3803
3600
|
verificationUri: start.verification_uri,
|
|
3804
|
-
...verificationUriComplete === void 0 ? {} : { verificationUriComplete },
|
|
3805
3601
|
userCode: start.user_code,
|
|
3806
3602
|
expiresAt: deadline
|
|
3807
3603
|
});
|
|
3808
3604
|
session.notify?.({
|
|
3809
3605
|
message: "Enter this code on the verification page to finish signing in.",
|
|
3810
|
-
url:
|
|
3606
|
+
url: start.verification_uri,
|
|
3811
3607
|
code: start.user_code
|
|
3812
3608
|
});
|
|
3813
3609
|
let waitMs = intervalSec * 1e3;
|
|
@@ -3852,11 +3648,8 @@ function flowDefinition(deps) {
|
|
|
3852
3648
|
return {
|
|
3853
3649
|
key: GITHUB_RECORD_KEY2,
|
|
3854
3650
|
label: "GitHub",
|
|
3855
|
-
methods: [
|
|
3856
|
-
|
|
3857
|
-
{ id: "device", label: "Use a device code" }
|
|
3858
|
-
],
|
|
3859
|
-
run: (session) => session.method === "device" ? runDevice(deps, session) : runBrowser(deps, session)
|
|
3651
|
+
methods: [{ id: "device", label: "Use a device code" }],
|
|
3652
|
+
run: (session) => runDevice(deps, session)
|
|
3860
3653
|
};
|
|
3861
3654
|
}
|
|
3862
3655
|
var registeredOn = /* @__PURE__ */ new WeakSet();
|
|
@@ -3900,21 +3693,17 @@ function registerGithubFlow(deps) {
|
|
|
3900
3693
|
}
|
|
3901
3694
|
var START_TIMEOUT_MS = 1500;
|
|
3902
3695
|
var START_POLL_MS = 10;
|
|
3903
|
-
async function beginGithubSignIn(deps
|
|
3696
|
+
async function beginGithubSignIn(deps) {
|
|
3904
3697
|
const authorization = deps.get("authorization");
|
|
3905
3698
|
if (authorization === void 0 || typeof authorization.begin !== "function") {
|
|
3906
|
-
throw new Error("authorization \u670D\u52A1\u4E0D\u53EF\u7528\uFF1A\u65E0\u6CD5\u8FDB\u884C\
|
|
3699
|
+
throw new Error("authorization \u670D\u52A1\u4E0D\u53EF\u7528\uFF1A\u65E0\u6CD5\u8FDB\u884C GitHub \u767B\u5F55");
|
|
3907
3700
|
}
|
|
3908
3701
|
if (!ensureGithubFlow(deps)) {
|
|
3909
3702
|
throw new Error("authorization \u670D\u52A1\u5C1A\u672A\u5C31\u7EEA\uFF0CGitHub \u6388\u6743\u6D41\u7A0B\u6CA1\u6709\u6CE8\u518C\u6210\u529F\uFF1A\u8BF7\u7A0D\u540E\u91CD\u8BD5");
|
|
3910
3703
|
}
|
|
3911
|
-
if (current !== void 0 && (current.phase === "waiting-
|
|
3704
|
+
if (current !== void 0 && (current.phase === "waiting-device" || current.phase === "exchanging")) {
|
|
3912
3705
|
throw new Error("already-in-flight");
|
|
3913
3706
|
}
|
|
3914
|
-
const effectiveMethod = resolveMethod(deps, method);
|
|
3915
|
-
if (effectiveMethod !== method) {
|
|
3916
|
-
deps.logger?.("auth.method.fallback", { from: method, to: effectiveMethod, reason: "no-client-secret" });
|
|
3917
|
-
}
|
|
3918
3707
|
const controller = new AbortController();
|
|
3919
3708
|
const timer = setTimeout(() => controller.abort(), attemptTimeout(deps));
|
|
3920
3709
|
const attempt = { phase: "idle", controller, done: Promise.resolve() };
|
|
@@ -3923,15 +3712,13 @@ async function beginGithubSignIn(deps, method = "browser") {
|
|
|
3923
3712
|
try {
|
|
3924
3713
|
started = authorization.begin({
|
|
3925
3714
|
key: GITHUB_RECORD_KEY2,
|
|
3926
|
-
method:
|
|
3715
|
+
method: "device",
|
|
3927
3716
|
signal: controller.signal,
|
|
3928
|
-
//
|
|
3717
|
+
// 设备码:notify 只更新内存视图;prompt 不支持(拒绝)。
|
|
3929
3718
|
interaction: {
|
|
3930
3719
|
notify: (notice) => {
|
|
3931
|
-
if (notice.code !== void 0
|
|
3720
|
+
if (notice.code !== void 0) {
|
|
3932
3721
|
updateCurrent({ phase: "waiting-device", userCode: notice.code });
|
|
3933
|
-
} else if (notice.url !== void 0) {
|
|
3934
|
-
updateCurrent({ phase: "waiting-browser", authorizeUrl: notice.url });
|
|
3935
3722
|
}
|
|
3936
3723
|
},
|
|
3937
3724
|
prompt: () => Promise.reject(new Error("interactive prompt unsupported in this surface"))
|
|
@@ -3968,7 +3755,6 @@ function resetAttemptForTest() {
|
|
|
3968
3755
|
}
|
|
3969
3756
|
function normalizeEndpoints(endpoints = {}) {
|
|
3970
3757
|
return {
|
|
3971
|
-
authorize: endpoints?.authorize ?? AUTHORIZE_URL,
|
|
3972
3758
|
accessToken: endpoints?.accessToken ?? ACCESS_TOKEN_URL,
|
|
3973
3759
|
deviceCode: endpoints?.deviceCode ?? DEVICE_CODE_URL,
|
|
3974
3760
|
user: endpoints?.user ?? GITHUB_USER_URL
|
|
@@ -3977,37 +3763,6 @@ function normalizeEndpoints(endpoints = {}) {
|
|
|
3977
3763
|
function attemptTimeout(deps) {
|
|
3978
3764
|
return typeof deps.attemptTimeoutMs === "number" && deps.attemptTimeoutMs > 0 ? deps.attemptTimeoutMs : DEFAULT_ATTEMPT_TIMEOUT_MS;
|
|
3979
3765
|
}
|
|
3980
|
-
function localOrigin(webServer) {
|
|
3981
|
-
const port = webServer.port;
|
|
3982
|
-
if (typeof port !== "number" || port <= 0) throw new Error("webServer \u5C1A\u672A\u76D1\u542C\uFF0C\u65E0\u6CD5\u786E\u5B9A\u56DE\u8C03\u5730\u5740");
|
|
3983
|
-
const host = typeof webServer.host === "string" && webServer.host !== "" ? webServer.host : "127.0.0.1";
|
|
3984
|
-
const loopback = host === "0.0.0.0" || host === "::" ? "127.0.0.1" : host;
|
|
3985
|
-
return `http://${loopback}:${port}`;
|
|
3986
|
-
}
|
|
3987
|
-
function withAbort(promise, signal, onAbort) {
|
|
3988
|
-
if (signal === void 0) return promise;
|
|
3989
|
-
if (signal.aborted) {
|
|
3990
|
-
onAbort();
|
|
3991
|
-
return Promise.reject(new Error("authorization cancelled"));
|
|
3992
|
-
}
|
|
3993
|
-
return new Promise((resolve, reject) => {
|
|
3994
|
-
const abort = () => {
|
|
3995
|
-
onAbort();
|
|
3996
|
-
reject(new Error("authorization cancelled"));
|
|
3997
|
-
};
|
|
3998
|
-
signal.addEventListener("abort", abort, { once: true });
|
|
3999
|
-
promise.then(
|
|
4000
|
-
(value) => {
|
|
4001
|
-
signal.removeEventListener("abort", abort);
|
|
4002
|
-
resolve(value);
|
|
4003
|
-
},
|
|
4004
|
-
(error) => {
|
|
4005
|
-
signal.removeEventListener("abort", abort);
|
|
4006
|
-
reject(error);
|
|
4007
|
-
}
|
|
4008
|
-
);
|
|
4009
|
-
});
|
|
4010
|
-
}
|
|
4011
3766
|
function sleep(ms, signal) {
|
|
4012
3767
|
return new Promise((resolve, reject) => {
|
|
4013
3768
|
if (signal?.aborted === true) {
|
|
@@ -4541,7 +4296,6 @@ function githubAuthDeps(deps) {
|
|
|
4541
4296
|
get: deps.get,
|
|
4542
4297
|
...deps.fetchImpl === void 0 ? {} : { fetchImpl: deps.fetchImpl },
|
|
4543
4298
|
...deps.githubClientId === void 0 ? {} : { clientId: deps.githubClientId },
|
|
4544
|
-
...deps.githubClientSecret === void 0 ? {} : { clientSecret: deps.githubClientSecret },
|
|
4545
4299
|
...deps.logger === void 0 ? {} : { logger: deps.logger }
|
|
4546
4300
|
};
|
|
4547
4301
|
}
|
|
@@ -4728,9 +4482,8 @@ async function dispatch(method, pathname, url, body, deps) {
|
|
|
4728
4482
|
return { github: probe };
|
|
4729
4483
|
}
|
|
4730
4484
|
if (method === "POST" && pathname === "/github/browser/begin") {
|
|
4731
|
-
const method2 = body.method === "device" ? "device" : "browser";
|
|
4732
4485
|
try {
|
|
4733
|
-
const view = await beginGithubSignIn(githubAuthDeps(deps)
|
|
4486
|
+
const view = await beginGithubSignIn(githubAuthDeps(deps));
|
|
4734
4487
|
if (view.phase === "error") throw new IpcError("GITHUB_AUTH_UNAVAILABLE", redact(view.error ?? "GitHub \u767B\u5F55\u5931\u8D25"));
|
|
4735
4488
|
return { attempt: view };
|
|
4736
4489
|
} catch (error) {
|
|
@@ -4878,15 +4631,10 @@ async function statePayload(deps, settings) {
|
|
|
4878
4631
|
authMode: settings.github.authMode,
|
|
4879
4632
|
configured: github.token !== void 0,
|
|
4880
4633
|
source: github.source,
|
|
4881
|
-
/**
|
|
4634
|
+
/** GitHub 登录 attempt 视图(idle / waiting-device / exchanging / done / error)。 */
|
|
4882
4635
|
attempt: attemptView(),
|
|
4883
|
-
/**
|
|
4884
|
-
browserAvailable: browserSignInAvailable(deps)
|
|
4885
|
-
/**
|
|
4886
|
-
* 回环 web flow 是否可用:GitHub 换 token 必须有 client_secret,内置 client_id 没有 → 只能设备码。
|
|
4887
|
-
* 前端据此决定主按钮启动哪个 method(false 时直接用 device,避免点了必然失败的 web flow)。
|
|
4888
|
-
*/
|
|
4889
|
-
loopbackAvailable: isLoopbackSignInAvailable(githubAuthDeps(deps))
|
|
4636
|
+
/** 登录是否可用:authorization 服务在、且 GitHub flow 真的注册上了(client_id 有内置默认)。 */
|
|
4637
|
+
browserAvailable: browserSignInAvailable(deps)
|
|
4890
4638
|
}
|
|
4891
4639
|
};
|
|
4892
4640
|
}
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
createUpdateService,
|
|
10
10
|
ensureGithubFlow,
|
|
11
11
|
readPluginInfo
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-OMQY3T3V.js";
|
|
13
13
|
|
|
14
14
|
// src/index.ts
|
|
15
15
|
var name = "dsh-github-trending";
|
|
@@ -20,7 +20,6 @@ function readVersion() {
|
|
|
20
20
|
var VERSION = readVersion();
|
|
21
21
|
function apply(ctx, config = {}) {
|
|
22
22
|
const env = process.env;
|
|
23
|
-
const githubClientSecret = (config.githubClientSecret ?? env.DSH_GITHUB_CLIENT_SECRET)?.trim();
|
|
24
23
|
const get = (key) => typeof ctx.get === "function" ? ctx.get(key) : void 0;
|
|
25
24
|
const log = (event, data) => {
|
|
26
25
|
const suffix = data === void 0 ? "" : ` ${JSON.stringify(data)}`;
|
|
@@ -68,8 +67,7 @@ function apply(ctx, config = {}) {
|
|
|
68
67
|
const githubAuth = (resolve) => ({
|
|
69
68
|
get: resolve,
|
|
70
69
|
logger: log,
|
|
71
|
-
...config.githubClientId === void 0 ? {} : { clientId: config.githubClientId }
|
|
72
|
-
...githubClientSecret === void 0 || githubClientSecret === "" ? {} : { clientSecret: githubClientSecret }
|
|
70
|
+
...config.githubClientId === void 0 ? {} : { clientId: config.githubClientId }
|
|
73
71
|
});
|
|
74
72
|
const registerAuth = (resolve) => {
|
|
75
73
|
if (!ensureGithubFlow(githubAuth(resolve ?? get))) log("auth.flow.deferred", { reason: "authorization-not-ready" });
|
|
@@ -102,7 +100,6 @@ function apply(ctx, config = {}) {
|
|
|
102
100
|
pluginName: pluginInfo.name,
|
|
103
101
|
...pluginInfo.repository === void 0 ? {} : { repository: pluginInfo.repository },
|
|
104
102
|
...config.githubClientId === void 0 ? {} : { githubClientId: config.githubClientId },
|
|
105
|
-
...githubClientSecret === void 0 || githubClientSecret === "" ? {} : { githubClientSecret },
|
|
106
103
|
logger: log
|
|
107
104
|
});
|
|
108
105
|
const register = () => {
|
package/lib/internal.d.ts
CHANGED
|
@@ -1157,39 +1157,36 @@ declare namespace github {
|
|
|
1157
1157
|
export { type github_GithubProbeResult as GithubProbeResult, github_probeGithubAuth as probeGithubAuth };
|
|
1158
1158
|
}
|
|
1159
1159
|
|
|
1160
|
+
/**
|
|
1161
|
+
* GitHub 浏览器登录(薄 adapter)。
|
|
1162
|
+
*
|
|
1163
|
+
* 设计原则:**只补核心缺的那一层,其余全用核心轮子**(见
|
|
1164
|
+
* `.dsh/docs/plans/2026-11-01-github-browser-auth-plan.md`)。
|
|
1165
|
+
* - 协议生命周期 / attempt 单飞 / 取消 / 结算 → `ctx.authorization`(核心)
|
|
1166
|
+
* - 回环回调 HTTP 载体 → `ctx.webServer.register({ kind:'exact' })`(核心)
|
|
1167
|
+
* - token 落盘 / 原子写 / 0600 / record 事件 → `ctx.credentials`(核心)
|
|
1168
|
+
* - 交互词汇 notify/prompt → `AuthorizationSession`(核心)
|
|
1169
|
+
*
|
|
1170
|
+
* 本文件只写 GitHub provider 专有的:client_id、端点、PKCE 三行、state 校验、exchange、
|
|
1171
|
+
* grant payload,以及「进程内 begin + 内存 attempt 视图」这点胶水(核心没有给第三方 key
|
|
1172
|
+
* 的 authorization HTTP 投影,见阶段 0 核实 R4)。
|
|
1173
|
+
*
|
|
1174
|
+
* 不 import 任何 `@deepseek-ai/*` 运行时模块:全部走 `get(...)` 的鸭子类型,故不需要新增
|
|
1175
|
+
* peerDependency。record 键用字符串 `'github/default'`(与核心包提案同名同构,便于迁移)。
|
|
1176
|
+
*/
|
|
1160
1177
|
/** 与核心 `@deepseek-ai/dsh-github-auth` 提案保持同 key;迁移时消费端无需改。 */
|
|
1161
1178
|
declare const GITHUB_RECORD_KEY = "github/default";
|
|
1162
|
-
/** 本地回调路径(带集成前缀,避免多 provider 撞 webServer 的 `(kind,path)` 唯一约束)。 */
|
|
1163
|
-
declare const CALLBACK_PATH = "/api/morehao/github-trending/oauth/github/callback";
|
|
1164
1179
|
/**
|
|
1165
1180
|
* 内置的 GitHub OAuth App 公开 client_id(**非机密**:OAuth 的 client_id 设计上就是公开的,
|
|
1166
1181
|
* 会出现在授权 URL 里,与 `gh`/VS Code 内置自己的 client_id 同理)。
|
|
1167
1182
|
*
|
|
1168
|
-
*
|
|
1169
|
-
*
|
|
1170
|
-
*
|
|
1171
|
-
* - 内置 client_id → 只能走 **device flow**(`resolveMethod` 自动降级),开箱即用;
|
|
1172
|
-
* - 用户自带 OAuth App(`githubClientId` + `githubClientSecret`)→ 才启用回环 web flow。
|
|
1173
|
-
* 且 device flow 需要在 OAuth App 设置里勾选启用(本插件内置的 App 已启用)。
|
|
1174
|
-
*
|
|
1175
|
-
* OAuth App 侧登记的回调:`http://127.0.0.1/api/morehao/github-trending/oauth/github/callback`
|
|
1176
|
-
* (loopback 按 RFC 8252 忽略端口,运行时随机端口可正常回跳)。
|
|
1183
|
+
* 只走 **device flow**:GitHub 的 web application flow 换 token 必须带 client_secret,
|
|
1184
|
+
* 而客户端不能内置机密,故本插件不实现回环 web flow(也不支持自带 OAuth App 的 secret)。
|
|
1185
|
+
* device flow 需要在 OAuth App 设置里勾选启用(本插件内置的 App 已启用)。
|
|
1177
1186
|
*/
|
|
1178
1187
|
declare const DEFAULT_GITHUB_CLIENT_ID = "Ov23li7rhp0EKoqbkJKY";
|
|
1179
|
-
/** 解析生效的 client_id:显式 config
|
|
1188
|
+
/** 解析生效的 client_id:显式 config 优先,否则用内置默认(device flow 允许自定义 client_id)。 */
|
|
1180
1189
|
declare function resolveClientId(deps: GithubAuthDeps): string | undefined;
|
|
1181
|
-
/** 解析生效的 client_secret(没有就返回 undefined,绝不以空串形式发出去)。 */
|
|
1182
|
-
declare function resolveClientSecret(deps: GithubAuthDeps): string | undefined;
|
|
1183
|
-
/**
|
|
1184
|
-
* 回环(浏览器 web flow)是否可用:GitHub 换 token 必须带 client_secret,
|
|
1185
|
-
* 内置的公开 client_id 没有 secret,只能退到设备码。见文件头的说明。
|
|
1186
|
-
*/
|
|
1187
|
-
declare function isLoopbackSignInAvailable(deps: GithubAuthDeps): boolean;
|
|
1188
|
-
/**
|
|
1189
|
-
* 实际要跑的方法:`browser` 需要 client_secret,缺省时自动降级为 `device`(开箱即用)。
|
|
1190
|
-
* 显式选择 `device` 的调用不受影响。
|
|
1191
|
-
*/
|
|
1192
|
-
declare function resolveMethod(deps: GithubAuthDeps, requested: 'browser' | 'device'): 'browser' | 'device';
|
|
1193
1190
|
/** 本插件运行需要 push / 建 PR,`read:user` 不够;一次授权到 `repo`。 */
|
|
1194
1191
|
declare const DEFAULT_SCOPE = "repo";
|
|
1195
1192
|
interface AuthorizationFlow {
|
|
@@ -1224,15 +1221,6 @@ interface AuthorizationLike {
|
|
|
1224
1221
|
/** 核心 0.2.x 有:按 key 查已注册的 flow;判定「真的注册上了」靠它。 */
|
|
1225
1222
|
describe?: (key: string) => unknown;
|
|
1226
1223
|
}
|
|
1227
|
-
interface WebServerLike {
|
|
1228
|
-
register?: (route: {
|
|
1229
|
-
kind: 'exact';
|
|
1230
|
-
path: string;
|
|
1231
|
-
handler: (req: any, res: any) => void;
|
|
1232
|
-
}) => () => void;
|
|
1233
|
-
port?: number;
|
|
1234
|
-
host?: string;
|
|
1235
|
-
}
|
|
1236
1224
|
type FetchLike = typeof fetch;
|
|
1237
1225
|
interface GithubAuthDeps {
|
|
1238
1226
|
get: (name: string) => unknown;
|
|
@@ -1240,70 +1228,25 @@ interface GithubAuthDeps {
|
|
|
1240
1228
|
logger?: (event: string, data?: Record<string, unknown>) => void;
|
|
1241
1229
|
/** 覆盖端点(测试用);生产留空走 GitHub 官方。 */
|
|
1242
1230
|
endpoints?: {
|
|
1243
|
-
authorize?: string;
|
|
1244
1231
|
accessToken?: string;
|
|
1245
1232
|
deviceCode?: string;
|
|
1246
1233
|
user?: string;
|
|
1247
1234
|
};
|
|
1248
|
-
/** GitHub OAuth App 的 public client_id
|
|
1235
|
+
/** GitHub OAuth App 的 public client_id(device flow 用;无需 secret)。 */
|
|
1249
1236
|
clientId?: string;
|
|
1250
|
-
/**
|
|
1251
|
-
* GitHub OAuth App 的 client_secret。只有自带 OAuth App 的回环 web flow 才需要;
|
|
1252
|
-
* 缺省时 `browser` 方法自动降级为 device flow。不进 `settings.json`、不进日志。
|
|
1253
|
-
*/
|
|
1254
|
-
clientSecret?: string;
|
|
1255
1237
|
scope?: string;
|
|
1256
1238
|
attemptTimeoutMs?: number;
|
|
1257
1239
|
}
|
|
1258
|
-
type GithubAttemptPhase = 'idle' | 'waiting-
|
|
1240
|
+
type GithubAttemptPhase = 'idle' | 'waiting-device' | 'exchanging' | 'done' | 'error';
|
|
1259
1241
|
interface GithubAttemptView {
|
|
1260
1242
|
phase: GithubAttemptPhase;
|
|
1261
|
-
authorizeUrl?: string;
|
|
1262
1243
|
verificationUri?: string;
|
|
1263
|
-
/**
|
|
1264
|
-
* device flow 的预填验证码地址(`verification_uri_complete`),**可选**:若 provider 返回就透出,
|
|
1265
|
-
* 前端优先用它打开(码已预填)。注意 GitHub 官方 device flow 实测不返回该字段,此时走
|
|
1266
|
-
* `verificationUri` + 手动输入;保留此字段只为兼容会返回它的 provider。
|
|
1267
|
-
*/
|
|
1268
|
-
verificationUriComplete?: string;
|
|
1269
1244
|
userCode?: string;
|
|
1270
1245
|
expiresAt?: number;
|
|
1271
1246
|
login?: string;
|
|
1272
1247
|
error?: string;
|
|
1273
1248
|
}
|
|
1274
1249
|
declare function attemptView(): GithubAttemptView;
|
|
1275
|
-
/** 判断一个未知值是否是可直接打开的 http(s) URL(用于校验 GitHub 返回的验证页地址)。 */
|
|
1276
|
-
declare function isHttpUrl(value: unknown): boolean;
|
|
1277
|
-
/** PKCE:返回 verifier 与 S256 challenge。 */
|
|
1278
|
-
declare function createPkce(): {
|
|
1279
|
-
verifier: string;
|
|
1280
|
-
challenge: string;
|
|
1281
|
-
};
|
|
1282
|
-
/** 常量时间比较 state(长度不等直接 false,避免 timingSafeEqual 抛错)。 */
|
|
1283
|
-
declare function verifyState(received: string, expected: string): boolean;
|
|
1284
|
-
/** 回调落地页的两种结果(纯展示,无外部资源,离线可测)。 */
|
|
1285
|
-
type CallbackPageKind = 'success' | 'error';
|
|
1286
|
-
/**
|
|
1287
|
-
* 回环回调的落地页 HTML。自包含、无外链资源(CSP 友好、离线可用),
|
|
1288
|
-
* 跟随系统深浅色;成功页会尝试自动关闭本窗口(脚本失败时文字兜底)。
|
|
1289
|
-
*/
|
|
1290
|
-
declare function renderCallbackPage(kind: CallbackPageKind): string;
|
|
1291
|
-
/** 拼授权页 URL。 */
|
|
1292
|
-
declare function buildAuthorizeUrl(params: {
|
|
1293
|
-
authorizeEndpoint: string;
|
|
1294
|
-
clientId: string;
|
|
1295
|
-
redirectUri: string;
|
|
1296
|
-
scope: string;
|
|
1297
|
-
state: string;
|
|
1298
|
-
challenge: string;
|
|
1299
|
-
}): string;
|
|
1300
|
-
interface GithubGrantPayload {
|
|
1301
|
-
version: 1;
|
|
1302
|
-
token: string;
|
|
1303
|
-
login?: string;
|
|
1304
|
-
tokenType?: string;
|
|
1305
|
-
scope?: string;
|
|
1306
|
-
}
|
|
1307
1250
|
/** 这个 key 现在是否**真的**有 flow 在注册表里。 */
|
|
1308
1251
|
declare function isGithubFlowRegistered(deps: GithubAuthDeps): boolean;
|
|
1309
1252
|
/**
|
|
@@ -1334,7 +1277,7 @@ declare function registerGithubFlow(deps: GithubAuthDeps): void;
|
|
|
1334
1277
|
*
|
|
1335
1278
|
* @throws 服务不可用、flow 未注册、已有 attempt 在飞时抛错。
|
|
1336
1279
|
*/
|
|
1337
|
-
declare function beginGithubSignIn(deps: GithubAuthDeps
|
|
1280
|
+
declare function beginGithubSignIn(deps: GithubAuthDeps): Promise<GithubAttemptView>;
|
|
1338
1281
|
/** 取消进行中的 attempt。 */
|
|
1339
1282
|
declare function cancelGithubSignIn(deps: GithubAuthDeps): void;
|
|
1340
1283
|
/** 仅测试用:清空内存 attempt。 */
|
|
@@ -1343,33 +1286,22 @@ declare function resetAttemptForTest(): void;
|
|
|
1343
1286
|
type githubAuth_AuthorizationFlow = AuthorizationFlow;
|
|
1344
1287
|
type githubAuth_AuthorizationLike = AuthorizationLike;
|
|
1345
1288
|
type githubAuth_AuthorizationSessionLike = AuthorizationSessionLike;
|
|
1346
|
-
declare const githubAuth_CALLBACK_PATH: typeof CALLBACK_PATH;
|
|
1347
1289
|
declare const githubAuth_DEFAULT_GITHUB_CLIENT_ID: typeof DEFAULT_GITHUB_CLIENT_ID;
|
|
1348
1290
|
declare const githubAuth_DEFAULT_SCOPE: typeof DEFAULT_SCOPE;
|
|
1349
1291
|
declare const githubAuth_GITHUB_RECORD_KEY: typeof GITHUB_RECORD_KEY;
|
|
1350
1292
|
type githubAuth_GithubAttemptPhase = GithubAttemptPhase;
|
|
1351
1293
|
type githubAuth_GithubAttemptView = GithubAttemptView;
|
|
1352
1294
|
type githubAuth_GithubAuthDeps = GithubAuthDeps;
|
|
1353
|
-
type githubAuth_GithubGrantPayload = GithubGrantPayload;
|
|
1354
|
-
type githubAuth_WebServerLike = WebServerLike;
|
|
1355
1295
|
declare const githubAuth_attemptView: typeof attemptView;
|
|
1356
1296
|
declare const githubAuth_beginGithubSignIn: typeof beginGithubSignIn;
|
|
1357
|
-
declare const githubAuth_buildAuthorizeUrl: typeof buildAuthorizeUrl;
|
|
1358
1297
|
declare const githubAuth_cancelGithubSignIn: typeof cancelGithubSignIn;
|
|
1359
|
-
declare const githubAuth_createPkce: typeof createPkce;
|
|
1360
1298
|
declare const githubAuth_ensureGithubFlow: typeof ensureGithubFlow;
|
|
1361
1299
|
declare const githubAuth_isGithubFlowRegistered: typeof isGithubFlowRegistered;
|
|
1362
|
-
declare const githubAuth_isHttpUrl: typeof isHttpUrl;
|
|
1363
|
-
declare const githubAuth_isLoopbackSignInAvailable: typeof isLoopbackSignInAvailable;
|
|
1364
1300
|
declare const githubAuth_registerGithubFlow: typeof registerGithubFlow;
|
|
1365
|
-
declare const githubAuth_renderCallbackPage: typeof renderCallbackPage;
|
|
1366
1301
|
declare const githubAuth_resetAttemptForTest: typeof resetAttemptForTest;
|
|
1367
1302
|
declare const githubAuth_resolveClientId: typeof resolveClientId;
|
|
1368
|
-
declare const githubAuth_resolveClientSecret: typeof resolveClientSecret;
|
|
1369
|
-
declare const githubAuth_resolveMethod: typeof resolveMethod;
|
|
1370
|
-
declare const githubAuth_verifyState: typeof verifyState;
|
|
1371
1303
|
declare namespace githubAuth {
|
|
1372
|
-
export { type githubAuth_AuthorizationFlow as AuthorizationFlow, type githubAuth_AuthorizationLike as AuthorizationLike, type githubAuth_AuthorizationSessionLike as AuthorizationSessionLike,
|
|
1304
|
+
export { type githubAuth_AuthorizationFlow as AuthorizationFlow, type githubAuth_AuthorizationLike as AuthorizationLike, type githubAuth_AuthorizationSessionLike as AuthorizationSessionLike, githubAuth_DEFAULT_GITHUB_CLIENT_ID as DEFAULT_GITHUB_CLIENT_ID, githubAuth_DEFAULT_SCOPE as DEFAULT_SCOPE, githubAuth_GITHUB_RECORD_KEY as GITHUB_RECORD_KEY, type githubAuth_GithubAttemptPhase as GithubAttemptPhase, type githubAuth_GithubAttemptView as GithubAttemptView, type githubAuth_GithubAuthDeps as GithubAuthDeps, githubAuth_attemptView as attemptView, githubAuth_beginGithubSignIn as beginGithubSignIn, githubAuth_cancelGithubSignIn as cancelGithubSignIn, githubAuth_ensureGithubFlow as ensureGithubFlow, githubAuth_isGithubFlowRegistered as isGithubFlowRegistered, githubAuth_registerGithubFlow as registerGithubFlow, githubAuth_resetAttemptForTest as resetAttemptForTest, githubAuth_resolveClientId as resolveClientId };
|
|
1373
1305
|
}
|
|
1374
1306
|
|
|
1375
1307
|
interface DefaultBranchResult {
|
|
@@ -2053,10 +1985,8 @@ interface RouteDeps {
|
|
|
2053
1985
|
/** 包名与仓库地址都来自 package.json,由 src/index.ts 传入。 */
|
|
2054
1986
|
pluginName?: string;
|
|
2055
1987
|
repository?: string;
|
|
2056
|
-
/**
|
|
1988
|
+
/** GitHub 登录用的 public client_id(由 apply 的 config 传入;缺省时用内置默认)。 */
|
|
2057
1989
|
githubClientId?: string;
|
|
2058
|
-
/** 自带 OAuth App 时的 client_secret(只用于回环 web flow;缺省时该 method 自动降级为设备码)。 */
|
|
2059
|
-
githubClientSecret?: string;
|
|
2060
1990
|
logger?: (event: string, data?: Record<string, unknown>) => void;
|
|
2061
1991
|
}
|
|
2062
1992
|
declare function createRoutes(deps: RouteDeps): (request: http.IncomingMessage, response: http.ServerResponse) => Promise<void>;
|