code:
# memoize-one

A memoization library that only caches the result of the most recent arguments.

[![npm](https://img.shields.io/npm/v/memoize-one.svg)](https://www.npmjs.com/package/memoize-one)
![types](https://img.shields.io/badge/types-typescript%20%7C%20flow-blueviolet)
[![minzip](https://img.shields.io/bundlephobia/minzip/memoize-one.svg)](https://www.npmjs.com/package/memoize-one)
[![Downloads per month](https://img.shields.io/npm/dm/memoize-one.svg)](https://www.npmjs.com/package/memoize-one)

## Rationale

Unlike other memoization libraries, `memoize-one` only remembers the latest arguments and result. No need to worry about cache busting mechanisms such as `maxAge`, `maxSize`, `exclusions` and so on, which can be prone to memory leaks. A function memoized with `memoize-one` simply remembers the last arguments, and if the memoized function is next called with the same arguments then it returns the previous result.

> For working with promises, [@Kikobeats](https://github.com/Kikobeats) has built [async-memoize-one](https://github.com/microlinkhq/async-memoize-one).

## Usage

```js
// memoize-one uses the default import
import memoizeOne from 'memoize-one';

function add(a, b) {
  return a + b;
}
const memoizedAdd = memoizeOne(add);

memoizedAdd(1, 2);
// add function: is called
// [new value returned: 3]

memoizedAdd(1, 2);
// add function: not called
// [cached result is returned: 3]

memoizedAdd(2, 3);
// add function: is called
// [new value returned: 5]

memoizedAdd(2, 3);
// add function: not called
// [cached result is returned: 5]

memoizedAdd(1, 2);
// add function: is called
// [new value returned: 3]
// 👇
// While the result of `add(1, 2)` was previously cached
// `(1, 2)` was not the *latest* arguments (the last call was `(2, 3)`)
// so the previous cached result of `(1, 3)` was lost
```

## Installation

```bash
# yarn
yarn add memoize-one

# npm
npm install memoize-one --save
```

## Function argument equality

By default, we apply our own _fast_ and _relatively naive_ equality function to determine whether the arguments provided to your function are equal. You can see the full code here: [are-inputs-equal.ts](https://github.com/alexreardon/memoize-one/blob/master/src/are-inputs-equal.ts).

(By default) function arguments are considered equal if:

1. there is same amount of arguments
2. each new argument has strict equality (`===`) with the previous argument
3. **[special case]** if two arguments are not `===` and they are both `NaN` then the two arguments are treated as equal

What this looks like in practice:

```js
import memoizeOne from 'memoize-one';

// add all numbers provided to the function
const add = (...args = []) =>
  args.reduce((current, value) => {
    return current + value;
  }, 0);
const memoizedAdd = memoizeOne(add);
```

> 1. there is same amount of arguments

```js
memoizedAdd(1, 2);
// the amount of arguments has changed, so underlying add function is called
memoizedAdd(1, 2, 3);
```

> 2. new arguments have strict equality (`===`) with the previous argument

```js
memoizedAdd(1, 2);
// each argument is `===` to the last argument, so cache is used
memoizedAdd(1, 2);
// second argument has changed, so add function is called again
memoizedAdd(1, 3);
// the first value is not `===` to the previous first value (1 !== 3)
// so add function is called again
memoizedAdd(3, 1);
```

> 3. **[special case]** if the arguments are not `===` and they are both `NaN` then the argument is treated as equal

```js
memoizedAdd(NaN);
// Even though NaN !== NaN these arguments are
// treated as equal as they are both `NaN`
memoizedAdd(NaN);
```

## Custom equality function

You can also pass in a custom function for checking the equality of two sets of arguments

```js
const memoized = memoizeOne(fn, isEqual);
```

An equality function should return `true` if the arguments are equal. If `true` is returned then the wrapped function will not be called.

**Tip**: A custom equality function needs to compare `Arrays`. The `newArgs` array will be a new reference every time so a simple `newArgs === lastArgs` will always return `false`.

Equality functions are not called if the `this` context of the function has changed (see below).

Here is an example that uses a [lodash.isEqual](https://lodash.com/docs/4.17.15#isEqual) deep equal equality check

> `lodash.isequal` correctly handles deep comparing two arrays

```js
import memoizeOne from 'memoize-one';
import isDeepEqual from 'lodash.isequal';

const identity = (x) => x;

const shallowMemoized = memoizeOne(identity);
const deepMemoized = memoizeOne(identity, isDeepEqual);

const result1 = shallowMemoized({ foo: 'bar' });
const result2 = shallowMemoized({ foo: 'bar' });

result1 === result2; // false - different object reference

const result3 = deepMemoized({ foo: 'bar' });
const result4 = deepMemoized({ foo: 'bar' });

result3 === result4; // true - arguments are deep equal
```

The equality function needs to conform to the `EqualityFn` `type`:

```ts
// TFunc is the function being memoized
type EqualityFn<TFunc extends (...args: any[]) => any> = (
  newArgs: Parameters<TFunc>,
  lastArgs: Parameters<TFunc>,
) => boolean;

// You can import this type
import type { EqualityFn } from 'memoize-one';
```

The `EqualityFn` type allows you to create equality functions that are extremely typesafe. You are welcome to provide your own less type safe equality functions.

Here are some examples of equality functions which are ordered by most type safe, to least type safe:

  Example equality function types

```ts
// the function we are going to memoize
function add(first: number, second: number): number {
  return first + second;
}

// Some options for our equality function
// ↑ stronger types
// ↓ weaker types

// ✅ exact parameters of `add`
{
  const isEqual = function (first: Parameters<typeof add>, second: Parameters<typeof add>) {
    return true;
  };
  expectTypeOf<typeof isEqual>().toMatchTypeOf<EqualityFn<typeof add>>();
}

// ✅ tuple of the correct types
{
  const isEqual = function (first: [number, number], second: [number, number]) {
    return true;
  };
  expectTypeOf<typeof isEqual>().toMatchTypeOf<EqualityFn<typeof add>>();
}

// ❌ tuple of incorrect types
{
  const isEqual = function (first: [number, string], second: [number, number]) {
    return true;
  };
  expectTypeOf<typeof isEqual>().not.toMatchTypeOf<EqualityFn<typeof add>>();
}

// ✅ array of the correct types
{
  const isEqual = function (first: number[], second: number[]) {
    return true;
  };
  expectTypeOf<typeof isEqual>().toMatchTypeOf<EqualityFn<typeof add>>();
}

// ❌ array of incorrect types
{
  const isEqual = function (first: string[], second: number[]) {
    return true;
  };
  expectTypeOf<typeof isEqual>().not.toMatchTypeOf<EqualityFn<typeof add>>();
}

// ✅ tuple of 'unknown'
{
  const isEqual = function (first: [unknown, unknown], second: [unknown, unknown]) {
    return true;
  };
  expectTypeOf<typeof isEqual>().toMatchTypeOf<EqualityFn<typeof add>>();
}

// ❌ tuple of 'unknown' of incorrect length
{
  const isEqual = function (first: [unknown, unknown, unknown], second: [unknown, unknown]) {
    return true;
  };
  expectTypeOf<typeof isEqual>().not.toMatchTypeOf<EqualityFn<typeof add>>();
}

// ✅ array of 'unknown'
{
  const isEqual = function (first: unknown[], second: unknown[]) {
    return true;
  };
  expectTypeOf<typeof isEqual>().toMatchTypeOf<EqualityFn<typeof add>>();
}

// ✅ spread of 'unknown'
{
  const isEqual = function (...first: unknown[]) {
    return !!first;
  };
  expectTypeOf<typeof isEqual>().toMatchTypeOf<EqualityFn<typeof add>>();
}

// ✅ tuple of 'any'
{
  const isEqual = function (first: [any, any], second: [any, any]) {
    return true;
  };
  expectTypeOf<typeof isEqual>().toMatchTypeOf<EqualityFn<typeof add>>();
}

// ❌ tuple of 'any' or incorrect size
{
  const isEqual = function (first: [any, any, any], second: [any, any]) {
    return true;
  };
  expectTypeOf<typeof isEqual>().not.toMatchTypeOf<EqualityFn<typeof add>>();
}

// ✅ array of 'any'
{
  const isEqual = function (first: any[], second: any[]) {
    return true;
  };
  expectTypeOf<typeof isEqual>().toMatchTypeOf<EqualityFn<typeof add>>();
}

// ✅ two arguments of type any
{
  const isEqual = function (first: any, second: any) {
    return true;
  };
  expectTypeOf<typeof isEqual>().toMatchTypeOf<EqualityFn<typeof add>>();
}

// ✅ a single argument of type any
{
  const isEqual = function (first: any) {
    return true;
  };
  expectTypeOf<typeof isEqual>().toMatchTypeOf<EqualityFn<typeof add>>();
}

// ✅ spread of any type
{
  const isEqual = function (...first: any[]) {
    return true;
  };
  expectTypeOf<typeof isEqual>().toMatchTypeOf<EqualityFn<typeof add>>();
}
```

## `this`

### `memoize-one` correctly respects `this` control

This library takes special care to maintain, and allow control over the the `this` context for **both** the original function being memoized as well as the returned memoized function. Both the original function and the memoized function's `this` context respect [all the `this` controlling techniques](https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch2.md):

- new bindings (`new`)
- explicit binding (`call`, `apply`, `bind`);
- implicit binding (call site: `obj.foo()`);
- default binding (`window` or `undefined` in `strict mode`);
- fat arrow binding (binding to lexical `this`)
- ignored this (pass `null` as `this` to explicit binding)

### Changes to `this` is considered an argument change

Changes to the running context (`this`) of a function can result in the function returning a different value even though its arguments have stayed the same:

```js
function getA() {
  return this.a;
}

const temp1 = {
  a: 20,
};
const temp2 = {
  a: 30,
};

getA.call(temp1); // 20
getA.call(temp2); // 30
```

Therefore, in order to prevent against unexpected results, `memoize-one` takes into account the current execution context (`this`) of the memoized function. If `this` is different to the previous invocation then it is considered a change in argument. [further discussion](https://github.com/alexreardon/memoize-one/issues/3).

Generally this will be of no impact if you are not explicity controlling the `this` context of functions you want to memoize with [explicit binding](https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch2.md#explicit-binding) or [implicit binding](https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch2.md#implicit-binding). `memoize-One` will detect when you are manipulating `this` and will then consider the `this` context as an argument. If `this` changes, it will re-execute the original function even if the arguments have not changed.

## Clearing the memoization cache

A `.clear()` property is added to memoized functions to allow you to clear it's memoization cache.

This is helpful if you want to:

- Release memory
- Allow the underlying function to be called again without having to change arguments

```ts
import memoizeOne from 'memoize-one';

function add(a: number, b: number): number {
  return a + b;
}

const memoizedAdd = memoizeOne(add);

// first call - not memoized
const first = memoizedAdd(1, 2);

// second call - cache hit (underlying function not called)
const second = memoizedAdd(1, 2);

// 👋 clearing memoization cache
memoizedAdd.clear();

// third call - not memoized (cache was cleared)
const third = memoizedAdd(1, 2);
```

## When your result function `throw`s

> There is no caching when your result function throws

If your result function `throw`s then the memoized function will also throw. The throw will not break the memoized functions existing argument cache. It means the memoized function will pretend like it was never called with arguments that made it `throw`.

```js
const canThrow = (name: string) => {
  console.log('called');
  if (name === 'throw') {
    throw new Error(name);
  }
  return { name };
};

const memoized = memoizeOne(canThrow);

const value1 = memoized('Alex');
// console.log => 'called'
const value2 = memoized('Alex');
// result function not called

console.log(value1 === value2);
// console.log => true

try {
  memoized('throw');
  // console.log => 'called'
} catch (e) {
  firstError = e;
}

try {
  memoized('throw');
  // console.log => 'called'
  // the result function was called again even though it was called twice
  // with the 'throw' string
} catch (e) {
  secondError = e;
}

console.log(firstError !== secondError);

const value3 = memoized('Alex');
// result function not called as the original memoization cache has not been busted
console.log(value1 === value3);
// console.log => true
```

## Function properties

Functions memoized with `memoize-one` do not preserve any properties on the function object.

> This behaviour correctly reflected in the TypeScript types

```ts
import memoizeOne from 'memoize-one';

function add(a, b) {
  return a + b;
}
add.hello = 'hi';

console.log(typeof add.hello); // string

const memoized = memoizeOne(add);

// hello property on the `add` was not preserved
console.log(typeof memoized.hello); // undefined
```

If you feel strongly that `memoize-one` _should_ preserve function properties, please raise an issue. This decision was made in order to keep `memoize-one` as light as possible.

For _now_, the `.length` property of a function is not preserved on the memoized function

```ts
import memoizeOne from 'memoize-one';

function add(a, b) {
  return a + b;
}

console.log(add.length); // 2

const memoized = memoizeOne(add);

console.log(memoized.length); // 0
```

There is no (great) way to correctly set the `.length` property of the memoized function while also supporting ie11. Once we [remove ie11 support](https://github.com/alexreardon/memoize-one/issues/125) then we will set the `.length` property of the memoized function to match the original function

[→ discussion](https://github.com/alexreardon/memoize-one/pull/124).

## Memoized function `type`

The resulting function you get back from `memoize-one` has *almost* the same `type` as the function that you are memoizing

```ts
declare type MemoizedFn<TFunc extends (this: any, ...args: any[]) => any> = {
  clear: () => void;
  (this: ThisParameterType<TFunc>, ...args: Parameters<TFunc>): ReturnType<TFunc>;
};
```

- the same call signature as the function being memoized
- a `.clear()` function property added
- other function object properties on `TFunc` as not carried over

You are welcome to use the `MemoizedFn` generic directly from `memoize-one` if you like:

```ts
import memoize, { MemoizedFn } from 'memoize-one';
import isDeepEqual from 'lodash.isequal';
import { expectTypeOf } from 'expect-type';

// Takes any function: TFunc, and returns a Memoized<TFunc>
function withDeepEqual<TFunc extends (...args: any[]) => any>(fn: TFunc): MemoizedFn<TFunc> {
  return memoize(fn, isDeepEqual);
}

function add(first: number, second: number): number {
  return first + second;
}

const memoized = withDeepEqual(add);

expectTypeOf<typeof memoized>().toEqualTypeOf<MemoizedFn<typeof add>>();
```

In this specific example, this type would have been correctly inferred too

```ts
import memoize, { MemoizedFn } from 'memoize-one';
import isDeepEqual from 'lodash.isequal';
import { expectTypeOf } from 'expect-type';

// return type of MemoizedFn<TFunc> is inferred
function withDeepEqual<TFunc extends (...args: any[]) => any>(fn: TFunc) {
  return memoize(fn, isDeepEqual);
}

function add(first: number, second: number): number {
  return first + second;
}

const memoized = withDeepEqual(add);

// type test still passes
expectTypeOf<typeof memoized>().toEqualTypeOf<MemoizedFn<typeof add>>();
```

## Performance 🚀

### Tiny

`memoize-one` is super lightweight at [![min](https://img.shields.io/bundlephobia/min/memoize-one.svg?label=)](https://www.npmjs.com/package/memoize-one) minified and [![minzip](https://img.shields.io/bundlephobia/minzip/memoize-one.svg?label=)](https://www.npmjs.com/package/memoize-one) gzipped. (`1KB` = `1,024 Bytes`)

### Extremely fast

`memoize-one` performs better or on par with than other popular memoization libraries for the purpose of remembering the latest invocation.

The comparisons are not exhaustive and are primarily to show that `memoize-one` accomplishes remembering the latest invocation really fast. There is variability between runs. The benchmarks do not take into account the differences in feature sets, library sizes, parse time, and so on.

  Expand for results

node version `16.11.1`

You can run this test in the repo by:

1. Add `"type": "module"` to the `package.json` (why is things so hard)
2. Run `yarn perf:library-comparison`

**no arguments**

| Position | Library                                      | Operations per second |
| -------- | -------------------------------------------- | --------------------- |
| 1        | memoize-one                                  | 80,112,981            |
| 2        | moize                                        | 72,885,631            |
| 3        | memoizee                                     | 35,550,009            |
| 4        | mem (JSON.stringify strategy)                | 4,610,532             |
| 5        | lodash.memoize (JSON.stringify key resolver) | 3,708,945             |
| 6        | no memoization                               | 505                   |
| 7        | fast-memoize                                 | 504                   |

**single primitive argument**

| Position | Library                                      | Operations per second |
| -------- | -------------------------------------------- | --------------------- |
| 1        | fast-memoize                                 | 45,482,711            |
| 2        | moize                                        | 34,810,659            |
| 3        | memoize-one                                  | 29,030,828            |
| 4        | memoizee                                     | 23,467,065            |
| 5        | mem (JSON.stringify strategy)                | 3,985,223             |
| 6        | lodash.memoize (JSON.stringify key resolver) | 3,369,297             |
| 7        | no memoization                               | 507                   |

**single complex argument**

| Position | Library                                      | Operations per second |
| -------- | -------------------------------------------- | --------------------- |
| 1        | moize                                        | 27,660,856            |
| 2        | memoize-one                                  | 22,407,916            |
| 3        | memoizee                                     | 19,546,835            |
| 4        | mem (JSON.stringify strategy)                | 2,068,038             |
| 5        | lodash.memoize (JSON.stringify key resolver) | 1,911,335             |
| 6        | fast-memoize                                 | 1,633,855             |
| 7        | no memoization                               | 504                   |

**multiple primitive arguments**

| Position | Library                                      | Operations per second |
| -------- | -------------------------------------------- | --------------------- |
| 1        | moize                                        | 22,366,497            |
| 2        | memoize-one                                  | 17,241,995            |
| 3        | memoizee                                     | 9,789,442             |
| 4        | mem (JSON.stringify strategy)                | 3,065,328             |
| 5        | lodash.memoize (JSON.stringify key resolver) | 2,663,599             |
| 6        | fast-memoize                                 | 1,219,548             |
| 7        | no memoization                               | 504                   |

**multiple complex arguments**

| Position | Library                                      | Operations per second |
| -------- | -------------------------------------------- | --------------------- |
| 1        | moize                                        | 21,788,081            |
| 2        | memoize-one                                  | 17,321,248            |
| 3        | memoizee                                     | 9,595,420             |
| 4        | lodash.memoize (JSON.stringify key resolver) | 873,283               |
| 5        | mem (JSON.stringify strategy)                | 850,779               |
| 6        | fast-memoize                                 | 687,863               |
| 7        | no memoization                               | 504                   |

**multiple complex arguments (spreading arguments)**

| Position | Library                                      | Operations per second |
| -------- | -------------------------------------------- | --------------------- |
| 1        | moize                                        | 21,701,537            |
| 2        | memoizee                                     | 19,463,942            |
| 3        | memoize-one                                  | 17,027,544            |
| 4        | lodash.memoize (JSON.stringify key resolver) | 887,816               |
| 5        | mem (JSON.stringify strategy)                | 849,244               |
| 6        | fast-memoize                                 | 691,512               |
| 7        | no memoization                               | 504                   |

## Code health 👍

- Tested with all built in [JavaScript types](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/types%20%26%20grammar/ch1.md)
- Written in `Typescript`
- Correct typing for `Typescript` and `flow` type systems
- No dependencies


code: export default function areInputsEqual(newInputs: readonly unknown[], lastInputs: readonly unknown[]): boolean;

license: mit


code:
'use strict';

var safeIsNaN = Number.isNaN ||
    function ponyfill(value) {
        return typeof value === 'number' && value !== value;
    };
function isEqual(first, second) {
    if (first === second) {
        return true;
    }
    if (safeIsNaN(first) && safeIsNaN(second)) {
        return true;
    }
    return false;
}
function areInputsEqual(newInputs, lastInputs) {
    if (newInputs.length !== lastInputs.length) {
        return false;
    }
    for (var i = 0; i < newInputs.length; i++) {
        if (!isEqual(newInputs[i], lastInputs[i])) {
            return false;
        }
    }
    return true;
}

function memoizeOne(resultFn, isEqual) {
    if (isEqual === void 0) { isEqual = areInputsEqual; }
    var cache = null;
    function memoized() {
        var newArgs = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            newArgs[_i] = arguments[_i];
        }
        if (cache && cache.lastThis === this && isEqual(newArgs, cache.lastArgs)) {
            return cache.lastResult;
        }
        var lastResult = resultFn.apply(this, newArgs);
        cache = {
            lastResult: lastResult,
            lastArgs: newArgs,
            lastThis: this,
        };
        return lastResult;
    }
    memoized.clear = function clear() {
        cache = null;
    };
    return memoized;
}

module.exports = memoizeOne;


code:
// @flow

// These types are not as powerful as the TypeScript types, but they get the job done

export type EqualityFn = (newArgs: mixed[], lastArgs: mixed[]) => boolean;

// default export
declare export default function memoizeOne<ResultFn: (...any[]) => mixed>(
  fn: ResultFn,
  isEqual?: EqualityFn,
): ResultFn & { clear: () => void };


code:
export declare type EqualityFn<TFunc extends (...args: any[]) => any> = (newArgs: Parameters<TFunc>, lastArgs: Parameters<TFunc>) => boolean;
export declare type MemoizedFn<TFunc extends (this: any, ...args: any[]) => any> = {
    clear: () => void;
    (this: ThisParameterType<TFunc>, ...args: Parameters<TFunc>): ReturnType<TFunc>;
};
declare function memoizeOne<TFunc extends (this: any, ...newArgs: any[]) => any>(resultFn: TFunc, isEqual?: EqualityFn<TFunc>): MemoizedFn<TFunc>;
export default memoizeOne;


code:
var safeIsNaN = Number.isNaN ||
    function ponyfill(value) {
        return typeof value === 'number' && value !== value;
    };
function isEqual(first, second) {
    if (first === second) {
        return true;
    }
    if (safeIsNaN(first) && safeIsNaN(second)) {
        return true;
    }
    return false;
}
function areInputsEqual(newInputs, lastInputs) {
    if (newInputs.length !== lastInputs.length) {
        return false;
    }
    for (var i = 0; i < newInputs.length; i++) {
        if (!isEqual(newInputs[i], lastInputs[i])) {
            return false;
        }
    }
    return true;
}

function memoizeOne(resultFn, isEqual) {
    if (isEqual === void 0) { isEqual = areInputsEqual; }
    var cache = null;
    function memoized() {
        var newArgs = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            newArgs[_i] = arguments[_i];
        }
        if (cache && cache.lastThis === this && isEqual(newArgs, cache.lastArgs)) {
            return cache.lastResult;
        }
        var lastResult = resultFn.apply(this, newArgs);
        cache = {
            lastResult: lastResult,
            lastArgs: newArgs,
            lastThis: this,
        };
        return lastResult;
    }
    memoized.clear = function clear() {
        cache = null;
    };
    return memoized;
}

export { memoizeOne as default };


code:
(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  typeof define === 'function' && define.amd ? define(factory) :
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.memoizeOne = factory());
})(this, (function () { 'use strict';

  var safeIsNaN = Number.isNaN ||
      function ponyfill(value) {
          return typeof value === 'number' && value !== value;
      };
  function isEqual(first, second) {
      if (first === second) {
          return true;
      }
      if (safeIsNaN(first) && safeIsNaN(second)) {
          return true;
      }
      return false;
  }
  function areInputsEqual(newInputs, lastInputs) {
      if (newInputs.length !== lastInputs.length) {
          return false;
      }
      for (var i = 0; i < newInputs.length; i++) {
          if (!isEqual(newInputs[i], lastInputs[i])) {
              return false;
          }
      }
      return true;
  }

  function memoizeOne(resultFn, isEqual) {
      if (isEqual === void 0) { isEqual = areInputsEqual; }
      var cache = null;
      function memoized() {
          var newArgs = [];
          for (var _i = 0; _i < arguments.length; _i++) {
              newArgs[_i] = arguments[_i];
          }
          if (cache && cache.lastThis === this && isEqual(newArgs, cache.lastArgs)) {
              return cache.lastResult;
          }
          var lastResult = resultFn.apply(this, newArgs);
          cache = {
              lastResult: lastResult,
              lastArgs: newArgs,
              lastThis: this,
          };
          return lastResult;
      }
      memoized.clear = function clear() {
          cache = null;
      };
      return memoized;
  }

  return memoizeOne;

}));


code: !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).memoizeOne=t()}(this,(function(){"use strict";var e=Number.isNaN||function(e){return"number"==typeof e&&e!=e};function t(t,n){if(t.length!==n.length)return!1;for(var r=0;r<t.length;r++)if(i=t[r],u=n[r],!(i===u||e(i)&&e(u)))return!1;var i,u;return!0}return function(e,n){void 0===n&&(n=t);var r=null;function i(){for(var t=[],i=0;i<arguments.length;i++)t[i]=arguments[i];if(r&&r.lastThis===this&&n(t,r.lastArgs))return r.lastResult;var u=e.apply(this,t);return r={lastResult:u,lastArgs:t,lastThis:this},u}return i.clear=function(){r=null},i}}));


memoize-one

description: A memoization library which only remembers the latest invocation

author: Alex Reardon <alexreardon@gmail.com>

license: MIT

type: git

files: /dist /src

keywords: memoize memoization cache performance

validate: yarn prettier:check && yarn eslint:check && yarn typescript:check

test: yarn jest

test:size: yarn build && yarn size-limit

typescript:check: yarn tsc --noEmit

prettier:check: yarn prettier --debug-check $npm_package_config_prettier_target

prettier:write: yarn prettier --write $npm_package_config_prettier_target

build: yarn build:clean && yarn build:dist && yarn build:typescript && yarn build:flow

build:clean: yarn rimraf dist

build:dist: yarn rollup -c

build:typescript: yarn tsc ./src/memoize-one.ts --emitDeclarationOnly --declaration --outDir ./dist

perf:library-comparison: yarn build && node ./benchmarks/library-comparison.js

prepublishOnly: yarn build


code:
// Number.isNaN as it is not supported in IE11 so conditionally using ponyfill
// Using Number.isNaN where possible as it is ~10% faster

const safeIsNaN =
  Number.isNaN ||
  function ponyfill(value: unknown): boolean {
    // // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN#polyfill
    // NaN is the only value in JavaScript which is not equal to itself.
    return typeof value === 'number' && value !== value;
  };

function isEqual(first: unknown, second: unknown): boolean {
  if (first === second) {
    return true;
  }

  // Special case for NaN (NaN !== NaN)
  if (safeIsNaN(first) && safeIsNaN(second)) {
    return true;
  }

  return false;
}

export default function areInputsEqual(
  newInputs: readonly unknown[],
  lastInputs: readonly unknown[],
): boolean {
  // no checks needed if the inputs length has changed
  if (newInputs.length !== lastInputs.length) {
    return false;
  }
  // Using for loop for speed. It generally performs better than array.every
  // https://github.com/alexreardon/memoize-one/pull/59
  for (let i = 0; i < newInputs.length; i++) {
    if (!isEqual(newInputs[i], lastInputs[i])) {
      return false;
    }
  }
  return true;
}


code:
import areInputsEqual from './are-inputs-equal';

export type EqualityFn<TFunc extends (...args: any[]) => any> = (
  newArgs: Parameters<TFunc>,
  lastArgs: Parameters<TFunc>,
) => boolean;

export type MemoizedFn<TFunc extends (this: any, ...args: any[]) => any> = {
  clear: () => void;
  (this: ThisParameterType<TFunc>, ...args: Parameters<TFunc>): ReturnType<TFunc>;
};

// internal type
type Cache<TFunc extends (this: any, ...args: any[]) => any> = {
  lastThis: ThisParameterType<TFunc>;
  lastArgs: Parameters<TFunc>;
  lastResult: ReturnType<TFunc>;
};

function memoizeOne<TFunc extends (this: any, ...newArgs: any[]) => any>(
  resultFn: TFunc,
  isEqual: EqualityFn<TFunc> = areInputsEqual,
): MemoizedFn<TFunc> {
  let cache: Cache<TFunc> | null = null;

  // breaking cache when context (this) or arguments change
  function memoized(
    this: ThisParameterType<TFunc>,
    ...newArgs: Parameters<TFunc>
  ): ReturnType<TFunc> {
    if (cache && cache.lastThis === this && isEqual(newArgs, cache.lastArgs)) {
      return cache.lastResult;
    }

    // Throwing during an assignment aborts the assignment: https://codepen.io/alexreardon/pen/RYKoaz
    // Doing the lastResult assignment first so that if it throws
    // the cache will not be overwritten
    const lastResult = resultFn.apply(this, newArgs);
    cache = {
      lastResult,
      lastArgs: newArgs,
      lastThis: this,
    };

    return lastResult;
  }

  // Adding the ability to clear the cache of a memoized function
  memoized.clear = function clear() {
    cache = null;
  };

  return memoized;
}

export default memoizeOne;


code:
1.0.1 / 2016-01-17
==================

  * perf: enable strict mode

1.0.0 / 2015-03-01
==================

  * Add option to only add new descriptors
  * Add simple argument validation
  * Add jsdoc to source file

0.0.2 / 2013-12-14
==================

  * Move repository to `component` organization

0.0.1 / 2013-10-29
==================

  * Initial release


code:
# Merge Descriptors

[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Build Status][travis-image]][travis-url]
[![Test Coverage][coveralls-image]][coveralls-url]

Merge objects using descriptors.

```js
var thing = {
  get name() {
    return 'jon'
  }
}

var animal = {

}

merge(animal, thing)

animal.name === 'jon'
```

## API

### merge(destination, source)

Redefines `destination`'s descriptors with `source`'s.

### merge(destination, source, false)

Defines `source`'s descriptors on `destination` if `destination` does not have
a descriptor by the same name.

## License

[MIT](LICENSE)

[npm-image]: https://img.shields.io/npm/v/merge-descriptors.svg
[npm-url]: https://npmjs.org/package/merge-descriptors
[travis-image]: https://img.shields.io/travis/component/merge-descriptors/master.svg
[travis-url]: https://travis-ci.org/component/merge-descriptors
[coveralls-image]: https://img.shields.io/coveralls/component/merge-descriptors/master.svg
[coveralls-url]: https://coveralls.io/r/component/merge-descriptors?branch=master
[downloads-image]: https://img.shields.io/npm/dm/merge-descriptors.svg
[downloads-url]: https://npmjs.org/package/merge-descriptors


code:
/*!
 * merge-descriptors
 * Copyright(c) 2014 Jonathan Ong
 * Copyright(c) 2015 Douglas Christopher Wilson
 * MIT Licensed
 */

'use strict'

/**
 * Module exports.
 * @public
 */

module.exports = merge

/**
 * Module variables.
 * @private
 */

var hasOwnProperty = Object.prototype.hasOwnProperty

/**
 * Merge the property descriptors of `src` into `dest`
 *
 * @param {object} dest Object to add descriptors to
 * @param {object} src Object to clone descriptors from
 * @param {boolean} [redefine=true] Redefine `dest` properties with `src` properties
 * @returns {object} Reference to dest
 * @public
 */

function merge(dest, src, redefine) {
  if (!dest) {
    throw new TypeError('argument dest is required')
  }

  if (!src) {
    throw new TypeError('argument src is required')
  }

  if (redefine === undefined) {
    // Default to true
    redefine = true
  }

  Object.getOwnPropertyNames(src).forEach(function forEachOwnPropertyName(name) {
    if (!redefine && hasOwnProperty.call(dest, name)) {
      // Skip desriptor
      return
    }

    // Copy descriptor
    var descriptor = Object.getOwnPropertyDescriptor(src, name)
    Object.defineProperty(dest, name, descriptor)
  })

  return dest
}


merge-descriptors

description: Merge objects using descriptors

contributors: Douglas Christopher Wilson <doug@somethingdoug.com>

repository: component/merge-descriptors

test: mocha --reporter spec --bail --check-leaks test/

test-ci: istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/

test-cov: istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/


code:
# merge-source-map

[![npm-version](https://img.shields.io/npm/v/merge-source-map.svg?style=flat-square)](https://npmjs.org/package/merge-source-map)
[![downloads](http://img.shields.io/npm/dm/merge-source-map.svg?style=flat-square)](https://npmjs.org/package/merge-source-map)
[![travis-ci](https://img.shields.io/travis/keik/merge-source-map.svg?style=flat-square)](https://travis-ci.org/keik/merge-source-map)
[![Coverage Status](https://img.shields.io/coveralls/keik/merge-source-map.svg?style=flat-square)](https://coveralls.io/github/keik/merge-source-map)

Merge old source map and new source map in multi-transform flow

# API

```javascript
var merge = require('merge-source-map')
```

## `merge(oldMap, newMap)`

Merge old source map and new source map and return merged.
If old or new source map value is falsy, return another one as it is.

    oldMap : object|undefined

    old source map object

    newmap : object|undefined

    new source map object

# Example

```javascript
var esprima    = require('esprima'),
    estraverse = require('estraverse'),
    escodegen  = require('escodegen'),
    convert    = require('convert-source-map'),
    merge      = require('merge-source-map')

const CODE = 'a = 1',
      FILEPATH = 'a.js'

// create AST of original code
var ast = esprima.parse(CODE, {sourceType: 'module', loc: true})

// transform AST of original code
estraverse.replace(ast, {
  enter: function(node, parent) { /* change AST */ },
  leave: function(node, parent) { /* change AST */ }
})

// generate code and source map from transformed AST
var gen = escodegen.generate(ast, {
  sourceMap: FILEPATH,
  sourceMapWithCode: true,
  sourceContent: CODE
})

// merge old source map and new source map
var oldMap = convert.fromSource(CODE) && convert.fromSource(CODE).toObject(),
    newMap = JSON.parse(gen.map.toString()),
    mergedMap = merge(oldMap, newMap),
    mapComment = convert.fromObject(mergedMap).toComment()

// attach merge source map to transformed code
var transformed = gen.code + '\n' + mapComment

console.log(transformed);
```

# Test

```
% npm install
% npm test
```

# License

MIT (c) keik


code:
var sourceMap = require('source-map')
var SourceMapConsumer = sourceMap.SourceMapConsumer
var SourceMapGenerator = sourceMap.SourceMapGenerator

module.exports = merge

/**
 * Merge old source map and new source map and return merged.
 * If old or new source map value is falsy, return another one as it is.
 *
 * @param {object|string} [oldMap] old source map object
 * @param {object|string} [newmap] new source map object
 * @return {object|undefined} merged source map object, or undefined when both old and new source map are undefined
 */
function merge(oldMap, newMap) {
  if (!oldMap) return newMap
  if (!newMap) return oldMap

  var oldMapConsumer = new SourceMapConsumer(oldMap)
  var newMapConsumer = new SourceMapConsumer(newMap)
  var mergedMapGenerator = new SourceMapGenerator()

  // iterate on new map and overwrite original position of new map with one of old map
  newMapConsumer.eachMapping(function(m) {
    // pass when `originalLine` is null.
    // It occurs in case that the node does not have origin in original code.
    if (m.originalLine == null) return

    var origPosInOldMap = oldMapConsumer.originalPositionFor({
      line: m.originalLine,
      column: m.originalColumn
    })

    if (origPosInOldMap.source == null) return

    mergedMapGenerator.addMapping({
      original: {
        line: origPosInOldMap.line,
        column: origPosInOldMap.column
      },
      generated: {
        line: m.generatedLine,
        column: m.generatedColumn
      },
      source: origPosInOldMap.source,
      name: origPosInOldMap.name
    })
  })

  var consumers = [oldMapConsumer, newMapConsumer]
  consumers.forEach(function(consumer) {
    consumer.sources.forEach(function(sourceFile) {
      mergedMapGenerator._sources.add(sourceFile)
      var sourceContent = consumer.sourceContentFor(sourceFile)
      if (sourceContent != null) {
        mergedMapGenerator.setSourceContent(sourceFile, sourceContent)
      }
    })
  })

  mergedMapGenerator._sourceRoot = oldMap.sourceRoot
  mergedMapGenerator._file = oldMap.file

  return JSON.parse(mergedMapGenerator.toString())
}


merge-source-map

description: Merge old source map and new source map in multi-transform flow

test: nyc tape test/*.js

lint: eslint index.js 'test/**/*.js'

version: npm run lint && npm run test

author: keik <k4t0.kei@gmail.com>

keywords: sourcemap source-map


code:
# merge-stream

Merge (interleave) a bunch of streams.

[![build status](https://secure.travis-ci.org/grncdr/merge-stream.svg?branch=master)](http://travis-ci.org/grncdr/merge-stream)

## Synopsis

```javascript
var stream1 = new Stream();
var stream2 = new Stream();

var merged = mergeStream(stream1, stream2);

var stream3 = new Stream();
merged.add(stream3);
merged.isEmpty();
//=> false
```

## Description

This is adapted from [event-stream](https://github.com/dominictarr/event-stream) separated into a new module, using Streams3.

## API

### `mergeStream`

Type: `function`

Merges an arbitrary number of streams. Returns a merged stream.

#### `merged.add`

A method to dynamically add more sources to the stream. The argument supplied to `add` can be either a source or an array of sources.

#### `merged.isEmpty`

A method that tells you if the merged stream is empty.

When a stream is "empty" (aka. no sources were added), it could not be returned to a gulp task.

So, we could do something like this:

```js
stream = require('merge-stream')();
// Something like a loop to add some streams to the merge stream
// stream.add(streamA);
// stream.add(streamB);
return stream.isEmpty() ? null : stream;
```

## Gulp example

An example use case for **merge-stream** is to combine parts of a task in a project's **gulpfile.js** like this:

```js
const gulp =          require('gulp');
const htmlValidator = require('gulp-w3c-html-validator');
const jsHint =        require('gulp-jshint');
const mergeStream =   require('merge-stream');

function lint() {
  return mergeStream(
    gulp.src('src/*.html')
      .pipe(htmlValidator())
      .pipe(htmlValidator.reporter()),
    gulp.src('src/*.js')
      .pipe(jsHint())
      .pipe(jsHint.reporter())
  );
}
gulp.task('lint', lint);
```

## License

MIT


code:
'use strict';

const { PassThrough } = require('stream');

module.exports = function (/*streams...*/) {
  var sources = []
  var output  = new PassThrough({objectMode: true})

  output.setMaxListeners(0)

  output.add = add
  output.isEmpty = isEmpty

  output.on('unpipe', remove)

  Array.prototype.slice.call(arguments).forEach(add)

  return output

  function add (source) {
    if (Array.isArray(source)) {
      source.forEach(add)
      return this
    }

    sources.push(source);
    source.once('end', remove.bind(null, source))
    source.once('error', output.emit.bind(output, 'error'))
    source.pipe(output, {end: false})
    return this
  }

  function isEmpty () {
    return sources.length == 0;
  }

  function remove (source) {
    sources = sources.filter(function (it) { return it !== source })
    if (!sources.length && output.readable) { output.end() }
  }
}


merge-stream

description: Create a stream that emits events from multiple other streams

test: istanbul cover test.js && istanbul check-cover --statements 100 --branches 100

repository: grncdr/merge-stream

author: Stephen Sugden <me@stephensugden.com>


code:
# merge2

Merge multiple streams into one stream in sequence or parallel.

[![NPM version][npm-image]][npm-url]
[![Build Status][travis-image]][travis-url]
[![Downloads][downloads-image]][downloads-url]

## Install

Install with [npm](https://npmjs.org/package/merge2)

```sh
npm install merge2
```

## Usage

```js
const gulp = require('gulp')
const merge2 = require('merge2')
const concat = require('gulp-concat')
const minifyHtml = require('gulp-minify-html')
const ngtemplate = require('gulp-ngtemplate')

gulp.task('app-js', function () {
  return merge2(
      gulp.src('static/src/tpl/*.html')
        .pipe(minifyHtml({empty: true}))
        .pipe(ngtemplate({
          module: 'genTemplates',
          standalone: true
        })
      ), gulp.src([
        'static/src/js/app.js',
        'static/src/js/locale_zh-cn.js',
        'static/src/js/router.js',
        'static/src/js/tools.js',
        'static/src/js/services.js',
        'static/src/js/filters.js',
        'static/src/js/directives.js',
        'static/src/js/controllers.js'
      ])
    )
    .pipe(concat('app.js'))
    .pipe(gulp.dest('static/dist/js/'))
})
```

```js
const stream = merge2([stream1, stream2], stream3, {end: false})
//...
stream.add(stream4, stream5)
//..
stream.end()
```

```js
// equal to merge2([stream1, stream2], stream3)
const stream = merge2()
stream.add([stream1, stream2])
stream.add(stream3)
```

```js
// merge order:
//   1. merge `stream1`;
//   2. merge `stream2` and `stream3` in parallel after `stream1` merged;
//   3. merge 'stream4' after `stream2` and `stream3` merged;
const stream = merge2(stream1, [stream2, stream3], stream4)

// merge order:
//   1. merge `stream5` and `stream6` in parallel after `stream4` merged;
//   2. merge 'stream7' after `stream5` and `stream6` merged;
stream.add([stream5, stream6], stream7)
```

```js
// nest merge
// equal to merge2(stream1, stream2, stream6, stream3, [stream4, stream5]);
const streamA = merge2(stream1, stream2)
const streamB = merge2(stream3, [stream4, stream5])
const stream = merge2(streamA, streamB)
streamA.add(stream6)
```

## API

```js
const merge2 = require('merge2')
```

### merge2()

### merge2(options)

### merge2(stream1, stream2, ..., streamN)

### merge2(stream1, stream2, ..., streamN, options)

### merge2(stream1, [stream2, stream3, ...], streamN, options)

return a duplex stream (mergedStream). streams in array will be merged in parallel.

### mergedStream.add(stream)

### mergedStream.add(stream1, [stream2, stream3, ...], ...)

return the mergedStream.

### mergedStream.on('queueDrain', function() {})

It will emit 'queueDrain' when all streams merged. If you set `end === false` in options, this event give you a notice that should add more streams to merge or end the mergedStream.

#### stream

*option*
Type: `Readable` or `Duplex` or `Transform` stream.

#### options

*option*
Type: `Object`.

* **end** - `Boolean` - if `end === false` then mergedStream will not be auto ended, you should end by yourself. **Default:** `undefined`

* **pipeError** - `Boolean` - if `pipeError === true` then mergedStream will emit `error` event from source streams. **Default:** `undefined`

* **objectMode** - `Boolean` . **Default:** `true`

`objectMode` and other options(`highWaterMark`, `defaultEncoding` ...) is same as Node.js `Stream`.

## License

MIT © [Teambition](https://www.teambition.com)

[npm-url]: https://npmjs.org/package/merge2
[npm-image]: http://img.shields.io/npm/v/merge2.svg

[travis-url]: https://travis-ci.org/teambition/merge2
[travis-image]: http://img.shields.io/travis/teambition/merge2.svg

[downloads-url]: https://npmjs.org/package/merge2
[downloads-image]: http://img.shields.io/npm/dm/merge2.svg?style=flat-square


code:
'use strict'
/*
 * merge2
 * https://github.com/teambition/merge2
 *
 * Copyright (c) 2014-2020 Teambition
 * Licensed under the MIT license.
 */
const Stream = require('stream')
const PassThrough = Stream.PassThrough
const slice = Array.prototype.slice

module.exports = merge2

function merge2 () {
  const streamsQueue = []
  const args = slice.call(arguments)
  let merging = false
  let options = args[args.length - 1]

  if (options && !Array.isArray(options) && options.pipe == null) {
    args.pop()
  } else {
    options = {}
  }

  const doEnd = options.end !== false
  const doPipeError = options.pipeError === true
  if (options.objectMode == null) {
    options.objectMode = true
  }
  if (options.highWaterMark == null) {
    options.highWaterMark = 64 * 1024
  }
  const mergedStream = PassThrough(options)

  function addStream () {
    for (let i = 0, len = arguments.length; i < len; i++) {
      streamsQueue.push(pauseStreams(arguments[i], options))
    }
    mergeStream()
    return this
  }

  function mergeStream () {
    if (merging) {
      return
    }
    merging = true

    let streams = streamsQueue.shift()
    if (!streams) {
      process.nextTick(endStream)
      return
    }
    if (!Array.isArray(streams)) {
      streams = [streams]
    }

    let pipesCount = streams.length + 1

    function next () {
      if (--pipesCount > 0) {
        return
      }
      merging = false
      mergeStream()
    }

    function pipe (stream) {
      function onend () {
        stream.removeListener('merge2UnpipeEnd', onend)
        stream.removeListener('end', onend)
        if (doPipeError) {
          stream.removeListener('error', onerror)
        }
        next()
      }
      function onerror (err) {
        mergedStream.emit('error', err)
      }
      // skip ended stream
      if (stream._readableState.endEmitted) {
        return next()
      }

      stream.on('merge2UnpipeEnd', onend)
      stream.on('end', onend)

      if (doPipeError) {
        stream.on('error', onerror)
      }

      stream.pipe(mergedStream, { end: false })
      // compatible for old stream
      stream.resume()
    }

    for (let i = 0; i < streams.length; i++) {
      pipe(streams[i])
    }

    next()
  }

  function endStream () {
    merging = false
    // emit 'queueDrain' when all streams merged.
    mergedStream.emit('queueDrain')
    if (doEnd) {
      mergedStream.end()
    }
  }

  mergedStream.setMaxListeners(0)
  mergedStream.add = addStream
  mergedStream.on('unpipe', function (stream) {
    stream.emit('merge2UnpipeEnd')
  })

  if (args.length) {
    addStream.apply(null, args)
  }
  return mergedStream
}

// check and pause streams for pipe.
function pauseStreams (streams, options) {
  if (!Array.isArray(streams)) {
    // Backwards-compat with old-style streams
    if (!streams._readableState && streams.pipe) {
      streams = streams.pipe(PassThrough(options))
    }
    if (!streams._readableState || !streams.pause || !streams.pipe) {
      throw new Error('Only readable stream can be merged.')
    }
    streams.pause()
  } else {
    for (let i = 0, len = streams.length; i < len; i++) {
      streams[i] = pauseStreams(streams[i], options)
    }
  }
  return streams
}


description: Merge multiple streams into one stream in sequence or parallel.

keywords:
merge2
multiple
sequence
parallel
merge
stream
merge stream
sync

test: standard && tman


code:
# Methods

[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Node.js Version][node-version-image]][node-version-url]
[![Build Status][travis-image]][travis-url]
[![Test Coverage][coveralls-image]][coveralls-url]

HTTP verbs that Node.js core's HTTP parser supports.

This module provides an export that is just like `http.METHODS` from Node.js core,
with the following differences:

  * All method names are lower-cased.
  * Contains a fallback list of methods for Node.js versions that do not have a
    `http.METHODS` export (0.10 and lower).
  * Provides the fallback list when using tools like `browserify` without pulling
    in the `http` shim module.

## Install

```bash
$ npm install methods
```

## API

```js
var methods = require('methods')
```

### methods

This is an array of lower-cased method names that Node.js supports. If Node.js
provides the `http.METHODS` export, then this is the same array lower-cased,
otherwise it is a snapshot of the verbs from Node.js 0.10.

## License

[MIT](LICENSE)

[npm-image]: https://img.shields.io/npm/v/methods.svg?style=flat
[npm-url]: https://npmjs.org/package/methods
[node-version-image]: https://img.shields.io/node/v/methods.svg?style=flat
[node-version-url]: https://nodejs.org/en/download/
[travis-image]: https://img.shields.io/travis/jshttp/methods.svg?style=flat
[travis-url]: https://travis-ci.org/jshttp/methods
[coveralls-image]: https://img.shields.io/coveralls/jshttp/methods.svg?style=flat
[coveralls-url]: https://coveralls.io/r/jshttp/methods?branch=master
[downloads-image]: https://img.shields.io/npm/dm/methods.svg?style=flat
[downloads-url]: https://npmjs.org/package/methods


code:
/*!
 * methods
 * Copyright(c) 2013-2014 TJ Holowaychuk
 * Copyright(c) 2015-2016 Douglas Christopher Wilson
 * MIT Licensed
 */

'use strict';

/**
 * Module dependencies.
 * @private
 */

var http = require('http');

/**
 * Module exports.
 * @public
 */

module.exports = getCurrentNodeMethods() || getBasicNodeMethods();

/**
 * Get the current Node.js methods.
 * @private
 */

function getCurrentNodeMethods() {
  return http.METHODS && http.METHODS.map(function lowerCaseMethod(method) {
    return method.toLowerCase();
  });
}

/**
 * Get the "basic" Node.js methods, a snapshot from Node.js 0.10.
 * @private
 */

function getBasicNodeMethods() {
  return [
    'get',
    'post',
    'put',
    'head',
    'delete',
    'options',
    'trace',
    'copy',
    'lock',
    'mkcol',
    'move',
    'purge',
    'propfind',
    'proppatch',
    'unlock',
    'report',
    'mkactivity',
    'checkout',
    'merge',
    'm-search',
    'notify',
    'subscribe',
    'unsubscribe',
    'patch',
    'search',
    'connect'
  ];
}


methods

description: HTTP methods that node supports

contributors: Jonathan Ong <me@jongleberry.com> (http://jongleberry.com)

contributors: TJ Holowaychuk <tj@vision-media.ca> (http://tjholowaychuk.com)

repository: jshttp/methods

test-travis: istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/

keywords: http methods


code:
# micromatch [![NPM version](https://img.shields.io/npm/v/micromatch.svg?style=flat)](https://www.npmjs.com/package/micromatch) [![NPM monthly downloads](https://img.shields.io/npm/dm/micromatch.svg?style=flat)](https://npmjs.org/package/micromatch) [![NPM total downloads](https://img.shields.io/npm/dt/micromatch.svg?style=flat)](https://npmjs.org/package/micromatch)  [![Tests](https://github.com/micromatch/micromatch/actions/workflows/test.yml/badge.svg)](https://github.com/micromatch/micromatch/actions/workflows/test.yml)

> Glob matching for javascript/node.js. A replacement and faster alternative to minimatch and multimatch.

Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.

## Table of Contents

Details

  * [Install](#install)
- [Sponsors](#sponsors)
  * [Gold Sponsors](#gold-sponsors)
  * [Quickstart](#quickstart)
  * [Why use micromatch?](#why-use-micromatch)
    + [Matching features](#matching-features)
  * [Switching to micromatch](#switching-to-micromatch)
    + [From minimatch](#from-minimatch)
    + [From multimatch](#from-multimatch)
  * [API](#api)
  * [Options](#options)
  * [Options Examples](#options-examples)
    + [options.basename](#optionsbasename)
    + [options.bash](#optionsbash)
    + [options.expandRange](#optionsexpandrange)
    + [options.format](#optionsformat)
    + [options.ignore](#optionsignore)
    + [options.matchBase](#optionsmatchbase)
    + [options.noextglob](#optionsnoextglob)
    + [options.nonegate](#optionsnonegate)
    + [options.noglobstar](#optionsnoglobstar)
    + [options.nonull](#optionsnonull)
    + [options.nullglob](#optionsnullglob)
    + [options.onIgnore](#optionsonignore)
    + [options.onMatch](#optionsonmatch)
    + [options.onResult](#optionsonresult)
    + [options.posixSlashes](#optionsposixslashes)
    + [options.unescape](#optionsunescape)
  * [Extended globbing](#extended-globbing)
    + [Extglobs](#extglobs)
    + [Braces](#braces)
    + [Regex character classes](#regex-character-classes)
    + [Regex groups](#regex-groups)
    + [POSIX bracket expressions](#posix-bracket-expressions)
  * [Notes](#notes)
    + [Bash 4.3 parity](#bash-43-parity)
    + [Backslashes](#backslashes)
  * [Benchmarks](#benchmarks)
    + [Running benchmarks](#running-benchmarks)
    + [Latest results](#latest-results)
  * [Contributing](#contributing)
  * [About](#about)

## Install

Install with [npm](https://www.npmjs.com/):

```sh
$ npm install --save micromatch
```

# Sponsors

[Become a Sponsor](https://github.com/sponsors/jonschlinkert) to add your logo to this README, or any of [my other projects](https://github.com/jonschlinkert?tab=repositories&q=&type=&language=&sort=stargazers)

## Quickstart

```js
const micromatch = require('micromatch');
// micromatch(list, patterns[, options]);
```

The [main export](#micromatch) takes a list of strings and one or more glob patterns:

```js
console.log(micromatch(['foo', 'bar', 'baz', 'qux'], ['f*', 'b*'])) //=> ['foo', 'bar', 'baz']
console.log(micromatch(['foo', 'bar', 'baz', 'qux'], ['*', '!b*'])) //=> ['foo', 'qux']
```

Use [.isMatch()](#ismatch) to for boolean matching:

```js
console.log(micromatch.isMatch('foo', 'f*')) //=> true
console.log(micromatch.isMatch('foo', ['b*', 'f*'])) //=> true
```

[Switching](#switching-to-micromatch) from minimatch and multimatch is easy!

## Why use micromatch?

> micromatch is a [replacement](#switching-to-micromatch) for minimatch and multimatch

* Supports all of the same matching features as [minimatch](https://github.com/isaacs/minimatch) and [multimatch](https://github.com/sindresorhus/multimatch)
* More complete support for the Bash 4.3 specification than minimatch and multimatch. Micromatch passes _all of the spec tests_ from bash, including some that bash still fails.
* **Fast & Performant** - Loads in about 5ms and performs [fast matches](#benchmarks).
* **Glob matching** - Using wildcards (`*` and `?`), globstars (`**`) for nested directories
* **[Advanced globbing](#extended-globbing)** - Supports [extglobs](#extglobs), [braces](#braces-1), and [POSIX brackets](#posix-bracket-expressions), and support for escaping special characters with `\` or quotes.
* **Accurate** - Covers more scenarios [than minimatch](https://github.com/yarnpkg/yarn/pull/3339)
* **Well tested** - More than 5,000 [test assertions](./test)
* **Windows support** - More reliable windows support than minimatch and multimatch.
* **[Safe](https://github.com/micromatch/braces#braces-is-safe)** - Micromatch is not subject to DoS with brace patterns like minimatch and multimatch.

### Matching features

* Support for multiple glob patterns (no need for wrappers like multimatch)
* Wildcards (`**`, `*.js`)
* Negation (`'!a/*.js'`, `'*!(b).js'`)
* [extglobs](#extglobs) (`+(x|y)`, `!(a|b)`)
* [POSIX character classes](#posix-bracket-expressions) (`[[:alpha:][:digit:]]`)
* [brace expansion](https://github.com/micromatch/braces) (`foo/{1..5}.md`, `bar/{a,b,c}.js`)
* regex character classes (`foo-[1-5].js`)
* regex logical "or" (`foo/(abc|xyz).js`)

You can mix and match these features to create whatever patterns you need!

## Switching to micromatch

_(There is one notable difference between micromatch and minimatch in regards to how backslashes are handled. See [the notes about backslashes](#backslashes) for more information.)_

### From minimatch

Use [micromatch.isMatch()](#ismatch) instead of `minimatch()`:

```js
console.log(micromatch.isMatch('foo', 'b*')); //=> false
```

Use [micromatch.match()](#match) instead of `minimatch.match()`:

```js
console.log(micromatch.match(['foo', 'bar'], 'b*')); //=> 'bar'
```

### From multimatch

Same signature:

```js
console.log(micromatch(['foo', 'bar', 'baz'], ['f*', '*z'])); //=> ['foo', 'baz']
```

## API

**Params**

* `list` **{String|Array<string>}**: List of strings to match.
* `patterns` **{String|Array<string>}**: One or more glob patterns to use for matching.
* `options` **{Object}**: See available [options](#options)
* `returns` **{Array}**: Returns an array of matches

**Example**

```js
const mm = require('micromatch');
// mm(list, patterns[, options]);

console.log(mm(['a.js', 'a.txt'], ['*.js']));
//=> [ 'a.js' ]
```

### [.matcher](index.js#L109)

Returns a matcher function from the given glob `pattern` and `options`. The returned function takes a string to match as its only argument and returns true if the string is a match.

**Params**

* `pattern` **{String}**: Glob pattern
* `options` **{Object}**
* `returns` **{Function}**: Returns a matcher function.

**Example**

```js
const mm = require('micromatch');
// mm.matcher(pattern[, options]);

const isMatch = mm.matcher('*.!(*a)');
console.log(isMatch('a.a')); //=> false
console.log(isMatch('a.b')); //=> true
```

### [.isMatch](index.js#L128)

Returns true if **any** of the given glob `patterns` match the specified `string`.

**Params**

* `str` **{String}**: The string to test.
* `patterns` **{String|Array}**: One or more glob patterns to use for matching.
* `[options]` **{Object}**: See available [options](#options).
* `returns` **{Boolean}**: Returns true if any patterns match `str`

**Example**

```js
const mm = require('micromatch');
// mm.isMatch(string, patterns[, options]);

console.log(mm.isMatch('a.a', ['b.*', '*.a'])); //=> true
console.log(mm.isMatch('a.a', 'b.*')); //=> false
```

### [.not](index.js#L153)

Returns a list of strings that _**do not match any**_ of the given `patterns`.

**Params**

* `list` **{Array}**: Array of strings to match.
* `patterns` **{String|Array}**: One or more glob pattern to use for matching.
* `options` **{Object}**: See available [options](#options) for changing how matches are performed
* `returns` **{Array}**: Returns an array of strings that **do not match** the given patterns.

**Example**

```js
const mm = require('micromatch');
// mm.not(list, patterns[, options]);

console.log(mm.not(['a.a', 'b.b', 'c.c'], '*.a'));
//=> ['b.b', 'c.c']
```

### [.contains](index.js#L193)

Returns true if the given `string` contains the given pattern. Similar to [.isMatch](#isMatch) but the pattern can match any part of the string.

**Params**

* `str` **{String}**: The string to match.
* `patterns` **{String|Array}**: Glob pattern to use for matching.
* `options` **{Object}**: See available [options](#options) for changing how matches are performed
* `returns` **{Boolean}**: Returns true if any of the patterns matches any part of `str`.

**Example**

```js
var mm = require('micromatch');
// mm.contains(string, pattern[, options]);

console.log(mm.contains('aa/bb/cc', '*b'));
//=> true
console.log(mm.contains('aa/bb/cc', '*d'));
//=> false
```

### [.matchKeys](index.js#L235)

Filter the keys of the given object with the given `glob` pattern and `options`. Does not attempt to match nested keys. If you need this feature, use [glob-object](https://github.com/jonschlinkert/glob-object) instead.

**Params**

* `object` **{Object}**: The object with keys to filter.
* `patterns` **{String|Array}**: One or more glob patterns to use for matching.
* `options` **{Object}**: See available [options](#options) for changing how matches are performed
* `returns` **{Object}**: Returns an object with only keys that match the given patterns.

**Example**

```js
const mm = require('micromatch');
// mm.matchKeys(object, patterns[, options]);

const obj = { aa: 'a', ab: 'b', ac: 'c' };
console.log(mm.matchKeys(obj, '*b'));
//=> { ab: 'b' }
```

### [.some](index.js#L264)

Returns true if some of the strings in the given `list` match any of the given glob `patterns`.

**Params**

* `list` **{String|Array}**: The string or array of strings to test. Returns as soon as the first match is found.
* `patterns` **{String|Array}**: One or more glob patterns to use for matching.
* `options` **{Object}**: See available [options](#options) for changing how matches are performed
* `returns` **{Boolean}**: Returns true if any `patterns` matches any of the strings in `list`

**Example**

```js
const mm = require('micromatch');
// mm.some(list, patterns[, options]);

console.log(mm.some(['foo.js', 'bar.js'], ['*.js', '!foo.js']));
// true
console.log(mm.some(['foo.js'], ['*.js', '!foo.js']));
// false
```

### [.every](index.js#L300)

Returns true if every string in the given `list` matches any of the given glob `patterns`.

**Params**

* `list` **{String|Array}**: The string or array of strings to test.
* `patterns` **{String|Array}**: One or more glob patterns to use for matching.
* `options` **{Object}**: See available [options](#options) for changing how matches are performed
* `returns` **{Boolean}**: Returns true if all `patterns` matches all of the strings in `list`

**Example**

```js
const mm = require('micromatch');
// mm.every(list, patterns[, options]);

console.log(mm.every('foo.js', ['foo.js']));
// true
console.log(mm.every(['foo.js', 'bar.js'], ['*.js']));
// true
console.log(mm.every(['foo.js', 'bar.js'], ['*.js', '!foo.js']));
// false
console.log(mm.every(['foo.js'], ['*.js', '!foo.js']));
// false
```

### [.all](index.js#L339)

Returns true if **all** of the given `patterns` match the specified string.

**Params**

* `str` **{String|Array}**: The string to test.
* `patterns` **{String|Array}**: One or more glob patterns to use for matching.
* `options` **{Object}**: See available [options](#options) for changing how matches are performed
* `returns` **{Boolean}**: Returns true if any patterns match `str`

**Example**

```js
const mm = require('micromatch');
// mm.all(string, patterns[, options]);

console.log(mm.all('foo.js', ['foo.js']));
// true

console.log(mm.all('foo.js', ['*.js', '!foo.js']));
// false

console.log(mm.all('foo.js', ['*.js', 'foo.js']));
// true

console.log(mm.all('foo.js', ['*.js', 'f*', '*o*', '*o.js']));
// true
```

### [.capture](index.js#L366)

Returns an array of matches captured by `pattern` in `string, or`null` if the pattern did not match.

**Params**

* `glob` **{String}**: Glob pattern to use for matching.
* `input` **{String}**: String to match
* `options` **{Object}**: See available [options](#options) for changing how matches are performed
* `returns` **{Array|null}**: Returns an array of captures if the input matches the glob pattern, otherwise `null`.

**Example**

```js
const mm = require('micromatch');
// mm.capture(pattern, string[, options]);

console.log(mm.capture('test/*.js', 'test/foo.js'));
//=> ['foo']
console.log(mm.capture('test/*.js', 'foo/bar.css'));
//=> null
```

### [.makeRe](index.js#L392)

Create a regular expression from the given glob `pattern`.

**Params**

* `pattern` **{String}**: A glob pattern to convert to regex.
* `options` **{Object}**
* `returns` **{RegExp}**: Returns a regex created from the given pattern.

**Example**

```js
const mm = require('micromatch');
// mm.makeRe(pattern[, options]);

console.log(mm.makeRe('*.js'));
//=> /^(?:(\.[\\\/])?(?!\.)(?=.)[^\/]*?\.js)$/
```

### [.scan](index.js#L408)

Scan a glob pattern to separate the pattern into segments. Used by the [split](#split) method.

**Params**

* `pattern` **{String}**
* `options` **{Object}**
* `returns` **{Object}**: Returns an object with

**Example**

```js
const mm = require('micromatch');
const state = mm.scan(pattern[, options]);
```

### [.parse](index.js#L424)

Parse a glob pattern to create the source string for a regular expression.

**Params**

* `glob` **{String}**
* `options` **{Object}**
* `returns` **{Object}**: Returns an object with useful properties and output to be used as regex source string.

**Example**

```js
const mm = require('micromatch');
const state = mm.parse(pattern[, options]);
```

### [.braces](index.js#L451)

Process the given brace `pattern`.

**Params**

* `pattern` **{String}**: String with brace pattern to process.
* `options` **{Object}**: Any [options](#options) to change how expansion is performed. See the [braces](https://github.com/micromatch/braces) library for all available options.
* `returns` **{Array}**

**Example**

```js
const { braces } = require('micromatch');
console.log(braces('foo/{a,b,c}/bar'));
//=> [ 'foo/(a|b|c)/bar' ]

console.log(braces('foo/{a,b,c}/bar', { expand: true }));
//=> [ 'foo/a/bar', 'foo/b/bar', 'foo/c/bar' ]
```

## Options

| **Option** | **Type** | **Default value** | **Description** |
| --- | --- | --- | --- |
| `basename`            | `boolean`      | `false`     | If set, then patterns without slashes will be matched against the basename of the path if it contains slashes.  For example, `a?b` would match the path `/xyz/123/acb`, but not `/xyz/acb/123`. |
| `bash`                | `boolean`      | `false`     | Follow bash matching rules more strictly - disallows backslashes as escape characters, and treats single stars as globstars (`**`). |
| `capture`             | `boolean`      | `undefined` | Return regex matches in supporting methods. |
| `contains`            | `boolean`      | `undefined` | Allows glob to match any part of the given string(s). |
| `cwd`                 | `string`       | `process.cwd()` | Current working directory. Used by `picomatch.split()` |
| `debug`               | `boolean`      | `undefined` | Debug regular expressions when an error is thrown. |
| `dot`                 | `boolean`      | `false`     | Match dotfiles. Otherwise dotfiles are ignored unless a `.` is explicitly defined in the pattern. |
| `expandRange`         | `function`     | `undefined` | Custom function for expanding ranges in brace patterns, such as `{a..z}`. The function receives the range values as two arguments, and it must return a string to be used in the generated regex. It's recommended that returned strings be wrapped in parentheses. This option is overridden by the `expandBrace` option. |
| `failglob`            | `boolean`      | `false`     | Similar to the `failglob` behavior in Bash, throws an error when no matches are found. Based on the bash option of the same name. |
| `fastpaths`           | `boolean`      | `true`      | To speed up processing, full parsing is skipped for a handful common glob patterns. Disable this behavior by setting this option to `false`. |
| `flags`               | `boolean`      | `undefined` | Regex flags to use in the generated regex. If defined, the `nocase` option will be overridden. |
| [format](#optionsformat) | `function` | `undefined` | Custom function for formatting the returned string. This is useful for removing leading slashes, converting Windows paths to Posix paths, etc. |
| `ignore`              | `array\|string` | `undefined` | One or more glob patterns for excluding strings that should not be matched from the result. |
| `keepQuotes`          | `boolean`      | `false`     | Retain quotes in the generated regex, since quotes may also be used as an alternative to backslashes.  |
| `literalBrackets`     | `boolean`      | `undefined` | When `true`, brackets in the glob pattern will be escaped so that only literal brackets will be matched. |
| `lookbehinds`         | `boolean`      | `true`      | Support regex positive and negative lookbehinds. Note that you must be using Node 8.1.10 or higher to enable regex lookbehinds. |
| `matchBase`           | `boolean`      | `false`     | Alias for `basename` |
| `maxLength`           | `boolean`      | `65536`     | Limit the max length of the input string. An error is thrown if the input string is longer than this value. |
| `nobrace`             | `boolean`      | `false`     | Disable brace matching, so that `{a,b}` and `{1..3}` would be treated as literal characters. |
| `nobracket`           | `boolean`      | `undefined` | Disable matching with regex brackets. |
| `nocase`              | `boolean`      | `false`     | Perform case-insensitive matching. Equivalent to the regex `i` flag. Note that this option is ignored when the `flags` option is defined. |
| `nodupes`             | `boolean`      | `true`      | Deprecated, use `nounique` instead. This option will be removed in a future major release. By default duplicates are removed. Disable uniquification by setting this option to false. |
| `noext`               | `boolean`      | `false`     | Alias for `noextglob` |
| `noextglob`           | `boolean`      | `false`     | Disable support for matching with [extglobs](#extglobs) (like `+(a\|b)`) |
| `noglobstar`          | `boolean`      | `false`     | Disable support for matching nested directories with globstars (`**`) |
| `nonegate`            | `boolean`      | `false`     | Disable support for negating with leading `!` |
| `noquantifiers`       | `boolean`      | `false`     | Disable support for regex quantifiers (like `a{1,2}`) and treat them as brace patterns to be expanded. |
| [onIgnore](#optionsonIgnore) | `function` | `undefined` | Function to be called on ignored items. |
| [onMatch](#optionsonMatch) | `function` | `undefined` | Function to be called on matched items. |
| [onResult](#optionsonResult) | `function` | `undefined` | Function to be called on all items, regardless of whether or not they are matched or ignored. |
| `posix`               | `boolean`      | `false`     | Support [POSIX character classes](#posix-bracket-expressions) ("posix brackets"). |
| `posixSlashes`        | `boolean`      | `undefined` | Convert all slashes in file paths to forward slashes. This does not convert slashes in the glob pattern itself |
| `prepend`             | `string`       | `undefined` | String to prepend to the generated regex used for matching. |
| `regex`               | `boolean`      | `false`     | Use regular expression rules for `+` (instead of matching literal `+`), and for stars that follow closing parentheses or brackets (as in `)*` and `]*`). |
| `strictBrackets`      | `boolean`      | `undefined` | Throw an error if brackets, braces, or parens are imbalanced. |
| `strictSlashes`       | `boolean`      | `undefined` | When true, picomatch won't match trailing slashes with single stars. |
| `unescape`            | `boolean`      | `undefined` | Remove preceding backslashes from escaped glob characters before creating the regular expression to perform matches. |
| `unixify`             | `boolean`      | `undefined` | Alias for `posixSlashes`, for backwards compatitibility. |

## Options Examples

### options.basename

Allow glob patterns without slashes to match a file path based on its basename. Same behavior as [minimatch](https://github.com/isaacs/minimatch) option `matchBase`.

**Type**: `Boolean`

**Default**: `false`

**Example**

```js
micromatch(['a/b.js', 'a/c.md'], '*.js');
//=> []

micromatch(['a/b.js', 'a/c.md'], '*.js', { basename: true });
//=> ['a/b.js']
```

### options.bash

Enabled by default, this option enforces bash-like behavior with stars immediately following a bracket expression. Bash bracket expressions are similar to regex character classes, but unlike regex, a star following a bracket expression **does not repeat the bracketed characters**. Instead, the star is treated the same as any other star.

**Type**: `Boolean`

**Default**: `true`

**Example**

```js
const files = ['abc', 'ajz'];
console.log(micromatch(files, '[a-c]*'));
//=> ['abc', 'ajz']

console.log(micromatch(files, '[a-c]*', { bash: false }));
```

### options.expandRange

**Type**: `function`

**Default**: `undefined`

Custom function for expanding ranges in brace patterns. The [fill-range](https://github.com/jonschlinkert/fill-range) library is ideal for this purpose, or you can use custom code to do whatever you need.

**Example**

The following example shows how to create a glob that matches a numeric folder name between `01` and `25`, with leading zeros.

```js
const fill = require('fill-range');
const regex = micromatch.makeRe('foo/{01..25}/bar', {
  expandRange(a, b) {
    return `(${fill(a, b, { toRegex: true })})`;
  }
});

console.log(regex)
//=> /^(?:foo\/((?:0[1-9]|1[0-9]|2[0-5]))\/bar)$/

console.log(regex.test('foo/00/bar')) // false
console.log(regex.test('foo/01/bar')) // true
console.log(regex.test('foo/10/bar')) // true
console.log(regex.test('foo/22/bar')) // true
console.log(regex.test('foo/25/bar')) // true
console.log(regex.test('foo/26/bar')) // false
```

### options.format

**Type**: `function`

**Default**: `undefined`

Custom function for formatting strings before they're matched.

**Example**

```js
// strip leading './' from strings
const format = str => str.replace(/^\.\//, '');
const isMatch = picomatch('foo/*.js', { format });
console.log(isMatch('./foo/bar.js')) //=> true
```

### options.ignore

String or array of glob patterns to match files to ignore.

**Type**: `String|Array`

**Default**: `undefined`

```js
const isMatch = micromatch.matcher('*', { ignore: 'f*' });
console.log(isMatch('foo')) //=> false
console.log(isMatch('bar')) //=> true
console.log(isMatch('baz')) //=> true
```

### options.matchBase

Alias for [options.basename](#options-basename).

### options.noextglob

Disable extglob support, so that [extglobs](#extglobs) are regarded as literal characters.

**Type**: `Boolean`

**Default**: `undefined`

**Examples**

```js
console.log(micromatch(['a/z', 'a/b', 'a/!(z)'], 'a/!(z)'));
//=> ['a/b', 'a/!(z)']

console.log(micromatch(['a/z', 'a/b', 'a/!(z)'], 'a/!(z)', { noextglob: true }));
//=> ['a/!(z)'] (matches only as literal characters)
```

### options.nonegate

Disallow negation (`!`) patterns, and treat leading `!` as a literal character to match.

**Type**: `Boolean`

**Default**: `undefined`

### options.noglobstar

Disable matching with globstars (`**`).

**Type**: `Boolean`

**Default**: `undefined`

```js
micromatch(['a/b', 'a/b/c', 'a/b/c/d'], 'a/**');
//=> ['a/b', 'a/b/c', 'a/b/c/d']

micromatch(['a/b', 'a/b/c', 'a/b/c/d'], 'a/**', {noglobstar: true});
//=> ['a/b']
```

### options.nonull

Alias for [options.nullglob](#options-nullglob).

### options.nullglob

If `true`, when no matches are found the actual (arrayified) glob pattern is returned instead of an empty array. Same behavior as [minimatch](https://github.com/isaacs/minimatch) option `nonull`.

**Type**: `Boolean`

**Default**: `undefined`

### options.onIgnore

```js
const onIgnore = ({ glob, regex, input, output }) => {
  console.log({ glob, regex, input, output });
  // { glob: '*', regex: /^(?:(?!\.)(?=.)[^\/]*?\/?)$/, input: 'foo', output: 'foo' }
};

const isMatch = micromatch.matcher('*', { onIgnore, ignore: 'f*' });
isMatch('foo');
isMatch('bar');
isMatch('baz');
```

### options.onMatch

```js
const onMatch = ({ glob, regex, input, output }) => {
  console.log({ input, output });
  // { input: 'some\\path', output: 'some/path' }
  // { input: 'some\\path', output: 'some/path' }
  // { input: 'some\\path', output: 'some/path' }
};

const isMatch = micromatch.matcher('**', { onMatch, posixSlashes: true });
isMatch('some\\path');
isMatch('some\\path');
isMatch('some\\path');
```

### options.onResult

```js
const onResult = ({ glob, regex, input, output }) => {
  console.log({ glob, regex, input, output });
};

const isMatch = micromatch('*', { onResult, ignore: 'f*' });
isMatch('foo');
isMatch('bar');
isMatch('baz');
```

### options.posixSlashes

Convert path separators on returned files to posix/unix-style forward slashes. Aliased as `unixify` for backwards compatibility.

**Type**: `Boolean`

**Default**: `true` on windows, `false` everywhere else.

**Example**

```js
console.log(micromatch.match(['a\\b\\c'], 'a/**'));
//=> ['a/b/c']

console.log(micromatch.match(['a\\b\\c'], { posixSlashes: false }));
//=> ['a\\b\\c']
```

### options.unescape

Remove backslashes from escaped glob characters before creating the regular expression to perform matches.

**Type**: `Boolean`

**Default**: `undefined`

**Example**

In this example we want to match a literal `*`:

```js
console.log(micromatch.match(['abc', 'a\\*c'], 'a\\*c'));
//=> ['a\\*c']

console.log(micromatch.match(['abc', 'a\\*c'], 'a\\*c', { unescape: true }));
//=> ['a*c']
```

## Extended globbing

Micromatch supports the following extended globbing features.

### Extglobs

Extended globbing, as described by the bash man page:

| **pattern** | **regex equivalent** | **description** |
| --- | --- | --- |
| `?(pattern)` | `(pattern)?` | Matches zero or one occurrence of the given patterns |
| `*(pattern)` | `(pattern)*` | Matches zero or more occurrences of the given patterns |
| `+(pattern)` | `(pattern)+` | Matches one or more occurrences of the given patterns |
| `@(pattern)` | `(pattern)` * | Matches one of the given patterns |
| `!(pattern)` | N/A (equivalent regex is much more complicated) | Matches anything except one of the given patterns |

* Note that `@` isn't a regex character.

### Braces

Brace patterns can be used to match specific ranges or sets of characters.

**Example**

The pattern `{f,b}*/{1..3}/{b,q}*` would match any of following strings:

```
foo/1/bar
foo/2/bar
foo/3/bar
baz/1/qux
baz/2/qux
baz/3/qux
```

Visit [braces](https://github.com/micromatch/braces) to see the full range of features and options related to brace expansion, or to create brace matching or expansion related issues.

### Regex character classes

Given the list: `['a.js', 'b.js', 'c.js', 'd.js', 'E.js']`:

* `[ac].js`: matches both `a` and `c`, returning `['a.js', 'c.js']`
* `[b-d].js`: matches from `b` to `d`, returning `['b.js', 'c.js', 'd.js']`
* `a/[A-Z].js`: matches and uppercase letter, returning `['a/E.md']`

Learn about [regex character classes](http://www.regular-expressions.info/charclass.html).

### Regex groups

Given `['a.js', 'b.js', 'c.js', 'd.js', 'E.js']`:

* `(a|c).js`: would match either `a` or `c`, returning `['a.js', 'c.js']`
* `(b|d).js`: would match either `b` or `d`, returning `['b.js', 'd.js']`
* `(b|[A-Z]).js`: would match either `b` or an uppercase letter, returning `['b.js', 'E.js']`

As with regex, parens can be nested, so patterns like `((a|b)|c)/b` will work. Although brace expansion might be friendlier to use, depending on preference.

### POSIX bracket expressions

POSIX brackets are intended to be more user-friendly than regex character classes. This of course is in the eye of the beholder.

**Example**

```js
console.log(micromatch.isMatch('a1', '[[:alpha:][:digit:]]')) //=> true
console.log(micromatch.isMatch('a1', '[[:alpha:][:alpha:]]')) //=> false
```

***

## Notes

### Bash 4.3 parity

Whenever possible matching behavior is based on behavior Bash 4.3, which is mostly consistent with minimatch.

However, it's suprising how many edge cases and rabbit holes there are with glob matching, and since there is no real glob specification, and micromatch is more accurate than both Bash and minimatch, there are cases where best-guesses were made for behavior. In a few cases where Bash had no answers, we used wildmatch (used by git) as a fallback.

### Backslashes

There is an important, notable difference between minimatch and micromatch _in regards to how backslashes are handled_ in glob patterns.

* Micromatch exclusively and explicitly reserves backslashes for escaping characters in a glob pattern, even on windows, which is consistent with bash behavior. _More importantly, unescaping globs can result in unsafe regular expressions_.
* Minimatch converts all backslashes to forward slashes, which means you can't use backslashes to escape any characters in your glob patterns.

We made this decision for micromatch for a couple of reasons:

* Consistency with bash conventions.
* Glob patterns are not filepaths. They are a type of [regular language](https://en.wikipedia.org/wiki/Regular_language) that is converted to a JavaScript regular expression. Thus, when forward slashes are defined in a glob pattern, the resulting regular expression will match windows or POSIX path separators just fine.

**A note about joining paths to globs**

Note that when you pass something like `path.join('foo', '*')` to micromatch, you are creating a filepath and expecting it to still work as a glob pattern. This causes problems on windows, since the `path.sep` is `\\`.

In other words, since `\\` is reserved as an escape character in globs, on windows `path.join('foo', '*')` would result in `foo\\*`, which tells micromatch to match `*` as a literal character. This is the same behavior as bash.

To solve this, you might be inspired to do something like `'foo\\*'.replace(/\\/g, '/')`, but this causes another, potentially much more serious, problem.

## Benchmarks

### Running benchmarks

Install dependencies for running benchmarks:

```sh
$ cd bench && npm install
```

Run the benchmarks:

```sh
$ npm run bench
```

### Latest results

As of August 23, 2024 (longer bars are better):

```sh
# .makeRe star
  micromatch x 2,232,802 ops/sec ±2.34% (89 runs sampled))
  minimatch x 781,018 ops/sec ±6.74% (92 runs sampled))

# .makeRe star; dot=true
  micromatch x 1,863,453 ops/sec ±0.74% (93 runs sampled)
  minimatch x 723,105 ops/sec ±0.75% (93 runs sampled)

# .makeRe globstar
  micromatch x 1,624,179 ops/sec ±2.22% (91 runs sampled)
  minimatch x 1,117,230 ops/sec ±2.78% (86 runs sampled))

# .makeRe globstars
  micromatch x 1,658,642 ops/sec ±0.86% (92 runs sampled)
  minimatch x 741,224 ops/sec ±1.24% (89 runs sampled))

# .makeRe with leading star
  micromatch x 1,525,014 ops/sec ±1.63% (90 runs sampled)
  minimatch x 561,074 ops/sec ±3.07% (89 runs sampled)

# .makeRe - braces
  micromatch x 172,478 ops/sec ±2.37% (78 runs sampled)
  minimatch x 96,087 ops/sec ±2.34% (88 runs sampled)))

# .makeRe braces - range (expanded)
  micromatch x 26,973 ops/sec ±0.84% (89 runs sampled)
  minimatch x 3,023 ops/sec ±0.99% (90 runs sampled))

# .makeRe braces - range (compiled)
  micromatch x 152,892 ops/sec ±1.67% (83 runs sampled)
  minimatch x 992 ops/sec ±3.50% (89 runs sampled)d))

# .makeRe braces - nested ranges (expanded)
  micromatch x 15,816 ops/sec ±13.05% (80 runs sampled)
  minimatch x 2,953 ops/sec ±1.64% (91 runs sampled)

# .makeRe braces - nested ranges (compiled)
  micromatch x 110,881 ops/sec ±1.85% (82 runs sampled)
  minimatch x 1,008 ops/sec ±1.51% (91 runs sampled)

# .makeRe braces - set (compiled)
  micromatch x 134,930 ops/sec ±3.54% (63 runs sampled))
  minimatch x 43,242 ops/sec ±0.60% (93 runs sampled)

# .makeRe braces - nested sets (compiled)
  micromatch x 94,455 ops/sec ±1.74% (69 runs sampled))
  minimatch x 27,720 ops/sec ±1.84% (93 runs sampled))
```

## Contributing

All contributions are welcome! Please read [the contributing guide](.github/contributing.md) to get started.

**Bug reports**

Please create an issue if you encounter a bug or matching behavior that doesn't seem correct. If you find a matching-related issue, please:

* [research existing issues first](../../issues) (open and closed)
* visit the [GNU Bash documentation](https://www.gnu.org/software/bash/manual/) to see how Bash deals with the pattern
* visit the [minimatch](https://github.com/isaacs/minimatch) documentation to cross-check expected behavior in node.js
* if all else fails, since there is no real specification for globs we will probably need to discuss expected behavior and decide how to resolve it. which means any detail you can provide to help with this discussion would be greatly appreciated.

**Platform issues**

It's important to us that micromatch work consistently on all platforms. If you encounter any platform-specific matching or path related issues, please let us know (pull requests are also greatly appreciated).

## About

Contributing

Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).

Please read the [contributing guide](.github/contributing.md) for advice on opening issues, pull requests, and coding standards.

Running Tests

Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:

```sh
$ npm install && npm test
```

Building docs

_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_

To generate the readme, run the following command:

```sh
$ npm install -g verbose/verb#dev verb-generate-readme && verb
```

### Related projects

You might also be interested in these projects:

* [braces](https://www.npmjs.com/package/braces): Bash-like brace expansion, implemented in JavaScript. Safer than other brace expansion libs, with complete support… [more](https://github.com/micromatch/braces) | [homepage](https://github.com/micromatch/braces "Bash-like brace expansion, implemented in JavaScript. Safer than other brace expansion libs, with complete support for the Bash 4.3 braces specification, without sacrificing speed.")
* [expand-brackets](https://www.npmjs.com/package/expand-brackets): Expand POSIX bracket expressions (character classes) in glob patterns. | [homepage](https://github.com/micromatch/expand-brackets "Expand POSIX bracket expressions (character classes) in glob patterns.")
* [extglob](https://www.npmjs.com/package/extglob): Extended glob support for JavaScript. Adds (almost) the expressive power of regular expressions to glob… [more](https://github.com/micromatch/extglob) | [homepage](https://github.com/micromatch/extglob "Extended glob support for JavaScript. Adds (almost) the expressive power of regular expressions to glob patterns.")
* [fill-range](https://www.npmjs.com/package/fill-range): Fill in a range of numbers or letters, optionally passing an increment or `step` to… [more](https://github.com/jonschlinkert/fill-range) | [homepage](https://github.com/jonschlinkert/fill-range "Fill in a range of numbers or letters, optionally passing an increment or `step` to use, or create a regex-compatible range with `options.toRegex`")
* [nanomatch](https://www.npmjs.com/package/nanomatch): Fast, minimal glob matcher for node.js. Similar to micromatch, minimatch and multimatch, but complete Bash… [more](https://github.com/micromatch/nanomatch) | [homepage](https://github.com/micromatch/nanomatch "Fast, minimal glob matcher for node.js. Similar to micromatch, minimatch and multimatch, but complete Bash 4.3 wildcard support only (no support for exglobs, posix brackets or braces)")

### Contributors

| **Commits** | **Contributor** |
| --- | --- |
| 523 | [jonschlinkert](https://github.com/jonschlinkert) |
| 12  | [es128](https://github.com/es128) |
| 9   | [danez](https://github.com/danez) |
| 8   | [doowb](https://github.com/doowb) |
| 6   | [paulmillr](https://github.com/paulmillr) |
| 5   | [mrmlnc](https://github.com/mrmlnc) |
| 3   | [DrPizza](https://github.com/DrPizza) |
| 2   | [Tvrqvoise](https://github.com/Tvrqvoise) |
| 2   | [antonyk](https://github.com/antonyk) |
| 2   | [MartinKolarik](https://github.com/MartinKolarik) |
| 2   | [Glazy](https://github.com/Glazy) |
| 2   | [mceIdo](https://github.com/mceIdo) |
| 2   | [TrySound](https://github.com/TrySound) |
| 1   | [yvele](https://github.com/yvele) |
| 1   | [wtgtybhertgeghgtwtg](https://github.com/wtgtybhertgeghgtwtg) |
| 1   | [simlu](https://github.com/simlu) |
| 1   | [curbengh](https://github.com/curbengh) |
| 1   | [fidian](https://github.com/fidian) |
| 1   | [tomByrer](https://github.com/tomByrer) |
| 1   | [ZoomerTedJackson](https://github.com/ZoomerTedJackson) |
| 1   | [styfle](https://github.com/styfle) |
| 1   | [sebdeckers](https://github.com/sebdeckers) |
| 1   | [muescha](https://github.com/muescha) |
| 1   | [juszczykjakub](https://github.com/juszczykjakub) |
| 1   | [joyceerhl](https://github.com/joyceerhl) |
| 1   | [donatj](https://github.com/donatj) |
| 1   | [frangio](https://github.com/frangio) |
| 1   | [UltCombo](https://github.com/UltCombo) |
| 1   | [DianeLooney](https://github.com/DianeLooney) |
| 1   | [devongovett](https://github.com/devongovett) |
| 1   | [Cslove](https://github.com/Cslove) |
| 1   | [amilajack](https://github.com/amilajack) |

### Author

**Jon Schlinkert**

* [GitHub Profile](https://github.com/jonschlinkert)
* [Twitter Profile](https://twitter.com/jonschlinkert)
* [LinkedIn Profile](https://linkedin.com/in/jonschlinkert)

### License

Copyright © 2024, [Jon Schlinkert](https://github.com/jonschlinkert).
Released under the [MIT License](LICENSE).

***

_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.8.0, on August 23, 2024._