@napuketto/kernel 0.0.8 → 0.0.10
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/index.cjs +73 -16
- package/dist/index.d.cts +25 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +25 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +73 -16
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2590,6 +2590,8 @@ function startupSessionStart(ctx) {
|
|
|
2590
2590
|
/** 二维码过期错误码(errType=1 errCode=3,实测)。 */
|
|
2591
2591
|
const QR_EXPIRED_ERR_TYPE = 1;
|
|
2592
2592
|
const QR_EXPIRED_ERR_CODE = 3;
|
|
2593
|
+
/** 登录超时提示(参考项目文案,前端 failed 态展示)。 */
|
|
2594
|
+
const QR_LOGIN_TIMEOUT_MESSAGE = "登录超时,请刷新页面重试";
|
|
2593
2595
|
/** 二维码过期判定。 */
|
|
2594
2596
|
function isQrCodeExpired(errType, errCode) {
|
|
2595
2597
|
return errType === QR_EXPIRED_ERR_TYPE && errCode === QR_EXPIRED_ERR_CODE;
|
|
@@ -2604,10 +2606,17 @@ var QrLoginSession = class {
|
|
|
2604
2606
|
self = null;
|
|
2605
2607
|
qrCodeHandlers = /* @__PURE__ */ new Set();
|
|
2606
2608
|
stateHandlers = /* @__PURE__ */ new Set();
|
|
2607
|
-
|
|
2609
|
+
/** 超时定时器(refresh 后启动,登录成功/失败/stop 清理)。 */
|
|
2610
|
+
timeoutTimer = null;
|
|
2611
|
+
/** 失败原因(超时等,failed 态透出给上层提示文案)。 */
|
|
2612
|
+
failureReasonValue = null;
|
|
2613
|
+
/** 超时上限(毫秒,默认 QR_LOGIN_TIMEOUT_MS)。 */
|
|
2614
|
+
timeoutMs;
|
|
2615
|
+
constructor(loginService, options = {}) {
|
|
2608
2616
|
const svc = loginService;
|
|
2609
2617
|
if (svc === null || typeof svc.addKernelLoginListener !== "function") throw kernelError("loginService 无效(缺 addKernelLoginListener)", "INVALID_STATE");
|
|
2610
2618
|
this.loginService = svc;
|
|
2619
|
+
this.timeoutMs = options.timeoutMs ?? 12e4;
|
|
2611
2620
|
}
|
|
2612
2621
|
/** 当前状态。 */
|
|
2613
2622
|
get currentState() {
|
|
@@ -2617,6 +2626,10 @@ var QrLoginSession = class {
|
|
|
2617
2626
|
get selfInfo() {
|
|
2618
2627
|
return this.self;
|
|
2619
2628
|
}
|
|
2629
|
+
/** 失败原因(超时等;failed 态透出给上层提示文案)。 */
|
|
2630
|
+
get failureReason() {
|
|
2631
|
+
return this.failureReasonValue;
|
|
2632
|
+
}
|
|
2620
2633
|
/** 订阅二维码(png base64 + url)。返回退订函数。 */
|
|
2621
2634
|
onQrCode(cb) {
|
|
2622
2635
|
this.qrCodeHandlers.add(cb);
|
|
@@ -2632,15 +2645,19 @@ var QrLoginSession = class {
|
|
|
2632
2645
|
if (this.state !== "idle") return;
|
|
2633
2646
|
this.listenerId = this.loginService.addKernelLoginListener(this.buildListener());
|
|
2634
2647
|
this.loginService.connect();
|
|
2635
|
-
if (opts.quickUin !== void 0 && opts.quickUin !== "") this.loginService.quickLoginWithUin(opts.quickUin).
|
|
2648
|
+
if (opts.quickUin !== void 0 && opts.quickUin !== "") this.loginService.quickLoginWithUin(opts.quickUin).then((result) => {
|
|
2649
|
+
if (result.loginErrorInfo.errMsg !== "") this.refresh();
|
|
2650
|
+
}).catch(() => {
|
|
2636
2651
|
this.refresh();
|
|
2637
2652
|
});
|
|
2638
2653
|
else this.refresh();
|
|
2639
2654
|
}
|
|
2640
|
-
/** 刷新二维码(手动 /
|
|
2655
|
+
/** 刷新二维码(手动 / 过期自动)。每次出码重启超时计时。 */
|
|
2641
2656
|
refresh() {
|
|
2657
|
+
this.failureReasonValue = null;
|
|
2642
2658
|
this.setState("waiting_scan");
|
|
2643
2659
|
this.loginService.getQRCodePicture();
|
|
2660
|
+
this.restartTimeout();
|
|
2644
2661
|
}
|
|
2645
2662
|
/** 构建登录监听(普通 JS 对象,NAPI 反射)。 */
|
|
2646
2663
|
buildListener() {
|
|
@@ -2659,6 +2676,7 @@ var QrLoginSession = class {
|
|
|
2659
2676
|
this.setState("scanned");
|
|
2660
2677
|
};
|
|
2661
2678
|
listener.onQRCodeLoginSucceed = (result) => {
|
|
2679
|
+
this.clearTimeoutTimer();
|
|
2662
2680
|
this.self = {
|
|
2663
2681
|
uin: result.uin,
|
|
2664
2682
|
uid: result.uid,
|
|
@@ -2671,20 +2689,41 @@ var QrLoginSession = class {
|
|
|
2671
2689
|
this.refresh();
|
|
2672
2690
|
return;
|
|
2673
2691
|
}
|
|
2692
|
+
this.clearTimeoutTimer();
|
|
2693
|
+
this.failureReasonValue = null;
|
|
2674
2694
|
this.setState("failed");
|
|
2675
2695
|
};
|
|
2676
2696
|
listener.onLoginFailed = () => {
|
|
2697
|
+
this.clearTimeoutTimer();
|
|
2698
|
+
this.failureReasonValue = null;
|
|
2677
2699
|
this.setState("failed");
|
|
2678
2700
|
};
|
|
2679
2701
|
return listener;
|
|
2680
2702
|
}
|
|
2681
2703
|
/** 停止:注销监听(登录成功后调用,防重复回调)。 */
|
|
2682
2704
|
stop() {
|
|
2705
|
+
this.clearTimeoutTimer();
|
|
2683
2706
|
if (this.listenerId !== null) {
|
|
2684
2707
|
this.loginService.removeKernelLoginListener(this.listenerId);
|
|
2685
2708
|
this.listenerId = null;
|
|
2686
2709
|
}
|
|
2687
2710
|
}
|
|
2711
|
+
/** 重启超时计时器:超时未登录 → failed + 超时提示。 */
|
|
2712
|
+
restartTimeout() {
|
|
2713
|
+
this.clearTimeoutTimer();
|
|
2714
|
+
this.timeoutTimer = setTimeout(() => {
|
|
2715
|
+
this.timeoutTimer = null;
|
|
2716
|
+
this.failureReasonValue = QR_LOGIN_TIMEOUT_MESSAGE;
|
|
2717
|
+
this.setState("failed");
|
|
2718
|
+
}, this.timeoutMs);
|
|
2719
|
+
}
|
|
2720
|
+
/** 清理超时计时器(幂等)。 */
|
|
2721
|
+
clearTimeoutTimer() {
|
|
2722
|
+
if (this.timeoutTimer !== null) {
|
|
2723
|
+
clearTimeout(this.timeoutTimer);
|
|
2724
|
+
this.timeoutTimer = null;
|
|
2725
|
+
}
|
|
2726
|
+
}
|
|
2688
2727
|
setState(next) {
|
|
2689
2728
|
this.state = next;
|
|
2690
2729
|
for (const cb of this.stateHandlers) cb(next);
|
|
@@ -3169,6 +3208,8 @@ function getOrCreateLoginService(exports) {
|
|
|
3169
3208
|
var NapukettoCore = class NapukettoCore {
|
|
3170
3209
|
/** 装配根(协议层 / apis / cache 的消费入口)。 */
|
|
3171
3210
|
ctx;
|
|
3211
|
+
/** QR 登录会话句柄(登录期间非空;登录终态后清空)。refreshQr() 据此可达。 */
|
|
3212
|
+
qrSession = null;
|
|
3172
3213
|
/** 由 create() 装配,不直接 new。 */
|
|
3173
3214
|
constructor(ctx) {
|
|
3174
3215
|
this.ctx = ctx;
|
|
@@ -3267,25 +3308,37 @@ var NapukettoCore = class NapukettoCore {
|
|
|
3267
3308
|
if (this.ctx.wrapper === null) throw kernelError("wrapper 未装配,无法设置 session", "INVALID_STATE");
|
|
3268
3309
|
this.ctx.wrapper.session = session;
|
|
3269
3310
|
}
|
|
3311
|
+
/**
|
|
3312
|
+
* 手动刷新二维码(QR 登录期间可用)。返回是否成功触发(false = 当前不在扫码态)。
|
|
3313
|
+
* koishi 前端「刷新二维码」按钮经 loader IPC `login.refreshQr` 动作直达。
|
|
3314
|
+
*/
|
|
3315
|
+
refreshQr() {
|
|
3316
|
+
if (this.qrSession === null) return false;
|
|
3317
|
+
this.qrSession.refresh();
|
|
3318
|
+
return true;
|
|
3319
|
+
}
|
|
3270
3320
|
/** QR 登录:QrLoginSession 状态机 + 二维码写缓存目录(无 UI,cli 可打印路径)。 */
|
|
3271
3321
|
async loginByQr(opts) {
|
|
3272
3322
|
const { wrapper } = this.ctx;
|
|
3273
3323
|
if (wrapper === null || wrapper.loginService === null) throw kernelError("wrapper/loginService 不可用,无法 QR 登录", "INVALID_STATE");
|
|
3274
3324
|
const session = new QrLoginSession(wrapper.loginService);
|
|
3325
|
+
this.qrSession = session;
|
|
3275
3326
|
const qrPath = opts.qrCodePath ?? this.ctx.paths.file("cache", "qrcode.png");
|
|
3276
3327
|
this.subscribeQrProgress(session, opts, qrPath);
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3328
|
+
try {
|
|
3329
|
+
session.start();
|
|
3330
|
+
await waitQrLoggedIn(session);
|
|
3331
|
+
const self = session.selfInfo;
|
|
3332
|
+
if (self === null) throw kernelError("QR 登录成功但 selfInfo 为空", "INVALID_STATE");
|
|
3333
|
+
return {
|
|
3334
|
+
uin: self.uin,
|
|
3335
|
+
uid: self.uid,
|
|
3336
|
+
nick: self.nick
|
|
3337
|
+
};
|
|
3338
|
+
} finally {
|
|
3339
|
+
session.stop();
|
|
3340
|
+
this.qrSession = null;
|
|
3341
|
+
}
|
|
3289
3342
|
}
|
|
3290
3343
|
/** 订阅 QR 进度:二维码写盘 + 状态机经 onLoginProgress 转发。 */
|
|
3291
3344
|
subscribeQrProgress(session, opts, qrPath) {
|
|
@@ -3299,7 +3352,11 @@ var NapukettoCore = class NapukettoCore {
|
|
|
3299
3352
|
});
|
|
3300
3353
|
session.onStateChange((state) => {
|
|
3301
3354
|
this.ctx.logger.info({ state }, "QR 登录状态");
|
|
3302
|
-
|
|
3355
|
+
const message = state === "failed" ? session.failureReason ?? void 0 : void 0;
|
|
3356
|
+
opts.onLoginProgress?.({
|
|
3357
|
+
state,
|
|
3358
|
+
...message !== void 0 ? { message } : {}
|
|
3359
|
+
});
|
|
3303
3360
|
});
|
|
3304
3361
|
}
|
|
3305
3362
|
/** 停止:日志收尾(资源清理留给 P2 常驻管理)。 */
|