diff options
author | RaindropsSys <contact@minteck.org> | 2023-04-06 22:18:28 +0200 |
---|---|---|
committer | RaindropsSys <contact@minteck.org> | 2023-04-06 22:18:28 +0200 |
commit | 83354b2b88218090988dd6e526b0a2505b57e0f1 (patch) | |
tree | e3c73c38a122a78bb7e66fbb99056407edd9d4b9 /includes/external/addressbook/node_modules/form-data-encoder | |
parent | 47b8f2299a483024c4a6a8876af825a010954caa (diff) | |
download | pluralconnect-83354b2b88218090988dd6e526b0a2505b57e0f1.tar.gz pluralconnect-83354b2b88218090988dd6e526b0a2505b57e0f1.tar.bz2 pluralconnect-83354b2b88218090988dd6e526b0a2505b57e0f1.zip |
Updated 5 files and added 1110 files (automated)
Diffstat (limited to 'includes/external/addressbook/node_modules/form-data-encoder')
31 files changed, 1019 insertions, 0 deletions
diff --git a/includes/external/addressbook/node_modules/form-data-encoder/@type/FileLike.d.ts b/includes/external/addressbook/node_modules/form-data-encoder/@type/FileLike.d.ts new file mode 100644 index 0000000..8febb60 --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/@type/FileLike.d.ts @@ -0,0 +1,23 @@ +export interface FileLike { + /** + * Name of the file referenced by the File object. + */ + readonly name: string; + /** + * Returns the media type ([`MIME`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types)) of the file represented by a `File` object. + */ + readonly type: string; + /** + * Size of the file parts in bytes + */ + readonly size: number; + /** + * The last modified date of the file as the number of milliseconds since the Unix epoch (January 1, 1970 at midnight). Files without a known last modified date return the current date. + */ + readonly lastModified: number; + /** + * Returns a [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) which upon reading returns the data contained within the [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File). + */ + stream(): AsyncIterable<Uint8Array>; + readonly [Symbol.toStringTag]: string; +} diff --git a/includes/external/addressbook/node_modules/form-data-encoder/@type/FormDataEncoder.d.ts b/includes/external/addressbook/node_modules/form-data-encoder/@type/FormDataEncoder.d.ts new file mode 100644 index 0000000..24123ab --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/@type/FormDataEncoder.d.ts @@ -0,0 +1,169 @@ +import type { FormDataEncoderHeaders } from "./util/Headers.js"; +import type { FormDataLike } from "./FormDataLike.js"; +import type { FileLike } from "./FileLike.js"; +export interface FormDataEncoderOptions { + /** + * When enabled, the encoder will emit additional per part headers, such as `Content-Length`. + * + * Please note that the web clients do not include these, so when enabled this option might cause an error if `multipart/form-data` does not consider additional headers. + * + * Defaults to `false`. + */ + enableAdditionalHeaders?: boolean; +} +/** + * Implements [`multipart/form-data` encoding algorithm](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart/form-data-encoding-algorithm), + * allowing to add support for spec-comliant [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) to an HTTP client. + */ +export declare class FormDataEncoder { + #private; + /** + * Returns boundary string + */ + readonly boundary: string; + /** + * Returns Content-Type header + */ + readonly contentType: string; + /** + * Returns Content-Length header + */ + readonly contentLength: string | undefined; + /** + * Returns headers object with Content-Type and Content-Length header + */ + readonly headers: Readonly<FormDataEncoderHeaders>; + /** + * Creates a multipart/form-data encoder. + * + * @param form FormData object to encode. This object must be a spec-compatible FormData implementation. + * + * @example + * + * ```js + * import {Readable} from "stream" + * + * import {FormData, File, fileFromPath} from "formdata-node" + * import {FormDataEncoder} from "form-data-encoder" + * + * import fetch from "node-fetch" + * + * const form = new FormData() + * + * form.set("field", "Just a random string") + * form.set("file", new File(["Using files is class amazing"], "file.txt")) + * form.set("fileFromPath", await fileFromPath("path/to/a/file.txt")) + * + * const encoder = new FormDataEncoder(form) + * + * const options = { + * method: "post", + * headers: encoder.headers, + * body: Readable.from(encoder) + * } + * + * const response = await fetch("https://httpbin.org/post", options) + * + * console.log(await response.json()) + * ``` + */ + constructor(form: FormDataLike); + /** + * Creates multipart/form-data encoder with custom boundary string. + * + * @param form FormData object to encode. This object must be a spec-compatible FormData implementation. + * @param boundary An optional boundary string that will be used by the encoder. If there's no boundary string is present, Encoder will generate it automatically. + */ + constructor(form: FormDataLike, boundary: string); + /** + * Creates multipart/form-data encoder with additional options. + * + * @param form FormData object to encode. This object must be a spec-compatible FormData implementation. + * @param options Additional options + */ + constructor(form: FormDataLike, options: FormDataEncoderOptions); + constructor(form: FormDataLike, boundary: string, options?: FormDataEncoderOptions); + /** + * Returns form-data content length + * + * @deprecated Use FormDataEncoder.contentLength or FormDataEncoder.headers["Content-Length"] instead + */ + getContentLength(): number | undefined; + /** + * Creates an iterator allowing to go through form-data parts (with metadata). + * This method **will not** read the files. + * + * Using this method, you can convert form-data content into Blob: + * + * @example + * + * import {Readable} from "stream" + * + * import {FormDataEncoder} from "form-data-encoder" + * + * import {FormData} from "formdata-polyfill/esm-min.js" + * import {fileFrom} from "fetch-blob/form.js" + * import {File} from "fetch-blob/file.js" + * import {Blob} from "fetch-blob" + * + * import fetch from "node-fetch" + * + * const form = new FormData() + * + * form.set("field", "Just a random string") + * form.set("file", new File(["Using files is class amazing"])) + * form.set("fileFromPath", await fileFrom("path/to/a/file.txt")) + * + * const encoder = new FormDataEncoder(form) + * + * const options = { + * method: "post", + * body: new Blob(encoder, {type: encoder.contentType}) + * } + * + * const response = await fetch("https://httpbin.org/post", options) + * + * console.log(await response.json()) + */ + values(): Generator<Uint8Array | FileLike, void, undefined>; + /** + * Creates an async iterator allowing to perform the encoding by portions. + * This method **will** also read files. + * + * @example + * + * import {Readable} from "stream" + * + * import {FormData, File, fileFromPath} from "formdata-node" + * import {FormDataEncoder} from "form-data-encoder" + * + * import fetch from "node-fetch" + * + * const form = new FormData() + * + * form.set("field", "Just a random string") + * form.set("file", new File(["Using files is class amazing"], "file.txt")) + * form.set("fileFromPath", await fileFromPath("path/to/a/file.txt")) + * + * const encoder = new FormDataEncoder(form) + * + * const options = { + * method: "post", + * headers: encoder.headers, + * body: Readable.from(encoder.encode()) // or Readable.from(encoder) + * } + * + * const response = await fetch("https://httpbin.org/post", options) + * + * console.log(await response.json()) + */ + encode(): AsyncGenerator<Uint8Array, void, undefined>; + /** + * Creates an iterator allowing to read through the encoder data using for...of loops + */ + [Symbol.iterator](): Generator<Uint8Array | FileLike, void, undefined>; + /** + * Creates an **async** iterator allowing to read through the encoder data using for-await...of loops + */ + [Symbol.asyncIterator](): AsyncGenerator<Uint8Array, void, undefined>; +} diff --git a/includes/external/addressbook/node_modules/form-data-encoder/@type/FormDataLike.d.ts b/includes/external/addressbook/node_modules/form-data-encoder/@type/FormDataLike.d.ts new file mode 100644 index 0000000..05824ad --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/@type/FormDataLike.d.ts @@ -0,0 +1,40 @@ +import { FileLike } from "./FileLike.js"; +/** + * A `string` or `File` that represents a single value from a set of `FormData` key-value pairs. + */ +export type FormDataEntryValue = string | FileLike; +/** + * This interface reflects minimal shape of the FormData + */ +export interface FormDataLike { + /** + * Appends a new value onto an existing key inside a FormData object, + * or adds the key if it does not already exist. + * + * The difference between `set()` and `append()` is that if the specified key already exists, `set()` will overwrite all existing values with the new one, whereas `append()` will append the new value onto the end of the existing set of values. + * + * @param name The name of the field whose data is contained in `value`. + * @param value The field's value. This can be [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) + or [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File). If none of these are specified the value is converted to a string. + * @param fileName The filename reported to the server, when a Blob or File is passed as the second parameter. The default filename for Blob objects is "blob". The default filename for File objects is the file's filename. + */ + append(name: string, value: unknown, fileName?: string): void; + /** + * Returns all the values associated with a given key from within a `FormData` object. + * + * @param {string} name A name of the value you want to retrieve. + * + * @returns An array of `FormDataEntryValue` whose key matches the value passed in the `name` parameter. If the key doesn't exist, the method returns an empty list. + */ + getAll(name: string): FormDataEntryValue[]; + /** + * Returns an [`iterator`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) allowing to go through the `FormData` key/value pairs. + * The key of each pair is a string; the value is a [`FormDataValue`](https://developer.mozilla.org/en-US/docs/Web/API/FormDataEntryValue). + */ + entries(): Generator<[string, FormDataEntryValue]>; + /** + * An alias for FormDataLike#entries() + */ + [Symbol.iterator](): Generator<[string, FormDataEntryValue]>; + readonly [Symbol.toStringTag]: string; +} diff --git a/includes/external/addressbook/node_modules/form-data-encoder/@type/index.d.ts b/includes/external/addressbook/node_modules/form-data-encoder/@type/index.d.ts new file mode 100644 index 0000000..4b0c507 --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/@type/index.d.ts @@ -0,0 +1,5 @@ +export * from "./FormDataEncoder.js"; +export * from "./FileLike.js"; +export * from "./FormDataLike.js"; +export * from "./util/isFile.js"; +export * from "./util/isFormData.js"; diff --git a/includes/external/addressbook/node_modules/form-data-encoder/@type/util/Headers.d.ts b/includes/external/addressbook/node_modules/form-data-encoder/@type/util/Headers.d.ts new file mode 100644 index 0000000..e018e34 --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/@type/util/Headers.d.ts @@ -0,0 +1,8 @@ +export interface RawHeaders { + "Content-Type": string; + "Content-Length"?: string; +} +export interface FormDataEncoderHeaders extends RawHeaders { + "content-type": string; + "content-length"?: string; +} diff --git a/includes/external/addressbook/node_modules/form-data-encoder/@type/util/createBoundary.d.ts b/includes/external/addressbook/node_modules/form-data-encoder/@type/util/createBoundary.d.ts new file mode 100644 index 0000000..3dd8eac --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/@type/util/createBoundary.d.ts @@ -0,0 +1,12 @@ +/** + * Generates a boundary string for FormData encoder. + * + * @api private + * + * ```js + * import createBoundary from "./util/createBoundary" + * + * createBoundary() // -> n2vw38xdagaq6lrv + * ``` + */ +export declare function createBoundary(): string; diff --git a/includes/external/addressbook/node_modules/form-data-encoder/@type/util/escapeName.d.ts b/includes/external/addressbook/node_modules/form-data-encoder/@type/util/escapeName.d.ts new file mode 100644 index 0000000..aeefc63 --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/@type/util/escapeName.d.ts @@ -0,0 +1,10 @@ +/** + * Escape fieldname following the spec requirements. + * + * See: https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data + * + * @param name A fieldname to escape + * + * @api private + */ +export declare const escapeName: (name: unknown) => string; diff --git a/includes/external/addressbook/node_modules/form-data-encoder/@type/util/getStreamIterator.d.ts b/includes/external/addressbook/node_modules/form-data-encoder/@type/util/getStreamIterator.d.ts new file mode 100644 index 0000000..d8f3a41 --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/@type/util/getStreamIterator.d.ts @@ -0,0 +1,6 @@ +/** + * Turns ReadableStream into async iterable when the `Symbol.asyncIterable` is not implemented on given stream. + * + * @param source A ReadableStream to create async iterator for + */ +export declare const getStreamIterator: (source: ReadableStream<Uint8Array> | AsyncIterable<Uint8Array>) => AsyncIterable<Uint8Array>; diff --git a/includes/external/addressbook/node_modules/form-data-encoder/@type/util/isFile.d.ts b/includes/external/addressbook/node_modules/form-data-encoder/@type/util/isFile.d.ts new file mode 100644 index 0000000..ba27e13 --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/@type/util/isFile.d.ts @@ -0,0 +1,34 @@ +import type { FileLike } from "../FileLike.js"; +/** + * 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 {createReadStream} from "node:fs" + * + * import {isFile} from "form-data-encoder" + * + * isFile(new File(["Content"], "file.txt")) // -> true + * ``` + * + * However, if you pass a Node.js `Buffer` or `ReadStream`, it will return `false`: + * + * ```js + * import {isFile} from "form-data-encoder" + * + * isFile(Buffer.from("Content")) // -> false + * isFile(createReadStream("path/to/a/file.txt")) // -> false + * ``` + */ +export declare const isFile: (value: unknown) => value is FileLike; +/** + * @deprecated use `isFile` instead + */ +export declare const isFileLike: (value: unknown) => value is FileLike; diff --git a/includes/external/addressbook/node_modules/form-data-encoder/@type/util/isFormData.d.ts b/includes/external/addressbook/node_modules/form-data-encoder/@type/util/isFormData.d.ts new file mode 100644 index 0000000..54ea959 --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/@type/util/isFormData.d.ts @@ -0,0 +1,7 @@ +import type { FormDataLike } from "../FormDataLike.js"; +/** + * Check if given object is FormData + * + * @param value an object to test + */ +export declare const isFormData: (value: unknown) => value is FormDataLike; diff --git a/includes/external/addressbook/node_modules/form-data-encoder/@type/util/isFunction.d.ts b/includes/external/addressbook/node_modules/form-data-encoder/@type/util/isFunction.d.ts new file mode 100644 index 0000000..98d647e --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/@type/util/isFunction.d.ts @@ -0,0 +1,6 @@ +/** + * Checks if given value is a function. + * + * @api private + */ +export declare const isFunction: (value: unknown) => value is Function; diff --git a/includes/external/addressbook/node_modules/form-data-encoder/@type/util/isPlainObject.d.ts b/includes/external/addressbook/node_modules/form-data-encoder/@type/util/isPlainObject.d.ts new file mode 100644 index 0000000..b69bc56 --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/@type/util/isPlainObject.d.ts @@ -0,0 +1 @@ +export declare function isPlainObject(value: unknown): value is object; diff --git a/includes/external/addressbook/node_modules/form-data-encoder/@type/util/normalizeValue.d.ts b/includes/external/addressbook/node_modules/form-data-encoder/@type/util/normalizeValue.d.ts new file mode 100644 index 0000000..a70661b --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/@type/util/normalizeValue.d.ts @@ -0,0 +1,10 @@ +/** + * Normalize non-File value following the spec requirements. + * + * See: https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data + * + * @param value A value to normalize + * + * @api private + */ +export declare const normalizeValue: (value: unknown) => string; diff --git a/includes/external/addressbook/node_modules/form-data-encoder/@type/util/proxyHeaders.d.ts b/includes/external/addressbook/node_modules/form-data-encoder/@type/util/proxyHeaders.d.ts new file mode 100644 index 0000000..504e45e --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/@type/util/proxyHeaders.d.ts @@ -0,0 +1,2 @@ +import type { FormDataEncoderHeaders, RawHeaders } from "./Headers.js"; +export declare const proxyHeaders: (object: RawHeaders) => FormDataEncoderHeaders; diff --git a/includes/external/addressbook/node_modules/form-data-encoder/lib/FileLike.js b/includes/external/addressbook/node_modules/form-data-encoder/lib/FileLike.js new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/lib/FileLike.js @@ -0,0 +1 @@ +export {}; diff --git a/includes/external/addressbook/node_modules/form-data-encoder/lib/FormDataEncoder.js b/includes/external/addressbook/node_modules/form-data-encoder/lib/FormDataEncoder.js new file mode 100644 index 0000000..eff989a --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/lib/FormDataEncoder.js @@ -0,0 +1,134 @@ +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _FormDataEncoder_instances, _FormDataEncoder_CRLF, _FormDataEncoder_CRLF_BYTES, _FormDataEncoder_CRLF_BYTES_LENGTH, _FormDataEncoder_DASHES, _FormDataEncoder_encoder, _FormDataEncoder_footer, _FormDataEncoder_form, _FormDataEncoder_options, _FormDataEncoder_getFieldHeader, _FormDataEncoder_getContentLength; +import { getStreamIterator } from "./util/getStreamIterator.js"; +import { createBoundary } from "./util/createBoundary.js"; +import { normalizeValue } from "./util/normalizeValue.js"; +import { isPlainObject } from "./util/isPlainObject.js"; +import { proxyHeaders } from "./util/proxyHeaders.js"; +import { isFormData } from "./util/isFormData.js"; +import { escapeName } from "./util/escapeName.js"; +import { isFile } from "./util/isFile.js"; +const defaultOptions = { + enableAdditionalHeaders: false +}; +const readonlyProp = { writable: false, configurable: false }; +export class FormDataEncoder { + constructor(form, boundaryOrOptions, options) { + _FormDataEncoder_instances.add(this); + _FormDataEncoder_CRLF.set(this, "\r\n"); + _FormDataEncoder_CRLF_BYTES.set(this, void 0); + _FormDataEncoder_CRLF_BYTES_LENGTH.set(this, void 0); + _FormDataEncoder_DASHES.set(this, "-".repeat(2)); + _FormDataEncoder_encoder.set(this, new TextEncoder()); + _FormDataEncoder_footer.set(this, void 0); + _FormDataEncoder_form.set(this, void 0); + _FormDataEncoder_options.set(this, void 0); + if (!isFormData(form)) { + throw new TypeError("Expected first argument to be a FormData instance."); + } + let boundary; + if (isPlainObject(boundaryOrOptions)) { + options = boundaryOrOptions; + } + else { + boundary = boundaryOrOptions; + } + if (!boundary) { + boundary = createBoundary(); + } + if (typeof boundary !== "string") { + throw new TypeError("Expected boundary argument to be a string."); + } + if (options && !isPlainObject(options)) { + throw new TypeError("Expected options argument to be an object."); + } + __classPrivateFieldSet(this, _FormDataEncoder_form, Array.from(form.entries()), "f"); + __classPrivateFieldSet(this, _FormDataEncoder_options, { ...defaultOptions, ...options }, "f"); + __classPrivateFieldSet(this, _FormDataEncoder_CRLF_BYTES, __classPrivateFieldGet(this, _FormDataEncoder_encoder, "f").encode(__classPrivateFieldGet(this, _FormDataEncoder_CRLF, "f")), "f"); + __classPrivateFieldSet(this, _FormDataEncoder_CRLF_BYTES_LENGTH, __classPrivateFieldGet(this, _FormDataEncoder_CRLF_BYTES, "f").byteLength, "f"); + this.boundary = `form-data-boundary-${boundary}`; + this.contentType = `multipart/form-data; boundary=${this.boundary}`; + __classPrivateFieldSet(this, _FormDataEncoder_footer, __classPrivateFieldGet(this, _FormDataEncoder_encoder, "f").encode(`${__classPrivateFieldGet(this, _FormDataEncoder_DASHES, "f")}${this.boundary}${__classPrivateFieldGet(this, _FormDataEncoder_DASHES, "f")}${__classPrivateFieldGet(this, _FormDataEncoder_CRLF, "f").repeat(2)}`), "f"); + const headers = { + "Content-Type": this.contentType + }; + const contentLength = __classPrivateFieldGet(this, _FormDataEncoder_instances, "m", _FormDataEncoder_getContentLength).call(this); + if (contentLength) { + this.contentLength = contentLength; + headers["Content-Length"] = contentLength; + } + this.headers = proxyHeaders(Object.freeze(headers)); + Object.defineProperties(this, { + boundary: readonlyProp, + contentType: readonlyProp, + contentLength: readonlyProp, + headers: readonlyProp + }); + } + getContentLength() { + return this.contentLength == null ? undefined : Number(this.contentLength); + } + *values() { + for (const [name, raw] of __classPrivateFieldGet(this, _FormDataEncoder_form, "f")) { + const value = isFile(raw) ? raw : __classPrivateFieldGet(this, _FormDataEncoder_encoder, "f").encode(normalizeValue(raw)); + yield __classPrivateFieldGet(this, _FormDataEncoder_instances, "m", _FormDataEncoder_getFieldHeader).call(this, name, value); + yield value; + yield __classPrivateFieldGet(this, _FormDataEncoder_CRLF_BYTES, "f"); + } + yield __classPrivateFieldGet(this, _FormDataEncoder_footer, "f"); + } + async *encode() { + for (const part of this.values()) { + if (isFile(part)) { + yield* getStreamIterator(part.stream()); + } + else { + yield part; + } + } + } + [(_FormDataEncoder_CRLF = new WeakMap(), _FormDataEncoder_CRLF_BYTES = new WeakMap(), _FormDataEncoder_CRLF_BYTES_LENGTH = new WeakMap(), _FormDataEncoder_DASHES = new WeakMap(), _FormDataEncoder_encoder = new WeakMap(), _FormDataEncoder_footer = new WeakMap(), _FormDataEncoder_form = new WeakMap(), _FormDataEncoder_options = new WeakMap(), _FormDataEncoder_instances = new WeakSet(), _FormDataEncoder_getFieldHeader = function _FormDataEncoder_getFieldHeader(name, value) { + let header = ""; + header += `${__classPrivateFieldGet(this, _FormDataEncoder_DASHES, "f")}${this.boundary}${__classPrivateFieldGet(this, _FormDataEncoder_CRLF, "f")}`; + header += `Content-Disposition: form-data; name="${escapeName(name)}"`; + if (isFile(value)) { + header += `; filename="${escapeName(value.name)}"${__classPrivateFieldGet(this, _FormDataEncoder_CRLF, "f")}`; + header += `Content-Type: ${value.type || "application/octet-stream"}`; + } + const size = isFile(value) ? value.size : value.byteLength; + if (__classPrivateFieldGet(this, _FormDataEncoder_options, "f").enableAdditionalHeaders === true + && size != null + && !isNaN(size)) { + header += `${__classPrivateFieldGet(this, _FormDataEncoder_CRLF, "f")}Content-Length: ${isFile(value) ? value.size : value.byteLength}`; + } + return __classPrivateFieldGet(this, _FormDataEncoder_encoder, "f").encode(`${header}${__classPrivateFieldGet(this, _FormDataEncoder_CRLF, "f").repeat(2)}`); + }, _FormDataEncoder_getContentLength = function _FormDataEncoder_getContentLength() { + let length = 0; + for (const [name, raw] of __classPrivateFieldGet(this, _FormDataEncoder_form, "f")) { + const value = isFile(raw) ? raw : __classPrivateFieldGet(this, _FormDataEncoder_encoder, "f").encode(normalizeValue(raw)); + const size = isFile(value) ? value.size : value.byteLength; + if (size == null || isNaN(size)) { + return undefined; + } + length += __classPrivateFieldGet(this, _FormDataEncoder_instances, "m", _FormDataEncoder_getFieldHeader).call(this, name, value).byteLength; + length += size; + length += __classPrivateFieldGet(this, _FormDataEncoder_CRLF_BYTES_LENGTH, "f"); + } + return String(length + __classPrivateFieldGet(this, _FormDataEncoder_footer, "f").byteLength); + }, Symbol.iterator)]() { + return this.values(); + } + [Symbol.asyncIterator]() { + return this.encode(); + } +} diff --git a/includes/external/addressbook/node_modules/form-data-encoder/lib/FormDataLike.js b/includes/external/addressbook/node_modules/form-data-encoder/lib/FormDataLike.js new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/lib/FormDataLike.js @@ -0,0 +1 @@ +export {}; diff --git a/includes/external/addressbook/node_modules/form-data-encoder/lib/index.js b/includes/external/addressbook/node_modules/form-data-encoder/lib/index.js new file mode 100644 index 0000000..4b0c507 --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/lib/index.js @@ -0,0 +1,5 @@ +export * from "./FormDataEncoder.js"; +export * from "./FileLike.js"; +export * from "./FormDataLike.js"; +export * from "./util/isFile.js"; +export * from "./util/isFormData.js"; diff --git a/includes/external/addressbook/node_modules/form-data-encoder/lib/util/Headers.js b/includes/external/addressbook/node_modules/form-data-encoder/lib/util/Headers.js new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/lib/util/Headers.js @@ -0,0 +1 @@ +export {}; diff --git a/includes/external/addressbook/node_modules/form-data-encoder/lib/util/createBoundary.js b/includes/external/addressbook/node_modules/form-data-encoder/lib/util/createBoundary.js new file mode 100644 index 0000000..4ed7434 --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/lib/util/createBoundary.js @@ -0,0 +1,9 @@ +const alphabet = "abcdefghijklmnopqrstuvwxyz0123456789"; +export function createBoundary() { + let size = 16; + let res = ""; + while (size--) { + res += alphabet[(Math.random() * alphabet.length) << 0]; + } + return res; +} diff --git a/includes/external/addressbook/node_modules/form-data-encoder/lib/util/escapeName.js b/includes/external/addressbook/node_modules/form-data-encoder/lib/util/escapeName.js new file mode 100644 index 0000000..8b2ce25 --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/lib/util/escapeName.js @@ -0,0 +1,4 @@ +export const escapeName = (name) => String(name) + .replace(/\r/g, "%0D") + .replace(/\n/g, "%0A") + .replace(/"/g, "%22"); diff --git a/includes/external/addressbook/node_modules/form-data-encoder/lib/util/getStreamIterator.js b/includes/external/addressbook/node_modules/form-data-encoder/lib/util/getStreamIterator.js new file mode 100644 index 0000000..f97676a --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/lib/util/getStreamIterator.js @@ -0,0 +1,21 @@ +import { isFunction } from "./isFunction.js"; +const isAsyncIterable = (value) => (isFunction(value[Symbol.asyncIterator])); +async function* readStream(readable) { + const reader = readable.getReader(); + while (true) { + const { done, value } = await reader.read(); + if (done) { + break; + } + yield value; + } +} +export const getStreamIterator = (source) => { + if (isAsyncIterable(source)) { + return source; + } + if (isFunction(source.getReader)) { + return readStream(source); + } + throw new TypeError("Unsupported data source: Expected either ReadableStream or async iterable."); +}; diff --git a/includes/external/addressbook/node_modules/form-data-encoder/lib/util/isFile.js b/includes/external/addressbook/node_modules/form-data-encoder/lib/util/isFile.js new file mode 100644 index 0000000..eec965d --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/lib/util/isFile.js @@ -0,0 +1,8 @@ +import { isFunction } from "./isFunction.js"; +export const isFile = (value) => Boolean(value + && typeof value === "object" + && isFunction(value.constructor) + && value[Symbol.toStringTag] === "File" + && isFunction(value.stream) + && value.name != null); +export const isFileLike = isFile; diff --git a/includes/external/addressbook/node_modules/form-data-encoder/lib/util/isFormData.js b/includes/external/addressbook/node_modules/form-data-encoder/lib/util/isFormData.js new file mode 100644 index 0000000..237419f --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/lib/util/isFormData.js @@ -0,0 +1,8 @@ +import { isFunction } from "./isFunction.js"; +export const isFormData = (value) => Boolean(value + && isFunction(value.constructor) + && value[Symbol.toStringTag] === "FormData" + && isFunction(value.append) + && isFunction(value.getAll) + && isFunction(value.entries) + && isFunction(value[Symbol.iterator])); diff --git a/includes/external/addressbook/node_modules/form-data-encoder/lib/util/isFunction.js b/includes/external/addressbook/node_modules/form-data-encoder/lib/util/isFunction.js new file mode 100644 index 0000000..a8dbdc2 --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/lib/util/isFunction.js @@ -0,0 +1 @@ +export const isFunction = (value) => (typeof value === "function"); diff --git a/includes/external/addressbook/node_modules/form-data-encoder/lib/util/isPlainObject.js b/includes/external/addressbook/node_modules/form-data-encoder/lib/util/isPlainObject.js new file mode 100644 index 0000000..9f3fb7e --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/lib/util/isPlainObject.js @@ -0,0 +1,12 @@ +const getType = (value) => (Object.prototype.toString.call(value).slice(8, -1).toLowerCase()); +export function isPlainObject(value) { + if (getType(value) !== "object") { + return false; + } + const pp = Object.getPrototypeOf(value); + if (pp === null || pp === undefined) { + return true; + } + const Ctor = pp.constructor && pp.constructor.toString(); + return Ctor === Object.toString(); +} diff --git a/includes/external/addressbook/node_modules/form-data-encoder/lib/util/normalizeValue.js b/includes/external/addressbook/node_modules/form-data-encoder/lib/util/normalizeValue.js new file mode 100644 index 0000000..05e058a --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/lib/util/normalizeValue.js @@ -0,0 +1,8 @@ +export const normalizeValue = (value) => String(value) + .replace(/\r|\n/g, (match, i, str) => { + if ((match === "\r" && str[i + 1] !== "\n") + || (match === "\n" && str[i - 1] !== "\r")) { + return "\r\n"; + } + return match; +}); diff --git a/includes/external/addressbook/node_modules/form-data-encoder/lib/util/proxyHeaders.js b/includes/external/addressbook/node_modules/form-data-encoder/lib/util/proxyHeaders.js new file mode 100644 index 0000000..05a4ab3 --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/lib/util/proxyHeaders.js @@ -0,0 +1,14 @@ +function getProperty(target, prop) { + if (typeof prop === "string") { + for (const [name, value] of Object.entries(target)) { + if (prop.toLowerCase() === name.toLowerCase()) { + return value; + } + } + } + return undefined; +} +export const proxyHeaders = (object) => new Proxy(object, { + get: (target, prop) => getProperty(target, prop), + has: (target, prop) => getProperty(target, prop) !== undefined +}); diff --git a/includes/external/addressbook/node_modules/form-data-encoder/license b/includes/external/addressbook/node_modules/form-data-encoder/license new file mode 100644 index 0000000..0c8fa88 --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/license @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2021-present Nick K. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/includes/external/addressbook/node_modules/form-data-encoder/package.json b/includes/external/addressbook/node_modules/form-data-encoder/package.json new file mode 100644 index 0000000..e3dcbcc --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/package.json @@ -0,0 +1,70 @@ +{ + "type": "module", + "name": "form-data-encoder", + "version": "2.1.4", + "description": "Encode FormData content into the multipart/form-data format", + "repository": "octet-stream/form-data-encoder", + "sideEffects": false, + "engines": { + "node": ">= 14.17" + }, + "keywords": [ + "form-data", + "encoder", + "multipart", + "files-upload", + "async-iterator", + "spec-compatible", + "form" + ], + "main": "./lib/index.js", + "module": "./lib/index.js", + "exports": { + "types": "./@type/index.d.ts", + "default": "./lib/index.js" + }, + "types": "./@type/index.d.ts", + "scripts": { + "eslint": "eslint src/**/*.ts", + "staged": "lint-staged", + "coverage": "c8 npm test", + "ci": "c8 npm test && c8 report --reporter=json", + "build:types": "tsc --project tsconfig.d.ts.json", + "build": "tsc && npm run build:types", + "test": "ava --fail-fast", + "cleanup": "del-cli @type lib", + "prepare": "npm run cleanup && npm run build", + "_postinstall": "husky install", + "prepublishOnly": "pinst --disable", + "postpublish": "pinst --enable" + }, + "author": "Nick K.", + "license": "MIT", + "devDependencies": { + "@octetstream/eslint-config": "6.2.2", + "@types/mime-types": "2.1.1", + "@types/node": "18.11.9", + "@types/sinon": "^10.0.13", + "@typescript-eslint/eslint-plugin": "5.44.0", + "@typescript-eslint/parser": "5.44.0", + "ava": "5.1.0", + "c8": "7.12.0", + "del-cli": "5.0.0", + "eslint": "8.28.0", + "eslint-config-airbnb-typescript": "17.0.0", + "eslint-import-resolver-typescript": "3.5.2", + "eslint-plugin-ava": "13.2.0", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-jsx-a11y": "6.6.1", + "eslint-plugin-react": "7.31.11", + "formdata-node": "5.0.0", + "husky": "8.0.2", + "lint-staged": "13.0.3", + "pinst": "3.0.0", + "sinon": "^14.0.2", + "ts-node": "10.9.1", + "ttypescript": "1.5.13", + "typescript": "4.9.3", + "web-streams-polyfill": "4.0.0-beta.3" + } +} diff --git a/includes/external/addressbook/node_modules/form-data-encoder/readme.md b/includes/external/addressbook/node_modules/form-data-encoder/readme.md new file mode 100644 index 0000000..a8f4190 --- /dev/null +++ b/includes/external/addressbook/node_modules/form-data-encoder/readme.md @@ -0,0 +1,368 @@ +# form-data-encoder + +Encode `FormData` content into the `multipart/form-data` format + +[![Code Coverage](https://codecov.io/github/octet-stream/form-data-encoder/coverage.svg?branch=master)](https://codecov.io/github/octet-stream/form-data-encoder?branch=master) +[![CI](https://github.com/octet-stream/form-data-encoder/workflows/CI/badge.svg)](https://github.com/octet-stream/form-data-encoder/actions/workflows/ci.yml) +[![ESLint](https://github.com/octet-stream/form-data-encoder/workflows/ESLint/badge.svg)](https://github.com/octet-stream/form-data-encoder/actions/workflows/eslint.yml) + +## Requirements + +- Node.js v14.17 or higher; +- Runtime should support `TextEncoder`, `TextDecoder`, `WeakMap`, `WeakSet` and async generator functions; +- For TypeScript users: tsc v4.3 or higher. + +## Installation + +You can install this package using npm: + +```sh +npm install form-data-encoder +``` + +Or yarn: + +```sh +yarn add form-data-encoder +``` + +Or pnpm: + +```sh +pnpm add form-data-encoder +``` + +## Usage + +1. To start the encoding process, you need to create a new Encoder instance with the FormData you want to encode: + +```js +import {Readable} from "stream" + +import {FormData, File} from "formdata-node" +import {FormDataEncoder} from "form-data-encoder" + +import fetch from "node-fetch" + +const form = new FormData() + +form.set("greeting", "Hello, World!") +form.set("file", new File(["On Soviet Moon landscape see binoculars through YOU"], "file.txt")) + +const encoder = new FormDataEncoder(form) + +const options = { + method: "post", + + // Set request headers provided by the Encoder. + // The `headers` property has `Content-Type` and `Content-Length` headers. + headers: encoder.headers, + + // Create a Readable stream from the Encoder. + // You can omit usage of `Readable.from` for HTTP clients whose support async iterables in request body. + // The Encoder will yield FormData content portions encoded into the multipart/form-data format as node-fetch consumes the stream. + body: Readable.from(encoder.encode()) // or just Readable.from(encoder) +} + +const response = await fetch("https://httpbin.org/post", options) + +console.log(await response.json()) +``` + +2. Encoder support different spec-compatible FormData implementations. Let's try it with [`formdata-polyfill`](https://github.com/jimmywarting/FormData): + +```js +import {Readable} from "stream" + +import {FormDataEncoder} from "form-data-encoder" +import {FormData} from "formdata-polyfill/esm-min.js" +import {File} from "fetch-blob" // v3 + +const form = new FormData() + +form.set("field", "Some value") +form.set("file", new File(["File content goes here"], "file.txt")) + +const encoder = new FormDataEncoder(form) + +const options = { + method: "post", + headers: encoder.headers, + body: Readable.from(encoder) +} + +await fetch("https://httpbin.org/post", options) +``` + +3. Because the Encoder is iterable (it has both Symbol.asyncIterator and Symbol.iterator methods), you can use it with different targets. Let's say you want to convert FormData content into `Blob`, for that you can write a function like this: + +```js +import {Readable} from "stream" + +import {FormDataEncoder} from "form-data-encoder" + +import {FormData, File, Blob, fileFromPath} from "formdata-node" + +import fetch from "node-fetch" + +const form = new FormData() + +form.set("field", "Just a random string") +form.set("file", new File(["Using files is class amazing"], "file.txt")) +form.set("fileFromPath", await fileFromPath("path/to/a/file.txt")) + +// Note 1: When using with native Blob or fetch-blob@2 you might also need to generate boundary string for your FormDataEncoder instance +// because Blob will lowercase value of the `type` option and default boundary generator produces a string with both lower and upper cased alphabetical characters. Math.random() should be enough to fix this: +// const encoder = new FormDataEncoder(form, String(Math.random())) +const encoder = new FormDataEncoder(form) + +const options = { + method: "post", + + // Note 2: To use this approach with fetch-blob@2 you probably gonna need to convert the encoder parts output to an array first: + // new Blob([...encoder], {type: encoder.contentType}) + body: new Blob(encoder, {type: encoder.contentType}) +} + +const response = await fetch("https://httpbin.org/post", options) + +console.log(await response.json()) +``` + +4. Here's FormData to Blob conversion with async-iterator approach: + +```js +import {FormData} from "formdata-polyfill/esm-min.js" +import {blobFrom} from "fetch-blob/from.js" +import {FormDataEncoder} from "form-data-encoder" + +import Blob from "fetch-blob" +import fetch from "node-fetch" + +// This approach may require much more RAM compared to the previous one, but it works too. +async function toBlob(form) { + const encoder = new Encoder(form) + const chunks = [] + + for await (const chunk of encoder) { + chunks.push(chunk) + } + + return new Blob(chunks, {type: encoder.contentType}) +} + +const form = new FormData() + +form.set("name", "John Doe") +form.set("avatar", await blobFrom("path/to/an/avatar.png"), "avatar.png") + +const options = { + method: "post", + body: await toBlob(form) +} + +await fetch("https://httpbin.org/post", options) +``` + +5. Another way to convert FormData parts to blob using `form-data-encoder` is making a Blob-ish class: + +```js +import {Readable} from "stream" + +import {FormDataEncoder} from "form-data-encoder" +import {FormData} from "formdata-polyfill/esm-min.js" +import {blobFrom} from "fetch-blob/from.js" + +import Blob from "fetch-blob" +import fetch from "node-fetch" + +class BlobDataItem { + constructor(encoder) { + this.#encoder = encoder + this.#size = encoder.headers["Content-Length"] + this.#type = encoder.headers["Content-Type"] + } + + get type() { + return this.#type + } + + get size() { + return this.#size + } + + stream() { + return Readable.from(this.#encoder) + } + + get [Symbol.toStringTag]() { + return "Blob" + } +} + +const form = new FormData() + +form.set("name", "John Doe") +form.set("avatar", await blobFrom("path/to/an/avatar.png"), "avatar.png") + +const encoder = new FormDataEncoder(form) + +// Note that node-fetch@2 performs more strictness tests for Blob objects, so you may need to do extra steps before you set up request body (like, maybe you'll need to instaniate a Blob with BlobDataItem as one of its blobPart) +const blob = new BlobDataItem(enocoder) // or new Blob([new BlobDataItem(enocoder)], {type: encoder.contentType}) + +const options = { + method: "post", + body: blob +} + +await fetch("https://httpbin.org/post", options) +``` + +6. In this example we will pull FormData content into the ReadableStream: + +```js + // This module is only necessary when you targeting Node.js or need web streams that implement Symbol.asyncIterator +import {ReadableStream} from "web-streams-polyfill/ponyfill/es2018" + +import {FormDataEncoder} from "form-data-encoder" +import {FormData} from "formdata-node" + +import fetch from "node-fetch" + +function toReadableStream(encoder) { + const iterator = encoder.encode() + + return new ReadableStream({ + async pull(controller) { + const {value, done} = await iterator.next() + + if (done) { + return controller.close() + } + + controller.enqueue(value) + } + }) +} + +const form = new FormData() + +form.set("field", "My hovercraft is full of eels") + +const encoder = new FormDataEncoder(form) + +const options = { + method: "post", + headers: encoder.headers, + body: toReadableStream(encoder) +} + +// Note that this example requires `fetch` to support Symbol.asyncIterator, which node-fetch lacks of (but will support eventually) +await fetch("https://httpbin.org/post", options) +``` + +7. Speaking of async iterables - if HTTP client supports them, you can use encoder like this: + +```js +import {FormDataEncoder} from "form-data-encoder" +import {FormData} from "formdata-node" + +import fetch from "node-fetch" + +const form = new FormData() + +form.set("field", "My hovercraft is full of eels") + +const encoder = new FormDataEncoder(form) + +const options = { + method: "post", + headers: encoder.headers, + body: encoder +} + +await fetch("https://httpbin.org/post", options) +``` + +8. ...And for those client whose supporting form-data-encoder out of the box, the usage will be much, much more simpler: + +```js +import {FormData} from "formdata-node" // Or any other spec-compatible implementation + +import fetch from "node-fetch" + +const form = new FormData() + +form.set("field", "My hovercraft is full of eels") + +const options = { + method: "post", + body: form +} + +// Note that node-fetch does NOT support form-data-encoder +await fetch("https://httpbin.org/post", options) +``` + +## API + +### `class FormDataEncoder` + +##### `constructor(form[, boundary, options]) -> {FormDataEncoder}` + + - **{FormDataLike}** form - FormData object to encode. This object must be a spec-compatible FormData implementation. + - **{string}** [boundary] - An optional boundary string that will be used by the encoder. If there's no boundary string is present, FormDataEncoder will generate it automatically. + - **{object}** [options] - FormDataEncoder options. + - **{boolean}** [options.enableAdditionalHeaders = false] - When enabled, the encoder will emit additional per part headers, such as `Content-Length`. Please note that the web clients do not include these, so when enabled this option might cause an error if `multipart/form-data` does not consider additional headers. + +Creates a `multipart/form-data` encoder. + +#### Instance properties + +##### `boundary -> {string}` + +Returns boundary string. + +##### `contentType -> {string}` + +Returns Content-Type header. + +##### `contentLength -> {string}` + +Return Content-Length header. + +##### `headers -> {object}` + +Returns headers object with Content-Type and Content-Length header. + +#### Instance methods + +##### `values() -> {Generator<Uint8Array | FileLike, void, undefined>}` + +Creates an iterator allowing to go through form-data parts (with metadata). +This method **will not** read the files. + +##### `encode() -> {AsyncGenerator<Uint8Array, void, undefined>}` + +Creates an async iterator allowing to perform the encoding by portions. +This method **will** also read files. + +##### `[Symbol.iterator]() -> {Generator<Uint8Array | FileLike, void, undefined>}` + +An alias for `Encoder#values()` method. + +##### `[Symbol.asyncIterator]() -> {AsyncGenerator<Uint8Array, void, undefined>}` + +An alias for `Encoder#encode()` method. + +### `isFile(value) -> {boolean}` + +Check if a value is File-ish object. + + - **{unknown}** value - a value to test + +### `isFormData(value) -> {boolean}` + +Check if a value is FormData-ish object. + + - **{unknown}** value - a value to test |