Skip to content

Commit

Permalink
Improve in-code documentation for utilities. Rename isFile.ts -> isFi…
Browse files Browse the repository at this point in the history
…leLike.ts to match public API naming.
  • Loading branch information
octet-stream committed Nov 4, 2021
1 parent 1ed9fad commit 71cfeff
Show file tree
Hide file tree
Showing 11 changed files with 80 additions and 49 deletions.
16 changes: 8 additions & 8 deletions lib/FormDataEncoder.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import createBoundary from "./util/createBoundary"
import isPlainObject from "./util/isPlainObject"
import normalize from "./util/normalizeValue"
import isFormData from "./util/isFormData"
import escape from "./util/escapeName"
import isFile from "./util/isFile"

import {isFileLike} from "./util/isFileLike"
import {isFormData} from "./util/isFormData"
import {FormDataLike} from "./FormDataLike"
import {FileLike} from "./FileLike"

Expand Down Expand Up @@ -185,14 +185,14 @@ export class FormDataEncoder {
header += `${this.#DASHES}${this.boundary}${this.#CRLF}`
header += `Content-Disposition: form-data; name="${escape(name)}"`

if (isFile(value)) {
if (isFileLike(value)) {
header += `; filename="${escape(value.name)}"${this.#CRLF}`
header += `Content-Type: ${value.type || "application/octet-stream"}`
}

if (this.#options.enableAdditionalHeaders === true) {
header += `${this.#CRLF}Content-Length: ${
isFile(value) ? value.size : value.byteLength
isFileLike(value) ? value.size : value.byteLength
}`
}

Expand All @@ -206,11 +206,11 @@ export class FormDataEncoder {
let length = 0

for (const [name, raw] of this.#form) {
const value = isFile(raw) ? raw : this.#encoder.encode(normalize(raw))
const value = isFileLike(raw) ? raw : this.#encoder.encode(normalize(raw))

length += this.#getFieldHeader(name, value).byteLength

length += isFile(value) ? value.size : value.byteLength
length += isFileLike(value) ? value.size : value.byteLength

length += this.#CRLF_BYTES_LENGTH
}
Expand Down Expand Up @@ -256,7 +256,7 @@ export class FormDataEncoder {
*/
* values(): Generator<Uint8Array | FileLike, void, undefined> {
for (const [name, raw] of this.#form.entries()) {
const value = isFile(raw) ? raw : this.#encoder.encode(normalize(raw))
const value = isFileLike(raw) ? raw : this.#encoder.encode(normalize(raw))

yield this.#getFieldHeader(name, value)

Expand Down Expand Up @@ -301,7 +301,7 @@ export class FormDataEncoder {
*/
async* encode(): AsyncGenerator<Uint8Array, void, undefined> {
for (const part of this.values()) {
if (isFile(part)) {
if (isFileLike(part)) {
yield* part.stream()
} else {
yield part
Expand Down
9 changes: 5 additions & 4 deletions lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export * from "./FormDataEncoder"
export * from "./FormDataLike"
export * from "./FileLike"

export {default as isFileLike} from "./util/isFile"
export {default as isFormDataLike} from "./util/isFormData"
// Utilities
export * from "./FileLike"
export * from "./FormDataLike"
export * from "./util/isFileLike"
export * from "./util/isFormData"
8 changes: 8 additions & 0 deletions lib/util/createBoundary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ const alphabet = "abcdefghijklmnopqrstuvwxyz0123456789"

/**
* Generates a boundary string for FormData encoder.
*
* @api private
*
* ```js
* import createBoundary from "./util/createBoundary"
*
* createBoundary() // -> n2vw38xdagaq6lrv
* ```
*/
function createBoundary(): string {
let size = 16
Expand Down
2 changes: 2 additions & 0 deletions lib/util/escapeName.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
* See: https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data
*
* @param name A fieldname to escape
*
* @api private
*/
const escapeName = (name: unknown) => String(name)
.replace(/\r/g, "%0D") // CR
Expand Down
25 changes: 0 additions & 25 deletions lib/util/isFile.ts

This file was deleted.

16 changes: 8 additions & 8 deletions lib/util/isFile.test.ts → lib/util/isFileLike.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import {File, Blob} from "formdata-node"

import {FileLike} from "../FileLike"

import isFile from "./isFile"
import {isFileLike} from "./isFileLike"

test("Returns true for a File", t => {
const file = new File(["Content"], "name.txt")

t.true(isFile(file))
t.true(isFileLike(file))
})

test("Returns true for a class that implements File", t => {
Expand All @@ -31,7 +31,7 @@ test("Returns true for a class that implements File", t => {
}
}

t.true(isFile(new MyFile()))
t.true(isFileLike(new MyFile()))
})

test("Returns true for a file-shaped object", t => {
Expand All @@ -53,23 +53,23 @@ test("Returns true for a file-shaped object", t => {
}
}

t.true(isFile(object))
t.true(isFileLike(object))
})

test("Returns false for null", t => {
t.false(isFile(null))
t.false(isFileLike(null))
})

test("Returns false for undefined", t => {
t.false(isFile(undefined))
t.false(isFileLike(undefined))
})

test("Returns false for non-File object", t => {
t.false(isFile(new Map()))
t.false(isFileLike(new Map()))
})

test("Returns false for Blob", t => {
const blob = new Blob(["Content"], {type: "text/plain"})

t.false(isFile(blob))
t.false(isFileLike(blob))
})
40 changes: 40 additions & 0 deletions lib/util/isFileLike.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import isFunction from "./isFunction"

import {FileLike} from "../FileLike"

/**
* Check if given object is `File`.
*
* Note that this function will return `false` for Blob, because the FormDataEncoder expects FormData to return File when a value is binary data.
*
* @param value an object to test
*
* @api public
*
* This function will return `true` for FileAPI compatible `File` objects:
*
* ```
* import {isFileLike} from "form-data-encoder"
*
* isFileLike(new File(["Content"], "file.txt")) // -> true
* ```
*
* However, if you pass a Node.js `Buffer` or `ReadStream`, it will return `false`:
*
* ```js
* import {isFileLike} from "form-data-encoder"
*
* isFileLike(Buffer.from("Content")) // -> false
* isFileLike(fs.createReadStream("path/to/a/file.txt")) // -> false
* ```
*/
export const isFileLike = (value?: unknown): value is FileLike => Boolean(
(value as FileLike)
&& typeof (value as FileLike) === "object"
&& isFunction((value as FileLike).constructor)
&& (value as FileLike)[Symbol.toStringTag] === "File"
&& isFunction((value as FileLike).stream)
&& (value as FileLike).name != null
&& (value as FileLike).size != null
&& (value as FileLike).lastModified != null
)
2 changes: 1 addition & 1 deletion lib/util/isFormData.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import test from "ava"

import {FormData} from "formdata-node"

import isFormData from "./isFormData"
import {isFormData} from "./isFormData"

import {FormDataLike, FormDataEntryValue} from "../FormDataLike"

Expand Down
4 changes: 1 addition & 3 deletions lib/util/isFormData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {FormDataLike} from "../FormDataLike"
*
* @param value an object to test
*/
const isFormData = (value?: unknown): value is FormDataLike => Boolean(
export const isFormData = (value?: unknown): value is FormDataLike => Boolean(
(value as FormDataLike)
&& isFunction((value as FormDataLike).constructor)
&& (value as FormDataLike)[Symbol.toStringTag] === "FormData"
Expand All @@ -16,5 +16,3 @@ const isFormData = (value?: unknown): value is FormDataLike => Boolean(
&& isFunction((value as FormDataLike).entries)
&& isFunction((value as FormDataLike)[Symbol.iterator])
)

export default isFormData
5 changes: 5 additions & 0 deletions lib/util/isFunction.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/**
* Checks if given value is a function.
*
* @api private
*/
const isFunction = (value: unknown): value is Function => (
typeof value === "function"
)
Expand Down
2 changes: 2 additions & 0 deletions lib/util/normalizeValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
* See: https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data
*
* @param value A value to normalize
*
* @api private
*/
const normalizeValue = (value: unknown): string => String(value)
.replace(/\r(?!\n)|(?<!\r)\n/g, "\r\n")
Expand Down

0 comments on commit 71cfeff

Please sign in to comment.