@stoplight/elements-core 7.12.3 → 7.13.1

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.
@@ -2,9 +2,10 @@ import { HttpSecurityScheme } from '@stoplight/types';
2
2
  import * as React from 'react';
3
3
  import { HttpSecuritySchemeWithValues } from './authentication-utils';
4
4
  interface TryItAuthProps {
5
- operationSecurityScheme: HttpSecurityScheme[][];
6
- onChange: (authObject: HttpSecuritySchemeWithValues | undefined) => void;
7
- value: HttpSecuritySchemeWithValues | undefined;
5
+ operationSecuritySchemes: HttpSecurityScheme[][];
6
+ operationAuthValue: HttpSecuritySchemeWithValues[] | undefined;
7
+ setOperationAuthValue: React.Dispatch<HttpSecuritySchemeWithValues | undefined>;
8
+ setCurrentScheme: React.Dispatch<HttpSecuritySchemeWithValues[] | undefined>;
8
9
  }
9
10
  export declare const TryItAuth: React.FC<TryItAuthProps>;
10
11
  export {};
@@ -12,6 +12,8 @@ export declare const isDigestSecurityScheme: (maybeIBearer: HttpSecurityScheme)
12
12
  export declare function filterOutAuthorizationParams(queryParams: IHttpQueryParam[], securitySchemes?: HttpSecurityScheme[][]): IHttpQueryParam[];
13
13
  export declare function filterOutAuthorizationParams(queryParams: IHttpHeaderParam[], securitySchemes?: HttpSecurityScheme[][]): IHttpHeaderParam[];
14
14
  export declare const usePersistedSecuritySchemeWithValues: () => [
15
- HttpSecuritySchemeWithValues | undefined,
16
- React.Dispatch<HttpSecuritySchemeWithValues | undefined>
15
+ HttpSecuritySchemeWithValues[] | undefined,
16
+ React.Dispatch<HttpSecuritySchemeWithValues | undefined>,
17
+ React.Dispatch<HttpSecuritySchemeWithValues[] | undefined>
17
18
  ];
19
+ export declare const createUndefinedValuedSchemes: (schemes: HttpSecurityScheme[]) => HttpSecuritySchemeWithValues[];
@@ -10,7 +10,7 @@ interface BuildRequestInput {
10
10
  serverVariableValues: Dictionary<string, string>;
11
11
  bodyInput?: BodyParameterValues | string;
12
12
  mockData?: MockData;
13
- auth?: HttpSecuritySchemeWithValues;
13
+ auth?: HttpSecuritySchemeWithValues[];
14
14
  chosenServer?: IServer | null;
15
15
  credentials?: 'omit' | 'include' | 'same-origin';
16
16
  corsProxy?: string;
package/index.esm.js CHANGED
@@ -19,9 +19,9 @@ import { atom, useAtom, Provider } from 'jotai';
19
19
  import URI from 'urijs';
20
20
  import { CodeViewer } from '@stoplight/mosaic-code-viewer';
21
21
  import { isValidTargetId, HTTPSnippet } from 'httpsnippet-lite';
22
- import flatten from 'lodash/flatten.js';
23
22
  import capitalize from 'lodash/capitalize.js';
24
23
  import filter from 'lodash/filter.js';
24
+ import flatten from 'lodash/flatten.js';
25
25
  import { nanoid } from 'nanoid';
26
26
  import curry from 'lodash/curry.js';
27
27
  import omit from 'lodash/omit.js';
@@ -877,15 +877,34 @@ function getReadableSecurityName(securityScheme, includeKey = false) {
877
877
  case 'mutualTLS':
878
878
  name = 'Mutual TLS';
879
879
  break;
880
+ case undefined:
881
+ name = 'None';
882
+ break;
880
883
  }
881
884
  return includeKey ? `${name} (${securityScheme.key})` : name;
882
885
  }
886
+ function getReadableSecurityNames(securitySchemes, includeKey = false) {
887
+ if (securitySchemes.length === 0)
888
+ return 'None';
889
+ let name = '';
890
+ for (let i = 0; i < securitySchemes.length; i++) {
891
+ if (i > 0)
892
+ name += ' & ';
893
+ name += getReadableSecurityName(securitySchemes[i], shouldIncludeKey(securitySchemes, securitySchemes[i].type));
894
+ }
895
+ return includeKey ? `${name} (${securitySchemes[0].key})` : name;
896
+ }
883
897
  const isOAuth2ImplicitFlow = (maybeFlow) => isObject(maybeFlow) && 'authorizationUrl' in maybeFlow && !('tokenUrl' in maybeFlow);
884
898
  const isOauth2AuthorizationCodeFlow = (maybeFlow) => isObject(maybeFlow) && 'authorizationUrl' in maybeFlow && 'tokenUrl' in maybeFlow;
885
899
  const isOauth2ClientCredentialsOrPasswordFlow = (maybeFlow) => isObject(maybeFlow) && !('authorizationUrl' in maybeFlow) && 'tokenUrl' in maybeFlow;
886
900
  function shouldIncludeKey(schemes, type) {
887
901
  return filter(schemes, { type }).length > 1;
888
- }
902
+ }
903
+ const shouldAddKey = (auth, operationSecuritySchemes) => {
904
+ if (auth.length !== 1)
905
+ return false;
906
+ return shouldIncludeKey(flatten(operationSecuritySchemes.filter(scheme => scheme.length === 1)), auth[0].type);
907
+ };
889
908
 
890
909
  const useUniqueId = (prefix = 'id_') => React.useRef(`${prefix}${nanoid(8)}`).current;
891
910
 
@@ -899,16 +918,73 @@ const AuthTokenInput = ({ type, name, value, onChange }) => {
899
918
  };
900
919
 
901
920
  const APIKeyAuth = ({ scheme, onChange, value }) => {
902
- return (React.createElement(Panel.Content, { className: "ParameterGrid" },
921
+ return (React.createElement(Panel.Content, { className: "ParameterGrid", "data-test": "auth-try-it-row" },
903
922
  React.createElement(AuthTokenInput, { type: "apiKey", name: scheme.name, value: value, onChange: onChange })));
904
923
  };
905
924
 
925
+ const caseInsensitivelyEquals = curry((a, b) => a.toUpperCase() === b.toUpperCase());
926
+ function slugify(name) {
927
+ return name
928
+ .replace(/\/|{|}|\s/g, '-')
929
+ .replace(/-{2,}/, '-')
930
+ .replace(/^-/, '')
931
+ .replace(/-$/, '');
932
+ }
933
+
934
+ const isApiKeySecurityScheme = (maybeIApiKey) => isObject(maybeIApiKey) && maybeIApiKey.type === 'apiKey';
935
+ const isOAuth2SecurityScheme = (maybeIOAuth2) => isObject(maybeIOAuth2) && maybeIOAuth2.type === 'oauth2';
936
+ const isBasicSecurityScheme = (maybeIBasic) => isObject(maybeIBasic) && maybeIBasic.type === 'http' && maybeIBasic.scheme === 'basic';
937
+ const isBearerSecurityScheme = (maybeIBearer) => isObject(maybeIBearer) && maybeIBearer.type === 'http' && maybeIBearer.scheme === 'bearer';
938
+ const isDigestSecurityScheme = (maybeIBearer) => isObject(maybeIBearer) && maybeIBearer.type === 'http' && maybeIBearer.scheme === 'digest';
939
+ function filterOutAuthorizationParams(queryParams, securitySchemes = []) {
940
+ const flattenedSecuritySchemes = flatten(securitySchemes);
941
+ const securitySchemeNames = getSecuritySchemeNames(flattenedSecuritySchemes);
942
+ return queryParams.filter(queryParam => !securitySchemeNames.some(caseInsensitivelyEquals(queryParam.name)));
943
+ }
944
+ const getSecuritySchemeNames = (securitySchemes) => securitySchemes.flatMap(scheme => {
945
+ if (isApiKeySecurityScheme(scheme)) {
946
+ return scheme.name;
947
+ }
948
+ if (isOAuth2SecurityScheme(scheme)) {
949
+ return 'Authorization';
950
+ }
951
+ return [];
952
+ });
953
+ const securitySchemeValuesAtom = persistAtom('TryIt_securitySchemeValues', atom({}));
954
+ const usePersistedSecuritySchemeWithValues = () => {
955
+ const [currentScheme, setCurrentScheme] = React__default.useState();
956
+ const [securitySchemeValues, setSecuritySchemeValues] = useAtom(securitySchemeValuesAtom);
957
+ const setPersistedAuthenticationSettings = (securitySchemeWithValues) => {
958
+ if (securitySchemeWithValues) {
959
+ const key = securitySchemeWithValues.scheme.key;
960
+ const value = securitySchemeWithValues.authValue;
961
+ if (value !== undefined) {
962
+ setSecuritySchemeValues(Object.assign(Object.assign({}, securitySchemeValues), { [key]: value }));
963
+ }
964
+ }
965
+ };
966
+ const schemeWithPersistedValue = React__default.useMemo(() => {
967
+ if (!currentScheme)
968
+ return undefined;
969
+ return currentScheme.map(scheme => {
970
+ return {
971
+ scheme: scheme.scheme,
972
+ authValue: securitySchemeValues[scheme.scheme.key],
973
+ };
974
+ });
975
+ }, [currentScheme, securitySchemeValues]);
976
+ return [schemeWithPersistedValue, setPersistedAuthenticationSettings, setCurrentScheme];
977
+ };
978
+ const createUndefinedValuedSchemes = (schemes) => {
979
+ return schemes.map(scheme => ({ scheme, authValue: undefined }));
980
+ };
981
+
906
982
  const BasicAuth = ({ onChange, value }) => {
907
983
  const [username = '', password = ''] = decode(value).split(':');
908
984
  const onCredentialsChange = (username, password) => {
909
985
  onChange(encode(`${username}:${password}`));
910
986
  };
911
- return (React.createElement(Panel.Content, { className: "ParameterGrid" },
987
+ return (React.createElement(Panel.Content, { className: "ParameterGrid", "data-test": "auth-try-it-row" },
912
988
  React.createElement("div", null, "Username"),
913
989
  React.createElement(Text, { mx: 3 }, ":"),
914
990
  React.createElement(Flex, { flex: 1 },
@@ -931,7 +1007,7 @@ function decode(encoded) {
931
1007
  }
932
1008
 
933
1009
  const BearerAuth = ({ value, onChange }) => {
934
- return (React.createElement(Panel.Content, { className: "ParameterGrid" },
1010
+ return (React.createElement(Panel.Content, { className: "ParameterGrid", "data-test": "auth-try-it-row" },
935
1011
  React.createElement(AuthTokenInput, { type: "http", name: "Token", value: value, onChange: onChange })));
936
1012
  };
937
1013
 
@@ -946,63 +1022,78 @@ const digestPlaceholder = `Digest username="User Name",
946
1022
  opaque="5ccc069c403ebaf9f0171e9517f40e41"
947
1023
  `;
948
1024
  const DigestAuth = ({ onChange, value }) => {
949
- return (React.createElement(Panel.Content, { className: "ParameterGrid" },
1025
+ return (React.createElement(Panel.Content, { className: "ParameterGrid", "data-test": "auth-try-it-row" },
950
1026
  React.createElement("div", null, "Authorization"),
951
1027
  React.createElement(Text, { mx: 3 }, ":"),
952
1028
  React.createElement("textarea", { className: "sl-relative sl-z-10 sl-w-full sl-text-base sl-bg-canvas-100 sl-p-1 sl-pr-2.5 sl-pl-2.5 sl-rounded sl-border-transparent hover:sl-border-input focus:sl-border-primary sl-border", "aria-label": "Authorization", placeholder: digestPlaceholder, value: value, onChange: e => onChange(e.currentTarget.value), rows: 9 })));
953
1029
  };
954
1030
 
955
1031
  const OAuth2Auth = ({ value, onChange }) => {
956
- return (React.createElement(Panel.Content, { className: "ParameterGrid" },
1032
+ return (React.createElement(Panel.Content, { className: "ParameterGrid", "data-test": "auth-try-it-row" },
957
1033
  React.createElement(AuthTokenInput, { type: "oauth2", name: "Token", value: value, onChange: onChange })));
958
1034
  };
959
1035
 
960
- function getSupportedSecurityScheme(value, supportedSecuritySchemes) {
961
- var _a;
962
- if (value && supportedSecuritySchemes.some(s => value.scheme.id === s.id)) {
963
- return [value.scheme, (_a = value.authValue) !== null && _a !== void 0 ? _a : ''];
1036
+ const checkViableCurrentAuth = (current, operationSecuritySchemes) => {
1037
+ if (current === undefined)
1038
+ return false;
1039
+ const flattened = operationSecuritySchemes.flat(1);
1040
+ for (const element of current) {
1041
+ if (!flattened.some(flat => flat.id === element.scheme.id))
1042
+ return false;
964
1043
  }
965
- return [supportedSecuritySchemes[0], ''];
966
- }
967
- const TryItAuth = ({ operationSecurityScheme: operationAuth, onChange, value }) => {
968
- const operationSecurityArray = flatten(operationAuth);
969
- const filteredSecurityItems = operationSecurityArray.filter(scheme => securitySchemeKeys.includes(scheme === null || scheme === void 0 ? void 0 : scheme.type));
970
- const [securityScheme, authValue] = getSupportedSecurityScheme(value, filteredSecurityItems);
971
- const menuName = securityScheme ? getReadableSecurityName(securityScheme) : 'Security Scheme';
972
- const handleChange = (authValue) => {
973
- onChange(securityScheme && { scheme: securityScheme, authValue: authValue });
1044
+ return true;
1045
+ };
1046
+ const createMenuChild = (name, currentItemName, onPress) => {
1047
+ return {
1048
+ id: `security-scheme-${name}`,
1049
+ title: name,
1050
+ isChecked: name === currentItemName,
1051
+ onPress,
1052
+ };
1053
+ };
1054
+ const TryItAuth = ({ operationSecuritySchemes, operationAuthValue, setOperationAuthValue, setCurrentScheme, }) => {
1055
+ const filteredSecurityItems = operationSecuritySchemes.filter(auth => auth.length === 0 || auth.every(scheme => securitySchemeKeys.includes(scheme.type)));
1056
+ const menuName = operationAuthValue
1057
+ ? getReadableSecurityNames(operationAuthValue.map(auth => auth.scheme))
1058
+ : 'Security Scheme';
1059
+ const currentName = operationAuthValue
1060
+ ? getReadableSecurityNames(operationAuthValue.map(auth => auth.scheme), shouldAddKey(operationAuthValue.map(auth => auth.scheme), operationSecuritySchemes))
1061
+ : undefined;
1062
+ const handleChange = (scheme, authValue) => {
1063
+ setOperationAuthValue({ scheme, authValue });
974
1064
  };
975
1065
  React.useEffect(() => {
976
- handleChange();
977
- }, []);
1066
+ if (checkViableCurrentAuth(operationAuthValue, operationSecuritySchemes) === false) {
1067
+ setCurrentScheme(createUndefinedValuedSchemes(operationSecuritySchemes[0]));
1068
+ }
1069
+ });
978
1070
  const menuItems = React.useMemo(() => {
979
1071
  const items = [
980
1072
  {
981
1073
  type: 'group',
982
1074
  title: 'Security Schemes',
983
- children: filteredSecurityItems.map(auth => ({
984
- id: `security-scheme-${auth.key}`,
985
- title: getReadableSecurityName(auth, shouldIncludeKey(filteredSecurityItems, auth.type)),
986
- isChecked: auth.key === (securityScheme === null || securityScheme === void 0 ? void 0 : securityScheme.key),
987
- onPress: () => {
988
- onChange({ scheme: auth, authValue: undefined });
989
- },
990
- })),
1075
+ children: filteredSecurityItems.map(auth => createMenuChild(getReadableSecurityNames(auth, shouldAddKey(auth, operationSecuritySchemes)), currentName, () => setCurrentScheme(createUndefinedValuedSchemes(auth)))),
991
1076
  },
992
1077
  ];
993
1078
  return items;
994
- }, [filteredSecurityItems, onChange, securityScheme]);
1079
+ }, [currentName, filteredSecurityItems, operationSecuritySchemes, setCurrentScheme]);
995
1080
  if (filteredSecurityItems.length === 0)
996
1081
  return null;
997
- return (React.createElement(Panel, { defaultIsOpen: true },
1082
+ return (React.createElement(Panel, { defaultIsOpen: true, "data-test": "try-it-auth" },
998
1083
  React.createElement(Panel.Titlebar, { rightComponent: filteredSecurityItems.length > 1 && (React.createElement(Menu, { "aria-label": "security-schemes", items: menuItems, closeOnPress: true, renderTrigger: ({ isOpen }) => (React.createElement(Button, { appearance: "minimal", size: "sm", iconRight: ['fas', 'sort'], active: isOpen }, menuName)) })) }, "Auth"),
999
- React.createElement(SecuritySchemeComponent, { scheme: securityScheme, onChange: handleChange, value: authValue })));
1084
+ operationAuthValue && operationAuthValue.length > 0 ? (operationAuthValue.map(scheme => {
1085
+ var _a;
1086
+ return (React.createElement(SecuritySchemeComponent, { key: scheme.scheme.key, scheme: scheme.scheme, onChange: (authValue) => handleChange(scheme.scheme, authValue), value: (_a = scheme.authValue) !== null && _a !== void 0 ? _a : '' }));
1087
+ })) : (React.createElement(OptionalMessageContainer, null))));
1000
1088
  };
1001
1089
  const GenericMessageContainer = ({ scheme }) => {
1002
- return React.createElement(Panel.Content, null,
1090
+ return React.createElement(Panel.Content, { "data-test": "auth-try-it-row" },
1003
1091
  "Coming Soon: ",
1004
1092
  getReadableSecurityName(scheme));
1005
1093
  };
1094
+ const OptionalMessageContainer = () => {
1095
+ return React.createElement(Panel.Content, null, "No auth selected");
1096
+ };
1006
1097
  const SecuritySchemeComponent = (_a) => {
1007
1098
  var { scheme } = _a, rest = __rest(_a, ["scheme"]);
1008
1099
  switch (scheme.type) {
@@ -1027,59 +1118,6 @@ const SecuritySchemeComponent = (_a) => {
1027
1118
  };
1028
1119
  const securitySchemeKeys = ['apiKey', 'http', 'oauth2', 'openIdConnect'];
1029
1120
 
1030
- const caseInsensitivelyEquals = curry((a, b) => a.toUpperCase() === b.toUpperCase());
1031
- function slugify(name) {
1032
- return name
1033
- .replace(/\/|{|}|\s/g, '-')
1034
- .replace(/-{2,}/, '-')
1035
- .replace(/^-/, '')
1036
- .replace(/-$/, '');
1037
- }
1038
-
1039
- const isApiKeySecurityScheme = (maybeIApiKey) => isObject(maybeIApiKey) && maybeIApiKey.type === 'apiKey';
1040
- const isOAuth2SecurityScheme = (maybeIOAuth2) => isObject(maybeIOAuth2) && maybeIOAuth2.type === 'oauth2';
1041
- const isBasicSecurityScheme = (maybeIBasic) => isObject(maybeIBasic) && maybeIBasic.type === 'http' && maybeIBasic.scheme === 'basic';
1042
- const isBearerSecurityScheme = (maybeIBearer) => isObject(maybeIBearer) && maybeIBearer.type === 'http' && maybeIBearer.scheme === 'bearer';
1043
- const isDigestSecurityScheme = (maybeIBearer) => isObject(maybeIBearer) && maybeIBearer.type === 'http' && maybeIBearer.scheme === 'digest';
1044
- function filterOutAuthorizationParams(queryParams, securitySchemes = []) {
1045
- const flattenedSecuritySchemes = flatten(securitySchemes);
1046
- const securitySchemeNames = getSecuritySchemeNames(flattenedSecuritySchemes);
1047
- return queryParams.filter(queryParam => !securitySchemeNames.some(caseInsensitivelyEquals(queryParam.name)));
1048
- }
1049
- const getSecuritySchemeNames = (securitySchemes) => securitySchemes.flatMap(scheme => {
1050
- if (isApiKeySecurityScheme(scheme)) {
1051
- return scheme.name;
1052
- }
1053
- if (isOAuth2SecurityScheme(scheme)) {
1054
- return 'Authorization';
1055
- }
1056
- return [];
1057
- });
1058
- const securitySchemeValuesAtom = persistAtom('TryIt_securitySchemeValues', atom({}));
1059
- const usePersistedSecuritySchemeWithValues = () => {
1060
- const [currentScheme, setCurrentScheme] = React__default.useState();
1061
- const [securitySchemeValues, setSecuritySchemeValues] = useAtom(securitySchemeValuesAtom);
1062
- const setPersistedAuthenticationSettings = (securitySchemeWithValues) => {
1063
- setCurrentScheme(securitySchemeWithValues);
1064
- if (securitySchemeWithValues) {
1065
- const key = securitySchemeWithValues.scheme.key;
1066
- const value = securitySchemeWithValues.authValue;
1067
- if (value !== undefined) {
1068
- setSecuritySchemeValues(Object.assign(Object.assign({}, securitySchemeValues), { [key]: value }));
1069
- }
1070
- }
1071
- };
1072
- const persistedSecuritySchemeValue = currentScheme && securitySchemeValues[currentScheme.scheme.key];
1073
- const schemeWithPersistedValue = React__default.useMemo(() => {
1074
- if (!currentScheme)
1075
- return undefined;
1076
- if (currentScheme.authValue)
1077
- return currentScheme;
1078
- return Object.assign(Object.assign({}, currentScheme), { authValue: persistedSecuritySchemeValue });
1079
- }, [currentScheme, persistedSecuritySchemeValue]);
1080
- return [schemeWithPersistedValue, setPersistedAuthenticationSettings];
1081
- };
1082
-
1083
1121
  const FileUploadParameterEditor = ({ parameter, value, onChange }) => {
1084
1122
  var _a;
1085
1123
  const parameterDisplayName = `${parameter.name}${parameter.required ? '*' : ''}`;
@@ -1564,50 +1602,52 @@ function buildFetchRequest({ httpOperation, mediaTypeContent, bodyInput, paramet
1564
1602
  ];
1565
1603
  });
1566
1604
  }
1567
- const runAuthRequestEhancements = (auth, queryParams, headers) => {
1568
- var _a, _b, _c, _d, _e;
1569
- if (!auth)
1605
+ const runAuthRequestEhancements = (auths, queryParams, headers) => {
1606
+ if (!auths)
1570
1607
  return [queryParams, headers];
1571
1608
  const newQueryParams = [...queryParams];
1572
1609
  const newHeaders = [...headers];
1573
- if (isApiKeySecurityScheme(auth.scheme)) {
1574
- if (auth.scheme.in === 'query') {
1575
- newQueryParams.push({
1576
- name: auth.scheme.name,
1577
- value: (_a = auth.authValue) !== null && _a !== void 0 ? _a : '',
1610
+ auths.forEach(auth => {
1611
+ var _a, _b, _c, _d, _e;
1612
+ if (isApiKeySecurityScheme(auth.scheme)) {
1613
+ if (auth.scheme.in === 'query') {
1614
+ newQueryParams.push({
1615
+ name: auth.scheme.name,
1616
+ value: (_a = auth.authValue) !== null && _a !== void 0 ? _a : '',
1617
+ });
1618
+ }
1619
+ if (auth.scheme.in === 'header') {
1620
+ newHeaders.push({
1621
+ name: auth.scheme.name,
1622
+ value: (_b = auth.authValue) !== null && _b !== void 0 ? _b : '',
1623
+ });
1624
+ }
1625
+ }
1626
+ if (isOAuth2SecurityScheme(auth.scheme)) {
1627
+ newHeaders.push({
1628
+ name: 'Authorization',
1629
+ value: (_c = auth.authValue) !== null && _c !== void 0 ? _c : '',
1578
1630
  });
1579
1631
  }
1580
- if (auth.scheme.in === 'header') {
1632
+ if (isBearerSecurityScheme(auth.scheme)) {
1581
1633
  newHeaders.push({
1582
- name: auth.scheme.name,
1583
- value: (_b = auth.authValue) !== null && _b !== void 0 ? _b : '',
1634
+ name: 'Authorization',
1635
+ value: `Bearer ${auth.authValue}`,
1584
1636
  });
1585
1637
  }
1586
- }
1587
- if (isOAuth2SecurityScheme(auth.scheme)) {
1588
- newHeaders.push({
1589
- name: 'Authorization',
1590
- value: (_c = auth.authValue) !== null && _c !== void 0 ? _c : '',
1591
- });
1592
- }
1593
- if (isBearerSecurityScheme(auth.scheme)) {
1594
- newHeaders.push({
1595
- name: 'Authorization',
1596
- value: `Bearer ${auth.authValue}`,
1597
- });
1598
- }
1599
- if (isDigestSecurityScheme(auth.scheme)) {
1600
- newHeaders.push({
1601
- name: 'Authorization',
1602
- value: (_e = (_d = auth.authValue) === null || _d === void 0 ? void 0 : _d.replace(/\s\s+/g, ' ').trim()) !== null && _e !== void 0 ? _e : '',
1603
- });
1604
- }
1605
- if (isBasicSecurityScheme(auth.scheme)) {
1606
- newHeaders.push({
1607
- name: 'Authorization',
1608
- value: `Basic ${auth.authValue}`,
1609
- });
1610
- }
1638
+ if (isDigestSecurityScheme(auth.scheme)) {
1639
+ newHeaders.push({
1640
+ name: 'Authorization',
1641
+ value: (_e = (_d = auth.authValue) === null || _d === void 0 ? void 0 : _d.replace(/\s\s+/g, ' ').trim()) !== null && _e !== void 0 ? _e : '',
1642
+ });
1643
+ }
1644
+ if (isBasicSecurityScheme(auth.scheme)) {
1645
+ newHeaders.push({
1646
+ name: 'Authorization',
1647
+ value: `Basic ${auth.authValue}`,
1648
+ });
1649
+ }
1650
+ });
1611
1651
  return [newQueryParams, newHeaders];
1612
1652
  };
1613
1653
  function buildHarRequest({ httpOperation, bodyInput, parameterValues, serverVariableValues, mediaTypeContent, auth, mockData, chosenServer, corsProxy, }) {
@@ -1987,9 +2027,9 @@ const VariableEditor = ({ variable, value, onChange }) => {
1987
2027
  };
1988
2028
 
1989
2029
  const ServerVariables = ({ variables, values, onChangeValue }) => {
1990
- return (React.createElement(Panel, { defaultIsOpen: true },
2030
+ return (React.createElement(Panel, { defaultIsOpen: true, "data-test": "server-vars-try-it" },
1991
2031
  React.createElement(Panel.Titlebar, null, "Server Variables"),
1992
- React.createElement(Panel.Content, { className: "sl-overflow-y-auto ParameterGrid ServerVariablesContent" }, variables.map(variable => (React.createElement(VariableEditor, { key: variable.name, variable: variable, value: values[variable.name], onChange: (value) => {
2032
+ React.createElement(Panel.Content, { className: "sl-overflow-y-auto ParameterGrid ServerVariablesContent" }, variables.map(variable => (React.createElement(VariableEditor, { key: variable.name, "data-test": "server-vars-try-it-row", variable: variable, value: values[variable.name], onChange: (value) => {
1993
2033
  const actualValue = String(value);
1994
2034
  onChangeValue(variable.enum || actualValue !== '' ? 'set' : 'unset', variable.name, actualValue);
1995
2035
  } }))))));
@@ -1997,7 +2037,7 @@ const ServerVariables = ({ variables, values, onChangeValue }) => {
1997
2037
 
1998
2038
  const defaultServers = [];
1999
2039
  const TryIt = ({ httpOperation, mockUrl, onRequestChange, requestBodyIndex, embeddedInMd = false, tryItCredentialsPolicy, corsProxy, }) => {
2000
- var _a, _b, _c, _d, _e, _f, _g;
2040
+ var _a, _b, _c, _d, _e, _f;
2001
2041
  TryIt.displayName = 'TryIt';
2002
2042
  const isDark = useThemeIsDark();
2003
2043
  const [response, setResponse] = React.useState();
@@ -2009,7 +2049,7 @@ const TryIt = ({ httpOperation, mockUrl, onRequestChange, requestBodyIndex, embe
2009
2049
  const [mockingOptions, setMockingOptions] = useMockingOptions();
2010
2050
  const [bodyParameterValues, setBodyParameterValues, isAllowedEmptyValues, setAllowedEmptyValues, formDataState] = useBodyParameterState(mediaTypeContent);
2011
2051
  const [textRequestBody, setTextRequestBody] = useTextRequestBodyState(mediaTypeContent);
2012
- const [operationAuthValue, setOperationAuthValue] = usePersistedSecuritySchemeWithValues();
2052
+ const [operationAuthValue, setOperationAuthValue, setCurrentScheme] = usePersistedSecuritySchemeWithValues();
2013
2053
  const servers = React.useMemo(() => {
2014
2054
  return getServersToDisplay(httpOperation.servers || defaultServers, mockUrl, false);
2015
2055
  }, [httpOperation.servers, mockUrl]);
@@ -2117,10 +2157,10 @@ const TryIt = ({ httpOperation, mockUrl, onRequestChange, requestBodyIndex, embe
2117
2157
  });
2118
2158
  const isOnlySendButton = !((_d = httpOperation.security) === null || _d === void 0 ? void 0 : _d.length) && !allParameters.length && !formDataState.isFormDataBody && !mediaTypeContent;
2119
2159
  const tryItPanelContents = (React.createElement(React.Fragment, null,
2120
- ((_e = httpOperation.security) === null || _e === void 0 ? void 0 : _e.length) ? (React.createElement(TryItAuth, { onChange: setOperationAuthValue, operationSecurityScheme: (_f = httpOperation.security) !== null && _f !== void 0 ? _f : [], value: operationAuthValue })) : null,
2160
+ ((_e = httpOperation.security) === null || _e === void 0 ? void 0 : _e.length) ? (React.createElement(TryItAuth, { operationSecuritySchemes: httpOperation.security, operationAuthValue: operationAuthValue, setOperationAuthValue: setOperationAuthValue, setCurrentScheme: setCurrentScheme })) : null,
2121
2161
  serverVariables.length > 0 && (React.createElement(ServerVariables, { variables: serverVariables, values: serverVariableValues, onChangeValue: updateServerVariableValue })),
2122
2162
  allParameters.length > 0 && (React.createElement(OperationParameters, { parameters: allParameters, values: parameterValuesWithDefaults, onChangeValue: updateParameterValue, validate: validateParameters })),
2123
- formDataState.isFormDataBody ? (React.createElement(FormDataBody, { specification: formDataState.bodySpecification, values: bodyParameterValues, onChangeValues: setBodyParameterValues, onChangeParameterAllow: setAllowedEmptyValues, isAllowedEmptyValues: isAllowedEmptyValues })) : mediaTypeContent ? (React.createElement(RequestBody, { examples: (_g = mediaTypeContent.examples) !== null && _g !== void 0 ? _g : [], requestBody: textRequestBody, onChange: setTextRequestBody })) : null,
2163
+ formDataState.isFormDataBody ? (React.createElement(FormDataBody, { specification: formDataState.bodySpecification, values: bodyParameterValues, onChangeValues: setBodyParameterValues, onChangeParameterAllow: setAllowedEmptyValues, isAllowedEmptyValues: isAllowedEmptyValues })) : mediaTypeContent ? (React.createElement(RequestBody, { examples: (_f = mediaTypeContent.examples) !== null && _f !== void 0 ? _f : [], requestBody: textRequestBody, onChange: setTextRequestBody })) : null,
2124
2164
  React.createElement(Panel.Content, { className: "SendButtonHolder", mt: 4, pt: !isOnlySendButton && !embeddedInMd ? 0 : undefined },
2125
2165
  React.createElement(HStack, { alignItems: "center", spacing: 2 },
2126
2166
  React.createElement(Button, { appearance: "primary", loading: loading, disabled: loading, onPress: handleSendRequest, size: "sm" }, "Send API Request"),
@@ -2403,7 +2443,7 @@ const Request = ({ operation: { request, request: { path: pathParams = [], heade
2403
2443
  if (!request || typeof request !== 'object')
2404
2444
  return null;
2405
2445
  const bodyIsEmpty = isBodyEmpty(body);
2406
- const securitySchemes = flatten(security);
2446
+ const securitySchemes = security !== null && security !== void 0 ? security : [];
2407
2447
  const hasRequestData = Boolean(securitySchemes.length ||
2408
2448
  pathParams.length ||
2409
2449
  queryParams.length ||
@@ -2431,19 +2471,25 @@ const Request = ({ operation: { request, request: { path: pathParams = [], heade
2431
2471
  };
2432
2472
  Request.displayName = 'HttpOperation.Request';
2433
2473
  const schemeExpandedState = atomWithStorage('HttpOperation_security_expanded', {});
2434
- const SecurityPanel = ({ scheme, includeKey }) => {
2474
+ const SecurityPanel = ({ schemes, includeKey }) => {
2435
2475
  const [expandedState, setExpanded] = useAtom(schemeExpandedState);
2436
- return (React.createElement(SubSectionPanel, { title: `Security: ${getReadableSecurityName(scheme, includeKey)}`, defaultIsOpen: !!expandedState[scheme.key], onChange: isOpen => setExpanded(Object.assign(Object.assign({}, expandedState), { [scheme.key]: isOpen })) },
2437
- React.createElement(MarkdownViewer, { style: { fontSize: 12 }, markdown: `${scheme.description || ''}\n\n` + getDefaultDescription(scheme) })));
2476
+ const { nodeHasChanged } = useOptionsCtx();
2477
+ const collection = schemes.length > 1;
2478
+ return (React.createElement(SubSectionPanel, { title: `Security: ${getReadableSecurityNames(schemes, includeKey)}`, defaultIsOpen: !!expandedState[getReadableSecurityNames(schemes)], onChange: isOpen => setExpanded(Object.assign(Object.assign({}, expandedState), { [getReadableSecurityNames(schemes)]: isOpen })) },
2479
+ React.createElement(Box, { m: -2 }, schemes.map(scheme => {
2480
+ var _a;
2481
+ return (React.createElement(Box, { key: scheme.key, p: 2, m: 2, border: true },
2482
+ collection && (React.createElement(MarkdownViewer, { style: { fontWeight: 'bold', fontSize: 12, marginBottom: 10 }, markdown: getReadableSecurityName(scheme, shouldIncludeKey(schemes, scheme.type)) })),
2483
+ React.createElement(MarkdownViewer, { style: { fontSize: 12 }, markdown: `${(_a = scheme.description) !== null && _a !== void 0 ? _a : ''}\n\n` + getDefaultDescription(scheme) }),
2484
+ React.createElement(NodeAnnotation, { change: nodeHasChanged === null || nodeHasChanged === void 0 ? void 0 : nodeHasChanged({ nodeId: scheme.id }) })));
2485
+ }))));
2438
2486
  };
2439
2487
  const SecuritySchemes$1 = ({ schemes }) => {
2440
- const { nodeHasChanged } = useOptionsCtx();
2441
2488
  if (!schemes.length) {
2442
2489
  return null;
2443
2490
  }
2444
- return (React.createElement(VStack, { spacing: 3 }, schemes.map((scheme, i) => (React.createElement(Box, { pos: "relative", key: i },
2445
- React.createElement(SecurityPanel, { scheme: scheme, includeKey: shouldIncludeKey(schemes, scheme.type) }),
2446
- React.createElement(NodeAnnotation, { change: nodeHasChanged === null || nodeHasChanged === void 0 ? void 0 : nodeHasChanged({ nodeId: scheme.id }) }))))));
2491
+ return (React.createElement(VStack, { spacing: 3 }, schemes.map((scheme, i) => (React.createElement(Box, { pos: "relative", key: i, p: 0, "data-test": "security-row" },
2492
+ React.createElement(SecurityPanel, { schemes: scheme, includeKey: shouldAddKey(scheme, schemes) }))))));
2447
2493
  };
2448
2494
 
2449
2495
  const Responses = ({ responses: unsortedResponses, onStatusCodeChange, onMediaTypeChange, isCompact, }) => {
@@ -2633,7 +2679,7 @@ const ExportButton = ({ original, bundled }) => {
2633
2679
  };
2634
2680
 
2635
2681
  const SecuritySchemes = ({ schemes, defaultScheme, defaultCollapsed = false, }) => {
2636
- return (React__default.createElement(Panel, { rounded: true, isCollapsible: defaultCollapsed },
2682
+ return (React__default.createElement(Panel, { rounded: true, isCollapsible: defaultCollapsed, "data-test": "security-row" },
2637
2683
  React__default.createElement(Panel.Titlebar, { bg: "canvas-300" },
2638
2684
  React__default.createElement(Box, { as: "span", role: "heading" }, "Security")),
2639
2685
  React__default.createElement(Panel.Content, { p: 0 }, sortBy(schemes, 'type').map((scheme, i) => (React__default.createElement(SecurityScheme, { key: i, scheme: scheme, defaultIsOpen: defaultScheme ? scheme.key === defaultScheme : i === 0, isCollapsible: schemes.length > 1, showSchemeKey: shouldIncludeKey(schemes, scheme.type) }))))));
@@ -2659,7 +2705,7 @@ const ServerInfo = ({ servers, mockUrl }) => {
2659
2705
  return null;
2660
2706
  }
2661
2707
  return (React.createElement(InvertTheme, null,
2662
- React.createElement(Panel, { rounded: true, isCollapsible: false, className: "BaseURLContent", w: "full" },
2708
+ React.createElement(Panel, { rounded: true, isCollapsible: false, className: "BaseURLContent", w: "full", "data-test": "servers" },
2663
2709
  React.createElement(Panel.Titlebar, { whitespace: "nowrap" }, "API Base URL"),
2664
2710
  React.createElement(Panel.Content, { w: "full", className: "sl-flex sl-flex-col" },
2665
2711
  React.createElement(VStack, { spacing: 1, divider: true }, serversToDisplay.map((server, index) => (React.createElement(ServerUrl, Object.assign({}, server, { defaultIsOpen: index === firstServerVariableIndex, hasAnyServerVariables: firstServerVariableIndex !== -1, key: server.id })))))))));
@@ -2675,7 +2721,7 @@ const ServerUrl = ({ id, description, url, variables, hasAnyServerVariables, def
2675
2721
  e.stopPropagation();
2676
2722
  onCopy();
2677
2723
  }, [onCopy]);
2678
- return (React.createElement(Panel, { isCollapsible: !!variablesSchema, defaultIsOpen: defaultIsOpen, w: "full" },
2724
+ return (React.createElement(Panel, { isCollapsible: !!variablesSchema, defaultIsOpen: defaultIsOpen, w: "full", "data-test": "server-row" },
2679
2725
  React.createElement(Panel.Titlebar, { whitespace: "nowrap" },
2680
2726
  React.createElement(Text, { pl: titlePaddingLeft, pr: 2, fontWeight: "bold" },
2681
2727
  description,
@@ -2767,8 +2813,8 @@ const HttpServiceComponent = React.memo(({ data: unresolvedData, location = {},
2767
2813
  pathname && (layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.showPoweredByLink) && (React.createElement(PoweredByLink, { source: (_a = data.name) !== null && _a !== void 0 ? _a : 'no-title', pathname: pathname, packageType: "elements", layout: "stacked" })),
2768
2814
  React.createElement(VStack, { spacing: 6 },
2769
2815
  React.createElement(ServerInfo, { servers: (_b = data.servers) !== null && _b !== void 0 ? _b : [], mockUrl: mocking.mockUrl }),
2770
- React.createElement(Box, null, ((_c = data.securitySchemes) === null || _c === void 0 ? void 0 : _c.length) ? (React.createElement(SecuritySchemes, { schemes: data.securitySchemes, defaultScheme: query.get('security') || undefined })) : null),
2771
- React.createElement(Box, null, (((_d = data.contact) === null || _d === void 0 ? void 0 : _d.email) || data.license || data.termsOfService) && (React.createElement(AdditionalInfo, { id: data.id, contact: data.contact, license: data.license, termsOfService: data.termsOfService })))),
2816
+ React.createElement(Box, { "data-test": "security" }, ((_c = data.securitySchemes) === null || _c === void 0 ? void 0 : _c.length) ? (React.createElement(SecuritySchemes, { schemes: data.securitySchemes, defaultScheme: query.get('security') || undefined })) : null),
2817
+ React.createElement(Box, { "data-test": "additional-info" }, (((_d = data.contact) === null || _d === void 0 ? void 0 : _d.email) || data.license || data.termsOfService) && (React.createElement(AdditionalInfo, { id: data.id, contact: data.contact, license: data.license, termsOfService: data.termsOfService })))),
2772
2818
  data.description && (React.createElement(Box, { pos: "relative" },
2773
2819
  React.createElement(MarkdownViewer, { className: "sl-my-5", markdown: data.description }),
2774
2820
  React.createElement(NodeAnnotation, { change: descriptionChanged })))));