Skip to content

Commit d684bb3

Browse files
committed
Add Encoder#.values() and Encoder#[Symbol.iterator]() methods.
1 parent f50610f commit d684bb3

File tree

1 file changed

+64
-10
lines changed

1 file changed

+64
-10
lines changed

lib/Encoder.ts

Lines changed: 64 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import isFormData from "./util/isFormData"
44
import isFile from "./util/isFile"
55

66
import {FormDataLike} from "./FormDataLike"
7+
import {FileLike} from "./FileLike"
78

89
export class Encoder {
910
/**
@@ -126,8 +127,57 @@ export class Encoder {
126127
return length + this.#footer.byteLength
127128
}
128129

130+
/**
131+
* Creates an iterator allowing to go through form-data parts (with metadata).
132+
* This method **will not** read the files.
133+
*
134+
* Using this method, you can convert form-data content into Blob:
135+
*
136+
* @example
137+
*
138+
* import {Readable} from "stream"
139+
*
140+
* import {Encoder} from "form-data-encoder"
141+
*
142+
* import {FormData} from "formdata-polyfill/esm-min.js"
143+
* import {fileFrom} from "fetch-blob/form.js"
144+
* import {File} from "fetch-blob/file.js"
145+
* import {Blob} from "fetch-blob"
146+
*
147+
* import fetch from "node-fetch"
148+
*
149+
* const fd = new FormData()
150+
*
151+
* fd.set("field", "Just a random string")
152+
* fd.set("file", new File(["Using files is class amazing"]))
153+
* fd.set("fileFromPath", await fileFromPath("path/to/a/file.txt"))
154+
*
155+
* const encoder = new Encoder(fd)
156+
*
157+
* const options = {
158+
* method: "post",
159+
* body: new Blob(encoder, {type: encoder.contentType})
160+
* }
161+
*
162+
* const response = await fetch("https://httpbin.org/post", options)
163+
*
164+
* console.log(await response.json())
165+
*/
166+
* values(): Generator<Uint8Array | FileLike, void, undefined> {
167+
for (const [name, value] of this.#form.entries()) {
168+
yield this.#getFieldHeader(name, value)
169+
170+
yield isFile(value) ? value : this.#encoder.encode(String(value))
171+
172+
yield this.#CRLF_BYTES
173+
}
174+
175+
yield this.#footer
176+
}
177+
129178
/**
130179
* Creates an async iterator allowing to perform the encoding by portions.
180+
* This method **will** also read files.
131181
*
132182
* @example
133183
*
@@ -157,22 +207,26 @@ export class Encoder {
157207
* console.log(await response.json())
158208
*/
159209
async* encode(): AsyncGenerator<Uint8Array, void, undefined> {
160-
for (const [name, value] of this.#form) {
161-
yield this.#getFieldHeader(name, value)
162-
163-
if (isFile(value)) {
164-
yield* value.stream()
210+
for (const part of this.values()) {
211+
if (isFile(part)) {
212+
yield* part.stream()
165213
} else {
166-
yield this.#encoder.encode(String(value))
214+
yield part
167215
}
168-
169-
yield this.#CRLF_BYTES
170216
}
217+
}
171218

172-
yield this.#footer
219+
/**
220+
* Creates an iterator allowing to read through the encoder data using for...of loops
221+
*/
222+
[Symbol.iterator](): Generator<Uint8Array | FileLike, void, undefined> {
223+
return this.values()
173224
}
174225

175-
[Symbol.asyncIterator]() {
226+
/**
227+
* Creates an **async** iterator allowing to read through the encoder data using for-await...of loops
228+
*/
229+
[Symbol.asyncIterator](): AsyncGenerator<Uint8Array, void, undefined> {
176230
return this.encode()
177231
}
178232
}

0 commit comments

Comments
 (0)