[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\nindent_style = tab\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n[{package.json,.*rc,*.yml}]\nindent_style = space\nindent_size = 2\ninsert_final_newline = false\n\n[*.md]\ntrim_trailing_whitespace = false\nindent_style = space\nindent_size = 2\n"
  },
  {
    "path": ".eslintrc",
    "content": "{\n  \"ignorePatterns\": [\n    \"node_modules\",\n    \"dist\",\n    \"index.d.ts\"\n  ],\n  \"extends\": [\n    \"plugin:@typescript-eslint/eslint-recommended\",\n    \"plugin:@typescript-eslint/recommended\",\n    \"developit\"\n  ],\n  \"parser\": \"@typescript-eslint/parser\",\n  \"parserOptions\": {\n    \"sourceType\": \"module\"\n  },\n  \"env\": {\n    \"browser\": true,\n    \"mocha\": true,\n    \"jest\": false,\n    \"es6\": true\n  },\n  \"globals\": {\n    \"expect\": true\n  },\n  \"rules\": {\n    \"semi\": [\n      2,\n      \"always\"\n    ],\n    \"brace-style\": [\n      2,\n      \"1tbs\"\n    ],\n    \"quotes\": [\n      2,\n      \"single\"\n    ],\n    \"lines-around-comment\": [\n      2,\n      {\n        \"allowBlockStart\": true,\n        \"allowObjectStart\": true\n      }\n    ],\n    \"jest/valid-expect\": 0,\n    \"@typescript-eslint/no-explicit-any\": 0,\n    \"@typescript-eslint/explicit-function-return-type\": 0,\n    \"@typescript-eslint/explicit-module-boundary-types\": 0,\n    \"@typescript-eslint/no-empty-function\": 0,\n    \"@typescript-eslint/no-non-null-assertion\": 0\n  }\n}\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "<!--\n    Thank you for contributing!\n-->\n\n#### What is the purpose of this pull request? (put an \"X\" next to an item)\n\n- [ ] Documentation update\n- [ ] Bug fix\n- [ ] Feature\n- [ ] Code style update (formatting)\n- [ ] Refactoring (no functional changes)\n- [ ] CI related changes\n- [ ] Other, please explain:\n\n#### What changes did you make? (Give an overview)\n\n#### Is there anything you'd like reviewers to focus on?\n\n#### Does this PR introduce a breaking change? (What changes might other developers need to make in their application due to this PR?)"
  },
  {
    "path": ".github/workflows/compressed-size.yml",
    "content": "name: Compressed Size\n\non: [pull_request]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v2\n      - uses: preactjs/compressed-size-action@v2\n        with:\n          pattern: \"./dist/*.{js,mjs,cjs}\"\n"
  },
  {
    "path": ".github/workflows/main.yml",
    "content": "name: CI\n\non:\n  pull_request:\n    branches:\n      - \"**\"\n  push:\n    branches:\n      - main\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v2\n      - uses: actions/setup-node@v2\n        with:\n          node-version: 14\n      - name: npm install, build, and test\n        run: |\n          npm install\n          npm run build --if-present\n          npm test\n        env:\n          CI: true\n"
  },
  {
    "path": ".gitignore",
    "content": "/dist\n/test-reports\n/node_modules\n/npm-debug.log\n/index.d.ts\npackage-lock.json\n.DS_Store\n.idea\n.vscode\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2021 Jason Miller\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "<p align=\"center\">\n  <img src=\"https://i.imgur.com/BqsX9NT.png\" width=\"300\" height=\"300\" alt=\"mitt\">\n  <br>\n  <a href=\"https://www.npmjs.org/package/mitt\"><img src=\"https://img.shields.io/npm/v/mitt.svg\" alt=\"npm\"></a>\n  <img src=\"https://github.com/developit/mitt/workflows/CI/badge.svg\" alt=\"build status\">\n  <a href=\"https://unpkg.com/mitt/dist/mitt.js\"><img src=\"https://img.badgesize.io/https://unpkg.com/mitt/dist/mitt.js?compression=gzip\" alt=\"gzip size\"></a>\n</p>\n\n# Mitt\n\n> Tiny 200b functional event emitter / pubsub.\n\n-   **Microscopic:** weighs less than 200 bytes gzipped\n-   **Useful:** a wildcard `\"*\"` event type listens to all events\n-   **Familiar:** same names & ideas as [Node's EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter)\n-   **Functional:** methods don't rely on `this`\n-   **Great Name:** somehow [mitt](https://npm.im/mitt) wasn't taken\n\nMitt was made for the browser, but works in any JavaScript runtime. It has no dependencies and supports IE9+.\n\n## Table of Contents\n\n-   [Install](#install)\n-   [Usage](#usage)\n-   [Examples & Demos](#examples--demos)\n-   [API](#api)\n-   [Contribute](#contribute)\n-   [License](#license)\n\n## Install\n\nThis project uses [node](http://nodejs.org) and [npm](https://npmjs.com). Go check them out if you don't have them locally installed.\n\n```sh\n$ npm install --save mitt\n```\n\nThen with a module bundler like [rollup](http://rollupjs.org/) or [webpack](https://webpack.js.org/), use as you would anything else:\n\n```javascript\n// using ES6 modules\nimport mitt from 'mitt'\n\n// using CommonJS modules\nvar mitt = require('mitt')\n```\n\nThe [UMD](https://github.com/umdjs/umd) build is also available on [unpkg](https://unpkg.com):\n\n```html\n<script src=\"https://unpkg.com/mitt/dist/mitt.umd.js\"></script>\n```\n\nYou can find the library on `window.mitt`.\n\n## Usage\n\n```js\nimport mitt from 'mitt'\n\nconst emitter = mitt()\n\n// listen to an event\nemitter.on('foo', e => console.log('foo', e) )\n\n// listen to all events\nemitter.on('*', (type, e) => console.log(type, e) )\n\n// fire an event\nemitter.emit('foo', { a: 'b' })\n\n// clearing all events\nemitter.all.clear()\n\n// working with handler references:\nfunction onFoo() {}\nemitter.on('foo', onFoo)   // listen\nemitter.off('foo', onFoo)  // unlisten\n```\n\n### Typescript\n\nSet `\"strict\": true` in your tsconfig.json to get improved type inference for `mitt` instance methods.\n\n```ts\nimport mitt from 'mitt';\n\ntype Events = {\n  foo: string;\n  bar?: number;\n};\n\nconst emitter = mitt<Events>(); // inferred as Emitter<Events>\n\nemitter.on('foo', (e) => {}); // 'e' has inferred type 'string'\n\nemitter.emit('foo', 42); // Error: Argument of type 'number' is not assignable to parameter of type 'string'. (2345)\n```\n\nAlternatively, you can use the provided `Emitter` type:\n\n```ts\nimport mitt, { Emitter } from 'mitt';\n\ntype Events = {\n  foo: string;\n  bar?: number;\n};\n\nconst emitter: Emitter<Events> = mitt<Events>();\n```\n\n## Examples & Demos\n\n<a href=\"http://codepen.io/developit/pen/rjMEwW?editors=0110\">\n  <b>Preact + Mitt Codepen Demo</b>\n  <br>\n  <img src=\"https://i.imgur.com/CjBgOfJ.png\" width=\"278\" alt=\"preact + mitt preview\">\n</a>\n\n* * *\n\n## API\n\n<!-- Generated by documentation.js. Update this documentation by updating the source code. -->\n\n#### Table of Contents\n\n-   [mitt](#mitt)\n-   [all](#all)\n-   [on](#on)\n    -   [Parameters](#parameters)\n-   [off](#off)\n    -   [Parameters](#parameters-1)\n-   [emit](#emit)\n    -   [Parameters](#parameters-2)\n\n### mitt\n\nMitt: Tiny (~200b) functional event emitter / pubsub.\n\nReturns **Mitt** \n\n### all\n\nA Map of event names to registered handler functions.\n\n### on\n\nRegister an event handler for the given type.\n\n#### Parameters\n\n-   `type` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) \\| [symbol](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Symbol))** Type of event to listen for, or `'*'` for all events\n-   `handler` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** Function to call in response to given event\n\n### off\n\nRemove an event handler for the given type.\nIf `handler` is omitted, all handlers of the given type are removed.\n\n#### Parameters\n\n-   `type` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) \\| [symbol](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Symbol))** Type of event to unregister `handler` from, or `'*'`\n-   `handler` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)?** Handler function to remove\n\n### emit\n\nInvoke all handlers for the given type.\nIf present, `'*'` handlers are invoked after type-matched handlers.\n\nNote: Manually firing '\\*' handlers is not supported.\n\n#### Parameters\n\n-   `type` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) \\| [symbol](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Symbol))** The event type to invoke\n-   `evt` **Any?** Any value (object is recommended and powerful), passed to each handler\n\n## Contribute\n\nFirst off, thanks for taking the time to contribute!\nNow, take a moment to be sure your contributions make sense to everyone else.\n\n### Reporting Issues\n\nFound a problem? Want a new feature? First of all see if your issue or idea has [already been reported](../../issues).\nIf don't, just open a [new clear and descriptive issue](../../issues/new).\n\n### Submitting pull requests\n\nPull requests are the greatest contributions, so be sure they are focused in scope, and do avoid unrelated commits.\n\n-   Fork it!\n-   Clone your fork: `git clone https://github.com/<your-username>/mitt`\n-   Navigate to the newly cloned directory: `cd mitt`\n-   Create a new branch for the new feature: `git checkout -b my-new-feature`\n-   Install the tools necessary for development: `npm install`\n-   Make your changes.\n-   Commit your changes: `git commit -am 'Add some feature'`\n-   Push to the branch: `git push origin my-new-feature`\n-   Submit a pull request with full remarks documenting your changes.\n\n## License\n\n[MIT License](https://opensource.org/licenses/MIT) © [Jason Miller](https://jasonformat.com/)\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"mitt\",\n  \"version\": \"3.0.1\",\n  \"description\": \"Tiny 200b functional Event Emitter / pubsub.\",\n  \"module\": \"dist/mitt.mjs\",\n  \"main\": \"dist/mitt.js\",\n  \"jsnext:main\": \"dist/mitt.mjs\",\n  \"umd:main\": \"dist/mitt.umd.js\",\n  \"source\": \"src/index.ts\",\n  \"typings\": \"index.d.ts\",\n  \"exports\": {\n    \"types\": \"./index.d.ts\",\n    \"module\": \"./dist/mitt.mjs\",\n    \"import\": \"./dist/mitt.mjs\",\n    \"require\": \"./dist/mitt.js\",\n    \"default\": \"./dist/mitt.mjs\"\n  },\n  \"scripts\": {\n    \"test\": \"npm-run-all --silent typecheck lint mocha test-types\",\n    \"mocha\": \"mocha test\",\n    \"test-types\": \"tsc test/test-types-compilation.ts --noEmit --strict\",\n    \"lint\": \"eslint src test --ext ts --ext js\",\n    \"typecheck\": \"tsc --noEmit\",\n    \"bundle\": \"microbundle -f es,cjs,umd\",\n    \"build\": \"npm-run-all --silent clean -p bundle -s docs\",\n    \"clean\": \"rimraf dist\",\n    \"docs\": \"documentation readme src/index.ts --section API -q --parse-extension ts\",\n    \"release\": \"npm run -s build -s && npm t && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish\"\n  },\n  \"repository\": \"developit/mitt\",\n  \"keywords\": [\n    \"events\",\n    \"eventemitter\",\n    \"emitter\",\n    \"pubsub\"\n  ],\n  \"homepage\": \"https://github.com/developit/mitt\",\n  \"authors\": [\n    \"Jason Miller <jason@developit.ca>\"\n  ],\n  \"license\": \"MIT\",\n  \"files\": [\n    \"dist\",\n    \"index.d.ts\"\n  ],\n  \"mocha\": {\n    \"extension\": [\n      \"ts\"\n    ],\n    \"require\": [\n      \"ts-node/register\",\n      \"esm\"\n    ],\n    \"spec\": [\n      \"test/*_test.ts\"\n    ]\n  },\n  \"prettier\": {\n    \"singleQuote\": true,\n    \"trailingComma\": \"none\"\n  },\n  \"devDependencies\": {\n    \"@types/chai\": \"^4.2.11\",\n    \"@types/mocha\": \"^7.0.2\",\n    \"@types/sinon\": \"^9.0.4\",\n    \"@types/sinon-chai\": \"^3.2.4\",\n    \"@typescript-eslint/eslint-plugin\": \"^5.61.0\",\n    \"@typescript-eslint/parser\": \"^5.61.0\",\n    \"chai\": \"^4.2.0\",\n    \"documentation\": \"^14.0.2\",\n    \"eslint\": \"^7.32.0\",\n    \"eslint-config-developit\": \"^1.2.0\",\n    \"eslint-plugin-compat\": \"^4.1.4\",\n    \"esm\": \"^3.2.25\",\n    \"microbundle\": \"^0.12.3\",\n    \"mocha\": \"^8.0.1\",\n    \"npm-run-all\": \"^4.1.5\",\n    \"prettier\": \"^2.8.8\",\n    \"rimraf\": \"^3.0.2\",\n    \"sinon\": \"^9.0.2\",\n    \"sinon-chai\": \"^3.5.0\",\n    \"ts-node\": \"^10.9.1\",\n    \"typescript\": \"^4.9.5\"\n  }\n}\n"
  },
  {
    "path": "src/index.ts",
    "content": "export type EventType = string | symbol;\n\n// An event handler can take an optional event argument\n// and should not return a value\nexport type Handler<T = unknown> = (event: T) => void;\nexport type WildcardHandler<T = Record<string, unknown>> = (\n\ttype: keyof T,\n\tevent: T[keyof T]\n) => void;\n\n// An array of all currently registered event handlers for a type\nexport type EventHandlerList<T = unknown> = Array<Handler<T>>;\nexport type WildCardEventHandlerList<T = Record<string, unknown>> = Array<\n\tWildcardHandler<T>\n>;\n\n// A map of event types and their corresponding event handlers.\nexport type EventHandlerMap<Events extends Record<EventType, unknown>> = Map<\n\tkeyof Events | '*',\n\tEventHandlerList<Events[keyof Events]> | WildCardEventHandlerList<Events>\n>;\n\nexport interface Emitter<Events extends Record<EventType, unknown>> {\n\tall: EventHandlerMap<Events>;\n\n\ton<Key extends keyof Events>(type: Key, handler: Handler<Events[Key]>): void;\n\ton(type: '*', handler: WildcardHandler<Events>): void;\n\n\toff<Key extends keyof Events>(\n\t\ttype: Key,\n\t\thandler?: Handler<Events[Key]>\n\t): void;\n\toff(type: '*', handler: WildcardHandler<Events>): void;\n\n\temit<Key extends keyof Events>(type: Key, event: Events[Key]): void;\n\temit<Key extends keyof Events>(\n\t\ttype: undefined extends Events[Key] ? Key : never\n\t): void;\n}\n\n/**\n * Mitt: Tiny (~200b) functional event emitter / pubsub.\n * @name mitt\n * @returns {Mitt}\n */\nexport default function mitt<Events extends Record<EventType, unknown>>(\n\tall?: EventHandlerMap<Events>\n): Emitter<Events> {\n\ttype GenericEventHandler =\n\t\t| Handler<Events[keyof Events]>\n\t\t| WildcardHandler<Events>;\n\tall = all || new Map();\n\n\treturn {\n\t\t/**\n\t\t * A Map of event names to registered handler functions.\n\t\t */\n\t\tall,\n\n\t\t/**\n\t\t * Register an event handler for the given type.\n\t\t * @param {string|symbol} type Type of event to listen for, or `'*'` for all events\n\t\t * @param {Function} handler Function to call in response to given event\n\t\t * @memberOf mitt\n\t\t */\n\t\ton<Key extends keyof Events>(type: Key, handler: GenericEventHandler) {\n\t\t\tconst handlers: Array<GenericEventHandler> | undefined = all!.get(type);\n\t\t\tif (handlers) {\n\t\t\t\thandlers.push(handler);\n\t\t\t} else {\n\t\t\t\tall!.set(type, [handler] as EventHandlerList<Events[keyof Events]>);\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Remove an event handler for the given type.\n\t\t * If `handler` is omitted, all handlers of the given type are removed.\n\t\t * @param {string|symbol} type Type of event to unregister `handler` from (`'*'` to remove a wildcard handler)\n\t\t * @param {Function} [handler] Handler function to remove\n\t\t * @memberOf mitt\n\t\t */\n\t\toff<Key extends keyof Events>(type: Key, handler?: GenericEventHandler) {\n\t\t\tconst handlers: Array<GenericEventHandler> | undefined = all!.get(type);\n\t\t\tif (handlers) {\n\t\t\t\tif (handler) {\n\t\t\t\t\thandlers.splice(handlers.indexOf(handler) >>> 0, 1);\n\t\t\t\t} else {\n\t\t\t\t\tall!.set(type, []);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Invoke all handlers for the given type.\n\t\t * If present, `'*'` handlers are invoked after type-matched handlers.\n\t\t *\n\t\t * Note: Manually firing '*' handlers is not supported.\n\t\t *\n\t\t * @param {string|symbol} type The event type to invoke\n\t\t * @param {Any} [evt] Any value (object is recommended and powerful), passed to each handler\n\t\t * @memberOf mitt\n\t\t */\n\t\temit<Key extends keyof Events>(type: Key, evt?: Events[Key]) {\n\t\t\tlet handlers = all!.get(type);\n\t\t\tif (handlers) {\n\t\t\t\t(handlers as EventHandlerList<Events[keyof Events]>)\n\t\t\t\t\t.slice()\n\t\t\t\t\t.map((handler) => {\n\t\t\t\t\t\thandler(evt!);\n\t\t\t\t\t});\n\t\t\t}\n\n\t\t\thandlers = all!.get('*');\n\t\t\tif (handlers) {\n\t\t\t\t(handlers as WildCardEventHandlerList<Events>)\n\t\t\t\t\t.slice()\n\t\t\t\t\t.map((handler) => {\n\t\t\t\t\t\thandler(type, evt!);\n\t\t\t\t\t});\n\t\t\t}\n\t\t}\n\t};\n}\n"
  },
  {
    "path": "test/index_test.ts",
    "content": "import mitt, { Emitter, EventHandlerMap } from '..';\nimport chai, { expect } from 'chai';\nimport { spy } from 'sinon';\nimport sinonChai from 'sinon-chai';\nchai.use(sinonChai);\n\ndescribe('mitt', () => {\n\tit('should default export be a function', () => {\n\t\texpect(mitt).to.be.a('function');\n\t});\n\n\tit('should accept an optional event handler map', () => {\n\t\texpect(() => mitt(new Map())).not.to.throw;\n\t\tconst map = new Map();\n\t\tconst a = spy();\n\t\tconst b = spy();\n\t\tmap.set('foo', [a, b]);\n\t\tconst events = mitt<{ foo: undefined }>(map);\n\t\tevents.emit('foo');\n\t\texpect(a).to.have.been.calledOnce;\n\t\texpect(b).to.have.been.calledOnce;\n\t});\n});\n\ndescribe('mitt#', () => {\n\tconst eventType = Symbol('eventType');\n\ttype Events = {\n\t\tfoo: unknown;\n\t\tconstructor: unknown;\n\t\tFOO: unknown;\n\t\tbar: unknown;\n\t\tBar: unknown;\n\t\t'baz:bat!': unknown;\n\t\t'baz:baT!': unknown;\n\t\tFoo: unknown;\n\t\t[eventType]: unknown;\n\t};\n\tlet events: EventHandlerMap<Events>, inst: Emitter<Events>;\n\n\tbeforeEach(() => {\n\t\tevents = new Map();\n\t\tinst = mitt(events);\n\t});\n\n\tdescribe('properties', () => {\n\t\tit('should expose the event handler map', () => {\n\t\t\texpect(inst).to.have.property('all').that.is.a('map');\n\t\t});\n\t});\n\n\tdescribe('on()', () => {\n\t\tit('should be a function', () => {\n\t\t\texpect(inst).to.have.property('on').that.is.a('function');\n\t\t});\n\n\t\tit('should register handler for new type', () => {\n\t\t\tconst foo = () => {};\n\t\t\tinst.on('foo', foo);\n\n\t\t\texpect(events.get('foo')).to.deep.equal([foo]);\n\t\t});\n\n\t\tit('should register handlers for any type strings', () => {\n\t\t\tconst foo = () => {};\n\t\t\tinst.on('constructor', foo);\n\n\t\t\texpect(events.get('constructor')).to.deep.equal([foo]);\n\t\t});\n\n\t\tit('should append handler for existing type', () => {\n\t\t\tconst foo = () => {};\n\t\t\tconst bar = () => {};\n\t\t\tinst.on('foo', foo);\n\t\t\tinst.on('foo', bar);\n\n\t\t\texpect(events.get('foo')).to.deep.equal([foo, bar]);\n\t\t});\n\n\t\tit('should NOT normalize case', () => {\n\t\t\tconst foo = () => {};\n\t\t\tinst.on('FOO', foo);\n\t\t\tinst.on('Bar', foo);\n\t\t\tinst.on('baz:baT!', foo);\n\n\t\t\texpect(events.get('FOO')).to.deep.equal([foo]);\n\t\t\texpect(events.has('foo')).to.equal(false);\n\t\t\texpect(events.get('Bar')).to.deep.equal([foo]);\n\t\t\texpect(events.has('bar')).to.equal(false);\n\t\t\texpect(events.get('baz:baT!')).to.deep.equal([foo]);\n\t\t});\n\n\t\tit('can take symbols for event types', () => {\n\t\t\tconst foo = () => {};\n\t\t\tinst.on(eventType, foo);\n\t\t\texpect(events.get(eventType)).to.deep.equal([foo]);\n\t\t});\n\n\t\t// Adding the same listener multiple times should register it multiple times.\n\t\t// See https://nodejs.org/api/events.html#events_emitter_on_eventname_listener\n\t\tit('should add duplicate listeners', () => {\n\t\t\tconst foo = () => {};\n\t\t\tinst.on('foo', foo);\n\t\t\tinst.on('foo', foo);\n\t\t\texpect(events.get('foo')).to.deep.equal([foo, foo]);\n\t\t});\n\t});\n\n\tdescribe('off()', () => {\n\t\tit('should be a function', () => {\n\t\t\texpect(inst).to.have.property('off').that.is.a('function');\n\t\t});\n\n\t\tit('should remove handler for type', () => {\n\t\t\tconst foo = () => {};\n\t\t\tinst.on('foo', foo);\n\t\t\tinst.off('foo', foo);\n\n\t\t\texpect(events.get('foo')).to.be.empty;\n\t\t});\n\n\t\tit('should NOT normalize case', () => {\n\t\t\tconst foo = () => {};\n\t\t\tinst.on('FOO', foo);\n\t\t\tinst.on('Bar', foo);\n\t\t\tinst.on('baz:bat!', foo);\n\n\t\t\tinst.off('FOO', foo);\n\t\t\tinst.off('Bar', foo);\n\t\t\tinst.off('baz:baT!', foo);\n\n\t\t\texpect(events.get('FOO')).to.be.empty;\n\t\t\texpect(events.has('foo')).to.equal(false);\n\t\t\texpect(events.get('Bar')).to.be.empty;\n\t\t\texpect(events.has('bar')).to.equal(false);\n\t\t\texpect(events.get('baz:bat!')).to.have.lengthOf(1);\n\t\t});\n\n\t\tit('should remove only the first matching listener', () => {\n\t\t\tconst foo = () => {};\n\t\t\tinst.on('foo', foo);\n\t\t\tinst.on('foo', foo);\n\t\t\tinst.off('foo', foo);\n\t\t\texpect(events.get('foo')).to.deep.equal([foo]);\n\t\t\tinst.off('foo', foo);\n\t\t\texpect(events.get('foo')).to.deep.equal([]);\n\t\t});\n\n\t\tit('off(\"type\") should remove all handlers of the given type', () => {\n\t\t\tinst.on('foo', () => {});\n\t\t\tinst.on('foo', () => {});\n\t\t\tinst.on('bar', () => {});\n\t\t\tinst.off('foo');\n\t\t\texpect(events.get('foo')).to.deep.equal([]);\n\t\t\texpect(events.get('bar')).to.have.length(1);\n\t\t\tinst.off('bar');\n\t\t\texpect(events.get('bar')).to.deep.equal([]);\n\t\t});\n\t});\n\n\tdescribe('emit()', () => {\n\t\tit('should be a function', () => {\n\t\t\texpect(inst).to.have.property('emit').that.is.a('function');\n\t\t});\n\n\t\tit('should invoke handler for type', () => {\n\t\t\tconst event = { a: 'b' };\n\n\t\t\tinst.on('foo', (one, two?: unknown) => {\n\t\t\t\texpect(one).to.deep.equal(event);\n\t\t\t\texpect(two).to.be.an('undefined');\n\t\t\t});\n\n\t\t\tinst.emit('foo', event);\n\t\t});\n\n\t\tit('should NOT ignore case', () => {\n\t\t\tconst onFoo = spy(),\n\t\t\t\tonFOO = spy();\n\t\t\tevents.set('Foo', [onFoo]);\n\t\t\tevents.set('FOO', [onFOO]);\n\n\t\t\tinst.emit('Foo', 'Foo arg');\n\t\t\tinst.emit('FOO', 'FOO arg');\n\n\t\t\texpect(onFoo).to.have.been.calledOnce.and.calledWith('Foo arg');\n\t\t\texpect(onFOO).to.have.been.calledOnce.and.calledWith('FOO arg');\n\t\t});\n\n\t\tit('should invoke * handlers', () => {\n\t\t\tconst star = spy(),\n\t\t\t\tea = { a: 'a' },\n\t\t\t\teb = { b: 'b' };\n\n\t\t\tevents.set('*', [star]);\n\n\t\t\tinst.emit('foo', ea);\n\t\t\texpect(star).to.have.been.calledOnce.and.calledWith('foo', ea);\n\t\t\tstar.resetHistory();\n\n\t\t\tinst.emit('bar', eb);\n\t\t\texpect(star).to.have.been.calledOnce.and.calledWith('bar', eb);\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/test-types-compilation.ts",
    "content": "/* eslint-disable @typescript-eslint/ban-ts-comment, @typescript-eslint/no-unused-vars */\n\nimport mitt from '..';\n\ninterface SomeEventData {\n\tname: string;\n}\n\nconst emitter = mitt<{\n\tfoo: string;\n\tsomeEvent: SomeEventData;\n\tbar?: number;\n}>();\n\nconst barHandler = (x?: number) => {};\nconst fooHandler = (x: string) => {};\nconst wildcardHandler = (\n\t_type: 'foo' | 'bar' | 'someEvent',\n\t_event: string | SomeEventData | number | undefined\n) => {};\n\n/*\n * Check that 'on' args are inferred correctly\n */\n{\n\t// @ts-expect-error\n\temitter.on('foo', barHandler);\n\temitter.on('foo', fooHandler);\n\n\temitter.on('bar', barHandler);\n\t// @ts-expect-error\n\temitter.on('bar', fooHandler);\n\n\temitter.on('*', wildcardHandler);\n\t// fooHandler is ok, because ('foo' | 'bar' | 'someEvent') extends string\n\temitter.on('*', fooHandler);\n\t// @ts-expect-error\n\temitter.on('*', barHandler);\n}\n\n/*\n * Check that 'off' args are inferred correctly\n */\n{\n\t// @ts-expect-error\n\temitter.off('foo', barHandler);\n\temitter.off('foo', fooHandler);\n\n\temitter.off('bar', barHandler);\n\t// @ts-expect-error\n\temitter.off('bar', fooHandler);\n\n\temitter.off('*', wildcardHandler);\n\t// fooHandler is ok, because ('foo' | 'bar' | 'someEvent') extends string\n\temitter.off('*', fooHandler);\n\t// @ts-expect-error\n\temitter.off('*', barHandler);\n}\n\n/*\n * Check that 'emit' args are inferred correctly\n */\n{\n\t// @ts-expect-error\n\temitter.emit('someEvent', 'NOT VALID');\n\temitter.emit('someEvent', { name: 'jack' });\n\n\t// @ts-expect-error\n\temitter.emit('foo');\n\t// @ts-expect-error\n\temitter.emit('foo', 1);\n\temitter.emit('foo', 'string');\n\n\temitter.emit('bar');\n\temitter.emit('bar', 1);\n\t// @ts-expect-error\n\temitter.emit('bar', 'string');\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n\t\"compileOnSave\": false,\n\t\"compilerOptions\": {\n\t\t\"strict\": true,\n\t\t\"noEmit\": true,\n\t\t\"declaration\": true,\n\t\t\"moduleResolution\": \"node\",\n\t\t\"skipLibCheck\": true,\n\t\t\"esModuleInterop\": true,\n\t},\n\t\"include\": [\n\t\t\"src/*.ts\",\n\t\t\"test/*.ts\"\n\t]\n}\n"
  }
]