@xapps-platform/marketplace-ui 0.1.2 → 0.1.3

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.js CHANGED
@@ -4010,6 +4010,27 @@ function readPaymentEvidenceParams(search) {
4010
4010
  }
4011
4011
  return out;
4012
4012
  }
4013
+ function toSessionExpiredUi(input) {
4014
+ const data = asRecord(input);
4015
+ const reason = readString(data.reason).toLowerCase();
4016
+ const message = readFirstString(data.message);
4017
+ if (reason === "logout") {
4018
+ return {
4019
+ title: "Session ended",
4020
+ message: message || "Your session ended. Go back and open the widget again."
4021
+ };
4022
+ }
4023
+ if (reason === "token_refresh_failed") {
4024
+ return {
4025
+ title: "Widget session expired",
4026
+ message: message || "This widget session expired and could not be renewed. Open it again to continue."
4027
+ };
4028
+ }
4029
+ return {
4030
+ title: "Widget session expired",
4031
+ message: message || "This widget session ended. Go back and open it again to continue."
4032
+ };
4033
+ }
4013
4034
  function WidgetView() {
4014
4035
  const { client, host, env } = useMarketplace();
4015
4036
  const { installationId, widgetId } = useParams3();
@@ -4024,6 +4045,7 @@ function WidgetView() {
4024
4045
  const [discoveredOperationalSurfaces, setDiscoveredOperationalSurfaces] = useState8([]);
4025
4046
  const [widgetToken, setWidgetToken] = useState8("");
4026
4047
  const [error, setError] = useState8(null);
4048
+ const [sessionExpired, setSessionExpired] = useState8(null);
4027
4049
  const [hostNestedExpandStage, setHostNestedExpandStage] = useState8("inline");
4028
4050
  const loc = useLocation8();
4029
4051
  const isEmbedded = window.location.pathname.startsWith("/embed");
@@ -4114,6 +4136,7 @@ function WidgetView() {
4114
4136
  try {
4115
4137
  const { token: wToken } = await client.getWidgetToken(installationId, widgetId);
4116
4138
  if (!alive) return;
4139
+ setSessionExpired(null);
4117
4140
  setWidgetToken(wToken);
4118
4141
  } catch (e) {
4119
4142
  if (!alive) return;
@@ -4124,6 +4147,22 @@ function WidgetView() {
4124
4147
  alive = false;
4125
4148
  };
4126
4149
  }, [installationId, widgetId, client]);
4150
+ async function remintWidgetSession() {
4151
+ if (!installationId || !widgetId) {
4152
+ throw new Error("Missing installationId/widgetId for widget refresh");
4153
+ }
4154
+ const refreshed = await client.getWidgetToken(installationId, widgetId);
4155
+ const nextToken = String(refreshed?.token || "").trim();
4156
+ if (!nextToken) {
4157
+ throw new Error("Widget refresh did not return a token");
4158
+ }
4159
+ setSessionExpired(null);
4160
+ setWidgetToken(nextToken);
4161
+ return {
4162
+ token: nextToken,
4163
+ expires_in: Number.isFinite(Number(refreshed?.expires_in)) && Number(refreshed?.expires_in) > 0 ? Number(refreshed?.expires_in) : void 0
4164
+ };
4165
+ }
4127
4166
  useEffect9(() => {
4128
4167
  return () => {
4129
4168
  for (const [, pending] of nestedExpandPendingRef.current) {
@@ -4351,6 +4390,56 @@ function WidgetView() {
4351
4390
  }
4352
4391
  return;
4353
4392
  }
4393
+ if (msgType === "XAPPS_TOKEN_REFRESH_REQUEST" && e.source === iframeRef.current?.contentWindow) {
4394
+ void (async () => {
4395
+ try {
4396
+ const refreshed = await remintWidgetSession();
4397
+ try {
4398
+ e.source?.postMessage(
4399
+ {
4400
+ type: "XAPPS_TOKEN_REFRESH",
4401
+ id: readString(msg.id) || void 0,
4402
+ data: {
4403
+ token: refreshed.token,
4404
+ ...typeof refreshed.expires_in === "number" ? { expires_in: refreshed.expires_in } : {}
4405
+ }
4406
+ },
4407
+ "*"
4408
+ );
4409
+ } catch {
4410
+ }
4411
+ } catch (refreshError) {
4412
+ const sessionExpiredUi = toSessionExpiredUi({
4413
+ reason: "token_refresh_failed",
4414
+ message: readFirstString(asRecord(refreshError).message) || "Widget session refresh failed"
4415
+ });
4416
+ setSessionExpired(sessionExpiredUi);
4417
+ setWidgetToken("");
4418
+ try {
4419
+ e.source?.postMessage(
4420
+ {
4421
+ type: "XAPPS_SESSION_EXPIRED",
4422
+ id: readString(msg.id) || void 0,
4423
+ data: {
4424
+ reason: "token_refresh_failed",
4425
+ channel: "host",
4426
+ recoverable: false,
4427
+ message: sessionExpiredUi.message
4428
+ }
4429
+ },
4430
+ "*"
4431
+ );
4432
+ } catch {
4433
+ }
4434
+ }
4435
+ })();
4436
+ return;
4437
+ }
4438
+ if (msgType === "XAPPS_SESSION_EXPIRED") {
4439
+ setSessionExpired(toSessionExpiredUi(msg.data));
4440
+ setWidgetToken("");
4441
+ return;
4442
+ }
4354
4443
  if (msgType === "XAPPS_OPEN_WIDGET") {
4355
4444
  if (e.source === window) return;
4356
4445
  const data = asRecord(msg.data);
@@ -4451,6 +4540,27 @@ function WidgetView() {
4451
4540
  ] })
4452
4541
  ] });
4453
4542
  }
4543
+ if (sessionExpired) {
4544
+ return /* @__PURE__ */ jsxs11("div", { className: `mx-catalog-container ${isEmbedded ? "is-embedded" : ""}`, children: [
4545
+ /* @__PURE__ */ jsxs11("div", { className: "mx-breadcrumb", children: [
4546
+ /* @__PURE__ */ jsx13("button", { className: "mx-breadcrumb-link-btn", onClick: onBackToPortal, children: "Portal" }),
4547
+ !env?.singleXappMode && /* @__PURE__ */ jsxs11(Fragment8, { children: [
4548
+ /* @__PURE__ */ jsx13("span", { className: "mx-breadcrumb-sep", children: "/" }),
4549
+ /* @__PURE__ */ jsx13(Link10, { to: marketplaceTo, children: "Marketplace" })
4550
+ ] }),
4551
+ /* @__PURE__ */ jsx13("span", { className: "mx-breadcrumb-sep", children: "/" }),
4552
+ /* @__PURE__ */ jsx13("span", { children: "Session" })
4553
+ ] }),
4554
+ /* @__PURE__ */ jsxs11("div", { className: "mx-widget-error", children: [
4555
+ /* @__PURE__ */ jsx13("div", { className: "mx-widget-error-title", children: sessionExpired.title }),
4556
+ /* @__PURE__ */ jsx13("div", { className: "mx-widget-error-desc", children: sessionExpired.message }),
4557
+ /* @__PURE__ */ jsxs11("div", { className: "mx-widget-error-actions", children: [
4558
+ /* @__PURE__ */ jsx13(Link10, { to: marketplaceTo, className: "mx-btn mx-btn-outline", children: "Back to Marketplace" }),
4559
+ /* @__PURE__ */ jsx13("button", { className: "mx-btn mx-btn-ghost", onClick: onBackToPortal, children: "Back to Portal" })
4560
+ ] })
4561
+ ] })
4562
+ ] });
4563
+ }
4454
4564
  if (!widgetToken) {
4455
4565
  return /* @__PURE__ */ jsxs11("div", { className: `mx-catalog-container ${isEmbedded ? "is-embedded" : ""}`, children: [
4456
4566
  /* @__PURE__ */ jsxs11("div", { className: "mx-breadcrumb", children: [