@benji-money/connect-sdk 1.1.4-beta.1 → 1.1.4-beta.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/README.md +3 -2
- package/dist/connect-sdk.umd.global.js +72 -15
- package/dist/connect-sdk.umd.global.js.map +1 -1
- package/dist/index.cjs +72 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +72 -15
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -88,7 +88,7 @@ The SDK accepts the following configuration options:
|
|
|
88
88
|
- `token` (required): Your API connect token
|
|
89
89
|
- `mode` (optional): `BenjiConnectMode` — `CONNECT` (default), `TRANSFER`, `REDEEM`, or `LOGIN`
|
|
90
90
|
- `authType` (optional): `PartnerIntegrationType` — LOGIN only; omit or set `DUMMY` for the visible modal iframe; set to your partner type (1–6) for popup-only auth. Prefer `tokenData.authType` when using `tokenData`.
|
|
91
|
-
- `tokenData` (optional): `BenjiConnectTokenData` — LOGIN only; pass `partnerAuthLink` (Auth Service `connect_url`) and `authType` so the SDK opens the partner auth URL synchronously
|
|
91
|
+
- `tokenData` (optional): `BenjiConnectTokenData` — LOGIN only; pass `partnerAuthLink` (Auth Service `connect_url`), `configToken` (mint `config_token`, used as OAuth `state` on the popup URL), and `authType` so the SDK opens the partner auth URL synchronously on `open()`
|
|
92
92
|
- `onSuccess` (optional): Callback function called when connect completed successfully
|
|
93
93
|
- `onError` (optional): Callback function called when error occurs in the connect flow
|
|
94
94
|
- `onExit` (optional): Callback function called when the user exits the connect flow
|
|
@@ -164,6 +164,7 @@ const sdk = new ConnectSDK({
|
|
|
164
164
|
tokenData: {
|
|
165
165
|
authType: PartnerIntegrationType.OAUTH_PKCE,
|
|
166
166
|
partnerAuthLink: connectUrl, // from Auth Service connect_url
|
|
167
|
+
configToken: configToken, // from GET /connect/token — OAuth state
|
|
167
168
|
},
|
|
168
169
|
anchor: "#login-btn",
|
|
169
170
|
placement: BenjiConnectPlacement.BOTTOM_END,
|
|
@@ -176,7 +177,7 @@ const sdk = new ConnectSDK({
|
|
|
176
177
|
await sdk.open();
|
|
177
178
|
```
|
|
178
179
|
|
|
179
|
-
> **`bottom-end`** positions the **partner popup** below the anchor with its right edge aligned to the anchor's right edge. The Benji Connect iframe stays headless (not visible). When `tokenData.partnerAuthLink` is set, the popup
|
|
180
|
+
> **`bottom-end`** positions the **partner popup** below the anchor with its right edge aligned to the anchor's right edge. The Benji Connect iframe stays headless (not visible). When `tokenData.partnerAuthLink` is set, the popup opens that URL on `open()` (with `state` from `configToken` when provided). The SDK skips `PARTNER_LOGIN_OPEN` navigation when the popup already has a partner URL. Popup→iframe auth messages are queued until the Connect iframe `load` event. Otherwise the pre-opened popup shows generic loading UI (`Loading sign-in…`) until Benji Connect sends the partner auth URL.
|
|
180
181
|
|
|
181
182
|
### Environments
|
|
182
183
|
|
|
@@ -110,7 +110,7 @@ var ConnectSDK = (() => {
|
|
|
110
110
|
// src/utils/config.ts
|
|
111
111
|
var buildContext = () => ({
|
|
112
112
|
namespace: "benji-connect-sdk" ? "benji-connect-sdk" : "benji-connect-sdk",
|
|
113
|
-
version: "1.1.4-beta.
|
|
113
|
+
version: "1.1.4-beta.2" ? String("1.1.4-beta.2") : "0.0.0"
|
|
114
114
|
});
|
|
115
115
|
function isBenjiConnectEnvironment(environment) {
|
|
116
116
|
return environment === "local" /* LOCAL */ || environment === "development" /* DEVELOPMENT */ || environment === "sandbox" /* SANDBOX */ || environment === "production" /* PRODUCTION */;
|
|
@@ -217,10 +217,34 @@ var ConnectSDK = (() => {
|
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
// src/utils/partnerAuthLink.ts
|
|
220
|
+
var LOGIN_POPUP_QUERY_FLAG = "benji_login_popup";
|
|
221
|
+
function ensureAuthLinkStateNonce(url, nonce) {
|
|
222
|
+
try {
|
|
223
|
+
const parsed = new URL(url);
|
|
224
|
+
if (!parsed.searchParams.get("state")) {
|
|
225
|
+
parsed.searchParams.set("state", nonce);
|
|
226
|
+
}
|
|
227
|
+
return parsed.toString();
|
|
228
|
+
} catch {
|
|
229
|
+
if (url.includes("state=")) {
|
|
230
|
+
return url;
|
|
231
|
+
}
|
|
232
|
+
const separator = url.includes("?") ? "&" : "?";
|
|
233
|
+
return `${url}${separator}state=${encodeURIComponent(nonce)}`;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
220
236
|
function appendLoginPopupFlag(url) {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
237
|
+
try {
|
|
238
|
+
const parsed = new URL(url);
|
|
239
|
+
parsed.searchParams.set(LOGIN_POPUP_QUERY_FLAG, "1");
|
|
240
|
+
return parsed.toString();
|
|
241
|
+
} catch {
|
|
242
|
+
const separator = url.includes("?") ? "&" : "?";
|
|
243
|
+
return `${url}${separator}${LOGIN_POPUP_QUERY_FLAG}=1`;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
function preparePartnerAuthUrl(url, nonce) {
|
|
247
|
+
return ensureAuthLinkStateNonce(url, nonce);
|
|
224
248
|
}
|
|
225
249
|
|
|
226
250
|
// src/utils/placement.ts
|
|
@@ -833,6 +857,12 @@ var ConnectSDK = (() => {
|
|
|
833
857
|
this.loginPopup = context.loginPopup;
|
|
834
858
|
this.mode = context.mode;
|
|
835
859
|
this.connectOrigin = new URL(Endpoints.benji_connect_auth_url).origin;
|
|
860
|
+
if (this.isIframeReady) {
|
|
861
|
+
this.flushPendingPopupAuth();
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
static resetIframeReady() {
|
|
865
|
+
this.isIframeReady = false;
|
|
836
866
|
}
|
|
837
867
|
static setMode(mode) {
|
|
838
868
|
this.mode = mode;
|
|
@@ -853,6 +883,8 @@ var ConnectSDK = (() => {
|
|
|
853
883
|
this.loginPopup = null;
|
|
854
884
|
this.mode = 1 /* CONNECT */;
|
|
855
885
|
this.connectOrigin = "";
|
|
886
|
+
this.isIframeReady = false;
|
|
887
|
+
this.pendingPopupAuth = [];
|
|
856
888
|
}
|
|
857
889
|
static handleErrorMessage(event) {
|
|
858
890
|
switch (event.type) {
|
|
@@ -875,12 +907,25 @@ var ConnectSDK = (() => {
|
|
|
875
907
|
static relayToIframe(event) {
|
|
876
908
|
var _a;
|
|
877
909
|
const iframeWindow = (_a = this.iframe) == null ? void 0 : _a.contentWindow;
|
|
878
|
-
if (!iframeWindow) {
|
|
879
|
-
|
|
910
|
+
if (!this.isIframeReady || !iframeWindow) {
|
|
911
|
+
this.pendingPopupAuth.push(event);
|
|
880
912
|
return;
|
|
881
913
|
}
|
|
882
914
|
iframeWindow.postMessage(event.data, this.connectOrigin);
|
|
883
915
|
}
|
|
916
|
+
static markIframeReady(iframe) {
|
|
917
|
+
if (this.iframe !== iframe) return;
|
|
918
|
+
this.isIframeReady = true;
|
|
919
|
+
this.flushPendingPopupAuth();
|
|
920
|
+
}
|
|
921
|
+
static flushPendingPopupAuth() {
|
|
922
|
+
if (!this.isIframeReady || !this.pendingPopupAuth.length) return;
|
|
923
|
+
const queued = this.pendingPopupAuth;
|
|
924
|
+
this.pendingPopupAuth = [];
|
|
925
|
+
for (const event of queued) {
|
|
926
|
+
this.relayToIframe(event);
|
|
927
|
+
}
|
|
928
|
+
}
|
|
884
929
|
static relayToPopup(payload) {
|
|
885
930
|
if (!this.loginPopup) {
|
|
886
931
|
console.warn("[Benji Connect SDK] Skipping login auth relay, no login popup");
|
|
@@ -987,6 +1032,8 @@ var ConnectSDK = (() => {
|
|
|
987
1032
|
_MessageRouter.loginPopup = null;
|
|
988
1033
|
_MessageRouter.mode = 1 /* CONNECT */;
|
|
989
1034
|
_MessageRouter.connectOrigin = "";
|
|
1035
|
+
_MessageRouter.isIframeReady = false;
|
|
1036
|
+
_MessageRouter.pendingPopupAuth = [];
|
|
990
1037
|
_MessageRouter.errorEventHandler = (event) => {
|
|
991
1038
|
return _MessageRouter.handleErrorMessage(event);
|
|
992
1039
|
};
|
|
@@ -1026,6 +1073,10 @@ var ConnectSDK = (() => {
|
|
|
1026
1073
|
* while the in-flight open() still registers listeners and mounts the iframe.
|
|
1027
1074
|
*/
|
|
1028
1075
|
this.openAbortController = null;
|
|
1076
|
+
this.onIframeLoad = () => {
|
|
1077
|
+
if (this.isClosing || !this.iframe) return;
|
|
1078
|
+
MessageRouter.markIframeReady(this.iframe);
|
|
1079
|
+
};
|
|
1029
1080
|
this.sdkConfig = config;
|
|
1030
1081
|
if (!this.sdkConfig.environment) throw new Error("Environment is required");
|
|
1031
1082
|
if (!this.sdkConfig.token) throw new Error("Connect token is required");
|
|
@@ -1064,14 +1115,16 @@ var ConnectSDK = (() => {
|
|
|
1064
1115
|
});
|
|
1065
1116
|
}
|
|
1066
1117
|
openLoginPopup() {
|
|
1067
|
-
var _a, _b, _c;
|
|
1118
|
+
var _a, _b, _c, _d;
|
|
1068
1119
|
const position = computePopupScreenPosition(
|
|
1069
1120
|
this.sdkConfig,
|
|
1070
1121
|
this.popupLayoutState,
|
|
1071
1122
|
{ warnOnInvalidAnchor: true }
|
|
1072
1123
|
);
|
|
1073
1124
|
const partnerAuthLink = (_a = this.sdkConfig.tokenData) == null ? void 0 : _a.partnerAuthLink;
|
|
1074
|
-
const
|
|
1125
|
+
const configToken = (_b = this.sdkConfig.tokenData) == null ? void 0 : _b.configToken;
|
|
1126
|
+
const preparedLink = partnerAuthLink && configToken ? preparePartnerAuthUrl(partnerAuthLink, configToken) : partnerAuthLink;
|
|
1127
|
+
const popupUrl = preparedLink ? appendLoginPopupFlag(preparedLink) : "about:blank";
|
|
1075
1128
|
this.loginPopup = window.open(
|
|
1076
1129
|
popupUrl,
|
|
1077
1130
|
"benji_partner_auth",
|
|
@@ -1079,15 +1132,15 @@ var ConnectSDK = (() => {
|
|
|
1079
1132
|
);
|
|
1080
1133
|
if (!this.loginPopup) {
|
|
1081
1134
|
console.warn("[Connect SDK] Failed to pre-open LOGIN partner auth popup");
|
|
1082
|
-
(
|
|
1083
|
-
|
|
1135
|
+
(_d = (_c = this.sdkConfig).onError) == null ? void 0 : _d.call(
|
|
1136
|
+
_c,
|
|
1084
1137
|
new Error("Popup blocked. Allow popups for this site and try again."),
|
|
1085
1138
|
"400",
|
|
1086
1139
|
{ context: buildContext() }
|
|
1087
1140
|
);
|
|
1088
1141
|
return false;
|
|
1089
1142
|
}
|
|
1090
|
-
if (
|
|
1143
|
+
if (preparedLink) {
|
|
1091
1144
|
this.hasLoginPopupUrl = true;
|
|
1092
1145
|
} else {
|
|
1093
1146
|
writeLoginPopupLoadingDocument(this.loginPopup);
|
|
@@ -1164,8 +1217,9 @@ var ConnectSDK = (() => {
|
|
|
1164
1217
|
});
|
|
1165
1218
|
}
|
|
1166
1219
|
openUI() {
|
|
1167
|
-
var _a;
|
|
1220
|
+
var _a, _b;
|
|
1168
1221
|
if (this.iframe) return;
|
|
1222
|
+
MessageRouter.resetIframeReady();
|
|
1169
1223
|
const headless = this.isLoginPopupOnly();
|
|
1170
1224
|
this.container = document.createElement("div");
|
|
1171
1225
|
if (headless) {
|
|
@@ -1183,6 +1237,8 @@ var ConnectSDK = (() => {
|
|
|
1183
1237
|
url.searchParams.set("mode", String(this.sdkConfig.mode));
|
|
1184
1238
|
}
|
|
1185
1239
|
this.iframe = document.createElement("iframe");
|
|
1240
|
+
this.syncLoginContext((_a = this.sdkConfig.mode) != null ? _a : 1 /* CONNECT */);
|
|
1241
|
+
this.iframe.addEventListener("load", this.onIframeLoad);
|
|
1186
1242
|
this.iframe.src = url.toString();
|
|
1187
1243
|
this.container.appendChild(this.iframe);
|
|
1188
1244
|
document.body.appendChild(this.container);
|
|
@@ -1213,9 +1269,9 @@ var ConnectSDK = (() => {
|
|
|
1213
1269
|
}
|
|
1214
1270
|
);
|
|
1215
1271
|
this.container.addEventListener("click", (e) => {
|
|
1216
|
-
var _a2,
|
|
1272
|
+
var _a2, _b2;
|
|
1217
1273
|
if (e.target === this.container) {
|
|
1218
|
-
(
|
|
1274
|
+
(_b2 = (_a2 = this.sdkConfig).onExit) == null ? void 0 : _b2.call(_a2, {
|
|
1219
1275
|
context: buildContext(),
|
|
1220
1276
|
trigger: "TAPPED_OUT_OF_BOUNDS" /* TAPPED_OUT_OF_BOUNDS */
|
|
1221
1277
|
});
|
|
@@ -1223,7 +1279,7 @@ var ConnectSDK = (() => {
|
|
|
1223
1279
|
}
|
|
1224
1280
|
});
|
|
1225
1281
|
}
|
|
1226
|
-
this.syncLoginContext((
|
|
1282
|
+
this.syncLoginContext((_b = this.sdkConfig.mode) != null ? _b : 1 /* CONNECT */);
|
|
1227
1283
|
}
|
|
1228
1284
|
navigateLoginPopup(url) {
|
|
1229
1285
|
if (this.hasLoginPopupUrl) return;
|
|
@@ -1266,6 +1322,7 @@ var ConnectSDK = (() => {
|
|
|
1266
1322
|
this.repositionListeners = null;
|
|
1267
1323
|
this.layoutState.lastValidAnchoredLayout = null;
|
|
1268
1324
|
this.popupLayoutState.lastValidAnchoredLayout = null;
|
|
1325
|
+
this.iframe.removeEventListener("load", this.onIframeLoad);
|
|
1269
1326
|
if ((_b = this.container) == null ? void 0 : _b.parentNode) {
|
|
1270
1327
|
this.container.parentNode.removeChild(this.container);
|
|
1271
1328
|
}
|