오수한

Discord.js add

Showing 346 changed files with 4565 additions and 0 deletions
1 +{
2 + "name": "discord_chatbot",
3 + "lockfileVersion": 2,
4 + "requires": true,
5 + "packages": {
6 + "node_modules/@discordjs/collection": {
7 + "version": "0.1.6",
8 + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz",
9 + "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ=="
10 + },
11 + "node_modules/@discordjs/form-data": {
12 + "version": "3.0.1",
13 + "resolved": "https://registry.npmjs.org/@discordjs/form-data/-/form-data-3.0.1.tgz",
14 + "integrity": "sha512-ZfFsbgEXW71Rw/6EtBdrP5VxBJy4dthyC0tpQKGKmYFImlmmrykO14Za+BiIVduwjte0jXEBlhSKf0MWbFp9Eg==",
15 + "dependencies": {
16 + "asynckit": "^0.4.0",
17 + "combined-stream": "^1.0.8",
18 + "mime-types": "^2.1.12"
19 + },
20 + "engines": {
21 + "node": ">= 6"
22 + }
23 + },
24 + "node_modules/abort-controller": {
25 + "version": "3.0.0",
26 + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
27 + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
28 + "dependencies": {
29 + "event-target-shim": "^5.0.0"
30 + },
31 + "engines": {
32 + "node": ">=6.5"
33 + }
34 + },
35 + "node_modules/asynckit": {
36 + "version": "0.4.0",
37 + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
38 + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
39 + },
40 + "node_modules/combined-stream": {
41 + "version": "1.0.8",
42 + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
43 + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
44 + "dependencies": {
45 + "delayed-stream": "~1.0.0"
46 + },
47 + "engines": {
48 + "node": ">= 0.8"
49 + }
50 + },
51 + "node_modules/delayed-stream": {
52 + "version": "1.0.0",
53 + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
54 + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
55 + "engines": {
56 + "node": ">=0.4.0"
57 + }
58 + },
59 + "node_modules/discord.js": {
60 + "version": "12.5.3",
61 + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-12.5.3.tgz",
62 + "integrity": "sha512-D3nkOa/pCkNyn6jLZnAiJApw2N9XrIsXUAdThf01i7yrEuqUmDGc7/CexVWwEcgbQR97XQ+mcnqJpmJ/92B4Aw==",
63 + "deprecated": "no longer supported",
64 + "dependencies": {
65 + "@discordjs/collection": "^0.1.6",
66 + "@discordjs/form-data": "^3.0.1",
67 + "abort-controller": "^3.0.0",
68 + "node-fetch": "^2.6.1",
69 + "prism-media": "^1.2.9",
70 + "setimmediate": "^1.0.5",
71 + "tweetnacl": "^1.0.3",
72 + "ws": "^7.4.4"
73 + },
74 + "engines": {
75 + "node": ">=12.0.0"
76 + }
77 + },
78 + "node_modules/event-target-shim": {
79 + "version": "5.0.1",
80 + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
81 + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
82 + "engines": {
83 + "node": ">=6"
84 + }
85 + },
86 + "node_modules/mime-db": {
87 + "version": "1.52.0",
88 + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
89 + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
90 + "engines": {
91 + "node": ">= 0.6"
92 + }
93 + },
94 + "node_modules/mime-types": {
95 + "version": "2.1.35",
96 + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
97 + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
98 + "dependencies": {
99 + "mime-db": "1.52.0"
100 + },
101 + "engines": {
102 + "node": ">= 0.6"
103 + }
104 + },
105 + "node_modules/node-fetch": {
106 + "version": "2.6.7",
107 + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
108 + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
109 + "dependencies": {
110 + "whatwg-url": "^5.0.0"
111 + },
112 + "engines": {
113 + "node": "4.x || >=6.0.0"
114 + },
115 + "peerDependencies": {
116 + "encoding": "^0.1.0"
117 + },
118 + "peerDependenciesMeta": {
119 + "encoding": {
120 + "optional": true
121 + }
122 + }
123 + },
124 + "node_modules/prism-media": {
125 + "version": "1.3.2",
126 + "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.3.2.tgz",
127 + "integrity": "sha512-L6UsGHcT6i4wrQhFF1aPK+MNYgjRqR2tUoIqEY+CG1NqVkMjPRKzS37j9f8GiYPlD6wG9ruBj+q5Ax+bH8Ik1g==",
128 + "peerDependencies": {
129 + "@discordjs/opus": "^0.5.0",
130 + "ffmpeg-static": "^4.2.7 || ^3.0.0 || ^2.4.0",
131 + "node-opus": "^0.3.3",
132 + "opusscript": "^0.0.8"
133 + },
134 + "peerDependenciesMeta": {
135 + "@discordjs/opus": {
136 + "optional": true
137 + },
138 + "ffmpeg-static": {
139 + "optional": true
140 + },
141 + "node-opus": {
142 + "optional": true
143 + },
144 + "opusscript": {
145 + "optional": true
146 + }
147 + }
148 + },
149 + "node_modules/setimmediate": {
150 + "version": "1.0.5",
151 + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
152 + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
153 + },
154 + "node_modules/tr46": {
155 + "version": "0.0.3",
156 + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
157 + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
158 + },
159 + "node_modules/tweetnacl": {
160 + "version": "1.0.3",
161 + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz",
162 + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw=="
163 + },
164 + "node_modules/webidl-conversions": {
165 + "version": "3.0.1",
166 + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
167 + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
168 + },
169 + "node_modules/whatwg-url": {
170 + "version": "5.0.0",
171 + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
172 + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
173 + "dependencies": {
174 + "tr46": "~0.0.3",
175 + "webidl-conversions": "^3.0.0"
176 + }
177 + },
178 + "node_modules/ws": {
179 + "version": "7.5.7",
180 + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz",
181 + "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==",
182 + "engines": {
183 + "node": ">=8.3.0"
184 + },
185 + "peerDependencies": {
186 + "bufferutil": "^4.0.1",
187 + "utf-8-validate": "^5.0.2"
188 + },
189 + "peerDependenciesMeta": {
190 + "bufferutil": {
191 + "optional": true
192 + },
193 + "utf-8-validate": {
194 + "optional": true
195 + }
196 + }
197 + }
198 + }
199 +}
This diff is collapsed. Click to expand it.
1 +# Collection
2 +
3 +Utility data structure used in Discord.js.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
1 +{
2 + "name": "@discordjs/collection",
3 + "version": "0.1.6",
4 + "description": "Utility data structure used in Discord.js",
5 + "main": "dist/index.js",
6 + "types": "dist/index.d.ts",
7 + "scripts": {
8 + "lint": "eslint src --ext .ts",
9 + "prebuild": "npm run lint",
10 + "build": "rimraf dist/ && tsc",
11 + "pretest": "npm run build",
12 + "test": "node test/index.js",
13 + "docs": "docgen --jsdoc jsdoc.json --source src/*.ts src/**/*.ts --custom docs/index.yml --output docs/docs.json",
14 + "docs:test": "docgen --jsdoc jsdoc.json --source src/*.ts src/**/*.ts --custom docs/index.yml"
15 + },
16 + "repository": {
17 + "type": "git",
18 + "url": "git+https://github.com/discordjs/collection.git"
19 + },
20 + "keywords": [
21 + "map",
22 + "collection",
23 + "utility"
24 + ],
25 + "author": "Amish Shah <amishshah.2k@gmail.com>",
26 + "license": "Apache-2.0",
27 + "bugs": {
28 + "url": "https://github.com/discordjs/collection/issues"
29 + },
30 + "homepage": "https://github.com/discordjs/collection#readme",
31 + "devDependencies": {
32 + "@babel/cli": "^7.8.4",
33 + "@babel/core": "^7.8.4",
34 + "@babel/preset-env": "^7.8.4",
35 + "@babel/preset-typescript": "^7.8.3",
36 + "@types/node": "^13.7.4",
37 + "@typescript-eslint/eslint-plugin": "^2.21.0",
38 + "@typescript-eslint/parser": "^2.21.0",
39 + "discord.js-docgen": "discordjs/docgen#ts-patch",
40 + "eslint": "^6.8.0",
41 + "eslint-config-marine": "^6.0.0",
42 + "jsdoc-babel": "^0.5.0",
43 + "rimraf": "^3.0.2",
44 + "typescript": "^3.8.2"
45 + },
46 + "eslintConfig": {
47 + "extends": "marine/node"
48 + }
49 +}
1 +Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors
2 +
3 + Permission is hereby granted, free of charge, to any person obtaining a copy
4 + of this software and associated documentation files (the "Software"), to deal
5 + in the Software without restriction, including without limitation the rights
6 + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 + copies of the Software, and to permit persons to whom the Software is
8 + furnished to do so, subject to the following conditions:
9 +
10 + The above copyright notice and this permission notice shall be included in
11 + all copies or substantial portions of the Software.
12 +
13 + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 + THE SOFTWARE.
This diff is collapsed. Click to expand it.
1 +// Definitions by: Carlos Ballesteros Velasco <https://github.com/soywiz>
2 +// Leon Yu <https://github.com/leonyu>
3 +// BendingBender <https://github.com/BendingBender>
4 +// Maple Miao <https://github.com/mapleeit>
5 +
6 +/// <reference types="node" />
7 +import * as stream from 'stream';
8 +import * as http from 'http';
9 +
10 +export = FormData;
11 +
12 +// Extracted because @types/node doesn't export interfaces.
13 +interface ReadableOptions {
14 + highWaterMark?: number;
15 + encoding?: string;
16 + objectMode?: boolean;
17 + read?(this: stream.Readable, size: number): void;
18 + destroy?(this: stream.Readable, error: Error | null, callback: (error: Error | null) => void): void;
19 + autoDestroy?: boolean;
20 +}
21 +
22 +interface Options extends ReadableOptions {
23 + writable?: boolean;
24 + readable?: boolean;
25 + dataSize?: number;
26 + maxDataSize?: number;
27 + pauseStreams?: boolean;
28 +}
29 +
30 +declare class FormData extends stream.Readable {
31 + constructor(options?: Options);
32 + append(key: string, value: any, options?: FormData.AppendOptions | string): void;
33 + getHeaders(userHeaders?: FormData.Headers): FormData.Headers;
34 + submit(
35 + params: string | FormData.SubmitOptions,
36 + callback?: (error: Error | null, response: http.IncomingMessage) => void
37 + ): http.ClientRequest;
38 + getBuffer(): Buffer;
39 + getBoundary(): string;
40 + getLength(callback: (err: Error | null, length: number) => void): void;
41 + getLengthSync(): number;
42 + hasKnownLength(): boolean;
43 +}
44 +
45 +declare namespace FormData {
46 + interface Headers {
47 + [key: string]: any;
48 + }
49 +
50 + interface AppendOptions {
51 + header?: string | Headers;
52 + knownLength?: number;
53 + filename?: string;
54 + filepath?: string;
55 + contentType?: string;
56 + }
57 +
58 + interface SubmitOptions extends http.RequestOptions {
59 + protocol?: 'https:' | 'http:';
60 + }
61 +}
1 +/* eslint-env browser */
2 +module.exports = typeof self == 'object' ? self.FormData : window.FormData;
This diff is collapsed. Click to expand it.
1 +// populates missing values
2 +module.exports = function(dst, src) {
3 +
4 + Object.keys(src).forEach(function(prop)
5 + {
6 + dst[prop] = dst[prop] || src[prop];
7 + });
8 +
9 + return dst;
10 +};
1 +{
2 + "author": "Felix Geisendörfer <felix@debuggable.com> (http://debuggable.com/)",
3 + "name": "@discordjs/form-data",
4 + "description": "A library to create readable \"multipart/form-data\" streams. Can be used to submit forms and file uploads to other web applications.",
5 + "version": "3.0.1",
6 + "repository": {
7 + "type": "git",
8 + "url": "git://github.com/form-data/form-data.git"
9 + },
10 + "main": "./lib/form_data",
11 + "browser": "./lib/browser",
12 + "typings": "./index.d.ts",
13 + "scripts": {
14 + "pretest": "rimraf coverage test/tmp",
15 + "test": "istanbul cover test/run.js",
16 + "posttest": "istanbul report lcov text",
17 + "lint": "eslint lib/*.js test/*.js test/integration/*.js",
18 + "report": "istanbul report lcov text",
19 + "ci-lint": "is-node-modern 8 && npm run lint || is-node-not-modern 8",
20 + "ci-test": "npm run test && npm run browser && npm run report",
21 + "predebug": "rimraf coverage test/tmp",
22 + "debug": "verbose=1 ./test/run.js",
23 + "browser": "browserify -t browserify-istanbul test/run-browser.js | obake --coverage",
24 + "check": "istanbul check-coverage coverage/coverage*.json",
25 + "files": "pkgfiles --sort=name",
26 + "get-version": "node -e \"console.log(require('./package.json').version)\""
27 + },
28 + "pre-commit": [
29 + "lint",
30 + "ci-test",
31 + "check"
32 + ],
33 + "engines": {
34 + "node": ">= 6"
35 + },
36 + "dependencies": {
37 + "asynckit": "^0.4.0",
38 + "combined-stream": "^1.0.8",
39 + "mime-types": "^2.1.12"
40 + },
41 + "devDependencies": {
42 + "@types/node": "^12.0.10",
43 + "browserify": "^13.1.1",
44 + "browserify-istanbul": "^2.0.0",
45 + "coveralls": "^3.0.4",
46 + "cross-spawn": "^6.0.5",
47 + "eslint": "^6.0.1",
48 + "fake": "^0.2.2",
49 + "far": "^0.0.7",
50 + "formidable": "^1.0.17",
51 + "in-publish": "^2.0.0",
52 + "is-node-modern": "^1.0.0",
53 + "istanbul": "^0.4.5",
54 + "obake": "^0.1.2",
55 + "puppeteer": "^1.19.0",
56 + "pkgfiles": "^2.3.0",
57 + "pre-commit": "^1.1.3",
58 + "request": "^2.88.0",
59 + "rimraf": "^2.7.1",
60 + "tape": "^4.6.2",
61 + "typescript": "^3.5.2"
62 + },
63 + "license": "MIT"
64 +}
1 +MIT License
2 +
3 +Copyright (c) 2017 Toru Nagashima
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy
6 +of this software and associated documentation files (the "Software"), to deal
7 +in the Software without restriction, including without limitation the rights
8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom the Software is
10 +furnished to do so, subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in all
13 +copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 +SOFTWARE.
1 +# abort-controller
2 +
3 +[![npm version](https://img.shields.io/npm/v/abort-controller.svg)](https://www.npmjs.com/package/abort-controller)
4 +[![Downloads/month](https://img.shields.io/npm/dm/abort-controller.svg)](http://www.npmtrends.com/abort-controller)
5 +[![Build Status](https://travis-ci.org/mysticatea/abort-controller.svg?branch=master)](https://travis-ci.org/mysticatea/abort-controller)
6 +[![Coverage Status](https://codecov.io/gh/mysticatea/abort-controller/branch/master/graph/badge.svg)](https://codecov.io/gh/mysticatea/abort-controller)
7 +[![Dependency Status](https://david-dm.org/mysticatea/abort-controller.svg)](https://david-dm.org/mysticatea/abort-controller)
8 +
9 +An implementation of [WHATWG AbortController interface](https://dom.spec.whatwg.org/#interface-abortcontroller).
10 +
11 +```js
12 +import AbortController from "abort-controller"
13 +
14 +const controller = new AbortController()
15 +const signal = controller.signal
16 +
17 +signal.addEventListener("abort", () => {
18 + console.log("aborted!")
19 +})
20 +
21 +controller.abort()
22 +```
23 +
24 +> https://jsfiddle.net/1r2994qp/1/
25 +
26 +## 💿 Installation
27 +
28 +Use [npm](https://www.npmjs.com/) to install then use a bundler.
29 +
30 +```
31 +npm install abort-controller
32 +```
33 +
34 +Or download from [`dist` directory](./dist).
35 +
36 +- [dist/abort-controller.mjs](dist/abort-controller.mjs) ... ES modules version.
37 +- [dist/abort-controller.js](dist/abort-controller.js) ... Common JS version.
38 +- [dist/abort-controller.umd.js](dist/abort-controller.umd.js) ... UMD (Universal Module Definition) version. This is transpiled by [Babel](https://babeljs.io/) for IE 11.
39 +
40 +## 📖 Usage
41 +
42 +### Basic
43 +
44 +```js
45 +import AbortController from "abort-controller"
46 +// or
47 +const AbortController = require("abort-controller")
48 +
49 +// or UMD version defines a global variable:
50 +const AbortController = window.AbortControllerShim
51 +```
52 +
53 +If your bundler recognizes `browser` field of `package.json`, the imported `AbortController` is the native one and it doesn't contain shim (even if the native implementation was nothing).
54 +If you wanted to polyfill `AbortController` for IE, use `abort-controller/polyfill`.
55 +
56 +### Polyfilling
57 +
58 +Importing `abort-controller/polyfill` assigns the `AbortController` shim to the `AbortController` global variable if the native implementation was nothing.
59 +
60 +```js
61 +import "abort-controller/polyfill"
62 +// or
63 +require("abort-controller/polyfill")
64 +```
65 +
66 +### API
67 +
68 +#### AbortController
69 +
70 +> https://dom.spec.whatwg.org/#interface-abortcontroller
71 +
72 +##### controller.signal
73 +
74 +The [AbortSignal](https://dom.spec.whatwg.org/#interface-AbortSignal) object which is associated to this controller.
75 +
76 +##### controller.abort()
77 +
78 +Notify `abort` event to listeners that the `signal` has.
79 +
80 +## 📰 Changelog
81 +
82 +- See [GitHub releases](https://github.com/mysticatea/abort-controller/releases).
83 +
84 +## 🍻 Contributing
85 +
86 +Contributing is welcome ❤️
87 +
88 +Please use GitHub issues/PRs.
89 +
90 +### Development tools
91 +
92 +- `npm install` installs dependencies for development.
93 +- `npm test` runs tests and measures code coverage.
94 +- `npm run clean` removes temporary files of tests.
95 +- `npm run coverage` opens code coverage of the previous test with your default browser.
96 +- `npm run lint` runs ESLint.
97 +- `npm run build` generates `dist` codes.
98 +- `npm run watch` runs tests on each file change.
1 +/*globals self, window */
2 +"use strict"
3 +
4 +/*eslint-disable @mysticatea/prettier */
5 +const { AbortController, AbortSignal } =
6 + typeof self !== "undefined" ? self :
7 + typeof window !== "undefined" ? window :
8 + /* otherwise */ undefined
9 +/*eslint-enable @mysticatea/prettier */
10 +
11 +module.exports = AbortController
12 +module.exports.AbortSignal = AbortSignal
13 +module.exports.default = AbortController
1 +/*globals self, window */
2 +
3 +/*eslint-disable @mysticatea/prettier */
4 +const { AbortController, AbortSignal } =
5 + typeof self !== "undefined" ? self :
6 + typeof window !== "undefined" ? window :
7 + /* otherwise */ undefined
8 +/*eslint-enable @mysticatea/prettier */
9 +
10 +export default AbortController
11 +export { AbortController, AbortSignal }
1 +import { EventTarget } from "event-target-shim"
2 +
3 +type Events = {
4 + abort: any
5 +}
6 +type EventAttributes = {
7 + onabort: any
8 +}
9 +/**
10 + * The signal class.
11 + * @see https://dom.spec.whatwg.org/#abortsignal
12 + */
13 +declare class AbortSignal extends EventTarget<Events, EventAttributes> {
14 + /**
15 + * AbortSignal cannot be constructed directly.
16 + */
17 + constructor()
18 + /**
19 + * Returns `true` if this `AbortSignal`"s `AbortController` has signaled to abort, and `false` otherwise.
20 + */
21 + readonly aborted: boolean
22 +}
23 +/**
24 + * The AbortController.
25 + * @see https://dom.spec.whatwg.org/#abortcontroller
26 + */
27 +declare class AbortController {
28 + /**
29 + * Initialize this controller.
30 + */
31 + constructor()
32 + /**
33 + * Returns the `AbortSignal` object associated with this object.
34 + */
35 + readonly signal: AbortSignal
36 + /**
37 + * Abort and signal to any observers that the associated activity is to be aborted.
38 + */
39 + abort(): void
40 +}
41 +
42 +export default AbortController
43 +export { AbortController, AbortSignal }
1 +/**
2 + * @author Toru Nagashima <https://github.com/mysticatea>
3 + * See LICENSE file in root directory for full license.
4 + */
5 +'use strict';
6 +
7 +Object.defineProperty(exports, '__esModule', { value: true });
8 +
9 +var eventTargetShim = require('event-target-shim');
10 +
11 +/**
12 + * The signal class.
13 + * @see https://dom.spec.whatwg.org/#abortsignal
14 + */
15 +class AbortSignal extends eventTargetShim.EventTarget {
16 + /**
17 + * AbortSignal cannot be constructed directly.
18 + */
19 + constructor() {
20 + super();
21 + throw new TypeError("AbortSignal cannot be constructed directly");
22 + }
23 + /**
24 + * Returns `true` if this `AbortSignal`'s `AbortController` has signaled to abort, and `false` otherwise.
25 + */
26 + get aborted() {
27 + const aborted = abortedFlags.get(this);
28 + if (typeof aborted !== "boolean") {
29 + throw new TypeError(`Expected 'this' to be an 'AbortSignal' object, but got ${this === null ? "null" : typeof this}`);
30 + }
31 + return aborted;
32 + }
33 +}
34 +eventTargetShim.defineEventAttribute(AbortSignal.prototype, "abort");
35 +/**
36 + * Create an AbortSignal object.
37 + */
38 +function createAbortSignal() {
39 + const signal = Object.create(AbortSignal.prototype);
40 + eventTargetShim.EventTarget.call(signal);
41 + abortedFlags.set(signal, false);
42 + return signal;
43 +}
44 +/**
45 + * Abort a given signal.
46 + */
47 +function abortSignal(signal) {
48 + if (abortedFlags.get(signal) !== false) {
49 + return;
50 + }
51 + abortedFlags.set(signal, true);
52 + signal.dispatchEvent({ type: "abort" });
53 +}
54 +/**
55 + * Aborted flag for each instances.
56 + */
57 +const abortedFlags = new WeakMap();
58 +// Properties should be enumerable.
59 +Object.defineProperties(AbortSignal.prototype, {
60 + aborted: { enumerable: true },
61 +});
62 +// `toString()` should return `"[object AbortSignal]"`
63 +if (typeof Symbol === "function" && typeof Symbol.toStringTag === "symbol") {
64 + Object.defineProperty(AbortSignal.prototype, Symbol.toStringTag, {
65 + configurable: true,
66 + value: "AbortSignal",
67 + });
68 +}
69 +
70 +/**
71 + * The AbortController.
72 + * @see https://dom.spec.whatwg.org/#abortcontroller
73 + */
74 +class AbortController {
75 + /**
76 + * Initialize this controller.
77 + */
78 + constructor() {
79 + signals.set(this, createAbortSignal());
80 + }
81 + /**
82 + * Returns the `AbortSignal` object associated with this object.
83 + */
84 + get signal() {
85 + return getSignal(this);
86 + }
87 + /**
88 + * Abort and signal to any observers that the associated activity is to be aborted.
89 + */
90 + abort() {
91 + abortSignal(getSignal(this));
92 + }
93 +}
94 +/**
95 + * Associated signals.
96 + */
97 +const signals = new WeakMap();
98 +/**
99 + * Get the associated signal of a given controller.
100 + */
101 +function getSignal(controller) {
102 + const signal = signals.get(controller);
103 + if (signal == null) {
104 + throw new TypeError(`Expected 'this' to be an 'AbortController' object, but got ${controller === null ? "null" : typeof controller}`);
105 + }
106 + return signal;
107 +}
108 +// Properties should be enumerable.
109 +Object.defineProperties(AbortController.prototype, {
110 + signal: { enumerable: true },
111 + abort: { enumerable: true },
112 +});
113 +if (typeof Symbol === "function" && typeof Symbol.toStringTag === "symbol") {
114 + Object.defineProperty(AbortController.prototype, Symbol.toStringTag, {
115 + configurable: true,
116 + value: "AbortController",
117 + });
118 +}
119 +
120 +exports.AbortController = AbortController;
121 +exports.AbortSignal = AbortSignal;
122 +exports.default = AbortController;
123 +
124 +module.exports = AbortController
125 +module.exports.AbortController = module.exports["default"] = AbortController
126 +module.exports.AbortSignal = AbortSignal
127 +//# sourceMappingURL=abort-controller.js.map
1 +{"version":3,"file":"abort-controller.js","sources":["../src/abort-signal.ts","../src/abort-controller.ts"],"sourcesContent":["import {\n // Event,\n EventTarget,\n // Type,\n defineEventAttribute,\n} from \"event-target-shim\"\n\n// Known Limitation\n// Use `any` because the type of `AbortSignal` in `lib.dom.d.ts` is wrong and\n// to make assignable our `AbortSignal` into that.\n// https://github.com/Microsoft/TSJS-lib-generator/pull/623\ntype Events = {\n abort: any // Event & Type<\"abort\">\n}\ntype EventAttributes = {\n onabort: any // Event & Type<\"abort\">\n}\n\n/**\n * The signal class.\n * @see https://dom.spec.whatwg.org/#abortsignal\n */\nexport default class AbortSignal extends EventTarget<Events, EventAttributes> {\n /**\n * AbortSignal cannot be constructed directly.\n */\n public constructor() {\n super()\n throw new TypeError(\"AbortSignal cannot be constructed directly\")\n }\n\n /**\n * Returns `true` if this `AbortSignal`'s `AbortController` has signaled to abort, and `false` otherwise.\n */\n public get aborted(): boolean {\n const aborted = abortedFlags.get(this)\n if (typeof aborted !== \"boolean\") {\n throw new TypeError(\n `Expected 'this' to be an 'AbortSignal' object, but got ${\n this === null ? \"null\" : typeof this\n }`,\n )\n }\n return aborted\n }\n}\ndefineEventAttribute(AbortSignal.prototype, \"abort\")\n\n/**\n * Create an AbortSignal object.\n */\nexport function createAbortSignal(): AbortSignal {\n const signal = Object.create(AbortSignal.prototype)\n EventTarget.call(signal)\n abortedFlags.set(signal, false)\n return signal\n}\n\n/**\n * Abort a given signal.\n */\nexport function abortSignal(signal: AbortSignal): void {\n if (abortedFlags.get(signal) !== false) {\n return\n }\n\n abortedFlags.set(signal, true)\n signal.dispatchEvent<\"abort\">({ type: \"abort\" })\n}\n\n/**\n * Aborted flag for each instances.\n */\nconst abortedFlags = new WeakMap<AbortSignal, boolean>()\n\n// Properties should be enumerable.\nObject.defineProperties(AbortSignal.prototype, {\n aborted: { enumerable: true },\n})\n\n// `toString()` should return `\"[object AbortSignal]\"`\nif (typeof Symbol === \"function\" && typeof Symbol.toStringTag === \"symbol\") {\n Object.defineProperty(AbortSignal.prototype, Symbol.toStringTag, {\n configurable: true,\n value: \"AbortSignal\",\n })\n}\n","import AbortSignal, { abortSignal, createAbortSignal } from \"./abort-signal\"\n\n/**\n * The AbortController.\n * @see https://dom.spec.whatwg.org/#abortcontroller\n */\nexport default class AbortController {\n /**\n * Initialize this controller.\n */\n public constructor() {\n signals.set(this, createAbortSignal())\n }\n\n /**\n * Returns the `AbortSignal` object associated with this object.\n */\n public get signal(): AbortSignal {\n return getSignal(this)\n }\n\n /**\n * Abort and signal to any observers that the associated activity is to be aborted.\n */\n public abort(): void {\n abortSignal(getSignal(this))\n }\n}\n\n/**\n * Associated signals.\n */\nconst signals = new WeakMap<AbortController, AbortSignal>()\n\n/**\n * Get the associated signal of a given controller.\n */\nfunction getSignal(controller: AbortController): AbortSignal {\n const signal = signals.get(controller)\n if (signal == null) {\n throw new TypeError(\n `Expected 'this' to be an 'AbortController' object, but got ${\n controller === null ? \"null\" : typeof controller\n }`,\n )\n }\n return signal\n}\n\n// Properties should be enumerable.\nObject.defineProperties(AbortController.prototype, {\n signal: { enumerable: true },\n abort: { enumerable: true },\n})\n\nif (typeof Symbol === \"function\" && typeof Symbol.toStringTag === \"symbol\") {\n Object.defineProperty(AbortController.prototype, Symbol.toStringTag, {\n configurable: true,\n value: \"AbortController\",\n })\n}\n\nexport { AbortController, AbortSignal }\n"],"names":["EventTarget","defineEventAttribute"],"mappings":";;;;;;;;;;AAkBA;;;;AAIA,MAAqB,WAAY,SAAQA,2BAAoC;;;;IAIzE;QACI,KAAK,EAAE,CAAA;QACP,MAAM,IAAI,SAAS,CAAC,4CAA4C,CAAC,CAAA;KACpE;;;;IAKD,IAAW,OAAO;QACd,MAAM,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACtC,IAAI,OAAO,OAAO,KAAK,SAAS,EAAE;YAC9B,MAAM,IAAI,SAAS,CACf,0DACI,IAAI,KAAK,IAAI,GAAG,MAAM,GAAG,OAAO,IACpC,EAAE,CACL,CAAA;SACJ;QACD,OAAO,OAAO,CAAA;KACjB;CACJ;AACDC,oCAAoB,CAAC,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;;;;AAKpD,SAAgB,iBAAiB;IAC7B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAA;IACnDD,2BAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IACxB,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;IAC/B,OAAO,MAAM,CAAA;CAChB;;;;AAKD,SAAgB,WAAW,CAAC,MAAmB;IAC3C,IAAI,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,KAAK,EAAE;QACpC,OAAM;KACT;IAED,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;IAC9B,MAAM,CAAC,aAAa,CAAU,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAA;CACnD;;;;AAKD,MAAM,YAAY,GAAG,IAAI,OAAO,EAAwB,CAAA;;AAGxD,MAAM,CAAC,gBAAgB,CAAC,WAAW,CAAC,SAAS,EAAE;IAC3C,OAAO,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE;CAChC,CAAC,CAAA;;AAGF,IAAI,OAAO,MAAM,KAAK,UAAU,IAAI,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ,EAAE;IACxE,MAAM,CAAC,cAAc,CAAC,WAAW,CAAC,SAAS,EAAE,MAAM,CAAC,WAAW,EAAE;QAC7D,YAAY,EAAE,IAAI;QAClB,KAAK,EAAE,aAAa;KACvB,CAAC,CAAA;CACL;;ACpFD;;;;AAIA,MAAqB,eAAe;;;;IAIhC;QACI,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,iBAAiB,EAAE,CAAC,CAAA;KACzC;;;;IAKD,IAAW,MAAM;QACb,OAAO,SAAS,CAAC,IAAI,CAAC,CAAA;KACzB;;;;IAKM,KAAK;QACR,WAAW,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;KAC/B;CACJ;;;;AAKD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAgC,CAAA;;;;AAK3D,SAAS,SAAS,CAAC,UAA2B;IAC1C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;IACtC,IAAI,MAAM,IAAI,IAAI,EAAE;QAChB,MAAM,IAAI,SAAS,CACf,8DACI,UAAU,KAAK,IAAI,GAAG,MAAM,GAAG,OAAO,UAC1C,EAAE,CACL,CAAA;KACJ;IACD,OAAO,MAAM,CAAA;CAChB;;AAGD,MAAM,CAAC,gBAAgB,CAAC,eAAe,CAAC,SAAS,EAAE;IAC/C,MAAM,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE;IAC5B,KAAK,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE;CAC9B,CAAC,CAAA;AAEF,IAAI,OAAO,MAAM,KAAK,UAAU,IAAI,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ,EAAE;IACxE,MAAM,CAAC,cAAc,CAAC,eAAe,CAAC,SAAS,EAAE,MAAM,CAAC,WAAW,EAAE;QACjE,YAAY,EAAE,IAAI;QAClB,KAAK,EAAE,iBAAiB;KAC3B,CAAC,CAAA;CACL;;;;;;;;;;;;;"}
...\ No newline at end of file ...\ No newline at end of file
1 +/**
2 + * @author Toru Nagashima <https://github.com/mysticatea>
3 + * See LICENSE file in root directory for full license.
4 + */
5 +import { EventTarget, defineEventAttribute } from 'event-target-shim';
6 +
7 +/**
8 + * The signal class.
9 + * @see https://dom.spec.whatwg.org/#abortsignal
10 + */
11 +class AbortSignal extends EventTarget {
12 + /**
13 + * AbortSignal cannot be constructed directly.
14 + */
15 + constructor() {
16 + super();
17 + throw new TypeError("AbortSignal cannot be constructed directly");
18 + }
19 + /**
20 + * Returns `true` if this `AbortSignal`'s `AbortController` has signaled to abort, and `false` otherwise.
21 + */
22 + get aborted() {
23 + const aborted = abortedFlags.get(this);
24 + if (typeof aborted !== "boolean") {
25 + throw new TypeError(`Expected 'this' to be an 'AbortSignal' object, but got ${this === null ? "null" : typeof this}`);
26 + }
27 + return aborted;
28 + }
29 +}
30 +defineEventAttribute(AbortSignal.prototype, "abort");
31 +/**
32 + * Create an AbortSignal object.
33 + */
34 +function createAbortSignal() {
35 + const signal = Object.create(AbortSignal.prototype);
36 + EventTarget.call(signal);
37 + abortedFlags.set(signal, false);
38 + return signal;
39 +}
40 +/**
41 + * Abort a given signal.
42 + */
43 +function abortSignal(signal) {
44 + if (abortedFlags.get(signal) !== false) {
45 + return;
46 + }
47 + abortedFlags.set(signal, true);
48 + signal.dispatchEvent({ type: "abort" });
49 +}
50 +/**
51 + * Aborted flag for each instances.
52 + */
53 +const abortedFlags = new WeakMap();
54 +// Properties should be enumerable.
55 +Object.defineProperties(AbortSignal.prototype, {
56 + aborted: { enumerable: true },
57 +});
58 +// `toString()` should return `"[object AbortSignal]"`
59 +if (typeof Symbol === "function" && typeof Symbol.toStringTag === "symbol") {
60 + Object.defineProperty(AbortSignal.prototype, Symbol.toStringTag, {
61 + configurable: true,
62 + value: "AbortSignal",
63 + });
64 +}
65 +
66 +/**
67 + * The AbortController.
68 + * @see https://dom.spec.whatwg.org/#abortcontroller
69 + */
70 +class AbortController {
71 + /**
72 + * Initialize this controller.
73 + */
74 + constructor() {
75 + signals.set(this, createAbortSignal());
76 + }
77 + /**
78 + * Returns the `AbortSignal` object associated with this object.
79 + */
80 + get signal() {
81 + return getSignal(this);
82 + }
83 + /**
84 + * Abort and signal to any observers that the associated activity is to be aborted.
85 + */
86 + abort() {
87 + abortSignal(getSignal(this));
88 + }
89 +}
90 +/**
91 + * Associated signals.
92 + */
93 +const signals = new WeakMap();
94 +/**
95 + * Get the associated signal of a given controller.
96 + */
97 +function getSignal(controller) {
98 + const signal = signals.get(controller);
99 + if (signal == null) {
100 + throw new TypeError(`Expected 'this' to be an 'AbortController' object, but got ${controller === null ? "null" : typeof controller}`);
101 + }
102 + return signal;
103 +}
104 +// Properties should be enumerable.
105 +Object.defineProperties(AbortController.prototype, {
106 + signal: { enumerable: true },
107 + abort: { enumerable: true },
108 +});
109 +if (typeof Symbol === "function" && typeof Symbol.toStringTag === "symbol") {
110 + Object.defineProperty(AbortController.prototype, Symbol.toStringTag, {
111 + configurable: true,
112 + value: "AbortController",
113 + });
114 +}
115 +
116 +export default AbortController;
117 +export { AbortController, AbortSignal };
118 +//# sourceMappingURL=abort-controller.mjs.map
1 +{"version":3,"file":"abort-controller.mjs","sources":["../src/abort-signal.ts","../src/abort-controller.ts"],"sourcesContent":["import {\n // Event,\n EventTarget,\n // Type,\n defineEventAttribute,\n} from \"event-target-shim\"\n\n// Known Limitation\n// Use `any` because the type of `AbortSignal` in `lib.dom.d.ts` is wrong and\n// to make assignable our `AbortSignal` into that.\n// https://github.com/Microsoft/TSJS-lib-generator/pull/623\ntype Events = {\n abort: any // Event & Type<\"abort\">\n}\ntype EventAttributes = {\n onabort: any // Event & Type<\"abort\">\n}\n\n/**\n * The signal class.\n * @see https://dom.spec.whatwg.org/#abortsignal\n */\nexport default class AbortSignal extends EventTarget<Events, EventAttributes> {\n /**\n * AbortSignal cannot be constructed directly.\n */\n public constructor() {\n super()\n throw new TypeError(\"AbortSignal cannot be constructed directly\")\n }\n\n /**\n * Returns `true` if this `AbortSignal`'s `AbortController` has signaled to abort, and `false` otherwise.\n */\n public get aborted(): boolean {\n const aborted = abortedFlags.get(this)\n if (typeof aborted !== \"boolean\") {\n throw new TypeError(\n `Expected 'this' to be an 'AbortSignal' object, but got ${\n this === null ? \"null\" : typeof this\n }`,\n )\n }\n return aborted\n }\n}\ndefineEventAttribute(AbortSignal.prototype, \"abort\")\n\n/**\n * Create an AbortSignal object.\n */\nexport function createAbortSignal(): AbortSignal {\n const signal = Object.create(AbortSignal.prototype)\n EventTarget.call(signal)\n abortedFlags.set(signal, false)\n return signal\n}\n\n/**\n * Abort a given signal.\n */\nexport function abortSignal(signal: AbortSignal): void {\n if (abortedFlags.get(signal) !== false) {\n return\n }\n\n abortedFlags.set(signal, true)\n signal.dispatchEvent<\"abort\">({ type: \"abort\" })\n}\n\n/**\n * Aborted flag for each instances.\n */\nconst abortedFlags = new WeakMap<AbortSignal, boolean>()\n\n// Properties should be enumerable.\nObject.defineProperties(AbortSignal.prototype, {\n aborted: { enumerable: true },\n})\n\n// `toString()` should return `\"[object AbortSignal]\"`\nif (typeof Symbol === \"function\" && typeof Symbol.toStringTag === \"symbol\") {\n Object.defineProperty(AbortSignal.prototype, Symbol.toStringTag, {\n configurable: true,\n value: \"AbortSignal\",\n })\n}\n","import AbortSignal, { abortSignal, createAbortSignal } from \"./abort-signal\"\n\n/**\n * The AbortController.\n * @see https://dom.spec.whatwg.org/#abortcontroller\n */\nexport default class AbortController {\n /**\n * Initialize this controller.\n */\n public constructor() {\n signals.set(this, createAbortSignal())\n }\n\n /**\n * Returns the `AbortSignal` object associated with this object.\n */\n public get signal(): AbortSignal {\n return getSignal(this)\n }\n\n /**\n * Abort and signal to any observers that the associated activity is to be aborted.\n */\n public abort(): void {\n abortSignal(getSignal(this))\n }\n}\n\n/**\n * Associated signals.\n */\nconst signals = new WeakMap<AbortController, AbortSignal>()\n\n/**\n * Get the associated signal of a given controller.\n */\nfunction getSignal(controller: AbortController): AbortSignal {\n const signal = signals.get(controller)\n if (signal == null) {\n throw new TypeError(\n `Expected 'this' to be an 'AbortController' object, but got ${\n controller === null ? \"null\" : typeof controller\n }`,\n )\n }\n return signal\n}\n\n// Properties should be enumerable.\nObject.defineProperties(AbortController.prototype, {\n signal: { enumerable: true },\n abort: { enumerable: true },\n})\n\nif (typeof Symbol === \"function\" && typeof Symbol.toStringTag === \"symbol\") {\n Object.defineProperty(AbortController.prototype, Symbol.toStringTag, {\n configurable: true,\n value: \"AbortController\",\n })\n}\n\nexport { AbortController, AbortSignal }\n"],"names":[],"mappings":";;;;;;AAkBA;;;;AAIA,MAAqB,WAAY,SAAQ,WAAoC;;;;IAIzE;QACI,KAAK,EAAE,CAAA;QACP,MAAM,IAAI,SAAS,CAAC,4CAA4C,CAAC,CAAA;KACpE;;;;IAKD,IAAW,OAAO;QACd,MAAM,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACtC,IAAI,OAAO,OAAO,KAAK,SAAS,EAAE;YAC9B,MAAM,IAAI,SAAS,CACf,0DACI,IAAI,KAAK,IAAI,GAAG,MAAM,GAAG,OAAO,IACpC,EAAE,CACL,CAAA;SACJ;QACD,OAAO,OAAO,CAAA;KACjB;CACJ;AACD,oBAAoB,CAAC,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;;;;AAKpD,SAAgB,iBAAiB;IAC7B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAA;IACnD,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IACxB,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;IAC/B,OAAO,MAAM,CAAA;CAChB;;;;AAKD,SAAgB,WAAW,CAAC,MAAmB;IAC3C,IAAI,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,KAAK,EAAE;QACpC,OAAM;KACT;IAED,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;IAC9B,MAAM,CAAC,aAAa,CAAU,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAA;CACnD;;;;AAKD,MAAM,YAAY,GAAG,IAAI,OAAO,EAAwB,CAAA;;AAGxD,MAAM,CAAC,gBAAgB,CAAC,WAAW,CAAC,SAAS,EAAE;IAC3C,OAAO,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE;CAChC,CAAC,CAAA;;AAGF,IAAI,OAAO,MAAM,KAAK,UAAU,IAAI,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ,EAAE;IACxE,MAAM,CAAC,cAAc,CAAC,WAAW,CAAC,SAAS,EAAE,MAAM,CAAC,WAAW,EAAE;QAC7D,YAAY,EAAE,IAAI;QAClB,KAAK,EAAE,aAAa;KACvB,CAAC,CAAA;CACL;;ACpFD;;;;AAIA,MAAqB,eAAe;;;;IAIhC;QACI,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,iBAAiB,EAAE,CAAC,CAAA;KACzC;;;;IAKD,IAAW,MAAM;QACb,OAAO,SAAS,CAAC,IAAI,CAAC,CAAA;KACzB;;;;IAKM,KAAK;QACR,WAAW,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;KAC/B;CACJ;;;;AAKD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAgC,CAAA;;;;AAK3D,SAAS,SAAS,CAAC,UAA2B;IAC1C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;IACtC,IAAI,MAAM,IAAI,IAAI,EAAE;QAChB,MAAM,IAAI,SAAS,CACf,8DACI,UAAU,KAAK,IAAI,GAAG,MAAM,GAAG,OAAO,UAC1C,EAAE,CACL,CAAA;KACJ;IACD,OAAO,MAAM,CAAA;CAChB;;AAGD,MAAM,CAAC,gBAAgB,CAAC,eAAe,CAAC,SAAS,EAAE;IAC/C,MAAM,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE;IAC5B,KAAK,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE;CAC9B,CAAC,CAAA;AAEF,IAAI,OAAO,MAAM,KAAK,UAAU,IAAI,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ,EAAE;IACxE,MAAM,CAAC,cAAc,CAAC,eAAe,CAAC,SAAS,EAAE,MAAM,CAAC,WAAW,EAAE;QACjE,YAAY,EAAE,IAAI;QAClB,KAAK,EAAE,iBAAiB;KAC3B,CAAC,CAAA;CACL;;;;;"}
...\ No newline at end of file ...\ No newline at end of file
1 +/**
2 + * @author Toru Nagashima <https://github.com/mysticatea>
3 + * See LICENSE file in root directory for full license.
4 + */(function(a,b){"object"==typeof exports&&"undefined"!=typeof module?b(exports):"function"==typeof define&&define.amd?define(["exports"],b):(a=a||self,b(a.AbortControllerShim={}))})(this,function(a){'use strict';function b(a){return b="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a},b(a)}function c(a,b){if(!(a instanceof b))throw new TypeError("Cannot call a class as a function")}function d(a,b){for(var c,d=0;d<b.length;d++)c=b[d],c.enumerable=c.enumerable||!1,c.configurable=!0,"value"in c&&(c.writable=!0),Object.defineProperty(a,c.key,c)}function e(a,b,c){return b&&d(a.prototype,b),c&&d(a,c),a}function f(a,b){if("function"!=typeof b&&null!==b)throw new TypeError("Super expression must either be null or a function");a.prototype=Object.create(b&&b.prototype,{constructor:{value:a,writable:!0,configurable:!0}}),b&&h(a,b)}function g(a){return g=Object.setPrototypeOf?Object.getPrototypeOf:function(a){return a.__proto__||Object.getPrototypeOf(a)},g(a)}function h(a,b){return h=Object.setPrototypeOf||function(a,b){return a.__proto__=b,a},h(a,b)}function i(a){if(void 0===a)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return a}function j(a,b){return b&&("object"==typeof b||"function"==typeof b)?b:i(a)}function k(a){var b=F.get(a);return console.assert(null!=b,"'this' is expected an Event object, but got",a),b}function l(a){return null==a.passiveListener?void(!a.event.cancelable||(a.canceled=!0,"function"==typeof a.event.preventDefault&&a.event.preventDefault())):void("undefined"!=typeof console&&"function"==typeof console.error&&console.error("Unable to preventDefault inside passive event listener invocation.",a.passiveListener))}function m(a,b){F.set(this,{eventTarget:a,event:b,eventPhase:2,currentTarget:a,canceled:!1,stopped:!1,immediateStopped:!1,passiveListener:null,timeStamp:b.timeStamp||Date.now()}),Object.defineProperty(this,"isTrusted",{value:!1,enumerable:!0});for(var c,d=Object.keys(b),e=0;e<d.length;++e)c=d[e],c in this||Object.defineProperty(this,c,n(c))}function n(a){return{get:function(){return k(this).event[a]},set:function(b){k(this).event[a]=b},configurable:!0,enumerable:!0}}function o(a){return{value:function(){var b=k(this).event;return b[a].apply(b,arguments)},configurable:!0,enumerable:!0}}function p(a,b){function c(b,c){a.call(this,b,c)}var d=Object.keys(b);if(0===d.length)return a;c.prototype=Object.create(a.prototype,{constructor:{value:c,configurable:!0,writable:!0}});for(var e,f=0;f<d.length;++f)if(e=d[f],!(e in a.prototype)){var g=Object.getOwnPropertyDescriptor(b,e),h="function"==typeof g.value;Object.defineProperty(c.prototype,e,h?o(e):n(e))}return c}function q(a){if(null==a||a===Object.prototype)return m;var b=G.get(a);return null==b&&(b=p(q(Object.getPrototypeOf(a)),a),G.set(a,b)),b}function r(a,b){var c=q(Object.getPrototypeOf(b));return new c(a,b)}function s(a){return k(a).immediateStopped}function t(a,b){k(a).eventPhase=b}function u(a,b){k(a).currentTarget=b}function v(a,b){k(a).passiveListener=b}function w(a){return null!==a&&"object"===b(a)}function x(a){var b=H.get(a);if(null==b)throw new TypeError("'this' is expected an EventTarget object, but got another value.");return b}function y(a){return{get:function(){for(var b=x(this),c=b.get(a);null!=c;){if(3===c.listenerType)return c.listener;c=c.next}return null},set:function(b){"function"==typeof b||w(b)||(b=null);for(var c=x(this),d=null,e=c.get(a);null!=e;)3===e.listenerType?null===d?null===e.next?c.delete(a):c.set(a,e.next):d.next=e.next:d=e,e=e.next;if(null!==b){var f={listener:b,listenerType:3,passive:!1,once:!1,next:null};null===d?c.set(a,f):d.next=f}},configurable:!0,enumerable:!0}}function z(a,b){Object.defineProperty(a,"on".concat(b),y(b))}function A(a){function b(){B.call(this)}b.prototype=Object.create(B.prototype,{constructor:{value:b,configurable:!0,writable:!0}});for(var c=0;c<a.length;++c)z(b.prototype,a[c]);return b}function B(){if(this instanceof B)return void H.set(this,new Map);if(1===arguments.length&&Array.isArray(arguments[0]))return A(arguments[0]);if(0<arguments.length){for(var a=Array(arguments.length),b=0;b<arguments.length;++b)a[b]=arguments[b];return A(a)}throw new TypeError("Cannot call a class as a function")}function C(){var a=Object.create(K.prototype);return B.call(a),L.set(a,!1),a}function D(a){!1!==L.get(a)||(L.set(a,!0),a.dispatchEvent({type:"abort"}))}function E(a){var c=N.get(a);if(null==c)throw new TypeError("Expected 'this' to be an 'AbortController' object, but got ".concat(null===a?"null":b(a)));return c}var F=new WeakMap,G=new WeakMap;m.prototype={get type(){return k(this).event.type},get target(){return k(this).eventTarget},get currentTarget(){return k(this).currentTarget},composedPath:function(){var a=k(this).currentTarget;return null==a?[]:[a]},get NONE(){return 0},get CAPTURING_PHASE(){return 1},get AT_TARGET(){return 2},get BUBBLING_PHASE(){return 3},get eventPhase(){return k(this).eventPhase},stopPropagation:function(){var a=k(this);a.stopped=!0,"function"==typeof a.event.stopPropagation&&a.event.stopPropagation()},stopImmediatePropagation:function(){var a=k(this);a.stopped=!0,a.immediateStopped=!0,"function"==typeof a.event.stopImmediatePropagation&&a.event.stopImmediatePropagation()},get bubbles(){return!!k(this).event.bubbles},get cancelable(){return!!k(this).event.cancelable},preventDefault:function(){l(k(this))},get defaultPrevented(){return k(this).canceled},get composed(){return!!k(this).event.composed},get timeStamp(){return k(this).timeStamp},get srcElement(){return k(this).eventTarget},get cancelBubble(){return k(this).stopped},set cancelBubble(a){if(a){var b=k(this);b.stopped=!0,"boolean"==typeof b.event.cancelBubble&&(b.event.cancelBubble=!0)}},get returnValue(){return!k(this).canceled},set returnValue(a){a||l(k(this))},initEvent:function(){}},Object.defineProperty(m.prototype,"constructor",{value:m,configurable:!0,writable:!0}),"undefined"!=typeof window&&"undefined"!=typeof window.Event&&(Object.setPrototypeOf(m.prototype,window.Event.prototype),G.set(window.Event.prototype,m));var H=new WeakMap,I=1,J=2;B.prototype={addEventListener:function(a,b,c){if(null!=b){if("function"!=typeof b&&!w(b))throw new TypeError("'listener' should be a function or an object.");var d=x(this),e=w(c),f=e?!!c.capture:!!c,g=f?I:J,h={listener:b,listenerType:g,passive:e&&!!c.passive,once:e&&!!c.once,next:null},i=d.get(a);if(void 0===i)return void d.set(a,h);for(var j=null;null!=i;){if(i.listener===b&&i.listenerType===g)return;j=i,i=i.next}j.next=h}},removeEventListener:function(a,b,c){if(null!=b)for(var d=x(this),e=w(c)?!!c.capture:!!c,f=e?I:J,g=null,h=d.get(a);null!=h;){if(h.listener===b&&h.listenerType===f)return void(null===g?null===h.next?d.delete(a):d.set(a,h.next):g.next=h.next);g=h,h=h.next}},dispatchEvent:function(a){if(null==a||"string"!=typeof a.type)throw new TypeError("\"event.type\" should be a string.");var b=x(this),c=a.type,d=b.get(c);if(null==d)return!0;for(var e=r(this,a),f=null;null!=d;){if(d.once?null===f?null===d.next?b.delete(c):b.set(c,d.next):f.next=d.next:f=d,v(e,d.passive?d.listener:null),"function"==typeof d.listener)try{d.listener.call(this,e)}catch(a){"undefined"!=typeof console&&"function"==typeof console.error&&console.error(a)}else d.listenerType!==3&&"function"==typeof d.listener.handleEvent&&d.listener.handleEvent(e);if(s(e))break;d=d.next}return v(e,null),t(e,0),u(e,null),!e.defaultPrevented}},Object.defineProperty(B.prototype,"constructor",{value:B,configurable:!0,writable:!0}),"undefined"!=typeof window&&"undefined"!=typeof window.EventTarget&&Object.setPrototypeOf(B.prototype,window.EventTarget.prototype);var K=function(a){function d(){var a;throw c(this,d),a=j(this,g(d).call(this)),new TypeError("AbortSignal cannot be constructed directly")}return f(d,a),e(d,[{key:"aborted",get:function(){var a=L.get(this);if("boolean"!=typeof a)throw new TypeError("Expected 'this' to be an 'AbortSignal' object, but got ".concat(null===this?"null":b(this)));return a}}]),d}(B);z(K.prototype,"abort");var L=new WeakMap;Object.defineProperties(K.prototype,{aborted:{enumerable:!0}}),"function"==typeof Symbol&&"symbol"===b(Symbol.toStringTag)&&Object.defineProperty(K.prototype,Symbol.toStringTag,{configurable:!0,value:"AbortSignal"});var M=function(){function a(){c(this,a),N.set(this,C())}return e(a,[{key:"abort",value:function(){D(E(this))}},{key:"signal",get:function(){return E(this)}}]),a}(),N=new WeakMap;if(Object.defineProperties(M.prototype,{signal:{enumerable:!0},abort:{enumerable:!0}}),"function"==typeof Symbol&&"symbol"===b(Symbol.toStringTag)&&Object.defineProperty(M.prototype,Symbol.toStringTag,{configurable:!0,value:"AbortController"}),a.AbortController=M,a.AbortSignal=K,a.default=M,Object.defineProperty(a,"__esModule",{value:!0}),"undefined"==typeof module&&"undefined"==typeof define){var O=Function("return this")();"undefined"==typeof O.AbortController&&(O.AbortController=M,O.AbortSignal=K)}});
5 +//# sourceMappingURL=abort-controller.umd.js.map
This diff is collapsed. Click to expand it.
1 +{
2 + "name": "abort-controller",
3 + "version": "3.0.0",
4 + "description": "An implementation of WHATWG AbortController interface.",
5 + "main": "dist/abort-controller",
6 + "files": [
7 + "dist",
8 + "polyfill.*",
9 + "browser.*"
10 + ],
11 + "engines": {
12 + "node": ">=6.5"
13 + },
14 + "dependencies": {
15 + "event-target-shim": "^5.0.0"
16 + },
17 + "browser": "./browser.js",
18 + "devDependencies": {
19 + "@babel/core": "^7.2.2",
20 + "@babel/plugin-transform-modules-commonjs": "^7.2.0",
21 + "@babel/preset-env": "^7.3.0",
22 + "@babel/register": "^7.0.0",
23 + "@mysticatea/eslint-plugin": "^8.0.1",
24 + "@mysticatea/spy": "^0.1.2",
25 + "@types/mocha": "^5.2.5",
26 + "@types/node": "^10.12.18",
27 + "assert": "^1.4.1",
28 + "codecov": "^3.1.0",
29 + "dts-bundle-generator": "^2.0.0",
30 + "eslint": "^5.12.1",
31 + "karma": "^3.1.4",
32 + "karma-chrome-launcher": "^2.2.0",
33 + "karma-coverage": "^1.1.2",
34 + "karma-firefox-launcher": "^1.1.0",
35 + "karma-growl-reporter": "^1.0.0",
36 + "karma-ie-launcher": "^1.0.0",
37 + "karma-mocha": "^1.3.0",
38 + "karma-rollup-preprocessor": "^7.0.0-rc.2",
39 + "mocha": "^5.2.0",
40 + "npm-run-all": "^4.1.5",
41 + "nyc": "^13.1.0",
42 + "opener": "^1.5.1",
43 + "rimraf": "^2.6.3",
44 + "rollup": "^1.1.2",
45 + "rollup-plugin-babel": "^4.3.2",
46 + "rollup-plugin-babel-minify": "^7.0.0",
47 + "rollup-plugin-commonjs": "^9.2.0",
48 + "rollup-plugin-node-resolve": "^4.0.0",
49 + "rollup-plugin-sourcemaps": "^0.4.2",
50 + "rollup-plugin-typescript": "^1.0.0",
51 + "rollup-watch": "^4.3.1",
52 + "ts-node": "^8.0.1",
53 + "type-tester": "^1.0.0",
54 + "typescript": "^3.2.4"
55 + },
56 + "scripts": {
57 + "preversion": "npm test",
58 + "version": "npm run -s build && git add dist/*",
59 + "postversion": "git push && git push --tags",
60 + "clean": "rimraf .nyc_output coverage",
61 + "coverage": "opener coverage/lcov-report/index.html",
62 + "lint": "eslint . --ext .ts",
63 + "build": "run-s -s build:*",
64 + "build:rollup": "rollup -c",
65 + "build:dts": "dts-bundle-generator -o dist/abort-controller.d.ts src/abort-controller.ts && ts-node scripts/fix-dts",
66 + "test": "run-s -s lint test:*",
67 + "test:mocha": "nyc mocha test/*.ts",
68 + "test:karma": "karma start --single-run",
69 + "watch": "run-p -s watch:*",
70 + "watch:mocha": "mocha test/*.ts --require ts-node/register --watch-extensions ts --watch --growl",
71 + "watch:karma": "karma start --watch",
72 + "codecov": "codecov"
73 + },
74 + "repository": {
75 + "type": "git",
76 + "url": "git+https://github.com/mysticatea/abort-controller.git"
77 + },
78 + "keywords": [
79 + "w3c",
80 + "whatwg",
81 + "event",
82 + "events",
83 + "abort",
84 + "cancel",
85 + "abortcontroller",
86 + "abortsignal",
87 + "controller",
88 + "signal",
89 + "shim"
90 + ],
91 + "author": "Toru Nagashima (https://github.com/mysticatea)",
92 + "license": "MIT",
93 + "bugs": {
94 + "url": "https://github.com/mysticatea/abort-controller/issues"
95 + },
96 + "homepage": "https://github.com/mysticatea/abort-controller#readme"
97 +}
1 +/*globals require, self, window */
2 +"use strict"
3 +
4 +const ac = require("./dist/abort-controller")
5 +
6 +/*eslint-disable @mysticatea/prettier */
7 +const g =
8 + typeof self !== "undefined" ? self :
9 + typeof window !== "undefined" ? window :
10 + typeof global !== "undefined" ? global :
11 + /* otherwise */ undefined
12 +/*eslint-enable @mysticatea/prettier */
13 +
14 +if (g) {
15 + if (typeof g.AbortController === "undefined") {
16 + g.AbortController = ac.AbortController
17 + }
18 + if (typeof g.AbortSignal === "undefined") {
19 + g.AbortSignal = ac.AbortSignal
20 + }
21 +}
1 +/*globals self, window */
2 +import * as ac from "./dist/abort-controller"
3 +
4 +/*eslint-disable @mysticatea/prettier */
5 +const g =
6 + typeof self !== "undefined" ? self :
7 + typeof window !== "undefined" ? window :
8 + typeof global !== "undefined" ? global :
9 + /* otherwise */ undefined
10 +/*eslint-enable @mysticatea/prettier */
11 +
12 +if (g) {
13 + if (typeof g.AbortController === "undefined") {
14 + g.AbortController = ac.AbortController
15 + }
16 + if (typeof g.AbortSignal === "undefined") {
17 + g.AbortSignal = ac.AbortSignal
18 + }
19 +}
1 +The MIT License (MIT)
2 +
3 +Copyright (c) 2016 Alex Indigo
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy
6 +of this software and associated documentation files (the "Software"), to deal
7 +in the Software without restriction, including without limitation the rights
8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom the Software is
10 +furnished to do so, subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in all
13 +copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 +SOFTWARE.
1 +# asynckit [![NPM Module](https://img.shields.io/npm/v/asynckit.svg?style=flat)](https://www.npmjs.com/package/asynckit)
2 +
3 +Minimal async jobs utility library, with streams support.
4 +
5 +[![PhantomJS Build](https://img.shields.io/travis/alexindigo/asynckit/v0.4.0.svg?label=browser&style=flat)](https://travis-ci.org/alexindigo/asynckit)
6 +[![Linux Build](https://img.shields.io/travis/alexindigo/asynckit/v0.4.0.svg?label=linux:0.12-6.x&style=flat)](https://travis-ci.org/alexindigo/asynckit)
7 +[![Windows Build](https://img.shields.io/appveyor/ci/alexindigo/asynckit/v0.4.0.svg?label=windows:0.12-6.x&style=flat)](https://ci.appveyor.com/project/alexindigo/asynckit)
8 +
9 +[![Coverage Status](https://img.shields.io/coveralls/alexindigo/asynckit/v0.4.0.svg?label=code+coverage&style=flat)](https://coveralls.io/github/alexindigo/asynckit?branch=master)
10 +[![Dependency Status](https://img.shields.io/david/alexindigo/asynckit/v0.4.0.svg?style=flat)](https://david-dm.org/alexindigo/asynckit)
11 +[![bitHound Overall Score](https://www.bithound.io/github/alexindigo/asynckit/badges/score.svg)](https://www.bithound.io/github/alexindigo/asynckit)
12 +
13 +<!-- [![Readme](https://img.shields.io/badge/readme-tested-brightgreen.svg?style=flat)](https://www.npmjs.com/package/reamde) -->
14 +
15 +AsyncKit provides harness for `parallel` and `serial` iterators over list of items represented by arrays or objects.
16 +Optionally it accepts abort function (should be synchronously return by iterator for each item), and terminates left over jobs upon an error event. For specific iteration order built-in (`ascending` and `descending`) and custom sort helpers also supported, via `asynckit.serialOrdered` method.
17 +
18 +It ensures async operations to keep behavior more stable and prevent `Maximum call stack size exceeded` errors, from sync iterators.
19 +
20 +| compression | size |
21 +| :----------------- | -------: |
22 +| asynckit.js | 12.34 kB |
23 +| asynckit.min.js | 4.11 kB |
24 +| asynckit.min.js.gz | 1.47 kB |
25 +
26 +
27 +## Install
28 +
29 +```sh
30 +$ npm install --save asynckit
31 +```
32 +
33 +## Examples
34 +
35 +### Parallel Jobs
36 +
37 +Runs iterator over provided array in parallel. Stores output in the `result` array,
38 +on the matching positions. In unlikely event of an error from one of the jobs,
39 +will terminate rest of the active jobs (if abort function is provided)
40 +and return error along with salvaged data to the main callback function.
41 +
42 +#### Input Array
43 +
44 +```javascript
45 +var parallel = require('asynckit').parallel
46 + , assert = require('assert')
47 + ;
48 +
49 +var source = [ 1, 1, 4, 16, 64, 32, 8, 2 ]
50 + , expectedResult = [ 2, 2, 8, 32, 128, 64, 16, 4 ]
51 + , expectedTarget = [ 1, 1, 2, 4, 8, 16, 32, 64 ]
52 + , target = []
53 + ;
54 +
55 +parallel(source, asyncJob, function(err, result)
56 +{
57 + assert.deepEqual(result, expectedResult);
58 + assert.deepEqual(target, expectedTarget);
59 +});
60 +
61 +// async job accepts one element from the array
62 +// and a callback function
63 +function asyncJob(item, cb)
64 +{
65 + // different delays (in ms) per item
66 + var delay = item * 25;
67 +
68 + // pretend different jobs take different time to finish
69 + // and not in consequential order
70 + var timeoutId = setTimeout(function() {
71 + target.push(item);
72 + cb(null, item * 2);
73 + }, delay);
74 +
75 + // allow to cancel "leftover" jobs upon error
76 + // return function, invoking of which will abort this job
77 + return clearTimeout.bind(null, timeoutId);
78 +}
79 +```
80 +
81 +More examples could be found in [test/test-parallel-array.js](test/test-parallel-array.js).
82 +
83 +#### Input Object
84 +
85 +Also it supports named jobs, listed via object.
86 +
87 +```javascript
88 +var parallel = require('asynckit/parallel')
89 + , assert = require('assert')
90 + ;
91 +
92 +var source = { first: 1, one: 1, four: 4, sixteen: 16, sixtyFour: 64, thirtyTwo: 32, eight: 8, two: 2 }
93 + , expectedResult = { first: 2, one: 2, four: 8, sixteen: 32, sixtyFour: 128, thirtyTwo: 64, eight: 16, two: 4 }
94 + , expectedTarget = [ 1, 1, 2, 4, 8, 16, 32, 64 ]
95 + , expectedKeys = [ 'first', 'one', 'two', 'four', 'eight', 'sixteen', 'thirtyTwo', 'sixtyFour' ]
96 + , target = []
97 + , keys = []
98 + ;
99 +
100 +parallel(source, asyncJob, function(err, result)
101 +{
102 + assert.deepEqual(result, expectedResult);
103 + assert.deepEqual(target, expectedTarget);
104 + assert.deepEqual(keys, expectedKeys);
105 +});
106 +
107 +// supports full value, key, callback (shortcut) interface
108 +function asyncJob(item, key, cb)
109 +{
110 + // different delays (in ms) per item
111 + var delay = item * 25;
112 +
113 + // pretend different jobs take different time to finish
114 + // and not in consequential order
115 + var timeoutId = setTimeout(function() {
116 + keys.push(key);
117 + target.push(item);
118 + cb(null, item * 2);
119 + }, delay);
120 +
121 + // allow to cancel "leftover" jobs upon error
122 + // return function, invoking of which will abort this job
123 + return clearTimeout.bind(null, timeoutId);
124 +}
125 +```
126 +
127 +More examples could be found in [test/test-parallel-object.js](test/test-parallel-object.js).
128 +
129 +### Serial Jobs
130 +
131 +Runs iterator over provided array sequentially. Stores output in the `result` array,
132 +on the matching positions. In unlikely event of an error from one of the jobs,
133 +will not proceed to the rest of the items in the list
134 +and return error along with salvaged data to the main callback function.
135 +
136 +#### Input Array
137 +
138 +```javascript
139 +var serial = require('asynckit/serial')
140 + , assert = require('assert')
141 + ;
142 +
143 +var source = [ 1, 1, 4, 16, 64, 32, 8, 2 ]
144 + , expectedResult = [ 2, 2, 8, 32, 128, 64, 16, 4 ]
145 + , expectedTarget = [ 0, 1, 2, 3, 4, 5, 6, 7 ]
146 + , target = []
147 + ;
148 +
149 +serial(source, asyncJob, function(err, result)
150 +{
151 + assert.deepEqual(result, expectedResult);
152 + assert.deepEqual(target, expectedTarget);
153 +});
154 +
155 +// extended interface (item, key, callback)
156 +// also supported for arrays
157 +function asyncJob(item, key, cb)
158 +{
159 + target.push(key);
160 +
161 + // it will be automatically made async
162 + // even it iterator "returns" in the same event loop
163 + cb(null, item * 2);
164 +}
165 +```
166 +
167 +More examples could be found in [test/test-serial-array.js](test/test-serial-array.js).
168 +
169 +#### Input Object
170 +
171 +Also it supports named jobs, listed via object.
172 +
173 +```javascript
174 +var serial = require('asynckit').serial
175 + , assert = require('assert')
176 + ;
177 +
178 +var source = [ 1, 1, 4, 16, 64, 32, 8, 2 ]
179 + , expectedResult = [ 2, 2, 8, 32, 128, 64, 16, 4 ]
180 + , expectedTarget = [ 0, 1, 2, 3, 4, 5, 6, 7 ]
181 + , target = []
182 + ;
183 +
184 +var source = { first: 1, one: 1, four: 4, sixteen: 16, sixtyFour: 64, thirtyTwo: 32, eight: 8, two: 2 }
185 + , expectedResult = { first: 2, one: 2, four: 8, sixteen: 32, sixtyFour: 128, thirtyTwo: 64, eight: 16, two: 4 }
186 + , expectedTarget = [ 1, 1, 4, 16, 64, 32, 8, 2 ]
187 + , target = []
188 + ;
189 +
190 +
191 +serial(source, asyncJob, function(err, result)
192 +{
193 + assert.deepEqual(result, expectedResult);
194 + assert.deepEqual(target, expectedTarget);
195 +});
196 +
197 +// shortcut interface (item, callback)
198 +// works for object as well as for the arrays
199 +function asyncJob(item, cb)
200 +{
201 + target.push(item);
202 +
203 + // it will be automatically made async
204 + // even it iterator "returns" in the same event loop
205 + cb(null, item * 2);
206 +}
207 +```
208 +
209 +More examples could be found in [test/test-serial-object.js](test/test-serial-object.js).
210 +
211 +_Note: Since _object_ is an _unordered_ collection of properties,
212 +it may produce unexpected results with sequential iterations.
213 +Whenever order of the jobs' execution is important please use `serialOrdered` method._
214 +
215 +### Ordered Serial Iterations
216 +
217 +TBD
218 +
219 +For example [compare-property](compare-property) package.
220 +
221 +### Streaming interface
222 +
223 +TBD
224 +
225 +## Want to Know More?
226 +
227 +More examples can be found in [test folder](test/).
228 +
229 +Or open an [issue](https://github.com/alexindigo/asynckit/issues) with questions and/or suggestions.
230 +
231 +## License
232 +
233 +AsyncKit is licensed under the MIT license.
1 +/* eslint no-console: "off" */
2 +
3 +var asynckit = require('./')
4 + , async = require('async')
5 + , assert = require('assert')
6 + , expected = 0
7 + ;
8 +
9 +var Benchmark = require('benchmark');
10 +var suite = new Benchmark.Suite;
11 +
12 +var source = [];
13 +for (var z = 1; z < 100; z++)
14 +{
15 + source.push(z);
16 + expected += z;
17 +}
18 +
19 +suite
20 +// add tests
21 +
22 +.add('async.map', function(deferred)
23 +{
24 + var total = 0;
25 +
26 + async.map(source,
27 + function(i, cb)
28 + {
29 + setImmediate(function()
30 + {
31 + total += i;
32 + cb(null, total);
33 + });
34 + },
35 + function(err, result)
36 + {
37 + assert.ifError(err);
38 + assert.equal(result[result.length - 1], expected);
39 + deferred.resolve();
40 + });
41 +}, {'defer': true})
42 +
43 +
44 +.add('asynckit.parallel', function(deferred)
45 +{
46 + var total = 0;
47 +
48 + asynckit.parallel(source,
49 + function(i, cb)
50 + {
51 + setImmediate(function()
52 + {
53 + total += i;
54 + cb(null, total);
55 + });
56 + },
57 + function(err, result)
58 + {
59 + assert.ifError(err);
60 + assert.equal(result[result.length - 1], expected);
61 + deferred.resolve();
62 + });
63 +}, {'defer': true})
64 +
65 +
66 +// add listeners
67 +.on('cycle', function(ev)
68 +{
69 + console.log(String(ev.target));
70 +})
71 +.on('complete', function()
72 +{
73 + console.log('Fastest is ' + this.filter('fastest').map('name'));
74 +})
75 +// run async
76 +.run({ 'async': true });
1 +module.exports =
2 +{
3 + parallel : require('./parallel.js'),
4 + serial : require('./serial.js'),
5 + serialOrdered : require('./serialOrdered.js')
6 +};
1 +// API
2 +module.exports = abort;
3 +
4 +/**
5 + * Aborts leftover active jobs
6 + *
7 + * @param {object} state - current state object
8 + */
9 +function abort(state)
10 +{
11 + Object.keys(state.jobs).forEach(clean.bind(state));
12 +
13 + // reset leftover jobs
14 + state.jobs = {};
15 +}
16 +
17 +/**
18 + * Cleans up leftover job by invoking abort function for the provided job id
19 + *
20 + * @this state
21 + * @param {string|number} key - job id to abort
22 + */
23 +function clean(key)
24 +{
25 + if (typeof this.jobs[key] == 'function')
26 + {
27 + this.jobs[key]();
28 + }
29 +}
1 +var defer = require('./defer.js');
2 +
3 +// API
4 +module.exports = async;
5 +
6 +/**
7 + * Runs provided callback asynchronously
8 + * even if callback itself is not
9 + *
10 + * @param {function} callback - callback to invoke
11 + * @returns {function} - augmented callback
12 + */
13 +function async(callback)
14 +{
15 + var isAsync = false;
16 +
17 + // check if async happened
18 + defer(function() { isAsync = true; });
19 +
20 + return function async_callback(err, result)
21 + {
22 + if (isAsync)
23 + {
24 + callback(err, result);
25 + }
26 + else
27 + {
28 + defer(function nextTick_callback()
29 + {
30 + callback(err, result);
31 + });
32 + }
33 + };
34 +}
1 +module.exports = defer;
2 +
3 +/**
4 + * Runs provided function on next iteration of the event loop
5 + *
6 + * @param {function} fn - function to run
7 + */
8 +function defer(fn)
9 +{
10 + var nextTick = typeof setImmediate == 'function'
11 + ? setImmediate
12 + : (
13 + typeof process == 'object' && typeof process.nextTick == 'function'
14 + ? process.nextTick
15 + : null
16 + );
17 +
18 + if (nextTick)
19 + {
20 + nextTick(fn);
21 + }
22 + else
23 + {
24 + setTimeout(fn, 0);
25 + }
26 +}
1 +var async = require('./async.js')
2 + , abort = require('./abort.js')
3 + ;
4 +
5 +// API
6 +module.exports = iterate;
7 +
8 +/**
9 + * Iterates over each job object
10 + *
11 + * @param {array|object} list - array or object (named list) to iterate over
12 + * @param {function} iterator - iterator to run
13 + * @param {object} state - current job status
14 + * @param {function} callback - invoked when all elements processed
15 + */
16 +function iterate(list, iterator, state, callback)
17 +{
18 + // store current index
19 + var key = state['keyedList'] ? state['keyedList'][state.index] : state.index;
20 +
21 + state.jobs[key] = runJob(iterator, key, list[key], function(error, output)
22 + {
23 + // don't repeat yourself
24 + // skip secondary callbacks
25 + if (!(key in state.jobs))
26 + {
27 + return;
28 + }
29 +
30 + // clean up jobs
31 + delete state.jobs[key];
32 +
33 + if (error)
34 + {
35 + // don't process rest of the results
36 + // stop still active jobs
37 + // and reset the list
38 + abort(state);
39 + }
40 + else
41 + {
42 + state.results[key] = output;
43 + }
44 +
45 + // return salvaged results
46 + callback(error, state.results);
47 + });
48 +}
49 +
50 +/**
51 + * Runs iterator over provided job element
52 + *
53 + * @param {function} iterator - iterator to invoke
54 + * @param {string|number} key - key/index of the element in the list of jobs
55 + * @param {mixed} item - job description
56 + * @param {function} callback - invoked after iterator is done with the job
57 + * @returns {function|mixed} - job abort function or something else
58 + */
59 +function runJob(iterator, key, item, callback)
60 +{
61 + var aborter;
62 +
63 + // allow shortcut if iterator expects only two arguments
64 + if (iterator.length == 2)
65 + {
66 + aborter = iterator(item, async(callback));
67 + }
68 + // otherwise go with full three arguments
69 + else
70 + {
71 + aborter = iterator(item, key, async(callback));
72 + }
73 +
74 + return aborter;
75 +}
1 +var streamify = require('./streamify.js')
2 + , defer = require('./defer.js')
3 + ;
4 +
5 +// API
6 +module.exports = ReadableAsyncKit;
7 +
8 +/**
9 + * Base constructor for all streams
10 + * used to hold properties/methods
11 + */
12 +function ReadableAsyncKit()
13 +{
14 + ReadableAsyncKit.super_.apply(this, arguments);
15 +
16 + // list of active jobs
17 + this.jobs = {};
18 +
19 + // add stream methods
20 + this.destroy = destroy;
21 + this._start = _start;
22 + this._read = _read;
23 +}
24 +
25 +/**
26 + * Destroys readable stream,
27 + * by aborting outstanding jobs
28 + *
29 + * @returns {void}
30 + */
31 +function destroy()
32 +{
33 + if (this.destroyed)
34 + {
35 + return;
36 + }
37 +
38 + this.destroyed = true;
39 +
40 + if (typeof this.terminator == 'function')
41 + {
42 + this.terminator();
43 + }
44 +}
45 +
46 +/**
47 + * Starts provided jobs in async manner
48 + *
49 + * @private
50 + */
51 +function _start()
52 +{
53 + // first argument – runner function
54 + var runner = arguments[0]
55 + // take away first argument
56 + , args = Array.prototype.slice.call(arguments, 1)
57 + // second argument - input data
58 + , input = args[0]
59 + // last argument - result callback
60 + , endCb = streamify.callback.call(this, args[args.length - 1])
61 + ;
62 +
63 + args[args.length - 1] = endCb;
64 + // third argument - iterator
65 + args[1] = streamify.iterator.call(this, args[1]);
66 +
67 + // allow time for proper setup
68 + defer(function()
69 + {
70 + if (!this.destroyed)
71 + {
72 + this.terminator = runner.apply(null, args);
73 + }
74 + else
75 + {
76 + endCb(null, Array.isArray(input) ? [] : {});
77 + }
78 + }.bind(this));
79 +}
80 +
81 +
82 +/**
83 + * Implement _read to comply with Readable streams
84 + * Doesn't really make sense for flowing object mode
85 + *
86 + * @private
87 + */
88 +function _read()
89 +{
90 +
91 +}
1 +var parallel = require('../parallel.js');
2 +
3 +// API
4 +module.exports = ReadableParallel;
5 +
6 +/**
7 + * Streaming wrapper to `asynckit.parallel`
8 + *
9 + * @param {array|object} list - array or object (named list) to iterate over
10 + * @param {function} iterator - iterator to run
11 + * @param {function} callback - invoked when all elements processed
12 + * @returns {stream.Readable#}
13 + */
14 +function ReadableParallel(list, iterator, callback)
15 +{
16 + if (!(this instanceof ReadableParallel))
17 + {
18 + return new ReadableParallel(list, iterator, callback);
19 + }
20 +
21 + // turn on object mode
22 + ReadableParallel.super_.call(this, {objectMode: true});
23 +
24 + this._start(parallel, list, iterator, callback);
25 +}
1 +var serial = require('../serial.js');
2 +
3 +// API
4 +module.exports = ReadableSerial;
5 +
6 +/**
7 + * Streaming wrapper to `asynckit.serial`
8 + *
9 + * @param {array|object} list - array or object (named list) to iterate over
10 + * @param {function} iterator - iterator to run
11 + * @param {function} callback - invoked when all elements processed
12 + * @returns {stream.Readable#}
13 + */
14 +function ReadableSerial(list, iterator, callback)
15 +{
16 + if (!(this instanceof ReadableSerial))
17 + {
18 + return new ReadableSerial(list, iterator, callback);
19 + }
20 +
21 + // turn on object mode
22 + ReadableSerial.super_.call(this, {objectMode: true});
23 +
24 + this._start(serial, list, iterator, callback);
25 +}
1 +var serialOrdered = require('../serialOrdered.js');
2 +
3 +// API
4 +module.exports = ReadableSerialOrdered;
5 +// expose sort helpers
6 +module.exports.ascending = serialOrdered.ascending;
7 +module.exports.descending = serialOrdered.descending;
8 +
9 +/**
10 + * Streaming wrapper to `asynckit.serialOrdered`
11 + *
12 + * @param {array|object} list - array or object (named list) to iterate over
13 + * @param {function} iterator - iterator to run
14 + * @param {function} sortMethod - custom sort function
15 + * @param {function} callback - invoked when all elements processed
16 + * @returns {stream.Readable#}
17 + */
18 +function ReadableSerialOrdered(list, iterator, sortMethod, callback)
19 +{
20 + if (!(this instanceof ReadableSerialOrdered))
21 + {
22 + return new ReadableSerialOrdered(list, iterator, sortMethod, callback);
23 + }
24 +
25 + // turn on object mode
26 + ReadableSerialOrdered.super_.call(this, {objectMode: true});
27 +
28 + this._start(serialOrdered, list, iterator, sortMethod, callback);
29 +}
1 +// API
2 +module.exports = state;
3 +
4 +/**
5 + * Creates initial state object
6 + * for iteration over list
7 + *
8 + * @param {array|object} list - list to iterate over
9 + * @param {function|null} sortMethod - function to use for keys sort,
10 + * or `null` to keep them as is
11 + * @returns {object} - initial state object
12 + */
13 +function state(list, sortMethod)
14 +{
15 + var isNamedList = !Array.isArray(list)
16 + , initState =
17 + {
18 + index : 0,
19 + keyedList: isNamedList || sortMethod ? Object.keys(list) : null,
20 + jobs : {},
21 + results : isNamedList ? {} : [],
22 + size : isNamedList ? Object.keys(list).length : list.length
23 + }
24 + ;
25 +
26 + if (sortMethod)
27 + {
28 + // sort array keys based on it's values
29 + // sort object's keys just on own merit
30 + initState.keyedList.sort(isNamedList ? sortMethod : function(a, b)
31 + {
32 + return sortMethod(list[a], list[b]);
33 + });
34 + }
35 +
36 + return initState;
37 +}
1 +var async = require('./async.js');
2 +
3 +// API
4 +module.exports = {
5 + iterator: wrapIterator,
6 + callback: wrapCallback
7 +};
8 +
9 +/**
10 + * Wraps iterators with long signature
11 + *
12 + * @this ReadableAsyncKit#
13 + * @param {function} iterator - function to wrap
14 + * @returns {function} - wrapped function
15 + */
16 +function wrapIterator(iterator)
17 +{
18 + var stream = this;
19 +
20 + return function(item, key, cb)
21 + {
22 + var aborter
23 + , wrappedCb = async(wrapIteratorCallback.call(stream, cb, key))
24 + ;
25 +
26 + stream.jobs[key] = wrappedCb;
27 +
28 + // it's either shortcut (item, cb)
29 + if (iterator.length == 2)
30 + {
31 + aborter = iterator(item, wrappedCb);
32 + }
33 + // or long format (item, key, cb)
34 + else
35 + {
36 + aborter = iterator(item, key, wrappedCb);
37 + }
38 +
39 + return aborter;
40 + };
41 +}
42 +
43 +/**
44 + * Wraps provided callback function
45 + * allowing to execute snitch function before
46 + * real callback
47 + *
48 + * @this ReadableAsyncKit#
49 + * @param {function} callback - function to wrap
50 + * @returns {function} - wrapped function
51 + */
52 +function wrapCallback(callback)
53 +{
54 + var stream = this;
55 +
56 + var wrapped = function(error, result)
57 + {
58 + return finisher.call(stream, error, result, callback);
59 + };
60 +
61 + return wrapped;
62 +}
63 +
64 +/**
65 + * Wraps provided iterator callback function
66 + * makes sure snitch only called once,
67 + * but passes secondary calls to the original callback
68 + *
69 + * @this ReadableAsyncKit#
70 + * @param {function} callback - callback to wrap
71 + * @param {number|string} key - iteration key
72 + * @returns {function} wrapped callback
73 + */
74 +function wrapIteratorCallback(callback, key)
75 +{
76 + var stream = this;
77 +
78 + return function(error, output)
79 + {
80 + // don't repeat yourself
81 + if (!(key in stream.jobs))
82 + {
83 + callback(error, output);
84 + return;
85 + }
86 +
87 + // clean up jobs
88 + delete stream.jobs[key];
89 +
90 + return streamer.call(stream, error, {key: key, value: output}, callback);
91 + };
92 +}
93 +
94 +/**
95 + * Stream wrapper for iterator callback
96 + *
97 + * @this ReadableAsyncKit#
98 + * @param {mixed} error - error response
99 + * @param {mixed} output - iterator output
100 + * @param {function} callback - callback that expects iterator results
101 + */
102 +function streamer(error, output, callback)
103 +{
104 + if (error && !this.error)
105 + {
106 + this.error = error;
107 + this.pause();
108 + this.emit('error', error);
109 + // send back value only, as expected
110 + callback(error, output && output.value);
111 + return;
112 + }
113 +
114 + // stream stuff
115 + this.push(output);
116 +
117 + // back to original track
118 + // send back value only, as expected
119 + callback(error, output && output.value);
120 +}
121 +
122 +/**
123 + * Stream wrapper for finishing callback
124 + *
125 + * @this ReadableAsyncKit#
126 + * @param {mixed} error - error response
127 + * @param {mixed} output - iterator output
128 + * @param {function} callback - callback that expects final results
129 + */
130 +function finisher(error, output, callback)
131 +{
132 + // signal end of the stream
133 + // only for successfully finished streams
134 + if (!error)
135 + {
136 + this.push(null);
137 + }
138 +
139 + // back to original track
140 + callback(error, output);
141 +}
1 +var abort = require('./abort.js')
2 + , async = require('./async.js')
3 + ;
4 +
5 +// API
6 +module.exports = terminator;
7 +
8 +/**
9 + * Terminates jobs in the attached state context
10 + *
11 + * @this AsyncKitState#
12 + * @param {function} callback - final callback to invoke after termination
13 + */
14 +function terminator(callback)
15 +{
16 + if (!Object.keys(this.jobs).length)
17 + {
18 + return;
19 + }
20 +
21 + // fast forward iteration index
22 + this.index = this.size;
23 +
24 + // abort jobs
25 + abort(this);
26 +
27 + // send back results we have so far
28 + async(callback)(null, this.results);
29 +}
1 +{
2 + "name": "asynckit",
3 + "version": "0.4.0",
4 + "description": "Minimal async jobs utility library, with streams support",
5 + "main": "index.js",
6 + "scripts": {
7 + "clean": "rimraf coverage",
8 + "lint": "eslint *.js lib/*.js test/*.js",
9 + "test": "istanbul cover --reporter=json tape -- 'test/test-*.js' | tap-spec",
10 + "win-test": "tape test/test-*.js",
11 + "browser": "browserify -t browserify-istanbul test/lib/browserify_adjustment.js test/test-*.js | obake --coverage | tap-spec",
12 + "report": "istanbul report",
13 + "size": "browserify index.js | size-table asynckit",
14 + "debug": "tape test/test-*.js"
15 + },
16 + "pre-commit": [
17 + "clean",
18 + "lint",
19 + "test",
20 + "browser",
21 + "report",
22 + "size"
23 + ],
24 + "repository": {
25 + "type": "git",
26 + "url": "git+https://github.com/alexindigo/asynckit.git"
27 + },
28 + "keywords": [
29 + "async",
30 + "jobs",
31 + "parallel",
32 + "serial",
33 + "iterator",
34 + "array",
35 + "object",
36 + "stream",
37 + "destroy",
38 + "terminate",
39 + "abort"
40 + ],
41 + "author": "Alex Indigo <iam@alexindigo.com>",
42 + "license": "MIT",
43 + "bugs": {
44 + "url": "https://github.com/alexindigo/asynckit/issues"
45 + },
46 + "homepage": "https://github.com/alexindigo/asynckit#readme",
47 + "devDependencies": {
48 + "browserify": "^13.0.0",
49 + "browserify-istanbul": "^2.0.0",
50 + "coveralls": "^2.11.9",
51 + "eslint": "^2.9.0",
52 + "istanbul": "^0.4.3",
53 + "obake": "^0.1.2",
54 + "phantomjs-prebuilt": "^2.1.7",
55 + "pre-commit": "^1.1.3",
56 + "reamde": "^1.1.0",
57 + "rimraf": "^2.5.2",
58 + "size-table": "^0.2.0",
59 + "tap-spec": "^4.1.1",
60 + "tape": "^4.5.1"
61 + },
62 + "dependencies": {}
63 +}
1 +var iterate = require('./lib/iterate.js')
2 + , initState = require('./lib/state.js')
3 + , terminator = require('./lib/terminator.js')
4 + ;
5 +
6 +// Public API
7 +module.exports = parallel;
8 +
9 +/**
10 + * Runs iterator over provided array elements in parallel
11 + *
12 + * @param {array|object} list - array or object (named list) to iterate over
13 + * @param {function} iterator - iterator to run
14 + * @param {function} callback - invoked when all elements processed
15 + * @returns {function} - jobs terminator
16 + */
17 +function parallel(list, iterator, callback)
18 +{
19 + var state = initState(list);
20 +
21 + while (state.index < (state['keyedList'] || list).length)
22 + {
23 + iterate(list, iterator, state, function(error, result)
24 + {
25 + if (error)
26 + {
27 + callback(error, result);
28 + return;
29 + }
30 +
31 + // looks like it's the last one
32 + if (Object.keys(state.jobs).length === 0)
33 + {
34 + callback(null, state.results);
35 + return;
36 + }
37 + });
38 +
39 + state.index++;
40 + }
41 +
42 + return terminator.bind(state, callback);
43 +}
1 +var serialOrdered = require('./serialOrdered.js');
2 +
3 +// Public API
4 +module.exports = serial;
5 +
6 +/**
7 + * Runs iterator over provided array elements in series
8 + *
9 + * @param {array|object} list - array or object (named list) to iterate over
10 + * @param {function} iterator - iterator to run
11 + * @param {function} callback - invoked when all elements processed
12 + * @returns {function} - jobs terminator
13 + */
14 +function serial(list, iterator, callback)
15 +{
16 + return serialOrdered(list, iterator, null, callback);
17 +}
1 +var iterate = require('./lib/iterate.js')
2 + , initState = require('./lib/state.js')
3 + , terminator = require('./lib/terminator.js')
4 + ;
5 +
6 +// Public API
7 +module.exports = serialOrdered;
8 +// sorting helpers
9 +module.exports.ascending = ascending;
10 +module.exports.descending = descending;
11 +
12 +/**
13 + * Runs iterator over provided sorted array elements in series
14 + *
15 + * @param {array|object} list - array or object (named list) to iterate over
16 + * @param {function} iterator - iterator to run
17 + * @param {function} sortMethod - custom sort function
18 + * @param {function} callback - invoked when all elements processed
19 + * @returns {function} - jobs terminator
20 + */
21 +function serialOrdered(list, iterator, sortMethod, callback)
22 +{
23 + var state = initState(list, sortMethod);
24 +
25 + iterate(list, iterator, state, function iteratorHandler(error, result)
26 + {
27 + if (error)
28 + {
29 + callback(error, result);
30 + return;
31 + }
32 +
33 + state.index++;
34 +
35 + // are we there yet?
36 + if (state.index < (state['keyedList'] || list).length)
37 + {
38 + iterate(list, iterator, state, iteratorHandler);
39 + return;
40 + }
41 +
42 + // done here
43 + callback(null, state.results);
44 + });
45 +
46 + return terminator.bind(state, callback);
47 +}
48 +
49 +/*
50 + * -- Sort methods
51 + */
52 +
53 +/**
54 + * sort helper to sort array elements in ascending order
55 + *
56 + * @param {mixed} a - an item to compare
57 + * @param {mixed} b - an item to compare
58 + * @returns {number} - comparison result
59 + */
60 +function ascending(a, b)
61 +{
62 + return a < b ? -1 : a > b ? 1 : 0;
63 +}
64 +
65 +/**
66 + * sort helper to sort array elements in descending order
67 + *
68 + * @param {mixed} a - an item to compare
69 + * @param {mixed} b - an item to compare
70 + * @returns {number} - comparison result
71 + */
72 +function descending(a, b)
73 +{
74 + return -1 * ascending(a, b);
75 +}
1 +var inherits = require('util').inherits
2 + , Readable = require('stream').Readable
3 + , ReadableAsyncKit = require('./lib/readable_asynckit.js')
4 + , ReadableParallel = require('./lib/readable_parallel.js')
5 + , ReadableSerial = require('./lib/readable_serial.js')
6 + , ReadableSerialOrdered = require('./lib/readable_serial_ordered.js')
7 + ;
8 +
9 +// API
10 +module.exports =
11 +{
12 + parallel : ReadableParallel,
13 + serial : ReadableSerial,
14 + serialOrdered : ReadableSerialOrdered,
15 +};
16 +
17 +inherits(ReadableAsyncKit, Readable);
18 +
19 +inherits(ReadableParallel, ReadableAsyncKit);
20 +inherits(ReadableSerial, ReadableAsyncKit);
21 +inherits(ReadableSerialOrdered, ReadableAsyncKit);
1 +Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
2 +
3 +Permission is hereby granted, free of charge, to any person obtaining a copy
4 +of this software and associated documentation files (the "Software"), to deal
5 +in the Software without restriction, including without limitation the rights
6 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 +copies of the Software, and to permit persons to whom the Software is
8 +furnished to do so, subject to the following conditions:
9 +
10 +The above copyright notice and this permission notice shall be included in
11 +all copies or substantial portions of the Software.
12 +
13 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 +THE SOFTWARE.
1 +# combined-stream
2 +
3 +A stream that emits multiple other streams one after another.
4 +
5 +**NB** Currently `combined-stream` works with streams version 1 only. There is ongoing effort to switch this library to streams version 2. Any help is welcome. :) Meanwhile you can explore other libraries that provide streams2 support with more or less compatibility with `combined-stream`.
6 +
7 +- [combined-stream2](https://www.npmjs.com/package/combined-stream2): A drop-in streams2-compatible replacement for the combined-stream module.
8 +
9 +- [multistream](https://www.npmjs.com/package/multistream): A stream that emits multiple other streams one after another.
10 +
11 +## Installation
12 +
13 +``` bash
14 +npm install combined-stream
15 +```
16 +
17 +## Usage
18 +
19 +Here is a simple example that shows how you can use combined-stream to combine
20 +two files into one:
21 +
22 +``` javascript
23 +var CombinedStream = require('combined-stream');
24 +var fs = require('fs');
25 +
26 +var combinedStream = CombinedStream.create();
27 +combinedStream.append(fs.createReadStream('file1.txt'));
28 +combinedStream.append(fs.createReadStream('file2.txt'));
29 +
30 +combinedStream.pipe(fs.createWriteStream('combined.txt'));
31 +```
32 +
33 +While the example above works great, it will pause all source streams until
34 +they are needed. If you don't want that to happen, you can set `pauseStreams`
35 +to `false`:
36 +
37 +``` javascript
38 +var CombinedStream = require('combined-stream');
39 +var fs = require('fs');
40 +
41 +var combinedStream = CombinedStream.create({pauseStreams: false});
42 +combinedStream.append(fs.createReadStream('file1.txt'));
43 +combinedStream.append(fs.createReadStream('file2.txt'));
44 +
45 +combinedStream.pipe(fs.createWriteStream('combined.txt'));
46 +```
47 +
48 +However, what if you don't have all the source streams yet, or you don't want
49 +to allocate the resources (file descriptors, memory, etc.) for them right away?
50 +Well, in that case you can simply provide a callback that supplies the stream
51 +by calling a `next()` function:
52 +
53 +``` javascript
54 +var CombinedStream = require('combined-stream');
55 +var fs = require('fs');
56 +
57 +var combinedStream = CombinedStream.create();
58 +combinedStream.append(function(next) {
59 + next(fs.createReadStream('file1.txt'));
60 +});
61 +combinedStream.append(function(next) {
62 + next(fs.createReadStream('file2.txt'));
63 +});
64 +
65 +combinedStream.pipe(fs.createWriteStream('combined.txt'));
66 +```
67 +
68 +## API
69 +
70 +### CombinedStream.create([options])
71 +
72 +Returns a new combined stream object. Available options are:
73 +
74 +* `maxDataSize`
75 +* `pauseStreams`
76 +
77 +The effect of those options is described below.
78 +
79 +### combinedStream.pauseStreams = `true`
80 +
81 +Whether to apply back pressure to the underlaying streams. If set to `false`,
82 +the underlaying streams will never be paused. If set to `true`, the
83 +underlaying streams will be paused right after being appended, as well as when
84 +`delayedStream.pipe()` wants to throttle.
85 +
86 +### combinedStream.maxDataSize = `2 * 1024 * 1024`
87 +
88 +The maximum amount of bytes (or characters) to buffer for all source streams.
89 +If this value is exceeded, `combinedStream` emits an `'error'` event.
90 +
91 +### combinedStream.dataSize = `0`
92 +
93 +The amount of bytes (or characters) currently buffered by `combinedStream`.
94 +
95 +### combinedStream.append(stream)
96 +
97 +Appends the given `stream` to the combinedStream object. If `pauseStreams` is
98 +set to `true, this stream will also be paused right away.
99 +
100 +`streams` can also be a function that takes one parameter called `next`. `next`
101 +is a function that must be invoked in order to provide the `next` stream, see
102 +example above.
103 +
104 +Regardless of how the `stream` is appended, combined-stream always attaches an
105 +`'error'` listener to it, so you don't have to do that manually.
106 +
107 +Special case: `stream` can also be a String or Buffer.
108 +
109 +### combinedStream.write(data)
110 +
111 +You should not call this, `combinedStream` takes care of piping the appended
112 +streams into itself for you.
113 +
114 +### combinedStream.resume()
115 +
116 +Causes `combinedStream` to start drain the streams it manages. The function is
117 +idempotent, and also emits a `'resume'` event each time which usually goes to
118 +the stream that is currently being drained.
119 +
120 +### combinedStream.pause();
121 +
122 +If `combinedStream.pauseStreams` is set to `false`, this does nothing.
123 +Otherwise a `'pause'` event is emitted, this goes to the stream that is
124 +currently being drained, so you can use it to apply back pressure.
125 +
126 +### combinedStream.end();
127 +
128 +Sets `combinedStream.writable` to false, emits an `'end'` event, and removes
129 +all streams from the queue.
130 +
131 +### combinedStream.destroy();
132 +
133 +Same as `combinedStream.end()`, except it emits a `'close'` event instead of
134 +`'end'`.
135 +
136 +## License
137 +
138 +combined-stream is licensed under the MIT license.
1 +var util = require('util');
2 +var Stream = require('stream').Stream;
3 +var DelayedStream = require('delayed-stream');
4 +
5 +module.exports = CombinedStream;
6 +function CombinedStream() {
7 + this.writable = false;
8 + this.readable = true;
9 + this.dataSize = 0;
10 + this.maxDataSize = 2 * 1024 * 1024;
11 + this.pauseStreams = true;
12 +
13 + this._released = false;
14 + this._streams = [];
15 + this._currentStream = null;
16 + this._insideLoop = false;
17 + this._pendingNext = false;
18 +}
19 +util.inherits(CombinedStream, Stream);
20 +
21 +CombinedStream.create = function(options) {
22 + var combinedStream = new this();
23 +
24 + options = options || {};
25 + for (var option in options) {
26 + combinedStream[option] = options[option];
27 + }
28 +
29 + return combinedStream;
30 +};
31 +
32 +CombinedStream.isStreamLike = function(stream) {
33 + return (typeof stream !== 'function')
34 + && (typeof stream !== 'string')
35 + && (typeof stream !== 'boolean')
36 + && (typeof stream !== 'number')
37 + && (!Buffer.isBuffer(stream));
38 +};
39 +
40 +CombinedStream.prototype.append = function(stream) {
41 + var isStreamLike = CombinedStream.isStreamLike(stream);
42 +
43 + if (isStreamLike) {
44 + if (!(stream instanceof DelayedStream)) {
45 + var newStream = DelayedStream.create(stream, {
46 + maxDataSize: Infinity,
47 + pauseStream: this.pauseStreams,
48 + });
49 + stream.on('data', this._checkDataSize.bind(this));
50 + stream = newStream;
51 + }
52 +
53 + this._handleErrors(stream);
54 +
55 + if (this.pauseStreams) {
56 + stream.pause();
57 + }
58 + }
59 +
60 + this._streams.push(stream);
61 + return this;
62 +};
63 +
64 +CombinedStream.prototype.pipe = function(dest, options) {
65 + Stream.prototype.pipe.call(this, dest, options);
66 + this.resume();
67 + return dest;
68 +};
69 +
70 +CombinedStream.prototype._getNext = function() {
71 + this._currentStream = null;
72 +
73 + if (this._insideLoop) {
74 + this._pendingNext = true;
75 + return; // defer call
76 + }
77 +
78 + this._insideLoop = true;
79 + try {
80 + do {
81 + this._pendingNext = false;
82 + this._realGetNext();
83 + } while (this._pendingNext);
84 + } finally {
85 + this._insideLoop = false;
86 + }
87 +};
88 +
89 +CombinedStream.prototype._realGetNext = function() {
90 + var stream = this._streams.shift();
91 +
92 +
93 + if (typeof stream == 'undefined') {
94 + this.end();
95 + return;
96 + }
97 +
98 + if (typeof stream !== 'function') {
99 + this._pipeNext(stream);
100 + return;
101 + }
102 +
103 + var getStream = stream;
104 + getStream(function(stream) {
105 + var isStreamLike = CombinedStream.isStreamLike(stream);
106 + if (isStreamLike) {
107 + stream.on('data', this._checkDataSize.bind(this));
108 + this._handleErrors(stream);
109 + }
110 +
111 + this._pipeNext(stream);
112 + }.bind(this));
113 +};
114 +
115 +CombinedStream.prototype._pipeNext = function(stream) {
116 + this._currentStream = stream;
117 +
118 + var isStreamLike = CombinedStream.isStreamLike(stream);
119 + if (isStreamLike) {
120 + stream.on('end', this._getNext.bind(this));
121 + stream.pipe(this, {end: false});
122 + return;
123 + }
124 +
125 + var value = stream;
126 + this.write(value);
127 + this._getNext();
128 +};
129 +
130 +CombinedStream.prototype._handleErrors = function(stream) {
131 + var self = this;
132 + stream.on('error', function(err) {
133 + self._emitError(err);
134 + });
135 +};
136 +
137 +CombinedStream.prototype.write = function(data) {
138 + this.emit('data', data);
139 +};
140 +
141 +CombinedStream.prototype.pause = function() {
142 + if (!this.pauseStreams) {
143 + return;
144 + }
145 +
146 + if(this.pauseStreams && this._currentStream && typeof(this._currentStream.pause) == 'function') this._currentStream.pause();
147 + this.emit('pause');
148 +};
149 +
150 +CombinedStream.prototype.resume = function() {
151 + if (!this._released) {
152 + this._released = true;
153 + this.writable = true;
154 + this._getNext();
155 + }
156 +
157 + if(this.pauseStreams && this._currentStream && typeof(this._currentStream.resume) == 'function') this._currentStream.resume();
158 + this.emit('resume');
159 +};
160 +
161 +CombinedStream.prototype.end = function() {
162 + this._reset();
163 + this.emit('end');
164 +};
165 +
166 +CombinedStream.prototype.destroy = function() {
167 + this._reset();
168 + this.emit('close');
169 +};
170 +
171 +CombinedStream.prototype._reset = function() {
172 + this.writable = false;
173 + this._streams = [];
174 + this._currentStream = null;
175 +};
176 +
177 +CombinedStream.prototype._checkDataSize = function() {
178 + this._updateDataSize();
179 + if (this.dataSize <= this.maxDataSize) {
180 + return;
181 + }
182 +
183 + var message =
184 + 'DelayedStream#maxDataSize of ' + this.maxDataSize + ' bytes exceeded.';
185 + this._emitError(new Error(message));
186 +};
187 +
188 +CombinedStream.prototype._updateDataSize = function() {
189 + this.dataSize = 0;
190 +
191 + var self = this;
192 + this._streams.forEach(function(stream) {
193 + if (!stream.dataSize) {
194 + return;
195 + }
196 +
197 + self.dataSize += stream.dataSize;
198 + });
199 +
200 + if (this._currentStream && this._currentStream.dataSize) {
201 + this.dataSize += this._currentStream.dataSize;
202 + }
203 +};
204 +
205 +CombinedStream.prototype._emitError = function(err) {
206 + this._reset();
207 + this.emit('error', err);
208 +};
1 +{
2 + "author": "Felix Geisendörfer <felix@debuggable.com> (http://debuggable.com/)",
3 + "name": "combined-stream",
4 + "description": "A stream that emits multiple other streams one after another.",
5 + "version": "1.0.8",
6 + "homepage": "https://github.com/felixge/node-combined-stream",
7 + "repository": {
8 + "type": "git",
9 + "url": "git://github.com/felixge/node-combined-stream.git"
10 + },
11 + "main": "./lib/combined_stream",
12 + "scripts": {
13 + "test": "node test/run.js"
14 + },
15 + "engines": {
16 + "node": ">= 0.8"
17 + },
18 + "dependencies": {
19 + "delayed-stream": "~1.0.0"
20 + },
21 + "devDependencies": {
22 + "far": "~0.0.7"
23 + },
24 + "license": "MIT"
25 +}
1 +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 +# yarn lockfile v1
3 +
4 +
5 +delayed-stream@~1.0.0:
6 + version "1.0.0"
7 + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
8 +
9 +far@~0.0.7:
10 + version "0.0.7"
11 + resolved "https://registry.yarnpkg.com/far/-/far-0.0.7.tgz#01c1fd362bcd26ce9cf161af3938aa34619f79a7"
12 + dependencies:
13 + oop "0.0.3"
14 +
15 +oop@0.0.3:
16 + version "0.0.3"
17 + resolved "https://registry.yarnpkg.com/oop/-/oop-0.0.3.tgz#70fa405a5650891a194fdc82ca68dad6dabf4401"
1 +Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
2 +
3 +Permission is hereby granted, free of charge, to any person obtaining a copy
4 +of this software and associated documentation files (the "Software"), to deal
5 +in the Software without restriction, including without limitation the rights
6 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 +copies of the Software, and to permit persons to whom the Software is
8 +furnished to do so, subject to the following conditions:
9 +
10 +The above copyright notice and this permission notice shall be included in
11 +all copies or substantial portions of the Software.
12 +
13 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 +THE SOFTWARE.
1 +SHELL := /bin/bash
2 +
3 +test:
4 + @./test/run.js
5 +
6 +.PHONY: test
7 +
1 +# delayed-stream
2 +
3 +Buffers events from a stream until you are ready to handle them.
4 +
5 +## Installation
6 +
7 +``` bash
8 +npm install delayed-stream
9 +```
10 +
11 +## Usage
12 +
13 +The following example shows how to write a http echo server that delays its
14 +response by 1000 ms.
15 +
16 +``` javascript
17 +var DelayedStream = require('delayed-stream');
18 +var http = require('http');
19 +
20 +http.createServer(function(req, res) {
21 + var delayed = DelayedStream.create(req);
22 +
23 + setTimeout(function() {
24 + res.writeHead(200);
25 + delayed.pipe(res);
26 + }, 1000);
27 +});
28 +```
29 +
30 +If you are not using `Stream#pipe`, you can also manually release the buffered
31 +events by calling `delayedStream.resume()`:
32 +
33 +``` javascript
34 +var delayed = DelayedStream.create(req);
35 +
36 +setTimeout(function() {
37 + // Emit all buffered events and resume underlaying source
38 + delayed.resume();
39 +}, 1000);
40 +```
41 +
42 +## Implementation
43 +
44 +In order to use this meta stream properly, here are a few things you should
45 +know about the implementation.
46 +
47 +### Event Buffering / Proxying
48 +
49 +All events of the `source` stream are hijacked by overwriting the `source.emit`
50 +method. Until node implements a catch-all event listener, this is the only way.
51 +
52 +However, delayed-stream still continues to emit all events it captures on the
53 +`source`, regardless of whether you have released the delayed stream yet or
54 +not.
55 +
56 +Upon creation, delayed-stream captures all `source` events and stores them in
57 +an internal event buffer. Once `delayedStream.release()` is called, all
58 +buffered events are emitted on the `delayedStream`, and the event buffer is
59 +cleared. After that, delayed-stream merely acts as a proxy for the underlaying
60 +source.
61 +
62 +### Error handling
63 +
64 +Error events on `source` are buffered / proxied just like any other events.
65 +However, `delayedStream.create` attaches a no-op `'error'` listener to the
66 +`source`. This way you only have to handle errors on the `delayedStream`
67 +object, rather than in two places.
68 +
69 +### Buffer limits
70 +
71 +delayed-stream provides a `maxDataSize` property that can be used to limit
72 +the amount of data being buffered. In order to protect you from bad `source`
73 +streams that don't react to `source.pause()`, this feature is enabled by
74 +default.
75 +
76 +## API
77 +
78 +### DelayedStream.create(source, [options])
79 +
80 +Returns a new `delayedStream`. Available options are:
81 +
82 +* `pauseStream`
83 +* `maxDataSize`
84 +
85 +The description for those properties can be found below.
86 +
87 +### delayedStream.source
88 +
89 +The `source` stream managed by this object. This is useful if you are
90 +passing your `delayedStream` around, and you still want to access properties
91 +on the `source` object.
92 +
93 +### delayedStream.pauseStream = true
94 +
95 +Whether to pause the underlaying `source` when calling
96 +`DelayedStream.create()`. Modifying this property afterwards has no effect.
97 +
98 +### delayedStream.maxDataSize = 1024 * 1024
99 +
100 +The amount of data to buffer before emitting an `error`.
101 +
102 +If the underlaying source is emitting `Buffer` objects, the `maxDataSize`
103 +refers to bytes.
104 +
105 +If the underlaying source is emitting JavaScript strings, the size refers to
106 +characters.
107 +
108 +If you know what you are doing, you can set this property to `Infinity` to
109 +disable this feature. You can also modify this property during runtime.
110 +
111 +### delayedStream.dataSize = 0
112 +
113 +The amount of data buffered so far.
114 +
115 +### delayedStream.readable
116 +
117 +An ECMA5 getter that returns the value of `source.readable`.
118 +
119 +### delayedStream.resume()
120 +
121 +If the `delayedStream` has not been released so far, `delayedStream.release()`
122 +is called.
123 +
124 +In either case, `source.resume()` is called.
125 +
126 +### delayedStream.pause()
127 +
128 +Calls `source.pause()`.
129 +
130 +### delayedStream.pipe(dest)
131 +
132 +Calls `delayedStream.resume()` and then proxies the arguments to `source.pipe`.
133 +
134 +### delayedStream.release()
135 +
136 +Emits and clears all events that have been buffered up so far. This does not
137 +resume the underlaying source, use `delayedStream.resume()` instead.
138 +
139 +## License
140 +
141 +delayed-stream is licensed under the MIT license.
1 +var Stream = require('stream').Stream;
2 +var util = require('util');
3 +
4 +module.exports = DelayedStream;
5 +function DelayedStream() {
6 + this.source = null;
7 + this.dataSize = 0;
8 + this.maxDataSize = 1024 * 1024;
9 + this.pauseStream = true;
10 +
11 + this._maxDataSizeExceeded = false;
12 + this._released = false;
13 + this._bufferedEvents = [];
14 +}
15 +util.inherits(DelayedStream, Stream);
16 +
17 +DelayedStream.create = function(source, options) {
18 + var delayedStream = new this();
19 +
20 + options = options || {};
21 + for (var option in options) {
22 + delayedStream[option] = options[option];
23 + }
24 +
25 + delayedStream.source = source;
26 +
27 + var realEmit = source.emit;
28 + source.emit = function() {
29 + delayedStream._handleEmit(arguments);
30 + return realEmit.apply(source, arguments);
31 + };
32 +
33 + source.on('error', function() {});
34 + if (delayedStream.pauseStream) {
35 + source.pause();
36 + }
37 +
38 + return delayedStream;
39 +};
40 +
41 +Object.defineProperty(DelayedStream.prototype, 'readable', {
42 + configurable: true,
43 + enumerable: true,
44 + get: function() {
45 + return this.source.readable;
46 + }
47 +});
48 +
49 +DelayedStream.prototype.setEncoding = function() {
50 + return this.source.setEncoding.apply(this.source, arguments);
51 +};
52 +
53 +DelayedStream.prototype.resume = function() {
54 + if (!this._released) {
55 + this.release();
56 + }
57 +
58 + this.source.resume();
59 +};
60 +
61 +DelayedStream.prototype.pause = function() {
62 + this.source.pause();
63 +};
64 +
65 +DelayedStream.prototype.release = function() {
66 + this._released = true;
67 +
68 + this._bufferedEvents.forEach(function(args) {
69 + this.emit.apply(this, args);
70 + }.bind(this));
71 + this._bufferedEvents = [];
72 +};
73 +
74 +DelayedStream.prototype.pipe = function() {
75 + var r = Stream.prototype.pipe.apply(this, arguments);
76 + this.resume();
77 + return r;
78 +};
79 +
80 +DelayedStream.prototype._handleEmit = function(args) {
81 + if (this._released) {
82 + this.emit.apply(this, args);
83 + return;
84 + }
85 +
86 + if (args[0] === 'data') {
87 + this.dataSize += args[1].length;
88 + this._checkIfMaxDataSizeExceeded();
89 + }
90 +
91 + this._bufferedEvents.push(args);
92 +};
93 +
94 +DelayedStream.prototype._checkIfMaxDataSizeExceeded = function() {
95 + if (this._maxDataSizeExceeded) {
96 + return;
97 + }
98 +
99 + if (this.dataSize <= this.maxDataSize) {
100 + return;
101 + }
102 +
103 + this._maxDataSizeExceeded = true;
104 + var message =
105 + 'DelayedStream#maxDataSize of ' + this.maxDataSize + ' bytes exceeded.'
106 + this.emit('error', new Error(message));
107 +};
1 +{
2 + "author": "Felix Geisendörfer <felix@debuggable.com> (http://debuggable.com/)",
3 + "contributors": [
4 + "Mike Atkins <apeherder@gmail.com>"
5 + ],
6 + "name": "delayed-stream",
7 + "description": "Buffers events from a stream until you are ready to handle them.",
8 + "license": "MIT",
9 + "version": "1.0.0",
10 + "homepage": "https://github.com/felixge/node-delayed-stream",
11 + "repository": {
12 + "type": "git",
13 + "url": "git://github.com/felixge/node-delayed-stream.git"
14 + },
15 + "main": "./lib/delayed_stream",
16 + "engines": {
17 + "node": ">=0.4.0"
18 + },
19 + "scripts": {
20 + "test": "make test"
21 + },
22 + "dependencies": {},
23 + "devDependencies": {
24 + "fake": "0.2.0",
25 + "far": "0.0.1"
26 + }
27 +}
1 +{
2 + "ecmaVersion": 7,
3 + "libs": [],
4 + "loadEagerly": ["./src/*.js"],
5 + "dontLoad": ["node_modules/**"],
6 + "plugins": {
7 + "es_modules": {},
8 + "node": {},
9 + "doc_comment": {
10 + "fullDocs": true,
11 + "strong": true
12 + },
13 + "webpack": {
14 + "configPath": "./webpack.config.js"
15 + }
16 + }
17 +}
This diff is collapsed. Click to expand it.
1 +<div align="center">
2 + <br />
3 + <p>
4 + <a href="https://discord.js.org"><img src="https://discord.js.org/static/logo.svg" width="546" alt="discord.js" /></a>
5 + </p>
6 + <br />
7 + <p>
8 + <a href="https://discord.gg/bRCvFy9"><img src="https://img.shields.io/discord/222078108977594368?color=7289da&logo=discord&logoColor=white" alt="Discord server" /></a>
9 + <a href="https://www.npmjs.com/package/discord.js"><img src="https://img.shields.io/npm/v/discord.js.svg?maxAge=3600" alt="NPM version" /></a>
10 + <a href="https://www.npmjs.com/package/discord.js"><img src="https://img.shields.io/npm/dt/discord.js.svg?maxAge=3600" alt="NPM downloads" /></a>
11 + <a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/workflows/Testing/badge.svg" alt="Build status" /></a>
12 + <a href="https://david-dm.org/discordjs/discord.js"><img src="https://img.shields.io/david/discordjs/discord.js.svg?maxAge=3600" alt="Dependencies" /></a>
13 + <a href="https://www.patreon.com/discordjs"><img src="https://img.shields.io/badge/donate-patreon-F96854.svg" alt="Patreon" /></a>
14 + </p>
15 + <p>
16 + <a href="https://nodei.co/npm/discord.js/"><img src="https://nodei.co/npm/discord.js.png?downloads=true&stars=true" alt="npm installnfo" /></a>
17 + </p>
18 +</div>
19 +
20 +## Table of contents
21 +
22 +- [About](#about)
23 +- [Installation](#installation)
24 + - [Audio engines](#audio-engines)
25 + - [Optional packages](#optional-packages)
26 +- [Example Usage](#example-usage)
27 +- [Links](#links)
28 + - [Extensions](#extensions)
29 +- [Contributing](#contributing)
30 +- [Help](#help)
31 +
32 +## About
33 +
34 +discord.js is a powerful [Node.js](https://nodejs.org) module that allows you to easily interact with the
35 +[Discord API](https://discord.com/developers/docs/intro).
36 +
37 +- Object-oriented
38 +- Predictable abstractions
39 +- Performant
40 +- 100% coverage of the Discord API
41 +
42 +## Installation
43 +
44 +**Node.js 12.0.0 or newer is required.**
45 +Ignore any warnings about unmet peer dependencies, as they're all optional.
46 +
47 +Without voice support: `npm install discord.js`
48 +With voice support ([@discordjs/opus](https://www.npmjs.com/package/@discordjs/opus)): `npm install discord.js @discordjs/opus`
49 +With voice support ([opusscript](https://www.npmjs.com/package/opusscript)): `npm install discord.js opusscript`
50 +
51 +### Audio engines
52 +
53 +The preferred audio engine is @discordjs/opus, as it performs significantly better than opusscript. When both are available, discord.js will automatically choose @discordjs/opus.
54 +Using opusscript is only recommended for development environments where @discordjs/opus is tough to get working.
55 +For production bots, using @discordjs/opus should be considered a necessity, especially if they're going to be running on multiple servers.
56 +
57 +### Optional packages
58 +
59 +- [zlib-sync](https://www.npmjs.com/package/zlib-sync) for WebSocket data compression and inflation (`npm install zlib-sync`)
60 +- [erlpack](https://github.com/discord/erlpack) for significantly faster WebSocket data (de)serialisation (`npm install discord/erlpack`)
61 +- One of the following packages can be installed for faster voice packet encryption and decryption:
62 + - [sodium](https://www.npmjs.com/package/sodium) (`npm install sodium`)
63 + - [libsodium.js](https://www.npmjs.com/package/libsodium-wrappers) (`npm install libsodium-wrappers`)
64 +- [bufferutil](https://www.npmjs.com/package/bufferutil) for a much faster WebSocket connection (`npm install bufferutil`)
65 +- [utf-8-validate](https://www.npmjs.com/package/utf-8-validate) in combination with `bufferutil` for much faster WebSocket processing (`npm install utf-8-validate`)
66 +
67 +## Example usage
68 +
69 +```js
70 +const Discord = require('discord.js');
71 +const client = new Discord.Client();
72 +
73 +client.on('ready', () => {
74 + console.log(`Logged in as ${client.user.tag}!`);
75 +});
76 +
77 +client.on('message', msg => {
78 + if (msg.content === 'ping') {
79 + msg.reply('pong');
80 + }
81 +});
82 +
83 +client.login('token');
84 +```
85 +
86 +## Links
87 +
88 +- [Website](https://discord.js.org/) ([source](https://github.com/discordjs/website))
89 +- [Documentation](https://discord.js.org/#/docs/main/master/general/welcome)
90 +- [Guide](https://discordjs.guide/) ([source](https://github.com/discordjs/guide)) - this is still for stable
91 + See also the [Update Guide](https://discordjs.guide/additional-info/changes-in-v12.html), including updated and removed items in the library.
92 +- [Discord.js Discord server](https://discord.gg/bRCvFy9)
93 +- [Discord API Discord server](https://discord.gg/discord-api)
94 +- [GitHub](https://github.com/discordjs/discord.js)
95 +- [NPM](https://www.npmjs.com/package/discord.js)
96 +- [Related libraries](https://discordapi.com/unofficial/libs.html)
97 +
98 +### Extensions
99 +
100 +- [RPC](https://www.npmjs.com/package/discord-rpc) ([source](https://github.com/discordjs/RPC))
101 +
102 +## Contributing
103 +
104 +Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the
105 +[documentation](https://discord.js.org/#/docs).
106 +See [the contribution guide](https://github.com/discordjs/discord.js/blob/master/.github/CONTRIBUTING.md) if you'd like to submit a PR.
107 +
108 +## Help
109 +
110 +If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle
111 +nudge in the right direction, please don't hesitate to join our official [Discord.js Server](https://discord.gg/bRCvFy9).
1 +import Discord from '../src/index.js';
2 +
3 +export default Discord;
4 +
5 +export const {
6 + BaseClient,
7 + Client,
8 + Shard,
9 + ShardClientUtil,
10 + ShardingManager,
11 + WebhookClient,
12 + ActivityFlags,
13 + BitField,
14 + Collection,
15 + Constants,
16 + DataResolver,
17 + BaseManager,
18 + DiscordAPIError,
19 + HTTPError,
20 + MessageFlags,
21 + Intents,
22 + Permissions,
23 + Speaking,
24 + Snowflake,
25 + SnowflakeUtil,
26 + Structures,
27 + SystemChannelFlags,
28 + UserFlags,
29 + Util,
30 + version,
31 + ChannelManager,
32 + GuildChannelManager,
33 + GuildEmojiManager,
34 + GuildEmojiRoleManager,
35 + GuildMemberManager,
36 + GuildMemberRoleManager,
37 + GuildManager,
38 + ReactionManager,
39 + ReactionUserManager,
40 + MessageManager,
41 + PresenceManager,
42 + RoleManager,
43 + UserManager,
44 + discordSort,
45 + escapeMarkdown,
46 + fetchRecommendedShards,
47 + resolveColor,
48 + resolveString,
49 + splitMessage,
50 + Application,
51 + Base,
52 + Activity,
53 + APIMessage,
54 + BaseGuildEmoji,
55 + CategoryChannel,
56 + Channel,
57 + ClientApplication,
58 + ClientUser,
59 + Collector,
60 + DMChannel,
61 + Emoji,
62 + Guild,
63 + GuildAuditLogs,
64 + GuildChannel,
65 + GuildEmoji,
66 + GuildMember,
67 + GuildPreview,
68 + GuildTemplate,
69 + Integration,
70 + Invite,
71 + Message,
72 + MessageAttachment,
73 + MessageCollector,
74 + MessageEmbed,
75 + MessageMentions,
76 + MessageReaction,
77 + NewsChannel,
78 + PermissionOverwrites,
79 + Presence,
80 + ClientPresence,
81 + ReactionCollector,
82 + ReactionEmoji,
83 + RichPresenceAssets,
84 + Role,
85 + StoreChannel,
86 + Team,
87 + TeamMember,
88 + TextChannel,
89 + User,
90 + VoiceChannel,
91 + VoiceRegion,
92 + VoiceState,
93 + Webhook,
94 + WebSocket
95 +} = Discord;
1 +{
2 + "plugins": ["node_modules/jsdoc-strip-async-await"]
3 +}
1 +{
2 + "name": "discord.js",
3 + "version": "12.5.3",
4 + "description": "A powerful library for interacting with the Discord API",
5 + "main": "./src/index",
6 + "types": "./typings/index.d.ts",
7 + "exports": {
8 + ".": [
9 + {
10 + "require": "./src/index.js",
11 + "import": "./esm/discord.mjs"
12 + },
13 + "./src/index.js"
14 + ],
15 + "./esm": "./esm/discord.mjs"
16 + },
17 + "scripts": {
18 + "test": "npm run lint && npm run docs:test && npm run lint:typings",
19 + "test:typescript": "tsc",
20 + "docs": "docgen --source src --custom docs/index.yml --output docs/docs.json",
21 + "docs:test": "docgen --source src --custom docs/index.yml",
22 + "lint": "eslint src",
23 + "lint:fix": "eslint src --fix",
24 + "lint:typings": "tslint typings/index.d.ts",
25 + "prettier": "prettier --write src/**/*.js typings/**/*.ts",
26 + "build:browser": "webpack",
27 + "prepublishOnly": "npm run test && cross-env NODE_ENV=production npm run build:browser"
28 + },
29 + "repository": {
30 + "type": "git",
31 + "url": "git+https://github.com/discordjs/discord.js.git"
32 + },
33 + "keywords": [
34 + "discord",
35 + "api",
36 + "bot",
37 + "client",
38 + "node",
39 + "discordapp"
40 + ],
41 + "author": "Amish Shah <amishshah.2k@gmail.com>",
42 + "license": "Apache-2.0",
43 + "bugs": {
44 + "url": "https://github.com/discordjs/discord.js/issues"
45 + },
46 + "homepage": "https://github.com/discordjs/discord.js#readme",
47 + "runkitExampleFilename": "./docs/examples/ping.js",
48 + "unpkg": "./webpack/discord.min.js",
49 + "dependencies": {
50 + "@discordjs/collection": "^0.1.6",
51 + "@discordjs/form-data": "^3.0.1",
52 + "abort-controller": "^3.0.0",
53 + "node-fetch": "^2.6.1",
54 + "prism-media": "^1.2.9",
55 + "setimmediate": "^1.0.5",
56 + "tweetnacl": "^1.0.3",
57 + "ws": "^7.4.4"
58 + },
59 + "devDependencies": {
60 + "@commitlint/cli": "^12.0.1",
61 + "@commitlint/config-angular": "^12.0.1",
62 + "@types/node": "^12.12.6",
63 + "@types/ws": "^7.4.0",
64 + "cross-env": "^7.0.3",
65 + "discord.js-docgen": "git+https://github.com/discordjs/docgen.git",
66 + "dtslint": "^4.0.8",
67 + "eslint": "^7.23.0",
68 + "eslint-config-prettier": "^6.13.0",
69 + "eslint-plugin-import": "^2.22.1",
70 + "eslint-plugin-prettier": "^3.3.1",
71 + "husky": "^4.3.0",
72 + "jest": "^26.6.3",
73 + "json-filter-loader": "^1.0.0",
74 + "lint-staged": "^10.5.4",
75 + "prettier": "^2.2.1",
76 + "terser-webpack-plugin": "^4.2.3",
77 + "tslint": "^6.1.3",
78 + "typescript": "^4.2.3",
79 + "webpack": "^4.44.2",
80 + "webpack-cli": "^3.3.12"
81 + },
82 + "engines": {
83 + "node": ">=12.0.0"
84 + },
85 + "browser": {
86 + "@discordjs/opus": false,
87 + "https": false,
88 + "ws": false,
89 + "erlpack": false,
90 + "prism-media": false,
91 + "opusscript": false,
92 + "node-opus": false,
93 + "tweetnacl": false,
94 + "sodium": false,
95 + "worker_threads": false,
96 + "zlib-sync": false,
97 + "src/sharding/Shard.js": false,
98 + "src/sharding/ShardClientUtil.js": false,
99 + "src/sharding/ShardingManager.js": false,
100 + "src/client/voice/ClientVoiceManager.js": false,
101 + "src/client/voice/VoiceBroadcast.js": false,
102 + "src/client/voice/VoiceConnection.js": false,
103 + "src/client/voice/dispatcher/BroadcastDispatcher.js": false,
104 + "src/client/voice/dispatcher/StreamDispatcher.js": false,
105 + "src/client/voice/networking/VoiceUDPClient.js": false,
106 + "src/client/voice/networking/VoiceWebSocket.js": false,
107 + "src/client/voice/player/AudioPlayer.js": false,
108 + "src/client/voice/player/BasePlayer.js": false,
109 + "src/client/voice/player/BroadcastAudioPlayer.js": false,
110 + "src/client/voice/receiver/PacketHandler.js": false,
111 + "src/client/voice/receiver/Receiver.js": false,
112 + "src/client/voice/util/PlayInterface.js": false,
113 + "src/client/voice/util/Secretbox.js": false,
114 + "src/client/voice/util/Silence.js": false,
115 + "src/client/voice/util/VolumeInterface.js": false
116 + },
117 + "husky": {
118 + "hooks": {
119 + "pre-commit": "lint-staged",
120 + "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
121 + }
122 + },
123 + "lint-staged": {
124 + "*.js": "eslint --fix",
125 + "*.ts": "prettier --write"
126 + },
127 + "commitlint": {
128 + "extends": [
129 + "@commitlint/config-angular"
130 + ],
131 + "rules": {
132 + "scope-case": [
133 + 2,
134 + "always",
135 + "pascal-case"
136 + ],
137 + "type-enum": [
138 + 2,
139 + "always",
140 + [
141 + "chore",
142 + "build",
143 + "ci",
144 + "docs",
145 + "feat",
146 + "fix",
147 + "perf",
148 + "refactor",
149 + "revert",
150 + "style",
151 + "test"
152 + ]
153 + ]
154 + }
155 + },
156 + "prettier": {
157 + "singleQuote": true,
158 + "printWidth": 120,
159 + "trailingComma": "all",
160 + "endOfLine": "lf",
161 + "arrowParens": "avoid"
162 + }
163 +}
1 +'use strict';
2 +
3 +const { browser } = require('./util/Constants');
4 +
5 +let erlpack;
6 +
7 +try {
8 + erlpack = require('erlpack');
9 + if (!erlpack.pack) erlpack = null;
10 +} catch {} // eslint-disable-line no-empty
11 +
12 +let TextDecoder;
13 +
14 +if (browser) {
15 + TextDecoder = window.TextDecoder; // eslint-disable-line no-undef
16 + exports.WebSocket = window.WebSocket; // eslint-disable-line no-undef
17 +} else {
18 + TextDecoder = require('util').TextDecoder;
19 + exports.WebSocket = require('ws');
20 +}
21 +
22 +const ab = new TextDecoder();
23 +
24 +exports.encoding = erlpack ? 'etf' : 'json';
25 +
26 +exports.pack = erlpack ? erlpack.pack : JSON.stringify;
27 +
28 +exports.unpack = (data, type) => {
29 + if (exports.encoding === 'json' || type === 'json') {
30 + if (typeof data !== 'string') {
31 + data = ab.decode(data);
32 + }
33 + return JSON.parse(data);
34 + }
35 + if (!Buffer.isBuffer(data)) data = Buffer.from(new Uint8Array(data));
36 + return erlpack.unpack(data);
37 +};
38 +
39 +exports.create = (gateway, query = {}, ...args) => {
40 + const [g, q] = gateway.split('?');
41 + query.encoding = exports.encoding;
42 + query = new URLSearchParams(query);
43 + if (q) new URLSearchParams(q).forEach((v, k) => query.set(k, v));
44 + const ws = new exports.WebSocket(`${g}?${query}`, ...args);
45 + if (browser) ws.binaryType = 'arraybuffer';
46 + return ws;
47 +};
48 +
49 +for (const state of ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED']) exports[state] = exports.WebSocket[state];
1 +'use strict';
2 +
3 +require('setimmediate');
4 +const EventEmitter = require('events');
5 +const RESTManager = require('../rest/RESTManager');
6 +const { DefaultOptions } = require('../util/Constants');
7 +const Util = require('../util/Util');
8 +
9 +/**
10 + * The base class for all clients.
11 + * @extends {EventEmitter}
12 + */
13 +class BaseClient extends EventEmitter {
14 + constructor(options = {}) {
15 + super();
16 +
17 + /**
18 + * Timeouts set by {@link BaseClient#setTimeout} that are still active
19 + * @type {Set<Timeout>}
20 + * @private
21 + */
22 + this._timeouts = new Set();
23 +
24 + /**
25 + * Intervals set by {@link BaseClient#setInterval} that are still active
26 + * @type {Set<Timeout>}
27 + * @private
28 + */
29 + this._intervals = new Set();
30 +
31 + /**
32 + * Intervals set by {@link BaseClient#setImmediate} that are still active
33 + * @type {Set<Immediate>}
34 + * @private
35 + */
36 + this._immediates = new Set();
37 +
38 + /**
39 + * The options the client was instantiated with
40 + * @type {ClientOptions}
41 + */
42 + this.options = Util.mergeDefault(DefaultOptions, options);
43 +
44 + /**
45 + * The REST manager of the client
46 + * @type {RESTManager}
47 + * @private
48 + */
49 + this.rest = new RESTManager(this, options._tokenType);
50 + }
51 +
52 + /**
53 + * API shortcut
54 + * @type {Object}
55 + * @readonly
56 + * @private
57 + */
58 + get api() {
59 + return this.rest.api;
60 + }
61 +
62 + /**
63 + * Destroys all assets used by the base client.
64 + */
65 + destroy() {
66 + for (const t of this._timeouts) this.clearTimeout(t);
67 + for (const i of this._intervals) this.clearInterval(i);
68 + for (const i of this._immediates) this.clearImmediate(i);
69 + this._timeouts.clear();
70 + this._intervals.clear();
71 + this._immediates.clear();
72 + }
73 +
74 + /**
75 + * Sets a timeout that will be automatically cancelled if the client is destroyed.
76 + * @param {Function} fn Function to execute
77 + * @param {number} delay Time to wait before executing (in milliseconds)
78 + * @param {...*} args Arguments for the function
79 + * @returns {Timeout}
80 + */
81 + setTimeout(fn, delay, ...args) {
82 + const timeout = setTimeout(() => {
83 + fn(...args);
84 + this._timeouts.delete(timeout);
85 + }, delay);
86 + this._timeouts.add(timeout);
87 + return timeout;
88 + }
89 +
90 + /**
91 + * Clears a timeout.
92 + * @param {Timeout} timeout Timeout to cancel
93 + */
94 + clearTimeout(timeout) {
95 + clearTimeout(timeout);
96 + this._timeouts.delete(timeout);
97 + }
98 +
99 + /**
100 + * Sets an interval that will be automatically cancelled if the client is destroyed.
101 + * @param {Function} fn Function to execute
102 + * @param {number} delay Time to wait between executions (in milliseconds)
103 + * @param {...*} args Arguments for the function
104 + * @returns {Timeout}
105 + */
106 + setInterval(fn, delay, ...args) {
107 + const interval = setInterval(fn, delay, ...args);
108 + this._intervals.add(interval);
109 + return interval;
110 + }
111 +
112 + /**
113 + * Clears an interval.
114 + * @param {Timeout} interval Interval to cancel
115 + */
116 + clearInterval(interval) {
117 + clearInterval(interval);
118 + this._intervals.delete(interval);
119 + }
120 +
121 + /**
122 + * Sets an immediate that will be automatically cancelled if the client is destroyed.
123 + * @param {Function} fn Function to execute
124 + * @param {...*} args Arguments for the function
125 + * @returns {Immediate}
126 + */
127 + setImmediate(fn, ...args) {
128 + const immediate = setImmediate(fn, ...args);
129 + this._immediates.add(immediate);
130 + return immediate;
131 + }
132 +
133 + /**
134 + * Clears an immediate.
135 + * @param {Immediate} immediate Immediate to cancel
136 + */
137 + clearImmediate(immediate) {
138 + clearImmediate(immediate);
139 + this._immediates.delete(immediate);
140 + }
141 +
142 + /**
143 + * Increments max listeners by one, if they are not zero.
144 + * @private
145 + */
146 + incrementMaxListeners() {
147 + const maxListeners = this.getMaxListeners();
148 + if (maxListeners !== 0) {
149 + this.setMaxListeners(maxListeners + 1);
150 + }
151 + }
152 +
153 + /**
154 + * Decrements max listeners by one, if they are not zero.
155 + * @private
156 + */
157 + decrementMaxListeners() {
158 + const maxListeners = this.getMaxListeners();
159 + if (maxListeners !== 0) {
160 + this.setMaxListeners(maxListeners - 1);
161 + }
162 + }
163 +
164 + toJSON(...props) {
165 + return Util.flatten(this, { domain: false }, ...props);
166 + }
167 +}
168 +
169 +module.exports = BaseClient;
This diff is collapsed. Click to expand it.
1 +'use strict';
2 +
3 +const BaseClient = require('./BaseClient');
4 +const Webhook = require('../structures/Webhook');
5 +
6 +/**
7 + * The webhook client.
8 + * @implements {Webhook}
9 + * @extends {BaseClient}
10 + */
11 +class WebhookClient extends BaseClient {
12 + /**
13 + * @param {Snowflake} id ID of the webhook
14 + * @param {string} token Token of the webhook
15 + * @param {ClientOptions} [options] Options for the client
16 + * @example
17 + * // Create a new webhook and send a message
18 + * const hook = new Discord.WebhookClient('1234', 'abcdef');
19 + * hook.send('This will send a message').catch(console.error);
20 + */
21 + constructor(id, token, options) {
22 + super(options);
23 + Object.defineProperty(this, 'client', { value: this });
24 + this.id = id;
25 + Object.defineProperty(this, 'token', { value: token, writable: true, configurable: true });
26 + }
27 +}
28 +
29 +Webhook.applyToClass(WebhookClient);
30 +
31 +module.exports = WebhookClient;
1 +'use strict';
2 +
3 +const { PartialTypes } = require('../../util/Constants');
4 +
5 +/*
6 +
7 +ABOUT ACTIONS
8 +
9 +Actions are similar to WebSocket Packet Handlers, but since introducing
10 +the REST API methods, in order to prevent rewriting code to handle data,
11 +"actions" have been introduced. They're basically what Packet Handlers
12 +used to be but they're strictly for manipulating data and making sure
13 +that WebSocket events don't clash with REST methods.
14 +
15 +*/
16 +
17 +class GenericAction {
18 + constructor(client) {
19 + this.client = client;
20 + }
21 +
22 + handle(data) {
23 + return data;
24 + }
25 +
26 + getPayload(data, manager, id, partialType, cache) {
27 + const existing = manager.cache.get(id);
28 + if (!existing && this.client.options.partials.includes(partialType)) {
29 + return manager.add(data, cache);
30 + }
31 + return existing;
32 + }
33 +
34 + getChannel(data) {
35 + const id = data.channel_id || data.id;
36 + return (
37 + data.channel ||
38 + this.getPayload(
39 + {
40 + id,
41 + guild_id: data.guild_id,
42 + recipients: [data.author || { id: data.user_id }],
43 + },
44 + this.client.channels,
45 + id,
46 + PartialTypes.CHANNEL,
47 + )
48 + );
49 + }
50 +
51 + getMessage(data, channel, cache) {
52 + const id = data.message_id || data.id;
53 + return (
54 + data.message ||
55 + this.getPayload(
56 + {
57 + id,
58 + channel_id: channel.id,
59 + guild_id: data.guild_id || (channel.guild ? channel.guild.id : null),
60 + },
61 + channel.messages,
62 + id,
63 + PartialTypes.MESSAGE,
64 + cache,
65 + )
66 + );
67 + }
68 +
69 + getReaction(data, message, user) {
70 + const id = data.emoji.id || decodeURIComponent(data.emoji.name);
71 + return this.getPayload(
72 + {
73 + emoji: data.emoji,
74 + count: message.partial ? null : 0,
75 + me: user ? user.id === this.client.user.id : false,
76 + },
77 + message.reactions,
78 + id,
79 + PartialTypes.REACTION,
80 + );
81 + }
82 +
83 + getMember(data, guild) {
84 + return this.getPayload(data, guild.members, data.user.id, PartialTypes.GUILD_MEMBER);
85 + }
86 +
87 + getUser(data) {
88 + const id = data.user_id;
89 + return data.user || this.getPayload({ id }, this.client.users, id, PartialTypes.USER);
90 + }
91 +
92 + getUserFromMember(data) {
93 + if (data.guild_id && data.member && data.member.user) {
94 + const guild = this.client.guilds.cache.get(data.guild_id);
95 + if (guild) {
96 + return guild.members.add(data.member).user;
97 + } else {
98 + return this.client.users.add(data.member.user);
99 + }
100 + }
101 + return this.getUser(data);
102 + }
103 +}
104 +
105 +module.exports = GenericAction;
1 +'use strict';
2 +
3 +class ActionsManager {
4 + constructor(client) {
5 + this.client = client;
6 +
7 + this.register(require('./MessageCreate'));
8 + this.register(require('./MessageDelete'));
9 + this.register(require('./MessageDeleteBulk'));
10 + this.register(require('./MessageUpdate'));
11 + this.register(require('./MessageReactionAdd'));
12 + this.register(require('./MessageReactionRemove'));
13 + this.register(require('./MessageReactionRemoveAll'));
14 + this.register(require('./MessageReactionRemoveEmoji'));
15 + this.register(require('./ChannelCreate'));
16 + this.register(require('./ChannelDelete'));
17 + this.register(require('./ChannelUpdate'));
18 + this.register(require('./GuildDelete'));
19 + this.register(require('./GuildUpdate'));
20 + this.register(require('./InviteCreate'));
21 + this.register(require('./InviteDelete'));
22 + this.register(require('./GuildMemberRemove'));
23 + this.register(require('./GuildMemberUpdate'));
24 + this.register(require('./GuildBanRemove'));
25 + this.register(require('./GuildRoleCreate'));
26 + this.register(require('./GuildRoleDelete'));
27 + this.register(require('./GuildRoleUpdate'));
28 + this.register(require('./PresenceUpdate'));
29 + this.register(require('./UserUpdate'));
30 + this.register(require('./VoiceStateUpdate'));
31 + this.register(require('./GuildEmojiCreate'));
32 + this.register(require('./GuildEmojiDelete'));
33 + this.register(require('./GuildEmojiUpdate'));
34 + this.register(require('./GuildEmojisUpdate'));
35 + this.register(require('./GuildRolesPositionUpdate'));
36 + this.register(require('./GuildChannelsPositionUpdate'));
37 + this.register(require('./GuildIntegrationsUpdate'));
38 + this.register(require('./WebhooksUpdate'));
39 + this.register(require('./TypingStart'));
40 + }
41 +
42 + register(Action) {
43 + this[Action.name.replace(/Action$/, '')] = new Action(this.client);
44 + }
45 +}
46 +
47 +module.exports = ActionsManager;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +const { Events } = require('../../util/Constants');
5 +
6 +class ChannelCreateAction extends Action {
7 + handle(data) {
8 + const client = this.client;
9 + const existing = client.channels.cache.has(data.id);
10 + const channel = client.channels.add(data);
11 + if (!existing && channel) {
12 + /**
13 + * Emitted whenever a channel is created.
14 + * @event Client#channelCreate
15 + * @param {DMChannel|GuildChannel} channel The channel that was created
16 + */
17 + client.emit(Events.CHANNEL_CREATE, channel);
18 + }
19 + return { channel };
20 + }
21 +}
22 +
23 +module.exports = ChannelCreateAction;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +const DMChannel = require('../../structures/DMChannel');
5 +const { Events } = require('../../util/Constants');
6 +
7 +class ChannelDeleteAction extends Action {
8 + constructor(client) {
9 + super(client);
10 + this.deleted = new Map();
11 + }
12 +
13 + handle(data) {
14 + const client = this.client;
15 + let channel = client.channels.cache.get(data.id);
16 +
17 + if (channel) {
18 + client.channels.remove(channel.id);
19 + channel.deleted = true;
20 + if (channel.messages && !(channel instanceof DMChannel)) {
21 + for (const message of channel.messages.cache.values()) {
22 + message.deleted = true;
23 + }
24 + }
25 + /**
26 + * Emitted whenever a channel is deleted.
27 + * @event Client#channelDelete
28 + * @param {DMChannel|GuildChannel} channel The channel that was deleted
29 + */
30 + client.emit(Events.CHANNEL_DELETE, channel);
31 + }
32 +
33 + return { channel };
34 + }
35 +}
36 +
37 +module.exports = ChannelDeleteAction;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +const Channel = require('../../structures/Channel');
5 +const { ChannelTypes } = require('../../util/Constants');
6 +
7 +class ChannelUpdateAction extends Action {
8 + handle(data) {
9 + const client = this.client;
10 +
11 + let channel = client.channels.cache.get(data.id);
12 + if (channel) {
13 + const old = channel._update(data);
14 +
15 + if (ChannelTypes[channel.type.toUpperCase()] !== data.type) {
16 + const newChannel = Channel.create(this.client, data, channel.guild);
17 + for (const [id, message] of channel.messages.cache) newChannel.messages.cache.set(id, message);
18 + newChannel._typing = new Map(channel._typing);
19 + channel = newChannel;
20 + this.client.channels.cache.set(channel.id, channel);
21 + }
22 +
23 + return {
24 + old,
25 + updated: channel,
26 + };
27 + }
28 +
29 + return {};
30 + }
31 +}
32 +
33 +module.exports = ChannelUpdateAction;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +const { Events } = require('../../util/Constants');
5 +
6 +class GuildBanRemove extends Action {
7 + handle(data) {
8 + const client = this.client;
9 + const guild = client.guilds.cache.get(data.guild_id);
10 + const user = client.users.add(data.user);
11 + /**
12 + * Emitted whenever a member is unbanned from a guild.
13 + * @event Client#guildBanRemove
14 + * @param {Guild} guild The guild that the unban occurred in
15 + * @param {User} user The user that was unbanned
16 + */
17 + if (guild && user) client.emit(Events.GUILD_BAN_REMOVE, guild, user);
18 + }
19 +}
20 +
21 +module.exports = GuildBanRemove;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +
5 +class GuildChannelsPositionUpdate extends Action {
6 + handle(data) {
7 + const client = this.client;
8 +
9 + const guild = client.guilds.cache.get(data.guild_id);
10 + if (guild) {
11 + for (const partialChannel of data.channels) {
12 + const channel = guild.channels.cache.get(partialChannel.id);
13 + if (channel) channel.rawPosition = partialChannel.position;
14 + }
15 + }
16 +
17 + return { guild };
18 + }
19 +}
20 +
21 +module.exports = GuildChannelsPositionUpdate;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +const { Events } = require('../../util/Constants');
5 +
6 +class GuildDeleteAction extends Action {
7 + constructor(client) {
8 + super(client);
9 + this.deleted = new Map();
10 + }
11 +
12 + handle(data) {
13 + const client = this.client;
14 +
15 + let guild = client.guilds.cache.get(data.id);
16 + if (guild) {
17 + for (const channel of guild.channels.cache.values()) {
18 + if (channel.type === 'text') channel.stopTyping(true);
19 + }
20 +
21 + if (data.unavailable) {
22 + // Guild is unavailable
23 + guild.available = false;
24 +
25 + /**
26 + * Emitted whenever a guild becomes unavailable, likely due to a server outage.
27 + * @event Client#guildUnavailable
28 + * @param {Guild} guild The guild that has become unavailable
29 + */
30 + client.emit(Events.GUILD_UNAVAILABLE, guild);
31 +
32 + // Stops the GuildDelete packet thinking a guild was actually deleted,
33 + // handles emitting of event itself
34 + return {
35 + guild: null,
36 + };
37 + }
38 +
39 + for (const channel of guild.channels.cache.values()) this.client.channels.remove(channel.id);
40 + if (guild.voice && guild.voice.connection) guild.voice.connection.disconnect();
41 +
42 + // Delete guild
43 + client.guilds.cache.delete(guild.id);
44 + guild.deleted = true;
45 +
46 + /**
47 + * Emitted whenever a guild kicks the client or the guild is deleted/left.
48 + * @event Client#guildDelete
49 + * @param {Guild} guild The guild that was deleted
50 + */
51 + client.emit(Events.GUILD_DELETE, guild);
52 +
53 + this.deleted.set(guild.id, guild);
54 + this.scheduleForDeletion(guild.id);
55 + } else {
56 + guild = this.deleted.get(data.id) || null;
57 + }
58 +
59 + return { guild };
60 + }
61 +
62 + scheduleForDeletion(id) {
63 + this.client.setTimeout(() => this.deleted.delete(id), this.client.options.restWsBridgeTimeout);
64 + }
65 +}
66 +
67 +module.exports = GuildDeleteAction;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +const { Events } = require('../../util/Constants');
5 +
6 +class GuildEmojiCreateAction extends Action {
7 + handle(guild, createdEmoji) {
8 + const already = guild.emojis.cache.has(createdEmoji.id);
9 + const emoji = guild.emojis.add(createdEmoji);
10 + /**
11 + * Emitted whenever a custom emoji is created in a guild.
12 + * @event Client#emojiCreate
13 + * @param {GuildEmoji} emoji The emoji that was created
14 + */
15 + if (!already) this.client.emit(Events.GUILD_EMOJI_CREATE, emoji);
16 + return { emoji };
17 + }
18 +}
19 +
20 +module.exports = GuildEmojiCreateAction;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +const { Events } = require('../../util/Constants');
5 +
6 +class GuildEmojiDeleteAction extends Action {
7 + handle(emoji) {
8 + emoji.guild.emojis.cache.delete(emoji.id);
9 + emoji.deleted = true;
10 + /**
11 + * Emitted whenever a custom emoji is deleted in a guild.
12 + * @event Client#emojiDelete
13 + * @param {GuildEmoji} emoji The emoji that was deleted
14 + */
15 + this.client.emit(Events.GUILD_EMOJI_DELETE, emoji);
16 + return { emoji };
17 + }
18 +}
19 +
20 +module.exports = GuildEmojiDeleteAction;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +const { Events } = require('../../util/Constants');
5 +
6 +class GuildEmojiUpdateAction extends Action {
7 + handle(current, data) {
8 + const old = current._update(data);
9 + /**
10 + * Emitted whenever a custom emoji is updated in a guild.
11 + * @event Client#emojiUpdate
12 + * @param {GuildEmoji} oldEmoji The old emoji
13 + * @param {GuildEmoji} newEmoji The new emoji
14 + */
15 + this.client.emit(Events.GUILD_EMOJI_UPDATE, old, current);
16 + return { emoji: current };
17 + }
18 +}
19 +
20 +module.exports = GuildEmojiUpdateAction;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +
5 +class GuildEmojisUpdateAction extends Action {
6 + handle(data) {
7 + const guild = this.client.guilds.cache.get(data.guild_id);
8 + if (!guild || !guild.emojis) return;
9 +
10 + const deletions = new Map(guild.emojis.cache);
11 +
12 + for (const emoji of data.emojis) {
13 + // Determine type of emoji event
14 + const cachedEmoji = guild.emojis.cache.get(emoji.id);
15 + if (cachedEmoji) {
16 + deletions.delete(emoji.id);
17 + if (!cachedEmoji.equals(emoji)) {
18 + // Emoji updated
19 + this.client.actions.GuildEmojiUpdate.handle(cachedEmoji, emoji);
20 + }
21 + } else {
22 + // Emoji added
23 + this.client.actions.GuildEmojiCreate.handle(guild, emoji);
24 + }
25 + }
26 +
27 + for (const emoji of deletions.values()) {
28 + // Emoji deleted
29 + this.client.actions.GuildEmojiDelete.handle(emoji);
30 + }
31 + }
32 +}
33 +
34 +module.exports = GuildEmojisUpdateAction;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +const { Events } = require('../../util/Constants');
5 +
6 +class GuildIntegrationsUpdate extends Action {
7 + handle(data) {
8 + const client = this.client;
9 + const guild = client.guilds.cache.get(data.guild_id);
10 + /**
11 + * Emitted whenever a guild integration is updated
12 + * @event Client#guildIntegrationsUpdate
13 + * @param {Guild} guild The guild whose integrations were updated
14 + */
15 + if (guild) client.emit(Events.GUILD_INTEGRATIONS_UPDATE, guild);
16 + }
17 +}
18 +
19 +module.exports = GuildIntegrationsUpdate;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +const { Events, Status } = require('../../util/Constants');
5 +
6 +class GuildMemberRemoveAction extends Action {
7 + handle(data, shard) {
8 + const client = this.client;
9 + const guild = client.guilds.cache.get(data.guild_id);
10 + let member = null;
11 + if (guild) {
12 + member = this.getMember({ user: data.user }, guild);
13 + guild.memberCount--;
14 + if (member) {
15 + member.deleted = true;
16 + guild.members.cache.delete(member.id);
17 + /**
18 + * Emitted whenever a member leaves a guild, or is kicked.
19 + * @event Client#guildMemberRemove
20 + * @param {GuildMember} member The member that has left/been kicked from the guild
21 + */
22 + if (shard.status === Status.READY) client.emit(Events.GUILD_MEMBER_REMOVE, member);
23 + }
24 + guild.voiceStates.cache.delete(data.user.id);
25 + }
26 + return { guild, member };
27 + }
28 +}
29 +
30 +module.exports = GuildMemberRemoveAction;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +const { Status, Events } = require('../../util/Constants');
5 +
6 +class GuildMemberUpdateAction extends Action {
7 + handle(data, shard) {
8 + const { client } = this;
9 + if (data.user.username) {
10 + const user = client.users.cache.get(data.user.id);
11 + if (!user) {
12 + client.users.add(data.user);
13 + } else if (!user.equals(data.user)) {
14 + client.actions.UserUpdate.handle(data.user);
15 + }
16 + }
17 +
18 + const guild = client.guilds.cache.get(data.guild_id);
19 + if (guild) {
20 + const member = this.getMember({ user: data.user }, guild);
21 + if (member) {
22 + const old = member._update(data);
23 + /**
24 + * Emitted whenever a guild member changes - i.e. new role, removed role, nickname.
25 + * Also emitted when the user's details (e.g. username) change.
26 + * @event Client#guildMemberUpdate
27 + * @param {GuildMember} oldMember The member before the update
28 + * @param {GuildMember} newMember The member after the update
29 + */
30 + if (shard.status === Status.READY) client.emit(Events.GUILD_MEMBER_UPDATE, old, member);
31 + } else {
32 + const newMember = guild.members.add(data);
33 + /**
34 + * Emitted whenever a member becomes available in a large guild.
35 + * @event Client#guildMemberAvailable
36 + * @param {GuildMember} member The member that became available
37 + */
38 + this.client.emit(Events.GUILD_MEMBER_AVAILABLE, newMember);
39 + }
40 + }
41 + }
42 +}
43 +
44 +module.exports = GuildMemberUpdateAction;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +const { Events } = require('../../util/Constants');
5 +
6 +class GuildRoleCreate extends Action {
7 + handle(data) {
8 + const client = this.client;
9 + const guild = client.guilds.cache.get(data.guild_id);
10 + let role;
11 + if (guild) {
12 + const already = guild.roles.cache.has(data.role.id);
13 + role = guild.roles.add(data.role);
14 + /**
15 + * Emitted whenever a role is created.
16 + * @event Client#roleCreate
17 + * @param {Role} role The role that was created
18 + */
19 + if (!already) client.emit(Events.GUILD_ROLE_CREATE, role);
20 + }
21 + return { role };
22 + }
23 +}
24 +
25 +module.exports = GuildRoleCreate;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +const { Events } = require('../../util/Constants');
5 +
6 +class GuildRoleDeleteAction extends Action {
7 + handle(data) {
8 + const client = this.client;
9 + const guild = client.guilds.cache.get(data.guild_id);
10 + let role;
11 +
12 + if (guild) {
13 + role = guild.roles.cache.get(data.role_id);
14 + if (role) {
15 + guild.roles.cache.delete(data.role_id);
16 + role.deleted = true;
17 + /**
18 + * Emitted whenever a guild role is deleted.
19 + * @event Client#roleDelete
20 + * @param {Role} role The role that was deleted
21 + */
22 + client.emit(Events.GUILD_ROLE_DELETE, role);
23 + }
24 + }
25 +
26 + return { role };
27 + }
28 +}
29 +
30 +module.exports = GuildRoleDeleteAction;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +const { Events } = require('../../util/Constants');
5 +
6 +class GuildRoleUpdateAction extends Action {
7 + handle(data) {
8 + const client = this.client;
9 + const guild = client.guilds.cache.get(data.guild_id);
10 +
11 + if (guild) {
12 + let old = null;
13 +
14 + const role = guild.roles.cache.get(data.role.id);
15 + if (role) {
16 + old = role._update(data.role);
17 + /**
18 + * Emitted whenever a guild role is updated.
19 + * @event Client#roleUpdate
20 + * @param {Role} oldRole The role before the update
21 + * @param {Role} newRole The role after the update
22 + */
23 + client.emit(Events.GUILD_ROLE_UPDATE, old, role);
24 + }
25 +
26 + return {
27 + old,
28 + updated: role,
29 + };
30 + }
31 +
32 + return {
33 + old: null,
34 + updated: null,
35 + };
36 + }
37 +}
38 +
39 +module.exports = GuildRoleUpdateAction;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +
5 +class GuildRolesPositionUpdate extends Action {
6 + handle(data) {
7 + const client = this.client;
8 +
9 + const guild = client.guilds.cache.get(data.guild_id);
10 + if (guild) {
11 + for (const partialRole of data.roles) {
12 + const role = guild.roles.cache.get(partialRole.id);
13 + if (role) role.rawPosition = partialRole.position;
14 + }
15 + }
16 +
17 + return { guild };
18 + }
19 +}
20 +
21 +module.exports = GuildRolesPositionUpdate;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +const { Events } = require('../../util/Constants');
5 +
6 +class GuildUpdateAction extends Action {
7 + handle(data) {
8 + const client = this.client;
9 +
10 + const guild = client.guilds.cache.get(data.id);
11 + if (guild) {
12 + const old = guild._update(data);
13 + /**
14 + * Emitted whenever a guild is updated - e.g. name change.
15 + * @event Client#guildUpdate
16 + * @param {Guild} oldGuild The guild before the update
17 + * @param {Guild} newGuild The guild after the update
18 + */
19 + client.emit(Events.GUILD_UPDATE, old, guild);
20 + return {
21 + old,
22 + updated: guild,
23 + };
24 + }
25 +
26 + return {
27 + old: null,
28 + updated: null,
29 + };
30 + }
31 +}
32 +
33 +module.exports = GuildUpdateAction;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +const Invite = require('../../structures/Invite');
5 +const { Events } = require('../../util/Constants');
6 +
7 +class InviteCreateAction extends Action {
8 + handle(data) {
9 + const client = this.client;
10 + const channel = client.channels.cache.get(data.channel_id);
11 + const guild = client.guilds.cache.get(data.guild_id);
12 + if (!channel) return false;
13 +
14 + const inviteData = Object.assign(data, { channel, guild });
15 + const invite = new Invite(client, inviteData);
16 + /**
17 + * Emitted when an invite is created.
18 + * <info> This event only triggers if the client has `MANAGE_GUILD` permissions for the guild,
19 + * or `MANAGE_CHANNEL` permissions for the channel.</info>
20 + * @event Client#inviteCreate
21 + * @param {Invite} invite The invite that was created
22 + */
23 + client.emit(Events.INVITE_CREATE, invite);
24 + return { invite };
25 + }
26 +}
27 +
28 +module.exports = InviteCreateAction;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +const Invite = require('../../structures/Invite');
5 +const { Events } = require('../../util/Constants');
6 +
7 +class InviteDeleteAction extends Action {
8 + handle(data) {
9 + const client = this.client;
10 + const channel = client.channels.cache.get(data.channel_id);
11 + const guild = client.guilds.cache.get(data.guild_id);
12 + if (!channel) return false;
13 +
14 + const inviteData = Object.assign(data, { channel, guild });
15 + const invite = new Invite(client, inviteData);
16 +
17 + /**
18 + * Emitted when an invite is deleted.
19 + * <info> This event only triggers if the client has `MANAGE_GUILD` permissions for the guild,
20 + * or `MANAGE_CHANNEL` permissions for the channel.</info>
21 + * @event Client#inviteDelete
22 + * @param {Invite} invite The invite that was deleted
23 + */
24 + client.emit(Events.INVITE_DELETE, invite);
25 + return { invite };
26 + }
27 +}
28 +
29 +module.exports = InviteDeleteAction;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +const { Events } = require('../../util/Constants');
5 +
6 +class MessageCreateAction extends Action {
7 + handle(data) {
8 + const client = this.client;
9 + const channel = client.channels.cache.get(data.channel_id);
10 + if (channel) {
11 + const existing = channel.messages.cache.get(data.id);
12 + if (existing) return { message: existing };
13 + const message = channel.messages.add(data);
14 + const user = message.author;
15 + let member = message.member;
16 + channel.lastMessageID = data.id;
17 + if (user) {
18 + user.lastMessageID = data.id;
19 + user.lastMessageChannelID = channel.id;
20 + }
21 + if (member) {
22 + member.lastMessageID = data.id;
23 + member.lastMessageChannelID = channel.id;
24 + }
25 +
26 + /**
27 + * Emitted whenever a message is created.
28 + * @event Client#message
29 + * @param {Message} message The created message
30 + */
31 + client.emit(Events.MESSAGE_CREATE, message);
32 + return { message };
33 + }
34 +
35 + return {};
36 + }
37 +}
38 +
39 +module.exports = MessageCreateAction;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +const { Events } = require('../../util/Constants');
5 +
6 +class MessageDeleteAction extends Action {
7 + handle(data) {
8 + const client = this.client;
9 + const channel = this.getChannel(data);
10 + let message;
11 + if (channel) {
12 + message = this.getMessage(data, channel);
13 + if (message) {
14 + channel.messages.cache.delete(message.id);
15 + message.deleted = true;
16 + /**
17 + * Emitted whenever a message is deleted.
18 + * @event Client#messageDelete
19 + * @param {Message} message The deleted message
20 + */
21 + client.emit(Events.MESSAGE_DELETE, message);
22 + }
23 + }
24 +
25 + return { message };
26 + }
27 +}
28 +
29 +module.exports = MessageDeleteAction;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +const Collection = require('../../util/Collection');
5 +const { Events } = require('../../util/Constants');
6 +
7 +class MessageDeleteBulkAction extends Action {
8 + handle(data) {
9 + const client = this.client;
10 + const channel = client.channels.cache.get(data.channel_id);
11 +
12 + if (channel) {
13 + const ids = data.ids;
14 + const messages = new Collection();
15 + for (const id of ids) {
16 + const message = this.getMessage(
17 + {
18 + id,
19 + guild_id: data.guild_id,
20 + },
21 + channel,
22 + false,
23 + );
24 + if (message) {
25 + message.deleted = true;
26 + messages.set(message.id, message);
27 + channel.messages.cache.delete(id);
28 + }
29 + }
30 +
31 + /**
32 + * Emitted whenever messages are deleted in bulk.
33 + * @event Client#messageDeleteBulk
34 + * @param {Collection<Snowflake, Message>} messages The deleted messages, mapped by their ID
35 + */
36 + if (messages.size > 0) client.emit(Events.MESSAGE_BULK_DELETE, messages);
37 + return { messages };
38 + }
39 + return {};
40 + }
41 +}
42 +
43 +module.exports = MessageDeleteBulkAction;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +const { Events } = require('../../util/Constants');
5 +const { PartialTypes } = require('../../util/Constants');
6 +
7 +/*
8 +{ user_id: 'id',
9 + message_id: 'id',
10 + emoji: { name: '�', id: null },
11 + channel_id: 'id',
12 + // If originating from a guild
13 + guild_id: 'id',
14 + member: { ..., user: { ... } } }
15 +*/
16 +
17 +class MessageReactionAdd extends Action {
18 + handle(data) {
19 + if (!data.emoji) return false;
20 +
21 + const user = this.getUserFromMember(data);
22 + if (!user) return false;
23 +
24 + // Verify channel
25 + const channel = this.getChannel(data);
26 + if (!channel || channel.type === 'voice') return false;
27 +
28 + // Verify message
29 + const message = this.getMessage(data, channel);
30 + if (!message) return false;
31 +
32 + // Verify reaction
33 + if (message.partial && !this.client.options.partials.includes(PartialTypes.REACTION)) return false;
34 + const existing = message.reactions.cache.get(data.emoji.id || data.emoji.name);
35 + if (existing && existing.users.cache.has(user.id)) return { message, reaction: existing, user };
36 + const reaction = message.reactions.add({
37 + emoji: data.emoji,
38 + count: message.partial ? null : 0,
39 + me: user.id === this.client.user.id,
40 + });
41 + if (!reaction) return false;
42 + reaction._add(user);
43 + /**
44 + * Emitted whenever a reaction is added to a cached message.
45 + * @event Client#messageReactionAdd
46 + * @param {MessageReaction} messageReaction The reaction object
47 + * @param {User} user The user that applied the guild or reaction emoji
48 + */
49 + this.client.emit(Events.MESSAGE_REACTION_ADD, reaction, user);
50 +
51 + return { message, reaction, user };
52 + }
53 +}
54 +
55 +module.exports = MessageReactionAdd;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +const { Events } = require('../../util/Constants');
5 +
6 +/*
7 +{ user_id: 'id',
8 + message_id: 'id',
9 + emoji: { name: '�', id: null },
10 + channel_id: 'id',
11 + guild_id: 'id' }
12 +*/
13 +
14 +class MessageReactionRemove extends Action {
15 + handle(data) {
16 + if (!data.emoji) return false;
17 +
18 + const user = this.getUser(data);
19 + if (!user) return false;
20 +
21 + // Verify channel
22 + const channel = this.getChannel(data);
23 + if (!channel || channel.type === 'voice') return false;
24 +
25 + // Verify message
26 + const message = this.getMessage(data, channel);
27 + if (!message) return false;
28 +
29 + // Verify reaction
30 + const reaction = this.getReaction(data, message, user);
31 + if (!reaction) return false;
32 + reaction._remove(user);
33 + /**
34 + * Emitted whenever a reaction is removed from a cached message.
35 + * @event Client#messageReactionRemove
36 + * @param {MessageReaction} messageReaction The reaction object
37 + * @param {User} user The user whose emoji or reaction emoji was removed
38 + */
39 + this.client.emit(Events.MESSAGE_REACTION_REMOVE, reaction, user);
40 +
41 + return { message, reaction, user };
42 + }
43 +}
44 +
45 +module.exports = MessageReactionRemove;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +const { Events } = require('../../util/Constants');
5 +
6 +class MessageReactionRemoveAll extends Action {
7 + handle(data) {
8 + // Verify channel
9 + const channel = this.getChannel(data);
10 + if (!channel || channel.type === 'voice') return false;
11 +
12 + // Verify message
13 + const message = this.getMessage(data, channel);
14 + if (!message) return false;
15 +
16 + message.reactions.cache.clear();
17 + this.client.emit(Events.MESSAGE_REACTION_REMOVE_ALL, message);
18 +
19 + return { message };
20 + }
21 +}
22 +
23 +/**
24 + * Emitted whenever all reactions are removed from a cached message.
25 + * @event Client#messageReactionRemoveAll
26 + * @param {Message} message The message the reactions were removed from
27 + */
28 +
29 +module.exports = MessageReactionRemoveAll;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +const { Events } = require('../../util/Constants');
5 +
6 +class MessageReactionRemoveEmoji extends Action {
7 + handle(data) {
8 + const channel = this.getChannel(data);
9 + if (!channel || channel.type === 'voice') return false;
10 +
11 + const message = this.getMessage(data, channel);
12 + if (!message) return false;
13 +
14 + const reaction = this.getReaction(data, message);
15 + if (!reaction) return false;
16 + if (!message.partial) message.reactions.cache.delete(reaction.emoji.id || reaction.emoji.name);
17 +
18 + /**
19 + * Emitted when a bot removes an emoji reaction from a cached message.
20 + * @event Client#messageReactionRemoveEmoji
21 + * @param {MessageReaction} reaction The reaction that was removed
22 + */
23 + this.client.emit(Events.MESSAGE_REACTION_REMOVE_EMOJI, reaction);
24 + return { reaction };
25 + }
26 +}
27 +
28 +module.exports = MessageReactionRemoveEmoji;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +
5 +class MessageUpdateAction extends Action {
6 + handle(data) {
7 + const channel = this.getChannel(data);
8 + if (channel) {
9 + const { id, channel_id, guild_id, author, timestamp, type } = data;
10 + const message = this.getMessage({ id, channel_id, guild_id, author, timestamp, type }, channel);
11 + if (message) {
12 + const old = message.patch(data);
13 + return {
14 + old,
15 + updated: message,
16 + };
17 + }
18 + }
19 +
20 + return {};
21 + }
22 +}
23 +
24 +module.exports = MessageUpdateAction;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +const { Events } = require('../../util/Constants');
5 +
6 +class PresenceUpdateAction extends Action {
7 + handle(data) {
8 + let user = this.client.users.cache.get(data.user.id);
9 + if (!user && data.user.username) user = this.client.users.add(data.user);
10 + if (!user) return;
11 +
12 + if (data.user && data.user.username) {
13 + if (!user.equals(data.user)) this.client.actions.UserUpdate.handle(data.user);
14 + }
15 +
16 + const guild = this.client.guilds.cache.get(data.guild_id);
17 + if (!guild) return;
18 +
19 + let oldPresence = guild.presences.cache.get(user.id);
20 + if (oldPresence) oldPresence = oldPresence._clone();
21 + let member = guild.members.cache.get(user.id);
22 + if (!member && data.status !== 'offline') {
23 + member = guild.members.add({
24 + user,
25 + roles: data.roles,
26 + deaf: false,
27 + mute: false,
28 + });
29 + this.client.emit(Events.GUILD_MEMBER_AVAILABLE, member);
30 + }
31 + guild.presences.add(Object.assign(data, { guild }));
32 + if (member && this.client.listenerCount(Events.PRESENCE_UPDATE)) {
33 + /**
34 + * Emitted whenever a guild member's presence (e.g. status, activity) is changed.
35 + * @event Client#presenceUpdate
36 + * @param {?Presence} oldPresence The presence before the update, if one at all
37 + * @param {Presence} newPresence The presence after the update
38 + */
39 + this.client.emit(Events.PRESENCE_UPDATE, oldPresence, member.presence);
40 + }
41 + }
42 +}
43 +
44 +module.exports = PresenceUpdateAction;
1 +'use strict';
2 +
3 +const Action = require('./Action');
4 +const { Events } = require('../../util/Constants');
5 +const textBasedChannelTypes = ['dm', 'text', 'news'];
6 +
7 +class TypingStart extends Action {
8 + handle(data) {
9 + const channel = this.getChannel(data);
10 + if (!channel) {
11 + return;
12 + }
13 + if (!textBasedChannelTypes.includes(channel.type)) {
14 + this.client.emit(Events.WARN, `Discord sent a typing packet to a ${channel.type} channel ${channel.id}`);
15 + return;
16 + }
17 +
18 + const user = this.getUserFromMember(data);
19 + const timestamp = new Date(data.timestamp * 1000);
20 +
21 + if (channel && user) {
22 + if (channel._typing.has(user.id)) {
23 + const typing = channel._typing.get(user.id);
24 +
25 + typing.lastTimestamp = timestamp;
26 + typing.elapsedTime = Date.now() - typing.since;
27 + this.client.clearTimeout(typing.timeout);
28 + typing.timeout = this.tooLate(channel, user);
29 + } else {
30 + const since = new Date();
31 + const lastTimestamp = new Date();
32 + channel._typing.set(user.id, {
33 + user,
34 + since,
35 + lastTimestamp,
36 + elapsedTime: Date.now() - since,
37 + timeout: this.tooLate(channel, user),
38 + });
39 +
40 + /**
41 + * Emitted whenever a user starts typing in a channel.
42 + * @event Client#typingStart
43 + * @param {Channel} channel The channel the user started typing in
44 + * @param {User} user The user that started typing
45 + */
46 + this.client.emit(Events.TYPING_START, channel, user);
47 + }
48 + }
49 + }
50 +
51 + tooLate(channel, user) {
52 + return channel.client.setTimeout(() => {
53 + channel._typing.delete(user.id);
54 + }, 10000);
55 + }
56 +}
57 +
58 +module.exports = TypingStart;
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.