Skip to content

Commit 171576b

Browse files
committed
feat: adds form-data and url encoded support
1 parent 23bdfd0 commit 171576b

File tree

4 files changed

+76
-2
lines changed

4 files changed

+76
-2
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
},
4242
"dependencies": {
4343
"@lcdev/ts": "0.2",
44+
"isomorphic-form-data": "2",
4445
"query-string": "6"
4546
},
4647
"prettier": "@lcdev/prettier",

src/index.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,4 +329,29 @@ describe('serialization options', () => {
329329
body: JSON.stringify([1, 2, 3]),
330330
});
331331
});
332+
333+
test('form data', () => {
334+
expect(
335+
apiCall('/', HttpMethod.POST)
336+
.withFormDataBody({ foo: 'bar' })
337+
.build(),
338+
).toMatchObject({
339+
path: '/',
340+
body: expect.any(FormData),
341+
});
342+
});
343+
344+
test('url encoded', () => {
345+
expect(
346+
apiCall('/', HttpMethod.POST)
347+
.withURLEncodedBody({ foo: 'bar' })
348+
.build(),
349+
).toMatchObject({
350+
path: '/',
351+
headers: new Headers({
352+
'content-type': 'application/x-www-form-urlencoded',
353+
}),
354+
body: expect.any(URLSearchParams),
355+
});
356+
});
332357
});

src/index.ts

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { stringify as stringifyQuery } from 'query-string';
22
import { Json } from '@lcdev/ts';
33

4+
import 'isomorphic-form-data';
5+
46
export enum HttpMethod {
57
GET = 'GET',
68
POST = 'POST',
@@ -36,16 +38,22 @@ export interface ApiCall<Method extends HttpMethod> extends Promise<Response> {
3638
readonly body?: Json | BodyInit;
3739

3840
withQuery(query: Query, options?: SerializationOptions): ApiCall<Method>;
39-
withBearerToken(token: BearerToken): ApiCall<Method>;
40-
withContentType(contentType: string): ApiCall<Method>;
41+
4142
withHeaders(headers: Headers): ApiCall<Method>;
4243
withHeader(name: string, value: string): ApiCall<Method>;
44+
withContentType(contentType: string): ApiCall<Method>;
45+
withBearerToken(token: BearerToken): ApiCall<Method>;
46+
4347
withBody<B extends Json | BodyInit>(
4448
body: B,
4549
json?: boolean,
4650
options?: SerializationOptions,
4751
): ApiCall<Method>;
4852

53+
withJsonBody<B extends Json>(body: B, options?: SerializationOptions): ApiCall<Method>;
54+
withFormDataBody<B extends Query>(data: B, options?: SerializationOptions): ApiCall<Method>;
55+
withURLEncodedBody<B extends Query>(data: B, options?: SerializationOptions): ApiCall<Method>;
56+
4957
expectStatus(code: number): ApiCall<Method>;
5058
expectSuccessStatus(): ApiCall<Method>;
5159

@@ -145,6 +153,30 @@ class ApiCallImpl<Method extends HttpMethod> implements ApiCall<Method> {
145153
return this;
146154
}
147155

156+
withJsonBody<B extends Json>(body: B, options?: SerializationOptions) {
157+
return this.withBody(body, true, options);
158+
}
159+
160+
withFormDataBody<B extends Query>(data: B, options?: SerializationOptions) {
161+
const body = new FormData();
162+
163+
for (const [k, v] of Object.entries(data)) {
164+
if (v) body.append(k, `${v}`);
165+
}
166+
167+
return this.withBody(body, false, options);
168+
}
169+
170+
withURLEncodedBody<B extends Query>(data: B, options?: SerializationOptions) {
171+
const body = new URLSearchParams();
172+
173+
for (const [k, v] of Object.entries(data)) {
174+
if (v) body.append(k, `${v}`);
175+
}
176+
177+
return this.withContentType('application/x-www-form-urlencoded').withBody(body, false, options);
178+
}
179+
148180
expectStatus(code: number) {
149181
return this.onResponse(res => {
150182
if (res.status !== code) {

yarn.lock

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2031,6 +2031,15 @@ forever-agent@~0.6.1:
20312031
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
20322032
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
20332033

2034+
form-data@^2.3.2:
2035+
version "2.5.1"
2036+
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4"
2037+
integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==
2038+
dependencies:
2039+
asynckit "^0.4.0"
2040+
combined-stream "^1.0.6"
2041+
mime-types "^2.1.12"
2042+
20342043
form-data@~2.3.2:
20352044
version "2.3.3"
20362045
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
@@ -2572,6 +2581,13 @@ isobject@^3.0.0, isobject@^3.0.1:
25722581
resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
25732582
integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
25742583

2584+
isomorphic-form-data@2:
2585+
version "2.0.0"
2586+
resolved "https://registry.yarnpkg.com/isomorphic-form-data/-/isomorphic-form-data-2.0.0.tgz#9f6adf1c4c61ae3aefd8f110ab60fb9b143d6cec"
2587+
integrity sha512-TYgVnXWeESVmQSg4GLVbalmQ+B4NPi/H4eWxqALKj63KsUrcu301YDjBqaOw3h+cbak7Na4Xyps3BiptHtxTfg==
2588+
dependencies:
2589+
form-data "^2.3.2"
2590+
25752591
isstream@~0.1.2:
25762592
version "0.1.2"
25772593
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"

0 commit comments

Comments
 (0)