@rixl/sdk 0.8.0 → 0.8.1

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.d.ts CHANGED
@@ -11713,6 +11713,7 @@ interface AuthConfig {
11713
11713
  interface ConnectConfig {
11714
11714
  baseUrl: string;
11715
11715
  apiKey?: string;
11716
+ token?: string;
11716
11717
  auth?: AuthConfig;
11717
11718
  }
11718
11719
  declare const connect: (config: ConnectConfig) => Promise<string | undefined>;
package/dist/index.js CHANGED
@@ -2686,6 +2686,119 @@ function isWireErrorBody(error) {
2686
2686
  return typeof error === "object" && error !== null;
2687
2687
  }
2688
2688
  let configured = false;
2689
+ let tokenResolver = getToken;
2690
+ function setTokenResolver(resolver) {
2691
+ tokenResolver = resolver;
2692
+ }
2693
+ /**
2694
+ * Routes that do not require a Bearer token at the gateway edge. These
2695
+ * authenticate via credentials in the request body (or are webhooks verified by
2696
+ * signature), so attaching an Authorization header here would make the gateway
2697
+ * attempt to validate a stale/absent token and reject the request with 401.
2698
+ * Mirrors `publicRoutes` in backend/gateway/internal/routes/routes.go.
2699
+ */
2700
+ const publicRoutes = [
2701
+ {
2702
+ method: "POST",
2703
+ path: "/auth/v1/token"
2704
+ },
2705
+ {
2706
+ method: "POST",
2707
+ path: "/auth/v1/register"
2708
+ },
2709
+ {
2710
+ method: "POST",
2711
+ path: "/auth/v1/login"
2712
+ },
2713
+ {
2714
+ method: "POST",
2715
+ path: "/auth/v1/email/verify"
2716
+ },
2717
+ {
2718
+ method: "POST",
2719
+ path: "/auth/v1/email/verify/resend"
2720
+ },
2721
+ {
2722
+ method: "POST",
2723
+ path: "/auth/v1/password/reset"
2724
+ },
2725
+ {
2726
+ method: "POST",
2727
+ path: "/auth/v1/password/reset/confirm"
2728
+ },
2729
+ {
2730
+ method: "POST",
2731
+ path: "/auth/v1/verify-totp"
2732
+ },
2733
+ {
2734
+ method: "POST",
2735
+ path: "/auth/v1/verify-passkey"
2736
+ },
2737
+ {
2738
+ method: "POST",
2739
+ path: "/auth/v1/invitations/",
2740
+ prefix: true
2741
+ },
2742
+ {
2743
+ method: "POST",
2744
+ path: "/auth/v1/passkey/login/begin"
2745
+ },
2746
+ {
2747
+ method: "POST",
2748
+ path: "/auth/v1/passkey/login/finish"
2749
+ },
2750
+ {
2751
+ method: "POST",
2752
+ path: "/auth/v1/logout"
2753
+ },
2754
+ {
2755
+ method: "POST",
2756
+ path: "/auth/v1/blog/unsubscribe/email"
2757
+ },
2758
+ {
2759
+ method: "POST",
2760
+ path: "/auth/v1/blog/broadcast"
2761
+ },
2762
+ {
2763
+ method: "GET",
2764
+ path: "/media/v1/videos/",
2765
+ prefix: true
2766
+ },
2767
+ {
2768
+ method: "GET",
2769
+ path: "/media/v1/images/",
2770
+ prefix: true
2771
+ },
2772
+ {
2773
+ method: "GET",
2774
+ path: "/media/v1/languages"
2775
+ },
2776
+ {
2777
+ method: "GET",
2778
+ path: "/posts/v1/feeds/",
2779
+ prefix: true
2780
+ },
2781
+ {
2782
+ method: "POST",
2783
+ path: "/billing/webhooks/stripe"
2784
+ },
2785
+ {
2786
+ method: "POST",
2787
+ path: "/webhooks/storage"
2788
+ },
2789
+ {
2790
+ method: "POST",
2791
+ path: "/platform/auth/v1/token"
2792
+ },
2793
+ {
2794
+ method: "POST",
2795
+ path: "/platform/auth/v1/refresh"
2796
+ }
2797
+ ];
2798
+ function isPublicRoute(method, pathname) {
2799
+ const match = method.toUpperCase();
2800
+ return publicRoutes.some(({ method: m, path, prefix }) => match === m && (prefix ? pathname.startsWith(path) : pathname === path));
2801
+ }
2689
2802
  function configureSdkClient() {
2690
2803
  if (configured) return;
2691
2804
  configured = true;
@@ -2695,8 +2808,8 @@ function configureSdkClient() {
2695
2808
  });
2696
2809
  client.interceptors.request.use(async (request) => {
2697
2810
  if (request.headers.has("Authorization")) return request;
2698
- if (new URL(request.url).pathname.endsWith("/auth/v1/token")) return request;
2699
- const token = await getToken();
2811
+ if (isPublicRoute(request.method, new URL(request.url).pathname)) return request;
2812
+ const token = await tokenResolver();
2700
2813
  if (token) request.headers.set("Authorization", `Bearer ${token}`);
2701
2814
  return request;
2702
2815
  });
@@ -3063,14 +3176,77 @@ const initSocials = async () => {
3063
3176
  }
3064
3177
  };
3065
3178
 
3179
+ //#endregion
3180
+ //#region src/platform/platformAuthStore.ts
3181
+ const platformAccessToken = atom(void 0);
3182
+ const platformRefreshToken = atom(void 0);
3183
+ const platformExpireAt = atom(0);
3184
+ let currentPlatformTokenPromise = null;
3185
+ const setPlatformTokens = (access, refresh, expiresIn) => {
3186
+ platformAccessToken.set(access);
3187
+ platformRefreshToken.set(refresh);
3188
+ platformExpireAt.set(Date.now() + expiresIn * 1e3);
3189
+ };
3190
+ const clearPlatformTokens = () => {
3191
+ platformAccessToken.set(void 0);
3192
+ platformRefreshToken.set(void 0);
3193
+ platformExpireAt.set(0);
3194
+ };
3195
+ const exchangeApiKey = async (apiKey) => {
3196
+ const { data } = await platformauthV1PlatformAuthServiceExchangeApiKey({
3197
+ body: { api_key: apiKey },
3198
+ throwOnError: true
3199
+ });
3200
+ if (!data.access_token || !data.refresh_token) throw new Error("Platform token exchange did not return tokens");
3201
+ setPlatformTokens(data.access_token, data.refresh_token, Number(data.expires_in ?? 0));
3202
+ };
3203
+ const refreshPlatformAccessToken = async (refresh) => {
3204
+ const { data } = await platformauthV1PlatformAuthServiceRefreshPlatformToken({
3205
+ body: { refresh_token: refresh },
3206
+ throwOnError: true
3207
+ });
3208
+ if (!data.access_token || !data.refresh_token) throw new Error("Platform token refresh did not return tokens");
3209
+ setPlatformTokens(data.access_token, data.refresh_token, Number(data.expires_in ?? 0));
3210
+ };
3211
+ const ensureValidPlatformToken = async (refresh) => {
3212
+ if (platformAccessToken.get() && !isTokenExpired(platformExpireAt.get())) return;
3213
+ try {
3214
+ await refreshPlatformAccessToken(refresh);
3215
+ } catch (refreshError) {
3216
+ console.error("Platform token refresh failed in getPlatformToken:", refreshError);
3217
+ clearPlatformTokens();
3218
+ throw refreshError;
3219
+ }
3220
+ };
3221
+ const getPlatformToken = async () => {
3222
+ if (currentPlatformTokenPromise) return currentPlatformTokenPromise;
3223
+ const currentRefreshToken = platformRefreshToken.get();
3224
+ if (!currentRefreshToken) return void 0;
3225
+ currentPlatformTokenPromise = (async () => {
3226
+ try {
3227
+ await ensureValidPlatformToken(currentRefreshToken);
3228
+ return platformAccessToken.get();
3229
+ } finally {
3230
+ currentPlatformTokenPromise = null;
3231
+ }
3232
+ })();
3233
+ return currentPlatformTokenPromise;
3234
+ };
3235
+
3066
3236
  //#endregion
3067
3237
  //#region src/connect.ts
3068
3238
  const connect = async (config) => {
3239
+ apiURL.set(config.baseUrl);
3069
3240
  client.setConfig({ baseUrl: config.baseUrl });
3070
- if (config.apiKey) client.interceptors.request.use(async (request) => {
3071
- request.headers.set("X-API-Key", config.apiKey);
3072
- return request;
3073
- });
3241
+ if (config.apiKey) {
3242
+ await exchangeApiKey(config.apiKey);
3243
+ setTokenResolver(getPlatformToken);
3244
+ configureSdkClient();
3245
+ }
3246
+ if (config.token) {
3247
+ setTokenResolver(async () => config.token);
3248
+ configureSdkClient();
3249
+ }
3074
3250
  if (config.auth) return initClient({
3075
3251
  apiUrl: config.baseUrl,
3076
3252
  loginRedirectUrl: config.auth.loginRedirectUrl,