@moneko/core 4.7.4 → 4.7.5

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.
@@ -1,4 +1,33 @@
1
1
  import { IncomingMessage, ServerResponse } from 'node:http';
2
+ /**
3
+ * 将请求 URI 转换为文件名
4
+ * @param uri 请求 URI
5
+ * @returns 文件名
6
+ * @example
7
+ * convertUriToFileName('GET /api/create') => 'GET➯api>create'
8
+ * convertUriToFileName('POST /api/create') => 'POST➯api>create'
9
+ */ declare function convertUriToFileName(uri: string): string;
10
+ interface HarvesterOptions {
11
+ /**
12
+ * 生成的 Mock 文件名
13
+ * @param params 参数
14
+ * @param params.method 请求方法
15
+ * @param params.pathname 请求 URL 的 pathname
16
+ * @param params.convert 转换文件名的函数
17
+ * @returns 文件名,文件名会自动添加到 mock 目录下,如果返回false, 则不生成 Mock 文件
18
+ */ generate?: (params: HarvesterGenerateParams) => string | boolean;
19
+ }
20
+ interface HarvesterGenerateParams {
21
+ /**
22
+ * 请求方法
23
+ */ method: string;
24
+ /**
25
+ * 请求 URL 的 pathname
26
+ */ pathname: string;
27
+ /**
28
+ * 转换文件名的函数
29
+ */ convert: typeof convertUriToFileName;
30
+ }
2
31
  type ProxyItem = {
3
32
  target: string;
4
33
  changeOrigin?: boolean;
@@ -6,7 +35,7 @@ type ProxyItem = {
6
35
  ws?: boolean;
7
36
  pathRewrite?: Record<string, string>;
8
37
  headers?: Record<string, string>;
9
- /** 抓取上游响应数据用于初始化 Mock 数据 */ harvester?: boolean;
38
+ /** 抓取上游响应数据用于初始化 Mock 数据 */ harvester?: HarvesterOptions | boolean;
10
39
  };
11
40
  export type ProxyConfig = Record<string, string | ProxyItem>;
12
41
  type IServerResponse = ServerResponse<IncomingMessage> & {
package/lib/dev/proxy.mjs CHANGED
@@ -1 +1 @@
1
- import{request as e}from"node:http";import{request as t}from"node:https";import{URL as o}from"node:url";import{brotliDecompressSync as r,gunzipSync as n,inflateSync as i}from"node:zlib";import{updateFile as p}from"@moneko/utils";import a from"../commom/log.mjs";import{containMockUrl as s}from"./mock.mjs";export async function setupProxy(m,l,c){if(l.writableEnded)return l;let d=m.url,h=Object.keys(c).find(e=>new RegExp(e).test(d));if(!h)return!1;let f="string"==typeof c[h]?{target:c[h],pathRewrite:void 0,changeOrigin:!0,secure:!0,ws:!1}:c[h],u=new o(f.target),g=d;if(f.pathRewrite&&"object"==typeof f.pathRewrite)for(let e in f.pathRewrite)Object.prototype.hasOwnProperty.call(f.pathRewrite,e)&&(g=d.replace(new RegExp(e),f.pathRewrite[e]));let w="https:"===u.protocol,y={method:m.method,hostname:u.hostname,port:u.port||(w?443:80),path:g,headers:{...m.headers},protocol:u.protocol};f.changeOrigin&&(y.headers.host=u.host);let R=w?t:e;return new Promise(e=>{let t=R(y,t=>{let a=t.statusCode||404,c=a>=400,d=`${m.method||"GET"} ${new o(`${u.origin}${m.url}`).pathname}`,h=!!s(d);if(c&&h)return e(!1);if(l.writeHead(a,t.headers),!c&&!h&&f.harvester){let e=[];t.on("data",t=>e.push(t)),t.on("end",()=>{let o={" ":"➯","/":">",":":"◍"},a=Buffer.concat(e),s=t.headers["content-encoding"]||"",m=null;(m=s.includes("gzip")?n(a).toString():s.includes("br")?r(a).toString():s.includes("deflate")?i(a).toString():a.toString())&&p(`mock/${d.replace(/[\s/:]/g,e=>o[e]||e)}.ts`,`import type { MockConfiguration } from '@moneko/core';const conf: MockConfiguration = {'${d}': ${m}};export default conf;`)})}t.pipe(l),e(l)});t.on("error",t=>(a(t),l.headersSent?l.end():(l.writeHead(502,{"Content-Type":"text/plain"}),l.end(`Proxy Error: ${t.message}`)),e(!1))),m.pipe(t)})}
1
+ import{request as e}from"node:http";import{request as t}from"node:https";import{URL as r}from"node:url";import{brotliDecompressSync as o,gunzipSync as n,inflateSync as i}from"node:zlib";import{updateFile as a}from"@moneko/utils";import p from"../commom/log.mjs";import{isFunction as s,isObject as m}from"../utils/index.mjs";import{containMockUrl as l}from"./mock.mjs";function c(e){let t={" ":"➯","/":">",":":"◍"};return e.replace(/[\s/:]/g,e=>t[e]||e)}export async function setupProxy(h,d,f){if(d.writableEnded)return d;let u=h.url,g=Object.keys(f).find(e=>new RegExp(e).test(u));if(!g)return!1;let w="string"==typeof f[g]?{target:f[g],pathRewrite:void 0,changeOrigin:!0,secure:!0,ws:!1}:f[g],y=new r(w.target),x=u;if(w.pathRewrite&&"object"==typeof w.pathRewrite)for(let e in w.pathRewrite)Object.prototype.hasOwnProperty.call(w.pathRewrite,e)&&(x=u.replace(new RegExp(e),w.pathRewrite[e]));let R="https:"===y.protocol,$={method:h.method,hostname:y.hostname,port:y.port||(R?443:80),path:x,headers:{...h.headers},protocol:y.protocol};w.changeOrigin&&($.headers.host=y.host);let k=R?t:e;return new Promise(e=>{let t=k($,t=>{let p=h.method||"GET",f=new r(`${y.origin}${h.url}`).pathname,u=`${p} ${f}`,g=t.statusCode||404,x=g>=400,R=!!l(u);if(x&&R)return e(!1);if(d.writeHead(g,t.headers),!x&&!R&&w.harvester){let e=m(w.harvester)&&s(w.harvester.generate)?w.harvester.generate({method:p,pathname:f,convert:c}):c(u);if(e){let r=[];t.on("data",e=>r.push(e)),t.on("end",()=>{let p=Buffer.concat(r),s=t.headers["content-encoding"]||"",m=null;(m=s.includes("gzip")?n(p).toString():s.includes("br")?o(p).toString():s.includes("deflate")?i(p).toString():p.toString())&&a(`mock/${e}.ts`,`import type { MockConfiguration } from '@moneko/core';const conf: MockConfiguration = {'${u}': ${m}};export default conf;`)})}}t.pipe(d),e(d)});t.on("error",t=>(p(t),d.headersSent?d.end():(d.writeHead(502,{"Content-Type":"text/plain"}),d.end(`Proxy Error: ${t.message}`)),e(!1))),h.pipe(t)})}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moneko/core",
3
- "version": "4.7.4",
3
+ "version": "4.7.5",
4
4
  "description": "core",
5
5
  "main": "lib/index.mjs",
6
6
  "type": "module",