@scalemule/nextjs 0.1.14 → 0.1.15

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/client.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { a8 as StorageAdapter } from './index-BIIUrnPr.mjs';
1
+ import { a8 as StorageAdapter } from './index-DTWyUcyd.mjs';
2
2
 
3
3
  /**
4
4
  * ScaleMule API Client
package/dist/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a8 as StorageAdapter } from './index-BIIUrnPr.js';
1
+ import { a8 as StorageAdapter } from './index-DTWyUcyd.js';
2
2
 
3
3
  /**
4
4
  * ScaleMule API Client
package/dist/client.js CHANGED
@@ -2,11 +2,12 @@
2
2
 
3
3
  // src/types/index.ts
4
4
  var ScaleMuleApiError = class extends Error {
5
- constructor(error) {
5
+ constructor(error, status) {
6
6
  super(error.message);
7
7
  this.name = "ScaleMuleApiError";
8
8
  this.code = error.code;
9
9
  this.field = error.field;
10
+ this.status = status;
10
11
  }
11
12
  };
12
13
 
package/dist/client.mjs CHANGED
@@ -1,10 +1,11 @@
1
1
  // src/types/index.ts
2
2
  var ScaleMuleApiError = class extends Error {
3
- constructor(error) {
3
+ constructor(error, status) {
4
4
  super(error.message);
5
5
  this.name = "ScaleMuleApiError";
6
6
  this.code = error.code;
7
7
  this.field = error.field;
8
+ this.status = status;
8
9
  }
9
10
  };
10
11
 
@@ -53,6 +53,27 @@ interface ScaleMuleConfig {
53
53
  * // Handle register, login, logout, etc. using ScaleMule server client
54
54
  */
55
55
  authProxyUrl?: string;
56
+ /**
57
+ * Endpoint to ship SDK error logs to (fire-and-forget POST).
58
+ *
59
+ * When set, every non-2xx response from the auth proxy (and any other
60
+ * SDK call that throws a ScaleMuleApiError) will be reported to this
61
+ * URL as a structured log entry, alongside the regular setError() and
62
+ * thrown ScaleMuleApiError. This makes API failures visible in your
63
+ * platform's error logger even when the calling code catches the
64
+ * error and surfaces a UI message — the case the global window.onerror
65
+ * / unhandledrejection / React error-boundary collectors all miss by
66
+ * design.
67
+ *
68
+ * Recommended value: '/api/telemetry/errors' (the same endpoint your
69
+ * host-app's client-side error collector already POSTs to). The body
70
+ * shape matches what `createTelemetryRoutes()` expects:
71
+ * `{ logs: [{ message, metadata, timestamp }] }`.
72
+ *
73
+ * @example
74
+ * telemetryEndpoint: '/api/telemetry/errors'
75
+ */
76
+ telemetryEndpoint?: string;
56
77
  /**
57
78
  * Publishable API key for browser-safe operations (e.g., analytics)
58
79
  *
@@ -100,7 +121,7 @@ declare class ScaleMuleApiError extends Error {
100
121
  status?: number;
101
122
  field?: string;
102
123
  details?: unknown;
103
- constructor(error: ApiError);
124
+ constructor(error: ApiError, status?: number);
104
125
  }
105
126
  interface ApiResponse<T> {
106
127
  success: boolean;
@@ -53,6 +53,27 @@ interface ScaleMuleConfig {
53
53
  * // Handle register, login, logout, etc. using ScaleMule server client
54
54
  */
55
55
  authProxyUrl?: string;
56
+ /**
57
+ * Endpoint to ship SDK error logs to (fire-and-forget POST).
58
+ *
59
+ * When set, every non-2xx response from the auth proxy (and any other
60
+ * SDK call that throws a ScaleMuleApiError) will be reported to this
61
+ * URL as a structured log entry, alongside the regular setError() and
62
+ * thrown ScaleMuleApiError. This makes API failures visible in your
63
+ * platform's error logger even when the calling code catches the
64
+ * error and surfaces a UI message — the case the global window.onerror
65
+ * / unhandledrejection / React error-boundary collectors all miss by
66
+ * design.
67
+ *
68
+ * Recommended value: '/api/telemetry/errors' (the same endpoint your
69
+ * host-app's client-side error collector already POSTs to). The body
70
+ * shape matches what `createTelemetryRoutes()` expects:
71
+ * `{ logs: [{ message, metadata, timestamp }] }`.
72
+ *
73
+ * @example
74
+ * telemetryEndpoint: '/api/telemetry/errors'
75
+ */
76
+ telemetryEndpoint?: string;
56
77
  /**
57
78
  * Publishable API key for browser-safe operations (e.g., analytics)
58
79
  *
@@ -100,7 +121,7 @@ declare class ScaleMuleApiError extends Error {
100
121
  status?: number;
101
122
  field?: string;
102
123
  details?: unknown;
103
- constructor(error: ApiError);
124
+ constructor(error: ApiError, status?: number);
104
125
  }
105
126
  interface ApiResponse<T> {
106
127
  success: boolean;
package/dist/index.d.mts CHANGED
@@ -6,8 +6,8 @@ import { MoneyClient } from '@scalemule/money';
6
6
  export { MoneyClient, MoneyClientConfig, createMoneyClient } from '@scalemule/money';
7
7
  import { ScaleMuleClient } from './client.mjs';
8
8
  export { ClientConfig, RequestOptions, createClient } from './client.mjs';
9
- import { S as ScaleMuleConfig, U as User, L as LoginResponse, A as ApiError$1, a as UseAuthReturn, b as UseBillingReturn, c as ListFilesParams, d as UseContentReturn, e as UseUserReturn, f as UseAnalyticsOptions, g as UseAnalyticsReturn } from './index-BIIUrnPr.mjs';
10
- export { h as AccountBalance, i as AnalyticsEvent, j as ApiResponse, B as BatchTrackRequest, k as BillingPayment, l as BillingPayout, m as BillingRefund, n as BillingTransaction, C as ChangeEmailRequest, o as ChangePasswordRequest, p as ClientContext, q as ConnectedAccount, D as DeviceFingerprint, r as DeviceInfo, E as EnhancedAnalyticsEvent, F as ForgotPasswordRequest, K as KnownAccountInfo, s as LinkedAccount, t as ListFilesResponse, u as LoginDeviceInfo, v as LoginRequest, w as LoginResponseWithMFA, x as LoginRiskInfo, M as MFAChallengeResponse, y as MFAMethod, z as MFASMSSetupResponse, G as MFASetupRequest, H as MFAStatus, I as MFATOTPSetupResponse, J as MFAVerifyRequest, O as OAuthCallbackRequest, N as OAuthCallbackResponse, P as OAuthConfig, Q as OAuthProvider, R as OAuthStartResponse, T as PageViewData, V as PayoutSchedule, W as PhoneLoginRequest, X as PhoneSendCodeRequest, Y as PhoneVerifyRequest, Z as Profile, _ as RefreshResponse, $ as RegisterRequest, a0 as ResetPasswordRequest, a1 as ScaleMuleApiError, a2 as ScaleMuleEnvironment, a3 as Session, a4 as SignedUploadCompleteRequest, a5 as SignedUploadRequest, a6 as SignedUploadResponse, a7 as SignedUploadUrl, a8 as StorageAdapter, a9 as StorageFile, aa as TrackEventResponse, ab as TransactionSummary, ac as UTMParams, ad as UpdateProfileRequest, ae as UploadOptions, af as UploadResponse, ag as VerifyEmailRequest } from './index-BIIUrnPr.mjs';
9
+ import { S as ScaleMuleConfig, U as User, L as LoginResponse, A as ApiError$1, a as UseAuthReturn, b as UseBillingReturn, c as ListFilesParams, d as UseContentReturn, e as UseUserReturn, f as UseAnalyticsOptions, g as UseAnalyticsReturn } from './index-DTWyUcyd.mjs';
10
+ export { h as AccountBalance, i as AnalyticsEvent, j as ApiResponse, B as BatchTrackRequest, k as BillingPayment, l as BillingPayout, m as BillingRefund, n as BillingTransaction, C as ChangeEmailRequest, o as ChangePasswordRequest, p as ClientContext, q as ConnectedAccount, D as DeviceFingerprint, r as DeviceInfo, E as EnhancedAnalyticsEvent, F as ForgotPasswordRequest, K as KnownAccountInfo, s as LinkedAccount, t as ListFilesResponse, u as LoginDeviceInfo, v as LoginRequest, w as LoginResponseWithMFA, x as LoginRiskInfo, M as MFAChallengeResponse, y as MFAMethod, z as MFASMSSetupResponse, G as MFASetupRequest, H as MFAStatus, I as MFATOTPSetupResponse, J as MFAVerifyRequest, O as OAuthCallbackRequest, N as OAuthCallbackResponse, P as OAuthConfig, Q as OAuthProvider, R as OAuthStartResponse, T as PageViewData, V as PayoutSchedule, W as PhoneLoginRequest, X as PhoneSendCodeRequest, Y as PhoneVerifyRequest, Z as Profile, _ as RefreshResponse, $ as RegisterRequest, a0 as ResetPasswordRequest, a1 as ScaleMuleApiError, a2 as ScaleMuleEnvironment, a3 as Session, a4 as SignedUploadCompleteRequest, a5 as SignedUploadRequest, a6 as SignedUploadResponse, a7 as SignedUploadUrl, a8 as StorageAdapter, a9 as StorageFile, aa as TrackEventResponse, ab as TransactionSummary, ac as UTMParams, ad as UpdateProfileRequest, ae as UploadOptions, af as UploadResponse, ag as VerifyEmailRequest } from './index-DTWyUcyd.mjs';
11
11
 
12
12
  /**
13
13
  * Result of a single {@link useMedia} upload call.
@@ -226,7 +226,7 @@ interface ScaleMuleProviderProps extends ScaleMuleConfig {
226
226
  */
227
227
  mediaPolicy?: MediaPolicy;
228
228
  }
229
- declare function ScaleMuleProvider({ apiKey, applicationId, environment, gatewayUrl, debug, storage, analyticsProxyUrl, authProxyUrl, publishableKey, enableAccountSwitcher, accountSwitcherPrivacy, children, onLogin, onLogout, onAuthError, bootstrapFlags, mediaPolicy, }: ScaleMuleProviderProps): react_jsx_runtime.JSX.Element;
229
+ declare function ScaleMuleProvider({ apiKey, applicationId, environment, gatewayUrl, debug, storage, analyticsProxyUrl, authProxyUrl, telemetryEndpoint, publishableKey, enableAccountSwitcher, accountSwitcherPrivacy, children, onLogin, onLogout, onAuthError, bootstrapFlags, mediaPolicy, }: ScaleMuleProviderProps): react_jsx_runtime.JSX.Element;
230
230
  declare function useScaleMule(): ScaleMuleContextValue;
231
231
  declare function useScaleMuleClient(): ScaleMuleClient;
232
232
  declare function useMoneyClient(): MoneyClient;
package/dist/index.d.ts CHANGED
@@ -6,8 +6,8 @@ import { MoneyClient } from '@scalemule/money';
6
6
  export { MoneyClient, MoneyClientConfig, createMoneyClient } from '@scalemule/money';
7
7
  import { ScaleMuleClient } from './client.js';
8
8
  export { ClientConfig, RequestOptions, createClient } from './client.js';
9
- import { S as ScaleMuleConfig, U as User, L as LoginResponse, A as ApiError$1, a as UseAuthReturn, b as UseBillingReturn, c as ListFilesParams, d as UseContentReturn, e as UseUserReturn, f as UseAnalyticsOptions, g as UseAnalyticsReturn } from './index-BIIUrnPr.js';
10
- export { h as AccountBalance, i as AnalyticsEvent, j as ApiResponse, B as BatchTrackRequest, k as BillingPayment, l as BillingPayout, m as BillingRefund, n as BillingTransaction, C as ChangeEmailRequest, o as ChangePasswordRequest, p as ClientContext, q as ConnectedAccount, D as DeviceFingerprint, r as DeviceInfo, E as EnhancedAnalyticsEvent, F as ForgotPasswordRequest, K as KnownAccountInfo, s as LinkedAccount, t as ListFilesResponse, u as LoginDeviceInfo, v as LoginRequest, w as LoginResponseWithMFA, x as LoginRiskInfo, M as MFAChallengeResponse, y as MFAMethod, z as MFASMSSetupResponse, G as MFASetupRequest, H as MFAStatus, I as MFATOTPSetupResponse, J as MFAVerifyRequest, O as OAuthCallbackRequest, N as OAuthCallbackResponse, P as OAuthConfig, Q as OAuthProvider, R as OAuthStartResponse, T as PageViewData, V as PayoutSchedule, W as PhoneLoginRequest, X as PhoneSendCodeRequest, Y as PhoneVerifyRequest, Z as Profile, _ as RefreshResponse, $ as RegisterRequest, a0 as ResetPasswordRequest, a1 as ScaleMuleApiError, a2 as ScaleMuleEnvironment, a3 as Session, a4 as SignedUploadCompleteRequest, a5 as SignedUploadRequest, a6 as SignedUploadResponse, a7 as SignedUploadUrl, a8 as StorageAdapter, a9 as StorageFile, aa as TrackEventResponse, ab as TransactionSummary, ac as UTMParams, ad as UpdateProfileRequest, ae as UploadOptions, af as UploadResponse, ag as VerifyEmailRequest } from './index-BIIUrnPr.js';
9
+ import { S as ScaleMuleConfig, U as User, L as LoginResponse, A as ApiError$1, a as UseAuthReturn, b as UseBillingReturn, c as ListFilesParams, d as UseContentReturn, e as UseUserReturn, f as UseAnalyticsOptions, g as UseAnalyticsReturn } from './index-DTWyUcyd.js';
10
+ export { h as AccountBalance, i as AnalyticsEvent, j as ApiResponse, B as BatchTrackRequest, k as BillingPayment, l as BillingPayout, m as BillingRefund, n as BillingTransaction, C as ChangeEmailRequest, o as ChangePasswordRequest, p as ClientContext, q as ConnectedAccount, D as DeviceFingerprint, r as DeviceInfo, E as EnhancedAnalyticsEvent, F as ForgotPasswordRequest, K as KnownAccountInfo, s as LinkedAccount, t as ListFilesResponse, u as LoginDeviceInfo, v as LoginRequest, w as LoginResponseWithMFA, x as LoginRiskInfo, M as MFAChallengeResponse, y as MFAMethod, z as MFASMSSetupResponse, G as MFASetupRequest, H as MFAStatus, I as MFATOTPSetupResponse, J as MFAVerifyRequest, O as OAuthCallbackRequest, N as OAuthCallbackResponse, P as OAuthConfig, Q as OAuthProvider, R as OAuthStartResponse, T as PageViewData, V as PayoutSchedule, W as PhoneLoginRequest, X as PhoneSendCodeRequest, Y as PhoneVerifyRequest, Z as Profile, _ as RefreshResponse, $ as RegisterRequest, a0 as ResetPasswordRequest, a1 as ScaleMuleApiError, a2 as ScaleMuleEnvironment, a3 as Session, a4 as SignedUploadCompleteRequest, a5 as SignedUploadRequest, a6 as SignedUploadResponse, a7 as SignedUploadUrl, a8 as StorageAdapter, a9 as StorageFile, aa as TrackEventResponse, ab as TransactionSummary, ac as UTMParams, ad as UpdateProfileRequest, ae as UploadOptions, af as UploadResponse, ag as VerifyEmailRequest } from './index-DTWyUcyd.js';
11
11
 
12
12
  /**
13
13
  * Result of a single {@link useMedia} upload call.
@@ -226,7 +226,7 @@ interface ScaleMuleProviderProps extends ScaleMuleConfig {
226
226
  */
227
227
  mediaPolicy?: MediaPolicy;
228
228
  }
229
- declare function ScaleMuleProvider({ apiKey, applicationId, environment, gatewayUrl, debug, storage, analyticsProxyUrl, authProxyUrl, publishableKey, enableAccountSwitcher, accountSwitcherPrivacy, children, onLogin, onLogout, onAuthError, bootstrapFlags, mediaPolicy, }: ScaleMuleProviderProps): react_jsx_runtime.JSX.Element;
229
+ declare function ScaleMuleProvider({ apiKey, applicationId, environment, gatewayUrl, debug, storage, analyticsProxyUrl, authProxyUrl, telemetryEndpoint, publishableKey, enableAccountSwitcher, accountSwitcherPrivacy, children, onLogin, onLogout, onAuthError, bootstrapFlags, mediaPolicy, }: ScaleMuleProviderProps): react_jsx_runtime.JSX.Element;
230
230
  declare function useScaleMule(): ScaleMuleContextValue;
231
231
  declare function useScaleMuleClient(): ScaleMuleClient;
232
232
  declare function useMoneyClient(): MoneyClient;
package/dist/index.js CHANGED
@@ -4886,16 +4886,16 @@ var WebPushManager = class {
4886
4886
  userVisibleOnly: true,
4887
4887
  applicationServerKey: applicationServerKey.buffer
4888
4888
  });
4889
- const endpoint = pushSubscription.endpoint;
4889
+ const endpoint2 = pushSubscription.endpoint;
4890
4890
  const p256dh = arrayBufferToBase64url(pushSubscription.getKey("p256dh"));
4891
4891
  const auth = arrayBufferToBase64url(pushSubscription.getKey("auth"));
4892
4892
  const subscription = {
4893
- endpoint,
4893
+ endpoint: endpoint2,
4894
4894
  keys: { p256dh, auth }
4895
4895
  };
4896
4896
  const resolvedDeviceId = deviceId || this.state?.deviceId || generateDeviceId();
4897
4897
  const result = await this.fetcher.registerToken({
4898
- token: endpoint,
4898
+ token: endpoint2,
4899
4899
  platform: "web",
4900
4900
  device_id: resolvedDeviceId,
4901
4901
  subscription,
@@ -4907,12 +4907,12 @@ var WebPushManager = class {
4907
4907
  registration_source: this.registrationSource
4908
4908
  });
4909
4909
  this.state = {
4910
- endpoint,
4910
+ endpoint: endpoint2,
4911
4911
  tokenId: result.id,
4912
4912
  deviceId: resolvedDeviceId
4913
4913
  };
4914
4914
  this.persistState();
4915
- return { tokenId: result.id, endpoint };
4915
+ return { tokenId: result.id, endpoint: endpoint2 };
4916
4916
  }
4917
4917
  /** Unsubscribe from browser push and deregister token */
4918
4918
  async unsubscribe() {
@@ -6747,11 +6747,12 @@ var ScaleMule = class {
6747
6747
 
6748
6748
  // src/types/index.ts
6749
6749
  var ScaleMuleApiError = class extends Error {
6750
- constructor(error) {
6750
+ constructor(error, status) {
6751
6751
  super(error.message);
6752
6752
  this.name = "ScaleMuleApiError";
6753
6753
  this.code = error.code;
6754
6754
  this.field = error.field;
6755
+ this.status = status;
6755
6756
  }
6756
6757
  };
6757
6758
 
@@ -7522,6 +7523,45 @@ var ScaleMuleClient2 = class {
7522
7523
  function createClient(config) {
7523
7524
  return new ScaleMuleClient2(config);
7524
7525
  }
7526
+
7527
+ // src/sdk-telemetry.ts
7528
+ var endpoint;
7529
+ function setSdkTelemetryEndpoint(url) {
7530
+ endpoint = url;
7531
+ }
7532
+ function reportSdkError(payload) {
7533
+ if (!endpoint) return;
7534
+ if (typeof fetch === "undefined") return;
7535
+ const body = JSON.stringify({
7536
+ logs: [
7537
+ {
7538
+ message: `${payload.code}: ${payload.message}`,
7539
+ metadata: {
7540
+ name: payload.code,
7541
+ source: "scalemule-sdk",
7542
+ kind: "sdk",
7543
+ op: payload.op,
7544
+ status: payload.status ?? null,
7545
+ path: payload.path ?? null,
7546
+ field: payload.field ?? null,
7547
+ route: typeof window !== "undefined" ? window.location.pathname : null
7548
+ },
7549
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
7550
+ }
7551
+ ]
7552
+ });
7553
+ try {
7554
+ void fetch(endpoint, {
7555
+ method: "POST",
7556
+ headers: { "Content-Type": "application/json" },
7557
+ body,
7558
+ keepalive: true,
7559
+ credentials: "same-origin"
7560
+ }).catch(() => {
7561
+ });
7562
+ } catch {
7563
+ }
7564
+ }
7525
7565
  var USER_CACHE_KEY = "scalemule_user";
7526
7566
  function getCachedUser() {
7527
7567
  if (typeof window === "undefined") return null;
@@ -7553,6 +7593,7 @@ function ScaleMuleProvider({
7553
7593
  storage,
7554
7594
  analyticsProxyUrl,
7555
7595
  authProxyUrl,
7596
+ telemetryEndpoint,
7556
7597
  publishableKey,
7557
7598
  enableAccountSwitcher,
7558
7599
  accountSwitcherPrivacy,
@@ -7566,6 +7607,10 @@ function ScaleMuleProvider({
7566
7607
  const [user, setUser] = React.useState(null);
7567
7608
  const [initializing, setInitializing] = React.useState(true);
7568
7609
  const [error, setError] = React.useState(null);
7610
+ React.useEffect(() => {
7611
+ setSdkTelemetryEndpoint(telemetryEndpoint);
7612
+ return () => setSdkTelemetryEndpoint(void 0);
7613
+ }, [telemetryEndpoint]);
7569
7614
  const resolvedGatewayUrl = gatewayUrl || (environment === "dev" ? "https://api-dev.scalemule.com" : "https://api.scalemule.com");
7570
7615
  const client = React.useMemo(
7571
7616
  () => createClient({
@@ -7659,8 +7704,12 @@ function ScaleMuleProvider({
7659
7704
  }
7660
7705
  }
7661
7706
  } catch {
7662
- if (mounted && debug) {
7663
- console.debug("[ScaleMule] Auth proxy session check failed");
7707
+ if (mounted) {
7708
+ setUser(null);
7709
+ setCachedUser(null);
7710
+ if (debug) {
7711
+ console.debug("[ScaleMule] Auth proxy session check failed; clearing cached user");
7712
+ }
7664
7713
  }
7665
7714
  } finally {
7666
7715
  client.resolveSessionPending();
@@ -7819,6 +7868,19 @@ async function proxyFetch(proxyUrl, path, options = {}) {
7819
7868
  // Include cookies for session management
7820
7869
  });
7821
7870
  const data = await response.json();
7871
+ if (data && data.error && !(data.error instanceof ScaleMuleApiError)) {
7872
+ data.error = new ScaleMuleApiError(data.error, response.status);
7873
+ }
7874
+ if (data && data.success === false && data.error) {
7875
+ reportSdkError({
7876
+ code: data.error.code,
7877
+ message: data.error.message,
7878
+ status: response.status,
7879
+ op: path,
7880
+ path: `${proxyUrl}/${path}`,
7881
+ field: data.error.field
7882
+ });
7883
+ }
7822
7884
  return data;
7823
7885
  }
7824
7886
  function useAuth() {
@@ -10141,8 +10203,8 @@ function useAnalytics(options = {}) {
10141
10203
  return { tracked: 1, session_id: sessionIdRef.current || void 0 };
10142
10204
  }
10143
10205
  if (publishableKey && gatewayUrl) {
10144
- const endpoint2 = useV2 ? "/v1/analytics/v2/events" : "/v1/analytics/events";
10145
- fetch(`${gatewayUrl}${endpoint2}`, {
10206
+ const endpoint3 = useV2 ? "/v1/analytics/v2/events" : "/v1/analytics/events";
10207
+ fetch(`${gatewayUrl}${endpoint3}`, {
10146
10208
  method: "POST",
10147
10209
  headers: {
10148
10210
  "Content-Type": "application/json",
@@ -10155,8 +10217,8 @@ function useAnalytics(options = {}) {
10155
10217
  });
10156
10218
  return { tracked: 1, session_id: sessionIdRef.current || void 0 };
10157
10219
  }
10158
- const endpoint = useV2 ? "/v1/analytics/v2/events" : "/v1/analytics/events";
10159
- return await client.post(endpoint, fullEvent);
10220
+ const endpoint2 = useV2 ? "/v1/analytics/v2/events" : "/v1/analytics/events";
10221
+ return await client.post(endpoint2, fullEvent);
10160
10222
  },
10161
10223
  // Note: sessionId removed - we use ref to keep this stable
10162
10224
  [client, buildFullEvent, useV2, analyticsProxyUrl, publishableKey, gatewayUrl]
@@ -10232,8 +10294,8 @@ function useAnalytics(options = {}) {
10232
10294
  return { tracked: events.length, session_id: sessionIdRef.current || void 0 };
10233
10295
  }
10234
10296
  if (publishableKey && gatewayUrl) {
10235
- const endpoint2 = useV2 ? "/v1/analytics/v2/events/batch" : "/v1/analytics/events/batch";
10236
- fetch(`${gatewayUrl}${endpoint2}`, {
10297
+ const endpoint3 = useV2 ? "/v1/analytics/v2/events/batch" : "/v1/analytics/events/batch";
10298
+ fetch(`${gatewayUrl}${endpoint3}`, {
10237
10299
  method: "POST",
10238
10300
  headers: {
10239
10301
  "Content-Type": "application/json",
@@ -10247,8 +10309,8 @@ function useAnalytics(options = {}) {
10247
10309
  setLoading(false);
10248
10310
  return { tracked: events.length, session_id: sessionIdRef.current || void 0 };
10249
10311
  }
10250
- const endpoint = useV2 ? "/v1/analytics/v2/events/batch" : "/v1/analytics/events/batch";
10251
- return await client.post(endpoint, {
10312
+ const endpoint2 = useV2 ? "/v1/analytics/v2/events/batch" : "/v1/analytics/events/batch";
10313
+ return await client.post(endpoint2, {
10252
10314
  events: fullEvents
10253
10315
  });
10254
10316
  } finally {
@@ -10384,10 +10446,10 @@ function useFeatureFlags(options = {}) {
10384
10446
  try {
10385
10447
  const currentKeys = keysRef.current;
10386
10448
  const payload = currentKeys && currentKeys.length > 0 ? { flag_keys: currentKeys, environment, context: contextRef.current } : { environment, context: contextRef.current };
10387
- const endpoint = currentKeys && currentKeys.length > 0 ? "/v1/flags/evaluate/batch" : "/v1/flags/evaluate/all";
10449
+ const endpoint2 = currentKeys && currentKeys.length > 0 ? "/v1/flags/evaluate/batch" : "/v1/flags/evaluate/all";
10388
10450
  let result;
10389
10451
  if (publishableKey && gatewayUrl) {
10390
- const response = await fetch(`${gatewayUrl}${endpoint}`, {
10452
+ const response = await fetch(`${gatewayUrl}${endpoint2}`, {
10391
10453
  method: "POST",
10392
10454
  headers: {
10393
10455
  "Content-Type": "application/json",
@@ -10401,7 +10463,7 @@ function useFeatureFlags(options = {}) {
10401
10463
  const json = await response.json();
10402
10464
  result = json.data || json || {};
10403
10465
  } else {
10404
- result = await client.post(endpoint, payload);
10466
+ result = await client.post(endpoint2, payload);
10405
10467
  }
10406
10468
  setFlags(result || {});
10407
10469
  setError(null);
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { createContext, useState, useMemo, useEffect, useCallback, useContext, useRef } from 'react';
2
+ import { createContext, useState, useEffect, useMemo, useCallback, useContext, useRef } from 'react';
3
3
  import { createMoneyClient } from '@scalemule/money';
4
4
  export { MoneyClient, createMoneyClient } from '@scalemule/money';
5
5
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
@@ -4866,16 +4866,16 @@ var WebPushManager = class {
4866
4866
  userVisibleOnly: true,
4867
4867
  applicationServerKey: applicationServerKey.buffer
4868
4868
  });
4869
- const endpoint = pushSubscription.endpoint;
4869
+ const endpoint2 = pushSubscription.endpoint;
4870
4870
  const p256dh = arrayBufferToBase64url(pushSubscription.getKey("p256dh"));
4871
4871
  const auth = arrayBufferToBase64url(pushSubscription.getKey("auth"));
4872
4872
  const subscription = {
4873
- endpoint,
4873
+ endpoint: endpoint2,
4874
4874
  keys: { p256dh, auth }
4875
4875
  };
4876
4876
  const resolvedDeviceId = deviceId || this.state?.deviceId || generateDeviceId();
4877
4877
  const result = await this.fetcher.registerToken({
4878
- token: endpoint,
4878
+ token: endpoint2,
4879
4879
  platform: "web",
4880
4880
  device_id: resolvedDeviceId,
4881
4881
  subscription,
@@ -4887,12 +4887,12 @@ var WebPushManager = class {
4887
4887
  registration_source: this.registrationSource
4888
4888
  });
4889
4889
  this.state = {
4890
- endpoint,
4890
+ endpoint: endpoint2,
4891
4891
  tokenId: result.id,
4892
4892
  deviceId: resolvedDeviceId
4893
4893
  };
4894
4894
  this.persistState();
4895
- return { tokenId: result.id, endpoint };
4895
+ return { tokenId: result.id, endpoint: endpoint2 };
4896
4896
  }
4897
4897
  /** Unsubscribe from browser push and deregister token */
4898
4898
  async unsubscribe() {
@@ -6727,11 +6727,12 @@ var ScaleMule = class {
6727
6727
 
6728
6728
  // src/types/index.ts
6729
6729
  var ScaleMuleApiError = class extends Error {
6730
- constructor(error) {
6730
+ constructor(error, status) {
6731
6731
  super(error.message);
6732
6732
  this.name = "ScaleMuleApiError";
6733
6733
  this.code = error.code;
6734
6734
  this.field = error.field;
6735
+ this.status = status;
6735
6736
  }
6736
6737
  };
6737
6738
 
@@ -7502,6 +7503,45 @@ var ScaleMuleClient2 = class {
7502
7503
  function createClient(config) {
7503
7504
  return new ScaleMuleClient2(config);
7504
7505
  }
7506
+
7507
+ // src/sdk-telemetry.ts
7508
+ var endpoint;
7509
+ function setSdkTelemetryEndpoint(url) {
7510
+ endpoint = url;
7511
+ }
7512
+ function reportSdkError(payload) {
7513
+ if (!endpoint) return;
7514
+ if (typeof fetch === "undefined") return;
7515
+ const body = JSON.stringify({
7516
+ logs: [
7517
+ {
7518
+ message: `${payload.code}: ${payload.message}`,
7519
+ metadata: {
7520
+ name: payload.code,
7521
+ source: "scalemule-sdk",
7522
+ kind: "sdk",
7523
+ op: payload.op,
7524
+ status: payload.status ?? null,
7525
+ path: payload.path ?? null,
7526
+ field: payload.field ?? null,
7527
+ route: typeof window !== "undefined" ? window.location.pathname : null
7528
+ },
7529
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
7530
+ }
7531
+ ]
7532
+ });
7533
+ try {
7534
+ void fetch(endpoint, {
7535
+ method: "POST",
7536
+ headers: { "Content-Type": "application/json" },
7537
+ body,
7538
+ keepalive: true,
7539
+ credentials: "same-origin"
7540
+ }).catch(() => {
7541
+ });
7542
+ } catch {
7543
+ }
7544
+ }
7505
7545
  var USER_CACHE_KEY = "scalemule_user";
7506
7546
  function getCachedUser() {
7507
7547
  if (typeof window === "undefined") return null;
@@ -7533,6 +7573,7 @@ function ScaleMuleProvider({
7533
7573
  storage,
7534
7574
  analyticsProxyUrl,
7535
7575
  authProxyUrl,
7576
+ telemetryEndpoint,
7536
7577
  publishableKey,
7537
7578
  enableAccountSwitcher,
7538
7579
  accountSwitcherPrivacy,
@@ -7546,6 +7587,10 @@ function ScaleMuleProvider({
7546
7587
  const [user, setUser] = useState(null);
7547
7588
  const [initializing, setInitializing] = useState(true);
7548
7589
  const [error, setError] = useState(null);
7590
+ useEffect(() => {
7591
+ setSdkTelemetryEndpoint(telemetryEndpoint);
7592
+ return () => setSdkTelemetryEndpoint(void 0);
7593
+ }, [telemetryEndpoint]);
7549
7594
  const resolvedGatewayUrl = gatewayUrl || (environment === "dev" ? "https://api-dev.scalemule.com" : "https://api.scalemule.com");
7550
7595
  const client = useMemo(
7551
7596
  () => createClient({
@@ -7639,8 +7684,12 @@ function ScaleMuleProvider({
7639
7684
  }
7640
7685
  }
7641
7686
  } catch {
7642
- if (mounted && debug) {
7643
- console.debug("[ScaleMule] Auth proxy session check failed");
7687
+ if (mounted) {
7688
+ setUser(null);
7689
+ setCachedUser(null);
7690
+ if (debug) {
7691
+ console.debug("[ScaleMule] Auth proxy session check failed; clearing cached user");
7692
+ }
7644
7693
  }
7645
7694
  } finally {
7646
7695
  client.resolveSessionPending();
@@ -7799,6 +7848,19 @@ async function proxyFetch(proxyUrl, path, options = {}) {
7799
7848
  // Include cookies for session management
7800
7849
  });
7801
7850
  const data = await response.json();
7851
+ if (data && data.error && !(data.error instanceof ScaleMuleApiError)) {
7852
+ data.error = new ScaleMuleApiError(data.error, response.status);
7853
+ }
7854
+ if (data && data.success === false && data.error) {
7855
+ reportSdkError({
7856
+ code: data.error.code,
7857
+ message: data.error.message,
7858
+ status: response.status,
7859
+ op: path,
7860
+ path: `${proxyUrl}/${path}`,
7861
+ field: data.error.field
7862
+ });
7863
+ }
7802
7864
  return data;
7803
7865
  }
7804
7866
  function useAuth() {
@@ -10121,8 +10183,8 @@ function useAnalytics(options = {}) {
10121
10183
  return { tracked: 1, session_id: sessionIdRef.current || void 0 };
10122
10184
  }
10123
10185
  if (publishableKey && gatewayUrl) {
10124
- const endpoint2 = useV2 ? "/v1/analytics/v2/events" : "/v1/analytics/events";
10125
- fetch(`${gatewayUrl}${endpoint2}`, {
10186
+ const endpoint3 = useV2 ? "/v1/analytics/v2/events" : "/v1/analytics/events";
10187
+ fetch(`${gatewayUrl}${endpoint3}`, {
10126
10188
  method: "POST",
10127
10189
  headers: {
10128
10190
  "Content-Type": "application/json",
@@ -10135,8 +10197,8 @@ function useAnalytics(options = {}) {
10135
10197
  });
10136
10198
  return { tracked: 1, session_id: sessionIdRef.current || void 0 };
10137
10199
  }
10138
- const endpoint = useV2 ? "/v1/analytics/v2/events" : "/v1/analytics/events";
10139
- return await client.post(endpoint, fullEvent);
10200
+ const endpoint2 = useV2 ? "/v1/analytics/v2/events" : "/v1/analytics/events";
10201
+ return await client.post(endpoint2, fullEvent);
10140
10202
  },
10141
10203
  // Note: sessionId removed - we use ref to keep this stable
10142
10204
  [client, buildFullEvent, useV2, analyticsProxyUrl, publishableKey, gatewayUrl]
@@ -10212,8 +10274,8 @@ function useAnalytics(options = {}) {
10212
10274
  return { tracked: events.length, session_id: sessionIdRef.current || void 0 };
10213
10275
  }
10214
10276
  if (publishableKey && gatewayUrl) {
10215
- const endpoint2 = useV2 ? "/v1/analytics/v2/events/batch" : "/v1/analytics/events/batch";
10216
- fetch(`${gatewayUrl}${endpoint2}`, {
10277
+ const endpoint3 = useV2 ? "/v1/analytics/v2/events/batch" : "/v1/analytics/events/batch";
10278
+ fetch(`${gatewayUrl}${endpoint3}`, {
10217
10279
  method: "POST",
10218
10280
  headers: {
10219
10281
  "Content-Type": "application/json",
@@ -10227,8 +10289,8 @@ function useAnalytics(options = {}) {
10227
10289
  setLoading(false);
10228
10290
  return { tracked: events.length, session_id: sessionIdRef.current || void 0 };
10229
10291
  }
10230
- const endpoint = useV2 ? "/v1/analytics/v2/events/batch" : "/v1/analytics/events/batch";
10231
- return await client.post(endpoint, {
10292
+ const endpoint2 = useV2 ? "/v1/analytics/v2/events/batch" : "/v1/analytics/events/batch";
10293
+ return await client.post(endpoint2, {
10232
10294
  events: fullEvents
10233
10295
  });
10234
10296
  } finally {
@@ -10364,10 +10426,10 @@ function useFeatureFlags(options = {}) {
10364
10426
  try {
10365
10427
  const currentKeys = keysRef.current;
10366
10428
  const payload = currentKeys && currentKeys.length > 0 ? { flag_keys: currentKeys, environment, context: contextRef.current } : { environment, context: contextRef.current };
10367
- const endpoint = currentKeys && currentKeys.length > 0 ? "/v1/flags/evaluate/batch" : "/v1/flags/evaluate/all";
10429
+ const endpoint2 = currentKeys && currentKeys.length > 0 ? "/v1/flags/evaluate/batch" : "/v1/flags/evaluate/all";
10368
10430
  let result;
10369
10431
  if (publishableKey && gatewayUrl) {
10370
- const response = await fetch(`${gatewayUrl}${endpoint}`, {
10432
+ const response = await fetch(`${gatewayUrl}${endpoint2}`, {
10371
10433
  method: "POST",
10372
10434
  headers: {
10373
10435
  "Content-Type": "application/json",
@@ -10381,7 +10443,7 @@ function useFeatureFlags(options = {}) {
10381
10443
  const json = await response.json();
10382
10444
  result = json.data || json || {};
10383
10445
  } else {
10384
- result = await client.post(endpoint, payload);
10446
+ result = await client.post(endpoint2, payload);
10385
10447
  }
10386
10448
  setFlags(result || {});
10387
10449
  setError(null);
@@ -0,0 +1,43 @@
1
+ declare const SM_LEDVERY_STATE_COOKIE = "sm_ledvery_state";
2
+ declare const SM_LEDVERY_PKCE_VERIFIER_COOKIE = "sm_ledvery_pkce_verifier";
3
+ declare const SM_LEDVERY_NONCE_COOKIE = "sm_ledvery_nonce";
4
+ declare const SM_LEDVERY_ID_TOKEN_COOKIE = "sm_ledvery_id_token";
5
+ declare const SM_LEDVERY_ACCESS_TOKEN_COOKIE = "sm_ledvery_access_token";
6
+ interface SessionCookieOverrides {
7
+ maxAge?: number;
8
+ domain?: string;
9
+ path?: string;
10
+ sameSite?: 'strict' | 'lax' | 'none';
11
+ secure?: boolean;
12
+ }
13
+ interface LedverySessionData {
14
+ idToken: string;
15
+ accessToken?: string;
16
+ claims: Record<string, unknown>;
17
+ expiresAt: string;
18
+ }
19
+ declare function getLedverySession(request: Request): LedverySessionData | null;
20
+
21
+ interface LedveryRoutesConfig {
22
+ issuer: string;
23
+ clientId: string;
24
+ clientSecret?: string;
25
+ redirectUri: string;
26
+ defaultScope?: string;
27
+ postLoginRedirect?: string;
28
+ postLogoutRedirect?: string;
29
+ cookies?: SessionCookieOverrides;
30
+ storeAccessToken?: boolean;
31
+ fetch?: typeof fetch;
32
+ }
33
+ type RouteHandler = (request: Request, context: {
34
+ params: Promise<{
35
+ action?: string[];
36
+ }>;
37
+ }) => Promise<Response>;
38
+ declare function createLedveryRoutes(config: LedveryRoutesConfig): {
39
+ GET: RouteHandler;
40
+ POST: RouteHandler;
41
+ };
42
+
43
+ export { type LedveryRoutesConfig as L, SM_LEDVERY_ACCESS_TOKEN_COOKIE as S, type LedverySessionData as a, SM_LEDVERY_ID_TOKEN_COOKIE as b, SM_LEDVERY_NONCE_COOKIE as c, SM_LEDVERY_PKCE_VERIFIER_COOKIE as d, SM_LEDVERY_STATE_COOKIE as e, createLedveryRoutes as f, getLedverySession as g };