@benji-money/connect-sdk 1.1.0-beta.3 → 1.1.0-beta.5
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 +2 -2
- package/dist/connect-sdk.umd.d.ts +14 -0
- package/dist/connect-sdk.umd.global.js +195 -19
- package/dist/connect-sdk.umd.global.js.map +1 -1
- package/dist/index.cjs +195 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +195 -19
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -102,7 +102,7 @@ The SDK accepts the following configuration options:
|
|
|
102
102
|
| ---- | ---------- | ----- |
|
|
103
103
|
| **CONNECT** (default) | Centered or anchored modal iframe | No `authType`; standard connect / verify flow |
|
|
104
104
|
| **LOGIN + DUMMY / no `authType`** | Same visible modal iframe | Partner auth runs in a nested iframe inside Benji Connect |
|
|
105
|
-
| **LOGIN + non-DUMMY** | Partner popup only | Pass `authType`; Benji Connect iframe is headless — see [LOGIN popup example](#login-popup-example) below |
|
|
105
|
+
| **LOGIN + non-DUMMY** | Partner popup only | Pass `authType`; Benji Connect iframe is headless — popup shows a loading spinner until partner auth navigates — see [LOGIN popup example](#login-popup-example) below |
|
|
106
106
|
|
|
107
107
|
### Placement
|
|
108
108
|
|
|
@@ -172,7 +172,7 @@ const sdk = new ConnectSDK({
|
|
|
172
172
|
await sdk.open();
|
|
173
173
|
```
|
|
174
174
|
|
|
175
|
-
> **`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).
|
|
175
|
+
> **`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). The pre-opened popup shows generic loading UI (`Loading sign-in…`) until Benji Connect sends the partner auth URL.
|
|
176
176
|
|
|
177
177
|
### Environments
|
|
178
178
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// These are compile-time constants replaced by tsup's `define` option.
|
|
2
|
+
// Declaring them globally prevents TypeScript errors.
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
declare global {
|
|
6
|
+
const __VERSION__: string;
|
|
7
|
+
const __NAMESPACE__: string;
|
|
8
|
+
|
|
9
|
+
// Global browser exposure for UMD builds
|
|
10
|
+
interface Window {
|
|
11
|
+
// SDK main class (UMD builds attach this)
|
|
12
|
+
ConnectSDK?: any;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -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.0-beta.
|
|
113
|
+
version: "1.1.0-beta.5" ? String("1.1.0-beta.5") : "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 */;
|
|
@@ -130,6 +130,92 @@ var ConnectSDK = (() => {
|
|
|
130
130
|
return defaultEnvironment;
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
+
// src/utils/loginPopupLoading.ts
|
|
134
|
+
var LOGIN_POPUP_TITLE = "User sign-in";
|
|
135
|
+
var LOGIN_POPUP_MESSAGE = "Loading sign-in\u2026";
|
|
136
|
+
function buildLoginPopupLoadingHtml() {
|
|
137
|
+
return `<!DOCTYPE html>
|
|
138
|
+
<html lang="en">
|
|
139
|
+
<head>
|
|
140
|
+
<meta charset="utf-8">
|
|
141
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
142
|
+
<title>${LOGIN_POPUP_TITLE}</title>
|
|
143
|
+
<style>
|
|
144
|
+
* { box-sizing: border-box; }
|
|
145
|
+
html, body {
|
|
146
|
+
margin: 0;
|
|
147
|
+
height: 100%;
|
|
148
|
+
background: #fff;
|
|
149
|
+
}
|
|
150
|
+
body {
|
|
151
|
+
width: 100%;
|
|
152
|
+
height: 100%;
|
|
153
|
+
display: flex;
|
|
154
|
+
justify-content: center;
|
|
155
|
+
align-items: center;
|
|
156
|
+
font-family: Inter, system-ui, -apple-system, sans-serif;
|
|
157
|
+
}
|
|
158
|
+
.loading-content {
|
|
159
|
+
display: flex;
|
|
160
|
+
flex-direction: column;
|
|
161
|
+
align-items: center;
|
|
162
|
+
gap: 14px;
|
|
163
|
+
padding: 24px;
|
|
164
|
+
max-width: 320px;
|
|
165
|
+
transform: translateY(-28px);
|
|
166
|
+
}
|
|
167
|
+
.loader {
|
|
168
|
+
width: 48px;
|
|
169
|
+
height: 48px;
|
|
170
|
+
border: 3px solid #e5e7eb;
|
|
171
|
+
border-top-color: #9ca3af;
|
|
172
|
+
border-radius: 50%;
|
|
173
|
+
animation: spin 0.75s linear infinite;
|
|
174
|
+
}
|
|
175
|
+
@keyframes spin {
|
|
176
|
+
to { transform: rotate(360deg); }
|
|
177
|
+
}
|
|
178
|
+
.loading-text {
|
|
179
|
+
font-size: 16px;
|
|
180
|
+
text-align: center;
|
|
181
|
+
font-family: Inter, sans-serif;
|
|
182
|
+
margin: 0;
|
|
183
|
+
background: linear-gradient(
|
|
184
|
+
90deg,
|
|
185
|
+
#374151 0%,
|
|
186
|
+
#9ca3af 50%,
|
|
187
|
+
#374151 100%
|
|
188
|
+
);
|
|
189
|
+
background-size: 200% 100%;
|
|
190
|
+
-webkit-background-clip: text;
|
|
191
|
+
background-clip: text;
|
|
192
|
+
-webkit-text-fill-color: transparent;
|
|
193
|
+
animation: shimmer 1.8s ease-in-out infinite;
|
|
194
|
+
}
|
|
195
|
+
@keyframes shimmer {
|
|
196
|
+
0% { background-position: 100% 0; }
|
|
197
|
+
100% { background-position: -100% 0; }
|
|
198
|
+
}
|
|
199
|
+
</style>
|
|
200
|
+
</head>
|
|
201
|
+
<body>
|
|
202
|
+
<div class="loading-content">
|
|
203
|
+
<div class="loader" aria-hidden="true"></div>
|
|
204
|
+
<p class="loading-text">${LOGIN_POPUP_MESSAGE}</p>
|
|
205
|
+
</div>
|
|
206
|
+
</body>
|
|
207
|
+
</html>`;
|
|
208
|
+
}
|
|
209
|
+
function writeLoginPopupLoadingDocument(popup) {
|
|
210
|
+
try {
|
|
211
|
+
popup.document.open();
|
|
212
|
+
popup.document.write(buildLoginPopupLoadingHtml());
|
|
213
|
+
popup.document.close();
|
|
214
|
+
} catch (error) {
|
|
215
|
+
console.warn("[Connect SDK] Failed to write LOGIN popup loading document", error);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
133
219
|
// src/utils/placement.ts
|
|
134
220
|
var IFRAME_WIDTH = 400;
|
|
135
221
|
var IFRAME_HEIGHT = 645;
|
|
@@ -584,7 +670,28 @@ var ConnectSDK = (() => {
|
|
|
584
670
|
})(BenjiConnectEventType || {});
|
|
585
671
|
|
|
586
672
|
// src/utils/auth.ts
|
|
673
|
+
var AUTH_MESSAGE_TYPES = /* @__PURE__ */ new Set([
|
|
674
|
+
"auth_config",
|
|
675
|
+
"code_received",
|
|
676
|
+
"code_verification_error",
|
|
677
|
+
"loyalty_verification",
|
|
678
|
+
"phone_verification",
|
|
679
|
+
"request_auth_config",
|
|
680
|
+
"request_code_exchange",
|
|
681
|
+
"request_code_with_login",
|
|
682
|
+
"request_code_with_phone",
|
|
683
|
+
"request_loyalty_verification",
|
|
684
|
+
"request_phone_verification"
|
|
685
|
+
]);
|
|
587
686
|
var CONNECT_MESSAGE_TYPES = new Set(Object.values(BenjiConnectEventType));
|
|
687
|
+
function isAuthMessageType(data2) {
|
|
688
|
+
if (!data2 || typeof data2 !== "object") return false;
|
|
689
|
+
const type = data2.type;
|
|
690
|
+
return typeof type === "string" && AUTH_MESSAGE_TYPES.has(type);
|
|
691
|
+
}
|
|
692
|
+
function shouldRelayMessage(mode, data2) {
|
|
693
|
+
return mode === 5 /* LOGIN */ && isAuthMessageType(data2);
|
|
694
|
+
}
|
|
588
695
|
function isConnectMessageType(data2) {
|
|
589
696
|
if (!data2 || typeof data2 !== "object") return false;
|
|
590
697
|
const type = data2.type;
|
|
@@ -714,6 +821,12 @@ var ConnectSDK = (() => {
|
|
|
714
821
|
this.closeLoginPopup = config.closeLoginPopup;
|
|
715
822
|
this.navigateLoginPopup = config.navigateLoginPopup;
|
|
716
823
|
}
|
|
824
|
+
static setLoginContext(context) {
|
|
825
|
+
this.iframe = context.iframe;
|
|
826
|
+
this.loginPopup = context.loginPopup;
|
|
827
|
+
this.mode = context.mode;
|
|
828
|
+
this.connectOrigin = new URL(Endpoints.benji_connect_auth_url).origin;
|
|
829
|
+
}
|
|
717
830
|
static setMode(mode) {
|
|
718
831
|
this.mode = mode;
|
|
719
832
|
}
|
|
@@ -729,7 +842,10 @@ var ConnectSDK = (() => {
|
|
|
729
842
|
window.removeEventListener("unhandledrejection", this.errorEventHandler);
|
|
730
843
|
window.removeEventListener("message", this.messageEventHandler);
|
|
731
844
|
this.configuredListeners = false;
|
|
845
|
+
this.iframe = null;
|
|
846
|
+
this.loginPopup = null;
|
|
732
847
|
this.mode = 1 /* CONNECT */;
|
|
848
|
+
this.connectOrigin = "";
|
|
733
849
|
}
|
|
734
850
|
static handleErrorMessage(event) {
|
|
735
851
|
switch (event.type) {
|
|
@@ -749,8 +865,49 @@ var ConnectSDK = (() => {
|
|
|
749
865
|
}
|
|
750
866
|
}
|
|
751
867
|
}
|
|
868
|
+
static relayToIframe(event) {
|
|
869
|
+
var _a;
|
|
870
|
+
const iframeWindow = (_a = this.iframe) == null ? void 0 : _a.contentWindow;
|
|
871
|
+
if (!iframeWindow) {
|
|
872
|
+
console.warn("[Benji Connect SDK] Skipping login auth relay, iframe not ready");
|
|
873
|
+
return;
|
|
874
|
+
}
|
|
875
|
+
iframeWindow.postMessage(event.data, this.connectOrigin);
|
|
876
|
+
}
|
|
877
|
+
static relayToPopup(payload) {
|
|
878
|
+
if (!this.loginPopup) {
|
|
879
|
+
console.warn("[Benji Connect SDK] Skipping login auth relay, no login popup");
|
|
880
|
+
return;
|
|
881
|
+
}
|
|
882
|
+
try {
|
|
883
|
+
this.loginPopup.postMessage(payload, "*");
|
|
884
|
+
} catch (error) {
|
|
885
|
+
console.error("[Benji Connect SDK] Failed to forward login auth message to popup", error);
|
|
886
|
+
}
|
|
887
|
+
}
|
|
752
888
|
static handleMessage(event) {
|
|
753
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
889
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
890
|
+
if (shouldRelayMessage(this.mode, event.data) && this.loginPopup) {
|
|
891
|
+
const expectedOrigin2 = this.connectOrigin || new URL(Endpoints.benji_connect_auth_url).origin;
|
|
892
|
+
const iframeWindow = (_a = this.iframe) == null ? void 0 : _a.contentWindow;
|
|
893
|
+
if (event.source === this.loginPopup) {
|
|
894
|
+
this.relayToIframe(event);
|
|
895
|
+
return;
|
|
896
|
+
}
|
|
897
|
+
if (iframeWindow && event.source === iframeWindow) {
|
|
898
|
+
if (event.origin !== expectedOrigin2) {
|
|
899
|
+
console.warn(
|
|
900
|
+
"[Benji Connect SDK] Skipped auth relay, unexpected origin",
|
|
901
|
+
event.origin,
|
|
902
|
+
expectedOrigin2
|
|
903
|
+
);
|
|
904
|
+
return;
|
|
905
|
+
}
|
|
906
|
+
this.relayToPopup(event.data);
|
|
907
|
+
return;
|
|
908
|
+
}
|
|
909
|
+
return;
|
|
910
|
+
}
|
|
754
911
|
if (!isConnectMessageType(event.data)) return;
|
|
755
912
|
const expectedOrigin = new URL(Endpoints.benji_connect_auth_url).origin;
|
|
756
913
|
if (!event || event.origin !== expectedOrigin) {
|
|
@@ -764,48 +921,53 @@ var ConnectSDK = (() => {
|
|
|
764
921
|
const message = partial;
|
|
765
922
|
try {
|
|
766
923
|
switch (message.type) {
|
|
924
|
+
case "PARTNER_LOGIN_OPEN" /* PARTNER_LOGIN_OPEN */: {
|
|
925
|
+
const connectMessage = message;
|
|
926
|
+
const url = (_b = connectMessage.data) == null ? void 0 : _b.url;
|
|
927
|
+
if (url) {
|
|
928
|
+
(_c = this.navigateLoginPopup) == null ? void 0 : _c.call(this, url);
|
|
929
|
+
} else {
|
|
930
|
+
(_d = this.closeLoginPopup) == null ? void 0 : _d.call(this);
|
|
931
|
+
}
|
|
932
|
+
break;
|
|
933
|
+
}
|
|
767
934
|
case "AUTH_SUCCESS" /* AUTH_SUCCESS */: {
|
|
768
935
|
const connectMessage = message;
|
|
769
936
|
const callbackData = BenjiConnectCallbackMapperMap.AUTH_SUCCESS(connectMessage, connectMessage.data);
|
|
770
|
-
(
|
|
937
|
+
(_e = this.onEvent) == null ? void 0 : _e.call(this, callbackData.type, callbackData.metadata);
|
|
771
938
|
break;
|
|
772
939
|
}
|
|
773
940
|
case "FLOW_EXIT" /* FLOW_EXIT */: {
|
|
774
941
|
const connectMessage = message;
|
|
775
942
|
const callbackData = BenjiConnectCallbackMapperMap.FLOW_EXIT(connectMessage.data);
|
|
776
|
-
(
|
|
777
|
-
(
|
|
943
|
+
(_f = this.onExit) == null ? void 0 : _f.call(this, callbackData.metadata);
|
|
944
|
+
(_g = this.close) == null ? void 0 : _g.call(this);
|
|
778
945
|
break;
|
|
779
946
|
}
|
|
780
947
|
case "FLOW_SUCCESS" /* FLOW_SUCCESS */: {
|
|
781
948
|
const connectMessage = message;
|
|
782
949
|
const callbackData = BenjiConnectCallbackMapperMap.FLOW_SUCCESS(connectMessage.data);
|
|
783
|
-
(
|
|
950
|
+
(_h = this.onSuccess) == null ? void 0 : _h.call(this, callbackData.token, callbackData.metadata);
|
|
784
951
|
if (this.mode === 5 /* LOGIN */) {
|
|
785
|
-
(
|
|
952
|
+
(_i = this.close) == null ? void 0 : _i.call(this);
|
|
786
953
|
}
|
|
787
954
|
break;
|
|
788
955
|
}
|
|
789
956
|
case "ERROR" /* ERROR */: {
|
|
790
957
|
const connectMessage = message;
|
|
791
958
|
const callbackData = BenjiConnectCallbackMapperMap.ERROR(connectMessage.data);
|
|
792
|
-
(
|
|
959
|
+
(_j = this.onError) == null ? void 0 : _j.call(this, callbackData.error, callbackData.error_id, callbackData.metadata);
|
|
793
960
|
break;
|
|
794
961
|
}
|
|
795
962
|
case "EVENT" /* EVENT */: {
|
|
796
963
|
const connectMessage = message;
|
|
797
964
|
const callbackData = mapToOnEventData(connectMessage, connectMessage.data);
|
|
798
|
-
(
|
|
965
|
+
(_k = this.onEvent) == null ? void 0 : _k.call(this, callbackData.type, callbackData.metadata);
|
|
799
966
|
break;
|
|
800
967
|
}
|
|
801
|
-
|
|
802
|
-
const
|
|
803
|
-
|
|
804
|
-
if (url) {
|
|
805
|
-
(_i = this.navigateLoginPopup) == null ? void 0 : _i.call(this, url);
|
|
806
|
-
} else {
|
|
807
|
-
(_j = this.closeLoginPopup) == null ? void 0 : _j.call(this);
|
|
808
|
-
}
|
|
968
|
+
default: {
|
|
969
|
+
const _exhaustive = message.type;
|
|
970
|
+
console.warn("[Benji Connect SDK] Unhandled connect message type", _exhaustive);
|
|
809
971
|
break;
|
|
810
972
|
}
|
|
811
973
|
}
|
|
@@ -814,7 +976,10 @@ var ConnectSDK = (() => {
|
|
|
814
976
|
}
|
|
815
977
|
};
|
|
816
978
|
_MessageRouter.configuredListeners = false;
|
|
979
|
+
_MessageRouter.iframe = null;
|
|
980
|
+
_MessageRouter.loginPopup = null;
|
|
817
981
|
_MessageRouter.mode = 1 /* CONNECT */;
|
|
982
|
+
_MessageRouter.connectOrigin = "";
|
|
818
983
|
_MessageRouter.errorEventHandler = (event) => {
|
|
819
984
|
return _MessageRouter.handleErrorMessage(event);
|
|
820
985
|
};
|
|
@@ -907,6 +1072,7 @@ var ConnectSDK = (() => {
|
|
|
907
1072
|
);
|
|
908
1073
|
return false;
|
|
909
1074
|
}
|
|
1075
|
+
writeLoginPopupLoadingDocument(this.loginPopup);
|
|
910
1076
|
this.startPopupClosedPoll();
|
|
911
1077
|
return true;
|
|
912
1078
|
}
|
|
@@ -969,8 +1135,17 @@ var ConnectSDK = (() => {
|
|
|
969
1135
|
return;
|
|
970
1136
|
}
|
|
971
1137
|
this.openUI();
|
|
1138
|
+
this.syncLoginContext(mode);
|
|
1139
|
+
}
|
|
1140
|
+
syncLoginContext(mode) {
|
|
1141
|
+
MessageRouter.setLoginContext({
|
|
1142
|
+
iframe: this.iframe,
|
|
1143
|
+
loginPopup: this.loginPopup,
|
|
1144
|
+
mode
|
|
1145
|
+
});
|
|
972
1146
|
}
|
|
973
1147
|
openUI() {
|
|
1148
|
+
var _a;
|
|
974
1149
|
if (this.iframe) return;
|
|
975
1150
|
const headless = this.isLoginPopupOnly();
|
|
976
1151
|
this.container = document.createElement("div");
|
|
@@ -1019,9 +1194,9 @@ var ConnectSDK = (() => {
|
|
|
1019
1194
|
}
|
|
1020
1195
|
);
|
|
1021
1196
|
this.container.addEventListener("click", (e) => {
|
|
1022
|
-
var
|
|
1197
|
+
var _a2, _b;
|
|
1023
1198
|
if (e.target === this.container) {
|
|
1024
|
-
(_b = (
|
|
1199
|
+
(_b = (_a2 = this.sdkConfig).onExit) == null ? void 0 : _b.call(_a2, {
|
|
1025
1200
|
context: buildContext(),
|
|
1026
1201
|
trigger: "TAPPED_OUT_OF_BOUNDS" /* TAPPED_OUT_OF_BOUNDS */
|
|
1027
1202
|
});
|
|
@@ -1029,6 +1204,7 @@ var ConnectSDK = (() => {
|
|
|
1029
1204
|
}
|
|
1030
1205
|
});
|
|
1031
1206
|
}
|
|
1207
|
+
this.syncLoginContext((_a = this.sdkConfig.mode) != null ? _a : 1 /* CONNECT */);
|
|
1032
1208
|
}
|
|
1033
1209
|
navigateLoginPopup(url) {
|
|
1034
1210
|
if (!this.loginPopup || this.loginPopup.closed) {
|