@sendoracloud/sdk-react-native 0.18.4 → 0.18.6
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.cjs +73 -3
- package/dist/index.d.cts +52 -0
- package/dist/index.d.ts +52 -0
- package/dist/index.js +73 -3
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -654,6 +654,29 @@ var Auth = class {
|
|
|
654
654
|
}
|
|
655
655
|
return { authorizationUrl: parsed.data.authorizationUrl };
|
|
656
656
|
}
|
|
657
|
+
/**
|
|
658
|
+
* Kick off a SAML 2.0 SSO flow. Mirrors `startSso` for SAML —
|
|
659
|
+
* backend POST `/auth-service/sso/saml/start` returns the IdP
|
|
660
|
+
* AuthnRequest URL. Caller opens it with
|
|
661
|
+
* ASWebAuthenticationSession (iOS) / Custom Tabs (Android) /
|
|
662
|
+
* Linking, captures the callback URL via the standard
|
|
663
|
+
* `Linking.addEventListener` flow, then passes the captured URL to
|
|
664
|
+
* `consumeSsoFragment(url)`. consumeSsoFragment handles both OIDC
|
|
665
|
+
* and SAML fragments transparently.
|
|
666
|
+
*/
|
|
667
|
+
async startSaml(returnTo) {
|
|
668
|
+
const res = await post(
|
|
669
|
+
{ apiUrl: this.hooks.apiUrl, publicKey: this.hooks.publicKey, debug: this.hooks.debug },
|
|
670
|
+
"/api/v1/auth-service/sso/saml/start",
|
|
671
|
+
{ returnTo }
|
|
672
|
+
);
|
|
673
|
+
if (!res || !res.ok) throw new AuthError("SAML_START_FAILED", `HTTP ${res?.status ?? "network"}`);
|
|
674
|
+
const parsed = await res.json();
|
|
675
|
+
if (!parsed.success || !parsed.data?.authorizationUrl) {
|
|
676
|
+
throw new AuthError("SAML_START_FAILED", "Missing authorizationUrl");
|
|
677
|
+
}
|
|
678
|
+
return { authorizationUrl: parsed.data.authorizationUrl };
|
|
679
|
+
}
|
|
657
680
|
/**
|
|
658
681
|
* Consume an OIDC callback URL captured via React Native's
|
|
659
682
|
* `Linking.addEventListener('url', ...)`. Reads the fragment for
|
|
@@ -666,10 +689,10 @@ var Auth = class {
|
|
|
666
689
|
const hashIdx = callbackUrl.indexOf("#");
|
|
667
690
|
const fragment = hashIdx >= 0 ? callbackUrl.slice(hashIdx + 1) : "";
|
|
668
691
|
const params = new URLSearchParams(fragment);
|
|
669
|
-
const err = params.get("sendora_oidc_error");
|
|
692
|
+
const err = params.get("sendora_oidc_error") ?? params.get("sendora_saml_error");
|
|
670
693
|
if (err) throw new AuthError("SSO_FAILED", decodeURIComponent(err));
|
|
671
|
-
const refresh = params.get("sendora_oidc_token");
|
|
672
|
-
if (!refresh) throw new AuthError("SSO_NO_TOKEN", "Callback URL has no
|
|
694
|
+
const refresh = params.get("sendora_oidc_token") ?? params.get("sendora_saml_token");
|
|
695
|
+
if (!refresh) throw new AuthError("SSO_NO_TOKEN", "Callback URL has no SSO token");
|
|
673
696
|
const res = await post(
|
|
674
697
|
{ apiUrl: this.hooks.apiUrl, publicKey: this.hooks.publicKey, debug: this.hooks.debug },
|
|
675
698
|
"/api/v1/auth-service/token/refresh",
|
|
@@ -2071,6 +2094,53 @@ var SendoraSDK = class {
|
|
|
2071
2094
|
}
|
|
2072
2095
|
};
|
|
2073
2096
|
}
|
|
2097
|
+
/**
|
|
2098
|
+
* In-app messaging namespace — fetch active messages (modals,
|
|
2099
|
+
* banners, slideouts, tooltips) targeted at this user + record
|
|
2100
|
+
* impressions (shown / clicked / dismissed) so the dashboard's
|
|
2101
|
+
* "shown N times" caps and CTR analytics work. Mirrors backend
|
|
2102
|
+
* `/in-app-messages/{active,impressions}` SDK routes and the web
|
|
2103
|
+
* SDK's `InAppMessaging` class.
|
|
2104
|
+
*
|
|
2105
|
+
* Typical use:
|
|
2106
|
+
* const msgs = await SendoraCloud.messages.fetchActive();
|
|
2107
|
+
* for (const m of msgs) renderMessage(m);
|
|
2108
|
+
* // when user sees it:
|
|
2109
|
+
* await SendoraCloud.messages.recordImpression({ messageId: m.id, action: "shown" });
|
|
2110
|
+
* // when user clicks CTA:
|
|
2111
|
+
* await SendoraCloud.messages.recordImpression({ messageId: m.id, action: "clicked" });
|
|
2112
|
+
*
|
|
2113
|
+
* `action` is a free-form string; "shown" / "clicked" / "dismissed"
|
|
2114
|
+
* are the canonical set the dashboard graphs from.
|
|
2115
|
+
*/
|
|
2116
|
+
get messages() {
|
|
2117
|
+
const self = this;
|
|
2118
|
+
return {
|
|
2119
|
+
fetchActive: async () => {
|
|
2120
|
+
if (!self.config) throw new Error("[sendoracloud] init() must complete before messages.fetchActive().");
|
|
2121
|
+
const url = `${self.config.apiUrl}/api/v1/in-app-messages/active`;
|
|
2122
|
+
const res = await fetch(url, {
|
|
2123
|
+
method: "GET",
|
|
2124
|
+
headers: { "x-api-key": self.config.publicKey }
|
|
2125
|
+
});
|
|
2126
|
+
if (!res.ok) throw new Error(`[sendoracloud] messages.fetchActive failed (${res.status})`);
|
|
2127
|
+
const parsed = await res.json();
|
|
2128
|
+
if (!parsed.success || !Array.isArray(parsed.data)) {
|
|
2129
|
+
throw new Error("[sendoracloud] messages.fetchActive: bad response");
|
|
2130
|
+
}
|
|
2131
|
+
return parsed.data;
|
|
2132
|
+
},
|
|
2133
|
+
recordImpression: async (input) => {
|
|
2134
|
+
if (!self.config) throw new Error("[sendoracloud] init() must complete before messages.recordImpression().");
|
|
2135
|
+
const res = await post(
|
|
2136
|
+
{ apiUrl: self.config.apiUrl, publicKey: self.config.publicKey, debug: self.debug },
|
|
2137
|
+
"/in-app-messages/impressions",
|
|
2138
|
+
input
|
|
2139
|
+
);
|
|
2140
|
+
if (!res || !res.ok) throw new Error(`[sendoracloud] messages.recordImpression failed (${res?.status ?? "network"})`);
|
|
2141
|
+
}
|
|
2142
|
+
};
|
|
2143
|
+
}
|
|
2074
2144
|
/**
|
|
2075
2145
|
* Clear identity + rotate the anonymous id. Call on logout. Awaits
|
|
2076
2146
|
* the AsyncStorage writes so a caller who kills the app immediately
|
package/dist/index.d.cts
CHANGED
|
@@ -268,6 +268,19 @@ declare class Auth {
|
|
|
268
268
|
startSso(returnTo: string): Promise<{
|
|
269
269
|
authorizationUrl: string;
|
|
270
270
|
}>;
|
|
271
|
+
/**
|
|
272
|
+
* Kick off a SAML 2.0 SSO flow. Mirrors `startSso` for SAML —
|
|
273
|
+
* backend POST `/auth-service/sso/saml/start` returns the IdP
|
|
274
|
+
* AuthnRequest URL. Caller opens it with
|
|
275
|
+
* ASWebAuthenticationSession (iOS) / Custom Tabs (Android) /
|
|
276
|
+
* Linking, captures the callback URL via the standard
|
|
277
|
+
* `Linking.addEventListener` flow, then passes the captured URL to
|
|
278
|
+
* `consumeSsoFragment(url)`. consumeSsoFragment handles both OIDC
|
|
279
|
+
* and SAML fragments transparently.
|
|
280
|
+
*/
|
|
281
|
+
startSaml(returnTo: string): Promise<{
|
|
282
|
+
authorizationUrl: string;
|
|
283
|
+
}>;
|
|
271
284
|
/**
|
|
272
285
|
* Consume an OIDC callback URL captured via React Native's
|
|
273
286
|
* `Linking.addEventListener('url', ...)`. Reads the fragment for
|
|
@@ -983,6 +996,45 @@ declare class SendoraSDK {
|
|
|
983
996
|
submittedAt: string;
|
|
984
997
|
}>;
|
|
985
998
|
};
|
|
999
|
+
/**
|
|
1000
|
+
* In-app messaging namespace — fetch active messages (modals,
|
|
1001
|
+
* banners, slideouts, tooltips) targeted at this user + record
|
|
1002
|
+
* impressions (shown / clicked / dismissed) so the dashboard's
|
|
1003
|
+
* "shown N times" caps and CTR analytics work. Mirrors backend
|
|
1004
|
+
* `/in-app-messages/{active,impressions}` SDK routes and the web
|
|
1005
|
+
* SDK's `InAppMessaging` class.
|
|
1006
|
+
*
|
|
1007
|
+
* Typical use:
|
|
1008
|
+
* const msgs = await SendoraCloud.messages.fetchActive();
|
|
1009
|
+
* for (const m of msgs) renderMessage(m);
|
|
1010
|
+
* // when user sees it:
|
|
1011
|
+
* await SendoraCloud.messages.recordImpression({ messageId: m.id, action: "shown" });
|
|
1012
|
+
* // when user clicks CTA:
|
|
1013
|
+
* await SendoraCloud.messages.recordImpression({ messageId: m.id, action: "clicked" });
|
|
1014
|
+
*
|
|
1015
|
+
* `action` is a free-form string; "shown" / "clicked" / "dismissed"
|
|
1016
|
+
* are the canonical set the dashboard graphs from.
|
|
1017
|
+
*/
|
|
1018
|
+
get messages(): {
|
|
1019
|
+
fetchActive: () => Promise<Array<{
|
|
1020
|
+
id: string;
|
|
1021
|
+
type: string;
|
|
1022
|
+
title: string | null;
|
|
1023
|
+
body: string;
|
|
1024
|
+
ctaText: string | null;
|
|
1025
|
+
ctaUrl: string | null;
|
|
1026
|
+
imageUrl: string | null;
|
|
1027
|
+
theme: string | null;
|
|
1028
|
+
priority: number;
|
|
1029
|
+
isActive: boolean;
|
|
1030
|
+
[key: string]: unknown;
|
|
1031
|
+
}>>;
|
|
1032
|
+
recordImpression: (input: {
|
|
1033
|
+
messageId: string;
|
|
1034
|
+
action: string;
|
|
1035
|
+
entityId?: string;
|
|
1036
|
+
}) => Promise<void>;
|
|
1037
|
+
};
|
|
986
1038
|
/**
|
|
987
1039
|
* Clear identity + rotate the anonymous id. Call on logout. Awaits
|
|
988
1040
|
* the AsyncStorage writes so a caller who kills the app immediately
|
package/dist/index.d.ts
CHANGED
|
@@ -268,6 +268,19 @@ declare class Auth {
|
|
|
268
268
|
startSso(returnTo: string): Promise<{
|
|
269
269
|
authorizationUrl: string;
|
|
270
270
|
}>;
|
|
271
|
+
/**
|
|
272
|
+
* Kick off a SAML 2.0 SSO flow. Mirrors `startSso` for SAML —
|
|
273
|
+
* backend POST `/auth-service/sso/saml/start` returns the IdP
|
|
274
|
+
* AuthnRequest URL. Caller opens it with
|
|
275
|
+
* ASWebAuthenticationSession (iOS) / Custom Tabs (Android) /
|
|
276
|
+
* Linking, captures the callback URL via the standard
|
|
277
|
+
* `Linking.addEventListener` flow, then passes the captured URL to
|
|
278
|
+
* `consumeSsoFragment(url)`. consumeSsoFragment handles both OIDC
|
|
279
|
+
* and SAML fragments transparently.
|
|
280
|
+
*/
|
|
281
|
+
startSaml(returnTo: string): Promise<{
|
|
282
|
+
authorizationUrl: string;
|
|
283
|
+
}>;
|
|
271
284
|
/**
|
|
272
285
|
* Consume an OIDC callback URL captured via React Native's
|
|
273
286
|
* `Linking.addEventListener('url', ...)`. Reads the fragment for
|
|
@@ -983,6 +996,45 @@ declare class SendoraSDK {
|
|
|
983
996
|
submittedAt: string;
|
|
984
997
|
}>;
|
|
985
998
|
};
|
|
999
|
+
/**
|
|
1000
|
+
* In-app messaging namespace — fetch active messages (modals,
|
|
1001
|
+
* banners, slideouts, tooltips) targeted at this user + record
|
|
1002
|
+
* impressions (shown / clicked / dismissed) so the dashboard's
|
|
1003
|
+
* "shown N times" caps and CTR analytics work. Mirrors backend
|
|
1004
|
+
* `/in-app-messages/{active,impressions}` SDK routes and the web
|
|
1005
|
+
* SDK's `InAppMessaging` class.
|
|
1006
|
+
*
|
|
1007
|
+
* Typical use:
|
|
1008
|
+
* const msgs = await SendoraCloud.messages.fetchActive();
|
|
1009
|
+
* for (const m of msgs) renderMessage(m);
|
|
1010
|
+
* // when user sees it:
|
|
1011
|
+
* await SendoraCloud.messages.recordImpression({ messageId: m.id, action: "shown" });
|
|
1012
|
+
* // when user clicks CTA:
|
|
1013
|
+
* await SendoraCloud.messages.recordImpression({ messageId: m.id, action: "clicked" });
|
|
1014
|
+
*
|
|
1015
|
+
* `action` is a free-form string; "shown" / "clicked" / "dismissed"
|
|
1016
|
+
* are the canonical set the dashboard graphs from.
|
|
1017
|
+
*/
|
|
1018
|
+
get messages(): {
|
|
1019
|
+
fetchActive: () => Promise<Array<{
|
|
1020
|
+
id: string;
|
|
1021
|
+
type: string;
|
|
1022
|
+
title: string | null;
|
|
1023
|
+
body: string;
|
|
1024
|
+
ctaText: string | null;
|
|
1025
|
+
ctaUrl: string | null;
|
|
1026
|
+
imageUrl: string | null;
|
|
1027
|
+
theme: string | null;
|
|
1028
|
+
priority: number;
|
|
1029
|
+
isActive: boolean;
|
|
1030
|
+
[key: string]: unknown;
|
|
1031
|
+
}>>;
|
|
1032
|
+
recordImpression: (input: {
|
|
1033
|
+
messageId: string;
|
|
1034
|
+
action: string;
|
|
1035
|
+
entityId?: string;
|
|
1036
|
+
}) => Promise<void>;
|
|
1037
|
+
};
|
|
986
1038
|
/**
|
|
987
1039
|
* Clear identity + rotate the anonymous id. Call on logout. Awaits
|
|
988
1040
|
* the AsyncStorage writes so a caller who kills the app immediately
|
package/dist/index.js
CHANGED
|
@@ -611,6 +611,29 @@ var Auth = class {
|
|
|
611
611
|
}
|
|
612
612
|
return { authorizationUrl: parsed.data.authorizationUrl };
|
|
613
613
|
}
|
|
614
|
+
/**
|
|
615
|
+
* Kick off a SAML 2.0 SSO flow. Mirrors `startSso` for SAML —
|
|
616
|
+
* backend POST `/auth-service/sso/saml/start` returns the IdP
|
|
617
|
+
* AuthnRequest URL. Caller opens it with
|
|
618
|
+
* ASWebAuthenticationSession (iOS) / Custom Tabs (Android) /
|
|
619
|
+
* Linking, captures the callback URL via the standard
|
|
620
|
+
* `Linking.addEventListener` flow, then passes the captured URL to
|
|
621
|
+
* `consumeSsoFragment(url)`. consumeSsoFragment handles both OIDC
|
|
622
|
+
* and SAML fragments transparently.
|
|
623
|
+
*/
|
|
624
|
+
async startSaml(returnTo) {
|
|
625
|
+
const res = await post(
|
|
626
|
+
{ apiUrl: this.hooks.apiUrl, publicKey: this.hooks.publicKey, debug: this.hooks.debug },
|
|
627
|
+
"/api/v1/auth-service/sso/saml/start",
|
|
628
|
+
{ returnTo }
|
|
629
|
+
);
|
|
630
|
+
if (!res || !res.ok) throw new AuthError("SAML_START_FAILED", `HTTP ${res?.status ?? "network"}`);
|
|
631
|
+
const parsed = await res.json();
|
|
632
|
+
if (!parsed.success || !parsed.data?.authorizationUrl) {
|
|
633
|
+
throw new AuthError("SAML_START_FAILED", "Missing authorizationUrl");
|
|
634
|
+
}
|
|
635
|
+
return { authorizationUrl: parsed.data.authorizationUrl };
|
|
636
|
+
}
|
|
614
637
|
/**
|
|
615
638
|
* Consume an OIDC callback URL captured via React Native's
|
|
616
639
|
* `Linking.addEventListener('url', ...)`. Reads the fragment for
|
|
@@ -623,10 +646,10 @@ var Auth = class {
|
|
|
623
646
|
const hashIdx = callbackUrl.indexOf("#");
|
|
624
647
|
const fragment = hashIdx >= 0 ? callbackUrl.slice(hashIdx + 1) : "";
|
|
625
648
|
const params = new URLSearchParams(fragment);
|
|
626
|
-
const err = params.get("sendora_oidc_error");
|
|
649
|
+
const err = params.get("sendora_oidc_error") ?? params.get("sendora_saml_error");
|
|
627
650
|
if (err) throw new AuthError("SSO_FAILED", decodeURIComponent(err));
|
|
628
|
-
const refresh = params.get("sendora_oidc_token");
|
|
629
|
-
if (!refresh) throw new AuthError("SSO_NO_TOKEN", "Callback URL has no
|
|
651
|
+
const refresh = params.get("sendora_oidc_token") ?? params.get("sendora_saml_token");
|
|
652
|
+
if (!refresh) throw new AuthError("SSO_NO_TOKEN", "Callback URL has no SSO token");
|
|
630
653
|
const res = await post(
|
|
631
654
|
{ apiUrl: this.hooks.apiUrl, publicKey: this.hooks.publicKey, debug: this.hooks.debug },
|
|
632
655
|
"/api/v1/auth-service/token/refresh",
|
|
@@ -2033,6 +2056,53 @@ var SendoraSDK = class {
|
|
|
2033
2056
|
}
|
|
2034
2057
|
};
|
|
2035
2058
|
}
|
|
2059
|
+
/**
|
|
2060
|
+
* In-app messaging namespace — fetch active messages (modals,
|
|
2061
|
+
* banners, slideouts, tooltips) targeted at this user + record
|
|
2062
|
+
* impressions (shown / clicked / dismissed) so the dashboard's
|
|
2063
|
+
* "shown N times" caps and CTR analytics work. Mirrors backend
|
|
2064
|
+
* `/in-app-messages/{active,impressions}` SDK routes and the web
|
|
2065
|
+
* SDK's `InAppMessaging` class.
|
|
2066
|
+
*
|
|
2067
|
+
* Typical use:
|
|
2068
|
+
* const msgs = await SendoraCloud.messages.fetchActive();
|
|
2069
|
+
* for (const m of msgs) renderMessage(m);
|
|
2070
|
+
* // when user sees it:
|
|
2071
|
+
* await SendoraCloud.messages.recordImpression({ messageId: m.id, action: "shown" });
|
|
2072
|
+
* // when user clicks CTA:
|
|
2073
|
+
* await SendoraCloud.messages.recordImpression({ messageId: m.id, action: "clicked" });
|
|
2074
|
+
*
|
|
2075
|
+
* `action` is a free-form string; "shown" / "clicked" / "dismissed"
|
|
2076
|
+
* are the canonical set the dashboard graphs from.
|
|
2077
|
+
*/
|
|
2078
|
+
get messages() {
|
|
2079
|
+
const self = this;
|
|
2080
|
+
return {
|
|
2081
|
+
fetchActive: async () => {
|
|
2082
|
+
if (!self.config) throw new Error("[sendoracloud] init() must complete before messages.fetchActive().");
|
|
2083
|
+
const url = `${self.config.apiUrl}/api/v1/in-app-messages/active`;
|
|
2084
|
+
const res = await fetch(url, {
|
|
2085
|
+
method: "GET",
|
|
2086
|
+
headers: { "x-api-key": self.config.publicKey }
|
|
2087
|
+
});
|
|
2088
|
+
if (!res.ok) throw new Error(`[sendoracloud] messages.fetchActive failed (${res.status})`);
|
|
2089
|
+
const parsed = await res.json();
|
|
2090
|
+
if (!parsed.success || !Array.isArray(parsed.data)) {
|
|
2091
|
+
throw new Error("[sendoracloud] messages.fetchActive: bad response");
|
|
2092
|
+
}
|
|
2093
|
+
return parsed.data;
|
|
2094
|
+
},
|
|
2095
|
+
recordImpression: async (input) => {
|
|
2096
|
+
if (!self.config) throw new Error("[sendoracloud] init() must complete before messages.recordImpression().");
|
|
2097
|
+
const res = await post(
|
|
2098
|
+
{ apiUrl: self.config.apiUrl, publicKey: self.config.publicKey, debug: self.debug },
|
|
2099
|
+
"/in-app-messages/impressions",
|
|
2100
|
+
input
|
|
2101
|
+
);
|
|
2102
|
+
if (!res || !res.ok) throw new Error(`[sendoracloud] messages.recordImpression failed (${res?.status ?? "network"})`);
|
|
2103
|
+
}
|
|
2104
|
+
};
|
|
2105
|
+
}
|
|
2036
2106
|
/**
|
|
2037
2107
|
* Clear identity + rotate the anonymous id. Call on logout. Awaits
|
|
2038
2108
|
* the AsyncStorage writes so a caller who kills the app immediately
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sendoracloud/sdk-react-native",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.6",
|
|
4
4
|
"description": "Sendora Cloud React Native + Expo SDK — analytics, identity, push-token registration, auth, deep links (Branch / Firebase Dynamic Links parity). Auth + analytics + deep links work in Expo Go; push token registration requires a Dev Client (EAS Build or `npx expo prebuild`).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|