api-render-ui 1.1.1 → 1.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.cjs CHANGED
@@ -212,10 +212,12 @@ var GLOBAL_STYLES = `.codigma-apioperatorlist {
212
212
  align-items: center;
213
213
  align-self: stretch;
214
214
  display: inline-flex;
215
- height: 114px;
216
215
  justify-content: flex-start;
217
216
  padding-right: 5px
218
217
  }
218
+ .codigma-apiunit-request-body-info {
219
+ align-self: stretch;
220
+ }
219
221
  .codigma-apiunit-parakeyvalues {
220
222
  align-items: flex-start;
221
223
  align-self: stretch;
@@ -289,7 +291,7 @@ var ApiRenderer = class _ApiRenderer {
289
291
  }, options);
290
292
  this.container = null;
291
293
  }
292
- render(apiSpec, renderUnit = false) {
294
+ render(apiSpec, currentServer, serviceName, renderUnit = false) {
293
295
  const appendInlineStyle = (text) => {
294
296
  if (!_ApiRenderer.globalStyleInjected) {
295
297
  const styleEl = document.createElement("style");
@@ -306,7 +308,7 @@ var ApiRenderer = class _ApiRenderer {
306
308
  }
307
309
  if (apiSpec["openapi"] && apiSpec["openapi"].startsWith("3.") || apiSpec["swagger"] && apiSpec["swagger"].startsWith("2.")) {
308
310
  const countApi = countOpenAPI(apiSpec);
309
- const apiOperatorList = parseOpenAPI(apiSpec);
311
+ const apiOperatorList = parseOpenApiSpec(apiSpec, currentServer, serviceName);
310
312
  if (countApi == 1 && renderUnit) {
311
313
  this.container = createApiUnit(apiOperatorList[0]);
312
314
  } else {
@@ -371,12 +373,47 @@ var ApiRenderer = class _ApiRenderer {
371
373
  mountElement.appendChild(this.container);
372
374
  }
373
375
  };
376
+ var auths = [
377
+ {
378
+ value: "No Auth"
379
+ },
380
+ {
381
+ value: "Basic Auth",
382
+ parameters: [
383
+ {
384
+ name: "userName",
385
+ value: ""
386
+ },
387
+ {
388
+ name: "password",
389
+ value: ""
390
+ }
391
+ ]
392
+ },
393
+ {
394
+ value: "OAuth 2.0"
395
+ }
396
+ ];
397
+ var grantTypes = [
398
+ { value: "authorization_code" },
399
+ { value: "Implicit" },
400
+ { value: "Resource Owner Password Credentials" },
401
+ { value: "client_credentials" }
402
+ ];
403
+ var clientAuthenticationOpts = [
404
+ { value: "Headers", displayName: "Send credentials in headers" },
405
+ { value: "Body", displayName: "Send credentials in body" }
406
+ ];
407
+ var consumeOpts = [
408
+ { value: "None" },
409
+ { value: "application/json" },
410
+ { value: "application/xml" },
411
+ { value: "application/x-www-form-urlencoded" },
412
+ { value: "multipart/form-data" },
413
+ { value: "text/plain" }
414
+ ];
374
415
  function renderApiUnit(apiOperator, containerRef, elementMap) {
375
416
  return function(evt) {
376
- console.log("\u70B9\u51FB\u7684API\u64CD\u4F5C\uFF1A");
377
- console.log("\u65B9\u6CD5:", apiOperator.method);
378
- console.log("URL:", apiOperator.url);
379
- console.log("------------------------");
380
417
  const currentTarget = evt.currentTarget;
381
418
  if (elementMap.has(currentTarget)) {
382
419
  const newElement = elementMap.get(currentTarget);
@@ -407,7 +444,7 @@ function createApiUnit(apiOperator) {
407
444
  const paramSection = createParamSection(apiOperator);
408
445
  const headerSection = createSectionHeader(apiOperator);
409
446
  const authSection = createSectionAuth(apiOperator);
410
- const bodySection = createSectionRequestBody(apiOperator.requestBody);
447
+ const bodySection = createSectionRequestBody(apiOperator);
411
448
  reqContent.append(paramSection, headerSection, authSection, bodySection);
412
449
  apiContainer.appendChild(reqContent);
413
450
  apiContainer.appendChild(responseSection);
@@ -438,7 +475,6 @@ function createReqOperator(apiOperator) {
438
475
  reqUrl.className = "Requrl codigma-apiunit-requrl";
439
476
  reqUrl.value = apiOperator.url;
440
477
  reqUrl.addEventListener("input", (e) => {
441
- console.log("\u5F53\u524D\u503C:", e.target.value);
442
478
  apiOperator.url = e.target.value;
443
479
  });
444
480
  reqOperator.appendChild(reqUrl);
@@ -451,7 +487,6 @@ function createReqOperator(apiOperator) {
451
487
  sendText.textContent = "Send";
452
488
  sendButton.appendChild(sendText);
453
489
  sendButton.addEventListener("click", (e) => {
454
- console.log("\u5F53\u524D\u503C:", e.target.value);
455
490
  const respRef = apiOperator._responseSectionRef || null;
456
491
  sendRequest(apiOperator, respRef);
457
492
  });
@@ -518,17 +553,135 @@ function createSectionAuth(apiOperator) {
518
553
  const authValues = document.createElement("div");
519
554
  authValues.setAttribute("data-layer", "paraKeyValues");
520
555
  authValues.className = "Parakeyvalues codigma-apiunit-parakeyvalues";
521
- let auths = apiOperator.auths || [];
522
- const authTypeRow = createSelectRow(auths, authValues);
523
- if (auths.length > 0) {
524
- let parameters = apiOperator.auths[0].parameters || [];
525
- const authRows = parameters.map((parameter) => createRow(parameter));
526
- authValues.append(authTypeRow, ...authRows);
527
- }
556
+ const authTypeRow = createSelectRow("Authorization Type", auths);
557
+ authTypeRow.children[1].addEventListener("change", function(event) {
558
+ authValues && Array.from(authValues.children).slice(1).forEach((el) => el.remove());
559
+ const auth = auths[event.target.selectedIndex];
560
+ if (auth.value == "No Auth") {
561
+ } else if (auth.value == "Basic Auth") {
562
+ apiOperator.auth = [
563
+ {
564
+ name: "userName",
565
+ value: ""
566
+ },
567
+ {
568
+ name: "password",
569
+ value: ""
570
+ }
571
+ ];
572
+ const authRows = apiOperator.auth.map((parameter) => createRow(parameter));
573
+ authValues.append(...authRows);
574
+ } else if (auth.value == "OAuth 2.0") {
575
+ apiOperator.auth = {};
576
+ renderAuthForm(apiOperator, authValues, authTypeRow);
577
+ }
578
+ });
579
+ authValues.append(authTypeRow);
528
580
  authSection.append(authCnr, authValues);
529
581
  return authSection;
530
582
  }
531
- function createSectionRequestBody(requestBody) {
583
+ function createElement(tag, props = {}, classes = []) {
584
+ const el = document.createElement(tag);
585
+ Object.entries(props).forEach(([key, value]) => el.setAttribute(key, value));
586
+ if (classes.length) el.classList.add(...classes);
587
+ return el;
588
+ }
589
+ function createLabeledInput(apiOperator, labelText, inputId, inputName, modelKey, required = false) {
590
+ const wrapper = createElement("div", {}, ["Keyvalue", "codigma-apiunit-keyvalue"]);
591
+ const label = createElement("label", { for: inputId }, ["type", "codigma-apiunit-send"]);
592
+ label.textContent = labelText + ":";
593
+ const input = createElement("input", {
594
+ type: "text",
595
+ id: inputId,
596
+ name: inputName,
597
+ autocomplete: "off",
598
+ ...required ? { required: "true" } : {}
599
+ }, ["Valuetext", "codigma-apiunit-valuetext"]);
600
+ input.value = apiOperator.auth[modelKey] || "";
601
+ input.addEventListener("input", (e) => {
602
+ apiOperator.auth[modelKey] = e.target.value;
603
+ });
604
+ wrapper.appendChild(label);
605
+ wrapper.appendChild(input);
606
+ return wrapper;
607
+ }
608
+ function createSelect(apiOperator, labelText, selectId, options, modelKey, changeHandler) {
609
+ const wrapper = createElement("div", {}, ["Keyvalue", "codigma-apiunit-keyvalue"]);
610
+ const label = createElement("label", { for: selectId }, ["type", "codigma-apiunit-send"]);
611
+ label.textContent = labelText + ":";
612
+ const select = createElement("select", {
613
+ id: selectId,
614
+ name: selectId
615
+ }, []);
616
+ options.forEach((opt) => {
617
+ const option = createElement("option", { value: opt.value });
618
+ option.textContent = opt.displayName || opt.value;
619
+ select.appendChild(option);
620
+ });
621
+ select.value = apiOperator.auth[modelKey] || options[0]?.value || "";
622
+ select.addEventListener("change", (e) => {
623
+ const val = e.target.value;
624
+ changeHandler(val);
625
+ });
626
+ wrapper.appendChild(label);
627
+ wrapper.appendChild(select);
628
+ return wrapper;
629
+ }
630
+ function renderAuthForm(apiOperator, authValues, authTypeRow) {
631
+ authValues.innerHTML = "";
632
+ authValues.append(authTypeRow);
633
+ authValues.appendChild(createLabeledInput(apiOperator, "Token", "token", "token", "token", true));
634
+ authValues.appendChild(
635
+ createSelect(
636
+ apiOperator,
637
+ "Grant Type",
638
+ "grantType",
639
+ grantTypes,
640
+ "grantType",
641
+ (value) => {
642
+ apiOperator.auth.grantType = value;
643
+ renderAuthForm(apiOperator, authValues, authTypeRow);
644
+ }
645
+ )
646
+ );
647
+ const gt = apiOperator.auth.grantType || "authorization_code";
648
+ if (gt === "authorization_code" || gt === "Implicit") {
649
+ authValues.appendChild(createLabeledInput(apiOperator, "Authorization Endpoint", "authorizationEndpoint", "authorizationEndpoint", "authorizationEndpoint", true));
650
+ authValues.appendChild(createLabeledInput(apiOperator, "Redirect URL", "RedirectURI", "RedirectURI", "redirectURI", true));
651
+ }
652
+ if (gt === "authorization_code" || gt === "client_credentials" || gt === "Resource Owner Password Credentials") {
653
+ authValues.appendChild(createLabeledInput(apiOperator, "Token Endpoint", "TokenEndpoint", "TokenEndpoint", "tokenEndpoint", true));
654
+ }
655
+ authValues.appendChild(createLabeledInput(apiOperator, "Client ID", "ClientID", "ClientID", "clientId", true));
656
+ if (gt === "authorization_code" || gt === "client_credentials" || gt === "Resource Owner Password Credentials") {
657
+ authValues.appendChild(createLabeledInput(apiOperator, "Client Secret", "ClientSecret", "ClientSecret", "clientSecret", true));
658
+ }
659
+ if (gt === "Resource Owner Password Credentials") {
660
+ authValues.appendChild(createLabeledInput(apiOperator, "Username", "Username", "Username", "username", true));
661
+ authValues.appendChild(createLabeledInput(apiOperator, "Password", "Password", "Password", "password", true));
662
+ }
663
+ authValues.appendChild(createLabeledInput(apiOperator, "Scopes", "Scopes", "Scopes", "scopes", true));
664
+ authValues.appendChild(
665
+ createSelect(
666
+ apiOperator,
667
+ "Client Authentication",
668
+ "clientAuthentication",
669
+ clientAuthenticationOpts,
670
+ "clientAuthentication",
671
+ (value) => {
672
+ apiOperator.auth.clientAuthentication = value;
673
+ }
674
+ )
675
+ );
676
+ const buttonWrapper = createElement("div", {}, ["parameter-item"]);
677
+ const generateBtn = createElement("button", {}, ["parameter-button"]);
678
+ generateBtn.type = "button";
679
+ generateBtn.textContent = "Generate Token";
680
+ generateBtn.addEventListener("click", () => generateOAuth2Token(apiOperator));
681
+ buttonWrapper.appendChild(generateBtn);
682
+ authValues.appendChild(buttonWrapper);
683
+ }
684
+ function createSectionRequestBody(apiOperator) {
532
685
  const bodySection = document.createElement("div");
533
686
  bodySection.setAttribute("data-layer", "request-body-section");
534
687
  bodySection.className = "RequestBodySection codigma-apiunit-request-body-section";
@@ -541,13 +694,108 @@ function createSectionRequestBody(requestBody) {
541
694
  bodyText.textContent = "Body";
542
695
  bodyCnr.appendChild(bodyText);
543
696
  bodySection.appendChild(bodyCnr);
544
- const bodyValue = document.createElement("textarea");
545
- bodyValue.setAttribute("data-layer", "bodyTextValue");
546
- bodyValue.className = "Id0CategoryId0NameNamePhotourlsTagsId0NameStatusAvailable codigma-apiunit-parakeyvalues";
547
- bodyValue.value = JSON.stringify(requestBody);
548
- bodySection.appendChild(bodyValue);
697
+ renderConsumeSection(apiOperator, bodySection, bodyCnr);
549
698
  return bodySection;
550
699
  }
700
+ function createConsumeSelect(apiOperator, container, bodyCnr) {
701
+ const wrapper = createElement("div");
702
+ const label = createElement("label");
703
+ label.style.margin = "0 1rem";
704
+ label.textContent = "Content-Type";
705
+ const select = createElement("select");
706
+ select.style.width = "18rem";
707
+ consumeOpts.forEach((opt) => {
708
+ const option = document.createElement("option");
709
+ option.value = opt.value;
710
+ option.textContent = opt.value;
711
+ select.appendChild(option);
712
+ });
713
+ select.value = apiOperator.currentConsume || getCurrentConsume(apiOperator);
714
+ select.addEventListener("change", (e) => {
715
+ const newValue = e.target.value;
716
+ if (apiOperator.currentConsume !== newValue) {
717
+ apiOperator.currentConsume = newValue;
718
+ renderConsumeSection(apiOperator, container, bodyCnr);
719
+ }
720
+ });
721
+ wrapper.appendChild(label);
722
+ wrapper.appendChild(select);
723
+ return wrapper;
724
+ }
725
+ function renderRequestBodyInto(apiOperator, targetDiv) {
726
+ targetDiv.innerHTML = "";
727
+ const ct = apiOperator.currentConsume || getCurrentConsume(apiOperator);
728
+ if (ct === null || ct === "None" || ct === "application/json" || ct === "application/xml" || ct === "text/plain") {
729
+ const mimeType = ct || "None";
730
+ let rawValue = apiOperator.requestBody.content[mimeType];
731
+ if (rawValue == null) {
732
+ rawValue = "";
733
+ apiOperator.requestBody.content[mimeType] = rawValue;
734
+ }
735
+ const textarea = createElement("textarea", {}, []);
736
+ textarea.style.width = "100%";
737
+ textarea.style.height = "200px";
738
+ textarea.style.fontFamily = "monospace";
739
+ textarea.style.fontSize = "14px";
740
+ textarea.placeholder = `Enter ${mimeType} body...`;
741
+ textarea.value = rawValue;
742
+ textarea.addEventListener("input", () => {
743
+ apiOperator.requestBody.content[mimeType] = textarea.value;
744
+ console.log(`Content updated for ${mimeType}:`, textarea.value);
745
+ });
746
+ targetDiv.appendChild(textarea);
747
+ } else if ((ct === "application/x-www-form-urlencoded" || ct === "multipart/form-data") && apiOperator.requestBody.content && Array.isArray(apiOperator.requestBody.content[ct])) {
748
+ const params = apiOperator.requestBody.content[ct];
749
+ params.forEach((param, index) => {
750
+ const item = createElement("div", {}, ["Keyvalue", "codigma-apiunit-keyvalue"]);
751
+ const label = createElement("label", { for: `param-${Date.now()}-${index}` }, ["petId", "codigma-apiunit-send"]);
752
+ label.textContent = `${param.name}:`;
753
+ const input = createElement("input", {
754
+ type: param.uiType || "text",
755
+ // 使用时间戳+索引避免 id 冲突(仅用于 label for)
756
+ id: `param-${Date.now()}-${index}`,
757
+ name: "name"
758
+ }, ["Valuetext", "codigma-apiunit-valuetext"]);
759
+ input.value = param.value || "";
760
+ input.autocomplete = "off";
761
+ input.required = true;
762
+ input.addEventListener("keydown", (e) => {
763
+ setEditStatus(e, true);
764
+ });
765
+ input.addEventListener("input", () => {
766
+ param.value = input.value;
767
+ });
768
+ item.appendChild(label);
769
+ item.appendChild(input);
770
+ targetDiv.appendChild(item);
771
+ });
772
+ }
773
+ }
774
+ function getCurrentConsume(apiOperator) {
775
+ if (!apiOperator.requestBody) {
776
+ apiOperator.requestBody = { content: {} };
777
+ }
778
+ if (!apiOperator.requestBody.content) {
779
+ apiOperator.requestBody.content = {};
780
+ }
781
+ const keys = Object.keys(apiOperator.requestBody.content);
782
+ const ct = apiOperator.currentConsume = keys.length > 0 ? keys[0] : "None";
783
+ return ct;
784
+ }
785
+ function setEditStatus(event, status) {
786
+ console.log("setEditStatus called:", event.key, status);
787
+ }
788
+ function renderConsumeSection(apiOperator, container, bodyCnr) {
789
+ container.innerHTML = "";
790
+ container.appendChild(bodyCnr);
791
+ const wrapperDiv = createElement("div", {}, ["codigma-apiunit-parakeyvalues"]);
792
+ const selectWrapper = createConsumeSelect(apiOperator, container, bodyCnr);
793
+ wrapperDiv.appendChild(selectWrapper);
794
+ const reqBodyContainer = createElement("div", {}, ["codigma-apiunit-request-body-info"]);
795
+ renderRequestBodyInto(apiOperator, reqBodyContainer);
796
+ wrapperDiv.appendChild(reqBodyContainer);
797
+ container.appendChild(wrapperDiv);
798
+ }
551
799
  function createSectionResponse(apiOperator) {
552
800
  const responseSection = document.createElement("div");
553
801
  responseSection.setAttribute("data-layer", "reqresponse");
@@ -582,6 +830,9 @@ function createTimeStatusElement(apiOperator) {
582
830
  updateTimeStatus(timeStatus, apiOperator);
583
831
  return timeStatus;
584
832
  }
833
+ function updateTimeStatus(timeStatus, apiOperator) {
834
+ timeStatus.textContent = `Status: ${apiOperator.response.status || ""} ${apiOperator.response.statusText || ""} Time: ${apiOperator.requestDuration || ""}`;
835
+ }
585
836
  function createRow(parameter) {
586
837
  const petIdRow = document.createElement("div");
587
838
  petIdRow.setAttribute("data-layer", "keyValue");
@@ -595,7 +846,6 @@ function createRow(parameter) {
595
846
  petIdValue.className = "Valuetext codigma-apiunit-valuetext";
596
847
  petIdValue.value = parameter["value"] || "";
597
848
  petIdValue.addEventListener("input", (e) => {
598
- console.log("\u5F53\u524D\u503C:", e.target.value);
599
849
  parameter["value"] = e.target.value;
600
850
  });
601
851
  petIdRow.append(petIdLabel, petIdValue);
@@ -609,31 +859,24 @@ function createInputElement() {
609
859
  inputText.setAttribute("autocomplete", "off");
610
860
  return inputText;
611
861
  }
612
- function createSelectRow(auths, authValues) {
862
+ function createSelectRow(name, args) {
613
863
  const container = document.createElement("div");
614
864
  container.setAttribute("data-layer", "keyValue");
615
865
  container.className = "Keyvalue codigma-apiunit-keyvalue";
616
866
  const typeLabel = document.createElement("div");
617
- typeLabel.setAttribute("data-layer", "type");
867
+ typeLabel.setAttribute("data-layer", name);
618
868
  typeLabel.className = "type codigma-apiunit-send";
619
- typeLabel.textContent = "Type:";
869
+ typeLabel.textContent = name + ":";
620
870
  const selectElement = document.createElement("select");
621
871
  selectElement.name = "text-select";
622
872
  selectElement.label = "text-select";
623
873
  selectElement.setAttribute("data-layer", "valueText");
624
- auths.forEach((auth) => {
874
+ args.forEach((auth) => {
625
875
  const option1 = document.createElement("option");
626
- option1.value = auth["type"];
627
- option1.textContent = auth["type"];
876
+ option1.value = auth["value"];
877
+ option1.textContent = auth["displayName"] != null || auth["label"] != null ? auth["displayName"] || auth["label"] : auth["value"];
628
878
  selectElement.appendChild(option1);
629
879
  });
630
- selectElement.addEventListener("change", function(event) {
631
- authValues && Array.from(authValues.children).slice(1).forEach((el) => el.remove());
632
- const auth = auths[event.target.selectedIndex];
633
- let parameters = auth.parameters || [];
634
- const authRows = parameters.map((parameter) => createRow(parameter));
635
- authValues.append(...authRows);
636
- });
637
880
  container.appendChild(typeLabel);
638
881
  container.appendChild(selectElement);
639
882
  return container;
@@ -644,58 +887,153 @@ function isPathOrQueryParam(param) {
644
887
  function isHeaderParam(param) {
645
888
  return param.in === "header";
646
889
  }
647
- function sendRequest(apiOperator, responseSectionRef) {
648
- if (!responseSectionRef) {
649
- console.error("sendRequest: missing responseSectionRef. Aborting request to avoid runtime errors.");
650
- return;
890
+ async function generateOAuth2Token(apiInfo) {
891
+ const accessToken = await getAccessToken(apiInfo);
892
+ apiInfo.auth.token = accessToken;
893
+ }
894
+ async function getAccessToken(apiInfo) {
895
+ const auth = apiInfo.auth;
896
+ if (auth == null) {
897
+ throw new Error("OAuth2.0\u8BA4\u8BC1\u4FE1\u606F\u672A\u914D\u7F6E");
898
+ }
899
+ const CLIENT_ID = auth.clientId;
900
+ const CLIENT_SECRET = auth.clientSecret;
901
+ const SCOPE = auth.scopes;
902
+ if (apiInfo.auth.grantType == "client_credentials") {
903
+ try {
904
+ console.log("\u6B63\u5728\u83B7\u53D6\u8BBF\u95EE\u4EE4\u724C...");
905
+ const headerParams = {
906
+ "Content-Type": "application/x-www-form-urlencoded"
907
+ };
908
+ const bodyParams = new URLSearchParams();
909
+ bodyParams.append("grant_type", "client_credentials");
910
+ if (SCOPE) {
911
+ bodyParams.append("scope", SCOPE);
912
+ }
913
+ if (apiInfo.auth.clientAuthentication == "Body") {
914
+ bodyParams.append("client_id", CLIENT_ID);
915
+ bodyParams.append("client_secret", CLIENT_SECRET);
916
+ } else {
917
+ headerParams["Authorization"] = "Basic " + btoa(CLIENT_ID + ":" + CLIENT_SECRET);
918
+ }
919
+ const response = await fetch(auth.tokenEndpoint, {
920
+ method: "POST",
921
+ headers: headerParams,
922
+ body: bodyParams.toString()
923
+ });
924
+ if (!response.ok) {
925
+ const errorData = await response.json().catch(() => ({}));
926
+ throw new Error(`\u83B7\u53D6\u4EE4\u724C\u5931\u8D25: ${response.status} ${response.statusText}. ${JSON.stringify(errorData)}`);
927
+ }
928
+ const tokenData = await response.json();
929
+ console.log("\u4EE4\u724C\u83B7\u53D6\u6210\u529F:", tokenData);
930
+ return tokenData.access_token;
931
+ } catch (error) {
932
+ console.error("\u83B7\u53D6\u8BBF\u95EE\u4EE4\u724C\u65F6\u51FA\u9519:", error);
933
+ throw error;
934
+ }
935
+ } else if (apiInfo.auth.grantType == "Resource Owner Password Credentials") {
936
+ } else if (apiInfo.auth.grantType == "authorization_code") {
937
+ let getUrlParams2 = function() {
938
+ const params = new URLSearchParams(window.location.search);
939
+ return Object.fromEntries(params.entries());
940
+ }, redirectToAuth2 = function() {
941
+ const state = Math.random().toString(36).substring(2);
942
+ const nonce = Math.random().toString(36).substring(2);
943
+ const authUrl = new URL(config.authUrl);
944
+ authUrl.searchParams.append("client_id", config.clientId);
945
+ authUrl.searchParams.append("redirect_uri", config.redirectUri);
946
+ authUrl.searchParams.append("response_type", "code");
947
+ authUrl.searchParams.append("scope", config.scope);
948
+ authUrl.searchParams.append("state", state);
949
+ authUrl.searchParams.append("nonce", nonce);
950
+ authUrl.searchParams.append("access_type", "offline");
951
+ const newTab = window.open(authUrl.toString(), "_blank");
952
+ };
953
+ var getUrlParams = getUrlParams2, redirectToAuth = redirectToAuth2;
954
+ const config = {
955
+ clientId: apiInfo.auth.clientId,
956
+ // 替换为你的 client_id
957
+ clientSecret: apiInfo.auth.clientSecret,
958
+ // 替换为你的 client_secret
959
+ redirectUri: apiInfo.auth.redirectURI,
960
+ // 必须与注册的 redirect_uri 一致
961
+ authUrl: apiInfo.auth.authorizationEndpoint,
962
+ tokenUrl: apiInfo.auth.tokenEndpoint,
963
+ scope: apiInfo.auth.scopes
964
+ // 可选: 'openid profile email' 如果服务支持
965
+ };
966
+ redirectToAuth2();
967
+ } else if (apiInfo.auth.grantType == "Implicit") {
968
+ } else {
651
969
  }
652
- let reuqestUrl = getRequestUrl(apiOperator);
653
- const result = checkIfParameter(apiOperator);
654
- let header = result.hasRequestBody ? "application/json" : result.hasRequestFormData ? "application/x-www-form-urlencoded" : "application/json";
970
+ }
971
+ function getBodyEditorContent(apiOperator) {
972
+ const ct = apiOperator.currentConsume || "None";
973
+ return apiOperator.requestBody.content[ct];
974
+ }
975
+ var gotResponse = false;
976
+ var ifSendingRequest = false;
977
+ var requestDuration = "0";
978
+ var responseObj = {};
979
+ function sendRequest(apiOperator, responseSectionRef) {
980
+ const apiInfo = apiOperator;
981
+ let reuqestUrl = getRequestUrl(apiInfo);
982
+ let header = apiInfo["parameterHasFormDataVer2"] ? "application/x-www-form-urlencoded" : apiInfo["parameterHasBody"] ? apiInfo["currentConsume"] : "application/json";
655
983
  let headers = {
656
984
  "Content-Type": header
657
985
  };
658
- if (apiOperator.custom) {
659
- for (let index = 0; index < apiOperator.customHeaderparameters.length; index++) {
660
- const paras = apiOperator.customHeaderparameters[index];
661
- if (paras.name != "" && paras.value != "" && paras.name != null && paras.value != null) {
662
- headers[paras.name] = paras.value;
986
+ const headerParas = getHeadersParams(apiInfo, apiInfo.rawApiInfo.parameters || []);
987
+ Object.assign(headers, headerParas);
988
+ addAuthHeader(apiInfo, headers);
989
+ let body;
990
+ if (apiInfo.method.toUpperCase() == "POST" || apiInfo.method.toUpperCase() == "PUT") {
991
+ if (apiInfo["currentConsume"] == "application/json" && apiInfo.requestBody != null) {
992
+ body = getBodyEditorContent(apiOperator);
993
+ } else if (apiInfo["parameterHasFormDataVer2"]) {
994
+ body = getRequestFormData(apiInfo.rawApiInfo);
995
+ } else if (apiInfo["currentConsume"] == "application/x-www-form-urlencoded") {
996
+ for (const key of apiInfo["requestBody"]["content"][apiInfo["currentConsume"]]) {
997
+ if (body == null || body == "") {
998
+ body = key.name + "=" + key.value;
999
+ } else {
1000
+ body = body + "&" + key.name + "=" + key.value;
1001
+ }
663
1002
  }
1003
+ } else {
1004
+ body = "";
664
1005
  }
1006
+ } else {
1007
+ body = "";
665
1008
  }
666
- let body = result.hasRequestBody ? apiOperator.requestBody : result.hasRequestFormData ? getRequestFormData(apiOperator.rawApiInfo) : null;
667
- if (apiOperator.custom) {
668
- if (apiOperator.method.toUpperCase() == "POST" || apiOperator.method.toUpperCase() == "PUT") {
669
- body = apiOperator.requestBody;
670
- }
671
- }
672
- apiOperator.ifSendingRequest = true;
1009
+ ifSendingRequest = true;
673
1010
  const startTime = Date.now();
674
1011
  apiOperator.controller = new AbortController();
675
1012
  const signal = apiOperator.controller.signal;
676
1013
  const overlayLayerContainer = createRequestOverlayLayer(apiOperator, responseSectionRef);
677
1014
  fetch(reuqestUrl, {
678
- method: apiOperator.method.toUpperCase(),
1015
+ method: apiInfo.method.toUpperCase(),
679
1016
  headers,
680
- body: body != null ? JSON.stringify(body) : null,
1017
+ body,
681
1018
  signal
682
1019
  }).then((response) => {
683
1020
  if (!response.ok) {
684
- apiOperator.response = {
1021
+ responseObj = {
685
1022
  status: response.status,
686
- statusText: response.statusText
1023
+ statusText: response.statusText,
1024
+ body: ""
687
1025
  };
688
1026
  const endTime2 = Date.now();
689
- apiOperator.requestDuration = formatDuration(endTime2 - startTime);
690
- apiOperator.ifSendingRequest = false;
1027
+ requestDuration = formatDuration(endTime2 - startTime);
1028
+ ifSendingRequest = false;
691
1029
  throw new Error("Network response was not ok.");
692
1030
  }
693
1031
  const endTime = Date.now();
694
- apiOperator.requestDuration = formatDuration(endTime - startTime);
1032
+ requestDuration = formatDuration(endTime - startTime);
695
1033
  const responsebodyElement = responseSectionRef.querySelector('[data-layer="responsebody"]');
696
1034
  responsebodyElement.removeChild(overlayLayerContainer);
697
- apiOperator.ifSendingRequest = false;
698
- apiOperator.response = {
1035
+ ifSendingRequest = false;
1036
+ responseObj = {
699
1037
  status: response.status,
700
1038
  statusText: response.statusText
701
1039
  };
@@ -710,22 +1048,20 @@ function sendRequest(apiOperator, responseSectionRef) {
710
1048
  return responseClone.text();
711
1049
  });
712
1050
  }).then((data) => {
713
- apiOperator.gotResponse = true;
1051
+ gotResponse = true;
714
1052
  const responsebodyElement = responseSectionRef.querySelector('[data-layer="responsebody"]');
715
1053
  if (typeof data === "object") {
716
1054
  console.log("Received JSON:", data);
717
- responsebodyElement.textContent = JSON.stringify(data, null, 4);
1055
+ responseObj.body = JSON.stringify(data, null, 4);
718
1056
  } else {
719
1057
  console.log("Received text:", data);
720
- responsebodyElement.textContent = data;
1058
+ responseObj.body = data;
721
1059
  }
1060
+ responsebodyElement.textContent = responseObj.body;
722
1061
  }).catch((error) => {
723
1062
  console.error("There has been a problem with your fetch operation:", error);
724
1063
  });
725
1064
  }
726
- function updateTimeStatus(timeStatus, apiOperator) {
727
- timeStatus.textContent = `Status: ${apiOperator.response.status || ""} ${apiOperator.response.statusText || ""} Time: ${apiOperator.requestDuration || ""}`;
728
- }
729
1065
  function createRequestOverlayLayer(apiOperator, responseSectionRef) {
730
1066
  const container = document.createElement("div");
731
1067
  Object.assign(container.style, {
@@ -768,28 +1104,6 @@ function createRequestOverlayLayer(apiOperator, responseSectionRef) {
768
1104
  });
769
1105
  return container;
770
1106
  }
771
- function checkIfParameter(apiOperator) {
772
- let hasRequestBody = false;
773
- let hasRequestFormData = false;
774
- const parameters = apiOperator.rawApiInfo.parameters;
775
- if (parameters) {
776
- for (let index = 0; index < parameters.length; index++) {
777
- const parameter = parameters[index];
778
- if (parameter.in == "query" || parameter.in == "path") {
779
- } else if (parameter.in == "body") {
780
- hasRequestBody = true;
781
- parameter.name = parameter.name.charAt(0).toUpperCase() + parameter.name.slice(1);
782
- } else if (parameter.in == "formData") {
783
- hasRequestFormData = true;
784
- }
785
- }
786
- }
787
- const requestBody = apiOperator.rawApiInfo.requestBody;
788
- if (requestBody) {
789
- hasRequestBody = true;
790
- }
791
- return { hasRequestBody, hasRequestFormData };
792
- }
793
1107
  function formatDuration(milliseconds) {
794
1108
  let totalSeconds = Math.floor(milliseconds / 1e3);
795
1109
  let seconds = totalSeconds % 60;
@@ -802,9 +1116,9 @@ function formatDuration(milliseconds) {
802
1116
  seconds = seconds.toString().padStart(2, "0");
803
1117
  return `${hours}h${minutes}m${seconds}s${millisecondsPart}ms`;
804
1118
  }
805
- function getRequestUrl(apiOperator) {
806
- let reuqestUrl = apiOperator.url;
807
- const requestParameters = apiOperator.rawApiInfo.parameters || [];
1119
+ function getRequestUrl(apiInfo) {
1120
+ let reuqestUrl = apiInfo.url;
1121
+ const requestParameters = apiInfo.rawApiInfo.parameters || [];
808
1122
  if (requestParameters == null) {
809
1123
  return reuqestUrl;
810
1124
  }
@@ -813,11 +1127,45 @@ function getRequestUrl(apiOperator) {
813
1127
  reuqestUrl = reuqestUrl.replace("{" + element.name + "}", element.value);
814
1128
  }
815
1129
  }
816
- let queryParams = getQueryParams(apiOperator, requestParameters);
1130
+ let queryParams = getQueryParams(apiInfo, requestParameters);
817
1131
  reuqestUrl = queryParams.length > 0 ? reuqestUrl + "?" + queryParams.join("&") : reuqestUrl;
818
1132
  return reuqestUrl;
819
1133
  }
820
- function getQueryParams(apiOperator, requestParameters) {
1134
+ function addAuthHeader(apiInfo, headers) {
1135
+ const env = isBrowserEnvironment();
1136
+ if (apiInfo.auth.authType == "Basic Auth" && apiInfo.auth != null) {
1137
+ if (env) {
1138
+ const credentials = btoa(`${apiInfo.auth.username}:${apiInfo.auth.passWord}`);
1139
+ headers["Authorization"] = `Basic ${credentials}`;
1140
+ } else {
1141
+ const buffer = Buffer.from(`${apiInfo.auth.username}:${apiInfo.auth.passWord}`);
1142
+ const credentials = buffer.toString("base64");
1143
+ headers["Authorization"] = `Basic ${credentials}`;
1144
+ }
1145
+ } else if (apiInfo.auth.authType == "OAuth 2.0" && apiInfo.auth != null) {
1146
+ if (apiInfo.auth.token != null || apiInfo.auth.token != "") {
1147
+ headers["Authorization"] = `Bearer ${apiInfo.auth.token}`;
1148
+ }
1149
+ }
1150
+ }
1151
+ function getHeadersParams(apiInfo, requestParameters) {
1152
+ let headersParams = [];
1153
+ for (const element of requestParameters) {
1154
+ if (element.in == "header") {
1155
+ headersParams[element.name] = element.value;
1156
+ }
1157
+ }
1158
+ if (apiInfo.customHeaderparameters) {
1159
+ for (let index = 0; index < apiInfo.customHeaderparameters.length; index++) {
1160
+ const paras = apiInfo.customHeaderparameters[index];
1161
+ if (paras.name != "" && paras.value != "" && paras.name != null && paras.value != null) {
1162
+ headersParams[paras.name] = paras.value;
1163
+ }
1164
+ }
1165
+ }
1166
+ return headersParams;
1167
+ }
1168
+ function getQueryParams(apiInfo, requestParameters) {
821
1169
  let queryParams = [];
822
1170
  for (const element of requestParameters) {
823
1171
  if (element.in == "query") {
@@ -832,9 +1180,9 @@ function getQueryParams(apiOperator, requestParameters) {
832
1180
  }
833
1181
  }
834
1182
  }
835
- if (apiOperator.custom) {
836
- for (let index = 0; index < apiOperator.customQueryparameters.length; index++) {
837
- const paras = apiOperator.customQueryparameters[index];
1183
+ if (apiInfo.customQueryparameters) {
1184
+ for (let index = 0; index < apiInfo.customQueryparameters.length; index++) {
1185
+ const paras = apiInfo.customQueryparameters[index];
838
1186
  if (paras.name != "" && paras.value != "" && paras.name != null && paras.value != null) {
839
1187
  queryParams.push(paras.name + "=" + paras.value);
840
1188
  }
@@ -861,6 +1209,15 @@ function getRequestFormData(rawApiInfo) {
861
1209
  }
862
1210
  return formData;
863
1211
  }
1212
+ function isBrowserEnvironment() {
1213
+ if (typeof window !== "undefined" && typeof document !== "undefined") {
1214
+ return true;
1215
+ } else if (typeof process !== "undefined" && process.versions && process.versions.node) {
1216
+ return false;
1217
+ } else {
1218
+ return false;
1219
+ }
1220
+ }
864
1221
  function createSvg() {
865
1222
  const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
866
1223
  svg.setAttribute("width", "21");
@@ -879,18 +1236,16 @@ function createSvg() {
879
1236
  }
880
1237
  function parseParaModel(parameterObj, dataDef) {
881
1238
  let bodyModel;
882
- if (parameterObj && parameterObj.schema) {
883
- if (parameterObj.schema["$ref"]) {
884
- bodyModel = parseModel(parameterObj.schema["$ref"], dataDef);
885
- } else if (parameterObj.schema["type"] == "array") {
886
- const itemObj = parameterObj.schema["items"];
887
- if (itemObj["$ref"]) {
888
- bodyModel = parseModel(itemObj["$ref"], dataDef);
889
- } else if (itemObj["type"]) {
890
- bodyModel = parseElement(itemObj);
891
- }
892
- bodyModel = [bodyModel];
1239
+ if (parameterObj.schema["$ref"]) {
1240
+ bodyModel = parseModel(parameterObj.schema["$ref"], dataDef);
1241
+ } else if (parameterObj.schema["type"] == "array") {
1242
+ const itemObj = parameterObj.schema["items"];
1243
+ if (itemObj["$ref"]) {
1244
+ bodyModel = parseModel(itemObj["$ref"], dataDef);
1245
+ } else if (itemObj["type"]) {
1246
+ bodyModel = parseElement(itemObj);
893
1247
  }
1248
+ bodyModel = [bodyModel];
894
1249
  }
895
1250
  return bodyModel;
896
1251
  }
@@ -921,10 +1276,66 @@ function parseModel(modelDef, apiDef) {
921
1276
  }
922
1277
  return model;
923
1278
  }
1279
+ function parseFormDataModel(modelDef, apiDef) {
1280
+ const model = [];
1281
+ const bodyName = modelDef.substring(modelDef.lastIndexOf("/") + 1);
1282
+ const def = apiDef[bodyName];
1283
+ const props = def["properties"];
1284
+ if (props) {
1285
+ for (const key in props) {
1286
+ if (Object.prototype.hasOwnProperty.call(props, key)) {
1287
+ const element = props[key];
1288
+ let modelEle;
1289
+ if (element.hasOwnProperty("items") && element["type"] == "array") {
1290
+ if (element["items"]["$ref"]) {
1291
+ modelEle = [parseModel(element["items"]["$ref"], apiDef)];
1292
+ } else if (element["items"]["type"]) {
1293
+ modelEle = [parseElement(element["items"])];
1294
+ }
1295
+ if (modelEle) {
1296
+ model.push({
1297
+ type: "string",
1298
+ uiType: "text",
1299
+ name: key,
1300
+ value: JSON.stringify(modelEle)
1301
+ });
1302
+ }
1303
+ } else if (element["type"]) {
1304
+ model.push({
1305
+ type: element["type"],
1306
+ uiType: element["type"] == "integer" || element["type"] == "number" ? "number" : "text",
1307
+ name: key,
1308
+ value: parseElement(element)
1309
+ });
1310
+ } else if (element["$ref"]) {
1311
+ const bodyModel = parseModel(element["$ref"], apiDef);
1312
+ model.push({
1313
+ type: "string",
1314
+ uiType: "text",
1315
+ name: key,
1316
+ value: JSON.stringify(bodyModel)
1317
+ });
1318
+ }
1319
+ }
1320
+ }
1321
+ }
1322
+ return model;
1323
+ }
1324
+ function parseFormDataParaModel(parameterObj, dataDef) {
1325
+ let bodyModel = [];
1326
+ if (parameterObj.schema["$ref"]) {
1327
+ bodyModel = parseFormDataModel(parameterObj.schema["$ref"], dataDef);
1328
+ }
1329
+ return bodyModel;
1330
+ }
924
1331
  function parseElement(element) {
925
1332
  let elementValue;
926
1333
  if (element["type"].includes("integer")) {
927
- elementValue = 0;
1334
+ if (element["enum"]) {
1335
+ elementValue = element["enum"][0];
1336
+ } else {
1337
+ elementValue = 0;
1338
+ }
928
1339
  } else if (element["type"].includes("boolean")) {
929
1340
  elementValue = false;
930
1341
  } else if (element["type"].includes("string")) {
@@ -934,16 +1345,29 @@ function parseElement(element) {
934
1345
  elementValue = "";
935
1346
  }
936
1347
  }
1348
+ if (element["default"]) {
1349
+ elementValue = element["default"];
1350
+ }
937
1351
  if (element["example"]) {
938
1352
  elementValue = element["example"];
939
1353
  }
940
1354
  return elementValue;
941
1355
  }
1356
+ function parseElementType(element) {
1357
+ if (element["type"].includes("integer")) {
1358
+ return "integer";
1359
+ } else if (element["type"].includes("boolean")) {
1360
+ return "boolean";
1361
+ } else if (element["type"].includes("string")) {
1362
+ return "string";
1363
+ }
1364
+ return "string";
1365
+ }
942
1366
  var HTTP_METHODS = ["get", "put", "post", "delete", "options", "head", "patch", "trace"];
943
1367
  function isHttpMethod(method) {
944
1368
  return HTTP_METHODS.includes(method);
945
1369
  }
946
- function parseOpenAPI(openapiSpec) {
1370
+ function parseOpenApiSpec(openapiSpec, currentServer, serviceName) {
947
1371
  const apiOperatorList = [];
948
1372
  const pathEntries = [];
949
1373
  for (const path in openapiSpec.paths) {
@@ -964,51 +1388,99 @@ function parseOpenAPI(openapiSpec) {
964
1388
  }
965
1389
  }
966
1390
  pathItemEntries.forEach(([method, operation]) => {
1391
+ let url = path;
1392
+ if (currentServer) {
1393
+ url = currentServer.value + "/api/" + serviceName + "/v1" + path;
1394
+ } else if (openapiSpec.servers && openapiSpec.servers.length > 0) {
1395
+ url = openapiSpec.servers[0].url + path;
1396
+ }
967
1397
  const apiOperator = {
968
1398
  method: method.toUpperCase(),
969
- url: path,
970
- rawApiInfo: null,
1399
+ url,
1400
+ rawApiInfo: operation,
971
1401
  requestBody: null,
972
1402
  response: {},
973
- auths: [
974
- {
975
- type: "No Auth"
976
- },
977
- {
978
- type: "Basic Auth",
979
- parameters: [
980
- {
981
- name: "userName",
982
- value: ""
983
- },
984
- {
985
- name: "password",
986
- value: ""
987
- }
988
- ]
989
- }
990
- ]
1403
+ auth: {}
991
1404
  };
992
1405
  if (operation) {
993
- if (operation.parameters) {
994
- const parameter = operation.parameters.filter((val) => val.in == "body");
995
- if (parameter && parameter.length > 0) {
1406
+ if (apiOperator.rawApiInfo.parameters) {
1407
+ const parameterBody = apiOperator.rawApiInfo.parameters.filter((val) => val.in == "body");
1408
+ if (parameterBody && parameterBody.length > 0) {
1409
+ apiOperator["requestBody"] = {
1410
+ content: {}
1411
+ };
1412
+ apiOperator["consumes"] = apiOperator.rawApiInfo["consumes"];
1413
+ const currentConsume = apiOperator.rawApiInfo["consumes"].length > 0 ? apiOperator.rawApiInfo["consumes"][0] : "application/json";
1414
+ apiOperator["currentConsume"] = currentConsume;
1415
+ let requestBody = parseParaModel(parameterBody[0], openapiSpec["definitions"]);
1416
+ apiOperator["requestBody"]["content"][currentConsume] = JSON.stringify(requestBody, null, 4);
1417
+ apiOperator["parameterHasBody"] = true;
1418
+ } else {
1419
+ for (const parameter of apiOperator.rawApiInfo.parameters) {
1420
+ if (parameter.in == "query" || parameter.in == "header" || parameter.in == "path" || parameter.in == "formData") {
1421
+ if (parameter.type == "integer" || parameter.schema != null && parameter.schema.type == "integer" || parameter.type == "number" || parameter.schema != null && parameter.schema.type == "number") {
1422
+ parameter.uiType = "number";
1423
+ }
1424
+ if (parameter.type == "string" || parameter.schema != null && parameter.schema.type == "string") {
1425
+ parameter.uiType = "text";
1426
+ }
1427
+ if (parameter.type == "boolean" || parameter.schema != null && parameter.schema.type == "boolean") {
1428
+ parameter.uiType = "text";
1429
+ }
1430
+ }
1431
+ }
1432
+ const parameterFormData = apiOperator.rawApiInfo.parameters.filter((val) => val.in == "formData");
1433
+ if (parameterFormData && parameterFormData.length > 0) {
1434
+ apiOperator["parameterHasFormDataVer2"] = true;
1435
+ }
1436
+ for (const param of apiOperator.rawApiInfo.parameters) {
1437
+ const paramSchema = param.schema;
1438
+ if (paramSchema && paramSchema["$ref"]) {
1439
+ const bodyName = paramSchema["$ref"].substring(paramSchema["$ref"].lastIndexOf("/") + 1);
1440
+ if (openapiSpec && openapiSpec["components"] != null && openapiSpec["components"]["schemas"] != null) {
1441
+ const def = openapiSpec["components"] != null ? openapiSpec["components"]["schemas"][bodyName] : { type: "" };
1442
+ param.type = parseElementType(def);
1443
+ param.uiType = param.type == "integer" || param.type == "number" ? "number" : "text";
1444
+ param.value = parseElement(def);
1445
+ }
1446
+ }
1447
+ }
996
1448
  }
997
1449
  }
998
- if (operation.requestBody) {
999
- const requestBodyObject = operation.requestBody;
1000
- const content = requestBodyObject.content;
1450
+ if (apiOperator.rawApiInfo.requestBody) {
1451
+ const content = apiOperator.rawApiInfo.requestBody.content;
1452
+ apiOperator["requestBody"] = {
1453
+ content: {}
1454
+ };
1001
1455
  for (const key in content) {
1002
1456
  if (Object.prototype.hasOwnProperty.call(content, key)) {
1003
1457
  const element = content[key];
1458
+ apiOperator["consumes"]?.push(key);
1004
1459
  if (element) {
1005
- let requestBody = parseParaModel(element, openapiSpec["components"]["schemas"]);
1006
- apiOperator.requestBody = requestBody;
1460
+ if (element.schema == void 0) {
1461
+ console.log("pathKey is:", path);
1462
+ console.log("key is:", key);
1463
+ console.log("content is:", content);
1464
+ console.log("Unsupported requestBody schema format:", element);
1465
+ continue;
1466
+ }
1467
+ if (key != "application/x-www-form-urlencoded" && key != "multipart/form-data") {
1468
+ let requestBody = parseParaModel(element, openapiSpec["components"]["schemas"]);
1469
+ apiOperator["requestBody"]["content"][key] = JSON.stringify(requestBody, null, 4);
1470
+ } else {
1471
+ let requestFormDataBody = parseFormDataParaModel(element, openapiSpec["components"]["schemas"]);
1472
+ apiOperator["requestBody"]["content"][key] = requestFormDataBody;
1473
+ }
1474
+ apiOperator["parameterHasBody"] = true;
1007
1475
  }
1008
1476
  }
1009
1477
  }
1478
+ if (apiOperator.consumes) {
1479
+ if (apiOperator.consumes.length > 0) {
1480
+ apiOperator["currentConsume"] = apiOperator["consumes"][0];
1481
+ }
1482
+ }
1010
1483
  }
1011
- apiOperator.rawApiInfo = operation;
1012
1484
  apiOperatorList.push(apiOperator);
1013
1485
  }
1014
1486
  });