Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to customize what are extractable files #11

Merged
merged 10 commits into from
Dec 5, 2019
3 changes: 3 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

### Minor

- Added the ability to customize what are extractable files, fixing [#10](https://github.com/jaydenseric/extract-files/issues/10) via [#11](https://github.com/jaydenseric/extract-files/pull/11):
- Added a new third parameter to the `extractFiles` function, for specifying a custom extractable file matcher.
- Export a new `isExtractableFile` function that is used as the default extractable file matcher for the `extractFiles` function. This can be used in a custom extractable file matcher implementation to match the default extractable files, along with additional custom files.
- Setup [GitHub Sponsors funding](https://github.com/sponsors/jaydenseric):
- Added `.github/funding.yml` to display a sponsor button in GitHub.
- Added a `package.json` `funding` field to enable npm CLI funding features.
Expand Down
55 changes: 55 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ See the [`extractFiles`](#function-extractfiles) documentation to get started.

- [class ReactNativeFile](#class-reactnativefile)
- [function extractFiles](#function-extractfiles)
- [function isExtractableFile](#function-isextractablefile)
- [type ExtractableFile](#type-extractablefile)
- [type ExtractableFileMatcher](#type-extractablefilematcher)
- [type ExtractFilesResult](#type-extractfilesresult)
- [type ObjectPath](#type-objectpath)
- [type ReactNativeFileSubstitute](#type-reactnativefilesubstitute)
Expand Down Expand Up @@ -65,6 +67,7 @@ Clones a value, recursively extracting [`File`](https://developer.mozilla.org/do
| :-- | :-- | :-- |
| `value` | \* | Value (typically an object tree) to extract files from. |
| `path` | [ObjectPath](#type-objectpath)? = `''` | Prefix for object paths for extracted files. |
| `isExtractableFile` | [ExtractableFileMatcher](#type-extractablefilematcher)? = [isExtractableFile](#function-isextractablefile) | The function used to identify extractable files. |

**Returns:** [ExtractFilesResult](#type-extractfilesresult) — Result.

Expand Down Expand Up @@ -107,6 +110,28 @@ _Extract files from an object._

---

### function isExtractableFile

Checks if a value is an [extractable file](#type-extractablefile).

**Type:** [ExtractableFileMatcher](#type-extractablefilematcher)

| Parameter | Type | Description |
| :-------- | :--- | :-------------- |
| `value` | \* | Value to check. |

**Returns:** boolean — Is the value an [extractable file](#type-extractablefile).

#### Examples

_How to import._

> ```js
> import { isExtractableFile } from 'extract-files'
> ```

---

### type ExtractableFile

An extractable file.
Expand All @@ -115,6 +140,36 @@ An extractable file.

---

### type ExtractableFileMatcher

A function that checks if a value is an extractable file.

**Type:** Function

| Parameter | Type | Description |
| :-------- | :--- | :-------------- |
| `value` | \* | Value to check. |

**Returns:** boolean — Is the value an extractable file.

#### See

- [`isExtractableFile`](#function-isextractablefile) is the default extractable file matcher.

#### Examples

_How to check for the default exactable files, as well as a custom type of file._

> ```js
> import { isExtractableFile } from 'extract-files'
>
> const isExtractableFileEnhanced = value =>
> isExtractableFile(value) ||
> (typeof CustomFile !== 'undefined' && value instanceof CustomFile)
> ```

---

### type ExtractFilesResult

What [`extractFiles`](#function-extractfiles) returns.
Expand Down
23 changes: 14 additions & 9 deletions src/extractFiles.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ReactNativeFile } from './ReactNativeFile.mjs'
import { isExtractableFile as defaultIsExtractableFile } from './isExtractableFile.mjs'

/**
* Clones a value, recursively extracting
Expand All @@ -13,6 +13,7 @@ import { ReactNativeFile } from './ReactNativeFile.mjs'
* @name extractFiles
* @param {*} value Value (typically an object tree) to extract files from.
* @param {ObjectPath} [path=''] Prefix for object paths for extracted files.
* @param {ExtractableFileMatcher} [isExtractableFile=isExtractableFile] The function used to identify extractable files.
* @returns {ExtractFilesResult} Result.
* @example <caption>Extract files from an object.</caption>
* For the following:
Expand Down Expand Up @@ -48,7 +49,11 @@ import { ReactNativeFile } from './ReactNativeFile.mjs'
* | `file1` | `['prefix.a', 'prefix.b.0']` |
* | `file2` | `['prefix.b.1']` |
*/
export function extractFiles(value, path = '') {
export function extractFiles(
value,
path = '',
isExtractableFile = defaultIsExtractableFile
) {
let clone
const files = new Map()

Expand All @@ -66,11 +71,7 @@ export function extractFiles(value, path = '') {
else files.set(file, paths)
}

if (
(typeof File !== 'undefined' && value instanceof File) ||
(typeof Blob !== 'undefined' && value instanceof Blob) ||
value instanceof ReactNativeFile
) {
if (isExtractableFile(value)) {
clone = null
addFile([path], value)
} else {
Expand All @@ -83,14 +84,18 @@ export function extractFiles(value, path = '') {
})
else if (Array.isArray(value))
clone = value.map((child, i) => {
const result = extractFiles(child, `${prefix}${i}`)
const result = extractFiles(child, `${prefix}${i}`, isExtractableFile)
result.files.forEach(addFile)
return result.clone
})
else if (value && value.constructor === Object) {
clone = {}
for (const i in value) {
const result = extractFiles(value[i], `${prefix}${i}`)
const result = extractFiles(
value[i],
`${prefix}${i}`,
isExtractableFile
)
result.files.forEach(addFile)
clone[i] = result.clone
}
Expand Down
19 changes: 19 additions & 0 deletions src/index.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export { extractFiles } from './extractFiles.mjs'
export { ReactNativeFile } from './ReactNativeFile.mjs'
export { isExtractableFile } from './isExtractableFile.mjs'

/**
* An extractable file.
Expand All @@ -8,6 +9,24 @@ export { ReactNativeFile } from './ReactNativeFile.mjs'
* @type {File|Blob|ReactNativeFile}
*/

/**
* A function that checks if a value is an extractable file.
* @kind typedef
* @name ExtractableFileMatcher
* @type {Function}
* @param {*} value Value to check.
* @returns {boolean} Is the value an extractable file.
* @see [`isExtractableFile`]{@link isExtractableFile} is the default extractable file matcher.
* @example <caption>How to check for the default exactable files, as well as a custom type of file.</caption>
* ```js
* import { isExtractableFile } from 'extract-files'
*
* const isExtractableFileEnhanced = value =>
* isExtractableFile(value) ||
* (typeof CustomFile !== 'undefined' && value instanceof CustomFile)
* ```
*/

/**
* What [`extractFiles`]{@link extractFiles} returns.
* @kind typedef
Expand Down
18 changes: 18 additions & 0 deletions src/isExtractableFile.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { ReactNativeFile } from './ReactNativeFile.mjs'

/**
* Checks if a value is an [extractable file]{@link ExtractableFile}.
* @kind function
* @name isExtractableFile
* @type {ExtractableFileMatcher}
* @param {*} value Value to check.
* @returns {boolean} Is the value an [extractable file]{@link ExtractableFile}.
* @example <caption>How to import.</caption>
* ```js
* import { isExtractableFile } from 'extract-files'
* ```
*/
export const isExtractableFile = value =>
(typeof File !== 'undefined' && value instanceof File) ||
(typeof Blob !== 'undefined' && value instanceof Blob) ||
value instanceof ReactNativeFile
Loading