framepayments 2.3.0 → 2.4.0

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.mjs CHANGED
@@ -15,12 +15,14 @@ var FrameAPIError = class extends Error {
15
15
  };
16
16
  //#endregion
17
17
  //#region src/client.ts
18
- const PUBLISHABLE_FLAG_KEY = "X-Frame-Use-Publishable-Key";
18
+ const FRAME_USE_PUBLISHABLE_KEY = "frameUsePublishableKey";
19
+ const FRAME_AUTH_TOKEN = "frameAuthToken";
20
+ const createOnboardingSessionStore = () => ({ token: null });
19
21
  function safeRawFromAxiosError(err) {
20
22
  if (!err || typeof err !== "object") return err;
21
23
  const cleanedConfig = err.config ? (() => {
22
- const { headers, ...restConfig } = err.config;
23
- const cleanedHeaders = headers && typeof headers === "object" ? Object.fromEntries(Object.entries(headers).filter(([k]) => k.toLowerCase() !== "authorization" && k !== PUBLISHABLE_FLAG_KEY)) : headers;
24
+ const { headers, [FRAME_AUTH_TOKEN]: _authToken, ...restConfig } = err.config;
25
+ const cleanedHeaders = headers && typeof headers === "object" ? Object.fromEntries(Object.entries(headers).filter(([k]) => k.toLowerCase() !== "authorization")) : headers;
24
26
  return {
25
27
  ...restConfig,
26
28
  headers: cleanedHeaders
@@ -33,7 +35,7 @@ function safeRawFromAxiosError(err) {
33
35
  config: cleanedConfig
34
36
  };
35
37
  }
36
- const createApiClient = (config) => {
38
+ const createApiClient = (config, sessionStore = createOnboardingSessionStore()) => {
37
39
  const { apiKey, publishableKey, defaultHeaders } = config;
38
40
  if (!apiKey && !publishableKey) throw new Error("FrameSDK config requires at least one of: apiKey, publishableKey. Mobile clients should ship publishableKey only; server code should use apiKey.");
39
41
  const baseURL = config.baseURL ?? "https://api.framepayments.com";
@@ -43,9 +45,11 @@ const createApiClient = (config) => {
43
45
  });
44
46
  client.interceptors.request.use((requestConfig) => {
45
47
  const headers = requestConfig.headers;
46
- const wantsPublishable = headers instanceof AxiosHeaders ? headers.has(PUBLISHABLE_FLAG_KEY) : Boolean(headers?.[PUBLISHABLE_FLAG_KEY]);
47
- if (headers instanceof AxiosHeaders) headers.delete(PUBLISHABLE_FLAG_KEY);
48
- else if (headers && PUBLISHABLE_FLAG_KEY in headers) delete headers[PUBLISHABLE_FLAG_KEY];
48
+ const cfg = requestConfig;
49
+ const wantsPublishable = cfg.frameUsePublishableKey === true;
50
+ const rawAuthToken = cfg.frameAuthToken;
51
+ if (rawAuthToken === "") throw new FrameAPIError("Frame authToken was provided but empty. Pass a non-empty client_secret (e.g. ci_..._secret_...), or omit authToken to use the configured key.", "invalid_auth_token", 0, null);
52
+ const perRequestAuthToken = typeof rawAuthToken === "string" && rawAuthToken.length > 0 ? rawAuthToken : void 0;
49
53
  if (defaultHeaders) for (const [name, value] of Object.entries(defaultHeaders)) {
50
54
  if (value == null) continue;
51
55
  if (headers instanceof AxiosHeaders) {
@@ -55,10 +59,17 @@ const createApiClient = (config) => {
55
59
  if (h[name] === void 0) h[name] = value;
56
60
  }
57
61
  }
58
- const keyToUse = wantsPublishable ? publishableKey : apiKey;
59
- if (!keyToUse) throw new FrameAPIError(wantsPublishable ? "Frame publishable key is not configured. Pass { publishableKey } to new FrameSDK(...) before calling endpoints with { usePublishableKey: true }." : "Frame API key is not configured. Pass { apiKey } to new FrameSDK(...) before calling secret-keyed endpoints.", wantsPublishable ? "missing_publishable_key" : "missing_api_key", 0, null);
60
- if (headers instanceof AxiosHeaders) headers.set("Authorization", `Bearer ${keyToUse}`);
61
- else if (headers) headers["Authorization"] = `Bearer ${keyToUse}`;
62
+ const sessionToken = sessionStore.token;
63
+ let bearer;
64
+ if (perRequestAuthToken) bearer = perRequestAuthToken;
65
+ else if (sessionToken) bearer = sessionToken;
66
+ else {
67
+ const keyToUse = wantsPublishable ? publishableKey : apiKey;
68
+ if (!keyToUse) throw new FrameAPIError(wantsPublishable ? "Frame publishable key is not configured. Pass { publishableKey } to new FrameSDK(...) before calling endpoints with { usePublishableKey: true }." : "Frame API key is not configured. Pass { apiKey } to new FrameSDK(...) before calling secret-keyed endpoints.", wantsPublishable ? "missing_publishable_key" : "missing_api_key", 0, null);
69
+ bearer = keyToUse;
70
+ }
71
+ if (headers instanceof AxiosHeaders) headers.set("Authorization", `Bearer ${bearer}`);
72
+ else if (headers) headers["Authorization"] = `Bearer ${bearer}`;
62
73
  return requestConfig;
63
74
  });
64
75
  client.interceptors.response.use((response) => response, (error) => {
@@ -72,33 +83,18 @@ const createApiClient = (config) => {
72
83
  });
73
84
  return client;
74
85
  };
86
+ function buildRequestConfig(publishableDefault, opts) {
87
+ const { usePublishableKey = publishableDefault, authToken, ...rest } = opts ?? {};
88
+ const cfg = { ...rest };
89
+ if (usePublishableKey) cfg[FRAME_USE_PUBLISHABLE_KEY] = true;
90
+ if (authToken !== void 0) cfg[FRAME_AUTH_TOKEN] = authToken;
91
+ return cfg;
92
+ }
75
93
  function withPublishableKey(opts) {
76
- const { usePublishableKey = true, headers, ...rest } = opts ?? {};
77
- if (!usePublishableKey) return headers ? {
78
- ...rest,
79
- headers
80
- } : { ...rest };
81
- return {
82
- ...rest,
83
- headers: {
84
- ...headers ?? {},
85
- [PUBLISHABLE_FLAG_KEY]: "1"
86
- }
87
- };
94
+ return buildRequestConfig(true, opts);
88
95
  }
89
96
  function maybePublishableKey(opts) {
90
- const { usePublishableKey = false, headers, ...rest } = opts ?? {};
91
- if (!usePublishableKey) return headers ? {
92
- ...rest,
93
- headers
94
- } : { ...rest };
95
- return {
96
- ...rest,
97
- headers: {
98
- ...headers ?? {},
99
- [PUBLISHABLE_FLAG_KEY]: "1"
100
- }
101
- };
97
+ return buildRequestConfig(false, opts);
102
98
  }
103
99
  //#endregion
104
100
  //#region src/utils/paginator.ts
@@ -166,11 +162,11 @@ var CapabilitiesAPI = class {
166
162
  constructor(client) {
167
163
  this.client = client;
168
164
  }
169
- async list(accountId) {
170
- return (await this.client.get(`/v1/accounts/${accountId}/capabilities`)).data;
165
+ async list(accountId, opts) {
166
+ return (await this.client.get(`/v1/accounts/${accountId}/capabilities`, maybePublishableKey(opts))).data;
171
167
  }
172
- async request(accountId, params) {
173
- return (await this.client.post(`/v1/accounts/${accountId}/capabilities`, params)).data;
168
+ async request(accountId, params, opts) {
169
+ return (await this.client.post(`/v1/accounts/${accountId}/capabilities`, params, maybePublishableKey(opts))).data;
174
170
  }
175
171
  async get(accountId, name) {
176
172
  return (await this.client.get(`/v1/accounts/${accountId}/capabilities/${name}`)).data;
@@ -185,11 +181,14 @@ var OnboardingSessionsAPI = class {
185
181
  constructor(client) {
186
182
  this.client = client;
187
183
  }
188
- async create(params) {
189
- return (await this.client.post("/v1/onboarding_sessions", params)).data;
184
+ async create(params, opts) {
185
+ return (await this.client.post("/v1/onboarding_sessions", params, maybePublishableKey(opts))).data;
190
186
  }
191
- async getByAccount(accountId) {
192
- return (await this.client.get("/v1/onboarding_sessions", { params: { account_id: accountId } })).data;
187
+ async getByAccount(accountId, opts) {
188
+ return (await this.client.get("/v1/onboarding_sessions", {
189
+ ...maybePublishableKey(opts),
190
+ params: { account_id: accountId }
191
+ })).data;
193
192
  }
194
193
  };
195
194
  //#endregion
@@ -318,8 +317,8 @@ var ChargeIntentsAPI = class {
318
317
  async update(id, params) {
319
318
  return (await this.client.patch(`/v1/charge_intents/${id}`, params)).data;
320
319
  }
321
- async get(id) {
322
- return (await this.client.get(`/v1/charge_intents/${id}`)).data;
320
+ async get(id, opts) {
321
+ return (await this.client.get(`/v1/charge_intents/${id}`, maybePublishableKey(opts))).data;
323
322
  }
324
323
  async list(per_page, page) {
325
324
  return (await this.client.get("/v1/charge_intents", { params: {
@@ -976,14 +975,14 @@ var ThreeDSAPI = class {
976
975
  constructor(client) {
977
976
  this.client = client;
978
977
  }
979
- async create(params) {
980
- return (await this.client.post("/v1/3ds/intents", params)).data;
978
+ async create(params, opts) {
979
+ return (await this.client.post("/v1/3ds/intents", params, maybePublishableKey(opts))).data;
981
980
  }
982
- async get(id) {
983
- return (await this.client.get(`/v1/3ds/intents/${id}`)).data;
981
+ async get(id, opts) {
982
+ return (await this.client.get(`/v1/3ds/intents/${id}`, maybePublishableKey(opts))).data;
984
983
  }
985
- async resend(id) {
986
- return (await this.client.post(`/v1/3ds/intents/${id}/resend`)).data;
984
+ async resend(id, opts) {
985
+ return (await this.client.post(`/v1/3ds/intents/${id}/resend`, void 0, maybePublishableKey(opts))).data;
987
986
  }
988
987
  };
989
988
  //#endregion
@@ -1028,8 +1027,8 @@ var TermsOfServiceAPI = class {
1028
1027
  constructor(client) {
1029
1028
  this.client = client;
1030
1029
  }
1031
- async createToken() {
1032
- return (await this.client.post("/v1/terms_of_service", {})).data;
1030
+ async createToken(opts) {
1031
+ return (await this.client.post("/v1/terms_of_service", {}, maybePublishableKey(opts))).data;
1033
1032
  }
1034
1033
  async update(params) {
1035
1034
  return (await this.client.patch("/v1/terms_of_service", params)).data;
@@ -1107,7 +1106,8 @@ var GeoComplianceAPI = class {
1107
1106
  //#region src/index.ts
1108
1107
  var FrameSDK = class {
1109
1108
  constructor(config) {
1110
- const client = createApiClient(config);
1109
+ this.onboardingSessionStore = createOnboardingSessionStore();
1110
+ const client = createApiClient(config, this.onboardingSessionStore);
1111
1111
  this.accounts = new AccountsAPI(client);
1112
1112
  this.capabilities = new CapabilitiesAPI(client);
1113
1113
  this.onboardingSessions = new OnboardingSessionsAPI(client);
@@ -1147,6 +1147,33 @@ var FrameSDK = class {
1147
1147
  this.wallet = new WalletAPI(client);
1148
1148
  this.geoCompliance = new GeoComplianceAPI(client);
1149
1149
  }
1150
+ /**
1151
+ * Begin an onboarding session. While a session is active, every request sends
1152
+ * `Authorization: Bearer <token>` (e.g. an `onb_sess_...` token), overriding
1153
+ * the configured publishable/secret keys regardless of `usePublishableKey`.
1154
+ * A per-request `authToken` (object client_secret) still takes precedence.
1155
+ *
1156
+ * Mirrors the native iOS `beginOnboardingSession`.
1157
+ */
1158
+ setOnboardingSession(token) {
1159
+ this.onboardingSessionStore.token = token;
1160
+ }
1161
+ /**
1162
+ * End the active onboarding session, reverting auth to the configured
1163
+ * publishable/secret keys.
1164
+ *
1165
+ * Safe-clear: when `token` is provided, the session is cleared only if it
1166
+ * matches the currently active token. This mirrors Android's guarded
1167
+ * teardown so a stale unmount cannot wipe a newer session. Omit `token` to
1168
+ * force-clear unconditionally.
1169
+ *
1170
+ * @returns true if a session was cleared, false if the guard prevented it.
1171
+ */
1172
+ clearOnboardingSession(token) {
1173
+ if (token !== void 0 && this.onboardingSessionStore.token !== token) return false;
1174
+ this.onboardingSessionStore.token = null;
1175
+ return true;
1176
+ }
1150
1177
  };
1151
1178
  //#endregion
1152
1179
  export { FrameAPIError, FrameSDK, maybePublishableKey, paginate, withPublishableKey };