@goast/typescript 0.8.0-beta.1 → 0.8.0-beta.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/LICENSE +21 -21
- package/README.md +52 -52
- package/assets/client/angular/angular-service.utils.ts +82 -82
- package/assets/client/angular/request-builder.ts +377 -377
- package/assets/client/fetch/fetch-client.utils.ts +52 -52
- package/assets/client/k6/request-builder.js +448 -448
- package/assets/client/k6/request-builder.ts +366 -366
- package/assets/stubs/easy-network-stub/easy-network-stub.utils.ts +257 -257
- package/esm/src/generators/models/model-generator.d.ts +22 -0
- package/esm/src/generators/models/model-generator.d.ts.map +1 -1
- package/esm/src/generators/models/model-generator.js +37 -5
- package/esm/src/generators/services/angular-services/angular-service-generator.js +9 -9
- package/esm/src/generators/services/angular-services/angular-services-generator.js +2 -2
- package/esm/src/generators/services/easy-network-stub/easy-network-stub-generator.js +9 -9
- package/esm/src/generators/services/fetch-clients/fetch-client-generator.js +4 -4
- package/esm/src/generators/services/k6-clients/k6-client-generator.d.ts.map +1 -1
- package/esm/src/generators/services/k6-clients/k6-client-generator.js +23 -13
- package/esm/src/import-collection.d.ts.map +1 -1
- package/esm/src/import-collection.js +2 -2
- package/package.json +2 -2
- package/script/src/generators/models/model-generator.d.ts +22 -0
- package/script/src/generators/models/model-generator.d.ts.map +1 -1
- package/script/src/generators/models/model-generator.js +37 -5
- package/script/src/generators/services/angular-services/angular-service-generator.js +9 -9
- package/script/src/generators/services/angular-services/angular-services-generator.js +2 -2
- package/script/src/generators/services/easy-network-stub/easy-network-stub-generator.js +9 -9
- package/script/src/generators/services/fetch-clients/fetch-client-generator.js +4 -4
- package/script/src/generators/services/k6-clients/k6-client-generator.d.ts.map +1 -1
- package/script/src/generators/services/k6-clients/k6-client-generator.js +23 -13
- package/script/src/import-collection.d.ts.map +1 -1
- package/script/src/import-collection.js +1 -1
|
@@ -1,257 +1,257 @@
|
|
|
1
|
-
import type { EasyNetworkStub, ErrorResponse, HttpMethod, RouteResponseCallback, StubHandle } from 'easy-network-stub';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Options for the `EasyNetworkStubWrapper`.
|
|
5
|
-
*/
|
|
6
|
-
export type EasyNetworkStubWrapperOptions = {
|
|
7
|
-
/**
|
|
8
|
-
* Delay in milliseconds before responding.
|
|
9
|
-
* @default 0
|
|
10
|
-
*/
|
|
11
|
-
delay: number;
|
|
12
|
-
/**
|
|
13
|
-
* Whether to log requests to the console.
|
|
14
|
-
* @default false
|
|
15
|
-
*/
|
|
16
|
-
logRequests: boolean;
|
|
17
|
-
/**
|
|
18
|
-
* Whether to log responses to the console.
|
|
19
|
-
* @default false
|
|
20
|
-
*/
|
|
21
|
-
logResponses: boolean;
|
|
22
|
-
/**
|
|
23
|
-
* Whether to remember requests. Remebered requests can be accessed via the `requests` property.
|
|
24
|
-
* @default false
|
|
25
|
-
*/
|
|
26
|
-
rememberRequests: boolean;
|
|
27
|
-
/**
|
|
28
|
-
* Function to call when a response is sent.
|
|
29
|
-
* @param response The response that was sent.
|
|
30
|
-
* @default undefined
|
|
31
|
-
*/
|
|
32
|
-
responseCallback?: (response: unknown) => void;
|
|
33
|
-
/**
|
|
34
|
-
* A prefix to add to the URL in log messages.
|
|
35
|
-
* @default /api/
|
|
36
|
-
*/
|
|
37
|
-
logUrlPrefix: string;
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Represents a request intercepted by the `EasyNetworkStubWrapper`.
|
|
42
|
-
*/
|
|
43
|
-
export type StubRequestItem = {
|
|
44
|
-
/**
|
|
45
|
-
* The HTTP method of the request.
|
|
46
|
-
*/
|
|
47
|
-
method: HttpMethod;
|
|
48
|
-
/**
|
|
49
|
-
* The route of the request.
|
|
50
|
-
*/
|
|
51
|
-
route: string;
|
|
52
|
-
/**
|
|
53
|
-
* The request information provided by `easy-network-stub`.
|
|
54
|
-
*/
|
|
55
|
-
request: StubRequestInfo;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Represents the request information provided by `easy-network-stub`.
|
|
60
|
-
*/
|
|
61
|
-
export type StubRequestInfo<TRoute extends string = string, TBody = unknown> = Parameters<
|
|
62
|
-
RouteResponseCallback<TRoute, TBody>
|
|
63
|
-
>[0];
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* A strict version of `RouteResponseCallback` that allows for a responder to be passed as the first argument.
|
|
67
|
-
*/
|
|
68
|
-
export type StrictRouteResponseCallback<T, P extends string, R> = (
|
|
69
|
-
respondWith: R,
|
|
70
|
-
...args: Parameters<RouteResponseCallback<P, T>>
|
|
71
|
-
) => ErrorResponse<any> | Promise<ErrorResponse<any>>;
|
|
72
|
-
|
|
73
|
-
type _UnionToIntersection<U> = (U extends any ? (x: U) => void : never) extends (x: infer I) => void ? I : never;
|
|
74
|
-
type __StubResponder<T extends Record<number, unknown>, S> = S extends number
|
|
75
|
-
? [T[S]] extends [never] ? (statusCode: S) => ErrorResponse<T[S]>
|
|
76
|
-
: (statusCode: S, content: T[S]) => ErrorResponse<T[S]>
|
|
77
|
-
: never;
|
|
78
|
-
type _StubResponder<T extends Record<number, unknown>> = _UnionToIntersection<__StubResponder<T, keyof T>>;
|
|
79
|
-
const untypedResponder = (statusCode: number, content?: unknown) => ({ statusCode, content });
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Gets the responder function typed to a specific set of status codes.
|
|
83
|
-
* @returns The responder function.
|
|
84
|
-
*/
|
|
85
|
-
export function getStubResponder<T extends Record<number, unknown>>(): _StubResponder<T> {
|
|
86
|
-
return untypedResponder as _StubResponder<T>;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Wrapper for `EasyNetworkStub` that adds additional functionality.
|
|
91
|
-
*/
|
|
92
|
-
export class EasyNetworkStubWrapper {
|
|
93
|
-
private _requests: StubRequestItem[] = [];
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* The options for the wrapper.
|
|
97
|
-
*/
|
|
98
|
-
public readonly options: Readonly<EasyNetworkStubWrapperOptions>;
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* The requests that have been intercepted by the wrapper.
|
|
102
|
-
*/
|
|
103
|
-
public get requests(): ReadonlyArray<StubRequestItem> {
|
|
104
|
-
return this._requests;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
constructor(
|
|
108
|
-
public readonly wrappedStub: EasyNetworkStub,
|
|
109
|
-
options?: Partial<EasyNetworkStubWrapperOptions>,
|
|
110
|
-
) {
|
|
111
|
-
this.options = {
|
|
112
|
-
delay: options?.delay ?? 0,
|
|
113
|
-
logRequests: options?.logRequests ?? false,
|
|
114
|
-
logResponses: options?.logResponses ?? false,
|
|
115
|
-
rememberRequests: options?.rememberRequests ?? false,
|
|
116
|
-
responseCallback: options?.responseCallback,
|
|
117
|
-
logUrlPrefix: options?.logUrlPrefix ?? '/api/',
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Add a single api stub to your intercepted routes.
|
|
123
|
-
* @param method The http method that should be stubbed
|
|
124
|
-
* @param route The route that should be stubbed. Supports parameters in the form of {name:type}.
|
|
125
|
-
* @param response The callback in which you can process the request and reply with the stub. When a Promise is returned, the stub response will be delayed until it is resolved.
|
|
126
|
-
*/
|
|
127
|
-
public stub<Route extends string>(
|
|
128
|
-
method: HttpMethod,
|
|
129
|
-
route: Route,
|
|
130
|
-
response: RouteResponseCallback<Route, unknown>,
|
|
131
|
-
): StubHandle {
|
|
132
|
-
return this.wrappedStub.stub<Route>(method, route, async (request) => {
|
|
133
|
-
if (this.options.delay > 0) await sleep(this.options.delay);
|
|
134
|
-
return await this.runRequest(method, route, response, request);
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* The stub2 method provides a way to set the type of the body that is sent.
|
|
140
|
-
* Due to restrictions in TypeScript (https://github.com/microsoft/TypeScript/issues/10571, https://github.com/Microsoft/TypeScript/pull/26349),
|
|
141
|
-
* We have to hacke a bit here. Calling stub2<T>() will return the stub method with a body of type T.
|
|
142
|
-
*
|
|
143
|
-
* Usage:
|
|
144
|
-
* ```
|
|
145
|
-
* .stub2<MyRequest>()('GET', '/api/test', ({ body }) => {
|
|
146
|
-
* // body is of type MyRequest
|
|
147
|
-
* });
|
|
148
|
-
* ```
|
|
149
|
-
* @returns The stub method with a body of type T.
|
|
150
|
-
*/
|
|
151
|
-
public stub2<T>(): <Route extends string>(
|
|
152
|
-
method: HttpMethod,
|
|
153
|
-
route: Route,
|
|
154
|
-
response: RouteResponseCallback<Route, T>,
|
|
155
|
-
) => StubHandle {
|
|
156
|
-
return <Route extends string>(method: HttpMethod, route: Route, response: RouteResponseCallback<Route, T>) => {
|
|
157
|
-
return this.wrappedStub.stub2<T>()<Route>(method, route, async (request) => {
|
|
158
|
-
if (this.options.delay > 0) await sleep(this.options.delay);
|
|
159
|
-
return await this.runRequest(method, route, response, request);
|
|
160
|
-
});
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Reset the stubs and requests.
|
|
166
|
-
*/
|
|
167
|
-
public reset(): void {
|
|
168
|
-
this._requests = [];
|
|
169
|
-
this.wrappedStub.unregisterAll();
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
private async runRequest<Route extends string, T>(
|
|
173
|
-
method: HttpMethod,
|
|
174
|
-
route: Route,
|
|
175
|
-
response: RouteResponseCallback<Route, T>,
|
|
176
|
-
request: StubRequestInfo<Route, T>,
|
|
177
|
-
): Promise<unknown> {
|
|
178
|
-
if (this.options.rememberRequests) {
|
|
179
|
-
this._requests.push({ method, route, request });
|
|
180
|
-
}
|
|
181
|
-
this.log('request', method, route, request, '#7FFFFF');
|
|
182
|
-
try {
|
|
183
|
-
const r = await response(request);
|
|
184
|
-
this.options.responseCallback?.(r);
|
|
185
|
-
this.log('response', method, route, r, '#7FFF8E');
|
|
186
|
-
return r;
|
|
187
|
-
} catch (error: unknown) {
|
|
188
|
-
this.options.responseCallback?.(error);
|
|
189
|
-
if (isHttpResponse(error) && error.statusCode >= 200 && error.statusCode < 300) {
|
|
190
|
-
this.log('response', method, route, error.content, '#7FFF8E');
|
|
191
|
-
throw error;
|
|
192
|
-
} else {
|
|
193
|
-
const isError = isHttpResponse(error) && error.statusCode >= 400 && error.statusCode < 600;
|
|
194
|
-
this.log('response', method, route, error, isError ? '#FF7F7F' : '7F7F7F');
|
|
195
|
-
throw error;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
private log(type: 'request' | 'response', method: HttpMethod, route: string, data: unknown, color: string) {
|
|
201
|
-
if (type === 'request' && !this.options.logRequests) return;
|
|
202
|
-
if (type === 'response' && !this.options.logResponses) return;
|
|
203
|
-
const typeDisplay = type === 'request' ? ' [req]' : '[resp]';
|
|
204
|
-
const strippedRoute = route.match(/[^?]*(?=\?)?/)?.[0];
|
|
205
|
-
console.log(`%c${typeDisplay} ${method}: ${this.options.logUrlPrefix}${strippedRoute}`, `color:${color};`, data);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Base class for generated easy network stubs.
|
|
211
|
-
*/
|
|
212
|
-
export class EasyNetworkStubBase {
|
|
213
|
-
protected readonly stubWrapper: EasyNetworkStubWrapper;
|
|
214
|
-
protected readonly ownsStubWrapper: boolean;
|
|
215
|
-
|
|
216
|
-
constructor(stub: EasyNetworkStub | EasyNetworkStubWrapper, options?: EasyNetworkStubWrapperOptions) {
|
|
217
|
-
this.stubWrapper = stub instanceof EasyNetworkStubWrapper ? stub : new EasyNetworkStubWrapper(stub, options);
|
|
218
|
-
this.ownsStubWrapper = !(stub instanceof EasyNetworkStubWrapper);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
public reset() {
|
|
222
|
-
if (this.ownsStubWrapper) {
|
|
223
|
-
this.stubWrapper.reset();
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
export type EasyNetworkStubGroup<Group, GroupContainer> = Group & {
|
|
229
|
-
(stubActions: (stubs: Group) => void): GroupContainer;
|
|
230
|
-
};
|
|
231
|
-
|
|
232
|
-
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
233
|
-
declare interface GroupType<T> extends Function {
|
|
234
|
-
new (stubWrapper: EasyNetworkStubWrapper): T;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
export function createEasyNetworkStubGroup<GroupContainer, Group>(
|
|
238
|
-
container: GroupContainer,
|
|
239
|
-
stubWrapper: EasyNetworkStubWrapper,
|
|
240
|
-
groupType: GroupType<Group>,
|
|
241
|
-
): EasyNetworkStubGroup<Group, GroupContainer> {
|
|
242
|
-
const group = new groupType(stubWrapper);
|
|
243
|
-
const groupFn = (stubActions: (stubs: Group) => void) => {
|
|
244
|
-
stubActions(group);
|
|
245
|
-
return container;
|
|
246
|
-
};
|
|
247
|
-
Object.setPrototypeOf(groupFn, groupType.prototype);
|
|
248
|
-
return Object.assign(groupFn, group);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
function sleep(ms: number): Promise<void> {
|
|
252
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
function isHttpResponse(value: unknown): value is ErrorResponse<unknown> {
|
|
256
|
-
return typeof value === 'object' && value !== null && 'statusCode' in value;
|
|
257
|
-
}
|
|
1
|
+
import type { EasyNetworkStub, ErrorResponse, HttpMethod, RouteResponseCallback, StubHandle } from 'easy-network-stub';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Options for the `EasyNetworkStubWrapper`.
|
|
5
|
+
*/
|
|
6
|
+
export type EasyNetworkStubWrapperOptions = {
|
|
7
|
+
/**
|
|
8
|
+
* Delay in milliseconds before responding.
|
|
9
|
+
* @default 0
|
|
10
|
+
*/
|
|
11
|
+
delay: number;
|
|
12
|
+
/**
|
|
13
|
+
* Whether to log requests to the console.
|
|
14
|
+
* @default false
|
|
15
|
+
*/
|
|
16
|
+
logRequests: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Whether to log responses to the console.
|
|
19
|
+
* @default false
|
|
20
|
+
*/
|
|
21
|
+
logResponses: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Whether to remember requests. Remebered requests can be accessed via the `requests` property.
|
|
24
|
+
* @default false
|
|
25
|
+
*/
|
|
26
|
+
rememberRequests: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Function to call when a response is sent.
|
|
29
|
+
* @param response The response that was sent.
|
|
30
|
+
* @default undefined
|
|
31
|
+
*/
|
|
32
|
+
responseCallback?: (response: unknown) => void;
|
|
33
|
+
/**
|
|
34
|
+
* A prefix to add to the URL in log messages.
|
|
35
|
+
* @default /api/
|
|
36
|
+
*/
|
|
37
|
+
logUrlPrefix: string;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Represents a request intercepted by the `EasyNetworkStubWrapper`.
|
|
42
|
+
*/
|
|
43
|
+
export type StubRequestItem = {
|
|
44
|
+
/**
|
|
45
|
+
* The HTTP method of the request.
|
|
46
|
+
*/
|
|
47
|
+
method: HttpMethod;
|
|
48
|
+
/**
|
|
49
|
+
* The route of the request.
|
|
50
|
+
*/
|
|
51
|
+
route: string;
|
|
52
|
+
/**
|
|
53
|
+
* The request information provided by `easy-network-stub`.
|
|
54
|
+
*/
|
|
55
|
+
request: StubRequestInfo;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Represents the request information provided by `easy-network-stub`.
|
|
60
|
+
*/
|
|
61
|
+
export type StubRequestInfo<TRoute extends string = string, TBody = unknown> = Parameters<
|
|
62
|
+
RouteResponseCallback<TRoute, TBody>
|
|
63
|
+
>[0];
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* A strict version of `RouteResponseCallback` that allows for a responder to be passed as the first argument.
|
|
67
|
+
*/
|
|
68
|
+
export type StrictRouteResponseCallback<T, P extends string, R> = (
|
|
69
|
+
respondWith: R,
|
|
70
|
+
...args: Parameters<RouteResponseCallback<P, T>>
|
|
71
|
+
) => ErrorResponse<any> | Promise<ErrorResponse<any>>;
|
|
72
|
+
|
|
73
|
+
type _UnionToIntersection<U> = (U extends any ? (x: U) => void : never) extends (x: infer I) => void ? I : never;
|
|
74
|
+
type __StubResponder<T extends Record<number, unknown>, S> = S extends number
|
|
75
|
+
? [T[S]] extends [never] ? (statusCode: S) => ErrorResponse<T[S]>
|
|
76
|
+
: (statusCode: S, content: T[S]) => ErrorResponse<T[S]>
|
|
77
|
+
: never;
|
|
78
|
+
type _StubResponder<T extends Record<number, unknown>> = _UnionToIntersection<__StubResponder<T, keyof T>>;
|
|
79
|
+
const untypedResponder = (statusCode: number, content?: unknown) => ({ statusCode, content });
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Gets the responder function typed to a specific set of status codes.
|
|
83
|
+
* @returns The responder function.
|
|
84
|
+
*/
|
|
85
|
+
export function getStubResponder<T extends Record<number, unknown>>(): _StubResponder<T> {
|
|
86
|
+
return untypedResponder as _StubResponder<T>;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Wrapper for `EasyNetworkStub` that adds additional functionality.
|
|
91
|
+
*/
|
|
92
|
+
export class EasyNetworkStubWrapper {
|
|
93
|
+
private _requests: StubRequestItem[] = [];
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* The options for the wrapper.
|
|
97
|
+
*/
|
|
98
|
+
public readonly options: Readonly<EasyNetworkStubWrapperOptions>;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* The requests that have been intercepted by the wrapper.
|
|
102
|
+
*/
|
|
103
|
+
public get requests(): ReadonlyArray<StubRequestItem> {
|
|
104
|
+
return this._requests;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
constructor(
|
|
108
|
+
public readonly wrappedStub: EasyNetworkStub,
|
|
109
|
+
options?: Partial<EasyNetworkStubWrapperOptions>,
|
|
110
|
+
) {
|
|
111
|
+
this.options = {
|
|
112
|
+
delay: options?.delay ?? 0,
|
|
113
|
+
logRequests: options?.logRequests ?? false,
|
|
114
|
+
logResponses: options?.logResponses ?? false,
|
|
115
|
+
rememberRequests: options?.rememberRequests ?? false,
|
|
116
|
+
responseCallback: options?.responseCallback,
|
|
117
|
+
logUrlPrefix: options?.logUrlPrefix ?? '/api/',
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Add a single api stub to your intercepted routes.
|
|
123
|
+
* @param method The http method that should be stubbed
|
|
124
|
+
* @param route The route that should be stubbed. Supports parameters in the form of {name:type}.
|
|
125
|
+
* @param response The callback in which you can process the request and reply with the stub. When a Promise is returned, the stub response will be delayed until it is resolved.
|
|
126
|
+
*/
|
|
127
|
+
public stub<Route extends string>(
|
|
128
|
+
method: HttpMethod,
|
|
129
|
+
route: Route,
|
|
130
|
+
response: RouteResponseCallback<Route, unknown>,
|
|
131
|
+
): StubHandle {
|
|
132
|
+
return this.wrappedStub.stub<Route>(method, route, async (request) => {
|
|
133
|
+
if (this.options.delay > 0) await sleep(this.options.delay);
|
|
134
|
+
return await this.runRequest(method, route, response, request);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* The stub2 method provides a way to set the type of the body that is sent.
|
|
140
|
+
* Due to restrictions in TypeScript (https://github.com/microsoft/TypeScript/issues/10571, https://github.com/Microsoft/TypeScript/pull/26349),
|
|
141
|
+
* We have to hacke a bit here. Calling stub2<T>() will return the stub method with a body of type T.
|
|
142
|
+
*
|
|
143
|
+
* Usage:
|
|
144
|
+
* ```
|
|
145
|
+
* .stub2<MyRequest>()('GET', '/api/test', ({ body }) => {
|
|
146
|
+
* // body is of type MyRequest
|
|
147
|
+
* });
|
|
148
|
+
* ```
|
|
149
|
+
* @returns The stub method with a body of type T.
|
|
150
|
+
*/
|
|
151
|
+
public stub2<T>(): <Route extends string>(
|
|
152
|
+
method: HttpMethod,
|
|
153
|
+
route: Route,
|
|
154
|
+
response: RouteResponseCallback<Route, T>,
|
|
155
|
+
) => StubHandle {
|
|
156
|
+
return <Route extends string>(method: HttpMethod, route: Route, response: RouteResponseCallback<Route, T>) => {
|
|
157
|
+
return this.wrappedStub.stub2<T>()<Route>(method, route, async (request) => {
|
|
158
|
+
if (this.options.delay > 0) await sleep(this.options.delay);
|
|
159
|
+
return await this.runRequest(method, route, response, request);
|
|
160
|
+
});
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Reset the stubs and requests.
|
|
166
|
+
*/
|
|
167
|
+
public reset(): void {
|
|
168
|
+
this._requests = [];
|
|
169
|
+
this.wrappedStub.unregisterAll();
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
private async runRequest<Route extends string, T>(
|
|
173
|
+
method: HttpMethod,
|
|
174
|
+
route: Route,
|
|
175
|
+
response: RouteResponseCallback<Route, T>,
|
|
176
|
+
request: StubRequestInfo<Route, T>,
|
|
177
|
+
): Promise<unknown> {
|
|
178
|
+
if (this.options.rememberRequests) {
|
|
179
|
+
this._requests.push({ method, route, request });
|
|
180
|
+
}
|
|
181
|
+
this.log('request', method, route, request, '#7FFFFF');
|
|
182
|
+
try {
|
|
183
|
+
const r = await response(request);
|
|
184
|
+
this.options.responseCallback?.(r);
|
|
185
|
+
this.log('response', method, route, r, '#7FFF8E');
|
|
186
|
+
return r;
|
|
187
|
+
} catch (error: unknown) {
|
|
188
|
+
this.options.responseCallback?.(error);
|
|
189
|
+
if (isHttpResponse(error) && error.statusCode >= 200 && error.statusCode < 300) {
|
|
190
|
+
this.log('response', method, route, error.content, '#7FFF8E');
|
|
191
|
+
throw error;
|
|
192
|
+
} else {
|
|
193
|
+
const isError = isHttpResponse(error) && error.statusCode >= 400 && error.statusCode < 600;
|
|
194
|
+
this.log('response', method, route, error, isError ? '#FF7F7F' : '7F7F7F');
|
|
195
|
+
throw error;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
private log(type: 'request' | 'response', method: HttpMethod, route: string, data: unknown, color: string) {
|
|
201
|
+
if (type === 'request' && !this.options.logRequests) return;
|
|
202
|
+
if (type === 'response' && !this.options.logResponses) return;
|
|
203
|
+
const typeDisplay = type === 'request' ? ' [req]' : '[resp]';
|
|
204
|
+
const strippedRoute = route.match(/[^?]*(?=\?)?/)?.[0];
|
|
205
|
+
console.log(`%c${typeDisplay} ${method}: ${this.options.logUrlPrefix}${strippedRoute}`, `color:${color};`, data);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Base class for generated easy network stubs.
|
|
211
|
+
*/
|
|
212
|
+
export class EasyNetworkStubBase {
|
|
213
|
+
protected readonly stubWrapper: EasyNetworkStubWrapper;
|
|
214
|
+
protected readonly ownsStubWrapper: boolean;
|
|
215
|
+
|
|
216
|
+
constructor(stub: EasyNetworkStub | EasyNetworkStubWrapper, options?: EasyNetworkStubWrapperOptions) {
|
|
217
|
+
this.stubWrapper = stub instanceof EasyNetworkStubWrapper ? stub : new EasyNetworkStubWrapper(stub, options);
|
|
218
|
+
this.ownsStubWrapper = !(stub instanceof EasyNetworkStubWrapper);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
public reset() {
|
|
222
|
+
if (this.ownsStubWrapper) {
|
|
223
|
+
this.stubWrapper.reset();
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export type EasyNetworkStubGroup<Group, GroupContainer> = Group & {
|
|
229
|
+
(stubActions: (stubs: Group) => void): GroupContainer;
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
233
|
+
declare interface GroupType<T> extends Function {
|
|
234
|
+
new (stubWrapper: EasyNetworkStubWrapper): T;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export function createEasyNetworkStubGroup<GroupContainer, Group>(
|
|
238
|
+
container: GroupContainer,
|
|
239
|
+
stubWrapper: EasyNetworkStubWrapper,
|
|
240
|
+
groupType: GroupType<Group>,
|
|
241
|
+
): EasyNetworkStubGroup<Group, GroupContainer> {
|
|
242
|
+
const group = new groupType(stubWrapper);
|
|
243
|
+
const groupFn = (stubActions: (stubs: Group) => void) => {
|
|
244
|
+
stubActions(group);
|
|
245
|
+
return container;
|
|
246
|
+
};
|
|
247
|
+
Object.setPrototypeOf(groupFn, groupType.prototype);
|
|
248
|
+
return Object.assign(groupFn, group);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function sleep(ms: number): Promise<void> {
|
|
252
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function isHttpResponse(value: unknown): value is ErrorResponse<unknown> {
|
|
256
|
+
return typeof value === 'object' && value !== null && 'statusCode' in value;
|
|
257
|
+
}
|
|
@@ -20,6 +20,28 @@ export declare class DefaultTypeScriptModelGenerator extends TypeScriptFileGener
|
|
|
20
20
|
protected getEnumValuesVariable(ctx: Context, schema: ApiSchema): ts.Variable<Builder>;
|
|
21
21
|
protected getIndexer(ctx: Context, schema: ObjectLikeApiSchema): ts.Indexer<Builder> | null;
|
|
22
22
|
protected getProperties(ctx: Context, schema: ObjectLikeApiSchema): ts.Property<Builder>[];
|
|
23
|
+
/**
|
|
24
|
+
* The type of a schema used as a *member* of an enclosing type - a composition branch, an array element, an
|
|
25
|
+
* `additionalProperties` value - with the schema's own nullability applied.
|
|
26
|
+
*
|
|
27
|
+
* `getType` renders a schema's type without its `null` on purpose: the two contexts that render a schema's type
|
|
28
|
+
* as a whole declare nullability themselves. A property has it added by `getProperties`, and a top-level type
|
|
29
|
+
* alias deliberately does not hoist it, because that would change what every declared type means for consumers.
|
|
30
|
+
* A member position has neither - nothing downstream can add the `null` back - so unless it is admitted here the
|
|
31
|
+
* emitted type cannot represent a value the spec explicitly permits.
|
|
32
|
+
*/
|
|
33
|
+
protected getMemberType(ctx: Context, schema: Nullable<ApiSchema>, options?: {
|
|
34
|
+
skipSchemas?: boolean;
|
|
35
|
+
useBaseType?: boolean;
|
|
36
|
+
}): ts.Type<Builder> | null;
|
|
37
|
+
/**
|
|
38
|
+
* Whether a schema needs a `null` added to the type `getType` renders for it. A schema that only ever renders as
|
|
39
|
+
* `null` (the null type itself) already admits it, and adding a second one would emit `(null) | (null)`.
|
|
40
|
+
*
|
|
41
|
+
* Nullability is read through the reference chain the same way `getType` reads the type, so a `$ref` to a
|
|
42
|
+
* declared nullable schema - whose own declaration does not hoist the `null` - still admits null where it is used.
|
|
43
|
+
*/
|
|
44
|
+
protected isNullableMember(schema: ApiSchema): boolean;
|
|
23
45
|
protected getType(ctx: Context, schema: Nullable<ApiSchema>, options?: {
|
|
24
46
|
skipSchemas?: boolean;
|
|
25
47
|
useBaseType?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-generator.d.ts","sourceRoot":"","sources":["../../../../src/src/generators/models/model-generator.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"model-generator.d.ts","sourceRoot":"","sources":["../../../../src/src/generators/models/model-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -158,7 +158,7 @@ export class DefaultTypeScriptModelGenerator extends TypeScriptFileGenerator {
|
|
|
158
158
|
getIndexer(ctx, schema) {
|
|
159
159
|
var _a;
|
|
160
160
|
return schema.additionalProperties
|
|
161
|
-
? ts.indexer(ts.refs.string(), (_a = (schema.additionalProperties === true ? null : this.
|
|
161
|
+
? ts.indexer(ts.refs.string(), (_a = (schema.additionalProperties === true ? null : this.getMemberType(ctx, schema.additionalProperties))) !== null && _a !== void 0 ? _a : this.getAnyType(ctx), { readonly: ctx.config.immutableTypes })
|
|
162
162
|
: null;
|
|
163
163
|
}
|
|
164
164
|
getProperties(ctx, schema) {
|
|
@@ -174,6 +174,33 @@ export class DefaultTypeScriptModelGenerator extends TypeScriptFileGenerator {
|
|
|
174
174
|
});
|
|
175
175
|
});
|
|
176
176
|
}
|
|
177
|
+
/**
|
|
178
|
+
* The type of a schema used as a *member* of an enclosing type - a composition branch, an array element, an
|
|
179
|
+
* `additionalProperties` value - with the schema's own nullability applied.
|
|
180
|
+
*
|
|
181
|
+
* `getType` renders a schema's type without its `null` on purpose: the two contexts that render a schema's type
|
|
182
|
+
* as a whole declare nullability themselves. A property has it added by `getProperties`, and a top-level type
|
|
183
|
+
* alias deliberately does not hoist it, because that would change what every declared type means for consumers.
|
|
184
|
+
* A member position has neither - nothing downstream can add the `null` back - so unless it is admitted here the
|
|
185
|
+
* emitted type cannot represent a value the spec explicitly permits.
|
|
186
|
+
*/
|
|
187
|
+
getMemberType(ctx, schema, options) {
|
|
188
|
+
const type = this.getType(ctx, schema, options);
|
|
189
|
+
return type !== null && schema && this.isNullableMember(schema) ? ts.unionType([type, 'null']) : type;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Whether a schema needs a `null` added to the type `getType` renders for it. A schema that only ever renders as
|
|
193
|
+
* `null` (the null type itself) already admits it, and adding a second one would emit `(null) | (null)`.
|
|
194
|
+
*
|
|
195
|
+
* Nullability is read through the reference chain the same way `getType` reads the type, so a `$ref` to a
|
|
196
|
+
* declared nullable schema - whose own declaration does not hoist the `null` - still admits null where it is used.
|
|
197
|
+
*/
|
|
198
|
+
isNullableMember(schema) {
|
|
199
|
+
const resolved = getSchemaReference(schema, DEFAULT_IGNORED_SCHEMA_PROPERTIES);
|
|
200
|
+
if (resolved.kind === 'null')
|
|
201
|
+
return false;
|
|
202
|
+
return schema.nullable === true || resolved.nullable === true;
|
|
203
|
+
}
|
|
177
204
|
getType(ctx, schema, options) {
|
|
178
205
|
if (!schema)
|
|
179
206
|
return this.getAnyType(ctx);
|
|
@@ -228,7 +255,7 @@ export class DefaultTypeScriptModelGenerator extends TypeScriptFileGenerator {
|
|
|
228
255
|
}
|
|
229
256
|
getArrayType(ctx, schema) {
|
|
230
257
|
var _a;
|
|
231
|
-
return ts.arrayType((_a = this.
|
|
258
|
+
return ts.arrayType((_a = this.getMemberType(ctx, schema.items)) !== null && _a !== void 0 ? _a : this.getAnyType(ctx), {
|
|
232
259
|
readonly: ctx.config.immutableTypes,
|
|
233
260
|
});
|
|
234
261
|
}
|
|
@@ -276,16 +303,21 @@ export class DefaultTypeScriptModelGenerator extends TypeScriptFileGenerator {
|
|
|
276
303
|
return this.getAnyType(ctx);
|
|
277
304
|
}
|
|
278
305
|
const useBaseType = schema.id === ctx.schema.id;
|
|
306
|
+
// allOf branches must all hold at once, i.e. an intersection. anyOf branches only require at least one to hold,
|
|
307
|
+
// i.e. a union - TypeScript unions already admit values matching several branches, so no Partial<> wrapper is
|
|
308
|
+
// needed to express that overlap. A schema with both intersects the allOf branches with the anyOf union.
|
|
279
309
|
return ts.intersectionType([
|
|
280
|
-
...schema.allOf.map((x) => this.
|
|
281
|
-
|
|
310
|
+
...schema.allOf.map((x) => this.getMemberType(ctx, x, { useBaseType })),
|
|
311
|
+
schema.anyOf.length > 0
|
|
312
|
+
? ts.unionType(schema.anyOf.map((x) => this.getMemberType(ctx, x, { useBaseType })))
|
|
313
|
+
: null,
|
|
282
314
|
]);
|
|
283
315
|
}
|
|
284
316
|
getOneOfType(ctx, schema) {
|
|
285
317
|
if (schema.oneOf.length === 0) {
|
|
286
318
|
return this.getAnyType(ctx);
|
|
287
319
|
}
|
|
288
|
-
return ts.unionType(schema.oneOf.map((x) => this.
|
|
320
|
+
return ts.unionType(schema.oneOf.map((x) => this.getMemberType(ctx, x)));
|
|
289
321
|
}
|
|
290
322
|
getMultiType(ctx, schema) {
|
|
291
323
|
if (schema.type.length === 0) {
|