index.ts 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. import prettier from "prettier";
  2. import { isEmpty, last } from "lodash";
  3. import { createDir, firstUpperCase, readFile, toCamel } from "../../utils";
  4. import { createWriteStream } from "fs";
  5. import { join } from "path";
  6. import config from "./config";
  7. interface Options {
  8. list: {
  9. prefix: string;
  10. name: string;
  11. columns: any[];
  12. api: {
  13. name: string;
  14. method: string;
  15. path: string;
  16. summary: string;
  17. dts: {
  18. parameters: {
  19. description: string;
  20. schema: {
  21. type: string;
  22. };
  23. name: string;
  24. required: boolean;
  25. }[];
  26. };
  27. }[];
  28. }[];
  29. service: {
  30. [key: string]: any;
  31. };
  32. }
  33. // 临时目录路径
  34. const tempPath = join(__dirname, "../../temp");
  35. // 获取类型
  36. function getType({ entityName, propertyName, type }) {
  37. for (const map of config.entity.mapping) {
  38. if (map.custom) {
  39. const resType = map.custom({ entityName, propertyName, type });
  40. if (resType) return resType;
  41. }
  42. if (map.test) {
  43. if (map.test.includes(type)) return map.type;
  44. }
  45. }
  46. return type;
  47. }
  48. // 创建 Entity
  49. function createEntity({ list }: Options) {
  50. const t0: any[] = [];
  51. for (const item of list) {
  52. if (!item.name) continue;
  53. const t = [`interface ${item.name} {`];
  54. for (const col of item.columns || []) {
  55. // 描述
  56. t.push("\n");
  57. t.push("/**\n");
  58. t.push(` * ${col.comment}\n`);
  59. t.push(" */\n");
  60. t.push(
  61. `${col.propertyName}?: ${getType({
  62. entityName: item.name,
  63. propertyName: col.propertyName,
  64. type: col.type
  65. })};`
  66. );
  67. }
  68. t.push("\n");
  69. t.push("/**\n");
  70. t.push(` * 任意键值\n`);
  71. t.push(" */\n");
  72. t.push(`[key: string]: any;`);
  73. t.push("}");
  74. t0.push(t);
  75. }
  76. return t0.map((e) => e.join("")).join("\n\n");
  77. }
  78. // 创建 Service
  79. function createService({ list, service }: Options) {
  80. const t0: any[] = [];
  81. const t1 = [
  82. `type Service = {
  83. request(options?: {
  84. url: string;
  85. method?: 'POST' | 'GET' | string;
  86. data?: any;
  87. params?: any;
  88. proxy?: boolean;
  89. [key: string]: any;
  90. }): Promise<any>;
  91. `
  92. ];
  93. // 处理数据
  94. function deep(d: any, k?: string) {
  95. if (!k) k = "";
  96. for (const i in d) {
  97. const name = k + toCamel(firstUpperCase(i.replace(/[:]/g, "")));
  98. if (d[i].namespace) {
  99. // 查找配置
  100. const item = list.find((e) => (e.prefix || "").includes(d[i].namespace));
  101. if (item) {
  102. const t = [`interface ${name} {`];
  103. t1.push(`${i}: ${name};`);
  104. // 插入方法
  105. if (item.api) {
  106. // 权限列表
  107. const permission: string[] = [];
  108. item.api.forEach((a) => {
  109. // 方法名
  110. const n = toCamel(a.name || last(a.path.split("/")) || "").replace(
  111. /[:\/-]/g,
  112. ""
  113. );
  114. if (n) {
  115. // 参数类型
  116. let q: string[] = [];
  117. // 参数列表
  118. const { parameters = [] } = a.dts || {};
  119. parameters.forEach((p) => {
  120. if (p.description) {
  121. q.push(`\n/** ${p.description} */\n`);
  122. }
  123. if (p.name.includes(":")) {
  124. return false;
  125. }
  126. const a = `${p.name}${p.required ? "" : "?"}`;
  127. const b = `${p.schema.type || "string"}`;
  128. q.push(`${a}: ${b},`);
  129. });
  130. if (isEmpty(q)) {
  131. q = ["any"];
  132. } else {
  133. q.unshift("{");
  134. q.push("}");
  135. }
  136. // 返回类型
  137. let res = "";
  138. // 实体名
  139. const en = item.name || "any";
  140. switch (a.path) {
  141. case "/page":
  142. res = `
  143. {
  144. pagination: { size: number; page: number; total: number };
  145. list: ${en} [];
  146. [key: string]: any;
  147. }
  148. `;
  149. break;
  150. case "/list":
  151. res = `${en} []`;
  152. break;
  153. case "/info":
  154. res = en;
  155. break;
  156. default:
  157. res = "any";
  158. break;
  159. }
  160. // 描述
  161. t.push("\n");
  162. t.push("/**\n");
  163. t.push(` * ${a.summary || n}\n`);
  164. t.push(" */\n");
  165. t.push(
  166. `${n}(data${q.length == 1 ? "?" : ""}: ${q.join(
  167. ""
  168. )}): Promise<${res}>;`
  169. );
  170. }
  171. permission.push(n);
  172. });
  173. // 权限标识
  174. t.push("\n");
  175. t.push("/**\n");
  176. t.push(" * 权限标识\n");
  177. t.push(" */\n");
  178. t.push(
  179. `permission: { ${permission.map((e) => `${e}: string;`).join("\n")} };`
  180. );
  181. // 权限状态
  182. t.push("\n");
  183. t.push("/**\n");
  184. t.push(" * 权限状态\n");
  185. t.push(" */\n");
  186. t.push(
  187. `_permission: { ${permission
  188. .map((e) => `${e}: boolean;`)
  189. .join("\n")} };`
  190. );
  191. // 请求
  192. t.push("\n");
  193. t.push("/**\n");
  194. t.push(" * 请求\n");
  195. t.push(" */\n");
  196. t.push(`request: Service['request']`);
  197. }
  198. t.push("}");
  199. t0.push(t);
  200. }
  201. } else {
  202. t1.push(`${i}: {`);
  203. deep(d[i], name);
  204. t1.push(`},`);
  205. }
  206. }
  207. }
  208. // 深度
  209. deep(service);
  210. // 结束
  211. t1.push("}");
  212. // 追加
  213. t0.push(t1);
  214. return t0.map((e) => e.join("")).join("\n\n");
  215. }
  216. // 创建描述文件
  217. export async function createEps(options: Options) {
  218. // 文件内容
  219. const text = `
  220. declare namespace Eps {
  221. ${createEntity(options)}
  222. ${createService(options)}
  223. }
  224. `;
  225. // 文本内容
  226. const content = prettier.format(text, {
  227. parser: "typescript",
  228. useTabs: true,
  229. tabWidth: 4,
  230. endOfLine: "lf",
  231. semi: true,
  232. singleQuote: false,
  233. printWidth: 100,
  234. trailingComma: "none"
  235. });
  236. // 创建 temp 目录
  237. createDir(tempPath);
  238. // 创建 eps 描述文件
  239. createWriteStream(join(tempPath, "eps.d.ts"), {
  240. flags: "w"
  241. }).write(content);
  242. // 创建 eps 数据文件
  243. createWriteStream(join(tempPath, "eps.json"), {
  244. flags: "w"
  245. }).write(
  246. JSON.stringify(
  247. (options.list || []).map((e) => {
  248. const req = e.api.map((a) => {
  249. const arr = [a.name ? `/${a.name}` : a.path];
  250. if (a.method) {
  251. arr.push(a.method);
  252. }
  253. return arr;
  254. });
  255. return [e.prefix, e.name || "", req];
  256. })
  257. )
  258. );
  259. }
  260. // 获取描述
  261. export function getEps() {
  262. return JSON.stringify(readFile(join(tempPath, "eps.json")));
  263. }