JsonSchema2Typescript

yapi接口JsonSchema转typescript

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

// ==UserScript==
// @name         JsonSchema2Typescript
// @namespace    https://github.com/codeshareman/tookit.git
// @version      0.3
// @description  yapi接口JsonSchema转typescript
// @author       codeshareman
// @match        *://*/*
// @run-at       document-end
// @license      MIT
// ==/UserScript==

(function () {
  "use strict";
  const TYPE_MAP = {
    string: "string",
    integer: "number",
    boolean: "boolean",
    object: "Object",
    "object []": "array",
  };
  const SCHEMA_TRANS_SITE = "https://app.quicktype.io";

  var _wr = function (type) {
    var orig = history[type];
    return function () {
      var rv = orig.apply(this, arguments);
      var e = new Event(type);
      e.arguments = arguments;
      window.dispatchEvent(e);
      return rv;
    };
  };
  history.pushState = _wr("pushState");
  history.replaceState = _wr("replaceState");

  window.onload = () => {
    function transQuery2Typescript(query) {
      if (query === undefined || query === null) return {};
      return query.reduce((pre, item, index) => {
        const name = item.name;
        pre[name] = "string";
        return pre;
      }, {});
    }

    function transBody2Typescript(body) {
      if (body === undefined || body === null) return {};
      const bodyJson = JSON.parse(body);
      let body_ts = { ...bodyJson };

      function loop(body, preName) {
        const properties = body.properties;
        const fields = properties !== undefined ? Object.keys(properties) : [];
        let transData = {};
        
        if (body.type && !["array"].includes(body.type)) {
          body.title = `${preName}Data`;
        }

        fields.forEach((name) => {
          let fieldData = properties[name];
          const type = fieldData.type;
          if (!["array", "object"].includes(type)) {
            delete fieldData.title;
            transData[name] = fieldData;
          } else {
            const pascalName = name.replace(/^\S/, (s) => s.toUpperCase());
            fieldData.title = preName ? `${preName}${pascalName}` : name;
            transData[name] = fieldData;
            if (type === "array") {
              transData[name].items.properties = loop(fieldData.items, name);
            } else {
              transData[name].properties = loop(fieldData, name);
            }
          }
        });
        return transData;
      }

      if (bodyJson !== undefined) {
        body_ts.properties = loop(bodyJson);
      }

      return body_ts;
    }

    function css(target, style) {
      for (const property in style) {
        target.style[property] = style[property];
      }
    }

    function copyText(text, onSuccess) {
      if (navigator.clipboard) {
        // clipboard api 复制
        navigator.clipboard.writeText(text).then(onSuccess);
      } else {
        var textarea = document.createElement("textarea");
        document.body.appendChild(textarea);
        // 隐藏此输入框
        textarea.style.position = "fixed";
        textarea.style.clip = "rect(0 0 0 0)";
        textarea.style.top = "10px";
        // 赋值
        textarea.value = text;
        // 选中
        textarea.select();
        // 复制
        document.execCommand("copy", true);
        // 移除输入框
        document.body.removeChild(textarea);
        onSuccess();
      }
    }

    function generateTypescriptElement(target, originContent) {
      const content = JSON.stringify(originContent, null, 2);

      // 清除旧节点
      const oldEle = document.querySelector(".code-typescript");
      oldEle && oldEle.remove();

      if (target === undefined || target === null) return;

      const $ele_ts_wrapper = document.createElement("div");
      const $ele_header = document.createElement("div");
      const $ele_copy = document.createElement("a");
      const $ele_code = document.createElement("pre");

      $ele_header.innerHTML = `请将复制的内容粘贴到 ${SCHEMA_TRANS_SITE} 的左侧源内容区,SourceType选择JSON Schema,即可将schema转换为typescript`;
      $ele_ts_wrapper.className = "code-typescript";
      css($ele_ts_wrapper, {
        position: "relative",
        margin: "8px 0",
        padding: "30px 12px 12px 4px",
        background: "#f9f9f9",
        border: "1px solid #ebe7e7",
        boxShadow: "0px 0px 12px #eee",
      });
      css($ele_header, {
        position: "absolute",
        width: "100%",
        top: 0,
        left: 0,
        background: "#e3e3e3",
        padding: "4px 12px",
      });
      css($ele_code, {
        height: "500px",
        overflowY: "auto",
      });
      $ele_ts_wrapper.appendChild($ele_header);
      $ele_ts_wrapper.appendChild($ele_code);
      $ele_code.innerText = content;
      $ele_copy.innerText = "复制(copy)";

      css($ele_copy, {
        position: "absolute",
        right: "0px",
        top: "0px",
        height: "27px",
        lineHeight: "27px",
        background: "#d93326",
        padding: "0 8px",
        color: "#fff",
      });

      let copied = false;
      $ele_copy.addEventListener("click", () => {
        if (copied) return;
        copyText(content, () => {
          copied = true;
          $ele_copy.innerText = "已复制";
          const $ele_a = document.createElement("a");
          $ele_a.href = SCHEMA_TRANS_SITE;
          $ele_a.target = "_blank";
          $ele_a.click();
          $ele_a.remove();
          setTimeout(() => {
            copied = false;
            $ele_copy.innerText = "复制(copy)";
          }, 1000);
        });
      });
      $ele_header.appendChild($ele_copy);
      target.appendChild($ele_ts_wrapper);
    }

    function transApi2Typescript() {
      const ORIGIN = location.origin;
      const API_ID = location.pathname.split("/").pop();
      const url = `${ORIGIN}/api/interface/get?id=${API_ID}`;
      fetch(url)
        .then((res) => res.json())
        .then((data) => {
          if (data !== undefined) {
            const errCode = data.errcode;
            if (errCode === 0) {
              const resData = data.data;
              const query = resData.req_query;
              const body = resData.res_body;

              const query_ts = transQuery2Typescript(query);
              const $ele_query = document.querySelector(".colQuery");
              generateTypescriptElement($ele_query, query_ts);

              const body_ts = transBody2Typescript(body);
              const $ele_body = document.querySelector(".caseContainer");
              generateTypescriptElement($ele_body, body_ts);
            }
          }
        });
    }

    transApi2Typescript();

    window.addEventListener("popstate", function (event) {
      transApi2Typescript();
    });

    window.addEventListener("pushState", function (e) {
      transApi2Typescript();
    });

    window.addEventListener("replaceState", function (e) {
      transApi2Typescript();
    });
  };
})();