@schmock/angular 1.5.1 → 1.5.2
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 +1 -263
- package/package.json +2 -3
package/dist/index.js
CHANGED
|
@@ -1,263 +1 @@
|
|
|
1
|
-
var
|
|
2
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
4
|
-
r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
-
else
|
|
6
|
-
for (var i = decorators.length - 1;i >= 0; i--)
|
|
7
|
-
if (d = decorators[i])
|
|
8
|
-
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
9
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
// src/index.ts
|
|
13
|
-
import {
|
|
14
|
-
HTTP_INTERCEPTORS,
|
|
15
|
-
HttpErrorResponse,
|
|
16
|
-
HttpHeaders,
|
|
17
|
-
HttpResponse
|
|
18
|
-
} from "@angular/common/http";
|
|
19
|
-
import { Injectable } from "@angular/core";
|
|
20
|
-
import { isHttpMethod, ROUTE_NOT_FOUND_CODE } from "@schmock/core";
|
|
21
|
-
import { Observable } from "rxjs";
|
|
22
|
-
function toHttpMethod(method) {
|
|
23
|
-
const upper = method.toUpperCase();
|
|
24
|
-
if (isHttpMethod(upper)) {
|
|
25
|
-
return upper;
|
|
26
|
-
}
|
|
27
|
-
return "GET";
|
|
28
|
-
}
|
|
29
|
-
function getStatusText(status) {
|
|
30
|
-
const statusTexts = {
|
|
31
|
-
200: "OK",
|
|
32
|
-
201: "Created",
|
|
33
|
-
204: "No Content",
|
|
34
|
-
400: "Bad Request",
|
|
35
|
-
401: "Unauthorized",
|
|
36
|
-
403: "Forbidden",
|
|
37
|
-
404: "Not Found",
|
|
38
|
-
500: "Internal Server Error"
|
|
39
|
-
};
|
|
40
|
-
return statusTexts[status] || "Unknown";
|
|
41
|
-
}
|
|
42
|
-
function extractQueryParams(request) {
|
|
43
|
-
const result = {};
|
|
44
|
-
request.params.keys().forEach((key) => {
|
|
45
|
-
const value = request.params.get(key);
|
|
46
|
-
if (value !== null) {
|
|
47
|
-
result[key] = value;
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
const url = request.url;
|
|
51
|
-
const queryStart = url.indexOf("?");
|
|
52
|
-
if (queryStart !== -1) {
|
|
53
|
-
const urlParams = new URLSearchParams(url.slice(queryStart + 1));
|
|
54
|
-
urlParams.forEach((value, key) => {
|
|
55
|
-
if (!(key in result)) {
|
|
56
|
-
result[key] = value;
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
return result;
|
|
61
|
-
}
|
|
62
|
-
function extractPathname(url) {
|
|
63
|
-
const queryStart = url.indexOf("?");
|
|
64
|
-
const urlWithoutQuery = queryStart === -1 ? url : url.slice(0, queryStart);
|
|
65
|
-
if (urlWithoutQuery.includes("://")) {
|
|
66
|
-
try {
|
|
67
|
-
const parsed = new URL(urlWithoutQuery);
|
|
68
|
-
return parsed.pathname;
|
|
69
|
-
} catch {}
|
|
70
|
-
}
|
|
71
|
-
if (!urlWithoutQuery.startsWith("/")) {
|
|
72
|
-
return `/${urlWithoutQuery}`;
|
|
73
|
-
}
|
|
74
|
-
return urlWithoutQuery;
|
|
75
|
-
}
|
|
76
|
-
function headersToObject(request) {
|
|
77
|
-
const headers = {};
|
|
78
|
-
request.headers.keys().forEach((key) => {
|
|
79
|
-
const value = request.headers.get(key);
|
|
80
|
-
if (value !== null) {
|
|
81
|
-
headers[key] = value;
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
return headers;
|
|
85
|
-
}
|
|
86
|
-
function createSchmockInterceptor(mock, options = {}) {
|
|
87
|
-
const {
|
|
88
|
-
baseUrl,
|
|
89
|
-
passthrough = true,
|
|
90
|
-
errorFormatter,
|
|
91
|
-
transformRequest,
|
|
92
|
-
transformResponse
|
|
93
|
-
} = options;
|
|
94
|
-
|
|
95
|
-
class SchmockInterceptor {
|
|
96
|
-
intercept(req, next) {
|
|
97
|
-
const path = extractPathname(req.url);
|
|
98
|
-
if (baseUrl && !path.startsWith(baseUrl)) {
|
|
99
|
-
return next.handle(req);
|
|
100
|
-
}
|
|
101
|
-
const query = extractQueryParams(req);
|
|
102
|
-
let requestData = {
|
|
103
|
-
method: toHttpMethod(req.method),
|
|
104
|
-
path,
|
|
105
|
-
headers: headersToObject(req),
|
|
106
|
-
body: req.body,
|
|
107
|
-
query
|
|
108
|
-
};
|
|
109
|
-
if (transformRequest) {
|
|
110
|
-
const transformed = transformRequest(req);
|
|
111
|
-
requestData = {
|
|
112
|
-
...requestData,
|
|
113
|
-
...transformed,
|
|
114
|
-
method: toHttpMethod(transformed.method ?? req.method)
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
return new Observable((observer) => {
|
|
118
|
-
let innerSub;
|
|
119
|
-
let aborted = false;
|
|
120
|
-
mock.handle(requestData.method, requestData.path, {
|
|
121
|
-
headers: requestData.headers,
|
|
122
|
-
body: requestData.body,
|
|
123
|
-
query: requestData.query
|
|
124
|
-
}).then((schmockResponse) => {
|
|
125
|
-
if (aborted)
|
|
126
|
-
return;
|
|
127
|
-
const body = schmockResponse.body;
|
|
128
|
-
const isRouteNotFound = schmockResponse.status === 404 && body !== null && typeof body === "object" && "code" in body && body.code === ROUTE_NOT_FOUND_CODE;
|
|
129
|
-
if (isRouteNotFound && passthrough) {
|
|
130
|
-
innerSub = next.handle(req).subscribe(observer);
|
|
131
|
-
} else if (isRouteNotFound) {
|
|
132
|
-
observer.error(new HttpErrorResponse({
|
|
133
|
-
error: { message: "No matching mock route found" },
|
|
134
|
-
status: 404,
|
|
135
|
-
statusText: "Not Found",
|
|
136
|
-
url: req.url
|
|
137
|
-
}));
|
|
138
|
-
} else {
|
|
139
|
-
let response = schmockResponse;
|
|
140
|
-
if (transformResponse) {
|
|
141
|
-
response = transformResponse(response, req);
|
|
142
|
-
}
|
|
143
|
-
const status = response.status || 200;
|
|
144
|
-
if (status >= 400) {
|
|
145
|
-
let errorBody = response.body;
|
|
146
|
-
const respBody = response.body;
|
|
147
|
-
if (status === 500 && errorFormatter && respBody !== null && typeof respBody === "object" && "error" in respBody && "code" in respBody) {
|
|
148
|
-
const errMsg = typeof respBody.error === "string" ? respBody.error : "Unknown error";
|
|
149
|
-
const error = new Error(errMsg);
|
|
150
|
-
errorBody = errorFormatter(error, req);
|
|
151
|
-
}
|
|
152
|
-
observer.error(new HttpErrorResponse({
|
|
153
|
-
error: errorBody,
|
|
154
|
-
status,
|
|
155
|
-
statusText: getStatusText(status),
|
|
156
|
-
url: req.url,
|
|
157
|
-
headers: new HttpHeaders(response.headers || {})
|
|
158
|
-
}));
|
|
159
|
-
} else {
|
|
160
|
-
const httpResponse = new HttpResponse({
|
|
161
|
-
body: response.body,
|
|
162
|
-
status,
|
|
163
|
-
statusText: getStatusText(status),
|
|
164
|
-
url: req.url,
|
|
165
|
-
headers: new HttpHeaders(response.headers || {})
|
|
166
|
-
});
|
|
167
|
-
observer.next(httpResponse);
|
|
168
|
-
observer.complete();
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}).catch((error) => {
|
|
172
|
-
if (aborted)
|
|
173
|
-
return;
|
|
174
|
-
let errorBody;
|
|
175
|
-
if (errorFormatter) {
|
|
176
|
-
errorBody = errorFormatter(error instanceof Error ? error : new Error(String(error)), req);
|
|
177
|
-
} else {
|
|
178
|
-
const hasCode = error !== null && typeof error === "object" && "code" in error && typeof error.code === "string";
|
|
179
|
-
errorBody = {
|
|
180
|
-
error: error instanceof Error ? error.message : "Internal Server Error",
|
|
181
|
-
code: hasCode ? error.code : "INTERNAL_ERROR"
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
observer.error(new HttpErrorResponse({
|
|
185
|
-
error: errorBody,
|
|
186
|
-
status: 500,
|
|
187
|
-
statusText: "Internal Server Error",
|
|
188
|
-
url: req.url
|
|
189
|
-
}));
|
|
190
|
-
});
|
|
191
|
-
return () => {
|
|
192
|
-
aborted = true;
|
|
193
|
-
innerSub?.unsubscribe();
|
|
194
|
-
};
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
SchmockInterceptor = __legacyDecorateClassTS([
|
|
199
|
-
Injectable()
|
|
200
|
-
], SchmockInterceptor);
|
|
201
|
-
return SchmockInterceptor;
|
|
202
|
-
}
|
|
203
|
-
function provideSchmockInterceptor(mock, options) {
|
|
204
|
-
return {
|
|
205
|
-
provide: HTTP_INTERCEPTORS,
|
|
206
|
-
useClass: createSchmockInterceptor(mock, options),
|
|
207
|
-
multi: true
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
function notFound(message = "Not Found") {
|
|
211
|
-
const body = typeof message === "string" ? { message } : message;
|
|
212
|
-
return [404, body];
|
|
213
|
-
}
|
|
214
|
-
function badRequest(message = "Bad Request") {
|
|
215
|
-
const body = typeof message === "string" ? { message } : message;
|
|
216
|
-
return [400, body];
|
|
217
|
-
}
|
|
218
|
-
function unauthorized(message = "Unauthorized") {
|
|
219
|
-
const body = typeof message === "string" ? { message } : message;
|
|
220
|
-
return [401, body];
|
|
221
|
-
}
|
|
222
|
-
function forbidden(message = "Forbidden") {
|
|
223
|
-
const body = typeof message === "string" ? { message } : message;
|
|
224
|
-
return [403, body];
|
|
225
|
-
}
|
|
226
|
-
function serverError(message = "Internal Server Error") {
|
|
227
|
-
const body = typeof message === "string" ? { message } : message;
|
|
228
|
-
return [500, body];
|
|
229
|
-
}
|
|
230
|
-
function created(body) {
|
|
231
|
-
return [201, body];
|
|
232
|
-
}
|
|
233
|
-
function noContent() {
|
|
234
|
-
return [204, null];
|
|
235
|
-
}
|
|
236
|
-
function paginate(items, options = {}) {
|
|
237
|
-
const page = options.page || 1;
|
|
238
|
-
const pageSize = options.pageSize || 10;
|
|
239
|
-
const total = items.length;
|
|
240
|
-
const totalPages = Math.ceil(total / pageSize);
|
|
241
|
-
const start = (page - 1) * pageSize;
|
|
242
|
-
const end = start + pageSize;
|
|
243
|
-
const data = items.slice(start, end);
|
|
244
|
-
return {
|
|
245
|
-
data,
|
|
246
|
-
page,
|
|
247
|
-
pageSize,
|
|
248
|
-
total,
|
|
249
|
-
totalPages
|
|
250
|
-
};
|
|
251
|
-
}
|
|
252
|
-
export {
|
|
253
|
-
unauthorized,
|
|
254
|
-
serverError,
|
|
255
|
-
provideSchmockInterceptor,
|
|
256
|
-
paginate,
|
|
257
|
-
notFound,
|
|
258
|
-
noContent,
|
|
259
|
-
forbidden,
|
|
260
|
-
created,
|
|
261
|
-
createSchmockInterceptor,
|
|
262
|
-
badRequest
|
|
263
|
-
};
|
|
1
|
+
var O=function(A,J,K,L){var Y=arguments.length,V=Y<3?J:L===null?L=Object.getOwnPropertyDescriptor(J,K):L,$;if(typeof Reflect==="object"&&typeof Reflect.decorate==="function")V=Reflect.decorate(A,J,K,L);else for(var w=A.length-1;w>=0;w--)if($=A[w])V=(Y<3?$(V):Y>3?$(J,K,V):$(J,K))||V;return Y>3&&V&&Object.defineProperty(J,K,V),V};import{HTTP_INTERCEPTORS as H,HttpErrorResponse as f,HttpHeaders as E,HttpResponse as v}from"@angular/common/http";import{Injectable as R}from"@angular/core";import{isHttpMethod as S,ROUTE_NOT_FOUND_CODE as b}from"@schmock/core";import{Observable as k}from"rxjs";function D(A){let J=A.toUpperCase();if(S(J))return J;return"GET"}function x(A){return{200:"OK",201:"Created",204:"No Content",400:"Bad Request",401:"Unauthorized",403:"Forbidden",404:"Not Found",500:"Internal Server Error"}[A]||"Unknown"}function l(A){let J={};A.params.keys().forEach((Y)=>{let V=A.params.get(Y);if(V!==null)J[Y]=V});let K=A.url,L=K.indexOf("?");if(L!==-1)new URLSearchParams(K.slice(L+1)).forEach((V,$)=>{if(!($ in J))J[$]=V});return J}function h(A){let J=A.indexOf("?"),K=J===-1?A:A.slice(0,J);if(K.includes("://"))try{return new URL(K).pathname}catch{}if(!K.startsWith("/"))return`/${K}`;return K}function i(A){let J={};return A.headers.keys().forEach((K)=>{let L=A.headers.get(K);if(L!==null)J[K]=L}),J}function d(A,J={}){let{baseUrl:K,passthrough:L=!0,errorFormatter:Y,transformRequest:V,transformResponse:$}=J;class w{intercept(X,z){let Q=h(X.url);if(K&&!Q.startsWith(K))return z.handle(X);let T=l(X),M={method:D(X.method),path:Q,headers:i(X),body:X.body,query:T};if(V){let G=V(X);M={...M,...G,method:D(G.method??X.method)}}return new k((G)=>{let F,W=!1;return A.handle(M.method,M.path,{headers:M.headers,body:M.body,query:M.query}).then((Z)=>{if(W)return;let j=Z.body,N=Z.status===404&&j!==null&&typeof j==="object"&&"code"in j&&j.code===b;if(N&&L)F=z.handle(X).subscribe(G);else if(N)G.error(new f({error:{message:"No matching mock route found"},status:404,statusText:"Not Found",url:X.url}));else{let C=Z;if($)C=$(C,X);let U=C.status||200;if(U>=400){let{body:P,body:_}=C;if(U===500&&Y&&_!==null&&typeof _==="object"&&"error"in _&&"code"in _){let B=typeof _.error==="string"?_.error:"Unknown error",I=Error(B);P=Y(I,X)}G.error(new f({error:P,status:U,statusText:x(U),url:X.url,headers:new E(C.headers||{})}))}else{let P=new v({body:C.body,status:U,statusText:x(U),url:X.url,headers:new E(C.headers||{})});G.next(P),G.complete()}}}).catch((Z)=>{if(W)return;let j;if(Y)j=Y(Z instanceof Error?Z:Error(String(Z)),X);else{let N=Z!==null&&typeof Z==="object"&&"code"in Z&&typeof Z.code==="string";j={error:Z instanceof Error?Z.message:"Internal Server Error",code:N?Z.code:"INTERNAL_ERROR"}}G.error(new f({error:j,status:500,statusText:"Internal Server Error",url:X.url}))}),()=>{W=!0,F?.unsubscribe()}})}}return w=O([R()],w),w}function m(A,J){return{provide:H,useClass:d(A,J),multi:!0}}function p(A="Not Found"){return[404,typeof A==="string"?{message:A}:A]}function u(A="Bad Request"){return[400,typeof A==="string"?{message:A}:A]}function a(A="Unauthorized"){return[401,typeof A==="string"?{message:A}:A]}function o(A="Forbidden"){return[403,typeof A==="string"?{message:A}:A]}function t(A="Internal Server Error"){return[500,typeof A==="string"?{message:A}:A]}function s(A){return[201,A]}function r(){return[204,null]}function e(A,J={}){let K=J.page||1,L=J.pageSize||10,Y=A.length,V=Math.ceil(Y/L),$=(K-1)*L,w=$+L;return{data:A.slice($,w),page:K,pageSize:L,total:Y,totalPages:V}}export{a as unauthorized,t as serverError,m as provideSchmockInterceptor,e as paginate,p as notFound,r as noContent,o as forbidden,s as created,d as createSchmockInterceptor,u as badRequest};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@schmock/angular",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.2",
|
|
4
4
|
"description": "Angular HTTP interceptor adapter for Schmock",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"dev": "bun build:lib --watch",
|
|
19
19
|
"clean": "rm -rf dist",
|
|
20
20
|
"build": "bun run clean && bun run build:lib && bun run build:types",
|
|
21
|
-
"build:lib": "bun build src/index.ts --outdir dist --target node --format esm --external @angular/common --external @angular/core --external @schmock/core --external rxjs",
|
|
21
|
+
"build:lib": "bun build --minify src/index.ts --outdir dist --target node --format esm --external @angular/common --external @angular/core --external @schmock/core --external rxjs",
|
|
22
22
|
"build:types": "rm -f tsconfig.tsbuildinfo && tsc --build",
|
|
23
23
|
"test": "vitest run",
|
|
24
24
|
"test:watch": "vitest",
|
|
@@ -40,7 +40,6 @@
|
|
|
40
40
|
"@angular/platform-browser": "^21.1.3",
|
|
41
41
|
"@angular/platform-browser-dynamic": "^21.1.3",
|
|
42
42
|
"@types/node": "^25.2.1",
|
|
43
|
-
"jsdom": "^27.4.0",
|
|
44
43
|
"typescript": "^5.9.3",
|
|
45
44
|
"vitest": "^4.0.18",
|
|
46
45
|
"zone.js": "^0.16.0"
|