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.js CHANGED
@@ -186,10 +186,12 @@ var GLOBAL_STYLES = `.codigma-apioperatorlist {
186
186
  align-items: center;
187
187
  align-self: stretch;
188
188
  display: inline-flex;
189
- height: 114px;
190
189
  justify-content: flex-start;
191
190
  padding-right: 5px
192
191
  }
192
+ .codigma-apiunit-request-body-info {
193
+ align-self: stretch;
194
+ }
193
195
  .codigma-apiunit-parakeyvalues {
194
196
  align-items: flex-start;
195
197
  align-self: stretch;
@@ -263,7 +265,7 @@ var ApiRenderer = class _ApiRenderer {
263
265
  }, options);
264
266
  this.container = null;
265
267
  }
266
- render(apiSpec, renderUnit = false) {
268
+ render(apiSpec, currentServer, serviceName, renderUnit = false) {
267
269
  const appendInlineStyle = (text) => {
268
270
  if (!_ApiRenderer.globalStyleInjected) {
269
271
  const styleEl = document.createElement("style");
@@ -280,7 +282,7 @@ var ApiRenderer = class _ApiRenderer {
280
282
  }
281
283
  if (apiSpec["openapi"] && apiSpec["openapi"].startsWith("3.") || apiSpec["swagger"] && apiSpec["swagger"].startsWith("2.")) {
282
284
  const countApi = countOpenAPI(apiSpec);
283
- const apiOperatorList = parseOpenAPI(apiSpec);
285
+ const apiOperatorList = parseOpenApiSpec(apiSpec, currentServer, serviceName);
284
286
  if (countApi == 1 && renderUnit) {
285
287
  this.container = createApiUnit(apiOperatorList[0]);
286
288
  } else {
@@ -345,12 +347,47 @@ var ApiRenderer = class _ApiRenderer {
345
347
  mountElement.appendChild(this.container);
346
348
  }
347
349
  };
350
+ var auths = [
351
+ {
352
+ value: "No Auth"
353
+ },
354
+ {
355
+ value: "Basic Auth",
356
+ parameters: [
357
+ {
358
+ name: "userName",
359
+ value: ""
360
+ },
361
+ {
362
+ name: "password",
363
+ value: ""
364
+ }
365
+ ]
366
+ },
367
+ {
368
+ value: "OAuth 2.0"
369
+ }
370
+ ];
371
+ var grantTypes = [
372
+ { value: "authorization_code" },
373
+ { value: "Implicit" },
374
+ { value: "Resource Owner Password Credentials" },
375
+ { value: "client_credentials" }
376
+ ];
377
+ var clientAuthenticationOpts = [
378
+ { value: "Headers", displayName: "Send credentials in headers" },
379
+ { value: "Body", displayName: "Send credentials in body" }
380
+ ];
381
+ var consumeOpts = [
382
+ { value: "None" },
383
+ { value: "application/json" },
384
+ { value: "application/xml" },
385
+ { value: "application/x-www-form-urlencoded" },
386
+ { value: "multipart/form-data" },
387
+ { value: "text/plain" }
388
+ ];
348
389
  function renderApiUnit(apiOperator, containerRef, elementMap) {
349
390
  return function(evt) {
350
- console.log("\u70B9\u51FB\u7684API\u64CD\u4F5C\uFF1A");
351
- console.log("\u65B9\u6CD5:", apiOperator.method);
352
- console.log("URL:", apiOperator.url);
353
- console.log("------------------------");
354
391
  const currentTarget = evt.currentTarget;
355
392
  if (elementMap.has(currentTarget)) {
356
393
  const newElement = elementMap.get(currentTarget);
@@ -381,7 +418,7 @@ function createApiUnit(apiOperator) {
381
418
  const paramSection = createParamSection(apiOperator);
382
419
  const headerSection = createSectionHeader(apiOperator);
383
420
  const authSection = createSectionAuth(apiOperator);
384
- const bodySection = createSectionRequestBody(apiOperator.requestBody);
421
+ const bodySection = createSectionRequestBody(apiOperator);
385
422
  reqContent.append(paramSection, headerSection, authSection, bodySection);
386
423
  apiContainer.appendChild(reqContent);
387
424
  apiContainer.appendChild(responseSection);
@@ -412,7 +449,6 @@ function createReqOperator(apiOperator) {
412
449
  reqUrl.className = "Requrl codigma-apiunit-requrl";
413
450
  reqUrl.value = apiOperator.url;
414
451
  reqUrl.addEventListener("input", (e) => {
415
- console.log("\u5F53\u524D\u503C:", e.target.value);
416
452
  apiOperator.url = e.target.value;
417
453
  });
418
454
  reqOperator.appendChild(reqUrl);
@@ -425,7 +461,6 @@ function createReqOperator(apiOperator) {
425
461
  sendText.textContent = "Send";
426
462
  sendButton.appendChild(sendText);
427
463
  sendButton.addEventListener("click", (e) => {
428
- console.log("\u5F53\u524D\u503C:", e.target.value);
429
464
  const respRef = apiOperator._responseSectionRef || null;
430
465
  sendRequest(apiOperator, respRef);
431
466
  });
@@ -492,17 +527,135 @@ function createSectionAuth(apiOperator) {
492
527
  const authValues = document.createElement("div");
493
528
  authValues.setAttribute("data-layer", "paraKeyValues");
494
529
  authValues.className = "Parakeyvalues codigma-apiunit-parakeyvalues";
495
- let auths = apiOperator.auths || [];
496
- const authTypeRow = createSelectRow(auths, authValues);
497
- if (auths.length > 0) {
498
- let parameters = apiOperator.auths[0].parameters || [];
499
- const authRows = parameters.map((parameter) => createRow(parameter));
500
- authValues.append(authTypeRow, ...authRows);
501
- }
530
+ const authTypeRow = createSelectRow("Authorization Type", auths);
531
+ authTypeRow.children[1].addEventListener("change", function(event) {
532
+ authValues && Array.from(authValues.children).slice(1).forEach((el) => el.remove());
533
+ const auth = auths[event.target.selectedIndex];
534
+ if (auth.value == "No Auth") {
535
+ } else if (auth.value == "Basic Auth") {
536
+ apiOperator.auth = [
537
+ {
538
+ name: "userName",
539
+ value: ""
540
+ },
541
+ {
542
+ name: "password",
543
+ value: ""
544
+ }
545
+ ];
546
+ const authRows = apiOperator.auth.map((parameter) => createRow(parameter));
547
+ authValues.append(...authRows);
548
+ } else if (auth.value == "OAuth 2.0") {
549
+ apiOperator.auth = {};
550
+ renderAuthForm(apiOperator, authValues, authTypeRow);
551
+ }
552
+ });
553
+ authValues.append(authTypeRow);
502
554
  authSection.append(authCnr, authValues);
503
555
  return authSection;
504
556
  }
505
- function createSectionRequestBody(requestBody) {
557
+ function createElement(tag, props = {}, classes = []) {
558
+ const el = document.createElement(tag);
559
+ Object.entries(props).forEach(([key, value]) => el.setAttribute(key, value));
560
+ if (classes.length) el.classList.add(...classes);
561
+ return el;
562
+ }
563
+ function createLabeledInput(apiOperator, labelText, inputId, inputName, modelKey, required = false) {
564
+ const wrapper = createElement("div", {}, ["Keyvalue", "codigma-apiunit-keyvalue"]);
565
+ const label = createElement("label", { for: inputId }, ["type", "codigma-apiunit-send"]);
566
+ label.textContent = labelText + ":";
567
+ const input = createElement("input", {
568
+ type: "text",
569
+ id: inputId,
570
+ name: inputName,
571
+ autocomplete: "off",
572
+ ...required ? { required: "true" } : {}
573
+ }, ["Valuetext", "codigma-apiunit-valuetext"]);
574
+ input.value = apiOperator.auth[modelKey] || "";
575
+ input.addEventListener("input", (e) => {
576
+ apiOperator.auth[modelKey] = e.target.value;
577
+ });
578
+ wrapper.appendChild(label);
579
+ wrapper.appendChild(input);
580
+ return wrapper;
581
+ }
582
+ function createSelect(apiOperator, labelText, selectId, options, modelKey, changeHandler) {
583
+ const wrapper = createElement("div", {}, ["Keyvalue", "codigma-apiunit-keyvalue"]);
584
+ const label = createElement("label", { for: selectId }, ["type", "codigma-apiunit-send"]);
585
+ label.textContent = labelText + ":";
586
+ const select = createElement("select", {
587
+ id: selectId,
588
+ name: selectId
589
+ }, []);
590
+ options.forEach((opt) => {
591
+ const option = createElement("option", { value: opt.value });
592
+ option.textContent = opt.displayName || opt.value;
593
+ select.appendChild(option);
594
+ });
595
+ select.value = apiOperator.auth[modelKey] || options[0]?.value || "";
596
+ select.addEventListener("change", (e) => {
597
+ const val = e.target.value;
598
+ changeHandler(val);
599
+ });
600
+ wrapper.appendChild(label);
601
+ wrapper.appendChild(select);
602
+ return wrapper;
603
+ }
604
+ function renderAuthForm(apiOperator, authValues, authTypeRow) {
605
+ authValues.innerHTML = "";
606
+ authValues.append(authTypeRow);
607
+ authValues.appendChild(createLabeledInput(apiOperator, "Token", "token", "token", "token", true));
608
+ authValues.appendChild(
609
+ createSelect(
610
+ apiOperator,
611
+ "Grant Type",
612
+ "grantType",
613
+ grantTypes,
614
+ "grantType",
615
+ (value) => {
616
+ apiOperator.auth.grantType = value;
617
+ renderAuthForm(apiOperator, authValues, authTypeRow);
618
+ }
619
+ )
620
+ );
621
+ const gt = apiOperator.auth.grantType || "authorization_code";
622
+ if (gt === "authorization_code" || gt === "Implicit") {
623
+ authValues.appendChild(createLabeledInput(apiOperator, "Authorization Endpoint", "authorizationEndpoint", "authorizationEndpoint", "authorizationEndpoint", true));
624
+ authValues.appendChild(createLabeledInput(apiOperator, "Redirect URL", "RedirectURI", "RedirectURI", "redirectURI", true));
625
+ }
626
+ if (gt === "authorization_code" || gt === "client_credentials" || gt === "Resource Owner Password Credentials") {
627
+ authValues.appendChild(createLabeledInput(apiOperator, "Token Endpoint", "TokenEndpoint", "TokenEndpoint", "tokenEndpoint", true));
628
+ }
629
+ authValues.appendChild(createLabeledInput(apiOperator, "Client ID", "ClientID", "ClientID", "clientId", true));
630
+ if (gt === "authorization_code" || gt === "client_credentials" || gt === "Resource Owner Password Credentials") {
631
+ authValues.appendChild(createLabeledInput(apiOperator, "Client Secret", "ClientSecret", "ClientSecret", "clientSecret", true));
632
+ }
633
+ if (gt === "Resource Owner Password Credentials") {
634
+ authValues.appendChild(createLabeledInput(apiOperator, "Username", "Username", "Username", "username", true));
635
+ authValues.appendChild(createLabeledInput(apiOperator, "Password", "Password", "Password", "password", true));
636
+ }
637
+ authValues.appendChild(createLabeledInput(apiOperator, "Scopes", "Scopes", "Scopes", "scopes", true));
638
+ authValues.appendChild(
639
+ createSelect(
640
+ apiOperator,
641
+ "Client Authentication",
642
+ "clientAuthentication",
643
+ clientAuthenticationOpts,
644
+ "clientAuthentication",
645
+ (value) => {
646
+ apiOperator.auth.clientAuthentication = value;
647
+ }
648
+ )
649
+ );
650
+ const buttonWrapper = createElement("div", {}, ["parameter-item"]);
651
+ const generateBtn = createElement("button", {}, ["parameter-button"]);
652
+ generateBtn.type = "button";
653
+ generateBtn.textContent = "Generate Token";
654
+ generateBtn.addEventListener("click", () => generateOAuth2Token(apiOperator));
655
+ buttonWrapper.appendChild(generateBtn);
656
+ authValues.appendChild(buttonWrapper);
657
+ }
658
+ function createSectionRequestBody(apiOperator) {
506
659
  const bodySection = document.createElement("div");
507
660
  bodySection.setAttribute("data-layer", "request-body-section");
508
661
  bodySection.className = "RequestBodySection codigma-apiunit-request-body-section";
@@ -515,13 +668,108 @@ function createSectionRequestBody(requestBody) {
515
668
  bodyText.textContent = "Body";
516
669
  bodyCnr.appendChild(bodyText);
517
670
  bodySection.appendChild(bodyCnr);
518
- const bodyValue = document.createElement("textarea");
519
- bodyValue.setAttribute("data-layer", "bodyTextValue");
520
- bodyValue.className = "Id0CategoryId0NameNamePhotourlsTagsId0NameStatusAvailable codigma-apiunit-parakeyvalues";
521
- bodyValue.value = JSON.stringify(requestBody);
522
- bodySection.appendChild(bodyValue);
671
+ renderConsumeSection(apiOperator, bodySection, bodyCnr);
523
672
  return bodySection;
524
673
  }
674
+ function createConsumeSelect(apiOperator, container, bodyCnr) {
675
+ const wrapper = createElement("div");
676
+ const label = createElement("label");
677
+ label.style.margin = "0 1rem";
678
+ label.textContent = "Content-Type";
679
+ const select = createElement("select");
680
+ select.style.width = "18rem";
681
+ consumeOpts.forEach((opt) => {
682
+ const option = document.createElement("option");
683
+ option.value = opt.value;
684
+ option.textContent = opt.value;
685
+ select.appendChild(option);
686
+ });
687
+ select.value = apiOperator.currentConsume || getCurrentConsume(apiOperator);
688
+ select.addEventListener("change", (e) => {
689
+ const newValue = e.target.value;
690
+ if (apiOperator.currentConsume !== newValue) {
691
+ apiOperator.currentConsume = newValue;
692
+ renderConsumeSection(apiOperator, container, bodyCnr);
693
+ }
694
+ });
695
+ wrapper.appendChild(label);
696
+ wrapper.appendChild(select);
697
+ return wrapper;
698
+ }
699
+ function renderRequestBodyInto(apiOperator, targetDiv) {
700
+ targetDiv.innerHTML = "";
701
+ const ct = apiOperator.currentConsume || getCurrentConsume(apiOperator);
702
+ if (ct === null || ct === "None" || ct === "application/json" || ct === "application/xml" || ct === "text/plain") {
703
+ const mimeType = ct || "None";
704
+ let rawValue = apiOperator.requestBody.content[mimeType];
705
+ if (rawValue == null) {
706
+ rawValue = "";
707
+ apiOperator.requestBody.content[mimeType] = rawValue;
708
+ }
709
+ const textarea = createElement("textarea", {}, []);
710
+ textarea.style.width = "100%";
711
+ textarea.style.height = "200px";
712
+ textarea.style.fontFamily = "monospace";
713
+ textarea.style.fontSize = "14px";
714
+ textarea.placeholder = `Enter ${mimeType} body...`;
715
+ textarea.value = rawValue;
716
+ textarea.addEventListener("input", () => {
717
+ apiOperator.requestBody.content[mimeType] = textarea.value;
718
+ console.log(`Content updated for ${mimeType}:`, textarea.value);
719
+ });
720
+ targetDiv.appendChild(textarea);
721
+ } else if ((ct === "application/x-www-form-urlencoded" || ct === "multipart/form-data") && apiOperator.requestBody.content && Array.isArray(apiOperator.requestBody.content[ct])) {
722
+ const params = apiOperator.requestBody.content[ct];
723
+ params.forEach((param, index) => {
724
+ const item = createElement("div", {}, ["Keyvalue", "codigma-apiunit-keyvalue"]);
725
+ const label = createElement("label", { for: `param-${Date.now()}-${index}` }, ["petId", "codigma-apiunit-send"]);
726
+ label.textContent = `${param.name}:`;
727
+ const input = createElement("input", {
728
+ type: param.uiType || "text",
729
+ // 使用时间戳+索引避免 id 冲突(仅用于 label for)
730
+ id: `param-${Date.now()}-${index}`,
731
+ name: "name"
732
+ }, ["Valuetext", "codigma-apiunit-valuetext"]);
733
+ input.value = param.value || "";
734
+ input.autocomplete = "off";
735
+ input.required = true;
736
+ input.addEventListener("keydown", (e) => {
737
+ setEditStatus(e, true);
738
+ });
739
+ input.addEventListener("input", () => {
740
+ param.value = input.value;
741
+ });
742
+ item.appendChild(label);
743
+ item.appendChild(input);
744
+ targetDiv.appendChild(item);
745
+ });
746
+ }
747
+ }
748
+ function getCurrentConsume(apiOperator) {
749
+ if (!apiOperator.requestBody) {
750
+ apiOperator.requestBody = { content: {} };
751
+ }
752
+ if (!apiOperator.requestBody.content) {
753
+ apiOperator.requestBody.content = {};
754
+ }
755
+ const keys = Object.keys(apiOperator.requestBody.content);
756
+ const ct = apiOperator.currentConsume = keys.length > 0 ? keys[0] : "None";
757
+ return ct;
758
+ }
759
+ function setEditStatus(event, status) {
760
+ console.log("setEditStatus called:", event.key, status);
761
+ }
762
+ function renderConsumeSection(apiOperator, container, bodyCnr) {
763
+ container.innerHTML = "";
764
+ container.appendChild(bodyCnr);
765
+ const wrapperDiv = createElement("div", {}, ["codigma-apiunit-parakeyvalues"]);
766
+ const selectWrapper = createConsumeSelect(apiOperator, container, bodyCnr);
767
+ wrapperDiv.appendChild(selectWrapper);
768
+ const reqBodyContainer = createElement("div", {}, ["codigma-apiunit-request-body-info"]);
769
+ renderRequestBodyInto(apiOperator, reqBodyContainer);
770
+ wrapperDiv.appendChild(reqBodyContainer);
771
+ container.appendChild(wrapperDiv);
772
+ }
525
773
  function createSectionResponse(apiOperator) {
526
774
  const responseSection = document.createElement("div");
527
775
  responseSection.setAttribute("data-layer", "reqresponse");
@@ -556,6 +804,9 @@ function createTimeStatusElement(apiOperator) {
556
804
  updateTimeStatus(timeStatus, apiOperator);
557
805
  return timeStatus;
558
806
  }
807
+ function updateTimeStatus(timeStatus, apiOperator) {
808
+ timeStatus.textContent = `Status: ${apiOperator.response.status || ""} ${apiOperator.response.statusText || ""} Time: ${apiOperator.requestDuration || ""}`;
809
+ }
559
810
  function createRow(parameter) {
560
811
  const petIdRow = document.createElement("div");
561
812
  petIdRow.setAttribute("data-layer", "keyValue");
@@ -569,7 +820,6 @@ function createRow(parameter) {
569
820
  petIdValue.className = "Valuetext codigma-apiunit-valuetext";
570
821
  petIdValue.value = parameter["value"] || "";
571
822
  petIdValue.addEventListener("input", (e) => {
572
- console.log("\u5F53\u524D\u503C:", e.target.value);
573
823
  parameter["value"] = e.target.value;
574
824
  });
575
825
  petIdRow.append(petIdLabel, petIdValue);
@@ -583,31 +833,24 @@ function createInputElement() {
583
833
  inputText.setAttribute("autocomplete", "off");
584
834
  return inputText;
585
835
  }
586
- function createSelectRow(auths, authValues) {
836
+ function createSelectRow(name, args) {
587
837
  const container = document.createElement("div");
588
838
  container.setAttribute("data-layer", "keyValue");
589
839
  container.className = "Keyvalue codigma-apiunit-keyvalue";
590
840
  const typeLabel = document.createElement("div");
591
- typeLabel.setAttribute("data-layer", "type");
841
+ typeLabel.setAttribute("data-layer", name);
592
842
  typeLabel.className = "type codigma-apiunit-send";
593
- typeLabel.textContent = "Type:";
843
+ typeLabel.textContent = name + ":";
594
844
  const selectElement = document.createElement("select");
595
845
  selectElement.name = "text-select";
596
846
  selectElement.label = "text-select";
597
847
  selectElement.setAttribute("data-layer", "valueText");
598
- auths.forEach((auth) => {
848
+ args.forEach((auth) => {
599
849
  const option1 = document.createElement("option");
600
- option1.value = auth["type"];
601
- option1.textContent = auth["type"];
850
+ option1.value = auth["value"];
851
+ option1.textContent = auth["displayName"] != null || auth["label"] != null ? auth["displayName"] || auth["label"] : auth["value"];
602
852
  selectElement.appendChild(option1);
603
853
  });
604
- selectElement.addEventListener("change", function(event) {
605
- authValues && Array.from(authValues.children).slice(1).forEach((el) => el.remove());
606
- const auth = auths[event.target.selectedIndex];
607
- let parameters = auth.parameters || [];
608
- const authRows = parameters.map((parameter) => createRow(parameter));
609
- authValues.append(...authRows);
610
- });
611
854
  container.appendChild(typeLabel);
612
855
  container.appendChild(selectElement);
613
856
  return container;
@@ -618,58 +861,153 @@ function isPathOrQueryParam(param) {
618
861
  function isHeaderParam(param) {
619
862
  return param.in === "header";
620
863
  }
621
- function sendRequest(apiOperator, responseSectionRef) {
622
- if (!responseSectionRef) {
623
- console.error("sendRequest: missing responseSectionRef. Aborting request to avoid runtime errors.");
624
- return;
864
+ async function generateOAuth2Token(apiInfo) {
865
+ const accessToken = await getAccessToken(apiInfo);
866
+ apiInfo.auth.token = accessToken;
867
+ }
868
+ async function getAccessToken(apiInfo) {
869
+ const auth = apiInfo.auth;
870
+ if (auth == null) {
871
+ throw new Error("OAuth2.0\u8BA4\u8BC1\u4FE1\u606F\u672A\u914D\u7F6E");
872
+ }
873
+ const CLIENT_ID = auth.clientId;
874
+ const CLIENT_SECRET = auth.clientSecret;
875
+ const SCOPE = auth.scopes;
876
+ if (apiInfo.auth.grantType == "client_credentials") {
877
+ try {
878
+ console.log("\u6B63\u5728\u83B7\u53D6\u8BBF\u95EE\u4EE4\u724C...");
879
+ const headerParams = {
880
+ "Content-Type": "application/x-www-form-urlencoded"
881
+ };
882
+ const bodyParams = new URLSearchParams();
883
+ bodyParams.append("grant_type", "client_credentials");
884
+ if (SCOPE) {
885
+ bodyParams.append("scope", SCOPE);
886
+ }
887
+ if (apiInfo.auth.clientAuthentication == "Body") {
888
+ bodyParams.append("client_id", CLIENT_ID);
889
+ bodyParams.append("client_secret", CLIENT_SECRET);
890
+ } else {
891
+ headerParams["Authorization"] = "Basic " + btoa(CLIENT_ID + ":" + CLIENT_SECRET);
892
+ }
893
+ const response = await fetch(auth.tokenEndpoint, {
894
+ method: "POST",
895
+ headers: headerParams,
896
+ body: bodyParams.toString()
897
+ });
898
+ if (!response.ok) {
899
+ const errorData = await response.json().catch(() => ({}));
900
+ throw new Error(`\u83B7\u53D6\u4EE4\u724C\u5931\u8D25: ${response.status} ${response.statusText}. ${JSON.stringify(errorData)}`);
901
+ }
902
+ const tokenData = await response.json();
903
+ console.log("\u4EE4\u724C\u83B7\u53D6\u6210\u529F:", tokenData);
904
+ return tokenData.access_token;
905
+ } catch (error) {
906
+ console.error("\u83B7\u53D6\u8BBF\u95EE\u4EE4\u724C\u65F6\u51FA\u9519:", error);
907
+ throw error;
908
+ }
909
+ } else if (apiInfo.auth.grantType == "Resource Owner Password Credentials") {
910
+ } else if (apiInfo.auth.grantType == "authorization_code") {
911
+ let getUrlParams2 = function() {
912
+ const params = new URLSearchParams(window.location.search);
913
+ return Object.fromEntries(params.entries());
914
+ }, redirectToAuth2 = function() {
915
+ const state = Math.random().toString(36).substring(2);
916
+ const nonce = Math.random().toString(36).substring(2);
917
+ const authUrl = new URL(config.authUrl);
918
+ authUrl.searchParams.append("client_id", config.clientId);
919
+ authUrl.searchParams.append("redirect_uri", config.redirectUri);
920
+ authUrl.searchParams.append("response_type", "code");
921
+ authUrl.searchParams.append("scope", config.scope);
922
+ authUrl.searchParams.append("state", state);
923
+ authUrl.searchParams.append("nonce", nonce);
924
+ authUrl.searchParams.append("access_type", "offline");
925
+ const newTab = window.open(authUrl.toString(), "_blank");
926
+ };
927
+ var getUrlParams = getUrlParams2, redirectToAuth = redirectToAuth2;
928
+ const config = {
929
+ clientId: apiInfo.auth.clientId,
930
+ // 替换为你的 client_id
931
+ clientSecret: apiInfo.auth.clientSecret,
932
+ // 替换为你的 client_secret
933
+ redirectUri: apiInfo.auth.redirectURI,
934
+ // 必须与注册的 redirect_uri 一致
935
+ authUrl: apiInfo.auth.authorizationEndpoint,
936
+ tokenUrl: apiInfo.auth.tokenEndpoint,
937
+ scope: apiInfo.auth.scopes
938
+ // 可选: 'openid profile email' 如果服务支持
939
+ };
940
+ redirectToAuth2();
941
+ } else if (apiInfo.auth.grantType == "Implicit") {
942
+ } else {
625
943
  }
626
- let reuqestUrl = getRequestUrl(apiOperator);
627
- const result = checkIfParameter(apiOperator);
628
- let header = result.hasRequestBody ? "application/json" : result.hasRequestFormData ? "application/x-www-form-urlencoded" : "application/json";
944
+ }
945
+ function getBodyEditorContent(apiOperator) {
946
+ const ct = apiOperator.currentConsume || "None";
947
+ return apiOperator.requestBody.content[ct];
948
+ }
949
+ var gotResponse = false;
950
+ var ifSendingRequest = false;
951
+ var requestDuration = "0";
952
+ var responseObj = {};
953
+ function sendRequest(apiOperator, responseSectionRef) {
954
+ const apiInfo = apiOperator;
955
+ let reuqestUrl = getRequestUrl(apiInfo);
956
+ let header = apiInfo["parameterHasFormDataVer2"] ? "application/x-www-form-urlencoded" : apiInfo["parameterHasBody"] ? apiInfo["currentConsume"] : "application/json";
629
957
  let headers = {
630
958
  "Content-Type": header
631
959
  };
632
- if (apiOperator.custom) {
633
- for (let index = 0; index < apiOperator.customHeaderparameters.length; index++) {
634
- const paras = apiOperator.customHeaderparameters[index];
635
- if (paras.name != "" && paras.value != "" && paras.name != null && paras.value != null) {
636
- headers[paras.name] = paras.value;
960
+ const headerParas = getHeadersParams(apiInfo, apiInfo.rawApiInfo.parameters || []);
961
+ Object.assign(headers, headerParas);
962
+ addAuthHeader(apiInfo, headers);
963
+ let body;
964
+ if (apiInfo.method.toUpperCase() == "POST" || apiInfo.method.toUpperCase() == "PUT") {
965
+ if (apiInfo["currentConsume"] == "application/json" && apiInfo.requestBody != null) {
966
+ body = getBodyEditorContent(apiOperator);
967
+ } else if (apiInfo["parameterHasFormDataVer2"]) {
968
+ body = getRequestFormData(apiInfo.rawApiInfo);
969
+ } else if (apiInfo["currentConsume"] == "application/x-www-form-urlencoded") {
970
+ for (const key of apiInfo["requestBody"]["content"][apiInfo["currentConsume"]]) {
971
+ if (body == null || body == "") {
972
+ body = key.name + "=" + key.value;
973
+ } else {
974
+ body = body + "&" + key.name + "=" + key.value;
975
+ }
637
976
  }
977
+ } else {
978
+ body = "";
638
979
  }
980
+ } else {
981
+ body = "";
639
982
  }
640
- let body = result.hasRequestBody ? apiOperator.requestBody : result.hasRequestFormData ? getRequestFormData(apiOperator.rawApiInfo) : null;
641
- if (apiOperator.custom) {
642
- if (apiOperator.method.toUpperCase() == "POST" || apiOperator.method.toUpperCase() == "PUT") {
643
- body = apiOperator.requestBody;
644
- }
645
- }
646
- apiOperator.ifSendingRequest = true;
983
+ ifSendingRequest = true;
647
984
  const startTime = Date.now();
648
985
  apiOperator.controller = new AbortController();
649
986
  const signal = apiOperator.controller.signal;
650
987
  const overlayLayerContainer = createRequestOverlayLayer(apiOperator, responseSectionRef);
651
988
  fetch(reuqestUrl, {
652
- method: apiOperator.method.toUpperCase(),
989
+ method: apiInfo.method.toUpperCase(),
653
990
  headers,
654
- body: body != null ? JSON.stringify(body) : null,
991
+ body,
655
992
  signal
656
993
  }).then((response) => {
657
994
  if (!response.ok) {
658
- apiOperator.response = {
995
+ responseObj = {
659
996
  status: response.status,
660
- statusText: response.statusText
997
+ statusText: response.statusText,
998
+ body: ""
661
999
  };
662
1000
  const endTime2 = Date.now();
663
- apiOperator.requestDuration = formatDuration(endTime2 - startTime);
664
- apiOperator.ifSendingRequest = false;
1001
+ requestDuration = formatDuration(endTime2 - startTime);
1002
+ ifSendingRequest = false;
665
1003
  throw new Error("Network response was not ok.");
666
1004
  }
667
1005
  const endTime = Date.now();
668
- apiOperator.requestDuration = formatDuration(endTime - startTime);
1006
+ requestDuration = formatDuration(endTime - startTime);
669
1007
  const responsebodyElement = responseSectionRef.querySelector('[data-layer="responsebody"]');
670
1008
  responsebodyElement.removeChild(overlayLayerContainer);
671
- apiOperator.ifSendingRequest = false;
672
- apiOperator.response = {
1009
+ ifSendingRequest = false;
1010
+ responseObj = {
673
1011
  status: response.status,
674
1012
  statusText: response.statusText
675
1013
  };
@@ -684,22 +1022,20 @@ function sendRequest(apiOperator, responseSectionRef) {
684
1022
  return responseClone.text();
685
1023
  });
686
1024
  }).then((data) => {
687
- apiOperator.gotResponse = true;
1025
+ gotResponse = true;
688
1026
  const responsebodyElement = responseSectionRef.querySelector('[data-layer="responsebody"]');
689
1027
  if (typeof data === "object") {
690
1028
  console.log("Received JSON:", data);
691
- responsebodyElement.textContent = JSON.stringify(data, null, 4);
1029
+ responseObj.body = JSON.stringify(data, null, 4);
692
1030
  } else {
693
1031
  console.log("Received text:", data);
694
- responsebodyElement.textContent = data;
1032
+ responseObj.body = data;
695
1033
  }
1034
+ responsebodyElement.textContent = responseObj.body;
696
1035
  }).catch((error) => {
697
1036
  console.error("There has been a problem with your fetch operation:", error);
698
1037
  });
699
1038
  }
700
- function updateTimeStatus(timeStatus, apiOperator) {
701
- timeStatus.textContent = `Status: ${apiOperator.response.status || ""} ${apiOperator.response.statusText || ""} Time: ${apiOperator.requestDuration || ""}`;
702
- }
703
1039
  function createRequestOverlayLayer(apiOperator, responseSectionRef) {
704
1040
  const container = document.createElement("div");
705
1041
  Object.assign(container.style, {
@@ -742,28 +1078,6 @@ function createRequestOverlayLayer(apiOperator, responseSectionRef) {
742
1078
  });
743
1079
  return container;
744
1080
  }
745
- function checkIfParameter(apiOperator) {
746
- let hasRequestBody = false;
747
- let hasRequestFormData = false;
748
- const parameters = apiOperator.rawApiInfo.parameters;
749
- if (parameters) {
750
- for (let index = 0; index < parameters.length; index++) {
751
- const parameter = parameters[index];
752
- if (parameter.in == "query" || parameter.in == "path") {
753
- } else if (parameter.in == "body") {
754
- hasRequestBody = true;
755
- parameter.name = parameter.name.charAt(0).toUpperCase() + parameter.name.slice(1);
756
- } else if (parameter.in == "formData") {
757
- hasRequestFormData = true;
758
- }
759
- }
760
- }
761
- const requestBody = apiOperator.rawApiInfo.requestBody;
762
- if (requestBody) {
763
- hasRequestBody = true;
764
- }
765
- return { hasRequestBody, hasRequestFormData };
766
- }
767
1081
  function formatDuration(milliseconds) {
768
1082
  let totalSeconds = Math.floor(milliseconds / 1e3);
769
1083
  let seconds = totalSeconds % 60;
@@ -776,9 +1090,9 @@ function formatDuration(milliseconds) {
776
1090
  seconds = seconds.toString().padStart(2, "0");
777
1091
  return `${hours}h${minutes}m${seconds}s${millisecondsPart}ms`;
778
1092
  }
779
- function getRequestUrl(apiOperator) {
780
- let reuqestUrl = apiOperator.url;
781
- const requestParameters = apiOperator.rawApiInfo.parameters || [];
1093
+ function getRequestUrl(apiInfo) {
1094
+ let reuqestUrl = apiInfo.url;
1095
+ const requestParameters = apiInfo.rawApiInfo.parameters || [];
782
1096
  if (requestParameters == null) {
783
1097
  return reuqestUrl;
784
1098
  }
@@ -787,11 +1101,45 @@ function getRequestUrl(apiOperator) {
787
1101
  reuqestUrl = reuqestUrl.replace("{" + element.name + "}", element.value);
788
1102
  }
789
1103
  }
790
- let queryParams = getQueryParams(apiOperator, requestParameters);
1104
+ let queryParams = getQueryParams(apiInfo, requestParameters);
791
1105
  reuqestUrl = queryParams.length > 0 ? reuqestUrl + "?" + queryParams.join("&") : reuqestUrl;
792
1106
  return reuqestUrl;
793
1107
  }
794
- function getQueryParams(apiOperator, requestParameters) {
1108
+ function addAuthHeader(apiInfo, headers) {
1109
+ const env = isBrowserEnvironment();
1110
+ if (apiInfo.auth.authType == "Basic Auth" && apiInfo.auth != null) {
1111
+ if (env) {
1112
+ const credentials = btoa(`${apiInfo.auth.username}:${apiInfo.auth.passWord}`);
1113
+ headers["Authorization"] = `Basic ${credentials}`;
1114
+ } else {
1115
+ const buffer = Buffer.from(`${apiInfo.auth.username}:${apiInfo.auth.passWord}`);
1116
+ const credentials = buffer.toString("base64");
1117
+ headers["Authorization"] = `Basic ${credentials}`;
1118
+ }
1119
+ } else if (apiInfo.auth.authType == "OAuth 2.0" && apiInfo.auth != null) {
1120
+ if (apiInfo.auth.token != null || apiInfo.auth.token != "") {
1121
+ headers["Authorization"] = `Bearer ${apiInfo.auth.token}`;
1122
+ }
1123
+ }
1124
+ }
1125
+ function getHeadersParams(apiInfo, requestParameters) {
1126
+ let headersParams = [];
1127
+ for (const element of requestParameters) {
1128
+ if (element.in == "header") {
1129
+ headersParams[element.name] = element.value;
1130
+ }
1131
+ }
1132
+ if (apiInfo.customHeaderparameters) {
1133
+ for (let index = 0; index < apiInfo.customHeaderparameters.length; index++) {
1134
+ const paras = apiInfo.customHeaderparameters[index];
1135
+ if (paras.name != "" && paras.value != "" && paras.name != null && paras.value != null) {
1136
+ headersParams[paras.name] = paras.value;
1137
+ }
1138
+ }
1139
+ }
1140
+ return headersParams;
1141
+ }
1142
+ function getQueryParams(apiInfo, requestParameters) {
795
1143
  let queryParams = [];
796
1144
  for (const element of requestParameters) {
797
1145
  if (element.in == "query") {
@@ -806,9 +1154,9 @@ function getQueryParams(apiOperator, requestParameters) {
806
1154
  }
807
1155
  }
808
1156
  }
809
- if (apiOperator.custom) {
810
- for (let index = 0; index < apiOperator.customQueryparameters.length; index++) {
811
- const paras = apiOperator.customQueryparameters[index];
1157
+ if (apiInfo.customQueryparameters) {
1158
+ for (let index = 0; index < apiInfo.customQueryparameters.length; index++) {
1159
+ const paras = apiInfo.customQueryparameters[index];
812
1160
  if (paras.name != "" && paras.value != "" && paras.name != null && paras.value != null) {
813
1161
  queryParams.push(paras.name + "=" + paras.value);
814
1162
  }
@@ -835,6 +1183,15 @@ function getRequestFormData(rawApiInfo) {
835
1183
  }
836
1184
  return formData;
837
1185
  }
1186
+ function isBrowserEnvironment() {
1187
+ if (typeof window !== "undefined" && typeof document !== "undefined") {
1188
+ return true;
1189
+ } else if (typeof process !== "undefined" && process.versions && process.versions.node) {
1190
+ return false;
1191
+ } else {
1192
+ return false;
1193
+ }
1194
+ }
838
1195
  function createSvg() {
839
1196
  const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
840
1197
  svg.setAttribute("width", "21");
@@ -853,18 +1210,16 @@ function createSvg() {
853
1210
  }
854
1211
  function parseParaModel(parameterObj, dataDef) {
855
1212
  let bodyModel;
856
- if (parameterObj && parameterObj.schema) {
857
- if (parameterObj.schema["$ref"]) {
858
- bodyModel = parseModel(parameterObj.schema["$ref"], dataDef);
859
- } else if (parameterObj.schema["type"] == "array") {
860
- const itemObj = parameterObj.schema["items"];
861
- if (itemObj["$ref"]) {
862
- bodyModel = parseModel(itemObj["$ref"], dataDef);
863
- } else if (itemObj["type"]) {
864
- bodyModel = parseElement(itemObj);
865
- }
866
- bodyModel = [bodyModel];
1213
+ if (parameterObj.schema["$ref"]) {
1214
+ bodyModel = parseModel(parameterObj.schema["$ref"], dataDef);
1215
+ } else if (parameterObj.schema["type"] == "array") {
1216
+ const itemObj = parameterObj.schema["items"];
1217
+ if (itemObj["$ref"]) {
1218
+ bodyModel = parseModel(itemObj["$ref"], dataDef);
1219
+ } else if (itemObj["type"]) {
1220
+ bodyModel = parseElement(itemObj);
867
1221
  }
1222
+ bodyModel = [bodyModel];
868
1223
  }
869
1224
  return bodyModel;
870
1225
  }
@@ -895,10 +1250,66 @@ function parseModel(modelDef, apiDef) {
895
1250
  }
896
1251
  return model;
897
1252
  }
1253
+ function parseFormDataModel(modelDef, apiDef) {
1254
+ const model = [];
1255
+ const bodyName = modelDef.substring(modelDef.lastIndexOf("/") + 1);
1256
+ const def = apiDef[bodyName];
1257
+ const props = def["properties"];
1258
+ if (props) {
1259
+ for (const key in props) {
1260
+ if (Object.prototype.hasOwnProperty.call(props, key)) {
1261
+ const element = props[key];
1262
+ let modelEle;
1263
+ if (element.hasOwnProperty("items") && element["type"] == "array") {
1264
+ if (element["items"]["$ref"]) {
1265
+ modelEle = [parseModel(element["items"]["$ref"], apiDef)];
1266
+ } else if (element["items"]["type"]) {
1267
+ modelEle = [parseElement(element["items"])];
1268
+ }
1269
+ if (modelEle) {
1270
+ model.push({
1271
+ type: "string",
1272
+ uiType: "text",
1273
+ name: key,
1274
+ value: JSON.stringify(modelEle)
1275
+ });
1276
+ }
1277
+ } else if (element["type"]) {
1278
+ model.push({
1279
+ type: element["type"],
1280
+ uiType: element["type"] == "integer" || element["type"] == "number" ? "number" : "text",
1281
+ name: key,
1282
+ value: parseElement(element)
1283
+ });
1284
+ } else if (element["$ref"]) {
1285
+ const bodyModel = parseModel(element["$ref"], apiDef);
1286
+ model.push({
1287
+ type: "string",
1288
+ uiType: "text",
1289
+ name: key,
1290
+ value: JSON.stringify(bodyModel)
1291
+ });
1292
+ }
1293
+ }
1294
+ }
1295
+ }
1296
+ return model;
1297
+ }
1298
+ function parseFormDataParaModel(parameterObj, dataDef) {
1299
+ let bodyModel = [];
1300
+ if (parameterObj.schema["$ref"]) {
1301
+ bodyModel = parseFormDataModel(parameterObj.schema["$ref"], dataDef);
1302
+ }
1303
+ return bodyModel;
1304
+ }
898
1305
  function parseElement(element) {
899
1306
  let elementValue;
900
1307
  if (element["type"].includes("integer")) {
901
- elementValue = 0;
1308
+ if (element["enum"]) {
1309
+ elementValue = element["enum"][0];
1310
+ } else {
1311
+ elementValue = 0;
1312
+ }
902
1313
  } else if (element["type"].includes("boolean")) {
903
1314
  elementValue = false;
904
1315
  } else if (element["type"].includes("string")) {
@@ -908,16 +1319,29 @@ function parseElement(element) {
908
1319
  elementValue = "";
909
1320
  }
910
1321
  }
1322
+ if (element["default"]) {
1323
+ elementValue = element["default"];
1324
+ }
911
1325
  if (element["example"]) {
912
1326
  elementValue = element["example"];
913
1327
  }
914
1328
  return elementValue;
915
1329
  }
1330
+ function parseElementType(element) {
1331
+ if (element["type"].includes("integer")) {
1332
+ return "integer";
1333
+ } else if (element["type"].includes("boolean")) {
1334
+ return "boolean";
1335
+ } else if (element["type"].includes("string")) {
1336
+ return "string";
1337
+ }
1338
+ return "string";
1339
+ }
916
1340
  var HTTP_METHODS = ["get", "put", "post", "delete", "options", "head", "patch", "trace"];
917
1341
  function isHttpMethod(method) {
918
1342
  return HTTP_METHODS.includes(method);
919
1343
  }
920
- function parseOpenAPI(openapiSpec) {
1344
+ function parseOpenApiSpec(openapiSpec, currentServer, serviceName) {
921
1345
  const apiOperatorList = [];
922
1346
  const pathEntries = [];
923
1347
  for (const path in openapiSpec.paths) {
@@ -938,51 +1362,99 @@ function parseOpenAPI(openapiSpec) {
938
1362
  }
939
1363
  }
940
1364
  pathItemEntries.forEach(([method, operation]) => {
1365
+ let url = path;
1366
+ if (currentServer) {
1367
+ url = currentServer.value + "/api/" + serviceName + "/v1" + path;
1368
+ } else if (openapiSpec.servers && openapiSpec.servers.length > 0) {
1369
+ url = openapiSpec.servers[0].url + path;
1370
+ }
941
1371
  const apiOperator = {
942
1372
  method: method.toUpperCase(),
943
- url: path,
944
- rawApiInfo: null,
1373
+ url,
1374
+ rawApiInfo: operation,
945
1375
  requestBody: null,
946
1376
  response: {},
947
- auths: [
948
- {
949
- type: "No Auth"
950
- },
951
- {
952
- type: "Basic Auth",
953
- parameters: [
954
- {
955
- name: "userName",
956
- value: ""
957
- },
958
- {
959
- name: "password",
960
- value: ""
961
- }
962
- ]
963
- }
964
- ]
1377
+ auth: {}
965
1378
  };
966
1379
  if (operation) {
967
- if (operation.parameters) {
968
- const parameter = operation.parameters.filter((val) => val.in == "body");
969
- if (parameter && parameter.length > 0) {
1380
+ if (apiOperator.rawApiInfo.parameters) {
1381
+ const parameterBody = apiOperator.rawApiInfo.parameters.filter((val) => val.in == "body");
1382
+ if (parameterBody && parameterBody.length > 0) {
1383
+ apiOperator["requestBody"] = {
1384
+ content: {}
1385
+ };
1386
+ apiOperator["consumes"] = apiOperator.rawApiInfo["consumes"];
1387
+ const currentConsume = apiOperator.rawApiInfo["consumes"].length > 0 ? apiOperator.rawApiInfo["consumes"][0] : "application/json";
1388
+ apiOperator["currentConsume"] = currentConsume;
1389
+ let requestBody = parseParaModel(parameterBody[0], openapiSpec["definitions"]);
1390
+ apiOperator["requestBody"]["content"][currentConsume] = JSON.stringify(requestBody, null, 4);
1391
+ apiOperator["parameterHasBody"] = true;
1392
+ } else {
1393
+ for (const parameter of apiOperator.rawApiInfo.parameters) {
1394
+ if (parameter.in == "query" || parameter.in == "header" || parameter.in == "path" || parameter.in == "formData") {
1395
+ if (parameter.type == "integer" || parameter.schema != null && parameter.schema.type == "integer" || parameter.type == "number" || parameter.schema != null && parameter.schema.type == "number") {
1396
+ parameter.uiType = "number";
1397
+ }
1398
+ if (parameter.type == "string" || parameter.schema != null && parameter.schema.type == "string") {
1399
+ parameter.uiType = "text";
1400
+ }
1401
+ if (parameter.type == "boolean" || parameter.schema != null && parameter.schema.type == "boolean") {
1402
+ parameter.uiType = "text";
1403
+ }
1404
+ }
1405
+ }
1406
+ const parameterFormData = apiOperator.rawApiInfo.parameters.filter((val) => val.in == "formData");
1407
+ if (parameterFormData && parameterFormData.length > 0) {
1408
+ apiOperator["parameterHasFormDataVer2"] = true;
1409
+ }
1410
+ for (const param of apiOperator.rawApiInfo.parameters) {
1411
+ const paramSchema = param.schema;
1412
+ if (paramSchema && paramSchema["$ref"]) {
1413
+ const bodyName = paramSchema["$ref"].substring(paramSchema["$ref"].lastIndexOf("/") + 1);
1414
+ if (openapiSpec && openapiSpec["components"] != null && openapiSpec["components"]["schemas"] != null) {
1415
+ const def = openapiSpec["components"] != null ? openapiSpec["components"]["schemas"][bodyName] : { type: "" };
1416
+ param.type = parseElementType(def);
1417
+ param.uiType = param.type == "integer" || param.type == "number" ? "number" : "text";
1418
+ param.value = parseElement(def);
1419
+ }
1420
+ }
1421
+ }
970
1422
  }
971
1423
  }
972
- if (operation.requestBody) {
973
- const requestBodyObject = operation.requestBody;
974
- const content = requestBodyObject.content;
1424
+ if (apiOperator.rawApiInfo.requestBody) {
1425
+ const content = apiOperator.rawApiInfo.requestBody.content;
1426
+ apiOperator["requestBody"] = {
1427
+ content: {}
1428
+ };
975
1429
  for (const key in content) {
976
1430
  if (Object.prototype.hasOwnProperty.call(content, key)) {
977
1431
  const element = content[key];
1432
+ apiOperator["consumes"]?.push(key);
978
1433
  if (element) {
979
- let requestBody = parseParaModel(element, openapiSpec["components"]["schemas"]);
980
- apiOperator.requestBody = requestBody;
1434
+ if (element.schema == void 0) {
1435
+ console.log("pathKey is:", path);
1436
+ console.log("key is:", key);
1437
+ console.log("content is:", content);
1438
+ console.log("Unsupported requestBody schema format:", element);
1439
+ continue;
1440
+ }
1441
+ if (key != "application/x-www-form-urlencoded" && key != "multipart/form-data") {
1442
+ let requestBody = parseParaModel(element, openapiSpec["components"]["schemas"]);
1443
+ apiOperator["requestBody"]["content"][key] = JSON.stringify(requestBody, null, 4);
1444
+ } else {
1445
+ let requestFormDataBody = parseFormDataParaModel(element, openapiSpec["components"]["schemas"]);
1446
+ apiOperator["requestBody"]["content"][key] = requestFormDataBody;
1447
+ }
1448
+ apiOperator["parameterHasBody"] = true;
981
1449
  }
982
1450
  }
983
1451
  }
1452
+ if (apiOperator.consumes) {
1453
+ if (apiOperator.consumes.length > 0) {
1454
+ apiOperator["currentConsume"] = apiOperator["consumes"][0];
1455
+ }
1456
+ }
984
1457
  }
985
- apiOperator.rawApiInfo = operation;
986
1458
  apiOperatorList.push(apiOperator);
987
1459
  }
988
1460
  });