@amaster.ai/auth-client 1.1.0-beta.73 → 1.1.0-beta.75

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.md CHANGED
@@ -96,7 +96,6 @@ interface AuthClientOptions {
96
96
 
97
97
  ```typescript
98
98
  const authClient = createAuthClient({
99
- baseURL: "https://api.example.com",
100
99
  onTokenExpired: () => (window.location.href = "/login"),
101
100
  onUnauthorized: () => alert("Session expired"),
102
101
  });
@@ -192,6 +191,11 @@ verification-code login, registration auto-login, and mini-program login. Set
192
191
  `autoRedirectAfterLogin: false` to disable this behavior and fully control
193
192
  navigation in the application layer.
194
193
 
194
+ When the SDK actually consumes a redirect target, successful login results will
195
+ include `result.data.redirectHandled === true` and `result.data.redirectTarget`.
196
+ Applications that still run their own post-login navigation should short-circuit
197
+ on that flag to avoid double redirects.
198
+
195
199
  **Popup window:**
196
200
 
197
201
  ```typescript
@@ -212,40 +216,56 @@ if (window.opener) {
212
216
  }
213
217
  ```
214
218
 
215
- ### WeChat Mini Program Login
219
+ ### Mini Program Login
220
+
221
+ The SDK exposes a unified Mini Program API for both WeChat and Douyin.
222
+
223
+ - WeChat runtime: auto-detects `wx` and uses WeChat endpoints
224
+ - Douyin Mini Program: auto-detects the `tt` runtime and uses Douyin endpoints
225
+ - Non-runtime or mixed environments: you can explicitly pass `platform`
226
+
227
+ The SDK automatically detects the Mini Program storage runtime and uses WeChat `wx.storage` or Douyin `tt.storage`.
228
+ For most app code, prefer the high-level methods:
216
229
 
217
- The SDK automatically detects WeChat Mini Program environment and uses `wx.storage`:
230
+ - `miniLogin()` - automatically calls `Taro.login` / Douyin `tt.login` / WeChat `wx.login`, then completes backend login
231
+ - `miniGetPhone(...)` - accepts a raw code or event object, extracts the phone code, then binds the phone number
218
232
 
219
233
  ```typescript
220
234
  import { createAuthClient } from "@amaster.ai/auth-client";
235
+ import Taro from "@tarojs/taro";
221
236
 
222
- // Zero configuration - auto-detects WeChat environment
223
- const authClient = createAuthClient({
224
- baseURL: "https://api.yourdomain.com",
225
- });
237
+ // Zero configuration - auto-detects mini-program environment
238
+ const authClient = createAuthClient();
226
239
 
227
- // Login with WeChat code
228
- wx.login({
229
- success: async (res) => {
230
- if (res.code) {
231
- const result = await authClient.loginWithMiniProgram(res.code);
232
-
233
- if (result.data) {
234
- console.log("Logged in:", result.data.user);
235
- // Token automatically saved to wx.storage
236
- wx.switchTab({ url: "/pages/index/index" });
237
- } else if (result.error) {
238
- wx.showToast({
239
- title: result.error.message || "Login failed",
240
- icon: "none",
241
- });
242
- }
243
- }
244
- },
245
- fail: (err) => {
246
- console.error("wx.login failed:", err);
247
- },
240
+ const result = await authClient.miniLogin();
241
+
242
+ if (result.data) {
243
+ console.log("Logged in:", result.data.user);
244
+ // Token automatically saved to mini-program storage
245
+ Taro.switchTab({ url: "/pages/index/index" });
246
+ } else if (result.error) {
247
+ Taro.showToast({
248
+ title: result.error.message || "Login failed",
249
+ icon: "none",
250
+ });
251
+ }
252
+ ```
253
+
254
+ **Login with Douyin Mini Program:**
255
+
256
+ ```typescript
257
+ const result = await authClient.miniLogin({
258
+ platform: "douyin",
248
259
  });
260
+
261
+ if (result.data) {
262
+ console.log("Logged in:", result.data.user);
263
+ } else if (result.error) {
264
+ Taro.showToast({
265
+ title: result.error.message || "Login failed",
266
+ icon: "none",
267
+ });
268
+ }
249
269
  ```
250
270
 
251
271
  **Get user phone number (optional):**
@@ -263,25 +283,21 @@ wx.login({
263
283
  ```typescript
264
284
  // JS
265
285
  async onGetPhoneNumber(e) {
266
- const { code } = e.detail;
286
+ const result = await authClient.miniGetPhone(e);
267
287
 
268
- if (code) {
269
- const result = await authClient.getMiniProgramPhoneNumber(code);
270
-
271
- if (result.data) {
272
- console.log("Phone number:", result.data.phone);
273
- console.log("Verified:", result.data.phoneVerified);
288
+ if (result.data) {
289
+ console.log("Phone number:", result.data.phone);
290
+ console.log("Verified:", result.data.phoneVerified);
274
291
 
275
- // Update UI with phone number
276
- this.setData({
277
- phone: result.data.phone
278
- });
279
- } else if (result.error) {
280
- wx.showToast({
281
- title: result.error.message || 'Failed to get phone number',
282
- icon: 'none'
283
- });
284
- }
292
+ // Update UI with phone number
293
+ this.setData({
294
+ phone: result.data.phone
295
+ });
296
+ } else if (result.error) {
297
+ Taro.showToast({
298
+ title: result.error.message || 'Failed to get phone number',
299
+ icon: 'none'
300
+ });
285
301
  } else {
286
302
  // User denied authorization
287
303
  console.log("User cancelled phone number authorization");
@@ -289,15 +305,29 @@ async onGetPhoneNumber(e) {
289
305
  }
290
306
  ```
291
307
 
308
+ **Get Douyin Mini Program phone number:**
309
+
310
+ ```typescript
311
+ async function onGetPhoneNumber(e) {
312
+ const result = await authClient.miniGetPhone({
313
+ ...e,
314
+ platform: "douyin",
315
+ });
316
+
317
+ if (result.data) {
318
+ console.log("Phone number:", result.data.phone);
319
+ }
320
+ }
321
+ ```
322
+
292
323
  **Complete Mini Program example:**
293
324
 
294
325
  ```typescript
295
326
  // pages/login/login.js
296
327
  import { createAuthClient } from "@amaster.ai/auth-client";
328
+ import Taro from "@tarojs/taro";
297
329
 
298
- const authClient = createAuthClient({
299
- baseURL: "https://api.yourdomain.com",
300
- });
330
+ const authClient = createAuthClient();
301
331
 
302
332
  Page({
303
333
  data: {
@@ -312,38 +342,25 @@ Page({
312
342
 
313
343
  // WeChat Mini Program login
314
344
  async handleLogin() {
315
- wx.showLoading({ title: "Logging in..." });
316
-
317
- wx.login({
318
- success: async (res) => {
319
- if (res.code) {
320
- const result = await authClient.loginWithMiniProgram(res.code);
321
-
322
- wx.hideLoading();
323
-
324
- if (result.data) {
325
- this.setData({
326
- userInfo: result.data.user,
327
- });
328
-
329
- // Navigate to home
330
- wx.switchTab({ url: "/pages/index/index" });
331
- } else {
332
- wx.showToast({
333
- title: "Login failed",
334
- icon: "none",
335
- });
336
- }
337
- }
338
- },
339
- fail: () => {
340
- wx.hideLoading();
341
- wx.showToast({
342
- title: "Login failed",
343
- icon: "none",
344
- });
345
- },
346
- });
345
+ Taro.showLoading({ title: "Logging in..." });
346
+
347
+ const result = await authClient.miniLogin();
348
+
349
+ Taro.hideLoading();
350
+
351
+ if (result.data) {
352
+ this.setData({
353
+ userInfo: result.data.user,
354
+ });
355
+
356
+ // Navigate to home
357
+ Taro.switchTab({ url: "/pages/index/index" });
358
+ } else {
359
+ Taro.showToast({
360
+ title: "Login failed",
361
+ icon: "none",
362
+ });
363
+ }
347
364
  },
348
365
 
349
366
  // Get phone number with user authorization
@@ -351,30 +368,30 @@ Page({
351
368
  const { code } = e.detail;
352
369
 
353
370
  if (!code) {
354
- wx.showToast({
371
+ Taro.showToast({
355
372
  title: "Authorization cancelled",
356
373
  icon: "none",
357
374
  });
358
375
  return;
359
376
  }
360
377
 
361
- wx.showLoading({ title: "Getting phone..." });
378
+ Taro.showLoading({ title: "Getting phone..." });
362
379
 
363
- const result = await authClient.getMiniProgramPhoneNumber(code);
380
+ const result = await authClient.miniGetPhone(e);
364
381
 
365
- wx.hideLoading();
382
+ Taro.hideLoading();
366
383
 
367
384
  if (result.data) {
368
385
  this.setData({
369
386
  hasPhone: true,
370
387
  });
371
388
 
372
- wx.showToast({
389
+ Taro.showToast({
373
390
  title: "Phone number obtained",
374
391
  icon: "success",
375
392
  });
376
393
  } else {
377
- wx.showToast({
394
+ Taro.showToast({
378
395
  title: result.error?.message || "Failed to get phone",
379
396
  icon: "none",
380
397
  });
@@ -383,6 +400,13 @@ Page({
383
400
  });
384
401
  ```
385
402
 
403
+ **Low-level compatibility APIs (deprecated, advanced use only):**
404
+
405
+ If your app already has a login `code` or phone `code`, you can still call:
406
+
407
+ - `loginWithMiniProgram(code | { code, platform })`
408
+ - `getMiniProgramPhoneNumber(code | { code, platform })`
409
+
386
410
  ### Logout
387
411
 
388
412
  ```typescript
package/dist/auth.d.cts CHANGED
@@ -14,7 +14,7 @@
14
14
  * ============================================================================
15
15
  */
16
16
  import { HttpClient, ClientResult } from '@amaster.ai/http-client';
17
- import { q as User, i as RegisterParams, e as LoginResponse, L as LoginParams, c as CodeLoginParams, S as SendCodeParams, p as SuccessResponse, b as CaptchaResponse, g as OAuthProvider, M as MiniProgramPhoneResponse, R as RefreshTokenResponse } from './types-DGF9cpAg.cjs';
17
+ import { w as User, o as RegisterParams, e as LoginResponse, L as LoginParams, c as CodeLoginParams, S as SendCodeParams, v as SuccessResponse, b as CaptchaResponse, m as OAuthProvider, i as MiniProgramLoginParams, h as MiniLoginParams, k as MiniProgramPhoneParams, l as MiniProgramPhoneResponse, g as MiniGetPhoneParams, R as RefreshTokenResponse } from './types-DqwQ2EzH.cjs';
18
18
 
19
19
  /**
20
20
  * Authentication Module
@@ -36,6 +36,7 @@ declare const browserNavigation: {
36
36
  interface AuthModuleDeps {
37
37
  http: HttpClient;
38
38
  onLoginSuccess: (user: User, accessToken: string) => void;
39
+ onLogout: () => void;
39
40
  autoRedirectAfterLogin: boolean;
40
41
  storage: {
41
42
  getItem: (key: string) => string | null;
@@ -134,50 +135,63 @@ declare function createAuthModule(deps: AuthModuleDeps): {
134
135
  */
135
136
  handleOAuthCallback(): Promise<ClientResult<LoginResponse>>;
136
137
  /**
137
- * Login with WeChat Mini Program code
138
+ * Login with Mini Program code
139
+ *
140
+ * Lower-level API for submitting an already acquired mini-program login code.
141
+ * For most app code, prefer `miniLogin()`.
142
+ *
143
+ * @deprecated Prefer `miniLogin()` unless you already have a resolved mini-program login code.
144
+ *
145
+ * @category Authentication
146
+ */
147
+ loginWithMiniProgram(input: string | MiniProgramLoginParams): Promise<ClientResult<LoginResponse>>;
148
+ /**
149
+ * Unified Mini Program login entry.
150
+ *
151
+ * Automatically calls Taro / WeChat `wx` / Douyin `tt` login APIs to fetch the temporary login code,
152
+ * then submits it to the backend using the correct platform endpoint.
138
153
  *
139
154
  * @category Authentication
140
155
  * @example
141
156
  * ```typescript
142
- * // In WeChat Mini Program
143
- * wx.login({
144
- * success: async (res) => {
145
- * if (res.code) {
146
- * const result = await auth.loginWithMiniProgram(res.code);
147
- * if (result.data) {
148
- * console.log("Logged in:", result.data.user);
149
- * }
150
- * }
151
- * }
157
+ * const result = await auth.miniLogin();
158
+ *
159
+ * const douyinResult = await auth.miniLogin({
160
+ * platform: "douyin",
152
161
  * });
153
162
  * ```
154
163
  */
155
- loginWithMiniProgram(code: string): Promise<ClientResult<LoginResponse>>;
164
+ miniLogin(params?: MiniLoginParams): Promise<ClientResult<LoginResponse>>;
156
165
  /**
157
- * Get WeChat Mini Program user phone number
166
+ * Get Mini Program user phone number
158
167
  * Requires user authorization via getPhoneNumber button
159
168
  *
169
+ * Lower-level API for submitting an already acquired phone code.
170
+ * For most app code, prefer `miniGetPhone(...)`.
171
+ *
172
+ * @deprecated Prefer `miniGetPhone(...)` unless you already have a resolved phone authorization code.
173
+ *
174
+ * @category Authentication
175
+ */
176
+ getMiniProgramPhoneNumber(input: string | MiniProgramPhoneParams): Promise<ClientResult<MiniProgramPhoneResponse>>;
177
+ /**
178
+ * Unified Mini Program phone binding entry.
179
+ *
180
+ * Accepts a raw code, a `{ code, platform }` object, or a Mini Program event object
181
+ * such as the payload received from WeChat `wx`, Douyin `tt`, or Taro `getPhoneNumber`.
182
+ *
160
183
  * @category Authentication
161
184
  * @example
162
185
  * ```typescript
163
- * // WXML
164
- * <button open-type="getPhoneNumber" bindgetphonenumber="onGetPhoneNumber">
165
- * Get Phone Number
166
- * </button>
167
- *
168
- * // JS
169
- * async onGetPhoneNumber(e) {
170
- * const { code } = e.detail;
171
- * if (code) {
172
- * const result = await auth.getMiniProgramPhoneNumber(code);
173
- * if (result.data) {
174
- * console.log("Phone:", result.data.phone);
175
- * }
176
- * }
177
- * }
186
+ * const result = await auth.miniGetPhone(e);
187
+ *
188
+ * const douyinResult = await auth.miniGetPhone({
189
+ * code,
190
+ * platform: "douyin",
191
+ * });
178
192
  * ```
179
193
  */
180
- getMiniProgramPhoneNumber(code: string): Promise<ClientResult<MiniProgramPhoneResponse>>;
194
+ miniGetPhone(input: MiniGetPhoneParams): Promise<ClientResult<MiniProgramPhoneResponse>>;
181
195
  /**
182
196
  * Logout current user
183
197
  *
package/dist/auth.d.ts CHANGED
@@ -14,7 +14,7 @@
14
14
  * ============================================================================
15
15
  */
16
16
  import { HttpClient, ClientResult } from '@amaster.ai/http-client';
17
- import { q as User, i as RegisterParams, e as LoginResponse, L as LoginParams, c as CodeLoginParams, S as SendCodeParams, p as SuccessResponse, b as CaptchaResponse, g as OAuthProvider, M as MiniProgramPhoneResponse, R as RefreshTokenResponse } from './types-DGF9cpAg.js';
17
+ import { w as User, o as RegisterParams, e as LoginResponse, L as LoginParams, c as CodeLoginParams, S as SendCodeParams, v as SuccessResponse, b as CaptchaResponse, m as OAuthProvider, i as MiniProgramLoginParams, h as MiniLoginParams, k as MiniProgramPhoneParams, l as MiniProgramPhoneResponse, g as MiniGetPhoneParams, R as RefreshTokenResponse } from './types-DqwQ2EzH.js';
18
18
 
19
19
  /**
20
20
  * Authentication Module
@@ -36,6 +36,7 @@ declare const browserNavigation: {
36
36
  interface AuthModuleDeps {
37
37
  http: HttpClient;
38
38
  onLoginSuccess: (user: User, accessToken: string) => void;
39
+ onLogout: () => void;
39
40
  autoRedirectAfterLogin: boolean;
40
41
  storage: {
41
42
  getItem: (key: string) => string | null;
@@ -134,50 +135,63 @@ declare function createAuthModule(deps: AuthModuleDeps): {
134
135
  */
135
136
  handleOAuthCallback(): Promise<ClientResult<LoginResponse>>;
136
137
  /**
137
- * Login with WeChat Mini Program code
138
+ * Login with Mini Program code
139
+ *
140
+ * Lower-level API for submitting an already acquired mini-program login code.
141
+ * For most app code, prefer `miniLogin()`.
142
+ *
143
+ * @deprecated Prefer `miniLogin()` unless you already have a resolved mini-program login code.
144
+ *
145
+ * @category Authentication
146
+ */
147
+ loginWithMiniProgram(input: string | MiniProgramLoginParams): Promise<ClientResult<LoginResponse>>;
148
+ /**
149
+ * Unified Mini Program login entry.
150
+ *
151
+ * Automatically calls Taro / WeChat `wx` / Douyin `tt` login APIs to fetch the temporary login code,
152
+ * then submits it to the backend using the correct platform endpoint.
138
153
  *
139
154
  * @category Authentication
140
155
  * @example
141
156
  * ```typescript
142
- * // In WeChat Mini Program
143
- * wx.login({
144
- * success: async (res) => {
145
- * if (res.code) {
146
- * const result = await auth.loginWithMiniProgram(res.code);
147
- * if (result.data) {
148
- * console.log("Logged in:", result.data.user);
149
- * }
150
- * }
151
- * }
157
+ * const result = await auth.miniLogin();
158
+ *
159
+ * const douyinResult = await auth.miniLogin({
160
+ * platform: "douyin",
152
161
  * });
153
162
  * ```
154
163
  */
155
- loginWithMiniProgram(code: string): Promise<ClientResult<LoginResponse>>;
164
+ miniLogin(params?: MiniLoginParams): Promise<ClientResult<LoginResponse>>;
156
165
  /**
157
- * Get WeChat Mini Program user phone number
166
+ * Get Mini Program user phone number
158
167
  * Requires user authorization via getPhoneNumber button
159
168
  *
169
+ * Lower-level API for submitting an already acquired phone code.
170
+ * For most app code, prefer `miniGetPhone(...)`.
171
+ *
172
+ * @deprecated Prefer `miniGetPhone(...)` unless you already have a resolved phone authorization code.
173
+ *
174
+ * @category Authentication
175
+ */
176
+ getMiniProgramPhoneNumber(input: string | MiniProgramPhoneParams): Promise<ClientResult<MiniProgramPhoneResponse>>;
177
+ /**
178
+ * Unified Mini Program phone binding entry.
179
+ *
180
+ * Accepts a raw code, a `{ code, platform }` object, or a Mini Program event object
181
+ * such as the payload received from WeChat `wx`, Douyin `tt`, or Taro `getPhoneNumber`.
182
+ *
160
183
  * @category Authentication
161
184
  * @example
162
185
  * ```typescript
163
- * // WXML
164
- * <button open-type="getPhoneNumber" bindgetphonenumber="onGetPhoneNumber">
165
- * Get Phone Number
166
- * </button>
167
- *
168
- * // JS
169
- * async onGetPhoneNumber(e) {
170
- * const { code } = e.detail;
171
- * if (code) {
172
- * const result = await auth.getMiniProgramPhoneNumber(code);
173
- * if (result.data) {
174
- * console.log("Phone:", result.data.phone);
175
- * }
176
- * }
177
- * }
186
+ * const result = await auth.miniGetPhone(e);
187
+ *
188
+ * const douyinResult = await auth.miniGetPhone({
189
+ * code,
190
+ * platform: "douyin",
191
+ * });
178
192
  * ```
179
193
  */
180
- getMiniProgramPhoneNumber(code: string): Promise<ClientResult<MiniProgramPhoneResponse>>;
194
+ miniGetPhone(input: MiniGetPhoneParams): Promise<ClientResult<MiniProgramPhoneResponse>>;
181
195
  /**
182
196
  * Logout current user
183
197
  *
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- 'use strict';var httpClient=require('@amaster.ai/http-client');var R=class{constructor(){this.events={};}on(e,s){this.events[e]||(this.events[e]=[]),this.events[e].push(s);}off(e,s){this.events[e]&&(this.events[e]=this.events[e].filter(r=>r!==s));}emit(e,...s){this.events[e]&&this.events[e].forEach(r=>{try{r(...s);}catch(o){console.error(`[AuthClient] Error in event handler for "${e}":`,o);}});}removeAllListeners(){this.events={};}};var c={ACCESS_TOKEN:"amaster_access_token",REFRESH_TOKEN:"amaster_refresh_token",USER:"amaster_user"};function B(){return typeof wx<"u"&&wx.getStorageSync?"wechat-miniprogram":typeof tt<"u"&&tt.getStorageSync?"douyin-miniprogram":typeof window<"u"&&typeof window.localStorage<"u"?"browser":"node"}function T(){switch(B()){case "wechat-miniprogram":return w(wx,"WeChat");case "douyin-miniprogram":return w(tt,"Douyin");case "browser":return F();case "node":return z()}}function F(){let t=window.localStorage;return {getItem(e){try{return t.getItem(e)}catch(s){return console.error("[AuthClient] Failed to get item from localStorage:",s),null}},setItem(e,s){try{t.setItem(e,s);}catch(r){console.error("[AuthClient] Failed to set item in localStorage:",r);}},removeItem(e){try{t.removeItem(e);}catch(s){console.error("[AuthClient] Failed to remove item from localStorage:",s);}},clear(){try{t.removeItem(c.ACCESS_TOKEN),t.removeItem(c.REFRESH_TOKEN),t.removeItem(c.USER);}catch(e){console.error("[AuthClient] Failed to clear localStorage:",e);}}}}function w(t,e){return {getItem(s){try{return t.getStorageSync(s)||null}catch(r){return console.error(`[AuthClient] Failed to get item from ${e} storage:`,r),null}},setItem(s,r){try{t.setStorageSync(s,r);}catch(o){console.error(`[AuthClient] Failed to set item in ${e} storage:`,o);}},removeItem(s){try{t.removeStorageSync(s);}catch(r){console.error(`[AuthClient] Failed to remove item from ${e} storage:`,r);}},clear(){try{t.removeStorageSync(c.ACCESS_TOKEN),t.removeStorageSync(c.REFRESH_TOKEN),t.removeStorageSync(c.USER);}catch(s){console.error(`[AuthClient] Failed to clear ${e} storage:`,s);}}}}function z(){let t=new Map;return {getItem(e){return t.get(e)??null},setItem(e,s){t.set(e,s);},removeItem(e){t.delete(e);},clear(){t.clear();}}}function K(t){try{let e=t.split(".");if(e.length!==3)return null;let r=(e[1]||"").replace(/-/g,"+").replace(/_/g,"/");if(typeof atob<"u"){let o=decodeURIComponent(atob(r).split("").map(u=>"%"+("00"+u.charCodeAt(0).toString(16)).slice(-2)).join(""));return JSON.parse(o)}if(typeof Buffer<"u"){let o=Buffer.from(r,"base64").toString("utf-8");return JSON.parse(o)}return null}catch(e){return console.error("[AuthClient] Failed to parse JWT token:",e),null}}var S=class{constructor(){this.refreshTimer=null;this.isRefreshing=false;this.refreshCallback=null;}setRefreshCallback(e){this.refreshCallback=e;}scheduleRefresh(e){this.clearSchedule(),!(e<=0)&&(this.refreshTimer=setTimeout(()=>{this.refresh();},e));}scheduleRefreshFromToken(e,s=300){let r=K(e);if(!r||!r.exp){console.warn("[AuthClient] Cannot schedule refresh: invalid token or missing exp claim");return}let o=r.exp*1e3,u=Date.now(),a=o-u-s*1e3;a<=0?(console.warn("[AuthClient] Token already expired or expiring soon, refreshing immediately"),this.refresh()):this.scheduleRefresh(a);}async refresh(){if(!this.isRefreshing){if(!this.refreshCallback){console.error("[AuthClient] No refresh callback set");return}this.isRefreshing=true;try{await this.refreshCallback();}catch(e){console.error("[AuthClient] Token refresh failed:",e);}finally{this.isRefreshing=false;}}}clearSchedule(){this.refreshTimer&&(clearTimeout(this.refreshTimer),this.refreshTimer=null);}isCurrentlyRefreshing(){return this.isRefreshing}destroy(){this.clearSchedule(),this.refreshCallback=null,this.isRefreshing=false;}};function P(t){return t&&typeof t=="object"&&("statusCode"in t||"status"in t)&&"data"in t?t.data:t}var v={transformResponse:P,logErrors:true};function j(t){if(t.email)return "email";if(t.username)return "username";if(t.phone)return "phone"}function D(t){if(t.email)return "email";if(t.phone)return "phone"}function J(t){let e=new URLSearchParams(t);return e.get("access_token")||e.get("accessToken")}function W(t){return new URLSearchParams(t).get("user")}function G(){if(typeof window>"u")return null;try{let t=new URLSearchParams(window.location.search).get("redirect");if(!t)return null;let e=new URL(t,window.location.origin);return e.origin!==window.location.origin?(console.warn("[AuthClient] Ignored cross-origin redirect target:",t),null):`${e.pathname}${e.search}${e.hash}`}catch(t){return console.warn("[AuthClient] Failed to resolve redirect target:",t),null}}var Y={replace(t){window.location.replace(t);}};function A(t){if(!t||typeof window>"u"||window.opener)return;let e=G();e&&Y.replace(e);}function E(t){let{http:e,onLoginSuccess:s,autoRedirectAfterLogin:r,storage:o,clearAuth:u}=t;return {async register(n){let a=await e.request({url:"/api/auth/register",method:"post",headers:{"Content-Type":"application/json"},data:n});return a.data?.user&&a.data?.accessToken&&(s(a.data.user,a.data.accessToken),A(r)),a},async login(n){let a=n.loginType||j(n);if(!a)return {data:null,error:{message:"Unable to determine login type. Please provide email, username, or phone.",status:400},status:400};let d={...n,loginType:a},l=await e.request({url:"/api/auth/login",method:"post",headers:{"Content-Type":"application/json"},data:d});return l.data?.user&&l.data?.accessToken&&(s(l.data.user,l.data.accessToken),A(r)),l},async loginWithCode(n){let a=n.loginType||D(n);if(!a)return {data:null,error:{message:"Unable to determine login type. Please provide email or phone.",status:400},status:400};let d={...n,loginType:a},l=await e.request({url:"/api/auth/login-with-code",method:"post",headers:{"Content-Type":"application/json"},data:d});return l.data?.user&&l.data?.accessToken&&(s(l.data.user,l.data.accessToken),A(r)),l},async sendCode(n){return e.request({url:"/api/auth/send-code",method:"post",headers:{"Content-Type":"application/json"},data:n})},async getCaptcha(){return e.request({url:"/api/auth/captcha",method:"get"})},loginWithOAuth(n,a){if(typeof window>"u"){console.error("[AuthClient] OAuth login is only available in browser environment");return}let d=a?`/api/auth/oauth/${n}?redirect_url=${encodeURIComponent(a)}`:`/api/auth/oauth/${n}`;window.location.href=d;},async handleOAuthCallback(){if(typeof window>"u")return {data:null,error:{message:"OAuth callback is only available in browser environment",status:400},status:400};try{let n=window.location.hash.substring(1),a=J(n),d=W(n);if(!a)return {data:null,error:{message:"OAuth callback failed: missing access token",status:400},status:400};let l;if(d)l=JSON.parse(decodeURIComponent(d));else {o.setItem(c.ACCESS_TOKEN,a);let m=await e.request({url:"/api/auth/me",method:"get",headers:{Authorization:`Bearer ${a}`}});if(!m.data)return {data:null,error:{message:"OAuth callback failed: unable to fetch user info",status:m.status||500},status:m.status||500};l=m.data;}if(s(l,a),window.history&&window.history.replaceState){let m=window.location.pathname+window.location.search;window.history.replaceState(null,"",m);}else window.location.hash="";return A(r),{data:{user:l,accessToken:a},error:null,status:200}}catch(n){return {data:null,error:{message:`OAuth callback failed: ${n instanceof Error?n.message:String(n)}`,status:400},status:400}}},async loginWithMiniProgram(n){let a=await e.request({url:"/api/auth/miniprogram/login",method:"post",headers:{"Content-Type":"application/json"},data:{code:n}});return a.data?.user&&a.data?.accessToken&&(s(a.data.user,a.data.accessToken),A(r)),a},async getMiniProgramPhoneNumber(n){let a=o.getItem("amaster_access_token");return a?e.request({url:"/api/auth/miniprogram/phone",method:"post",headers:{"Content-Type":"application/json",Authorization:`Bearer ${a}`},data:{code:n}}):{data:null,error:{message:"Not authenticated",status:401},status:401}},async logout(){let n=o.getItem("amaster_access_token"),a=await e.request({url:"/api/auth/logout",method:"post",headers:n?{Authorization:`Bearer ${n}`}:void 0});return u(),a},async refreshToken(){let n=await e.request({url:"/api/auth/refresh",method:"post"});return n.data?.accessToken&&o.setItem("amaster_access_token",n.data.accessToken),n}}}function O(t){let{getCurrentUser:e}=t;return {hasRole(s){let r=e();return !r||!r.roles?false:r.roles.includes(s)},hasPermission(s,r){let o=e();if(!o||!o.permissions)return false;let u=`${s}.${r}`;return o.permissions.includes(u)},hasAnyPermission(s){return s.some(({resource:r,action:o})=>this.hasPermission(r,o))},hasAllPermissions(s){return s.every(({resource:r,action:o})=>this.hasPermission(r,o))}}}function b(t){let{http:e,storage:s,onUserUpdate:r}=t;return {async getMe(){let o=s.getItem("amaster_access_token");if(!o)return {data:null,error:{message:"Not authenticated",status:401},status:401};let u=await e.request({url:"/api/auth/me",method:"get",headers:{Authorization:`Bearer ${o}`}});return u.data&&r(u.data),u},async updateMe(o){let u=s.getItem("amaster_access_token");if(!u)return {data:null,error:{message:"Not authenticated",status:401},status:401};let n=await e.request({url:"/api/auth/me",method:"put",headers:{Authorization:`Bearer ${u}`,"Content-Type":"application/json"},data:o});return n.data&&r(n.data),n},async changePassword(o){let u=s.getItem("amaster_access_token");return u?e.request({url:"/api/auth/change-password",method:"post",headers:{Authorization:`Bearer ${u}`,"Content-Type":"application/json"},data:o}):{data:null,error:{message:"Not authenticated",status:401},status:401}}}}function M(t){let{http:e,storage:s}=t;return {async getOAuthBindings(){let r=s.getItem("amaster_access_token");return r?e.request({url:"/api/auth/oauth-bindings",method:"get",headers:{Authorization:`Bearer ${r}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}},bindOAuth(r){if(typeof window>"u"){console.error("[AuthClient] OAuth binding is only available in browser environment");return}window.location.href=`/api/auth/oauth/${r}/bind`;},async unbindOAuth(r){let o=s.getItem("amaster_access_token");return o?e.request({url:`/api/auth/oauth/${r}/unbind`,method:"delete",headers:{Authorization:`Bearer ${o}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}}}}function U(t){let{http:e,storage:s}=t;return {async getSession(){let r=s.getItem("amaster_access_token");return r?e.request({url:"/api/auth/sessions/current",method:"get",headers:{Authorization:`Bearer ${r}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}},async getSessions(){let r=s.getItem("amaster_access_token");return r?e.request({url:"/api/auth/sessions",method:"get",headers:{Authorization:`Bearer ${r}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}},async revokeSession(r){let o=s.getItem("amaster_access_token");return o?r?e.request({url:`/api/auth/sessions/${r}`,method:"delete",headers:{Authorization:`Bearer ${o}`}}):{data:null,error:{message:"Session ID is required",status:400},status:400}:{data:null,error:{message:"Not authenticated",status:401},status:401}},async revokeAllSessions(){let r=s.getItem("amaster_access_token");return r?e.request({url:"/api/auth/sessions",method:"delete",headers:{Authorization:`Bearer ${r}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}}}}function V(t={},e){let {baseURL:s,headers:r,onTokenExpired:o,onUnauthorized:u,autoHandleOAuthCallback:n=true,autoRedirectAfterLogin:a=true}=t,d=e||httpClient.createHttpClient({...v,baseURL:s,headers:r}),m=300,h=T(),f=new R,C=new S,y=null;try{let i=h.getItem(c.USER);i&&(y=JSON.parse(i));}catch(i){console.error("[AuthClient] Failed to load user from storage:",i);}let g;C.setRefreshCallback(async()=>{let i=await g.refreshToken();i.data?(await g.getMe(),f.emit("tokenRefreshed",i.data.accessToken)):(f.emit("tokenExpired"),o?.());});function I(i,p){h.setItem(c.ACCESS_TOKEN,p),h.setItem(c.USER,JSON.stringify(i)),y=i,C.scheduleRefreshFromToken(p,m),f.emit("login",i);}function _(i){y=i,h.setItem(c.USER,JSON.stringify(i));}function k(){h.clear(),y=null,C.clearSchedule();}function x(){return y}let L=E({http:d,onLoginSuccess:I,autoRedirectAfterLogin:a,storage:h,clearAuth:k}),H=O({getCurrentUser:x}),N=b({http:d,storage:h,onUserUpdate:_}),$=M({http:d,storage:h}),q=U({http:d,storage:h});if(g={...L,...H,...N,...$,...q,on(i,p){f.on(i,p);},off(i,p){f.off(i,p);},isAuthenticated(){return !!h.getItem(c.ACCESS_TOKEN)},getAccessToken(){return h.getItem(c.ACCESS_TOKEN)},setAccessToken(i){h.setItem(c.ACCESS_TOKEN,i),C.scheduleRefreshFromToken(i,m);},clearAuth:k},g.on("unauthorized",()=>{u?.();}),g.isAuthenticated()&&g.getMe().catch(i=>{console.warn("[AuthClient] Failed to sync user info on init:",i);}),n&&typeof window<"u"){let i=window.location.hash;i&&(i.includes("access_token")||i.includes("accessToken"))&&g.handleOAuthCallback().then(p=>{p.error&&console.error("[AuthClient] Auto OAuth callback failed:",p.error);}).catch(p=>{console.error("[AuthClient] Auto OAuth callback error:",p);});}return g}exports.createAuthClient=V;exports.defaultHttpClientOptions=v;exports.transformAmasterResponse=P;//# sourceMappingURL=index.cjs.map
1
+ 'use strict';var httpClient=require('@amaster.ai/http-client');var A=class{constructor(){this.events={};}on(e,r){this.events[e]||(this.events[e]=[]),this.events[e].push(r);}off(e,r){this.events[e]&&(this.events[e]=this.events[e].filter(n=>n!==r));}emit(e,...r){this.events[e]&&this.events[e].forEach(n=>{try{n(...r);}catch(a){console.error(`[AuthClient] Error in event handler for "${e}":`,a);}});}removeAllListeners(){this.events={};}};var g={ACCESS_TOKEN:"amaster_access_token",REFRESH_TOKEN:"amaster_refresh_token",USER:"amaster_user"};function v(t){return globalThis[t]}function J(){let t=v("wx"),e=v("tt");return t?.getStorageSync&&t?.setStorageSync&&t?.removeStorageSync?"wechat-miniprogram":e?.getStorageSync&&e?.setStorageSync&&e?.removeStorageSync?"douyin-miniprogram":typeof window<"u"&&typeof window.localStorage<"u"?"browser":"node"}function O(){switch(J()){case "wechat-miniprogram":return b(v("wx"),"WeChat");case "douyin-miniprogram":return b(v("tt"),"Douyin");case "browser":return W();case "node":return Y()}}function W(){let t=window.localStorage;return {getItem(e){try{return t.getItem(e)}catch(r){return console.error("[AuthClient] Failed to get item from localStorage:",r),null}},setItem(e,r){try{t.setItem(e,r);}catch(n){console.error("[AuthClient] Failed to set item in localStorage:",n);}},removeItem(e){try{t.removeItem(e);}catch(r){console.error("[AuthClient] Failed to remove item from localStorage:",r);}},clear(){try{t.removeItem(g.ACCESS_TOKEN),t.removeItem(g.REFRESH_TOKEN),t.removeItem(g.USER);}catch(e){console.error("[AuthClient] Failed to clear localStorage:",e);}}}}function b(t,e){return {getItem(r){try{return t.getStorageSync(r)||null}catch(n){return console.error(`[AuthClient] Failed to get item from ${e} storage:`,n),null}},setItem(r,n){try{t.setStorageSync(r,n);}catch(a){console.error(`[AuthClient] Failed to set item in ${e} storage:`,a);}},removeItem(r){try{t.removeStorageSync(r);}catch(n){console.error(`[AuthClient] Failed to remove item from ${e} storage:`,n);}},clear(){try{t.removeStorageSync(g.ACCESS_TOKEN),t.removeStorageSync(g.REFRESH_TOKEN),t.removeStorageSync(g.USER);}catch(r){console.error(`[AuthClient] Failed to clear ${e} storage:`,r);}}}}function Y(){let t=new Map;return {getItem(e){return t.get(e)??null},setItem(e,r){t.set(e,r);},removeItem(e){t.delete(e);},clear(){t.clear();}}}function Q(t){try{let e=t.split(".");if(e.length!==3)return null;let n=(e[1]||"").replace(/-/g,"+").replace(/_/g,"/");if(typeof atob<"u"){let a=decodeURIComponent(atob(n).split("").map(l=>"%"+("00"+l.charCodeAt(0).toString(16)).slice(-2)).join(""));return JSON.parse(a)}if(typeof Buffer<"u"){let a=Buffer.from(n,"base64").toString("utf-8");return JSON.parse(a)}return null}catch(e){return console.error("[AuthClient] Failed to parse JWT token:",e),null}}var w=class{constructor(){this.refreshTimer=null;this.isRefreshing=false;this.refreshCallback=null;}setRefreshCallback(e){this.refreshCallback=e;}scheduleRefresh(e){this.clearSchedule(),!(e<=0)&&(this.refreshTimer=setTimeout(()=>{this.refresh();},e));}scheduleRefreshFromToken(e,r=300){let n=Q(e);if(!n||!n.exp){console.warn("[AuthClient] Cannot schedule refresh: invalid token or missing exp claim");return}let a=n.exp*1e3,l=Date.now(),s=a-l-r*1e3;s<=0?(console.warn("[AuthClient] Token already expired or expiring soon, refreshing immediately"),this.refresh()):this.scheduleRefresh(s);}async refresh(){if(!this.isRefreshing){if(!this.refreshCallback){console.error("[AuthClient] No refresh callback set");return}this.isRefreshing=true;try{await this.refreshCallback();}catch(e){console.error("[AuthClient] Token refresh failed:",e);}finally{this.isRefreshing=false;}}}clearSchedule(){this.refreshTimer&&(clearTimeout(this.refreshTimer),this.refreshTimer=null);}isCurrentlyRefreshing(){return this.isRefreshing}destroy(){this.clearSchedule(),this.refreshCallback=null,this.isRefreshing=false;}};function U(t){return t&&typeof t=="object"&&("statusCode"in t||"status"in t)&&"data"in t?t.data:t}var M={transformResponse:U,logErrors:true};function Z(t){if(t.email)return "email";if(t.username)return "username";if(t.phone)return "phone"}function ee(t){if(t.email)return "email";if(t.phone)return "phone"}function k(t){return t||(httpClient.detectMiniProgramPlatform()??"wechat")}function T(t){return typeof t=="string"?{code:t,platform:k()}:{code:t.code,platform:k(t.platform)}}function L(t,e){return e==="douyin"?`/api/auth/miniprogram/douyin/${t}`:`/api/auth/miniprogram/${t}`}async function te(t){let e=k(t),r=httpClient.getMiniProgramLogin(e),n=async a=>await new Promise((l,m)=>{let s=false,i=o=>{if(!s){if(s=true,typeof o?.code=="string"&&o.code){l(o.code);return}m(new Error("Mini Program login failed: missing code"));}},c=o=>{s||(s=true,m(new Error(`Mini Program login failed: ${o instanceof Error?o.message:String(o)}`)));};try{let o=a({success:i,fail:c});if(o&&typeof o.then=="function"){o.then(i,c);return}o&&typeof o=="object"&&"code"in o&&i(o);}catch(o){c(o);}});if(typeof r!="function")throw new Error(`Mini Program login API is not available for platform '${e}'`);return {code:await n(r),platform:e}}function re(t){if(typeof t=="string")return T(t);let e="detail"in t&&t.detail&&typeof t.detail=="object"?t.detail:null,r=typeof e?.code=="string"&&e.code?e.code:typeof t.code=="string"&&t.code?t.code:void 0;return r?{code:r,platform:k(t.platform)}:null}function ne(t){let e=new URLSearchParams(t);return e.get("access_token")||e.get("accessToken")}function oe(t){return new URLSearchParams(t).get("user")}function se(){if(typeof window>"u")return null;try{let t=new URLSearchParams(window.location.search).get("redirect");if(!t)return null;let e=new URL(t,window.location.origin);return e.origin!==window.location.origin?(console.warn("[AuthClient] Ignored cross-origin redirect target:",t),null):`${e.pathname}${e.search}${e.hash}`}catch(t){return console.warn("[AuthClient] Failed to resolve redirect target:",t),null}}var ie={replace(t){window.location.replace(t);}};function S(t,e){return e.handled?{...t,redirectHandled:true,redirectTarget:e.target}:t}function R(t){if(!t||typeof window>"u"||window.opener)return {handled:false};let e=se();return e?(ie.replace(e),{handled:true,target:e}):{handled:false}}function I(t){let{http:e,onLoginSuccess:r,onLogout:n,autoRedirectAfterLogin:a,storage:l,clearAuth:m}=t;return {async register(s){let i=await e.request({url:"/api/auth/register",method:"post",headers:{"Content-Type":"application/json"},data:s});if(i.data?.user&&i.data?.accessToken){r(i.data.user,i.data.accessToken);let c=R(a);i.data=S(i.data,c);}return i},async login(s){let i=s.loginType||Z(s);if(!i)return {data:null,error:{message:"Unable to determine login type. Please provide email, username, or phone.",status:400},status:400};let c={...s,loginType:i},o=await e.request({url:"/api/auth/login",method:"post",headers:{"Content-Type":"application/json"},data:c});if(o.data?.user&&o.data?.accessToken){r(o.data.user,o.data.accessToken);let p=R(a);o.data=S(o.data,p);}return o},async loginWithCode(s){let i=s.loginType||ee(s);if(!i)return {data:null,error:{message:"Unable to determine login type. Please provide email or phone.",status:400},status:400};let c={...s,loginType:i},o=await e.request({url:"/api/auth/login-with-code",method:"post",headers:{"Content-Type":"application/json"},data:c});if(o.data?.user&&o.data?.accessToken){r(o.data.user,o.data.accessToken);let p=R(a);o.data=S(o.data,p);}return o},async sendCode(s){return e.request({url:"/api/auth/send-code",method:"post",headers:{"Content-Type":"application/json"},data:s})},async getCaptcha(){return e.request({url:"/api/auth/captcha",method:"get"})},loginWithOAuth(s,i){if(typeof window>"u"){console.error("[AuthClient] OAuth login is only available in browser environment");return}let c=i?`/api/auth/oauth/${s}?redirect_url=${encodeURIComponent(i)}`:`/api/auth/oauth/${s}`;window.location.href=c;},async handleOAuthCallback(){if(typeof window>"u")return {data:null,error:{message:"OAuth callback is only available in browser environment",status:400},status:400};try{let s=window.location.hash.substring(1),i=ne(s),c=oe(s);if(!i)return {data:null,error:{message:"OAuth callback failed: missing access token",status:400},status:400};let o;if(c)o=JSON.parse(decodeURIComponent(c));else {l.setItem(g.ACCESS_TOKEN,i);let d=await e.request({url:"/api/auth/me",method:"get",headers:{Authorization:`Bearer ${i}`}});if(!d.data)return {data:null,error:{message:"OAuth callback failed: unable to fetch user info",status:d.status||500},status:d.status||500};o=d.data;}if(r(o,i),window.history&&window.history.replaceState){let d=window.location.pathname+window.location.search;window.history.replaceState(null,"",d);}else window.location.hash="";let p=R(a);return {data:S({user:o,accessToken:i},p),error:null,status:200}}catch(s){return {data:null,error:{message:`OAuth callback failed: ${s instanceof Error?s.message:String(s)}`,status:400},status:400}}},async loginWithMiniProgram(s){let{code:i,platform:c}=T(s),o=await e.request({url:L("login",c),method:"post",headers:{"Content-Type":"application/json"},data:{code:i}});if(o.data?.user&&o.data?.accessToken){r(o.data.user,o.data.accessToken);let p=R(a);o.data=S(o.data,p);}return o},async miniLogin(s={}){try{let i=await te(s.platform);return await this.loginWithMiniProgram(i)}catch(i){return {data:null,error:{message:i instanceof Error?i.message:String(i),status:400},status:400}}},async getMiniProgramPhoneNumber(s){let{code:i,platform:c}=T(s),o=l.getItem(g.ACCESS_TOKEN);return o?e.request({url:L("phone",c),method:"post",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},data:{code:i}}):{data:null,error:{message:"Not authenticated",status:401},status:401}},async miniGetPhone(s){let i=re(s);return i?this.getMiniProgramPhoneNumber(i):{data:null,error:{message:"Unable to resolve mini-program phone code from input",status:400},status:400}},async logout(){let s=l.getItem("amaster_access_token"),i=await e.request({url:"/api/auth/logout",method:"post",headers:s?{Authorization:`Bearer ${s}`}:void 0});return m(),n(),i},async refreshToken(){let s=await e.request({url:"/api/auth/refresh",method:"post"});return s.data?.accessToken&&l.setItem("amaster_access_token",s.data.accessToken),s}}}function _(t){let{getCurrentUser:e}=t;return {hasRole(r){let n=e();return !n||!n.roles?false:n.roles.includes(r)},hasPermission(r,n){let a=e();if(!a||!a.permissions)return false;let l=`${r}.${n}`;return a.permissions.includes(l)},hasAnyPermission(r){return r.some(({resource:n,action:a})=>this.hasPermission(n,a))},hasAllPermissions(r){return r.every(({resource:n,action:a})=>this.hasPermission(n,a))}}}function x(t){let{http:e,storage:r,onUserUpdate:n}=t;return {async getMe(){let a=r.getItem("amaster_access_token");if(!a)return {data:null,error:{message:"Not authenticated",status:401},status:401};let l=await e.request({url:"/api/auth/me",method:"get",headers:{Authorization:`Bearer ${a}`}});return l.data&&n(l.data),l},async updateMe(a){let l=r.getItem("amaster_access_token");if(!l)return {data:null,error:{message:"Not authenticated",status:401},status:401};let m=await e.request({url:"/api/auth/me",method:"put",headers:{Authorization:`Bearer ${l}`,"Content-Type":"application/json"},data:a});return m.data&&n(m.data),m},async changePassword(a){let l=r.getItem("amaster_access_token");return l?e.request({url:"/api/auth/change-password",method:"post",headers:{Authorization:`Bearer ${l}`,"Content-Type":"application/json"},data:a}):{data:null,error:{message:"Not authenticated",status:401},status:401}}}}function H(t){let{http:e,storage:r}=t;return {async getOAuthBindings(){let n=r.getItem("amaster_access_token");return n?e.request({url:"/api/auth/oauth-bindings",method:"get",headers:{Authorization:`Bearer ${n}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}},bindOAuth(n){if(typeof window>"u"){console.error("[AuthClient] OAuth binding is only available in browser environment");return}window.location.href=`/api/auth/oauth/${n}/bind`;},async unbindOAuth(n){let a=r.getItem("amaster_access_token");return a?e.request({url:`/api/auth/oauth/${n}/unbind`,method:"delete",headers:{Authorization:`Bearer ${a}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}}}}function $(t){let{http:e,storage:r}=t;return {async getSession(){let n=r.getItem("amaster_access_token");return n?e.request({url:"/api/auth/sessions/current",method:"get",headers:{Authorization:`Bearer ${n}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}},async getSessions(){let n=r.getItem("amaster_access_token");return n?e.request({url:"/api/auth/sessions",method:"get",headers:{Authorization:`Bearer ${n}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}},async revokeSession(n){let a=r.getItem("amaster_access_token");return a?n?e.request({url:`/api/auth/sessions/${n}`,method:"delete",headers:{Authorization:`Bearer ${a}`}}):{data:null,error:{message:"Session ID is required",status:400},status:400}:{data:null,error:{message:"Not authenticated",status:401},status:401}},async revokeAllSessions(){let n=r.getItem("amaster_access_token");return n?e.request({url:"/api/auth/sessions",method:"delete",headers:{Authorization:`Bearer ${n}`}}):{data:null,error:{message:"Not authenticated",status:401},status:401}}}}function le(t={},e){let{baseURL:r,headers:n,onTokenExpired:a,onUnauthorized:l,autoHandleOAuthCallback:m=true,autoRedirectAfterLogin:s=true,runtime:i}=t;i&&httpClient.setMiniProgramRuntime(i);let c=e||httpClient.createHttpClient({...M,baseURL:r,headers:n,runtime:i}),p=300,d=O(),y=new A,C=new w,P=null;try{let u=d.getItem(g.USER);u&&(P=JSON.parse(u));}catch(u){console.error("[AuthClient] Failed to load user from storage:",u);}let f;C.setRefreshCallback(async()=>{let u=await f.refreshToken();u.data?(await f.getMe(),y.emit("tokenRefreshed",u.data.accessToken)):(y.emit("tokenExpired"),a?.());});function N(u,h){d.setItem(g.ACCESS_TOKEN,h),d.setItem(g.USER,JSON.stringify(u)),P=u,C.scheduleRefreshFromToken(h,p),y.emit("login",u);}function q(u){P=u,d.setItem(g.USER,JSON.stringify(u));}function B(){y.emit("logout");}function E(){d.clear(),P=null,C.clearSchedule();}function F(){return P}let G=I({http:c,onLoginSuccess:N,onLogout:B,autoRedirectAfterLogin:s,storage:d,clearAuth:E}),z=_({getCurrentUser:F}),K=x({http:c,storage:d,onUserUpdate:q}),j=H({http:c,storage:d}),D=$({http:c,storage:d});if(f={...G,...z,...K,...j,...D,on(u,h){y.on(u,h);},off(u,h){y.off(u,h);},isAuthenticated(){return !!d.getItem(g.ACCESS_TOKEN)},getAccessToken(){return d.getItem(g.ACCESS_TOKEN)},setAccessToken(u){d.setItem(g.ACCESS_TOKEN,u),C.scheduleRefreshFromToken(u,p);},clearAuth:E},f.on("unauthorized",()=>{l?.();}),f.isAuthenticated()&&f.getMe().catch(u=>{console.warn("[AuthClient] Failed to sync user info on init:",u);}),m&&typeof window<"u"){let u=window.location.hash;u&&(u.includes("access_token")||u.includes("accessToken"))&&f.handleOAuthCallback().then(h=>{h.error&&console.error("[AuthClient] Auto OAuth callback failed:",h.error);}).catch(h=>{console.error("[AuthClient] Auto OAuth callback error:",h);});}return f}exports.createAuthClient=le;exports.defaultHttpClientOptions=M;exports.transformAmasterResponse=U;//# sourceMappingURL=index.cjs.map
2
2
  //# sourceMappingURL=index.cjs.map