@rixl/sdk 0.8.0 → 0.8.2

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,9 +2808,11 @@ 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();
2700
- if (token) request.headers.set("Authorization", `Bearer ${token}`);
2811
+ const { pathname } = new URL(request.url);
2812
+ if (isPublicRoute(request.method, pathname)) return request;
2813
+ const token = await tokenResolver();
2814
+ if (!token) throw new ApiError("No access token available for an authenticated request", HTTP_STATUS.UNAUTHORIZED, pathname);
2815
+ request.headers.set("Authorization", `Bearer ${token}`);
2701
2816
  return request;
2702
2817
  });
2703
2818
  client.interceptors.error.use((error, response, request) => {
@@ -3063,14 +3178,77 @@ const initSocials = async () => {
3063
3178
  }
3064
3179
  };
3065
3180
 
3181
+ //#endregion
3182
+ //#region src/platform/platformAuthStore.ts
3183
+ const platformAccessToken = atom(void 0);
3184
+ const platformRefreshToken = atom(void 0);
3185
+ const platformExpireAt = atom(0);
3186
+ let currentPlatformTokenPromise = null;
3187
+ const setPlatformTokens = (access, refresh, expiresIn) => {
3188
+ platformAccessToken.set(access);
3189
+ platformRefreshToken.set(refresh);
3190
+ platformExpireAt.set(Date.now() + expiresIn * 1e3);
3191
+ };
3192
+ const clearPlatformTokens = () => {
3193
+ platformAccessToken.set(void 0);
3194
+ platformRefreshToken.set(void 0);
3195
+ platformExpireAt.set(0);
3196
+ };
3197
+ const exchangeApiKey = async (apiKey) => {
3198
+ const { data } = await platformauthV1PlatformAuthServiceExchangeApiKey({
3199
+ body: { api_key: apiKey },
3200
+ throwOnError: true
3201
+ });
3202
+ if (!data.access_token || !data.refresh_token) throw new Error("Platform token exchange did not return tokens");
3203
+ setPlatformTokens(data.access_token, data.refresh_token, Number(data.expires_in ?? 0));
3204
+ };
3205
+ const refreshPlatformAccessToken = async (refresh) => {
3206
+ const { data } = await platformauthV1PlatformAuthServiceRefreshPlatformToken({
3207
+ body: { refresh_token: refresh },
3208
+ throwOnError: true
3209
+ });
3210
+ if (!data.access_token || !data.refresh_token) throw new Error("Platform token refresh did not return tokens");
3211
+ setPlatformTokens(data.access_token, data.refresh_token, Number(data.expires_in ?? 0));
3212
+ };
3213
+ const ensureValidPlatformToken = async (refresh) => {
3214
+ if (platformAccessToken.get() && !isTokenExpired(platformExpireAt.get())) return;
3215
+ try {
3216
+ await refreshPlatformAccessToken(refresh);
3217
+ } catch (refreshError) {
3218
+ console.error("Platform token refresh failed in getPlatformToken:", refreshError);
3219
+ clearPlatformTokens();
3220
+ throw refreshError;
3221
+ }
3222
+ };
3223
+ const getPlatformToken = async () => {
3224
+ if (currentPlatformTokenPromise) return currentPlatformTokenPromise;
3225
+ const currentRefreshToken = platformRefreshToken.get();
3226
+ if (!currentRefreshToken) return void 0;
3227
+ currentPlatformTokenPromise = (async () => {
3228
+ try {
3229
+ await ensureValidPlatformToken(currentRefreshToken);
3230
+ return platformAccessToken.get();
3231
+ } finally {
3232
+ currentPlatformTokenPromise = null;
3233
+ }
3234
+ })();
3235
+ return currentPlatformTokenPromise;
3236
+ };
3237
+
3066
3238
  //#endregion
3067
3239
  //#region src/connect.ts
3068
3240
  const connect = async (config) => {
3241
+ apiURL.set(config.baseUrl);
3069
3242
  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
- });
3243
+ if (config.apiKey) {
3244
+ await exchangeApiKey(config.apiKey);
3245
+ setTokenResolver(getPlatformToken);
3246
+ configureSdkClient();
3247
+ }
3248
+ if (config.token) {
3249
+ setTokenResolver(async () => config.token);
3250
+ configureSdkClient();
3251
+ }
3074
3252
  if (config.auth) return initClient({
3075
3253
  apiUrl: config.baseUrl,
3076
3254
  loginRedirectUrl: config.auth.loginRedirectUrl,