@schmock/express 2.4.1 → 2.6.0

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.d.ts CHANGED
@@ -23,8 +23,20 @@ export interface ExpressAdapterOptions {
23
23
  */
24
24
  transformHeaders?: (headers: Request["headers"]) => Record<string, string>;
25
25
  /**
26
- * Custom query transformation
27
- * @param query - Express query
26
+ * Custom query transformation.
27
+ *
28
+ * Without it, the adapter ignores `req.query` and re-reads the query string
29
+ * of `req.url` (the URL `req.path` comes from, so a rewrite by earlier
30
+ * middleware moves path and query together) with the CLI's parser: keys
31
+ * stay literal (`filter[name]`, `sort[]`), a repeated key resolves to its
32
+ * last value, and a `req.query` that earlier middleware assigned or
33
+ * redefined is ignored.
34
+ *
35
+ * Supplying `transformQuery` switches that default off: it receives
36
+ * `req.query` as Express parsed it (qs-nested values under the "extended"
37
+ * parser, plus any change earlier middleware made), and its return value
38
+ * is the query the mock sees.
39
+ * @param query - `req.query` as Express, or earlier middleware, left it
28
40
  * @returns Transformed query for Schmock
29
41
  */
30
42
  transformQuery?: (query: Request["query"]) => Record<string, string>;
@@ -48,4 +60,3 @@ export interface ExpressAdapterOptions {
48
60
  * Convert a Schmock mock instance to Express middleware
49
61
  */
50
62
  export declare function toExpress(mock: Schmock.CallableMockInstance, options?: ExpressAdapterOptions): RequestHandler;
51
- //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{getResponseException as E,isBinaryBody as y,isRouteNotFound as g,normalizeResponse as b,SchmockError as v,serializeResponseBody as k,toHttpMethod as M}from"@schmock/core";var R=Symbol.for("@schmock/core.request-admission");function q(G){return typeof G==="object"&&G!==null&&"handle"in G&&typeof G.handle==="function"&&"release"in G&&typeof G.release==="function"}function p(G){let K=Reflect.get(G,R);if(typeof K!=="function")return;let L=Reflect.apply(K,G,[]);if(!q(L))throw Error("Schmock returned an invalid request admission");return L}function h(G){let K={};for(let[L,V]of Object.entries(G??{})){if(L.toLowerCase()==="content-type")continue;K[L]=V}return K["content-type"]="application/json",K}function T(G){if("reason"in G&&G.reason!==void 0)return G.reason;let K=Error("Request aborted");return K.name="AbortError",K}function P(G,K){if(K.aborted)return Promise.reject(T(K));return new Promise((L,V)=>{let Z=!1,J=($)=>{if(Z)return;Z=!0,K.removeEventListener("abort",U),$()},U=()=>J(()=>V(T(K)));K.addEventListener("abort",U,{once:!0}),Promise.resolve(G).then(($)=>J(()=>L($)),($)=>J(()=>V($)))})}function w(G,K,L){let V={...G.headers};if(!Object.keys(V).some(($)=>$.toLowerCase()==="content-type")&&G.body!==null&&G.body!==void 0){if(y(G.body))V["content-type"]="application/octet-stream";else if(typeof G.body!=="string")V["content-type"]="application/json"}let J=b({...G,headers:V},K);L.status(J.status);for(let[$,Y]of Object.entries(J.headers))L.set($,Y);let U=k(J);L.end(U===void 0?void 0:Buffer.from(U))}function D(G,K,L,V,Z,J={}){try{let U=G(K,L);try{w({status:500,body:U,headers:h(J)},V,Z)}catch{w({status:500,body:U,headers:{"content-type":"application/json"}},V,Z)}}catch{if(!Z.headersSent)Z.status(500),Z.set("content-type","application/json");if(!Z.writableEnded)Z.end(Z.headersSent?void 0:Buffer.from(JSON.stringify({error:"Internal Server Error",code:"INTERNAL_ERROR"})))}}function u(G){return Object.fromEntries(Object.entries(G).map(([K,L])=>[K,Array.isArray(L)?L[0]:L]).filter((K)=>typeof K[1]==="string"))}function d(G){let K={};for(let[L,V]of Object.entries(G))if(typeof V==="string")K[L]=V;else if(Array.isArray(V))K[L]=V[0]?String(V[0]):"";else if(V!=null)K[L]=String(V);return K}function c(G,K={}){let{errorFormatter:L,passErrorsToNext:V=!0,transformHeaders:Z=u,transformQuery:J=d,beforeRequest:U,beforeResponse:$}=K;return async(Y,X,j)=>{let B=new AbortController,S=()=>B.abort(),H=()=>{if(!X.writableFinished)B.abort()},A=typeof Y.once==="function",F=typeof X.once==="function";if(A)Y.once("aborted",S);if(F)X.once("close",H);let N,Q="GET";try{N=p(G);let _=N?.handle??((I,f,x)=>G.handle(I,f,x));Q=Y.method.toUpperCase()==="HEAD"?"HEAD":"GET";let W;try{W=M(Y.method),Q=W}catch{return j()}let z={method:W,path:Y.path,headers:Z(Y.headers),body:Y.body,query:J(Y.query)};if(U){let I=await P(U(Y,X),B.signal);if(I)z={...z,...I,method:M(I.method||z.method)},Q=z.method}if(X.headersSent||X.writableEnded)return;let O=await P(_(z.method,z.path,{headers:z.headers,body:z.body,query:z.query,signal:B.signal}),B.signal),C=E(O);if(g(O)){j();return}if($){let I=await P($(O,Y,X),B.signal);if(I)O=I}if(X.headersSent||X.writableEnded)return;if(L&&C&&O.status===500){D(L,C,Y,z.method,X,O.headers);return}w(O,z.method,X)}catch(_){if(B.signal.aborted)return;if(X.headersSent){if(V)j(_);else if(!X.writableEnded)X.end();return}if(X.writableEnded)return;if(L){let W=_ instanceof Error?_:Error(String(_));D(L,W,Y,Q,X)}else if(V)j(_);else w({status:500,body:{error:_ instanceof Error?_.message:"Internal Server Error",code:_ instanceof v?_.code:"INTERNAL_ERROR"},headers:{"content-type":"application/json"}},Q,X)}finally{if(A)Y.off("aborted",S);if(F)X.off("close",H);N?.release()}}}export{c as toExpress};
1
+ import{buildFormattedErrorResponse as x,getResponseException as f,isRouteNotFound as b,normalizeResponse as y,parseNodeQuery as k,SchmockError as v,serializeResponseBody as R,toHttpMethod as M,withDefaultContentType as i}from"@schmock/core";import{acquireRequestAdmission as h,awaitWithAbort as W}from"@schmock/core/adapter";function H(G,I,j){let J=y(i(G),I);j.status(J.status);for(let[g,z]of Object.entries(J.headers))j.setHeader(g,z);let _=R(J);j.end(_===void 0?void 0:Buffer.from(_))}function C(G){let{errorFormatter:I,req:j,res:J,method:_}=G,g=x({formatter:(z)=>I(z,j),error:G.error,inheritedHeaders:G.inheritedHeaders,method:_});try{H(g,_,J)}catch{if(!J.headersSent)J.status(500),J.setHeader("content-type","application/json");if(!J.writableEnded)J.end(J.headersSent?void 0:Buffer.from(JSON.stringify({error:"Internal Server Error",code:"INTERNAL_ERROR"})))}}function c(G){return Object.fromEntries(Object.entries(G).map(([I,j])=>[I,Array.isArray(j)?j[0]:j]).filter((I)=>typeof I[1]==="string"))}function N(G,I,j){if(Array.isArray(j)){if(j.length===0)G[I]="";for(let J of j)N(G,I,J)}else if(typeof j==="object"&&j!==null)for(let[J,_]of Object.entries(j))N(G,`${I}[${J}]`,_);else if(j!==null&&j!==void 0)G[I]=String(j)}function p(G){let I={};for(let[j,J]of Object.entries(G))N(I,j,J);return I}function m(G){let I=G.url??G.originalUrl;if(typeof I==="string")try{return k(new URL(I,"http://localhost"))}catch{}return p(G.query??{})}function l(G,I={}){let{errorFormatter:j,passErrorsToNext:J=!0,transformHeaders:_=c,transformQuery:g,beforeRequest:z,beforeResponse:P}=I;return async(X,L,U)=>{let B=new AbortController,w=()=>B.abort(),A=()=>{if(!L.writableFinished)B.abort()},Q=typeof X.once==="function",T=typeof L.once==="function";if(Q)X.once("aborted",w);if(T)L.once("close",A);let V,O="GET";try{V=h(G);let Y=V?.handle??(($,D,E)=>G.handle($,D,E));O=X.method.toUpperCase()==="HEAD"?"HEAD":"GET";let S;try{S=M(X.method),O=S}catch{return U()}let Z={method:S,path:X.path,headers:_(X.headers),body:X.body,query:g?g(X.query):m(X)};if(z){let $=await W(z(X,L),B.signal);if($)Z={...Z,...$,method:M($.method||Z.method)},O=Z.method}if(L.headersSent||L.writableEnded)return;let K=await W(Y(Z.method,Z.path,{headers:Z.headers,body:Z.body,query:Z.query,signal:B.signal}),B.signal),F=f(K);if(b(K)){U();return}if(P){let $=await W(P(K,X,L),B.signal);if($)K=$}if(L.headersSent||L.writableEnded)return;if(j&&F&&K.status===500){C({errorFormatter:j,error:F,req:X,res:L,method:Z.method,inheritedHeaders:K.headers});return}H(K,Z.method,L)}catch(Y){if(B.signal.aborted)return;if(L.headersSent){if(J)U(Y);else if(!L.writableEnded)L.end();return}if(L.writableEnded)return;if(j){let S=Y instanceof Error?Y:Error(String(Y));C({errorFormatter:j,error:S,req:X,res:L,method:O})}else if(J)U(Y);else H({status:500,body:{error:Y instanceof Error?Y.message:"Internal Server Error",code:Y instanceof v?Y.code:"INTERNAL_ERROR"},headers:{"content-type":"application/json"}},O,L)}finally{if(Q)X.off("aborted",w);if(T)L.off("close",A);V?.release()}}}export{l as toExpress};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schmock/express",
3
- "version": "2.4.1",
3
+ "version": "2.6.0",
4
4
  "description": "Express adapter for Schmock mock API generator",
5
5
  "type": "module",
6
6
  "repository": {
@@ -17,7 +17,8 @@
17
17
  "exports": {
18
18
  ".": {
19
19
  "types": "./dist/index.d.ts",
20
- "import": "./dist/index.js"
20
+ "import": "./dist/index.js",
21
+ "default": "./dist/index.js"
21
22
  },
22
23
  "./package.json": "./package.json"
23
24
  },
@@ -50,7 +51,7 @@
50
51
  "vitest": "^4.1.7"
51
52
  },
52
53
  "peerDependencies": {
53
- "@schmock/core": "^2.4.1",
54
+ "@schmock/core": "^2.6.0",
54
55
  "express": "^4.18.0 || ^5.0.0"
55
56
  },
56
57
  "keywords": [
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,OAAO,MAAM,eAAe,CAAC;AAU9C,OAAO,KAAK,EAAgB,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAuF/E;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;;OAKG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC;IAEzD;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE3E;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAErE;;;;;OAKG;IACH,aAAa,CAAC,EAAE,CACd,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,KAEX,OAAO,CAAC,sBAAsB,GAC9B,SAAS,GACT,OAAO,CAAC,OAAO,CAAC,sBAAsB,GAAG,SAAS,CAAC,CAAC;IAExD;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,CACf,eAAe,EAAE,OAAO,CAAC,QAAQ,EACjC,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,KACV,OAAO,CAAC,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC;CAC3E;AAkJD;;GAEG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,OAAO,CAAC,oBAAoB,EAClC,OAAO,GAAE,qBAA0B,GAClC,cAAc,CAsLhB"}