@ory/elements-react 1.0.0-rc.3 → 1.0.0-rc.4

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
@@ -1,4 +1,4 @@
1
- import { UiNodeGroupEnum, isUiNodeInputAttributes, isUiNodeAnchorAttributes, isUiNodeImageAttributes, isUiNodeScriptAttributes, FlowType, getNodeId, Configuration, FrontendApi, isUiNodeTextAttributes, UiNodeInputAttributesTypeEnum, handleContinueWith, handleFlowError, settingsUrl, isResponseError, loginUrl, recoveryUrl, verificationUrl, registrationUrl, instanceOfContinueWithRecoveryUi } from '@ory/client-fetch';
1
+ import { UiNodeGroupEnum, isUiNodeInputAttributes, isUiNodeAnchorAttributes, isUiNodeImageAttributes, isUiNodeScriptAttributes, FlowType, getNodeId, Configuration, FrontendApi, isUiNodeTextAttributes, UiNodeInputAttributesTypeEnum, handleContinueWith, isResponseError as isResponseError$1, loginUrl, settingsUrl, registrationUrl, FetchError, ResponseError, recoveryUrl, instanceOfContinueWithRecoveryUi, verificationUrl as verificationUrl$1 } from '@ory/client-fetch';
2
2
  import { createContext, useContext, useRef, useState, useMemo, useReducer, useEffect } from 'react';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
  import { useIntl, IntlProvider as IntlProvider$1 } from 'react-intl';
@@ -320,9 +320,7 @@ function parseStateFromFlow(flow) {
320
320
  return { current: "method_active", method: "code" };
321
321
  } else if (methodWithMessage) {
322
322
  return { current: "method_active", method: methodWithMessage.group };
323
- } else if (flow.flow.active && !["default", "identifier_first", "oidc", "saml"].includes(
324
- flow.flow.active
325
- )) {
323
+ } else if (flow.flow.active && !["default", "identifier_first"].includes(flow.flow.active)) {
326
324
  return { current: "method_active", method: flow.flow.active };
327
325
  } else if (isChoosingMethod(flow)) {
328
326
  const authMethods = nodesToAuthMethodGroups(flow.flow.ui.nodes);
@@ -360,14 +358,20 @@ function useFormStateReducer(flow) {
360
358
  const formStateReducer = (state, action2) => {
361
359
  switch (action2.type) {
362
360
  case "action_flow_update": {
363
- if (selectedMethod)
361
+ if (selectedMethod) {
364
362
  return { current: "method_active", method: selectedMethod };
363
+ }
365
364
  return parseStateFromFlow(action2.flow);
366
365
  }
367
366
  case "action_select_method": {
368
367
  setSelectedMethod(action2.method);
369
368
  return { current: "method_active", method: action2.method };
370
369
  }
370
+ case "action_clear_active_method": {
371
+ return {
372
+ current: "select_method"
373
+ };
374
+ }
371
375
  }
372
376
  return state;
373
377
  };
@@ -676,6 +680,134 @@ function replaceWindowFlowId(flow) {
676
680
  url.searchParams.set("flow", flow);
677
681
  window.location.href = url.toString();
678
682
  }
683
+ function isGenericErrorResponse(response) {
684
+ return typeof response === "object" && !!response && "error" in response && typeof response.error === "object" && !!response.error && "id" in response.error;
685
+ }
686
+ function isNeedsPrivilegedSessionError(response) {
687
+ return isGenericErrorResponse(response) && response.error.id === "session_refresh_required";
688
+ }
689
+ function isSelfServiceFlowExpiredError(response) {
690
+ return isGenericErrorResponse(response) && response.error.id === "self_service_flow_expired";
691
+ }
692
+ function isBrowserLocationChangeRequired(response) {
693
+ return isGenericErrorResponse(response) && isGenericErrorResponse(response) && response.error.id === "browser_location_change_required";
694
+ }
695
+ function isAddressNotVerified(response) {
696
+ return isGenericErrorResponse(response) && response.error.id === "session_verified_address_required";
697
+ }
698
+ function isCsrfError(response) {
699
+ return isGenericErrorResponse(response) && response.error.id === "security_csrf_violation";
700
+ }
701
+ var isResponseError = (err) => {
702
+ if (err instanceof ResponseError) {
703
+ return true;
704
+ }
705
+ return typeof err === "object" && !!err && "name" in err && err.name === "ResponseError";
706
+ };
707
+ var isFetchError = (err) => {
708
+ return err instanceof FetchError;
709
+ };
710
+
711
+ // src/util/sdk-helpers/urlHelpers.ts
712
+ var verificationUrl = (config) => config.sdk.url + "/self-service/verification/browser";
713
+ var handleFlowError = (opts) => async (err) => {
714
+ var _a;
715
+ if (!isResponseError(err)) {
716
+ if (isFetchError(err)) {
717
+ throw new FetchError(
718
+ err,
719
+ "Unable to call the API endpoint. Ensure that CORS is set up correctly and that you have provided a valid SDK URL to Ory Elements."
720
+ );
721
+ }
722
+ throw err;
723
+ }
724
+ const contentType = err.response.headers.get("content-type") || "";
725
+ if (contentType.includes("application/json")) {
726
+ const body = await toBody(err.response);
727
+ if (isSelfServiceFlowExpiredError(body)) {
728
+ opts.onRestartFlow(body.use_flow_id);
729
+ return;
730
+ } else if (isAddressNotVerified(body)) {
731
+ for (const continueWith of ((_a = body.error.details) == null ? void 0 : _a.continue_with) || []) {
732
+ if (continueWith.action === "show_verification_ui" && continueWith.flow.url) {
733
+ opts.onRedirect(continueWith.flow.url, true);
734
+ return;
735
+ }
736
+ }
737
+ opts.onRedirect(verificationUrl(opts.config), true);
738
+ return;
739
+ } else if (isBrowserLocationChangeRequired(body) && body.redirect_browser_to) {
740
+ opts.onRedirect(body.redirect_browser_to, true);
741
+ return;
742
+ } else if (isNeedsPrivilegedSessionError(body) && body.redirect_browser_to) {
743
+ opts.onRedirect(body.redirect_browser_to, true);
744
+ return;
745
+ } else if (isCsrfError(body)) {
746
+ opts.onRestartFlow();
747
+ return;
748
+ }
749
+ switch (err.response.status) {
750
+ case 404:
751
+ opts.onRestartFlow();
752
+ return;
753
+ case 410:
754
+ opts.onRestartFlow();
755
+ return;
756
+ case 400:
757
+ return opts.onValidationError(
758
+ await err.response.json()
759
+ );
760
+ case 403:
761
+ opts.onRestartFlow();
762
+ return;
763
+ case 422: {
764
+ throw new ResponseError(
765
+ err.response,
766
+ "The API returned an error code indicating a required redirect, but the SDK is outdated and does not know how to handle the action. Received response: " + await err.response.json()
767
+ );
768
+ }
769
+ }
770
+ throw new ResponseError(
771
+ err.response,
772
+ "The Ory API endpoint returned a response code the SDK does not know how to handle. Please check the network tab for more information. Received response: " + await err.response.json()
773
+ );
774
+ } else if (
775
+ // Not a JSON response? If it's a text response we will return an error informing the user that the response is not JSON.
776
+ contentType.includes("text/") || contentType.includes("html") || contentType.includes("xml")
777
+ ) {
778
+ await logResponseError(err.response, true);
779
+ throw new ResponseError(
780
+ err.response,
781
+ `The Ory API endpoint returned an unexpected HTML or text response. Check your console output for details.`
782
+ );
783
+ }
784
+ await logResponseError(err.response, false);
785
+ throw new ResponseError(
786
+ err.response,
787
+ "The Ory API endpoint returned unexpected content type `" + contentType + "`. Check your console output for details."
788
+ );
789
+ };
790
+ async function toBody(response) {
791
+ try {
792
+ return await response.clone().json();
793
+ } catch (e) {
794
+ await logResponseError(response, true, [e]);
795
+ throw new ResponseError(
796
+ response,
797
+ "Unable to decode API response using JSON."
798
+ );
799
+ }
800
+ }
801
+ async function logResponseError(response, printBody, wrap) {
802
+ console.error("Unable to decode API response", {
803
+ response: {
804
+ status: response.status,
805
+ headers: Object.fromEntries(response.headers.entries()),
806
+ body: printBody ? await response.clone().text() : void 0
807
+ },
808
+ errors: wrap
809
+ });
810
+ }
679
811
 
680
812
  // src/util/onSubmitLogin.ts
681
813
  async function onSubmitLogin({ flow }, config, {
@@ -711,7 +843,8 @@ async function onSubmitLogin({ flow }, config, {
711
843
  flowType: FlowType.Login
712
844
  });
713
845
  },
714
- onRedirect
846
+ onRedirect,
847
+ config
715
848
  })
716
849
  );
717
850
  }
@@ -755,7 +888,8 @@ async function onSubmitRecovery({ flow }, config, {
755
888
  });
756
889
  }
757
890
  },
758
- onRedirect
891
+ onRedirect,
892
+ config
759
893
  })
760
894
  );
761
895
  }
@@ -804,7 +938,8 @@ async function onSubmitRegistration({ flow }, config, {
804
938
  flowType: FlowType.Registration
805
939
  });
806
940
  },
807
- onRedirect
941
+ onRedirect,
942
+ config
808
943
  })
809
944
  );
810
945
  }
@@ -843,10 +978,11 @@ async function onSubmitSettings({ flow }, config, {
843
978
  flowType: FlowType.Settings
844
979
  });
845
980
  },
846
- onRedirect
981
+ onRedirect,
982
+ config
847
983
  })
848
984
  ).catch((err) => {
849
- if (isResponseError(err)) {
985
+ if (isResponseError$1(err)) {
850
986
  if (err.response.status === 401) {
851
987
  return onRedirect(
852
988
  loginUrl(config) + "?return_to=" + settingsUrl(config),
@@ -876,7 +1012,7 @@ async function onSubmitVerification({ flow }, config, {
876
1012
  if (useFlowId) {
877
1013
  replaceWindowFlowId(useFlowId);
878
1014
  } else {
879
- onRedirect(verificationUrl(config), true);
1015
+ onRedirect(verificationUrl$1(config), true);
880
1016
  }
881
1017
  },
882
1018
  onValidationError: (body2) => {
@@ -885,7 +1021,8 @@ async function onSubmitVerification({ flow }, config, {
885
1021
  flowType: FlowType.Verification
886
1022
  });
887
1023
  },
888
- onRedirect
1024
+ onRedirect,
1025
+ config
889
1026
  })
890
1027
  );
891
1028
  }
@@ -1142,7 +1279,20 @@ var NodeInput = ({
1142
1279
  case UiNodeInputAttributesTypeEnum.Submit:
1143
1280
  case UiNodeInputAttributesTypeEnum.Button:
1144
1281
  if (isSocial) {
1145
- return null;
1282
+ return /* @__PURE__ */ jsx(
1283
+ Node2.OidcButton,
1284
+ {
1285
+ node,
1286
+ attributes: attrs,
1287
+ onClick: () => {
1288
+ setValue(
1289
+ "provider",
1290
+ node.attributes.value
1291
+ );
1292
+ setValue("method", node.group);
1293
+ }
1294
+ }
1295
+ );
1146
1296
  }
1147
1297
  if (isResendNode || isScreenSelectionNode) {
1148
1298
  return null;
@@ -1232,6 +1382,37 @@ var Node = ({ node, onClick }) => {
1232
1382
  }
1233
1383
  return null;
1234
1384
  };
1385
+ function OryTwoStepCardStateMethodActive({
1386
+ formState
1387
+ }) {
1388
+ const { Form } = useComponents();
1389
+ const { flow, flowType, dispatchFormState } = useOryFlow();
1390
+ const { ui } = flow;
1391
+ const nodeSorter = useNodeSorter();
1392
+ const sortNodes = (a, b) => nodeSorter(a, b, { flowType });
1393
+ const groupsToShow = useNodeGroupsWithVisibleNodes(ui.nodes);
1394
+ const finalNodes = getFinalNodes(groupsToShow, formState.method);
1395
+ return /* @__PURE__ */ jsxs(OryCard, { children: [
1396
+ /* @__PURE__ */ jsx(OryCardHeader, {}),
1397
+ /* @__PURE__ */ jsxs(OryCardContent, { children: [
1398
+ /* @__PURE__ */ jsx(OryCardValidationMessages, {}),
1399
+ /* @__PURE__ */ jsx(
1400
+ OryForm,
1401
+ {
1402
+ "data-testid": `ory/form/methods/local`,
1403
+ onAfterSubmit: handleAfterFormSubmit(dispatchFormState),
1404
+ children: /* @__PURE__ */ jsxs(Form.Group, { children: [
1405
+ ui.nodes.filter(
1406
+ (n) => isUiNodeScriptAttributes(n.attributes) || n.group === UiNodeGroupEnum.Default || n.group === UiNodeGroupEnum.Profile
1407
+ ).map((node, k) => /* @__PURE__ */ jsx(Node, { node }, k)),
1408
+ finalNodes.sort(sortNodes).map((node, k) => /* @__PURE__ */ jsx(Node, { node }, k))
1409
+ ] })
1410
+ }
1411
+ )
1412
+ ] }),
1413
+ /* @__PURE__ */ jsx(OryCardFooter, {})
1414
+ ] });
1415
+ }
1235
1416
  function OryFormOidcButtons() {
1236
1417
  const {
1237
1418
  flow: { ui }
@@ -1262,8 +1443,10 @@ function OryFormOidcButtons() {
1262
1443
  }
1263
1444
  function OryFormSocialButtonsForm() {
1264
1445
  const {
1265
- flow: { ui }
1446
+ flow: { ui },
1447
+ formState
1266
1448
  } = useOryFlow();
1449
+ console.log(formState);
1267
1450
  const filteredNodes = ui.nodes.filter(
1268
1451
  (node) => node.group === UiNodeGroupEnum.Saml || node.group === UiNodeGroupEnum.Oidc
1269
1452
  );
@@ -1272,39 +1455,6 @@ function OryFormSocialButtonsForm() {
1272
1455
  }
1273
1456
  return /* @__PURE__ */ jsx(OryFormProvider, { children: /* @__PURE__ */ jsx(OryForm, { "data-testid": `ory/form/methods/oidc-saml`, children: /* @__PURE__ */ jsx(OryFormOidcButtons, {}) }) });
1274
1457
  }
1275
- function OryTwoStepCardStateMethodActive({
1276
- formState
1277
- }) {
1278
- const { Form } = useComponents();
1279
- const { flow, flowType, dispatchFormState } = useOryFlow();
1280
- const { ui } = flow;
1281
- const nodeSorter = useNodeSorter();
1282
- const sortNodes = (a, b) => nodeSorter(a, b, { flowType });
1283
- const groupsToShow = useNodeGroupsWithVisibleNodes(ui.nodes);
1284
- const finalNodes = getFinalNodes(groupsToShow, formState.method);
1285
- const selectedMethodIsSocial = formState.method === UiNodeGroupEnum.Oidc || formState.method === UiNodeGroupEnum.Saml;
1286
- return /* @__PURE__ */ jsxs(OryCard, { children: [
1287
- /* @__PURE__ */ jsx(OryCardHeader, {}),
1288
- /* @__PURE__ */ jsxs(OryCardContent, { children: [
1289
- /* @__PURE__ */ jsx(OryCardValidationMessages, {}),
1290
- selectedMethodIsSocial && /* @__PURE__ */ jsx(OryFormSocialButtonsForm, {}),
1291
- /* @__PURE__ */ jsx(
1292
- OryForm,
1293
- {
1294
- "data-testid": `ory/form/methods/local`,
1295
- onAfterSubmit: handleAfterFormSubmit(dispatchFormState),
1296
- children: /* @__PURE__ */ jsxs(Form.Group, { children: [
1297
- ui.nodes.filter(
1298
- (n) => isUiNodeScriptAttributes(n.attributes) || n.group === UiNodeGroupEnum.Default || n.group === UiNodeGroupEnum.Profile
1299
- ).map((node, k) => /* @__PURE__ */ jsx(Node, { node }, k)),
1300
- finalNodes.sort(sortNodes).map((node, k) => /* @__PURE__ */ jsx(Node, { node }, k))
1301
- ] })
1302
- }
1303
- )
1304
- ] }),
1305
- /* @__PURE__ */ jsx(OryCardFooter, {})
1306
- ] });
1307
- }
1308
1458
  function OryTwoStepCardStateProvideIdentifier() {
1309
1459
  const { Form, Card } = useComponents();
1310
1460
  const { flowType, flow, dispatchFormState } = useOryFlow();