@ctil/gql 1.1.6 → 1.1.8

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 CHANGED
@@ -4378,8 +4378,8 @@ var rateLimitConfig = {
4378
4378
  mutation: { max: 10, window: 1, debounce: 200 }
4379
4379
  },
4380
4380
  custom: {
4381
- login: { max: 1, window: 5, debounce: 0 },
4382
- refreshToken: { max: 2, window: 5, debounce: 0 }
4381
+ login: { max: 2, window: 3, debounce: 0 },
4382
+ refreshToken: { max: 3, window: 5, debounce: 0 }
4383
4383
  }
4384
4384
  };
4385
4385
 
@@ -4515,6 +4515,8 @@ var CCRequest = class {
4515
4515
  this.config = config;
4516
4516
  this._remember = false;
4517
4517
  this.interceptors = [];
4518
+ this.refreshPromise = null;
4519
+ this.logoutPromise = null;
4518
4520
  this.deviceInfoPromise = getDeviceInfo();
4519
4521
  this.headers = this.buildHeaders(config);
4520
4522
  const loginInfo = this.loadLoginInfo();
@@ -4656,62 +4658,79 @@ var CCRequest = class {
4656
4658
  clearHeaders() {
4657
4659
  this.headers = { "Content-Type": "application/json" };
4658
4660
  }
4659
- //无感刷新
4661
+ async logoutOnce() {
4662
+ if (!this.logoutPromise) {
4663
+ this.logoutPromise = (async () => {
4664
+ await this.removeLoginInfo();
4665
+ })();
4666
+ }
4667
+ return this.logoutPromise;
4668
+ }
4660
4669
  /** 无感刷新 token */
4661
4670
  async ensureTokenValid() {
4662
- const loginInfo = this.getLoginInfo();
4671
+ const loginInfo = await this.getLoginInfo();
4663
4672
  if (!loginInfo) return;
4664
4673
  const now = Date.now();
4665
- const accessExpired = new Date(loginInfo.expireAt).getTime() <= now;
4674
+ const accessExpire = new Date(loginInfo.expireAt).getTime() <= now + 6e5;
4666
4675
  const refreshExpired = new Date(loginInfo.refreshExpireAt).getTime() <= now;
4667
4676
  if (refreshExpired) {
4668
- this.removeLoginInfo();
4677
+ await this.logoutOnce();
4669
4678
  throw new Error("Login expired. Please login again.");
4670
4679
  }
4671
- if (accessExpired && !refreshExpired) {
4672
- try {
4673
- const refreshResult = await auth.refreshToken({
4674
- refreshToken: loginInfo.refreshToken,
4675
- remember: this._remember
4676
- // 使用持久化的 remember
4677
- });
4678
- const newInfo = refreshResult.refreshToken ?? refreshResult;
4679
- this.setLoginInfo(newInfo, this._remember);
4680
- } catch (err) {
4681
- this.removeLoginInfo();
4682
- throw new Error("Failed to refresh token. Please login again." + err?.message);
4683
- }
4680
+ if (accessExpire) {
4681
+ await this.refreshToken();
4684
4682
  }
4685
4683
  }
4684
+ async refreshToken() {
4685
+ const loginInfo = await this.getLoginInfo();
4686
+ if (!loginInfo) return;
4687
+ if (!this.refreshPromise) {
4688
+ this.refreshPromise = (async () => {
4689
+ try {
4690
+ const newToken = await auth.refreshToken({
4691
+ refreshToken: loginInfo.refreshToken,
4692
+ remember: this._remember
4693
+ });
4694
+ this.setToken(newToken.refreshToken.token);
4695
+ } catch (e) {
4696
+ await this.logoutOnce();
4697
+ throw e;
4698
+ } finally {
4699
+ this.refreshPromise = null;
4700
+ }
4701
+ })();
4702
+ }
4703
+ return this.refreshPromise;
4704
+ }
4686
4705
  // ===== 请求逻辑 =====
4687
4706
  async request(query2, variables) {
4688
4707
  let queryStr = typeof query2 === "string" ? query2 : print(query2);
4689
- const { deviceId, deviceName } = await this.deviceInfoPromise;
4690
- let headersWithDevice = Object.fromEntries(
4691
- Object.entries({
4692
- ...this.headers,
4693
- "X-Device-Id": deviceId,
4694
- "X-Device-Name": deviceName
4695
- }).filter(([_, v]) => v !== void 0)
4696
- );
4697
- for (const interceptor of this.interceptors) {
4698
- if (interceptor.onRequest) {
4699
- const result = await interceptor.onRequest({
4700
- query: queryStr,
4701
- variables,
4702
- headers: headersWithDevice
4703
- });
4704
- queryStr = result.query;
4705
- variables = result.variables;
4706
- headersWithDevice = Object.fromEntries(
4707
- Object.entries(result.headers).filter(([_, v]) => v !== void 0)
4708
- );
4709
- }
4710
- }
4711
4708
  try {
4712
4709
  if (!/refreshToken/i.test(queryStr)) {
4713
4710
  await this.ensureTokenValid();
4714
4711
  }
4712
+ const { deviceId, deviceName } = await this.deviceInfoPromise;
4713
+ let headersWithDevice = Object.fromEntries(
4714
+ Object.entries({
4715
+ ...this.headers,
4716
+ "X-Device-Id": deviceId,
4717
+ "X-Device-Name": deviceName
4718
+ }).filter(([_, v]) => v !== void 0)
4719
+ );
4720
+ for (const interceptor of this.interceptors) {
4721
+ if (interceptor.onRequest) {
4722
+ const result = await interceptor.onRequest({
4723
+ query: queryStr,
4724
+ variables,
4725
+ headers: headersWithDevice
4726
+ });
4727
+ queryStr = result.query;
4728
+ variables = result.variables;
4729
+ headersWithDevice = Object.fromEntries(
4730
+ Object.entries(result.headers).filter(([_, v]) => v !== void 0)
4731
+ );
4732
+ }
4733
+ }
4715
4734
  const res = await this.client.rawRequest(
4716
4735
  queryStr,
4717
4736
  variables,
@@ -4727,6 +4746,14 @@ var CCRequest = class {
4727
4746
  } catch (err) {
4728
4747
  const message = err.response?.errors?.[0]?.message ?? err.message;
4729
4748
  const status = err.response?.errors?.[0]?.extensions?.code ?? 500;
4749
+ if (status === 401 && !/refreshToken/i.test(queryStr)) {
4750
+ try {
4751
+ await this.refreshToken();
4752
+ return this.request(queryStr, variables);
4753
+ } catch {
4754
+ await this.logoutOnce();
4755
+ }
4756
+ }
4730
4757
  const formattedError = {
4731
4758
  message,
4732
4759
  status,