Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions packages/io-ts-express/test/test-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ test('should offer a delightful developer experience', async (t) => {
// application layer :thonking:
const response = await apiClient['hello.world']
.put({ secretCode: 1000 })
.decodeExpecting('ok')
.decodeExpecting(200)
.then((res) => res.body);

t.like(response, { message: "Who's there?" });
Expand All @@ -130,7 +130,7 @@ test('should invoke app-level middleware', async (t) => {

const response = await apiClient['hello.world']
.put({ secretCode: 1000 })
.decodeExpecting('ok')
.decodeExpecting(200)
.then((res) => res.body);

t.like(response, { message: "Who's there?", appMiddlewareRan: true });
Expand All @@ -153,7 +153,7 @@ test('should invoke route-level middleware', async (t) => {

const response = await apiClient['hello.world']
.put({ secretCode: 1000 })
.decodeExpecting('ok')
.decodeExpecting(200)
.then((res) => res.body);

t.like(response, { message: "Who's there?", routeMiddlewareRan: true });
Expand All @@ -176,7 +176,7 @@ test('should infer status code from response type', async (t) => {

const response = await apiClient['hello.world']
.put({ secretCode: 0 })
.decodeExpecting('invalidRequest')
.decodeExpecting(400)
.then((res) => res.body);

t.like(response, { errors: 'Please do not tell me zero! I will now explode' });
Expand Down
3 changes: 3 additions & 0 deletions packages/io-ts-http/src/httpResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ export const HttpResponseCodes: { [K in Status]: number } = {
internalError: 500,
serviceUnavailable: 503,
};

export type KnownHttpStatusCodes<Response extends HttpResponse> =
typeof HttpResponseCodes[KnownResponses<Response>];
17 changes: 9 additions & 8 deletions packages/superagent-codec-adapter/src/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,15 @@ import type { Response, SuperAgent, SuperAgentRequest } from 'superagent';
import type { SuperTest } from 'supertest';
import { URL } from 'url';
import { pipe } from 'fp-ts/function';
import { HttpResponseCodes } from '@bitgo/io-ts-http';

type SuccessfulResponses<Route extends h.HttpRoute> = {
[Status in h.KnownResponses<Route['response']>]: {
[Status in h.KnownHttpStatusCodes<Route['response']>]: {
status: Status;
error?: undefined;
body: t.TypeOf<Route['response'][Status]>;
original: Response;
};
}[h.KnownResponses<Route['response']>];
}[h.KnownHttpStatusCodes<Route['response']>];

type DecodedResponse<Route extends h.HttpRoute> =
| SuccessfulResponses<Route>
Expand All @@ -29,15 +28,15 @@ const decodedResponse = <Route extends h.HttpRoute>(res: DecodedResponse<Route>)

type ExpectedDecodedResponse<
Route extends h.HttpRoute,
Status extends h.KnownResponses<Route['response']>,
Status extends h.KnownHttpStatusCodes<Route['response']>,
> = {
body: t.TypeOf<Route['response'][Status]>;
original: Response;
};

type PatchedRequest<Req extends SuperAgentRequest, Route extends h.HttpRoute> = Req & {
decode: () => Promise<DecodedResponse<Route>>;
decodeExpecting: <Status extends h.KnownResponses<Route['response']>>(
decodeExpecting: <Status extends h.KnownHttpStatusCodes<Route['response']>>(
status: Status,
) => Promise<ExpectedDecodedResponse<Route, Status>>;
};
Expand Down Expand Up @@ -97,7 +96,7 @@ const patchRequest = <Req extends SuperAgentRequest, Route extends h.HttpRoute>(

let status: string | undefined;
// DISCUSS: Should we have this as a preprocessed const in io-ts-http?
for (const [name, code] of Object.entries(HttpResponseCodes)) {
for (const [name, code] of Object.entries(h.HttpResponseCodes)) {
if (statusCode === code) {
status = name;
break;
Expand Down Expand Up @@ -125,7 +124,7 @@ const patchRequest = <Req extends SuperAgentRequest, Route extends h.HttpRoute>(
route.response[status].decode(res.body),
E.map((body) =>
decodedResponse<Route>({
status: status as h.KnownResponses<Route['response']>,
status: statusCode,
body,
original: res,
}),
Expand All @@ -142,7 +141,9 @@ const patchRequest = <Req extends SuperAgentRequest, Route extends h.HttpRoute>(
);
});

patchedReq.decodeExpecting = <Status extends h.KnownResponses<Route['response']>>(
patchedReq.decodeExpecting = <
Status extends h.KnownHttpStatusCodes<Route['response']>,
>(
status: Status,
) =>
patchedReq.decode().then((res) => {
Expand Down
8 changes: 4 additions & 4 deletions packages/superagent-codec-adapter/test/request.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ describe('request', () => {
.post({ id: 1337, foo: 'test', bar: 42 })
.decode();

assert.equal(response.status, 'ok');
assert.equal(response.status, 200);
assert.deepEqual(response.body, {
id: 1337,
foo: 'test',
Expand Down Expand Up @@ -152,7 +152,7 @@ describe('request', () => {
it('narrows expected response types', async () => {
const response = await apiClient['api.v1.test']
.post({ id: 1337, foo: 'test', bar: 42 })
.decodeExpecting('ok');
.decodeExpecting(200);

assert.deepEqual(response.body, {
id: 1337,
Expand All @@ -166,7 +166,7 @@ describe('request', () => {
const result = await apiClient['api.v1.test']
.post({ id: 1337, foo: 'test', bar: 42 })
.set('x-send-unexpected-status-code', 'true')
.decodeExpecting('ok')
.decodeExpecting(200)
.then(() => false)
.catch(() => true);

Expand All @@ -177,7 +177,7 @@ describe('request', () => {
const result = await apiClient['api.v1.test']
.post({ id: 1337, foo: 'test', bar: 42 })
.set('x-send-invalid-response-body', 'true')
.decodeExpecting('ok')
.decodeExpecting(200)
.then(() => false)
.catch(() => true);

Expand Down